diff --git a/.gitignore b/.gitignore
index 42e80e9e98..9d941743c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,3 +61,4 @@ stream_list.*
*.i90
src/core_*/inc
+/build-cmake-colm-debug
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e7e010394d..c934cde3e9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,6 +22,7 @@ option(MPAS_PROFILE "Enable GPTL profiling" OFF)
option(MPAS_OPENMP "Enable OpenMP" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(MPAS_USE_PIO "Build with PIO I/O library" OFF)
+option(MPAS_COLM2024 "Build atmosphere core with embedded CoLM2024 land-surface physics" OFF)
message(STATUS "[OPTION] MPAS_CORES: ${MPAS_CORES}")
message(STATUS "[OPTION] MPAS_DOUBLE_PRECISION: ${MPAS_DOUBLE_PRECISION}")
@@ -29,6 +30,7 @@ message(STATUS "[OPTION] MPAS_PROFILE: ${MPAS_PROFILE}")
message(STATUS "[OPTION] MPAS_OPENMP: ${MPAS_OPENMP}")
message(STATUS "[OPTION] BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}")
message(STATUS "[OPTION] MPAS_USE_PIO: ${MPAS_USE_PIO}")
+message(STATUS "[OPTION] MPAS_COLM2024: ${MPAS_COLM2024}")
# Build product output locations
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
@@ -68,9 +70,14 @@ endif()
find_package(MPI REQUIRED COMPONENTS Fortran)
find_package(PnetCDF REQUIRED COMPONENTS Fortran)
+if(MPAS_USE_PIO OR MPAS_COLM2024)
+ find_package(NetCDF REQUIRED COMPONENTS Fortran C)
+endif()
+if(MPAS_COLM2024)
+ find_package(LAPACK REQUIRED)
+endif()
if(MPAS_USE_PIO)
find_package(PIO REQUIRED COMPONENTS Fortran C)
- find_package(NetCDF REQUIRED COMPONENTS Fortran C)
endif()
if(MPAS_PROFILE)
find_package(GPTL REQUIRED)
diff --git a/Makefile b/Makefile
index 07ba5f9556..3b9f5277a5 100644
--- a/Makefile
+++ b/Makefile
@@ -1029,6 +1029,13 @@ endif # END OF GIT DESCRIBE VERSION
####################################################
# Section for adding external libraries and includes
####################################################
+ifeq "$(COLM2024)" "true"
+COLM2024_DIR ?= $(PWD)/src/core_atmosphere/physics/physics_colm2024
+override CPPFLAGS += -DMPAS_COLM2024
+COLM2024_MESSAGE = "MPAS was built with CoLM2024 from $(COLM2024_DIR)."
+else
+COLM2024_MESSAGE = "MPAS was not built with CoLM2024."
+endif
ifdef MPAS_EXTERNAL_LIBS
override LIBS += $(MPAS_EXTERNAL_LIBS)
endif
@@ -1573,6 +1580,7 @@ mpas_main: $(MAIN_DEPS)
@echo $(OPENMP_OFFLOAD_MESSAGE)
@echo $(OPENACC_MESSAGE)
@echo $(MUSICA_MESSAGE)
+ @echo $(COLM2024_MESSAGE)
@echo $(SCOTCH_MESSAGE)
@echo $(SHAREDLIB_MESSAGE)
ifeq "$(AUTOCLEAN)" "true"
@@ -1648,4 +1656,3 @@ errmsg:
ifdef CORE
exit 1
endif
-
diff --git a/cmake/Functions/MPAS_Functions.cmake b/cmake/Functions/MPAS_Functions.cmake
index 15d9f63fc1..1a349d13fc 100644
--- a/cmake/Functions/MPAS_Functions.cmake
+++ b/cmake/Functions/MPAS_Functions.cmake
@@ -214,25 +214,26 @@ function(mpas_core_target)
if (${DO_PHYSICS})
set(CPP_EXTRA_FLAGS ${CPP_EXTRA_FLAGS} -DDO_PHYSICS)
endif()
+ set(REGISTRY_PROCESSED_XML ${CMAKE_CURRENT_BINARY_DIR}/Registry_processed.xml)
-add_custom_command(OUTPUT Registry_processed.xml
- COMMAND ${CPP_EXECUTABLE} -E -P ${CPP_EXTRA_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/Registry.xml > Registry_processed.xml
+add_custom_command(OUTPUT ${REGISTRY_PROCESSED_XML}
+ COMMAND ${CPP_EXECUTABLE} -E -P ${CPP_EXTRA_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/Registry.xml > ${REGISTRY_PROCESSED_XML}
COMMENT "CORE ${ARG_CORE}: Pre-Process Registry"
- DEPENDS Registry.xml)
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Registry.xml)
add_custom_command(OUTPUT ${ARG_INCLUDES}
- COMMAND mpas_parse_${ARG_CORE} Registry_processed.xml ${CPP_EXTRA_FLAGS}
+ COMMAND mpas_parse_${ARG_CORE} ${REGISTRY_PROCESSED_XML} ${CPP_EXTRA_FLAGS}
COMMENT "CORE ${ARG_CORE}: Parse Registry"
- DEPENDS mpas_parse_${ARG_CORE} Registry_processed.xml)
+ DEPENDS mpas_parse_${ARG_CORE} ${REGISTRY_PROCESSED_XML})
add_custom_command(OUTPUT namelist.${ARG_CORE}
WORKING_DIRECTORY ${CORE_DATADIR}
- COMMAND mpas_namelist_gen ${CMAKE_CURRENT_BINARY_DIR}/Registry_processed.xml namelist.${ARG_CORE} in_defaults=true
+ COMMAND mpas_namelist_gen ${REGISTRY_PROCESSED_XML} namelist.${ARG_CORE} in_defaults=true
COMMENT "CORE ${ARG_CORE}: Generate Namelist"
- DEPENDS mpas_namelist_gen Registry_processed.xml)
+ DEPENDS mpas_namelist_gen ${REGISTRY_PROCESSED_XML})
add_custom_command(OUTPUT streams.${ARG_CORE}
WORKING_DIRECTORY ${CORE_DATADIR}
- COMMAND mpas_streams_gen ${CMAKE_CURRENT_BINARY_DIR}/Registry_processed.xml streams.${ARG_CORE} stream_list.${ARG_CORE}. listed
+ COMMAND mpas_streams_gen ${REGISTRY_PROCESSED_XML} streams.${ARG_CORE} stream_list.${ARG_CORE}. listed
COMMENT "CORE ${ARG_CORE}: Generate Streams"
- DEPENDS mpas_streams_gen Registry_processed.xml)
+ DEPENDS mpas_streams_gen ${REGISTRY_PROCESSED_XML})
add_custom_target(gen_${ARG_CORE} DEPENDS ${ARG_INCLUDES} namelist.${ARG_CORE} streams.${ARG_CORE})
add_dependencies(${ARG_TARGET} gen_${ARG_CORE})
diff --git a/src/core_atmosphere/CMakeLists.txt b/src/core_atmosphere/CMakeLists.txt
index 7fdbe66992..9780e83714 100644
--- a/src/core_atmosphere/CMakeLists.txt
+++ b/src/core_atmosphere/CMakeLists.txt
@@ -35,6 +35,7 @@ set(ATMOSPHERE_CORE_PHYSICS_SOURCES
mpas_atmphys_driver_sfclayer.F
mpas_atmphys_init.F
mpas_atmphys_lsm_shared.F
+ mpas_atmphys_driver_lsm_colm2024.F
mpas_atmphys_packages.F
mpas_atmphys_todynamics.F
mpas_atmphys_vars.F
@@ -298,6 +299,108 @@ set(ATMOSPHERE_CORE_PHYSICS_NOAMP_SRC_SOURCES
)
list(TRANSFORM ATMOSPHERE_CORE_PHYSICS_NOAMP_SRC_SOURCES PREPEND physics/physics_noahmp/src/)
+if(MPAS_COLM2024)
+ set(COLM2024_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/physics/physics_colm2024)
+ set(COLM2024_SOURCE_SEARCH_DIRS
+ share
+ main
+ main/HYDRO
+ main/BGC
+ main/URBAN
+ main/DA
+ main/ParaOpt
+ drivers/mpas
+ )
+ foreach(_colm2024_dir IN LISTS COLM2024_SOURCE_SEARCH_DIRS)
+ file(GLOB _colm2024_dir_sources CONFIGURE_DEPENDS
+ ${COLM2024_SOURCE_ROOT}/${_colm2024_dir}/*.F90)
+ list(APPEND COLM2024_SOURCE_CANDIDATES ${_colm2024_dir_sources})
+ endforeach()
+ list(REMOVE_DUPLICATES COLM2024_SOURCE_CANDIDATES)
+ list(SORT COLM2024_SOURCE_CANDIDATES)
+ foreach(_colm2024_src IN LISTS COLM2024_SOURCE_CANDIDATES)
+ file(RELATIVE_PATH _colm2024_src_rel ${CMAKE_CURRENT_SOURCE_DIR} ${_colm2024_src})
+ execute_process(
+ COMMAND ${CPP_EXECUTABLE} -traditional-cpp -P -I${COLM2024_SOURCE_ROOT}/include ${_colm2024_src}
+ OUTPUT_VARIABLE _colm2024_preprocessed_src
+ ERROR_VARIABLE _colm2024_preprocess_error
+ RESULT_VARIABLE _colm2024_preprocess_result
+ )
+ if(NOT _colm2024_preprocess_result EQUAL 0)
+ message(FATAL_ERROR "Could not preprocess CoLM2024 source ${_colm2024_src}: ${_colm2024_preprocess_error}")
+ endif()
+ string(TOUPPER "${_colm2024_preprocessed_src}" _colm2024_preprocessed_src_upper)
+ if(NOT "${_colm2024_preprocessed_src_upper}" MATCHES "(^|\n)[ \t]*(MODULE|SUBROUTINE|FUNCTION|PROGRAM)[ \t]+[A-Z0-9_]+")
+ list(APPEND ATMOSPHERE_CORE_PHYSICS_COLM2024_SKIPPED_EMPTY_SOURCES ${_colm2024_src_rel})
+ continue()
+ endif()
+ list(APPEND ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES ${_colm2024_src_rel})
+ endforeach()
+ list(LENGTH ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES _colm2024_source_count)
+ if(_colm2024_source_count EQUAL 0)
+ message(FATAL_ERROR "CoLM2024 CMake source list is empty")
+ endif()
+ list(LENGTH ATMOSPHERE_CORE_PHYSICS_COLM2024_SKIPPED_EMPTY_SOURCES _colm2024_skipped_empty_count)
+ message(STATUS "CoLM2024 embedded CMake sources: ${_colm2024_source_count}")
+ message(STATUS "CoLM2024 embedded CMake skipped empty sources: ${_colm2024_skipped_empty_count}")
+
+ function(_colm2024_object_path out source)
+ set(${out} "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/core_atmosphere.dir/${source}.o" PARENT_SCOPE)
+ endfunction()
+
+ function(_colm2024_source_depends source)
+ if(NOT "${source}" IN_LIST ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES)
+ return()
+ endif()
+ set(_colm2024_deps)
+ foreach(_colm2024_dep IN LISTS ARGN)
+ if(NOT "${_colm2024_dep}" IN_LIST ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES)
+ continue()
+ endif()
+ _colm2024_object_path(_colm2024_dep_obj ${_colm2024_dep})
+ list(APPEND _colm2024_deps ${_colm2024_dep_obj})
+ endforeach()
+ if(_colm2024_deps)
+ set_property(SOURCE ${source} APPEND PROPERTY OBJECT_DEPENDS "${_colm2024_deps}")
+ endif()
+ endfunction()
+
+ _colm2024_source_depends(
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeTimeVars.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90)
+ _colm2024_source_depends(
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeHist.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Vector_ReadWrite.F90)
+ _colm2024_source_depends(
+ physics/physics_colm2024/main/MOD_HistGridded.F90
+ physics/physics_colm2024/main/MOD_HistWriteBack.F90)
+ _colm2024_source_depends(
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeFlow.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeTimeVars.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeHist.F90)
+ _colm2024_source_depends(
+ physics/physics_colm2024/main/MOD_Vars_TimeVariables.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeTimeVars.F90)
+ _colm2024_source_depends(
+ physics/physics_colm2024/main/MOD_Hist.F90
+ physics/physics_colm2024/main/MOD_Vars_TimeVariables.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeHist.F90)
+ _colm2024_source_depends(
+ physics/physics_colm2024/drivers/mpas/MOD_CoLM_MPAS_Interface.F90
+ physics/physics_colm2024/main/MOD_Vars_TimeVariables.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90
+ physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeFlow.F90)
+ _colm2024_source_depends(
+ physics/mpas_atmphys_driver_lsm_colm2024.F
+ physics/physics_colm2024/drivers/mpas/MOD_CoLM_MPAS_Interface.F90)
+endif()
+
# diagnostics/
set(ATMOSPHERE_CORE_DIAGNOSTIC_SOURCES
mpas_atm_diagnostic_template.F
@@ -351,6 +454,7 @@ add_library(core_atmosphere ${ATMOSPHERE_CORE_SOURCES}
${ATMOSPHERE_CORE_PHYSICS_NOAMP_UTILITY_SOURCES}
${ATMOSPHERE_CORE_PHYSICS_NOAMP_MPAS_DRIVER_SOURCES}
${ATMOSPHERE_CORE_PHYSICS_NOAMP_SRC_SOURCES}
+ ${ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES}
${ATMOSPHERE_CORE_PHYSICS_SOURCES}
${ATMOSPHERE_CORE_PHYSICS_MMM_SOURCES}
${ATMOSPHERE_CORE_PHYSICS_WRF_SOURCES}
@@ -365,7 +469,35 @@ set(CORE_ATMOSPHERE_COMPILE_DEFINITIONS
if (${DO_PHYSICS})
list(APPEND CORE_ATMOSPHERE_COMPILE_DEFINITIONS DO_PHYSICS)
endif ()
+if (MPAS_COLM2024)
+ list(APPEND CORE_ATMOSPHERE_COMPILE_DEFINITIONS MPAS_COLM2024)
+endif ()
target_compile_definitions(core_atmosphere PRIVATE ${CORE_ATMOSPHERE_COMPILE_DEFINITIONS})
+if (MPAS_COLM2024)
+ target_include_directories(core_atmosphere PRIVATE ${COLM2024_SOURCE_ROOT}/include)
+ target_link_libraries(core_atmosphere PUBLIC NetCDF::NetCDF_Fortran NetCDF::NetCDF_C)
+ if(TARGET LAPACK::LAPACK)
+ target_link_libraries(core_atmosphere PUBLIC LAPACK::LAPACK)
+ else()
+ target_link_libraries(core_atmosphere PUBLIC ${LAPACK_LIBRARIES})
+ endif()
+ set_property(SOURCE ${ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES}
+ PROPERTY Fortran_PREPROCESS ON)
+ if(CMAKE_Fortran_COMPILER_ID MATCHES GNU)
+ set(_colm2024_compile_options -fdefault-real-8 -ffree-line-length-none)
+ if(CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 10)
+ list(APPEND _colm2024_compile_options -fallow-argument-mismatch)
+ endif()
+ elseif(CMAKE_Fortran_COMPILER_ID MATCHES Intel)
+ set(_colm2024_compile_options -real-size 64)
+ elseif(CMAKE_Fortran_COMPILER_ID MATCHES NVHPC)
+ set(_colm2024_compile_options -r8)
+ endif()
+ if(_colm2024_compile_options)
+ set_property(SOURCE ${ATMOSPHERE_CORE_PHYSICS_COLM2024_SOURCES}
+ APPEND PROPERTY COMPILE_OPTIONS ${_colm2024_compile_options})
+ endif()
+endif ()
set_MPAS_DEBUG_flag(core_atmosphere)
mpas_core_target(CORE atmosphere TARGET core_atmosphere INCLUDES ${ATMOSPHERE_CORE_INCLUDES})
diff --git a/src/core_atmosphere/Makefile b/src/core_atmosphere/Makefile
index bb2bd2c2e7..332823e86c 100644
--- a/src/core_atmosphere/Makefile
+++ b/src/core_atmosphere/Makefile
@@ -48,6 +48,7 @@ post_build:
physcore: mpas_atm_dimensions.o
( cd physics; $(MAKE) all )
+ $(RM) -r libphys
( mkdir libphys; cd libphys; ar -x ../physics/libphys.a )
( cd ../..; ln -sf ./src/core_atmosphere/physics/physics_wrf/files/*TBL .)
( cd ../..; ln -sf ./src/core_atmosphere/physics/physics_wrf/files/*DATA* .)
@@ -55,6 +56,7 @@ physcore: mpas_atm_dimensions.o
chemcore:
( cd chemistry; $(MAKE) all CHEMISTRY="$(CHEMISTRY)" )
+ $(RM) -r libchem
( mkdir libchem; cd libchem; ar -x ../chemistry/libchem.a )
dycore: mpas_atm_dimensions.o $(PHYSCORE) $(CHEMCORE)
@@ -67,6 +69,7 @@ utilities: $(PHYSCORE)
( cd utils; $(MAKE) all PHYSICS="$(PHYSICS)" )
atmcore: $(PHYSCORE) dycore diagcore $(OBJS)
+ $(RM) libdycore.a
ar -ru libdycore.a $(OBJS) dynamics/*.o $(PHYS_OBJS) $(CHEM_OBJS) diagnostics/*.o
mpas_atm_core_interface.o: mpas_atm_core.o
diff --git a/src/core_atmosphere/Registry.xml b/src/core_atmosphere/Registry.xml
index 425e0349d1..8b0ff5241e 100644
--- a/src/core_atmosphere/Registry.xml
+++ b/src/core_atmosphere/Registry.xml
@@ -474,6 +474,7 @@
+
@@ -496,9 +497,9 @@
-
@@ -599,9 +600,9 @@
-
@@ -647,11 +648,11 @@
#endif
-
@@ -924,9 +925,9 @@
#endif
-
@@ -997,6 +998,14 @@
+
+
+
+
+
+
+
+
@@ -1028,9 +1037,9 @@
#endif
-
@@ -1157,9 +1166,9 @@
#endif
-
@@ -1170,9 +1179,9 @@
#endif
-
@@ -1694,7 +1703,7 @@
description="Moist potential temperature: theta*(1+q_v*R_v/R_d)"/>
-
+
#ifndef MPAS_CAM_DYCORE
@@ -2024,7 +2033,7 @@
-
+
@@ -2060,7 +2069,7 @@
description="Tendency of surface pressure"/>
-
+
#ifndef MPAS_CAM_DYCORE
@@ -2093,7 +2102,7 @@
description="Tendency of cloud ice number concentration multiplied by dry air density divided by d(zeta)/dz"
packages="bl_mynn_in;mp_thompson_in;mp_thompson_aers_in"/>
-
@@ -2109,7 +2118,7 @@
description="Tendency of water-friendly aerosol number concentration multiplied by dry air density divided by d(zeta)/dz"
packages="mp_thompson_aers_in"/>
-
@@ -2252,7 +2261,7 @@
possible_values="Positive integers"/>
-
+
+ possible_values="`suite',`sf_noah',`sf_noahmp`, `sf_colm2024`, `off'"/>
+
+
+
+
@@ -3237,6 +3253,18 @@
+
+
+
+
+
+
+
+
@@ -3543,7 +3571,7 @@
-
+
#ifdef DO_PHYSICS
@@ -3970,7 +3998,7 @@
#endif
-
+
diff --git a/src/core_atmosphere/mpas_atm_core.F b/src/core_atmosphere/mpas_atm_core.F
index eef1951e36..792d9f561d 100644
--- a/src/core_atmosphere/mpas_atm_core.F
+++ b/src/core_atmosphere/mpas_atm_core.F
@@ -591,7 +591,7 @@ subroutine atm_mpas_init_block(dminfo, stream_manager, block, mesh, dt)
call physics_run_init(block % configs, mesh, state, clock, stream_manager)
!initialization of all physics:
- call physics_init(dminfo, stream_manager, clock, block % configs, mesh, diag, tend, tend_physics, state, 1, &
+ call physics_init(dminfo, stream_manager, clock, block, block % configs, mesh, diag, tend, tend_physics, state, 1, &
diag_physics, diag_physics_noahmp, ngw_input, atm_input, sfc_input, output_noahmp)
endif
#endif
diff --git a/src/core_atmosphere/physics/Makefile b/src/core_atmosphere/physics/Makefile
index 2b7422ddec..0422dc4da0 100644
--- a/src/core_atmosphere/physics/Makefile
+++ b/src/core_atmosphere/physics/Makefile
@@ -4,9 +4,42 @@ ifeq ($(CORE),atmosphere)
COREDEF = -Dmpas
endif
+ifneq (,$(findstring -DMPAS_COLM2024,$(CPPFLAGS)))
+COLM2024_ENABLED = true
+COLM2024_CORE = core_physics_colm2024_embedded
+COLM2024_BUILD_DIR = physics_colm2024/.mpas_bld
+COLM2024_HEADER = physics_colm2024/include/define.h
+COLM2024_STAMP = $(COLM2024_BUILD_DIR)/.built
+COLM2024_MOD_CMD ?= -J
+NF_CONFIG ?= nf-config
+COLM2024_NETCDF_INC ?= $(shell $(NF_CONFIG) --includedir 2>/dev/null || nc-config --includedir 2>/dev/null)
+COLM2024_INCLUDES = -I./physics_colm2024/include -I./$(COLM2024_BUILD_DIR)
+ifneq ($(strip $(COLM2024_NETCDF_INC)),)
+COLM2024_INCLUDES += -I$(COLM2024_NETCDF_INC)
+endif
+ifneq ($(strip $(PNETCDF)),)
+COLM2024_INCLUDES += -I$(PNETCDF)/include
+endif
+ifneq ($(strip $(PNETCDF_INC)),)
+COLM2024_INCLUDES += -I$(PNETCDF_INC)
+endif
+COLM2024_FOPTS ?= $(CPPFLAGS) $(COREDEF) $(FFLAGS) -fdefault-real-8 -ffree-form -cpp -ffree-line-length-0 -fallow-argument-mismatch
+COLM2024_SOURCE_DIRS = \
+ physics_colm2024/share \
+ physics_colm2024/main \
+ physics_colm2024/main/HYDRO \
+ physics_colm2024/main/BGC \
+ physics_colm2024/main/URBAN \
+ physics_colm2024/main/DA \
+ physics_colm2024/main/ParaOpt \
+ physics_colm2024/drivers/mpas
+COLM2024_SOURCES = $(foreach dir,$(COLM2024_SOURCE_DIRS),$(wildcard $(dir)/*.F90))
+endif
+
all:
./../tools/manage_externals/checkout_externals --externals ./../Externals.cfg
- $(MAKE) lookup_tables core_physics_init core_physics_mmm core_UGWP core_physics_wrf core_physics_noahmp core_physics
+ $(RM) libphys.a
+ $(MAKE) lookup_tables $(COLM2024_CORE) core_physics_init core_physics_mmm core_UGWP core_physics_wrf core_physics_noahmp core_physics
dummy:
echo "****** compiling physics ******"
@@ -27,6 +60,7 @@ OBJS = \
mpas_atmphys_driver_gwdo.o \
mpas_atmphys_driver_lsm.o \
mpas_atmphys_driver_lsm_noahmp.o \
+ mpas_atmphys_driver_lsm_colm2024.o \
mpas_atmphys_driver_microphysics.o \
mpas_atmphys_driver_oml.o \
mpas_atmphys_driver_pbl.o \
@@ -71,9 +105,245 @@ core_physics_noahmp:
(cd physics_noahmp/src; $(MAKE) all COREDEF="$(COREDEF)")
(cd physics_noahmp/drivers/mpas; $(MAKE) all COREDEF="$(COREDEF)")
+ifeq "$(COLM2024_ENABLED)" "true"
+COLM2024_OBJS_SHARED_NAMES = \
+ MOD_Precision.o \
+ MOD_SPMD_Task.o \
+ MOD_Namelist.o \
+ MOD_Vars_Global.o \
+ MOD_Const_Physical.o \
+ MOD_Const_LC.o \
+ MOD_Utils.o \
+ MOD_IncompleteGamma.o \
+ MOD_UserDefFun.o \
+ MOD_TimeManager.o \
+ MOD_Const_PFT.o \
+ MOD_NetCDFSerial.o \
+ MOD_Block.o \
+ MOD_Grid.o \
+ MOD_Pixel.o \
+ MOD_DataType.o \
+ MOD_NetCDFPoint.o \
+ MOD_NetCDFBlock.o \
+ MOD_CatchmentDataReadin.o \
+ MOD_5x5DataReadin.o \
+ MOD_Mesh.o \
+ MOD_Pixelset.o \
+ MOD_NetCDFVector.o \
+ MOD_RangeCheck.o \
+ MOD_SpatialMapping.o \
+ MOD_ComputePushData.o \
+ MOD_AggregationRequestData.o \
+ MOD_PixelsetShared.o \
+ MOD_LandElm.o \
+ MOD_LandHRU.o \
+ MOD_LandPatch.o \
+ MOD_Land2mWMO.o \
+ MOD_LandCrop.o \
+ MOD_LandPFT.o \
+ MOD_LandUrban.o \
+ MOD_Urban_Const_LCZ.o \
+ MOD_SingleSrfdata.o \
+ MOD_SrfdataRestart.o \
+ MOD_ElmVector.o \
+ MOD_HRUVector.o \
+ MOD_MeshFilter.o
+
+COLM2024_OBJS_BASIC_NAMES = \
+ MOD_Vector_ReadWrite.o \
+ MOD_dataSpec_PDB.o \
+ MOD_tav_abs.o \
+ MOD_prospect_DB.o \
+ MOD_Catch_BasinNetwork.o \
+ MOD_Catch_Vars_TimeVariables.o \
+ MOD_Catch_Vars_1DFluxes.o \
+ MOD_Grid_RiverLakeNetwork.o \
+ MOD_Grid_Reservoir.o \
+ MOD_Grid_RiverLakeTimeVars.o \
+ MOD_BGC_Vars_1DFluxes.o \
+ MOD_BGC_Vars_1DPFTFluxes.o \
+ MOD_BGC_Vars_PFTimeVariables.o \
+ MOD_BGC_Vars_TimeInvariants.o \
+ MOD_BGC_Vars_TimeVariables.o \
+ MOD_Urban_Vars_1DFluxes.o \
+ MOD_Urban_Vars_TimeVariables.o \
+ MOD_Urban_Vars_TimeInvariants.o \
+ MOD_DA_Vars_1DFluxes.o \
+ MOD_Vars_TimeInvariants.o \
+ MOD_DA_Vars_TimeVariables.o \
+ MOD_Vars_TimeVariables.o \
+ MOD_Vars_1DPFTFluxes.o \
+ MOD_Vars_1DFluxes.o \
+ MOD_Vars_1DForcing.o \
+ MOD_Hydro_SoilFunction.o \
+ MOD_Hydro_SoilWater.o \
+ MOD_Eroot.o \
+ MOD_Qsadv.o \
+ MOD_LAIEmpirical.o \
+ MOD_LAIReadin.o \
+ MOD_CropReadin.o \
+ MOD_NitrifData.o \
+ MOD_NdepData.o \
+ MOD_FireData.o \
+ MOD_OrbCoszen.o \
+ MOD_OrbCosazi.o \
+ MOD_HighRes_Parameters.o \
+ MOD_3DCanopyRadiation.o \
+ MOD_Aerosol.o \
+ MOD_SnowSnicar.o \
+ MOD_Albedo.o \
+ MOD_SnowSnicar_HiRes.o \
+ MOD_Albedo_HiRes.o \
+ MOD_SnowFraction.o \
+ MOD_Urban_LAIReadin.o \
+ MOD_Urban_Shortwave.o \
+ MOD_Urban_Albedo.o \
+ MOD_MonthlyinSituCO2MaunaLoa.o \
+ MOD_BGC_CNSummary.o \
+ MOD_ElementNeighbour.o \
+ MOD_Catch_HillslopeNetwork.o \
+ MOD_Catch_RiverLakeNetwork.o \
+ MOD_Catch_Reservoir.o \
+ MOD_VicParaReadin.o
+
+COLM2024_OBJS_MAIN_NAMES = \
+ MOD_Catch_HillslopeFlow.o \
+ MOD_Catch_SubsurfaceFlow.o \
+ MOD_Catch_RiverLakeFlow.o \
+ MOD_Catch_Hist.o \
+ MOD_Catch_WriteParameters.o \
+ MOD_BGC_CNCStateUpdate1.o \
+ MOD_BGC_CNCStateUpdate2.o \
+ MOD_BGC_CNCStateUpdate3.o \
+ MOD_BGC_CNNStateUpdate1.o \
+ MOD_BGC_CNNStateUpdate2.o \
+ MOD_BGC_CNNStateUpdate3.o \
+ MOD_BGC_Soil_BiogeochemNStateUpdate1.o \
+ MOD_BGC_Soil_BiogeochemNitrifDenitrif.o \
+ MOD_BGC_Soil_BiogeochemCompetition.o \
+ MOD_BGC_Soil_BiogeochemDecompCascadeBGC.o \
+ MOD_BGC_Soil_BiogeochemDecomp.o \
+ MOD_BGC_Soil_BiogeochemLittVertTransp.o \
+ MOD_BGC_Soil_BiogeochemNLeaching.o \
+ MOD_BGC_Soil_BiogeochemPotential.o \
+ MOD_BGC_Soil_BiogeochemVerticalProfile.o \
+ MOD_BGC_Veg_CNGapMortality.o \
+ MOD_BGC_Veg_CNGResp.o \
+ MOD_BGC_Veg_CNMResp.o \
+ MOD_BGC_Daylength.o \
+ MOD_BGC_Veg_CNPhenology.o \
+ MOD_BGC_Veg_NutrientCompetition.o \
+ MOD_BGC_Veg_CNVegStructUpdate.o \
+ MOD_BGC_CNAnnualUpdate.o \
+ MOD_BGC_CNZeroFluxes.o \
+ MOD_BGC_CNBalanceCheck.o \
+ MOD_BGC_CNSASU.o \
+ MOD_BGC_Veg_CNNDynamics.o \
+ MOD_BGC_Veg_CNFireBase.o \
+ MOD_BGC_Veg_CNFireLi2016.o \
+ MOD_Vars_2DForcing.o \
+ MOD_UserSpecifiedForcing.o \
+ MOD_ForcingDownscaling.o \
+ MOD_Forcing.o \
+ MOD_DA_TWS.o \
+ MOD_DA_Const.o \
+ MOD_DA_RTM.o \
+ MOD_DA_EnKF.o \
+ MOD_DA_SM.o \
+ MOD_DA_Ensemble.o \
+ MOD_DA_Main.o \
+ MOD_Opt_Baseflow.o \
+ MOD_ParameterOptimization.o \
+ MOD_AssimStomataConductance.o \
+ MOD_PlantHydraulic.o \
+ MOD_FrictionVelocity.o \
+ MOD_TurbulenceLEddy.o \
+ MOD_Ozone.o \
+ MOD_CanopyLayerProfile.o \
+ MOD_LeafTemperature.o \
+ MOD_LeafTemperaturePC.o \
+ MOD_SoilThermalParameters.o \
+ MOD_Hydro_VIC_Variables.o \
+ MOD_Hydro_VIC.o \
+ MOD_Runoff.o \
+ MOD_SoilSnowHydrology.o \
+ MOD_SnowLayersCombineDivide.o \
+ MOD_PhaseChange.o \
+ MOD_Glacier.o \
+ MOD_Lake.o \
+ MOD_SimpleOcean.o \
+ MOD_GroundFluxes.o \
+ MOD_GroundTemperature.o \
+ MOD_LeafInterception.o \
+ MOD_NetSolar.o \
+ MOD_NetSolar_Hyper.o \
+ MOD_WetBulb.o \
+ MOD_RainSnowTemp.o \
+ MOD_SoilSurfaceResistance.o \
+ MOD_NewSnow.o \
+ MOD_Thermal.o \
+ MOD_Vars_1DAccFluxes.o \
+ MOD_Irrigation.o \
+ MOD_BGC_driver.o \
+ MOD_HistWriteBack.o \
+ MOD_HistGridded.o \
+ MOD_HistVector.o \
+ MOD_HistSingle.o \
+ MOD_Grid_RiverLakeHist.o \
+ MOD_Hist.o \
+ MOD_CheckEquilibrium.o \
+ MOD_LightningData.o \
+ MOD_Catch_LateralFlow.o \
+ MOD_Grid_RiverLakeFlow.o \
+ MOD_Urban_Longwave.o \
+ MOD_Urban_NetSolar.o \
+ MOD_Urban_Flux.o \
+ MOD_Urban_GroundFlux.o \
+ MOD_Urban_RoofFlux.o \
+ MOD_Urban_RoofTemperature.o \
+ MOD_Urban_WallTemperature.o \
+ MOD_Urban_PerviousTemperature.o \
+ MOD_Urban_ImperviousTemperature.o \
+ MOD_Urban_Hydrology.o \
+ MOD_Urban_BEM.o \
+ MOD_Urban_LUCY.o \
+ MOD_Urban_Thermal.o \
+ CoLMMAIN_Urban.o \
+ CoLMDRIVER.o \
+ MOD_CoLM_MPAS_Interface.o \
+ CoLMMAIN.o
+
+COLM2024_OBJ_NAMES = $(COLM2024_OBJS_SHARED_NAMES) $(COLM2024_OBJS_BASIC_NAMES) $(COLM2024_OBJS_MAIN_NAMES)
+COLM2024_OBJS = $(addprefix $(COLM2024_BUILD_DIR)/,$(COLM2024_OBJ_NAMES))
+
+.PHONY: core_physics_colm2024_embedded
+core_physics_colm2024_embedded: $(COLM2024_STAMP)
+
+$(COLM2024_BUILD_DIR):
+ mkdir -p $(COLM2024_BUILD_DIR)
+
+$(COLM2024_STAMP): $(COLM2024_HEADER) $(COLM2024_SOURCES) | $(COLM2024_BUILD_DIR)
+ @echo 'compiling embedded CoLM2024 physics >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>'
+ @set -e; \
+ for obj in $(COLM2024_OBJ_NAMES); do \
+ src=""; \
+ stem="$${obj%.o}"; \
+ for dir in $(COLM2024_SOURCE_DIRS); do \
+ if [ -f "$$dir/$$stem.F90" ]; then src="$$dir/$$stem.F90"; break; fi; \
+ done; \
+ if [ -z "$$src" ]; then \
+ echo "CoLM2024 source not found for $$obj"; \
+ exit 1; \
+ fi; \
+ echo " $$src"; \
+ $(FC) -c $(COLM2024_FOPTS) $(COLM2024_INCLUDES) -o "$(COLM2024_BUILD_DIR)/$$obj" "$$src" $(COLM2024_MOD_CMD)$(COLM2024_BUILD_DIR); \
+ done; \
+ touch $@
+endif
+
core_physics_init: $(OBJS_init)
-core_physics: core_physics_wrf core_physics_noahmp
+core_physics: core_physics_wrf core_physics_noahmp $(COLM2024_CORE)
($(MAKE) phys_interface COREDEF="$(COREDEF)")
ar -ru libphys.a $(OBJS_init) $(OBJS)
($(MAKE) -C ./physics_mmm -f Makefile.mpas physics_mmm_lib)
@@ -81,6 +351,9 @@ core_physics: core_physics_wrf core_physics_noahmp
($(MAKE) -C ./physics_noahmp/drivers/mpas driver_lib)
($(MAKE) -C ./physics_noahmp/src src_lib)
($(MAKE) -C ./physics_noahmp/utility utility_lib)
+ifeq "$(COLM2024_ENABLED)" "true"
+ ar -ru libphys.a $(COLM2024_OBJS)
+endif
phys_interface: $(OBJS)
@@ -99,6 +372,7 @@ mpas_atmphys_driver.o: \
mpas_atmphys_driver_gwdo.o \
mpas_atmphys_driver_lsm.o \
mpas_atmphys_driver_lsm_noahmp.o \
+ mpas_atmphys_driver_lsm_colm2024.o \
mpas_atmphys_driver_pbl.o \
mpas_atmphys_driver_radiation_lw.o \
mpas_atmphys_driver_radiation_sw.o \
@@ -175,7 +449,8 @@ mpas_atmphys_driver_sfclayer.o: \
mpas_atmphys_vars.o
mpas_atmphys_finalize.o: \
- mpas_atmphys_lsm_noahmpfinalize.o
+ mpas_atmphys_lsm_noahmpfinalize.o \
+ mpas_atmphys_driver_lsm_colm2024.o
mpas_atmphys_init.o: \
mpas_atmphys_driver_convection.o \
@@ -186,6 +461,7 @@ mpas_atmphys_init.o: \
mpas_atmphys_driver_radiation_sw.o \
mpas_atmphys_driver_sfclayer.o \
mpas_atmphys_lsm_noahmpinit.o \
+ mpas_atmphys_driver_lsm_colm2024.o \
mpas_atmphys_landuse.o \
mpas_atmphys_o3climatology.o \
mpas_atmphys_vars.o
@@ -209,6 +485,8 @@ mpas_atmphys_lsm_noahmpinit.o: \
mpas_atmphys_lsm_noahmpfinalize.o : \
mpas_atmphys_vars.o
+mpas_atmphys_driver_lsm_colm2024.o : mpas_atmphys_utilities.o $(COLM2024_STAMP)
+
mpas_atmphys_manager.o: \
mpas_atmphys_constants.o \
mpas_atmphys_o3climatology.o \
@@ -253,6 +531,7 @@ clean:
( cd physics_noahmp/drivers/mpas; $(MAKE) clean )
( cd physics_noahmp/src; $(MAKE) clean )
( cd physics_noahmp/utility; $(MAKE) clean )
+ $(RM) -r physics_colm2024/.mpas_bld
( if [ -d physics_noaa/UGWP ]; then cd physics_noaa/UGWP; $(MAKE) clean; fi )
@# Certain systems with intel compilers generate *.i files
@# This removes them during the clean process
@@ -262,7 +541,7 @@ clean:
$(RM) $@ $*.mod
ifeq "$(GEN_F90)" "true"
$(CPP) $(CPPFLAGS) $(COREDEF) $(HYDROSTATIC) $(CPPINCLUDES) -I../../framework $< > $*.f90
- $(FC) $(FFLAGS) -c $*.f90 $(FCINCLUDES) -I./physics_mmm -I./physics_wrf -I./physics_noahmp -I./physics_noahmp/utility -I./physics_noahmp/drivers/mpas -I./physics_noahmp/src -I./physics_noaa/UGWP -I.. -I../../framework $(MPAS_ESMF_INC)
+ $(FC) $(FFLAGS) -c $*.f90 $(FCINCLUDES) $(COLM2024_INCLUDES) -I./physics_mmm -I./physics_wrf -I./physics_noahmp -I./physics_noahmp/utility -I./physics_noahmp/drivers/mpas -I./physics_noahmp/src -I./physics_noaa/UGWP -I.. -I../../framework $(MPAS_ESMF_INC)
else
- $(FC) $(CPPFLAGS) $(COREDEF) $(HYDROSATIC) $(FFLAGS) -c $*.F $(CPPINCLUDES) $(FCINCLUDES) -I./physics_mmm -I./physics_wrf -I./physics_noahmp -I./physics_noahmp/utility -I./physics_noahmp/drivers/mpas -I./physics_noahmp/src -I./physics_noaa/UGWP -I.. -I../../framework $(MPAS_ESMF_INC)
+ $(FC) $(CPPFLAGS) $(COREDEF) $(HYDROSATIC) $(FFLAGS) -c $*.F $(CPPINCLUDES) $(FCINCLUDES) $(COLM2024_INCLUDES) -I./physics_mmm -I./physics_wrf -I./physics_noahmp -I./physics_noahmp/utility -I./physics_noahmp/drivers/mpas -I./physics_noahmp/src -I./physics_noaa/UGWP -I.. -I../../framework $(MPAS_ESMF_INC)
endif
diff --git a/src/core_atmosphere/physics/mpas_atmphys_control.F b/src/core_atmosphere/physics/mpas_atmphys_control.F
index b3162019e5..c83013c5ee 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_control.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_control.F
@@ -52,7 +52,7 @@ module mpas_atmphys_control
! * renamed "kain_fritsch" to "cu_kain_fritsch" and "tiedtke" to "cu_tiedtke".
! Laura D. Fowler (laura@ucar.edu) / 2016-03-22.
! * renamed "ysu" to "bl_ysu", "ysu_gwdo" to "bl_gwdo_ysu", and "monin_obukhov" to "sf_monin_obukhov".
-! Laura D. Fowler (laura@ucar.edu) / 2016-03-25.
+! Laura D. Fowler (laura@ucar.edu) / 2016-03-25.
! * added the option mp_thompson.
! Laura D. Fowler (laura@ucar.edu) / 2016-03-25.
! * added the option cu_grell_freitas.
@@ -224,7 +224,7 @@ subroutine physics_namelist_check(configs)
if(.not. (config_radt_lw_scheme .eq. 'off' .or. &
config_radt_lw_scheme .eq. 'cam_lw' .or. &
config_radt_lw_scheme .eq. 'rrtmg_lw')) then
-
+
write(mpas_err_message,'(A,A20)') 'illegal value for longwave radiation scheme: ', &
trim(config_radt_lw_scheme)
call physics_error_fatal(mpas_err_message)
@@ -235,7 +235,7 @@ subroutine physics_namelist_check(configs)
if(.not. (config_radt_sw_scheme .eq. 'off' .or. &
config_radt_sw_scheme .eq. 'cam_sw' .or. &
config_radt_sw_scheme .eq. 'rrtmg_sw')) then
-
+
write(mpas_err_message,'(A,A20)') 'illegal value for shortwave radiation _scheme: ', &
trim(config_radt_sw_scheme)
call physics_error_fatal(mpas_err_message)
@@ -272,7 +272,7 @@ subroutine physics_namelist_check(configs)
config_sfclayer_scheme .eq. 'sf_mynn' .or. &
config_sfclayer_scheme .eq. 'sf_monin_obukhov' .or. &
config_sfclayer_scheme .eq. 'sf_monin_obukhov_rev')) then
-
+
write(mpas_err_message,'(A,A20)') 'illegal value for surface layer scheme: ', &
trim(config_sfclayer_scheme)
call physics_error_fatal(mpas_err_message)
@@ -292,14 +292,15 @@ subroutine physics_namelist_check(configs)
!land-surface scheme: note that config_sfclayer_scheme must be defined for the land-surface
!scheme to be called:
if(config_lsm_scheme .ne. 'off' .and. config_sfclayer_scheme .eq. 'off') then
-
+
call physics_error_fatal('land surface scheme: ' // &
'set config_sfclayer_scheme different than off')
-
+
elseif(.not. (config_lsm_scheme .eq. 'off ' .or. &
config_lsm_scheme .eq. 'sf_noah' .or. &
- config_lsm_scheme .eq. 'sf_noahmp')) then
-
+ config_lsm_scheme .eq. 'sf_noahmp' .or. &
+ config_lsm_scheme .eq. 'sf_colm2024')) then
+
write(mpas_err_message,'(A,A20)') 'illegal value for land surface scheme: ', &
trim(config_lsm_scheme)
call physics_error_fatal(mpas_err_message)
@@ -308,7 +309,7 @@ subroutine physics_namelist_check(configs)
!checks if any physics process is called. if not, return:
moist_physics = .true.
-
+
if(config_microp_scheme .eq. 'off' .and. &
config_convection_scheme .eq. 'off' .and. &
config_lsm_scheme .eq. 'off' .and. &
@@ -379,9 +380,9 @@ subroutine physics_registry_init(mesh,configs,sfc_input)
enddo
case default
-
+
end select lsm_select
-
+
endif
!call mpas_log_write('--- enter subroutine physics_namelist_check.')
@@ -535,4 +536,3 @@ end subroutine physics_compatibility_check
!=================================================================================================================
end module mpas_atmphys_control
!=================================================================================================================
-
diff --git a/src/core_atmosphere/physics/mpas_atmphys_driver.F b/src/core_atmosphere/physics/mpas_atmphys_driver.F
index 8e31672657..1538930736 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_driver.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_driver.F
@@ -15,9 +15,10 @@ module mpas_atmphys_driver
use mpas_atmphys_driver_gwdo
use mpas_atmphys_driver_lsm
use mpas_atmphys_driver_lsm_noahmp
+ use mpas_atmphys_driver_lsm_colm2024,only: push_lsm_colm2024, step_lsm_colm2024, pull_lsm_colm2024
use mpas_atmphys_driver_pbl
use mpas_atmphys_driver_radiation_lw
- use mpas_atmphys_driver_radiation_sw
+ use mpas_atmphys_driver_radiation_sw
use mpas_atmphys_driver_seaice,only: allocate_seaice,deallocate_seaice,driver_seaice
use mpas_atmphys_driver_sfclayer
use mpas_atmphys_driver_oml
@@ -169,18 +170,216 @@ subroutine physics_driver(domain,itimestep,xtime_s)
call mpas_pool_get_config(domain%configs,'config_sfclayer_scheme' ,config_sfclayer_scheme )
call mpas_pool_get_config(domain%configs,'config_bucket_radt' ,config_bucket_radt )
call mpas_pool_get_config(domain%configs,'config_bucket_update' ,config_bucket_update )
- call mpas_pool_get_config(domain%configs,'config_frac_seaice' ,config_frac_seaice )
+ call mpas_pool_get_config(domain%configs,'config_frac_seaice' ,config_frac_seaice )
call mpas_pool_get_config(domain%configs,'config_oml1d' ,config_oml1d )
- if(config_convection_scheme .ne. 'off' .or. &
- config_lsm_scheme .ne. 'off' .or. &
- config_pbl_scheme .ne. 'off' .or. &
- config_radt_lw_scheme .ne. 'off' .or. &
- config_radt_sw_scheme .ne. 'off' .or. &
- config_sfclayer_scheme .ne. 'off') then
-
- block => domain % blocklist
- do while(associated(block))
+ if(config_convection_scheme .ne. 'off' .or. &
+ config_lsm_scheme .ne. 'off' .or. &
+ config_pbl_scheme .ne. 'off' .or. &
+ config_radt_lw_scheme .ne. 'off' .or. &
+ config_radt_sw_scheme .ne. 'off' .or. &
+ config_sfclayer_scheme .ne. 'off') then
+
+ if(config_lsm_scheme == 'sf_colm2024') then
+
+ block => domain % blocklist
+ do while(associated(block))
+
+ call mpas_pool_get_subpool(block%structs,'mesh' ,mesh )
+ call mpas_pool_get_subpool(block%structs,'state' ,state )
+ call mpas_pool_get_subpool(block%structs,'diag' ,diag )
+ call mpas_pool_get_subpool(block%structs,'diag_physics' ,diag_physics )
+ call mpas_pool_get_subpool(block%structs,'diag_physics_noahmp',diag_physics_noahmp)
+ call mpas_pool_get_subpool(block%structs,'output_noahmp' ,output_noahmp )
+ call mpas_pool_get_subpool(block%structs,'atm_input' ,atm_input )
+ call mpas_pool_get_subpool(block%structs,'sfc_input' ,sfc_input )
+ call mpas_pool_get_subpool(block%structs,'ngw_input' ,ngw_input )
+ call mpas_pool_get_subpool(block%structs,'tend_physics' ,tend_physics )
+
+ call mpas_pool_get_dimension(block%dimensions,'nThreads',nThreads)
+ call mpas_pool_get_dimension(block%dimensions,'cellSolveThreadStart',cellSolveThreadStart)
+ call mpas_pool_get_dimension(block%dimensions,'cellSolveThreadEnd',cellSolveThreadEnd)
+
+ call allocate_forall_physics(block%configs)
+ time_lev = 1
+
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call MPAS_to_physics(block%configs,mesh,state,time_lev,diag,diag_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+
+ if(l_radtlw .or. l_radtsw) then
+ call allocate_cloudiness
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_cloudiness(block%configs,mesh,diag_physics,sfc_input, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ endif
+
+ if(l_radtsw) then
+ time_lev = 1
+ call allocate_radiation_sw(block%configs,xtime_s)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_radiation_sw(itimestep,block%configs,mesh,state,time_lev,diag_physics, &
+ atm_input,sfc_input,tend_physics,xtime_s, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ endif
+
+ if(l_radtlw) then
+ time_lev = 1
+ call allocate_radiation_lw(block%configs,xtime_s)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_radiation_lw(xtime_s,block%configs,mesh,state,time_lev,diag_physics, &
+ atm_input,sfc_input,tend_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ endif
+
+ if(config_bucket_update /= 'none' .and. config_bucket_radt .gt. 0._RKIND) then
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call update_radiation_diagnostics(block%configs,mesh,diag_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ endif
+
+ if(config_radt_sw_scheme.ne.'off' .or. config_radt_lw_scheme.ne.'off') &
+ call deallocate_cloudiness
+ if(config_radt_sw_scheme.ne.'off') call deallocate_radiation_sw(block%configs)
+ if(config_radt_lw_scheme.ne.'off') call deallocate_radiation_lw(block%configs)
+
+ if(config_sfclayer_scheme .ne. 'off') then
+ call allocate_sfclayer(block%configs)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_sfclayer(itimestep,block%configs,mesh,diag_physics,sfc_input, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ call deallocate_sfclayer(block%configs)
+ endif
+
+ if(config_oml1d) call driver_oml1d(block%configs,mesh,diag,diag_physics,sfc_input)
+
+ call push_lsm_colm2024(block,block%configs,mesh,state,time_lev,diag,diag_physics, &
+ sfc_input,itimestep,cellSolveThreadStart(1),cellSolveThreadEnd(nThreads))
+
+ call deallocate_forall_physics(block%configs)
+ block => block % next
+ end do
+
+ call step_lsm_colm2024()
+
+ block => domain % blocklist
+ do while(associated(block))
+
+ call mpas_pool_get_subpool(block%structs,'mesh' ,mesh )
+ call mpas_pool_get_subpool(block%structs,'state' ,state )
+ call mpas_pool_get_subpool(block%structs,'diag' ,diag )
+ call mpas_pool_get_subpool(block%structs,'diag_physics' ,diag_physics )
+ call mpas_pool_get_subpool(block%structs,'diag_physics_noahmp',diag_physics_noahmp)
+ call mpas_pool_get_subpool(block%structs,'output_noahmp' ,output_noahmp )
+ call mpas_pool_get_subpool(block%structs,'sfc_input' ,sfc_input )
+ call mpas_pool_get_subpool(block%structs,'ngw_input' ,ngw_input )
+ call mpas_pool_get_subpool(block%structs,'tend_physics' ,tend_physics )
+
+ call mpas_pool_get_dimension(block%dimensions,'nThreads',nThreads)
+ call mpas_pool_get_dimension(block%dimensions,'cellSolveThreadStart',cellSolveThreadStart)
+ call mpas_pool_get_dimension(block%dimensions,'cellSolveThreadEnd',cellSolveThreadEnd)
+
+ call allocate_forall_physics(block%configs)
+ time_lev = 1
+
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call MPAS_to_physics(block%configs,mesh,state,time_lev,diag,diag_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+
+ call pull_lsm_colm2024(block,diag_physics,sfc_input,cellSolveThreadStart(1),cellSolveThreadEnd(nThreads))
+
+ call allocate_seaice(block%configs)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_seaice(block%configs,diag_physics,sfc_input, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ enddo
+ !$OMP END PARALLEL DO
+ call deallocate_seaice(block%configs)
+
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call atmphys_sfc_diagnostics(block%configs,mesh,diag,diag_physics,sfc_input,output_noahmp, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ enddo
+ !$OMP END PARALLEL DO
+
+ if(config_pbl_scheme .ne. 'off' .and. config_sfclayer_scheme .ne. 'off') then
+ call allocate_pbl(block%configs)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_pbl(itimestep,block%configs,mesh,sfc_input,diag_physics,tend_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ call deallocate_pbl(block%configs)
+ endif
+
+ if(config_gwdo_scheme .ne. 'off') then
+ call allocate_gwdo(block%configs)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_gwdo(itimestep,block%configs,mesh,sfc_input,ngw_input,diag_physics, &
+ tend_physics,cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ call deallocate_gwdo(block%configs)
+ endif
+
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call update_convection_step1(block%configs,diag_physics,tend_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ if(l_conv) then
+ call allocate_convection(block%configs)
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call driver_convection(itimestep,block%configs,mesh,sfc_input,diag_physics,tend_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ call deallocate_convection(block%configs)
+ endif
+ if(config_convection_scheme .ne. 'off') then
+ !$OMP PARALLEL DO
+ do thread=1,nThreads
+ call update_convection_step2(block%configs,diag_physics, &
+ cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
+ end do
+ !$OMP END PARALLEL DO
+ end if
+
+ call deallocate_forall_physics(block%configs)
+ block => block % next
+ end do
+
+ else
+
+ block => domain % blocklist
+ do while(associated(block))
call mpas_pool_get_subpool(block%structs,'mesh' ,mesh )
call mpas_pool_get_subpool(block%structs,'state' ,state )
@@ -297,7 +496,7 @@ subroutine physics_driver(domain,itimestep,xtime_s)
diag_physics_noahmp,output_noahmp,sfc_input,itimestep, &
cellSolveThreadStart(thread),cellSolveThreadEnd(thread))
enddo
- endif
+ endif
call allocate_seaice(block%configs)
!$OMP PARALLEL DO
@@ -372,9 +571,10 @@ subroutine physics_driver(domain,itimestep,xtime_s)
call deallocate_forall_physics(block%configs)
block => block % next
- end do
+ end do
+ endif
- endif
+ endif
call mpas_timer_stop('physics driver')
diff --git a/src/core_atmosphere/physics/mpas_atmphys_driver_lsm_colm2024.F b/src/core_atmosphere/physics/mpas_atmphys_driver_lsm_colm2024.F
new file mode 100644
index 0000000000..aeca5641a5
--- /dev/null
+++ b/src/core_atmosphere/physics/mpas_atmphys_driver_lsm_colm2024.F
@@ -0,0 +1,577 @@
+! Copyright (c) 2013, Los Alamos National Security, LLC (LANS)
+! and the University Corporation for Atmospheric Research (UCAR).
+!
+! Unless noted otherwise source code is licensed under the BSD license.
+! Additional copyright and license information can be found in the LICENSE file
+! distributed with this code, or at http://mpas-dev.github.com/license.html
+!
+!=================================================================================================================
+ module mpas_atmphys_driver_lsm_colm2024
+ use mpas_kind_types
+ use mpas_derived_types, only: block_type, dm_info
+ use mpas_pool_routines
+
+ use mpas_atmphys_constants, only: R_d, R_v
+ use mpas_atmphys_manager, only: year, curr_julday
+ use mpas_atmphys_utilities, only: physics_error_fatal
+ use mpas_atmphys_vars, only: dt_pbl, xice_threshold
+
+#ifdef MPAS_COLM2024
+ use MOD_Precision, only: colm_r8 => r8
+ use MOD_CoLM_MPAS_Interface, only: colm_mpas_initialize_from_namelist, colm_mpas_ready, &
+ colm_mpas_set_element_forcing, &
+ colm_mpas_step, colm_mpas_get_element_surface, &
+ colm_mpas_get_element_state, &
+ colm_mpas_finalize
+ use MOD_Vars_Global, only: colm_dz_soi => dz_soi
+#endif
+
+ implicit none
+ private
+ public :: init_lsm_colm2024, push_lsm_colm2024, step_lsm_colm2024, pull_lsm_colm2024, finalize_lsm_colm2024
+
+ logical, save :: colm_first_step = .true.
+#ifdef MPAS_COLM2024
+ type colm_block_map_type
+ integer :: local_block_id = -1
+ integer, allocatable :: element_for_cell(:)
+ type(colm_block_map_type), pointer :: next => null()
+ end type colm_block_map_type
+
+ type(colm_block_map_type), pointer, save :: colm_block_maps => null()
+ logical, save :: colm_initialized = .false.
+#endif
+
+ contains
+
+!=================================================================================================================
+ subroutine init_lsm_colm2024(dminfo,configs,block,diag_physics,sfc_input)
+!=================================================================================================================
+
+ type(dm_info),intent(in):: dminfo
+ type(mpas_pool_type),intent(in):: configs
+ type(block_type),intent(in):: block
+ type(mpas_pool_type),intent(inout):: diag_physics
+ type(mpas_pool_type),intent(inout):: sfc_input
+#ifdef MPAS_COLM2024
+ logical :: colm_ready
+ integer :: colm_ierr
+ integer :: colm_mpas_comm
+ integer :: colm_patch_count
+ integer :: block_cells
+ integer :: n_mpas_cells
+ integer :: offset
+ character(len=StrKIND),pointer:: config_colm2024_namelist
+ integer,pointer:: nCellsSolve
+ integer,dimension(:),pointer:: indexToCellID
+ integer,allocatable:: cell_to_element(:), mpas_cell_id(:)
+ type(block_type),pointer:: block_cursor
+ type(colm_block_map_type),pointer:: block_map
+ type(mpas_pool_type),pointer:: block_mesh
+#endif
+
+#ifdef MPAS_COLM2024
+ call mpas_pool_get_config(configs,'config_colm2024_namelist',config_colm2024_namelist)
+ if(trim(config_colm2024_namelist) == 'none' .or. trim(config_colm2024_namelist) == '') then
+ call physics_error_fatal("config_lsm_scheme='sf_colm2024' requires config_colm2024_namelist.")
+ endif
+
+ if(colm_initialized) return
+ if(associated(block % next)) return
+ if(.not. associated(block % domain)) call physics_error_fatal("CoLM2024 MPAS block is missing its owning domain.")
+
+ call colm2024_free_block_maps()
+
+ n_mpas_cells = 0
+ block_cursor => block % domain % blocklist
+ do while(associated(block_cursor))
+ call mpas_pool_get_subpool(block_cursor % structs,'mesh',block_mesh)
+ call mpas_pool_get_dimension(block_mesh,'nCellsSolve',nCellsSolve)
+ n_mpas_cells = n_mpas_cells + nCellsSolve
+ block_cursor => block_cursor % next
+ enddo
+ allocate(mpas_cell_id(n_mpas_cells), cell_to_element(n_mpas_cells))
+
+ offset = 0
+ block_cursor => block % domain % blocklist
+ do while(associated(block_cursor))
+ call mpas_pool_get_subpool(block_cursor % structs,'mesh',block_mesh)
+ call mpas_pool_get_dimension(block_mesh,'nCellsSolve',nCellsSolve)
+ call mpas_pool_get_array(block_mesh,'indexToCellID',indexToCellID)
+
+ block_cells = nCellsSolve
+ if(block_cells > 0) then
+ mpas_cell_id(offset+1:offset+block_cells) = indexToCellID(1:block_cells)
+ endif
+ call colm2024_add_block_map(block_cursor % localBlockID, size(indexToCellID))
+ offset = offset + block_cells
+ block_cursor => block_cursor % next
+ enddo
+
+#ifdef MPAS_USE_MPI_F08
+ colm_mpas_comm = dminfo % comm % mpi_val
+#else
+ colm_mpas_comm = dminfo % comm
+#endif
+
+ call colm_mpas_initialize_from_namelist(trim(config_colm2024_namelist), colm_ierr, &
+ mpas_comm=colm_mpas_comm, &
+ mpas_cell_id=mpas_cell_id, &
+ n_mpas_cells=n_mpas_cells, &
+ cell_to_element=cell_to_element)
+ if(colm_ierr /= 0) call physics_error_fatal("CoLM2024 initialization from config_colm2024_namelist failed.")
+
+ offset = 0
+ block_cursor => block % domain % blocklist
+ do while(associated(block_cursor))
+ call mpas_pool_get_subpool(block_cursor % structs,'mesh',block_mesh)
+ call mpas_pool_get_dimension(block_mesh,'nCellsSolve',nCellsSolve)
+ call colm2024_find_block_map(block_cursor % localBlockID, block_map)
+ if(.not. associated(block_map)) call physics_error_fatal("CoLM2024 MPAS block map was not created.")
+ block_map % element_for_cell(:) = 0
+ block_cells = nCellsSolve
+ if(block_cells > 0) block_map % element_for_cell(1:block_cells) = cell_to_element(offset+1:offset+block_cells)
+ offset = offset + block_cells
+ block_cursor => block_cursor % next
+ enddo
+
+ call colm_mpas_ready(colm_ready, colm_patch_count)
+ if(.not. colm_ready) call colm2024_adapter_not_ready
+
+ colm_first_step = .true.
+ colm_initialized = .true.
+#else
+ call colm2024_adapter_not_built
+#endif
+
+ end subroutine init_lsm_colm2024
+
+!=================================================================================================================
+ subroutine push_lsm_colm2024(block,configs,mesh,state,time_lev,diag,diag_physics,sfc_input,itimestep,its,ite)
+!=================================================================================================================
+
+ type(block_type),intent(in):: block
+ type(mpas_pool_type),intent(in):: configs
+ type(mpas_pool_type),intent(in):: mesh
+ type(mpas_pool_type),intent(in):: state
+ type(mpas_pool_type),intent(in):: diag
+ type(mpas_pool_type),intent(inout):: diag_physics
+ type(mpas_pool_type),intent(inout):: sfc_input
+ integer,intent(in):: time_lev
+ integer,intent(in):: itimestep
+ integer,intent(in):: its,ite
+#ifdef MPAS_COLM2024
+ logical :: colm_ready
+ integer :: colm_patch_count
+ type(colm_block_map_type),pointer:: block_map
+#endif
+
+#ifdef MPAS_COLM2024
+ call colm_mpas_ready(colm_ready, colm_patch_count)
+ if(.not. colm_ready) call colm2024_adapter_not_ready
+ call colm2024_find_block_map(block % localBlockID, block_map)
+ if(.not. associated(block_map)) call physics_error_fatal("CoLM2024 MPAS cell-to-element map is not initialized.")
+ if(size(block_map % element_for_cell) < ite) call physics_error_fatal("CoLM2024 MPAS cell-to-element map is smaller " // &
+ "than the MPAS cell range.")
+
+ call colm2024_push_mpas_forcing(block_map % element_for_cell, configs, mesh, state, time_lev, diag, diag_physics, &
+ sfc_input, itimestep, its, ite)
+#else
+ call colm2024_adapter_not_built
+#endif
+
+ end subroutine push_lsm_colm2024
+
+!=================================================================================================================
+ subroutine step_lsm_colm2024()
+!=================================================================================================================
+
+#ifdef MPAS_COLM2024
+ logical :: colm_ready
+ integer :: colm_ierr
+ integer :: colm_patch_count
+ integer :: colm_idate(3)
+
+ call colm_mpas_ready(colm_ready, colm_patch_count)
+ if(.not. colm_ready) call colm2024_adapter_not_ready
+ colm_idate(1) = year
+ colm_idate(2) = int(curr_julday) + 1
+ colm_idate(3) = nint((curr_julday - real(int(curr_julday), RKIND)) * 86400._RKIND)
+ call colm_mpas_step(colm_idate, real(dt_pbl, colm_r8), colm_first_step, .true., .false., colm_ierr)
+ if(colm_ierr /= 0) call physics_error_fatal("CoLM2024 driver returned before completing a land-surface step.")
+ colm_first_step = .false.
+#else
+ call colm2024_adapter_not_built
+#endif
+
+ end subroutine step_lsm_colm2024
+
+!=================================================================================================================
+ subroutine pull_lsm_colm2024(block,diag_physics,sfc_input,its,ite)
+!=================================================================================================================
+
+ type(block_type),intent(in):: block
+ type(mpas_pool_type),intent(inout):: diag_physics
+ type(mpas_pool_type),intent(inout):: sfc_input
+ integer,intent(in):: its,ite
+#ifdef MPAS_COLM2024
+ logical :: colm_ready
+ integer :: colm_patch_count
+ type(colm_block_map_type),pointer:: block_map
+
+ call colm_mpas_ready(colm_ready, colm_patch_count)
+ if(.not. colm_ready) call colm2024_adapter_not_ready
+ call colm2024_find_block_map(block % localBlockID, block_map)
+ if(.not. associated(block_map)) call physics_error_fatal("CoLM2024 MPAS cell-to-element map is not initialized.")
+ if(size(block_map % element_for_cell) < ite) call physics_error_fatal("CoLM2024 MPAS cell-to-element map is smaller " // &
+ "than the MPAS cell range.")
+
+ call colm2024_pull_mpas_surface(block_map % element_for_cell, diag_physics, sfc_input, real(dt_pbl, colm_r8), its, ite)
+#else
+ call colm2024_adapter_not_built
+#endif
+
+ end subroutine pull_lsm_colm2024
+
+!=================================================================================================================
+ subroutine finalize_lsm_colm2024()
+ !=================================================================================================================
+
+#ifdef MPAS_COLM2024
+ integer :: colm_ierr
+
+ if(.not. colm_initialized) return
+ call colm_mpas_finalize(colm_ierr)
+ if(colm_ierr /= 0) call physics_error_fatal("CoLM2024 finalization failed.")
+ call colm2024_free_block_maps()
+ colm_first_step = .true.
+ colm_initialized = .false.
+#endif
+
+ end subroutine finalize_lsm_colm2024
+
+#ifdef MPAS_COLM2024
+!=================================================================================================================
+ subroutine colm2024_add_block_map(local_block_id, nCells)
+!=================================================================================================================
+
+ integer,intent(in):: local_block_id
+ integer,intent(in):: nCells
+ type(colm_block_map_type),pointer:: block_map, cursor
+
+ allocate(block_map)
+ block_map % local_block_id = local_block_id
+ allocate(block_map % element_for_cell(nCells))
+ block_map % element_for_cell(:) = 0
+ nullify(block_map % next)
+
+ if(.not. associated(colm_block_maps)) then
+ colm_block_maps => block_map
+ else
+ cursor => colm_block_maps
+ do while(associated(cursor % next))
+ cursor => cursor % next
+ enddo
+ cursor % next => block_map
+ endif
+
+ end subroutine colm2024_add_block_map
+
+!=================================================================================================================
+ subroutine colm2024_find_block_map(local_block_id, block_map)
+!=================================================================================================================
+
+ integer,intent(in):: local_block_id
+ type(colm_block_map_type),pointer:: block_map
+
+ block_map => colm_block_maps
+ do while(associated(block_map))
+ if(block_map % local_block_id == local_block_id) return
+ block_map => block_map % next
+ enddo
+ nullify(block_map)
+
+ end subroutine colm2024_find_block_map
+
+!=================================================================================================================
+ subroutine colm2024_free_block_maps()
+!=================================================================================================================
+
+ type(colm_block_map_type),pointer:: block_map, next_map
+
+ block_map => colm_block_maps
+ do while(associated(block_map))
+ next_map => block_map % next
+ if(allocated(block_map % element_for_cell)) deallocate(block_map % element_for_cell)
+ deallocate(block_map)
+ block_map => next_map
+ enddo
+ nullify(colm_block_maps)
+
+ end subroutine colm2024_free_block_maps
+
+!=================================================================================================================
+ subroutine colm2024_push_mpas_forcing(element_for_cell,configs,mesh,state,time_lev,diag,diag_physics,sfc_input,itimestep,its,ite)
+!=================================================================================================================
+
+ integer,dimension(:),intent(in):: element_for_cell
+ type(mpas_pool_type),intent(in):: configs
+ type(mpas_pool_type),intent(in):: mesh
+ type(mpas_pool_type),intent(in):: state
+ type(mpas_pool_type),intent(in):: diag
+ type(mpas_pool_type),intent(in):: diag_physics
+ type(mpas_pool_type),intent(in):: sfc_input
+ integer,intent(in):: time_lev
+ integer,intent(in):: itimestep
+ integer,intent(in):: its,ite
+
+ character(len=StrKIND),pointer:: config_convection_scheme, config_microp_scheme
+ integer,pointer:: index_qv
+ integer:: i, k
+ integer:: ierr
+ real(kind=colm_r8):: aerdep(14)
+ real(kind=colm_r8):: dt, micro_rain, micro_snow, hgt, oro, pbot, psrf, prc, prl, qair, rain, rhoair, snow, &
+ solld, soll, solsd, sols, spectral_sw, swdir, swdif, tair, uair, vair
+ real(kind=RKIND):: qv_cell
+ real(kind=RKIND),dimension(:),pointer:: glw, swddir, swddif, swvisdir, swvisdif, swnirdir, swnirdif
+ real(kind=RKIND),dimension(:),pointer:: surface_pressure, sr, xice, xland
+ real(kind=RKIND),dimension(:),pointer:: raincv, rainncv, snowncv, graupelncv
+ real(kind=RKIND),dimension(:,:),pointer:: exner, pressure_b, pressure_p, theta_m, u, v, zgrid
+ real(kind=RKIND),dimension(:,:,:),pointer:: scalars
+
+ call mpas_pool_get_config(configs,'config_convection_scheme',config_convection_scheme)
+ call mpas_pool_get_config(configs,'config_microp_scheme' ,config_microp_scheme )
+
+ call mpas_pool_get_dimension(state,'index_qv',index_qv)
+ call mpas_pool_get_array(mesh,'zgrid',zgrid)
+ call mpas_pool_get_array(state,'theta_m',theta_m,time_lev)
+ call mpas_pool_get_array(state,'scalars',scalars,time_lev)
+ call mpas_pool_get_array(diag,'exner' ,exner )
+ call mpas_pool_get_array(diag,'pressure_base' ,pressure_b)
+ call mpas_pool_get_array(diag,'pressure_p' ,pressure_p)
+ call mpas_pool_get_array(diag,'uReconstructZonal' ,u )
+ call mpas_pool_get_array(diag,'uReconstructMeridional',v )
+ call mpas_pool_get_array(diag,'surface_pressure',surface_pressure)
+ call mpas_pool_get_array(diag_physics,'glw' ,glw )
+ call mpas_pool_get_array(diag_physics,'swddir',swddir)
+ call mpas_pool_get_array(diag_physics,'swddif',swddif)
+ call mpas_pool_get_array(diag_physics,'swvisdir',swvisdir)
+ call mpas_pool_get_array(diag_physics,'swvisdif',swvisdif)
+ call mpas_pool_get_array(diag_physics,'swnirdir',swnirdir)
+ call mpas_pool_get_array(diag_physics,'swnirdif',swnirdif)
+ call mpas_pool_get_array(diag_physics,'raincv' ,raincv )
+ call mpas_pool_get_array(diag_physics,'rainncv' ,rainncv )
+ call mpas_pool_get_array(diag_physics,'snowncv' ,snowncv )
+ call mpas_pool_get_array(diag_physics,'graupelncv',graupelncv)
+ call mpas_pool_get_array(diag_physics,'sr' ,sr )
+ call mpas_pool_get_array(sfc_input,'xland',xland)
+ call mpas_pool_get_array(sfc_input,'xice' ,xice )
+
+ dt = max(real(dt_pbl, colm_r8), 1._colm_r8)
+ aerdep(:) = 0._colm_r8
+
+ k = lbound(theta_m, 1)
+ do i = its,ite
+ if(element_for_cell(i) <= 0) call physics_error_fatal("CoLM2024 MPAS cell-to-element map has an invalid element index.")
+
+ psrf = real(surface_pressure(i), colm_r8)
+ pbot = real(pressure_b(k,i) + pressure_p(k,i), colm_r8)
+ qv_cell = max(0._RKIND, scalars(index_qv,k,i))
+ tair = real((theta_m(k,i) / (1._RKIND + R_v / R_d * qv_cell)) * exner(k,i), colm_r8)
+ qair = real(qv_cell / (1._RKIND + qv_cell), colm_r8)
+ uair = real(u(k,i), colm_r8)
+ vair = real(v(k,i), colm_r8)
+ hgt = 2._colm_r8
+ if(ubound(zgrid, 1) >= k + 1) hgt = max(2._colm_r8, real(0.5_RKIND * (zgrid(k+1,i) - zgrid(k,i)), colm_r8))
+ rhoair = max(0.1_colm_r8, pbot / (R_d * tair * (1._colm_r8 + 0.61_colm_r8 * qair)))
+ prc = 0._colm_r8
+ prl = 0._colm_r8
+ rain = 0._colm_r8
+ snow = 0._colm_r8
+
+ if(config_convection_scheme .ne. 'off') then
+ prc = max(0._colm_r8, real(raincv(i), colm_r8) / dt)
+ rain = rain + prc
+ endif
+ if(config_microp_scheme .ne. 'off') then
+ micro_rain = max(0._colm_r8, real(rainncv(i), colm_r8) / dt)
+ micro_snow = max(0._colm_r8, real(snowncv(i) + graupelncv(i), colm_r8) / dt)
+ if(micro_snow <= 0._colm_r8 .and. sr(i) > 0._RKIND) then
+ micro_snow = micro_rain * min(1._colm_r8, real(sr(i), colm_r8))
+ micro_rain = max(0._colm_r8, micro_rain - micro_snow)
+ endif
+ prl = micro_rain + micro_snow
+ rain = rain + micro_rain
+ snow = snow + micro_snow
+ endif
+
+ swdir = max(0._colm_r8, real(swddir(i), colm_r8))
+ swdif = max(0._colm_r8, real(swddif(i), colm_r8))
+ sols = max(0._colm_r8, real(swvisdir(i), colm_r8))
+ solsd = max(0._colm_r8, real(swvisdif(i), colm_r8))
+ soll = max(0._colm_r8, real(swnirdir(i), colm_r8))
+ solld = max(0._colm_r8, real(swnirdif(i), colm_r8))
+ spectral_sw = sols + solsd + soll + solld
+ if(spectral_sw <= 0._colm_r8 .and. swdir + swdif > 0._colm_r8) then
+ sols = 0.5_colm_r8 * swdir
+ soll = 0.5_colm_r8 * swdir
+ solsd = 0.5_colm_r8 * swdif
+ solld = 0.5_colm_r8 * swdif
+ endif
+ oro = 1._colm_r8
+ if(xland(i) >= 1.5_RKIND) oro = 0._colm_r8
+ if(xice(i) >= xice_threshold) oro = 2._colm_r8
+
+ call colm_mpas_set_element_forcing(element_for_cell(i), psrf * 420.e-6_colm_r8, &
+ psrf * 0.209_colm_r8, uair, vair, tair, qair, &
+ prc, prl, rain, snow, psrf, pbot, &
+ sols, soll, solsd, solld, &
+ real(glw(i), colm_r8), hgt, hgt, hgt, rhoair, 1000._colm_r8, &
+ aerdep, oro=oro, ierr=ierr)
+ if(ierr /= 0) call physics_error_fatal("Failed to pass MPAS forcing into CoLM2024.")
+ enddo
+
+ end subroutine colm2024_push_mpas_forcing
+
+!=================================================================================================================
+ subroutine colm2024_pull_mpas_surface(element_for_cell,diag_physics,sfc_input,dt,its,ite)
+!=================================================================================================================
+
+ integer,dimension(:),intent(in):: element_for_cell
+ type(mpas_pool_type),intent(inout):: diag_physics
+ type(mpas_pool_type),intent(inout):: sfc_input
+ real(kind=colm_r8),intent(in):: dt
+ integer,intent(in):: its,ite
+
+ integer:: i, ns, nlev, nvalid_soil
+ integer:: ierr
+ real(kind=colm_r8):: sensible, latent, evaporation, ground_heat, runoff
+ real(kind=colm_r8):: surface_runoff, subsurface_runoff, skin_temp, t2m_colm, q2m_colm, qsfc_colm
+ real(kind=colm_r8):: emissivity, roughness, albedo
+ real(kind=colm_r8):: canopy_water, snow_water, snow_depth, snow_cover, leaf_area_index
+ real(kind=colm_r8):: soil_moisture_sum
+ real(kind=colm_r8):: soil_depth_sum
+ real(kind=colm_r8),parameter:: colm_state_bad_value = 1.e30_colm_r8
+ real(kind=colm_r8),dimension(:),allocatable:: soil_liquid, soil_moisture, soil_temperature
+ real(kind=RKIND),dimension(:),pointer:: hfx, lh, qfx, grdflx, sfcrunoff, udrunoff
+ real(kind=RKIND),dimension(:),pointer:: sfc_albedo, sfc_emiss, z0, znt, qsfc, t2m, q2
+ real(kind=RKIND),dimension(:),pointer:: skintemp, canwat, smstav, smstot, snow, snowc, snowh, lai
+ real(kind=RKIND),dimension(:,:),pointer:: sh2o, smois, tslb
+
+ call mpas_pool_get_array(diag_physics,'hfx' ,hfx )
+ call mpas_pool_get_array(diag_physics,'lh' ,lh )
+ call mpas_pool_get_array(diag_physics,'qfx' ,qfx )
+ call mpas_pool_get_array(diag_physics,'grdflx' ,grdflx )
+ call mpas_pool_get_array(diag_physics,'sfcrunoff' ,sfcrunoff )
+ call mpas_pool_get_array(diag_physics,'udrunoff' ,udrunoff )
+ call mpas_pool_get_array(diag_physics,'sfc_albedo',sfc_albedo)
+ call mpas_pool_get_array(diag_physics,'sfc_emiss' ,sfc_emiss )
+ call mpas_pool_get_array(diag_physics,'z0' ,z0 )
+ call mpas_pool_get_array(diag_physics,'znt' ,znt )
+ call mpas_pool_get_array(diag_physics,'qsfc' ,qsfc )
+ call mpas_pool_get_array(diag_physics,'t2m' ,t2m )
+ call mpas_pool_get_array(diag_physics,'q2' ,q2 )
+ call mpas_pool_get_array(diag_physics,'canwat' ,canwat )
+ call mpas_pool_get_array(diag_physics,'smstav' ,smstav )
+ call mpas_pool_get_array(diag_physics,'smstot' ,smstot )
+ call mpas_pool_get_array(diag_physics,'lai' ,lai )
+ call mpas_pool_get_array(sfc_input,'skintemp',skintemp)
+ call mpas_pool_get_array(sfc_input,'snow' ,snow )
+ call mpas_pool_get_array(sfc_input,'snowc' ,snowc )
+ call mpas_pool_get_array(sfc_input,'snowh' ,snowh )
+ call mpas_pool_get_array(sfc_input,'sh2o' ,sh2o )
+ call mpas_pool_get_array(sfc_input,'smois' ,smois )
+ call mpas_pool_get_array(sfc_input,'tslb' ,tslb )
+
+ nlev = size(tslb, 1)
+ allocate(soil_liquid(nlev), soil_moisture(nlev), soil_temperature(nlev))
+
+ do i = its,ite
+ if(element_for_cell(i) <= 0) call physics_error_fatal("CoLM2024 MPAS cell-to-element map has an invalid element index.")
+
+ call colm_mpas_get_element_surface(element_for_cell(i), sensible, latent, evaporation, ground_heat, runoff, &
+ surface_runoff, subsurface_runoff, skin_temp, t2m_colm, q2m_colm, &
+ qsfc_colm, emissivity, roughness, albedo, ierr)
+ if(ierr /= 0) call physics_error_fatal("Failed to retrieve CoLM2024 surface fluxes.")
+ call colm_mpas_get_element_state(element_for_cell(i), canopy_water, snow_water, snow_depth, snow_cover, &
+ leaf_area_index, soil_liquid, soil_moisture, soil_temperature, ierr)
+ if(ierr /= 0) call physics_error_fatal("Failed to retrieve CoLM2024 surface state.")
+
+ hfx(i) = real(sensible, RKIND)
+ lh(i) = real(latent, RKIND)
+ qfx(i) = real(evaporation, RKIND)
+ ! CoLM fgrnd and MPAS/Noah-MP grdflx are positive into soil/snow.
+ grdflx(i) = real(ground_heat, RKIND)
+ ! MPAS runoff diagnostics are accumulated depths, matching Noah/Noah-MP.
+ sfcrunoff(i) = sfcrunoff(i) + real(surface_runoff * dt, RKIND)
+ udrunoff(i) = udrunoff(i) + real(subsurface_runoff * dt, RKIND)
+ skintemp(i) = real(skin_temp, RKIND)
+ t2m(i) = real(t2m_colm, RKIND)
+ qsfc(i) = real(qsfc_colm, RKIND)
+ ! MPAS/WRF q2 is a 2 m mixing ratio; CoLM qref is specific humidity.
+ if(abs(q2m_colm) < colm_state_bad_value .and. q2m_colm >= 0._colm_r8 .and. q2m_colm < 1._colm_r8) then
+ q2(i) = real(q2m_colm / (1._colm_r8 - q2m_colm), RKIND)
+ endif
+ sfc_emiss(i) = real(emissivity, RKIND)
+ z0(i) = real(roughness, RKIND)
+ znt(i) = real(roughness, RKIND)
+ if(albedo > 0._colm_r8 .and. albedo < 1._colm_r8) sfc_albedo(i) = real(albedo, RKIND)
+ canwat(i) = real(canopy_water, RKIND)
+ snow(i) = real(snow_water, RKIND)
+ snowh(i) = real(snow_depth, RKIND)
+ snowc(i) = real(max(0._colm_r8, min(1._colm_r8, snow_cover)), RKIND)
+ lai(i) = real(max(0._colm_r8, leaf_area_index), RKIND)
+
+ soil_moisture_sum = 0._colm_r8
+ soil_depth_sum = 0._colm_r8
+ nvalid_soil = 0
+ do ns = 1,nlev
+ if(abs(soil_liquid(ns)) < colm_state_bad_value .and. &
+ abs(soil_moisture(ns)) < colm_state_bad_value .and. &
+ abs(soil_temperature(ns)) < colm_state_bad_value) then
+ sh2o(ns,i) = real(soil_liquid(ns), RKIND)
+ smois(ns,i) = real(soil_moisture(ns), RKIND)
+ tslb(ns,i) = real(soil_temperature(ns), RKIND)
+ if(ns <= size(colm_dz_soi) .and. colm_dz_soi(ns) > 0._colm_r8) then
+ soil_moisture_sum = soil_moisture_sum + soil_moisture(ns) * colm_dz_soi(ns)
+ soil_depth_sum = soil_depth_sum + colm_dz_soi(ns)
+ endif
+ nvalid_soil = nvalid_soil + 1
+ endif
+ enddo
+ if(nvalid_soil > 0 .and. soil_depth_sum > 0._colm_r8) then
+ smstot(i) = real(soil_moisture_sum / soil_depth_sum, RKIND)
+ if(abs(soil_moisture(1)) < colm_state_bad_value) then
+ smstav(i) = real(soil_moisture(1), RKIND)
+ else
+ smstav(i) = smstot(i)
+ endif
+ smstav(i) = max(0._RKIND, min(1._RKIND, smstav(i)))
+ endif
+ enddo
+
+ deallocate(soil_liquid, soil_moisture, soil_temperature)
+
+ end subroutine colm2024_pull_mpas_surface
+#endif
+
+!=================================================================================================================
+ subroutine colm2024_adapter_not_ready()
+!=================================================================================================================
+
+ call physics_error_fatal("CoLM2024 is linked, but CoLM landpatch/restart state has not been initialized " // &
+ "for this MPAS run.")
+
+ end subroutine colm2024_adapter_not_ready
+
+!=================================================================================================================
+ subroutine colm2024_adapter_not_built()
+!=================================================================================================================
+
+ call physics_error_fatal("CoLM2024 requires building MPAS with COLM2024=true.")
+
+ end subroutine colm2024_adapter_not_built
+
+!=================================================================================================================
+ end module mpas_atmphys_driver_lsm_colm2024
+!=================================================================================================================
diff --git a/src/core_atmosphere/physics/mpas_atmphys_driver_radiation_sw.F b/src/core_atmosphere/physics/mpas_atmphys_driver_radiation_sw.F
index 3a14275826..777260259d 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_driver_radiation_sw.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_driver_radiation_sw.F
@@ -16,7 +16,7 @@ module mpas_atmphys_driver_radiation_sw
use mpas_atmphys_camrad_init
use mpas_atmphys_rrtmg_swinit
use mpas_atmphys_vars
-
+
!wrf physics:
use module_mp_thompson_aerosols
use module_ra_rrtmg_sw_aerosols
@@ -142,7 +142,7 @@ subroutine allocate_radiation_sw(configs,xtime_s)
if(.not.allocated(swupbc_p) ) allocate(swupbc_p(ims:ime,jms:jme) )
if(.not.allocated(swupt_p) ) allocate(swupt_p(ims:ime,jms:jme) )
if(.not.allocated(swuptc_p) ) allocate(swuptc_p(ims:ime,jms:jme) )
-
+
if(.not.allocated(rthratensw_p) ) allocate(rthratensw_p(ims:ime,kms:kme,jms:jme) )
radiation_sw_select: select case (trim(radt_sw_scheme))
@@ -208,7 +208,7 @@ subroutine allocate_radiation_sw(configs,xtime_s)
if(.not.allocated(pin_p) ) allocate(pin_p(num_oznlevels) )
if(.not.allocated(ozmixm_p) ) &
allocate(ozmixm_p(ims:ime,1:num_oznlevels,jms:jme,num_months) )
-
+
if(.not.allocated(m_hybi_p) ) allocate(m_hybi_p(num_aerlevels) )
if(.not.allocated(m_psn_p) ) allocate(m_psn_p(ims:ime,jms:jme) )
if(.not.allocated(m_psp_p) ) allocate(m_psp_p(ims:ime,jms:jme) )
@@ -270,7 +270,7 @@ subroutine deallocate_radiation_sw(configs)
if(allocated(swupbc_p) ) deallocate(swupbc_p )
if(allocated(swupt_p) ) deallocate(swupt_p )
if(allocated(swuptc_p) ) deallocate(swuptc_p )
-
+
if(allocated(rthratensw_p) ) deallocate(rthratensw_p )
radiation_sw_select: select case (trim(radt_sw_scheme))
@@ -478,6 +478,10 @@ subroutine radiation_sw_from_MPAS(configs,mesh,state,time_lev,diag_physics,atm_i
swddir_p(i,j) = 0.0_RKIND
swddni_p(i,j) = 0.0_RKIND
swddif_p(i,j) = 0.0_RKIND
+ swvisdir_p(i,j) = 0.0_RKIND
+ swvisdif_p(i,j) = 0.0_RKIND
+ swnirdir_p(i,j) = 0.0_RKIND
+ swnirdif_p(i,j) = 0.0_RKIND
enddo
enddo
@@ -525,7 +529,7 @@ subroutine radiation_sw_from_MPAS(configs,mesh,state,time_lev,diag_physics,atm_i
enddo
endif
- case default
+ case default
end select microp_select
aerosol_select: select case(microp_scheme)
@@ -717,9 +721,9 @@ subroutine radiation_sw_to_MPAS(configs,diag_physics,tend_physics,its,ite)
!input arguments:
type(mpas_pool_type),intent(inout):: diag_physics
type(mpas_pool_type),intent(inout):: tend_physics
- type(mpas_pool_type),intent(in):: configs
+ type(mpas_pool_type),intent(in):: configs
!local pointers:
- character(len=StrKIND),pointer:: radt_sw_scheme
+ character(len=StrKIND),pointer:: radt_sw_scheme
integer,intent(in):: its,ite
@@ -729,7 +733,7 @@ subroutine radiation_sw_to_MPAS(configs,diag_physics,tend_physics,its,ite)
!local pointers:
real(kind=RKIND),dimension(:),pointer :: coszr,gsw,swcf,swdnb,swdnbc,swdnt,swdntc, &
swupb,swupbc,swupt,swuptc,swddir,swddni, &
- swddif
+ swddif,swvisdir,swvisdif,swnirdir,swnirdif
real(kind=RKIND),dimension(:,:),pointer:: rthratensw
!-----------------------------------------------------------------------------------------------------------------
@@ -750,9 +754,13 @@ subroutine radiation_sw_to_MPAS(configs,diag_physics,tend_physics,its,ite)
call mpas_pool_get_array(diag_physics,'swddir' ,swddir )
call mpas_pool_get_array(diag_physics,'swddni' ,swddni )
call mpas_pool_get_array(diag_physics,'swddif' ,swddif )
+ call mpas_pool_get_array(diag_physics,'swvisdir' ,swvisdir )
+ call mpas_pool_get_array(diag_physics,'swvisdif' ,swvisdif )
+ call mpas_pool_get_array(diag_physics,'swnirdir' ,swnirdir )
+ call mpas_pool_get_array(diag_physics,'swnirdif' ,swnirdif )
call mpas_pool_get_array(tend_physics,'rthratensw',rthratensw)
- call mpas_pool_get_config(configs,'config_radt_sw_scheme',radt_sw_scheme)
+ call mpas_pool_get_config(configs,'config_radt_sw_scheme',radt_sw_scheme)
do j = jts,jte
@@ -768,6 +776,10 @@ subroutine radiation_sw_to_MPAS(configs,diag_physics,tend_physics,its,ite)
swupbc(i) = swupbc_p(i,j)
swupt(i) = swupt_p(i,j)
swuptc(i) = swuptc_p(i,j)
+ swvisdir(i) = 0.0_RKIND
+ swvisdif(i) = 0.0_RKIND
+ swnirdir(i) = 0.0_RKIND
+ swnirdif(i) = 0.0_RKIND
enddo
radiation_sw_select: select case (trim(radt_sw_scheme))
@@ -776,6 +788,10 @@ subroutine radiation_sw_to_MPAS(configs,diag_physics,tend_physics,its,ite)
swddir(i) = swddir_p(i,j)
swddni(i) = swddni_p(i,j)
swddif(i) = swddif_p(i,j)
+ swvisdir(i) = swvisdir_p(i,j)
+ swvisdif(i) = swvisdif_p(i,j)
+ swnirdir(i) = swnirdir_p(i,j)
+ swnirdif(i) = swnirdif_p(i,j)
enddo
case default
end select radiation_sw_select
@@ -894,7 +910,7 @@ subroutine driver_radiation_sw(itimestep,configs,mesh,state,time_lev,diag_physic
!... convert the radiation time_step to minutes:
radt = dt_radtsw/60.
-
+
!call to shortwave radiation scheme:
radiation_sw_select: select case (trim(radt_sw_scheme))
case ("rrtmg_sw")
@@ -938,6 +954,8 @@ subroutine driver_radiation_sw(itimestep,configs,mesh,state,time_lev,diag_physic
swdnt = swdnt_p , swdntc = swdntc_p , swupb = swupb_p , &
swupbc = swupbc_p , swdnb = swdnb_p , swdnbc = swdnbc_p , &
swddir = swddir_p , swddni = swddni_p , swddif = swddif_p , &
+ swvisdir = swvisdir_p , swvisdif = swvisdif_p , swnirdir = swnirdir_p , &
+ swnirdif = swnirdif_p , &
ids = ids , ide = ide , jds = jds , jde = jde , kds = kds , kde = kde , &
ims = ims , ime = ime , jms = jms , jme = jme , kms = kms , kme = kme , &
its = its , ite = ite , jts = jts , jte = jte , kts = kts , kte = kte &
@@ -949,7 +967,7 @@ subroutine driver_radiation_sw(itimestep,configs,mesh,state,time_lev,diag_physic
call camrad( dolw = .false. , dosw = .true. , &
p_phy = pres_hyd_p , p8w = pres2_hyd_p , &
pi_phy = pi_p , t_phy = t_p , &
- z = zmid_p , dz8w = dz_p , &
+ z = zmid_p , dz8w = dz_p , &
rthratenlw = rthratenlw_p , rthratensw = rthratensw_p , &
swupt = swupt_p , swuptc = swuptc_p , &
swdnt = swdnt_p , swdntc = swdntc_p , &
@@ -962,11 +980,11 @@ subroutine driver_radiation_sw(itimestep,configs,mesh,state,time_lev,diag_physic
swcf = swcf_p , lwcf = lwcf_p , &
gsw = gsw_p , glw = glw_p , &
olr = olrtoa_p , cemiss = cemiss_p , &
- taucldc = taucldc_p , taucldi = taucldi_p , &
- coszr = coszr_p , albedo = sfc_albedo_p , &
- emiss = sfc_emiss_p , tsk = tsk_p , &
+ taucldc = taucldc_p , taucldi = taucldi_p , &
+ coszr = coszr_p , albedo = sfc_albedo_p , &
+ emiss = sfc_emiss_p , tsk = tsk_p , &
xlat = xlat_p , xlong = xlon_p , &
- rho_phy = rho_p , qv3d = qv_p , &
+ rho_phy = rho_p , qv3d = qv_p , &
qc3d = qc_p , qr3d = qr_p , &
qi3d = qi_p , qs3d = qs_p , &
qg3d = qg_p , f_qc = f_qc , &
@@ -974,7 +992,7 @@ subroutine driver_radiation_sw(itimestep,configs,mesh,state,time_lev,diag_physic
f_qs = f_qs , f_ice_phy = f_ice , &
f_rain_phy = f_rain , cldfra = cldfrac_p , &
xland = xland_p , xice = xice_p , &
- num_months = num_months , levsiz = num_oznlevels , &
+ num_months = num_months , levsiz = num_oznlevels , &
pin0 = pin_p , ozmixm = ozmixm_p , &
paerlev = num_aerlevels , naer_c = num_aerosols , &
m_psp = m_psp_p , m_psn = m_psn_p , &
@@ -1026,11 +1044,11 @@ subroutine radconst(declin,solcon,julian,degrad,dpd)
solcon=0.
!obecl : obliquity = 23.5 degree.
-
+
obecl=23.5*degrad
sinob=sin(obecl)
-
-!calculate longitude of the sun from vernal equinox:
+
+!calculate longitude of the sun from vernal equinox:
if(julian.ge.80.)sxlong=dpd*(julian-80.)
if(julian.lt.80.)sxlong=dpd*(julian+285.)
diff --git a/src/core_atmosphere/physics/mpas_atmphys_finalize.F b/src/core_atmosphere/physics/mpas_atmphys_finalize.F
index 5367d83286..b3d7a7b12b 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_finalize.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_finalize.F
@@ -10,6 +10,7 @@ module mpas_atmphys_finalize
use mpas_pool_routines
use mpas_atmphys_lsm_noahmpfinalize,only: sf_noahmp_deallocate
+ use mpas_atmphys_driver_lsm_colm2024,only: finalize_lsm_colm2024
use module_mp_thompson
use cires_ugwpv1_module
@@ -46,7 +47,7 @@ subroutine atmphys_finalize(configs)
character(len=StrKIND),pointer:: config_gwdo_scheme
logical,pointer:: config_ngw_scheme
-!-----------------------------------------------------------------------------------------------------------------
+!-----------------------------------------------------------------------------------------------------------------
call mpas_pool_get_config(configs,'config_lsm_scheme' ,config_lsm_scheme )
call mpas_pool_get_config(configs,'config_microp_scheme',config_microp_scheme)
@@ -55,6 +56,8 @@ subroutine atmphys_finalize(configs)
if(trim(config_lsm_scheme) == 'sf_noahmp') &
call sf_noahmp_deallocate
+ if(trim(config_lsm_scheme) == 'sf_colm2024') &
+ call finalize_lsm_colm2024
if(trim(config_microp_scheme) == 'mp_thompson' .or. &
trim(config_microp_scheme) == 'mp_thompson_aerosols') then
@@ -72,7 +75,7 @@ subroutine mp_thompson_deallocate
!call mpas_log_write('')
!call mpas_log_write('--- enter subroutine mp_thompson_deallocate:')
- if(allocated(tcg_racg) ) deallocate(tcg_racg )
+ if(allocated(tcg_racg) ) deallocate(tcg_racg )
if(allocated(tmr_racg) ) deallocate(tmr_racg )
if(allocated(tcr_gacr) ) deallocate(tcr_gacr )
if(allocated(tmg_gacr) ) deallocate(tmg_gacr )
diff --git a/src/core_atmosphere/physics/mpas_atmphys_init.F b/src/core_atmosphere/physics/mpas_atmphys_init.F
index 5183f5a974..431442c19b 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_init.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_init.F
@@ -23,6 +23,7 @@ module mpas_atmphys_init
use mpas_atmphys_landuse
use mpas_atmphys_o3climatology
use mpas_atmphys_lsm_noahmpinit,only: init_lsm_noahmp
+ use mpas_atmphys_driver_lsm_colm2024,only: init_lsm_colm2024
use bl_ugwpv1_ngw, only: ugwpv1_ngw_init
@@ -74,21 +75,23 @@ module mpas_atmphys_init
! * added call to subroutine init_lsm_noahmp to initialize the Noah-MP land surface scheme.
! Laura D. Fowler (laura@ucar.edu) / 2024-03-11.
! * added initialization of the integer variable mp_top_level to the physics_init code.
-! Bill Skamarock / 2025-10-17
+! Bill Skamarock / 2025-10-17
contains
!=================================================================================================================
- subroutine physics_init(dminfo,stream_manager,clock,configs,mesh,diag,tend,tend_physics,state,time_lev,diag_physics, &
+ subroutine physics_init(dminfo,stream_manager,clock,block,configs,mesh,diag,tend,tend_physics,state,time_lev,diag_physics, &
diag_physics_noahmp,ngw_input,atm_input,sfc_input,output_noahmp)
!=================================================================================================================
use mpas_stream_manager
+use mpas_derived_types, only: block_type
!input arguments:
type(dm_info),intent(in):: dminfo
type(MPAS_streamManager_type),intent(inout):: stream_manager
+ type(block_type),intent(in):: block
type(mpas_pool_type),intent(in):: mesh
type(mpas_pool_type),intent(in):: configs
type(MPAS_Clock_type),intent(in):: clock
@@ -158,7 +161,7 @@ subroutine physics_init(dminfo,stream_manager,clock,configs,mesh,diag,tend,tend_
type(MPAS_Time_Type):: currTime
logical:: init_done
- integer:: ierr,julday
+ integer:: ierr,julday
integer:: iCell,iLag,k
real(kind=RKIND):: layer_height
@@ -420,6 +423,8 @@ subroutine physics_init(dminfo,stream_manager,clock,configs,mesh,diag,tend,tend_
call init_lsm(dminfo,mesh,configs,diag_physics,sfc_input)
elseif(config_lsm_scheme .eq. 'sf_noahmp') then
call init_lsm_noahmp(configs,mesh,clock,diag_physics,diag_physics_noahmp,output_noahmp,sfc_input)
+ elseif(config_lsm_scheme .eq. 'sf_colm2024') then
+ call init_lsm_colm2024(dminfo,configs,block,diag_physics,sfc_input)
endif
endif
@@ -437,7 +442,7 @@ subroutine physics_init(dminfo,stream_manager,clock,configs,mesh,diag,tend,tend_
!initialization of longwave radiation processes: if we run the CAM radiation codes, the initia
!lization of the longwave and shortwave parameterizations is the same, and needs to be called
!only once:
- if(config_radt_lw_scheme.ne.'off') then
+ if(config_radt_lw_scheme.ne.'off') then
if(trim(config_radt_lw_scheme) .eq. 'cam_lw') then
if(.not. init_done) then
call init_radiation_lw(dminfo,configs,mesh,atm_input,diag,diag_physics,state,time_lev)
diff --git a/src/core_atmosphere/physics/mpas_atmphys_packages.F b/src/core_atmosphere/physics/mpas_atmphys_packages.F
index 5d32cb297e..228bb86243 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_packages.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_packages.F
@@ -41,6 +41,7 @@ function atmphys_setup_packages(configs,packages,iocontext) result(ierr)
logical,pointer:: cu_grell_freitas_in,cu_kain_fritsch_in,cu_ntiedtke_in
logical,pointer:: bl_mynn_in,bl_ysu_in
logical,pointer:: sf_noahmp_in
+ logical,pointer:: sf_colm2024_in
integer :: ierr
@@ -178,8 +179,11 @@ function atmphys_setup_packages(configs,packages,iocontext) result(ierr)
nullify(sf_noahmp_in)
call mpas_pool_get_package(packages,'sf_noahmp_inActive',sf_noahmp_in)
+ nullify(sf_colm2024_in)
+ call mpas_pool_get_package(packages,'sf_colm2024_inActive',sf_colm2024_in)
- if(.not.associated(sf_noahmp_in)) then
+ if(.not.associated(sf_noahmp_in) .or. &
+ .not.associated(sf_colm2024_in)) then
call mpas_log_write('====================================================================================',messageType=MPAS_LOG_ERR)
call mpas_log_write('* Error while setting up packages for land surface options in atmosphere core.' , messageType=MPAS_LOG_ERR)
call mpas_log_write('====================================================================================',messageType=MPAS_LOG_ERR)
@@ -190,8 +194,12 @@ function atmphys_setup_packages(configs,packages,iocontext) result(ierr)
if(config_lsm_scheme=='sf_noahmp') then
sf_noahmp_in = .true.
endif
+ if(config_lsm_scheme=='sf_colm2024') then
+ sf_colm2024_in = .true.
+ endif
call mpas_log_write(' sf_noahmp_in = $l', logicArgs=(/sf_noahmp_in/))
+ call mpas_log_write(' sf_colm2024_in = $l', logicArgs=(/sf_colm2024_in/))
call mpas_log_write('')
@@ -200,6 +208,3 @@ end function atmphys_setup_packages
!=================================================================================================================
end module mpas_atmphys_packages
!=================================================================================================================
-
-
-
diff --git a/src/core_atmosphere/physics/mpas_atmphys_sfc_diagnostics.F b/src/core_atmosphere/physics/mpas_atmphys_sfc_diagnostics.F
index 6e3a84c394..bf830df049 100644
--- a/src/core_atmosphere/physics/mpas_atmphys_sfc_diagnostics.F
+++ b/src/core_atmosphere/physics/mpas_atmphys_sfc_diagnostics.F
@@ -115,6 +115,11 @@ subroutine atmphys_sfc_diagnostics(configs,mesh,diag,diag_physics,sfc_input,outp
th2m(i) = t2m(i)*(P0/psfc(i))**rcp
enddo
+ case("sf_colm2024")
+ do i = 1,nCellsSolve
+ th2m(i) = t2m(i)*(P0/psfc(i))**rcp
+ enddo
+
case default
end select sf_select
@@ -125,4 +130,3 @@ end subroutine atmphys_sfc_diagnostics
!=================================================================================================================
end module mpas_atmphys_sfc_diagnostics
!=================================================================================================================
-
diff --git a/src/core_atmosphere/physics/physics_colm2024/.gitignore b/src/core_atmosphere/physics/physics_colm2024/.gitignore
new file mode 100644
index 0000000000..62b6d29223
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/.gitignore
@@ -0,0 +1,13 @@
+
+.DS_Store
+*.pyc
+__pycache__
+*.o
+*.mod
+.vscode
+.bld
+.mpas
+lib
+*.a
+*.x
+*.log
diff --git a/src/core_atmosphere/physics/physics_colm2024/README.md b/src/core_atmosphere/physics/physics_colm2024/README.md
new file mode 100644
index 0000000000..d08b93f20e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/README.md
@@ -0,0 +1,12 @@
+# MPAS-Embedded CoLM2024
+
+This directory contains the CoLM2024 land-surface physics used by
+MPAS-Atmosphere when `config_lsm_scheme = 'sf_colm2024'`.
+
+Build CoLM2024 through MPAS:
+
+- CMake: configure with `-DMPAS_COLM2024=ON`.
+- Make: build atmosphere with `COLM2024=true`.
+
+Standalone CoLM run cases, forcing namelist examples, and evaluation scripts
+are intentionally not kept in this embedded source tree.
diff --git a/src/core_atmosphere/physics/physics_colm2024/drivers/mpas/MOD_CoLM_MPAS_Interface.F90 b/src/core_atmosphere/physics/physics_colm2024/drivers/mpas/MOD_CoLM_MPAS_Interface.F90
new file mode 100644
index 0000000000..eb500330d0
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/drivers/mpas/MOD_CoLM_MPAS_Interface.F90
@@ -0,0 +1,1313 @@
+#include
+
+MODULE MOD_CoLM_MPAS_Interface
+
+ USE MOD_Precision
+ USE MOD_LandPatch, only: numpatch, landpatch, elm_patch
+ USE MOD_Vars_Global, only: spval, nl_soil, dz_soi
+ USE MOD_Vars_1DForcing, only: forc_pco2m, forc_po2m, forc_us, forc_vs, forc_t, forc_q, &
+ forc_prc, forc_prl, forc_rain, forc_snow, forc_psrf, forc_pbot, forc_sols, forc_soll, &
+ forc_solsd, forc_solld, forc_frl, forc_swrad, forc_hgt_u, forc_hgt_t, forc_hgt_q, &
+ forc_rhoair, forc_ozone, forc_hpbl, forc_aerdep
+#ifdef HYPERSPECTRAL
+ USE MOD_Vars_1DForcing, only: forc_solarin
+#endif
+ USE MOD_Vars_1DFluxes, only: oroflag, fsena, lfevpa, fevpa, fgrnd, rnof, rsur, rsub
+ USE MOD_Vars_TimeInvariants, only: patchmask
+ USE MOD_Vars_TimeVariables, only: t_grnd, tref, qref, qsfc, emis, z0m, alb, &
+ ldew, scv, snowdp, fsno, lai, t_soisno, wliq_soisno, wice_soisno
+ USE MOD_TimeManager, only: timestamp
+
+ IMPLICIT NONE
+ PRIVATE
+
+ PUBLIC :: colm_mpas_initialize_from_namelist
+ PUBLIC :: colm_mpas_finalize
+ PUBLIC :: colm_mpas_ready
+ PUBLIC :: colm_mpas_set_element_forcing
+ PUBLIC :: colm_mpas_step
+ PUBLIC :: colm_mpas_get_surface
+ PUBLIC :: colm_mpas_get_element_surface
+ PUBLIC :: colm_mpas_get_element_state
+
+ logical, save :: colm_mpas_initialized = .false.
+ character(len=256), save :: colm_mpas_casename = ''
+ character(len=256), save :: colm_mpas_dir_restart = ''
+ integer, save :: colm_mpas_lc_year = -1
+ integer, save :: colm_mpas_last_idate(3) = -1
+ integer, save :: colm_mpas_last_restart_idate(3) = -1
+ type(timestamp), save :: colm_mpas_ptstamp
+ type(timestamp), save :: colm_mpas_etstamp
+ logical, save :: colm_mpas_restart_ready = .false.
+
+ INTERFACE
+ SUBROUTINE CoLMDRIVER(idate,deltim,dolai,doalb,dosst,oro)
+ USE MOD_Precision
+ USE MOD_LandPatch, only: numpatch
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ logical, intent(in) :: dolai, doalb, dosst
+ real(r8), intent(inout) :: oro(numpatch)
+ END SUBROUTINE CoLMDRIVER
+ END INTERFACE
+
+CONTAINS
+
+ SUBROUTINE colm_mpas_initialize_from_namelist(nlfile, ierr, mpas_comm, mpas_cell_id, &
+ n_mpas_cells, cell_to_element)
+ USE MOD_Namelist, only: read_namelist, DEF_CASE_NAME, DEF_dir_landdata, &
+ DEF_dir_restart, DEF_LC_YEAR, DEF_simulation_time, DEF_USE_SNICAR, &
+ DEF_file_snowoptics, DEF_file_snowaging, DEF_forcing, DEF_Reservoir_Method, &
+ DEF_WRST_FREQ, DEF_HIST_FREQ, DEF_HIST_WriteBack
+ USE MOD_Vars_Global, only: Init_GlobalVars
+ USE MOD_SPMD_Task, only: spmd_init, p_is_root
+ USE MOD_Const_LC, only: Init_LC_Const
+ USE MOD_Const_PFT, only: Init_PFT_Const, rho_p, tau_p
+ USE MOD_TimeManager, only: initimetype, monthday2julian, adj2begin, adj2end
+ USE MOD_Block, only: gblock
+ USE MOD_Pixel, only: pixel
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandElm, only: landelm
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: landpft, numpft, map_patch_to_pft
+#endif
+ USE MOD_SrfdataRestart, only: mesh_load_from_file, pixelset_load_from_file
+ USE MOD_Vars_TimeInvariants, only: allocate_TimeInvariants, READ_TimeInvariants
+ USE MOD_Vars_TimeVariables, only: allocate_TimeVariables, READ_TimeVariables
+ USE MOD_Vars_1DForcing, only: allocate_1D_Forcing
+ USE MOD_Vars_1DFluxes, only: allocate_1D_Fluxes
+#ifdef GridRiverLakeFlow
+ USE MOD_Grid_RiverLakeNetwork, only: build_riverlake_network
+ USE MOD_Grid_Reservoir, only: reservoir_init
+ USE MOD_Grid_RiverLakeFlow, only: grid_riverlake_flow_init
+#endif
+#ifdef HYPERSPECTRAL
+ USE MOD_SnowSnicar_HiRes, only: SnowAge_init, SnowOptics_init
+ USE MOD_HighRes_Parameters, only: flux_frac_init, leaf_property_init, &
+ get_water_optical_properties
+#else
+ USE MOD_SnowSnicar, only: SnowAge_init, SnowOptics_init
+#endif
+ character(len=*), intent(in) :: nlfile
+ integer, intent(out) :: ierr
+ integer, intent(in), optional :: mpas_comm
+ integer, intent(in), optional :: mpas_cell_id(:)
+ integer, intent(in), optional :: n_mpas_cells
+ integer, intent(out), optional :: cell_to_element(:)
+
+ character(len=256) :: casename
+ character(len=256) :: dir_landdata
+ character(len=256) :: dir_restart
+ integer :: lc_year
+ integer :: sdate(3)
+ integer :: jdate(3)
+ integer :: s_julian
+ integer :: p_julian
+ integer :: e_julian
+ integer :: n_mpas
+ integer :: i
+ integer*8, allocatable :: mpas_cell_id_i8(:)
+
+ ierr = 1
+ IF (colm_mpas_initialized) THEN
+ ierr = 0
+ RETURN
+ ENDIF
+
+ IF (present(mpas_comm)) THEN
+ CALL spmd_init(mpas_comm)
+ ELSE
+ CALL spmd_init()
+ ENDIF
+
+ CALL read_namelist(trim(nlfile))
+#ifdef MPAS_EMBEDDED_COLM
+ CALL colm_mpas_check_embedded_io(ierr)
+ IF (ierr /= 0) RETURN
+#endif
+
+ casename = DEF_CASE_NAME
+ dir_landdata = DEF_dir_landdata
+ dir_restart = DEF_dir_restart
+ lc_year = DEF_LC_YEAR
+
+ CALL initimetype(DEF_simulation_time%greenwich)
+ CALL monthday2julian(DEF_simulation_time%start_year, DEF_simulation_time%start_month, &
+ DEF_simulation_time%start_day, s_julian)
+ CALL monthday2julian(DEF_simulation_time%spinup_year, DEF_simulation_time%spinup_month, &
+ DEF_simulation_time%spinup_day, p_julian)
+ CALL monthday2julian(DEF_simulation_time%end_year, DEF_simulation_time%end_month, &
+ DEF_simulation_time%end_day, e_julian)
+ sdate(1) = DEF_simulation_time%start_year
+ sdate(2) = s_julian
+ sdate(3) = DEF_simulation_time%start_sec
+
+ colm_mpas_casename = casename
+ colm_mpas_dir_restart = dir_restart
+ colm_mpas_lc_year = lc_year
+ colm_mpas_ptstamp%year = DEF_simulation_time%spinup_year
+ colm_mpas_ptstamp%day = p_julian
+ colm_mpas_ptstamp%sec = DEF_simulation_time%spinup_sec
+ colm_mpas_etstamp%year = DEF_simulation_time%end_year
+ colm_mpas_etstamp%day = e_julian
+ colm_mpas_etstamp%sec = DEF_simulation_time%end_sec
+ colm_mpas_last_idate(:) = -1
+ colm_mpas_last_restart_idate(:) = -1
+ colm_mpas_restart_ready = .true.
+
+ CALL Init_GlobalVars
+ CALL Init_LC_Const
+ CALL Init_PFT_Const
+
+ n_mpas = 0
+#ifdef MPAS_EMBEDDED_COLM
+ IF (.not. present(n_mpas_cells)) THEN
+ IF (p_is_root) write(*,'(A)') 'CoLM2024 MPAS embedded initialization requires MPAS-owned cell ids.'
+ RETURN
+ ENDIF
+#endif
+ IF (present(n_mpas_cells)) THEN
+ IF (.not. present(mpas_cell_id)) RETURN
+ IF (.not. present(cell_to_element)) RETURN
+
+ n_mpas = n_mpas_cells
+ IF (n_mpas < 0) RETURN
+ IF (size(mpas_cell_id) < n_mpas) RETURN
+ IF (size(cell_to_element) < n_mpas) RETURN
+
+ allocate(mpas_cell_id_i8(n_mpas))
+ DO i = 1, n_mpas
+ mpas_cell_id_i8(i) = int(mpas_cell_id(i), 8)
+ ENDDO
+ ENDIF
+
+ CALL pixel%load_from_file(dir_landdata)
+ CALL gblock%load_from_file(dir_landdata)
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL colm_mpas_claim_owned_blocks(dir_landdata, lc_year, mpas_cell_id_i8, n_mpas, ierr)
+ IF (ierr /= 0) RETURN
+
+ CALL mesh_load_from_file(dir_landdata, lc_year, subset_eindex=mpas_cell_id_i8)
+ CALL pixelset_load_from_file(dir_landdata, 'landelm', landelm, numelm, lc_year, &
+ subset_eindex=mpas_cell_id_i8)
+ CALL pixelset_load_from_file(dir_landdata, 'landpatch', landpatch, numpatch, lc_year, &
+ subset_eindex=mpas_cell_id_i8)
+#else
+ IF (n_mpas > 0) THEN
+ CALL colm_mpas_claim_owned_blocks(dir_landdata, lc_year, mpas_cell_id_i8, n_mpas, ierr)
+ IF (ierr /= 0) RETURN
+
+ CALL mesh_load_from_file(dir_landdata, lc_year, subset_eindex=mpas_cell_id_i8)
+ CALL pixelset_load_from_file(dir_landdata, 'landelm', landelm, numelm, lc_year, &
+ subset_eindex=mpas_cell_id_i8)
+ CALL pixelset_load_from_file(dir_landdata, 'landpatch', landpatch, numpatch, lc_year, &
+ subset_eindex=mpas_cell_id_i8)
+ ELSE
+ CALL mesh_load_from_file(dir_landdata, lc_year)
+ CALL pixelset_load_from_file(dir_landdata, 'landelm', landelm, numelm, lc_year)
+ CALL pixelset_load_from_file(dir_landdata, 'landpatch', landpatch, numpatch, lc_year)
+ ENDIF
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+#ifdef MPAS_EMBEDDED_COLM
+ CALL pixelset_load_from_file(dir_landdata, 'landpft', landpft, numpft, lc_year, &
+ subset_eindex=mpas_cell_id_i8)
+#else
+ IF (n_mpas > 0) THEN
+ CALL pixelset_load_from_file(dir_landdata, 'landpft', landpft, numpft, lc_year, &
+ subset_eindex=mpas_cell_id_i8)
+ ELSE
+ CALL pixelset_load_from_file(dir_landdata, 'landpft', landpft, numpft, lc_year)
+ ENDIF
+#endif
+#endif
+
+ IF (n_mpas > 0) THEN
+ CALL colm_mpas_restrict_to_mpas_cells(mpas_cell_id, n_mpas, cell_to_element, ierr)
+ IF (ierr /= 0) RETURN
+ ENDIF
+
+ CALL elm_patch%build(landelm, landpatch, use_frac = .true.)
+#ifdef MPAS_EMBEDDED_COLM
+ CALL colm_mpas_validate_element_patch_map(.false., ierr)
+ IF (ierr /= 0) RETURN
+#endif
+
+#ifdef GridRiverLakeFlow
+#ifdef MPAS_EMBEDDED_COLM
+ CALL colm_mpas_check_embedded_riverlake(ierr)
+ IF (ierr /= 0) RETURN
+#endif
+ CALL build_riverlake_network()
+ IF (DEF_Reservoir_Method > 0) CALL reservoir_init()
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL map_patch_to_pft
+#endif
+
+ CALL adj2end(sdate)
+ jdate = sdate
+ CALL adj2begin(jdate)
+
+ CALL allocate_TimeInvariants()
+ CALL READ_TimeInvariants(lc_year, casename, dir_restart)
+#ifdef MPAS_EMBEDDED_COLM
+ CALL colm_mpas_validate_element_patch_map(.true., ierr)
+ IF (ierr /= 0) RETURN
+#endif
+ CALL allocate_TimeVariables()
+ CALL READ_TimeVariables(jdate, lc_year, casename, dir_restart)
+
+ IF (DEF_USE_SNICAR) THEN
+ CALL SnowOptics_init(DEF_file_snowoptics)
+ CALL SnowAge_init(DEF_file_snowaging)
+ ENDIF
+
+#ifdef HYPERSPECTRAL
+ CALL flux_frac_init()
+ CALL leaf_property_init(rho_p, tau_p)
+ CALL get_water_optical_properties()
+#endif
+
+ CALL allocate_1D_Forcing()
+ CALL allocate_1D_Fluxes()
+ DEF_forcing%has_missing_value = .false.
+
+#ifdef GridRiverLakeFlow
+ CALL grid_riverlake_flow_init()
+#endif
+
+ colm_mpas_initialized = .true.
+ ierr = 0
+ END SUBROUTINE colm_mpas_initialize_from_namelist
+
+#if defined(GridRiverLakeFlow) && defined(MPAS_EMBEDDED_COLM)
+ SUBROUTINE colm_mpas_check_embedded_riverlake(ierr)
+ USE MOD_Namelist, only: DEF_USE_SEDIMENT
+ USE MOD_SPMD_Task, only: p_np_glb, p_is_root
+ integer, intent(out) :: ierr
+
+ ierr = 0
+ IF (DEF_USE_SEDIMENT) THEN
+ IF (p_is_root) THEN
+ write(*,'(A)') 'CoLM2024 MPAS embedded mode does not support GridRiverLakeSediment yet.'
+ write(*,'(A)') 'Set DEF_USE_SEDIMENT = .false. until sediment routing is migrated to MPAS-owned rank decomposition.'
+ ENDIF
+ ierr = 1
+ RETURN
+ ENDIF
+ IF (p_np_glb > 1 .and. p_is_root) THEN
+ write(*,'(A)') 'CoLM2024 MPAS embedded GridRiverLakeFlow uses MPAS communicator ranks for distributed routing.'
+ write(*,'(A)') 'Legacy CoLM MPI process pools and replicated full-river-network fallback are disabled.'
+ ENDIF
+ END SUBROUTINE colm_mpas_check_embedded_riverlake
+#endif
+
+ SUBROUTINE colm_mpas_check_embedded_io(ierr)
+ USE MOD_Namelist, only: DEF_HIST_FREQ, DEF_HIST_WriteBack, USE_SITE_HistWriteBack
+ USE MOD_SPMD_Task, only: p_is_root
+ integer, intent(out) :: ierr
+
+ ierr = 0
+ USE_SITE_HistWriteBack = .false.
+ IF ((trim(adjustl(DEF_HIST_FREQ)) /= 'none' .and. trim(adjustl(DEF_HIST_FREQ)) /= 'NONE') .or. &
+ DEF_HIST_WriteBack) THEN
+ IF (p_is_root) THEN
+ write(*,'(A)') 'CoLM2024 MPAS embedded mode currently writes fluxes through MPAS streams.'
+ write(*,'(A)') 'Disable CoLM DEF_HIST_FREQ/DEF_HIST_WriteBack; CoLM restart files remain supported for patch/PFT state.'
+ write(*,'(A)') 'CoLM USE_SITE_HistWriteBack is forced off in MPAS embedded mode.'
+ ENDIF
+ ierr = 1
+ ENDIF
+ END SUBROUTINE colm_mpas_check_embedded_io
+
+ SUBROUTINE colm_mpas_claim_owned_blocks(dir_landdata, lc_year, mpas_cell_id, n_mpas_cells, ierr)
+ USE MOD_Block, only: gblock, get_filename_block
+ USE MOD_SPMD_Task, only: p_iam_glb
+ USE MOD_NetCDFSerial, only: ncio_read_serial
+ USE MOD_Utils, only: quicksort, find_in_sorted_list1
+ character(len=*), intent(in) :: dir_landdata
+ integer, intent(in) :: lc_year
+ integer*8, intent(in) :: mpas_cell_id(:)
+ integer, intent(in) :: n_mpas_cells
+ integer, intent(out) :: ierr
+
+ logical, allocatable :: keep_block(:,:)
+ logical, allocatable :: found_element(:)
+ logical :: fexists
+ integer :: i
+ integer :: ie
+ integer :: iblk
+ integer :: jblk
+ integer :: iblkme
+ integer :: match
+ character(len=256) :: filename
+ character(len=256) :: fileblock
+ character(len=256) :: cyear
+ integer, allocatable :: order(:)
+ integer*8, allocatable :: elmindx(:)
+ integer*8, allocatable :: sorted_cell_id(:)
+
+ ierr = 1
+ IF (n_mpas_cells < 0) RETURN
+ IF (.not. allocated(gblock%pio)) RETURN
+ IF (.not. allocated(gblock%lon_w)) RETURN
+ IF (.not. allocated(gblock%lat_s)) RETURN
+ IF (size(mpas_cell_id) < n_mpas_cells) RETURN
+
+ allocate(keep_block(gblock%nxblk, gblock%nyblk))
+ keep_block = .false.
+
+ IF (n_mpas_cells == 0) THEN
+ gblock%pio(:,:) = -1
+ IF (allocated(gblock%xblkme)) deallocate(gblock%xblkme)
+ IF (allocated(gblock%yblkme)) deallocate(gblock%yblkme)
+ gblock%nblkme = 0
+ deallocate(keep_block)
+ ierr = 0
+ RETURN
+ ENDIF
+
+ allocate(found_element(n_mpas_cells))
+ allocate(sorted_cell_id(n_mpas_cells))
+ found_element = .false.
+ sorted_cell_id = mpas_cell_id(1:n_mpas_cells)
+
+ IF (n_mpas_cells > 1) THEN
+ allocate(order(n_mpas_cells))
+ order = (/ (i, i = 1, n_mpas_cells) /)
+ CALL quicksort(n_mpas_cells, sorted_cell_id, order)
+ deallocate(order)
+
+ DO i = 2, n_mpas_cells
+ IF (sorted_cell_id(i) == sorted_cell_id(i-1)) THEN
+ write(*,'(A,I0,A,I0)') 'CoLM2024 MPAS embedded duplicate cell/eindex on rank ', &
+ p_iam_glb, ': ', sorted_cell_id(i)
+ deallocate(keep_block, found_element, sorted_cell_id)
+ RETURN
+ ENDIF
+ ENDDO
+ ENDIF
+
+ write(cyear,'(i4.4)') lc_year
+ filename = trim(dir_landdata) // '/mesh/' // trim(cyear) // '/mesh.nc'
+
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ CALL get_filename_block(filename, iblk, jblk, fileblock)
+ inquire(file=trim(fileblock), exist=fexists)
+ IF (.not. fexists) CYCLE
+
+ CALL ncio_read_serial(fileblock, 'elmindex', elmindx)
+ DO ie = 1, size(elmindx)
+ match = find_in_sorted_list1(elmindx(ie), n_mpas_cells, sorted_cell_id)
+ IF (match > 0) THEN
+ keep_block(iblk,jblk) = .true.
+ found_element(match) = .true.
+ ENDIF
+ ENDDO
+ IF (allocated(elmindx)) deallocate(elmindx)
+ ENDDO
+ ENDDO
+
+ IF (count(found_element) /= n_mpas_cells) THEN
+ DO i = 1, n_mpas_cells
+ IF (.not. found_element(i)) THEN
+ write(*,'(A,I0,A,I0)') 'CoLM2024 MPAS embedded mesh is missing cell/eindex on rank ', &
+ p_iam_glb, ': ', sorted_cell_id(i)
+ EXIT
+ ENDIF
+ ENDDO
+ deallocate(keep_block, found_element, sorted_cell_id)
+ RETURN
+ ENDIF
+
+ gblock%pio(:,:) = -1
+ WHERE (keep_block)
+ gblock%pio = p_iam_glb
+ END WHERE
+
+ IF (allocated(gblock%xblkme)) deallocate(gblock%xblkme)
+ IF (allocated(gblock%yblkme)) deallocate(gblock%yblkme)
+ gblock%nblkme = count(keep_block)
+ IF (gblock%nblkme < 1) THEN
+ write(*,'(A,I0)') 'CoLM2024 MPAS embedded found no local mesh blocks for rank ', p_iam_glb
+ deallocate(keep_block, found_element, sorted_cell_id)
+ RETURN
+ ENDIF
+
+ allocate(gblock%xblkme(gblock%nblkme))
+ allocate(gblock%yblkme(gblock%nblkme))
+ iblkme = 0
+ DO iblk = 1, gblock%nxblk
+ DO jblk = 1, gblock%nyblk
+ IF (keep_block(iblk,jblk)) THEN
+ iblkme = iblkme + 1
+ gblock%xblkme(iblkme) = iblk
+ gblock%yblkme(iblkme) = jblk
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate(keep_block, found_element, sorted_cell_id)
+ ierr = 0
+ END SUBROUTINE colm_mpas_claim_owned_blocks
+
+ SUBROUTINE colm_mpas_finalize(ierr)
+#ifdef GridRiverLakeFlow
+ USE MOD_Grid_RiverLakeFlow, only: grid_riverlake_flow_final
+#endif
+ USE MOD_SPMD_Task, only: spmd_exit
+ integer, intent(out) :: ierr
+
+ ierr = 0
+ IF (.not. colm_mpas_initialized) RETURN
+
+ IF (colm_mpas_last_idate(1) > 0) THEN
+ CALL colm_mpas_write_restart_if_due(colm_mpas_last_idate, 0._r8, .true., ierr)
+ IF (ierr /= 0) RETURN
+ ENDIF
+
+#ifdef GridRiverLakeFlow
+ CALL grid_riverlake_flow_final()
+#endif
+
+ CALL spmd_exit()
+ colm_mpas_initialized = .false.
+ colm_mpas_restart_ready = .false.
+ END SUBROUTINE colm_mpas_finalize
+
+ SUBROUTINE colm_mpas_restrict_to_mpas_cells(mpas_cell_id, n_mpas_cells, cell_to_element, ierr)
+ USE MOD_LandElm, only: landelm
+ USE MOD_LandPatch, only: landpatch, numpatch
+ USE MOD_Mesh, only: numelm
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: landpft, numpft
+#endif
+ integer, intent(in) :: mpas_cell_id(:)
+ integer, intent(in) :: n_mpas_cells
+ integer, intent(out) :: cell_to_element(:)
+ integer, intent(out) :: ierr
+
+ logical, allocatable :: keep_elm(:)
+ logical, allocatable :: keep_patch(:)
+ logical, allocatable :: keep_pft(:)
+ integer, allocatable :: old_to_new(:)
+ integer, allocatable :: old_element_for_cell(:)
+ integer :: i
+ integer :: old_element
+ integer :: packed_count
+
+ ierr = 1
+ IF (n_mpas_cells < 1) RETURN
+ IF (numelm < 1) RETURN
+ IF (landelm%nset < 1) RETURN
+
+ allocate(keep_elm(numelm))
+ allocate(old_to_new(numelm))
+ allocate(old_element_for_cell(n_mpas_cells))
+
+ keep_elm = .false.
+ old_to_new = 0
+
+ DO i = 1, n_mpas_cells
+ CALL colm_mpas_find_element_by_eindex(mpas_cell_id(i), old_element)
+ IF (old_element <= 0 .or. old_element > numelm) RETURN
+
+ old_element_for_cell(i) = old_element
+ keep_elm(old_element) = .true.
+ ENDDO
+
+ packed_count = 0
+ DO i = 1, numelm
+ IF (keep_elm(i)) THEN
+ packed_count = packed_count + 1
+ old_to_new(i) = packed_count
+ ENDIF
+ ENDDO
+ IF (packed_count /= n_mpas_cells) RETURN
+
+ CALL colm_mpas_pack_mesh(keep_elm, old_to_new)
+ CALL landelm%pset_pack(keep_elm, packed_count)
+ CALL colm_mpas_remap_pixelset_ielm(landelm, old_to_new, ierr)
+ IF (ierr /= 0) RETURN
+
+ IF (landpatch%nset > 0) THEN
+ allocate(keep_patch(landpatch%nset))
+ DO i = 1, landpatch%nset
+ keep_patch(i) = landpatch%ielm(i) >= 1 .and. landpatch%ielm(i) <= size(old_to_new)
+ IF (keep_patch(i)) keep_patch(i) = old_to_new(landpatch%ielm(i)) > 0
+ ENDDO
+ CALL landpatch%pset_pack(keep_patch, numpatch)
+ CALL colm_mpas_remap_pixelset_ielm(landpatch, old_to_new, ierr)
+ deallocate(keep_patch)
+ IF (ierr /= 0) RETURN
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (landpft%nset > 0) THEN
+ allocate(keep_pft(landpft%nset))
+ DO i = 1, landpft%nset
+ keep_pft(i) = landpft%ielm(i) >= 1 .and. landpft%ielm(i) <= size(old_to_new)
+ IF (keep_pft(i)) keep_pft(i) = old_to_new(landpft%ielm(i)) > 0
+ ENDDO
+ CALL landpft%pset_pack(keep_pft, numpft)
+ CALL colm_mpas_remap_pixelset_ielm(landpft, old_to_new, ierr)
+ deallocate(keep_pft)
+ IF (ierr /= 0) RETURN
+ ENDIF
+#endif
+
+ DO i = 1, n_mpas_cells
+ cell_to_element(i) = old_to_new(old_element_for_cell(i))
+ IF (cell_to_element(i) <= 0) RETURN
+ ENDDO
+
+ ierr = 0
+ END SUBROUTINE colm_mpas_restrict_to_mpas_cells
+
+ SUBROUTINE colm_mpas_pack_mesh(keep_elm, old_to_new)
+ USE MOD_Mesh, only: irregular_elm_type, mesh, numelm, copy_elm
+ logical, intent(in) :: keep_elm(:)
+ integer, intent(in) :: old_to_new(:)
+
+ type(irregular_elm_type), allocatable :: packed_mesh(:)
+ integer :: old_elm
+ integer :: new_elm
+ integer :: packed_count
+
+ packed_count = count(keep_elm)
+ allocate(packed_mesh(packed_count))
+
+ DO old_elm = 1, size(keep_elm)
+ IF (.not. keep_elm(old_elm)) CYCLE
+ new_elm = old_to_new(old_elm)
+ CALL copy_elm(mesh(old_elm), packed_mesh(new_elm))
+ ENDDO
+
+ IF (allocated(mesh)) deallocate(mesh)
+ CALL move_alloc(packed_mesh, mesh)
+ numelm = packed_count
+ END SUBROUTINE colm_mpas_pack_mesh
+
+ SUBROUTINE colm_mpas_remap_pixelset_ielm(pixelset, old_to_new, ierr)
+ USE MOD_Pixelset, only: pixelset_type
+ type(pixelset_type), intent(inout) :: pixelset
+ integer, intent(in) :: old_to_new(:)
+ integer, intent(out) :: ierr
+
+ integer :: iset
+ integer :: old_elm
+
+ ierr = 1
+ DO iset = 1, pixelset%nset
+ old_elm = pixelset%ielm(iset)
+ IF (old_elm < 1 .or. old_elm > size(old_to_new)) RETURN
+ IF (old_to_new(old_elm) <= 0) RETURN
+ pixelset%ielm(iset) = old_to_new(old_elm)
+ ENDDO
+
+ ierr = 0
+ END SUBROUTINE colm_mpas_remap_pixelset_ielm
+
+ SUBROUTINE colm_mpas_find_element_by_eindex(cell_id, element)
+ USE MOD_LandElm, only: landelm
+ integer, intent(in) :: cell_id
+ integer, intent(out) :: element
+
+ integer :: i
+ integer :: hits
+ integer*8 :: cell_id_i8
+
+ element = 0
+ hits = 0
+ cell_id_i8 = cell_id
+ DO i = 1, landelm%nset
+ IF (landelm%eindex(i) == cell_id_i8) THEN
+ hits = hits + 1
+ element = i
+ ENDIF
+ ENDDO
+ IF (hits /= 1) element = 0
+ END SUBROUTINE colm_mpas_find_element_by_eindex
+
+ SUBROUTINE colm_mpas_validate_element_patch_map(require_active_patch, ierr)
+ USE MOD_LandElm, only: landelm
+ USE MOD_SPMD_Task, only: p_iam_glb
+ logical, intent(in) :: require_active_patch
+ integer, intent(out) :: ierr
+
+ integer :: element
+ integer :: patch
+ integer :: istt
+ integer :: iend
+ integer :: local_missing
+ integer :: first_missing
+ logical :: has_patch
+
+ ierr = 1
+ IF (.not. allocated(elm_patch%substt)) RETURN
+ IF (.not. allocated(elm_patch%subend)) RETURN
+ IF (.not. allocated(elm_patch%subfrc)) RETURN
+ IF (size(elm_patch%substt) < landelm%nset) RETURN
+ IF (size(elm_patch%subend) < landelm%nset) RETURN
+ IF (size(elm_patch%subfrc) < numpatch) RETURN
+ IF (require_active_patch .and. numpatch > 0 .and. .not. allocated(patchmask)) RETURN
+ IF (require_active_patch .and. numpatch > 0) THEN
+ IF (size(patchmask) < numpatch) RETURN
+ ENDIF
+
+ local_missing = 0
+ first_missing = -1
+
+ DO element = 1, landelm%nset
+ istt = elm_patch%substt(element)
+ iend = elm_patch%subend(element)
+ has_patch = .false.
+
+ IF (istt >= 1 .and. iend >= istt .and. iend <= numpatch) THEN
+ DO patch = istt, iend
+ IF (patch < 1 .or. patch > numpatch) CYCLE
+ IF (require_active_patch .and. allocated(patchmask)) THEN
+ IF (patchmask(patch)) has_patch = .true.
+ ELSE
+ has_patch = .true.
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (.not. has_patch) THEN
+ local_missing = local_missing + 1
+ IF (first_missing < 0) first_missing = element
+ ENDIF
+ ENDDO
+
+ IF (local_missing > 0) THEN
+ IF (first_missing > 0 .and. first_missing <= landelm%nset) THEN
+ write(*,'(A,I0,A,I0,A,I0,A,I0)') &
+ 'CoLM2024 MPAS embedded landdata is missing usable patch coverage on rank ', &
+ p_iam_glb, ': ', local_missing, ' element(s); first local element ', &
+ first_missing, ', eindex ', landelm%eindex(first_missing)
+ ELSE
+ write(*,'(A,I0,A,I0)') &
+ 'CoLM2024 MPAS embedded landdata is missing usable patch coverage on rank ', &
+ p_iam_glb, ': ', local_missing
+ ENDIF
+ RETURN
+ ENDIF
+
+ ierr = 0
+ END SUBROUTINE colm_mpas_validate_element_patch_map
+
+ SUBROUTINE colm_mpas_ready(ready, patch_count)
+ logical, intent(out) :: ready
+ integer, intent(out), optional :: patch_count
+
+ IF (numpatch == 0) THEN
+ ready = colm_mpas_initialized .and. allocated(elm_patch%substt) .and. &
+ allocated(elm_patch%subend) .and. allocated(elm_patch%subfrc)
+ ELSE
+ ready = allocated(forc_t) .and. allocated(oroflag) .and. allocated(fsena) .and. allocated(t_grnd) &
+ .and. allocated(elm_patch%substt) .and. allocated(elm_patch%subend) .and. allocated(elm_patch%subfrc)
+ ENDIF
+ IF (present(patch_count)) THEN
+ IF (allocated(oroflag)) THEN
+ patch_count = size(oroflag)
+ ELSE
+ patch_count = 0
+ ENDIF
+ ENDIF
+ END SUBROUTINE colm_mpas_ready
+
+ SUBROUTINE colm_mpas_set_forcing(patch, pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow, &
+ psrf, pbot, sols, soll, solsd, solld, frl, hgt_u, hgt_t, hgt_q, &
+ rhoair, hpbl, aerdep, oro, ozone, ierr)
+ integer, intent(in) :: patch
+ real(r8), intent(in) :: pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow
+ real(r8), intent(in) :: psrf, pbot, sols, soll, solsd, solld, frl
+ real(r8), intent(in) :: hgt_u, hgt_t, hgt_q, rhoair, hpbl
+ real(r8), intent(in) :: aerdep(14)
+ real(r8), intent(in), optional :: oro
+ real(r8), intent(in), optional :: ozone
+ integer, intent(out) :: ierr
+
+ ierr = 1
+ IF (.not. allocated(forc_t)) RETURN
+ IF (patch < 1 .or. patch > size(forc_t)) RETURN
+
+ forc_pco2m(patch) = pco2m
+ forc_po2m (patch) = po2m
+ forc_us (patch) = us
+ forc_vs (patch) = vs
+ forc_t (patch) = tair
+ forc_q (patch) = qair
+ forc_prc (patch) = prc
+ forc_prl (patch) = prl
+ forc_rain (patch) = rain
+ forc_snow (patch) = snow
+ forc_psrf (patch) = psrf
+ forc_pbot (patch) = pbot
+ forc_sols (patch) = sols
+ forc_soll (patch) = soll
+ forc_solsd(patch) = solsd
+ forc_solld(patch) = solld
+ forc_frl (patch) = frl
+ forc_swrad(patch) = sols + soll + solsd + solld
+#ifdef HYPERSPECTRAL
+ forc_solarin(patch) = forc_swrad(patch)
+#endif
+ forc_hgt_u(patch) = hgt_u
+ forc_hgt_t(patch) = hgt_t
+ forc_hgt_q(patch) = hgt_q
+ forc_rhoair(patch) = rhoair
+ forc_hpbl (patch) = hpbl
+ forc_aerdep(:,patch) = aerdep(:)
+ IF (present(oro) .and. allocated(oroflag)) oroflag(patch) = oro
+ IF (present(ozone)) THEN
+ forc_ozone(patch) = ozone
+ ELSE
+ forc_ozone(patch) = 0._r8
+ ENDIF
+ ierr = 0
+ END SUBROUTINE colm_mpas_set_forcing
+
+ SUBROUTINE colm_mpas_set_element_forcing(element, pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow, &
+ psrf, pbot, sols, soll, solsd, solld, frl, hgt_u, hgt_t, hgt_q, &
+ rhoair, hpbl, aerdep, oro, ozone, ierr)
+ integer, intent(in) :: element
+ real(r8), intent(in) :: pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow
+ real(r8), intent(in) :: psrf, pbot, sols, soll, solsd, solld, frl
+ real(r8), intent(in) :: hgt_u, hgt_t, hgt_q, rhoair, hpbl
+ real(r8), intent(in) :: aerdep(14)
+ real(r8), intent(in), optional :: oro
+ real(r8), intent(in), optional :: ozone
+ integer, intent(out) :: ierr
+
+ integer :: patch
+ integer :: patch_ierr
+ integer :: istt
+ integer :: iend
+ logical :: did_set
+
+ ierr = 1
+ IF (.not. allocated(elm_patch%substt)) RETURN
+ IF (.not. allocated(elm_patch%subend)) RETURN
+ IF (.not. allocated(elm_patch%subfrc)) RETURN
+ IF (element < 1 .or. element > size(elm_patch%substt)) RETURN
+
+ istt = elm_patch%substt(element)
+ iend = elm_patch%subend(element)
+ IF (istt < 1 .or. iend < istt) RETURN
+
+ did_set = .false.
+ DO patch = istt, iend
+ IF (patch < 1 .or. patch > numpatch) CYCLE
+ IF (allocated(patchmask)) THEN
+ IF (.not. patchmask(patch)) CYCLE
+ ENDIF
+ IF (present(oro) .and. present(ozone)) THEN
+ CALL colm_mpas_set_forcing(patch, pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow, &
+ psrf, pbot, sols, soll, solsd, solld, frl, hgt_u, hgt_t, hgt_q, &
+ rhoair, hpbl, aerdep, oro=oro, ozone=ozone, ierr=patch_ierr)
+ ELSEIF (present(oro)) THEN
+ CALL colm_mpas_set_forcing(patch, pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow, &
+ psrf, pbot, sols, soll, solsd, solld, frl, hgt_u, hgt_t, hgt_q, &
+ rhoair, hpbl, aerdep, oro=oro, ierr=patch_ierr)
+ ELSEIF (present(ozone)) THEN
+ CALL colm_mpas_set_forcing(patch, pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow, &
+ psrf, pbot, sols, soll, solsd, solld, frl, hgt_u, hgt_t, hgt_q, &
+ rhoair, hpbl, aerdep, ozone=ozone, ierr=patch_ierr)
+ ELSE
+ CALL colm_mpas_set_forcing(patch, pco2m, po2m, us, vs, tair, qair, prc, prl, rain, snow, &
+ psrf, pbot, sols, soll, solsd, solld, frl, hgt_u, hgt_t, hgt_q, &
+ rhoair, hpbl, aerdep, ierr=patch_ierr)
+ ENDIF
+ IF (patch_ierr /= 0) RETURN
+ did_set = .true.
+ ENDDO
+
+ IF (did_set) ierr = 0
+ END SUBROUTINE colm_mpas_set_element_forcing
+
+ SUBROUTINE colm_mpas_step(idate, deltim, dolai, doalb, dosst, ierr)
+#ifdef GridRiverLakeFlow
+ USE MOD_Grid_RiverLakeFlow, only: grid_riverlake_flow
+#endif
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ logical, intent(in) :: dolai, doalb, dosst
+ integer, intent(out) :: ierr
+
+ logical :: ready
+
+ CALL colm_mpas_ready(ready)
+ ierr = 1
+ IF (.not. ready) RETURN
+
+ IF (numpatch > 0) CALL CoLMDRIVER(idate, deltim, dolai, doalb, dosst, oroflag)
+#ifdef GridRiverLakeFlow
+ CALL grid_riverlake_flow(idate(1), deltim)
+#endif
+ colm_mpas_last_idate(:) = idate(:)
+ CALL colm_mpas_write_restart_if_due(idate, deltim, .false., ierr)
+ IF (ierr /= 0) RETURN
+ ierr = 0
+ END SUBROUTINE colm_mpas_step
+
+ SUBROUTINE colm_mpas_write_restart_if_due(idate, deltim, force, ierr)
+ USE MOD_Namelist, only: DEF_WRST_FREQ
+ USE MOD_SPMD_Task, only: p_is_root
+ USE MOD_TimeManager, only: adj2begin
+ USE MOD_Vars_TimeVariables, only: save_to_restart, WRITE_TimeVariables
+#ifdef GridRiverLakeFlow
+ USE MOD_Grid_RiverLakeTimeVars, only: WRITE_GridRiverLakeTimeVars
+#endif
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ logical, intent(in) :: force
+ integer, intent(out) :: ierr
+
+ type(timestamp) :: itstamp
+ integer :: write_idate(3)
+ integer :: write_lc_year
+ logical :: should_write
+ character(len=256) :: wrst_freq
+#if defined(GridRiverLakeFlow) && !defined(MPAS_EMBEDDED_COLM)
+ character(len=14) :: cdate
+ character(len=256) :: cyear
+ character(len=256) :: file_restart
+#endif
+
+ ierr = 0
+ IF (.not. colm_mpas_restart_ready) RETURN
+
+ write_idate(:) = idate(:)
+ CALL adj2begin(write_idate)
+
+ IF (all(write_idate == colm_mpas_last_restart_idate)) RETURN
+
+ itstamp%year = idate(1)
+ itstamp%day = idate(2)
+ itstamp%sec = idate(3)
+
+ wrst_freq = trim(adjustl(DEF_WRST_FREQ))
+ IF (wrst_freq == '' .or. wrst_freq == 'none' .or. wrst_freq == 'NONE') THEN
+ should_write = force .or. colm_mpas_timestamp_reached(itstamp, colm_mpas_etstamp)
+ ELSEIF (force) THEN
+ should_write = .true.
+ ELSE
+ should_write = save_to_restart(idate, deltim, itstamp, colm_mpas_ptstamp, colm_mpas_etstamp)
+ ENDIF
+ IF (.not. should_write) RETURN
+
+#ifdef LULCC
+ IF (write_idate(1) >= 2000) THEN
+ write_lc_year = write_idate(1)
+ ELSE
+ write_lc_year = (write_idate(1) / 5) * 5
+ ENDIF
+#else
+ write_lc_year = colm_mpas_lc_year
+#endif
+
+#ifdef GridRiverLakeFlow
+#ifdef MPAS_EMBEDDED_COLM
+ CALL WRITE_TimeVariables(write_idate, write_lc_year, colm_mpas_casename, colm_mpas_dir_restart)
+#else
+ IF (numpatch == 0) THEN
+ write(cyear,'(i4.4)') write_lc_year
+ write(cdate,'(i4.4,"-",i3.3,"-",i5.5)') write_idate(1), write_idate(2), write_idate(3)
+ IF (p_is_root) CALL system('mkdir -p ' // trim(colm_mpas_dir_restart)//'/'//trim(cdate))
+ file_restart = trim(colm_mpas_dir_restart)// '/'//trim(cdate)//'/' // &
+ trim(colm_mpas_casename) //'_restart_gridriver_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_GridRiverLakeTimeVars(file_restart)
+ ELSE
+ CALL WRITE_TimeVariables(write_idate, write_lc_year, colm_mpas_casename, colm_mpas_dir_restart)
+ ENDIF
+#endif
+#else
+#ifdef MPAS_EMBEDDED_COLM
+ CALL WRITE_TimeVariables(write_idate, write_lc_year, colm_mpas_casename, colm_mpas_dir_restart)
+#else
+ IF (numpatch > 0) CALL WRITE_TimeVariables(write_idate, write_lc_year, colm_mpas_casename, colm_mpas_dir_restart)
+#endif
+#endif
+ colm_mpas_last_restart_idate(:) = write_idate(:)
+ END SUBROUTINE colm_mpas_write_restart_if_due
+
+ LOGICAL FUNCTION colm_mpas_timestamp_reached(tstamp, target)
+ type(timestamp), intent(in) :: tstamp
+ type(timestamp), intent(in) :: target
+
+ colm_mpas_timestamp_reached = .false.
+ IF (tstamp%year > target%year) THEN
+ colm_mpas_timestamp_reached = .true.
+ ELSEIF (tstamp%year == target%year .and. tstamp%day > target%day) THEN
+ colm_mpas_timestamp_reached = .true.
+ ELSEIF (tstamp%year == target%year .and. tstamp%day == target%day .and. tstamp%sec >= target%sec) THEN
+ colm_mpas_timestamp_reached = .true.
+ ENDIF
+ END FUNCTION colm_mpas_timestamp_reached
+
+ SUBROUTINE colm_mpas_get_surface(patch, sensible, latent, evaporation, ground_heat, runoff, &
+ surface_runoff, subsurface_runoff, skin_temp, t2m, q2m, &
+ surface_humidity, emissivity, roughness, albedo, ierr)
+ integer, intent(in) :: patch
+ real(r8), intent(out) :: sensible, latent, evaporation, ground_heat, runoff
+ real(r8), intent(out) :: surface_runoff, subsurface_runoff, skin_temp, t2m, q2m
+ real(r8), intent(out) :: surface_humidity
+ real(r8), intent(out) :: emissivity, roughness, albedo
+ integer, intent(out) :: ierr
+
+ ierr = 1
+ sensible = spval
+ latent = spval
+ evaporation = spval
+ ground_heat = spval
+ runoff = spval
+ surface_runoff = spval
+ subsurface_runoff = spval
+ skin_temp = spval
+ t2m = spval
+ q2m = spval
+ surface_humidity = spval
+ emissivity = spval
+ roughness = spval
+ albedo = spval
+
+ IF (.not. allocated(fsena)) RETURN
+ IF (.not. allocated(lfevpa)) RETURN
+ IF (.not. allocated(fevpa)) RETURN
+ IF (.not. allocated(fgrnd)) RETURN
+ IF (.not. allocated(rnof)) RETURN
+ IF (.not. allocated(rsur)) RETURN
+ IF (.not. allocated(rsub)) RETURN
+ IF (.not. allocated(t_grnd)) RETURN
+ IF (.not. allocated(tref)) RETURN
+ IF (.not. allocated(qref)) RETURN
+ IF (.not. allocated(emis)) RETURN
+ IF (.not. allocated(z0m)) RETURN
+ IF (patch < 1) RETURN
+ IF (patch > size(fsena)) RETURN
+ IF (patch > size(lfevpa)) RETURN
+ IF (patch > size(fevpa)) RETURN
+ IF (patch > size(fgrnd)) RETURN
+ IF (patch > size(rnof)) RETURN
+ IF (patch > size(rsur)) RETURN
+ IF (patch > size(rsub)) RETURN
+ IF (patch > size(t_grnd)) RETURN
+ IF (patch > size(tref)) RETURN
+ IF (patch > size(qref)) RETURN
+ IF (patch > size(emis)) RETURN
+ IF (patch > size(z0m)) RETURN
+
+ sensible = fsena(patch)
+ latent = lfevpa(patch)
+ evaporation = fevpa(patch)
+ ground_heat = fgrnd(patch)
+ runoff = rnof(patch)
+ surface_runoff = rsur(patch)
+ subsurface_runoff = rsub(patch)
+ skin_temp = t_grnd(patch)
+ t2m = tref(patch)
+ q2m = qref(patch)
+ surface_humidity = qref(patch)
+ IF (allocated(qsfc)) THEN
+ IF (patch <= size(qsfc)) THEN
+ IF (qsfc(patch) > 0._r8 .and. qsfc(patch) < 1._r8) surface_humidity = qsfc(patch)
+ ENDIF
+ ENDIF
+ emissivity = emis(patch)
+ roughness = z0m(patch)
+ IF (allocated(alb)) THEN
+ ! ponytail: bulk albedo average; replace with band/beam mapping when MPAS consumes CoLM spectral albedo.
+ IF (patch <= size(alb,3)) albedo = sum(alb(:,:,patch)) / real(size(alb(:,:,patch)), r8)
+ ENDIF
+ ierr = 0
+ END SUBROUTINE colm_mpas_get_surface
+
+ SUBROUTINE colm_mpas_get_element_surface(element, sensible, latent, evaporation, ground_heat, runoff, &
+ surface_runoff, subsurface_runoff, skin_temp, t2m, q2m, &
+ surface_humidity, emissivity, roughness, albedo, ierr)
+ integer, intent(in) :: element
+ real(r8), intent(out) :: sensible, latent, evaporation, ground_heat, runoff
+ real(r8), intent(out) :: surface_runoff, subsurface_runoff, skin_temp, t2m, q2m
+ real(r8), intent(out) :: surface_humidity
+ real(r8), intent(out) :: emissivity, roughness, albedo
+ integer, intent(out) :: ierr
+
+ integer :: patch
+ integer :: patch_ierr
+ integer :: istt
+ integer :: iend
+ real(r8) :: wt
+ real(r8) :: sumwt
+ real(r8) :: albedo_sum
+ real(r8) :: albedo_wt
+ real(r8) :: patch_sensible, patch_latent, patch_evaporation, patch_ground_heat
+ real(r8) :: patch_runoff, patch_surface_runoff, patch_subsurface_runoff
+ real(r8) :: patch_skin_temp, patch_t2m, patch_q2m, patch_surface_humidity
+ real(r8) :: patch_emissivity, patch_roughness, patch_albedo
+
+ ierr = 1
+ sensible = spval
+ latent = spval
+ evaporation = spval
+ ground_heat = spval
+ runoff = spval
+ surface_runoff = spval
+ subsurface_runoff = spval
+ skin_temp = spval
+ t2m = spval
+ q2m = spval
+ surface_humidity = spval
+ emissivity = spval
+ roughness = spval
+ albedo = spval
+
+ IF (.not. allocated(elm_patch%substt)) RETURN
+ IF (.not. allocated(elm_patch%subend)) RETURN
+ IF (.not. allocated(elm_patch%subfrc)) RETURN
+ IF (element < 1 .or. element > size(elm_patch%substt)) RETURN
+
+ istt = elm_patch%substt(element)
+ iend = elm_patch%subend(element)
+ IF (istt < 1 .or. iend < istt) RETURN
+
+ sensible = 0._r8
+ latent = 0._r8
+ evaporation = 0._r8
+ ground_heat = 0._r8
+ runoff = 0._r8
+ surface_runoff = 0._r8
+ subsurface_runoff = 0._r8
+ skin_temp = 0._r8
+ t2m = 0._r8
+ q2m = 0._r8
+ surface_humidity = 0._r8
+ emissivity = 0._r8
+ roughness = 0._r8
+ albedo_sum = 0._r8
+ albedo_wt = 0._r8
+ sumwt = 0._r8
+
+ DO patch = istt, iend
+ IF (patch < 1 .or. patch > numpatch) THEN
+ WRITE(*,*) 'Error: CoLM2024 element surface references invalid patch:', element, patch, numpatch
+ RETURN
+ ENDIF
+ IF (allocated(patchmask)) THEN
+ IF (.not. patchmask(patch)) CYCLE
+ ENDIF
+ wt = elm_patch%subfrc(patch)
+ IF (wt <= 0._r8) CYCLE
+ CALL colm_mpas_get_surface(patch, patch_sensible, patch_latent, patch_evaporation, patch_ground_heat, &
+ patch_runoff, patch_surface_runoff, patch_subsurface_runoff, &
+ patch_skin_temp, patch_t2m, patch_q2m, patch_surface_humidity, &
+ patch_emissivity, patch_roughness, patch_albedo, patch_ierr)
+ IF (patch_ierr /= 0) THEN
+ WRITE(*,*) 'Error: failed to retrieve CoLM2024 patch surface:', element, patch, patch_ierr
+ RETURN
+ ENDIF
+
+ sumwt = sumwt + wt
+ sensible = sensible + wt * patch_sensible
+ latent = latent + wt * patch_latent
+ evaporation = evaporation + wt * patch_evaporation
+ ground_heat = ground_heat + wt * patch_ground_heat
+ runoff = runoff + wt * patch_runoff
+ surface_runoff = surface_runoff + wt * patch_surface_runoff
+ subsurface_runoff = subsurface_runoff + wt * patch_subsurface_runoff
+ skin_temp = skin_temp + wt * patch_skin_temp
+ t2m = t2m + wt * patch_t2m
+ q2m = q2m + wt * patch_q2m
+ surface_humidity = surface_humidity + wt * patch_surface_humidity
+ emissivity = emissivity + wt * patch_emissivity
+ roughness = roughness + wt * patch_roughness
+ IF (patch_albedo > 0._r8 .and. patch_albedo < 1._r8) THEN
+ albedo_sum = albedo_sum + wt * patch_albedo
+ albedo_wt = albedo_wt + wt
+ ENDIF
+ ENDDO
+
+ IF (sumwt <= 0._r8) THEN
+ sensible = spval
+ latent = spval
+ evaporation = spval
+ ground_heat = spval
+ runoff = spval
+ surface_runoff = spval
+ subsurface_runoff = spval
+ skin_temp = spval
+ t2m = spval
+ q2m = spval
+ surface_humidity = spval
+ emissivity = spval
+ roughness = spval
+ RETURN
+ ENDIF
+
+ sensible = sensible / sumwt
+ latent = latent / sumwt
+ evaporation = evaporation / sumwt
+ ground_heat = ground_heat / sumwt
+ runoff = runoff / sumwt
+ surface_runoff = surface_runoff / sumwt
+ subsurface_runoff = subsurface_runoff / sumwt
+ skin_temp = skin_temp / sumwt
+ t2m = t2m / sumwt
+ q2m = q2m / sumwt
+ surface_humidity = surface_humidity / sumwt
+ emissivity = emissivity / sumwt
+ roughness = roughness / sumwt
+ IF (albedo_wt > 0._r8) albedo = albedo_sum / albedo_wt
+ ierr = 0
+ END SUBROUTINE colm_mpas_get_element_surface
+
+ SUBROUTINE colm_mpas_get_element_state(element, canopy_water, snow_water, snow_depth, snow_cover, &
+ leaf_area_index, soil_liquid, soil_moisture, soil_temperature, ierr)
+ integer, intent(in) :: element
+ real(r8), intent(out) :: canopy_water, snow_water, snow_depth, snow_cover, leaf_area_index
+ real(r8), intent(out) :: soil_liquid(:), soil_moisture(:), soil_temperature(:)
+ integer, intent(out) :: ierr
+
+ integer :: patch
+ integer :: istt
+ integer :: iend
+ integer :: n
+ integer :: nlev
+ real(r8) :: wt
+ real(r8) :: sumwt
+ real(r8) :: bad_value
+ real(r8) :: patch_canopy_water
+ real(r8) :: patch_snow_water
+ real(r8) :: patch_snow_depth
+ real(r8) :: patch_snow_cover
+ real(r8) :: patch_lai
+ real(r8) :: patch_liquid
+ real(r8) :: patch_moisture
+ real(r8) :: soil_wt(size(soil_liquid))
+
+ ierr = 1
+ canopy_water = spval
+ snow_water = spval
+ snow_depth = spval
+ snow_cover = spval
+ leaf_area_index = spval
+ soil_liquid(:) = spval
+ soil_moisture(:) = spval
+ soil_temperature(:) = spval
+
+ nlev = min(size(soil_liquid), size(soil_moisture), size(soil_temperature), nl_soil)
+ IF (nlev < 1) RETURN
+ IF (.not. allocated(elm_patch%substt)) RETURN
+ IF (.not. allocated(elm_patch%subend)) RETURN
+ IF (.not. allocated(elm_patch%subfrc)) RETURN
+ IF (.not. allocated(ldew)) RETURN
+ IF (.not. allocated(scv)) RETURN
+ IF (.not. allocated(snowdp)) RETURN
+ IF (.not. allocated(fsno)) RETURN
+ IF (.not. allocated(lai)) RETURN
+ IF (.not. allocated(t_soisno)) RETURN
+ IF (.not. allocated(wliq_soisno)) RETURN
+ IF (.not. allocated(wice_soisno)) RETURN
+ IF (element < 1 .or. element > size(elm_patch%substt)) RETURN
+
+ istt = elm_patch%substt(element)
+ iend = elm_patch%subend(element)
+ IF (istt < 1 .or. iend < istt) RETURN
+
+ bad_value = 0.5_r8 * abs(spval)
+ canopy_water = 0._r8
+ snow_water = 0._r8
+ snow_depth = 0._r8
+ snow_cover = 0._r8
+ leaf_area_index = 0._r8
+ soil_liquid(:) = 0._r8
+ soil_moisture(:) = 0._r8
+ soil_temperature(:) = 0._r8
+ soil_wt(:) = 0._r8
+ sumwt = 0._r8
+
+ DO patch = istt, iend
+ IF (patch < 1 .or. patch > numpatch) THEN
+ WRITE(*,*) 'Error: CoLM2024 element state references invalid patch:', element, patch, numpatch
+ RETURN
+ ENDIF
+ IF (allocated(patchmask)) THEN
+ IF (.not. patchmask(patch)) CYCLE
+ ENDIF
+ wt = elm_patch%subfrc(patch)
+ IF (wt <= 0._r8) CYCLE
+
+ patch_canopy_water = ldew(patch)
+ IF (abs(patch_canopy_water) >= bad_value) patch_canopy_water = 0._r8
+ patch_snow_water = scv(patch)
+ IF (abs(patch_snow_water) >= bad_value) patch_snow_water = 0._r8
+ patch_snow_depth = snowdp(patch)
+ IF (abs(patch_snow_depth) >= bad_value) patch_snow_depth = 0._r8
+ patch_snow_cover = fsno(patch)
+ IF (abs(patch_snow_cover) >= bad_value) patch_snow_cover = 0._r8
+ patch_lai = lai(patch)
+ IF (abs(patch_lai) >= bad_value) patch_lai = 0._r8
+
+ sumwt = sumwt + wt
+ canopy_water = canopy_water + wt * max(0._r8, patch_canopy_water)
+ snow_water = snow_water + wt * max(0._r8, patch_snow_water)
+ snow_depth = snow_depth + wt * max(0._r8, patch_snow_depth)
+ snow_cover = snow_cover + wt * max(0._r8, min(1._r8, patch_snow_cover))
+ leaf_area_index = leaf_area_index + wt * max(0._r8, patch_lai)
+
+ DO n = 1, nlev
+ IF (n < lbound(t_soisno, 1) .or. n > ubound(t_soisno, 1)) CYCLE
+ IF (dz_soi(n) <= 0._r8) CYCLE
+ IF (abs(t_soisno(n, patch)) >= bad_value) CYCLE
+ IF (abs(wliq_soisno(n, patch)) >= bad_value) CYCLE
+ IF (abs(wice_soisno(n, patch)) >= bad_value) CYCLE
+
+ patch_liquid = max(0._r8, wliq_soisno(n, patch) / (1000._r8 * dz_soi(n)))
+ patch_moisture = max(0._r8, (wliq_soisno(n, patch) + wice_soisno(n, patch)) / (1000._r8 * dz_soi(n)))
+ soil_liquid(n) = soil_liquid(n) + wt * min(1._r8, patch_liquid)
+ soil_moisture(n) = soil_moisture(n) + wt * min(1._r8, patch_moisture)
+ soil_temperature(n) = soil_temperature(n) + wt * t_soisno(n, patch)
+ soil_wt(n) = soil_wt(n) + wt
+ ENDDO
+ ENDDO
+
+ IF (sumwt <= 0._r8) THEN
+ canopy_water = spval
+ snow_water = spval
+ snow_depth = spval
+ snow_cover = spval
+ leaf_area_index = spval
+ soil_liquid(:) = spval
+ soil_moisture(:) = spval
+ soil_temperature(:) = spval
+ RETURN
+ ENDIF
+
+ canopy_water = canopy_water / sumwt
+ snow_water = snow_water / sumwt
+ snow_depth = snow_depth / sumwt
+ snow_cover = snow_cover / sumwt
+ leaf_area_index = leaf_area_index / sumwt
+
+ DO n = 1, nlev
+ IF (soil_wt(n) > 0._r8) THEN
+ soil_liquid(n) = soil_liquid(n) / soil_wt(n)
+ soil_moisture(n) = soil_moisture(n) / soil_wt(n)
+ soil_temperature(n) = soil_temperature(n) / soil_wt(n)
+ ELSE
+ soil_liquid(n) = spval
+ soil_moisture(n) = spval
+ soil_temperature(n) = spval
+ ENDIF
+ ENDDO
+
+ ierr = 0
+ END SUBROUTINE colm_mpas_get_element_state
+
+ END MODULE MOD_CoLM_MPAS_Interface
diff --git a/src/core_atmosphere/physics/physics_colm2024/include/define.h b/src/core_atmosphere/physics/physics_colm2024/include/define.h
new file mode 100644
index 0000000000..d3f5da4b34
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/include/define.h
@@ -0,0 +1,115 @@
+! 1. Spatial structure:
+! Select one of the following options.
+#define GRIDBASED
+#undef CATCHMENT
+#undef UNSTRUCTURED
+#undef SinglePoint
+
+! 2. Land subgrid type classification:
+! Select one of the following options.
+#undef LULC_USGS
+#undef LULC_IGBP
+#undef LULC_IGBP_PFT
+#define LULC_IGBP_PC
+
+! 2.1 3D Urban model (put it temporarily here):
+#undef URBAN_MODEL
+! Dependence: only LULC_IGBP subgrid type for
+! single point URBAN_MODEL right now.
+#if (defined URBAN_MODEL && defined SinglePoint)
+#define LULC_IGBP
+#undef LULC_USGS
+#undef LULC_IGBP_PFT
+#undef LULC_IGBP_PC
+#endif
+
+! 3. If defined, debug information is output.
+#define CoLMDEBUG
+! 3.1 If defined, range of variables is checked.
+#define RangeCheck
+! 3.1 If defined, surface data in vector is mapped to gridded data for checking.
+#undef SrfdataDiag
+
+! 4. CoLM uses MPI collectives through MPAS-owned communicators. The legacy
+! CoLM process-pool decomposition is disabled in MOD_SPMD_Task.
+#define USEMPI
+
+! 5. Hydrological process options.
+! 5.1 Two soil hydraulic models can be used.
+#undef Campbell_SOIL_MODEL
+#define vanGenuchten_Mualem_SOIL_MODEL
+! 5.2 If defined, lateral flow is modeled.
+#define CatchLateralFlow
+! Conflicts :
+#ifndef CATCHMENT
+#undef CatchLateralFlow
+#endif
+
+! 6. Embedded grid river-lake routing.
+#define GridRiverLakeFlow
+! Conflicts :
+#if (defined CATCHMENT || defined SinglePoint)
+#undef GridRiverLakeFlow
+#endif
+
+#undef GridRiverLakeSediment
+#if (!defined GridRiverLakeFlow)
+#undef GridRiverLakeSediment
+#endif
+
+! 7. If defined, BGC model is used.
+#undef BGC
+
+! Conflicts : only used when LULC_IGBP_PFT is defined.
+#ifndef LULC_IGBP_PFT
+#ifndef LULC_IGBP_PC
+#undef BGC
+#endif
+#endif
+! 7.1 If defined, CROP model is used
+#undef CROP
+! Conflicts : only used when BGC is defined
+#ifndef BGC
+#undef CROP
+#endif
+
+! 8. If defined, open Land use and land cover change mode.
+#undef LULCC
+
+! 9. If defined, data assimilation is used.
+#undef DataAssimilation
+#if (defined DataAssimilation)
+#define LULC_IGBP
+#undef LULC_USGS
+#undef LULC_IGBP_PFT
+#undef LULC_IGBP_PC
+#endif
+
+! 10. Interface to AI model.
+#undef USESplitAI
+
+! 11. External lake models.
+#undef EXTERNAL_LAKE
+
+! 12. Hyperspectral scheme.
+#define HYPERSPECTRAL
+
+! MPAS embeds CoLM as a local land-surface physics package on each MPAS rank.
+! Reusing the legacy CoLM process split inside MPAS leaves some
+! ranks without patch forcing/flux arrays, so the embedded library keeps CoLM
+! land state on MPAS-owned cells. MPAS also supplies broadband shortwave forcing.
+#define MPAS_EMBEDDED_COLM
+#ifdef MPAS_EMBEDDED_COLM
+#ifndef USEMPI
+#define USEMPI
+#endif
+#undef HYPERSPECTRAL
+#undef CoLMDEBUG
+! CoLM range diagnostics still assume the standalone role split.
+#undef RangeCheck
+#endif
+
+#undef COLM_PARALLEL
+#if defined(USEMPI)
+#define COLM_PARALLEL
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNAnnualUpdate.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNAnnualUpdate.F90
new file mode 100644
index 0000000000..8eff998fda
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNAnnualUpdate.F90
@@ -0,0 +1,81 @@
+#include
+
+#ifdef BGC
+MODULE MOD_BGC_CNAnnualUpdate
+
+!------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! On the radiation time step, update annual summation variables mostly for phenology modules:
+! annsum_potential_gpp : annual sum of potential gpp of last year is used to calculate the available
+! retranslocation N
+! annmax_retransn : maximum of retranslocation N pool size of last year in a whole year, used to
+! calculate the available rentranslocation N
+! annavg_tref : annual 2m air temperature of last year is used to calculate onset phenology
+! annsum_npp : annual NPP of last year is used to calculate the allocation partition.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! !REFERENCES:
+! Lawrence, D.M., Fisher, R.A., Koven, C.D., Oleson, K.W., Swenson, S.C., Bonan, G., Collier, N.,
+! Ghimire, B., van Kampenhout, L., Kennedy, D. and Kluzek, E., 2019.
+! The Community Land Model version 5: Description of new features, benchmarking,
+! and impact of forcing uncertainty. Journal of Advances in Modeling Earth Systems, 11(12), 4245-4287.
+
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+
+ USE MOD_Vars_PFTimeVariables, only: &
+ tempsum_potential_gpp_p, tempmax_retransn_p, tempavg_tref_p, tempsum_npp_p, &
+ annsum_potential_gpp_p , annmax_retransn_p , annavg_tref_p , annsum_npp_p
+
+ USE MOD_TimeManager, only: isendofyear
+ USE MOD_Precision
+
+ IMPLICIT NONE
+
+ PUBLIC CNAnnualUpdate
+
+CONTAINS
+
+ SUBROUTINE CNAnnualUpdate(i,ps,pe,deltim,idate)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: idate(3) ! date (year, days of year, seconds of the day)
+
+ !!LOCAL VARIABLES:
+ integer m
+
+
+ IF (isendofyear(idate,deltim)) THEN
+
+ DO m = ps, pe
+ ! update annual plant ndemand accumulator
+ annsum_potential_gpp_p(m) = tempsum_potential_gpp_p(m)
+ tempsum_potential_gpp_p(m) = 0._r8
+
+ ! update annual total N retranslocation accumulator
+ annmax_retransn_p(m) = tempmax_retransn_p(m)
+ tempmax_retransn_p(m) = 0._r8
+
+ ! update annual average 2m air temperature accumulator
+ annavg_tref_p(m) = tempavg_tref_p(m)
+ tempavg_tref_p(m) = 0._r8
+
+ ! update annual NPP accumulator, convert to annual total
+ annsum_npp_p(m) = tempsum_npp_p(m) * deltim
+ tempsum_npp_p(m) = 0._r8
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE CNAnnualUpdate
+
+END MODULE MOD_BGC_CNAnnualUpdate
+
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNBalanceCheck.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNBalanceCheck.F90
new file mode 100644
index 0000000000..df66ec3151
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNBalanceCheck.F90
@@ -0,0 +1,273 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_CNBalanceCheck
+
+!--------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! C and N balance check module.
+! run sequential: BeginCNBalance(i) -> all CN cycle processes ->CBalanceCheck & NBalanceCheck
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_NITRIF
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ sminn, col_endcb, col_begcb, totcolc, col_endnb, col_begnb, totcoln, &
+ col_vegbegcb, totvegc, ctrunc_veg, col_vegbegnb, totvegn, ntrunc_veg, &
+ col_soilbegcb, totsomc, totlitc, totcwdc, ctrunc_soil, &
+ col_soilbegnb, totsomn, totlitn, totcwdn, ntrunc_soil, col_sminnbegnb, &
+ col_vegendcb, col_vegendnb, col_soilendcb, col_soilendnb, col_sminnendnb
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ gpp, er, ar, decomp_hr, fire_closs, hrv_xsmrpool_to_atm, wood_harvestc, grainc_to_cropprodc, &
+ som_c_leached, ndep_to_sminn, nfix_to_sminn, supplement_to_sminn, ffix_to_sminn, &
+ fert_to_sminn, soyfixn_to_sminn, denit, fire_nloss, wood_harvestn, grainn_to_cropprodn, &
+ sminn_leached, f_n2o_nit, smin_no3_leached, smin_no3_runoff, som_n_leached, sminn_to_plant
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ leafc_p, frootc_p, livestemc_p, deadstemc_p, livecrootc_p, deadcrootc_p, &
+ leafc_storage_p, frootc_storage_p, livestemc_storage_p, &
+ deadstemc_storage_p, livecrootc_storage_p, deadcrootc_storage_p, gresp_storage_p, &
+ leafc_xfer_p, frootc_xfer_p, livestemc_xfer_p, &
+ deadstemc_xfer_p, livecrootc_xfer_p, deadcrootc_xfer_p, gresp_xfer_p, xsmrpool_p, &
+ grainc_p, grainc_storage_p, grainc_xfer_p, ctrunc_p, totvegc_p, cropseedc_deficit_p
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ grainc_to_food_p, &
+ leafc_to_litter_p , frootc_to_litter_p , livestemc_to_litter_p, &
+ m_leafc_to_litter_p , m_leafc_storage_to_litter_p , m_leafc_xfer_to_litter_p , &
+ m_frootc_to_litter_p , m_frootc_storage_to_litter_p , m_frootc_xfer_to_litter_p , &
+ m_livestemc_to_litter_p , m_livestemc_storage_to_litter_p , m_livestemc_xfer_to_litter_p , &
+ m_deadstemc_to_litter_p , m_deadstemc_storage_to_litter_p , m_deadstemc_xfer_to_litter_p , &
+ m_livecrootc_to_litter_p , m_livecrootc_storage_to_litter_p, m_livecrootc_xfer_to_litter_p, &
+ m_deadcrootc_to_litter_p , m_deadcrootc_storage_to_litter_p, m_deadcrootc_xfer_to_litter_p, &
+ m_gresp_storage_to_litter_p, m_gresp_xfer_to_litter_p
+ USE MOD_SPMD_Task
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ gap_mortality_to_met_c, gap_mortality_to_cel_c, gap_mortality_to_lig_c, gap_mortality_to_cwdc , &
+ phenology_to_met_c, phenology_to_cel_c, phenology_to_lig_c
+
+ IMPLICIT NONE
+
+ PUBLIC BeginCNBalance
+ PUBLIC CBalanceCheck
+ PUBLIC NBalanceCheck
+
+CONTAINS
+
+ SUBROUTINE BeginCNBalance(i)
+
+ ! !DESCRIPTION:
+ ! BeginCNBalance SUBROUTINE stores initial C and N pool size at begining of each time step, which is
+ ! further used in CN balance check.
+ !
+ ! !ORIGINAL:
+ ! The Community Land Model version 5.0 (CLM5.0)
+ !
+ ! !REVISION:
+ ! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+
+ col_begcb(i) = totcolc(i)
+ col_begnb(i) = totcoln(i)
+
+ col_vegbegcb(i) = totvegc(i) + ctrunc_veg(i)
+ col_vegbegnb(i) = totvegn(i) + ntrunc_veg(i)
+
+ col_soilbegcb(i) = totsomc(i) + totlitc(i) + totcwdc(i) + ctrunc_soil(i)
+ col_soilbegnb(i) = totsomn(i) + totlitn(i) + totcwdn(i) + ntrunc_soil(i)
+
+ col_sminnbegnb(i) = sminn(i)
+
+ END SUBROUTINE BeginCNBalance
+
+ SUBROUTINE CBalanceCheck(i,ps,pe,nl_soil,dz_soi,deltim,dlat,dlon)
+
+ ! !DESCRIPTION:
+ ! CBalanceCheck tests the carbon balance of each time step, which meet C balance equation:
+ ! col_endcb - col_begcb = (col_cinputs - col_coutputs)*deltim
+ !
+ ! !ORIGINAL:
+ ! The Community Land Model version 5.0 (CLM5.0)
+ !
+ ! !REVISION:
+ ! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! end pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dlat ! latitude (degree)
+ real(r8),intent(in) :: dlon ! longitude (degree)
+ integer, intent(in) :: nl_soil
+ real(r8),intent(in) :: dz_soi(nl_soil)
+
+!Local variables
+ real(r8),parameter :: cerror = 1.e-7_r8
+ real(r8) :: col_cinputs, col_coutputs, col_errcb
+ real(r8) :: veg_to_litter, phen_to_litter, gap_leaf_to_litter, gap_froot_to_litter, &
+ gap_livestem_to_litter, gap_deadstem_to_litter, gap_livecroot_to_litter, &
+ gap_deadcroot_to_litter, gap_gresp_to_litter, gap_veg_to_litter, phen_veg_to_litter
+ integer m
+
+ col_endcb(i) = totcolc(i)
+ col_vegendcb(i) = totvegc(i) + ctrunc_veg(i)
+ col_soilendcb(i) = totsomc(i) + totlitc(i) + totcwdc(i) + ctrunc_soil(i)
+
+ col_cinputs = gpp(i)
+
+ col_coutputs = er(i) + fire_closs(i) + hrv_xsmrpool_to_atm(i) &
+ + wood_harvestc(i) + grainc_to_cropprodc(i) - som_c_leached(i)
+
+ col_errcb = (col_cinputs - col_coutputs)*deltim - &
+ (col_endcb(i) - col_begcb(i))
+
+ phen_to_litter = sum(pftfrac(ps:pe)*(leafc_to_litter_p (ps:pe) + frootc_to_litter_p(ps:pe) &
+ + livestemc_to_litter_p(ps:pe)))
+ gap_leaf_to_litter = sum(pftfrac(ps:pe)*(m_leafc_to_litter_p (ps:pe) + m_leafc_storage_to_litter_p(ps:pe) &
+ + m_leafc_xfer_to_litter_p(ps:pe)))
+ gap_froot_to_litter = sum(pftfrac(ps:pe)*(m_frootc_to_litter_p (ps:pe) + m_frootc_storage_to_litter_p(ps:pe)&
+ + m_frootc_xfer_to_litter_p(ps:pe)))
+ gap_livestem_to_litter = sum(pftfrac(ps:pe)*(m_livestemc_to_litter_p (ps:pe) + m_livestemc_storage_to_litter_p(ps:pe)&
+ + m_livestemc_xfer_to_litter_p(ps:pe)))
+ gap_deadstem_to_litter = sum(pftfrac(ps:pe)*(m_deadstemc_to_litter_p (ps:pe) + m_deadstemc_storage_to_litter_p(ps:pe)&
+ + m_deadstemc_xfer_to_litter_p(ps:pe)))
+ gap_livecroot_to_litter = sum(pftfrac(ps:pe)*(m_livecrootc_to_litter_p(ps:pe) + m_livecrootc_storage_to_litter_p(ps:pe)&
+ + m_livecrootc_xfer_to_litter_p(ps:pe)))
+ gap_deadcroot_to_litter = sum(pftfrac(ps:pe)*(m_deadcrootc_to_litter_p(ps:pe) + m_deadcrootc_storage_to_litter_p(ps:pe)&
+ + m_deadcrootc_xfer_to_litter_p(ps:pe)))
+ gap_gresp_to_litter = sum(pftfrac(ps:pe)*(m_gresp_storage_to_litter_p(ps:pe)+m_gresp_xfer_to_litter_p(ps:pe)))
+
+ gap_veg_to_litter = sum((gap_mortality_to_met_c(1:nl_soil,i) + gap_mortality_to_cel_c(1:nl_soil,i)&
+ + gap_mortality_to_lig_c(1:nl_soil,i) + gap_mortality_to_cwdc (1:nl_soil,i))*dz_soi(1:nl_soil))
+ phen_veg_to_litter = sum((phenology_to_met_c (1:nl_soil,i) + phenology_to_cel_c (1:nl_soil,i)&
+ + phenology_to_lig_c (1:nl_soil,i))*dz_soi(1:nl_soil))
+ veg_to_litter = phen_to_litter + gap_leaf_to_litter + gap_froot_to_litter + gap_livestem_to_litter &
+ + gap_deadstem_to_litter + gap_livecroot_to_litter + gap_deadcroot_to_litter + gap_gresp_to_litter
+
+ IF(abs(col_errcb) > cerror) THEN
+ write(*,*)'column cbalance error = ', col_errcb, i, p_iam_glb
+ write(*,*)'Latdeg,Londeg=' , dlat, dlon
+ write(*,*)'begcb = ',col_begcb(i)
+ write(*,*)'endcb = ',col_endcb(i)
+ write(*,*)'delta store = ',col_endcb(i)-col_begcb(i)
+ write(*,*)'delta veg = ',col_vegendcb(i) - col_vegbegcb(i),totvegc(i),col_vegendcb(i),col_vegbegcb(i)
+ write(*,*)'delta soil = ',col_soilendcb(i) - col_soilbegcb(i),totsomc(i),totlitc(i),totcwdc(i),col_soilendcb(i),col_soilbegcb(i)
+ DO m = ps, pe
+ write(*,*)'m=',m,pftclass(m)
+ write(*,*)'vegc,leafc = ',leafc_p(m)+leafc_storage_p(m)+leafc_xfer_p(m)
+ write(*,*)'vegc,frootc = ',frootc_p(m)+frootc_storage_p(m)+frootc_xfer_p(m)
+ write(*,*)'vegc,livestemc = ',livestemc_p(m)+livestemc_storage_p(m)+livestemc_xfer_p(m)
+ write(*,*)'vegc,deadstemc = ',deadstemc_p(m)+deadstemc_storage_p(m)+deadstemc_xfer_p(m)
+ write(*,*)'vegc,livecrootc = ',livecrootc_p(m)+livecrootc_storage_p(m)+livecrootc_xfer_p(m)
+ write(*,*)'vegc,deadcrootc = ',deadcrootc_p(m)+deadcrootc_storage_p(m)+deadcrootc_xfer_p(m)
+ write(*,*)'grainc = ',grainc_p(m)+grainc_storage_p(m)+grainc_xfer_p(m)+cropseedc_deficit_p(m)
+ write(*,*)'growth respiration c = ',gresp_storage_p(m)+gresp_xfer_p(m)+xsmrpool_p(m)
+ ENDDO
+ write(*,*)'--------veg output to litter-------------'
+ write(*,*)'veg to soil and litter = ', veg_to_litter, phen_to_litter, gap_leaf_to_litter, gap_froot_to_litter, gap_livestem_to_litter, &
+ gap_deadstem_to_litter, gap_livecroot_to_litter, gap_deadcroot_to_litter , gap_gresp_to_litter
+ write(*,*)'--------liter and soil input from veg----'
+ write(*,*)'input to soil and litter = ',gap_veg_to_litter + phen_veg_to_litter
+ write(*,*)'phen, gap to litter = ',phen_veg_to_litter, gap_veg_to_litter
+ write(*,*)'--- Inputs ---'
+ write(*,*)'gpp = ',gpp(i)*deltim
+ write(*,*)'--- Outputs ---'
+ write(*,*)'er = ',er(i)*deltim
+ write(*,*)'ar = ',ar(i)*deltim
+ write(*,*)'decomp_hr = ',decomp_hr(i)*deltim
+ write(*,*)'fire_closs = ',fire_closs(i)*deltim
+ write(*,*)'col_hrv_xsmrpool_to_atm = ',hrv_xsmrpool_to_atm(i)*deltim
+ write(*,*)'wood_harvestc = ',wood_harvestc(i)*deltim
+ write(*,*)'grainc_to_cropprodc = ',grainc_to_cropprodc(i)*deltim, grainc_to_food_p(ps)*deltim
+ write(*,*)'-1*som_c_leached = ',som_c_leached(i)*deltim
+#ifdef USEMPI
+ CALL mpi_abort (p_comm_glb, p_err)
+#else
+ CALL abort
+#endif
+ ENDIF
+
+ END SUBROUTINE CBalanceCheck
+
+ SUBROUTINE NBalanceCheck(i,ps,pe,deltim,dlat,dlon)
+
+! !DESCRIPTION:
+! NBalanceCheck tests the carbon balance of each time step, which meet N balance equation:
+! col_endnb - col_begnb = (col_ninputs - col_noutputs)*deltim
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i,ps,pe ! patch index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dlat ! latitude (degree)
+ real(r8),intent(in) :: dlon ! longitude (degree)
+
+!Local variables
+ real(r8),parameter :: nerror = 1.e-7_r8
+ real(r8) :: col_ninputs, col_noutputs, col_errnb
+
+ col_endnb(i) = totcoln(i)
+ col_vegendnb(i) = totvegn(i) + ntrunc_veg(i)
+ col_soilendnb(i) = totsomn(i) + totlitn(i) + totcwdn(i) + ntrunc_soil(i)
+ col_sminnendnb(i) = sminn(i)
+
+ col_ninputs = ndep_to_sminn(i) + nfix_to_sminn(i) + supplement_to_sminn(i)
+
+ col_ninputs = col_ninputs + fert_to_sminn(i) + soyfixn_to_sminn(i)
+
+ col_noutputs = denit(i) + fire_nloss(i) + wood_harvestn(i) + grainn_to_cropprodn(i)
+
+ IF(DEF_USE_NITRIF)THEN
+ col_noutputs = col_noutputs + f_n2o_nit(i) + smin_no3_leached(i) + smin_no3_runoff(i)
+ ELSE
+ col_noutputs = col_noutputs + sminn_leached(i)
+ ENDIF
+
+ col_noutputs = col_noutputs - som_n_leached(i)
+ col_errnb =(col_ninputs - col_noutputs)*deltim - (col_endnb(i) - col_begnb(i))
+
+ IF (abs(col_errnb) > nerror) THEN !
+ write(*,*)'column nbalance error = ',col_errnb, i, p_iam_glb
+ write(*,*)'Latdeg,Londeg = ',dlat, dlon
+ write(*,*)'begnb = ',col_begnb(i)
+ write(*,*)'endnb = ',col_endnb(i)
+ write(*,*)'delta store = ',col_endnb(i)-col_begnb(i)
+ write(*,*)'delta veg = ',col_vegendnb(i)-col_vegbegnb(i)
+ write(*,*)'delta soil = ',col_soilendnb(i)-col_soilbegnb(i)
+ write(*,*)'delta sminn = ',col_sminnendnb(i)-col_sminnbegnb(i)
+ write(*,*)'smin_to_plant = ',sminn_to_plant(i)*deltim
+ write(*,*)'input mass = ',col_ninputs*deltim
+ write(*,*)'output mass = ',col_noutputs*deltim,f_n2o_nit(i)*deltim,smin_no3_leached(i)*deltim,&
+ smin_no3_runoff(i)*deltim, denit(i)*deltim,fire_nloss(i)*deltim,&
+ ( wood_harvestn(i) + grainn_to_cropprodn(i))*deltim
+ write(*,*)'net flux = ',(col_ninputs-col_noutputs)*deltim
+ write(*,*)'inputs,ffix,nfix,ndep = ',ffix_to_sminn(i)*deltim,nfix_to_sminn(i)*deltim,ndep_to_sminn(i)*deltim,&
+ fert_to_sminn(i)*deltim,soyfixn_to_sminn(i)*deltim
+ IF(DEF_USE_NITRIF)THEN
+ write(*,*)'outputs,leached,runoff,denit = ',smin_no3_leached(i)*deltim, smin_no3_runoff(i)*deltim,f_n2o_nit(i)*deltim
+ ELSE
+ write(*,*)'outputs,leached,denit,fire,harvest,som_n_leached',&
+ sminn_leached(i)*deltim,denit(i)*deltim,fire_nloss(i)*deltim,&
+ (wood_harvestn(i)+grainn_to_cropprodn(i))*deltim, - som_n_leached(i)
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_abort (p_comm_glb, p_err)
+#else
+ CALL abort
+#endif
+ ENDIF
+
+ END SUBROUTINE NBalanceCheck
+
+END MODULE MOD_BGC_CNBalanceCheck
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate1.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate1.F90
new file mode 100644
index 0000000000..24f7bd6731
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate1.F90
@@ -0,0 +1,493 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_CNCStateUpdate1
+
+!-------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! First updates in vegetation and soil carbon. The major updates are included in bgc_CNCStateUpdate1Mod
+! 1. Update phenology-associated veg and soil C pool size changes, including plant growth
+! 2. Update decomposition-associated soil C pool size changes
+! 3. Record the accumulated C transfers associated to phenology and decomposition for semi-analytic spinup
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record the accumulated phenology-associated C transfer for veg and soil C semi-analytic spinup
+! 3) Record the accumulated decomposition-associated C transfer for soil C semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+ USE MOD_Const_PFT, only: woody
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+! bgc constants
+ donor_pool, receiver_pool, i_met_lit, i_cel_lit, i_lig_lit, i_cwd, i_soil1, i_soil2, i_soil3
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ I_met_c_vr_acc, I_cel_c_vr_acc, I_lig_c_vr_acc, &
+ AKX_met_to_soil1_c_vr_acc , AKX_cel_to_soil1_c_vr_acc , AKX_lig_to_soil2_c_vr_acc , AKX_soil1_to_soil2_c_vr_acc, &
+ AKX_cwd_to_cel_c_vr_acc , AKX_cwd_to_lig_c_vr_acc , AKX_soil1_to_soil3_c_vr_acc, AKX_soil2_to_soil1_c_vr_acc, &
+ AKX_soil2_to_soil3_c_vr_acc, AKX_soil3_to_soil1_c_vr_acc, &
+ AKX_met_exit_c_vr_acc , AKX_cel_exit_c_vr_acc , AKX_lig_exit_c_vr_acc , AKX_cwd_exit_c_vr_acc , &
+ AKX_soil1_exit_c_vr_acc , AKX_soil2_exit_c_vr_acc , AKX_soil3_exit_c_vr_acc
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+! decomposition pools flux variables (in)
+ decomp_cpools_sourcesink, decomp_ctransfer_vr, decomp_hr_vr , &
+ phenology_to_met_c , phenology_to_cel_c , phenology_to_lig_c
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+! vegetation carbon state variables (inout)
+ leafc_p , leafc_storage_p , leafc_xfer_p , &
+ frootc_p , frootc_storage_p , frootc_xfer_p , &
+ livestemc_p , livestemc_storage_p , livestemc_xfer_p , &
+ deadstemc_p , deadstemc_storage_p , deadstemc_xfer_p , &
+ livecrootc_p , livecrootc_storage_p, livecrootc_xfer_p, &
+ deadcrootc_p , deadcrootc_storage_p, deadcrootc_xfer_p, &
+ grainc_p , grainc_storage_p , grainc_xfer_p , &
+ cropseedc_deficit_p, xsmrpool_p , gresp_storage_p , gresp_xfer_p, &
+ cpool_p, &
+
+! crop variables (in)
+ harvdate_p , cropprod1c_p , &
+
+! SASU variables
+ I_leafc_p_acc , I_leafc_st_p_acc , I_frootc_p_acc , I_frootc_st_p_acc , &
+ I_livestemc_p_acc , I_livestemc_st_p_acc , I_deadstemc_p_acc , I_deadstemc_st_p_acc , &
+ I_livecrootc_p_acc, I_livecrootc_st_p_acc, I_deadcrootc_p_acc, I_deadcrootc_st_p_acc, &
+ I_grainc_p_acc , I_grainc_st_p_acc , &
+
+ AKX_leafc_xf_to_leafc_p_acc , AKX_frootc_xf_to_frootc_p_acc , AKX_livestemc_xf_to_livestemc_p_acc , &
+ AKX_deadstemc_xf_to_deadstemc_p_acc , AKX_livecrootc_xf_to_livecrootc_p_acc , AKX_deadcrootc_xf_to_deadcrootc_p_acc , &
+ AKX_grainc_xf_to_grainc_p_acc , AKX_livestemc_to_deadstemc_p_acc , AKX_livecrootc_to_deadcrootc_p_acc , &
+
+ AKX_leafc_st_to_leafc_xf_p_acc , AKX_frootc_st_to_frootc_xf_p_acc , AKX_livestemc_st_to_livestemc_xf_p_acc , &
+ AKX_deadstemc_st_to_deadstemc_xf_p_acc, AKX_livecrootc_st_to_livecrootc_xf_p_acc, AKX_deadcrootc_st_to_deadcrootc_xf_p_acc, &
+ AKX_livestemc_st_to_livestemc_xf_p_acc, AKX_grainc_st_to_grainc_xf_p_acc , &
+
+ AKX_leafc_exit_p_acc , AKX_frootc_exit_p_acc , AKX_livestemc_exit_p_acc , &
+ AKX_deadstemc_exit_p_acc , AKX_livecrootc_exit_p_acc , AKX_deadcrootc_exit_p_acc , &
+ AKX_grainc_exit_p_acc , &
+
+ AKX_leafc_st_exit_p_acc , AKX_frootc_st_exit_p_acc , AKX_livestemc_st_exit_p_acc , &
+ AKX_deadstemc_st_exit_p_acc , AKX_livecrootc_st_exit_p_acc , AKX_deadcrootc_st_exit_p_acc , &
+ AKX_grainc_st_exit_p_acc , &
+
+ AKX_leafc_xf_exit_p_acc , AKX_frootc_xf_exit_p_acc , AKX_livestemc_xf_exit_p_acc , &
+ AKX_deadstemc_xf_exit_p_acc , AKX_livecrootc_xf_exit_p_acc , AKX_deadcrootc_xf_exit_p_acc , &
+ AKX_grainc_xf_exit_p_acc
+
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+! vegetation carbon flux variables (in)
+! Vegetation physiology
+ psn_to_cpool_p, &
+
+! xfer to display
+ leafc_xfer_to_leafc_p , frootc_xfer_to_frootc_p , &
+ livestemc_xfer_to_livestemc_p , deadstemc_xfer_to_deadstemc_p , &
+ livecrootc_xfer_to_livecrootc_p, deadcrootc_xfer_to_deadcrootc_p, &
+ grainc_xfer_to_grainc_p , &
+
+! storage to xfer (in)
+ leafc_storage_to_xfer_p , frootc_storage_to_xfer_p , &
+ livestemc_storage_to_xfer_p , deadstemc_storage_to_xfer_p , &
+ livecrootc_storage_to_xfer_p, deadcrootc_storage_to_xfer_p, &
+ grainc_storage_to_xfer_p , gresp_storage_to_xfer_p , &
+
+! display to litter & live to dead (in)
+ leafc_to_litter_p , frootc_to_litter_p , &
+ grainc_to_food_p , grainc_to_seed_p , &
+ crop_seedc_to_leaf_p , livestemc_to_litter_p , &
+ livestemc_to_deadstemc_p, livecrootc_to_deadcrootc_p, &
+
+! crop
+ cropprod1c_loss_p, &
+
+! cpool to display/storage (in)
+ cpool_to_xsmrpool_p , cpool_to_gresp_storage_p , &
+ cpool_to_leafc_p , cpool_to_leafc_storage_p , &
+ cpool_to_frootc_p , cpool_to_frootc_storage_p , &
+ cpool_to_livestemc_p , cpool_to_livestemc_storage_p , &
+ cpool_to_deadstemc_p , cpool_to_deadstemc_storage_p , &
+ cpool_to_livecrootc_p, cpool_to_livecrootc_storage_p, &
+ cpool_to_deadcrootc_p, cpool_to_deadcrootc_storage_p, &
+ cpool_to_grainc_p , cpool_to_grainc_storage_p , &
+
+! cpool to growth repsiration
+ cpool_leaf_gr_p , cpool_froot_gr_p , &
+ cpool_livestem_gr_p , cpool_deadstem_gr_p , &
+ cpool_livecroot_gr_p , cpool_deadcroot_gr_p , &
+ cpool_leaf_storage_gr_p , cpool_froot_storage_gr_p , &
+ cpool_livestem_storage_gr_p , cpool_deadstem_storage_gr_p , &
+ cpool_livecroot_storage_gr_p, cpool_deadcroot_storage_gr_p , &
+
+ cpool_grain_gr_p , cpool_grain_storage_gr_p , &
+
+! maintenance respiration fluxes (in)
+ leaf_xsmr_p, froot_xsmr_p, livestem_xsmr_p, livecroot_xsmr_p, grain_xsmr_p , &
+ leaf_curmr_p, froot_curmr_p, livestem_curmr_p, livecroot_curmr_p, grain_curmr_p, &
+
+! growth respiration fluxes (in/inout)
+ transfer_leaf_gr_p , transfer_froot_gr_p , &
+ transfer_livestem_gr_p , transfer_deadstem_gr_p , &
+ transfer_livecroot_gr_p, transfer_deadcroot_gr_p, &
+ transfer_grain_gr_p , xsmrpool_to_atm_p
+
+
+ IMPLICIT NONE
+
+ PUBLIC :: CStateUpdate1
+
+CONTAINS
+
+ SUBROUTINE CStateUpdate1 (i, ps, pe, deltim, nl_soil, ndecomp_transitions, npcropmin)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ndecomp_transitions ! number of total transitions among different litter & soil bgc pools
+ integer ,intent(in) :: npcropmin ! index of first crop pft
+
+! Local variables
+ integer j,k
+ integer ivt, m
+
+ DO m = ps, pe
+ cpool_p(m) = cpool_p(m) + psn_to_cpool_p(m) * deltim
+ ENDDO
+ DO j=1,nl_soil
+ decomp_cpools_sourcesink(j,i_met_lit,i) = phenology_to_met_c(j,i) *deltim
+ decomp_cpools_sourcesink(j,i_cel_lit,i) = phenology_to_cel_c(j,i) *deltim
+ decomp_cpools_sourcesink(j,i_lig_lit,i) = phenology_to_lig_c(j,i) *deltim
+ decomp_cpools_sourcesink(j,i_cwd ,i) = 0._r8
+ ENDDO
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ DO j=1,nl_soil
+ I_met_c_vr_acc(j,i) = I_met_c_vr_acc(j,i) + phenology_to_met_c(j,i) *deltim
+ I_cel_c_vr_acc(j,i) = I_cel_c_vr_acc(j,i) + phenology_to_cel_c(j,i) *deltim
+ I_lig_c_vr_acc(j,i) = I_lig_c_vr_acc(j,i) + phenology_to_lig_c(j,i) *deltim
+ ENDDO
+ ENDIF
+
+ DO k = 1, ndecomp_transitions
+ DO j = 1,nl_soil
+ decomp_cpools_sourcesink(j,donor_pool(k),i) = &
+ decomp_cpools_sourcesink(j,donor_pool(k),i) &
+ - (decomp_hr_vr(j,k,i) + decomp_ctransfer_vr(j,k,i)) * deltim
+ ENDDO
+ ENDDO
+
+ DO k = 1,ndecomp_transitions
+ IF ( receiver_pool(k) /= 0 ) THEN ! skip terminal transitions
+ DO j = 1,nl_soil
+ decomp_cpools_sourcesink(j,receiver_pool(k),i) = &
+ decomp_cpools_sourcesink(j,receiver_pool(k),i) &
+ + decomp_ctransfer_vr(j,k,i) * deltim
+ ENDDO
+ ENDIF
+ ENDDO
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ DO j = 1, nl_soil
+ AKX_met_to_soil1_c_vr_acc (j,i) = AKX_met_to_soil1_c_vr_acc (j,i) + decomp_ctransfer_vr(j, 1,i) * deltim
+ AKX_cel_to_soil1_c_vr_acc (j,i) = AKX_cel_to_soil1_c_vr_acc (j,i) + decomp_ctransfer_vr(j, 2,i) * deltim
+ AKX_lig_to_soil2_c_vr_acc (j,i) = AKX_lig_to_soil2_c_vr_acc (j,i) + decomp_ctransfer_vr(j, 3,i) * deltim
+ AKX_soil1_to_soil2_c_vr_acc(j,i) = AKX_soil1_to_soil2_c_vr_acc(j,i) + decomp_ctransfer_vr(j, 4,i) * deltim
+ AKX_cwd_to_cel_c_vr_acc (j,i) = AKX_cwd_to_cel_c_vr_acc (j,i) + decomp_ctransfer_vr(j, 5,i) * deltim
+ AKX_cwd_to_lig_c_vr_acc (j,i) = AKX_cwd_to_lig_c_vr_acc (j,i) + decomp_ctransfer_vr(j, 6,i) * deltim
+ AKX_soil1_to_soil3_c_vr_acc(j,i) = AKX_soil1_to_soil3_c_vr_acc(j,i) + decomp_ctransfer_vr(j, 7,i) * deltim
+ AKX_soil2_to_soil1_c_vr_acc(j,i) = AKX_soil2_to_soil1_c_vr_acc(j,i) + decomp_ctransfer_vr(j, 8,i) * deltim
+ AKX_soil2_to_soil3_c_vr_acc(j,i) = AKX_soil2_to_soil3_c_vr_acc(j,i) + decomp_ctransfer_vr(j, 9,i) * deltim
+ AKX_soil3_to_soil1_c_vr_acc(j,i) = AKX_soil3_to_soil1_c_vr_acc(j,i) + decomp_ctransfer_vr(j,10,i) * deltim
+
+ AKX_met_exit_c_vr_acc (j,i) = AKX_met_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 1,i) + decomp_ctransfer_vr(j, 1,i)) * deltim
+ AKX_cel_exit_c_vr_acc (j,i) = AKX_cel_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 2,i) + decomp_ctransfer_vr(j, 2,i)) * deltim
+ AKX_lig_exit_c_vr_acc (j,i) = AKX_lig_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 3,i) + decomp_ctransfer_vr(j, 3,i)) * deltim
+ AKX_soil1_exit_c_vr_acc (j,i) = AKX_soil1_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 4,i) + decomp_ctransfer_vr(j, 4,i)) * deltim
+ AKX_cwd_exit_c_vr_acc (j,i) = AKX_cwd_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 5,i) + decomp_ctransfer_vr(j, 5,i)) * deltim
+ AKX_cwd_exit_c_vr_acc (j,i) = AKX_cwd_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 6,i) + decomp_ctransfer_vr(j, 6,i)) * deltim
+ AKX_soil1_exit_c_vr_acc (j,i) = AKX_soil1_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 7,i) + decomp_ctransfer_vr(j, 7,i)) * deltim
+ AKX_soil2_exit_c_vr_acc (j,i) = AKX_soil2_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 8,i) + decomp_ctransfer_vr(j, 8,i)) * deltim
+ AKX_soil2_exit_c_vr_acc (j,i) = AKX_soil2_exit_c_vr_acc (j,i) + (decomp_hr_vr(j, 9,i) + decomp_ctransfer_vr(j, 9,i)) * deltim
+ AKX_soil3_exit_c_vr_acc (j,i) = AKX_soil3_exit_c_vr_acc (j,i) + (decomp_hr_vr(j,10,i) + decomp_ctransfer_vr(j,10,i)) * deltim
+ ENDDO
+ ENDIF
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+ leafc_p (m) = leafc_p (m) + leafc_xfer_to_leafc_p (m) * deltim
+ leafc_xfer_p (m) = leafc_xfer_p (m) - leafc_xfer_to_leafc_p (m) * deltim
+ frootc_p (m) = frootc_p (m) + frootc_xfer_to_frootc_p(m) * deltim
+ frootc_xfer_p(m) = frootc_xfer_p(m) - frootc_xfer_to_frootc_p(m) * deltim
+ IF(woody(ivt) == 1)THEN
+ livestemc_p (m) = livestemc_p (m) + livestemc_xfer_to_livestemc_p (m) * deltim
+ livestemc_xfer_p (m) = livestemc_xfer_p (m) - livestemc_xfer_to_livestemc_p (m) * deltim
+ deadstemc_p (m) = deadstemc_p (m) + deadstemc_xfer_to_deadstemc_p (m) * deltim
+ deadstemc_xfer_p (m) = deadstemc_xfer_p (m) - deadstemc_xfer_to_deadstemc_p (m) * deltim
+ livecrootc_p (m) = livecrootc_p (m) + livecrootc_xfer_to_livecrootc_p(m) * deltim
+ livecrootc_xfer_p(m) = livecrootc_xfer_p(m) - livecrootc_xfer_to_livecrootc_p(m) * deltim
+ deadcrootc_p (m) = deadcrootc_p (m) + deadcrootc_xfer_to_deadcrootc_p(m) * deltim
+ deadcrootc_xfer_p(m) = deadcrootc_xfer_p(m) - deadcrootc_xfer_to_deadcrootc_p(m) * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+! lines here for consistency; the transfer terms are zero
+ livestemc_p (m) = livestemc_p (m) + livestemc_xfer_to_livestemc_p(m) * deltim
+ livestemc_xfer_p(m) = livestemc_xfer_p(m) - livestemc_xfer_to_livestemc_p(m) * deltim
+ grainc_p (m) = grainc_p (m) + grainc_xfer_to_grainc_p (m) * deltim
+ grainc_xfer_p (m) = grainc_xfer_p (m) - grainc_xfer_to_grainc_p (m) * deltim
+ ENDIF
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafc_xf_to_leafc_p_acc (m) = AKX_leafc_xf_to_leafc_p_acc (m) + leafc_xfer_to_leafc_p (m) * deltim
+ AKX_frootc_xf_to_frootc_p_acc(m) = AKX_frootc_xf_to_frootc_p_acc(m) + frootc_xfer_to_frootc_p(m) * deltim
+ AKX_leafc_xf_exit_p_acc (m) = AKX_leafc_xf_exit_p_acc (m) + leafc_xfer_to_leafc_p (m) * deltim
+ AKX_frootc_xf_exit_p_acc (m) = AKX_frootc_xf_exit_p_acc (m) + frootc_xfer_to_frootc_p(m) * deltim
+ IF(woody(ivt) == 1)THEN
+ AKX_livestemc_xf_to_livestemc_p_acc (m) = AKX_livestemc_xf_to_livestemc_p_acc (m) + livestemc_xfer_to_livestemc_p (m) * deltim
+ AKX_livestemc_xf_exit_p_acc (m) = AKX_livestemc_xf_exit_p_acc (m) + livestemc_xfer_to_livestemc_p (m) * deltim
+ AKX_deadstemc_xf_to_deadstemc_p_acc (m) = AKX_deadstemc_xf_to_deadstemc_p_acc (m) + deadstemc_xfer_to_deadstemc_p (m) * deltim
+ AKX_deadstemc_xf_exit_p_acc (m) = AKX_deadstemc_xf_exit_p_acc (m) + deadstemc_xfer_to_deadstemc_p (m) * deltim
+ AKX_livecrootc_xf_to_livecrootc_p_acc(m) = AKX_livecrootc_xf_to_livecrootc_p_acc(m) + livecrootc_xfer_to_livecrootc_p(m) * deltim
+ AKX_livecrootc_xf_exit_p_acc (m) = AKX_livecrootc_xf_exit_p_acc (m) + livecrootc_xfer_to_livecrootc_p(m) * deltim
+ AKX_deadcrootc_xf_to_deadcrootc_p_acc(m) = AKX_deadcrootc_xf_to_deadcrootc_p_acc(m) + deadcrootc_xfer_to_deadcrootc_p(m) * deltim
+ AKX_deadcrootc_xf_exit_p_acc (m) = AKX_deadcrootc_xf_exit_p_acc (m) + deadcrootc_xfer_to_deadcrootc_p(m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin) THEN
+ AKX_livestemc_xf_to_livestemc_p_acc(m) = AKX_livestemc_xf_to_livestemc_p_acc(m) + livestemc_xfer_to_livestemc_p(m) * deltim
+ AKX_livestemc_xf_exit_p_acc (m) = AKX_livestemc_xf_exit_p_acc (m) + livestemc_xfer_to_livestemc_p(m) * deltim
+ AKX_grainc_xf_to_grainc_p_acc (m) = AKX_grainc_xf_to_grainc_p_acc (m) + grainc_xfer_to_grainc_p (m) * deltim
+ AKX_grainc_xf_exit_p_acc (m) = AKX_grainc_xf_exit_p_acc (m) + grainc_xfer_to_grainc_p (m) * deltim
+ ENDIF
+ ENDIF
+
+! phenology: litterfall fluxes
+ leafc_p (m) = leafc_p (m) - leafc_to_litter_p (m) * deltim
+ frootc_p(m) = frootc_p(m) - frootc_to_litter_p(m) * deltim
+
+! livewood turnover fluxes
+ IF (woody(ivt) == 1) THEN
+ livestemc_p (m) = livestemc_p (m) - livestemc_to_deadstemc_p (m) * deltim
+ deadstemc_p (m) = deadstemc_p (m) + livestemc_to_deadstemc_p (m) * deltim
+ livecrootc_p(m) = livecrootc_p(m) - livecrootc_to_deadcrootc_p(m) * deltim
+ deadcrootc_p(m) = deadcrootc_p(m) + livecrootc_to_deadcrootc_p(m) * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ livestemc_p (m) = livestemc_p (m) - livestemc_to_litter_p(m) * deltim
+ grainc_p (m) = grainc_p (m) - (grainc_to_food_p(m) + grainc_to_seed_p(m)) * deltim
+ cropseedc_deficit_p(m) = cropseedc_deficit_p(m) - crop_seedc_to_leaf_p(m) * deltim + grainc_to_seed_p(m) * deltim
+ ENDIF
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafc_exit_p_acc (m) = AKX_leafc_exit_p_acc (m) + leafc_to_litter_p (m) * deltim
+ AKX_frootc_exit_p_acc(m) = AKX_frootc_exit_p_acc(m) + frootc_to_litter_p(m) * deltim
+ IF(woody(ivt) == 1) THEN
+ AKX_livestemc_to_deadstemc_p_acc (m) = AKX_livestemc_to_deadstemc_p_acc (m) + livestemc_to_deadstemc_p (m) * deltim
+ AKX_livestemc_exit_p_acc (m) = AKX_livestemc_exit_p_acc (m) + livestemc_to_deadstemc_p (m) * deltim
+ AKX_livecrootc_to_deadcrootc_p_acc(m) = AKX_livecrootc_to_deadcrootc_p_acc(m) + livecrootc_to_deadcrootc_p(m) * deltim
+ AKX_livecrootc_exit_p_acc (m) = AKX_livecrootc_exit_p_acc (m) + livecrootc_to_deadcrootc_p(m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin) THEN
+ AKX_livestemc_exit_p_acc (m) = AKX_livestemc_exit_p_acc (m) + livestemc_to_litter_p (m) * deltim
+ AKX_grainc_exit_p_acc (m) = AKX_grainc_exit_p_acc (m) + (grainc_to_food_p(m) + grainc_to_seed_p(m)) * deltim
+ ENDIF
+ ENDIF
+! maintenance respiration fluxes from xsmrpool
+ cpool_p (m) = cpool_p (m) - cpool_to_xsmrpool_p(m) * deltim
+ cpool_p (m) = cpool_p (m) - leaf_curmr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - froot_curmr_p (m) * deltim
+ IF (woody(ivt) == 1) THEN
+ cpool_p(m) = cpool_p (m) - livestem_curmr_p (m) * deltim
+ cpool_p(m) = cpool_p (m) - livecroot_curmr_p (m) * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN
+ cpool_p(m) = cpool_p (m) - livestem_curmr_p (m) * deltim
+ cpool_p(m) = cpool_p (m) - grain_curmr_p (m) * deltim
+ ENDIF
+#ifdef FUN
+ cpool_p (m) = cpool_p (m) - soilc_change_p (m) * deltim
+#endif
+ xsmrpool_p(m) = xsmrpool_p(m) + cpool_to_xsmrpool_p(m) * deltim
+ xsmrpool_p(m) = xsmrpool_p(m) - leaf_xsmr_p (m) * deltim
+ xsmrpool_p(m) = xsmrpool_p(m) - froot_xsmr_p (m) * deltim
+ IF (woody(ivt) == 1) THEN
+ xsmrpool_p(m) = xsmrpool_p(m) - livestem_xsmr_p (m) * deltim
+ xsmrpool_p(m) = xsmrpool_p(m) - livecroot_xsmr_p(m) * deltim
+ ENDIF
+ cpool_p (m) = cpool_p (m) - cpool_to_leafc_p (m) * deltim
+ leafc_p (m) = leafc_p (m) + cpool_to_leafc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_leafc_storage_p (m) * deltim
+ leafc_storage_p (m) = leafc_storage_p (m) + cpool_to_leafc_storage_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_frootc_p (m) * deltim
+ frootc_p (m) = frootc_p (m) + cpool_to_frootc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_frootc_storage_p(m) * deltim
+ frootc_storage_p(m) = frootc_storage_p(m) + cpool_to_frootc_storage_p(m) * deltim
+ IF (woody(ivt) == 1) THEN
+ cpool_p (m) = cpool_p (m) - cpool_to_livestemc_p (m) * deltim
+ livestemc_p (m) = livestemc_p (m) + cpool_to_livestemc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_livestemc_storage_p (m) * deltim
+ livestemc_storage_p (m) = livestemc_storage_p (m) + cpool_to_livestemc_storage_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_deadstemc_p (m) * deltim
+ deadstemc_p (m) = deadstemc_p (m) + cpool_to_deadstemc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_deadstemc_storage_p (m) * deltim
+ deadstemc_storage_p (m) = deadstemc_storage_p (m) + cpool_to_deadstemc_storage_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_livecrootc_p (m) * deltim
+ livecrootc_p (m) = livecrootc_p (m) + cpool_to_livecrootc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_livecrootc_storage_p(m) * deltim
+ livecrootc_storage_p(m) = livecrootc_storage_p(m) + cpool_to_livecrootc_storage_p(m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_deadcrootc_p (m) * deltim
+ deadcrootc_p (m) = deadcrootc_p (m) + cpool_to_deadcrootc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_deadcrootc_storage_p(m) * deltim
+ deadcrootc_storage_p(m) = deadcrootc_storage_p(m) + cpool_to_deadcrootc_storage_p(m) * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ cpool_p (m) = cpool_p (m) - cpool_to_livestemc_p (m) * deltim
+ livestemc_p (m) = livestemc_p (m) + cpool_to_livestemc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_livestemc_storage_p(m) * deltim
+ livestemc_storage_p(m) = livestemc_storage_p(m) + cpool_to_livestemc_storage_p(m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_grainc_p (m) * deltim
+ grainc_p (m) = grainc_p (m) + cpool_to_grainc_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_to_grainc_storage_p (m) * deltim
+ grainc_storage_p (m) = grainc_storage_p (m) + cpool_to_grainc_storage_p (m) * deltim
+ ENDIF
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ I_leafc_p_acc(m) = I_leafc_p_acc(m) + cpool_to_leafc_p (m) * deltim
+ I_leafc_st_p_acc(m) = I_leafc_st_p_acc(m) + cpool_to_leafc_storage_p (m) * deltim
+ I_frootc_p_acc(m) = I_frootc_p_acc(m) + cpool_to_frootc_p (m) * deltim
+ I_frootc_st_p_acc(m) = I_frootc_st_p_acc(m) + cpool_to_frootc_storage_p (m) * deltim
+ IF(woody(ivt) == 1) THEN
+ I_livestemc_p_acc (m) = I_livestemc_p_acc (m) + cpool_to_livestemc_p (m) * deltim
+ I_livestemc_st_p_acc (m) = I_livestemc_st_p_acc (m) + cpool_to_livestemc_storage_p (m) * deltim
+ I_deadstemc_p_acc (m) = I_deadstemc_p_acc (m) + cpool_to_deadstemc_p (m) * deltim
+ I_deadstemc_st_p_acc (m) = I_deadstemc_st_p_acc (m) + cpool_to_deadstemc_storage_p (m) * deltim
+ I_livecrootc_p_acc (m) = I_livecrootc_p_acc (m) + cpool_to_livecrootc_p (m) * deltim
+ I_livecrootc_st_p_acc(m) = I_livecrootc_st_p_acc(m) + cpool_to_livecrootc_storage_p(m) * deltim
+ I_deadcrootc_p_acc (m) = I_deadcrootc_p_acc (m) + cpool_to_deadcrootc_p (m) * deltim
+ I_deadcrootc_st_p_acc(m) = I_deadcrootc_st_p_acc(m) + cpool_to_deadcrootc_storage_p(m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin) THEN
+ I_livestemc_p_acc (m) = I_livestemc_p_acc (m) + cpool_to_livestemc_p (m) * deltim
+ I_livestemc_st_p_acc (m) = I_livestemc_st_p_acc (m) + cpool_to_livestemc_storage_p (m) * deltim
+ I_grainc_p_acc (m) = I_grainc_p_acc (m) + cpool_to_grainc_p (m) * deltim
+ I_grainc_st_p_acc (m) = I_grainc_st_p_acc (m) + cpool_to_grainc_storage_p (m) * deltim
+ ENDIF
+ ENDIF
+ ! growth respiration for transfer growth
+ cpool_p (m) = cpool_p (m) - cpool_leaf_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_froot_gr_p (m) * deltim
+ IF(woody(ivt) == 1) THEN
+ cpool_p (m) = cpool_p (m) - cpool_livestem_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_deadstem_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_livecroot_gr_p(m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_deadcroot_gr_p(m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin)THEN
+ cpool_p (m) = cpool_p (m) - cpool_livestem_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_grain_gr_p (m) * deltim
+ ENDIF
+
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_leaf_gr_p (m) * deltim
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_froot_gr_p(m) * deltim
+ IF (woody(ivt) == 1) THEN
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_livestem_gr_p (m) * deltim
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_deadstem_gr_p (m) * deltim
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_livecroot_gr_p(m) * deltim
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_deadcroot_gr_p(m) * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_livestem_gr_p(m) * deltim
+ gresp_xfer_p(m) = gresp_xfer_p(m) - transfer_grain_gr_p (m) * deltim
+ ENDIF
+ ! growth respiration at time of storage
+ cpool_p (m) = cpool_p (m) - cpool_leaf_storage_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_froot_storage_gr_p(m) * deltim
+ IF(woody(ivt) == 1)THEN
+ cpool_p (m) = cpool_p (m) - cpool_livestem_storage_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_deadstem_storage_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_livecroot_storage_gr_p(m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_deadcroot_storage_gr_p(m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin)THEN
+ cpool_p (m) = cpool_p (m) - cpool_livestem_storage_gr_p (m) * deltim
+ cpool_p (m) = cpool_p (m) - cpool_grain_storage_gr_p (m) * deltim
+ ENDIF
+
+ ! growth respiration stored for release during transfer growth
+ cpool_p (m) = cpool_p (m) - cpool_to_gresp_storage_p(m) * deltim
+ gresp_storage_p(m) = gresp_storage_p(m) + cpool_to_gresp_storage_p(m) * deltim
+
+ ! move storage pools into transfer pools
+ leafc_storage_p (m) = leafc_storage_p (m) - leafc_storage_to_xfer_p (m) * deltim
+ leafc_xfer_p (m) = leafc_xfer_p (m) + leafc_storage_to_xfer_p (m) * deltim
+ frootc_storage_p(m) = frootc_storage_p(m) - frootc_storage_to_xfer_p(m) * deltim
+ frootc_xfer_p (m) = frootc_xfer_p (m) + frootc_storage_to_xfer_p(m) * deltim
+ IF (woody(ivt) == 1) THEN
+ gresp_storage_p (m) = gresp_storage_p (m) - gresp_storage_to_xfer_p(m) * deltim
+ gresp_xfer_p (m) = gresp_xfer_p (m) + gresp_storage_to_xfer_p(m) * deltim
+
+ livestemc_storage_p (m) = livestemc_storage_p (m) - livestemc_storage_to_xfer_p (m) * deltim
+ livestemc_xfer_p (m) = livestemc_xfer_p (m) + livestemc_storage_to_xfer_p (m) * deltim
+ deadstemc_storage_p (m) = deadstemc_storage_p (m) - deadstemc_storage_to_xfer_p (m) * deltim
+ deadstemc_xfer_p (m) = deadstemc_xfer_p (m) + deadstemc_storage_to_xfer_p (m) * deltim
+ livecrootc_storage_p(m) = livecrootc_storage_p(m) - livecrootc_storage_to_xfer_p(m) * deltim
+ livecrootc_xfer_p (m) = livecrootc_xfer_p (m) + livecrootc_storage_to_xfer_p(m) * deltim
+ deadcrootc_storage_p(m) = deadcrootc_storage_p(m) - deadcrootc_storage_to_xfer_p(m) * deltim
+ deadcrootc_xfer_p (m) = deadcrootc_xfer_p (m) + deadcrootc_storage_to_xfer_p(m) * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ ! lines here for consistency; the transfer terms are zero
+ livestemc_storage_p (m) = livestemc_storage_p(m) - livestemc_storage_to_xfer_p(m) * deltim
+ livestemc_xfer_p (m) = livestemc_xfer_p (m) + livestemc_storage_to_xfer_p(m) * deltim
+ grainc_storage_p (m) = grainc_storage_p (m) - grainc_storage_to_xfer_p (m) * deltim
+ grainc_xfer_p (m) = grainc_xfer_p (m) + grainc_storage_to_xfer_p (m) * deltim
+ ENDIF
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafc_st_to_leafc_xf_p_acc (m) = AKX_leafc_st_to_leafc_xf_p_acc (m) + leafc_storage_to_xfer_p (m) * deltim
+ AKX_leafc_st_exit_p_acc (m) = AKX_leafc_st_exit_p_acc (m) + leafc_storage_to_xfer_p (m) * deltim
+ AKX_frootc_st_to_frootc_xf_p_acc(m) = AKX_frootc_st_to_frootc_xf_p_acc(m) + frootc_storage_to_xfer_p(m) * deltim
+ AKX_frootc_st_exit_p_acc (m) = AKX_frootc_st_exit_p_acc (m) + frootc_storage_to_xfer_p(m) * deltim
+ IF(woody(ivt) == 1) THEN
+ AKX_livestemc_st_to_livestemc_xf_p_acc (m) = AKX_livestemc_st_to_livestemc_xf_p_acc (m) + livestemc_storage_to_xfer_p (m) * deltim
+ AKX_livestemc_st_exit_p_acc (m) = AKX_livestemc_st_exit_p_acc (m) + livestemc_storage_to_xfer_p (m) * deltim
+ AKX_deadstemc_st_to_deadstemc_xf_p_acc (m) = AKX_deadstemc_st_to_deadstemc_xf_p_acc (m) + deadstemc_storage_to_xfer_p (m) * deltim
+ AKX_deadstemc_st_exit_p_acc (m) = AKX_deadstemc_st_exit_p_acc (m) + deadstemc_storage_to_xfer_p (m) * deltim
+ AKX_livecrootc_st_to_livecrootc_xf_p_acc(m) = AKX_livecrootc_st_to_livecrootc_xf_p_acc(m) + livecrootc_storage_to_xfer_p(m) * deltim
+ AKX_livecrootc_st_exit_p_acc (m) = AKX_livecrootc_st_exit_p_acc (m) + livecrootc_storage_to_xfer_p(m) * deltim
+ AKX_deadcrootc_st_to_deadcrootc_xf_p_acc(m) = AKX_deadcrootc_st_to_deadcrootc_xf_p_acc(m) + deadcrootc_storage_to_xfer_p(m) * deltim
+ AKX_deadcrootc_st_exit_p_acc (m) = AKX_deadcrootc_st_exit_p_acc (m) + deadcrootc_storage_to_xfer_p(m) * deltim
+ ENDIF
+ IF( ivt >= npcropmin) THEN
+ AKX_livestemc_st_to_livestemc_xf_p_acc (m) = AKX_livestemc_st_to_livestemc_xf_p_acc (m) + livestemc_storage_to_xfer_p (m) * deltim
+ AKX_livestemc_st_exit_p_acc (m) = AKX_livestemc_st_exit_p_acc (m) + livestemc_storage_to_xfer_p (m) * deltim
+ AKX_grainc_st_to_grainc_xf_p_acc (m) = AKX_grainc_st_to_grainc_xf_p_acc (m) + grainc_storage_to_xfer_p (m) * deltim
+ AKX_grainc_st_exit_p_acc (m) = AKX_grainc_st_exit_p_acc (m) + grainc_storage_to_xfer_p (m) * deltim
+ ENDIF
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ xsmrpool_p(m) = xsmrpool_p(m) - livestem_xsmr_p(m)*deltim
+ xsmrpool_p(m) = xsmrpool_p(m) - grain_xsmr_p (m)*deltim
+ IF (harvdate_p(m) < 999) THEN ! beginning at harvest, send to atm
+ xsmrpool_to_atm_p(m) = xsmrpool_to_atm_p(m) + xsmrpool_p(m)/deltim
+ xsmrpool_p (m) = 0._r8
+ xsmrpool_to_atm_p(m) = xsmrpool_to_atm_p(m) + cpool_p (m)/deltim
+ cpool_p (m) = 0._r8
+ xsmrpool_to_atm_p(m) = xsmrpool_to_atm_p(m) + frootc_p(m)/deltim
+ frootc_p (m) = 0._r8
+ ENDIF
+ ENDIF
+#ifdef CROP
+ cropprod1c_loss_p(m) = cropprod1c_p(m) * 7.2e-8_r8
+ cropprod1c_p (m) = cropprod1c_p(m) + grainc_to_food_p(m) * deltim - cropprod1c_loss_p(m) * deltim
+#endif
+ ENDDO ! END pft loop
+
+ END SUBROUTINE CStateUpdate1
+
+END MODULE MOD_BGC_CNCStateUpdate1
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate2.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate2.F90
new file mode 100644
index 0000000000..25fee8e971
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate2.F90
@@ -0,0 +1,176 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_CNCStateUpdate2
+
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! First updates in vegetation and soil carbon. The major updates are included in bgc_CNCStateUpdate1Mod
+! 1. Update gap-mortality-associated veg and soil C pool size changes
+! 2. Record the accumulated C transfers associated to gap-mortality for semi-analytic spinup
+
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record the accumulated gap-mortality-associated C transfers for veg and soil C semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_Vars_TimeInvariants, only: &
+ i_met_lit,i_cel_lit,i_lig_lit ,i_cwd
+ USE MOD_Vars_TimeVariables, only: &
+! decomposition pools & fluxes variables (inout)
+ decomp_cpools_vr, &
+ I_met_c_vr_acc, I_cel_c_vr_acc, I_lig_c_vr_acc, I_cwd_c_vr_acc
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ gap_mortality_to_met_c, gap_mortality_to_cel_c , &
+ gap_mortality_to_lig_c, gap_mortality_to_cwdc
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+! vegetation carbon state variables (inout)
+ leafc_p , leafc_storage_p , leafc_xfer_p , &
+ frootc_p , frootc_storage_p , frootc_xfer_p , &
+ livestemc_p , livestemc_storage_p , livestemc_xfer_p , &
+ deadstemc_p , deadstemc_storage_p , deadstemc_xfer_p , &
+ livecrootc_p , livecrootc_storage_p, livecrootc_xfer_p, &
+ deadcrootc_p , deadcrootc_storage_p, deadcrootc_xfer_p, &
+ gresp_storage_p , gresp_xfer_p , &
+
+! SASU variables
+ AKX_leafc_exit_p_acc , AKX_leafc_st_exit_p_acc , AKX_leafc_xf_exit_p_acc , &
+ AKX_frootc_exit_p_acc , AKX_frootc_st_exit_p_acc , AKX_frootc_xf_exit_p_acc , &
+ AKX_livestemc_exit_p_acc , AKX_livestemc_st_exit_p_acc , AKX_livestemc_xf_exit_p_acc , &
+ AKX_deadstemc_exit_p_acc , AKX_deadstemc_st_exit_p_acc , AKX_deadstemc_xf_exit_p_acc , &
+ AKX_livecrootc_exit_p_acc, AKX_livecrootc_st_exit_p_acc, AKX_livecrootc_xf_exit_p_acc, &
+ AKX_deadcrootc_exit_p_acc, AKX_deadcrootc_st_exit_p_acc, AKX_deadcrootc_xf_exit_p_acc
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+! vegetation carbon flux variables
+ m_leafc_to_litter_p , m_leafc_storage_to_litter_p , m_leafc_xfer_to_litter_p , &
+ m_frootc_to_litter_p , m_frootc_storage_to_litter_p , m_frootc_xfer_to_litter_p , &
+ m_livestemc_to_litter_p , m_livestemc_storage_to_litter_p , m_livestemc_xfer_to_litter_p , &
+ m_deadstemc_to_litter_p , m_deadstemc_storage_to_litter_p , m_deadstemc_xfer_to_litter_p , &
+ m_livecrootc_to_litter_p , m_livecrootc_storage_to_litter_p, m_livecrootc_xfer_to_litter_p, &
+ m_deadcrootc_to_litter_p , m_deadcrootc_storage_to_litter_p, m_deadcrootc_xfer_to_litter_p, &
+ m_gresp_storage_to_litter_p, m_gresp_xfer_to_litter_p
+
+ IMPLICIT NONE
+
+ PUBLIC CStateUpdate2
+
+CONTAINS
+
+ SUBROUTINE CStateUpdate2 (i, ps, pe, deltim, nl_soil)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in second
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+
+ integer j
+ integer m
+
+! column level carbon fluxes from gap-phase mortality
+ DO j = 1,nl_soil
+! column gap mortality fluxes
+ decomp_cpools_vr(j,i_met_lit,i) = &
+ decomp_cpools_vr(j,i_met_lit,i) + gap_mortality_to_met_c(j,i) * deltim
+ decomp_cpools_vr(j,i_cel_lit,i) = &
+ decomp_cpools_vr(j,i_cel_lit,i) + gap_mortality_to_cel_c(j,i) * deltim
+ decomp_cpools_vr(j,i_lig_lit,i) = &
+ decomp_cpools_vr(j,i_lig_lit,i) + gap_mortality_to_lig_c(j,i) * deltim
+ decomp_cpools_vr(j,i_cwd,i) = &
+ decomp_cpools_vr(j,i_cwd,i) + gap_mortality_to_cwdc(j,i) * deltim
+ ENDDO
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ DO j = 1,nl_soil
+ I_met_c_vr_acc(j,i) = I_met_c_vr_acc(j,i) + gap_mortality_to_met_c(j,i) * deltim
+ I_cel_c_vr_acc(j,i) = I_cel_c_vr_acc(j,i) + gap_mortality_to_cel_c(j,i) * deltim
+ I_lig_c_vr_acc(j,i) = I_lig_c_vr_acc(j,i) + gap_mortality_to_lig_c(j,i) * deltim
+ I_cwd_c_vr_acc(j,i) = I_cwd_c_vr_acc(j,i) + gap_mortality_to_cwdc (j,i) * deltim
+ ENDDO
+ ENDIF
+
+ ! patch loop
+
+ DO m = ps, pe
+ gresp_xfer_p (m) = gresp_xfer_p(m) &
+ - m_gresp_xfer_to_litter_p (m) * deltim
+ gresp_storage_p (m) = gresp_storage_p(m) &
+ - m_gresp_storage_to_litter_p (m) * deltim
+ ! patch-level carbon fluxes from gap-phase mortality
+ ! displayed pools
+ leafc_p (m) = leafc_p (m) &
+ - m_leafc_to_litter_p (m) * deltim
+ frootc_p (m) = frootc_p (m) &
+ - m_frootc_to_litter_p (m) * deltim
+ livestemc_p (m) = livestemc_p (m) &
+ - m_livestemc_to_litter_p (m) * deltim
+ deadstemc_p (m) = deadstemc_p (m) &
+ - m_deadstemc_to_litter_p (m) * deltim
+ livecrootc_p (m) = livecrootc_p (m) &
+ - m_livecrootc_to_litter_p (m) * deltim
+ deadcrootc_p (m) = deadcrootc_p (m) &
+ - m_deadcrootc_to_litter_p (m) * deltim
+
+ ! storage pools
+ leafc_storage_p (m) = leafc_storage_p (m) &
+ - m_leafc_storage_to_litter_p (m) * deltim
+ frootc_storage_p (m) = frootc_storage_p (m) &
+ - m_frootc_storage_to_litter_p (m) * deltim
+ livestemc_storage_p (m) = livestemc_storage_p (m) &
+ - m_livestemc_storage_to_litter_p (m) * deltim
+ deadstemc_storage_p (m) = deadstemc_storage_p (m) &
+ - m_deadstemc_storage_to_litter_p (m) * deltim
+ livecrootc_storage_p(m) = livecrootc_storage_p(m) &
+ - m_livecrootc_storage_to_litter_p(m) * deltim
+ deadcrootc_storage_p(m) = deadcrootc_storage_p(m) &
+ - m_deadcrootc_storage_to_litter_p(m) * deltim
+
+ ! transfer pools
+ leafc_xfer_p (m) = leafc_xfer_p (m) &
+ - m_leafc_xfer_to_litter_p (m) * deltim
+ frootc_xfer_p (m) = frootc_xfer_p (m) &
+ - m_frootc_xfer_to_litter_p (m) * deltim
+ livestemc_xfer_p (m) = livestemc_xfer_p (m) &
+ - m_livestemc_xfer_to_litter_p (m) * deltim
+ deadstemc_xfer_p (m) = deadstemc_xfer_p (m) &
+ - m_deadstemc_xfer_to_litter_p (m) * deltim
+ livecrootc_xfer_p (m) = livecrootc_xfer_p (m) &
+ - m_livecrootc_xfer_to_litter_p (m) * deltim
+ deadcrootc_xfer_p (m) = deadcrootc_xfer_p (m) &
+ - m_deadcrootc_xfer_to_litter_p (m) * deltim
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafc_exit_p_acc (m) = AKX_leafc_exit_p_acc (m) + m_leafc_to_litter_p (m) * deltim
+ AKX_frootc_exit_p_acc (m) = AKX_frootc_exit_p_acc (m) + m_frootc_to_litter_p (m) * deltim
+ AKX_livestemc_exit_p_acc (m) = AKX_livestemc_exit_p_acc (m) + m_livestemc_to_litter_p (m) * deltim
+ AKX_deadstemc_exit_p_acc (m) = AKX_deadstemc_exit_p_acc (m) + m_deadstemc_to_litter_p (m) * deltim
+ AKX_livecrootc_exit_p_acc (m) = AKX_livecrootc_exit_p_acc (m) + m_livecrootc_to_litter_p (m) * deltim
+ AKX_deadcrootc_exit_p_acc (m) = AKX_deadcrootc_exit_p_acc (m) + m_deadcrootc_to_litter_p (m) * deltim
+
+ AKX_leafc_st_exit_p_acc (m) = AKX_leafc_st_exit_p_acc (m) + m_leafc_storage_to_litter_p (m) * deltim
+ AKX_frootc_st_exit_p_acc (m) = AKX_frootc_st_exit_p_acc (m) + m_frootc_storage_to_litter_p (m) * deltim
+ AKX_livestemc_st_exit_p_acc (m) = AKX_livestemc_st_exit_p_acc (m) + m_livestemc_storage_to_litter_p (m) * deltim
+ AKX_deadstemc_st_exit_p_acc (m) = AKX_deadstemc_st_exit_p_acc (m) + m_deadstemc_storage_to_litter_p (m) * deltim
+ AKX_livecrootc_st_exit_p_acc(m) = AKX_livecrootc_st_exit_p_acc(m) + m_livecrootc_storage_to_litter_p(m) * deltim
+ AKX_deadcrootc_st_exit_p_acc(m) = AKX_deadcrootc_st_exit_p_acc(m) + m_deadcrootc_storage_to_litter_p(m) * deltim
+
+ AKX_leafc_xf_exit_p_acc (m) = AKX_leafc_xf_exit_p_acc (m) + m_leafc_xfer_to_litter_p (m) * deltim
+ AKX_frootc_xf_exit_p_acc (m) = AKX_frootc_xf_exit_p_acc (m) + m_frootc_xfer_to_litter_p (m) * deltim
+ AKX_livestemc_xf_exit_p_acc (m) = AKX_livestemc_xf_exit_p_acc (m) + m_livestemc_xfer_to_litter_p (m) * deltim
+ AKX_deadstemc_xf_exit_p_acc (m) = AKX_deadstemc_xf_exit_p_acc (m) + m_deadstemc_xfer_to_litter_p (m) * deltim
+ AKX_livecrootc_xf_exit_p_acc(m) = AKX_livecrootc_xf_exit_p_acc(m) + m_livecrootc_xfer_to_litter_p (m) * deltim
+ AKX_deadcrootc_xf_exit_p_acc(m) = AKX_deadcrootc_xf_exit_p_acc(m) + m_deadcrootc_xfer_to_litter_p (m) * deltim
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CStateUpdate2
+
+END MODULE MOD_BGC_CNCStateUpdate2
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate3.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate3.F90
new file mode 100644
index 0000000000..afb640fdd1
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNCStateUpdate3.F90
@@ -0,0 +1,194 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_CNCStateUpdate3
+
+!-------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! First updates in vegetation and soil carbon. The major updates are included in bgc_CNCStateUpdate1Mod
+! 1. Update fire-associated veg and soil(litter) C pool size changes
+! 2. Record the accumulated C transfers associated to fire for semi-analytic spinup
+
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! !REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record accumulated fire-associated C transfers for veg and soil C semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ i_met_lit,i_cel_lit,i_lig_lit ,i_cwd
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decomposition pools & fluxes variables (inout)
+ decomp_cpools_vr
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ m_decomp_cpools_to_fire_vr, &
+ fire_mortality_to_met_c, fire_mortality_to_cel_c, &
+ fire_mortality_to_lig_c, fire_mortality_to_cwdc
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ ! vegetation carbon state variables (inout)
+ leafc_p , leafc_storage_p , leafc_xfer_p , &
+ frootc_p , frootc_storage_p , frootc_xfer_p , &
+ livestemc_p , livestemc_storage_p , livestemc_xfer_p , &
+ deadstemc_p , deadstemc_storage_p , deadstemc_xfer_p , &
+ livecrootc_p , livecrootc_storage_p, livecrootc_xfer_p, &
+ deadcrootc_p , deadcrootc_storage_p, deadcrootc_xfer_p, &
+ gresp_storage_p , gresp_xfer_p
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ ! vegetation carbon flux variables
+ m_leafc_to_fire_p , m_leafc_storage_to_fire_p , m_leafc_xfer_to_fire_p , &
+ m_frootc_to_fire_p , m_frootc_storage_to_fire_p , m_frootc_xfer_to_fire_p , &
+ m_livestemc_to_fire_p , m_livestemc_storage_to_fire_p , m_livestemc_xfer_to_fire_p , &
+ m_deadstemc_to_fire_p , m_deadstemc_storage_to_fire_p , m_deadstemc_xfer_to_fire_p , &
+ m_livecrootc_to_fire_p , m_livecrootc_storage_to_fire_p, m_livecrootc_xfer_to_fire_p, &
+ m_deadcrootc_to_fire_p , m_deadcrootc_storage_to_fire_p, m_deadcrootc_xfer_to_fire_p, &
+ m_livestemc_to_deadstemc_fire_p , m_livecrootc_to_deadcrootc_fire_p , &
+ m_gresp_storage_to_fire_p , m_gresp_xfer_to_fire_p , &
+
+ m_leafc_to_litter_fire_p , m_leafc_storage_to_litter_fire_p , m_leafc_xfer_to_litter_fire_p , &
+ m_frootc_to_litter_fire_p , m_frootc_storage_to_litter_fire_p , m_frootc_xfer_to_litter_fire_p , &
+ m_livestemc_to_litter_fire_p , m_livestemc_storage_to_litter_fire_p , m_livestemc_xfer_to_litter_fire_p , &
+ m_deadstemc_to_litter_fire_p , m_deadstemc_storage_to_litter_fire_p , m_deadstemc_xfer_to_litter_fire_p , &
+ m_livecrootc_to_litter_fire_p , m_livecrootc_storage_to_litter_fire_p, m_livecrootc_xfer_to_litter_fire_p, &
+ m_deadcrootc_to_litter_fire_p , m_deadcrootc_storage_to_litter_fire_p, m_deadcrootc_xfer_to_litter_fire_p, &
+ m_gresp_storage_to_litter_fire_p, m_gresp_xfer_to_litter_fire_p
+
+ IMPLICIT NONE
+
+ PUBLIC CStateUpdate3
+
+CONTAINS
+
+ SUBROUTINE CStateUpdate3(i, ps, pe, deltim, nl_soil, ndecomp_pools)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil number
+ integer ,intent(in) :: ndecomp_pools ! number total litter & soil pools
+
+ integer j,l,m
+
+ DO j = 1, nl_soil
+ ! patch-level wood to column-level CWD (uncombusted wood)
+ decomp_cpools_vr(j,i_cwd,i) = decomp_cpools_vr(j,i_cwd,i) &
+ + fire_mortality_to_cwdc (j,i) * deltim
+
+ ! patch-level wood to column-level litter (uncombusted wood)
+ decomp_cpools_vr(j,i_met_lit,i) = decomp_cpools_vr(j,i_met_lit,i) &
+ + fire_mortality_to_met_c(j,i) * deltim
+ decomp_cpools_vr(j,i_cel_lit,i) = decomp_cpools_vr(j,i_cel_lit,i) &
+ + fire_mortality_to_cel_c(j,i) * deltim
+ decomp_cpools_vr(j,i_lig_lit,i) = decomp_cpools_vr(j,i_lig_lit,i) &
+ + fire_mortality_to_lig_c(j,i) * deltim
+ ENDDO
+
+ ! litter and CWD losses to fire
+ DO l = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_cpools_vr(j,l,i) = decomp_cpools_vr(j,l,i) &
+ - m_decomp_cpools_to_fire_vr(j,l,i) * deltim
+ ENDDO
+ ENDDO
+
+ ! patch-level carbon fluxes from fire
+ DO m = ps , pe
+ gresp_storage_p (m) = gresp_storage_p (m) &
+ - m_gresp_storage_to_fire_p (m) * deltim
+ gresp_storage_p (m) = gresp_storage_p (m) &
+ - m_gresp_storage_to_litter_fire_p (m) * deltim
+ gresp_xfer_p (m) = gresp_xfer_p (m) &
+ - m_gresp_xfer_to_fire_p (m) * deltim
+ gresp_xfer_p (m) = gresp_xfer_p (m) &
+ - m_gresp_xfer_to_litter_fire_p (m) * deltim
+ ! displayed pools
+ leafc_p (m) = leafc_p (m) &
+ - m_leafc_to_fire_p (m) * deltim
+ leafc_p (m) = leafc_p (m) &
+ - m_leafc_to_litter_fire_p (m) * deltim
+ frootc_p (m) = frootc_p (m) &
+ - m_frootc_to_fire_p (m) * deltim
+ frootc_p (m) = frootc_p (m) &
+ - m_frootc_to_litter_fire_p (m) * deltim
+ livestemc_p (m) = livestemc_p (m) &
+ - m_livestemc_to_fire_p (m) * deltim
+ livestemc_p (m) = livestemc_p (m) &
+ - m_livestemc_to_litter_fire_p (m) * deltim &
+ - m_livestemc_to_deadstemc_fire_p (m) * deltim
+ deadstemc_p (m) = deadstemc_p (m) &
+ - m_deadstemc_to_fire_p (m) * deltim
+ deadstemc_p (m) = deadstemc_p (m) &
+ - m_deadstemc_to_litter_fire_p (m) * deltim &
+ + m_livestemc_to_deadstemc_fire_p (m) * deltim
+ livecrootc_p (m) = livecrootc_p (m) &
+ - m_livecrootc_to_fire_p (m) * deltim
+ livecrootc_p (m) = livecrootc_p (m) &
+ - m_livecrootc_to_litter_fire_p (m) * deltim &
+ - m_livecrootc_to_deadcrootc_fire_p (m) * deltim
+ deadcrootc_p (m) = deadcrootc_p (m) &
+ - m_deadcrootc_to_fire_p (m) * deltim
+ deadcrootc_p (m) = deadcrootc_p (m) &
+ - m_deadcrootc_to_litter_fire_p (m) * deltim &
+ + m_livecrootc_to_deadcrootc_fire_p (m) * deltim
+
+ ! storage pools
+ leafc_storage_p (m) = leafc_storage_p (m) &
+ - m_leafc_storage_to_fire_p (m) * deltim
+ leafc_storage_p (m) = leafc_storage_p (m) &
+ - m_leafc_storage_to_litter_fire_p (m) * deltim
+ frootc_storage_p (m) = frootc_storage_p (m) &
+ - m_frootc_storage_to_fire_p (m) * deltim
+ frootc_storage_p (m) = frootc_storage_p (m) &
+ - m_frootc_storage_to_litter_fire_p (m) * deltim
+ livestemc_storage_p (m) = livestemc_storage_p (m) &
+ - m_livestemc_storage_to_fire_p (m) * deltim
+ livestemc_storage_p (m) = livestemc_storage_p (m) &
+ - m_livestemc_storage_to_litter_fire_p (m) * deltim
+ deadstemc_storage_p (m) = deadstemc_storage_p (m) &
+ - m_deadstemc_storage_to_fire_p (m) * deltim
+ deadstemc_storage_p (m) = deadstemc_storage_p (m) &
+ - m_deadstemc_storage_to_litter_fire_p (m) * deltim
+ livecrootc_storage_p(m) = livecrootc_storage_p(m) &
+ - m_livecrootc_storage_to_fire_p (m) * deltim
+ livecrootc_storage_p(m) = livecrootc_storage_p(m) &
+ - m_livecrootc_storage_to_litter_fire_p(m) * deltim
+ deadcrootc_storage_p(m) = deadcrootc_storage_p(m) &
+ - m_deadcrootc_storage_to_fire_p (m) * deltim
+ deadcrootc_storage_p(m) = deadcrootc_storage_p(m) &
+ - m_deadcrootc_storage_to_litter_fire_p(m) * deltim
+
+ ! transfer pools
+ leafc_xfer_p (m) = leafc_xfer_p (m) &
+ - m_leafc_xfer_to_fire_p (m) * deltim
+ leafc_xfer_p (m) = leafc_xfer_p (m) &
+ - m_leafc_xfer_to_litter_fire_p (m) * deltim
+ frootc_xfer_p (m) = frootc_xfer_p (m) &
+ - m_frootc_xfer_to_fire_p (m) * deltim
+ frootc_xfer_p (m) = frootc_xfer_p (m) &
+ - m_frootc_xfer_to_litter_fire_p (m) * deltim
+ livestemc_xfer_p (m) = livestemc_xfer_p (m) &
+ - m_livestemc_xfer_to_fire_p (m) * deltim
+ livestemc_xfer_p (m) = livestemc_xfer_p (m) &
+ - m_livestemc_xfer_to_litter_fire_p (m) * deltim
+ deadstemc_xfer_p (m) = deadstemc_xfer_p (m) &
+ - m_deadstemc_xfer_to_fire_p (m) * deltim
+ deadstemc_xfer_p (m) = deadstemc_xfer_p (m) &
+ - m_deadstemc_xfer_to_litter_fire_p (m) * deltim
+ livecrootc_xfer_p (m) = livecrootc_xfer_p (m) &
+ - m_livecrootc_xfer_to_fire_p (m) * deltim
+ livecrootc_xfer_p (m) = livecrootc_xfer_p (m) &
+ - m_livecrootc_xfer_to_litter_fire_p (m) * deltim
+ deadcrootc_xfer_p (m) = deadcrootc_xfer_p (m) &
+ - m_deadcrootc_xfer_to_fire_p (m) * deltim
+ deadcrootc_xfer_p (m) = deadcrootc_xfer_p (m) &
+ - m_deadcrootc_xfer_to_litter_fire_p (m) * deltim
+ ENDDO
+
+ END SUBROUTINE CStateUpdate3
+
+END MODULE MOD_BGC_CNCStateUpdate3
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate1.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate1.F90
new file mode 100644
index 0000000000..d0678b2a5b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate1.F90
@@ -0,0 +1,410 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_CNNStateUpdate1
+
+!-------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! First updates in vegetation and soil nitrogen. The major updates are included in bgc_CNNStateUpdate1Mod
+! 1. Update phenology-associated veg and soil N pool size changes, including plant growth
+! 2. Update decomposition-associated soil N pool size changes
+! 3. Record the accumulated N transfers associated to phenology and decomposition for semi-analytic spinup
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record the accumulated phenology-associated N transfer for veg and soil N semi-analytic spinup
+! 3) Record the accumulated decomposition-associated N transfer for soil N semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_Const_PFT, only: woody
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ ! bgc constants
+ donor_pool, receiver_pool, i_met_lit, i_cel_lit, i_lig_lit, i_cwd, i_soil1, i_soil2, i_soil3
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ I_met_n_vr_acc, I_cel_n_vr_acc, I_lig_n_vr_acc
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ ! decomposition pools flux varables (in)
+ decomp_npools_sourcesink, &
+ phenology_to_met_n , phenology_to_cel_n, phenology_to_lig_n
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ ! vegetation nitrogen state variables (inout)
+ leafn_p , leafn_storage_p , leafn_xfer_p , &
+ frootn_p , frootn_storage_p , frootn_xfer_p , &
+ livestemn_p , livestemn_storage_p , livestemn_xfer_p , &
+ deadstemn_p , deadstemn_storage_p , deadstemn_xfer_p , &
+ livecrootn_p , livecrootn_storage_p, livecrootn_xfer_p, &
+ deadcrootn_p , deadcrootn_storage_p, deadcrootn_xfer_p, &
+ grainn_p , grainn_storage_p , grainn_xfer_p , &
+ cropseedn_deficit_p, retransn_p , npool_p , &
+
+ ! SASU variables
+ I_leafn_p_acc , I_leafn_st_p_acc , I_frootn_p_acc , I_frootn_st_p_acc , &
+ I_livestemn_p_acc , I_livestemn_st_p_acc , I_deadstemn_p_acc , I_deadstemn_st_p_acc , &
+ I_livecrootn_p_acc, I_livecrootn_st_p_acc, I_deadcrootn_p_acc, I_deadcrootn_st_p_acc, &
+ I_grainn_p_acc , I_grainn_st_p_acc , &
+
+ AKX_leafn_xf_to_leafn_p_acc , AKX_frootn_xf_to_frootn_p_acc , AKX_livestemn_xf_to_livestemn_p_acc , &
+ AKX_deadstemn_xf_to_deadstemn_p_acc , AKX_livecrootn_xf_to_livecrootn_p_acc , AKX_deadcrootn_xf_to_deadcrootn_p_acc , &
+ AKX_grainn_xf_to_grainn_p_acc , AKX_livestemn_to_deadstemn_p_acc , AKX_livecrootn_to_deadcrootn_p_acc , &
+
+ AKX_leafn_st_to_leafn_xf_p_acc , AKX_frootn_st_to_frootn_xf_p_acc , AKX_livestemn_st_to_livestemn_xf_p_acc , &
+ AKX_deadstemn_st_to_deadstemn_xf_p_acc, AKX_livecrootn_st_to_livecrootn_xf_p_acc, AKX_deadcrootn_st_to_deadcrootn_xf_p_acc, &
+ AKX_livestemn_st_to_livestemn_xf_p_acc, AKX_grainn_st_to_grainn_xf_p_acc , &
+
+ AKX_leafn_to_retransn_p_acc , AKX_frootn_to_retransn_p_acc , AKX_livestemn_to_retransn_p_acc , &
+ AKX_livecrootn_to_retransn_p_acc , &
+
+ AKX_retransn_to_leafn_p_acc , AKX_retransn_to_frootn_p_acc , AKX_retransn_to_livestemn_p_acc , &
+ AKX_retransn_to_deadstemn_p_acc , AKX_retransn_to_livecrootn_p_acc , AKX_retransn_to_deadcrootn_p_acc , &
+ AKX_retransn_to_grainn_p_acc , &
+
+ AKX_retransn_to_leafn_st_p_acc , AKX_retransn_to_frootn_st_p_acc , AKX_retransn_to_livestemn_st_p_acc , &
+ AKX_retransn_to_deadstemn_st_p_acc , AKX_retransn_to_livecrootn_st_p_acc , AKX_retransn_to_deadcrootn_st_p_acc , &
+ AKX_retransn_to_grainn_st_p_acc , &
+
+ AKX_leafn_exit_p_acc , AKX_frootn_exit_p_acc , AKX_livestemn_exit_p_acc , &
+ AKX_deadstemn_exit_p_acc , AKX_livecrootn_exit_p_acc , AKX_deadcrootn_exit_p_acc , &
+ AKX_grainn_exit_p_acc , AKX_retransn_exit_p_acc , &
+
+ AKX_leafn_st_exit_p_acc , AKX_frootn_st_exit_p_acc , AKX_livestemn_st_exit_p_acc , &
+ AKX_deadstemn_st_exit_p_acc , AKX_livecrootn_st_exit_p_acc , AKX_deadcrootn_st_exit_p_acc , &
+ AKX_grainn_st_exit_p_acc , &
+
+ AKX_leafn_xf_exit_p_acc , AKX_frootn_xf_exit_p_acc , AKX_livestemn_xf_exit_p_acc , &
+ AKX_deadstemn_xf_exit_p_acc , AKX_livecrootn_xf_exit_p_acc , AKX_deadcrootn_xf_exit_p_acc , &
+ AKX_grainn_xf_exit_p_acc
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ ! vegetation nitrogen flux variables (in)
+ ! xfer to display
+ leafn_xfer_to_leafn_p , frootn_xfer_to_frootn_p , &
+ livestemn_xfer_to_livestemn_p , deadstemn_xfer_to_deadstemn_p , &
+ livecrootn_xfer_to_livecrootn_p, deadcrootn_xfer_to_deadcrootn_p, &
+ grainn_xfer_to_grainn_p , &
+
+ ! storage to xfer (in)
+ leafn_storage_to_xfer_p , frootn_storage_to_xfer_p , &
+ livestemn_storage_to_xfer_p , deadstemn_storage_to_xfer_p , &
+ livecrootn_storage_to_xfer_p, deadcrootn_storage_to_xfer_p, &
+ grainn_storage_to_xfer_p , &
+
+ ! display to litter & live to dead (in)
+ leafn_to_litter_p , frootn_to_litter_p , &
+ grainn_to_food_p , grainn_to_seed_p , &
+ crop_seedn_to_leaf_p , livestemn_to_litter_p , &
+ livestemn_to_deadstemn_p, livecrootn_to_deadcrootn_p, &
+
+ ! display to retransn / retransn to npool (in)
+ leafn_to_retransn_p , frootn_to_retransn_p , &
+ livestemn_to_retransn_p , livecrootn_to_retransn_p , &
+ retransn_to_npool_p , free_retransn_to_npool_p , &
+
+ ! npool to display/storage (in)
+ npool_to_leafn_p , npool_to_leafn_storage_p , &
+ npool_to_frootn_p , npool_to_frootn_storage_p , &
+ npool_to_livestemn_p , npool_to_livestemn_storage_p , &
+ npool_to_deadstemn_p , npool_to_deadstemn_storage_p , &
+ npool_to_livecrootn_p, npool_to_livecrootn_storage_p, &
+ npool_to_deadcrootn_p, npool_to_deadcrootn_storage_p, &
+ npool_to_grainn_p , npool_to_grainn_storage_p , plant_nalloc_p
+
+ USE MOD_Vars_PFTimeInvariants, only: pftfrac
+ IMPLICIT NONE
+
+ PUBLIC NStateUpdate1
+
+CONTAINS
+
+ SUBROUTINE NStateUpdate1 (i, ps, pe, deltim, nl_soil, ndecomp_transitions, npcropmin,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ndecomp_transitions ! number of total transitions among different litter & soil bgc pools
+ integer ,intent(in) :: npcropmin ! index of first crop pft
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer
+
+ integer j,k
+ integer ivt, m
+ real(r8) f_retr_in_nall
+
+ ! soilbiogeochemistry fluxes TODO - this should be moved elsewhere
+ ! plant to litter fluxes - phenology and dynamic landcover fluxes
+ DO j = 1, nl_soil
+ decomp_npools_sourcesink(j,i_met_lit,i) = phenology_to_met_n(j,i) * deltim
+
+ decomp_npools_sourcesink(j,i_cel_lit,i) = phenology_to_cel_n(j,i) * deltim
+
+ decomp_npools_sourcesink(j,i_lig_lit,i) = phenology_to_lig_n(j,i) * deltim
+
+ decomp_npools_sourcesink(j,i_cwd,i) = 0._r8
+
+ ENDDO
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ DO j=1,nl_soil
+ I_met_n_vr_acc(j,i) = I_met_n_vr_acc(j,i) + phenology_to_met_n(j,i) * deltim
+ I_cel_n_vr_acc(j,i) = I_cel_n_vr_acc(j,i) + phenology_to_cel_n(j,i) * deltim
+ I_lig_n_vr_acc(j,i) = I_lig_n_vr_acc(j,i) + phenology_to_lig_n(j,i) * deltim
+ ENDDO
+ ENDIF
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+ ! phenology: transfer growth fluxes
+ leafn_p(m) = leafn_p(m) + leafn_xfer_to_leafn_p(m)*deltim
+ leafn_xfer_p(m) = leafn_xfer_p(m) - leafn_xfer_to_leafn_p(m)*deltim
+ frootn_p(m) = frootn_p(m) + frootn_xfer_to_frootn_p(m)*deltim
+ frootn_xfer_p(m) = frootn_xfer_p(m) - frootn_xfer_to_frootn_p(m)*deltim
+
+ IF (woody(ivt) == 1) THEN
+ livestemn_p(m) = livestemn_p(m) + livestemn_xfer_to_livestemn_p(m)*deltim
+ livestemn_xfer_p(m) = livestemn_xfer_p(m) - livestemn_xfer_to_livestemn_p(m)*deltim
+ deadstemn_p(m) = deadstemn_p(m) + deadstemn_xfer_to_deadstemn_p(m)*deltim
+ deadstemn_xfer_p(m) = deadstemn_xfer_p(m) - deadstemn_xfer_to_deadstemn_p(m)*deltim
+ livecrootn_p(m) = livecrootn_p(m) + livecrootn_xfer_to_livecrootn_p(m)*deltim
+ livecrootn_xfer_p(m) = livecrootn_xfer_p(m) - livecrootn_xfer_to_livecrootn_p(m)*deltim
+ deadcrootn_p(m) = deadcrootn_p(m) + deadcrootn_xfer_to_deadcrootn_p(m)*deltim
+ deadcrootn_xfer_p(m) = deadcrootn_xfer_p(m) - deadcrootn_xfer_to_deadcrootn_p(m)*deltim
+ ENDIF
+
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ ! lines here for consistency; the transfer terms are zero
+ livestemn_p(m) = livestemn_p(m) + livestemn_xfer_to_livestemn_p(m)*deltim
+ livestemn_xfer_p(m) = livestemn_xfer_p(m) - livestemn_xfer_to_livestemn_p(m)*deltim
+ grainn_p(m) = grainn_p(m) + grainn_xfer_to_grainn_p(m)*deltim
+ grainn_xfer_p(m) = grainn_xfer_p(m) - grainn_xfer_to_grainn_p(m)*deltim
+ ENDIF
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafn_xf_to_leafn_p_acc (m) = AKX_leafn_xf_to_leafn_p_acc (m) + leafn_xfer_to_leafn_p (m) * deltim
+ AKX_frootn_xf_to_frootn_p_acc(m) = AKX_frootn_xf_to_frootn_p_acc(m) + frootn_xfer_to_frootn_p(m) * deltim
+ AKX_leafn_xf_exit_p_acc (m) = AKX_leafn_xf_exit_p_acc (m) + leafn_xfer_to_leafn_p (m) * deltim
+ AKX_frootn_xf_exit_p_acc (m) = AKX_frootn_xf_exit_p_acc (m) + frootn_xfer_to_frootn_p(m) * deltim
+ IF(woody(ivt) == 1)THEN
+ AKX_livestemn_xf_to_livestemn_p_acc (m) = AKX_livestemn_xf_to_livestemn_p_acc (m) + livestemn_xfer_to_livestemn_p (m) * deltim
+ AKX_livestemn_xf_exit_p_acc (m) = AKX_livestemn_xf_exit_p_acc (m) + livestemn_xfer_to_livestemn_p (m) * deltim
+ AKX_deadstemn_xf_to_deadstemn_p_acc (m) = AKX_deadstemn_xf_to_deadstemn_p_acc (m) + deadstemn_xfer_to_deadstemn_p (m) * deltim
+ AKX_deadstemn_xf_exit_p_acc (m) = AKX_deadstemn_xf_exit_p_acc (m) + deadstemn_xfer_to_deadstemn_p (m) * deltim
+ AKX_livecrootn_xf_to_livecrootn_p_acc(m) = AKX_livecrootn_xf_to_livecrootn_p_acc(m) + livecrootn_xfer_to_livecrootn_p(m) * deltim
+ AKX_livecrootn_xf_exit_p_acc (m) = AKX_livecrootn_xf_exit_p_acc (m) + livecrootn_xfer_to_livecrootn_p(m) * deltim
+ AKX_deadcrootn_xf_to_deadcrootn_p_acc(m) = AKX_deadcrootn_xf_to_deadcrootn_p_acc(m) + deadcrootn_xfer_to_deadcrootn_p(m) * deltim
+ AKX_deadcrootn_xf_exit_p_acc (m) = AKX_deadcrootn_xf_exit_p_acc (m) + deadcrootn_xfer_to_deadcrootn_p(m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin) THEN
+ AKX_livestemn_xf_to_livestemn_p_acc(m) = AKX_livestemn_xf_to_livestemn_p_acc(m) + livestemn_xfer_to_livestemn_p(m) * deltim
+ AKX_livestemn_xf_exit_p_acc (m) = AKX_livestemn_xf_exit_p_acc (m) + livestemn_xfer_to_livestemn_p(m) * deltim
+ AKX_grainn_xf_to_grainn_p_acc (m) = AKX_grainn_xf_to_grainn_p_acc (m) + grainn_xfer_to_grainn_p (m) * deltim
+ AKX_grainn_xf_exit_p_acc (m) = AKX_grainn_xf_exit_p_acc (m) + grainn_xfer_to_grainn_p (m) * deltim
+ ENDIF
+ ENDIF
+
+ ! phenology: litterfall and retranslocation fluxes
+ leafn_p(m) = leafn_p(m) - leafn_to_litter_p(m)*deltim
+ frootn_p(m) = frootn_p(m) - frootn_to_litter_p(m)*deltim
+ leafn_p(m) = leafn_p(m) - leafn_to_retransn_p(m)*deltim
+ retransn_p(m) = retransn_p(m) + leafn_to_retransn_p(m)*deltim
+
+ ! live wood turnover and retranslocation fluxes
+ IF (woody(ivt) == 1) THEN
+ livestemn_p(m) = livestemn_p(m) - livestemn_to_deadstemn_p(m)*deltim
+ deadstemn_p(m) = deadstemn_p(m) + livestemn_to_deadstemn_p(m)*deltim
+ livecrootn_p(m) = livecrootn_p(m) - livecrootn_to_deadcrootn_p(m)*deltim
+ deadcrootn_p(m) = deadcrootn_p(m) + livecrootn_to_deadcrootn_p(m)*deltim
+
+ livestemn_p(m) = livestemn_p(m) - livestemn_to_retransn_p(m)*deltim
+ retransn_p(m) = retransn_p(m) + livestemn_to_retransn_p(m)*deltim
+ livecrootn_p(m) = livecrootn_p(m) - livecrootn_to_retransn_p(m)*deltim
+ retransn_p(m) = retransn_p(m) + livecrootn_to_retransn_p(m)*deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN
+ frootn_p(m) = frootn_p(m) - frootn_to_retransn_p(m)*deltim
+ retransn_p(m) = retransn_p(m) + frootn_to_retransn_p(m)*deltim
+ livestemn_p(m) = livestemn_p(m) - livestemn_to_litter_p(m)*deltim
+ livestemn_p(m) = livestemn_p(m) - livestemn_to_retransn_p(m)*deltim
+ retransn_p(m) = retransn_p(m) + livestemn_to_retransn_p(m)*deltim
+ grainn_p(m) = grainn_p(m) &
+ - (grainn_to_food_p(m) + grainn_to_seed_p(m))*deltim
+ cropseedn_deficit_p(m) = cropseedn_deficit_p(m) &
+ - crop_seedn_to_leaf_p(m) * deltim &
+ + grainn_to_seed_p(m) * deltim
+ ENDIF
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafn_exit_p_acc (m) = AKX_leafn_exit_p_acc (m) + leafn_to_litter_p (m) * deltim
+ AKX_frootn_exit_p_acc (m) = AKX_frootn_exit_p_acc (m) + frootn_to_litter_p (m) * deltim
+ AKX_leafn_to_retransn_p_acc(m) = AKX_leafn_to_retransn_p_acc(m) + leafn_to_retransn_p(m) * deltim
+ AKX_leafn_exit_p_acc (m) = AKX_leafn_exit_p_acc (m) + leafn_to_retransn_p(m) * deltim
+ IF(woody(ivt) == 1) THEN
+ AKX_livestemn_to_deadstemn_p_acc (m) = AKX_livestemn_to_deadstemn_p_acc (m) + livestemn_to_deadstemn_p (m) * deltim
+ AKX_livestemn_exit_p_acc (m) = AKX_livestemn_exit_p_acc (m) + livestemn_to_deadstemn_p (m) * deltim
+ AKX_livecrootn_to_deadcrootn_p_acc(m) = AKX_livecrootn_to_deadcrootn_p_acc(m) + livecrootn_to_deadcrootn_p(m) * deltim
+ AKX_livecrootn_exit_p_acc (m) = AKX_livecrootn_exit_p_acc (m) + livecrootn_to_deadcrootn_p(m) * deltim
+
+ AKX_livestemn_to_retransn_p_acc (m) = AKX_livestemn_to_retransn_p_acc (m) + livestemn_to_retransn_p (m) * deltim
+ AKX_livestemn_exit_p_acc (m) = AKX_livestemn_exit_p_acc (m) + livestemn_to_retransn_p (m) * deltim
+ AKX_livecrootn_to_retransn_p_acc (m) = AKX_livecrootn_to_retransn_p_acc (m) + livecrootn_to_retransn_p (m) * deltim
+ AKX_livecrootn_exit_p_acc (m) = AKX_livecrootn_exit_p_acc (m) + livecrootn_to_retransn_p (m) * deltim
+ ENDIF
+ IF(ivt >= npcropmin) THEN
+ AKX_frootn_to_retransn_p_acc (m) = AKX_frootn_to_retransn_p_acc (m) + frootn_to_retransn_p (m) * deltim
+ AKX_frootn_exit_p_acc (m) = AKX_frootn_exit_p_acc (m) + frootn_to_retransn_p (m) * deltim
+ AKX_livestemn_exit_p_acc (m) = AKX_livestemn_exit_p_acc (m) + livestemn_to_litter_p (m) * deltim
+ AKX_livestemn_to_retransn_p_acc (m) = AKX_livestemn_to_retransn_p_acc (m) + livestemn_to_retransn_p (m) * deltim
+ AKX_livestemn_exit_p_acc (m) = AKX_livestemn_exit_p_acc (m) + livestemn_to_retransn_p (m) * deltim
+ AKX_grainn_exit_p_acc (m) = AKX_grainn_exit_p_acc (m) + (grainn_to_food_p(m) + grainn_to_seed_p(m)) * deltim
+ ENDIF
+ ENDIF
+
+ ! allocation fluxes
+ retransn_p(m) = retransn_p(m) - retransn_to_npool_p(m)*deltim
+ retransn_p(m) = retransn_p(m) - free_retransn_to_npool_p(m)*deltim
+ leafn_p(m) = leafn_p(m) + npool_to_leafn_p(m)*deltim
+ leafn_storage_p(m) = leafn_storage_p(m) + npool_to_leafn_storage_p(m)*deltim
+ frootn_p(m) = frootn_p(m) + npool_to_frootn_p(m)*deltim
+ frootn_storage_p(m) = frootn_storage_p(m) + npool_to_frootn_storage_p(m)*deltim
+
+ IF (woody(ivt) == 1) THEN
+ livestemn_p(m) = livestemn_p(m) + npool_to_livestemn_p(m)*deltim
+ livestemn_storage_p(m) = livestemn_storage_p(m) + npool_to_livestemn_storage_p(m)*deltim
+ deadstemn_p(m) = deadstemn_p(m) + npool_to_deadstemn_p(m)*deltim
+ deadstemn_storage_p(m) = deadstemn_storage_p(m) + npool_to_deadstemn_storage_p(m)*deltim
+ livecrootn_p(m) = livecrootn_p(m) + npool_to_livecrootn_p(m)*deltim
+ livecrootn_storage_p(m) = livecrootn_storage_p(m) + npool_to_livecrootn_storage_p(m)*deltim
+ deadcrootn_p(m) = deadcrootn_p(m) + npool_to_deadcrootn_p(m)*deltim
+ deadcrootn_storage_p(m) = deadcrootn_storage_p(m) + npool_to_deadcrootn_storage_p(m)*deltim
+ ENDIF
+
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ livestemn_p(m) = livestemn_p(m) + npool_to_livestemn_p(m)*deltim
+ livestemn_storage_p(m) = livestemn_storage_p(m) + npool_to_livestemn_storage_p(m)*deltim
+ grainn_p(m) = grainn_p(m) + npool_to_grainn_p(m)*deltim
+ grainn_storage_p(m) = grainn_storage_p(m) + npool_to_grainn_storage_p(m)*deltim
+ ENDIF
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ IF(plant_nalloc_p(m) .ne. 0)THEN
+ f_retr_in_nall = retransn_to_npool_p(m) / plant_nalloc_p(m)
+ AKX_retransn_exit_p_acc (m) = AKX_retransn_exit_p_acc (m) &
+ + (retransn_to_npool_p (m) + free_retransn_to_npool_p (m)) * deltim
+ I_leafn_p_acc (m) = I_leafn_p_acc (m) + npool_to_leafn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_leafn_p_acc (m) = AKX_retransn_to_leafn_p_acc (m) + npool_to_leafn_p (m) * f_retr_in_nall * deltim
+ I_leafn_st_p_acc (m) = I_leafn_st_p_acc (m) + npool_to_leafn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_leafn_st_p_acc (m) = AKX_retransn_to_leafn_st_p_acc (m) + npool_to_leafn_storage_p (m) * f_retr_in_nall * deltim
+ I_frootn_p_acc (m) = I_frootn_p_acc (m) + npool_to_frootn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_frootn_p_acc (m) = AKX_retransn_to_frootn_p_acc (m) + npool_to_frootn_p (m) * f_retr_in_nall * deltim
+ I_frootn_st_p_acc (m) = I_frootn_st_p_acc (m) + npool_to_frootn_storage_p(m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_frootn_st_p_acc(m) = AKX_retransn_to_frootn_st_p_acc(m) + npool_to_frootn_storage_p(m) * f_retr_in_nall * deltim
+ IF(woody(ivt) == 1)THEN
+ I_livestemn_p_acc (m) = I_livestemn_p_acc (m) &
+ + npool_to_livestemn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_livestemn_p_acc (m) = AKX_retransn_to_livestemn_p_acc (m) &
+ + npool_to_livestemn_p (m) * f_retr_in_nall * deltim
+ I_livestemn_st_p_acc (m) = I_livestemn_st_p_acc (m) &
+ + npool_to_livestemn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_livestemn_st_p_acc (m) = AKX_retransn_to_livestemn_st_p_acc (m) &
+ + npool_to_livestemn_storage_p (m) * f_retr_in_nall * deltim
+ I_deadstemn_p_acc (m) = I_deadstemn_p_acc (m) &
+ + npool_to_deadstemn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_deadstemn_p_acc (m) = AKX_retransn_to_deadstemn_p_acc (m) &
+ + npool_to_deadstemn_p (m) * f_retr_in_nall * deltim
+ I_deadstemn_st_p_acc (m) = I_deadstemn_st_p_acc (m) &
+ + npool_to_deadstemn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_deadstemn_st_p_acc (m) = AKX_retransn_to_deadstemn_st_p_acc (m) &
+ + npool_to_deadstemn_storage_p (m) * f_retr_in_nall * deltim
+ I_livecrootn_p_acc (m) = I_livecrootn_p_acc (m) &
+ + npool_to_livecrootn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_livecrootn_p_acc (m) = AKX_retransn_to_livecrootn_p_acc (m) &
+ + npool_to_livecrootn_p (m) * f_retr_in_nall * deltim
+ I_livecrootn_st_p_acc (m) = I_livecrootn_st_p_acc (m) &
+ + npool_to_livecrootn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_livecrootn_st_p_acc(m) = AKX_retransn_to_livecrootn_st_p_acc(m) &
+ + npool_to_livecrootn_storage_p (m) * f_retr_in_nall * deltim
+ I_deadcrootn_p_acc (m) = I_deadcrootn_p_acc (m) &
+ + npool_to_deadcrootn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_deadcrootn_p_acc (m) = AKX_retransn_to_deadcrootn_p_acc (m) &
+ + npool_to_deadcrootn_p (m) * f_retr_in_nall * deltim
+ I_deadcrootn_st_p_acc (m) = I_deadcrootn_st_p_acc (m) &
+ + npool_to_deadcrootn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_deadcrootn_st_p_acc(m) = AKX_retransn_to_deadcrootn_st_p_acc(m) &
+ + npool_to_deadcrootn_storage_p (m) * f_retr_in_nall * deltim
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ I_livestemn_p_acc (m) = I_livestemn_p_acc (m) &
+ + npool_to_livestemn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_livestemn_p_acc (m) = AKX_retransn_to_livestemn_p_acc(m) &
+ + npool_to_livestemn_p (m) * f_retr_in_nall * deltim
+ I_livestemn_st_p_acc (m) = I_livestemn_st_p_acc (m) &
+ + npool_to_livestemn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_livestemn_st_p_acc (m) = AKX_retransn_to_livestemn_st_p_acc(m) &
+ + npool_to_livestemn_storage_p (m) * f_retr_in_nall * deltim
+ I_grainn_p_acc (m) = I_grainn_p_acc (m) &
+ + npool_to_grainn_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_grainn_p_acc (m) = AKX_retransn_to_grainn_p_acc (m) &
+ + npool_to_grainn_p (m) * f_retr_in_nall * deltim
+ I_grainn_st_p_acc (m) = I_grainn_st_p_acc (m) &
+ + npool_to_grainn_storage_p (m) * (1._r8 - f_retr_in_nall) * deltim
+ AKX_retransn_to_grainn_st_p_acc (m) = AKX_retransn_to_grainn_st_p_acc(m) &
+ + npool_to_grainn_storage_p (m) * f_retr_in_nall * deltim
+ ENDIF
+ ENDIF
+ ENDIF
+ ! move storage pools into transfer pools
+ leafn_storage_p(m) = leafn_storage_p(m) - leafn_storage_to_xfer_p(m)*deltim
+ leafn_xfer_p(m) = leafn_xfer_p(m) + leafn_storage_to_xfer_p(m)*deltim
+ frootn_storage_p(m) = frootn_storage_p(m) - frootn_storage_to_xfer_p(m)*deltim
+ frootn_xfer_p(m) = frootn_xfer_p(m) + frootn_storage_to_xfer_p(m)*deltim
+
+ IF (woody(ivt) == 1) THEN
+ livestemn_storage_p(m) = livestemn_storage_p(m) - livestemn_storage_to_xfer_p(m)*deltim
+ livestemn_xfer_p(m) = livestemn_xfer_p(m) + livestemn_storage_to_xfer_p(m)*deltim
+ deadstemn_storage_p(m) = deadstemn_storage_p(m) - deadstemn_storage_to_xfer_p(m)*deltim
+ deadstemn_xfer_p(m) = deadstemn_xfer_p(m) + deadstemn_storage_to_xfer_p(m)*deltim
+ livecrootn_storage_p(m) = livecrootn_storage_p(m) - livecrootn_storage_to_xfer_p(m)*deltim
+ livecrootn_xfer_p(m) = livecrootn_xfer_p(m) + livecrootn_storage_to_xfer_p(m)*deltim
+ deadcrootn_storage_p(m) = deadcrootn_storage_p(m) - deadcrootn_storage_to_xfer_p(m)*deltim
+ deadcrootn_xfer_p(m) = deadcrootn_xfer_p(m) + deadcrootn_storage_to_xfer_p(m)*deltim
+ ENDIF
+
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ ! lines here for consistency; the transfer terms are zero
+ livestemn_storage_p(m) = livestemn_storage_p(m) - livestemn_storage_to_xfer_p(m)*deltim
+ livestemn_xfer_p(m) = livestemn_xfer_p(m) + livestemn_storage_to_xfer_p(m)*deltim
+ grainn_storage_p(m) = grainn_storage_p(m) - grainn_storage_to_xfer_p(m)*deltim
+ grainn_xfer_p(m) = grainn_xfer_p(m) + grainn_storage_to_xfer_p(m)*deltim
+ ENDIF
+
+ IF(DEF_USE_SASU)THEN
+ AKX_leafn_st_to_leafn_xf_p_acc (m) = AKX_leafn_st_to_leafn_xf_p_acc (m) + leafn_storage_to_xfer_p (m) * deltim
+ AKX_leafn_st_exit_p_acc (m) = AKX_leafn_st_exit_p_acc (m) + leafn_storage_to_xfer_p (m) * deltim
+ AKX_frootn_st_to_frootn_xf_p_acc (m) = AKX_frootn_st_to_frootn_xf_p_acc (m) + frootn_storage_to_xfer_p (m) * deltim
+ AKX_frootn_st_exit_p_acc (m) = AKX_frootn_st_exit_p_acc (m) + frootn_storage_to_xfer_p (m) * deltim
+ IF(woody(ivt) == 1) THEN
+ AKX_livestemn_st_to_livestemn_xf_p_acc (m) = AKX_livestemn_st_to_livestemn_xf_p_acc (m) + livestemn_storage_to_xfer_p (m) * deltim
+ AKX_livestemn_st_exit_p_acc (m) = AKX_livestemn_st_exit_p_acc (m) + livestemn_storage_to_xfer_p (m) * deltim
+ AKX_deadstemn_st_to_deadstemn_xf_p_acc (m) = AKX_deadstemn_st_to_deadstemn_xf_p_acc (m) + deadstemn_storage_to_xfer_p (m) * deltim
+ AKX_deadstemn_st_exit_p_acc (m) = AKX_deadstemn_st_exit_p_acc (m) + deadstemn_storage_to_xfer_p (m) * deltim
+ AKX_livecrootn_st_to_livecrootn_xf_p_acc(m) = AKX_livecrootn_st_to_livecrootn_xf_p_acc(m) + livecrootn_storage_to_xfer_p(m) * deltim
+ AKX_livecrootn_st_exit_p_acc (m) = AKX_livecrootn_st_exit_p_acc (m) + livecrootn_storage_to_xfer_p(m) * deltim
+ AKX_deadcrootn_st_to_deadcrootn_xf_p_acc(m) = AKX_deadcrootn_st_to_deadcrootn_xf_p_acc(m) + deadcrootn_storage_to_xfer_p(m) * deltim
+ AKX_deadcrootn_st_exit_p_acc (m) = AKX_deadcrootn_st_exit_p_acc (m) + deadcrootn_storage_to_xfer_p(m) * deltim
+ ENDIF
+ IF( ivt >= npcropmin) THEN
+ AKX_livestemn_st_to_livestemn_xf_p_acc (m) = AKX_livestemn_st_to_livestemn_xf_p_acc (m) + livestemn_storage_to_xfer_p (m) * deltim
+ AKX_livestemn_st_exit_p_acc (m) = AKX_livestemn_st_exit_p_acc (m) + livestemn_storage_to_xfer_p (m) * deltim
+ AKX_grainn_st_to_grainn_xf_p_acc (m) = AKX_grainn_st_to_grainn_xf_p_acc (m) + grainn_storage_to_xfer_p (m) * deltim
+ AKX_grainn_st_exit_p_acc (m) = AKX_grainn_st_exit_p_acc (m) + grainn_storage_to_xfer_p (m) * deltim
+ ENDIF
+ ENDIF
+ ENDDO ! END pft loop
+
+ END SUBROUTINE NStateUpdate1
+
+END MODULE MOD_BGC_CNNStateUpdate1
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate2.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate2.F90
new file mode 100644
index 0000000000..d44a47e063
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate2.F90
@@ -0,0 +1,172 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_CNNStateUpdate2
+
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! First updates in vegetation and soil nitrogen. The major updates are included in bgc_CNNStateUpdate1Mod
+! 1. Update gap-mortality-associated veg and soil N pool size changes
+! 2. Record the accumulated N transfers associated to gap-mortality for semi-analytic spinup
+
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record the accumulated gap-mortality-associated N transfers for veg and soil N semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ i_met_lit,i_cel_lit,i_lig_lit ,i_cwd, i_soil1, i_soil2,i_soil3
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decompositionn nitrogen pools & fluxes variables (inout)
+ decomp_npools_vr, &
+ I_met_n_vr_acc , I_cel_n_vr_acc , I_lig_n_vr_acc , I_cwd_n_vr_acc
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ gap_mortality_to_met_n, gap_mortality_to_cel_n , &
+ gap_mortality_to_lig_n, gap_mortality_to_cwdn
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ ! vegetation nitrogen state variables (inout)
+ leafn_p , leafn_storage_p , leafn_xfer_p , &
+ frootn_p , frootn_storage_p , frootn_xfer_p , &
+ livestemn_p , livestemn_storage_p , livestemn_xfer_p , &
+ deadstemn_p , deadstemn_storage_p , deadstemn_xfer_p , &
+ livecrootn_p , livecrootn_storage_p, livecrootn_xfer_p, &
+ deadcrootn_p , deadcrootn_storage_p, deadcrootn_xfer_p, &
+ retransn_p , npool_p, grainn_p, grainn_storage_p, grainn_xfer_p, cropseedn_deficit_p, &
+
+ ! SASU variables
+ AKX_leafn_exit_p_acc , AKX_leafn_st_exit_p_acc , AKX_leafn_xf_exit_p_acc , &
+ AKX_frootn_exit_p_acc , AKX_frootn_st_exit_p_acc , AKX_frootn_xf_exit_p_acc , &
+ AKX_livestemn_exit_p_acc , AKX_livestemn_st_exit_p_acc , AKX_livestemn_xf_exit_p_acc , &
+ AKX_deadstemn_exit_p_acc , AKX_deadstemn_st_exit_p_acc , AKX_deadstemn_xf_exit_p_acc , &
+ AKX_livecrootn_exit_p_acc, AKX_livecrootn_st_exit_p_acc, AKX_livecrootn_xf_exit_p_acc, &
+ AKX_deadcrootn_exit_p_acc, AKX_deadcrootn_st_exit_p_acc, AKX_deadcrootn_xf_exit_p_acc, &
+ AKX_retransn_exit_p_acc
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ ! vegetation nitrogen flux variables
+ m_leafn_to_litter_p , m_leafn_storage_to_litter_p , m_leafn_xfer_to_litter_p , &
+ m_frootn_to_litter_p , m_frootn_storage_to_litter_p , m_frootn_xfer_to_litter_p , &
+ m_livestemn_to_litter_p , m_livestemn_storage_to_litter_p , m_livestemn_xfer_to_litter_p , &
+ m_deadstemn_to_litter_p , m_deadstemn_storage_to_litter_p , m_deadstemn_xfer_to_litter_p , &
+ m_livecrootn_to_litter_p , m_livecrootn_storage_to_litter_p, m_livecrootn_xfer_to_litter_p, &
+ m_deadcrootn_to_litter_p , m_deadcrootn_storage_to_litter_p, m_deadcrootn_xfer_to_litter_p, &
+ m_retransn_to_litter_p
+
+ USE MOD_Vars_PFTimeInvariants, only: pftfrac
+ IMPLICIT NONE
+
+ PUBLIC NStateUpdate2
+
+CONTAINS
+
+ SUBROUTINE NStateUpdate2(i, ps, pe, deltim, nl_soil, dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer
+
+ integer j, m
+
+ ! column-level nitrogen fluxes from gap-phase mortality
+ DO j = 1, nl_soil
+ decomp_npools_vr(j,i_met_lit,i) = &
+ decomp_npools_vr(j,i_met_lit,i) + gap_mortality_to_met_n(j,i) * deltim
+ decomp_npools_vr(j,i_cel_lit,i) = &
+ decomp_npools_vr(j,i_cel_lit,i) + gap_mortality_to_cel_n(j,i) * deltim
+ decomp_npools_vr(j,i_lig_lit,i) = &
+ decomp_npools_vr(j,i_lig_lit,i) + gap_mortality_to_lig_n(j,i) * deltim
+ decomp_npools_vr(j,i_cwd,i) = &
+ decomp_npools_vr(j,i_cwd,i) + gap_mortality_to_cwdn(j,i) * deltim
+ ENDDO
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ DO j=1,nl_soil
+ I_met_n_vr_acc(j,i) = I_met_n_vr_acc(j,i) + gap_mortality_to_met_n(j,i) * deltim
+ I_cel_n_vr_acc(j,i) = I_cel_n_vr_acc(j,i) + gap_mortality_to_cel_n(j,i) * deltim
+ I_lig_n_vr_acc(j,i) = I_lig_n_vr_acc(j,i) + gap_mortality_to_lig_n(j,i) * deltim
+ I_cwd_n_vr_acc(j,i) = I_cwd_n_vr_acc(j,i) + gap_mortality_to_cwdn (j,i) * deltim
+ ENDDO
+ ENDIF
+ ! patch -level nitrogen fluxes from gap-phase mortality
+
+ ! displayed pools
+ DO m = ps, pe
+ leafn_p (m) = leafn_p (m) &
+ - m_leafn_to_litter_p (m) * deltim
+ frootn_p (m) = frootn_p (m) &
+ - m_frootn_to_litter_p (m) * deltim
+ livestemn_p (m) = livestemn_p (m) &
+ - m_livestemn_to_litter_p (m) * deltim
+ deadstemn_p (m) = deadstemn_p (m) &
+ - m_deadstemn_to_litter_p (m) * deltim
+ livecrootn_p (m) = livecrootn_p (m) &
+ - m_livecrootn_to_litter_p (m) * deltim
+ deadcrootn_p (m) = deadcrootn_p (m) &
+ - m_deadcrootn_to_litter_p (m) * deltim
+ retransn_p (m) = retransn_p (m) &
+ - m_retransn_to_litter_p (m) * deltim
+
+ ! storage pools
+ leafn_storage_p (m) = leafn_storage_p (m) &
+ - m_leafn_storage_to_litter_p (m) * deltim
+ frootn_storage_p (m) = frootn_storage_p (m) &
+ - m_frootn_storage_to_litter_p (m) * deltim
+ livestemn_storage_p (m) = livestemn_storage_p (m) &
+ - m_livestemn_storage_to_litter_p (m) * deltim
+ deadstemn_storage_p (m) = deadstemn_storage_p (m) &
+ - m_deadstemn_storage_to_litter_p (m) * deltim
+ livecrootn_storage_p(m) = livecrootn_storage_p(m) &
+ - m_livecrootn_storage_to_litter_p(m) * deltim
+ deadcrootn_storage_p(m) = deadcrootn_storage_p(m) &
+ - m_deadcrootn_storage_to_litter_p(m) * deltim
+
+ ! transfer pools
+ leafn_xfer_p (m) = leafn_xfer_p (m) &
+ - m_leafn_xfer_to_litter_p (m) * deltim
+ frootn_xfer_p (m) = frootn_xfer_p (m) &
+ - m_frootn_xfer_to_litter_p (m) * deltim
+ livestemn_xfer_p (m) = livestemn_xfer_p (m) &
+ - m_livestemn_xfer_to_litter_p (m) * deltim
+ deadstemn_xfer_p (m) = deadstemn_xfer_p (m) &
+ - m_deadstemn_xfer_to_litter_p (m) * deltim
+ livecrootn_xfer_p (m) = livecrootn_xfer_p (m) &
+ - m_livecrootn_xfer_to_litter_p (m) * deltim
+ deadcrootn_xfer_p (m) = deadcrootn_xfer_p (m) &
+ - m_deadcrootn_xfer_to_litter_p (m) * deltim
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ AKX_leafn_exit_p_acc (m) = AKX_leafn_exit_p_acc (m) + m_leafn_to_litter_p (m) * deltim
+ AKX_frootn_exit_p_acc (m) = AKX_frootn_exit_p_acc (m) + m_frootn_to_litter_p (m) * deltim
+ AKX_livestemn_exit_p_acc (m) = AKX_livestemn_exit_p_acc (m) + m_livestemn_to_litter_p (m) * deltim
+ AKX_deadstemn_exit_p_acc (m) = AKX_deadstemn_exit_p_acc (m) + m_deadstemn_to_litter_p (m) * deltim
+ AKX_livecrootn_exit_p_acc (m) = AKX_livecrootn_exit_p_acc (m) + m_livecrootn_to_litter_p (m) * deltim
+ AKX_deadcrootn_exit_p_acc (m) = AKX_deadcrootn_exit_p_acc (m) + m_deadcrootn_to_litter_p (m) * deltim
+ AKX_retransn_exit_p_acc (m) = AKX_retransn_exit_p_acc (m) + m_retransn_to_litter_p (m) * deltim
+
+ AKX_leafn_st_exit_p_acc (m) = AKX_leafn_st_exit_p_acc (m) + m_leafn_storage_to_litter_p (m) * deltim
+ AKX_frootn_st_exit_p_acc (m) = AKX_frootn_st_exit_p_acc (m) + m_frootn_storage_to_litter_p (m) * deltim
+ AKX_livestemn_st_exit_p_acc (m) = AKX_livestemn_st_exit_p_acc (m) + m_livestemn_storage_to_litter_p (m) * deltim
+ AKX_deadstemn_st_exit_p_acc (m) = AKX_deadstemn_st_exit_p_acc (m) + m_deadstemn_storage_to_litter_p (m) * deltim
+ AKX_livecrootn_st_exit_p_acc (m) = AKX_livecrootn_st_exit_p_acc (m) + m_livecrootn_storage_to_litter_p(m) * deltim
+ AKX_deadcrootn_st_exit_p_acc (m) = AKX_deadcrootn_st_exit_p_acc (m) + m_deadcrootn_storage_to_litter_p(m) * deltim
+
+ AKX_leafn_xf_exit_p_acc (m) = AKX_leafn_xf_exit_p_acc (m) + m_leafn_xfer_to_litter_p (m) * deltim
+ AKX_frootn_xf_exit_p_acc (m) = AKX_frootn_xf_exit_p_acc (m) + m_frootn_xfer_to_litter_p (m) * deltim
+ AKX_livestemn_xf_exit_p_acc (m) = AKX_livestemn_xf_exit_p_acc (m) + m_livestemn_xfer_to_litter_p (m) * deltim
+ AKX_deadstemn_xf_exit_p_acc (m) = AKX_deadstemn_xf_exit_p_acc (m) + m_deadstemn_xfer_to_litter_p (m) * deltim
+ AKX_livecrootn_xf_exit_p_acc (m) = AKX_livecrootn_xf_exit_p_acc (m) + m_livecrootn_xfer_to_litter_p (m) * deltim
+ AKX_deadcrootn_xf_exit_p_acc (m) = AKX_deadcrootn_xf_exit_p_acc (m) + m_deadcrootn_xfer_to_litter_p (m) * deltim
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE NStateUpdate2
+
+END MODULE MOD_BGC_CNNStateUpdate2
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate3.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate3.F90
new file mode 100644
index 0000000000..eff81d7448
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNNStateUpdate3.F90
@@ -0,0 +1,222 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_CNNStateUpdate3
+
+!-------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! First updates in vegetation and soil nitrogen. The major updates are included in bgc_CNNStateUpdate1Mod
+! 1. Update fire-associated veg and soil(litter) N pool size changes
+! 2. Record the accumulated N transfers associated to fire for semi-analytic spinup
+
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! !REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record accumulated fire-associated N transfers for veg and soil N semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_NITRIF, DEF_USE_FIRE
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ i_met_lit,i_cel_lit,i_lig_lit ,i_cwd, i_soil1, i_soil2, i_soil3
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decomposition pools & fluxes variables (inout)
+ decomp_npools_vr, sminn_vr, smin_no3_vr, smin_nh4_vr
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ m_decomp_npools_to_fire_vr, &
+ fire_mortality_to_met_n, fire_mortality_to_cel_n, &
+ fire_mortality_to_lig_n, fire_mortality_to_cwdn , &
+
+ ! mineral nitrogen pools & fluxes variables (inout)
+ sminn_leached_vr, smin_no3_leached_vr, smin_no3_runoff_vr
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ ! vegetation nitrogen state variables (inout)
+ leafn_p , leafn_storage_p , leafn_xfer_p , &
+ frootn_p , frootn_storage_p , frootn_xfer_p , &
+ livestemn_p , livestemn_storage_p , livestemn_xfer_p , &
+ deadstemn_p , deadstemn_storage_p , deadstemn_xfer_p , &
+ livecrootn_p , livecrootn_storage_p, livecrootn_xfer_p, &
+ deadcrootn_p , deadcrootn_storage_p, deadcrootn_xfer_p, &
+ retransn_p
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ ! vegetation nitrogen flux variables
+ m_leafn_to_fire_p , m_leafn_storage_to_fire_p , m_leafn_xfer_to_fire_p , &
+ m_frootn_to_fire_p , m_frootn_storage_to_fire_p , m_frootn_xfer_to_fire_p , &
+ m_livestemn_to_fire_p , m_livestemn_storage_to_fire_p , m_livestemn_xfer_to_fire_p , &
+ m_deadstemn_to_fire_p , m_deadstemn_storage_to_fire_p , m_deadstemn_xfer_to_fire_p , &
+ m_livecrootn_to_fire_p , m_livecrootn_storage_to_fire_p, m_livecrootn_xfer_to_fire_p, &
+ m_deadcrootn_to_fire_p , m_deadcrootn_storage_to_fire_p, m_deadcrootn_xfer_to_fire_p, &
+ m_livestemn_to_deadstemn_fire_p , m_livecrootn_to_deadcrootn_fire_p , &
+ m_retransn_to_fire_p, &
+
+ m_leafn_to_litter_fire_p , m_leafn_storage_to_litter_fire_p , m_leafn_xfer_to_litter_fire_p , &
+ m_frootn_to_litter_fire_p , m_frootn_storage_to_litter_fire_p , m_frootn_xfer_to_litter_fire_p , &
+ m_livestemn_to_litter_fire_p , m_livestemn_storage_to_litter_fire_p , m_livestemn_xfer_to_litter_fire_p , &
+ m_deadstemn_to_litter_fire_p , m_deadstemn_storage_to_litter_fire_p , m_deadstemn_xfer_to_litter_fire_p , &
+ m_livecrootn_to_litter_fire_p , m_livecrootn_storage_to_litter_fire_p, m_livecrootn_xfer_to_litter_fire_p, &
+ m_deadcrootn_to_litter_fire_p , m_deadcrootn_storage_to_litter_fire_p, m_deadcrootn_xfer_to_litter_fire_p, &
+ m_retransn_to_litter_fire_p
+
+
+ IMPLICIT NONE
+
+ PUBLIC NStateUpdate3
+
+CONTAINS
+
+ SUBROUTINE NStateUpdate3(i, ps, pe, deltim, nl_soil, ndecomp_pools, dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+
+ integer ,intent(in) :: nl_soil ! number of total soil number
+ integer ,intent(in) :: ndecomp_pools ! number total litter & soil pools
+ real(r8),intent(in) :: dz_soi(1:nl_soil)! thicnesses of eacn soil layer
+
+ integer j,l,m
+
+
+ IF(.not. DEF_USE_NITRIF)THEN
+ ! mineral N loss due to leaching
+ DO j = 1, nl_soil
+ sminn_vr(j,i) = sminn_vr(j,i) - sminn_leached_vr(j,i) * deltim
+ ENDDO
+ ELSE
+ DO j = 1, nl_soil
+ ! mineral N loss due to leaching and runoff
+ smin_no3_vr(j,i) = max( smin_no3_vr(j,i) &
+ - ( smin_no3_leached_vr(j,i) + smin_no3_runoff_vr(j,i) ) * deltim, 0._r8)
+
+ sminn_vr(j,i) = smin_no3_vr(j,i) + smin_nh4_vr(j,i)
+ ENDDO
+ ENDIF
+
+ ! column level nitrogen fluxes from fire
+ ! patch-level wood to column-level CWD (uncombusted wood)
+ IF(DEF_USE_FIRE)THEN
+ DO j = 1, nl_soil
+ decomp_npools_vr(j,i_cwd,i) = decomp_npools_vr(j,i_cwd,i) &
+ + fire_mortality_to_cwdn(j,i) * deltim
+
+ ! patch-level wood to column-level litter (uncombusted wood)
+ decomp_npools_vr(j,i_met_lit,i) = decomp_npools_vr(j,i_met_lit,i) &
+ + fire_mortality_to_met_n(j,i)* deltim
+ decomp_npools_vr(j,i_cel_lit,i) = decomp_npools_vr(j,i_cel_lit,i) &
+ + fire_mortality_to_cel_n(j,i)* deltim
+ decomp_npools_vr(j,i_lig_lit,i) = decomp_npools_vr(j,i_lig_lit,i) &
+ + fire_mortality_to_lig_n(j,i)* deltim
+ ENDDO
+
+ ! litter and CWD losses to fire
+ DO l = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_npools_vr(j,l,i) = decomp_npools_vr(j,l,i) &
+ - m_decomp_npools_to_fire_vr(j,l,i) * deltim
+ ENDDO
+ ENDDO
+
+ DO m = ps , pe
+ !from fire displayed pools
+ leafn_p (m) = leafn_p (m) &
+ - m_leafn_to_fire_p (m) * deltim
+ frootn_p (m) = frootn_p (m) &
+ - m_frootn_to_fire_p (m) * deltim
+ livestemn_p (m) = livestemn_p (m) &
+ - m_livestemn_to_fire_p (m) * deltim
+ deadstemn_p (m) = deadstemn_p (m) &
+ - m_deadstemn_to_fire_p (m) * deltim
+ livecrootn_p (m) = livecrootn_p (m) &
+ - m_livecrootn_to_fire_p (m) * deltim
+ deadcrootn_p (m) = deadcrootn_p (m) &
+ - m_deadcrootn_to_fire_p (m) * deltim
+
+ leafn_p (m) = leafn_p (m) &
+ - m_leafn_to_litter_fire_p (m) * deltim
+ frootn_p (m) = frootn_p (m) &
+ - m_frootn_to_litter_fire_p (m) * deltim
+ livestemn_p (m) = livestemn_p (m) &
+ - m_livestemn_to_litter_fire_p (m) * deltim &
+ - m_livestemn_to_deadstemn_fire_p (m) * deltim
+ deadstemn_p (m) = deadstemn_p (m) &
+ - m_deadstemn_to_litter_fire_p (m) * deltim &
+ + m_livestemn_to_deadstemn_fire_p (m) * deltim
+ livecrootn_p (m) = livecrootn_p (m) &
+ - m_livecrootn_to_litter_fire_p (m) * deltim &
+ - m_livecrootn_to_deadcrootn_fire_p(m) * deltim
+ deadcrootn_p (m) = deadcrootn_p (m) &
+ - m_deadcrootn_to_litter_fire_p (m) * deltim &
+ + m_livecrootn_to_deadcrootn_fire_p(m) * deltim
+
+ ! storage pools
+ leafn_storage_p (m) = leafn_storage_p (m) &
+ - m_leafn_storage_to_fire_p (m) * deltim
+ frootn_storage_p (m) = frootn_storage_p (m) &
+ - m_frootn_storage_to_fire_p (m) * deltim
+ livestemn_storage_p (m) = livestemn_storage_p (m) &
+ - m_livestemn_storage_to_fire_p (m) * deltim
+ deadstemn_storage_p (m) = deadstemn_storage_p (m) &
+ - m_deadstemn_storage_to_fire_p (m) * deltim
+ livecrootn_storage_p(m) = livecrootn_storage_p(m) &
+ - m_livecrootn_storage_to_fire_p (m) * deltim
+ deadcrootn_storage_p(m) = deadcrootn_storage_p(m) &
+ - m_deadcrootn_storage_to_fire_p (m) * deltim
+
+ leafn_storage_p (m) = leafn_storage_p (m) &
+ - m_leafn_storage_to_litter_fire_p (m) * deltim
+ frootn_storage_p (m) = frootn_storage_p (m) &
+ - m_frootn_storage_to_litter_fire_p (m) * deltim
+ livestemn_storage_p (m) = livestemn_storage_p (m) &
+ - m_livestemn_storage_to_litter_fire_p (m) * deltim
+ deadstemn_storage_p (m) = deadstemn_storage_p (m) &
+ - m_deadstemn_storage_to_litter_fire_p (m) * deltim
+ livecrootn_storage_p(m) = livecrootn_storage_p(m) &
+ - m_livecrootn_storage_to_litter_fire_p(m) * deltim
+ deadcrootn_storage_p(m) = deadcrootn_storage_p(m) &
+ - m_deadcrootn_storage_to_litter_fire_p(m) * deltim
+
+
+ ! transfer pools
+ leafn_xfer_p (m) = leafn_xfer_p (m) &
+ - m_leafn_xfer_to_fire_p (m) * deltim
+ frootn_xfer_p (m) = frootn_xfer_p (m) &
+ - m_frootn_xfer_to_fire_p (m) * deltim
+ livestemn_xfer_p (m) = livestemn_xfer_p (m) &
+ - m_livestemn_xfer_to_fire_p (m) * deltim
+ deadstemn_xfer_p (m) = deadstemn_xfer_p (m) &
+ - m_deadstemn_xfer_to_fire_p (m) * deltim
+ livecrootn_xfer_p (m) = livecrootn_xfer_p (m) &
+ - m_livecrootn_xfer_to_fire_p (m) * deltim
+ deadcrootn_xfer_p (m) = deadcrootn_xfer_p (m) &
+ - m_deadcrootn_xfer_to_fire_p (m) * deltim
+
+ leafn_xfer_p (m) = leafn_xfer_p (m) &
+ - m_leafn_xfer_to_litter_fire_p (m) * deltim
+ frootn_xfer_p (m) = frootn_xfer_p (m) &
+ - m_frootn_xfer_to_litter_fire_p (m) * deltim
+ livestemn_xfer_p (m) = livestemn_xfer_p (m) &
+ - m_livestemn_xfer_to_litter_fire_p (m) * deltim
+ deadstemn_xfer_p (m) = deadstemn_xfer_p (m) &
+ - m_deadstemn_xfer_to_litter_fire_p (m) * deltim
+ livecrootn_xfer_p (m) = livecrootn_xfer_p (m) &
+ - m_livecrootn_xfer_to_litter_fire_p (m) * deltim
+ deadcrootn_xfer_p (m) = deadcrootn_xfer_p (m) &
+ - m_deadcrootn_xfer_to_litter_fire_p (m) * deltim
+
+ ! retranslocated N pool
+ retransn_p (m) = retransn_p (m) &
+ - m_retransn_to_fire_p (m) * deltim
+ retransn_p (m) = retransn_p (m) &
+ - m_retransn_to_litter_fire_p (m) * deltim
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE NStateUpdate3
+
+END MODULE MOD_BGC_CNNStateUpdate3
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNSASU.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNSASU.F90
new file mode 100644
index 0000000000..f4cd21b975
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNSASU.F90
@@ -0,0 +1,1074 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_CNSASU
+
+!----------------------------------------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This MODULE implements an semi-analytic accerlating spin-up method (SASU) in CoLM bgc MODULE. The SASU method analytically calculates
+! the steady state of each vegetation and soil C and N pool sizes, and replace current CN pool sizes with analytical steady state
+! solution. So, CN pool sizes in both vegetation and soil reach steady state much faster than conventional spin up method.
+!
+! !MODULE for CoLM-BGC matrices
+! The vegetation matrix equation
+! Xn+1 = Xn + I*dt + (Aph*Kph + Agm*Kgm + Afire*Kfire) * dt
+! The soil matrix equation
+! Xn+1 = Xn + I*dt + (A*K(ksi) + Kfire + tri/dz)*Xn*dt
+! The steady state solution for vegetation C is X = -I*B*(Aph*Kph + Agm*Kgm + Afire*Kfire)**(-1)
+! The steady state solution for soil C is X = -I *(A*K(ksi) + Kfire + tri/dz)**(-1)
+!
+! !ORIGINAL:
+! The Community Land Model version 5.1 (CLM5.1) unreleased version developed by Xingjie Lu
+!
+! !REFERENCES:
+! Lu, X., Du, Z., Huang, Y., Lawrence, D., Kluzek, E., Collier, N., Lombardozzi, D., Sobhani, N., Schuur, E.A. and Luo, Y., 2020.
+! Full implementation of matrix approach to biogeochemistry MODULE of CLM5. Journal of Advances in Modeling Earth Systems, 12(11), e2020MS002105.
+! Liao, C., Lu, X., Huang Y., Tao F., Lawrence, D., Koven C., Oleson, K., Wieder, W., Kluzek, E., Huang, X., Luo, Y. (in submission)
+! Matrix Approach to Accelerate Spin-Up of CLM5
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+! USE accumulated transfer fluxes to calculate the matrix.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ i_met_lit, i_cel_lit, i_lig_lit, i_cwd, i_soil1, i_soil2, i_soil3, floating_cn_ratio
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ decomp_cpools_vr , decomp_npools_vr , decomp0_cpools_vr , decomp0_npools_vr , &
+ decomp_cpools_vr_Cap , decomp_npools_vr_Cap , &
+ I_met_c_vr_acc , I_cel_c_vr_acc , I_lig_c_vr_acc , I_cwd_c_vr_acc , &
+ AKX_met_to_soil1_c_vr_acc , AKX_cel_to_soil1_c_vr_acc , AKX_lig_to_soil2_c_vr_acc , AKX_soil1_to_soil2_c_vr_acc, &
+ AKX_cwd_to_cel_c_vr_acc , AKX_cwd_to_lig_c_vr_acc , AKX_soil1_to_soil3_c_vr_acc, AKX_soil2_to_soil1_c_vr_acc, &
+ AKX_soil2_to_soil3_c_vr_acc, AKX_soil3_to_soil1_c_vr_acc, &
+ AKX_met_exit_c_vr_acc , AKX_cel_exit_c_vr_acc , AKX_lig_exit_c_vr_acc , AKX_cwd_exit_c_vr_acc , &
+ AKX_soil1_exit_c_vr_acc , AKX_soil2_exit_c_vr_acc , AKX_soil3_exit_c_vr_acc , &
+ diagVX_c_vr_acc , upperVX_c_vr_acc , lowerVX_c_vr_acc , &
+ I_met_n_vr_acc , I_cel_n_vr_acc , I_lig_n_vr_acc , I_cwd_n_vr_acc , &
+ AKX_met_to_soil1_n_vr_acc , AKX_cel_to_soil1_n_vr_acc , AKX_lig_to_soil2_n_vr_acc , AKX_soil1_to_soil2_n_vr_acc, &
+ AKX_cwd_to_cel_n_vr_acc , AKX_cwd_to_lig_n_vr_acc , AKX_soil1_to_soil3_n_vr_acc, AKX_soil2_to_soil1_n_vr_acc, &
+ AKX_soil2_to_soil3_n_vr_acc, AKX_soil3_to_soil1_n_vr_acc, &
+ AKX_met_exit_n_vr_acc , AKX_cel_exit_n_vr_acc , AKX_lig_exit_n_vr_acc , AKX_cwd_exit_n_vr_acc , &
+ AKX_soil1_exit_n_vr_acc , AKX_soil2_exit_n_vr_acc , AKX_soil3_exit_n_vr_acc , &
+ diagVX_n_vr_acc , upperVX_n_vr_acc , lowerVX_n_vr_acc , skip_balance_check , &
+ cn_decomp_pools
+
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ leafc_p , leafc_storage_p , leafc_xfer_p , leafc0_p , leafc0_storage_p , leafc0_xfer_p , &
+ frootc_p , frootc_storage_p , frootc_xfer_p , frootc0_p , frootc0_storage_p , frootc0_xfer_p , &
+ livestemc_p , livestemc_storage_p , livestemc_xfer_p , livestemc0_p , livestemc0_storage_p , livestemc0_xfer_p , &
+ deadstemc_p , deadstemc_storage_p , deadstemc_xfer_p , deadstemc0_p , deadstemc0_storage_p , deadstemc0_xfer_p , &
+ livecrootc_p , livecrootc_storage_p , livecrootc_xfer_p , livecrootc0_p , livecrootc0_storage_p, livecrootc0_xfer_p, &
+ deadcrootc_p , deadcrootc_storage_p , deadcrootc_xfer_p , deadcrootc0_p , deadcrootc0_storage_p, deadcrootc0_xfer_p, &
+ grainc_p , grainc_storage_p , grainc_xfer_p , grainc0_p , grainc0_storage_p , grainc0_xfer_p , &
+
+ leafcCap_p , leafc_storageCap_p , leafc_xferCap_p , &
+ frootcCap_p , frootc_storageCap_p , frootc_xferCap_p , &
+ livestemcCap_p , livestemc_storageCap_p , livestemc_xferCap_p , &
+ deadstemcCap_p , deadstemc_storageCap_p , deadstemc_xferCap_p , &
+ livecrootcCap_p , livecrootc_storageCap_p , livecrootc_xferCap_p , &
+ deadcrootcCap_p , deadcrootc_storageCap_p , deadcrootc_xferCap_p , &
+
+ leafnCap_p , leafn_storageCap_p , leafn_xferCap_p , &
+ frootnCap_p , frootn_storageCap_p , frootn_xferCap_p , &
+ livestemnCap_p , livestemn_storageCap_p , livestemn_xferCap_p , &
+ deadstemnCap_p , deadstemn_storageCap_p , deadstemn_xferCap_p , &
+ livecrootnCap_p , livecrootn_storageCap_p , livecrootn_xferCap_p , &
+ deadcrootnCap_p , deadcrootn_storageCap_p , deadcrootn_xferCap_p , &
+
+ leafn_p , leafn_storage_p , leafn_xfer_p , leafn0_p , leafn0_storage_p , leafn0_xfer_p , &
+ frootn_p , frootn_storage_p , frootn_xfer_p , frootn0_p , frootn0_storage_p , frootn0_xfer_p , &
+ livestemn_p , livestemn_storage_p , livestemn_xfer_p , livestemn0_p , livestemn0_storage_p , livestemn0_xfer_p , &
+ deadstemn_p , deadstemn_storage_p , deadstemn_xfer_p , deadstemn0_p , deadstemn0_storage_p , deadstemn0_xfer_p , &
+ livecrootn_p , livecrootn_storage_p , livecrootn_xfer_p , livecrootn0_p , livecrootn0_storage_p, livecrootn0_xfer_p, &
+ deadcrootn_p , deadcrootn_storage_p , deadcrootn_xfer_p , deadcrootn0_p , deadcrootn0_storage_p, deadcrootn0_xfer_p, &
+ grainn_p , grainn_storage_p , grainn_xfer_p , grainn0_p , grainn0_storage_p , grainn0_xfer_p , &
+ retransn_p , retransn0_p , &
+
+ I_leafc_p_acc , I_leafc_st_p_acc , I_frootc_p_acc , I_frootc_st_p_acc , &
+ I_livestemc_p_acc , I_livestemc_st_p_acc , I_deadstemc_p_acc , I_deadstemc_st_p_acc , &
+ I_livecrootc_p_acc, I_livecrootc_st_p_acc, I_deadcrootc_p_acc, I_deadcrootc_st_p_acc, &
+ I_grainc_p_acc , I_grainc_st_p_acc , &
+
+ I_leafn_p_acc , I_leafn_st_p_acc , I_frootn_p_acc , I_frootn_st_p_acc , &
+ I_livestemn_p_acc , I_livestemn_st_p_acc , I_deadstemn_p_acc , I_deadstemn_st_p_acc , &
+ I_livecrootn_p_acc, I_livecrootn_st_p_acc, I_deadcrootn_p_acc, I_deadcrootn_st_p_acc, &
+ I_grainn_p_acc , I_grainn_st_p_acc , &
+
+ AKX_leafc_xf_to_leafc_p_acc , AKX_frootc_xf_to_frootc_p_acc , AKX_livestemc_xf_to_livestemc_p_acc , &
+ AKX_deadstemc_xf_to_deadstemc_p_acc , AKX_livecrootc_xf_to_livecrootc_p_acc , AKX_deadcrootc_xf_to_deadcrootc_p_acc , &
+ AKX_grainc_xf_to_grainc_p_acc , AKX_livestemc_to_deadstemc_p_acc , AKX_livecrootc_to_deadcrootc_p_acc , &
+
+ AKX_leafc_st_to_leafc_xf_p_acc , AKX_frootc_st_to_frootc_xf_p_acc , AKX_livestemc_st_to_livestemc_xf_p_acc , &
+ AKX_deadstemc_st_to_deadstemc_xf_p_acc, AKX_livecrootc_st_to_livecrootc_xf_p_acc, AKX_deadcrootc_st_to_deadcrootc_xf_p_acc, &
+ AKX_grainc_st_to_grainc_xf_p_acc , &
+
+ AKX_leafc_exit_p_acc , AKX_frootc_exit_p_acc , AKX_livestemc_exit_p_acc , &
+ AKX_deadstemc_exit_p_acc , AKX_livecrootc_exit_p_acc , AKX_deadcrootc_exit_p_acc , &
+ AKX_grainc_exit_p_acc , &
+
+ AKX_leafc_st_exit_p_acc , AKX_frootc_st_exit_p_acc , AKX_livestemc_st_exit_p_acc , &
+ AKX_deadstemc_st_exit_p_acc , AKX_livecrootc_st_exit_p_acc , AKX_deadcrootc_st_exit_p_acc , &
+ AKX_grainc_st_exit_p_acc , &
+
+ AKX_leafc_xf_exit_p_acc , AKX_frootc_xf_exit_p_acc , AKX_livestemc_xf_exit_p_acc , &
+ AKX_deadstemc_xf_exit_p_acc , AKX_livecrootc_xf_exit_p_acc , AKX_deadcrootc_xf_exit_p_acc , &
+ AKX_grainc_xf_exit_p_acc , &
+
+ AKX_leafn_xf_to_leafn_p_acc , AKX_frootn_xf_to_frootn_p_acc , AKX_livestemn_xf_to_livestemn_p_acc , &
+ AKX_deadstemn_xf_to_deadstemn_p_acc , AKX_livecrootn_xf_to_livecrootn_p_acc , AKX_deadcrootn_xf_to_deadcrootn_p_acc , &
+ AKX_grainn_xf_to_grainn_p_acc , AKX_livestemn_to_deadstemn_p_acc , AKX_livecrootn_to_deadcrootn_p_acc , &
+
+ AKX_leafn_st_to_leafn_xf_p_acc , AKX_frootn_st_to_frootn_xf_p_acc , AKX_livestemn_st_to_livestemn_xf_p_acc , &
+ AKX_deadstemn_st_to_deadstemn_xf_p_acc, AKX_livecrootn_st_to_livecrootn_xf_p_acc, AKX_deadcrootn_st_to_deadcrootn_xf_p_acc, &
+ AKX_grainn_st_to_grainn_xf_p_acc , &
+
+ AKX_leafn_to_retransn_p_acc , AKX_frootn_to_retransn_p_acc , AKX_livestemn_to_retransn_p_acc , &
+ AKX_livecrootn_to_retransn_p_acc , &
+
+ AKX_retransn_to_leafn_p_acc , AKX_retransn_to_frootn_p_acc , AKX_retransn_to_livestemn_p_acc , &
+ AKX_retransn_to_deadstemn_p_acc , AKX_retransn_to_livecrootn_p_acc , AKX_retransn_to_deadcrootn_p_acc , &
+ AKX_retransn_to_grainn_p_acc , &
+
+ AKX_retransn_to_leafn_st_p_acc , AKX_retransn_to_frootn_st_p_acc , AKX_retransn_to_livestemn_st_p_acc , &
+ AKX_retransn_to_deadstemn_st_p_acc , AKX_retransn_to_livecrootn_st_p_acc , AKX_retransn_to_deadcrootn_st_p_acc , &
+ AKX_retransn_to_grainn_st_p_acc , &
+
+ AKX_leafn_exit_p_acc , AKX_frootn_exit_p_acc , AKX_livestemn_exit_p_acc , &
+ AKX_deadstemn_exit_p_acc , AKX_livecrootn_exit_p_acc , AKX_deadcrootn_exit_p_acc , &
+ AKX_grainn_exit_p_acc , AKX_retransn_exit_p_acc , &
+
+ AKX_leafn_st_exit_p_acc , AKX_frootn_st_exit_p_acc , AKX_livestemn_st_exit_p_acc , &
+ AKX_deadstemn_st_exit_p_acc , AKX_livecrootn_st_exit_p_acc , AKX_deadcrootn_st_exit_p_acc , &
+ AKX_grainn_st_exit_p_acc , &
+
+ AKX_leafn_xf_exit_p_acc , AKX_frootn_xf_exit_p_acc , AKX_livestemn_xf_exit_p_acc , &
+ AKX_deadstemn_xf_exit_p_acc , AKX_livecrootn_xf_exit_p_acc , AKX_deadcrootn_xf_exit_p_acc , &
+ AKX_grainn_xf_exit_p_acc
+!
+ IMPLICIT NONE
+
+ PUBLIC :: CNSASU
+ PUBLIC :: inverse
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE CNSASU(i,ps,pe,deltim,idate,nl_soil,ndecomp_transitions, ndecomp_pools, ndecomp_pools_vr)
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: idate(3) ! current date (year, days of the year, seconds of the day)
+ integer, intent(in) :: nl_soil ! number of total soil number
+ integer, intent(in) :: ndecomp_transitions ! number of total litter & soil pools
+ integer, intent(in) :: ndecomp_pools ! number of total transfers between all litter & soil pools in the decomposition.
+ integer, intent(in) :: ndecomp_pools_vr ! number of total litter & soil pools times numer of soil layers (eg. 7 * 10)
+
+ !-----------------------------------------------------------------------
+
+ integer :: k, m, j
+ ! set index of vegetation CN pools
+ real(r8),parameter :: epsi = 1.e-8_r8
+ integer ,parameter :: nvegc = 21
+ integer ,parameter :: nvegn = 22
+ integer ,parameter :: ileaf = 1
+ integer ,parameter :: ileaf_st = 2
+ integer ,parameter :: ileaf_xf = 3
+ integer ,parameter :: ifroot = 4
+ integer ,parameter :: ifroot_st = 5
+ integer ,parameter :: ifroot_xf = 6
+ integer ,parameter :: ilivestem = 7
+ integer ,parameter :: ilivestem_st = 8
+ integer ,parameter :: ilivestem_xf = 9
+ integer ,parameter :: ideadstem = 10
+ integer ,parameter :: ideadstem_st = 11
+ integer ,parameter :: ideadstem_xf = 12
+ integer ,parameter :: ilivecroot = 13
+ integer ,parameter :: ilivecroot_st = 14
+ integer ,parameter :: ilivecroot_xf = 15
+ integer ,parameter :: ideadcroot = 16
+ integer ,parameter :: ideadcroot_st = 17
+ integer ,parameter :: ideadcroot_xf = 18
+ integer ,parameter :: igrain = 19
+ integer ,parameter :: igrain_st = 20
+ integer ,parameter :: igrain_xf = 21
+ integer ,parameter :: iretrans = 22
+
+
+ real(r8),dimension(1:nvegc,1:nvegc) :: AK_veg_acc
+ real(r8),dimension(1:nvegn,1:nvegn) :: AK_veg_nacc
+ real(r8),dimension(1:nvegc) :: I_veg_acc
+ real(r8),dimension(1:nvegn) :: I_veg_nacc
+ real(r8),dimension(1:ndecomp_pools_vr,1:ndecomp_pools_vr) :: AK_soil_acc
+ real(r8),dimension(1:ndecomp_pools_vr,1:ndecomp_pools_vr) :: AK_soil_nacc
+ real(r8),dimension(1:ndecomp_pools_vr) :: I_soil_acc
+ real(r8),dimension(1:ndecomp_pools_vr) :: I_soil_nacc
+ real(r8),dimension(1:nvegc,1:nvegc) :: AKinv_veg
+ real(r8),dimension(1:nvegn,1:nvegn) :: AKinvn_veg
+ real(r8),dimension(1:ndecomp_pools_vr,1:ndecomp_pools_vr) :: AKinv_soil
+ real(r8),dimension(1:ndecomp_pools_vr,1:ndecomp_pools_vr) :: AKinvn_soil
+ real(r8),dimension(1:nvegc,1) :: vegmatrixc_cap
+ real(r8),dimension(1:nvegn,1) :: vegmatrixn_cap
+ real(r8),dimension(1:ndecomp_pools_vr,1) :: soilmatrixc_cap
+ real(r8),dimension(1:ndecomp_pools_vr,1) :: soilmatrixn_cap
+
+ ! Save the C and N pool size at begin of each year, which are used to calculate C and N capacity at end of each year.
+ IF (idate(2) .eq. 1 .and. idate(3) .eq. deltim)THEN
+ DO m = ps, pe
+ leafc0_p (m) = max(leafc_p (m),epsi)
+ leafc0_storage_p (m) = max(leafc_storage_p (m),epsi)
+ leafc0_xfer_p (m) = max(leafc_xfer_p (m),epsi)
+ frootc0_p (m) = max(frootc_p (m),epsi)
+ frootc0_storage_p (m) = max(frootc_storage_p (m),epsi)
+ frootc0_xfer_p (m) = max(frootc_xfer_p (m),epsi)
+ livestemc0_p (m) = max(livestemc_p (m),epsi)
+ livestemc0_storage_p (m) = max(livestemc_storage_p (m),epsi)
+ livestemc0_xfer_p (m) = max(livestemc_xfer_p (m),epsi)
+ deadstemc0_p (m) = max(deadstemc_p (m),epsi)
+ deadstemc0_storage_p (m) = max(deadstemc_storage_p (m),epsi)
+ deadstemc0_xfer_p (m) = max(deadstemc_xfer_p (m),epsi)
+ livecrootc0_p (m) = max(livecrootc_p (m),epsi)
+ livecrootc0_storage_p(m) = max(livecrootc_storage_p(m),epsi)
+ livecrootc0_xfer_p (m) = max(livecrootc_xfer_p (m),epsi)
+ deadcrootc0_p (m) = max(deadcrootc_p (m),epsi)
+ deadcrootc0_storage_p(m) = max(deadcrootc_storage_p(m),epsi)
+ deadcrootc0_xfer_p (m) = max(deadcrootc_xfer_p (m),epsi)
+ grainc0_p (m) = max(grainc_p (m),epsi)
+ grainc0_storage_p (m) = max(grainc_storage_p (m),epsi)
+ grainc0_xfer_p (m) = max(grainc_xfer_p (m),epsi)
+ leafn0_p (m) = max(leafn_p (m),epsi)
+ leafn0_storage_p (m) = max(leafn_storage_p (m),epsi)
+ leafn0_xfer_p (m) = max(leafn_xfer_p (m),epsi)
+ frootn0_p (m) = max(frootn_p (m),epsi)
+ frootn0_storage_p (m) = max(frootn_storage_p (m),epsi)
+ frootn0_xfer_p (m) = max(frootn_xfer_p (m),epsi)
+ livestemn0_p (m) = max(livestemn_p (m),epsi)
+ livestemn0_storage_p (m) = max(livestemn_storage_p (m),epsi)
+ livestemn0_xfer_p (m) = max(livestemn_xfer_p (m),epsi)
+ deadstemn0_p (m) = max(deadstemn_p (m),epsi)
+ deadstemn0_storage_p (m) = max(deadstemn_storage_p (m),epsi)
+ deadstemn0_xfer_p (m) = max(deadstemn_xfer_p (m),epsi)
+ livecrootn0_p (m) = max(livecrootn_p (m),epsi)
+ livecrootn0_storage_p(m) = max(livecrootn_storage_p(m),epsi)
+ livecrootn0_xfer_p (m) = max(livecrootn_xfer_p (m),epsi)
+ deadcrootn0_p (m) = max(deadcrootn_p (m),epsi)
+ deadcrootn0_storage_p(m) = max(deadcrootn_storage_p(m),epsi)
+ deadcrootn0_xfer_p (m) = max(deadcrootn_xfer_p (m),epsi)
+ grainn0_p (m) = max(grainn_p (m),epsi)
+ grainn0_storage_p (m) = max(grainn_storage_p (m),epsi)
+ grainn0_xfer_p (m) = max(grainn_xfer_p (m),epsi)
+ retransn0_p (m) = max(retransn_p (m),epsi)
+ ENDDO
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp0_cpools_vr(j,k,i)=max(decomp_cpools_vr(j,k,i),epsi)
+ decomp0_npools_vr(j,k,i)=max(decomp_npools_vr(j,k,i),epsi)
+ ENDDO
+ ENDDO
+ ENDIF
+
+ IF(idate(2) .eq. 365 .and. idate(3) .eq. 86400 - deltim)THEN
+ ! Copy C transfers from sparse matrix to 2D temporary variables tran_acc and tran_nacc
+ ! Calculate the C and N transfer rate by dividing CN transfer by base value saved at begin of each year.
+
+ DO m = ps, pe
+ AK_veg_acc (1:nvegc,1:nvegc) = 0._r8
+ AK_veg_nacc (1:nvegn,1:nvegn) = 0._r8
+ I_veg_acc (1:nvegc) = 0._r8
+ I_veg_nacc (1:nvegn) = 0._r8
+
+ AK_veg_acc ( ileaf, ileaf_xf) = AKX_leafc_xf_to_leafc_p_acc (m) / leafc0_xfer_p (m)
+ AK_veg_acc ( ifroot, ifroot_xf) = AKX_frootc_xf_to_frootc_p_acc (m) / frootc0_xfer_p (m)
+ AK_veg_acc ( ilivestem, ilivestem_xf) = AKX_livestemc_xf_to_livestemc_p_acc (m) / livestemc0_xfer_p (m)
+ AK_veg_acc ( ideadstem, ideadstem_xf) = AKX_deadstemc_xf_to_deadstemc_p_acc (m) / deadstemc0_xfer_p (m)
+ AK_veg_acc ( ilivecroot,ilivecroot_xf) = AKX_livecrootc_xf_to_livecrootc_p_acc (m) / livecrootc0_xfer_p (m)
+ AK_veg_acc ( ideadcroot,ideadcroot_xf) = AKX_deadcrootc_xf_to_deadcrootc_p_acc (m) / deadcrootc0_xfer_p (m)
+ AK_veg_acc ( igrain, igrain_xf) = AKX_grainc_xf_to_grainc_p_acc (m) / grainc0_xfer_p (m)
+ AK_veg_acc ( ideadstem, ilivestem) = AKX_livestemc_to_deadstemc_p_acc (m) / livestemc0_p (m)
+ AK_veg_acc ( ideadcroot, ilivecroot) = AKX_livecrootc_to_deadcrootc_p_acc (m) / livecrootc0_p (m)
+
+ AK_veg_acc ( ileaf_xf, ileaf_st) = AKX_leafc_st_to_leafc_xf_p_acc (m) / leafc0_storage_p (m)
+ AK_veg_acc ( ifroot_xf, ifroot_st) = AKX_frootc_st_to_frootc_xf_p_acc (m) / frootc0_storage_p (m)
+ AK_veg_acc ( ilivestem_xf, ilivestem_st) = AKX_livestemc_st_to_livestemc_xf_p_acc (m) / livestemc0_storage_p (m)
+ AK_veg_acc ( ideadstem_xf, ideadstem_st) = AKX_deadstemc_st_to_deadstemc_xf_p_acc (m) / deadstemc0_storage_p (m)
+ AK_veg_acc (ilivecroot_xf,ilivecroot_st) = AKX_livecrootc_st_to_livecrootc_xf_p_acc(m) / livecrootc0_storage_p(m)
+ AK_veg_acc (ideadcroot_xf,ideadcroot_st) = AKX_deadcrootc_st_to_deadcrootc_xf_p_acc(m) / deadcrootc0_storage_p(m)
+ AK_veg_acc ( igrain_xf, igrain_st) = AKX_grainc_st_to_grainc_xf_p_acc (m) / grainc0_storage_p (m)
+
+ AK_veg_acc ( ileaf, ileaf) = - AKX_leafc_exit_p_acc (m) / leafc0_p (m)
+ AK_veg_acc ( ileaf_st, ileaf_st) = - AKX_leafc_st_exit_p_acc (m) / leafc0_storage_p (m)
+ AK_veg_acc ( ileaf_xf, ileaf_xf) = - AKX_leafc_xf_exit_p_acc (m) / leafc0_xfer_p (m)
+ AK_veg_acc ( ifroot, ifroot) = - AKX_frootc_exit_p_acc (m) / frootc0_p (m)
+ AK_veg_acc ( ifroot_st, ifroot_st) = - AKX_frootc_st_exit_p_acc (m) / frootc0_storage_p (m)
+ AK_veg_acc ( ifroot_xf, ifroot_xf) = - AKX_frootc_xf_exit_p_acc (m) / frootc0_xfer_p (m)
+ AK_veg_acc ( ilivestem, ilivestem) = - AKX_livestemc_exit_p_acc (m) / livestemc0_p (m)
+ AK_veg_acc ( ilivestem_st, ilivestem_st) = - AKX_livestemc_st_exit_p_acc (m) / livestemc0_storage_p (m)
+ AK_veg_acc ( ilivestem_xf, ilivestem_xf) = - AKX_livestemc_xf_exit_p_acc (m) / livestemc0_xfer_p (m)
+ AK_veg_acc ( ideadstem, ideadstem) = - AKX_deadstemc_exit_p_acc (m) / deadstemc0_p (m)
+ AK_veg_acc ( ideadstem_st, ideadstem_st) = - AKX_deadstemc_st_exit_p_acc (m) / deadstemc0_storage_p (m)
+ AK_veg_acc ( ideadstem_xf, ideadstem_xf) = - AKX_deadstemc_xf_exit_p_acc (m) / deadstemc0_xfer_p (m)
+ AK_veg_acc ( ilivecroot, ilivecroot) = - AKX_livecrootc_exit_p_acc (m) / livecrootc0_p (m)
+ AK_veg_acc (ilivecroot_st,ilivecroot_st) = - AKX_livecrootc_st_exit_p_acc (m) / livecrootc0_storage_p(m)
+ AK_veg_acc (ilivecroot_xf,ilivecroot_xf) = - AKX_livecrootc_xf_exit_p_acc (m) / livecrootc0_xfer_p (m)
+ AK_veg_acc ( ideadcroot, ideadcroot) = - AKX_deadcrootc_exit_p_acc (m) / deadcrootc0_p (m)
+ AK_veg_acc (ideadcroot_st,ideadcroot_st) = - AKX_deadcrootc_st_exit_p_acc (m) / deadcrootc0_storage_p(m)
+ AK_veg_acc (ideadcroot_xf,ideadcroot_xf) = - AKX_deadcrootc_xf_exit_p_acc (m) / deadcrootc0_xfer_p (m)
+ AK_veg_acc ( igrain, igrain) = - AKX_grainc_exit_p_acc (m) / grainc0_p (m)
+ AK_veg_acc ( igrain_st, igrain_st) = - AKX_grainc_st_exit_p_acc (m) / grainc0_storage_p (m)
+ AK_veg_acc ( igrain_xf, igrain_xf) = - AKX_grainc_xf_exit_p_acc (m) / grainc0_xfer_p (m)
+
+ I_veg_acc ( ileaf) = I_leafc_p_acc (m)
+ I_veg_acc ( ileaf_st) = I_leafc_st_p_acc (m)
+ I_veg_acc ( ifroot) = I_frootc_p_acc (m)
+ I_veg_acc ( ifroot_st) = I_frootc_st_p_acc (m)
+ I_veg_acc ( ilivestem) = I_livestemc_p_acc (m)
+ I_veg_acc ( ilivestem_st) = I_livestemc_st_p_acc (m)
+ I_veg_acc ( ideadstem) = I_deadstemc_p_acc (m)
+ I_veg_acc ( ideadstem_st) = I_deadstemc_st_p_acc (m)
+ I_veg_acc ( ilivecroot) = I_livecrootc_p_acc (m)
+ I_veg_acc (ilivecroot_st) = I_livecrootc_st_p_acc (m)
+ I_veg_acc ( ideadcroot) = I_deadcrootc_p_acc (m)
+ I_veg_acc (ideadcroot_st) = I_deadcrootc_st_p_acc (m)
+ I_veg_acc ( igrain) = I_grainc_p_acc (m)
+ I_veg_acc ( igrain_st) = I_grainc_st_p_acc (m)
+
+ AK_veg_nacc ( ileaf, ileaf_xf) = AKX_leafn_xf_to_leafn_p_acc (m) / leafn0_xfer_p (m)
+ AK_veg_nacc ( ifroot, ifroot_xf) = AKX_frootn_xf_to_frootn_p_acc (m) / frootn0_xfer_p (m)
+ AK_veg_nacc ( ilivestem, ilivestem_xf) = AKX_livestemn_xf_to_livestemn_p_acc (m) / livestemn0_xfer_p (m)
+ AK_veg_nacc ( ideadstem, ideadstem_xf) = AKX_deadstemn_xf_to_deadstemn_p_acc (m) / deadstemn0_xfer_p (m)
+ AK_veg_nacc ( ilivecroot,ilivecroot_xf) = AKX_livecrootn_xf_to_livecrootn_p_acc (m) / livecrootn0_xfer_p (m)
+ AK_veg_nacc ( ideadcroot,ideadcroot_xf) = AKX_deadcrootn_xf_to_deadcrootn_p_acc (m) / deadcrootn0_xfer_p (m)
+ AK_veg_nacc ( igrain, igrain_xf) = AKX_grainn_xf_to_grainn_p_acc (m) / grainn0_xfer_p (m)
+ AK_veg_nacc ( ideadstem, ilivestem) = AKX_livestemn_to_deadstemn_p_acc (m) / livestemn0_p (m)
+ AK_veg_nacc ( ideadcroot, ilivecroot) = AKX_livecrootn_to_deadcrootn_p_acc (m) / livecrootn0_p (m)
+
+ AK_veg_nacc ( ileaf_xf, ileaf_st) = AKX_leafn_st_to_leafn_xf_p_acc (m) / leafn0_storage_p (m)
+ AK_veg_nacc ( ifroot_xf, ifroot_st) = AKX_frootn_st_to_frootn_xf_p_acc (m) / frootn0_storage_p (m)
+ AK_veg_nacc ( ilivestem_xf, ilivestem_st) = AKX_livestemn_st_to_livestemn_xf_p_acc (m) / livestemn0_storage_p (m)
+ AK_veg_nacc ( ideadstem_xf, ideadstem_st) = AKX_deadstemn_st_to_deadstemn_xf_p_acc (m) / deadstemn0_storage_p (m)
+ AK_veg_nacc (ilivecroot_xf,ilivecroot_st) = AKX_livecrootn_st_to_livecrootn_xf_p_acc(m) / livecrootn0_storage_p(m)
+ AK_veg_nacc (ideadcroot_xf,ideadcroot_st) = AKX_deadcrootn_st_to_deadcrootn_xf_p_acc(m) / deadcrootn0_storage_p(m)
+ AK_veg_nacc ( igrain_xf, igrain_st) = AKX_grainn_st_to_grainn_xf_p_acc (m) / grainn0_storage_p (m)
+
+ AK_veg_nacc ( iretrans, ileaf) = AKX_leafn_to_retransn_p_acc (m) / leafn0_p (m)
+ AK_veg_nacc ( iretrans, ifroot) = AKX_frootn_to_retransn_p_acc (m) / frootn0_p (m)
+ AK_veg_nacc ( iretrans, ilivestem) = AKX_livestemn_to_retransn_p_acc (m) / livestemn0_p (m)
+ AK_veg_nacc ( iretrans, ilivecroot) = AKX_livecrootn_to_retransn_p_acc (m) / livecrootn0_p (m)
+
+ AK_veg_nacc ( ileaf, iretrans) = AKX_retransn_to_leafn_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ifroot, iretrans) = AKX_retransn_to_frootn_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ilivestem, iretrans) = AKX_retransn_to_livestemn_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ideadstem, iretrans) = AKX_retransn_to_deadstemn_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ilivecroot, iretrans) = AKX_retransn_to_livecrootn_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ideadcroot, iretrans) = AKX_retransn_to_deadcrootn_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( igrain, iretrans) = AKX_retransn_to_grainn_p_acc (m) / retransn0_p (m)
+
+ AK_veg_nacc ( ileaf_st, iretrans) = AKX_retransn_to_leafn_st_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ifroot_st, iretrans) = AKX_retransn_to_frootn_st_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ilivestem_st, iretrans) = AKX_retransn_to_livestemn_st_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( ideadstem_st, iretrans) = AKX_retransn_to_deadstemn_st_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc (ilivecroot_st, iretrans) = AKX_retransn_to_livecrootn_st_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc (ideadcroot_st, iretrans) = AKX_retransn_to_deadcrootn_st_p_acc (m) / retransn0_p (m)
+ AK_veg_nacc ( igrain_st, iretrans) = AKX_retransn_to_grainn_st_p_acc (m) / retransn0_p (m)
+
+ AK_veg_nacc ( ileaf, ileaf) = - AKX_leafn_exit_p_acc (m) / leafn0_p (m)
+ AK_veg_nacc ( ileaf_st, ileaf_st) = - AKX_leafn_st_exit_p_acc (m) / leafn0_storage_p (m)
+ AK_veg_nacc ( ileaf_xf, ileaf_xf) = - AKX_leafn_xf_exit_p_acc (m) / leafn0_xfer_p (m)
+ AK_veg_nacc ( ifroot, ifroot) = - AKX_frootn_exit_p_acc (m) / frootn0_p (m)
+ AK_veg_nacc ( ifroot_st, ifroot_st) = - AKX_frootn_st_exit_p_acc (m) / frootn0_storage_p (m)
+ AK_veg_nacc ( ifroot_xf, ifroot_xf) = - AKX_frootn_xf_exit_p_acc (m) / frootn0_xfer_p (m)
+ AK_veg_nacc ( ilivestem, ilivestem) = - AKX_livestemn_exit_p_acc (m) / livestemn0_p (m)
+ AK_veg_nacc ( ilivestem_st, ilivestem_st) = - AKX_livestemn_st_exit_p_acc (m) / livestemn0_storage_p (m)
+ AK_veg_nacc ( ilivestem_xf, ilivestem_xf) = - AKX_livestemn_xf_exit_p_acc (m) / livestemn0_xfer_p (m)
+ AK_veg_nacc ( ideadstem, ideadstem) = - AKX_deadstemn_exit_p_acc (m) / deadstemn0_p (m)
+ AK_veg_nacc ( ideadstem_st, ideadstem_st) = - AKX_deadstemn_st_exit_p_acc (m) / deadstemn0_storage_p (m)
+ AK_veg_nacc ( ideadstem_xf, ideadstem_xf) = - AKX_deadstemn_xf_exit_p_acc (m) / deadstemn0_xfer_p (m)
+ AK_veg_nacc ( ilivecroot, ilivecroot) = - AKX_livecrootn_exit_p_acc (m) / livecrootn0_p (m)
+ AK_veg_nacc (ilivecroot_st,ilivecroot_st) = - AKX_livecrootn_st_exit_p_acc (m) / livecrootn0_storage_p(m)
+ AK_veg_nacc (ilivecroot_xf,ilivecroot_xf) = - AKX_livecrootn_xf_exit_p_acc (m) / livecrootn0_xfer_p (m)
+ AK_veg_nacc ( ideadcroot, ideadcroot) = - AKX_deadcrootn_exit_p_acc (m) / deadcrootn0_p (m)
+ AK_veg_nacc (ideadcroot_st,ideadcroot_st) = - AKX_deadcrootn_st_exit_p_acc (m) / deadcrootn0_storage_p(m)
+ AK_veg_nacc (ideadcroot_xf,ideadcroot_xf) = - AKX_deadcrootn_xf_exit_p_acc (m) / deadcrootn0_xfer_p (m)
+ AK_veg_nacc ( igrain, igrain) = - AKX_grainn_exit_p_acc (m) / grainn0_p (m)
+ AK_veg_nacc ( igrain_st, igrain_st) = - AKX_grainn_st_exit_p_acc (m) / grainn0_storage_p (m)
+ AK_veg_nacc ( igrain_xf, igrain_xf) = - AKX_grainn_xf_exit_p_acc (m) / grainn0_xfer_p (m)
+ AK_veg_nacc ( iretrans, iretrans) = - AKX_retransn_exit_p_acc (m) / retransn0_p (m)
+
+ I_veg_nacc ( ileaf) = I_leafn_p_acc (m)
+ I_veg_nacc ( ileaf_st) = I_leafn_st_p_acc (m)
+ I_veg_nacc ( ifroot) = I_frootn_p_acc (m)
+ I_veg_nacc ( ifroot_st) = I_frootn_st_p_acc (m)
+ I_veg_nacc ( ilivestem) = I_livestemn_p_acc (m)
+ I_veg_nacc ( ilivestem_st) = I_livestemn_st_p_acc (m)
+ I_veg_nacc ( ideadstem) = I_deadstemn_p_acc (m)
+ I_veg_nacc ( ideadstem_st) = I_deadstemn_st_p_acc (m)
+ I_veg_nacc ( ilivecroot) = I_livecrootn_p_acc (m)
+ I_veg_nacc (ilivecroot_st) = I_livecrootn_st_p_acc (m)
+ I_veg_nacc ( ideadcroot) = I_deadcrootn_p_acc (m)
+ I_veg_nacc (ideadcroot_st) = I_deadcrootn_st_p_acc (m)
+ I_veg_nacc ( igrain) = I_grainn_p_acc (m)
+ I_veg_nacc ( igrain_st) = I_grainn_st_p_acc (m)
+
+ DO j = 1, nvegc
+ IF(AK_veg_acc(j,j) .eq. 0)THEN
+ AK_veg_acc(j,j) = - 1.e+36
+ ENDIF
+ ENDDO
+ DO j = 1, nvegn
+ IF(AK_veg_nacc(j,j) .eq. 0)THEN
+ AK_veg_nacc(j,j) = - 1.e+36
+ ENDIF
+ ENDDO
+
+ ! Calculate capacity
+ CALL inverse(AK_veg_acc (1:nvegc,1:nvegc),AKinv_veg (1:nvegc,1:nvegc),nvegc)
+ CALL inverse(AK_veg_nacc(1:nvegn,1:nvegn),AKinvn_veg(1:nvegn,1:nvegn),nvegn)
+ vegmatrixc_cap(:,1) = -matmul(AKinv_veg (1:nvegc,1:nvegc),I_veg_acc (1:nvegc))
+ vegmatrixn_cap(:,1) = -matmul(AKinvn_veg(1:nvegn,1:nvegn),I_veg_nacc(1:nvegn))
+
+ DO k = 1, nvegc
+ IF(vegmatrixc_cap(k,1) .lt. 0)THEN
+ vegmatrixc_cap(k,1) = epsi
+ ENDIF
+ ENDDO
+ DO k = 1, nvegn
+ IF(vegmatrixn_cap(k,1) .lt. 0)THEN
+ vegmatrixn_cap(k,1) = epsi
+ ENDIF
+ ENDDO
+ IF(DEF_USE_DiagMatrix)THEN
+ leafcCap_p (m) = vegmatrixc_cap(ileaf ,1)
+ leafc_storageCap_p (m) = vegmatrixc_cap(ileaf_st ,1)
+ leafc_xferCap_p (m) = vegmatrixc_cap(ileaf_xf ,1)
+ frootcCap_p (m) = vegmatrixc_cap(ifroot ,1)
+ frootc_storageCap_p (m) = vegmatrixc_cap(ifroot_st ,1)
+ frootc_xferCap_p (m) = vegmatrixc_cap(ifroot_xf ,1)
+ livestemcCap_p (m) = vegmatrixc_cap(ilivestem ,1)
+ livestemc_storageCap_p (m) = vegmatrixc_cap(ilivestem_st ,1)
+ livestemc_xferCap_p (m) = vegmatrixc_cap(ilivestem_xf ,1)
+ deadstemcCap_p (m) = vegmatrixc_cap(ideadstem ,1)
+ deadstemc_storageCap_p (m) = vegmatrixc_cap(ideadstem_st ,1)
+ deadstemc_xferCap_p (m) = vegmatrixc_cap(ideadstem_xf ,1)
+ livecrootcCap_p (m) = vegmatrixc_cap(ilivecroot ,1)
+ livecrootc_storageCap_p (m) = vegmatrixc_cap(ilivecroot_st ,1)
+ livecrootc_xferCap_p (m) = vegmatrixc_cap(ilivecroot_xf ,1)
+ deadcrootcCap_p (m) = vegmatrixc_cap(ideadcroot ,1)
+ deadcrootc_storageCap_p (m) = vegmatrixc_cap(ideadcroot_st ,1)
+ deadcrootc_xferCap_p (m) = vegmatrixc_cap(ideadcroot_xf ,1)
+ leafnCap_p (m) = vegmatrixn_cap(ileaf ,1)
+ leafn_storageCap_p (m) = vegmatrixn_cap(ileaf_st ,1)
+ leafn_xferCap_p (m) = vegmatrixn_cap(ileaf_xf ,1)
+ frootnCap_p (m) = vegmatrixn_cap(ifroot ,1)
+ frootn_storageCap_p (m) = vegmatrixn_cap(ifroot_st ,1)
+ frootn_xferCap_p (m) = vegmatrixn_cap(ifroot_xf ,1)
+ livestemnCap_p (m) = vegmatrixn_cap(ilivestem ,1)
+ livestemn_storageCap_p (m) = vegmatrixn_cap(ilivestem_st ,1)
+ livestemn_xferCap_p (m) = vegmatrixn_cap(ilivestem_xf ,1)
+ deadstemnCap_p (m) = vegmatrixn_cap(ideadstem ,1)
+ deadstemn_storageCap_p (m) = vegmatrixn_cap(ideadstem_st ,1)
+ deadstemn_xferCap_p (m) = vegmatrixn_cap(ideadstem_xf ,1)
+ livecrootnCap_p (m) = vegmatrixn_cap(ilivecroot ,1)
+ livecrootn_storageCap_p (m) = vegmatrixn_cap(ilivecroot_st ,1)
+ livecrootn_xferCap_p (m) = vegmatrixn_cap(ilivecroot_xf ,1)
+ deadcrootnCap_p (m) = vegmatrixn_cap(ideadcroot ,1)
+ deadcrootn_storageCap_p (m) = vegmatrixn_cap(ideadcroot_st ,1)
+ deadcrootn_xferCap_p (m) = vegmatrixn_cap(ideadcroot_xf ,1)
+ ENDIF
+ IF(DEF_USE_SASU)then
+ deadstemc_p (m) = vegmatrixc_cap(ideadstem,1)
+ deadstemc_storage_p (m) = vegmatrixc_cap(ideadstem_st,1)
+ deadcrootc_p (m) = vegmatrixc_cap(ideadcroot,1)
+ deadcrootc_storage_p(m) = vegmatrixc_cap(ideadcroot_st,1)
+ deadstemn_p (m) = vegmatrixn_cap(ideadstem,1)
+ deadstemn_storage_p (m) = vegmatrixn_cap(ideadstem_st,1)
+ deadcrootn_p (m) = vegmatrixn_cap(ideadcroot,1)
+ deadcrootn_storage_p(m) = vegmatrixn_cap(ideadcroot_st,1)
+ ENDIF
+ ENDDO
+
+ AK_soil_acc (1:ndecomp_pools_vr,1:ndecomp_pools_vr) = 0._r8
+ AK_soil_nacc(1:ndecomp_pools_vr,1:ndecomp_pools_vr) = 0._r8
+ I_soil_acc (1:ndecomp_pools_vr) = 0._r8
+ I_soil_nacc (1:ndecomp_pools_vr) = 0._r8
+ DO j=1, nl_soil
+ ! C EXIT rate
+ AK_soil_acc ((i_met_lit-1)*nl_soil+j,(i_met_lit-1)*nl_soil+j) &
+ = - (AKX_met_exit_c_vr_acc(j,i) + diagVX_c_vr_acc(j,i_met_lit,i)) / decomp0_cpools_vr(j,i_met_lit,i)
+ AK_soil_acc ((i_cel_lit-1)*nl_soil+j,(i_cel_lit-1)*nl_soil+j) &
+ = - (AKX_cel_exit_c_vr_acc(j,i) + diagVX_c_vr_acc(j,i_cel_lit,i)) / decomp0_cpools_vr(j,i_cel_lit,i)
+ AK_soil_acc ((i_lig_lit-1)*nl_soil+j,(i_lig_lit-1)*nl_soil+j) &
+ = - (AKX_lig_exit_c_vr_acc(j,i) + diagVX_c_vr_acc(j,i_lig_lit,i)) / decomp0_cpools_vr(j,i_lig_lit,i)
+ AK_soil_acc ((i_cwd -1)*nl_soil+j,(i_cwd -1)*nl_soil+j) &
+ = - AKX_cwd_exit_c_vr_acc(j,i) / decomp0_cpools_vr(j,i_cwd ,i)
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j) &
+ = - (AKX_soil1_exit_c_vr_acc(j,i) + diagVX_c_vr_acc(j,i_soil1,i)) / decomp0_cpools_vr(j,i_soil1 ,i)
+ AK_soil_acc ((i_soil2 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j) &
+ = - (AKX_soil2_exit_c_vr_acc(j,i) + diagVX_c_vr_acc(j,i_soil2,i)) / decomp0_cpools_vr(j,i_soil2 ,i)
+ AK_soil_acc ((i_soil3 -1)*nl_soil+j,(i_soil3 -1)*nl_soil+j) &
+ = - (AKX_soil3_exit_c_vr_acc(j,i) + diagVX_c_vr_acc(j,i_soil3,i)) / decomp0_cpools_vr(j,i_soil3 ,i)
+
+ ! C transfer
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j,(i_met_lit-1)*nl_soil+j) &
+ = AKX_met_to_soil1_c_vr_acc (j,i) / decomp0_cpools_vr(j,i_met_lit,i)
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j,(i_cel_lit-1)*nl_soil+j) &
+ = AKX_cel_to_soil1_c_vr_acc (j,i) / decomp0_cpools_vr(j,i_cel_lit,i)
+ AK_soil_acc ((i_soil2 -1)*nl_soil+j,(i_lig_lit-1)*nl_soil+j) &
+ = AKX_lig_to_soil2_c_vr_acc (j,i) / decomp0_cpools_vr(j,i_lig_lit,i)
+ AK_soil_acc ((i_soil2 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j) &
+ = AKX_soil1_to_soil2_c_vr_acc(j,i) / decomp0_cpools_vr(j,i_soil1 ,i)
+ AK_soil_acc ((i_cel_lit-1)*nl_soil+j,(i_cwd -1)*nl_soil+j) &
+ = AKX_cwd_to_cel_c_vr_acc (j,i) / decomp0_cpools_vr(j,i_cwd ,i)
+ AK_soil_acc ((i_lig_lit-1)*nl_soil+j,(i_cwd -1)*nl_soil+j) &
+ = AKX_cwd_to_lig_c_vr_acc (j,i) / decomp0_cpools_vr(j,i_cwd ,i)
+ AK_soil_acc ((i_soil3 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j) &
+ = AKX_soil1_to_soil3_c_vr_acc(j,i) / decomp0_cpools_vr(j,i_soil1 ,i)
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j) &
+ = AKX_soil2_to_soil1_c_vr_acc(j,i) / decomp0_cpools_vr(j,i_soil2 ,i)
+ AK_soil_acc ((i_soil3 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j) &
+ = AKX_soil2_to_soil3_c_vr_acc(j,i) / decomp0_cpools_vr(j,i_soil2 ,i)
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j,(i_soil3 -1)*nl_soil+j) &
+ = AKX_soil3_to_soil1_c_vr_acc(j,i) / decomp0_cpools_vr(j,i_soil3 ,i)
+
+ ! C input
+ I_soil_acc((i_met_lit-1)*nl_soil+j) = I_met_c_vr_acc(j,i)
+ I_soil_acc((i_cel_lit-1)*nl_soil+j) = I_cel_c_vr_acc(j,i)
+ I_soil_acc((i_lig_lit-1)*nl_soil+j) = I_lig_c_vr_acc(j,i)
+ I_soil_acc((i_cwd -1)*nl_soil+j) = I_cwd_c_vr_acc(j,i)
+
+ ! N EXIT rate
+ AK_soil_nacc((i_met_lit-1)*nl_soil+j,(i_met_lit-1)*nl_soil+j) &
+ = - (AKX_met_exit_n_vr_acc(j,i) + diagVX_n_vr_acc(j,i_met_lit,i)) / decomp0_npools_vr(j,i_met_lit,i)
+ AK_soil_nacc((i_cel_lit-1)*nl_soil+j,(i_cel_lit-1)*nl_soil+j) &
+ = - (AKX_cel_exit_n_vr_acc(j,i) + diagVX_n_vr_acc(j,i_cel_lit,i)) / decomp0_npools_vr(j,i_cel_lit,i)
+ AK_soil_nacc((i_lig_lit-1)*nl_soil+j,(i_lig_lit-1)*nl_soil+j) &
+ = - (AKX_lig_exit_n_vr_acc(j,i) + diagVX_n_vr_acc(j,i_lig_lit,i)) / decomp0_npools_vr(j,i_lig_lit,i)
+ AK_soil_nacc((i_cwd -1)*nl_soil+j,(i_cwd -1)*nl_soil+j) &
+ = - AKX_cwd_exit_n_vr_acc(j,i) / decomp0_npools_vr(j,i_cwd ,i)
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j) &
+ = - (AKX_soil1_exit_n_vr_acc(j,i) + diagVX_n_vr_acc(j,i_soil1,i)) / decomp0_npools_vr(j,i_soil1 ,i)
+ AK_soil_nacc((i_soil2 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j) &
+ = - (AKX_soil2_exit_n_vr_acc(j,i) + diagVX_n_vr_acc(j,i_soil2,i)) / decomp0_npools_vr(j,i_soil2 ,i)
+ AK_soil_nacc((i_soil3 -1)*nl_soil+j,(i_soil3 -1)*nl_soil+j) &
+ = - (AKX_soil3_exit_n_vr_acc(j,i) + diagVX_n_vr_acc(j,i_soil3,i)) / decomp0_npools_vr(j,i_soil3 ,i)
+
+ ! N transfer
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j,(i_met_lit-1)*nl_soil+j) &
+ = AKX_met_to_soil1_n_vr_acc (j,i) / decomp0_npools_vr(j,i_met_lit,i)
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j,(i_cel_lit-1)*nl_soil+j) &
+ = AKX_cel_to_soil1_n_vr_acc (j,i) / decomp0_npools_vr(j,i_cel_lit,i)
+ AK_soil_nacc((i_soil2 -1)*nl_soil+j,(i_lig_lit-1)*nl_soil+j) &
+ = AKX_lig_to_soil2_n_vr_acc (j,i) / decomp0_npools_vr(j,i_lig_lit,i)
+ AK_soil_nacc((i_soil2 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j) &
+ = AKX_soil1_to_soil2_n_vr_acc(j,i) / decomp0_npools_vr(j,i_soil1 ,i)
+ AK_soil_nacc((i_cel_lit-1)*nl_soil+j,(i_cwd -1)*nl_soil+j) &
+ = AKX_cwd_to_cel_n_vr_acc (j,i) / decomp0_npools_vr(j,i_cwd ,i)
+ AK_soil_nacc((i_lig_lit-1)*nl_soil+j,(i_cwd -1)*nl_soil+j) &
+ = AKX_cwd_to_lig_n_vr_acc (j,i) / decomp0_npools_vr(j,i_cwd ,i)
+ AK_soil_nacc((i_soil3 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j) &
+ = AKX_soil1_to_soil3_n_vr_acc(j,i) / decomp0_npools_vr(j,i_soil1 ,i)
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j) &
+ = AKX_soil2_to_soil1_n_vr_acc(j,i) / decomp0_npools_vr(j,i_soil2 ,i)
+ AK_soil_nacc((i_soil3 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j) &
+ = AKX_soil2_to_soil3_n_vr_acc(j,i) / decomp0_npools_vr(j,i_soil2 ,i)
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j,(i_soil3 -1)*nl_soil+j) &
+ = AKX_soil3_to_soil1_n_vr_acc(j,i) / decomp0_npools_vr(j,i_soil3 ,i)
+
+ ENDDO
+
+ DO j=1,nl_soil-1
+ ! upper triadiagnonal entries for C
+ AK_soil_acc ((i_met_lit-1)*nl_soil+j,(i_met_lit-1)*nl_soil+j+1) &
+ = upperVX_c_vr_acc(j,i_met_lit,i) / decomp0_cpools_vr(j+1,i_met_lit,i)
+ AK_soil_acc ((i_cel_lit-1)*nl_soil+j,(i_cel_lit-1)*nl_soil+j+1) &
+ = upperVX_c_vr_acc(j,i_cel_lit,i) / decomp0_cpools_vr(j+1,i_cel_lit,i)
+ AK_soil_acc ((i_lig_lit-1)*nl_soil+j,(i_lig_lit-1)*nl_soil+j+1) &
+ = upperVX_c_vr_acc(j,i_lig_lit,i) / decomp0_cpools_vr(j+1,i_lig_lit,i)
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j+1) &
+ = upperVX_c_vr_acc(j,i_soil1 ,i) / decomp0_cpools_vr(j+1,i_soil1 ,i)
+ AK_soil_acc ((i_soil2 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j+1) &
+ = upperVX_c_vr_acc(j,i_soil2 ,i) / decomp0_cpools_vr(j+1,i_soil2 ,i)
+ AK_soil_acc ((i_soil3 -1)*nl_soil+j,(i_soil3 -1)*nl_soil+j+1) &
+ = upperVX_c_vr_acc(j,i_soil3 ,i) / decomp0_cpools_vr(j+1,i_soil3 ,i)
+
+ ! lower triadiagnonal entries for C
+ AK_soil_acc ((i_met_lit-1)*nl_soil+j+1,(i_met_lit-1)*nl_soil+j) &
+ = lowerVX_c_vr_acc(j+1,i_met_lit,i) / decomp0_cpools_vr(j,i_met_lit,i)
+ AK_soil_acc ((i_cel_lit-1)*nl_soil+j+1,(i_cel_lit-1)*nl_soil+j) &
+ = lowerVX_c_vr_acc(j+1,i_cel_lit,i) / decomp0_cpools_vr(j,i_cel_lit,i)
+ AK_soil_acc ((i_lig_lit-1)*nl_soil+j+1,(i_lig_lit-1)*nl_soil+j) &
+ = lowerVX_c_vr_acc(j+1,i_lig_lit,i) / decomp0_cpools_vr(j,i_lig_lit,i)
+ AK_soil_acc ((i_soil1 -1)*nl_soil+j+1,(i_soil1 -1)*nl_soil+j) &
+ = lowerVX_c_vr_acc(j+1,i_soil1 ,i) / decomp0_cpools_vr(j,i_soil1 ,i)
+ AK_soil_acc ((i_soil2 -1)*nl_soil+j+1,(i_soil2 -1)*nl_soil+j) &
+ = lowerVX_c_vr_acc(j+1,i_soil2 ,i) / decomp0_cpools_vr(j,i_soil2 ,i)
+ AK_soil_acc ((i_soil3 -1)*nl_soil+j+1,(i_soil3 -1)*nl_soil+j) &
+ = lowerVX_c_vr_acc(j+1,i_soil3 ,i) / decomp0_cpools_vr(j,i_soil3 ,i)
+
+
+ ! upper triadiagnonal entries for N
+ AK_soil_nacc((i_met_lit-1)*nl_soil+j,(i_met_lit-1)*nl_soil+j+1) &
+ = upperVX_n_vr_acc(j,i_met_lit,i) / decomp0_npools_vr(j+1,i_met_lit,i)
+ AK_soil_nacc((i_cel_lit-1)*nl_soil+j,(i_cel_lit-1)*nl_soil+j+1) &
+ = upperVX_n_vr_acc(j,i_cel_lit,i) / decomp0_npools_vr(j+1,i_cel_lit,i)
+ AK_soil_nacc((i_lig_lit-1)*nl_soil+j,(i_lig_lit-1)*nl_soil+j+1) &
+ = upperVX_n_vr_acc(j,i_lig_lit,i) / decomp0_npools_vr(j+1,i_lig_lit,i)
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j,(i_soil1 -1)*nl_soil+j+1) &
+ = upperVX_n_vr_acc(j,i_soil1 ,i) / decomp0_npools_vr(j+1,i_soil1 ,i)
+ AK_soil_nacc((i_soil2 -1)*nl_soil+j,(i_soil2 -1)*nl_soil+j+1) &
+ = upperVX_n_vr_acc(j,i_soil2 ,i) / decomp0_npools_vr(j+1,i_soil2 ,i)
+ AK_soil_nacc((i_soil3 -1)*nl_soil+j,(i_soil3 -1)*nl_soil+j+1) &
+ = upperVX_n_vr_acc(j,i_soil3 ,i) / decomp0_npools_vr(j+1,i_soil3 ,i)
+
+ ! lower triadiagnonal entries for N
+ AK_soil_nacc((i_met_lit-1)*nl_soil+j+1,(i_met_lit-1)*nl_soil+j) &
+ = lowerVX_n_vr_acc(j+1,i_met_lit,i) / decomp0_npools_vr(j,i_met_lit,i)
+ AK_soil_nacc((i_cel_lit-1)*nl_soil+j+1,(i_cel_lit-1)*nl_soil+j) &
+ = lowerVX_n_vr_acc(j+1,i_cel_lit,i) / decomp0_npools_vr(j,i_cel_lit,i)
+ AK_soil_nacc((i_lig_lit-1)*nl_soil+j+1,(i_lig_lit-1)*nl_soil+j) &
+ = lowerVX_n_vr_acc(j+1,i_lig_lit,i) / decomp0_npools_vr(j,i_lig_lit,i)
+ AK_soil_nacc((i_soil1 -1)*nl_soil+j+1,(i_soil1 -1)*nl_soil+j) &
+ = lowerVX_n_vr_acc(j+1,i_soil1 ,i) / decomp0_npools_vr(j,i_soil1 ,i)
+ AK_soil_nacc((i_soil2 -1)*nl_soil+j+1,(i_soil2 -1)*nl_soil+j) &
+ = lowerVX_n_vr_acc(j+1,i_soil2 ,i) / decomp0_npools_vr(j,i_soil2 ,i)
+ AK_soil_nacc((i_soil3 -1)*nl_soil+j+1,(i_soil3 -1)*nl_soil+j) &
+ = lowerVX_n_vr_acc(j+1,i_soil3 ,i) / decomp0_npools_vr(j,i_soil3 ,i)
+
+ ! N input
+ I_soil_nacc((i_met_lit-1)*nl_soil+j) = I_met_n_vr_acc(j,i)
+ I_soil_nacc((i_cel_lit-1)*nl_soil+j) = I_cel_n_vr_acc(j,i)
+ I_soil_nacc((i_lig_lit-1)*nl_soil+j) = I_lig_n_vr_acc(j,i)
+ I_soil_nacc((i_cwd -1)*nl_soil+j) = I_cwd_n_vr_acc(j,i)
+
+ ENDDO
+
+ DO k=1,ndecomp_pools_vr
+ IF (abs(AK_soil_acc(k,k)) .le. epsi)THEN !avoid inversion nan
+ AK_soil_acc(k,k) = - 1.e+36_r8
+ ENDIF
+ ENDDO
+
+ DO k=1,ndecomp_pools_vr
+ IF (abs(AK_soil_nacc(k,k)) .le. epsi)THEN
+ AK_soil_nacc(k,k) = - 1.e+36_r8
+ ENDIF
+ ENDDO
+
+ ! Calculate capacity
+ CALL inverse(AK_soil_acc (1:ndecomp_pools_vr,1:ndecomp_pools_vr),AKinv_soil (1:ndecomp_pools_vr,1:ndecomp_pools_vr),ndecomp_pools_vr)
+ CALL inverse(AK_soil_nacc(1:ndecomp_pools_vr,1:ndecomp_pools_vr),AKinvn_soil(1:ndecomp_pools_vr,1:ndecomp_pools_vr),ndecomp_pools_vr)
+ soilmatrixc_cap(:,1) = -matmul(AKinv_soil(1:ndecomp_pools_vr,1:ndecomp_pools_vr), I_soil_acc (1:ndecomp_pools_vr))
+ soilmatrixn_cap(:,1) = -matmul(AKinvn_soil(1:ndecomp_pools_vr,1:ndecomp_pools_vr),I_soil_nacc(1:ndecomp_pools_vr))
+
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ IF(soilmatrixc_cap(j+(k-1)*nl_soil,1) .lt. 0)THEN
+ soilmatrixc_cap(j+(k-1)*nl_soil,1) = 0._r8
+ ENDIF
+ IF(soilmatrixn_cap(j+(k-1)*nl_soil,1) .lt. 0)THEN
+ soilmatrixn_cap(j+(k-1)*nl_soil,1) = 0._r8
+ ENDIF
+ ENDDO
+ ENDDO
+
+ IF(DEF_USE_DiagMatrix)THEN
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_cpools_vr_Cap(j,k,i) = soilmatrixc_cap(j+(k-1)*nl_soil,1)
+ decomp_npools_vr_Cap(j,k,i) = soilmatrixn_cap(j+(k-1)*nl_soil,1)
+ ENDDO
+ ENDDO
+ ENDIF
+ IF(DEF_USE_SASU)THEN
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ IF((soilmatrixc_cap(j+(k-1)*nl_soil,1)/decomp0_cpools_vr(j,k,i) .gt. 100 .and. soilmatrixc_cap(j+(k-1)*nl_soil,1) .gt. 1.e+5_r8 &
+ .or. soilmatrixn_cap(j+(k-1)*nl_soil,1)/decomp0_npools_vr(j,k,i) .gt. 100 .and. soilmatrixn_cap(j+(k-1)*nl_soil,1) .gt. 1.e+3_r8) &
+ .or. k .eq. i_cwd .and. (soilmatrixc_cap(j+(k-1)*nl_soil,1)/decomp0_cpools_vr(j,k,i) .gt. 100 .and. soilmatrixc_cap(j+(k-1)*nl_soil,1) .gt. 1.e+5_r8 &
+ .or. soilmatrixn_cap(j+(k-1)*nl_soil,1)/decomp0_npools_vr(j,k,i) .gt. 100 .and. soilmatrixn_cap(j+(k-1)*nl_soil,1) .gt. 1.e+3_r8) )THEN
+ soilmatrixc_cap(j+(k-1)*nl_soil,1) = decomp_cpools_vr(j,k,i)
+ soilmatrixn_cap(j+(k-1)*nl_soil,1) = decomp_npools_vr(j,k,i)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ IF(any(soilmatrixc_cap(:,1) .gt. 1.e+8_r8) .or. any(soilmatrixn_cap(:,1) .gt. 1.e+8_r8))THEN
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ soilmatrixc_cap(j+(k-1)*nl_soil,1) = decomp_cpools_vr(j,k,i)
+ soilmatrixn_cap(j+(k-1)*nl_soil,1) = decomp_npools_vr(j,k,i)
+ ENDDO
+ ENDDO
+ ENDIF
+
+ ! IF spin up is on, the capacity replaces the pool size with capacity.
+ ! Copy the capacity into a 3D variable, and be ready to write to history files.
+
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_cpools_vr(j,k,i) = soilmatrixc_cap(j+(k-1)*nl_soil,1)
+ IF(floating_cn_ratio(k))THEN
+ decomp_npools_vr(j,k,i) = soilmatrixn_cap(j+(k-1)*nl_soil,1)
+ ELSE
+ decomp_npools_vr(j,k,i) = decomp_cpools_vr(j,k,i) / cn_decomp_pools(j,k,i)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ skip_balance_check(i) = .true.
+ ENDIF
+
+ ! Reset to accumulation variables to 0 at END of each year
+ DO m=ps, pe
+ I_leafc_p_acc (m) = 0._r8
+ I_leafc_st_p_acc (m) = 0._r8
+ I_frootc_p_acc (m) = 0._r8
+ I_frootc_st_p_acc (m) = 0._r8
+ I_livestemc_p_acc (m) = 0._r8
+ I_livestemc_st_p_acc (m) = 0._r8
+ I_deadstemc_p_acc (m) = 0._r8
+ I_deadstemc_st_p_acc (m) = 0._r8
+ I_livecrootc_p_acc (m) = 0._r8
+ I_livecrootc_st_p_acc(m) = 0._r8
+ I_deadcrootc_p_acc (m) = 0._r8
+ I_deadcrootc_st_p_acc(m) = 0._r8
+ I_grainc_p_acc (m) = 0._r8
+ I_grainc_st_p_acc (m) = 0._r8
+ I_leafn_p_acc (m) = 0._r8
+ I_leafn_st_p_acc (m) = 0._r8
+ I_frootn_p_acc (m) = 0._r8
+ I_frootn_st_p_acc (m) = 0._r8
+ I_livestemn_p_acc (m) = 0._r8
+ I_livestemn_st_p_acc (m) = 0._r8
+ I_deadstemn_p_acc (m) = 0._r8
+ I_deadstemn_st_p_acc (m) = 0._r8
+ I_livecrootn_p_acc (m) = 0._r8
+ I_livecrootn_st_p_acc(m) = 0._r8
+ I_deadcrootn_p_acc (m) = 0._r8
+ I_deadcrootn_st_p_acc(m) = 0._r8
+ I_grainn_p_acc (m) = 0._r8
+ I_grainn_st_p_acc (m) = 0._r8
+
+ AKX_leafc_xf_to_leafc_p_acc (m) = 0._r8
+ AKX_frootc_xf_to_frootc_p_acc (m) = 0._r8
+ AKX_livestemc_xf_to_livestemc_p_acc (m) = 0._r8
+ AKX_deadstemc_xf_to_deadstemc_p_acc (m) = 0._r8
+ AKX_livecrootc_xf_to_livecrootc_p_acc (m) = 0._r8
+ AKX_deadcrootc_xf_to_deadcrootc_p_acc (m) = 0._r8
+ AKX_grainc_xf_to_grainc_p_acc (m) = 0._r8
+ AKX_livestemc_to_deadstemc_p_acc (m) = 0._r8
+ AKX_livecrootc_to_deadcrootc_p_acc (m) = 0._r8
+
+ AKX_leafc_st_to_leafc_xf_p_acc (m) = 0._r8
+ AKX_frootc_st_to_frootc_xf_p_acc (m) = 0._r8
+ AKX_livestemc_st_to_livestemc_xf_p_acc (m) = 0._r8
+ AKX_deadstemc_st_to_deadstemc_xf_p_acc (m) = 0._r8
+ AKX_livecrootc_st_to_livecrootc_xf_p_acc(m) = 0._r8
+ AKX_deadcrootc_st_to_deadcrootc_xf_p_acc(m) = 0._r8
+ AKX_grainc_st_to_grainc_xf_p_acc (m) = 0._r8
+
+ AKX_leafc_exit_p_acc (m) = 0._r8
+ AKX_frootc_exit_p_acc (m) = 0._r8
+ AKX_livestemc_exit_p_acc (m) = 0._r8
+ AKX_deadstemc_exit_p_acc (m) = 0._r8
+ AKX_livecrootc_exit_p_acc (m) = 0._r8
+ AKX_deadcrootc_exit_p_acc (m) = 0._r8
+ AKX_grainc_exit_p_acc (m) = 0._r8
+
+ AKX_leafc_st_exit_p_acc (m) = 0._r8
+ AKX_frootc_st_exit_p_acc (m) = 0._r8
+ AKX_livestemc_st_exit_p_acc (m) = 0._r8
+ AKX_deadstemc_st_exit_p_acc (m) = 0._r8
+ AKX_livecrootc_st_exit_p_acc (m) = 0._r8
+ AKX_deadcrootc_st_exit_p_acc (m) = 0._r8
+ AKX_grainc_st_exit_p_acc (m) = 0._r8
+
+ AKX_leafc_xf_exit_p_acc (m) = 0._r8
+ AKX_frootc_xf_exit_p_acc (m) = 0._r8
+ AKX_livestemc_xf_exit_p_acc (m) = 0._r8
+ AKX_deadstemc_xf_exit_p_acc (m) = 0._r8
+ AKX_livecrootc_xf_exit_p_acc (m) = 0._r8
+ AKX_deadcrootc_xf_exit_p_acc (m) = 0._r8
+ AKX_grainc_xf_exit_p_acc (m) = 0._r8
+
+ AKX_leafn_xf_to_leafn_p_acc (m) = 0._r8
+ AKX_frootn_xf_to_frootn_p_acc (m) = 0._r8
+ AKX_livestemn_xf_to_livestemn_p_acc (m) = 0._r8
+ AKX_deadstemn_xf_to_deadstemn_p_acc (m) = 0._r8
+ AKX_livecrootn_xf_to_livecrootn_p_acc (m) = 0._r8
+ AKX_deadcrootn_xf_to_deadcrootn_p_acc (m) = 0._r8
+ AKX_grainn_xf_to_grainn_p_acc (m) = 0._r8
+ AKX_livestemn_to_deadstemn_p_acc (m) = 0._r8
+ AKX_livecrootn_to_deadcrootn_p_acc (m) = 0._r8
+
+ AKX_leafn_st_to_leafn_xf_p_acc (m) = 0._r8
+ AKX_frootn_st_to_frootn_xf_p_acc (m) = 0._r8
+ AKX_livestemn_st_to_livestemn_xf_p_acc (m) = 0._r8
+ AKX_deadstemn_st_to_deadstemn_xf_p_acc (m) = 0._r8
+ AKX_livecrootn_st_to_livecrootn_xf_p_acc(m) = 0._r8
+ AKX_deadcrootn_st_to_deadcrootn_xf_p_acc(m) = 0._r8
+ AKX_grainn_st_to_grainn_xf_p_acc (m) = 0._r8
+
+ AKX_leafn_to_retransn_p_acc (m) = 0._r8
+ AKX_frootn_to_retransn_p_acc (m) = 0._r8
+ AKX_livestemn_to_retransn_p_acc (m) = 0._r8
+ AKX_livecrootn_to_retransn_p_acc (m) = 0._r8
+
+ AKX_retransn_to_leafn_p_acc (m) = 0._r8
+ AKX_retransn_to_frootn_p_acc (m) = 0._r8
+ AKX_retransn_to_livestemn_p_acc (m) = 0._r8
+ AKX_retransn_to_deadstemn_p_acc (m) = 0._r8
+ AKX_retransn_to_livecrootn_p_acc (m) = 0._r8
+ AKX_retransn_to_deadcrootn_p_acc (m) = 0._r8
+ AKX_retransn_to_grainn_p_acc (m) = 0._r8
+
+ AKX_retransn_to_leafn_st_p_acc (m) = 0._r8
+ AKX_retransn_to_frootn_st_p_acc (m) = 0._r8
+ AKX_retransn_to_livestemn_st_p_acc (m) = 0._r8
+ AKX_retransn_to_deadstemn_st_p_acc (m) = 0._r8
+ AKX_retransn_to_livecrootn_st_p_acc (m) = 0._r8
+ AKX_retransn_to_deadcrootn_st_p_acc (m) = 0._r8
+ AKX_retransn_to_grainn_st_p_acc (m) = 0._r8
+
+ AKX_leafn_exit_p_acc (m) = 0._r8
+ AKX_frootn_exit_p_acc (m) = 0._r8
+ AKX_livestemn_exit_p_acc (m) = 0._r8
+ AKX_deadstemn_exit_p_acc (m) = 0._r8
+ AKX_livecrootn_exit_p_acc (m) = 0._r8
+ AKX_deadcrootn_exit_p_acc (m) = 0._r8
+ AKX_grainn_exit_p_acc (m) = 0._r8
+ AKX_retransn_exit_p_acc (m) = 0._r8
+
+ AKX_leafn_st_exit_p_acc (m) = 0._r8
+ AKX_frootn_st_exit_p_acc (m) = 0._r8
+ AKX_livestemn_st_exit_p_acc (m) = 0._r8
+ AKX_deadstemn_st_exit_p_acc (m) = 0._r8
+ AKX_livecrootn_st_exit_p_acc (m) = 0._r8
+ AKX_deadcrootn_st_exit_p_acc (m) = 0._r8
+ AKX_grainn_st_exit_p_acc (m) = 0._r8
+
+ AKX_leafn_xf_exit_p_acc (m) = 0._r8
+ AKX_frootn_xf_exit_p_acc (m) = 0._r8
+ AKX_livestemn_xf_exit_p_acc (m) = 0._r8
+ AKX_deadstemn_xf_exit_p_acc (m) = 0._r8
+ AKX_livecrootn_xf_exit_p_acc (m) = 0._r8
+ AKX_deadcrootn_xf_exit_p_acc (m) = 0._r8
+ AKX_grainn_xf_exit_p_acc (m) = 0._r8
+ ENDDO
+
+ DO j=1,nl_soil
+ AKX_met_exit_c_vr_acc (j,i) = 0._r8
+ AKX_cel_exit_c_vr_acc (j,i) = 0._r8
+ AKX_lig_exit_c_vr_acc (j,i) = 0._r8
+ AKX_cwd_exit_c_vr_acc (j,i) = 0._r8
+ AKX_soil1_exit_c_vr_acc (j,i) = 0._r8
+ AKX_soil2_exit_c_vr_acc (j,i) = 0._r8
+ AKX_soil3_exit_c_vr_acc (j,i) = 0._r8
+
+ AKX_met_to_soil1_c_vr_acc (j,i) = 0._r8
+ AKX_cel_to_soil1_c_vr_acc (j,i) = 0._r8
+ AKX_lig_to_soil2_c_vr_acc (j,i) = 0._r8
+ AKX_soil1_to_soil2_c_vr_acc(j,i) = 0._r8
+ AKX_cwd_to_cel_c_vr_acc (j,i) = 0._r8
+ AKX_cwd_to_lig_c_vr_acc (j,i) = 0._r8
+ AKX_soil1_to_soil3_c_vr_acc(j,i) = 0._r8
+ AKX_soil2_to_soil1_c_vr_acc(j,i) = 0._r8
+ AKX_soil2_to_soil3_c_vr_acc(j,i) = 0._r8
+ AKX_soil3_to_soil1_c_vr_acc(j,i) = 0._r8
+
+ diagVX_c_vr_acc (j,i_met_lit,i) = 0._r8
+ diagVX_c_vr_acc (j,i_cel_lit,i) = 0._r8
+ diagVX_c_vr_acc (j,i_lig_lit,i) = 0._r8
+ diagVX_c_vr_acc (j,i_cwd ,i) = 0._r8
+ diagVX_c_vr_acc (j,i_soil1 ,i) = 0._r8
+ diagVX_c_vr_acc (j,i_soil2 ,i) = 0._r8
+ diagVX_c_vr_acc (j,i_soil3 ,i) = 0._r8
+
+ upperVX_c_vr_acc (j,i_met_lit,i) = 0._r8
+ upperVX_c_vr_acc (j,i_cel_lit,i) = 0._r8
+ upperVX_c_vr_acc (j,i_lig_lit,i) = 0._r8
+ upperVX_c_vr_acc (j,i_cwd ,i) = 0._r8
+ upperVX_c_vr_acc (j,i_soil1 ,i) = 0._r8
+ upperVX_c_vr_acc (j,i_soil2 ,i) = 0._r8
+ upperVX_c_vr_acc (j,i_soil3 ,i) = 0._r8
+
+ lowerVX_c_vr_acc (j,i_met_lit,i) = 0._r8
+ lowerVX_c_vr_acc (j,i_cel_lit,i) = 0._r8
+ lowerVX_c_vr_acc (j,i_lig_lit,i) = 0._r8
+ lowerVX_c_vr_acc (j,i_cwd ,i) = 0._r8
+ lowerVX_c_vr_acc (j,i_soil1 ,i) = 0._r8
+ lowerVX_c_vr_acc (j,i_soil2 ,i) = 0._r8
+ lowerVX_c_vr_acc (j,i_soil3 ,i) = 0._r8
+
+ AKX_met_exit_n_vr_acc (j,i) = 0._r8
+ AKX_cel_exit_n_vr_acc (j,i) = 0._r8
+ AKX_lig_exit_n_vr_acc (j,i) = 0._r8
+ AKX_cwd_exit_n_vr_acc (j,i) = 0._r8
+ AKX_soil1_exit_n_vr_acc (j,i) = 0._r8
+ AKX_soil2_exit_n_vr_acc (j,i) = 0._r8
+ AKX_soil3_exit_n_vr_acc (j,i) = 0._r8
+
+ AKX_met_to_soil1_n_vr_acc (j,i) = 0._r8
+ AKX_cel_to_soil1_n_vr_acc (j,i) = 0._r8
+ AKX_lig_to_soil2_n_vr_acc (j,i) = 0._r8
+ AKX_soil1_to_soil2_n_vr_acc(j,i) = 0._r8
+ AKX_cwd_to_cel_n_vr_acc (j,i) = 0._r8
+ AKX_cwd_to_lig_n_vr_acc (j,i) = 0._r8
+ AKX_soil1_to_soil3_n_vr_acc(j,i) = 0._r8
+ AKX_soil2_to_soil1_n_vr_acc(j,i) = 0._r8
+ AKX_soil2_to_soil3_n_vr_acc(j,i) = 0._r8
+ AKX_soil3_to_soil1_n_vr_acc(j,i) = 0._r8
+
+ diagVX_n_vr_acc (j,i_met_lit,i) = 0._r8
+ diagVX_n_vr_acc (j,i_cel_lit,i) = 0._r8
+ diagVX_n_vr_acc (j,i_lig_lit,i) = 0._r8
+ diagVX_n_vr_acc (j,i_cwd ,i) = 0._r8
+ diagVX_n_vr_acc (j,i_soil1 ,i) = 0._r8
+ diagVX_n_vr_acc (j,i_soil2 ,i) = 0._r8
+ diagVX_n_vr_acc (j,i_soil3 ,i) = 0._r8
+
+ upperVX_n_vr_acc (j,i_met_lit,i) = 0._r8
+ upperVX_n_vr_acc (j,i_cel_lit,i) = 0._r8
+ upperVX_n_vr_acc (j,i_lig_lit,i) = 0._r8
+ upperVX_n_vr_acc (j,i_cwd ,i) = 0._r8
+ upperVX_n_vr_acc (j,i_soil1 ,i) = 0._r8
+ upperVX_n_vr_acc (j,i_soil2 ,i) = 0._r8
+ upperVX_n_vr_acc (j,i_soil3 ,i) = 0._r8
+
+ lowerVX_n_vr_acc (j,i_met_lit,i) = 0._r8
+ lowerVX_n_vr_acc (j,i_cel_lit,i) = 0._r8
+ lowerVX_n_vr_acc (j,i_lig_lit,i) = 0._r8
+ lowerVX_n_vr_acc (j,i_cwd ,i) = 0._r8
+ lowerVX_n_vr_acc (j,i_soil1 ,i) = 0._r8
+ lowerVX_n_vr_acc (j,i_soil2 ,i) = 0._r8
+ lowerVX_n_vr_acc (j,i_soil3 ,i) = 0._r8
+
+ I_met_c_vr_acc(j,i) = 0._r8
+ I_cel_c_vr_acc(j,i) = 0._r8
+ I_lig_c_vr_acc(j,i) = 0._r8
+ I_cwd_c_vr_acc(j,i) = 0._r8
+
+ I_met_n_vr_acc(j,i) = 0._r8
+ I_cel_n_vr_acc(j,i) = 0._r8
+ I_lig_n_vr_acc(j,i) = 0._r8
+ I_cwd_n_vr_acc(j,i) = 0._r8
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE CNSASU
+
+ SUBROUTINE inverse(a,c,n)
+
+ ! !DESCRIPTION:
+ ! Inverse matrix
+ ! Method: Based on Doolittle LU factorization for Ax=b
+ ! Alex G. December 2009
+ !-----------------------------------------------------------
+ ! input ...
+ ! a(n,n) - array of coefficients for matrix A
+ ! n - dimension
+ ! output ...
+ ! c(n,n) - inverse matrix of A
+ ! comments ...
+ ! the original matrix a(n,n) will be destroyed
+ ! during the calculation
+
+ IMPLICIT NONE
+ ! Arguments
+ integer,intent(in) :: n ! Size of matrix
+ real(r8),intent(in) :: a(:,:) ! Input matrix to fine the inverse of
+ real(r8),intent(out) :: c(:,:) ! Output inverse
+ ! Local variables
+ real(r8) :: L(n,n) ! matrix of the elimination coefficient
+ real(r8) :: U(n,n) ! Upper triangular part of input matrix A
+ real(r8) :: aa(n,n) ! Temporary equal to input matrix a
+ real(r8) :: b(n) ! Temporary vector
+ real(r8) :: d(n) ! Temporary vector (solution of L*d)
+ real(r8) :: x(n) ! Temporary vector (U*x = d)
+ real(r8) :: coeff ! coefficient
+ integer i, j, k ! Indices
+ character(len=*), parameter :: subname = 'inverse'
+
+ DO k=1,n
+ IF ( a(k,k) == 0.0_r8 )THEN
+ CALL abort
+ ENDIF
+ ENDDO
+ !
+ ! step 0: initialization for matrices L and U and b
+ ! Fortran 90/95 aloows such operations on matrices
+ !
+ L=0.0
+ U=0.0
+ b=0.0
+
+ aa=a
+ !
+ ! Step 1: forward elimination
+ !
+ DO k=1, n-1
+ DO i=k+1,n
+ ! Already verifieid that divisor isn't zero
+ coeff=aa(i,k)/aa(k,k)
+ L(i,k) = coeff
+ DO j=k+1,n
+ aa(i,j) = aa(i,j)-coeff*aa(k,j)
+ ENDDO
+ ENDDO
+ ENDDO
+
+ !
+ ! Step 2: prepare L and U matrices
+ ! L matrix is a matrix of the elimination coefficient
+ ! + the diagonal elements are 1.0
+ !
+ DO i=1,n
+ L(i,i) = 1.0
+ ENDDO
+ !
+ ! U matrix is the upper triangular part of A
+ !
+ DO j=1,n
+ DO i=1,j
+ U(i,j) = aa(i,j)
+ ENDDO
+ ENDDO
+ !
+ ! Step 3: compute columns of the inverse matrix C
+ !
+ DO k=1,n
+ b(k)=1.0
+ d(1) = b(1)
+ ! Step 3a: Solve Ld=b using the forward substitution
+ DO i=2,n
+ d(i)=b(i)
+ DO j=1,i-1
+ d(i) = d(i) - L(i,j)*d(j)
+ ENDDO
+ ENDDO
+ ! Step 3b: Solve Ux=d using the back substitution
+ x(n)=d(n)/U(n,n)
+ DO i = n-1,1,-1
+ x(i) = d(i)
+ DO j=n,i+1,-1
+ x(i)=x(i)-U(i,j)*x(j)
+ ENDDO
+ ! Already verifieid that divisor isn't zero
+ x(i) = x(i)/u(i,i)
+ ENDDO
+ ! Step 3c: fill the solutions x(n) into column k of C
+ DO i=1,n
+ c(i,k) = x(i)
+ ENDDO
+ b(k)=0.0
+ ENDDO
+
+ END SUBROUTINE inverse
+
+END MODULE MOD_BGC_CNSASU
+
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNSummary.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNSummary.F90
new file mode 100644
index 0000000000..0d612d9eb7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNSummary.F90
@@ -0,0 +1,919 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_CNSummary
+
+!------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! bgc_CNSummaryMod calculates following statistics:
+! 1) total CN fluxes and pool sizes from individual contribution of each pool.
+! 2) aggregate the PFT-level fluxes and pool sizes into Column-level fluxes and pool sizes.
+! 3) PFT-level leaf pool sizes, GPP and crop production.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_NITRIF, DEF_USE_DiagMatrix
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_Vars_PFTimeVariables, only:irrig_method_p, lai_p
+ USE MOD_Vars_TimeInvariants, only: BD_all
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ totlitc, totsomc, totcwdc, decomp_cpools, decomp_cpools_vr, ctrunc_soil,ctrunc_veg, ctrunc_vr, &
+ totlitn, totsomn, totcwdn, decomp_npools, decomp_npools_vr, ntrunc_soil,ntrunc_veg, ntrunc_vr, &
+ totvegc, totvegn, totcolc, totcoln, sminn, sminn_vr, totsoiln_vr, &
+ leafc, frootc, livestemc, deadstemc, livecrootc, deadcrootc, leafc_storage, frootc_storage, livestemc_storage, &
+ deadstemc_storage, livecrootc_storage, deadcrootc_storage, leafc_xfer, frootc_xfer, livestemc_xfer, &
+ deadstemc_xfer, livecrootc_xfer, deadcrootc_xfer, xsmrpool, &
+ leafcCap, frootcCap, livestemcCap, deadstemcCap, livecrootcCap, deadcrootcCap, leafc_storageCap, frootc_storageCap, &
+ livestemc_storageCap, deadstemc_storageCap, livecrootc_storageCap, deadcrootc_storageCap, leafc_xferCap, &
+ frootc_xferCap, livestemc_xferCap, deadstemc_xferCap, livecrootc_xferCap, deadcrootc_xferCap, &
+#ifdef CROP
+ grainc, grainc_storage, grainc_xfer, &
+ cropseedc_deficit, cropprod1c, cphase, hui, vf, gddplant, gddmaturity, &
+ manunitro, fertnitro_corn, fertnitro_swheat, fertnitro_wwheat, fertnitro_soybean, &
+ fertnitro_cotton, fertnitro_rice1, fertnitro_rice2, fertnitro_sugarcane, &
+ grainn, grainn_storage, grainn_xfer, plantdate, &
+#endif
+ leafn, frootn, livestemn, deadstemn, livecrootn, deadcrootn, leafn_storage, frootn_storage, livestemn_storage, &
+ deadstemn_storage, livecrootn_storage, deadcrootn_storage, leafn_xfer, frootn_xfer, livestemn_xfer, &
+ deadstemn_xfer, livecrootn_xfer, deadcrootn_xfer, retransn, downreg, lag_npp, &
+ leafnCap, frootnCap, livestemnCap, deadstemnCap, livecrootnCap, deadcrootnCap, leafn_storageCap, frootn_storageCap, &
+ livestemn_storageCap, deadstemn_storageCap, livecrootn_storageCap, deadcrootn_storageCap, leafn_xferCap, &
+ frootn_xferCap, livestemn_xferCap, deadstemn_xferCap, livecrootn_xferCap, deadcrootn_xferCap
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ is_litter, is_soil, is_cwd, nfix_timeconst
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ leafc_p, frootc_p, livestemc_p, deadstemc_p, livecrootc_p, deadcrootc_p, &
+ leafc_storage_p, frootc_storage_p, livestemc_storage_p, &
+ deadstemc_storage_p, livecrootc_storage_p, deadcrootc_storage_p, gresp_storage_p, &
+ leafc_xfer_p, frootc_xfer_p, livestemc_xfer_p, &
+ deadstemc_xfer_p, livecrootc_xfer_p, deadcrootc_xfer_p, gresp_xfer_p, xsmrpool_p, &
+ leafcCap_p, frootcCap_p, livestemcCap_p, deadstemcCap_p, livecrootcCap_p, deadcrootcCap_p, &
+ leafc_storageCap_p, frootc_storageCap_p, livestemc_storageCap_p, &
+ deadstemc_storageCap_p, livecrootc_storageCap_p, deadcrootc_storageCap_p, &
+ leafc_xferCap_p, frootc_xferCap_p, livestemc_xferCap_p, &
+ deadstemc_xferCap_p, livecrootc_xferCap_p, deadcrootc_xferCap_p, &
+#ifdef CROP
+ grainc_p, grainc_storage_p, grainc_xfer_p, &
+#endif
+ ctrunc_p, totvegc_p, &
+ cropseedc_deficit_p, cropprod1c_p, cpool_p, &
+#ifdef CROP
+ plantdate_p, cphase_p, manunitro_p, fertnitro_p, hui_p, gddmaturity_p, gddplant_p, vf_p, &
+ grainn_p, grainn_storage_p, grainn_xfer_p, cropseedn_deficit_p, &
+#endif
+ leafn_p, frootn_p, livestemn_p, deadstemn_p, livecrootn_p, deadcrootn_p, &
+ leafn_storage_p, frootn_storage_p, livestemn_storage_p, &
+ deadstemn_storage_p, livecrootn_storage_p, deadcrootn_storage_p, &
+ leafn_xfer_p, frootn_xfer_p, livestemn_xfer_p, &
+ deadstemn_xfer_p, livecrootn_xfer_p, deadcrootn_xfer_p, retransn_p, npool_p, &
+ leafnCap_p, frootnCap_p, livestemnCap_p, deadstemnCap_p, livecrootnCap_p, deadcrootnCap_p, &
+ leafn_storageCap_p, frootn_storageCap_p, livestemn_storageCap_p, &
+ deadstemn_storageCap_p, livecrootn_storageCap_p, deadcrootn_storageCap_p, &
+ leafn_xferCap_p, frootn_xferCap_p, livestemn_xferCap_p, &
+ deadstemn_xferCap_p, livecrootn_xferCap_p, deadcrootn_xferCap_p, &
+ ntrunc_p, totvegn_p, downreg_p
+ USE MOD_Vars_PFTimeInvariants, only: pftfrac
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ gpp_enftemp, gpp_enfboreal, gpp_dnfboreal, gpp_ebftrop, gpp_ebftemp, gpp_dbftrop, gpp_dbftemp, &
+ gpp_dbfboreal, gpp_ebstemp, gpp_dbstemp, gpp_dbsboreal, gpp_c3arcgrass, gpp_c3grass, gpp_c4grass, &
+ leafc_enftemp, leafc_enfboreal, leafc_dnfboreal, leafc_ebftrop, leafc_ebftemp, leafc_dbftrop, leafc_dbftemp, &
+ leafc_dbfboreal, leafc_ebstemp, leafc_dbstemp, leafc_dbsboreal, leafc_c3arcgrass, leafc_c3grass, leafc_c4grass, &
+ decomp_hr, decomp_hr_vr, gpp, ar, er, supplement_to_sminn, supplement_to_sminn_vr, &
+ npp_enftemp, npp_enfboreal, npp_dnfboreal, npp_ebftrop, npp_ebftemp, npp_dbftrop, npp_dbftemp, &
+ npp_dbfboreal, npp_ebstemp, npp_dbstemp, npp_dbsboreal, npp_c3arcgrass, npp_c3grass, npp_c4grass, &
+ npptoleafc_enftemp, npptoleafc_enfboreal, npptoleafc_dnfboreal, npptoleafc_ebftrop, &
+ npptoleafc_ebftemp, npptoleafc_dbftrop, npptoleafc_dbftemp, npptoleafc_dbfboreal, npptoleafc_ebstemp, &
+ npptoleafc_dbstemp, npptoleafc_dbsboreal, npptoleafc_c3arcgrass, npptoleafc_c3grass, npptoleafc_c4grass, &
+#ifdef CROP
+ cropprod1c_loss, grainc_to_cropprodc, grainc_to_seed, grainn_to_cropprodn, &
+#endif
+ sminn_leached, sminn_leached_vr, smin_no3_leached, smin_no3_leached_vr, smin_no3_runoff, smin_no3_runoff_vr, &
+ f_n2o_nit, f_n2o_nit_vr, decomp_cpools_transport_tendency, decomp_npools_transport_tendency, &
+ denit, f_denit_vr, fire_closs, hrv_xsmrpool_to_atm, som_c_leached, som_n_leached, sminn_to_denit_excess_vr, &
+ sminn_to_denit_decomp_vr
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ psn_to_cpool_p, leaf_mr_p, froot_mr_p, livestem_mr_p, livecroot_mr_p, &
+ cpool_leaf_gr_p, cpool_froot_gr_p, cpool_livestem_gr_p, cpool_deadstem_gr_p, &
+ cpool_livecroot_gr_p, cpool_deadcroot_gr_p, transfer_leaf_gr_p, transfer_froot_gr_p, &
+ transfer_livestem_gr_p, transfer_deadstem_gr_p, &
+ transfer_livecroot_gr_p, transfer_deadcroot_gr_p, &
+ cpool_leaf_storage_gr_p, cpool_froot_storage_gr_p, &
+ cpool_livestem_storage_gr_p, cpool_deadstem_storage_gr_p, &
+ cpool_livecroot_storage_gr_p, cpool_deadcroot_storage_gr_p, &
+ grain_mr_p, xsmrpool_to_atm_p, cpool_grain_gr_p, &
+ transfer_grain_gr_p, cpool_grain_storage_gr_p, soil_change_p, &
+ fire_closs_p, hrv_xsmrpool_to_atm_p, &
+ cpool_to_leafc_p, cpool_to_leafc_storage_p, &
+#ifdef CROP
+ cropprod1c_loss_p, grainc_to_seed_p, grainc_to_food_p, grainn_to_food_p, &
+#endif
+ m_leafc_to_fire_p, m_leafc_storage_to_fire_p, m_leafc_xfer_to_fire_p, &
+ m_frootc_to_fire_p, m_frootc_storage_to_fire_p, m_frootc_xfer_to_fire_p, &
+ m_livestemc_to_fire_p, m_livestemc_storage_to_fire_p, m_livestemc_xfer_to_fire_p, &
+ m_deadstemc_to_fire_p, m_deadstemc_storage_to_fire_p, m_deadstemc_xfer_to_fire_p, &
+ m_livecrootc_to_fire_p, m_livecrootc_storage_to_fire_p, m_livecrootc_xfer_to_fire_p, &
+ m_deadcrootc_to_fire_p, m_deadcrootc_storage_to_fire_p, m_deadcrootc_xfer_to_fire_p, &
+ m_gresp_storage_to_fire_p, m_gresp_xfer_to_fire_p
+ USE MOD_Vars_TimeVariables, only: &
+ irrig_method_corn , irrig_method_swheat, irrig_method_wwheat, irrig_method_soybean , &
+ irrig_method_cotton, irrig_method_rice1 , irrig_method_rice2 , irrig_method_sugarcane, &
+ lai_enftemp, lai_enfboreal, lai_dnfboreal, lai_ebftrop, lai_ebftemp, lai_dbftrop, lai_dbftemp, &
+ lai_dbfboreal, lai_ebstemp, lai_dbstemp, lai_dbsboreal, lai_c3arcgrass, lai_c3grass, lai_c4grass
+
+ USE MOD_Vars_TimeInvariants, only: patchclass
+ USE MOD_Vars_Global, only: spval
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ PUBLIC CNDriverSummarizeStates
+ PUBLIC CNDriverSummarizeFluxes
+
+ PRIVATE soilbiogeochem_carbonstate_summary
+ PRIVATE soilbiogeochem_nitrogenstate_summary
+ PRIVATE cnveg_carbonstate_summary
+ PRIVATE cnveg_nitrogenstate_summary
+ PRIVATE soilbiogeochem_carbonflux_summary
+ PRIVATE soilbiogeochem_nitrogenflux_summary
+ PRIVATE cnveg_carbonflux_summary
+ PRIVATE cnveg_nitrogenflux_summary
+
+CONTAINS
+
+ SUBROUTINE CNDriverSummarizeStates(i,ps,pe,nl_soil,dz_soi,ndecomp_pools,init)
+
+! !DESCRIPTION:
+! summarizes CN state varaibles for veg and soil.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ integer, intent(in) :: nl_soil ! number of total soil
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+ integer, intent(in) :: ndecomp_pools ! number of total soil & litter pools
+ logical, intent(in) :: init
+
+ CALL soilbiogeochem_carbonstate_summary(i,nl_soil,dz_soi,ndecomp_pools)
+ CALL soilbiogeochem_nitrogenstate_summary(i,nl_soil,dz_soi,ndecomp_pools)
+
+ CALL cnveg_carbonstate_summary(i,ps,pe,init)
+ CALL cnveg_nitrogenstate_summary(i,ps,pe)
+
+ END SUBROUTINE CNDriverSummarizeStates
+
+ SUBROUTINE CNDriverSummarizeFluxes(i,ps,pe,nl_soil,dz_soi,ndecomp_transitions,ndecomp_pools,deltim)
+
+! !DESCRIPTION:
+! summarizes CN flux varaibles for veg and soil.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+ integer, intent(in) :: ndecomp_transitions ! number of total transfers between soil and litter pools in the decomposition
+ integer, intent(in) :: ndecomp_pools ! number of tootal soil & litter pools
+ real(r8),intent(in) :: deltim ! time step in seconds
+
+ CALL soilbiogeochem_carbonflux_summary(i,nl_soil,dz_soi,ndecomp_transitions,ndecomp_pools)
+
+ CALL soilbiogeochem_nitrogenflux_summary(i,nl_soil,dz_soi,ndecomp_transitions,ndecomp_pools)
+
+ CALL cnveg_carbonflux_summary(i,ps,pe,deltim)
+
+ CALL cnveg_nitrogenflux_summary(i,ps,pe)
+
+ END SUBROUTINE CNDriverSummarizeFluxes
+
+ SUBROUTINE soilbiogeochem_carbonstate_summary(i,nl_soil,dz_soi, ndecomp_pools)
+
+! !DESCRIPTION
+! summarizes soil C state varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+ integer, intent(in) :: ndecomp_pools ! number of tootal soil & litter pools
+
+ integer :: l,j
+
+ totsomc(i) = 0._r8
+ totlitc(i) = 0._r8
+ totcwdc(i) = 0._r8
+ ctrunc_soil(i) = 0._r8
+
+ DO l = 1, ndecomp_pools
+ decomp_cpools(l,i) = 0._r8
+ DO j = 1, nl_soil
+ decomp_cpools(l,i) = decomp_cpools(l,i) + decomp_cpools_vr(j,l,i) * dz_soi(j)
+ ENDDO
+ ENDDO
+
+ DO l = 1, ndecomp_pools
+ IF(is_litter(l))THEN
+ totlitc(i) = totlitc(i) + decomp_cpools(l,i)
+ ENDIF
+ IF(is_soil(l))THEN
+ totsomc(i) = totsomc(i) + decomp_cpools(l,i)
+ ENDIF
+ IF(is_cwd(l))THEN
+ totcwdc(i) = totcwdc(i) + decomp_cpools(l,i)
+ ENDIF
+ ENDDO
+
+ DO j = 1, nl_soil
+ ctrunc_soil(i) = ctrunc_soil(i) + ctrunc_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ END SUBROUTINE soilbiogeochem_carbonstate_summary
+
+ SUBROUTINE soilbiogeochem_nitrogenstate_summary(i,nl_soil,dz_soi,ndecomp_pools)
+
+! !DESCRIPTION
+! summarizes soil N state varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+ integer, intent(in) :: ndecomp_pools ! number of tootal soil & litter pools
+
+ integer :: l,j
+
+ totsomn(i) = 0._r8
+ totlitn(i) = 0._r8
+ totcwdn(i) = 0._r8
+ sminn(i) = 0._r8
+ ntrunc_soil(i) = 0._r8
+ totsoiln_vr(1:nl_soil,i) = 0 ! soil total nitrogen (gN/gsoil * 100%)
+
+ DO l = 1, ndecomp_pools
+ decomp_npools(l,i) = 0._r8
+ DO j = 1, nl_soil
+ decomp_npools(l,i) = decomp_npools(l,i) + decomp_npools_vr(j,l,i) * dz_soi(j)
+ totsoiln_vr(j,i) = totsoiln_vr(j,i) + decomp_npools_vr(j,l,i) / (BD_all(j,i) * 1000) * 100 !(unit %)
+ ENDDO
+ ENDDO
+
+ DO j = 1, nl_soil
+ sminn(i) = sminn(i) + sminn_vr(j,i) * dz_soi(j)
+ totsoiln_vr(j,i) = totsoiln_vr(j,i) + sminn_vr(j,i) / (BD_all(j,i) * 1000) * 100 !(unit %)
+ ENDDO
+
+ DO l = 1, ndecomp_pools
+ IF(is_litter(l))THEN
+ totlitn(i) = totlitn(i) + decomp_npools(l,i)
+ ENDIF
+ IF(is_soil(l))THEN
+ totsomn(i) = totsomn(i) + decomp_npools(l,i)
+ ENDIF
+ IF(is_cwd(l))THEN
+ totcwdn(i) = totcwdn(i) + decomp_npools(l,i)
+ ENDIF
+ ENDDO
+
+ DO j = 1, nl_soil
+ ntrunc_soil(i) = ntrunc_soil(i) + ntrunc_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ END SUBROUTINE soilbiogeochem_nitrogenstate_summary
+
+ SUBROUTINE cnveg_carbonstate_summary(i,ps,pe,init)
+
+! !DESCRIPTION
+! summarizes vegetation C state varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ logical, intent(in) :: init
+
+ integer m
+
+ leafc(i) = sum(leafc_p(ps:pe) * pftfrac(ps:pe))
+ leafc_storage(i) = sum(leafc_storage_p(ps:pe) * pftfrac(ps:pe))
+ leafc_xfer(i) = sum(leafc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ frootc(i) = sum(frootc_p(ps:pe) * pftfrac(ps:pe))
+ frootc_storage(i) = sum(frootc_storage_p(ps:pe) * pftfrac(ps:pe))
+ frootc_xfer(i) = sum(frootc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ livestemc(i) = sum(livestemc_p(ps:pe) * pftfrac(ps:pe))
+ livestemc_storage(i) = sum(livestemc_storage_p(ps:pe) * pftfrac(ps:pe))
+ livestemc_xfer(i) = sum(livestemc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ deadstemc(i) = sum(deadstemc_p(ps:pe) * pftfrac(ps:pe))
+ deadstemc_storage(i) = sum(deadstemc_storage_p(ps:pe) * pftfrac(ps:pe))
+ deadstemc_xfer(i) = sum(deadstemc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ livecrootc(i) = sum(livecrootc_p(ps:pe) * pftfrac(ps:pe))
+ livecrootc_storage(i) = sum(livecrootc_storage_p(ps:pe) * pftfrac(ps:pe))
+ livecrootc_xfer(i) = sum(livecrootc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootc(i) = sum(deadcrootc_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootc_storage(i) = sum(deadcrootc_storage_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootc_xfer(i) = sum(deadcrootc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ xsmrpool(i) = sum(xsmrpool_p(ps:pe) * pftfrac(ps:pe))
+#ifdef CROP
+ grainc(i) = sum(grainc_p(ps:pe) * pftfrac(ps:pe))
+ grainc_storage(i) = sum(grainc_storage_p(ps:pe) * pftfrac(ps:pe))
+ grainc_xfer(i) = sum(grainc_xfer_p(ps:pe) * pftfrac(ps:pe))
+ cropseedc_deficit(i) = sum(cropseedc_deficit_p(ps:pe) * pftfrac(ps:pe))
+ cropprod1c(i) = sum(cropprod1c_p(ps:pe) * pftfrac(ps:pe))
+ cphase(i) = sum(cphase_p(ps:pe) * pftfrac(ps:pe))
+ hui(i) = hui_p(ps)
+ gddplant(i) = sum(gddplant_p(ps:pe) * pftfrac(ps:pe))
+ gddmaturity(i) = sum(gddmaturity_p(ps:pe) * pftfrac(ps:pe))
+ vf(i) = sum(vf_p(ps:pe) * pftfrac(ps:pe))
+
+ fertnitro_corn(i) = 0._r8
+ fertnitro_swheat(i) = 0._r8
+ fertnitro_wwheat(i) = 0._r8
+ fertnitro_soybean(i) = 0._r8
+ fertnitro_cotton(i) = 0._r8
+ fertnitro_rice1(i) = 0._r8
+ fertnitro_rice2(i) = 0._r8
+ fertnitro_sugarcane(i)= 0._r8
+
+ manunitro(i) = sum(manunitro_p(ps:pe) * pftfrac(ps:pe))
+
+#endif
+ IF(DEF_USE_DiagMatrix)THEN
+ leafcCap(i) = sum(leafcCap_p(ps:pe) * pftfrac(ps:pe))
+ leafc_storageCap(i) = sum(leafc_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ leafc_xferCap(i) = sum(leafc_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ frootcCap(i) = sum(frootcCap_p(ps:pe) * pftfrac(ps:pe))
+ frootc_storageCap(i) = sum(frootc_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ frootc_xferCap(i) = sum(frootc_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ livestemcCap(i) = sum(livestemcCap_p(ps:pe) * pftfrac(ps:pe))
+ livestemc_storageCap(i) = sum(livestemc_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ livestemc_xferCap(i) = sum(livestemc_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ deadstemcCap(i) = sum(deadstemcCap_p(ps:pe) * pftfrac(ps:pe))
+ deadstemc_storageCap(i) = sum(deadstemc_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ deadstemc_xferCap(i) = sum(deadstemc_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ livecrootcCap(i) = sum(livecrootcCap_p(ps:pe) * pftfrac(ps:pe))
+ livecrootc_storageCap(i) = sum(livecrootc_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ livecrootc_xferCap(i) = sum(livecrootc_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootcCap(i) = sum(deadcrootcCap_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootc_storageCap(i) = sum(deadcrootc_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootc_xferCap(i) = sum(deadcrootc_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ ENDIF
+ DO m = ps, pe
+ totvegc_p(m) = leafc_p(m) + frootc_p(m) + livestemc_p(m) &
+ + deadstemc_p(m) + livecrootc_p(m) + deadcrootc_p(m) &
+ + leafc_storage_p(m) + frootc_storage_p(m) + livestemc_storage_p(m) &
+ + deadstemc_storage_p(m) + livecrootc_storage_p(m) + deadcrootc_storage_p(m) &
+ + leafc_xfer_p(m) + frootc_xfer_p(m) + livestemc_xfer_p(m) &
+ + deadstemc_xfer_p(m) + livecrootc_xfer_p(m) + deadcrootc_xfer_p(m) &
+#ifdef CROP
+ + grainc_p(m) + grainc_storage_p(m) + grainc_xfer_p(m) &
+ + cropseedc_deficit_p(m) &
+#endif
+ + gresp_storage_p(m) + gresp_xfer_p(m) + xsmrpool_p(m) + cpool_p(m)
+
+#ifdef CROP
+ IF( pftclass(m) .eq. 17 .or. pftclass(m) .eq. 18 .or. pftclass(m) .eq. 63 .or. pftclass(m) .eq. 64)THEN
+ fertnitro_corn (i) = fertnitro_p (m)
+ irrig_method_corn (i) = irrig_method_p(m)
+ ELSE IF(pftclass(m) .eq. 19 .or. pftclass(m) .eq. 20)THEN
+ fertnitro_swheat (i) = fertnitro_p (m)
+ irrig_method_swheat(i) = irrig_method_p (m)
+ ELSE IF(pftclass(m) .eq. 21 .or. pftclass(m) .eq. 22)THEN
+ fertnitro_wwheat (i) = fertnitro_p (m)
+ irrig_method_wwheat (i) = irrig_method_p(m)
+ ELSE IF(pftclass(m) .eq. 23 .or. pftclass(m) .eq. 24 .or. pftclass(m) .eq. 77 .or. pftclass(m) .eq. 78)THEN
+ fertnitro_soybean (i) = fertnitro_p (m)
+ irrig_method_soybean (i) = irrig_method_p(m)
+ ELSE IF(pftclass(m) .eq. 41 .or. pftclass(m) .eq. 42)THEN
+ fertnitro_cotton (i) = fertnitro_p (m)
+ irrig_method_cotton (i) = irrig_method_p(m)
+ ELSE IF(pftclass(m) .eq. 61 .or. pftclass(m) .eq. 62)THEN
+ fertnitro_rice1 (i) = fertnitro_p (m)
+ fertnitro_rice2 (i) = fertnitro_p (m)
+ irrig_method_rice1 (i) = irrig_method_p(m)
+ irrig_method_rice2 (i) = irrig_method_p(m)
+ ELSE IF(pftclass(m) .eq. 67 .or. pftclass(m) .eq. 68)THEN
+ fertnitro_sugarcane (i) = fertnitro_p (m)
+ irrig_method_sugarcane(i) = irrig_method_p(m)
+ ENDIF
+#endif
+ ENDDO
+
+ IF(.not. init)THEN
+ leafc_enftemp (i) = 0._r8
+ leafc_enfboreal (i) = 0._r8
+ leafc_dnfboreal (i) = 0._r8
+ leafc_ebftrop (i) = 0._r8
+ leafc_ebftemp (i) = 0._r8
+ leafc_dbftrop (i) = 0._r8
+ leafc_dbftemp (i) = 0._r8
+ leafc_dbfboreal (i) = 0._r8
+ leafc_ebstemp (i) = 0._r8
+ leafc_dbstemp (i) = 0._r8
+ leafc_dbsboreal (i) = 0._r8
+ leafc_c3arcgrass (i) = 0._r8
+ leafc_c3grass (i) = 0._r8
+ leafc_c4grass (i) = 0._r8
+ lai_enftemp (i) = 0._r8
+ lai_enfboreal (i) = 0._r8
+ lai_dnfboreal (i) = 0._r8
+ lai_ebftrop (i) = 0._r8
+ lai_ebftemp (i) = 0._r8
+ lai_dbftrop (i) = 0._r8
+ lai_dbftemp (i) = 0._r8
+ lai_dbfboreal (i) = 0._r8
+ lai_ebstemp (i) = 0._r8
+ lai_dbstemp (i) = 0._r8
+ lai_dbsboreal (i) = 0._r8
+ lai_c3arcgrass (i) = 0._r8
+ lai_c3grass (i) = 0._r8
+ lai_c4grass (i) = 0._r8
+ DO m = ps, pe
+ IF(pftclass (m) .eq. 1)THEN
+ leafc_enftemp (i) = leafc_p(m)
+ lai_enftemp (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 2)THEN
+ leafc_enfboreal (i) = leafc_p(m)
+ lai_enfboreal (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 3)THEN
+ leafc_dnfboreal (i) = leafc_p(m)
+ lai_dnfboreal (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 4)THEN
+ leafc_ebftrop (i) = leafc_p(m)
+ lai_ebftrop (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 5)THEN
+ leafc_ebftemp (i) = leafc_p(m)
+ lai_ebftemp (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 6)THEN
+ leafc_dbftrop (i) = leafc_p(m)
+ lai_dbftrop (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 7)THEN
+ leafc_dbftemp (i) = leafc_p(m)
+ lai_dbftemp (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 8)THEN
+ leafc_dbfboreal (i) = leafc_p(m)
+ lai_dbfboreal (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 9)THEN
+ leafc_ebstemp (i) = leafc_p(m)
+ lai_ebstemp (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 10)THEN
+ leafc_dbstemp (i) = leafc_p(m)
+ lai_dbstemp (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 11)THEN
+ leafc_dbsboreal (i) = leafc_p(m)
+ lai_dbsboreal (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 12)THEN
+ leafc_c3arcgrass(i)= leafc_p(m)
+ lai_c3arcgrass (i)= lai_p(m)
+ ELSE IF(pftclass (m) .eq. 13)THEN
+ leafc_c3grass (i) = leafc_p(m)
+ lai_c3grass (i) = lai_p(m)
+ ELSE IF(pftclass (m) .eq. 14)THEN
+ leafc_c4grass (i) = leafc_p(m)
+ lai_c4grass (i) = lai_p(m)
+ ENDIF
+ ENDDO
+ ENDIF
+ totvegc(i) = sum(totvegc_p(ps:pe)*pftfrac(ps:pe))
+ ctrunc_veg(i) = sum(ctrunc_p(ps:pe) *pftfrac(ps:pe))
+ totcolc(i) = totvegc(i) + totcwdc(i) + totlitc(i) + totsomc(i) + ctrunc_veg(i) +ctrunc_soil(i)
+
+
+ END SUBROUTINE cnveg_carbonstate_summary
+
+ SUBROUTINE cnveg_nitrogenstate_summary(i,ps,pe)
+
+! !DESCRIPTION
+! summarizes vegetation N state varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+
+ integer m
+
+ leafn(i) = sum(leafn_p(ps:pe) * pftfrac(ps:pe))
+ leafn_storage(i) = sum(leafn_storage_p(ps:pe) * pftfrac(ps:pe))
+ leafn_xfer(i) = sum(leafn_xfer_p(ps:pe) * pftfrac(ps:pe))
+ frootn(i) = sum(frootn_p(ps:pe) * pftfrac(ps:pe))
+ frootn_storage(i) = sum(frootn_storage_p(ps:pe) * pftfrac(ps:pe))
+ frootn_xfer(i) = sum(frootn_xfer_p(ps:pe) * pftfrac(ps:pe))
+ livestemn(i) = sum(livestemn_p(ps:pe) * pftfrac(ps:pe))
+ livestemn_storage(i) = sum(livestemn_storage_p(ps:pe) * pftfrac(ps:pe))
+ livestemn_xfer(i) = sum(livestemn_xfer_p(ps:pe) * pftfrac(ps:pe))
+ deadstemn(i) = sum(deadstemn_p(ps:pe) * pftfrac(ps:pe))
+ deadstemn_storage(i) = sum(deadstemn_storage_p(ps:pe) * pftfrac(ps:pe))
+ deadstemn_xfer(i) = sum(deadstemn_xfer_p(ps:pe) * pftfrac(ps:pe))
+ livecrootn(i) = sum(livecrootn_p(ps:pe) * pftfrac(ps:pe))
+ livecrootn_storage(i) = sum(livecrootn_storage_p(ps:pe) * pftfrac(ps:pe))
+ livecrootn_xfer(i) = sum(livecrootn_xfer_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootn(i) = sum(deadcrootn_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootn_storage(i) = sum(deadcrootn_storage_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootn_xfer(i) = sum(deadcrootn_xfer_p(ps:pe) * pftfrac(ps:pe))
+#ifdef CROP
+ grainn(i) = sum(grainn_p(ps:pe) * pftfrac(ps:pe))
+ grainn_storage(i) = sum(grainn_storage_p(ps:pe) * pftfrac(ps:pe))
+ grainn_xfer(i) = sum(grainn_xfer_p(ps:pe) * pftfrac(ps:pe))
+#endif
+ retransn(i) = sum(retransn_p(ps:pe) * pftfrac(ps:pe))
+
+ IF(DEF_USE_DiagMatrix)THEN
+ leafnCap(i) = sum(leafnCap_p(ps:pe) * pftfrac(ps:pe))
+ leafn_storageCap(i) = sum(leafn_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ leafn_xferCap(i) = sum(leafn_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ frootnCap(i) = sum(frootnCap_p(ps:pe) * pftfrac(ps:pe))
+ frootn_storageCap(i) = sum(frootn_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ frootn_xferCap(i) = sum(frootn_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ livestemnCap(i) = sum(livestemnCap_p(ps:pe) * pftfrac(ps:pe))
+ livestemn_storageCap(i) = sum(livestemn_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ livestemn_xferCap(i) = sum(livestemn_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ deadstemnCap(i) = sum(deadstemnCap_p(ps:pe) * pftfrac(ps:pe))
+ deadstemn_storageCap(i) = sum(deadstemn_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ deadstemn_xferCap(i) = sum(deadstemn_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ livecrootnCap(i) = sum(livecrootnCap_p(ps:pe) * pftfrac(ps:pe))
+ livecrootn_storageCap(i) = sum(livecrootn_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ livecrootn_xferCap(i) = sum(livecrootn_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootnCap(i) = sum(deadcrootnCap_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootn_storageCap(i) = sum(deadcrootn_storageCap_p(ps:pe) * pftfrac(ps:pe))
+ deadcrootn_xferCap(i) = sum(deadcrootn_xferCap_p(ps:pe) * pftfrac(ps:pe))
+ ENDIF
+ DO m = ps, pe
+ totvegn_p(m) = leafn_p(m) + frootn_p(m) + livestemn_p(m) &
+ + deadstemn_p(m) + livecrootn_p(m) + deadcrootn_p(m) &
+ + leafn_storage_p(m) + frootn_storage_p(m) + livestemn_storage_p(m) &
+ + deadstemn_storage_p(m) + livecrootn_storage_p(m) + deadcrootn_storage_p(m) &
+ + leafn_xfer_p(m) + frootn_xfer_p(m) + livestemn_xfer_p(m) &
+ + deadstemn_xfer_p(m) + livecrootn_xfer_p(m) + deadcrootn_xfer_p(m) &
+#ifdef CROP
+ + grainn_p(m) + grainn_storage_p(m) + grainn_xfer_p(m) &
+ + cropseedn_deficit_p(m) &
+#endif
+ + npool_p(m) + retransn_p(m)
+ ENDDO
+
+ totvegn(i) = sum(totvegn_p(ps:pe)*pftfrac(ps:pe))
+ ntrunc_veg(i) = sum(ntrunc_p(ps:pe) *pftfrac(ps:pe))
+ totcoln(i) = totvegn(i) + totcwdn(i) + totlitn(i) + totsomn(i) + sminn(i) + ntrunc_veg(i) + ntrunc_soil(i)
+
+ END SUBROUTINE cnveg_nitrogenstate_summary
+
+ SUBROUTINE soilbiogeochem_carbonflux_summary(i,nl_soil,dz_soi,ndecomp_transitions,ndecomp_pools)
+
+! !DESCRIPTION
+! summarizes soil C flux varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+ integer, intent(in) :: ndecomp_transitions ! number of total transfers between soil and litter pools in the decomposition
+ integer, intent(in) :: ndecomp_pools ! number of total soil & litter pools in the decompositions
+
+ integer k,j,l
+
+ DO k = 1, ndecomp_transitions
+ DO j = 1, nl_soil
+ decomp_hr(i) = decomp_hr(i) &
+ + decomp_hr_vr(j,k,i) * dz_soi(j)
+ ENDDO
+ ENDDO
+
+ DO l = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ som_c_leached(i) = som_c_leached(i) + decomp_cpools_transport_tendency(j,l,i) * dz_soi(j)
+ ENDDO
+ ENDDO
+
+
+ END SUBROUTINE soilbiogeochem_carbonflux_summary
+
+ SUBROUTINE soilbiogeochem_nitrogenflux_summary(i,nl_soil,dz_soi,ndecomp_transitions,ndecomp_pools)
+
+! !DESCRIPTION
+! summarizes soil N flux varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+ integer, intent(in) :: ndecomp_transitions ! number of total transfers between soil and litter pools in the decomposition
+ integer, intent(in) :: ndecomp_pools ! number of total soil & litter pools in the decompositions
+
+ integer j,l,k
+
+ DO l = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ som_n_leached(i) = som_n_leached(i) + decomp_npools_transport_tendency(j,l,i) * dz_soi(j)
+ ENDDO
+ ENDDO
+
+ DO j = 1, nl_soil
+ supplement_to_sminn(i) = supplement_to_sminn(i) + supplement_to_sminn_vr(j,i) * dz_soi(j)
+ smin_no3_leached(i) = smin_no3_leached(i) + smin_no3_leached_vr(j,i) * dz_soi(j)
+ smin_no3_runoff(i) = smin_no3_runoff(i) + smin_no3_runoff_vr(j,i) * dz_soi(j)
+ sminn_leached(i) = sminn_leached(i) + sminn_leached_vr(j,i) * dz_soi(j)
+ f_n2o_nit(i) = f_n2o_nit(i) + f_n2o_nit_vr(j,i) * dz_soi(j)
+ IF(DEF_USE_NITRIF)THEN
+ denit(i) = denit(i) + f_denit_vr(j,i) * dz_soi(j)
+ ELSE
+ denit(i) = denit(i) + sminn_to_denit_excess_vr(j,i) * dz_soi(j)
+ ENDIF
+
+ IF(.not. DEF_USE_NITRIF)THEN
+ DO k = 1, ndecomp_transitions
+ denit(i) = denit(i) + sminn_to_denit_decomp_vr(j,k,i) * dz_soi(j)
+ ENDDO
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE soilbiogeochem_nitrogenflux_summary
+
+ SUBROUTINE cnveg_carbonflux_summary(i,ps,pe,deltim)
+
+! !DESCRIPTION
+! summarizes vegetationi C flux varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8) :: ar_p
+
+ integer m
+ real(r8) nfixlags
+
+ gpp(i) = sum(psn_to_cpool_p(ps:pe) * pftfrac(ps:pe))
+ downreg(i) = sum(downreg_p(ps:pe) * pftfrac(ps:pe))
+ ar (i) = sum((leaf_mr_p(ps:pe) + froot_mr_p(ps:pe) &
+ + livestem_mr_p(ps:pe) + livecroot_mr_p(ps:pe) &
+ + cpool_leaf_gr_p(ps:pe) + cpool_froot_gr_p(ps:pe) &
+ + cpool_livestem_gr_p(ps:pe) + cpool_deadstem_gr_p(ps:pe) &
+ + cpool_livecroot_gr_p(ps:pe) + cpool_deadcroot_gr_p(ps:pe) &
+ + transfer_leaf_gr_p(ps:pe) + transfer_froot_gr_p(ps:pe) &
+ + transfer_livestem_gr_p(ps:pe) + transfer_deadstem_gr_p(ps:pe) &
+ + transfer_livecroot_gr_p(ps:pe) + transfer_deadcroot_gr_p(ps:pe) &
+ + cpool_leaf_storage_gr_p(ps:pe) + cpool_froot_storage_gr_p(ps:pe) &
+ + cpool_livestem_storage_gr_p(ps:pe) + cpool_deadstem_storage_gr_p(ps:pe) &
+ + cpool_livecroot_storage_gr_p(ps:pe) + cpool_deadcroot_storage_gr_p(ps:pe) &
+ + grain_mr_p(ps:pe) + xsmrpool_to_atm_p(ps:pe) &
+ + cpool_grain_gr_p(ps:pe) + transfer_grain_gr_p(ps:pe) &
+ + cpool_grain_storage_gr_p(ps:pe)) * pftfrac(ps:pe))
+ gpp_enftemp (i) = 0._r8
+ gpp_enfboreal (i) = 0._r8
+ gpp_dnfboreal (i) = 0._r8
+ gpp_ebftrop (i) = 0._r8
+ gpp_ebftemp (i) = 0._r8
+ gpp_dbftrop (i) = 0._r8
+ gpp_dbftemp (i) = 0._r8
+ gpp_dbfboreal (i) = 0._r8
+ gpp_ebstemp (i) = 0._r8
+ gpp_dbstemp (i) = 0._r8
+ gpp_dbsboreal (i) = 0._r8
+ gpp_c3arcgrass (i) = 0._r8
+ gpp_c3grass (i) = 0._r8
+ gpp_c4grass (i) = 0._r8
+ npp_enftemp (i) = 0._r8
+ npp_enfboreal (i) = 0._r8
+ npp_dnfboreal (i) = 0._r8
+ npp_ebftrop (i) = 0._r8
+ npp_ebftemp (i) = 0._r8
+ npp_dbftrop (i) = 0._r8
+ npp_dbftemp (i) = 0._r8
+ npp_dbfboreal (i) = 0._r8
+ npp_ebstemp (i) = 0._r8
+ npp_dbstemp (i) = 0._r8
+ npp_dbsboreal (i) = 0._r8
+ npp_c3arcgrass (i) = 0._r8
+ npp_c3grass (i) = 0._r8
+ npp_c4grass (i) = 0._r8
+ npptoleafc_enftemp (i) = 0._r8
+ npptoleafc_enfboreal (i) = 0._r8
+ npptoleafc_dnfboreal (i) = 0._r8
+ npptoleafc_ebftrop (i) = 0._r8
+ npptoleafc_ebftemp (i) = 0._r8
+ npptoleafc_dbftrop (i) = 0._r8
+ npptoleafc_dbftemp (i) = 0._r8
+ npptoleafc_dbfboreal (i) = 0._r8
+ npptoleafc_ebstemp (i) = 0._r8
+ npptoleafc_dbstemp (i) = 0._r8
+ npptoleafc_dbsboreal (i) = 0._r8
+ npptoleafc_c3arcgrass (i) = 0._r8
+ npptoleafc_c3grass (i) = 0._r8
+ npptoleafc_c4grass (i) = 0._r8
+ DO m = ps, pe
+ ar_p = (leaf_mr_p(m) + froot_mr_p(m) &
+ + livestem_mr_p(m) + livecroot_mr_p(m) &
+ + cpool_leaf_gr_p(m) + cpool_froot_gr_p(m) &
+ + cpool_livestem_gr_p(m) + cpool_deadstem_gr_p(m) &
+ + cpool_livecroot_gr_p(m) + cpool_deadcroot_gr_p(m) &
+ + transfer_leaf_gr_p(m) + transfer_froot_gr_p(m) &
+ + transfer_livestem_gr_p(m) + transfer_deadstem_gr_p(m) &
+ + transfer_livecroot_gr_p(m) + transfer_deadcroot_gr_p(m) &
+ + cpool_leaf_storage_gr_p(m) + cpool_froot_storage_gr_p(m) &
+ + cpool_livestem_storage_gr_p(m) + cpool_deadstem_storage_gr_p(m) &
+ + cpool_livecroot_storage_gr_p(m) + cpool_deadcroot_storage_gr_p(m) &
+ + grain_mr_p(m) + xsmrpool_to_atm_p(m) &
+ + cpool_grain_gr_p(m) + transfer_grain_gr_p(m) &
+ + cpool_grain_storage_gr_p(m))
+ IF(pftclass (m) .eq. 1)THEN
+ gpp_enftemp (i) = psn_to_cpool_p(m)
+ npp_enftemp (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_enftemp (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 2)THEN
+ gpp_enfboreal (i) = psn_to_cpool_p(m)
+ npp_enfboreal (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_enfboreal (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 3)THEN
+ gpp_dnfboreal (i) = psn_to_cpool_p(m)
+ npp_dnfboreal (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_dnfboreal (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 4)THEN
+ gpp_ebftrop (i) = psn_to_cpool_p(m)
+ npp_ebftrop (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_ebftrop (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 5)THEN
+ gpp_ebftemp (i) = psn_to_cpool_p(m)
+ npp_ebftemp (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_ebftemp (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 6)THEN
+ gpp_dbftrop (i) = psn_to_cpool_p(m)
+ npp_dbftrop (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_dbftrop (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 7)THEN
+ gpp_dbftemp (i) = psn_to_cpool_p(m)
+ npp_dbftemp (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_dbftemp (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 8)THEN
+ gpp_dbfboreal (i) = psn_to_cpool_p(m)
+ npp_dbfboreal (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_dbfboreal (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 9)THEN
+ gpp_ebstemp (i) = psn_to_cpool_p(m)
+ npp_ebstemp (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_ebstemp (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 10)THEN
+ gpp_dbstemp (i) = psn_to_cpool_p(m)
+ npp_dbstemp (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_dbstemp (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 11)THEN
+ gpp_dbsboreal (i) = psn_to_cpool_p(m)
+ npp_dbsboreal (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_dbsboreal (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 12)THEN
+ gpp_c3arcgrass (i) = psn_to_cpool_p(m)
+ npp_c3arcgrass (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_c3arcgrass(i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 13)THEN
+ gpp_c3grass (i) = psn_to_cpool_p(m)
+ npp_c3grass (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_c3grass (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ELSE IF(pftclass (m) .eq. 14)THEN
+ gpp_c4grass (i) = psn_to_cpool_p(m)
+ npp_c4grass (i) = psn_to_cpool_p(m) - ar_p
+ npptoleafc_c4grass (i) = cpool_to_leafc_p(m) + cpool_to_leafc_storage_p(m)
+ ENDIF
+ ENDDO
+
+
+#ifdef FUN
+ ar(i) = ar(i) + sum(soil_change_p(ps:pe) * pftfrac(ps:pe))
+#endif
+ er(i) = ar(i) + decomp_hr(i)
+#ifdef CROP
+ IF(patchclass(i) .eq. 12)THEN
+ IF(ps .ne. pe)THEN
+ write(*,*) 'Error: crop patch CONTAINS multiple pfts:',p_iam_glb,'i=',i,'ps',ps,'does not equal to pe',pe
+ CALL abort
+ ELSE
+ cropprod1c_loss (i) = cropprod1c_loss_p(ps)
+ grainc_to_cropprodc (i) = grainc_to_food_p (ps)
+ grainc_to_seed (i) = grainc_to_seed_p (ps)
+ plantdate (i) = plantdate_p (ps)
+ ENDIF
+ ELSE
+ cropprod1c_loss (i) = 0._r8
+ grainc_to_cropprodc (i) = 0._r8
+ grainc_to_seed (i) = 0._r8
+ ENDIF
+#endif
+
+ !fire module is not activated yet.
+ DO m = ps, pe
+ fire_closs_p(m) = m_leafc_to_fire_p(m) &
+ + m_leafc_storage_to_fire_p(m) &
+ + m_leafc_xfer_to_fire_p(m) &
+ + m_frootc_to_fire_p(m) &
+ + m_frootc_storage_to_fire_p(m) &
+ + m_frootc_xfer_to_fire_p(m) &
+ + m_livestemc_to_fire_p(m) &
+ + m_livestemc_storage_to_fire_p(m) &
+ + m_livestemc_xfer_to_fire_p(m) &
+ + m_deadstemc_to_fire_p(m) &
+ + m_deadstemc_storage_to_fire_p(m) &
+ + m_deadstemc_xfer_to_fire_p(m) &
+ + m_livecrootc_to_fire_p(m) &
+ + m_livecrootc_storage_to_fire_p(m) &
+ + m_livecrootc_xfer_to_fire_p(m) &
+ + m_deadcrootc_to_fire_p(m) &
+ + m_deadcrootc_storage_to_fire_p(m) &
+ + m_deadcrootc_xfer_to_fire_p(m) &
+ + m_gresp_storage_to_fire_p(m) &
+ + m_gresp_xfer_to_fire_p(m)
+ ENDDO
+
+ fire_closs(i) = sum(fire_closs_p(ps:pe) * pftfrac(ps:pe))
+ hrv_xsmrpool_to_atm(i) = sum(hrv_xsmrpool_to_atm_p(ps:pe) * pftfrac(ps:pe))
+
+ nfixlags = nfix_timeconst * 86400._r8
+ IF(lag_npp(i) /= spval)THEN
+ lag_npp(i) = lag_npp(i) * exp(-deltim/nfixlags) + &
+ (gpp(i) - ar(i)) * (1._r8 - exp(-deltim/nfixlags))
+ ELSE
+ lag_npp(i) = gpp(i) - ar(i)
+ ENDIF
+
+ END SUBROUTINE cnveg_carbonflux_summary
+
+ SUBROUTINE cnveg_nitrogenflux_summary(i,ps,pe)
+
+! !DESCRIPTION
+! summarizes vegetationi N flux varaibles.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! end pft index
+
+#ifdef CROP
+ IF(patchclass(i) .eq. 12)THEN
+ IF(ps .ne. pe)THEN
+ write(*,*) 'Error: crop patch contains multiple pfts:',p_iam_glb,'i=',i,'ps',ps,'does not equal to pe',pe
+ CALL abort
+ ELSE
+ grainn_to_cropprodn (i) = grainn_to_food_p (ps)
+ ENDIF
+ ELSE
+ grainn_to_cropprodn (i) = 0._r8
+ ENDIF
+#endif
+ END SUBROUTINE cnveg_nitrogenflux_summary
+
+END MODULE MOD_BGC_CNSummary
+
+
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNZeroFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNZeroFluxes.F90
new file mode 100644
index 0000000000..a56282a884
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_CNZeroFluxes.F90
@@ -0,0 +1,838 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_CNZeroFluxes
+
+!----------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This MODULE reset flux variable to 0 at begining of each time step to avoid miscalculating from last step.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_NITRIF
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ m_leafc_to_litter_p , &
+ m_frootc_to_litter_p , &
+ m_leafc_storage_to_litter_p , &
+ m_frootc_storage_to_litter_p , &
+ m_livestemc_storage_to_litter_p , &
+ m_deadstemc_storage_to_litter_p , &
+ m_livecrootc_storage_to_litter_p , &
+ m_deadcrootc_storage_to_litter_p , &
+ m_leafc_xfer_to_litter_p , &
+ m_frootc_xfer_to_litter_p , &
+ m_livestemc_xfer_to_litter_p , &
+ m_deadstemc_xfer_to_litter_p , &
+ m_livecrootc_xfer_to_litter_p , &
+ m_deadcrootc_xfer_to_litter_p , &
+ m_livestemc_to_litter_p , &
+ m_deadstemc_to_litter_p , &
+ m_livecrootc_to_litter_p , &
+ m_deadcrootc_to_litter_p , &
+ m_gresp_storage_to_litter_p , &
+ m_gresp_xfer_to_litter_p , &
+ m_leafc_to_fire_p , &
+ m_leafc_storage_to_fire_p , &
+ m_leafc_xfer_to_fire_p , &
+ m_livestemc_to_fire_p , &
+ m_livestemc_storage_to_fire_p , &
+ m_livestemc_xfer_to_fire_p , &
+ m_deadstemc_to_fire_p , &
+ m_deadstemc_storage_to_fire_p , &
+ m_deadstemc_xfer_to_fire_p , &
+ m_frootc_to_fire_p , &
+ m_frootc_storage_to_fire_p , &
+ m_frootc_xfer_to_fire_p , &
+ m_livecrootc_to_fire_p , &
+ m_livecrootc_storage_to_fire_p , &
+ m_livecrootc_xfer_to_fire_p , &
+ m_deadcrootc_to_fire_p , &
+ m_deadcrootc_storage_to_fire_p , &
+ m_deadcrootc_xfer_to_fire_p , &
+ m_gresp_storage_to_fire_p , &
+ m_gresp_xfer_to_fire_p , &
+
+ m_leafc_to_litter_fire_p , &
+ m_leafc_storage_to_litter_fire_p , &
+ m_leafc_xfer_to_litter_fire_p , &
+ m_livestemc_to_litter_fire_p , &
+ m_livestemc_storage_to_litter_fire_p , &
+ m_livestemc_xfer_to_litter_fire_p , &
+ m_livestemc_to_deadstemc_fire_p , &
+ m_deadstemc_to_litter_fire_p , &
+ m_deadstemc_storage_to_litter_fire_p , &
+ m_deadstemc_xfer_to_litter_fire_p , &
+ m_frootc_to_litter_fire_p , &
+ m_frootc_storage_to_litter_fire_p , &
+ m_frootc_xfer_to_litter_fire_p , &
+ m_livecrootc_to_litter_fire_p , &
+ m_livecrootc_storage_to_litter_fire_p, &
+ m_livecrootc_xfer_to_litter_fire_p , &
+ m_livecrootc_to_deadcrootc_fire_p , &
+ m_deadcrootc_to_litter_fire_p , &
+ m_deadcrootc_storage_to_litter_fire_p, &
+ m_deadcrootc_xfer_to_litter_fire_p , &
+ m_gresp_storage_to_litter_fire_p , &
+ m_gresp_xfer_to_litter_fire_p , &
+
+ leafc_xfer_to_leafc_p , &
+ frootc_xfer_to_frootc_p , &
+ livestemc_xfer_to_livestemc_p , &
+ deadstemc_xfer_to_deadstemc_p , &
+ livecrootc_xfer_to_livecrootc_p , &
+ deadcrootc_xfer_to_deadcrootc_p , &
+ leafc_to_litter_p , &
+ frootc_to_litter_p , &
+
+ leaf_mr_p , &
+ froot_mr_p , &
+ livestem_mr_p , &
+ livecroot_mr_p , &
+ grain_mr_p , &
+ leaf_curmr_p , &
+ froot_curmr_p , &
+ livestem_curmr_p , &
+ livecroot_curmr_p , &
+ grain_curmr_p , &
+ leaf_xsmr_p , &
+ froot_xsmr_p , &
+ livestem_xsmr_p , &
+ livecroot_xsmr_p , &
+ grain_xsmr_p , &
+ psn_to_cpool_p , &
+ cpool_to_xsmrpool_p , &
+ cpool_to_leafc_p , &
+ cpool_to_leafc_storage_p , &
+ cpool_to_frootc_p , &
+ cpool_to_frootc_storage_p , &
+ cpool_to_livestemc_p , &
+ cpool_to_livestemc_storage_p , &
+ cpool_to_deadstemc_p , &
+ cpool_to_deadstemc_storage_p , &
+ cpool_to_livecrootc_p , &
+ cpool_to_livecrootc_storage_p , &
+ cpool_to_deadcrootc_p , &
+ cpool_to_deadcrootc_storage_p , &
+ cpool_to_gresp_storage_p , &
+ cpool_leaf_gr_p , &
+ cpool_leaf_storage_gr_p , &
+ transfer_leaf_gr_p , &
+ cpool_froot_gr_p , &
+ cpool_froot_storage_gr_p , &
+ transfer_froot_gr_p , &
+ cpool_livestem_gr_p , &
+ cpool_livestem_storage_gr_p , &
+ transfer_livestem_gr_p , &
+ cpool_deadstem_gr_p , &
+ cpool_deadstem_storage_gr_p , &
+ transfer_deadstem_gr_p , &
+ cpool_livecroot_gr_p , &
+ cpool_livecroot_storage_gr_p , &
+ transfer_livecroot_gr_p , &
+ cpool_deadcroot_gr_p , &
+ cpool_deadcroot_storage_gr_p , &
+ transfer_deadcroot_gr_p , &
+ leafc_storage_to_xfer_p , &
+ frootc_storage_to_xfer_p , &
+ livestemc_storage_to_xfer_p , &
+ deadstemc_storage_to_xfer_p , &
+ livecrootc_storage_to_xfer_p , &
+ deadcrootc_storage_to_xfer_p , &
+ gresp_storage_to_xfer_p , &
+ livestemc_to_deadstemc_p , &
+ livecrootc_to_deadcrootc_p , &
+ crop_seedc_to_leaf_p , &
+
+ hrv_xsmrpool_to_atm_p , &
+
+ xsmrpool_to_atm_p , &
+ livestemc_to_litter_p , &
+ grainc_to_food_p , &
+ grainc_to_seed_p , &
+ grainc_xfer_to_grainc_p , &
+ cpool_to_grainc_p , &
+ cpool_to_grainc_storage_p , &
+ cpool_grain_gr_p , &
+ cpool_grain_storage_gr_p , &
+ transfer_grain_gr_p , &
+ grainc_storage_to_xfer_p , &
+
+ gpp_p, &
+
+ m_leafn_to_litter_p , &
+ m_frootn_to_litter_p , &
+ m_leafn_storage_to_litter_p , &
+ m_frootn_storage_to_litter_p , &
+ m_livestemn_storage_to_litter_p , &
+ m_deadstemn_storage_to_litter_p , &
+ m_livecrootn_storage_to_litter_p , &
+ m_deadcrootn_storage_to_litter_p , &
+ m_leafn_xfer_to_litter_p , &
+ m_frootn_xfer_to_litter_p , &
+ m_livestemn_xfer_to_litter_p , &
+ m_deadstemn_xfer_to_litter_p , &
+ m_livecrootn_xfer_to_litter_p , &
+ m_deadcrootn_xfer_to_litter_p , &
+ m_livestemn_to_litter_p , &
+ m_deadstemn_to_litter_p , &
+ m_livecrootn_to_litter_p , &
+ m_deadcrootn_to_litter_p , &
+ m_retransn_to_litter_p , &
+
+ m_leafn_to_fire_p , &
+ m_leafn_storage_to_fire_p , &
+ m_leafn_xfer_to_fire_p , &
+ m_livestemn_to_fire_p , &
+ m_livestemn_storage_to_fire_p , &
+ m_livestemn_xfer_to_fire_p , &
+ m_deadstemn_to_fire_p , &
+ m_deadstemn_storage_to_fire_p , &
+ m_deadstemn_xfer_to_fire_p , &
+ m_frootn_to_fire_p , &
+ m_frootn_storage_to_fire_p , &
+ m_frootn_xfer_to_fire_p , &
+ m_livecrootn_to_fire_p , &
+ m_livecrootn_storage_to_fire_p , &
+ m_livecrootn_xfer_to_fire_p , &
+ m_deadcrootn_to_fire_p , &
+ m_deadcrootn_storage_to_fire_p , &
+ m_deadcrootn_xfer_to_fire_p , &
+ m_retransn_to_fire_p , &
+
+ m_leafn_to_litter_fire_p , &
+ m_leafn_storage_to_litter_fire_p , &
+ m_leafn_xfer_to_litter_fire_p , &
+ m_livestemn_to_litter_fire_p , &
+ m_livestemn_storage_to_litter_fire_p , &
+ m_livestemn_xfer_to_litter_fire_p , &
+ m_livestemn_to_deadstemn_fire_p , &
+ m_deadstemn_to_litter_fire_p , &
+ m_deadstemn_storage_to_litter_fire_p , &
+ m_deadstemn_xfer_to_litter_fire_p , &
+ m_frootn_to_litter_fire_p , &
+ m_frootn_storage_to_litter_fire_p , &
+ m_frootn_xfer_to_litter_fire_p , &
+ m_livecrootn_to_litter_fire_p , &
+ m_livecrootn_storage_to_litter_fire_p, &
+ m_livecrootn_xfer_to_litter_fire_p , &
+ m_livecrootn_to_deadcrootn_fire_p , &
+ m_deadcrootn_to_litter_fire_p , &
+ m_deadcrootn_storage_to_litter_fire_p, &
+ m_deadcrootn_xfer_to_litter_fire_p , &
+ m_retransn_to_litter_fire_p , &
+
+ leafn_xfer_to_leafn_p , &
+ frootn_xfer_to_frootn_p , &
+ livestemn_xfer_to_livestemn_p , &
+ deadstemn_xfer_to_deadstemn_p , &
+ livecrootn_xfer_to_livecrootn_p , &
+ deadcrootn_xfer_to_deadcrootn_p , &
+ leafn_to_litter_p , &
+ leafn_to_retransn_p , &
+ frootn_to_litter_p , &
+ retransn_to_npool_p , &
+ free_retransn_to_npool_p , &
+ sminn_to_npool_p , &
+ npool_to_leafn_p , &
+ npool_to_leafn_storage_p , &
+ npool_to_frootn_p , &
+ npool_to_frootn_storage_p , &
+ npool_to_livestemn_p , &
+ npool_to_livestemn_storage_p , &
+ npool_to_deadstemn_p , &
+ npool_to_deadstemn_storage_p , &
+ npool_to_livecrootn_p , &
+ npool_to_livecrootn_storage_p , &
+ npool_to_deadcrootn_p , &
+ npool_to_deadcrootn_storage_p , &
+ leafn_storage_to_xfer_p , &
+ frootn_storage_to_xfer_p , &
+ livestemn_storage_to_xfer_p , &
+ deadstemn_storage_to_xfer_p , &
+ livecrootn_storage_to_xfer_p , &
+ deadcrootn_storage_to_xfer_p , &
+ livestemn_to_deadstemn_p , &
+ livestemn_to_retransn_p , &
+ livecrootn_to_deadcrootn_p , &
+ livecrootn_to_retransn_p , &
+
+ crop_seedn_to_leaf_p , &
+
+ livestemn_to_litter_p , &
+ grainn_to_food_p , &
+ grainn_to_seed_p , &
+ grainn_xfer_to_grainn_p , &
+ npool_to_grainn_p , &
+ npool_to_grainn_storage_p , &
+ grainn_storage_to_xfer_p , &
+ frootn_to_retransn_p , &
+
+ fire_closs_p , &
+ fire_nloss_p , &
+ wood_harvestc_p , &
+ wood_harvestn_p , &
+ grainc_to_cropprodc_p , &
+ grainn_to_cropprodn_p , &
+ soyfixn_p
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+
+ ! phenologgy
+ phenology_to_met_c , &
+ phenology_to_cel_c , &
+ phenology_to_lig_c , &
+
+ ! gap mortality
+ gap_mortality_to_met_c , &
+ gap_mortality_to_cel_c , &
+ gap_mortality_to_lig_c , &
+ gap_mortality_to_cwdc , &
+
+ ! fire
+ fire_mortality_to_cwdc , &
+ fire_mortality_to_met_c , &
+ fire_mortality_to_cel_c , &
+ fire_mortality_to_lig_c , &
+
+ m_decomp_cpools_to_fire_vr , &
+
+ ! phenologgy
+ phenology_to_met_n , &
+ phenology_to_cel_n , &
+ phenology_to_lig_n , &
+
+ ! gap mortality
+ gap_mortality_to_met_n , &
+ gap_mortality_to_cel_n , &
+ gap_mortality_to_lig_n , &
+ gap_mortality_to_cwdn , &
+
+ ! fire
+ fire_mortality_to_cwdn , &
+ fire_mortality_to_met_n , &
+ fire_mortality_to_cel_n , &
+ fire_mortality_to_lig_n , &
+
+ m_decomp_npools_to_fire_vr , &
+
+ fire_closs , &
+ fire_nloss , &
+ wood_harvestc , &
+ wood_harvestn , &
+ grainc_to_cropprodc , &
+ grainn_to_cropprodn , &
+
+ decomp_hr , &
+ decomp_hr_vr , &
+ decomp_ctransfer_vr , &
+
+ decomp_cpools_transport_tendency , &
+ decomp_cpools_sourcesink , &
+
+ somc_fire , &
+ som_c_leached , &
+
+ sminn_to_denit_excess_vr , &
+ sminn_leached_vr , &
+ sminn_to_plant_fun_vr , &
+
+ f_nit_vr , &
+ f_denit_vr , &
+ smin_no3_leached_vr , &
+ smin_no3_runoff_vr , &
+ n2_n2o_ratio_denit_vr , &
+ pot_f_nit_vr , &
+ pot_f_denit_vr , &
+ actual_immob_no3_vr , &
+ actual_immob_nh4_vr , &
+ smin_no3_to_plant_vr , &
+ smin_nh4_to_plant_vr , &
+ f_n2o_denit_vr , &
+ f_n2o_nit_vr , &
+
+ potential_immob_vr , &
+ actual_immob_vr , &
+ sminn_to_plant , &
+ sminn_to_plant_vr , &
+ supplement_to_sminn_vr , &
+ gross_nmin_vr , &
+ net_nmin_vr , &
+ sminn_to_plant_fun_no3_vr , &
+ sminn_to_plant_fun_nh4_vr , &
+
+ nfix_to_sminn , &
+ ffix_to_sminn , &
+ fert_to_sminn , &
+ soyfixn_to_sminn , &
+ sminn_to_plant , &
+ supplement_to_sminn , &
+ gross_nmin , &
+ net_nmin , &
+ denit , &
+ f_n2o_nit , &
+ smin_no3_leached , &
+ smin_no3_runoff , &
+ sminn_leached , &
+ som_n_leached , &
+
+ decomp_npools_transport_tendency , &
+
+ decomp_ntransfer_vr , &
+ decomp_sminn_flux_vr , &
+ sminn_to_denit_decomp_vr , &
+
+ decomp_npools_sourcesink
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ decomp_k
+
+ IMPLICIT NONE
+
+ PUBLIC CNZeroFluxes
+
+CONTAINS
+
+ SUBROUTINE CNZeroFluxes (i,ps,pe,nl_soil,ndecomp_pools,ndecomp_transitions)
+
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! end pft index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ integer, intent(in) :: ndecomp_pools ! number of total soil & litter pools in the decompositions
+ integer, intent(in) :: ndecomp_transitions ! number of total transfers between soil and litter pools in the decomposition
+
+ integer j,k, m
+
+ DO m = ps , pe
+ ! CNVegCarbonFluxes set zero
+ m_leafc_to_litter_p(m) = 0._r8
+ m_frootc_to_litter_p(m) = 0._r8
+ m_leafc_storage_to_litter_p(m) = 0._r8
+ m_frootc_storage_to_litter_p(m) = 0._r8
+ m_livestemc_storage_to_litter_p(m) = 0._r8
+ m_deadstemc_storage_to_litter_p(m) = 0._r8
+ m_livecrootc_storage_to_litter_p(m) = 0._r8
+ m_deadcrootc_storage_to_litter_p(m) = 0._r8
+ m_leafc_xfer_to_litter_p(m) = 0._r8
+ m_frootc_xfer_to_litter_p(m) = 0._r8
+ m_livestemc_xfer_to_litter_p(m) = 0._r8
+ m_deadstemc_xfer_to_litter_p(m) = 0._r8
+ m_livecrootc_xfer_to_litter_p(m) = 0._r8
+ m_deadcrootc_xfer_to_litter_p(m) = 0._r8
+ m_livestemc_to_litter_p(m) = 0._r8
+ m_deadstemc_to_litter_p(m) = 0._r8
+ m_livecrootc_to_litter_p(m) = 0._r8
+ m_deadcrootc_to_litter_p(m) = 0._r8
+ m_gresp_storage_to_litter_p(m) = 0._r8
+ m_gresp_xfer_to_litter_p(m) = 0._r8
+ m_leafc_to_fire_p(m) = 0._r8
+ m_leafc_storage_to_fire_p(m) = 0._r8
+ m_leafc_xfer_to_fire_p(m) = 0._r8
+ m_livestemc_to_fire_p(m) = 0._r8
+ m_livestemc_storage_to_fire_p(m) = 0._r8
+ m_livestemc_xfer_to_fire_p(m) = 0._r8
+ m_deadstemc_to_fire_p(m) = 0._r8
+ m_deadstemc_storage_to_fire_p(m) = 0._r8
+ m_deadstemc_xfer_to_fire_p(m) = 0._r8
+ m_frootc_to_fire_p(m) = 0._r8
+ m_frootc_storage_to_fire_p(m) = 0._r8
+ m_frootc_xfer_to_fire_p(m) = 0._r8
+ m_livecrootc_to_fire_p(m) = 0._r8
+ m_livecrootc_storage_to_fire_p(m) = 0._r8
+ m_livecrootc_xfer_to_fire_p(m) = 0._r8
+ m_deadcrootc_to_fire_p(m) = 0._r8
+ m_deadcrootc_storage_to_fire_p(m) = 0._r8
+ m_deadcrootc_xfer_to_fire_p(m) = 0._r8
+ m_gresp_storage_to_fire_p(m) = 0._r8
+ m_gresp_xfer_to_fire_p(m) = 0._r8
+
+ m_leafc_to_litter_fire_p(m) = 0._r8
+ m_leafc_storage_to_litter_fire_p(m) = 0._r8
+ m_leafc_xfer_to_litter_fire_p(m) = 0._r8
+ m_livestemc_to_litter_fire_p(m) = 0._r8
+ m_livestemc_storage_to_litter_fire_p(m) = 0._r8
+ m_livestemc_xfer_to_litter_fire_p(m) = 0._r8
+ m_livestemc_to_deadstemc_fire_p(m) = 0._r8
+ m_deadstemc_to_litter_fire_p(m) = 0._r8
+ m_deadstemc_storage_to_litter_fire_p(m) = 0._r8
+ m_deadstemc_xfer_to_litter_fire_p(m) = 0._r8
+ m_frootc_to_litter_fire_p(m) = 0._r8
+ m_frootc_storage_to_litter_fire_p(m) = 0._r8
+ m_frootc_xfer_to_litter_fire_p(m) = 0._r8
+ m_livecrootc_to_litter_fire_p(m) = 0._r8
+ m_livecrootc_storage_to_litter_fire_p(m) = 0._r8
+ m_livecrootc_xfer_to_litter_fire_p(m) = 0._r8
+ m_livecrootc_to_deadcrootc_fire_p(m) = 0._r8
+ m_deadcrootc_to_litter_fire_p(m) = 0._r8
+ m_deadcrootc_storage_to_litter_fire_p(m) = 0._r8
+ m_deadcrootc_xfer_to_litter_fire_p(m) = 0._r8
+ m_gresp_storage_to_litter_fire_p(m) = 0._r8
+ m_gresp_xfer_to_litter_fire_p(m) = 0._r8
+ leafc_xfer_to_leafc_p(m) = 0._r8
+ frootc_xfer_to_frootc_p(m) = 0._r8
+ livestemc_xfer_to_livestemc_p(m) = 0._r8
+ deadstemc_xfer_to_deadstemc_p(m) = 0._r8
+ livecrootc_xfer_to_livecrootc_p(m) = 0._r8
+ deadcrootc_xfer_to_deadcrootc_p(m) = 0._r8
+ leafc_to_litter_p(m) = 0._r8
+ frootc_to_litter_p(m) = 0._r8
+ leaf_mr_p(m) = 0._r8
+ froot_mr_p(m) = 0._r8
+ livestem_mr_p(m) = 0._r8
+ livecroot_mr_p(m) = 0._r8
+ grain_mr_p(m) = 0._r8
+ leaf_curmr_p(m) = 0._r8
+ froot_curmr_p(m) = 0._r8
+ livestem_curmr_p(m) = 0._r8
+ livecroot_curmr_p(m) = 0._r8
+ grain_curmr_p(m) = 0._r8
+ leaf_xsmr_p(m) = 0._r8
+ froot_xsmr_p(m) = 0._r8
+ livestem_xsmr_p(m) = 0._r8
+ livecroot_xsmr_p(m) = 0._r8
+ grain_xsmr_p(m) = 0._r8
+ psn_to_cpool_p(m) = 0._r8
+ cpool_to_xsmrpool_p(m) = 0._r8
+ cpool_to_leafc_p(m) = 0._r8
+ cpool_to_leafc_storage_p(m) = 0._r8
+ cpool_to_frootc_p(m) = 0._r8
+ cpool_to_frootc_storage_p(m) = 0._r8
+ cpool_to_livestemc_p(m) = 0._r8
+ cpool_to_livestemc_storage_p(m) = 0._r8
+ cpool_to_deadstemc_p(m) = 0._r8
+ cpool_to_deadstemc_storage_p(m) = 0._r8
+ cpool_to_livecrootc_p(m) = 0._r8
+ cpool_to_livecrootc_storage_p(m) = 0._r8
+ cpool_to_deadcrootc_p(m) = 0._r8
+ cpool_to_deadcrootc_storage_p(m) = 0._r8
+ cpool_to_gresp_storage_p(m) = 0._r8
+ cpool_leaf_gr_p(m) = 0._r8
+ cpool_leaf_storage_gr_p(m) = 0._r8
+ transfer_leaf_gr_p(m) = 0._r8
+ cpool_froot_gr_p(m) = 0._r8
+ cpool_froot_storage_gr_p(m) = 0._r8
+ transfer_froot_gr_p(m) = 0._r8
+ cpool_livestem_gr_p(m) = 0._r8
+ cpool_livestem_storage_gr_p(m) = 0._r8
+ transfer_livestem_gr_p(m) = 0._r8
+ cpool_deadstem_gr_p(m) = 0._r8
+ cpool_deadstem_storage_gr_p(m) = 0._r8
+ transfer_deadstem_gr_p(m) = 0._r8
+ cpool_livecroot_gr_p(m) = 0._r8
+ cpool_livecroot_storage_gr_p(m) = 0._r8
+ transfer_livecroot_gr_p(m) = 0._r8
+ cpool_deadcroot_gr_p(m) = 0._r8
+ cpool_deadcroot_storage_gr_p(m) = 0._r8
+ transfer_deadcroot_gr_p(m) = 0._r8
+ leafc_storage_to_xfer_p(m) = 0._r8
+ frootc_storage_to_xfer_p(m) = 0._r8
+ livestemc_storage_to_xfer_p(m) = 0._r8
+ deadstemc_storage_to_xfer_p(m) = 0._r8
+ livecrootc_storage_to_xfer_p(m) = 0._r8
+ deadcrootc_storage_to_xfer_p(m) = 0._r8
+ gresp_storage_to_xfer_p(m) = 0._r8
+ livestemc_to_deadstemc_p(m) = 0._r8
+ livecrootc_to_deadcrootc_p(m) = 0._r8
+ crop_seedc_to_leaf_p(m) = 0._r8
+
+ hrv_xsmrpool_to_atm_p(m) = 0._r8
+
+ xsmrpool_to_atm_p(m) = 0._r8
+ livestemc_to_litter_p(m) = 0._r8
+ grainc_to_food_p(m) = 0._r8
+ grainc_to_seed_p(m) = 0._r8
+ grainc_xfer_to_grainc_p(m) = 0._r8
+ cpool_to_grainc_p(m) = 0._r8
+ cpool_to_grainc_storage_p(m) = 0._r8
+ cpool_grain_gr_p(m) = 0._r8
+ cpool_grain_storage_gr_p(m) = 0._r8
+ transfer_grain_gr_p(m) = 0._r8
+ grainc_storage_to_xfer_p(m) = 0._r8
+ ENDDO
+
+ DO j=1,nl_soil
+ phenology_to_met_c(j,i) = 0._r8
+ phenology_to_cel_c(j,i) = 0._r8
+ phenology_to_lig_c(j,i) = 0._r8
+
+ gap_mortality_to_met_c(j,i) = 0._r8
+ gap_mortality_to_cel_c(j,i) = 0._r8
+ gap_mortality_to_lig_c(j,i) = 0._r8
+ gap_mortality_to_cwdc(j,i) = 0._r8
+
+ fire_mortality_to_cwdc(j,i) = 0._r8
+ fire_mortality_to_met_c(j,i) = 0._r8
+ fire_mortality_to_cel_c(j,i) = 0._r8
+ fire_mortality_to_lig_c(j,i) = 0._r8
+
+ DO k=1,ndecomp_pools
+ m_decomp_cpools_to_fire_vr(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ fire_closs(i) = 0._r8
+ fire_nloss(i) = 0._r8
+ wood_harvestc(i) = 0._r8
+ wood_harvestn(i) = 0._r8
+ grainc_to_cropprodc(i) = 0._r8
+ grainn_to_cropprodn(i) = 0._r8
+
+ DO m = ps, pe
+ gpp_p(m) = 0._r8
+ wood_harvestc_p(m) = 0._r8
+ wood_harvestn_p(m) = 0._r8
+ grainc_to_cropprodc_p(m) = 0._r8
+ grainn_to_cropprodn_p(m) = 0._r8
+ soyfixn_p(m) = 0._r8
+
+ fire_closs_p(m) = 0._r8
+ fire_nloss_p(m) = 0._r8
+
+ ! CNVegNitrogenFluxes set zero
+
+ m_leafn_to_litter_p(m) = 0._r8
+ m_frootn_to_litter_p(m) = 0._r8
+ m_leafn_storage_to_litter_p(m) = 0._r8
+ m_frootn_storage_to_litter_p(m) = 0._r8
+ m_livestemn_storage_to_litter_p(m) = 0._r8
+ m_deadstemn_storage_to_litter_p(m) = 0._r8
+ m_livecrootn_storage_to_litter_p(m) = 0._r8
+ m_deadcrootn_storage_to_litter_p(m) = 0._r8
+ m_leafn_xfer_to_litter_p(m) = 0._r8
+ m_frootn_xfer_to_litter_p(m) = 0._r8
+ m_livestemn_xfer_to_litter_p(m) = 0._r8
+ m_deadstemn_xfer_to_litter_p(m) = 0._r8
+ m_livecrootn_xfer_to_litter_p(m) = 0._r8
+ m_deadcrootn_xfer_to_litter_p(m) = 0._r8
+ m_livestemn_to_litter_p(m) = 0._r8
+ m_deadstemn_to_litter_p(m) = 0._r8
+ m_livecrootn_to_litter_p(m) = 0._r8
+ m_deadcrootn_to_litter_p(m) = 0._r8
+ m_retransn_to_litter_p(m) = 0._r8
+
+ m_leafn_to_fire_p(m) = 0._r8
+ m_leafn_storage_to_fire_p(m) = 0._r8
+ m_leafn_xfer_to_fire_p(m) = 0._r8
+ m_livestemn_to_fire_p(m) = 0._r8
+ m_livestemn_storage_to_fire_p(m) = 0._r8
+ m_livestemn_xfer_to_fire_p(m) = 0._r8
+ m_deadstemn_to_fire_p(m) = 0._r8
+ m_deadstemn_storage_to_fire_p(m) = 0._r8
+ m_deadstemn_xfer_to_fire_p(m) = 0._r8
+ m_frootn_to_fire_p(m) = 0._r8
+ m_frootn_storage_to_fire_p(m) = 0._r8
+ m_frootn_xfer_to_fire_p(m) = 0._r8
+ m_livecrootn_to_fire_p(m) = 0._r8
+ m_livecrootn_storage_to_fire_p(m) = 0._r8
+ m_livecrootn_xfer_to_fire_p(m) = 0._r8
+ m_deadcrootn_to_fire_p(m) = 0._r8
+ m_deadcrootn_storage_to_fire_p(m) = 0._r8
+ m_deadcrootn_xfer_to_fire_p(m) = 0._r8
+ m_retransn_to_fire_p(m) = 0._r8
+
+
+ m_leafn_to_litter_fire_p(m) = 0._r8
+ m_leafn_storage_to_litter_fire_p(m) = 0._r8
+ m_leafn_xfer_to_litter_fire_p(m) = 0._r8
+ m_livestemn_to_litter_fire_p(m) = 0._r8
+ m_livestemn_storage_to_litter_fire_p(m) = 0._r8
+ m_livestemn_xfer_to_litter_fire_p(m) = 0._r8
+ m_livestemn_to_deadstemn_fire_p(m) = 0._r8
+ m_deadstemn_to_litter_fire_p(m) = 0._r8
+ m_deadstemn_storage_to_litter_fire_p(m) = 0._r8
+ m_deadstemn_xfer_to_litter_fire_p(m) = 0._r8
+ m_frootn_to_litter_fire_p(m) = 0._r8
+ m_frootn_storage_to_litter_fire_p(m) = 0._r8
+ m_frootn_xfer_to_litter_fire_p(m) = 0._r8
+ m_livecrootn_to_litter_fire_p(m) = 0._r8
+ m_livecrootn_storage_to_litter_fire_p(m) = 0._r8
+ m_livecrootn_xfer_to_litter_fire_p(m) = 0._r8
+ m_livecrootn_to_deadcrootn_fire_p(m) = 0._r8
+ m_deadcrootn_to_litter_fire_p(m) = 0._r8
+ m_deadcrootn_storage_to_litter_fire_p(m) = 0._r8
+ m_deadcrootn_xfer_to_litter_fire_p(m) = 0._r8
+ m_retransn_to_litter_fire_p(m) = 0._r8
+
+ leafn_xfer_to_leafn_p(m) = 0._r8
+ frootn_xfer_to_frootn_p(m) = 0._r8
+ livestemn_xfer_to_livestemn_p(m) = 0._r8
+ deadstemn_xfer_to_deadstemn_p(m) = 0._r8
+ livecrootn_xfer_to_livecrootn_p(m) = 0._r8
+ deadcrootn_xfer_to_deadcrootn_p(m) = 0._r8
+ leafn_to_litter_p(m) = 0._r8
+ leafn_to_retransn_p(m) = 0._r8
+ frootn_to_litter_p(m) = 0._r8
+ retransn_to_npool_p(m) = 0._r8
+ free_retransn_to_npool_p(m) = 0._r8
+ sminn_to_npool_p(m) = 0._r8
+ npool_to_leafn_p(m) = 0._r8
+ npool_to_leafn_storage_p(m) = 0._r8
+ npool_to_frootn_p(m) = 0._r8
+ npool_to_frootn_storage_p(m) = 0._r8
+ npool_to_livestemn_p(m) = 0._r8
+ npool_to_livestemn_storage_p(m) = 0._r8
+ npool_to_deadstemn_p(m) = 0._r8
+ npool_to_deadstemn_storage_p(m) = 0._r8
+ npool_to_livecrootn_p(m) = 0._r8
+ npool_to_livecrootn_storage_p(m) = 0._r8
+ npool_to_deadcrootn_p(m) = 0._r8
+ npool_to_deadcrootn_storage_p(m) = 0._r8
+ leafn_storage_to_xfer_p(m) = 0._r8
+ frootn_storage_to_xfer_p(m) = 0._r8
+ livestemn_storage_to_xfer_p(m) = 0._r8
+ deadstemn_storage_to_xfer_p(m) = 0._r8
+ livecrootn_storage_to_xfer_p(m) = 0._r8
+ deadcrootn_storage_to_xfer_p(m) = 0._r8
+ livestemn_to_deadstemn_p(m) = 0._r8
+ livestemn_to_retransn_p(m) = 0._r8
+ livecrootn_to_deadcrootn_p(m) = 0._r8
+ livecrootn_to_retransn_p(m) = 0._r8
+
+ crop_seedn_to_leaf_p(m) = 0._r8
+
+ livestemn_to_litter_p(m) = 0._r8
+ grainn_to_food_p(m) = 0._r8
+ grainn_to_seed_p(m) = 0._r8
+ grainn_xfer_to_grainn_p(m) = 0._r8
+ npool_to_grainn_p(m) = 0._r8
+ npool_to_grainn_storage_p(m) = 0._r8
+ grainn_storage_to_xfer_p(m) = 0._r8
+ frootn_to_retransn_p(m) = 0._r8
+ ENDDO
+
+ DO j=1,nl_soil
+
+ ! phenology: litterfall and crop fluxes associated wit
+ phenology_to_met_n(j,i) = 0._r8
+ phenology_to_cel_n(j,i) = 0._r8
+ phenology_to_lig_n(j,i) = 0._r8
+
+ ! gap mortality
+ gap_mortality_to_met_n(j,i) = 0._r8
+ gap_mortality_to_cel_n(j,i) = 0._r8
+ gap_mortality_to_lig_n(j,i) = 0._r8
+ gap_mortality_to_cwdn(j,i) = 0._r8
+
+ ! fire
+ fire_mortality_to_cwdn(j,i) = 0._r8
+ fire_mortality_to_met_n(j,i) = 0._r8
+ fire_mortality_to_cel_n(j,i) = 0._r8
+ fire_mortality_to_lig_n(j,i) = 0._r8
+
+ ENDDO
+
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ m_decomp_npools_to_fire_vr(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ DO k=1,ndecomp_transitions
+ DO j=1,nl_soil
+ decomp_hr_vr(j,k,i) = 0._r8
+ decomp_ctransfer_vr(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_cpools_transport_tendency(j,k,i) = 0._r8
+ decomp_cpools_sourcesink(j,k,i) = 0._r8
+ decomp_k(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ somc_fire(i) = 0._r8
+ som_c_leached(i) = 0._r8
+ decomp_hr(i) = 0._r8
+
+
+
+ IF(.not. DEF_USE_NITRIF)THEN
+ DO j = 1, nl_soil
+ sminn_to_denit_excess_vr(j,i) = 0._r8
+ sminn_leached_vr(j,i) = 0._r8
+ sminn_to_plant_fun_vr(j,i) = 0._r8
+ ENDDO
+ ELSE
+ DO j = 1, nl_soil
+ f_nit_vr(j,i) = 0._r8
+ f_denit_vr(j,i) = 0._r8
+ smin_no3_leached_vr(j,i) = 0._r8
+ smin_no3_runoff_vr(j,i) = 0._r8
+ n2_n2o_ratio_denit_vr(j,i) = 0._r8
+ pot_f_nit_vr(j,i) = 0._r8
+ pot_f_denit_vr(j,i) = 0._r8
+ actual_immob_no3_vr(j,i) = 0._r8
+ actual_immob_nh4_vr(j,i) = 0._r8
+ smin_no3_to_plant_vr(j,i) = 0._r8
+ smin_nh4_to_plant_vr(j,i) = 0._r8
+ f_n2o_denit_vr(j,i) = 0._r8
+ f_n2o_nit_vr(j,i) = 0._r8
+ ENDDO
+ ENDIF
+
+ DO j = 1, nl_soil
+ potential_immob_vr(j,i) = 0._r8
+ actual_immob_vr(j,i) = 0._r8
+ sminn_to_plant(i) = 0._r8
+ sminn_to_plant_vr(j,i) = 0._r8
+ supplement_to_sminn_vr(j,i) = 0._r8
+ gross_nmin_vr(j,i) = 0._r8
+ net_nmin_vr(j,i) = 0._r8
+ sminn_to_plant_fun_no3_vr(j,i) = 0._r8
+ sminn_to_plant_fun_nh4_vr(j,i) = 0._r8
+ ENDDO
+
+ nfix_to_sminn(i) = 0._r8
+ ffix_to_sminn(i) = 0._r8
+ fert_to_sminn(i) = 0._r8
+ soyfixn_to_sminn(i) = 0._r8
+ supplement_to_sminn(i) = 0._r8
+ gross_nmin(i) = 0._r8
+ net_nmin(i) = 0._r8
+ denit(i) = 0._r8
+ f_n2o_nit(i) = 0._r8
+ smin_no3_leached(i) = 0._r8
+ smin_no3_runoff(i) = 0._r8
+ sminn_leached(i) = 0._r8
+ som_n_leached(i) = 0._r8
+
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_npools_transport_tendency(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ DO k = 1, ndecomp_transitions
+ DO j = 1, nl_soil
+ decomp_ntransfer_vr(j,k,i) = 0._r8
+ decomp_sminn_flux_vr(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ IF(.not. DEF_USE_NITRIF)THEN
+ DO k = 1, ndecomp_transitions
+ DO j = 1, nl_soil
+ sminn_to_denit_decomp_vr(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+ ENDIF
+
+ DO k = 1, ndecomp_pools
+ DO j = 1, nl_soil
+ decomp_npools_sourcesink(j,k,i) = 0._r8
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE CNZeroFluxes
+
+END MODULE MOD_BGC_CNZeroFluxes
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Daylength.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Daylength.F90
new file mode 100644
index 0000000000..e37fcd3871
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Daylength.F90
@@ -0,0 +1,90 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Daylength
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Computes day length and solar declination angle based on given latitude and date.
+!
+! ! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! REVISION:
+! Xingjie Lu, 2022, modify original CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+ PRIVATE
+
+ PUBLIC :: daylength ! function to compute daylength
+ PRIVATE :: declin_angle ! function to compute solar decliation angle
+ !
+ !-----------------------------------------------------------------------
+
+CONTAINS
+
+ !-----------------------------------------------------------------------
+ real(r8) FUNCTION daylength(dlat, idate2)
+!
+! !DESCRIPTION:
+! Computes daylength (in seconds)
+!
+! Latitude and solar declination angle should both be specified in radians. decl must
+! be strictly less than pi/2; lat must be less than pi/2 within a small tolerance.
+!
+ real(r8), intent(in) :: dlat ! latitude (degrees)
+ integer , intent(in) :: idate2 ! day of the year
+
+ real(r8),parameter :: PI = 4.*atan(1.)!
+ ! !LOCAL VARIABLES:
+ real(r8) :: my_lat ! local version of lat, possibly adjusted slightly
+ real(r8) :: temp ! temporary variable
+ real(r8) :: decl
+
+ ! number of seconds per radian of hour-angle
+ real(r8), parameter :: secs_per_radian = 13750.9871_r8
+
+ ! epsilon for defining latitudes "near" the pole
+ real(r8), parameter :: lat_epsilon = 10._r8 * epsilon(1._r8)
+
+ ! Define an offset pole as slightly less than pi/2 to avoid problems with cos(lat) being negative
+ real(r8), parameter :: pole = PI/2.0_r8
+ real(r8), parameter :: offset_pole = pole - lat_epsilon
+ !-----------------------------------------------------------------------
+
+ decl=declin_angle(idate2)
+
+ ! lat must be less than pi/2 within a small tolerance
+ IF (abs(dlat/180*PI) >= (pole + lat_epsilon)) THEN
+ daylength = -9999
+ write(*,*)"error in latitude",dlat
+
+ ! decl must be strictly less than pi/2
+ ELSE IF (abs(decl) >= pole) THEN
+ daylength = -9999
+ write(*,*)"error in idate:",idate2
+
+ ! normal case
+ ELSE
+ ! Ensure that latitude isn't too close to pole, to avoid problems with cos(lat) being negative
+ my_lat = min(offset_pole, max(-1._r8 * offset_pole, dlat/180*PI))
+
+ temp = -(sin(my_lat)*sin(decl))/(cos(my_lat) * cos(decl))
+ temp = min(1._r8,max(-1._r8,temp))
+ daylength = 2.0_r8 * secs_per_radian * acos(temp)
+ ENDIF
+
+ END FUNCTION daylength
+
+ real(r8) FUNCTION declin_angle(idate2)
+
+ integer ,intent(in) :: idate2 ! day of the year
+ real(r8),parameter :: PI = 4.*atan(1.) ! circular constant
+
+ declin_angle=-23.44_r8/180._r8*PI*cos(2*PI/365*(idate2+10))
+
+ END FUNCTION declin_angle
+
+END MODULE MOD_BGC_Daylength
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemCompetition.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemCompetition.F90
new file mode 100644
index 0000000000..6438b71cf8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemCompetition.F90
@@ -0,0 +1,469 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemCompetition
+
+!---------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate the soil mineral nitrogen competition between soil microbial (immobilisation) and plant (N uptake).
+! Note that there is no non-linear microbial model in CoLM-BGC.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: npcropmin
+ USE MOD_Namelist, only: DEF_USE_NITRIF, DEF_USE_NOSTRESSNITROGEN
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ pot_f_nit_vr, potential_immob_vr, sminn_to_plant_vr, sminn_to_denit_excess_vr, plant_ndemand, &
+ actual_immob_vr, sminn_to_plant, pot_f_nit_vr, actual_immob_nh4_vr, f_nit_vr, &
+ smin_nh4_to_plant_vr, pot_f_denit_vr, actual_immob_no3_vr, f_denit_vr, smin_no3_to_plant_vr, &
+ n2_n2o_ratio_denit_vr, f_n2o_nit_vr, f_n2o_denit_vr, supplement_to_sminn_vr
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ sminn_vr, smin_no3_vr, smin_nh4_vr, nfixation_prof, fpi_vr, fpi, fpg
+ USE MOD_BGC_Vars_TimeInvariants,only: &
+ bdnr, compet_plant_no3, compet_plant_nh4, compet_decomp_no3, compet_decomp_nh4, compet_denit, compet_nit, &
+ nitrif_n2o_loss_frac
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemCompetition
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemCompetition(i,deltim,nl_soil,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+
+
+ integer :: p,l,pi,j ! indices
+ real(r8) :: fpi_no3_vr(1:nl_soil) ! fraction of potential immobilization supplied by no3(no units)
+ real(r8) :: fpi_nh4_vr(1:nl_soil) ! fraction of potential immobilization supplied by nh4 (no units)
+ real(r8) :: sum_nh4_demand(1:nl_soil)
+ real(r8) :: sum_nh4_demand_scaled(1:nl_soil)
+ real(r8) :: sum_no3_demand(1:nl_soil)
+ real(r8) :: sum_no3_demand_scaled(1:nl_soil)
+ real(r8) :: sum_ndemand_vr( 1:nl_soil) !total column N demand (gN/m3/s) at a given level
+ real(r8) :: nuptake_prof( 1:nl_soil)
+ real(r8) :: sminn_tot
+ integer :: nlimit(1:nl_soil) !flag for N limitation
+ integer :: nlimit_no3(1:nl_soil) !flag for NO3 limitation
+ integer :: nlimit_nh4(1:nl_soil) !flag for NH4 limitation
+ real(r8) :: residual_sminn_vr( 1:nl_soil)
+ real(r8) :: residual_sminn
+ real(r8) :: residual_smin_nh4_vr( 1:nl_soil)
+ real(r8) :: residual_smin_no3_vr( 1:nl_soil)
+ real(r8) :: residual_smin_nh4
+ real(r8) :: residual_smin_no3
+ real(r8) :: residual_plant_ndemand
+ real(r8) :: sminn_to_plant_new
+ real(r8) :: actual_immob
+ real(r8) :: potential_immob
+ integer :: ivt, ps, pe, m
+ !-----------------------------------------------------------------------
+
+ sminn_to_plant_new = 0._r8
+
+ IF(.not. DEF_USE_NITRIF)THEN
+
+ ! init sminn_tot
+ sminn_tot = 0.
+
+ DO j = 1, nl_soil
+ sminn_tot = sminn_tot + sminn_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ DO j = 1, nl_soil
+ IF (sminn_tot > 0.) THEN
+ nuptake_prof(j) = sminn_vr(j,i) / sminn_tot
+ ELSE
+ nuptake_prof(j) = nfixation_prof(j,i)
+ ENDIF
+ ENDDO
+
+ DO j = 1, nl_soil
+ sum_ndemand_vr(j) = plant_ndemand(i) * nuptake_prof(j) + potential_immob_vr(j,i)
+ ENDDO
+
+ DO j = 1, nl_soil
+ IF (sum_ndemand_vr(j)*deltim < sminn_vr(j,i)) THEN
+
+ ! N availability is not limiting immobilization or plant
+ ! uptake, and both can proceed at their potential rates
+ nlimit(j) = 0
+ fpi_vr(j,i) = 1.0_r8
+ actual_immob_vr(j,i) = potential_immob_vr(j,i)
+ sminn_to_plant_vr(j,i) = plant_ndemand(i) * nuptake_prof(j)
+ ELSE
+ ! N availability can not satisfy the sum of immobilization and
+ ! plant growth demands, so these two demands compete for available
+ ! soil mineral N resource.
+
+ nlimit(j) = 1
+ IF (sum_ndemand_vr(j) > 0.0_r8) THEN
+ actual_immob_vr(j,i) = (sminn_vr(j,i)/deltim)*(potential_immob_vr(j,i) / sum_ndemand_vr(j))
+ ELSE
+ actual_immob_vr(j,i) = 0.0_r8
+ ENDIF
+
+ IF (potential_immob_vr(j,i) > 0.0_r8) THEN
+ fpi_vr(j,i) = actual_immob_vr(j,i) / potential_immob_vr(j,i)
+ ELSE
+ fpi_vr(j,i) = 0.0_r8
+ ENDIF
+
+ sminn_to_plant_vr(j,i) = (sminn_vr(j,i)/deltim) - actual_immob_vr(j,i)
+ ENDIF
+
+ IF (DEF_USE_NOSTRESSNITROGEN) THEN
+ ps = patch_pft_s(i)
+ pe = patch_pft_e(i)
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF (ivt >= npcropmin) THEN
+ nlimit(j) = 1
+ fpi_vr(j,i) = 1.0_r8
+ actual_immob_vr(j,i) = potential_immob_vr(j,i)
+ sminn_to_plant_vr(j,i) = plant_ndemand(i) * nuptake_prof(j)
+ supplement_to_sminn_vr(j,i) = sum_ndemand_vr(j) - (sminn_vr(j,i)/deltim)
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ! sum up N fluxes to plant
+ DO j = 1, nl_soil
+ sminn_to_plant(i) = sminn_to_plant(i) + sminn_to_plant_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ ! give plants a second pass to see IF there is any mineral N left over with which to satisfy residual N demand.
+ residual_sminn = 0._r8
+
+ ! sum up total N left over after initial plant and immobilization fluxes
+ residual_plant_ndemand = plant_ndemand(i) - sminn_to_plant(i)
+
+ DO j = 1, nl_soil
+ IF (residual_plant_ndemand > 0._r8 ) THEN
+ IF (nlimit(j) .eq. 0) THEN
+ residual_sminn_vr(j) = max(sminn_vr(j,i) - (actual_immob_vr(j,i) + sminn_to_plant_vr(j,i) ) * deltim, 0._r8)
+ residual_sminn = residual_sminn + residual_sminn_vr(j) * dz_soi(j)
+ ELSE
+ residual_sminn_vr(j) = 0._r8
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! distribute residual N to plants
+ DO j = 1, nl_soil
+ IF ( residual_plant_ndemand > 0._r8 .and. residual_sminn > 0._r8 .and. nlimit(j) .eq. 0) THEN
+ sminn_to_plant_vr(j,i) = sminn_to_plant_vr(j,i) + residual_sminn_vr(j) * &
+ min(( residual_plant_ndemand * deltim ) / residual_sminn, 1._r8) / deltim
+ ENDIF
+ ENDDO
+
+ ! re-sum up N fluxes to plant
+ sminn_to_plant(i) = 0._r8
+ DO j = 1, nl_soil
+ sminn_to_plant(i) = sminn_to_plant(i) + sminn_to_plant_vr(j,i) * dz_soi(j)
+ sum_ndemand_vr(j) = potential_immob_vr(j,i) + sminn_to_plant_vr(j,i)
+ ENDDO
+
+ ! under conditions of excess N, some proportion is assumed to
+ ! be lost to denitrification, in addition to the constant
+ ! proportion lost in the decomposition pathways
+ DO j = 1, nl_soil
+ IF ((sminn_to_plant_vr(j,i) + actual_immob_vr(j,i))*deltim < sminn_vr(j,i)) THEN
+ sminn_to_denit_excess_vr(j,i) = max(bdnr*deltim/86400._r8*((sminn_vr(j,i)/deltim) - sum_ndemand_vr(j)),0._r8)
+ ELSE
+ sminn_to_denit_excess_vr(j,i) = 0._r8
+ ENDIF
+ ENDDO
+
+ ! sum up N fluxes to immobilization
+ actual_immob = 0._r8
+ potential_immob = 0._r8
+ DO j = 1, nl_soil
+ actual_immob = actual_immob + actual_immob_vr(j,i) * dz_soi(j)
+ potential_immob = potential_immob + potential_immob_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ ! calculate the fraction of potential growth that can be
+ ! achieved with the N available to plants
+ IF (plant_ndemand(i) > 0.0_r8) THEN
+ fpg(i) = sminn_to_plant(i) / plant_ndemand(i)
+ ELSE
+ fpg(i) = 1.0_r8
+ ENDIF
+
+ ! calculate the fraction of immobilization realized (for diagnostic purposes)
+ IF (potential_immob > 0.0_r8) THEN
+ fpi(i) = actual_immob / potential_immob
+ ELSE
+ fpi(i) = 1.0_r8
+ ENDIF
+
+ ELSE
+ ! init total mineral N pools
+ sminn_tot = 0.
+
+ ! sum up total mineral N pools
+ DO j = 1, nl_soil
+ sminn_tot = sminn_tot + (smin_no3_vr(j,i) + smin_nh4_vr(j,i)) * dz_soi(j)
+ ENDDO
+
+ ! define N uptake profile for initial vertical distribution of plant N uptake, assuming plant seeks N from WHERE it is most abundant
+ DO j = 1, nl_soil
+ IF (sminn_tot > 0.) THEN
+ nuptake_prof(j) = sminn_vr(j,i) / sminn_tot
+ ELSE
+ nuptake_prof(j) = nfixation_prof(j,i)
+ ENDIF
+ ENDDO
+
+ ! main column/vertical loop
+ DO j = 1, nl_soil
+ ! first compete for nh4
+ sum_nh4_demand(j) = plant_ndemand(i) * nuptake_prof(j) + potential_immob_vr(j,i) + pot_f_nit_vr(j,i)
+ sum_nh4_demand_scaled(j) = plant_ndemand(i)* nuptake_prof(j) * compet_plant_nh4 + &
+ potential_immob_vr(j,i)*compet_decomp_nh4 + pot_f_nit_vr(j,i)*compet_nit
+
+ IF (sum_nh4_demand(j)*deltim < smin_nh4_vr(j,i)) THEN
+
+ ! NH4 availability is not limiting immobilization or plant
+ ! uptake, and all can proceed at their potential rates
+ nlimit_nh4(j) = 0
+ fpi_nh4_vr(j) = 1.0_r8
+ actual_immob_nh4_vr(j,i) = potential_immob_vr(j,i)
+ !RF added new term.
+
+ f_nit_vr(j,i) = pot_f_nit_vr(j,i)
+
+ smin_nh4_to_plant_vr(j,i) = plant_ndemand(i) * nuptake_prof(j)
+
+ ELSE
+
+ ! NH4 availability can not satisfy the sum of immobilization, nitrification, and
+ ! plant growth demands, so these three demands compete for available
+ ! soil mineral NH4 resource.
+ nlimit_nh4(j) = 1
+ IF (sum_nh4_demand(j) > 0.0_r8) THEN
+ ! RF microbes compete based on the hypothesised plant demand.
+ actual_immob_nh4_vr(j,i) = min((smin_nh4_vr(j,i)/deltim)*(potential_immob_vr(j,i)* &
+ compet_decomp_nh4 / sum_nh4_demand_scaled(j)), potential_immob_vr(j,i))
+
+ f_nit_vr(j,i) = min((smin_nh4_vr(j,i)/deltim)*(pot_f_nit_vr(j,i)*compet_nit / &
+ sum_nh4_demand_scaled(j)), pot_f_nit_vr(j,i))
+
+ smin_nh4_to_plant_vr(j,i) = min((smin_nh4_vr(j,i)/deltim)*(plant_ndemand(i)* &
+ nuptake_prof(j)*compet_plant_nh4 / sum_nh4_demand_scaled(j)), plant_ndemand(i)*nuptake_prof(j))
+
+ ELSE
+ actual_immob_nh4_vr(j,i) = 0.0_r8
+ smin_nh4_to_plant_vr(j,i) = 0.0_r8
+ f_nit_vr(j,i) = 0.0_r8
+ ENDIF
+
+ IF (potential_immob_vr(j,i) > 0.0_r8) THEN
+ fpi_nh4_vr(j) = actual_immob_nh4_vr(j,i) / potential_immob_vr(j,i)
+ ELSE
+ fpi_nh4_vr(j) = 0.0_r8
+ ENDIF
+
+ ENDIF
+ sum_no3_demand(j) = (plant_ndemand(i)*nuptake_prof(j)-smin_nh4_to_plant_vr(j,i)) &
+ + (potential_immob_vr(j,i)-actual_immob_nh4_vr(j,i)) + pot_f_denit_vr(j,i)
+ sum_no3_demand_scaled(j) = (plant_ndemand(i)*nuptake_prof(j) &
+ - smin_nh4_to_plant_vr(j,i))*compet_plant_no3 &
+ + (potential_immob_vr(j,i)-actual_immob_nh4_vr(j,i))*compet_decomp_no3 + pot_f_denit_vr(j,i)*compet_denit
+
+ IF (sum_no3_demand(j)*deltim < smin_no3_vr(j,i)) THEN
+
+ ! NO3 availability is not limiting immobilization or plant
+ ! uptake, and all can proceed at their potential rates
+ nlimit_no3(j) = 0
+ fpi_no3_vr(j) = 1.0_r8 - fpi_nh4_vr(j)
+ actual_immob_no3_vr(j,i) = (potential_immob_vr(j,i)-actual_immob_nh4_vr(j,i))
+
+ f_denit_vr(j,i) = pot_f_denit_vr(j,i)
+
+ smin_no3_to_plant_vr(j,i) = (plant_ndemand(i)*nuptake_prof(j)-smin_nh4_to_plant_vr(j,i))
+ ELSE
+
+ ! NO3 availability can not satisfy the sum of immobilization, denitrification, and
+ ! plant growth demands, so these three demands compete for available
+ ! soil mineral NO3 resource.
+ nlimit_no3(j) = 1
+
+ IF (sum_no3_demand(j) > 0.0_r8) THEN
+ actual_immob_no3_vr(j,i) = min((smin_no3_vr(j,i)/deltim)*((potential_immob_vr(j,i) &
+ - actual_immob_nh4_vr(j,i))*compet_decomp_no3 / sum_no3_demand_scaled(j)), &
+ potential_immob_vr(j,i)-actual_immob_nh4_vr(j,i))
+
+ smin_no3_to_plant_vr(j,i) = min((smin_no3_vr(j,i)/deltim)*((plant_ndemand(i) &
+ * nuptake_prof(j)-smin_nh4_to_plant_vr(j,i))*compet_plant_no3 / sum_no3_demand_scaled(j)), &
+ plant_ndemand(i)*nuptake_prof(j)-smin_nh4_to_plant_vr(j,i))
+
+ f_denit_vr(j,i) = min((smin_no3_vr(j,i)/deltim)*(pot_f_denit_vr(j,i)*compet_denit / &
+ sum_no3_demand_scaled(j)), pot_f_denit_vr(j,i))
+
+ ELSE ! no no3 demand. no uptake fluxes.
+ actual_immob_no3_vr(j,i) = 0.0_r8
+ smin_no3_to_plant_vr(j,i) = 0.0_r8
+ f_denit_vr(j,i) = 0.0_r8
+
+ ENDIF !any no3 demand?
+
+ IF (potential_immob_vr(j,i) > 0.0_r8) THEN
+ fpi_no3_vr(j) = actual_immob_no3_vr(j,i) / potential_immob_vr(j,i)
+ ELSE
+ fpi_no3_vr(j) = 0.0_r8
+ ENDIF
+
+ ENDIF
+
+ ! n2o emissions: n2o from nitr is const fraction, n2o from denitr is calculated in nitrif_denitrif
+ f_n2o_nit_vr(j,i) = f_nit_vr(j,i) * nitrif_n2o_loss_frac
+ f_n2o_denit_vr(j,i) = f_denit_vr(j,i) / (1._r8 + n2_n2o_ratio_denit_vr(j,i))
+
+
+ ! this code block controls the addition of N to sminn pool
+ ! to eliminate any N limitation, when Carbon_Only is set. This lets the
+ ! model behave essentially as a carbon-only model, but with the
+ ! benefit of keeping track of the N additions needed to
+ ! eliminate N limitations, so there is still a diagnostic quantity
+ ! that describes the degree of N limitation at steady-state.
+ IF (DEF_USE_NOSTRESSNITROGEN) THEN
+ ps = patch_pft_s(i)
+ pe = patch_pft_e(i)
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF (ivt >= npcropmin) THEN
+ IF (fpi_no3_vr(j) + fpi_nh4_vr(j) < 1._r8) THEN
+ fpi_nh4_vr(j) = 1.0_r8 - fpi_no3_vr(j)
+ supplement_to_sminn_vr(j,i) = (potential_immob_vr(j,i) &
+ - actual_immob_no3_vr(j,i)) - actual_immob_nh4_vr(j,i)
+ ! update to new values that satisfy demand
+ actual_immob_nh4_vr(j,i) = potential_immob_vr(j,i) - actual_immob_no3_vr(j,i)
+ ENDIF
+ IF (smin_no3_to_plant_vr(j,i) + smin_nh4_to_plant_vr(j,i) < plant_ndemand(i)*nuptake_prof(j)) THEN
+ supplement_to_sminn_vr(j,i) = supplement_to_sminn_vr(j,i) + &
+ (plant_ndemand(i)*nuptake_prof(j) - smin_no3_to_plant_vr(j,i)) - smin_nh4_to_plant_vr(j,i) ! use old values
+ smin_nh4_to_plant_vr(j,i) = plant_ndemand(i)*nuptake_prof(j) - smin_no3_to_plant_vr(j,i)
+ ENDIF
+ sminn_to_plant_vr(j,i) = smin_no3_to_plant_vr(j,i) + smin_nh4_to_plant_vr(j,i)
+ ENDIF
+ ENDDO
+ ENDIF
+ ! sum up no3 and nh4 fluxes
+ fpi_vr(j,i) = fpi_no3_vr(j) + fpi_nh4_vr(j)
+ sminn_to_plant_vr(j,i) = smin_no3_to_plant_vr(j,i) + smin_nh4_to_plant_vr(j,i)
+ actual_immob_vr(j,i) = actual_immob_no3_vr(j,i) + actual_immob_nh4_vr(j,i)
+ ENDDO
+
+ ! sum up N fluxes to plant after initial competition
+ sminn_to_plant(i) = 0._r8
+ DO j = 1, nl_soil
+ sminn_to_plant(i) = sminn_to_plant(i) + sminn_to_plant_vr(j,i) * dz_soi(j)
+ ENDDO
+ ! give plants a second pass to see IF there is any mineral N left over with which to satisfy residual N demand.
+ ! first take frm nh4 pool; THEN take from no3 pool
+ residual_plant_ndemand = plant_ndemand(i) - sminn_to_plant(i)
+ residual_smin_nh4 = 0._r8
+ DO j = 1, nl_soil
+ IF (residual_plant_ndemand > 0._r8 ) THEN
+ IF (nlimit_nh4(j) .eq. 0) THEN
+ residual_smin_nh4_vr(j) = max(smin_nh4_vr(j,i) - (actual_immob_nh4_vr(j,i) + &
+ smin_nh4_to_plant_vr(j,i) + f_nit_vr(j,i) ) * deltim, 0._r8)
+
+ residual_smin_nh4 = residual_smin_nh4 + residual_smin_nh4_vr(j) * dz_soi(j)
+ ELSE
+ residual_smin_nh4_vr(j) = 0._r8
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO j = 1, nl_soil
+ IF (residual_plant_ndemand > 0._r8 ) THEN
+ IF ( residual_smin_nh4 > 0._r8 .and. nlimit_nh4(j) .eq. 0 ) THEN
+ smin_nh4_to_plant_vr(j,i) = smin_nh4_to_plant_vr(j,i) + residual_smin_nh4_vr(j) * &
+ min(( residual_plant_ndemand * deltim ) / residual_smin_nh4, 1._r8) / deltim
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! re-sum up N fluxes to plant after second pass for nh4
+ sminn_to_plant(i) = 0._r8
+ DO j = 1, nl_soil
+ sminn_to_plant_vr(j,i) = smin_nh4_to_plant_vr(j,i) + smin_no3_to_plant_vr(j,i)
+ sminn_to_plant(i) = sminn_to_plant(i) + (sminn_to_plant_vr(j,i)) * dz_soi(j)
+ ENDDO
+
+ !
+ ! and now DO second pass for no3
+ residual_plant_ndemand = plant_ndemand(i) - sminn_to_plant(i)
+ residual_smin_no3 = 0._r8
+
+ DO j = 1, nl_soil
+ IF (residual_plant_ndemand > 0._r8 ) THEN
+ IF (nlimit_no3(j) .eq. 0) THEN
+ residual_smin_no3_vr(j) = max(smin_no3_vr(j,i) - (actual_immob_no3_vr(j,i) + &
+ smin_no3_to_plant_vr(j,i) + f_denit_vr(j,i) ) * deltim, 0._r8)
+ residual_smin_no3 = residual_smin_no3 + residual_smin_no3_vr(j) * dz_soi(j)
+ ELSE
+ residual_smin_no3_vr(j) = 0._r8
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO j = 1, nl_soil
+ IF (residual_plant_ndemand > 0._r8 ) THEN
+ IF ( residual_smin_no3 > 0._r8 .and. nlimit_no3(j) .eq. 0) THEN
+ smin_no3_to_plant_vr(j,i) = smin_no3_to_plant_vr(j,i) + residual_smin_no3_vr(j) * &
+ min(( residual_plant_ndemand * deltim ) / residual_smin_no3, 1._r8) / deltim
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! re-sum up N fluxes to plant after second passes of both no3 and nh4
+ sminn_to_plant(i) = 0._r8
+ DO j = 1, nl_soil
+ sminn_to_plant_vr(j,i) = smin_nh4_to_plant_vr(j,i) + smin_no3_to_plant_vr(j,i)
+ sminn_to_plant(i) = sminn_to_plant(i) + (sminn_to_plant_vr(j,i)) * dz_soi(j)
+ ENDDO
+
+ ! sum up N fluxes to immobilization
+ actual_immob = 0._r8
+ potential_immob = 0._r8
+ DO j = 1, nl_soil
+ actual_immob = actual_immob + actual_immob_vr(j,i) * dz_soi(j)
+ potential_immob = potential_immob + potential_immob_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ ! calculate the fraction of potential growth that can be
+ ! achieved with the N available to plants
+ ! calculate the fraction of immobilization realized (for diagnostic purposes)
+
+ IF (plant_ndemand(i) > 0.0_r8) THEN
+ fpg(i) = sminn_to_plant(i) / plant_ndemand(i)
+ ELSE
+ fpg(i) = 1._r8
+ ENDIF
+
+ IF (potential_immob > 0.0_r8) THEN
+ fpi(i) = actual_immob / potential_immob
+ ELSE
+ fpi(i) = 1._r8
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE SoilBiogeochemCompetition
+
+END MODULE MOD_BGC_Soil_BiogeochemCompetition
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemDecomp.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemDecomp.F90
new file mode 100644
index 0000000000..0ba34efc97
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemDecomp.F90
@@ -0,0 +1,122 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemDecomp
+
+!-----------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This MODULE calculates the CN transfer fluxes between different soil and litter pools,
+! which includes CN transfer fluxes (decomp_ctransfer or decomp_ntransfer), heterotrophic respiration (decomp_hr),
+! net mineralisation and gross mineralisation. Denitrification flux will be also calculated when nitrification model
+! is activated.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised original CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_NITRIF
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ floating_cn_ratio, initial_cn_ratio, dnp, rf_decomp, receiver_pool, donor_pool, i_atm
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decomposition carbon & nitrogen pools
+ decomp_cpools_vr, decomp_npools_vr, &
+
+ ! other variables
+ cn_decomp_pools, fpi_vr
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ ! decomposition fluxes variables
+ decomp_sminn_flux_vr, decomp_hr_vr, decomp_ctransfer_vr, decomp_ntransfer_vr, &
+ pmnf_decomp, p_decomp_cpool_loss, sminn_to_denit_decomp_vr, &
+ net_nmin_vr, gross_nmin_vr, net_nmin, gross_nmin
+
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemDecomp
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemDecomp(i,nl_soil,ndecomp_pools,ndecomp_transitions, dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ndecomp_pools ! number of total soil & litter pools in the decompositions
+ integer ,intent(in) :: ndecomp_transitions ! number of total transfers between soil and litter pools in the decomposition
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer
+
+ integer j,k,l
+ ! calculate c:n ratios of applicable pools
+ DO l = 1, ndecomp_pools
+ IF ( floating_cn_ratio(l) ) THEN
+ DO j = 1,nl_soil
+ IF ( decomp_npools_vr(j,l,i) > 0._r8 ) THEN
+ cn_decomp_pools(j,l,i) = decomp_cpools_vr(j,l,i) / decomp_npools_vr(j,l,i)
+ ENDIF
+ ENDDO
+ ELSE
+ DO j = 1,nl_soil
+ cn_decomp_pools(j,l,i) = initial_cn_ratio(l)
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ! column loop to calculate actual immobilization and decomp rates, following
+ ! resolution of plant/heterotroph competition for mineral N
+
+ ! upon RETURN from SoilBiogeochemCompetition, the fraction of potential immobilization
+ ! has been set (soilbiogeochem_state_inst%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
+ ! of mineralization flux.
+
+ DO k = 1, ndecomp_transitions
+ DO j = 1,nl_soil
+ IF (decomp_cpools_vr(j,donor_pool(k),i) > 0._r8) THEN
+ IF ( pmnf_decomp(j,k,i) > 0._r8 ) THEN
+ p_decomp_cpool_loss(j,k,i) = p_decomp_cpool_loss(j,k,i) * fpi_vr(j,i)
+ pmnf_decomp(j,k,i) = pmnf_decomp(j,k,i) * fpi_vr(j,i)
+ IF(.not. DEF_USE_NITRIF)THEN
+ sminn_to_denit_decomp_vr(j,k,i) = 0._r8
+ ENDIF
+ ELSE
+ IF(.not. DEF_USE_NITRIF)THEN
+ sminn_to_denit_decomp_vr(j,k,i) = -dnp * pmnf_decomp(j,k,i)
+ ENDIF
+ ENDIF
+ decomp_hr_vr(j,k,i) = rf_decomp(j,k,i) * p_decomp_cpool_loss(j,k,i)
+ decomp_ctransfer_vr(j,k,i) = (1._r8 - rf_decomp(j,k,i)) * p_decomp_cpool_loss(j,k,i)
+ IF (decomp_npools_vr(j,donor_pool(k),i) > 0._r8 .and. receiver_pool(k) /= i_atm) THEN
+ decomp_ntransfer_vr(j,k,i) = p_decomp_cpool_loss(j,k,i) / cn_decomp_pools(j,donor_pool(k),i)
+ ELSE
+ decomp_ntransfer_vr(j,k,i) = 0._r8
+ ENDIF
+ IF ( receiver_pool(k) /= 0 ) THEN
+ decomp_sminn_flux_vr(j,k,i) = pmnf_decomp(j,k,i)
+ ELSE ! keep sign convention negative for terminal pools
+ decomp_sminn_flux_vr(j,k,i) = - pmnf_decomp(j,k,i)
+ ENDIF
+ net_nmin_vr(j,i) = net_nmin_vr(j,i) - pmnf_decomp(j,k,i)
+ ELSE
+ decomp_ntransfer_vr(j,k,i) = 0._r8
+ IF(.not. DEF_USE_NITRIF)THEN
+ sminn_to_denit_decomp_vr(j,k,i) = 0._r8
+ ENDIF
+ decomp_sminn_flux_vr(j,k,i) = 0._r8
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ DO j = 1,nl_soil
+ net_nmin(i) = net_nmin(i) + net_nmin_vr(j,i) * dz_soi(j)
+ gross_nmin(i) = gross_nmin(i) + gross_nmin_vr(j,i) * dz_soi(j)
+ ENDDO
+
+ END SUBROUTINE SoilBiogeochemDecomp
+
+END MODULE MOD_BGC_Soil_BiogeochemDecomp
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemDecompCascadeBGC.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemDecompCascadeBGC.F90
new file mode 100644
index 0000000000..23f23f2056
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemDecompCascadeBGC.F90
@@ -0,0 +1,122 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemDecompCascadeBGC
+
+!---------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate the soil decomposition rate according to soil temperature, soil matric potential, and depth
+!
+! !REFERENCES:
+! Koven, C.D., Riley, W.J., Subin, Z.M., Tang, J.Y., Torn, M.S., Collins, W.D., Bonan, G.B., Lawrence,
+! D.M. and Swenson, S.C., 2013. The effect of vertically resolved soil biogeochemistry and alternate
+! soil C and N models on C dynamics of CLM4. Biogeosciences, 10(11), 7109-7131.
+! Thornton, P.E., Law, B.E., Gholz, H.L., Clark, K.L., Falge, E., Ellsworth, D.S., Goldstein, A.H., Monson,
+! R.K., Hollinger, D., Falk, M. and Chen, J., 2002. Modeling and measuring the effects of disturbance
+! history and climate on carbon and water budgets in evergreen needleleaf forests.
+! Agricultural and forest meteorology, 113(1-4), 185-222.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Vars_TimeInvariants, only: &
+ Q10, smpmax_hr, smpmin_hr, tau_l1, tau_l2_l3, tau_s1, tau_s2, tau_s3, tau_cwd, froz_q10, &
+ i_met_lit,i_cel_lit,i_lig_lit ,i_cwd,i_soil1,i_soil2,i_soil3
+ USE MOD_Vars_TimeVariables, only: &
+ smp, t_soisno, t_scalar, w_scalar, o_scalar, depth_scalar, decomp_k
+ USE MOD_Vars_Global, only: PI
+
+ IMPLICIT NONE
+
+ PUBLIC decomp_rate_constants_bgc
+
+CONTAINS
+
+ SUBROUTINE decomp_rate_constants_bgc(i,nl_soil,z_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: z_soi(1:nl_soil) ! depth of each soil layer
+
+ real(r8) normalization_factor ! factor by which to offset the decomposition rates frm century to a q10 formulation
+ real(r8),parameter :: decomp_depth_efolding = 10._r8
+ real(r8) k_l1, k_l2_l3, k_s1, k_s2, k_s3, k_frag
+ real(r8) psi
+ integer j
+ real(r8) catanf
+ real(r8) catanf_30
+ real(r8) t1
+
+ catanf(t1) = 11.75_r8 +(29.7_r8 / PI) * atan( PI * 0.031_r8 * ( t1 - 15.4_r8 ))
+
+ ! translate to per-second time constant
+ k_l1 = 1._r8 / (86400._r8 * 365._r8 * tau_l1)
+ k_l2_l3 = 1._r8 / (86400._r8 * 365._r8 * tau_l2_l3)
+ k_s1 = 1._r8 / (86400._r8 * 365._r8 * tau_s1)
+ k_s2 = 1._r8 / (86400._r8 * 365._r8 * tau_s2)
+ k_s3 = 1._r8 / (86400._r8 * 365._r8 * tau_s3)
+ k_frag = 1._r8 / (86400._r8 * 365._r8 * tau_cwd)
+
+ ! calc ref rate
+ catanf_30 = catanf(30._r8)
+
+ DO j = 1, nl_soil
+ IF (t_soisno(j,i) >= 273.15_r8) THEN
+ t_scalar(j,i)= (Q10**((t_soisno(j,i)-(273.15_r8+25._r8))/10._r8))
+ ELSE
+ t_scalar(j,i)= (Q10**(-25._r8/10._r8))*(froz_q10**((t_soisno(j,i)-273.15_r8)/10._r8))
+ ENDIF
+ ENDDO
+
+ ! calculate the rate constant scalar for soil water content.
+ ! Uses the log relationship with water potential given in
+ ! Andren, O., and K. Paustian, 1987. Barley straw decomposition in the field:
+ ! a comparison of models. Ecology, 68(5):1190-1200.
+ ! and supported by data in
+ ! Orchard, V.A., and F.J. Cook, 1983. Relationship between soil respiration
+ ! and soil moisture. Soil Biol. Biochem., 15(4):447-453.
+
+ DO j = 1,nl_soil
+ psi = min(smp(j,i),smpmax_hr)
+ ! decomp only IF soilpsi is higher than minpsi
+ IF (psi > smpmin_hr) THEN
+ w_scalar(j,i) = (log(smpmin_hr/psi)/log(smpmin_hr/smpmax_hr))
+ ELSE
+ w_scalar(j,i) = 0.001_r8
+ ! update froot_prof_p for root carbon turnover when soil is frozen
+ ENDIF
+ ENDDO
+
+ o_scalar(1:nl_soil,i) = 1._r8
+
+ ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10
+ normalization_factor = (catanf(15._r8)/catanf_30) / (Q10**((15._r8-25._r8)/10._r8))
+ DO j = 1, nl_soil
+ t_scalar(j,i) = t_scalar(j,i) * normalization_factor
+ ENDDO
+
+ DO j = 1, nl_soil
+ depth_scalar(j,i) = exp(-z_soi(j)/decomp_depth_efolding)
+ ENDDO
+
+ DO j = 1, nl_soil
+ decomp_k(j,i_met_lit,i) = k_l1 * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * o_scalar(j,i) !&
+ decomp_k(j,i_cel_lit,i) = k_l2_l3 * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * o_scalar(j,i) !&
+ decomp_k(j,i_lig_lit,i) = k_l2_l3 * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * o_scalar(j,i) !&
+ decomp_k(j,i_soil1 ,i) = k_s1 * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * o_scalar(j,i) !&
+ decomp_k(j,i_soil2 ,i) = k_s2 * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * o_scalar(j,i) !&
+ decomp_k(j,i_soil3 ,i) = k_s3 * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * o_scalar(j,i) !&
+ ENDDO
+
+ DO j = 1,nl_soil
+ decomp_k(j,i_cwd,i) = k_frag * t_scalar(j,i) * w_scalar(j,i) * depth_scalar(j,i) * &
+ o_scalar(j,i)
+ ENDDO
+
+ END SUBROUTINE decomp_rate_constants_bgc
+
+END MODULE MOD_BGC_Soil_BiogeochemDecompCascadeBGC
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemLittVertTransp.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemLittVertTransp.F90
new file mode 100644
index 0000000000..27a2cb36e3
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemLittVertTransp.F90
@@ -0,0 +1,333 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemLittVertTransp
+
+!----------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! Simulate the soil and litter CN vertical mixing (diffusion and advection) processes. Solve the dynamics
+! of soil and litter vertical profile with a tridiagonal matrix.
+!
+! !REFERENCES:
+! Koven, C.D., Riley, W.J., Subin, Z.M., Tang, J.Y., Torn, M.S., Collins, W.D., Bonan, G.B., Lawrence,
+! D.M. and Swenson, S.C., 2013. The effect of vertically resolved soil biogeochemistry and alternate
+! soil C and N models on C dynamics of CLM4. Biogeosciences, 10(11), 7109-7131.
+! Thornton, P.E., Law, B.E., Gholz, H.L., Clark, K.L., Falge, E., Ellsworth, D.S., Goldstein, A.H., Monson,
+! R.K., Hollinger, D., Falk, M. and Chen, J., 2002. Modeling and measuring the effects of disturbance
+! history and climate on carbon and water budgets in evergreen needleleaf forests.
+! Agricultural and forest meteorology, 113(1-4), 185-222.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, 1) Revised the CLM5 code to be compatible with CoLM code structure.
+! 2) Record accumulated organic CN vertical transfer rates for semi-analytic spin-up.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ is_cwd, som_adv_flux, som_diffus, cryoturb_diffusion_k, max_altdepth_cryoturbation, max_depth_cryoturb
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ altmax, altmax_lastyear, som_adv_coef, som_diffus_coef, &
+ decomp_cpools_vr, decomp_npools_vr, &
+ diagVX_c_vr_acc, upperVX_c_vr_acc, lowerVX_c_vr_acc, &
+ diagVX_n_vr_acc, upperVX_n_vr_acc, lowerVX_n_vr_acc
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ decomp_cpools_sourcesink, decomp_npools_sourcesink, &
+ decomp_cpools_transport_tendency, decomp_npools_transport_tendency
+ USE MOD_Utils, only: tridia
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemLittVertTransp
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemLittVertTransp(i,deltim,nl_soil,nl_soil_full,ndecomp_pools,nbedrock,z_soi,zi_soi,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: nl_soil_full ! number of total soil layers plus bedrock layers
+ integer ,intent(in) :: ndecomp_pools ! number of total soil & litter pools in the decompositions
+ integer ,intent(in) :: nbedrock ! where bedrock layer starts
+ real(r8),intent(in) :: z_soi (1:nl_soil_full) ! depth of each soil layer (m)
+ real(r8),intent(in) :: zi_soi(0:nl_soil_full) ! interface level below a zsoi level (m)
+ real(r8),intent(in) :: dz_soi(1:nl_soil_full) ! thicknesses of each soil layer (m)
+
+ ! !LOCAL VARIABLES:
+ real(r8) :: diffus (1:nl_soil+1) ! diffusivity (m2/s) (includes spinup correction, if any)
+ real(r8) :: adv_flux(1:nl_soil+1) ! advective flux (m/s) (includes spinup correction, if any)
+ real(r8) :: aaa ! "A" function in Patankar
+ real(r8) :: pe ! Pe for "A" function in Patankar
+ real(r8) :: w_m1, w_p1 ! Weights for calculating harmonic mean of diffusivity
+ real(r8) :: d_m1, d_p1 ! Harmonic mean of diffusivity
+ real(r8) :: a_tri(0:nl_soil+1) ! "a" vector for tridiagonal matrix
+ real(r8) :: b_tri(0:nl_soil+1) ! "b" vector for tridiagonal matrix
+ real(r8) :: c_tri(0:nl_soil+1) ! "c" vector for tridiagonal matrix
+ real(r8) :: r_tri_c(0:nl_soil+1) ! "r" vector for tridiagonal solution for soil C
+ real(r8) :: r_tri_n(0:nl_soil+1) ! "r" vector for tridiagonal solution for soil N
+ real(r8) :: d_p1_zp1(1:nl_soil+1) ! diffusivity/delta_z for next j (set to zero for no diffusion)
+ real(r8) :: d_m1_zm1(1:nl_soil+1) ! diffusivity/delta_z for previous j (set to zero for no diffusion)
+ real(r8) :: f_p1(1:nl_soil+1) ! water flux for next j
+ real(r8) :: f_m1(1:nl_soil+1) ! water flux for previous j
+ real(r8) :: pe_p1(1:nl_soil+1) ! Peclet # for next j
+ real(r8) :: pe_m1(1:nl_soil+1) ! Peclet # for previous j
+ real(r8) :: dz_node(1:nl_soil+1) ! difference between nodes
+ real(r8) :: conc_trcr_c(0:nl_soil+1) ! dummy term
+ real(r8) :: conc_trcr_n(0:nl_soil+1) ! dummy term
+ real(r8) :: a_p_0
+ integer :: s,j,l ! indices
+ integer :: jtop ! top level at each column
+ real(r8) :: spinup_term ! spinup accelerated decomposition factor, used to accelerate transport as well
+ real(r8) :: epsilon ! small number
+
+ aaa (pe) = max (0._r8, (1._r8 - 0.1_r8 * abs(pe))**5) ! A function from Patankar, Table 5.2, pg 95
+
+ epsilon = 1.e-30
+ spinup_term = 1._r8
+
+ IF (( max(altmax(i), altmax_lastyear(i)) <= max_altdepth_cryoturbation ) .and. &
+ ( max(altmax(i), altmax_lastyear(i)) > 0._r8) ) THEN
+ ! use mixing profile modified slightly from Koven et al. (2009): constant through active layer, linear decrease from base of active layer to zero at a fixed depth
+ DO j = 1,nl_soil+1
+ IF ( j <= nbedrock+1 ) THEN
+ IF ( zi_soi(j) < max(altmax(i), altmax_lastyear(i)) ) THEN
+ som_diffus_coef(j,i) = cryoturb_diffusion_k
+ som_adv_coef(j,i) = 0._r8
+ ELSE
+ som_diffus_coef(j,i) = max(cryoturb_diffusion_k * &
+ ( 1._r8 - ( zi_soi(j) - max(altmax(i), altmax_lastyear(i)) ) / &
+ ( min(max_depth_cryoturb, zi_soi(nbedrock+1)) - max(altmax(i), altmax_lastyear(i)) ) ), 0._r8) ! go linearly to zero between ALT and max_depth_cryoturb
+ som_adv_coef(j,i) = 0._r8
+ ENDIF
+ ELSE
+ som_adv_coef(j,i) = 0._r8
+ som_diffus_coef(j,i) = 0._r8
+ ENDIF
+ ENDDO
+ ELSEIF ( max(altmax(i), altmax_lastyear(i)) > 0._r8 ) THEN
+ ! constant advection, constant diffusion
+ DO j = 1,nl_soil+1
+ IF ( j <= nbedrock+1 ) THEN
+ som_adv_coef(j,i) = som_adv_flux
+ som_diffus_coef(j,i) = som_diffus
+ ELSE
+ som_adv_coef(j,i) = 0._r8
+ som_diffus_coef(j,i) = 0._r8
+ ENDIF
+ ENDDO
+ ELSE
+ ! completely frozen soils--no mixing
+ DO j = 1,nl_soil+1
+ som_adv_coef(j,i) = 0._r8
+ som_diffus_coef(j,i) = 0._r8
+ ENDDO
+ ENDIF
+
+ ! Set the distance between the node and the one ABOVE it
+ dz_node(1) = z_soi(1)
+ DO j = 2, nl_soil+1
+ dz_node(j)= z_soi(j) - z_soi(j-1)
+ ENDDO
+
+ DO s = 1, ndecomp_pools
+ IF ( .not. is_cwd(s) ) THEN
+ DO j = 1,nl_soil+1
+ IF ( abs(som_adv_coef(j,i)) * spinup_term < epsilon ) THEN
+ adv_flux(j) = epsilon
+ ELSE
+ adv_flux(j) = som_adv_coef(j,i) * spinup_term
+ ENDIF
+ !
+ IF ( abs(som_diffus_coef(j,i)) * spinup_term < epsilon ) THEN
+ diffus(j) = epsilon
+ ELSE
+ diffus(j) = som_diffus_coef(j,i) * spinup_term
+ ENDIF
+ !
+ ENDDO
+
+ ! Set Pe (Peclet #) and D/dz throughout column
+ conc_trcr_c(0) = 0._r8
+ conc_trcr_n(0) = 0._r8
+ conc_trcr_c(nbedrock+1:nl_soil+1) = 0._r8
+ conc_trcr_n(nbedrock+1:nl_soil+1) = 0._r8
+
+ DO j = 1,nl_soil+1
+ conc_trcr_c(j) = decomp_cpools_vr(j,s,i)
+ conc_trcr_n(j) = decomp_npools_vr(j,s,i)
+
+ ! dz_tracer below is the difference between gridcell edges (dz_soi)
+ ! dz_node_tracer is difference between cell centers
+
+ ! Calculate the D and F terms in the Patankar algorithm
+ IF (j == 1) THEN
+ d_m1_zm1(j) = 0._r8
+ w_p1 = (z_soi(j+1) - zi_soi(j)) / dz_node(j+1)
+ IF ( diffus(j+1) > 0._r8 .and. diffus(j) > 0._r8) THEN
+ d_p1 = 1._r8 / ((1._r8 - w_p1) / diffus(j) + w_p1 / diffus(j+1)) ! Harmonic mean of diffus
+ ELSE
+ d_p1 = 0._r8
+ ENDIF
+ d_p1_zp1(j) = d_p1 / dz_node(j+1)
+ f_m1(j) = adv_flux(j) ! Include infiltration here
+ f_p1(j) = adv_flux(j+1)
+ pe_m1(j) = 0._r8
+ pe_p1(j) = f_p1(j) / d_p1_zp1(j) ! Peclet #
+ ELSEIF (j >= nbedrock+1) THEN
+ ! At the bottom, assume no gradient in d_z (i.e., they're the same)
+ w_m1 = (zi_soi(j-1) - z_soi(j-1)) / dz_node(j)
+ IF ( diffus(j) > 0._r8 .and. diffus(j-1) > 0._r8) THEN
+ d_m1 = 1._r8 / ((1._r8 - w_m1) / diffus(j) + w_m1 / diffus(j-1)) ! Harmonic mean of diffus
+ ELSE
+ d_m1 = 0._r8
+ ENDIF
+ d_m1_zm1(j) = d_m1 / dz_node(j)
+ d_p1_zp1(j) = d_m1_zm1(j) ! Set to be the same
+ f_m1(j) = adv_flux(j)
+ f_p1(j) = 0._r8
+ pe_m1(j) = f_m1(j) / d_m1_zm1(j) ! Peclet #
+ pe_p1(j) = f_p1(j) / d_p1_zp1(j) ! Peclet #
+ ELSE
+ ! Use distance from j-1 node to interface with j divided by distance between nodes
+ w_m1 = (zi_soi(j-1) - z_soi(j-1)) / dz_node(j)
+ IF ( diffus(j-1) > 0._r8 .and. diffus(j) > 0._r8) THEN
+ d_m1 = 1._r8 / ((1._r8 - w_m1) / diffus(j) + w_m1 / diffus(j-1)) ! Harmonic mean of diffus
+ ELSE
+ d_m1 = 0._r8
+ ENDIF
+ w_p1 = (z_soi(j+1) - zi_soi(j)) / dz_node(j+1)
+ IF ( diffus(j+1) > 0._r8 .and. diffus(j) > 0._r8) THEN
+ d_p1 = 1._r8 / ((1._r8 - w_p1) / diffus(j) + w_p1 / diffus(j+1)) ! Harmonic mean of diffus
+ ELSE
+ d_p1 = (1._r8 - w_p1) * diffus(j) + w_p1 * diffus(j+1) ! Arithmetic mean of diffus
+ ENDIF
+ d_m1_zm1(j) = d_m1 / dz_node(j)
+ d_p1_zp1(j) = d_p1 / dz_node(j+1)
+ f_m1(j) = adv_flux(j)
+ f_p1(j) = adv_flux(j+1)
+ pe_m1(j) = f_m1(j) / d_m1_zm1(j) ! Peclet #
+ pe_p1(j) = f_p1(j) / d_p1_zp1(j) ! Peclet #
+ ENDIF
+ ENDDO ! j; nl_soil
+
+ ! Calculate the tridiagonal coefficients
+ DO j = 0,nl_soil +1
+
+ IF (j > 0 .and. j < nl_soil+1) THEN
+ a_p_0 = dz_soi(j) / deltim
+ ENDIF
+
+ IF (j == 0) THEN ! top layer (atmosphere)
+ a_tri(j) = 0._r8
+ b_tri(j) = 1._r8
+ c_tri(j) = -1._r8
+ r_tri_c(j) = 0._r8
+ r_tri_n(j) = 0._r8
+ ELSEIF (j == 1) THEN
+ a_tri(j) = -(d_m1_zm1(j) * aaa(pe_m1(j)) + max( f_m1(j), 0._r8)) ! Eqn 5.47 Patankar
+ c_tri(j) = -(d_p1_zp1(j) * aaa(pe_p1(j)) + max(-f_p1(j), 0._r8))
+ b_tri(j) = - a_tri(j) - c_tri(j) + a_p_0
+ r_tri_c(j) = decomp_cpools_sourcesink(j,s,i) * dz_soi(j) /deltim + (a_p_0 - adv_flux(j)) * conc_trcr_c(j)
+ r_tri_n(j) = decomp_npools_sourcesink(j,s,i) * dz_soi(j) /deltim + (a_p_0 - adv_flux(j)) * conc_trcr_n(j)
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ upperVX_c_vr_acc(j,s,i) = upperVX_c_vr_acc(j,s,i) - c_tri(j) / dz_soi(j) * deltim * conc_trcr_c(j+1)! upwards transfer
+ diagVX_c_vr_acc (j,s,i) = diagVX_c_vr_acc (j,s,i) - c_tri(j) / dz_soi(j) * deltim * conc_trcr_c(j)! EXIT flux
+ upperVX_n_vr_acc(j,s,i) = upperVX_n_vr_acc(j,s,i) - c_tri(j) / dz_soi(j) * deltim * conc_trcr_n(j+1)! upwards transfer
+ diagVX_n_vr_acc (j,s,i) = diagVX_n_vr_acc (j,s,i) - c_tri(j) / dz_soi(j) * deltim * conc_trcr_n(j)! EXIT flux
+ ENDIF
+ ELSEIF (j < nl_soil+1) THEN
+
+ a_tri(j) = -(d_m1_zm1(j) * aaa(pe_m1(j)) + max( f_m1(j), 0._r8)) ! Eqn 5.47 Patankar
+ c_tri(j) = -(d_p1_zp1(j) * aaa(pe_p1(j)) + max(-f_p1(j), 0._r8))
+ b_tri(j) = - a_tri(j) - c_tri(j) + a_p_0
+ r_tri_c(j) = decomp_cpools_sourcesink(j,s,i) * dz_soi(j) /deltim + a_p_0 * conc_trcr_c(j)
+ r_tri_n(j) = decomp_npools_sourcesink(j,s,i) * dz_soi(j) /deltim + a_p_0 * conc_trcr_n(j)
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ IF(j .le. nbedrock)THEN
+ lowerVX_c_vr_acc(j,s,i) = lowerVX_c_vr_acc(j,s,i) - a_tri(j) / dz_soi(j) * deltim * conc_trcr_c(j-1)
+ lowerVX_n_vr_acc(j,s,i) = lowerVX_n_vr_acc(j,s,i) - a_tri(j) / dz_soi(j) * deltim * conc_trcr_n(j-1)
+ IF(j .ne. nl_soil)THEN
+ upperVX_c_vr_acc(j,s,i) = upperVX_c_vr_acc(j,s,i) - c_tri(j) / dz_soi(j) * deltim * conc_trcr_c(j+1)
+ upperVX_n_vr_acc(j,s,i) = upperVX_n_vr_acc(j,s,i) - c_tri(j) / dz_soi(j) * deltim * conc_trcr_n(j+1)
+ diagVX_c_vr_acc(j,s,i) = diagVX_c_vr_acc(j,s,i) + (b_tri(j) - a_p_0) / dz_soi(j) * deltim * conc_trcr_c(j)
+ diagVX_n_vr_acc(j,s,i) = diagVX_n_vr_acc(j,s,i) + (b_tri(j) - a_p_0) / dz_soi(j) * deltim * conc_trcr_n(j)
+ ELSE
+ diagVX_c_vr_acc(j,s,i) = diagVX_c_vr_acc (j,s,i) - a_tri(j) / dz_soi(j) * deltim * conc_trcr_c(j)
+ diagVX_n_vr_acc(j,s,i) = diagVX_n_vr_acc (j,s,i) - a_tri(j) / dz_soi(j) * deltim * conc_trcr_n(j)
+ ENDIF
+ ELSE
+ IF(j .eq. nbedrock + 1 .and. j .ne. nl_soil .and. j .gt. 1)THEN
+ diagVX_c_vr_acc(j-1,s,i) = diagVX_c_vr_acc(j-1,s,i) + a_tri(j) / dz_soi(j-1) * deltim * conc_trcr_c(j-1)
+ diagVX_n_vr_acc(j-1,s,i) = diagVX_n_vr_acc(j-1,s,i) + a_tri(j) / dz_soi(j-1) * deltim * conc_trcr_n(j-1)
+ ENDIF
+ ENDIF
+ ENDIF
+ ELSE ! j==nl_soil+1; 0 concentration gradient at bottom
+ a_tri(j) = -1._r8
+ b_tri(j) = 1._r8
+ c_tri(j) = 0._r8
+ r_tri_c(j) = 0._r8
+ r_tri_n(j) = 0._r8
+ ENDIF
+ ENDDO ! j; nl_soil
+
+ jtop = 0
+
+ ! subtract initial concentration and source terms for tendency calculation
+ DO j = 1, nl_soil
+ decomp_cpools_transport_tendency(j,s,i) = 0.-(conc_trcr_c(j) + decomp_cpools_sourcesink(j,s,i))
+ decomp_npools_transport_tendency(j,s,i) = 0.-(conc_trcr_n(j) + decomp_npools_sourcesink(j,s,i))
+ ENDDO
+
+ CALL tridia(nl_soil+2, a_tri (:), b_tri(:), c_tri(:), r_tri_c(:), conc_trcr_c(0:nl_soil+1))
+ CALL tridia(nl_soil+2, a_tri (:), b_tri(:), c_tri(:), r_tri_n(:), conc_trcr_n(0:nl_soil+1))
+
+ ! add post-transport concentration to calculate tendency term
+ DO j = 1, nl_soil
+ decomp_cpools_transport_tendency(j,s,i) = decomp_cpools_transport_tendency(j,s,i) + conc_trcr_c(j)
+ decomp_cpools_transport_tendency(j,s,i) = decomp_cpools_transport_tendency(j,s,i) / deltim
+ decomp_npools_transport_tendency(j,s,i) = decomp_npools_transport_tendency(j,s,i) + conc_trcr_n(j)
+ decomp_npools_transport_tendency(j,s,i) = decomp_npools_transport_tendency(j,s,i) / deltim
+ ENDDO
+ ELSE
+ ! for CWD pools, just add
+ DO j = 1,nl_soil
+ conc_trcr_c(j) = decomp_cpools_vr(j,s,i) + decomp_cpools_sourcesink(j,s,i)
+ conc_trcr_n(j) = decomp_npools_vr(j,s,i) + decomp_npools_sourcesink(j,s,i)
+ IF (j > nbedrock .and. decomp_cpools_sourcesink(j,s,i) > 0._r8) THEN
+ write(*,*) 'C source >0',i,j,s,decomp_cpools_sourcesink(j,s,i)
+ ENDIF
+ IF (j > nbedrock .and. decomp_cpools_vr(j,s,i) > 0._r8) THEN
+ write(*,*) 'C conc_ptr >0',i,j,s,decomp_cpools_vr(j,s,i)
+ ENDIF
+ IF (j > nbedrock .and. decomp_npools_sourcesink(j,s,i) > 0._r8) THEN
+ write(*,*) 'N source >0',i,j,s,decomp_npools_sourcesink(j,s,i)
+ ENDIF
+ IF (j > nbedrock .and. decomp_npools_vr(j,s,i) > 0._r8) THEN
+ write(*,*) 'N conc_ptr >0',i,j,s,decomp_npools_vr(j,s,i)
+ ENDIF
+ ENDDO
+ ENDIF ! not CWD
+
+ DO j = 1,nl_soil
+ decomp_cpools_vr(j,s,i) = conc_trcr_c(j)
+ decomp_npools_vr(j,s,i) = conc_trcr_n(j)
+ ! Correct for small amounts of carbon that leak into bedrock
+ IF (j > nbedrock) THEN
+ decomp_cpools_vr(nbedrock,s,i) = decomp_cpools_vr(nbedrock,s,i) + &
+ conc_trcr_c(j) * (dz_soi(j) / dz_soi(nbedrock))
+ decomp_cpools_vr(j,s,i) = 0._r8
+ decomp_npools_vr(nbedrock,s,i) = decomp_npools_vr(nbedrock,s,i) + &
+ conc_trcr_n(j) * (dz_soi(j) / dz_soi(nbedrock))
+ decomp_npools_vr(j,s,i) = 0._r8
+ ENDIF
+ ENDDO
+ ENDDO ! s (pool loop)
+
+ END SUBROUTINE SoilBiogeochemLittVertTransp
+
+END MODULE MOD_BGC_Soil_BiogeochemLittVertTransp
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNLeaching.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNLeaching.F90
new file mode 100644
index 0000000000..d5f322a15c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNLeaching.F90
@@ -0,0 +1,167 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_Soil_BiogeochemNLeaching
+
+!----------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This module calculates the soil mineral N loss due to leaching. The leaching flux is a function of
+! dissolved N concentration and sub-surface drainage flux.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised original CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_NITRIF
+ USE MOD_BGC_Vars_TimeInvariants, only: sf, sf_no3
+ USE MOD_Vars_TimeVariables, only: wliq_soisno
+ USE MOD_BGC_Vars_TimeVariables, only: sminn_vr, smin_no3_vr
+ USE MOD_Vars_1DFluxes, only: rnof, rsur
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ sminn_leached_vr, smin_no3_leached_vr, smin_no3_runoff_vr
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemNLeaching
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemNLeaching(i,deltim,nl_soil,zi_soi,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: zi_soi(0:nl_soil) ! interface level below a zsoi level (m)
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+
+ integer :: j ! indices
+ real(r8) :: disn_conc ! dissolved mineral N concentration (gN/kg water)
+ real(r8) :: tot_water ! total column liquid water (kg water/m2)
+ real(r8) :: surface_water ! liquid water to shallow surface depth (kg water/m2)
+ real(r8) :: drain_tot ! total drainage flux (mm H2O /s)
+ real(r8), parameter :: depth_runoff_Nloss = 0.05 ! (m) depth over which runoff mixes with soil water for N loss to runoff
+
+ ! calculate the total soil water
+ tot_water = 0._r8
+ DO j = 1,nl_soil
+ tot_water = tot_water + wliq_soisno(j,i)
+ ENDDO
+
+ ! for runoff calculation; calculate total water to a given depth
+ surface_water = 0._r8
+ DO j = 1,nl_soil
+ IF ( zi_soi(j) <= depth_runoff_Nloss) THEN
+ surface_water = surface_water + wliq_soisno(j,i)
+ elseif ( zi_soi(j-1) < depth_runoff_Nloss) THEN
+ surface_water = surface_water + wliq_soisno(j,i) * ( (depth_runoff_Nloss - zi_soi(j-1)) / dz_soi(j))
+ ENDIF
+ ENDDO
+
+ ! Loop through columns
+ drain_tot = rnof(i) - rsur(i)
+
+
+ IF(.not. DEF_USE_NITRIF)THEN
+ !----------------------------------------
+ ! --------- NITRIF_NITRIF OFF------------
+ !----------------------------------------
+ DO j = 1,nl_soil
+ ! calculate the dissolved mineral N concentration (gN/kg water)
+ ! assumes that 10% of mineral nitrogen is soluble
+ disn_conc = 0._r8
+ IF (wliq_soisno(j,i) > 0._r8) THEN
+ disn_conc = (sf * sminn_vr(j,i) * dz_soi(j) )/(wliq_soisno(j,i) )
+ ENDIF
+
+ ! calculate the N leaching flux as a FUNCTION of the dissolved
+ ! concentration and the sub-surface drainage flux
+ IF(tot_water > 0._r8)THEN
+ sminn_leached_vr(j,i) = disn_conc * drain_tot * wliq_soisno(j,i) / ( tot_water * dz_soi(j) )
+ ELSE
+ sminn_leached_vr(j,i) = 0._r8
+ ENDIF
+
+ ! limit the flux based on current sminn state
+ ! only let at most the assumed soluble fraction
+ ! of sminn be leached on any given timestep
+ sminn_leached_vr(j,i) = min(sminn_leached_vr(j,i), (sf * sminn_vr(j,i))/deltim)
+
+ ! limit the flux to a positive value
+ sminn_leached_vr(j,i) = max(sminn_leached_vr(j,i), 0._r8)
+
+ ENDDO
+
+ ELSE
+
+ !----------------------------------------
+ ! --------- NITRIF_NITRIF ON-------------
+ !----------------------------------------
+
+ DO j = 1,nl_soil
+ ! calculate the dissolved mineral N concentration (gN/kg water)
+ ! assumes that 10% of mineral nitrogen is soluble
+ disn_conc = 0._r8
+ IF (wliq_soisno(j,i) > 0._r8) THEN
+ disn_conc = (sf_no3 * smin_no3_vr(j,i) * dz_soi(j) )/(wliq_soisno(j,i) )
+ ENDIF
+ !
+ ! calculate the N leaching flux as a FUNCTION of the dissolved
+ ! concentration and the sub-surface drainage flux
+ IF(tot_water > 0._r8)THEN
+ smin_no3_leached_vr(j,i) = disn_conc * drain_tot * wliq_soisno(j,i) / ( tot_water * dz_soi(j) )
+ ELSE
+ smin_no3_leached_vr(j,i) = 0._r8
+ ENDIF
+ !
+ ! ensure that leaching rate isn't larger than soil N pool
+ smin_no3_leached_vr(j,i) = min(smin_no3_leached_vr(j,i), smin_no3_vr(j,i) / deltim )
+ !
+ ! limit the leaching flux to a positive value
+ smin_no3_leached_vr(j,i) = max(smin_no3_leached_vr(j,i), 0._r8)
+ !
+ !
+ ! calculate the N loss from surface runoff, assuming a shallow mixing of surface waters into soil and removal based on runoff
+ IF ( zi_soi(j) <= depth_runoff_Nloss ) THEN
+ IF(surface_water > 0._r8)THEN
+ smin_no3_runoff_vr(j,i) = disn_conc * rsur(i) * &
+ wliq_soisno(j,i) / ( surface_water * dz_soi(j) )
+ ELSE
+ smin_no3_runoff_vr(j,i) = 0._r8
+ ENDIF
+ ELSEIF ( zi_soi(j-1) < depth_runoff_Nloss ) THEN
+ IF(surface_water > 0._r8)THEN
+ smin_no3_runoff_vr(j,i) = disn_conc * rsur(i) * &
+ wliq_soisno(j,i) * ((depth_runoff_Nloss - zi_soi(j-1)) / &
+ dz_soi(j)) / ( surface_water * (depth_runoff_Nloss-zi_soi(j-1) ))
+ ELSE
+ smin_no3_runoff_vr(j,i) = 0._r8
+ ENDIF
+ ELSE
+ smin_no3_runoff_vr(j,i) = 0._r8
+ ENDIF
+ !
+ ! ensure that runoff rate isn't larger than soil N pool
+ smin_no3_runoff_vr(j,i) = min(smin_no3_runoff_vr(j,i), smin_no3_vr(j,i) / deltim - smin_no3_leached_vr(j,i))
+ !
+ ! limit the flux to a positive value
+ smin_no3_runoff_vr(j,i) = max(smin_no3_runoff_vr(j,i), 0._r8)
+
+
+ ! limit the flux based on current smin_no3 state
+ ! only let at most the assumed soluble fraction
+ ! of smin_no3 be leached on any given timestep
+ smin_no3_leached_vr(j,i) = min(smin_no3_leached_vr(j,i), (sf_no3 * smin_no3_vr(j,i))/deltim)
+
+ ! limit the flux to a positive value
+ smin_no3_leached_vr(j,i) = max(smin_no3_leached_vr(j,i), 0._r8)
+
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE SoilBiogeochemNLeaching
+
+END MODULE MOD_BGC_Soil_BiogeochemNLeaching
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNStateUpdate1.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNStateUpdate1.F90
new file mode 100644
index 0000000000..aa07e6c7c3
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNStateUpdate1.F90
@@ -0,0 +1,244 @@
+#include
+#ifdef BGC
+
+MODULE MOD_BGC_Soil_BiogeochemNStateUpdate1
+
+!---------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! Updates soil mineral nitrogen pool sizes. The dynamics of soil mineral nitrogen pool is
+! simulated according to fertilisation, nitrogen deposition, biological fixation, plant uptake,
+! mineralisation and immobilisation in this module. IF nitrification is activated, nitrate nitrogen
+! has a separated pool against ammonium nitrogen pool. Accumulated nitrogen transfer
+! network is also recorded for semi-analytic spinup.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2022, 1) modify original CLM5 to be compatible with CoLM code structure.
+! 2) Record accumulated nitrogen transfer network for semi-analytic spinup
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix, DEF_USE_NITRIF, DEF_USE_CNSOYFIXN
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ ! bgc constants
+ i_met_lit, i_cel_lit, i_lig_lit, i_cwd, i_soil1, i_soil2, i_soil3
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ receiver_pool, donor_pool, nitrif_n2o_loss_frac
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! Mineral nitrogen pools (inout)
+ sminn_vr , smin_nh4_vr , smin_no3_vr , &
+ ndep_prof , nfixation_prof , &
+ AKX_met_to_soil1_n_vr_acc , AKX_cel_to_soil1_n_vr_acc , AKX_lig_to_soil2_n_vr_acc , AKX_soil1_to_soil2_n_vr_acc, &
+ AKX_cwd_to_cel_n_vr_acc , AKX_cwd_to_lig_n_vr_acc , AKX_soil1_to_soil3_n_vr_acc, AKX_soil2_to_soil1_n_vr_acc, &
+ AKX_soil2_to_soil3_n_vr_acc, AKX_soil3_to_soil1_n_vr_acc, &
+ AKX_met_exit_n_vr_acc , AKX_cel_exit_n_vr_acc , AKX_lig_exit_n_vr_acc , AKX_cwd_exit_n_vr_acc , &
+ AKX_soil1_exit_n_vr_acc , AKX_soil2_exit_n_vr_acc , AKX_soil3_exit_n_vr_acc
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ ! Decomposition fluxes variables (inout)
+ decomp_npools_sourcesink, decomp_ntransfer_vr , decomp_sminn_flux_vr , sminn_to_denit_decomp_vr, &
+ gross_nmin_vr , actual_immob_nh4_vr , actual_immob_no3_vr , &
+ sminn_to_plant_vr , smin_nh4_to_plant_vr , smin_no3_to_plant_vr , supplement_to_sminn_vr, &
+ sminn_to_plant_fun_vr , sminn_to_plant_fun_nh4_vr, sminn_to_plant_fun_no3_vr, &
+ sminn_to_denit_excess_vr, f_nit_vr , f_denit_vr , soyfixn_to_sminn, &
+ ndep_to_sminn , ffix_to_sminn , nfix_to_sminn , fert_to_sminn
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemNStateUpdate1
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemNStateUpdate1(i,deltim,nl_soil,ndecomp_transitions,dz_soi)
+
+ integer ,intent(in) :: i ! patch idnex
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ndecomp_transitions! number of total transfers between soil and litter pools in the decomposition
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer (m)
+
+ integer j,k
+ real(r8):: sminflux,minerflux
+
+ IF(.not. DEF_USE_NITRIF)THEN
+ DO j = 1, nl_soil
+ ! N deposition and fixation
+ sminn_vr(j,i) = sminn_vr(j,i) + ndep_to_sminn(i)*deltim * ndep_prof(j,i)
+ sminn_vr(j,i) = sminn_vr(j,i) + nfix_to_sminn(i)*deltim * nfixation_prof(j,i)
+ ENDDO
+ ELSE
+ DO j = 1, nl_soil
+ ! N deposition and fixation (put all into NH4 pool)
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) + ndep_to_sminn(i)*deltim * ndep_prof(j,i)
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) + nfix_to_sminn(i)*deltim * nfixation_prof(j,i)
+ ENDDO
+ ENDIF
+
+ ! repeating N dep and fixation for crops
+#ifdef CROP
+ IF(.not. DEF_USE_NITRIF)THEN
+ DO j = 1, nl_soil
+ ! column loop
+ ! N deposition and fixation
+ sminn_vr(j,i) = sminn_vr(j,i) &
+ + fert_to_sminn(i) * deltim * ndep_prof(j,i)
+ ENDDO
+ IF(DEF_USE_CNSOYFIXN)THEN
+ DO j = 1, nl_soil
+ sminn_vr(j,i) = sminn_vr(j,i) &
+ + soyfixn_to_sminn(i) * deltim * nfixation_prof(j,i)
+ ENDDO
+ ENDIF
+ ELSE
+ DO j = 1, nl_soil
+ ! N deposition and fixation (put all into NH4 pool)
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) &
+ + fert_to_sminn(i) * deltim * ndep_prof(j,i)
+ ENDDO
+ IF(DEF_USE_CNSOYFIXN)THEN
+ DO j = 1, nl_soil
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) &
+ + soyfixn_to_sminn(i) * deltim * nfixation_prof(j,i)
+ ENDDO
+ ENDIF
+ ENDIF
+#endif
+
+ ! decomposition fluxes
+ DO k = 1, ndecomp_transitions
+ DO j = 1, nl_soil
+ decomp_npools_sourcesink(j,donor_pool(k),i) = &
+ decomp_npools_sourcesink(j,donor_pool(k),i) - &
+ decomp_ntransfer_vr(j,k,i) * deltim
+ ENDDO
+ ENDDO
+
+
+ DO k = 1, ndecomp_transitions
+ IF ( receiver_pool(k) /= 0 ) THEN ! skip terminal transitions
+ DO j = 1, nl_soil
+ decomp_npools_sourcesink(j,receiver_pool(k),i) = &
+ decomp_npools_sourcesink(j,receiver_pool(k),i) + &
+ (decomp_ntransfer_vr(j,k,i) + &
+ decomp_sminn_flux_vr(j,k,i)) * deltim
+ ENDDO
+ ELSE ! terminal transitions
+ DO j = 1, nl_soil
+ decomp_npools_sourcesink(j,donor_pool(k),i) = &
+ decomp_npools_sourcesink(j,donor_pool(k),i) - &
+ decomp_sminn_flux_vr(j,k,i) * deltim
+ ENDDO
+ ENDIF
+ ENDDO
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ DO j = 1, nl_soil
+ AKX_met_to_soil1_n_vr_acc (j,i) = AKX_met_to_soil1_n_vr_acc (j,i) + (decomp_ntransfer_vr(j, 1,i) + decomp_sminn_flux_vr(j, 1,i)) * deltim
+ AKX_cel_to_soil1_n_vr_acc (j,i) = AKX_cel_to_soil1_n_vr_acc (j,i) + (decomp_ntransfer_vr(j, 2,i) + decomp_sminn_flux_vr(j, 2,i)) * deltim
+ AKX_lig_to_soil2_n_vr_acc (j,i) = AKX_lig_to_soil2_n_vr_acc (j,i) + (decomp_ntransfer_vr(j, 3,i) + decomp_sminn_flux_vr(j, 3,i)) * deltim
+ AKX_soil1_to_soil2_n_vr_acc(j,i) = AKX_soil1_to_soil2_n_vr_acc(j,i) + (decomp_ntransfer_vr(j, 4,i) + decomp_sminn_flux_vr(j, 4,i)) * deltim
+ AKX_cwd_to_cel_n_vr_acc (j,i) = AKX_cwd_to_cel_n_vr_acc (j,i) + (decomp_ntransfer_vr(j, 5,i) + decomp_sminn_flux_vr(j, 5,i)) * deltim
+ AKX_cwd_to_lig_n_vr_acc (j,i) = AKX_cwd_to_lig_n_vr_acc (j,i) + (decomp_ntransfer_vr(j, 6,i) + decomp_sminn_flux_vr(j, 6,i)) * deltim
+ AKX_soil1_to_soil3_n_vr_acc(j,i) = AKX_soil1_to_soil3_n_vr_acc(j,i) + (decomp_ntransfer_vr(j, 7,i) + decomp_sminn_flux_vr(j, 7,i)) * deltim
+ AKX_soil2_to_soil1_n_vr_acc(j,i) = AKX_soil2_to_soil1_n_vr_acc(j,i) + (decomp_ntransfer_vr(j, 8,i) + decomp_sminn_flux_vr(j, 8,i)) * deltim
+ AKX_soil2_to_soil3_n_vr_acc(j,i) = AKX_soil2_to_soil3_n_vr_acc(j,i) + (decomp_ntransfer_vr(j, 9,i) + decomp_sminn_flux_vr(j, 9,i)) * deltim
+ AKX_soil3_to_soil1_n_vr_acc(j,i) = AKX_soil3_to_soil1_n_vr_acc(j,i) + (decomp_ntransfer_vr(j,10,i) + decomp_sminn_flux_vr(j,10,i)) * deltim
+
+ AKX_met_exit_n_vr_acc (j,i) = AKX_met_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 1,i) * deltim
+ AKX_cel_exit_n_vr_acc (j,i) = AKX_cel_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 2,i) * deltim
+ AKX_lig_exit_n_vr_acc (j,i) = AKX_lig_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 3,i) * deltim
+ AKX_soil1_exit_n_vr_acc (j,i) = AKX_soil1_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 4,i) * deltim
+ AKX_cwd_exit_n_vr_acc (j,i) = AKX_cwd_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 5,i) * deltim
+ AKX_cwd_exit_n_vr_acc (j,i) = AKX_cwd_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 6,i) * deltim
+ AKX_soil1_exit_n_vr_acc (j,i) = AKX_soil1_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 7,i) * deltim
+ AKX_soil2_exit_n_vr_acc (j,i) = AKX_soil2_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 8,i) * deltim
+ AKX_soil2_exit_n_vr_acc (j,i) = AKX_soil2_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j, 9,i) * deltim
+ AKX_soil3_exit_n_vr_acc (j,i) = AKX_soil3_exit_n_vr_acc (j,i) + decomp_ntransfer_vr(j,10,i) * deltim
+ ENDDO
+ ENDIF
+
+ IF(.not. DEF_USE_NITRIF)THEN
+
+ !--------------------------------------------------------
+ !------------- NITRIF_DENITRIF OFF -------------------
+ !--------------------------------------------------------
+
+ ! immobilization/mineralization in litter-to-SOM and SOM-to-SOM fluxes and denitrification fluxes
+ DO k = 1, ndecomp_transitions
+ IF ( receiver_pool(k) /= 0 ) THEN ! skip terminal transitions
+ DO j = 1, nl_soil
+ sminn_vr(j,i) = sminn_vr(j,i) - &
+ (sminn_to_denit_decomp_vr(j,k,i) + &
+ decomp_sminn_flux_vr(j,k,i))* deltim
+ ENDDO
+ ELSE
+ DO j = 1, nl_soil
+ sminn_vr(j,i) = sminn_vr(j,i) - &
+ sminn_to_denit_decomp_vr(j,k,i)* deltim
+
+ sminn_vr(j,i) = sminn_vr(j,i) + &
+ decomp_sminn_flux_vr(j,k,i)* deltim
+
+ ENDDO
+ ENDIF
+ ENDDO
+
+
+ DO j = 1, nl_soil
+ ! "bulk denitrification"
+ sminn_vr(j,i) = sminn_vr(j,i) - sminn_to_denit_excess_vr(j,i) * deltim
+
+ ! total plant uptake from mineral N
+ sminn_vr(j,i) = sminn_vr(j,i) - sminn_to_plant_vr(j,i)*deltim
+ ! flux that prevents N limitation (when Carbon_only is set)
+ sminn_vr(j,i) = sminn_vr(j,i) + supplement_to_sminn_vr(j,i)*deltim
+ ENDDO
+
+ ELSE
+
+ !--------------------------------------------------------
+ !------------- NITRIF_DENITRIF ON --------------------
+ !--------------------------------------------------------
+
+ DO j = 1, nl_soil
+
+ ! mineralization fluxes (divert a fraction of this stream to nitrification flux, add the rest to NH4 pool)
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) + gross_nmin_vr(j,i)*deltim
+
+ ! immobilization fluxes
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) - actual_immob_nh4_vr(j,i)*deltim
+
+ smin_no3_vr(j,i) = smin_no3_vr(j,i) - actual_immob_no3_vr(j,i)*deltim
+
+ ! plant uptake fluxes
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) - smin_nh4_to_plant_vr(j,i)*deltim
+
+ smin_no3_vr(j,i) = smin_no3_vr(j,i) - smin_no3_to_plant_vr(j,i)*deltim
+
+
+ ! Account for nitrification fluxes
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) - f_nit_vr(j,i) * deltim
+
+ smin_no3_vr(j,i) = smin_no3_vr(j,i) + f_nit_vr(j,i) * deltim &
+ * (1._r8 - nitrif_n2o_loss_frac)
+
+ ! Account for denitrification fluxes
+ smin_no3_vr(j,i) = smin_no3_vr(j,i) - f_denit_vr(j,i) * deltim
+
+ ! flux that prevents N limitation (when Carbon_only is set; put all into NH4)
+ smin_nh4_vr(j,i) = smin_nh4_vr(j,i) + supplement_to_sminn_vr(j,i)*deltim
+
+ ! update diagnostic total
+ sminn_vr(j,i) = smin_nh4_vr(j,i) + smin_no3_vr(j,i)
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE SoilBiogeochemNStateUpdate1
+
+END MODULE MOD_BGC_Soil_BiogeochemNStateUpdate1
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNitrifDenitrif.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNitrifDenitrif.F90
new file mode 100644
index 0000000000..54a1f5ec02
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemNitrifDenitrif.F90
@@ -0,0 +1,186 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemNitrifDenitrif
+
+!--------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate the potential nitrification and dentrification rate.
+!
+! !REFERENCES:
+! Parton, W. et al. 1996. Generalized model for N2 and N2O production from nitrification and
+! denitrification. Global Biogeochemical Cycles 10(3):401-412.
+! Parton, W.J. et al. 2001. Generalized model for NOx and N2O emissions from soils. J. Geophys. Res.
+! 106(D15):17403-17419
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised original CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o, tfrz
+ USE MOD_Vars_TimeVariables, only: t_soisno, wliq_soisno, wice_soisno, t_scalar, w_scalar, smp
+ USE MOD_Vars_TimeInvariants, only: &
+ porsl, wfc, bsw, BD_all, OM_density
+
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ surface_tension_water, rij_kro_a, rij_kro_alpha, rij_kro_beta, rij_kro_gamma, rij_kro_delta, organic_max, &
+ k_nitr_max, d_con_g21, d_con_g22, d_con_w21, d_con_w22, d_con_w23, &
+ denit_resp_coef, denit_resp_exp, denit_nitrate_coef, denit_nitrate_exp
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decomposition carbon & nitrogen pools
+ to2_decomp_depth_unsat, tconc_o2_unsat, smin_nh4_vr, smin_no3_vr
+
+
+ ! other variables
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ ! decomposition fluxes variables
+
+ ! mineral N fluxes
+ phr_vr, pot_f_nit_vr, pot_f_denit_vr, n2_n2o_ratio_denit_vr
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemNitrifDenitrif
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemNitrifDenitrif(i,nl_soil,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi (1:nl_soil) ! thicknesses of each soil layer (m)
+
+ integer j
+
+ real(r8) :: soil_hr_vr ! total soil respiration rate (g C / m3 / s)
+ real(r8) :: soil_bulkdensity
+ real(r8) :: g_per_m3__to__ug_per_gsoil
+ real(r8) :: g_per_m3_sec__to__ug_per_gsoil_day
+ real(r8) :: pH
+ real(r8) :: eps
+ real(r8) :: f_a
+ real(r8) :: rho_w = 1.e3_r8 ! (kg/m3)
+ real(r8) :: r_max
+ real(r8) :: r_min(1:nl_soil), r_psi(1:nl_soil)
+ real(r8) :: ratio_diffusivity_water_gas(1:nl_soil)
+ real(r8) :: om_frac
+ real(r8) :: diffus
+ real(r8) :: vol_ice, vol_liq, eff_porosity, anaerobic_frac
+ real(r8) :: k_nitr_t_vr, k_nitr_ph_vr, k_nitr_h2o_vr, k_nitr_vr
+ real(r8) :: smin_no3_massdens_vr, soil_co2_prod, fmax_denit_carbonsubstrate_vr, fmax_denit_nitrate_vr
+ real(r8) :: f_denit_base_vr, ratio_k1, ratio_no3_co2, wfps_vr, fr_WFPS
+ real(r8),parameter :: PI = 4.*atan(1.)
+
+ pH = 6.5
+
+ DO j = 1, nl_soil
+
+ f_a = 1._r8 - wfc(j,i) / porsl(j,i)
+ eps = porsl(j,i)-wfc(j,i) ! Air-filled fraction of total soil volume
+
+ ! use diffusivity calculation including peat
+ IF (organic_max > 0._r8) THEN
+ om_frac = min(OM_density(j,i)/organic_max, 1._r8)
+ ! Use first power, not square as in iniTimeConst
+ ELSE
+ om_frac = 1._r8
+ ENDIF
+ diffus = (d_con_g21 + d_con_g22*t_soisno(j,i)) * 1.e-4_r8 * &
+ (om_frac * f_a**(10._r8/3._r8) / porsl(j,i)**2 + &
+ (1._r8-om_frac) * eps**2 * f_a**(3._r8 / bsw(j,i)) )
+
+ ! calculate anoxic fraction of soils
+ ! use rijtema and kroess model after Riley et al., 2000
+ ! caclulated r_psi as a FUNCTION of psi
+ r_min(j) = 2 * surface_tension_water / (rho_w * 9.80616_r8 * amax1(abs(smp(j,i) * 1.e-5_r8),1.e-10))
+ r_max = 2 * surface_tension_water / (rho_w * 9.80616_r8 * 0.1_r8)
+ r_psi(j) = sqrt(r_min(j) * r_max)
+ ratio_diffusivity_water_gas(j) = (d_con_g21 + d_con_g22*t_soisno(j,i) ) * 1.e-4_r8 / &
+ ((d_con_w21 + d_con_w22*t_soisno(j,i) + d_con_w23*t_soisno(j,i)**2) * 1.e-9_r8)
+
+ vol_ice = min(porsl(j,i), wice_soisno(j,i)/(dz_soi(j)*denice))
+ eff_porosity = max(0.01, porsl(j,i)-vol_ice)
+ vol_liq = min(eff_porosity, wliq_soisno(j,i)/(dz_soi(j)*denh2o))
+ IF (to2_decomp_depth_unsat(j,i) > 0._r8) THEN
+ anaerobic_frac = exp(-rij_kro_a * r_psi(j)**(-rij_kro_alpha) * &
+ to2_decomp_depth_unsat(j,i)**(-rij_kro_beta) * &
+ tconc_o2_unsat(j,i)**rij_kro_gamma * (vol_liq + ratio_diffusivity_water_gas(j) * &
+ porsl(j,i))**rij_kro_delta)
+ ELSE
+ anaerobic_frac = 0._r8
+ ENDIF
+
+ k_nitr_t_vr = min(t_scalar(j,i), 1._r8)
+
+ ! ph function from Parton et al., (2001, 1996)
+ k_nitr_ph_vr = 0.56 + atan(PI * 0.45 * (-5.+ pH))/PI
+
+ ! moisture function-- assume the same moisture function as limits heterotrophic respiration
+ ! Parton et al. base their nitrification- soil moisture rate constants based on heterotrophic rates-- can we DO the same?
+ k_nitr_h2o_vr = w_scalar(j,i)
+
+ ! nitrification constant is a set scalar * temp, moisture, and ph scalars
+ k_nitr_vr = k_nitr_max * k_nitr_t_vr * k_nitr_h2o_vr * k_nitr_ph_vr
+
+ ! first-order decay of ammonium pool with scalar defined above
+ pot_f_nit_vr(j,i) = max(smin_nh4_vr(j,i) * k_nitr_vr, 0._r8)
+
+ ! limit to oxic fraction of soils
+ pot_f_nit_vr(j,i) = pot_f_nit_vr(j,i) * (1._r8 - anaerobic_frac)
+
+ !---------------- denitrification
+ ! first some input variables an unit conversions
+ soil_hr_vr = phr_vr(j,i)
+
+ ! CENTURY papers give denitrification in units of per gram soil; need to convert from volumetric to mass-based units here
+ soil_bulkdensity = BD_all(j,i) + wliq_soisno(j,i)/dz_soi(j)
+
+ g_per_m3__to__ug_per_gsoil = 1.e3_r8 / soil_bulkdensity
+
+ g_per_m3_sec__to__ug_per_gsoil_day = g_per_m3__to__ug_per_gsoil * 86400._r8
+
+ smin_no3_massdens_vr = max(smin_no3_vr(j,i), 0._r8) * g_per_m3__to__ug_per_gsoil
+
+ soil_co2_prod = (soil_hr_vr * (g_per_m3_sec__to__ug_per_gsoil_day))
+
+ !! maximum potential denitrification rates based on heterotrophic respiration rates or nitrate concentrations,
+ !! from (del Grosso et al., 2000)
+ fmax_denit_carbonsubstrate_vr = (denit_resp_coef * (soil_co2_prod**denit_resp_exp)) &
+ / g_per_m3_sec__to__ug_per_gsoil_day
+ !
+ fmax_denit_nitrate_vr = (denit_nitrate_coef * smin_no3_massdens_vr**denit_nitrate_exp) &
+ / g_per_m3_sec__to__ug_per_gsoil_day
+
+ ! find limiting denitrification rate
+ f_denit_base_vr = max(min(fmax_denit_carbonsubstrate_vr, fmax_denit_nitrate_vr),0._r8)
+
+ ! limit to anoxic fraction of soils
+ pot_f_denit_vr(j,i) = f_denit_base_vr * anaerobic_frac
+
+ ! now calculate the ratio of N2O to N2 from denitrifictaion, following Del Grosso et al., 2000
+ ! diffusivity constant (figure 6b)
+ ratio_k1 = max(1.7_r8, 38.4_r8 - 350._r8 * diffus)
+
+ ! ratio function (figure 7c)
+ IF ( soil_co2_prod > 1.0e-9_r8 ) THEN
+ ratio_no3_co2 = smin_no3_massdens_vr / soil_co2_prod
+ ELSE
+ ! fucntion saturates at large no3/co2 ratios, so set as some nominally large number
+ ratio_no3_co2 = 100._r8
+ ENDIF
+
+ ! total water limitation function (Del Grosso et al., 2000, figure 7a)
+ wfps_vr = max(min(vol_liq/porsl(j,i), 1._r8), 0._r8) * 100._r8
+ fr_WFPS = max(0.1_r8, 0.015_r8 * wfps_vr - 0.32_r8)
+
+ ! final ratio expression
+ n2_n2o_ratio_denit_vr(j,i) = max(0.16*ratio_k1, ratio_k1*exp(-0.8 * ratio_no3_co2)) * fr_WFPS
+
+ ENDDO
+ END SUBROUTINE SoilBiogeochemNitrifDenitrif
+END MODULE MOD_BGC_Soil_BiogeochemNitrifDenitrif
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemPotential.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemPotential.F90
new file mode 100644
index 0000000000..e65bdc2177
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemPotential.F90
@@ -0,0 +1,150 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemPotential
+
+!---------------------------------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This module calculates the potential C exit flux and the potential N immobilisation and mineralisation flux. The potential C exit flux
+! (p_decomp_cpool_loss) equals the product of donor C pool size (decomp_cpools_vr) and transfer pathway fraction (pathfrac_decomp).
+! The potential N immobilisation and mineralisation flux (pmnf_decomp) equals:
+! the receiver's N demand to immobalize new carbon (p_decomp_cpool_loss * (1 - rf_decomp)/cn_decomp_pools(receiver)) minus actual N
+! transfer (p_decomp_cpool_loss * cn_decomp_pools(donor))
+! p_decomp_cpool_loss and pmnf_decomp are THEN used in bgc_soil_SoilBiogeochemDecompMod.F90
+!
+! !REFERENCES:
+! Thornton, P.E., Law, B.E., Gholz, H.L., Clark, K.L., Falge, E., Ellsworth, D.S., Goldstein, A.H., Monson,
+! R.K., Hollinger, D., Falk, M. and Chen, J., 2002. Modeling and measuring the effects of disturbance
+! history and climate on carbon and water budgets in evergreen needleleaf forests.
+! Agricultural and forest meteorology, 113(1-4), 185-222.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised original CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ floating_cn_ratio, initial_cn_ratio, rf_decomp, receiver_pool, donor_pool, i_atm, pathfrac_decomp
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decomposition carbon & nitrogen pools
+ decomp_cpools_vr, decomp_npools_vr, decomp_k, &
+
+ ! other variables
+ cn_decomp_pools
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ ! decomposition fluxes variables
+ pmnf_decomp, p_decomp_cpool_loss, gross_nmin_vr, &
+
+ ! mineral N fluxes
+ potential_immob_vr, phr_vr
+
+
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemPotential
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemPotential(i,nl_soil,ndecomp_pools,ndecomp_transitions)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ndecomp_pools ! number of total soil & litter pools in the decompositions
+ integer ,intent(in) :: ndecomp_transitions ! number of total transfers between soil and litter pools in the decomposition
+
+ integer j,k,l
+ real(r8) immob(1:nl_soil)
+ real(r8) ratio
+
+ p_decomp_cpool_loss(:, :, i) = 0._r8
+ pmnf_decomp(:, :, i) = 0._r8
+
+ ! column loop to calculate potential decomp rates and total immobilization demand
+
+ !! calculate c:n ratios of applicable pools
+ DO l = 1, ndecomp_pools
+ IF ( floating_cn_ratio(l) ) THEN
+ DO j = 1,nl_soil
+ IF ( decomp_npools_vr(j,l,i) > 0._r8 ) THEN
+ cn_decomp_pools(j,l,i) = decomp_cpools_vr(j,l,i) / decomp_npools_vr(j,l,i)
+ ENDIF
+ ENDDO
+ ELSE
+ DO j = 1,nl_soil
+ cn_decomp_pools(j,l,i) = initial_cn_ratio(l)
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ! calculate the non-nitrogen-limited fluxes
+ ! these fluxes include the "/ dt" term to put them on a
+ ! per second basis, since the rate constants have been
+ ! calculated on a per timestep basis.
+
+ DO k = 1, ndecomp_transitions
+ DO j = 1,nl_soil
+
+ IF (decomp_cpools_vr(j,donor_pool(k),i) > 0._r8 .and. &
+ decomp_k(j,donor_pool(k),i) > 0._r8 ) THEN
+ p_decomp_cpool_loss(j,k,i) = decomp_cpools_vr(j,donor_pool(k),i) &
+ * decomp_k(j,donor_pool(k),i) * pathfrac_decomp(j,k,i)
+ IF ( .not. floating_cn_ratio(receiver_pool(k)) ) THEN !! not transition of cwd to litter
+
+ IF (receiver_pool(k) /= i_atm ) THEN ! not 100% respiration
+ ratio = 0._r8
+
+ IF (decomp_npools_vr(j,donor_pool(k),i) > 0._r8) THEN
+ ratio = cn_decomp_pools(j,receiver_pool(k),i)/cn_decomp_pools(j,donor_pool(k),i)
+ ENDIF
+
+ pmnf_decomp(j,k,i) = (p_decomp_cpool_loss(j,k,i) * (1.0_r8 - rf_decomp(j,k,i) - ratio) &
+ / cn_decomp_pools(j,receiver_pool(k),i) )
+
+ ELSE ! 100% respiration
+ pmnf_decomp(j,k,i) = - p_decomp_cpool_loss(j,k,i) / cn_decomp_pools(j,donor_pool(k),i)
+ ENDIF
+
+ ELSE ! CWD -> litter
+ pmnf_decomp(j,k,i) = 0._r8
+ ENDIF
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ! Sum up all the potential immobilization fluxes (positive pmnf flux)
+ ! and all the mineralization fluxes (negative pmnf flux)
+ DO j = 1,nl_soil
+ immob(j) = 0._r8
+ ENDDO
+ DO k = 1, ndecomp_transitions
+ DO j = 1,nl_soil
+ IF (pmnf_decomp(j,k,i) > 0._r8) THEN
+ immob(j) = immob(j) + pmnf_decomp(j,k,i)
+ ELSE
+ gross_nmin_vr(j,i) = gross_nmin_vr(j,i) - pmnf_decomp(j,k,i)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ DO j = 1,nl_soil
+ potential_immob_vr(j,i) = immob(j)
+ ENDDO
+
+ ! Add up potential hr for methane calculations
+ DO j = 1,nl_soil
+ phr_vr(j,i) = 0._r8
+ ENDDO
+ DO k = 1, ndecomp_transitions
+ DO j = 1,nl_soil
+ phr_vr(j,i) = phr_vr(j,i) + rf_decomp(j,k,i) * p_decomp_cpool_loss(j,k,i)
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE SoilBiogeochemPotential
+
+END MODULE MOD_BGC_Soil_BiogeochemPotential
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemVerticalProfile.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemVerticalProfile.F90
new file mode 100644
index 0000000000..b255dfe366
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Soil_BiogeochemVerticalProfile.F90
@@ -0,0 +1,237 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Soil_BiogeochemVerticalProfile
+
+!------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This MODULE calculate soil vertical profile of different C and N inputs, including:
+! nitrogen fixation, nitrogen deposition, fine root litter, coarse root litter,
+! leaf litter and stem litter.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+
+ USE MOD_Precision
+ USE MOD_Const_PFT, only: rootfr_p
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ nfixation_prof, ndep_prof, altmax_lastyear_indx, w_scalar
+ USE MOD_Vars_TimeVariables, only: t_soisno
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ leaf_prof_p, froot_prof_p, croot_prof_p, stem_prof_p, cinput_rootfr_p
+ USE MOD_Vars_PFTimeInvariants, only: &
+ pftclass, pftfrac
+ IMPLICIT NONE
+
+ PUBLIC SoilBiogeochemVerticalProfile
+
+ real(r8), PUBLIC :: surfprof_exp = 10. ! how steep profile is for surface components (1/ e_folding depth) (1/m)
+
+CONTAINS
+
+ SUBROUTINE SoilBiogeochemVerticalProfile(i,ps,pe,nl_soil,nl_soil_full,nbedrock,zmin_bedrock,z_soi,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: nl_soil_full ! number of total soil layers plus bedrock layers
+ integer ,intent(in) :: nbedrock ! where bedrock layer starts (ith soil layer)
+ real(r8),intent(in) :: zmin_bedrock ! depth where bedrock layer starts (m)
+ real(r8),intent(in) :: z_soi (1:nl_soil_full) ! depth of each soil layer (m)
+ real(r8),intent(in) :: dz_soi(1:nl_soil_full) ! thicknesses of each soil layer (m)
+
+ ! !LOCAL VARIABLES:
+ real(r8) :: surface_prof(1:nl_soil)
+ real(r8) :: surface_prof_tot
+ real(r8) :: rootfr_tot
+ real(r8) :: col_cinput_rootfr(1:nl_soil_full)
+ integer :: ivt, m
+ integer :: j
+ ! debugging temp variables
+ real(r8) :: froot_prof_sum
+ real(r8) :: croot_prof_sum
+ real(r8) :: leaf_prof_sum
+ real(r8) :: stem_prof_sum
+ real(r8) :: ndep_prof_sum
+ real(r8) :: nfixation_prof_sum
+ real(r8) :: delta = 1.e-10
+ real(r8) :: sumprof
+
+ surface_prof(:) = 0._r8
+ DO j = 1, nl_soil
+ surface_prof(j) = exp(-surfprof_exp * z_soi(j)) / dz_soi(j)
+ IF (z_soi(j) > zmin_bedrock) THEN
+ surface_prof(j) = 0._r8
+ ENDIF
+ ENDDO
+
+ ! initialize profiles to zero
+ col_cinput_rootfr(:) = 0._r8
+ nfixation_prof (:,i) = 0._r8
+ ndep_prof (:,i) = 0._r8
+ DO m = ps , pe
+ ivt = pftclass(m)
+ leaf_prof_p (:,m) = 0._r8
+ froot_prof_p(:,m) = 0._r8
+ croot_prof_p(:,m) = 0._r8
+ stem_prof_p (:,m) = 0._r8
+
+ cinput_rootfr_p(:,m) = 0._r8
+
+ IF (ivt /= 0) THEN
+ DO j = 1, nl_soil
+ cinput_rootfr_p(j,m) = rootfr_p(j,ivt) / dz_soi(j)
+ ENDDO
+
+ ELSE
+ cinput_rootfr_p(1,m) = 0.
+ ENDIF
+ ENDDO
+
+ DO m = ps , pe
+ ! integrate rootfr over active layer of soil column
+ rootfr_tot = 0._r8
+ surface_prof_tot = 0._r8
+ DO j = 1, min(max(altmax_lastyear_indx(i), 1), nl_soil)
+ rootfr_tot = rootfr_tot + cinput_rootfr_p(j,m) * dz_soi(j)
+ surface_prof_tot = surface_prof_tot + surface_prof(j) * dz_soi(j)
+ ENDDO
+ IF ( (altmax_lastyear_indx(i) > 0) .and. (rootfr_tot > 0._r8) .and. (surface_prof_tot > 0._r8) ) THEN
+ ! WHERE there is not permafrost extending to the surface, integrate the profiles over the active layer
+ ! this is equivalnet to integrating over all soil layers outside of permafrost regions
+ DO j = 1, min(max(altmax_lastyear_indx(i), 1), nl_soil)
+ froot_prof_p(j,m) = cinput_rootfr_p(j,m) / rootfr_tot
+ croot_prof_p(j,m) = cinput_rootfr_p(j,m) / rootfr_tot
+
+ IF (j > nbedrock .and. cinput_rootfr_p(j,m) > 0._r8) THEN
+ write(*,*) 'ERROR: cinput_rootfr_p > 0 in bedrock'
+ ENDIF
+ ! set all surface processes to shallower profile
+ leaf_prof_p(j,m) = surface_prof(j)/ surface_prof_tot
+ stem_prof_p(j,m) = surface_prof(j)/ surface_prof_tot
+ ENDDO
+ ELSE
+ ! IF fully frozen, or no roots, put everything in the top layer
+ froot_prof_p(1,m) = 1./dz_soi(1)
+ croot_prof_p(1,m) = 1./dz_soi(1)
+ leaf_prof_p(1,m) = 1./dz_soi(1)
+ stem_prof_p(1,m) = 1./dz_soi(1)
+ ENDIF
+ DO j = 1, nl_soil
+ IF(w_scalar(j,i) .eq. 0._r8 .and. t_soisno(j,i) < 273.15_r8)THEN
+ froot_prof_p(j,m) = 0._r8
+ croot_prof_p(j,m) = 0._r8
+ stem_prof_p (j,m) = 0._r8
+ leaf_prof_p (j,m) = 0._r8
+ ENDIF
+ ENDDO
+ sumprof = sum(froot_prof_p(1:nl_soil,m)*dz_soi(1:nl_soil))
+ IF(sumprof .ne. 0)THEN
+ DO j = 1,nl_soil
+ froot_prof_p(j,m) = froot_prof_p(j,m) / sumprof
+ ENDDO
+ ELSE
+ froot_prof_p(1,m) = 1./dz_soi(1)
+ ENDIF
+ sumprof = sum(croot_prof_p(1:nl_soil,m)*dz_soi(1:nl_soil))
+ IF(sumprof .ne. 0)THEN
+ DO j = 1,nl_soil
+ croot_prof_p(j,m) = croot_prof_p(j,m) / sumprof
+ ENDDO
+ ELSE
+ croot_prof_p(1,m) = 1./dz_soi(1)
+ ENDIF
+ sumprof = sum(stem_prof_p(1:nl_soil,m)*dz_soi(1:nl_soil))
+ IF(sumprof .ne. 0)THEN
+ DO j = 1,nl_soil
+ stem_prof_p(j,m) = stem_prof_p(j,m) / sumprof
+ ENDDO
+ ELSE
+ stem_prof_p(1,m) = 1./dz_soi(1)
+ ENDIF
+ sumprof = sum(leaf_prof_p(1:nl_soil,m)*dz_soi(1:nl_soil))
+ IF(sumprof .ne. 0)THEN
+ DO j = 1,nl_soil
+ leaf_prof_p(j,m) = leaf_prof_p(j,m) / sumprof
+ ENDDO
+ ELSE
+ leaf_prof_p(1,m) = 1./dz_soi(1)
+ ENDIF
+ ENDDO
+
+
+
+ !! aggregate root profile to column
+ DO m = ps , pe
+ DO j = 1,nl_soil
+ col_cinput_rootfr(j) = col_cinput_rootfr(j) + cinput_rootfr_p(j,m) * pftfrac(m)
+ ENDDO
+ ENDDO
+
+ ! repeat for column-native profiles: Ndep and Nfix
+ rootfr_tot = 0._r8
+ surface_prof_tot = 0._r8
+ ! redo column ntegration over active layer for column-native profiles
+ DO j = 1, min(max(altmax_lastyear_indx(i), 1), nl_soil)
+ rootfr_tot = rootfr_tot + col_cinput_rootfr(j) * dz_soi(j)
+ surface_prof_tot = surface_prof_tot + surface_prof(j) * dz_soi(j)
+ ENDDO
+ IF ( (altmax_lastyear_indx(i) > 0) .and. (rootfr_tot > 0._r8) .and. (surface_prof_tot > 0._r8) ) THEN
+ DO j = 1, min(max(altmax_lastyear_indx(i), 1), nl_soil)
+ nfixation_prof(j,i) = col_cinput_rootfr(j) / rootfr_tot
+ ndep_prof(j,i) = surface_prof(j)/ surface_prof_tot
+ ENDDO
+ ELSE
+ nfixation_prof(1,i) = 1./dz_soi(1)
+ ndep_prof(1,i) = 1./dz_soi(1)
+ ENDIF
+
+ ! check to make sure integral of all profiles = 1.
+ ndep_prof_sum = 0.
+ nfixation_prof_sum = 0.
+ DO j = 1, nl_soil
+ ndep_prof_sum = ndep_prof_sum + ndep_prof(j,i) * dz_soi(j)
+ nfixation_prof_sum = nfixation_prof_sum + nfixation_prof(j,i) * dz_soi(j)
+ ENDDO
+ IF ( ( abs(ndep_prof_sum - 1._r8) > delta ) .or. ( abs(nfixation_prof_sum - 1._r8) > delta ) ) THEN
+ print*,'i',i,delta
+ write(*,*) 'profile sums:',ndep_prof_sum-1._r8,nfixation_prof_sum-1._r8
+ write(*,*) 'altmax_lastyear_indx: ', altmax_lastyear_indx(i)
+ write(*,*) 'nfixation_prof: ', nfixation_prof(:,i)
+ write(*,*) 'ndep_prof: ', ndep_prof(:,i)
+ write(*,*) 'cinput_rootfr: ', cinput_rootfr_p(:,ps:pe)
+ write(*,*) 'dz_soi: ', dz_soi(:)
+ write(*,*) 'surface_prof: ', surface_prof(:)
+ write(*,*) 'p, itype(p) : ', i, pftclass(ps:pe)
+ write(*,*) 'cinput_rootfr(p,:): ', cinput_rootfr_p(:,ps:pe)
+ write(*,*) 'ERROR: _prof_sum-1>delta'
+ CALL abort()
+ ENDIF
+
+ DO m = ps , pe
+ froot_prof_sum = 0.
+ croot_prof_sum = 0.
+ leaf_prof_sum = 0.
+ stem_prof_sum = 0.
+ DO j = 1, nl_soil
+ froot_prof_sum = froot_prof_sum + froot_prof_p(j,m) * dz_soi(j)
+ croot_prof_sum = croot_prof_sum + croot_prof_p(j,m) * dz_soi(j)
+ leaf_prof_sum = leaf_prof_sum + leaf_prof_p(j,m) * dz_soi(j)
+ stem_prof_sum = stem_prof_sum + stem_prof_p(j,m) * dz_soi(j)
+ ENDDO
+ IF ( ( abs(froot_prof_sum - 1._r8) > delta ) .or. ( abs(croot_prof_sum - 1._r8) > delta ) .or. &
+ ( abs(stem_prof_sum - 1._r8) > delta ) .or. ( abs(leaf_prof_sum - 1._r8) > delta ) ) THEN
+ write(*,*) 'profile sums: ', froot_prof_sum, croot_prof_sum, leaf_prof_sum, stem_prof_sum
+ write(*,*) ' ERROR: sum-1 > delta'
+ CALL abort
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE SoilBiogeochemVerticalProfile
+
+END MODULE MOD_BGC_Soil_BiogeochemVerticalProfile
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_1DFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_1DFluxes.F90
new file mode 100644
index 0000000000..ae192eb1c3
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_1DFluxes.F90
@@ -0,0 +1,740 @@
+#include
+
+MODULE MOD_BGC_Vars_1DFluxes
+#ifdef BGC
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! Define, allocate, and deallocate biogeochemical flux variables at patch level
+
+! !ORIGINAL:
+! Xingjie Lu, 2022, created the original version
+
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+!--------------------- BGC variables --------------------------------------
+! ecosystem vegetation carbon/nitrogen flux
+ real(r8), allocatable :: gpp (:) ! gross primary productivity (gC m-2 s-1)
+ real(r8), allocatable :: gpp_enftemp (:) ! gross primary productivity for needleleaf evergreen temperate tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_enfboreal (:) ! gross primary productivity for needleleaf evergreen boreal tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_dnfboreal (:) ! gross primary productivity for needleleaf deciduous boreal tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_ebftrop (:) ! gross primary productivity for broadleaf evergreen tropical tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_ebftemp (:) ! gross primary productivity for broadleaf evergreen temperate tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_dbftrop (:) ! gross primary productivity for broadleaf deciduous tropical tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_dbftemp (:) ! gross primary productivity for broadleaf deciduous temperate tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_dbfboreal (:) ! gross primary productivity for broadleaf deciduous boreal tree (gC m-2 s-1)
+ real(r8), allocatable :: gpp_ebstemp (:) ! gross primary productivity for broadleaf evergreen temperate shrub (gC m-2 s-1)
+ real(r8), allocatable :: gpp_dbstemp (:) ! gross primary productivity for broadleaf deciduous temperate shrub (gC m-2 s-1)
+ real(r8), allocatable :: gpp_dbsboreal (:) ! gross primary productivity for broadleaf deciduous boreal shrub (gC m-2 s-1)
+ real(r8), allocatable :: gpp_c3arcgrass (:) ! gross primary productivity for c3 arctic grass (gC m-2 s-1)
+ real(r8), allocatable :: gpp_c3grass (:) ! gross primary productivity for c3 grass (gC m-2 s-1)
+ real(r8), allocatable :: gpp_c4grass (:) ! gross primary productivity for c4 grass (gC m-2 s-1)
+ real(r8), allocatable :: npp_enftemp (:) ! leaf carbon display pool for needleleaf evergreen temperate tree (gC m-2)
+ real(r8), allocatable :: npp_enfboreal (:) ! leaf carbon display pool for needleleaf evergreen boreal tree (gC m-2)
+ real(r8), allocatable :: npp_dnfboreal (:) ! leaf carbon display pool for needleleaf deciduous boreal tree (gC m-2)
+ real(r8), allocatable :: npp_ebftrop (:) ! leaf carbon display pool for broadleaf evergreen tropical tree (gC m-2)
+ real(r8), allocatable :: npp_ebftemp (:) ! leaf carbon display pool for broadleaf evergreen temperate tree (gC m-2)
+ real(r8), allocatable :: npp_dbftrop (:) ! leaf carbon display pool for broadleaf deciduous tropical tree (gC m-2)
+ real(r8), allocatable :: npp_dbftemp (:) ! leaf carbon display pool for broadleaf deciduous temperate tree (gC m-2)
+ real(r8), allocatable :: npp_dbfboreal (:) ! leaf carbon display pool for broadleaf deciduous boreal tree (gC m-2)
+ real(r8), allocatable :: npp_ebstemp (:) ! leaf carbon display pool for broadleaf evergreen temperate shrub (gC m-2)
+ real(r8), allocatable :: npp_dbstemp (:) ! leaf carbon display pool for broadleaf deciduous temperate shrub (gC m-2)
+ real(r8), allocatable :: npp_dbsboreal (:) ! leaf carbon display pool for broadleaf deciduous boreal shrub (gC m-2)
+ real(r8), allocatable :: npp_c3arcgrass (:) ! leaf carbon display pool for c3 arctic grass (gC m-2)
+ real(r8), allocatable :: npp_c3grass (:) ! leaf carbon display pool for c3 grass (gC m-2)
+ real(r8), allocatable :: npp_c4grass (:) ! leaf carbon display pool for c4 grass (gC m-2)
+ real(r8), allocatable :: npptoleafc_enftemp (:) ! leaf carbon display pool for needleleaf evergreen temperate tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_enfboreal (:) ! leaf carbon display pool for needleleaf evergreen boreal tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_dnfboreal (:) ! leaf carbon display pool for needleleaf deciduous boreal tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_ebftrop (:) ! leaf carbon display pool for broadleaf evergreen tropical tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_ebftemp (:) ! leaf carbon display pool for broadleaf evergreen temperate tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_dbftrop (:) ! leaf carbon display pool for broadleaf deciduous tropical tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_dbftemp (:) ! leaf carbon display pool for broadleaf deciduous temperate tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_dbfboreal (:) ! leaf carbon display pool for broadleaf deciduous boreal tree (gC m-2)
+ real(r8), allocatable :: npptoleafc_ebstemp (:) ! leaf carbon display pool for broadleaf evergreen temperate shrub (gC m-2)
+ real(r8), allocatable :: npptoleafc_dbstemp (:) ! leaf carbon display pool for broadleaf deciduous temperate shrub (gC m-2)
+ real(r8), allocatable :: npptoleafc_dbsboreal (:) ! leaf carbon display pool for broadleaf deciduous boreal shrub (gC m-2)
+ real(r8), allocatable :: npptoleafc_c3arcgrass (:) ! leaf carbon display pool for c3 arctic grass (gC m-2)
+ real(r8), allocatable :: npptoleafc_c3grass (:) ! leaf carbon display pool for c3 grass (gC m-2)
+ real(r8), allocatable :: npptoleafc_c4grass (:) ! leaf carbon display pool for c4 grass (gC m-2)
+ real(r8), allocatable :: leafc_enftemp (:) ! leaf carbon display pool for needleleaf evergreen temperate tree (gC m-2)
+ real(r8), allocatable :: leafc_enfboreal (:) ! leaf carbon display pool for needleleaf evergreen boreal tree (gC m-2)
+ real(r8), allocatable :: leafc_dnfboreal (:) ! leaf carbon display pool for needleleaf deciduous boreal tree (gC m-2)
+ real(r8), allocatable :: leafc_ebftrop (:) ! leaf carbon display pool for broadleaf evergreen tropical tree (gC m-2)
+ real(r8), allocatable :: leafc_ebftemp (:) ! leaf carbon display pool for broadleaf evergreen temperate tree (gC m-2)
+ real(r8), allocatable :: leafc_dbftrop (:) ! leaf carbon display pool for broadleaf deciduous tropical tree (gC m-2)
+ real(r8), allocatable :: leafc_dbftemp (:) ! leaf carbon display pool for broadleaf deciduous temperate tree (gC m-2)
+ real(r8), allocatable :: leafc_dbfboreal (:) ! leaf carbon display pool for broadleaf deciduous boreal tree (gC m-2)
+ real(r8), allocatable :: leafc_ebstemp (:) ! leaf carbon display pool for broadleaf evergreen temperate shrub (gC m-2)
+ real(r8), allocatable :: leafc_dbstemp (:) ! leaf carbon display pool for broadleaf deciduous temperate shrub (gC m-2)
+ real(r8), allocatable :: leafc_dbsboreal (:) ! leaf carbon display pool for broadleaf deciduous boreal shrub (gC m-2)
+ real(r8), allocatable :: leafc_c3arcgrass (:) ! leaf carbon display pool for c3 arctic grass (gC m-2)
+ real(r8), allocatable :: leafc_c3grass (:) ! leaf carbon display pool for c3 grass (gC m-2)
+ real(r8), allocatable :: leafc_c4grass (:) ! leaf carbon display pool for c4 grass (gC m-2)
+ real(r8), allocatable :: ar (:) ! autotrophic respiration (gC m-2 s-1)
+ real(r8), allocatable :: cwdprod (:) ! CWD production (gC m-2 s-1)
+ real(r8), allocatable :: cwddecomp (:) ! CWD decomposition (gC m-2 s-1)
+ real(r8), allocatable :: hr (:) ! heterotrophic respiration (gC m-2 s-1)
+ real(r8), allocatable :: er (:) ! total ecosystem respiration, autotrophic + heterotrophic (gC m-2 s-1)
+ real(r8), allocatable :: fire_closs (:) ! total C emissions due to fire (gC m-2 s-1)
+ real(r8), allocatable :: fire_nloss (:) ! total N emissions due to fire (gN m-2 s-1)
+ real(r8), allocatable :: hrv_xsmrpool_to_atm (:) ! maintenance respiration storage C to atmosphere due to harvest (gC m-2 s-1)
+ real(r8), allocatable :: wood_harvestc (:) ! harvested wood C (gC m-2 s-1)
+ real(r8), allocatable :: wood_harvestn (:) ! harvested wood N (gN m-2 s-1)
+ real(r8), allocatable :: grainc_to_cropprodc (:) ! grain to crop production carbon (gC m-2 s-1)
+ real(r8), allocatable :: grainc_to_seed (:) ! grain to crop seed carbon (gC m-2 s-1)
+ real(r8), allocatable :: grainn_to_cropprodn (:) ! grain to crop production nitrogen (gN m-2 s-1)
+ real(r8), allocatable :: cropprod1c_loss (:) ! loss rate of 1-yr crop production carbon (gC m-2 s-1)
+
+ ! decomposition carbon fluxes
+ real(r8), allocatable :: decomp_cpools_sourcesink (:,:,:) ! vertical resolved: the input of litter & soil carbon pools (donor or receiver) from phenology-associated litterfall and decomposition (gC m-3 timestep-1)
+ real(r8), allocatable :: decomp_ctransfer_vr (:,:,:) ! vertical resolved: the non-respiratory portion of potential carbon transfer from one litter & soil carbon pool to another (gC m-3 s-1)
+ real(r8), allocatable :: decomp_hr_vr (:,:,:) ! vertical resolved: the heterotrophic respiration portion of potential carbon loss from one litter & soil carbon pool to another (gC m-3 s-1)
+ real(r8), allocatable :: decomp_hr (:) ! the heterotrophic respiration portion of potential carbon loss from one decomposition carbon pool to another (gC m-3 s-1)
+ real(r8), allocatable :: phr_vr (:,:) ! vertical resolved: the potential heterotrophic respiration carbon flux (gC m-3 s-1)
+ real(r8), allocatable :: m_decomp_cpools_to_fire_vr (:,:,:) ! vertical resolved: the carbon from decomposition pools to fire emissions (gC m-3 s-1)
+ real(r8), allocatable :: decomp_cpools_transport_tendency(:,:,:) ! vertical resolved: the carbon tendency due to vertical transport in decomposition carbon pools (gC m-3 s-1)
+ real(r8), allocatable :: som_c_leached (:) ! total soil organic matter C loss from vertical transport (gC m-2 s-1)
+
+ ! vegetation to decomposition carbon fluxes
+ real(r8), allocatable :: phenology_to_met_c (:,:) ! phenology-associated plant C loss to metabolic litter C (gC m-3 s-1)
+ real(r8), allocatable :: phenology_to_cel_c (:,:) ! phenology-associated plant C loss to cellulosic litter C (gC m-3 s-1)
+ real(r8), allocatable :: phenology_to_lig_c (:,:) ! phenology-associated plant C loss to lignin litter C (gC m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_met_c (:,:) ! gap mortality-associated plant C loss to metabolic litter C (gC m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_cel_c (:,:) ! gap mortality-associated plant C loss to cellulosic litter C (gC m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_lig_c (:,:) ! gap mortality-associated plant C loss to lignin litter C (gC m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_cwdc (:,:) ! gap mortality-associated plant C loss to coarse woody debris C (gC m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_met_c (:,:) ! fire mortality-associated plant C loss to metabolic litter C (gC m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_cel_c (:,:) ! fire mortality-associated plant C loss to cellulosic litter C (gC m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_lig_c (:,:) ! fire mortality-associated plant C loss to lignin litter C (gC m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_cwdc (:,:) ! fire mortality-associated plant C loss to coarse woody debris C (gC m-3 s-1)
+
+ ! decomposition nitrogen fluxes
+ real(r8), allocatable :: decomp_npools_sourcesink (:,:,:) ! vertical resolved: the the input of litter & soil nitrogen pools (donor or receiver) (gN m-3 timestep)
+ real(r8), allocatable :: decomp_ntransfer_vr (:,:,:) ! vertical resolved: the nitrogen flux transfer from one litter & soil nitrogen pool to another (gN m-3 s-1)
+ real(r8), allocatable :: decomp_sminn_flux_vr (:,:,:) ! vertical resolved: the nitrogen mineralization flux from each nitrogen transfer between litter & soil pools (gN m-3 s-1)
+ real(r8), allocatable :: sminn_to_denit_decomp_vr (:,:,:) ! vertical resolved: the nitrogen denitrification flux from each nitrogen transfer between litter & soil pools (gN m-3 s-1)
+ real(r8), allocatable :: m_decomp_npools_to_fire_vr (:,:,:) ! vertical resolved: the litter & soil nitrogen loss associated to the fire (gN m-3 s-1)
+ real(r8), allocatable :: decomp_npools_transport_tendency(:,:,:) ! vertical resolved: the nitrogen tendency due to vertical transport in decomposition nitrogen pools (gN m-3 s-1)
+ real(r8), allocatable :: som_n_leached (:) ! total soil organic matter N loss from vertical transport (gN m-2 s-1)
+
+ ! vegetation to decomposition nitrogen fluxes
+ real(r8), allocatable :: phenology_to_met_n (:,:) ! phenology-associated plant N loss to metabolic litter N (gN m-3 s-1)
+ real(r8), allocatable :: phenology_to_cel_n (:,:) ! phenology-associated plant N loss to cellulosic litter N (gN m-3 s-1)
+ real(r8), allocatable :: phenology_to_lig_n (:,:) ! phenology-associated plant N loss to lignin litter N (gN m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_met_n (:,:) ! gap mortality-associated plant N loss to metabolic litter N (gN m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_cel_n (:,:) ! gap mortality-associated plant N loss to cellulosic litter N (gN m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_lig_n (:,:) ! gap mortality-associated plant N loss to lignin litter N (gN m-3 s-1)
+ real(r8), allocatable :: gap_mortality_to_cwdn (:,:) ! gap mortality-associated plant N loss to coarse woody debris N (gN m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_met_n (:,:) ! fire mortality-associated plant N loss to metabolic litter N (gN m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_cel_n (:,:) ! fire mortality-associated plant N loss to cellulosic litter N (gN m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_lig_n (:,:) ! fire mortality-associated plant N loss to lignin litter N (gN m-3 s-1)
+ real(r8), allocatable :: fire_mortality_to_cwdn (:,:) ! fire mortality-associated plant N loss to coarse woody debris N (gN m-3 s-1)
+
+ real(r8), allocatable :: sminn_leached_vr (:,:) ! vertical resolved: soil mineral N loss due to leaching (gN m-3 s-1)
+ real(r8), allocatable :: smin_no3_leached_vr (:,:) ! vertical resolved: soil mineral NO3 loss due to leaching (gN m-3 s-1)
+ real(r8), allocatable :: smin_no3_runoff_vr (:,:) ! vertical resolved: soil mineral NO3 loss due to runoff (gN m-3 s-1)
+ real(r8), allocatable :: net_nmin_vr (:,:) ! vertical resolved: net N mineralization (gN m-3 s-1)
+ real(r8), allocatable :: gross_nmin_vr (:,:) ! vertical resolved: total N mineralization (gN m-3 s-1)
+ real(r8), allocatable :: net_nmin (:) ! net N mineralization (gN m-2 s-1)
+ real(r8), allocatable :: gross_nmin (:) ! total N mineralization (gN m-2 s-1)
+ real(r8), allocatable :: plant_ndemand (:) ! potential plant N uptake (gN m-2 s-1)
+ real(r8), allocatable :: actual_immob_vr (:,:) ! vertical resolved: actual N immobilization (gN m-3 s-1)
+ real(r8), allocatable :: actual_immob_nh4_vr (:,:) ! vertical resolved: actual NH4 immobilization (gN m-3 s-1)
+ real(r8), allocatable :: actual_immob_no3_vr (:,:) ! vertical resolved: actual NO3 immobilization (gN m-3 s-1)
+ real(r8), allocatable :: potential_immob_vr (:,:) ! vertical resolved: potential N immobilization (gN m-3 s-1)
+ real(r8), allocatable :: pmnf_decomp (:,:,:) ! vertical resolved: potential N mineralization flux of each transfer between litter & soil pools (gN m-3 s-1)
+ real(r8), allocatable :: p_decomp_cpool_loss (:,:,:) ! vertical resolved: potential C exit rate (transfer+hr) of the donor pool of each transfer between litter & soil pools (gC m-3 s-1)
+ real(r8), allocatable :: sminn_to_plant (:) ! plant uptake N (gN m-2 s-1)
+ real(r8), allocatable :: sminn_to_plant_vr (:,:) ! vertical resolved: plant uptake N (gN m-3 s-1)
+ real(r8), allocatable :: smin_nh4_to_plant_vr (:,:) ! vertical resolved: plant uptake NH4 (gN m-3 s-1)
+ real(r8), allocatable :: smin_no3_to_plant_vr (:,:) ! vertical resolved: plant uptake NO3 (gN m-3 s-1)
+ real(r8), allocatable :: supplement_to_sminn_vr (:,:) ! vertical resolved: supplemental N supply to soil mineral N (gN m-3 s-1)
+ real(r8), allocatable :: sminn_to_plant_fun_vr (:,:) ! vertical resolved: plant uptake N by FUN (gN m-3 s-1)
+ real(r8), allocatable :: sminn_to_plant_fun_nh4_vr(:,:) ! vertical resolved: plant uptake NH4 by FUN (gN m-3 s-1)
+ real(r8), allocatable :: sminn_to_plant_fun_no3_vr(:,:) ! vertical resolved: plant uptake NO3 by FUN (gN m-3 s-1)
+ real(r8), allocatable :: sminn_to_denit_excess_vr (:,:) ! vertical resolved: denitrification from excess mineral N (gN m-3 s-1)
+ real(r8), allocatable :: f_nit_vr (:,:) ! vertical resolved: nitrification (gN m-3 s-1)
+ real(r8), allocatable :: f_denit_vr (:,:) ! vertical resolved: denitrification (gN m-3 s-1)
+ real(r8), allocatable :: f_n2o_nit_vr (:,:) ! vertical resolved: N2O emission from N nitrification (gN m-3 s-1)
+ real(r8), allocatable :: f_n2o_denit_vr (:,:) ! vertical resolved: N2O emission from N denitrification (gN m-3 s-1)
+ real(r8), allocatable :: pot_f_nit_vr (:,:) ! vertical resolved: potential N nitrification (gN m-3 s-1)
+ real(r8), allocatable :: pot_f_denit_vr (:,:) ! vertical resolved: potential N denitrification (gN m-3 s-1)
+ real(r8), allocatable :: n2_n2o_ratio_denit_vr (:,:) ! vertical resolved: ratio of N2 to N2O production by denitrification (gN gN-1)
+ real(r8), allocatable :: ndep_to_sminn (:) ! atmospheric N deposition to soil mineral N (gN m-2 s-1)
+ real(r8), allocatable :: ffix_to_sminn (:) ! free living N fixation to soil mineral N (gN m-2 s-1)
+ real(r8), allocatable :: nfix_to_sminn (:) ! N fixation to soil mineral N (gN m-2 s-1)
+ real(r8), allocatable :: somc_fire (:) ! soil organic matters C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: supplement_to_sminn (:) ! supplemental N supply to soil mineral N (gN m-2 s-1)
+ real(r8), allocatable :: fert_to_sminn (:) ! fertilizer N to soil mineral N (gN m-2 s-1)
+ real(r8), allocatable :: soyfixn_to_sminn (:) ! soybean N fixation to soil mineral N (gN m-2 s-1)
+ real(r8), allocatable :: denit (:) ! total N denitrification (gN m-2 s-1)
+ real(r8), allocatable :: sminn_leached (:) ! soil mineral N loss due to leaching (gN m-2 s-1)
+ real(r8), allocatable :: f_n2o_nit (:) ! flux of N2O from N nitrification (gN m-2 s-1)
+ real(r8), allocatable :: smin_no3_leached (:) ! soil mineral NO3 loss due to leaching (gN m-2 s-1)
+ real(r8), allocatable :: smin_no3_runoff (:) ! soil mineral NO3 loss due to runoff (gN m-2 s-1)
+ !----------------- end BGC variables -----------------------------------
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_BGCFluxes
+ PUBLIC :: deallocate_1D_BGCFluxes
+ PUBLIC :: set_1D_BGCFluxes
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_BGCFluxes
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+! bgc variables
+! ecosystem carbon flux
+ allocate (gpp (numpatch)) ; gpp (:) = spval
+ allocate (gpp_enftemp (numpatch)) ; gpp_enftemp (:) = spval
+ allocate (gpp_enfboreal (numpatch)) ; gpp_enfboreal (:) = spval
+ allocate (gpp_dnfboreal (numpatch)) ; gpp_dnfboreal (:) = spval
+ allocate (gpp_ebftrop (numpatch)) ; gpp_ebftrop (:) = spval
+ allocate (gpp_ebftemp (numpatch)) ; gpp_ebftemp (:) = spval
+ allocate (gpp_dbftrop (numpatch)) ; gpp_dbftrop (:) = spval
+ allocate (gpp_dbftemp (numpatch)) ; gpp_dbftemp (:) = spval
+ allocate (gpp_dbfboreal (numpatch)) ; gpp_dbfboreal (:) = spval
+ allocate (gpp_ebstemp (numpatch)) ; gpp_ebstemp (:) = spval
+ allocate (gpp_dbstemp (numpatch)) ; gpp_dbstemp (:) = spval
+ allocate (gpp_dbsboreal (numpatch)) ; gpp_dbsboreal (:) = spval
+ allocate (gpp_c3arcgrass (numpatch)) ; gpp_c3arcgrass (:) = spval
+ allocate (gpp_c3grass (numpatch)) ; gpp_c3grass (:) = spval
+ allocate (gpp_c4grass (numpatch)) ; gpp_c4grass (:) = spval
+ allocate (npp_enftemp (numpatch)) ; npp_enftemp (:) = spval
+ allocate (npp_enfboreal (numpatch)) ; npp_enfboreal (:) = spval
+ allocate (npp_dnfboreal (numpatch)) ; npp_dnfboreal (:) = spval
+ allocate (npp_ebftrop (numpatch)) ; npp_ebftrop (:) = spval
+ allocate (npp_ebftemp (numpatch)) ; npp_ebftemp (:) = spval
+ allocate (npp_dbftrop (numpatch)) ; npp_dbftrop (:) = spval
+ allocate (npp_dbftemp (numpatch)) ; npp_dbftemp (:) = spval
+ allocate (npp_dbfboreal (numpatch)) ; npp_dbfboreal (:) = spval
+ allocate (npp_ebstemp (numpatch)) ; npp_ebstemp (:) = spval
+ allocate (npp_dbstemp (numpatch)) ; npp_dbstemp (:) = spval
+ allocate (npp_dbsboreal (numpatch)) ; npp_dbsboreal (:) = spval
+ allocate (npp_c3arcgrass (numpatch)) ; npp_c3arcgrass (:) = spval
+ allocate (npp_c3grass (numpatch)) ; npp_c3grass (:) = spval
+ allocate (npp_c4grass (numpatch)) ; npp_c4grass (:) = spval
+ allocate (npptoleafc_enftemp (numpatch)) ; npptoleafc_enftemp (:) = spval
+ allocate (npptoleafc_enfboreal (numpatch)) ; npptoleafc_enfboreal (:) = spval
+ allocate (npptoleafc_dnfboreal (numpatch)) ; npptoleafc_dnfboreal (:) = spval
+ allocate (npptoleafc_ebftrop (numpatch)) ; npptoleafc_ebftrop (:) = spval
+ allocate (npptoleafc_ebftemp (numpatch)) ; npptoleafc_ebftemp (:) = spval
+ allocate (npptoleafc_dbftrop (numpatch)) ; npptoleafc_dbftrop (:) = spval
+ allocate (npptoleafc_dbftemp (numpatch)) ; npptoleafc_dbftemp (:) = spval
+ allocate (npptoleafc_dbfboreal (numpatch)) ; npptoleafc_dbfboreal (:) = spval
+ allocate (npptoleafc_ebstemp (numpatch)) ; npptoleafc_ebstemp (:) = spval
+ allocate (npptoleafc_dbstemp (numpatch)) ; npptoleafc_dbstemp (:) = spval
+ allocate (npptoleafc_dbsboreal (numpatch)) ; npptoleafc_dbsboreal (:) = spval
+ allocate (npptoleafc_c3arcgrass (numpatch)) ; npptoleafc_c3arcgrass (:) = spval
+ allocate (npptoleafc_c3grass (numpatch)) ; npptoleafc_c3grass (:) = spval
+ allocate (npptoleafc_c4grass (numpatch)) ; npptoleafc_c4grass (:) = spval
+ allocate (leafc_enftemp (numpatch)) ; leafc_enftemp (:) = spval
+ allocate (leafc_enfboreal (numpatch)) ; leafc_enfboreal (:) = spval
+ allocate (leafc_dnfboreal (numpatch)) ; leafc_dnfboreal (:) = spval
+ allocate (leafc_ebftrop (numpatch)) ; leafc_ebftrop (:) = spval
+ allocate (leafc_ebftemp (numpatch)) ; leafc_ebftemp (:) = spval
+ allocate (leafc_dbftrop (numpatch)) ; leafc_dbftrop (:) = spval
+ allocate (leafc_dbftemp (numpatch)) ; leafc_dbftemp (:) = spval
+ allocate (leafc_dbfboreal (numpatch)) ; leafc_dbfboreal (:) = spval
+ allocate (leafc_ebstemp (numpatch)) ; leafc_ebstemp (:) = spval
+ allocate (leafc_dbstemp (numpatch)) ; leafc_dbstemp (:) = spval
+ allocate (leafc_dbsboreal (numpatch)) ; leafc_dbsboreal (:) = spval
+ allocate (leafc_c3arcgrass (numpatch)) ; leafc_c3arcgrass (:) = spval
+ allocate (leafc_c3grass (numpatch)) ; leafc_c3grass (:) = spval
+ allocate (leafc_c4grass (numpatch)) ; leafc_c4grass (:) = spval
+ allocate (ar (numpatch)) ; ar (:) = spval
+ allocate (cwdprod (numpatch)) ; cwdprod (:) = spval
+ allocate (cwddecomp (numpatch)) ; cwddecomp (:) = spval
+ allocate (hr (numpatch)) ; hr (:) = spval
+ allocate (er (numpatch)) ; er (:) = spval
+ allocate (fire_closs (numpatch)) ; fire_closs (:) = spval
+ allocate (fire_nloss (numpatch)) ; fire_nloss (:) = spval
+ allocate (hrv_xsmrpool_to_atm (numpatch)) ; hrv_xsmrpool_to_atm (:) = spval
+ allocate (wood_harvestc (numpatch)) ; wood_harvestc (:) = spval
+ allocate (wood_harvestn (numpatch)) ; wood_harvestn (:) = spval
+ allocate (grainc_to_cropprodc (numpatch)) ; grainc_to_cropprodc (:) = spval
+ allocate (grainc_to_seed (numpatch)) ; grainc_to_seed (:) = spval
+ allocate (grainn_to_cropprodn (numpatch)) ; grainn_to_cropprodn (:) = spval
+ allocate (cropprod1c_loss (numpatch)) ; cropprod1c_loss (:) = spval
+
+
+! decomposition carbon fluxes
+ allocate (decomp_cpools_sourcesink (nl_soil_full,ndecomp_pools,numpatch)); decomp_cpools_sourcesink (:,:,:) = spval
+ allocate (decomp_ctransfer_vr (nl_soil_full,ndecomp_transitions,numpatch)); decomp_ctransfer_vr (:,:,:) = spval
+ allocate (decomp_hr_vr (nl_soil_full,ndecomp_transitions,numpatch)); decomp_hr_vr (:,:,:) = spval
+ allocate (decomp_hr (numpatch)) ; decomp_hr (:) = spval
+ allocate (phr_vr (nl_soil_full,numpatch)); phr_vr (:,:) = spval
+ allocate (m_decomp_cpools_to_fire_vr (nl_soil_full,ndecomp_pools,numpatch)); m_decomp_cpools_to_fire_vr (:,:,:) = spval
+ allocate (decomp_cpools_transport_tendency(nl_soil_full,ndecomp_pools,numpatch)); decomp_cpools_transport_tendency(:,:,:) = spval
+ allocate (som_c_leached (numpatch)) ; som_c_leached (:) = spval
+
+! vegetation to decomposition carbon fluxes
+ allocate (phenology_to_met_c (nl_soil,numpatch)); phenology_to_met_c (:,:) = spval
+ allocate (phenology_to_cel_c (nl_soil,numpatch)); phenology_to_cel_c (:,:) = spval
+ allocate (phenology_to_lig_c (nl_soil,numpatch)); phenology_to_lig_c (:,:) = spval
+ allocate (gap_mortality_to_met_c (nl_soil,numpatch)); gap_mortality_to_met_c (:,:) = spval
+ allocate (gap_mortality_to_cel_c (nl_soil,numpatch)); gap_mortality_to_cel_c (:,:) = spval
+ allocate (gap_mortality_to_lig_c (nl_soil,numpatch)); gap_mortality_to_lig_c (:,:) = spval
+ allocate (gap_mortality_to_cwdc (nl_soil,numpatch)); gap_mortality_to_cwdc (:,:) = spval
+ allocate (fire_mortality_to_met_c (nl_soil,numpatch)); fire_mortality_to_met_c (:,:) = spval
+ allocate (fire_mortality_to_cel_c (nl_soil,numpatch)); fire_mortality_to_cel_c (:,:) = spval
+ allocate (fire_mortality_to_lig_c (nl_soil,numpatch)); fire_mortality_to_lig_c (:,:) = spval
+ allocate (fire_mortality_to_cwdc (nl_soil,numpatch)); fire_mortality_to_cwdc (:,:) = spval
+
+! decomposition nitrogen fluxes
+ allocate (decomp_npools_sourcesink (nl_soil_full,ndecomp_pools,numpatch)); decomp_npools_sourcesink (:,:,:) = spval
+ allocate (decomp_ntransfer_vr (nl_soil_full,ndecomp_transitions,numpatch)); decomp_ntransfer_vr (:,:,:) = spval
+ allocate (decomp_sminn_flux_vr (nl_soil_full,ndecomp_transitions,numpatch)); decomp_sminn_flux_vr (:,:,:) = spval
+ allocate (sminn_to_denit_decomp_vr (nl_soil_full,ndecomp_transitions,numpatch)); sminn_to_denit_decomp_vr(:,:,:) = spval
+ allocate (m_decomp_npools_to_fire_vr (nl_soil_full,ndecomp_pools,numpatch)); m_decomp_npools_to_fire_vr (:,:,:) = spval
+ allocate (decomp_npools_transport_tendency(nl_soil_full,ndecomp_pools,numpatch)); decomp_npools_transport_tendency(:,:,:) = spval
+ allocate (som_n_leached (numpatch)) ; som_n_leached (:) = spval
+
+! vegetation to decomposition nitrogen fluxes
+ allocate (phenology_to_met_n (nl_soil,numpatch)); phenology_to_met_n (:,:) = spval
+ allocate (phenology_to_cel_n (nl_soil,numpatch)); phenology_to_cel_n (:,:) = spval
+ allocate (phenology_to_lig_n (nl_soil,numpatch)); phenology_to_lig_n (:,:) = spval
+ allocate (gap_mortality_to_met_n (nl_soil,numpatch)); gap_mortality_to_met_n (:,:) = spval
+ allocate (gap_mortality_to_cel_n (nl_soil,numpatch)); gap_mortality_to_cel_n (:,:) = spval
+ allocate (gap_mortality_to_lig_n (nl_soil,numpatch)); gap_mortality_to_lig_n (:,:) = spval
+ allocate (gap_mortality_to_cwdn (nl_soil,numpatch)); gap_mortality_to_cwdn (:,:) = spval
+ allocate (fire_mortality_to_met_n (nl_soil,numpatch)); fire_mortality_to_met_n (:,:) = spval
+ allocate (fire_mortality_to_cel_n (nl_soil,numpatch)); fire_mortality_to_cel_n (:,:) = spval
+ allocate (fire_mortality_to_lig_n (nl_soil,numpatch)); fire_mortality_to_lig_n (:,:) = spval
+ allocate (fire_mortality_to_cwdn (nl_soil,numpatch)); fire_mortality_to_cwdn (:,:) = spval
+
+ allocate (sminn_leached_vr (nl_soil,numpatch)); sminn_leached_vr (:,:) = spval
+ allocate (smin_no3_leached_vr (nl_soil,numpatch)); smin_no3_leached_vr (:,:) = spval
+ allocate (smin_no3_runoff_vr (nl_soil,numpatch)); smin_no3_runoff_vr (:,:) = spval
+ allocate (net_nmin_vr (nl_soil,numpatch)); net_nmin_vr (:,:) = spval
+ allocate (gross_nmin_vr (nl_soil,numpatch)); gross_nmin_vr (:,:) = spval
+ allocate (net_nmin (numpatch)) ; net_nmin (:) = spval
+ allocate (gross_nmin (numpatch)) ; gross_nmin (:) = spval
+ allocate (plant_ndemand (numpatch)) ; plant_ndemand (:) = spval
+ allocate (actual_immob_vr (nl_soil,numpatch)); actual_immob_vr (:,:) = spval
+ allocate (actual_immob_nh4_vr (nl_soil,numpatch)); actual_immob_nh4_vr (:,:) = spval
+ allocate (actual_immob_no3_vr (nl_soil,numpatch)); actual_immob_no3_vr (:,:) = spval
+ allocate (potential_immob_vr (nl_soil,numpatch)); potential_immob_vr (:,:) = spval
+ allocate (pmnf_decomp (nl_soil,ndecomp_transitions,numpatch)); pmnf_decomp (:,:,:) = spval
+ allocate (p_decomp_cpool_loss (nl_soil,ndecomp_transitions,numpatch)); p_decomp_cpool_loss (:,:,:) = spval
+ allocate (sminn_to_plant (numpatch)) ; sminn_to_plant (:) = spval
+ allocate (sminn_to_plant_vr (nl_soil,numpatch)); sminn_to_plant_vr (:,:) = spval
+ allocate (smin_nh4_to_plant_vr (nl_soil,numpatch)); smin_nh4_to_plant_vr (:,:) = spval
+ allocate (smin_no3_to_plant_vr (nl_soil,numpatch)); smin_no3_to_plant_vr (:,:) = spval
+ allocate (supplement_to_sminn_vr (nl_soil,numpatch)); supplement_to_sminn_vr (:,:) = spval
+ allocate (sminn_to_plant_fun_vr (nl_soil,numpatch)); sminn_to_plant_fun_vr (:,:) = spval
+ allocate (sminn_to_plant_fun_nh4_vr(nl_soil,numpatch)); sminn_to_plant_fun_nh4_vr(:,:) = spval
+ allocate (sminn_to_plant_fun_no3_vr(nl_soil,numpatch)); sminn_to_plant_fun_no3_vr(:,:) = spval
+ allocate (sminn_to_denit_excess_vr (nl_soil,numpatch)); sminn_to_denit_excess_vr (:,:) = spval
+ allocate (f_nit_vr (nl_soil,numpatch)); f_nit_vr (:,:) = spval
+ allocate (f_denit_vr (nl_soil,numpatch)); f_denit_vr (:,:) = spval
+ allocate (f_n2o_nit_vr (nl_soil,numpatch)); f_n2o_nit_vr (:,:) = spval
+ allocate (f_n2o_denit_vr (nl_soil,numpatch)); f_n2o_denit_vr (:,:) = spval
+ allocate (pot_f_nit_vr (nl_soil,numpatch)); pot_f_nit_vr (:,:) = spval
+ allocate (pot_f_denit_vr (nl_soil,numpatch)); pot_f_denit_vr (:,:) = spval
+ allocate (n2_n2o_ratio_denit_vr (nl_soil,numpatch)); n2_n2o_ratio_denit_vr (:,:) = spval
+ allocate (ndep_to_sminn (numpatch)) ; ndep_to_sminn (:) = spval
+ allocate (ffix_to_sminn (numpatch)) ; ffix_to_sminn (:) = spval
+ allocate (nfix_to_sminn (numpatch)) ; nfix_to_sminn (:) = spval
+ allocate (somc_fire (numpatch)) ; somc_fire (:) = spval
+ allocate (supplement_to_sminn (numpatch)) ; supplement_to_sminn (:) = spval
+ allocate (fert_to_sminn (numpatch)) ; fert_to_sminn (:) = spval
+ allocate (soyfixn_to_sminn (numpatch)) ; soyfixn_to_sminn (:) = spval
+ allocate (denit (numpatch)) ; denit (:) = spval
+ allocate (sminn_leached (numpatch)) ; sminn_leached (:) = spval
+ allocate (f_n2o_nit (numpatch)) ; f_n2o_nit (:) = spval
+ allocate (smin_no3_leached (numpatch)) ; smin_no3_leached (:) = spval
+ allocate (smin_no3_runoff (numpatch)) ; smin_no3_runoff (:) = spval
+ ENDIF
+ ENDIF
+
+
+ END SUBROUTINE allocate_1D_BGCFluxes
+
+ SUBROUTINE deallocate_1D_BGCFluxes ()
+ ! --------------------------------------------------------------------
+ ! deallocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+! bgc variables
+! ecosystem carbon flux
+ deallocate (gpp )
+ deallocate (gpp_enftemp ) !1
+ deallocate (gpp_enfboreal ) !2
+ deallocate (gpp_dnfboreal ) !3
+ deallocate (gpp_ebftrop ) !4
+ deallocate (gpp_ebftemp ) !5
+ deallocate (gpp_dbftrop ) !6
+ deallocate (gpp_dbftemp ) !7
+ deallocate (gpp_dbfboreal ) !8
+ deallocate (gpp_ebstemp ) !9
+ deallocate (gpp_dbstemp ) !10
+ deallocate (gpp_dbsboreal ) !11
+ deallocate (gpp_c3arcgrass ) !12
+ deallocate (gpp_c3grass ) !13
+ deallocate (gpp_c4grass ) !14
+ deallocate (npp_enftemp ) !1
+ deallocate (npp_enfboreal ) !2
+ deallocate (npp_dnfboreal ) !3
+ deallocate (npp_ebftrop ) !4
+ deallocate (npp_ebftemp ) !5
+ deallocate (npp_dbftrop ) !6
+ deallocate (npp_dbftemp ) !7
+ deallocate (npp_dbfboreal ) !8
+ deallocate (npp_ebstemp ) !9
+ deallocate (npp_dbstemp ) !10
+ deallocate (npp_dbsboreal ) !11
+ deallocate (npp_c3arcgrass ) !12
+ deallocate (npp_c3grass ) !13
+ deallocate (npp_c4grass ) !14
+ deallocate (npptoleafc_enftemp ) !1
+ deallocate (npptoleafc_enfboreal ) !2
+ deallocate (npptoleafc_dnfboreal ) !3
+ deallocate (npptoleafc_ebftrop ) !4
+ deallocate (npptoleafc_ebftemp ) !5
+ deallocate (npptoleafc_dbftrop ) !6
+ deallocate (npptoleafc_dbftemp ) !7
+ deallocate (npptoleafc_dbfboreal ) !8
+ deallocate (npptoleafc_ebstemp ) !9
+ deallocate (npptoleafc_dbstemp ) !10
+ deallocate (npptoleafc_dbsboreal ) !11
+ deallocate (npptoleafc_c3arcgrass ) !12
+ deallocate (npptoleafc_c3grass ) !13
+ deallocate (npptoleafc_c4grass ) !14
+ deallocate (leafc_enftemp ) !1
+ deallocate (leafc_enfboreal ) !2
+ deallocate (leafc_dnfboreal ) !3
+ deallocate (leafc_ebftrop ) !4
+ deallocate (leafc_ebftemp ) !5
+ deallocate (leafc_dbftrop ) !6
+ deallocate (leafc_dbftemp ) !7
+ deallocate (leafc_dbfboreal ) !8
+ deallocate (leafc_ebstemp ) !9
+ deallocate (leafc_dbstemp ) !10
+ deallocate (leafc_dbsboreal ) !11
+ deallocate (leafc_c3arcgrass ) !12
+ deallocate (leafc_c3grass ) !13
+ deallocate (leafc_c4grass ) !14
+ deallocate (ar )
+ deallocate (cwdprod )
+ deallocate (cwddecomp )
+ deallocate (hr )
+ deallocate (er )
+ deallocate (fire_closs )
+ deallocate (fire_nloss )
+ deallocate (hrv_xsmrpool_to_atm )
+ deallocate (wood_harvestc )
+ deallocate (wood_harvestn )
+ deallocate (grainc_to_cropprodc )
+ deallocate (grainc_to_seed )
+ deallocate (grainn_to_cropprodn )
+ deallocate (cropprod1c_loss )
+
+
+ ! decomposition carbon fluxes
+ deallocate (decomp_cpools_sourcesink )
+ deallocate (decomp_ctransfer_vr )
+ deallocate (decomp_hr_vr )
+ deallocate (decomp_hr )
+ deallocate (phr_vr )
+ deallocate (m_decomp_cpools_to_fire_vr )
+ deallocate (decomp_cpools_transport_tendency)
+ deallocate (som_c_leached )
+
+ ! vegetation to decomposition carbon fluxes
+ deallocate (phenology_to_met_c )
+ deallocate (phenology_to_cel_c )
+ deallocate (phenology_to_lig_c )
+ deallocate (gap_mortality_to_met_c )
+ deallocate (gap_mortality_to_cel_c )
+ deallocate (gap_mortality_to_lig_c )
+ deallocate (gap_mortality_to_cwdc )
+ deallocate (fire_mortality_to_met_c )
+ deallocate (fire_mortality_to_cel_c )
+ deallocate (fire_mortality_to_lig_c )
+ deallocate (fire_mortality_to_cwdc )
+
+ ! decomposition nitrogen fluxes
+ deallocate (decomp_npools_sourcesink )
+ deallocate (decomp_ntransfer_vr )
+ deallocate (decomp_sminn_flux_vr )
+ deallocate (sminn_to_denit_decomp_vr )
+ deallocate (m_decomp_npools_to_fire_vr )
+ deallocate (decomp_npools_transport_tendency)
+ deallocate (som_n_leached )
+
+ ! vegetation to decomposition nitrogen fluxes
+ deallocate (phenology_to_met_n )
+ deallocate (phenology_to_cel_n )
+ deallocate (phenology_to_lig_n )
+ deallocate (gap_mortality_to_met_n )
+ deallocate (gap_mortality_to_cel_n )
+ deallocate (gap_mortality_to_lig_n )
+ deallocate (gap_mortality_to_cwdn )
+ deallocate (fire_mortality_to_met_n )
+ deallocate (fire_mortality_to_cel_n )
+ deallocate (fire_mortality_to_lig_n )
+ deallocate (fire_mortality_to_cwdn )
+
+ deallocate (sminn_leached_vr )
+ deallocate (smin_no3_leached_vr )
+ deallocate (smin_no3_runoff_vr )
+ deallocate (net_nmin_vr )
+ deallocate (gross_nmin_vr )
+ deallocate (net_nmin )
+ deallocate (gross_nmin )
+ deallocate (plant_ndemand )
+ deallocate (actual_immob_vr )
+ deallocate (actual_immob_nh4_vr )
+ deallocate (actual_immob_no3_vr )
+ deallocate (potential_immob_vr )
+ deallocate (pmnf_decomp )
+ deallocate (p_decomp_cpool_loss )
+ deallocate (sminn_to_plant )
+ deallocate (sminn_to_plant_vr )
+ deallocate (smin_nh4_to_plant_vr )
+ deallocate (smin_no3_to_plant_vr )
+ deallocate (supplement_to_sminn_vr )
+ deallocate (sminn_to_plant_fun_vr )
+ deallocate (sminn_to_plant_fun_nh4_vr)
+ deallocate (sminn_to_plant_fun_no3_vr)
+ deallocate (sminn_to_denit_excess_vr )
+ deallocate (f_nit_vr )
+ deallocate (f_denit_vr )
+ deallocate (f_n2o_nit_vr )
+ deallocate (f_n2o_denit_vr )
+ deallocate (pot_f_nit_vr )
+ deallocate (pot_f_denit_vr )
+ deallocate (n2_n2o_ratio_denit_vr )
+ deallocate (ndep_to_sminn )
+ deallocate (ffix_to_sminn )
+ deallocate (nfix_to_sminn )
+ deallocate (somc_fire )
+ deallocate (supplement_to_sminn )
+ deallocate (fert_to_sminn )
+ deallocate (soyfixn_to_sminn )
+ deallocate (denit )
+ deallocate (sminn_leached )
+ deallocate (f_n2o_nit )
+ deallocate (smin_no3_leached )
+ deallocate (smin_no3_runoff )
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_1D_BGCFluxes
+
+SUBROUTINE set_1D_BGCFluxes(Values, Nan)
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ IMPLICIT NONE
+ real(r8),intent(in) :: Values
+ real(r8),intent(in) :: Nan
+
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+! bgc variables
+! ecosystem carbon flux
+ gpp (:) = Values
+ gpp_enftemp (:) = Values !1
+ gpp_enfboreal (:) = Values !2
+ gpp_dnfboreal (:) = Values !3
+ gpp_ebftrop (:) = Values !4
+ gpp_ebftemp (:) = Values !5
+ gpp_dbftrop (:) = Values !6
+ gpp_dbftemp (:) = Values !7
+ gpp_dbfboreal (:) = Values !8
+ gpp_ebstemp (:) = Values !9
+ gpp_dbstemp (:) = Values !10
+ gpp_dbsboreal (:) = Values !11
+ gpp_c3arcgrass (:) = Values !12
+ gpp_c3grass (:) = Values !13
+ gpp_c4grass (:) = Values !14
+ npp_enftemp (:) = Values !1
+ npp_enfboreal (:) = Values !2
+ npp_dnfboreal (:) = Values !3
+ npp_ebftrop (:) = Values !4
+ npp_ebftemp (:) = Values !5
+ npp_dbftrop (:) = Values !6
+ npp_dbftemp (:) = Values !7
+ npp_dbfboreal (:) = Values !8
+ npp_ebstemp (:) = Values !9
+ npp_dbstemp (:) = Values !10
+ npp_dbsboreal (:) = Values !11
+ npp_c3arcgrass (:) = Values !12
+ npp_c3grass (:) = Values !13
+ npp_c4grass (:) = Values !14
+ npptoleafc_enftemp (:) = Values !1
+ npptoleafc_enfboreal (:) = Values !2
+ npptoleafc_dnfboreal (:) = Values !3
+ npptoleafc_ebftrop (:) = Values !4
+ npptoleafc_ebftemp (:) = Values !5
+ npptoleafc_dbftrop (:) = Values !6
+ npptoleafc_dbftemp (:) = Values !7
+ npptoleafc_dbfboreal (:) = Values !8
+ npptoleafc_ebstemp (:) = Values !9
+ npptoleafc_dbstemp (:) = Values !10
+ npptoleafc_dbsboreal (:) = Values !11
+ npptoleafc_c3arcgrass (:) = Values !12
+ npptoleafc_c3grass (:) = Values !13
+ npptoleafc_c4grass (:) = Values !14
+ leafc_enftemp (:) = Values !1
+ leafc_enfboreal (:) = Values !2
+ leafc_dnfboreal (:) = Values !3
+ leafc_ebftrop (:) = Values !4
+ leafc_ebftemp (:) = Values !5
+ leafc_dbftrop (:) = Values !6
+ leafc_dbftemp (:) = Values !7
+ leafc_dbfboreal (:) = Values !8
+ leafc_ebstemp (:) = Values !9
+ leafc_dbstemp (:) = Values !10
+ leafc_dbsboreal (:) = Values !11
+ leafc_c3arcgrass (:) = Values !12
+ leafc_c3grass (:) = Values !13
+ leafc_c4grass (:) = Values !14
+ ar (:) = Values
+ cwdprod (:) = Values
+ cwddecomp (:) = Values
+ hr (:) = Values
+ er (:) = Values
+ fire_closs (:) = Values
+ fire_nloss (:) = Values
+ hrv_xsmrpool_to_atm (:) = Values
+ wood_harvestc (:) = Values
+ wood_harvestn (:) = Values
+ grainc_to_cropprodc (:) = Values
+ grainc_to_seed (:) = Values
+ grainn_to_cropprodn (:) = Values
+ cropprod1c_loss (:) = Values
+
+
+! decomposition carbon fluxes
+ decomp_cpools_sourcesink (:,:,:) = Values
+ decomp_ctransfer_vr (:,:,:) = Values
+ decomp_hr_vr (:,:,:) = Values
+ decomp_hr (:) = Values
+ phr_vr (:,: ) = Values
+ m_decomp_cpools_to_fire_vr (:,:,:) = Values
+ decomp_cpools_transport_tendency(:,:,:) = Values
+ som_c_leached (:) = Values
+
+! vegetation to decomposition carbon fluxes
+ phenology_to_met_c (:,:) = Values
+ phenology_to_cel_c (:,:) = Values
+ phenology_to_lig_c (:,:) = Values
+ gap_mortality_to_met_c (:,:) = Values
+ gap_mortality_to_cel_c (:,:) = Values
+ gap_mortality_to_lig_c (:,:) = Values
+ gap_mortality_to_cwdc (:,:) = Values
+ fire_mortality_to_met_c (:,:) = Values
+ fire_mortality_to_cel_c (:,:) = Values
+ fire_mortality_to_lig_c (:,:) = Values
+ fire_mortality_to_cwdc (:,:) = Values
+
+! decomposition nitrogen fluxes
+ decomp_npools_sourcesink (:,:,:) = Values
+ decomp_ntransfer_vr (:,:,:) = Values
+ decomp_sminn_flux_vr (:,:,:) = Values
+ sminn_to_denit_decomp_vr (:,:,:) = Values
+ m_decomp_npools_to_fire_vr (:,:,:) = Values
+ decomp_npools_transport_tendency(:,:,:) = Values
+ som_n_leached (:) = Values
+
+! vegetation to decomposition nitrogen fluxes
+ phenology_to_met_n (:,:) = Values
+ phenology_to_cel_n (:,:) = Values
+ phenology_to_lig_n (:,:) = Values
+ gap_mortality_to_met_n (:,:) = Values
+ gap_mortality_to_cel_n (:,:) = Values
+ gap_mortality_to_lig_n (:,:) = Values
+ gap_mortality_to_cwdn (:,:) = Values
+ fire_mortality_to_met_n (:,:) = Values
+ fire_mortality_to_cel_n (:,:) = Values
+ fire_mortality_to_lig_n (:,:) = Values
+ fire_mortality_to_cwdn (:,:) = Values
+
+ sminn_leached_vr (:,:) = Values
+ smin_no3_leached_vr (:,:) = Values
+ smin_no3_runoff_vr (:,:) = Values
+ net_nmin_vr (:,:) = Values
+ gross_nmin_vr (:,:) = Values
+ net_nmin (:) = Values
+ gross_nmin (:) = Values
+ plant_ndemand (:) = Values
+ actual_immob_vr (:,:) = Values
+ actual_immob_nh4_vr (:,:) = Values
+ actual_immob_no3_vr (:,:) = Values
+ potential_immob_vr (:,:) = Values
+ pmnf_decomp (:,:,:) = Values
+ p_decomp_cpool_loss (:,:,:) = Values
+ sminn_to_plant (:) = Values
+ sminn_to_plant_vr (:,:) = Values
+ smin_nh4_to_plant_vr (:,:) = Values
+ smin_no3_to_plant_vr (:,:) = Values
+ supplement_to_sminn_vr (:,:) = Values
+ sminn_to_plant_fun_vr (:,:) = Values
+ sminn_to_plant_fun_nh4_vr(:,:) = Values
+ sminn_to_plant_fun_no3_vr(:,:) = Values
+ sminn_to_denit_excess_vr (:,:) = Values
+ f_nit_vr (:,:) = Values
+ f_denit_vr (:,:) = Values
+ f_n2o_nit_vr (:,:) = Values
+ f_n2o_denit_vr (:,:) = Values
+ pot_f_nit_vr (:,:) = Values
+ pot_f_denit_vr (:,:) = Values
+ n2_n2o_ratio_denit_vr (:,:) = Values
+ ndep_to_sminn (:) = Values
+ ffix_to_sminn (:) = Values
+ nfix_to_sminn (:) = Values
+ somc_fire (:) = Values
+ supplement_to_sminn (:) = Values
+ fert_to_sminn (:) = Values
+ soyfixn_to_sminn (:) = Values
+ denit (:) = Values
+ sminn_leached (:) = Values
+ f_n2o_nit (:) = Values
+ smin_no3_leached (:) = Values
+ smin_no3_runoff (:) = Values
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE set_1D_BGCFluxes
+
+#endif
+END MODULE MOD_BGC_Vars_1DFluxes
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_1DPFTFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_1DPFTFluxes.F90
new file mode 100644
index 0000000000..916ac32018
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_1DPFTFluxes.F90
@@ -0,0 +1,1313 @@
+#include
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+MODULE MOD_BGC_Vars_1DPFTFluxes
+#ifdef BGC
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! Define, allocate, and deallocate biogeochemical flux variables at pft level
+
+! !ORIGINAL:
+! Xingjie Lu, 2022, created the original version
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! bgc variables
+ real(r8), allocatable :: leafc_xfer_to_leafc_p (:) ! pft level: phenology-associated flux: leaf transfer C to display C (gC m-2 s-1)
+ real(r8), allocatable :: frootc_xfer_to_frootc_p (:) ! pft level: phenology-associated flux: fine root transfer C to display C (gC m-2 s-1)
+ real(r8), allocatable :: livestemc_xfer_to_livestemc_p (:) ! pft level: phenology-associated flux: live stem transfer C to display C (gC m-2 s-1)
+ real(r8), allocatable :: deadstemc_xfer_to_deadstemc_p (:) ! pft level: phenology-associated flux: dead stem transfer C to display C (gC m-2 s-1)
+ real(r8), allocatable :: livecrootc_xfer_to_livecrootc_p (:) ! pft level: phenology-associated flux: live coarse root transfer C to display C (gC m-2 s-1)
+ real(r8), allocatable :: deadcrootc_xfer_to_deadcrootc_p (:) ! pft level: phenology-associated flux: dead coarse root transfer C to display C (gC m-2 s-1)
+ real(r8), allocatable :: grainc_xfer_to_grainc_p (:) ! pft level: phenology-associated flux: grain transfer C to display C (gC m-2 s-1)
+
+ real(r8), allocatable :: leafc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: leaf storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: frootc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: fine root storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: livestemc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: live stem storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: deadstemc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: dead stem storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: livecrootc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: live coarse root storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: deadcrootc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: dead coarse root storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: grainc_storage_to_xfer_p (:) ! pft level: phenology-associated flux: grain storage C to transfer C (gC m-2 s-1)
+ real(r8), allocatable :: gresp_storage_to_xfer_p (:) ! pft level: phenology-associated flux: growth respiration storage C to transfer C (gC m-2 s-1)
+
+ real(r8), allocatable :: leafc_to_litter_p (:) ! pft level: phenology-associated flux: leaf display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: frootc_to_litter_p (:) ! pft level: phenology-associated flux: fine root display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: grainc_to_food_p (:) ! pft level: phenology-associated flux: grain display C to product C (gC m-2 s-1)
+ real(r8), allocatable :: grainc_to_seed_p (:) ! pft level: phenology-associated flux: grain display C to seed C (gC m-2 s-1)
+ real(r8), allocatable :: crop_seedc_to_leaf_p (:) ! pft level: phenology-associated flux: seed C to leaf display C (gC m-2 s-1)
+ real(r8), allocatable :: livestemc_to_litter_p (:) ! pft level: phenology-associated flux: live stem display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: livestemc_to_deadstemc_p (:) ! pft level: phenology-associated flux: live stem display C to dead stem display C (gC m-2 s-1)
+ real(r8), allocatable :: livecrootc_to_deadcrootc_p (:) ! pft level: phenology-associated flux: live coarse root display C to dead coarse root display C (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_to_litter_p (:) ! pft level: gap mortality-associated flux: leaf display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_to_litter_p (:) ! pft level: gap mortality-associated flux: fine root display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_to_litter_p (:) ! pft level: gap mortality-associated flux: live stem display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_to_litter_p (:) ! pft level: gap mortality-associated flux: dead stem display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_to_litter_p (:) ! pft level: gap mortality-associated flux: live coarse root display C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_to_litter_p (:) ! pft level: gap mortality-associated flux: dead coarse root display C to litter C (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: leaf storage C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: fine root storage C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: live stem storage C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: dead stem storage C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: live coarse root storage C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: dead coarse root storage C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_gresp_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: growth respiration storage C to litter C (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: leaf transfer C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: fine root transfer C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: live stem transfer C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: dead stem transfer C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: live coarse root transfer C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: dead coarse root transfer C to litter C (gC m-2 s-1)
+ real(r8), allocatable :: m_gresp_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: growth respiration transfer C to litter C (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_to_fire_p (:) ! pft level: fire mortality-associated flux: leaf display C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_to_fire_p (:) ! pft level: fire mortality-associated flux: fine root display C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_to_fire_p (:) ! pft level: fire mortality-associated flux: live stem display C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_to_fire_p (:) ! pft level: fire mortality-associated flux: dead stem display C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_to_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root display C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_to_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root display C to fire emissions (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: leaf storage C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: fine root storage C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: live stem storage C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: dead stem storage C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root storage C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root storage C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_gresp_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: growth respiration storage C to fire emissions (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: leaf transfer C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: fine root transfer C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: live stem transfer C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: dead stem transfer C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root transfer C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root transfer C to fire emissions (gC m-2 s-1)
+ real(r8), allocatable :: m_gresp_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: growth respiration transfer C to fire emissions (gC m-2 s-1)
+
+ real(r8), allocatable :: m_livestemc_to_deadstemc_fire_p (:) ! pft level: fire mortality-associated flux: live stem display C to dead stem display C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_to_deadcrootc_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root display C to dead coarse root display C due to fire (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: leaf display C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: fine root display C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live stem display C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead stem display C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root display C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root display C to litter C due to fire (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: leaf storage C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: fine root storage C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live stem storage C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead stem storage C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_storage_to_litter_fire_p(:) ! pft level: fire mortality-associated flux: live coarse root storage C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_storage_to_litter_fire_p(:) ! pft level: fire mortality-associated flux: dead coarse root storage C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_gresp_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: growth respiration storage C to litter C due to fire (gC m-2 s-1)
+
+ real(r8), allocatable :: m_leafc_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: leaf transfer C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_frootc_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: fine root transfer C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livestemc_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live stem transfer C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_deadstemc_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead stem transfer C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_livecrootc_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root transfer C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_deadcrootc_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root transfer C to litter C due to fire (gC m-2 s-1)
+ real(r8), allocatable :: m_gresp_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: growth respiration transfer C to litter C due to fire (gC m-2 s-1)
+
+ real(r8), allocatable :: cpool_to_xsmrpool_p (:) ! pft level: allocation-associated flux: available C allocated to maintenance respiration storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_gresp_storage_p (:) ! pft level: allocation-associated flux: available C allocated to growth respiration storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_leafc_p (:) ! pft level: allocation-associated flux: available C allocated to leaf display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_leafc_storage_p (:) ! pft level: allocation-associated flux: available C allocated to leaf storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_frootc_p (:) ! pft level: allocation-associated flux: available C allocated to fine root display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_frootc_storage_p (:) ! pft level: allocation-associated flux: available C allocated to fine root storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_livestemc_p (:) ! pft level: allocation-associated flux: available C allocated to live stem display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_livestemc_storage_p (:) ! pft level: allocation-associated flux: available C allocated to live stem storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_deadstemc_p (:) ! pft level: allocation-associated flux: available C allocated to dead stem display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_deadstemc_storage_p (:) ! pft level: allocation-associated flux: available C allocated to dead stem storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_livecrootc_p (:) ! pft level: allocation-associated flux: available C allocated to live coarse display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_livecrootc_storage_p(:) ! pft level: allocation-associated flux: available C allocated to live coarse storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_deadcrootc_p (:) ! pft level: allocation-associated flux: available C allocated to dead coarse root display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_deadcrootc_storage_p(:) ! pft level: allocation-associated flux: available C allocated to dead coarse root storage C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_grainc_p (:) ! pft level: allocation-associated flux: available C allocated to grain display C (gC m-2 s-1)
+ real(r8), allocatable :: cpool_to_grainc_storage_p (:) ! pft level: allocation-associated flux: available C allocated to grain storage C (gC m-2 s-1)
+
+ real(r8), allocatable :: leaf_xsmr_p (:) ! pft level: leaf maintenance respiration storage C due to available C deficit (gC m-2 s-1)
+ real(r8), allocatable :: froot_xsmr_p (:) ! pft level: fine root maintenance respiration storage C due to available C deficit (gC m-2 s-1)
+ real(r8), allocatable :: livestem_xsmr_p (:) ! pft level: live stem maintenance respiration storage C due to available C deficit (gC m-2 s-1)
+ real(r8), allocatable :: livecroot_xsmr_p (:) ! pft level: live coarse root maintenance respiration storage C due to available C deficit (gC m-2 s-1)
+ real(r8), allocatable :: grain_xsmr_p (:) ! pft level: grain maintenance respiration storage C due to available C deficit (gC m-2 s-1)
+
+ real(r8), allocatable :: cpool_leaf_gr_p (:) ! pft level: allocation-associated flux: available C allocated to leaf display growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_froot_gr_p (:) ! pft level: allocation-associated flux: available C allocated to fine root display growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_livestem_gr_p (:) ! pft level: allocation-associated flux: available C allocated to live stem display growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_deadstem_gr_p (:) ! pft level: allocation-associated flux: available C allocated to dead stem display growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_livecroot_gr_p (:) ! pft level: allocation-associated flux: available C allocated to live coarse display growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_deadcroot_gr_p (:) ! pft level: allocation-associated flux: available C allocated to dead coarse display growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_grain_gr_p (:) ! pft level: allocation-associated flux: available C allocated to grain display growth respiration (gC m-2 s-1)
+
+ real(r8), allocatable :: cpool_leaf_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to leaf storage growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_froot_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to fine root storage growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_livestem_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to live stem storage growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_deadstem_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to dead stem storage growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_livecroot_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to live coarse storage growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_deadcroot_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to dead coarse storage growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: cpool_grain_storage_gr_p (:) ! pft level: allocation-associated flux: available C allocated to grain storage growth respiration (gC m-2 s-1)
+
+ real(r8), allocatable :: transfer_leaf_gr_p (:) ! pft level: allocation-associated flux: available C allocated to leaf transfer growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: transfer_froot_gr_p (:) ! pft level: allocation-associated flux: available C allocated to fine root transfer growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: transfer_livestem_gr_p (:) ! pft level: allocation-associated flux: available C allocated to live stem transfer growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: transfer_deadstem_gr_p (:) ! pft level: allocation-associated flux: available C allocated to dead stem transfer growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: transfer_livecroot_gr_p (:) ! pft level: allocation-associated flux: available C allocated to live coarse transfer growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: transfer_deadcroot_gr_p (:) ! pft level: allocation-associated flux: available C allocated to dead coarse transfer growth respiration (gC m-2 s-1)
+ real(r8), allocatable :: transfer_grain_gr_p (:) ! pft level: allocation-associated flux: available C allocated to grain transfer growth respiration (gC m-2 s-1)
+
+ real(r8), allocatable :: xsmrpool_to_atm_p (:) ! pft level: maintenance respiration storage C to atmosphere due to harvest (gC m-2 s-1)
+
+ real(r8), allocatable :: cropprod1c_loss_p (:) ! pft level: product loss (gC m-2 s-1)
+
+ real(r8), allocatable :: plant_ndemand_p (:) ! pft level: plant potential demand N (gN m-2 s-1)
+
+ real(r8), allocatable :: leafn_xfer_to_leafn_p (:) ! pft level: phenology-associated flux: leaf transfer N to display N (gN m-2 s-1)
+ real(r8), allocatable :: frootn_xfer_to_frootn_p (:) ! pft level: phenology-associated flux: fine root transfer N to display N (gN m-2 s-1)
+ real(r8), allocatable :: livestemn_xfer_to_livestemn_p (:) ! pft level: phenology-associated flux: live stem transfer N to display N (gN m-2 s-1)
+ real(r8), allocatable :: deadstemn_xfer_to_deadstemn_p (:) ! pft level: phenology-associated flux: dead stem transfer N to display N (gN m-2 s-1)
+ real(r8), allocatable :: livecrootn_xfer_to_livecrootn_p (:) ! pft level: phenology-associated flux: live coarse root transfer N to display N (gN m-2 s-1)
+ real(r8), allocatable :: deadcrootn_xfer_to_deadcrootn_p (:) ! pft level: phenology-associated flux: dead coarse root transfer N to display N (gN m-2 s-1)
+ real(r8), allocatable :: grainn_xfer_to_grainn_p (:) ! pft level: phenology-associated flux: grain transfer N to display N (gN m-2 s-1)
+
+ real(r8), allocatable :: leafn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: leaf storage N to transfer N (gN m-2 s-1)
+ real(r8), allocatable :: frootn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: fine root storage N to transfer N (gN m-2 s-1)
+ real(r8), allocatable :: livestemn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: live stem storage N to transfer N (gN m-2 s-1)
+ real(r8), allocatable :: deadstemn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: dead stem storage N to transfer N (gN m-2 s-1)
+ real(r8), allocatable :: livecrootn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: live coarse root storage N to transfer N (gN m-2 s-1)
+ real(r8), allocatable :: deadcrootn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: dead coarse root storage N to transfer N (gN m-2 s-1)
+ real(r8), allocatable :: grainn_storage_to_xfer_p (:) ! pft level: phenology-associated flux: grain storage N to transfer N (gN m-2 s-1)
+
+ real(r8), allocatable :: leafn_to_litter_p (:) ! pft level: phenology-associated flux: leaf display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: frootn_to_litter_p (:) ! pft level: phenology-associated flux: fine root display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: grainn_to_food_p (:) ! pft level: phenology-associated flux: grain display N to product N (gN m-2 s-1)
+ real(r8), allocatable :: grainn_to_seed_p (:) ! pft level: phenology-associated flux: grain display N to seed N (gN m-2 s-1)
+ real(r8), allocatable :: crop_seedn_to_leaf_p (:) ! pft level: phenology-associated flux: seed N to leaf display N (gN m-2 s-1)
+ real(r8), allocatable :: livestemn_to_litter_p (:) ! pft level: phenology-associated flux: live stem display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: livestemn_to_deadstemn_p (:) ! pft level: phenology-associated flux: live stem display N to dead stem display N (gN m-2 s-1)
+ real(r8), allocatable :: livecrootn_to_deadcrootn_p (:) ! pft level: phenology-associated flux: live coarse root display N to dead coarse root display N (gN m-2 s-1)
+
+ real(r8), allocatable :: leafn_to_retransn_p (:) ! pft level: phenology-associated flux: leaf display N to retranslocated N (gN m-2 s-1)
+ real(r8), allocatable :: frootn_to_retransn_p (:) ! pft level: phenology-associated flux: fine root display N to retranslocated N (gN m-2 s-1)
+ real(r8), allocatable :: livestemn_to_retransn_p (:) ! pft level: phenology-associated flux: live stem display N to retranslocated N (gN m-2 s-1)
+ real(r8), allocatable :: livecrootn_to_retransn_p (:) ! pft level: phenology-associated flux: live coarse root display N to retranslocated N (gN m-2 s-1)
+ real(r8), allocatable :: retransn_to_npool_p (:) ! pft level: phenology-associated flux: retranslocated N to available N (gN m-2 s-1)
+ real(r8), allocatable :: free_retransn_to_npool_p (:) ! pft level: phenology-associated flux: retranslocated N to available N (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_to_litter_p (:) ! pft level: gap mortality-associated flux: leaf display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_to_litter_p (:) ! pft level: gap mortality-associated flux: fine root display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_to_litter_p (:) ! pft level: gap mortality-associated flux: live stem display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_to_litter_p (:) ! pft level: gap mortality-associated flux: dead stem display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_to_litter_p (:) ! pft level: gap mortality-associated flux: live coarse root display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_to_litter_p (:) ! pft level: gap mortality-associated flux: dead coarse root display N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_retransn_to_litter_p (:) ! pft level: gap mortality-associated flux: retranslocated N to litter N (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: leaf storage N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: fine root storage N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: live stem storage N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: dead stem storage N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: live coarse root storage N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_storage_to_litter_p (:) ! pft level: gap mortality-associated flux: dead coarse root storage N to litter N (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: leaf transfer N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: fine root transfer N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: live stem transfer N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: dead stem transfer N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: live coarse root transfer N to litter N (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_xfer_to_litter_p (:) ! pft level: gap mortality-associated flux: dead coarse root transfer N to litter N (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_to_fire_p (:) ! pft level: fire mortality-associated flux: leaf display N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_to_fire_p (:) ! pft level: fire mortality-associated flux: fine root display N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_to_fire_p (:) ! pft level: fire mortality-associated flux: live stem display N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_to_fire_p (:) ! pft level: fire mortality-associated flux: dead stem display N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_to_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root display N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_to_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root display N to fire emissions (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: leaf storage N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: fine root storage N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: live stem storage N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: dead stem storage N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root storage N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_storage_to_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root storage N to fire emissions (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: leaf transfer N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: fine root transfer N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: live stem transfer N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: dead stem transfer N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root transfer N to fire emissions (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_xfer_to_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root transfer N to fire emissions (gN m-2 s-1)
+
+ real(r8), allocatable :: m_livestemn_to_deadstemn_fire_p (:) ! pft level: fire mortality-associated flux: live stem display N to dead stem display N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_to_deadcrootn_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root display N to dead coarse root display N due to fire (gN m-2 s-1)
+
+ real(r8), allocatable :: m_retransn_to_fire_p (:) ! pft level: fire mortality-associated flux: retranslocated N to fire emissions (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: leaf display N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: fine root display N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live stem display N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead stem display N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root display N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root display N to litter N due to fire (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: leaf storage N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: fine root storage N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live stem storage N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_storage_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead stem storage N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_storage_to_litter_fire_p(:) ! pft level: fire mortality-associated flux: live coarse root storage N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_storage_to_litter_fire_p(:) ! pft level: fire mortality-associated flux: dead coarse root storage N to litter N due to fire (gN m-2 s-1)
+
+ real(r8), allocatable :: m_leafn_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: leaf transfer N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_frootn_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: fine root transfer N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livestemn_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live stem transfer N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_deadstemn_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead stem transfer N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_livecrootn_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: live coarse root transfer N to litter N due to fire (gN m-2 s-1)
+ real(r8), allocatable :: m_deadcrootn_xfer_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: dead coarse root transfer N to litter N due to fire (gN m-2 s-1)
+
+ real(r8), allocatable :: m_retransn_to_litter_fire_p (:) ! pft level: fire mortality-associated flux: retranslocated N to litter N due to fire (gN m-2 s-1)
+
+ real(r8), allocatable :: npool_to_leafn_p (:) ! pft level: allocation-associated flux: available N allocated to leaf display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_leafn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to leaf storage N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_frootn_p (:) ! pft level: allocation-associated flux: available N allocated to fine root display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_frootn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to fine root storage N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_livestemn_p (:) ! pft level: allocation-associated flux: available N allocated to live stem display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_livestemn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to live stem storage N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_deadstemn_p (:) ! pft level: allocation-associated flux: available N allocated to dead stem display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_deadstemn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to dead stem storage N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_livecrootn_p (:) ! pft level: allocation-associated flux: available N allocated to live coarse display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_livecrootn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to live coarse storage N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_deadcrootn_p (:) ! pft level: allocation-associated flux: available N allocated to dead coarse root display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_deadcrootn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to dead coarse root storage N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_grainn_p (:) ! pft level: allocation-associated flux: available N allocated to grain display N (gN m-2 s-1)
+ real(r8), allocatable :: npool_to_grainn_storage_p (:) ! pft level: allocation-associated flux: available N allocated to grain storage N (gN m-2 s-1)
+
+ real(r8), allocatable :: respcsun_p (:) ! pft level: sunlit leaf respiration (gC m-2 s-1)
+ real(r8), allocatable :: respcsha_p (:) ! pft level: shaded leaf respiration (gC m-2 s-1)
+ real(r8), allocatable :: leaf_mr_p (:) ! pft level: leaf maintenance respiration (gC m-2 s-1)
+ real(r8), allocatable :: froot_mr_p (:) ! pft level: fine root maintenance respiration (gC m-2 s-1)
+ real(r8), allocatable :: livestem_mr_p (:) ! pft level: live stem maintenance respiration (gC m-2 s-1)
+ real(r8), allocatable :: livecroot_mr_p (:) ! pft level: live coarse root maintenance respiration (gC m-2 s-1)
+ real(r8), allocatable :: grain_mr_p (:) ! pft level: grain maintenance respiration (gC m-2 s-1)
+
+ real(r8), allocatable :: soil_change_p (:) ! pft level: soil carbon used by FUN (gC m-2 s-1)
+
+ real(r8), allocatable :: psn_to_cpool_p (:) ! pft level: photosynthesis rate (gC m-2 s-1)
+ real(r8), allocatable :: gpp_p (:) ! pft level: gross primary production (gC m-2 s-1)
+ real(r8), allocatable :: availc_p (:) ! pft level: available C (gC m-2 s-1)
+ real(r8), allocatable :: avail_retransn_p (:) ! pft level: available retranslocated N (gN m-2 s-1)
+ real(r8), allocatable :: xsmrpool_recover_p (:) ! pft level: available C to maintenance respiration storage C to recover previous excess mainte
+ real(r8), allocatable :: excess_cflux_p (:) ! pft level: excess C due to N limitation (gC m-2 s-1)
+ real(r8), allocatable :: sminn_to_npool_p (:) ! pft level: soil mineral N uptake for plant growth (gN m-2 s-1)
+
+ real(r8), allocatable :: plant_calloc_p (:) ! pft level: actual available C for plant grwoth (gC m-2 s-1)
+ real(r8), allocatable :: plant_nalloc_p (:) ! pft level: actual available N for plant growth (gN m-2 s-1)
+ real(r8), allocatable :: leaf_curmr_p (:) ! pft level: leaf maintenance respiration from current available C (gC m-2 s-1)
+ real(r8), allocatable :: froot_curmr_p (:) ! pft level: fine root maintenance respiration from current available C (gC m-2 s-1)
+ real(r8), allocatable :: livestem_curmr_p (:) ! pft level: live stem maintenance respiration from current available C (gC m-2 s-1)
+ real(r8), allocatable :: livecroot_curmr_p (:) ! pft level: live coarse root maintenance respiration from current available C (gC m-2 s-1)
+ real(r8), allocatable :: grain_curmr_p (:) ! pft level: grain maintenance respiration from current available C (gC m-2 s-1)
+
+ real(r8), allocatable :: fire_closs_p (:) ! pft level: total C emissions due to fire (gC m-2 s-1)
+ real(r8), allocatable :: fire_nloss_p (:) ! pft level: total N emissions due to fire (gN m-2 s-1)
+ real(r8), allocatable :: wood_harvestc_p (:) ! pft level: harvested wood C (gC m-2 s-1)
+ real(r8), allocatable :: wood_harvestn_p (:) ! pft level: harvested wood N (gN m-2 s-1)
+ real(r8), allocatable :: grainc_to_cropprodc_p (:) ! pft level: harvested grain C (gC m-2 s-1)
+ real(r8), allocatable :: grainn_to_cropprodn_p (:) ! pft level: harvested grain N (gN m-2 s-1)
+ real(r8), allocatable :: hrv_xsmrpool_to_atm_p (:) ! pft level: maintenance respiration storage C to atmosphere due to harvest (gC m-2 s-1)
+ real(r8), allocatable :: soyfixn_p (:) ! pft level: soybean fixed nitrogen rate (gN m-2 s-1)
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_BGCPFTFluxes
+ PUBLIC :: deallocate_1D_BGCPFTFluxes
+ PUBLIC :: set_1D_BGCPFTFluxes
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_BGCPFTFluxes
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CoLM PFT 1d [numpft] variables
+ ! --------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+
+ ! bgc variables
+ allocate (leafc_xfer_to_leafc_p (numpft)) ; leafc_xfer_to_leafc_p (:) = spval
+ allocate (frootc_xfer_to_frootc_p (numpft)) ; frootc_xfer_to_frootc_p (:) = spval
+ allocate (livestemc_xfer_to_livestemc_p (numpft)) ; livestemc_xfer_to_livestemc_p (:) = spval
+ allocate (deadstemc_xfer_to_deadstemc_p (numpft)) ; deadstemc_xfer_to_deadstemc_p (:) = spval
+ allocate (livecrootc_xfer_to_livecrootc_p (numpft)) ; livecrootc_xfer_to_livecrootc_p (:) = spval
+ allocate (deadcrootc_xfer_to_deadcrootc_p (numpft)) ; deadcrootc_xfer_to_deadcrootc_p (:) = spval
+ allocate (grainc_xfer_to_grainc_p (numpft)) ; grainc_xfer_to_grainc_p (:) = spval
+
+ allocate (leafc_storage_to_xfer_p (numpft)) ; leafc_storage_to_xfer_p (:) = spval
+ allocate (frootc_storage_to_xfer_p (numpft)) ; frootc_storage_to_xfer_p (:) = spval
+ allocate (livestemc_storage_to_xfer_p (numpft)) ; livestemc_storage_to_xfer_p (:) = spval
+ allocate (deadstemc_storage_to_xfer_p (numpft)) ; deadstemc_storage_to_xfer_p (:) = spval
+ allocate (livecrootc_storage_to_xfer_p (numpft)) ; livecrootc_storage_to_xfer_p (:) = spval
+ allocate (deadcrootc_storage_to_xfer_p (numpft)) ; deadcrootc_storage_to_xfer_p (:) = spval
+ allocate (grainc_storage_to_xfer_p (numpft)) ; grainc_storage_to_xfer_p (:) = spval
+ allocate (gresp_storage_to_xfer_p (numpft)) ; gresp_storage_to_xfer_p (:) = spval
+
+ allocate (leafc_to_litter_p (numpft)) ; leafc_to_litter_p (:) = spval
+ allocate (frootc_to_litter_p (numpft)) ; frootc_to_litter_p (:) = spval
+ allocate (grainc_to_food_p (numpft)) ; grainc_to_food_p (:) = spval
+ allocate (grainc_to_seed_p (numpft)) ; grainc_to_seed_p (:) = spval
+ allocate (crop_seedc_to_leaf_p (numpft)) ; crop_seedc_to_leaf_p (:) = spval
+ allocate (livestemc_to_litter_p (numpft)) ; livestemc_to_litter_p (:) = spval
+ allocate (livestemc_to_deadstemc_p (numpft)) ; livestemc_to_deadstemc_p (:) = spval
+ allocate (livecrootc_to_deadcrootc_p (numpft)) ; livecrootc_to_deadcrootc_p (:) = spval
+
+ allocate (m_leafc_to_litter_p (numpft)) ; m_leafc_to_litter_p (:) = spval
+ allocate (m_frootc_to_litter_p (numpft)) ; m_frootc_to_litter_p (:) = spval
+ allocate (m_livestemc_to_litter_p (numpft)) ; m_livestemc_to_litter_p (:) = spval
+ allocate (m_deadstemc_to_litter_p (numpft)) ; m_deadstemc_to_litter_p (:) = spval
+ allocate (m_livecrootc_to_litter_p (numpft)) ; m_livecrootc_to_litter_p (:) = spval
+ allocate (m_deadcrootc_to_litter_p (numpft)) ; m_deadcrootc_to_litter_p (:) = spval
+
+ allocate (m_leafc_storage_to_litter_p (numpft)) ; m_leafc_storage_to_litter_p (:) = spval
+ allocate (m_frootc_storage_to_litter_p (numpft)) ; m_frootc_storage_to_litter_p (:) = spval
+ allocate (m_livestemc_storage_to_litter_p (numpft)) ; m_livestemc_storage_to_litter_p (:) = spval
+ allocate (m_deadstemc_storage_to_litter_p (numpft)) ; m_deadstemc_storage_to_litter_p (:) = spval
+ allocate (m_livecrootc_storage_to_litter_p (numpft)) ; m_livecrootc_storage_to_litter_p (:) = spval
+ allocate (m_deadcrootc_storage_to_litter_p (numpft)) ; m_deadcrootc_storage_to_litter_p (:) = spval
+ allocate (m_gresp_storage_to_litter_p (numpft)) ; m_gresp_storage_to_litter_p (:) = spval
+
+ allocate (m_leafc_xfer_to_litter_p (numpft)) ; m_leafc_xfer_to_litter_p (:) = spval
+ allocate (m_frootc_xfer_to_litter_p (numpft)) ; m_frootc_xfer_to_litter_p (:) = spval
+ allocate (m_livestemc_xfer_to_litter_p (numpft)) ; m_livestemc_xfer_to_litter_p (:) = spval
+ allocate (m_deadstemc_xfer_to_litter_p (numpft)) ; m_deadstemc_xfer_to_litter_p (:) = spval
+ allocate (m_livecrootc_xfer_to_litter_p (numpft)) ; m_livecrootc_xfer_to_litter_p (:) = spval
+ allocate (m_deadcrootc_xfer_to_litter_p (numpft)) ; m_deadcrootc_xfer_to_litter_p (:) = spval
+ allocate (m_gresp_xfer_to_litter_p (numpft)) ; m_gresp_xfer_to_litter_p (:) = spval
+
+ allocate (m_leafc_to_fire_p (numpft)) ; m_leafc_to_fire_p (:) = spval
+ allocate (m_frootc_to_fire_p (numpft)) ; m_frootc_to_fire_p (:) = spval
+ allocate (m_livestemc_to_fire_p (numpft)) ; m_livestemc_to_fire_p (:) = spval
+ allocate (m_deadstemc_to_fire_p (numpft)) ; m_deadstemc_to_fire_p (:) = spval
+ allocate (m_livecrootc_to_fire_p (numpft)) ; m_livecrootc_to_fire_p (:) = spval
+ allocate (m_deadcrootc_to_fire_p (numpft)) ; m_deadcrootc_to_fire_p (:) = spval
+
+ allocate (m_leafc_storage_to_fire_p (numpft)) ; m_leafc_storage_to_fire_p (:) = spval
+ allocate (m_frootc_storage_to_fire_p (numpft)) ; m_frootc_storage_to_fire_p (:) = spval
+ allocate (m_livestemc_storage_to_fire_p (numpft)) ; m_livestemc_storage_to_fire_p (:) = spval
+ allocate (m_deadstemc_storage_to_fire_p (numpft)) ; m_deadstemc_storage_to_fire_p (:) = spval
+ allocate (m_livecrootc_storage_to_fire_p (numpft)) ; m_livecrootc_storage_to_fire_p (:) = spval
+ allocate (m_deadcrootc_storage_to_fire_p (numpft)) ; m_deadcrootc_storage_to_fire_p (:) = spval
+ allocate (m_gresp_storage_to_fire_p (numpft)) ; m_gresp_storage_to_fire_p (:) = spval
+
+ allocate (m_leafc_xfer_to_fire_p (numpft)) ; m_leafc_xfer_to_fire_p (:) = spval
+ allocate (m_frootc_xfer_to_fire_p (numpft)) ; m_frootc_xfer_to_fire_p (:) = spval
+ allocate (m_livestemc_xfer_to_fire_p (numpft)) ; m_livestemc_xfer_to_fire_p (:) = spval
+ allocate (m_deadstemc_xfer_to_fire_p (numpft)) ; m_deadstemc_xfer_to_fire_p (:) = spval
+ allocate (m_livecrootc_xfer_to_fire_p (numpft)) ; m_livecrootc_xfer_to_fire_p (:) = spval
+ allocate (m_deadcrootc_xfer_to_fire_p (numpft)) ; m_deadcrootc_xfer_to_fire_p (:) = spval
+ allocate (m_gresp_xfer_to_fire_p (numpft)) ; m_gresp_xfer_to_fire_p (:) = spval
+
+ allocate (m_livestemc_to_deadstemc_fire_p (numpft)) ; m_livestemc_to_deadstemc_fire_p (:) = spval
+ allocate (m_livecrootc_to_deadcrootc_fire_p (numpft)) ; m_livecrootc_to_deadcrootc_fire_p (:) = spval
+
+ allocate (m_leafc_to_litter_fire_p (numpft)) ; m_leafc_to_litter_fire_p (:) = spval
+ allocate (m_frootc_to_litter_fire_p (numpft)) ; m_frootc_to_litter_fire_p (:) = spval
+ allocate (m_livestemc_to_litter_fire_p (numpft)) ; m_livestemc_to_litter_fire_p (:) = spval
+ allocate (m_deadstemc_to_litter_fire_p (numpft)) ; m_deadstemc_to_litter_fire_p (:) = spval
+ allocate (m_livecrootc_to_litter_fire_p (numpft)) ; m_livecrootc_to_litter_fire_p (:) = spval
+ allocate (m_deadcrootc_to_litter_fire_p (numpft)) ; m_deadcrootc_to_litter_fire_p (:) = spval
+
+ allocate (m_leafc_storage_to_litter_fire_p (numpft)) ; m_leafc_storage_to_litter_fire_p (:) = spval
+ allocate (m_frootc_storage_to_litter_fire_p (numpft)) ; m_frootc_storage_to_litter_fire_p (:) = spval
+ allocate (m_livestemc_storage_to_litter_fire_p (numpft)) ; m_livestemc_storage_to_litter_fire_p (:) = spval
+ allocate (m_deadstemc_storage_to_litter_fire_p (numpft)) ; m_deadstemc_storage_to_litter_fire_p (:) = spval
+ allocate (m_livecrootc_storage_to_litter_fire_p(numpft)) ; m_livecrootc_storage_to_litter_fire_p(:) = spval
+ allocate (m_deadcrootc_storage_to_litter_fire_p(numpft)) ; m_deadcrootc_storage_to_litter_fire_p(:) = spval
+ allocate (m_gresp_storage_to_litter_fire_p (numpft)) ; m_gresp_storage_to_litter_fire_p (:) = spval
+
+ allocate (m_leafc_xfer_to_litter_fire_p (numpft)) ; m_leafc_xfer_to_litter_fire_p (:) = spval
+ allocate (m_frootc_xfer_to_litter_fire_p (numpft)) ; m_frootc_xfer_to_litter_fire_p (:) = spval
+ allocate (m_livestemc_xfer_to_litter_fire_p (numpft)) ; m_livestemc_xfer_to_litter_fire_p (:) = spval
+ allocate (m_deadstemc_xfer_to_litter_fire_p (numpft)) ; m_deadstemc_xfer_to_litter_fire_p (:) = spval
+ allocate (m_livecrootc_xfer_to_litter_fire_p (numpft)) ; m_livecrootc_xfer_to_litter_fire_p (:) = spval
+ allocate (m_deadcrootc_xfer_to_litter_fire_p (numpft)) ; m_deadcrootc_xfer_to_litter_fire_p (:) = spval
+ allocate (m_gresp_xfer_to_litter_fire_p (numpft)) ; m_gresp_xfer_to_litter_fire_p (:) = spval
+
+ allocate (cpool_to_xsmrpool_p (numpft)) ; cpool_to_xsmrpool_p (:) = spval
+ allocate (cpool_to_gresp_storage_p (numpft)) ; cpool_to_gresp_storage_p (:) = spval
+ allocate (cpool_to_leafc_p (numpft)) ; cpool_to_leafc_p (:) = spval
+ allocate (cpool_to_leafc_storage_p (numpft)) ; cpool_to_leafc_storage_p (:) = spval
+ allocate (cpool_to_frootc_p (numpft)) ; cpool_to_frootc_p (:) = spval
+ allocate (cpool_to_frootc_storage_p (numpft)) ; cpool_to_frootc_storage_p (:) = spval
+ allocate (cpool_to_livestemc_p (numpft)) ; cpool_to_livestemc_p (:) = spval
+ allocate (cpool_to_livestemc_storage_p (numpft)) ; cpool_to_livestemc_storage_p (:) = spval
+ allocate (cpool_to_deadstemc_p (numpft)) ; cpool_to_deadstemc_p (:) = spval
+ allocate (cpool_to_deadstemc_storage_p (numpft)) ; cpool_to_deadstemc_storage_p (:) = spval
+ allocate (cpool_to_livecrootc_p (numpft)) ; cpool_to_livecrootc_p (:) = spval
+ allocate (cpool_to_livecrootc_storage_p(numpft)) ; cpool_to_livecrootc_storage_p(:) = spval
+ allocate (cpool_to_deadcrootc_p (numpft)) ; cpool_to_deadcrootc_p (:) = spval
+ allocate (cpool_to_deadcrootc_storage_p(numpft)) ; cpool_to_deadcrootc_storage_p(:) = spval
+ allocate (cpool_to_grainc_p (numpft)) ; cpool_to_grainc_p (:) = spval
+ allocate (cpool_to_grainc_storage_p (numpft)) ; cpool_to_grainc_storage_p (:) = spval
+
+ allocate (leaf_xsmr_p (numpft)) ; leaf_xsmr_p (:) = spval
+ allocate (froot_xsmr_p (numpft)) ; froot_xsmr_p (:) = spval
+ allocate (livestem_xsmr_p (numpft)) ; livestem_xsmr_p (:) = spval
+ allocate (livecroot_xsmr_p (numpft)) ; livecroot_xsmr_p (:) = spval
+ allocate (grain_xsmr_p (numpft)) ; grain_xsmr_p (:) = spval
+
+ allocate (cpool_leaf_gr_p (numpft)) ; cpool_leaf_gr_p (:) = spval
+ allocate (cpool_froot_gr_p (numpft)) ; cpool_froot_gr_p (:) = spval
+ allocate (cpool_livestem_gr_p (numpft)) ; cpool_livestem_gr_p (:) = spval
+ allocate (cpool_deadstem_gr_p (numpft)) ; cpool_deadstem_gr_p (:) = spval
+ allocate (cpool_livecroot_gr_p (numpft)) ; cpool_livecroot_gr_p (:) = spval
+ allocate (cpool_deadcroot_gr_p (numpft)) ; cpool_deadcroot_gr_p (:) = spval
+ allocate (cpool_grain_gr_p (numpft)) ; cpool_grain_gr_p (:) = spval
+
+ allocate (cpool_leaf_storage_gr_p (numpft)) ; cpool_leaf_storage_gr_p (:) = spval
+ allocate (cpool_froot_storage_gr_p (numpft)) ; cpool_froot_storage_gr_p (:) = spval
+ allocate (cpool_livestem_storage_gr_p (numpft)) ; cpool_livestem_storage_gr_p (:) = spval
+ allocate (cpool_deadstem_storage_gr_p (numpft)) ; cpool_deadstem_storage_gr_p (:) = spval
+ allocate (cpool_livecroot_storage_gr_p (numpft)) ; cpool_livecroot_storage_gr_p (:) = spval
+ allocate (cpool_deadcroot_storage_gr_p (numpft)) ; cpool_deadcroot_storage_gr_p (:) = spval
+ allocate (cpool_grain_storage_gr_p (numpft)) ; cpool_grain_storage_gr_p (:) = spval
+
+ allocate (transfer_leaf_gr_p (numpft)) ; transfer_leaf_gr_p (:) = spval
+ allocate (transfer_froot_gr_p (numpft)) ; transfer_froot_gr_p (:) = spval
+ allocate (transfer_livestem_gr_p (numpft)) ; transfer_livestem_gr_p (:) = spval
+ allocate (transfer_deadstem_gr_p (numpft)) ; transfer_deadstem_gr_p (:) = spval
+ allocate (transfer_livecroot_gr_p (numpft)) ; transfer_livecroot_gr_p (:) = spval
+ allocate (transfer_deadcroot_gr_p (numpft)) ; transfer_deadcroot_gr_p (:) = spval
+ allocate (transfer_grain_gr_p (numpft)) ; transfer_grain_gr_p (:) = spval
+
+ allocate (xsmrpool_to_atm_p (numpft)) ; xsmrpool_to_atm_p (:) = spval
+
+ allocate (cropprod1c_loss_p (numpft)) ; cropprod1c_loss_p (:) = spval
+
+ allocate (plant_ndemand_p (numpft)) ; plant_ndemand_p (:) = spval
+
+ allocate (leafn_xfer_to_leafn_p (numpft)) ; leafn_xfer_to_leafn_p (:) = spval
+ allocate (frootn_xfer_to_frootn_p (numpft)) ; frootn_xfer_to_frootn_p (:) = spval
+ allocate (livestemn_xfer_to_livestemn_p (numpft)) ; livestemn_xfer_to_livestemn_p (:) = spval
+ allocate (deadstemn_xfer_to_deadstemn_p (numpft)) ; deadstemn_xfer_to_deadstemn_p (:) = spval
+ allocate (livecrootn_xfer_to_livecrootn_p (numpft)) ; livecrootn_xfer_to_livecrootn_p (:) = spval
+ allocate (deadcrootn_xfer_to_deadcrootn_p (numpft)) ; deadcrootn_xfer_to_deadcrootn_p (:) = spval
+ allocate (grainn_xfer_to_grainn_p (numpft)) ; grainn_xfer_to_grainn_p (:) = spval
+
+ allocate (leafn_storage_to_xfer_p (numpft)) ; leafn_storage_to_xfer_p (:) = spval
+ allocate (frootn_storage_to_xfer_p (numpft)) ; frootn_storage_to_xfer_p (:) = spval
+ allocate (livestemn_storage_to_xfer_p (numpft)) ; livestemn_storage_to_xfer_p (:) = spval
+ allocate (deadstemn_storage_to_xfer_p (numpft)) ; deadstemn_storage_to_xfer_p (:) = spval
+ allocate (livecrootn_storage_to_xfer_p (numpft)) ; livecrootn_storage_to_xfer_p (:) = spval
+ allocate (deadcrootn_storage_to_xfer_p (numpft)) ; deadcrootn_storage_to_xfer_p (:) = spval
+ allocate (grainn_storage_to_xfer_p (numpft)) ; grainn_storage_to_xfer_p (:) = spval
+
+ allocate (leafn_to_litter_p (numpft)) ; leafn_to_litter_p (:) = spval
+ allocate (frootn_to_litter_p (numpft)) ; frootn_to_litter_p (:) = spval
+ allocate (grainn_to_food_p (numpft)) ; grainn_to_food_p (:) = spval
+ allocate (grainn_to_seed_p (numpft)) ; grainn_to_seed_p (:) = spval
+ allocate (crop_seedn_to_leaf_p (numpft)) ; crop_seedn_to_leaf_p (:) = spval
+ allocate (livestemn_to_litter_p (numpft)) ; livestemn_to_litter_p (:) = spval
+ allocate (livestemn_to_deadstemn_p (numpft)) ; livestemn_to_deadstemn_p (:) = spval
+ allocate (livecrootn_to_deadcrootn_p (numpft)) ; livecrootn_to_deadcrootn_p (:) = spval
+
+ allocate (leafn_to_retransn_p (numpft)) ; leafn_to_retransn_p (:) = spval
+ allocate (frootn_to_retransn_p (numpft)) ; frootn_to_retransn_p (:) = spval
+ allocate (livestemn_to_retransn_p (numpft)) ; livestemn_to_retransn_p (:) = spval
+ allocate (livecrootn_to_retransn_p (numpft)) ; livecrootn_to_retransn_p (:) = spval
+ allocate (retransn_to_npool_p (numpft)) ; retransn_to_npool_p (:) = spval
+ allocate (free_retransn_to_npool_p (numpft)) ; free_retransn_to_npool_p (:) = spval
+
+ allocate (m_leafn_to_litter_p (numpft)) ; m_leafn_to_litter_p (:) = spval
+ allocate (m_frootn_to_litter_p (numpft)) ; m_frootn_to_litter_p (:) = spval
+ allocate (m_livestemn_to_litter_p (numpft)) ; m_livestemn_to_litter_p (:) = spval
+ allocate (m_deadstemn_to_litter_p (numpft)) ; m_deadstemn_to_litter_p (:) = spval
+ allocate (m_livecrootn_to_litter_p (numpft)) ; m_livecrootn_to_litter_p (:) = spval
+ allocate (m_deadcrootn_to_litter_p (numpft)) ; m_deadcrootn_to_litter_p (:) = spval
+ allocate (m_retransn_to_litter_p (numpft)) ; m_retransn_to_litter_p (:) = spval
+
+ allocate (m_leafn_storage_to_litter_p (numpft)) ; m_leafn_storage_to_litter_p (:) = spval
+ allocate (m_frootn_storage_to_litter_p (numpft)) ; m_frootn_storage_to_litter_p (:) = spval
+ allocate (m_livestemn_storage_to_litter_p (numpft)) ; m_livestemn_storage_to_litter_p (:) = spval
+ allocate (m_deadstemn_storage_to_litter_p (numpft)) ; m_deadstemn_storage_to_litter_p (:) = spval
+ allocate (m_livecrootn_storage_to_litter_p (numpft)) ; m_livecrootn_storage_to_litter_p (:) = spval
+ allocate (m_deadcrootn_storage_to_litter_p (numpft)) ; m_deadcrootn_storage_to_litter_p (:) = spval
+
+ allocate (m_leafn_xfer_to_litter_p (numpft)) ; m_leafn_xfer_to_litter_p (:) = spval
+ allocate (m_frootn_xfer_to_litter_p (numpft)) ; m_frootn_xfer_to_litter_p (:) = spval
+ allocate (m_livestemn_xfer_to_litter_p (numpft)) ; m_livestemn_xfer_to_litter_p (:) = spval
+ allocate (m_deadstemn_xfer_to_litter_p (numpft)) ; m_deadstemn_xfer_to_litter_p (:) = spval
+ allocate (m_livecrootn_xfer_to_litter_p (numpft)) ; m_livecrootn_xfer_to_litter_p (:) = spval
+ allocate (m_deadcrootn_xfer_to_litter_p (numpft)) ; m_deadcrootn_xfer_to_litter_p (:) = spval
+
+ allocate (m_leafn_to_fire_p (numpft)) ; m_leafn_to_fire_p (:) = spval
+ allocate (m_frootn_to_fire_p (numpft)) ; m_frootn_to_fire_p (:) = spval
+ allocate (m_livestemn_to_fire_p (numpft)) ; m_livestemn_to_fire_p (:) = spval
+ allocate (m_deadstemn_to_fire_p (numpft)) ; m_deadstemn_to_fire_p (:) = spval
+ allocate (m_livecrootn_to_fire_p (numpft)) ; m_livecrootn_to_fire_p (:) = spval
+ allocate (m_deadcrootn_to_fire_p (numpft)) ; m_deadcrootn_to_fire_p (:) = spval
+
+ allocate (m_leafn_storage_to_fire_p (numpft)) ; m_leafn_storage_to_fire_p (:) = spval
+ allocate (m_frootn_storage_to_fire_p (numpft)) ; m_frootn_storage_to_fire_p (:) = spval
+ allocate (m_livestemn_storage_to_fire_p (numpft)) ; m_livestemn_storage_to_fire_p (:) = spval
+ allocate (m_deadstemn_storage_to_fire_p (numpft)) ; m_deadstemn_storage_to_fire_p (:) = spval
+ allocate (m_livecrootn_storage_to_fire_p (numpft)) ; m_livecrootn_storage_to_fire_p (:) = spval
+ allocate (m_deadcrootn_storage_to_fire_p (numpft)) ; m_deadcrootn_storage_to_fire_p (:) = spval
+
+ allocate (m_leafn_xfer_to_fire_p (numpft)) ; m_leafn_xfer_to_fire_p (:) = spval
+ allocate (m_frootn_xfer_to_fire_p (numpft)) ; m_frootn_xfer_to_fire_p (:) = spval
+ allocate (m_livestemn_xfer_to_fire_p (numpft)) ; m_livestemn_xfer_to_fire_p (:) = spval
+ allocate (m_deadstemn_xfer_to_fire_p (numpft)) ; m_deadstemn_xfer_to_fire_p (:) = spval
+ allocate (m_livecrootn_xfer_to_fire_p (numpft)) ; m_livecrootn_xfer_to_fire_p (:) = spval
+ allocate (m_deadcrootn_xfer_to_fire_p (numpft)) ; m_deadcrootn_xfer_to_fire_p (:) = spval
+
+ allocate (m_livestemn_to_deadstemn_fire_p (numpft)) ; m_livestemn_to_deadstemn_fire_p (:) = spval
+ allocate (m_livecrootn_to_deadcrootn_fire_p (numpft)) ; m_livecrootn_to_deadcrootn_fire_p (:) = spval
+
+ allocate (m_retransn_to_fire_p (numpft)) ; m_retransn_to_fire_p (:) = spval
+
+ allocate (m_leafn_to_litter_fire_p (numpft)) ; m_leafn_to_litter_fire_p (:) = spval
+ allocate (m_frootn_to_litter_fire_p (numpft)) ; m_frootn_to_litter_fire_p (:) = spval
+ allocate (m_livestemn_to_litter_fire_p (numpft)) ; m_livestemn_to_litter_fire_p (:) = spval
+ allocate (m_deadstemn_to_litter_fire_p (numpft)) ; m_deadstemn_to_litter_fire_p (:) = spval
+ allocate (m_livecrootn_to_litter_fire_p (numpft)) ; m_livecrootn_to_litter_fire_p (:) = spval
+ allocate (m_deadcrootn_to_litter_fire_p (numpft)) ; m_deadcrootn_to_litter_fire_p (:) = spval
+
+ allocate (m_leafn_storage_to_litter_fire_p (numpft)) ; m_leafn_storage_to_litter_fire_p (:) = spval
+ allocate (m_frootn_storage_to_litter_fire_p (numpft)) ; m_frootn_storage_to_litter_fire_p (:) = spval
+ allocate (m_livestemn_storage_to_litter_fire_p (numpft)) ; m_livestemn_storage_to_litter_fire_p (:) = spval
+ allocate (m_deadstemn_storage_to_litter_fire_p (numpft)) ; m_deadstemn_storage_to_litter_fire_p (:) = spval
+ allocate (m_livecrootn_storage_to_litter_fire_p(numpft)) ; m_livecrootn_storage_to_litter_fire_p(:) = spval
+ allocate (m_deadcrootn_storage_to_litter_fire_p(numpft)) ; m_deadcrootn_storage_to_litter_fire_p(:) = spval
+
+ allocate (m_leafn_xfer_to_litter_fire_p (numpft)) ; m_leafn_xfer_to_litter_fire_p (:) = spval
+ allocate (m_frootn_xfer_to_litter_fire_p (numpft)) ; m_frootn_xfer_to_litter_fire_p (:) = spval
+ allocate (m_livestemn_xfer_to_litter_fire_p (numpft)) ; m_livestemn_xfer_to_litter_fire_p (:) = spval
+ allocate (m_deadstemn_xfer_to_litter_fire_p (numpft)) ; m_deadstemn_xfer_to_litter_fire_p (:) = spval
+ allocate (m_livecrootn_xfer_to_litter_fire_p (numpft)) ; m_livecrootn_xfer_to_litter_fire_p (:) = spval
+ allocate (m_deadcrootn_xfer_to_litter_fire_p (numpft)) ; m_deadcrootn_xfer_to_litter_fire_p (:) = spval
+
+ allocate (m_retransn_to_litter_fire_p (numpft)) ; m_retransn_to_litter_fire_p (:) = spval
+
+ allocate (npool_to_leafn_p (numpft)) ; npool_to_leafn_p (:) = spval
+ allocate (npool_to_leafn_storage_p (numpft)) ; npool_to_leafn_storage_p (:) = spval
+ allocate (npool_to_frootn_p (numpft)) ; npool_to_frootn_p (:) = spval
+ allocate (npool_to_frootn_storage_p (numpft)) ; npool_to_frootn_storage_p (:) = spval
+ allocate (npool_to_livestemn_p (numpft)) ; npool_to_livestemn_p (:) = spval
+ allocate (npool_to_livestemn_storage_p (numpft)) ; npool_to_livestemn_storage_p (:) = spval
+ allocate (npool_to_deadstemn_p (numpft)) ; npool_to_deadstemn_p (:) = spval
+ allocate (npool_to_deadstemn_storage_p (numpft)) ; npool_to_deadstemn_storage_p (:) = spval
+ allocate (npool_to_livecrootn_p (numpft)) ; npool_to_livecrootn_p (:) = spval
+ allocate (npool_to_livecrootn_storage_p (numpft)) ; npool_to_livecrootn_storage_p (:) = spval
+ allocate (npool_to_deadcrootn_p (numpft)) ; npool_to_deadcrootn_p (:) = spval
+ allocate (npool_to_deadcrootn_storage_p (numpft)) ; npool_to_deadcrootn_storage_p (:) = spval
+ allocate (npool_to_grainn_p (numpft)) ; npool_to_grainn_p (:) = spval
+ allocate (npool_to_grainn_storage_p (numpft)) ; npool_to_grainn_storage_p (:) = spval
+
+ allocate (respcsun_p (numpft)) ; respcsun_p (:) = spval
+ allocate (respcsha_p (numpft)) ; respcsha_p (:) = spval
+ allocate (leaf_mr_p (numpft)) ; leaf_mr_p (:) = spval
+ allocate (froot_mr_p (numpft)) ; froot_mr_p (:) = spval
+ allocate (livestem_mr_p (numpft)) ; livestem_mr_p (:) = spval
+ allocate (livecroot_mr_p (numpft)) ; livecroot_mr_p (:) = spval
+ allocate (grain_mr_p (numpft)) ; grain_mr_p (:) = spval
+
+ allocate (soil_change_p (numpft)) ; soil_change_p (:) = spval
+
+ allocate (psn_to_cpool_p (numpft)) ; psn_to_cpool_p (:) = spval
+ allocate (gpp_p (numpft)) ; gpp_p (:) = spval
+ allocate (availc_p (numpft)) ; availc_p (:) = spval
+ allocate (avail_retransn_p (numpft)) ; avail_retransn_p (:) = spval
+ allocate (xsmrpool_recover_p (numpft)) ; xsmrpool_recover_p (:) = spval
+ allocate (excess_cflux_p (numpft)) ; excess_cflux_p (:) = spval
+ allocate (sminn_to_npool_p (numpft)) ; sminn_to_npool_p (:) = spval
+
+ allocate (plant_calloc_p (numpft)) ; plant_calloc_p (:) = spval
+ allocate (plant_nalloc_p (numpft)) ; plant_nalloc_p (:) = spval
+ allocate (leaf_curmr_p (numpft)) ; leaf_curmr_p (:) = spval
+ allocate (froot_curmr_p (numpft)) ; froot_curmr_p (:) = spval
+ allocate (livestem_curmr_p (numpft)) ; livestem_curmr_p (:) = spval
+ allocate (livecroot_curmr_p (numpft)) ; livecroot_curmr_p (:) = spval
+ allocate (grain_curmr_p (numpft)) ; grain_curmr_p (:) = spval
+
+ allocate (fire_closs_p (numpft)) ; fire_closs_p (:) = spval
+ allocate (fire_nloss_p (numpft)) ; fire_nloss_p (:) = spval
+ allocate (wood_harvestc_p (numpft)) ; wood_harvestc_p (:) = spval
+ allocate (wood_harvestn_p (numpft)) ; wood_harvestn_p (:) = spval
+ allocate (grainc_to_cropprodc_p (numpft)) ; grainc_to_cropprodc_p (:) = spval
+ allocate (grainn_to_cropprodn_p (numpft)) ; grainn_to_cropprodn_p (:) = spval
+ allocate (hrv_xsmrpool_to_atm_p (numpft)) ; hrv_xsmrpool_to_atm_p (:) = spval
+ allocate (soyfixn_p (numpft)) ; soyfixn_p (:) = spval
+
+ ENDIF
+ ENDIF
+
+!--------
+
+ END SUBROUTINE allocate_1D_BGCPFTFluxes
+
+ SUBROUTINE deallocate_1D_BGCPFTFluxes
+ ! --------------------------------------------------------------------
+ ! deallocates memory for CoLM PFT 1d [numpft] variables
+ ! --------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+
+! bgc variables
+ deallocate (leafc_xfer_to_leafc_p )
+ deallocate (frootc_xfer_to_frootc_p )
+ deallocate (livestemc_xfer_to_livestemc_p )
+ deallocate (deadstemc_xfer_to_deadstemc_p )
+ deallocate (livecrootc_xfer_to_livecrootc_p )
+ deallocate (deadcrootc_xfer_to_deadcrootc_p )
+ deallocate (grainc_xfer_to_grainc_p )
+
+ deallocate (leafc_storage_to_xfer_p )
+ deallocate (frootc_storage_to_xfer_p )
+ deallocate (livestemc_storage_to_xfer_p )
+ deallocate (deadstemc_storage_to_xfer_p )
+ deallocate (livecrootc_storage_to_xfer_p )
+ deallocate (deadcrootc_storage_to_xfer_p )
+ deallocate (grainc_storage_to_xfer_p )
+ deallocate (gresp_storage_to_xfer_p )
+
+ deallocate (leafc_to_litter_p )
+ deallocate (frootc_to_litter_p )
+ deallocate (grainc_to_food_p )
+ deallocate (grainc_to_seed_p )
+ deallocate (crop_seedc_to_leaf_p )
+ deallocate (livestemc_to_litter_p )
+ deallocate (livestemc_to_deadstemc_p )
+ deallocate (livecrootc_to_deadcrootc_p )
+
+ deallocate (m_leafc_to_litter_p )
+ deallocate (m_frootc_to_litter_p )
+ deallocate (m_livestemc_to_litter_p )
+ deallocate (m_deadstemc_to_litter_p )
+ deallocate (m_livecrootc_to_litter_p )
+ deallocate (m_deadcrootc_to_litter_p )
+
+ deallocate (m_leafc_storage_to_litter_p )
+ deallocate (m_frootc_storage_to_litter_p )
+ deallocate (m_livestemc_storage_to_litter_p )
+ deallocate (m_deadstemc_storage_to_litter_p )
+ deallocate (m_livecrootc_storage_to_litter_p )
+ deallocate (m_deadcrootc_storage_to_litter_p )
+ deallocate (m_gresp_storage_to_litter_p )
+
+ deallocate (m_leafc_xfer_to_litter_p )
+ deallocate (m_frootc_xfer_to_litter_p )
+ deallocate (m_livestemc_xfer_to_litter_p )
+ deallocate (m_deadstemc_xfer_to_litter_p )
+ deallocate (m_livecrootc_xfer_to_litter_p )
+ deallocate (m_deadcrootc_xfer_to_litter_p )
+ deallocate (m_gresp_xfer_to_litter_p )
+
+ deallocate (m_leafc_to_fire_p )
+ deallocate (m_frootc_to_fire_p )
+ deallocate (m_livestemc_to_fire_p )
+ deallocate (m_deadstemc_to_fire_p )
+ deallocate (m_livecrootc_to_fire_p )
+ deallocate (m_deadcrootc_to_fire_p )
+
+ deallocate (m_leafc_storage_to_fire_p )
+ deallocate (m_frootc_storage_to_fire_p )
+ deallocate (m_livestemc_storage_to_fire_p )
+ deallocate (m_deadstemc_storage_to_fire_p )
+ deallocate (m_livecrootc_storage_to_fire_p )
+ deallocate (m_deadcrootc_storage_to_fire_p )
+ deallocate (m_gresp_storage_to_fire_p )
+
+ deallocate (m_leafc_xfer_to_fire_p )
+ deallocate (m_frootc_xfer_to_fire_p )
+ deallocate (m_livestemc_xfer_to_fire_p )
+ deallocate (m_deadstemc_xfer_to_fire_p )
+ deallocate (m_livecrootc_xfer_to_fire_p )
+ deallocate (m_deadcrootc_xfer_to_fire_p )
+ deallocate (m_gresp_xfer_to_fire_p )
+
+ deallocate (m_livestemc_to_deadstemc_fire_p )
+ deallocate (m_livecrootc_to_deadcrootc_fire_p )
+
+ deallocate (m_leafc_to_litter_fire_p )
+ deallocate (m_frootc_to_litter_fire_p )
+ deallocate (m_livestemc_to_litter_fire_p )
+ deallocate (m_deadstemc_to_litter_fire_p )
+ deallocate (m_livecrootc_to_litter_fire_p )
+ deallocate (m_deadcrootc_to_litter_fire_p )
+
+ deallocate (m_leafc_storage_to_litter_fire_p )
+ deallocate (m_frootc_storage_to_litter_fire_p )
+ deallocate (m_livestemc_storage_to_litter_fire_p )
+ deallocate (m_deadstemc_storage_to_litter_fire_p )
+ deallocate (m_livecrootc_storage_to_litter_fire_p)
+ deallocate (m_deadcrootc_storage_to_litter_fire_p)
+ deallocate (m_gresp_storage_to_litter_fire_p )
+
+ deallocate (m_leafc_xfer_to_litter_fire_p )
+ deallocate (m_frootc_xfer_to_litter_fire_p )
+ deallocate (m_livestemc_xfer_to_litter_fire_p )
+ deallocate (m_deadstemc_xfer_to_litter_fire_p )
+ deallocate (m_livecrootc_xfer_to_litter_fire_p )
+ deallocate (m_deadcrootc_xfer_to_litter_fire_p )
+ deallocate (m_gresp_xfer_to_litter_fire_p )
+
+ deallocate (cpool_to_xsmrpool_p )
+ deallocate (cpool_to_gresp_storage_p )
+ deallocate (cpool_to_leafc_p )
+ deallocate (cpool_to_leafc_storage_p )
+ deallocate (cpool_to_frootc_p )
+ deallocate (cpool_to_frootc_storage_p )
+ deallocate (cpool_to_livestemc_p )
+ deallocate (cpool_to_livestemc_storage_p )
+ deallocate (cpool_to_deadstemc_p )
+ deallocate (cpool_to_deadstemc_storage_p )
+ deallocate (cpool_to_livecrootc_p )
+ deallocate (cpool_to_livecrootc_storage_p)
+ deallocate (cpool_to_deadcrootc_p )
+ deallocate (cpool_to_deadcrootc_storage_p)
+ deallocate (cpool_to_grainc_p )
+ deallocate (cpool_to_grainc_storage_p )
+
+ deallocate (leaf_xsmr_p )
+ deallocate (froot_xsmr_p )
+ deallocate (livestem_xsmr_p )
+ deallocate (livecroot_xsmr_p )
+ deallocate (grain_xsmr_p )
+
+ deallocate (cpool_leaf_gr_p )
+ deallocate (cpool_froot_gr_p )
+ deallocate (cpool_livestem_gr_p )
+ deallocate (cpool_deadstem_gr_p )
+ deallocate (cpool_livecroot_gr_p )
+ deallocate (cpool_deadcroot_gr_p )
+ deallocate (cpool_grain_gr_p )
+
+ deallocate (cpool_leaf_storage_gr_p )
+ deallocate (cpool_froot_storage_gr_p )
+ deallocate (cpool_livestem_storage_gr_p )
+ deallocate (cpool_deadstem_storage_gr_p )
+ deallocate (cpool_livecroot_storage_gr_p )
+ deallocate (cpool_deadcroot_storage_gr_p )
+ deallocate (cpool_grain_storage_gr_p )
+
+ deallocate (transfer_leaf_gr_p )
+ deallocate (transfer_froot_gr_p )
+ deallocate (transfer_livestem_gr_p )
+ deallocate (transfer_deadstem_gr_p )
+ deallocate (transfer_livecroot_gr_p )
+ deallocate (transfer_deadcroot_gr_p )
+ deallocate (transfer_grain_gr_p )
+
+ deallocate (xsmrpool_to_atm_p )
+
+ deallocate (cropprod1c_loss_p )
+
+ deallocate (plant_ndemand_p )
+
+ deallocate (leafn_xfer_to_leafn_p )
+ deallocate (frootn_xfer_to_frootn_p )
+ deallocate (livestemn_xfer_to_livestemn_p )
+ deallocate (deadstemn_xfer_to_deadstemn_p )
+ deallocate (livecrootn_xfer_to_livecrootn_p )
+ deallocate (deadcrootn_xfer_to_deadcrootn_p )
+ deallocate (grainn_xfer_to_grainn_p )
+
+ deallocate (leafn_storage_to_xfer_p )
+ deallocate (frootn_storage_to_xfer_p )
+ deallocate (livestemn_storage_to_xfer_p )
+ deallocate (deadstemn_storage_to_xfer_p )
+ deallocate (livecrootn_storage_to_xfer_p )
+ deallocate (deadcrootn_storage_to_xfer_p )
+ deallocate (grainn_storage_to_xfer_p )
+
+ deallocate (leafn_to_litter_p )
+ deallocate (frootn_to_litter_p )
+ deallocate (grainn_to_food_p )
+ deallocate (grainn_to_seed_p )
+ deallocate (crop_seedn_to_leaf_p )
+ deallocate (livestemn_to_litter_p )
+ deallocate (livestemn_to_deadstemn_p )
+ deallocate (livecrootn_to_deadcrootn_p )
+
+ deallocate (leafn_to_retransn_p )
+ deallocate (frootn_to_retransn_p )
+ deallocate (livestemn_to_retransn_p )
+ deallocate (livecrootn_to_retransn_p )
+ deallocate (retransn_to_npool_p )
+ deallocate (free_retransn_to_npool_p )
+
+ deallocate (m_leafn_to_litter_p )
+ deallocate (m_frootn_to_litter_p )
+ deallocate (m_livestemn_to_litter_p )
+ deallocate (m_deadstemn_to_litter_p )
+ deallocate (m_livecrootn_to_litter_p )
+ deallocate (m_deadcrootn_to_litter_p )
+ deallocate (m_retransn_to_litter_p )
+
+ deallocate (m_leafn_storage_to_litter_p )
+ deallocate (m_frootn_storage_to_litter_p )
+ deallocate (m_livestemn_storage_to_litter_p )
+ deallocate (m_deadstemn_storage_to_litter_p )
+ deallocate (m_livecrootn_storage_to_litter_p )
+ deallocate (m_deadcrootn_storage_to_litter_p )
+
+ deallocate (m_leafn_xfer_to_litter_p )
+ deallocate (m_frootn_xfer_to_litter_p )
+ deallocate (m_livestemn_xfer_to_litter_p )
+ deallocate (m_deadstemn_xfer_to_litter_p )
+ deallocate (m_livecrootn_xfer_to_litter_p )
+ deallocate (m_deadcrootn_xfer_to_litter_p )
+
+ deallocate (m_leafn_to_fire_p )
+ deallocate (m_frootn_to_fire_p )
+ deallocate (m_livestemn_to_fire_p )
+ deallocate (m_deadstemn_to_fire_p )
+ deallocate (m_livecrootn_to_fire_p )
+ deallocate (m_deadcrootn_to_fire_p )
+
+ deallocate (m_leafn_storage_to_fire_p )
+ deallocate (m_frootn_storage_to_fire_p )
+ deallocate (m_livestemn_storage_to_fire_p )
+ deallocate (m_deadstemn_storage_to_fire_p )
+ deallocate (m_livecrootn_storage_to_fire_p )
+ deallocate (m_deadcrootn_storage_to_fire_p )
+
+ deallocate (m_leafn_xfer_to_fire_p )
+ deallocate (m_frootn_xfer_to_fire_p )
+ deallocate (m_livestemn_xfer_to_fire_p )
+ deallocate (m_deadstemn_xfer_to_fire_p )
+ deallocate (m_livecrootn_xfer_to_fire_p )
+ deallocate (m_deadcrootn_xfer_to_fire_p )
+
+ deallocate (m_livestemn_to_deadstemn_fire_p )
+ deallocate (m_livecrootn_to_deadcrootn_fire_p )
+
+ deallocate (m_retransn_to_fire_p )
+
+ deallocate (m_leafn_to_litter_fire_p )
+ deallocate (m_frootn_to_litter_fire_p )
+ deallocate (m_livestemn_to_litter_fire_p )
+ deallocate (m_deadstemn_to_litter_fire_p )
+ deallocate (m_livecrootn_to_litter_fire_p )
+ deallocate (m_deadcrootn_to_litter_fire_p )
+
+ deallocate (m_leafn_storage_to_litter_fire_p )
+ deallocate (m_frootn_storage_to_litter_fire_p )
+ deallocate (m_livestemn_storage_to_litter_fire_p )
+ deallocate (m_deadstemn_storage_to_litter_fire_p )
+ deallocate (m_livecrootn_storage_to_litter_fire_p)
+ deallocate (m_deadcrootn_storage_to_litter_fire_p)
+
+ deallocate (m_leafn_xfer_to_litter_fire_p )
+ deallocate (m_frootn_xfer_to_litter_fire_p )
+ deallocate (m_livestemn_xfer_to_litter_fire_p )
+ deallocate (m_deadstemn_xfer_to_litter_fire_p )
+ deallocate (m_livecrootn_xfer_to_litter_fire_p )
+ deallocate (m_deadcrootn_xfer_to_litter_fire_p )
+
+ deallocate (m_retransn_to_litter_fire_p )
+
+ deallocate (npool_to_leafn_p )
+ deallocate (npool_to_leafn_storage_p )
+ deallocate (npool_to_frootn_p )
+ deallocate (npool_to_frootn_storage_p )
+ deallocate (npool_to_livestemn_p )
+ deallocate (npool_to_livestemn_storage_p )
+ deallocate (npool_to_deadstemn_p )
+ deallocate (npool_to_deadstemn_storage_p )
+ deallocate (npool_to_livecrootn_p )
+ deallocate (npool_to_livecrootn_storage_p )
+ deallocate (npool_to_deadcrootn_p )
+ deallocate (npool_to_deadcrootn_storage_p )
+ deallocate (npool_to_grainn_p )
+ deallocate (npool_to_grainn_storage_p )
+
+ deallocate (respcsun_p )
+ deallocate (respcsha_p )
+ deallocate (leaf_mr_p )
+ deallocate (froot_mr_p )
+ deallocate (livestem_mr_p )
+ deallocate (livecroot_mr_p )
+ deallocate (grain_mr_p )
+
+ deallocate (soil_change_p )
+
+ deallocate (psn_to_cpool_p )
+ deallocate (gpp_p )
+ deallocate (availc_p )
+ deallocate (avail_retransn_p )
+ deallocate (xsmrpool_recover_p )
+ deallocate (excess_cflux_p )
+ deallocate (sminn_to_npool_p )
+
+ deallocate (plant_calloc_p )
+ deallocate (plant_nalloc_p )
+ deallocate (leaf_curmr_p )
+ deallocate (froot_curmr_p )
+ deallocate (livestem_curmr_p )
+ deallocate (livecroot_curmr_p )
+ deallocate (grain_curmr_p )
+
+ deallocate (fire_closs_p )
+ deallocate (fire_nloss_p )
+ deallocate (wood_harvestc_p )
+ deallocate (wood_harvestn_p )
+ deallocate (grainc_to_cropprodc_p )
+ deallocate (grainn_to_cropprodn_p )
+ deallocate (hrv_xsmrpool_to_atm_p )
+ deallocate (soyfixn_p )
+
+ ENDIF
+ ENDIF
+
+
+ END SUBROUTINE deallocate_1D_BGCPFTFluxes
+
+ SUBROUTINE set_1D_BGCPFTFluxes(Values, Nan)
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CoLM PFT 1d [numpft] variables
+ ! --------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+ IMPLICIT NONE
+ real(r8),intent(in) :: Values
+ real(r8),intent(in) :: Nan
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+
+ ! bgc variables
+ leafc_xfer_to_leafc_p (:) = Values
+ frootc_xfer_to_frootc_p (:) = Values
+ livestemc_xfer_to_livestemc_p (:) = Values
+ deadstemc_xfer_to_deadstemc_p (:) = Values
+ livecrootc_xfer_to_livecrootc_p (:) = Values
+ deadcrootc_xfer_to_deadcrootc_p (:) = Values
+ grainc_xfer_to_grainc_p (:) = Values
+
+ leafc_storage_to_xfer_p (:) = Values
+ frootc_storage_to_xfer_p (:) = Values
+ livestemc_storage_to_xfer_p (:) = Values
+ deadstemc_storage_to_xfer_p (:) = Values
+ livecrootc_storage_to_xfer_p (:) = Values
+ deadcrootc_storage_to_xfer_p (:) = Values
+ grainc_storage_to_xfer_p (:) = Values
+ gresp_storage_to_xfer_p (:) = Values
+
+ leafc_to_litter_p (:) = Values
+ frootc_to_litter_p (:) = Values
+ grainc_to_food_p (:) = Values
+ grainc_to_seed_p (:) = Values
+ crop_seedc_to_leaf_p (:) = Values
+ livestemc_to_litter_p (:) = Values
+ livestemc_to_deadstemc_p (:) = Values
+ livecrootc_to_deadcrootc_p (:) = Values
+
+ m_leafc_to_litter_p (:) = Values
+ m_frootc_to_litter_p (:) = Values
+ m_livestemc_to_litter_p (:) = Values
+ m_deadstemc_to_litter_p (:) = Values
+ m_livecrootc_to_litter_p (:) = Values
+ m_deadcrootc_to_litter_p (:) = Values
+
+ m_leafc_storage_to_litter_p (:) = Values
+ m_frootc_storage_to_litter_p (:) = Values
+ m_livestemc_storage_to_litter_p (:) = Values
+ m_deadstemc_storage_to_litter_p (:) = Values
+ m_livecrootc_storage_to_litter_p (:) = Values
+ m_deadcrootc_storage_to_litter_p (:) = Values
+ m_gresp_storage_to_litter_p (:) = Values
+
+ m_leafc_xfer_to_litter_p (:) = Values
+ m_frootc_xfer_to_litter_p (:) = Values
+ m_livestemc_xfer_to_litter_p (:) = Values
+ m_deadstemc_xfer_to_litter_p (:) = Values
+ m_livecrootc_xfer_to_litter_p (:) = Values
+ m_deadcrootc_xfer_to_litter_p (:) = Values
+ m_gresp_xfer_to_litter_p (:) = Values
+
+ m_leafc_to_fire_p (:) = Values
+ m_frootc_to_fire_p (:) = Values
+ m_livestemc_to_fire_p (:) = Values
+ m_deadstemc_to_fire_p (:) = Values
+ m_livecrootc_to_fire_p (:) = Values
+ m_deadcrootc_to_fire_p (:) = Values
+
+ m_leafc_storage_to_fire_p (:) = Values
+ m_frootc_storage_to_fire_p (:) = Values
+ m_livestemc_storage_to_fire_p (:) = Values
+ m_deadstemc_storage_to_fire_p (:) = Values
+ m_livecrootc_storage_to_fire_p (:) = Values
+ m_deadcrootc_storage_to_fire_p (:) = Values
+ m_gresp_storage_to_fire_p (:) = Values
+
+ m_leafc_xfer_to_fire_p (:) = Values
+ m_frootc_xfer_to_fire_p (:) = Values
+ m_livestemc_xfer_to_fire_p (:) = Values
+ m_deadstemc_xfer_to_fire_p (:) = Values
+ m_livecrootc_xfer_to_fire_p (:) = Values
+ m_deadcrootc_xfer_to_fire_p (:) = Values
+ m_gresp_xfer_to_fire_p (:) = Values
+
+ m_livestemc_to_deadstemc_fire_p (:) = Values
+ m_livecrootc_to_deadcrootc_fire_p (:) = Values
+
+ m_leafc_to_litter_fire_p (:) = Values
+ m_frootc_to_litter_fire_p (:) = Values
+ m_livestemc_to_litter_fire_p (:) = Values
+ m_deadstemc_to_litter_fire_p (:) = Values
+ m_livecrootc_to_litter_fire_p (:) = Values
+ m_deadcrootc_to_litter_fire_p (:) = Values
+
+ m_leafc_storage_to_litter_fire_p (:) = Values
+ m_frootc_storage_to_litter_fire_p (:) = Values
+ m_livestemc_storage_to_litter_fire_p (:) = Values
+ m_deadstemc_storage_to_litter_fire_p (:) = Values
+ m_livecrootc_storage_to_litter_fire_p(:) = Values
+ m_deadcrootc_storage_to_litter_fire_p(:) = Values
+ m_gresp_storage_to_litter_fire_p (:) = Values
+
+ m_leafc_xfer_to_litter_fire_p (:) = Values
+ m_frootc_xfer_to_litter_fire_p (:) = Values
+ m_livestemc_xfer_to_litter_fire_p (:) = Values
+ m_deadstemc_xfer_to_litter_fire_p (:) = Values
+ m_livecrootc_xfer_to_litter_fire_p (:) = Values
+ m_deadcrootc_xfer_to_litter_fire_p (:) = Values
+ m_gresp_xfer_to_litter_fire_p (:) = Values
+
+ cpool_to_xsmrpool_p (:) = Values
+ cpool_to_gresp_storage_p (:) = Values
+ cpool_to_leafc_p (:) = Values
+ cpool_to_leafc_storage_p (:) = Values
+ cpool_to_frootc_p (:) = Values
+ cpool_to_frootc_storage_p (:) = Values
+ cpool_to_livestemc_p (:) = Values
+ cpool_to_livestemc_storage_p (:) = Values
+ cpool_to_deadstemc_p (:) = Values
+ cpool_to_deadstemc_storage_p (:) = Values
+ cpool_to_livecrootc_p (:) = Values
+ cpool_to_livecrootc_storage_p (:) = Values
+ cpool_to_deadcrootc_p (:) = Values
+ cpool_to_deadcrootc_storage_p (:) = Values
+ cpool_to_grainc_p (:) = Values
+ cpool_to_grainc_storage_p (:) = Values
+
+ leaf_xsmr_p (:) = Values
+ froot_xsmr_p (:) = Values
+ livestem_xsmr_p (:) = Values
+ livecroot_xsmr_p (:) = Values
+ grain_xsmr_p (:) = Values
+
+ cpool_leaf_gr_p (:) = Values
+ cpool_froot_gr_p (:) = Values
+ cpool_livestem_gr_p (:) = Values
+ cpool_deadstem_gr_p (:) = Values
+ cpool_livecroot_gr_p (:) = Values
+ cpool_deadcroot_gr_p (:) = Values
+ cpool_grain_gr_p (:) = Values
+
+ cpool_leaf_storage_gr_p (:) = Values
+ cpool_froot_storage_gr_p (:) = Values
+ cpool_livestem_storage_gr_p (:) = Values
+ cpool_deadstem_storage_gr_p (:) = Values
+ cpool_livecroot_storage_gr_p (:) = Values
+ cpool_deadcroot_storage_gr_p (:) = Values
+ cpool_grain_storage_gr_p (:) = Values
+
+ transfer_leaf_gr_p (:) = Values
+ transfer_froot_gr_p (:) = Values
+ transfer_livestem_gr_p (:) = Values
+ transfer_deadstem_gr_p (:) = Values
+ transfer_livecroot_gr_p (:) = Values
+ transfer_deadcroot_gr_p (:) = Values
+ transfer_grain_gr_p (:) = Values
+
+ xsmrpool_to_atm_p (:) = Values
+
+ cropprod1c_loss_p (:) = Values
+
+ plant_ndemand_p (:) = Values
+
+ leafn_xfer_to_leafn_p (:) = Values
+ frootn_xfer_to_frootn_p (:) = Values
+ livestemn_xfer_to_livestemn_p (:) = Values
+ deadstemn_xfer_to_deadstemn_p (:) = Values
+ livecrootn_xfer_to_livecrootn_p (:) = Values
+ deadcrootn_xfer_to_deadcrootn_p (:) = Values
+ grainn_xfer_to_grainn_p (:) = Values
+
+ leafn_storage_to_xfer_p (:) = Values
+ frootn_storage_to_xfer_p (:) = Values
+ livestemn_storage_to_xfer_p (:) = Values
+ deadstemn_storage_to_xfer_p (:) = Values
+ livecrootn_storage_to_xfer_p (:) = Values
+ deadcrootn_storage_to_xfer_p (:) = Values
+ grainn_storage_to_xfer_p (:) = Values
+
+ leafn_to_litter_p (:) = Values
+ frootn_to_litter_p (:) = Values
+ grainn_to_food_p (:) = Values
+ grainn_to_seed_p (:) = Values
+ crop_seedn_to_leaf_p (:) = Values
+ livestemn_to_litter_p (:) = Values
+ livestemn_to_deadstemn_p (:) = Values
+ livecrootn_to_deadcrootn_p (:) = Values
+
+ leafn_to_retransn_p (:) = Values
+ frootn_to_retransn_p (:) = Values
+ livestemn_to_retransn_p (:) = Values
+ livecrootn_to_retransn_p (:) = Values
+ retransn_to_npool_p (:) = Values
+ free_retransn_to_npool_p (:) = Values
+
+ m_leafn_to_litter_p (:) = Values
+ m_frootn_to_litter_p (:) = Values
+ m_livestemn_to_litter_p (:) = Values
+ m_deadstemn_to_litter_p (:) = Values
+ m_livecrootn_to_litter_p (:) = Values
+ m_deadcrootn_to_litter_p (:) = Values
+ m_retransn_to_litter_p (:) = Values
+
+ m_leafn_storage_to_litter_p (:) = Values
+ m_frootn_storage_to_litter_p (:) = Values
+ m_livestemn_storage_to_litter_p (:) = Values
+ m_deadstemn_storage_to_litter_p (:) = Values
+ m_livecrootn_storage_to_litter_p (:) = Values
+ m_deadcrootn_storage_to_litter_p (:) = Values
+
+ m_leafn_xfer_to_litter_p (:) = Values
+ m_frootn_xfer_to_litter_p (:) = Values
+ m_livestemn_xfer_to_litter_p (:) = Values
+ m_deadstemn_xfer_to_litter_p (:) = Values
+ m_livecrootn_xfer_to_litter_p (:) = Values
+ m_deadcrootn_xfer_to_litter_p (:) = Values
+
+ m_leafn_to_fire_p (:) = Values
+ m_frootn_to_fire_p (:) = Values
+ m_livestemn_to_fire_p (:) = Values
+ m_deadstemn_to_fire_p (:) = Values
+ m_livecrootn_to_fire_p (:) = Values
+ m_deadcrootn_to_fire_p (:) = Values
+
+ m_leafn_storage_to_fire_p (:) = Values
+ m_frootn_storage_to_fire_p (:) = Values
+ m_livestemn_storage_to_fire_p (:) = Values
+ m_deadstemn_storage_to_fire_p (:) = Values
+ m_livecrootn_storage_to_fire_p (:) = Values
+ m_deadcrootn_storage_to_fire_p (:) = Values
+
+ m_leafn_xfer_to_fire_p (:) = Values
+ m_frootn_xfer_to_fire_p (:) = Values
+ m_livestemn_xfer_to_fire_p (:) = Values
+ m_deadstemn_xfer_to_fire_p (:) = Values
+ m_livecrootn_xfer_to_fire_p (:) = Values
+ m_deadcrootn_xfer_to_fire_p (:) = Values
+
+ m_livestemn_to_deadstemn_fire_p (:) = Values
+ m_livecrootn_to_deadcrootn_fire_p (:) = Values
+
+ m_retransn_to_fire_p (:) = Values
+
+ m_leafn_to_litter_fire_p (:) = Values
+ m_frootn_to_litter_fire_p (:) = Values
+ m_livestemn_to_litter_fire_p (:) = Values
+ m_deadstemn_to_litter_fire_p (:) = Values
+ m_livecrootn_to_litter_fire_p (:) = Values
+ m_deadcrootn_to_litter_fire_p (:) = Values
+
+ m_leafn_storage_to_litter_fire_p (:) = Values
+ m_frootn_storage_to_litter_fire_p (:) = Values
+ m_livestemn_storage_to_litter_fire_p (:) = Values
+ m_deadstemn_storage_to_litter_fire_p (:) = Values
+ m_livecrootn_storage_to_litter_fire_p(:) = Values
+ m_deadcrootn_storage_to_litter_fire_p(:) = Values
+
+ m_leafn_xfer_to_litter_fire_p (:) = Values
+ m_frootn_xfer_to_litter_fire_p (:) = Values
+ m_livestemn_xfer_to_litter_fire_p (:) = Values
+ m_deadstemn_xfer_to_litter_fire_p (:) = Values
+ m_livecrootn_xfer_to_litter_fire_p (:) = Values
+ m_deadcrootn_xfer_to_litter_fire_p (:) = Values
+
+ m_retransn_to_litter_fire_p (:) = Values
+
+ npool_to_leafn_p (:) = Values
+ npool_to_leafn_storage_p (:) = Values
+ npool_to_frootn_p (:) = Values
+ npool_to_frootn_storage_p (:) = Values
+ npool_to_livestemn_p (:) = Values
+ npool_to_livestemn_storage_p (:) = Values
+ npool_to_deadstemn_p (:) = Values
+ npool_to_deadstemn_storage_p (:) = Values
+ npool_to_livecrootn_p (:) = Values
+ npool_to_livecrootn_storage_p (:) = Values
+ npool_to_deadcrootn_p (:) = Values
+ npool_to_deadcrootn_storage_p (:) = Values
+ npool_to_grainn_p (:) = Values
+ npool_to_grainn_storage_p (:) = Values
+
+ respcsun_p (:) = Values!sunlit leaf respiration
+ respcsha_p (:) = Values!shaded leaf respiration
+ leaf_mr_p (:) = Values!leaf maintenance respiration
+ froot_mr_p (:) = Values!fine root maintenance respiration
+ livestem_mr_p (:) = Values!live stem maintenance respiration
+ livecroot_mr_p (:) = Values!live coarse root maintenance respiration
+ grain_mr_p (:) = Values!grain maintenance respiration
+
+ soil_change_p (:) = Values
+
+ psn_to_cpool_p (:) = Values
+ gpp_p (:) = Values
+ availc_p (:) = Values
+ avail_retransn_p (:) = Values
+ xsmrpool_recover_p (:) = Values
+ excess_cflux_p (:) = Values
+ sminn_to_npool_p (:) = Values
+
+ plant_calloc_p (:) = Values
+ plant_nalloc_p (:) = Values
+ leaf_curmr_p (:) = Values
+ froot_curmr_p (:) = Values
+ livestem_curmr_p (:) = Values
+ livecroot_curmr_p (:) = Values
+ grain_curmr_p (:) = Values
+
+ fire_closs_p (:) = Values
+ fire_nloss_p (:) = Values
+ wood_harvestc_p (:) = Values
+ wood_harvestn_p (:) = Values
+ grainc_to_cropprodc_p (:) = Values
+ grainn_to_cropprodn_p (:) = Values
+ hrv_xsmrpool_to_atm_p (:) = Values
+ soyfixn_p (:) = Values
+
+ ENDIF
+ ENDIF
+
+!--------
+
+ END SUBROUTINE set_1D_BGCPFTFluxes
+#endif
+
+END MODULE MOD_BGC_Vars_1DPFTFluxes
+
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_PFTimeVariables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_PFTimeVariables.F90
new file mode 100644
index 0000000000..b91c4e7301
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_PFTimeVariables.F90
@@ -0,0 +1,2696 @@
+#include
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+MODULE MOD_BGC_Vars_PFTimeVariables
+
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! Define, allocate, and deallocate biogeochemical state variables at pft level.
+! Read and write biogeochemical state variables at pft level from/to restart files.
+
+! !ORIGINAL:
+! Xingjie Lu, 2022, created the original version
+
+#ifdef BGC
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_TimeManager
+
+ IMPLICIT NONE
+ SAVE
+! -----------------------------------------------------------------
+! Time-varying state variables which required by restart run
+!--------------------- bgc variables ---------------------------------------
+ real(r8), allocatable :: leafc_p (:) ! leaf display C (gC m-2)
+ real(r8), allocatable :: leafc_storage_p (:) ! leaf storage C (gC m-2)
+ real(r8), allocatable :: leafc_xfer_p (:) ! leaf transfer C (gC m-2)
+ real(r8), allocatable :: frootc_p (:) ! fine root display C (gC m-2)
+ real(r8), allocatable :: frootc_storage_p (:) ! fine root storage C (gC m-2)
+ real(r8), allocatable :: frootc_xfer_p (:) ! fine root transfer C (gC m-2)
+ real(r8), allocatable :: livestemc_p (:) ! live stem display C (gC m-2)
+ real(r8), allocatable :: livestemc_storage_p (:) ! live stem storage C (gC m-2)
+ real(r8), allocatable :: livestemc_xfer_p (:) ! live stem transfer C (gC m-2)
+ real(r8), allocatable :: deadstemc_p (:) ! dead stem display C (gC m-2)
+ real(r8), allocatable :: deadstemc_storage_p (:) ! dead stem storage C (gC m-2)
+ real(r8), allocatable :: deadstemc_xfer_p (:) ! dead stem transfer C (gC m-2)
+ real(r8), allocatable :: livecrootc_p (:) ! live coarse root display C (gC m-2)
+ real(r8), allocatable :: livecrootc_storage_p (:) ! live coarse root storage C (gC m-2)
+ real(r8), allocatable :: livecrootc_xfer_p (:) ! live coarse root transfer C (gC m-2)
+ real(r8), allocatable :: deadcrootc_p (:) ! dead coarse root display C (gC m-2)
+ real(r8), allocatable :: deadcrootc_storage_p (:) ! dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: deadcrootc_xfer_p (:) ! dead coarse root transfer C (gC m-2)
+ real(r8), allocatable :: grainc_p (:) ! grain display C (gC m-2)
+ real(r8), allocatable :: grainc_storage_p (:) ! grain storage C (gC m-2)
+ real(r8), allocatable :: grainc_xfer_p (:) ! grain transfer C (gC m-2)
+ real(r8), allocatable :: cropseedc_deficit_p (:) ! crop seed deficit C (gC m-2)
+ real(r8), allocatable :: cropprod1c_p (:) ! product C (gC m-2)
+ real(r8), allocatable :: xsmrpool_p (:) ! maintenance respiration storage C (gC m-2)
+ real(r8), allocatable :: gresp_storage_p (:) ! growth respiration storage C (gC m-2)
+ real(r8), allocatable :: gresp_xfer_p (:) ! growth respiration transfer C (gC m-2)
+ real(r8), allocatable :: cpool_p (:) ! available C (gC m-2)
+ real(r8), allocatable :: totvegc_p (:) ! total vegetation C, including available C (gC m-2)
+
+ real(r8), allocatable :: leaf_prof_p (:,:) ! vertical profile of leaves input to litter (m-1)
+ real(r8), allocatable :: stem_prof_p (:,:) ! vertical profile of stem input to litter (m-1)
+ real(r8), allocatable :: froot_prof_p (:,:) ! vertical profile of fine roots input to litter (m-1)
+ real(r8), allocatable :: croot_prof_p (:,:) ! vertical profile of coarse roots input to litter (m-1)
+ real(r8), allocatable :: cinput_rootfr_p (:,:) ! root fraction used for calculating vertical profile of roots input to litter (m-1)
+
+ real(r8), allocatable :: leafn_p (:) ! leaf display N (gN m-2)
+ real(r8), allocatable :: leafn_storage_p (:) ! leaf storage N (gN m-2)
+ real(r8), allocatable :: leafn_xfer_p (:) ! leaf transfer N (gN m-2)
+ real(r8), allocatable :: frootn_p (:) ! fine root display N (gN m-2)
+ real(r8), allocatable :: frootn_storage_p (:) ! fine root storage N (gN m-2)
+ real(r8), allocatable :: frootn_xfer_p (:) ! fine root transfer N (gN m-2)
+ real(r8), allocatable :: livestemn_p (:) ! live stem display N (gN m-2)
+ real(r8), allocatable :: livestemn_storage_p (:) ! live stem storage N (gN m-2)
+ real(r8), allocatable :: livestemn_xfer_p (:) ! live stem transfer N (gN m-2)
+ real(r8), allocatable :: deadstemn_p (:) ! dead stem display N (gN m-2)
+ real(r8), allocatable :: deadstemn_storage_p (:) ! dead stem storage N (gN m-2)
+ real(r8), allocatable :: deadstemn_xfer_p (:) ! dead stem transfer N (gN m-2)
+ real(r8), allocatable :: livecrootn_p (:) ! live coarse root display N (gN m-2)
+ real(r8), allocatable :: livecrootn_storage_p (:) ! live coarse root storage N (gN m-2)
+ real(r8), allocatable :: livecrootn_xfer_p (:) ! live coarse root transfer N (gN m-2)
+ real(r8), allocatable :: deadcrootn_p (:) ! dead coarse root display N (gN m-2)
+ real(r8), allocatable :: deadcrootn_storage_p (:) ! dead coarse root storage N (gN m-2)
+ real(r8), allocatable :: deadcrootn_xfer_p (:) ! dead coarse root transfer N (gN m-2)
+ real(r8), allocatable :: grainn_p (:) ! grain display N (gN m-2)
+ real(r8), allocatable :: grainn_storage_p (:) ! grain storage N (gN m-2)
+ real(r8), allocatable :: grainn_xfer_p (:) ! grain transfer N (gN m-2)
+ real(r8), allocatable :: cropseedn_deficit_p (:) ! crop seed deficit N (gN m-2)
+ real(r8), allocatable :: harvdate_p (:) ! harvest date
+ integer , allocatable :: nyrs_crop_active_p (:) ! number of years of this crop has been active to calculate climate GDD
+ real(r8), allocatable :: retransn_p (:) ! retranslocated N (gN m-2)
+ real(r8), allocatable :: totvegn_p (:) ! total vegetation N, including available N (gN m-2)
+
+ real(r8), allocatable :: tempsum_potential_gpp_p (:) ! temporary annual sum of potential GPP (gC m-2)
+ real(r8), allocatable :: tempmax_retransn_p (:) ! temporary annual max of retranslocated N (gN m-2)
+ real(r8), allocatable :: tempavg_tref_p (:) ! temporary annual average 2m air temperature (degree C)
+ real(r8), allocatable :: tempsum_npp_p (:) ! temporary annual sum NPP (gC m-2)
+ real(r8), allocatable :: tempsum_litfall_p (:) ! temporary annual sum litterfall (gC m-2)
+ real(r8), allocatable :: annsum_potential_gpp_p (:) ! annual sum of potential GPP (gC m-2)
+ real(r8), allocatable :: annmax_retransn_p (:) ! annual max of retranslocated N (gN m-2)
+ real(r8), allocatable :: annavg_tref_p (:) ! annual average 2m air temperature (degree C)
+ real(r8), allocatable :: annsum_npp_p (:) ! annual sum NPP (gC m-2)
+ real(r8), allocatable :: annsum_litfall_p (:) ! annual sum litterfall (gC m-2)
+
+ real(r8), allocatable :: bglfr_p (:) ! background litterfall rate (1/s)
+ real(r8), allocatable :: bgtr_p (:) ! background transfer rate (1/s)
+ real(r8), allocatable :: lgsf_p (:) ! long growing season factor (0-1)
+ real(r8), allocatable :: gdd0_p (:) ! GDD based on 0 degree C
+ real(r8), allocatable :: gdd8_p (:) ! GDD based on 8 degree C
+ real(r8), allocatable :: gdd10_p (:) ! GDD based on 10 degree C
+ real(r8), allocatable :: gdd020_p (:) ! 20-year mean of GDD based on 0 degree C
+ real(r8), allocatable :: gdd820_p (:) ! 20-year mean of GDD based on 8 degree C
+ real(r8), allocatable :: gdd1020_p (:) ! 20-year mean of GDD based on 10 degree C
+
+ real(r8), allocatable :: offset_flag_p (:) ! flag, 1 if offset
+ real(r8), allocatable :: offset_counter_p (:) ! time left for offset (s)
+ real(r8), allocatable :: onset_flag_p (:) ! flag, 1 if onset
+ real(r8), allocatable :: onset_counter_p (:) ! time left for onset (s)
+ real(r8), allocatable :: onset_gddflag_p (:) ! flag, 1 if begin to accumulate GDD for onset
+ real(r8), allocatable :: onset_gdd_p (:) ! onset GDD
+ real(r8), allocatable :: onset_fdd_p (:) ! onset freezing degree days counter
+ real(r8), allocatable :: onset_swi_p (:) ! onset soil water index
+ real(r8), allocatable :: offset_fdd_p (:) ! offset freezing degree days counter
+ real(r8), allocatable :: offset_swi_p (:) ! offset soil water index
+ real(r8), allocatable :: dormant_flag_p (:) ! flag, 1 if dormancy, 0 if not
+ real(r8), allocatable :: prev_leafc_to_litter_p (:) ! previous timestep leaf display C to litter C (gN m-2 s-1)
+ real(r8), allocatable :: prev_frootc_to_litter_p (:) ! previous timestep fine root display C to litter C (gN m-2 s-1)
+ real(r8), allocatable :: days_active_p (:) ! phenology-associated state: number of days since last dormancy
+
+ real(r8), allocatable :: burndate_p (:) ! burn date for crop
+
+ real(r8), allocatable :: c_allometry_p (:) ! C allocation index
+ real(r8), allocatable :: n_allometry_p (:) ! N allocation index
+ real(r8), allocatable :: downreg_p (:) ! fractional reduction in GPP due to N limitation
+ real(r8), allocatable :: grain_flag_p (:) ! flag, 1 if grain fill, 0 if not
+
+ real(r8), allocatable :: ctrunc_p (:) ! additional carbon from precision control, currently not used
+ real(r8), allocatable :: ntrunc_p (:) ! additional nitrogen from precision control, currently not used
+ real(r8), allocatable :: npool_p (:) ! available N (gN m-2)
+
+!--------------------- CROP variables for GPAM------------------------------
+#ifdef CROP
+ logical, allocatable :: croplive_p (:) ! flag, true if crop live, not harvested
+ real(r8),allocatable :: hui_p (:) ! heat unit index since planting
+ real(r8),allocatable :: gddplant_p (:) ! GDD since planting
+ integer ,allocatable :: peaklai_p (:) ! flag, 1 if lai at maximum allowed, 0 if lai not at maximum allowed
+ real(r8),allocatable :: aroot_p (:) ! root allocation coefficient
+ real(r8),allocatable :: astem_p (:) ! stem allocation coefficient
+ real(r8),allocatable :: arepr_p (:) ! reproduction (fruit) allocation coefficient
+ real(r8),allocatable :: aleaf_p (:) ! leaf allocation coefficient
+ real(r8),allocatable :: astemi_p (:) ! stem allocation coefficient of phase 2
+ real(r8),allocatable :: aleafi_p (:) ! leaf allocation coefficient of phase 2
+ real(r8),allocatable :: gddmaturity_p (:) ! gdd needed to harvest
+
+ logical, allocatable :: cropplant_p (:) ! flag, true if crop planted, not harvested; but if winter cereal still live at begin of the year, it will be set false
+ integer ,allocatable :: idop_p (:) ! planting date
+ real(r8),allocatable :: a5tmin_p (:) ! 5-day running mean of min 2 m temperature (degree C)
+ real(r8),allocatable :: a10tmin_p (:) ! 10-day running mean of min 2 m temperature (degree C)
+ real(r8),allocatable :: t10_p (:) ! 10-day running mean of 2 m temperature (degree C)
+ real(r8),allocatable :: cumvd_p (:) ! effective vernalization days (d)
+ real(r8),allocatable :: vf_p (:) ! vernalization factor (0-1)
+ real(r8),allocatable :: cphase_p (:) ! phenology phase
+ real(r8),allocatable :: fert_counter_p (:) ! time left to fertilize (s)
+ real(r8),allocatable :: tref_min_p (:) ! daily min of average 2-m temperature (degree C)
+ real(r8),allocatable :: tref_max_p (:) ! daily max of average 2-m temperature (degree C)
+ real(r8),allocatable :: tref_min_inst_p (:) ! temporary daily min of average 2-m temperature (degree C)
+ real(r8),allocatable :: tref_max_inst_p (:) ! temporary daily max of average 2-m temperature (degree C)
+ real(r8),allocatable :: fertnitro_p (:) ! fertilizer nitrogen (gN m-2)
+ real(r8),allocatable :: manunitro_p (:) ! manure nitrogen (gN m-2)
+ real(r8),allocatable :: fert_p (:) ! fertilizer nitrogen (gN m-2) including manure
+ real(r8),allocatable :: latbaset_p (:) ! latitude vary base temperature for gddplant (degree C)
+ real(r8),allocatable :: plantdate_p (:) ! planting date (input)
+#endif
+! --------------------- END CROP variables -------------------------
+
+! --------------------- SASU variables -----------------------------
+ real(r8), allocatable :: leafcCap_p (:) ! leaf display C (gC m-2)
+ real(r8), allocatable :: leafc_storageCap_p (:) ! leaf storage C (gC m-2)
+ real(r8), allocatable :: leafc_xferCap_p (:) ! leaf transfer C (gC m-2)
+ real(r8), allocatable :: frootcCap_p (:) ! fine root display C (gC m-2)
+ real(r8), allocatable :: frootc_storageCap_p (:) ! fine root storage C (gC m-2)
+ real(r8), allocatable :: frootc_xferCap_p (:) ! fine root transfer C (gC m-2)
+ real(r8), allocatable :: livestemcCap_p (:) ! live stem display C (gC m-2)
+ real(r8), allocatable :: livestemc_storageCap_p (:) ! live stem storage C (gC m-2)
+ real(r8), allocatable :: livestemc_xferCap_p (:) ! live stem transfer C (gC m-2)
+ real(r8), allocatable :: deadstemcCap_p (:) ! dead stem display C (gC m-2)
+ real(r8), allocatable :: deadstemc_storageCap_p (:) ! dead stem storage C (gC m-2)
+ real(r8), allocatable :: deadstemc_xferCap_p (:) ! dead stem transfer C (gC m-2)
+ real(r8), allocatable :: livecrootcCap_p (:) ! live coarse root display C (gC m-2)
+ real(r8), allocatable :: livecrootc_storageCap_p (:) ! live coarse root storage C (gC m-2)
+ real(r8), allocatable :: livecrootc_xferCap_p (:) ! live coarse root transfer C (gC m-2)
+ real(r8), allocatable :: deadcrootcCap_p (:) ! dead coarse root display C (gC m-2)
+ real(r8), allocatable :: deadcrootc_storageCap_p (:) ! dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: deadcrootc_xferCap_p (:) ! dead coarse root transfer C (gC m-2)
+
+ real(r8), allocatable :: leafnCap_p (:) ! leaf display C (gC m-2)
+ real(r8), allocatable :: leafn_storageCap_p (:) ! leaf storage C (gC m-2)
+ real(r8), allocatable :: leafn_xferCap_p (:) ! leaf transfer C (gC m-2)
+ real(r8), allocatable :: frootnCap_p (:) ! fine root display C (gC m-2)
+ real(r8), allocatable :: frootn_storageCap_p (:) ! fine root storage C (gC m-2)
+ real(r8), allocatable :: frootn_xferCap_p (:) ! fine root transfer C (gC m-2)
+ real(r8), allocatable :: livestemnCap_p (:) ! live stem display C (gC m-2)
+ real(r8), allocatable :: livestemn_storageCap_p (:) ! live stem storage C (gC m-2)
+ real(r8), allocatable :: livestemn_xferCap_p (:) ! live stem transfer C (gC m-2)
+ real(r8), allocatable :: deadstemnCap_p (:) ! dead stem display C (gC m-2)
+ real(r8), allocatable :: deadstemn_storageCap_p (:) ! dead stem storage C (gC m-2)
+ real(r8), allocatable :: deadstemn_xferCap_p (:) ! dead stem transfer C (gC m-2)
+ real(r8), allocatable :: livecrootnCap_p (:) ! live coarse root display C (gC m-2)
+ real(r8), allocatable :: livecrootn_storageCap_p (:) ! live coarse root storage C (gC m-2)
+ real(r8), allocatable :: livecrootn_xferCap_p (:) ! live coarse root transfer C (gC m-2)
+ real(r8), allocatable :: deadcrootnCap_p (:) ! dead coarse root display C (gC m-2)
+ real(r8), allocatable :: deadcrootn_storageCap_p (:) ! dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: deadcrootn_xferCap_p (:) ! dead coarse root transfer C (gC m-2)
+
+ real(r8), allocatable :: leafc0_p (:) ! SASU spinup initial value: leaf display C (gC m-2)
+ real(r8), allocatable :: leafc0_storage_p (:) ! SASU spinup initial value: leaf storage C (gC m-2)
+ real(r8), allocatable :: leafc0_xfer_p (:) ! SASU spinup initial value: leaf transfer C (gC m-2)
+ real(r8), allocatable :: frootc0_p (:) ! SASU spinup initial value: fine root display C (gC m-2)
+ real(r8), allocatable :: frootc0_storage_p (:) ! SASU spinup initial value: fine root storage C (gC m-2)
+ real(r8), allocatable :: frootc0_xfer_p (:) ! SASU spinup initial value: fine root transfer C (gC m-2)
+ real(r8), allocatable :: livestemc0_p (:) ! SASU spinup initial value: live stem display C (gC m-2)
+ real(r8), allocatable :: livestemc0_storage_p (:) ! SASU spinup initial value: live stem storage C (gC m-2)
+ real(r8), allocatable :: livestemc0_xfer_p (:) ! SASU spinup initial value: live stem transfer C (gC m-2)
+ real(r8), allocatable :: deadstemc0_p (:) ! SASU spinup initial value: dead stem display C (gC m-2)
+ real(r8), allocatable :: deadstemc0_storage_p (:) ! SASU spinup initial value: dead stem storage C (gC m-2)
+ real(r8), allocatable :: deadstemc0_xfer_p (:) ! SASU spinup initial value: dead stem transfer C (gC m-2)
+ real(r8), allocatable :: livecrootc0_p (:) ! SASU spinup initial value: live coarse root display C (gC m-2)
+ real(r8), allocatable :: livecrootc0_storage_p (:) ! SASU spinup initial value: live coarse root storage C (gC m-2)
+ real(r8), allocatable :: livecrootc0_xfer_p (:) ! SASU spinup initial value: live coarse root transfer C (gC m-2)
+ real(r8), allocatable :: deadcrootc0_p (:) ! SASU spinup initial value: dead coarse root display C (gC m-2)
+ real(r8), allocatable :: deadcrootc0_storage_p (:) ! SASU spinup initial value: dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: deadcrootc0_xfer_p (:) ! SASU spinup initial value: dead coarse root transfer C (gC m-2)
+ real(r8), allocatable :: grainc0_p (:) ! SASU spinup initial value: grain display C (gC m-2)
+ real(r8), allocatable :: grainc0_storage_p (:) ! SASU spinup initial value: grain storage C (gC m-2)
+ real(r8), allocatable :: grainc0_xfer_p (:) ! SASU spinup initial value: grain transfer C (gC m-2)
+
+ real(r8), allocatable :: leafn0_p (:) ! SASU spinup initial value: leaf display N (gN m-2)
+ real(r8), allocatable :: leafn0_storage_p (:) ! SASU spinup initial value: leaf storage N (gN m-2)
+ real(r8), allocatable :: leafn0_xfer_p (:) ! SASU spinup initial value: leaf transfer N (gN m-2)
+ real(r8), allocatable :: frootn0_p (:) ! SASU spinup initial value: fine root display N (gN m-2)
+ real(r8), allocatable :: frootn0_storage_p (:) ! SASU spinup initial value: fine root storage N (gN m-2)
+ real(r8), allocatable :: frootn0_xfer_p (:) ! SASU spinup initial value: fine root transfer N (gN m-2)
+ real(r8), allocatable :: livestemn0_p (:) ! SASU spinup initial value: live stem display N (gN m-2)
+ real(r8), allocatable :: livestemn0_storage_p (:) ! SASU spinup initial value: live stem storage N (gN m-2)
+ real(r8), allocatable :: livestemn0_xfer_p (:) ! SASU spinup initial value: live stem transfer N (gN m-2)
+ real(r8), allocatable :: deadstemn0_p (:) ! SASU spinup initial value: dead stem display N (gN m-2)
+ real(r8), allocatable :: deadstemn0_storage_p (:) ! SASU spinup initial value: dead stem storage N (gN m-2)
+ real(r8), allocatable :: deadstemn0_xfer_p (:) ! SASU spinup initial value: dead stem transfer N (gN m-2)
+ real(r8), allocatable :: livecrootn0_p (:) ! SASU spinup initial value: live coarse root display N (gN m-2)
+ real(r8), allocatable :: livecrootn0_storage_p (:) ! SASU spinup initial value: live coarse root storage N (gN m-2)
+ real(r8), allocatable :: livecrootn0_xfer_p (:) ! SASU spinup initial value: live coarse root transfer N (gN m-2)
+ real(r8), allocatable :: deadcrootn0_p (:) ! SASU spinup initial value: dead coarse root display N (gN m-2)
+ real(r8), allocatable :: deadcrootn0_storage_p (:) ! SASU spinup initial value: dead coarse root storage N (gN m-2)
+ real(r8), allocatable :: deadcrootn0_xfer_p (:) ! SASU spinup initial value: dead coarse root transfer N (gN m-2)
+ real(r8), allocatable :: grainn0_p (:) ! SASU spinup initial value: grain display N (gN m-2)
+ real(r8), allocatable :: grainn0_storage_p (:) ! SASU spinup initial value: grain storage N (gN m-2)
+ real(r8), allocatable :: grainn0_xfer_p (:) ! SASU spinup initial value: grain transfer N (gN m-2)
+ real(r8), allocatable :: retransn0_p (:) ! SASU spinup initial value: retranslocated N (gN m-2)
+
+ real(r8), allocatable :: I_leafc_p_acc (:) ! SASU spinup diagnostics: accumulated input to leaf display C (gC m-2)
+ real(r8), allocatable :: I_leafc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to leaf storage C (gC m-2)
+ real(r8), allocatable :: I_frootc_p_acc (:) ! SASU spinup diagnostics: accumulated input to fine root display C (gC m-2)
+ real(r8), allocatable :: I_frootc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to fine root storage C (gC m-2)
+ real(r8), allocatable :: I_livestemc_p_acc (:) ! SASU spinup diagnostics: accumulated input to live stem display C (gC m-2)
+ real(r8), allocatable :: I_livestemc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to live stem storage C (gC m-2)
+ real(r8), allocatable :: I_deadstemc_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead stem display C (gC m-2)
+ real(r8), allocatable :: I_deadstemc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead stem storage C (gC m-2)
+ real(r8), allocatable :: I_livecrootc_p_acc (:) ! SASU spinup diagnostics: accumulated input to live coarse root display C (gC m-2)
+ real(r8), allocatable :: I_livecrootc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to live coarse root storage C (gC m-2)
+ real(r8), allocatable :: I_deadcrootc_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead coarse root display C (gC m-2)
+ real(r8), allocatable :: I_deadcrootc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: I_grainc_p_acc (:) ! SASU spinup diagnostics: accumulated input to grain display C (gC m-2)
+ real(r8), allocatable :: I_grainc_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to grain storage C (gC m-2)
+ real(r8), allocatable :: I_leafn_p_acc (:) ! SASU spinup diagnostics: accumulated input to leaf display N (gN m-2)
+ real(r8), allocatable :: I_leafn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to leaf storage N (gN m-2)
+ real(r8), allocatable :: I_frootn_p_acc (:) ! SASU spinup diagnostics: accumulated input to fine root display N (gN m-2)
+ real(r8), allocatable :: I_frootn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to fine root storage N (gN m-2)
+ real(r8), allocatable :: I_livestemn_p_acc (:) ! SASU spinup diagnostics: accumulated input to live stem display N (gN m-2)
+ real(r8), allocatable :: I_livestemn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to live stem storage N (gN m-2)
+ real(r8), allocatable :: I_deadstemn_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead stem display N (gN m-2)
+ real(r8), allocatable :: I_deadstemn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead stem storage N (gN m-2)
+ real(r8), allocatable :: I_livecrootn_p_acc (:) ! SASU spinup diagnostics: accumulated input to live coarse root display N (gN m-2)
+ real(r8), allocatable :: I_livecrootn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to live coarse root storage N (gN m-2)
+ real(r8), allocatable :: I_deadcrootn_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead coarse root display N (gN m-2)
+ real(r8), allocatable :: I_deadcrootn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to dead coarse root storage N (gN m-2)
+ real(r8), allocatable :: I_grainn_p_acc (:) ! SASU spinup diagnostics: accumulated input to grain display N (gN m-2)
+ real(r8), allocatable :: I_grainn_st_p_acc (:) ! SASU spinup diagnostics: accumulated input to grain storage N (gN m-2)
+
+ real(r8), allocatable :: AKX_leafc_xf_to_leafc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from leaf transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_frootc_xf_to_frootc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from fine root transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_livestemc_xf_to_livestemc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_deadstemc_xf_to_deadstemc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead stem transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_livecrootc_xf_to_livecrootc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_deadcrootc_xf_to_deadcrootc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead coarse root transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_grainc_xf_to_grainc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from grain transfer C to display C (gC m-2)
+ real(r8), allocatable :: AKX_livestemc_to_deadstemc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem display C to dead stem display C (gC m-2)
+ real(r8), allocatable :: AKX_livecrootc_to_deadcrootc_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root display C to dead coarse root display C (gC m-2)
+
+ real(r8), allocatable :: AKX_leafc_st_to_leafc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from leaf storage C to transfer C (gC m-2)
+ real(r8), allocatable :: AKX_frootc_st_to_frootc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from fine root storage C to transfer C (gC m-2)
+ real(r8), allocatable :: AKX_livestemc_st_to_livestemc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem storage C to transfer C (gC m-2)
+ real(r8), allocatable :: AKX_deadstemc_st_to_deadstemc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead stem storage C to transfer C (gC m-2)
+ real(r8), allocatable :: AKX_livecrootc_st_to_livecrootc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root storage C to transfer C (gC m-2)
+ real(r8), allocatable :: AKX_deadcrootc_st_to_deadcrootc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead coarse root storage C to transfer C (gC m-2)
+ real(r8), allocatable :: AKX_grainc_st_to_grainc_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from grain storage C to transfer C (gC m-2)
+
+ real(r8), allocatable :: AKX_leafc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from leaf display C (gC m-2)
+ real(r8), allocatable :: AKX_frootc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from fine root display C (gC m-2)
+ real(r8), allocatable :: AKX_livestemc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live stem display C (gC m-2)
+ real(r8), allocatable :: AKX_deadstemc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead stem display C (gC m-2)
+ real(r8), allocatable :: AKX_livecrootc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live coarse root display C (gC m-2)
+ real(r8), allocatable :: AKX_deadcrootc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead coarse root display C (gC m-2)
+ real(r8), allocatable :: AKX_grainc_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from grain display C (gC m-2)
+
+ real(r8), allocatable :: AKX_leafc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from leaf storage C (gC m-2)
+ real(r8), allocatable :: AKX_frootc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from fine root storage C (gC m-2)
+ real(r8), allocatable :: AKX_livestemc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live stem storage C (gC m-2)
+ real(r8), allocatable :: AKX_deadstemc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead stem storage C (gC m-2)
+ real(r8), allocatable :: AKX_livecrootc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live coarse root storage C (gC m-2)
+ real(r8), allocatable :: AKX_deadcrootc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: AKX_grainc_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from grain storage C (gC m-2)
+
+ real(r8), allocatable :: AKX_leafc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from leaf transfer C (gC m-2)
+ real(r8), allocatable :: AKX_frootc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from fine root transfer C (gC m-2)
+ real(r8), allocatable :: AKX_livestemc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live stem transfer C (gC m-2)
+ real(r8), allocatable :: AKX_deadstemc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead stem transfer C (gC m-2)
+ real(r8), allocatable :: AKX_livecrootc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live coarse root transfer C (gC m-2)
+ real(r8), allocatable :: AKX_deadcrootc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead coarse root transfer C (gC m-2)
+ real(r8), allocatable :: AKX_grainc_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from grain transfer C (gC m-2)
+
+ real(r8), allocatable :: AKX_leafn_xf_to_leafn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from leaf transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_frootn_xf_to_frootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from fine root transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_xf_to_livestemn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_deadstemn_xf_to_deadstemn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead stem transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_xf_to_livecrootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_deadcrootn_xf_to_deadcrootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead coarse root transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_grainn_xf_to_grainn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from grain transfer N to display N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_to_deadstemn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem display N to dead stem display N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_to_deadcrootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root display N to dead coarse root display N (gN m-2)
+
+ real(r8), allocatable :: AKX_leafn_st_to_leafn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from leaf storage N to transfer N (gN m-2)
+ real(r8), allocatable :: AKX_frootn_st_to_frootn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from fine root storage N to transfer N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_st_to_livestemn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem storage N to transfer N (gN m-2)
+ real(r8), allocatable :: AKX_deadstemn_st_to_deadstemn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead stem storage N to transfer N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_st_to_livecrootn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root storage N to transfer N (gN m-2)
+ real(r8), allocatable :: AKX_deadcrootn_st_to_deadcrootn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from dead coarse root storage N to transfer N (gN m-2)
+ real(r8), allocatable :: AKX_grainn_st_to_grainn_xf_p_acc (:) ! SASU spinup diagnostics: accumulated flux from grain storage N to transfer N (gN m-2)
+
+ real(r8), allocatable :: AKX_leafn_to_retransn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from leaf display N to retranslocated N (gN m-2)
+ real(r8), allocatable :: AKX_frootn_to_retransn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from fine root display N to retranslocated N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_to_retransn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live stem display N to retranslocated N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_to_retransn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from live coarse root display N to retranslocated N (gN m-2)
+
+ real(r8), allocatable :: AKX_retransn_to_leafn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to leaf display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_frootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to fine root display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_livestemn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to live stem display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_deadstemn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to dead stem display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_livecrootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to live coarse root display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_deadcrootn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to dead coarse root display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_grainn_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to grain display N (gN m-2)
+
+ real(r8), allocatable :: AKX_retransn_to_leafn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to leaf storage N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_frootn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to fine root storage N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_livestemn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to live stem storage N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_deadstemn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to dead stem storage N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_livecrootn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to live coarse root storage N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_deadcrootn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to dead coarse root storage N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_to_grainn_st_p_acc (:) ! SASU spinup diagnostics: accumulated flux from retranslocated N to grain storage N (gN m-2)
+
+ real(r8), allocatable :: AKX_leafn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from leaf display N (gN m-2)
+ real(r8), allocatable :: AKX_frootn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from fine root display N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live stem display N (gN m-2)
+ real(r8), allocatable :: AKX_deadstemn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead stem display N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live coarse root display N (gN m-2)
+ real(r8), allocatable :: AKX_deadcrootn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead coarse root display N (gN m-2)
+ real(r8), allocatable :: AKX_grainn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from grain display N (gN m-2)
+ real(r8), allocatable :: AKX_retransn_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from retranslocated N (gN m-2)
+
+ real(r8), allocatable :: AKX_leafn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from leaf storge N (gN m-2)
+ real(r8), allocatable :: AKX_frootn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from fine root storge N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live stem storge N (gN m-2)
+ real(r8), allocatable :: AKX_deadstemn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead stem storge N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live coarse root storge N (gN m-2)
+ real(r8), allocatable :: AKX_deadcrootn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead coarse root storge N (gN m-2)
+ real(r8), allocatable :: AKX_grainn_st_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from grain storge N (gN m-2)
+
+ real(r8), allocatable :: AKX_leafn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from leaf transfer N (gN m-2)
+ real(r8), allocatable :: AKX_frootn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from fine root transfer N (gN m-2)
+ real(r8), allocatable :: AKX_livestemn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live stem transfer N (gN m-2)
+ real(r8), allocatable :: AKX_deadstemn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead stem transfer N (gN m-2)
+ real(r8), allocatable :: AKX_livecrootn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from live coarse root transfer N (gN m-2)
+ real(r8), allocatable :: AKX_deadcrootn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from dead coarse root transfer N (gN m-2)
+ real(r8), allocatable :: AKX_grainn_xf_exit_p_acc (:) ! SASU spinup diagnostics: accumulated flux exiting from grain transfer N (gN m-2)
+ !------------------------- END BGC/SASU variables ---------------------
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_BGCPFTimeVariables
+ PUBLIC :: deallocate_BGCPFTimeVariables
+ PUBLIC :: READ_BGCPFTimeVariables
+ PUBLIC :: WRITE_BGCPFTimeVariables
+#ifdef RangeCheck
+ PUBLIC :: check_BGCPFTimeVariables
+#endif
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_BGCPFTimeVariables ()
+! ------------------------------------------------------
+! Allocates memory for CoLM 1d [numpft] variables
+! ------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+ ! bgc variables
+ allocate (leafc_p (numpft)); leafc_p (:) = spval
+ allocate (leafc_storage_p (numpft)); leafc_storage_p (:) = spval
+ allocate (leafc_xfer_p (numpft)); leafc_xfer_p (:) = spval
+ allocate (frootc_p (numpft)); frootc_p (:) = spval
+ allocate (frootc_storage_p (numpft)); frootc_storage_p (:) = spval
+ allocate (frootc_xfer_p (numpft)); frootc_xfer_p (:) = spval
+ allocate (livestemc_p (numpft)); livestemc_p (:) = spval
+ allocate (livestemc_storage_p (numpft)); livestemc_storage_p (:) = spval
+ allocate (livestemc_xfer_p (numpft)); livestemc_xfer_p (:) = spval
+ allocate (deadstemc_p (numpft)); deadstemc_p (:) = spval
+ allocate (deadstemc_storage_p (numpft)); deadstemc_storage_p (:) = spval
+ allocate (deadstemc_xfer_p (numpft)); deadstemc_xfer_p (:) = spval
+ allocate (livecrootc_p (numpft)); livecrootc_p (:) = spval
+ allocate (livecrootc_storage_p (numpft)); livecrootc_storage_p (:) = spval
+ allocate (livecrootc_xfer_p (numpft)); livecrootc_xfer_p (:) = spval
+ allocate (deadcrootc_p (numpft)); deadcrootc_p (:) = spval
+ allocate (deadcrootc_storage_p (numpft)); deadcrootc_storage_p (:) = spval
+ allocate (deadcrootc_xfer_p (numpft)); deadcrootc_xfer_p (:) = spval
+ allocate (grainc_p (numpft)); grainc_p (:) = spval
+ allocate (grainc_storage_p (numpft)); grainc_storage_p (:) = spval
+ allocate (grainc_xfer_p (numpft)); grainc_xfer_p (:) = spval
+ allocate (cropseedc_deficit_p (numpft)); cropseedc_deficit_p (:) = spval
+ allocate (xsmrpool_p (numpft)); xsmrpool_p (:) = spval
+ allocate (gresp_storage_p (numpft)); gresp_storage_p (:) = spval
+ allocate (gresp_xfer_p (numpft)); gresp_xfer_p (:) = spval
+ allocate (cpool_p (numpft)); cpool_p (:) = spval
+ allocate (totvegc_p (numpft)); totvegc_p (:) = spval
+ allocate (cropprod1c_p (numpft)); cropprod1c_p (:) = spval
+
+ allocate (leaf_prof_p (nl_soil,numpft)) ; leaf_prof_p (:,:) = spval
+ allocate (froot_prof_p (nl_soil,numpft)) ; froot_prof_p (:,:) = spval
+ allocate (croot_prof_p (nl_soil,numpft)) ; croot_prof_p (:,:) = spval
+ allocate (stem_prof_p (nl_soil,numpft)) ; stem_prof_p (:,:) = spval
+ allocate (cinput_rootfr_p (nl_soil,numpft)) ; cinput_rootfr_p (:,:) = spval
+
+ allocate (leafn_p (numpft)); leafn_p (:) = spval
+ allocate (leafn_storage_p (numpft)); leafn_storage_p (:) = spval
+ allocate (leafn_xfer_p (numpft)); leafn_xfer_p (:) = spval
+ allocate (frootn_p (numpft)); frootn_p (:) = spval
+ allocate (frootn_storage_p (numpft)); frootn_storage_p (:) = spval
+ allocate (frootn_xfer_p (numpft)); frootn_xfer_p (:) = spval
+ allocate (livestemn_p (numpft)); livestemn_p (:) = spval
+ allocate (livestemn_storage_p (numpft)); livestemn_storage_p (:) = spval
+ allocate (livestemn_xfer_p (numpft)); livestemn_xfer_p (:) = spval
+ allocate (deadstemn_p (numpft)); deadstemn_p (:) = spval
+ allocate (deadstemn_storage_p (numpft)); deadstemn_storage_p (:) = spval
+ allocate (deadstemn_xfer_p (numpft)); deadstemn_xfer_p (:) = spval
+ allocate (livecrootn_p (numpft)); livecrootn_p (:) = spval
+ allocate (livecrootn_storage_p (numpft)); livecrootn_storage_p (:) = spval
+ allocate (livecrootn_xfer_p (numpft)); livecrootn_xfer_p (:) = spval
+ allocate (deadcrootn_p (numpft)); deadcrootn_p (:) = spval
+ allocate (deadcrootn_storage_p (numpft)); deadcrootn_storage_p (:) = spval
+ allocate (deadcrootn_xfer_p (numpft)); deadcrootn_xfer_p (:) = spval
+ allocate (grainn_p (numpft)); grainn_p (:) = spval
+ allocate (grainn_storage_p (numpft)); grainn_storage_p (:) = spval
+ allocate (grainn_xfer_p (numpft)); grainn_xfer_p (:) = spval
+ allocate (cropseedn_deficit_p (numpft)); cropseedn_deficit_p (:) = spval
+ allocate (retransn_p (numpft)); retransn_p (:) = spval
+ allocate (totvegn_p (numpft)); totvegn_p (:) = spval
+
+ allocate (harvdate_p (numpft)); harvdate_p (:) = spval
+
+ allocate (tempsum_potential_gpp_p (numpft)); tempsum_potential_gpp_p (:) = spval
+ allocate (tempmax_retransn_p (numpft)); tempmax_retransn_p (:) = spval
+ allocate (tempavg_tref_p (numpft)); tempavg_tref_p (:) = spval
+ allocate (tempsum_npp_p (numpft)); tempsum_npp_p (:) = spval
+ allocate (tempsum_litfall_p (numpft)); tempsum_litfall_p (:) = spval
+ allocate (annsum_potential_gpp_p (numpft)); annsum_potential_gpp_p (:) = spval
+ allocate (annmax_retransn_p (numpft)); annmax_retransn_p (:) = spval
+ allocate (annavg_tref_p (numpft)); annavg_tref_p (:) = spval
+ allocate (annsum_npp_p (numpft)); annsum_npp_p (:) = spval
+ allocate (annsum_litfall_p (numpft)); annsum_litfall_p (:) = spval
+
+ allocate (bglfr_p (numpft)); bglfr_p (:) = spval
+ allocate (bgtr_p (numpft)); bgtr_p (:) = spval
+ allocate (lgsf_p (numpft)); lgsf_p (:) = spval
+ allocate (gdd0_p (numpft)); gdd0_p (:) = spval
+ allocate (gdd8_p (numpft)); gdd8_p (:) = spval
+ allocate (gdd10_p (numpft)); gdd10_p (:) = spval
+ allocate (gdd020_p (numpft)); gdd020_p (:) = spval
+ allocate (gdd820_p (numpft)); gdd820_p (:) = spval
+ allocate (gdd1020_p (numpft)); gdd1020_p (:) = spval
+ allocate (nyrs_crop_active_p (numpft)); nyrs_crop_active_p (:) = spval_i4
+
+ allocate (offset_flag_p (numpft)); offset_flag_p (:) = spval
+ allocate (offset_counter_p (numpft)); offset_counter_p (:) = spval
+ allocate (onset_flag_p (numpft)); onset_flag_p (:) = spval
+ allocate (onset_counter_p (numpft)); onset_counter_p (:) = spval
+ allocate (onset_gddflag_p (numpft)); onset_gddflag_p (:) = spval
+ allocate (onset_gdd_p (numpft)); onset_gdd_p (:) = spval
+ allocate (onset_fdd_p (numpft)); onset_fdd_p (:) = spval
+ allocate (onset_swi_p (numpft)); onset_swi_p (:) = spval
+ allocate (offset_fdd_p (numpft)); offset_fdd_p (:) = spval
+ allocate (offset_swi_p (numpft)); offset_swi_p (:) = spval
+ allocate (dormant_flag_p (numpft)); dormant_flag_p (:) = spval
+ allocate (prev_leafc_to_litter_p (numpft)); prev_leafc_to_litter_p (:) = spval
+ allocate (prev_frootc_to_litter_p (numpft)); prev_frootc_to_litter_p (:) = spval
+ allocate (days_active_p (numpft)); days_active_p (:) = spval
+
+ allocate (burndate_p (numpft)); burndate_p (:) = spval
+
+ allocate (c_allometry_p (numpft)); c_allometry_p (:) = spval
+ allocate (n_allometry_p (numpft)); n_allometry_p (:) = spval
+ allocate (downreg_p (numpft)); downreg_p (:) = spval
+ allocate (grain_flag_p (numpft)); grain_flag_p (:) = spval
+
+ allocate (ctrunc_p (numpft)); ctrunc_p (:) = spval
+ allocate (ntrunc_p (numpft)); ntrunc_p (:) = spval
+ allocate (npool_p (numpft)); npool_p (:) = spval
+
+#ifdef CROP
+! crop variables
+ allocate (croplive_p (numpft)); croplive_p (:) = .false.
+ allocate (hui_p (numpft)); hui_p (:) = spval
+ allocate (gddplant_p (numpft)); gddplant_p (:) = spval
+ allocate (peaklai_p (numpft)); peaklai_p (:) = spval_i4
+ allocate (aroot_p (numpft)); aroot_p (:) = spval
+ allocate (astem_p (numpft)); astem_p (:) = spval
+ allocate (arepr_p (numpft)); arepr_p (:) = spval
+ allocate (aleaf_p (numpft)); aleaf_p (:) = spval
+ allocate (astemi_p (numpft)); astemi_p (:) = spval
+ allocate (aleafi_p (numpft)); aleafi_p (:) = spval
+ allocate (gddmaturity_p (numpft)); gddmaturity_p (:) = spval
+
+ allocate (cropplant_p (numpft)); cropplant_p (:) = .false.
+ allocate (idop_p (numpft)); idop_p (:) = spval_i4
+ allocate (a5tmin_p (numpft)); a5tmin_p (:) = spval
+ allocate (a10tmin_p (numpft)); a10tmin_p (:) = spval
+ allocate (t10_p (numpft)); t10_p (:) = spval
+ allocate (cumvd_p (numpft)); cumvd_p (:) = spval
+ allocate (vf_p (numpft)); vf_p (:) = spval
+ allocate (cphase_p (numpft)); cphase_p (:) = spval
+ allocate (fert_counter_p (numpft)); fert_counter_p (:) = spval
+ allocate (tref_min_p (numpft)); tref_min_p (:) = spval
+ allocate (tref_max_p (numpft)); tref_max_p (:) = spval
+ allocate (tref_min_inst_p (numpft)); tref_min_inst_p (:) = spval
+ allocate (tref_max_inst_p (numpft)); tref_max_inst_p (:) = spval
+ allocate (fertnitro_p (numpft)); fertnitro_p (:) = spval
+ allocate (manunitro_p (numpft)); manunitro_p (:) = spval
+ allocate (fert_p (numpft)); fert_p (:) = spval
+ allocate (latbaset_p (numpft)); latbaset_p (:) = spval
+ allocate (plantdate_p (numpft)); plantdate_p (:) = spval
+#endif
+
+! SASU variables
+ allocate (leafcCap_p (numpft)); leafcCap_p (:) = spval
+ allocate (leafc_storageCap_p (numpft)); leafc_storageCap_p (:) = spval
+ allocate (leafc_xferCap_p (numpft)); leafc_xferCap_p (:) = spval
+ allocate (frootcCap_p (numpft)); frootcCap_p (:) = spval
+ allocate (frootc_storageCap_p (numpft)); frootc_storageCap_p (:) = spval
+ allocate (frootc_xferCap_p (numpft)); frootc_xferCap_p (:) = spval
+ allocate (livestemcCap_p (numpft)); livestemcCap_p (:) = spval
+ allocate (livestemc_storageCap_p (numpft)); livestemc_storageCap_p (:) = spval
+ allocate (livestemc_xferCap_p (numpft)); livestemc_xferCap_p (:) = spval
+ allocate (deadstemcCap_p (numpft)); deadstemcCap_p (:) = spval
+ allocate (deadstemc_storageCap_p (numpft)); deadstemc_storageCap_p (:) = spval
+ allocate (deadstemc_xferCap_p (numpft)); deadstemc_xferCap_p (:) = spval
+ allocate (livecrootcCap_p (numpft)); livecrootcCap_p (:) = spval
+ allocate (livecrootc_storageCap_p (numpft)); livecrootc_storageCap_p (:) = spval
+ allocate (livecrootc_xferCap_p (numpft)); livecrootc_xferCap_p (:) = spval
+ allocate (deadcrootcCap_p (numpft)); deadcrootcCap_p (:) = spval
+ allocate (deadcrootc_storageCap_p (numpft)); deadcrootc_storageCap_p (:) = spval
+ allocate (deadcrootc_xferCap_p (numpft)); deadcrootc_xferCap_p (:) = spval
+
+ allocate (leafnCap_p (numpft)); leafnCap_p (:) = spval
+ allocate (leafn_storageCap_p (numpft)); leafn_storageCap_p (:) = spval
+ allocate (leafn_xferCap_p (numpft)); leafn_xferCap_p (:) = spval
+ allocate (frootnCap_p (numpft)); frootnCap_p (:) = spval
+ allocate (frootn_storageCap_p (numpft)); frootn_storageCap_p (:) = spval
+ allocate (frootn_xferCap_p (numpft)); frootn_xferCap_p (:) = spval
+ allocate (livestemnCap_p (numpft)); livestemnCap_p (:) = spval
+ allocate (livestemn_storageCap_p (numpft)); livestemn_storageCap_p (:) = spval
+ allocate (livestemn_xferCap_p (numpft)); livestemn_xferCap_p (:) = spval
+ allocate (deadstemnCap_p (numpft)); deadstemnCap_p (:) = spval
+ allocate (deadstemn_storageCap_p (numpft)); deadstemn_storageCap_p (:) = spval
+ allocate (deadstemn_xferCap_p (numpft)); deadstemn_xferCap_p (:) = spval
+ allocate (livecrootnCap_p (numpft)); livecrootnCap_p (:) = spval
+ allocate (livecrootn_storageCap_p (numpft)); livecrootn_storageCap_p (:) = spval
+ allocate (livecrootn_xferCap_p (numpft)); livecrootn_xferCap_p (:) = spval
+ allocate (deadcrootnCap_p (numpft)); deadcrootnCap_p (:) = spval
+ allocate (deadcrootn_storageCap_p (numpft)); deadcrootn_storageCap_p (:) = spval
+ allocate (deadcrootn_xferCap_p (numpft)); deadcrootn_xferCap_p (:) = spval
+
+ allocate (leafc0_p (numpft)); leafc0_p (:) = spval
+ allocate (leafc0_storage_p (numpft)); leafc0_storage_p (:) = spval
+ allocate (leafc0_xfer_p (numpft)); leafc0_xfer_p (:) = spval
+ allocate (frootc0_p (numpft)); frootc0_p (:) = spval
+ allocate (frootc0_storage_p (numpft)); frootc0_storage_p (:) = spval
+ allocate (frootc0_xfer_p (numpft)); frootc0_xfer_p (:) = spval
+ allocate (livestemc0_p (numpft)); livestemc0_p (:) = spval
+ allocate (livestemc0_storage_p (numpft)); livestemc0_storage_p (:) = spval
+ allocate (livestemc0_xfer_p (numpft)); livestemc0_xfer_p (:) = spval
+ allocate (deadstemc0_p (numpft)); deadstemc0_p (:) = spval
+ allocate (deadstemc0_storage_p (numpft)); deadstemc0_storage_p (:) = spval
+ allocate (deadstemc0_xfer_p (numpft)); deadstemc0_xfer_p (:) = spval
+ allocate (livecrootc0_p (numpft)); livecrootc0_p (:) = spval
+ allocate (livecrootc0_storage_p (numpft)); livecrootc0_storage_p (:) = spval
+ allocate (livecrootc0_xfer_p (numpft)); livecrootc0_xfer_p (:) = spval
+ allocate (deadcrootc0_p (numpft)); deadcrootc0_p (:) = spval
+ allocate (deadcrootc0_storage_p (numpft)); deadcrootc0_storage_p (:) = spval
+ allocate (deadcrootc0_xfer_p (numpft)); deadcrootc0_xfer_p (:) = spval
+ allocate (grainc0_p (numpft)); grainc0_p (:) = spval
+ allocate (grainc0_storage_p (numpft)); grainc0_storage_p (:) = spval
+ allocate (grainc0_xfer_p (numpft)); grainc0_xfer_p (:) = spval
+
+ allocate (leafn0_p (numpft)); leafn0_p (:) = spval
+ allocate (leafn0_storage_p (numpft)); leafn0_storage_p (:) = spval
+ allocate (leafn0_xfer_p (numpft)); leafn0_xfer_p (:) = spval
+ allocate (frootn0_p (numpft)); frootn0_p (:) = spval
+ allocate (frootn0_storage_p (numpft)); frootn0_storage_p (:) = spval
+ allocate (frootn0_xfer_p (numpft)); frootn0_xfer_p (:) = spval
+ allocate (livestemn0_p (numpft)); livestemn0_p (:) = spval
+ allocate (livestemn0_storage_p (numpft)); livestemn0_storage_p (:) = spval
+ allocate (livestemn0_xfer_p (numpft)); livestemn0_xfer_p (:) = spval
+ allocate (deadstemn0_p (numpft)); deadstemn0_p (:) = spval
+ allocate (deadstemn0_storage_p (numpft)); deadstemn0_storage_p (:) = spval
+ allocate (deadstemn0_xfer_p (numpft)); deadstemn0_xfer_p (:) = spval
+ allocate (livecrootn0_p (numpft)); livecrootn0_p (:) = spval
+ allocate (livecrootn0_storage_p (numpft)); livecrootn0_storage_p (:) = spval
+ allocate (livecrootn0_xfer_p (numpft)); livecrootn0_xfer_p (:) = spval
+ allocate (deadcrootn0_p (numpft)); deadcrootn0_p (:) = spval
+ allocate (deadcrootn0_storage_p (numpft)); deadcrootn0_storage_p (:) = spval
+ allocate (deadcrootn0_xfer_p (numpft)); deadcrootn0_xfer_p (:) = spval
+ allocate (grainn0_p (numpft)); grainn0_p (:) = spval
+ allocate (grainn0_storage_p (numpft)); grainn0_storage_p (:) = spval
+ allocate (grainn0_xfer_p (numpft)); grainn0_xfer_p (:) = spval
+ allocate (retransn0_p (numpft)); retransn0_p (:) = spval
+
+ allocate (I_leafc_p_acc (numpft)); I_leafc_p_acc (:) = spval
+ allocate (I_leafc_st_p_acc (numpft)); I_leafc_st_p_acc (:) = spval
+ allocate (I_frootc_p_acc (numpft)); I_frootc_p_acc (:) = spval
+ allocate (I_frootc_st_p_acc (numpft)); I_frootc_st_p_acc (:) = spval
+ allocate (I_livestemc_p_acc (numpft)); I_livestemc_p_acc (:) = spval
+ allocate (I_livestemc_st_p_acc (numpft)); I_livestemc_st_p_acc (:) = spval
+ allocate (I_deadstemc_p_acc (numpft)); I_deadstemc_p_acc (:) = spval
+ allocate (I_deadstemc_st_p_acc (numpft)); I_deadstemc_st_p_acc (:) = spval
+ allocate (I_livecrootc_p_acc (numpft)); I_livecrootc_p_acc (:) = spval
+ allocate (I_livecrootc_st_p_acc (numpft)); I_livecrootc_st_p_acc (:) = spval
+ allocate (I_deadcrootc_p_acc (numpft)); I_deadcrootc_p_acc (:) = spval
+ allocate (I_deadcrootc_st_p_acc (numpft)); I_deadcrootc_st_p_acc (:) = spval
+ allocate (I_grainc_p_acc (numpft)); I_grainc_p_acc (:) = spval
+ allocate (I_grainc_st_p_acc (numpft)); I_grainc_st_p_acc (:) = spval
+ allocate (I_leafn_p_acc (numpft)); I_leafn_p_acc (:) = spval
+ allocate (I_leafn_st_p_acc (numpft)); I_leafn_st_p_acc (:) = spval
+ allocate (I_frootn_p_acc (numpft)); I_frootn_p_acc (:) = spval
+ allocate (I_frootn_st_p_acc (numpft)); I_frootn_st_p_acc (:) = spval
+ allocate (I_livestemn_p_acc (numpft)); I_livestemn_p_acc (:) = spval
+ allocate (I_livestemn_st_p_acc (numpft)); I_livestemn_st_p_acc (:) = spval
+ allocate (I_deadstemn_p_acc (numpft)); I_deadstemn_p_acc (:) = spval
+ allocate (I_deadstemn_st_p_acc (numpft)); I_deadstemn_st_p_acc (:) = spval
+ allocate (I_livecrootn_p_acc (numpft)); I_livecrootn_p_acc (:) = spval
+ allocate (I_livecrootn_st_p_acc (numpft)); I_livecrootn_st_p_acc (:) = spval
+ allocate (I_deadcrootn_p_acc (numpft)); I_deadcrootn_p_acc (:) = spval
+ allocate (I_deadcrootn_st_p_acc (numpft)); I_deadcrootn_st_p_acc (:) = spval
+ allocate (I_grainn_p_acc (numpft)); I_grainn_p_acc (:) = spval
+ allocate (I_grainn_st_p_acc (numpft)); I_grainn_st_p_acc (:) = spval
+
+ allocate (AKX_leafc_xf_to_leafc_p_acc (numpft)); AKX_leafc_xf_to_leafc_p_acc (:) = spval
+ allocate (AKX_frootc_xf_to_frootc_p_acc (numpft)); AKX_frootc_xf_to_frootc_p_acc (:) = spval
+ allocate (AKX_livestemc_xf_to_livestemc_p_acc (numpft)); AKX_livestemc_xf_to_livestemc_p_acc (:) = spval
+ allocate (AKX_deadstemc_xf_to_deadstemc_p_acc (numpft)); AKX_deadstemc_xf_to_deadstemc_p_acc (:) = spval
+ allocate (AKX_livecrootc_xf_to_livecrootc_p_acc (numpft)); AKX_livecrootc_xf_to_livecrootc_p_acc (:) = spval
+ allocate (AKX_deadcrootc_xf_to_deadcrootc_p_acc (numpft)); AKX_deadcrootc_xf_to_deadcrootc_p_acc (:) = spval
+ allocate (AKX_grainc_xf_to_grainc_p_acc (numpft)); AKX_grainc_xf_to_grainc_p_acc (:) = spval
+ allocate (AKX_livestemc_to_deadstemc_p_acc (numpft)); AKX_livestemc_to_deadstemc_p_acc (:) = spval
+ allocate (AKX_livecrootc_to_deadcrootc_p_acc (numpft)); AKX_livecrootc_to_deadcrootc_p_acc (:) = spval
+
+ allocate (AKX_leafc_st_to_leafc_xf_p_acc (numpft)); AKX_leafc_st_to_leafc_xf_p_acc (:) = spval
+ allocate (AKX_frootc_st_to_frootc_xf_p_acc (numpft)); AKX_frootc_st_to_frootc_xf_p_acc (:) = spval
+ allocate (AKX_livestemc_st_to_livestemc_xf_p_acc (numpft)); AKX_livestemc_st_to_livestemc_xf_p_acc (:) = spval
+ allocate (AKX_deadstemc_st_to_deadstemc_xf_p_acc (numpft)); AKX_deadstemc_st_to_deadstemc_xf_p_acc (:) = spval
+ allocate (AKX_livecrootc_st_to_livecrootc_xf_p_acc (numpft)); AKX_livecrootc_st_to_livecrootc_xf_p_acc (:) = spval
+ allocate (AKX_deadcrootc_st_to_deadcrootc_xf_p_acc (numpft)); AKX_deadcrootc_st_to_deadcrootc_xf_p_acc (:) = spval
+ allocate (AKX_grainc_st_to_grainc_xf_p_acc (numpft)); AKX_grainc_st_to_grainc_xf_p_acc (:) = spval
+
+ allocate (AKX_leafc_exit_p_acc (numpft)); AKX_leafc_exit_p_acc (:) = spval
+ allocate (AKX_frootc_exit_p_acc (numpft)); AKX_frootc_exit_p_acc (:) = spval
+ allocate (AKX_livestemc_exit_p_acc (numpft)); AKX_livestemc_exit_p_acc (:) = spval
+ allocate (AKX_deadstemc_exit_p_acc (numpft)); AKX_deadstemc_exit_p_acc (:) = spval
+ allocate (AKX_livecrootc_exit_p_acc (numpft)); AKX_livecrootc_exit_p_acc (:) = spval
+ allocate (AKX_deadcrootc_exit_p_acc (numpft)); AKX_deadcrootc_exit_p_acc (:) = spval
+ allocate (AKX_grainc_exit_p_acc (numpft)); AKX_grainc_exit_p_acc (:) = spval
+
+ allocate (AKX_leafc_st_exit_p_acc (numpft)); AKX_leafc_st_exit_p_acc (:) = spval
+ allocate (AKX_frootc_st_exit_p_acc (numpft)); AKX_frootc_st_exit_p_acc (:) = spval
+ allocate (AKX_livestemc_st_exit_p_acc (numpft)); AKX_livestemc_st_exit_p_acc (:) = spval
+ allocate (AKX_deadstemc_st_exit_p_acc (numpft)); AKX_deadstemc_st_exit_p_acc (:) = spval
+ allocate (AKX_livecrootc_st_exit_p_acc (numpft)); AKX_livecrootc_st_exit_p_acc (:) = spval
+ allocate (AKX_deadcrootc_st_exit_p_acc (numpft)); AKX_deadcrootc_st_exit_p_acc (:) = spval
+ allocate (AKX_grainc_st_exit_p_acc (numpft)); AKX_grainc_st_exit_p_acc (:) = spval
+
+ allocate (AKX_leafc_xf_exit_p_acc (numpft)); AKX_leafc_xf_exit_p_acc (:) = spval
+ allocate (AKX_frootc_xf_exit_p_acc (numpft)); AKX_frootc_xf_exit_p_acc (:) = spval
+ allocate (AKX_livestemc_xf_exit_p_acc (numpft)); AKX_livestemc_xf_exit_p_acc (:) = spval
+ allocate (AKX_deadstemc_xf_exit_p_acc (numpft)); AKX_deadstemc_xf_exit_p_acc (:) = spval
+ allocate (AKX_livecrootc_xf_exit_p_acc (numpft)); AKX_livecrootc_xf_exit_p_acc (:) = spval
+ allocate (AKX_deadcrootc_xf_exit_p_acc (numpft)); AKX_deadcrootc_xf_exit_p_acc (:) = spval
+ allocate (AKX_grainc_xf_exit_p_acc (numpft)); AKX_grainc_xf_exit_p_acc (:) = spval
+
+ allocate (AKX_leafn_xf_to_leafn_p_acc (numpft)); AKX_leafn_xf_to_leafn_p_acc (:) = spval
+ allocate (AKX_frootn_xf_to_frootn_p_acc (numpft)); AKX_frootn_xf_to_frootn_p_acc (:) = spval
+ allocate (AKX_livestemn_xf_to_livestemn_p_acc (numpft)); AKX_livestemn_xf_to_livestemn_p_acc (:) = spval
+ allocate (AKX_deadstemn_xf_to_deadstemn_p_acc (numpft)); AKX_deadstemn_xf_to_deadstemn_p_acc (:) = spval
+ allocate (AKX_livecrootn_xf_to_livecrootn_p_acc (numpft)); AKX_livecrootn_xf_to_livecrootn_p_acc (:) = spval
+ allocate (AKX_deadcrootn_xf_to_deadcrootn_p_acc (numpft)); AKX_deadcrootn_xf_to_deadcrootn_p_acc (:) = spval
+ allocate (AKX_grainn_xf_to_grainn_p_acc (numpft)); AKX_grainn_xf_to_grainn_p_acc (:) = spval
+ allocate (AKX_livestemn_to_deadstemn_p_acc (numpft)); AKX_livestemn_to_deadstemn_p_acc (:) = spval
+ allocate (AKX_livecrootn_to_deadcrootn_p_acc (numpft)); AKX_livecrootn_to_deadcrootn_p_acc (:) = spval
+
+ allocate (AKX_leafn_st_to_leafn_xf_p_acc (numpft)); AKX_leafn_st_to_leafn_xf_p_acc (:) = spval
+ allocate (AKX_frootn_st_to_frootn_xf_p_acc (numpft)); AKX_frootn_st_to_frootn_xf_p_acc (:) = spval
+ allocate (AKX_livestemn_st_to_livestemn_xf_p_acc (numpft)); AKX_livestemn_st_to_livestemn_xf_p_acc (:) = spval
+ allocate (AKX_deadstemn_st_to_deadstemn_xf_p_acc (numpft)); AKX_deadstemn_st_to_deadstemn_xf_p_acc (:) = spval
+ allocate (AKX_livecrootn_st_to_livecrootn_xf_p_acc (numpft)); AKX_livecrootn_st_to_livecrootn_xf_p_acc (:) = spval
+ allocate (AKX_deadcrootn_st_to_deadcrootn_xf_p_acc (numpft)); AKX_deadcrootn_st_to_deadcrootn_xf_p_acc (:) = spval
+ allocate (AKX_grainn_st_to_grainn_xf_p_acc (numpft)); AKX_grainn_st_to_grainn_xf_p_acc (:) = spval
+
+ allocate (AKX_leafn_to_retransn_p_acc (numpft)); AKX_leafn_to_retransn_p_acc (:) = spval
+ allocate (AKX_frootn_to_retransn_p_acc (numpft)); AKX_frootn_to_retransn_p_acc (:) = spval
+ allocate (AKX_livestemn_to_retransn_p_acc (numpft)); AKX_livestemn_to_retransn_p_acc (:) = spval
+ allocate (AKX_livecrootn_to_retransn_p_acc (numpft)); AKX_livecrootn_to_retransn_p_acc (:) = spval
+
+ allocate (AKX_retransn_to_leafn_p_acc (numpft)); AKX_retransn_to_leafn_p_acc (:) = spval
+ allocate (AKX_retransn_to_frootn_p_acc (numpft)); AKX_retransn_to_frootn_p_acc (:) = spval
+ allocate (AKX_retransn_to_livestemn_p_acc (numpft)); AKX_retransn_to_livestemn_p_acc (:) = spval
+ allocate (AKX_retransn_to_deadstemn_p_acc (numpft)); AKX_retransn_to_deadstemn_p_acc (:) = spval
+ allocate (AKX_retransn_to_livecrootn_p_acc (numpft)); AKX_retransn_to_livecrootn_p_acc (:) = spval
+ allocate (AKX_retransn_to_deadcrootn_p_acc (numpft)); AKX_retransn_to_deadcrootn_p_acc (:) = spval
+ allocate (AKX_retransn_to_grainn_p_acc (numpft)); AKX_retransn_to_grainn_p_acc (:) = spval
+
+ allocate (AKX_retransn_to_leafn_st_p_acc (numpft)); AKX_retransn_to_leafn_st_p_acc (:) = spval
+ allocate (AKX_retransn_to_frootn_st_p_acc (numpft)); AKX_retransn_to_frootn_st_p_acc (:) = spval
+ allocate (AKX_retransn_to_livestemn_st_p_acc (numpft)); AKX_retransn_to_livestemn_st_p_acc (:) = spval
+ allocate (AKX_retransn_to_deadstemn_st_p_acc (numpft)); AKX_retransn_to_deadstemn_st_p_acc (:) = spval
+ allocate (AKX_retransn_to_livecrootn_st_p_acc (numpft)); AKX_retransn_to_livecrootn_st_p_acc (:) = spval
+ allocate (AKX_retransn_to_deadcrootn_st_p_acc (numpft)); AKX_retransn_to_deadcrootn_st_p_acc (:) = spval
+ allocate (AKX_retransn_to_grainn_st_p_acc (numpft)); AKX_retransn_to_grainn_st_p_acc (:) = spval
+
+ allocate (AKX_leafn_exit_p_acc (numpft)); AKX_leafn_exit_p_acc (:) = spval
+ allocate (AKX_frootn_exit_p_acc (numpft)); AKX_frootn_exit_p_acc (:) = spval
+ allocate (AKX_livestemn_exit_p_acc (numpft)); AKX_livestemn_exit_p_acc (:) = spval
+ allocate (AKX_deadstemn_exit_p_acc (numpft)); AKX_deadstemn_exit_p_acc (:) = spval
+ allocate (AKX_livecrootn_exit_p_acc (numpft)); AKX_livecrootn_exit_p_acc (:) = spval
+ allocate (AKX_deadcrootn_exit_p_acc (numpft)); AKX_deadcrootn_exit_p_acc (:) = spval
+ allocate (AKX_grainn_exit_p_acc (numpft)); AKX_grainn_exit_p_acc (:) = spval
+ allocate (AKX_retransn_exit_p_acc (numpft)); AKX_retransn_exit_p_acc (:) = spval
+
+ allocate (AKX_leafn_st_exit_p_acc (numpft)); AKX_leafn_st_exit_p_acc (:) = spval
+ allocate (AKX_frootn_st_exit_p_acc (numpft)); AKX_frootn_st_exit_p_acc (:) = spval
+ allocate (AKX_livestemn_st_exit_p_acc (numpft)); AKX_livestemn_st_exit_p_acc (:) = spval
+ allocate (AKX_deadstemn_st_exit_p_acc (numpft)); AKX_deadstemn_st_exit_p_acc (:) = spval
+ allocate (AKX_livecrootn_st_exit_p_acc (numpft)); AKX_livecrootn_st_exit_p_acc (:) = spval
+ allocate (AKX_deadcrootn_st_exit_p_acc (numpft)); AKX_deadcrootn_st_exit_p_acc (:) = spval
+ allocate (AKX_grainn_st_exit_p_acc (numpft)); AKX_grainn_st_exit_p_acc (:) = spval
+
+ allocate (AKX_leafn_xf_exit_p_acc (numpft)); AKX_leafn_xf_exit_p_acc (:) = spval
+ allocate (AKX_frootn_xf_exit_p_acc (numpft)); AKX_frootn_xf_exit_p_acc (:) = spval
+ allocate (AKX_livestemn_xf_exit_p_acc (numpft)); AKX_livestemn_xf_exit_p_acc (:) = spval
+ allocate (AKX_deadstemn_xf_exit_p_acc (numpft)); AKX_deadstemn_xf_exit_p_acc (:) = spval
+ allocate (AKX_livecrootn_xf_exit_p_acc (numpft)); AKX_livecrootn_xf_exit_p_acc (:) = spval
+ allocate (AKX_deadcrootn_xf_exit_p_acc (numpft)); AKX_deadcrootn_xf_exit_p_acc (:) = spval
+ allocate (AKX_grainn_xf_exit_p_acc (numpft)); AKX_grainn_xf_exit_p_acc (:) = spval
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE allocate_BGCPFTimeVariables
+
+ SUBROUTINE READ_BGCPFTimeVariables (file_restart)
+
+ USE MOD_NetCDFVector
+ USE MOD_LandPFT
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+! bgc variables
+ CALL ncio_read_vector (file_restart, 'leafc_p ', landpft, leafc_p )
+ CALL ncio_read_vector (file_restart, 'leafc_storage_p ', landpft, leafc_storage_p )
+ CALL ncio_read_vector (file_restart, 'leafc_xfer_p ', landpft, leafc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'frootc_p ', landpft, frootc_p )
+ CALL ncio_read_vector (file_restart, 'frootc_storage_p ', landpft, frootc_storage_p )
+ CALL ncio_read_vector (file_restart, 'frootc_xfer_p ', landpft, frootc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'livestemc_p ', landpft, livestemc_p )
+ CALL ncio_read_vector (file_restart, 'livestemc_storage_p ', landpft, livestemc_storage_p )
+ CALL ncio_read_vector (file_restart, 'livestemc_xfer_p ', landpft, livestemc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'deadstemc_p ', landpft, deadstemc_p )
+ CALL ncio_read_vector (file_restart, 'deadstemc_storage_p ', landpft, deadstemc_storage_p )
+ CALL ncio_read_vector (file_restart, 'deadstemc_xfer_p ', landpft, deadstemc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'livecrootc_p ', landpft, livecrootc_p )
+ CALL ncio_read_vector (file_restart, 'livecrootc_storage_p ', landpft, livecrootc_storage_p )
+ CALL ncio_read_vector (file_restart, 'livecrootc_xfer_p ', landpft, livecrootc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'deadcrootc_p ', landpft, deadcrootc_p )
+ CALL ncio_read_vector (file_restart, 'deadcrootc_storage_p ', landpft, deadcrootc_storage_p )
+ CALL ncio_read_vector (file_restart, 'deadcrootc_xfer_p ', landpft, deadcrootc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'grainc_p ', landpft, grainc_p )
+ CALL ncio_read_vector (file_restart, 'grainc_storage_p ', landpft, grainc_storage_p )
+ CALL ncio_read_vector (file_restart, 'grainc_xfer_p ', landpft, grainc_xfer_p )
+ CALL ncio_read_vector (file_restart, 'cropseedc_deficit_p ', landpft, cropseedc_deficit_p )
+ CALL ncio_read_vector (file_restart, 'xsmrpool_p ', landpft, xsmrpool_p )
+ CALL ncio_read_vector (file_restart, 'gresp_storage_p ', landpft, gresp_storage_p )
+ CALL ncio_read_vector (file_restart, 'gresp_xfer_p ', landpft, gresp_xfer_p )
+ CALL ncio_read_vector (file_restart, 'cpool_p ', landpft, cpool_p )
+ ! CALL ncio_read_vector (file_restart, 'totvegc_p ', landpft, totvegc_p )
+ CALL ncio_read_vector (file_restart, 'cropprod1c_p ', landpft, cropprod1c_p )
+
+ CALL ncio_read_vector (file_restart, 'leafn_p ', landpft, leafn_p )
+ CALL ncio_read_vector (file_restart, 'leafn_storage_p ', landpft, leafn_storage_p )
+ CALL ncio_read_vector (file_restart, 'leafn_xfer_p ', landpft, leafn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'frootn_p ', landpft, frootn_p )
+ CALL ncio_read_vector (file_restart, 'frootn_storage_p ', landpft, frootn_storage_p )
+ CALL ncio_read_vector (file_restart, 'frootn_xfer_p ', landpft, frootn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'livestemn_p ', landpft, livestemn_p )
+ CALL ncio_read_vector (file_restart, 'livestemn_storage_p ', landpft, livestemn_storage_p )
+ CALL ncio_read_vector (file_restart, 'livestemn_xfer_p ', landpft, livestemn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'deadstemn_p ', landpft, deadstemn_p )
+ CALL ncio_read_vector (file_restart, 'deadstemn_storage_p ', landpft, deadstemn_storage_p )
+ CALL ncio_read_vector (file_restart, 'deadstemn_xfer_p ', landpft, deadstemn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'livecrootn_p ', landpft, livecrootn_p )
+ CALL ncio_read_vector (file_restart, 'livecrootn_storage_p ', landpft, livecrootn_storage_p )
+ CALL ncio_read_vector (file_restart, 'livecrootn_xfer_p ', landpft, livecrootn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'deadcrootn_p ', landpft, deadcrootn_p )
+ CALL ncio_read_vector (file_restart, 'deadcrootn_storage_p ', landpft, deadcrootn_storage_p )
+ CALL ncio_read_vector (file_restart, 'deadcrootn_xfer_p ', landpft, deadcrootn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'grainn_p ', landpft, grainn_p )
+ CALL ncio_read_vector (file_restart, 'grainn_storage_p ', landpft, grainn_storage_p )
+ CALL ncio_read_vector (file_restart, 'grainn_xfer_p ', landpft, grainn_xfer_p )
+ CALL ncio_read_vector (file_restart, 'cropseedn_deficit_p ', landpft, cropseedn_deficit_p )
+ CALL ncio_read_vector (file_restart, 'retransn_p ', landpft, retransn_p )
+ ! CALL ncio_read_vector (file_restart, 'totvegn_p ', landpft, totvegn_p )
+
+ CALL ncio_read_vector (file_restart, 'harvdate_p ', landpft, harvdate_p )
+
+ CALL ncio_read_vector (file_restart, 'tempsum_potential_gpp_p', landpft, tempsum_potential_gpp_p)
+ CALL ncio_read_vector (file_restart, 'tempmax_retransn_p ', landpft, tempmax_retransn_p )
+ CALL ncio_read_vector (file_restart, 'tempavg_tref_p ', landpft, tempavg_tref_p )
+ CALL ncio_read_vector (file_restart, 'tempsum_npp_p ', landpft, tempsum_npp_p )
+ CALL ncio_read_vector (file_restart, 'tempsum_litfall_p ', landpft, tempsum_litfall_p )
+ CALL ncio_read_vector (file_restart, 'annsum_potential_gpp_p ', landpft, annsum_potential_gpp_p)
+ CALL ncio_read_vector (file_restart, 'annmax_retransn_p ', landpft, annmax_retransn_p )
+ CALL ncio_read_vector (file_restart, 'annavg_tref_p ', landpft, annavg_tref_p )
+ CALL ncio_read_vector (file_restart, 'annsum_npp_p ', landpft, annsum_npp_p )
+ CALL ncio_read_vector (file_restart, 'annsum_litfall_p ', landpft, annsum_litfall_p )
+
+ CALL ncio_read_vector (file_restart, 'bglfr_p ', landpft, bglfr_p )
+ CALL ncio_read_vector (file_restart, 'bgtr_p ', landpft, bgtr_p )
+ CALL ncio_read_vector (file_restart, 'lgsf_p ', landpft, lgsf_p )
+ CALL ncio_read_vector (file_restart, 'gdd0_p ', landpft, gdd0_p )
+ CALL ncio_read_vector (file_restart, 'gdd8_p ', landpft, gdd8_p )
+ CALL ncio_read_vector (file_restart, 'gdd10_p ', landpft, gdd10_p )
+ CALL ncio_read_vector (file_restart, 'gdd020_p ', landpft, gdd020_p )
+ CALL ncio_read_vector (file_restart, 'gdd820_p ', landpft, gdd820_p )
+ CALL ncio_read_vector (file_restart, 'gdd1020_p ', landpft, gdd1020_p )
+ CALL ncio_read_vector (file_restart, 'nyrs_crop_active_p ', landpft, nyrs_crop_active_p )
+
+ CALL ncio_read_vector (file_restart, 'offset_flag_p ', landpft, offset_flag_p )
+ CALL ncio_read_vector (file_restart, 'offset_counter_p ', landpft, offset_counter_p )
+ CALL ncio_read_vector (file_restart, 'onset_flag_p ', landpft, onset_flag_p )
+ CALL ncio_read_vector (file_restart, 'onset_counter_p ', landpft, onset_counter_p )
+ CALL ncio_read_vector (file_restart, 'onset_gddflag_p ', landpft, onset_gddflag_p )
+ CALL ncio_read_vector (file_restart, 'onset_gdd_p ', landpft, onset_gdd_p )
+ CALL ncio_read_vector (file_restart, 'onset_fdd_p ', landpft, onset_fdd_p )
+ CALL ncio_read_vector (file_restart, 'onset_swi_p ', landpft, onset_swi_p )
+ CALL ncio_read_vector (file_restart, 'offset_fdd_p ', landpft, offset_fdd_p )
+ CALL ncio_read_vector (file_restart, 'offset_swi_p ', landpft, offset_swi_p )
+ CALL ncio_read_vector (file_restart, 'dormant_flag_p ', landpft, dormant_flag_p )
+ CALL ncio_read_vector (file_restart, 'prev_leafc_to_litter_p ', landpft, prev_leafc_to_litter_p)
+ CALL ncio_read_vector (file_restart, 'prev_frootc_to_litter_p', landpft, prev_frootc_to_litter_p)
+ CALL ncio_read_vector (file_restart, 'days_active_p ', landpft, days_active_p )
+
+ CALL ncio_read_vector (file_restart, 'burndate_p ', landpft, burndate_p )
+ CALL ncio_read_vector (file_restart, 'grain_flag_p ', landpft, grain_flag_p )
+ CALL ncio_read_vector (file_restart, 'ctrunc_p ', landpft, ctrunc_p )
+ CALL ncio_read_vector (file_restart, 'ntrunc_p ', landpft, ntrunc_p )
+ CALL ncio_read_vector (file_restart, 'npool_p ', landpft, npool_p )
+
+#ifdef CROP
+! crop variables
+ CALL ncio_read_vector (file_restart, 'croplive_p ', landpft, croplive_p )
+ CALL ncio_read_vector (file_restart, 'hui_p ', landpft, hui_p )
+ CALL ncio_read_vector (file_restart, 'gddplant_p ', landpft, gddplant_p )
+ CALL ncio_read_vector (file_restart, 'peaklai_p ', landpft, peaklai_p )
+ CALL ncio_read_vector (file_restart, 'aroot_p ', landpft, aroot_p )
+ CALL ncio_read_vector (file_restart, 'astem_p ', landpft, astem_p )
+ CALL ncio_read_vector (file_restart, 'arepr_p ', landpft, arepr_p )
+ CALL ncio_read_vector (file_restart, 'aleaf_p ', landpft, aleaf_p )
+ CALL ncio_read_vector (file_restart, 'astemi_p ', landpft, astemi_p )
+ CALL ncio_read_vector (file_restart, 'aleafi_p ', landpft, aleafi_p )
+ CALL ncio_read_vector (file_restart, 'gddmaturity_p ', landpft, gddmaturity_p )
+
+ CALL ncio_read_vector (file_restart, 'cropplant_p ', landpft, cropplant_p )
+ CALL ncio_read_vector (file_restart, 'idop_p ', landpft, idop_p )
+ CALL ncio_read_vector (file_restart, 'a5tmin_p ', landpft, a5tmin_p )
+ CALL ncio_read_vector (file_restart, 'a10tmin_p ', landpft, a10tmin_p )
+ CALL ncio_read_vector (file_restart, 't10_p ', landpft, t10_p )
+ CALL ncio_read_vector (file_restart, 'cumvd_p ', landpft, cumvd_p )
+ CALL ncio_read_vector (file_restart, 'vf_p ', landpft, vf_p )
+ CALL ncio_read_vector (file_restart, 'cphase_p ', landpft, cphase_p )
+ CALL ncio_read_vector (file_restart, 'fert_counter_p ', landpft, fert_counter_p )
+ CALL ncio_read_vector (file_restart, 'tref_min_p ', landpft, tref_min_p )
+ CALL ncio_read_vector (file_restart, 'tref_max_p ', landpft, tref_max_p )
+ CALL ncio_read_vector (file_restart, 'tref_min_inst_p ', landpft, tref_min_inst_p )
+ CALL ncio_read_vector (file_restart, 'tref_max_inst_p ', landpft, tref_max_inst_p )
+ CALL ncio_read_vector (file_restart, 'fertnitro_p ', landpft, fertnitro_p )
+ CALL ncio_read_vector (file_restart, 'manunitro_p ', landpft, manunitro_p )
+ CALL ncio_read_vector (file_restart, 'fert_p ', landpft, fert_p )
+ CALL ncio_read_vector (file_restart, 'latbaset_p ', landpft, latbaset_p )
+ CALL ncio_read_vector (file_restart, 'plantdate_p ', landpft, plantdate_p )
+#endif
+
+ IF(DEF_USE_DiagMatrix)THEN
+! SASU variables
+ CALL ncio_read_vector (file_restart, 'leafcCap_p ', landpft, leafcCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafc_storageCap_p ', landpft, leafc_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafc_xferCap_p ', landpft, leafc_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootcCap_p ', landpft, frootcCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootc_storageCap_p ', landpft, frootc_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootc_xferCap_p ', landpft, frootc_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemcCap_p ', landpft, livestemcCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemc_storageCap_p ', landpft, livestemc_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemc_xferCap_p ', landpft, livestemc_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemcCap_p ', landpft, deadstemcCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemc_storageCap_p ', landpft, deadstemc_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemc_xferCap_p ', landpft, deadstemc_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootcCap_p ', landpft, livecrootcCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootc_storageCap_p', landpft, livecrootc_storageCap_p, defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootc_xferCap_p ', landpft, livecrootc_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootcCap_p ', landpft, deadcrootcCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootc_storageCap_p', landpft, deadcrootc_storageCap_p, defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootc_xferCap_p ', landpft, deadcrootc_xferCap_p , defval = 1._r8)
+
+ CALL ncio_read_vector (file_restart, 'leafnCap_p ', landpft, leafnCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafn_storageCap_p ', landpft, leafn_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafn_xferCap_p ', landpft, leafn_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootnCap_p ', landpft, frootnCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootn_storageCap_p ', landpft, frootn_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootn_xferCap_p ', landpft, frootn_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemnCap_p ', landpft, livestemnCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemn_storageCap_p ', landpft, livestemn_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemn_xferCap_p ', landpft, livestemn_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemnCap_p ', landpft, deadstemnCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemn_storageCap_p ', landpft, deadstemn_storageCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemn_xferCap_p ', landpft, deadstemn_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootnCap_p ', landpft, livecrootnCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootn_storageCap_p', landpft, livecrootn_storageCap_p, defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootn_xferCap_p ', landpft, livecrootn_xferCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootnCap_p ', landpft, deadcrootnCap_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootn_storageCap_p', landpft, deadcrootn_storageCap_p, defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootn_xferCap_p ', landpft, deadcrootn_xferCap_p , defval = 1._r8)
+ ENDIF
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ CALL ncio_read_vector (file_restart, 'leafc0_p ', landpft, leafc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafc0_storage_p ', landpft, leafc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafc0_xfer_p ', landpft, leafc0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootc0_p ', landpft, frootc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootc0_storage_p ', landpft, frootc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootc0_xfer_p ', landpft, frootc0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemc0_p ', landpft, livestemc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemc0_storage_p ', landpft, livestemc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemc0_xfer_p ', landpft, livestemc0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemc0_p ', landpft, deadstemc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemc0_storage_p ', landpft, deadstemc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemc0_xfer_p ', landpft, deadstemc0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootc0_p ', landpft, livecrootc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootc0_storage_p ', landpft, livecrootc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootc0_xfer_p ', landpft, livecrootc0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootc0_p ', landpft, deadcrootc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootc0_storage_p ', landpft, deadcrootc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootc0_xfer_p ', landpft, deadcrootc0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'grainc0_p ', landpft, grainc0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'grainc0_storage_p ', landpft, grainc0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'grainc0_xfer_p ', landpft, grainc0_xfer_p , defval = 1._r8)
+
+ CALL ncio_read_vector (file_restart, 'leafn0_p ', landpft, leafn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafn0_storage_p ', landpft, leafn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'leafn0_xfer_p ', landpft, leafn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootn0_p ', landpft, frootn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootn0_storage_p ', landpft, frootn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'frootn0_xfer_p ', landpft, frootn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemn0_p ', landpft, livestemn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemn0_storage_p ', landpft, livestemn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livestemn0_xfer_p ', landpft, livestemn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemn0_p ', landpft, deadstemn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemn0_storage_p ', landpft, deadstemn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadstemn0_xfer_p ', landpft, deadstemn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootn0_p ', landpft, livecrootn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootn0_storage_p ', landpft, livecrootn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'livecrootn0_xfer_p ', landpft, livecrootn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootn0_p ', landpft, deadcrootn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootn0_storage_p ', landpft, deadcrootn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'deadcrootn0_xfer_p ', landpft, deadcrootn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'grainn0_p ', landpft, grainn0_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'grainn0_storage_p ', landpft, grainn0_storage_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'grainn0_xfer_p ', landpft, grainn0_xfer_p , defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'retransn0_p ', landpft, retransn0_p , defval = 1._r8)
+
+ CALL ncio_read_vector (file_restart, 'I_leafc_p_acc ', landpft, I_leafc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_leafc_st_p_acc ', landpft, I_leafc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_frootc_p_acc ', landpft, I_frootc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_frootc_st_p_acc ', landpft, I_frootc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livestemc_p_acc ', landpft, I_livestemc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livestemc_st_p_acc ', landpft, I_livestemc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadstemc_p_acc ', landpft, I_deadstemc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadstemc_st_p_acc ', landpft, I_deadstemc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livecrootc_p_acc ', landpft, I_livecrootc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livecrootc_st_p_acc ', landpft, I_livecrootc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadcrootc_p_acc ', landpft, I_deadcrootc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadcrootc_st_p_acc ', landpft, I_deadcrootc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_grainc_p_acc ', landpft, I_grainc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_grainc_st_p_acc ', landpft, I_grainc_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_leafn_p_acc ', landpft, I_leafn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_leafn_st_p_acc ', landpft, I_leafn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_frootn_p_acc ', landpft, I_frootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_frootn_st_p_acc ', landpft, I_frootn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livestemn_p_acc ', landpft, I_livestemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livestemn_st_p_acc ', landpft, I_livestemn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadstemn_p_acc ', landpft, I_deadstemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadstemn_st_p_acc ', landpft, I_deadstemn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livecrootn_p_acc ', landpft, I_livecrootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_livecrootn_st_p_acc ', landpft, I_livecrootn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadcrootn_p_acc ', landpft, I_deadcrootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_deadcrootn_st_p_acc ', landpft, I_deadcrootn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_grainn_p_acc ', landpft, I_grainn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'I_grainn_st_p_acc ', landpft, I_grainn_st_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafc_xf_to_leafc_p_acc ', landpft, &
+ AKX_leafc_xf_to_leafc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootc_xf_to_frootc_p_acc ', landpft, &
+ AKX_frootc_xf_to_frootc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemc_xf_to_livestemc_p_acc ', landpft, &
+ AKX_livestemc_xf_to_livestemc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemc_xf_to_deadstemc_p_acc ', landpft, &
+ AKX_deadstemc_xf_to_deadstemc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootc_xf_to_livecrootc_p_acc ', landpft, &
+ AKX_livecrootc_xf_to_livecrootc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootc_xf_to_deadcrootc_p_acc ', landpft, &
+ AKX_deadcrootc_xf_to_deadcrootc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainc_xf_to_grainc_p_acc ', landpft, &
+ AKX_grainc_xf_to_grainc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemc_to_deadstemc_p_acc ', landpft, &
+ AKX_livestemc_to_deadstemc_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootc_to_deadcrootc_p_acc ', landpft, &
+ AKX_livecrootc_to_deadcrootc_p_acc , defval = 0._r8)
+
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafc_st_to_leafc_xf_p_acc ', landpft, &
+ AKX_leafc_st_to_leafc_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootc_st_to_frootc_xf_p_acc ', landpft, &
+ AKX_frootc_st_to_frootc_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemc_st_to_livestemc_xf_p_acc ', landpft, &
+ AKX_livestemc_st_to_livestemc_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemc_st_to_deadstemc_xf_p_acc ', landpft, &
+ AKX_deadstemc_st_to_deadstemc_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootc_st_to_livecrootc_xf_p_acc ', landpft, &
+ AKX_livecrootc_st_to_livecrootc_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootc_st_to_deadcrootc_xf_p_acc ', landpft, &
+ AKX_deadcrootc_st_to_deadcrootc_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainc_st_to_grainc_xf_p_acc ', landpft, &
+ AKX_grainc_st_to_grainc_xf_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafc_exit_p_acc ', landpft, &
+ AKX_leafc_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootc_exit_p_acc ', landpft, &
+ AKX_frootc_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemc_exit_p_acc ', landpft, &
+ AKX_livestemc_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemc_exit_p_acc ', landpft, &
+ AKX_deadstemc_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootc_exit_p_acc ', landpft, &
+ AKX_livecrootc_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootc_exit_p_acc ', landpft, &
+ AKX_deadcrootc_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainc_exit_p_acc ', landpft, &
+ AKX_grainc_exit_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafc_st_exit_p_acc ', landpft, &
+ AKX_leafc_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootc_st_exit_p_acc ', landpft, &
+ AKX_frootc_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemc_st_exit_p_acc ', landpft, &
+ AKX_livestemc_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemc_st_exit_p_acc ', landpft, &
+ AKX_deadstemc_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootc_st_exit_p_acc ', landpft, &
+ AKX_livecrootc_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootc_st_exit_p_acc ', landpft, &
+ AKX_deadcrootc_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainc_st_exit_p_acc ', landpft, &
+ AKX_grainc_st_exit_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafc_xf_exit_p_acc ', landpft, &
+ AKX_leafc_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootc_xf_exit_p_acc ', landpft, &
+ AKX_frootc_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemc_xf_exit_p_acc ', landpft, &
+ AKX_livestemc_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemc_xf_exit_p_acc ', landpft, &
+ AKX_deadstemc_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootc_xf_exit_p_acc ', landpft, &
+ AKX_livecrootc_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootc_xf_exit_p_acc ', landpft, &
+ AKX_deadcrootc_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainc_xf_exit_p_acc ', landpft, &
+ AKX_grainc_xf_exit_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafn_xf_to_leafn_p_acc ', landpft, &
+ AKX_leafn_xf_to_leafn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootn_xf_to_frootn_p_acc ', landpft, &
+ AKX_frootn_xf_to_frootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_xf_to_livestemn_p_acc ', landpft, &
+ AKX_livestemn_xf_to_livestemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemn_xf_to_deadstemn_p_acc ', landpft, &
+ AKX_deadstemn_xf_to_deadstemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_xf_to_livecrootn_p_acc ', landpft, &
+ AKX_livecrootn_xf_to_livecrootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootn_xf_to_deadcrootn_p_acc ', landpft, &
+ AKX_deadcrootn_xf_to_deadcrootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainn_xf_to_grainn_p_acc ', landpft, &
+ AKX_grainn_xf_to_grainn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_to_deadstemn_p_acc ', landpft, &
+ AKX_livestemn_to_deadstemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_to_deadcrootn_p_acc ', landpft, &
+ AKX_livecrootn_to_deadcrootn_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafn_st_to_leafn_xf_p_acc ', landpft, &
+ AKX_leafn_st_to_leafn_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootn_st_to_frootn_xf_p_acc ', landpft, &
+ AKX_frootn_st_to_frootn_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_st_to_livestemn_xf_p_acc ', landpft, &
+ AKX_livestemn_st_to_livestemn_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemn_st_to_deadstemn_xf_p_acc ', landpft, &
+ AKX_deadstemn_st_to_deadstemn_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_st_to_livecrootn_xf_p_acc ', landpft, &
+ AKX_livecrootn_st_to_livecrootn_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootn_st_to_deadcrootn_xf_p_acc ', landpft, &
+ AKX_deadcrootn_st_to_deadcrootn_xf_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainn_st_to_grainn_xf_p_acc ', landpft, &
+ AKX_grainn_st_to_grainn_xf_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafn_to_retransn_p_acc ', landpft, &
+ AKX_leafn_to_retransn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootn_to_retransn_p_acc ', landpft, &
+ AKX_frootn_to_retransn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_to_retransn_p_acc ', landpft, &
+ AKX_livestemn_to_retransn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_to_retransn_p_acc ', landpft, &
+ AKX_livecrootn_to_retransn_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_leafn_p_acc ', landpft, &
+ AKX_retransn_to_leafn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_frootn_p_acc ', landpft, &
+ AKX_retransn_to_frootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_livestemn_p_acc ', landpft, &
+ AKX_retransn_to_livestemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_deadstemn_p_acc ', landpft, &
+ AKX_retransn_to_deadstemn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_livecrootn_p_acc ', landpft, &
+ AKX_retransn_to_livecrootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_deadcrootn_p_acc ', landpft, &
+ AKX_retransn_to_deadcrootn_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_grainn_p_acc ', landpft, &
+ AKX_retransn_to_grainn_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_leafn_st_p_acc ', landpft, &
+ AKX_retransn_to_leafn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_frootn_st_p_acc ', landpft, &
+ AKX_retransn_to_frootn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_livestemn_st_p_acc ', landpft, &
+ AKX_retransn_to_livestemn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_deadstemn_st_p_acc ', landpft, &
+ AKX_retransn_to_deadstemn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_livecrootn_st_p_acc ', landpft, &
+ AKX_retransn_to_livecrootn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_deadcrootn_st_p_acc ', landpft, &
+ AKX_retransn_to_deadcrootn_st_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_to_grainn_st_p_acc ', landpft, &
+ AKX_retransn_to_grainn_st_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafn_exit_p_acc ', landpft, &
+ AKX_leafn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootn_exit_p_acc ', landpft, &
+ AKX_frootn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_exit_p_acc ', landpft, &
+ AKX_livestemn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemn_exit_p_acc ', landpft, &
+ AKX_deadstemn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_exit_p_acc ', landpft, &
+ AKX_livecrootn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootn_exit_p_acc ', landpft, &
+ AKX_deadcrootn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainn_exit_p_acc ', landpft, &
+ AKX_grainn_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_retransn_exit_p_acc ', landpft, &
+ AKX_retransn_exit_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafn_st_exit_p_acc ', landpft, &
+ AKX_leafn_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootn_st_exit_p_acc ', landpft, &
+ AKX_frootn_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_st_exit_p_acc ', landpft, &
+ AKX_livestemn_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemn_st_exit_p_acc ', landpft, &
+ AKX_deadstemn_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_st_exit_p_acc ', landpft, &
+ AKX_livecrootn_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootn_st_exit_p_acc ', landpft, &
+ AKX_deadcrootn_st_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainn_st_exit_p_acc ', landpft, &
+ AKX_grainn_st_exit_p_acc , defval = 0._r8)
+
+ CALL ncio_read_vector (file_restart, 'AKX_leafn_xf_exit_p_acc ', landpft, &
+ AKX_leafn_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_frootn_xf_exit_p_acc ', landpft, &
+ AKX_frootn_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livestemn_xf_exit_p_acc ', landpft, &
+ AKX_livestemn_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadstemn_xf_exit_p_acc ', landpft, &
+ AKX_deadstemn_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_livecrootn_xf_exit_p_acc ', landpft, &
+ AKX_livecrootn_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_deadcrootn_xf_exit_p_acc ', landpft, &
+ AKX_deadcrootn_xf_exit_p_acc , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'AKX_grainn_xf_exit_p_acc ', landpft, &
+ AKX_grainn_xf_exit_p_acc , defval = 0._r8)
+ ENDIF
+ END SUBROUTINE READ_BGCPFTimeVariables
+
+ SUBROUTINE WRITE_BGCPFTimeVariables (file_restart)
+
+ USE MOD_Namelist, only: DEF_REST_CompressLevel
+ USE MOD_LandPFT
+ USE MOD_NetCDFVector
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ ! Local variables
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ ! bgc variables
+ CALL ncio_write_vector (file_restart, 'leafc_p ', 'pft', landpft, &
+ leafc_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafc_storage_p ', 'pft', landpft, &
+ leafc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafc_xfer_p ', 'pft', landpft, &
+ leafc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc_p ', 'pft', landpft, &
+ frootc_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc_storage_p ', 'pft', landpft, &
+ frootc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc_xfer_p ', 'pft', landpft, &
+ frootc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc_p ', 'pft', landpft, &
+ livestemc_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc_storage_p ', 'pft', landpft, &
+ livestemc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc_xfer_p ', 'pft', landpft, &
+ livestemc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc_p ', 'pft', landpft, &
+ deadstemc_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc_storage_p ', 'pft', landpft, &
+ deadstemc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc_xfer_p ', 'pft', landpft, &
+ deadstemc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc_p ', 'pft', landpft, &
+ livecrootc_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc_storage_p ', 'pft', landpft, &
+ livecrootc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc_xfer_p ', 'pft', landpft, &
+ livecrootc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc_p ', 'pft', landpft, &
+ deadcrootc_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc_storage_p ', 'pft', landpft, &
+ deadcrootc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc_xfer_p ', 'pft', landpft, &
+ deadcrootc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainc_p ', 'pft', landpft, &
+ grainc_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainc_storage_p ', 'pft', landpft, &
+ grainc_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainc_xfer_p ', 'pft', landpft, &
+ grainc_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'cropseedc_deficit_p ', 'pft', landpft, &
+ cropseedc_deficit_p , compress)
+ CALL ncio_write_vector (file_restart, 'xsmrpool_p ', 'pft', landpft, &
+ xsmrpool_p , compress)
+ CALL ncio_write_vector (file_restart, 'gresp_storage_p ', 'pft', landpft, &
+ gresp_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'gresp_xfer_p ', 'pft', landpft, &
+ gresp_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'cpool_p ', 'pft', landpft, &
+ cpool_p , compress)
+ ! CALL ncio_write_vector (file_restart, 'totvegc_p ', 'pft', landpft, &
+ ! totvegc_p , compress)
+ CALL ncio_write_vector (file_restart, 'cropprod1c_p ', 'pft', landpft, &
+ cropprod1c_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'leafn_p ', 'pft', landpft, &
+ leafn_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafn_storage_p ', 'pft', landpft, &
+ leafn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafn_xfer_p ', 'pft', landpft, &
+ leafn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn_p ', 'pft', landpft, &
+ frootn_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn_storage_p ', 'pft', landpft, &
+ frootn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn_xfer_p ', 'pft', landpft, &
+ frootn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn_p ', 'pft', landpft, &
+ livestemn_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn_storage_p ', 'pft', landpft, &
+ livestemn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn_xfer_p ', 'pft', landpft, &
+ livestemn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn_p ', 'pft', landpft, &
+ deadstemn_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn_storage_p ', 'pft', landpft, &
+ deadstemn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn_xfer_p ', 'pft', landpft, &
+ deadstemn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn_p ', 'pft', landpft, &
+ livecrootn_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn_storage_p ', 'pft', landpft, &
+ livecrootn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn_xfer_p ', 'pft', landpft, &
+ livecrootn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn_p ', 'pft', landpft, &
+ deadcrootn_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn_storage_p ', 'pft', landpft, &
+ deadcrootn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn_xfer_p ', 'pft', landpft, &
+ deadcrootn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainn_p ', 'pft', landpft, &
+ grainn_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainn_storage_p ', 'pft', landpft, &
+ grainn_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainn_xfer_p ', 'pft', landpft, &
+ grainn_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'cropseedn_deficit_p ', 'pft', landpft, &
+ cropseedn_deficit_p , compress)
+ CALL ncio_write_vector (file_restart, 'retransn_p ', 'pft', landpft, &
+ retransn_p , compress)
+ ! CALL ncio_write_vector (file_restart, 'totvegn_p ', 'pft', landpft, &
+ ! totvegn_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'harvdate_p ', 'pft', landpft, &
+ harvdate_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'tempsum_potential_gpp_p', 'pft', landpft, &
+ tempsum_potential_gpp_p, compress)
+ CALL ncio_write_vector (file_restart, 'tempmax_retransn_p ', 'pft', landpft, &
+ tempmax_retransn_p , compress)
+ CALL ncio_write_vector (file_restart, 'tempavg_tref_p ', 'pft', landpft, &
+ tempavg_tref_p , compress)
+ CALL ncio_write_vector (file_restart, 'tempsum_npp_p ', 'pft', landpft, &
+ tempsum_npp_p , compress)
+ CALL ncio_write_vector (file_restart, 'tempsum_litfall_p ', 'pft', landpft, &
+ tempsum_litfall_p , compress)
+ CALL ncio_write_vector (file_restart, 'annsum_potential_gpp_p ', 'pft', landpft, &
+ annsum_potential_gpp_p, compress)
+ CALL ncio_write_vector (file_restart, 'annmax_retransn_p ', 'pft', landpft, &
+ annmax_retransn_p , compress)
+ CALL ncio_write_vector (file_restart, 'annavg_tref_p ', 'pft', landpft, &
+ annavg_tref_p , compress)
+ CALL ncio_write_vector (file_restart, 'annsum_npp_p ', 'pft', landpft, &
+ annsum_npp_p , compress)
+ CALL ncio_write_vector (file_restart, 'annsum_litfall_p ', 'pft', landpft, &
+ annsum_litfall_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'bglfr_p ', 'pft', landpft, &
+ bglfr_p , compress)
+ CALL ncio_write_vector (file_restart, 'bgtr_p ', 'pft', landpft, &
+ bgtr_p , compress)
+ CALL ncio_write_vector (file_restart, 'lgsf_p ', 'pft', landpft, &
+ lgsf_p , compress)
+ CALL ncio_write_vector (file_restart, 'gdd0_p ', 'pft', landpft, &
+ gdd0_p , compress)
+ CALL ncio_write_vector (file_restart, 'gdd8_p ', 'pft', landpft, &
+ gdd8_p , compress)
+ CALL ncio_write_vector (file_restart, 'gdd10_p ', 'pft', landpft, &
+ gdd10_p , compress)
+ CALL ncio_write_vector (file_restart, 'gdd020_p ', 'pft', landpft, &
+ gdd020_p , compress)
+ CALL ncio_write_vector (file_restart, 'gdd820_p ', 'pft', landpft, &
+ gdd820_p , compress)
+ CALL ncio_write_vector (file_restart, 'gdd1020_p ', 'pft', landpft, &
+ gdd1020_p , compress)
+ CALL ncio_write_vector (file_restart, 'nyrs_crop_active_p ', 'pft', landpft, &
+ nyrs_crop_active_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'offset_flag_p ', 'pft', landpft, &
+ offset_flag_p , compress)
+ CALL ncio_write_vector (file_restart, 'offset_counter_p ', 'pft', landpft, &
+ offset_counter_p , compress)
+ CALL ncio_write_vector (file_restart, 'onset_flag_p ', 'pft', landpft, &
+ onset_flag_p , compress)
+ CALL ncio_write_vector (file_restart, 'onset_counter_p ', 'pft', landpft, &
+ onset_counter_p , compress)
+ CALL ncio_write_vector (file_restart, 'onset_gddflag_p ', 'pft', landpft, &
+ onset_gddflag_p , compress)
+ CALL ncio_write_vector (file_restart, 'onset_gdd_p ', 'pft', landpft, &
+ onset_gdd_p , compress)
+ CALL ncio_write_vector (file_restart, 'onset_fdd_p ', 'pft', landpft, &
+ onset_fdd_p , compress)
+ CALL ncio_write_vector (file_restart, 'onset_swi_p ', 'pft', landpft, &
+ onset_swi_p , compress)
+ CALL ncio_write_vector (file_restart, 'offset_fdd_p ', 'pft', landpft, &
+ offset_fdd_p , compress)
+ CALL ncio_write_vector (file_restart, 'offset_swi_p ', 'pft', landpft, &
+ offset_swi_p , compress)
+ CALL ncio_write_vector (file_restart, 'dormant_flag_p ', 'pft', landpft, &
+ dormant_flag_p , compress)
+ CALL ncio_write_vector (file_restart, 'prev_leafc_to_litter_p ', 'pft', landpft, &
+ prev_leafc_to_litter_p, compress)
+ CALL ncio_write_vector (file_restart, 'prev_frootc_to_litter_p', 'pft', landpft, &
+ prev_frootc_to_litter_p, compress)
+ CALL ncio_write_vector (file_restart, 'days_active_p ', 'pft', landpft, &
+ days_active_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'burndate_p ', 'pft', landpft, &
+ burndate_p , compress)
+ CALL ncio_write_vector (file_restart, 'grain_flag_p ', 'pft', landpft, &
+ grain_flag_p , compress)
+ CALL ncio_write_vector (file_restart, 'ctrunc_p ', 'pft', landpft, &
+ ctrunc_p , compress)
+ CALL ncio_write_vector (file_restart, 'ntrunc_p ', 'pft', landpft, &
+ ntrunc_p , compress)
+ CALL ncio_write_vector (file_restart, 'npool_p ', 'pft', landpft, &
+ npool_p , compress)
+
+#ifdef CROP
+! crop variables
+ CALL ncio_write_vector (file_restart, 'croplive_p ', 'pft', landpft, &
+ croplive_p , compress)
+ CALL ncio_write_vector (file_restart, 'hui_p ', 'pft', landpft, &
+ hui_p , compress)
+ CALL ncio_write_vector (file_restart, 'gddplant_p ', 'pft', landpft, &
+ gddplant_p , compress)
+ CALL ncio_write_vector (file_restart, 'peaklai_p ', 'pft', landpft, &
+ peaklai_p , compress)
+ CALL ncio_write_vector (file_restart, 'aroot_p ', 'pft', landpft, &
+ aroot_p , compress)
+ CALL ncio_write_vector (file_restart, 'astem_p ', 'pft', landpft, &
+ astem_p , compress)
+ CALL ncio_write_vector (file_restart, 'arepr_p ', 'pft', landpft, &
+ arepr_p , compress)
+ CALL ncio_write_vector (file_restart, 'aleaf_p ', 'pft', landpft, &
+ aleaf_p , compress)
+ CALL ncio_write_vector (file_restart, 'astemi_p ', 'pft', landpft, &
+ astemi_p , compress)
+ CALL ncio_write_vector (file_restart, 'aleafi_p ', 'pft', landpft, &
+ aleafi_p , compress)
+ CALL ncio_write_vector (file_restart, 'gddmaturity_p ', 'pft', landpft, &
+ gddmaturity_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'cropplant_p ', 'pft', landpft, &
+ cropplant_p , compress)
+ CALL ncio_write_vector (file_restart, 'idop_p ', 'pft', landpft, &
+ idop_p , compress)
+ CALL ncio_write_vector (file_restart, 'a5tmin_p ', 'pft', landpft, &
+ a5tmin_p , compress)
+ CALL ncio_write_vector (file_restart, 'a10tmin_p ', 'pft', landpft, &
+ a10tmin_p , compress)
+ CALL ncio_write_vector (file_restart, 't10_p ', 'pft', landpft, &
+ t10_p , compress)
+ CALL ncio_write_vector (file_restart, 'cumvd_p ', 'pft', landpft, &
+ cumvd_p , compress)
+ CALL ncio_write_vector (file_restart, 'vf_p ', 'pft', landpft, &
+ vf_p , compress)
+ CALL ncio_write_vector (file_restart, 'cphase_p ', 'pft', landpft, &
+ cphase_p , compress)
+ CALL ncio_write_vector (file_restart, 'fert_counter_p ', 'pft', landpft, &
+ fert_counter_p , compress)
+ CALL ncio_write_vector (file_restart, 'tref_min_p ', 'pft', landpft, &
+ tref_min_p , compress)
+ CALL ncio_write_vector (file_restart, 'tref_max_p ', 'pft', landpft, &
+ tref_max_p , compress)
+ CALL ncio_write_vector (file_restart, 'tref_min_inst_p ', 'pft', landpft, &
+ tref_min_inst_p , compress)
+ CALL ncio_write_vector (file_restart, 'tref_max_inst_p ', 'pft', landpft, &
+ tref_max_inst_p , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_p ', 'pft', landpft, &
+ fertnitro_p , compress)
+ CALL ncio_write_vector (file_restart, 'manunitro_p ', 'pft', landpft, &
+ manunitro_p , compress)
+ CALL ncio_write_vector (file_restart, 'fert_p ', 'pft', landpft, &
+ fert_p , compress)
+ CALL ncio_write_vector (file_restart, 'latbaset_p ', 'pft', landpft, &
+ latbaset_p , compress)
+ CALL ncio_write_vector (file_restart, 'plantdate_p ', 'pft', landpft, &
+ plantdate_p , compress)
+#endif
+
+ IF(DEF_USE_DiagMatrix)THEN
+! SASU variables
+ CALL ncio_write_vector (file_restart, 'leafcCap_p ', 'pft', landpft, &
+ leafcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafc_storageCap_p ', 'pft', landpft, &
+ leafc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafc_xferCap_p ', 'pft', landpft, &
+ leafc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootcCap_p ', 'pft', landpft, &
+ frootcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc_storageCap_p ', 'pft', landpft, &
+ frootc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc_xferCap_p ', 'pft', landpft, &
+ frootc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemcCap_p ', 'pft', landpft, &
+ livestemcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc_storageCap_p ', 'pft', landpft, &
+ livestemc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc_xferCap_p ', 'pft', landpft, &
+ livestemc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemcCap_p ', 'pft', landpft, &
+ deadstemcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc_storageCap_p ', 'pft', landpft, &
+ deadstemc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc_xferCap_p ', 'pft', landpft, &
+ deadstemc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootcCap_p ', 'pft', landpft, &
+ livecrootcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc_storageCap_p ', 'pft', landpft, &
+ livecrootc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc_xferCap_p ', 'pft', landpft, &
+ livecrootc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootcCap_p ', 'pft', landpft, &
+ deadcrootcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc_storageCap_p ', 'pft', landpft, &
+ deadcrootc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc_xferCap_p ', 'pft', landpft, &
+ deadcrootc_xferCap_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'leafnCap_p ', 'pft', landpft, &
+ leafcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafn_storageCap_p ', 'pft', landpft, &
+ leafc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafn_xferCap_p ', 'pft', landpft, &
+ leafc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootnCap_p ', 'pft', landpft, &
+ frootcCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn_storageCap_p ', 'pft', landpft, &
+ frootc_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn_xferCap_p ', 'pft', landpft, &
+ frootc_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemnCap_p ', 'pft', landpft, &
+ livestemnCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn_storageCap_p ', 'pft', landpft, &
+ livestemn_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn_xferCap_p ', 'pft', landpft, &
+ livestemn_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemnCap_p ', 'pft', landpft, &
+ deadstemnCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn_storageCap_p ', 'pft', landpft, &
+ deadstemn_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn_xferCap_p ', 'pft', landpft, &
+ deadstemn_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootnCap_p ', 'pft', landpft, &
+ livecrootnCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn_storageCap_p ', 'pft', landpft, &
+ livecrootn_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn_xferCap_p ', 'pft', landpft, &
+ livecrootn_xferCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootnCap_p ', 'pft', landpft, &
+ deadcrootnCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn_storageCap_p ', 'pft', landpft, &
+ deadcrootn_storageCap_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn_xferCap_p ', 'pft', landpft, &
+ deadcrootn_xferCap_p , compress)
+ ENDIF
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ CALL ncio_write_vector (file_restart, 'leafc0_p ', 'pft', landpft, &
+ leafc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafc0_storage_p ', 'pft', landpft, &
+ leafc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafc0_xfer_p ', 'pft', landpft, &
+ leafc0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc0_p ', 'pft', landpft, &
+ frootc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc0_storage_p ', 'pft', landpft, &
+ frootc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootc0_xfer_p ', 'pft', landpft, &
+ frootc0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc0_p ', 'pft', landpft, &
+ livestemc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc0_storage_p ', 'pft', landpft, &
+ livestemc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemc0_xfer_p ', 'pft', landpft, &
+ livestemc0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc0_p ', 'pft', landpft, &
+ deadstemc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc0_storage_p ', 'pft', landpft, &
+ deadstemc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemc0_xfer_p ', 'pft', landpft, &
+ deadstemc0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc0_p ', 'pft', landpft, &
+ livecrootc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc0_storage_p ', 'pft', landpft, &
+ livecrootc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootc0_xfer_p ', 'pft', landpft, &
+ livecrootc0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc0_p ', 'pft', landpft, &
+ deadcrootc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc0_storage_p ', 'pft', landpft, &
+ deadcrootc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootc0_xfer_p ', 'pft', landpft, &
+ deadcrootc0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainc0_p ', 'pft', landpft, &
+ grainc0_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainc0_storage_p ', 'pft', landpft, &
+ grainc0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainc0_xfer_p ', 'pft', landpft, &
+ grainc0_xfer_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'leafn0_p ', 'pft', landpft, &
+ leafn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafn0_storage_p ', 'pft', landpft, &
+ leafn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'leafn0_xfer_p ', 'pft', landpft, &
+ leafn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn0_p ', 'pft', landpft, &
+ frootn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn0_storage_p ', 'pft', landpft, &
+ frootn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'frootn0_xfer_p ', 'pft', landpft, &
+ frootn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn0_p ', 'pft', landpft, &
+ livestemn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn0_storage_p ', 'pft', landpft, &
+ livestemn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livestemn0_xfer_p ', 'pft', landpft, &
+ livestemn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn0_p ', 'pft', landpft, &
+ deadstemn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn0_storage_p ', 'pft', landpft, &
+ deadstemn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadstemn0_xfer_p ', 'pft', landpft, &
+ deadstemn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn0_p ', 'pft', landpft, &
+ livecrootn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn0_storage_p ', 'pft', landpft, &
+ livecrootn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'livecrootn0_xfer_p ', 'pft', landpft, &
+ livecrootn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn0_p ', 'pft', landpft, &
+ deadcrootn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn0_storage_p ', 'pft', landpft, &
+ deadcrootn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'deadcrootn0_xfer_p ', 'pft', landpft, &
+ deadcrootn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainn0_p ', 'pft', landpft, &
+ grainn0_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainn0_storage_p ', 'pft', landpft, &
+ grainn0_storage_p , compress)
+ CALL ncio_write_vector (file_restart, 'grainn0_xfer_p ', 'pft', landpft, &
+ grainn0_xfer_p , compress)
+ CALL ncio_write_vector (file_restart, 'retransn0_p ', 'pft', landpft, &
+ retransn0_p , compress)
+
+ CALL ncio_write_vector (file_restart, 'I_leafc_p_acc ', 'pft', landpft, &
+ I_leafc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_leafc_st_p_acc ', 'pft', landpft, &
+ I_leafc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_frootc_p_acc ', 'pft', landpft, &
+ I_frootc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_frootc_st_p_acc ', 'pft', landpft, &
+ I_frootc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livestemc_p_acc ', 'pft', landpft, &
+ I_livestemc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livestemc_st_p_acc ', 'pft', landpft, &
+ I_livestemc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadstemc_p_acc ', 'pft', landpft, &
+ I_deadstemc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadstemc_st_p_acc ', 'pft', landpft, &
+ I_deadstemc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livecrootc_p_acc ', 'pft', landpft, &
+ I_livecrootc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livecrootc_st_p_acc ', 'pft', landpft, &
+ I_livecrootc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadcrootc_p_acc ', 'pft', landpft, &
+ I_deadcrootc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadcrootc_st_p_acc ', 'pft', landpft, &
+ I_deadcrootc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_grainc_p_acc ', 'pft', landpft, &
+ I_grainc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_grainc_st_p_acc ', 'pft', landpft, &
+ I_grainc_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_leafn_p_acc ', 'pft', landpft, &
+ I_leafn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_leafn_st_p_acc ', 'pft', landpft, &
+ I_leafn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_frootn_p_acc ', 'pft', landpft, &
+ I_frootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_frootn_st_p_acc ', 'pft', landpft, &
+ I_frootn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livestemn_p_acc ', 'pft', landpft, &
+ I_livestemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livestemn_st_p_acc ', 'pft', landpft, &
+ I_livestemn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadstemn_p_acc ', 'pft', landpft, &
+ I_deadstemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadstemn_st_p_acc ', 'pft', landpft, &
+ I_deadstemn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livecrootn_p_acc ', 'pft', landpft, &
+ I_livecrootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_livecrootn_st_p_acc ', 'pft', landpft, &
+ I_livecrootn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadcrootn_p_acc ', 'pft', landpft, &
+ I_deadcrootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_deadcrootn_st_p_acc ', 'pft', landpft, &
+ I_deadcrootn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_grainn_p_acc ', 'pft', landpft, &
+ I_grainn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'I_grainn_st_p_acc ', 'pft', landpft, &
+ I_grainn_st_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafc_xf_to_leafc_p_acc ', 'pft', landpft, &
+ AKX_leafc_xf_to_leafc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootc_xf_to_frootc_p_acc ', 'pft', landpft, &
+ AKX_frootc_xf_to_frootc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemc_xf_to_livestemc_p_acc ', 'pft', landpft, &
+ AKX_livestemc_xf_to_livestemc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemc_xf_to_deadstemc_p_acc ', 'pft', landpft, &
+ AKX_deadstemc_xf_to_deadstemc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootc_xf_to_livecrootc_p_acc ', 'pft', landpft, &
+ AKX_livecrootc_xf_to_livecrootc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootc_xf_to_deadcrootc_p_acc ', 'pft', landpft, &
+ AKX_deadcrootc_xf_to_deadcrootc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainc_xf_to_grainc_p_acc ', 'pft', landpft, &
+ AKX_grainc_xf_to_grainc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemc_to_deadstemc_p_acc ', 'pft', landpft, &
+ AKX_livestemc_to_deadstemc_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootc_to_deadcrootc_p_acc ', 'pft', landpft, &
+ AKX_livecrootc_to_deadcrootc_p_acc , compress)
+
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafc_st_to_leafc_xf_p_acc ', 'pft', landpft, &
+ AKX_leafc_st_to_leafc_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootc_st_to_frootc_xf_p_acc ', 'pft', landpft, &
+ AKX_frootc_st_to_frootc_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemc_st_to_livestemc_xf_p_acc ', 'pft', landpft, &
+ AKX_livestemc_st_to_livestemc_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemc_st_to_deadstemc_xf_p_acc ', 'pft', landpft, &
+ AKX_deadstemc_st_to_deadstemc_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootc_st_to_livecrootc_xf_p_acc ', 'pft', landpft, &
+ AKX_livecrootc_st_to_livecrootc_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootc_st_to_deadcrootc_xf_p_acc ', 'pft', landpft, &
+ AKX_deadcrootc_st_to_deadcrootc_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainc_st_to_grainc_xf_p_acc ', 'pft', landpft, &
+ AKX_grainc_st_to_grainc_xf_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafc_exit_p_acc ', 'pft', landpft, &
+ AKX_leafc_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootc_exit_p_acc ', 'pft', landpft, &
+ AKX_frootc_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemc_exit_p_acc ', 'pft', landpft, &
+ AKX_livestemc_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemc_exit_p_acc ', 'pft', landpft, &
+ AKX_deadstemc_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootc_exit_p_acc ', 'pft', landpft, &
+ AKX_livecrootc_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootc_exit_p_acc ', 'pft', landpft, &
+ AKX_deadcrootc_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainc_exit_p_acc ', 'pft', landpft, &
+ AKX_grainc_exit_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_leafc_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_frootc_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_livestemc_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_deadstemc_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_livecrootc_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_deadcrootc_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainc_st_exit_p_acc ', 'pft', landpft, &
+ AKX_grainc_st_exit_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_leafc_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_frootc_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_livestemc_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_deadstemc_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_livecrootc_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_deadcrootc_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainc_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_grainc_xf_exit_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafn_xf_to_leafn_p_acc ', 'pft', landpft, &
+ AKX_leafn_xf_to_leafn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootn_xf_to_frootn_p_acc ', 'pft', landpft, &
+ AKX_frootn_xf_to_frootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_xf_to_livestemn_p_acc ', 'pft', landpft, &
+ AKX_livestemn_xf_to_livestemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemn_xf_to_deadstemn_p_acc ', 'pft', landpft, &
+ AKX_deadstemn_xf_to_deadstemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_xf_to_livecrootn_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_xf_to_livecrootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootn_xf_to_deadcrootn_p_acc ', 'pft', landpft, &
+ AKX_deadcrootn_xf_to_deadcrootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainn_xf_to_grainn_p_acc ', 'pft', landpft, &
+ AKX_grainn_xf_to_grainn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_to_deadstemn_p_acc ', 'pft', landpft, &
+ AKX_livestemn_to_deadstemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_to_deadcrootn_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_to_deadcrootn_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafn_st_to_leafn_xf_p_acc ', 'pft', landpft, &
+ AKX_leafn_st_to_leafn_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootn_st_to_frootn_xf_p_acc ', 'pft', landpft, &
+ AKX_frootn_st_to_frootn_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_st_to_livestemn_xf_p_acc ', 'pft', landpft, &
+ AKX_livestemn_st_to_livestemn_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemn_st_to_deadstemn_xf_p_acc ', 'pft', landpft, &
+ AKX_deadstemn_st_to_deadstemn_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_st_to_livecrootn_xf_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_st_to_livecrootn_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootn_st_to_deadcrootn_xf_p_acc ', 'pft', landpft, &
+ AKX_deadcrootn_st_to_deadcrootn_xf_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainn_st_to_grainn_xf_p_acc ', 'pft', landpft, &
+ AKX_grainn_st_to_grainn_xf_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafn_to_retransn_p_acc ', 'pft', landpft, &
+ AKX_leafn_to_retransn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootn_to_retransn_p_acc ', 'pft', landpft, &
+ AKX_frootn_to_retransn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_to_retransn_p_acc ', 'pft', landpft, &
+ AKX_livestemn_to_retransn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_to_retransn_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_to_retransn_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_leafn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_leafn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_frootn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_frootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_livestemn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_livestemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_deadstemn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_deadstemn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_livecrootn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_livecrootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_deadcrootn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_deadcrootn_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_grainn_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_grainn_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_leafn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_leafn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_frootn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_frootn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_livestemn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_livestemn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_deadstemn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_deadstemn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_livecrootn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_livecrootn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_deadcrootn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_deadcrootn_st_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_to_grainn_st_p_acc ', 'pft', landpft, &
+ AKX_retransn_to_grainn_st_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafn_exit_p_acc ', 'pft', landpft, &
+ AKX_leafn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootn_exit_p_acc ', 'pft', landpft, &
+ AKX_frootn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_exit_p_acc ', 'pft', landpft, &
+ AKX_livestemn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemn_exit_p_acc ', 'pft', landpft, &
+ AKX_deadstemn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_exit_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootn_exit_p_acc ', 'pft', landpft, &
+ AKX_deadcrootn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainn_exit_p_acc ', 'pft', landpft, &
+ AKX_grainn_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_retransn_exit_p_acc ', 'pft', landpft, &
+ AKX_retransn_exit_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_leafn_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_frootn_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_livestemn_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_deadstemn_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_deadcrootn_st_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainn_st_exit_p_acc ', 'pft', landpft, &
+ AKX_grainn_st_exit_p_acc , compress)
+
+ CALL ncio_write_vector (file_restart, 'AKX_leafn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_leafn_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_frootn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_frootn_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livestemn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_livestemn_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadstemn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_deadstemn_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_livecrootn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_livecrootn_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_deadcrootn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_deadcrootn_xf_exit_p_acc , compress)
+ CALL ncio_write_vector (file_restart, 'AKX_grainn_xf_exit_p_acc ', 'pft', landpft, &
+ AKX_grainn_xf_exit_p_acc , compress)
+ ENDIF
+ END SUBROUTINE WRITE_BGCPFTimeVariables
+
+
+ SUBROUTINE deallocate_BGCPFTimeVariables ()
+! --------------------------------------------------
+! Deallocates memory for CoLM 1d [numpft/numpc] variables
+! --------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+! bgc variables
+ deallocate (leafc_p )
+ deallocate (leafc_storage_p )
+ deallocate (leafc_xfer_p )
+ deallocate (frootc_p )
+ deallocate (frootc_storage_p )
+ deallocate (frootc_xfer_p )
+ deallocate (livestemc_p )
+ deallocate (livestemc_storage_p )
+ deallocate (livestemc_xfer_p )
+ deallocate (deadstemc_p )
+ deallocate (deadstemc_storage_p )
+ deallocate (deadstemc_xfer_p )
+ deallocate (livecrootc_p )
+ deallocate (livecrootc_storage_p )
+ deallocate (livecrootc_xfer_p )
+ deallocate (deadcrootc_p )
+ deallocate (deadcrootc_storage_p )
+ deallocate (deadcrootc_xfer_p )
+ deallocate (grainc_p )
+ deallocate (grainc_storage_p )
+ deallocate (grainc_xfer_p )
+ deallocate (cropseedc_deficit_p )
+ deallocate (xsmrpool_p )
+ deallocate (gresp_storage_p )
+ deallocate (gresp_xfer_p )
+ deallocate (cpool_p )
+ deallocate (totvegc_p )
+ deallocate (cropprod1c_p )
+
+ deallocate (leaf_prof_p )
+ deallocate (froot_prof_p )
+ deallocate (croot_prof_p )
+ deallocate (stem_prof_p )
+ deallocate (cinput_rootfr_p )
+
+ deallocate (leafn_p )
+ deallocate (leafn_storage_p )
+ deallocate (leafn_xfer_p )
+ deallocate (frootn_p )
+ deallocate (frootn_storage_p )
+ deallocate (frootn_xfer_p )
+ deallocate (livestemn_p )
+ deallocate (livestemn_storage_p )
+ deallocate (livestemn_xfer_p )
+ deallocate (deadstemn_p )
+ deallocate (deadstemn_storage_p )
+ deallocate (deadstemn_xfer_p )
+ deallocate (livecrootn_p )
+ deallocate (livecrootn_storage_p )
+ deallocate (livecrootn_xfer_p )
+ deallocate (deadcrootn_p )
+ deallocate (deadcrootn_storage_p )
+ deallocate (deadcrootn_xfer_p )
+ deallocate (grainn_p )
+ deallocate (grainn_storage_p )
+ deallocate (grainn_xfer_p )
+ deallocate (cropseedn_deficit_p )
+ deallocate (retransn_p )
+ deallocate (totvegn_p )
+
+ deallocate (harvdate_p )
+
+ deallocate (tempsum_potential_gpp_p )
+ deallocate (tempmax_retransn_p )
+ deallocate (tempavg_tref_p )
+ deallocate (tempsum_npp_p )
+ deallocate (tempsum_litfall_p )
+ deallocate (annsum_potential_gpp_p )
+ deallocate (annmax_retransn_p )
+ deallocate (annavg_tref_p )
+ deallocate (annsum_npp_p )
+ deallocate (annsum_litfall_p )
+
+ deallocate (bglfr_p )
+ deallocate (bgtr_p )
+ deallocate (lgsf_p )
+ deallocate (gdd0_p )
+ deallocate (gdd8_p )
+ deallocate (gdd10_p )
+ deallocate (gdd020_p )
+ deallocate (gdd820_p )
+ deallocate (gdd1020_p )
+ deallocate (nyrs_crop_active_p )
+
+ deallocate (offset_flag_p )
+ deallocate (offset_counter_p )
+ deallocate (onset_flag_p )
+ deallocate (onset_counter_p )
+ deallocate (onset_gddflag_p )
+ deallocate (onset_gdd_p )
+ deallocate (onset_fdd_p )
+ deallocate (onset_swi_p )
+ deallocate (offset_fdd_p )
+ deallocate (offset_swi_p )
+ deallocate (dormant_flag_p )
+ deallocate (prev_leafc_to_litter_p )
+ deallocate (prev_frootc_to_litter_p )
+ deallocate (days_active_p )
+
+ deallocate (burndate_p )
+
+ deallocate (c_allometry_p )
+ deallocate (n_allometry_p )
+ deallocate (downreg_p )
+ deallocate (grain_flag_p )
+
+ deallocate (ctrunc_p )
+ deallocate (ntrunc_p )
+ deallocate (npool_p )
+
+#ifdef CROP
+! crop variables
+ deallocate (croplive_p )
+ deallocate (hui_p )
+ deallocate (gddplant_p )
+ deallocate (peaklai_p )
+ deallocate (aroot_p )
+ deallocate (astem_p )
+ deallocate (arepr_p )
+ deallocate (aleaf_p )
+ deallocate (astemi_p )
+ deallocate (aleafi_p )
+ deallocate (gddmaturity_p )
+
+ deallocate (cropplant_p )
+ deallocate (idop_p )
+ deallocate (a5tmin_p )
+ deallocate (a10tmin_p )
+ deallocate (t10_p )
+ deallocate (cumvd_p )
+ deallocate (vf_p )
+ deallocate (cphase_p )
+ deallocate (fert_counter_p )
+ deallocate (tref_min_p )
+ deallocate (tref_max_p )
+ deallocate (tref_min_inst_p )
+ deallocate (tref_max_inst_p )
+ deallocate (fertnitro_p )
+ deallocate (manunitro_p )
+ deallocate (fert_p )
+ deallocate (latbaset_p )
+ deallocate (plantdate_p )
+#endif
+
+! SASU variables
+ deallocate (leafcCap_p )
+ deallocate (leafc_storageCap_p )
+ deallocate (leafc_xferCap_p )
+ deallocate (frootcCap_p )
+ deallocate (frootc_storageCap_p )
+ deallocate (frootc_xferCap_p )
+ deallocate (livestemcCap_p )
+ deallocate (livestemc_storageCap_p )
+ deallocate (livestemc_xferCap_p )
+ deallocate (deadstemcCap_p )
+ deallocate (deadstemc_storageCap_p )
+ deallocate (deadstemc_xferCap_p )
+ deallocate (livecrootcCap_p )
+ deallocate (livecrootc_storageCap_p )
+ deallocate (livecrootc_xferCap_p )
+ deallocate (deadcrootcCap_p )
+ deallocate (deadcrootc_storageCap_p )
+ deallocate (deadcrootc_xferCap_p )
+
+ deallocate (leafnCap_p )
+ deallocate (leafn_storageCap_p )
+ deallocate (leafn_xferCap_p )
+ deallocate (frootnCap_p )
+ deallocate (frootn_storageCap_p )
+ deallocate (frootn_xferCap_p )
+ deallocate (livestemnCap_p )
+ deallocate (livestemn_storageCap_p )
+ deallocate (livestemn_xferCap_p )
+ deallocate (deadstemnCap_p )
+ deallocate (deadstemn_storageCap_p )
+ deallocate (deadstemn_xferCap_p )
+ deallocate (livecrootnCap_p )
+ deallocate (livecrootn_storageCap_p )
+ deallocate (livecrootn_xferCap_p )
+ deallocate (deadcrootnCap_p )
+ deallocate (deadcrootn_storageCap_p )
+ deallocate (deadcrootn_xferCap_p )
+
+ deallocate (leafc0_p )
+ deallocate (leafc0_storage_p )
+ deallocate (leafc0_xfer_p )
+ deallocate (frootc0_p )
+ deallocate (frootc0_storage_p )
+ deallocate (frootc0_xfer_p )
+ deallocate (livestemc0_p )
+ deallocate (livestemc0_storage_p )
+ deallocate (livestemc0_xfer_p )
+ deallocate (deadstemc0_p )
+ deallocate (deadstemc0_storage_p )
+ deallocate (deadstemc0_xfer_p )
+ deallocate (livecrootc0_p )
+ deallocate (livecrootc0_storage_p )
+ deallocate (livecrootc0_xfer_p )
+ deallocate (deadcrootc0_p )
+ deallocate (deadcrootc0_storage_p )
+ deallocate (deadcrootc0_xfer_p )
+ deallocate (grainc0_p )
+ deallocate (grainc0_storage_p )
+ deallocate (grainc0_xfer_p )
+
+ deallocate (leafn0_p )
+ deallocate (leafn0_storage_p )
+ deallocate (leafn0_xfer_p )
+ deallocate (frootn0_p )
+ deallocate (frootn0_storage_p )
+ deallocate (frootn0_xfer_p )
+ deallocate (livestemn0_p )
+ deallocate (livestemn0_storage_p )
+ deallocate (livestemn0_xfer_p )
+ deallocate (deadstemn0_p )
+ deallocate (deadstemn0_storage_p )
+ deallocate (deadstemn0_xfer_p )
+ deallocate (livecrootn0_p )
+ deallocate (livecrootn0_storage_p )
+ deallocate (livecrootn0_xfer_p )
+ deallocate (deadcrootn0_p )
+ deallocate (deadcrootn0_storage_p )
+ deallocate (deadcrootn0_xfer_p )
+ deallocate (grainn0_p )
+ deallocate (grainn0_storage_p )
+ deallocate (grainn0_xfer_p )
+ deallocate (retransn0_p )
+
+ deallocate (I_leafc_p_acc )
+ deallocate (I_leafc_st_p_acc )
+ deallocate (I_frootc_p_acc )
+ deallocate (I_frootc_st_p_acc )
+ deallocate (I_livestemc_p_acc )
+ deallocate (I_livestemc_st_p_acc )
+ deallocate (I_deadstemc_p_acc )
+ deallocate (I_deadstemc_st_p_acc )
+ deallocate (I_livecrootc_p_acc )
+ deallocate (I_livecrootc_st_p_acc )
+ deallocate (I_deadcrootc_p_acc )
+ deallocate (I_deadcrootc_st_p_acc )
+ deallocate (I_grainc_p_acc )
+ deallocate (I_grainc_st_p_acc )
+ deallocate (I_leafn_p_acc )
+ deallocate (I_leafn_st_p_acc )
+ deallocate (I_frootn_p_acc )
+ deallocate (I_frootn_st_p_acc )
+ deallocate (I_livestemn_p_acc )
+ deallocate (I_livestemn_st_p_acc )
+ deallocate (I_deadstemn_p_acc )
+ deallocate (I_deadstemn_st_p_acc )
+ deallocate (I_livecrootn_p_acc )
+ deallocate (I_livecrootn_st_p_acc )
+ deallocate (I_deadcrootn_p_acc )
+ deallocate (I_deadcrootn_st_p_acc )
+ deallocate (I_grainn_p_acc )
+ deallocate (I_grainn_st_p_acc )
+
+ deallocate (AKX_leafc_xf_to_leafc_p_acc )
+ deallocate (AKX_frootc_xf_to_frootc_p_acc )
+ deallocate (AKX_livestemc_xf_to_livestemc_p_acc )
+ deallocate (AKX_deadstemc_xf_to_deadstemc_p_acc )
+ deallocate (AKX_livecrootc_xf_to_livecrootc_p_acc )
+ deallocate (AKX_deadcrootc_xf_to_deadcrootc_p_acc )
+ deallocate (AKX_grainc_xf_to_grainc_p_acc )
+ deallocate (AKX_livestemc_to_deadstemc_p_acc )
+ deallocate (AKX_livecrootc_to_deadcrootc_p_acc )
+
+ deallocate (AKX_leafc_st_to_leafc_xf_p_acc )
+ deallocate (AKX_frootc_st_to_frootc_xf_p_acc )
+ deallocate (AKX_livestemc_st_to_livestemc_xf_p_acc )
+ deallocate (AKX_deadstemc_st_to_deadstemc_xf_p_acc )
+ deallocate (AKX_livecrootc_st_to_livecrootc_xf_p_acc )
+ deallocate (AKX_deadcrootc_st_to_deadcrootc_xf_p_acc )
+ deallocate (AKX_grainc_st_to_grainc_xf_p_acc )
+
+ deallocate (AKX_leafc_exit_p_acc )
+ deallocate (AKX_frootc_exit_p_acc )
+ deallocate (AKX_livestemc_exit_p_acc )
+ deallocate (AKX_deadstemc_exit_p_acc )
+ deallocate (AKX_livecrootc_exit_p_acc )
+ deallocate (AKX_deadcrootc_exit_p_acc )
+ deallocate (AKX_grainc_exit_p_acc )
+
+ deallocate (AKX_leafc_st_exit_p_acc )
+ deallocate (AKX_frootc_st_exit_p_acc )
+ deallocate (AKX_livestemc_st_exit_p_acc )
+ deallocate (AKX_deadstemc_st_exit_p_acc )
+ deallocate (AKX_livecrootc_st_exit_p_acc )
+ deallocate (AKX_deadcrootc_st_exit_p_acc )
+ deallocate (AKX_grainc_st_exit_p_acc )
+
+ deallocate (AKX_leafc_xf_exit_p_acc )
+ deallocate (AKX_frootc_xf_exit_p_acc )
+ deallocate (AKX_livestemc_xf_exit_p_acc )
+ deallocate (AKX_deadstemc_xf_exit_p_acc )
+ deallocate (AKX_livecrootc_xf_exit_p_acc )
+ deallocate (AKX_deadcrootc_xf_exit_p_acc )
+ deallocate (AKX_grainc_xf_exit_p_acc )
+
+ deallocate (AKX_leafn_xf_to_leafn_p_acc )
+ deallocate (AKX_frootn_xf_to_frootn_p_acc )
+ deallocate (AKX_livestemn_xf_to_livestemn_p_acc )
+ deallocate (AKX_deadstemn_xf_to_deadstemn_p_acc )
+ deallocate (AKX_livecrootn_xf_to_livecrootn_p_acc )
+ deallocate (AKX_deadcrootn_xf_to_deadcrootn_p_acc )
+ deallocate (AKX_grainn_xf_to_grainn_p_acc )
+ deallocate (AKX_livestemn_to_deadstemn_p_acc )
+ deallocate (AKX_livecrootn_to_deadcrootn_p_acc )
+
+ deallocate (AKX_leafn_st_to_leafn_xf_p_acc )
+ deallocate (AKX_frootn_st_to_frootn_xf_p_acc )
+ deallocate (AKX_livestemn_st_to_livestemn_xf_p_acc )
+ deallocate (AKX_deadstemn_st_to_deadstemn_xf_p_acc )
+ deallocate (AKX_livecrootn_st_to_livecrootn_xf_p_acc )
+ deallocate (AKX_deadcrootn_st_to_deadcrootn_xf_p_acc )
+ deallocate (AKX_grainn_st_to_grainn_xf_p_acc )
+
+ deallocate (AKX_leafn_to_retransn_p_acc )
+ deallocate (AKX_frootn_to_retransn_p_acc )
+ deallocate (AKX_livestemn_to_retransn_p_acc )
+ deallocate (AKX_livecrootn_to_retransn_p_acc )
+
+ deallocate (AKX_retransn_to_leafn_p_acc )
+ deallocate (AKX_retransn_to_frootn_p_acc )
+ deallocate (AKX_retransn_to_livestemn_p_acc )
+ deallocate (AKX_retransn_to_deadstemn_p_acc )
+ deallocate (AKX_retransn_to_livecrootn_p_acc )
+ deallocate (AKX_retransn_to_deadcrootn_p_acc )
+ deallocate (AKX_retransn_to_grainn_p_acc )
+
+ deallocate (AKX_retransn_to_leafn_st_p_acc )
+ deallocate (AKX_retransn_to_frootn_st_p_acc )
+ deallocate (AKX_retransn_to_livestemn_st_p_acc )
+ deallocate (AKX_retransn_to_deadstemn_st_p_acc )
+ deallocate (AKX_retransn_to_livecrootn_st_p_acc )
+ deallocate (AKX_retransn_to_deadcrootn_st_p_acc )
+ deallocate (AKX_retransn_to_grainn_st_p_acc )
+
+ deallocate (AKX_leafn_exit_p_acc )
+ deallocate (AKX_frootn_exit_p_acc )
+ deallocate (AKX_livestemn_exit_p_acc )
+ deallocate (AKX_deadstemn_exit_p_acc )
+ deallocate (AKX_livecrootn_exit_p_acc )
+ deallocate (AKX_deadcrootn_exit_p_acc )
+ deallocate (AKX_grainn_exit_p_acc )
+ deallocate (AKX_retransn_exit_p_acc )
+
+ deallocate (AKX_leafn_st_exit_p_acc )
+ deallocate (AKX_frootn_st_exit_p_acc )
+ deallocate (AKX_livestemn_st_exit_p_acc )
+ deallocate (AKX_deadstemn_st_exit_p_acc )
+ deallocate (AKX_livecrootn_st_exit_p_acc )
+ deallocate (AKX_deadcrootn_st_exit_p_acc )
+ deallocate (AKX_grainn_st_exit_p_acc )
+
+ deallocate (AKX_leafn_xf_exit_p_acc )
+ deallocate (AKX_frootn_xf_exit_p_acc )
+ deallocate (AKX_livestemn_xf_exit_p_acc )
+ deallocate (AKX_deadstemn_xf_exit_p_acc )
+ deallocate (AKX_livecrootn_xf_exit_p_acc )
+ deallocate (AKX_deadcrootn_xf_exit_p_acc )
+ deallocate (AKX_grainn_xf_exit_p_acc )
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_BGCPFTimeVariables
+
+#ifdef RangeCheck
+ SUBROUTINE check_BGCPFTimeVariables
+
+ USE MOD_RangeCheck
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+! bgc variables
+ CALL check_vector_data ('leafc_p ', leafc_p )
+ CALL check_vector_data ('leafc_storage_p ', leafc_storage_p )
+ CALL check_vector_data ('leafc_xfer_p ', leafc_xfer_p )
+ CALL check_vector_data ('frootc_p ', frootc_p )
+ CALL check_vector_data ('frootc_storage_p ', frootc_storage_p )
+ CALL check_vector_data ('frootc_xfer_p ', frootc_xfer_p )
+ CALL check_vector_data ('livestemc_p ', livestemc_p )
+ CALL check_vector_data ('livestemc_storage_p ', livestemc_storage_p )
+ CALL check_vector_data ('livestemc_xfer_p ', livestemc_xfer_p )
+ CALL check_vector_data ('deadstemc_p ', deadstemc_p )
+ CALL check_vector_data ('deadstemc_storage_p ', deadstemc_storage_p )
+ CALL check_vector_data ('deadstemc_xfer_p ', deadstemc_xfer_p )
+ CALL check_vector_data ('livecrootc_p ', livecrootc_p )
+ CALL check_vector_data ('livecrootc_storage_p ', livecrootc_storage_p )
+ CALL check_vector_data ('livecrootc_xfer_p ', livecrootc_xfer_p )
+ CALL check_vector_data ('deadcrootc_p ', deadcrootc_p )
+ CALL check_vector_data ('deadcrootc_storage_p ', deadcrootc_storage_p )
+ CALL check_vector_data ('deadcrootc_xfer_p ', deadcrootc_xfer_p )
+ CALL check_vector_data ('grainc_p ', grainc_p )
+ CALL check_vector_data ('grainc_storage_p ', grainc_storage_p )
+ CALL check_vector_data ('grainc_xfer_p ', grainc_xfer_p )
+ CALL check_vector_data ('cropseedc_deficit_p ', cropseedc_deficit_p )
+ CALL check_vector_data ('xsmrpool_p ', xsmrpool_p )
+ CALL check_vector_data ('gresp_storage_p ', gresp_storage_p )
+ CALL check_vector_data ('gresp_xfer_p ', gresp_xfer_p )
+ CALL check_vector_data ('cpool_p ', cpool_p )
+ CALL check_vector_data ('totvegc_p ', totvegc_p )
+ CALL check_vector_data ('cropprod1c_p ', cropprod1c_p )
+
+ CALL check_vector_data ('leaf_prof_p ', leaf_prof_p )
+ CALL check_vector_data ('froot_prof_p ', froot_prof_p )
+ CALL check_vector_data ('croot_prof_p ', croot_prof_p )
+ CALL check_vector_data ('stem_prof_p ', stem_prof_p )
+ CALL check_vector_data ('cinput_rootfr_p ', cinput_rootfr_p )
+
+ CALL check_vector_data ('leafn_p ', leafn_p )
+ CALL check_vector_data ('leafn_storage_p ', leafn_storage_p )
+ CALL check_vector_data ('leafn_xfer_p ', leafn_xfer_p )
+ CALL check_vector_data ('frootn_p ', frootn_p )
+ CALL check_vector_data ('frootn_storage_p ', frootn_storage_p )
+ CALL check_vector_data ('frootn_xfer_p ', frootn_xfer_p )
+ CALL check_vector_data ('livestemn_p ', livestemn_p )
+ CALL check_vector_data ('livestemn_storage_p ', livestemn_storage_p )
+ CALL check_vector_data ('livestemn_xfer_p ', livestemn_xfer_p )
+ CALL check_vector_data ('deadstemn_p ', deadstemn_p )
+ CALL check_vector_data ('deadstemn_storage_p ', deadstemn_storage_p )
+ CALL check_vector_data ('deadstemn_xfer_p ', deadstemn_xfer_p )
+ CALL check_vector_data ('livecrootn_p ', livecrootn_p )
+ CALL check_vector_data ('livecrootn_storage_p ', livecrootn_storage_p )
+ CALL check_vector_data ('livecrootn_xfer_p ', livecrootn_xfer_p )
+ CALL check_vector_data ('deadcrootn_p ', deadcrootn_p )
+ CALL check_vector_data ('deadcrootn_storage_p ', deadcrootn_storage_p )
+ CALL check_vector_data ('deadcrootn_xfer_p ', deadcrootn_xfer_p )
+ CALL check_vector_data ('grainn_p ', grainn_p )
+ CALL check_vector_data ('grainn_storage_p ', grainn_storage_p )
+ CALL check_vector_data ('grainn_xfer_p ', grainn_xfer_p )
+ CALL check_vector_data ('cropseedn_deficit_p ', cropseedn_deficit_p )
+ CALL check_vector_data ('retransn_p ', retransn_p )
+ CALL check_vector_data ('totvegn_p ', totvegn_p )
+
+ CALL check_vector_data ('harvdate_p ', harvdate_p )
+
+ CALL check_vector_data ('tempsum_potential_gpp_p', tempsum_potential_gpp_p)
+ CALL check_vector_data ('tempmax_retransn_p ', tempmax_retransn_p )
+ CALL check_vector_data ('tempavg_tref_p ', tempavg_tref_p )
+ CALL check_vector_data ('tempsum_npp_p ', tempsum_npp_p )
+ CALL check_vector_data ('tempsum_litfall_p ', tempsum_litfall_p )
+ CALL check_vector_data ('annsum_potential_gpp_p ', annsum_potential_gpp_p )
+ CALL check_vector_data ('annmax_retransn_p ', annmax_retransn_p )
+ CALL check_vector_data ('annavg_tref_p ', annavg_tref_p )
+ CALL check_vector_data ('annsum_npp_p ', annsum_npp_p )
+ CALL check_vector_data ('annsum_litfall_p ', annsum_litfall_p )
+
+ CALL check_vector_data ('bglfr_p ', bglfr_p )
+ CALL check_vector_data ('bgtr_p ', bgtr_p )
+ CALL check_vector_data ('lgsf_p ', lgsf_p )
+ CALL check_vector_data ('gdd0_p ', gdd0_p )
+ CALL check_vector_data ('gdd8_p ', gdd8_p )
+ CALL check_vector_data ('gdd10_p ', gdd10_p )
+ CALL check_vector_data ('gdd020_p ', gdd020_p )
+ CALL check_vector_data ('gdd820_p ', gdd820_p )
+ CALL check_vector_data ('gdd1020_p ', gdd1020_p )
+
+ CALL check_vector_data ('offset_flag_p ', offset_flag_p )
+ CALL check_vector_data ('offset_counter_p ', offset_counter_p )
+ CALL check_vector_data ('onset_flag_p ', onset_flag_p )
+ CALL check_vector_data ('onset_counter_p ', onset_counter_p )
+ CALL check_vector_data ('onset_gddflag_p ', onset_gddflag_p )
+ CALL check_vector_data ('onset_gdd_p ', onset_gdd_p )
+ CALL check_vector_data ('onset_fdd_p ', onset_fdd_p )
+ CALL check_vector_data ('onset_swi_p ', onset_swi_p )
+ CALL check_vector_data ('offset_fdd_p ', offset_fdd_p )
+ CALL check_vector_data ('offset_swi_p ', offset_swi_p )
+ CALL check_vector_data ('dormant_flag_p ', dormant_flag_p )
+ CALL check_vector_data ('prev_leafc_to_litter_p ', prev_leafc_to_litter_p )
+ CALL check_vector_data ('prev_frootc_to_litter_p', prev_frootc_to_litter_p)
+ CALL check_vector_data ('days_active_p ', days_active_p )
+
+ CALL check_vector_data ('burndate_p ', burndate_p )
+
+ CALL check_vector_data ('c_allometry_p ', c_allometry_p )
+ CALL check_vector_data ('n_allometry_p ', n_allometry_p )
+ CALL check_vector_data ('downreg_p ', downreg_p )
+ CALL check_vector_data ('grain_flag_p ', grain_flag_p )
+
+ CALL check_vector_data ('ctrunc_p ', ctrunc_p )
+ CALL check_vector_data ('ntrunc_p ', ntrunc_p )
+ CALL check_vector_data ('npool_p ', npool_p )
+
+#ifdef CROP
+! crop variables
+ CALL check_vector_data ('hui_p ', hui_p )
+ CALL check_vector_data ('gddplant_p ', gddplant_p )
+ CALL check_vector_data ('aroot_p ', aroot_p )
+ CALL check_vector_data ('astem_p ', astem_p )
+ CALL check_vector_data ('arepr_p ', arepr_p )
+ CALL check_vector_data ('aleaf_p ', aleaf_p )
+ CALL check_vector_data ('astemi_p ', astemi_p )
+ CALL check_vector_data ('aleafi_p ', aleafi_p )
+ CALL check_vector_data ('gddmaturity_p ', gddmaturity_p )
+
+ CALL check_vector_data ('a5tmin_p ', a5tmin_p )
+ CALL check_vector_data ('a10tmin_p ', a10tmin_p )
+ CALL check_vector_data ('t10_p ', t10_p )
+ CALL check_vector_data ('cumvd_p ', cumvd_p )
+ CALL check_vector_data ('vf_p ', vf_p )
+ CALL check_vector_data ('cphase_p ', cphase_p )
+ CALL check_vector_data ('fert_counter_p ', fert_counter_p )
+ CALL check_vector_data ('tref_min_p ', tref_min_p )
+ CALL check_vector_data ('tref_max_p ', tref_max_p )
+ CALL check_vector_data ('tref_min_inst_p ', tref_min_inst_p )
+ CALL check_vector_data ('tref_max_inst_p ', tref_max_inst_p )
+ CALL check_vector_data ('fertnitro_p ', fertnitro_p )
+ CALL check_vector_data ('manunitro_p ', manunitro_p )
+ CALL check_vector_data ('fert_p ', fert_p )
+ CALL check_vector_data ('latbaset_p ', latbaset_p )
+ CALL check_vector_data ('plantdate_p ', plantdate_p )
+#endif
+
+ IF(DEF_USE_DiagMatrix)THEN
+! SASU variables
+ CALL check_vector_data ('leafcCap_p ', leafcCap_p )
+ CALL check_vector_data ('leafc_storageCap_p ', leafc_storageCap_p )
+ CALL check_vector_data ('leafc_xferCap_p ', leafc_xferCap_p )
+ CALL check_vector_data ('frootcCap_p ', frootcCap_p )
+ CALL check_vector_data ('frootc_storageCap_p ', frootc_storageCap_p )
+ CALL check_vector_data ('frootc_xferCap_p ', frootc_xferCap_p )
+ CALL check_vector_data ('livestemcCap_p ', livestemcCap_p )
+ CALL check_vector_data ('livestemc_storageCap_p ', livestemc_storageCap_p )
+ CALL check_vector_data ('livestemc_xferCap_p ', livestemc_xferCap_p )
+ CALL check_vector_data ('deadstemcCap_p ', deadstemcCap_p )
+ CALL check_vector_data ('deadstemc_storageCap_p ', deadstemc_storageCap_p )
+ CALL check_vector_data ('deadstemc_xferCap_p ', deadstemc_xferCap_p )
+ CALL check_vector_data ('livecrootcCap_p ', livecrootcCap_p )
+ CALL check_vector_data ('livecrootc_storageCap_p ', livecrootc_storageCap_p )
+ CALL check_vector_data ('livecrootc_xferCap_p ', livecrootc_xferCap_p )
+ CALL check_vector_data ('deadcrootcCap_p ', deadcrootcCap_p )
+ CALL check_vector_data ('deadcrootc_storageCap_p ', deadcrootc_storageCap_p )
+ CALL check_vector_data ('deadcrootc_xferCap_p ', deadcrootc_xferCap_p )
+
+ CALL check_vector_data ('leafnCap_p ', leafnCap_p )
+ CALL check_vector_data ('leafn_storageCap_p ', leafn_storageCap_p )
+ CALL check_vector_data ('leafn_xferCap_p ', leafn_xferCap_p )
+ CALL check_vector_data ('frootnCap_p ', frootnCap_p )
+ CALL check_vector_data ('frootn_storageCap_p ', frootn_storageCap_p )
+ CALL check_vector_data ('frootn_xferCap_p ', frootn_xferCap_p )
+ CALL check_vector_data ('livestemnCap_p ', livestemnCap_p )
+ CALL check_vector_data ('livestemn_storageCap_p ', livestemn_storageCap_p )
+ CALL check_vector_data ('livestemn_xferCap_p ', livestemn_xferCap_p )
+ CALL check_vector_data ('deadstemnCap_p ', deadstemnCap_p )
+ CALL check_vector_data ('deadstemn_storageCap_p ', deadstemn_storageCap_p )
+ CALL check_vector_data ('deadstemn_xferCap_p ', deadstemn_xferCap_p )
+ CALL check_vector_data ('livecrootnCap_p ', livecrootnCap_p )
+ CALL check_vector_data ('livecrootn_storageCap_p ', livecrootn_storageCap_p )
+ CALL check_vector_data ('livecrootn_xferCap_p ', livecrootn_xferCap_p )
+ CALL check_vector_data ('deadcrootnCap_p ', deadcrootnCap_p )
+ CALL check_vector_data ('deadcrootn_storageCap_p ', deadcrootn_storageCap_p )
+ CALL check_vector_data ('deadcrootn_xferCap_p ', deadcrootn_xferCap_p )
+ ENDIF
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ CALL check_vector_data ('leafc0_p ', leafc0_p )
+ CALL check_vector_data ('leafc0_storage_p ', leafc0_storage_p )
+ CALL check_vector_data ('leafc0_xfer_p ', leafc0_xfer_p )
+ CALL check_vector_data ('frootc0_p ', frootc0_p )
+ CALL check_vector_data ('frootc0_storage_p ', frootc0_storage_p )
+ CALL check_vector_data ('frootc0_xfer_p ', frootc0_xfer_p )
+ CALL check_vector_data ('livestemc0_p ', livestemc0_p )
+ CALL check_vector_data ('livestemc0_storage_p ', livestemc0_storage_p )
+ CALL check_vector_data ('livestemc0_xfer_p ', livestemc0_xfer_p )
+ CALL check_vector_data ('deadstemc0_p ', deadstemc0_p )
+ CALL check_vector_data ('deadstemc0_storage_p ', deadstemc0_storage_p )
+ CALL check_vector_data ('deadstemc0_xfer_p ', deadstemc0_xfer_p )
+ CALL check_vector_data ('livecrootc0_p ', livecrootc0_p )
+ CALL check_vector_data ('livecrootc0_storage_p ', livecrootc0_storage_p )
+ CALL check_vector_data ('livecrootc0_xfer_p ', livecrootc0_xfer_p )
+ CALL check_vector_data ('deadcrootc0_p ', deadcrootc0_p )
+ CALL check_vector_data ('deadcrootc0_storage_p ', deadcrootc0_storage_p )
+ CALL check_vector_data ('deadcrootc0_xfer_p ', deadcrootc0_xfer_p )
+ CALL check_vector_data ('grainc0_p ', grainc0_p )
+ CALL check_vector_data ('grainc0_storage_p ', grainc0_storage_p )
+ CALL check_vector_data ('grainc0_xfer_p ', grainc0_xfer_p )
+
+ CALL check_vector_data ('leafn0_p ', leafn0_p )
+ CALL check_vector_data ('leafn0_storage_p ', leafn0_storage_p )
+ CALL check_vector_data ('leafn0_xfer_p ', leafn0_xfer_p )
+ CALL check_vector_data ('frootn0_p ', frootn0_p )
+ CALL check_vector_data ('frootn0_storage_p ', frootn0_storage_p )
+ CALL check_vector_data ('frootn0_xfer_p ', frootn0_xfer_p )
+ CALL check_vector_data ('livestemn0_p ', livestemn0_p )
+ CALL check_vector_data ('livestemn0_storage_p ', livestemn0_storage_p )
+ CALL check_vector_data ('livestemn0_xfer_p ', livestemn0_xfer_p )
+ CALL check_vector_data ('deadstemn0_p ', deadstemn0_p )
+ CALL check_vector_data ('deadstemn0_storage_p ', deadstemn0_storage_p )
+ CALL check_vector_data ('deadstemn0_xfer_p ', deadstemn0_xfer_p )
+ CALL check_vector_data ('livecrootn0_p ', livecrootn0_p )
+ CALL check_vector_data ('livecrootn0_storage_p ', livecrootn0_storage_p )
+ CALL check_vector_data ('livecrootn0_xfer_p ', livecrootn0_xfer_p )
+ CALL check_vector_data ('deadcrootn0_p ', deadcrootn0_p )
+ CALL check_vector_data ('deadcrootn0_storage_p ', deadcrootn0_storage_p )
+ CALL check_vector_data ('deadcrootn0_xfer_p ', deadcrootn0_xfer_p )
+ CALL check_vector_data ('grainn0_p ', grainn0_p )
+ CALL check_vector_data ('grainn0_storage_p ', grainn0_storage_p )
+ CALL check_vector_data ('grainn0_xfer_p ', grainn0_xfer_p )
+ CALL check_vector_data ('retransn0_p ', retransn0_p )
+
+ CALL check_vector_data ('I_leafc_p_acc ', I_leafc_p_acc )
+ CALL check_vector_data ('I_leafc_st_p_acc ', I_leafc_st_p_acc )
+ CALL check_vector_data ('I_frootc_p_acc ', I_frootc_p_acc )
+ CALL check_vector_data ('I_frootc_st_p_acc ', I_frootc_st_p_acc )
+ CALL check_vector_data ('I_livestemc_p_acc ', I_livestemc_p_acc )
+ CALL check_vector_data ('I_livestemc_st_p_acc ', I_livestemc_st_p_acc )
+ CALL check_vector_data ('I_deadstemc_p_acc ', I_deadstemc_p_acc )
+ CALL check_vector_data ('I_deadstemc_st_p_acc ', I_deadstemc_st_p_acc )
+ CALL check_vector_data ('I_livecrootc_p_acc ', I_livecrootc_p_acc )
+ CALL check_vector_data ('I_livecrootc_st_p_acc ', I_livecrootc_st_p_acc )
+ CALL check_vector_data ('I_deadcrootc_p_acc ', I_deadcrootc_p_acc )
+ CALL check_vector_data ('I_deadcrootc_st_p_acc ', I_deadcrootc_st_p_acc )
+ CALL check_vector_data ('I_grainc_p_acc ', I_grainc_p_acc )
+ CALL check_vector_data ('I_grainc_st_p_acc ', I_grainc_st_p_acc )
+ CALL check_vector_data ('I_leafn_p_acc ', I_leafn_p_acc )
+ CALL check_vector_data ('I_leafn_st_p_acc ', I_leafn_st_p_acc )
+ CALL check_vector_data ('I_frootn_p_acc ', I_frootn_p_acc )
+ CALL check_vector_data ('I_frootn_st_p_acc ', I_frootn_st_p_acc )
+ CALL check_vector_data ('I_livestemn_p_acc ', I_livestemn_p_acc )
+ CALL check_vector_data ('I_livestemn_st_p_acc ', I_livestemn_st_p_acc )
+ CALL check_vector_data ('I_deadstemn_p_acc ', I_deadstemn_p_acc )
+ CALL check_vector_data ('I_deadstemn_st_p_acc ', I_deadstemn_st_p_acc )
+ CALL check_vector_data ('I_livecrootn_p_acc ', I_livecrootn_p_acc )
+ CALL check_vector_data ('I_livecrootn_st_p_acc ', I_livecrootn_st_p_acc )
+ CALL check_vector_data ('I_deadcrootn_p_acc ', I_deadcrootn_p_acc )
+ CALL check_vector_data ('I_deadcrootn_st_p_acc ', I_deadcrootn_st_p_acc )
+ CALL check_vector_data ('I_grainn_p_acc ', I_grainn_p_acc )
+ CALL check_vector_data ('I_grainn_st_p_acc ', I_grainn_st_p_acc )
+
+ CALL check_vector_data ('AKX_leafc_xf_to_leafc_p_acc ', AKX_leafc_xf_to_leafc_p_acc )
+ CALL check_vector_data ('AKX_frootc_xf_to_frootc_p_acc ', AKX_frootc_xf_to_frootc_p_acc )
+ CALL check_vector_data ('AKX_livestemc_xf_to_livestemc_p_acc ', AKX_livestemc_xf_to_livestemc_p_acc )
+ CALL check_vector_data ('AKX_deadstemc_xf_to_deadstemc_p_acc ', AKX_deadstemc_xf_to_deadstemc_p_acc )
+ CALL check_vector_data ('AKX_livecrootc_xf_to_livecrootc_p_acc ', AKX_livecrootc_xf_to_livecrootc_p_acc )
+ CALL check_vector_data ('AKX_deadcrootc_xf_to_deadcrootc_p_acc ', AKX_deadcrootc_xf_to_deadcrootc_p_acc )
+ CALL check_vector_data ('AKX_grainc_xf_to_grainc_p_acc ', AKX_grainc_xf_to_grainc_p_acc )
+ CALL check_vector_data ('AKX_livestemc_to_deadstemc_p_acc ', AKX_livestemc_to_deadstemc_p_acc )
+ CALL check_vector_data ('AKX_livecrootc_to_deadcrootc_p_acc ', AKX_livecrootc_to_deadcrootc_p_acc )
+ CALL check_vector_data ('AKX_leafc_st_to_leafc_xf_p_acc ', AKX_leafc_st_to_leafc_xf_p_acc )
+ CALL check_vector_data ('AKX_frootc_st_to_frootc_xf_p_acc ', AKX_frootc_st_to_frootc_xf_p_acc )
+ CALL check_vector_data ('AKX_livestemc_st_to_livestemc_xf_p_acc ', AKX_livestemc_st_to_livestemc_xf_p_acc )
+ CALL check_vector_data ('AKX_deadstemc_st_to_deadstemc_xf_p_acc ', AKX_deadstemc_st_to_deadstemc_xf_p_acc )
+ CALL check_vector_data ('AKX_livecrootc_st_to_livecrootc_xf_p_acc ', AKX_livecrootc_st_to_livecrootc_xf_p_acc )
+ CALL check_vector_data ('AKX_deadcrootc_st_to_deadcrootc_xf_p_acc ', AKX_deadcrootc_st_to_deadcrootc_xf_p_acc )
+ CALL check_vector_data ('AKX_grainc_st_to_grainc_xf_p_acc ', AKX_grainc_st_to_grainc_xf_p_acc )
+ CALL check_vector_data ('AKX_leafc_exit_p_acc ', AKX_leafc_exit_p_acc )
+ CALL check_vector_data ('AKX_frootc_exit_p_acc ', AKX_frootc_exit_p_acc )
+ CALL check_vector_data ('AKX_livestemc_exit_p_acc ', AKX_livestemc_exit_p_acc )
+ CALL check_vector_data ('AKX_deadstemc_exit_p_acc ', AKX_deadstemc_exit_p_acc )
+ CALL check_vector_data ('AKX_livecrootc_exit_p_acc ', AKX_livecrootc_exit_p_acc )
+ CALL check_vector_data ('AKX_deadcrootc_exit_p_acc ', AKX_deadcrootc_exit_p_acc )
+ CALL check_vector_data ('AKX_grainc_exit_p_acc ', AKX_grainc_exit_p_acc )
+
+ CALL check_vector_data ('AKX_leafc_st_exit_p_acc ', AKX_leafc_st_exit_p_acc )
+ CALL check_vector_data ('AKX_frootc_st_exit_p_acc ', AKX_frootc_st_exit_p_acc )
+ CALL check_vector_data ('AKX_livestemc_st_exit_p_acc ', AKX_livestemc_st_exit_p_acc )
+ CALL check_vector_data ('AKX_deadstemc_st_exit_p_acc ', AKX_deadstemc_st_exit_p_acc )
+ CALL check_vector_data ('AKX_livecrootc_st_exit_p_acc ', AKX_livecrootc_st_exit_p_acc )
+ CALL check_vector_data ('AKX_deadcrootc_st_exit_p_acc ', AKX_deadcrootc_st_exit_p_acc )
+ CALL check_vector_data ('AKX_grainc_st_exit_p_acc ', AKX_grainc_st_exit_p_acc )
+
+ CALL check_vector_data ('AKX_leafc_xf_exit_p_acc ', AKX_leafc_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_frootc_xf_exit_p_acc ', AKX_frootc_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_livestemc_xf_exit_p_acc ', AKX_livestemc_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_deadstemc_xf_exit_p_acc ', AKX_deadstemc_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_livecrootc_xf_exit_p_acc ', AKX_livecrootc_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_deadcrootc_xf_exit_p_acc ', AKX_deadcrootc_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_grainc_xf_exit_p_acc ', AKX_grainc_xf_exit_p_acc )
+
+ CALL check_vector_data ('AKX_leafn_xf_to_leafn_p_acc ', AKX_leafn_xf_to_leafn_p_acc )
+ CALL check_vector_data ('AKX_frootn_xf_to_frootn_p_acc ', AKX_frootn_xf_to_frootn_p_acc )
+ CALL check_vector_data ('AKX_livestemn_xf_to_livestemn_p_acc ', AKX_livestemn_xf_to_livestemn_p_acc )
+ CALL check_vector_data ('AKX_deadstemn_xf_to_deadstemn_p_acc ', AKX_deadstemn_xf_to_deadstemn_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_xf_to_livecrootn_p_acc ', AKX_livecrootn_xf_to_livecrootn_p_acc )
+ CALL check_vector_data ('AKX_deadcrootn_xf_to_deadcrootn_p_acc ', AKX_deadcrootn_xf_to_deadcrootn_p_acc )
+ CALL check_vector_data ('AKX_grainn_xf_to_grainn_p_acc ', AKX_grainn_xf_to_grainn_p_acc )
+ CALL check_vector_data ('AKX_livestemn_to_deadstemn_p_acc ', AKX_livestemn_to_deadstemn_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_to_deadcrootn_p_acc ', AKX_livecrootn_to_deadcrootn_p_acc )
+
+ CALL check_vector_data ('AKX_leafn_st_to_leafn_xf_p_acc ', AKX_leafn_st_to_leafn_xf_p_acc )
+ CALL check_vector_data ('AKX_frootn_st_to_frootn_xf_p_acc ', AKX_frootn_st_to_frootn_xf_p_acc )
+ CALL check_vector_data ('AKX_livestemn_st_to_livestemn_xf_p_acc ', AKX_livestemn_st_to_livestemn_xf_p_acc )
+ CALL check_vector_data ('AKX_deadstemn_st_to_deadstemn_xf_p_acc ', AKX_deadstemn_st_to_deadstemn_xf_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_st_to_livecrootn_xf_p_acc ', AKX_livecrootn_st_to_livecrootn_xf_p_acc )
+ CALL check_vector_data ('AKX_deadcrootn_st_to_deadcrootn_xf_p_acc ', AKX_deadcrootn_st_to_deadcrootn_xf_p_acc )
+ CALL check_vector_data ('AKX_grainn_st_to_grainn_xf_p_acc ', AKX_grainn_st_to_grainn_xf_p_acc )
+
+ CALL check_vector_data ('AKX_leafn_to_retransn_p_acc ', AKX_leafn_to_retransn_p_acc )
+ CALL check_vector_data ('AKX_frootn_to_retransn_p_acc ', AKX_frootn_to_retransn_p_acc )
+ CALL check_vector_data ('AKX_livestemn_to_retransn_p_acc ', AKX_livestemn_to_retransn_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_to_retransn_p_acc ', AKX_livecrootn_to_retransn_p_acc )
+
+ CALL check_vector_data ('AKX_retransn_to_leafn_p_acc ', AKX_retransn_to_leafn_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_frootn_p_acc ', AKX_retransn_to_frootn_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_livestemn_p_acc ', AKX_retransn_to_livestemn_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_deadstemn_p_acc ', AKX_retransn_to_deadstemn_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_livecrootn_p_acc ', AKX_retransn_to_livecrootn_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_deadcrootn_p_acc ', AKX_retransn_to_deadcrootn_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_grainn_p_acc ', AKX_retransn_to_grainn_p_acc )
+
+ CALL check_vector_data ('AKX_retransn_to_leafn_st_p_acc ', AKX_retransn_to_leafn_st_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_frootn_st_p_acc ', AKX_retransn_to_frootn_st_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_livestemn_st_p_acc ', AKX_retransn_to_livestemn_st_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_deadstemn_st_p_acc ', AKX_retransn_to_deadstemn_st_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_livecrootn_st_p_acc ', AKX_retransn_to_livecrootn_st_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_deadcrootn_st_p_acc ', AKX_retransn_to_deadcrootn_st_p_acc )
+ CALL check_vector_data ('AKX_retransn_to_grainn_st_p_acc ', AKX_retransn_to_grainn_st_p_acc )
+
+ CALL check_vector_data ('AKX_leafn_exit_p_acc ', AKX_leafn_exit_p_acc )
+ CALL check_vector_data ('AKX_frootn_exit_p_acc ', AKX_frootn_exit_p_acc )
+ CALL check_vector_data ('AKX_livestemn_exit_p_acc ', AKX_livestemn_exit_p_acc )
+ CALL check_vector_data ('AKX_deadstemn_exit_p_acc ', AKX_deadstemn_exit_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_exit_p_acc ', AKX_livecrootn_exit_p_acc )
+ CALL check_vector_data ('AKX_deadcrootn_exit_p_acc ', AKX_deadcrootn_exit_p_acc )
+ CALL check_vector_data ('AKX_grainn_exit_p_acc ', AKX_grainn_exit_p_acc )
+ CALL check_vector_data ('AKX_retransn_exit_p_acc ', AKX_retransn_exit_p_acc )
+
+ CALL check_vector_data ('AKX_leafn_st_exit_p_acc ', AKX_leafn_st_exit_p_acc )
+ CALL check_vector_data ('AKX_frootn_st_exit_p_acc ', AKX_frootn_st_exit_p_acc )
+ CALL check_vector_data ('AKX_livestemn_st_exit_p_acc ', AKX_livestemn_st_exit_p_acc )
+ CALL check_vector_data ('AKX_deadstemn_st_exit_p_acc ', AKX_deadstemn_st_exit_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_st_exit_p_acc ', AKX_livecrootn_st_exit_p_acc )
+ CALL check_vector_data ('AKX_deadcrootn_st_exit_p_acc ', AKX_deadcrootn_st_exit_p_acc )
+ CALL check_vector_data ('AKX_grainn_st_exit_p_acc ', AKX_grainn_st_exit_p_acc )
+
+ CALL check_vector_data ('AKX_leafn_xf_exit_p_acc ', AKX_leafn_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_frootn_xf_exit_p_acc ', AKX_frootn_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_livestemn_xf_exit_p_acc ', AKX_livestemn_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_deadstemn_xf_exit_p_acc ', AKX_deadstemn_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_livecrootn_xf_exit_p_acc ', AKX_livecrootn_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_deadcrootn_xf_exit_p_acc ', AKX_deadcrootn_xf_exit_p_acc )
+ CALL check_vector_data ('AKX_grainn_xf_exit_p_acc ', AKX_grainn_xf_exit_p_acc )
+ ENDIF
+ END SUBROUTINE check_BGCPFTimeVariables
+#endif
+
+#endif
+END MODULE MOD_BGC_Vars_PFTimeVariables
+
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_TimeInvariants.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_TimeInvariants.F90
new file mode 100644
index 0000000000..6d9d9605a9
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_TimeInvariants.F90
@@ -0,0 +1,512 @@
+#include
+
+MODULE MOD_BGC_Vars_TimeInvariants
+
+! --------------------------------------------------------------------
+
+! !DESCRIPTION
+! Define, allocate, and deallocate biogeochemical constant at patch level.
+! Read and write biogeochemical constant at patch level from/to restart files.
+
+! !ORIGINAL:
+! Xingjie Lu, 2022, created the original version
+! -------------------------------
+#ifdef BGC
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+!------------------------- BGC constant --------------------------------------
+ integer , allocatable :: donor_pool (:) ! soil or litter pools where each decomposition transfered C&N is from.
+ integer , allocatable :: receiver_pool (:) ! soil or litter pools where each decomposition transfered C&N is to
+ real(r8) :: am ! gap-mortality rate constant (year-1)
+ logical , allocatable :: floating_cn_ratio(:) ! flag, soil or litter pool has 1) true: flexible or 2) false: fixed C:N ratio.
+ real(r8), allocatable :: initial_cn_ratio (:) ! initial c:n ratio of each litter and soil pool
+ real(r8), allocatable :: rf_decomp (:,:,:) ! respiratory fraction of the ith transfer hr(i) / (hr(i) + ctransfer(i))
+ real(r8), allocatable :: pathfrac_decomp (:,:,:) ! pathway fraction of each transfer from the same donor pool &
+ ! (hr(i)+ctransfer(i))/sum(hr(donor_pool(:)==donor_pool(i))+ctransfer(donor_pool(:)==donor_pool(i)))
+
+ integer :: i_met_lit ! index of metabolic litter pool
+ integer :: i_cel_lit ! index of cellulose litter pool
+ integer :: i_lig_lit ! index of lignin litter pool
+ integer :: i_cwd ! index of coarse woody debris pool
+ integer :: i_soil1 ! index of active soil organic matter pool
+ integer :: i_soil2 ! index of slow soil organic matter pool
+ integer :: i_soil3 ! index of passive soil organic matter pool
+ integer :: i_atm ! index of atmosphere pool
+
+ logical , allocatable :: is_cwd (:) ! (1:ndecomp_pools) ! True => is a coarse woody debris pool
+ logical , allocatable :: is_litter (:) ! (1:ndecomp_pools) ! True => is a litter pool
+ logical , allocatable :: is_soil (:) ! (1:ndecomp_pools) ! True => is a soil pool
+
+ real(r8), allocatable :: gdp_lf (:) ! gdp data
+ real(r8), allocatable :: abm_lf (:) ! prescribed crop fire time
+ real(r8), allocatable :: peatf_lf (:) ! peatland fraction data
+ real(r8), allocatable :: cmb_cmplt_fact(:) ! combustion completion factor
+ integer , allocatable :: rice2pdt (:) ! rice2 planting date
+
+ real(r8) :: nitrif_n2o_loss_frac ! fraction of N lost as N2O in nitrification (unitless)
+ real(r8) :: dnp ! denitrification proportion (unitless)
+ real(r8) :: bdnr ! bulk denitrification rate (1/day)
+ real(r8) :: compet_plant_no3 ! relative compettiveness of plants for NO3 (unitless)
+ real(r8) :: compet_plant_nh4 ! relative compettiveness of plants for NH4 (unitless)
+ real(r8) :: compet_decomp_no3 ! relative competitiveness of immobilizers for NO3 (unitless)
+ real(r8) :: compet_decomp_nh4 ! relative competitiveness of immobilizers for NH4 (unitless)
+ real(r8) :: compet_denit ! relative competitiveness of denitrifiers for NO3 (unitless)
+ real(r8) :: compet_nit ! relative competitiveness of nitrifiers for NH4 (unitless)
+ real(r8) :: surface_tension_water ! surface tension of water (J m-2)
+ real(r8) :: rij_kro_a ! parameters for calculation of anoxic fraction of soil
+ real(r8) :: rij_kro_alpha ! parameters for calculation of anoxic fraction of soil
+ real(r8) :: rij_kro_beta ! parameters for calculation of anoxic fraction of soil
+ real(r8) :: rij_kro_gamma ! parameters for calculation of anoxic fraction of soil
+ real(r8) :: rij_kro_delta ! parameters for calculation of anoxic fraction of soil
+ real(r8) :: nfix_timeconst ! timescale for smoothing npp in N fixation term
+ real(r8) :: organic_max ! organic matter content (kg m-3) where soil is assumed to act like peat
+ real(r8) :: d_con_g21 ! O2 diffusivity constants in gas (cm2 s-1)
+ real(r8) :: d_con_g22 ! O2 diffusivity constants in gas (cm2 s-1)
+ real(r8) :: d_con_w21 ! O2 diffusivity constants in water (cm2 s-1)
+ real(r8) :: d_con_w22 ! O2 diffusivity constants in water (cm2 s-1)
+ real(r8) :: d_con_w23 ! O2 diffusivity constants in water (cm2 s-1)
+ real(r8) :: denit_resp_coef ! coefficient for maximum N denitrification rate based on respiration
+ real(r8) :: denit_resp_exp ! exponent for maximum N denitrification rate based on respiration
+ real(r8) :: denit_nitrate_coef ! coefficient for maximum N denitrification rate based on nitrate concentration
+ real(r8) :: denit_nitrate_exp ! exponent for maximum N denitrification rate based on nitrate concentration
+ real(r8) :: k_nitr_max ! maximum N nitrification rate (day-1)
+ real(r8) :: Q10 ! respiration rate increments when temperature rising 10 degree C
+ real(r8) :: froz_q10 ! respiration rate increments when temperature rising 10 degree C for frozen soil
+ real(r8) :: tau_l1 ! baseline turnover rate of metabolic litter from Century (year-1)
+ real(r8) :: tau_l2_l3 ! baseline turnover rate of cellulose litter and lignin litter from Century (year-1)
+ real(r8) :: tau_s1 ! baseline turnover rate of active soil organic matter from Century (year-1)
+ real(r8) :: tau_s2 ! baseline turnover rate of slow soil organic matter from Century (year-1)
+ real(r8) :: tau_s3 ! baseline turnover rate of passive soil organic matter from Century (year-1)
+ real(r8) :: tau_cwd ! baseline turnover rate of CWD (year-1)
+ real(r8) :: lwtop ! live wood turnover proportion
+
+ real(r8) :: som_adv_flux ! the advection term in soil organic matter mixing
+ real(r8) :: som_diffus ! the diffusion term in soil organic matter mixing
+ real(r8) :: cryoturb_diffusion_k ! the cryoturbation diffusive constant cryoturbation to the active layer thickness (m2 s-1)
+ real(r8) :: max_altdepth_cryoturbation ! maximum active layer thickness for cryoturbation to occur (m)
+ real(r8) :: max_depth_cryoturb ! the maximum depth of cryoturbation (m)
+
+ real(r8) :: br ! basal maintenance respiration rate for aboveground biomass (gC gN-1 s-1)
+ real(r8) :: br_root ! basal maintenance respiration rate for belowground biomass (gC gN-1 s-1)
+ real(r8) :: fstor2tran ! fraction of storage to transfer pool at each onset event
+ real(r8) :: ndays_on ! number of days to complete leaf onset
+ real(r8) :: ndays_off ! number of days to complete leaf offset
+ real(r8) :: crit_dayl ! critical day length for senescence (s)
+ real(r8) :: crit_onset_fdd ! critical number of freezing days to begin gdd accumulation
+ real(r8) :: crit_onset_swi ! critical number of days exceeding soil water potential threshold to initiate onset
+ real(r8) :: crit_offset_fdd ! critical number of freezing days to initiate offset
+ real(r8) :: crit_offset_swi ! critical number of days below soil water potential threshold to initiate offset
+ real(r8) :: soilpsi_on ! critical soil water potential threshold for onset
+ real(r8) :: soilpsi_off ! critical soil water potential threshold for offset
+
+ real(r8) :: occur_hi_gdp_tree ! fire occurance for high GDP areas that are tree dominated (fraction)
+ real(r8) :: lfuel ! lower threshold of fuel mass (gC/m2) for ignition, Li et al.(2014)
+ real(r8) :: ufuel ! upper threshold of fuel mass (gC/m2) for ignition, Li et al.(2014)
+ real(r8) :: cropfire_a1 ! a1 parameter for cropland fire in (Li et. al., 2014) (1/hr)
+ real(r8) :: borealat ! Latitude bound for boreal peat fires
+ real(r8) :: troplat ! Latitude bound for tropical
+ real(r8) :: non_boreal_peatfire_c ! c parameter for non-boreal peatland fire in Li et. al. (2013) (1/hr)
+ real(r8) :: boreal_peatfire_c ! c parameter for boreal peatland fire in Li et. al. (2013) (/hr)
+ real(r8) :: rh_low ! parameter for lower relative humidity on fire (%)
+ real(r8) :: rh_hgh ! parameter for higher relative humidity on fire (%)
+ real(r8) :: bt_min ! minimum water stress factor
+ real(r8) :: bt_max ! maximum water stress factor
+ real(r8) :: pot_hmn_ign_counts_alpha ! Potential human ignition counts (alpha in Li et. al. 2012) (1/person/month)
+ real(r8) :: g0_fire ! constant for fire spread estimates
+
+ real(r8) :: sf ! soluble fraction of mineral N (unitless)
+ real(r8) :: sf_no3 ! soluble fraction of NO3 (unitless)
+
+!----------------------------------- END BGC constants -----------------
+
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_BGCTimeInvariants
+ PUBLIC :: deallocate_BGCTimeInvariants
+ PUBLIC :: READ_BGCTimeInvariants
+ PUBLIC :: WRITE_BGCTimeInvariants
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_BGCTimeInvariants ()
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: nl_soil, ndecomp_transitions, ndecomp_pools, spval_i4, spval
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+ ! bgc variables
+ allocate (donor_pool (ndecomp_transitions)) ; donor_pool (:) = spval_i4
+ allocate (receiver_pool (ndecomp_transitions)) ; receiver_pool (:) = spval_i4
+ allocate (floating_cn_ratio (ndecomp_pools)) ; floating_cn_ratio (:) = .false.
+ allocate (initial_cn_ratio (ndecomp_pools)) ; initial_cn_ratio (:) = spval
+ allocate (rf_decomp (nl_soil,ndecomp_transitions,numpatch)) ; rf_decomp (:,:,:) = spval
+ allocate (pathfrac_decomp (nl_soil,ndecomp_transitions,numpatch)) ; pathfrac_decomp(:,:,:) = spval
+ allocate (is_cwd (ndecomp_pools)) ; is_cwd (:) = .false. ! True => is a coarse woody debris pool
+ allocate (is_litter (ndecomp_pools)) ; is_litter (:) = .false. ! True => is a litter pool
+ allocate (is_soil (ndecomp_pools)) ; is_soil (:) = .false. ! True => is a soil pool
+ allocate (gdp_lf (numpatch)) ; gdp_lf (:) = spval
+ allocate (abm_lf (numpatch)) ; abm_lf (:) = spval
+ allocate (peatf_lf (numpatch)) ; peatf_lf (:) = spval
+ allocate (cmb_cmplt_fact (2)) ; cmb_cmplt_fact (:) = spval
+ allocate (rice2pdt (numpatch)) ; rice2pdt (:) = spval_i4
+
+ ! END bgc variables
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE allocate_BGCTimeInvariants
+
+ !---------------------------------------
+ SUBROUTINE READ_BGCTimeInvariants (file_restart)
+
+ !=======================================================================
+ ! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+ !=======================================================================
+
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFVector
+ USE MOD_NetCDFSerial
+#ifdef RangeCheck
+ USE MOD_RangeCheck
+#endif
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+! bgc constants
+ CALL ncio_read_bcast_serial (file_restart, 'donor_pool ', donor_pool )
+ CALL ncio_read_bcast_serial (file_restart, 'receiver_pool ', receiver_pool )
+ CALL ncio_read_bcast_serial (file_restart, 'floating_cn_ratio', floating_cn_ratio)
+ CALL ncio_read_bcast_serial (file_restart, 'initial_cn_ratio' , initial_cn_ratio)
+ CALL ncio_read_vector (file_restart, 'rf_decomp ', nl_soil,ndecomp_transitions,landpatch, rf_decomp )
+ CALL ncio_read_vector (file_restart, 'pathfrac_decomp ', nl_soil,ndecomp_transitions,landpatch,pathfrac_decomp )
+
+ CALL ncio_read_bcast_serial (file_restart, 'i_met_lit ', i_met_lit )
+ CALL ncio_read_bcast_serial (file_restart, 'i_cel_lit ', i_cel_lit )
+ CALL ncio_read_bcast_serial (file_restart, 'i_lig_lit ', i_lig_lit )
+ CALL ncio_read_bcast_serial (file_restart, 'i_cwd ', i_cwd )
+ CALL ncio_read_bcast_serial (file_restart, 'i_soil1 ', i_soil1 )
+ CALL ncio_read_bcast_serial (file_restart, 'i_soil2 ', i_soil2 )
+ CALL ncio_read_bcast_serial (file_restart, 'i_soil3 ', i_soil3 )
+ CALL ncio_read_bcast_serial (file_restart, 'i_atm ', i_atm )
+ CALL ncio_read_bcast_serial (file_restart, 'is_cwd ', is_cwd )
+ CALL ncio_read_bcast_serial (file_restart, 'is_litter ', is_litter )
+ CALL ncio_read_bcast_serial (file_restart, 'is_soil ', is_soil )
+
+ ! CALL ncio_read_vector (file_restart, 'gdp_lf ', landpatch, gdp_lf )
+ ! CALL ncio_read_vector (file_restart, 'abm_lf ', landpatch, abm_lf )
+ ! CALL ncio_read_vector (file_restart, 'peatf_lf ', landpatch, peatf_lf )
+ CALL ncio_read_bcast_serial (file_restart, 'cmb_cmplt_fact ', cmb_cmplt_fact )
+ CALL ncio_read_vector (file_restart, 'rice2pdt ', landpatch, rice2pdt )
+
+ CALL ncio_read_bcast_serial (file_restart, 'nitrif_n2o_loss_frac', nitrif_n2o_loss_frac)
+ CALL ncio_read_bcast_serial (file_restart, 'dnp ', dnp )!
+ CALL ncio_read_bcast_serial (file_restart, 'bdnr ', bdnr )!
+ CALL ncio_read_bcast_serial (file_restart, 'compet_plant_no3 ', compet_plant_no3 )!
+ CALL ncio_read_bcast_serial (file_restart, 'compet_plant_nh4 ', compet_plant_nh4 )!
+ CALL ncio_read_bcast_serial (file_restart, 'compet_decomp_no3 ', compet_decomp_no3 )!
+ CALL ncio_read_bcast_serial (file_restart, 'compet_decomp_nh4 ', compet_decomp_nh4 )!
+ CALL ncio_read_bcast_serial (file_restart, 'compet_denit ', compet_denit )!
+ CALL ncio_read_bcast_serial (file_restart, 'compet_nit ', compet_nit )!
+ CALL ncio_read_bcast_serial (file_restart, 'surface_tension_water',surface_tension_water)
+ CALL ncio_read_bcast_serial (file_restart, 'rij_kro_a ', rij_kro_a )
+ CALL ncio_read_bcast_serial (file_restart, 'rij_kro_alpha ', rij_kro_alpha )
+ CALL ncio_read_bcast_serial (file_restart, 'rij_kro_beta ', rij_kro_beta )
+ CALL ncio_read_bcast_serial (file_restart, 'rij_kro_gamma ', rij_kro_gamma )
+ CALL ncio_read_bcast_serial (file_restart, 'rij_kro_delta ', rij_kro_delta )
+ CALL ncio_read_bcast_serial (file_restart, 'nfix_timeconst ', nfix_timeconst )
+ CALL ncio_read_bcast_serial (file_restart, 'organic_max ', organic_max )
+ CALL ncio_read_bcast_serial (file_restart, 'd_con_g21 ', d_con_g21 )
+ CALL ncio_read_bcast_serial (file_restart, 'd_con_g22 ', d_con_g22 )
+ CALL ncio_read_bcast_serial (file_restart, 'd_con_w21 ', d_con_w21 )
+ CALL ncio_read_bcast_serial (file_restart, 'd_con_w22 ', d_con_w22 )
+ CALL ncio_read_bcast_serial (file_restart, 'd_con_w23 ', d_con_w23 )
+ CALL ncio_read_bcast_serial (file_restart, 'denit_resp_coef ', denit_resp_coef )
+ CALL ncio_read_bcast_serial (file_restart, 'denit_resp_exp ', denit_resp_exp )
+ CALL ncio_read_bcast_serial (file_restart, 'denit_nitrate_coef ', denit_nitrate_coef )
+ CALL ncio_read_bcast_serial (file_restart, 'denit_nitrate_exp ', denit_nitrate_exp )!
+ CALL ncio_read_bcast_serial (file_restart, 'k_nitr_max ', k_nitr_max )!
+ CALL ncio_read_bcast_serial (file_restart, 'Q10 ', Q10 )!
+ CALL ncio_read_bcast_serial (file_restart, 'froz_q10 ', froz_q10 )!
+ CALL ncio_read_bcast_serial (file_restart, 'tau_l1 ', tau_l1 )!
+ CALL ncio_read_bcast_serial (file_restart, 'tau_l2_l3 ', tau_l2_l3 )!
+ CALL ncio_read_bcast_serial (file_restart, 'tau_s1 ', tau_s1 )!
+ CALL ncio_read_bcast_serial (file_restart, 'tau_s2 ', tau_s2 )!
+ CALL ncio_read_bcast_serial (file_restart, 'tau_s3 ', tau_s3 )!
+ CALL ncio_read_bcast_serial (file_restart, 'tau_cwd ', tau_cwd )
+ CALL ncio_read_bcast_serial (file_restart, 'lwtop ', lwtop )
+
+ CALL ncio_read_bcast_serial (file_restart, 'som_adv_flux ', som_adv_flux )
+ CALL ncio_read_bcast_serial (file_restart, 'som_diffus ', som_diffus )
+ CALL ncio_read_bcast_serial (file_restart, 'cryoturb_diffusion_k', cryoturb_diffusion_k)
+ CALL ncio_read_bcast_serial (file_restart, 'max_altdepth_cryoturbation', max_altdepth_cryoturbation)
+ CALL ncio_read_bcast_serial (file_restart, 'max_depth_cryoturb ', max_depth_cryoturb )
+
+ CALL ncio_read_bcast_serial (file_restart, 'am ', am )
+ CALL ncio_read_bcast_serial (file_restart, 'br ', br )
+ CALL ncio_read_bcast_serial (file_restart, 'br_root ', br_root )
+ CALL ncio_read_bcast_serial (file_restart, 'fstor2tran ', fstor2tran )
+ CALL ncio_read_bcast_serial (file_restart, 'ndays_on ', ndays_on )
+ CALL ncio_read_bcast_serial (file_restart, 'ndays_off ', ndays_off )
+ CALL ncio_read_bcast_serial (file_restart, 'crit_dayl ', crit_dayl )
+ CALL ncio_read_bcast_serial (file_restart, 'crit_onset_fdd ', crit_onset_fdd )
+ CALL ncio_read_bcast_serial (file_restart, 'crit_onset_swi ', crit_onset_swi )
+ CALL ncio_read_bcast_serial (file_restart, 'crit_offset_fdd ', crit_offset_fdd )
+ CALL ncio_read_bcast_serial (file_restart, 'crit_offset_swi ', crit_offset_swi )
+ CALL ncio_read_bcast_serial (file_restart, 'soilpsi_on ', soilpsi_on )
+ CALL ncio_read_bcast_serial (file_restart, 'soilpsi_off ', soilpsi_off )
+
+ CALL ncio_read_bcast_serial (file_restart, 'occur_hi_gdp_tree ', occur_hi_gdp_tree )
+ CALL ncio_read_bcast_serial (file_restart, 'lfuel ', lfuel )
+ CALL ncio_read_bcast_serial (file_restart, 'ufuel ', ufuel )
+ CALL ncio_read_bcast_serial (file_restart, 'cropfire_a1 ', cropfire_a1 )
+ CALL ncio_read_bcast_serial (file_restart, 'borealat ', borealat )
+ CALL ncio_read_bcast_serial (file_restart, 'troplat ', troplat )
+ CALL ncio_read_bcast_serial (file_restart, 'non_boreal_peatfire_c', non_boreal_peatfire_c)
+ CALL ncio_read_bcast_serial (file_restart, 'boreal_peatfire_c ', boreal_peatfire_c )
+ CALL ncio_read_bcast_serial (file_restart, 'rh_low ', rh_low )
+ CALL ncio_read_bcast_serial (file_restart, 'rh_hgh ', rh_hgh )
+ CALL ncio_read_bcast_serial (file_restart, 'bt_min ', bt_min )
+ CALL ncio_read_bcast_serial (file_restart, 'bt_max ', bt_max )
+ CALL ncio_read_bcast_serial (file_restart, 'pot_hmn_ign_counts_alpha', pot_hmn_ign_counts_alpha)
+ CALL ncio_read_bcast_serial (file_restart, 'g0_fire', g0_fire)
+
+ CALL ncio_read_bcast_serial (file_restart, 'sf', sf)
+ CALL ncio_read_bcast_serial (file_restart, 'sf_no3', sf_no3)
+
+#ifdef RangeCheck
+ CALL check_BGCTimeInvariants ()
+#endif
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE READ_BGCTimeInvariants
+
+ !---------------------------------------
+ SUBROUTINE WRITE_BGCTimeInvariants (file_restart)
+
+ !=======================================================================
+ ! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+ !=======================================================================
+
+ USE MOD_Namelist, only: DEF_REST_CompressLevel
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFVector
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ ! Local Variables
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ CALL ncio_create_file_vector (file_restart, landpatch)
+
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil', nl_soil)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'ndecomp_transitions',ndecomp_transitions)
+
+ CALL ncio_write_vector (file_restart, 'rf_decomp ', 'soil' , nl_soil , &
+ 'ndecomp_transitions', ndecomp_transitions,'patch', landpatch, rf_decomp , compress)
+ CALL ncio_write_vector (file_restart, 'pathfrac_decomp', 'soil' , nl_soil , &
+ 'ndecomp_transitions', ndecomp_transitions,'patch', landpatch, pathfrac_decomp, compress)
+ ! CALL ncio_write_vector (file_restart, 'gdp_lf ', 'patch', landpatch, gdp_lf , compress)
+ ! CALL ncio_write_vector (file_restart, 'abm_lf ', 'patch', landpatch, abm_lf , compress)
+ ! CALL ncio_write_vector (file_restart, 'peatf_lf ', 'patch', landpatch, peatf_lf , compress)
+ CALL ncio_write_vector (file_restart, 'rice2pdt ', 'patch', landpatch, rice2pdt , compress)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+
+#if (!defined(VectorInOneFileS) && !defined(VectorInOneFileP))
+ CALL ncio_create_file (file_restart)
+#endif
+ CALL ncio_define_dimension(file_restart, 'ndecomp_transitions',ndecomp_transitions)
+ CALL ncio_define_dimension(file_restart, 'ndecomp_pools' ,ndecomp_pools)
+ CALL ncio_define_dimension(file_restart, 'nlitter_fire' ,2 )
+
+ ! bgc constants
+ CALL ncio_write_serial (file_restart, 'donor_pool ' , donor_pool , 'ndecomp_transitions')
+ CALL ncio_write_serial (file_restart, 'receiver_pool ' , receiver_pool , 'ndecomp_transitions')
+ CALL ncio_write_serial (file_restart, 'floating_cn_ratio', floating_cn_ratio, 'ndecomp_pools')
+ CALL ncio_write_serial (file_restart, 'initial_cn_ratio' , initial_cn_ratio , 'ndecomp_pools')
+ CALL ncio_write_serial (file_restart, 'is_cwd ' , is_cwd , 'ndecomp_pools')
+ CALL ncio_write_serial (file_restart, 'is_litter ' , is_litter , 'ndecomp_pools')
+ CALL ncio_write_serial (file_restart, 'is_soil ' , is_soil , 'ndecomp_pools')
+ CALL ncio_write_serial (file_restart, 'cmb_cmplt_fact ' , cmb_cmplt_fact , 'nlitter_fire' )
+
+ CALL ncio_write_serial (file_restart, 'i_met_lit ', i_met_lit )
+ CALL ncio_write_serial (file_restart, 'i_cel_lit ', i_cel_lit )
+ CALL ncio_write_serial (file_restart, 'i_lig_lit ', i_lig_lit )
+ CALL ncio_write_serial (file_restart, 'i_cwd ', i_cwd )
+ CALL ncio_write_serial (file_restart, 'i_soil1 ', i_soil1 )
+ CALL ncio_write_serial (file_restart, 'i_soil2 ', i_soil2 )
+ CALL ncio_write_serial (file_restart, 'i_soil3 ', i_soil3 )
+ CALL ncio_write_serial (file_restart, 'i_atm ', i_atm )
+
+
+ CALL ncio_write_serial (file_restart, 'nitrif_n2o_loss_frac', nitrif_n2o_loss_frac)
+ CALL ncio_write_serial (file_restart, 'dnp ', dnp )!
+ CALL ncio_write_serial (file_restart, 'bdnr ', bdnr )!
+ CALL ncio_write_serial (file_restart, 'compet_plant_no3 ', compet_plant_no3 )!
+ CALL ncio_write_serial (file_restart, 'compet_plant_nh4 ', compet_plant_nh4 )!
+ CALL ncio_write_serial (file_restart, 'compet_decomp_no3 ', compet_decomp_no3 )!
+ CALL ncio_write_serial (file_restart, 'compet_decomp_nh4 ', compet_decomp_nh4 )!
+ CALL ncio_write_serial (file_restart, 'compet_denit ', compet_denit )!
+ CALL ncio_write_serial (file_restart, 'compet_nit ', compet_nit )!
+ CALL ncio_write_serial (file_restart, 'surface_tension_water',surface_tension_water)
+ CALL ncio_write_serial (file_restart, 'rij_kro_a ', rij_kro_a )
+ CALL ncio_write_serial (file_restart, 'rij_kro_alpha ', rij_kro_alpha )
+ CALL ncio_write_serial (file_restart, 'rij_kro_beta ', rij_kro_beta )
+ CALL ncio_write_serial (file_restart, 'rij_kro_gamma ', rij_kro_gamma )
+ CALL ncio_write_serial (file_restart, 'rij_kro_delta ', rij_kro_delta )
+ CALL ncio_write_serial (file_restart, 'nfix_timeconst ', nfix_timeconst )
+ CALL ncio_write_serial (file_restart, 'organic_max ', organic_max )
+ CALL ncio_write_serial (file_restart, 'd_con_g21 ', d_con_g21 )
+ CALL ncio_write_serial (file_restart, 'd_con_g22 ', d_con_g22 )
+ CALL ncio_write_serial (file_restart, 'd_con_w21 ', d_con_w21 )
+ CALL ncio_write_serial (file_restart, 'd_con_w22 ', d_con_w22 )
+ CALL ncio_write_serial (file_restart, 'd_con_w23 ', d_con_w23 )
+ CALL ncio_write_serial (file_restart, 'denit_resp_coef ', denit_resp_coef )
+ CALL ncio_write_serial (file_restart, 'denit_resp_exp ', denit_resp_exp )
+ CALL ncio_write_serial (file_restart, 'denit_nitrate_coef ', denit_nitrate_coef )
+ CALL ncio_write_serial (file_restart, 'denit_nitrate_exp ', denit_nitrate_exp )!
+ CALL ncio_write_serial (file_restart, 'k_nitr_max ', k_nitr_max )!
+ CALL ncio_write_serial (file_restart, 'Q10 ', Q10 )!
+ CALL ncio_write_serial (file_restart, 'froz_q10 ', froz_q10 )!
+ CALL ncio_write_serial (file_restart, 'tau_l1 ', tau_l1 )!
+ CALL ncio_write_serial (file_restart, 'tau_l2_l3 ', tau_l2_l3 )!
+ CALL ncio_write_serial (file_restart, 'tau_s1 ', tau_s1 )!
+ CALL ncio_write_serial (file_restart, 'tau_s2 ', tau_s2 )!
+ CALL ncio_write_serial (file_restart, 'tau_s3 ', tau_s3 )!
+ CALL ncio_write_serial (file_restart, 'tau_cwd ', tau_cwd )
+ CALL ncio_write_serial (file_restart, 'lwtop ', lwtop )
+
+ CALL ncio_write_serial (file_restart, 'som_adv_flux ', som_adv_flux )
+ CALL ncio_write_serial (file_restart, 'som_diffus ', som_diffus )
+ CALL ncio_write_serial (file_restart, 'cryoturb_diffusion_k', cryoturb_diffusion_k)
+ CALL ncio_write_serial (file_restart, 'max_altdepth_cryoturbation', max_altdepth_cryoturbation)
+ CALL ncio_write_serial (file_restart, 'max_depth_cryoturb ', max_depth_cryoturb )
+
+ CALL ncio_write_serial (file_restart, 'am ', am )
+ CALL ncio_write_serial (file_restart, 'br ', br )
+ CALL ncio_write_serial (file_restart, 'br_root ', br_root )
+ CALL ncio_write_serial (file_restart, 'fstor2tran ', fstor2tran )
+ CALL ncio_write_serial (file_restart, 'ndays_on ', ndays_on )
+ CALL ncio_write_serial (file_restart, 'ndays_off ', ndays_off )
+ CALL ncio_write_serial (file_restart, 'crit_dayl ', crit_dayl )
+ CALL ncio_write_serial (file_restart, 'crit_onset_fdd ', crit_onset_fdd )
+ CALL ncio_write_serial (file_restart, 'crit_onset_swi ', crit_onset_swi )
+ CALL ncio_write_serial (file_restart, 'crit_offset_fdd ', crit_offset_fdd )
+ CALL ncio_write_serial (file_restart, 'crit_offset_swi ', crit_offset_swi )
+ CALL ncio_write_serial (file_restart, 'soilpsi_on ', soilpsi_on )
+ CALL ncio_write_serial (file_restart, 'soilpsi_off ', soilpsi_off )
+
+ CALL ncio_write_serial (file_restart, 'occur_hi_gdp_tree ', occur_hi_gdp_tree )
+ CALL ncio_write_serial (file_restart, 'lfuel ', lfuel )
+ CALL ncio_write_serial (file_restart, 'ufuel ', ufuel )
+ CALL ncio_write_serial (file_restart, 'cropfire_a1 ', cropfire_a1 )
+ CALL ncio_write_serial (file_restart, 'borealat ', borealat )
+ CALL ncio_write_serial (file_restart, 'troplat ', troplat )
+ CALL ncio_write_serial (file_restart, 'non_boreal_peatfire_c', non_boreal_peatfire_c)
+ CALL ncio_write_serial (file_restart, 'boreal_peatfire_c ', boreal_peatfire_c )
+ CALL ncio_write_serial (file_restart, 'rh_low ', rh_low )
+ CALL ncio_write_serial (file_restart, 'rh_hgh ', rh_hgh )
+ CALL ncio_write_serial (file_restart, 'bt_min ', bt_min )
+ CALL ncio_write_serial (file_restart, 'bt_max ', bt_max )
+ CALL ncio_write_serial (file_restart, 'pot_hmn_ign_counts_alpha', pot_hmn_ign_counts_alpha)
+ CALL ncio_write_serial (file_restart, 'g0_fire', g0_fire)
+
+ CALL ncio_write_serial (file_restart, 'sf', sf)
+ CALL ncio_write_serial (file_restart, 'sf_no3', sf_no3)
+
+ ENDIF
+
+ END SUBROUTINE WRITE_BGCTimeInvariants
+
+ SUBROUTINE deallocate_BGCTimeInvariants ()
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+ ! --------------------------------------------------
+ ! Deallocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ ! bgc variables
+ deallocate (donor_pool )
+ deallocate (receiver_pool )
+ deallocate (floating_cn_ratio)
+ deallocate (initial_cn_ratio )
+ deallocate (rf_decomp )
+ deallocate (pathfrac_decomp)
+ deallocate (is_cwd )
+ deallocate (is_litter )
+ deallocate (is_soil )
+ deallocate (gdp_lf )
+ deallocate (abm_lf )
+ deallocate (peatf_lf )
+ deallocate (cmb_cmplt_fact )
+ deallocate (rice2pdt )
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_BGCTimeInvariants
+
+#ifdef RangeCheck
+ !---------------------------------------
+ SUBROUTINE check_BGCTimeInvariants ()
+
+ USE MOD_SPMD_Task
+ USE MOD_RangeCheck
+
+ IMPLICIT NONE
+
+ CALL check_vector_data ('rf_decomp ', rf_decomp )
+ CALL check_vector_data ('pathfrac_decomp', pathfrac_decomp)
+ CALL check_vector_data ('gdp_lf ', gdp_lf )
+ CALL check_vector_data ('abm_lf ', abm_lf )
+ CALL check_vector_data ('peatf_lf ', peatf_lf )
+ CALL check_vector_data ('rice2pdt ', rice2pdt )
+
+ END SUBROUTINE check_BGCTimeInvariants
+#endif
+
+#endif
+END MODULE MOD_BGC_Vars_TimeInvariants
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_TimeVariables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_TimeVariables.F90
new file mode 100644
index 0000000000..ec3ee02169
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Vars_TimeVariables.F90
@@ -0,0 +1,1543 @@
+#include
+
+MODULE MOD_BGC_Vars_TimeVariables
+#ifdef BGC
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! Define, allocate, and deallocate biogeochemical state variables at patch level.
+! Read and write biogeochemical state variables at patch level from/to restart files.
+
+! !ORIGINAL:
+! Xingjie Lu, 2022, created the original version
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix
+ USE MOD_TimeManager
+ IMPLICIT NONE
+ SAVE
+!------------------------- BGC variables -------------------------------
+ real(r8), allocatable :: decomp_cpools_vr (:,:,:) ! vertical resolved: soil decomposition (litter, cwd, soil organic matter) carbon pools (gC m-3)
+ real(r8), allocatable :: decomp_cpools (:,:) ! soil decomposition (litter, cwd, soil) carbon pools (gC m-2)
+ real(r8), allocatable :: decomp_cpools_vr_Cap (:,:,:) ! vertical resolved: soil decomposition (litter, cwd, soil organic matter) carbon Capacity (gC m-3)
+ real(r8), allocatable :: decomp_k (:,:,:) ! soil decomposition rate (s-1)
+ real(r8), allocatable :: ctrunc_vr (:,:) ! currently not used
+ real(r8), allocatable :: ctrunc_veg (:) ! currently not used
+ real(r8), allocatable :: ctrunc_soil (:) ! currently not used
+
+ real(r8), allocatable :: t_scalar (:,:) ! vertical resolved: soil decomposition temperature scalars
+ real(r8), allocatable :: w_scalar (:,:) ! vertical resolved: soil decomposition water scalars
+ real(r8), allocatable :: o_scalar (:,:) ! vertical resolved: soil decomposition oxygen scalars
+ real(r8), allocatable :: depth_scalar (:,:) ! vertical resolved: soil decomposition depth scalars
+
+!Soil CN diffusion and advection
+ real(r8), allocatable :: som_adv_coef (:,:) ! vertical resolved: soil organic matter advective flux (m2 s-1)
+ real(r8), allocatable :: som_diffus_coef (:,:) ! vertical resolved: soil organic matter diffusion flux (m2 s-1)
+
+!Active Layer
+ real(r8), allocatable :: altmax (:) ! maximum annual depth of thaw (m)
+ real(r8), allocatable :: altmax_lastyear (:) ! previous year maximum annual depth of thaw (m)
+ integer , allocatable :: altmax_lastyear_indx (:) ! previous year maximum annual soil layer of thaw
+
+ real(r8), allocatable :: totlitc (:) ! carbon balance diagnostics: total column litter carbon (gC m-2)
+ real(r8), allocatable :: totvegc (:) ! carbon balance diagnostics: total column vegetation carbon (gC m-2)
+ real(r8), allocatable :: totsomc (:) ! carbon balance diagnostics: total column soil organic matter carbon (gC m-2)
+ real(r8), allocatable :: totcwdc (:) ! carbon balance diagnostics: total column coarse woody debris carbon (gC m-2)
+ real(r8), allocatable :: totcolc (:) ! carbon balance diagnostics: total column carbon (veg, soil, litter, et al) (gC m-2)
+ real(r8), allocatable :: col_begcb (:) ! carbon balance diagnostics: column carbon, begin of time step (gC m-2)
+ real(r8), allocatable :: col_endcb (:) ! carbon balance diagnostics: column carbon, END of time step (gC m-2)
+ real(r8), allocatable :: col_vegbegcb (:) ! carbon balance diagnostics: column vegetation carbon, begin of time step (gC m-2)
+ real(r8), allocatable :: col_vegendcb (:) ! carbon balance diagnostics: column vegetation carbon, end of time step (gC m-2)
+ real(r8), allocatable :: col_soilbegcb (:) ! carbon balance diagnostics: column soil carbon, begin of time step (gC m-2)
+ real(r8), allocatable :: col_soilendcb (:) ! carbon balance diagnostics: column soil carbon, end of time step (gC m-2)
+
+ real(r8), allocatable :: totlitn (:) ! nitrogen balance diagnostics: total column litter nitrogen (gN m-2)
+ real(r8), allocatable :: totvegn (:) ! nitrogen balance diagnostics: total column vegetation nitrogen (gN m-2)
+ real(r8), allocatable :: totsomn (:) ! nitrogen balance diagnostics: total column soil organic matter nitrogen (gN m-2)
+ real(r8), allocatable :: totcwdn (:) ! nitrogen balance diagnostics: total column coarse woody debris nitrogen (gN m-2)
+ real(r8), allocatable :: totcoln (:) ! nitrogen balance diagnostics: total column nitrogen (veg, soil, litter, et al) (gN m-2)
+ real(r8), allocatable :: col_begnb (:) ! nitrogen balance diagnostics: column nitrogen, begin of time step (gN m-2)
+ real(r8), allocatable :: col_endnb (:) ! nitrogen balance diagnostics: column nitrogen, end of time step (gN m-2)
+ real(r8), allocatable :: col_vegbegnb (:) ! nitrogen balance diagnostics: column vegetation nitrogen, begin of time step (gN m-2)
+ real(r8), allocatable :: col_vegendnb (:) ! nitrogen balance diagnostics: column vegetation nitrogen, end of time step (gN m-2)
+ real(r8), allocatable :: col_soilbegnb (:) ! nitrogen balance diagnostics: column soil organic nitrogen, begin of time step (gN m-2)
+ real(r8), allocatable :: col_soilendnb (:) ! nitrogen balance diagnostics: column soil organic nitrogen, end of time step (gN m-2)
+ real(r8), allocatable :: col_sminnbegnb (:) ! nitrogen balance diagnostics: column soil mineral nitrogen, begin of time step (gN m-2)
+ real(r8), allocatable :: col_sminnendnb (:) ! nitrogen balance diagnostics: column soil mineral nitrogen, end of time step (gN m-2)
+
+ real(r8), allocatable :: leafc (:) ! leaf display C (gC m-2)
+ real(r8), allocatable :: leafc_storage (:) ! leaf storage C (gC m-2)
+ real(r8), allocatable :: leafc_xfer (:) ! leaf transfer C (gC m-2)
+ real(r8), allocatable :: frootc (:) ! fine root display C (gC m-2)
+ real(r8), allocatable :: frootc_storage (:) ! fine root storage C (gC m-2)
+ real(r8), allocatable :: frootc_xfer (:) ! fine root transfer C (gC m-2)
+ real(r8), allocatable :: livestemc (:) ! live stem display C (gC m-2)
+ real(r8), allocatable :: livestemc_storage (:) ! live stem storage C (gC m-2)
+ real(r8), allocatable :: livestemc_xfer (:) ! live stem transfer C (gC m-2)
+ real(r8), allocatable :: deadstemc (:) ! dead stem display C (gC m-2)
+ real(r8), allocatable :: deadstemc_storage (:) ! dead stem storage C (gC m-2)
+ real(r8), allocatable :: deadstemc_xfer (:) ! dead stem transfer C (gC m-2)
+ real(r8), allocatable :: livecrootc (:) ! live coarse root display C (gC m-2)
+ real(r8), allocatable :: livecrootc_storage (:) ! live coarse root storage C (gC m-2)
+ real(r8), allocatable :: livecrootc_xfer (:) ! live coarse root transfer C (gC m-2)
+ real(r8), allocatable :: deadcrootc (:) ! dead coarse root display C (gC m-2)
+ real(r8), allocatable :: deadcrootc_storage (:) ! dead coarse root storage C (gC m-2)
+ real(r8), allocatable :: deadcrootc_xfer (:) ! dead coarse root transfer C (gC m-2)
+ real(r8), allocatable :: grainc (:) ! grain display C (gC m-2)
+ real(r8), allocatable :: grainc_storage (:) ! grain storage C (gC m-2)
+ real(r8), allocatable :: grainc_xfer (:) ! grain transfer C (gC m-2)
+ real(r8), allocatable :: xsmrpool (:) ! maintenance respiration storage C (gC m-2)
+ real(r8), allocatable :: downreg (:) ! fractional reduction in GPP due to N limitation
+ real(r8), allocatable :: cropprod1c (:) ! product C (gC m-2)
+ real(r8), allocatable :: cropseedc_deficit (:) ! crop seed deficit C (gC m-2)
+
+ real(r8), allocatable :: leafn (:) ! leaf display N (gN m-2)
+ real(r8), allocatable :: leafn_storage (:) ! leaf storage N (gN m-2)
+ real(r8), allocatable :: leafn_xfer (:) ! leaf transfer N (gN m-2)
+ real(r8), allocatable :: frootn (:) ! fine root display N (gN m-2)d
+ real(r8), allocatable :: frootn_storage (:) ! fine root storage N (gN m-2)d
+ real(r8), allocatable :: frootn_xfer (:) ! fine root transfer N (gN m-2)d
+ real(r8), allocatable :: livestemn (:) ! live stem display N (gN m-2)d
+ real(r8), allocatable :: livestemn_storage (:) ! live stem storage N (gN m-2)d
+ real(r8), allocatable :: livestemn_xfer (:) ! live stem transfer N (gN m-2)d
+ real(r8), allocatable :: deadstemn (:) ! dead stem display N (gN m-2)d
+ real(r8), allocatable :: deadstemn_storage (:) ! dead stem storage N (gN m-2)d
+ real(r8), allocatable :: deadstemn_xfer (:) ! dead stem transfer N (gN m-2)d
+ real(r8), allocatable :: livecrootn (:) ! live coarse root display N (gN m-2)
+ real(r8), allocatable :: livecrootn_storage (:) ! live coarse root storage N (gN m-2)
+ real(r8), allocatable :: livecrootn_xfer (:) ! live coarse root transfer N (gN m-2)
+ real(r8), allocatable :: deadcrootn (:) ! dead coarse root display N (gN m-2)
+ real(r8), allocatable :: deadcrootn_storage (:) ! dead coarse root storage N (gN m-2)
+ real(r8), allocatable :: deadcrootn_xfer (:) ! dead coarse root transfer N (gN m-2)
+ real(r8), allocatable :: grainn (:) ! grain display N (gN m-2)
+ real(r8), allocatable :: grainn_storage (:) ! grain storage N (gN m-2)
+ real(r8), allocatable :: grainn_xfer (:) ! grain transfer N (gN m-2)
+ real(r8), allocatable :: retransn (:) ! retranslocated N (gN m-2)
+
+ real(r8), allocatable :: leafcCap (:) ! leaf display C capacity (gC m-2)
+ real(r8), allocatable :: leafc_storageCap (:) ! leaf storage C capacity (gC m-2)
+ real(r8), allocatable :: leafc_xferCap (:) ! leaf transfer C capacity (gC m-2)
+ real(r8), allocatable :: frootcCap (:) ! fine root display C capacity (gC m-2)
+ real(r8), allocatable :: frootc_storageCap (:) ! fine root storage C capacity (gC m-2)
+ real(r8), allocatable :: frootc_xferCap (:) ! fine root transfer C capacity (gC m-2)
+ real(r8), allocatable :: livestemcCap (:) ! live stem display C capacity (gC m-2)
+ real(r8), allocatable :: livestemc_storageCap (:) ! live stem storage C capacity (gC m-2)
+ real(r8), allocatable :: livestemc_xferCap (:) ! live stem transfer C capacity (gC m-2)
+ real(r8), allocatable :: deadstemcCap (:) ! dead stem display C capacity (gC m-2)
+ real(r8), allocatable :: deadstemc_storageCap (:) ! dead stem storage C capacity (gC m-2)
+ real(r8), allocatable :: deadstemc_xferCap (:) ! dead stem transfer C capacity (gC m-2)
+ real(r8), allocatable :: livecrootcCap (:) ! live coarse root display C capacity (gC m-2)
+ real(r8), allocatable :: livecrootc_storageCap (:) ! live coarse root storage C capacity (gC m-2)
+ real(r8), allocatable :: livecrootc_xferCap (:) ! live coarse root transfer C capacity (gC m-2)
+ real(r8), allocatable :: deadcrootcCap (:) ! dead coarse root display C capacity (gC m-2)
+ real(r8), allocatable :: deadcrootc_storageCap (:) ! dead coarse root storage C capacity (gC m-2)
+ real(r8), allocatable :: deadcrootc_xferCap (:) ! dead coarse root transfer C capacity (gC m-2)
+
+ real(r8), allocatable :: leafnCap (:) ! leaf display N capacity (gN m-2)
+ real(r8), allocatable :: leafn_storageCap (:) ! leaf storage N capacity (gN m-2)
+ real(r8), allocatable :: leafn_xferCap (:) ! leaf transfer N capacity (gN m-2)
+ real(r8), allocatable :: frootnCap (:) ! fine root display N capacity (gN m-2)
+ real(r8), allocatable :: frootn_storageCap (:) ! fine root storage N capacity (gN m-2)
+ real(r8), allocatable :: frootn_xferCap (:) ! fine root transfer N capacity (gN m-2)
+ real(r8), allocatable :: livestemnCap (:) ! live stem display N capacity (gN m-2)
+ real(r8), allocatable :: livestemn_storageCap (:) ! live stem storage N capacity (gN m-2)
+ real(r8), allocatable :: livestemn_xferCap (:) ! live stem transfer N capacity (gN m-2)
+ real(r8), allocatable :: deadstemnCap (:) ! dead stem display N capacity (gN m-2)
+ real(r8), allocatable :: deadstemn_storageCap (:) ! dead stem storage N capacity (gN m-2)
+ real(r8), allocatable :: deadstemn_xferCap (:) ! dead stem transfer N capacity (gN m-2)
+ real(r8), allocatable :: livecrootnCap (:) ! live coarse root display N capacity (gN m-2)
+ real(r8), allocatable :: livecrootn_storageCap (:) ! live coarse root storage N capacity (gN m-2)
+ real(r8), allocatable :: livecrootn_xferCap (:) ! live coarse root transfer N capacity (gN m-2)
+ real(r8), allocatable :: deadcrootnCap (:) ! dead coarse root display N capacity (gN m-2)
+ real(r8), allocatable :: deadcrootn_storageCap (:) ! dead coarse root storage N capacity (gN m-2)
+ real(r8), allocatable :: deadcrootn_xferCap (:) ! dead coarse root transfer N capacity (gN m-2)
+
+ real(r8), allocatable :: decomp_npools_vr (:,:,:) ! vertical resolved: soil decomposition (litter, cwd, soil) nitrogen (gN m-3)
+ real(r8), allocatable :: decomp_npools (:,:) ! soil decomposition (litter, cwd, soil) nitrogen (gN m-2)
+ real(r8), allocatable :: decomp_npools_vr_Cap (:,:,:) ! vertical resolved: soil decomposition (litter, cwd, soil organic matter) carbon Capacity (gC m-3)
+ real(r8), allocatable :: totsoiln_vr (:,:) ! vertical resolved: total soil nitrogen (%: gN/gSoil*100)
+ real(r8), allocatable :: ntrunc_vr (:,:) ! currently not used
+ real(r8), allocatable :: ntrunc_veg (:) ! currently not used
+ real(r8), allocatable :: ntrunc_soil (:) ! currently not used
+
+ real(r8), allocatable :: sminn_vr (:,:) ! vertical resolved: soil mineral nitrogen (gN m-3)
+ real(r8), allocatable :: smin_no3_vr (:,:) ! vertical resolved: soil mineral NO3 (gN m-3)
+ real(r8), allocatable :: smin_nh4_vr (:,:) ! vertical resolved: soil mineral NH4 (gN m-3)
+ real(r8), allocatable :: sminn (:) ! soil mineral nitrogen (gN m-2)
+ real(r8), allocatable :: ndep (:) ! atmospheric nitrogen deposition (gN m-2)
+
+ real(r8), allocatable :: to2_decomp_depth_unsat (:,:) ! vertical resolved: O2 soil consumption from heterotrophic respiration and autotrophic respiration (mol m-3 s-1)
+ real(r8), allocatable :: tconc_o2_unsat (:,:) ! vertical resolved: O2 soil consumption (mol m-3 s-1)
+
+ real(r8), allocatable :: ndep_prof (:,:) ! vertical resolved: atmospheric N deposition input to soil (m-1)
+ real(r8), allocatable :: nfixation_prof (:,:) ! vertical resolved: N fixation input to soil (m-1)
+
+ real(r8), allocatable :: cn_decomp_pools (:,:,:) ! vertical resolved: c:n ratios of each decomposition pools
+ real(r8), allocatable :: fpi_vr (:,:) ! vertical resolved: actual immobilization N :potential immobilization N
+ real(r8), allocatable :: fpi (:) ! actual immobilization N : potential immobilization N
+ real(r8), allocatable :: fpg (:) ! actual plant uptake N : plant potential need N
+
+ real(r8), allocatable :: cropf (:) !
+ real(r8), allocatable :: lfwt (:) !
+ real(r8), allocatable :: fuelc (:) !
+ real(r8), allocatable :: fuelc_crop (:) !
+ real(r8), allocatable :: fsr (:) !
+ real(r8), allocatable :: fd (:) !
+ real(r8), allocatable :: rootc (:) !
+ real(r8), allocatable :: lgdp (:) !
+ real(r8), allocatable :: lgdp1 (:) !
+ real(r8), allocatable :: lpop (:) !
+ real(r8), allocatable :: wtlf (:) !
+ real(r8), allocatable :: trotr1 (:) !
+ real(r8), allocatable :: trotr2 (:) !
+ real(r8), allocatable :: hdm_lf (:) !
+ real(r8), allocatable :: lnfm (:) !
+ real(r8), allocatable :: baf_crop (:) !
+ real(r8), allocatable :: baf_peatf (:) !
+ real(r8), allocatable :: farea_burned (:) ! total fractional area burned (s-1)
+ real(r8), allocatable :: nfire (:) ! fire counts (count km-2 s-1)
+ real(r8), allocatable :: fsat (:) !
+ real(r8), allocatable :: prec10 (:) ! 10-day running mean of total precipitation (mm -1)
+ real(r8), allocatable :: prec60 (:) ! 60-day running mean of total precipitation (mm -1)
+ real(r8), allocatable :: prec365 (:) ! 365-day running mean of tota l precipitation (mm -1)
+ real(r8), allocatable :: prec_today (:) ! today's daily precipitation (mm -1)
+ real(r8), allocatable :: prec_daily (:,:) ! daily total precipitation (mm -1)
+ real(r8), allocatable :: wf2 (:) ! soil moisture (K)
+ real(r8), allocatable :: tsoi17 (:) ! soil temperature (cm3 cm-3)
+ real(r8), allocatable :: rh30 (:) ! 30-day running mean of relative humidity (%)
+ real(r8), allocatable :: accumnstep (:) ! timestep accumulator
+
+ real(r8), allocatable :: dayl (:) ! day length (s)
+ real(r8), allocatable :: prev_dayl (:) ! day length from previous day (s)
+
+!-------------BGC/SASU variables---------------------------
+ real(r8), allocatable :: decomp0_cpools_vr (:,:,:) ! SASU spinup diagnostics vertical-resolved: soil decomposition (litter, cwd, soil organic matter) carbon pools (gC m-3)
+ real(r8), allocatable :: I_met_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to metabolic litter C (gC m-3)
+ real(r8), allocatable :: I_cel_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to cellulosic litter C (gC m-3)
+ real(r8), allocatable :: I_lig_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to lignin litter C (gC m-3)
+ real(r8), allocatable :: I_cwd_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to coarse woody debris C (gC m-3)
+ real(r8), allocatable :: AKX_met_to_soil1_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from metabolic litter C to active soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_cel_to_soil1_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from cellulosic litter C to active soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_lig_to_soil2_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from lignin litter C to slow soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_soil1_to_soil2_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from active soil organic matter C to slow soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_cwd_to_cel_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from coarse woody debris C to cellulosic litter C (gC m-3)
+ real(r8), allocatable :: AKX_cwd_to_lig_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from coarse woody debris C to lignin litter C (gC m-3)
+ real(r8), allocatable :: AKX_soil1_to_soil3_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from active soil organic matter C to passive soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_soil2_to_soil1_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from slow soil organic matter C to active soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_soil2_to_soil3_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from slow soil organic matter C to passive soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_soil3_to_soil1_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from passive soil organic matter C to active soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_met_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from metabolic litter C (gC m-3)
+ real(r8), allocatable :: AKX_cel_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from cellulosic litter C (gC m-3)
+ real(r8), allocatable :: AKX_lig_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from lignin litter C (gC m-3)
+ real(r8), allocatable :: AKX_cwd_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from coarse woody debris C (gC m-3)
+ real(r8), allocatable :: AKX_soil1_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from active soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_soil2_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from slow soil organic matter C (gC m-3)
+ real(r8), allocatable :: AKX_soil3_exit_c_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from passive soil organic matter C (gC m-3)
+
+ real(r8), allocatable :: decomp0_npools_vr (:,:,:) ! SASU spinup diagnostics vertical-resolved: soil decomposition (litter, cwd, soil organic matter) carbon pools (gN m-3)
+ real(r8), allocatable :: I_met_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to metabolic litter N (gN m-3)
+ real(r8), allocatable :: I_cel_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to cellulosic litter N (gN m-3)
+ real(r8), allocatable :: I_lig_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to lignin litter N (gN m-3)
+ real(r8), allocatable :: I_cwd_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated input to coarse woody debris N (gN m-3)
+ real(r8), allocatable :: AKX_met_to_soil1_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from metabolic litter N to active soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_cel_to_soil1_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from cellulosic litter N to active soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_lig_to_soil2_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from lignin litter N to slow soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_soil1_to_soil2_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from active soil organic matter N to slow soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_cwd_to_cel_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from coarse woody debris N to cellulosic litter N (gN m-3)
+ real(r8), allocatable :: AKX_cwd_to_lig_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from coarse woody debris N to lignin litter N (gN m-3)
+ real(r8), allocatable :: AKX_soil1_to_soil3_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from active soil organic matter N to passive soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_soil2_to_soil1_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from slow soil organic matter N to active soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_soil2_to_soil3_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from slow soil organic matter N to passive soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_soil3_to_soil1_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux from passive soil organic matter N to active soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_met_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from metabolic litter N (gN m-3)
+ real(r8), allocatable :: AKX_cel_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from cellulosic litter N (gN m-3)
+ real(r8), allocatable :: AKX_lig_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from lignin litter N (gN m-3)
+ real(r8), allocatable :: AKX_cwd_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from coarse woody debris N (gN m-3)
+ real(r8), allocatable :: AKX_soil1_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from active soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_soil2_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from slow soil organic matter N (gN m-3)
+ real(r8), allocatable :: AKX_soil3_exit_n_vr_acc (:,:) ! SASU spinup diagnostics vertical-resolved: accumulated flux exiting from passive soil organic matter N (gN m-3)
+
+ real(r8), allocatable :: diagVX_c_vr_acc (:,:,:) ! SASU spinup diagnostics vertical-resolved: accumulated carbon EXIT flux due to the vertical mixing in soil and litter pools (gC m-3)
+ real(r8), allocatable :: upperVX_c_vr_acc (:,:,:) ! SASU spinup diagnostics vertical-resolved: accumulated carbon upward flux due to the vertical mixing in soil and litter pools (gC m-3)
+ real(r8), allocatable :: lowerVX_c_vr_acc (:,:,:) ! SASU spinup diagnostics vertical-resolved: accumulated carbon downward flux due to the vertical mixing in soil and litter pools (gC m-3)
+ real(r8), allocatable :: diagVX_n_vr_acc (:,:,:) ! SASU spinup diagnostics vertical-resolved: accumulated nitrogen EXIT flux due to the vertical mixing in soil and litter pools (gN m-3)
+ real(r8), allocatable :: upperVX_n_vr_acc (:,:,:) ! SASU spinup diagnostics vertical-resolved: accumulated nitrogen upward flux due to the vertical mixing in soil and litter pools (gN m-3)
+ real(r8), allocatable :: lowerVX_n_vr_acc (:,:,:) ! SASU spinup diagnostics vertical-resolved: accumulated nitrogen downward flux due to the vertical mixing in soil and litter pools (gN m-3)
+ logical , allocatable :: skip_balance_check (:) ! When we estimate the steady state and update the actcual pool with steady state in SASU, the CN balance check is expected to fail. &
+ ! Skip the balance check at END of the year when SASU is on
+#ifdef CROP
+ real(r8), allocatable :: cphase (:) ! crop phasecrop phase
+ real(r8), allocatable :: vf (:) ! vernalization response
+ real(r8), allocatable :: gddplant (:) ! gdd since planting (ddays)
+ real(r8), allocatable :: gddmaturity (:) ! gdd needed to harvest (ddays)
+ real(r8), allocatable :: hui (:) ! heat unit index
+ real(r8), allocatable :: huiswheat (:) ! heat unit index (rainfed spring wheat)
+ real(r8), allocatable :: pdcorn (:) ! planting date of corn
+ real(r8), allocatable :: pdswheat (:) ! planting date of spring wheat
+ real(r8), allocatable :: pdwwheat (:) ! planting date of winter wheat
+ real(r8), allocatable :: pdsoybean (:) ! planting date of soybean
+ real(r8), allocatable :: pdcotton (:) ! planting date of cotton
+ real(r8), allocatable :: pdrice1 (:) ! planting date of rice1
+ real(r8), allocatable :: pdrice2 (:) ! planting date of rice2
+ real(r8), allocatable :: pdsugarcane (:) ! planting date of sugarcane
+ real(r8), allocatable :: plantdate (:) ! planting date
+ real(r8), allocatable :: manunitro (:) ! nitrogen fertilizer for corn (gN m-2)
+ real(r8), allocatable :: fertnitro_corn (:) ! nitrogen fertilizer for corn (gN m-2)
+ real(r8), allocatable :: fertnitro_swheat (:) ! nitrogen fertilizer for spring wheat (gN m-2)
+ real(r8), allocatable :: fertnitro_wwheat (:) ! nitrogen fertilizer for winter wheat (gN m-2)
+ real(r8), allocatable :: fertnitro_soybean (:) ! nitrogen fertilizer for soybean (gN m-2)
+ real(r8), allocatable :: fertnitro_cotton (:) ! nitrogen fertilizer for cotton (gN m-2)
+ real(r8), allocatable :: fertnitro_rice1 (:) ! nitrogen fertilizer for rice1 (gN m-2)
+ real(r8), allocatable :: fertnitro_rice2 (:) ! nitrogen fertilizer for rice2 (gN m-2)
+ real(r8), allocatable :: fertnitro_sugarcane (:) ! nitrogen fertilizer for sugarcane (gN m-2)
+#endif
+ real(r8), allocatable :: lag_npp (:) !!! lagged net primary production (gC m-2)
+!------------------------------------------------------
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_BGCTimeVariables
+ PUBLIC :: deallocate_BGCTimeVariables
+ PUBLIC :: READ_BGCTimeVariables
+ PUBLIC :: WRITE_BGCTimeVariables
+#ifdef RangeCheck
+ PUBLIC :: check_BGCTimeVariables
+#endif
+
+! PRIVATE MEMBER FUNCTIONS:
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_BGCTimeVariables
+! --------------------------------------------------------------------
+! Allocates memory for CoLM 1d [numpatch] variables
+! ------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ ! bgc variables
+ allocate (decomp_cpools_vr (nl_soil_full,ndecomp_pools,numpatch)) ; decomp_cpools_vr (:,:,:) = spval
+ allocate (decomp_cpools (ndecomp_pools,numpatch)) ; decomp_cpools (:,:) = spval
+ allocate (decomp_cpools_vr_Cap (nl_soil_full,ndecomp_pools,numpatch)) ; decomp_cpools_vr_Cap(:,:,:) = spval
+ allocate (ctrunc_vr (nl_soil,numpatch)) ; ctrunc_vr (:,:) = spval
+ allocate (ctrunc_veg (numpatch)) ; ctrunc_veg (:) = spval
+ allocate (ctrunc_soil (numpatch)) ; ctrunc_soil (:) = spval
+ allocate (decomp_k (nl_soil_full,ndecomp_pools,numpatch)) ; decomp_k (:,:,:) = spval
+
+ allocate (t_scalar (nl_soil,numpatch)) ; t_scalar (:,:) = spval
+ allocate (w_scalar (nl_soil,numpatch)) ; w_scalar (:,:) = spval
+ allocate (o_scalar (nl_soil,numpatch)) ; o_scalar (:,:) = spval
+ allocate (depth_scalar (nl_soil,numpatch)) ; depth_scalar (:,:) = spval
+
+ allocate (som_adv_coef (nl_soil_full,numpatch)) ; som_adv_coef (:,:) = spval
+ allocate (som_diffus_coef (nl_soil_full,numpatch)) ; som_diffus_coef (:,:) = spval
+
+ allocate (altmax (numpatch)) ; altmax (:) = spval
+ allocate (altmax_lastyear (numpatch)) ; altmax_lastyear (:) = spval
+ allocate (altmax_lastyear_indx (numpatch)) ; altmax_lastyear_indx (:) = spval_i4
+
+ allocate (totlitc (numpatch)) ; totlitc (:) = spval
+ allocate (totvegc (numpatch)) ; totvegc (:) = spval
+ allocate (totsomc (numpatch)) ; totsomc (:) = spval
+ allocate (totcwdc (numpatch)) ; totcwdc (:) = spval
+ allocate (totcolc (numpatch)) ; totcolc (:) = spval
+ allocate (col_begcb (numpatch)) ; col_begcb (:) = spval
+ allocate (col_endcb (numpatch)) ; col_endcb (:) = spval
+ allocate (col_vegbegcb (numpatch)) ; col_vegbegcb (:) = spval
+ allocate (col_vegendcb (numpatch)) ; col_vegendcb (:) = spval
+ allocate (col_soilbegcb (numpatch)) ; col_soilbegcb (:) = spval
+ allocate (col_soilendcb (numpatch)) ; col_soilendcb (:) = spval
+
+ allocate (totlitn (numpatch)) ; totlitn (:) = spval
+ allocate (totvegn (numpatch)) ; totvegn (:) = spval
+ allocate (totsomn (numpatch)) ; totsomn (:) = spval
+ allocate (totcwdn (numpatch)) ; totcwdn (:) = spval
+ allocate (totcoln (numpatch)) ; totcoln (:) = spval
+ allocate (col_begnb (numpatch)) ; col_begnb (:) = spval
+ allocate (col_endnb (numpatch)) ; col_endnb (:) = spval
+ allocate (col_vegbegnb (numpatch)) ; col_vegbegnb (:) = spval
+ allocate (col_vegendnb (numpatch)) ; col_vegendnb (:) = spval
+ allocate (col_soilbegnb (numpatch)) ; col_soilbegnb (:) = spval
+ allocate (col_soilendnb (numpatch)) ; col_soilendnb (:) = spval
+ allocate (col_sminnbegnb (numpatch)) ; col_sminnbegnb (:) = spval
+ allocate (col_sminnendnb (numpatch)) ; col_sminnendnb (:) = spval
+
+ allocate (leafc (numpatch)) ; leafc (:) = spval
+ allocate (leafc_storage (numpatch)) ; leafc_storage (:) = spval
+ allocate (leafc_xfer (numpatch)) ; leafc_xfer (:) = spval
+ allocate (frootc (numpatch)) ; frootc (:) = spval
+ allocate (frootc_storage (numpatch)) ; frootc_storage (:) = spval
+ allocate (frootc_xfer (numpatch)) ; frootc_xfer (:) = spval
+ allocate (livestemc (numpatch)) ; livestemc (:) = spval
+ allocate (livestemc_storage (numpatch)) ; livestemc_storage (:) = spval
+ allocate (livestemc_xfer (numpatch)) ; livestemc_xfer (:) = spval
+ allocate (deadstemc (numpatch)) ; deadstemc (:) = spval
+ allocate (deadstemc_storage (numpatch)) ; deadstemc_storage (:) = spval
+ allocate (deadstemc_xfer (numpatch)) ; deadstemc_xfer (:) = spval
+ allocate (livecrootc (numpatch)) ; livecrootc (:) = spval
+ allocate (livecrootc_storage (numpatch)) ; livecrootc_storage (:) = spval
+ allocate (livecrootc_xfer (numpatch)) ; livecrootc_xfer (:) = spval
+ allocate (deadcrootc (numpatch)) ; deadcrootc (:) = spval
+ allocate (deadcrootc_storage (numpatch)) ; deadcrootc_storage (:) = spval
+ allocate (deadcrootc_xfer (numpatch)) ; deadcrootc_xfer (:) = spval
+ allocate (grainc (numpatch)) ; grainc (:) = spval
+ allocate (grainc_storage (numpatch)) ; grainc_storage (:) = spval
+ allocate (grainc_xfer (numpatch)) ; grainc_xfer (:) = spval
+ allocate (xsmrpool (numpatch)) ; xsmrpool (:) = spval
+ allocate (downreg (numpatch)) ; downreg (:) = spval
+ allocate (cropprod1c (numpatch)) ; cropprod1c (:) = spval
+ allocate (cropseedc_deficit (numpatch)) ; cropseedc_deficit (:) = spval
+
+ allocate (leafn (numpatch)) ; leafn (:) = spval
+ allocate (leafn_storage (numpatch)) ; leafn_storage (:) = spval
+ allocate (leafn_xfer (numpatch)) ; leafn_xfer (:) = spval
+ allocate (frootn (numpatch)) ; frootn (:) = spval
+ allocate (frootn_storage (numpatch)) ; frootn_storage (:) = spval
+ allocate (frootn_xfer (numpatch)) ; frootn_xfer (:) = spval
+ allocate (livestemn (numpatch)) ; livestemn (:) = spval
+ allocate (livestemn_storage (numpatch)) ; livestemn_storage (:) = spval
+ allocate (livestemn_xfer (numpatch)) ; livestemn_xfer (:) = spval
+ allocate (deadstemn (numpatch)) ; deadstemn (:) = spval
+ allocate (deadstemn_storage (numpatch)) ; deadstemn_storage (:) = spval
+ allocate (deadstemn_xfer (numpatch)) ; deadstemn_xfer (:) = spval
+ allocate (livecrootn (numpatch)) ; livecrootn (:) = spval
+ allocate (livecrootn_storage (numpatch)) ; livecrootn_storage (:) = spval
+ allocate (livecrootn_xfer (numpatch)) ; livecrootn_xfer (:) = spval
+ allocate (deadcrootn (numpatch)) ; deadcrootn (:) = spval
+ allocate (deadcrootn_storage (numpatch)) ; deadcrootn_storage (:) = spval
+ allocate (deadcrootn_xfer (numpatch)) ; deadcrootn_xfer (:) = spval
+ allocate (grainn (numpatch)) ; grainn (:) = spval
+ allocate (grainn_storage (numpatch)) ; grainn_storage (:) = spval
+ allocate (grainn_xfer (numpatch)) ; grainn_xfer (:) = spval
+ allocate (retransn (numpatch)) ; retransn (:) = spval
+
+ allocate (leafcCap (numpatch)) ; leafcCap (:) = spval
+ allocate (leafc_storageCap (numpatch)) ; leafc_storageCap (:) = spval
+ allocate (leafc_xferCap (numpatch)) ; leafc_xferCap (:) = spval
+ allocate (frootcCap (numpatch)) ; frootcCap (:) = spval
+ allocate (frootc_storageCap (numpatch)) ; frootc_storageCap (:) = spval
+ allocate (frootc_xferCap (numpatch)) ; frootc_xferCap (:) = spval
+ allocate (livestemcCap (numpatch)) ; livestemcCap (:) = spval
+ allocate (livestemc_storageCap (numpatch)) ; livestemc_storageCap (:) = spval
+ allocate (livestemc_xferCap (numpatch)) ; livestemc_xferCap (:) = spval
+ allocate (deadstemcCap (numpatch)) ; deadstemcCap (:) = spval
+ allocate (deadstemc_storageCap (numpatch)) ; deadstemc_storageCap (:) = spval
+ allocate (deadstemc_xferCap (numpatch)) ; deadstemc_xferCap (:) = spval
+ allocate (livecrootcCap (numpatch)) ; livecrootcCap (:) = spval
+ allocate (livecrootc_storageCap (numpatch)) ; livecrootc_storageCap (:) = spval
+ allocate (livecrootc_xferCap (numpatch)) ; livecrootc_xferCap (:) = spval
+ allocate (deadcrootcCap (numpatch)) ; deadcrootcCap (:) = spval
+ allocate (deadcrootc_storageCap (numpatch)) ; deadcrootc_storageCap (:) = spval
+ allocate (deadcrootc_xferCap (numpatch)) ; deadcrootc_xferCap (:) = spval
+
+ allocate (leafnCap (numpatch)) ; leafnCap (:) = spval
+ allocate (leafn_storageCap (numpatch)) ; leafn_storageCap (:) = spval
+ allocate (leafn_xferCap (numpatch)) ; leafn_xferCap (:) = spval
+ allocate (frootnCap (numpatch)) ; frootnCap (:) = spval
+ allocate (frootn_storageCap (numpatch)) ; frootn_storageCap (:) = spval
+ allocate (frootn_xferCap (numpatch)) ; frootn_xferCap (:) = spval
+ allocate (livestemnCap (numpatch)) ; livestemnCap (:) = spval
+ allocate (livestemn_storageCap (numpatch)) ; livestemn_storageCap (:) = spval
+ allocate (livestemn_xferCap (numpatch)) ; livestemn_xferCap (:) = spval
+ allocate (deadstemnCap (numpatch)) ; deadstemnCap (:) = spval
+ allocate (deadstemn_storageCap (numpatch)) ; deadstemn_storageCap (:) = spval
+ allocate (deadstemn_xferCap (numpatch)) ; deadstemn_xferCap (:) = spval
+ allocate (livecrootnCap (numpatch)) ; livecrootnCap (:) = spval
+ allocate (livecrootn_storageCap (numpatch)) ; livecrootn_storageCap (:) = spval
+ allocate (livecrootn_xferCap (numpatch)) ; livecrootn_xferCap (:) = spval
+ allocate (deadcrootnCap (numpatch)) ; deadcrootnCap (:) = spval
+ allocate (deadcrootn_storageCap (numpatch)) ; deadcrootn_storageCap (:) = spval
+ allocate (deadcrootn_xferCap (numpatch)) ; deadcrootn_xferCap (:) = spval
+
+ allocate (decomp_npools_vr (nl_soil_full,ndecomp_pools,numpatch)) ; decomp_npools_vr (:,:,:) = spval
+ allocate (decomp_npools (ndecomp_pools,numpatch)) ; decomp_npools (:,:) = spval
+ allocate (decomp_npools_vr_Cap (nl_soil_full,ndecomp_pools,numpatch)) ; decomp_npools_vr_Cap(:,:,:) = spval
+ allocate (totsoiln_vr (nl_soil,numpatch)) ; totsoiln_vr (:,:) = spval
+ allocate (ntrunc_vr (nl_soil,numpatch)) ; ntrunc_vr (:,:) = spval
+ allocate (ntrunc_veg (numpatch)) ; ntrunc_veg (:) = spval
+ allocate (ntrunc_soil (numpatch)) ; ntrunc_soil (:) = spval
+ allocate (sminn_vr (nl_soil,numpatch)) ; sminn_vr (:,:) = spval
+ allocate (smin_no3_vr (nl_soil,numpatch)) ; smin_no3_vr (:,:) = spval
+ allocate (smin_nh4_vr (nl_soil,numpatch)) ; smin_nh4_vr (:,:) = spval
+ allocate (sminn (numpatch)) ; sminn (:) = spval
+ allocate (ndep (numpatch)) ; ndep (:) = spval
+
+ allocate (to2_decomp_depth_unsat (nl_soil,numpatch)) ; to2_decomp_depth_unsat (:,:) = spval
+ allocate (tconc_o2_unsat (nl_soil,numpatch)) ; tconc_o2_unsat (:,:) = spval
+
+ allocate (ndep_prof (nl_soil,numpatch)) ; ndep_prof (:,:) = spval
+ allocate (nfixation_prof (nl_soil,numpatch)) ; nfixation_prof (:,:) = spval
+
+ allocate (cn_decomp_pools (nl_soil,ndecomp_pools,numpatch)) ; cn_decomp_pools (:,:,:) = spval
+ allocate (fpi_vr (nl_soil,numpatch)) ; fpi_vr (:,:) = spval
+ allocate (fpi (numpatch)) ; fpi (:) = spval
+ allocate (fpg (numpatch)) ; fpg (:) = spval
+
+ allocate (cropf (numpatch)) ; cropf (:) = spval
+ allocate (lfwt (numpatch)) ; lfwt (:) = spval
+ allocate (fuelc (numpatch)) ; fuelc (:) = spval
+ allocate (fuelc_crop (numpatch)) ; fuelc_crop (:) = spval
+ allocate (fsr (numpatch)) ; fsr (:) = spval
+ allocate (fd (numpatch)) ; fd (:) = spval
+ allocate (rootc (numpatch)) ; rootc (:) = spval
+ allocate (lgdp (numpatch)) ; lgdp (:) = spval
+ allocate (lgdp1 (numpatch)) ; lgdp1 (:) = spval
+ allocate (lpop (numpatch)) ; lpop (:) = spval
+ allocate (wtlf (numpatch)) ; wtlf (:) = spval
+ allocate (trotr1 (numpatch)) ; trotr1 (:) = spval
+ allocate (trotr2 (numpatch)) ; trotr2 (:) = spval
+ allocate (hdm_lf (numpatch)) ; hdm_lf (:) = spval
+ allocate (lnfm (numpatch)) ; lnfm (:) = spval
+ allocate (baf_crop (numpatch)) ; baf_crop (:) = spval
+ allocate (baf_peatf (numpatch)) ; baf_peatf (:) = spval
+ allocate (farea_burned (numpatch)) ; farea_burned (:) = spval
+ allocate (nfire (numpatch)) ; nfire (:) = spval
+ allocate (fsat (numpatch)) ; fsat (:) = spval
+ allocate (prec10 (numpatch)) ; prec10 (:) = spval
+ allocate (prec60 (numpatch)) ; prec60 (:) = spval
+ allocate (prec365 (numpatch)) ; prec365 (:) = spval
+ allocate (prec_today (numpatch)) ; prec_today (:) = spval
+ allocate (prec_daily (365,numpatch)) ; prec_daily (:,:) = spval! daily total precipitation [mm/day]
+ allocate (wf2 (numpatch)) ; wf2 (:) = spval
+ allocate (tsoi17 (numpatch)) ; tsoi17 (:) = spval
+ allocate (rh30 (numpatch)) ; rh30 (:) = spval
+ allocate (accumnstep (numpatch)) ; accumnstep (:) = spval
+ ;
+ allocate (dayl (numpatch)) ; dayl (:) = spval
+ allocate (prev_dayl (numpatch)) ; prev_dayl (:) = spval
+
+ !---------------------------SASU variables--------------------------------------
+ allocate (decomp0_cpools_vr (nl_soil,ndecomp_pools,numpatch)) ; decomp0_cpools_vr (:,:,:) = spval
+ allocate (I_met_c_vr_acc (nl_soil,numpatch)) ; I_met_c_vr_acc (:,:) = spval
+ allocate (I_cel_c_vr_acc (nl_soil,numpatch)) ; I_cel_c_vr_acc (:,:) = spval
+ allocate (I_lig_c_vr_acc (nl_soil,numpatch)) ; I_lig_c_vr_acc (:,:) = spval
+ allocate (I_cwd_c_vr_acc (nl_soil,numpatch)) ; I_cwd_c_vr_acc (:,:) = spval
+ allocate (AKX_met_to_soil1_c_vr_acc (nl_soil,numpatch)) ; AKX_met_to_soil1_c_vr_acc (:,:) = spval
+ allocate (AKX_cel_to_soil1_c_vr_acc (nl_soil,numpatch)) ; AKX_cel_to_soil1_c_vr_acc (:,:) = spval
+ allocate (AKX_lig_to_soil2_c_vr_acc (nl_soil,numpatch)) ; AKX_lig_to_soil2_c_vr_acc (:,:) = spval
+ allocate (AKX_soil1_to_soil2_c_vr_acc (nl_soil,numpatch)) ; AKX_soil1_to_soil2_c_vr_acc (:,:) = spval
+ allocate (AKX_cwd_to_cel_c_vr_acc (nl_soil,numpatch)) ; AKX_cwd_to_cel_c_vr_acc (:,:) = spval
+ allocate (AKX_cwd_to_lig_c_vr_acc (nl_soil,numpatch)) ; AKX_cwd_to_lig_c_vr_acc (:,:) = spval
+ allocate (AKX_soil1_to_soil3_c_vr_acc (nl_soil,numpatch)) ; AKX_soil1_to_soil3_c_vr_acc (:,:) = spval
+ allocate (AKX_soil2_to_soil1_c_vr_acc (nl_soil,numpatch)) ; AKX_soil2_to_soil1_c_vr_acc (:,:) = spval
+ allocate (AKX_soil2_to_soil3_c_vr_acc (nl_soil,numpatch)) ; AKX_soil2_to_soil3_c_vr_acc (:,:) = spval
+ allocate (AKX_soil3_to_soil1_c_vr_acc (nl_soil,numpatch)) ; AKX_soil3_to_soil1_c_vr_acc (:,:) = spval
+ allocate (AKX_met_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_met_exit_c_vr_acc (:,:) = spval
+ allocate (AKX_cel_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_cel_exit_c_vr_acc (:,:) = spval
+ allocate (AKX_lig_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_lig_exit_c_vr_acc (:,:) = spval
+ allocate (AKX_cwd_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_cwd_exit_c_vr_acc (:,:) = spval
+ allocate (AKX_soil1_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_soil1_exit_c_vr_acc (:,:) = spval
+ allocate (AKX_soil2_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_soil2_exit_c_vr_acc (:,:) = spval
+ allocate (AKX_soil3_exit_c_vr_acc (nl_soil,numpatch)) ; AKX_soil3_exit_c_vr_acc (:,:) = spval
+
+ allocate (decomp0_npools_vr (nl_soil,ndecomp_pools,numpatch)) ; decomp0_npools_vr (:,:,:) = spval
+ allocate (I_met_n_vr_acc (nl_soil,numpatch)) ; I_met_n_vr_acc (:,:) = spval
+ allocate (I_cel_n_vr_acc (nl_soil,numpatch)) ; I_cel_n_vr_acc (:,:) = spval
+ allocate (I_lig_n_vr_acc (nl_soil,numpatch)) ; I_lig_n_vr_acc (:,:) = spval
+ allocate (I_cwd_n_vr_acc (nl_soil,numpatch)) ; I_cwd_n_vr_acc (:,:) = spval
+ allocate (AKX_met_to_soil1_n_vr_acc (nl_soil,numpatch)) ; AKX_met_to_soil1_n_vr_acc (:,:) = spval
+ allocate (AKX_cel_to_soil1_n_vr_acc (nl_soil,numpatch)) ; AKX_cel_to_soil1_n_vr_acc (:,:) = spval
+ allocate (AKX_lig_to_soil2_n_vr_acc (nl_soil,numpatch)) ; AKX_lig_to_soil2_n_vr_acc (:,:) = spval
+ allocate (AKX_soil1_to_soil2_n_vr_acc (nl_soil,numpatch)) ; AKX_soil1_to_soil2_n_vr_acc (:,:) = spval
+ allocate (AKX_cwd_to_cel_n_vr_acc (nl_soil,numpatch)) ; AKX_cwd_to_cel_n_vr_acc (:,:) = spval
+ allocate (AKX_cwd_to_lig_n_vr_acc (nl_soil,numpatch)) ; AKX_cwd_to_lig_n_vr_acc (:,:) = spval
+ allocate (AKX_soil1_to_soil3_n_vr_acc (nl_soil,numpatch)) ; AKX_soil1_to_soil3_n_vr_acc (:,:) = spval
+ allocate (AKX_soil2_to_soil1_n_vr_acc (nl_soil,numpatch)) ; AKX_soil2_to_soil1_n_vr_acc (:,:) = spval
+ allocate (AKX_soil2_to_soil3_n_vr_acc (nl_soil,numpatch)) ; AKX_soil2_to_soil3_n_vr_acc (:,:) = spval
+ allocate (AKX_soil3_to_soil1_n_vr_acc (nl_soil,numpatch)) ; AKX_soil3_to_soil1_n_vr_acc (:,:) = spval
+ allocate (AKX_met_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_met_exit_n_vr_acc (:,:) = spval
+ allocate (AKX_cel_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_cel_exit_n_vr_acc (:,:) = spval
+ allocate (AKX_lig_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_lig_exit_n_vr_acc (:,:) = spval
+ allocate (AKX_cwd_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_cwd_exit_n_vr_acc (:,:) = spval
+ allocate (AKX_soil1_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_soil1_exit_n_vr_acc (:,:) = spval
+ allocate (AKX_soil2_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_soil2_exit_n_vr_acc (:,:) = spval
+ allocate (AKX_soil3_exit_n_vr_acc (nl_soil,numpatch)) ; AKX_soil3_exit_n_vr_acc (:,:) = spval
+
+ allocate (diagVX_c_vr_acc (nl_soil,ndecomp_pools,numpatch)) ; diagVX_c_vr_acc (:,:,:) = spval
+ allocate (upperVX_c_vr_acc (nl_soil,ndecomp_pools,numpatch)) ; upperVX_c_vr_acc (:,:,:) = spval
+ allocate (lowerVX_c_vr_acc (nl_soil,ndecomp_pools,numpatch)) ; lowerVX_c_vr_acc (:,:,:) = spval
+ allocate (diagVX_n_vr_acc (nl_soil,ndecomp_pools,numpatch)) ; diagVX_n_vr_acc (:,:,:) = spval
+ allocate (upperVX_n_vr_acc (nl_soil,ndecomp_pools,numpatch)) ; upperVX_n_vr_acc (:,:,:) = spval
+ allocate (lowerVX_n_vr_acc (nl_soil,ndecomp_pools,numpatch)) ; lowerVX_n_vr_acc (:,:,:) = spval
+
+ !---------------------------------------------------------------------------
+ allocate (skip_balance_check (numpatch)) ; skip_balance_check (:) = .false.
+
+#ifdef CROP
+ allocate (cphase (numpatch)) ; cphase (:) = spval ! 30-day running mean of relative humidity
+ allocate (vf (numpatch)) ; vf (:) = spval
+ allocate (gddmaturity (numpatch)) ; gddmaturity (:) = spval
+ allocate (gddplant (numpatch)) ; gddplant (:) = spval
+ allocate (hui (numpatch)) ; hui (:) = spval
+ allocate (huiswheat (numpatch)) ; huiswheat (:) = spval
+ allocate (pdcorn (numpatch)) ; pdcorn (:) = spval
+ allocate (pdswheat (numpatch)) ; pdswheat (:) = spval
+ allocate (pdwwheat (numpatch)) ; pdwwheat (:) = spval
+ allocate (pdsoybean (numpatch)) ; pdsoybean (:) = spval
+ allocate (pdcotton (numpatch)) ; pdcotton (:) = spval
+ allocate (pdrice1 (numpatch)) ; pdrice1 (:) = spval
+ allocate (pdrice2 (numpatch)) ; pdrice2 (:) = spval
+ allocate (plantdate (numpatch)) ; plantdate (:) = spval
+ allocate (pdsugarcane (numpatch)) ; pdsugarcane (:) = spval
+ allocate (manunitro (numpatch)) ; manunitro (:) = spval
+ allocate (fertnitro_corn (numpatch)) ; fertnitro_corn (:) = spval
+ allocate (fertnitro_swheat (numpatch)) ; fertnitro_swheat (:) = spval
+ allocate (fertnitro_wwheat (numpatch)) ; fertnitro_wwheat (:) = spval
+ allocate (fertnitro_soybean (numpatch)) ; fertnitro_soybean (:) = spval
+ allocate (fertnitro_cotton (numpatch)) ; fertnitro_cotton (:) = spval
+ allocate (fertnitro_rice1 (numpatch)) ; fertnitro_rice1 (:) = spval
+ allocate (fertnitro_rice2 (numpatch)) ; fertnitro_rice2 (:) = spval
+ allocate (fertnitro_sugarcane (numpatch)) ; fertnitro_sugarcane (:) = spval
+#endif
+ allocate (lag_npp (numpatch)) ; lag_npp (:) = spval
+ ENDIF
+ ENDIF
+
+
+ END SUBROUTINE allocate_BGCTimeVariables
+
+
+ SUBROUTINE deallocate_BGCTimeVariables ()
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+! --------------------------------------------------
+! Deallocates memory for CoLM 1d [numpatch] variables
+! --------------------------------------------------
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ ! bgc variables
+ deallocate (decomp_cpools_vr )
+ deallocate (decomp_cpools )
+ deallocate (decomp_cpools_vr_Cap )
+ deallocate (ctrunc_vr )
+ deallocate (ctrunc_veg )
+ deallocate (ctrunc_soil )
+ deallocate (decomp_k )
+
+ deallocate (t_scalar )
+ deallocate (w_scalar )
+ deallocate (o_scalar )
+ deallocate (depth_scalar )
+
+ deallocate (som_adv_coef )
+ deallocate (som_diffus_coef )
+
+ deallocate (altmax )
+ deallocate (altmax_lastyear )
+ deallocate (altmax_lastyear_indx )
+
+ deallocate (totlitc )
+ deallocate (totvegc )
+ deallocate (totsomc )
+ deallocate (totcwdc )
+ deallocate (totcolc )
+ deallocate (col_begcb )
+ deallocate (col_endcb )
+ deallocate (col_vegbegcb )
+ deallocate (col_vegendcb )
+ deallocate (col_soilbegcb )
+ deallocate (col_soilendcb )
+
+ deallocate (totlitn )
+ deallocate (totvegn )
+ deallocate (totsomn )
+ deallocate (totcwdn )
+ deallocate (totcoln )
+ deallocate (col_begnb )
+ deallocate (col_endnb )
+ deallocate (col_vegbegnb )
+ deallocate (col_vegendnb )
+ deallocate (col_soilbegnb )
+ deallocate (col_soilendnb )
+ deallocate (col_sminnbegnb )
+ deallocate (col_sminnendnb )
+
+ deallocate (leafc )
+ deallocate (leafc_storage )
+ deallocate (leafc_xfer )
+ deallocate (frootc )
+ deallocate (frootc_storage )
+ deallocate (frootc_xfer )
+ deallocate (livestemc )
+ deallocate (livestemc_storage )
+ deallocate (livestemc_xfer )
+ deallocate (deadstemc )
+ deallocate (deadstemc_storage )
+ deallocate (deadstemc_xfer )
+ deallocate (livecrootc )
+ deallocate (livecrootc_storage )
+ deallocate (livecrootc_xfer )
+ deallocate (deadcrootc )
+ deallocate (deadcrootc_storage )
+ deallocate (deadcrootc_xfer )
+ deallocate (grainc )
+ deallocate (grainc_storage )
+ deallocate (grainc_xfer )
+ deallocate (xsmrpool )
+ deallocate (downreg )
+ deallocate (cropprod1c )
+ deallocate (cropseedc_deficit )
+
+ deallocate (leafn )
+ deallocate (leafn_storage )
+ deallocate (leafn_xfer )
+ deallocate (frootn )
+ deallocate (frootn_storage )
+ deallocate (frootn_xfer )
+ deallocate (livestemn )
+ deallocate (livestemn_storage )
+ deallocate (livestemn_xfer )
+ deallocate (deadstemn )
+ deallocate (deadstemn_storage )
+ deallocate (deadstemn_xfer )
+ deallocate (livecrootn )
+ deallocate (livecrootn_storage )
+ deallocate (livecrootn_xfer )
+ deallocate (deadcrootn )
+ deallocate (deadcrootn_storage )
+ deallocate (deadcrootn_xfer )
+ deallocate (grainn )
+ deallocate (grainn_storage )
+ deallocate (grainn_xfer )
+ deallocate (retransn )
+
+ deallocate (leafcCap )
+ deallocate (leafc_storageCap )
+ deallocate (leafc_xferCap )
+ deallocate (frootcCap )
+ deallocate (frootc_storageCap )
+ deallocate (frootc_xferCap )
+ deallocate (livestemcCap )
+ deallocate (livestemc_storageCap )
+ deallocate (livestemc_xferCap )
+ deallocate (deadstemcCap )
+ deallocate (deadstemc_storageCap )
+ deallocate (deadstemc_xferCap )
+ deallocate (livecrootcCap )
+ deallocate (livecrootc_storageCap )
+ deallocate (livecrootc_xferCap )
+ deallocate (deadcrootcCap )
+ deallocate (deadcrootc_storageCap )
+ deallocate (deadcrootc_xferCap )
+
+ deallocate (leafnCap )
+ deallocate (leafn_storageCap )
+ deallocate (leafn_xferCap )
+ deallocate (frootnCap )
+ deallocate (frootn_storageCap )
+ deallocate (frootn_xferCap )
+ deallocate (livestemnCap )
+ deallocate (livestemn_storageCap )
+ deallocate (livestemn_xferCap )
+ deallocate (deadstemnCap )
+ deallocate (deadstemn_storageCap )
+ deallocate (deadstemn_xferCap )
+ deallocate (livecrootnCap )
+ deallocate (livecrootn_storageCap )
+ deallocate (livecrootn_xferCap )
+ deallocate (deadcrootnCap )
+ deallocate (deadcrootn_storageCap )
+ deallocate (deadcrootn_xferCap )
+
+ deallocate (decomp_npools_vr )
+ deallocate (decomp_npools )
+ deallocate (decomp_npools_vr_Cap )
+ deallocate (totsoiln_vr )
+ deallocate (ntrunc_vr )
+ deallocate (ntrunc_veg )
+ deallocate (ntrunc_soil )
+ deallocate (sminn_vr )
+ deallocate (smin_no3_vr )
+ deallocate (smin_nh4_vr )
+ deallocate (sminn )
+ deallocate (ndep )
+
+ deallocate (to2_decomp_depth_unsat )
+ deallocate (tconc_o2_unsat )
+
+ deallocate (ndep_prof )
+ deallocate (nfixation_prof )
+
+ deallocate (cn_decomp_pools )
+ deallocate (fpi_vr )
+ deallocate (fpi )
+ deallocate (fpg )
+
+ deallocate (cropf )
+ deallocate (lfwt )
+ deallocate (fuelc )
+ deallocate (fuelc_crop )
+ deallocate (fsr )
+ deallocate (fd )
+ deallocate (rootc )
+ deallocate (lgdp )
+ deallocate (lgdp1 )
+ deallocate (lpop )
+ deallocate (wtlf )
+ deallocate (trotr1 )
+ deallocate (trotr2 )
+ deallocate (hdm_lf )
+ deallocate (lnfm )
+ deallocate (baf_crop )
+ deallocate (baf_peatf )
+ deallocate (farea_burned )
+ deallocate (nfire )
+ deallocate (fsat )
+ deallocate (prec10 )
+ deallocate (prec60 )
+ deallocate (prec365 )
+ deallocate (prec_today )
+ deallocate (prec_daily )
+ deallocate (wf2 )
+ deallocate (tsoi17 )
+ deallocate (rh30 )
+ deallocate (accumnstep )
+
+ deallocate (dayl )
+ deallocate (prev_dayl )
+
+ !---------------------------SASU variables--------------------------------------
+ deallocate (decomp0_cpools_vr )
+ deallocate (I_met_c_vr_acc )
+ deallocate (I_cel_c_vr_acc )
+ deallocate (I_lig_c_vr_acc )
+ deallocate (I_cwd_c_vr_acc )
+ deallocate (AKX_met_to_soil1_c_vr_acc )
+ deallocate (AKX_cel_to_soil1_c_vr_acc )
+ deallocate (AKX_lig_to_soil2_c_vr_acc )
+ deallocate (AKX_soil1_to_soil2_c_vr_acc )
+ deallocate (AKX_cwd_to_cel_c_vr_acc )
+ deallocate (AKX_cwd_to_lig_c_vr_acc )
+ deallocate (AKX_soil1_to_soil3_c_vr_acc )
+ deallocate (AKX_soil2_to_soil1_c_vr_acc )
+ deallocate (AKX_soil2_to_soil3_c_vr_acc )
+ deallocate (AKX_soil3_to_soil1_c_vr_acc )
+ deallocate (AKX_met_exit_c_vr_acc )
+ deallocate (AKX_cel_exit_c_vr_acc )
+ deallocate (AKX_lig_exit_c_vr_acc )
+ deallocate (AKX_cwd_exit_c_vr_acc )
+ deallocate (AKX_soil1_exit_c_vr_acc )
+ deallocate (AKX_soil2_exit_c_vr_acc )
+ deallocate (AKX_soil3_exit_c_vr_acc )
+
+ deallocate (decomp0_npools_vr )
+ deallocate (I_met_n_vr_acc )
+ deallocate (I_cel_n_vr_acc )
+ deallocate (I_lig_n_vr_acc )
+ deallocate (I_cwd_n_vr_acc )
+ deallocate (AKX_met_to_soil1_n_vr_acc )
+ deallocate (AKX_cel_to_soil1_n_vr_acc )
+ deallocate (AKX_lig_to_soil2_n_vr_acc )
+ deallocate (AKX_soil1_to_soil2_n_vr_acc )
+ deallocate (AKX_cwd_to_cel_n_vr_acc )
+ deallocate (AKX_cwd_to_lig_n_vr_acc )
+ deallocate (AKX_soil1_to_soil3_n_vr_acc )
+ deallocate (AKX_soil2_to_soil1_n_vr_acc )
+ deallocate (AKX_soil2_to_soil3_n_vr_acc )
+ deallocate (AKX_soil3_to_soil1_n_vr_acc )
+ deallocate (AKX_met_exit_n_vr_acc )
+ deallocate (AKX_cel_exit_n_vr_acc )
+ deallocate (AKX_lig_exit_n_vr_acc )
+ deallocate (AKX_cwd_exit_n_vr_acc )
+ deallocate (AKX_soil1_exit_n_vr_acc )
+ deallocate (AKX_soil2_exit_n_vr_acc )
+ deallocate (AKX_soil3_exit_n_vr_acc )
+
+ deallocate (diagVX_c_vr_acc )
+ deallocate (upperVX_c_vr_acc )
+ deallocate (lowerVX_c_vr_acc )
+ deallocate (diagVX_n_vr_acc )
+ deallocate (upperVX_n_vr_acc )
+ deallocate (lowerVX_n_vr_acc )
+
+ !---------------------------------------------------------------------------
+ deallocate (skip_balance_check )
+#ifdef CROP
+ deallocate (cphase )
+ deallocate (vf )
+ deallocate (gddplant )
+ deallocate (gddmaturity)
+ deallocate (hui )
+ deallocate (huiswheat )
+ deallocate (pdcorn )
+ deallocate (pdswheat )
+ deallocate (pdwwheat )
+ deallocate (pdsoybean )
+ deallocate (pdcotton )
+ deallocate (pdrice1 )
+ deallocate (pdrice2 )
+ deallocate (plantdate )
+ deallocate (pdsugarcane)
+ deallocate (manunitro )
+ deallocate (fertnitro_corn )
+ deallocate (fertnitro_swheat )
+ deallocate (fertnitro_wwheat )
+ deallocate (fertnitro_soybean )
+ deallocate (fertnitro_cotton )
+ deallocate (fertnitro_rice1 )
+ deallocate (fertnitro_rice2 )
+ deallocate (fertnitro_sugarcane)
+#endif
+ deallocate (lag_npp )
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_BGCTimeVariables
+
+
+ !---------------------------------------
+ SUBROUTINE WRITE_BGCTimeVariables (file_restart)
+
+!=======================================================================
+! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+!=======================================================================
+
+ USE MOD_Namelist, only: DEF_REST_CompressLevel, DEF_USE_NITRIF
+ USE MOD_LandPatch
+ USE MOD_NetCDFVector
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ ! Local variables
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ CALL ncio_create_file_vector (file_restart, landpatch)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil', nl_soil)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil_full', nl_soil_full)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'ndecomp_pools', ndecomp_pools)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'doy' , 365)
+
+ ! bgc variables
+ CALL ncio_write_vector (file_restart, 'totlitc ', 'patch', landpatch, totlitc )
+ CALL ncio_write_vector (file_restart, 'totvegc ', 'patch', landpatch, totvegc )
+ CALL ncio_write_vector (file_restart, 'totsomc ', 'patch', landpatch, totsomc )
+ CALL ncio_write_vector (file_restart, 'totcwdc ', 'patch', landpatch, totcwdc )
+ CALL ncio_write_vector (file_restart, 'totcolc ', 'patch', landpatch, totcolc )
+ CALL ncio_write_vector (file_restart, 'totlitn ', 'patch', landpatch, totlitn )
+ CALL ncio_write_vector (file_restart, 'totvegn ', 'patch', landpatch, totvegn )
+ CALL ncio_write_vector (file_restart, 'totsomn ', 'patch', landpatch, totsomn )
+ CALL ncio_write_vector (file_restart, 'totcwdn ', 'patch', landpatch, totcwdn )
+ CALL ncio_write_vector (file_restart, 'totcoln ', 'patch', landpatch, totcoln )
+
+ CALL ncio_write_vector (file_restart, 'sminn ', 'patch', landpatch, sminn )
+ CALL ncio_write_vector (file_restart, 'ndep ', 'patch', landpatch, ndep )
+
+ CALL ncio_write_vector (file_restart, 'decomp_cpools_vr ', 'soil_full', nl_soil_full, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, decomp_cpools_vr)
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL ncio_write_vector (file_restart, 'decomp_cpools_vr_Cap ', 'soil_full', nl_soil_full, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, decomp_cpools_vr_Cap)
+ ENDIF
+ CALL ncio_write_vector (file_restart, 'ctrunc_vr ', 'soil' , nl_soil, 'patch', landpatch, ctrunc_vr)
+ CALL ncio_write_vector (file_restart, 'ctrunc_veg ', 'patch', landpatch, ctrunc_veg )
+ CALL ncio_write_vector (file_restart, 'ctrunc_soil ', 'patch', landpatch, ctrunc_soil )
+
+ CALL ncio_write_vector (file_restart, 'altmax ', 'patch', landpatch, altmax )
+ CALL ncio_write_vector (file_restart, 'altmax_lastyear ', 'patch', landpatch, altmax_lastyear )
+ CALL ncio_write_vector (file_restart, 'altmax_lastyear_indx ', 'patch', landpatch, altmax_lastyear_indx )
+
+ CALL ncio_write_vector (file_restart, 'decomp_npools_vr ', 'soil_full', nl_soil_full, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, decomp_npools_vr)
+ CALL ncio_write_vector (file_restart, 'totsoiln_vr ', 'soil' , nl_soil, 'patch', landpatch, totsoiln_vr )
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL ncio_write_vector (file_restart, 'decomp_npools_vr_Cap ', 'soil_full', nl_soil_full, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, decomp_npools_vr_Cap)
+ ENDIF
+ CALL ncio_write_vector (file_restart, 'ntrunc_vr ', 'soil' , nl_soil, 'patch', landpatch, ntrunc_vr )
+ CALL ncio_write_vector (file_restart, 'ntrunc_veg ', 'patch', landpatch, ntrunc_veg )
+ CALL ncio_write_vector (file_restart, 'ntrunc_soil ', 'patch', landpatch, ntrunc_soil )
+ CALL ncio_write_vector (file_restart, 'sminn_vr ', 'soil' , nl_soil, 'patch', landpatch, sminn_vr )
+ CALL ncio_write_vector (file_restart, 'smin_no3_vr ', 'soil' , nl_soil, 'patch', landpatch, smin_no3_vr )
+ CALL ncio_write_vector (file_restart, 'smin_nh4_vr ', 'soil' , nl_soil, 'patch', landpatch, smin_nh4_vr )
+ CALL ncio_write_vector (file_restart, 'lag_npp ', 'patch', landpatch, lag_npp )
+
+ IF(DEF_USE_NITRIF)THEN
+ CALL ncio_write_vector (file_restart, 'tCONC_O2_UNSAT ', 'soil' , nl_soil, 'patch', landpatch, tconc_o2_unsat)
+ CALL ncio_write_vector (file_restart, 'tO2_DECOMP_DEPTH_UNSAT','soil' , nl_soil, 'patch', landpatch, to2_decomp_depth_unsat)
+ ENDIF
+
+ CALL ncio_write_vector (file_restart, 'prec10 ', 'patch', landpatch, prec10 )
+ CALL ncio_write_vector (file_restart, 'prec60 ', 'patch', landpatch, prec60 )
+ CALL ncio_write_vector (file_restart, 'prec365 ', 'patch', landpatch, prec365 )
+ CALL ncio_write_vector (file_restart, 'prec_today ', 'patch', landpatch, prec_today )
+ CALL ncio_write_vector (file_restart, 'prec_daily ', 'doy' , 365, 'patch', landpatch, prec_daily )
+ CALL ncio_write_vector (file_restart, 'tsoi17 ', 'patch', landpatch, tsoi17 )
+ CALL ncio_write_vector (file_restart, 'rh30 ', 'patch', landpatch, rh30 )
+ CALL ncio_write_vector (file_restart, 'accumnstep ', 'patch', landpatch, accumnstep )
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ !---------------SASU variables-----------------------
+ CALL ncio_write_vector (file_restart, 'decomp0_cpools_vr ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, decomp0_cpools_vr )
+ CALL ncio_write_vector (file_restart, 'I_met_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_met_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'I_cel_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_cel_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'I_lig_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_lig_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'I_cwd_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_cwd_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_met_to_soil1_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_met_to_soil1_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cel_to_soil1_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cel_to_soil1_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_lig_to_soil2_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_lig_to_soil2_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil1_to_soil2_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil1_to_soil2_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cwd_to_cel_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cwd_to_cel_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cwd_to_lig_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cwd_to_lig_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil1_to_soil3_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil1_to_soil3_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil2_to_soil1_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil2_to_soil1_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil2_to_soil3_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil2_to_soil3_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil3_to_soil1_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil3_to_soil1_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_met_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_met_exit_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cel_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cel_exit_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_lig_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_lig_exit_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cwd_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cwd_exit_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil1_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil1_exit_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil2_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil2_exit_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil3_exit_c_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil3_exit_c_vr_acc )
+
+ CALL ncio_write_vector (file_restart, 'decomp0_npools_vr ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, decomp0_npools_vr )
+ CALL ncio_write_vector (file_restart, 'I_met_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_met_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'I_cel_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_cel_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'I_lig_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_lig_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'I_cwd_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, I_cwd_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_met_to_soil1_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_met_to_soil1_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cel_to_soil1_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cel_to_soil1_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_lig_to_soil2_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_lig_to_soil2_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil1_to_soil2_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil1_to_soil2_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cwd_to_cel_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cwd_to_cel_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cwd_to_lig_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cwd_to_lig_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil1_to_soil3_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil1_to_soil3_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil2_to_soil1_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil2_to_soil1_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil2_to_soil3_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil2_to_soil3_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil3_to_soil1_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil3_to_soil1_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_met_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_met_exit_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cel_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cel_exit_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_lig_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_lig_exit_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_cwd_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_cwd_exit_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil1_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil1_exit_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil2_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil2_exit_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'AKX_soil3_exit_n_vr_acc ', 'soil' , nl_soil, 'patch', landpatch, AKX_soil3_exit_n_vr_acc )
+
+ CALL ncio_write_vector (file_restart, 'diagVX_c_vr_acc ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, diagVX_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'upperVX_c_vr_acc ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, upperVX_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'lowerVX_c_vr_acc ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, lowerVX_c_vr_acc )
+ CALL ncio_write_vector (file_restart, 'diagVX_n_vr_acc ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, diagVX_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'upperVX_n_vr_acc ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, upperVX_n_vr_acc )
+ CALL ncio_write_vector (file_restart, 'lowerVX_n_vr_acc ', 'soil' , nl_soil, 'ndecomp_pools', ndecomp_pools, &
+ 'patch', landpatch, lowerVX_n_vr_acc )
+
+ !----------------------------------------------------
+ ENDIF
+ CALL ncio_write_vector (file_restart, 'skip_balance_check ', 'patch', landpatch, skip_balance_check )
+
+#ifdef CROP
+ CALL ncio_write_vector (file_restart, 'cphase ' , 'patch', landpatch, cphase )
+ CALL ncio_write_vector (file_restart, 'pdcorn ' , 'patch', landpatch, pdcorn , compress)
+ CALL ncio_write_vector (file_restart, 'pdswheat ' , 'patch', landpatch, pdswheat , compress)
+ CALL ncio_write_vector (file_restart, 'pdwwheat ' , 'patch', landpatch, pdwwheat , compress)
+ CALL ncio_write_vector (file_restart, 'pdsoybean ' , 'patch', landpatch, pdsoybean , compress)
+ CALL ncio_write_vector (file_restart, 'pdcotton ' , 'patch', landpatch, pdcotton , compress)
+ CALL ncio_write_vector (file_restart, 'pdrice1 ' , 'patch', landpatch, pdrice1 , compress)
+ CALL ncio_write_vector (file_restart, 'pdrice2 ' , 'patch', landpatch, pdrice2 , compress)
+ CALL ncio_write_vector (file_restart, 'pdsugarcane' , 'patch', landpatch, pdsugarcane, compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_corn ' , 'patch', landpatch, fertnitro_corn , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_swheat ' , 'patch', landpatch, fertnitro_swheat , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_wwheat ' , 'patch', landpatch, fertnitro_wwheat , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_soybean ' , 'patch', landpatch, fertnitro_soybean , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_cotton ' , 'patch', landpatch, fertnitro_cotton , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_rice1 ' , 'patch', landpatch, fertnitro_rice1 , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_rice2 ' , 'patch', landpatch, fertnitro_rice2 , compress)
+ CALL ncio_write_vector (file_restart, 'fertnitro_sugarcane' , 'patch', landpatch, fertnitro_sugarcane, compress)
+#endif
+
+ END SUBROUTINE WRITE_BGCTimeVariables
+
+ !---------------------------------------
+ SUBROUTINE READ_BGCTimeVariables (file_restart)
+
+!=======================================================================
+! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+!=======================================================================
+
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFVector
+#ifdef RangeCheck
+ USE MOD_RangeCheck
+#endif
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+! bgc variables
+ CALL ncio_read_vector (file_restart, 'totlitc ', landpatch, totlitc )
+ CALL ncio_read_vector (file_restart, 'totvegc ', landpatch, totvegc )
+ CALL ncio_read_vector (file_restart, 'totsomc ', landpatch, totsomc )
+ CALL ncio_read_vector (file_restart, 'totcwdc ', landpatch, totcwdc )
+ CALL ncio_read_vector (file_restart, 'totcolc ', landpatch, totcolc )
+ CALL ncio_read_vector (file_restart, 'totlitn ', landpatch, totlitn )
+ CALL ncio_read_vector (file_restart, 'totvegn ', landpatch, totvegn )
+ CALL ncio_read_vector (file_restart, 'totsomn ', landpatch, totsomn )
+ CALL ncio_read_vector (file_restart, 'totcwdn ', landpatch, totcwdn )
+ CALL ncio_read_vector (file_restart, 'totcoln ', landpatch, totcoln )
+
+ CALL ncio_read_vector (file_restart, 'sminn ', landpatch, sminn )
+ CALL ncio_read_vector (file_restart, 'ndep ', landpatch, ndep )
+
+ CALL ncio_read_vector (file_restart, 'decomp_cpools_vr ', nl_soil_full, ndecomp_pools, landpatch, decomp_cpools_vr)
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL ncio_read_vector (file_restart, 'decomp_cpools_vr_Cap ', nl_soil_full, ndecomp_pools, landpatch, decomp_cpools_vr_Cap, defval = 1._r8)
+ ENDIF
+ CALL ncio_read_vector (file_restart, 'ctrunc_vr ', nl_soil, landpatch, ctrunc_vr )
+ CALL ncio_read_vector (file_restart, 'ctrunc_veg ', landpatch, ctrunc_veg )
+ CALL ncio_read_vector (file_restart, 'ctrunc_soil ', landpatch, ctrunc_soil )
+
+ CALL ncio_read_vector (file_restart, 'altmax ', landpatch, altmax )
+ CALL ncio_read_vector (file_restart, 'altmax_lastyear ', landpatch, altmax_lastyear )
+ CALL ncio_read_vector (file_restart, 'altmax_lastyear_indx ', landpatch, altmax_lastyear_indx )
+
+ CALL ncio_read_vector (file_restart, 'decomp_npools_vr ', nl_soil_full, ndecomp_pools, landpatch, decomp_npools_vr)
+ CALL ncio_read_vector (file_restart, 'totsoiln_vr ', nl_soil, landpatch, totsoiln_vr, defval = 1._r8)
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL ncio_read_vector (file_restart, 'decomp_npools_vr_Cap ',nl_soil_full, ndecomp_pools, landpatch, decomp_npools_vr_Cap, defval = 1._r8)
+ ENDIF
+ CALL ncio_read_vector (file_restart, 'ntrunc_vr ', nl_soil, landpatch, ntrunc_vr )
+ CALL ncio_read_vector (file_restart, 'ntrunc_veg ', landpatch, ntrunc_veg )
+ CALL ncio_read_vector (file_restart, 'ntrunc_soil ', landpatch, ntrunc_soil )
+ CALL ncio_read_vector (file_restart, 'sminn_vr ', nl_soil, landpatch, sminn_vr )
+ CALL ncio_read_vector (file_restart, 'smin_no3_vr ', nl_soil, landpatch, smin_no3_vr)
+ CALL ncio_read_vector (file_restart, 'smin_nh4_vr ', nl_soil, landpatch, smin_nh4_vr)
+ CALL ncio_read_vector (file_restart, 'lag_npp ', landpatch, lag_npp, defval =spval )
+
+ IF(DEF_USE_NITRIF)THEN
+ CALL ncio_read_vector (file_restart, 'tCONC_O2_UNSAT ', nl_soil, landpatch, tconc_o2_unsat )
+ CALL ncio_read_vector (file_restart, 'tO2_DECOMP_DEPTH_UNSAT', nl_soil, landpatch, to2_decomp_depth_unsat )
+ ENDIF
+
+ CALL ncio_read_vector (file_restart, 'prec10 ', landpatch, prec10 )
+ CALL ncio_read_vector (file_restart, 'prec60 ', landpatch, prec60 )
+ CALL ncio_read_vector (file_restart, 'prec365 ', landpatch, prec365 )
+ CALL ncio_read_vector (file_restart, 'prec_today ', landpatch, prec_today )
+ CALL ncio_read_vector (file_restart, 'prec_daily ', 365, landpatch, prec_daily)
+ CALL ncio_read_vector (file_restart, 'tsoi17 ', landpatch, tsoi17 )
+ CALL ncio_read_vector (file_restart, 'rh30 ', landpatch, rh30 )
+ CALL ncio_read_vector (file_restart, 'accumnstep ', landpatch, accumnstep )
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ !---------------SASU variables-----------------------
+ CALL ncio_read_vector (file_restart, 'decomp0_cpools_vr ', nl_soil, ndecomp_pools, landpatch, decomp0_cpools_vr, defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'I_met_c_vr_acc ', nl_soil, landpatch, I_met_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'I_cel_c_vr_acc ', nl_soil, landpatch, I_cel_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'I_lig_c_vr_acc ', nl_soil, landpatch, I_lig_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'I_cwd_c_vr_acc ', nl_soil, landpatch, I_cwd_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_met_to_soil1_c_vr_acc ', nl_soil, landpatch, AKX_met_to_soil1_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cel_to_soil1_c_vr_acc ', nl_soil, landpatch, AKX_cel_to_soil1_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_lig_to_soil2_c_vr_acc ', nl_soil, landpatch, AKX_lig_to_soil2_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil1_to_soil2_c_vr_acc ', nl_soil, landpatch, AKX_soil1_to_soil2_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cwd_to_cel_c_vr_acc ', nl_soil, landpatch, AKX_cwd_to_cel_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cwd_to_lig_c_vr_acc ', nl_soil, landpatch, AKX_cwd_to_lig_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil1_to_soil3_c_vr_acc ', nl_soil, landpatch, AKX_soil1_to_soil3_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil2_to_soil1_c_vr_acc ', nl_soil, landpatch, AKX_soil2_to_soil1_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil2_to_soil3_c_vr_acc ', nl_soil, landpatch, AKX_soil2_to_soil3_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil3_to_soil1_c_vr_acc ', nl_soil, landpatch, AKX_soil3_to_soil1_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_met_exit_c_vr_acc ', nl_soil, landpatch, AKX_met_exit_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cel_exit_c_vr_acc ', nl_soil, landpatch, AKX_cel_exit_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_lig_exit_c_vr_acc ', nl_soil, landpatch, AKX_lig_exit_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cwd_exit_c_vr_acc ', nl_soil, landpatch, AKX_cwd_exit_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil1_exit_c_vr_acc ', nl_soil, landpatch, AKX_soil1_exit_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil2_exit_c_vr_acc ', nl_soil, landpatch, AKX_soil2_exit_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil3_exit_c_vr_acc ', nl_soil, landpatch, AKX_soil3_exit_c_vr_acc, defval = 0._r8 )
+
+ CALL ncio_read_vector (file_restart, 'decomp0_npools_vr ', nl_soil, ndecomp_pools, landpatch, decomp0_npools_vr, defval = 1._r8)
+ CALL ncio_read_vector (file_restart, 'I_met_n_vr_acc ', nl_soil, landpatch, I_met_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'I_cel_n_vr_acc ', nl_soil, landpatch, I_cel_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'I_lig_n_vr_acc ', nl_soil, landpatch, I_lig_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'I_cwd_n_vr_acc ', nl_soil, landpatch, I_cwd_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_met_to_soil1_n_vr_acc ', nl_soil, landpatch, AKX_met_to_soil1_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cel_to_soil1_n_vr_acc ', nl_soil, landpatch, AKX_cel_to_soil1_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_lig_to_soil2_n_vr_acc ', nl_soil, landpatch, AKX_lig_to_soil2_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil1_to_soil2_n_vr_acc ', nl_soil, landpatch, AKX_soil1_to_soil2_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cwd_to_cel_n_vr_acc ', nl_soil, landpatch, AKX_cwd_to_cel_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cwd_to_lig_n_vr_acc ', nl_soil, landpatch, AKX_cwd_to_lig_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil1_to_soil3_n_vr_acc ', nl_soil, landpatch, AKX_soil1_to_soil3_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil2_to_soil1_n_vr_acc ', nl_soil, landpatch, AKX_soil2_to_soil1_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil2_to_soil3_n_vr_acc ', nl_soil, landpatch, AKX_soil2_to_soil3_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil3_to_soil1_n_vr_acc ', nl_soil, landpatch, AKX_soil3_to_soil1_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_met_exit_n_vr_acc ', nl_soil, landpatch, AKX_met_exit_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cel_exit_n_vr_acc ', nl_soil, landpatch, AKX_cel_exit_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_lig_exit_n_vr_acc ', nl_soil, landpatch, AKX_lig_exit_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_cwd_exit_n_vr_acc ', nl_soil, landpatch, AKX_cwd_exit_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil1_exit_n_vr_acc ', nl_soil, landpatch, AKX_soil1_exit_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil2_exit_n_vr_acc ', nl_soil, landpatch, AKX_soil2_exit_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'AKX_soil3_exit_n_vr_acc ', nl_soil, landpatch, AKX_soil3_exit_n_vr_acc, defval = 0._r8 )
+
+ CALL ncio_read_vector (file_restart, 'diagVX_c_vr_acc ', nl_soil, ndecomp_pools, landpatch, diagVX_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'upperVX_c_vr_acc ', nl_soil, ndecomp_pools, landpatch, upperVX_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'lowerVX_c_vr_acc ', nl_soil, ndecomp_pools, landpatch, lowerVX_c_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'diagVX_n_vr_acc ', nl_soil, ndecomp_pools, landpatch, diagVX_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'upperVX_n_vr_acc ', nl_soil, ndecomp_pools, landpatch, upperVX_n_vr_acc, defval = 0._r8 )
+ CALL ncio_read_vector (file_restart, 'lowerVX_n_vr_acc ', nl_soil, ndecomp_pools, landpatch, lowerVX_n_vr_acc, defval = 0._r8 )
+ ENDIF
+
+ !----------------------------------------------------
+ CALL ncio_read_vector (file_restart, 'skip_balance_check ', landpatch, skip_balance_check )
+#ifdef CROP
+ CALL ncio_read_vector (file_restart, 'cphase ' , landpatch, cphase )
+ CALL ncio_read_vector (file_restart, 'pdcorn ' , landpatch, pdcorn )
+ CALL ncio_read_vector (file_restart, 'pdswheat ' , landpatch, pdswheat )
+ CALL ncio_read_vector (file_restart, 'pdwwheat ' , landpatch, pdwwheat )
+ CALL ncio_read_vector (file_restart, 'pdsoybean ' , landpatch, pdsoybean )
+ CALL ncio_read_vector (file_restart, 'pdcotton ' , landpatch, pdcotton )
+ CALL ncio_read_vector (file_restart, 'pdrice1 ' , landpatch, pdrice1 )
+ CALL ncio_read_vector (file_restart, 'pdrice2 ' , landpatch, pdrice2 )
+ CALL ncio_read_vector (file_restart, 'pdsugarcane' , landpatch, pdsugarcane)
+ CALL ncio_read_vector (file_restart, 'fertnitro_corn ' , landpatch, fertnitro_corn )
+ CALL ncio_read_vector (file_restart, 'fertnitro_swheat ' , landpatch, fertnitro_swheat )
+ CALL ncio_read_vector (file_restart, 'fertnitro_wwheat ' , landpatch, fertnitro_wwheat )
+ CALL ncio_read_vector (file_restart, 'fertnitro_soybean ' , landpatch, fertnitro_soybean )
+ CALL ncio_read_vector (file_restart, 'fertnitro_cotton ' , landpatch, fertnitro_cotton )
+ CALL ncio_read_vector (file_restart, 'fertnitro_rice1 ' , landpatch, fertnitro_rice1 )
+ CALL ncio_read_vector (file_restart, 'fertnitro_rice2 ' , landpatch, fertnitro_rice2 )
+ CALL ncio_read_vector (file_restart, 'fertnitro_sugarcane' , landpatch, fertnitro_sugarcane)
+#endif
+
+#ifdef RangeCheck
+ CALL check_BGCTimeVariables
+#endif
+
+ END SUBROUTINE READ_BGCTimeVariables
+
+ !---------------------------------------
+#ifdef RangeCheck
+ SUBROUTINE check_BGCTimeVariables ()
+
+ USE MOD_SPMD_Task
+ USE MOD_RangeCheck
+ USE MOD_Namelist, only: DEF_USE_NITRIF, DEF_USE_SASU, DEF_USE_DiagMatrix
+
+ IMPLICIT NONE
+
+! bgc variables
+ CALL check_vector_data ('decomp_cpools_vr ', decomp_cpools_vr )
+ CALL check_vector_data ('decomp_cpools ', decomp_cpools )
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL check_vector_data ('decomp_cpools_vr_Cap',decomp_cpools_vr_Cap)
+ ENDIF
+ CALL check_vector_data ('decomp_k ', decomp_k )
+ CALL check_vector_data ('ctrunc_vr ', ctrunc_vr )
+ CALL check_vector_data ('ctrunc_veg ', ctrunc_veg )
+ CALL check_vector_data ('ctrunc_soil ', ctrunc_soil )
+
+ CALL check_vector_data ('t_scalar ', t_scalar )
+ CALL check_vector_data ('w_scalar ', w_scalar )
+ CALL check_vector_data ('o_scalar ', o_scalar )
+ CALL check_vector_data ('depth_scalar ', depth_scalar )
+
+ ! Soil CN diffusion and advection
+ CALL check_vector_data ('som_adv_coef ', som_adv_coef )
+ CALL check_vector_data ('som_diffus_coef ', som_diffus_coef )
+
+ ! Active Layer
+ CALL check_vector_data ('altmax ', altmax )
+ CALL check_vector_data ('altmax_lastyear ', altmax_lastyear )
+ !CALL check_vector_data ('altmax_lastyear_indx ', altmax_lastyear_indx )
+
+ CALL check_vector_data ('totlitc ', totlitc )
+ CALL check_vector_data ('totvegc ', totvegc )
+ CALL check_vector_data ('totsomc ', totsomc )
+ CALL check_vector_data ('totcwdc ', totcwdc )
+ CALL check_vector_data ('totcolc ', totcolc )
+ CALL check_vector_data ('col_begcb ', col_begcb )
+ CALL check_vector_data ('col_endcb ', col_endcb )
+ CALL check_vector_data ('col_vegbegcb ', col_vegbegcb )
+ CALL check_vector_data ('col_vegendcb ', col_vegendcb )
+ CALL check_vector_data ('col_soilbegcb ', col_soilbegcb )
+ CALL check_vector_data ('col_soilendcb ', col_soilendcb )
+
+ CALL check_vector_data ('totlitn ', totlitn )
+ CALL check_vector_data ('totvegn ', totvegn )
+ CALL check_vector_data ('totsomn ', totsomn )
+ CALL check_vector_data ('totcwdn ', totcwdn )
+ CALL check_vector_data ('totcoln ', totcoln )
+ CALL check_vector_data ('col_begnb ', col_begnb )
+ CALL check_vector_data ('col_endnb ', col_endnb )
+ CALL check_vector_data ('col_vegbegnb ', col_vegbegnb )
+ CALL check_vector_data ('col_vegendnb ', col_vegendnb )
+ CALL check_vector_data ('col_soilbegnb ', col_soilbegnb )
+ CALL check_vector_data ('col_soilendnb ', col_soilendnb )
+ CALL check_vector_data ('col_sminnbegnb ', col_sminnbegnb )
+ CALL check_vector_data ('col_sminnendnb ', col_sminnendnb )
+
+ CALL check_vector_data ('leafc ', leafc )
+ CALL check_vector_data ('leafc_storage ', leafc_storage )
+ CALL check_vector_data ('leafc_xfer ', leafc_xfer )
+ CALL check_vector_data ('frootc ', frootc )
+ CALL check_vector_data ('frootc_storage ', frootc_storage )
+ CALL check_vector_data ('frootc_xfer ', frootc_xfer )
+ CALL check_vector_data ('livestemc ', livestemc )
+ CALL check_vector_data ('livestemc_storage ', livestemc_storage )
+ CALL check_vector_data ('livestemc_xfer ', livestemc_xfer )
+ CALL check_vector_data ('deadstemc ', deadstemc )
+ CALL check_vector_data ('deadstemc_storage ', deadstemc_storage )
+ CALL check_vector_data ('deadstemc_xfer ', deadstemc_xfer )
+ CALL check_vector_data ('livecrootc ', livecrootc )
+ CALL check_vector_data ('livecrootc_storage ', livecrootc_storage )
+ CALL check_vector_data ('livecrootc_xfer ', livecrootc_xfer )
+ CALL check_vector_data ('deadcrootc ', deadcrootc )
+ CALL check_vector_data ('deadcrootc_storage ', deadcrootc_storage )
+ CALL check_vector_data ('deadcrootc_xfer ', deadcrootc_xfer )
+ CALL check_vector_data ('grainc ', grainc )
+ CALL check_vector_data ('grainc_storage ', grainc_storage )
+ CALL check_vector_data ('grainc_xfer ', grainc_xfer )
+ CALL check_vector_data ('xsmrpool ', xsmrpool )
+ CALL check_vector_data ('downreg ', downreg )
+ CALL check_vector_data ('cropprod1c ', cropprod1c )
+ CALL check_vector_data ('cropseedc_deficit ', cropseedc_deficit )
+
+ CALL check_vector_data ('leafn ', leafn )
+ CALL check_vector_data ('leafn_storage ', leafn_storage )
+ CALL check_vector_data ('leafn_xfer ', leafn_xfer )
+ CALL check_vector_data ('frootn ', frootn )
+ CALL check_vector_data ('frootn_storage ', frootn_storage )
+ CALL check_vector_data ('frootn_xfer ', frootn_xfer )
+ CALL check_vector_data ('livestemn ', livestemn )
+ CALL check_vector_data ('livestemn_storage ', livestemn_storage )
+ CALL check_vector_data ('livestemn_xfer ', livestemn_xfer )
+ CALL check_vector_data ('deadstemn ', deadstemn )
+ CALL check_vector_data ('deadstemn_storage ', deadstemn_storage )
+ CALL check_vector_data ('deadstemn_xfer ', deadstemn_xfer )
+ CALL check_vector_data ('livecrootn ', livecrootn )
+ CALL check_vector_data ('livecrootn_storage ', livecrootn_storage )
+ CALL check_vector_data ('livecrootn_xfer ', livecrootn_xfer )
+ CALL check_vector_data ('deadcrootn ', deadcrootn )
+ CALL check_vector_data ('deadcrootn_storage ', deadcrootn_storage )
+ CALL check_vector_data ('deadcrootn_xfer ', deadcrootn_xfer )
+ CALL check_vector_data ('grainn ', grainn )
+ CALL check_vector_data ('grainn_storage ', grainn_storage )
+ CALL check_vector_data ('grainn_xfer ', grainn_xfer )
+ CALL check_vector_data ('retransn ', retransn )
+
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL check_vector_data ('leafcCap ', leafcCap )
+ CALL check_vector_data ('leafc_storageCap ', leafc_storageCap )
+ CALL check_vector_data ('leafc_xferCap ', leafc_xferCap )
+ CALL check_vector_data ('frootcCap ', frootcCap )
+ CALL check_vector_data ('frootc_storageCap ', frootc_storageCap )
+ CALL check_vector_data ('frootc_xferCap ', frootc_xferCap )
+ CALL check_vector_data ('livestemcCap ', livestemcCap )
+ CALL check_vector_data ('livestemc_storageCap ', livestemc_storageCap )
+ CALL check_vector_data ('livestemc_xferCap ', livestemc_xferCap )
+ CALL check_vector_data ('deadstemcCap ', deadstemcCap )
+ CALL check_vector_data ('deadstemc_storageCap ', deadstemc_storageCap )
+ CALL check_vector_data ('deadstemc_xferCap ', deadstemc_xferCap )
+ CALL check_vector_data ('livecrootcCap ', livecrootcCap )
+ CALL check_vector_data ('livecrootc_storageCap ', livecrootc_storageCap )
+ CALL check_vector_data ('livecrootc_xferCap ', livecrootc_xferCap )
+ CALL check_vector_data ('deadcrootcCap ', deadcrootcCap )
+ CALL check_vector_data ('deadcrootc_storageCap ', deadcrootc_storageCap )
+ CALL check_vector_data ('deadcrootc_xferCap ', deadcrootc_xferCap )
+
+ CALL check_vector_data ('leafnCap ', leafnCap )
+ CALL check_vector_data ('leafn_storageCap ', leafn_storageCap )
+ CALL check_vector_data ('leafn_xferCap ', leafn_xferCap )
+ CALL check_vector_data ('frootnCap ', frootnCap )
+ CALL check_vector_data ('frootn_storageCap ', frootn_storageCap )
+ CALL check_vector_data ('frootn_xferCap ', frootn_xferCap )
+ CALL check_vector_data ('livestemnCap ', livestemnCap )
+ CALL check_vector_data ('livestemn_storageCap ', livestemn_storageCap )
+ CALL check_vector_data ('livestemn_xferCap ', livestemn_xferCap )
+ CALL check_vector_data ('deadstemnCap ', deadstemnCap )
+ CALL check_vector_data ('deadstemn_storageCap ', deadstemn_storageCap )
+ CALL check_vector_data ('deadstemn_xferCap ', deadstemn_xferCap )
+ CALL check_vector_data ('livecrootnCap ', livecrootnCap )
+ CALL check_vector_data ('livecrootn_storageCap ', livecrootn_storageCap )
+ CALL check_vector_data ('livecrootn_xferCap ', livecrootn_xferCap )
+ CALL check_vector_data ('deadcrootnCap ', deadcrootnCap )
+ CALL check_vector_data ('deadcrootn_storageCap ', deadcrootn_storageCap )
+ CALL check_vector_data ('deadcrootn_xferCap ', deadcrootn_xferCap )
+
+ ENDIF
+
+ CALL check_vector_data ('decomp_npools_vr ', decomp_npools_vr )
+ CALL check_vector_data ('decomp_npools ', decomp_npools )
+ CALL check_vector_data ('totsoiln_vr ', totsoiln_vr )
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL check_vector_data ('decomp_npools_vr_Cap ',decomp_npools_vr_Cap )
+ ENDIF
+ CALL check_vector_data ('ntrunc_vr ', ntrunc_vr )
+ CALL check_vector_data ('ntrunc_veg ', ntrunc_veg )
+ CALL check_vector_data ('ntrunc_soil ', ntrunc_soil )
+
+ CALL check_vector_data ('sminn_vr ', sminn_vr )
+ CALL check_vector_data ('smin_no3_vr ', smin_no3_vr )
+ CALL check_vector_data ('smin_nh4_vr ', smin_nh4_vr )
+
+ IF(DEF_USE_NITRIF)THEN
+ CALL check_vector_data ('tCONC_O2_UNSAT ', tconc_o2_unsat )
+ CALL check_vector_data ('tO2_DECOMP_DEPTH_UNSAT ', to2_decomp_depth_unsat)
+ ENDIF
+
+ CALL check_vector_data ('sminn ', sminn )
+ CALL check_vector_data ('ndep ', ndep )
+
+ CALL check_vector_data ('ndep_prof ', ndep_prof )
+ CALL check_vector_data ('nfixation_prof ', nfixation_prof )
+
+ CALL check_vector_data ('cn_decomp_pools ', cn_decomp_pools )
+ CALL check_vector_data ('fpi_vr ', fpi_vr )
+ CALL check_vector_data ('fpi ', fpi )
+ CALL check_vector_data ('fpg ', fpg )
+
+ CALL check_vector_data ('cropf ', cropf )
+ CALL check_vector_data ('lfwt ', lfwt )
+ CALL check_vector_data ('fuelc ', fuelc )
+ CALL check_vector_data ('fuelc_crop ', fuelc_crop )
+ CALL check_vector_data ('fsr ', fsr )
+ CALL check_vector_data ('fd ', fd )
+ CALL check_vector_data ('rootc ', rootc )
+ CALL check_vector_data ('lgdp ', lgdp )
+ CALL check_vector_data ('lgdp1 ', lgdp1 )
+ CALL check_vector_data ('lpop ', lpop )
+ CALL check_vector_data ('wtlf ', wtlf )
+ CALL check_vector_data ('trotr1 ', trotr1 )
+ CALL check_vector_data ('trotr2 ', trotr2 )
+ CALL check_vector_data ('hdm_lf ', hdm_lf )
+ CALL check_vector_data ('lnfm ', lnfm )
+ CALL check_vector_data ('baf_crop ', baf_crop )
+ CALL check_vector_data ('baf_peatf ', baf_peatf )
+ CALL check_vector_data ('farea_burned ', farea_burned )
+ CALL check_vector_data ('nfire ', nfire )
+ CALL check_vector_data ('fsat ', fsat )
+ CALL check_vector_data ('prec10 ', prec10 )
+ CALL check_vector_data ('prec60 ', prec60 )
+ CALL check_vector_data ('prec365 ', prec365 )
+ CALL check_vector_data ('prec_today ', prec_today )
+ CALL check_vector_data ('prec_daily ', prec_daily )
+ CALL check_vector_data ('wf2 ', wf2 )
+ CALL check_vector_data ('tsoi17 ', tsoi17 )
+ CALL check_vector_data ('rh30 ', rh30 )
+ CALL check_vector_data ('accumnstep ', accumnstep )
+
+ CALL check_vector_data ('dayl ', dayl )
+ CALL check_vector_data ('prev_dayl ', prev_dayl )
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ !--------------SASU variables---------------------------
+ CALL check_vector_data ('decomp0_cpools_vr ', decomp0_cpools_vr )
+ CALL check_vector_data ('I_met_c_vr_acc ', I_met_c_vr_acc )
+ CALL check_vector_data ('I_cel_c_vr_acc ', I_cel_c_vr_acc )
+ CALL check_vector_data ('I_lig_c_vr_acc ', I_lig_c_vr_acc )
+ CALL check_vector_data ('I_cwd_c_vr_acc ', I_cwd_c_vr_acc )
+ CALL check_vector_data ('AKX_met_to_soil1_c_vr_acc ', AKX_met_to_soil1_c_vr_acc )
+ CALL check_vector_data ('AKX_cel_to_soil1_c_vr_acc ', AKX_cel_to_soil1_c_vr_acc )
+ CALL check_vector_data ('AKX_lig_to_soil2_c_vr_acc ', AKX_lig_to_soil2_c_vr_acc )
+ CALL check_vector_data ('AKX_soil1_to_soil2_c_vr_acc ', AKX_soil1_to_soil2_c_vr_acc )
+ CALL check_vector_data ('AKX_cwd_to_cel_c_vr_acc ', AKX_cwd_to_cel_c_vr_acc )
+ CALL check_vector_data ('AKX_cwd_to_lig_c_vr_acc ', AKX_cwd_to_lig_c_vr_acc )
+ CALL check_vector_data ('AKX_soil1_to_soil3_c_vr_acc ', AKX_soil1_to_soil3_c_vr_acc )
+ CALL check_vector_data ('AKX_soil2_to_soil1_c_vr_acc ', AKX_soil2_to_soil1_c_vr_acc )
+ CALL check_vector_data ('AKX_soil2_to_soil3_c_vr_acc ', AKX_soil2_to_soil3_c_vr_acc )
+ CALL check_vector_data ('AKX_soil3_to_soil1_c_vr_acc ', AKX_soil3_to_soil1_c_vr_acc )
+ CALL check_vector_data ('AKX_met_exit_c_vr_acc ', AKX_met_exit_c_vr_acc )
+ CALL check_vector_data ('AKX_cel_exit_c_vr_acc ', AKX_cel_exit_c_vr_acc )
+ CALL check_vector_data ('AKX_lig_exit_c_vr_acc ', AKX_lig_exit_c_vr_acc )
+ CALL check_vector_data ('AKX_cwd_exit_c_vr_acc ', AKX_cwd_exit_c_vr_acc )
+ CALL check_vector_data ('AKX_soil1_exit_c_vr_acc ', AKX_soil1_exit_c_vr_acc )
+ CALL check_vector_data ('AKX_soil2_exit_c_vr_acc ', AKX_soil2_exit_c_vr_acc )
+ CALL check_vector_data ('AKX_soil3_exit_c_vr_acc ', AKX_soil3_exit_c_vr_acc )
+
+ CALL check_vector_data ('decomp0_npools_vr ', decomp0_npools_vr )
+ CALL check_vector_data ('I_met_n_vr_acc ', I_met_n_vr_acc )
+ CALL check_vector_data ('I_cel_n_vr_acc ', I_cel_n_vr_acc )
+ CALL check_vector_data ('I_lig_n_vr_acc ', I_lig_n_vr_acc )
+ CALL check_vector_data ('I_cwd_n_vr_acc ', I_cwd_n_vr_acc )
+ CALL check_vector_data ('AKX_met_to_soil1_n_vr_acc ', AKX_met_to_soil1_n_vr_acc )
+ CALL check_vector_data ('AKX_cel_to_soil1_n_vr_acc ', AKX_cel_to_soil1_n_vr_acc )
+ CALL check_vector_data ('AKX_lig_to_soil2_n_vr_acc ', AKX_lig_to_soil2_n_vr_acc )
+ CALL check_vector_data ('AKX_soil1_to_soil2_n_vr_acc ', AKX_soil1_to_soil2_n_vr_acc )
+ CALL check_vector_data ('AKX_cwd_to_cel_n_vr_acc ', AKX_cwd_to_cel_n_vr_acc )
+ CALL check_vector_data ('AKX_cwd_to_lig_n_vr_acc ', AKX_cwd_to_lig_n_vr_acc )
+ CALL check_vector_data ('AKX_soil1_to_soil3_n_vr_acc ', AKX_soil1_to_soil3_n_vr_acc )
+ CALL check_vector_data ('AKX_soil2_to_soil1_n_vr_acc ', AKX_soil2_to_soil1_n_vr_acc )
+ CALL check_vector_data ('AKX_soil2_to_soil3_n_vr_acc ', AKX_soil2_to_soil3_n_vr_acc )
+ CALL check_vector_data ('AKX_soil3_to_soil1_n_vr_acc ', AKX_soil3_to_soil1_n_vr_acc )
+ CALL check_vector_data ('AKX_met_exit_n_vr_acc ', AKX_met_exit_n_vr_acc )
+ CALL check_vector_data ('AKX_cel_exit_n_vr_acc ', AKX_cel_exit_n_vr_acc )
+ CALL check_vector_data ('AKX_lig_exit_n_vr_acc ', AKX_lig_exit_n_vr_acc )
+ CALL check_vector_data ('AKX_cwd_exit_n_vr_acc ', AKX_cwd_exit_n_vr_acc )
+ CALL check_vector_data ('AKX_soil1_exit_n_vr_acc ', AKX_soil1_exit_n_vr_acc )
+ CALL check_vector_data ('AKX_soil2_exit_n_vr_acc ', AKX_soil2_exit_n_vr_acc )
+ CALL check_vector_data ('AKX_soil3_exit_n_vr_acc ', AKX_soil3_exit_n_vr_acc )
+
+ CALL check_vector_data ('diagVX_c_vr_acc ', diagVX_c_vr_acc )
+ CALL check_vector_data ('upperVX_c_vr_acc ', upperVX_c_vr_acc )
+ CALL check_vector_data ('lowerVX_c_vr_acc ', lowerVX_c_vr_acc )
+ CALL check_vector_data ('diagVX_n_vr_acc ', diagVX_n_vr_acc )
+ CALL check_vector_data ('upperVX_n_vr_acc ', upperVX_n_vr_acc )
+ CALL check_vector_data ('lowerVX_n_vr_acc ', lowerVX_n_vr_acc )
+ ! CALL check_vector_data ('skip_balance_check ', skip_balance_check )
+ !------------------------------------------------------
+ ENDIF
+#ifdef CROP
+ CALL check_vector_data ('cphase ' , cphase )
+ CALL check_vector_data ('vf ' , vf )
+ CALL check_vector_data ('hui ' , hui )
+ CALL check_vector_data ('huiswheat ' , huiswheat )
+ CALL check_vector_data ('gddplant ' , gddplant )
+ CALL check_vector_data ('gddmaturity' , gddmaturity)
+ CALL check_vector_data ('pdcorn ' , pdcorn )
+ CALL check_vector_data ('pdswheat ' , pdswheat )
+ CALL check_vector_data ('pdwwheat ' , pdwwheat )
+ CALL check_vector_data ('pdsoybean ' , pdsoybean )
+ CALL check_vector_data ('pdcotton ' , pdcotton )
+ CALL check_vector_data ('pdrice1 ' , pdrice1 )
+ CALL check_vector_data ('pdrice2 ' , pdrice2 )
+ CALL check_vector_data ('plantdate ' , plantdate )
+ CALL check_vector_data ('pdsugarcane' , pdsugarcane)
+ CALL check_vector_data ('manunitro ' , manunitro )
+ CALL check_vector_data ('fertnitro_corn ' , fertnitro_corn )
+ CALL check_vector_data ('fertnitro_swheat ' , fertnitro_swheat )
+ CALL check_vector_data ('fertnitro_wwheat ' , fertnitro_wwheat )
+ CALL check_vector_data ('fertnitro_soybean ' , fertnitro_soybean )
+ CALL check_vector_data ('fertnitro_cotton ' , fertnitro_cotton )
+ CALL check_vector_data ('fertnitro_rice1 ' , fertnitro_rice1 )
+ CALL check_vector_data ('fertnitro_rice2 ' , fertnitro_rice2 )
+ CALL check_vector_data ('fertnitro_sugarcane' , fertnitro_sugarcane)
+#endif
+ CALL check_vector_data ('lag_npp ' , lag_npp )
+
+ END SUBROUTINE check_BGCTimeVariables
+#endif
+
+#endif
+END MODULE MOD_BGC_Vars_TimeVariables
+! ------ EOP --------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNFireBase.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNFireBase.F90
new file mode 100644
index 0000000000..cc4be943a1
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNFireBase.F90
@@ -0,0 +1,421 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNFireBase
+
+!---------------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This MODULE calculate fire-induced vegetation and litter CN transfers flux, the calculation is based on the fire-induced
+! CN loss rates (f). The CN loss rates (f) is calculated from bgc_veg_CNFireLi2016Mod.F90.
+!
+! !REFERENCES:
+! Li, F., Levis, S., and Ward, D. S. 2013a. Quantifying the role of fire in the Earth system - Part 1: Improved global fire
+! modeling in the Community Earth System Model (CESM1). Biogeosciences 10:2293-2314.
+! Li, F., and Lawrence, D. 2017. Role of fire in the global land water budget during the 20th century through changing
+! ecosystems. J. Clim. 30: 1894-1908.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+
+ USE MOD_Precision
+ USE MOD_Const_PFT, only: &
+ cc_leaf , cc_lstem , cc_dstem , cc_other, fm_leaf, fm_lstem, fm_lroot, fm_root, fm_droot, fm_other, &
+ fr_fcel , fr_flig , fr_flab , lf_fcel , lf_flig, lf_flab
+ USE MOD_Vars_TimeInvariants, only: &
+ cmb_cmplt_fact, patchlatr, borealat, is_cwd, is_litter
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ ! decomposition pools & fluxes variables (inout)
+ decomp_cpools_vr, decomp_npools_vr, cropf, farea_burned, baf_crop, baf_peatf, totsomc
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ m_decomp_cpools_to_fire_vr, m_decomp_npools_to_fire_vr, &
+ fire_mortality_to_met_c, fire_mortality_to_cel_c, fire_mortality_to_lig_c, fire_mortality_to_cwdc, &
+ fire_mortality_to_met_n, fire_mortality_to_cel_n, fire_mortality_to_lig_n, fire_mortality_to_cwdn, &
+ somc_fire
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ leafc_p , leafc_storage_p , leafc_xfer_p , frootc_p , frootc_storage_p , frootc_xfer_p , &
+ livestemc_p , livestemc_storage_p , livestemc_xfer_p , deadstemc_p , deadstemc_storage_p , deadstemc_xfer_p , &
+ livecrootc_p, livecrootc_storage_p, livecrootc_xfer_p, deadcrootc_p, deadcrootc_storage_p, deadcrootc_xfer_p, &
+ leafn_p , leafn_storage_p , leafn_xfer_p , frootn_p , frootn_storage_p , frootn_xfer_p , &
+ livestemn_p , livestemn_storage_p , livestemn_xfer_p , deadstemn_p , deadstemn_storage_p , deadstemn_xfer_p , &
+ livecrootn_p, livecrootn_storage_p, livecrootn_xfer_p, deadcrootn_p, deadcrootn_storage_p, deadcrootn_xfer_p, &
+ livecrootn_p, livecrootn_storage_p, livecrootn_xfer_p, deadcrootn_p, deadcrootn_storage_p, deadcrootn_xfer_p, &
+ gresp_xfer_p, gresp_storage_p , retransn_p , &
+ leaf_prof_p , froot_prof_p , croot_prof_p , stem_prof_p
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ m_leafc_to_fire_p , m_leafc_storage_to_fire_p , m_leafc_xfer_to_fire_p , &
+ m_frootc_to_fire_p , m_frootc_storage_to_fire_p , m_frootc_xfer_to_fire_p , &
+ m_livestemc_to_fire_p , m_livestemc_storage_to_fire_p , m_livestemc_xfer_to_fire_p , &
+ m_deadstemc_to_fire_p , m_deadstemc_storage_to_fire_p , m_deadstemc_xfer_to_fire_p , &
+ m_livecrootc_to_fire_p , m_livecrootc_storage_to_fire_p , m_livecrootc_xfer_to_fire_p, &
+ m_deadcrootc_to_fire_p , m_deadcrootc_storage_to_fire_p , m_deadcrootc_xfer_to_fire_p, &
+ m_livestemc_to_deadstemc_fire_p, m_livecrootc_to_deadcrootc_fire_p, &
+ m_gresp_xfer_to_fire_p , m_gresp_storage_to_fire_p , m_retransn_to_fire_p , &
+ m_leafn_to_fire_p , m_leafn_storage_to_fire_p , m_leafn_xfer_to_fire_p , &
+ m_frootn_to_fire_p , m_frootn_storage_to_fire_p , m_frootn_xfer_to_fire_p , &
+ m_livestemn_to_fire_p , m_livestemn_storage_to_fire_p , m_livestemn_xfer_to_fire_p , &
+ m_deadstemn_to_fire_p , m_deadstemn_storage_to_fire_p , m_deadstemn_xfer_to_fire_p , &
+ m_livecrootn_to_fire_p , m_livecrootn_storage_to_fire_p , m_livecrootn_xfer_to_fire_p, &
+ m_deadcrootn_to_fire_p , m_deadcrootn_storage_to_fire_p , m_deadcrootn_xfer_to_fire_p, &
+ m_livestemn_to_deadstemn_fire_p, m_livecrootn_to_deadcrootn_fire_p, &
+
+ m_leafc_to_litter_fire_p , m_leafc_storage_to_litter_fire_p , m_leafc_xfer_to_litter_fire_p , &
+ m_frootc_to_litter_fire_p , m_frootc_storage_to_litter_fire_p , m_frootc_xfer_to_litter_fire_p , &
+ m_livestemc_to_litter_fire_p , m_livestemc_storage_to_litter_fire_p , m_livestemc_xfer_to_litter_fire_p , &
+ m_deadstemc_to_litter_fire_p , m_deadstemc_storage_to_litter_fire_p , m_deadstemc_xfer_to_litter_fire_p , &
+ m_livecrootc_to_litter_fire_p, m_livecrootc_storage_to_litter_fire_p, m_livecrootc_xfer_to_litter_fire_p, &
+ m_deadcrootc_to_litter_fire_p, m_deadcrootc_storage_to_litter_fire_p, m_deadcrootc_xfer_to_litter_fire_p, &
+ m_gresp_xfer_to_litter_fire_p, m_gresp_storage_to_litter_fire_p , m_retransn_to_litter_fire_p , &
+ m_leafn_to_litter_fire_p , m_leafn_storage_to_litter_fire_p , m_leafn_xfer_to_litter_fire_p , &
+ m_frootn_to_litter_fire_p , m_frootn_storage_to_litter_fire_p , m_frootn_xfer_to_litter_fire_p , &
+ m_livestemn_to_litter_fire_p , m_livestemn_storage_to_litter_fire_p , m_livestemn_xfer_to_litter_fire_p , &
+ m_deadstemn_to_litter_fire_p , m_deadstemn_storage_to_litter_fire_p , m_deadstemn_xfer_to_litter_fire_p , &
+ m_livecrootn_to_litter_fire_p, m_livecrootn_storage_to_litter_fire_p, m_livecrootn_xfer_to_litter_fire_p, &
+ m_deadcrootn_to_litter_fire_p, m_deadcrootn_storage_to_litter_fire_p, m_deadcrootn_xfer_to_litter_fire_p
+
+ USE MOD_Vars_PFTimeInvariants, only: pftfrac
+
+ IMPLICIT NONE
+
+ PUBLIC CNFireFluxes
+
+CONTAINS
+
+ SUBROUTINE CNFireFluxes(i,ps,pe,dlat,nl_soil,ndecomp_pools)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: dlat ! latitude (degree)
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ndecomp_pools! number of total soil & litter pools in the decomposition
+
+ ! !LOCAL VARIABLES:
+ integer :: j,l ! indices
+ real(r8):: f
+ real(r8):: mort
+ integer :: ivt, m
+
+ integer, parameter :: lit_fp = 1 ! Pool for liter
+ integer, parameter :: cwd_fp = 2 ! Pool for CWD Course woody debris
+
+
+ DO m = ps, pe
+ IF(cropf(i) < 1.0_r8)THEN
+ ! For non-crop (bare-soil and natural vegetation)
+ f = (farea_burned(i)-baf_crop(i))/(1.0_r8-cropf(i))
+ ELSE
+ ! For crops
+ IF(cropf(i) > 0._r8)THEN
+ f = baf_crop(i) /cropf(i)
+ ELSE
+ f = 0._r8
+ ENDIF
+ ENDIF
+
+ ! apply this rate to the patch state variables to get flux rates
+ ! biomass burning
+ ! carbon fluxes
+ mort = 1._r8
+ m_leafc_to_fire_p(m) = leafc_p(m) * f * cc_leaf(ivt)
+ m_leafc_storage_to_fire_p(m) = leafc_storage_p(m) * f * cc_other(ivt)
+ m_leafc_xfer_to_fire_p(m) = leafc_xfer_p(m) * f * cc_other(ivt)
+ m_livestemc_to_fire_p(m) = livestemc_p(m) * f * cc_lstem(ivt)
+ m_livestemc_storage_to_fire_p(m) = livestemc_storage_p(m) * f * cc_other(ivt)
+ m_livestemc_xfer_to_fire_p(m) = livestemc_xfer_p(m) * f * cc_other(ivt)
+ m_deadstemc_to_fire_p(m) = deadstemc_p(m) * f * cc_dstem(ivt)
+ m_deadstemc_storage_to_fire_p(m) = deadstemc_storage_p(m) * f * cc_other(ivt)
+ m_deadstemc_xfer_to_fire_p(m) = deadstemc_xfer_p(m) * f * cc_other(ivt)
+ m_frootc_to_fire_p(m) = frootc_p(m) * f * 0._r8
+ m_frootc_storage_to_fire_p(m) = frootc_storage_p(m) * f * cc_other(ivt)
+ m_frootc_xfer_to_fire_p(m) = frootc_xfer_p(m) * f * cc_other(ivt)
+ m_livecrootc_to_fire_p(m) = livecrootc_p(m) * f * 0._r8
+ m_livecrootc_storage_to_fire_p(m) = livecrootc_storage_p(m) * f * cc_other(ivt)
+ m_livecrootc_xfer_to_fire_p(m) = livecrootc_xfer_p(m) * f * cc_other(ivt)
+ m_deadcrootc_to_fire_p(m) = deadcrootc_p(m) * f * 0._r8
+ m_deadcrootc_storage_to_fire_p(m) = deadcrootc_storage_p(m) * f* cc_other(ivt)
+ m_deadcrootc_xfer_to_fire_p(m) = deadcrootc_xfer_p(m) * f * cc_other(ivt)
+ m_gresp_storage_to_fire_p(m) = gresp_storage_p(m) * f * cc_other(ivt)
+ m_gresp_xfer_to_fire_p(m) = gresp_xfer_p(m) * f * cc_other(ivt)
+
+
+ ! nitrogen fluxes
+ m_leafn_to_fire_p(m) = leafn_p(m) * f * cc_leaf(ivt)
+ m_leafn_storage_to_fire_p(m) = leafn_storage_p(m) * f * cc_other(ivt)
+ m_leafn_xfer_to_fire_p(m) = leafn_xfer_p(m) * f * cc_other(ivt)
+ m_livestemn_to_fire_p(m) = livestemn_p(m) * f * cc_lstem(ivt)
+ m_livestemn_storage_to_fire_p(m) = livestemn_storage_p(m) * f * cc_other(ivt)
+ m_livestemn_xfer_to_fire_p(m) = livestemn_xfer_p(m) * f * cc_other(ivt)
+ m_deadstemn_to_fire_p(m) = deadstemn_p(m) * f * cc_dstem(ivt)
+ m_deadstemn_storage_to_fire_p(m) = deadstemn_storage_p(m) * f * cc_other(ivt)
+ m_deadstemn_xfer_to_fire_p(m) = deadstemn_xfer_p(m) * f * cc_other(ivt)
+ m_frootn_to_fire_p(m) = frootn_p(m) * f * 0._r8
+ m_frootn_storage_to_fire_p(m) = frootn_storage_p(m) * f * cc_other(ivt)
+ m_frootn_xfer_to_fire_p(m) = frootn_xfer_p(m) * f * cc_other(ivt)
+ m_livecrootn_to_fire_p(m) = livecrootn_p(m) * f * 0._r8
+ m_livecrootn_storage_to_fire_p(m) = livecrootn_storage_p(m) * f * cc_other(ivt)
+ m_livecrootn_xfer_to_fire_p(m) = livecrootn_xfer_p(m) * f * cc_other(ivt)
+ m_deadcrootn_to_fire_p(m) = deadcrootn_p(m) * f * 0._r8
+ m_deadcrootn_xfer_to_fire_p(m) = deadcrootn_xfer_p(m) * f * cc_other(ivt)
+ m_deadcrootn_storage_to_fire_p(m) = deadcrootn_storage_p(m) * f * cc_other(ivt)
+ m_retransn_to_fire_p(m) = retransn_p(m) * f * cc_other(ivt)
+
+ ! mortality due to fire
+ ! carbon pools
+ m_leafc_to_litter_fire_p(m) = leafc_p(m) * f * &
+ (1._r8 - cc_leaf(ivt)) * &
+ fm_leaf(ivt)
+ m_leafc_storage_to_litter_fire_p(m) = leafc_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_leafc_xfer_to_litter_fire_p(m) = leafc_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livestemc_to_litter_fire_p(m) = livestemc_p(m) * f * &
+ (1._r8 - cc_lstem(ivt)) * &
+ fm_droot(ivt)
+ m_livestemc_storage_to_litter_fire_p(m) = livestemc_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livestemc_xfer_to_litter_fire_p(m) = livestemc_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livestemc_to_deadstemc_fire_p(m) = livestemc_p(m) * f * &
+ (1._r8 - cc_lstem(ivt)) * &
+ (fm_lstem(ivt)-fm_droot(ivt))
+ m_deadstemc_to_litter_fire_p(m) = deadstemc_p(m) * f * m * &
+ (1._r8 - cc_dstem(ivt)) * &
+ fm_droot(ivt)
+ m_deadstemc_storage_to_litter_fire_p(m) = deadstemc_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_deadstemc_xfer_to_litter_fire_p(m) = deadstemc_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_frootc_to_litter_fire_p(m) = frootc_p(m) * f * &
+ fm_root(ivt)
+ m_frootc_storage_to_litter_fire_p(m) = frootc_storage_p(m) * f * &
+ (1._r8- cc_other(ivt)) * &
+ fm_other(ivt)
+ m_frootc_xfer_to_litter_fire_p(m) = frootc_xfer_p(m) * f * &
+ (1._r8- cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livecrootc_to_litter_fire_p(m) = livecrootc_p(m) * f * &
+ fm_droot(ivt)
+ m_livecrootc_storage_to_litter_fire_p(m) = livecrootc_storage_p(m) * f * &
+ (1._r8- cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livecrootc_xfer_to_litter_fire_p(m) = livecrootc_xfer_p(m) * f * &
+ (1._r8- cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livecrootc_to_deadcrootc_fire_p(m) = livecrootc_p(m) * f * &
+ (fm_lroot(ivt)-fm_droot(ivt))
+ m_deadcrootc_to_litter_fire_p(m) = deadcrootc_p(m) * f * m * &
+ fm_droot(ivt)
+ m_deadcrootc_storage_to_litter_fire_p(m) = deadcrootc_storage_p(m) * f * &
+ (1._r8- cc_other(ivt)) * &
+ fm_other(ivt)
+ m_deadcrootc_xfer_to_litter_fire_p(m) = deadcrootc_xfer_p(m) * f * &
+ (1._r8- cc_other(ivt)) * &
+ fm_other(ivt)
+ m_gresp_storage_to_litter_fire_p(m) = gresp_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_gresp_xfer_to_litter_fire_p(m) = gresp_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+
+
+ ! nitrogen pools
+ m_leafn_to_litter_fire_p(m) = leafn_p(m) * f * &
+ (1._r8 - cc_leaf(ivt)) * &
+ fm_leaf(ivt)
+ m_leafn_storage_to_litter_fire_p(m) = leafn_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_leafn_xfer_to_litter_fire_p(m) = leafn_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livestemn_to_litter_fire_p(m) = livestemn_p(m) * f * &
+ (1._r8 - cc_lstem(ivt)) * &
+ fm_droot(ivt)
+ m_livestemn_storage_to_litter_fire_p(m) = livestemn_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livestemn_xfer_to_litter_fire_p(m) = livestemn_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livestemn_to_deadstemn_fire_p(m) = livestemn_p(m) * f * &
+ (1._r8 - cc_lstem(ivt)) * &
+ (fm_lstem(ivt)-fm_droot(ivt))
+ m_deadstemn_to_litter_fire_p(m) = deadstemn_p(m) * f * m * &
+ (1._r8 - cc_dstem(ivt)) * &
+ fm_droot(ivt)
+ m_deadstemn_storage_to_litter_fire_p(m) = deadstemn_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_deadstemn_xfer_to_litter_fire_p(m) = deadstemn_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_frootn_to_litter_fire_p(m) = frootn_p(m) * f * &
+ fm_root(ivt)
+ m_frootn_storage_to_litter_fire_p(m) = frootn_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_frootn_xfer_to_litter_fire_p(m) = frootn_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livecrootn_to_litter_fire_p(m) = livecrootn_p(m) * f * &
+ fm_droot(ivt)
+ m_livecrootn_storage_to_litter_fire_p(m) = livecrootn_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livecrootn_xfer_to_litter_fire_p(m) = livecrootn_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_livecrootn_to_deadcrootn_fire_p(m) = livecrootn_p(m) * f * &
+ (fm_lroot(ivt)-fm_droot(ivt))
+ m_deadcrootn_to_litter_fire_p(m) = deadcrootn_p(m) * f * &
+ fm_droot(ivt)
+ m_deadcrootn_storage_to_litter_fire_p(m) = deadcrootn_storage_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_deadcrootn_xfer_to_litter_fire_p(m) = deadcrootn_xfer_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+ m_retransn_to_litter_fire_p(m) = retransn_p(m) * f * &
+ (1._r8 - cc_other(ivt)) * &
+ fm_other(ivt)
+
+ ENDDO ! END of patches loop
+
+ ! fire-induced transfer of carbon and nitrogen pools to litter and cwd
+
+ DO j = 1,nl_soil
+ fire_mortality_to_cwdc (j,i) = 0._r8
+ fire_mortality_to_cwdn (j,i) = 0._r8
+ fire_mortality_to_met_c(j,i) = 0._r8
+ DO m = ps, pe
+ fire_mortality_to_cwdc(j,i) = fire_mortality_to_cwdc(j,i) + &
+ m_deadstemc_to_litter_fire_p(m) * stem_prof_p(j,m) * pftfrac(m)
+ fire_mortality_to_cwdc(j,i) = fire_mortality_to_cwdc(j,i) + &
+ m_deadcrootc_to_litter_fire_p(m) * croot_prof_p(j,m) * pftfrac(m)
+ fire_mortality_to_cwdn(j,i) = fire_mortality_to_cwdn(j,i) + &
+ m_deadstemn_to_litter_fire_p(m) * stem_prof_p(j,m) * pftfrac(m)
+ fire_mortality_to_cwdn(j,i) = fire_mortality_to_cwdn(j,i) + &
+ m_deadcrootn_to_litter_fire_p(m) * croot_prof_p(j,m) * pftfrac(m)
+
+
+ fire_mortality_to_cwdc(j,i) = fire_mortality_to_cwdc(j,i) + &
+ m_livestemc_to_litter_fire_p(m) * stem_prof_p(j,m) * pftfrac(m)
+ fire_mortality_to_cwdc(j,i) = fire_mortality_to_cwdc(j,i) + &
+ m_livecrootc_to_litter_fire_p(m) * croot_prof_p(j,m) * pftfrac(m)
+ fire_mortality_to_cwdn(j,i) = fire_mortality_to_cwdn(j,i) + &
+ m_livestemn_to_litter_fire_p(m) * stem_prof_p(j,m) * pftfrac(m)
+ fire_mortality_to_cwdn(j,i) = fire_mortality_to_cwdn(j,i) + &
+ m_livecrootn_to_litter_fire_p(m) * croot_prof_p(j,m) * pftfrac(m)
+
+
+ fire_mortality_to_met_c(j,i)=fire_mortality_to_met_c(j,i) &
+ +((m_leafc_to_litter_fire_p(m)*lf_flab(ivt) &
+ + m_leafc_storage_to_litter_fire_p(m) &
+ + m_leafc_xfer_to_litter_fire_p(m) &
+ + m_gresp_storage_to_litter_fire_p(m) &
+ + m_gresp_xfer_to_litter_fire_p(m)) * leaf_prof_p(j,m) &
+ + (m_frootc_to_litter_fire_p(m)*fr_flab(ivt) &
+ + m_frootc_storage_to_litter_fire_p(m) &
+ + m_frootc_xfer_to_litter_fire_p(m)) * froot_prof_p(j,m) &
+ + (m_livestemc_storage_to_litter_fire_p(m) &
+ + m_livestemc_xfer_to_litter_fire_p(m) &
+ + m_deadstemc_storage_to_litter_fire_p(m) &
+ + m_deadstemc_xfer_to_litter_fire_p(m)) * stem_prof_p(j,m) &
+ + (m_livecrootc_storage_to_litter_fire_p(m) &
+ + m_livecrootc_xfer_to_litter_fire_p(m) &
+ + m_deadcrootc_storage_to_litter_fire_p(m) &
+ + m_deadcrootc_xfer_to_litter_fire_p(m)) * croot_prof_p(j,m)) * pftfrac(m)
+ fire_mortality_to_cel_c(j,i)=fire_mortality_to_cel_c(j,i) &
+ + (m_leafc_to_litter_fire_p(m)*lf_fcel(ivt)*leaf_prof_p(j,m) &
+ + m_frootc_to_litter_fire_p(m)*fr_fcel(ivt)*froot_prof_p(j,m)) * pftfrac(m)
+ fire_mortality_to_lig_c(j,i)=fire_mortality_to_lig_c(j,i) &
+ + (m_leafc_to_litter_fire_p(m)*lf_flig(ivt)*leaf_prof_p(j,m) &
+ + m_frootc_to_litter_fire_p(m)*fr_flig(ivt)*froot_prof_p(j,m)) * pftfrac(m)
+
+ fire_mortality_to_met_n(j,i)=fire_mortality_to_met_n(j,i) &
+ + ((m_leafn_to_litter_fire_p(m)*lf_flab(ivt) &
+ + m_leafn_storage_to_litter_fire_p(m) &
+ + m_leafn_xfer_to_litter_fire_p(m) &
+ + m_retransn_to_litter_fire_p(m)) *leaf_prof_p(j,m) &
+ + (m_frootn_to_litter_fire_p(m)*fr_flab(ivt) &
+ + m_frootn_storage_to_litter_fire_p(m) &
+ + m_frootn_xfer_to_litter_fire_p(m))*froot_prof_p(j,m) &
+ + (m_livestemn_storage_to_litter_fire_p(m) &
+ + m_livestemn_xfer_to_litter_fire_p(m) &
+ + m_deadstemn_storage_to_litter_fire_p(m) &
+ + m_deadstemn_xfer_to_litter_fire_p(m))* stem_prof_p(j,m)&
+ + (m_livecrootn_storage_to_litter_fire_p(m) &
+ + m_livecrootn_xfer_to_litter_fire_p(m) &
+ + m_deadcrootn_storage_to_litter_fire_p(m) &
+ + m_deadcrootn_xfer_to_litter_fire_p(m)) * croot_prof_p(j,m)) * pftfrac(m)
+ fire_mortality_to_cel_n(j,i)=fire_mortality_to_cel_n(j,i) &
+ + (m_leafn_to_litter_fire_p(m)*lf_fcel(i)*leaf_prof_p(j,m) &
+ + m_frootn_to_litter_fire_p(m)*fr_fcel(i)*froot_prof_p(j,m)) * pftfrac(m)
+ fire_mortality_to_lig_n(j,i)=fire_mortality_to_lig_n(j,i) &
+ + (m_leafn_to_litter_fire_p(m)*lf_flig(i)*leaf_prof_p(j,m) &
+ + m_frootn_to_litter_fire_p(m)*fr_flig(i)*froot_prof_p(j,m)) * pftfrac(m)
+ ENDDO
+ ENDDO
+ !
+ ! vertically-resolved decomposing C/N fire loss
+ ! column loop
+ !
+ DO j = 1, nl_soil
+ ! carbon fluxes
+ DO l = 1, ndecomp_pools
+ IF ( is_litter(l) ) THEN
+ m_decomp_cpools_to_fire_vr(j,l,i) = decomp_cpools_vr(j,l,i) * f * &
+ cmb_cmplt_fact(lit_fp)
+ ENDIF
+ IF ( is_cwd(l) ) THEN
+ m_decomp_cpools_to_fire_vr(j,l,i) = decomp_cpools_vr(j,l,i) * &
+ (f-baf_crop(i)) * cmb_cmplt_fact(cwd_fp)
+ ENDIF
+ ENDDO
+
+ ! nitrogen fluxes
+ DO l = 1, ndecomp_pools
+ IF ( is_litter(l) ) THEN
+ m_decomp_npools_to_fire_vr(j,l,i) = decomp_npools_vr(j,l,i) * f * &
+ cmb_cmplt_fact(lit_fp)
+ ENDIF
+ IF ( is_cwd(l) ) THEN
+ m_decomp_npools_to_fire_vr(j,l,i) = decomp_npools_vr(j,l,i) * &
+ (f-baf_crop(i)) * cmb_cmplt_fact(cwd_fp)
+ ENDIF
+ ENDDO
+
+ ENDDO
+ ! Carbon loss due to peat fires
+ !
+ ! somc_fire is not connected to clm45 soil carbon pool, ie does not decrease
+ ! soil carbon b/c clm45 soil carbon was very low in several peatland grids
+ IF( patchlatr(i) < borealat)THEN
+ somc_fire(i)= totsomc(i)*baf_peatf(i)*6.0_r8/33.9_r8
+ ELSE
+ somc_fire(i)= baf_peatf(i)*2.2e3_r8
+ ENDIF
+
+ ! Fang Li has not added aerosol and trace gas emissions due to fire, yet
+ ! They will be added here in proportion to the carbon emission
+ ! Emission factors differ for various fire types
+
+
+ END SUBROUTINE CNFireFluxes
+
+END MODULE MOD_BGC_Veg_CNFireBase
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNFireLi2016.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNFireLi2016.F90
new file mode 100644
index 0000000000..c2b77e572e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNFireLi2016.F90
@@ -0,0 +1,320 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNFireLi2016
+
+!-------------------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This module calculate burned area of each fire. The burned area is used to calculate fire induced CN loss rates
+! in bgc_veg_CNFireBaseMod.F90
+!
+! !REFERENCES:
+! Li, F., Levis, S., and Ward, D. S. 2013a. Quantifying the role of fire in the Earth system - Part 1: Improved global fire
+! modeling in the Community Earth System Model (CESM1). Biogeosciences 10:2293-2314.
+! Li, F., and Lawrence, D. 2017. Role of fire in the global land water budget during the 20th century through changing
+! ecosystems. J. Clim. 30: 1894-1908.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_TimeManager
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Vars_1DForcing, only: &
+ forc_q, forc_t, forc_psrf, forc_us, forc_vs
+ USE MOD_Const_PFT, only: isshrub, isgrass, isbetr, isbdtr, isbare, iscrop, isnatveg, fd_pft, fsr_pft, rootfr_p
+ USE MOD_Vars_TimeInvariants, only: &
+ i_cwd, occur_hi_gdp_tree, gdp_lf, abm_lf, peatf_lf, &
+ lfuel, ufuel, cropfire_a1, borealat, troplat, non_boreal_peatfire_c, boreal_peatfire_c, rh_low, rh_hgh, &
+ bt_min, bt_max, pot_hmn_ign_counts_alpha, g0_fire, psi0, porsl, bsw
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ USE MOD_Vars_TimeInvariants, only: theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm
+#endif
+ USE MOD_Vars_TimeVariables, only: &
+ decomp_cpools_vr , totlitc , totvegc , cropf , lfwt , fuelc , fuelc_crop , fsr , &
+ fd , rootc , lgdp , lgdp1 , lpop , wtlf , &
+ trotr1 , trotr2 , hdm_lf , lnfm , baf_crop , baf_peatf , &
+ farea_burned , nfire , fsat , prec60 , wf2 , &
+ tsoi17 , rh30 , t_soisno , wliq_soisno
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ burndate_p
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+ USE MOD_BGC_Vars_PFTimeVariables, only: leafc_p , leafc_storage_p , leafc_xfer_p , &
+ frootc_p , frootc_storage_p , frootc_xfer_p , &
+ deadcrootc_p, deadcrootc_storage_p, deadcrootc_xfer_p, &
+ livecrootc_p, livecrootc_storage_p, livecrootc_xfer_p
+ USE MOD_Eroot, only: eroot
+ USE MOD_Qsadv
+
+ IMPLICIT NONE
+
+ PUBLIC CNFireArea
+
+CONTAINS
+
+ SUBROUTINE CNFireArea(i,ps,pe,dlat,nl_soil,idate,dz_soi)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: dlat ! latitude (degree)
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: idate(3) ! current date (year, day of the year, seconds of the day)
+ real(r8),intent(in) :: dz_soi(1:nl_soil) ! thicknesses of each soil layer
+
+ integer :: g,l,c,p,j,fc,fp,kyr, kmo, kda, mcsec ! index variables
+ integer :: ivt
+ real(r8) :: dayspyr ! days per year
+ real(r8) :: fb ! availability of fuel for regs A and C
+ real(r8) :: fhd ! impact of hd on agricultural fire
+ real(r8) :: fgdp ! impact of gdp on agricultural fire
+ real(r8) :: fire_m ! combustability of fuel for fire occurrence
+ real(r8) :: spread_m ! combustability of fuel for fire spread
+ real(r8) :: Lb_lf ! length-to-breadth ratio added by Lifang
+ real(r8) :: lh ! anthro. ignitions (count/km2/hr)
+ real(r8) :: fs ! hd-dependent fires suppression (0-1)
+ real(r8) :: ig ! total ignitions (count/km2/hr)
+ real(r8) :: arh, arh30 !combustability of fuel related to RH and RH30
+ real(r8) :: afuel !weight for arh and arh30
+ real(r8) :: eq
+ real(r8) :: deqdT
+ real(r8) :: qsatq
+ real(r8) :: qsatqdT
+ real(r8) :: forc_rh
+ real(r8) :: rootr(nl_soil)
+ real(r8) :: rresis(nl_soil)
+ real(r8) :: smp_node
+ real(r8) :: s_node
+ real(r8) :: tmp1d(nl_soil)
+ real(r8) :: tmp0d
+ real(r8) :: btran2
+ real(r8) :: btran2_p(ps:pe)
+
+ real(r8),parameter :: secsphr = 3600._r8
+ real(r8),parameter :: secspday = 86400._r8
+ real(r8),parameter :: PI = 4.*atan(1.)
+ integer m
+
+ tsoi17 = forc_t(i) ! Temporarily use air temperature for tsoi17, need to revised later.
+ prec60 = 0 ! Temporarily use 0 for prec60, need to revised later
+ wf2 = 0.5 ! Temporarily set up, need to revise later.
+ fsat = 0 ! Temporarily set up, need to revise later.
+ rh30 = 0 ! Temporarily set up, need to revise later.
+
+ CALL julian2monthday(idate(1),idate(2),kmo,kda)
+
+ DO m = ps, pe
+ CALL eroot(nl_soil,0._r8,porsl(1:,i),&
+#ifdef Campbell_SOIL_MODEL
+ bsw(1:,i),&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r(1:,i), alpha_vgm(1:,i), n_vgm(1:,i), L_vgm(1:,i), sc_vgm(1:,i), fc_vgm(1:,i), &
+#endif
+ psi0(1:,i),rootfr_p(1:,pftclass(m)),dz_soi(1:),&
+ t_soisno(1:,i),wliq_soisno(1:,i),tmp1d,tmp0d,btran2_p(m))
+ btran2 = sum(btran2_p(ps:pe) * pftfrac(m))
+ ENDDO
+ !
+ ! Calculate fraction of crop (cropf_col) and non-crop and non-bare-soil
+ ! vegetation (lfwt) in vegetated column
+ !
+ cropf(i) = 0._r8
+ lfwt (i) = 0._r8
+
+ ! For crop veg types
+ DO m = ps, pe
+ IF( iscrop(pftclass(m)) )THEN
+ cropf(i) = cropf(i) + pftfrac(m)
+ ENDIF
+ ! For natural vegetation (non-crop and non-bare-soil)
+ IF( isnatveg(pftclass(m)))THEN
+ lfwt (i) = lfwt(i) + pftfrac(m)
+ ENDIF
+ ENDDO
+
+ !
+ ! Calculate crop fuel
+ !
+ fuelc_crop(i)=0._r8
+
+ ! For crop PFTs, fuel load includes leaf and litter; only
+ ! column-level litter carbon
+ ! is available, so we use leaf carbon to estimate the
+ ! litter carbon for crop PFTs
+ DO m = ps, pe
+ IF( iscrop(pftclass(m)) .and. sum(leafc_p(ps:pe)*pftfrac(ps:pe)) > 0._r8 )THEN
+ fuelc_crop(i)= fuelc_crop(i) + (leafc_p(m) + leafc_storage_p(m) + leafc_xfer_p(m))*pftfrac(m)/cropf(i) &
+ + totlitc(i)*leafc_p(m)/sum(leafc_p(ps:pe)*pftfrac(ps:pe))*pftfrac(m)/cropf(i)
+ ENDIF
+ ENDDO
+ !
+ ! Calculate noncrop column variables
+ !
+ fsr (i) = 0._r8
+ fd (i) = 0._r8
+ rootc (i) = 0._r8
+ lgdp (i) = 0._r8
+ lgdp1 (i) = 0._r8
+ lpop (i) = 0._r8
+ wtlf (i) = 0._r8
+ trotr1(i) = 0._r8
+ trotr2(i) = 0._r8
+
+ ! Warning : ivt is not initialized.
+ ! For non-crop -- natural vegetation and bare-soil
+ IF( isnatveg(ivt) .or. isbare(ivt) )THEN
+ IF (btran2 <= 1._r8 ) THEN
+ wtlf(i) = 1._r8
+ ENDIF
+
+ IF( isbetr(ivt) )THEN
+ trotr1(i)=1._r8
+ ENDIF
+ IF( isbdtr(ivt) .and. abs(dlat) .lt. troplat)THEN
+ trotr2(i)=1._r8
+ ENDIF
+
+ rootc(i) = rootc(i) + sum((frootc_p(ps:pe) + frootc_storage_p(ps:pe) + &
+ frootc_xfer_p(ps:pe) + deadcrootc_p(ps:pe) + &
+ deadcrootc_storage_p(ps:pe) + deadcrootc_xfer_p(ps:pe) + &
+ livecrootc_p(ps:pe)+livecrootc_storage_p(ps:pe) + &
+ livecrootc_xfer_p(ps:pe)) * pftfrac(ps:pe))
+
+ fsr(i) = fsr_pft(ivt)
+
+ ! all these constants are in Li et al. BG (2012a,b;2013)
+
+ IF( hdm_lf(i) > 0.1_r8 )THEN
+ ! For not bare-soil
+ IF(.not. isbare(ivt) )THEN
+ ! For shrub and grass (crop already excluded above)
+ IF( isshrub(ivt) .or. isgrass(ivt) )THEN !for shurb and grass
+ lgdp(i) = lgdp(i) + (0.1_r8 + 0.9_r8* &
+ exp(-1._r8*PI* &
+ (gdp_lf(i)/8._r8)**0.5_r8))/(1.0_r8-cropf(i))
+ lgdp1(i) = lgdp1(i) + (0.2_r8 + 0.8_r8* &
+ exp(-1._r8*PI* &
+ (gdp_lf(i)/7._r8)))/(1._r8-cropf(i))
+ lpop(i) = lpop(i) + (0.2_r8 + 0.8_r8* &
+ exp(-1._r8*PI* &
+ (hdm_lf(i)/450._r8)**0.5_r8))/(1._r8-cropf(i))
+ ELSE ! for trees
+ IF( gdp_lf(i) > 20._r8 )THEN
+ lgdp(i) =lgdp(i)+occur_hi_gdp_tree/(1._r8-cropf(i))
+ lgdp1(i) =lgdp1(i)+0.62_r8/(1._r8-cropf(i))
+ ELSE
+ IF( gdp_lf(i) > 8._r8 )THEN
+ lgdp(i)=lgdp(i)+0.79_r8/(1._r8-cropf(i))
+ lgdp1(i)=lgdp1(i)+0.83_r8/(1._r8-cropf(i))
+ ELSE
+ lgdp(i) = lgdp(i)+1._r8/(1._r8-cropf(i))
+ lgdp1(i)=lgdp1(i)+1._r8/(1._r8-cropf(i))
+ ENDIF
+ ENDIF
+ lpop(i) = lpop(i) + (0.4_r8 + 0.6_r8* &
+ exp(-1._r8*PI* &
+ (hdm_lf(i)/125._r8)))/(1._r8-cropf(i))
+ ENDIF
+ ENDIF
+ ELSE
+ lgdp(i) = lgdp(i) + 1._r8/(1._r8-cropf(i))
+ lgdp1(i) = lgdp1(i) + 1._r8/(1._r8-cropf(i))
+ lpop(i) = lpop(i) + 1._r8/(1._r8-cropf(i))
+ ENDIF
+
+ fd(i) = fd_pft(ivt) * secsphr / (1.0_r8-cropf(i))
+ ENDIF
+ !
+ ! calculate burned area fraction in cropland
+ !
+ baf_crop(i)=0._r8
+
+ DO m = ps, pe
+ IF( kmo == 1 .and. kda == 1 .and. idate(3) == 0 )THEN
+ burndate_p(m) = 10000 ! init. value; actual range [0 365]
+ ENDIF
+ ENDDO
+
+ ! For crop
+ DO m = ps, pe
+ IF( forc_t(i) >= tfrz .and. iscrop(ivt) .and. &
+ kmo == abm_lf(i) .and. burndate_p(m) >= 999)THEN ! catch crop burn time
+
+ ! calculate human density impact on ag. fire
+ fhd = 0.04_r8+0.96_r8*exp(-1._r8*PI*(hdm_lf(i)/350._r8)**0.5_r8)
+
+ ! calculate impact of GDP on ag. fire
+ fgdp = 0.01_r8+0.99_r8*exp(-1._r8*PI*(gdp_lf(i)/10._r8))
+
+ ! calculate burned area
+ fb = max(0.0_r8,min(1.0_r8,(fuelc_crop(i)-lfuel)/(ufuel-lfuel)))
+
+ ! crop fire only for generic crop types at this time
+ ! managed crops are treated as grasses IF crop model is turned on
+ baf_crop(i) = baf_crop(i) + cropfire_a1/secsphr*fhd*fgdp
+ IF( fb*fhd*fgdp > 0._r8)THEN
+ burndate_p(m) = kda
+ ENDIF
+ ENDIF
+ ENDDO
+
+ !
+ ! calculate peatland fire
+ !
+ IF(dlat < borealat )THEN
+ baf_peatf(i) = non_boreal_peatfire_c/secsphr*max(0._r8, &
+ min(1._r8,(4.0_r8-prec60(i)*secspday)/ &
+ 4.0_r8))**2*peatf_lf(i)*(1._r8-fsat(i))
+ ELSE
+ baf_peatf(i) = boreal_peatfire_c/secsphr*exp(-PI*(max(wf2(i),0._r8)/0.3_r8))* &
+ max(0._r8,min(1._r8,(tsoi17(i)-tfrz)/10._r8))*peatf_lf(i)* &
+ (1._r8-fsat(i))
+ ENDIF
+ !
+ ! calculate other fires
+ !
+
+ CALL qsadv(forc_t(i),forc_psrf(i),eq,deqdT,qsatq,qsatqdT)
+ forc_rh = forc_q(i) / eq
+
+ IF( cropf(i) < 1._r8 )THEN
+ fuelc(i) = totlitc(i)+totvegc(i)-rootc(i)-fuelc_crop(i)*cropf(i)
+ DO j = 1, nl_soil
+ fuelc(i) = fuelc(i)+decomp_cpools_vr(j,i_cwd,i) * dz_soi(j)
+ ENDDO
+ fuelc(i) = fuelc(i)/(1._r8-cropf(i))
+ fb = max(0.0_r8,min(1.0_r8,(fuelc(i)-lfuel)/(ufuel-lfuel)))
+ IF (trotr1(i)+trotr2(i)<=0.6_r8) THEN
+ afuel =min(1._r8,max(0._r8,(fuelc(i)-2500._r8)/(5000._r8-2500._r8)))
+ arh=1._r8-max(0._r8, min(1._r8,(forc_rh-rh_low)/(rh_hgh-rh_low)))
+ arh30=1._r8-max(0.7_r8, min(1._r8,rh30(i)/90._r8))
+ IF (forc_rh < rh_hgh.and. wtlf(i) > 0._r8 .and. tsoi17(i)> tfrz)THEN
+ fire_m = ((afuel*arh30+(1._r8-afuel)*arh)**1.5_r8)*((1._r8 -max(0._r8,&
+ min(1._r8,(btran2/wtlf(i)-bt_min)/(bt_max-bt_min))))**0.5_r8)
+ ELSE
+ fire_m = 0._r8
+ ENDIF
+ lh = pot_hmn_ign_counts_alpha*6.8_r8*hdm_lf(i)**(0.43_r8)/30._r8/24._r8
+ fs = 1._r8-(0.01_r8+0.98_r8*exp(-0.025_r8*hdm_lf(i)))
+ ig = (lh+lnfm(i)/(5.16_r8+2.16_r8*cos(PI/180._r8*3*min(60._r8,abs(dlat/PI*180))))*0.22_r8) &
+ *(1._r8-fs)*(1._r8-cropf(i))
+ nfire(i) = ig/secsphr*fb*fire_m*lgdp(i) !fire counts/km2/sec
+ Lb_lf = 1._r8+10._r8*(1._r8-EXP(-0.06_r8*sqrt(forc_us(i)*forc_us(i)+forc_vs(i)*forc_vs(i))))
+ spread_m = fire_m**0.5_r8
+ farea_burned(i) = min(1._r8,(g0_fire*spread_m*fsr(i)* &
+ fd(i)/1000._r8)**2*lgdp1(i)* &
+ lpop(i)*nfire(i)*PI*Lb_lf+ &
+ baf_crop(i)+baf_peatf(i)) ! fraction (0-1) per sec
+ ELSE
+ farea_burned(i)=min(1._r8,baf_crop(i)+baf_peatf(i))
+ ENDIF
+ ELSE
+ farea_burned(i) = min(1._r8,baf_crop(i)+baf_peatf(i))
+ ENDIF
+ END SUBROUTINE CNFireArea
+
+END MODULE MOD_BGC_Veg_CNFireLi2016
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNGResp.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNGResp.F90
new file mode 100644
index 0000000000..9fcc35bb6d
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNGResp.F90
@@ -0,0 +1,139 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNGResp
+
+!-----------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This module calculate growth respiration rate.
+!
+! !REFERENCES:
+! Atkin, O.K., Bahar, N.H., Bloomfield, K.J., Griffin, K.L., Heskel, M.A., Huntingford, C., de la Torre, A.M.
+! and Turnbull, M.H., 2017. Leaf respiration in terrestrial biosphere models. Plant respiration: metabolic
+! fluxes and carbon balance, pp.107-142.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Const_PFT, only: &
+ grperc, grpnow, woody
+
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ cpool_to_leafc_p , cpool_to_leafc_storage_p , leafc_xfer_to_leafc_p , &
+ cpool_to_frootc_p , cpool_to_frootc_storage_p , frootc_xfer_to_frootc_p , &
+ cpool_to_livestemc_p , cpool_to_livestemc_storage_p , livestemc_xfer_to_livestemc_p , &
+ cpool_to_deadstemc_p , cpool_to_deadstemc_storage_p , deadstemc_xfer_to_deadstemc_p , &
+ cpool_to_livecrootc_p, cpool_to_livecrootc_storage_p, livecrootc_xfer_to_livecrootc_p, &
+ cpool_to_deadcrootc_p, cpool_to_deadcrootc_storage_p, deadcrootc_xfer_to_deadcrootc_p, &
+ cpool_to_grainc_p , cpool_to_grainc_storage_p , grainc_xfer_to_grainc_p , &
+ cpool_leaf_gr_p , cpool_leaf_storage_gr_p , transfer_leaf_gr_p , &
+ cpool_froot_gr_p , cpool_froot_storage_gr_p , transfer_froot_gr_p , &
+ cpool_livestem_gr_p , cpool_livestem_storage_gr_p , transfer_livestem_gr_p , &
+ cpool_deadstem_gr_p , cpool_deadstem_storage_gr_p , transfer_deadstem_gr_p , &
+ cpool_livecroot_gr_p , cpool_livecroot_storage_gr_p , transfer_livecroot_gr_p , &
+ cpool_deadcroot_gr_p , cpool_deadcroot_storage_gr_p , transfer_deadcroot_gr_p , &
+ cpool_grain_gr_p , cpool_grain_storage_gr_p , transfer_grain_gr_p
+
+ IMPLICIT NONE
+
+ PUBLIC CNGResp
+
+CONTAINS
+
+ SUBROUTINE CNGResp(i, ps, pe, npcropmin)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! end pft index
+ integer ,intent(in) :: npcropmin ! first crop pft index
+
+ ! !LOCAL VARIABLES:
+ real(r8):: respfact_leaf
+ real(r8):: respfact_froot
+ real(r8):: respfact_livecroot
+ real(r8):: respfact_livestem
+ real(r8):: respfact_leaf_storage
+ real(r8):: respfact_froot_storage
+ real(r8):: respfact_livecroot_storage
+ real(r8):: respfact_livestem_storage
+ integer :: ivt, m
+
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ respfact_leaf = 1.0_r8
+ respfact_froot = 1.0_r8
+ respfact_livecroot = 1.0_r8
+ respfact_livestem = 1.0_r8
+ respfact_livecroot = 1.0_r8
+ respfact_livestem = 1.0_r8
+ respfact_leaf_storage = 1.0_r8
+ respfact_froot_storage = 1.0_r8
+ respfact_livecroot_storage = 1.0_r8
+ respfact_livestem_storage = 1.0_r8
+ respfact_livecroot_storage = 1.0_r8
+ respfact_livestem_storage = 1.0_r8
+
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ cpool_livestem_gr_p (m) = cpool_to_livestemc_p (m) * grperc(ivt) * respfact_livestem
+
+ cpool_livestem_storage_gr_p (m) = cpool_to_livestemc_storage_p (m) * grperc(ivt) * grpnow(ivt) * respfact_livestem_storage
+
+ transfer_livestem_gr_p (m) = livestemc_xfer_to_livestemc_p (m) * grperc(ivt) * (1._r8 - grpnow(ivt)) * respfact_livestem_storage
+
+ cpool_grain_gr_p (m) = cpool_to_grainc_p (m) * grperc(ivt)
+
+ cpool_grain_storage_gr_p (m) = cpool_to_grainc_storage_p (m) * grperc(ivt) * grpnow(ivt)
+
+ transfer_grain_gr_p (m) = grainc_xfer_to_grainc_p (m) * grperc(ivt) * (1._r8 - grpnow(ivt))
+ ENDIF
+
+ ! leaf and fine root growth respiration
+ cpool_leaf_gr_p (m) = cpool_to_leafc_p (m) * grperc(ivt) * respfact_leaf
+
+ cpool_leaf_storage_gr_p (m) = cpool_to_leafc_storage_p (m) * grperc(ivt) * grpnow(ivt) * respfact_leaf_storage
+
+ transfer_leaf_gr_p (m) = leafc_xfer_to_leafc_p (m) * grperc(ivt) * (1._r8 - grpnow(ivt)) * respfact_leaf_storage
+
+ cpool_froot_gr_p (m) = cpool_to_frootc_p (m) * grperc(ivt) * respfact_froot
+
+ cpool_froot_storage_gr_p (m) = cpool_to_frootc_storage_p (m) * grperc(ivt) * grpnow(ivt) * respfact_froot_storage
+
+ transfer_froot_gr_p (m) = frootc_xfer_to_frootc_p (m) * grperc(ivt) * (1._r8 - grpnow(ivt)) * respfact_froot_storage
+
+ IF (woody(ivt) == 1._r8) THEN
+ cpool_livestem_gr_p (m) = cpool_to_livestemc_p (m) * grperc(ivt) * respfact_livestem
+
+ cpool_livestem_storage_gr_p (m) = cpool_to_livestemc_storage_p (m) * grperc(ivt) * grpnow(ivt) * respfact_livestem_storage
+
+ transfer_livestem_gr_p (m) = livestemc_xfer_to_livestemc_p (m) * grperc(ivt) * (1._r8 - grpnow(ivt)) * respfact_livestem_storage
+
+ cpool_deadstem_gr_p (m) = cpool_to_deadstemc_p (m) * grperc(ivt)
+
+ cpool_deadstem_storage_gr_p (m) = cpool_to_deadstemc_storage_p (m) * grperc(ivt) * grpnow(ivt)
+
+ transfer_deadstem_gr_p (m) = deadstemc_xfer_to_deadstemc_p (m) * grperc(ivt) * (1._r8 - grpnow(ivt))
+
+ cpool_livecroot_gr_p (m) = cpool_to_livecrootc_p (m) * grperc(ivt) * respfact_livecroot
+
+ cpool_livecroot_storage_gr_p(m) = cpool_to_livecrootc_storage_p (m) * grperc(ivt) * grpnow(ivt) * respfact_livecroot_storage
+
+ transfer_livecroot_gr_p (m) = livecrootc_xfer_to_livecrootc_p(m) * grperc(ivt) * (1._r8 - grpnow(ivt)) * respfact_livecroot_storage
+
+ cpool_deadcroot_gr_p (m) = cpool_to_deadcrootc_p (m) * grperc(ivt)
+
+ cpool_deadcroot_storage_gr_p(m) = cpool_to_deadcrootc_storage_p (m) * grperc(ivt) * grpnow(ivt)
+
+ transfer_deadcroot_gr_p (m) = deadcrootc_xfer_to_deadcrootc_p(m) * grperc(ivt) * (1._r8 - grpnow(ivt))
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CNGResp
+
+END MODULE MOD_BGC_Veg_CNGResp
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNGapMortality.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNGapMortality.F90
new file mode 100644
index 0000000000..b4f22dfb92
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNGapMortality.F90
@@ -0,0 +1,274 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNGapMortality
+
+!---------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This module calculates the CN fluxes from vegetation to litterfall due to gap mortality.
+! The mortality rates are assumed constant for all vegetation function types.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_Const_PFT, only: lf_flab, lf_fcel, lf_flig, fr_flab, fr_fcel, fr_flig
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ ! bgc constants
+ am
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ ! decomposition carbon flux varables (in)
+ gap_mortality_to_met_c, gap_mortality_to_cel_c , &
+ gap_mortality_to_lig_c, gap_mortality_to_cwdc , &
+
+ ! decompositionn nitrogen fluxes variables (inout)
+ gap_mortality_to_met_n, gap_mortality_to_cel_n , &
+ gap_mortality_to_lig_n, gap_mortality_to_cwdn
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ ! vegetation carbon flux variables
+ m_leafc_to_litter_p , m_leafc_storage_to_litter_p , m_leafc_xfer_to_litter_p , &
+ m_frootc_to_litter_p , m_frootc_storage_to_litter_p , m_frootc_xfer_to_litter_p , &
+ m_livestemc_to_litter_p , m_livestemc_storage_to_litter_p , m_livestemc_xfer_to_litter_p , &
+ m_deadstemc_to_litter_p , m_deadstemc_storage_to_litter_p , m_deadstemc_xfer_to_litter_p , &
+ m_livecrootc_to_litter_p , m_livecrootc_storage_to_litter_p, m_livecrootc_xfer_to_litter_p, &
+ m_deadcrootc_to_litter_p , m_deadcrootc_storage_to_litter_p, m_deadcrootc_xfer_to_litter_p, &
+ m_gresp_storage_to_litter_p, m_gresp_xfer_to_litter_p , &
+
+ ! vegetation nitrogen flux variables
+ m_leafn_to_litter_p , m_leafn_storage_to_litter_p , m_leafn_xfer_to_litter_p , &
+ m_frootn_to_litter_p , m_frootn_storage_to_litter_p , m_frootn_xfer_to_litter_p , &
+ m_livestemn_to_litter_p , m_livestemn_storage_to_litter_p , m_livestemn_xfer_to_litter_p , &
+ m_deadstemn_to_litter_p , m_deadstemn_storage_to_litter_p , m_deadstemn_xfer_to_litter_p , &
+ m_livecrootn_to_litter_p , m_livecrootn_storage_to_litter_p, m_livecrootn_xfer_to_litter_p, &
+ m_deadcrootn_to_litter_p , m_deadcrootn_storage_to_litter_p, m_deadcrootn_xfer_to_litter_p, &
+ m_retransn_to_litter_p
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ ! vegetation carbon state variables (inout)
+ leafc_p , leafc_storage_p , leafc_xfer_p , &
+ frootc_p , frootc_storage_p , frootc_xfer_p , &
+ livestemc_p , livestemc_storage_p , livestemc_xfer_p , &
+ deadstemc_p , deadstemc_storage_p , deadstemc_xfer_p , &
+ livecrootc_p , livecrootc_storage_p, livecrootc_xfer_p, &
+ deadcrootc_p , deadcrootc_storage_p, deadcrootc_xfer_p, &
+ gresp_storage_p , gresp_xfer_p , &
+
+ ! vegetation nitrogen state variables (inout)
+ leafn_p , leafn_storage_p , leafn_xfer_p , &
+ frootn_p , frootn_storage_p , frootn_xfer_p , &
+ livestemn_p , livestemn_storage_p , livestemn_xfer_p , &
+ deadstemn_p , deadstemn_storage_p , deadstemn_xfer_p , &
+ livecrootn_p , livecrootn_storage_p, livecrootn_xfer_p, &
+ deadcrootn_p , deadcrootn_storage_p, deadcrootn_xfer_p, &
+ retransn_p , &
+
+ ! profiles
+ leaf_prof_p, stem_prof_p, froot_prof_p, croot_prof_p
+
+ IMPLICIT NONE
+
+ PUBLIC CNGapMortality
+
+ PRIVATE CNGap_VegToLitter
+
+CONTAINS
+
+ SUBROUTINE CNGapMortality(i, ps, pe, nl_soil, npcropmin)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! end pft index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: npcropmin! first crop pft index
+
+ real(r8):: mort ! rate for fractional mortality (1/s)
+ integer :: ivt, m
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+
+ mort = am/(365._r8 * 86400._r8)
+
+ !------------------------------------------------------
+ ! pft-level gap mortality carbon fluxes
+ !------------------------------------------------------
+
+ ! displayed pools
+ m_leafc_to_litter_p (m) = leafc_p (m) * mort
+ m_frootc_to_litter_p (m) = frootc_p (m) * mort
+ m_livestemc_to_litter_p (m) = livestemc_p (m) * mort
+ m_livecrootc_to_litter_p (m) = livecrootc_p (m) * mort
+ m_deadstemc_to_litter_p (m) = deadstemc_p (m) * mort
+ m_deadcrootc_to_litter_p (m) = deadcrootc_p (m) * mort
+
+ ! storage pools
+ m_leafc_storage_to_litter_p (m) = leafc_storage_p (m) * mort
+ m_frootc_storage_to_litter_p (m) = frootc_storage_p (m) * mort
+ m_livestemc_storage_to_litter_p (m) = livestemc_storage_p (m) * mort
+ m_deadstemc_storage_to_litter_p (m) = deadstemc_storage_p (m) * mort
+ m_livecrootc_storage_to_litter_p(m) = livecrootc_storage_p(m) * mort
+ m_deadcrootc_storage_to_litter_p(m) = deadcrootc_storage_p(m) * mort
+ m_gresp_storage_to_litter_p (m) = gresp_storage_p (m) * mort
+
+ ! transfer pools
+ m_leafc_xfer_to_litter_p (m) = leafc_xfer_p (m) * mort
+ m_frootc_xfer_to_litter_p (m) = frootc_xfer_p (m) * mort
+ m_livestemc_xfer_to_litter_p (m) = livestemc_xfer_p (m) * mort
+ m_deadstemc_xfer_to_litter_p (m) = deadstemc_xfer_p (m) * mort
+ m_livecrootc_xfer_to_litter_p (m) = livecrootc_xfer_p (m) * mort
+ m_deadcrootc_xfer_to_litter_p (m) = deadcrootc_xfer_p (m) * mort
+ m_gresp_xfer_to_litter_p (m) = gresp_xfer_p (m) * mort
+
+ !------------------------------------------------------
+ ! pft-level gap mortality nitrogen fluxes
+ !------------------------------------------------------
+
+ ! displayed pools
+ m_leafn_to_litter_p (m) = leafn_p (m) * mort
+ m_frootn_to_litter_p (m) = frootn_p (m) * mort
+ m_livestemn_to_litter_p (m) = livestemn_p (m) * mort
+ m_livecrootn_to_litter_p (m) = livecrootn_p (m) * mort
+
+ m_deadstemn_to_litter_p (m) = deadstemn_p (m) * mort
+ m_deadcrootn_to_litter_p (m) = deadcrootn_p (m) * mort
+
+ IF (ivt < npcropmin) THEN
+ m_retransn_to_litter_p (m) = retransn_p (m) * mort
+ ENDIF
+
+ ! storage pools
+ m_leafn_storage_to_litter_p (m) = leafn_storage_p (m) * mort
+ m_frootn_storage_to_litter_p (m) = frootn_storage_p (m) * mort
+ m_livestemn_storage_to_litter_p (m) = livestemn_storage_p (m) * mort
+ m_deadstemn_storage_to_litter_p (m) = deadstemn_storage_p (m) * mort
+ m_livecrootn_storage_to_litter_p(m) = livecrootn_storage_p(m) * mort
+ m_deadcrootn_storage_to_litter_p(m) = deadcrootn_storage_p(m) * mort
+
+ ! transfer pools
+ m_leafn_xfer_to_litter_p (m) = leafn_xfer_p (m) * mort
+ m_frootn_xfer_to_litter_p (m) = frootn_xfer_p (m) * mort
+ m_livestemn_xfer_to_litter_p (m) = livestemn_xfer_p (m) * mort
+ m_deadstemn_xfer_to_litter_p (m) = deadstemn_xfer_p (m) * mort
+ m_livecrootn_xfer_to_litter_p (m) = livecrootn_xfer_p (m) * mort
+ m_deadcrootn_xfer_to_litter_p (m) = deadcrootn_xfer_p (m) * mort
+ ENDDO
+
+ CALL CNGap_VegToLitter(i, ps, pe, nl_soil)
+
+ END SUBROUTINE CNGapMortality
+
+ SUBROUTINE CNGap_VegToLitter(i, ps, pe, nl_soil)
+
+ integer ,intent(in) :: i
+ integer ,intent(in) :: ps
+ integer ,intent(in) :: pe
+ integer ,intent(in) :: nl_soil
+
+ integer j,m,ivt
+ real(r8) :: wtcol
+
+ DO j = 1,nl_soil
+ DO m = ps, pe
+ ivt = pftclass(m)
+ wtcol = pftfrac(m)
+
+ ! leaf gap mortality carbon fluxes
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ m_leafc_to_litter_p(m) * lf_flab(ivt) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_cel_c(j,i) = gap_mortality_to_cel_c(j,i) + &
+ m_leafc_to_litter_p(m) * lf_fcel(ivt) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_lig_c(j,i) = gap_mortality_to_lig_c(j,i) + &
+ m_leafc_to_litter_p(m) * lf_flig(ivt) * wtcol * leaf_prof_p(j,m)
+
+ ! fine root gap mortality carbon fluxes
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ m_frootc_to_litter_p(m) * fr_flab(ivt) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_cel_c(j,i) = gap_mortality_to_cel_c(j,i) + &
+ m_frootc_to_litter_p(m) * fr_fcel(ivt) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_lig_c(j,i) = gap_mortality_to_lig_c(j,i) + &
+ m_frootc_to_litter_p(m) * fr_flig(ivt) * wtcol * froot_prof_p(j,m)
+
+ ! wood gap mortality carbon fluxes
+ gap_mortality_to_cwdc(j,i) = gap_mortality_to_cwdc(j,i) + &
+ (m_livestemc_to_litter_p(m) + m_deadstemc_to_litter_p(m)) * wtcol * stem_prof_p(j,m)
+ gap_mortality_to_cwdc(j,i) = gap_mortality_to_cwdc(j,i) + &
+ (m_livecrootc_to_litter_p(m) + m_deadcrootc_to_litter_p(m)) * wtcol * croot_prof_p(j,m)
+
+ ! storage gap mortality carbon fluxes
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ (m_leafc_storage_to_litter_p(m) + m_gresp_storage_to_litter_p(m)) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ m_frootc_storage_to_litter_p(m) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ (m_livestemc_storage_to_litter_p(m) + m_deadstemc_storage_to_litter_p(m)) * wtcol * stem_prof_p(j,m)
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ (m_livecrootc_storage_to_litter_p(m) + m_deadcrootc_storage_to_litter_p(m)) * wtcol * croot_prof_p(j,m)
+
+ ! transfer gap mortality carbon fluxes
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ (m_leafc_xfer_to_litter_p(m) + m_gresp_xfer_to_litter_p(m)) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ m_frootc_xfer_to_litter_p(m) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ (m_livestemc_xfer_to_litter_p(m) + m_deadstemc_xfer_to_litter_p(m)) * wtcol * stem_prof_p(j,m)
+ gap_mortality_to_met_c(j,i) = gap_mortality_to_met_c(j,i) + &
+ (m_livecrootc_xfer_to_litter_p(m) + m_deadcrootc_xfer_to_litter_p(m)) * wtcol * croot_prof_p(j,m)
+
+ ! leaf gap mortality nitrogen fluxes
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_leafn_to_litter_p(m) * lf_flab(ivt) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_cel_n(j,i) = gap_mortality_to_cel_n(j,i) + &
+ m_leafn_to_litter_p(m) * lf_fcel(ivt) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_lig_n(j,i) = gap_mortality_to_lig_n(j,i) + &
+ m_leafn_to_litter_p(m) * lf_flig(ivt) * wtcol * leaf_prof_p(j,m)
+
+ ! fine root litter nitrogen fluxes
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_frootn_to_litter_p(m) * fr_flab(ivt) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_cel_n(j,i) = gap_mortality_to_cel_n(j,i) + &
+ m_frootn_to_litter_p(m) * fr_fcel(ivt) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_lig_n(j,i) = gap_mortality_to_lig_n(j,i) + &
+ m_frootn_to_litter_p(m) * fr_flig(ivt) * wtcol * froot_prof_p(j,m)
+
+ ! wood gap mortality nitrogen fluxes
+ gap_mortality_to_cwdn(j,i) = gap_mortality_to_cwdn(j,i) + &
+ (m_livestemn_to_litter_p(m) + m_deadstemn_to_litter_p(m)) * wtcol * stem_prof_p(j,m)
+ gap_mortality_to_cwdn(j,i) = gap_mortality_to_cwdn(j,i) + &
+ (m_livecrootn_to_litter_p(m) + m_deadcrootn_to_litter_p(m)) * wtcol * croot_prof_p(j,m)
+
+ ! retranslocated N pool gap mortality fluxes
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_retransn_to_litter_p(m) * wtcol * leaf_prof_p(j,m)
+
+ ! storage gap mortality nitrogen fluxes
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_leafn_storage_to_litter_p(m) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_frootn_storage_to_litter_p(m) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ (m_livestemn_storage_to_litter_p(m) + m_deadstemn_storage_to_litter_p(m)) * wtcol * stem_prof_p(j,m)
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ (m_livecrootn_storage_to_litter_p(m) + m_deadcrootn_storage_to_litter_p(m)) * wtcol * croot_prof_p(j,m)
+
+ ! transfer gap mortality nitrogen fluxes
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_leafn_xfer_to_litter_p(m) * wtcol * leaf_prof_p(j,m)
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ m_frootn_xfer_to_litter_p(m) * wtcol * froot_prof_p(j,m)
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ (m_livestemn_xfer_to_litter_p(m) + m_deadstemn_xfer_to_litter_p(m)) * wtcol * stem_prof_p(j,m)
+ gap_mortality_to_met_n(j,i) = gap_mortality_to_met_n(j,i) + &
+ (m_livecrootn_xfer_to_litter_p(m) + m_deadcrootn_xfer_to_litter_p(m)) * wtcol * croot_prof_p(j,m)
+
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE CNGap_VegToLitter
+
+END MODULE MOD_BGC_Veg_CNGapMortality
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNMResp.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNMResp.F90
new file mode 100644
index 0000000000..a1a2dc434b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNMResp.F90
@@ -0,0 +1,119 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNMResp
+
+!-----------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This module calculates plant maintenance respiration
+!
+! !REFERENCES:
+! Atkin OK, Bloomfield KJ, Reich PB, Tjoelker MG, Asner GP, Bonal D et al (2015) Global variability in leaf respiration
+! in relation to climate, plant functional types and leaf traits. New Phytologist 206:614-636
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ Q10,br, br_root
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_Vars_TimeVariables, only: &
+ t_soisno, tref
+ USE MOD_Vars_PFTimeVariables, only: &
+ laisun_p, laisha_p, sigf_p
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ frootn_p, livestemn_p, livecrootn_p, grainn_p
+ USE MOD_Vars_1DPFTFluxes, only: &
+ respc_p
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ leaf_mr_p, froot_mr_p, livestem_mr_p, livecroot_mr_p, grain_mr_p
+ USE MOD_Const_PFT, only: &
+ woody, rootfr_p
+
+ IMPLICIT NONE
+
+ PUBLIC CNMResp
+
+CONTAINS
+
+ SUBROUTINE CNMResp(i, ps, pe, nl_soil, npcropmin)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: npcropmin ! first crop pft index
+
+ ! !LOCAL VARIABLES:
+ integer :: j ! indices
+ integer :: ivt, m
+
+ real(r8):: tc ! temperature correction, 2m air temp (unitless)
+ real(r8):: tcsoi(nl_soil) ! temperature correction by soil layer (unitless)
+
+! base rate for maintenance respiration is from:
+! M. Ryan, 1991. Effects of climate change on plant respiration.
+! Ecological Applications, 1(2), 157-167.
+! Original expression is br = 0.0106 molC/(molN h)
+! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s)
+! set constants
+
+! Peter Thornton: 3/13/09
+! Q10 was originally set to 2.0, an arbitrary choice, but reduced to 1.5 as part of the tuning
+! to improve seasonal CYCLE of atmospheric CO2 concentration in global
+! simulatoins
+
+! column loop to calculate temperature factors in each soil layer
+ DO j=1,nl_soil
+
+ ! calculate temperature corrections for each soil layer, for USE in
+ ! estimating fine root maintenance respiration with depth
+ tcsoi(j) = Q10**((t_soisno(j,i) - 273.15_r8 - 20.0_r8)/10.0_r8)
+ ENDDO
+
+ ! calculate maintenance respiration fluxes in
+ ! gC/m2/s for each of the live plant tissues.
+ ! Leaf and live wood MR
+
+ tc = Q10**((tref(i) - 273.15_r8 - 20.0_r8)/10.0_r8)
+
+ !RF: acclimation of root and stem respiration fluxes
+ ! n.b. we DO not yet know IF this is defensible scientifically (awaiting data analysis)
+ ! turning this on will increase R and decrease productivity in boreal forests, A LOT. :)
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF (sigf_p(m) == 1) THEN
+ leaf_mr_p(m) = respc_p(m) * 12.011_r8
+ ELSE !nosno
+ leaf_mr_p(m) = 0._r8
+ ENDIF
+
+ IF (woody(ivt) == 1) THEN
+ livestem_mr_p (m) = livestemn_p (m)*br*tc
+ livecroot_mr_p(m) = livecrootn_p(m)*br_root*tc
+ ELSE IF (ivt >= npcropmin) THEN
+ livestem_mr_p (m) = livestemn_p (m)*br*tc
+ grain_mr_p (m) = grainn_p (m)*br*tc
+ ENDIF
+ ! soil and patch loop for fine root
+
+ DO j = 1,nl_soil
+
+ ! Fine root MR
+ ! crootfr(j) sums to 1.0 over all soil layers, and
+ ! describes the fraction of root mass for carbon that is in each
+ ! layer. This is used with the layer temperature correction
+ ! to estimate the total fine root maintenance respiration as a
+ ! function of temperature and N content.
+ froot_mr_p(m) = froot_mr_p(m) + frootn_p(m)*br_root*tcsoi(j)*rootfr_p(j,ivt)
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE CNMResp
+
+END MODULE MOD_BGC_Veg_CNMResp
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNNDynamics.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNNDynamics.F90
new file mode 100644
index 0000000000..cdea61366b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNNDynamics.F90
@@ -0,0 +1,193 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNNDynamics
+
+!---------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! This MODULE simulates the plant biological fixation (Cleveland et al., 1999),
+! crop fertilisation (Lawrence et al., 2016, and soy nitrogen fixation (Neitsch et al., 2005).
+!
+! !REFERENCES:
+! Cleveland, C.C., Townsend, A.R., Schimel, D.S., Fisher, H., Howarth, R.W., Hedin, L.O., Perakis, S.S., Latty, E.F.,
+! Von Fischer, J.C., Elseroad, A., and Wasson, M.F. 1999. Global patterns of terrestrial biological nitrogen (N2) fixation
+! in natural ecosystems. Global Biogeochem. Cycles 13:623-645.
+! Lawrence, D.M., Hurtt, G.C., Arneth, A., Brovkin, V., Calvin, K.V., Jones, A.D., Jones, C.D., Lawrence, P.J., de
+! Noblet-Ducoudré, N., Pongratz, J., Seneviratne, S.I., and Shevliakova, E. 2016. The Land USE Model Intercomparison
+! Project (LUMIP) contribution to CMIP6: rationale and experimental design. Geosci. Model Dev. 9:2973-2998.
+! DOI:10.5194/gmd-9-2973-2016.
+! Neitsch, S.L., Arnold, J.G., Kiniry, J.R., and Williams J.R. 2005. Soil and Water Assessment Tool,
+! Theoretical Documentation: Version 2005. Temple, TX. USDA Agricultural Research Service and
+! Texas A&M Blackland Research Center.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+
+ USE MOD_Precision
+
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+ USE MOD_Vars_TimeInvariants, only: porsl, psi0, bsw
+ USE MOD_Vars_TimeVariables, only: h2osoi
+
+ USE MOD_BGC_Vars_1DFluxes, only: fert_to_sminn, soyfixn_to_sminn, nfix_to_sminn
+
+ USE MOD_BGC_Vars_TimeVariables, only: sminn, fpg, lag_npp
+#ifdef CROP
+ USE MOD_BGC_Vars_PFTimeVariables, only: croplive_p, hui_p
+ USE MOD_BGC_Vars_PFTimeVariables, only: fert_p
+#endif
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: plant_ndemand_p, soyfixn_p
+
+ USE MOD_Vars_Global, only: z_soi, dz_soi, spval
+ USE MOD_TimeManager
+ IMPLICIT NONE
+
+ PUBLIC CNNFixation
+#ifdef CROP
+ PUBLIC CNNFert
+ PUBLIC CNSoyfix
+#endif
+
+CONTAINS
+
+ SUBROUTINE CNNFixation(i,idate)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: idate(3) ! current date (year, day of the year, seconds of the day)
+ real(r8) t, dayspyr
+
+ IF(isleapyear(idate(1)))THEN
+ dayspyr = 366
+ ELSE
+ dayspyr = 365
+ ENDIF
+
+ IF (lag_npp(i) /= spval) THEN
+ ! need to put npp in units of gC/m^2/year here first
+ t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * lag_npp(i)*(86400._r8 * dayspyr))))/(86400._r8 * dayspyr)
+ nfix_to_sminn(i) = max(0._r8,t)
+ ELSE
+ nfix_to_sminn(i) = 0._r8
+ ENDIF
+
+ END SUBROUTINE CNNFixation
+
+#ifdef CROP
+ SUBROUTINE CNNFert(i,ps,pe)
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+
+ fert_to_sminn(i) = sum(fert_p(ps:pe))
+
+ END SUBROUTINE CNNFert
+
+ SUBROUTINE CNSoyfix (i, ps, pe, nl_soil)
+ ! GPAM Soybean biological N fixation
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! end pft index
+ integer, intent(in) :: nl_soil ! number of total soil layers
+ real(r8):: fxw,fxn,fxg,fxr ! soil water factor, nitrogen factor, growth stage factor
+ real(r8):: soy_ndemand ! difference between nitrogen supply and demand
+ real(r8):: sminnthreshold1, sminnthreshold2
+ real(r8):: GDDfracthreshold1, GDDfracthreshold2
+ real(r8):: GDDfracthreshold3, GDDfracthreshold4
+ integer m, ivt, j
+ real(r8) :: rwat, swat, rz, watdry, wf, tsw, stsw
+
+ sminnthreshold1 = 30._r8
+ sminnthreshold2 = 10._r8
+ GDDfracthreshold1 = 0.15_r8
+ GDDfracthreshold2 = 0.30_r8
+ GDDfracthreshold3 = 0.55_r8
+ GDDfracthreshold4 = 0.75_r8
+
+ rwat = 0._r8
+ swat = 0._r8
+ rz = 0._r8
+
+ DO j = 1, nl_soil
+ IF (z_soi(j)+0.5_r8*dz_soi(j) <= 0.05_r8) THEN
+ watdry = porsl(j,i) * (316230._r8/(-psi0(j,i))) ** (-1._r8/bsw(j,i))
+ rwat = rwat + (h2osoi(j,i)-watdry) * dz_soi(j)
+ swat = swat + (porsl (j,i)-watdry) * dz_soi(j)
+ rz = rz + dz_soi(j)
+ ENDIF
+ ENDDO
+
+ tsw = rwat/rz
+ stsw = swat/rz
+ IF (rz .gt. 0._r8 .and. stsw .gt. 0._r8) THEN
+ wf = tsw/stsw
+ ELSE
+ wf = 0._r8
+ ENDIF
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF(croplive_p(m) .and. (ivt == 23 .or. ivt == 24 .or. ivt == 77 .or. ivt == 78))THEN
+
+ ! difference between supply and demand
+
+ IF(fpg(i) .lt. 1._r8) THEN
+ soy_ndemand = plant_ndemand_p(m) - plant_ndemand_p(m) * fpg(i)
+
+ ! fixation depends on nitrogen, soil water, and growth stage
+ ! soil water factor
+
+ fxw = wf / 0.85_r8
+
+ ! soil nitrogen factor (Beth says: CHECK UNITS)
+
+ IF (sminn(i) .gt. sminnthreshold1) THEN
+ fxn = 0._r8
+ ELSE IF (sminn(i) > sminnthreshold2 .and. sminn(i) <= sminnthreshold1) THEN
+ fxn = 1.5_r8 - .005_r8 * (sminn(i) * 10._r8)
+ ELSE IF (sminn(i) <= sminnthreshold2) THEN
+ fxn = 1._r8
+ ENDIF
+
+ ! growth stage factor
+
+ IF (hui_p(m) <= GDDfracthreshold1) THEN
+ fxg = 0._r8
+ ELSE IF (hui_p(m) > GDDfracthreshold1 .and. hui_p(m) <= GDDfracthreshold2) THEN
+ fxg = 6.67_r8 * hui_p(m) - 1._r8
+ ELSE IF (hui_p(m) > GDDfracthreshold2 .and. hui_p(m) <= GDDfracthreshold3) THEN
+ fxg = 1._r8
+ ELSE IF (hui_p(m) > GDDfracthreshold3 .and. hui_p(m) <= GDDfracthreshold4) THEN
+ fxg = 3.75_r8 - 5._r8 * hui_p(m)
+ ELSE
+ fxg = 0._r8
+ ENDIF
+
+ ! calculate the nitrogen fixed by the soybean
+
+ fxr = max(0._r8, min(1._r8, fxw, fxn) * fxg)
+ soyfixn_p(m) = min(fxr * soy_ndemand, soy_ndemand)
+
+ ELSE ! IF nitrogen demand met, no fixation
+
+ soyfixn_p(m) = 0._r8
+
+ ENDIF
+
+ ELSE ! IF not live soybean, no fixation
+
+ soyfixn_p(m) = 0._r8
+
+ ENDIF
+ ENDDO
+
+ soyfixn_to_sminn(i) = sum(soyfixn_p(ps:pe)*pftfrac(ps:pe))
+
+ END SUBROUTINE CNSoyfix
+#endif
+
+END MODULE MOD_BGC_Veg_CNNDynamics
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNPhenology.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNPhenology.F90
new file mode 100644
index 0000000000..8513dde698
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNPhenology.F90
@@ -0,0 +1,1615 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNPhenology
+
+!--------------------
+! !DESCRIPTION:
+! This MODULE holds all phenology related subroutines for natural vegetation and crop in the C and N cycle.
+! CoLM Phenology controls the gain and loss of leaf carbon. LAI is then updated from leaf carbon.
+! So, the seasonal variation in LAI can be simulated for different phenology types.
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+! Fang Li, 2022, implemented GPAM crop model in this MODULE.
+!
+! !USES:
+ USE MOD_Const_PFT, only: &
+ isevg , issed , isstd , leaf_long, woody , leafcn , frootcn, livewdcn, deadwdcn, &
+ lflitcn, lf_flab, lf_fcel, lf_flig , fr_flab, fr_fcel, fr_flig, &
+
+ ! crop variables
+ lfemerg, mxmat, grnfill, baset
+
+ USE MOD_BGC_Vars_TimeInvariants, only: &
+ ndays_on , ndays_off , fstor2tran, crit_dayl , crit_onset_fdd, crit_onset_swi, &
+ crit_offset_fdd , crit_offset_swi, soilpsi_on, soilpsi_off, lwtop, rice2pdt
+
+ USE MOD_Vars_Global, only: &
+ !crop variables
+ nswheat , nirrig_swheat , nsugarcane , nirrig_sugarcane , &
+ nwwheat , nirrig_wwheat , ntmp_corn , nirrig_tmp_corn , &
+ ntrp_corn , nirrig_trp_corn , nmiscanthus , nirrig_miscanthus , &
+ nswitchgrass , nirrig_switchgrass, ncotton , nirrig_cotton , &
+ nrice , nirrig_rice , ntmp_soybean, nirrig_tmp_soybean, &
+ ntrp_soybean , nirrig_trp_soybean, &
+ spval
+ USE MOD_Const_Physical, only: tfrz
+
+ USE MOD_Vars_TimeVariables, only: &
+ t_soisno, smp
+
+ USE MOD_BGC_Vars_TimeVariables, only: &
+ dayl, prev_dayl, prec10, prec60, prec365, prec_today, prec_daily, accumnstep
+
+ USE MOD_Vars_PFTimeVariables, only: &
+ tref_p ,tlai_p
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ tempavg_tref_p , annavg_tref_p , gdd0_p , gdd8_p , &
+ gdd10_p , gdd020_p , gdd820_p , gdd1020_p , nyrs_crop_active_p, &
+ bglfr_p , bgtr_p , lgsf_p , offset_flag_p , offset_counter_p , &
+ onset_flag_p , onset_counter_p, onset_gddflag_p, onset_gdd_p , onset_fdd_p , &
+ onset_swi_p , offset_fdd_p , offset_swi_p , dormant_flag_p, &
+
+ prev_leafc_to_litter_p , prev_frootc_to_litter_p , days_active_p , &
+
+ leafc_p , frootc_p , livestemc_p , &
+ livestemn_p , livecrootc_p , grainc_p, grainn_p , &
+
+ leafc_storage_p , frootc_storage_p , livestemc_storage_p , &
+ deadstemc_storage_p, livecrootc_storage_p, deadcrootc_storage_p, &
+ leafn_storage_p , frootn_storage_p , livestemn_storage_p , &
+ deadstemn_storage_p, livecrootn_storage_p, deadcrootn_storage_p, &
+
+ leafc_xfer_p , frootc_xfer_p , livestemc_xfer_p , &
+ deadstemc_xfer_p , livecrootc_xfer_p , deadcrootc_xfer_p , &
+ leafn_xfer_p , frootn_xfer_p , livestemn_xfer_p , &
+ deadstemn_xfer_p , livecrootn_xfer_p , deadcrootn_xfer_p , &
+ gresp_storage_p , &
+
+! crop variables
+#ifdef CROP
+ cropplant_p , idop_p , a5tmin_p , a10tmin_p , t10_p , &
+ cumvd_p , vf_p , cphase_p , fert_counter_p , &
+ croplive_p , gddplant_p , harvdate_p , gddmaturity_p , &
+ hui_p , peaklai_p , &
+ tref_min_p , tref_max_p , tref_min_inst_p , tref_max_inst_p , &
+ manunitro_p , fertnitro_p , plantdate_p , fert_p , &! input from files
+#endif
+
+ leaf_prof_p , froot_prof_p , &
+ cropseedc_deficit_p, cropseedn_deficit_p
+
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ livestemc_to_deadstemc_p , livecrootc_to_deadcrootc_p , &
+
+ leafc_storage_to_xfer_p , frootc_storage_to_xfer_p , &
+ livestemc_storage_to_xfer_p , deadstemc_storage_to_xfer_p , &
+ livecrootc_storage_to_xfer_p , deadcrootc_storage_to_xfer_p , &
+ gresp_storage_to_xfer_p , &
+
+ leafc_xfer_to_leafc_p , frootc_xfer_to_frootc_p , &
+ livestemc_xfer_to_livestemc_p , deadstemc_xfer_to_deadstemc_p , &
+ livecrootc_xfer_to_livecrootc_p, deadcrootc_xfer_to_deadcrootc_p, &
+
+ livestemn_to_deadstemn_p , livecrootn_to_deadcrootn_p , &
+ livestemn_to_retransn_p , livecrootn_to_retransn_p , &
+
+ leafn_storage_to_xfer_p , frootn_storage_to_xfer_p , &
+ livestemn_storage_to_xfer_p , deadstemn_storage_to_xfer_p , &
+ livecrootn_storage_to_xfer_p , deadcrootn_storage_to_xfer_p , &
+
+ leafn_xfer_to_leafn_p , frootn_xfer_to_frootn_p , &
+ livestemn_xfer_to_livestemn_p , deadstemn_xfer_to_deadstemn_p , &
+ livecrootn_xfer_to_livecrootn_p, deadcrootn_xfer_to_deadcrootn_p, &
+ cpool_to_leafc_p , cpool_to_frootc_p , &
+ leafc_to_litter_p , frootc_to_litter_p , &
+ leafn_to_litter_p , frootn_to_litter_p , &
+ leafn_to_retransn_p , &
+
+ crop_seedc_to_leaf_p , crop_seedn_to_leaf_p , &
+ grainc_to_seed_p , grainn_to_seed_p , &
+ grainc_to_food_p , grainn_to_food_p , &
+ cpool_to_grainc_p , npool_to_grainn_p , &
+ livestemc_to_litter_p , livestemn_to_litter_p , &
+ cpool_to_livestemc_p
+
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+
+ USE MOD_BGC_Vars_1DFluxes, only: &
+ phenology_to_met_c , phenology_to_cel_c , phenology_to_lig_c, &
+ phenology_to_met_n , phenology_to_cel_n , phenology_to_lig_n, &
+ grainc_to_cropprodc, grainn_to_cropprodn
+
+ USE MOD_Vars_1DForcing, only: forc_prc, forc_prl
+
+ USE MOD_TimeManager
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_FERT
+ USE MOD_BGC_Daylength, only: daylength
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ PUBLIC CNPhenology
+
+ integer, parameter :: NOT_Planted = 999 ! If not planted yet in year
+ integer, parameter :: NOT_Harvested = 999 ! If not harvested yet in year
+
+CONTAINS
+
+ SUBROUTINE CNPhenology(i,ps,pe,nl_soil,idate,dz_soi,deltim,dlat,npcropmin,phase)
+
+! !DESCRIPTION:
+! The main driver of phenology model. Two phases are included:
+! 1) phase==1: Calculates the phenology-related carbon and nitroge pool size changes,
+! especially when specific phenology trigure is on (eg. leaf onset and offset).
+! The pool size change rates is calculated from phase 2.
+! 2) phase==2: Calculates phenology climatic diagnostics for onset and offset trigures
+! Calculates the pool size change rates of all phenology processes.
+!
+! !
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ IMPLICIT NONE
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: idate(3) ! current date (year, day of the year, seconds of the day)
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dlat ! latitude (degrees)
+ integer ,intent(in) :: npcropmin ! first crop pft index
+ real(r8),intent(in) :: dz_soi(nl_soil)! thicknesses of each soil layer
+ integer ,intent(in) :: phase ! indicator of the SUBROUTINE options (see DESCRIPTION above)
+
+ real(r8) dayspyr
+ integer h ! 1 for north hemsiphere; 2 for south hemisphere
+
+ IF(isleapyear(idate(1)))THEN
+ dayspyr = 366
+ ELSE
+ dayspyr = 365
+ ENDIF
+
+ IF ( phase == 1 ) THEN
+ CALL CNPhenologyClimate (i,ps,pe,idate(1:3),deltim,dayspyr,npcropmin,nl_soil,dz_soi,dlat)
+
+ CALL CNEvergreenPhenology (i,ps,pe,deltim,dayspyr)
+
+ CALL CNSeasonDecidPhenology(i,ps,pe,idate(1:3),deltim,dayspyr,dlat)
+
+ CALL CNStressDecidPhenology(i,ps,pe,deltim,dayspyr)
+
+#ifdef CROP
+ IF(dlat >= 0)THEN
+ h = 1
+ ELSE
+ h = 2
+ ENDIF
+ CALL CropPhenology(i,ps,pe,idate(1:3),h,deltim,dayspyr,npcropmin)
+#endif
+ ELSE IF ( phase == 2 ) THEN
+ ! the same onset and offset routines are called regardless of
+ ! phenology type - they depend only on onset_flag, offset_flag, bglfr, and bgtr
+
+ CALL CNOnsetGrowth(i,ps,pe,deltim)
+
+ CALL CNOffsetLitterfall(i,ps,pe,deltim,npcropmin)
+
+ CALL CNBackgroundLitterfall(i,ps,pe)
+
+ CALL CNLivewoodTurnover(i,ps,pe)
+
+ CALL CNLitterToColumn(i,ps,pe,nl_soil,npcropmin)
+ ELSE
+ write(*,*) 'bad phenology phase'
+ ENDIF
+
+ END SUBROUTINE CNPhenology
+
+ SUBROUTINE CNPhenologyClimate (i,ps,pe,idate,deltim,dayspyr,npcropmin,nl_soil,dz_soi,dlat)
+
+! !DESCRIPTION:
+! This SUBROUTINE summaries climate statistics, such as annual averaged temperature,
+! maximum and minimum temperature, averaged precipitation over recent 10 days, 60 days and 365 days,
+! growing degree days above 0, 8, and 10 degrees celsius. These climate statistics will be
+! used in following phenology simulations.
+!
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ !
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: idate(3) ! current date (year, days of the year, seconds of the day)
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dayspyr ! days per year (days)
+ integer ,intent(in) :: npcropmin! first crop pft index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ real(r8),intent(in) :: dz_soi(nl_soil) ! thicknesses of each soil layer
+ real(r8),intent(in) :: dlat ! latitude (degrees)
+
+ ! !LOCAL VARIABLES:
+ real(r8), parameter :: yravg = 20.0_r8 ! length of years to average for gdd
+ real(r8), parameter :: yravgm1 = yravg-1.0_r8 ! minus 1 of above
+ integer :: m,ivt
+ logical , parameter :: isconst_baset = .true. ! .true. for constant base temperature
+ ! .false. for latidinal varied base temperature
+ real(r8) stepperday, nsteps
+ integer month, mday
+ !-----------------------------------------------------------------------
+
+ ! set time steps
+
+ stepperday = 86400._r8 / deltim
+ DO m = ps , pe
+ tempavg_tref_p(m) = tempavg_tref_p(m) + tref_p(m) * (deltim/86400._r8/dayspyr)
+#ifdef CROP
+ IF(idate(3) .eq. deltim .or. tref_max_inst_p(m) .eq. spval)THEN
+ tref_max_inst_p(m) = tref_p(m)
+ ELSE
+ tref_max_inst_p(m) = max(tref_max_inst_p(m) , tref_p(m))
+ ENDIF
+
+ IF(idate(3) .eq. deltim .or. tref_min_inst_p(m) .eq. spval)THEN
+ tref_min_inst_p(m) = tref_p(m)
+ ELSE
+ tref_min_inst_p(m) = min(tref_min_inst_p(m) , tref_p(m))
+ ENDIF
+ IF(idate(3) .eq. 86400 - nint(deltim))THEN
+ tref_max_p(m) = tref_max_inst_p(m)
+ tref_min_p(m) = tref_min_inst_p(m)
+ ENDIF
+#endif
+ ENDDO
+
+ accumnstep(i) = accumnstep(i) + 1
+ prec_today(i) = forc_prc(i) + forc_prl(i)
+
+ nsteps = amin1(10._r8 * stepperday, accumnstep(i))
+ prec10 (i) = ( prec10 (i) * (nsteps - 1) + prec_today(i) ) / nsteps
+
+ nsteps = amin1(60._r8 * stepperday, accumnstep(i))
+ prec60 (i) = ( prec60 (i) * (nsteps - 1) + prec_today(i) ) / nsteps
+
+ nsteps = amin1(365._r8 * stepperday, accumnstep(i))
+ prec365 (i) = ( prec365(i) * (nsteps - 1) + prec_today(i) ) / nsteps
+
+ CALL julian2monthday(idate(1),idate(2),month,mday)
+ !calculate gdd0,gdd8,gdd10,gddplant for GPAM crop phenology F. Li
+ DO m = ps , pe
+ ivt = pftclass(m)
+ IF(((month .ge. 4 .and. month .le. 9) .and. dlat .ge. 0) .or. &
+ ((month .gt. 9 .or. month .lt. 4) .and. dlat .lt. 0)) THEN
+ gdd0_p (m) = gdd0_p (m) + max(0._r8, tref_p(m) - 273.15) * deltim / 86400._r8
+ gdd8_p (m) = gdd8_p (m) + max(0._r8, tref_p(m) - 273.15 - 8) * deltim / 86400._r8
+ gdd10_p(m) = gdd10_p(m) + max(0._r8, tref_p(m) - 273.15 - 10) * deltim / 86400._r8
+ ENDIF
+#ifdef CROP
+ IF(croplive_p(m))THEN
+ IF((ivt == nwwheat .or. ivt == nirrig_wwheat).and.cphase_p(m) == 2._r8)THEN
+ gddplant_p(m) = gddplant_p(m) +vf_p(m) * max(0._r8, &
+ tref_p(m) - (273.15 + baset(ivt))) * deltim / 86400._r8
+ ELSE
+ gddplant_p(m) = gddplant_p(m) + max(0._r8, &
+ tref_p(m) - (273.15 + baset(ivt))) * deltim / 86400._r8
+ ENDIF
+ ELSE
+ gddplant_p(m) = 0._r8
+ ENDIF
+#endif
+ ENDDO
+
+ !calculate gdd020,gdd820,gdd1020 for gddmaturity in GPAM crop phenology F. Li
+ DO m = ps , pe
+ ivt = pftclass(m)
+ IF (idate(2) == 1 .and. idate(3) == deltim)THEN
+ IF(nyrs_crop_active_p(m) == 0) THEN ! YR 1:
+ gdd020_p(m) = 0._r8 ! set gdd..20 variables to 0
+ gdd820_p(m) = 0._r8 ! and crops will not be planted
+ gdd1020_p(m) = 0._r8
+ ELSE
+ IF (nyrs_crop_active_p(m) == 1) THEN ! <-- END of YR 1
+ gdd020_p(m) = gdd0_p(m) ! <-- END of YR 1
+ gdd820_p(m) = gdd8_p(m) ! <-- END of YR 1
+ gdd1020_p(m) = gdd10_p(m) ! <-- END of YR 1
+ ELSE
+ gdd020_p(m) = (yravgm1* gdd020_p(m) + gdd0_p(m)) / yravg ! gdd..20 must be long term avgs
+ gdd820_p(m) = (yravgm1* gdd820_p(m) + gdd8_p(m)) / yravg ! so ignore results for yrs 1 & 2
+ gdd1020_p(m) = (yravgm1* gdd1020_p(m) + gdd10_p(m)) / yravg
+ ENDIF
+ ENDIF ! <-- END of YR 1
+ gdd0_p (m) = 0._r8
+ gdd8_p (m) = 0._r8
+ gdd10_p(m) = 0._r8
+ ENDIF
+ IF (isendofyear(idate,deltim)) THEN ! <-- END of EVERY YR:
+ nyrs_crop_active_p(m) = nyrs_crop_active_p(m) + 1
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CNPhenologyClimate
+
+
+ SUBROUTINE CNEvergreenPhenology (i,ps,pe,deltim,dayspyr)
+!
+! !DESCRIPTION:
+! Evergreen phenology assumes CN stock from vegetation storage pool go to transfer
+! pool steadily with a constant rate 0.0002. All CN stock from transfer pool go to
+! display pool immediately when it receives CN flow from storage pool. in recent version,
+! Evergreen types only allocate NPP or N uptake to display pools. Storage and transfer
+! pool stay 0 over whole simulation periods. Leaf litter fall simulation depends on a
+! background turnover, which a constant parameter leaf_long was assigned (from MOD_Const_PFT.F90)
+! to indicate the background turnover rates.
+!
+! Allocation NPP -> DISPLAY pool -> litter
+!
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+!
+! !ARGUMENTS:
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dayspyr ! Days per year
+ !
+ ! !LOCAL VARIABLES:
+
+ real(r8):: tranr
+ real(r8):: t1 ! temporary variable
+ integer :: ivt, m
+ !-----------------------------------------------------------------------
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+ IF (isevg(ivt)) THEN
+ bglfr_p(m) = 1._r8/(leaf_long(ivt) * dayspyr * 86400._r8)
+ bgtr_p(m) = 0._r8
+ lgsf_p(m) = 0._r8
+ ENDIF
+ ENDDO
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+ IF (isevg(ivt)) THEN
+
+ tranr=0.0002_r8
+ ! set carbon fluxes for shifting storage pools to transfer pools
+ leafc_storage_to_xfer_p(m) = tranr * leafc_storage_p(m)/deltim
+ frootc_storage_to_xfer_p(m) = tranr * frootc_storage_p(m)/deltim
+ IF (woody(ivt) == 1) THEN
+ livestemc_storage_to_xfer_p(m) = tranr * livestemc_storage_p(m)/deltim
+ deadstemc_storage_to_xfer_p(m) = tranr * deadstemc_storage_p(m)/deltim
+ livecrootc_storage_to_xfer_p(m) = tranr * livecrootc_storage_p(m)/deltim
+ deadcrootc_storage_to_xfer_p(m) = tranr * deadcrootc_storage_p(m)/deltim
+ gresp_storage_to_xfer_p(m) = tranr * gresp_storage_p(m)/deltim
+ ENDIF
+
+ ! set nitrogen fluxes for shifting storage pools to transfer pools
+ leafn_storage_to_xfer_p(m) = tranr * leafn_storage_p(m)/deltim
+ frootn_storage_to_xfer_p(m) = tranr * frootn_storage_p(m)/deltim
+ IF (woody(ivt) == 1) THEN
+ livestemn_storage_to_xfer_p(m) = tranr * livestemn_storage_p(m)/deltim
+ deadstemn_storage_to_xfer_p(m) = tranr * deadstemn_storage_p(m)/deltim
+ livecrootn_storage_to_xfer_p(m) = tranr * livecrootn_storage_p(m)/deltim
+ deadcrootn_storage_to_xfer_p(m) = tranr * deadcrootn_storage_p(m)/deltim
+ ENDIF
+
+ t1 = 1.0_r8 / deltim
+
+ leafc_xfer_to_leafc_p(m) = t1 * leafc_xfer_p(m)
+ frootc_xfer_to_frootc_p(m) = t1 * frootc_xfer_p(m)
+
+ leafn_xfer_to_leafn_p(m) = t1 * leafn_xfer_p(m)
+ frootn_xfer_to_frootn_p(m) = t1 * frootn_xfer_p(m)
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_to_livestemc_p(m) = t1 * livestemc_xfer_p(m)
+ deadstemc_xfer_to_deadstemc_p(m) = t1 * deadstemc_xfer_p(m)
+ livecrootc_xfer_to_livecrootc_p(m) = t1 * livecrootc_xfer_p(m)
+ deadcrootc_xfer_to_deadcrootc_p(m) = t1 * deadcrootc_xfer_p(m)
+
+ livestemn_xfer_to_livestemn_p(m) = t1 * livestemn_xfer_p(m)
+ deadstemn_xfer_to_deadstemn_p(m) = t1 * deadstemn_xfer_p(m)
+ livecrootn_xfer_to_livecrootn_p(m) = t1 * livecrootn_xfer_p(m)
+ deadcrootn_xfer_to_deadcrootn_p(m) = t1 * deadcrootn_xfer_p(m)
+ ENDIF
+
+ ENDIF ! END of IF (isevg(ivt(p)) == 1._r8) THEN
+
+ ENDDO ! END of pft loop
+
+ END SUBROUTINE CNEvergreenPhenology
+
+ SUBROUTINE CNSeasonDecidPhenology(i,ps,pe,idate,deltim,dayspyr,dlat)
+
+!
+! !DESCRIPTION:
+! This routine handles the seasonal deciduous phenology code (temperate deciduous
+! vegetation that has only one growing season per year). Seasonal deciduous phenology
+! assumes 0 background turnover rates. NPP or N uptake only allocated to storage pool.
+! Display pool size changes occur only in onset and offset period. All CN stock from
+! transfer pool go to display pool immediately when it receives CN flow from storage
+! pool.
+!
+! Onset period:
+! Allocation NPP -> STORAGE pool -> XFER pool -> DISPLAY pool
+! Offset period:
+! DISPLAY pool -> litter
+!
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+! !ARGUMENTS:
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: idate(3)! current date (year, day of the year, second of the day)
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dayspyr ! Days per year
+ real(r8),intent(in) :: dlat ! latitude (degree)
+
+ !
+ ! !LOCAL VARIABLES:
+ real(r8):: ws_flag !winter-summer solstice flag (0 or 1)
+ real(r8):: crit_onset_gdd !critical onset growing degree-day sum
+ real(r8):: soilt
+ integer :: idate2_last
+ integer :: ivt, m
+ !-----------------------------------------------------------------------
+
+
+ idate2_last = idate(2) - 1
+ IF(idate2_last .le. 0)idate2_last=idate2_last+365
+ prev_dayl(i)=daylength(dlat,idate2_last)
+ dayl(i) =daylength(dlat,idate(2))
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+ IF (issed(ivt)) THEN
+
+ ! set background litterfall rate, background transfer rate, and
+ ! long growing season factor to 0 for seasonal deciduous types
+ bglfr_p(m) = 0._r8
+ bgtr_p(m) = 0._r8
+ lgsf_p(m) = 0._r8
+
+ ! onset gdd sum from Biome-BGC, v4.1.2
+ crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_tref_p(m) - 273.15_r8))
+
+ ! set flag for solstice period (winter->summer = 1, summer->winter = 0)
+ IF (dayl(i) >= prev_dayl(i)) THEN
+ ws_flag = 1._r8
+ ELSE
+ ws_flag = 0._r8
+ ENDIF
+
+ ! update offset_counter and test for the END of the offset period
+ IF (offset_flag_p(m) == 1.0_r8) THEN
+ ! decrement counter for offset period
+ offset_counter_p(m) = offset_counter_p(m) - deltim
+
+ ! IF this is the END of the offset_period, reset phenology
+ ! flags and indices
+ IF (abs(offset_counter_p(m)) .lt. 0.1_r8) THEN
+ ! this code block was originally handled by CALL cn_offset_cleanup(i)
+ ! inlined during vectorization
+
+ offset_flag_p(m) = 0._r8
+ offset_counter_p(m) = 0._r8
+ dormant_flag_p(m) = 1._r8
+ days_active_p(m) = 0._r8
+
+ ! reset the previous timestep litterfall flux memory
+ prev_leafc_to_litter_p(m) = 0._r8
+ prev_frootc_to_litter_p(m) = 0._r8
+ ENDIF
+ ENDIF
+
+ ! update onset_counter and test for the END of the onset period
+ IF (onset_flag_p(m) == 1.0_r8) THEN
+ ! decrement counter for onset period
+ onset_counter_p(m) = onset_counter_p(m) - deltim
+
+ ! IF this is the END of the onset period, reset phenology
+ ! flags and indices
+ IF (abs(onset_counter_p(m)) .lt. 0.1_r8) THEN
+ ! this code block was originally handled by CALL cn_onset_cleanup(i)
+ ! inlined during vectorization
+
+ onset_flag_p(m) = 0.0_r8
+ onset_counter_p(m) = 0.0_r8
+ ! set all transfer growth rates to 0.0
+ leafc_xfer_to_leafc_p(m) = 0.0_r8
+ frootc_xfer_to_frootc_p(m) = 0.0_r8
+ leafn_xfer_to_leafn_p(m) = 0.0_r8
+ frootn_xfer_to_frootn_p(m) = 0.0_r8
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_to_livestemc_p(m) = 0.0_r8
+ deadstemc_xfer_to_deadstemc_p(m) = 0.0_r8
+ livecrootc_xfer_to_livecrootc_p(m) = 0.0_r8
+ deadcrootc_xfer_to_deadcrootc_p(m) = 0.0_r8
+ livestemn_xfer_to_livestemn_p(m) = 0.0_r8
+ deadstemn_xfer_to_deadstemn_p(m) = 0.0_r8
+ livecrootn_xfer_to_livecrootn_p(m) = 0.0_r8
+ deadcrootn_xfer_to_deadcrootn_p(m) = 0.0_r8
+ ENDIF
+ ! set transfer pools to 0.0
+ leafc_xfer_p(m) = 0.0_r8
+ leafn_xfer_p(m) = 0.0_r8
+ frootc_xfer_p(m) = 0.0_r8
+ frootn_xfer_p(m) = 0.0_r8
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_p(m) = 0.0_r8
+ livestemn_xfer_p(m) = 0.0_r8
+ deadstemc_xfer_p(m) = 0.0_r8
+ deadstemn_xfer_p(m) = 0.0_r8
+ livecrootc_xfer_p(m) = 0.0_r8
+ livecrootn_xfer_p(m) = 0.0_r8
+ deadcrootc_xfer_p(m) = 0.0_r8
+ deadcrootn_xfer_p(m) = 0.0_r8
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! test for switching from dormant period to growth period
+ IF (dormant_flag_p(m) == 1.0_r8) THEN
+
+ ! Test to turn on growing degree-day sum, IF off.
+ ! switch on the growing degree day sum on the winter solstice
+
+ IF (onset_gddflag_p(m) == 0._r8 .and. ws_flag == 1._r8) THEN
+ onset_gddflag_p(m) = 1._r8
+ onset_gdd_p(m) = 0._r8
+ ENDIF
+
+ ! Test to turn off growing degree-day sum, IF on.
+ ! This test resets the growing degree day sum IF it gets past
+ ! the summer solstice without reaching the threshold value.
+ ! in that CASE, it will take until the next winter solstice
+ ! before the growing degree-day summation starts again.
+
+ IF (onset_gddflag_p(m) == 1._r8 .and. ws_flag == 0._r8) THEN
+ onset_gddflag_p(m) = 0._r8
+ onset_gdd_p(m) = 0._r8
+ ENDIF
+
+ ! IF the gdd flag is set, and IF the soil is above freezing
+ ! THEN accumulate growing degree days for onset trigger
+
+ soilt = t_soisno(3,i)
+ IF (onset_gddflag_p(m) == 1.0_r8 .and. soilt > 273.15_r8) THEN
+ onset_gdd_p(m) = onset_gdd_p(m) + (soilt-273.15_r8)*(deltim/86400._r8)
+ ENDIF
+
+ ! set onset_flag IF critical growing degree-day sum is exceeded
+ IF (onset_gdd_p(m) > crit_onset_gdd) THEN
+ onset_flag_p(m) = 1.0_r8
+ dormant_flag_p(m) = 0.0_r8
+ onset_gddflag_p(m) = 0.0_r8
+ onset_gdd_p(m) = 0.0_r8
+ onset_counter_p(m) = ndays_on * 86400._r8
+
+ ! move all the storage pools into transfer pools,
+ ! WHERE they will be transfered to displayed growth over the onset period.
+ ! this code was originally handled with CALL cn_storage_to_xfer(p)
+ ! inlined during vectorization
+
+ ! set carbon fluxes for shifting storage pools to transfer pools
+ leafc_storage_to_xfer_p(m) = fstor2tran * leafc_storage_p(m)/deltim
+ frootc_storage_to_xfer_p(m) = fstor2tran * frootc_storage_p(m)/deltim
+ IF (woody(ivt) == 1) THEN
+ livestemc_storage_to_xfer_p(m) = fstor2tran * livestemc_storage_p(m)/deltim
+ deadstemc_storage_to_xfer_p(m) = fstor2tran * deadstemc_storage_p(m)/deltim
+ livecrootc_storage_to_xfer_p(m) = fstor2tran * livecrootc_storage_p(m)/deltim
+ deadcrootc_storage_to_xfer_p(m) = fstor2tran * deadcrootc_storage_p(m)/deltim
+ gresp_storage_to_xfer_p(m) = fstor2tran * gresp_storage_p(m)/deltim
+ ENDIF
+
+ ! set nitrogen fluxes for shifting storage pools to transfer pools
+ leafn_storage_to_xfer_p(m) = fstor2tran * leafn_storage_p(m)/deltim
+ frootn_storage_to_xfer_p(m) = fstor2tran * frootn_storage_p(m)/deltim
+ IF (woody(ivt) == 1) THEN
+ livestemn_storage_to_xfer_p(m) = fstor2tran * livestemn_storage_p(m)/deltim
+ deadstemn_storage_to_xfer_p(m) = fstor2tran * deadstemn_storage_p(m)/deltim
+ livecrootn_storage_to_xfer_p(m) = fstor2tran * livecrootn_storage_p(m)/deltim
+ deadcrootn_storage_to_xfer_p(m) = fstor2tran * deadcrootn_storage_p(m)/deltim
+ ENDIF
+ ENDIF
+
+ ! test for switching from growth period to offset period
+ ELSE IF (offset_flag_p(m) == 0.0_r8) THEN
+
+ ! only begin to test for offset daylength once past the summer sol
+ IF (ws_flag == 0._r8 .and. dayl(i) < crit_dayl) THEN
+ offset_flag_p(m) = 1._r8
+ offset_counter_p(m) = ndays_off * 86400._r8
+ prev_leafc_to_litter_p(m) = 0._r8
+ prev_frootc_to_litter_p(m) = 0._r8
+ ENDIF
+ ENDIF
+
+ ENDIF ! ENDIF seasonal deciduous
+ ENDDO
+
+ END SUBROUTINE CNSeasonDecidPhenology
+
+ SUBROUTINE CNStressDecidPhenology(i,ps,pe,deltim,dayspyr)
+
+!
+! !DESCRIPTION:
+! This routine handles the stress deciduous phenology code (deciduous vegetation with
+! one or more growing season per year). NPP or N uptake only allocated to storage pool.
+!
+! Onset period:
+! Allocation NPP -> STORAGE pool -> XFER pool -> DISPLAY pool
+! Offset period:
+! DISPLAY pool -> litter
+!
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ integer, intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ real(r8),intent(in) :: dayspyr ! days per year
+
+ ! !LOCAL VARIABLES:
+ real(r8),parameter :: secspqtrday = 86400._r8 / 4 ! seconds per quarter day
+ real(r8):: crit_onset_gdd ! degree days for onset trigger
+ real(r8):: soilt ! temperature of top soil layer
+ real(r8):: psi ! soil water potential [MPa]
+ real(r8):: rain_threshold ! rain threshold for leaf on [mm]
+ logical :: additional_onset_condition ! additional condition for leaf onset
+ integer :: ivt, m
+ !-----------------------------------------------------------------------
+
+
+ ! specify rain threshold for leaf onset
+ rain_threshold = 20._r8
+
+ DO m = ps , pe
+ ivt = pftclass(m)
+ IF (isstd(ivt)) THEN
+ soilt = t_soisno(3,i)
+ psi = smp(3,i) * 1.e-5 ! mmH2O -> MPa
+
+ ! onset gdd sum from Biome-BGC, v4.1.2
+ crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_tref_p(m) - 273.15_r8))
+
+ ! update offset_counter and test for the END of the offset period
+ IF (offset_flag_p(m) == 1._r8) THEN
+ ! decrement counter for offset period
+ offset_counter_p(m) = offset_counter_p(m) - deltim
+
+ ! IF this is the END of the offset_period, reset phenology
+ ! flags and indices
+ IF (abs(offset_counter_p(m)) .lt. 0.1_r8) THEN
+ ! this code block was originally handled by CALL cn_offset_cleanup(i)
+ ! inlined during vectorization
+ offset_flag_p(m) = 0._r8
+ offset_counter_p(m) = 0._r8
+ dormant_flag_p(m) = 1._r8
+ days_active_p(m) = 0._r8
+
+ ! reset the previous timestep litterfall flux memory
+ prev_leafc_to_litter_p(m) = 0._r8
+ prev_frootc_to_litter_p(m) = 0._r8
+ ENDIF
+ ENDIF
+
+ ! update onset_counter and test for the END of the onset period
+ IF (onset_flag_p(m) == 1.0_r8) THEN
+ ! decrement counter for onset period
+ onset_counter_p(m) = onset_counter_p(m) - deltim
+
+ ! IF this is the END of the onset period, reset phenology
+ ! flags and indices
+ IF (abs(onset_counter_p(m)) .lt. 0.1_r8) THEN
+ ! this code block was originally handled by CALL cn_onset_cleanup(i)
+ ! inlined during vectorization
+ onset_flag_p(m) = 0._r8
+ onset_counter_p(m) = 0._r8
+ ! set all transfer growth rates to 0.0
+ leafc_xfer_to_leafc_p(m) = 0._r8
+ frootc_xfer_to_frootc_p(m) = 0._r8
+ leafn_xfer_to_leafn_p(m) = 0._r8
+ frootn_xfer_to_frootn_p(m) = 0._r8
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_to_livestemc_p(m) = 0._r8
+ deadstemc_xfer_to_deadstemc_p(m) = 0._r8
+ livecrootc_xfer_to_livecrootc_p(m) = 0._r8
+ deadcrootc_xfer_to_deadcrootc_p(m) = 0._r8
+ livestemn_xfer_to_livestemn_p(m) = 0._r8
+ deadstemn_xfer_to_deadstemn_p(m) = 0._r8
+ livecrootn_xfer_to_livecrootn_p(m) = 0._r8
+ deadcrootn_xfer_to_deadcrootn_p(m) = 0._r8
+ ENDIF
+ ! set transfer pools to 0.0
+ leafc_xfer_p(m) = 0._r8
+ leafn_xfer_p(m) = 0._r8
+ frootc_xfer_p(m) = 0._r8
+ frootn_xfer_p(m) = 0._r8
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_p(m) = 0._r8
+ livestemn_xfer_p(m) = 0._r8
+ deadstemc_xfer_p(m) = 0._r8
+ deadstemn_xfer_p(m) = 0._r8
+ livecrootc_xfer_p(m) = 0._r8
+ livecrootn_xfer_p(m) = 0._r8
+ deadcrootc_xfer_p(m) = 0._r8
+ deadcrootn_xfer_p(m) = 0._r8
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! test for switching from dormant period to growth period
+ IF (dormant_flag_p(m) == 1._r8) THEN
+
+ ! keep track of the number of freezing degree days in this
+ ! dormancy period (only IF the freeze flag has not previously been set
+ ! for this dormancy period
+
+ IF (onset_gddflag_p(m) == 0._r8 .and. soilt < 273.15_r8) onset_fdd_p(m) = onset_fdd_p(m) + deltim/86400._r8
+
+ ! IF the number of freezing degree days exceeds a critical value,
+ ! THEN onset will require both wet soils and a critical soil
+ ! temperature sum. IF this CASE is triggered, reset any previously
+ ! accumulated value in onset_swi, so that onset now depends on
+ ! the accumulated soil water index following the freeze trigger
+
+ IF (onset_fdd_p(m) > crit_onset_fdd) THEN
+ onset_gddflag_p(m) = 1._r8
+ onset_fdd_p(m) = 0._r8
+ onset_swi_p(m) = 0._r8
+ ENDIF
+
+ ! IF the freeze flag is set, and IF the soil is above freezing
+ ! THEN accumulate growing degree days for onset trigger
+
+ IF (onset_gddflag_p(m) == 1._r8 .and. soilt > 273.15_r8) THEN
+ onset_gdd_p(m) = onset_gdd_p(m) + (soilt-273.15_r8)*deltim/86400._r8
+ ENDIF
+
+ ! IF soils are wet, accumulate soil water index for onset trigger
+ additional_onset_condition = .true.
+ ! IF additional constraint condition not met, set to false
+ IF ((prec10(i) * (3600.0_r8*10.0_r8*24.0_r8)) < rain_threshold) THEN
+ additional_onset_condition = .false.
+ ENDIF
+
+ IF (psi >= soilpsi_on) THEN
+ onset_swi_p(m) = onset_swi_p(m) + deltim/86400._r8
+ ENDIF
+
+ ! IF critical soil water index is exceeded, set onset_flag, and
+ ! THEN test for soil temperature criteria
+
+ ! Adding in Kyla's rainfall trigger when fun on. RF. prec10 (mm/s) needs to be higher than 8mm over 10 days.
+
+ IF (onset_swi_p(m) > crit_onset_swi.and. additional_onset_condition) THEN
+ onset_flag_p(m) = 1._r8
+
+ ! only check soil temperature criteria IF freeze flag set since
+ ! beginning of last dormancy. IF freeze flag set and growing
+ ! degree day sum (since freeze trigger) is lower than critical
+ ! value, THEN override the onset_flag set from soil water.
+
+ IF (onset_gddflag_p(m) == 1._r8 .and. onset_gdd_p(m) < crit_onset_gdd) onset_flag_p(m) = 0._r8
+ ENDIF
+
+ ! only allow onset IF dayl > 6hrs
+ IF (onset_flag_p(m) == 1._r8 .and. dayl(i) <= secspqtrday) THEN
+ onset_flag_p(m) = 0._r8
+ ENDIF
+
+ ! IF this is the beginning of the onset period
+ ! THEN reset the phenology flags and indices
+
+ IF (onset_flag_p(m) == 1._r8) THEN
+ dormant_flag_p(m) = 0._r8
+ days_active_p(m) = 0._r8
+ onset_gddflag_p(m) = 0._r8
+ onset_fdd_p(m) = 0._r8
+ onset_gdd_p(m) = 0._r8
+ onset_swi_p(m) = 0._r8
+ onset_counter_p(m) = ndays_on * 86400._r8
+
+ ! CALL SUBROUTINE to move all the storage pools into transfer pools,
+ ! WHERE they will be transfered to displayed growth over the onset period.
+ ! this code was originally handled with CALL cn_storage_to_xfer(i)
+ ! inlined during vectorization
+
+ ! set carbon fluxes for shifting storage pools to transfer pools
+ leafc_storage_to_xfer_p(m) = fstor2tran * leafc_storage_p(m)/deltim
+ frootc_storage_to_xfer_p(m) = fstor2tran * frootc_storage_p(m)/deltim
+ IF (woody(ivt) == 1) THEN
+ livestemc_storage_to_xfer_p(m) = fstor2tran * livestemc_storage_p(m)/deltim
+ deadstemc_storage_to_xfer_p(m) = fstor2tran * deadstemc_storage_p(m)/deltim
+ livecrootc_storage_to_xfer_p(m) = fstor2tran * livecrootc_storage_p(m)/deltim
+ deadcrootc_storage_to_xfer_p(m) = fstor2tran * deadcrootc_storage_p(m)/deltim
+ gresp_storage_to_xfer_p(m) = fstor2tran * gresp_storage_p(m)/deltim
+ ENDIF
+
+ ! set nitrogen fluxes for shifting storage pools to transfer pools
+ leafn_storage_to_xfer_p(m) = fstor2tran * leafn_storage_p(m)/deltim
+ frootn_storage_to_xfer_p(m) = fstor2tran * frootn_storage_p(m)/deltim
+ IF (woody(ivt) == 1) THEN
+ livestemn_storage_to_xfer_p(m) = fstor2tran * livestemn_storage_p(m)/deltim
+ deadstemn_storage_to_xfer_p(m) = fstor2tran * deadstemn_storage_p(m)/deltim
+ livecrootn_storage_to_xfer_p(m) = fstor2tran * livecrootn_storage_p(m)/deltim
+ deadcrootn_storage_to_xfer_p(m) = fstor2tran * deadcrootn_storage_p(m)/deltim
+ ENDIF
+ ENDIF
+
+ ! test for switching from growth period to offset period
+ ELSE IF (offset_flag_p(m) == 0._r8) THEN
+
+ ! IF soil water potential lower than critical value, accumulate
+ ! as stress in offset soil water index
+
+ IF (psi <= soilpsi_off) THEN
+ offset_swi_p(m) = offset_swi_p(m) + deltim/86400._r8
+
+ ! IF the offset soil water index exceeds critical value, and
+ ! IF this is not the middle of a previously initiated onset period,
+ ! THEN set flag to start the offset period and reset index variables
+
+ IF (offset_swi_p(m) >= crit_offset_swi .and. onset_flag_p(m) == 0._r8) offset_flag_p(m) = 1._r8
+
+ ! IF soil water potential higher than critical value, reduce the
+ ! offset water stress index. By this mechanism, there must be a
+ ! sustained period of water stress to initiate offset.
+
+ ELSE IF (psi >= soilpsi_on) THEN
+ offset_swi_p(m) = offset_swi_p(m) - deltim/86400._r8
+ offset_swi_p(m) = max(offset_swi_p(m),0._r8)
+ ENDIF
+
+ ! decrease freezing day accumulator for warm soil
+ IF (offset_fdd_p(m) > 0._r8 .and. soilt > 273.15_r8) THEN
+ offset_fdd_p(m) = offset_fdd_p(m) - deltim/86400._r8
+ offset_fdd_p(m) = max(0._r8, offset_fdd_p(m))
+ ENDIF
+
+ ! increase freezing day accumulator for cold soil
+ IF (soilt <= 273.15_r8) THEN
+ offset_fdd_p(m) = offset_fdd_p(m) + deltim/86400._r8
+
+ ! IF freezing degree day sum is greater than critical value, initiate offset
+ IF (offset_fdd_p(m) > crit_offset_fdd .and. onset_flag_p(m) == 0._r8) offset_flag_p(m) = 1._r8
+ ENDIF
+
+ ! force offset IF daylength is < 6 hrs
+ IF (dayl(i) <= secspqtrday) THEN
+ offset_flag_p(m) = 1._r8
+ ENDIF
+
+ ! IF this is the beginning of the offset period
+ ! THEN reset flags and indices
+ IF (offset_flag_p(m) == 1._r8) THEN
+ offset_fdd_p(m) = 0._r8
+ offset_swi_p(m) = 0._r8
+ offset_counter_p(m) = ndays_off * 86400._r8
+ prev_leafc_to_litter_p(m) = 0._r8
+ prev_frootc_to_litter_p(m) = 0._r8
+ ENDIF
+ ENDIF
+
+ ! keep track of number of days since last dormancy for control on
+ ! fraction of new growth to send to storage for next growing season
+
+ IF (dormant_flag_p(m) == 0.0_r8) THEN
+ days_active_p(m) = days_active_p(m) + deltim/86400._r8
+ ENDIF
+
+ ! calculate long growing season factor (lgsf)
+ ! only begin to calculate a lgsf greater than 0.0 once the number
+ ! of days active exceeds days/year.
+ lgsf_p(m) = max(min(3.0_r8*(days_active_p(m)-leaf_long(ivt)*dayspyr )/dayspyr, 1._r8),0._r8)
+ ! RosieF. 5 Nov 2015. Changed this such that the increase in leaf turnover is faster after
+ ! trees enter the 'fake evergreen' state. Otherwise, they have a whole year of
+ ! cheating, with less litterfall than they should have, resulting in very high LAI.
+ ! Further, the 'fake evergreen' state (WHERE lgsf>0) is entered at the END of a single leaf lifespan
+ ! and not a whole year. The '3' is arbitrary, given that this entire system is quite abstract.
+ ! set background litterfall rate, when not in the phenological offset period
+ IF (offset_flag_p(m) == 1._r8) THEN
+ bglfr_p(m) = 0._r8
+ ELSE
+ ! calculate the background litterfall rate (bglfr)
+ ! in units 1/s, based on leaf longevity (yrs) and correction for long growing season
+
+ bglfr_p(m) = (1._r8/(leaf_long(ivt)*dayspyr*86400._r8))*lgsf_p(m)
+ ENDIF
+
+ ! set background transfer rate when active but not in the phenological onset period
+ IF (onset_flag_p(m) == 1._r8) THEN
+ bgtr_p(m) = 0._r8
+ ELSE
+ ! the background transfer rate is calculated as the rate that would result
+ ! in complete turnover of the storage pools in one year at steady state,
+ ! once lgsf has reached 1.0 (after 730 days active).
+
+ bgtr_p(m) = (1._r8/(dayspyr*86400._r8))*lgsf_p(m)
+
+ ! set carbon fluxes for shifting storage pools to transfer pools
+
+ ! reduced the amount of stored carbon flowing to display pool by only counting the delta
+ ! between leafc and leafc_store in the flux. RosieF, Nov5 2015.
+ leafc_storage_to_xfer_p(m) = max(0.0_r8,(leafc_storage_p(m)-leafc_p(m))) * bgtr_p(m)
+ frootc_storage_to_xfer_p(m) = max(0.0_r8,(frootc_storage_p(m)-frootc_p(m))) * bgtr_p(m)
+ IF (woody(ivt) == 1) THEN
+ livestemc_storage_to_xfer_p(m) = livestemc_storage_p(m) * bgtr_p(m)
+ deadstemc_storage_to_xfer_p(m) = deadstemc_storage_p(m) * bgtr_p(m)
+ livecrootc_storage_to_xfer_p(m) = livecrootc_storage_p(m) * bgtr_p(m)
+ deadcrootc_storage_to_xfer_p(m) = deadcrootc_storage_p(m) * bgtr_p(m)
+ gresp_storage_to_xfer_p(m) = gresp_storage_p(m) * bgtr_p(m)
+ ENDIF
+
+ ! set nitrogen fluxes for shifting storage pools to transfer pools
+ leafn_storage_to_xfer_p(m) = leafn_storage_p(m) * bgtr_p(m)
+ frootn_storage_to_xfer_p(m) = frootn_storage_p(m) * bgtr_p(m)
+ IF (woody(ivt) == 1) THEN
+ livestemn_storage_to_xfer_p(m) = livestemn_storage_p(m) * bgtr_p(m)
+ deadstemn_storage_to_xfer_p(m) = deadstemn_storage_p(m) * bgtr_p(m)
+ livecrootn_storage_to_xfer_p(m) = livecrootn_storage_p(m) * bgtr_p(m)
+ deadcrootn_storage_to_xfer_p(m) = deadcrootn_storage_p(m) * bgtr_p(m)
+ ENDIF
+ ENDIF
+
+ ENDIF ! ENDIF stress deciduous
+ ENDDO !END pft loop
+
+ END SUBROUTINE CNStressDecidPhenology
+
+#ifdef CROP
+ SUBROUTINE CropPhenology(i,ps,pe,idate,h,deltim,dayspyr,npcropmin)
+
+! !DESCRIPTION:
+! GPAM crop phenology and code from CN to
+! handle CN fluxes during the phenological onset & offset periods.
+!
+! ORIGINAL: The Community Land Model version 5.0 (CLM5.0)
+!
+! REVISION: F. Li, 2022, implemented GPAM in CoLM.
+
+ integer, intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: idate(1:3)! current date (year, day of the year, second of the day)
+ integer ,intent(in) :: h ! hemisphere indicator: 1 for north hemisphere; 2 for south hemisphere
+ real(r8),intent(in) :: deltim ! timestep in seconds
+ real(r8),intent(in) :: dayspyr ! days per year
+ integer ,intent(in) :: npcropmin ! first crop pft index
+
+ ! LOCAL VARAIBLES:
+ integer kyr ! current year
+ integer kmo ! month of year (1, ..., 12)
+ integer kda ! day of month (1, ..., 31)
+ integer mcsec
+ integer jday
+ integer fp,m ! patch indices
+ integer c ! column indices
+ integer g ! gridcell indices
+ integer idpp ! number of days past planting
+ real(r8) ndays_on ! number of days to fertilize
+ integer :: jdayyrstart(2)
+ real(r8) :: initial_seed_at_planting = 3._r8 ! Initial seed at planting
+ integer ivt
+
+ !------------------------------------------------------------------------
+
+ jdayyrstart(1) = 1
+ jdayyrstart(2) = 182
+
+ jday = idate(2)
+ mcsec = idate(3)
+ ! get time info
+
+ ndays_on = 20._r8 ! number of days to fertilize
+
+ ! background litterfall and transfer rates; long growing season factor
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF(ivt >= npcropmin)THEN
+ bglfr_p(m) = 0._r8 ! this value changes later in a crop's life CYCLE
+ bgtr_p(m) = 0._r8
+ lgsf_p(m) = 0._r8
+
+
+ ! plantdate is read in
+ ! determine IF the cft is planted in this time step
+ IF ( (.not. croplive_p(m)) .and. (.not. cropplant_p(m)) ) THEN
+ IF (jday == int(plantdate_p(m))) THEN
+ cumvd_p(m) = 0._r8
+ vf_p(m) = 0._r8
+ croplive_p(m) = .true.
+ cropplant_p(m) = .true.
+ idop_p(m) = jday
+ harvdate_p(m) = NOT_Harvested
+ leafc_xfer_p(m) = initial_seed_at_planting
+ leafn_xfer_p(m) = leafc_xfer_p(m) / leafcn(ivt) ! with onset
+ crop_seedc_to_leaf_p(m) = leafc_xfer_p(m)/deltim
+ crop_seedn_to_leaf_p(m) = leafn_xfer_p(m)/deltim
+ ENDIF
+ ENDIF
+ ! calculate gddmaturity
+ IF(croplive_p(m))THEN
+ IF (ivt == nwwheat .or. ivt == nirrig_wwheat)THEN
+ gddmaturity_p(m) = 0.42_r8 * gdd1020_p(m) + 440._r8
+ ENDIF
+ IF ( ivt == ntmp_soybean .or. ivt == nirrig_tmp_soybean .or. &
+ ivt == ntrp_soybean .or. ivt == nirrig_trp_soybean) THEN
+ gddmaturity_p(m) = 0.30_r8 * gdd1020_p(m) + 710._r8
+ ENDIF
+ IF (ivt == ntmp_corn .or. ivt == nirrig_tmp_corn .or. &
+ ivt == ntrp_corn .or. ivt == nirrig_trp_corn .or. &
+ ivt == nsugarcane .or. ivt == nirrig_sugarcane .or. &
+ ivt == nmiscanthus .or. ivt == nirrig_miscanthus .or. &
+ ivt == nswitchgrass .or. ivt == nirrig_switchgrass) THEN
+ gddmaturity_p(m) = 0.30_r8 * gdd820_p(m) + 816._r8
+ ENDIF
+ IF (ivt == nswheat .or. ivt == nirrig_swheat .or. &
+ ivt == ncotton .or. ivt == nirrig_cotton)THEN
+ gddmaturity_p(m) = 0.24_r8 * gdd020_p(m) + 1349._r8
+ ENDIF
+ IF (ivt == nrice .or. ivt == nirrig_rice) THEN
+ gddmaturity_p(m) = 0.35_r8 * gdd020_p(m) + 587._r8
+ ENDIF
+ hui_p(m)=gddplant_p(m)/gddmaturity_p(m)
+ ENDIF
+
+ ! all of the phenology changes are based on hui
+
+ ! Phase 1: Planting to leaf emergence
+ ! Phase 2: Leaf emergence to beginning of grain fill (LAI increase)
+ ! Phase 3: Grain fill to physiological maturity and harvest (LAI decline)
+ ! Harvest: IF gdd past grain fill initiation exceeds limit
+ ! or number of days past planting reaches a maximum, the crop has
+ ! reached physiological maturity and plant is harvested;
+ ! --- --- ---
+
+ onset_flag_p(m) = 0._r8 ! CN terminology to trigger certain
+ offset_flag_p(m) = 0._r8 ! carbon and nitrogen transfers
+
+ IF (croplive_p(m)) THEN
+ cphase_p(m) = 1._r8
+ ! days past planting may determine harvest
+
+ IF (jday >= idop_p(m)) THEN
+ idpp = jday - idop_p(m)
+ ELSE
+ idpp = int(dayspyr) + jday - idop_p(m)
+ ENDIF
+
+ ! onset_counter initialized to zero when .not. croplive
+ ! offset_counter relevant only at time step of harvest
+
+ onset_counter_p(m) = onset_counter_p(m) - deltim
+
+ ! enter phase 2 onset for one time step:
+ ! transfer seed carbon to leaf emergence
+
+ ! IF (peaklai_p(m) >= 1) THEN
+ ! hui_p(m) = max(hui_p(m),grnfill(ivt))
+ ! ENDIF
+
+ IF (hui_p(m) >= lfemerg(ivt) .and. hui_p(m) < grnfill(ivt) .and. idpp < mxmat(ivt)) THEN
+ cphase_p(m) = 2._r8
+ ! CALL vernalization IF winter temperate cereal planted, living, and the
+ ! vernalization factor is not 1;
+ ! vf affects the calculation of gddplant
+ IF ( vf_p(m) /= 1._r8 .and. (ivt == nwwheat .or. ivt == nirrig_wwheat) .and. hui_p(m) < 0.8_r8 * grnfill(ivt)) THEN
+ CALL vernalization(i,m,deltim)
+ ENDIF
+
+ !fertilization
+
+ IF (abs(onset_counter_p(m)) > 1.e-6_r8) THEN
+ onset_flag_p(m) = 1._r8
+ onset_counter_p(m) = deltim
+ fert_counter_p(m) = ndays_on * 86400.
+ IF (ndays_on .gt. 0) THEN
+ IF(DEF_USE_FERT)THEN
+ fert_p(m) = (manunitro_p(m) + fertnitro_p(m))/ fert_counter_p(m)
+ ELSE
+ fert_p(m) = 0._r8
+ ENDIF
+ ELSE
+ fert_p(m) = 0._r8
+ ENDIF
+ ELSE
+ ! this ensures no re-entry to onset of phase2
+ ! b/c onset_counter(p) = onset_counter(p) - deltim
+ ! at every time step
+
+ onset_counter_p(m) = deltim
+ ENDIF
+
+ ! enter harvest for one time step:
+ ! - transfer live biomass to litter and to crop yield
+ ! - send xsmrpool to the atmosphere
+ ! IF onset and harvest needed to last longer than one timestep
+ ! the onset_counter would change from dt and you'd need to make
+ ! changes to the offset SUBROUTINE below
+
+ ELSE IF (hui_p(m) >= 1._r8 .or. idpp >= mxmat(ivt)) THEN
+ IF (harvdate_p(m) >= NOT_Harvested) harvdate_p(m) = jday
+ croplive_p(m) = .false. ! no re-entry in greater IF-block
+ cropplant_p(m)=.false.
+ cphase_p(m) = 4._r8
+ hui_p(m)=0._r8
+ IF (tlai_p(m) > 0._r8) THEN ! plant had emerged before harvest
+ offset_flag_p(m) = 1._r8
+ offset_counter_p(m) = deltim
+ ELSE ! plant never emerged from the ground
+ ! Revert planting transfers; this will replenish the crop seed deficit.
+ ! We subtract from any existing value in crop_seedc_to_leaf /
+ ! crop_seedn_to_leaf in the unlikely event that we enter this block of
+ ! code in the same time step WHERE the planting transfer originally
+ ! occurred.
+ crop_seedc_to_leaf_p(m) = crop_seedc_to_leaf_p(m) - leafc_xfer_p(m)/deltim
+ crop_seedn_to_leaf_p(m) = crop_seedn_to_leaf_p(m) - leafn_xfer_p(m)/deltim
+ leafc_xfer_p(m) = 0._r8
+ leafn_xfer_p(m) = leafc_xfer_p(m) / leafcn(ivt)
+ ENDIF
+
+ ! enter phase 3 WHILE previous criteria fail and next is true;
+ ! in terms of order, phase 3 occurs before harvest, but when
+ ! harvest *can* occur, we want it to have first priority.
+ ! AgroIBIS uses a complex formula for lai decline.
+ ! USE CN's simple formula at least as a place holder (slevis)
+
+ ELSE IF (hui_p(m) >= grnfill(ivt)) THEN
+ cphase_p(m) = 3._r8
+ bglfr_p(m) = 1._r8/(leaf_long(ivt)*dayspyr*86400.)
+ ENDIF
+
+ ! continue fertilizer application WHILE in phase 2;
+ ! assumes that onset of phase 2 took one time step only
+
+ IF (fert_counter_p(m) <= 0._r8) THEN
+ fert_p(m) = 0._r8
+ ELSE ! continue same fert application every timestep
+ fert_counter_p(m) = fert_counter_p(m) - deltim
+ ENDIF
+
+ ELSE ! crop not live
+ ! next 2 lines conserve mass IF leaf*_xfer > 0 due to interpinic.
+ ! We subtract from any existing value in crop_seedc_to_leaf /
+ ! crop_seedn_to_leaf in the unlikely event that we enter this block of
+ ! code in the same time step WHERE the planting transfer originally
+ ! occurred.
+ crop_seedc_to_leaf_p(m) = crop_seedc_to_leaf_p(m) - leafc_xfer_p(m)/deltim
+ crop_seedn_to_leaf_p(m) = crop_seedn_to_leaf_p(m) - leafn_xfer_p(m)/deltim
+ onset_counter_p(m) = 0._r8
+ leafc_xfer_p(m) = 0._r8
+ leafn_xfer_p(m) = leafc_xfer_p(m) / leafcn(ivt)
+ IF(DEF_USE_FERT)THEN
+ fert_p(m) = 0._r8
+ ENDIF
+ ENDIF ! croplive
+ ELSE
+ fert_p(m) = 0._r8
+ ENDIF
+ ENDDO ! prognostic crops loop
+
+ END SUBROUTINE CropPhenology
+#endif
+
+ !---------------------------------------------------------
+ SUBROUTINE CNOnsetGrowth(i,ps,pe,deltim)
+
+! !DESCRIPTION:
+! Calculates flux from transfer CN to display CN during onset period.
+! Transfer CN -> DISPLAY CN
+
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+
+ ! !LOCAL VARIABLES:
+ real(r8):: t1 ! temporary variable
+ integer :: ivt, m
+
+ ! only calculate these fluxes during onset period
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF (onset_flag_p(m) == 1._r8) THEN
+
+ ! The transfer rate is a linearly decreasing FUNCTION of time,
+ ! going to zero on the last timestep of the onset period
+
+ IF (onset_counter_p(m) == deltim) THEN
+ t1 = 1.0_r8 / deltim
+ ELSE
+ t1 = 2.0_r8 / (onset_counter_p(m))
+ ENDIF
+ leafc_xfer_to_leafc_p(m) = t1 * leafc_xfer_p(m)
+ frootc_xfer_to_frootc_p(m) = t1 * frootc_xfer_p(m)
+ leafn_xfer_to_leafn_p(m) = t1 * leafn_xfer_p(m)
+ frootn_xfer_to_frootn_p(m) = t1 * frootn_xfer_p(m)
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_to_livestemc_p(m) = t1 * livestemc_xfer_p(m)
+ deadstemc_xfer_to_deadstemc_p(m) = t1 * deadstemc_xfer_p(m)
+ livecrootc_xfer_to_livecrootc_p(m) = t1 * livecrootc_xfer_p(m)
+ deadcrootc_xfer_to_deadcrootc_p(m) = t1 * deadcrootc_xfer_p(m)
+ livestemn_xfer_to_livestemn_p(m) = t1 * livestemn_xfer_p(m)
+ deadstemn_xfer_to_deadstemn_p(m) = t1 * deadstemn_xfer_p(m)
+ livecrootn_xfer_to_livecrootn_p(m) = t1 * livecrootn_xfer_p(m)
+ deadcrootn_xfer_to_deadcrootn_p(m) = t1 * deadcrootn_xfer_p(m)
+ ENDIF
+
+ ENDIF ! ENDIF onset period
+
+ ! calculate the background rate of transfer growth (used for stress
+ ! deciduous algorithm). in this CASE, all of the mass in the transfer
+ ! pools should be moved to displayed growth in each timestep.
+
+ IF (bgtr_p(m) > 0._r8) THEN
+ leafc_xfer_to_leafc_p(m) = leafc_xfer_p(m) / deltim
+ frootc_xfer_to_frootc_p(m) = frootc_xfer_p(m) / deltim
+ leafn_xfer_to_leafn_p(m) = leafn_xfer_p(m) / deltim
+ frootn_xfer_to_frootn_p(m) = frootn_xfer_p(m) / deltim
+ IF (woody(ivt) == 1) THEN
+ livestemc_xfer_to_livestemc_p(m) = livestemc_xfer_p(m) / deltim
+ deadstemc_xfer_to_deadstemc_p(m) = deadstemc_xfer_p(m) / deltim
+ livecrootc_xfer_to_livecrootc_p(m) = livecrootc_xfer_p(m) / deltim
+ deadcrootc_xfer_to_deadcrootc_p(m) = deadcrootc_xfer_p(m) / deltim
+ livestemn_xfer_to_livestemn_p(m) = livestemn_xfer_p(m) / deltim
+ deadstemn_xfer_to_deadstemn_p(m) = deadstemn_xfer_p(m) / deltim
+ livecrootn_xfer_to_livecrootn_p(m) = livecrootn_xfer_p(m) / deltim
+ deadcrootn_xfer_to_deadcrootn_p(m) = deadcrootn_xfer_p(m) / deltim
+ ENDIF
+ ENDIF ! ENDIF bgtr
+ ENDDO
+
+ END SUBROUTINE CNOnsetGrowth
+
+ SUBROUTINE CNOffsetLitterfall(i,ps,pe,deltim,npcropmin)
+! !DESCRIPTION:
+! Calculates flux from display CN to litter CN during offset period.
+! DISPLAY CN -> litter CN
+
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: npcropmin ! first crop pft index
+
+ real(r8) :: t1 ! temporary variable
+ real(r8) :: denom ! temporary variable for divisor
+ real(r8) :: ntovr_leaf
+ real(r8) :: fr_leafn_to_litter ! fraction of the nitrogen turnover that goes to litter; remaining fraction is retranslocated
+ integer :: ivt, m
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ ! only calculate fluxes during offset period
+ IF (offset_flag_p(m) == 1._r8) THEN
+
+ IF (offset_counter_p(m) == deltim) THEN
+ t1 = 1.0_r8 / deltim
+ leafc_to_litter_p(m) = t1 * leafc_p(m) + cpool_to_leafc_p(m)
+ frootc_to_litter_p(m) = t1 * frootc_p(m) + cpool_to_frootc_p(m)
+ ! this assumes that offset_counter == dt for crops
+ ! IF this were ever changed, we'd need to add code to the "ELSE"
+ IF (ivt >= npcropmin) THEN
+ ! Replenish the seed deficits from grain, IF there is enough
+ ! available grain. (IF there is not enough available grain, the seed
+ ! deficits will accumulate until there is eventually enough grain to
+ ! replenish them.)
+ grainc_to_seed_p(m) = t1 * min(-cropseedc_deficit_p(m), grainc_p(m))
+ grainn_to_seed_p(m) = t1 * min(-cropseedn_deficit_p(m), grainn_p(m))
+ ! Send the remaining grain to the food product pool
+ grainc_to_food_p(m) = t1 * grainc_p(m) + cpool_to_grainc_p(m) - grainc_to_seed_p(m)
+ grainn_to_food_p(m) = t1 * grainn_p(m) + npool_to_grainn_p(m) - grainn_to_seed_p(m)
+
+ livestemc_to_litter_p(m) = t1 * livestemc_p(m) + cpool_to_livestemc_p(m)
+ ENDIF
+ ELSE
+ t1 = deltim * 2.0_r8 / (offset_counter_p(m) * offset_counter_p(m))
+ leafc_to_litter_p(m) = prev_leafc_to_litter_p(m) + t1*(leafc_p(m) - prev_leafc_to_litter_p(m)*offset_counter_p(m))
+ frootc_to_litter_p(m) = prev_frootc_to_litter_p(m) + t1*(frootc_p(m) - prev_frootc_to_litter_p(m)*offset_counter_p(m))
+
+ ENDIF
+
+ leafn_to_litter_p(m) = leafc_to_litter_p(m) / lflitcn(ivt)
+ leafn_to_retransn_p(m) = (leafc_to_litter_p(m) / leafcn(ivt)) - leafn_to_litter_p(m)
+
+
+ ! calculate fine root N litterfall (no retranslocation of fine root N)
+ frootn_to_litter_p(m) = frootc_to_litter_p(m) / frootcn(ivt)
+
+ IF (ivt >= npcropmin) THEN
+ ! NOTE(slevis, 2014-12) results in -ve livestemn and -ve totpftn
+ !X! livestemn_to_litter(p) = livestemc_to_litter(p) / livewdcn(ivt(p))
+ ! NOTE(slevis, 2014-12) Beth Drewniak suggested this instead
+ livestemn_to_litter_p(m) = livestemn_p(m) / deltim
+ ENDIF
+
+ ! SAVE the current litterfall fluxes
+ prev_leafc_to_litter_p(m) = leafc_to_litter_p(m)
+ prev_frootc_to_litter_p(m) = frootc_to_litter_p(m)
+
+ ENDIF ! ENDIF offset period
+ ENDDO
+
+ END SUBROUTINE CNOffsetLitterfall
+
+ SUBROUTINE CNBackgroundLitterfall(i,ps,pe)
+
+! !DESCRIPTION:
+! Calculate leaf and fine root background turnover.
+! DISPLAY -> litter
+!
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+
+ ! !LOCAL VARIABLES:
+ real(r8) :: fr_leafn_to_litter ! fraction of the nitrogen turnover that goes to litter; remaining fraction is retranslocated
+ real(r8) :: ntovr_leaf
+ real(r8) :: denom
+ integer :: ivt, m
+ !-----------------------------------------------------------------------
+
+ DO m = ps , pe
+ ! only calculate these fluxes IF the background litterfall rate is non-zero
+ ivt = pftclass(m)
+ IF (bglfr_p(m) > 0._r8) THEN
+ ! units for bglfr are already 1/s
+ leafc_to_litter_p(m) = bglfr_p(m) * leafc_p(m)
+ frootc_to_litter_p(m) = bglfr_p(m) * frootc_p(m)
+ ! calculate the leaf N litterfall and retranslocation
+ leafn_to_litter_p(m) = leafc_to_litter_p(m) / lflitcn(ivt)
+ leafn_to_retransn_p(m) = (leafc_to_litter_p(m) / leafcn(ivt)) - leafn_to_litter_p(m)
+
+ frootn_to_litter_p(m) = frootc_to_litter_p(m) / frootcn(ivt)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CNBackgroundLitterfall
+
+ SUBROUTINE CNLivewoodTurnover(i,ps,pe)
+
+! !DESCRIPTION:
+! Livewood transfer to deadwood each year
+!
+! !ORIGINAL:
+! Community Land Model Version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2022, Revise the code to be compatible with CoLM code structure.
+
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: ps ! start pft index
+ integer, intent(in) :: pe ! END pft index
+
+ ! !LOCAL VARIABLES:
+ real(r8):: ctovr ! temporary variable for carbon turnover
+ real(r8):: ntovr ! temporary variable for nitrogen turnover
+ integer :: ivt, m
+ !-----------------------------------------------------------------------
+
+ DO m = ps, pe
+ ! only calculate these fluxes for woody types
+ ivt = pftclass(m)
+ IF (woody(ivt) > 0._r8) THEN
+
+ ! live stem to dead stem turnover
+
+ ctovr = livestemc_p(m) * lwtop
+ ntovr = ctovr / livewdcn(ivt)
+ livestemc_to_deadstemc_p(m) = ctovr
+ livestemn_to_deadstemn_p(m) = ctovr / deadwdcn(ivt)
+
+ livestemn_to_retransn_p(m) = ntovr - livestemn_to_deadstemn_p(m)
+ !matrix for livestemn_to_retransn will be added in allocation SUBROUTINE
+
+ ! live coarse root to dead coarse root turnover
+
+ ctovr = livecrootc_p(m) * lwtop
+ ntovr = ctovr / livewdcn(ivt)
+ livecrootc_to_deadcrootc_p(m) = ctovr
+ livecrootn_to_deadcrootn_p(m) = ctovr / deadwdcn(ivt)
+
+ livecrootn_to_retransn_p(m) = ntovr - livecrootn_to_deadcrootn_p(m)
+ ENDIF
+ ENDDO ! END pft loop
+
+ END SUBROUTINE CNLivewoodTurnover
+
+ SUBROUTINE CNGrainToProductPools(i,ps,pe)
+! !DESCRIPTION:
+! Summary crop production C & N from pft to patch
+!
+! !ORIGINAL:
+! Community Land Model Version 5.0 (CLM5)
+!
+! !REVISION:
+! Xingjie Lu, 2022, revised the code to be compatible with CoLM code structure
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+
+ integer m
+ real(r8) wtcol
+
+ DO m = ps, pe
+ wtcol = pftfrac(m)
+ grainc_to_cropprodc(i) = grainc_to_cropprodc(i) + grainc_to_food_p(m) * wtcol
+ grainn_to_cropprodn(i) = grainn_to_cropprodn(i) + grainn_to_food_p(m) * wtcol
+ ENDDO
+
+ END SUBROUTINE CNGrainToProductPools
+
+ SUBROUTINE CNLitterToColumn(i,ps,pe,nl_soil,npcropmin)
+
+! !DESCRIPTION:
+! Calculate column level litterfall flux from pft level litterfall.
+
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code sturcture.
+
+ integer ,intent(in) :: i ! patch index
+ integer ,intent(in) :: nl_soil ! number of total soil layers
+ integer ,intent(in) :: ps ! start pft index
+ integer ,intent(in) :: pe ! END pft index
+ integer ,intent(in) :: npcropmin ! first crop pft index
+
+ integer j
+ integer ivt,m
+ real(r8):: wtcol
+
+ DO j = 1, nl_soil
+ DO m = ps,pe
+ ivt = pftclass(m)
+ wtcol = pftfrac(m)
+ ! leaf litter carbon fluxes
+ phenology_to_met_c(j,i) = phenology_to_met_c(j,i) &
+ + leafc_to_litter_p(m) * lf_flab(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_cel_c(j,i) = phenology_to_cel_c(j,i) &
+ + leafc_to_litter_p(m) * lf_fcel(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_lig_c(j,i) = phenology_to_lig_c(j,i) &
+ + leafc_to_litter_p(m) * lf_flig(ivt) * wtcol * leaf_prof_p(j,m)
+
+ ! leaf litter nitrogen fluxes
+ phenology_to_met_n(j,i) = phenology_to_met_n(j,i) &
+ + leafn_to_litter_p(m) * lf_flab(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_cel_n(j,i) = phenology_to_cel_n(j,i) &
+ + leafn_to_litter_p(m) * lf_fcel(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_lig_n(j,i) = phenology_to_lig_n(j,i) &
+ + leafn_to_litter_p(m) * lf_flig(ivt) * wtcol * leaf_prof_p(j,m)
+
+ ! fine root litter carbon fluxes
+ phenology_to_met_c(j,i) = phenology_to_met_c(j,i) &
+ + frootc_to_litter_p(m) * fr_flab(ivt) * wtcol * froot_prof_p(j,m)
+ phenology_to_cel_c(j,i) = phenology_to_cel_c(j,i) &
+ + frootc_to_litter_p(m) * fr_fcel(ivt) * wtcol * froot_prof_p(j,m)
+ phenology_to_lig_c(j,i) = phenology_to_lig_c(j,i) &
+ + frootc_to_litter_p(m) * fr_flig(ivt) * wtcol * froot_prof_p(j,m)
+
+ ! fine root litter nitrogen fluxes
+ phenology_to_met_n(j,i) = phenology_to_met_n(j,i) &
+ + frootn_to_litter_p(m) * fr_flab(ivt) * wtcol * froot_prof_p(j,m)
+ phenology_to_cel_n(j,i) = phenology_to_cel_n(j,i) &
+ + frootn_to_litter_p(m) * fr_fcel(ivt) * wtcol * froot_prof_p(j,m)
+ phenology_to_lig_n(j,i) = phenology_to_lig_n(j,i) &
+ + frootn_to_litter_p(m) * fr_flig(ivt) * wtcol * froot_prof_p(j,m)
+
+ ! agroibis puts crop stem litter together with leaf litter
+ ! so I've used the leaf lf_f* parameters instead of making
+ ! new ones for now (slevis)
+ ! also for simplicity I've put "food" into the litter pools
+
+ IF (ivt >= npcropmin) THEN ! add livestemc to litter
+ ! stem litter carbon fluxes
+ phenology_to_met_c(j,i) = phenology_to_met_c(j,i) &
+ + livestemc_to_litter_p(m) * lf_flab(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_cel_c(j,i) = phenology_to_cel_c(j,i) &
+ + livestemc_to_litter_p(m) * lf_fcel(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_lig_c(j,i) = phenology_to_lig_c(j,i) &
+ + livestemc_to_litter_p(m) * lf_flig(ivt) * wtcol * leaf_prof_p(j,m)
+
+ ! stem litter nitrogen fluxes
+ phenology_to_met_n(j,i) = phenology_to_met_n(j,i) &
+ + livestemn_to_litter_p(m) * lf_flab(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_cel_n(j,i) = phenology_to_cel_n(j,i) &
+ + livestemn_to_litter_p(m) * lf_fcel(ivt) * wtcol * leaf_prof_p(j,m)
+ phenology_to_lig_n(j,i) = phenology_to_lig_n(j,i) &
+ + livestemn_to_litter_p(m) * lf_flig(ivt) * wtcol * leaf_prof_p(j,m)
+
+ ENDIF
+ ENDDO !END pft loop
+ ENDDO! END soil level loop
+
+ END SUBROUTINE CNLitterToColumn
+
+#ifdef CROP
+ SUBROUTINE vernalization(i,m,deltim)
+! !DESCRIPTION
+! vernalizatoin for winter wheat.
+
+! ORITINAL: F. Li's GPAM model
+ integer, intent(in) :: i ! patch index
+ integer, intent(in) :: m ! pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ ! LOCAL VARAIBLES:
+ real(r8) vtmin,vtopt,vtmax ! vernalization minimum, optimum, maximum temperature
+ real(r8) alpha ! parameter in calculating vernalization rate
+ real(r8) tc ! t_ref2m in degree C
+ real(r8) dt ! convert dtime from sec to hour
+
+
+! for all equations - temperatures must be in degrees (C)
+! calculate temperature of crown of crop (e.g., 3 cm soil temperature)
+! snow depth in centimeters
+
+ vtmin=-1.3_r8
+ vtopt=4.9_r8
+ vtmax=15.7_r8
+ dt=deltim/3600.0_r8 !dt is the time step in hour
+ alpha=log(2._r8)/log((vtmax-vtmin)/(vtopt-vtmin))
+
+ tc = tref_p(m)-tfrz
+ IF(tc >=vtmin .and. tc <= vtmax) THEN
+ cumvd_p(m)=cumvd_p(m) + (2._r8*((tc-vtmin)**alpha)*(vtopt-vtmin)**alpha &
+ - (tc-vtmin)**(2._r8*alpha))/(vtopt-vtmin)**(2._r8*alpha)*(dt/24._r8)
+ ENDIF
+
+ vf_p(m)=(cumvd_p(m)**5._r8)/(22.5_r8**5._r8+cumvd_p(m)**5._r8)
+
+ END SUBROUTINE vernalization
+#endif
+
+END MODULE MOD_BGC_Veg_CNPhenology
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNVegStructUpdate.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNVegStructUpdate.F90
new file mode 100644
index 0000000000..5ad9767291
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_CNVegStructUpdate.F90
@@ -0,0 +1,159 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_CNVegStructUpdate
+
+!----------------------------------------------------------------------------------
+! !DESCRIPTION:
+! On the radiation time step, USE C state variables and epc to diagnose
+! vegetation structure (LAI, SAI, height)
+!
+! ORIGINAL:
+! The Community Land Model version 5.0 (CLM5)
+!
+! REVISION:
+! Xingjie Lu, 2021, revised the CLM5 code to be compatible with CoLM code structure.
+!
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_LAIFEEDBACK, DEF_USE_Fire
+ USE MOD_Vars_Global, only: nc3crop, nc3irrig, nbrdlf_evr_shrub, nbrdlf_dcd_brl_shrub, &
+ npcropmin, ntmp_corn, nirrig_tmp_corn, ntrp_corn, nirrig_trp_corn, &
+ nsugarcane, nirrig_sugarcane, nmiscanthus, nirrig_miscanthus, &
+ nswitchgrass, nirrig_switchgrass, noveg
+
+ USE MOD_Vars_PFTimeVariables, only: lai_p, tlai_p, tsai_p, leafc_p, deadstemc_p, harvdate_p
+ USE MOD_Vars_TimeVariables, only: lai, tlai
+#ifdef CROP
+ USE MOD_BGC_Vars_PFTimeVariables, only: peaklai_p
+#endif
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+ USE MOD_BGC_Vars_TimeVariables, only: farea_burned
+ USE MOD_Const_PFT, only: dsladlai, slatop, laimx, woody
+
+ !CLM5
+ PUBLIC :: CNVegStructUpdate
+ !-----------------------------------------------------------------------
+
+CONTAINS
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE CNVegStructUpdate(i,ps,pe,deltim,npcropmin)
+
+ integer,intent(in) :: i ! patch index
+ integer,intent(in) :: ps ! start pft index
+ integer,intent(in) :: pe ! END pft index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer,intent(in) :: npcropmin ! first crop pft index
+
+ ! !LOCAL VARIABLES:
+ integer :: p,c,g ! indices
+ integer :: fp ! lake filter indices
+ real(r8) :: stocking ! #stems / ha (stocking density)
+ real(r8) :: ol ! thickness of canopy layer covered by snow (m)
+ real(r8) :: fb ! fraction of canopy layer covered by snow
+ real(r8) :: tlai_old ! for USE in Zeng tsai formula
+ real(r8) :: tsai_old ! for USE in Zeng tsai formula
+ real(r8) :: tsai_min ! PATCH derived minimum tsai
+ real(r8) :: tsai_alpha ! monthly decay rate of tsai
+ real(r8) :: frac_sno_adjusted ! frac_sno adjusted per frac_sno_threshold
+
+ real(r8), parameter :: dtsmonth = 2592000._r8 ! number of seconds in a 30 day month (60x60x24x30)
+ real(r8), parameter :: frac_sno_threshold = 0.999_r8 ! frac_sno values greater than this are treated as 1
+ real(r8), parameter :: natlaimx = 8._r8
+ real(r8), parameter :: theta = 0.8_r8
+ integer m, ivt
+!-----------------------------------------------------------------------
+! tsai formula from Zeng et. al. 2002, Journal of Climate, p1835
+!
+! tsai(m) = max( tsai_alpha(ivt(m))*tsai_old + max(tlai_old-tlai(m),0_r8), tsai_min(ivt(m)) )
+! notes:
+! * RHS tsai & tlai are from previous timestep
+! * should create tsai_alpha(ivt(m)) & tsai_min(ivt(m)) in pftconMod.F90 - slevis
+! * all non-crop patches USE same values:
+! crop tsai_alpha,tsai_min = 0.0,0.1
+! noncrop tsai_alpha,tsai_min = 0.5,1.0 (includes bare soil and urban)
+!-------------------------------------------------------------------------------
+
+ ! patch loop
+
+ lai (i) = 0._r8
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF (ivt /= noveg) THEN
+
+ tlai_old = tlai_p(m) ! n-1 value
+ tsai_old = tsai_p(m) ! n-1 value
+
+ IF(DEF_USE_LAIFEEDBACK)THEN
+ tlai_p(m) = ((natlaimx + slatop(ivt) * leafc_p(m)) &
+ - sqrt((natlaimx + slatop(ivt) * leafc_p(m))**2 &
+ - 4 * theta * natlaimx * slatop(ivt) * leafc_p(m)))/ (2*theta)
+ tlai_p(m) = max(0._r8, tlai_p(m))
+ lai_p (m) = tlai_p(m)
+ ENDIF
+
+ ! update the stem area index and height based on LAI, stem mass, and veg type.
+ ! With the exception of htop for woody vegetation, this follows the DGVM logic.
+
+ ! tsai formula from Zeng et. al. 2002, Journal of Climate, p1835 (see notes)
+ ! Assumes doalb time step .eq. CLM time step, SAI min and monthly decay factor
+ ! alpha are set by PFT, and alpha is scaled to CLM time step by multiplying by
+ ! deltim and dividing by dtsmonth (seconds in average 30 day month)
+ ! tsai_min scaled by 0.5 to match MODIS satellite derived values
+ IF (ivt == nc3crop .or. ivt == nc3irrig) THEN ! generic crops
+
+ tsai_alpha = 1.0_r8-1.0_r8*deltim/dtsmonth
+ tsai_min = 0.1_r8
+ ELSE
+ tsai_alpha = 1.0_r8-0.5_r8*deltim/dtsmonth
+ tsai_min = 1.0_r8
+ ENDIF
+ tsai_min = tsai_min * 0.5_r8
+ tsai_p(m) = max(tsai_alpha*tsai_old+max(tlai_old-tlai_p(m),0._r8),tsai_min)
+
+ ! calculate vegetation physiological parameters used in biomass heat storage
+ !
+ IF (woody(ivt) == 1._r8) THEN
+
+ ! trees and shrubs for now have a very simple allometry, with hard-wired
+ ! stem taper (height:radius) and nstem from PFT parameter file
+ ELSE IF (ivt >= npcropmin) THEN ! prognostic crops
+#ifdef CROP
+ IF (tlai_p(m) >= laimx(ivt)) peaklai_p(m) = 1 ! used in CNAllocation
+
+ IF (ivt == ntmp_corn .or. ivt == nirrig_tmp_corn .or. &
+ ivt == ntrp_corn .or. ivt == nirrig_trp_corn .or. &
+ ivt == nsugarcane .or. ivt == nirrig_sugarcane .or. &
+ ivt == nmiscanthus .or. ivt == nirrig_miscanthus .or. &
+ ivt == nswitchgrass .or. ivt == nirrig_switchgrass) THEN
+ tsai_p(m) = 0.1_r8 * tlai_p(m)
+ ELSE
+ tsai_p(m) = 0.2_r8 * tlai_p(m)
+ ENDIF
+
+ ! "stubble" after harvest
+ IF (harvdate_p(m) < 999 .and. tlai_p(m) == 0._r8) THEN
+ peaklai_p(m) = 0
+ IF(DEF_USE_Fire)THEN
+ tsai_p(m) = 0.25_r8*(1._r8-farea_burned(i)*0.90_r8) !changed by F. Li and S. Levis
+ ENDIF
+ ENDIF
+#endif
+ ENDIF
+
+ ENDIF
+
+! adjust lai and sai for burying by snow.
+! snow burial fraction for short vegetation (e.g. grasses, crops) changes with vegetation height
+! accounts for a 20% bending factor, as used in Lombardozzi et al. (2018) GRL 45(18), 9889-9897
+
+! NOTE: The following snow burial code is duplicated in SatellitePhenologyMod.
+! Changes in one place should be accompanied by similar changes in the other.
+ lai(i) = lai(i) + lai_p(m) * pftfrac(m)
+ ENDDO
+ tlai(i) = lai(i)
+
+ END SUBROUTINE CNVegStructUpdate
+
+END MODULE MOD_BGC_Veg_CNVegStructUpdate
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_NutrientCompetition.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_NutrientCompetition.F90
new file mode 100644
index 0000000000..3dba43ad97
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_Veg_NutrientCompetition.F90
@@ -0,0 +1,539 @@
+#include
+#ifdef BGC
+MODULE MOD_BGC_Veg_NutrientCompetition
+
+!----------------------------------------------------------------------------------------------------
+! !DESCRIPTION
+! This MODULE simulates the plant growth with regard to the available soil mineral nitrogen.
+! Allocation of NPP and N uptake to different vegetation CN pools uses allocation scheme from CLM4.5.
+! CALL sequence is: calc_plant_nutrient_demand_CLM45_default => calc_plant_nutrient_competition_CLM45_default
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+! Fang Li, 2022, add GPAM C allocation scheme for crop.
+
+ !
+ USE MOD_Precision
+ USE MOD_Const_PFT, only: &
+ woody, leafcn, frootcn, livewdcn, deadwdcn, graincn, &
+ froot_leaf, croot_stem, stem_leaf, flivewd, grperc, grpnow, fcur2, &
+! crop variables
+ astemf, arooti, arootf, fleafi, bfact, declfact, allconss, allconsl, fleafcn, fstemcn, ffrootcn, &
+ lfemerg, grnfill
+
+ USE MOD_Vars_PFTimeInvariants, only: pftclass, pftfrac
+
+ USE MOD_BGC_Vars_PFTimeVariables, only: &
+ xsmrpool_p, retransn_p, tempsum_npp_p, &
+ tempsum_potential_gpp_p, tempmax_retransn_p, annmax_retransn_p, annsum_potential_gpp_p, &
+! crop variables
+#ifdef CROP
+ croplive_p, hui_p, peaklai_p, &
+ aroot_p, astem_p, arepr_p, aleaf_p, astemi_p, aleafi_p, vf_p, &
+#endif
+ c_allometry_p, n_allometry_p, downreg_p, grain_flag_p, annsum_npp_p, &
+ leafc_p, livestemc_p, frootc_p
+ USE MOD_Vars_Global, only: nwwheat, nirrig_wwheat
+
+ USE MOD_BGC_Vars_TimeVariables, only: fpg
+ USE MOD_Vars_Global, only: ntmp_soybean, ntrp_soybean, nirrig_tmp_soybean, nirrig_trp_soybean
+
+ USE MOD_Vars_1DPFTFluxes, only: assim_p
+
+ USE MOD_BGC_Vars_1DPFTFluxes, only: &
+ leaf_xsmr_p, froot_xsmr_p, livestem_xsmr_p, livecroot_xsmr_p, grain_xsmr_p, cpool_to_xsmrpool_p, &
+ leaf_mr_p, froot_mr_p, livestem_mr_p, livecroot_mr_p, grain_mr_p, &
+ plant_ndemand_p, retransn_to_npool_p, cpool_to_leafc_p, cpool_to_leafc_storage_p, &
+ cpool_to_frootc_p, cpool_to_frootc_storage_p, cpool_to_livestemc_p, cpool_to_livestemc_storage_p, &
+ cpool_to_deadstemc_p, cpool_to_deadstemc_storage_p, cpool_to_livecrootc_p, cpool_to_livecrootc_storage_p, &
+ cpool_to_deadcrootc_p, cpool_to_deadcrootc_storage_p, cpool_to_grainc_p, cpool_to_grainc_storage_p, &
+ cpool_to_gresp_storage_p, npool_to_leafn_p, npool_to_leafn_storage_p, &
+ npool_to_frootn_p, npool_to_frootn_storage_p, npool_to_livestemn_p, npool_to_livestemn_storage_p, &
+ npool_to_deadstemn_p, npool_to_deadstemn_storage_p, npool_to_livecrootn_p, npool_to_livecrootn_storage_p, &
+ npool_to_deadcrootn_p, npool_to_deadcrootn_storage_p, npool_to_grainn_p, npool_to_grainn_storage_p, &
+ leafn_to_retransn_p, livestemn_to_retransn_p, frootn_to_retransn_p, &
+ plant_calloc_p, plant_nalloc_p, leaf_curmr_p, froot_curmr_p, livestem_curmr_p, livecroot_curmr_p, grain_curmr_p, &
+ psn_to_cpool_p, gpp_p, availc_p, avail_retransn_p, xsmrpool_recover_p, sminn_to_npool_p, excess_cflux_p
+
+ IMPLICIT NONE
+
+ PUBLIC calc_plant_nutrient_competition_CLM45_default
+ PUBLIC calc_plant_nutrient_demand_CLM45_default
+
+CONTAINS
+
+ SUBROUTINE calc_plant_nutrient_competition_CLM45_default(i,ps,pe,npcropmin)
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION
+! Calulate the nitrogen limitation on the plant growth based on the available
+! nitrogen and nitrogen demand from "calc_plant_nutrient_demand_CLM45_default".
+!
+! !Original:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+! Fang Li, 2022, add GPAM C allocation scheme for crop.
+
+ integer ,intent(in) :: i
+ integer ,intent(in) :: ps
+ integer ,intent(in) :: pe
+ integer ,intent(in) :: npcropmin
+
+ ! !LOCAL VARIABLES:
+ real(r8):: f1,f2,f3,f4,g1,g2 ! allocation parameters
+ real(r8):: cnl,cnfr,cnlw,cndw ! C:N ratios for leaf, fine root, and wood
+ real(r8):: fcur ! fraction of current psn displayed as growth
+ real(r8):: gresp_storage ! temporary variable for growth resp to storage
+ real(r8):: nlc ! temporary variable for total new leaf carbon allocation
+ real(r8):: f5 ! grain allocation parameter
+ real(r8):: cng ! C:N ratio for grain (= cnlw for now; slevis)
+ integer :: ivt, m
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ ! set some local allocation variables
+ f1 = froot_leaf(ivt)
+ f2 = croot_stem(ivt)
+
+ ! modified wood allocation to be 2.2 at npp=800 gC/m2/yr, 0.2 at npp=0,
+ ! constrained so that it does not go lower than 0.2 (under negative annsum_npp)
+ ! There was an error in this formula in previous version, WHERE the coefficient
+ ! was 0.004 instead of 0.0025.
+ ! This variable allocation is only for trees. Shrubs have a constant
+ ! allocation as specified in the pft-physiology file. The value is also used
+ ! as a trigger here: -1.0 means to USE the dynamic allocation (trees).
+ IF (stem_leaf(ivt) == -1._r8) THEN
+ f3 = (2.7/(1.0+exp(-0.004*(annsum_npp_p(m) - 300.0)))) - 0.4
+ ELSE
+ f3 = stem_leaf(ivt)
+ ENDIF
+
+ f4 = flivewd(ivt)
+ g1 = grperc(ivt)
+ g2 = grpnow(ivt)
+ cnl = leafcn(ivt)
+ cnfr = frootcn(ivt)
+ cnlw = livewdcn(ivt)
+ cndw = deadwdcn(ivt)
+ fcur = fcur2(ivt)
+
+#ifdef CROP
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ IF (croplive_p(m)) THEN
+ f1 = aroot_p(m) / aleaf_p(m)
+ f3 = astem_p(m) / aleaf_p(m)
+ f5 = arepr_p(m) / aleaf_p(m)
+ g1 = grperc(ivt)
+ ELSE
+ f1 = 0._r8
+ f3 = 0._r8
+ f5 = 0._r8
+ g1 = grperc(ivt)
+ ENDIF
+ ENDIF
+#endif
+
+ sminn_to_npool_p(m) = plant_ndemand_p(m) * fpg(i)
+
+ plant_nalloc_p(m) = sminn_to_npool_p(m) + retransn_to_npool_p(m)
+ plant_calloc_p(m) = plant_nalloc_p(m) * (c_allometry_p(m)/n_allometry_p(m))
+
+
+ excess_cflux_p(m) = availc_p(m) - plant_calloc_p(m)
+ ! reduce gpp fluxes due to N limitation
+ IF (gpp_p(m) > 0.0_r8) THEN
+ downreg_p(m) = excess_cflux_p(m)/gpp_p(m)
+ psn_to_cpool_p(m) = psn_to_cpool_p(m) * (1._r8 - downreg_p(m))
+ ELSE
+ downreg_p(m) = 0._r8
+ ENDIF
+
+ ! calculate the amount of new leaf C dictated by these allocation
+ ! decisions, and calculate the daily fluxes of C and N to current
+ ! growth and storage pools
+
+ ! fcur is the proportion of this day's growth that is displayed now,
+ ! the remainder going into storage for display next year through the
+ ! transfer pools
+
+ nlc = plant_calloc_p(m) / c_allometry_p(m)
+ cpool_to_leafc_p(m) = nlc * fcur
+ cpool_to_leafc_storage_p(m) = nlc * (1._r8 - fcur)
+ cpool_to_frootc_p(m) = nlc * f1 * fcur
+ cpool_to_frootc_storage_p(m) = nlc * f1 * (1._r8 - fcur)
+ IF (woody(ivt) == 1._r8) THEN
+ cpool_to_livestemc_p(m) = nlc * f3 * f4 * fcur
+ cpool_to_livestemc_storage_p(m) = nlc * f3 * f4 * (1._r8 - fcur)
+ cpool_to_deadstemc_p(m) = nlc * f3 * (1._r8 - f4) * fcur
+ cpool_to_deadstemc_storage_p(m) = nlc * f3 * (1._r8 - f4) * (1._r8 - fcur)
+ cpool_to_livecrootc_p(m) = nlc * f2 * f3 * f4 * fcur
+ cpool_to_livecrootc_storage_p(m) = nlc * f2 * f3 * f4 * (1._r8 - fcur)
+ cpool_to_deadcrootc_p(m) = nlc * f2 * f3 * (1._r8 - f4) * fcur
+ cpool_to_deadcrootc_storage_p(m) = nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur)
+ ENDIF
+#ifdef CROP
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ cpool_to_livestemc_p(m) = nlc * f3 * f4 * fcur
+ cpool_to_livestemc_storage_p(m) = nlc * f3 * f4 * (1._r8 - fcur)
+ cpool_to_deadstemc_p(m) = nlc * f3 * (1._r8 - f4) * fcur
+ cpool_to_deadstemc_storage_p(m) = nlc * f3 * (1._r8 - f4) * (1._r8 - fcur)
+ cpool_to_livecrootc_p(m) = nlc * f2 * f3 * f4 * fcur
+ cpool_to_livecrootc_storage_p(m) = nlc * f2 * f3 * f4 * (1._r8 - fcur)
+ cpool_to_deadcrootc_p(m) = nlc * f2 * f3 * (1._r8 - f4) * fcur
+ cpool_to_deadcrootc_storage_p(m) = nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur)
+ cpool_to_grainc_p(m) = nlc * f5 * fcur
+ cpool_to_grainc_storage_p(m) = nlc * f5 * (1._r8 -fcur)
+ ENDIF
+#endif
+
+ ! corresponding N fluxes
+ npool_to_leafn_p(m) = (nlc / cnl) * fcur
+ npool_to_leafn_storage_p(m) = (nlc / cnl) * (1._r8 - fcur)
+ npool_to_frootn_p(m) = (nlc * f1 / cnfr) * fcur
+ npool_to_frootn_storage_p(m) = (nlc * f1 / cnfr) * (1._r8 - fcur)
+ IF (woody(ivt) == 1._r8) THEN
+ npool_to_livestemn_p(m) = (nlc * f3 * f4 / cnlw) * fcur
+ npool_to_livestemn_storage_p(m) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur)
+ npool_to_deadstemn_p(m) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur
+ npool_to_deadstemn_storage_p(m) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur)
+ npool_to_livecrootn_p(m) = (nlc * f2 * f3 * f4 / cnlw) * fcur
+ npool_to_livecrootn_storage_p(m) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur)
+ npool_to_deadcrootn_p(m) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur
+ npool_to_deadcrootn_storage_p(m) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur)
+ ENDIF
+#ifdef CROP
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ cng = graincn(ivt)
+ npool_to_livestemn_p(m) = (nlc * f3 * f4 / cnlw) * fcur
+ npool_to_livestemn_storage_p(m) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur)
+ npool_to_deadstemn_p(m) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur
+ npool_to_deadstemn_storage_p(m) = (nlc * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur)
+ npool_to_livecrootn_p(m) = (nlc * f2 * f3 * f4 / cnlw) * fcur
+ npool_to_livecrootn_storage_p(m) = (nlc * f2 * f3 * f4 / cnlw) * (1._r8 - fcur)
+ npool_to_deadcrootn_p(m) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur
+ npool_to_deadcrootn_storage_p(m) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur)
+ npool_to_grainn_p(m) = (nlc * f5 / cng) * fcur
+ npool_to_grainn_storage_p(m) = (nlc * f5 / cng) * (1._r8 -fcur)
+ ENDIF
+#endif
+
+ ! Calculate the amount of carbon that needs to go into growth
+ ! respiration storage to satisfy all of the storage growth demands.
+ ! Allows for the fraction of growth respiration that is released at the
+ ! time of fixation, versus the remaining fraction that is stored for
+ ! release at the time of display. Note that all the growth respiration
+ ! fluxes that get released on a given timestep are calculated in growth_resp(),
+ ! but that the storage of C for growth resp during display of transferred
+ ! growth is assigned here.
+
+ gresp_storage = cpool_to_leafc_storage_p(m) + cpool_to_frootc_storage_p(m)
+ IF (woody(ivt) == 1._r8) THEN
+ gresp_storage = gresp_storage + cpool_to_livestemc_storage_p(m)
+ gresp_storage = gresp_storage + cpool_to_deadstemc_storage_p(m)
+
+ gresp_storage = gresp_storage + cpool_to_livecrootc_storage_p(m)
+ gresp_storage = gresp_storage + cpool_to_deadcrootc_storage_p(m)
+ ENDIF
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+ gresp_storage = gresp_storage + cpool_to_livestemc_storage_p(m)
+ gresp_storage = gresp_storage + cpool_to_grainc_storage_p(m)
+ ENDIF
+ cpool_to_gresp_storage_p(m) = gresp_storage * g1 * (1._r8 - g2)
+
+ tempsum_npp_p(m) = tempsum_npp_p(m) + plant_calloc_p(m)
+
+
+ ENDDO ! END patch loop
+
+ END SUBROUTINE calc_plant_nutrient_competition_CLM45_default
+
+ SUBROUTINE calc_plant_nutrient_demand_CLM45_default(i,ps,pe,deltim,npcropmin)
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION
+! Calculate allocation fraction and plant nitrogen demand.
+!
+! !Original:
+! The Community Land Model version 5.0 (CLM5.0)
+
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+! Fang Li, 2022, add GPAM C allocation scheme for crop.
+
+
+ integer ,intent(in) :: i
+ integer ,intent(in) :: ps
+ integer ,intent(in) :: pe
+ real(r8),intent(in) :: deltim
+ integer ,intent(in) :: npcropmin
+
+ ! !LOCAL VARIABLES:
+ integer :: j ! indices
+ real(r8):: mr ! maintenance respiration (gC/m2/s)
+ real(r8):: f1,f2,f3,f4,g1,g2 ! allocation parameters
+ real(r8):: cnl,cnfr,cnlw,cndw ! C:N ratios for leaf, fine root, and wood
+ real(r8):: curmr, curmr_ratio ! xsmrpool temporary variables
+ real(r8):: f5 ! grain allocation parameter
+ real(r8):: cng ! C:N ratio for grain (= cnlw for now; slevis)
+ real(r8):: fleaf ! fraction allocated to leaf
+ real(r8):: t1 ! temporary variable
+ real(r8):: dayscrecover ! number of days to recover negative cpool
+ integer :: ivt, m
+ dayscrecover = 30._r8
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ psn_to_cpool_p(m) = assim_p(m) * 12.011_r8
+
+ gpp_p(m) = psn_to_cpool_p(m)
+
+ ! get the time step total maintenance respiration
+ ! These fluxes should already be in gC/m2/s
+
+ mr = leaf_mr_p(m) + froot_mr_p(m)
+ IF (woody(ivt) == 1.0_r8) THEN
+ mr = mr + livestem_mr_p(m) + livecroot_mr_p(m)
+ ELSE IF (ivt >= npcropmin) THEN
+#ifdef CROP
+ IF (croplive_p(m)) mr = mr + livestem_mr_p(m) + grain_mr_p(m)
+#endif
+ ENDIF
+
+ ! carbon flux available for allocation
+ availc_p(m) = gpp_p(m) - mr
+
+ ! new code added for isotope calculations, 7/1/05, PET
+ ! IF mr > gpp, THEN some mr comes from gpp, the rest comes from
+ ! cpool (xsmr)
+ IF (mr > 0._r8 .and. availc_p(m) < 0._r8) THEN
+ curmr = gpp_p(m)
+ curmr_ratio = curmr / mr
+ ELSE
+ curmr_ratio = 1._r8
+ ENDIF
+ leaf_curmr_p(m) = leaf_mr_p(m) * curmr_ratio
+ leaf_xsmr_p(m) = leaf_mr_p(m) - leaf_curmr_p(m)
+ froot_curmr_p(m) = froot_mr_p(m) * curmr_ratio
+ froot_xsmr_p(m) = froot_mr_p(m) - froot_curmr_p(m)
+ livestem_curmr_p(m) = livestem_mr_p(m) * curmr_ratio
+ livestem_xsmr_p(m) = livestem_mr_p(m) - livestem_curmr_p(m)
+ livecroot_curmr_p(m) = livecroot_mr_p(m) * curmr_ratio
+ livecroot_xsmr_p(m) = livecroot_mr_p(m) - livecroot_curmr_p(m)
+ grain_curmr_p(m) = grain_mr_p(m) * curmr_ratio
+ grain_xsmr_p(m) = grain_mr_p(m) - grain_curmr_p(m)
+
+ ! no allocation when available c is negative
+ availc_p(m) = max(availc_p(m),0.0_r8)
+
+ ! test for an xsmrpool deficit
+ IF (xsmrpool_p(m) < 0.0_r8) THEN
+ ! Running a deficit in the xsmrpool, so the first priority is to let
+ ! some availc from this timestep accumulate in xsmrpool.
+ ! Determine rate of recovery for xsmrpool deficit
+
+ xsmrpool_recover_p(m) = -xsmrpool_p(m)/(dayscrecover*86400._r8)
+ IF (xsmrpool_recover_p(m) < availc_p(m)) THEN
+ ! available carbon reduced by amount for xsmrpool recovery
+ availc_p(m) = availc_p(m) - xsmrpool_recover_p(m)
+ ELSE
+ ! all of the available carbon goes to xsmrpool recovery
+ xsmrpool_recover_p(m) = availc_p(m)
+ availc_p(m) = 0.0_r8
+ ENDIF
+ cpool_to_xsmrpool_p(m) = xsmrpool_recover_p(m)
+ ENDIF
+
+ f1 = froot_leaf(ivt)
+ f2 = croot_stem(ivt)
+
+ ! modified wood allocation to be 2.2 at npp=800 gC/m2/yr, 0.2 at npp=0,
+ ! constrained so that it does not go lower than 0.2 (under negative annsum_npp)
+ ! This variable allocation is only for trees. Shrubs have a constant
+ ! allocation as specified in the pft-physiologfy file. The value is also used
+ ! as a trigger here: -1.0 means to USE the dynamic allocation (trees).
+
+ IF (stem_leaf(ivt) == -1._r8) THEN
+ f3 = (2.7/(1.0+exp(-0.004*(annsum_npp_p(m) - 300.0)))) - 0.4
+ ELSE
+ f3 = stem_leaf(ivt)
+ ENDIF
+
+ f4 = flivewd(ivt)
+ g1 = grperc(ivt)
+ g2 = grpnow(ivt)
+ cnl = leafcn(ivt)
+ cnfr = frootcn(ivt)
+ cnlw = livewdcn(ivt)
+ cndw = deadwdcn(ivt)
+
+ ! calculate f1 to f5 for prog crops following AgroIBIS subr phenocrop
+
+ f5 = 0._r8 ! continued intializations from above
+#ifdef CROP
+ IF (ivt >= npcropmin) THEN ! skip 2 generic crops
+
+ IF (croplive_p(m)) THEN
+ ! same phases appear in SUBROUTINE CropPhenology
+
+ ! Phase 1 completed:
+ ! ==================
+ ! Next phase: leaf emergence to start of leaf decline
+
+ IF (hui_p(m) >= lfemerg(ivt) .and. hui_p(m) < grnfill(ivt)) THEN
+ ! allocation rules for crops based on maturity and linear decrease
+ ! of amount allocated to roots over course of the growing season
+
+ IF (peaklai_p(m) == 1) THEN ! lai at maximum allowed
+ arepr_p(m) = 0._r8
+ aleaf_p(m) = 1.e-5_r8
+ astem_p(m) = 0._r8
+ aroot_p(m) = 1._r8 - arepr_p(m) - aleaf_p(m) - astem_p(m)
+ ELSE
+ arepr_p(m) = 0._r8
+ aroot_p(m) = arooti(ivt) - (arooti(ivt) - arootf(ivt)) * hui_p(m)
+ fleaf = fleafi(ivt) * (exp(-bfact(ivt)) - &
+ exp(-bfact(ivt)*hui_p(m)/grnfill(ivt))) / &
+ (exp(-bfact(ivt))-1) ! fraction alloc to leaf (from J Norman alloc curve)
+ aleaf_p(m) = max(1.e-5_r8, (1._r8 - aroot_p(m)) * fleaf)
+ astem_p(m) = 1._r8 - arepr_p(m) - aleaf_p(m) - aroot_p(m)
+ ENDIF
+ ! AgroIBIS included here an immediate adjustment to aleaf & astem IF the
+ ! predicted lai from the above allocation coefficients exceeded laimx.
+ ! We have decided to live with lais slightly higher than laimx by
+ ! enforcing the cap in the following tstep through the peaklai logic above.
+
+ astemi_p(m) = astem_p(m) ! SAVE for USE by equations after shift to reproductive
+ grain_flag_p(m) = 0._r8 ! phenology stage begins setting to 0 WHILE in phase 2
+
+ ! Phase 2 completed:
+ ! ==================
+ ! shift allocation either when enough hui are accumulated or maximum number
+ ! of days has elapsed since planting
+
+ ELSE IF (hui_p(m) >= grnfill(ivt)) THEN
+
+ aroot_p(m) = arooti(ivt) - (arooti(ivt) - arootf(ivt)) * min(1._r8, hui_p(m))
+ astem_p(m) = max(astemf(ivt), astem_p(m) * max(0._r8, (1._r8-hui_p(m))/ &
+ (1._r8-grnfill(ivt)))**allconss(ivt))
+ aleaf_p(m) = 1.e-5_r8
+
+ !Beth's retranslocation of leafn, stemn, rootn to organ
+ !Filter excess plant N to retransn pool for organ N
+ !only DO one time THEN hold grain_flag till onset next season
+
+ IF (astem_p(m) == astemf(ivt) .or. &
+ (ivt /= ntmp_soybean .and. ivt /= nirrig_tmp_soybean .and.&
+ ivt /= ntrp_soybean .and. ivt /= nirrig_trp_soybean)) THEN
+ IF (grain_flag_p(m) == 0._r8)THEN
+ t1 = 1._r8 / deltim
+ leafn_to_retransn_p(m) = t1 * ((leafc_p(m) / leafcn(ivt)) - (leafc_p(m) / &
+ fleafcn(ivt)))
+ livestemn_to_retransn_p(m) = t1 * ((livestemc_p(m) / livewdcn(ivt)) - (livestemc_p(m) / &
+ fstemcn(ivt)))
+ frootn_to_retransn_p(m) = 0._r8
+ IF (ffrootcn(ivt) > 0._r8) THEN
+ frootn_to_retransn_p(m) = t1 * ((frootc_p(m) / frootcn(ivt)) - (frootc_p(m) / &
+ ffrootcn(ivt)))
+ ENDIF
+ grain_flag_p(m) = 1._r8
+ ENDIF
+ ENDIF
+
+ arepr_p(m) = 1._r8 - aroot_p(m) - astem_p(m) - aleaf_p(m)
+ !F. Li for vernalization effect 2
+ IF(ivt == nwwheat .or. ivt == nirrig_wwheat) THEN
+ arepr_p(m) = arepr_p(m)*vf_p(m)
+ aroot_p(m) = 1._r8 - aleaf_p(m) - astem_p(m) - arepr_p(m)
+ ENDIF
+ ELSE ! pre emergence
+ aleaf_p(m) = 1.e-5_r8 ! allocation coefficients should be irrelevant
+ astem_p(m) = 0._r8 ! because crops have no live carbon pools;
+ aroot_p(m) = 0._r8 ! this applies to this "ELSE" and to the "ELSE"
+ arepr_p(m) = 0._r8 ! a few lines down
+ ENDIF
+
+ f1 = aroot_p(m) / aleaf_p(m)
+ f3 = astem_p(m) / aleaf_p(m)
+ f5 = arepr_p(m) / aleaf_p(m)
+ g1 = grperc(ivt)
+
+ ELSE ! .not croplive
+ f1 = 0._r8
+ f3 = 0._r8
+ f5 = 0._r8
+ g1 = grperc(ivt)
+ ENDIF
+ ENDIF
+#endif
+
+! based on available C, USE constant allometric relationships to
+! determine N requirements
+
+!RF. I removed the growth respiration from this, because it is used to calculate
+!plantCN for N uptake and c_allometry for allocation. IF we add gresp to the
+!allometry calculation THEN we allocate too much carbon since gresp is not allocated here.
+ IF (woody(ivt) == 1.0_r8) THEN
+ c_allometry_p(m) = (1._r8+g1)*(1._r8+f1+f3*(1._r8+f2))
+ n_allometry_p(m) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + &
+ (f3*(1._r8-f4)*(1._r8+f2))/cndw
+ ELSE IF (ivt >= npcropmin) THEN ! skip generic crops
+#ifdef CROP
+ cng = graincn(ivt)
+ c_allometry_p(m) = (1._r8+g1)*(1._r8+f1+f5+f3*(1._r8+f2))
+ n_allometry_p(m) = 1._r8/cnl + f1/cnfr + f5/cng + (f3*f4*(1._r8+f2))/cnlw + &
+ (f3*(1._r8-f4)*(1._r8+f2))/cndw
+#endif
+ ELSE
+ c_allometry_p(m) = 1._r8+g1+f1+f1*g1
+ n_allometry_p(m) = 1._r8/cnl + f1/cnfr
+ ENDIF
+
+ plant_ndemand_p(m) = availc_p(m)*(n_allometry_p(m)/c_allometry_p(m))
+
+ ! retranslocated N deployment depends on seasonal CYCLE of potential GPP
+ ! (requires one year run to accumulate demand)
+
+ tempsum_potential_gpp_p(m) = tempsum_potential_gpp_p(m) + gpp_p(m)
+
+ ! Adding the following line to carry max retransn info to CN Annual Update
+ tempmax_retransn_p(m) = max(tempmax_retransn_p(m),retransn_p(m))
+
+ ! Beth's code: crops pull from retransn pool only during grain fill;
+ ! retransn pool has N from leaves, stems, and roots for
+ ! retranslocation
+
+ IF (ivt >= npcropmin .and. grain_flag_p(m) == 1._r8) THEN
+ avail_retransn_p(m) = plant_ndemand_p(m)
+ ELSE IF (ivt < npcropmin .and. annsum_potential_gpp_p(m) > 0._r8) THEN
+ avail_retransn_p(m) = (annmax_retransn_p(m)/2._r8)*(gpp_p(m)/annsum_potential_gpp_p(m))/deltim
+ ELSE
+ avail_retransn_p(m) = 0.0_r8
+ ENDIF
+
+ ! make sure available retrans N doesn't exceed storage
+ avail_retransn_p(m) = min(avail_retransn_p(m), retransn_p(m)/deltim)
+
+ ! modify plant N demand according to the availability of
+ ! retranslocated N
+ ! take from retransn pool at most the flux required to meet
+ ! plant ndemand
+
+ IF (plant_ndemand_p(m) > avail_retransn_p(m)) THEN
+ retransn_to_npool_p(m) = avail_retransn_p(m)
+ ELSE
+ retransn_to_npool_p(m) = plant_ndemand_p(m)
+ ENDIF
+
+ plant_ndemand_p(m) = plant_ndemand_p(m) - retransn_to_npool_p(m)
+
+ ENDDO ! END loop pft patch.
+
+ END SUBROUTINE calc_plant_nutrient_demand_CLM45_default
+
+END MODULE MOD_BGC_Veg_NutrientCompetition
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_driver.F90 b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_driver.F90
new file mode 100644
index 0000000000..6f386687ef
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/BGC/MOD_BGC_driver.F90
@@ -0,0 +1,166 @@
+#include
+#ifdef BGC
+
+ SUBROUTINE bgc_driver (i,idate,deltim,dlat,dlon)
+
+!-----------------------------------------------------------------------------------------------------------
+! !DESCRIPTION:
+! The trunk subroutine of the CoLM biogeochemistry module. The bgc_driver link different bgc processes, and
+! sequentially run each process step by step. bgc_driver was called by CoLMDRIVER includes vegetation
+! and soil CN cycle processes.
+!
+!
+! !ORIGINAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REFERENCES:
+! Lawrence, D.M., Fisher, R.A., Koven, C.D., Oleson, K.W., Swenson, S.C., Bonan, G., Collier, N.,
+! Ghimire, B., van Kampenhout, L., Kennedy, D. and Kluzek, E., 2019.
+! The Community Land Model version 5: Description of new features, benchmarking,
+! and impact of forcing uncertainty. Journal of Advances in Modeling Earth Systems, 11(12), 4245-4287.
+!
+! !REVISION:
+! Xingjie Lu, 2022, modify original CLM5 to be compatible with CoLM code structure.
+
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SASU, DEF_USE_DiagMatrix, DEF_USE_NITRIF, DEF_USE_CNSOYFIXN, DEF_USE_FIRE, DEF_USE_IRRIGATION
+ USE MOD_Const_Physical, only: tfrz, denh2o, denice
+ USE MOD_Vars_PFTimeInvariants, only: pftfrac
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_BGC_Vars_1DFluxes, only: plant_ndemand, ndep_to_sminn
+ USE MOD_BGC_Vars_1DPFTFluxes, only: plant_ndemand_p, cpool_to_leafc_p, crop_seedc_to_leaf_p
+ USE MOD_BGC_Veg_CNMResp, only: CNMResp
+ USE MOD_BGC_Soil_BiogeochemDecompCascadeBGC, only: decomp_rate_constants_bgc
+ USE MOD_BGC_Soil_BiogeochemPotential, only: SoilBiogeochemPotential
+ USE MOD_BGC_Soil_BiogeochemVerticalProfile, only: SoilBiogeochemVerticalProfile
+ USE MOD_BGC_Veg_NutrientCompetition, only: calc_plant_nutrient_demand_CLM45_default,&
+ calc_plant_nutrient_competition_CLM45_default
+ USE MOD_BGC_Soil_BiogeochemNitrifDenitrif, only: SoilBiogeochemNitrifDenitrif
+
+ USE MOD_BGC_Soil_BiogeochemCompetition, only: SoilBiogeochemCompetition
+ USE MOD_BGC_Soil_BiogeochemDecomp, only: SoilBiogeochemDecomp
+ USE MOD_BGC_Veg_CNPhenology, only: CNPhenology
+ USE MOD_BGC_Veg_CNGResp, only: CNGResp
+ USE MOD_BGC_CNCStateUpdate1, only: CStateUpdate1
+ USE MOD_BGC_CNNStateUpdate1, only: NStateUpdate1
+ USE MOD_BGC_Soil_BiogeochemNStateUpdate1, only: SoilBiogeochemNStateUpdate1
+ USE MOD_BGC_Soil_BiogeochemLittVertTransp, only: SoilBiogeochemLittVertTransp
+ USE MOD_BGC_Veg_CNGapMortality, only: CNGapMortality
+ USE MOD_BGC_CNCStateUpdate2, only: CStateUpdate2
+ USE MOD_BGC_CNNStateUpdate2, only: NStateUpdate2
+ USE MOD_BGC_CNCStateUpdate3, only: CStateUpdate3
+ USE MOD_BGC_Soil_BiogeochemNLeaching, only: SoilBiogeochemNLeaching
+ USE MOD_BGC_CNNStateUpdate3, only: NstateUpdate3
+ USE MOD_BGC_CNSummary, only: CNDriverSummarizeStates, CNDriverSummarizeFluxes
+ USE MOD_BGC_CNAnnualUpdate, only: CNAnnualUpdate
+ USE MOD_BGC_CNZeroFluxes, only: CNZeroFluxes
+ USE MOD_BGC_Veg_CNVegStructUpdate, only: CNVegStructUpdate
+ USE MOD_BGC_CNBalanceCheck, only: BeginCNBalance, CBalanceCheck, NBalanceCheck
+ USE MOD_BGC_CNSASU, only: CNSASU
+ USE MOD_BGC_Veg_CNNDynamics, only: CNNFixation
+#ifdef CROP
+ USE MOD_BGC_Veg_CNNDynamics, only: CNNFert, CNSoyfix
+ USE MOD_Irrigation, only: CalIrrigationNeeded
+#endif
+ USE MOD_TimeManager
+ USE MOD_Vars_Global, only: nl_soil, nl_soil_full, ndecomp_pools, ndecomp_pools_vr, ndecomp_transitions, npcropmin, &
+ z_soi,dz_soi,zi_soi,nbedrock,zmin_bedrock
+
+ USE MOD_BGC_Vars_TimeVariables, only: sminn_vr, col_begnb, skip_balance_check, decomp_cpools_vr
+ USE MOD_BGC_Veg_CNFireBase, only: CNFireFluxes
+ USE MOD_BGC_Veg_CNFireLi2016, only: CNFireArea
+
+ IMPLICIT NONE
+
+ integer ,intent(in) :: i ! patch index
+ real(r8),intent(in) :: deltim ! time step in seconds
+ integer ,intent(in) :: idate(3) ! current date (year, day of the year, seconds of the day)
+ real(r8),intent(in) :: dlat ! latitude (degrees)
+ real(r8),intent(in) :: dlon ! longitude (degrees)
+
+ integer :: ps, pe
+ integer j
+ ps = patch_pft_s(i)
+ pe = patch_pft_e(i)
+ CALL BeginCNBalance(i)
+ CALL CNZeroFluxes(i, ps, pe, nl_soil, ndecomp_pools, ndecomp_transitions)
+ CALL CNNFixation(i,idate)
+ CALL CNMResp(i, ps, pe, nl_soil, npcropmin)
+ CALL decomp_rate_constants_bgc(i, nl_soil, z_soi)
+ CALL SoilBiogeochemPotential(i,nl_soil,ndecomp_pools,ndecomp_transitions)
+ CALL SoilBiogeochemVerticalProfile(i,ps,pe,nl_soil,nl_soil_full,nbedrock,zmin_bedrock,z_soi,dz_soi)
+ IF(DEF_USE_NITRIF)THEN
+ CALL SoilBiogeochemNitrifDenitrif(i,nl_soil,dz_soi)
+ ENDIF
+ CALL calc_plant_nutrient_demand_CLM45_default(i,ps,pe,deltim,npcropmin)
+
+ plant_ndemand(i) = sum( plant_ndemand_p(ps:pe)*pftfrac(ps:pe) )
+
+ CALL SoilBiogeochemCompetition(i,deltim,nl_soil,dz_soi)
+ CALL calc_plant_nutrient_competition_CLM45_default(i,ps,pe,npcropmin)
+#ifdef CROP
+ IF(DEF_USE_CNSOYFIXN)THEN
+ CALL CNSoyfix (i, ps, pe, nl_soil)
+ ENDIF
+#endif
+
+ CALL SoilBiogeochemDecomp(i,nl_soil,ndecomp_pools,ndecomp_transitions, dz_soi)
+ CALL CNPhenology(i,ps,pe,nl_soil,idate(1:3),dz_soi,deltim,dlat,npcropmin,phase=1)
+ CALL CNPhenology(i,ps,pe,nl_soil,idate(1:3),dz_soi,deltim,dlat,npcropmin,phase=2)
+#ifdef CROP
+ CALL CNNFert(i, ps, pe)
+#endif
+ CALL CNGResp(i, ps, pe, npcropmin)
+#ifdef CROP
+ IF(DEF_USE_IRRIGATION)THEN
+ CALL CalIrrigationNeeded(i,idate,nl_soil,nbedrock,z_soi,zi_soi,dz_soi,deltim,dlon,npcropmin)
+ ENDIF
+#endif
+ ! update vegetation pools from phenology, allocation and nitrogen uptake
+ ! update soil N pools from decomposition and nitrogen competition
+ CALL CStateUpdate1(i, ps, pe, deltim, nl_soil, ndecomp_transitions, npcropmin)
+ CALL NStateUpdate1(i, ps, pe, deltim, nl_soil, ndecomp_transitions, npcropmin,dz_soi)
+ CALL SoilBiogeochemNStateUpdate1(i,deltim,nl_soil,ndecomp_transitions,dz_soi)
+
+ ! update soil pools from soil vertical mixing
+ CALL SoilBiogeochemLittVertTransp(i,deltim,nl_soil,nl_soil_full,ndecomp_pools,nbedrock,z_soi,zi_soi,dz_soi)
+
+ ! update vegetation pools from gap mortality
+ CALL CNGapMortality(i, ps, pe, nl_soil, npcropmin)
+ CALL CStateUpdate2(i, ps, pe, deltim, nl_soil)
+ CALL NStateUpdate2(i, ps, pe, deltim, nl_soil, dz_soi)
+
+ IF(DEF_USE_FIRE)THEN
+ ! update vegetation and fire pools from fire
+ CALL CNFireArea(i,ps,pe,dlat,nl_soil,idate,dz_soi)
+ CALL CNFireFluxes(i,ps,pe,dlat,nl_soil,ndecomp_pools)
+ ENDIF
+ CALL CStateUpdate3(i,ps,pe,deltim, nl_soil, ndecomp_pools)
+ CALL CNAnnualUpdate(i,ps,pe,deltim,idate(1:3))
+
+ ! update soil mineral nitrogen pools leaching
+ CALL SoilBiogeochemNLeaching(i,deltim,nl_soil,zi_soi,dz_soi)
+ CALL NstateUpdate3(i, ps, pe, deltim, nl_soil, ndecomp_pools,dz_soi)
+
+ IF(DEF_USE_SASU .or. DEF_USE_DiagMatrix)THEN
+ CALL CNSASU(i,ps,pe,deltim,idate(1:3),nl_soil,ndecomp_transitions,ndecomp_pools,ndecomp_pools_vr)! only for spin up
+ ENDIF
+
+ CALL CNDriverSummarizeStates(i,ps,pe,nl_soil,dz_soi,ndecomp_pools, .false.)
+ CALL CNDriverSummarizeFluxes(i,ps,pe,nl_soil,dz_soi,ndecomp_transitions,ndecomp_pools,deltim)
+
+ IF( .not. skip_balance_check(i) )THEN
+ CALL CBalanceCheck(i,ps,pe,nl_soil,dz_soi,deltim,dlat,dlon)
+ CALL NBalanceCheck(i,ps,pe,deltim,dlat,dlon)
+
+
+ ELSE
+ skip_balance_check(i) = .false.
+ ENDIF
+
+ CALL CNVegStructUpdate(i,ps,pe,deltim,npcropmin)
+
+ END SUBROUTINE bgc_driver
+
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/CoLMDRIVER.F90 b/src/core_atmosphere/physics/physics_colm2024/main/CoLMDRIVER.F90
new file mode 100644
index 0000000000..8cb4a8bba1
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/CoLMDRIVER.F90
@@ -0,0 +1,355 @@
+#include
+
+SUBROUTINE CoLMDRIVER (idate,deltim,dolai,doalb,dosst,oro)
+
+
+!=======================================================================
+!
+! CoLM MODEL DRIVER
+!
+! Initial : Yongjiu Dai, 1999-2014
+! Revised : Hua Yuan, Shupeng Zhang, Nan Wei, Xingjie Lu, Zhongwang Wei, Yongjiu Dai
+! 2014-2024
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz, rgas, vonkar
+ USE MOD_Const_LC
+ USE MOD_Vars_Global
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_1DForcing
+ USE MOD_Vars_1DFluxes
+ USE MOD_LandPatch, only: numpatch,landpatch
+ USE MOD_LandUrban, only: patch2urban
+ USE MOD_Namelist, only: DEF_forcing, DEF_URBAN_RUN
+ USE MOD_Forcing, only: forcmask_pch
+ USE omp_lib
+#ifdef HYPERSPECTRAL
+ USE MOD_HighRes_Parameters
+#endif
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3) ! model calendar for next time step (year, julian day, seconds)
+ real(r8), intent(in) :: deltim ! seconds in a time-step
+
+ logical, intent(in) :: dolai ! true if time for time-varying vegetation parameter
+ logical, intent(in) :: doalb ! true if time for surface albedo calculation
+ logical, intent(in) :: dosst ! true if time for update sst/ice/snow
+
+ real(r8), intent(inout) :: oro(numpatch) ! ocean(0)/seaice(2)/ flag
+
+ real(r8) :: deltim_phy
+ integer :: steps_in_one_deltim
+ integer :: i, m, u, k
+
+! ======================================================================
+
+#ifdef OPENMP
+!$OMP PARALLEL DO NUM_THREADS(OPENMP) &
+!$OMP PRIVATE(i, m, u, k, steps_in_one_deltim, deltim_phy) &
+!$OMP SCHEDULE(STATIC, 1)
+#endif
+
+ DO i = 1, numpatch
+
+ ! Apply forcing mask
+ IF (DEF_forcing%has_missing_value) THEN
+ IF (.not. forcmask_pch(i)) CYCLE
+ ENDIF
+
+ ! Apply patch mask, but still run virtual 2m WMO patch (patch ipxstt=-1)
+ IF (DEF_Output_2mWMO) THEN
+ IF (.not. patchmask(i) .and. (landpatch%ipxstt(i)>0) ) CYCLE
+ ELSE
+ IF (.not. patchmask(i)) CYCLE
+ ENDIF
+
+ m = patchclass(i)
+
+ steps_in_one_deltim = 1
+ ! deltim need to be within 1800s for water body with snow in order to avoid large
+ ! temperature fluctuations due to rapid snow heat conductance
+ IF(m == WATERBODY) steps_in_one_deltim = ceiling(deltim/1800.)
+ deltim_phy = deltim/steps_in_one_deltim
+
+ ! For non urban patch or slab urban
+ IF (.not.DEF_URBAN_RUN .or. m.ne.URBAN) THEN
+
+ DO k = 1, steps_in_one_deltim
+ ! ***** Call CoLM main program *****
+ !
+ CALL CoLMMAIN ( i,idate, coszen(i), deltim_phy, &
+ patchlonr(i), patchlatr(i), patchclass(i), patchtype(i), &
+ doalb, dolai, dosst, oro(i), &
+
+ ! SOIL INFORMATION AND LAKE DEPTH
+ soil_s_v_alb(i), soil_d_v_alb(i), soil_s_n_alb(i), soil_d_n_alb(i), &
+ vf_quartz(1:,i), vf_gravels(1:,i),vf_om(1:,i), vf_sand(1:,i), &
+ wf_gravels(1:,i),wf_sand(1:,i), porsl(1:,i), psi0(1:,i), &
+ bsw(1:,i), theta_r(1:,i), fsatmax(i), fsatdcf(i), &
+ topoweti(i), alp_twi(i), chi_twi(i), mu_twi(i), &
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm(1:,i), n_vgm(1:,i), L_vgm(1:,i), &
+ sc_vgm(1:,i), fc_vgm(1:,i), &
+#endif
+ hksati(1:,i), csol(1:,i), k_solids(1:,i), dksatu(1:,i), &
+ dksatf(1:,i), dkdry(1:,i), BA_alpha(1:,i), BA_beta(1:,i), &
+ rootfr(1:,m), lakedepth(i), dz_lake(1:,i), elvstd(i), &
+ BVIC(i), &
+ ! VEGETATION INFORMATION
+ htop(i), hbot(i), sqrtdi(m), &
+ effcon(m), vmax25(m), c3c4(m), &
+ kmax_sun(m), kmax_sha(m), kmax_xyl(m), kmax_root(m), &
+ psi50_sun(m), psi50_sha(m), psi50_xyl(m), psi50_root(m), &
+ ck(m), slti(m), hlti(m), shti(m), &
+ hhti(m), trda(m), trdm(m), trop(m), &
+ g1(m), g0(m), gradm(m), binter(m), &
+ extkn(m), chil(m), rho(1:,1:,m), tau(1:,1:,m), &
+#ifdef HYPERSPECTRAL
+ ! variables for high spectral resolution
+ ! note that rho & tau are depend on wavelength
+ clr_frac, cld_frac, &
+ reflectance(0:,1:,1:), transmittance(0:,1:,1:), &
+ soil_alb(1:,i), kw(1:), nw(1:), &
+#endif
+
+ ! ATMOSPHERIC FORCING
+ forc_pco2m(i), forc_po2m(i), forc_us(i), forc_vs(i), &
+ forc_t(i), forc_q(i), forc_prc(i), forc_prl(i), &
+ forc_rain(i), forc_snow(i), forc_psrf(i), forc_pbot(i), &
+ forc_sols(i), forc_soll(i), forc_solsd(i), forc_solld(i), &
+ forc_frl(i), forc_hgt_u(i), forc_hgt_t(i), forc_hgt_q(i), &
+ forc_rhoair(i), &
+#ifdef HYPERSPECTRAL
+ ! solar forcing
+ forc_solarin(i), &
+#endif
+ ! CBL height forcing
+ forc_hpbl(i), &
+ ! Aerosol deposition
+ forc_aerdep(:,i), &
+
+ ! LAND SURFACE VARIABLES REQUIRED FOR RESTART
+ z_sno(maxsnl+1:,i), dz_sno(maxsnl+1:,i), &
+ t_soisno(maxsnl+1:,i), wliq_soisno(maxsnl+1:,i), &
+ wice_soisno(maxsnl+1:,i), smp(1:,i), hk(1:,i), &
+ t_grnd(i), tleaf(i), ldew(i), ldew_rain(i), &
+ ldew_snow(i), fwet_snow(i), sag(i), scv(i), &
+ snowdp(i), fveg(i), fsno(i), sigf(i), &
+ green(i), lai(i), sai(i), alb(1:,1:,i), &
+ ssun(1:,1:,i), ssha(1:,1:,i), ssoi(:,:,i), ssno(:,:,i), &
+ thermk(i), extkb(i), extkd(i), vegwp(1:,i), &
+ gs0sun(i), gs0sha(i), &
+#ifdef HYPERSPECTRAL
+ ! high-res variables
+ alb_hires(1:,1:,i), &
+ sol_dir_ln_hires(1:,i), sol_dif_ln_hires(1:,i) ,&
+ sr_dir_ln_hires(1:,i) , sr_dif_ln_hires (1:,i) ,&
+ reflectance_out(:,:,i), transmittance_out(:,:,i),&
+#endif
+ ! Ozone Stress Variables
+ o3coefv_sun(i), o3coefv_sha(i), o3coefg_sun(i), o3coefg_sha(i), &
+ lai_old(i), o3uptakesun(i), o3uptakesha(i), forc_ozone(i), &
+ ! End ozone stress variables
+ ! WUE stomata model parameter
+ lambda(m), &
+ ! End WUE model parameter
+ zwt(i), wdsrf(i), wa(i), wetwat(i), &
+ t_lake(1:,i), lake_icefrac(1:,i), savedtke1(i), &
+
+ ! SNICAR snow model related
+ snw_rds(:,i), ssno_lyr(:,:,:,i), &
+ mss_bcpho(:,i), mss_bcphi(:,i), mss_ocpho(:,i), mss_ocphi(:,i), &
+ mss_dst1(:,i), mss_dst2(:,i), mss_dst3(:,i), mss_dst4(:,i), &
+
+ ! additional diagnostic variables for output
+ laisun(i), laisha(i), rootr(1:,i), rootflux(1:,i), &
+ rstfacsun_out(i),rstfacsha_out(i),gssun_out(i), gssha_out(i), &
+ assimsun_out(i), etrsun_out(i), assimsha_out(i), etrsha_out(i), &
+ h2osoi(1:,i), wat(i), rss(i), &
+
+ ! FLUXES
+ taux(i), tauy(i), fsena(i), fevpa(i), &
+ lfevpa(i), fsenl(i), fevpl(i), etr(i), &
+ fseng(i), fevpg(i), olrg(i), fgrnd(i), &
+ trad(i), tref(i), qref(i), t2m_wmo(i), &
+ frcsat(i), rsur(i), rsur_se(i), rsur_ie(i), &
+ rsub(i), &
+ rnof(i), qintr(i), qinfl(i), qlayer(0:,i), &
+ lake_deficit(i), qdrip(i), rst(i), assim(i), &
+ respc(i), sabvsun(i), sabvsha(i), sabg(i), &
+ sr(i), solvd(i), solvi(i), solnd(i), &
+ solni(i), srvd(i), srvi(i), srnd(i), &
+ srni(i), solvdln(i), solviln(i), solndln(i), &
+ solniln(i), srvdln(i), srviln(i), srndln(i), &
+ srniln(i), qcharge(i), xerr(i), zerr(i), &
+
+ ! TUNABLE modle constants
+ zlnd, zsno, csoilc, dewmx, &
+ ! 'wtfact' is updated to gridded 'fsatmax' data.
+ capr, cnfac, ssi, wimp, &
+ pondmx, smpmax, smpmin, trsmx0, &
+ tcrit, &
+
+ ! additional variables required by coupling with WRF model
+ emis(i), z0m(i), zol(i), rib(i), &
+ ustar(i), qstar(i), tstar(i), &
+ fm(i), fh(i), fq(i) )
+
+ ENDDO
+ ENDIF
+
+
+#if (defined BGC)
+ IF(patchtype(i) .eq. 0)THEN
+ !
+ ! ***** Call CoLM BGC model *****
+ !
+ CALL bgc_driver (i,idate(1:3),deltim, patchlatr(i)*180/PI,patchlonr(i)*180/PI)
+ ENDIF
+#endif
+
+
+#ifdef URBAN_MODEL
+ ! For urban model and urban patches
+ IF (DEF_URBAN_RUN .and. m.eq.URBAN) THEN
+
+ u = patch2urban(i)
+ !
+ ! ***** Call CoLM urban model *****
+ !
+ CALL CoLMMAIN_Urban ( &
+ ! MODEL RUNNING PARAMETERS
+ i ,idate ,coszen(i) ,deltim ,&
+ patchlonr(i) ,patchlatr(i) ,patchclass(i) ,patchtype(i) ,&
+
+ ! URBAN PARAMETERS
+ froof(u) ,flake(u) ,hroof(u) ,hlr(u) ,&
+ fgper(u) ,em_roof(u) ,em_wall(u) ,em_gimp(u) ,&
+ em_gper(u) ,cv_roof(:,u) ,cv_wall(:,u) ,cv_gimp(:,u) ,&
+ tk_roof(:,u) ,tk_wall(:,u) ,tk_gimp(:,u) ,z_roof(:,u) ,&
+ z_wall(:,u) ,dz_roof(:,u) ,dz_wall(:,u) ,lakedepth(i) ,&
+ dz_lake(1:,i) ,elvstd(i) ,BVIC(i) ,&
+
+ ! LUCY INPUT PARAMETERS
+ fix_holiday(:,u),week_holiday(:,u),hum_prof(:,u) ,pop_den(u) ,&
+ vehicle(:,u) ,weh_prof(:,u) ,wdh_prof(:,u) ,&
+
+ ! SOIL INFORMATION AND LAKE DEPTH
+ vf_quartz(1:,i) ,vf_gravels(1:,i),vf_om(1:,i) ,vf_sand(1:,i) ,&
+ wf_gravels(1:,i),wf_sand(1:,i) ,porsl(1:,i) ,psi0(1:,i) ,&
+ bsw(1:,i) ,theta_r(1:,i) ,fsatmax(i) ,fsatdcf(i) ,&
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm(1:,i) ,n_vgm(1:,i) ,L_vgm(1:,i) ,&
+ sc_vgm(1:,i) ,fc_vgm(1:,i) ,&
+#endif
+ hksati(1:,i) ,csol(1:,i) ,k_solids(1:,i) ,dksatu(1:,i) ,&
+ dksatf(1:,i) ,dkdry(1:,i) ,BA_alpha(1:,i) ,BA_beta(1:,i) ,&
+ alb_roof(:,:,u) ,alb_wall(:,:,u) ,alb_gimp(:,:,u) ,alb_gper(:,:,u) ,&
+
+ ! VEGETATION INFORMATION
+ htop(i) ,hbot(i) ,sqrtdi(m) ,chil(m) ,&
+ effcon(m) ,vmax25(m) ,c3c4(m) ,slti(m) ,hlti(m) ,&
+ shti(m) ,hhti(m) ,trda(m) ,trdm(m) ,&
+ trop(m) ,g1(m) ,g0(m) ,gradm(m) ,&
+ binter(m) ,extkn(m) ,rho(1:,1:,m) ,tau(1:,1:,m) ,&
+ rootfr(1:,m) ,&
+ ! WUE model parameter
+ lambda(m) ,&
+ ! END WUE model parameter
+
+ ! ATMOSPHERIC FORCING
+ forc_pco2m(i) ,forc_po2m(i) ,forc_us(i) ,forc_vs(i) ,&
+ forc_t(i) ,forc_q(i) ,forc_prc(i) ,forc_prl(i) ,&
+ forc_rain(i) ,forc_snow(i) ,forc_psrf(i) ,forc_pbot(i) ,&
+ forc_sols(i) ,forc_soll(i) ,forc_solsd(i) ,forc_solld(i) ,&
+ forc_frl(i) ,forc_hgt_u(i) ,forc_hgt_t(i) ,forc_hgt_q(i) ,&
+ forc_rhoair(i) ,Fhac(u) ,Fwst(u) ,Fach(u) ,&
+ Fahe(u) ,Fhah(u) ,vehc(u) ,meta(u) ,&
+
+ ! LAND SURFACE VARIABLES REQUIRED FOR RESTART
+ z_sno_roof (maxsnl+1:,u) ,z_sno_gimp (maxsnl+1:,u) ,&
+ z_sno_gper (maxsnl+1:,u) ,z_sno_lake (maxsnl+1:,u) ,&
+ dz_sno_roof (maxsnl+1:,u) ,dz_sno_gimp (maxsnl+1:,u) ,&
+ dz_sno_gper (maxsnl+1:,u) ,dz_sno_lake (maxsnl+1:,u) ,&
+ t_roofsno (maxsnl+1:,u) ,t_gimpsno (maxsnl+1:,u) ,&
+ t_gpersno (maxsnl+1:,u) ,t_lakesno (maxsnl+1:,u) ,&
+ wliq_roofsno(maxsnl+1:,u) ,wliq_gimpsno(maxsnl+1:,u) ,&
+ wliq_gpersno(maxsnl+1:,u) ,wliq_lakesno(maxsnl+1:,u) ,&
+ wice_roofsno(maxsnl+1:,u) ,wice_gimpsno(maxsnl+1:,u) ,&
+ wice_gpersno(maxsnl+1:,u) ,wice_lakesno(maxsnl+1:,u) ,&
+ z_sno (maxsnl+1:,i) ,dz_sno (maxsnl+1:,i) ,&
+ wliq_soisno (maxsnl+1:,i) ,wice_soisno (maxsnl+1:,i) ,&
+ t_soisno (maxsnl+1:,i) ,&
+ smp (1:,i) ,hk (1:,i) ,&
+ t_wallsun (1:,u) ,t_wallsha (1:,u) ,&
+
+ lai(i) ,sai(i) ,fveg(i) ,sigf(i) ,&
+ green(i) ,tleaf(i) ,ldew(i) ,ldew_rain(i) ,&
+ ldew_snow(i) ,fwet_snow(i) ,t_grnd(i) ,&
+
+ sag_roof(u) ,sag_gimp(u) ,sag_gper(u) ,sag_lake(u) ,&
+ scv_roof(u) ,scv_gimp(u) ,scv_gper(u) ,scv_lake(u) ,&
+ snowdp_roof(u) ,snowdp_gimp(u) ,snowdp_gper(u) ,snowdp_lake(u) ,&
+ fsno_roof(u) ,fsno_gimp(u) ,fsno_gper(u) ,fsno_lake(u) ,&
+ sag(i) ,scv(i) ,snowdp(i) ,fsno(i) ,&
+ extkd(i) ,alb(1:,1:,i) ,ssun(1:,1:,i) ,ssha(1:,1:,i) ,&
+ sroof(1:,1:,u) ,swsun(1:,1:,u) ,swsha(1:,1:,u) ,sgimp(1:,1:,u) ,&
+ sgper(1:,1:,u) ,slake(1:,1:,u) ,lwsun(u) ,lwsha(u) ,&
+ lgimp(u) ,lgper(u) ,lveg(u) ,fwsun(u) ,&
+ dfwsun(u) ,t_room(u) ,troof_inner(u) ,twsun_inner(u) ,&
+ twsha_inner(u) ,t_roommax(u) ,t_roommin(u) ,tafu(u) ,&
+
+ zwt(i) ,wdsrf(i) ,wa(i) ,&
+ t_lake(1:,i) ,lake_icefrac(1:,i), savedtke1(i) ,&
+
+ ! SNICAR snow model related
+ snw_rds(:,i) ,ssno_lyr(:,:,:,i) ,&
+ mss_bcpho(:,i) ,mss_bcphi(:,i) ,mss_ocpho(:,i) ,mss_ocphi(:,i) ,&
+ mss_dst1(:,i) ,mss_dst2(:,i) ,mss_dst3(:,i) ,mss_dst4(:,i) ,&
+
+ ! additional diagnostic variables for output
+ laisun(i) ,laisha(i) ,rss(i) ,&
+ rstfacsun_out(i),h2osoi(1:,i) ,wat(i) ,&
+
+ ! FLUXES
+ taux(i) ,tauy(i) ,fsena(i) ,fevpa(i) ,&
+ lfevpa(i) ,fsenl(i) ,fevpl(i) ,etr(i) ,&
+ fseng(i) ,fevpg(i) ,olrg(i) ,fgrnd(i) ,&
+ fsen_roof(u) ,fsen_wsun(u) ,fsen_wsha(u) ,fsen_gimp(u) ,&
+ fsen_gper(u) ,fsen_urbl(u) ,t_roof(u) ,t_wall(u) ,&
+ lfevp_roof(u) ,lfevp_gimp(u) ,lfevp_gper(u) ,lfevp_urbl(u) ,&
+ trad(i) ,tref(i) ,&
+ qref(i) ,rsur(i) ,rnof(i) ,qintr(i) ,&
+ qinfl(i) ,qdrip(i) ,rst(i) ,assim(i) ,&
+ respc(i) ,sabvsun(i) ,sabvsha(i) ,sabg(i) ,&
+ sr(i) ,solvd(i) ,solvi(i) ,solnd(i) ,&
+ solni(i) ,srvd(i) ,srvi(i) ,srnd(i) ,&
+ srni(i) ,solvdln(i) ,solviln(i) ,solndln(i) ,&
+ solniln(i) ,srvdln(i) ,srviln(i) ,srndln(i) ,&
+ srniln(i) ,qcharge(i) ,xerr(i) ,zerr(i) ,&
+
+ ! TUNABLE model constants
+ zlnd ,zsno ,csoilc ,dewmx ,&
+ ! 'wtfact' is updated to gridded 'fsatmax' data.
+ capr ,cnfac ,ssi ,wimp ,&
+ pondmx ,smpmax ,smpmin ,trsmx0 ,&
+ tcrit ,&
+
+ ! additional variables required by coupling with WRF model
+ emis(i) ,z0m(i) ,zol(i) ,rib(i) ,&
+ ustar(i) ,qstar(i) ,tstar(i) ,fm(i) ,&
+ fh(i) ,fq(i) ,forc_hpbl(i) )
+ rsub(i) = rnof(i) - rsur(i)
+ ENDIF
+
+#endif
+ ENDDO
+#ifdef OPENMP
+!$OMP END PARALLEL DO
+#endif
+
+END SUBROUTINE CoLMDRIVER
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/CoLMMAIN.F90 b/src/core_atmosphere/physics/physics_colm2024/main/CoLMMAIN.F90
new file mode 100644
index 0000000000..2b2ca31314
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/CoLMMAIN.F90
@@ -0,0 +1,1652 @@
+#include
+
+SUBROUTINE CoLMMAIN ( &
+
+ ! model running information
+ ipatch, idate, coszen, deltim, &
+ patchlonr, patchlatr, patchclass, patchtype, &
+ doalb, dolai, dosst, oro, &
+
+ ! soil information and lake depth
+ soil_s_v_alb, soil_d_v_alb, soil_s_n_alb, soil_d_n_alb, &
+ vf_quartz, vf_gravels, vf_om, vf_sand, &
+ wf_gravels, wf_sand, porsl, psi0, &
+ bsw, theta_r, fsatmax, fsatdcf, &
+ topoweti, alp_twi, chi_twi, mu_twi, &
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm, n_vgm, L_vgm, &
+ sc_vgm, fc_vgm, &
+#endif
+ hksati, csol, k_solids, dksatu, &
+ dksatf, dkdry, BA_alpha, BA_beta, &
+ rootfr, lakedepth, dz_lake, elvstd, BVIC,&
+
+ ! vegetation information
+ htop, hbot, sqrtdi, &
+ effcon, vmax25, c3c4, &
+ kmax_sun, kmax_sha, kmax_xyl, kmax_root, &
+ psi50_sun, psi50_sha, psi50_xyl, psi50_root, &
+ ck, slti, hlti, shti, &
+ hhti, trda, trdm, trop, &
+ g1, g0, gradm, binter, &
+ extkn, chil, rho, tau, &
+#ifdef HYPERSPECTRAL
+ ! variables for hyperspectral scheme
+ clr_frac, cld_frac, &
+ reflectance, transmittance, &
+ soil_alb, kw, nw, &
+#endif
+
+ ! atmospheric forcing
+ forc_pco2m, forc_po2m, forc_us, forc_vs, &
+ forc_t, forc_q, forc_prc, forc_prl, &
+ forc_rain, forc_snow, forc_psrf, forc_pbot, &
+ forc_sols, forc_soll, forc_solsd, forc_solld, &
+ forc_frl, forc_hgt_u, forc_hgt_t, forc_hgt_q, &
+ forc_rhoair, &
+#ifdef HYPERSPECTRAL
+ forc_solarin, &
+#endif
+
+ ! cbl forcing
+ forc_hpbl, &
+ ! aerosol deposition
+ forc_aerdep, &
+
+ ! land surface variables required for restart
+ z_sno, dz_sno, t_soisno, wliq_soisno, &
+ wice_soisno, smp, hk, t_grnd, &
+ tleaf, ldew, ldew_rain, ldew_snow, &
+ fwet_snow, sag, scv, snowdp, &
+ fveg, fsno, sigf, green, &
+ lai, sai, alb, ssun, &
+ ssha, ssoi, ssno, thermk, &
+ extkb, extkd, vegwp, gs0sun, &
+ gs0sha, &
+#ifdef HYPERSPECTRAL
+ alb_hires, &
+ sol_dir_ln_hires, sol_dif_ln_hires ,&
+ sr_dir_ln_hires , sr_dif_ln_hires ,&
+ reflectance_out , transmittance_out,&
+#endif
+ !Ozone stress variables
+ o3coefv_sun, o3coefv_sha, o3coefg_sun, o3coefg_sha, &
+ lai_old, o3uptakesun, o3uptakesha, forc_ozone, &
+ !End ozone stress variables
+ !WUE stomata model parameter
+ lambda, &
+ !End WUE stomata model parameter
+ zwt, wdsrf, wa, wetwat, &
+ t_lake, lake_icefrac, savedtke1, &
+
+ ! SNICAR snow model related
+ snw_rds, ssno_lyr, &
+ mss_bcpho, mss_bcphi, mss_ocpho, mss_ocphi, &
+ mss_dst1, mss_dst2, mss_dst3, mss_dst4, &
+
+ ! additional diagnostic variables for output
+ laisun, laisha, rootr, rootflux, &
+ rstfacsun_out,rstfacsha_out,gssun_out, gssha_out, &
+ assimsun_out, etrsun_out, assimsha_out, etrsha_out, &
+ h2osoi, wat, rss, &
+
+ ! FLUXES
+ taux, tauy, fsena, fevpa, &
+ lfevpa, fsenl, fevpl, etr, &
+ fseng, fevpg, olrg, fgrnd, &
+ trad, tref, qref, t2m_wmo, &
+ frcsat, rsur, rsur_se, rsur_ie, &
+ rsub, &
+ rnof, qintr, qinfl, qlayer, &
+ lake_deficit, qdrip, rst, assim, &
+ respc, sabvsun, sabvsha, sabg, &
+ sr, solvd, solvi, solnd, &
+ solni, srvd, srvi, srnd, &
+ srni, solvdln, solviln, solndln, &
+ solniln, srvdln, srviln, srndln, &
+ srniln, qcharge, xerr, zerr, &
+
+ ! TUNABLE model constants
+ zlnd, zsno, csoilc, dewmx, &
+ ! 'wtfact' is updated to gridded 'fsatmax' data.
+ capr, cnfac, ssi, wimp, &
+ pondmx, smpmax, smpmin, trsmx0, &
+ tcrit, &
+
+ ! additional variables required by coupling with WRF model
+ emis, z0m, zol, rib, &
+ ustar, qstar, tstar, fm, &
+ fh, fq )
+
+!=======================================================================
+!
+! Main subroutine, advance time information
+!
+! Initial : Yongjiu Dai, 1999-2014
+! Revised : Hua Yuan, Shupeng Zhang, Nan Wei, Xingjie Lu, Zhongwang Wei, Yongjiu Dai
+! 2014-2024
+!
+! FLOW DIAGRAM FOR CoLMMAIN
+!
+! CoLMMAIN ===>netsolar |> all surface
+! rain_snow_temp !> all surface
+!
+! LEAF_interception |]
+! newsnow |] patchtype = 0 (soil ground)
+! THERMAL |] = 1 (urban & built-up)
+! WATER |] = 2 (wetland)
+! snowcompaction |] = 3 (land ice)
+! snowlayerscombine |] = 4 (lake)
+! snowlayersdivide |]
+!
+! GLACIER_TEMP |] glacier model
+! GLACIER_WATER |]
+!
+! newsnow_lake |]
+! laketem |] lake scheme
+! snowwater_lake |]
+!
+! SOCEAN |> ocean and sea ice
+!
+! orb_coszen |> all surface
+! EcoModel (LAI_empirical) |> land - not actived
+! snowfraction |> land
+! albland |> land
+! albocean |> ocean & sea ice
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: tfrz, denh2o, denice, cpliq, cpice
+ USE MOD_Vars_TimeVariables, only: tlai, tsai, waterstorage
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+#endif
+ USE MOD_RainSnowTemp
+#ifdef HYPERSPECTRAL
+ USE MOD_NetSolar_Hyper
+#else
+ USE MOD_NetSolar
+#endif
+ USE MOD_OrbCoszen
+ USE MOD_NewSnow
+ USE MOD_Thermal
+ USE MOD_SoilSnowHydrology
+ USE MOD_SnowFraction
+ USE MOD_SnowLayersCombineDivide
+ USE MOD_Glacier
+ USE MOD_Lake
+ USE MOD_SimpleOcean
+#ifdef HYPERSPECTRAL
+ USE MOD_Albedo_hires
+ USE MOD_HighRes_Parameters, only: get_loc_params
+#else
+ USE MOD_Albedo
+#endif
+ USE MOD_LAIEmpirical
+ USE MOD_TimeManager
+ USE MOD_Namelist, only: DEF_Interception_scheme, DEF_USE_VariablySaturatedFlow, &
+ DEF_USE_PLANTHYDRAULICS, DEF_USE_IRRIGATION
+ USE MOD_LeafInterception
+#ifdef CROP
+ USE MOD_Irrigation, only: CalIrrigationApplicationFluxes
+#endif
+ USE MOD_SPMD_Task
+
+#ifdef EXTERNAL_LAKE
+ USE MOD_Lake_Driver, only: external_lake
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8),intent(in) :: deltim !seconds in a time step [second]
+ logical, intent(in) :: doalb !true if time for surface albedo calculation
+ logical, intent(in) :: dolai !true if time for leaf area index calculation
+ logical, intent(in) :: dosst !true to update sst/ice/snow before calculation
+
+ integer, intent(in) :: &
+ ipatch ! patch index
+
+ real(r8), intent(in) :: &
+ patchlonr ,&! longitude in radians
+ patchlatr ! latitude in radians
+
+ integer, intent(in) :: &
+ patchclass ,&! land patch class of USGS classification or others
+ patchtype ! land patch type (0=soil, 1=urban and built-up,
+ ! 2=wetland, 3=land ice, 4=land water bodies, 99 = ocean)
+
+ real(r8), intent(in) :: lakedepth ! lake depth (m)
+ real(r8), intent(inout) :: dz_lake(nl_lake) ! lake layer thickness (m)
+
+ real(r8), intent(in) :: &
+ elvstd ,&! standard deviation of elevation (m)
+ BVIC ,&! vic model parameter b
+
+ ! soil physical parameters and lake info
+ soil_s_v_alb ,&! albedo of visible of the saturated soil
+ soil_d_v_alb ,&! albedo of visible of the dry soil
+ soil_s_n_alb ,&! albedo of near infrared of the saturated soil
+ soil_d_n_alb ,&! albedo of near infrared of the dry soil
+
+ vf_quartz (nl_soil) ,&! volumetric fraction of quartz within mineral soil
+ vf_gravels (nl_soil) ,&! volumetric fraction of gravels
+ vf_om (nl_soil) ,&! volumetric fraction of organic matter
+ vf_sand (nl_soil) ,&! volumetric fraction of sand
+ wf_gravels (nl_soil) ,&! gravimetric fraction of gravels
+ wf_sand (nl_soil) ,&! gravimetric fraction of sand
+ porsl (nl_soil) ,&! fraction of soil that is voids [-]
+ psi0 (nl_soil) ,&! minimum soil suction [mm]
+ bsw (nl_soil) ,&! clapp and hornberger "b" parameter [-]
+ theta_r (1:nl_soil) ,&! residual water content (cm3/cm3)
+ fsatmax ,&! maximum saturated area fraction [-]
+ fsatdcf ,&! decay factor in calculation of saturated area fraction [1/m]
+ topoweti ,&! mean topographic wetness index
+ alp_twi ,&! alpha in three parameter gamma distribution of twi
+ chi_twi ,&! chi in three parameter gamma distribution of twi
+ mu_twi ,&! mu in three parameter gamma distribution of twi
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm(1:nl_soil) ,&! parameter corresponding approximately to inverse of air-entry value
+ n_vgm (1:nl_soil) ,&! a shape parameter
+ L_vgm (1:nl_soil) ,&! pore-connectivity parameter
+ sc_vgm (1:nl_soil) ,&! saturation at air entry value in classical vanGenuchten model [-]
+ fc_vgm (1:nl_soil) ,&! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+ hksati (nl_soil) ,&! hydraulic conductivity at saturation [mm h2o/s]
+ csol (nl_soil) ,&! heat capacity of soil solids [J/(m3 K)]
+ k_solids (nl_soil) ,&! thermal conductivity of minerals soil [W/m-K]
+ dksatu (nl_soil) ,&! thermal conductivity of saturated unfrozen soil [W/m-K]
+ dksatf (nl_soil) ,&! thermal conductivity of saturated frozen soil [W/m-K]
+ dkdry (nl_soil) ,&! thermal conductivity for dry soil [J/(K s m)]
+ BA_alpha (nl_soil) ,&! alpha in Balland and Arp(2005) thermal conductivity scheme
+ BA_beta (nl_soil) ,&! beta in Balland and Arp(2005) thermal conductivity scheme
+ rootfr (nl_soil) ,&! fraction of roots in each soil layer
+
+ ! vegetation static, dynamic, derived parameters
+ htop ,&! canopy top height [m]
+ hbot ,&! canopy bottom height [m]
+ sqrtdi ,&! inverse sqrt of leaf dimension [m**-0.5]
+ effcon ,&! quantum efficiency of RuBP regeneration (mol CO2/mol quanta)
+ vmax25 ,&! maximum carboxylation rate at 25 C at canopy top
+ kmax_sun ,&! Plant Hydraulics Parameters
+ kmax_sha ,&! Plant Hydraulics Parameters
+ kmax_xyl ,&! Plant Hydraulics Parameters
+ kmax_root ,&! Plant Hydraulics Parameters
+ psi50_sun ,&! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ psi50_sha ,&! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ psi50_xyl ,&! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ psi50_root ,&! water potential at 50% loss of root tissue conductance (mmH2O)
+ ck ,&! shape-fitting parameter for vulnerability curve (-)
+ slti ,&! slope of low temperature inhibition function [s3]
+ hlti ,&! 1/2 point of low temperature inhibition function [s4]
+ shti ,&! slope of high temperature inhibition function [s1]
+ hhti ,&! 1/2 point of high temperature inhibition function [s2]
+ trda ,&! temperature coefficient in gs-a model [s5]
+ trdm ,&! temperature coefficient in gs-a model [s6]
+ trop ,&! temperature coefficient in gs-a model
+ g1 ,&! conductance-photosynthesis slope parameter for medlyn model
+ g0 ,&! conductance-photosynthesis intercept for medlyn model
+ gradm ,&! conductance-photosynthesis slope parameter
+ binter ,&! conductance-photosynthesis intercep
+ extkn ,&! coefficient of leaf nitrogen allocation
+ chil ,&! leaf angle distribution factor
+ rho(2,2) ,&! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2) ,&! leaf transmittance (iw=iband, il=life and dead)
+#ifdef HYPERSPECTRAL
+ ! hyperspectral scheme parameters
+ clr_frac ( 211, 90, 5 ),&
+ cld_frac ( 211, 5 ) ,&
+ reflectance ( 0:15, 211, 2 ),&
+ transmittance( 0:15, 211, 2 ),&
+ soil_alb ( 211 ) ,&
+ kw ( 211 ) ,&
+ nw ( 211 ) ,&
+#endif
+
+ ! tunable parameters
+ zlnd ,&! roughness length for soil [m]
+ zsno ,&! roughness length for snow [m]
+ csoilc ,&! drag coefficient for soil under canopy [-]
+ dewmx ,&! maximum dew
+ ! wtfact ,&! (updated to gridded 'fsatmax') fraction of model area with high water table
+ capr ,&! tuning factor to turn first layer T into surface T
+ cnfac ,&! Crank Nicholson factor between 0 and 1
+ ssi ,&! irreducible water saturation of snow
+ wimp ,&! water impermeable if porosity less than wimp
+ pondmx ,&! ponding depth (mm)
+ smpmax ,&! wilting point potential in mm
+ smpmin ,&! restriction for min of soil poten. (mm)
+ trsmx0 ,&! max transpiration for moist soil+100% veg. [mm/s]
+ tcrit ! critical temp. to determine rain or snow
+
+ integer , intent(in) :: &
+ c3c4 ! 1 for C3, 2 for C4
+
+#ifdef HYPERSPECTRAL
+ ! Urban hyperspectral albedo
+ REAL(r8), ALLOCATABLE :: urban_albedo( :, :, : ) ! (cluster_id, season wavelength)
+ REAL(r8), ALLOCATABLE :: mean_albedo ( :, : ) ! (season, wavelength)
+ REAL(r8), ALLOCATABLE :: lat_north ( : ) ! (cluster_id)
+ REAL(r8), ALLOCATABLE :: lat_south ( : ) ! (cluster_id)
+ REAL(r8), ALLOCATABLE :: lon_east ( : ) ! (cluster_id)
+ REAL(r8), ALLOCATABLE :: lon_west ( : ) ! (cluster_id)
+
+#endif
+
+! Forcing
+!-----------------------------------------------------------------------
+ real(r8), intent(in) :: &
+ forc_pco2m ,&! partial pressure of CO2 at observational height [pa]
+ forc_po2m ,&! partial pressure of O2 at observational height [pa]
+ forc_us ,&! wind speed in eastward direction [m/s]
+ forc_vs ,&! wind speed in northward direction [m/s]
+ forc_t ,&! temperature at agcm reference height [kelvin]
+ forc_q ,&! specific humidity at agcm reference height [kg/kg]
+ forc_prc ,&! convective precipitation [mm/s]
+ forc_prl ,&! large scale precipitation [mm/s]
+ forc_psrf ,&! atmosphere pressure at the surface [pa]
+ forc_pbot ,&! atmosphere pressure at the bottom of the atmos. model level [pa]
+ forc_sols ,&! atm vis direct beam solar rad onto srf [W/m2]
+ forc_soll ,&! atm nir direct beam solar rad onto srf [W/m2]
+ forc_solsd ,&! atm vis diffuse solar rad onto srf [W/m2]
+ forc_solld ,&! atm nir diffuse solar rad onto srf [W/m2]
+#ifdef HYPERSPECTRAL
+ forc_solarin,&! atm solar rad onto srf [W/m2]
+#endif
+ forc_frl ,&! atmospheric infrared (longwave) radiation [W/m2]
+ forc_hgt_u ,&! observational height of wind [m]
+ forc_hgt_t ,&! observational height of temperature [m]
+ forc_hgt_q ,&! observational height of humidity [m]
+ forc_rhoair ,&! density air [kg/m3]
+ forc_hpbl ,&! atmospheric boundary layer height [m]
+ forc_aerdep(14)!atmospheric aerosol deposition data [kg/m/s]
+
+! Variables required for restart run
+!-----------------------------------------------------------------------
+ integer, intent(in) :: &
+ idate(3) ! next time-step /year/julian day/second in a day/
+
+ real(r8), intent(inout) :: oro ! ocean(0)/seaice(2)/ flag
+ real(r8), intent(inout) :: &
+ z_sno (maxsnl+1:0) ,&! layer depth (m)
+ dz_sno (maxsnl+1:0) ,&! layer thickness (m)
+ t_soisno (maxsnl+1:nl_soil) ,&! soil + snow layer temperature [K]
+ wliq_soisno(maxsnl+1:nl_soil) ,&! liquid water (kg/m2)
+ wice_soisno(maxsnl+1:nl_soil) ,&! ice lens (kg/m2)
+ hk(1:nl_soil) ,&! hydraulic conductivity [mm h2o/s]
+ smp(1:nl_soil) ,&! soil matrix potential [mm]
+
+ t_lake(nl_lake) ,&! lake temperature (kelvin)
+ lake_icefrac(nl_lake) ,&! lake mass fraction of lake layer that is frozen
+ savedtke1 ,&! top level eddy conductivity (W/m K)
+ vegwp(nvegwcs) ,&! ground surface temperature [k]
+ gs0sun ,&! working copy of sunlit stomata conductance
+ gs0sha ,&! working copy of shalit stomata conductance
+ !Ozone stress variables
+ lai_old ,&! lai in last time step
+ o3uptakesun ,&! Ozone does, sunlit leaf (mmol O3/m^2)
+ o3uptakesha ,&! Ozone does, shaded leaf (mmol O3/m^2)
+ forc_ozone ,&
+ o3coefv_sun ,&! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefv_sha ,&! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefg_sun ,&! Ozone stress factor for stomata on shaded leaf
+ o3coefg_sha ,&! Ozone stress factor for stomata on shaded leaf
+ !End ozone stress variables
+ !WUE stomata model parameter
+ lambda ,&! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+ !WUE stomata model parameter
+ t_grnd ,&! ground surface temperature [k]
+ tleaf ,&! leaf temperature [K]
+ ldew ,&! depth of water on foliage [kg/m2/s]
+ ldew_rain ,&! depth of rain on foliage[kg/m2/s]
+ ldew_snow ,&! depth of snow on foliage[kg/m2/s]
+ fwet_snow ,&! vegetation canopy snow fractional cover [-]
+ sag ,&! non dimensional snow age [-]
+ scv ,&! snow mass (kg/m2)
+ snowdp ,&! snow depth (m)
+ zwt ,&! the depth to water table [m]
+ wdsrf ,&! depth of surface water [mm]
+ wa ,&! water storage in aquifer [mm]
+ wetwat ,&! water storage in wetland [mm]
+
+ snw_rds ( maxsnl+1:0 ) ,&! effective grain radius (col,lyr) [microns, m-6]
+ mss_bcpho ( maxsnl+1:0 ) ,&! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi ( maxsnl+1:0 ) ,&! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho ( maxsnl+1:0 ) ,&! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi ( maxsnl+1:0 ) ,&! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 ( maxsnl+1:0 ) ,&! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 ( maxsnl+1:0 ) ,&! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 ( maxsnl+1:0 ) ,&! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 ( maxsnl+1:0 ) ,&! mass of dust species 4 in snow (col,lyr) [kg]
+ ssno_lyr (2,2,maxsnl+1:1) ,&! snow layer absorption [-]
+
+ fveg ,&! fraction of vegetation cover
+ fsno ,&! fractional snow cover
+ sigf ,&! fraction of veg cover, excluding snow-covered veg [-]
+ green ,&! greenness
+ lai ,&! leaf area index
+ sai ,&! stem area index
+#ifdef HYPERSPECTRAL
+ alb_hires(211, 2),& ! hyperspectral albedo
+#endif
+
+ coszen ,&! cosine of solar zenith angle
+ alb(2,2) ,&! averaged albedo [-]
+ ssun(2,2) ,&! sunlit canopy absorption for solar radiation
+ ssha(2,2) ,&! shaded canopy absorption for solar radiation
+ ssoi(2,2) ,&! ground soil absorption [-]
+ ssno(2,2) ,&! ground snow absorption [-]
+ thermk ,&! canopy gap fraction for tir radiation
+ extkb ,&! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd ! diffuse and scattered diffuse PAR extinction coefficient
+
+
+! additional diagnostic variables for output
+ real(r8), intent(out) :: &
+ laisun ,&! sunlit leaf area index
+ laisha ,&! shaded leaf area index
+ rstfacsun_out ,&! factor of soil water stress
+ rstfacsha_out ,&! factor of soil water stress
+ gssun_out ,&! sunlit stomata conductance
+ gssha_out ,&! shaded stomata conductance
+ wat ,&! total water storage
+ rss ,&! soil surface resistance [s/m]
+ rootr(nl_soil) ,&! water uptake fraction from different layers, all layers add to 1.0
+ rootflux(nl_soil),&! water exchange between soil and root in different layers
+ ! Positive: soil->root[?]
+#ifdef HYPERSPECTRAL
+ reflectance_out (211, 0:15) ,&! high resolution reflectance
+ transmittance_out(211, 0:15) ,&! high resolution transmittance
+#endif
+ h2osoi(nl_soil) ,&! volumetric soil water in layers [m3/m3]
+ qlayer(0:nl_soil),&! water flux at between soil layer [mm h2o/s]
+ lake_deficit ! lake deficit due to evaporation (mm h2o/s)
+
+ real(r8), intent(out) :: &
+ assimsun_out,&
+ etrsun_out ,&
+ assimsha_out,&
+ etrsha_out
+! Fluxes
+!-----------------------------------------------------------------------
+ real(r8), intent(out) :: &
+ taux ,&! wind stress: E-W [kg/m/s**2]
+ tauy ,&! wind stress: N-S [kg/m/s**2]
+ fsena ,&! sensible heat from canopy height to atmosphere [W/m2]
+ fevpa ,&! evapotranspiration from canopy height to atmosphere [mm/s]
+ lfevpa ,&! latent heat flux from canopy height to atmosphere [W/2]
+ fsenl ,&! sensible heat from leaves [W/m2]
+ fevpl ,&! evaporation+transpiration from leaves [mm/s]
+ etr ,&! transpiration rate [mm/s]
+ fseng ,&! sensible heat flux from ground [W/m2]
+ fevpg ,&! evaporation heat flux from ground [mm/s]
+ olrg ,&! outgoing long-wave radiation from ground+canopy
+ fgrnd ,&! ground heat flux [W/m2]
+ xerr ,&! water balance error at current time-step [mm/s]
+ zerr ,&! energy balance error at current time-step [W/m2]
+
+ tref ,&! 2 m height air temperature [K]
+ qref ,&! 2 m height air specific humidity
+ t2m_wmo ,&! 2 m wmo std air temperature [K]
+ trad ,&! radiative temperature [K]
+ frcsat ,&! fraction of saturation area
+ rsur ,&! surface runoff (mm h2o/s)
+ rsur_se ,&! saturation excess surface runoff (mm h2o/s)
+ rsur_ie ,&! infiltration excess surface runoff (mm h2o/s)
+ rsub ,&! subsurface runoff (mm h2o/s)
+ rnof ,&! total runoff (mm h2o/s)
+ qintr ,&! interception (mm h2o/s)
+ qinfl ,&! infiltration (mm h2o/s)
+ qdrip ,&! throughfall (mm h2o/s)
+ qcharge ,&! groundwater recharge [mm/s]
+
+ rst ,&! canopy stomatal resistance
+ assim ,&! canopy assimilation
+ respc ,&! canopy respiration
+
+ sabvsun ,&! solar absorbed by sunlit vegetation [W/m2]
+ sabvsha ,&! solar absorbed by shaded vegetation [W/m2]
+ sabg ,&! solar absorbed by ground [W/m2]
+ sr ,&! total reflected solar radiation (W/m2)
+ solvd ,&! incident direct beam vis solar radiation (W/m2)
+ solvi ,&! incident diffuse beam vis solar radiation (W/m2)
+ solnd ,&! incident direct beam nir solar radiation (W/m2)
+ solni ,&! incident diffuse beam nir solar radiation (W/m2)
+ srvd ,&! reflected direct beam vis solar radiation (W/m2)
+ srvi ,&! reflected diffuse beam vis solar radiation (W/m2)
+ srnd ,&! reflected direct beam nir solar radiation (W/m2)
+ srni ,&! reflected diffuse beam nir solar radiation (W/m2)
+ solvdln ,&! incident direct beam vis solar radiation at local noon(W/m2)
+ solviln ,&! incident diffuse beam vis solar radiation at local noon(W/m2)
+ solndln ,&! incident direct beam nir solar radiation at local noon(W/m2)
+ solniln ,&! incident diffuse beam nir solar radiation at local noon(W/m2)
+ srvdln ,&! reflected direct beam vis solar radiation at local noon(W/m2)
+ srviln ,&! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ srndln ,&! reflected direct beam nir solar radiation at local noon(W/m2)
+ srniln ,&! reflected diffuse beam nir solar radiation at local noon(W/m2)
+#ifdef HYPERSPECTRAL
+ sol_dir_ln_hires(211) ,&! incident direct beam vis solar radiation at local noon(W/m2)
+ sol_dif_ln_hires(211) ,&! incident diffuse beam vis solar radiation at local noon(W/m2)
+ sr_dir_ln_hires(211) ,&! reflected direct beam nir solar radiation at local noon(W/m2)
+ sr_dif_ln_hires(211) ,&! reflected diffuse beam nir solar radiation at local noon(W/m2)
+#endif
+
+ forc_rain ,&! rain [mm/s]
+ forc_snow ,&! snow [mm/s]
+
+ emis ,&! averaged bulk surface emissivity
+ z0m ,&! effective roughness [m]
+ zol ,&! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib ,&! bulk Richardson number in surface layer
+ ustar ,&! u* in similarity theory [m/s]
+ qstar ,&! q* in similarity theory [kg/kg]
+ tstar ,&! t* in similarity theory [K]
+ fm ,&! integral of profile function for momentum
+ fh ,&! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+!-------------------------- Local Variables ----------------------------
+ logical :: is_dry_lake
+
+ real(r8) :: &
+ calday ,&! Julian cal day (1.xx to 365.xx)
+ endwb ,&! water mass at the end of time step
+ errore ,&! energy balance error (Wm-2)
+ errorw ,&! water balance error (mm)
+ fiold(maxsnl+1:nl_soil), &! fraction of ice relative to the total water
+ w_old ,&! liquid water mass of the column at the previous time step (mm)
+
+ sabg_soil ,&! solar absorbed by soil fraction
+ sabg_snow ,&! solar absorbed by snow fraction
+ parsun ,&! PAR by sunlit leaves [W/m2]
+ parsha ,&! PAR by shaded leaves [W/m2]
+ qseva ,&! ground surface evaporation rate (mm h2o/s)
+ qsdew ,&! ground surface dew formation (mm h2o /s) [+]
+ qsubl ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qseva_soil ,&! ground soil surface evaporation rate (mm h2o/s)
+ qsdew_soil ,&! ground soil surface dew formation (mm h2o /s) [+]
+ qsubl_soil ,&! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qfros_soil ,&! surface dew added to soil ice pack (mm h2o /s) [+]
+ qseva_snow ,&! ground snow surface evaporation rate (mm h2o/s)
+ qsdew_snow ,&! ground snow surface dew formation (mm h2o /s) [+]
+ qsubl_snow ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros_snow ,&! surface dew added to snow pack (mm h2o /s) [+]
+ scvold ,&! snow cover for previous time step [mm]
+ sm ,&! rate of snowmelt [kg/(m2 s)]
+ ssw ,&! water volumetric content of soil surface layer [m3/m3]
+ tssub(7) ,&! surface/sub-surface temperatures [K]
+ tssea ,&! sea surface temperature [K]
+ totwb ,&! water mass at the beginning of time step
+ wt ,&! fraction of vegetation buried (covered) by snow [-]
+ z_soisno (maxsnl+1:nl_soil), &! layer depth (m)
+ dz_soisno(maxsnl+1:nl_soil), &! layer thickness (m)
+ zi_soisno(maxsnl :nl_soil) ! interface level below a "z" level (m)
+
+ real(r8) :: &
+ prc_rain ,&! convective rainfall [kg/(m2 s)]
+ prc_snow ,&! convective snowfall [kg/(m2 s)]
+ prl_rain ,&! large scale rainfall [kg/(m2 s)]
+ prl_snow ,&! large scale snowfall [kg/(m2 s)]
+ t_precip ,&! snowfall/rainfall temperature [kelvin]
+ bifall ,&! bulk density of newly fallen dry snow [kg/m3]
+ pg_rain ,&! rainfall onto ground including canopy runoff [kg/(m2 s)]
+ pg_snow ,&! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ qintr_rain ,&! rainfall interception (mm h2o/s)
+ qintr_snow ! snowfall interception (mm h2o/s)
+
+#ifdef HYPERSPECTRAL
+ real(r8) :: &
+ dir_frac(211),&! direct beam fraction
+ dif_frac(211) ! diffuse beam fraction
+#endif
+
+ integer snl ,&! number of snow layers
+ imelt(maxsnl+1:nl_soil), &! flag for: melting=1, freezing=2, Nothing happened=0
+ lb ,lbsn ,&! lower bound of arrays
+ j ! do looping index
+
+ ! For SNICAR snow model
+ !----------------------------------------------------------------------
+ integer snl_bef !number of snow layers
+ real(r8) forc_aer ( 14 ) !aerosol deposition from atmosphere (grd,aer) [kg m-1 s-1]
+ real(r8) snofrz (maxsnl+1:0) !snow freezing rate (col,lyr) [kg m-2 s-1]
+ real(r8) t_soisno_ (maxsnl+1:1) !soil + snow layer temperature [K]
+ real(r8) dz_soisno_ (maxsnl+1:1) !layer thickness (m)
+ real(r8) sabg_snow_lyr(maxsnl+1:1) !snow layer absorption [W/m-2]
+ !----------------------------------------------------------------------
+ ! For irrigation
+ !----------------------------------------------------------------------
+ real(r8) :: qflx_irrig_drip ! drip irrigation rate [mm/s]
+ real(r8) :: qflx_irrig_sprinkler ! sprinkler irrigation rate [mm/s]
+ real(r8) :: qflx_irrig_flood ! flood irrigation rate [mm/s]
+ real(r8) :: qflx_irrig_paddy ! paddy irrigation rate [mm/s]
+ !----------------------------------------------------------------------
+ real(r8) :: a, aa, gwat
+ real(r8) :: wextra, t_rain, t_snow
+ integer ps, pe, pc
+
+!-----------------------------------------------------------------------
+
+ z_soisno (maxsnl+1:0) = z_sno (maxsnl+1:0)
+ z_soisno (1:nl_soil ) = z_soi (1:nl_soil )
+ dz_soisno(maxsnl+1:0) = dz_sno(maxsnl+1:0)
+ dz_soisno(1:nl_soil ) = dz_soi(1:nl_soil )
+
+ ! SNICAR initialization
+ ! ---------------------
+
+ ! snow freezing rate (col,lyr) [kg m-2 s-1]
+ snofrz(:) = 0.
+
+ ! aerosol deposition value
+ IF (DEF_Aerosol_Readin) THEN
+ forc_aer(:) = forc_aerdep ! read from outside forcing file
+ ELSE
+ forc_aer(:) = 0. ! manual setting
+ ENDIF
+
+
+!======================================================================
+! [1] Solar absorbed by vegetation and ground
+! and precipitation information (rain/snow fall and precip temperature
+!======================================================================
+#ifdef HYPERSPECTRAL
+ CALL get_loc_params(forc_solarin, idate, coszen, patchlatr, patchlonr, clr_frac, cld_frac, dir_frac, dif_frac)
+
+ CALL netsolar_hyper (ipatch,idate,deltim,patchlonr,patchtype,&
+ forc_sols,forc_soll,forc_solsd,forc_solld,&
+ alb,ssun,ssha,lai,sai,rho,tau,ssoi,ssno,ssno_lyr,fsno,&
+ parsun,parsha,sabvsun,sabvsha,sabg,sabg_soil,sabg_snow,sabg_snow_lyr,&
+ sr,solvd,solvi,solnd,solni,srvd,srvi,srnd,srni,&
+ solvdln,solviln,solndln,solniln,srvdln,srviln,srndln,srniln,&
+ ! new variables for hyperspectral scheme
+ dir_frac, dif_frac, alb_hires ,&
+ sol_dir_ln_hires,sol_dif_ln_hires,&
+ sr_dir_ln_hires ,sr_dif_ln_hires )
+
+#else
+ CALL netsolar (ipatch,idate,deltim,patchlonr,patchtype,&
+ forc_sols,forc_soll,forc_solsd,forc_solld,&
+ alb,ssun,ssha,lai,sai,rho,tau,ssoi,ssno,ssno_lyr,fsno,&
+ parsun,parsha,sabvsun,sabvsha,sabg,sabg_soil,sabg_snow,sabg_snow_lyr,&
+ sr,solvd,solvi,solnd,solni,srvd,srvi,srnd,srni,&
+ solvdln,solviln,solndln,solniln,srvdln,srviln,srndln,srniln)
+#endif
+
+ CALL rain_snow_temp (patchtype, &
+ forc_t,forc_q,forc_psrf,forc_prc,forc_prl,forc_us,forc_vs,tcrit,&
+ prc_rain,prc_snow,prl_rain,prl_snow,t_precip,bifall)
+
+#ifdef MPAS_EMBEDDED_COLM
+ ! MPAS already provides hydrometeor phase; keep it while using CoLM for precipitation temperature.
+ prc_rain = max(0._r8, min(forc_prc, forc_rain))
+ prc_snow = max(0._r8, forc_prc - prc_rain)
+ prl_rain = max(0._r8, forc_rain - prc_rain)
+ prl_snow = max(0._r8, forc_snow - prc_snow)
+#else
+ forc_rain = prc_rain + prl_rain
+ forc_snow = prc_snow + prl_snow
+#endif
+
+!======================================================================
+
+ is_dry_lake = DEF_USE_Dynamic_Lake .and. (patchtype == 4) .and. &
+ ((wdsrf < 100.) .or. (zwt > 0.))
+
+
+ ! / SOIL GROUND (patchtype = 0)
+ IF ((patchtype <= 2) .or. is_dry_lake) THEN ! <=== is - URBAN and BUILT-UP (patchtype = 1)
+ ! \ WETLAND (patchtype = 2)
+ ! Dry Lake (patchtype = 4)
+
+! NOTE: PFT and PC are only for soil patches, i.e., patchtype=0.
+!======================================================================
+ ! initial set
+ scvold = scv ! snow mass at previous time step
+
+ snl = 0
+ DO j=maxsnl+1,0
+ IF(wliq_soisno(j)+wice_soisno(j)>0.) snl=snl-1
+ ENDDO
+
+ zi_soisno(0)=0.
+ IF (snl < 0) THEN
+ DO j = -1, snl, -1
+ zi_soisno(j)=zi_soisno(j+1)-dz_soisno(j+1)
+ ENDDO
+ ENDIF
+ DO j = 1,nl_soil
+ zi_soisno(j)=zi_soisno(j-1)+dz_soisno(j)
+ ENDDO
+
+ totwb = ldew + scv + sum(wice_soisno(1:)+wliq_soisno(1:)) + wa
+#ifdef CROP
+ if(DEF_USE_IRRIGATION) totwb = totwb + waterstorage(ipatch)
+#endif
+ totwb = totwb + wdsrf
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ IF (patchtype == 2) THEN
+ totwb = totwb + wetwat
+ ENDIF
+ ENDIF
+
+ fiold(:) = 0.0
+ IF (snl <0 ) THEN
+ fiold(snl+1:0)=wice_soisno(snl+1:0)/(wliq_soisno(snl+1:0)+wice_soisno(snl+1:0))
+ ENDIF
+
+!----------------------------------------------------------------------
+! [2] Irrigation
+!----------------------------------------------------------------------
+ qflx_irrig_drip = 0._r8
+ qflx_irrig_sprinkler = 0._r8
+ qflx_irrig_flood = 0._r8
+ qflx_irrig_paddy = 0._r8
+#ifdef CROP
+ IF (DEF_USE_IRRIGATION) THEN
+ IF (patchtype == 0) THEN
+ CALL CalIrrigationApplicationFluxes(ipatch,deltim,qflx_irrig_drip,qflx_irrig_sprinkler,qflx_irrig_flood,qflx_irrig_paddy)
+ ENDIF
+ ENDIF
+#endif
+!----------------------------------------------------------------------
+! [3] Canopy interception and precipitation onto ground surface
+!----------------------------------------------------------------------
+ IF (patchtype == 0) THEN
+
+#if (defined LULC_USGS || defined LULC_IGBP)
+ CALL LEAF_interception_wrap (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,forc_t,&
+ tleaf,prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,forc_hgt_u,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL LEAF_interception_pftwrap (ipatch,deltim,dewmx,forc_us,forc_vs,forc_t,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,forc_hgt_u,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+#endif
+
+ ELSE
+ CALL LEAF_interception_wrap (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,forc_t,&
+ tleaf,prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,forc_hgt_u,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+ ENDIF
+
+ qdrip = pg_rain + pg_snow
+
+!----------------------------------------------------------------------
+! [3] Initialize new snow nodes for snowfall / sleet
+!----------------------------------------------------------------------
+
+ snl_bef = snl
+
+ CALL newsnow (patchtype,maxsnl,deltim,t_grnd,pg_rain,pg_snow,bifall,&
+ t_precip,zi_soisno(:0),z_soisno(:0),dz_soisno(:0),t_soisno(:0),&
+ wliq_soisno(:0),wice_soisno(:0),fiold(:0),snl,sag,scv,snowdp,fsno,wetwat)
+
+!----------------------------------------------------------------------
+! [4] Energy and Water balance
+!----------------------------------------------------------------------
+ lb = snl + 1 !lower bound of array
+ lbsn = min(lb,0)
+
+ CALL THERMAL (ipatch,patchtype,is_dry_lake,lb ,deltim ,&
+ trsmx0 ,zlnd ,zsno ,csoilc ,&
+ dewmx ,capr ,cnfac ,vf_quartz ,&
+ vf_gravels ,vf_om ,vf_sand ,wf_gravels ,&
+ wf_sand ,csol ,porsl ,psi0 ,&
+#ifdef Campbell_SOIL_MODEL
+ bsw ,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r ,alpha_vgm ,n_vgm ,L_vgm ,&
+ sc_vgm ,fc_vgm ,&
+#endif
+ k_solids ,dksatu ,dksatf ,dkdry ,&
+ BA_alpha ,BA_beta ,lai ,laisun ,&
+ laisha ,sai ,htop ,hbot ,&
+ sqrtdi ,rootfr ,rstfacsun_out ,rstfacsha_out ,&
+ rss ,gssun_out ,gssha_out ,assimsun_out ,&
+ etrsun_out ,assimsha_out ,etrsha_out ,&
+
+ effcon ,vmax25,c3c4 ,hksati ,smp ,hk ,&
+ kmax_sun ,kmax_sha ,kmax_xyl ,kmax_root ,&
+ psi50_sun ,psi50_sha ,psi50_xyl ,psi50_root ,&
+ ck ,vegwp ,gs0sun ,gs0sha ,&
+ !Ozone stress variables
+ o3coefv_sun ,o3coefv_sha ,o3coefg_sun ,o3coefg_sha ,&
+ lai_old ,o3uptakesun ,o3uptakesha ,forc_ozone ,&
+ !End ozone stress variables
+ !WUE stomata model parameter
+ lambda ,&! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+ !WUE stomata model parameter
+ slti ,hlti ,shti ,hhti ,&
+ trda ,trdm ,trop ,g1 ,&
+ g0 ,gradm ,binter ,extkn ,&
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_rhoair ,&
+ forc_psrf ,forc_pco2m ,forc_hpbl ,forc_po2m ,&
+ coszen ,parsun ,parsha ,sabvsun ,&
+ sabvsha ,sabg ,sabg_soil ,sabg_snow ,&
+ forc_frl ,extkb ,extkd ,thermk ,&
+ fsno ,sigf ,dz_soisno(lb:) ,z_soisno(lb:) ,&
+ zi_soisno(lb-1:) ,tleaf ,t_soisno(lb:) ,wice_soisno(lb:) ,&
+ wliq_soisno(lb:) ,ldew ,ldew_rain ,ldew_snow ,&
+ fwet_snow ,scv ,snowdp ,imelt(lb:) ,&
+ taux ,tauy ,fsena ,fevpa ,&
+ lfevpa ,fsenl ,fevpl ,etr ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ rootr ,rootflux ,qseva ,qsdew ,&
+ qsubl ,qfros ,qseva_soil ,qsdew_soil ,&
+ qsubl_soil ,qfros_soil ,qseva_snow ,qsdew_snow ,&
+ qsubl_snow ,qfros_snow ,sm ,tref ,&
+ qref ,trad ,rst ,assim ,&
+ respc ,errore ,emis ,z0m ,&
+ zol ,rib ,ustar ,qstar ,&
+ tstar ,fm ,fh ,fq ,&
+ pg_rain ,pg_snow ,t_precip ,qintr_rain ,&
+ qintr_snow ,snofrz(lbsn:0) ,sabg_snow_lyr(lb:1) )
+
+ IF (.not. DEF_USE_VariablySaturatedFlow) THEN
+
+ CALL WATER_2014 (ipatch,patchtype ,lb ,nl_soil ,&
+ deltim ,z_soisno(lb:) ,dz_soisno(lb:) ,zi_soisno(lb-1:) ,&
+ bsw ,porsl ,psi0 ,hksati ,&
+ theta_r ,fsatmax ,fsatdcf ,elvstd ,&
+ BVIC ,rootr ,rootflux ,t_soisno(lb:) ,&
+ wliq_soisno(lb:) ,wice_soisno(lb:) ,smp ,hk ,&
+ pg_rain ,sm ,etr ,qseva ,&
+ qsdew ,qsubl ,qfros ,qseva_soil ,&
+ qsdew_soil ,qsubl_soil ,qfros_soil ,qseva_snow ,&
+ qsdew_snow ,qsubl_snow ,qfros_snow ,fsno ,&
+ rsur ,rnof ,qinfl ,pondmx ,&
+ ssi ,wimp ,smpmin ,zwt ,&
+ wdsrf ,wa ,qcharge ,&
+
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho(lbsn:0) ,mss_bcphi(lbsn:0) ,mss_ocpho(lbsn:0) ,mss_ocphi(lbsn:0) ,&
+ mss_dst1(lbsn:0) ,mss_dst2(lbsn:0) ,mss_dst3(lbsn:0) ,mss_dst4(lbsn:0) ,&
+! irrigation variables
+ qflx_irrig_drip ,qflx_irrig_flood ,qflx_irrig_paddy)
+ rsub = rnof - rsur
+ ELSE
+
+ CALL WATER_VSF (ipatch ,patchtype,is_dry_lake, lb ,nl_soil ,&
+ deltim ,z_soisno(lb:) ,dz_soisno(lb:) ,zi_soisno(lb-1:) ,&
+ bsw ,theta_r ,fsatmax ,fsatdcf ,&
+ topoweti ,alp_twi ,chi_twi ,mu_twi ,&
+ elvstd ,BVIC ,&
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm ,n_vgm ,L_vgm ,sc_vgm ,&
+ fc_vgm ,&
+#endif
+ porsl ,psi0 ,hksati ,rootr ,&
+ rootflux ,t_soisno(lb:) ,wliq_soisno(lb:) ,wice_soisno(lb:) ,&
+ smp ,hk ,pg_rain ,sm ,&
+ etr ,qseva ,qsdew ,qsubl ,&
+ qfros ,qseva_soil ,qsdew_soil ,qsubl_soil ,&
+ qfros_soil ,qseva_snow ,qsdew_snow ,qsubl_snow ,&
+ qfros_snow ,fsno ,frcsat ,rsur ,&
+ rsur_se ,rsur_ie ,rsub ,rnof ,&
+ qinfl ,&
+ qlayer ,ssi ,pondmx ,wimp ,&
+ zwt ,wdsrf ,wa ,wetwat ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho(lbsn:0) ,mss_bcphi(lbsn:0) ,mss_ocpho(lbsn:0) ,mss_ocphi(lbsn:0) ,&
+ mss_dst1(lbsn:0) ,mss_dst2(lbsn:0) ,mss_dst3(lbsn:0) ,mss_dst4(lbsn:0) ,&
+! irrigation variables
+ qflx_irrig_drip ,qflx_irrig_flood ,qflx_irrig_paddy)
+ ENDIF
+
+ IF (snl < 0) THEN
+ ! Compaction rate for snow
+ ! Natural compaction and metamorphosis. The compaction rate
+ ! is recalculated for every new timestep
+ lb = snl + 1 !lower bound of array
+ CALL snowcompaction (lb,deltim,&
+ imelt(lb:0),fiold(lb:0),t_soisno(lb:0),&
+ wliq_soisno(lb:0),wice_soisno(lb:0),forc_us,forc_vs,dz_soisno(lb:0))
+
+ ! Combine thin snow elements
+ lb = maxsnl + 1
+
+ IF (DEF_USE_SNICAR) THEN
+ CALL snowlayerscombine_snicar (lb,snl,&
+ z_soisno(lb:1),dz_soisno(lb:1),zi_soisno(lb-1:1),&
+ wliq_soisno(lb:1),wice_soisno(lb:1),t_soisno(lb:1),scv,snowdp,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ELSE
+ CALL snowlayerscombine (lb,snl,&
+ z_soisno(lb:1),dz_soisno(lb:1),zi_soisno(lb-1:1),&
+ wliq_soisno(lb:1),wice_soisno(lb:1),t_soisno(lb:1),scv,snowdp)
+ ENDIF
+
+ ! Divide thick snow elements
+ IF(snl<0) THEN
+ IF (DEF_USE_SNICAR) THEN
+ CALL snowlayersdivide_snicar (lb,snl,&
+ z_soisno(lb:0),dz_soisno(lb:0),zi_soisno(lb-1:0),&
+ wliq_soisno(lb:0),wice_soisno(lb:0),t_soisno(lb:0),&
+ mss_bcpho(lb:0),mss_bcphi(lb:0),mss_ocpho(lb:0),mss_ocphi(lb:0),&
+ mss_dst1(lb:0),mss_dst2(lb:0),mss_dst3(lb:0),mss_dst4(lb:0) )
+ ELSE
+ CALL snowlayersdivide (lb,snl,&
+ z_soisno(lb:0),dz_soisno(lb:0),zi_soisno(lb-1:0),&
+ wliq_soisno(lb:0),wice_soisno(lb:0),t_soisno(lb:0))
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! Set zero to the empty node
+ IF (snl > maxsnl) THEN
+ wice_soisno(maxsnl+1:snl) = 0.
+ wliq_soisno(maxsnl+1:snl) = 0.
+ t_soisno (maxsnl+1:snl) = 0.
+ z_soisno (maxsnl+1:snl) = 0.
+ dz_soisno (maxsnl+1:snl) = 0.
+ ENDIF
+
+ lb = snl + 1
+ t_grnd = t_soisno(lb)
+
+ IF (is_dry_lake) THEN
+ dz_lake = wdsrf*1.e-3/nl_lake
+ t_lake = t_soisno(1)
+ IF (t_soisno(1) >= tfrz) THEN
+ lake_icefrac = 0.
+ ELSE
+ lake_icefrac = 1.
+ ENDIF
+
+ IF (wdsrf >= 100.) THEN
+ CALL adjust_lake_layer (nl_lake, dz_lake, t_lake, lake_icefrac)
+ ENDIF
+ ENDIF
+
+ ! ----------------------------------------
+ ! energy balance
+ ! ----------------------------------------
+ zerr=errore
+#if (defined CoLMDEBUG)
+ IF (abs(errore) > .5) THEN
+ write(6,*) 'Warning: energy balance violation ',errore,patchclass
+ ENDIF
+#endif
+
+ ! ----------------------------------------
+ ! water balance
+ ! ----------------------------------------
+ endwb=sum(wice_soisno(1:)+wliq_soisno(1:))+ldew+scv + wa
+#ifdef CROP
+ IF (DEF_USE_IRRIGATION) endwb = endwb + waterstorage(ipatch)
+#endif
+
+ endwb = endwb + wdsrf
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ IF (patchtype == 2) THEN
+ endwb = endwb + wetwat
+ ENDIF
+ ENDIF
+#ifndef CatchLateralFlow
+ errorw=(endwb-totwb)-(forc_prc+forc_prl-fevpa-rnof)*deltim
+#else
+ ! for lateral flow, "rsur" is considered in HYDRO/MOD_Hydro_SurfaceFlow.F90
+ errorw=(endwb-totwb)-(forc_prc+forc_prl-fevpa)*deltim
+#endif
+
+ IF (.not. DEF_USE_VariablySaturatedFlow) THEN
+ IF (patchtype==2) errorw=0. !wetland
+ ENDIF
+
+ xerr=errorw/deltim
+
+#if (defined CoLMDEBUG)
+ IF (abs(errorw) > 1.e-3) THEN
+ IF (patchtype == 0) THEN
+ write(6,*) 'Warning: water balance violation in CoLMMAIN (soil) ', errorw
+ ELSEIF (patchtype == 1) THEN
+ write(6,*) 'Warning: water balance violation in CoLMMAIN (urban) ', errorw
+ ELSEIF (patchtype == 2) THEN
+ write(6,*) 'Warning: water balance violation in CoLMMAIN (wetland) ', errorw
+ ELSEIF (patchtype == 4) THEN
+ write(6,*) 'Warning: water balance violation in CoLMMAIN (dry lake) ', errorw
+ ENDIF
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+
+!======================================================================
+
+ ELSEIF (patchtype == 3) THEN ! <=== is LAND ICE (glacier/ice sheet) (patchtype = 3)
+
+!======================================================================
+ ! initial set
+ scvold = scv ! snow mass at previous time step
+
+ snl = 0
+ DO j=maxsnl+1,0
+ IF(wliq_soisno(j)+wice_soisno(j)>0.) snl=snl-1
+ ENDDO
+
+ zi_soisno(0)=0.
+ IF (snl < 0) THEN
+ DO j = -1, snl, -1
+ zi_soisno(j)=zi_soisno(j+1)-dz_soisno(j+1)
+ ENDDO
+ ENDIF
+ DO j = 1,nl_soil
+ zi_soisno(j)=zi_soisno(j-1)+dz_soisno(j)
+ ENDDO
+
+ totwb = scv + sum(wice_soisno(1:)+wliq_soisno(1:))
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ totwb = wdsrf + totwb
+ ENDIF
+
+ fiold(:) = 0.0
+ IF (snl <0 ) THEN
+ fiold(snl+1:0)=wice_soisno(snl+1:0)/(wliq_soisno(snl+1:0)+wice_soisno(snl+1:0))
+ ENDIF
+
+ pg_rain = prc_rain + prl_rain
+ pg_snow = prc_snow + prl_snow
+
+ t_rain = t_precip
+ IF (wliq_soisno(1) > dz_soisno(1)*denh2o) THEN
+ wextra = (wliq_soisno(1) - dz_soisno(1)*denh2o) / deltim
+ t_rain = (pg_rain*t_precip + wextra*t_soisno(1)) / (pg_rain + wextra)
+ pg_rain = pg_rain + wextra
+ wliq_soisno(1) = dz_soisno(1)*denh2o
+ totwb = totwb - wextra*deltim
+ ENDIF
+
+ t_snow = t_precip
+ IF (wice_soisno(1) > dz_soisno(1)*denice) THEN
+ wextra = (wice_soisno(1) - dz_soisno(1)*denice) / deltim
+ t_snow = (pg_snow*t_precip + wextra*t_soisno(1)) / (pg_snow + wextra)
+ pg_snow = pg_snow + wextra
+ wice_soisno(1) = dz_soisno(1)*denice
+ totwb = totwb - wextra*deltim
+ ENDIF
+
+ IF (pg_rain+pg_snow > 0) THEN
+ t_precip = (pg_rain*cpliq*t_rain + pg_snow*cpice*t_snow)/(pg_rain*cpliq+pg_snow*cpice)
+ ENDIF
+
+ !----------------------------------------------------------------
+ ! Initialize new snow nodes for snowfall / sleet
+ !----------------------------------------------------------------
+
+ snl_bef = snl
+
+ CALL newsnow (patchtype,maxsnl,deltim,t_grnd,pg_rain,pg_snow,bifall,&
+ t_precip,zi_soisno(:0),z_soisno(:0),dz_soisno(:0),t_soisno(:0),&
+ wliq_soisno(:0),wice_soisno(:0),fiold(:0),snl,sag,scv,snowdp,fsno)
+
+ !----------------------------------------------------------------
+ ! Energy and Water balance
+ !----------------------------------------------------------------
+ lb = snl + 1 !lower bound of array
+ lbsn = min(lb,0)
+
+ CALL GLACIER_TEMP (patchtype,lb ,nl_soil ,deltim ,&
+ zlnd ,zsno ,capr ,cnfac ,&
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_hpbl ,&
+ forc_rhoair ,forc_psrf ,coszen ,sabg ,&
+ forc_frl ,fsno ,dz_soisno(lb:) ,&
+ z_soisno(lb:),zi_soisno(lb-1:) ,&
+ t_soisno(lb:),wice_soisno(lb:),wliq_soisno(lb:) ,&
+ scv ,snowdp ,imelt(lb:) ,taux ,&
+ tauy ,fsena ,fevpa ,lfevpa ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ qseva ,qsdew ,qsubl ,qfros ,&
+ sm ,tref ,qref ,trad ,&
+ errore ,emis ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,pg_rain ,&
+ pg_snow ,t_precip ,&
+ snofrz(lbsn:0), sabg_snow_lyr(lb:1) )
+
+
+ IF (DEF_USE_SNICAR) THEN
+ CALL GLACIER_WATER_snicar (nl_soil ,maxsnl ,deltim ,&
+ z_soisno ,dz_soisno ,zi_soisno ,t_soisno ,&
+ wliq_soisno ,wice_soisno ,pg_rain ,pg_snow ,&
+ sm ,scv ,snowdp ,imelt ,&
+ fiold ,snl ,qseva ,qsdew ,&
+ qsubl ,qfros ,gwat ,ssi ,&
+ wimp ,forc_us ,forc_vs ,&
+ ! SNICAR
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 )
+ ELSE
+ CALL GLACIER_WATER ( nl_soil ,maxsnl ,deltim ,&
+ z_soisno ,dz_soisno ,zi_soisno ,t_soisno ,&
+ wliq_soisno ,wice_soisno ,pg_rain ,pg_snow ,&
+ sm ,scv ,snowdp ,imelt ,&
+ fiold ,snl ,qseva ,qsdew ,&
+ qsubl ,qfros ,gwat ,ssi ,&
+ wimp ,forc_us ,forc_vs )
+ ENDIF
+
+ IF (.not. DEF_USE_VariablySaturatedFlow) THEN
+ rsur = max(0.0,gwat)
+ rsub = 0.
+ rnof = rsur
+ ELSE
+ a = wdsrf + wliq_soisno(1) + gwat * deltim
+ IF (a > dz_soisno(1)*denh2o) THEN
+ wliq_soisno(1) = dz_soisno(1)*denh2o
+ wdsrf = a - wliq_soisno(1)
+ ELSE
+ wdsrf = 0.
+ wliq_soisno(1) = max(a, 1.e-8)
+ ENDIF
+#ifndef CatchLateralFlow
+ IF (wdsrf > pondmx) THEN
+ rsur = (wdsrf - pondmx) / deltim
+ wdsrf = pondmx
+ ELSE
+ rsur = 0.
+ ENDIF
+ rsub = 0.
+ rnof = rsur
+ rsur_se = rsur
+ rsur_ie = 0.
+#endif
+ ENDIF
+
+ lb = snl + 1
+ t_grnd = t_soisno(lb)
+
+ ! ----------------------------------------
+ ! energy and water balance check
+ ! ----------------------------------------
+ zerr=errore
+
+ endwb = scv + sum(wice_soisno(1:)+wliq_soisno(1:))
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ endwb = wdsrf + endwb
+ ENDIF
+
+#ifndef CatchLateralFlow
+ errorw=(endwb-totwb)-(pg_rain+pg_snow-fevpa-rnof)*deltim
+#else
+ errorw=(endwb-totwb)-(pg_rain+pg_snow-fevpa)*deltim
+#endif
+
+#if (defined CoLMDEBUG)
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ IF (abs(errorw) > 1.e-3) THEN
+ write(6,*) 'Warning: water balance violation in CoLMMAIN (land ice) ', errorw
+ CALL CoLM_stop ()
+ ENDIF
+ ENDIF
+#endif
+
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ xerr=errorw/deltim
+ ELSE
+ xerr = 0.
+ ENDIF
+
+!======================================================================
+
+ ELSEIF (patchtype == 4) THEN ! <=== is LAND WATER BODIES
+ ! (lake, reservoir and river) (patchtype = 4)
+
+!======================================================================
+
+ totwb = scv + sum(wice_soisno(1:)+wliq_soisno(1:)) + wa
+ IF (DEF_USE_Dynamic_Lake) THEN
+ totwb = totwb + wdsrf
+ ENDIF
+
+ snl = 0
+ DO j = maxsnl+1, 0
+ IF (wliq_soisno(j)+wice_soisno(j) > 0.) THEN
+ snl=snl-1
+ ENDIF
+ ENDDO
+
+ zi_soisno(0) = 0.
+ IF (snl < 0) THEN
+ DO j = -1, snl, -1
+ zi_soisno(j)=zi_soisno(j+1)-dz_soisno(j+1)
+ ENDDO
+ ENDIF
+
+ DO j = 1,nl_soil
+ zi_soisno(j)=zi_soisno(j-1)+dz_soisno(j)
+ ENDDO
+
+ scvold = scv !snow mass at previous time step
+ fiold(:) = 0.0
+ IF (snl < 0) THEN
+ fiold(snl+1:0)=wice_soisno(snl+1:0)/(wliq_soisno(snl+1:0)+wice_soisno(snl+1:0))
+ ENDIF
+
+ w_old = sum(wliq_soisno(1:)) + sum(wice_soisno(1:))
+
+ pg_rain = prc_rain + prl_rain
+ pg_snow = prc_snow + prl_snow
+
+#ifndef EXTERNAL_LAKE
+ CALL newsnow_lake ( DEF_USE_Dynamic_Lake, &
+ ! "in" arguments
+ ! ---------------
+ maxsnl ,nl_lake ,deltim ,dz_lake ,&
+ pg_rain ,pg_snow ,t_precip ,bifall ,&
+
+ ! "inout" arguments
+ ! ------------------
+ t_lake ,zi_soisno(:0),z_soisno(:0) ,&
+ dz_soisno(:0),t_soisno(:0) ,wliq_soisno(:0) ,wice_soisno(:0) ,&
+ fiold(:0) ,snl ,sag ,scv ,&
+ snowdp ,lake_icefrac )
+
+ CALL laketem ( &
+ ! "in" laketem arguments
+ ! ---------------------------
+ patchtype ,maxsnl ,nl_soil ,nl_lake ,&
+ patchlatr ,deltim ,forc_hgt_u ,forc_hgt_t ,&
+ forc_hgt_q ,forc_us ,forc_vs ,forc_t ,&
+ forc_q ,forc_rhoair ,forc_psrf ,forc_sols ,&
+ forc_soll ,forc_solsd ,forc_solld ,sabg ,&
+ forc_frl ,dz_soisno ,z_soisno ,zi_soisno ,&
+ dz_lake ,lakedepth ,vf_quartz ,vf_gravels ,&
+ vf_om ,vf_sand ,wf_gravels ,wf_sand ,&
+ porsl ,csol ,k_solids ,&
+ dksatu ,dksatf ,dkdry ,&
+ BA_alpha ,BA_beta ,forc_hpbl ,&
+
+ ! "inout" laketem arguments
+ ! ---------------------------
+ t_grnd ,scv ,snowdp ,t_soisno ,&
+ wliq_soisno ,wice_soisno ,imelt ,t_lake ,&
+ lake_icefrac ,savedtke1 ,&
+
+! SNICAR model variables
+ snofrz ,sabg_snow_lyr,&
+! END SNICAR model variables
+
+ ! "out" laketem arguments
+ ! ---------------------------
+ taux ,tauy ,fsena ,&
+ fevpa ,lfevpa ,fseng ,fevpg ,&
+ qseva ,qsubl ,qsdew ,qfros ,&
+ olrg ,fgrnd ,tref ,qref ,&
+ trad ,emis ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,sm )
+
+ CALL snowwater_lake ( DEF_USE_Dynamic_Lake, &
+ ! "in" snowater_lake arguments
+ ! ---------------------------
+ maxsnl ,nl_soil ,nl_lake ,deltim ,&
+ ssi ,wimp ,porsl ,pg_rain ,&
+ pg_snow ,dz_lake ,imelt(:0) ,fiold(:0) ,&
+ qseva ,qsubl ,qsdew ,qfros ,&
+
+ ! "inout" snowater_lake arguments
+ ! ---------------------------
+ z_soisno ,dz_soisno ,zi_soisno ,t_soisno ,&
+ wice_soisno ,wliq_soisno ,t_lake ,lake_icefrac ,&
+ gwat ,&
+ fseng ,fgrnd ,snl ,scv ,&
+ snowdp ,sm ,forc_us ,forc_vs ,&
+
+ ! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 )
+
+#else
+ CALL external_lake( &
+ ! "in" arguments
+ ! -------------------
+ deltim ,patchlatr ,patchlonr ,bifall ,&
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_rhoair ,&
+ forc_psrf ,forc_frl ,sabg ,forc_hpbl ,&
+ forc_sols ,forc_soll ,forc_solsd ,forc_solld ,&
+ prc_rain ,prl_rain ,prc_snow ,prl_snow ,&
+ t_precip ,ipatch ,&
+ ! "inout" arguments
+ ! -------------------
+ t_grnd ,t_lake ,t_soisno ,snl ,&
+ z_soisno ,zi_soisno ,dz_soisno ,scv ,&
+ savedtke1 ,sag ,snowdp ,lake_icefrac ,&
+ wliq_soisno ,wice_soisno ,gwat ,&
+! SNICAR model variables
+ forc_aer ,sabg_snow_lyr ,snofrz ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+! END SNICAR model variables
+ ! "out" arguments
+ ! -------------------
+ fsena ,fevpa ,lfevpa ,fseng ,&
+ fevpg ,olrg ,fgrnd ,trad ,&
+ qseva ,qsubl ,qsdew ,qfros ,&
+ taux ,tauy ,ustar ,qstar ,&
+ tstar ,emis ,sm ,zol ,&
+ tref ,qref ,fm ,fq ,&
+ rib ,fh ,z0m )
+#endif
+
+ IF (.not. DEF_USE_Dynamic_Lake) THEN
+ ! We assume the land water bodies have zero extra liquid water capacity
+ ! (i.e.,constant capacity), all excess liquid water are put into the runoff,
+ ! this unreasonable assumption should be updated in the future version
+ a = (sum(wliq_soisno(1:))+sum(wice_soisno(1:))+scv-w_old-scvold)/deltim
+ aa = qseva+qsubl-qsdew-qfros
+ rsur = max(0., pg_rain + pg_snow - aa - a)
+ rsub = 0.
+ rnof = rsur
+ rsur_se = rsur
+ rsur_ie = 0.
+ lake_deficit = - min(0., pg_rain + pg_snow - aa - a)
+ ELSE
+
+ wdsrf = sum(dz_lake) * 1.e3
+
+#ifndef CatchLateralFlow
+ IF (wdsrf > lakedepth*1.e3) THEN
+ rsur = (wdsrf - lakedepth*1.e3) / deltim
+ wdsrf = lakedepth*1.e3
+ dz_lake = dz_lake * lakedepth/sum(dz_lake)
+ CALL adjust_lake_layer (nl_lake, dz_lake, t_lake, lake_icefrac)
+ ELSE
+ rsur = 0.
+ ENDIF
+ rsub = 0.
+ rnof = rsur
+ rsur_se = rsur
+ rsur_ie = 0.
+#endif
+ ENDIF
+
+ endwb = scv + sum(wice_soisno(1:)+wliq_soisno(1:)) + wa
+ IF (DEF_USE_Dynamic_Lake) THEN
+ endwb = endwb + wdsrf
+ ELSE
+ endwb = endwb - lake_deficit * deltim
+ ENDIF
+
+ errorw = (endwb-totwb) - (forc_prc+forc_prl-fevpa) * deltim
+#ifndef CatchLateralFlow
+ errorw = errorw + rnof * deltim
+#endif
+
+#if (defined CoLMDEBUG)
+ IF (abs(errorw) > 1.e-3) THEN
+ write(*,*) 'Warning: water balance violation in CoLMMAIN (lake) ', errorw
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+
+ IF (DEF_USE_Dynamic_Lake) THEN
+ xerr = errorw / deltim
+ ELSE
+ xerr = 0.
+ ENDIF
+
+ ! Set zero to the empty node
+ IF (snl > maxsnl) THEN
+ wice_soisno(maxsnl+1:snl) = 0.
+ wliq_soisno(maxsnl+1:snl) = 0.
+ t_soisno (maxsnl+1:snl) = 0.
+ z_soisno (maxsnl+1:snl) = 0.
+ dz_soisno (maxsnl+1:snl) = 0.
+ ENDIF
+
+!======================================================================
+
+ ELSE ! <=== is OCEAN (patchtype >= 99)
+
+!======================================================================
+! simple ocean-sea ice model
+
+ tssea = t_grnd
+ tssub (1:7) = t_soisno (1:7)
+ CALL SOCEAN (dosst,deltim,oro,forc_hgt_u,forc_hgt_t,forc_hgt_q,&
+ forc_us,forc_vs,forc_t,forc_t,forc_rhoair,forc_psrf,&
+ sabg,forc_frl,tssea,tssub(1:7),scv,&
+ taux,tauy,fsena,fevpa,lfevpa,fseng,fevpg,tref,qref,&
+ z0m,zol,rib,ustar,qstar,tstar,fm,fh,fq,emis,olrg)
+
+ ! null data for sea component
+ z_soisno (:) = 0.0
+ dz_soisno (maxsnl+1:0) = 0.
+ t_soisno (:) = 0.0
+ t_soisno (1:7) = tssub(1:7)
+ wliq_soisno(:) = 0.0
+ wice_soisno(:) = 0.0
+ t_grnd = tssea
+ snowdp = scv/1000.*20.
+
+ trad = tssea
+ fgrnd = 0.0
+ rsur = 0.0
+ rsur_se = 0.0
+ rsur_ie = 0.0
+ rsub = 0.0
+ rnof = 0.0
+ xerr = 0.0
+
+!======================================================================
+ ENDIF
+
+!======================================================================
+! Preparation for the next time step
+! 1) time-varying parameters for vegetation
+! 2) fraction of snow cover
+! 3) solar zenith angle and
+! 4) albedos
+!======================================================================
+
+ ! cosine of solar zenith angle
+ calday = calendarday(idate)
+ coszen = orb_coszen(calday,patchlonr,patchlatr)
+
+ IF (patchtype <= 5) THEN !LAND
+#if (defined DYN_PHENOLOGY)
+ ! need to update lai and sai, fveg, green, they are done once in a day only
+ IF (dolai) THEN
+ CALL LAI_empirical(patchclass,nl_soil,rootfr,t_soisno(1:),lai,sai,fveg,green)
+ ENDIF
+#endif
+
+! only for soil patches
+!NOTE: lai from remote sensing has already considered snow coverage
+
+!NOTE: IF account for snow on vegetation:
+! 1) should use snow-free LAI data and 2) update LAI and SAI according to snowdp
+
+ IF (patchtype == 0) THEN
+
+#if (defined LULC_USGS || defined LULC_IGBP)
+ CALL snowfraction (tlai(ipatch),tsai(ipatch),z0m,zlnd,scv,snowdp,wt,sigf,fsno)
+ lai = tlai(ipatch)
+ sai = tsai(ipatch) * sigf
+
+ !NOTE: use snow-free LAI by defining namelist DEF_VEG_SNOW
+ IF ( DEF_VEG_SNOW ) THEN
+ lai = tlai(ipatch) * sigf
+ ENDIF
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+ CALL snowfraction_pftwrap (ipatch,zlnd,scv,snowdp,wt,sigf,fsno)
+ IF(DEF_USE_LAIFEEDBACK)THEN
+ lai = sum(lai_p(ps:pe)*pftfrac(ps:pe))
+ ELSE
+ lai_p(ps:pe) = tlai_p(ps:pe)
+ lai = tlai(ipatch)
+
+ !NOTE: use snow-free LAI by defining namelist DEF_VEG_SNOW
+ IF ( DEF_VEG_SNOW ) THEN
+ lai_p(ps:pe) = tlai_p(ps:pe)*sigf_p(ps:pe)
+ lai = sum(lai_p(ps:pe)*pftfrac(ps:pe))
+ ENDIF
+ ENDIF
+ sai_p(ps:pe) = tsai_p(ps:pe) * sigf_p(ps:pe)
+ sai = sum(sai_p(ps:pe)*pftfrac(ps:pe))
+#endif
+
+ ELSE
+ CALL snowfraction (tlai(ipatch),tsai(ipatch),z0m,zlnd,scv,snowdp,wt,sigf,fsno)
+ lai = tlai(ipatch)
+ sai = tsai(ipatch) * sigf
+
+ !NOTE: use snow-free LAI by defining namelist DEF_VEG_SNOW
+ IF ( DEF_VEG_SNOW ) THEN
+ lai = tlai(ipatch) * sigf
+ ENDIF
+ ENDIF
+
+ ! water volumetric content of soil surface layer [m3/m3]
+ ssw = min(1.,1.e-3*wliq_soisno(1)/dz_soisno(1))
+ IF (patchtype >= 3) ssw = 1.0
+
+! ============================================================================
+! Snow aging routine based on Flanner and Zender (2006), Linking snowpack
+! microphysics and albedo evolution, JGR, and Brun (1989), Investigation of
+! wet-snow metamorphism in respect of liquid-water content, Ann. Glacial.
+
+ dz_soisno_(:1) = dz_soisno(:1)
+ t_soisno_ (:1) = t_soisno (:1)
+
+ IF ((patchtype == 4) .and. (.not. is_dry_lake)) THEN
+ dz_soisno_(1) = dz_lake(1)
+ t_soisno_ (1) = t_lake (1)
+ ENDIF
+
+! ============================================================================
+ ! albedos
+ ! we supposed CALL it every time-step, because
+ ! other vegetation related parameters are needed to create
+ IF (doalb) THEN
+#ifdef HYPERSPECTRAL
+ CALL albland_HiRes (ipatch, patchtype,deltim,&
+ soil_s_v_alb,soil_d_v_alb,soil_s_n_alb,soil_d_n_alb,&
+ chil,rho,tau,fveg,green,lai,sai,fwet_snow,coszen,&
+ wt,fsno,scv,scvold,sag,ssw,pg_snow,forc_t,t_grnd,t_soisno_,dz_soisno_,&
+ snl,wliq_soisno,wice_soisno,snw_rds,snofrz,&
+ mss_bcpho,mss_bcphi,mss_ocpho,mss_ocphi,&
+ mss_dst1,mss_dst2,mss_dst3,mss_dst4,&
+ alb,ssun,ssha,ssoi,ssno,ssno_lyr,thermk,extkb,extkd,&
+
+ ! new parameters for hyperspectral scheme
+ alb_hires ,&
+ dir_frac , dif_frac ,&
+ reflectance , transmittance ,&
+ soil_alb, kw, nw, porsl(1) ,&
+ reflectance_out, transmittance_out,&
+ idate(2), patchlatr, patchlonr ,&
+ urban_albedo, mean_albedo, lat_north, lat_south, lon_west, lon_east )
+
+#else
+ CALL albland (ipatch,patchtype,deltim,&
+ soil_s_v_alb,soil_d_v_alb,soil_s_n_alb,soil_d_n_alb,&
+ chil,rho,tau,fveg,green,lai,sai,fwet_snow,coszen,&
+ wt,fsno,scv,scvold,sag,ssw,pg_snow,forc_t,t_grnd,t_soisno_,dz_soisno_,&
+ snl,wliq_soisno,wice_soisno,snw_rds,snofrz,&
+ mss_bcpho,mss_bcphi,mss_ocpho,mss_ocphi,&
+ mss_dst1,mss_dst2,mss_dst3,mss_dst4,&
+ alb,ssun,ssha,ssoi,ssno,ssno_lyr,thermk,extkb,extkd)
+#endif
+ ENDIF
+
+ ELSE !OCEAN
+ sag = 0.0
+ IF(doalb)THEN
+ CALL albocean (oro,scv,coszen,alb)
+ ENDIF
+ ENDIF
+
+ ! zero-filling set for glacier/ice-sheet/land water bodies/ocean components
+ IF ((patchtype > 2) .and. (.not. is_dry_lake)) THEN
+ lai = 0.0
+ sai = 0.0
+ laisun = 0.0
+ laisha = 0.0
+ green = 0.0
+ fveg = 0.0
+ sigf = 0.0
+
+ ssun(:,:) = 0.0
+ ssha(:,:) = 0.0
+ thermk = 0.0
+ extkb = 0.0
+ extkd = 0.0
+
+ tleaf = forc_t
+ ldew_rain = 0.0
+ ldew_snow = 0.0
+ fwet_snow = 0.0
+ ldew = 0.0
+ fsenl = 0.0
+ fevpl = 0.0
+ etr = 0.0
+ assim = 0.0
+ respc = 0.0
+
+ zerr = 0.
+
+ qinfl = 0.
+ qlayer = 0.
+ qdrip = forc_rain + forc_snow
+ qintr = 0.
+ frcsat = 1.
+ h2osoi = 0.
+ rstfacsun_out = 0.
+ rstfacsha_out = 0.
+ gssun_out = 0.
+ gssha_out = 0.
+ assimsun_out = 0.
+ etrsun_out = 0.
+ assimsha_out = 0.
+ etrsha_out = 0.
+ rootr = 0.
+ rootflux = 0.
+ zwt = 0.
+
+ IF (.not. DEF_USE_VariablySaturatedFlow) THEN
+ wa = 4800.
+ ENDIF
+
+ qcharge = 0.
+ IF (DEF_USE_PLANTHYDRAULICS)THEN
+ vegwp = -2.5e4
+ ENDIF
+ ENDIF
+
+ h2osoi = wliq_soisno(1:)/(dz_soisno(1:)*denh2o) + wice_soisno(1:)/(dz_soisno(1:)*denice)
+
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ wat = sum(wice_soisno(1:)+wliq_soisno(1:))+ldew+scv+wetwat
+ ELSE
+ wat = sum(wice_soisno(1:)+wliq_soisno(1:))+ldew+scv + wa
+ ENDIF
+
+ z_sno (maxsnl+1:0) = z_soisno (maxsnl+1:0)
+ dz_sno(maxsnl+1:0) = dz_soisno(maxsnl+1:0)
+
+END SUBROUTINE CoLMMAIN
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Const.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Const.F90
new file mode 100644
index 0000000000..f4280b27fe
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Const.F90
@@ -0,0 +1,143 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_Const
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! 1. Define constants (do not rely on satellite parameters) used in RTM.
+! 2. Define parameters (IGBP) used in RTM.
+!
+! REFERENCES:
+! [1] L-band Microwave Emission of the Biosphere (L-MEB) Model: Description
+! and calibration against experimental data sets over crop fields.
+!
+! [2] Wigneron, J. P., Jackson, T. J., O'neill, P., De Lannoy, G., de Rosnay, P., Walker,
+! J. P., ... & Kerr, Y. (2017). Modelling the passive microwave signature from land surfaces:
+! A review of recent results and application to the L-band SMOS & SMAP soil moisture retrieval algorithms.
+! Remote Sensing of Environment, 192, 238-262.
+!
+! AUTHOR:
+! Lu Li, 12/2024: Initial version
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: pi, N_land_classification
+
+ IMPLICIT NONE
+ SAVE
+
+ ! Constant variables
+ real(r8), parameter :: C = 2.998e8 ! speed of light (m/s)
+ real(r8), parameter :: mu0 = 4.*pi*1e-7 ! vacuum permeability (H/m)
+ real(r8), parameter :: eps0 = 8.854e-12 ! vacuum permittivity (Klein and Swift 1977) [Farads/meter]
+ real(r8), parameter :: z0 = sqrt(mu0/eps0) ! impendace of free space (Ohm)
+ real(r8), parameter :: eps_w_inf = 4.9 ! dielectric constant at infinite frequency (Stogryn 1971),
+ real(r8), parameter :: eps_0 = 8.854e-12 ! dielectric constant of free space (Klein and Swift 1977) [Farads/meter]
+ real(r8), parameter :: rho_soil = 2.66 ! soil specific density (g/cm3)
+ real(r8), parameter :: f0w = 9. ! relaxation frequency of liquid water (GHz)
+ real(r8), parameter :: rgh_surf = 2.2 ! soil surface roughness (cm)
+ complex(r8), parameter :: jj = (0., 1.) ! imaginary unit for complex number
+
+
+#ifdef LULC_IGBP
+
+ ! MODIS IGBP Land Use/Land Cover System Legend
+ !---------------------------
+ ! 0 Ocean ! 海洋
+ ! 1 Evergreen Needleleaf Forests ! 常绿针叶林
+ ! 2 Evergreen Broadleaf Forests ! 常绿阔叶林
+ ! 3 Deciduous Needleleaf Forests ! 落叶针叶林
+ ! 4 Deciduous Broadleaf Forests ! 落叶阔叶林
+ ! 5 Mixed Forests ! 混交林
+ ! 6 Closed Shrublands ! 密闭灌丛
+ ! 7 Open Shrublands ! 稀疏灌丛
+ ! 8 Woody Savannas ! 木本稀树草原
+ ! 9 Savannas ! 稀树草原
+ !10 Grasslands ! 草地
+ !11 Permanent Wetlands ! 永久性湿地
+ !12 Croplands ! 农田
+ !13 Urban and Built-up Lands ! 城市与建成区
+ !14 Cropland/Natural Vegetation Mosaics ! 农田-自然植被镶嵌区
+ !15 Permanent Snow and Ice ! 永久冰雪
+ !16 Barren ! 裸地
+ !17 Water Bodies ! 水体
+
+ ! empirical parameters to account for the dependence of optical depth on incidence angle [1]
+ real(r8), parameter, dimension(N_land_classification) :: tth &
+ = (/0.80, 1.00, 0.80, 0.49, 0.49, &
+ 1.00, 1.00, 1.00, 1.00, 1.00, &
+ 1.00, 1.00, 1.00, 1.00, 1.00, &
+ 1.00, 2.00/)
+ real(r8), parameter, dimension(N_land_classification) :: ttv &
+ = (/0.80, 1.00, 0.80, 0.46, 0.46, &
+ 1.00, 1.00, 1.00, 1.00, 1.00, &
+ 1.00, 2.00, 1.00, 2.00, 1.00, &
+ 1.00, 1.00/)
+
+ ! empirical roughness parameters (Table 2 in [2])
+ real(r8), parameter, dimension(N_land_classification) :: hr_SMAP &
+ = (/0.160, 0.160, 0.160, 0.160, 0.160, &
+ 0.110, 0.110, 0.125, 0.156, 0.156, &
+ 0.100, 0.108, 0.000, 0.130, 0.000, &
+ 0.150, 0.000/)
+
+ real(r8), parameter, dimension(N_land_classification) :: hr_SMOS &
+ = (/0.300, 0.300, 0.300, 0.300, 0.300, &
+ 0.100, 0.100, 0.100, 0.100, 0.100, &
+ 0.100, 0.100, 0.100, 0.100, 0.000, &
+ 0.100, 0.000/)
+
+ real(r8), parameter, dimension(N_land_classification) :: hr_P16 &
+ = (/0.350, 0.460, 0.430, 0.450, 0.410, &
+ 0.260, 0.170, 0.350, 0.230, 0.130, &
+ 0.020, 0.170, 0.190, 0.220, 0.000, &
+ 0.020, 0.000/)
+
+ ! b parameters for Wigneron vegetation model (ref?)
+ real(r8), parameter, dimension(N_land_classification) :: b1 &
+ = (/0.2600, 0.2260, 0.2600, 0.2260, 0.2260, &
+ 0.0375, 0.0375, 0.0375, 0.0375, 0.0375, &
+ 0.0000, 0.0500, 0.0000, 0.0500, 0.0000, &
+ 0.0000, 0.0500/)
+
+ real(r8), parameter, dimension(N_land_classification) :: b2 &
+ = (/0.0060, 0.0010, 0.0060, 0.0010, 0.0010, &
+ 0.0500, 0.0500, 0.0500, 0.0500, 0.0500, &
+ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000/)
+
+ real(r8), parameter, dimension(N_land_classification) :: b3 &
+ = (/0.6900, 0.7000, 0.6900, 0.7000, 0.7000, &
+ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, &
+ 0.0000, 0.0000/)
+
+ ! effective diffusion albedo (Table 3 in [2])
+ real(r8), parameter, dimension(N_land_classification) :: w_SMAPL2 &
+ = (/0.050, 0.050, 0.050, 0.050, 0.050, &
+ 0.050, 0.050, 0.050, 0.080, 0.050, &
+ 0.050, 0.000, 0.065, 0.000, 0.000, &
+ 0.000, 0.000/)
+
+ real(r8), parameter, dimension(N_land_classification) :: w_CMEM &
+ = (/0.080, 0.095, 0.080, 0.070, 0.070, &
+ 0.050, 0.050, 0.050, 0.050, 0.050, &
+ 0.000, 0.000, 0.000, 0.000, 0.000, &
+ 0.000, 0.000/)
+
+ real(r8), parameter, dimension(N_land_classification) :: w_K16 &
+ = (/0.050, 0.050, 0.060, 0.030, 0.050, &
+ 0.030, 0.050, 0.040, 0.020, 0.030, &
+ 0.000, 0.040, 0.000, 0.020, 0.000, &
+ 0.000, 0.000/)
+
+ real(r8), parameter, dimension(N_land_classification) :: w_SMAPL4 &
+ = (/0.120, 0.080, 0.120, 0.100, 0.120, &
+ 0.140, 0.110, 0.130, 0.120, 0.070, &
+ 0.000, 0.120, 0.000, 0.150, 0.000, &
+ 0.000, 0.000/)
+#endif
+
+END MODULE MOD_DA_Const
+!-----------------------------------------------------------------------------
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_EnKF.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_EnKF.F90
new file mode 100644
index 0000000000..1ec32f06e1
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_EnKF.F90
@@ -0,0 +1,137 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_EnKF
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! ensemble Kalman filter (EnKF) types
+!
+! AUTHOR:
+! Lu Li, 12/2024: Initial version
+! Zhilong Fan, Lu Li, 03/2024: Debug and clean codes
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+ SAVE
+
+! public functions
+ PUBLIC :: letkf
+
+
+!-----------------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE letkf (&
+ num_ens, num_obs, &
+ HA, y, R, infl, &
+ trans)
+
+!-----------------------------------------------------------------------------
+! Description:
+! local transform ensemble Kalman filter
+!
+! Original author :
+! Lu Li, 12/2024
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!------------------------ Dummy Arguments ------------------------------------
+ integer, intent(in) :: num_ens ! ensemble size
+ integer, intent(in) :: num_obs ! number of observations
+ real(r8), intent(in) :: HA(num_obs, num_ens) ! ensemble predicted observation matrix
+ real(r8), intent(in) :: y(num_obs) ! observation vector
+ real(r8), intent(in) :: R(num_obs) ! observation error variance
+ real(r8), intent(in) :: infl ! inflation factor
+ real(r8), intent(out) :: trans(num_ens, num_ens) ! transform matrix (k x k)
+
+!------------------------ Local Variables ------------------------------------
+ real(r8) :: HA_mean(num_obs) ! mean of ensemble predicted observation (l)
+ real(r8) :: dHA(num_obs, num_ens) ! HA - mean(HA) (l x k)
+ real(r8) :: dHA_t(num_ens, num_obs) ! transpose of dHA (k x l)
+ real(r8) :: C(num_ens, num_obs) ! C = (dHA)^T * (R)^-1 (k x l)
+ real(r8) :: M1(num_ens, num_ens) ! C * dHA (k x k)
+ real(r8) :: pa_inv(num_ens, num_ens) ! inverse of background error covariance matrix (k x k)
+ real(r8) :: eigval(num_ens) ! eigenvalues of pa_inv (k)
+ real(r8) :: eigvec(num_ens, num_ens) ! eigenvectors of pa_inv (k x k)
+ integer :: lwork
+ real(r8), allocatable :: work(:)
+ integer :: err
+ real(r8) :: M2(num_ens, num_ens) ! M2 = eigvec * eigval^-1 (k x k)
+ real(r8) :: pa(num_ens, num_ens) ! background error covariance matrix (k x k)
+ real(r8) :: M3(num_ens, num_obs) ! M3 = pa * C (k x l)
+ real(r8) :: delta(num_obs) ! increment of observation (l)
+ real(r8) :: w_avg(num_ens) ! weight (k)
+ real(r8) :: M4(num_ens, num_ens) ! M4 = eigvec * sqrt((k-1)/eigval) (k x k)
+ real(r8) :: trans_pert(num_ens, num_ens) ! perturbation transform matrix (k x k)
+ real(r8) :: I0(num_ens, num_ens) ! identity matrix (k x k)
+ real(r8) :: one_div_ens(num_ens) ! 1/num_ens
+ integer :: i, j
+
+!-----------------------------------------------------------------------------
+
+ ! calculate observation space perturbation
+ HA_mean = sum(HA, dim=2) / size(HA, dim=2) !(lx1)
+ DO j = 1, num_ens
+ dHA(:,j) = HA(:,j) - HA_mean !(lxk)
+ ENDDO
+
+ ! calculate C, intermediate matrix in localized observation
+ dHA_t = transpose(dHA) !(kxl)
+ DO j = 1, num_obs
+ C(:,j) = dHA_t(:,j) / (R(j)) !(kxl)
+ ENDDO
+
+ ! calculate C*dHA, intermediate matrix in background error M1
+ CALL dgemm('N', 'N', num_ens, num_ens, num_obs, 1.0_8, C, num_ens, dHA, num_obs, 0.0_8, M1, num_ens)
+
+ ! calculate inverse of background error
+ pa_inv = M1
+ do i=1, num_ens
+ pa_inv(i,i) = M1(i,i) + (num_ens-1)*1.0d0/infl
+ end do
+
+ ! eigenvalues and eigenvectors of inverse of background error
+ lwork = 4 * num_ens
+ allocate( work(lwork) )
+ CALL dsyev('V', 'U', num_ens, pa_inv, num_ens, eigval, work, lwork, err)
+ eigvec = pa_inv !(kxk)
+
+ ! calculate background error covariance matrix pa = eigvec (eigval)^-1 eigvec^T
+ DO i = 1, num_ens
+ M2(:,i) = eigvec(:,i) / eigval(i) !(kxk)
+ ENDDO
+ CALL dgemm('N', 'T', num_ens, num_ens, num_ens, 1.0_8, M2, num_ens, eigvec, num_ens, 0.0_8, pa, num_ens) !(kxk)
+
+ ! caculate pa * C, intermediate matrix in Kalman gain M3
+ CALL dgemm('N', 'N', num_ens, num_obs, num_ens, 1.0_8, pa, num_ens, C, num_ens, 0.0_8, M3, num_ens) !(kxl)
+
+ ! calculate weight
+ delta = y - HA_mean
+ CALL dgemm('N', 'N', num_ens, 1, num_obs, 1.0_8, M3, num_ens, delta, num_obs, 0.0_8, w_avg, num_ens) !(kx1)
+
+ ! calculate pertubation transform matrix
+ DO j = 1, num_ens
+ M4(:,j) = eigvec(:,j) * sqrt((num_ens-1) / eigval(j)) !(kxk)
+ ENDDO
+ CALL dgemm('N', 'T', num_ens, num_ens, num_ens, 1.0_8, M4, num_ens, eigvec, num_ens, 0.0_8, trans_pert, num_ens) !(kxk)
+
+ ! calculate transform matrix
+ one_div_ens(:) = 1./num_ens
+ I0 = -1.0 / num_ens
+ DO i = 1, num_ens
+ I0(i, i) = 1.0 - 1./num_ens
+ ENDDO
+ DO j = 1, num_ens
+ trans(:, j) = matmul(trans_pert(:, j) + w_avg(:), I0) + one_div_ens(:)
+ ENDDO
+
+ END SUBROUTINE letkf
+
+!-----------------------------------------------------------------------------
+END MODULE MOD_DA_EnKF
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Ensemble.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Ensemble.F90
new file mode 100644
index 0000000000..8eea429ae2
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Ensemble.F90
@@ -0,0 +1,267 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_Ensemble
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Provide functions to generate ensemble samples for data assimilation
+!
+! REFERENCES:
+! [1] Algorithm Theoretical Basis Document Level 4 Surface and Root
+! Zone Soil Moisture (L4_SM) Data Product
+!
+! AUTHOR:
+! Lu Li, 12/2024: Initial version
+! Lu Li, 10/2025: Consider correlation & AR(1) process
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_Vars_TimeVariables
+ USE MOD_DA_Vars_TimeVariables
+ USE MOD_Vars_1DForcing
+ USE MOD_LandPatch
+ IMPLICIT NONE
+ SAVE
+
+ ! public functions
+ PUBLIC :: ensemble
+
+ ! local parameters
+ ! forcing [parameters used here is consistent with SMAP L4 (Table 4 in [1])]
+ integer, parameter :: nvar = 4 ! number of pertutated forcing variables
+ real(r8), parameter :: tau_ar = 24.0 ! correlation time scale in hours
+
+ real(r8) :: dt ! time step in hours
+ real(r8) :: phi ! AR(1) autocorrelation coefficient consider time scale
+ real(r8) :: sigma_eps ! standard deviation of noise in AR(1) process
+ real(r8), dimension(nvar) :: sigma = (/0.5, 0.3, 20.0, 1.0/) ! standard deviation of perturbed forcing variables (prcp, sw, lw, t)
+ real(r8), dimension(nvar, nvar) :: C = reshape([ &
+ 1.0, -0.8, 0.5, 0.0, &
+ -0.8, 1.0, -0.5, 0.4, &
+ 0.5, -0.5, 1.0, 0.4, &
+ 0.0, 0.4, 0.4, 1.0], shape=[nvar, nvar]) ! cross-correlation matrix between perturbed forcing variables
+ real(r8), allocatable :: r_prev(:,:,:) ! previous perturbation (numpatch, nvar, DEF_DA_ENS_NUM)
+ real(r8), allocatable :: r_curr(:,:,:) ! current perturbation (numpatch, nvar, DEF_DA_ENS_NUM)
+ logical :: initialized = .false. ! flag to indicate if is initialized
+
+ ! soil moisture [default set 0.002 m3/m3 disterbulance]
+ integer, parameter :: nvar_sm = 2 ! number of pertutated soil moisture layers
+ real(r8), parameter :: tau_sm = 3.0 ! correlation time scale in hours
+ real(r8) :: phi_sm ! AR(1) autocorrelation coefficient consider time scale
+ real(r8) :: sigma_eps_sm ! standard deviation of noise in AR(1) process
+ real(r8), dimension(nvar_sm) :: sigma_sm = (/0.035, 0.0552/) ! standard deviation of perturbed soil moisture (equal to 0.002 m3/m3)
+ real(r8), allocatable :: r_prev_sm(:,:,:) ! previous perturbation (numpatch, nvar_sm, DEF_DA_ENS_NUM)
+ real(r8), allocatable :: r_curr_sm(:,:,:) ! current perturbation (numpatch, nvar_sm, DEF_DA_ENS_NUM)
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE ensemble(deltim)
+
+!-----------------------------------------------------------------------
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim
+
+!------------------------ Local Variables ------------------------------
+ integer :: np, i, j
+
+ real(r8) :: cov_matrix(nvar, nvar) ! covariance matrix between perturbed forcing variables
+ real(r8) :: L(nvar, nvar) ! Cholesky decomposition of correlation matrix
+ integer :: info ! info flag for Cholesky decomposition
+ real(r8) :: u1(DEF_DA_ENS_NUM/2), u2(DEF_DA_ENS_NUM/2) ! uniform random variables
+ real(r8) :: z(nvar, DEF_DA_ENS_NUM) ! standard normal random variables
+ real(r8) :: mean_z(nvar) ! mean of perturbation (nvar)
+ real(r8) :: std_z(nvar) ! std of perturbation (nvar)
+ real(r8) :: zxL(nvar, DEF_DA_ENS_NUM) ! correlated random variables (nvar, DEF_DA_ENS_NUM)
+
+ real(r8) :: z_sm(DEF_DA_ENS_NUM) ! standard normal random variables
+ real(r8) :: mean_z_sm ! mean of perturbation
+ real(r8) :: std_z_sm ! std of perturbation
+ real(r8) :: mean_r_sm(nvar_sm) ! mean of perturbation for soil moisture (nvar_sm)
+ real(r8) :: std_r_sm(nvar_sm) ! std of perturbation for soil moisture (nvar_sm)
+ real(r8) :: a1(DEF_DA_ENS_NUM) ! temporary disturbed variable for soil moisture layer 1
+ real(r8) :: a2(DEF_DA_ENS_NUM) ! temporary disturbed variable for soil moisture layer 2
+
+!-----------------------------------------------------------------------
+
+ ! initialize persistent variables
+ IF (.not. initialized) THEN
+ allocate(r_prev(numpatch, nvar, DEF_DA_ENS_NUM))
+ allocate(r_curr(numpatch, nvar, DEF_DA_ENS_NUM))
+ allocate(r_prev_sm(numpatch, nvar_sm, DEF_DA_ENS_NUM))
+ allocate(r_curr_sm(numpatch, nvar_sm, DEF_DA_ENS_NUM))
+ r_prev = 0.0_r8
+ r_curr = 0.0_r8
+ r_prev_sm = 0.0_r8
+ r_curr_sm = 0.0_r8
+ initialized = .true.
+ ENDIF
+
+ ! calculate AR(1) parameters
+ dt = deltim/3600
+ phi = exp(-dt/tau_ar)
+ sigma_eps = sqrt(1.0 - phi**2)
+ phi_sm = exp(-dt/tau_sm)
+ sigma_eps_sm = sqrt(1.0 - phi_sm**2)
+
+ ! calculate covariance matrix by cross-correlation matrix and standard deviation
+ cov_matrix = 0.0_r8
+ DO i = 1, nvar
+ DO j = 1, nvar
+ cov_matrix(i,j) = C(i,j) * sigma(i) * sigma(j)
+ ENDDO
+ ENDDO
+
+ ! perform Cholesky decomposition of covariance matrix
+ L = cov_matrix
+ CALL dpotrf('L', nvar, L, nvar, info)
+ DO i = 1, nvar
+ DO j = i+1, nvar
+ L(i,j) = 0.0_r8
+ ENDDO
+ ENDDO
+ IF (info /= 0) THEN
+ print *, 'Error: Cholesky decomposition failed'
+ stop
+ ENDIF
+
+ ! Generate ensemble samples for forcing variables
+ DO np = 1, numpatch
+ ! generate disturbance ensemble samples ~ N(0, I)
+ CALL random_seed()
+ CALL random_number(u1)
+ CALL random_number(u2)
+ DO i = 1, DEF_DA_ENS_NUM/2
+ u1(i) = max(u1(i), 1e-10) ! ensure u1 is not zero
+ z(1,i*2-1) = sqrt(-2.0*log(u1(i))) * cos(2.0*pi*u2(i))
+ z(1,i*2) = sqrt(-2.0*log(u1(i))) * sin(2.0*pi*u2(i))
+ ENDDO
+ CALL random_seed()
+ CALL random_number(u1)
+ CALL random_number(u2)
+ DO i = 1, DEF_DA_ENS_NUM/2
+ u1(i) = max(u1(i), 1e-10)
+ z(2,i*2-1) = sqrt(-2.0*log(u1(i))) * cos(2.0*pi*u2(i))
+ z(2,i*2) = sqrt(-2.0*log(u1(i))) * sin(2.0*pi*u2(i))
+ ENDDO
+ CALL random_seed()
+ CALL random_number(u1)
+ CALL random_number(u2)
+ DO i = 1, DEF_DA_ENS_NUM/2
+ u1(i) = max(u1(i), 1e-10)
+ z(3,i*2-1) = sqrt(-2.0*log(u1(i))) * cos(2.0*pi*u2(i))
+ z(3,i*2) = sqrt(-2.0*log(u1(i))) * sin(2.0*pi*u2(i))
+ ENDDO
+ CALL random_seed()
+ CALL random_number(u1)
+ CALL random_number(u2)
+ DO i = 1, DEF_DA_ENS_NUM/2
+ u1(i) = max(u1(i), 1e-10)
+ z(4,i*2-1) = sqrt(-2.0*log(u1(i))) * cos(2.0*pi*u2(i))
+ z(4,i*2) = sqrt(-2.0*log(u1(i))) * sin(2.0*pi*u2(i))
+ ENDDO
+
+ ! normalize z to mean 0 and std 1
+ DO i = 1, nvar
+ mean_z(i) = sum(z(i, :))/DEF_DA_ENS_NUM
+ std_z(i) = sqrt(sum((z(i, :) - mean_z(i))**2)/(DEF_DA_ENS_NUM - 1))
+ ENDDO
+ DO i = 1, nvar
+ z(i,:) = (z(i,:)-mean_z(i))/std_z(i)
+ ENDDO
+
+ ! multiply by Cholesky factor to introduce correlation (z*L)
+ CALL dgemm('N', 'N', nvar, DEF_DA_ENS_NUM, nvar, 1.0_r8, L, nvar, z, nvar, 0.0_r8, zxL, nvar)
+
+ ! introduce correlation using AR(1) process
+ DO i = 1, nvar
+ DO j = 1, DEF_DA_ENS_NUM
+ r_curr(np,i,j) = phi * r_prev(np,i,j) + sigma_eps * zxL(i,j)
+ ENDDO
+ ENDDO
+ ! no AR(1) process, directly use correlated random variables
+ ! r_curr(np,:,:) = zxL
+
+ ! normalize the disturbance ensemble samples to mean 0
+ mean_z = sum(r_curr(np,:,:), dim=2)/DEF_DA_ENS_NUM
+ DO i = 1, nvar
+ DO j = 1, DEF_DA_ENS_NUM
+ r_curr(np,i,j) = r_curr(np,i,j) - mean_z(i)
+ ENDDO
+ ENDDO
+
+ ! save current perturbation as previous perturbation for next time step
+ r_prev = r_curr
+
+ ! generate ensemble samples according different types
+ DO j = 1, DEF_DA_ENS_NUM
+ forc_prc_ens(j,np) = forc_prc(np) * exp(r_curr(np,1,j) - 0.5 * sigma(1)**2)
+ forc_prl_ens(j,np) = forc_prl(np) * exp(r_curr(np,1,j) - 0.5 * sigma(1)**2)
+ forc_sols_ens(j,np) = forc_sols(np) * exp(r_curr(np,2,j) - 0.5 * sigma(2)**2)
+ forc_soll_ens(j,np) = forc_soll(np) * exp(r_curr(np,2,j) - 0.5 * sigma(2)**2)
+ forc_solsd_ens(j,np) = forc_solsd(np) * exp(r_curr(np,2,j) - 0.5 * sigma(2)**2)
+ forc_solld_ens(j,np) = forc_solld(np) * exp(r_curr(np,2,j) - 0.5 * sigma(2)**2)
+ forc_frl_ens(j,np) = forc_frl(np) + r_curr(np,3,j)
+ forc_t_ens(j,np) = forc_t(np) + r_curr(np,4,j)
+ ENDDO
+
+ IF (DEF_DA_ENS_SM) THEN
+ ! generate ensemble samples (0, I) for soil moisture
+ CALL random_seed()
+ CALL random_number(u1)
+ CALL random_number(u2)
+ DO i = 1, DEF_DA_ENS_NUM/2
+ u1(i) = max(u1(i), 1e-10)
+ z_sm(i*2-1) = sqrt(-2.0*log(u1(i))) * cos(2.0*pi*u2(i))
+ z_sm(i*2) = sqrt(-2.0*log(u1(i))) * sin(2.0*pi*u2(i))
+ ENDDO
+ mean_z_sm = sum(z_sm)/DEF_DA_ENS_NUM
+ std_z_sm = sqrt(sum((z_sm - mean_z_sm)**2)/(DEF_DA_ENS_NUM - 1))
+ z_sm = (z_sm - mean_z_sm)/std_z_sm
+
+ ! introduce correlation using AR(1) process
+ DO i = 1, nvar_sm
+ DO j = 1, DEF_DA_ENS_NUM
+ r_curr_sm(np,i,j) = phi_sm * r_prev_sm(np,i,j) + sigma_eps_sm * sigma_sm(i) * z_sm(j)
+ ENDDO
+ ENDDO
+
+ ! normalize the disturbance ensemble samples to mean 0
+ mean_r_sm = sum(r_curr_sm(np,:,:), dim=2)/DEF_DA_ENS_NUM
+ DO i = 1, nvar_sm
+ DO j = 1, DEF_DA_ENS_NUM
+ r_curr_sm(np,i,j) = r_curr_sm(np,i,j) - mean_r_sm(i)
+ ENDDO
+ ENDDO
+
+ ! save current perturbation as previous perturbation for next time step
+ r_prev_sm = r_curr_sm
+
+ ! generate ensemble samples according different types
+ DO j = 1, DEF_DA_ENS_NUM
+ a1(j) = wliq_soisno_ens(1,j,np) + r_curr_sm(np,1,j)
+ a2(j) = wliq_soisno_ens(2,j,np) + r_curr_sm(np,2,j)
+ ENDDO
+ DO j = 1, DEF_DA_ENS_NUM
+ a1(j) = max(1e-10, a1(j))
+ a2(j) = max(1e-10, a2(j))
+ ENDDO
+
+ ! move residual water to water table
+ DO j = 1, DEF_DA_ENS_NUM
+ wa_ens(j, np) = wa_ens(j, np) - (sum(wliq_soisno_ens(1:2, j, np)) - a1(j) - a2(j))
+ wliq_soisno_ens(1, j, np) = a1(j)
+ wliq_soisno_ens(2, j, np) = a2(j)
+ ENDDO
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE ensemble
+
+!-----------------------------------------------------------------------
+END MODULE MOD_DA_Ensemble
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Main.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Main.F90
new file mode 100644
index 0000000000..70ab7e8981
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Main.F90
@@ -0,0 +1,396 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_Main
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! Main procedures for data assimilation
+!
+! AUTHOR:
+! Lu Li, 12/2024
+! Zhilong Fan, Lu Li, 03/2024
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Spmd_task
+ USE MOD_Namelist
+ USE MOD_TimeManager
+ USE MOD_LandPatch
+ USE MOD_DA_TWS
+ USE MOD_DA_SM
+ USE MOD_DA_Ensemble
+ USE MOD_Vars_1DFluxes
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_1DForcing
+ IMPLICIT NONE
+ SAVE
+
+!-----------------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE init_DA ()
+
+!-----------------------------------------------------------------------------
+ IMPLICIT NONE
+
+!-----------------------------------------------------------------------------
+
+!#############################################################################
+! Init data assimilation for different products
+!#############################################################################
+ IF (DEF_DA_TWS) THEN
+ IF (DEF_DA_TWS_GRACE) THEN
+ CALL init_DA_GRACE ()
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM) THEN
+ IF (p_is_root) THEN
+ print *, '[CoLM-DA] initialize surface soil moisture & temperature data assimilation.'
+ ENDIF
+ CALL init_DA_SM ()
+ ENDIF
+
+ END SUBROUTINE init_DA
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE run_DA (idate, deltim, dolai, doalb, dosst, oro)
+
+!-----------------------------------------------------------------------------
+ IMPLICIT NONE
+
+!------------------------ Dummy Arguments ------------------------------------
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ logical, intent(in) :: dolai ! true if time for time-varying vegetation parameter
+ logical, intent(in) :: doalb ! true if time for surface albedo calculation
+ logical, intent(in) :: dosst ! true if time for update sst/ice/snow
+
+ real(r8), intent(inout) :: oro(numpatch) ! ocean(0)/seaice(2)/ flag
+
+!------------------------ Local Variables ------------------------------------
+ integer :: np, i, maxday
+ integer :: sdate(3) ! backward date from the end to the begin of the time step
+
+!-----------------------------------------------------------------------------
+
+ ! use OI for terrestrial water storage
+ IF (DEF_DA_TWS) THEN
+ IF (DEF_DA_TWS_GRACE) THEN
+ CALL run_DA_GRACE (idate, deltim)
+ ENDIF
+ ENDIF
+
+ ! use ensemble DA for soil moisture
+ IF ((DEF_DA_SM) .and. (DEF_DA_ENS_NUM > 1))THEN
+!#############################################################################
+! Generate ensemble members
+!#############################################################################
+ IF (p_is_compute) THEN
+
+ ! store the non-DA trajectory
+ z_sno_noda = z_sno
+ dz_sno_noda = dz_sno
+ t_soisno_noda = t_soisno
+ wliq_soisno_noda = wliq_soisno
+ wice_soisno_noda = wice_soisno
+ smp_noda = smp
+ hk_noda = hk
+ t_grnd_noda = t_grnd
+ tleaf_noda = tleaf
+ ldew_noda = ldew
+ ldew_rain_noda = ldew_rain
+ ldew_snow_noda = ldew_snow
+ fwet_snow_noda = fwet_snow
+ sag_noda = sag
+ scv_noda = scv
+ snowdp_noda = snowdp
+ fveg_noda = fveg
+ fsno_noda = fsno
+ sigf_noda = sigf
+ green_noda = green
+ tlai_noda = tlai
+ lai_noda = lai
+ tsai_noda = tsai
+ sai_noda = sai
+ alb_noda = alb
+ ssun_noda = ssun
+ ssha_noda = ssha
+ ssoi_noda = ssoi
+ ssno_noda = ssno
+ thermk_noda = thermk
+ extkb_noda = extkb
+ extkd_noda = extkd
+ zwt_noda = zwt
+ wdsrf_noda = wdsrf
+ wa_noda = wa
+ wetwat_noda = wetwat
+ t_lake_noda = t_lake
+ lake_icefrac_noda = lake_icefrac
+ savedtke1_noda = savedtke1
+
+ tref_noda = tref
+ h2osoi_noda = h2osoi
+
+ ! Generate ensemble members
+ CALL ensemble (deltim)
+
+ ! loop over ensemble members
+ DO i = 1, DEF_DA_ENS_NUM
+ ! set ensemble forcing variables
+ forc_t = forc_t_ens(i,:)
+ forc_prc = forc_prc_ens(i,:)
+ forc_prl = forc_prl_ens(i,:)
+ forc_sols = forc_sols_ens(i,:)
+ forc_soll = forc_soll_ens(i,:)
+ forc_solsd = forc_solsd_ens(i,:)
+ forc_solld = forc_solld_ens(i,:)
+ forc_frl = forc_frl_ens(i,:)
+
+ ! give the i-th trajectory state value to state variables
+ z_sno = z_sno_ens ( :,i,:)
+ dz_sno = dz_sno_ens ( :,i,:)
+ t_soisno = t_soisno_ens ( :,i,:)
+ wliq_soisno = wliq_soisno_ens ( :,i,:)
+ wice_soisno = wice_soisno_ens ( :,i,:)
+ smp = smp_ens ( :,i,:)
+ hk = hk_ens ( :,i,:)
+ t_grnd = t_grnd_ens ( i,:)
+ tleaf = tleaf_ens ( i,:)
+ ldew = ldew_ens ( i,:)
+ ldew_rain = ldew_rain_ens ( i,:)
+ ldew_snow = ldew_snow_ens ( i,:)
+ fwet_snow = fwet_snow_ens ( i,:)
+ sag = sag_ens ( i,:)
+ scv = scv_ens ( i,:)
+ snowdp = snowdp_ens ( i,:)
+ fveg = fveg_ens ( i,:)
+ fsno = fsno_ens ( i,:)
+ sigf = sigf_ens ( i,:)
+ green = green_ens ( i,:)
+ tlai = tlai_ens ( i,:)
+ lai = lai_ens ( i,:)
+ tsai = tsai_ens ( i,:)
+ sai = sai_ens ( i,:)
+ alb = alb_ens (:,:,i,:)
+ ssun = ssun_ens (:,:,i,:)
+ ssha = ssha_ens (:,:,i,:)
+ ssoi = ssoi_ens (:,:,i,:)
+ ssno = ssno_ens (:,:,i,:)
+ thermk = thermk_ens ( i,:)
+ extkb = extkb_ens ( i,:)
+ extkd = extkd_ens ( i,:)
+ zwt = zwt_ens ( i,:)
+ wdsrf = wdsrf_ens ( i,:)
+ wa = wa_ens ( i,:)
+ wetwat = wetwat_ens ( i,:)
+ t_lake = t_lake_ens ( :,i,:)
+ lake_icefrac = lake_icefrac_ens( :,i,:)
+ savedtke1 = savedtke1_ens ( i,:)
+
+ ! run colm
+ CALL CoLMDRIVER (idate, deltim, dolai, doalb, dosst, oro)
+
+ ! output ensemble members
+ z_sno_ens ( :,i,:) = z_sno
+ dz_sno_ens ( :,i,:) = dz_sno
+ t_soisno_ens ( :,i,:) = t_soisno
+ wliq_soisno_ens ( :,i,:) = wliq_soisno
+ wice_soisno_ens ( :,i,:) = wice_soisno
+ smp_ens ( :,i,:) = smp
+ hk_ens ( :,i,:) = hk
+ t_grnd_ens ( i,:) = t_grnd
+ tleaf_ens ( i,:) = tleaf
+ ldew_ens ( i,:) = ldew
+ ldew_rain_ens ( i,:) = ldew_rain
+ ldew_snow_ens ( i,:) = ldew_snow
+ fwet_snow_ens ( i,:) = fwet_snow
+ sag_ens ( i,:) = sag
+ scv_ens ( i,:) = scv
+ snowdp_ens ( i,:) = snowdp
+ fveg_ens ( i,:) = fveg
+ fsno_ens ( i,:) = fsno
+ sigf_ens ( i,:) = sigf
+ green_ens ( i,:) = green
+ tlai_ens ( i,:) = tlai
+ lai_ens ( i,:) = lai
+ tsai_ens ( i,:) = tsai
+ sai_ens ( i,:) = sai
+ alb_ens (:,:,i,:) = alb
+ ssun_ens (:,:,i,:) = ssun
+ ssha_ens (:,:,i,:) = ssha
+ ssoi_ens (:,:,i,:) = ssoi
+ ssno_ens (:,:,i,:) = ssno
+ thermk_ens ( i,:) = thermk
+ extkb_ens ( i,:) = extkb
+ extkd_ens ( i,:) = extkd
+ zwt_ens ( i,:) = zwt
+ wdsrf_ens ( i,:) = wdsrf
+ wa_ens ( i,:) = wa
+ wetwat_ens ( i,:) = wetwat
+ t_lake_ens ( :,i,:) = t_lake
+ lake_icefrac_ens( :,i,:) = lake_icefrac
+ savedtke1_ens ( i,:) = savedtke1
+
+ h2osoi_ens(:,i,:) = h2osoi
+ trad_ens (i,:) = trad
+ tref_ens (i,:) = tref
+ qref_ens (i,:) = qref
+ ustar_ens (i,:) = ustar
+ qstar_ens (i,:) = qstar
+ tstar_ens (i,:) = tstar
+ fm_ens (i,:) = fm
+ fh_ens (i,:) = fh
+ fq_ens (i,:) = fq
+
+ fsena_ens (i,:) = fsena
+ lfevpa_ens(i,:) = lfevpa
+ fevpa_ens (i,:) = fevpa
+ rsur_ens (i,:) = rsur
+ ENDDO
+
+ ! recover the no-DA trajectory
+ z_sno = z_sno_noda
+ dz_sno = dz_sno_noda
+ t_soisno = t_soisno_noda
+ wliq_soisno = wliq_soisno_noda
+ wice_soisno = wice_soisno_noda
+ smp = smp_noda
+ hk = hk_noda
+ t_grnd = t_grnd_noda
+ tleaf = tleaf_noda
+ ldew = ldew_noda
+ ldew_rain = ldew_rain_noda
+ ldew_snow = ldew_snow_noda
+ fwet_snow = fwet_snow_noda
+ sag = sag_noda
+ scv = scv_noda
+ snowdp = snowdp_noda
+ fveg = fveg_noda
+ fsno = fsno_noda
+ sigf = sigf_noda
+ green = green_noda
+ tlai = tlai_noda
+ lai = lai_noda
+ tsai = tsai_noda
+ sai = sai_noda
+ alb = alb_noda
+ ssun = ssun_noda
+ ssha = ssha_noda
+ ssoi = ssoi_noda
+ ssno = ssno_noda
+ thermk = thermk_noda
+ extkb = extkb_noda
+ extkd = extkd_noda
+ zwt = zwt_noda
+ wdsrf = wdsrf_noda
+ wa = wa_noda
+ wetwat = wetwat_noda
+ t_lake = t_lake_noda
+ lake_icefrac = lake_icefrac_noda
+ savedtke1 = savedtke1_noda
+
+ tref = tref_noda
+ h2osoi = h2osoi_noda
+
+ ENDIF
+ ENDIF
+
+!#############################################################################
+! Perform data assimilation for different satellite products
+!#############################################################################
+ IF (DEF_DA_SM) THEN
+ ! backward date from the end to the begin of the time step
+ sdate = idate
+ sdate(3) = sdate(3) - nint(deltim)
+ IF (sdate(3) < 0) THEN
+ sdate(2) = sdate(2) - 1
+ sdate(3) = sdate(3) + 86400
+
+ IF (sdate(2) < 1) THEN
+ sdate(1) = sdate(1) - 1
+ IF (isleapyear(sdate(1))) THEN
+ maxday = 366
+ ELSE
+ maxday = 365
+ ENDIF
+ sdate(2) = maxday
+ ENDIF
+ ENDIF
+
+ ! data assimilation
+ IF (DEF_DA_SM) THEN
+ IF (p_is_root) THEN
+ print *, '[CoLM-DA] Start surface soil moisture & temperature data assimilation.'
+ ENDIF
+ CALL mpi_barrier (p_comm_glb, p_err)
+ CALL run_DA_SM (sdate, deltim)
+ ENDIF
+ ENDIF
+
+!#############################################################################
+! Use ensemble mean for important outputs
+!#############################################################################
+ IF ((DEF_DA_SM) .and. (DEF_DA_ENS_NUM > 1))THEN
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO np = 1, numpatch
+ ! important state variables
+ t_soisno_a(:,np) = sum(t_soisno_ens(:,:,np), dim=2) / DEF_DA_ENS_NUM
+ wliq_soisno_a(:,np) = sum(wliq_soisno_ens(:,:,np), dim=2) / DEF_DA_ENS_NUM
+ wice_soisno_a(:,np) = sum(wice_soisno_ens(:,:,np), dim=2) / DEF_DA_ENS_NUM
+ t_grnd_a(np) = sum(t_grnd_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ tleaf_a(np) = sum(tleaf_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ snowdp_a(np) = sum(snowdp_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+
+ ! diagnostic variables
+ h2osoi_a(:,np) = sum(h2osoi_ens(:,:,np), dim=2) / DEF_DA_ENS_NUM
+ t_brt_smap_a(:,np) = sum(t_brt_smap_ens(:,:,np), dim=2) / DEF_DA_ENS_NUM
+ t_brt_fy3d_a(:,np) = sum(t_brt_fy3d_ens(:,:,np), dim=2) / DEF_DA_ENS_NUM
+ trad_a(np) = sum(trad_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ tref_a(np) = sum(tref_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ qref_a(np) = sum(qref_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ ustar_a(np) = sum(ustar_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ qstar_a(np) = sum(qstar_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ tstar_a(np) = sum(tstar_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ fm_a(np) = sum(fm_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ fh_a(np) = sum(fh_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ fq_a(np) = sum(fq_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ fsena_a(np) = sum(fsena_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ fevpa_a(np) = sum(fevpa_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ lfevpa_a(np) = sum(lfevpa_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ rsur_a(np) = sum(rsur_ens(:,np), dim=1) / DEF_DA_ENS_NUM
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE run_DA
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE end_DA ()
+
+!-----------------------------------------------------------------------------
+ IMPLICIT NONE
+
+!-----------------------------------------------------------------------------
+
+ IF (DEF_DA_TWS) THEN
+ IF (DEF_DA_TWS_GRACE) THEN
+ CALL end_DA_GRACE ()
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM) THEN
+ CALL end_DA_SM ()
+ ENDIF
+
+ END SUBROUTINE end_DA
+
+!-----------------------------------------------------------------------------
+END MODULE MOD_DA_Main
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_RTM.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_RTM.F90
new file mode 100644
index 0000000000..ef234e5cba
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_RTM.F90
@@ -0,0 +1,1431 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_RTM
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Forward modeling of brightness temperature observations
+!
+! AUTHOR:
+! Lu Li, 12/2024: Initial version
+! Zhilong Fan, Lu Li, 03/2024: Debug and clean codes
+! Lu Li, 10/2025: Debug and clean codes
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ USE MOD_Vars_1DForcing
+ USE MOD_DA_Const
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: nl_soil, nl_lake, N_land_classification
+ USE MOD_Namelist
+ IMPLICIT NONE
+ SAVE
+
+! public functions
+ PUBLIC :: forward
+
+! local variables (parameters depends on frequency and incidence angle of satellite)
+ real(r8) :: fghz ! frequency of satellite (GHz)
+ real(r8) :: theta ! incidence angle of satellite (rad)
+ real(r8) :: f ! frequency (Hz)
+ real(r8) :: omega ! radian frequency
+ real(r8) :: lam ! wavelength (m)
+ real(r8) :: k ! wave number (rad/m)
+ real(r8) :: kcm ! wave number (rad/cm)
+ real(r8) :: kr ! size parameter used in calcuate single-particle albedo
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE forward( &
+ patchtype, patchclass, dz_sno, &
+ forc_topo, htop, &
+ tref, t_soisno, tleaf, &
+ wliq_soisno, wice_soisno, h2osoi, &
+ snowdp, lai, sai, &
+ wf_clay, wf_sand, wf_silt, BD_all, porsl, &
+ sat_theta, sat_fghz, &
+ tb_toa_h, tb_toa_v)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Forward modeling of brightness temperature observations
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ USE MOD_Vars_Global, only: nl_soil, nl_lake, maxsnl, spval, dz_soi
+ USE MOD_DA_Const
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ integer, intent(in) :: patchtype ! land cover type
+ integer, intent(in) :: patchclass ! land cover class
+ real(r8), intent(in) :: dz_sno(maxsnl + 1:0) ! layer thickness (m)
+ real(r8), intent(in) :: forc_topo ! topography [m]
+ real(r8), intent(in) :: htop ! upper height of vegetation [m]
+ real(r8), intent(in) :: tref ! 2 m height air temperature [kelvin]
+ real(r8), intent(in) :: tleaf ! leaf temperature [K]
+ real(r8), intent(in) :: t_soisno(maxsnl + 1:nl_soil) ! soil temperature [K]
+ real(r8), intent(in) :: wliq_soisno(maxsnl + 1:nl_soil) ! liquid water in layers [kg/m2]
+ real(r8), intent(in) :: wice_soisno(maxsnl + 1:nl_soil) ! ice lens in layers [kg/m2]
+ real(r8), intent(in) :: h2osoi(nl_soil) ! volumetric soil water in layers [m3/m3]
+ real(r8), intent(in) :: snowdp ! snow depth [meter]
+ real(r8), intent(in) :: lai ! leaf area index
+ real(r8), intent(in) :: sai ! stem area index
+ real(r8), intent(in) :: wf_clay(nl_soil) ! gravimetric fraction of clay
+ real(r8), intent(in) :: wf_sand(nl_soil) ! gravimetric fraction of sand
+ real(r8), intent(in) :: wf_silt(nl_soil) ! gravimetric fraction of silt
+ real(r8), intent(in) :: BD_all(nl_soil) ! bulk density of soil (GRAVELS + ORGANIC MATTER + Mineral Soils,kg/m3)
+ real(r8), intent(in) :: porsl(nl_soil) ! fraction of soil that is voids [-]
+ real(r8), intent(in) :: sat_theta ! incidence angle of satellite (rad)
+ real(r8), intent(in) :: sat_fghz ! frequency of satellite (GHz)
+ real(r8), intent(out) :: tb_toa_h ! brightness temperature of top-of-atmosphere for H- polarization
+ real(r8), intent(out) :: tb_toa_v ! brightness temperature of top-of-atmosphere for V- polarization
+
+!----------------------- Local Variables -------------------------------
+ logical :: is_low_veg ! flag for low vegetation
+ real(r8) :: dz_soisno(maxsnl+1:nl_soil) ! liquid water in layers [kg/m2]
+ integer :: lb ! lower bound of arrays
+ real(r8) :: tau_atm ! atmospheric optical depth
+ real(r8) :: r_r(2) ! rough surface reflectivity for H and V polarizations
+ real(r8) :: r_sn(2) ! reflectivity between the snow and ground for H and V polarizations
+ real(r8) :: r_snow(2) ! reflectivity of the snow for H and V polarizations
+ real(r8) :: tb_soil(2) ! brightness temperature of soil for H and V polarizations
+ real(r8) :: tb_tos(2) ! brightness temperature of snow-covered ground for H and V polarizations
+ real(r8) :: tb_tov(2) ! brightness temperature of vegetation (consider snow) for H and V polarizations
+ real(r8) :: tb_tov_noad(2) ! brightness temperature of vegetation (no downwelling radiation) for H and V polarizations
+ real(r8) :: tb_au(2) ! upwelling radiation (brightness temperature) of atmosphere
+ real(r8) :: tb_ad(2) ! downwelling radiation (brightness temperature) of atmosphere
+ real(r8) :: rho_snow ! snow density (g/cm3)
+ real(r8) :: liq_snow ! snow liquid water content (cm3/cm3)
+ real(r8) :: gamma_p(2) ! vegetation opacity for H- and V- polarization
+ real(r8) :: tb_veg(2) ! brightness temperature of vegetation for H- and V- polarization
+ real(r8) :: tb_2(2) ! the downwelling vegetation emission reflected by the soil and attenuated by the canopy layer
+ real(r8) :: tb_3(2) ! upwelling soil emission attenuated by the canopy
+ real(r8) :: tb_4(2) ! the downwelling cosmic ray reflected by the soil and attenuated by the canopy layer
+ real(r8) :: tb_toa(2) ! brightness temperature of top-of-atmosphere for H- and V- polarization
+ real(r8) :: wf_total(nl_soil) ! total gravimetric
+ real(r8) :: BD_all_surf ! bulk density of soil (g/m3) at surface
+ real(r8) :: porsl_surf ! soil porosity at surface
+ real(r8) :: t_surf ! soil temperature at surface (C)
+ real(r8) :: t_deep ! soil temperature at deep layer (C)
+ real(r8) :: liq_surf ! liquid volumetric water content at surface (m3/m3)
+ real(r8) :: ice_surf ! ice volumetric water content at surface (m3/m3)
+ real(r8) :: wf_clay_surf ! gravimetric clay percent fraction(%) at surface
+ real(r8) :: wf_sand_surf ! gravimetric sand percent fraction(%) at surface
+ integer :: i
+
+!-----------------------------------------------------------------------
+
+!#############################################################################
+! Prepare parameters & states used in the operator
+!#############################################################################
+ ! get depth of soil and snow layers
+ dz_soisno(maxsnl+1:0) = dz_sno(maxsnl+1:0)
+ dz_soisno(1:nl_soil) = dz_soi(1:nl_soil)
+
+ ! calculate weighted parameters
+ wf_total = wf_clay + wf_sand + wf_silt
+ wf_clay_surf = (wf_clay(1)/wf_total(1)*0.0175 + wf_clay(2)/wf_total(2)*0.0276)/0.0451*100
+ wf_sand_surf = (wf_sand(1)/wf_total(1)*0.0175 + wf_sand(2)/wf_total(2)*0.0276)/0.0451*100
+ BD_all_surf = (BD_all(1)*0.0175 + BD_all(2)*0.0276)/0.0451/1000
+ porsl_surf = (porsl(1)*0.0175 + porsl(2)*0.0276)/0.0451
+
+ ! caculate temperature (C) at surface and deep soil layers
+ t_surf = ((t_soisno(1)*(0.0175) + t_soisno(2)*(0.0451 - 0.0175))/0.0451) - tfrz
+ t_deep = ((t_soisno(7)*(0.8289-0.5) + t_soisno(8)*(1.0 - 0.8289))/0.5) - tfrz
+
+ ! caculate liquid/ice volumetric water (first two layers)
+ liq_surf = (wliq_soisno(1) + wliq_soisno(2))/(0.0451*denh2o)
+ ice_surf = (wice_soisno(1) + wice_soisno(2))/(0.0451*denice)
+
+ ! calculate lower bound of snow
+ lb = 0
+ DO i = 0, maxsnl
+ IF (wliq_soisno(i) < 0.0) THEN
+ lb = i+1
+ EXIT
+ ENDIF
+ ENDDO
+
+!#############################################################################
+! Run the forward operator
+!#############################################################################
+ ! check the patch type
+ IF (patchtype >= 3) THEN ! ocean, lake, ice
+ tb_toa = spval
+ ELSE
+ ! calculate parameters used in operator varied with satellite
+ CALL calc_parameters(sat_theta, sat_fghz)
+
+!#############################################################################
+! atmosphere module
+!#############################################################################
+ CALL atm(forc_topo, tref, tau_atm, tb_au, tb_ad)
+
+!#############################################################################
+! soil module
+!#############################################################################
+ CALL soil(&
+ patchclass, &
+ t_surf, t_deep, &
+ liq_surf, ice_surf, &
+ wf_sand_surf, wf_clay_surf, BD_all_surf, porsl_surf, &
+ r_r, tb_soil)
+
+!#############################################################################
+! vegetation and snow module
+! We categorized four different cases for the calculations:
+! 1) no vegetation and no snow
+! 2) no vegetation with snow
+! 3) vegetation without snow
+! 4) vegetation with snow
+!#############################################################################
+ ! roughly judge low or high vegetation (only for IGBP)
+ is_low_veg = .true.
+ IF (patchclass >= 1 .and. patchclass <= 5) THEN
+ is_low_veg = .false.
+ END IF
+
+ ! ensure snow density to <= 1 g/cm3
+ IF (snowdp > 0.01) THEN
+ rho_snow = (wliq_soisno(lb) + wice_soisno(lb))/(dz_soisno(lb)*1e3)
+ liq_snow = wliq_soisno(lb)*rho_snow/(dz_soisno(lb)*1e3)
+
+ IF (liq_snow > 1.0 .or. rho_snow > 1.0) then
+ rho_snow = 1.0
+ liq_snow = wliq_soisno(lb)*rho_snow/(dz_soisno(lb)*1e3)
+ END IF
+ END IF
+
+ ! main procedures
+ ! --------------------------------------------------------------------
+ ! 1) no veg and no snow
+ ! two components:
+ ! (1) brightness temperature of soil
+ ! (2) the downwelling radiation reflected by the soil
+ ! --------------------------------------------------------------------
+ IF ((lai + sai < 1e-6) .and. (snowdp < 0.01)) THEN
+ tb_tov = tb_soil + tb_ad*r_r
+ tb_tov_noad = tb_soil
+
+ ! --------------------------------------------------------------------
+ ! 2) no veg and has snow
+ ! two components:
+ ! (1) brightness temperature of snow
+ ! (2) the downwelling radiation reflected by the snow
+ ! --------------------------------------------------------------------
+ ELSE IF ((lai + sai < 1e-6) .and. (snowdp > 0.01)) THEN
+ ! calculate brightness temperature of snow-covered ground
+ CALL snow(t_soisno(1), t_soisno(1), snowdp, rho_snow, liq_snow, r_r, r_snow, tb_tos)
+
+ tb_tov = tb_tos + tb_ad*r_snow
+ tb_tov_noad = tb_tos
+
+ ! --------------------------------------------------------------------
+ ! 3) has veg and no snow
+ ! four components:
+ ! (1) the direct upwelling vegetation emission,
+ ! (2) the downwelling vegetation emission reflected by the soil and attenuated by the canopy layer
+ ! (3) upwelling soil emission attenuated by the canopy
+ ! (4) the downwelling reflected by the soil and attenuated by the canopy layer
+ ! --------------------------------------------------------------------
+ ELSE IF ((lai + sai > 1e-6) .and. (snowdp < 0.01)) THEN
+ ! calculate brightness temperature of vegetation
+ CALL veg(patchclass, lai, htop, 0.0, tleaf, tb_veg, gamma_p)
+
+ DO i = 1, 2
+ tb_2(i) = tb_veg(i)*gamma_p(i)*r_r(i)
+ tb_3(i) = tb_soil(i)*gamma_p(i)
+ tb_4(i) = tb_ad(i)*r_r(i)*(gamma_p(i)**2)
+ tb_tov(i) = tb_veg(i) + tb_2(i) + tb_3(i) + tb_4(i)
+ tb_tov_noad(i) = tb_veg(i) + tb_2(i) + tb_3(i)
+ END DO
+
+ ! --------------------------------------------------------------------
+ ! 4) has veg and has snow
+ ! We need to determine the positional relationship between vegetation and snow.
+ !
+ ! If vegetation is higher than snow,
+ ! we first calculate brightness temperature of snow (soil boundary), then calculate
+ ! four components to derive brightness temperature of top of vegetation:
+ ! (1) the direct upwelling vegetation emission,
+ ! (2) the downwelling vegetation emission reflected by the snow and attenuated by the canopy layer
+ ! (3) upwelling snow emission attenuated by the canopy
+ ! (4) the downwelling reflected by the snow and attenuated by the canopy layer
+ !
+ ! If vegetation is lower than snow
+ ! we first calculate brightness temperature of top of vegetation (soil boundary), then calculate
+ ! four components to derive brightness temperature of top of snow:
+ ! (1) the direct upwelling vegetation emission,
+ ! (2) the downwelling vegetation emission reflected by the soil and attenuated by the canopy layer
+ ! (3) upwelling soil emission attenuated by the canopy
+ ! (4) the downwelling reflected by the soil and attenuated by the canopy layer
+ ! --------------------------------------------------------------------
+ ELSE IF ((lai + sai > 1e-6) .and. (snowdp > 0.01)) THEN
+ IF (htop < snowdp) THEN
+ ! calculate brightness temperature of low vegetation
+ CALL veg(patchclass, lai, htop, snowdp, tleaf, tb_veg, gamma_p)
+
+ ! calculate brightness temperature of top of vegetation
+ DO i = 1, 2
+ tb_2(i) = tb_veg(i)*gamma_p(i)*r_r(i)
+ tb_3(i) = tb_soil(i)*gamma_p(i)
+ tb_4(i) = tb_ad(i)*r_r(i)*(gamma_p(i)**2)
+ tb_tov(i) = tb_veg(i) + tb_2(i) + tb_3(i) + tb_4(i)
+ tb_tov_noad(i) = tb_veg(i) + tb_2(i) + tb_3(i)
+ END DO
+
+ ! calculate reflectivity between the snow and low veg (adopted from CMEM)
+ r_sn(:) = 1.0 - tb_tov_noad(:)/t_soisno(1)
+
+ ! calculate brightness temperature of snow-covered ground
+ CALL snow(t_soisno(1), t_soisno(1), snowdp, rho_snow, liq_snow, r_sn, r_snow, tb_tos)
+
+ ! calculate brightness temperature of top of snow
+ tb_tov = tb_tos + tb_ad*r_snow
+ tb_tov_noad = tb_tos
+
+ ELSE
+ ! calculate brightness temperature of snow-covered ground
+ CALL snow(t_soisno(1), t_soisno(1), snowdp, rho_snow, liq_snow, r_r, r_snow, tb_tos)
+
+ ! calculate brightness temperature of high vegetation
+ CALL veg(patchclass, lai, htop, snowdp, tleaf, tb_veg, gamma_p)
+
+ ! calculate brightness temperature of top of vegetation
+ DO i = 1, 2
+ tb_2(i) = tb_veg(i)*gamma_p(i)*r_snow(i)
+ tb_3(i) = tb_tos(i)*gamma_p(i)
+ tb_4(i) = tb_ad(i)*r_snow(i)*(gamma_p(i)**2)
+ tb_tov(i) = tb_veg(i) + tb_2(i) + tb_3(i) + tb_4(i)
+ tb_tov_noad(i) = tb_veg(i) + tb_2(i) + tb_3(i)
+ END DO
+ END IF
+ END IF
+
+!#############################################################################
+! Caculate brightness temperature of top-of-atmosphere
+!#############################################################################
+ tb_toa = tb_tov*exp(-tau_atm) + tb_au
+
+ END IF
+
+ tb_toa_h = tb_toa(1)
+ tb_toa_v = tb_toa(2)
+
+ END SUBROUTINE forward
+
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE calc_parameters (sat_theta, sat_fghz)
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_DA_Const
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument -------------------------------
+ real(r8), intent(in) :: sat_theta, sat_fghz
+
+!----------------------- Local Variables -------------------------------
+
+ theta = sat_theta ! incidence angle of satellite (rad)
+ fghz = sat_fghz ! frequency of satellite (GHz)
+ f = fghz*1e9 ! frequency (Hz)
+ omega = 2.0*pi*f ! radian frequency (rad/s)
+ lam = C/f ! wavelength (m)
+ k = 2*pi/lam ! wave number (rad/m)
+ kcm = k/100.0 ! wave number (rad/cm)
+ kr = k*(0.5*1e-3) ! size parameter used in calcuate single-particle albedo
+
+ END SUBROUTINE calc_parameters
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE atm(z, tref, tau_atm, tb_au, tb_ad)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the atmospheric opacity and up and downwelling brightness temperature
+!
+! REFERENCES:
+! [1] Pellarin, T., et al. (2003), Two-year global simulation of L-band brightness
+! temperature over land, IEEE Trans. Geosci. Remote Sens., 41, 2135–2139.
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: z ! altitude (m)
+ real(r8), intent(in) :: tref ! 2m air temperature (K)
+ real(r8), intent(out) :: tau_atm ! atmospheric optical depth
+ real(r8), intent(out) :: tb_au(2) ! upwelling radiation (brightness temperature) of atmosphere
+ real(r8), intent(out) :: tb_ad(2) ! downwelling radiation (brightness temperature) of atmosphere
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: t_sky = 2.7 ! cosmic ray radiation (K)
+ real(r8) :: t_eq ! equivalent layer temperature
+ real(r8) :: gossat
+
+!-----------------------------------------------------------------------
+
+ ! calculate optical depth of atmosphere [1] eq(A1)
+ tau_atm = exp(-3.9262 - 0.2211*z/1000 - 0.00369*tref)/cos(theta)
+ gossat = exp(-tau_atm)
+
+ ! calculate equivalent layer temperature
+ t_eq = exp(4.9274 + 0.002195*tref)
+
+ ! upwelling radiation (brightness temperature) of atmosphere
+ tb_au(:) = t_eq*(1.-gossat)
+
+ ! downwelling radiation (brightness temperature) of atmosphere [1] eq(A2)
+ tb_ad(:) = t_eq*(1.-gossat) + t_sky*gossat
+
+ END SUBROUTINE atm
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE soil( &
+ patchclass, &
+ t_surf, t_deep, &
+ liq_surf, ice_surf, &
+ wf_sand_surf, wf_clay_surf, BD_all_surf, porsl_surf, &
+ r_r, tb_soil)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate brightness temperature of soil surface
+!
+! REFERENCES:
+! [1] Wigneron et al., 2007, "L-band Microwave Emission of the Biosphere (L-MEB) Model:
+! Description and calibration against experimental
+! data sets over crop fields" Remote Sensing of Environment. Vol. 107, pp. 639-655k
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ integer, intent(in) :: patchclass ! land cover class
+ real(r8), intent(in) :: t_surf ! soil temperature at surface (C)
+ real(r8), intent(in) :: t_deep ! soil temperature at deep layer (C)
+ real(r8), intent(in) :: liq_surf ! liquid volumetric water content at surface (m3/m3)
+ real(r8), intent(in) :: ice_surf ! ice volumetric water content at surface (m3/m3)
+ real(r8), intent(in) :: wf_sand_surf ! gravimetric sand percent fraction(%) at surface
+ real(r8), intent(in) :: wf_clay_surf ! gravimetric clay percent fraction(%) at surface
+ real(r8), intent(in) :: BD_all_surf ! bulk density of soil (g/m3) at surface
+ real(r8), intent(in) :: porsl_surf ! soil porosity at surface
+ real(r8), intent(out) :: r_r(2) ! rough surface reflectivity for H and V polarizations
+ real(r8), intent(out) :: tb_soil(2) ! brightness temperature of soil
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: t_eff(2) ! effective temperature for H and V polarizations, [K]
+ complex(r8) :: eps_soil ! dielectric constant of soil for H and V polarizations
+ real(r8) :: r_s(2) ! smooth surface reflectivity for H and V polarizations
+ complex(r8) :: ew ! dielectric constant of water
+ logical :: is_desert ! flag for desert soil
+ real(r8) :: ffrz ! fraction of frozen soil
+ complex(r8) :: eps_f = (5.0, 0.5) ! dielectric constant of frozen soil
+ real(r8) :: sal_soil = 0.0 ! soil salinity (psu)
+
+!-----------------------------------------------------------------------
+
+ ! whether this patch is desert
+ is_desert = .false.
+ IF (liq_surf < 0.02 .and. wf_sand_surf > 90) THEN
+ is_desert = .true.
+ END IF
+
+ ! calculate ratio of freezed soil
+ IF (liq_surf + ice_surf <= 0.0d0) THEN
+ ffrz = 0.0d0
+ ELSE
+ ffrz = ice_surf / (liq_surf + ice_surf)
+ ENDIF
+
+ ! caculate effective temperature
+ CALL eff_soil_temp(liq_surf, t_surf, t_deep, t_eff)
+
+ ! caculate dielectric constant of soil (mixture medium)
+ IF (is_desert) THEN
+ ! Microwave 1-10GHz permittivity of dry sand (matzler '98, eq.1)
+ eps_soil = 2.53 + (2.79 - 2.53)/(1 - jj*(fghz/0.27)) + jj*0.002
+ ELSE
+ ! define bulk density and porosity (CMEM)
+ ! BD_all_surf = (wf_sand_surf*1.60d0 + wf_clay_surf*1.10d0 + (100.0d0 - wf_sand_surf - wf_clay_surf)*1.20d0)/100.0d0
+ ! porsl_surf = 1.0d0 - BD_all_surf/2.660d0
+
+ ! caculate ice or water dielectric constant
+ IF (ffrz > 0.95) THEN
+ CALL diel_ice(t_surf, ew)
+ ELSE
+ CALL diel_water(-1, liq_surf, t_surf, wf_sand_surf, wf_clay_surf, BD_all_surf, sal_soil, ew)
+ END IF
+
+ ! caculate dielectric constant in mixed soil
+ IF (DEF_DA_RTM_diel == 0) THEN
+ CALL diel_soil_W80 (ew, t_surf, liq_surf, wf_sand_surf, wf_clay_surf, porsl_surf, eps_soil)
+ ELSE IF (DEF_DA_RTM_diel == 1) THEN
+ CALL diel_soil_D85 (ew, liq_surf, wf_sand_surf, wf_clay_surf, BD_all_surf, eps_soil)
+ ELSE IF (DEF_DA_RTM_diel == 2) THEN
+ CALL diel_soil_M04 (liq_surf, wf_clay_surf, eps_soil)
+ ELSE IF (DEF_DA_RTM_diel == 3) THEN
+ CALL diel_soil_M09 (liq_surf, t_surf, wf_clay_surf, eps_soil)
+ ENDIF
+ END IF
+
+ ! mix dielectric constant of frozen and non-frozen soil
+ eps_soil = eps_soil*(1.-ffrz) + eps_f*ffrz
+
+ ! caculate smooth surface reflectivity
+ CALL smooth_reflectivity(eps_soil, r_s)
+
+ ! caculate rough surface reflectivity
+ CALL rough_reflectivity(is_desert, patchclass, r_s, r_r)
+
+ ! calculate brightness temperature
+ IF (is_desert) THEN
+ CALL desert(t_eff, r_r, eps_soil, tb_soil)
+ ELSE
+ tb_soil = t_eff * (1 - r_r)
+ END IF
+
+ END SUBROUTINE soil
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE eff_soil_temp(wc_surf, t_surf, t_deep, t_eff)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the effective temperature of soil
+!
+! REFERENCES:
+! [1] An improved two-layer algorithm for estimating effective soil
+! temperature in microwave radiometry using in situ temperature
+! and soil moisture measurements
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+
+! ------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: wc_surf ! soil moisture at surface (m3/m3)
+ real(r8), intent(in) :: t_surf ! soil temperature (C) at surface
+ real(r8), intent(in) :: t_deep ! soil temperature (C) at deep layer
+ real(r8), intent(out) :: t_eff(2) ! effective temperature for H and V polarizations, [K]
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: C ! parameter depending mainly on frequency
+ ! and soil moisture to describe the impact of
+ ! surface temperature on the effective temperature;
+ ! soil moisture increase, C large, teff close to tsurf
+ ! soil moisture decrease, C small, tdeep impact teff more
+ real(r8) :: w0 = 0.30 ! parameter
+ real(r8) :: bw = 0.30 ! parameter
+!-----------------------------------------------------------------------
+
+ IF (wc_surf < 0.0) THEN
+ C = 0.001
+ ELSE
+ C = max(0.001, (wc_surf/w0)**bw)
+ ENDIF
+ t_eff(:) = t_deep + (t_surf - t_deep)*C + tfrz
+
+ END SUBROUTINE eff_soil_temp
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE diel_ice(t, eps_i)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate dielectric constant of pure ice
+!
+! REFERENCES:
+! [1] Matzler, C. (2006). Thermal Microwave Radiation: Applications
+! for Remote Sensing p456-461
+!-----------------------------------------------------------------------
+ USE MOD_Const_Physical
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: t ! temperature (C)
+ complex(r8), intent(out) :: eps_i ! dielectric constant of ice water
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: betam ! beta parameter by Mishima et al. (1983)
+ real(r8) :: dbeta ! corrected delta beta parameter
+ real(r8) :: beta ! beta parameter
+ real(r8) :: t_inv ! modified inverse temperature
+ real(r8) :: tk ! temperature (K)
+ real(r8) :: alpha ! alpha parameter
+ real(r8) :: eps_i_r ! real part of pure ice dielectric constant
+ real(r8) :: eps_i_i ! imaginary part of pure ice dielectric constant
+
+!-----------------------------------------------------------------------
+
+ ! C to K
+ tk = t + tfrz
+
+ ! eq.(5.33): calculate beta parameter by Mishima et al. (1983)
+ betam = (0.0207/tk)*(exp(335./tk)/((exp(335./tk) - 1.)**2.)) + 1.16e-11*(fghz**2.) ! [1](5.33)
+
+ ! eq.(5.35): calculate delta beta parameter
+ dbeta = exp(-10.02 + 0.0364*t) ! [1](5.35)
+
+ ! eq.(5.34): calculate beta parameter
+ beta = betam + dbeta ! [1](5.34)
+
+ ! eq.(5.32): calculate alpha parameter
+ t_inv = 300./tk - 1 ! [1](p.457)
+ alpha = (0.00504 + 0.0062*t_inv)*exp(-22.1*t_inv) !(GHz) ! [1](5.32)
+
+ ! eq.(5.30): calculate real part of pure ice dielectric constant
+ eps_i_r = 3.1884 + 9.1e-4*t ! [1](5.30)
+
+ ! eq.(5.31): calculate imaginary part of pure ice dielectric constant
+ eps_i_i = alpha/fghz + beta*fghz ! [1](5.31)
+
+ ! calculate dielectric constant of pure ice
+ eps_i = eps_i_r - jj*eps_i_i ! [1](5.31)
+
+ END SUBROUTINE diel_ice
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE diel_water(type, swc, t, wf_sand, wf_clay, BD_all, sal, eps_w)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate dielectric constant of water in water (saline water)
+!
+! REFERENCES:
+! [1] Ulaby FT, R. K. Moore, and A. K. Fung, Microwave Remote Sensing:
+! Active and Passive. Vol. III. From theory to applications. Artech House,
+! Norwood, MA., 1986
+! [2] Klein, L. A. and C. T. Swift (1977): An improved model
+! for the dielectric constant of sea water at microwave
+! frequencies, IEEE Transactions on Antennas and Propagation,
+! Vol. AP-25, No. 1, 104-111.
+!-----------------------------------------------------------------------
+ USE MOD_Const_Physical
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ integer, intent(in) :: type ! type of water, 0: pure water, 1: sea water, 2: soil water
+ real(r8), intent(in) :: swc ! soil water content (m3/m3)
+ real(r8), intent(in) :: t ! soil temperature (C)
+ real(r8), intent(in) :: wf_sand ! gravimetric sand percent fraction(%)
+ real(r8), intent(in) :: wf_clay ! gravimetric clay percent fraction(%)
+ real(r8), intent(in) :: BD_all ! bulk density(g/cm3)
+ real(r8), intent(in) :: sal ! water salinity (psu)
+ complex(r8), intent(out) :: eps_w ! dielectric constant of soil water
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: sigma ! ionic conductivity (S/m)
+ real(r8) :: a, b ! parameters
+ real(r8) :: tau_w ! relaxation time of pure water
+ real(r8) :: eps_w0 ! static dielectric constant of pure water
+ real(r8) :: wc
+
+!-----------------------------------------------------------------------
+
+ ! [3] eq.16: tau(T, sal) = tau_w(T) * b(sal, T)
+ ! calculate relaxation time of pure water (Stogryn)
+ tau_w = 1.768e-11 - 6.068e-13*t + 1.104e-14*t**2 - 8.111e-17*t**3 ! [2](17)
+ b = 1.000 + 2.282e-5*sal*t - 7.638e-4*sal - 7.760e-6*sal**2 + 1.105e-8*sal**3 ! [2](18)
+ tau_w = tau_w*b ! [2](16)
+
+ ! [3] eq.13: eps_w0(sal, T) = eps_w0(T) * a(sal, T)
+ ! static dielectric constant of pure water (Klein and Swift)
+ eps_w0 = 87.134 - 1.949e-1*t - 1.276e-2*t**2 + 2.491e-4*t**3 ! [2](14)
+ a = 1.000 + 1.613e-5*sal*t - 3.656e-3*sal + 3.210e-5*sal**2 - 4.232e-7*sal**3 ! [2](15)
+ eps_w0 = eps_w0*a ! [2](13)
+
+ IF (type == 0) THEN ! pure water
+ ! [1] eq.19
+ eps_w0 = 88.045 - 0.4147*t + 6.295e-4*t**2 + 1.075e-5*t**3
+ eps_w = eps_w_inf + (eps_w0 - eps_w_inf)/(1 - jj*omega*tau_w)
+
+ ELSEIF (type == 1) THEN ! sea water
+ ! calculate ionic conductivity [1] eq.27, eq.28
+ sigma = sal*(0.182521 - 1.46192e-3*sal + 2.09324e-5*sal**2 - 1.28205e-7*sal**3) &
+ *exp(-1.*(25 - t)* &
+ (2.033e-2 + 1.266e-4*(25 - t) + 2.464e-6*(25 - t)**2 &
+ - sal*(1.849e-5 - 2.551e-7*(25 - t) + 2.551e-8*(25 - t)**2)))
+
+ ! diel constant of sea water [1] eq.21
+ eps_w = eps_w_inf + (eps_w0 - eps_w_inf)/(1 - jj*omega*tau_w) + jj*sigma/(omega*eps_0)
+ ELSE
+ ! calculate soil conductivity
+ sigma = -1.645 + 1.939*BD_all - 0.02256*wf_sand + 0.01594*wf_clay
+ IF (sigma < 0.) THEN
+ sigma = 0. ! negative for very sandy soils with low bulk density
+ END IF
+
+ ! calculate dielectric constant of soil-water by modified Debye expression
+ wc = max(0.001, swc)
+ eps_w = eps_w_inf + (eps_w0 - eps_w_inf)/(1 - jj*omega*tau_w) &
+ + jj*sigma/(omega*eps_0)*(rho_soil - BD_all)/(rho_soil*wc)
+ END IF
+
+ END SUBROUTINE diel_water
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE diel_soil_W80(ew, t, wc, wf_sand, wf_clay, porsl, eps)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the dielectric constant of a wet soil
+!
+! REFERENCES:
+! [1] Matzler, C. (1998). Microwave permittivity of dry sand.
+! IEEE Transactions on Geoscience and Remote Sensing, 36(1), 317-319.
+!
+! [2] Wang and Schmugge, 1980: An empirical model for the
+! complex dielectric permittivity of soils as a function of water
+! content. IEEE Trans. Geosci. Rem. Sens., GE-18, No. 4, 288-295.
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+! ------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: t ! soil temperature (C)
+ real(r8), intent(in) :: wc ! volumetric soil moisture (m3/m3)
+ real(r8), intent(in) :: wf_sand ! gravimetric sand percent fraction(%)
+ real(r8), intent(in) :: wf_clay ! gravimetric clay percent fraction(%)
+ real(r8), intent(in) :: porsl ! soil porosity at surface
+ complex(r8), intent(in) :: ew ! dielectric constant of water
+ complex(r8), intent(out) :: eps
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: wp ! wilting point
+ real(r8) :: wt ! transition moisture point (cm3/cm3)
+ real(r8) :: gamma ! fitting parameter
+ real(r8) :: ecl ! conductivity loss
+ real(r8) :: alpha ! conductivity loss parameter
+ real(r8) :: sal_sea = 32.5 ! sea water salinity (psu)
+ real(r8) :: sal_soil = 0.0 ! soil salinity (psu)
+ complex(r8) :: eps_x ! dielectric constant of the initially absorbed water
+ complex(r8) :: eps_a = (1.0, 0.0) ! dielectric constant of air, [2]IV
+ complex(r8) :: eps_r = (5.5, 0.2) ! dielectric constant of rock, [2]IV
+ complex(r8) :: eps_i = (3.2, 0.1) ! dielectric constant of ice, [2]IV
+ complex(r8) :: eps_f = (5.0, 0.5) ! dielectric constant of frozen soil
+
+!-----------------------------------------------------------------------
+
+ ! calculate wilting point at the soil layer
+ wp = 0.06774 - 0.00064*wf_sand + 0.00478*wf_clay ! [2](1)
+
+ ! calculate fitting parameters
+ gamma = -0.57*wp + 0.481 ! [2](8)
+
+ ! calculate transition moisture point
+ wt = 0.49*wp + 0.165 ! [2](9)
+
+ ! calculate dielectric constant of wet soil (when all soil freeze, eps_x = eps_i)
+ IF (wc <= wt) THEN
+ eps_x = eps_i + (ew - eps_i)*(wc/wt)*gamma ! [2](3)
+ eps = wc*eps_x + (porsl - wc)*eps_a + (1.-porsl)*eps_r ! [2](2)
+ ELSE
+ eps_x = eps_i + (ew - eps_i)*gamma ! [2](5)
+ eps = wt*eps_x + (wc - wt)*ew + (porsl - wc)*eps_a + (1.-porsl)*eps_r ! [2](4)
+ END IF
+
+ ! add conductivity loss for imaginary part
+ alpha = min(100.*wp, 26.)
+ ecl = alpha*wc**2 ! [2](6)
+ eps = eps + jj*ecl ! [2](6)
+
+ END SUBROUTINE diel_soil_W80
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE diel_soil_M04(wc, wf_clay, eps)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the dielectric constant of a wet soil Developed and
+! validated from 1 to 10 GHz, adapted for a large range of soil moisture
+!
+! REFERENCES:
+! [1] Mironov et al, Generalized Refractive Mixing Dielectric Model for
+! moist soil. IEEE Trans. Geosc. Rem. Sens., vol 42 (4), 773-785. 2004.
+!
+! [2] Mironov et al, Physically and Mineralogically Based Spectroscopic
+! Dielectric Model for Moist Soils. IEEE Trans. Geosc. Rem. Sens.,
+! vol 47 (7), 2059-2070. 2009.
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+! ------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: wc ! soil moisture (m3/m3)
+ real(r8), intent(in) :: wf_clay ! gravimetric clay percent fraction(%)
+ complex(r8), intent(out) :: eps
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: znd, zkd, zxmvt, zep0b, ztaub, zsigmab, zep0u, ztauu
+ real(r8) :: zsigmau, zcxb, zepwbx, zepwby, zcxu, zepwux, zepwuy
+ real(r8) :: znb, zkb, znu, zku, zxmvt2, znm, zkm, zepmx, zepmy
+ integer :: zflag
+
+!-----------------------------------------------------------------------
+!------------------------------------------------------------------------
+! Initializing the GRMDM spectroscopic parameters with clay (fraction)
+!------------------------------------------------------------------------
+ ! RI & NAC of dry soils
+ znd = 1.634 - 0.539 * (wf_clay/100) + 0.2748 * (wf_clay/100) ** 2
+ zkd = 0.03952 - 0.04038 * (wf_clay / 100) ! [2](18)
+
+ ! Maximum bound water fraction
+ zxmvt = 0.02863 + 0.30673 * wf_clay / 100 ! [2](19)
+
+ ! Bound water parameters
+ zep0b = 79.8 - 85.4 * (wf_clay / 100) + 32.7 * (wf_clay / 100)*(wf_clay / 100) ! [2](20)
+ ztaub = 1.062e-11 + 3.450e-12 * (wf_clay / 100) ! [2](21)
+ zsigmab = 0.3112 + 0.467 * (wf_clay / 100) ! [2](22)
+
+ ! Unbound (free) water parameters
+ zep0u = 100 ! [2](24)
+ ztauu = 8.5e-12 ! [2](25)
+ zsigmau = 0.3631 + 1.217 * (wf_clay / 100)
+
+ ! Computation of epsilon water (bound & unbound)
+ zcxb = (zep0b - eps_w_inf) / (1. + (2.*pi*f*ztaub)**2) ! [2](16)
+ zepwbx = eps_w_inf + zcxb ! [2](16)
+ zepwby = zcxb * (2.*pi*f*ztaub) + zsigmab / (2.*pi*eps_0*f) ! [2](16)
+ zcxu = (zep0u - eps_w_inf) / (1 + (2*pi*f*ztauu)**2) ! [2](16)
+ zepwux = eps_w_inf + zcxu ! [2](16)
+ zepwuy = zcxu * (2.*pi*f*ztauu) + zsigmau/(2.*pi*eps_0*f)
+
+ ! Computation of refractive index of water (bound & unbound)
+ znb = sqrt( sqrt( zepwbx**2 + zepwby**2) + zepwbx ) / sqrt(2.0) ! [2](14)
+ zkb = sqrt( sqrt( zepwbx**2 + zepwby**2) - zepwbx ) / sqrt(2.0) ! [2](15)
+ znu = sqrt( sqrt( zepwux**2 + zepwuy**2) + zepwux ) / sqrt(2.0) ! [2](14)
+ zku = sqrt( sqrt( zepwux**2 + zepwuy**2) - zepwux ) / sqrt(2.0) ! [2](15)
+
+ ! Computation of soil refractive index (nm & km): xmv can be a vector
+ zxmvt2 = min (wc, zxmvt)
+ zflag = 0
+ IF ( wc >= zxmvt ) zflag = 1
+ znm = znd + (znb - 1) * zxmvt2 + (znu - 1) * (wc-zxmvt) * zflag ! [2](12)
+ zkm = zkd + zkb * zxmvt2 + zku * (wc-zxmvt) * zflag ! [2](13)
+
+ ! computation of soil dielectric constant:
+ zepmx = znm ** 2 - zkm ** 2 ! [2](11)
+ zepmy = znm * zkm * 2 ! [2](11)
+ eps = cmplx(zepmx, zepmy, kind=r8)
+
+ END SUBROUTINE diel_soil_M04
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE diel_soil_M09(wc, t, wf_clay, eps)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the dielectric constant of a wet soil Developed and
+! validated from 1 to 10 GHz, adapted for a large range of soil moisture
+!
+! REFERENCES:
+! [1] V. L. Mironov, S. V. Fomin,
+! "Temperature and mineralogy dependable model for microwave dielectric
+! spectra of moist soils", PIERS Online, vol. 5, no. 5, pp. 411-415, 2009.
+!
+! [2] Mironov et al, Physically and Mineralogically Based Spectroscopic Dielectric
+! Model for Moist Soils. IEEE Trans. Geosc. Rem. Sens., vol 47 (7), 2059-2070. 2009.
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+! ------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: t ! soil temperature
+ real(r8), intent(in) :: wc ! soil moisture (m3/m3)
+ real(r8), intent(in) :: wf_clay ! weighted fraction (%)
+ complex(r8), intent(out) :: eps
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: nd, kd, mvt, ts, e0b, Bb, Bsgb, Fb, eb0
+ real(r8) :: dSbR, taub, sigmabt, sigmab, e0u, Bu, Bsgu, Fu, eu0, dHuR, dSuR, tauu, dHbR
+ real(r8) :: sigmau, sigmaut, cxb, eb_r, eb_i, cxu, eu_r, eu_i, nb, kb, nu, ku, nm, km, eps_r, eps_i
+
+!-----------------------------------------------------------------------
+!------------------------------------------------------------------------
+! Initializing the GRMDM spectroscopic parameters with clay (fraction)
+!------------------------------------------------------------------------
+ ! RI & NAC of dry soils
+ nd = 1.634 - 0.539 * (wf_clay/100) + 0.2748 * (wf_clay/100) ** 2 ! [1](11)
+ kd = 0.03952 - 0.04038 * (wf_clay/100) ! [1](12)
+
+ ! maximum bound water fraction
+ mvt = 0.02863 + 0.30673 * (wf_clay/100) ! [1](13)
+
+ ! starting temperature for parameters' fit ([1] p.413)
+ ts = 20.
+
+ ! eb0 computation
+ e0b = 79.8 - 85.4 * wf_clay + 32.7 * (wf_clay/100) **2 ! [1](14)
+ Bb = 8.67e-19 - 0.00126 * (wf_clay/100) + 0.00184 * (wf_clay/100) ** 2 - 9.77e-10*(wf_clay**3) - 1.39e-15 *(wf_clay**4) ! [1](15)
+ Bsgb = 0.0028 + 0.02094e-2*wf_clay - 0.01229e-4*(wf_clay**2) - 5.03e-22*(wf_clay**3) + 4.163e-24*(wf_clay**4) ! [1](23)
+ Fb = log((e0b - 1)/(e0b + 2)) ! [1](8)(ep0->e0p)
+ eb0 = (1 + 2*exp(Fb-Bb*(t-ts))) / (1 - exp(Fb-Bb*(t-ts))) ! [1](7)(e0p->ep0)
+
+ ! taub computation
+ dHbR = 1467 + 2697e-2*wf_clay - 980e-4 *(wf_clay**2) + 1.368e-10*(wf_clay**3) - 8.61e-13 *(wf_clay**4) ! [1](18)
+ dSbR = 0.888 + 9.7e-2 *wf_clay - 4.262e-4*(wf_clay**2) + 6.79e-21 *(wf_clay**3) + 4.263e-22*(wf_clay**4) ! [1](19)
+ taub = 48e-12 * exp(dHbR/(t+tfrz)-dSbR)/(t+tfrz) ! [1](9)
+
+ ! sigmab computation
+ sigmabt = 0.3112 + 0.467e-2*wf_clay ! [1](22)
+ sigmab = sigmabt + Bsgb*(t-ts) ! [1](10)
+
+ ! unbound (free) water parameters
+ !-------------------
+ ! eu0 computation
+ !-------------------
+ e0u = 100. ! [1](16)
+ Bu = 1.11e-4 - 1.603e-7 *wf_clay + 1.239e-9 *(wf_clay**2) + 8.33e-13 *(wf_clay**3) - 1.007e-14*(wf_clay**4) ! [1](17)
+ Bsgu = 0.00108 + 0.1413e-2*wf_clay - 0.2555e-4*(wf_clay**2) + 0.2147e-6*(wf_clay**3) - 0.0711e-8*(wf_clay**4) ! [1](25)
+ Fu = log((e0u - 1)/(e0u + 2)) ! [1](8)(ep0->e0p)
+ eu0 = (1 + 2*exp(Fu-Bu*(t-ts))) / (1-exp(Fu-Bu*(t-ts))) ! [1](7))e0p->ep0)
+
+ !--------------------
+ ! tauu computation
+ !--------------------
+ dHuR = 2231 - 143.1e-2 *wf_clay + 223.2e-4*(wf_clay**2) - 142.1e-6*(wf_clay**3) + 27.14e-8 *(wf_clay**4) ! [1](20)
+ dSuR = 3.649 - 0.4894e-2*wf_clay + 0.763e-4*(wf_clay**2) - 0.4859e-6*(wf_clay**3) + 0.0928e-8*(wf_clay**4) ! [1](21)
+ tauu = 48e-12 * exp(dHuR/(t+tfrz)-dSuR)/(t+tfrz) ! [1](9)
+
+ !----------------------
+ ! sigmau computation
+ !----------------------
+ sigmaut = 0.05_r8 + 1.4_r8*(1.0_r8 - (1.0_r8 - wf_clay*1.e-2_r8)**4.664_r8) ! [1](24)
+ sigmau = sigmaut + Bsgu*(t-ts) ! [1](10)
+
+ !--------------------------------------------------
+ ! computation of epsilon water (bound & unbound)
+ !--------------------------------------------------
+ cxb = (eb0-eps_w_inf) / (1+(2*pi*f*taub)**2) ! [1](6), [2](16)
+ eb_r = eps_w_inf + cxb ! [1](6), [2](16)
+ eb_i = cxb*(2*pi*f*taub) + sigmab/(2*pi*eps_0*f) ! [1](6), [2](16)
+ cxu = (eu0-eps_w_inf) / (1+(2*pi*f*tauu)**2) ! [1](6), [2](16)
+ eu_r = eps_w_inf + cxu ! [1](6), [2](16)
+ eu_i = cxu*(2*pi*f*tauu) + sigmau/(2*pi*eps_0*f) ! [1](6), [2](16)
+
+ !--------------------------------------------------------------
+ ! computation of refractive index of water (bound & unbound)
+ !--------------------------------------------------------------
+ nb = sqrt(sqrt(eb_r**2+eb_i**2)+eb_r) / sqrt(2.0) ! [1](5)
+ kb = sqrt(sqrt(eb_r**2+eb_i**2)-eb_r) / sqrt(2.0) ! [1](5)
+ nu = sqrt(sqrt(eu_r**2+eu_i**2)+eu_r) / sqrt(2.0) ! [1](5)
+ ku = sqrt(sqrt(eu_r**2+eu_i**2)-eu_r) / sqrt(2.0) ! [1](5)
+
+ !--------------------------------------------------
+ ! computation of soil refractive index (nm & km)
+ !--------------------------------------------------
+ IF (wc <= mvt) THEN
+ nm = nd + (nb-1)*wc ! [2](12)
+ km = kd + kb*wc ! [2](13)
+ ELSE
+ nm = nd + (nb-1)*mvt + (nu-1)*(wc-mvt) ! [2](12)
+ km = kd + kb*mvt + ku*(wc-mvt) ! [2](13)
+ ENDIF
+
+ !-------------------------------------------
+ ! computation of soil dielectric constant
+ !-------------------------------------------
+ eps_r = nm**2 - km**2 ! [1](4)
+ eps_i = 2* nm * km ! [1](4)
+ eps = cmplx(eps_r, eps_i, kind=r8)
+
+ END SUBROUTINE diel_soil_M09
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE diel_soil_D85(ew, swc, wf_sand, wf_clay, BD_all, eps)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the dielectric constant of a wet soil Developed and validated for 1.4 and 18 GHz.
+
+! REFERENCES:
+! [1] Dobson et al., 1985: Microwave Dielectric behavior of
+! wet soil - part II: Dielectric mixing models,
+! IEEE Trans. Geosc. Rem. Sens., GE-23, No. 1, 35-46.
+
+! [2] N. R. Peplinski, F. T. Ulaby, and M. C. Dobson,
+! Dielectric Properties of Soils in the 0.3-1.3-GHz Range,
+! IEEE Trans. Geosc. Rem. Sens., vol. 33, pp. 803-807, May 1995
+
+! [3] N. R. Peplinski, F. T. Ulaby, and M. C. Dobson,
+! Corrections to “Dielectric Properties of Soils in the 0.3-1.3-GHz Range",
+! IEEE Trans. Geosc. Rem. Sens., vol. 33, p. 1340, November 1995
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+! ------------------------ Dummy Argument ------------------------------
+ complex(r8), intent(in) :: ew ! dielectric constant of water
+ real(r8), intent(in) :: swc ! soil moisture
+ real(r8), intent(in) :: wf_sand ! gravimetric sand percent fraction(%)
+ real(r8), intent(in) :: wf_clay ! gravimetric clay percent fraction(%)
+ real(r8), intent(in) :: BD_all ! soil bulk density (g/cm3)
+ complex(r8), intent(out) :: eps
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: alphas = 0.65_r8
+ real(r8) :: beta, eaa, eps_s, epsi, epsr, wc
+
+!-----------------------------------------------------------------------
+
+ wc = max(swc, 0.001_r8)
+ eps_s = (1.01_r8 + 0.44_r8 * rho_soil)**2.0_r8 - 0.062_r8 ! [1](22)
+ beta = (127.48_r8 - 0.519_r8 * wf_sand - 0.152_r8 * wf_clay) / 100.0_r8 ! [1](30)
+ eaa = 1.0_r8 + (BD_all / rho_soil) * (eps_s ** alphas - 1.0_r8) &
+ & + (wc ** beta) * (real(ew) ** alphas) - wc ! [1](28)
+ epsr = eaa ** (1.0_r8/alphas) ! [2](2),[3]
+ beta = (133.797_r8 - 0.603_r8 * wf_sand - 0.166_r8 * wf_clay) / 100.0_r8 ! [1](31) 1.33797 -> 133.797, [2](5)
+ eaa = (wc ** beta) * (abs(aimag(ew)) ** alphas) ! [2](3)
+ epsi = eaa ** (1.0_r8/alphas) ! [2](3)
+ eps = cmplx(epsr, epsi, kind=r8)
+
+ END SUBROUTINE diel_soil_D85
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE smooth_reflectivity(eps, r_s)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the smooth surface reflectivity by Fresnel Law
+!
+! REFERENCES:
+! [1] Njoku and Kong, 1977: Theory for passive microwave remote sensing
+! of near-surface soil moisture. Journal of Geophysical Research,
+! Vol. 82, No. 20, 3108-3118.
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ complex(r8), intent(in) :: eps ! dielectric constant of the surface
+ real(r8), intent(out) :: r_s(2) ! reflectivities of flat surfaces for H and V polarizations
+
+!----------------------- Local Variables -------------------------------
+ complex(r8) :: g ! parameter in Fresnel Law
+
+!-----------------------------------------------------------------------
+
+ g = sqrt(eps - sin(theta)**2)
+ r_s(1) = abs((cos(theta) - g)/(cos(theta) + g))**2.
+ r_s(2) = abs((cos(theta)*eps - g)/(cos(theta)*eps + g))**2.
+
+ END SUBROUTINE smooth_reflectivity
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE rough_reflectivity(is_desert, patchclass, r_s, r_r)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the rough surface reflectivity
+!
+! REFERENCES:
+! [1] Kerr and Njokui, 1990: A Semiempirical Model For Interpreting Microwave
+! Emission From Semiarid Land Surfaces as Seen From Space
+! IEEE Trans. Geosci. Rem. Sens., Vol.28, No.3, 384-393.
+!
+! [2] Wigneron, J. P., Jackson, T. J., O'neill, P., De Lannoy, G., de Rosnay, P., Walker,
+! J. P., ... & Kerr, Y. (2017). Modelling the passive microwave signature from land surfaces:
+! A review of recent results and application to the L-band SMOS & SMAP soil moisture retrieval algorithms.
+! Remote Sensing of Environment, 192, 238-262.
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_DA_Const
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ logical, intent(in) :: is_desert ! flag for desert soil
+ integer, intent(in) :: patchclass ! patch class
+ real(r8), intent(in) :: r_s(2) ! reflectivities of flat surfaces for H and V polarizations
+ real(r8), intent(out) :: r_r(2) ! reflectivities of rough surfaces for H and V polarizations
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: Q ! parameter for polarization mixing
+ real(r8) :: hr(N_land_classification) ! roughness parameter
+ real(r8) :: nrh(N_land_classification) ! parameter for H polarization
+ real(r8) :: nrv(N_land_classification) ! parameter for V polarization
+
+!-----------------------------------------------------------------------
+
+ IF (is_desert) THEN
+ r_r = r_s
+ ELSE
+ ! calculate parameter for polarization mixing due to surface roughness
+ IF (fghz < 2.) THEN
+ Q = 0. ! Q is assumed zero at low frequency
+ ELSE
+ Q = 0.35*(1.0 - exp(-0.6*rgh_surf**2*fghz)) ! [1](16)
+ END IF
+
+ ! calculate rough surface reflectivity (default settings used in [2])
+ IF (DEF_DA_RTM_rough == 0) THEN
+ hr(:) = (2.0*kcm*rgh_surf)**2.0
+ nrh(:) = 0.0
+ nrv(:) = 0.0
+ ELSE IF (DEF_DA_RTM_rough == 1) THEN
+ hr(:) = hr_SMOS
+ nrh(:) = 2.0
+ nrv(:) = 0.0
+ ELSE IF (DEF_DA_RTM_rough == 2) THEN
+ hr(:) = hr_SMAP
+ nrh(:) = 2.0
+ nrv(:) = 2.0
+ ELSE IF (DEF_DA_RTM_rough == 3) THEN
+ hr(:) = hr_P16
+ nrh(:) = -1.0
+ nrv(:) = -1.0
+ END IF
+
+ ! rough surface reflectivity for H and V polarizations
+ r_r(1) = (Q*r_s(2) + (1.-Q)*r_s(1))*exp(-hr(patchclass)*cos(theta)**nrh(patchclass))
+ r_r(2) = (Q*r_s(1) + (1.-Q)*r_s(2))*exp(-hr(patchclass)*cos(theta)**nrv(patchclass))
+ END IF
+
+ END SUBROUTINE rough_reflectivity
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE desert(t_soil, r_r, eps, tb_desert)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate desert emissivity using Grody and Weng, 2008
+!
+! REFERENCES:
+! [1] Grody, N. C., & Weng, F. (2008). Microwave emission and scattering from deserts:
+! Theory compared with satellite measurements.
+! IEEE Transactions on Geoscience and Remote Sensing, 46, 361–375.
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: t_soil(2) ! desert surface temperature (K) (h-pol and v-pol)
+ real(r8), intent(in) :: r_r(2) ! reflectivity of rough surface (h-pol and v-pol)
+ complex(r8), intent(in) :: eps ! diel. const of desert
+ real(r8), intent(out) :: tb_desert(2) ! brightness temperature of soil for H- and V- polarization
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: f0 = 0.7 ! the fractional volume of spherical particles
+ ! (f = (4/3)*pi*r^3*n0),
+ ! r : the particle radius = 0.5 (mm)
+ ! n0 : the number of particles per unit volume.
+ real(r8) :: w ! single-particle albedo
+ real(r8) :: g ! asymmetry parameter
+ real(r8) :: a ! similarity parameter
+ real(r8) :: em(2) ! desert soil emissivity
+ real(r8) :: y_r ! real part of y-parameters
+ real(r8) :: y_i ! imaginary part of y-parameters
+
+!-----------------------------------------------------------------------
+ ! calculate y-parameters (eq.A15)
+ y_r = (real(eps) - 1)/(real(eps) + 2) ! [1](A15)
+ y_i = 3*aimag(eps)/(real(eps) + 2)**2 ! [1](A15)
+
+ ! calculate single-particle albedo (eq.A16)
+ w = (1 - f0)**4*kr**3*y_r**2/ &
+ ((1 - f0)**4*kr**3*y_r**2 + 1.5*(1 + 2*f0)**2*y_i) ! [1](A16)
+
+ ! calculate asymmetry parameter (p.374)
+ g = 0.23*kr**2 ! [1]p.374
+
+ ! calculate similarity parameter (eq.3b)
+ a = sqrt((1 - w)/(1 - w*g)) ! [1](3b)
+
+ ! calculate desert soil emissivity (eq.A13)
+ em = (1 - r_r)*(2*a/((1 + a) - (1 - a)*r_r)) ! [1](13)
+
+ ! calculate brightness temperature of desert
+ tb_desert = t_soil*em
+
+ END SUBROUTINE desert
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE veg(patchclass, lai, htop, snowdp, tleaf, tb_veg, gamma_p)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the brightness temperature on the top of vegetation
+!
+! REFERENCES:
+! [1] Wigneron et al., 2007, "L-band Microwave Emission of the Biosphere (L-MEB) Model:
+! Description and calibration against experimental
+! data sets over crop fields" Remote Sensing of Environment. Vol. 107, pp. 639-655k
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ integer, intent(in) :: patchclass ! land cover class
+ real(r8), intent(in) :: lai ! leaf area index
+ real(r8), intent(in) :: tleaf ! leaf temperature (K)
+ real(r8), intent(out) :: tb_veg(2) ! brightness temperature of vegetation for H- and V- polarization
+ real(r8), intent(out) :: gamma_p(2) ! vegetation opacity for H- and V- polarization
+ real(r8), intent(in) :: htop, snowdp
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: tau_nadir ! vegetation opacity at nadir
+ real(r8) :: tau_veg(2) ! vegetation opacity for H- and V- polarization
+ integer :: i
+
+!-----------------------------------------------------------------------
+
+ ! caculate vegetation opacity (optical depth) at nadir b*VWC
+ IF (htop < snowdp) THEN
+ tau_nadir = b1(patchclass)*lai + b2(patchclass) ! low veg ! [1](22)
+ ELSE
+ tau_nadir = b3(patchclass) ! high veg
+ END IF
+
+ ! calculate vegetation optical depth at H- and V- polarizations
+ tau_veg(1) = tau_nadir*(cos(theta)**2 + tth(patchclass)*sin(theta)**2) ! [1](23)
+ tau_veg(2) = tau_nadir*(cos(theta)**2 + ttv(patchclass)*sin(theta)**2) ! [1](24)
+
+ ! calculate brightness temperature of vegetation
+ DO i = 1, 2
+ gamma_p(i) = exp(-tau_veg(i)/cos(theta)) ! [1](15)
+ tb_veg(i) = (1.-w_CMEM(patchclass))*(1.-gamma_p(i))*tleaf
+ END DO
+
+ END SUBROUTINE veg
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE snow(t_snow, t, snowdp, rho_snow, liq_snow, r_sn, r_snow, tb_tos)
+
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+! Calculate the brightness temperature of snow-covered ground
+!
+! REFERENCES:
+! [1] Christian Mätzler (1987) Applications of the interaction of
+! microwaves with the natural snow cover, Remote Sensing Reviews, 2:2, 259-387, DOI:
+! 10.1080/02757258709532086
+!
+! [2] Anderson, E. A., 1976: A point energy and mass balance model of a snow cover.
+! NOAA Tech. Rep. NWS 19, 150 pp. U.S. Dept. of Commer., Washington, D.C.(eq.5.1)
+!
+! [3] Hallikainen, M. T., F. Ulaby, and T. Deventer. 1987. Extinction behavior of dry snow in the
+! 18- to 90-GHz range. IEEE Trans. Geosci. Remote Sens., GE-25, 737–745.
+!
+! [4] Microwave remote sensing : active and passive
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+!------------------------ Dummy Argument ------------------------------
+ real(r8), intent(in) :: t_snow ! average snow temperature (K)
+ real(r8), intent(in) :: t ! temperature at bottom of snow (K), i.e., soil or leaf
+ real(r8), intent(in) :: snowdp ! snow depth (m)
+ real(r8), intent(in) :: rho_snow ! snow density (g/cm3)
+ real(r8), intent(in) :: liq_snow ! snow liquid water content (cm3/cm3)
+ real(r8), intent(in) :: r_sn(2) ! reflectivity between the snow and ground at (1, H-POL. 2, V.)
+ real(r8), intent(out) :: r_snow(2) ! reflectivity between the snow and air for H- and V- polarization
+ real(r8), intent(out) :: tb_tos(2) ! brightness temperature of snow-cover ground for H- and V- polarization
+
+!----------------------- Local Variables -------------------------------
+ real(r8) :: sal_snow = 0.0 ! snow salinity (pmm)
+ real(r8) :: eps_i_r ! real part of dielectric constant of ice
+ real(r8) :: eps_i_i ! imaginary part of dielectric constant of ice
+ real(r8) :: eps_i_is ! imaginary part of dielectric constant of impure ice -5(C)
+ real(r8) :: eps_i_ip ! imaginary part of dielectric constant of pure ice -5(C)
+ real(r8) :: eps_ds_r ! real part of dielectric constant of dry snow
+ real(r8) :: eps_ds_i ! imaginary part of dielectric constant of dry snow
+ real(r8) :: eps_ws_i ! imaginary part of dielectric constant of wet snow
+ real(r8) :: eps_ws_r ! real part of dielectric constant of wet snow
+ real(r8) :: eps_w_s = 88. ! dielectric constant of static water
+ real(r8) :: eps_a_inf, eps_b_inf, eps_c_inf ! infinite frequency dielectric constant of three parts
+ real(r8) :: eps_a_s, eps_b_s, eps_c_s ! static dielectric constant of three parts
+ complex(r8) :: eps_i ! dielectric constant of ice
+ complex(r8) :: eps_a
+ complex(r8) :: eps_b
+ complex(r8) :: eps_c ! dielectric constant of three parts
+ complex(r8) :: eps ! dielectric constant of wet snow
+ real(r8) :: rho_ds ! density of dry snow (g/cm3)
+ real(r8) :: rho_i = 0.916 ! density of ice (g/cm3)
+ real(r8) :: aa = 0.005
+ real(r8) :: bb = 0.4975
+ real(r8) :: cc = 0.4975 ! fitting parameters
+ real(r8) :: fa, fb, fc ! relaxation frequency of wet snow
+ real(r8) :: d ! snow grain size (mm)
+ real(r8) :: alpha, beta, pp, qq ! parameter used to calculate propogation angle in snow
+ real(r8) :: theta_s ! propogation angle in snow
+ complex(r8) :: z_s ! wave impedance in snow
+ real(r8) :: r_sa ! reflectivity between the snow and air for H- and V- polarization
+ real(r8) :: tb_2 ! the net apparent temperature contributions due to emission by layers 2 (snow)
+ real(r8) :: tb_3 ! the net apparent temperature contributions due to emission by layers 3 (soil)
+ real(r8) :: l2_apu ! extinction coefficient of snow (Beer's Law)
+ real(r8) :: q = 0.96 ! parameter
+ real(r8) :: ka_ws ! absorption coefficient of wet snow
+ real(r8) :: ka_ds ! absorption coefficient of dry snow
+ real(r8) :: ke ! extinction coefficient of wet snow
+ real(r8) :: ke_ds ! extinction coefficient of dry snow
+ real(r8) :: ks ! scattering coefficient of snow
+ real(r8) :: b_ds, b_ws
+ real(r8) :: wk_h ! [m], equal to cmem cmem_snow_set_var.F90:476
+ integer :: i
+
+!-----------------------------------------------------------------------
+ IF (snowdp > 0.01) THEN ! > 1cm
+ ! calculate dielectric constant of ice
+ CALL diel_ice(t_snow - tfrz, eps_i)
+ eps_i_r = real(eps_i)
+ eps_i_i = aimag(eps_i)
+
+ ! consider the effect of salinity on the dielectric constant of ice
+ eps_i_is = 0.0026/fghz + 0.00023*(fghz**0.87) ! impure ice -5(C)
+ eps_i_ip = 6.e-4/fghz + 6.5e-5*(fghz**1.07) ! pure ice -5(C)
+ eps_i_i = eps_i_i + (eps_i_is - eps_i_ip)*sal_snow/13.0d0 ! corrected imaginary part of diel cons of ice
+
+ ! calculate dielectric constant of dry snow (mixed by air and ice) (Polder–van Santen mixing model)
+ rho_ds = (rho_snow - liq_snow)/(1.0 - liq_snow) ! caculate density of dry snow,
+ eps_ds_r = 1.0 + 1.58*rho_ds/(1.0 - 0.365*rho_ds)
+ eps_ds_i = 3.0*(rho_ds/rho_i)*eps_i_i*(eps_ds_r**2)*(2*eps_ds_r + 1)/ &
+ ((eps_i_r + 2*eps_ds_r)*(eps_i_r + 2*eps_ds_r**2)) ! negative imaginary part of diel cons of dry snow
+
+ ! calculate dielectric constant of wet snow (Matzler 1987)
+ IF (liq_snow > 0.) THEN ! wet snow
+ ! caculate relaxation frequency of three parts (eq.2.26)
+ fa = f0w*(1 + (aa*(eps_w_s - eps_w_inf)/(eps_ds_r + (aa*(eps_w_inf - eps_ds_r)))))
+ fb = f0w*(1 + (bb*(eps_w_s - eps_w_inf)/(eps_ds_r + (bb*(eps_w_inf - eps_ds_r)))))
+ fc = f0w*(1 + (cc*(eps_w_s - eps_w_inf)/(eps_ds_r + (cc*(eps_w_inf - eps_ds_r)))))
+
+ ! caculate infinite frequency dielectric constant of three parts
+ eps_a_inf = (liq_snow*(eps_w_inf - eps_ds_r)/3.)/ &
+ (1.+aa*((eps_w_inf/eps_ds_r) - 1.))
+ eps_b_inf = (liq_snow*(eps_w_inf - eps_ds_r)/3.)/ &
+ (1.+bb*((eps_w_inf/eps_ds_r) - 1.))
+ eps_c_inf = (liq_snow*(eps_w_inf - eps_ds_r)/3.)/ &
+ (1.+cc*((eps_w_inf/eps_ds_r) - 1.))
+
+ ! caculate static dielectric constant of three parts
+ eps_a_s = (liq_snow/3.)*(eps_w_s - eps_ds_r)/ &
+ (1.+aa*((eps_w_s/eps_ds_r) - 1.))
+ eps_b_s = (liq_snow/3.)*(eps_w_s - eps_ds_r)/ &
+ (1.+bb*((eps_w_s/eps_ds_r) - 1.))
+ eps_c_s = (liq_snow/3.)*(eps_w_s - eps_ds_r)/ &
+ (1.+cc*((eps_w_s/eps_ds_r) - 1.))
+
+ ! Debye equations
+ eps_a = eps_a_inf + (eps_a_s - eps_a_inf)/(1 + jj*fghz/fa)
+ eps_b = eps_b_inf + (eps_b_s - eps_b_inf)/(1 + jj*fghz/fb)
+ eps_c = eps_c_inf + (eps_c_s - eps_c_inf)/(1 + jj*fghz/fc)
+
+ ! calculate dielectric constant of wet snow
+ eps = eps_a + eps_b + eps_c + (eps_ds_r - jj*eps_ds_i)
+ eps_ws_r = real(eps)
+ eps_ws_i = -1.*aimag(eps)
+ ELSE
+ eps_ws_r = eps_ds_r
+ eps_ws_i = eps_ds_i
+ END IF
+
+ ! caculate propogation angle in snow (change medium from air to snow)
+ alpha = k*abs(aimag(sqrt(eps_ws_r - jj*eps_ws_i)))
+ beta = k*real(sqrt(eps_ws_r - jj*eps_ws_i))
+ pp = 2.*alpha*beta
+ qq = beta**2 - alpha**2 - (k*k)*(sin(theta)**2)
+ theta_s = atan(k*sin(theta)/((1./sqrt(2.)) &
+ *sqrt(sqrt(pp**2.+qq**2.) + qq)))
+
+ ! caclulate wave impedance in snow
+ z_s = z0/sqrt(eps_ws_r - jj*eps_ws_i)
+
+ ! calculate brightness temperature above snow for H- V- polarization
+ DO i = 1, 2
+ ! Fresnel reflection coefficient between snow and air
+ IF (i == 1) THEN
+ r_sa = abs((z_s*cos(theta) - z0*cos(theta_s))/ &
+ (z_s*cos(theta) + z0*cos(theta_s)))**2
+ ELSE
+ r_sa = abs((z0*cos(theta) - z_s*cos(theta_s))/ &
+ (z0*cos(theta) + z_s*cos(theta_s)))**2
+ END IF
+
+ ! calculate snow grain size (mm) (Anderson 1976, eq.5.1) TODO
+ d = min(1000*(1.6e-4 + 1.1e-13*((rho_snow*1000.0)**4)), 3.0)
+
+ ! extinction coefficient of dry snow
+ !//TODO: the paper is not focus on L-band, thus the formula is not suitable
+ ke_ds = 0.0018*(fghz**2.8)*(d**2)/4.3429 ! [3](14)
+
+ ! absorption coefficient of dry snow
+ b_ds = (eps_ds_i/eps_ds_r)**2
+ ka_ds = 2.*omega*sqrt(mu0*eps_0*eps_ds_r)* &
+ sqrt(b_ds/(2.*(sqrt(1.+b_ds) + 1.)))
+
+ IF (ke_ds < ka_ds) ke_ds = ka_ds
+
+ ! absorption coefficient of wet snow
+ b_ws = (eps_ws_i/eps_ws_r)**2
+ ka_ws = 2.*omega*sqrt(mu0*eps_0*eps_ws_r)* &
+ sqrt(b_ws/(2.*(sqrt(1.+b_ws) + 1)))
+
+ ! total extinction (assuming scattering is the same for dry and wet snow)
+ ke = (ke_ds - ka_ds) + ka_ws
+
+ ! scattering coefficient of dry and wet snow
+ ks = ke_ds - ka_ds
+
+ wk_h = snowdp/rho_snow
+ IF (((ke - q*ks)*(1./cos(theta_s))*wk_h) > (log(HUGE(1.)) - 1.)) THEN
+ l2_apu = sqrt(HUGE(1.))
+ ELSE
+ l2_apu = min(sqrt(HUGE(1.)), exp((ke - q*ks)*(1./cos(theta_s))*wk_h))
+ END IF
+
+ ! brightness temperature through snow-air layer ([4] pp.243, eq.4.161)
+ tb_2 = (1.+r_sn(i)/l2_apu)*(1.-r_sa)*t_snow* &
+ (ka_ws/(ke - q*ks))*(1.-1./l2_apu)/ &
+ (1.-r_sn(i)*r_sa/l2_apu**2.)
+
+ ! brightness temperature through soil-snow layer ([4] pp.243, eq.4.162)
+ tb_3 = ((1.-r_sn(i))*(1.-r_sa)*t)/ &
+ (l2_apu*(1.-r_sn(i)*r_sa/l2_apu**2.))
+
+ ! brightness temperature of snow-cover ground
+ tb_tos(i) = tb_2 + tb_3
+
+ ! emission by layers 2 (snow) and 3 (soil)
+ ! reflectivity by layers 2 (snow) and 3 (soil)
+ r_snow(i) = 1 - (tb_2/t_snow + tb_3/t)
+ END DO
+ END IF
+
+ END SUBROUTINE snow
+!-----------------------------------------------------------------------
+END MODULE MOD_DA_RTM
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_SM.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_SM.F90
new file mode 100644
index 0000000000..8854feb488
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_SM.F90
@@ -0,0 +1,1787 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_SM
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! Data assimilation of surface soil moisture and temperature
+!
+! AUTHOR:
+! Lu Li, 12/2024: Initial version, based on SMAP L1C TB data
+! Zhilong Fan, Lu Li, 03/2024: Debug and clean codes
+! Lu Li, 07/2025: reframe codes
+! Lu Li, 10/2025: support SMAP/FY3D/SYNOP data
+!-----------------------------------------------------------------------------
+ USE MOD_DataType
+ USE MOD_SpatialMapping
+ USE MOD_DA_RTM
+ USE MOD_DA_EnKF
+ USE MOD_DA_Vars_TimeVariables
+ USE MOD_Vars_Global, only: pi, nl_soil, maxsnl
+ USE MOD_LandPatch
+ USE MOD_Block
+ USE MOD_Namelist
+ USE MOD_DA_Vars_TimeVariables
+ USE MOD_Pixelset
+ USE MOD_Pixel
+ USE MOD_Mesh
+ IMPLICIT NONE
+ SAVE
+
+! public functions
+ PUBLIC :: init_DA_SM
+ PUBLIC :: run_DA_SM
+ PUBLIC :: end_DA_SM
+
+ PRIVATE
+
+! local variables
+!#############################################################################
+! Universal variables
+!#############################################################################
+ ! time (UTC) at current step
+ integer :: month, mday, hour ! month, day, hour of current step
+ character(len=256) :: yearstr, monthstr, daystr, hourstr ! string of year, month, day, hour
+ integer :: idate_b, idate_e ! begin & end seconds since begin of current day (UTC)
+
+ integer :: num_obs_p
+ ! mask water
+ logical, allocatable :: filter(:) ! to mask the water
+
+ ! logical
+ logical, allocatable :: has_DA ! whether has data assimilation
+
+ ! setting of SMAP satellite
+ real(r8), parameter :: smap_theta = 40.0*pi/180 ! incidence angle (rad)
+ real(r8), parameter :: smap_fghz = 1.4 ! frequency (GHz), L-band
+
+ ! setting of FY satellite
+ real(r8), parameter :: fy3d_theta = 40.0*pi/180 ! incidence angle (rad)
+ real(r8), parameter :: fy3d_fghz = 1.4 ! frequency (GHz), L-band
+
+ ! parameters of LETKF
+ real(r8), allocatable :: obs_err(:) ! observation error
+ real(r8), parameter :: dres = 0.4 ! search localization radius (deg)
+ real(r8), parameter :: loc_r = 40.0 ! localization radius (km)
+ real(r8), parameter :: infl = 1.2 ! inflation factor
+
+ ! data assimilation outputs
+ real(r8), allocatable :: trans(:,:) ! transformation matrix on each patch
+ real(r8), allocatable :: wliq_soi_ens(:,:) ! soil liquid water content
+ real(r8), allocatable :: wliq_soi_ens_da(:,:) ! soil liquid water content after data assimilation
+ real(r8), allocatable :: t_soi_ens(:,:) ! soil temperature
+ real(r8), allocatable :: t_soi_ens_da(:,:) ! soil temperature after data assimilation
+ real(r8) :: eff_porsl ! effective porosity of each soil layer
+ integer :: end_idx(3)
+
+ real(r8), allocatable :: pred_obs_p_ens(:,:) ! predicted observations on each patch
+ real(r8), allocatable :: obs_p(:) ! observations on each patch
+ real(r8), allocatable :: obs_err_p(:) ! observation errors on each patch
+
+ real(r8), allocatable :: smap_err(:) ! observation errors for SMAP TB
+ real(r8), allocatable :: fy3d_err(:) ! observation errors for FY3D TB
+ real(r8), allocatable :: synop_tref_err(:) ! observation errors for SYNOP 2m temperature
+ real(r8), allocatable :: synop_qref_err(:) ! observation errors for SYNOP 2m humidity
+
+!#############################################################################
+! For SMAP L1C brightness temperature
+!#############################################################################
+ ! file path
+ character(len=256) :: file_smap ! SMAP observation file path
+ character(len=256) :: file_grid_smap ! SMAP world grid file path
+
+ ! grid
+ type(grid_type) :: grid_smap ! SMAP world grid
+ type(spatial_mapping_type) :: mg2p_smap ! mapping between SMAP world grid to patch
+
+ ! time variables used to determine whether has obs
+ real(r8), allocatable :: smap_time(:) ! seconds of all obs since begin of current day (UTC)
+ real(r8), allocatable :: dt_b_smap(:) ! delta time between SMAP and begin seconds of current day
+ real(r8), allocatable :: dt_e_smap(:) ! delta time between SMAP and end seconds of current day
+
+ ! logical variables
+ logical :: has_smap_file ! whether has file of SMAP at target hour
+ logical :: has_smap_obs ! whether has SMAP obs at current step
+
+ ! observations (dimensions changes with time)
+ integer :: num_smap_obs ! number of all obs in current file
+ integer :: num_smap_obs_domain ! number of all obs in simulation domain at current file
+ real(r8), allocatable :: smap_lat(:) ! latitude of all obs
+ real(r8), allocatable :: smap_lon(:) ! longitude of all obs
+ real(r8), allocatable :: smap_tb_h(:) ! H- polarized brightness temperature of all obs ([K])
+ real(r8), allocatable :: smap_tb_v(:) ! V- polarized brightness temperature of all obs ([K])
+ integer, allocatable :: smap_ii(:) ! i-th lat grid in world map of all obs
+ integer, allocatable :: smap_jj(:) ! j-th lon grid in world map of all obs
+
+ ! history mean value of smap and colm
+ real(r8), allocatable :: pred_smap_tb_h_mean(:) ! history mean value of predicted H- polarized temp
+ real(r8), allocatable :: pred_smap_tb_v_mean(:) ! history mean value of predicted V- polarized temp
+ real(r8), allocatable :: smap_tb_h_mean(:) ! history mean value of SMAP H- polarized temp
+ real(r8), allocatable :: smap_tb_v_mean(:) ! history mean value of SMAP V- polarized temp
+
+ ! ensemble predicted observations (at patch)
+ real(r8), allocatable :: pred_smap_tb_h_pset_ens(:, :) ! predicted H- polarized temp on patch
+ real(r8), allocatable :: pred_smap_tb_v_pset_ens(:, :) ! predicted V- polarized temp on patch
+ real(r8), allocatable :: area_pset(:) ! area of each patch across world grid
+
+ ! ensemble predicted observations (at world grid)
+ type(block_data_real8_3d) :: pred_smap_tb_h_wgrid_ens ! predicted H- polarized temp on world grid
+ type(block_data_real8_3d) :: pred_smap_tb_v_wgrid_ens ! predicted V- polarized temp on world grid
+ type(block_data_real8_2d) :: area_smap_wgrid ! area of each patch across world grid
+
+ ! ensemble predicted observations (at obs grid)
+ real(r8), allocatable :: pred_smap_tb_h_ogrid_ens(:, :) ! predicted H- polarized temp on obs grid
+ real(r8), allocatable :: pred_smap_tb_v_ogrid_ens(:, :) ! predicted V- polarized temp on obs grid
+ real(r8) :: area_smap_wgrid_obs ! area of each patch across world grid for each obs
+
+ ! observations around patch (dimensions changes with patch)
+ integer :: num_smap_p
+ logical, allocatable :: index_smap_p(:) ! index of obs around each patch
+ real(r8), allocatable :: smap_lat_p(:) ! latitude of obs around each patch
+ real(r8), allocatable :: smap_lon_p(:) ! longitude of obs around each patch
+ real(r8), allocatable :: smap_tb_h_p(:) ! H- polarized brightness temperature of obs around each patch ([K])
+ real(r8), allocatable :: smap_tb_v_p(:) ! V- polarized brightness temperature of obs around each patch ([K])
+ real(r8), allocatable :: pred_smap_tb_h_p_ens(:, :) ! predicted H- polarized temp around patch
+ real(r8), allocatable :: pred_smap_tb_v_p_ens(:, :) ! predicted V- polarized temp around patch
+
+ ! history mean value of brightness temperature around patch
+ real(r8), allocatable :: pred_smap_tb_h_mean_p(:) ! history mean value of predicted H- polarized temp around patch
+ real(r8), allocatable :: pred_smap_tb_v_mean_p(:) ! history mean value of predicted V- polarized temp around patch
+ real(r8), allocatable :: smap_tb_h_mean_p(:) ! history mean value of SMAP H- polarized temp around patch
+ real(r8), allocatable :: smap_tb_v_mean_p(:) ! history mean value of SMAP V- polarized temp around patch
+
+ ! parameters for distance calculation
+ real(r8), allocatable :: d_smap_p(:) ! distance between obs and patch center
+ real(r8), parameter :: static_smap_err = 0.1 ! static observation error
+
+!#############################################################################
+! For FY3D L1 brightness temperature
+!#############################################################################
+ ! file path
+ character(len=256) :: file_fy3d ! FY3D observation file path
+ character(len=256) :: file_grid_fy3d ! FY3D world grid file path
+
+ ! grid
+ type(grid_type) :: grid_fy3d ! FY3D world grid
+ type(spatial_mapping_type) :: mg2p_fy3d ! mapping between FY3D world grid to patch
+
+ ! time variables used to determine whether has obs
+ real(r8), allocatable :: fy3d_time(:) ! seconds of all obs since begin of current day (UTC)
+ real(r8), allocatable :: dt_b_fy3d(:) ! delta time between FY3D and begin seconds of current day
+ real(r8), allocatable :: dt_e_fy3d(:) ! delta time between FY3D and end seconds of current day
+
+ ! logical variables
+ logical :: has_fy3d_file ! whether has file of FY3D at target hour
+ logical :: has_fy3d_obs ! whether has FY3D obs at current step
+
+ ! observations (dimensions changes with time)
+ integer :: num_fy3d_obs ! number of all obs in current file
+ integer :: num_fy3d_obs_domain ! number of all obs in simulation domain at current file
+ real(r8), allocatable :: fy3d_lat(:) ! latitude of all obs
+ real(r8), allocatable :: fy3d_lon(:) ! longitude of all obs
+ real(r8), allocatable :: fy3d_tb_h(:) ! H- polarized brightness temperature of all obs ([K])
+ real(r8), allocatable :: fy3d_tb_v(:) ! V- polarized brightness temperature of all obs ([K])
+ integer, allocatable :: fy3d_ii(:) ! i-th lat grid in world map of all obs
+ integer, allocatable :: fy3d_jj(:) ! j-th lon grid in world map of all obs
+
+ ! history mean value of fy3d and colm
+ real(r8), allocatable :: pred_fy3d_tb_h_mean(:) ! history mean value of predicted H- polarized temp
+ real(r8), allocatable :: pred_fy3d_tb_v_mean(:) ! history mean value of predicted V- polarized temp
+ real(r8), allocatable :: fy3d_tb_h_mean(:) ! history mean value of FY3D H- polarized temp
+ real(r8), allocatable :: fy3d_tb_v_mean(:) ! history mean value of FY3D V- polarized temp
+
+ ! ensemble predicted observations (at patch)
+ real(r8), allocatable :: pred_fy3d_tb_h_pset_ens(:, :) ! predicted H- polarized temp on patch
+ real(r8), allocatable :: pred_fy3d_tb_v_pset_ens(:, :) ! predicted V- polarized temp on patch
+
+ ! ensemble predicted observations (at world grid)
+ type(block_data_real8_3d) :: pred_fy3d_tb_h_wgrid_ens ! predicted H- polarized temp on world grid
+ type(block_data_real8_3d) :: pred_fy3d_tb_v_wgrid_ens ! predicted V- polarized temp on world grid
+ type(block_data_real8_2d) :: area_fy3d_wgrid ! area of each patch across world grid
+
+ ! ensemble predicted observations (at obs grid)
+ real(r8), allocatable :: pred_fy3d_tb_h_ogrid_ens(:, :) ! predicted H- polarized temp on obs grid
+ real(r8), allocatable :: pred_fy3d_tb_v_ogrid_ens(:, :) ! predicted V- polarized temp on obs grid
+ real(r8) :: area_fy3d_wgrid_obs ! area of each patch across world grid for each obs
+
+ ! observations around patch (dimensions changes with patch)
+ integer :: num_fy3d_p
+ logical, allocatable :: index_fy3d_p(:) ! index of obs around each patch
+ real(r8), allocatable :: fy3d_lat_p(:) ! latitude of obs around each patch
+ real(r8), allocatable :: fy3d_lon_p(:) ! longitude of obs around each patch
+ real(r8), allocatable :: fy3d_tb_h_p(:) ! H- polarized brightness temperature of obs around each patch ([K])
+ real(r8), allocatable :: fy3d_tb_v_p(:) ! V- polarized brightness temperature of obs around each patch ([K])
+ real(r8), allocatable :: pred_fy3d_tb_h_p_ens(:, :) ! predicted H- polarized temp around patch
+ real(r8), allocatable :: pred_fy3d_tb_v_p_ens(:, :) ! predicted V- polarized temp around patch
+
+ ! history mean value of brightness temperature around patch
+ real(r8), allocatable :: pred_fy3d_tb_h_mean_p(:) ! history mean value of predicted H- polarized temp around patch
+ real(r8), allocatable :: pred_fy3d_tb_v_mean_p(:) ! history mean value of predicted V- polarized temp around patch
+ real(r8), allocatable :: fy3d_tb_h_mean_p(:) ! history mean value of FY3D H- polarized temp around patch
+ real(r8), allocatable :: fy3d_tb_v_mean_p(:) ! history mean value of FY3D V- polarized temp around patch
+
+ ! parameters for distance calculation
+ real(r8), allocatable :: d_fy3d_p(:) ! distance between obs and patch center
+ real(r8), parameter :: static_fy3d_err = 10.0 ! static observation error
+
+!#############################################################################
+! For SYNOP 2m temperature and humidity observations
+!#############################################################################
+ ! derived types of pixel index in each rank
+ ! firstly sorted by pixel latitude index (nlat) and record
+ ! corresponding longitude index and patch id for each pixel
+ type :: idx_type
+ integer, allocatable :: ilon (:)
+ integer, allocatable :: ipatch (:)
+ END type idx_type
+ type(idx_type), allocatable :: idx (:) ! derived types of pixel index at each rank
+ integer, allocatable :: counter (:) ! counter of pixel longitude index of each latitude index at each rank
+
+ ! file path
+ character(len=256) :: file_synop ! SYNOP file path
+
+ ! info of all SYNOP sites
+ character(len=256) :: file_site ! file of location of all SYNOP sites
+ real(r8), allocatable :: synop_lat_all(:)
+ real(r8), allocatable :: synop_lon_all(:) ! latitude and longitude of all SYNOP sites
+ integer :: nsite ! number of all SYNOP sites
+ integer, allocatable :: iloc_synop (:,:) ! global lat/lon index of pixel cover each site in all SYNOP sites
+ integer :: counter_rank_nsite ! number of all SYNOP sites located at each rank
+ integer, allocatable :: ip_rank (:,:) ! patch id of all SYNOP sites located at each rank
+ integer, allocatable :: idx_lat(:), idx_lon(:), pos(:) ! temporary array save global lat/lon index of each site
+ integer, allocatable :: synop_lut (:,:) ! look-up-table of all SYNOP sites
+
+ ! time variables used to determine whether has obs
+ real(r8), allocatable :: synop_time(:) ! seconds of all obs since begin of current day (UTC)
+ real(r8), allocatable :: dt_b_synop(:) ! delta time between SYNOP and begin seconds of current day
+ real(r8), allocatable :: dt_e_synop(:) ! delta time between SYNOP and end seconds of current day
+
+ ! logical variables
+ logical :: has_synop_file ! whether has file of SYNOP at target day
+ logical :: has_synop_obs ! whether has SYNOP obs at current step
+
+ ! info of SYNOP sites at each step
+ integer, allocatable :: synop_idx (:,:) ! index of SYNOP sites (rank/patch id) at each step
+ integer, allocatable :: site_id_rank (:) ! site id of SYNOP sites at each step at each rank
+ real(r8), allocatable :: tref_ens_rank (:,:) ! predicted 2m temperature of SYNOP sites at each step at each rank
+ real(r8), allocatable :: qref_ens_rank (:,:) ! predicted 2m humidity of SYNOP sites at each step at each rank
+ real(r8), allocatable :: qref_ens_o (:,:) ! predicted 2m temperature of SYNOP sites at each step
+ real(r8), allocatable :: tref_ens_o (:,:) ! predicted 2m humidity of SYNOP sites at each step
+
+ ! observations (dimensions changes with time)
+ integer :: num_synop_obs ! number of all obs in current file
+ integer :: num_synop_obs_domain ! number of all obs in simulation domain at current file
+ real(r8), allocatable :: synop_lat(:) ! latitude of all obs
+ real(r8), allocatable :: synop_lon(:) ! longitude of all obs
+ integer, allocatable :: synop_id(:) ! global id of all obs
+ real(r8), allocatable :: synop_tref(:) ! 2m temperature of all obs ([K])
+ integer, allocatable :: synop_qref(:) ! 2m humidity of all obs ([K])
+
+ ! observations around patch (dimensions changes with patch)
+ integer :: num_synop_p
+ logical, allocatable :: index_synop_p(:) ! index of obs around each patch
+ real(r8), allocatable :: synop_lat_p(:) ! latitude of obs around each patch
+ real(r8), allocatable :: synop_lon_p(:) ! longitude of obs around each patch
+ real(r8), allocatable :: synop_qref_p(:) ! 2m temperature of obs around each patch ([K])
+ real(r8), allocatable :: synop_tref_p(:) ! 2m humidity of obs around each patch ([K])
+ real(r8), allocatable :: synop_p(:) ! concatenate 2m temperature and humidity of obs around each patch
+ real(r8), allocatable :: qref_ens_p(:,:) ! predicted 2m temperature around patch
+ real(r8), allocatable :: tref_ens_p(:,:) ! predicted 2m humidity around patch
+ real(r8), allocatable :: pred_synop_ens_p(:,:) ! predicted 2m temperature and humidity around patch
+
+ ! parameters for distance calculation
+ real(r8), allocatable :: d_synop_p(:) ! distance between obs and patch center
+ real(r8), parameter :: static_synop_tref_err = 1.0 ! static observation error (2m temperature)
+ real(r8), parameter :: static_synop_qref_err = 0.04 ! static observation error (2m humidity)
+
+!-----------------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE init_DA_SM()
+
+!-----------------------------------------------------------------------------
+ USE MOD_Spmd_Task
+ USE MOD_Namelist, only: DEF_DA_obsdir
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_LandPatch
+ USE MOD_Pixelset
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer :: np, ie, ipxstt, ipxend, ipxl, i, ilat, isite, ilon, iwork, mesg(2), isrc, ndata, numpxl_lat, numpxl_lon, numpxl
+ integer, allocatable :: temp (:,:) ! temporary array for receiving data from ranks
+
+!-----------------------------------------------------------------------------
+
+#ifndef SinglePoint
+ IF (DEF_DA_SM_SMAP) THEN
+ ! grid file path of EASE v2.0, 36km world grid
+ file_grid_smap = trim(DEF_DA_obsdir)//'/grid/'//'/SMAP_L1C_36km.nc'
+ CALL grid_smap%define_from_file(file_grid_smap, 'latitude', 'longitude')
+
+ ! map SMAP grid to patch
+ CALL mg2p_smap%build_arealweighted(grid_smap, landpatch)
+ ENDIF
+
+ IF (DEF_DA_SM_FY) THEN
+ ! grid file path of FY3D, 0.25 degree world grid
+ file_grid_fy3d = trim(DEF_DA_obsdir)//'/grid/'//'/FY3D_L1_0p25.nc'
+
+ CALL grid_fy3d%define_from_file(file_grid_fy3d, 'latitude', 'longitude')
+
+ ! map FY3D grid to patch
+ CALL mg2p_fy3d%build_arealweighted(grid_fy3d, landpatch)
+ ENDIF
+
+ IF (DEF_DA_SM_SYNOP) THEN
+!#############################################################################
+! Makeup derived types of pixel index for fast access at each rank
+!#############################################################################
+ IF (p_is_compute) THEN
+ allocate (counter (pixel%nlat))
+ counter(:) = 0
+
+ ! count the number of pixel lon index for each pixel lat index
+ DO np = 1, numpatch
+ ie = landpatch%ielm(np)
+
+ ipxstt = landpatch%ipxstt(np)
+ ipxend = landpatch%ipxend(np)
+
+ DO ipxl = ipxstt, ipxend
+ counter(mesh(ie)%ilat(ipxl)) = counter(mesh(ie)%ilat(ipxl)) + 1
+ ENDDO
+ ENDDO
+
+ ! allocate derived types of index
+ allocate (idx (pixel%nlat))
+ DO i = 1, pixel%nlat
+ IF (counter(i) > 0) THEN
+ allocate (idx(i)%ilon(counter(i)))
+ allocate (idx(i)%ipatch(counter(i)))
+
+ idx(i)%ilon(:) = 0
+ idx(i)%ipatch(:) = 0
+ ENDIF
+ ENDDO
+
+ ! fill the index
+ counter(:) = 0
+ DO np = 1, numpatch
+ ie = landpatch%ielm(np)
+
+ ipxstt = landpatch%ipxstt(np)
+ ipxend = landpatch%ipxend(np)
+
+ DO ipxl = ipxstt, ipxend
+ ilat = mesh(ie)%ilat(ipxl)
+ counter(mesh(ie)%ilat(ipxl)) = counter(mesh(ie)%ilat(ipxl)) + 1
+ idx(ilat)%ilon(counter(mesh(ie)%ilat(ipxl))) = mesh(ie)%ilon(ipxl)
+ idx(ilat)%ipatch(counter(mesh(ie)%ilat(ipxl))) = np
+ ENDDO
+ ENDDO
+ ENDIF
+
+
+!#############################################################################
+! Read the location of SYNOP sites and find the located pixel of each site
+!#############################################################################
+ ! file of SYNOP sites
+ file_site = trim(DEF_DA_obsdir)//'/grid/'//'/SYNOP.nc'
+
+ ! read latitude and longitude of sites
+ IF (ncio_var_exist(file_site, 'latitude')) THEN
+ CALL ncio_read_bcast_serial(file_site, 'latitude', synop_lat_all)
+ CALL ncio_read_bcast_serial(file_site, 'longitude', synop_lon_all)
+ ENDIF
+ nsite = size(synop_lat_all)
+
+ ! find the located pixel of each site & broadcast ranks
+ allocate (iloc_synop (2, nsite))
+ iloc_synop(:,:) = -1
+ IF (p_is_root) THEN
+ DO i = 1, nsite
+ numpxl_lat = count(pixel%lat_s <= synop_lat_all(i) .and. pixel%lat_n > synop_lat_all(i))
+ numpxl_lon = count(pixel%lon_w <= synop_lon_all(i) .and. pixel%lon_e > synop_lon_all(i))
+
+ IF (numpxl_lat ==1 .and. numpxl_lon ==1) THEN
+ IF (allocated (idx_lat)) deallocate (idx_lat)
+ IF (allocated (idx_lon)) deallocate (idx_lon)
+ allocate (idx_lat(numpxl_lat))
+ allocate (idx_lon(numpxl_lon))
+
+ idx_lat = pack([(isite, isite=1, pixel%nlat)], pixel%lat_s <= synop_lat_all(i) .and. pixel%lat_n > synop_lat_all(i))
+ idx_lon = pack([(isite, isite=1, pixel%nlon)], pixel%lon_w <= synop_lon_all(i) .and. pixel%lon_e > synop_lon_all(i))
+
+ iloc_synop(1,i) = idx_lat(1)
+ iloc_synop(2,i) = idx_lon(1)
+ ELSE
+ iloc_synop(1,i) = -1
+ iloc_synop(2,i) = -1
+ ENDIF
+ ENDDO
+ ENDIF
+ CALL mpi_bcast(iloc_synop, 2*nsite, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+!#############################################################################
+! Assess the patch id of pixel that cover each observation at each rank
+!#############################################################################
+ IF (p_is_compute) THEN
+ ! count the number of site that located in pixels of each rank
+ counter_rank_nsite = 0
+ DO i = 1, nsite
+ IF (iloc_synop(1, i) > 0) THEN
+ IF (counter(iloc_synop(1, i)) > 0) THEN
+ IF (any(idx(iloc_synop(1, i))%ilon == iloc_synop(2, i))) THEN
+ counter_rank_nsite = counter_rank_nsite + 1
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! assess patch/site id of sites located at each rank
+ IF (counter_rank_nsite > 0) THEN
+ allocate (ip_rank (2, counter_rank_nsite))
+ counter_rank_nsite = 0
+ ip_rank(:,:) = -1
+
+ DO i = 1, nsite
+ IF (iloc_synop(1, i) > 0) THEN
+ IF (counter(iloc_synop(1, i)) > 0) THEN
+ IF (any(idx(iloc_synop(1, i))%ilon == iloc_synop(2, i))) THEN
+ numpxl = count(idx(iloc_synop(1, i))%ilon == iloc_synop(2, i))
+ IF (allocated (pos)) deallocate (pos)
+ allocate (pos(numpxl))
+
+ pos = pack([(ilon, ilon=1, counter(iloc_synop(1, i)))], (idx(iloc_synop(1, i))%ilon == iloc_synop(2, i)))
+ counter_rank_nsite = counter_rank_nsite + 1
+ ip_rank(1, counter_rank_nsite) = i
+ ip_rank(2, counter_rank_nsite) = idx(iloc_synop(1, i))%ipatch(pos(1))
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! send the number of site and their patch id to root
+#ifdef USEMPI
+ mesg = (/p_iam_glb, counter_rank_nsite/)
+ CALL mpi_send(mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (counter_rank_nsite > 0) THEN
+ CALL mpi_send(ip_rank, 2*counter_rank_nsite, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#endif
+
+ ! deallocate
+ IF (allocated (counter)) deallocate (counter)
+ DO i = 1, pixel%nlat
+ IF (allocated(idx(i)%ilon)) deallocate (idx(i)%ilon)
+ IF (allocated(idx(i)%ipatch)) deallocate (idx(i)%ipatch)
+ ENDDO
+ IF (allocated (idx)) deallocate (idx)
+ IF (allocated (iloc_synop)) deallocate (iloc_synop)
+ IF (allocated (ip_rank)) deallocate (ip_rank)
+ ENDIF
+
+!#############################################################################
+! Generate look-up-table (contains the rank/patch id of each site) at root
+!#############################################################################
+ IF (p_is_root) THEN
+ allocate (synop_lut (2, nsite))
+ synop_lut(:,:) = -1
+
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv(mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ ndata = mesg(2)
+
+ IF (ndata > 0) THEN
+ allocate (temp(2, ndata))
+ CALL mpi_recv(temp, 2*ndata, MPI_INTEGER, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ DO i = 1, ndata
+ synop_lut(1, temp(1,i)) = isrc
+ synop_lut(2, temp(1,i)) = temp(2,i)
+ ENDDO
+
+ deallocate(temp)
+ ENDIF
+ ENDDO
+#endif
+ ENDIF
+ ENDIF
+#endif
+
+ END SUBROUTINE init_DA_SM
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE run_DA_SM(idate, deltim)
+
+!-----------------------------------------------------------------------------
+ USE MOD_Spmd_task
+ USE MOD_TimeManager
+ USE MOD_NetCDFBlock
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+ USE MOD_Vars_1DFluxes
+ USE MOD_Vars_1DForcing
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_TimeInvariants
+ USE MOD_DA_Vars_TimeVariables
+ USE MOD_RangeCheck
+ USE MOD_UserDefFun
+ USE MOD_DA_EnKF
+ USE MOD_Const_Physical, only: denice, denh2o
+ IMPLICIT NONE
+
+!------------------------ Dummy Arguments ------------------------------------
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+
+!------------------------ Local Variables ------------------------------------
+ real(r8) :: lat_p_n, lat_p_s, lon_p_w, lon_p_e
+ real(r8) :: lat_p, lon_p
+ real(r8) :: es, e
+ integer :: ib, jb, il, jl, ip, iens, iobs, np, i, n, ndata, isrc, j
+ integer :: sdate(3), smesg(2), rmesg(2)
+ integer, allocatable :: iloc(:)
+ integer, allocatable :: itemp(:)
+ real(r8), allocatable :: dtemp(:,:)
+ integer :: iwork, mesg(2)
+
+!-----------------------------------------------------------------------------
+
+!#############################################################################
+! Identify if there are observations at this time step
+!#############################################################################
+ ! Do not perform DA, only calcuate predict BRT for diagnostic
+ IF (DEF_DA_ENS_NUM == 1) THEN
+ has_smap_file = .false.
+ has_fy3d_file = .false.
+ has_synop_file = .false.
+ ELSE
+ ! covert local time to UTC for single point
+ sdate = idate
+ CALL adj2begin(sdate)
+#ifdef SinglePoint
+ IF (.not. DEF_simulation_time%greenwich) THEN
+ CALL localtime2gmt(sdate)
+ ENDIF
+#endif
+ ! calculate year/month/day/hour of current step
+ CALL julian2monthday(sdate(1), sdate(2), month, mday)
+ hour = int(sdate(3)/3600)
+
+ ! whether has file at target day
+ write (yearstr, '(I4.4)') sdate(1)
+ write (monthstr, '(I2.2)') month
+ write (daystr, '(I2.2)') mday
+ write (hourstr, '(I2.2)') hour
+
+ ! check SMAP brightness temperature observations
+ IF (DEF_DA_SM_SMAP) THEN
+ ! file path of SMAP
+ file_smap = trim(DEF_DA_obsdir)//'/SMAP_L1C_D/'//'/SMAP_L1C_TB_'// &
+ trim(yearstr)//'_'//trim(monthstr)//'_'//trim(daystr)//'_'//trim(hourstr)//'.nc'
+ inquire (file=trim(file_smap), exist=has_smap_file)
+
+ ! whether have obs at this time interval
+ has_smap_obs = .false.
+ IF (has_smap_file) THEN
+ CALL ncio_read_bcast_serial(file_smap, 'time', smap_time)
+ num_smap_obs = size(smap_time)
+ idate_b = sdate(3)
+ idate_e = sdate(3) + deltim
+ allocate (dt_b_smap(num_smap_obs))
+ allocate (dt_e_smap(num_smap_obs))
+ dt_b_smap = smap_time - idate_b
+ dt_e_smap = smap_time - idate_e
+ IF (any(dt_b_smap >= 0 .and. dt_e_smap <= 0)) has_smap_obs = .true.
+ deallocate (dt_b_smap)
+ deallocate (dt_e_smap)
+ ELSE
+ has_smap_obs = .false.
+ ENDIF
+
+ ! check if there are obs in simulation domain
+ IF (has_smap_obs) THEN
+ CALL ncio_read_bcast_serial(file_smap, 'lat', smap_lat)
+ CALL ncio_read_bcast_serial(file_smap, 'lon', smap_lon)
+
+ num_smap_obs_domain = count(smap_lat(:) < DEF_domain%edgen .and. smap_lat(:) > DEF_domain%edges .and. &
+ smap_lon(:) > DEF_domain%edgew .and. smap_lon(:) < DEF_domain%edgee)
+ IF (num_smap_obs_domain == 0) has_smap_obs = .false.
+ ENDIF
+ ELSE
+ has_smap_file = .false.
+ has_smap_obs = .false.
+ ENDIF
+
+ ! check FY brightness temperature observations
+ IF (DEF_DA_SM_FY) THEN
+ ! file path of FY3D
+ file_fy3d = trim(DEF_DA_obsdir)//'/FY3D_L1/'//'/FY3D_L1_TB_'// &
+ trim(yearstr)//'_'//trim(monthstr)//'_'//trim(daystr)//'_'//trim(hourstr)//'.nc'
+ inquire (file=trim(file_fy3d), exist=has_fy3d_file)
+
+ ! whether have obs at this time interval
+ has_fy3d_obs = .false.
+ IF (has_fy3d_file) THEN
+ CALL ncio_read_bcast_serial(file_fy3d, 'time', fy3d_time)
+ num_fy3d_obs = size(fy3d_time)
+ idate_b = sdate(3)
+ idate_e = sdate(3) + deltim
+ allocate (dt_b_fy3d(num_fy3d_obs))
+ allocate (dt_e_fy3d(num_fy3d_obs))
+ dt_b_fy3d = fy3d_time - idate_b
+ dt_e_fy3d = fy3d_time - idate_e
+ IF (any(dt_b_fy3d >= 0 .and. dt_e_fy3d <= 0)) has_fy3d_obs = .true.
+ deallocate (dt_b_fy3d)
+ deallocate (dt_e_fy3d)
+ ELSE
+ has_fy3d_obs = .false.
+ ENDIF
+
+ ! check if there are obs in simulation domain
+ IF (has_fy3d_obs) THEN
+ CALL ncio_read_bcast_serial(file_fy3d, 'lat', fy3d_lat)
+ CALL ncio_read_bcast_serial(file_fy3d, 'lon', fy3d_lon)
+
+ num_fy3d_obs_domain = count(fy3d_lat(:) < DEF_domain%edgen .and. fy3d_lat(:) > DEF_domain%edges .and. &
+ fy3d_lon(:) > DEF_domain%edgew .and. fy3d_lon(:) < DEF_domain%edgee)
+ IF (num_fy3d_obs_domain == 0) has_fy3d_obs = .false.
+ ENDIF
+ ELSE
+ has_fy3d_file = .false.
+ has_fy3d_obs = .false.
+ ENDIF
+
+ ! check SYNOP 2m observations
+ IF (DEF_DA_SM_SYNOP) THEN
+ file_synop = trim(DEF_DA_obsdir)//'/SYNOP/'//'/SYNOP_'// &
+ trim(yearstr)//'_'//trim(monthstr)//'_'//trim(daystr)//'_'//trim(hourstr)//'.nc'
+ inquire (file=trim(file_synop), exist=has_synop_file)
+
+ ! whether have obs at this time interval
+ has_synop_obs = .false.
+ IF (has_synop_file) THEN
+ CALL ncio_read_bcast_serial(file_synop, 'time', synop_time)
+ num_synop_obs = size(synop_time)
+ idate_b = sdate(3)
+ idate_e = sdate(3) + deltim
+ allocate (dt_b_synop(num_synop_obs))
+ allocate (dt_e_synop(num_synop_obs))
+ dt_b_synop = synop_time - idate_b
+ dt_e_synop = synop_time - idate_e
+ IF (any(dt_b_synop >= 0 .and. dt_e_synop <= 0)) has_synop_obs = .true.
+ deallocate (dt_b_synop)
+ deallocate (dt_e_synop)
+ ELSE
+ has_synop_obs = .false.
+ ENDIF
+
+ ! check if there are obs in simulation domain
+ IF (has_synop_obs) THEN
+ CALL ncio_read_bcast_serial(file_synop, 'lat', synop_lat)
+ CALL ncio_read_bcast_serial(file_synop, 'lon', synop_lon)
+
+ num_synop_obs_domain = count(synop_lat(:) < DEF_domain%edgen .and. synop_lat(:) > DEF_domain%edges .and. &
+ synop_lon(:) > DEF_domain%edgew .and. synop_lon(:) < DEF_domain%edgee)
+ IF (num_synop_obs_domain == 0) has_synop_obs = .false.
+ ENDIF
+ ELSE
+ has_synop_file = .false.
+ has_synop_obs = .false.
+ ENDIF
+ ENDIF
+
+ ! print info of observations
+ IF (p_is_root) THEN
+ IF (has_smap_obs) THEN
+ print *, '[CoLM-DA] Have SMAP observations:', trim(file_smap)
+ ELSE
+ print *, '[CoLM-DA] No SMAP observations.'
+ ENDIF
+ IF (has_fy3d_obs) THEN
+ print *, '[CoLM-DA] Have FY3D observations:', trim(file_fy3d)
+ ELSE
+ print *, '[CoLM-DA] No FY3D observations.'
+ ENDIF
+ IF (has_synop_obs) THEN
+ print *, '[CoLM-DA] Have SYNOP observations:', trim(file_synop)
+ ELSE
+ print *, '[CoLM-DA] No SYNOP observations.'
+ ENDIF
+ ENDIF
+
+!#############################################################################
+! Allocate memory for variables
+!#############################################################################
+ IF (DEF_DA_SM_SMAP) THEN
+ ! allocate memory for ensemble predicted observations at patch (for DA or no DA)
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ IF (allocated(pred_smap_tb_h_pset_ens)) deallocate (pred_smap_tb_h_pset_ens)
+ IF (allocated(pred_smap_tb_v_pset_ens)) deallocate (pred_smap_tb_v_pset_ens)
+ allocate (pred_smap_tb_h_pset_ens(DEF_DA_ENS_NUM, numpatch))
+ allocate (pred_smap_tb_v_pset_ens(DEF_DA_ENS_NUM, numpatch))
+ ENDIF
+ ENDIF
+
+ ! allocate memory for ensemble predicted observations in vectors (only for DA)
+#ifndef SinglePoint
+ IF (has_smap_obs) THEN
+ IF (allocated(pred_smap_tb_h_ogrid_ens)) deallocate (pred_smap_tb_h_ogrid_ens)
+ IF (allocated(pred_smap_tb_v_ogrid_ens)) deallocate (pred_smap_tb_v_ogrid_ens)
+ allocate (pred_smap_tb_h_ogrid_ens(num_smap_obs, DEF_DA_ENS_NUM))
+ allocate (pred_smap_tb_v_ogrid_ens(num_smap_obs, DEF_DA_ENS_NUM))
+ ENDIF
+#endif
+ ENDIF
+
+ IF (DEF_DA_SM_FY) THEN
+ ! allocate memory for ensemble predicted observations at patch (for DA or no DA)
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ IF (allocated(pred_fy3d_tb_h_pset_ens)) deallocate (pred_fy3d_tb_h_pset_ens)
+ IF (allocated(pred_fy3d_tb_v_pset_ens)) deallocate (pred_fy3d_tb_v_pset_ens)
+ allocate (pred_fy3d_tb_h_pset_ens(DEF_DA_ENS_NUM, numpatch))
+ allocate (pred_fy3d_tb_v_pset_ens(DEF_DA_ENS_NUM, numpatch))
+ ENDIF
+ ENDIF
+
+ ! allocate memory for ensemble predicted observations in vectors (only for DA)
+#ifndef SinglePoint
+ IF (has_fy3d_obs) THEN
+ IF (allocated(pred_fy3d_tb_h_ogrid_ens)) deallocate (pred_fy3d_tb_h_ogrid_ens)
+ IF (allocated(pred_fy3d_tb_v_ogrid_ens)) deallocate (pred_fy3d_tb_v_ogrid_ens)
+ allocate (pred_fy3d_tb_h_ogrid_ens(num_fy3d_obs, DEF_DA_ENS_NUM))
+ allocate (pred_fy3d_tb_v_ogrid_ens(num_fy3d_obs, DEF_DA_ENS_NUM))
+ ENDIF
+#endif
+ ENDIF
+
+ IF (DEF_DA_SM_SYNOP) THEN
+ ! allocate memory
+ IF (has_synop_obs) THEN
+ IF (allocated(synop_idx)) deallocate (synop_idx)
+ IF (allocated(qref_ens_o)) deallocate (qref_ens_o)
+ IF (allocated(tref_ens_o)) deallocate (tref_ens_o)
+ allocate (synop_idx (2, num_synop_obs))
+ allocate (qref_ens_o (num_synop_obs, DEF_DA_ENS_NUM))
+ allocate (tref_ens_o (num_synop_obs, DEF_DA_ENS_NUM))
+ ENDIF
+ ENDIF
+
+!#############################################################################
+! Calculate predicted observations using observation operator
+!#############################################################################
+ ! forward model (for no DA)
+ IF (p_is_compute) THEN
+ ! SMAP forward model
+ DO np = 1, numpatch
+ lat_p = patchlatr(np)*180/pi
+ lon_p = patchlonr(np)*180/pi
+ CALL forward(&
+ patchtype(np), patchclass(np), dz_sno(:,np), &
+ forc_topo(np), htop(np), &
+ tref(np), t_soisno(:,np), tleaf(np), &
+ wliq_soisno(:,np), wice_soisno(:,np), h2osoi(:,np), &
+ snowdp(np), lai(np), sai(np), &
+ wf_clay(:, np), wf_sand(:, np), wf_silt(:, np), BD_all(:, np), porsl(:, np), &
+ smap_theta, smap_fghz, &
+ t_brt_smap(1,np), t_brt_smap(2,np))
+ ENDDO
+
+ ! FY3D forward model
+ DO np = 1, numpatch
+ CALL forward(&
+ patchtype(np), patchclass(np), dz_sno(:,np), &
+ forc_topo(np), htop(np), &
+ tref(np), t_soisno(:,np), tleaf(np), &
+ wliq_soisno(:,np), wice_soisno(:,np), h2osoi(:,np), &
+ snowdp(np), lai(np), sai(np), &
+ wf_clay(:, np), wf_sand(:, np), wf_silt(:, np), BD_all(:, np), porsl(:, np), &
+ fy3d_theta, fy3d_fghz, &
+ t_brt_fy3d(1,np), t_brt_fy3d(2,np))
+ ENDDO
+ ENDIF
+
+ ! forward model for ensemble DA
+ IF (p_is_compute) THEN
+ IF (DEF_DA_SM_SMAP) THEN
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ DO iens = 1, DEF_DA_ENS_NUM
+ DO np = 1, numpatch
+ CALL forward(&
+ patchtype(np), patchclass(np), dz_sno_ens(:, iens, np), &
+ forc_topo(np), htop(np), &
+ tref_ens(iens, np), t_soisno_ens(:,iens,np), tleaf_ens(iens, np), &
+ wliq_soisno_ens(:, iens, np), wice_soisno_ens(:, iens, np), h2osoi_ens(:, iens, np), &
+ snowdp_ens(iens, np), lai_ens(iens, np), sai_ens(iens, np), &
+ wf_clay(:, np), wf_sand(:, np), wf_silt(:, np), BD_all(:, np), porsl(:, np), &
+ smap_theta, smap_fghz, &
+ pred_smap_tb_h_pset_ens(iens, np), pred_smap_tb_v_pset_ens(iens, np))
+ ENDDO
+ ENDDO
+ t_brt_smap_ens(1,:,:) = pred_smap_tb_h_pset_ens
+ t_brt_smap_ens(2,:,:) = pred_smap_tb_v_pset_ens
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM_FY) THEN
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ DO iens = 1, DEF_DA_ENS_NUM
+ DO np = 1, numpatch
+ CALL forward(&
+ patchtype(np), patchclass(np), dz_sno_ens(:, iens, np), &
+ forc_topo(np), htop(np), &
+ tref_ens(iens, np), t_soisno_ens(:,iens,np), tleaf_ens(iens, np), &
+ wliq_soisno_ens(:, iens, np), wice_soisno_ens(:, iens, np), h2osoi_ens(:, iens, np), &
+ snowdp_ens(iens, np), lai_ens(iens, np), sai_ens(iens, np), &
+ wf_clay(:, np), wf_sand(:, np), wf_silt(:, np), BD_all(:, np), porsl(:, np), &
+ fy3d_theta, fy3d_fghz, &
+ pred_fy3d_tb_h_pset_ens(iens, np), pred_fy3d_tb_v_pset_ens(iens, np))
+ ENDDO
+ ENDDO
+ t_brt_fy3d_ens(1,:,:) = pred_fy3d_tb_h_pset_ens
+ t_brt_fy3d_ens(2,:,:) = pred_fy3d_tb_v_pset_ens
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM_SYNOP) THEN
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ ! calculate relative humidity from specific humidity
+ DO ip = 1, numpatch
+ DO iens = 1, DEF_DA_ENS_NUM
+ es = 6.112 * exp((17.67 * (tref_ens(iens, ip) - 273.15))/ (tref_ens(iens, ip) - 273.15 + 243.5))
+ e = (qref_ens(iens, ip) * forc_psrf(ip) / 100) / (0.378 * qref_ens(iens, ip) + 0.622)
+ rhref_ens(iens, ip) = max(min(1.0d0, e / es), 0.0d0)
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDIF
+
+!#############################################################################
+! Reading observations data
+!#############################################################################
+ ! read observations data (only for DA)
+ IF (has_smap_obs) THEN
+ CALL ncio_read_bcast_serial(file_smap, 'ii' , smap_ii )
+ CALL ncio_read_bcast_serial(file_smap, 'jj' , smap_jj )
+ CALL ncio_read_bcast_serial(file_smap, 'tb_h', smap_tb_h)
+ CALL ncio_read_bcast_serial(file_smap, 'tb_v', smap_tb_v)
+ CALL ncio_read_bcast_serial(file_smap, 'tb_h_colm_mean', pred_smap_tb_h_mean)
+ CALL ncio_read_bcast_serial(file_smap, 'tb_v_colm_mean', pred_smap_tb_v_mean)
+ CALL ncio_read_bcast_serial(file_smap, 'tb_h_obs_mean', smap_tb_h_mean)
+ CALL ncio_read_bcast_serial(file_smap, 'tb_v_obs_mean', smap_tb_v_mean)
+ ENDIF
+ IF (has_fy3d_obs) THEN
+ CALL ncio_read_bcast_serial(file_fy3d, 'ii' , fy3d_ii )
+ CALL ncio_read_bcast_serial(file_fy3d, 'jj' , fy3d_jj )
+ CALL ncio_read_bcast_serial(file_fy3d, 'tb_h', fy3d_tb_h)
+ CALL ncio_read_bcast_serial(file_fy3d, 'tb_v', fy3d_tb_v)
+ CALL ncio_read_bcast_serial(file_fy3d, 'tb_h_colm_mean', pred_fy3d_tb_h_mean)
+ CALL ncio_read_bcast_serial(file_fy3d, 'tb_v_colm_mean', pred_fy3d_tb_v_mean)
+ CALL ncio_read_bcast_serial(file_fy3d, 'tb_h_obs_mean', fy3d_tb_h_mean)
+ CALL ncio_read_bcast_serial(file_fy3d, 'tb_v_obs_mean', fy3d_tb_v_mean)
+ ENDIF
+ IF (has_synop_obs) THEN
+ CALL ncio_read_bcast_serial(file_synop, 'lat', synop_lat )
+ CALL ncio_read_bcast_serial(file_synop, 'lon', synop_lon )
+ CALL ncio_read_bcast_serial(file_synop, 'id', synop_id )
+ CALL ncio_read_bcast_serial(file_synop, 'tref', synop_tref)
+ CALL ncio_read_bcast_serial(file_synop, 'qref', synop_qref)
+ ENDIF
+
+!#############################################################################
+! Cropping predicted observations at observations space
+!#############################################################################
+#ifndef SinglePoint
+ IF (DEF_DA_SM_SMAP) THEN
+ IF (has_smap_obs) THEN
+ ! prepare filter for land patches
+ allocate (filter(numpatch))
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ filter(:) = patchtype <= 2
+ ENDIF
+ ENDIF
+
+ ! calculate area of each patch across world grid
+ IF (p_is_active) CALL allocate_block_data(grid_smap, area_smap_wgrid)
+ CALL mg2p_smap%get_sumarea(area_smap_wgrid, filter)
+
+ ! mapping predicted observations from patch to world grid
+ IF (p_is_active) THEN
+ CALL allocate_block_data(grid_smap, pred_smap_tb_h_wgrid_ens, DEF_DA_ENS_NUM)
+ CALL allocate_block_data(grid_smap, pred_smap_tb_v_wgrid_ens, DEF_DA_ENS_NUM)
+ ENDIF
+ CALL mg2p_smap%pset2grid(pred_smap_tb_h_pset_ens, pred_smap_tb_h_wgrid_ens, spv=spval, msk=filter)
+ CALL mg2p_smap%pset2grid(pred_smap_tb_v_pset_ens, pred_smap_tb_v_wgrid_ens, spv=spval, msk=filter)
+ deallocate (filter)
+
+ ! crop the predicted observations
+ IF (p_is_active) THEN
+ allocate (iloc(num_smap_obs))
+ pred_smap_tb_h_ogrid_ens = -9999.0
+ pred_smap_tb_v_ogrid_ens = -9999.0
+
+ ! crop obs from world grid to all obs grids
+ ndata = 0
+ DO i = 1, num_smap_obs
+ ib = grid_smap%xblk(smap_jj(i))
+ jb = grid_smap%yblk(smap_ii(i))
+ il = grid_smap%xloc(smap_jj(i))
+ jl = grid_smap%yloc(smap_ii(i))
+ IF (ib /= 0 .and. jb /= 0) THEN
+ IF (gblock%pio(ib, jb) == p_iam_glb) THEN
+ area_smap_wgrid_obs = area_smap_wgrid%blk(ib, jb)%val(il, jl)
+ IF (area_smap_wgrid_obs /= 0) THEN
+#ifdef USEMPI
+ ndata = ndata + 1
+ iloc(ndata) = i
+ pred_smap_tb_h_ogrid_ens(ndata, :) = (pred_smap_tb_h_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_smap_wgrid_obs
+ pred_smap_tb_v_ogrid_ens(ndata, :) = (pred_smap_tb_v_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_smap_wgrid_obs
+#else
+ pred_smap_tb_h_ogrid_ens(i, :) = (pred_smap_tb_h_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_smap_wgrid_obs
+ pred_smap_tb_v_ogrid_ens(i, :) = (pred_smap_tb_v_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_smap_wgrid_obs
+#endif
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! send data from io to roots
+#ifdef USEMPI
+ smesg = (/p_iam_glb, ndata/)
+ CALL mpi_send(smesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (ndata > 0) THEN
+ CALL mpi_send(iloc(1:ndata), ndata, MPI_INTEGER, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (dtemp(ndata, DEF_DA_ENS_NUM))
+ dtemp = pred_smap_tb_h_ogrid_ens(1:ndata, :)
+ CALL mpi_send(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ dtemp = pred_smap_tb_v_ogrid_ens(1:ndata, :)
+ CALL mpi_send(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, mpi_tag_data + 1, p_comm_glb, p_err)
+ deallocate (dtemp)
+ ENDIF
+#endif
+ deallocate (iloc)
+ deallocate (pred_smap_tb_h_wgrid_ens%blk, pred_smap_tb_v_wgrid_ens%blk)
+ ENDIF
+
+ ! broadcast from root to all ranks
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ pred_smap_tb_h_ogrid_ens = -9999.0
+ pred_smap_tb_v_ogrid_ens = -9999.0
+ DO ip = 0, p_np_active - 1
+ CALL mpi_recv(rmesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ ndata = rmesg(2)
+ IF (ndata > 0) THEN
+ allocate (itemp(ndata))
+ allocate (dtemp(ndata, DEF_DA_ENS_NUM))
+
+ isrc = rmesg(1)
+ CALL mpi_recv(itemp, ndata, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ pred_smap_tb_h_ogrid_ens(itemp, :) = dtemp
+ CALL mpi_recv(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, isrc, mpi_tag_data + 1, p_comm_glb, p_stat, p_err)
+ pred_smap_tb_v_ogrid_ens(itemp, :) = dtemp
+
+ deallocate (itemp)
+ deallocate (dtemp)
+ ENDIF
+ ENDDO
+ ENDIF
+ CALL mpi_bcast(pred_smap_tb_h_ogrid_ens, num_smap_obs*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast(pred_smap_tb_v_ogrid_ens, num_smap_obs*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM_FY) THEN
+ IF (has_fy3d_obs) THEN
+ ! prepare filter for land patches
+ allocate (filter(numpatch))
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ filter(:) = patchtype <= 2
+ ENDIF
+ ENDIF
+
+ ! calculate area of each patch across world grid
+ IF (p_is_active) CALL allocate_block_data(grid_fy3d, area_fy3d_wgrid)
+ CALL mg2p_fy3d%get_sumarea(area_fy3d_wgrid, filter)
+
+ ! mapping predicted observations from patch to world grid
+ IF (p_is_active) THEN
+ CALL allocate_block_data(grid_fy3d, pred_fy3d_tb_h_wgrid_ens, DEF_DA_ENS_NUM)
+ CALL allocate_block_data(grid_fy3d, pred_fy3d_tb_v_wgrid_ens, DEF_DA_ENS_NUM)
+ ENDIF
+ CALL mg2p_fy3d%pset2grid(pred_fy3d_tb_h_pset_ens, pred_fy3d_tb_h_wgrid_ens, spv=spval, msk=filter)
+ CALL mg2p_fy3d%pset2grid(pred_fy3d_tb_v_pset_ens, pred_fy3d_tb_v_wgrid_ens, spv=spval, msk=filter)
+ deallocate (filter)
+
+ ! crop the predicted observations
+ IF (p_is_active) THEN
+ allocate (iloc(num_fy3d_obs))
+ pred_fy3d_tb_h_ogrid_ens = -9999.0
+ pred_fy3d_tb_v_ogrid_ens = -9999.0
+
+ ! crop obs from world grid to all obs grids
+ ndata = 0
+ DO i = 1, num_fy3d_obs
+ ib = grid_fy3d%xblk(fy3d_jj(i))
+ jb = grid_fy3d%yblk(fy3d_ii(i))
+ il = grid_fy3d%xloc(fy3d_jj(i))
+ jl = grid_fy3d%yloc(fy3d_ii(i))
+ IF (ib /= 0 .and. jb /= 0) THEN
+ IF (gblock%pio(ib, jb) == p_iam_glb) THEN
+ area_fy3d_wgrid_obs = area_fy3d_wgrid%blk(ib, jb)%val(il, jl)
+ IF (area_fy3d_wgrid_obs /= 0) THEN
+#ifdef USEMPI
+ ndata = ndata + 1
+ iloc(ndata) = i
+ pred_fy3d_tb_h_ogrid_ens(ndata, :) = (pred_fy3d_tb_h_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_fy3d_wgrid_obs
+ pred_fy3d_tb_v_ogrid_ens(ndata, :) = (pred_fy3d_tb_v_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_fy3d_wgrid_obs
+#else
+ pred_fy3d_tb_h_ogrid_ens(i, :) = (pred_fy3d_tb_h_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_fy3d_wgrid_obs
+ pred_fy3d_tb_v_ogrid_ens(i, :) = (pred_fy3d_tb_v_wgrid_ens%blk(ib, jb)%val(:, il, jl))/area_fy3d_wgrid_obs
+#endif
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! send data from io to roots
+#ifdef USEMPI
+ smesg = (/p_iam_glb, ndata/)
+ CALL mpi_send(smesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (ndata > 0) THEN
+ CALL mpi_send(iloc(1:ndata), ndata, MPI_INTEGER, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (dtemp(ndata, DEF_DA_ENS_NUM))
+ dtemp = pred_fy3d_tb_h_ogrid_ens(1:ndata, :)
+ CALL mpi_send(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ dtemp = pred_fy3d_tb_v_ogrid_ens(1:ndata, :)
+ CALL mpi_send(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, mpi_tag_data + 1, p_comm_glb, p_err)
+ deallocate (dtemp)
+ ENDIF
+#endif
+ deallocate (iloc)
+ deallocate (pred_fy3d_tb_h_wgrid_ens%blk, pred_fy3d_tb_v_wgrid_ens%blk)
+ ENDIF
+
+ ! broadcast from root to all ranks
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ pred_fy3d_tb_h_ogrid_ens = -9999.0
+ pred_fy3d_tb_v_ogrid_ens = -9999.0
+ DO ip = 0, p_np_active - 1
+ CALL mpi_recv(rmesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ ndata = rmesg(2)
+ IF (ndata > 0) THEN
+ allocate (itemp(ndata))
+ allocate (dtemp(ndata, DEF_DA_ENS_NUM))
+
+ isrc = rmesg(1)
+ CALL mpi_recv(itemp, ndata, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ pred_fy3d_tb_h_ogrid_ens(itemp, :) = dtemp
+ CALL mpi_recv(dtemp, ndata*DEF_DA_ENS_NUM, MPI_REAL8, isrc, mpi_tag_data + 1, p_comm_glb, p_stat, p_err)
+ pred_fy3d_tb_v_ogrid_ens(itemp, :) = dtemp
+
+ deallocate (itemp)
+ deallocate (dtemp)
+ ENDIF
+ ENDDO
+ ENDIF
+ CALL mpi_bcast(pred_fy3d_tb_h_ogrid_ens, num_fy3d_obs*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast(pred_fy3d_tb_v_ogrid_ens, num_fy3d_obs*DEF_DA_ENS_NUM, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM_SYNOP) THEN
+ ! crop corresponding index (rank id and patch id) of each observation
+ IF (has_synop_obs) THEN
+ synop_idx(:,:) = -1
+ IF (p_is_root) THEN
+ synop_idx = synop_lut(:, synop_id)
+ ENDIF
+ CALL mpi_bcast(synop_idx, 2*num_synop_obs, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ ENDIF
+
+ ! recount the number of observations at each rank
+ IF (has_synop_obs) THEN
+ IF (p_is_compute) THEN
+ counter_rank_nsite = 0
+ DO i = 1, num_synop_obs
+ IF (synop_idx(1, i) == p_iam_glb) THEN
+ counter_rank_nsite = counter_rank_nsite + 1
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ ! allocate memory for rank
+ IF (has_synop_obs) THEN
+ IF (p_is_compute) THEN
+ IF (counter_rank_nsite > 0) THEN
+ IF (allocated(tref_ens_rank)) deallocate (tref_ens_rank)
+ IF (allocated(qref_ens_rank)) deallocate (qref_ens_rank)
+ IF (allocated(site_id_rank)) deallocate (site_id_rank)
+ allocate (tref_ens_rank (counter_rank_nsite, DEF_DA_ENS_NUM))
+ allocate (qref_ens_rank (counter_rank_nsite, DEF_DA_ENS_NUM))
+ allocate (site_id_rank (counter_rank_nsite))
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! crop observations at each rank according index & send to root
+ IF (has_synop_obs) THEN
+ IF (p_is_compute) THEN
+ counter_rank_nsite = 0
+ DO i = 1, num_synop_obs
+ IF (synop_idx(1, i) == p_iam_glb) THEN
+ counter_rank_nsite = counter_rank_nsite + 1
+ tref_ens_rank(counter_rank_nsite,:) = tref_ens(:, synop_idx(2, i))
+ qref_ens_rank(counter_rank_nsite,:) = rhref_ens(:, synop_idx(2, i))
+ site_id_rank (counter_rank_nsite) = i
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ ! send the number of site and their patch id to root
+ mesg = (/p_iam_glb, counter_rank_nsite/)
+ CALL mpi_send(mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (counter_rank_nsite > 0) THEN
+ CALL mpi_send(tref_ens_rank, DEF_DA_ENS_NUM*counter_rank_nsite, MPI_REAL8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send(qref_ens_rank, DEF_DA_ENS_NUM*counter_rank_nsite, MPI_REAL8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send(site_id_rank, counter_rank_nsite, MPI_INTEGER, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#endif
+
+ IF (allocated(tref_ens_rank)) deallocate (tref_ens_rank)
+ IF (allocated(qref_ens_rank)) deallocate (qref_ens_rank)
+ IF (allocated(site_id_rank)) deallocate (site_id_rank)
+ ENDIF
+ ENDIF
+
+ ! concatenate all predicted observations at root & broadcast to all ranks
+ IF (has_synop_obs) THEN
+ qref_ens_o = spval
+ tref_ens_o = spval
+ IF (p_is_root) THEN
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv(mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ ndata = mesg(2)
+
+ IF (ndata > 0) THEN
+ allocate(tref_ens_rank(ndata, DEF_DA_ENS_NUM))
+ allocate(qref_ens_rank(ndata, DEF_DA_ENS_NUM))
+ allocate(site_id_rank (ndata))
+
+ CALL mpi_recv(tref_ens_rank, ndata*DEF_DA_ENS_NUM, MPI_REAL8, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv(qref_ens_rank, ndata*DEF_DA_ENS_NUM, MPI_REAL8, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv(site_id_rank, ndata, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ qref_ens_o(site_id_rank,:) = qref_ens_rank
+ tref_ens_o(site_id_rank,:) = tref_ens_rank
+ ENDIF
+
+ IF (allocated(tref_ens_rank)) deallocate(tref_ens_rank)
+ IF (allocated(qref_ens_rank)) deallocate(qref_ens_rank)
+ IF (allocated(site_id_rank)) deallocate(site_id_rank)
+ ENDDO
+#endif
+ ENDIF
+ CALL mpi_bcast(qref_ens_o, DEF_DA_ENS_NUM*num_synop_obs, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast(tref_ens_o, DEF_DA_ENS_NUM*num_synop_obs, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+ ENDIF
+ ENDIF
+#endif
+
+!#############################################################################
+! Run data assimilation (for only DA)
+!#############################################################################
+ has_DA = .false.
+ IF (has_smap_obs .or. has_fy3d_obs .or. has_synop_obs) THEN
+ ! for grid data assimilation
+ IF (p_is_compute) THEN
+ DO np = 1, numpatch
+
+!#############################################################################
+! 1. Find observations around each patch
+!#############################################################################
+ ! regions info around target patch
+ lat_p_n = patchlatr(np)*180/pi + dres
+ lat_p_s = patchlatr(np)*180/pi - dres
+ lon_p_w = patchlonr(np)*180/pi - dres
+ lon_p_e = patchlonr(np)*180/pi + dres
+
+ ! find observations around each patch
+ num_obs_p = 0
+ num_smap_p = 0
+ num_fy3d_p = 0
+ num_synop_p = 0
+ IF (DEF_DA_SM_SMAP) THEN
+ IF (has_smap_obs) THEN
+ num_smap_p = count(smap_lat(:) < lat_p_n .and. smap_lat(:) > lat_p_s .and. &
+ smap_lon(:) > lon_p_w .and. smap_lon(:) < lon_p_e .and. &
+ smap_time(:) - idate_b >= 0 .and. smap_time(:) - idate_e <= 0 .and. &
+ smap_tb_h_mean(:) > 0 .and. pred_smap_tb_h_mean(:) > 0)
+ ENDIF
+ ENDIF
+ IF (DEF_DA_SM_FY) THEN
+ IF (has_fy3d_obs) THEN
+ num_fy3d_p = count(fy3d_lat(:) < lat_p_n .and. fy3d_lat(:) > lat_p_s .and. &
+ fy3d_lon(:) > lon_p_w .and. fy3d_lon(:) < lon_p_e .and. &
+ fy3d_time(:) - idate_b >= 0 .and. fy3d_time(:) - idate_e <= 0 .and. &
+ fy3d_tb_h_mean(:) > 0 .and. pred_fy3d_tb_h_mean(:) > 0)
+ ENDIF
+ ENDIF
+ IF (DEF_DA_SM_SYNOP) THEN
+ IF (has_synop_obs) THEN
+ num_synop_p = count( &
+ synop_lat(:) < lat_p_n .and. synop_lat(:) > lat_p_s .and. &
+ synop_lon(:) > lon_p_w .and. synop_lon(:) < lon_p_e .and. &
+ synop_time(:) - idate_b >= 0 .and. synop_time(:) - idate_e <= 0 .and. &
+ tref_ens_o(:,1) > 0)
+ ENDIF
+ ENDIF
+ num_obs_p = num_smap_p + num_fy3d_p + 2*num_synop_p
+
+!#############################################################################
+! 2. Perform data assimilation
+!#############################################################################
+ IF (num_obs_p > 0) THEN
+ ! allocate memory for data assimilation
+ allocate (obs_err (num_obs_p ))
+ allocate (trans (DEF_DA_ENS_NUM,DEF_DA_ENS_NUM))
+ allocate (wliq_soi_ens (nl_soil, DEF_DA_ENS_NUM ))
+ allocate (wliq_soi_ens_da(nl_soil, DEF_DA_ENS_NUM ))
+ allocate (t_soi_ens (nl_soil, DEF_DA_ENS_NUM ))
+ allocate (t_soi_ens_da (nl_soil, DEF_DA_ENS_NUM ))
+ allocate (pred_obs_p_ens (num_obs_p, DEF_DA_ENS_NUM ))
+ allocate (obs_p (num_obs_p ))
+
+
+!#############################################################################
+! 2.1. Prepare observations around target patch for each observation dataset
+!#############################################################################
+ IF (num_smap_p > 0) THEN
+ ! allocate memory
+ allocate (index_smap_p (num_smap_p ))
+ allocate (smap_lat_p (num_smap_p ))
+ allocate (smap_lon_p (num_smap_p ))
+ allocate (smap_tb_h_p (num_smap_p ))
+ allocate (smap_tb_v_p (num_smap_p ))
+ allocate (pred_smap_tb_h_p_ens (num_smap_p, DEF_DA_ENS_NUM))
+ allocate (pred_smap_tb_v_p_ens (num_smap_p, DEF_DA_ENS_NUM))
+ allocate (smap_tb_h_mean_p (num_smap_p ))
+ allocate (smap_tb_v_mean_p (num_smap_p ))
+ allocate (pred_smap_tb_h_mean_p(num_smap_p ))
+ allocate (pred_smap_tb_v_mean_p(num_smap_p ))
+ allocate (smap_err (num_smap_p ))
+ allocate (d_smap_p (num_smap_p ))
+
+ ! index of observations around target patch
+ index_smap_p = (smap_lat(:) < lat_p_n .and. smap_lat(:) > lat_p_s .and. &
+ smap_lon(:) > lon_p_w .and. smap_lon(:) < lon_p_e .and. &
+ smap_time(:) - idate_b >= 0 .and. smap_time(:) - idate_e <= 0 .and. &
+ smap_tb_h_mean(:) > 0 .and. pred_smap_tb_h_mean(:) > 0)
+
+ ! crop observations around target patch
+ smap_lat_p = pack(smap_lat , index_smap_p)
+ smap_lon_p = pack(smap_lon , index_smap_p)
+ smap_tb_h_p = pack(smap_tb_h, index_smap_p)
+ smap_tb_v_p = pack(smap_tb_v, index_smap_p)
+
+ ! crop ensemble predicted observations around target patch
+ DO i = 1, DEF_DA_ENS_NUM
+ pred_smap_tb_h_p_ens(:, i) = pack(pred_smap_tb_h_ogrid_ens(:, i), index_smap_p)
+ pred_smap_tb_v_p_ens(:, i) = pack(pred_smap_tb_v_ogrid_ens(:, i), index_smap_p)
+ ENDDO
+
+ ! crop mean values around target patch
+ smap_tb_h_mean_p = pack(smap_tb_h_mean, index_smap_p)
+ smap_tb_v_mean_p = pack(smap_tb_v_mean, index_smap_p)
+ pred_smap_tb_h_mean_p = pack(pred_smap_tb_h_mean, index_smap_p)
+ pred_smap_tb_v_mean_p = pack(pred_smap_tb_v_mean, index_smap_p)
+
+ ! scaling
+ smap_tb_h_p = smap_tb_h_p - smap_tb_h_mean_p
+ smap_tb_v_p = smap_tb_v_p - smap_tb_v_mean_p
+ DO i = 1, DEF_DA_ENS_NUM
+ pred_smap_tb_h_p_ens(:, i) = pred_smap_tb_h_p_ens(:, i) - pred_smap_tb_h_mean_p
+ pred_smap_tb_v_p_ens(:, i) = pred_smap_tb_v_p_ens(:, i) - pred_smap_tb_v_mean_p
+ ENDDO
+
+ ! calculate distance between observation and patch center
+ d_smap_p = 2*6.3781e3*asin(sqrt(sin((smap_lat_p*pi/180 - patchlatr(np))/2.0)**2 + &
+ cos(smap_lat_p*pi/180)*cos(patchlatr(np))*sin((smap_lon_p*pi/180 - patchlonr(np))/2.0)**2))
+
+ ! calculate weighted observation error
+ smap_err = static_smap_err/(exp((-d_smap_p**2)/(2*loc_r**2)))
+ ENDIF
+
+ IF (num_fy3d_p > 0) THEN
+ ! allocate memory
+ allocate (index_fy3d_p (num_fy3d_p ))
+ allocate (fy3d_lat_p (num_fy3d_p ))
+ allocate (fy3d_lon_p (num_fy3d_p ))
+ allocate (fy3d_tb_h_p (num_fy3d_p ))
+ allocate (fy3d_tb_v_p (num_fy3d_p ))
+ allocate (pred_fy3d_tb_h_p_ens (num_fy3d_p, DEF_DA_ENS_NUM))
+ allocate (pred_fy3d_tb_v_p_ens (num_fy3d_p, DEF_DA_ENS_NUM))
+ allocate (fy3d_tb_h_mean_p (num_fy3d_p ))
+ allocate (fy3d_tb_v_mean_p (num_fy3d_p ))
+ allocate (pred_fy3d_tb_h_mean_p(num_fy3d_p ))
+ allocate (pred_fy3d_tb_v_mean_p(num_fy3d_p ))
+ allocate (fy3d_err (num_fy3d_p ))
+ allocate (d_fy3d_p (num_fy3d_p ))
+
+ ! index of observations around target patch
+ index_fy3d_p = (fy3d_lat(:) < lat_p_n .and. fy3d_lat(:) > lat_p_s .and. &
+ fy3d_lon(:) > lon_p_w .and. fy3d_lon(:) < lon_p_e .and. &
+ fy3d_time(:) - idate_b >= 0 .and. fy3d_time(:) - idate_e <= 0 .and. &
+ fy3d_tb_h_mean(:) > 0 .and. pred_fy3d_tb_h_mean(:) > 0)
+
+ ! crop observations around target patch
+ fy3d_lat_p = pack(fy3d_lat , index_fy3d_p)
+ fy3d_lon_p = pack(fy3d_lon , index_fy3d_p)
+ fy3d_tb_h_p = pack(fy3d_tb_h, index_fy3d_p)
+ fy3d_tb_v_p = pack(fy3d_tb_v, index_fy3d_p)
+
+ ! crop ensemble predicted observations around target patch
+ DO i = 1, DEF_DA_ENS_NUM
+ pred_fy3d_tb_h_p_ens(:, i) = pack(pred_fy3d_tb_h_ogrid_ens(:, i), index_fy3d_p)
+ pred_fy3d_tb_v_p_ens(:, i) = pack(pred_fy3d_tb_v_ogrid_ens(:, i), index_fy3d_p)
+ ENDDO
+
+ ! crop mean values around target patch
+ fy3d_tb_h_mean_p = pack(fy3d_tb_h_mean, index_fy3d_p)
+ fy3d_tb_v_mean_p = pack(fy3d_tb_v_mean, index_fy3d_p)
+ pred_fy3d_tb_h_mean_p = pack(pred_fy3d_tb_h_mean, index_fy3d_p)
+ pred_fy3d_tb_v_mean_p = pack(pred_fy3d_tb_v_mean, index_fy3d_p)
+
+ ! scaling
+ fy3d_tb_h_p = fy3d_tb_h_p - fy3d_tb_h_mean_p
+ fy3d_tb_v_p = fy3d_tb_v_p - fy3d_tb_v_mean_p
+ DO i = 1, DEF_DA_ENS_NUM
+ pred_fy3d_tb_h_p_ens(:, i) = pred_fy3d_tb_h_p_ens(:, i) - pred_fy3d_tb_h_mean_p
+ pred_fy3d_tb_v_p_ens(:, i) = pred_fy3d_tb_v_p_ens(:, i) - pred_fy3d_tb_v_mean_p
+ ENDDO
+
+ ! calculate distance between observation and patch center
+ d_fy3d_p = 2*6.3781e3*asin(sqrt(sin((fy3d_lat_p*pi/180 - patchlatr(np))/2.0)**2 + &
+ cos(fy3d_lat_p*pi/180)*cos(patchlatr(np))*sin((fy3d_lon_p*pi/180 - patchlonr(np))/2.0)**2))
+
+ ! calculate weighted observation error
+ fy3d_err = static_fy3d_err/(exp((-d_fy3d_p**2)/(2*loc_r**2)))
+ ENDIF
+
+ IF (num_synop_p > 0) THEN
+ ! allocate memory
+ allocate (index_synop_p (num_synop_p ))
+ allocate (synop_lat_p (num_synop_p ))
+ allocate (synop_lon_p (num_synop_p ))
+ allocate (synop_qref_p (num_synop_p ))
+ allocate (synop_tref_p (num_synop_p ))
+ allocate (qref_ens_p (num_synop_p, DEF_DA_ENS_NUM ))
+ allocate (tref_ens_p (num_synop_p, DEF_DA_ENS_NUM ))
+ allocate (synop_tref_err (num_synop_p ))
+ allocate (synop_qref_err (num_synop_p ))
+ allocate (d_synop_p (num_synop_p ))
+
+ ! index of observations around target patch
+ index_synop_p = ( &
+ synop_lat(:) < lat_p_n .and. synop_lat(:) > lat_p_s .and. &
+ synop_lon(:) > lon_p_w .and. synop_lon(:) < lon_p_e .and. &
+ synop_time(:) - idate_b >= 0 .and. synop_time(:) - idate_e <= 0 .and. &
+ tref_ens_o(:,1) > 0)
+
+ ! crop observations around target patch
+ synop_lat_p = pack(synop_lat, index_synop_p)
+ synop_lon_p = pack(synop_lon, index_synop_p)
+ synop_qref_p = pack(synop_qref, index_synop_p)
+ synop_tref_p = pack(synop_tref, index_synop_p)
+
+ ! crop ensemble predicted observations around target patch
+ DO i = 1, DEF_DA_ENS_NUM
+ qref_ens_p(:, i) = pack(qref_ens_o(:, i), index_synop_p)
+ tref_ens_p(:, i) = pack(tref_ens_o(:, i), index_synop_p)
+ ENDDO
+
+ ! calculate distance between observation and patch center
+ d_synop_p = 2*6.3781e3*asin(sqrt(sin((synop_lat_p*pi/180 - patchlatr(np))/2.0)**2 + &
+ cos(synop_lat_p*pi/180)*cos(patchlatr(np))*sin((synop_lon_p*pi/180 - patchlonr(np))/2.0)**2))
+
+ ! calculate weighted observation error
+ synop_tref_err = static_synop_tref_err/(exp((-d_synop_p**2)/(2*loc_r**2)))
+ synop_qref_err = static_synop_qref_err/(exp((-d_synop_p**2)/(2*loc_r**2)))
+ ENDIF
+
+!#############################################################################
+! 2.2. Concat observations & ensemble predictions around target patch
+!#############################################################################
+ ! index of end of each observation dataset
+ end_idx(1) = num_smap_p
+ end_idx(2) = num_smap_p + num_fy3d_p
+ end_idx(3) = num_smap_p + num_fy3d_p + num_synop_p
+
+ ! concatenate ensemble predictions
+ IF (num_smap_p > 0) THEN
+ pred_obs_p_ens(1:end_idx(1),:) = pred_smap_tb_h_p_ens
+ obs_p(1:end_idx(1)) = smap_tb_h_p
+ obs_err(1:end_idx(1)) = smap_err
+ ENDIF
+ IF (num_fy3d_p > 0) THEN
+ pred_obs_p_ens(end_idx(1)+1:end_idx(2),:) = pred_fy3d_tb_h_p_ens
+ obs_p(end_idx(1)+1:end_idx(2)) = fy3d_tb_h_p
+ obs_err(end_idx(1)+1:end_idx(2)) = fy3d_err
+ ENDIF
+ IF (num_synop_p > 0) THEN
+ pred_obs_p_ens(end_idx(2)+1:end_idx(3),:) = tref_ens_p
+ pred_obs_p_ens(end_idx(3)+1:,:) = qref_ens_p
+ obs_p(end_idx(2)+1:end_idx(3)) = synop_tref_p
+ obs_p(end_idx(3)+1:) = synop_qref_p
+ obs_err(end_idx(2)+1:end_idx(3)) = synop_tref_err
+ obs_err(end_idx(3)+1:) = synop_qref_err
+ ENDIF
+ !index_nearest = minloc(d_p, dim=1)
+
+!#############################################################################
+! Perform LETKF and postprocess analysis results
+!#############################################################################
+ ! calculate transformation matrix
+ CALL letkf(DEF_DA_ENS_NUM, num_obs_p, &
+ pred_obs_p_ens, obs_p, obs_err, infl, &
+ trans)
+
+ ! calculate analysis value
+ IF (patchtype(np) < 3) THEN ! ocean, lake, ice
+ has_DA = .true.
+
+ ! soil layer
+ DO iens = 1, DEF_DA_ENS_NUM
+ wliq_soi_ens(:, iens) = wliq_soisno_ens(1:, iens, np)
+ t_soi_ens(:, iens) = t_soisno_ens(1:, iens, np)
+ ENDDO
+
+ ! analysis
+ CALL dgemm('N', 'N', nl_soil, DEF_DA_ENS_NUM, DEF_DA_ENS_NUM, 1.0_8, wliq_soi_ens, &
+ nl_soil, trans, DEF_DA_ENS_NUM, 0.0_8, wliq_soi_ens_da, nl_soil)
+ CALL dgemm('N', 'N', nl_soil, DEF_DA_ENS_NUM, DEF_DA_ENS_NUM, 1.0_8, t_soi_ens, &
+ nl_soil, trans, DEF_DA_ENS_NUM, 0.0_8, t_soi_ens_da, nl_soil)
+
+ ! save analysis results
+ wliq_soi_ens_da = max(0.0, wliq_soi_ens_da)
+ DO iens = 1, DEF_DA_ENS_NUM
+ wliq_soisno_ens(1:2, iens, np) = wliq_soi_ens_da(1:2, iens)
+ ! limit the change of t_soisno in range of [-20.0, 20.0]
+ WHERE (t_soi_ens_da(1:2,iens) > t_soisno_ens(1:2,iens,np))
+ t_soisno_ens(1:2,iens,np) = t_soisno_ens(1:2,iens,np) + min(20.0, t_soi_ens_da(1:2,iens)-t_soisno_ens(1:2,iens,np))
+ ELSEWHERE
+ t_soisno_ens(1:2,iens,np) = t_soisno_ens(1:2,iens,np) + max(-20.0, t_soi_ens_da(1:2,iens)-t_soisno_ens(1:2,iens,np))
+ ENDWHERE
+ ENDDO
+
+ ! limit the soil liquid and ice water in a reasonable range
+ DO i = 1, nl_soil
+ DO iens = 1, DEF_DA_ENS_NUM
+ ! lower bound
+ wliq_soisno_ens(i, iens, np) = max(0.0d0, wliq_soisno_ens(i, iens, np))
+ wice_soisno_ens(i, iens, np) = max(0.0d0, wice_soisno_ens(i, iens, np))
+ IF (wliq_soisno_ens(i, iens, np) == 0.0 .and. wice_soisno_ens(i, iens, np) == 0.0) THEN
+ IF (t_soisno_ens(i, iens, np)-tfrz < -5.0) THEN
+ wice_soisno_ens(i, iens, np) = 1e-10
+ ELSE
+ wliq_soisno_ens(i, iens, np) = 1e-10
+ ENDIF
+ ENDIF
+
+ ! upper bound
+ wliq_soisno_ens(i, iens, np) = min(porsl(i, np)*(dz_soi(i)*denh2o), wliq_soisno_ens(i, iens, np))
+ eff_porsl = max(0.0d0, porsl(i, np) - wliq_soisno_ens(i, iens, np)/(dz_soi(i)*denh2o))
+ wice_soisno_ens(i, iens, np) = min(eff_porsl*(dz_soi(i)*denice), wice_soisno_ens(i, iens, np))
+ ENDDO
+ ENDDO
+
+ ! move residual water to water table
+ wa_ens(:, np) = wa_ens(:, np) - sum(wliq_soisno_ens(1:, :, np) - wliq_soi_ens, dim=1)
+
+ ! update volumetric water content for diagnostic
+ DO iens = 1, DEF_DA_ENS_NUM
+ h2osoi_ens(:, iens, np) = wliq_soisno_ens(1:, iens, np)/(dz_soi(:)*denh2o) + wice_soisno_ens(1:, iens, np)/(dz_soi(:)*denice)
+ h2osoi_ens(:, iens, np) = min(1.0d0, h2osoi_ens(:, iens, np))
+ h2osoi_ens(:, iens, np) = max(0.0d0, h2osoi_ens(:, iens, np))
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+!#############################################################################
+! deallocate memory changes with patch
+!#############################################################################
+ IF (allocated(trans )) deallocate (trans )
+ IF (allocated(smap_err )) deallocate (smap_err )
+ IF (allocated(d_smap_p )) deallocate (d_smap_p )
+ IF (allocated(fy3d_err )) deallocate (fy3d_err )
+ IF (allocated(d_fy3d_p )) deallocate (d_fy3d_p )
+ IF (allocated(synop_tref_err )) deallocate (synop_tref_err )
+ IF (allocated(synop_qref_err )) deallocate (synop_qref_err )
+ IF (allocated(d_synop_p )) deallocate (d_synop_p )
+ IF (allocated(pred_obs_p_ens )) deallocate (pred_obs_p_ens )
+ IF (allocated(obs_p )) deallocate (obs_p )
+ IF (allocated(obs_err )) deallocate (obs_err )
+ IF (allocated(wliq_soi_ens )) deallocate (wliq_soi_ens )
+ IF (allocated(wliq_soi_ens_da )) deallocate (wliq_soi_ens_da )
+ IF (allocated(t_soi_ens )) deallocate (t_soi_ens )
+ IF (allocated(t_soi_ens_da )) deallocate (t_soi_ens_da )
+
+ IF (allocated(index_smap_p )) deallocate (index_smap_p )
+ IF (allocated(smap_lat_p )) deallocate (smap_lat_p )
+ IF (allocated(smap_lon_p )) deallocate (smap_lon_p )
+ IF (allocated(smap_tb_h_p )) deallocate (smap_tb_h_p )
+ IF (allocated(smap_tb_v_p )) deallocate (smap_tb_v_p )
+ IF (allocated(pred_smap_tb_h_p_ens )) deallocate (pred_smap_tb_h_p_ens )
+ IF (allocated(pred_smap_tb_v_p_ens )) deallocate (pred_smap_tb_v_p_ens )
+ IF (allocated(smap_tb_h_mean_p )) deallocate (smap_tb_h_mean_p )
+ IF (allocated(pred_smap_tb_h_mean_p)) deallocate (pred_smap_tb_h_mean_p)
+ IF (allocated(smap_tb_v_mean_p )) deallocate (smap_tb_v_mean_p )
+ IF (allocated(pred_smap_tb_v_mean_p)) deallocate (pred_smap_tb_v_mean_p)
+
+ IF (allocated(index_fy3d_p )) deallocate (index_fy3d_p )
+ IF (allocated(fy3d_lat_p )) deallocate (fy3d_lat_p )
+ IF (allocated(fy3d_lon_p )) deallocate (fy3d_lon_p )
+ IF (allocated(fy3d_tb_h_p )) deallocate (fy3d_tb_h_p )
+ IF (allocated(fy3d_tb_v_p )) deallocate (fy3d_tb_v_p )
+ IF (allocated(pred_fy3d_tb_h_p_ens )) deallocate (pred_fy3d_tb_h_p_ens )
+ IF (allocated(pred_fy3d_tb_v_p_ens )) deallocate (pred_fy3d_tb_v_p_ens )
+ IF (allocated(fy3d_tb_h_mean_p )) deallocate (fy3d_tb_h_mean_p )
+ IF (allocated(pred_fy3d_tb_h_mean_p)) deallocate (pred_fy3d_tb_h_mean_p)
+ IF (allocated(fy3d_tb_v_mean_p )) deallocate (fy3d_tb_v_mean_p )
+ IF (allocated(pred_fy3d_tb_v_mean_p)) deallocate (pred_fy3d_tb_v_mean_p)
+
+ IF (allocated(index_synop_p )) deallocate (index_synop_p )
+ IF (allocated(synop_lat_p )) deallocate (synop_lat_p )
+ IF (allocated(synop_lon_p )) deallocate (synop_lon_p )
+ IF (allocated(synop_qref_p )) deallocate (synop_qref_p )
+ IF (allocated(synop_tref_p )) deallocate (synop_tref_p )
+ IF (allocated(qref_ens_p )) deallocate (qref_ens_p )
+ IF (allocated(tref_ens_p )) deallocate (tref_ens_p )
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+!#############################################################################
+! Calculate ensemble brightness temperature after DA for diagnostic
+!#############################################################################
+ IF (has_DA) THEN
+ IF (p_is_compute) THEN
+ IF (DEF_DA_SM_SMAP) THEN
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ DO iens = 1, DEF_DA_ENS_NUM
+ DO np = 1, numpatch
+ CALL forward(&
+ patchtype(np), patchclass(np), dz_sno_ens(:, iens, np), &
+ forc_topo(np), htop(np), &
+ tref_ens(iens, np), t_soisno_ens(:,iens,np), tleaf_ens(iens, np), &
+ wliq_soisno_ens(:, iens, np), wice_soisno_ens(:, iens, np), h2osoi_ens(:, iens, np), &
+ snowdp_ens(iens, np), lai_ens(iens, np), sai_ens(iens, np), &
+ wf_clay(:, np), wf_sand(:, np), wf_silt(:, np), BD_all(:, np), porsl(:, np), &
+ smap_theta, smap_fghz, &
+ t_brt_smap_ens(1,iens,np), t_brt_smap_ens(2,iens,np))
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (DEF_DA_SM_FY) THEN
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ DO iens = 1, DEF_DA_ENS_NUM
+ DO np = 1, numpatch
+ CALL forward(&
+ patchtype(np), patchclass(np), dz_sno_ens(:, iens, np), &
+ forc_topo(np), htop(np), &
+ tref_ens(iens, np), t_soisno_ens(:,iens,np), tleaf_ens(iens, np), &
+ wliq_soisno_ens(:, iens, np), wice_soisno_ens(:, iens, np), h2osoi_ens(:, iens, np), &
+ snowdp_ens(iens, np), lai_ens(iens, np), sai_ens(iens, np), &
+ wf_clay(:, np), wf_sand(:, np), wf_silt(:, np), BD_all(:, np), porsl(:, np), &
+ fy3d_theta, fy3d_fghz, &
+ t_brt_fy3d_ens(1,iens,np), t_brt_fy3d_ens(2,iens,np))
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+!#############################################################################
+! Deallocate all memory
+!#############################################################################
+ IF (allocated (trans)) deallocate (trans)
+ IF (allocated (obs_err)) deallocate (obs_err)
+ IF (allocated (filter )) deallocate (filter )
+ IF (allocated (wliq_soi_ens)) deallocate (wliq_soi_ens)
+ IF (allocated (wliq_soi_ens_da)) deallocate (wliq_soi_ens_da)
+ IF (allocated (t_soi_ens)) deallocate (t_soi_ens)
+ IF (allocated (t_soi_ens_da)) deallocate (t_soi_ens_da)
+
+ IF (allocated (smap_time)) deallocate (smap_time)
+ IF (allocated (dt_b_smap)) deallocate (dt_b_smap)
+ IF (allocated (dt_e_smap)) deallocate (dt_e_smap)
+ IF (allocated (smap_lat)) deallocate (smap_lat)
+ IF (allocated (smap_lon)) deallocate (smap_lon)
+ IF (allocated (smap_tb_h)) deallocate (smap_tb_h)
+ IF (allocated (smap_tb_v)) deallocate (smap_tb_v)
+ IF (allocated (smap_ii)) deallocate (smap_ii)
+ IF (allocated (smap_jj)) deallocate (smap_jj)
+ IF (allocated (smap_tb_h_mean)) deallocate (smap_tb_h_mean)
+ IF (allocated (smap_tb_v_mean)) deallocate (smap_tb_v_mean)
+ IF (allocated (pred_smap_tb_h_mean)) deallocate (pred_smap_tb_h_mean)
+ IF (allocated (pred_smap_tb_v_mean)) deallocate (pred_smap_tb_v_mean)
+ IF (allocated (pred_smap_tb_h_pset_ens)) deallocate (pred_smap_tb_h_pset_ens)
+ IF (allocated (pred_smap_tb_v_pset_ens)) deallocate (pred_smap_tb_v_pset_ens)
+ IF (allocated (pred_smap_tb_h_ogrid_ens)) deallocate (pred_smap_tb_h_ogrid_ens)
+ IF (allocated (pred_smap_tb_v_ogrid_ens)) deallocate (pred_smap_tb_v_ogrid_ens)
+
+ IF (allocated (fy3d_time)) deallocate (fy3d_time)
+ IF (allocated (dt_b_fy3d)) deallocate (dt_b_fy3d)
+ IF (allocated (dt_e_fy3d)) deallocate (dt_e_fy3d)
+ IF (allocated (fy3d_lat)) deallocate (fy3d_lat)
+ IF (allocated (fy3d_lon)) deallocate (fy3d_lon)
+ IF (allocated (fy3d_tb_h)) deallocate (fy3d_tb_h)
+ IF (allocated (fy3d_tb_v)) deallocate (fy3d_tb_v)
+ IF (allocated (fy3d_ii)) deallocate (fy3d_ii)
+ IF (allocated (fy3d_jj)) deallocate (fy3d_jj)
+ IF (allocated (fy3d_tb_h_mean)) deallocate (fy3d_tb_h_mean)
+ IF (allocated (fy3d_tb_v_mean)) deallocate (fy3d_tb_v_mean)
+ IF (allocated (pred_fy3d_tb_h_mean)) deallocate (pred_fy3d_tb_h_mean)
+ IF (allocated (pred_fy3d_tb_v_mean)) deallocate (pred_fy3d_tb_v_mean)
+ IF (allocated (pred_fy3d_tb_h_pset_ens)) deallocate (pred_fy3d_tb_h_pset_ens)
+ IF (allocated (pred_fy3d_tb_v_pset_ens)) deallocate (pred_fy3d_tb_v_pset_ens)
+ IF (allocated (pred_fy3d_tb_h_ogrid_ens)) deallocate (pred_fy3d_tb_h_ogrid_ens)
+ IF (allocated (pred_fy3d_tb_v_ogrid_ens)) deallocate (pred_fy3d_tb_v_ogrid_ens)
+
+ IF (allocated (synop_time)) deallocate (synop_time)
+ IF (allocated (synop_lat)) deallocate (synop_lat)
+ IF (allocated (synop_lon)) deallocate (synop_lon)
+ IF (allocated (synop_qref)) deallocate (synop_qref)
+ IF (allocated (synop_tref)) deallocate (synop_tref)
+ IF (allocated (tref_ens_o)) deallocate (tref_ens_o)
+ IF (allocated (qref_ens_o)) deallocate (qref_ens_o)
+
+ IF (allocated (synop_idx)) deallocate (synop_idx)
+ IF (allocated (site_id_rank)) deallocate (site_id_rank)
+ IF (allocated (tref_ens_rank)) deallocate (tref_ens_rank)
+ IF (allocated (qref_ens_rank)) deallocate (qref_ens_rank)
+ IF (allocated (qref_ens_o)) deallocate (qref_ens_o)
+ IF (allocated (tref_ens_o)) deallocate (tref_ens_o)
+
+
+
+ END SUBROUTINE run_DA_SM
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE end_DA_SM()
+
+!-----------------------------------------------------------------------------
+ IMPLICIT NONE
+
+!-----------------------------------------------------------------------------
+ IF (allocated (trans)) deallocate (trans)
+ IF (allocated (obs_err)) deallocate (obs_err)
+ IF (allocated (filter )) deallocate (filter )
+ IF (allocated (wliq_soi_ens)) deallocate (wliq_soi_ens)
+ IF (allocated (wliq_soi_ens_da)) deallocate (wliq_soi_ens_da)
+ IF (allocated (t_soi_ens)) deallocate (t_soi_ens)
+ IF (allocated (t_soi_ens_da)) deallocate (t_soi_ens_da)
+
+ IF (allocated (smap_time)) deallocate (smap_time)
+ IF (allocated (dt_b_smap)) deallocate (dt_b_smap)
+ IF (allocated (dt_e_smap)) deallocate (dt_e_smap)
+ IF (allocated (smap_lat)) deallocate (smap_lat)
+ IF (allocated (smap_lon)) deallocate (smap_lon)
+ IF (allocated (smap_tb_h)) deallocate (smap_tb_h)
+ IF (allocated (smap_tb_v)) deallocate (smap_tb_v)
+ IF (allocated (smap_ii)) deallocate (smap_ii)
+ IF (allocated (smap_jj)) deallocate (smap_jj)
+ IF (allocated (smap_tb_h_mean)) deallocate (smap_tb_h_mean)
+ IF (allocated (smap_tb_v_mean)) deallocate (smap_tb_v_mean)
+ IF (allocated (pred_smap_tb_h_mean)) deallocate (pred_smap_tb_h_mean)
+ IF (allocated (pred_smap_tb_v_mean)) deallocate (pred_smap_tb_v_mean)
+ IF (allocated (pred_smap_tb_h_pset_ens)) deallocate (pred_smap_tb_h_pset_ens)
+ IF (allocated (pred_smap_tb_v_pset_ens)) deallocate (pred_smap_tb_v_pset_ens)
+ IF (allocated (pred_smap_tb_h_ogrid_ens)) deallocate (pred_smap_tb_h_ogrid_ens)
+ IF (allocated (pred_smap_tb_v_ogrid_ens)) deallocate (pred_smap_tb_v_ogrid_ens)
+
+ IF (allocated (fy3d_time)) deallocate (fy3d_time)
+ IF (allocated (dt_b_fy3d)) deallocate (dt_b_fy3d)
+ IF (allocated (dt_e_fy3d)) deallocate (dt_e_fy3d)
+ IF (allocated (fy3d_lat)) deallocate (fy3d_lat)
+ IF (allocated (fy3d_lon)) deallocate (fy3d_lon)
+ IF (allocated (fy3d_tb_h)) deallocate (fy3d_tb_h)
+ IF (allocated (fy3d_tb_v)) deallocate (fy3d_tb_v)
+ IF (allocated (fy3d_ii)) deallocate (fy3d_ii)
+ IF (allocated (fy3d_jj)) deallocate (fy3d_jj)
+ IF (allocated (fy3d_tb_h_mean)) deallocate (fy3d_tb_h_mean)
+ IF (allocated (fy3d_tb_v_mean)) deallocate (fy3d_tb_v_mean)
+ IF (allocated (pred_fy3d_tb_h_mean)) deallocate (pred_fy3d_tb_h_mean)
+ IF (allocated (pred_fy3d_tb_v_mean)) deallocate (pred_fy3d_tb_v_mean)
+ IF (allocated (pred_fy3d_tb_h_pset_ens)) deallocate (pred_fy3d_tb_h_pset_ens)
+ IF (allocated (pred_fy3d_tb_v_pset_ens)) deallocate (pred_fy3d_tb_v_pset_ens)
+ IF (allocated (pred_fy3d_tb_h_ogrid_ens)) deallocate (pred_fy3d_tb_h_ogrid_ens)
+ IF (allocated (pred_fy3d_tb_v_ogrid_ens)) deallocate (pred_fy3d_tb_v_ogrid_ens)
+
+ IF (allocated (synop_time)) deallocate (synop_time)
+ IF (allocated (synop_lat)) deallocate (synop_lat)
+ IF (allocated (synop_lon)) deallocate (synop_lon)
+ IF (allocated (synop_qref)) deallocate (synop_qref)
+ IF (allocated (synop_tref)) deallocate (synop_tref)
+ IF (allocated (tref_ens_o)) deallocate (tref_ens_o)
+ IF (allocated (qref_ens_o)) deallocate (qref_ens_o)
+
+ IF (allocated (synop_idx)) deallocate (synop_idx)
+ IF (allocated (site_id_rank)) deallocate (site_id_rank)
+ IF (allocated (tref_ens_rank)) deallocate (tref_ens_rank)
+ IF (allocated (qref_ens_rank)) deallocate (qref_ens_rank)
+ IF (allocated (qref_ens_o)) deallocate (qref_ens_o)
+ IF (allocated (tref_ens_o)) deallocate (tref_ens_o)
+
+
+ END SUBROUTINE end_DA_SM
+
+!-----------------------------------------------------------------------------
+END MODULE MOD_DA_SM
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_TWS.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_TWS.F90
new file mode 100644
index 0000000000..90d2e17f9a
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_TWS.F90
@@ -0,0 +1,440 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_TWS
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! Data assimilation of terrestrial water storge from GRACE satellite
+!
+! AUTHOR:
+! Shupeng Zhang: Initial version
+!-----------------------------------------------------------------------------
+ USE MOD_DataType
+ USE MOD_SpatialMapping
+
+ IMPLICIT NONE
+
+ PUBLIC :: init_DA_GRACE
+ PUBLIC :: run_DA_GRACE
+ PUBLIC :: end_DA_GRACE
+
+ real(r8), allocatable, PUBLIC :: fslp_k_mon (:,:) ! slope factor of runoff
+ real(r8), allocatable, PUBLIC :: fslp_k (:) ! slope factor of runoff
+
+ PRIVATE
+
+ character(len=256) :: file_grace
+ type(grid_type) :: grid_grace
+
+ real(r8), allocatable :: longrace(:)
+ real(r8), allocatable :: latgrace(:)
+
+ integer :: nobstime
+ integer, allocatable :: obsyear (:)
+ integer, allocatable :: obsmonth (:)
+
+ type (spatial_mapping_type) :: mg2p_grace
+
+ real(r8), allocatable :: lwe_obs_this (:)
+ real(r8), allocatable :: err_obs_this (:)
+
+ real(r8), allocatable :: lwe_obs_prev (:)
+ real(r8), allocatable :: err_obs_prev (:)
+
+ real(r8), allocatable :: wat_prev_m (:)
+ real(r8), allocatable :: wat_this_m (:)
+
+ real(r8), allocatable :: rnof_acc_prev_m (:)
+ real(r8), allocatable :: rnof_acc_this_m (:)
+ real(r8), allocatable :: zwt_acc_prev_m (:)
+ real(r8), allocatable :: zwt_acc_this_m (:)
+
+ real(r8), allocatable :: rnof_prev_m0 (:)
+ real(r8), allocatable :: rnof_prev_m1 (:)
+ real(r8), allocatable :: rnof_this_m (:)
+
+ logical, allocatable :: rnofmask (:)
+
+ logical :: has_prev_grace_obs
+ integer :: nac_grace_this, nac_grace_prev
+
+ integer :: year_prev, month_prev
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE init_DA_GRACE ()
+
+ USE MOD_Spmd_Task
+ USE MOD_Namelist, only : DEF_DA_obsdir
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh, only : numelm
+ USE MOD_LandElm, only : landelm
+ USE MOD_LandPatch
+#ifdef CROP
+ USE MOD_LandCrop
+#endif
+ USE MOD_Pixelset
+ USE MOD_Vars_TimeInvariants, only : patchtype
+ USE MOD_Forcing, only : forcmask_pch
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ ! Local Variables
+
+ real(r8), allocatable :: time_real8(:)
+ integer :: itime
+
+ file_grace = trim(DEF_DA_obsdir) &
+ // '/GRACE_JPL/GRCTellus.JPL.200204_202207.GLO.RL06M.MSCNv02CRI.nc'
+
+ CALL ncio_read_bcast_serial (file_grace, 'time', time_real8)
+
+ nobstime = size(time_real8)
+ allocate (obsyear (nobstime))
+ allocate (obsmonth(nobstime))
+
+ DO itime = 1, nobstime
+ CALL retrieve_yymm_from_days (time_real8(itime), obsyear(itime), obsmonth(itime))
+ ENDDO
+
+ IF (p_is_root) THEN
+ write(*,*) 'Assimilate GRACE data at'
+ DO itime = 1, nobstime
+ write(*,*) obsyear(itime), obsmonth(itime)
+ ENDDO
+ ENDIF
+
+ CALL ncio_read_bcast_serial (file_grace, 'lon', longrace)
+ CALL ncio_read_bcast_serial (file_grace, 'lat', latgrace)
+
+ CALL grid_grace%define_by_center (latgrace,longrace)
+
+ CALL mg2p_grace%build_arealweighted (grid_grace, landelm)
+
+ IF (p_is_compute) THEN
+ IF (numelm > 0) THEN
+ allocate (lwe_obs_this (numelm))
+ allocate (err_obs_this (numelm))
+ allocate (lwe_obs_prev (numelm))
+ allocate (err_obs_prev (numelm))
+ ENDIF
+
+ IF (numpatch > 0) THEN
+ allocate (wat_prev_m (numpatch))
+ allocate (wat_this_m (numpatch))
+ allocate (rnof_acc_prev_m (numpatch))
+ allocate (rnof_acc_this_m (numpatch))
+ allocate (zwt_acc_prev_m (numpatch))
+ allocate (zwt_acc_this_m (numpatch))
+ allocate (rnof_prev_m0 (numpatch))
+ allocate (rnof_prev_m1 (numpatch))
+ allocate (rnof_this_m (numpatch))
+ allocate (rnofmask (numpatch))
+
+ allocate (fslp_k_mon (12,numpatch))
+ allocate (fslp_k (numpatch))
+ ENDIF
+ ENDIF
+
+ IF (p_is_compute) THEN
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ rnofmask = patchtype == 0
+ IF (DEF_forcing%has_missing_value) THEN
+ rnofmask = rnofmask .and. forcmask_pch
+ ENDIF
+ ENDIF
+ ENDIF
+
+
+ has_prev_grace_obs = .false.
+
+ nac_grace_this = 0
+ nac_grace_prev = 0
+
+ IF (p_is_compute) THEN
+ wat_this_m (:) = 0.
+ rnof_acc_this_m(:) = 0.
+ rnof_this_m (:) = 0.
+ zwt_acc_this_m (:) = 0.
+ fslp_k_mon (:,:) = 1.0
+ fslp_k (:) = 1.0
+ ENDIF
+
+ deallocate (time_real8)
+
+ END SUBROUTINE init_DA_GRACE
+
+ ! ----------
+ SUBROUTINE run_DA_GRACE (idate, deltim)
+
+ USE MOD_Spmd_task
+ USE MOD_TimeManager
+ USE MOD_NetCDFBlock
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_LandPatch
+ USE MOD_Vars_1DFluxes, only : rnof, rsur
+ USE MOD_Vars_TimeVariables, only : wat, wa, wdsrf, zwt
+ USE MOD_RangeCheck
+ USE MOD_UserDefFun
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+
+ ! Local Variables
+ logical :: is_obs_time
+ integer :: month, mday, itime, ielm, istt, iend, nextmonth
+
+ real(r8) :: sumpct
+ real(r8) :: w1, w0, r1, r0, var_o, var_m, dw_f, dw_o, dw_a, rr, zwt_ave
+ real(r8) :: fscal, fprev, fthis
+
+ type(block_data_real8_2d) :: f_grace_lwe ! unit: cm
+ type(block_data_real8_2d) :: f_grace_err ! unit: cm
+
+ character(len=256) :: sid, logfile
+
+ CALL julian2monthday (idate(1), idate(2), month, mday)
+
+ is_obs_time = any((obsyear == idate(1)) .and. (obsmonth == month))
+
+ IF (p_is_root) THEN
+ IF (is_obs_time) THEN
+ write(*,*) 'GRACE at this time.'
+ ENDIF
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (has_prev_grace_obs) THEN
+
+ nac_grace_prev = nac_grace_prev + 1
+
+ rnof_acc_prev_m = rnof_acc_prev_m + rnof * deltim
+ IF (is_obs_time) THEN
+ rnof_prev_m1 = rnof_prev_m1 + rnof_acc_prev_m
+ ENDIF
+
+ zwt_acc_prev_m = zwt_acc_prev_m + zwt
+ ENDIF
+
+ IF (is_obs_time) THEN
+
+ nac_grace_this = nac_grace_this + 1
+
+ wat_this_m = wat_this_m + wat + wa + wdsrf
+
+ rnof_acc_this_m = rnof_acc_this_m + rnof * deltim
+ rnof_this_m = rnof_this_m + rnof_acc_this_m
+
+ zwt_acc_this_m = zwt_acc_this_m + zwt
+ ENDIF
+
+ ENDIF
+
+ IF (is_obs_time .and. (isendofmonth(idate, deltim))) THEN
+
+ itime = findloc_ud((obsyear == idate(1)) .and. (obsmonth == month))
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_grace, f_grace_lwe)
+ CALL allocate_block_data (grid_grace, f_grace_err)
+ CALL ncio_read_block_time (file_grace, 'lwe_thickness', grid_grace, itime, f_grace_lwe)
+ CALL ncio_read_block_time (file_grace, 'uncertainty' , grid_grace, itime, f_grace_err)
+ ENDIF
+
+ CALL mg2p_grace%grid2pset (f_grace_lwe, lwe_obs_this)
+ CALL mg2p_grace%grid2pset (f_grace_err, err_obs_this)
+
+ IF (p_is_compute) THEN
+
+ lwe_obs_this = lwe_obs_this * 10.0 ! from cm to mm
+ err_obs_this = err_obs_this * 10.0 ! from cm to mm
+
+ wat_this_m = wat_this_m / nac_grace_this
+
+ zwt_acc_prev_m = zwt_acc_prev_m / nac_grace_prev
+
+ IF (has_prev_grace_obs) THEN
+ rnof_prev_m1 = rnof_prev_m1 / nac_grace_this
+ ENDIF
+
+ IF (has_prev_grace_obs .and. &
+ (((idate(1) == year_prev) .and. (month_prev == month-1)) &
+ .or. ((idate(1) == year_prev+1) .and. (month_prev == 12) .and. (month == 1)))) &
+ THEN
+
+ ! write(sid,'(I0)') p_iam_compute
+ ! logfile = 'log/grace_log_' // trim(sid) // '.txt'
+ ! open(12, file = trim(logfile), position = 'append')
+
+ DO ielm = 1, numelm
+ istt = elm_patch%substt(ielm)
+ iend = elm_patch%subend(ielm)
+
+ sumpct = sum(elm_patch%subfrc(istt:iend), mask = rnofmask(istt:iend))
+
+ IF (sumpct <= 0) THEN
+ CYCLE
+ ENDIF
+
+ w1 = sum(wat_this_m (istt:iend) * elm_patch%subfrc(istt:iend), &
+ mask = rnofmask(istt:iend)) / sumpct
+ w0 = sum(wat_prev_m (istt:iend) * elm_patch%subfrc(istt:iend), &
+ mask = rnofmask(istt:iend)) / sumpct
+ r1 = sum(rnof_prev_m1(istt:iend) * elm_patch%subfrc(istt:iend), &
+ mask = rnofmask(istt:iend)) / sumpct
+ r0 = sum(rnof_prev_m0(istt:iend) * elm_patch%subfrc(istt:iend), &
+ mask = rnofmask(istt:iend)) / sumpct
+
+ zwt_ave = sum(zwt_acc_prev_m(istt:iend) * elm_patch%subfrc(istt:iend), &
+ mask = rnofmask(istt:iend)) / sumpct
+
+
+ var_o = err_obs_this(ielm)**2 + err_obs_prev(ielm)**2
+
+ dw_f = w1 - w0
+ dw_o = lwe_obs_this(ielm) - lwe_obs_prev(ielm)
+ var_m = (dw_f-dw_o)**2 - var_o
+
+ IF (var_m > 0) THEN
+
+ dw_a = (var_o * dw_f + var_m * dw_o) / (var_m+var_o)
+
+ rr = r1 - r0
+
+ IF (rr > 0) THEN
+
+ fscal = (1-(dw_a-dw_f)/rr)
+
+ ! (2) method 2: one parameters adjusted
+ fprev = fslp_k_mon(month,istt)
+ fthis = fprev * fscal
+ fthis = min(max(fthis, fprev*0.5), fprev*2.0)
+ fslp_k_mon(month,istt:iend) = fthis
+
+ fprev = fslp_k_mon(month_prev,istt)
+ fthis = fprev * fscal
+ fthis = min(max(fthis, fprev*0.5), fprev*2.0)
+ fslp_k_mon(month_prev,istt:iend) = fthis
+
+ ! write(12,'(I4,I3,I8,8ES11.2)') idate(1), month, landelm%eindex(ielm), &
+ ! dw_o, sqrt(var_o), dw_f, sqrt(var_m), dw_a, &
+ ! rr, zwt_ave, fscal
+
+ ENDIF
+
+ ENDIF
+
+ ENDDO
+
+ ! close(12)
+ ENDIF
+
+ lwe_obs_prev = lwe_obs_this
+ err_obs_prev = err_obs_this
+
+ wat_prev_m = wat_this_m
+ wat_this_m = 0.
+
+ rnof_acc_prev_m = rnof_acc_this_m
+ rnof_acc_this_m = 0.
+
+ zwt_acc_prev_m = zwt_acc_this_m
+ zwt_acc_this_m = 0.
+
+ rnof_prev_m0 = rnof_this_m / nac_grace_this
+ rnof_prev_m1 = 0.
+ rnof_this_m = 0.
+
+ nac_grace_prev = nac_grace_this
+ nac_grace_this = 0
+
+ ENDIF
+
+ has_prev_grace_obs = .true.
+ year_prev = idate(1)
+ month_prev = month
+
+ ENDIF
+
+ IF (isendofmonth(idate, deltim)) THEN
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ nextmonth = mod(month+1,12)+1
+ fslp_k = fslp_k_mon(nextmonth,:)
+ ENDIF
+ ENDIF
+
+
+ END SUBROUTINE run_DA_GRACE
+
+ ! ---------
+ SUBROUTINE end_DA_GRACE ()
+
+ IMPLICIT NONE
+
+ IF (allocated(lwe_obs_this)) deallocate(lwe_obs_this)
+ IF (allocated(err_obs_this)) deallocate(err_obs_this)
+ IF (allocated(lwe_obs_prev)) deallocate(lwe_obs_prev)
+ IF (allocated(err_obs_prev)) deallocate(err_obs_prev)
+ IF (allocated(wat_prev_m )) deallocate(wat_prev_m )
+ IF (allocated(wat_this_m )) deallocate(wat_this_m )
+ IF (allocated(rnof_acc_prev_m)) deallocate(rnof_acc_prev_m)
+ IF (allocated(rnof_acc_this_m)) deallocate(rnof_acc_this_m)
+ IF (allocated(rnof_prev_m0 )) deallocate(rnof_prev_m0 )
+ IF (allocated(rnof_prev_m1 )) deallocate(rnof_prev_m1 )
+ IF (allocated(rnof_this_m )) deallocate(rnof_this_m )
+ IF (allocated(rnofmask )) deallocate(rnofmask )
+
+ IF (allocated(fslp_k_mon)) deallocate(fslp_k_mon)
+ IF (allocated(fslp_k)) deallocate(fslp_k)
+
+ IF (allocated(longrace)) deallocate(longrace)
+ IF (allocated(latgrace)) deallocate(latgrace)
+
+ END SUBROUTINE end_DA_GRACE
+
+ ! ---------
+ SUBROUTINE retrieve_yymm_from_days (days, yy, mm)
+
+ IMPLICIT NONE
+ real(r8), intent(in) :: days
+ integer, intent(out) :: yy, mm
+
+ ! Local Variables
+ real(r8) :: resday
+ integer :: mdays(12)
+
+ yy = 2002
+ mm = 1
+ mdays = (/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/)
+
+ resday = days
+ DO WHILE (resday > mdays(mm))
+
+ resday = resday - mdays(mm)
+
+ mm = mm + 1
+ IF (mm > 12) THEN
+ yy = yy + 1
+ mm = 1
+ IF( (mod(yy,4)==0 .and. mod(yy,100)/=0) .or. mod(yy,400)==0 ) THEN
+ mdays(2) = 29
+ ELSE
+ mdays(2) = 28
+ ENDIF
+ ENDIF
+
+ ENDDO
+
+ END SUBROUTINE retrieve_yymm_from_days
+
+END MODULE MOD_DA_TWS
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Vars_1DFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Vars_1DFluxes.F90
new file mode 100644
index 0000000000..eb71a15d76
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Vars_1DFluxes.F90
@@ -0,0 +1,92 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_Vars_1DFluxes
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! Process fluxes variables for diagnostic for data assimilation
+!
+! AUTHOR:
+! Lu Li, 07/2025: Initial version
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_DA_ENS_NUM
+ IMPLICIT NONE
+ SAVE
+
+ ! public functions
+ PUBLIC :: allocate_1D_DAFluxes
+ PUBLIC :: deallocate_1D_DAFluxes
+
+ ! define variables
+ real(r8), allocatable :: fsena_ens (:,:) ! sensible heat from canopy height to atmosphere [W/m2]
+ real(r8), allocatable :: lfevpa_ens (:,:) ! latent heat flux from canopy height to atmosphere [W/m2]
+ real(r8), allocatable :: fevpa_ens (:,:) ! evapotranspiration from canopy to atmosphere [mm/s]
+ real(r8), allocatable :: rsur_ens (:,:) ! surface runoff (mm h2o/s)
+
+ ! save for analysis increment
+ real(r8), allocatable :: fsena_a (:) !
+ real(r8), allocatable :: fevpa_a (:) !
+ real(r8), allocatable :: lfevpa_a (:) !
+ real(r8), allocatable :: rsur_a (:) !
+
+!-----------------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_DAFluxes ()
+
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+!-----------------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate ( fsena_ens (DEF_DA_ENS_NUM, numpatch) ) ; fsena_ens (:,:) = spval
+ allocate ( lfevpa_ens (DEF_DA_ENS_NUM, numpatch) ) ; lfevpa_ens (:,:) = spval
+ allocate ( fevpa_ens (DEF_DA_ENS_NUM, numpatch) ) ; fevpa_ens (:,:) = spval
+ allocate ( rsur_ens (DEF_DA_ENS_NUM, numpatch) ) ; rsur_ens (:,:) = spval
+
+ allocate ( fsena_a (numpatch) ) ; fsena_a (:) = spval
+ allocate ( fevpa_a (numpatch) ) ; fevpa_a (:) = spval
+ allocate ( lfevpa_a (numpatch) ) ; lfevpa_a (:) = spval
+ allocate ( rsur_a (numpatch) ) ; rsur_a (:) = spval
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE allocate_1D_DAFluxes
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE deallocate_1D_DAFluxes()
+
+!-----------------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+
+!-----------------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ deallocate ( fsena_ens )
+ deallocate ( lfevpa_ens )
+ deallocate ( fevpa_ens )
+ deallocate ( rsur_ens )
+
+ deallocate ( fsena_a )
+ deallocate ( fevpa_a )
+ deallocate ( lfevpa_a )
+ deallocate ( rsur_a )
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_1D_DAFluxes
+
+!-----------------------------------------------------------------------------
+END MODULE MOD_DA_Vars_1DFluxes
+#endif
\ No newline at end of file
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Vars_TimeVariables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Vars_TimeVariables.F90
new file mode 100644
index 0000000000..c082dcdfac
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/DA/MOD_DA_Vars_TimeVariables.F90
@@ -0,0 +1,716 @@
+#include
+
+#ifdef DataAssimilation
+MODULE MOD_DA_Vars_TimeVariables
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! Process time-varying state variables for data assimilation
+!
+! AUTHOR:
+! Lu Li, 12/2024: Initial version
+! Lu Li, 07/2025: Remove unused variables and clean codes
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_TimeManager
+ USE MOD_Namelist, only: DEF_DA_ENS_NUM
+ IMPLICIT NONE
+ SAVE
+
+ ! public functions
+ PUBLIC :: allocate_DATimeVariables
+ PUBLIC :: deallocate_DATimeVariables
+ PUBLIC :: READ_DATimeVariables
+ PUBLIC :: WRITE_DATimeVariables
+#ifdef RangeCheck
+ PUBLIC :: check_DATimeVariables
+#endif
+
+ ! define variables
+ ! Time-varying state variables which required by restart run, used to store tha noda trajectory state variable
+ real(r8), allocatable :: z_sno_noda (:,:) ! node depth [m]
+ real(r8), allocatable :: dz_sno_noda (:,:) ! interface depth [m]
+ real(r8), allocatable :: t_soisno_noda (:,:) ! soil temperature [K]
+ real(r8), allocatable :: wliq_soisno_noda (:,:) ! liquid water in layers [kg/m2]
+ real(r8), allocatable :: wice_soisno_noda (:,:) ! ice lens in layers [kg/m2]
+ real(r8), allocatable :: smp_noda (:,:) ! soil matrix potential [mm]
+ real(r8), allocatable :: hk_noda (:,:) ! hydraulic conductivity [mm h2o/s]
+ real(r8), allocatable :: t_grnd_noda (:) ! ground surface temperature [K]
+ real(r8), allocatable :: tleaf_noda (:) ! leaf temperature [K]
+ real(r8), allocatable :: ldew_noda (:) ! depth of water on foliage [mm]
+ real(r8), allocatable :: ldew_rain_noda (:) ! depth of rain on foliage [mm]
+ real(r8), allocatable :: ldew_snow_noda (:) ! depth of rain on foliage [mm]
+ real(r8), allocatable :: fwet_snow_noda (:) ! vegetation snow fractional cover [-]
+ real(r8), allocatable :: sag_noda (:) ! non dimensional snow age [-]
+ real(r8), allocatable :: scv_noda (:) ! snow cover, water equivalent [mm]
+ real(r8), allocatable :: snowdp_noda (:) ! snow depth [meter]
+ real(r8), allocatable :: fveg_noda (:) ! fraction of vegetation cover
+ real(r8), allocatable :: fsno_noda (:) ! fraction of snow cover on ground
+ real(r8), allocatable :: sigf_noda (:) ! fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), allocatable :: green_noda (:) ! leaf greenness
+ real(r8), allocatable :: tlai_noda (:) ! leaf area index
+ real(r8), allocatable :: lai_noda (:) ! leaf area index
+ real(r8), allocatable :: tsai_noda (:) ! stem area index
+ real(r8), allocatable :: sai_noda (:) ! stem area index
+ real(r8), allocatable :: alb_noda (:,:,:) ! averaged albedo [-]
+ real(r8), allocatable :: ssun_noda (:,:,:) ! sunlit canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssha_noda (:,:,:) ! shaded canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssoi_noda (:,:,:) ! soil absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssno_noda (:,:,:) ! snow absorption for solar radiation (0-1)
+ real(r8), allocatable :: thermk_noda (:) ! canopy gap fraction for tir radiation
+ real(r8), allocatable :: extkb_noda (:) ! (k, g(mu)/mu) direct solar extinction coefficient
+ real(r8), allocatable :: extkd_noda (:) ! diffuse and scattered diffuse PAR extinction coefficient
+ real(r8), allocatable :: zwt_noda (:) ! the depth to water table [m]
+ real(r8), allocatable :: wdsrf_noda (:) ! depth of surface water [mm]
+ real(r8), allocatable :: wa_noda (:) ! water storage in aquifer [mm]
+ real(r8), allocatable :: wetwat_noda (:) ! water storage in wetland [mm]
+ real(r8), allocatable :: t_lake_noda (:,:) ! lake layer teperature [K]
+ real(r8), allocatable :: lake_icefrac_noda(:,:) ! lake mass fraction of lake layer that is frozen
+ real(r8), allocatable :: savedtke1_noda (:) ! top level eddy conductivity (W/m K)
+
+ ! diagnostic variables for RTM forward operator
+ real(r8), allocatable :: tref_noda (:) ! 2 m height air temperature [kelvin]
+ real(r8), allocatable :: h2osoi_noda (:,:) ! volumetric soil water in layers [m3/m3]
+
+ ! Time-varying state variables which required by restart run
+ real(r8), allocatable :: z_sno_ens (:,:,:) ! node depth [m]
+ real(r8), allocatable :: dz_sno_ens (:,:,:) ! interface depth [m]
+ real(r8), allocatable :: t_soisno_ens (:,:,:) ! soil temperature [K]
+ real(r8), allocatable :: wliq_soisno_ens (:,:,:) ! liquid water in layers [kg/m2]
+ real(r8), allocatable :: wice_soisno_ens (:,:,:) ! ice lens in layers [kg/m2]
+ real(r8), allocatable :: smp_ens (:,:,:) ! soil matrix potential [mm]
+ real(r8), allocatable :: hk_ens (:,:,:) ! hydraulic conductivity [mm h2o/s]
+ real(r8), allocatable :: t_grnd_ens (:,:) ! ground surface temperature [K]
+ real(r8), allocatable :: tleaf_ens (:,:) ! leaf temperature [K]
+ real(r8), allocatable :: ldew_ens (:,:) ! depth of water on foliage [mm]
+ real(r8), allocatable :: ldew_rain_ens (:,:) ! depth of rain on foliage [mm]
+ real(r8), allocatable :: ldew_snow_ens (:,:) ! depth of rain on foliage [mm]
+ real(r8), allocatable :: fwet_snow_ens (:,:) ! vegetation snow fractional cover [-]
+ real(r8), allocatable :: sag_ens (:,:) ! non dimensional snow age [-]
+ real(r8), allocatable :: scv_ens (:,:) ! snow cover, water equivalent [mm]
+ real(r8), allocatable :: snowdp_ens (:,:) ! snow depth [meter]
+ real(r8), allocatable :: fveg_ens (:,:) ! fraction of vegetation cover
+ real(r8), allocatable :: fsno_ens (:,:) ! fraction of snow cover on ground
+ real(r8), allocatable :: sigf_ens (:,:) ! fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), allocatable :: green_ens (:,:) ! leaf greenness
+ real(r8), allocatable :: tlai_ens (:,:) ! leaf area index
+ real(r8), allocatable :: lai_ens (:,:) ! leaf area index
+ real(r8), allocatable :: tsai_ens (:,:) ! stem area index
+ real(r8), allocatable :: sai_ens (:,:) ! stem area index
+ real(r8), allocatable :: alb_ens (:,:,:,:) ! averaged albedo [-]
+ real(r8), allocatable :: ssun_ens (:,:,:,:) ! sunlit canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssha_ens (:,:,:,:) ! shaded canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssoi_ens (:,:,:,:) ! soil absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssno_ens (:,:,:,:) ! snow absorption for solar radiation (0-1)
+ real(r8), allocatable :: thermk_ens (:,:) ! canopy gap fraction for tir radiation
+ real(r8), allocatable :: extkb_ens (:,:) ! (k, g(mu)/mu) direct solar extinction coefficient
+ real(r8), allocatable :: extkd_ens (:,:) ! diffuse and scattered diffuse PAR extinction coefficient
+ real(r8), allocatable :: zwt_ens (:,:) ! the depth to water table [m]
+ real(r8), allocatable :: wdsrf_ens (:,:) ! depth of surface water [mm]
+ real(r8), allocatable :: wa_ens (:,:) ! water storage in aquifer [mm]
+ real(r8), allocatable :: wetwat_ens (:,:) ! water storage in wetland [mm]
+ real(r8), allocatable :: t_lake_ens (:,:,:) ! lake layer teperature [K]
+ real(r8), allocatable :: lake_icefrac_ens(:,:,:) ! lake mass fraction of lake layer that is frozen
+ real(r8), allocatable :: savedtke1_ens (:,:) ! top level eddy conductivity (W/m K)
+
+ ! diagnostic variables for DA
+ real(r8), allocatable :: h2osoi_ens (:,:,:) ! volumetric soil water in layers [m3/m3]
+ real(r8), allocatable :: t_brt_smap_ens (:,:,:) ! brightness temperature for radiance calculation [K]
+ real(r8), allocatable :: t_brt_fy3d_ens (:,:,:) ! brightness temperature for radiance calculation [K]
+ real(r8), allocatable :: t_brt_smap (:,:) ! brightness temperature for radiance calculation [K]
+ real(r8), allocatable :: t_brt_fy3d (:,:) ! brightness temperature for radiance calculation [K]
+ real(r8), allocatable :: trad_ens (:,:) ! radiative temperature of surface [K]
+ real(r8), allocatable :: tref_ens (:,:) ! 2 m height air temperature [kelvin]
+ real(r8), allocatable :: qref_ens (:,:) ! 2 m height air specific humidity
+ real(r8), allocatable :: rhref_ens (:,:) ! 2 m height air relative humidity
+ real(r8), allocatable :: ustar_ens (:,:) ! u* in similarity theory [m/s]
+ real(r8), allocatable :: qstar_ens (:,:) ! q* in similarity theory [kg/kg]
+ real(r8), allocatable :: tstar_ens (:,:) ! t* in similarity theory [K]
+ real(r8), allocatable :: fm_ens (:,:) ! integral of profile FUNCTION for momentum
+ real(r8), allocatable :: fh_ens (:,:) ! integral of profile FUNCTION for heat
+ real(r8), allocatable :: fq_ens (:,:) ! integral of profile FUNCTION for moisture
+
+ ! ensemble forcing variables used for ensemble DA
+ real(r8), allocatable :: forc_t_ens (:,:) ! temperature [K]
+ real(r8), allocatable :: forc_frl_ens (:,:) ! atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), allocatable :: forc_prc_ens (:,:) ! convective precipitation [mm/s]
+ real(r8), allocatable :: forc_prl_ens (:,:) ! large scale precipitation [mm/s]
+ real(r8), allocatable :: forc_sols_ens (:,:) ! atm vis direct beam solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_soll_ens (:,:) ! atm nir direct beam solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_solsd_ens (:,:) ! atm vis diffuse solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_solld_ens (:,:) ! atm nir diffuse solar rad onto srf [W/m2]
+
+ ! save for analysis increment
+ real(r8), allocatable :: t_soisno_a (:,:) !
+ real(r8), allocatable :: wliq_soisno_a (:,:) !
+ real(r8), allocatable :: wice_soisno_a (:,:) !
+ real(r8), allocatable :: t_grnd_a (:) !
+ real(r8), allocatable :: tleaf_a (:) !
+ real(r8), allocatable :: snowdp_a (:) !
+ real(r8), allocatable :: h2osoi_a (:,:) !
+ real(r8), allocatable :: t_brt_smap_a (:,:) !
+ real(r8), allocatable :: t_brt_fy3d_a (:,:) !
+ real(r8), allocatable :: trad_a (:) !
+ real(r8), allocatable :: tref_a (:) !
+ real(r8), allocatable :: qref_a (:) !
+ real(r8), allocatable :: ustar_a (:) !
+ real(r8), allocatable :: qstar_a (:) !
+ real(r8), allocatable :: tstar_a (:) !
+ real(r8), allocatable :: fm_a (:) !
+ real(r8), allocatable :: fh_a (:) !
+ real(r8), allocatable :: fq_a (:) !
+
+!-----------------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE allocate_DATimeVariables()
+
+!-----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+!-----------------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate (z_sno_noda (maxsnl+1:0, numpatch)); z_sno_noda (:,:) = spval
+ allocate (dz_sno_noda (maxsnl+1:0, numpatch)); dz_sno_noda (:,:) = spval
+ allocate (t_soisno_noda (maxsnl+1:nl_soil,numpatch)); t_soisno_noda (:,:) = spval
+ allocate (wliq_soisno_noda(maxsnl+1:nl_soil,numpatch)); wliq_soisno_noda (:,:) = spval
+ allocate (wice_soisno_noda(maxsnl+1:nl_soil,numpatch)); wice_soisno_noda (:,:) = spval
+ allocate (smp_noda (1:nl_soil,numpatch)); smp_noda (:,:) = spval
+ allocate (hk_noda (1:nl_soil,numpatch)); hk_noda (:,:) = spval
+ allocate (t_grnd_noda (numpatch)); t_grnd_noda (:) = spval
+ allocate (tleaf_noda (numpatch)); tleaf_noda (:) = spval
+ allocate (ldew_noda (numpatch)); ldew_noda (:) = spval
+ allocate (ldew_rain_noda (numpatch)); ldew_rain_noda (:) = spval
+ allocate (ldew_snow_noda (numpatch)); ldew_snow_noda (:) = spval
+ allocate (fwet_snow_noda (numpatch)); fwet_snow_noda (:) = spval
+ allocate (sag_noda (numpatch)); sag_noda (:) = spval
+ allocate (scv_noda (numpatch)); scv_noda (:) = spval
+ allocate (snowdp_noda (numpatch)); snowdp_noda (:) = spval
+ allocate (fveg_noda (numpatch)); fveg_noda (:) = spval
+ allocate (fsno_noda (numpatch)); fsno_noda (:) = spval
+ allocate (sigf_noda (numpatch)); sigf_noda (:) = spval
+ allocate (green_noda (numpatch)); green_noda (:) = spval
+ allocate (tlai_noda (numpatch)); tlai_noda (:) = spval
+ allocate (lai_noda (numpatch)); lai_noda (:) = spval
+ allocate (tsai_noda (numpatch)); tsai_noda (:) = spval
+ allocate (sai_noda (numpatch)); sai_noda (:) = spval
+ allocate (alb_noda (2,2,numpatch)); alb_noda (:,:,:) = spval
+ allocate (ssun_noda (2,2,numpatch)); ssun_noda (:,:,:) = spval
+ allocate (ssha_noda (2,2,numpatch)); ssha_noda (:,:,:) = spval
+ allocate (ssoi_noda (2,2,numpatch)); ssoi_noda (:,:,:) = spval
+ allocate (ssno_noda (2,2,numpatch)); ssno_noda (:,:,:) = spval
+ allocate (thermk_noda (numpatch)); thermk_noda (:) = spval
+ allocate (extkb_noda (numpatch)); extkb_noda (:) = spval
+ allocate (extkd_noda (numpatch)); extkd_noda (:) = spval
+ allocate (zwt_noda (numpatch)); zwt_noda (:) = spval
+ allocate (wdsrf_noda (numpatch)); wdsrf_noda (:) = spval
+ allocate (wa_noda (numpatch)); wa_noda (:) = spval
+ allocate (wetwat_noda (numpatch)); wetwat_noda (:) = spval
+ allocate (t_lake_noda (nl_lake,numpatch)); t_lake_noda (:,:) = spval
+ allocate (lake_icefrac_noda (nl_lake,numpatch)); lake_icefrac_noda(:,:) = spval
+ allocate (savedtke1_noda (numpatch)); savedtke1_noda (:) = spval
+
+ ! diagnostic variables for DA
+ allocate (h2osoi_noda (1:nl_soil,numpatch)); h2osoi_noda (:,:) = spval
+ allocate (tref_noda (numpatch)); tref_noda (:) = spval
+
+ ! allocate all time-varying state variables
+ allocate (z_sno_ens (maxsnl+1:0, DEF_DA_ENS_NUM,numpatch)); z_sno_ens (:,:,:) = spval
+ allocate (dz_sno_ens (maxsnl+1:0, DEF_DA_ENS_NUM,numpatch)); dz_sno_ens (:,:,:) = spval
+ allocate (t_soisno_ens (maxsnl+1:nl_soil,DEF_DA_ENS_NUM,numpatch)); t_soisno_ens (:,:,:) = spval
+ allocate (wliq_soisno_ens(maxsnl+1:nl_soil,DEF_DA_ENS_NUM,numpatch)); wliq_soisno_ens (:,:,:) = spval
+ allocate (wice_soisno_ens(maxsnl+1:nl_soil,DEF_DA_ENS_NUM,numpatch)); wice_soisno_ens (:,:,:) = spval
+ allocate (smp_ens (1:nl_soil,DEF_DA_ENS_NUM,numpatch)); smp_ens (:,:,:) = spval
+ allocate (hk_ens (1:nl_soil,DEF_DA_ENS_NUM,numpatch)); hk_ens (:,:,:) = spval
+ allocate (t_grnd_ens (DEF_DA_ENS_NUM,numpatch)); t_grnd_ens (:,:) = spval
+ allocate (tleaf_ens (DEF_DA_ENS_NUM,numpatch)); tleaf_ens (:,:) = spval
+ allocate (ldew_ens (DEF_DA_ENS_NUM,numpatch)); ldew_ens (:,:) = spval
+ allocate (ldew_rain_ens (DEF_DA_ENS_NUM,numpatch)); ldew_rain_ens (:,:) = spval
+ allocate (ldew_snow_ens (DEF_DA_ENS_NUM,numpatch)); ldew_snow_ens (:,:) = spval
+ allocate (fwet_snow_ens (DEF_DA_ENS_NUM,numpatch)); fwet_snow_ens (:,:) = spval
+ allocate (sag_ens (DEF_DA_ENS_NUM,numpatch)); sag_ens (:,:) = spval
+ allocate (scv_ens (DEF_DA_ENS_NUM,numpatch)); scv_ens (:,:) = spval
+ allocate (snowdp_ens (DEF_DA_ENS_NUM,numpatch)); snowdp_ens (:,:) = spval
+ allocate (fveg_ens (DEF_DA_ENS_NUM,numpatch)); fveg_ens (:,:) = spval
+ allocate (fsno_ens (DEF_DA_ENS_NUM,numpatch)); fsno_ens (:,:) = spval
+ allocate (sigf_ens (DEF_DA_ENS_NUM,numpatch)); sigf_ens (:,:) = spval
+ allocate (green_ens (DEF_DA_ENS_NUM,numpatch)); green_ens (:,:) = spval
+ allocate (tlai_ens (DEF_DA_ENS_NUM,numpatch)); tlai_ens (:,:) = spval
+ allocate (lai_ens (DEF_DA_ENS_NUM,numpatch)); lai_ens (:,:) = spval
+ allocate (tsai_ens (DEF_DA_ENS_NUM,numpatch)); tsai_ens (:,:) = spval
+ allocate (sai_ens (DEF_DA_ENS_NUM,numpatch)); sai_ens (:,:) = spval
+ allocate (alb_ens (2,2,DEF_DA_ENS_NUM,numpatch)); alb_ens (:,:,:,:) = spval
+ allocate (ssun_ens (2,2,DEF_DA_ENS_NUM,numpatch)); ssun_ens (:,:,:,:) = spval
+ allocate (ssha_ens (2,2,DEF_DA_ENS_NUM,numpatch)); ssha_ens (:,:,:,:) = spval
+ allocate (ssoi_ens (2,2,DEF_DA_ENS_NUM,numpatch)); ssoi_ens (:,:,:,:) = spval
+ allocate (ssno_ens (2,2,DEF_DA_ENS_NUM,numpatch)); ssno_ens (:,:,:,:) = spval
+ allocate (thermk_ens (DEF_DA_ENS_NUM,numpatch)); thermk_ens (:,:) = spval
+ allocate (extkb_ens (DEF_DA_ENS_NUM,numpatch)); extkb_ens (:,:) = spval
+ allocate (extkd_ens (DEF_DA_ENS_NUM,numpatch)); extkd_ens (:,:) = spval
+ allocate (zwt_ens (DEF_DA_ENS_NUM,numpatch)); zwt_ens (:,:) = spval
+ allocate (wdsrf_ens (DEF_DA_ENS_NUM,numpatch)); wdsrf_ens (:,:) = spval
+ allocate (wa_ens (DEF_DA_ENS_NUM,numpatch)); wa_ens (:,:) = spval
+ allocate (wetwat_ens (DEF_DA_ENS_NUM,numpatch)); wetwat_ens (:,:) = spval
+ allocate (t_lake_ens (nl_lake,DEF_DA_ENS_NUM,numpatch)); t_lake_ens (:,:,:) = spval
+ allocate (lake_icefrac_ens (nl_lake,DEF_DA_ENS_NUM,numpatch)); lake_icefrac_ens(:,:,:) = spval
+ allocate (savedtke1_ens (DEF_DA_ENS_NUM,numpatch)); savedtke1_ens (:,:) = spval
+
+ ! diagnostic variables for DA
+ allocate (h2osoi_ens (1:nl_soil,DEF_DA_ENS_NUM,numpatch)); h2osoi_ens (:,:,:) = spval
+ allocate (t_brt_smap_ens (2,DEF_DA_ENS_NUM,numpatch)); t_brt_smap_ens (:,:,:) = spval
+ allocate (t_brt_fy3d_ens (2,DEF_DA_ENS_NUM,numpatch)); t_brt_fy3d_ens (:,:,:) = spval
+ allocate (t_brt_smap (2,numpatch)); t_brt_smap (:,:) = spval
+ allocate (t_brt_fy3d (2,numpatch)); t_brt_fy3d (:,:) = spval
+ allocate (trad_ens (DEF_DA_ENS_NUM,numpatch)); trad_ens (:,:) = spval
+ allocate (tref_ens (DEF_DA_ENS_NUM,numpatch)); tref_ens (:,:) = spval
+ allocate (qref_ens (DEF_DA_ENS_NUM,numpatch)); qref_ens (:,:) = spval
+ allocate (rhref_ens (DEF_DA_ENS_NUM,numpatch)); rhref_ens (:,:) = spval
+ allocate (ustar_ens (DEF_DA_ENS_NUM,numpatch)); ustar_ens (:,:) = spval
+ allocate (qstar_ens (DEF_DA_ENS_NUM,numpatch)); qstar_ens (:,:) = spval
+ allocate (tstar_ens (DEF_DA_ENS_NUM,numpatch)); tstar_ens (:,:) = spval
+ allocate (fm_ens (DEF_DA_ENS_NUM,numpatch)); fm_ens (:,:) = spval
+ allocate (fh_ens (DEF_DA_ENS_NUM,numpatch)); fh_ens (:,:) = spval
+ allocate (fq_ens (DEF_DA_ENS_NUM,numpatch)); fq_ens (:,:) = spval
+
+ ! ensemble forcing variables used for ensemble DA
+ allocate (forc_t_ens (DEF_DA_ENS_NUM,numpatch)); forc_t_ens (:,:) = spval
+ allocate (forc_frl_ens (DEF_DA_ENS_NUM,numpatch)); forc_frl_ens (:,:) = spval
+ allocate (forc_prc_ens (DEF_DA_ENS_NUM,numpatch)); forc_prc_ens (:,:) = spval
+ allocate (forc_prl_ens (DEF_DA_ENS_NUM,numpatch)); forc_prl_ens (:,:) = spval
+ allocate (forc_sols_ens (DEF_DA_ENS_NUM,numpatch)); forc_sols_ens (:,:) = spval
+ allocate (forc_soll_ens (DEF_DA_ENS_NUM,numpatch)); forc_soll_ens (:,:) = spval
+ allocate (forc_solsd_ens (DEF_DA_ENS_NUM,numpatch)); forc_solsd_ens (:,:) = spval
+ allocate (forc_solld_ens (DEF_DA_ENS_NUM,numpatch)); forc_solld_ens (:,:) = spval
+
+ ! allocate variables for analysis increment
+ allocate (t_soisno_a (maxsnl+1:nl_soil,numpatch)); t_soisno_a (:,:) = spval
+ allocate (wliq_soisno_a (maxsnl+1:nl_soil,numpatch)); wliq_soisno_a (:,:) = spval
+ allocate (wice_soisno_a (maxsnl+1:nl_soil,numpatch)); wice_soisno_a (:,:) = spval
+ allocate (t_grnd_a (numpatch)); t_grnd_a (:) = spval
+ allocate (tleaf_a (numpatch)); tleaf_a (:) = spval
+ allocate (snowdp_a (numpatch)); snowdp_a (:) = spval
+ allocate (h2osoi_a (1:nl_soil,numpatch)); h2osoi_a (:,:) = spval
+ allocate (t_brt_smap_a (2,numpatch)); t_brt_smap_a (:,:) = spval
+ allocate (t_brt_fy3d_a (2,numpatch)); t_brt_fy3d_a (:,:) = spval
+
+ allocate (trad_a (numpatch)); trad_a (:) = spval
+ allocate (tref_a (numpatch)); tref_a (:) = spval
+ allocate (qref_a (numpatch)); qref_a (:) = spval
+ allocate (ustar_a (numpatch)); ustar_a (:) = spval
+ allocate (qstar_a (numpatch)); qstar_a (:) = spval
+ allocate (tstar_a (numpatch)); tstar_a (:) = spval
+ allocate (fm_a (numpatch)); fm_a (:) = spval
+ allocate (fh_a (numpatch)); fh_a (:) = spval
+ allocate (fq_a (numpatch)); fq_a (:) = spval
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE allocate_DATimeVariables
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE deallocate_DATimeVariables()
+
+!-----------------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+!-----------------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ deallocate (z_sno_noda )
+ deallocate (dz_sno_noda )
+ deallocate (t_soisno_noda )
+ deallocate (wliq_soisno_noda )
+ deallocate (wice_soisno_noda )
+ deallocate (smp_noda )
+ deallocate (hk_noda )
+ deallocate (t_grnd_noda )
+ deallocate (tleaf_noda )
+ deallocate (ldew_noda )
+ deallocate (ldew_rain_noda )
+ deallocate (ldew_snow_noda )
+ deallocate (fwet_snow_noda )
+ deallocate (sag_noda )
+ deallocate (scv_noda )
+ deallocate (snowdp_noda )
+ deallocate (fveg_noda )
+ deallocate (fsno_noda )
+ deallocate (sigf_noda )
+ deallocate (green_noda )
+ deallocate (tlai_noda )
+ deallocate (lai_noda )
+ deallocate (tsai_noda )
+ deallocate (sai_noda )
+ deallocate (alb_noda )
+ deallocate (ssun_noda )
+ deallocate (ssha_noda )
+ deallocate (ssoi_noda )
+ deallocate (ssno_noda )
+ deallocate (thermk_noda )
+ deallocate (extkb_noda )
+ deallocate (extkd_noda )
+ deallocate (zwt_noda )
+ deallocate (wdsrf_noda )
+ deallocate (wa_noda )
+ deallocate (wetwat_noda )
+ deallocate (t_lake_noda )
+ deallocate (lake_icefrac_noda )
+ deallocate (savedtke1_noda )
+
+ deallocate (tref_noda )
+ deallocate (h2osoi_noda )
+
+ deallocate (z_sno_ens )
+ deallocate (dz_sno_ens )
+ deallocate (t_soisno_ens )
+ deallocate (wliq_soisno_ens )
+ deallocate (wice_soisno_ens )
+ deallocate (smp_ens )
+ deallocate (hk_ens )
+ deallocate (t_grnd_ens )
+ deallocate (tleaf_ens )
+ deallocate (ldew_ens )
+ deallocate (ldew_rain_ens )
+ deallocate (ldew_snow_ens )
+ deallocate (fwet_snow_ens )
+ deallocate (sag_ens )
+ deallocate (scv_ens )
+ deallocate (snowdp_ens )
+ deallocate (fveg_ens )
+ deallocate (fsno_ens )
+ deallocate (sigf_ens )
+ deallocate (green_ens )
+ deallocate (tlai_ens )
+ deallocate (lai_ens )
+ deallocate (tsai_ens )
+ deallocate (sai_ens )
+ deallocate (alb_ens )
+ deallocate (ssun_ens )
+ deallocate (ssha_ens )
+ deallocate (ssoi_ens )
+ deallocate (ssno_ens )
+ deallocate (thermk_ens )
+ deallocate (extkb_ens )
+ deallocate (extkd_ens )
+ deallocate (zwt_ens )
+ deallocate (wdsrf_ens )
+ deallocate (wa_ens )
+ deallocate (wetwat_ens )
+ deallocate (t_lake_ens )
+ deallocate (lake_icefrac_ens )
+ deallocate (savedtke1_ens )
+
+ deallocate (h2osoi_ens )
+ deallocate (t_brt_smap_ens )
+ deallocate (t_brt_fy3d_ens )
+ deallocate (t_brt_smap )
+ deallocate (t_brt_fy3d )
+ deallocate (trad_ens )
+ deallocate (tref_ens )
+ deallocate (qref_ens )
+ deallocate (rhref_ens )
+ deallocate (ustar_ens )
+ deallocate (qstar_ens )
+ deallocate (tstar_ens )
+ deallocate (fm_ens )
+ deallocate (fh_ens )
+ deallocate (fq_ens )
+
+ deallocate (forc_t_ens )
+ deallocate (forc_frl_ens )
+ deallocate (forc_prc_ens )
+ deallocate (forc_prl_ens )
+ deallocate (forc_sols_ens )
+ deallocate (forc_soll_ens )
+ deallocate (forc_solsd_ens )
+ deallocate (forc_solld_ens )
+
+ deallocate (t_soisno_a )
+ deallocate (wliq_soisno_a )
+ deallocate (wice_soisno_a )
+ deallocate (t_grnd_a )
+ deallocate (tleaf_a )
+ deallocate (snowdp_a )
+ deallocate (h2osoi_a )
+ deallocate (t_brt_smap_a )
+ deallocate (t_brt_fy3d_a )
+ deallocate (trad_a )
+ deallocate (tref_a )
+ deallocate (qref_a )
+ deallocate (ustar_a )
+ deallocate (qstar_a )
+ deallocate (tstar_a )
+ deallocate (fm_a )
+ deallocate (fh_a )
+ deallocate (fq_a )
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_DATimeVariables
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE WRITE_DATimeVariables (idate, lc_year, site, dir_restart)
+
+!-----------------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only : DEF_REST_CompressLevel, DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, &
+ DEF_USE_IRRIGATION, DEF_USE_Dynamic_Lake
+ USE MOD_LandPatch
+ USE MOD_NetCDFVector
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+!------------------------ Dummy Arguments ------------------------------------
+ integer, intent(in) :: idate(3)
+ integer, intent(in) :: lc_year ! year of land cover type data
+ character(len=*), intent(in) :: site
+ character(len=*), intent(in) :: dir_restart
+
+!------------------------ Local Variables ------------------------------------
+ character(len=256) :: file_restart
+ character(len=14) :: cdate
+ character(len=256) :: cyear ! character for lc_year
+ integer :: compress
+ integer :: i
+
+!-----------------------------------------------------------------------------
+ compress = DEF_REST_CompressLevel
+
+ ! land cover type year
+ write(cyear,'(i4.4)') lc_year
+ write(cdate,'(i4.4,"-",i3.3,"-",i5.5)') idate(1), idate(2), idate(3)
+
+ IF (p_is_root) THEN
+ CALL system('mkdir -p ' // trim(dir_restart)//'/'//trim(cdate))
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_DA_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+
+ CALL ncio_create_file_vector (file_restart, landpatch)
+
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'snow', -maxsnl )
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'snowp1', -maxsnl+1 )
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soilsnow', nl_soil-maxsnl)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil', nl_soil)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'lake', nl_lake)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'band', 2)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'rtyp', 2)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'ens', DEF_DA_ENS_NUM)
+
+ ! Time-varying state variables which reaquired by restart run
+ CALL ncio_write_vector (file_restart, 'z_sno ' , 'snow', -maxsnl, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, z_sno_ens, compress) ! node depth [m]
+ CALL ncio_write_vector (file_restart, 'dz_sno ' , 'snow', -maxsnl, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, dz_sno_ens, compress) ! interface depth [m]
+ CALL ncio_write_vector (file_restart, 't_soisno' , 'soilsnow', nl_soil-maxsnl, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, t_soisno_ens, compress) ! soil temperature [K]
+ CALL ncio_write_vector (file_restart, 'wliq_soisno', 'soilsnow', nl_soil-maxsnl, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, wliq_soisno_ens, compress) ! liquid water in layers [kg/m2]
+ CALL ncio_write_vector (file_restart, 'wice_soisno', 'soilsnow', nl_soil-maxsnl, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, wice_soisno_ens, compress) ! ice lens in layers [kg/m2]
+ CALL ncio_write_vector (file_restart, 'smp', 'soil', nl_soil, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, smp_ens, compress) ! soil matrix potential [mm]
+ CALL ncio_write_vector (file_restart, 'hk', 'soil', nl_soil, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, hk_ens, compress) ! hydraulic conductivity [mm h2o/s]
+ CALL ncio_write_vector (file_restart, 't_grnd', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, t_grnd_ens, compress) ! ground surface temperature [K]
+ CALL ncio_write_vector (file_restart, 'tleaf', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, tleaf_ens, compress) ! leaf temperature [K]
+ CALL ncio_write_vector (file_restart, 'ldew', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ldew_ens, compress) ! depth of water on foliage [mm]
+ CALL ncio_write_vector (file_restart, 'ldew_rain', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ldew_rain_ens, compress) ! depth of water on foliage [mm]
+ CALL ncio_write_vector (file_restart, 'ldew_snow', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ldew_snow_ens, compress) ! depth of water on foliage [mm]
+ CALL ncio_write_vector (file_restart, 'fwet_snow', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, fwet_snow_ens, compress) ! vegetation snow fractional cover [-]
+ CALL ncio_write_vector (file_restart, 'sag', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, sag_ens, compress) ! non dimensional snow age [-]
+ CALL ncio_write_vector (file_restart, 'scv', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, scv_ens, compress) ! snow cover, water equivalent [mm]
+ CALL ncio_write_vector (file_restart, 'snowdp', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, snowdp_ens, compress) ! snow depth [meter]
+ CALL ncio_write_vector (file_restart, 'fveg', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, fveg_ens, compress) ! fraction of vegetation cover
+ CALL ncio_write_vector (file_restart, 'fsno', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, fsno_ens, compress) ! fraction of snow cover on ground
+ CALL ncio_write_vector (file_restart, 'sigf', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, sigf_ens, compress) ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL ncio_write_vector (file_restart, 'green', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, green_ens, compress) ! leaf greenness
+ CALL ncio_write_vector (file_restart, 'tlai', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, tlai_ens, compress) ! leaf area index
+ CALL ncio_write_vector (file_restart, 'lai', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, lai_ens, compress) ! leaf area index
+ CALL ncio_write_vector (file_restart, 'tsai', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, tsai_ens, compress) ! stem area index
+ CALL ncio_write_vector (file_restart, 'sai', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, sai_ens, compress) ! stem area index
+ CALL ncio_write_vector (file_restart, 'alb', 'band', 2, 'rtyp', 2, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, alb_ens, compress) ! averaged albedo [-]
+ CALL ncio_write_vector (file_restart, 'ssun', 'band', 2, 'rtyp', 2, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ssun_ens, compress) ! sunlit canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'ssha', 'band', 2, 'rtyp', 2, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ssha_ens, compress) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'ssoi', 'band', 2, 'rtyp', 2, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ssoi_ens, compress) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'ssno', 'band', 2, 'rtyp', 2, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, ssno_ens, compress) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'thermk', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, thermk_ens, compress) ! canopy gap fraction for tir radiation
+ CALL ncio_write_vector (file_restart, 'extkb', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, extkb_ens, compress) ! (k, g(mu)/mu) direct solar extinction coefficient
+ CALL ncio_write_vector (file_restart, 'extkd', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, extkd_ens, compress) ! diffuse and scattered diffuse PAR extinction coefficient
+ CALL ncio_write_vector (file_restart, 'zwt', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, zwt_ens, compress) ! the depth to water table [m]
+ CALL ncio_write_vector (file_restart, 'wdsrf', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, wdsrf_ens, compress) ! depth of surface water [mm]
+ CALL ncio_write_vector (file_restart, 'wa', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, wa_ens, compress) ! water storage in aquifer [mm]
+ CALL ncio_write_vector (file_restart, 'wetwat', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, wetwat_ens, compress) ! water storage in wetland [mm]
+ CALL ncio_write_vector (file_restart, 't_lake', 'lake', nl_lake, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, t_lake_ens, compress)
+ CALL ncio_write_vector (file_restart, 'lake_icefrc', 'lake', nl_lake, 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, lake_icefrac_ens, compress)
+ CALL ncio_write_vector (file_restart, 'savedtke1', 'ens', DEF_DA_ENS_NUM, 'patch', landpatch, savedtke1_ens, compress)
+
+ END SUBROUTINE WRITE_DATimeVariables
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE READ_DATimeVariables (idate, lc_year, site, dir_restart)
+
+!-----------------------------------------------------------------------------
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFVector
+#ifdef RangeCheck
+ USE MOD_RangeCheck
+#endif
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+!------------------------ Dummy Arguments ------------------------------------
+ integer, intent(in) :: idate(3)
+ integer, intent(in) :: lc_year !year of land cover type data
+ character(len=*), intent(in) :: site
+ character(len=*), intent(in) :: dir_restart
+
+!------------------------ Local Variables ------------------------------------
+ character(len=256) :: file_restart
+ character(len=14) :: cdate, cyear
+
+!-----------------------------------------------------------------------------
+#ifdef USEMPI
+ CALL mpi_barrier(p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write (*, *) 'Loading DA Time Variables ...'
+ END IF
+
+ ! land cover type year
+ write (cyear, '(i4.4)') lc_year
+
+ write (cdate, '(i4.4,"-",i3.3,"-",i5.5)') idate(1), idate(2), idate(3)
+ file_restart = trim(dir_restart)//'/'//trim(cdate)//'/'//trim(site)//'_restart_DA_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+
+ ! Time-varying state variables which reaquired by restart run
+ CALL ncio_read_vector(file_restart, 'z_sno ', -maxsnl, DEF_DA_ENS_NUM, landpatch, z_sno_ens) ! node depth [m]
+ CALL ncio_read_vector(file_restart, 'dz_sno ', -maxsnl, DEF_DA_ENS_NUM, landpatch, dz_sno_ens) ! interface depth [m]
+ CALL ncio_read_vector(file_restart, 't_soisno', nl_soil - maxsnl, DEF_DA_ENS_NUM, landpatch, t_soisno_ens) ! soil temperature [K]
+ CALL ncio_read_vector(file_restart, 'wliq_soisno', nl_soil - maxsnl, DEF_DA_ENS_NUM, landpatch, wliq_soisno_ens)! liquid water in layers [kg/m2]
+ CALL ncio_read_vector(file_restart, 'wice_soisno', nl_soil - maxsnl, DEF_DA_ENS_NUM, landpatch, wice_soisno_ens)! ice lens in layers [kg/m2]
+ CALL ncio_read_vector(file_restart, 'smp', nl_soil, DEF_DA_ENS_NUM, landpatch, smp_ens) ! soil matrix potential [mm]
+ CALL ncio_read_vector(file_restart, 'hk', nl_soil, DEF_DA_ENS_NUM, landpatch, hk_ens) ! hydraulic conductivity [mm h2o/s]
+ CALL ncio_read_vector(file_restart, 't_grnd ', DEF_DA_ENS_NUM, landpatch, t_grnd_ens) ! ground surface temperature [K]
+ CALL ncio_read_vector(file_restart, 'tleaf ', DEF_DA_ENS_NUM, landpatch, tleaf_ens) ! leaf temperature [K]
+ CALL ncio_read_vector(file_restart, 'ldew ', DEF_DA_ENS_NUM, landpatch, ldew_ens) ! depth of water on foliage [mm]
+ CALL ncio_read_vector(file_restart, 'ldew_rain', DEF_DA_ENS_NUM, landpatch, ldew_rain_ens) ! depth of water on foliage [mm]
+ CALL ncio_read_vector(file_restart, 'ldew_snow', DEF_DA_ENS_NUM, landpatch, ldew_snow_ens) ! depth of water on foliage [mm]
+ CALL ncio_read_vector(file_restart, 'fwet_snow', DEF_DA_ENS_NUM, landpatch, fwet_snow_ens) ! vegetation snow fractional cover [-]
+ CALL ncio_read_vector(file_restart, 'sag ', DEF_DA_ENS_NUM, landpatch, sag_ens) ! non dimensional snow age [-]
+ CALL ncio_read_vector(file_restart, 'scv ', DEF_DA_ENS_NUM, landpatch, scv_ens) ! snow cover, water equivalent [mm]
+ CALL ncio_read_vector(file_restart, 'snowdp ', DEF_DA_ENS_NUM, landpatch, snowdp_ens) ! snow depth [meter]
+ CALL ncio_read_vector(file_restart, 'fveg ', DEF_DA_ENS_NUM, landpatch, fveg_ens) ! fraction of vegetation cover
+ CALL ncio_read_vector(file_restart, 'fsno ', DEF_DA_ENS_NUM, landpatch, fsno_ens) ! fraction of snow cover on ground
+ CALL ncio_read_vector(file_restart, 'sigf ', DEF_DA_ENS_NUM, landpatch, sigf_ens) ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL ncio_read_vector(file_restart, 'green ', DEF_DA_ENS_NUM, landpatch, green_ens) ! leaf greenness
+ CALL ncio_read_vector(file_restart, 'lai ', DEF_DA_ENS_NUM, landpatch, lai_ens) ! leaf area index
+ CALL ncio_read_vector(file_restart, 'tlai ', DEF_DA_ENS_NUM, landpatch, tlai_ens) ! leaf area index
+ CALL ncio_read_vector(file_restart, 'sai ', DEF_DA_ENS_NUM, landpatch, sai_ens) ! stem area index
+ CALL ncio_read_vector(file_restart, 'tsai ', DEF_DA_ENS_NUM, landpatch, tsai_ens) ! stem area index
+ CALL ncio_read_vector(file_restart, 'alb ', 2, 2, DEF_DA_ENS_NUM, landpatch, alb_ens) ! averaged albedo [-]
+ CALL ncio_read_vector(file_restart, 'ssun ', 2, 2, DEF_DA_ENS_NUM, landpatch, ssun_ens) ! sunlit canopy absorption for solar radiation (0-1)
+ CALL ncio_read_vector(file_restart, 'ssha ', 2, 2, DEF_DA_ENS_NUM, landpatch, ssha_ens) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_read_vector(file_restart, 'ssoi ', 2, 2, DEF_DA_ENS_NUM, landpatch, ssoi_ens) ! soil absorption for solar radiation (0-1)
+ CALL ncio_read_vector(file_restart, 'ssno ', 2, 2, DEF_DA_ENS_NUM, landpatch, ssno_ens) ! snow absorption for solar radiation (0-1)
+ CALL ncio_read_vector(file_restart, 'thermk ', DEF_DA_ENS_NUM, landpatch, thermk_ens) ! canopy gap fraction for tir radiation
+ CALL ncio_read_vector(file_restart, 'extkb ', DEF_DA_ENS_NUM, landpatch, extkb_ens) ! (k, g(mu)/mu) direct solar extinction coefficient
+ CALL ncio_read_vector(file_restart, 'extkd ', DEF_DA_ENS_NUM, landpatch, extkd_ens) ! diffuse and scattered diffuse PAR extinction coefficient
+ CALL ncio_read_vector(file_restart, 'zwt ', DEF_DA_ENS_NUM, landpatch, zwt_ens) ! the depth to water table [m]
+ CALL ncio_read_vector(file_restart, 'wdsrf ', DEF_DA_ENS_NUM, landpatch, wdsrf_ens) ! depth of surface water [mm]
+ CALL ncio_read_vector(file_restart, 'wa ', DEF_DA_ENS_NUM, landpatch, wa_ens) ! water storage in aquifer [mm]
+ CALL ncio_read_vector(file_restart, 'wetwat ', DEF_DA_ENS_NUM, landpatch, wetwat_ens) ! water storage in wetland [mm]
+ CALL ncio_read_vector(file_restart, 't_lake ', nl_lake, DEF_DA_ENS_NUM, landpatch, t_lake_ens) ! lake temperature [K]
+ CALL ncio_read_vector(file_restart, 'lake_icefrc', nl_lake, DEF_DA_ENS_NUM, landpatch, lake_icefrac_ens) ! lake ice fraction [-]
+ CALL ncio_read_vector(file_restart, 'savedtke1 ', DEF_DA_ENS_NUM, landpatch, savedtke1_ens) ! saved tke1 [m2/s2]
+
+#ifdef RangeCheck
+ CALL check_DATimeVariables
+#endif
+
+ IF (p_is_root) THEN
+ write (*, *) 'Loading DA Time Variables done.'
+ END IF
+
+ END SUBROUTINE READ_DATimeVariables
+
+#ifdef RangeCheck
+!-----------------------------------------------------------------------
+
+ SUBROUTINE check_DATimeVariables ()
+
+!-----------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_RangeCheck
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, DEF_USE_IRRIGATION, &
+ DEF_USE_SNICAR, DEF_USE_Dynamic_Lake
+ IMPLICIT NONE
+
+#ifdef USEMPI
+ CALL mpi_barrier(p_comm_glb, p_err)
+#endif
+ IF (p_is_root) THEN
+ write (*, *) 'Checking DA Time Variables ...'
+ END IF
+
+ CALL check_vector_data ('z_sno [m] ', z_sno_ens ) ! node depth [m]
+ CALL check_vector_data ('dz_sno [m] ', dz_sno_ens ) ! interface depth [m]
+ CALL check_vector_data ('t_soisno [K] ', t_soisno_ens ) ! soil temperature [K]
+ CALL check_vector_data ('wliq_soisno [kg/m2]', wliq_soisno_ens ) ! liquid water in layers [kg/m2]
+ CALL check_vector_data ('wice_soisno [kg/m2]', wice_soisno_ens ) ! ice lens in layers [kg/m2]
+ CALL check_vector_data ('smp [mm] ', smp_ens ) ! soil matrix potential [mm]
+ CALL check_vector_data ('hk [mm/s] ', hk_ens ) ! hydraulic conductivity [mm h2o/s]
+ CALL check_vector_data ('t_grnd [K] ', t_grnd_ens ) ! ground surface temperature [K]
+ CALL check_vector_data ('tleaf [K] ', tleaf_ens ) ! leaf temperature [K]
+ CALL check_vector_data ('ldew [mm] ', ldew_ens ) ! depth of water on foliage [mm]
+ CALL check_vector_data ('ldew_rain [mm] ', ldew_rain_ens ) ! depth of rain on foliage [mm]
+ CALL check_vector_data ('ldew_snow [mm] ', ldew_snow_ens ) ! depth of snow on foliage [mm]
+ CALL check_vector_data ('fwet_snow [mm] ', fwet_snow_ens ) ! vegetation snow fractional cover [-]
+ CALL check_vector_data ('sag [-] ', sag_ens ) ! non dimensional snow age [-]
+ CALL check_vector_data ('scv [mm] ', scv_ens ) ! snow cover, water equivalent [mm]
+ CALL check_vector_data ('snowdp [m] ', snowdp_ens ) ! snow depth [meter]
+ CALL check_vector_data ('fveg [-] ', fveg_ens ) ! fraction of vegetation cover
+ CALL check_vector_data ('fsno [-] ', fsno_ens ) ! fraction of snow cover on ground
+ CALL check_vector_data ('sigf [-] ', sigf_ens ) ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL check_vector_data ('green [-] ', green_ens ) ! leaf greenness
+ CALL check_vector_data ('lai [-] ', lai_ens ) ! leaf area index
+ CALL check_vector_data ('tlai [-] ', tlai_ens ) ! leaf area index
+ CALL check_vector_data ('sai [-] ', sai_ens ) ! stem area index
+ CALL check_vector_data ('tsai [-] ', tsai_ens ) ! stem area index
+ CALL check_vector_data ('alb [-] ', alb_ens ) ! averaged albedo [-]
+ CALL check_vector_data ('ssun [-] ', ssun_ens ) ! sunlit canopy absorption for solar radiation (0-1)
+ CALL check_vector_data ('ssha [-] ', ssha_ens ) ! shaded canopy absorption for solar radiation (0-1)
+ CALL check_vector_data ('ssoi [-] ', ssoi_ens ) ! soil absorption for solar radiation (0-1)
+ CALL check_vector_data ('ssno [-] ', ssno_ens ) ! snow absorption for solar radiation (0-1)
+ CALL check_vector_data ('thermk [-] ', thermk_ens ) ! canopy gap fraction for tir radiation
+ CALL check_vector_data ('extkb [-] ', extkb_ens ) ! (k, g(mu)/mu) direct solar extinction coefficient
+ CALL check_vector_data ('extkd [-] ', extkd_ens ) ! diffuse and scattered diffuse PAR extinction coefficient
+ CALL check_vector_data ('zwt [m] ', zwt_ens ) ! the depth to water table [m]
+ CALL check_vector_data ('wdsrf [mm] ', wdsrf_ens ) ! depth of surface water [mm]
+ CALL check_vector_data ('wa [mm] ', wa_ens ) ! water storage in aquifer [mm]
+ CALL check_vector_data ('wetwat [mm] ', wetwat_ens ) ! water storage in wetland [mm]
+ CALL check_vector_data ('t_lake [K] ', t_lake_ens ) ! lake temperature [K]
+ CALL check_vector_data ('lake_icefrc [-] ', lake_icefrac_ens) ! lake ice fraction [-]
+ CALL check_vector_data ('savedtke1 [W/m K]', savedtke1_ens ) ! saved tke1 [m2/s2]
+
+#ifdef USEMPI
+ CALL mpi_barrier(p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE check_DATimeVariables
+!-----------------------------------------------------------------------------
+#endif
+
+END MODULE MOD_DA_Vars_TimeVariables
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_BasinNetwork.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_BasinNetwork.F90
new file mode 100644
index 0000000000..5a864c2a8b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_BasinNetwork.F90
@@ -0,0 +1,494 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_BasinNetwork
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Created by Shupeng Zhang, Feb 2025
+!--------------------------------------------------------------------------------
+
+ USE MOD_Pixelset
+ USE MOD_ComputePushData
+ IMPLICIT NONE
+
+ ! -- instances --
+ integer :: numbasin
+ integer, allocatable :: basinindex(:)
+
+ integer :: numbsnhru
+ type(subset_type) :: basin_hru
+
+ integer :: numrivmth
+ integer, allocatable :: rivermouth(:)
+
+ integer :: numlake, numresv
+ integer, allocatable :: lake_id (:)
+ integer, allocatable :: lake_type(:) ! lake type:
+ ! 0: not lake; 1: natural lake;
+ ! 2: reservoir; 3: controlled lake.
+ integer, allocatable :: bsn2lake (:)
+ integer, allocatable :: bsn2resv (:)
+
+ type(compute_pushdata_type) :: push_elm2bsn
+ type(compute_pushdata_type) :: push_bsn2elm
+
+ type(compute_pushdata_type) :: push_elmhru2bsnhru
+ type(compute_pushdata_type) :: push_bsnhru2elmhru
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE build_basin_network ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Utils
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandElm, only: landelm
+ USE MOD_LandHRU, only: elm_hru
+ IMPLICIT NONE
+
+ ! Local Variables
+ character(len=256) :: basin_file
+ integer, allocatable :: basindown(:)
+
+ integer, allocatable :: nups_nst(:), iups_nst(:), nups_all(:), b_up2down(:), orderbsn(:)
+
+ integer , allocatable :: nb_rs(:), irank_rs(:), nrank_rs(:), nave_rs(:), nb_rank(:)
+ real(r8), allocatable :: wtbsn(:), wt_rs (:), wt_rank (:)
+
+ integer :: totalnumbasin, ibasin, nbasin, iriv
+ integer :: irank, irankdsp, mesg(2), isrc, nrecv
+ integer :: iloc, i, j, ithis
+ real(r8) :: sumwt
+
+ integer, allocatable :: bindex(:), addrbasin(:), elmindex(:)
+
+ ! lake and reservoir
+ character(len=256) :: lake_info_file
+ integer, allocatable :: all_lake_id (:), all_lake_type (:), order(:), icache(:)
+ integer, allocatable :: lake_id_resv(:), lake_type_resv(:)
+ integer :: ilake, iresv
+
+
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ basin_file = DEF_CatchmentMesh_data
+
+ ! read in parameters from file.
+ IF (p_is_root) THEN
+ CALL ncio_read_serial (basin_file, 'basin_downstream', basindown)
+ totalnumbasin = size(basindown)
+ ENDIF
+
+#ifdef USEMPI
+ ! divide basins into groups and assign to ranks
+ IF (p_is_root) THEN
+
+ IF (ncio_var_exist(basin_file, 'weightbasin')) THEN
+ CALL ncio_read_serial (basin_file, 'weightbasin', wtbsn)
+ ELSE
+ allocate (wtbsn (totalnumbasin)); wtbsn(:) = 1.
+ ENDIF
+
+ ! sort basins from up to down, recorded by "b_up2down"
+
+ allocate (nups_nst (totalnumbasin)); nups_nst(:) = 0
+ allocate (iups_nst (totalnumbasin)); iups_nst(:) = 0
+ allocate (b_up2down(totalnumbasin))
+
+ DO i = 1, totalnumbasin
+ j = basindown(i)
+ IF (j > 0) THEN
+ nups_nst(j) = nups_nst(j) + 1
+ ENDIF
+ ENDDO
+
+ ithis = 0
+ DO i = 1, totalnumbasin
+ IF (iups_nst(i) == nups_nst(i)) THEN
+
+ ithis = ithis + 1
+ b_up2down(ithis) = i
+ iups_nst(i) = -1
+
+ j = basindown(i)
+ DO WHILE (j > 0)
+
+ iups_nst(j) = iups_nst(j) + 1
+
+ IF (iups_nst(j) == nups_nst(j)) THEN
+ ithis = ithis + 1
+ b_up2down(ithis) = j
+ iups_nst(j) = -1
+
+ j = basindown(j)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ deallocate (nups_nst)
+ deallocate (iups_nst)
+
+ allocate (rivermouth (totalnumbasin))
+ numrivmth = 0
+ DO i = totalnumbasin, 1, -1
+ j = basindown(b_up2down(i))
+ IF (j <= 0) THEN
+ numrivmth = numrivmth + 1
+ rivermouth(b_up2down(i)) = numrivmth
+ ELSE
+ rivermouth(b_up2down(i)) = rivermouth(j)
+ ENDIF
+ ENDDO
+
+ allocate (nb_rs (numrivmth)); nb_rs(:) = 0
+ allocate (wt_rs (numrivmth)); wt_rs(:) = 0
+ DO i = 1, totalnumbasin
+ nb_rs(rivermouth(i)) = nb_rs(rivermouth(i)) + 1
+ wt_rs(rivermouth(i)) = wt_rs(rivermouth(i)) + wtbsn(i)
+ ENDDO
+
+ sumwt = sum(wt_rs)
+
+ allocate (irank_rs (numrivmth))
+ allocate (nrank_rs (numrivmth))
+ allocate (nave_rs (numrivmth))
+
+ irankdsp = -1
+ DO i = 1, numrivmth
+ nrank_rs(i) = floor(wt_rs(i)/sumwt * p_np_compute)
+ IF (nrank_rs(i) > 1) THEN
+
+ nave_rs(i) = nb_rs(i) / nrank_rs(i)
+ IF (mod(nb_rs(i), nrank_rs(i)) /= 0) THEN
+ nave_rs(i) = nave_rs(i) + 1
+ ENDIF
+
+ irank_rs(i) = irankdsp + 1
+ irankdsp = irankdsp + nrank_rs(i)
+ ENDIF
+ ENDDO
+
+ allocate (nups_all (totalnumbasin)); nups_all(:) = 1
+
+ DO i = 1, totalnumbasin
+ j = basindown(b_up2down(i))
+ IF (j > 0) THEN
+ nups_all(j) = nups_all(j) + nups_all(b_up2down(i))
+ ENDIF
+ ENDDO
+
+ allocate (addrbasin (totalnumbasin)); addrbasin(:) = -1
+
+ allocate (wt_rank (0:p_np_compute-1)); wt_rank(:) = 0
+ allocate (nb_rank (0:p_np_compute-1)); nb_rank(:) = 0
+
+ allocate (orderbsn(totalnumbasin))
+ orderbsn(b_up2down) = (/(i, i = 1, totalnumbasin)/)
+
+ ithis = totalnumbasin
+ DO WHILE (ithis > 0)
+
+ i = b_up2down(ithis)
+
+ IF (addrbasin(i) >= 0) THEN
+ ithis = ithis - 1
+ CYCLE
+ ENDIF
+
+ j = basindown(i)
+ IF (j > 0) THEN
+ IF (addrbasin(j) >= 0) THEN
+ addrbasin(i) = addrbasin(j)
+ ithis = ithis - 1
+ CYCLE
+ ENDIF
+ ENDIF
+
+ iriv = rivermouth(i)
+ IF (nrank_rs(iriv) > 1) THEN
+ irank = irank_rs(iriv)
+ IF (nups_all(i) <= nave_rs(iriv)-nb_rank(irank)) THEN
+
+ addrbasin(i) = p_address_compute(irank)
+
+ nb_rank(irank) = nb_rank(irank) + nups_all(i)
+ IF (nb_rank(irank) == nave_rs(iriv)) THEN
+ irank_rs(iriv) = irank_rs(iriv) + 1
+ ENDIF
+
+ j = basindown(i)
+ IF (j > 0) THEN
+ DO WHILE (j > 0)
+ nups_all(j) = nups_all(j) - nups_all(i)
+ ithis = orderbsn(j)
+ j = basindown(j)
+ ENDDO
+ ELSE
+ ithis = ithis - 1
+ ENDIF
+ ELSE
+ ithis = ithis - 1
+ ENDIF
+ ELSE
+ irank = minloc(wt_rank(irankdsp+1:p_np_compute-1), dim=1) + irankdsp
+
+ addrbasin(i) = p_address_compute(irank)
+
+ wt_rank(irank) = wt_rank(irank) + wt_rs(iriv)
+ ithis = ithis - 1
+ ENDIF
+
+ ENDDO
+
+ deallocate (basindown)
+ deallocate (wtbsn )
+ deallocate (b_up2down)
+ deallocate (nups_all )
+ deallocate (orderbsn )
+ deallocate (nb_rs )
+ deallocate (wt_rs )
+ deallocate (irank_rs )
+ deallocate (nrank_rs )
+ deallocate (nave_rs )
+ deallocate (wt_rank )
+ deallocate (nb_rank )
+
+ ENDIF
+
+
+ ! send basin index to ranks
+ IF (p_is_root) THEN
+
+ allocate(basinindex (totalnumbasin))
+ basinindex = (/(i, i = 1, totalnumbasin)/)
+
+ DO irank = 0, p_np_compute-1
+
+ nbasin = count(addrbasin == p_address_compute(irank))
+ CALL mpi_send (nbasin, 1, MPI_INTEGER, p_address_compute(irank), mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (nbasin > 0) THEN
+ allocate (bindex (nbasin))
+
+ bindex = pack(basinindex, mask = (addrbasin == p_address_compute(irank)))
+ CALL mpi_send (bindex, nbasin, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (bindex)
+ ENDIF
+
+ ENDDO
+
+ deallocate (basinindex)
+
+ ELSEIF (p_is_compute) THEN
+
+ CALL mpi_recv (numbasin, 1, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ IF (numbasin > 0) THEN
+
+ allocate (basinindex (numbasin))
+ CALL mpi_recv (basinindex, numbasin, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ numbasin = totalnumbasin
+ allocate(basinindex (totalnumbasin))
+ basinindex = (/(i, i = 1, totalnumbasin)/)
+#endif
+
+
+ IF (p_is_compute) THEN
+ IF (numelm > 0) THEN
+ allocate (elmindex (numelm))
+ elmindex = landelm%eindex
+ ENDIF
+ ENDIF
+
+ CALL build_compute_pushdata (numelm, elmindex, numbasin, basinindex, push_elm2bsn)
+ CALL build_compute_pushdata (numbasin, basinindex, numelm, elmindex, push_bsn2elm)
+
+ CALL build_compute_pushdata_subset ( &
+ numelm, numbasin, push_elm2bsn, elm_hru, push_elmhru2bsnhru, basin_hru, numbsnhru)
+
+ CALL build_compute_pushdata_subset ( &
+ numbasin, numelm, push_bsn2elm, basin_hru, push_bsnhru2elmhru)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (allocated(addrbasin)) deallocate(addrbasin)
+ IF (allocated(elmindex )) deallocate(elmindex )
+
+
+ IF (p_is_root) THEN
+
+ lake_info_file = DEF_CatchmentMesh_data
+ CALL ncio_read_serial (lake_info_file, 'lake_id', all_lake_id)
+
+ lake_info_file = trim(DEF_dir_runtime)//'/HydroLAKES_Reservoir.nc'
+ CALL ncio_read_serial (lake_info_file, 'hylak_id', lake_id_resv )
+ CALL ncio_read_serial (lake_info_file, 'lake_type', lake_type_resv)
+
+ allocate (order (size(lake_id_resv)))
+ order = (/(iresv, iresv=1,size(lake_id_resv))/)
+
+ CALL quicksort (size(lake_id_resv), lake_id_resv, order)
+
+ lake_type_resv = lake_type_resv(order)
+
+ allocate (all_lake_type (size(all_lake_id)))
+ all_lake_type(:) = 0
+
+ DO ibasin = 1, size(all_lake_id)
+ IF (all_lake_id(ibasin) > 0) THEN
+ all_lake_type(ibasin) = 1
+ iresv = find_in_sorted_list1 (all_lake_id(ibasin), size(lake_id_resv), lake_id_resv)
+ IF (iresv > 0) THEN
+ all_lake_type(ibasin) = lake_type_resv(iresv)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (lake_id_resv )
+ deallocate (lake_type_resv)
+ deallocate (order)
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numbasin > 0) THEN
+ allocate (lake_id (numbasin)); lake_id (:) = 0
+ allocate (lake_type (numbasin)); lake_type(:) = 0
+ ENDIF
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_compute) THEN
+ mesg = (/p_iam_glb, numbasin/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numbasin > 0) THEN
+ CALL mpi_send (basinindex, numbasin, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ CALL mpi_recv (lake_id, numbasin, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ CALL mpi_recv (lake_type, numbasin, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+ DO irank = 0, p_np_compute-1
+
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ nbasin = mesg(2)
+ IF (nbasin > 0) THEN
+
+ allocate(bindex (nbasin))
+ CALL mpi_recv (bindex, nbasin, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate(icache (nbasin))
+
+ icache = all_lake_id (bindex)
+ CALL mpi_send (icache, nbasin, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_err)
+
+ icache = all_lake_type(bindex)
+ CALL mpi_send (icache, nbasin, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (bindex)
+ deallocate (icache)
+ ENDIF
+
+ ENDDO
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ lake_id = all_lake_id (basinindex)
+ lake_type = all_lake_type(basinindex)
+#endif
+
+ IF (p_is_compute) THEN
+ IF (numbasin > 0) THEN
+ numlake = count(lake_type /= 0)
+ numresv = count(lake_type >= 2)
+ ELSE
+ numlake = 0
+ numresv = 0
+ ENDIF
+
+ IF (numlake > 0) THEN
+ allocate (bsn2lake (numbasin))
+ ilake = 0
+ DO ibasin = 1, numbasin
+ IF (lake_type(ibasin) /= 0) THEN
+ ilake = ilake + 1
+ bsn2lake(ibasin) = ilake
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (numresv > 0) THEN
+ allocate (bsn2resv (numbasin))
+ iresv = 0
+ DO ibasin = 1, numbasin
+ IF (lake_type(ibasin) >= 2) THEN
+ iresv = iresv + 1
+ bsn2resv(ibasin) = iresv
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (allocated(all_lake_id )) deallocate(all_lake_id )
+ IF (allocated(all_lake_type)) deallocate(all_lake_type)
+
+
+ END SUBROUTINE build_basin_network
+
+ ! ---------
+ SUBROUTINE basin_network_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(basinindex)) deallocate(basinindex)
+ IF (allocated(rivermouth)) deallocate(rivermouth)
+
+ IF (allocated(lake_id )) deallocate(lake_id )
+ IF (allocated(lake_type )) deallocate(lake_type )
+
+ IF (allocated(bsn2lake )) deallocate(bsn2lake )
+ IF (allocated(bsn2resv )) deallocate(bsn2resv )
+
+ END SUBROUTINE basin_network_final
+
+END MODULE MOD_Catch_BasinNetwork
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_HillslopeFlow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_HillslopeFlow.F90
new file mode 100644
index 0000000000..fdcff24d4c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_HillslopeFlow.F90
@@ -0,0 +1,310 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_HillslopeFlow
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Shallow water equation solver over hillslopes.
+!
+! References
+! [1] Toro EF. Shock-capturing methods for free-surface shallow flows.
+! Chichester: John Wiley & Sons; 2001.
+! [2] Liang, Q., Borthwick, A. G. L. (2009). Adaptive quadtree simulation of shallow
+! flows with wet-dry fronts over complex topography.
+! Computers and Fluids, 38(2), 221-234.
+! [3] Audusse, E., Bouchut, F., Bristeau, M.-O., Klein, R., Perthame, B. (2004).
+! A Fast and Stable Well-Balanced Scheme with Hydrostatic Reconstruction for
+! Shallow Water Flows. SIAM Journal on Scientific Computing, 25(6), 2050-2065.
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! -- Parameters --
+ real(r8), parameter :: PONDMIN = 1.e-4
+ real(r8), parameter :: nmanning_hslp = 0.3
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE hillslope_flow (dt)
+
+ USE MOD_SPMD_Task
+ USE MOD_Catch_BasinNetwork
+ USE MOD_Catch_HillslopeNetwork
+ USE MOD_Catch_RiverLakeNetwork
+ USE MOD_Catch_Vars_TimeVariables
+ USE MOD_Catch_Vars_1DFluxes
+ USE MOD_Const_Physical, only: grav
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: dt
+
+ ! Local Variables
+ integer :: nhru, hs, he, ibasin, i, j
+
+ type(hillslope_network_type), pointer :: hillslope
+
+ real(r8), allocatable :: wdsrf_h (:) ! [m]
+ real(r8), allocatable :: momen_h (:) ! [m^2/s]
+ real(r8), allocatable :: veloc_h (:) ! [m/s]
+
+ real(r8), allocatable :: sum_hflux_h (:)
+ real(r8), allocatable :: sum_mflux_h (:)
+ real(r8), allocatable :: sum_zgrad_h (:)
+
+ real(r8) :: hand_fc, wdsrf_fc, veloc_fc, hflux_fc, mflux_fc
+ real(r8) :: wdsrf_up, wdsrf_dn, vwave_up, vwave_dn
+ real(r8) :: hflux_up, hflux_dn, mflux_up, mflux_dn
+
+ real(r8), allocatable :: xsurf_h (:) ! [m/s]
+
+ real(r8) :: friction
+ real(r8) :: dt_res, dt_this
+
+ logical, allocatable :: mask(:)
+ real(r8) :: srfbsn, dvol, nextl, nexta, nextv, ddep
+
+ IF (p_is_compute) THEN
+
+ DO ibasin = 1, numbasin
+
+ hs = basin_hru%substt(ibasin)
+ he = basin_hru%subend(ibasin)
+
+ IF (lake_id(ibasin) > 0) THEN
+ veloc_bsnhru(hs:he) = 0
+ momen_bsnhru(hs:he) = 0
+ CYCLE ! skip lakes
+ ELSE
+ DO i = hs, he
+ ! momentum is less or equal than the momentum at last time step.
+ momen_bsnhru(i) = min(wdsrf_bsnhru_prev(i), wdsrf_bsnhru(i)) * veloc_bsnhru(i)
+ ENDDO
+ ENDIF
+
+ hillslope => hillslope_basin(ibasin)
+
+ nhru = hillslope%nhru
+
+ allocate (wdsrf_h (nhru))
+ allocate (veloc_h (nhru))
+ allocate (momen_h (nhru))
+
+ allocate (sum_hflux_h (nhru))
+ allocate (sum_mflux_h (nhru))
+ allocate (sum_zgrad_h (nhru))
+
+ allocate (xsurf_h (nhru))
+
+ DO i = 1, nhru
+ wdsrf_h(i) = wdsrf_bsnhru(hillslope%ihru(i))
+ momen_h(i) = momen_bsnhru(hillslope%ihru(i))
+ IF (wdsrf_h(i) > 0.) THEN
+ veloc_h(i) = momen_h(i) / wdsrf_h(i)
+ ELSE
+ veloc_h(i) = 0.
+ ENDIF
+ ENDDO
+
+ dt_res = dt
+ DO WHILE (dt_res > 0.)
+
+ DO i = 1, nhru
+ sum_hflux_h(i) = 0.
+ sum_mflux_h(i) = 0.
+ sum_zgrad_h(i) = 0.
+ ENDDO
+
+ dt_this = dt_res
+
+ DO i = 1, nhru
+
+ j = hillslope%inext(i)
+
+ IF (j <= 0) CYCLE ! lowest HRUs
+
+ ! dry HRU
+ IF ((wdsrf_h(i) < PONDMIN) .and. (wdsrf_h(j) < PONDMIN)) THEN
+ CYCLE
+ ENDIF
+
+ ! reconstruction of height of water near interface
+ hand_fc = max(hillslope%hand(i), hillslope%hand(j))
+ wdsrf_up = max(0., hillslope%hand(i)+wdsrf_h(i) - hand_fc)
+ wdsrf_dn = max(0., hillslope%hand(j)+wdsrf_h(j) - hand_fc)
+
+ ! velocity at hydrounit downstream face
+ veloc_fc = 0.5 * (veloc_h(i) + veloc_h(j)) &
+ + sqrt(grav * wdsrf_up) - sqrt(grav * wdsrf_dn)
+
+ ! depth of water at downstream face
+ wdsrf_fc = 1/grav * (0.5*(sqrt(grav*wdsrf_up) + sqrt(grav*wdsrf_dn)) &
+ + 0.25 * (veloc_h(i) - veloc_h(j)))**2.0
+
+ IF (wdsrf_up > 0) THEN
+ vwave_up = min(veloc_h(i)-sqrt(grav*wdsrf_up), veloc_fc-sqrt(grav*wdsrf_fc))
+ ELSE
+ vwave_up = veloc_h(j) - 2.0 * sqrt(grav*wdsrf_dn)
+ ENDIF
+
+ IF (wdsrf_dn > 0) THEN
+ vwave_dn = max(veloc_h(j)+sqrt(grav*wdsrf_dn), veloc_fc+sqrt(grav*wdsrf_fc))
+ ELSE
+ vwave_dn = veloc_h(i) + 2.0 * sqrt(grav*wdsrf_up)
+ ENDIF
+
+ hflux_up = veloc_h(i) * wdsrf_up
+ hflux_dn = veloc_h(j) * wdsrf_dn
+ mflux_up = veloc_h(i)**2 * wdsrf_up + 0.5*grav * wdsrf_up**2
+ mflux_dn = veloc_h(j)**2 * wdsrf_dn + 0.5*grav * wdsrf_dn**2
+
+ IF (vwave_up >= 0.) THEN
+ hflux_fc = hillslope%flen(i) * hflux_up
+ mflux_fc = hillslope%flen(i) * mflux_up
+ ELSEIF (vwave_dn <= 0.) THEN
+ hflux_fc = hillslope%flen(i) * hflux_dn
+ mflux_fc = hillslope%flen(i) * mflux_dn
+ ELSE
+ hflux_fc = hillslope%flen(i) * (vwave_dn*hflux_up - vwave_up*hflux_dn &
+ + vwave_up*vwave_dn*(wdsrf_dn-wdsrf_up)) / (vwave_dn-vwave_up)
+ mflux_fc = hillslope%flen(i) * (vwave_dn*mflux_up - vwave_up*mflux_dn &
+ + vwave_up*vwave_dn*(hflux_dn-hflux_up)) / (vwave_dn-vwave_up)
+ ENDIF
+
+ sum_hflux_h(i) = sum_hflux_h(i) + hflux_fc
+ sum_hflux_h(j) = sum_hflux_h(j) - hflux_fc
+
+ sum_mflux_h(i) = sum_mflux_h(i) + mflux_fc
+ sum_mflux_h(j) = sum_mflux_h(j) - mflux_fc
+
+ sum_zgrad_h(i) = sum_zgrad_h(i) + hillslope%flen(i) * 0.5*grav * wdsrf_up**2
+ sum_zgrad_h(j) = sum_zgrad_h(j) - hillslope%flen(i) * 0.5*grav * wdsrf_dn**2
+
+ ENDDO
+
+ DO i = 1, nhru
+ ! constraint 1: CFL condition
+ IF (hillslope%inext(i) > 0) THEN
+ IF ((veloc_h(i) /= 0.) .or. (wdsrf_h(i) > 0.)) THEN
+ dt_this = min(dt_this, hillslope%plen(i)/(abs(veloc_h(i)) + sqrt(grav*wdsrf_h(i)))*0.8)
+ ENDIF
+ ENDIF
+
+ ! constraint 2: Avoid negative values of water
+ xsurf_h(i) = sum_hflux_h(i) / hillslope%area(i)
+ IF (xsurf_h(i) > 0) THEN
+ dt_this = min(dt_this, wdsrf_h(i) / xsurf_h(i))
+ ENDIF
+
+ ! constraint 3: Avoid change of flow direction
+ IF ((abs(veloc_h(i)) > 0.1) &
+ .and. (veloc_h(i) * (sum_mflux_h(i) - sum_zgrad_h(i)) > 0)) THEN
+ dt_this = min(dt_this, &
+ abs(momen_h(i) * hillslope%area(i) / (sum_mflux_h(i) - sum_zgrad_h(i))))
+ ENDIF
+ ENDDO
+
+ DO i = 1, nhru
+
+ wdsrf_h(i) = max(0., wdsrf_h(i) - xsurf_h(i) * dt_this)
+
+ IF (wdsrf_h(i) < PONDMIN) THEN
+ momen_h(i) = 0
+ ELSE
+ friction = grav * nmanning_hslp**2 * abs(momen_h(i)) / wdsrf_h(i)**(7.0/3.0)
+ momen_h(i) = (momen_h(i) - &
+ (sum_mflux_h(i) - sum_zgrad_h(i)) / hillslope%area(i) * dt_this) &
+ / (1 + friction * dt_this)
+
+ IF (hillslope%inext(i) <= 0) THEN
+ momen_h(i) = min(momen_h(i), 0.)
+ ENDIF
+
+ IF (all(hillslope%inext /= i)) THEN
+ momen_h(i) = max(momen_h(i), 0.)
+ ENDIF
+ ENDIF
+
+ ENDDO
+
+ IF (hillslope%indx(1) == 0) THEN
+ srfbsn = minval(hillslope%hand + wdsrf_h)
+ IF (srfbsn < wdsrf_h(1)) THEN
+ allocate (mask (hillslope%nhru))
+ dvol = (wdsrf_h(1) - srfbsn) * hillslope%area(1)
+ momen_h(1) = srfbsn/wdsrf_h(1) * momen_h(1)
+ wdsrf_h(1) = srfbsn
+ DO WHILE (dvol > 0)
+ mask = hillslope%hand + wdsrf_h > srfbsn
+ nexta = sum(hillslope%area, mask = (.not. mask))
+ IF (any(mask)) THEN
+ nextl = minval(hillslope%hand + wdsrf_h, mask = mask)
+ nextv = nexta*(nextl-srfbsn)
+ IF (dvol > nextv) THEN
+ ddep = nextl - srfbsn
+ dvol = dvol - nextv
+ ELSE
+ ddep = dvol/nexta
+ dvol = 0.
+ ENDIF
+ ELSE
+ ddep = dvol/nexta
+ dvol = 0.
+ ENDIF
+
+ srfbsn = srfbsn + ddep
+
+ WHERE (.not. mask)
+ wdsrf_h = wdsrf_h + ddep
+ END WHERE
+ ENDDO
+ deallocate(mask)
+ ENDIF
+ ENDIF
+
+ DO i = 1, nhru
+ IF (wdsrf_h(i) < PONDMIN) THEN
+ veloc_h(i) = 0
+ ELSE
+ veloc_h(i) = momen_h(i) / wdsrf_h(i)
+ ENDIF
+
+ wdsrf_bsnhru_ta(hillslope%ihru(i)) = wdsrf_bsnhru_ta(hillslope%ihru(i)) + wdsrf_h(i) * dt_this
+ momen_bsnhru_ta(hillslope%ihru(i)) = momen_bsnhru_ta(hillslope%ihru(i)) + momen_h(i) * dt_this
+ ENDDO
+
+ dt_res = dt_res - dt_this
+
+ ENDDO
+
+ ! SAVE depth of surface water
+ DO i = 1, nhru
+ wdsrf_bsnhru(hillslope%ihru(i)) = wdsrf_h(i)
+ veloc_bsnhru(hillslope%ihru(i)) = veloc_h(i)
+ ENDDO
+
+ deallocate (wdsrf_h)
+ deallocate (veloc_h)
+ deallocate (momen_h)
+
+ deallocate (sum_hflux_h)
+ deallocate (sum_mflux_h)
+ deallocate (sum_zgrad_h)
+
+ deallocate (xsurf_h)
+
+ ENDDO
+
+ IF (numbsnhru > 0) wdsrf_bsnhru_prev(:) = wdsrf_bsnhru(:)
+
+ ENDIF
+
+ END SUBROUTINE hillslope_flow
+
+END MODULE MOD_Catch_HillslopeFlow
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_HillslopeNetwork.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_HillslopeNetwork.F90
new file mode 100644
index 0000000000..92ab560435
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_HillslopeNetwork.F90
@@ -0,0 +1,381 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_HillslopeNetwork
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Surface networks (hillslope bands): data and communication subroutines.
+!
+! Created by Shupeng Zhang, May 2023
+!--------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! -- data type --
+ type :: hillslope_network_type
+ integer :: nhru
+ integer , pointer :: ihru (:) ! location of HRU in global vector "landhru"
+ integer , pointer :: indx (:) ! index of HRU
+ real(r8), pointer :: area (:) ! area of HRU [m^2]
+ real(r8), pointer :: agwt (:) ! water area only including (patchtype <= 2) [m^2]
+ real(r8), pointer :: hand (:) ! height above nearest drainage [m]
+ real(r8), pointer :: elva (:) ! elevation [m]
+ real(r8), pointer :: plen (:) ! average drainage path length to downstream HRU [m]
+ real(r8), pointer :: flen (:) ! interface length between this and downstream HRU [m]
+ integer , pointer :: inext(:) ! location of next HRU in this basin
+ real(r8), pointer :: fldprof (:,:) ! flood area profile
+ CONTAINS
+ final :: hillslope_network_free_mem
+ END type hillslope_network_type
+
+ integer :: nfldstep
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE hillslope_network_init (ne, elmindex, hillslope_network)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_UserDefFun
+ IMPLICIT NONE
+
+ integer, intent(in) :: ne
+ integer, intent(in) :: elmindex (:)
+ type(hillslope_network_type), pointer :: hillslope_network(:)
+
+ ! Local Variables
+ character(len=256) :: hillslope_network_file
+
+ integer :: maxnumhru, ie, nhru, hs, i, j
+ integer :: irank, mesg(2), nrecv, irecv, isrc, idest
+
+ integer , allocatable :: eid (:)
+
+ integer , allocatable :: nhru_all(:), nhru_in_bsn(:)
+
+ integer , allocatable :: indxhru (:,:)
+ real(r8), allocatable :: handhru (:,:)
+ real(r8), allocatable :: elvahru (:,:)
+ real(r8), allocatable :: plenhru (:,:)
+ real(r8), allocatable :: lfachru (:,:)
+ integer , allocatable :: nexthru (:,:)
+ real(r8), allocatable :: fldstep (:,:,:)
+
+ integer , allocatable :: icache (:,:)
+ real(r8), allocatable :: rcache (:,:), rcache2(:,:,:)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ hillslope_network_file = DEF_CatchmentMesh_data
+
+ IF (p_is_root) THEN
+
+ CALL ncio_read_serial (hillslope_network_file, 'basin_numhru', nhru_all)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_index', indxhru)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_hand', handhru)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_elva', elvahru)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_pathlen', plenhru)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_facelen', lfachru)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_downstream', nexthru)
+ CALL ncio_read_serial (hillslope_network_file, 'hydrounit_flood_step', fldstep)
+
+ ENDIF
+
+ IF (p_is_root) maxnumhru = size(indxhru,1)
+ IF (p_is_root) nfldstep = size(fldstep,1)
+#ifdef USEMPI
+ CALL mpi_bcast (maxnumhru, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast (nfldstep, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#endif
+
+ hillslope_network => null()
+
+ IF (p_is_root) THEN
+#ifdef USEMPI
+ DO irank = 1, p_np_compute
+ CALL mpi_recv (mesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ nrecv = mesg(2)
+ isrc = mesg(1)
+
+ IF (nrecv > 0) THEN
+
+ allocate (eid (nrecv))
+ allocate (nhru_in_bsn (nrecv))
+ allocate (icache (maxnumhru,nrecv))
+ allocate (rcache (maxnumhru,nrecv))
+
+ CALL mpi_recv (eid, nrecv, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ idest = isrc
+
+ nhru_in_bsn = nhru_all(eid)
+ CALL mpi_send (nhru_in_bsn, nrecv, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ icache(:,irecv) = indxhru(:,eid(irecv))
+ ENDDO
+ CALL mpi_send (icache, maxnumhru*nrecv, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ rcache(:,irecv) = handhru(:,eid(irecv))
+ ENDDO
+ CALL mpi_send (rcache, maxnumhru*nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ rcache(:,irecv) = elvahru(:,eid(irecv))
+ ENDDO
+ CALL mpi_send (rcache, maxnumhru*nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ rcache(:,irecv) = plenhru(:,eid(irecv))
+ ENDDO
+ CALL mpi_send (rcache, maxnumhru*nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ rcache(:,irecv) = lfachru(:,eid(irecv))
+ ENDDO
+ CALL mpi_send (rcache, maxnumhru*nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ icache(:,irecv) = nexthru(:,eid(irecv))
+ ENDDO
+ CALL mpi_send (icache, maxnumhru*nrecv, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (rcache2 (nfldstep,maxnumhru,nrecv))
+
+ DO irecv = 1, nrecv
+ rcache2(:,:,irecv) = fldstep(:,:,eid(irecv))
+ ENDDO
+ CALL mpi_send (rcache2, nfldstep*maxnumhru*nrecv, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (eid)
+ deallocate (nhru_in_bsn)
+ deallocate (icache)
+ deallocate (rcache)
+ deallocate (rcache2)
+ ENDIF
+ ENDDO
+#else
+ IF (ne > 0) THEN
+
+ allocate (nhru_in_bsn (ne))
+ allocate (icache (maxnumhru,ne))
+ allocate (rcache (maxnumhru,ne))
+
+ nhru_in_bsn = nhru_all(elmindex)
+
+ DO ie = 1, ne
+ icache(:,ie) = indxhru(:,elmindex(ie))
+ ENDDO
+ indxhru = icache
+
+ DO ie = 1, ne
+ rcache(:,ie) = handhru(:,elmindex(ie))
+ ENDDO
+ handhru = rcache
+
+ DO ie = 1, ne
+ rcache(:,ie) = elvahru(:,elmindex(ie))
+ ENDDO
+ elvahru = rcache
+
+ DO ie = 1, ne
+ rcache(:,ie) = plenhru(:,elmindex(ie))
+ ENDDO
+ plenhru = rcache
+
+ DO ie = 1, ne
+ rcache(:,ie) = lfachru(:,elmindex(ie))
+ ENDDO
+ lfachru = rcache
+
+ DO ie = 1, ne
+ icache(:,ie) = nexthru(:,elmindex(ie))
+ ENDDO
+ nexthru = icache
+
+ deallocate (icache)
+ deallocate (rcache)
+
+ allocate (rcache2 (nfldstep,maxnumhru,ne))
+
+ DO ie = 1, ne
+ rcache2(:,:,ie) = fldstep(:,:,elmindex(ie))
+ ENDDO
+ fldstep = rcache2
+
+ deallocate (rcache2)
+
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+#ifdef USEMPI
+ mesg(1:2) = (/p_iam_glb, ne/)
+ CALL mpi_send (mesg(1:2), 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (ne > 0) THEN
+
+ CALL mpi_send (elmindex, ne, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (nhru_in_bsn (ne))
+ CALL mpi_recv (nhru_in_bsn, ne, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (indxhru (maxnumhru,ne))
+ CALL mpi_recv (indxhru, maxnumhru*ne, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (handhru (maxnumhru,ne))
+ CALL mpi_recv (handhru, maxnumhru*ne, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (elvahru (maxnumhru,ne))
+ CALL mpi_recv (elvahru, maxnumhru*ne, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (plenhru (maxnumhru,ne))
+ CALL mpi_recv (plenhru, maxnumhru*ne, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (lfachru (maxnumhru,ne))
+ CALL mpi_recv (lfachru, maxnumhru*ne, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (nexthru (maxnumhru,ne))
+ CALL mpi_recv (nexthru, maxnumhru*ne, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (fldstep (nfldstep,maxnumhru,ne))
+ CALL mpi_recv (fldstep, nfldstep*maxnumhru*ne, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+#endif
+
+ IF (ne > 0) THEN
+ allocate( hillslope_network (ne))
+ ENDIF
+
+ hs = 0
+
+ DO ie = 1, ne
+
+ nhru = count(indxhru(:,ie) >= 0)
+
+ IF (nhru > 0) THEN
+
+ IF (nhru /= nhru_in_bsn(ie)) THEN
+ write(*,*) 'Warning : numbers of hydro units from file mismatch!'
+ ENDIF
+
+ allocate (hillslope_network(ie)%ihru (nhru))
+ allocate (hillslope_network(ie)%indx (nhru))
+ allocate (hillslope_network(ie)%area (nhru))
+ allocate (hillslope_network(ie)%agwt (nhru))
+ allocate (hillslope_network(ie)%hand (nhru))
+ allocate (hillslope_network(ie)%elva (nhru))
+ allocate (hillslope_network(ie)%plen (nhru))
+ allocate (hillslope_network(ie)%flen (nhru))
+ allocate (hillslope_network(ie)%inext (nhru))
+
+ hillslope_network(ie)%indx = indxhru(1:nhru,ie)
+ hillslope_network(ie)%hand = handhru(1:nhru,ie) ! m
+ hillslope_network(ie)%elva = elvahru(1:nhru,ie) ! m
+ hillslope_network(ie)%plen = plenhru(1:nhru,ie) * 1.0e3 ! km to m
+ hillslope_network(ie)%flen = lfachru(1:nhru,ie) * 1.0e3 ! km to m
+
+ hillslope_network(ie)%ihru = (/ (i, i = hs+1, hs+nhru) /)
+
+ allocate (hillslope_network(ie)%fldprof (nfldstep,nhru))
+
+ DO i = 1, nhru
+ DO j = 1, nfldstep
+ IF (j == 1) THEN
+ hillslope_network(ie)%fldprof(j,i) = max(fldstep(j,i,ie) * (j-0.5)/nfldstep, 1.e-3)
+ ELSE
+ hillslope_network(ie)%fldprof(j,i) = hillslope_network(ie)%fldprof(j-1,i) &
+ + (fldstep(j,i,ie) - fldstep(j-1,i,ie)) * (j-0.5)/nfldstep
+ ENDIF
+ ENDDO
+ ENDDO
+
+ DO i = 1, nhru
+ IF (nexthru(i,ie) >= 0) THEN
+ j = findloc_ud(indxhru(1:nhru,ie) == nexthru(i,ie))
+ hillslope_network(ie)%inext(i) = j
+ ELSE
+ hillslope_network(ie)%inext(i) = -1
+ ENDIF
+ ENDDO
+
+ ELSE
+ ! for lake
+ hillslope_network(ie)%ihru => null()
+ hillslope_network(ie)%indx => null()
+ hillslope_network(ie)%area => null()
+ hillslope_network(ie)%agwt => null()
+ hillslope_network(ie)%hand => null()
+ hillslope_network(ie)%elva => null()
+ hillslope_network(ie)%plen => null()
+ hillslope_network(ie)%flen => null()
+ hillslope_network(ie)%inext => null()
+ ENDIF
+
+ hillslope_network(ie)%nhru = nhru_in_bsn(ie)
+ hs = hs + nhru_in_bsn(ie)
+
+ ENDDO
+
+ ENDIF
+
+ IF (allocated(nhru_all )) deallocate(nhru_all )
+ IF (allocated(nhru_in_bsn)) deallocate(nhru_in_bsn)
+
+ IF (allocated(indxhru)) deallocate(indxhru)
+ IF (allocated(handhru)) deallocate(handhru)
+ IF (allocated(elvahru)) deallocate(elvahru)
+ IF (allocated(plenhru)) deallocate(plenhru)
+ IF (allocated(lfachru)) deallocate(lfachru)
+ IF (allocated(nexthru)) deallocate(nexthru)
+ IF (allocated(fldstep)) deallocate(fldstep)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+ IF (p_is_root) write(*,'(A)') 'Read hillslope network information done.'
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE hillslope_network_init
+
+ ! ---------
+ SUBROUTINE hillslope_network_free_mem (this)
+
+ IMPLICIT NONE
+ type(hillslope_network_type) :: this
+
+ IF (associated(this%ihru )) deallocate(this%ihru )
+ IF (associated(this%indx )) deallocate(this%indx )
+ IF (associated(this%area )) deallocate(this%area )
+ IF (associated(this%agwt )) deallocate(this%agwt )
+ IF (associated(this%hand )) deallocate(this%hand )
+ IF (associated(this%elva )) deallocate(this%elva )
+ IF (associated(this%plen )) deallocate(this%plen )
+ IF (associated(this%flen )) deallocate(this%flen )
+ IF (associated(this%inext )) deallocate(this%inext )
+ IF (associated(this%fldprof)) deallocate(this%fldprof)
+
+ END SUBROUTINE hillslope_network_free_mem
+
+END MODULE MOD_Catch_HillslopeNetwork
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Hist.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Hist.F90
new file mode 100644
index 0000000000..b773a0d304
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Hist.F90
@@ -0,0 +1,490 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_Hist
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Write out model results in lateral hydrological processes to history files.
+!
+! Created by Shupeng Zhang, May 2023
+!--------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Vars_Global, only: spval
+
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandHRU, only: numhru
+ USE MOD_Catch_BasinNetwork, only: numbasin, numbsnhru
+ USE MOD_Catch_Reservoir
+ USE MOD_Catch_Vars_1DFluxes
+ USE MOD_Vector_ReadWrite
+
+ ! -- ACC Fluxes --
+ integer :: nac_basin
+
+ real(r8), allocatable :: a_wdsrf_bsnhru (:)
+ real(r8), allocatable :: a_veloc_bsnhru (:)
+
+ real(r8), allocatable :: a_wdsrf_hru (:)
+ real(r8), allocatable :: a_veloc_hru (:)
+
+ real(r8), allocatable :: a_wdsrf_bsn (:)
+ real(r8), allocatable :: a_veloc_riv (:)
+ real(r8), allocatable :: a_discharge (:)
+
+ real(r8), allocatable :: a_wdsrf_elm (:)
+ real(r8), allocatable :: a_veloc_elm (:)
+ real(r8), allocatable :: a_dschg_elm (:)
+
+ real(r8), allocatable :: a_xsubs_elm (:)
+ real(r8), allocatable :: a_xsubs_hru (:)
+
+ real(r8), allocatable :: a_volresv (:)
+ real(r8), allocatable :: a_qresv_in (:)
+ real(r8), allocatable :: a_qresv_out (:)
+
+ real(r8), allocatable :: ntacc_elm (:)
+
+ ! -- PUBLIC SUBROUTINEs --
+ PUBLIC :: hist_basin_init
+ PUBLIC :: hist_basin_out
+ PUBLIC :: hist_basin_final
+
+!--------------------------------------------------------------------------
+CONTAINS
+
+ SUBROUTINE hist_basin_init
+
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numbsnhru > 0) THEN
+ allocate (a_wdsrf_bsnhru (numbsnhru))
+ allocate (a_veloc_bsnhru (numbsnhru))
+ ENDIF
+
+ IF (numbasin > 0) THEN
+ allocate (a_wdsrf_bsn (numbasin))
+ allocate (a_veloc_riv (numbasin))
+ allocate (a_discharge (numbasin))
+ ENDIF
+
+ IF (numelm > 0) allocate (a_xsubs_elm (numelm))
+ IF (numhru > 0) allocate (a_xsubs_hru (numhru))
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv > 0) allocate (a_volresv (numresv))
+ IF (numresv > 0) allocate (a_qresv_in (numresv))
+ IF (numresv > 0) allocate (a_qresv_out (numresv))
+ ENDIF
+ ENDIF
+
+ CALL FLUSH_acc_fluxes_basin ()
+
+ END SUBROUTINE hist_basin_init
+
+ !--------------------------------------
+ SUBROUTINE hist_basin_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(a_wdsrf_bsnhru)) deallocate(a_wdsrf_bsnhru)
+ IF (allocated(a_veloc_bsnhru)) deallocate(a_veloc_bsnhru)
+
+ IF (allocated(a_wdsrf_bsn)) deallocate(a_wdsrf_bsn)
+ IF (allocated(a_veloc_riv)) deallocate(a_veloc_riv)
+ IF (allocated(a_discharge)) deallocate(a_discharge)
+
+ IF (allocated(a_xsubs_elm)) deallocate(a_xsubs_elm)
+ IF (allocated(a_xsubs_hru)) deallocate(a_xsubs_hru)
+
+ IF (allocated(a_volresv )) deallocate(a_volresv )
+ IF (allocated(a_qresv_in )) deallocate(a_qresv_in )
+ IF (allocated(a_qresv_out)) deallocate(a_qresv_out)
+
+ END SUBROUTINE hist_basin_final
+
+ !---------------------------------------
+ SUBROUTINE hist_basin_out (file_hist, idate)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_ElmVector
+ USE MOD_HRUVector
+ USE MOD_LandHRU
+ USE MOD_Catch_BasinNetwork
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_hist
+ integer, intent(in) :: idate(3)
+
+ ! Local variables
+ character(len=256) :: file_hist_basin
+ logical :: fexists
+ integer :: itime_in_file
+ logical, allocatable :: filter (:)
+ real(r8), allocatable :: varhist(:)
+ integer :: i
+
+ IF (p_is_root) THEN
+
+ i = len_trim (file_hist)
+ DO WHILE (file_hist(i:i) /= '_')
+ i = i - 1
+ ENDDO
+ file_hist_basin = file_hist(1:i) // 'basin_' // file_hist(i+1:)
+
+ inquire (file=file_hist_basin, exist=fexists)
+ IF (.not. fexists) THEN
+ CALL ncio_create_file (trim(file_hist_basin))
+ CALL ncio_define_dimension(file_hist_basin, 'time', 0)
+ CALL ncio_define_dimension(file_hist_basin, 'basin', totalnumelm)
+ CALL ncio_define_dimension(file_hist_basin, 'hydrounit', totalnumhru)
+
+ CALL ncio_write_serial (file_hist_basin, 'basin', eindex_glb, 'basin')
+ CALL ncio_put_attr (file_hist_basin, 'basin', 'long_name', 'basin index')
+
+ CALL ncio_write_serial (file_hist_basin, 'basin_hru', eindx_hru, 'hydrounit')
+ CALL ncio_put_attr (file_hist_basin, 'basin_hru', 'long_name', &
+ 'basin index of hydrological units')
+
+ CALL ncio_write_serial (file_hist_basin, 'hru_type' , htype_hru, 'hydrounit')
+ CALL ncio_put_attr (file_hist_basin, 'hru_type' , 'long_name', &
+ 'index of hydrological units inside basin')
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv_uniq > 0) THEN
+ CALL ncio_define_dimension(file_hist_basin, 'reservoir', numresv_uniq)
+ CALL ncio_write_serial (file_hist_basin, 'resv_hylak_id' , resv_hylak_id, 'reservoir')
+ CALL ncio_put_attr (file_hist_basin, 'resv_hylak_id' , 'long_name', &
+ 'HydroLAKE ID of reservoirs')
+ ENDIF
+ ENDIF
+ ENDIF
+
+ CALL ncio_write_time (file_hist_basin, 'time', idate, itime_in_file, DEF_HIST_FREQ)
+
+ ENDIF
+
+
+ IF (p_is_compute) THEN
+ IF (numhru > 0) THEN
+ allocate (a_wdsrf_hru (numhru))
+ allocate (a_veloc_hru (numhru))
+ ENDIF
+
+ IF (numelm > 0) THEN
+ allocate (a_wdsrf_elm (numelm))
+ allocate (a_veloc_elm (numelm))
+ allocate (a_dschg_elm (numelm))
+ allocate (ntacc_elm (numelm))
+ ENDIF
+ ENDIF
+
+ ! ----- water depth in basin -----
+ IF (DEF_hist_vars%riv_height) THEN
+ IF ((p_is_compute) .and. allocated(a_wdsrf_bsn)) THEN
+ WHERE(a_wdsrf_bsn /= spval)
+ a_wdsrf_bsn = a_wdsrf_bsn / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_bsn2elm, a_wdsrf_bsn, a_wdsrf_elm, spval)
+
+ CALL vector_gather_and_write (&
+ a_wdsrf_elm, numelm, totalnumelm, elm_data_address, file_hist_basin, 'v_wdsrf_bsn', 'basin', &
+ itime_in_file, 'River Height', 'm')
+ ENDIF
+
+ ! ----- water velocity in river -----
+ IF (DEF_hist_vars%riv_veloct) THEN
+ IF ((p_is_compute) .and. allocated(a_veloc_riv)) THEN
+ WHERE(a_veloc_riv /= spval)
+ a_veloc_riv = a_veloc_riv / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_bsn2elm, a_veloc_riv, a_veloc_elm, spval)
+
+ CALL vector_gather_and_write (&
+ a_veloc_elm, numelm, totalnumelm, elm_data_address, file_hist_basin, 'v_veloc_riv', 'basin', &
+ itime_in_file, 'River Velocity', 'm/s')
+ ENDIF
+
+ ! ----- discharge in river -----
+ IF (DEF_hist_vars%discharge) THEN
+ IF ((p_is_compute) .and. allocated(a_discharge)) THEN
+ WHERE(a_discharge /= spval)
+ a_discharge = a_discharge / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_bsn2elm, a_discharge, a_dschg_elm, spval)
+
+ CALL vector_gather_and_write (&
+ a_dschg_elm, numelm, totalnumelm, elm_data_address, file_hist_basin, 'v_discharge', 'basin', &
+ itime_in_file, 'River Discharge', 'm^3/s')
+ ENDIF
+
+ ! ----- number of time steps for each basin -----
+ CALL compute_push_data (push_bsn2elm, ntacc_bsn, ntacc_elm, spval)
+
+ CALL vector_gather_and_write (&
+ ntacc_elm, numelm, totalnumelm, elm_data_address, file_hist_basin, 'timesteps', 'basin', &
+ itime_in_file, 'Number of accumulated timesteps for each basin', '-')
+
+ IF (p_is_compute .and. (numbasin > 0)) ntacc_bsn(:) = 0.
+
+ ! ----- water depth in hydro unit -----
+ IF (DEF_hist_vars%wdsrf_hru) THEN
+ IF ((p_is_compute) .and. allocated(a_wdsrf_bsnhru)) THEN
+ WHERE(a_wdsrf_bsnhru /= spval)
+ a_wdsrf_bsnhru = a_wdsrf_bsnhru / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_bsnhru2elmhru, a_wdsrf_bsnhru, a_wdsrf_hru, spval)
+
+ CALL vector_gather_and_write (&
+ a_wdsrf_hru, numhru, totalnumhru, hru_data_address, file_hist_basin, 'v_wdsrf_hru', 'hydrounit', &
+ itime_in_file, 'Depth of Surface Water in Hydro unit', 'm')
+ ENDIF
+
+ ! ----- water velocity in hydro unit -----
+ IF (DEF_hist_vars%veloc_hru) THEN
+ IF ((p_is_compute) .and. allocated(a_veloc_bsnhru)) THEN
+ WHERE(a_veloc_bsnhru /= spval)
+ a_veloc_bsnhru = a_veloc_bsnhru / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_bsnhru2elmhru, a_veloc_bsnhru, a_veloc_hru, spval)
+
+ CALL vector_gather_and_write (&
+ a_veloc_hru, numhru, totalnumhru, hru_data_address, file_hist_basin, 'v_veloc_hru', 'hydrounit', &
+ itime_in_file, 'Surface Flow Velocity in Hydro unit', 'm/s')
+ ENDIF
+
+ ! ----- subsurface water flow between elements -----
+ IF (DEF_hist_vars%xsubs_bsn) THEN
+ IF (p_is_compute) THEN
+ WHERE(a_xsubs_elm /= spval)
+ a_xsubs_elm = a_xsubs_elm / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ a_xsubs_elm, numelm, totalnumelm, elm_data_address, file_hist_basin, 'v_xsubs_bsn', 'basin', &
+ itime_in_file, 'Subsurface lateral flow between basins', 'm/s')
+ ENDIF
+
+ ! ----- subsurface water flow between hydro units -----
+ IF (DEF_hist_vars%xsubs_hru) THEN
+ IF (p_is_compute) THEN
+ WHERE(a_xsubs_hru /= spval)
+ a_xsubs_hru = a_xsubs_hru / nac_basin
+ END WHERE
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ a_xsubs_hru, numhru, totalnumhru, hru_data_address, file_hist_basin, 'v_xsubs_hru', 'hydrounit', &
+ itime_in_file, 'SubSurface lateral flow between HRUs', 'm/s')
+ ENDIF
+
+ ! ----- reservoir variables -----
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv_uniq > 0) THEN
+
+ allocate (varhist (numresv_uniq))
+
+ IF (DEF_hist_vars%volresv) THEN
+
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ WHERE (a_volresv /= spval)
+ a_volresv = a_volresv / nac_basin
+ END WHERE
+ ENDIF
+ ENDIF
+
+ CALL reservoir_gather_var (a_volresv, varhist)
+
+ IF (p_is_root) THEN
+ CALL ncio_write_serial_time (file_hist_basin, 'volresv', &
+ itime_in_file, varhist, 'reservoir', 'time', DEF_HIST_CompressLevel)
+ IF (itime_in_file == 1) THEN
+ CALL ncio_put_attr (file_hist_basin, 'volresv', 'long_name', 'reservoir water volume')
+ CALL ncio_put_attr (file_hist_basin, 'volresv', 'units', 'm^3')
+ CALL ncio_put_attr (file_hist_basin, 'volresv', 'missing_value', spval)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (DEF_hist_vars%qresv_in) THEN
+
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ WHERE (a_qresv_in /= spval)
+ a_qresv_in = a_qresv_in / nac_basin
+ END WHERE
+ ENDIF
+ ENDIF
+
+ CALL reservoir_gather_var (a_qresv_in, varhist)
+
+ IF (p_is_root) THEN
+ CALL ncio_write_serial_time (file_hist_basin, 'qresv_in', &
+ itime_in_file, varhist, 'reservoir', 'time', DEF_HIST_CompressLevel)
+ IF (itime_in_file == 1) THEN
+ CALL ncio_put_attr (file_hist_basin, 'qresv_in', 'long_name', 'reservoir inflow')
+ CALL ncio_put_attr (file_hist_basin, 'qresv_in', 'units', 'm^3/s')
+ CALL ncio_put_attr (file_hist_basin, 'qresv_in', 'missing_value', spval)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (DEF_hist_vars%qresv_out) THEN
+
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ WHERE (a_qresv_out /= spval)
+ a_qresv_out = a_qresv_out / nac_basin
+ END WHERE
+ ENDIF
+ ENDIF
+
+ CALL reservoir_gather_var (a_qresv_out, varhist)
+
+ IF (p_is_root) THEN
+ CALL ncio_write_serial_time (file_hist_basin, 'qresv_out', &
+ itime_in_file, varhist, 'reservoir', 'time', DEF_HIST_CompressLevel)
+ IF (itime_in_file == 1) THEN
+ CALL ncio_put_attr (file_hist_basin, 'qresv_out', 'long_name', 'reservoir outflow')
+ CALL ncio_put_attr (file_hist_basin, 'qresv_out', 'units', 'm^3/s')
+ CALL ncio_put_attr (file_hist_basin, 'qresv_out', 'missing_value', spval)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ deallocate (varhist)
+
+ ENDIF
+ ENDIF
+
+
+ CALL FLUSH_acc_fluxes_basin ()
+
+ IF (allocated(a_wdsrf_hru)) deallocate(a_wdsrf_hru)
+ IF (allocated(a_veloc_hru)) deallocate(a_veloc_hru)
+
+ IF (allocated(a_wdsrf_elm)) deallocate(a_wdsrf_elm)
+ IF (allocated(a_veloc_elm)) deallocate(a_veloc_elm)
+ IF (allocated(a_dschg_elm)) deallocate(a_dschg_elm)
+ IF (allocated(ntacc_elm )) deallocate(ntacc_elm )
+
+
+ END SUBROUTINE hist_basin_out
+
+ !-----------------------
+ SUBROUTINE FLUSH_acc_fluxes_basin ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandHRU, only: numhru
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ nac_basin = 0
+
+ IF (numbasin > 0) THEN
+ a_wdsrf_bsn(:) = spval
+ a_veloc_riv(:) = spval
+ a_discharge(:) = spval
+ ENDIF
+
+ IF (numelm > 0) a_xsubs_elm (:) = spval
+
+ IF (numbsnhru > 0) THEN
+ a_wdsrf_bsnhru(:) = spval
+ a_veloc_bsnhru(:) = spval
+ ENDIF
+
+ IF (numhru > 0) a_xsubs_hru(:) = spval
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv > 0) a_volresv (:) = spval
+ IF (numresv > 0) a_qresv_in (:) = spval
+ IF (numresv > 0) a_qresv_out(:) = spval
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE FLUSH_acc_fluxes_basin
+
+ ! -------
+ SUBROUTINE accumulate_fluxes_basin
+
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ nac_basin = nac_basin + 1
+
+ IF (numbasin > 0) THEN
+ CALL acc1d_basin (wdsrf_bsn_ta, a_wdsrf_bsn)
+ CALL acc1d_basin (veloc_riv_ta, a_veloc_riv)
+ CALL acc1d_basin (discharge_ta, a_discharge )
+ ENDIF
+
+ IF (numelm > 0) CALL acc1d_basin (xsubs_elm, a_xsubs_elm)
+
+ IF (numbsnhru > 0) THEN
+ CALL acc1d_basin (wdsrf_bsnhru_ta, a_wdsrf_bsnhru)
+ CALL acc1d_basin (veloc_bsnhru_ta, a_veloc_bsnhru)
+ ENDIF
+
+ IF (numhru > 0) CALL acc1d_basin (xsubs_hru, a_xsubs_hru)
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv > 0) CALL acc1d_basin (volresv_ta, a_volresv )
+ IF (numresv > 0) CALL acc1d_basin (qresv_in_ta, a_qresv_in )
+ IF (numresv > 0) CALL acc1d_basin (qresv_out_ta, a_qresv_out)
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE accumulate_fluxes_basin
+
+ ! -------
+ SUBROUTINE acc1d_basin (var, s)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: spval
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: var(:)
+ real(r8), intent(inout) :: s (:)
+ ! Local variables
+ integer :: i
+
+ DO i = lbound(var,1), ubound(var,1)
+ IF (var(i) /= spval) THEN
+ IF (s(i) /= spval) THEN
+ s(i) = s(i) + var(i)
+ ELSE
+ s(i) = var(i)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE acc1d_basin
+
+END MODULE MOD_Catch_Hist
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_LateralFlow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_LateralFlow.F90
new file mode 100644
index 0000000000..6f078ba38c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_LateralFlow.F90
@@ -0,0 +1,496 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_LateralFlow
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Lateral flow.
+!
+! Lateral flows in CoLM include
+! 1. Surface flow over hillslopes;
+! 2. Routing flow in rivers;
+! 3. Groundwater (subsurface) lateral flow.
+!
+! Water exchanges between
+! 1. surface flow and rivers;
+! 2. subsurface flow and rivers.
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Catch_Vars_TimeVariables
+ USE MOD_ElementNeighbour
+ USE MOD_Catch_BasinNetwork
+ USE MOD_Catch_RiverLakeNetwork
+ USE MOD_Catch_HillslopeNetwork
+ USE MOD_Catch_HillslopeFlow
+ USE MOD_Catch_SubsurfaceFlow
+ USE MOD_Catch_RiverLakeFlow
+ USE MOD_Catch_Reservoir
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_Global, only: dz_soi
+ USE MOD_Const_Physical, only: denice, denh2o
+ IMPLICIT NONE
+
+ integer, parameter :: nsubstep = 20
+ real(r8) :: dt_average
+
+ real(r8) :: landarea
+ real(r8), allocatable :: patcharea (:) ! m^2
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE lateral_flow_init (lc_year)
+
+#ifdef CoLMDEBUG
+ USE MOD_SPMD_Task
+ USE MOD_Mesh
+ USE MOD_Pixel
+ USE MOD_LandPatch
+ USE MOD_Utils
+#endif
+ USE MOD_Catch_WriteParameters
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year ! which year of land cover data used
+
+ integer :: ip, ie, ipxl
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+ allocate (patcharea (numpatch))
+ patcharea(:) = 0.
+ DO ip = 1, numpatch
+ ie = landpatch%ielm(ip)
+ DO ipxl = landpatch%ipxstt(ip), landpatch%ipxend(ip)
+ patcharea(ip) = patcharea(ip) + 1.0e6 * areaquad ( &
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDDO
+ IF (landpatch%has_shared) THEN
+ patcharea(ip) = patcharea(ip) * landpatch%pctshared(ip)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ landarea = 0.
+ IF (numpatch > 0) landarea = sum(patcharea)
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, landarea, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+#endif
+ ENDIF
+
+ CALL element_neighbour_init (patcharea, lc_year)
+ CALL river_lake_network_init (patcharea)
+ CALL subsurface_network_init (patcharea)
+ CALL reservoir_init ()
+
+ CALL write_catch_parameters ()
+
+
+ END SUBROUTINE lateral_flow_init
+
+ ! ----------
+ SUBROUTINE lateral_flow (year, deltime)
+
+ USE MOD_Namelist, only: DEF_Reservoir_Method, DEF_USE_Dynamic_Lake
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandHRU, only: landhru, numhru, elm_hru
+ USE MOD_LandPatch, only: numpatch, elm_patch, hru_patch
+
+ USE MOD_Vars_Global, only: nl_lake
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Vars_TimeVariables, only: wdsrf, t_lake, lake_icefrac, t_soisno
+ USE MOD_Vars_TimeInvariants, only: lakedepth, dz_lake
+ USE MOD_Vars_1DFluxes, only: rsur, rsub, rnof
+ USE MOD_Catch_Vars_1DFluxes
+ USE MOD_Catch_Vars_TimeVariables
+ USE MOD_Catch_RiverLakeNetwork
+
+ USE MOD_Lake, only: adjust_lake_layer
+
+ USE MOD_UserDefFun, only : findloc_ud
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: year
+ real(r8), intent(in) :: deltime
+
+ ! Local Variables
+ integer :: i, j, j0, h, ps, pe, istep, s
+ real(r8) :: rnofsrf, sumarea
+ real(r8), allocatable :: wdsrf_p (:), wdsrf_hru_p (:)
+#ifdef CoLMDEBUG
+ real(r8) :: dtolw, tolwat, toldis, maxdvol, maxdvol_g, sumdvol
+ integer :: hs, he, imax, bidmax
+ real(r8), allocatable :: wdsrf_bsnhru_p(:), delvol(:)
+#endif
+
+ IF (p_is_compute) THEN
+
+ ! a) The smallest unit in surface lateral flow (including hillslope flow and river-lake flow)
+ ! is HRU and the main prognostic variable is "wdsrf_bsnhru" (surface water depth).
+ ! b) "wdsrf_bsnhru" is updated by aggregating water depths in patches.
+ ! c) Water surface in a basin ("wdsrf_bsn", defined as the lowest surface water in the basin)
+ ! is derived from "wdsrf_bsnhru".
+ DO i = 1, numhru
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ wdsrf_hru(i) = sum(wdsrf(ps:pe) * hru_patch%subfrc(ps:pe))
+ wdsrf_hru(i) = wdsrf_hru(i) / 1.0e3 ! mm to m
+ ENDDO
+
+ IF (numhru > 0) THEN
+ allocate (wdsrf_hru_p (numhru))
+ wdsrf_hru_p = wdsrf_hru
+ ENDIF
+
+ IF (numpatch > 0) THEN
+ allocate (wdsrf_p (numpatch))
+ wdsrf_p = wdsrf
+ ENDIF
+
+ dt_average = 0.
+
+ IF (numbasin > 0) wdsrf_bsn_ta (:) = 0.
+ IF (numbasin > 0) momen_riv_ta (:) = 0.
+ IF (numbasin > 0) discharge_ta (:) = 0.
+ IF (numbsnhru > 0) wdsrf_bsnhru_ta (:) = 0.
+ IF (numbsnhru > 0) momen_bsnhru_ta (:) = 0.
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv > 0) volresv_ta (:) = 0.
+ IF (numresv > 0) qresv_in_ta (:) = 0.
+ IF (numresv > 0) qresv_out_ta(:) = 0.
+ ENDIF
+
+ CALL compute_push_data (push_elmhru2bsnhru, wdsrf_hru, wdsrf_bsnhru, spval)
+
+#ifdef CoLMDEBUG
+ IF (numbsnhru > 0) THEN
+ allocate (wdsrf_bsnhru_p (numbsnhru))
+ wdsrf_bsnhru_p = wdsrf_bsnhru
+ ENDIF
+#endif
+
+ DO istep = 1, nsubstep
+
+ ! (1) ------------------- Surface flow over hillslopes. -------------------
+ CALL hillslope_flow (deltime/nsubstep)
+
+ ! (2) ----------------------- River and Lake flow. ------------------------
+ CALL river_lake_flow (year, deltime/nsubstep)
+
+ dt_average = dt_average + deltime/nsubstep/ntimestep_riverlake
+
+ ENDDO
+
+ IF (numbasin > 0) THEN
+ wdsrf_bsn_ta(:) = wdsrf_bsn_ta(:) / deltime
+ momen_riv_ta(:) = momen_riv_ta(:) / deltime
+
+ WHERE (wdsrf_bsn_ta > 0)
+ veloc_riv_ta = momen_riv_ta / wdsrf_bsn_ta
+ ELSE WHERE
+ veloc_riv_ta = 0
+ END WHERE
+
+ discharge_ta = discharge_ta / deltime
+ ENDIF
+
+ IF (numbsnhru > 0) THEN
+ wdsrf_bsnhru_ta(:) = wdsrf_bsnhru_ta(:) / deltime
+ momen_bsnhru_ta(:) = momen_bsnhru_ta(:) / deltime
+
+ WHERE (wdsrf_bsnhru_ta > 0)
+ veloc_bsnhru_ta = momen_bsnhru_ta / wdsrf_bsnhru_ta
+ ELSE WHERE
+ veloc_bsnhru_ta = 0.
+ END WHERE
+ ENDIF
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ DO i = 1, numresv
+ IF (year >= dam_build_year(i)) THEN
+ volresv_ta (i) = volresv_ta (i) / deltime
+ qresv_in_ta (i) = qresv_in_ta (i) / deltime
+ qresv_out_ta(i) = qresv_out_ta(i) / deltime
+ ELSE
+ volresv_ta (i) = spval
+ qresv_in_ta (i) = spval
+ qresv_out_ta(i) = spval
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! update surface water depth on patches
+ CALL compute_push_data (push_bsnhru2elmhru, wdsrf_bsnhru, wdsrf_hru, spval)
+ DO i = 1, numhru
+ wdsrf_hru(i) = max(0., wdsrf_hru(i))
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ wdsrf(ps:pe) = wdsrf_hru(i) * 1.0e3 ! m to mm
+ ENDDO
+
+ IF (numpatch > 0) THEN
+ xwsur(:) = (wdsrf_p(:) - wdsrf(:)) / deltime
+ ENDIF
+
+ ! update surface runoff from hillslope to river
+ IF (numpatch > 0) rsur(:) = 0.
+ DO i = 1, numelm
+ IF (lake_id_elm(i) <= 0) THEN
+
+ rnofsrf = 0.
+ sumarea = 0.
+
+ IF (lake_id_elm(i) == 0) THEN
+ j0 = 2 ! regular catchment with river
+ ELSE
+ j0 = 1 ! catchment directly to lake
+ ENDIF
+
+ DO j = j0, hillslope_element(i)%nhru
+ h = hillslope_element(i)%ihru(j)
+ rnofsrf = rnofsrf + (wdsrf_hru_p(h) - wdsrf_hru(h)) * hillslope_element(i)%area(j)
+ sumarea = sumarea + hillslope_element(i)%area(j)
+ ENDDO
+
+ IF (sumarea > 0.) THEN
+ rnofsrf = rnofsrf / sumarea * 1.e3 / deltime ! unit: mm/s
+ DO j = j0, hillslope_element(i)%nhru
+ h = hillslope_element(i)%ihru(j)
+ ps = hru_patch%substt(h)
+ pe = hru_patch%subend(h)
+ rsur(ps:pe) = rnofsrf
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! update fraction of flooded area
+ DO i = 1, numelm
+ IF (lake_id_elm(i) <= 0) THEN
+ DO j = 1, hillslope_element(i)%nhru
+ h = hillslope_element(i)%ihru(j)
+ ps = hru_patch%substt(h)
+ pe = hru_patch%subend(h)
+
+ IF (hillslope_element(i)%indx(j) == 0) THEN
+ fldarea(ps:pe) = 1.0 ! river
+ ELSE
+ s = findloc_ud(hillslope_element(i)%fldprof(:,j) <= wdsrf_hru(h), back = .true.)
+ IF (s == nfldstep) THEN
+ fldarea(ps:pe) = 1.0
+ ELSEIF (s == 0) THEN
+ fldarea(ps:pe) = sqrt(wdsrf_hru(h)/hillslope_element(i)%fldprof(1,j) * 1./nfldstep**2)
+ ELSE
+ fldarea(ps:pe) = sqrt( (wdsrf_hru(h)-hillslope_element(i)%fldprof(s,j)) &
+ / (hillslope_element(i)%fldprof(s+1,j)-hillslope_element(i)%fldprof(s,j)) &
+ * real(2*s+1) / nfldstep**2 + real(s**2)/nfldstep**2 )
+ ENDIF
+ ENDIF
+ ENDDO
+ ELSE
+ ps = elm_patch%substt(i)
+ pe = elm_patch%subend(i)
+ fldarea(ps:pe) = 1.0 ! lake
+ ENDIF
+ ENDDO
+
+#ifdef CoLMDEBUG
+ IF (numbasin > 0) THEN
+
+ allocate (delvol (numbasin))
+
+ delvol(:) = 0
+ DO i = numbasin, 1, -1
+ hs = basin_hru%substt(i)
+ he = basin_hru%subend(i)
+
+ IF (lake_id(i) <= 0) THEN
+ delvol(i) = delvol(i) &
+ + sum((wdsrf_bsnhru_p(hs:he) - wdsrf_bsnhru(hs:he))* hillslope_basin(i)%area)
+ ELSE
+ delvol(i) = delvol(i) &
+ + sum((wdsrf_bsnhru_p(hs:he) - wdsrf_bsnhru(hs:he))* lakeinfo(i)%area0)
+ ENDIF
+
+ IF ((riverdown(i) == 0) .or. (riverdown(i) == -3)) THEN
+ delvol(i) = delvol(i) - discharge_ta(i) * deltime
+ ENDIF
+
+ IF (riversystem == -1) THEN
+ j0 = i; j = ilocdown(i)
+ DO WHILE (j > 0)
+
+ delvol(j) = delvol(j) + delvol(j0)
+ delvol(j0) = 0
+
+ IF ((j > i) .and. (ilocdown(j) > 0)) THEN
+ j0 = j; j = ilocdown(j)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ sumdvol = sum(delvol)
+
+ IF (riversystem /= -1) THEN
+ maxdvol = sum(delvol)
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, maxdvol, 1, MPI_REAL8, MPI_SUM, p_comm_rivsys, p_err)
+ maxdvol = abs(maxdvol)
+ imax = findloc_ud(riverdown <= 0)
+ IF (imax > 0) THEN
+ bidmax = basinindex(imax)
+ ELSE
+ bidmax = 0
+ ENDIF
+ CALL mpi_allreduce (MPI_IN_PLACE, bidmax, 1, MPI_INTEGER, MPI_MAX, p_comm_rivsys, p_err)
+#endif
+ ELSE
+ imax = maxloc(abs(delvol),dim=1)
+ maxdvol = abs(delvol(imax))
+ bidmax = basinindex(imax)
+ ENDIF
+
+ ELSE
+ maxdvol = 0.
+ bidmax = 0
+ sumdvol = 0.
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_allreduce (maxdvol, maxdvol_g, 1, MPI_REAL8, MPI_MAX, p_comm_compute, p_err)
+ IF (maxdvol < maxdvol_g) THEN
+ bidmax = 0
+ ENDIF
+ CALL mpi_allreduce (MPI_IN_PLACE, bidmax, 1, MPI_INTEGER, MPI_MAX, p_comm_compute, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, sumdvol, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+#else
+ maxdvol_g = maxdvol
+#endif
+
+ IF (allocated(wdsrf_bsnhru_p)) deallocate(wdsrf_bsnhru_p)
+ IF (allocated(delvol )) deallocate(delvol )
+#endif
+
+ ! (3) ------------------- Subsurface lateral flow -------------------
+ CALL subsurface_flow (deltime)
+
+ DO i = 1, numpatch
+ h2osoi(:,i) = wliq_soisno(1:,i)/(dz_soi(1:)*denh2o) + wice_soisno(1:,i)/(dz_soi(1:)*denice)
+ wat(i) = sum(wice_soisno(1:,i)+wliq_soisno(1:,i)) + ldew(i) + scv(i) + wetwat(i)
+ ENDDO
+
+ IF (numpatch > 0) rnof = rsur + rsub
+
+ ! (4) ---------------- vertical layers adjustment ---------------------
+ IF (DEF_USE_Dynamic_Lake) THEN
+ DO i = 1, numpatch
+ IF (wdsrf_p(i) >= 100.) THEN
+ ! wet previously
+ dz_lake(:,i) = dz_lake(:,i) * wdsrf(i)*1.e-3/sum(dz_lake(:,i))
+ ELSE
+ ! dry previously
+ dz_lake(:,i) = wdsrf(i)*1.e-3/nl_lake
+ t_lake (:,i) = t_soisno(1,i)
+ IF (t_soisno(1,i) >= tfrz) THEN
+ lake_icefrac(:,i) = 0.
+ ELSE
+ lake_icefrac(:,i) = 1.
+ ENDIF
+ ENDIF
+
+ IF (wdsrf(i) >= 100.) THEN
+ CALL adjust_lake_layer (nl_lake, dz_lake(:,i), t_lake(:,i), lake_icefrac(:,i))
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ENDIF
+
+#ifdef RangeCheck
+ IF (p_is_compute .and. (p_iam_compute == 0)) THEN
+ write(*,'(/,A)') 'Checking Lateral Flow Variables ...'
+ write(*,'(A,F12.5,A)') 'River Lake Flow minimum average timestep: ', &
+ dt_average/nsubstep, ' seconds'
+ ENDIF
+
+ CALL check_vector_data ('Basin Water Depth [m] ', wdsrf_bsn)
+ CALL check_vector_data ('River Velocity [m/s]', veloc_riv)
+ CALL check_vector_data ('HRU Water Depth [m] ', wdsrf_bsnhru)
+ CALL check_vector_data ('HRU Water Velocity [m/s]', veloc_bsnhru)
+ CALL check_vector_data ('Subsurface bt basin [m/s]', xsubs_elm)
+ CALL check_vector_data ('Subsurface bt HRU [m/s]', xsubs_hru)
+ CALL check_vector_data ('Subsurface bt patch [m/s]', xsubs_pch)
+
+#ifdef CoLMDEBUG
+ IF (p_is_compute) THEN
+
+ dtolw = 0
+ toldis = 0
+
+ IF (numpatch > 0) THEN
+ dtolw = sum(patcharea * xwsur ) / 1.e3 * deltime
+ tolwat = sum(patcharea * wdsrf_p) / 1.e3
+ ENDIF
+ IF (numbasin > 0) THEN
+ toldis = sum(discharge_ta*deltime, mask = (riverdown == 0) .or. (riverdown == -3))
+ dtolw = dtolw - toldis
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, dtolw, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, tolwat, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, toldis, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+#endif
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,E9.2,A,I0,A,E9.2,A)') 'River system error: max ', maxdvol_g, &
+ ' m^3 in river mouth ', bidmax, ', total ', sumdvol, ' m^3'
+ write(*,'(A,F12.2,A,ES8.1,A,ES10.3,A)') 'Total surface water error: ', dtolw, &
+ ' m^3 of total ', tolwat, ' m^3, discharge ', toldis, ' m^3'
+ ENDIF
+
+ dtolw = 0
+ IF (numpatch > 0) dtolw = sum(patcharea * xwsub) / 1.e3 * deltime
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, dtolw, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+#endif
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,F12.2,A,ES8.1,A)') 'Total ground water error: ', dtolw, &
+ ' m^3 in area ', landarea, ' m^2'
+ ENDIF
+ ENDIF
+#endif
+#endif
+
+ IF (allocated(wdsrf_p )) deallocate(wdsrf_p )
+ IF (allocated(wdsrf_hru_p)) deallocate(wdsrf_hru_p)
+
+ END SUBROUTINE lateral_flow
+
+ ! ----------
+ SUBROUTINE lateral_flow_final ()
+
+ IMPLICIT NONE
+
+ CALL river_lake_network_final ()
+ CALL subsurface_network_final ()
+ CALL basin_network_final ()
+ CALL reservoir_final ()
+
+ IF (allocated(patcharea)) deallocate(patcharea)
+
+ END SUBROUTINE lateral_flow_final
+
+END MODULE MOD_Catch_LateralFlow
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Reservoir.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Reservoir.F90
new file mode 100644
index 0000000000..62e2a12557
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Reservoir.F90
@@ -0,0 +1,497 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_Reservoir
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Reservoir module in catchment mesh.
+!
+! Created by Shupeng Zhang, July 2025
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Catch_BasinNetwork, only : numbasin, basinindex, numresv, bsn2resv, lake_id, lake_type
+
+ real(r8), allocatable :: dam_elv (:) ! dam elevation [m]
+
+ ! parameters
+ real(r8), allocatable :: volresv_total (:) ! total reservoir volume [m^3]
+ real(r8), allocatable :: volresv_emerg (:) ! emergency reservoir volume [m^3]
+ real(r8), allocatable :: volresv_adjust(:) ! adjustment reservoir volume [m^3]
+ real(r8), allocatable :: volresv_normal(:) ! normal reservoir volume [m^3]
+
+ real(r8), allocatable :: qresv_mean (:) ! mean natural reservoir outflow [m^3/s]
+ real(r8), allocatable :: qresv_flood (:) ! flood reservoir outflow [m^3/s]
+ real(r8), allocatable :: qresv_adjust (:) ! adjustment reservoir outflow [m^3/s]
+ real(r8), allocatable :: qresv_normal (:) ! normal reservoir outflow [m^3/s]
+
+ integer, allocatable :: dam_build_year(:) ! year in which the dam/barrier was built
+
+ ! time variables
+ real(r8), allocatable :: volresv (:) ! reservoir water volume [m^3]
+ real(r8), allocatable :: qresv_in (:) ! reservoir inflow [m^3/s]
+ real(r8), allocatable :: qresv_out (:) ! reservoir outflow [m^3/s]
+
+ ! time average variables for output
+ real(r8), allocatable :: volresv_ta (:) ! reservoir water volume [m^3]
+ real(r8), allocatable :: qresv_in_ta (:) ! inflow to reservoir [m^3/s]
+ real(r8), allocatable :: qresv_out_ta (:) ! outflow from reservoir [m^3/s]
+
+ integer :: numresv_uniq
+ integer, allocatable :: resv_hylak_id (:) ! HydroLAKE ID of reservoir
+ integer, allocatable :: resv_loc2glb (:) ! global index of reservoir
+
+ ! -- PUBLIC SUBROUTINEs --
+ PUBLIC :: reservoir_init
+ PUBLIC :: reservoir_operation
+ PUBLIC :: reservoir_gather_var
+ PUBLIC :: reservoir_final
+
+CONTAINS
+
+ ! -------
+ SUBROUTINE reservoir_init ( )
+
+ USE MOD_Vars_Global, only: spval
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_Utils
+ USE MOD_Catch_RiverLakeNetwork, only : wtsrfelv, bedelv, lakeinfo
+
+ IMPLICIT NONE
+
+ ! Local variables
+ character(len=256) :: basin_info_file, resv_info_file
+ integer :: maxlakeid, mesg(2), isrc, idest, irank
+
+ integer, allocatable :: lake_id_basin (:), ilat_outlet_basin(:), ilon_outlet_basin(:)
+ integer, allocatable :: lake_id_resv (:), ilat_outlet_resv (:), ilon_outlet_resv (:)
+ integer, allocatable :: lake_type_resv(:), lake_id2typ (:)
+ integer, allocatable :: resv_bsn_id (:), idlist (:)
+ integer, allocatable :: all_year_basin(:), all_year_resv (:)
+
+ real(r8), allocatable :: all_vol_basin (:), all_qmean_basin (:), all_qflood_basin (:)
+ real(r8), allocatable :: all_vol_resv (:), all_qmean_resv (:), all_qflood_resv (:)
+ real(r8), allocatable :: all_dhgt_basin(:), all_dhgt_resv (:), dam_height (:)
+
+ real(r8), allocatable :: rcache(:)
+ integer, allocatable :: icache(:)
+ integer :: nbasin, ibasin, irsv, nrecv, nrsv, iloc
+
+
+ IF (p_is_compute) THEN
+
+ IF (numresv > 0) THEN
+
+ allocate (dam_elv (numresv))
+
+ allocate (volresv_total (numresv))
+ allocate (volresv_emerg (numresv))
+ allocate (volresv_adjust(numresv))
+ allocate (volresv_normal(numresv))
+
+ allocate (qresv_mean (numresv))
+ allocate (qresv_flood (numresv))
+ allocate (qresv_adjust (numresv))
+ allocate (qresv_normal (numresv))
+
+ allocate (volresv (numresv))
+ allocate (qresv_in (numresv))
+ allocate (qresv_out (numresv))
+
+ allocate (volresv_ta (numresv))
+ allocate (qresv_in_ta (numresv))
+ allocate (qresv_out_ta (numresv))
+
+ allocate (dam_build_year(numresv))
+
+ allocate (dam_height (numresv))
+
+ ENDIF
+ ENDIF
+
+ ! read in parameters from file.
+ IF (p_is_root) THEN
+
+ basin_info_file = DEF_CatchmentMesh_data
+ CALL ncio_read_serial (basin_info_file, 'lake_id', lake_id_basin )
+ CALL ncio_read_serial (basin_info_file, 'ilat_outlet', ilat_outlet_basin)
+ CALL ncio_read_serial (basin_info_file, 'ilon_outlet', ilon_outlet_basin)
+
+ maxlakeid = maxval(lake_id_basin)
+ IF (maxlakeid > 0) THEN
+
+ resv_info_file = trim(DEF_dir_runtime)//'/HydroLAKES_Reservoir.nc'
+ CALL ncio_read_serial (resv_info_file, 'hylak_id', lake_id_resv )
+ CALL ncio_read_serial (resv_info_file, 'lake_type', lake_type_resv )
+ CALL ncio_read_serial (resv_info_file, 'ilat_outlet', ilat_outlet_resv)
+ CALL ncio_read_serial (resv_info_file, 'ilon_outlet', ilon_outlet_resv)
+ CALL ncio_read_serial (resv_info_file, 'volresv', all_vol_resv )
+ CALL ncio_read_serial (resv_info_file, 'qmean', all_qmean_resv )
+ CALL ncio_read_serial (resv_info_file, 'qflood', all_qflood_resv)
+
+ CALL ncio_read_serial (resv_info_file, 'build_year', all_year_resv)
+ CALL ncio_read_serial (resv_info_file, 'dam_height', all_dhgt_resv)
+
+ allocate (lake_id2typ (-1:maxlakeid))
+ lake_id2typ(:) = 0
+
+ DO irsv = 1, size(lake_id_resv)
+ IF (lake_id_resv(irsv) <= maxlakeid) THEN
+ lake_id2typ(lake_id_resv(irsv)) = lake_type_resv(irsv)
+ ENDIF
+ ENDDO
+
+
+ nbasin = size(lake_id_basin)
+
+ allocate(all_vol_basin (nbasin)); all_vol_basin (:) = spval
+ allocate(all_qmean_basin (nbasin)); all_qmean_basin (:) = spval
+ allocate(all_qflood_basin (nbasin)); all_qflood_basin(:) = spval
+ allocate(all_year_basin (nbasin)); all_year_basin (:) = -99
+ allocate(all_dhgt_basin (nbasin)); all_dhgt_basin (:) = spval
+
+ DO ibasin = 1, nbasin
+ IF (lake_id2typ(lake_id_basin(ibasin)) >= 2) THEN
+ DO irsv = 1, size(lake_id_resv)
+ IF (lake_id_basin(ibasin) == lake_id_resv(irsv)) THEN
+ IF (ilat_outlet_basin(ibasin) == ilat_outlet_resv(irsv)) THEN
+ IF (ilon_outlet_basin(ibasin) == ilon_outlet_resv(irsv)) THEN
+ all_vol_basin (ibasin) = all_vol_resv (irsv)
+ all_qmean_basin (ibasin) = all_qmean_resv (irsv)
+ all_qflood_basin(ibasin) = all_qflood_resv(irsv)
+ all_year_basin (ibasin) = all_year_resv (irsv)
+ all_dhgt_basin (ibasin) = all_dhgt_resv (irsv)
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ allocate (resv_bsn_id (numresv))
+ resv_bsn_id = pack(basinindex, lake_type >= 2)
+ ENDIF
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ DO irank = 0, p_np_compute-1
+
+ CALL mpi_recv (mesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ nrecv = mesg(2)
+
+ IF (nrecv > 0) THEN
+
+ allocate (resv_bsn_id (nrecv))
+ allocate (rcache (nrecv))
+ allocate (icache (nrecv))
+
+ CALL mpi_recv (resv_bsn_id, nrecv, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ idest = isrc
+
+ rcache = all_vol_basin(resv_bsn_id)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = all_qmean_basin(resv_bsn_id)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = all_qflood_basin(resv_bsn_id)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ icache = all_year_basin(resv_bsn_id)
+ CALL mpi_send (icache, nrecv, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = all_dhgt_basin(resv_bsn_id)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (resv_bsn_id)
+ deallocate (rcache)
+ deallocate (icache)
+
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ mesg(1:2) = (/p_iam_glb, numresv/)
+ CALL mpi_send (mesg(1:2), 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numresv > 0) THEN
+ CALL mpi_send (resv_bsn_id, numresv, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ CALL mpi_recv (volresv_total, numresv, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ CALL mpi_recv (qresv_mean, numresv, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ CALL mpi_recv (qresv_flood, numresv, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ CALL mpi_recv (dam_build_year, numresv, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ CALL mpi_recv (dam_height, numresv, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+#else
+ IF (numresv > 0) THEN
+ volresv_total = all_vol_basin (resv_bsn_id)
+ qresv_mean = all_qmean_basin (resv_bsn_id)
+ qresv_flood = all_qflood_basin(resv_bsn_id)
+ dam_build_year = all_year_basin (resv_bsn_id)
+ dam_height = all_dhgt_basin (resv_bsn_id)
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+ DO ibasin = 1, numbasin
+ IF (lake_type(ibasin) >= 2) THEN
+
+ irsv = bsn2resv(ibasin)
+
+ dam_height(irsv) = max(dam_height(irsv), wtsrfelv(ibasin)-bedelv(ibasin))
+ dam_height(irsv) = max(dam_height(irsv), lakeinfo(ibasin)%surface(volresv_total(irsv)))
+ dam_height(irsv) = min(dam_height(irsv), 335.)
+
+ dam_elv (irsv) = bedelv(ibasin) + dam_height(irsv)
+ volresv_total (irsv) = lakeinfo(ibasin)%volume( dam_height(irsv) )
+
+ volresv_emerg (irsv) = volresv_total(irsv) * 0.94
+ volresv_adjust(irsv) = volresv_total(irsv) * 0.77
+ volresv_normal(irsv) = volresv_total(irsv) * 0.7
+
+ qresv_normal (irsv) = volresv_normal(irsv)*0.7/(180*86400) + qresv_mean(irsv)*0.25
+ qresv_adjust (irsv) = (qresv_normal(irsv) + qresv_flood(irsv)) * 0.5
+ ENDIF
+ ENDDO
+ ENDIF
+
+
+ IF (p_is_root) THEN
+
+ nrsv = count(lake_id2typ(lake_id_basin) >= 2)
+
+ IF (nrsv > 0) THEN
+
+ allocate (idlist (nrsv))
+
+ numresv_uniq = 0
+ DO ibasin = 1, size(lake_id_basin)
+ IF (lake_id2typ(lake_id_basin(ibasin)) >= 2) THEN
+ CALL insert_into_sorted_list1 ( &
+ lake_id_basin(ibasin), numresv_uniq, idlist, iloc)
+ ENDIF
+ ENDDO
+
+ allocate (resv_hylak_id (numresv_uniq))
+ resv_hylak_id = idlist(1:numresv_uniq)
+
+ deallocate (idlist)
+
+ ELSE
+ numresv_uniq = 0
+ ENDIF
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (numresv_uniq, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+ IF (numresv_uniq > 0) THEN
+ IF (.not. p_is_root) allocate (resv_hylak_id (numresv_uniq))
+ CALL mpi_bcast (resv_hylak_id, numresv_uniq, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ allocate (resv_loc2glb (numresv))
+ DO ibasin = 1, numbasin
+ IF (lake_type(ibasin) >= 2) THEN
+ resv_loc2glb(bsn2resv(ibasin)) = &
+ find_in_sorted_list1 (lake_id(ibasin), numresv_uniq, resv_hylak_id)
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+ IF (allocated(lake_id2typ )) deallocate (lake_id2typ )
+ IF (allocated(lake_id_basin )) deallocate (lake_id_basin )
+ IF (allocated(ilat_outlet_basin)) deallocate (ilat_outlet_basin)
+ IF (allocated(ilon_outlet_basin)) deallocate (ilon_outlet_basin)
+ IF (allocated(lake_id_resv )) deallocate (lake_id_resv )
+ IF (allocated(lake_type_resv )) deallocate (lake_type_resv )
+ IF (allocated(ilat_outlet_resv )) deallocate (ilat_outlet_resv )
+ IF (allocated(ilon_outlet_resv )) deallocate (ilon_outlet_resv )
+ IF (allocated(all_qmean_basin )) deallocate (all_qmean_basin )
+ IF (allocated(all_qflood_basin )) deallocate (all_qflood_basin )
+ IF (allocated(all_qmean_resv )) deallocate (all_qmean_resv )
+ IF (allocated(all_qflood_resv )) deallocate (all_qflood_resv )
+ IF (allocated(all_year_basin )) deallocate (all_year_basin )
+ IF (allocated(all_year_resv )) deallocate (all_year_resv )
+ IF (allocated(all_dhgt_basin )) deallocate (all_dhgt_basin )
+ IF (allocated(all_dhgt_resv )) deallocate (all_dhgt_resv )
+ IF (allocated(dam_height )) deallocate (dam_height )
+ IF (allocated(resv_bsn_id )) deallocate (resv_bsn_id )
+
+
+ END SUBROUTINE reservoir_init
+
+
+ SUBROUTINE reservoir_operation (method, irsv, qin, vol, qout)
+
+ IMPLICIT NONE
+ integer, intent(in) :: method
+ integer, intent(in) :: irsv
+ real(r8), intent(in) :: qin, vol
+ real(r8), intent(out) :: qout
+
+ ! local variables
+ real(r8) :: q1
+
+ IF (method == 1) THEN
+ ! *** Reference ***
+ ! [1] Mizuki Funato, Dai Yamazaki, Dung Trung Vu.
+ ! Development of an improved reservoir operation scheme for global flood modeling.
+ ! ESS Open Archive . October 24, 2024.
+
+ IF (vol > volresv_emerg(irsv)) THEN
+ qout = max(qin, qresv_flood(irsv))
+ ELSEIF (vol > volresv_adjust(irsv)) THEN
+ qout = qresv_adjust(irsv) + (qresv_flood(irsv)-qresv_adjust(irsv)) &
+ * ((vol-volresv_adjust(irsv))/(volresv_emerg(irsv)-volresv_adjust(irsv)))**0.1
+ IF (qin > qresv_flood(irsv)) THEN
+ q1 = qresv_normal(irsv) + (qin-qresv_normal(irsv)) &
+ * (vol-volresv_normal(irsv))/(volresv_emerg(irsv)-volresv_normal(irsv))
+ qout = max(q1, qout)
+ ENDIF
+ ELSEIF (vol > volresv_normal(irsv)) THEN
+ qout = qresv_normal(irsv) + (qresv_adjust(irsv)-qresv_normal(irsv)) &
+ * ((vol-volresv_normal(irsv))/(volresv_adjust(irsv)-volresv_normal(irsv)))**3.
+ ELSE
+ qout = (vol/volresv_normal(irsv))**0.5 * qresv_normal(irsv)
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE reservoir_operation
+
+
+ SUBROUTINE reservoir_gather_var (varin, varout)
+
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: varin (:)
+ real(r8), intent(out) :: varout (:)
+
+ ! local variables
+ integer :: irsv, irank
+ real(r8), allocatable :: varall (:,:)
+
+ IF (numresv_uniq == 0) RETURN
+
+ IF (p_is_compute) THEN
+ varout(:) = spval
+ DO irsv = 1, numresv
+ IF (varin(irsv) /= spval) THEN
+ IF (varout(resv_loc2glb(irsv)) /= spval) THEN
+ varout(resv_loc2glb(irsv)) = varout(resv_loc2glb(irsv)) + varin(irsv)
+ ELSE
+ varout(resv_loc2glb(irsv)) = varin(irsv)
+ ENDIF
+ ENDIF
+ ENDDO
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (varall (numresv_uniq,0:p_np_compute-1))
+ ENDIF
+
+ CALL mpi_gather (varout, numresv_uniq, MPI_REAL8, &
+ varall, numresv_uniq, MPI_REAL8, p_root, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+
+ DO irsv = 1, numresv_uniq
+ DO irank = 0, p_np_compute-1
+ IF (irank /= p_root) THEN
+ IF (varall(irsv,irank) /= spval) THEN
+ IF (varout(irsv) /= spval) THEN
+ varout(irsv) = varout(irsv) + varall(irsv,irank)
+ ELSE
+ varout(irsv) = varall(irsv,irank)
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (varall)
+ ENDIF
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ CALL mpi_send (varout, numresv_uniq, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ IF (p_is_root) THEN
+ CALL mpi_recv (varout, numresv_uniq, MPI_REAL8, p_address_compute(p_root), &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+#endif
+
+ END SUBROUTINE reservoir_gather_var
+
+
+ SUBROUTINE reservoir_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(dam_elv )) deallocate (dam_elv )
+
+ IF (allocated(resv_hylak_id )) deallocate (resv_hylak_id )
+ IF (allocated(resv_loc2glb )) deallocate (resv_loc2glb )
+
+ IF (allocated(volresv_total )) deallocate (volresv_total )
+ IF (allocated(volresv_emerg )) deallocate (volresv_emerg )
+ IF (allocated(volresv_adjust)) deallocate (volresv_adjust)
+ IF (allocated(volresv_normal)) deallocate (volresv_normal)
+
+ IF (allocated(qresv_mean )) deallocate (qresv_mean )
+ IF (allocated(qresv_flood )) deallocate (qresv_flood )
+ IF (allocated(qresv_adjust )) deallocate (qresv_adjust )
+ IF (allocated(qresv_normal )) deallocate (qresv_normal )
+
+ IF (allocated(dam_build_year)) deallocate (dam_build_year)
+
+ IF (allocated(volresv )) deallocate (volresv )
+ IF (allocated(qresv_in )) deallocate (qresv_in )
+ IF (allocated(qresv_out )) deallocate (qresv_out )
+
+ IF (allocated(volresv_ta )) deallocate (volresv_ta )
+ IF (allocated(qresv_in_ta )) deallocate (qresv_in_ta )
+ IF (allocated(qresv_out_ta )) deallocate (qresv_out_ta )
+
+ END SUBROUTINE reservoir_final
+
+END MODULE MOD_Catch_Reservoir
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_RiverLakeFlow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_RiverLakeFlow.F90
new file mode 100644
index 0000000000..f0c83ba2d8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_RiverLakeFlow.F90
@@ -0,0 +1,596 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_RiverLakeFlow
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Shallow water equation solver in rivers.
+!
+! References
+! [1] Toro EF. Shock-capturing methods for free-surface shallow flows.
+! Chichester: John Wiley & Sons; 2001.
+! [2] Liang, Q., Borthwick, A. G. L. (2009). Adaptive quadtree simulation of shallow
+! flows with wet-dry fronts over complex topography.
+! Computers and Fluids, 38(2), 221-234.
+! [3] Audusse, E., Bouchut, F., Bristeau, M.-O., Klein, R., Perthame, B. (2004).
+! A Fast and Stable Well-Balanced Scheme with Hydrostatic Reconstruction for
+! Shallow Water Flows. SIAM Journal on Scientific Computing, 25(6), 2050-2065.
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), parameter :: nmanning_riv = 0.03
+
+ real(r8), parameter :: RIVERMIN = 1.e-5_r8
+ real(r8), parameter :: VOLUMEMIN = 1.e-5_r8
+
+ integer :: ntimestep_riverlake
+
+CONTAINS
+
+ ! ---------
+ SUBROUTINE river_lake_flow (year, dt)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only : DEF_Reservoir_Method
+ USE MOD_Utils
+ USE MOD_Catch_BasinNetwork
+ USE MOD_Catch_HillslopeNetwork
+ USE MOD_Catch_RiverLakeNetwork
+ USE MOD_Catch_Reservoir
+ USE MOD_Catch_Vars_TimeVariables
+ USE MOD_Catch_Vars_1DFluxes
+ USE MOD_Const_Physical, only: grav
+ IMPLICIT NONE
+
+ integer, intent(in) :: year
+ real(r8), intent(in) :: dt
+
+ ! Local Variables
+ integer :: hs, he, i, j, irsv
+ real(r8) :: dt_this
+
+ real(r8), allocatable :: wdsrf_bsn_ds(:)
+ real(r8), allocatable :: veloc_riv_ds(:)
+ real(r8), allocatable :: momen_riv_ds(:)
+
+ real(r16), allocatable :: hflux_fc(:)
+ real(r16), allocatable :: mflux_fc(:)
+ real(r16), allocatable :: zgrad_dn(:)
+
+ real(r16), allocatable :: hflux_resv(:)
+ real(r16), allocatable :: mflux_resv(:)
+
+ real(r16), allocatable :: sum_hflux_riv(:)
+ real(r16), allocatable :: sum_mflux_riv(:)
+ real(r16), allocatable :: sum_zgrad_riv(:)
+
+ real(r8) :: veloct_fc, height_fc, momen_fc, zsurf_fc
+ real(r8) :: bedelv_fc, height_up, height_dn
+ real(r8) :: vwave_up, vwave_dn, hflux_up, hflux_dn, mflux_up, mflux_dn
+ real(r8) :: totalvolume, friction, dvol, nextl, nexta, nextv, ddep
+ real(r8), allocatable :: dt_res(:), dt_all(:), dt_tmp(:)
+ logical, allocatable :: hmask(:), bsnfilter(:)
+
+
+ IF (p_is_compute) THEN
+
+ ! update water depth in basin by aggregating water depths in patches
+ DO i = 1, numbasin
+ hs = basin_hru%substt(i)
+ he = basin_hru%subend(i)
+
+ IF (lake_id(i) <= 0) THEN
+ ! river or lake catchment
+ ! Water surface in a basin is defined as the lowest surface water in the basin
+ wdsrf_bsn(i) = minval(hillslope_basin(i)%hand + wdsrf_bsnhru(hs:he)) - handmin(i)
+
+ ELSEIF (lake_id(i) > 0) THEN
+ ! lake
+ totalvolume = sum(wdsrf_bsnhru(hs:he) * lakeinfo(i)%area0)
+ wdsrf_bsn(i) = lakeinfo(i)%surface(totalvolume)
+ ENDIF
+
+
+ IF (lake_id(i) == 0) THEN
+ ! river momentum is less or equal than the momentum at last time step.
+ IF (wdsrf_bsn_prev(i) < wdsrf_bsn(i)) THEN
+ momen_riv(i) = wdsrf_bsn_prev(i) * veloc_riv(i)
+ veloc_riv(i) = momen_riv(i) / wdsrf_bsn(i)
+ ELSE
+ momen_riv(i) = wdsrf_bsn(i) * veloc_riv(i)
+ ENDIF
+ ELSE
+ ! water in lake or lake catchment is assumued to be stationary.
+ ! TODO: lake dynamics
+ momen_riv(i) = 0
+ veloc_riv(i) = 0
+ ENDIF
+
+ ENDDO
+
+ IF (numbasin > 0) THEN
+
+ allocate (wdsrf_bsn_ds (numbasin))
+ allocate (veloc_riv_ds (numbasin))
+ allocate (momen_riv_ds (numbasin))
+ allocate (hflux_fc (numbasin))
+ allocate (mflux_fc (numbasin))
+ allocate (zgrad_dn (numbasin))
+ allocate (sum_hflux_riv (numbasin))
+ allocate (sum_mflux_riv (numbasin))
+ allocate (sum_zgrad_riv (numbasin))
+ allocate (bsnfilter (numbasin))
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ allocate (hflux_resv (numbasin))
+ allocate (mflux_resv (numbasin))
+ ENDIF
+
+ ENDIF
+
+ allocate (dt_res (numrivsys))
+ allocate (dt_all (numrivsys))
+
+ ntimestep_riverlake = 0
+
+ dt_res(:) = dt
+
+ DO WHILE (any(dt_res > 0))
+
+ ntimestep_riverlake = ntimestep_riverlake + 1
+
+ DO i = 1, numbasin
+ bsnfilter(i) = dt_res(irivsys(i)) > 0
+ IF (bsnfilter(i)) THEN
+ sum_hflux_riv(i) = 0.
+ sum_mflux_riv(i) = 0.
+ sum_zgrad_riv(i) = 0.
+ ENDIF
+ ENDDO
+
+ WHERE (bsnfilter) ntacc_bsn = ntacc_bsn + 1
+
+ CALL pull_from_downstream (wdsrf_bsn, wdsrf_bsn_ds, bsnfilter)
+ CALL pull_from_downstream (veloc_riv, veloc_riv_ds, bsnfilter)
+ CALL pull_from_downstream (momen_riv, momen_riv_ds, bsnfilter)
+
+ ! velocity in ocean or inland depression is assumed to be 0.
+ IF (numbasin > 0) THEN
+ WHERE (riverdown <= 0)
+ veloc_riv_ds = 0.
+ END WHERE
+ ENDIF
+
+ dt_all(:) = dt_res(:)
+
+ DO i = 1, numbasin
+
+ IF (.not. bsnfilter(i)) CYCLE
+
+ IF (riverdown(i) >= 0) THEN
+
+ IF (riverdown(i) > 0) THEN
+ ! both elements are dry.
+ IF ((wdsrf_bsn(i) < RIVERMIN) .and. (wdsrf_bsn_ds(i) < RIVERMIN)) THEN
+ hflux_fc(i) = 0
+ mflux_fc(i) = 0
+ zgrad_dn(i) = 0
+ CYCLE
+ ENDIF
+ ENDIF
+
+ ! reconstruction of height of water near interface
+ IF (riverdown(i) > 0) THEN
+ bedelv_fc = max(bedelv(i), bedelv_ds(i))
+ IF ((lake_type(i) == 2) .or. (lake_type(i) == 3)) THEN
+ ! for reservoir (type=2) or controlled lake (type=3)
+ IF ((DEF_Reservoir_Method > 0) &
+ .and. (year >= dam_build_year(bsn2resv(i)))) THEN
+ bedelv_fc = max(bedelv_fc, dam_elv(bsn2resv(i)))
+ ENDIF
+ ENDIF
+ height_up = max(0., wdsrf_bsn(i) +bedelv(i) -bedelv_fc)
+ height_dn = max(0., wdsrf_bsn_ds(i)+bedelv_ds(i)-bedelv_fc)
+ ELSEIF (riverdown(i) == 0) THEN ! for river mouth
+ bedelv_fc = bedelv(i)
+ height_up = wdsrf_bsn(i)
+ ! sea level is assumed to be 0. and sea bed is assumed to be negative infinity.
+ height_dn = max(0., - bedelv_fc)
+ ENDIF
+
+ ! velocity at river downstream face (middle region in Riemann problem)
+ veloct_fc = 0.5 * (veloc_riv(i) + veloc_riv_ds(i)) &
+ + sqrt(grav * height_up) - sqrt(grav * height_dn)
+
+ ! height of water at downstream face (middle region in Riemann problem)
+ height_fc = 1/grav * (0.5*(sqrt(grav*height_up) + sqrt(grav*height_dn)) &
+ + 0.25 * (veloc_riv(i) - veloc_riv_ds(i))) ** 2
+
+ IF (height_up > 0) THEN
+ vwave_up = min(veloc_riv(i)-sqrt(grav*height_up), veloct_fc-sqrt(grav*height_fc))
+ ELSE
+ vwave_up = veloc_riv_ds(i) - 2.0 * sqrt(grav*height_dn)
+ ENDIF
+
+ IF (height_dn > 0) THEN
+ vwave_dn = max(veloc_riv_ds(i)+sqrt(grav*height_dn), veloct_fc+sqrt(grav*height_fc))
+ ELSE
+ vwave_dn = veloc_riv(i) + 2.0 * sqrt(grav*height_up)
+ ENDIF
+
+ hflux_up = veloc_riv(i) * height_up
+ hflux_dn = veloc_riv_ds(i) * height_dn
+ mflux_up = veloc_riv(i)**2 * height_up + 0.5*grav * height_up**2
+ mflux_dn = veloc_riv_ds(i)**2 * height_dn + 0.5*grav * height_dn**2
+
+ IF (vwave_up >= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_up
+ mflux_fc(i) = outletwth(i) * mflux_up
+ ELSEIF (vwave_dn <= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_dn
+ mflux_fc(i) = outletwth(i) * mflux_dn
+ ELSE
+ hflux_fc(i) = outletwth(i) * (vwave_dn*hflux_up - vwave_up*hflux_dn &
+ + vwave_up*vwave_dn*(height_dn-height_up)) / (vwave_dn-vwave_up)
+ mflux_fc(i) = outletwth(i) * (vwave_dn*mflux_up - vwave_up*mflux_dn &
+ + vwave_up*vwave_dn*(hflux_dn-hflux_up)) / (vwave_dn-vwave_up)
+ ENDIF
+
+ sum_zgrad_riv(i) = sum_zgrad_riv(i) + outletwth(i) * 0.5*grav * height_up**2
+
+ zgrad_dn(i) = outletwth(i) * 0.5*grav * height_dn**2
+
+ ELSEIF (riverdown(i) == -3) THEN
+ ! downstream is not in model region.
+ ! assume: 1. downstream river bed is equal to this river bed.
+ ! 2. downstream water surface is equal to this river depth.
+ ! 3. downstream water velocity is equal to this velocity.
+
+ veloc_riv(i) = max(veloc_riv(i), 0.)
+
+ IF (wdsrf_bsn(i) > riverdpth(i)) THEN
+
+ ! reconstruction of height of water near interface
+ height_up = wdsrf_bsn(i)
+ height_dn = riverdpth(i)
+
+ veloct_fc = veloc_riv(i) + sqrt(grav * height_up) - sqrt(grav * height_dn)
+ height_fc = 1/grav * (0.5*(sqrt(grav*height_up) + sqrt(grav*height_dn))) ** 2
+
+ vwave_up = min(veloc_riv(i)-sqrt(grav*height_up), veloct_fc-sqrt(grav*height_fc))
+ vwave_dn = max(veloc_riv(i)+sqrt(grav*height_dn), veloct_fc+sqrt(grav*height_fc))
+
+ hflux_up = veloc_riv(i) * height_up
+ hflux_dn = veloc_riv(i) * height_dn
+ mflux_up = veloc_riv(i)**2 * height_up + 0.5*grav * height_up**2
+ mflux_dn = veloc_riv(i)**2 * height_dn + 0.5*grav * height_dn**2
+
+ IF (vwave_up >= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_up
+ mflux_fc(i) = outletwth(i) * mflux_up
+ ELSEIF (vwave_dn <= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_dn
+ mflux_fc(i) = outletwth(i) * mflux_dn
+ ELSE
+ hflux_fc(i) = outletwth(i) * (vwave_dn*hflux_up - vwave_up*hflux_dn &
+ + vwave_up*vwave_dn*(height_dn-height_up)) / (vwave_dn-vwave_up)
+ mflux_fc(i) = outletwth(i) * (vwave_dn*mflux_up - vwave_up*mflux_dn &
+ + vwave_up*vwave_dn*(hflux_dn-hflux_up)) / (vwave_dn-vwave_up)
+ ENDIF
+
+ sum_zgrad_riv(i) = sum_zgrad_riv(i) + outletwth(i) * 0.5*grav * height_up**2
+
+ ELSE
+ hflux_fc(i) = 0
+ mflux_fc(i) = 0
+ ENDIF
+
+ ELSEIF (riverdown(i) == -1) THEN ! inland depression
+ hflux_fc(i) = 0
+ mflux_fc(i) = 0
+ ENDIF
+
+ IF ((lake_id(i) < 0) .and. (hflux_fc(i) < 0)) THEN
+ dt_this = dt_all(irivsys(i))
+ hflux_fc(i) = &
+ max(hflux_fc(i), (height_up-height_dn) / dt_this * sum(hillslope_basin(i)%area, &
+ mask = hillslope_basin(i)%hand <= wdsrf_bsn(i) + handmin(i)))
+ ENDIF
+
+ ! reservoir operation.
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (lake_type(i) == 2) THEN
+ IF (year >= dam_build_year(bsn2resv(i))) THEN
+ hflux_fc(i) = 0.
+ mflux_fc(i) = 0.
+ zgrad_dn(i) = 0.
+ ENDIF
+ ENDIF
+ ENDIF
+
+ sum_hflux_riv(i) = sum_hflux_riv(i) + hflux_fc(i)
+ sum_mflux_riv(i) = sum_mflux_riv(i) + mflux_fc(i)
+
+ ENDDO
+
+ IF (numbasin > 0) THEN
+ hflux_fc = - hflux_fc; mflux_fc = - mflux_fc; zgrad_dn = - zgrad_dn
+ ENDIF
+
+ CALL push_to_downstream (hflux_fc, sum_hflux_riv, bsnfilter)
+ CALL push_to_downstream (mflux_fc, sum_mflux_riv, bsnfilter)
+ CALL push_to_downstream (zgrad_dn, sum_zgrad_riv, bsnfilter)
+
+ IF (numbasin > 0) THEN
+ hflux_fc = - hflux_fc; mflux_fc = - mflux_fc; zgrad_dn = - zgrad_dn
+ ENDIF
+
+ ! reservoir operation.
+ IF (DEF_Reservoir_Method > 0) THEN
+
+ DO i = 1, numbasin
+
+ hflux_resv(i) = 0.
+ mflux_resv(i) = 0.
+
+ IF (bsnfilter(i)) THEN
+ IF ((lake_type(i) == 2) .and. (riverdown(i) /= -1)) THEN
+ IF (year >= dam_build_year(bsn2resv(i))) THEN
+
+ irsv = bsn2resv(i)
+ qresv_in(irsv) = - sum_hflux_riv(i)
+ volresv (irsv) = lakeinfo(i)%volume( wdsrf_bsn(i) )
+
+ IF (volresv(irsv) > 1.e-4 * volresv_total(irsv)) THEN
+ CALL reservoir_operation (DEF_Reservoir_Method, &
+ irsv, qresv_in(irsv), volresv(irsv), qresv_out(irsv))
+ ELSE
+ qresv_out (irsv) = 0.
+ ENDIF
+
+ hflux_fc(i) = qresv_out(irsv)
+ mflux_fc(i) = qresv_out(irsv) * sqrt(2*grav*wdsrf_bsn(i))
+
+ sum_hflux_riv(i) = sum_hflux_riv(i) + hflux_fc(i)
+ sum_mflux_riv(i) = sum_mflux_riv(i) + mflux_fc(i)
+
+ hflux_resv(i) = - hflux_fc(i)
+ mflux_resv(i) = - mflux_fc(i)
+
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+ CALL push_to_downstream (hflux_resv, sum_hflux_riv, bsnfilter)
+ CALL push_to_downstream (mflux_resv, sum_mflux_riv, bsnfilter)
+
+ ENDIF
+
+ DO i = 1, numbasin
+
+ IF (.not. bsnfilter(i)) CYCLE
+
+ dt_this = dt_all(irivsys(i))
+
+ ! constraint 1: CFL condition (only for rivers)
+ IF ((lake_id(i) == 0) .and. (riverdown(i) /= -1)) THEN
+ IF ((veloc_riv(i) /= 0.) .or. (wdsrf_bsn(i) > 0.)) THEN
+ dt_this = min(dt_this, riverlen(i)/(abs(veloc_riv(i))+sqrt(grav*wdsrf_bsn(i)))*0.8)
+ ENDIF
+ ENDIF
+
+ ! constraint 2: Avoid negative values of water
+ IF (sum_hflux_riv(i) > 0) THEN
+ IF (lake_id(i) <= 0) THEN
+ ! for river or lake catchment
+ totalvolume = sum((wdsrf_bsn(i) + handmin(i) - hillslope_basin(i)%hand) &
+ * hillslope_basin(i)%area, &
+ mask = wdsrf_bsn(i) + handmin(i) >= hillslope_basin(i)%hand)
+ ELSEIF (lake_id(i) > 0) THEN
+ ! for lake
+ totalvolume = lakeinfo(i)%volume(wdsrf_bsn(i))
+ ENDIF
+
+ dt_this = min(dt_this, totalvolume / sum_hflux_riv(i))
+
+ ENDIF
+
+ ! constraint 3: Avoid change of flow direction (only for rivers)
+ IF (lake_id(i) == 0) THEN
+ IF ((abs(veloc_riv(i)) > 0.1) &
+ .and. (veloc_riv(i) * (sum_mflux_riv(i)-sum_zgrad_riv(i)) > 0)) THEN
+ dt_this = min(dt_this, &
+ abs(momen_riv(i) * riverarea(i) / (sum_mflux_riv(i)-sum_zgrad_riv(i))))
+ ENDIF
+ ENDIF
+
+ dt_all(irivsys(i)) = min(dt_this, dt_all(irivsys(i)))
+
+ ENDDO
+
+#ifdef USEMPI
+ IF (riversystem /= -1) THEN
+ CALL mpi_allreduce (MPI_IN_PLACE, dt_all, 1, MPI_REAL8, MPI_MIN, p_comm_rivsys, p_err)
+ ENDIF
+#endif
+
+ DO i = 1, numbasin
+
+ IF (.not. bsnfilter(i)) CYCLE
+
+ IF (lake_id(i) <= 0) THEN
+ ! rivers or lake catchments
+ hs = basin_hru%substt(i)
+ he = basin_hru%subend(i)
+ allocate (hmask (hillslope_basin(i)%nhru))
+
+ totalvolume = sum((wdsrf_bsn(i) + handmin(i) - hillslope_basin(i)%hand) &
+ * hillslope_basin(i)%area, &
+ mask = wdsrf_bsn(i) + handmin(i) >= hillslope_basin(i)%hand)
+
+ totalvolume = totalvolume - sum_hflux_riv(i) * dt_all(irivsys(i))
+
+ IF (totalvolume < VOLUMEMIN) THEN
+ DO j = 1, hillslope_basin(i)%nhru
+ IF (hillslope_basin(i)%hand(j) <= wdsrf_bsn(i) + handmin(i)) THEN
+ wdsrf_bsnhru(j+hs-1) = wdsrf_bsnhru(j+hs-1) &
+ - (wdsrf_bsn(i) + handmin(i) - hillslope_basin(i)%hand(j))
+ ENDIF
+ ENDDO
+ wdsrf_bsn(i) = 0
+ ELSE
+
+ dvol = sum_hflux_riv(i) * dt_all(irivsys(i))
+ IF (dvol > VOLUMEMIN) THEN
+ DO WHILE (dvol > VOLUMEMIN)
+ hmask = hillslope_basin(i)%hand < wdsrf_bsn(i) + handmin(i)
+ nextl = maxval(hillslope_basin(i)%hand, mask = hmask)
+ nexta = sum (hillslope_basin(i)%area, mask = hmask)
+ nextv = nexta * (wdsrf_bsn(i)+handmin(i)-nextl)
+ IF (nextv > dvol) THEN
+ ddep = dvol/nexta
+ dvol = 0.
+ ELSE
+ ddep = wdsrf_bsn(i)+handmin(i) - nextl
+ dvol = dvol - nextv
+ ENDIF
+
+ wdsrf_bsn(i) = wdsrf_bsn(i) - ddep
+
+ DO j = 1, hillslope_basin(i)%nhru
+ IF (hmask(j)) THEN
+ wdsrf_bsnhru(j+hs-1) = wdsrf_bsnhru(j+hs-1) - ddep
+ ENDIF
+ ENDDO
+ ENDDO
+ ELSEIF (dvol < -VOLUMEMIN) THEN
+ hmask = .true.
+ nexta = 0.
+ DO WHILE (dvol < -VOLUMEMIN)
+ IF (any(hmask)) THEN
+ j = minloc(hillslope_basin(i)%hand + wdsrf_bsnhru(hs:he), 1, mask = hmask)
+ nexta = nexta + hillslope_basin(i)%area(j)
+ hmask(j) = .false.
+ ENDIF
+ IF (any(hmask)) THEN
+ nextl = minval(hillslope_basin(i)%hand + wdsrf_bsnhru(hs:he), mask = hmask)
+ nextv = nexta*(nextl-(wdsrf_bsn(i)+handmin(i)))
+ IF ((-dvol) > nextv) THEN
+ ddep = nextl - (wdsrf_bsn(i)+handmin(i))
+ dvol = dvol + nextv
+ ELSE
+ ddep = (-dvol)/nexta
+ dvol = 0.
+ ENDIF
+ ELSE
+ ddep = (-dvol)/nexta
+ dvol = 0.
+ ENDIF
+
+ wdsrf_bsn(i) = wdsrf_bsn(i) + ddep
+
+ DO j = 1, hillslope_basin(i)%nhru
+ IF (.not. hmask(j)) THEN
+ wdsrf_bsnhru(j+hs-1) = wdsrf_bsnhru(j+hs-1) + ddep
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+
+ ENDIF
+ deallocate(hmask)
+
+ ELSE
+ totalvolume = lakeinfo(i)%volume(wdsrf_bsn(i))
+ totalvolume = totalvolume - sum_hflux_riv(i) * dt_all(irivsys(i))
+ wdsrf_bsn(i) = lakeinfo(i)%surface(totalvolume)
+ ENDIF
+
+ IF ((lake_id(i) /= 0) .or. (wdsrf_bsn(i) < RIVERMIN)) THEN
+ momen_riv(i) = 0
+ veloc_riv(i) = 0
+ ELSE
+ friction = grav * nmanning_riv**2 / wdsrf_bsn(i)**(7.0/3.0) * abs(momen_riv(i))
+ momen_riv(i) = (momen_riv(i) &
+ - (sum_mflux_riv(i) - sum_zgrad_riv(i)) / riverarea(i) * dt_all(irivsys(i))) &
+ / (1 + friction * dt_all(irivsys(i)))
+ veloc_riv(i) = momen_riv(i) / wdsrf_bsn(i)
+ ENDIF
+
+ ! inland depression river
+ IF ((lake_id(i) == 0) .and. (riverdown(i) == -1)) THEN
+ momen_riv(i) = min(0., momen_riv(i))
+ veloc_riv(i) = min(0., veloc_riv(i))
+ ENDIF
+
+ veloc_riv(i) = min(veloc_riv(i), 20.)
+ veloc_riv(i) = max(veloc_riv(i), -20.)
+
+ ENDDO
+
+ DO i = 1, numbasin
+ IF (bsnfilter(i)) THEN
+
+ wdsrf_bsn_ta (i) = wdsrf_bsn_ta (i) + wdsrf_bsn(i) * dt_all(irivsys(i))
+ momen_riv_ta (i) = momen_riv_ta (i) + momen_riv(i) * dt_all(irivsys(i))
+ discharge_ta (i) = discharge_ta (i) + hflux_fc (i) * dt_all(irivsys(i))
+
+ IF (lake_id(i) > 0) THEN ! for lakes
+ hs = basin_hru%substt(i)
+ he = basin_hru%subend(i)
+ DO j = hs, he
+ wdsrf_bsnhru(j) = &
+ max(wdsrf_bsn(i) - (lakeinfo(i)%depth(1) - lakeinfo(i)%depth0(j-hs+1)), 0.)
+ wdsrf_bsnhru_ta(j) = wdsrf_bsnhru_ta(j) + wdsrf_bsnhru(j) * dt_all(irivsys(i))
+ ENDDO
+ ENDIF
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (lake_type(i) == 2) THEN
+ IF (year >= dam_build_year(bsn2resv(i))) THEN
+ irsv = bsn2resv(i)
+ volresv_ta (irsv) = volresv_ta (irsv) + volresv (irsv) * dt_all(irivsys(i))
+ qresv_in_ta (irsv) = qresv_in_ta (irsv) + qresv_in (irsv) * dt_all(irivsys(i))
+ qresv_out_ta(irsv) = qresv_out_ta(irsv) + qresv_out(irsv) * dt_all(irivsys(i))
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ENDIF
+ ENDDO
+
+ dt_res = dt_res - dt_all
+
+ ENDDO
+
+ IF (numbasin > 0) wdsrf_bsn_prev(:) = wdsrf_bsn(:)
+
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, ntimestep_riverlake, 1, MPI_INTEGER, MPI_MAX, p_comm_compute, p_err)
+#endif
+
+ IF (allocated(wdsrf_bsn_ds )) deallocate(wdsrf_bsn_ds )
+ IF (allocated(veloc_riv_ds )) deallocate(veloc_riv_ds )
+ IF (allocated(momen_riv_ds )) deallocate(momen_riv_ds )
+ IF (allocated(hflux_fc )) deallocate(hflux_fc )
+ IF (allocated(mflux_fc )) deallocate(mflux_fc )
+ IF (allocated(zgrad_dn )) deallocate(zgrad_dn )
+ IF (allocated(hflux_resv )) deallocate(hflux_resv )
+ IF (allocated(mflux_resv )) deallocate(mflux_resv )
+ IF (allocated(sum_hflux_riv)) deallocate(sum_hflux_riv)
+ IF (allocated(sum_mflux_riv)) deallocate(sum_mflux_riv)
+ IF (allocated(sum_zgrad_riv)) deallocate(sum_zgrad_riv)
+ IF (allocated(bsnfilter )) deallocate(bsnfilter )
+
+ ENDIF
+
+ END SUBROUTINE river_lake_flow
+
+END MODULE MOD_Catch_RiverLakeFlow
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_RiverLakeNetwork.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_RiverLakeNetwork.F90
new file mode 100644
index 0000000000..7ed4ee95a7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_RiverLakeNetwork.F90
@@ -0,0 +1,1145 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_RiverLakeNetwork
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! River networks: data and communication subroutines.
+!
+! Created by Shupeng Zhang, May 2023
+!--------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: spval
+ USE MOD_Pixelset
+ USE MOD_Catch_BasinNetwork
+ USE MOD_Catch_HillslopeNetwork
+ USE MOD_Catch_Vars_TimeVariables
+ IMPLICIT NONE
+
+ ! -- river parameters --
+ real(r8), allocatable :: riverlen (:)
+ real(r8), allocatable :: riverelv (:)
+ real(r8), allocatable :: riverwth (:)
+ real(r8), allocatable :: riverarea (:)
+ real(r8), allocatable :: riverdpth (:)
+
+ real(r8), allocatable :: basinelv (:)
+ real(r8), allocatable :: bedelv (:)
+ real(r8), allocatable :: handmin (:)
+
+ real(r8), allocatable :: wtsrfelv (:)
+
+ ! index of downstream river
+ ! > 0 : other catchment; 0 : river mouth; -1 : inland depression
+ integer, allocatable :: riverdown (:)
+ integer, allocatable :: ilocdown (:)
+ logical, allocatable :: to_lake (:)
+
+ real(r8), allocatable :: riverlen_ds (:)
+ real(r8), allocatable :: wtsrfelv_ds (:)
+ real(r8), allocatable :: riverwth_ds (:)
+ real(r8), allocatable :: bedelv_ds (:)
+
+ real(r8), allocatable :: outletwth (:)
+
+ integer :: riversystem
+
+ integer :: numrivsys
+ integer, allocatable :: irivsys (:)
+
+#ifdef USEMPI
+ integer :: p_comm_rivsys
+
+ integer :: numbsnlink
+ integer, allocatable :: linkbindex (:)
+
+ integer :: nlink_me
+ integer, allocatable :: linkpush (:)
+ integer, allocatable :: linkpull (:)
+#endif
+
+ ! -- lake data type --
+ type :: lake_info_type
+ integer :: nsub
+ real(r8), allocatable :: area0 (:) ! area data in HRU order
+ real(r8), allocatable :: area (:) ! area data in the order from deepest to shallowest HRU
+ real(r8), allocatable :: depth0 (:) ! depth data in HRU order
+ real(r8), allocatable :: depth (:) ! depth data in the order from deepest to shallowest HRU
+ ! a curve describing the relationship between depth of water from lake bottom and total water volume
+ ! the i-th value corresponds to the volume when water depth is at i-th depth
+ real(r8), allocatable :: dep_vol_curve (:)
+ CONTAINS
+ procedure, PUBLIC :: surface => retrieve_lake_surface_from_volume
+ procedure, PUBLIC :: volume => retrieve_lake_volume_from_surface
+ final :: lake_info_free_mem
+ END type lake_info_type
+
+ ! -- lake information --
+ type(lake_info_type), allocatable :: lakeinfo (:)
+
+ ! -- information of HRU in basin --
+ type(hillslope_network_type), pointer :: hillslope_basin (:)
+
+
+ ! ----- subroutines and functions -----
+ PUBLIC :: river_lake_network_init
+ PUBLIC :: pull_from_downstream
+ PUBLIC :: push_to_downstream
+ PUBLIC :: calc_riverdepth_from_runoff
+ PUBLIC :: retrieve_lake_surface_from_volume
+ PUBLIC :: river_lake_network_final
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE river_lake_network_init (patcharea)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh
+ USE MOD_Pixel
+ USE MOD_LandElm
+ USE MOD_LandHRU
+ USE MOD_LandPatch
+ USE MOD_ElementNeighbour
+ USE MOD_DataType
+ USE MOD_Utils
+ USE MOD_UserDefFun
+ USE MOD_Vars_TimeInvariants, only: lakedepth
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: patcharea (:)
+
+ ! Local Variables
+ character(len=256) :: river_file, rivdpt_file
+ logical :: use_calc_rivdpt
+
+ integer :: totalnumbasin, ibasin, jbasin, inb, iloc, ielm, i, j, ilink
+ integer :: irank, mesg(2), isrc, idest, nrecv
+
+#ifdef USEMPI
+ integer :: nblink_all
+ integer, allocatable :: linkbindex_all (:)
+ integer, allocatable :: linkrivmth_all (:)
+#endif
+
+ logical , allocatable :: is_link (:)
+ logical , allocatable :: link_on_me (:)
+
+ integer :: nnode
+ integer, allocatable :: route(:)
+
+ integer , allocatable :: icache (:)
+ real(r8), allocatable :: rcache (:)
+ logical , allocatable :: lcache (:)
+
+ integer, allocatable :: bindex(:), addrbasin(:), addrdown(:)
+ integer, allocatable :: basin_sorted(:), basin_order(:), order (:)
+
+ logical, allocatable :: bsnfilter(:)
+
+ ! for lakes
+ integer :: ps, pe, nsublake, hs, he, ihru
+ integer, allocatable :: all_lake_id (:), lake_id_elm (:)
+ integer , allocatable :: lakedown_id_elm(:), lakedown_id_bsn (:)
+ real(r8), allocatable :: lakedepth_hru (:), lakedepth_bsnhru(:)
+ real(r8), allocatable :: lakeoutlet_elm (:), lakeoutlet_bsn (:)
+ real(r8), allocatable :: unitarea_hru (:), unitarea_bsnhru (:)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ use_calc_rivdpt = DEF_USE_EstimatedRiverDepth
+ river_file = DEF_CatchmentMesh_data
+
+ ! step 1: read in parameters from file.
+ IF (p_is_root) THEN
+
+ CALL ncio_read_serial (river_file, 'lake_id', all_lake_id)
+
+ CALL ncio_read_serial (river_file, 'basin_downstream', riverdown)
+ CALL ncio_read_serial (river_file, 'river_length' , riverlen )
+ CALL ncio_read_serial (river_file, 'river_elevation' , riverelv )
+ CALL ncio_read_serial (river_file, 'basin_elevation' , basinelv )
+
+ IF (.not. use_calc_rivdpt) THEN
+ CALL ncio_read_serial (river_file, 'river_depth' , riverdpth)
+ ENDIF
+
+ riverlen = riverlen * 1.e3 ! km to m
+
+ totalnumbasin = size(riverdown)
+ allocate (to_lake (totalnumbasin))
+ to_lake = .false.
+ DO i = 1, totalnumbasin
+ IF (riverdown(i) > 0) THEN
+ to_lake(i) = all_lake_id(riverdown(i)) > 0
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ ! step 2: Estimate river depth by using runoff data.
+ IF (use_calc_rivdpt) THEN
+ CALL calc_riverdepth_from_runoff (patcharea)
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+
+ DO irank = 0, p_np_compute-1
+
+ CALL mpi_recv (mesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ nrecv = mesg(2)
+
+ IF (nrecv > 0) THEN
+
+ allocate (bindex (nrecv))
+ allocate (icache (nrecv))
+ allocate (rcache (nrecv))
+ allocate (lcache (nrecv))
+
+ CALL mpi_recv (bindex, nrecv, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ idest = isrc
+
+ icache = riverdown(bindex)
+ CALL mpi_send (icache, nrecv, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ lcache = to_lake(bindex)
+ CALL mpi_send (lcache, nrecv, MPI_LOGICAL, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = riverlen(bindex)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = riverelv(bindex)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = riverdpth(bindex)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ rcache = basinelv(bindex)
+ CALL mpi_send (rcache, nrecv, MPI_REAL8, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (bindex)
+ deallocate (icache)
+ deallocate (rcache)
+ deallocate (lcache)
+
+ ENDIF
+ ENDDO
+
+ deallocate (all_lake_id)
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ mesg(1:2) = (/p_iam_glb, numbasin/)
+ CALL mpi_send (mesg(1:2), 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numbasin > 0) THEN
+ CALL mpi_send (basinindex, numbasin, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (riverdown (numbasin))
+ CALL mpi_recv (riverdown, numbasin, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (to_lake (numbasin))
+ CALL mpi_recv (to_lake, numbasin, MPI_LOGICAL, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (riverlen (numbasin))
+ CALL mpi_recv (riverlen, numbasin, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (riverelv (numbasin))
+ CALL mpi_recv (riverelv, numbasin, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (riverdpth (numbasin))
+ CALL mpi_recv (riverdpth, numbasin, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (basinelv (numbasin))
+ CALL mpi_recv (basinelv, numbasin, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ IF (numbasin > 0) THEN
+
+ riverdown = riverdown(basinindex)
+ to_lake = to_lake (basinindex)
+ riverlen = riverlen (basinindex)
+ riverelv = riverelv (basinindex)
+ riverdpth = riverdpth(basinindex)
+ basinelv = basinelv (basinindex)
+
+ ENDIF
+#endif
+
+#ifdef USEMPI
+ ! get address of basins
+ IF (p_is_root) THEN
+
+ allocate (addrbasin (totalnumbasin)); addrbasin(:) = -1
+
+ DO irank = 0, p_np_compute-1
+
+ CALL mpi_recv (mesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ nrecv = mesg(2)
+
+ IF (nrecv > 0) THEN
+ allocate (bindex (nrecv))
+
+ CALL mpi_recv (bindex, nrecv, MPI_INTEGER, isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ addrbasin(bindex) = isrc
+
+ deallocate(bindex)
+ ENDIF
+
+ ENDDO
+
+ ELSEIF (p_is_compute) THEN
+
+ mesg(1:2) = (/p_iam_glb, numbasin/)
+ CALL mpi_send (mesg(1:2), 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numbasin > 0) THEN
+ CALL mpi_send (basinindex, numbasin, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ ENDIF
+
+
+ IF (p_is_root) THEN
+
+ allocate (addrdown (totalnumbasin))
+ allocate (is_link (totalnumbasin)); is_link = .false.
+
+ DO ibasin = 1, totalnumbasin
+ IF (riverdown(ibasin) >= 1) THEN
+ addrdown(ibasin) = addrbasin(riverdown(ibasin))
+ IF (addrdown(ibasin) /= addrbasin(ibasin)) THEN
+ is_link(riverdown(ibasin)) = .true.
+ ENDIF
+ ELSE
+ addrdown(ibasin) = addrbasin(ibasin)
+ ENDIF
+ ENDDO
+
+ nblink_all = count(is_link)
+
+ IF (nblink_all > 0) THEN
+ allocate (linkbindex_all (nblink_all))
+ allocate (linkrivmth_all (nblink_all))
+ linkbindex_all = pack((/(ibasin, ibasin = 1, totalnumbasin)/), mask = is_link)
+ linkrivmth_all = pack(rivermouth, mask = is_link)
+ ENDIF
+
+ deallocate (addrdown)
+ deallocate (is_link )
+
+ write(*,'(/,A,I5,A,/)') 'There are ', nblink_all, ' links between processors.'
+
+ ENDIF
+
+ CALL mpi_bcast (nblink_all, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (nblink_all > 0) THEN
+ IF (.not. allocated(linkbindex_all)) allocate (linkbindex_all (nblink_all))
+ IF (.not. allocated(linkrivmth_all)) allocate (linkrivmth_all (nblink_all))
+ CALL mpi_bcast (linkbindex_all, nblink_all, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast (linkrivmth_all, nblink_all, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+
+ IF (numbasin > 0) THEN
+ allocate (basin_sorted (numbasin))
+ allocate (basin_order (numbasin))
+ basin_sorted = basinindex
+ basin_order = (/(ibasin, ibasin = 1, numbasin)/)
+
+ CALL quicksort (numbasin, basin_sorted, basin_order)
+ ENDIF
+
+ riversystem = -1
+
+#ifdef USEMPI
+ IF (nblink_all > 0) THEN
+ DO ibasin = 1, numbasin
+
+ iloc = find_in_sorted_list1 (riverdown(ibasin), nblink_all, linkbindex_all)
+ IF (iloc <= 0) THEN
+ iloc = find_in_sorted_list1 (basinindex(ibasin), nblink_all, linkbindex_all)
+ ENDIF
+
+ IF (iloc > 0) THEN
+ IF (riversystem == -1) THEN
+ riversystem = linkrivmth_all(iloc)
+ ELSEIF (riversystem /= linkrivmth_all(iloc)) THEN
+ write(*,*) 'Warning: river system allocation error!'
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (riversystem /= -1) THEN
+ numbsnlink = count(linkrivmth_all == riversystem)
+ allocate (linkbindex (numbsnlink))
+ linkbindex = pack(linkbindex_all, linkrivmth_all == riversystem)
+
+ allocate (link_on_me (numbsnlink)); link_on_me = .false.
+
+ DO ibasin = 1, numbsnlink
+ iloc = find_in_sorted_list1 (linkbindex(ibasin), numbasin, basin_sorted)
+ IF (iloc > 0) THEN
+ link_on_me(ibasin) = .true.
+ ENDIF
+ ENDDO
+
+ nlink_me = count(link_on_me)
+
+ IF (nlink_me > 0) THEN
+ allocate (linkpush (nlink_me))
+ allocate (linkpull (nlink_me))
+ ilink = 0
+ DO ibasin = 1, numbsnlink
+ IF (link_on_me(ibasin)) THEN
+ ilink = ilink + 1
+ iloc = find_in_sorted_list1 (linkbindex(ibasin), numbasin, basin_sorted)
+ linkpush(ilink) = basin_order(iloc)
+ linkpull(ilink) = ibasin
+ ENDIF
+ ENDDO
+ ENDIF
+
+ deallocate (link_on_me)
+ ENDIF
+
+ IF (riversystem /= -1) THEN
+ CALL mpi_comm_split (p_comm_compute, riversystem, p_iam_compute, p_comm_rivsys, p_err)
+ ELSE
+ CALL mpi_comm_split (p_comm_compute, MPI_UNDEFINED, p_iam_compute, p_comm_rivsys, p_err)
+ ENDIF
+#endif
+
+
+ IF (numbasin > 0) THEN
+
+ allocate (ilocdown (numbasin)); ilocdown(:) = 0
+
+ DO ibasin = 1, numbasin
+ IF (riverdown(ibasin) > 0) THEN
+ iloc = find_in_sorted_list1 (riverdown(ibasin), numbasin, basin_sorted)
+ IF (iloc > 0) THEN
+ ilocdown(ibasin) = basin_order(iloc)
+#ifdef USEMPI
+ ELSE
+ iloc = find_in_sorted_list1 (riverdown(ibasin), numbsnlink, linkbindex)
+ ilocdown(ibasin) = - iloc
+#endif
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+
+ IF (numbasin > 0) allocate (irivsys (numbasin))
+ IF (numbasin > 0) allocate (route (numbasin))
+
+ IF (riversystem == -1) THEN
+ irivsys(:) = -1
+ numrivsys = 0
+ DO ibasin = 1, numbasin
+ IF (irivsys(ibasin) == -1) THEN
+
+ jbasin = ibasin
+ nnode = 1
+ route(nnode) = jbasin
+ DO WHILE ((riverdown(jbasin) > 0) .and. (irivsys(jbasin) == -1))
+ nnode = nnode + 1
+ route(nnode) = jbasin
+ jbasin = ilocdown(jbasin)
+ ENDDO
+
+ IF (irivsys(jbasin) == -1) THEN
+ numrivsys = numrivsys + 1
+ irivsys(jbasin) = numrivsys
+ ENDIF
+
+ irivsys(route(1:nnode)) = irivsys(jbasin)
+
+ ENDIF
+ ENDDO
+ ELSE
+ numrivsys = 1
+ irivsys(:) = 1
+ ENDIF
+
+ IF (numbasin > 0) deallocate (route)
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (allocated (linkbindex_all)) deallocate (linkbindex_all)
+ IF (allocated (linkrivmth_all)) deallocate (linkrivmth_all)
+#endif
+
+
+ CALL hillslope_network_init (numbasin, basinindex, hillslope_basin)
+
+ IF (p_is_compute) THEN
+
+ IF (numelm > 0) allocate (lake_id_elm (numelm))
+ IF (numhru > 0) allocate (lakedepth_hru (numhru))
+ IF (numbsnhru > 0) allocate (lakedepth_bsnhru(numbsnhru))
+ IF (numelm > 0) allocate (lakedown_id_elm (numelm))
+ IF (numbasin > 0) allocate (lakedown_id_bsn (numbasin))
+ IF (numelm > 0) allocate (lakeoutlet_elm (numelm))
+ IF (numbasin > 0) allocate (lakeoutlet_bsn (numbasin))
+ IF (numhru > 0) allocate (unitarea_hru (numhru))
+ IF (numbsnhru > 0) allocate (unitarea_bsnhru (numbsnhru))
+
+ DO ibasin = 1, numbasin
+
+ lakedown_id_bsn(ibasin) = 0
+
+ IF ((lake_id(ibasin) /= 0) .and. (to_lake(ibasin))) THEN
+ ! lake to lake .or. lake catchment to lake
+ lakedown_id_bsn(ibasin) = riverdown(ibasin)
+ ENDIF
+ IF ((lake_id(ibasin) > 0) .and. (riverdown(ibasin) == 0)) THEN
+ ! lake to ocean
+ lakedown_id_bsn(ibasin) = -9 ! -9 is ocean
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ CALL compute_push_data (push_bsn2elm, lake_id, lake_id_elm, -9999)
+ CALL compute_push_data (push_bsn2elm, lakedown_id_bsn, lakedown_id_elm, -9999)
+
+ IF (p_is_compute) THEN
+
+ unitarea_hru = 0.
+ lakedepth_hru = 0.
+ lakeoutlet_elm = 0.
+
+ DO ielm = 1, numelm
+ hs = elm_hru%substt(ielm)
+ he = elm_hru%subend(ielm)
+ DO ihru = hs, he
+ ps = hru_patch%substt(ihru)
+ pe = hru_patch%subend(ihru)
+
+ unitarea_hru(ihru) = sum(patcharea(ps:pe))
+
+ IF (lake_id_elm(ielm) > 0) THEN
+ lakedepth_hru(ihru) = maxval(lakedepth(ps:pe))
+ ENDIF
+ ENDDO
+
+ IF (lakedown_id_elm(ielm) /= 0) THEN
+ inb = findloc_ud(elementneighbour(ielm)%glbindex == lakedown_id_elm(ielm))
+ IF (inb > 0) lakeoutlet_elm(ielm) = elementneighbour(ielm)%lenbdr(inb)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL compute_push_data (push_elm2bsn, lakeoutlet_elm, lakeoutlet_bsn, spval)
+
+ CALL compute_push_data (push_elmhru2bsnhru, unitarea_hru, unitarea_bsnhru, spval)
+ CALL compute_push_data (push_elmhru2bsnhru, lakedepth_hru, lakedepth_bsnhru, spval)
+
+ IF (allocated (lake_id_elm )) deallocate (lake_id_elm )
+ IF (allocated (lakedepth_hru )) deallocate (lakedepth_hru )
+ IF (allocated (lakedown_id_elm)) deallocate (lakedown_id_elm)
+ IF (allocated (lakedown_id_bsn)) deallocate (lakedown_id_bsn)
+ IF (allocated (lakeoutlet_elm )) deallocate (lakeoutlet_elm )
+ IF (allocated (unitarea_hru )) deallocate (unitarea_hru )
+
+ IF (p_is_compute) THEN
+
+ IF (numbasin > 0) THEN
+
+ allocate (lakeinfo (numbasin))
+ allocate (riverarea (numbasin))
+ allocate (riverwth (numbasin))
+ allocate (bedelv (numbasin))
+ allocate (handmin (numbasin))
+ allocate (wtsrfelv (numbasin))
+ allocate (riverlen_ds (numbasin))
+ allocate (wtsrfelv_ds (numbasin))
+ allocate (riverwth_ds (numbasin))
+ allocate (bedelv_ds (numbasin))
+ allocate (outletwth (numbasin))
+
+ DO ibasin = 1, numbasin
+
+ hs = basin_hru%substt(ibasin)
+ he = basin_hru%subend(ibasin)
+
+ IF (lake_id(ibasin) == 0) THEN
+
+ hillslope_basin(ibasin)%area = unitarea_bsnhru(hs:he)
+
+ riverarea(ibasin) = hillslope_basin(ibasin)%area(1)
+ riverwth (ibasin) = riverarea(ibasin) / riverlen(ibasin)
+
+ ! modify height above nearest drainage data to consider river depth
+ IF (hillslope_basin(ibasin)%nhru > 1) THEN
+ hillslope_basin(ibasin)%hand(2:) = &
+ hillslope_basin(ibasin)%hand(2:) + riverdpth(ibasin)
+ ENDIF
+
+ wtsrfelv(ibasin) = riverelv(ibasin)
+ bedelv (ibasin) = riverelv(ibasin) - riverdpth(ibasin)
+
+ handmin(ibasin) = minval(hillslope_basin(ibasin)%hand)
+
+ ELSEIF (lake_id(ibasin) > 0) THEN
+
+ wtsrfelv(ibasin) = basinelv(ibasin)
+
+ bedelv(ibasin) = basinelv(ibasin) - maxval(lakedepth_bsnhru(hs:he))
+
+ nsublake = he - hs + 1
+ lakeinfo(ibasin)%nsub = nsublake
+
+ allocate (lakeinfo(ibasin)%area0 (nsublake))
+ allocate (lakeinfo(ibasin)%area (nsublake))
+ allocate (lakeinfo(ibasin)%depth0 (nsublake))
+ allocate (lakeinfo(ibasin)%depth (nsublake))
+
+ lakeinfo(ibasin)%area = unitarea_bsnhru (hs:he)
+ lakeinfo(ibasin)%depth = lakedepth_bsnhru(hs:he)
+
+ ! area data in HRU order
+ lakeinfo(ibasin)%area0 = lakeinfo(ibasin)%area
+
+ ! depth data in HRU order
+ lakeinfo(ibasin)%depth0 = lakeinfo(ibasin)%depth
+
+ allocate (order (1:nsublake))
+ order = (/(i, i = 1, nsublake)/)
+
+ CALL quicksort (nsublake, lakeinfo(ibasin)%depth, order)
+
+ ! area data in depth order
+ lakeinfo(ibasin)%area = lakeinfo(ibasin)%area(order)
+
+ ! adjust to be from deepest to shallowest
+ lakeinfo(ibasin)%depth = lakeinfo(ibasin)%depth(nsublake:1:-1)
+ lakeinfo(ibasin)%area = lakeinfo(ibasin)%area (nsublake:1:-1)
+
+ allocate (lakeinfo(ibasin)%dep_vol_curve (nsublake))
+
+ lakeinfo(ibasin)%dep_vol_curve(1) = 0
+ DO i = 2, nsublake
+ lakeinfo(ibasin)%dep_vol_curve(i) = &
+ lakeinfo(ibasin)%dep_vol_curve(i-1) &
+ + sum(lakeinfo(ibasin)%area(1:i-1)) &
+ * (lakeinfo(ibasin)%depth(i-1)-lakeinfo(ibasin)%depth(i))
+ ENDDO
+
+ riverlen(ibasin) = 0.
+
+ deallocate (order)
+
+ ELSEIF (lake_id(ibasin) < 0) THEN
+
+ hillslope_basin(ibasin)%area = unitarea_bsnhru(hs:he)
+ handmin(ibasin) = minval(hillslope_basin(ibasin)%hand)
+
+ ENDIF
+
+ ENDDO
+ ENDIF
+
+ IF (numbasin > 0) THEN
+ allocate(bsnfilter (numbasin))
+ bsnfilter(:) = .true.
+ ENDIF
+
+ CALL pull_from_downstream (riverlen, riverlen_ds, bsnfilter)
+ CALL pull_from_downstream (wtsrfelv, wtsrfelv_ds, bsnfilter)
+ CALL pull_from_downstream (riverwth, riverwth_ds, bsnfilter)
+ CALL pull_from_downstream (bedelv , bedelv_ds , bsnfilter)
+
+ IF (allocated(bsnfilter)) deallocate(bsnfilter)
+
+ DO ibasin = 1, numbasin
+ IF (lake_id(ibasin) < 0) THEN
+ bedelv(ibasin) = wtsrfelv_ds(ibasin) + minval(hillslope_basin(ibasin)%hand)
+ ENDIF
+ ENDDO
+
+ DO ibasin = 1, numbasin
+ IF (lake_id(ibasin) == 0) THEN
+ IF ((to_lake(ibasin)) .or. (riverdown(ibasin) <= 0)) THEN
+ ! river to lake, ocean, inland depression or out of region
+ outletwth(ibasin) = riverwth(ibasin)
+ ELSE
+ ! river to river
+ outletwth(ibasin) = (riverwth(ibasin) + riverwth_ds(ibasin)) * 0.5
+ ENDIF
+ ELSEIF (lake_id(ibasin) /= 0) THEN
+ IF ((.not. to_lake(ibasin)) .and. (riverdown(ibasin) /= 0)) THEN
+ IF (riverdown(ibasin) > 0) THEN
+ ! lake to river
+ outletwth(ibasin) = riverwth_ds(ibasin)
+ ELSEIF (riverdown(ibasin) == -1) THEN
+ ! lake is inland depression
+ outletwth(ibasin) = 0
+ ENDIF
+ ELSEIF (to_lake(ibasin)) THEN
+ ! lake to lake .or. lake catchment to lake
+ outletwth(ibasin) = lakeoutlet_bsn(ibasin)
+ ELSEIF (riverdown(ibasin) == 0) THEN
+ ! lake to ocean
+ outletwth(ibasin) = lakeoutlet_bsn(ibasin)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (allocated (lakedepth_bsnhru)) deallocate (lakedepth_bsnhru)
+ IF (allocated (lakeoutlet_bsn )) deallocate (lakeoutlet_bsn )
+ IF (allocated (unitarea_bsnhru )) deallocate (unitarea_bsnhru )
+
+ IF (allocated(basin_sorted )) deallocate(basin_sorted )
+ IF (allocated(basin_order )) deallocate(basin_order )
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+ IF (p_is_root) write(*,'(A)') 'Building river network information done.'
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE river_lake_network_init
+
+ ! ----- pull data from downstream basin -----
+ SUBROUTINE pull_from_downstream (datain, dataout, bsnfilter)
+
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: datain (:)
+ real(r8), intent(inout) :: dataout (:)
+ logical, intent(in) :: bsnfilter(:)
+
+ ! local variables
+ integer :: i, ibasin
+ real(r8), allocatable :: datalink(:)
+
+ IF (p_is_compute) THEN
+
+#ifdef USEMPI
+ IF (riversystem /= -1) THEN
+ allocate (datalink (numbsnlink)); datalink(:) = 0.
+ DO i = 1, nlink_me
+ datalink(linkpull(i)) = datain(linkpush(i))
+ ENDDO
+ CALL mpi_allreduce (MPI_IN_PLACE, datalink, numbsnlink, MPI_REAL8, MPI_SUM, p_comm_rivsys, p_err)
+ ENDIF
+#endif
+
+ DO ibasin = 1, numbasin
+ IF (bsnfilter(ibasin)) THEN
+ IF (riverdown(ibasin) > 0) THEN
+ IF (ilocdown(ibasin) > 0) THEN
+ dataout(ibasin) = datain(ilocdown(ibasin))
+#ifdef USEMPI
+ ELSEIF (ilocdown(ibasin) < 0) THEN
+ dataout(ibasin) = datalink(-ilocdown(ibasin))
+#endif
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ IF (allocated(datalink)) deallocate (datalink)
+#endif
+ ENDIF
+
+ END SUBROUTINE pull_from_downstream
+
+ ! ----- push data to downstream basin -----
+ SUBROUTINE push_to_downstream (datain, dataout, bsnfilter)
+
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ real(r16), intent(in) :: datain (:)
+ real(r16), intent(inout) :: dataout (:)
+ logical, intent(in) :: bsnfilter(:)
+
+ ! local variables
+ integer :: i, ibasin
+ real(r16), allocatable :: datalink(:)
+
+
+ IF (p_is_compute) THEN
+
+#ifdef USEMPI
+ IF (numbsnlink > 0) THEN
+ allocate (datalink (numbsnlink)); datalink(:) = 0.
+ ENDIF
+#endif
+
+ DO ibasin = 1, numbasin
+ IF (bsnfilter(ibasin)) THEN
+ IF (riverdown(ibasin) > 0) THEN
+ IF (ilocdown(ibasin) > 0) THEN
+ dataout(ilocdown(ibasin)) = dataout(ilocdown(ibasin)) + datain(ibasin)
+#ifdef USEMPI
+ ELSEIF (ilocdown(ibasin) < 0) THEN
+ datalink(-ilocdown(ibasin)) = datalink(-ilocdown(ibasin)) + datain(ibasin)
+#endif
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ IF (riversystem /= -1) THEN
+
+ CALL mpi_allreduce (MPI_IN_PLACE, datalink, numbsnlink, MPI_REAL16, MPI_SUM, p_comm_rivsys, p_err)
+
+ DO i = 1, nlink_me
+ dataout(linkpush(i)) = dataout(linkpush(i)) + datalink(linkpull(i))
+ ENDDO
+
+ deallocate (datalink)
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE push_to_downstream
+
+ ! ----- retrieve river depth from runoff -----
+ SUBROUTINE calc_riverdepth_from_runoff (patcharea)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_DataType
+ USE MOD_Utils
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ USE MOD_Pixel
+ USE MOD_Block
+ USE MOD_Mesh
+ USE MOD_Grid
+ USE MOD_SpatialMapping
+ USE MOD_LandElm
+ USE MOD_LandPatch
+ USE MOD_ElmVector
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: patcharea (:)
+
+ ! Local Variables
+ character(len=256) :: file_rnof, file_rivdpt
+ type(grid_type) :: grid_rnof
+ type(block_data_real8_2d) :: f_rnof
+ type(spatial_mapping_type) :: mg2p_rnof
+
+ real(r8), allocatable :: bsnrnof(:) , bsndis(:)
+ integer, allocatable :: nups_riv(:), iups_riv(:), b_up2down(:)
+
+ integer :: i, j, ithis, ib, jb, iblkme, ps, pe
+ integer :: iwork, mesg(2), isrc, ndata
+ real(r8), allocatable :: rcache(:)
+ real(r8) :: myarea
+
+ real(r8), parameter :: cH_rivdpt = 0.1
+ real(r8), parameter :: pH_rivdpt = 0.5
+ real(r8), parameter :: B0_rivdpt = 0.0
+ real(r8), parameter :: Bmin_rivdpt = 1.0
+
+
+ file_rnof = trim(DEF_dir_runtime) // '/runoff_clim.nc'
+
+ CALL grid_rnof%define_from_file (file_rnof, 'lat', 'lon')
+
+ CALL mg2p_rnof%build_arealweighted (grid_rnof, landelm)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_rnof, f_rnof)
+ CALL ncio_read_block (file_rnof, 'ro', grid_rnof, f_rnof)
+
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+ DO j = 1, grid_rnof%ycnt(jb)
+ DO i = 1, grid_rnof%xcnt(ib)
+ f_rnof%blk(ib,jb)%val(i,j) = max(f_rnof%blk(ib,jb)%val(i,j), 0.)
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numelm > 0) allocate (bsnrnof (numelm))
+ ENDIF
+
+ CALL mg2p_rnof%grid2pset (f_rnof, bsnrnof)
+
+ IF (p_is_compute) THEN
+ IF (numelm > 0) THEN
+ bsnrnof = bsnrnof /24.0/3600.0 ! from m/day to m/s
+ DO i = 1, numelm
+ ps = elm_patch%substt(i)
+ pe = elm_patch%subend(i)
+ myarea = sum(patcharea(ps:pe))
+ ! total runoff in basin, from m/s to m3/s
+ bsnrnof(i) = bsnrnof(i) * myarea
+ ENDDO
+ ENDIF
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_compute) THEN
+ mesg = (/p_iam_glb, numelm/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numelm > 0) THEN
+ CALL mpi_send (bsnrnof, numelm, MPI_REAL8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ allocate (bsnrnof (totalnumelm))
+
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate(rcache (ndata))
+
+ CALL mpi_recv (rcache, ndata, MPI_REAL8, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ bsnrnof(elm_data_address(p_itis_compute(isrc))%val) = rcache
+
+ deallocate (rcache)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ bsnrnof(elm_data_address(0)%val) = bsnrnof
+#endif
+
+
+ IF (p_is_root) THEN
+
+ allocate (nups_riv (totalnumelm))
+ allocate (iups_riv (totalnumelm))
+ allocate (b_up2down(totalnumelm))
+
+ allocate (bsndis (totalnumelm))
+
+ nups_riv(:) = 0
+ DO i = 1, totalnumelm
+ j = riverdown(i)
+ IF (j > 0) THEN
+ nups_riv(j) = nups_riv(j) + 1
+ ENDIF
+ ENDDO
+
+ iups_riv(:) = 0
+ ithis = 0
+ DO i = 1, totalnumelm
+ IF (iups_riv(i) == nups_riv(i)) THEN
+
+ ithis = ithis + 1
+ b_up2down(ithis) = i
+
+ j = riverdown(i)
+ DO WHILE (j > 0)
+
+ iups_riv(j) = iups_riv(j) + 1
+
+ IF (iups_riv(j) == nups_riv(j)) THEN
+ ithis = ithis + 1
+ b_up2down(ithis) = j
+ j = riverdown(j)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ bsndis(:) = 0.
+ DO i = 1, totalnumelm
+ j = b_up2down(i)
+ bsndis(j) = bsndis(j) + bsnrnof(j)
+ IF (riverdown(j) > 0) THEN
+ bsndis(riverdown(j)) = bsndis(riverdown(j)) + bsndis(j)
+ ENDIF
+ ENDDO
+
+ allocate (riverdpth (totalnumelm))
+ DO i = 1, totalnumelm
+ riverdpth(i) = max(cH_rivdpt * (bsndis(i)**pH_rivdpt) + B0_rivdpt, Bmin_rivdpt)
+ ENDDO
+
+ ENDIF
+
+ IF (allocated (bsnrnof )) deallocate(bsnrnof )
+ IF (allocated (bsndis )) deallocate(bsndis )
+ IF (allocated (nups_riv )) deallocate(nups_riv )
+ IF (allocated (iups_riv )) deallocate(iups_riv )
+ IF (allocated (b_up2down)) deallocate(b_up2down)
+
+ END SUBROUTINE calc_riverdepth_from_runoff
+
+ !
+ FUNCTION retrieve_lake_surface_from_volume (this, volume) result(surface)
+
+ IMPLICIT NONE
+
+ class(lake_info_type) :: this
+ real(r8), intent(in) :: volume
+ real(r8) :: surface
+
+ ! Local Variables
+ integer :: i
+
+ IF (volume <= 0) THEN
+ surface = 0
+ RETURN
+ ENDIF
+
+ IF (this%nsub == 1) THEN
+ surface = volume / this%area(1)
+ ELSE
+ i = 1
+ DO WHILE (i < this%nsub)
+ IF (volume >= this%dep_vol_curve(i+1)) THEN
+ i = i + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ surface = this%depth(1) - this%depth(i) + &
+ (volume - this%dep_vol_curve(i)) / sum(this%area(1:i))
+ ENDIF
+
+ END FUNCTION retrieve_lake_surface_from_volume
+
+ !
+ FUNCTION retrieve_lake_volume_from_surface (this, surface) result(volume)
+
+ IMPLICIT NONE
+
+ class(lake_info_type) :: this
+ real(r8), intent(in) :: surface
+ real(r8) :: volume
+
+ ! Local Variables
+ integer :: i
+
+ IF (surface <= 0) THEN
+ volume = 0
+ RETURN
+ ENDIF
+
+ IF (this%nsub == 1) THEN
+ volume = this%area(1) * surface
+ ELSE
+ i = 1
+ DO WHILE (i < this%nsub)
+ IF (surface >= this%depth(1)-this%depth(i+1)) THEN
+ i = i + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ volume = this%dep_vol_curve(i) &
+ + (surface - (this%depth(1) - this%depth(i))) * sum(this%area(1:i))
+ ENDIF
+
+ END FUNCTION retrieve_lake_volume_from_surface
+
+ ! ----------
+ SUBROUTINE river_lake_network_final ()
+
+ IMPLICIT NONE
+
+ ! Local Variables
+ integer :: ilake
+
+ IF (allocated (riverlen )) deallocate(riverlen )
+ IF (allocated (riverelv )) deallocate(riverelv )
+ IF (allocated (riverwth )) deallocate(riverwth )
+ IF (allocated (riverarea )) deallocate(riverarea )
+ IF (allocated (riverdpth )) deallocate(riverdpth )
+ IF (allocated (basinelv )) deallocate(basinelv )
+ IF (allocated (bedelv )) deallocate(bedelv )
+ IF (allocated (handmin )) deallocate(handmin )
+ IF (allocated (wtsrfelv )) deallocate(wtsrfelv )
+ IF (allocated (riverdown )) deallocate(riverdown )
+ IF (allocated (ilocdown )) deallocate(ilocdown )
+ IF (allocated (to_lake )) deallocate(to_lake )
+ IF (allocated (riverlen_ds )) deallocate(riverlen_ds )
+ IF (allocated (wtsrfelv_ds )) deallocate(wtsrfelv_ds )
+ IF (allocated (riverwth_ds )) deallocate(riverwth_ds )
+ IF (allocated (bedelv_ds )) deallocate(bedelv_ds )
+ IF (allocated (outletwth )) deallocate(outletwth )
+ IF (allocated (irivsys )) deallocate(irivsys )
+#ifdef USEMPI
+ IF (allocated (linkbindex )) deallocate(linkbindex )
+ IF (allocated (linkpush )) deallocate(linkpush )
+ IF (allocated (linkpull )) deallocate(linkpull )
+#endif
+ IF (allocated (lakeinfo )) deallocate(lakeinfo )
+ IF (associated(hillslope_basin)) deallocate(hillslope_basin)
+
+ END SUBROUTINE river_lake_network_final
+
+ ! ---------
+ SUBROUTINE lake_info_free_mem (this)
+
+ IMPLICIT NONE
+ type(lake_info_type) :: this
+
+ IF (allocated(this%area0 )) deallocate (this%area0 )
+ IF (allocated(this%area )) deallocate (this%area )
+ IF (allocated(this%depth0)) deallocate (this%depth0)
+ IF (allocated(this%depth )) deallocate (this%depth )
+ IF (allocated(this%dep_vol_curve)) deallocate (this%dep_vol_curve)
+
+ END SUBROUTINE lake_info_free_mem
+
+END MODULE MOD_Catch_RiverLakeNetwork
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_SubsurfaceFlow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_SubsurfaceFlow.F90
new file mode 100644
index 0000000000..7bbcf51834
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_SubsurfaceFlow.F90
@@ -0,0 +1,823 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_SubsurfaceFlow
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Ground water lateral flow.
+!
+! Ground water fluxes are calculated
+! 1. between elements
+! 2. between hydrological response units
+! 3. between patches inside one HRU
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_DataType
+ USE MOD_Catch_HillslopeNetwork
+ IMPLICIT NONE
+
+ ! --- information of HRU on hillslope ---
+ type(hillslope_network_type), pointer :: hillslope_element (:)
+
+ integer, allocatable :: lake_id_elm (:)
+ real(r8), allocatable :: lakedepth_elm(:)
+ real(r8), allocatable :: riverdpth_elm(:)
+ real(r8), allocatable :: wdsrf_elm (:)
+
+ real(r8), parameter :: e_ice = 6.0 ! soil ice impedance factor
+
+ ! anisotropy ratio of lateral/vertical hydraulic conductivity (unitless)
+ ! for USDA soil texture class:
+ ! 0: undefined
+ ! 1: clay; 2: silty clay; 3: sandy clay; 4: clay loam; 5: silty clay loam; 6: sandy clay loam; &
+ ! 7: loam; 8: silty loam; 9: sandy loam; 10: silt; 11: loamy sand; 12: sand
+ real(r8), parameter :: raniso(0:12) = (/ 1., &
+ 48., 40., 28., 24., 20., 14., 12., 10., 4., 2., 3., 2. /)
+
+ ! -- neighbour variables --
+ type(pointer_real8_1d), allocatable :: agwt_nb (:) ! ground water area (for patchtype <= 2) of neighbours [m^2]
+ type(pointer_real8_1d), allocatable :: theta_a_nb (:) ! saturated volume content [-]
+ type(pointer_real8_1d), allocatable :: zwt_nb (:) ! water table depth [m]
+ type(pointer_real8_1d), allocatable :: Kl_nb (:) ! lateral hydraulic conductivity [m/s]
+ type(pointer_real8_1d), allocatable :: wdsrf_nb (:) ! depth of surface water [m]
+ type(pointer_logic_1d), allocatable :: islake_nb (:) ! whether a neighbour is water body
+ type(pointer_real8_1d), allocatable :: lakedp_nb (:) ! lake depth of neighbour [m]
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE subsurface_network_init (patcharea)
+
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ USE MOD_Mesh
+ USE MOD_Pixel
+ USE MOD_LandElm
+ USE MOD_LandPatch
+ USE MOD_ElementNeighbour
+ USE MOD_ComputePushData, only: compute_push_data
+ USE MOD_Catch_BasinNetwork, only: push_bsn2elm
+ USE MOD_Catch_RiverLakeNetwork, only: lake_id, riverdpth
+ USE MOD_Vars_TimeInvariants, only: patchtype, lakedepth
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: patcharea (:)
+
+ integer :: ielm, inb, i, ihru, ps, pe, ipatch
+
+ real(r8), allocatable :: agwt_b(:)
+ real(r8), allocatable :: islake(:)
+ type(pointer_real8_1d), allocatable :: iswat_nb (:)
+
+ integer, allocatable :: eindex(:)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_compute) THEN
+ IF (numelm > 0) THEN
+ allocate (eindex (numelm))
+ eindex = landelm%eindex
+ ENDIF
+ ENDIF
+
+ CALL hillslope_network_init (numelm, eindex, hillslope_element)
+
+ IF (allocated(eindex)) deallocate (eindex)
+
+ IF (p_is_compute) THEN
+
+ IF (numelm > 0) allocate (lake_id_elm (numelm))
+ IF (numelm > 0) allocate (riverdpth_elm(numelm))
+ IF (numelm > 0) allocate (lakedepth_elm(numelm))
+ IF (numelm > 0) allocate (wdsrf_elm (numelm))
+
+ CALL compute_push_data (push_bsn2elm, lake_id, lake_id_elm, -9999)
+ CALL compute_push_data (push_bsn2elm, riverdpth, riverdpth_elm, spval)
+
+ DO ielm = 1, numelm
+ IF (lake_id_elm(ielm) <= 0) THEN
+ DO i = 1, hillslope_element(ielm)%nhru
+
+ hillslope_element(ielm)%agwt(i) = 0
+ hillslope_element(ielm)%area(i) = 0
+
+ ihru = hillslope_element(ielm)%ihru(i)
+ ps = hru_patch%substt(ihru)
+ pe = hru_patch%subend(ihru)
+ DO ipatch = ps, pe
+ hillslope_element(ielm)%area(i) = hillslope_element(ielm)%area(i) + patcharea(ipatch)
+ IF (patchtype(ipatch) <= 2) THEN
+ hillslope_element(ielm)%agwt(i) = hillslope_element(ielm)%agwt(i) + patcharea(ipatch)
+ ENDIF
+ ENDDO
+
+ ENDDO
+ ENDIF
+ ENDDO
+
+ lakedepth_elm(:) = 0.
+ DO ielm = 1, numelm
+ IF (lake_id_elm(ielm) > 0) THEN
+ ps = elm_patch%substt(ielm)
+ pe = elm_patch%subend(ielm)
+ lakedepth_elm(ielm) = sum(lakedepth(ps:pe) * elm_patch%subfrc(ps:pe))
+ ENDIF
+ ENDDO
+
+ CALL allocate_neighbour_data (agwt_nb )
+ CALL allocate_neighbour_data (theta_a_nb)
+ CALL allocate_neighbour_data (zwt_nb )
+ CALL allocate_neighbour_data (Kl_nb )
+ CALL allocate_neighbour_data (wdsrf_nb )
+ CALL allocate_neighbour_data (islake_nb )
+ CALL allocate_neighbour_data (lakedp_nb )
+ CALL allocate_neighbour_data (iswat_nb )
+
+ IF (numelm > 0) THEN
+ allocate (agwt_b(numelm))
+ allocate (islake(numelm))
+ DO ielm = 1, numelm
+ IF (lake_id_elm(ielm) <= 0) THEN
+ agwt_b(ielm) = sum(hillslope_element(ielm)%agwt)
+ islake(ielm) = 0.
+ ELSE
+ agwt_b(ielm) = 0.
+ islake(ielm) = 1.
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL retrieve_neighbour_data (lakedepth_elm, lakedp_nb)
+
+ CALL retrieve_neighbour_data (agwt_b, agwt_nb )
+ CALL retrieve_neighbour_data (islake, iswat_nb)
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%glbindex(inb) > 0) THEN ! skip ocean neighbour
+ islake_nb(ielm)%val(inb) = (iswat_nb(ielm)%val(inb) > 0)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ IF (allocated(agwt_b )) deallocate(agwt_b )
+ IF (allocated(islake )) deallocate(islake )
+ IF (allocated(iswat_nb)) deallocate(iswat_nb)
+
+ ENDIF
+
+ END SUBROUTINE subsurface_network_init
+
+ ! ---------
+ SUBROUTINE subsurface_flow (deltime)
+
+ USE MOD_SPMD_Task
+ USE MOD_UserDefFun
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_LandHRU
+ USE MOD_LandPatch
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_1DFluxes
+ USE MOD_Catch_HillslopeNetwork
+ USE MOD_ElementNeighbour
+ USE MOD_Const_Physical, only: denice, denh2o
+ USE MOD_Vars_Global, only: pi, nl_soil, zi_soi
+ USE MOD_Hydro_SoilWater, only: soilwater_aquifer_exchange
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltime
+
+ ! Local Variables
+ integer :: nhru, ielm, i, i0, j, ihru, ipatch, ps, pe, hs, he, ilev
+
+ type(hillslope_network_type), pointer :: hrus
+
+ real(r8), allocatable :: theta_a_h (:)
+ real(r8), allocatable :: zwt_h (:)
+ real(r8), allocatable :: Kl_h (:) ! [m/s]
+ real(r8), allocatable :: xsubs_h (:) ! [m/s]
+ real(r8), allocatable :: xsubs_fc (:) ! [m/s]
+
+ logical :: j_is_river
+ real(r8) :: theta_s_h, air_h, icefrac, imped, delp
+ real(r8) :: sumwt, sumarea, zwt_mean
+ real(r8) :: zsubs_h_up, zsubs_h_dn
+ real(r8) :: slope, bdamp, Kl_fc, Kl_in
+ real(r8) :: ca, cb
+ real(r8) :: alp
+
+ real(r8), allocatable :: theta_a_elm (:)
+ real(r8), allocatable :: zwt_elm (:)
+ real(r8), allocatable :: Kl_elm (:) ! [m/s]
+
+ integer :: jnb
+ real(r8) :: zsubs_up, zwt_up, Kl_up, theta_a_up, area_up
+ real(r8) :: zsubs_dn, zwt_dn, Kl_dn, theta_a_dn, area_dn
+ real(r8) :: lenbdr, xsubs_nb
+ logical :: iam_lake, nb_is_lake, has_river
+
+ ! for water exchange
+ logical :: is_dry_lake
+ integer :: izwt
+ real(r8) :: exwater
+ real(r8) :: sp_zi(0:nl_soil), sp_dz(1:nl_soil), zwtmm ! [mm]
+ real(r8) :: vl_r (1:nl_soil)
+#ifdef Campbell_SOIL_MODEL
+ integer, parameter :: nprms = 1
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ integer, parameter :: nprms = 5
+#endif
+ real(r8) :: prms (nprms,1:nl_soil)
+ real(r8) :: vol_ice (1:nl_soil)
+ real(r8) :: vol_liq (1:nl_soil)
+ real(r8) :: eff_porosity(1:nl_soil)
+ logical :: is_permeable(1:nl_soil)
+ real(r8) :: wresi (1:nl_soil)
+ real(r8) :: w_sum_before, w_sum_after, errblc
+
+
+ IF (p_is_compute) THEN
+
+ xsubs_elm(:) = 0. ! subsurface lateral flow between element basins
+ xsubs_hru(:) = 0. ! subsurface lateral flow between hydrological response units
+ xsubs_pch(:) = 0. ! subsurface lateral flow between patches inside one HRU
+
+ xwsub(:) = 0. ! total recharge/discharge from subsurface lateral flow
+
+ IF (numpatch > 0) rsub(:) = 0.
+
+ IF (numelm > 0) THEN
+ allocate (theta_a_elm (numelm)); theta_a_elm = 0.
+ allocate (zwt_elm (numelm)); zwt_elm = 0.
+ allocate (Kl_elm (numelm)); Kl_elm = 0.
+ ENDIF
+
+ DO ielm = 1, numelm
+
+ hrus => hillslope_element(ielm)
+
+ nhru = hrus%nhru
+
+ IF (lake_id_elm(ielm) > 0) CYCLE ! lake
+ IF (sum(hrus%agwt) <= 0) CYCLE ! no area of soil, urban or wetland
+
+ allocate (theta_a_h (nhru)); theta_a_h = 0.
+ allocate (zwt_h (nhru)); zwt_h = 0.
+ allocate (Kl_h (nhru)); Kl_h = 0.
+
+ DO i = 1, nhru
+
+ IF (hrus%indx(i) == 0) CYCLE ! river
+ IF (hrus%agwt(i) == 0) CYCLE ! no area of soil, urban or wetland
+
+ ps = hru_patch%substt(hrus%ihru(i))
+ pe = hru_patch%subend(hrus%ihru(i))
+
+ theta_s_h = 0
+ sumwt = 0
+ DO ipatch = ps, pe
+ IF (patchtype(ipatch) <= 2) THEN
+ theta_s_h = theta_s_h + hru_patch%subfrc(ipatch) &
+ * sum(porsl(1:nl_soil,ipatch) * dz_soi(1:nl_soil) &
+ - wice_soisno(1:nl_soil,ipatch)/denice) / sum(dz_soi(1:nl_soil))
+ sumwt = sumwt + hru_patch%subfrc(ipatch)
+ ENDIF
+ ENDDO
+ IF (sumwt > 0) theta_s_h = theta_s_h / sumwt
+
+ IF (theta_s_h > 0.) THEN
+
+ air_h = 0.
+ zwt_h(i) = 0.
+ sumwt = 0.
+ DO ipatch = ps, pe
+ IF (patchtype(ipatch) <= 2) THEN
+ air_h = air_h + hru_patch%subfrc(ipatch) &
+ * (sum( porsl(1:nl_soil,ipatch) * dz_soi(1:nl_soil) &
+ - wliq_soisno(1:nl_soil,ipatch)/denh2o &
+ - wice_soisno(1:nl_soil,ipatch)/denice ) - wa(ipatch)/1.0e3)
+ air_h = max(0., air_h)
+
+ zwt_h(i) = zwt_h(i) + zwt(ipatch) * hru_patch%subfrc(ipatch)
+
+ sumwt = sumwt + hru_patch%subfrc(ipatch)
+ ENDIF
+ ENDDO
+ IF (sumwt > 0) air_h = air_h / sumwt
+ IF (sumwt > 0) zwt_h(i) = zwt_h(i) / sumwt
+
+ IF ((air_h <= 0.) .or. (zwt_h(i) <= 0.)) THEN
+ theta_a_h(i) = theta_s_h
+ zwt_h(i) = 0.
+ ELSE
+ theta_a_h(i) = air_h / zwt_h(i)
+ IF (theta_a_h(i) > theta_s_h) THEN
+ theta_a_h(i) = theta_s_h
+ zwt_h(i) = air_h / theta_a_h(i)
+ ENDIF
+ ENDIF
+
+ Kl_h(i) = 0.
+ sumwt = 0.
+ DO ipatch = ps, pe
+ IF (patchtype(ipatch) <= 2) THEN
+ DO ilev = 1, nl_soil
+ icefrac = min(1., wice_soisno(ilev,ipatch)/denice/dz_soi(ilev)/porsl(ilev,ipatch))
+ imped = 10.**(-e_ice*icefrac)
+ Kl_h(i) = Kl_h(i) + hru_patch%subfrc(ipatch) * raniso(soiltext(ipatch)) &
+ * hksati(ilev,ipatch)/1.0e3 * imped * dz_soi(ilev)/zi_soi(nl_soil)
+ ENDDO
+ sumwt = sumwt + hru_patch%subfrc(ipatch)
+ ENDIF
+ ENDDO
+ IF (sumwt > 0) Kl_h(i) = Kl_h(i) / sumwt
+ ELSE
+ ! Frozen soil.
+ Kl_h(i) = 0.
+ ENDIF
+
+ ENDDO
+
+ allocate (xsubs_h (nhru))
+ allocate (xsubs_fc (nhru))
+
+ xsubs_h (:) = 0.
+ xsubs_fc(:) = 0.
+
+ DO i = 1, nhru
+
+ j = hrus%inext(i)
+
+ IF (j <= 0) CYCLE ! downstream is out of catchment
+ IF (Kl_h(i) == 0.) CYCLE ! this HRU is frozen
+
+ j_is_river = (hrus%indx(j) == 0)
+
+ IF ((.not. j_is_river) .and. (Kl_h(j) == 0.)) CYCLE ! non-river downstream HRU is frozen
+
+ zsubs_h_up = hrus%elva(i) - zwt_h(i)
+
+ IF (.not. j_is_river) THEN
+ zsubs_h_dn = hrus%elva(j) - zwt_h(j)
+ ELSE
+ zsubs_h_dn = hrus%elva(1) - riverdpth_elm(ielm) + wdsrf_hru(hrus%ihru(1))
+ ENDIF
+
+ IF (.not. j_is_river) THEN
+ delp = hrus%plen(i) + hrus%plen(j)
+ ELSE
+ delp = hrus%plen(i)
+ ENDIF
+
+ slope = abs(hrus%elva(i)-hrus%elva(j))/delp
+ ! from Fan et al., JGR 112(D10125)
+ IF (slope > 0.16) THEN
+ bdamp = 4.8
+ ELSE
+ bdamp = 120./(1+150.*slope)
+ ENDIF
+
+ ! Upstream scheme for hydraulic conductivity
+ IF ((zsubs_h_up > zsubs_h_dn) .or. j_is_river) THEN
+ IF (zwt_h(i) > 1.5) THEN
+ ! from Fan et al., JGR 112(D10125)
+ Kl_fc = Kl_h(i) * bdamp * exp(-(zwt_h(i)-1.5)/bdamp)
+ ELSE
+ Kl_fc = Kl_h(i) * ((1.5-zwt_h(i)) + bdamp)
+ ENDIF
+ ELSE
+ IF (zwt_h(j) > 1.5) THEN
+ Kl_fc = Kl_h(j) * bdamp * exp(-(zwt_h(j)-1.5)/bdamp)
+ ELSE
+ Kl_fc = Kl_h(j) * ((1.5-zwt_h(j)) + bdamp)
+ ENDIF
+ ENDIF
+
+ ca = hrus%flen(i) * Kl_fc / theta_a_h(i) / delp / hrus%agwt(i) * deltime
+
+ IF (.not. j_is_river) THEN
+ cb = hrus%flen(i) * Kl_fc / theta_a_h(j) / delp / hrus%agwt(j) * deltime
+ ELSE
+ cb = hrus%flen(i) * Kl_fc / delp / hrus%area(j) * deltime
+ ENDIF
+
+ xsubs_fc(i) = (zsubs_h_up - zsubs_h_dn) * hrus%flen(i) * Kl_fc / (1+ca+cb) / delp
+
+ xsubs_h(i) = xsubs_h(i) + xsubs_fc(i) / hrus%agwt(i)
+
+ IF (j_is_river) THEN
+ xsubs_h(j) = xsubs_h(j) - xsubs_fc(i) / hrus%area(j)
+ ELSE
+ xsubs_h(j) = xsubs_h(j) - xsubs_fc(i) / hrus%agwt(j)
+ ENDIF
+
+ ENDDO
+
+ IF (hrus%indx(1) == 0) THEN
+ ! xsubs_h(1) is positive = out of soil column
+ IF (xsubs_h(1)*deltime > wdsrf_hru(hrus%ihru(1))) THEN
+ alp = wdsrf_hru(hrus%ihru(1)) / (xsubs_h(1)*deltime)
+ xsubs_h(1) = xsubs_h(1) * alp
+ DO i = 2, nhru
+ IF ((hrus%inext(i) == 1) .and. (hrus%agwt(i) > 0.)) THEN
+ xsubs_h(i) = xsubs_h(i) - (1.0-alp)*xsubs_fc(i)/hrus%agwt(i)
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ ! Update total subsurface lateral flow (1): Between hydrological units
+ ! for soil, urban, wetland or river patches
+ DO i = 1, nhru
+ xsubs_hru(hrus%ihru(i)) = xsubs_h(i)
+
+ ps = hru_patch%substt(hrus%ihru(i))
+ pe = hru_patch%subend(hrus%ihru(i))
+ DO ipatch = ps, pe
+ IF ((patchtype(ipatch) <= 2) .or. (hrus%indx(i) == 0)) THEN
+ xwsub(ipatch) = xwsub(ipatch) + xsubs_h(i) * 1.e3 ! (positive = out of soil column)
+ ENDIF
+ ENDDO
+
+ IF (hrus%indx(1) == 0) THEN
+ DO ipatch = ps, pe
+ IF (patchtype(ipatch) <= 2) THEN
+ rsub(ipatch) = - xsubs_h(1) * hrus%area(1) / sum(hrus%agwt) * 1.0e3 ! m/s to mm/s
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ DO i = 1, nhru
+ ! Inside hydrological units
+ IF (hrus%agwt(i) > 0) THEN
+
+ bdamp = 4.8
+
+ IF (zwt_h(i) > 1.5) THEN
+ ! from Fan et al., JGR 112(D10125)
+ Kl_in = Kl_h(i) * bdamp * exp(-(zwt_h(i)-1.5)/bdamp)
+ ELSE
+ Kl_in = Kl_h(i) * ((1.5-zwt_h(i)) + bdamp)
+ ENDIF
+
+ ps = hru_patch%substt(hrus%ihru(i))
+ pe = hru_patch%subend(hrus%ihru(i))
+ sumwt = sum(hru_patch%subfrc(ps:pe), mask = patchtype(ps:pe) <= 2)
+ IF (sumwt > 0) THEN
+ zwt_mean = sum(zwt(ps:pe)*hru_patch%subfrc(ps:pe), mask = patchtype(ps:pe) <= 2) / sumwt
+
+ DO ipatch = ps, pe
+ IF (patchtype(ipatch) <= 2) THEN
+ xsubs_pch(ipatch) = - Kl_in * (zwt(ipatch) - zwt_mean) *6.0*pi/hrus%agwt(i)
+ ! Update total subsurface lateral flow (2): Between patches
+ xwsub(ipatch) = xwsub(ipatch) + xsubs_pch(ipatch) * 1.e3 ! m/s to mm/s
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDDO
+
+ sumarea = sum(hrus%agwt)
+ IF (sumarea > 0) THEN
+ theta_a_elm (ielm) = sum(theta_a_h * hrus%agwt) / sumarea
+ zwt_elm (ielm) = sum(zwt_h * hrus%agwt) / sumarea
+ Kl_elm (ielm) = sum(Kl_h * hrus%agwt) / sumarea
+ ENDIF
+
+ deallocate (theta_a_h)
+ deallocate (zwt_h )
+ deallocate (Kl_h )
+ deallocate (xsubs_h )
+ deallocate (xsubs_fc )
+
+ ENDDO
+
+ DO ielm = 1, numelm
+ hs = elm_hru%substt(ielm)
+ he = elm_hru%subend(ielm)
+ wdsrf_elm(ielm) = sum(wdsrf_hru(hs:he) * elm_hru%subfrc(hs:he))
+ ENDDO
+
+ CALL retrieve_neighbour_data (theta_a_elm, theta_a_nb)
+ CALL retrieve_neighbour_data (zwt_elm , zwt_nb )
+ CALL retrieve_neighbour_data (Kl_elm , Kl_nb )
+ CALL retrieve_neighbour_data (wdsrf_elm , wdsrf_nb )
+
+ DO ielm = 1, numelm
+
+ hrus => hillslope_element(ielm)
+
+ iam_lake = (lake_id_elm(ielm) > 0)
+
+ DO jnb = 1, elementneighbour(ielm)%nnb
+
+ IF (elementneighbour(ielm)%glbindex(jnb) == -9) CYCLE ! skip ocean neighbour
+
+ nb_is_lake = islake_nb(ielm)%val(jnb)
+
+ IF (iam_lake .and. nb_is_lake) THEN
+ CYCLE
+ ENDIF
+
+ IF (.not. iam_lake) THEN
+ Kl_up = Kl_elm (ielm)
+ zwt_up = zwt_elm (ielm)
+ theta_a_up = theta_a_elm(ielm)
+ zsubs_up = elementneighbour(ielm)%myelva - zwt_up
+ area_up = sum(hrus%agwt)
+ ELSE
+ theta_a_up = 1.
+ zsubs_up = elementneighbour(ielm)%myelva - lakedepth_elm(ielm) + wdsrf_elm(ielm)
+ area_up = elementneighbour(ielm)%myarea
+ ENDIF
+
+ IF (.not. nb_is_lake) THEN
+ Kl_dn = Kl_nb(ielm)%val(jnb)
+ zwt_dn = zwt_nb(ielm)%val(jnb)
+ theta_a_dn = theta_a_nb(ielm)%val(jnb)
+ zsubs_dn = elementneighbour(ielm)%elva(jnb) - zwt_dn
+ area_dn = agwt_nb(ielm)%val(jnb)
+ ELSE
+ theta_a_dn = 1.
+ zsubs_dn = elementneighbour(ielm)%elva(jnb) - lakedp_nb(ielm)%val(jnb) + wdsrf_nb(ielm)%val(jnb)
+ area_dn = elementneighbour(ielm)%area(jnb)
+ ENDIF
+
+ IF ((.not. iam_lake) .and. (area_up <= 0)) CYCLE
+ IF ((.not. nb_is_lake) .and. (area_dn <= 0)) CYCLE
+ IF ((.not. iam_lake) .and. (Kl_up == 0. )) CYCLE
+ IF ((.not. nb_is_lake) .and. (Kl_dn == 0. )) CYCLE
+
+ ! water body is dry.
+ IF (iam_lake .and. (zsubs_up > zsubs_dn) .and. (wdsrf_elm(ielm) == 0.)) THEN
+ CYCLE
+ ENDIF
+ IF (nb_is_lake .and. (zsubs_up < zsubs_dn) .and. (wdsrf_nb(ielm)%val(jnb) == 0.)) THEN
+ CYCLE
+ ENDIF
+
+ lenbdr = elementneighbour(ielm)%lenbdr(jnb)
+
+ delp = elementneighbour(ielm)%dist(jnb)
+ IF (iam_lake) THEN
+ delp = elementneighbour(ielm)%area(jnb) / lenbdr * 0.5
+ ENDIF
+ IF (nb_is_lake) THEN
+ delp = elementneighbour(ielm)%myarea / lenbdr * 0.5
+ ENDIF
+
+ ! from Fan et al., JGR 112(D10125)
+ slope = abs(elementneighbour(ielm)%slope(jnb))
+ IF (slope > 0.16) THEN
+ bdamp = 4.8
+ ELSE
+ bdamp = 120./(1+150.*slope)
+ ENDIF
+
+ ! Upstream scheme for hydraulic conductivity
+ IF (nb_is_lake .or. ((.not. iam_lake) .and. (zsubs_up > zsubs_dn))) THEN
+ IF (zwt_up > 1.5) THEN
+ ! from Fan et al., JGR 112(D10125)
+ Kl_fc = Kl_up * bdamp * exp(-(zwt_up-1.5)/bdamp)
+ ELSE
+ Kl_fc = Kl_up * ((1.5-zwt_up) + bdamp)
+ ENDIF
+ ELSE
+ IF (zwt_dn > 1.5) THEN
+ Kl_fc = Kl_dn * bdamp * exp(-(zwt_dn-1.5)/bdamp)
+ ELSE
+ Kl_fc = Kl_dn * ((1.5-zwt_dn) + bdamp)
+ ENDIF
+ ENDIF
+
+ ca = lenbdr * Kl_fc / theta_a_up / delp / area_up * deltime
+ cb = lenbdr * Kl_fc / theta_a_dn / delp / area_dn * deltime
+
+ xsubs_nb = (zsubs_up - zsubs_dn) * lenbdr * Kl_fc / (1+ca+cb) / delp
+
+ IF (.not. iam_lake) THEN
+ xsubs_nb = xsubs_nb / sum(hrus%agwt)
+ ELSE
+ xsubs_nb = xsubs_nb / elementneighbour(ielm)%myarea
+ ENDIF
+
+ xsubs_elm(ielm) = xsubs_elm(ielm) + xsubs_nb
+
+ IF (nb_is_lake) THEN
+ ps = elm_patch%substt(ielm)
+ pe = elm_patch%subend(ielm)
+ DO ipatch = ps, pe
+ IF (patchtype(ipatch) <= 2) THEN
+ rsub(ipatch) = rsub(ipatch) + xsubs_nb * 1.e3
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ENDDO
+
+ ! Update total subsurface lateral flow (3): Between basins
+ ps = elm_patch%substt(ielm)
+ pe = elm_patch%subend(ielm)
+ DO ipatch = ps, pe
+ IF (iam_lake .or. (patchtype(ipatch) <= 2)) THEN
+ xwsub(ipatch) = xwsub(ipatch) + xsubs_elm(ielm) * 1.e3 ! m/s to mm/s
+ ENDIF
+ ENDDO
+
+ ENDDO
+
+ IF (allocated(theta_a_elm)) deallocate(theta_a_elm)
+ IF (allocated(zwt_elm )) deallocate(zwt_elm )
+ IF (allocated(Kl_elm )) deallocate(Kl_elm )
+
+ ENDIF
+
+ ! Exchange between soil water and aquifer.
+ IF (p_is_compute) THEN
+
+ sp_zi(0) = 0.
+ sp_zi(1:nl_soil) = zi_soi(1:nl_soil) * 1000.0 ! from meter to mm
+ sp_dz(1:nl_soil) = sp_zi(1:nl_soil) - sp_zi(0:nl_soil-1)
+
+ DO ipatch = 1, numpatch
+
+#if (defined CoLMDEBUG)
+ ! For water balance check, the sum of water in soil column before the calcultion
+ w_sum_before = sum(wliq_soisno(1:nl_soil,ipatch)) + sum(wice_soisno(1:nl_soil,ipatch)) &
+ + wa(ipatch) + wdsrf(ipatch) + wetwat(ipatch)
+#endif
+
+ IF (DEF_USE_Dynamic_Lake) THEN
+ is_dry_lake = (patchtype(ipatch) == 4) .and. (zwt(ipatch) > 0.)
+ ELSE
+ is_dry_lake = .false.
+ ENDIF
+
+ IF ((patchtype(ipatch) <= 1) .or. is_dry_lake) THEN
+
+ exwater = xwsub(ipatch) * deltime
+
+#ifdef Campbell_SOIL_MODEL
+ vl_r(1:nl_soil) = 0._r8
+ prms(1,:) = bsw(1:nl_soil,ipatch)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ vl_r (1:nl_soil) = theta_r (1:nl_soil,ipatch)
+ prms(1,1:nl_soil) = alpha_vgm(1:nl_soil,ipatch)
+ prms(2,1:nl_soil) = n_vgm (1:nl_soil,ipatch)
+ prms(3,1:nl_soil) = L_vgm (1:nl_soil,ipatch)
+ prms(4,1:nl_soil) = sc_vgm (1:nl_soil,ipatch)
+ prms(5,1:nl_soil) = fc_vgm (1:nl_soil,ipatch)
+#endif
+
+ DO ilev = 1, nl_soil
+ vol_ice(ilev) = wice_soisno(ilev,ipatch)/denice*1000. / sp_dz(ilev)
+ vol_ice(ilev) = min(vol_ice(ilev), porsl(ilev,ipatch))
+
+ eff_porosity(ilev) = max(wimp, porsl(ilev,ipatch)-vol_ice(ilev))
+ is_permeable(ilev) = eff_porosity(ilev) > max(wimp, vl_r(ilev))
+ IF (is_permeable(ilev)) THEN
+ vol_liq(ilev) = wliq_soisno(ilev,ipatch)/denh2o*1000. / sp_dz(ilev)
+ vol_liq(ilev) = min(eff_porosity(ilev), max(0., vol_liq(ilev)))
+ wresi(ilev) = wliq_soisno(ilev,ipatch) - sp_dz(ilev)*vol_liq(ilev)/1000. * denh2o
+ ELSE
+ vol_liq(ilev) = eff_porosity(ilev)
+ wresi(ilev) = 0.
+ ENDIF
+ ENDDO
+
+ zwtmm = zwt(ipatch) * 1000. ! m -> mm
+
+ ! check consistancy between water table location and liquid water content
+ DO ilev = 1, nl_soil
+ IF ((vol_liq(ilev) < eff_porosity(ilev)-1.e-8) .and. (zwtmm <= sp_zi(ilev-1))) THEN
+ zwtmm = sp_zi(ilev)
+ ENDIF
+ ENDDO
+
+ izwt = findloc_ud(zwtmm >= sp_zi, back=.true.)
+
+ IF (izwt <= nl_soil) THEN
+ IF (is_permeable(izwt) .and. (zwtmm > sp_zi(izwt-1))) THEN
+ vol_liq(izwt) = (wliq_soisno(izwt,ipatch)/denh2o*1000.0 &
+ - eff_porosity(izwt)*(sp_zi(izwt)-zwtmm)) / (zwtmm - sp_zi(izwt-1))
+
+ IF (vol_liq(izwt) < 0.) THEN
+ zwtmm = sp_zi(izwt)
+ vol_liq(izwt) = wliq_soisno(izwt,ipatch)/denh2o*1000.0 / (sp_zi(izwt)-sp_zi(izwt-1))
+ ENDIF
+
+ vol_liq(izwt) = max(0., min(eff_porosity(izwt), vol_liq(izwt)))
+ wresi(izwt) = wliq_soisno(izwt,ipatch) - (eff_porosity(izwt)*(sp_zi(izwt)-zwtmm) &
+ + vol_liq(izwt)*(zwtmm-sp_zi(izwt-1))) /1000. * denh2o
+ ENDIF
+ ENDIF
+
+ CALL soilwater_aquifer_exchange ( &
+ nl_soil, exwater, sp_zi, is_permeable, eff_porosity, vl_r, psi0(:,ipatch), &
+ hksati(:,ipatch), nprms, prms, porsl(nl_soil,ipatch), wdsrf(ipatch), &
+ vol_liq, zwtmm, wa(ipatch), izwt)
+
+ ! update the mass of liquid water
+ DO ilev = nl_soil, 1, -1
+ IF (is_permeable(ilev)) THEN
+ IF (zwtmm < sp_zi(ilev)) THEN
+ IF (zwtmm >= sp_zi(ilev-1)) THEN
+ wliq_soisno(ilev,ipatch) = ((eff_porosity(ilev)*(sp_zi(ilev)-zwtmm)) &
+ + vol_liq(ilev)*(zwtmm-sp_zi(ilev-1)))/1000.0 * denh2o
+ ELSE
+ wliq_soisno(ilev,ipatch) = denh2o * eff_porosity(ilev)*sp_dz(ilev)/1000.0
+ ENDIF
+ ELSE
+ wliq_soisno(ilev,ipatch) = denh2o * vol_liq(ilev)*sp_dz(ilev)/1000.0
+ ENDIF
+
+ wliq_soisno(ilev,ipatch) = wliq_soisno(ilev,ipatch) + wresi(ilev)
+ ENDIF
+ ENDDO
+
+ zwt(ipatch) = zwtmm/1000.0
+
+ ELSEIF (patchtype(ipatch) == 2) THEN ! wetland
+
+ wetwat(ipatch) = wdsrf(ipatch) + wa(ipatch) + wetwat(ipatch) - xwsub(ipatch)*deltime
+
+ IF (wetwat(ipatch) > wetwatmax) THEN
+ wdsrf (ipatch) = wetwat(ipatch) - wetwatmax
+ wetwat(ipatch) = wetwatmax
+ wa (ipatch) = 0.
+ ELSEIF (wetwat(ipatch) < 0) THEN
+ wa (ipatch) = wetwat(ipatch)
+ wdsrf (ipatch) = 0.
+ wetwat(ipatch) = 0.
+ ELSE
+ wdsrf(ipatch) = 0.
+ wa (ipatch) = 0.
+ ENDIF
+
+ ELSEIF (patchtype(ipatch) == 4) THEN ! land water bodies
+
+ wdsrf(ipatch) = wa(ipatch) + wdsrf(ipatch) - xwsub(ipatch)*deltime
+
+ IF (wdsrf(ipatch) < 0) THEN
+ wa (ipatch) = wdsrf(ipatch)
+ wdsrf(ipatch) = 0
+ ELSE
+ wa(ipatch) = 0
+ ENDIF
+
+ ENDIF
+
+#if (defined CoLMDEBUG)
+ ! For water balance check, the sum of water in soil column after the calcultion
+ w_sum_after = sum(wliq_soisno(1:nl_soil,ipatch)) + sum(wice_soisno(1:nl_soil,ipatch)) &
+ + wa(ipatch) + wdsrf(ipatch) + wetwat(ipatch)
+ errblc = w_sum_after - w_sum_before + xwsub(ipatch)*deltime
+
+ IF(abs(errblc) > 1.e-3)THEN
+ write(6,'(A,I0,4E20.5)') 'Warning (Subsurface Runoff): water balance violation ', &
+ ipatch, errblc, xwsub(ipatch), zwtmm
+ write(*,*) patchtype(ipatch)
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE subsurface_flow
+
+ ! ----------
+ SUBROUTINE subsurface_network_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(lake_id_elm )) deallocate(lake_id_elm )
+ IF (allocated(riverdpth_elm)) deallocate(riverdpth_elm)
+ IF (allocated(lakedepth_elm)) deallocate(lakedepth_elm)
+ IF (allocated(wdsrf_elm )) deallocate(wdsrf_elm )
+
+ IF (allocated(theta_a_nb)) deallocate(theta_a_nb)
+ IF (allocated(zwt_nb )) deallocate(zwt_nb )
+ IF (allocated(Kl_nb )) deallocate(Kl_nb )
+ IF (allocated(wdsrf_nb )) deallocate(wdsrf_nb )
+ IF (allocated(agwt_nb )) deallocate(agwt_nb )
+ IF (allocated(islake_nb )) deallocate(islake_nb )
+ IF (allocated(lakedp_nb )) deallocate(lakedp_nb )
+
+ IF (associated(hillslope_element)) deallocate(hillslope_element)
+
+ END SUBROUTINE subsurface_network_final
+
+END MODULE MOD_Catch_SubsurfaceFlow
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Vars_1DFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Vars_1DFluxes.F90
new file mode 100644
index 0000000000..3eab827aab
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Vars_1DFluxes.F90
@@ -0,0 +1,115 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_Vars_1DFluxes
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! 1D fluxes in lateral hydrological processes.
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! -- fluxes --
+ real(r8), allocatable :: xsubs_elm (:) ! subsurface lateral flow between basins [m/s]
+ real(r8), allocatable :: xsubs_hru (:) ! subsurface lateral flow between hydrological response units [m/s]
+ real(r8), allocatable :: xsubs_pch (:) ! subsurface lateral flow between patches inside one HRU [m/s]
+
+ real(r8), allocatable :: wdsrf_bsn_ta (:) ! time step average of river height [m]
+ real(r8), allocatable :: momen_riv_ta (:) ! time step average of river momentum [m^2/s]
+ real(r8), allocatable :: veloc_riv_ta (:) ! time step average of river velocity [m/s]
+ real(r8), allocatable :: discharge_ta (:) ! river discharge [m^3/s]
+
+ real(r8), allocatable :: wdsrf_bsnhru_ta (:) ! time step average of surface water depth [m]
+ real(r8), allocatable :: momen_bsnhru_ta (:) ! time step average of surface water momentum [m^2/s]
+ real(r8), allocatable :: veloc_bsnhru_ta (:) ! time step average of surface water veloctiy [m/s]
+
+ real(r8), allocatable :: xwsur (:) ! surface water exchange [mm h2o/s]
+ real(r8), allocatable :: xwsub (:) ! subsurface water exchange [mm h2o/s]
+ real(r8), allocatable :: fldarea (:) ! fraction of flooded area [-]
+
+ real(r8), allocatable :: ntacc_bsn (:)
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_CatchFluxes
+ PUBLIC :: deallocate_1D_CatchFluxes
+
+CONTAINS
+
+ SUBROUTINE allocate_1D_CatchFluxes
+
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandHRU, only: numhru
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_Catch_BasinNetwork, only: numbasin, numbsnhru
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+ allocate (xsubs_pch (numpatch)) ; xsubs_pch (:) = spval
+ allocate (xwsur (numpatch)) ; xwsur (:) = spval
+ allocate (xwsub (numpatch)) ; xwsub (:) = spval
+ allocate (fldarea (numpatch)) ; fldarea (:) = spval
+ ENDIF
+
+ IF (numelm > 0) THEN
+ allocate (xsubs_elm (numelm)) ; xsubs_elm(:) = spval
+ ENDIF
+
+ IF (numbasin > 0) THEN
+ allocate (wdsrf_bsn_ta (numbasin)) ; wdsrf_bsn_ta (:) = spval
+ allocate (momen_riv_ta (numbasin)) ; momen_riv_ta (:) = spval
+ allocate (veloc_riv_ta (numbasin)) ; veloc_riv_ta (:) = spval
+ allocate (discharge_ta (numbasin)) ; discharge_ta (:) = spval
+ ENDIF
+
+ IF (numhru > 0) THEN
+ allocate (xsubs_hru (numhru)); xsubs_hru(:) = spval
+ ENDIF
+
+ IF (numbsnhru > 0) THEN
+ allocate (wdsrf_bsnhru_ta (numbsnhru)) ; wdsrf_bsnhru_ta (:) = spval
+ allocate (momen_bsnhru_ta (numbsnhru)) ; momen_bsnhru_ta (:) = spval
+ allocate (veloc_bsnhru_ta (numbsnhru)) ; veloc_bsnhru_ta (:) = spval
+ ENDIF
+
+ IF (numbasin > 0) allocate (ntacc_bsn (numbasin))
+ IF (numbasin > 0) ntacc_bsn(:) = 0.
+
+ ENDIF
+
+ END SUBROUTINE allocate_1D_CatchFluxes
+
+ SUBROUTINE deallocate_1D_CatchFluxes
+
+ IMPLICIT NONE
+
+ IF (allocated(xsubs_elm)) deallocate(xsubs_elm)
+ IF (allocated(xsubs_hru)) deallocate(xsubs_hru)
+ IF (allocated(xsubs_pch)) deallocate(xsubs_pch)
+
+ IF (allocated(wdsrf_bsn_ta)) deallocate(wdsrf_bsn_ta)
+ IF (allocated(momen_riv_ta)) deallocate(momen_riv_ta)
+ IF (allocated(veloc_riv_ta)) deallocate(veloc_riv_ta)
+ IF (allocated(discharge_ta)) deallocate(discharge_ta)
+
+ IF (allocated(wdsrf_bsnhru_ta)) deallocate(wdsrf_bsnhru_ta)
+ IF (allocated(momen_bsnhru_ta)) deallocate(momen_bsnhru_ta)
+ IF (allocated(veloc_bsnhru_ta)) deallocate(veloc_bsnhru_ta)
+
+ IF (allocated(xwsur )) deallocate(xwsur )
+ IF (allocated(xwsub )) deallocate(xwsub )
+ IF (allocated(fldarea)) deallocate(fldarea)
+
+ IF (allocated(ntacc_bsn)) deallocate(ntacc_bsn)
+
+ END SUBROUTINE deallocate_1D_CatchFluxes
+
+END MODULE MOD_Catch_Vars_1DFluxes
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Vars_TimeVariables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Vars_TimeVariables.F90
new file mode 100644
index 0000000000..37b9af417f
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_Vars_TimeVariables.F90
@@ -0,0 +1,178 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_Vars_TimeVariables
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Time Variables in lateral hydrological processes.
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Catch_BasinNetwork
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ ! -- state variables (1): necessary for restart --
+ real(r8), allocatable :: veloc_elm (:) ! river velocity [m/s]
+ real(r8), allocatable :: veloc_hru (:) ! surface water velocity [m/s]
+ real(r8), allocatable :: wdsrf_hru (:) ! surface water depth [m]
+
+ real(r8), allocatable :: wdsrf_elm_prev (:) ! river or lake water depth at previous time step [m]
+ real(r8), allocatable :: wdsrf_hru_prev (:) ! surface water depth at previous time step [m]
+
+ ! -- state variables (2): only in model --
+ real(r8), allocatable :: wdsrf_bsn (:) ! river or lake water depth [m]
+ real(r8), allocatable :: veloc_riv (:) ! river velocity [m/s]
+ real(r8), allocatable :: momen_riv (:) ! unit river momentum [m^2/s]
+ real(r8), allocatable :: wdsrf_bsnhru (:) ! surface water depth [m]
+ real(r8), allocatable :: veloc_bsnhru (:) ! surface water velocity [m/s]
+ real(r8), allocatable :: momen_bsnhru (:) ! unit surface water momentum [m^2/s]
+
+ real(r8), allocatable :: wdsrf_bsn_prev (:) ! river or lake water depth at previous time step [m]
+ real(r8), allocatable :: wdsrf_bsnhru_prev (:) ! surface water depth at previous time step [m]
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_CatchTimeVariables
+ PUBLIC :: deallocate_CatchTimeVariables
+
+ PUBLIC :: read_CatchTimeVariables
+ PUBLIC :: write_CatchTimeVariables
+
+CONTAINS
+
+ SUBROUTINE allocate_CatchTimeVariables
+
+ USE MOD_SPMD_Task
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandHRU, only: numhru
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numelm > 0) THEN
+ allocate (veloc_elm (numelm))
+ allocate (wdsrf_elm_prev (numelm))
+ ENDIF
+
+ IF (numhru > 0) THEN
+ allocate (veloc_hru (numhru))
+ allocate (wdsrf_hru (numhru))
+ allocate (wdsrf_hru_prev (numhru))
+ ENDIF
+
+ IF (numbasin > 0) allocate (wdsrf_bsn (numbasin))
+ IF (numbasin > 0) allocate (veloc_riv (numbasin))
+ IF (numbasin > 0) allocate (momen_riv (numbasin))
+ IF (numbasin > 0) allocate (wdsrf_bsn_prev(numbasin))
+
+ IF (numbsnhru > 0) allocate (wdsrf_bsnhru (numbsnhru))
+ IF (numbsnhru > 0) allocate (veloc_bsnhru (numbsnhru))
+ IF (numbsnhru > 0) allocate (momen_bsnhru (numbsnhru))
+ IF (numbsnhru > 0) allocate (wdsrf_bsnhru_prev (numbsnhru))
+
+ ENDIF
+
+ END SUBROUTINE allocate_CatchTimeVariables
+
+ SUBROUTINE READ_CatchTimeVariables (file_restart)
+
+ USE MOD_Mesh
+ USE MOD_LandHRU
+ USE MOD_Vector_ReadWrite
+ USE MOD_ElmVector
+ USE MOD_HRUVector
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ CALL vector_read_and_scatter (file_restart, veloc_elm, numelm, 'veloc_riv', elm_data_address)
+ CALL compute_push_data (push_elm2bsn, veloc_elm, veloc_riv, spval)
+
+ CALL vector_read_and_scatter (file_restart, wdsrf_elm_prev, numelm, 'wdsrf_bsn_prev', elm_data_address)
+ CALL compute_push_data (push_elm2bsn, wdsrf_elm_prev, wdsrf_bsn_prev, spval)
+
+ CALL vector_read_and_scatter (file_restart, veloc_hru, numhru, 'veloc_hru', hru_data_address)
+ CALL compute_push_data (push_elmhru2bsnhru, veloc_hru, veloc_bsnhru, spval)
+
+ CALL vector_read_and_scatter (file_restart, wdsrf_hru_prev, numhru, 'wdsrf_hru_prev', hru_data_address)
+ CALL compute_push_data (push_elmhru2bsnhru, wdsrf_hru_prev, wdsrf_bsnhru_prev, spval)
+
+ END SUBROUTINE READ_CatchTimeVariables
+
+ SUBROUTINE WRITE_CatchTimeVariables (file_restart)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh
+ USE MOD_LandHRU
+ USE MOD_Vector_ReadWrite
+ USE MOD_ElmVector
+ USE MOD_HRUVector
+ IMPLICIT NONE
+
+ integer :: iwork
+ character(len=*), intent(in) :: file_restart
+
+ IF (p_is_root) THEN
+ CALL ncio_create_file (trim(file_restart))
+ CALL ncio_define_dimension(file_restart, 'basin', totalnumelm)
+ CALL ncio_define_dimension(file_restart, 'hydrounit', totalnumhru)
+
+ CALL ncio_write_serial (file_restart, 'basin', eindex_glb, 'basin')
+ CALL ncio_put_attr (file_restart, 'basin', 'long_name', 'basin index')
+
+ CALL ncio_write_serial (file_restart, 'bsn_hru', eindx_hru, 'hydrounit')
+ CALL ncio_put_attr (file_restart, 'bsn_hru', &
+ 'long_name', 'basin index of hydrological units')
+
+ CALL ncio_write_serial (file_restart, 'hru_type' , htype_hru, 'hydrounit')
+ CALL ncio_put_attr (file_restart, 'hru_type' , &
+ 'long_name', 'index of hydrological units inside basin')
+ ENDIF
+
+ CALL compute_push_data (push_bsn2elm, veloc_riv, veloc_elm, spval)
+ CALL vector_gather_and_write (&
+ veloc_elm, numelm, totalnumelm, elm_data_address, file_restart, 'veloc_riv', 'basin')
+
+ CALL compute_push_data (push_bsn2elm, wdsrf_bsn_prev, wdsrf_elm_prev, spval)
+ CALL vector_gather_and_write (&
+ wdsrf_elm_prev, numelm, totalnumelm, elm_data_address, file_restart, 'wdsrf_bsn_prev', 'basin')
+
+ CALL compute_push_data (push_bsnhru2elmhru, veloc_bsnhru, veloc_hru, spval)
+ CALL vector_gather_and_write (&
+ veloc_hru, numhru, totalnumhru, hru_data_address, file_restart, 'veloc_hru', 'hydrounit')
+
+ CALL compute_push_data (push_bsnhru2elmhru, wdsrf_bsnhru_prev, wdsrf_hru_prev, spval)
+ CALL vector_gather_and_write (&
+ wdsrf_hru_prev, numhru, totalnumhru, hru_data_address, file_restart, 'wdsrf_hru_prev', 'hydrounit')
+
+ END SUBROUTINE WRITE_CatchTimeVariables
+
+ SUBROUTINE deallocate_CatchTimeVariables
+
+ IMPLICIT NONE
+
+ IF (allocated(veloc_elm)) deallocate(veloc_elm)
+ IF (allocated(veloc_hru)) deallocate(veloc_hru)
+ IF (allocated(wdsrf_hru)) deallocate(wdsrf_hru)
+
+ IF (allocated(wdsrf_elm_prev)) deallocate(wdsrf_elm_prev)
+ IF (allocated(wdsrf_hru_prev)) deallocate(wdsrf_hru_prev)
+
+ IF (allocated (wdsrf_bsn )) deallocate (wdsrf_bsn )
+ IF (allocated (veloc_riv )) deallocate (veloc_riv )
+ IF (allocated (momen_riv )) deallocate (momen_riv )
+ IF (allocated (wdsrf_bsn_prev)) deallocate (wdsrf_bsn_prev)
+
+ IF (allocated (wdsrf_bsnhru )) deallocate (wdsrf_bsnhru )
+ IF (allocated (veloc_bsnhru )) deallocate (veloc_bsnhru )
+ IF (allocated (momen_bsnhru )) deallocate (momen_bsnhru )
+ IF (allocated (wdsrf_bsnhru_prev)) deallocate (wdsrf_bsnhru_prev)
+
+ END SUBROUTINE deallocate_CatchTimeVariables
+
+END MODULE MOD_Catch_Vars_TimeVariables
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_WriteParameters.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_WriteParameters.F90
new file mode 100644
index 0000000000..c872b4ebf4
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Catch_WriteParameters.F90
@@ -0,0 +1,230 @@
+#include
+
+#ifdef CatchLateralFlow
+MODULE MOD_Catch_WriteParameters
+
+CONTAINS
+
+ SUBROUTINE write_catch_parameters
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_Vector_ReadWrite
+ USE MOD_ElmVector
+ USE MOD_Catch_Reservoir
+ USE MOD_Vars_TimeInvariants, only : wf_sand, wf_clay, wf_om, wf_gravels, patchclass
+ USE MOD_Catch_SubsurfaceFlow, only : hillslope_element, lake_id_elm
+ USE MOD_HRUVector, only : totalnumhru, hru_data_address, eindx_hru, htype_hru
+ USE MOD_Mesh, only : numelm
+ USE MOD_LandHRU, only : numhru
+ USE MOD_LandPatch, only : hru_patch
+ USE MOD_Vars_Global, only : spval
+ IMPLICIT NONE
+
+ character(len=256) :: file_parameters
+ character(len=1) :: slev
+ real(r8), allocatable :: hrupara(:), varpara(:)
+ integer :: ilev, i, ps, pe, ielm, ihru, j
+
+ file_parameters = trim(DEF_dir_output) // '/' // trim(DEF_CASE_NAME) // '/catch_parameters.nc'
+
+ IF (p_is_root) THEN
+ CALL ncio_create_file (trim(file_parameters))
+ CALL ncio_define_dimension(file_parameters, 'hydrounit', totalnumhru)
+
+ CALL ncio_write_serial (file_parameters, 'bsn_hru', eindx_hru, 'hydrounit')
+ CALL ncio_put_attr (file_parameters, 'bsn_hru', &
+ 'long_name', 'basin index of hydrological units')
+
+ CALL ncio_write_serial (file_parameters, 'hru_type' , htype_hru, 'hydrounit')
+ CALL ncio_put_attr (file_parameters, 'hru_type' , &
+ 'long_name', 'index of hydrological units inside basin')
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numhru > 0) allocate (hrupara (numhru))
+ ENDIF
+
+ DO ilev = 1, 5
+
+ write(slev,'(i1.1)') ilev
+
+ ! sand
+ IF (p_is_compute) THEN
+ DO i = 1, numhru
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ hrupara(i) = sum(wf_sand(ilev,ps:pe) * hru_patch%subfrc(ps:pe))
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'wf_sand_l'//slev, 'hydrounit')
+
+ ! clay
+ IF (p_is_compute) THEN
+ DO i = 1, numhru
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ hrupara(i) = sum(wf_clay(ilev,ps:pe) * hru_patch%subfrc(ps:pe))
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'wf_clay_l'//slev, 'hydrounit')
+
+ ! organic matter
+ IF (p_is_compute) THEN
+ DO i = 1, numhru
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ hrupara(i) = sum(wf_om(ilev,ps:pe) * hru_patch%subfrc(ps:pe))
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'wf_om_l'//slev, 'hydrounit')
+
+ ! silt
+ IF (p_is_compute) THEN
+ DO i = 1, numhru
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ hrupara(i) = sum((1-wf_sand(ilev,ps:pe)-wf_gravels(ilev,ps:pe)-wf_om(ilev,ps:pe)-wf_clay(ilev,ps:pe)) * hru_patch%subfrc(ps:pe))
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'wf_silt_l'//slev, 'hydrounit')
+ ENDDO
+
+
+
+ IF (p_is_compute) THEN
+ DO i = 1, numhru
+ ps = hru_patch%substt(i)
+ pe = hru_patch%subend(i)
+ hrupara(i) = patchclass(ps)
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'lulc_igbp', 'hydrounit')
+
+ IF (p_is_compute) THEN
+ IF (numhru > 0) hrupara(:) = spval
+ DO ielm = 1, numelm
+ IF (lake_id_elm(ielm) <= 0) THEN
+ DO i = 1, hillslope_element(ielm)%nhru
+ IF (hillslope_element(ielm)%indx(i) /= 0) THEN
+ ihru = hillslope_element(ielm)%ihru(i)
+ hrupara(ihru) = hillslope_element(ielm)%plen(i) * 2.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'slope_length', 'hydrounit')
+
+ IF (p_is_root) THEN
+ CALL ncio_put_attr (file_parameters, 'slope_length', 'units', 'm')
+ CALL ncio_put_attr (file_parameters, 'slope_length', 'missing_value', spval)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numhru > 0) hrupara(:) = spval
+ DO ielm = 1, numelm
+ IF (lake_id_elm(ielm) <= 0) THEN
+ DO i = 1, hillslope_element(ielm)%nhru
+ IF (hillslope_element(ielm)%indx(i) /= 0) THEN
+ ihru = hillslope_element(ielm)%ihru(i)
+ hrupara(ihru) = hillslope_element(ielm)%elva(i)
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'elevation', 'hydrounit')
+
+ IF (p_is_root) THEN
+ CALL ncio_put_attr (file_parameters, 'elevation', 'units', 'm')
+ CALL ncio_put_attr (file_parameters, 'elevation', 'missing_value', spval)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numhru > 0) hrupara(:) = spval
+ DO ielm = 1, numelm
+ IF (lake_id_elm(ielm) <= 0) THEN
+ DO i = 1, hillslope_element(ielm)%nhru
+ IF (hillslope_element(ielm)%indx(i) /= 0) THEN
+ ihru = hillslope_element(ielm)%ihru(i)
+ j = hillslope_element(ielm)%inext(i)
+ IF (j > 0) THEN
+ hrupara(ihru) = (hillslope_element(ielm)%hand(i) - hillslope_element(ielm)%hand(j)) &
+ / (hillslope_element(ielm)%plen(i) + hillslope_element(ielm)%plen(j))
+ ELSE
+ hrupara(ihru) = hillslope_element(ielm)%hand(i) / hillslope_element(ielm)%plen(i)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ hrupara, numhru, totalnumhru, hru_data_address, file_parameters, 'slope_ratio', 'hydrounit')
+
+ IF (p_is_root) THEN
+ CALL ncio_put_attr (file_parameters, 'slope_ratio', 'units', '-')
+ CALL ncio_put_attr (file_parameters, 'slope_ratio', 'missing_value', spval)
+ ENDIF
+
+ IF (allocated(hrupara)) deallocate(hrupara)
+
+
+ ! ----- reservoirs -----
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (numresv_uniq > 0) THEN
+
+ IF (p_is_root) THEN
+ CALL ncio_define_dimension (file_parameters, 'reservoir', numresv_uniq)
+ CALL ncio_write_serial (file_parameters, 'resv_hylak_id' , resv_hylak_id, 'reservoir')
+ CALL ncio_put_attr (file_parameters, 'resv_hylak_id' , 'long_name', &
+ 'HydroLAKE ID of reservoirs')
+ ENDIF
+
+ allocate (varpara (numresv_uniq))
+
+ CALL reservoir_gather_var (volresv_total, varpara)
+ IF (p_is_root) THEN
+ CALL ncio_write_serial (file_parameters, 'volresv_total', varpara, 'reservoir', 1)
+ CALL ncio_put_attr (file_parameters, 'volresv_total', 'units', 'm^3')
+ ENDIF
+
+ CALL reservoir_gather_var (qresv_mean, varpara)
+ IF (p_is_root) THEN
+ CALL ncio_write_serial (file_parameters, 'qresv_mean', varpara, 'reservoir', 1)
+ CALL ncio_put_attr (file_parameters, 'qresv_mean', 'units', 'm^3/s')
+ ENDIF
+
+ CALL reservoir_gather_var (qresv_flood, varpara)
+ IF (p_is_root) THEN
+ CALL ncio_write_serial (file_parameters, 'qresv_flood', varpara, 'reservoir', 1)
+ CALL ncio_put_attr (file_parameters, 'qresv_flood', 'units', 'm^3/s')
+ ENDIF
+
+ deallocate (varpara)
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE write_catch_parameters
+
+END MODULE MOD_Catch_WriteParameters
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_ElementNeighbour.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_ElementNeighbour.F90
new file mode 100644
index 0000000000..8897bb1f3c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_ElementNeighbour.F90
@@ -0,0 +1,711 @@
+#include
+
+MODULE MOD_ElementNeighbour
+!--------------------------------------------------------------------------------!
+! DESCRIPTION: !
+! !
+! Element Neighbours : data and communication subroutines. !
+! !
+! Created by Shupeng Zhang, May 2023 !
+!--------------------------------------------------------------------------------!
+
+ USE MOD_Precision
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ ! -- neighbour parameters --
+ type element_neighbour_type
+
+ integer :: nnb ! number of neighbours
+ real(r8) :: myarea ! area of this element [m^2]
+ real(r8) :: myelva ! elevation of this element [m]
+
+ integer*8, allocatable :: glbindex (:) ! neighbour global index
+
+ ! data address: (1,:) refers to process, (2,:) refers to location
+ integer , allocatable :: addr (:,:)
+
+ real(r8), allocatable :: dist (:) ! distance between element centers [m]
+ real(r8), allocatable :: lenbdr (:) ! length of boundary line [m]
+ real(r8), allocatable :: area (:) ! area of neighbours [m^2]
+ real(r8), allocatable :: elva (:) ! elevation of neighbours [m]
+ real(r8), allocatable :: slope (:) ! slope (positive) [-]
+
+ END type element_neighbour_type
+
+ type(element_neighbour_type), allocatable :: elementneighbour (:)
+
+ ! -- neighbour communication --
+ type neighbour_sendrecv_type
+ integer :: ndata
+ integer*8, allocatable :: glbindex (:)
+ integer, allocatable :: ielement (:)
+ END type neighbour_sendrecv_type
+
+ type(neighbour_sendrecv_type), allocatable :: recvaddr(:)
+ type(neighbour_sendrecv_type), allocatable :: sendaddr(:)
+
+ INTERFACE allocate_neighbour_data
+ MODULE procedure allocate_neighbour_data_real8
+ MODULE procedure allocate_neighbour_data_logic
+ END INTERFACE allocate_neighbour_data
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE element_neighbour_init (patcharea, lc_year)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFVector
+ USE MOD_Mesh
+ USE MOD_Pixel
+ USE MOD_LandElm
+ USE MOD_LandPatch
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year ! which year of land cover data used
+ real(r8), intent(in) :: patcharea (:)
+
+ ! Local Variables
+ character(len=256) :: neighbour_file
+
+ integer :: ielm
+ integer :: iwork, mesg(2), isrc, idest
+ integer :: nrecv, irecv
+ integer :: iloc, iloc1, iloc2
+ integer :: nnb, nnbinq, inb, ndata
+
+ integer :: maxnnb
+ integer , allocatable :: nnball (:)
+ integer , allocatable :: idxnball (:,:)
+ real(r8), allocatable :: lenbdall (:,:)
+
+ integer , allocatable :: addrelement(:)
+
+ integer*8, allocatable :: eindex (:)
+ integer, allocatable :: icache1 (:)
+ integer, allocatable :: icache2 (:,:)
+ real(r8), allocatable :: rcache2 (:,:)
+
+ integer*8, allocatable :: elm_sorted (:)
+ integer, allocatable :: order (:)
+ integer*8, allocatable :: idxinq (:)
+ integer, allocatable :: addrinq (:)
+
+ logical, allocatable :: mask(:)
+
+ real(r8), allocatable :: rlon_b(:), rlat_b(:)
+ type(pointer_real8_1d), allocatable :: rlon_nb(:), rlat_nb(:)
+
+ real(r8), allocatable :: area_b(:)
+ real(r8), allocatable :: elva_b(:)
+
+ character(len=256) :: lndname, cyear
+ real(r8), allocatable :: elv_patches(:)
+
+ type(pointer_real8_1d), allocatable :: area_nb (:) ! m^2
+ type(pointer_real8_1d), allocatable :: elva_nb (:) ! m
+
+ integer :: istt, iend
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ neighbour_file = DEF_ElementNeighbour_file
+
+ IF (p_is_root) THEN
+ CALL ncio_read_serial (neighbour_file, 'num_neighbour', nnball )
+ CALL ncio_read_serial (neighbour_file, 'idx_neighbour', idxnball)
+ CALL ncio_read_serial (neighbour_file, 'len_border' , lenbdall)
+
+ maxnnb = size(idxnball,1)
+
+ lenbdall = lenbdall * 1.e3 ! km to m
+ ENDIF
+
+#ifdef USEMPI
+
+ CALL mpi_bcast (maxnnb, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+ IF (p_is_root) THEN
+
+ allocate (addrelement (size(nnball)))
+ addrelement(:) = -1
+
+ DO iwork = 0, p_np_compute-1
+
+ CALL mpi_recv (mesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ nrecv = mesg(2)
+
+ IF (nrecv > 0) THEN
+
+ allocate (eindex (nrecv))
+ allocate (icache1 (nrecv))
+ allocate (icache2 (maxnnb,nrecv))
+ allocate (rcache2 (maxnnb,nrecv))
+
+ CALL mpi_recv (eindex, nrecv, MPI_INTEGER8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ addrelement(eindex) = isrc
+
+ idest = isrc
+
+ icache1 = nnball(eindex)
+ CALL mpi_send (icache1, nrecv, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ icache2(:,irecv) = idxnball(:,eindex(irecv))
+ ENDDO
+ CALL mpi_send (icache2, maxnnb*nrecv, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ DO irecv = 1, nrecv
+ rcache2(:,irecv) = lenbdall(:,eindex(irecv))
+ ENDDO
+ CALL mpi_send (rcache2, maxnnb*nrecv, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (eindex )
+ deallocate (icache1)
+ deallocate (icache2)
+ deallocate (rcache2)
+
+ ENDIF
+ ENDDO
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+
+ IF (numelm > 0) THEN
+ allocate (eindex (numelm))
+ eindex = landelm%eindex
+ ENDIF
+
+#ifdef USEMPI
+ mesg(1:2) = (/p_iam_glb, numelm/)
+ CALL mpi_send (mesg(1:2), 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numelm > 0) THEN
+ CALL mpi_send (eindex, numelm, MPI_INTEGER8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (nnball (numelm))
+ CALL mpi_recv (nnball, numelm, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (idxnball (maxnnb,numelm))
+ CALL mpi_recv (idxnball, maxnnb*numelm, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (lenbdall (maxnnb,numelm))
+ CALL mpi_recv (lenbdall, maxnnb*numelm, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+#else
+ allocate (icache1 (numelm))
+ allocate (icache2 (maxnnb,numelm))
+ allocate (rcache2 (maxnnb,numelm))
+
+ icache1 = nnball
+ icache2 = idxnball
+ rcache2 = lenbdall
+
+ DO ielm = 1, numelm
+ nnball (ielm) = icache1 (eindex(ielm))
+ idxnball (:,ielm) = icache2 (:,eindex(ielm))
+ lenbdall (:,ielm) = rcache2 (:,eindex(ielm))
+ ENDDO
+
+ deallocate (icache1, icache2, rcache2)
+#endif
+
+ IF (numelm > 0) THEN
+
+ allocate (elementneighbour (numelm))
+
+ DO ielm = 1, numelm
+ nnb = nnball(ielm)
+ elementneighbour(ielm)%nnb = nnb
+
+ IF (nnb > 0) THEN
+ allocate (elementneighbour(ielm)%glbindex (nnb))
+ allocate (elementneighbour(ielm)%lenbdr (nnb))
+ allocate (elementneighbour(ielm)%addr (2,nnb))
+
+ elementneighbour(ielm)%glbindex = idxnball(1:nnb,ielm)
+ elementneighbour(ielm)%lenbdr = lenbdall(1:nnb,ielm)
+ elementneighbour(ielm)%addr(1,:) = -9999
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ DO iwork = 0, p_np_compute-1
+
+ CALL mpi_recv (mesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = mesg(1)
+ nrecv = mesg(2)
+
+ IF (nrecv > 0) THEN
+ allocate (eindex (nrecv))
+ allocate (icache1 (nrecv))
+
+ CALL mpi_recv (eindex, nrecv, MPI_INTEGER8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ icache1 = addrelement(eindex)
+
+ idest = isrc
+ CALL mpi_send (icache1, nrecv, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate(eindex, icache1)
+ ENDIF
+ ENDDO
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+
+ IF (numelm > 0) THEN
+ allocate (elm_sorted (numelm))
+ allocate (order (numelm))
+
+ elm_sorted = eindex
+ order = (/(ielm, ielm = 1, numelm)/)
+
+ CALL quicksort (numelm, elm_sorted, order)
+
+#ifdef USEMPI
+ allocate(idxinq (numelm*maxnnb))
+#endif
+
+ nnbinq = 0
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+
+ IF (elementneighbour(ielm)%glbindex(inb) <= 0) CYCLE ! skip ocean neighbour
+
+ iloc = find_in_sorted_list1 (elementneighbour(ielm)%glbindex(inb), numelm, elm_sorted)
+ IF (iloc > 0) THEN
+ elementneighbour(ielm)%addr(1,inb) = -1
+ elementneighbour(ielm)%addr(2,inb) = order(iloc)
+#ifdef USEMPI
+ ELSE
+ CALL insert_into_sorted_list1 (elementneighbour(ielm)%glbindex(inb), nnbinq, idxinq, iloc)
+#endif
+ ENDIF
+ ENDDO
+ ENDDO
+ ELSE
+ nnbinq = 0
+ ENDIF
+
+#ifdef USEMPI
+ mesg(1:2) = (/p_iam_glb, nnbinq/)
+ CALL mpi_send (mesg(1:2), 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (nnbinq > 0) THEN
+
+ CALL mpi_send (idxinq(1:nnbinq), nnbinq, MPI_INTEGER8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (addrinq (nnbinq))
+ CALL mpi_recv (addrinq, nnbinq, MPI_INTEGER, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ ENDIF
+
+ IF (nnbinq > 0) allocate(mask (nnbinq))
+
+ allocate (recvaddr (0:p_np_compute-1))
+ DO iwork = 0, p_np_compute-1
+ IF (nnbinq > 0) THEN
+ mask = (addrinq == p_address_compute(iwork))
+ ndata = count(mask)
+ ELSE
+ ndata = 0
+ ENDIF
+
+ recvaddr(iwork)%ndata = ndata
+ IF (ndata > 0) THEN
+ allocate (recvaddr(iwork)%glbindex (ndata))
+ recvaddr(iwork)%glbindex = pack(idxinq(1:nnbinq), mask)
+ ENDIF
+ ENDDO
+
+ IF (nnbinq > 0) deallocate(mask)
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF ((elementneighbour(ielm)%addr(1,inb) == -9999) &
+ .and. (elementneighbour(ielm)%glbindex(inb) > 0)) THEN ! skip ocean neighbour
+
+ iloc = find_in_sorted_list1 (elementneighbour(ielm)%glbindex(inb), &
+ nnbinq, idxinq(1:nnbinq))
+
+ iwork = p_itis_compute(addrinq(iloc))
+ iloc1 = find_in_sorted_list1 (elementneighbour(ielm)%glbindex(inb), &
+ recvaddr(iwork)%ndata, recvaddr(iwork)%glbindex)
+
+ elementneighbour(ielm)%addr(1,inb) = iwork
+ elementneighbour(ielm)%addr(2,inb) = iloc1
+ ENDIF
+ ENDDO
+ ENDDO
+
+ allocate (sendaddr (0:p_np_compute-1))
+ DO iwork = 0, p_np_compute-1
+ sendaddr(iwork)%ndata = 0
+ ENDDO
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%addr(1,inb) >= 0) THEN
+ iwork = elementneighbour(ielm)%addr(1,inb)
+ sendaddr(iwork)%ndata = sendaddr(iwork)%ndata + 1
+ ENDIF
+ ENDDO
+ ENDDO
+
+ DO iwork = 0, p_np_compute-1
+ IF (sendaddr(iwork)%ndata > 0) THEN
+ allocate (sendaddr(iwork)%glbindex (sendaddr(iwork)%ndata))
+ sendaddr(iwork)%ndata = 0
+ ENDIF
+ ENDDO
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%addr(1,inb) >= 0) THEN
+ iwork = elementneighbour(ielm)%addr(1,inb)
+ CALL insert_into_sorted_list1 (eindex(ielm), &
+ sendaddr(iwork)%ndata, sendaddr(iwork)%glbindex, iloc)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ DO iwork = 0, p_np_compute-1
+ IF (sendaddr(iwork)%ndata > 0) THEN
+ IF (sendaddr(iwork)%ndata < size(sendaddr(iwork)%glbindex)) THEN
+ allocate (icache1 (sendaddr(iwork)%ndata))
+ icache1 = sendaddr(iwork)%glbindex(1:sendaddr(iwork)%ndata)
+
+ deallocate (sendaddr(iwork)%glbindex)
+ allocate (sendaddr(iwork)%glbindex (sendaddr(iwork)%ndata))
+ sendaddr(iwork)%glbindex = icache1
+
+ deallocate (icache1)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO iwork = 0, p_np_compute-1
+ IF (sendaddr(iwork)%ndata > 0) THEN
+ allocate (sendaddr(iwork)%ielement (sendaddr(iwork)%ndata))
+
+ DO inb = 1, sendaddr(iwork)%ndata
+ iloc = find_in_sorted_list1 (sendaddr(iwork)%glbindex(inb), numelm, elm_sorted)
+ sendaddr(iwork)%ielement(inb) = order(iloc)
+ ENDDO
+ ENDIF
+ ENDDO
+#endif
+ ENDIF
+
+ IF (allocated(addrelement)) deallocate(addrelement)
+ IF (allocated(elm_sorted )) deallocate(elm_sorted )
+ IF (allocated(nnball )) deallocate(nnball )
+ IF (allocated(idxnball )) deallocate(idxnball )
+ IF (allocated(lenbdall )) deallocate(lenbdall )
+ IF (allocated(eindex )) deallocate(eindex )
+ IF (allocated(icache1 )) deallocate(icache1 )
+ IF (allocated(icache2 )) deallocate(icache2 )
+ IF (allocated(rcache2 )) deallocate(rcache2 )
+ IF (allocated(order )) deallocate(order )
+ IF (allocated(idxinq )) deallocate(idxinq )
+ IF (allocated(addrinq )) deallocate(addrinq )
+ IF (allocated(mask )) deallocate(mask )
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ write(cyear,'(i4.4)') lc_year
+ lndname = trim(DEF_dir_landdata) // '/topography/'//trim(cyear)//'/elevation_patches.nc'
+ CALL ncio_read_vector (lndname, 'elevation_patches', landpatch, elv_patches)
+
+ IF (p_is_compute) THEN
+
+ DO ielm = 1, numelm
+ nnb = elementneighbour(ielm)%nnb
+ IF (nnb > 0) THEN
+ allocate (elementneighbour(ielm)%dist (nnb))
+ allocate (elementneighbour(ielm)%area (nnb))
+ allocate (elementneighbour(ielm)%elva (nnb))
+ allocate (elementneighbour(ielm)%slope (nnb))
+ ENDIF
+ ENDDO
+
+ IF (numelm > 0) THEN
+ allocate (rlon_b(numelm))
+ allocate (rlat_b(numelm))
+ CALL landelm%get_lonlat_radian (rlon_b, rlat_b)
+ ENDIF
+
+ CALL allocate_neighbour_data (rlon_nb)
+ CALL allocate_neighbour_data (rlat_nb)
+
+ CALL retrieve_neighbour_data (rlon_b, rlon_nb)
+ CALL retrieve_neighbour_data (rlat_b, rlat_nb)
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%glbindex(inb) > 0) THEN ! skip ocean neighbour
+ elementneighbour(ielm)%dist(inb) = 1.0e3 * arclen ( &
+ rlat_b (ielm), rlon_b (ielm), &
+ rlat_nb(ielm)%val(inb), rlon_nb(ielm)%val(inb))
+ elementneighbour(ielm)%dist(inb) = max(elementneighbour(ielm)%dist(inb), 90.)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ IF (numelm > 0) THEN
+ allocate (area_b(numelm))
+ allocate (elva_b(numelm))
+ DO ielm = 1, numelm
+ istt = elm_patch%substt(ielm)
+ iend = elm_patch%subend(ielm)
+ area_b(ielm) = sum(patcharea(istt:iend))
+ elva_b(ielm) = sum(elv_patches(istt:iend) * elm_patch%subfrc(istt:iend))
+
+ elementneighbour(ielm)%myarea = area_b(ielm)
+ elementneighbour(ielm)%myelva = elva_b(ielm)
+ ENDDO
+ ENDIF
+
+ CALL allocate_neighbour_data (area_nb)
+ CALL retrieve_neighbour_data (area_b, area_nb)
+
+ CALL allocate_neighbour_data (elva_nb)
+ CALL retrieve_neighbour_data (elva_b, elva_nb)
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%glbindex(inb) > 0) THEN ! skip ocean neighbour
+ elementneighbour(ielm)%area (inb) = area_nb(ielm)%val(inb)
+ elementneighbour(ielm)%elva (inb) = elva_nb(ielm)%val(inb)
+ elementneighbour(ielm)%slope(inb) = &
+ abs(elva_nb(ielm)%val(inb) - elva_b(ielm)) / elementneighbour(ielm)%dist(inb)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ IF (allocated(rlon_b )) deallocate(rlon_b )
+ IF (allocated(rlat_b )) deallocate(rlat_b )
+ IF (allocated(elva_b )) deallocate(elva_b )
+ IF (allocated(area_b )) deallocate(area_b )
+ IF (allocated(rlon_nb)) deallocate(rlon_nb)
+ IF (allocated(rlat_nb)) deallocate(rlat_nb)
+ IF (allocated(area_nb)) deallocate(area_nb)
+ IF (allocated(elva_nb)) deallocate(elva_nb)
+
+ ENDIF
+
+ END SUBROUTINE element_neighbour_init
+
+ ! ----------
+ SUBROUTINE retrieve_neighbour_data (vec_in, nbdata)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Mesh, only: numelm
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: vec_in (:)
+ type(pointer_real8_1d) :: nbdata (:)
+
+ ! Local Variables
+ logical, allocatable :: smask(:), rmask(:)
+ integer, allocatable :: req_send(:), req_recv(:)
+ type(pointer_real8_1d), allocatable :: sbuff(:), rbuff(:)
+ integer :: iwork, ielm, inb, iloc
+
+ IF (p_is_compute) THEN
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%addr(1,inb)== -1) THEN
+ iloc = elementneighbour(ielm)%addr(2,inb)
+ nbdata(ielm)%val(inb) = vec_in(iloc)
+ ENDIF
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_compute, p_err)
+
+ allocate (smask (0:p_np_compute-1))
+ allocate (req_send (0:p_np_compute-1))
+ allocate (sbuff (0:p_np_compute-1))
+ smask(:) = .false.
+
+ DO iwork = 0, p_np_compute-1
+ IF (sendaddr(iwork)%ndata > 0) THEN
+ smask(iwork) = .true.
+
+ allocate (sbuff(iwork)%val (sendaddr(iwork)%ndata))
+ sbuff(iwork)%val = vec_in(sendaddr(iwork)%ielement)
+
+ CALL mpi_isend(sbuff(iwork)%val, sendaddr(iwork)%ndata, MPI_REAL8, &
+ p_address_compute(iwork), 101, p_comm_glb, req_send(iwork), p_err)
+ ENDIF
+ ENDDO
+
+ allocate (rmask (0:p_np_compute-1))
+ allocate (req_recv (0:p_np_compute-1))
+ allocate (rbuff (0:p_np_compute-1))
+ rmask(:) = .false.
+
+ DO iwork = 0, p_np_compute-1
+ IF (recvaddr(iwork)%ndata > 0) THEN
+ rmask(iwork) = .true.
+
+ allocate (rbuff(iwork)%val (recvaddr(iwork)%ndata))
+
+ CALL mpi_irecv(rbuff(iwork)%val, recvaddr(iwork)%ndata, MPI_REAL8, &
+ p_address_compute(iwork), 101, p_comm_glb, req_recv(iwork), p_err)
+ ENDIF
+ ENDDO
+
+ IF (any(rmask)) THEN
+
+ CALL mpi_waitall(count(rmask), pack(req_recv,rmask), MPI_STATUSES_IGNORE, p_err)
+
+ DO ielm = 1, numelm
+ DO inb = 1, elementneighbour(ielm)%nnb
+ IF (elementneighbour(ielm)%addr(1,inb) >= 0) THEN
+ iwork = elementneighbour(ielm)%addr(1,inb)
+ iloc = elementneighbour(ielm)%addr(2,inb)
+ nbdata(ielm)%val(inb) = rbuff(iwork)%val(iloc)
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+
+ IF (any(smask)) THEN
+ CALL mpi_waitall(count(smask), pack(req_send,smask), MPI_STATUSES_IGNORE, p_err)
+ ENDIF
+
+ IF (allocated(smask)) deallocate(smask)
+ IF (allocated(rmask)) deallocate(rmask)
+
+ IF (allocated(req_send)) deallocate(req_send)
+ IF (allocated(req_recv)) deallocate(req_recv)
+
+ IF (allocated(sbuff)) deallocate(sbuff)
+ IF (allocated(rbuff)) deallocate(rbuff)
+
+ CALL mpi_barrier (p_comm_compute, p_err)
+#endif
+
+ ENDIF
+
+ END SUBROUTINE retrieve_neighbour_data
+
+ ! ---
+ SUBROUTINE allocate_neighbour_data_real8 (nbdata)
+
+ USE MOD_Mesh, only: numelm
+ IMPLICIT NONE
+
+ type(pointer_real8_1d), allocatable :: nbdata(:)
+ integer :: ielm
+
+ IF (numelm > 0) THEN
+ allocate (nbdata(numelm))
+ DO ielm = 1, numelm
+ IF (elementneighbour(ielm)%nnb > 0) THEN
+ allocate (nbdata(ielm)%val (elementneighbour(ielm)%nnb))
+ ENDIF
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE allocate_neighbour_data_real8
+
+ ! ---
+ SUBROUTINE allocate_neighbour_data_logic (nbdata)
+
+ USE MOD_Mesh, only: numelm
+ IMPLICIT NONE
+
+ type(pointer_logic_1d), allocatable :: nbdata(:)
+ integer :: ielm
+
+ IF (numelm > 0) THEN
+ allocate (nbdata(numelm))
+ DO ielm = 1, numelm
+ IF (elementneighbour(ielm)%nnb > 0) THEN
+ allocate (nbdata(ielm)%val (elementneighbour(ielm)%nnb))
+ ENDIF
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE allocate_neighbour_data_logic
+
+ ! ----------
+ SUBROUTINE element_neighbour_final ()
+
+ IMPLICIT NONE
+ integer :: i
+
+ IF (allocated(elementneighbour)) THEN
+ DO i = 1, size(elementneighbour)
+ IF (allocated(elementneighbour(i)%glbindex)) deallocate(elementneighbour(i)%glbindex)
+ IF (allocated(elementneighbour(i)%addr )) deallocate(elementneighbour(i)%addr )
+ IF (allocated(elementneighbour(i)%dist )) deallocate(elementneighbour(i)%dist )
+ IF (allocated(elementneighbour(i)%lenbdr)) deallocate(elementneighbour(i)%lenbdr)
+ IF (allocated(elementneighbour(i)%area )) deallocate(elementneighbour(i)%area )
+ IF (allocated(elementneighbour(i)%elva )) deallocate(elementneighbour(i)%elva )
+ IF (allocated(elementneighbour(i)%slope )) deallocate(elementneighbour(i)%slope )
+ ENDDO
+ deallocate(elementneighbour)
+ ENDIF
+
+ IF (allocated(recvaddr)) THEN
+ DO i = lbound(recvaddr,1), ubound(recvaddr,1)
+ IF (allocated(recvaddr(i)%glbindex)) deallocate(recvaddr(i)%glbindex)
+ IF (allocated(recvaddr(i)%ielement)) deallocate(recvaddr(i)%ielement)
+ ENDDO
+ ENDIF
+
+ IF (allocated(sendaddr)) THEN
+ DO i = lbound(sendaddr,1), ubound(sendaddr,1)
+ IF (allocated(sendaddr(i)%glbindex)) deallocate(sendaddr(i)%glbindex)
+ IF (allocated(sendaddr(i)%ielement)) deallocate(sendaddr(i)%ielement)
+ ENDDO
+ ENDIF
+
+ IF (allocated(recvaddr)) deallocate(recvaddr)
+ IF (allocated(sendaddr)) deallocate(sendaddr)
+
+ END SUBROUTINE element_neighbour_final
+
+END MODULE MOD_ElementNeighbour
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90
new file mode 100644
index 0000000000..d41418d8ce
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_Reservoir.F90
@@ -0,0 +1,337 @@
+#include
+
+#ifdef GridRiverLakeFlow
+MODULE MOD_Grid_Reservoir
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Reservoir module in gridded mesh.
+!
+! Created by Shupeng Zhang, Oct 2025
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_DataType
+
+ integer :: totalnumresv
+ integer :: numresv
+ integer, allocatable :: ucat2resv (:)
+ integer, allocatable :: resv_global_index(:)
+ type(pointer_int32_1d), allocatable :: resv_data_address (:)
+
+
+ ! parameters
+ integer, allocatable :: dam_GRAND_ID (:) ! GRAND dam ID
+
+ integer, allocatable :: dam_build_year(:) ! year in which the dam/barrier was built
+
+ real(r8), allocatable :: volresv_total (:) ! total reservoir volume [m^3]
+ real(r8), allocatable :: volresv_emerg (:) ! emergency reservoir volume [m^3]
+ real(r8), allocatable :: volresv_adjust(:) ! adjustment reservoir volume [m^3]
+ real(r8), allocatable :: volresv_normal(:) ! normal reservoir volume [m^3]
+
+ real(r8), allocatable :: qresv_flood (:) ! flood reservoir outflow [m^3/s]
+ real(r8), allocatable :: qresv_adjust (:) ! adjustment reservoir outflow [m^3/s]
+ real(r8), allocatable :: qresv_normal (:) ! normal reservoir outflow [m^3/s]
+
+ ! fluxes
+ real(r8), allocatable :: qresv_in (:) ! reservoir inflow [m^3/s]
+ real(r8), allocatable :: qresv_out (:) ! reservoir outflow [m^3/s]
+
+ ! -- PUBLIC SUBROUTINEs --
+ PUBLIC :: reservoir_init
+ PUBLIC :: reservoir_operation
+ PUBLIC :: reservoir_final
+
+CONTAINS
+
+ ! -------
+ SUBROUTINE reservoir_init ( )
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Utils
+ USE MOD_Namelist, only: DEF_ReservoirPara_file
+ USE MOD_Grid_RiverLakeNetwork, only: numucat, ucat_ucid, lake_type
+
+ IMPLICIT NONE
+
+ ! Local variables
+ character(len=256) :: parafile
+
+ integer, allocatable :: dam_seq(:), order(:), local_ucid(:)
+ real(r8), allocatable :: rcache (:)
+ integer, allocatable :: icache (:)
+
+ integer, parameter :: dam_seq_chunk_size = 1048576
+ integer :: i, iloc, irsv, nresv, irank
+ integer :: istart, iend, local_index
+
+
+ parafile = DEF_ReservoirPara_file
+
+#ifndef MPAS_EMBEDDED_COLM
+ IF (p_is_root) THEN
+ CALL ncio_read_serial (parafile, 'dam_GRAND_ID', dam_GRAND_ID)
+ ENDIF
+
+ CALL ncio_read_bcast_serial (parafile, 'dam_seq', dam_seq)
+
+ totalnumresv = size(dam_seq)
+#else
+ CALL ncio_inquire_length (parafile, 'dam_seq', totalnumresv)
+#endif
+
+ IF (p_is_compute) THEN
+
+ allocate (ucat2resv (numucat))
+ ucat2resv = 0
+ allocate (resv_global_index(numucat))
+
+ numresv = 0
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numucat > 0 .and. totalnumresv > 0) THEN
+ allocate (order (numucat))
+ allocate (local_ucid (numucat))
+
+ order = (/(i, i = 1, numucat)/)
+ local_ucid = ucat_ucid
+ CALL quicksort (numucat, local_ucid, order)
+
+ istart = 1
+ DO WHILE (istart <= totalnumresv)
+ iend = min(istart + dam_seq_chunk_size - 1, totalnumresv)
+ CALL ncio_read_part_serial (parafile, 'dam_seq', istart, iend, dam_seq)
+
+ DO i = lbound(dam_seq,1), ubound(dam_seq,1)
+ iloc = find_in_sorted_list1 (dam_seq(i), numucat, local_ucid)
+ IF (iloc > 0) THEN
+ local_index = order(iloc)
+ IF (ucat2resv(local_index) == 0) THEN
+ numresv = numresv + 1
+ lake_type(local_index) = 2
+ ucat2resv(local_index) = numresv
+ resv_global_index(numresv) = i
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (dam_seq)
+ istart = iend + 1
+ ENDDO
+ ENDIF
+#else
+ allocate (order (totalnumresv))
+ order = (/(i, i = 1, totalnumresv)/)
+
+ CALL quicksort (totalnumresv, dam_seq, order)
+
+ DO i = 1, numucat
+ iloc = find_in_sorted_list1 (ucat_ucid(i), totalnumresv, dam_seq)
+ IF (iloc > 0) THEN
+ numresv = numresv + 1
+ lake_type(i) = 2
+ ucat2resv(i) = numresv
+ resv_global_index(numresv) = order(iloc)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+#ifndef MPAS_EMBEDDED_COLM
+#ifdef COLM_PARALLEL
+ IF (.not. allocated(resv_data_address)) allocate (resv_data_address (0:p_np_compute-1))
+
+ IF (p_is_root) THEN
+ DO irank = 0, p_np_compute-1
+
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ nresv = numresv
+ ELSE
+ CALL mpi_recv (nresv, 1, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ IF (nresv > 0) THEN
+ allocate (resv_data_address(irank)%val (nresv))
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ resv_data_address(irank)%val = resv_global_index(1:nresv)
+ ELSE
+ CALL mpi_recv (resv_data_address(irank)%val, nresv, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ CALL mpi_send (numresv, 1, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numresv > 0) THEN
+ CALL mpi_send (resv_global_index(1:numresv), numresv, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ ENDIF
+#else
+ IF (numresv > 0) THEN
+ allocate (resv_data_address (0:0))
+ allocate (resv_data_address(0)%val (numresv))
+ resv_data_address(0)%val = resv_global_index(1:numresv)
+ ENDIF
+#endif
+#endif
+
+ IF (p_is_compute) THEN
+
+ IF (numresv > 0) THEN
+
+ allocate (dam_build_year (numresv))
+
+ allocate (volresv_total (numresv))
+ allocate (volresv_emerg (numresv))
+ allocate (volresv_adjust (numresv))
+ allocate (volresv_normal (numresv))
+
+ allocate (qresv_flood (numresv))
+ allocate (qresv_adjust (numresv))
+ allocate (qresv_normal (numresv))
+
+ allocate (qresv_in (numresv))
+ allocate (qresv_out (numresv))
+
+ ENDIF
+
+ ENDIF
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_compute .and. (numresv > 0)) THEN
+ CALL ncio_read_indexed_serial (parafile, 'dam_year', resv_global_index(1:numresv), icache)
+ dam_build_year = icache
+
+ CALL ncio_read_indexed_serial (parafile, 'dam_TotalVol_mcm', resv_global_index(1:numresv), rcache)
+ volresv_total = rcache*1.e6
+
+ CALL ncio_read_indexed_serial (parafile, 'dam_ConVol_mcm', resv_global_index(1:numresv), rcache)
+ volresv_normal = rcache*1.e6
+
+ CALL ncio_read_indexed_serial (parafile, 'dam_Qn', resv_global_index(1:numresv), rcache)
+ qresv_normal = rcache
+
+ CALL ncio_read_indexed_serial (parafile, 'dam_Qf', resv_global_index(1:numresv), rcache)
+ qresv_flood = rcache
+ ENDIF
+#else
+ CALL ncio_read_bcast_serial (parafile, 'dam_year', icache)
+ IF (p_is_compute .and. (numresv > 0)) THEN
+ dam_build_year = icache(resv_global_index(1:numresv))
+ ENDIF
+
+ CALL ncio_read_bcast_serial (parafile, 'dam_TotalVol_mcm', rcache)
+ IF (p_is_compute .and. (numresv > 0)) THEN
+ volresv_total = rcache(resv_global_index(1:numresv))*1.e6
+ ENDIF
+
+ CALL ncio_read_bcast_serial (parafile, 'dam_ConVol_mcm', rcache)
+ IF (p_is_compute .and. (numresv > 0)) THEN
+ volresv_normal = rcache(resv_global_index(1:numresv))*1.e6
+ ENDIF
+
+ CALL ncio_read_bcast_serial (parafile, 'dam_Qn', rcache)
+ IF (p_is_compute .and. (numresv > 0)) THEN
+ qresv_normal = rcache(resv_global_index(1:numresv))
+ ENDIF
+
+ CALL ncio_read_bcast_serial (parafile, 'dam_Qf', rcache)
+ IF (p_is_compute .and. (numresv > 0)) THEN
+ qresv_flood = rcache(resv_global_index(1:numresv))
+ ENDIF
+#endif
+
+
+ IF (p_is_compute) THEN
+ DO irsv = 1, numresv
+ volresv_emerg (irsv) = volresv_total(irsv) * 0.94
+ volresv_adjust(irsv) = volresv_total(irsv) * 0.77
+ volresv_normal(irsv) = min(volresv_total(irsv)*0.7, volresv_normal(irsv))
+ qresv_adjust (irsv) = (qresv_normal(irsv) + qresv_flood(irsv)) * 0.5
+ ENDDO
+ ENDIF
+
+ IF (allocated(dam_seq)) deallocate(dam_seq)
+ IF (allocated(order )) deallocate(order )
+ IF (allocated(rcache )) deallocate(rcache )
+ IF (allocated(icache )) deallocate(icache )
+
+ END SUBROUTINE reservoir_init
+
+
+ SUBROUTINE reservoir_operation (method, irsv, qin, vol, qout)
+
+ IMPLICIT NONE
+ integer, intent(in) :: method
+ integer, intent(in) :: irsv
+ real(r8), intent(in) :: qin, vol
+ real(r8), intent(out) :: qout
+
+ ! local variables
+ real(r8) :: q1
+
+ IF (method == 1) THEN
+ ! *** Reference ***
+ ! [1] Mizuki Funato, Dai Yamazaki, Dung Trung Vu.
+ ! Development of an improved reservoir operation scheme for global flood modeling.
+ ! ESS Open Archive . October 24, 2024.
+
+ IF (vol > volresv_emerg(irsv)) THEN
+ qout = max(qin, qresv_flood(irsv))
+ ELSEIF (vol > volresv_adjust(irsv)) THEN
+ qout = qresv_adjust(irsv) + (qresv_flood(irsv)-qresv_adjust(irsv)) &
+ * ((vol-volresv_adjust(irsv))/(volresv_emerg(irsv)-volresv_adjust(irsv)))**0.1
+ IF (qin > qresv_flood(irsv)) THEN
+ q1 = qresv_normal(irsv) + (qin-qresv_normal(irsv)) &
+ * (vol-volresv_normal(irsv))/(volresv_emerg(irsv)-volresv_normal(irsv))
+ qout = max(q1, qout)
+ ENDIF
+ ELSEIF (vol > volresv_normal(irsv)) THEN
+ qout = qresv_normal(irsv) + (qresv_adjust(irsv)-qresv_normal(irsv)) &
+ * ((vol-volresv_normal(irsv))/(volresv_adjust(irsv)-volresv_normal(irsv)))**3.
+ ELSE
+ qout = (vol/volresv_normal(irsv))**0.5 * qresv_normal(irsv)
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE reservoir_operation
+
+
+ SUBROUTINE reservoir_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(ucat2resv )) deallocate (ucat2resv )
+ IF (allocated(resv_global_index)) deallocate (resv_global_index)
+ IF (allocated(resv_data_address)) deallocate (resv_data_address)
+
+ IF (allocated(dam_GRAND_ID )) deallocate (dam_GRAND_ID )
+ IF (allocated(dam_build_year )) deallocate (dam_build_year )
+
+ IF (allocated(volresv_total )) deallocate (volresv_total )
+ IF (allocated(volresv_emerg )) deallocate (volresv_emerg )
+ IF (allocated(volresv_adjust )) deallocate (volresv_adjust )
+ IF (allocated(volresv_normal )) deallocate (volresv_normal )
+
+ IF (allocated(qresv_flood )) deallocate (qresv_flood )
+ IF (allocated(qresv_adjust )) deallocate (qresv_adjust )
+ IF (allocated(qresv_normal )) deallocate (qresv_normal )
+
+ IF (allocated(qresv_in )) deallocate (qresv_in )
+ IF (allocated(qresv_out )) deallocate (qresv_out )
+
+ END SUBROUTINE reservoir_final
+
+END MODULE MOD_Grid_Reservoir
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeFlow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeFlow.F90
new file mode 100644
index 0000000000..790931e487
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeFlow.F90
@@ -0,0 +1,787 @@
+#include
+
+#ifdef GridRiverLakeFlow
+MODULE MOD_Grid_RiverLakeFlow
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! River Lake flow.
+!
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Grid_RiverLakeNetwork
+ USE MOD_Grid_RiverLakeTimeVars
+ USE MOD_Grid_Reservoir
+ USE MOD_Grid_RiverLakeHist
+#ifdef GridRiverLakeSediment
+ USE MOD_Grid_RiverLakeSediment, only: grid_sediment_init, grid_sediment_calc, &
+ grid_sediment_final, sediment_diag_accumulate, sediment_forcing_put, &
+ read_sediment_restart
+#endif
+ IMPLICIT NONE
+
+ real(r8), parameter :: RIVERMIN = 1.e-5_r8
+
+ real(r8), save :: acctime_rnof_max
+
+ real(r8) :: acctime_rnof
+ real(r8), allocatable :: acc_rnof_uc (:)
+ logical, allocatable :: filter_rnof (:)
+
+CONTAINS
+
+ ! ---------
+ SUBROUTINE grid_riverlake_flow_init ()
+
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_Forcing, only: forcmask_pch
+ USE MOD_Vars_TimeInvariants, only: patchtype, patchmask
+ IMPLICIT NONE
+
+ acctime_rnof_max = DEF_GRIDBASED_ROUTING_MAX_DT
+ acctime_rnof = 0.
+
+ IF (p_is_compute) THEN
+ ! Allocate on all ranks (zero-length if numucat/numpatch=0)
+ ! to avoid passing unallocated arrays to assumed-shape MPI wrappers.
+ allocate (acc_rnof_uc (numucat))
+ acc_rnof_uc = 0.
+ ENDIF
+
+ ! excluding (patchtype >= 99), virtual patches and those forcing missed
+ IF (p_is_compute) THEN
+ allocate (filter_rnof (numpatch))
+ IF (numpatch > 0) THEN
+ filter_rnof = patchtype < 99
+ filter_rnof = filter_rnof .and. patchmask
+ IF (DEF_forcing%has_missing_value) THEN
+ filter_rnof = filter_rnof .and. forcmask_pch
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef GridRiverLakeSediment
+ CALL grid_sediment_init()
+ IF (len_trim(gridriver_restart_file) > 0) THEN
+ CALL read_sediment_restart(gridriver_restart_file)
+ ENDIF
+#endif
+
+ END SUBROUTINE grid_riverlake_flow_init
+
+ ! ---------
+ SUBROUTINE grid_riverlake_flow (year, deltime)
+
+ USE MOD_Utils
+ USE MOD_Namelist, only: DEF_Reservoir_Method, DEF_USE_SEDIMENT
+ USE MOD_Vars_1DFluxes, only: rnof
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandPatch, only: elm_patch, numpatch
+ USE MOD_Const_Physical, only: grav
+ USE MOD_Vars_Global, only: spval
+#ifdef GridRiverLakeSediment
+ USE MOD_Vars_1DForcing, only: forc_prc, forc_prl
+#endif
+ IMPLICIT NONE
+
+ integer, intent(in) :: year
+ real(r8), intent(in) :: deltime
+
+ ! Local Variables
+ integer :: i, j, irsv, ntimestep
+ real(r8) :: dt_this
+ integer :: sed_clock_start, sed_clock_end, sed_clock_rate
+ real(r8) :: sed_elapsed
+
+ real(r8), allocatable :: rnof_gd(:)
+ real(r8), allocatable :: rnof_uc(:)
+
+#ifdef GridRiverLakeSediment
+ real(r8), allocatable :: prcp_gd(:)
+ real(r8), allocatable :: prcp_uc(:)
+ real(r8), allocatable :: prcp_pch(:)
+ real(r8), allocatable :: floodarea_sed(:)
+#endif
+
+ logical, allocatable :: is_built_resv(:)
+
+ real(r8), allocatable :: wdsrf_next(:)
+ real(r8), allocatable :: veloc_next(:)
+
+ real(r8), allocatable :: hflux_fc(:)
+ real(r8), allocatable :: mflux_fc(:)
+ real(r8), allocatable :: zgrad_dn(:)
+
+ real(r8), allocatable :: hflux_resv(:)
+ real(r8), allocatable :: mflux_resv(:)
+
+ real(r8), allocatable :: hflux_sumups(:)
+ real(r8), allocatable :: mflux_sumups(:)
+ real(r8), allocatable :: zgrad_sumups(:)
+
+ real(r8), allocatable :: sum_hflux_riv(:)
+ real(r8), allocatable :: sum_mflux_riv(:)
+ real(r8), allocatable :: sum_zgrad_riv(:)
+
+ real(r8) :: veloct_fc, height_fc, momen_fc, zsurf_fc
+ real(r8) :: bedelv_fc, height_up, height_dn
+ real(r8) :: vwave_up, vwave_dn, hflux_up, hflux_dn, mflux_up, mflux_dn
+ real(r8) :: volwater, friction, floodarea
+ real(r8), allocatable :: dt_res(:), dt_all(:)
+ logical, allocatable :: ucatfilter(:)
+ real(r8) :: global_dt_remaining(1)
+#ifdef CoLMDEBUG
+ real(r8) :: totalvol_bef, totalvol_aft, totalrnof, totaldis
+#endif
+
+
+ IF (p_is_compute) THEN
+
+ allocate (rnof_gd (numinpm))
+ allocate (rnof_uc (numucat))
+
+ IF (numpatch > 0) THEN
+ CALL compute_remap_data_pset2grid (remap_patch2inpm, rnof, rnof_gd, &
+ fillvalue = 0., filter = filter_rnof)
+ ELSE
+ rnof_gd = 0._r8
+ ENDIF
+
+ IF (numinpm > 0) THEN
+ WHERE (push_ucat2inpm%sum_area > 0)
+ rnof_gd = rnof_gd / push_ucat2inpm%sum_area
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_inpm2ucat, rnof_gd, rnof_uc, &
+ fillvalue = 0., mode = 'sum')
+
+ IF (numucat > 0) THEN
+ acc_rnof_uc = acc_rnof_uc + rnof_uc*1.e-3*deltime
+ ENDIF
+
+ deallocate(rnof_gd)
+ deallocate(rnof_uc)
+
+#ifdef GridRiverLakeSediment
+ IF (DEF_USE_SEDIMENT) THEN
+ ! Allocate zero-length arrays on empty ranks to avoid passing unallocated
+ ! arrays to assumed-shape dummy arguments in MPI communication routines.
+ IF (numpatch > 0) THEN
+ allocate (prcp_pch (numpatch))
+ prcp_pch = forc_prc + forc_prl
+ ELSE
+ allocate (prcp_pch (0))
+ ENDIF
+ IF (numinpm > 0) THEN
+ allocate (prcp_gd (numinpm))
+ ELSE
+ allocate (prcp_gd (0))
+ ENDIF
+ IF (numucat > 0) THEN
+ allocate (prcp_uc (numucat))
+ ELSE
+ allocate (prcp_uc (0))
+ ENDIF
+
+ CALL compute_remap_data_pset2grid (remap_patch2inpm, prcp_pch, prcp_gd, &
+ fillvalue = 0., filter = filter_rnof)
+
+ IF (numinpm > 0) THEN
+ WHERE (push_ucat2inpm%sum_area > 0)
+ prcp_gd = prcp_gd / push_ucat2inpm%sum_area
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_inpm2ucat, prcp_gd, prcp_uc, &
+ fillvalue = 0., mode = 'sum')
+
+ ! Convert from area-integrated [mm/s * m²] back to flux density [mm/s].
+ ! push_data(mode='sum') produces area-integrated values (like rnof_uc),
+ ! but the sediment yield formula expects a rate and multiplies by area internally.
+ IF (numucat > 0) THEN
+ WHERE (topo_area > 0._r8)
+ prcp_uc = prcp_uc / topo_area
+ END WHERE
+ ENDIF
+
+ CALL sediment_forcing_put(prcp_uc, deltime)
+
+ deallocate(prcp_pch)
+ deallocate(prcp_gd)
+ deallocate(prcp_uc)
+ ENDIF
+#endif
+
+ ENDIF
+
+
+ acctime_rnof = acctime_rnof + deltime
+
+ IF (acctime_rnof+0.01 < acctime_rnof_max) THEN
+ RETURN
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (is_built_resv (numucat))
+ allocate (wdsrf_next (numucat))
+ allocate (veloc_next (numucat))
+ allocate (hflux_fc (numucat))
+ allocate (mflux_fc (numucat))
+ allocate (zgrad_dn (numucat))
+ allocate (sum_hflux_riv (numucat))
+ allocate (sum_mflux_riv (numucat))
+ allocate (sum_zgrad_riv (numucat))
+ allocate (ucatfilter (numucat))
+
+ allocate (hflux_sumups (numucat))
+ allocate (mflux_sumups (numucat))
+ allocate (zgrad_sumups (numucat))
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ allocate (hflux_resv (numucat))
+ allocate (mflux_resv (numucat))
+ ENDIF
+
+ allocate (dt_res (max(1,numrivsys)))
+ allocate (dt_all (max(1,numrivsys)))
+
+#ifdef CoLMDEBUG
+ totalrnof = sum(acc_rnof_uc)
+ totalvol_bef = 0.
+#endif
+
+ DO i = 1, numucat
+
+ is_built_resv(i) = .false.
+ IF (lake_type(i) == 2) THEN
+ irsv = ucat2resv(i)
+ IF (year >= dam_build_year(irsv)) THEN
+ is_built_resv(i) = .true.
+ IF (volresv(irsv) == spval) THEN
+ volresv(irsv) = floodplain_curve(i)%volume (wdsrf_ucat(i))
+ ELSE
+ wdsrf_ucat(i) = floodplain_curve(i)%depth (volresv(irsv))
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (.not. is_built_resv(i)) THEN
+ momen_riv(i) = wdsrf_ucat(i) * veloc_riv(i)
+ volwater = floodplain_curve(i)%volume (wdsrf_ucat(i))
+ ELSE
+ ! water in reservoirs is assumued to be stationary.
+ momen_riv(i) = 0
+ veloc_riv(i) = 0
+ volwater = volresv(ucat2resv(i))
+ ENDIF
+
+#ifdef CoLMDEBUG
+ totalvol_bef = totalvol_bef + volwater
+#endif
+
+ volwater = volwater + acc_rnof_uc(i)
+
+ IF (.not. is_built_resv(i)) THEN
+ wdsrf_ucat(i) = floodplain_curve(i)%depth (volwater)
+ IF (wdsrf_ucat(i) > RIVERMIN) THEN
+ veloc_riv(i) = momen_riv(i) / wdsrf_ucat(i)
+ ELSE
+ veloc_riv(i) = 0.
+ ENDIF
+ ELSE
+ volresv(ucat2resv(i)) = volwater
+ ENDIF
+
+ ENDDO
+
+
+ ntimestep = 0
+#ifdef CoLMDEBUG
+ totaldis = 0.
+#endif
+
+ dt_res(:) = 0._r8
+ DO i = 1, numucat
+ dt_res(irivsys(i)) = acctime_rnof
+ ENDDO
+
+ global_dt_remaining(1) = maxval(dt_res)
+#ifdef COLM_PARALLEL
+ IF (rivsys_by_multiple_procs) THEN
+ CALL mpi_allreduce (MPI_IN_PLACE, global_dt_remaining, 1, MPI_REAL8, MPI_MAX, p_comm_rivsys, p_err)
+ ENDIF
+#endif
+
+ DO WHILE (global_dt_remaining(1) > 0._r8)
+
+ ntimestep = ntimestep + 1
+
+ CALL compute_push_data (push_next2ucat, wdsrf_ucat, wdsrf_next, fillvalue = spval)
+ ! velocity in ocean or inland depression is assumed to be 0.
+ CALL compute_push_data (push_next2ucat, veloc_riv, veloc_next, fillvalue = 0.)
+
+ dt_all(:) = huge(1._r8)
+ WHERE (dt_res > 0._r8)
+ dt_all = min(dt_res, 60._r8)
+ END WHERE
+
+ DO i = 1, numucat
+
+ ucatfilter(i) = dt_res(irivsys(i)) > 0._r8
+
+ IF (.not. ucatfilter(i)) CYCLE
+
+ sum_hflux_riv(i) = 0.
+ sum_mflux_riv(i) = 0.
+ sum_zgrad_riv(i) = 0.
+
+ ! reservoir
+ IF (is_built_resv(i)) THEN
+ hflux_fc(i) = 0.
+ mflux_fc(i) = 0.
+ zgrad_dn(i) = 0.
+ CYCLE
+ ENDIF
+
+ IF ((ucat_next(i) > 0) .or. (ucat_next(i) == -9)) THEN
+
+ IF (ucat_next(i) > 0) THEN
+ ! both rivers are dry.
+ IF ((wdsrf_ucat(i) < RIVERMIN) .and. (wdsrf_next(i) < RIVERMIN)) THEN
+ hflux_fc(i) = 0
+ mflux_fc(i) = 0
+ zgrad_dn(i) = 0
+ CYCLE
+ ENDIF
+ ENDIF
+
+ ! reconstruction of height of water near interface
+ IF (ucat_next(i) > 0) THEN
+ bedelv_fc = max(topo_rivelv(i), bedelv_next(i))
+ height_up = max(0., wdsrf_ucat(i)+topo_rivelv(i)-bedelv_fc)
+ height_dn = max(0., wdsrf_next(i)+bedelv_next(i)-bedelv_fc)
+ ELSEIF (ucat_next(i) == -9) THEN ! for river mouth
+ bedelv_fc = topo_rivelv(i)
+ height_up = wdsrf_ucat (i)
+ ! sea level is assumed to be 0. and sea bed is assumed to be negative infinity.
+ height_dn = max(0., - bedelv_fc)
+ ENDIF
+
+ ! velocity at river downstream face (middle region in Riemann problem)
+ veloct_fc = 0.5 * (veloc_riv(i) + veloc_next(i)) &
+ + sqrt(grav * height_up) - sqrt(grav * height_dn)
+
+ ! height of water at downstream face (middle region in Riemann problem)
+ height_fc = 1/grav * (0.5*(sqrt(grav*height_up) + sqrt(grav*height_dn)) &
+ + 0.25 * (veloc_riv(i) - veloc_next(i))) ** 2
+
+ IF (height_up > 0) THEN
+ vwave_up = min(veloc_riv(i)-sqrt(grav*height_up), veloct_fc-sqrt(grav*height_fc))
+ ELSE
+ vwave_up = veloc_next(i) - 2.0 * sqrt(grav*height_dn)
+ ENDIF
+
+ IF (height_dn > 0) THEN
+ vwave_dn = max(veloc_next(i)+sqrt(grav*height_dn), veloct_fc+sqrt(grav*height_fc))
+ ELSE
+ vwave_dn = veloc_riv(i) + 2.0 * sqrt(grav*height_up)
+ ENDIF
+
+ hflux_up = veloc_riv(i) * height_up
+ hflux_dn = veloc_next(i) * height_dn
+ mflux_up = veloc_riv(i)**2 * height_up + 0.5*grav * height_up**2
+ mflux_dn = veloc_next(i)**2 * height_dn + 0.5*grav * height_dn**2
+
+ IF (vwave_up >= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_up
+ mflux_fc(i) = outletwth(i) * mflux_up
+ ELSEIF (vwave_dn <= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_dn
+ mflux_fc(i) = outletwth(i) * mflux_dn
+ ELSE
+ hflux_fc(i) = outletwth(i) * (vwave_dn*hflux_up - vwave_up*hflux_dn &
+ + vwave_up*vwave_dn*(height_dn-height_up)) / (vwave_dn-vwave_up)
+ mflux_fc(i) = outletwth(i) * (vwave_dn*mflux_up - vwave_up*mflux_dn &
+ + vwave_up*vwave_dn*(hflux_dn-hflux_up)) / (vwave_dn-vwave_up)
+ ENDIF
+
+ sum_zgrad_riv(i) = sum_zgrad_riv(i) + outletwth(i) * 0.5*grav * height_up**2
+
+ zgrad_dn(i) = outletwth(i) * 0.5*grav * height_dn**2
+
+ ELSEIF (ucat_next(i) == -99) THEN
+ ! downstream is not in model region.
+ ! assume: 1. downstream river bed is equal to this river bed.
+ ! 2. downstream water surface is equal to this river depth.
+ ! 3. downstream water velocity is equal to this velocity.
+
+ veloc_riv(i) = max(veloc_riv(i), 0.)
+
+ IF (wdsrf_ucat(i) > topo_rivhgt(i)) THEN
+
+ ! reconstruction of height of water near interface
+ height_up = wdsrf_ucat (i)
+ height_dn = topo_rivhgt(i)
+
+ veloct_fc = veloc_riv(i) + sqrt(grav * height_up) - sqrt(grav * height_dn)
+ height_fc = 1/grav * (0.5*(sqrt(grav*height_up) + sqrt(grav*height_dn))) ** 2
+
+ vwave_up = min(veloc_riv(i)-sqrt(grav*height_up), veloct_fc-sqrt(grav*height_fc))
+ vwave_dn = max(veloc_riv(i)+sqrt(grav*height_dn), veloct_fc+sqrt(grav*height_fc))
+
+ hflux_up = veloc_riv(i) * height_up
+ hflux_dn = veloc_riv(i) * height_dn
+ mflux_up = veloc_riv(i)**2 * height_up + 0.5*grav * height_up**2
+ mflux_dn = veloc_riv(i)**2 * height_dn + 0.5*grav * height_dn**2
+
+ IF (vwave_up >= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_up
+ mflux_fc(i) = outletwth(i) * mflux_up
+ ELSEIF (vwave_dn <= 0.) THEN
+ hflux_fc(i) = outletwth(i) * hflux_dn
+ mflux_fc(i) = outletwth(i) * mflux_dn
+ ELSE
+ hflux_fc(i) = outletwth(i) * (vwave_dn*hflux_up - vwave_up*hflux_dn &
+ + vwave_up*vwave_dn*(height_dn-height_up)) / (vwave_dn-vwave_up)
+ mflux_fc(i) = outletwth(i) * (vwave_dn*mflux_up - vwave_up*mflux_dn &
+ + vwave_up*vwave_dn*(hflux_dn-hflux_up)) / (vwave_dn-vwave_up)
+ ENDIF
+
+ sum_zgrad_riv(i) = sum_zgrad_riv(i) + outletwth(i) * 0.5*grav * height_up**2
+
+ ELSE
+ hflux_fc(i) = 0
+ mflux_fc(i) = 0
+ ENDIF
+
+ ELSEIF (ucat_next(i) == -10) THEN ! inland depression
+ hflux_fc(i) = 0
+ mflux_fc(i) = 0
+ ENDIF
+
+ sum_hflux_riv(i) = sum_hflux_riv(i) + hflux_fc(i)
+ sum_mflux_riv(i) = sum_mflux_riv(i) + mflux_fc(i)
+
+ ENDDO
+
+ CALL compute_push_data (push_ups2ucat, hflux_fc, hflux_sumups, fillvalue = 0., mode = 'sum')
+ CALL compute_push_data (push_ups2ucat, mflux_fc, mflux_sumups, fillvalue = 0., mode = 'sum')
+ CALL compute_push_data (push_ups2ucat, zgrad_dn, zgrad_sumups, fillvalue = 0., mode = 'sum')
+
+ IF (numucat > 0) THEN
+ WHERE (ucatfilter)
+ sum_hflux_riv = sum_hflux_riv - hflux_sumups
+ sum_mflux_riv = sum_mflux_riv - mflux_sumups
+ sum_zgrad_riv = sum_zgrad_riv - zgrad_sumups
+ END WHERE
+ ENDIF
+
+ ! reservoir operation.
+ IF (DEF_Reservoir_Method > 0) THEN
+
+ DO i = 1, numucat
+
+ IF ((.not. ucatfilter(i)) .or. (ucat_next(i) == -10)) CYCLE
+
+ hflux_resv(i) = 0.
+ mflux_resv(i) = 0.
+
+ IF (is_built_resv(i)) THEN
+
+ irsv = ucat2resv(i)
+ qresv_in(irsv) = - sum_hflux_riv(i)
+
+ IF (volresv(irsv) > 1.e-4 * volresv_total(irsv)) THEN
+ CALL reservoir_operation (DEF_Reservoir_Method, &
+ irsv, qresv_in(irsv), volresv(irsv), qresv_out(irsv))
+ ELSE
+ qresv_out (irsv) = 0.
+ ENDIF
+
+ hflux_fc(i) = qresv_out(irsv)
+ mflux_fc(i) = qresv_out(irsv) * sqrt(2*grav*wdsrf_ucat(i))
+
+ sum_hflux_riv(i) = sum_hflux_riv(i) + hflux_fc(i)
+ sum_mflux_riv(i) = sum_mflux_riv(i) + mflux_fc(i)
+
+ hflux_resv(i) = hflux_fc(i)
+ mflux_resv(i) = mflux_fc(i)
+ ENDIF
+
+ ENDDO
+
+ CALL compute_push_data (push_ups2ucat, hflux_resv, hflux_sumups, fillvalue = 0., mode = 'sum')
+ CALL compute_push_data (push_ups2ucat, mflux_resv, mflux_sumups, fillvalue = 0., mode = 'sum')
+
+ IF (numucat > 0) THEN
+ WHERE (ucatfilter)
+ sum_hflux_riv = sum_hflux_riv - hflux_sumups
+ sum_mflux_riv = sum_mflux_riv - mflux_sumups
+ END WHERE
+ ENDIF
+
+ ENDIF
+
+ DO i = 1, numucat
+
+ IF (.not. ucatfilter(i)) CYCLE
+
+ dt_this = dt_all(irivsys(i))
+
+ ! constraint 1: CFL condition (only for rivers)
+ IF (.not. is_built_resv(i)) THEN
+ IF ((veloc_riv(i) /= 0.) .or. (wdsrf_ucat(i) > 0.)) THEN
+ dt_this = min(dt_this, topo_rivlen(i)/(abs(veloc_riv(i))+sqrt(grav*wdsrf_ucat(i)))*0.8)
+ ENDIF
+ ENDIF
+
+ ! constraint 2: Avoid negative values of water
+ IF (sum_hflux_riv(i) > 0) THEN
+ IF (.not. is_built_resv(i)) THEN
+ ! for river or lake catchment
+ volwater = floodplain_curve(i)%volume (wdsrf_ucat(i))
+ ELSE
+ ! for reservoir
+ volwater = volresv(ucat2resv(i))
+ ENDIF
+
+ dt_this = min(dt_this, volwater / sum_hflux_riv(i))
+
+ ENDIF
+
+ ! constraint 3: Avoid change of flow direction (only for rivers)
+ ! IF (.not. is_built_resv(i)) THEN
+ ! IF ((abs(veloc_riv(i)) > 0.1) &
+ ! .and. (veloc_riv(i) * (sum_mflux_riv(i)-sum_zgrad_riv(i)) > 0)) THEN
+ ! dt_this = min(dt_this, &
+ ! abs(momen_riv(i) * topo_rivare(i) / (sum_mflux_riv(i)-sum_zgrad_riv(i))))
+ ! ENDIF
+ ! ENDIF
+
+ dt_all(irivsys(i)) = min(dt_this, dt_all(irivsys(i)))
+
+ ENDDO
+
+#ifdef COLM_PARALLEL
+ IF (rivsys_by_multiple_procs) THEN
+ CALL mpi_allreduce (MPI_IN_PLACE, dt_all, size(dt_all), MPI_REAL8, MPI_MIN, p_comm_rivsys, p_err)
+ ENDIF
+#endif
+
+ DO i = 1, numucat
+
+ IF (.not. ucatfilter(i)) CYCLE
+
+ IF (.not. is_built_resv(i)) THEN
+ volwater = floodplain_curve(i)%volume (wdsrf_ucat(i))
+ ELSE
+ volwater = volresv(ucat2resv(i))
+ ENDIF
+
+ volwater = volwater - sum_hflux_riv(i) * dt_all(irivsys(i))
+ volwater = max(volwater, 0.)
+
+ ! for inland depression, remove excess water (to be optimized)
+ IF (ucat_next(i) == -10) THEN
+ IF (volwater > topo_rivstomax(i)) THEN
+ hflux_fc(i) = (volwater - topo_rivstomax(i)) / dt_all(irivsys(i))
+ volwater = topo_rivstomax(i)
+ ENDIF
+ ENDIF
+
+ wdsrf_ucat(i) = floodplain_curve(i)%depth (volwater)
+
+ IF (is_built_resv(i)) THEN
+ volresv(ucat2resv(i)) = volwater
+ ENDIF
+
+ IF ((.not. is_built_resv(i)) .and. (wdsrf_ucat(i) >= RIVERMIN)) THEN
+ friction = grav * topo_rivman(i)**2 / wdsrf_ucat(i)**(7.0/3.0) * abs(momen_riv(i))
+ momen_riv(i) = (momen_riv(i) &
+ - (sum_mflux_riv(i) - sum_zgrad_riv(i)) / topo_rivare(i) * dt_all(irivsys(i))) &
+ / (1 + friction * dt_all(irivsys(i)))
+ veloc_riv(i) = momen_riv(i) / wdsrf_ucat(i)
+ ELSE
+ momen_riv(i) = 0
+ veloc_riv(i) = 0
+ ENDIF
+
+ ! inland depression river
+ IF ((.not. is_built_resv(i)) .and. (ucat_next(i) == -10)) THEN
+ momen_riv(i) = min(0., momen_riv(i))
+ veloc_riv(i) = min(0., veloc_riv(i))
+ ENDIF
+
+ veloc_riv(i) = min(veloc_riv(i), 20.)
+ veloc_riv(i) = max(veloc_riv(i), -20.)
+
+ ENDDO
+
+ DO i = 1, numucat
+ IF (ucatfilter(i)) THEN
+
+#ifdef CoLMDEBUG
+ IF (ucat_next(i) <= 0) THEN
+ totaldis = totaldis + hflux_fc(i)*dt_all(irivsys(i))
+ ENDIF
+#endif
+
+ IF (allocated(acctime_ucat) .and. allocated(a_wdsrf_ucat) .and. &
+ allocated(a_veloc_riv) .and. allocated(a_discharge) .and. &
+ allocated(a_floodarea)) THEN
+ acctime_ucat(i) = acctime_ucat(i) + dt_all(irivsys(i))
+
+ a_wdsrf_ucat(i) = a_wdsrf_ucat(i) + wdsrf_ucat(i) * dt_all(irivsys(i))
+ a_veloc_riv (i) = a_veloc_riv (i) + veloc_riv (i) * dt_all(irivsys(i))
+ a_discharge (i) = a_discharge (i) + hflux_fc (i) * dt_all(irivsys(i))
+
+ floodarea = floodplain_curve(i)%floodarea (wdsrf_ucat(i))
+ a_floodarea (i) = a_floodarea (i) + floodarea * dt_all(irivsys(i))
+
+ IF (is_built_resv(i) .and. allocated(acctime_resv) .and. &
+ allocated(a_volresv) .and. allocated(a_qresv_in) .and. &
+ allocated(a_qresv_out)) THEN
+ irsv = ucat2resv(i)
+ acctime_resv(irsv) = acctime_resv(irsv) + dt_all(irivsys(i))
+ a_volresv (irsv) = a_volresv (irsv) + volresv (irsv) * dt_all(irivsys(i))
+ a_qresv_in (irsv) = a_qresv_in (irsv) + qresv_in (irsv) * dt_all(irivsys(i))
+ a_qresv_out (irsv) = a_qresv_out(irsv) + qresv_out(irsv) * dt_all(irivsys(i))
+ ENDIF
+ ENDIF
+
+ ENDIF
+ ENDDO
+
+ WHERE (dt_res > 0._r8)
+ dt_res = max(0._r8, dt_res - dt_all)
+ END WHERE
+
+ global_dt_remaining(1) = maxval(dt_res)
+#ifdef COLM_PARALLEL
+ IF (rivsys_by_multiple_procs) THEN
+ CALL mpi_allreduce (MPI_IN_PLACE, global_dt_remaining, 1, MPI_REAL8, MPI_MAX, p_comm_rivsys, p_err)
+ ENDIF
+#endif
+
+#ifdef GridRiverLakeSediment
+ IF (DEF_USE_SEDIMENT) THEN
+ IF (numucat > 0) THEN
+ allocate(floodarea_sed(numucat))
+ DO i = 1, numucat
+ IF (ucatfilter(i)) THEN
+ floodarea_sed(i) = floodplain_curve(i)%floodarea(wdsrf_ucat(i))
+ ELSE
+ floodarea_sed(i) = 0._r8
+ ENDIF
+ ENDDO
+ ELSE
+ allocate(floodarea_sed(0))
+ ENDIF
+ CALL sediment_diag_accumulate(dt_all, irivsys, ucatfilter, &
+ veloc_riv, wdsrf_ucat, hflux_fc, floodarea_sed)
+ deallocate(floodarea_sed)
+ ENDIF
+#endif
+
+ ENDDO
+
+#ifdef CoLMDEBUG
+ totalvol_aft = 0.
+ DO i = 1, numucat
+ IF (.not. is_built_resv(i)) THEN
+ totalvol_aft = totalvol_aft + floodplain_curve(i)%volume (wdsrf_ucat(i))
+ ELSE
+ totalvol_aft = totalvol_aft + volresv(ucat2resv(i))
+ ENDIF
+ ENDDO
+#endif
+ ENDIF
+
+#ifdef CoLMDEBUG
+#ifdef COLM_PARALLEL
+ IF (.not. p_is_compute) ntimestep = 0
+ CALL mpi_allreduce (MPI_IN_PLACE, ntimestep, 1, MPI_INTEGER, MPI_MAX, p_comm_glb, p_err)
+
+ IF (.not. p_is_compute) totalvol_bef = 0.
+ IF (.not. p_is_compute) totalvol_aft = 0.
+ IF (.not. p_is_compute) totalrnof = 0.
+ IF (.not. p_is_compute) totaldis = 0.
+
+ CALL mpi_allreduce (MPI_IN_PLACE, totalvol_bef, 1, MPI_REAL8, MPI_SUM, p_comm_glb, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, totalvol_aft, 1, MPI_REAL8, MPI_SUM, p_comm_glb, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, totalrnof, 1, MPI_REAL8, MPI_SUM, p_comm_glb, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, totaldis, 1, MPI_REAL8, MPI_SUM, p_comm_glb, p_err)
+#endif
+ IF (p_is_root) THEN
+ write(*,'(/,A)') 'Checking River Routing Flow ...'
+ write(*,'(A,F12.5,A)') 'River Lake Flow minimum average timestep: ', acctime_rnof/ntimestep, ' seconds'
+ write(*,'(A,ES8.1,A)') 'Total water before : ', totalvol_bef, ' m^3'
+ write(*,'(A,ES8.1,A)') 'Total runoff : ', totalrnof, ' m^3'
+ write(*,'(A,ES8.1,A)') 'Total discharge : ', totaldis, ' m^3'
+ write(*,'(A,ES8.1,A)') 'Total water change : ', totalvol_aft-totalvol_bef, ' m^3'
+ write(*,'(A,ES8.1,A)') 'Total water balance : ', totalvol_aft-totalvol_bef-totalrnof+totaldis, ' m^3'
+ ENDIF
+#endif
+
+#ifdef GridRiverLakeSediment
+ IF (DEF_USE_SEDIMENT .and. p_is_compute) THEN
+ ! All ranks must participate (MPI point-to-point inside push_data).
+ ! fldfrc is now computed inside grid_sediment_calc from per-routing-period
+ ! accumulators (sed_acc_floodarea), not from history-period averages.
+ CALL grid_sediment_calc(acctime_rnof)
+ ENDIF
+#endif
+
+ acctime_rnof = 0.
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ acc_rnof_uc = 0.
+ ENDIF
+ ENDIF
+
+ IF (allocated(is_built_resv)) deallocate(is_built_resv)
+ IF (allocated(wdsrf_next )) deallocate(wdsrf_next )
+ IF (allocated(veloc_next )) deallocate(veloc_next )
+ IF (allocated(hflux_fc )) deallocate(hflux_fc )
+ IF (allocated(mflux_fc )) deallocate(mflux_fc )
+ IF (allocated(zgrad_dn )) deallocate(zgrad_dn )
+ IF (allocated(hflux_resv )) deallocate(hflux_resv )
+ IF (allocated(mflux_resv )) deallocate(mflux_resv )
+ IF (allocated(hflux_sumups )) deallocate(hflux_sumups )
+ IF (allocated(mflux_sumups )) deallocate(mflux_sumups )
+ IF (allocated(zgrad_sumups )) deallocate(zgrad_sumups )
+ IF (allocated(sum_hflux_riv)) deallocate(sum_hflux_riv)
+ IF (allocated(sum_mflux_riv)) deallocate(sum_mflux_riv)
+ IF (allocated(sum_zgrad_riv)) deallocate(sum_zgrad_riv)
+ IF (allocated(ucatfilter )) deallocate(ucatfilter )
+ IF (allocated(dt_res )) deallocate(dt_res )
+ IF (allocated(dt_all )) deallocate(dt_all )
+
+ END SUBROUTINE grid_riverlake_flow
+
+ ! ---------
+ SUBROUTINE grid_riverlake_flow_final ()
+
+ CALL riverlake_network_final ()
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ CALL reservoir_final ()
+ ENDIF
+
+#ifdef GridRiverLakeSediment
+ CALL grid_sediment_final()
+#endif
+
+ IF (allocated(acc_rnof_uc)) deallocate(acc_rnof_uc)
+ IF (allocated(filter_rnof)) deallocate(filter_rnof)
+
+ END SUBROUTINE grid_riverlake_flow_final
+
+END MODULE MOD_Grid_RiverLakeFlow
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeHist.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeHist.F90
new file mode 100644
index 0000000000..033dec6575
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeHist.F90
@@ -0,0 +1,756 @@
+#include
+
+#ifdef GridRiverLakeFlow
+MODULE MOD_Grid_RiverLakeHist
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Write out model results in lateral hydrological processes to history files.
+!
+! Created by Shupeng Zhang, May 2023
+!--------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_DataType
+#ifdef GridRiverLakeSediment
+ USE MOD_Grid_RiverLakeSediment, only: nsed, sed_hist_acctime, &
+ a_sedcon, a_sedout, a_bedout, a_sedinp, a_netflw, a_layer, a_shearvel
+#endif
+
+ ! -- ACC Fluxes --
+ real(r8), allocatable :: acctime_ucat (:)
+
+ real(r8), allocatable :: a_wdsrf_ucat (:)
+ real(r8), allocatable :: a_veloc_riv (:)
+ real(r8), allocatable :: a_discharge (:)
+ real(r8), allocatable :: a_floodarea (:) ! flooded area [m^2]
+
+ real(r8), allocatable :: a_wdsrf_ucat_pch (:)
+ real(r8), allocatable :: a_veloc_riv_pch (:)
+ real(r8), allocatable :: a_discharge_pch (:)
+ real(r8), allocatable :: a_dis_rmth_pch (:)
+ real(r8), allocatable :: a_floodfrc_pch (:) ! flooded area [m^2]
+
+ ! for reservoirs
+ real(r8), allocatable :: acctime_resv (:)
+
+ real(r8), allocatable :: a_volresv (:) ! reservoir water volume [m^3]
+ real(r8), allocatable :: a_qresv_in (:) ! inflow to reservoir [m^3/s]
+ real(r8), allocatable :: a_qresv_out (:) ! outflow from reservoir [m^3/s]
+
+ ! grid information
+ real(r8), allocatable :: lon_ucat (:)
+ real(r8), allocatable :: lat_ucat (:)
+
+ ! auxiliary data
+ type(block_data_real8_2d) :: sumarea_ucat ! 1) area covered by unit catchments
+ logical, allocatable :: filter_ucat (:)
+ real(r8), allocatable :: sum_grid_area (:) ! sum area of patches inside one grid
+
+ logical, allocatable :: filter_rivmth (:) ! 2) area covered by river mouths
+ real(r8), allocatable :: sum_rmth_area (:)
+
+ logical, allocatable :: filter_inpm (:) ! 3) area covered by input matrix
+ type(block_data_real8_2d) :: sumarea_inpm
+
+ type(block_data_real8_2d) :: allups_mask_grid ! 4) mask of unit catchments with all
+ real(r8), allocatable :: allups_mask_pch (:) ! upstreams in simulation region
+
+ ! -- PUBLIC SUBROUTINEs --
+ PUBLIC :: hist_grid_riverlake_init
+ PUBLIC :: hist_grid_riverlake_out
+ PUBLIC :: hist_grid_riverlake_final
+
+!--------------------------------------------------------------------------
+CONTAINS
+
+ !---------------------------------------
+ SUBROUTINE hist_grid_riverlake_init (histform)
+
+ USE MOD_Block
+ USE MOD_ComputePushData
+ USE MOD_HistGridded
+ USE MOD_Grid_RiverLakeNetwork
+ USE MOD_Grid_Reservoir, only: numresv
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_Forcing, only: forcmask_pch
+ USE MOD_Vars_TimeInvariants, only: patchtype, patchmask
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: histform
+
+ ! Local Variables
+ logical, allocatable :: filter_basic(:)
+ real(r8), allocatable :: vec_ucat(:), vec_grid(:), vec_inpm(:), vec_patch(:)
+ integer :: ilon, iblkme, iblk, jblk
+
+
+ ! ----- allocate memory for accumulative variables -----
+ IF (p_is_compute) THEN
+
+ allocate (acctime_ucat (numucat))
+ allocate (a_wdsrf_ucat (numucat))
+ allocate (a_veloc_riv (numucat))
+ allocate (a_discharge (numucat))
+ allocate (a_floodarea (numucat))
+
+ allocate (a_wdsrf_ucat_pch (numpatch))
+ allocate (a_veloc_riv_pch (numpatch))
+ allocate (a_discharge_pch (numpatch))
+ allocate (a_dis_rmth_pch (numpatch))
+ allocate (a_floodfrc_pch (numpatch))
+
+ allocate (acctime_resv (numresv))
+ allocate (a_volresv (numresv))
+ allocate (a_qresv_in (numresv))
+ allocate (a_qresv_out (numresv))
+
+ ENDIF
+
+ CALL flush_acc_fluxes_riverlake ()
+
+ ! ----- get longitude and latitude -----
+ IF (p_is_root) THEN
+ allocate (lon_ucat (griducat%nlon))
+ allocate (lat_ucat (griducat%nlat))
+
+ lat_ucat = (griducat%lat_s + griducat%lat_n) * 0.5
+
+ DO ilon = 1, griducat%nlon
+ IF (griducat%lon_w(ilon) > griducat%lon_e(ilon)) THEN
+ lon_ucat(ilon) = (griducat%lon_w(ilon) + griducat%lon_e(ilon)+360.) * 0.5
+ CALL normalize_longitude (lon_ucat(ilon))
+ ELSE
+ lon_ucat(ilon) = (griducat%lon_w(ilon) + griducat%lon_e(ilon)) * 0.5
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! ----- for auxiliary data -----
+ IF (p_is_compute) THEN
+ allocate (vec_ucat (numucat ))
+ allocate (vec_grid (numinpm ))
+ allocate (vec_inpm (numinpm ))
+ allocate (vec_patch (numpatch))
+
+ ! Patches excluding (type >= 99), virtual patches and thos forcing missed
+ allocate (filter_basic (numpatch))
+ IF (numpatch > 0) THEN
+ filter_basic = patchtype < 99
+ filter_basic = filter_basic .and. patchmask
+ IF (DEF_forcing%has_missing_value) THEN
+ filter_basic = filter_basic .and. forcmask_pch
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! ----- 1) area and filter covered by unit catchments -----
+ IF (p_is_compute) THEN
+
+ IF (numucat > 0) vec_ucat = 1.
+
+ CALL compute_push_data (push_ucat2grid, vec_ucat, vec_grid, fillvalue = spval)
+ CALL compute_remap_data_grid2pset ( &
+ remap_patch2inpm, vec_grid, vec_patch, fillvalue = spval, mode = 'average')
+
+ allocate (filter_ucat (numpatch))
+ IF (numpatch > 0) THEN
+ filter_ucat = filter_basic .and. (vec_patch /= spval)
+
+ WHERE (filter_ucat)
+ vec_patch = 1
+ ELSE WHERE
+ vec_patch = spval
+ END WHERE
+ ENDIF
+
+ allocate (sum_grid_area (numinpm))
+ CALL compute_remap_data_pset2grid (remap_patch2inpm, vec_patch, vec_grid, &
+ fillvalue = spval, filter = filter_ucat)
+ CALL compute_push_data (allreduce_inpm, vec_grid, sum_grid_area, fillvalue = spval)
+ ENDIF
+
+#ifndef MPAS_EMBEDDED_COLM
+ IF (trim(histform) == 'Gridded') THEN
+ IF (p_is_active) CALL allocate_block_data (ghist, sumarea_ucat)
+ CALL mp2g_hist%get_sumarea (sumarea_ucat, filter_ucat)
+ ENDIF
+#endif
+
+ ! ----- 2) area and filter covered by river mouth -----
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ WHERE (ucat_next == -9)
+ vec_ucat = 1.
+ ELSE WHERE
+ vec_ucat = spval
+ END WHERE
+ ENDIF
+
+ CALL compute_push_data (push_ucat2grid, vec_ucat, vec_grid, fillvalue = spval)
+ CALL compute_remap_data_grid2pset (remap_patch2inpm, vec_grid, vec_patch, &
+ fillvalue = spval, mode = 'average')
+
+ allocate (filter_rivmth (numpatch))
+ IF (numpatch > 0) THEN
+ filter_rivmth = filter_ucat .and. (vec_patch /= spval)
+
+ WHERE (filter_rivmth)
+ vec_patch = 1
+ ELSE WHERE
+ vec_patch = spval
+ END WHERE
+ ENDIF
+
+ allocate (sum_rmth_area (numinpm))
+
+ CALL compute_remap_data_pset2grid (remap_patch2inpm, vec_patch, vec_grid, &
+ fillvalue = spval, filter = filter_rivmth)
+ CALL compute_push_data (allreduce_inpm, vec_grid, sum_rmth_area, fillvalue = spval)
+ ENDIF
+
+ ! ----- 3) area covered by input matrix -----
+ IF (p_is_compute) THEN
+ IF (numucat > 0) vec_ucat = 1.
+ CALL compute_push_data (push_ucat2inpm, vec_ucat, vec_inpm, &
+ fillvalue = spval, mode = 'average')
+ CALL compute_remap_data_grid2pset (remap_patch2inpm, vec_inpm, vec_patch, &
+ fillvalue = spval, mode = 'average')
+
+ allocate (filter_inpm (numpatch))
+ IF (numpatch > 0) THEN
+ filter_inpm = filter_basic .and. (vec_patch /= spval)
+ ENDIF
+ ENDIF
+
+#ifndef MPAS_EMBEDDED_COLM
+ IF (trim(histform) == 'Gridded') THEN
+ IF (p_is_active) CALL allocate_block_data (ghist, sumarea_inpm)
+ CALL mp2g_hist%get_sumarea (sumarea_inpm, filter_inpm)
+ ENDIF
+#endif
+
+ ! ----- 4) mask of unit catchments with all upstreams in simulation region -----
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate (allups_mask_pch (numpatch))
+ ENDIF
+ ENDIF
+
+ IF (p_is_compute) THEN
+ CALL compute_push_data (push_ucat2grid, allups_mask_ucat, vec_grid, fillvalue = spval)
+ CALL compute_remap_data_grid2pset ( &
+ remap_patch2inpm, vec_grid, allups_mask_pch, fillvalue = spval, mode = 'average')
+ ENDIF
+
+#ifndef MPAS_EMBEDDED_COLM
+ IF (trim(histform) == 'Gridded') THEN
+
+ IF (p_is_active) CALL allocate_block_data (ghist, allups_mask_grid)
+
+ CALL mp2g_hist%pset2grid (allups_mask_pch, allups_mask_grid, spv = spval, msk = filter_ucat)
+
+ IF (p_is_active) THEN
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ WHERE (sumarea_ucat%blk(iblk,jblk)%val > 0.)
+ allups_mask_grid%blk(iblk,jblk)%val = &
+ allups_mask_grid%blk(iblk,jblk)%val / sumarea_ucat%blk(iblk,jblk)%val
+ ELSE WHERE
+ allups_mask_grid%blk(iblk,jblk)%val = spval
+ END WHERE
+ ENDDO
+ ENDIF
+
+ ENDIF
+#endif
+
+ IF (allocated (vec_ucat )) deallocate (vec_ucat )
+ IF (allocated (vec_grid )) deallocate (vec_grid )
+ IF (allocated (vec_inpm )) deallocate (vec_inpm )
+ IF (allocated (vec_patch )) deallocate (vec_patch )
+ IF (allocated (filter_basic)) deallocate (filter_basic)
+
+ END SUBROUTINE hist_grid_riverlake_init
+
+ !---------------------------------------
+ SUBROUTINE hist_grid_riverlake_out (file_hist, histform, idate, itime_in_file, is_first_in_file)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_ComputePushData
+ USE MOD_Grid_RiverLakeNetwork
+ USE MOD_Grid_Reservoir
+ USE MOD_Vector_ReadWrite
+ USE MOD_HistGridded
+#ifdef UNSTRUCTURED
+ USE MOD_HistVector
+#endif
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: histform
+ integer, intent(in) :: idate(3)
+ integer, intent(in) :: itime_in_file
+ logical, intent(in) :: is_first_in_file
+
+ ! Local variables
+ character(len=256) :: file_hist_ucat
+ logical :: fexists
+ integer :: itime_in_file_ucat, i
+
+ real(r8), allocatable :: acc_vec_grid (:)
+ real(r8), allocatable :: a_floodfrc_ucat (:) ! flooded area fraction
+ real(r8), allocatable :: a_floodfrc_inpm (:) ! flooded area fraction
+
+
+ IF (p_is_root) THEN
+ i = len_trim (file_hist)
+ DO WHILE (file_hist(i:i) /= '_')
+ i = i - 1
+ ENDDO
+ file_hist_ucat = file_hist(1:i) // 'unitcat_' // file_hist(i+1:)
+
+ inquire (file=file_hist_ucat, exist=fexists)
+ IF (.not. fexists) THEN
+
+ CALL ncio_create_file (trim(file_hist_ucat))
+
+ CALL ncio_define_dimension (file_hist_ucat, 'time', 0)
+ CALL ncio_define_dimension (file_hist_ucat, 'lat_ucat', griducat%nlat)
+ CALL ncio_define_dimension (file_hist_ucat, 'lon_ucat', griducat%nlon)
+
+ CALL ncio_write_serial (file_hist_ucat, 'lat_ucat', lat_ucat, 'lat_ucat')
+ CALL ncio_write_serial (file_hist_ucat, 'lon_ucat', lon_ucat, 'lon_ucat')
+ ENDIF
+
+ CALL ncio_write_time (file_hist_ucat, 'time', idate, itime_in_file_ucat, DEF_HIST_FREQ)
+
+ ENDIF
+
+ IF (is_first_in_file) THEN
+ IF (trim(histform) == 'Gridded') THEN
+ CALL hist_write_var_real8_2d ( &
+ file_hist, 'mask_complete_upstream_regird', ghist, -1, allups_mask_grid, compress = 1, &
+ longname = 'Mask of grids with all upstream located in simulation region', units = '100%')
+#ifdef UNSTRUCTURED
+ ELSE
+ CALL aggregate_to_vector_and_write_2d ( &
+ allups_mask_pch, file_hist, 'mask_complete_upstream_regird', -1, filter_ucat, &
+ longname = 'Mask of grids with all upstream located in simulation region', units = '100%')
+#endif
+ ENDIF
+
+ CALL vector_gather_map2grid_and_write ( &
+ allups_mask_ucat, numucat, totalnumucat, ucat_data_address, griducat%nlon, x_ucat, &
+ griducat%nlat, y_ucat, file_hist_ucat, 'mask_complete_upstream', 'lon_ucat', 'lat_ucat', &
+ longname = 'Mask of grids with all upstream located in simulation region', units = '100%')
+ ENDIF
+
+ IF (p_is_compute) THEN
+ allocate (acc_vec_grid (numinpm ))
+ ENDIF
+
+ IF (DEF_hist_vars%riv_height) THEN
+ IF (p_is_compute) THEN
+ IF (numucat > 0) a_wdsrf_ucat = a_wdsrf_ucat / acctime_ucat
+ CALL compute_push_data (push_ucat2grid, a_wdsrf_ucat, acc_vec_grid, fillvalue = spval)
+ CALL compute_remap_data_grid2pset ( remap_patch2inpm, acc_vec_grid, a_wdsrf_ucat_pch, &
+ fillvalue = spval, mode = 'average')
+ ENDIF
+
+ CALL vector_gather_map2grid_and_write ( a_wdsrf_ucat, numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_wdpth_ucat', 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'deepest water depth in river and flood plain', 'm')
+ ENDIF
+
+ IF (DEF_hist_vars%riv_veloct) THEN
+ IF (p_is_compute) THEN
+ IF (numucat > 0) a_veloc_riv = a_veloc_riv / acctime_ucat
+ CALL compute_push_data (push_ucat2grid, a_veloc_riv, acc_vec_grid, fillvalue = spval)
+ CALL compute_remap_data_grid2pset (remap_patch2inpm, acc_vec_grid, a_veloc_riv_pch, &
+ fillvalue = spval, mode = 'average')
+ ENDIF
+
+ CALL vector_gather_map2grid_and_write ( a_veloc_riv, numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_veloc_riv', 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'water velocity in river', 'm/s')
+ ENDIF
+
+ IF (DEF_hist_vars%discharge) THEN
+ IF (p_is_compute) THEN
+ IF (numucat > 0) a_discharge = a_discharge / acctime_ucat
+ CALL compute_push_data (push_ucat2grid, a_discharge, acc_vec_grid, fillvalue = spval)
+
+ IF (numinpm > 0) THEN
+ WHERE ((sum_grid_area /= spval) .and. (acc_vec_grid /= spval))
+ acc_vec_grid = acc_vec_grid / sum_grid_area
+ ELSE WHERE
+ acc_vec_grid = spval
+ END WHERE
+ ENDIF
+
+ CALL compute_remap_data_grid2pset (remap_patch2inpm, acc_vec_grid, a_discharge_pch, &
+ fillvalue = spval, mode = 'sum')
+ ENDIF
+
+ CALL vector_gather_map2grid_and_write ( a_discharge, numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_discharge', 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'discharge in river and flood plain', 'm^3/s')
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ WHERE (ucat_next /= -9) a_discharge = spval
+ ENDIF
+ CALL compute_push_data (push_ucat2grid, a_discharge, acc_vec_grid, fillvalue = spval)
+
+ IF (numinpm > 0) THEN
+ WHERE ((sum_rmth_area /= spval) .and. (acc_vec_grid /= spval))
+ acc_vec_grid = acc_vec_grid / sum_rmth_area
+ ELSE WHERE
+ acc_vec_grid = spval
+ END WHERE
+ ENDIF
+
+ CALL compute_remap_data_grid2pset (remap_patch2inpm, acc_vec_grid, a_dis_rmth_pch, &
+ fillvalue = spval, mode = 'sum')
+ ENDIF
+
+ CALL vector_gather_map2grid_and_write ( a_discharge, numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_discharge_rivermouth', 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'river mouth discharge into ocean', 'm^3/s')
+ ENDIF
+
+ IF (DEF_hist_vars%floodfrc) THEN
+
+ IF (p_is_compute) THEN
+
+ IF (numucat > 0) a_floodarea = a_floodarea / acctime_ucat
+
+ allocate (a_floodfrc_ucat (numucat))
+ IF (numucat > 0) THEN
+ WHERE (topo_area > 0)
+ a_floodfrc_ucat = a_floodarea / topo_area
+ ELSE WHERE
+ a_floodfrc_ucat = spval
+ END WHERE
+ ENDIF
+
+ allocate (a_floodfrc_inpm (numinpm))
+
+ CALL compute_push_data (push_ucat2inpm, a_floodfrc_ucat, a_floodfrc_inpm, &
+ fillvalue = spval, mode = 'average')
+
+ CALL compute_remap_data_grid2pset (remap_patch2inpm, a_floodfrc_inpm, a_floodfrc_pch, &
+ fillvalue = spval, mode = 'average')
+ ENDIF
+
+ ENDIF
+
+
+ IF (allocated (a_floodfrc_ucat)) deallocate (a_floodfrc_ucat)
+ IF (allocated (a_floodfrc_inpm)) deallocate (a_floodfrc_inpm)
+ IF (allocated (acc_vec_grid )) deallocate (acc_vec_grid )
+
+#ifdef GridRiverLakeSediment
+ CALL write_sediment_history (file_hist_ucat, itime_in_file_ucat)
+#endif
+
+ ! ----- reservoir variables -----
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (totalnumresv > 0) THEN
+
+ IF (p_is_root) THEN
+ IF (.not. fexists) THEN
+ CALL ncio_define_dimension(file_hist_ucat, 'reservoir', totalnumresv)
+ CALL ncio_write_serial (file_hist_ucat, 'resv_GRAND_ID' , dam_GRAND_ID, 'reservoir')
+ CALL ncio_put_attr (file_hist_ucat, 'resv_GRAND_ID', 'long_name', 'reservoir GRAND ID')
+ ENDIF
+ ENDIF
+
+ IF (DEF_hist_vars%volresv) THEN
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ WHERE (acctime_resv > 0)
+ a_volresv = a_volresv / acctime_resv
+ ELSEWHERE
+ a_volresv = spval
+ END WHERE
+ ENDIF
+ ENDIF
+
+ CALL vector_gather_and_write ( a_volresv, numresv, totalnumresv, resv_data_address, &
+ file_hist_ucat, 'volresv', 'reservoir', itime_in_file_ucat, 'reservoir water volume', 'm^3')
+ ENDIF
+
+ IF (DEF_hist_vars%qresv_in) THEN
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ WHERE (acctime_resv > 0)
+ a_qresv_in = a_qresv_in / acctime_resv
+ ELSEWHERE
+ a_qresv_in = spval
+ END WHERE
+ ENDIF
+ ENDIF
+
+ CALL vector_gather_and_write ( a_qresv_in, numresv, totalnumresv, resv_data_address, &
+ file_hist_ucat, 'qresv_in', 'reservoir', itime_in_file_ucat, 'reservoir inflow', 'm^3/s')
+ ENDIF
+
+ IF (DEF_hist_vars%qresv_out) THEN
+ IF (p_is_compute) THEN
+ IF (numresv > 0) THEN
+ WHERE (acctime_resv > 0)
+ a_qresv_out = a_qresv_out / acctime_resv
+ ELSEWHERE
+ a_qresv_out = spval
+ END WHERE
+ ENDIF
+ ENDIF
+
+ CALL vector_gather_and_write ( a_qresv_out, numresv, totalnumresv, resv_data_address, &
+ file_hist_ucat, 'qresv_out', 'reservoir', itime_in_file_ucat, 'reservoir outflow', 'm^3/s')
+ ENDIF
+
+ ENDIF
+ ENDIF
+
+ CALL flush_acc_fluxes_riverlake ()
+
+ END SUBROUTINE hist_grid_riverlake_out
+
+ !-----------------------
+ SUBROUTINE flush_acc_fluxes_riverlake ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Grid_RiverLakeNetwork, only: numucat
+ USE MOD_Grid_Reservoir, only: numresv
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numucat > 0) THEN
+ acctime_ucat (:) = 0.
+ a_wdsrf_ucat (:) = 0.
+ a_veloc_riv (:) = 0.
+ a_discharge (:) = 0.
+ a_floodarea (:) = 0.
+ ENDIF
+
+ IF (numresv > 0) THEN
+ acctime_resv (:) = 0.
+ a_volresv (:) = 0.
+ a_qresv_in (:) = 0.
+ a_qresv_out (:) = 0.
+ ENDIF
+
+#ifdef GridRiverLakeSediment
+ IF (DEF_USE_SEDIMENT .and. allocated(a_sedcon)) THEN
+ a_sedcon = 0.
+ a_sedout = 0.
+ a_bedout = 0.
+ a_sedinp = 0.
+ a_netflw = 0.
+ a_layer = 0.
+ a_shearvel = 0.
+ sed_hist_acctime = 0.
+ ENDIF
+#endif
+
+ ENDIF
+
+ END SUBROUTINE flush_acc_fluxes_riverlake
+
+ !---------------------------------------
+ SUBROUTINE hist_grid_riverlake_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(acctime_ucat )) deallocate (acctime_ucat )
+ IF (allocated(a_wdsrf_ucat )) deallocate (a_wdsrf_ucat )
+ IF (allocated(a_veloc_riv )) deallocate (a_veloc_riv )
+ IF (allocated(a_discharge )) deallocate (a_discharge )
+ IF (allocated(a_floodarea )) deallocate (a_floodarea )
+
+ IF (allocated(a_wdsrf_ucat_pch)) deallocate (a_wdsrf_ucat_pch)
+ IF (allocated(a_veloc_riv_pch )) deallocate (a_veloc_riv_pch )
+ IF (allocated(a_discharge_pch )) deallocate (a_discharge_pch )
+ IF (allocated(a_dis_rmth_pch )) deallocate (a_dis_rmth_pch )
+ IF (allocated(a_floodfrc_pch )) deallocate (a_floodfrc_pch )
+
+ IF (allocated(acctime_resv )) deallocate (acctime_resv )
+ IF (allocated(a_volresv )) deallocate (a_volresv )
+ IF (allocated(a_qresv_in )) deallocate (a_qresv_in )
+ IF (allocated(a_qresv_out )) deallocate (a_qresv_out )
+
+ IF (allocated(lon_ucat )) deallocate (lon_ucat )
+ IF (allocated(lat_ucat )) deallocate (lat_ucat )
+
+ IF (allocated(filter_ucat )) deallocate (filter_ucat )
+ IF (allocated(sum_grid_area )) deallocate (sum_grid_area )
+ IF (allocated(filter_rivmth )) deallocate (filter_rivmth )
+ IF (allocated(sum_rmth_area )) deallocate (sum_rmth_area )
+ IF (allocated(filter_inpm )) deallocate (filter_inpm )
+
+ IF (allocated(allups_mask_pch )) deallocate (allups_mask_pch )
+
+ END SUBROUTINE hist_grid_riverlake_final
+
+#ifdef GridRiverLakeSediment
+ !---------------------------------------
+ SUBROUTINE write_sediment_history (file_hist_ucat, itime_in_file_ucat)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Grid_RiverLakeNetwork, only: numucat, totalnumucat, ucat_data_address, &
+ x_ucat, y_ucat, griducat
+ USE MOD_Vector_ReadWrite
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_hist_ucat
+ integer, intent(in) :: itime_in_file_ucat
+
+ real(r8), allocatable :: a_sedcon_avg(:,:)
+ real(r8), allocatable :: a_sedout_avg(:,:)
+ real(r8), allocatable :: a_bedout_avg(:,:)
+ real(r8), allocatable :: a_sedinp_avg(:,:)
+ real(r8), allocatable :: a_netflw_avg(:,:)
+ real(r8), allocatable :: a_layer_avg(:,:)
+ real(r8), allocatable :: a_shearvel_avg(:)
+ integer :: ised
+ character(len=16) :: cised
+
+ IF (.not. DEF_USE_SEDIMENT) RETURN
+
+ ! Allocate on ALL processes (zero-size on non-ranks) to avoid
+ ! passing unallocated arrays to vector_gather_map2grid_and_write
+ IF (p_is_compute .and. numucat > 0) THEN
+ allocate (a_sedcon_avg (nsed, numucat))
+ allocate (a_sedout_avg (nsed, numucat))
+ allocate (a_bedout_avg (nsed, numucat))
+ allocate (a_sedinp_avg (nsed, numucat))
+ allocate (a_netflw_avg (nsed, numucat))
+ allocate (a_layer_avg (nsed, numucat))
+ allocate (a_shearvel_avg(numucat))
+
+ IF (sed_hist_acctime > 0._r8) THEN
+ a_shearvel_avg = a_shearvel / sed_hist_acctime
+ DO ised = 1, nsed
+ a_sedcon_avg(ised,:) = a_sedcon(ised,:) / sed_hist_acctime
+ a_sedout_avg(ised,:) = a_sedout(ised,:) / sed_hist_acctime
+ a_bedout_avg(ised,:) = a_bedout(ised,:) / sed_hist_acctime
+ a_sedinp_avg(ised,:) = a_sedinp(ised,:) / sed_hist_acctime
+ a_netflw_avg(ised,:) = a_netflw(ised,:) / sed_hist_acctime
+ a_layer_avg(ised,:) = a_layer(ised,:) / sed_hist_acctime
+ ENDDO
+ ELSE
+ a_shearvel_avg = 0.
+ a_sedcon_avg = 0.
+ a_sedout_avg = 0.
+ a_bedout_avg = 0.
+ a_sedinp_avg = 0.
+ a_netflw_avg = 0.
+ a_layer_avg = 0.
+ ENDIF
+ ELSE
+ ! Allocate with nsed in first dim so a_xxx_avg(ised,:) is a valid zero-length slice
+ allocate (a_sedcon_avg (nsed, 0))
+ allocate (a_sedout_avg (nsed, 0))
+ allocate (a_bedout_avg (nsed, 0))
+ allocate (a_sedinp_avg (nsed, 0))
+ allocate (a_netflw_avg (nsed, 0))
+ allocate (a_layer_avg (nsed, 0))
+ allocate (a_shearvel_avg(0))
+ ENDIF
+
+ IF (DEF_hist_vars%sedcon) THEN
+ DO ised = 1, nsed
+ WRITE(cised, '(I0)') ised
+ CALL vector_gather_map2grid_and_write ( a_sedcon_avg(ised,:), numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_sedcon_' // trim(cised), 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'suspended sediment concentration, size class ' // trim(cised), 'm^3/m^3')
+ ENDDO
+ ENDIF
+
+ IF (DEF_hist_vars%sedout) THEN
+ DO ised = 1, nsed
+ WRITE(cised, '(I0)') ised
+ CALL vector_gather_map2grid_and_write ( a_sedout_avg(ised,:), numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_sedout_' // trim(cised), 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'suspended sediment flux, size class ' // trim(cised), 'm^3/s')
+ ENDDO
+ ENDIF
+
+ IF (DEF_hist_vars%bedout) THEN
+ DO ised = 1, nsed
+ WRITE(cised, '(I0)') ised
+ CALL vector_gather_map2grid_and_write ( a_bedout_avg(ised,:), numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_bedout_' // trim(cised), 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'bedload flux, size class ' // trim(cised), 'm^3/s')
+ ENDDO
+ ENDIF
+
+ IF (DEF_hist_vars%sedinp) THEN
+ DO ised = 1, nsed
+ WRITE(cised, '(I0)') ised
+ CALL vector_gather_map2grid_and_write ( a_sedinp_avg(ised,:), numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_sedinp_' // trim(cised), 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'sediment erosion input, size class ' // trim(cised), 'm^3/s')
+ ENDDO
+ ENDIF
+
+ IF (DEF_hist_vars%netflw) THEN
+ DO ised = 1, nsed
+ WRITE(cised, '(I0)') ised
+ CALL vector_gather_map2grid_and_write ( a_netflw_avg(ised,:), numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_netflw_' // trim(cised), 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'net bed-water exchange flux (incl. shallow deposit), size class ' // trim(cised), 'm^3/s')
+ ENDDO
+ ENDIF
+
+ IF (DEF_hist_vars%sedlayer) THEN
+ DO ised = 1, nsed
+ WRITE(cised, '(I0)') ised
+ CALL vector_gather_map2grid_and_write ( a_layer_avg(ised,:), numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_layer_' // trim(cised), 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'active layer storage, size class ' // trim(cised), 'm^3')
+ ENDDO
+ ENDIF
+
+ IF (DEF_hist_vars%shearvel) THEN
+ CALL vector_gather_map2grid_and_write ( a_shearvel_avg, numucat, &
+ totalnumucat, ucat_data_address, griducat%nlon, x_ucat, griducat%nlat, y_ucat, &
+ file_hist_ucat, 'f_shearvel', 'lon_ucat', 'lat_ucat', itime_in_file_ucat, &
+ 'shear velocity', 'm/s')
+ ENDIF
+
+ IF (allocated(a_sedcon_avg )) deallocate (a_sedcon_avg )
+ IF (allocated(a_sedout_avg )) deallocate (a_sedout_avg )
+ IF (allocated(a_bedout_avg )) deallocate (a_bedout_avg )
+ IF (allocated(a_sedinp_avg )) deallocate (a_sedinp_avg )
+ IF (allocated(a_netflw_avg )) deallocate (a_netflw_avg )
+ IF (allocated(a_layer_avg )) deallocate (a_layer_avg )
+ IF (allocated(a_shearvel_avg)) deallocate (a_shearvel_avg)
+
+ END SUBROUTINE write_sediment_history
+#endif
+
+END MODULE MOD_Grid_RiverLakeHist
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90
new file mode 100644
index 0000000000..b3d21e2243
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeNetwork.F90
@@ -0,0 +1,2220 @@
+#include
+
+#ifdef GridRiverLakeFlow
+MODULE MOD_Grid_RiverLakeNetwork
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!--------------------------------------------------------------------------------
+
+ USE MOD_Grid
+ USE MOD_ComputePushData
+ IMPLICIT NONE
+
+ ! ----- River Lake network -----
+
+ type(grid_type) :: griducat
+
+ integer :: totalnumucat
+ integer :: numucat
+ integer, allocatable :: ucat_ucid (:) ! index in unit catchment numbering
+ integer, allocatable :: x_ucat (:) !
+ integer, allocatable :: y_ucat (:) !
+ integer, allocatable :: ucat_gdid (:) !
+
+ integer, allocatable :: numucat_rank (:)
+ type(pointer_int32_1d), allocatable :: ucat_data_address (:)
+
+ ! ----- Part 1: between runoff input elements and unit catchments -----
+ integer :: numinpm
+ integer, allocatable :: inpm_gdid (:)
+
+ integer :: inpn
+ integer, allocatable :: idmap_gd2uc (:,:)
+ real(r8), allocatable :: area_gd2uc (:,:)
+
+ integer :: nucpart
+ integer, allocatable :: idmap_uc2gd (:,:)
+ real(r8), allocatable :: area_uc2gd (:,:)
+
+ type(compute_remapdata_type) :: remap_patch2inpm
+ type(compute_pushdata_type) :: push_inpm2ucat
+ type(compute_pushdata_type) :: push_ucat2inpm
+ type(compute_pushdata_type) :: push_ucat2grid
+ type(compute_pushdata_type) :: allreduce_inpm
+
+ ! ----- Part 2: between upstream and downstream unit catchments -----
+ integer, allocatable :: ucat_next (:) ! next unit catchment
+ integer :: upnmax
+ integer, allocatable :: ucat_ups (:,:) ! upstream unit catchments
+ real(r8), allocatable :: wts_ups (:,:)
+
+ type(compute_pushdata_type) :: push_next2ucat
+ type(compute_pushdata_type) :: push_ups2ucat
+
+ ! ----- Part 3: river systems -----
+ integer :: numrivsys
+ logical :: rivsys_by_multiple_procs
+ integer, allocatable :: irivsys (:)
+#ifdef COLM_PARALLEL
+ integer :: p_comm_rivsys
+#endif
+
+
+ ! ----- Parameters for River and Lake -----
+
+ integer, allocatable :: lake_type (:) ! 0: river; 2: reservoir.
+
+ real(r8), allocatable :: topo_rivelv (:) ! river bed elevation [m]
+ real(r8), allocatable :: topo_rivhgt (:) ! river channel depth [m]
+ real(r8), allocatable :: topo_rivlen (:) ! river channel length [m]
+ real(r8), allocatable :: topo_rivman (:) ! river manning coefficient [m]
+ real(r8), allocatable :: topo_rivwth (:) ! river channel width [m]
+ real(r8), allocatable :: topo_rivare (:) ! river channel area [m^2]
+ real(r8), allocatable :: topo_rivstomax (:) ! max river channel storage [m^3]
+
+ real(r8), allocatable :: topo_area (:) ! floodplain area [m^2]
+ real(r8), allocatable :: topo_fldhgt (:,:) ! floodplain height profile [m]
+
+ real(r8), allocatable :: bedelv_next (:) ! downstream river bed elevation [m]
+ real(r8), allocatable :: outletwth (:) ! river outlet width [m]
+
+ type :: vol_dep_curve_type
+ integer :: nlfp
+ real(r8) :: rivhgt
+ real(r8) :: rivare
+ real(r8) :: rivstomax
+ real(r8), allocatable :: flphgt (:) ! floodplain height profile [m]
+ real(r8), allocatable :: flparea (:) ! flood plain area [m^2]
+ real(r8), allocatable :: flpaccare (:) ! flood plain accumulated area [m^2]
+ real(r8), allocatable :: flpstomax (:) ! max flood plain storage [m^3]
+ CONTAINS
+ procedure, PUBLIC :: depth => retrieve_depth_from_volume
+ procedure, PUBLIC :: volume => retrieve_volume_from_depth
+ procedure, PUBLIC :: floodarea => retrieve_area_from_depth
+ final :: vol_depth_curve_free_mem
+ END type vol_dep_curve_type
+
+ type(vol_dep_curve_type), allocatable :: floodplain_curve (:)
+
+
+ ! ----- Mask of Grids with all upstream area in the simulation region -----
+ real(r8), allocatable :: allups_mask_ucat (:)
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE build_riverlake_network ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh
+ USE MOD_Utils
+ USE MOD_LandPatch
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ ! Local Variables
+ character(len=256) :: parafile
+
+ integer, allocatable :: idmap_x(:,:), idmap_y(:,:)
+ integer, allocatable :: varsize(:)
+
+ integer :: numrivmth
+ integer, allocatable :: rivermouth(:)
+
+ integer, allocatable :: nups_nst (:), iups_nst (:), nups_all(:)
+ integer, allocatable :: ucat_next_all(:)
+ integer, allocatable :: uc_up2down(:), order_ucat(:)
+ integer, allocatable :: addr_ucat (:)
+
+ integer , allocatable :: nuc_rs(:), irank_rs(:), nrank_rs(:), nave_rs(:)
+ real(r8), allocatable :: wt_uc (:), wt_rs (:), wt_rank (:), nuc_rank(:)
+
+ integer, allocatable :: grdindex(:)
+
+
+ integer, allocatable :: idata1d(:), idata2d(:,:)
+ real(r8), allocatable :: rdata1d(:), rdata2d(:,:)
+
+ integer, allocatable :: allgrd_in_inp (:), nucat_g2d(:,:), iucat_g(:)
+
+ integer, allocatable :: idmap_uc2gd_all(:,:)
+ real(r8), allocatable :: area_uc2gd_all (:,:)
+
+ real(r8), allocatable :: ucat_area_all (:)
+
+ integer :: nlat_ucat, nlon_ucat
+ integer :: nucat, iriv, ngrdall, igrd, ngrd
+ integer :: p_np_rivsys, color
+ integer :: irank, irankdsp, self_rank
+ integer :: iloc, i, j, ithis
+ real(r8) :: sumwt
+ logical :: is_new
+
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL build_riverlake_network_mpas_embedded()
+ RETURN
+#endif
+
+ ! read in parameters from file.
+ parafile = DEF_UnitCatchment_file
+ IF (p_is_root) THEN
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL ncio_inquire_length (parafile, 'seq_next', totalnumucat)
+#else
+ CALL ncio_read_serial (parafile, 'seq_x', x_ucat)
+ CALL ncio_read_serial (parafile, 'seq_y', y_ucat)
+ totalnumucat = size(x_ucat)
+#endif
+
+ CALL ncio_read_serial (parafile, 'seq_next', ucat_next)
+
+ CALL ncio_inquire_length (parafile, 'lon', nlon_ucat)
+ CALL ncio_inquire_length (parafile, 'lat', nlat_ucat)
+
+#ifndef MPAS_EMBEDDED_COLM
+ CALL ncio_read_serial (parafile, 'inpmat_x', idmap_x)
+ CALL ncio_read_serial (parafile, 'inpmat_y', idmap_y)
+ CALL ncio_read_serial (parafile, 'inpmat_area', area_gd2uc)
+#endif
+
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ allocate (nups_nst (totalnumucat))
+ allocate (iups_nst (totalnumucat))
+
+ nups_nst(:) = 0
+ DO i = 1, totalnumucat
+ j = ucat_next(i)
+ IF (j > 0) THEN
+ nups_nst(j) = nups_nst(j) + 1
+ ENDIF
+ ENDDO
+
+ ! sort unit catchment from upstream to downstream, recorded by "uc_up2down"
+ allocate (uc_up2down (totalnumucat))
+
+ ithis = 0
+ iups_nst(:) = 0
+ DO i = 1, totalnumucat
+ IF (iups_nst(i) == nups_nst(i)) THEN
+
+ ithis = ithis + 1
+ uc_up2down(ithis) = i
+ iups_nst(i) = -1
+
+ j = ucat_next(i)
+ DO WHILE (j > 0)
+
+ iups_nst(j) = iups_nst(j) + 1
+
+ IF (iups_nst(j) == nups_nst(j)) THEN
+ ithis = ithis + 1
+ uc_up2down(ithis) = j
+ iups_nst(j) = -1
+
+ j = ucat_next(j)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ ! divide unit catchments into groups and assign to ranks
+ IF (p_is_root) THEN
+
+ allocate (wt_uc (totalnumucat)); wt_uc(:) = 1.
+
+ allocate (rivermouth (totalnumucat))
+ numrivmth = 0
+ DO i = totalnumucat, 1, -1
+ j = ucat_next(uc_up2down(i))
+ IF (j <= 0) THEN
+ numrivmth = numrivmth + 1
+ rivermouth(uc_up2down(i)) = numrivmth
+ ELSE
+ rivermouth(uc_up2down(i)) = rivermouth(j)
+ ENDIF
+ ENDDO
+
+ allocate (nuc_rs (numrivmth)); nuc_rs(:) = 0
+ allocate (wt_rs (numrivmth)); wt_rs (:) = 0.
+ DO i = 1, totalnumucat
+ nuc_rs(rivermouth(i)) = nuc_rs(rivermouth(i)) + 1
+ wt_rs (rivermouth(i)) = wt_rs (rivermouth(i)) + wt_uc(i)
+ ENDDO
+
+ sumwt = sum(wt_rs)
+
+ allocate (irank_rs (numrivmth))
+ allocate (nrank_rs (numrivmth))
+ allocate (nave_rs (numrivmth))
+
+ irankdsp = -1
+ DO i = 1, numrivmth
+ nrank_rs(i) = floor(wt_rs(i)/sumwt * p_np_compute)
+ IF (nrank_rs(i) > 1) THEN
+
+ nave_rs(i) = nuc_rs(i) / nrank_rs(i)
+ IF (mod(nuc_rs(i), nrank_rs(i)) /= 0) THEN
+ nave_rs(i) = nave_rs(i) + 1
+ ENDIF
+
+ irank_rs(i) = irankdsp + 1
+ irankdsp = irankdsp + nrank_rs(i)
+ ENDIF
+ ENDDO
+
+ allocate (nups_all (totalnumucat)); nups_all(:) = 1
+
+ DO i = 1, totalnumucat
+ j = ucat_next(uc_up2down(i))
+ IF (j > 0) THEN
+ nups_all(j) = nups_all(j) + nups_all(uc_up2down(i))
+ ENDIF
+ ENDDO
+
+ allocate (addr_ucat (totalnumucat)); addr_ucat(:) = -1
+
+ allocate (wt_rank (0:p_np_compute-1)); wt_rank (:) = 0
+ allocate (nuc_rank(0:p_np_compute-1)); nuc_rank(:) = 0
+
+ allocate (order_ucat (totalnumucat))
+ order_ucat(uc_up2down) = (/(i, i = 1, totalnumucat)/)
+
+ ithis = totalnumucat
+ DO WHILE (ithis > 0)
+
+ i = uc_up2down(ithis)
+
+ IF (addr_ucat(i) >= 0) THEN
+ ithis = ithis - 1
+ CYCLE
+ ENDIF
+
+ j = ucat_next(i)
+ IF (j > 0) THEN
+ IF (addr_ucat(j) >= 0) THEN
+ addr_ucat(i) = addr_ucat(j)
+ ithis = ithis - 1
+ CYCLE
+ ENDIF
+ ENDIF
+
+ iriv = rivermouth(i)
+ IF (nrank_rs(iriv) > 1) THEN
+ irank = irank_rs(iriv)
+ IF (nups_all(i) <= nave_rs(iriv)-nuc_rank(irank)) THEN
+
+ addr_ucat(i) = p_address_compute(irank)
+
+ nuc_rank(irank) = nuc_rank(irank) + nups_all(i)
+ IF (nuc_rank(irank) == nave_rs(iriv)) THEN
+ irank_rs(iriv) = irank_rs(iriv) + 1
+ ENDIF
+
+ j = ucat_next(i)
+ IF (j > 0) THEN
+ DO WHILE (j > 0)
+ nups_all(j) = nups_all(j) - nups_all(i)
+ ithis = order_ucat(j)
+ j = ucat_next(j)
+ ENDDO
+ ELSE
+ ithis = ithis - 1
+ ENDIF
+ ELSE
+ ithis = ithis - 1
+ ENDIF
+ ELSE
+ irank = minloc(wt_rank(irankdsp+1:p_np_compute-1), dim=1) + irankdsp
+
+ addr_ucat(i) = p_address_compute(irank)
+
+ wt_rank(irank) = wt_rank(irank) + wt_rs(iriv)
+ ithis = ithis - 1
+ ENDIF
+
+ ENDDO
+
+ deallocate (order_ucat)
+ deallocate (nups_all )
+ deallocate (nuc_rs )
+ deallocate (irank_rs )
+ deallocate (nrank_rs )
+ deallocate (nave_rs )
+ deallocate (wt_uc )
+ deallocate (wt_rs )
+ deallocate (wt_rank )
+ deallocate (nuc_rank )
+
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ allocate(ucat_ucid (totalnumucat))
+ ucat_ucid = (/(i, i = 1, totalnumucat)/)
+
+ allocate (numucat_rank (0:p_np_compute-1))
+ allocate (ucat_data_address (0:p_np_compute-1))
+
+ DO irank = 0, p_np_compute-1
+ nucat = count(addr_ucat == p_address_compute(irank))
+ numucat_rank(irank) = nucat
+ IF (nucat > 0) THEN
+ allocate (ucat_data_address(irank)%val (nucat))
+ ucat_data_address(irank)%val = &
+ pack(ucat_ucid, mask = (addr_ucat == p_address_compute(irank)))
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ CALL mpi_bcast (totalnumucat, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+ ! send unit catchment index to ranks
+ IF (p_is_root) THEN
+
+ self_rank = -1
+
+ DO irank = 0, p_np_compute-1
+
+ nucat = numucat_rank(irank)
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ numucat = nucat
+ self_rank = irank
+ CYCLE
+ ENDIF
+
+ CALL mpi_send (nucat, 1, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (nucat > 0) THEN
+
+ CALL mpi_send (ucat_data_address(irank)%val, nucat, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_data, p_comm_glb, p_err)
+
+#ifndef MPAS_EMBEDDED_COLM
+ allocate (idata1d (nucat))
+
+ idata1d = x_ucat (ucat_data_address(irank)%val)
+ CALL mpi_send (idata1d, nucat, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_data, p_comm_glb, p_err)
+
+ idata1d = y_ucat (ucat_data_address(irank)%val)
+ CALL mpi_send (idata1d, nucat, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (idata1d)
+#endif
+ ENDIF
+ ENDDO
+
+ IF (self_rank >= 0) THEN
+ nucat = numucat_rank(self_rank)
+ IF (allocated(idata1d)) deallocate(idata1d)
+ allocate (idata1d (nucat))
+ IF (nucat > 0) idata1d = ucat_data_address(self_rank)%val
+
+ IF (allocated(ucat_ucid)) deallocate(ucat_ucid)
+ allocate (ucat_ucid (nucat))
+ IF (nucat > 0) ucat_ucid = idata1d
+
+#ifndef MPAS_EMBEDDED_COLM
+ IF (allocated(x_ucat)) THEN
+ IF (nucat > 0) idata1d = x_ucat(ucat_ucid)
+ deallocate (x_ucat)
+ allocate (x_ucat (nucat))
+ IF (nucat > 0) x_ucat = idata1d
+ ENDIF
+
+ IF (allocated(y_ucat)) THEN
+ IF (nucat > 0) idata1d = y_ucat(ucat_ucid)
+ deallocate (y_ucat)
+ allocate (y_ucat (nucat))
+ IF (nucat > 0) y_ucat = idata1d
+ ENDIF
+#endif
+
+ deallocate (idata1d)
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ CALL mpi_recv (numucat, 1, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ IF (numucat > 0) THEN
+ allocate (ucat_ucid (numucat))
+#ifndef MPAS_EMBEDDED_COLM
+ allocate (x_ucat (numucat))
+ allocate (y_ucat (numucat))
+#endif
+ CALL mpi_recv (ucat_ucid, numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+#ifndef MPAS_EMBEDDED_COLM
+ CALL mpi_recv (x_ucat, numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (y_ucat, numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+#endif
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ numucat = totalnumucat
+
+ allocate(ucat_ucid (totalnumucat))
+ ucat_ucid = (/(i, i = 1, totalnumucat)/)
+
+ allocate (numucat_rank (0:0))
+ numucat_rank(0) = numucat
+
+ allocate (ucat_data_address (0:0))
+ allocate (ucat_data_address(0)%val (numucat))
+ ucat_data_address(0)%val = ucat_ucid
+#endif
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ CALL ncio_read_indexed_serial (parafile, 'seq_x', ucat_ucid, x_ucat)
+ CALL ncio_read_indexed_serial (parafile, 'seq_y', ucat_ucid, y_ucat)
+ ELSE
+ IF (.not. allocated(x_ucat)) allocate (x_ucat (0))
+ IF (.not. allocated(y_ucat)) allocate (y_ucat (0))
+ ENDIF
+ ENDIF
+#endif
+
+ IF (p_is_compute .and. numucat == 0) THEN
+ IF (.not. allocated(ucat_ucid)) allocate (ucat_ucid (0))
+ IF (.not. allocated(x_ucat )) allocate (x_ucat (0))
+ IF (.not. allocated(y_ucat )) allocate (y_ucat (0))
+ ENDIF
+
+ IF (allocated(addr_ucat)) deallocate(addr_ucat)
+
+ ! ----- Part 1: between runoff input elements and unit catchments -----
+
+#ifdef COLM_PARALLEL
+ CALL mpi_bcast (nlon_ucat, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast (nlat_ucat, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#endif
+
+ CALL griducat%define_by_ndims (nlon_ucat, nlat_ucat)
+
+ CALL build_compute_remapdata (landpatch, griducat, remap_patch2inpm)
+
+ IF (p_is_compute) THEN
+ numinpm = remap_patch2inpm%num_grid
+ IF (numinpm > 0) THEN
+ allocate (inpm_gdid (numinpm))
+ inpm_gdid = remap_patch2inpm%ids_me
+ ELSE
+ allocate (inpm_gdid (0))
+ ENDIF
+ ENDIF
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL ncio_inquire_varsize (parafile, 'inpmat_x', varsize)
+ inpn = varsize(1)
+ deallocate (varsize)
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ CALL ncio_read_indexed_serial (parafile, 'inpmat_x', ucat_ucid, idmap_x)
+ CALL ncio_read_indexed_serial (parafile, 'inpmat_y', ucat_ucid, idmap_y)
+ CALL ncio_read_indexed_serial (parafile, 'inpmat_area', ucat_ucid, area_gd2uc)
+
+ allocate(idmap_gd2uc (inpn,numucat))
+ idmap_gd2uc = (idmap_y-1)*nlon_ucat + idmap_x
+
+ WHERE ((area_gd2uc <= 0) .or. (idmap_gd2uc <= 0))
+ idmap_gd2uc = 0
+ area_gd2uc = 0.
+ END WHERE
+ ELSE
+ allocate(idmap_gd2uc (inpn,0))
+ allocate(area_gd2uc (inpn,0))
+ ENDIF
+
+ CALL build_mpas_embedded_uc2gd (parafile, nlon_ucat, inpn, numinpm, inpm_gdid, &
+ nucpart, idmap_uc2gd, area_uc2gd)
+ ENDIF
+#else
+ IF (p_is_root) THEN
+
+ inpn = size(idmap_x,1)
+
+ allocate(idmap_gd2uc (inpn,totalnumucat))
+
+ idmap_gd2uc = (idmap_y-1)*nlon_ucat + idmap_x
+
+ WHERE ((area_gd2uc <= 0) .or. (idmap_gd2uc <= 0))
+ idmap_gd2uc = 0
+ area_gd2uc = 0.
+ END WHERE
+
+ allocate (nucat_g2d (nlon_ucat,nlat_ucat))
+ nucat_g2d(:,:) = 0
+
+ DO i = 1, totalnumucat
+ DO j = 1, inpn
+ IF (idmap_gd2uc(j,i) > 0) THEN
+ nucat_g2d(idmap_x(j,i),idmap_y(j,i)) = nucat_g2d(idmap_x(j,i),idmap_y(j,i)) + 1
+ ENDIF
+ ENDDO
+ ENDDO
+
+ nucpart = maxval(nucat_g2d)
+ ngrdall = count(nucat_g2d > 0)
+
+ allocate (allgrd_in_inp (ngrdall))
+
+ igrd = 0
+ DO i = 1, nlat_ucat
+ DO j = 1, nlon_ucat
+ IF (nucat_g2d(j,i) > 0) THEN
+ igrd = igrd + 1
+ allgrd_in_inp(igrd) = (i-1)*nlon_ucat + j
+ ENDIF
+ ENDDO
+ ENDDO
+
+ allocate (idmap_uc2gd_all (nucpart, ngrdall)); idmap_uc2gd_all(:,:) = 0
+ allocate (area_uc2gd_all (nucpart, ngrdall)); area_uc2gd_all (:,:) = 0.
+
+ allocate (iucat_g (ngrdall)); iucat_g(:) = 0
+
+ DO i = 1, totalnumucat
+ DO j = 1, inpn
+ IF (idmap_gd2uc(j,i) > 0) THEN
+ iloc = find_in_sorted_list1 (idmap_gd2uc(j,i), ngrdall, allgrd_in_inp(1:ngrdall))
+ iucat_g(iloc) = iucat_g(iloc) + 1
+ idmap_uc2gd_all(iucat_g(iloc),iloc) = i
+ area_uc2gd_all (iucat_g(iloc),iloc) = area_gd2uc(j,i)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_bcast (inpn, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+ IF (p_is_root) THEN
+
+ self_rank = -1
+ DO irank = 0, p_np_compute-1
+
+ nucat = numucat_rank(irank)
+
+ IF (nucat > 0) THEN
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ self_rank = irank
+ CYCLE
+ ENDIF
+
+ allocate (idata2d (inpn, nucat))
+ DO i = 1, nucat
+ idata2d(:,i) = idmap_gd2uc(:,ucat_data_address(irank)%val(i))
+ ENDDO
+
+ allocate (rdata2d (inpn, nucat))
+ DO i = 1, nucat
+ rdata2d(:,i) = area_gd2uc(:,ucat_data_address(irank)%val(i))
+ ENDDO
+
+ CALL mpi_send (idata2d, inpn*nucat, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send (rdata2d, inpn*nucat, MPI_REAL8, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (idata2d)
+ deallocate (rdata2d)
+ ENDIF
+ ENDDO
+
+ IF (self_rank >= 0) THEN
+ nucat = numucat_rank(self_rank)
+ IF (nucat > 0) THEN
+ allocate (idata2d (inpn, nucat))
+ DO i = 1, nucat
+ idata2d(:,i) = idmap_gd2uc(:,ucat_data_address(self_rank)%val(i))
+ ENDDO
+
+ allocate (rdata2d (inpn, nucat))
+ DO i = 1, nucat
+ rdata2d(:,i) = area_gd2uc(:,ucat_data_address(self_rank)%val(i))
+ ENDDO
+
+ IF (allocated(idmap_gd2uc)) deallocate(idmap_gd2uc)
+ IF (allocated(area_gd2uc )) deallocate(area_gd2uc )
+ allocate (idmap_gd2uc (inpn, nucat))
+ allocate (area_gd2uc (inpn, nucat))
+ idmap_gd2uc = idata2d
+ area_gd2uc = rdata2d
+
+ deallocate (idata2d)
+ deallocate (rdata2d)
+ ENDIF
+ ENDIF
+
+ IF (.not. (p_is_compute .and. numucat > 0)) THEN
+ IF (allocated(idmap_gd2uc)) deallocate (idmap_gd2uc)
+ IF (allocated(area_gd2uc )) deallocate (area_gd2uc )
+ IF (p_is_compute) THEN
+ allocate (idmap_gd2uc (inpn,0))
+ allocate (area_gd2uc (inpn,0))
+ ENDIF
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ IF (numucat > 0) THEN
+
+ allocate (idmap_gd2uc (inpn, numucat))
+ CALL mpi_recv (idmap_gd2uc, inpn*numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (area_gd2uc (inpn, numucat))
+ CALL mpi_recv (area_gd2uc, inpn*numucat, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_bcast (nucpart, 1, mpi_integer, p_address_root, p_comm_glb, p_err)
+
+ IF (p_is_root) THEN
+
+ DO irank = 0, p_np_compute-1
+
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ ngrd = numinpm
+ ELSE
+ CALL mpi_recv (ngrd, 1, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ IF (ngrd > 0) THEN
+
+ allocate (grdindex (ngrd))
+ allocate (idata2d (nucpart, ngrd)); idata2d(:,:) = 0
+ allocate (rdata2d (nucpart, ngrd)); rdata2d(:,:) = 0.
+
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ grdindex = inpm_gdid
+ ELSE
+ CALL mpi_recv (grdindex, ngrd, MPI_INTEGER, &
+ p_address_compute(irank), mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ DO i = 1, ngrd
+ iloc = find_in_sorted_list1 (grdindex(i), ngrdall, allgrd_in_inp(1:ngrdall))
+ IF (iloc > 0) THEN
+ idata2d(:,i) = idmap_uc2gd_all(:,iloc)
+ rdata2d(:,i) = area_uc2gd_all (:,iloc)
+ ENDIF
+ ENDDO
+
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ IF (allocated(idmap_uc2gd)) deallocate(idmap_uc2gd)
+ IF (allocated(area_uc2gd )) deallocate(area_uc2gd )
+ allocate (idmap_uc2gd (nucpart, ngrd))
+ allocate (area_uc2gd (nucpart, ngrd))
+ idmap_uc2gd = idata2d
+ area_uc2gd = rdata2d
+ ELSE
+ CALL mpi_send (idata2d, nucpart*ngrd, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send (rdata2d, nucpart*ngrd, MPI_REAL8, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ deallocate (grdindex)
+ deallocate (idata2d )
+ deallocate (rdata2d )
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ CALL mpi_send (numinpm, 1, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (numinpm > 0) THEN
+
+ CALL mpi_send (inpm_gdid, numinpm, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_err)
+
+ allocate (idmap_uc2gd (nucpart,numinpm))
+ CALL mpi_recv (idmap_uc2gd, nucpart*numinpm, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (area_uc2gd (nucpart,numinpm))
+ CALL mpi_recv (area_uc2gd, nucpart*numinpm, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ allocate (idmap_uc2gd (nucpart,numinpm))
+ allocate (area_uc2gd (nucpart,numinpm))
+ idmap_uc2gd = 0
+ area_uc2gd = 0.
+
+ DO i = 1, numinpm
+ iloc = find_in_sorted_list1 (inpm_gdid(i), ngrdall, allgrd_in_inp(1:ngrdall))
+ IF (iloc > 0) THEN
+ idmap_uc2gd(:,i) = idmap_uc2gd_all(:,iloc)
+ area_uc2gd (:,i) = area_uc2gd_all (:,iloc)
+ ENDIF
+ ENDDO
+#endif
+#endif
+
+ IF (p_is_compute) THEN
+ IF (.not. allocated(idmap_gd2uc)) allocate (idmap_gd2uc (inpn,0))
+ IF (.not. allocated(area_gd2uc )) allocate (area_gd2uc (inpn,0))
+ IF (.not. allocated(idmap_uc2gd)) allocate (idmap_uc2gd (nucpart,0))
+ IF (.not. allocated(area_uc2gd )) allocate (area_uc2gd (nucpart,0))
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ allocate (ucat_gdid (numucat))
+ ucat_gdid = (y_ucat-1)*nlon_ucat + x_ucat
+ ELSE
+ allocate (ucat_gdid (0))
+ ENDIF
+ ENDIF
+
+ CALL build_compute_pushdata (numinpm, inpm_gdid, numucat, idmap_gd2uc, area_gd2uc, push_inpm2ucat)
+ CALL build_compute_pushdata (numucat, ucat_ucid, numinpm, idmap_uc2gd, area_uc2gd, push_ucat2inpm)
+ CALL build_compute_pushdata (numucat, ucat_gdid, numinpm, inpm_gdid, push_ucat2grid)
+ CALL build_compute_pushdata (numinpm, inpm_gdid, numinpm, inpm_gdid, allreduce_inpm)
+
+ IF (allocated(idmap_x)) deallocate (idmap_x)
+ IF (allocated(idmap_y)) deallocate (idmap_y)
+ IF (p_is_root) THEN
+ IF (allocated(allgrd_in_inp )) deallocate (allgrd_in_inp )
+ IF (allocated(nucat_g2d )) deallocate (nucat_g2d )
+ IF (allocated(iucat_g )) deallocate (iucat_g )
+ IF (allocated(idmap_uc2gd_all)) deallocate (idmap_uc2gd_all)
+ IF (allocated(area_uc2gd_all )) deallocate (area_uc2gd_all )
+ ENDIF
+
+ ! ----- Part 2: between upstream and downstream unit catchments -----
+
+ IF (p_is_root) THEN
+
+ upnmax = maxval(nups_nst)
+ allocate (ucat_ups (upnmax,totalnumucat))
+ ucat_ups(:,:) = 0
+ allocate (ucat_next_all (totalnumucat))
+ ucat_next_all = ucat_next
+
+ iups_nst(:) = 0
+ DO i = 1, totalnumucat
+ j = ucat_next(i)
+ IF (j > 0) THEN
+ iups_nst(j) = iups_nst(j) + 1
+ ucat_ups(iups_nst(j),j) = i
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+
+#ifdef COLM_PARALLEL
+ CALL mpi_bcast (upnmax, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+ IF (p_is_root) THEN
+
+ self_rank = -1
+ DO irank = 0, p_np_compute-1
+
+ nucat = numucat_rank(irank)
+
+ IF (nucat > 0) THEN
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ self_rank = irank
+ CYCLE
+ ENDIF
+
+ allocate (idata1d (nucat))
+ idata1d = ucat_next(ucat_data_address(irank)%val)
+
+ allocate (idata2d (upnmax,nucat))
+ DO i = 1, nucat
+ idata2d(:,i) = ucat_ups(:,ucat_data_address(irank)%val(i))
+ ENDDO
+
+ CALL mpi_send (idata1d, nucat, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send (idata2d, upnmax*nucat, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (idata1d)
+ deallocate (idata2d)
+ ENDIF
+ ENDDO
+
+ IF (self_rank >= 0) THEN
+ nucat = numucat_rank(self_rank)
+ IF (nucat > 0) THEN
+ allocate (idata1d (nucat))
+ idata1d = ucat_next(ucat_data_address(self_rank)%val)
+
+ allocate (idata2d (upnmax,nucat))
+ DO i = 1, nucat
+ idata2d(:,i) = ucat_ups(:,ucat_data_address(self_rank)%val(i))
+ ENDDO
+
+ IF (allocated(ucat_next)) deallocate(ucat_next)
+ IF (allocated(ucat_ups )) deallocate(ucat_ups )
+ allocate (ucat_next (nucat))
+ allocate (ucat_ups (upnmax,nucat))
+ ucat_next = idata1d
+ ucat_ups = idata2d
+
+ deallocate (idata1d)
+ deallocate (idata2d)
+ ELSE
+ IF (allocated(ucat_next)) deallocate(ucat_next)
+ IF (allocated(ucat_ups )) deallocate(ucat_ups )
+ allocate (ucat_next (0))
+ allocate (ucat_ups (upnmax,0))
+ ENDIF
+ ENDIF
+
+ IF (.not. (p_is_compute .and. numucat > 0)) THEN
+ IF (allocated(ucat_ups)) deallocate (ucat_ups)
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ IF (numucat > 0) THEN
+
+ allocate (ucat_next (numucat))
+ CALL mpi_recv (ucat_next, numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ allocate (ucat_ups (upnmax, numucat))
+ CALL mpi_recv (ucat_ups, upnmax*numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_compute) THEN
+ IF (.not. allocated(ucat_next)) allocate (ucat_next (0))
+ IF (.not. allocated(ucat_ups )) allocate (ucat_ups (upnmax,0))
+ allocate (wts_ups (upnmax,numucat))
+ IF (numucat > 0) wts_ups(:,:) = 1.
+ ENDIF
+
+ CALL build_compute_pushdata (numucat, ucat_ucid, numucat, ucat_next, push_next2ucat)
+ CALL build_compute_pushdata (numucat, ucat_ucid, numucat, ucat_ups, wts_ups, push_ups2ucat )
+
+#ifdef CoLMDEBUG
+ ! IF (p_is_compute) THEN
+ ! write(*,'(A,I0,A,I0,A,I0,A)') 'rank ', p_iam_compute, ' has ', numucat, &
+ ! ' unit catchment with ', sum(push_next2ucat%n_from_other), ' downstream to other ranks'
+ ! ENDIF
+#endif
+
+ ! ----- Part 3: river systems -----
+
+#ifdef COLM_PARALLEL
+ IF (p_is_root) THEN
+ self_rank = -1
+ DO irank = 0, p_np_compute-1
+ nucat = numucat_rank(irank)
+ IF (nucat > 0) THEN
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ self_rank = irank
+ CYCLE
+ ENDIF
+
+ allocate (idata1d (nucat))
+ idata1d = rivermouth(ucat_data_address(irank)%val)
+ CALL mpi_send (idata1d, nucat, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ deallocate (idata1d)
+ ENDIF
+ ENDDO
+
+ IF (self_rank >= 0) THEN
+ nucat = numucat_rank(self_rank)
+ allocate (idata1d (nucat))
+ IF (nucat > 0) idata1d = rivermouth(ucat_data_address(self_rank)%val)
+ IF (allocated(rivermouth)) deallocate(rivermouth)
+ allocate (rivermouth (nucat))
+ IF (nucat > 0) rivermouth = idata1d
+ deallocate (idata1d)
+ ENDIF
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+ IF (numucat > 0) THEN
+ allocate (rivermouth (numucat))
+ CALL mpi_recv (rivermouth, numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ color = maxval(rivermouth)
+ CALL mpi_comm_split (p_comm_compute, color, p_iam_compute, p_comm_rivsys, p_err)
+ ELSE
+ CALL mpi_comm_split (p_comm_compute, MPI_UNDEFINED, p_iam_compute, p_comm_rivsys, p_err)
+ ENDIF
+
+ rivsys_by_multiple_procs = .false.
+ IF (p_comm_rivsys /= MPI_COMM_NULL) THEN
+ CALL mpi_comm_size (p_comm_rivsys, p_np_rivsys, p_err)
+ IF (p_np_rivsys > 1) THEN
+ rivsys_by_multiple_procs = .true.
+ ENDIF
+ ENDIF
+ ENDIF
+#else
+ rivsys_by_multiple_procs = .false.
+#endif
+
+ IF (p_is_compute) THEN
+
+ IF (numucat > 0) allocate (irivsys (numucat))
+
+ IF (.not. rivsys_by_multiple_procs) THEN
+ IF (numucat > 0) THEN
+
+ allocate (order_ucat (numucat))
+ order_ucat = (/(i, i = 1, numucat)/)
+
+ CALL quicksort (numucat, rivermouth, order_ucat)
+
+ numrivsys = 1
+ irivsys(order_ucat(1)) = numrivsys
+ DO i = 2, numucat
+ IF (rivermouth(i) /= rivermouth(i-1)) THEN
+ numrivsys = numrivsys + 1
+ ENDIF
+ irivsys(order_ucat(i)) = numrivsys
+ ENDDO
+
+ ENDIF
+ ELSE
+ numrivsys = 1
+ irivsys(:) = 1
+ ENDIF
+
+ ENDIF
+
+ IF (allocated(rivermouth)) deallocate(rivermouth)
+ IF (allocated(order_ucat)) deallocate(order_ucat)
+
+ ! ----- Parameters for River and Lake -----
+
+ CALL readin_riverlake_parameter (parafile, 'topo_rivelv', rdata1d = topo_rivelv )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivhgt', rdata1d = topo_rivhgt )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivlen', rdata1d = topo_rivlen )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivman', rdata1d = topo_rivman )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivwth', rdata1d = topo_rivwth )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivstomax', rdata1d = topo_rivstomax)
+ CALL readin_riverlake_parameter (parafile, 'topo_area', rdata1d = topo_area )
+ CALL readin_riverlake_parameter (parafile, 'topo_fldhgt', rdata2d = topo_fldhgt )
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+
+ allocate (lake_type (numucat))
+ lake_type(:) = 0
+
+ allocate (topo_rivare (numucat))
+ topo_rivare = topo_rivstomax / topo_rivhgt
+
+ allocate (floodplain_curve (numucat))
+
+ DO i = 1, numucat
+ floodplain_curve(i)%nlfp = size(topo_fldhgt,1)
+ floodplain_curve(i)%rivhgt = topo_rivhgt(i)
+ floodplain_curve(i)%rivstomax = topo_rivstomax(i)
+ floodplain_curve(i)%rivare = topo_rivare(i)
+
+ allocate (floodplain_curve(i)%flphgt (0:floodplain_curve(i)%nlfp))
+ allocate (floodplain_curve(i)%flparea (0:floodplain_curve(i)%nlfp))
+ allocate (floodplain_curve(i)%flpaccare (0:floodplain_curve(i)%nlfp))
+ allocate (floodplain_curve(i)%flpstomax (0:floodplain_curve(i)%nlfp))
+
+ floodplain_curve(i)%flphgt(0) = 0.
+ floodplain_curve(i)%flphgt(1:) = topo_fldhgt(:,i)
+
+ floodplain_curve(i)%flparea(0) = 0.
+ floodplain_curve(i)%flparea(1:) = topo_area(i) / floodplain_curve(i)%nlfp
+
+ floodplain_curve(i)%flpaccare(0) = 0.
+ DO j = 1, floodplain_curve(i)%nlfp
+ floodplain_curve(i)%flpaccare(j) = &
+ floodplain_curve(i)%flpaccare(j-1) + floodplain_curve(i)%flparea(j)
+ ENDDO
+
+ floodplain_curve(i)%flpstomax(0) = 0.
+ DO j = 1, floodplain_curve(i)%nlfp
+ floodplain_curve(i)%flpstomax(j) = floodplain_curve(i)%flpstomax(j-1) &
+ + 0.5 * (floodplain_curve(i)%flparea(j) + floodplain_curve(i)%flparea(j-1)) &
+ * (floodplain_curve(i)%flphgt(j) - floodplain_curve(i)%flphgt(j-1))
+ ENDDO
+ ENDDO
+
+ allocate (bedelv_next (numucat))
+ allocate (outletwth (numucat))
+
+ ELSE
+ allocate (bedelv_next (0))
+ allocate (outletwth (0))
+ ENDIF
+ ENDIF
+
+ CALL compute_push_data (push_next2ucat, topo_rivelv, bedelv_next, fillvalue = spval)
+ CALL compute_push_data (push_next2ucat, topo_rivwth, outletwth , fillvalue = spval)
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ WHERE (ucat_next > 0)
+ outletwth = (outletwth + topo_rivwth) * 0.5
+ ELSEWHERE
+ outletwth = topo_rivwth
+ END WHERE
+ ENDIF
+ ENDIF
+
+ ! ----- Mask of Grids with all upstream area in the simulation region -----
+
+ IF (p_is_root) allocate (ucat_area_all (totalnumucat))
+
+#ifdef COLM_PARALLEL
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ IF (numucat > 0) THEN
+ CALL mpi_send (push_inpm2ucat%sum_area, numucat, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ DO irank = 0, p_np_compute-1
+ IF (numucat_rank(irank) > 0) THEN
+
+ allocate (rdata1d (numucat_rank(irank)))
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ rdata1d = push_inpm2ucat%sum_area
+ ELSE
+ CALL mpi_recv (rdata1d, numucat_rank(irank), MPI_REAL8, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ ucat_area_all(ucat_data_address(irank)%val) = rdata1d
+
+ deallocate (rdata1d)
+ ENDIF
+
+ ENDDO
+ ENDIF
+#else
+ ucat_area_all = push_inpm2ucat%sum_area
+#endif
+
+ IF (p_is_root) THEN
+
+ allocate (allups_mask_ucat (totalnumucat))
+ allups_mask_ucat (:) = 0
+
+ iups_nst(:) = 0
+ DO i = 1, totalnumucat
+ j = uc_up2down(i)
+ IF (ucat_area_all(j) > 0.) THEN
+ IF (iups_nst(j) == nups_nst(j)) THEN
+
+ allups_mask_ucat(j) = 1
+
+ IF (ucat_next_all(j) > 0) THEN
+ iups_nst(ucat_next_all(j)) = iups_nst(ucat_next_all(j)) + 1
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ IF (p_is_root) THEN
+ self_rank = -1
+ DO irank = 0, p_np_compute-1
+ IF (numucat_rank(irank) > 0) THEN
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ self_rank = irank
+ CYCLE
+ ENDIF
+
+ allocate (rdata1d (numucat_rank(irank)))
+ rdata1d = allups_mask_ucat(ucat_data_address(irank)%val)
+
+ CALL mpi_send (rdata1d, numucat_rank(irank), MPI_REAL8, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (rdata1d)
+ ENDIF
+ ENDDO
+
+ IF (self_rank >= 0) THEN
+ allocate (rdata1d (numucat_rank(self_rank)))
+ IF (numucat_rank(self_rank) > 0) &
+ rdata1d = allups_mask_ucat(ucat_data_address(self_rank)%val)
+ IF (allocated(allups_mask_ucat)) deallocate(allups_mask_ucat)
+ allocate (allups_mask_ucat (numucat_rank(self_rank)))
+ IF (numucat_rank(self_rank) > 0) allups_mask_ucat = rdata1d
+ deallocate (rdata1d)
+ ENDIF
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+ IF (numucat > 0) THEN
+ allocate (allups_mask_ucat (numucat))
+ CALL mpi_recv (allups_mask_ucat, numucat, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+#endif
+
+ IF (p_is_compute .and. numucat == 0) THEN
+ IF (.not. allocated(allups_mask_ucat)) allocate (allups_mask_ucat (0))
+ ENDIF
+
+
+ IF (allocated (uc_up2down )) deallocate (uc_up2down )
+ IF (allocated (ucat_next_all)) deallocate (ucat_next_all)
+ IF (allocated (nups_nst )) deallocate (nups_nst )
+ IF (allocated (iups_nst )) deallocate (iups_nst )
+ IF (allocated (ucat_area_all)) deallocate (ucat_area_all)
+
+ END SUBROUTINE build_riverlake_network
+
+#ifdef MPAS_EMBEDDED_COLM
+ ! ---------
+ SUBROUTINE build_riverlake_network_mpas_embedded ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh
+ USE MOD_LandPatch
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=256) :: parafile
+ integer, allocatable :: varsize(:)
+ integer, allocatable :: idmap_x(:,:), idmap_y(:,:)
+ integer :: nlat_ucat, nlon_ucat
+ integer :: inpn
+ integer :: i, j
+
+ parafile = DEF_UnitCatchment_file
+
+ CALL ncio_inquire_length (parafile, 'seq_next', totalnumucat)
+ CALL ncio_inquire_length (parafile, 'lon', nlon_ucat)
+ CALL ncio_inquire_length (parafile, 'lat', nlat_ucat)
+
+ CALL griducat%define_by_ndims (nlon_ucat, nlat_ucat)
+ CALL build_compute_remapdata (landpatch, griducat, remap_patch2inpm)
+
+ IF (p_is_compute) THEN
+ numinpm = remap_patch2inpm%num_grid
+ IF (numinpm > 0) THEN
+ allocate (inpm_gdid (numinpm))
+ inpm_gdid = remap_patch2inpm%ids_me
+ ELSE
+ allocate (inpm_gdid (0))
+ ENDIF
+ ENDIF
+
+ CALL build_mpas_embedded_local_ucats (parafile, nlon_ucat, numinpm, inpm_gdid)
+
+ CALL ncio_inquire_varsize (parafile, 'inpmat_x', varsize)
+ inpn = varsize(1)
+ deallocate (varsize)
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ CALL ncio_read_indexed_serial (parafile, 'inpmat_x', ucat_ucid, idmap_x)
+ CALL ncio_read_indexed_serial (parafile, 'inpmat_y', ucat_ucid, idmap_y)
+ CALL ncio_read_indexed_serial (parafile, 'inpmat_area', ucat_ucid, area_gd2uc)
+
+ allocate (idmap_gd2uc (inpn,numucat))
+ idmap_gd2uc = (idmap_y-1)*nlon_ucat + idmap_x
+
+ WHERE ((area_gd2uc <= 0._r8) .or. (idmap_gd2uc <= 0))
+ idmap_gd2uc = 0
+ area_gd2uc = 0._r8
+ END WHERE
+
+ deallocate (idmap_x)
+ deallocate (idmap_y)
+ ELSE
+ allocate (idmap_gd2uc (inpn,0))
+ allocate (area_gd2uc (inpn,0))
+ ENDIF
+
+ CALL build_mpas_embedded_uc2gd (parafile, nlon_ucat, inpn, numinpm, inpm_gdid, &
+ nucpart, idmap_uc2gd, area_uc2gd)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ CALL build_compute_pushdata (numinpm, inpm_gdid, numucat, idmap_gd2uc, area_gd2uc, push_inpm2ucat)
+ CALL build_compute_pushdata (numucat, ucat_ucid, numinpm, idmap_uc2gd, area_uc2gd, push_ucat2inpm)
+ CALL build_compute_pushdata (numucat, ucat_ucid, numinpm, inpm_gdid, push_ucat2grid)
+ CALL build_compute_pushdata (numinpm, inpm_gdid, numinpm, inpm_gdid, allreduce_inpm)
+ ENDIF
+
+ CALL build_mpas_embedded_local_topology (parafile)
+
+ IF (p_is_compute) THEN
+ allocate (wts_ups (upnmax,numucat))
+ IF (numucat > 0) wts_ups(:,:) = 1._r8
+
+ CALL build_compute_pushdata (numucat, ucat_ucid, numucat, ucat_next, push_next2ucat)
+ CALL check_mpas_embedded_downstream_ownership ()
+ CALL build_compute_pushdata (numucat, ucat_ucid, numucat, ucat_ups, wts_ups, push_ups2ucat )
+ ENDIF
+
+ CALL build_mpas_embedded_river_systems (parafile)
+
+ CALL readin_riverlake_parameter (parafile, 'topo_rivelv', rdata1d = topo_rivelv )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivhgt', rdata1d = topo_rivhgt )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivlen', rdata1d = topo_rivlen )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivman', rdata1d = topo_rivman )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivwth', rdata1d = topo_rivwth )
+ CALL readin_riverlake_parameter (parafile, 'topo_rivstomax', rdata1d = topo_rivstomax)
+ CALL readin_riverlake_parameter (parafile, 'topo_area', rdata1d = topo_area )
+ CALL readin_riverlake_parameter (parafile, 'topo_fldhgt', rdata2d = topo_fldhgt )
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ allocate (lake_type (numucat))
+ lake_type(:) = 0
+
+ allocate (topo_rivare (numucat))
+ topo_rivare = topo_rivstomax / topo_rivhgt
+
+ allocate (floodplain_curve (numucat))
+ DO i = 1, numucat
+ floodplain_curve(i)%nlfp = size(topo_fldhgt,1)
+ floodplain_curve(i)%rivhgt = topo_rivhgt(i)
+ floodplain_curve(i)%rivstomax = topo_rivstomax(i)
+ floodplain_curve(i)%rivare = topo_rivare(i)
+
+ allocate (floodplain_curve(i)%flphgt (0:floodplain_curve(i)%nlfp))
+ allocate (floodplain_curve(i)%flparea (0:floodplain_curve(i)%nlfp))
+ allocate (floodplain_curve(i)%flpaccare (0:floodplain_curve(i)%nlfp))
+ allocate (floodplain_curve(i)%flpstomax (0:floodplain_curve(i)%nlfp))
+
+ floodplain_curve(i)%flphgt(0) = 0._r8
+ floodplain_curve(i)%flphgt(1:) = topo_fldhgt(:,i)
+
+ floodplain_curve(i)%flparea(0) = 0._r8
+ floodplain_curve(i)%flparea(1:) = topo_area(i) / floodplain_curve(i)%nlfp
+
+ floodplain_curve(i)%flpaccare(0) = 0._r8
+ DO j = 1, floodplain_curve(i)%nlfp
+ floodplain_curve(i)%flpaccare(j) = &
+ floodplain_curve(i)%flpaccare(j-1) + floodplain_curve(i)%flparea(j)
+ ENDDO
+
+ floodplain_curve(i)%flpstomax(0) = 0._r8
+ DO j = 1, floodplain_curve(i)%nlfp
+ floodplain_curve(i)%flpstomax(j) = floodplain_curve(i)%flpstomax(j-1) &
+ + 0.5_r8 * (floodplain_curve(i)%flparea(j) + floodplain_curve(i)%flparea(j-1)) &
+ * (floodplain_curve(i)%flphgt(j) - floodplain_curve(i)%flphgt(j-1))
+ ENDDO
+ ENDDO
+
+ allocate (bedelv_next (numucat))
+ allocate (outletwth (numucat))
+ ELSE
+ allocate (bedelv_next (0))
+ allocate (outletwth (0))
+ ENDIF
+ ENDIF
+
+ CALL compute_push_data (push_next2ucat, topo_rivelv, bedelv_next, fillvalue = spval)
+ CALL compute_push_data (push_next2ucat, topo_rivwth, outletwth , fillvalue = spval)
+
+ IF (p_is_compute) THEN
+ IF (numucat > 0) THEN
+ WHERE (ucat_next > 0)
+ outletwth = (outletwth + topo_rivwth) * 0.5_r8
+ ELSEWHERE
+ outletwth = topo_rivwth
+ END WHERE
+ ENDIF
+
+ allocate (allups_mask_ucat (numucat))
+ IF (numucat > 0) THEN
+ allups_mask_ucat(:) = 0._r8
+ WHERE (push_inpm2ucat%sum_area > 0._r8)
+ allups_mask_ucat = 1._r8
+ END WHERE
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE build_riverlake_network_mpas_embedded
+
+ ! ---------
+ SUBROUTINE build_mpas_embedded_river_systems (parafile)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: parafile
+
+ integer, allocatable :: mouth_id(:), next_id(:)
+ integer, allocatable :: request(:), request_order(:), request_next(:)
+ integer, allocatable :: local_mouths(:), all_mouths(:), global_mouths(:)
+#ifdef COLM_PARALLEL
+ integer, allocatable :: counts(:), displs(:)
+#endif
+ integer :: i, iloc, nactive, niter, nlocal_mouths, total_mouths
+ logical :: is_new
+
+ IF (.not. p_is_compute) RETURN
+
+ allocate (irivsys (numucat))
+ allocate (mouth_id (numucat))
+ allocate (local_mouths (max(1,numucat)))
+ mouth_id(:) = 0
+
+ IF (numucat > 0) THEN
+ allocate (next_id (numucat))
+ next_id = ucat_next
+
+ DO i = 1, numucat
+ IF (next_id(i) <= 0) THEN
+ mouth_id(i) = ucat_ucid(i)
+ ENDIF
+ ENDDO
+
+ nactive = count(next_id > 0)
+ niter = 0
+ DO WHILE (nactive > 0)
+ niter = niter + 1
+ IF (niter > totalnumucat) THEN
+ CALL CoLM_Stop ('ERROR: MPAS embedded CoLM river network has a downstream cycle.')
+ ENDIF
+
+ allocate (request (nactive))
+ allocate (request_order (nactive))
+ iloc = 0
+ DO i = 1, numucat
+ IF (next_id(i) > 0) THEN
+ iloc = iloc + 1
+ request(iloc) = next_id(i)
+ request_order(iloc) = i
+ ENDIF
+ ENDDO
+
+ CALL quicksort (nactive, request, request_order)
+ CALL ncio_read_indexed_serial (parafile, 'seq_next', request, request_next)
+
+ nactive = 0
+ DO iloc = 1, size(request)
+ i = request_order(iloc)
+ IF (request_next(iloc) > 0) THEN
+ next_id(i) = request_next(iloc)
+ nactive = nactive + 1
+ ELSE
+ mouth_id(i) = request(iloc)
+ next_id(i) = 0
+ ENDIF
+ ENDDO
+
+ deallocate (request)
+ deallocate (request_order)
+ deallocate (request_next)
+ ENDDO
+
+ deallocate (next_id)
+ ENDIF
+
+ nlocal_mouths = 0
+ DO i = 1, numucat
+ CALL insert_into_sorted_list1 (mouth_id(i), nlocal_mouths, local_mouths, iloc, is_new)
+ ENDDO
+
+#ifdef COLM_PARALLEL
+ allocate (counts (0:p_np_compute-1))
+ allocate (displs (0:p_np_compute-1))
+ CALL mpi_allgather (nlocal_mouths, 1, MPI_INTEGER, counts, 1, MPI_INTEGER, p_comm_compute, p_err)
+
+ displs(0) = 0
+ DO i = 1, p_np_compute-1
+ displs(i) = displs(i-1) + counts(i-1)
+ ENDDO
+ total_mouths = sum(counts)
+
+ allocate (all_mouths (max(1,total_mouths)))
+ CALL mpi_allgatherv (local_mouths, nlocal_mouths, MPI_INTEGER, all_mouths, counts, displs, &
+ MPI_INTEGER, p_comm_compute, p_err)
+
+ allocate (global_mouths (max(1,total_mouths)))
+ numrivsys = 0
+ DO i = 1, total_mouths
+ CALL insert_into_sorted_list1 (all_mouths(i), numrivsys, global_mouths, iloc, is_new)
+ ENDDO
+
+ p_comm_rivsys = p_comm_compute
+ rivsys_by_multiple_procs = p_np_compute > 1
+
+ deallocate (counts)
+ deallocate (displs)
+ deallocate (all_mouths)
+#else
+ total_mouths = nlocal_mouths
+ allocate (global_mouths (max(1,total_mouths)))
+ numrivsys = nlocal_mouths
+ IF (numrivsys > 0) global_mouths(1:numrivsys) = local_mouths(1:numrivsys)
+ rivsys_by_multiple_procs = .false.
+#endif
+
+ DO i = 1, numucat
+ irivsys(i) = find_in_sorted_list1 (mouth_id(i), numrivsys, global_mouths(1:numrivsys))
+ IF (irivsys(i) <= 0) CALL CoLM_Stop ('ERROR: MPAS embedded CoLM river-system map is incomplete.')
+ ENDDO
+
+ deallocate (mouth_id)
+ deallocate (local_mouths)
+ deallocate (global_mouths)
+
+ END SUBROUTINE build_mpas_embedded_river_systems
+
+ ! ---------
+ SUBROUTINE build_mpas_embedded_local_ucats (parafile, nlon_ucat, numinpm, inpm_gdid)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: parafile
+ integer, intent(in) :: nlon_ucat
+ integer, intent(in) :: numinpm
+ integer, intent(in) :: inpm_gdid(:)
+
+ integer, parameter :: ucat_chunk_size = 131072
+ integer, allocatable :: inpm_sorted(:), inpm_order(:)
+ integer, allocatable :: seq_x_blk(:), seq_y_blk(:)
+ integer :: istart, iend, iucat, iloc, grid_id, nfound
+
+ IF (.not. p_is_compute) RETURN
+
+ IF (numinpm > 0) THEN
+ allocate (inpm_sorted (numinpm))
+ allocate (inpm_order (numinpm))
+ inpm_sorted = inpm_gdid
+ inpm_order = (/(iucat, iucat = 1, numinpm)/)
+ CALL quicksort (numinpm, inpm_sorted, inpm_order)
+
+ nfound = 0
+ istart = 1
+ DO WHILE (istart <= totalnumucat)
+ iend = min(istart + ucat_chunk_size - 1, totalnumucat)
+ CALL ncio_read_part_serial (parafile, 'seq_x', istart, iend, seq_x_blk)
+ CALL ncio_read_part_serial (parafile, 'seq_y', istart, iend, seq_y_blk)
+
+ DO iucat = lbound(seq_x_blk,1), ubound(seq_x_blk,1)
+ IF (seq_x_blk(iucat) > 0 .and. seq_y_blk(iucat) > 0) THEN
+ grid_id = (seq_y_blk(iucat)-1) * nlon_ucat + seq_x_blk(iucat)
+ iloc = find_in_sorted_list1 (grid_id, numinpm, inpm_sorted)
+ IF (iloc > 0) nfound = nfound + 1
+ ENDIF
+ ENDDO
+
+ deallocate (seq_x_blk)
+ deallocate (seq_y_blk)
+ istart = iend + 1
+ ENDDO
+ ELSE
+ nfound = 0
+ ENDIF
+
+ numucat = nfound
+ allocate (ucat_ucid (numucat))
+ allocate (x_ucat (numucat))
+ allocate (y_ucat (numucat))
+ allocate (ucat_gdid (numucat))
+
+ IF (numinpm > 0 .and. numucat > 0) THEN
+ nfound = 0
+ istart = 1
+ DO WHILE (istart <= totalnumucat)
+ iend = min(istart + ucat_chunk_size - 1, totalnumucat)
+ CALL ncio_read_part_serial (parafile, 'seq_x', istart, iend, seq_x_blk)
+ CALL ncio_read_part_serial (parafile, 'seq_y', istart, iend, seq_y_blk)
+
+ DO iucat = lbound(seq_x_blk,1), ubound(seq_x_blk,1)
+ IF (seq_x_blk(iucat) > 0 .and. seq_y_blk(iucat) > 0) THEN
+ grid_id = (seq_y_blk(iucat)-1) * nlon_ucat + seq_x_blk(iucat)
+ iloc = find_in_sorted_list1 (grid_id, numinpm, inpm_sorted)
+ IF (iloc > 0) THEN
+ nfound = nfound + 1
+ ucat_ucid(nfound) = iucat
+ x_ucat(nfound) = seq_x_blk(iucat)
+ y_ucat(nfound) = seq_y_blk(iucat)
+ ucat_gdid(nfound) = grid_id
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (seq_x_blk)
+ deallocate (seq_y_blk)
+ istart = iend + 1
+ ENDDO
+ ENDIF
+
+ IF (allocated(inpm_sorted)) deallocate (inpm_sorted)
+ IF (allocated(inpm_order )) deallocate (inpm_order )
+
+ END SUBROUTINE build_mpas_embedded_local_ucats
+
+ SUBROUTINE build_mpas_embedded_local_topology (parafile)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: parafile
+
+ integer, parameter :: ucat_chunk_size = 131072
+ integer, allocatable :: ucat_sorted(:), ucat_order(:), ups_count(:), ups_fill(:)
+ integer, allocatable :: seq_next_blk(:)
+ integer :: istart, iend, iucat, iloc, idn, local_upnmax
+
+ IF (.not. p_is_compute) RETURN
+
+ IF (numucat > 0) THEN
+ CALL ncio_read_indexed_serial (parafile, 'seq_next', ucat_ucid, ucat_next)
+
+ allocate (ucat_sorted (numucat))
+ allocate (ucat_order (numucat))
+ allocate (ups_count (numucat))
+
+ ucat_sorted = ucat_ucid
+ ucat_order = (/(iucat, iucat = 1, numucat)/)
+ CALL quicksort (numucat, ucat_sorted, ucat_order)
+
+ ups_count(:) = 0
+ istart = 1
+ DO WHILE (istart <= totalnumucat)
+ iend = min(istart + ucat_chunk_size - 1, totalnumucat)
+ CALL ncio_read_part_serial (parafile, 'seq_next', istart, iend, seq_next_blk)
+
+ DO iucat = lbound(seq_next_blk,1), ubound(seq_next_blk,1)
+ idn = seq_next_blk(iucat)
+ IF (idn > 0) THEN
+ iloc = find_in_sorted_list1 (idn, numucat, ucat_sorted)
+ IF (iloc > 0) ups_count(ucat_order(iloc)) = ups_count(ucat_order(iloc)) + 1
+ ENDIF
+ ENDDO
+
+ deallocate (seq_next_blk)
+ istart = iend + 1
+ ENDDO
+
+ local_upnmax = maxval(ups_count)
+ ELSE
+ allocate (ucat_next (0))
+ local_upnmax = 0
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_allreduce (local_upnmax, upnmax, 1, MPI_INTEGER, MPI_MAX, p_comm_compute, p_err)
+#else
+ upnmax = local_upnmax
+#endif
+ upnmax = max(1, upnmax)
+
+ allocate (ucat_ups (upnmax,numucat))
+ ucat_ups(:,:) = 0
+
+ IF (numucat > 0) THEN
+ allocate (ups_fill (numucat))
+ ups_fill(:) = 0
+
+ istart = 1
+ DO WHILE (istart <= totalnumucat)
+ iend = min(istart + ucat_chunk_size - 1, totalnumucat)
+ CALL ncio_read_part_serial (parafile, 'seq_next', istart, iend, seq_next_blk)
+
+ DO iucat = lbound(seq_next_blk,1), ubound(seq_next_blk,1)
+ idn = seq_next_blk(iucat)
+ IF (idn > 0) THEN
+ iloc = find_in_sorted_list1 (idn, numucat, ucat_sorted)
+ IF (iloc > 0) THEN
+ ups_fill(ucat_order(iloc)) = ups_fill(ucat_order(iloc)) + 1
+ ucat_ups(ups_fill(ucat_order(iloc)), ucat_order(iloc)) = iucat
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (seq_next_blk)
+ istart = iend + 1
+ ENDDO
+
+ deallocate (ups_fill)
+ deallocate (ups_count)
+ deallocate (ucat_sorted)
+ deallocate (ucat_order)
+ ENDIF
+
+ END SUBROUTINE build_mpas_embedded_local_topology
+
+ ! ---------
+ SUBROUTINE check_mpas_embedded_downstream_ownership ()
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ logical, allocatable :: id_found(:)
+ integer :: i, irank, ireq
+ integer :: local_missing, global_missing
+ integer :: first_missing, global_first_missing
+
+ IF (.not. p_is_compute) RETURN
+
+ local_missing = 0
+ first_missing = huge(1)
+
+ IF (numucat > 0 .and. push_next2ucat%num_req_uniq > 0) THEN
+ allocate (id_found (push_next2ucat%num_req_uniq))
+ id_found(:) = .false.
+
+ IF (push_next2ucat%nself > 0) id_found(push_next2ucat%self_to) = .true.
+
+#ifdef COLM_PARALLEL
+ DO irank = 0, p_np_compute-1
+ IF (push_next2ucat%n_from_other(irank) > 0) THEN
+ id_found(push_next2ucat%other_to(irank)%val) = .true.
+ ENDIF
+ ENDDO
+#endif
+
+ DO i = 1, numucat
+ IF (ucat_next(i) > 0) THEN
+ ireq = push_next2ucat%addr_single(i)
+ IF (ireq <= 0 .or. .not. id_found(ireq)) THEN
+ local_missing = local_missing + 1
+ first_missing = min(first_missing, ucat_next(i))
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (id_found)
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_allreduce (local_missing, global_missing, 1, MPI_INTEGER, MPI_SUM, p_comm_compute, p_err)
+ CALL mpi_allreduce (first_missing, global_first_missing, 1, MPI_INTEGER, MPI_MIN, p_comm_compute, p_err)
+#else
+ global_missing = local_missing
+ global_first_missing = first_missing
+#endif
+
+ IF (global_missing > 0) THEN
+ IF (p_is_root) THEN
+ write(*,'(A,I0,A,I0)') 'ERROR: MPAS embedded CoLM GridRiverLakeFlow is missing ', &
+ global_missing, ' downstream unit-catchment owner(s); first missing seq_next = ', &
+ global_first_missing
+ ENDIF
+ CALL CoLM_Stop ('ERROR: MPAS embedded CoLM river network ownership is incomplete.')
+ ENDIF
+
+ END SUBROUTINE check_mpas_embedded_downstream_ownership
+
+ ! ---------
+ SUBROUTINE build_mpas_embedded_uc2gd (parafile, nlon_ucat, inpn, numinpm, inpm_gdid, &
+ nucpart, idmap_uc2gd, area_uc2gd)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: parafile
+ integer, intent(in) :: nlon_ucat
+ integer, intent(in) :: inpn
+ integer, intent(in) :: numinpm
+ integer, intent(in) :: inpm_gdid(:)
+ integer, intent(out) :: nucpart
+ integer, allocatable, intent(out) :: idmap_uc2gd(:,:)
+ real(r8), allocatable, intent(out) :: area_uc2gd(:,:)
+
+ integer, parameter :: ucat_chunk_size = 131072
+ integer, allocatable :: inpm_sorted(:), inpm_order(:), nucat_g(:)
+ integer, allocatable :: idmap_x_blk(:,:), idmap_y_blk(:,:)
+ real(r8), allocatable :: area_blk(:,:)
+ integer :: istart, iend, iucat, imap, iloc, igrd, grid_id
+ integer :: nucpart_local
+
+ IF (numinpm > 0) THEN
+ allocate (inpm_sorted (numinpm))
+ allocate (inpm_order (numinpm))
+ allocate (nucat_g (numinpm))
+
+ inpm_sorted = inpm_gdid
+ inpm_order = (/(igrd, igrd = 1, numinpm)/)
+ CALL quicksort (numinpm, inpm_sorted, inpm_order)
+ nucat_g = 0
+
+ istart = 1
+ DO WHILE (istart <= totalnumucat)
+ iend = min(istart + ucat_chunk_size - 1, totalnumucat)
+ CALL ncio_read_part_serial (parafile, 'inpmat_x', (/1,istart/), (/inpn,iend/), idmap_x_blk)
+ CALL ncio_read_part_serial (parafile, 'inpmat_y', (/1,istart/), (/inpn,iend/), idmap_y_blk)
+ CALL ncio_read_part_serial (parafile, 'inpmat_area', (/1,istart/), (/inpn,iend/), area_blk)
+
+ DO iucat = lbound(idmap_x_blk,2), ubound(idmap_x_blk,2)
+ DO imap = 1, inpn
+ IF (area_blk(imap,iucat) > 0._r8 .and. idmap_x_blk(imap,iucat) > 0 .and. &
+ idmap_y_blk(imap,iucat) > 0) THEN
+ grid_id = (idmap_y_blk(imap,iucat)-1) * nlon_ucat + idmap_x_blk(imap,iucat)
+ iloc = find_in_sorted_list1 (grid_id, numinpm, inpm_sorted)
+ IF (iloc > 0) THEN
+ igrd = inpm_order(iloc)
+ nucat_g(igrd) = nucat_g(igrd) + 1
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (idmap_x_blk)
+ deallocate (idmap_y_blk)
+ deallocate (area_blk)
+ istart = iend + 1
+ ENDDO
+
+ nucpart_local = maxval(nucat_g)
+ ELSE
+ nucpart_local = 0
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_allreduce (nucpart_local, nucpart, 1, MPI_INTEGER, MPI_MAX, p_comm_glb, p_err)
+#else
+ nucpart = nucpart_local
+#endif
+ nucpart = max(1, nucpart)
+
+ allocate (idmap_uc2gd (nucpart,numinpm))
+ allocate (area_uc2gd (nucpart,numinpm))
+ idmap_uc2gd = 0
+ area_uc2gd = 0._r8
+
+ IF (numinpm > 0 .and. nucpart > 0) THEN
+ nucat_g = 0
+
+ istart = 1
+ DO WHILE (istart <= totalnumucat)
+ iend = min(istart + ucat_chunk_size - 1, totalnumucat)
+ CALL ncio_read_part_serial (parafile, 'inpmat_x', (/1,istart/), (/inpn,iend/), idmap_x_blk)
+ CALL ncio_read_part_serial (parafile, 'inpmat_y', (/1,istart/), (/inpn,iend/), idmap_y_blk)
+ CALL ncio_read_part_serial (parafile, 'inpmat_area', (/1,istart/), (/inpn,iend/), area_blk)
+
+ DO iucat = lbound(idmap_x_blk,2), ubound(idmap_x_blk,2)
+ DO imap = 1, inpn
+ IF (area_blk(imap,iucat) > 0._r8 .and. idmap_x_blk(imap,iucat) > 0 .and. &
+ idmap_y_blk(imap,iucat) > 0) THEN
+ grid_id = (idmap_y_blk(imap,iucat)-1) * nlon_ucat + idmap_x_blk(imap,iucat)
+ iloc = find_in_sorted_list1 (grid_id, numinpm, inpm_sorted)
+ IF (iloc > 0) THEN
+ igrd = inpm_order(iloc)
+ nucat_g(igrd) = nucat_g(igrd) + 1
+ idmap_uc2gd(nucat_g(igrd),igrd) = iucat
+ area_uc2gd (nucat_g(igrd),igrd) = area_blk(imap,iucat)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (idmap_x_blk)
+ deallocate (idmap_y_blk)
+ deallocate (area_blk)
+ istart = iend + 1
+ ENDDO
+ ENDIF
+
+ IF (allocated(inpm_sorted)) deallocate (inpm_sorted)
+ IF (allocated(inpm_order )) deallocate (inpm_order )
+ IF (allocated(nucat_g )) deallocate (nucat_g )
+
+ END SUBROUTINE build_mpas_embedded_uc2gd
+#endif
+
+ ! ---------
+ SUBROUTINE readin_riverlake_parameter (parafile, varname, rdata1d, rdata2d, idata1d)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: parafile
+ character(len=*), intent(in) :: varname
+
+ real(r8), allocatable, intent(inout), optional :: rdata1d (:)
+ real(r8), allocatable, intent(inout), optional :: rdata2d (:,:)
+ integer, allocatable, intent(inout), optional :: idata1d (:)
+
+ ! Local Variables
+ integer :: irank, nucat, ndim1, i
+ real(r8), allocatable :: rsend1d (:)
+ real(r8), allocatable :: rsend2d (:,:)
+ integer, allocatable :: isend1d (:)
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_compute) THEN
+ IF (present(rdata1d)) CALL ncio_read_indexed_serial (parafile, varname, ucat_ucid, rdata1d)
+ IF (present(rdata2d)) CALL ncio_read_indexed_serial (parafile, varname, ucat_ucid, rdata2d)
+ IF (present(idata1d)) CALL ncio_read_indexed_serial (parafile, varname, ucat_ucid, idata1d)
+ ENDIF
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ RETURN
+#endif
+
+ IF (p_is_root) THEN
+ IF (present(rdata1d)) CALL ncio_read_serial (parafile, varname, rdata1d)
+ IF (present(rdata2d)) CALL ncio_read_serial (parafile, varname, rdata2d)
+ IF (present(idata1d)) CALL ncio_read_serial (parafile, varname, idata1d)
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (present(rdata2d)) THEN
+ IF (p_is_root) ndim1 = size(rdata2d,1)
+ CALL mpi_bcast (ndim1, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ ENDIF
+
+ ! send unit catchment index to ranks
+ IF (p_is_root) THEN
+
+ DO irank = 0, p_np_compute-1
+
+ nucat = numucat_rank(irank)
+
+ IF (nucat > 0) THEN
+ IF (present(rdata1d)) THEN
+ allocate (rsend1d (nucat))
+
+ rsend1d = rdata1d(ucat_data_address(irank)%val)
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ IF (allocated(rdata1d)) deallocate(rdata1d)
+ allocate (rdata1d (nucat))
+ rdata1d = rsend1d
+ ELSE
+ CALL mpi_send (rsend1d, nucat, MPI_REAL8, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ deallocate (rsend1d)
+ ENDIF
+
+ IF (present(rdata2d)) THEN
+ allocate (rsend2d (ndim1,nucat))
+
+ DO i = 1, nucat
+ rsend2d(:,i) = rdata2d(:,ucat_data_address(irank)%val(i))
+ ENDDO
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ IF (allocated(rdata2d)) deallocate(rdata2d)
+ allocate (rdata2d (ndim1,nucat))
+ rdata2d = rsend2d
+ ELSE
+ CALL mpi_send (rsend2d, ndim1*nucat, MPI_REAL8, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ deallocate (rsend2d)
+ ENDIF
+
+ IF (present(idata1d)) THEN
+ allocate (isend1d (nucat))
+
+ isend1d = idata1d(ucat_data_address(irank)%val)
+ IF (p_address_compute(irank) == p_iam_glb) THEN
+ IF (allocated(idata1d)) deallocate(idata1d)
+ allocate (idata1d (nucat))
+ idata1d = isend1d
+ ELSE
+ CALL mpi_send (isend1d, nucat, MPI_INTEGER, p_address_compute(irank), &
+ mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ deallocate (isend1d)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ IF (.not. p_is_compute) THEN
+ IF (present(rdata1d)) deallocate (rdata1d)
+ IF (present(rdata2d)) deallocate (rdata2d)
+ IF (present(idata1d)) deallocate (idata1d)
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+
+ IF (numucat > 0) THEN
+ IF (present(rdata1d)) THEN
+ allocate (rdata1d (numucat))
+ CALL mpi_recv (rdata1d, numucat, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ IF (present(rdata2d)) THEN
+ allocate (rdata2d (ndim1,numucat))
+ CALL mpi_recv (rdata2d, ndim1*numucat, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ IF (present(idata1d)) THEN
+ allocate (idata1d (numucat))
+ CALL mpi_recv (idata1d, numucat, MPI_INTEGER, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_compute .and. numucat == 0) THEN
+ IF (present(rdata1d)) THEN
+ IF (.not. allocated(rdata1d)) allocate (rdata1d (0))
+ ENDIF
+ IF (present(rdata2d)) THEN
+ IF (.not. allocated(rdata2d)) allocate (rdata2d (ndim1,0))
+ ENDIF
+ IF (present(idata1d)) THEN
+ IF (.not. allocated(idata1d)) allocate (idata1d (0))
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE readin_riverlake_parameter
+
+ !
+ FUNCTION retrieve_depth_from_volume (this, volume) result(depth)
+
+ IMPLICIT NONE
+
+ class(vol_dep_curve_type) :: this
+ real(r8), intent(in) :: volume
+ real(r8) :: depth
+
+ ! Local Variables
+ real(r8) :: v0, g
+ integer :: i
+
+ v0 = volume - this%rivstomax
+ IF (v0 <= 0) THEN
+ depth = volume / this%rivare
+ ELSE
+ i = 1
+ DO WHILE (i <= this%nlfp)
+ IF (v0 > this%flpstomax(i)) THEN
+ i = i + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ IF (i == this%nlfp+1) THEN
+ depth = this%rivhgt + this%flphgt(this%nlfp) &
+ + (v0-this%flpstomax(this%nlfp)) / this%flpaccare(this%nlfp)
+ ELSE
+ g = (this%flphgt(i)-this%flphgt(i-1))/this%flparea(i)
+ depth = this%rivhgt + this%flphgt(i-1) &
+ + g * (-this%flpaccare(i-1)+sqrt((this%flpaccare(i-1))**2+2*(v0-this%flpstomax(i-1))/g))
+ ENDIF
+ ENDIF
+
+ END FUNCTION retrieve_depth_from_volume
+
+ !
+ FUNCTION retrieve_volume_from_depth (this, depth) result(volume)
+
+ IMPLICIT NONE
+
+ class(vol_dep_curve_type) :: this
+ real(r8), intent(in) :: depth
+ real(r8) :: volume
+
+ ! Local Variables
+ real(r8) :: h, d
+ integer :: i
+
+ IF (depth <= this%rivhgt) THEN
+ volume = this%rivare * depth
+ ELSE
+ i = 1
+ DO WHILE (i <= this%nlfp)
+ IF (depth > this%rivhgt+this%flphgt(i)) THEN
+ i = i + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ d = depth - this%rivhgt - this%flphgt(i-1)
+ IF (i == this%nlfp+1) THEN
+ volume = this%rivstomax + this%flpstomax(this%nlfp) + d * this%flpaccare(this%nlfp)
+ ELSE
+ h = this%flphgt(i)-this%flphgt(i-1)
+ volume = this%rivstomax + this%flpstomax(i-1) &
+ + (d/h*this%flparea(i)+2*this%flpaccare(i-1))*d*0.5
+ ENDIF
+ ENDIF
+
+ END FUNCTION retrieve_volume_from_depth
+
+ !
+ FUNCTION retrieve_area_from_depth (this, depth) result(area)
+
+ IMPLICIT NONE
+
+ class(vol_dep_curve_type) :: this
+ real(r8), intent(in) :: depth
+ real(r8) :: area
+
+ ! Local Variables
+ real(r8) :: h, d
+ integer :: i
+
+ IF (depth <= this%rivhgt) THEN
+ area = 0.
+ ELSE
+ i = 1
+ DO WHILE (i <= this%nlfp)
+ IF (depth > this%rivhgt+this%flphgt(i)) THEN
+ i = i + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ IF (i == this%nlfp+1) THEN
+ area = this%flpaccare(this%nlfp)
+ ELSE
+ h = this%flphgt(i)-this%flphgt(i-1)
+ d = depth - this%rivhgt - this%flphgt(i-1)
+ area = this%flpaccare(i-1) + d/h * this%flparea(i)
+ ENDIF
+ ENDIF
+
+ END FUNCTION retrieve_area_from_depth
+
+ ! ---
+ SUBROUTINE vol_depth_curve_free_mem (this)
+
+ IMPLICIT NONE
+ type(vol_dep_curve_type) :: this
+
+ IF (allocated(this%flphgt )) deallocate (this%flphgt )
+ IF (allocated(this%flparea )) deallocate (this%flparea )
+ IF (allocated(this%flpaccare)) deallocate (this%flpaccare)
+ IF (allocated(this%flpstomax)) deallocate (this%flpstomax)
+
+ END SUBROUTINE vol_depth_curve_free_mem
+
+ ! ---------
+ SUBROUTINE riverlake_network_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(x_ucat )) deallocate(x_ucat )
+ IF (allocated(y_ucat )) deallocate(y_ucat )
+
+ IF (allocated(ucat_ucid )) deallocate(ucat_ucid )
+ IF (allocated(ucat_gdid )) deallocate(ucat_gdid )
+
+ IF (allocated(numucat_rank )) deallocate(numucat_rank )
+ IF (allocated(ucat_data_address)) deallocate(ucat_data_address)
+
+ IF (allocated(inpm_gdid )) deallocate(inpm_gdid )
+ IF (allocated(idmap_gd2uc )) deallocate(idmap_gd2uc )
+ IF (allocated(area_gd2uc )) deallocate(area_gd2uc )
+ IF (allocated(idmap_uc2gd )) deallocate(idmap_uc2gd )
+ IF (allocated(area_uc2gd )) deallocate(area_uc2gd )
+ IF (allocated(ucat_next )) deallocate(ucat_next )
+ IF (allocated(ucat_ups )) deallocate(ucat_ups )
+ IF (allocated(irivsys )) deallocate(irivsys )
+
+ IF (allocated(topo_rivelv )) deallocate(topo_rivelv )
+ IF (allocated(topo_rivhgt )) deallocate(topo_rivhgt )
+ IF (allocated(topo_rivlen )) deallocate(topo_rivlen )
+ IF (allocated(topo_rivman )) deallocate(topo_rivman )
+ IF (allocated(topo_rivwth )) deallocate(topo_rivwth )
+ IF (allocated(topo_rivare )) deallocate(topo_rivare )
+ IF (allocated(topo_rivstomax )) deallocate(topo_rivstomax )
+ IF (allocated(topo_area )) deallocate(topo_area )
+ IF (allocated(topo_fldhgt )) deallocate(topo_fldhgt )
+ IF (allocated(bedelv_next )) deallocate(bedelv_next )
+ IF (allocated(outletwth )) deallocate(outletwth )
+
+ IF (allocated(floodplain_curve )) deallocate(floodplain_curve )
+
+ IF (allocated(allups_mask_ucat )) deallocate(allups_mask_ucat )
+
+ END SUBROUTINE riverlake_network_final
+
+END MODULE MOD_Grid_RiverLakeNetwork
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeTimeVars.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeTimeVars.F90
new file mode 100644
index 0000000000..69c329d91f
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Grid_RiverLakeTimeVars.F90
@@ -0,0 +1,287 @@
+#include
+
+#ifdef GridRiverLakeFlow
+MODULE MOD_Grid_RiverLakeTimeVars
+!-------------------------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Time Variables in gridded hydrological processes.
+!
+! Created by Shupeng Zhang, Oct 2025
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+#ifdef GridRiverLakeSediment
+ USE MOD_Grid_RiverLakeSediment, only: write_sediment_restart
+#endif
+ IMPLICIT NONE
+
+ ! -- state variables --
+ real(r8), allocatable :: wdsrf_ucat (:) ! river or lake water depth [m]
+ real(r8), allocatable :: veloc_riv (:) ! river velocity [m/s]
+ real(r8), allocatable :: momen_riv (:) ! unit river momentum [m^2/s]
+ real(r8), allocatable :: volresv (:) ! reservoir water volume [m^3]
+
+ ! -- restart file path (saved for deferred sediment restart read) --
+ character(len=512) :: gridriver_restart_file = ''
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_GridRiverLakeTimeVars
+ PUBLIC :: deallocate_GridRiverLakeTimeVars
+
+ PUBLIC :: read_GridRiverLakeTimeVars
+ PUBLIC :: write_GridRiverLakeTimeVars
+
+CONTAINS
+
+ SUBROUTINE allocate_GridRiverLakeTimeVars
+
+ USE MOD_SPMD_Task
+ USE MOD_Grid_RiverLakeNetwork, only: numucat
+ USE MOD_Grid_Reservoir, only: numresv
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ allocate (wdsrf_ucat (numucat))
+ allocate (veloc_riv (numucat))
+ allocate (momen_riv (numucat))
+ allocate (volresv (numresv))
+
+ ENDIF
+
+ END SUBROUTINE allocate_GridRiverLakeTimeVars
+
+
+ SUBROUTINE READ_GridRiverLakeTimeVars (file_restart)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Vector_ReadWrite
+#ifdef MPAS_EMBEDDED_COLM
+ USE MOD_NetCDFSerial, only: ncio_read_indexed_serial
+ USE MOD_Grid_RiverLakeNetwork, only: numucat, ucat_ucid
+ USE MOD_Grid_Reservoir, only: numresv, totalnumresv, resv_global_index
+#else
+ USE MOD_Grid_RiverLakeNetwork, only: numucat, ucat_data_address
+ USE MOD_Grid_Reservoir, only: numresv, resv_data_address, totalnumresv
+#endif
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ gridriver_restart_file = trim(file_restart)
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_compute .and. numucat > 0) THEN
+ CALL ncio_read_indexed_serial (file_restart, 'wdsrf_ucat', ucat_ucid, wdsrf_ucat)
+ CALL ncio_read_indexed_serial (file_restart, 'veloc_riv', ucat_ucid, veloc_riv )
+ ENDIF
+#else
+ CALL vector_read_and_scatter (file_restart, wdsrf_ucat, numucat, 'wdsrf_ucat', ucat_data_address)
+ CALL vector_read_and_scatter (file_restart, veloc_riv, numucat, 'veloc_riv', ucat_data_address)
+#endif
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (totalnumresv > 0) THEN
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_compute .and. numresv > 0) THEN
+ CALL ncio_read_indexed_serial (file_restart, 'volresv', resv_global_index, volresv)
+ ENDIF
+#else
+ CALL vector_read_and_scatter (file_restart, volresv, numresv, 'volresv', resv_data_address)
+#endif
+ ENDIF
+ ENDIF
+
+ ! Note: sediment restart is read separately in grid_sediment_read_restart,
+ ! called from grid_riverlake_flow_init after sediment module is initialized.
+
+ END SUBROUTINE READ_GridRiverLakeTimeVars
+
+
+ SUBROUTINE WRITE_GridRiverLakeTimeVars (file_restart)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+#ifndef MPAS_EMBEDDED_COLM
+ USE MOD_NetCDFSerial
+ USE MOD_Vector_ReadWrite
+ USE MOD_Grid_RiverLakeNetwork, only: numucat, totalnumucat, ucat_data_address
+ USE MOD_Grid_Reservoir, only: numresv, totalnumresv, resv_data_address
+#endif
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL write_gridriver_restart_mpas_embedded (file_restart)
+#else
+ IF (p_is_root) THEN
+ CALL ncio_create_file (trim(file_restart))
+ CALL ncio_define_dimension(file_restart, 'ucatch', totalnumucat)
+ ENDIF
+
+ CALL vector_gather_and_write (&
+ wdsrf_ucat, numucat, totalnumucat, ucat_data_address, file_restart, 'wdsrf_ucat', 'ucatch')
+
+ CALL vector_gather_and_write (&
+ veloc_riv, numucat, totalnumucat, ucat_data_address, file_restart, 'veloc_riv', 'ucatch')
+
+ IF (DEF_Reservoir_Method > 0) THEN
+ IF (totalnumresv > 0) THEN
+
+ IF (p_is_root) CALL ncio_define_dimension(file_restart, 'reservoir', totalnumresv)
+
+ CALL vector_gather_and_write (&
+ volresv, numresv, totalnumresv, resv_data_address, file_restart, 'volresv', 'reservoir')
+ ENDIF
+ ENDIF
+#endif
+
+#ifdef GridRiverLakeSediment
+ IF (DEF_USE_SEDIMENT) THEN
+ CALL write_sediment_restart(file_restart)
+ ENDIF
+#endif
+
+ END SUBROUTINE WRITE_GridRiverLakeTimeVars
+
+#ifdef MPAS_EMBEDDED_COLM
+ SUBROUTINE write_gridriver_restart_mpas_embedded (file_restart)
+
+ USE mpi, only: MPI_INFO_NULL, MPI_OFFSET_KIND
+ USE pnetcdf
+ USE MOD_SPMD_Task, only: p_comm_compute
+ USE MOD_Namelist, only: DEF_Reservoir_Method
+ USE MOD_Grid_RiverLakeNetwork, only: numucat, totalnumucat, ucat_ucid
+ USE MOD_Grid_Reservoir, only: numresv, totalnumresv, resv_global_index
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ integer :: ierr
+ integer :: ncid
+ integer :: dim_ucatch
+ integer :: dim_reservoir
+ integer :: var_wdsrf
+ integer :: var_veloc
+ integer :: var_volresv
+ logical :: write_reservoir
+
+ write_reservoir = DEF_Reservoir_Method > 0 .and. totalnumresv > 0
+
+ ierr = nf90mpi_create(p_comm_compute, trim(file_restart), &
+ IOR(NF90_CLOBBER, NF90_64BIT_OFFSET), MPI_INFO_NULL, ncid)
+ CALL pnetcdf_check(ierr, 'create', file_restart)
+
+ ierr = nf90mpi_def_dim(ncid, 'ucatch', int(totalnumucat, MPI_OFFSET_KIND), dim_ucatch)
+ CALL pnetcdf_check(ierr, 'define ucatch dimension', file_restart)
+
+ ierr = nf90mpi_def_var(ncid, 'wdsrf_ucat', NF90_DOUBLE, (/dim_ucatch/), var_wdsrf)
+ CALL pnetcdf_check(ierr, 'define wdsrf_ucat', file_restart)
+
+ ierr = nf90mpi_def_var(ncid, 'veloc_riv', NF90_DOUBLE, (/dim_ucatch/), var_veloc)
+ CALL pnetcdf_check(ierr, 'define veloc_riv', file_restart)
+
+ IF (write_reservoir) THEN
+ ierr = nf90mpi_def_dim(ncid, 'reservoir', int(totalnumresv, MPI_OFFSET_KIND), dim_reservoir)
+ CALL pnetcdf_check(ierr, 'define reservoir dimension', file_restart)
+
+ ierr = nf90mpi_def_var(ncid, 'volresv', NF90_DOUBLE, (/dim_reservoir/), var_volresv)
+ CALL pnetcdf_check(ierr, 'define volresv', file_restart)
+ ENDIF
+
+ ierr = nf90mpi_enddef(ncid)
+ CALL pnetcdf_check(ierr, 'end define mode', file_restart)
+
+ ierr = nf90mpi_begin_indep_data(ncid)
+ CALL pnetcdf_check(ierr, 'begin independent data mode', file_restart)
+
+ CALL pnetcdf_write_real8_points(ncid, var_wdsrf, ucat_ucid, wdsrf_ucat, numucat, &
+ 'wdsrf_ucat', file_restart)
+ CALL pnetcdf_write_real8_points(ncid, var_veloc, ucat_ucid, veloc_riv, numucat, &
+ 'veloc_riv', file_restart)
+
+ IF (write_reservoir) THEN
+ CALL pnetcdf_write_real8_points(ncid, var_volresv, resv_global_index, volresv, numresv, &
+ 'volresv', file_restart)
+ ENDIF
+
+ ierr = nf90mpi_end_indep_data(ncid)
+ CALL pnetcdf_check(ierr, 'end independent data mode', file_restart)
+
+ ierr = nf90mpi_close(ncid)
+ CALL pnetcdf_check(ierr, 'close', file_restart)
+
+ END SUBROUTINE write_gridriver_restart_mpas_embedded
+
+ SUBROUTINE pnetcdf_write_real8_points(ncid, varid, index, data, ndata, varname, filename)
+
+ USE mpi, only: MPI_OFFSET_KIND
+ USE pnetcdf, only: nf90mpi_put_var
+ USE MOD_SPMD_Task, only: CoLM_stop
+ IMPLICIT NONE
+
+ integer, intent(in) :: ncid
+ integer, intent(in) :: varid
+ integer, intent(in) :: index(:)
+ real(r8), intent(in) :: data(:)
+ integer, intent(in) :: ndata
+ character(len=*), intent(in) :: varname
+ character(len=*), intent(in) :: filename
+
+ integer :: ierr
+ integer :: i
+ integer(kind=MPI_OFFSET_KIND) :: start(1)
+ real(r8) :: value
+
+ IF (ndata > size(index) .or. ndata > size(data)) THEN
+ CALL CoLM_stop('PnetCDF indexed write size mismatch for '//trim(varname))
+ ENDIF
+
+ DO i = 1, ndata
+ IF (index(i) < 1) THEN
+ CALL CoLM_stop('PnetCDF indexed write invalid index for '//trim(varname))
+ ENDIF
+
+ start(1) = int(index(i), MPI_OFFSET_KIND)
+ value = data(i)
+ ierr = nf90mpi_put_var(ncid, varid, value, start=start)
+ CALL pnetcdf_check(ierr, 'write '//trim(varname), filename)
+ ENDDO
+
+ END SUBROUTINE pnetcdf_write_real8_points
+
+ SUBROUTINE pnetcdf_check(status, action, filename)
+
+ USE pnetcdf, only: NF90_NOERR, nf90mpi_strerror
+ USE MOD_SPMD_Task, only: CoLM_stop
+ IMPLICIT NONE
+
+ integer, intent(in) :: status
+ character(len=*), intent(in) :: action
+ character(len=*), intent(in) :: filename
+
+ IF (status /= NF90_NOERR) THEN
+ write(*,'(A)') 'PnetCDF error during '//trim(action)//' for '//trim(filename)//': ' &
+ //trim(nf90mpi_strerror(status))
+ CALL CoLM_stop()
+ ENDIF
+
+ END SUBROUTINE pnetcdf_check
+#endif
+
+ SUBROUTINE deallocate_GridRiverLakeTimeVars
+
+ IMPLICIT NONE
+
+ IF (allocated (wdsrf_ucat)) deallocate (wdsrf_ucat)
+ IF (allocated (veloc_riv )) deallocate (veloc_riv )
+ IF (allocated (momen_riv )) deallocate (momen_riv )
+ IF (allocated (volresv )) deallocate (volresv )
+
+ END SUBROUTINE deallocate_GridRiverLakeTimeVars
+
+END MODULE MOD_Grid_RiverLakeTimeVars
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_SoilFunction.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_SoilFunction.F90
new file mode 100644
index 0000000000..1480a85553
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_SoilFunction.F90
@@ -0,0 +1,173 @@
+#include
+
+MODULE MOD_Hydro_SoilFunction
+
+!----------------------------------------------------------------------------
+! Description:
+!
+! Soil function type 1:
+! Campbell model
+! CAMPBELL, G. S. (1974), Soil Science, 117(6), 311-314.
+!
+! Soil function type 2:
+! Modified van Genuchten & Mualem model by introducing an air-entry value
+! Ippisch et al. (2006), Advances in Water Resources, 29(12), 1780-1789.
+!
+! Created by Shupeng Zhang, 2022.
+!----------------------------------------------------------------------------
+
+ USE MOD_Precision
+
+ IMPLICIT NONE
+
+ real(r8), parameter :: minsmp = -1.e8
+
+ PUBLIC :: get_derived_parameters_vGM
+
+ PUBLIC :: soil_psi_from_vliq
+ PUBLIC :: soil_hk_from_psi
+ PUBLIC :: soil_vliq_from_psi
+
+CONTAINS
+
+ !-------------------------------------
+ SUBROUTINE get_derived_parameters_vGM ( &
+ psi_s, alpha_vgm, n_vgm, sc_vgm, fc_vgm)
+
+ real(r8), intent(in) :: psi_s
+ real(r8), intent(in) :: alpha_vgm
+ real(r8), intent(in) :: n_vgm
+
+ real(r8), intent(out) :: sc_vgm
+ real(r8), intent(out) :: fc_vgm
+
+ ! Local variables
+ real(r8) :: m_vgm
+
+ m_vgm = 1.0_r8 - 1.0_r8 / n_vgm
+ sc_vgm = (1.0_r8 + (- alpha_vgm * psi_s)**n_vgm) ** (-m_vgm)
+ fc_vgm = 1.0_r8 - (1.0_r8 - sc_vgm ** (1.0_r8/m_vgm)) ** m_vgm
+
+ END SUBROUTINE get_derived_parameters_vGM
+
+ !------------------------------------------------------------------
+ real(r8) FUNCTION soil_hk_from_psi (psi, &
+ psi_s, hksat, nprm, prms)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: psi
+
+ real(r8), intent(in) :: psi_s
+ real(r8), intent(in) :: hksat
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+
+ ! Local variables
+ real(r8) :: m_vgm, esat
+
+ IF (psi >= psi_s) THEN
+ soil_hk_from_psi = hksat
+ RETURN
+ ENDIF
+
+#ifdef Campbell_SOIL_MODEL
+ ! bsw => prms(1)
+ soil_hk_from_psi = hksat * (psi / psi_s)**(- 3.0_r8 / prms(1) - 2.0_r8)
+#endif
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ ! alpha_vgm => prms(1), n_vgm => prms(2), L_vgm => prms(3), sc_vgm => prms(4), fc_vgm => prms(5)
+ m_vgm = 1.0_r8 - 1.0_r8 / prms(2)
+ esat = (1.0_r8 + (- prms(1) * psi)**(prms(2)))**(-m_vgm) / prms(4)
+ soil_hk_from_psi = hksat * esat**prms(3) &
+ * ((1.0_r8 - (1.0_r8 - (esat*prms(4))**(1.0_r8/m_vgm))**m_vgm) / prms(5))**2.0_r8
+#endif
+
+ END FUNCTION soil_hk_from_psi
+
+
+ !-----------------------------------------------------------------
+ real(r8) FUNCTION soil_psi_from_vliq (vliq, &
+ porsl, vl_r, psi_s, nprm, prms)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: vliq
+
+ real(r8), intent(in) :: porsl
+ real(r8), intent(in) :: vl_r
+ real(r8), intent(in) :: psi_s
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+
+ ! Local variables
+ real(r8) :: esat, m_vgm
+
+ IF (vliq >= porsl) THEN
+ soil_psi_from_vliq = psi_s
+ RETURN
+ ELSEIF (vliq <= max(vl_r,1.0e-8)) THEN
+ soil_psi_from_vliq = minsmp
+ RETURN
+ ENDIF
+
+#ifdef Campbell_SOIL_MODEL
+ ! bsw => prms(1)
+ soil_psi_from_vliq = psi_s * (vliq / porsl)**(-prms(1))
+#endif
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ ! alpha_vgm => prms(1), n_vgm => prms(2), L_vgm => prms(3), sc_vgm => prms(4), fc_vgm => prms(5)
+ m_vgm = 1.0_r8 - 1.0_r8 / prms(2)
+ esat = (vliq - vl_r) / (porsl - vl_r)
+ soil_psi_from_vliq = - ((esat*prms(4))**(- 1.0_r8/m_vgm) - 1.0_r8)**(1.0_r8/prms(2)) &
+ / prms(1)
+#endif
+
+ soil_psi_from_vliq = max(soil_psi_from_vliq, minsmp)
+
+
+ END FUNCTION soil_psi_from_vliq
+
+ !------------------------------------------------------------------
+ real(r8) FUNCTION soil_vliq_from_psi (psi, &
+ porsl, vl_r, psi_s, nprm, prms)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: psi
+
+ real(r8), intent(in) :: porsl
+ real(r8), intent(in) :: vl_r
+ real(r8), intent(in) :: psi_s
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+
+ ! Local variables
+ real(r8) :: esat, m_vgm
+
+ IF (psi >= psi_s) THEN
+ soil_vliq_from_psi = porsl
+ RETURN
+ ENDIF
+
+#ifdef Campbell_SOIL_MODEL
+ ! bsw => prms(1)
+ soil_vliq_from_psi = porsl * (psi / psi_s)**(-1.0/prms(1))
+#endif
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ ! alpha_vgm => prms(1), n_vgm => prms(2), L_vgm => prms(3), sc_vgm => prms(4), fc_vgm => prms(5)
+ m_vgm = 1.0_r8 - 1.0_r8 / prms(2)
+ esat = (1.0_r8 + (psi * (-prms(1)))**(prms(2))) ** (-m_vgm) / prms(4)
+ soil_vliq_from_psi = (porsl - vl_r) * esat + vl_r
+#endif
+
+ END FUNCTION soil_vliq_from_psi
+
+
+END MODULE MOD_Hydro_SoilFunction
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_SoilWater.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_SoilWater.F90
new file mode 100644
index 0000000000..e5ef3018ca
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_SoilWater.F90
@@ -0,0 +1,3620 @@
+#include
+
+MODULE MOD_Hydro_SoilWater
+
+!-------------------------------------------------------------------------
+! Description:
+!
+! Numerical Solver of Richards equation.
+!
+! Dai, Y., Zhang, S., Yuan, H., & Wei, N. (2019).
+! Modeling Variably Saturated Flow in Stratified Soils
+! With Explicit Tracking of Wetting Front and Water Table Locations.
+! Water Resources Research. doi:10.1029/2019wr025368
+!
+! Created by Shupeng Zhang, 2022.
+!-------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Hydro_SoilFunction
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS
+ USE MOD_UserDefFun, only: findloc_ud
+
+ IMPLICIT NONE
+
+ ! public subroutines and functions
+ PUBLIC :: soil_water_vertical_movement
+ PUBLIC :: get_water_equilibrium_state
+ PUBLIC :: soilwater_aquifer_exchange
+ PUBLIC :: get_zwt_from_wa
+
+
+ ! boundary condition:
+ ! 1: fixed pressure head
+ ! 2: rainfall condition with a ponding layer on top of ground surface
+ ! and a flux such as rainfall into the ponding layer
+ ! 3: fixed flux
+ ! 4: drainage condition with aquifers below soil columns
+ integer, parameter :: BC_FIX_HEAD = 1
+ integer, parameter :: BC_RAINFALL = 2
+ integer, parameter :: BC_FIX_FLUX = 3
+ integer, parameter :: BC_DRAINAGE = 4
+
+ ! formula of effective hydraulic conductivity between levels
+ ! Please refer to Dai et al. (2019) for definitions
+ integer, parameter :: type_upstream_mean = 1
+ integer, parameter :: type_weighted_geometric_mean = 2
+
+ integer, parameter :: effective_hk_type = type_weighted_geometric_mean
+ integer, parameter :: max_iters_richards = 10
+ real(r8), parameter :: tol_richards = 8.e-8
+
+#ifdef CoLMDEBUG
+ integer(8) :: count_implicit = 0
+ integer(8) :: count_explicit = 0
+ integer(8) :: count_wet2dry = 0
+#endif
+
+ ! private subroutines and functions
+ PRIVATE :: Richards_solver
+
+ PRIVATE :: water_balance
+ PRIVATE :: initialize_sublevel_structure
+
+ PRIVATE :: use_explicit_form
+
+ PRIVATE :: var_perturb_level
+ PRIVATE :: var_perturb_rainfall
+ PRIVATE :: var_perturb_drainage
+
+ PRIVATE :: check_and_update_level
+
+ PRIVATE :: flux_all
+ PRIVATE :: flux_sat_zone_all
+ PRIVATE :: flux_sat_zone_fixed_bc
+ PRIVATE :: flux_inside_hm_soil
+ PRIVATE :: flux_at_unsaturated_interface
+ PRIVATE :: flux_top_transitive_interface
+ PRIVATE :: flux_btm_transitive_interface
+ PRIVATE :: flux_both_transitive_interface
+
+ PRIVATE :: solve_least_squares_problem
+ PRIVATE :: secant_method_iteration
+
+ PRIVATE :: find_unsat_lev_lower
+
+CONTAINS
+
+ ! ---- get equilibrium state ----
+ SUBROUTINE get_water_equilibrium_state ( &
+ zwtmm, nlev, wliq, smp, hk, wa, sp_zc, sp_zi, porsl, vl_r, psi_s, hksat, nprm, prms)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: zwtmm ! location of water table [mm]
+
+ integer, intent(in) :: nlev ! number of levels
+
+ real(r8), intent(out) :: wliq(1:nlev) ! [mm] or [kg/m2]
+ real(r8), intent(out) :: smp (1:nlev) ! [mm]
+ real(r8), intent(out) :: hk (1:nlev) ! [mm/s]
+ real(r8), intent(out) :: wa ! water in aquifer [mm]
+
+ real(r8), intent(in) :: sp_zc (1:nlev) ! soil parameter : centers of level [mm]
+ real(r8), intent(in) :: sp_zi (0:nlev) ! soil parameter : interfaces of level [mm]
+
+ real(r8), intent(in) :: porsl (1:nlev) ! soil porosity
+ real(r8), intent(in) :: vl_r (1:nlev) ! residual soil moisture
+ real(r8), intent(in) :: psi_s (1:nlev) ! saturated capillary potential [mm, negative]
+ real(r8), intent(in) :: hksat (1:nlev) ! saturated hydraulic conductivity [mm/s]
+
+ integer, intent(in) :: nprm ! number of parameters included in soil function
+ real(r8), intent(in) :: prms (nprm,1:nlev) ! parameters included in soil function
+
+ ! Local Variables
+ integer :: izwt, ilev
+ real(r8) :: psi_zwt, smp_up, vliq_up, vliq(1:nlev), psi, vl
+
+ ! water table location
+ izwt = findloc_ud(zwtmm >= sp_zi, back=.true.)
+
+ IF (izwt <= nlev) THEN
+ psi_zwt = psi_s(izwt)
+ ELSE
+ psi_zwt = psi_s(nlev)
+ ENDIF
+
+ DO ilev = 1, nlev
+ IF (ilev < izwt) THEN
+ smp (ilev) = psi_zwt - (zwtmm - sp_zc(ilev))
+ vliq(ilev) = soil_vliq_from_psi (smp(ilev), porsl(ilev), vl_r(ilev), psi_s(ilev), &
+ nprm, prms(:,ilev))
+ wliq(ilev) = vliq(ilev) * (sp_zi(ilev)-sp_zi(ilev-1))
+ hk (ilev) = soil_hk_from_psi (smp(ilev), psi_s(ilev), hksat(ilev), nprm, prms(:,ilev))
+ ELSEIF (ilev == izwt) THEN
+ smp_up = psi_zwt &
+ - (zwtmm-sp_zi(ilev-1)) * (sp_zi(ilev)-sp_zc(ilev))/(sp_zi(ilev)-sp_zi(ilev-1))
+ vliq_up = soil_vliq_from_psi (smp_up, porsl(ilev), vl_r(ilev), psi_s(ilev), &
+ nprm, prms(:,ilev))
+ wliq(ilev) = vliq_up * (zwtmm-sp_zi(ilev-1)) + porsl(ilev)*(sp_zi(ilev)-zwtmm)
+ vliq(ilev) = wliq(ilev) / (sp_zi(ilev)-sp_zi(ilev-1))
+ smp(ilev) = soil_psi_from_vliq (vliq(ilev), porsl(ilev), vl_r(ilev), psi_s(ilev), &
+ nprm, prms(:,ilev))
+ hk (ilev) = soil_hk_from_psi (smp(ilev), psi_s(ilev), hksat(ilev), nprm, prms(:,ilev))
+ ELSE
+ wliq(ilev) = porsl(ilev) * (sp_zi(ilev)-sp_zi(ilev-1))
+ smp (ilev) = psi_s(ilev)
+ hk (ilev) = hksat(ilev)
+ ENDIF
+ ENDDO
+
+ IF (izwt == nlev+1) THEN
+ psi = psi_zwt - (zwtmm - sp_zi(nlev)) * 0.5
+ vl = soil_vliq_from_psi (psi, porsl(nlev), vl_r(nlev), psi_s(nlev), nprm, prms(:,nlev))
+ wa = -(zwtmm-sp_zi(nlev))*(porsl(nlev)-vl)
+ ELSE
+ wa = 0.
+ ENDIF
+
+ END SUBROUTINE get_water_equilibrium_state
+
+ ! --- soil water movement ---
+ SUBROUTINE soil_water_vertical_movement ( &
+ nlev, dt, sp_zc, sp_zi, is_permeable, porsl, &
+ vl_r, psi_s, hksat, nprm, prms, porsl_wa, &
+ qgtop, etr, rootr, rootflux, rsubst, qinfl, &
+ ss_dp, zwt, wa, ss_vliq, smp, hk, &
+ qlayer, tolerance, wblc)
+
+ !=======================================================================
+ ! this is the main subroutine to execute the calculation of
+ ! soil water movement
+ !=======================================================================
+
+ USE MOD_Const_Physical, only: tfrz
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: nlev ! number of levels
+ real(r8), intent(in) :: dt ! time step (second)
+
+ real(r8), intent(in) :: sp_zc (1:nlev) ! soil parameter : centers of level (mm)
+ real(r8), intent(in) :: sp_zi (0:nlev) ! soil parameter : interfaces of level (mm)
+
+ logical, intent(in) :: is_permeable (1:nlev)
+
+ real(r8), intent(in) :: porsl (1:nlev) ! soil porosity (mm^3/mm^3)
+ real(r8), intent(in) :: vl_r (1:nlev) ! residual soil moisture (mm^3/mm^3)
+ real(r8), intent(in) :: psi_s (1:nlev) ! saturated capillary potential (mm)
+ real(r8), intent(in) :: hksat (1:nlev) ! saturated hydraulic conductivity (mm/s)
+
+ integer, intent(in) :: nprm ! number of parameters included in soil function
+ real(r8), intent(in) :: prms (nprm,1:nlev) ! parameters included in soil function
+
+ real(r8), intent(in) :: porsl_wa ! soil porosity in aquifer (mm^3/mm^3)
+
+ ! ground water including rain, snow melt and dew formation (mm/s)
+ real(r8), intent(in) :: qgtop
+
+ real(r8), intent(in) :: etr ! transpiration rate (mm/s)
+ real(r8), intent(in) :: rootr(1:nlev) ! root fractions (percentage)
+ real(r8), intent(in) :: rootflux(1:nlev) ! root water uptake from different layers (mm/s)
+
+ real(r8), intent(in) :: rsubst ! subsurface runoff (mm/s)
+ real(r8), intent(out) :: qinfl ! infiltration into soil (mm/s)
+
+ real(r8), intent(inout) :: ss_dp ! soil water state : depth of ponding water (mm)
+ real(r8), intent(inout) :: zwt ! location of water table (mm)
+ real(r8), intent(inout) :: wa ! water deficit in aquifer (negative, mm)
+ real(r8), intent(inout) :: ss_vliq(1:nlev) ! volume content of liquid water (mm^3/mm^3)
+
+ real(r8), intent(out) :: smp(1:nlev) ! soil matrix potential (mm)
+ real(r8), intent(out) :: hk (1:nlev) ! hydraulic conductivity (mm/s)
+
+ real(r8), intent(out) :: qlayer(0:nlev) ! water flux at interface of soil layers (mm/s)
+
+ real(r8), intent(in) :: tolerance
+
+ real(r8), intent(out) :: wblc
+
+ ! Local variables
+ integer :: lb, ub, ilev, izwt
+ real(r8) :: sumroot, deficit, etrdef, wexchange
+ real(r8) :: dp_m1, psi, vliq, zwtp, air
+ logical :: is_sat
+
+ real(r8) :: sp_dz (1:nlev)
+ real(r8) :: etroot (1:nlev)
+ real(r8) :: ss_wt (1:nlev)
+
+ integer :: ubc_typ_sub
+ real(r8) :: ubc_val_sub
+ integer :: lbc_typ_sub
+ real(r8) :: lbc_val_sub
+
+ real(r8) :: w_sum_before, w_sum_after, vl_before(nlev), wt_before, wa_before, dp_before
+
+ real(r8) :: tol_q, tol_z, tol_v, tol_p
+
+ sp_dz(1:nlev) = sp_zi(1:nlev) - sp_zi(0:nlev-1)
+
+ dp_m1 = ss_dp
+
+ ! tolerances
+ tol_q = tolerance / real(nlev,r8) / dt /2.0
+ tol_z = tol_q * dt
+ tol_v = tol_z / maxval(sp_dz)
+ tol_p = 1.0e-14
+
+ ! water table location
+ izwt = findloc_ud(zwt >= sp_zi, back=.true.)
+
+ ! total water mass
+ w_sum_before = ss_dp
+ DO ilev = 1, nlev
+ IF (is_permeable(ilev)) THEN
+ IF (ilev <= izwt-1) THEN
+ w_sum_before = w_sum_before + ss_vliq(ilev) * sp_dz(ilev)
+ ELSEIF (ilev == izwt) THEN
+ w_sum_before = w_sum_before + ss_vliq(izwt) * (zwt - sp_zi(izwt-1))
+ w_sum_before = w_sum_before + porsl (izwt) * (sp_zi(izwt) - zwt)
+ ELSE
+ w_sum_before = w_sum_before + porsl(ilev) * sp_dz(ilev)
+ ENDIF
+ ENDIF
+ ENDDO
+ w_sum_before = w_sum_before + wa
+
+ vl_before = ss_vliq
+ wt_before = zwt
+ wa_before = wa
+ dp_before = ss_dp
+
+ ! transpiration
+ IF(.not. DEF_USE_PLANTHYDRAULICS)THEN
+ sumroot = sum(rootr, mask = is_permeable .and. (rootr > 0.))
+ etroot(:) = 0.
+ IF (sumroot > 0.) THEN
+ WHERE (is_permeable)
+ etroot = etr * max(rootr, 0.) / sumroot
+ END WHERE
+ etrdef = 0.
+ ELSE
+ etrdef = etr*dt
+ ENDIF
+ ELSE
+ etrdef = 0.
+ etroot(:) = rootflux
+ ENDIF
+
+ deficit = etrdef
+
+ DO ilev = 1, izwt-1
+ IF (is_permeable(ilev)) THEN
+
+ ss_vliq(ilev) = (ss_vliq(ilev) * sp_dz(ilev) &
+ - etroot(ilev)*dt - deficit) / sp_dz(ilev)
+
+ IF (ss_vliq(ilev) < 0) THEN
+ deficit = ( - ss_vliq(ilev)) * sp_dz(ilev)
+ ss_vliq(ilev) = 0
+ ELSEIF (ss_vliq(ilev) > porsl(ilev)) THEN
+ deficit = - (ss_vliq(ilev) - porsl(ilev)) * sp_dz(ilev)
+ ss_vliq(ilev) = porsl(ilev)
+ ELSE
+ deficit = 0.
+ ENDIF
+ ELSE
+ deficit = deficit + etroot(ilev)*dt
+ ENDIF
+ ENDDO
+
+ DO ilev = izwt, nlev
+ deficit = deficit + etroot(ilev)*dt
+ ENDDO
+
+ ! Exchange water with aquifer
+ wexchange = rsubst * dt + deficit
+ CALL soilwater_aquifer_exchange ( &
+ nlev, wexchange, sp_zi, is_permeable, porsl, vl_r, psi_s, hksat, &
+ nprm, prms, porsl_wa, ss_dp, ss_vliq, zwt, wa, izwt)
+
+ ! water table location
+ ss_wt(:) = 0._r8
+ IF ((izwt >= 1) .and. (izwt <= nlev)) THEN
+ ss_wt(izwt) = sp_zi(izwt) - zwt
+ ENDIF
+ DO ilev = izwt+1, nlev
+ ss_wt(ilev) = sp_dz(ilev)
+ ENDDO
+
+ ! Impermeable levels cut the soil column into several disconnected parts.
+ ! The Richards solver is called to calculate water movement part by part.
+ ub = nlev
+ soilcolumn : DO WHILE (ub >= 1)
+
+ DO WHILE (.not. is_permeable(ub))
+
+ qlayer(ub-1:ub) = 0._r8
+
+ IF (ub > 1) THEN
+ ub = ub - 1
+ ELSE
+ EXIT soilcolumn
+ ENDIF
+ ENDDO
+
+ lb = ub
+ DO WHILE (lb > 1)
+ IF (is_permeable(lb-1)) THEN
+ lb = lb - 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ IF (lb == 1) THEN
+ ubc_typ_sub = BC_RAINFALL
+ ubc_val_sub = qgtop
+ ELSE
+ ubc_typ_sub = BC_FIX_FLUX
+ ubc_val_sub = 0
+ ENDIF
+
+ IF ((ub == nlev) .and. (izwt > nlev)) THEN
+ lbc_typ_sub = BC_DRAINAGE
+ lbc_val_sub = 0.
+ ELSE
+ lbc_typ_sub = BC_FIX_FLUX
+ lbc_val_sub = 0.
+ ENDIF
+
+ CALL Richards_solver ( &
+ lb, ub, dt, sp_zc(lb:ub), sp_zi(lb-1:ub), &
+ porsl(lb:ub), vl_r(lb:ub), psi_s(lb:ub), hksat(lb:ub), nprm, prms(:,lb:ub), &
+ porsl_wa, &
+ ubc_typ_sub, ubc_val_sub, lbc_typ_sub, lbc_val_sub, &
+ ss_dp, wa, ss_vliq(lb:ub), ss_wt(lb:ub), qlayer(lb-1:ub), &
+ tol_q, tol_z, tol_v, tol_p)
+
+ ub = lb - 1
+
+ ENDDO soilcolumn
+
+ IF (.not. is_permeable(1)) THEN
+ ss_dp = max(ss_dp + qgtop * dt, 0._r8)
+ ENDIF
+
+ IF (wa >= 0) THEN
+ DO ilev = nlev, 1, -1
+ is_sat = (.not. is_permeable(ilev)) &
+ .or. (ss_vliq(ilev) > porsl(ilev) - tol_v) &
+ .or. (ss_wt (ilev) > sp_dz(ilev) - tol_z)
+ IF (.not. is_sat) THEN
+ zwt = sp_zi(ilev) - ss_wt(ilev)
+ EXIT
+ ENDIF
+ ENDDO
+
+ IF (is_sat) THEN
+ zwt = 0._r8
+ ENDIF
+ ELSE
+ CALL get_zwt_from_wa ( &
+ porsl_wa, vl_r(nlev), psi_s(nlev), hksat(nlev), &
+ nprm, prms(:,nlev), tol_v, tol_z, &
+ wa, sp_zi(nlev), zwt)
+ ENDIF
+
+ izwt = findloc_ud(zwt >= sp_zi, back=.true.)
+ DO ilev = izwt-1, 1, -1
+ IF (is_permeable(ilev)) THEN
+ ss_vliq(ilev) = (ss_vliq(ilev)*(sp_dz(ilev)-ss_wt(ilev)) &
+ + porsl(ilev)*ss_wt(ilev)) / sp_dz(ilev)
+ ENDIF
+ ENDDO
+
+ qinfl = qgtop - (ss_dp - dp_m1)/dt
+
+ ! total water mass
+ w_sum_after = ss_dp
+ DO ilev = 1, nlev
+ IF (is_permeable(ilev)) THEN
+ IF (ilev <= izwt-1) THEN
+ w_sum_after = w_sum_after + ss_vliq(ilev) * sp_dz(ilev)
+ ELSEIF (ilev == izwt) THEN
+ w_sum_after = w_sum_after + ss_vliq(izwt) * (zwt - sp_zi(izwt-1))
+ w_sum_after = w_sum_after + porsl (izwt) * (sp_zi(izwt) - zwt)
+ ELSE
+ w_sum_after = w_sum_after + porsl(ilev) * sp_dz(ilev)
+ ENDIF
+ ENDIF
+ ENDDO
+ w_sum_after = w_sum_after + wa
+
+ wblc = w_sum_after - (w_sum_before + (qgtop - sum(etroot) - rsubst) * dt - etrdef)
+
+ IF (abs(wblc) > tolerance) THEN
+ write(*,*) 'soil_water_vertical_movement balance error: ', wblc, ' in mm.'
+ write(*,*) 'qtop: ', qgtop, 'etr: ', sum(etroot)+etrdef, 'rsubst: ', rsubst
+ write(*,*) 'permeable (1-10): ', is_permeable
+ write(*,*) 'ponding depth: ', dp_before, '(before) to ', ss_dp, '(after)'
+ write(*,*) 'porsl (c1) and liquid volume before (c2) and after (c3) (1-10) : '
+ DO ilev = 1, nlev
+ write(*,*) porsl(ilev), vl_before(ilev), ss_vliq(ilev)
+ ENDDO
+ write(*,*) 'water table : ', wt_before, '(before) to ', zwt, '(after)'
+ write(*,*) 'aquifer : ', wa_before, '(before) to ', wa, '(after)'
+ ENDIF
+
+ DO ilev = 1, nlev
+ IF (ilev < izwt) THEN
+ smp(ilev) = soil_psi_from_vliq (ss_vliq(ilev), porsl(ilev), vl_r(ilev), psi_s(ilev), &
+ nprm, prms(:,ilev))
+ hk (ilev) = soil_hk_from_psi (smp(ilev), psi_s(ilev), hksat(ilev), nprm, prms(:,ilev))
+ ELSEIF (ilev == izwt) THEN
+ vliq = (ss_vliq(izwt) * (zwt - sp_zi(izwt-1)) + porsl(izwt) * (sp_zi(izwt) - zwt)) &
+ / (sp_zi(izwt) - sp_zi(izwt-1))
+ smp(ilev) = soil_psi_from_vliq (vliq, porsl(ilev), vl_r(ilev), psi_s(ilev), &
+ nprm, prms(:,ilev))
+ hk (ilev) = soil_hk_from_psi (smp(ilev), psi_s(ilev), hksat(ilev), nprm, prms(:,ilev))
+ ELSE
+ smp(ilev) = psi_s(ilev)
+ hk (ilev) = hksat(ilev)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE soil_water_vertical_movement
+
+ ! --- water exchange between soil water and aquifer ---
+ SUBROUTINE soilwater_aquifer_exchange ( &
+ nlev, exwater, sp_zi, is_permeable, porsl, vl_r, psi_s, hksat, &
+ nprm, prms, porsl_wa, ss_dp, ss_vliq, zwt, wa, izwt)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: nlev
+
+ real(r8), intent(in) :: exwater ! total water exchange [mm]
+
+ real(r8), intent(in) :: sp_zi (0:nlev) ! soil parameter : interfaces of level [mm]
+
+ logical, intent(in) :: is_permeable (1:nlev)
+ real(r8), intent(in) :: porsl (1:nlev) ! soil porosity [mm^3/mm^3]
+ real(r8), intent(in) :: vl_r (1:nlev) ! residual soil moisture [mm^3/mm^3]
+ real(r8), intent(in) :: psi_s (1:nlev) ! saturated capillary potential [mm]
+ real(r8), intent(in) :: hksat (1:nlev) ! saturated hydraulic conductivity [mm/s]
+
+ integer, intent(in) :: nprm ! number of parameters included in soil function
+ real(r8), intent(in) :: prms (nprm,1:nlev) ! parameters included in soil function
+
+ real(r8), intent(in) :: porsl_wa ! soil porosity in aquifer [mm^3/mm^3]
+
+ real(r8), intent(inout) :: ss_dp ! depth of ponding water [mm]
+ real(r8), intent(inout) :: ss_vliq(1:nlev) ! volume content of liquid water [mm^3/mm^3]
+ real(r8), intent(inout) :: zwt ! location of water table [mm]
+ real(r8), intent(inout) :: wa ! water in aquifer [mm, negative]
+
+ integer, intent(out) :: izwt
+
+ ! Local variables
+ real(r8) :: sp_dz(1:nlev)
+ real(r8) :: reswater, zwtp, psi, vliq, air
+ real(r8) :: tol_v, tol_z
+
+ sp_dz(1:nlev) = sp_zi(1:nlev) - sp_zi(0:nlev-1)
+
+ ! tolerances
+ tol_z = tol_richards / sqrt(real(nlev,r8)) * 0.5_r8 * 1800._r8
+ tol_v = tol_z / maxval(sp_dz)
+
+ ! water table location
+ izwt = findloc_ud(zwt >= sp_zi, back=.true.)
+
+ reswater = exwater
+
+ IF (reswater > 0.) THEN
+
+ IF ((zwt <= 0.) .and. (ss_dp > 0.)) THEN
+ IF (ss_dp > reswater) THEN
+ ss_dp = ss_dp - reswater
+ reswater = 0.
+ ELSE
+ reswater = reswater - ss_dp
+ ss_dp = 0.
+ ENDIF
+ ENDIF
+
+ ! remove water from aquifer
+ DO WHILE (reswater > 0.)
+ IF (izwt <= nlev) THEN
+ IF (is_permeable(izwt)) THEN
+
+ CALL get_zwt_from_wa ( &
+ porsl(izwt), vl_r(izwt), psi_s(izwt), hksat(izwt), &
+ nprm, prms(:,izwt), tol_v, tol_z, -reswater, zwt, zwtp)
+
+ IF (zwtp < sp_zi(izwt)) THEN
+ ss_vliq(izwt) = (ss_vliq(izwt)*(zwt-sp_zi(izwt-1)) &
+ + porsl(izwt)*(zwtp-zwt) - reswater) / (zwtp - sp_zi(izwt-1))
+ reswater = 0.
+ zwt = zwtp
+ ELSE
+ psi = psi_s(izwt) - (zwtp - 0.5*(sp_zi(izwt) + zwt))
+ vliq = soil_vliq_from_psi (psi, &
+ porsl(izwt), vl_r(izwt), psi_s(izwt), nprm, prms(:,izwt))
+ IF (reswater > (porsl(izwt)-vliq) * (sp_zi(izwt)-zwt)) THEN
+ ss_vliq(izwt) = (ss_vliq(izwt)*(zwt-sp_zi(izwt-1)) &
+ + vliq * (sp_zi(izwt)-zwt)) / sp_dz(izwt)
+ reswater = reswater - (porsl(izwt)-vliq) * (sp_zi(izwt)-zwt)
+ ELSE
+ ss_vliq(izwt) = (ss_vliq(izwt)*(zwt-sp_zi(izwt-1)) &
+ + porsl(izwt)*(sp_zi(izwt)-zwt) - reswater) / sp_dz(izwt)
+ reswater = 0.
+ ENDIF
+
+ zwt = sp_zi(izwt)
+ izwt = izwt + 1
+ ENDIF
+
+ ELSE
+ zwt = sp_zi(izwt)
+ izwt = izwt + 1
+ ENDIF
+ ELSE
+ CALL get_zwt_from_wa ( &
+ porsl_wa, vl_r(nlev), psi_s(nlev), hksat(nlev), &
+ nprm, prms(:,nlev), tol_v, tol_z, wa-reswater, sp_zi(nlev), zwt)
+ wa = wa - reswater
+ reswater = 0.
+ ENDIF
+ ENDDO
+
+ ELSEIF (reswater < 0.) THEN
+
+ ! increase water in aquifer
+ DO WHILE (reswater < 0.)
+ IF (izwt > nlev) THEN
+ IF (wa <= reswater) THEN
+ wa = wa - reswater
+ reswater = 0.
+ ELSE
+ reswater = reswater - wa
+ wa = 0.
+ izwt = nlev
+ zwt = sp_zi(nlev)
+ ENDIF
+ ELSEIF (izwt >= 1) THEN
+ IF (is_permeable(izwt)) THEN
+ air = (porsl(izwt)-ss_vliq(izwt)) * (zwt-sp_zi(izwt-1))
+ IF (air > -reswater) THEN
+ ss_vliq(izwt) = ss_vliq(izwt) - reswater / (zwt-sp_zi(izwt-1))
+ reswater = 0.
+ ELSE
+ ss_vliq(izwt) = porsl(izwt)
+ reswater = reswater + air
+ izwt = izwt - 1
+ zwt = sp_zi(izwt)
+ ENDIF
+ ELSE
+ izwt = izwt - 1
+ zwt = sp_zi(izwt)
+ ENDIF
+ ELSE
+ ss_dp = ss_dp - reswater
+ reswater = 0.
+ izwt = 1
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE soilwater_aquifer_exchange
+
+ ! ---- Richards equation solver ----
+ SUBROUTINE Richards_solver ( &
+ lb, ub, dt, sp_zc, sp_zi, &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ vl_s_wa, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ ss_dp, waquifer, ss_vl, ss_wt, ss_q, &
+ tol_q, tol_z, tol_v, tol_p)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lb, ub ! lower and upper boundary
+
+ real(r8), intent(in) :: dt ! time step (second)
+
+ real(r8), intent(in) :: sp_zc (lb:ub) ! soil parameter : centers of level (mm)
+ real(r8), intent(in) :: sp_zi (lb-1:ub) ! soil parameter : interfaces of level (mm)
+
+ real(r8), intent(in) :: vl_s (lb:ub) ! soil porosity (mm^3/mm^3)
+ real(r8), intent(in) :: vl_r (lb:ub) ! residual soil moisture (mm^3/mm^3)
+ real(r8), intent(in) :: psi_s (lb:ub) ! saturated capillary potential (mm,negative)
+ real(r8), intent(in) :: hksat (lb:ub) ! saturated hydraulic conductivity (mm/s)
+
+ integer, intent(in) :: nprm ! number of parameters included in soil function
+ real(r8), intent(in) :: prms(nprm,lb:ub) ! parameters included in soil function
+
+ real(r8), intent(in) :: vl_s_wa ! soil porosity in aquifer (mm^3/mm^3)
+
+ integer, intent(in) :: ubc_typ ! upper boundary condition type
+ real(r8), intent(in) :: ubc_val ! value of upper boundary condition
+ integer, intent(in) :: lbc_typ ! lower boundary condition type
+ real(r8), intent(in) :: lbc_val ! value of lower boundary condition
+
+ real(r8), intent(inout) :: ss_dp ! soil water state : depth of ponding water (mm)
+ real(r8), intent(inout) :: waquifer ! water deficit in aquifer (mm, negative)
+ real(r8), intent(inout) :: ss_vl (lb:ub) ! soil water state : volume content of liquid water
+ real(r8), intent(inout) :: ss_wt (lb:ub) ! soil water state : location of water table (mm)
+ real(r8), intent(out) :: ss_q (lb-1:ub) ! soil water state : flux between levels (mm/s)
+
+ real(r8), intent(in) :: tol_q ! tolerance for flux
+ real(r8), intent(in) :: tol_z ! tolerance for locations
+ real(r8), intent(in) :: tol_v ! tolerance for volumetric water content
+ real(r8), intent(in) :: tol_p ! tolerance for potential head
+
+ ! Local variables
+ real(r8) :: zwt ! location of water table (mm)
+ real(r8) :: sp_dz (lb:ub) ! thickness of level (mm)
+ real(r8) :: ss_wf (lb:ub) ! soil water state : location of wetting front
+
+ logical :: is_sat (lb:ub) ! whether a level is saturated or not at this time step
+ logical :: has_wf (lb:ub) ! whether a wetting front is present or not
+ logical :: has_wt (lb:ub) ! whether a water table is present or not
+
+ real(r8) :: psi (lb:ub) ! water pressure head in unsaturated soil (mm)
+ real(r8) :: hk (lb:ub) ! hydraulic conductivity in unsaturated soil (mm/s)
+
+ real(r8) :: psi_pb (lb:ub) ! perturbed water pressure head (mm)
+ real(r8) :: hk_pb (lb:ub) ! perturbed hydraulic conductivity (mm/s)
+
+ real(r8) :: q_this(lb-1:ub) ! water flux between levels (mm/s)
+ real(r8) :: q_wf (lb:ub) ! water flux at wetting front (mm/s)
+ real(r8) :: q_wt (lb:ub) ! water flux at water table (mm/s)
+
+ real(r8) :: dp_m1 ! depth of ponding water at previous time step (mm)
+ real(r8) :: wf_m1 (lb:ub) ! location of wetting front at previous time step (mm)
+ real(r8) :: vl_m1 (lb:ub) ! volumetric water content at previous time step (mm/mm)
+ real(r8) :: wt_m1 (lb:ub) ! location of water table at previous time step (mm)
+ real(r8) :: waquifer_m1 ! water deficit in aquifer at previous time step
+
+ real(r8) :: q_0 (lb-1:ub) ! initial value of water flux between levels (mm/s)
+ real(r8) :: q_wf_0 (lb:ub) ! initial value of water flux at wetting front (mm/s)
+ real(r8) :: q_wt_0 (lb:ub) ! initial value of water flux at water table (mm/s)
+
+ real(r8) :: dp_pb ! perturbed depth of ponding water (mm)
+ real(r8) :: vl_pb (lb:ub) ! perturbed volumetric water content (mm/mm)
+ real(r8) :: wf_pb (lb:ub) ! perturbed location of wetting front (mm)
+ real(r8) :: wt_pb (lb:ub) ! perturbed location of water table (mm)
+ real(r8) :: zwt_pb, waquifer_pb
+
+ real(r8) :: q_pb (lb-1:ub) ! perturbed water flux between levels (mm/s)
+ real(r8) :: q_wf_pb (lb:ub) ! perturbed water flux at wetting front (mm/s)
+ real(r8) :: q_wt_pb (lb:ub) ! perturbed water flux at water table (mm/s)
+
+ real(r8) :: blc (lb-1:ub+1) ! mass balance (mm water)
+ logical :: is_solvable
+ logical :: lev_update (lb-1:ub+1) ! whether a level is updated or not
+ real(r8) :: blc_pb (lb-1:ub+1) ! perturbed mass balance (mm water)
+ logical :: vact (lb-1:ub+1) ! whether a level is active or not
+ integer :: jsbl (lb:ub) ! which variable of wf,vl,wt inside each level is active
+
+ real(r8) :: dr_dv (lb-1:ub+1,lb-1:ub+1) ! the Jacobian matrix
+ real(r8) :: dv (lb-1:ub+1) ! searching step of variables
+
+ real(r8) :: f2_norm (max_iters_richards) ! sqrt( f2 ), where f2 = sum_i (r_i ^2)
+
+ real(r8) :: dt_this, dt_done
+ real(r8) :: dt_explicit ! time step (day) for explicit scheme
+
+ integer :: ilev, iter
+ real(r8) :: dlt
+
+ logical :: wet2dry
+
+ real(r8) :: wsum_m1, wsum, werr
+
+ ss_wf(lb:ub) = 0
+
+ DO ilev = lb, ub
+ sp_dz(ilev) = sp_zi(ilev) - sp_zi(ilev-1)
+ ENDDO
+
+ dt_explicit = dt / max_iters_richards
+
+ ss_q = 0
+ dt_done = 0
+ DO WHILE (dt_done < dt)
+
+ dt_this = dt - dt_done
+
+ wf_m1 = ss_wf
+ vl_m1 = ss_vl
+ wt_m1 = ss_wt
+
+ wsum_m1 = sum(ss_vl * (sp_dz - ss_wt)) + sum(ss_wt * vl_s)
+ IF (ubc_typ == BC_RAINFALL) THEN
+ wsum_m1 = wsum_m1 + ss_dp
+ ENDIF
+ IF (lbc_typ == BC_DRAINAGE) THEN
+ wsum_m1 = wsum_m1 + waquifer
+ ENDIF
+
+ IF (ubc_typ == BC_RAINFALL) THEN
+ dp_m1 = max(ss_dp, 0._r8)
+ ENDIF
+
+ IF (lbc_typ == BC_DRAINAGE) THEN
+ waquifer_m1 = waquifer
+ CALL get_zwt_from_wa ( &
+ vl_s_wa, vl_r(ub), psi_s(ub), hksat(ub), &
+ nprm, prms(:,ub), tol_v, tol_z, &
+ waquifer, sp_zi(ub), zwt)
+ ENDIF
+
+ iter = 0
+ DO WHILE (.true.)
+
+ iter = iter + 1
+
+ CALL initialize_sublevel_structure ( &
+ lb, ub, sp_dz, sp_zi(ub), &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ is_sat, has_wf, has_wt, &
+ ss_wf, ss_vl, ss_wt, ss_dp, psi, hk, &
+ tol_v, tol_z)
+
+ lev_update (:) = .true.
+ CALL flux_all ( &
+ lb, ub, sp_dz, sp_zc, sp_zi, &
+ vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ lev_update, .true., &
+ is_sat, has_wf, has_wt, &
+ ss_wf, ss_vl, ss_wt, ss_dp, zwt, psi, hk, &
+ q_this, q_wf, q_wt, &
+ tol_q, tol_z, tol_p)
+
+ CALL water_balance ( &
+ lb, ub, sp_dz, dt_this, is_sat, vl_s, q_this, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ ss_wf, ss_vl, ss_wt, ss_dp, waquifer, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ blc, is_solvable, tol_richards * dt_this)
+
+ IF (iter == 1) THEN
+ q_0 = q_this
+ q_wf_0 = q_wf
+ q_wt_0 = q_wt
+
+ wet2dry = .false.
+ IF (ubc_typ == BC_RAINFALL) THEN
+ IF ((dp_m1 > tol_z) .and. (dp_m1 - (q_0(lb-1)-ubc_val)*dt_this < tol_z)) THEN
+ wet2dry = .true.
+ ENDIF
+ ENDIF
+ ENDIF
+
+ f2_norm(iter) = sqrt(sum(blc**2))
+
+ IF ( (f2_norm(iter) < tol_richards * dt_this) & ! converged
+ .or. (dt_this < dt_explicit) &
+ .or. (iter >= max_iters_richards) &
+ .or. (.not. is_solvable) &
+ .or. wet2dry) THEN
+
+ IF ((dt_this < dt_explicit) &
+ .or. (iter >= max_iters_richards) &
+ .or. (.not. is_solvable) &
+ .or. wet2dry) THEN
+
+ dt_this = min(dt_this, dt_explicit)
+ q_this = q_0
+
+ CALL use_explicit_form ( &
+ lb, ub, dt_this, sp_dz, sp_zc, sp_zi, &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ vl_s_wa, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ q_this, q_wf_0, q_wt_0, &
+ ss_wf, ss_vl, ss_wt, ss_dp, waquifer, zwt, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ tol_q, tol_z, tol_v)
+
+ ENDIF
+
+ dt_done = dt_done + dt_this
+
+#ifdef CoLMDEBUG
+ IF (f2_norm(iter) < tol_richards * dt_this) THEN
+ count_implicit = count_implicit + 1
+ ELSEIF (iter >= max_iters_richards) then
+ count_explicit = count_explicit + 1
+ ELSEIF (wet2dry) THEN
+ count_wet2dry = count_wet2dry + 1
+ ENDIF
+#endif
+
+ EXIT
+
+ ENDIF
+
+ dr_dv = 0
+ vact = .false.
+
+ IF (ubc_typ == BC_RAINFALL) THEN
+
+ CALL var_perturb_rainfall ( &
+ blc(lb-1), ss_dp, dp_pb, dlt, vact(lb-1))
+
+ IF (vact(lb-1)) THEN
+ q_pb = q_this
+ q_wf_pb = q_wf
+ q_wt_pb = q_wt
+
+ lev_update(:) = .false.
+ lev_update(lb-1) = .true.
+ CALL flux_all ( &
+ lb, ub, sp_dz, sp_zc, sp_zi, &
+ vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ lev_update, .false., &
+ is_sat, has_wf, has_wt, &
+ ss_wf, ss_vl, ss_wt, dp_pb, zwt, psi, hk, &
+ q_pb, q_wf_pb, q_wt_pb, &
+ tol_q, tol_z, tol_p)
+
+ CALL water_balance ( &
+ lb, ub, sp_dz, dt_this, is_sat, vl_s, q_pb, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ ss_wf, ss_vl, ss_wt, dp_pb, waquifer, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ blc_pb)
+
+ dr_dv(:,lb-1) = (blc_pb - blc) / dlt
+
+ ENDIF
+
+ ENDIF
+
+ DO ilev = lb, ub
+ IF (.not. is_sat(ilev)) THEN
+
+ wf_pb = ss_wf
+ vl_pb = ss_vl
+ wt_pb = ss_wt
+ psi_pb = psi
+ hk_pb = hk
+
+ CALL var_perturb_level ( jsbl(ilev), blc(ilev), &
+ sp_dz(ilev), sp_zc(ilev), sp_zi(ilev), &
+ vl_s(ilev), vl_r(ilev), psi_s(ilev), hksat(ilev), &
+ nprm, prms(:,ilev), &
+ is_sat(ilev), has_wf(ilev), has_wt(ilev), &
+ q_this(ilev-1), q_this(ilev), q_wf(ilev), q_wt(ilev), &
+ wf_pb(ilev), vl_pb(ilev), wt_pb(ilev), dlt, &
+ psi_pb(ilev), hk_pb(ilev), vact(ilev), &
+ tol_v)
+
+ IF (vact(ilev)) THEN
+
+ q_pb = q_this
+ q_wf_pb = q_wf
+ q_wt_pb = q_wt
+
+ lev_update(:) = .false.
+ lev_update(ilev) = .true.
+ CALL flux_all ( &
+ lb, ub, sp_dz, sp_zc, sp_zi, &
+ vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ lev_update, .false., &
+ is_sat, has_wf, has_wt, &
+ wf_pb, vl_pb, wt_pb, ss_dp, zwt, psi_pb, hk_pb, &
+ q_pb, q_wf_pb, q_wt_pb, &
+ tol_q, tol_z, tol_p)
+
+ CALL water_balance ( &
+ lb, ub, sp_dz, dt_this, is_sat, vl_s, q_pb, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ wf_pb, vl_pb, wt_pb, ss_dp, waquifer, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ blc_pb)
+
+ dr_dv(:,ilev) = (blc_pb - blc) / dlt
+
+ ENDIF
+ ENDIF
+ ENDDO
+
+ IF (lbc_typ == BC_DRAINAGE) THEN
+
+ CALL var_perturb_drainage (sp_zi(ub), blc(ub+1), zwt, zwt_pb, dlt, vact(ub+1))
+
+ IF (vact(ub+1)) THEN
+ q_pb = q_this
+ q_wf_pb = q_wf
+ q_wt_pb = q_wt
+
+ waquifer_pb = - (zwt_pb - sp_zi(ub)) * (vl_s_wa &
+ - soil_vliq_from_psi (psi_s(ub)+(sp_zi(ub)-zwt_pb)*0.5, &
+ vl_s_wa, vl_r(ub), psi_s(ub), nprm, prms(:,ub)))
+
+ lev_update(:) = .false.
+ lev_update(ub+1) = .true.
+ CALL flux_all ( &
+ lb, ub, sp_dz, sp_zc, sp_zi, &
+ vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ lev_update, .false., &
+ is_sat, has_wf, has_wt, &
+ ss_wf, ss_vl, ss_wt, ss_dp, zwt_pb, psi, hk, &
+ q_pb, q_wf_pb, q_wt_pb, &
+ tol_q, tol_z, tol_p)
+
+ CALL water_balance ( &
+ lb, ub, sp_dz, dt_this, is_sat, vl_s, q_pb, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ ss_wf, ss_vl, ss_wt, ss_dp, waquifer_pb, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ blc_pb)
+
+ dr_dv(:,ub+1) = (blc_pb - blc) / dlt
+
+ ENDIF
+
+ ENDIF
+
+ DO ilev = lb-1, ub+1
+ vact(ilev) = vact(ilev) .and. (abs(dr_dv(ilev,ilev)) > tol_q)
+ ENDDO
+
+ CALL solve_least_squares_problem (ub-lb+3, dr_dv, vact, blc, dv)
+
+ IF (vact(lb-1)) THEN
+ ss_dp = ss_dp - dv(lb-1)
+ ss_dp = max(ss_dp, 0._r8)
+ ENDIF
+
+ DO ilev = lb, ub
+ IF (vact(ilev)) THEN
+ IF (jsbl(ilev) == 1) THEN
+ IF ((ss_wf(ilev) == sp_dz(ilev)) .and. (dv(ilev) > 0)) THEN
+ ss_wf(ilev) = ss_wf(ilev) - min(dv(ilev), sp_dz(ilev))
+
+ psi(ilev) = psi_s(ilev) + (1 - q_this(ilev)/hksat(ilev)) &
+ * min(dv(ilev),sp_dz(ilev)) * (sp_zc(ilev)-sp_zi(ilev-1))/sp_dz(ilev)
+ ss_vl(ilev) = soil_vliq_from_psi (psi(ilev), &
+ vl_s(ilev), vl_r(ilev), psi_s(ilev), nprm, prms(:,ilev))
+ hk(ilev) = soil_hk_from_psi (psi(ilev), &
+ psi_s(ilev), hksat(ilev), nprm, prms(:,ilev))
+ ELSE
+ ss_wf(ilev) = ss_wf(ilev) - dv(ilev)
+ ss_wf(ilev) = max(ss_wf(ilev), 0._r8)
+ ss_wf(ilev) = min(ss_wf(ilev), sp_dz(ilev)-ss_wt(ilev))
+ ENDIF
+ ENDIF
+
+ IF (jsbl(ilev) == 2) THEN
+ ss_vl(ilev) = ss_vl(ilev) - dv(ilev)
+ ss_vl(ilev) = max(ss_vl(ilev), tol_v)
+ ss_vl(ilev) = min(ss_vl(ilev), vl_s(ilev))
+ ENDIF
+
+ IF (jsbl(ilev) == 3) THEN
+ IF ((ss_wt(ilev) == sp_dz(ilev)) .and. (dv(ilev) > 0)) THEN
+ ss_wt(ilev) = ss_wt(ilev) - min(dv(ilev), sp_dz(ilev))
+
+ psi(ilev) = psi_s(ilev) - (1 - q_this(ilev-1)/hksat(ilev)) &
+ * min(dv(ilev),sp_dz(ilev)) * (sp_zi(ilev)-sp_zc(ilev))/sp_dz(ilev)
+ ss_vl(ilev) = soil_vliq_from_psi (psi(ilev), &
+ vl_s(ilev), vl_r(ilev), psi_s(ilev), nprm, prms(:,ilev))
+ hk(ilev) = soil_hk_from_psi (psi(ilev), &
+ psi_s(ilev), hksat(ilev), nprm, prms(:,ilev))
+ ELSE
+ ss_wt(ilev) = ss_wt(ilev) - dv(ilev)
+ ss_wt(ilev) = max(ss_wt(ilev), 0._r8)
+ ss_wt(ilev) = min(ss_wt(ilev), sp_dz(ilev)-ss_wf(ilev))
+ ENDIF
+ ENDIF
+ ENDIF
+
+ CALL check_and_update_level (sp_dz(ilev), &
+ vl_s(ilev), vl_r(ilev), psi_s(ilev), hksat(ilev), &
+ nprm, prms(:,ilev), &
+ is_sat(ilev), has_wf(ilev), has_wt(ilev), &
+ ss_wf(ilev), ss_vl(ilev), ss_wt(ilev), psi(ilev), hk(ilev), &
+ jsbl(ilev) == 2, tol_v)
+ ENDDO
+
+ IF (vact(ub+1)) THEN
+ zwt = zwt - dv(ub+1)
+ zwt = max(zwt, sp_zi(ub))
+ waquifer = - (zwt - sp_zi(ub)) * (vl_s_wa &
+ - soil_vliq_from_psi (psi_s(ub)+(sp_zi(ub)-zwt)*0.5, &
+ vl_s_wa, vl_r(ub), psi_s(ub), nprm, prms(:,ub)))
+ ENDIF
+
+ ENDDO
+
+ ss_q = ss_q + q_this * dt_this
+
+ wsum = sum(ss_vl * (sp_dz - ss_wt - ss_wf)) + sum((ss_wt + ss_wf) * vl_s)
+ IF (ubc_typ == BC_RAINFALL) THEN
+ wsum = wsum + ss_dp
+ ENDIF
+ IF (lbc_typ == BC_DRAINAGE) THEN
+ wsum = wsum + waquifer
+ ENDIF
+
+ werr = wsum - (wsum_m1 + ubc_val * dt_this - lbc_val * dt_this)
+
+ ENDDO
+
+ ss_q = ss_q / dt
+
+ DO ilev = lb, ub
+ IF (abs(sp_dz(ilev) - ss_wt(ilev)) > tol_z) THEN
+ ss_vl(ilev) = (ss_wf(ilev) * vl_s(ilev) &
+ + (sp_dz(ilev) - ss_wf(ilev) - ss_wt(ilev)) * ss_vl(ilev)) &
+ / (sp_dz(ilev) - ss_wt(ilev))
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE Richards_solver
+
+
+ ! ---- water balance ----
+ SUBROUTINE water_balance ( &
+ lb, ub, dz, dt, is_sat, vl_s, q, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ wf, vl, wt, dp, waquifer, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ blc, is_solvable, tol)
+
+ integer, intent(in) :: lb, ub
+
+ real(r8), intent(in) :: dz(lb:ub)
+ real(r8), intent(in) :: dt
+
+ logical, intent(in) :: is_sat(lb:ub)
+ real(r8), intent(in) :: vl_s (lb:ub)
+
+ real(r8), intent(in) :: q(lb-1:ub)
+
+ integer, intent(in) :: ubc_typ
+ real(r8), intent(in) :: ubc_val
+ integer, intent(in) :: lbc_typ
+ real(r8), intent(in) :: lbc_val
+
+ real(r8), intent(in) :: wf(lb:ub)
+ real(r8), intent(in) :: vl(lb:ub)
+ real(r8), intent(in) :: wt(lb:ub)
+ real(r8), intent(in) :: dp
+ real(r8), intent(in) :: waquifer
+
+ real(r8), intent(in) :: wf_m1(lb:ub)
+ real(r8), intent(in) :: vl_m1(lb:ub)
+ real(r8), intent(in) :: wt_m1(lb:ub)
+ real(r8), intent(in) :: dp_m1
+ real(r8), intent(in) :: waquifer_m1
+
+ real(r8), intent(out) :: blc(lb-1:ub+1)
+ logical, intent(out), optional :: is_solvable
+ real(r8), intent(in ), optional :: tol
+
+ ! Local variables
+ integer :: ilev, jlev
+ real(r8) :: dmss, qsum
+
+ blc(:) = 0
+
+ IF (ubc_typ == BC_RAINFALL) THEN
+ dmss = max(dp, 0._r8) - max(dp_m1, 0._r8)
+ qsum = ubc_val - q(lb-1)
+ blc(lb-1) = dmss - qsum * dt
+ ENDIF
+
+ ilev = lb - 1
+ DO jlev = lb, ub
+
+ dmss = (vl_s(jlev) - vl_m1(jlev)) * (wf(jlev) - wf_m1(jlev))
+ dmss = (vl_s(jlev) - vl_m1(jlev)) * (wt(jlev) - wt_m1(jlev)) + dmss
+ dmss = (dz(jlev) - wt(jlev) - wf(jlev)) * (vl(jlev) - vl_m1(jlev)) + dmss
+
+ qsum = q(jlev-1) - q(jlev)
+
+ IF (.not. is_sat(jlev)) THEN
+
+ ilev = jlev
+
+ IF ((ubc_typ /= BC_RAINFALL) .and. (blc(lb-1) /= 0)) THEN
+ blc(ilev) = blc(ilev) + blc(lb-1)
+ blc(lb-1) = 0
+ ENDIF
+ ENDIF
+
+ blc(ilev) = blc(ilev) + dmss - qsum * dt
+
+ ENDDO
+
+ IF (lbc_typ == BC_DRAINAGE) THEN
+ IF ((waquifer == 0) .and. (q(ub) >= 0)) THEN
+ blc(ilev) = blc(ilev) - waquifer_m1 - q(ub) * dt
+ ELSE
+ blc(ub+1) = waquifer - waquifer_m1 - q(ub) * dt
+
+ IF ((ubc_typ /= BC_RAINFALL) .and. (blc(lb-1) /= 0)) THEN
+ blc(ub+1) = blc(ub+1) + blc(lb-1)
+ blc(lb-1) = 0
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (present(is_solvable)) THEN
+ IF (present(tol)) THEN
+ is_solvable = (ubc_typ == BC_RAINFALL) .or. (blc(lb-1) < tol)
+ ELSE
+ is_solvable = (ubc_typ == BC_RAINFALL) .or. (blc(lb-1) == 0)
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE water_balance
+
+ ! ---- initialize sublevel structure ----
+ SUBROUTINE initialize_sublevel_structure ( &
+ lb, ub, dz, zbtm, &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ is_sat, has_wf, has_wt, &
+ wf, vl, wt, dp, psi, hk, &
+ tol_v, tol_z)
+
+ integer, intent(in) :: lb, ub
+ real(r8), intent(in) :: dz (lb:ub)
+ real(r8), intent(in) :: zbtm
+
+ real(r8), intent(in) :: vl_s (lb:ub)
+ real(r8), intent(in) :: vl_r (lb:ub)
+ real(r8), intent(in) :: psi_s (lb:ub)
+ real(r8), intent(in) :: hksat (lb:ub)
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms (nprm,lb:ub)
+
+ integer, intent(in) :: ubc_typ
+ real(r8), intent(in) :: ubc_val
+ integer, intent(in) :: lbc_typ
+ real(r8), intent(in) :: lbc_val
+
+ logical, intent(inout) :: is_sat(lb:ub)
+ logical, intent(inout) :: has_wf(lb:ub)
+ logical, intent(inout) :: has_wt(lb:ub)
+
+ real(r8), intent(inout) :: wf(lb:ub)
+ real(r8), intent(inout) :: vl(lb:ub)
+ real(r8), intent(inout) :: wt(lb:ub)
+ real(r8), intent(inout) :: dp
+
+ real(r8), intent(inout) :: psi(lb:ub)
+ real(r8), intent(inout) :: hk (lb:ub)
+
+ real(r8), intent(in) :: tol_v
+ real(r8), intent(in) :: tol_z
+
+ ! Local variables
+ integer :: ilev
+
+ DO ilev = lb, ub
+ is_sat(ilev) = (abs(vl(ilev) - vl_s(ilev)) < tol_v) &
+ .or. (abs(wf(ilev) + wt(ilev) - dz(ilev)) < tol_z)
+ ENDDO
+
+ IF (ubc_typ == BC_FIX_HEAD) THEN
+ IF (ubc_val < psi_s(lb)) THEN
+ IF (is_sat(lb)) THEN
+ is_sat(lb) = .false.
+
+ wf(lb) = 0
+ vl(lb) = vl_s(lb)
+ wt(lb) = 0.9 * dz(lb)
+ ELSEIF (wf(lb) >= tol_z) THEN
+ vl(lb) = (wf(lb)*vl_s(lb) + vl(lb)*(dz(lb)-wf(lb)-wt(lb))) / (dz(lb)-wt(lb))
+ wf(lb) = 0
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (lbc_typ == BC_FIX_HEAD) THEN
+ IF (lbc_val < psi_s(ub)) THEN
+ IF (is_sat(ub)) THEN
+ is_sat(ub) = .false.
+
+ wf(ub) = 0.9 * dz(ub)
+ vl(ub) = vl_s(ub)
+ wt(ub) = 0
+ ELSEIF (wt(ub) >= tol_z) THEN
+ vl(ub) = (wt(ub)*vl_s(ub) + vl(ub)*(dz(ub)-wf(ub)-wt(ub))) / (dz(ub)-wf(ub))
+ wt(ub) = 0
+ ENDIF
+ ENDIF
+ ENDIF
+
+ DO ilev = lb, ub
+ IF (is_sat(ilev)) THEN
+ wf(ilev) = 0
+ wt(ilev) = dz(ilev)
+ vl(ilev) = vl_s(ilev)
+ ELSE
+ IF (ilev > lb) THEN
+ IF (is_sat(ilev-1)) THEN
+ has_wf(ilev) = .true.
+ ELSE
+ has_wf(ilev) = (wf(ilev) >= tol_z) .or. (wt(ilev-1) >= tol_z)
+ ENDIF
+
+ IF (has_wf(ilev)) THEN
+ IF ((wf(ilev) < tol_z) .and. (psi_s(ilev) < psi_s(ilev-1))) THEN
+ wf(ilev) = 0.1 * (dz(ilev)-wt(ilev))
+ ENDIF
+ ENDIF
+ ELSE
+ SELECTCASE (ubc_typ)
+ CASE (BC_RAINFALL)
+ has_wf(lb) = (dp >= tol_z) .or. (wf(lb) >= tol_z)
+ CASE (BC_FIX_HEAD)
+ has_wf(lb) = (ubc_val > psi_s(lb)) .or. (wf(lb) >= tol_z)
+
+ IF (has_wf(lb) .and. (wf(lb) < tol_z)) THEN
+ wf(lb) = 0.01 * (dz(lb)-wt(lb))
+ ENDIF
+ CASE (BC_FIX_FLUX)
+ has_wf(lb) = wf(lb) >= tol_z
+ ENDSELECT
+ ENDIF
+
+ IF (ilev < ub) THEN
+ IF (is_sat(ilev+1)) THEN
+ has_wt(ilev) = .true.
+ ELSE
+ has_wt(ilev) = (wt(ilev) >= tol_z) .or. (wf(ilev+1) >= tol_z)
+ ENDIF
+
+ IF (has_wt(ilev)) THEN
+ IF ((wt(ilev) < tol_z) .and. (psi_s(ilev) < psi_s(ilev+1))) THEN
+ wt(ilev) = 0.1 * (dz(ilev)-wf(ilev))
+ ENDIF
+ ENDIF
+ ELSE
+ SELECTCASE (lbc_typ)
+ CASE (BC_DRAINAGE)
+ has_wt(ub) = (wt(ub) >= tol_z)
+ CASE (BC_FIX_HEAD)
+ has_wt(ub) = (lbc_val > psi_s(ub)) .or. (wt(ub) >= tol_z)
+
+ IF ((has_wt(ub)) .and. (wt(ub) < tol_z)) THEN
+ wt(ub) = 0.01 * (dz(ub)-wf(ub))
+ ENDIF
+ CASE (BC_FIX_FLUX)
+ has_wt(ub) = (wt(ub) >= tol_z)
+ ENDSELECT
+ ENDIF
+ ENDIF
+
+ CALL check_and_update_level ( dz(ilev), &
+ vl_s(ilev), vl_r(ilev), psi_s(ilev), hksat(ilev), &
+ nprm, prms(:,ilev), &
+ is_sat(ilev), has_wf(ilev), has_wt(ilev), &
+ wf(ilev), vl(ilev), wt(ilev), psi(ilev), hk(ilev), &
+ .true., tol_v)
+ ENDDO
+
+ END SUBROUTINE initialize_sublevel_structure
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE use_explicit_form ( &
+ lb, ub, dt, dz, sp_zc, sp_zi, &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ vl_s_wa, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ q, q_wf, q_wt, wf, vl, wt, dp, waquifer, zwt, &
+ wf_m1, vl_m1, wt_m1, dp_m1, waquifer_m1, &
+ tol_q, tol_z, tol_v)
+
+ integer, intent(in) :: lb, ub
+
+ real(r8), intent(in) :: dt
+
+ real(r8), intent(in) :: dz (lb:ub)
+ real(r8), intent(in) :: sp_zc (lb:ub)
+ real(r8), intent(in) :: sp_zi(lb-1:ub)
+
+ real(r8), intent(in) :: vl_s (lb:ub)
+ real(r8), intent(in) :: vl_r (lb:ub)
+ real(r8), intent(in) :: psi_s (lb:ub)
+ real(r8), intent(in) :: hksat (lb:ub)
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm,lb:ub)
+
+ real(r8), intent(in) :: vl_s_wa
+
+ integer, intent(in) :: ubc_typ
+ real(r8), intent(in) :: ubc_val
+ integer, intent(in) :: lbc_typ
+ real(r8), intent(in) :: lbc_val
+
+ real(r8), intent(inout) :: q (lb-1:ub)
+ real(r8), intent(in) :: q_wf (lb:ub)
+ real(r8), intent(in) :: q_wt (lb:ub)
+
+ real(r8), intent(inout) :: wf (lb:ub)
+ real(r8), intent(inout) :: vl (lb:ub)
+ real(r8), intent(inout) :: wt (lb:ub)
+ real(r8), intent(inout) :: dp
+ real(r8), intent(inout) :: waquifer
+ real(r8), intent(inout) :: zwt
+
+ real(r8), intent(in) :: wf_m1 (lb:ub)
+ real(r8), intent(in) :: vl_m1 (lb:ub)
+ real(r8), intent(in) :: wt_m1 (lb:ub)
+ real(r8), intent(in) :: dp_m1
+ real(r8), intent(in) :: waquifer_m1
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_z
+ real(r8), intent(in) :: tol_v
+
+ ! Local variables
+ integer :: ilev
+ real(r8) :: air_m1, wa_m1, dwat, dwat_s
+ real(r8) :: alp, zwf_this, zwt_this, vl_wa
+
+ real(r8) :: dmss, mblc
+
+ ! depleted : decrease outflux from top down
+ IF (ubc_typ == BC_RAINFALL) THEN
+ IF (dp_m1 < - (ubc_val - q(lb-1))*dt) THEN
+ q(lb-1) = dp_m1/dt + ubc_val
+ ENDIF
+ ENDIF
+
+ DO ilev = lb, ub
+
+ dwat = (q(ilev-1) - q(ilev)) * dt
+ wa_m1 = (wt_m1(ilev)+wf_m1(ilev)) * vl_s(ilev) &
+ + (dz(ilev)-wt_m1(ilev)-wf_m1(ilev)) * vl_m1(ilev)
+ IF (dwat <= - wa_m1) THEN
+ q(ilev) = q(ilev-1) + wa_m1/dt
+ ENDIF
+
+ ENDDO
+
+ IF ((lbc_typ == BC_FIX_FLUX) .and. (q(ub) < lbc_val)) THEN
+
+ q(ub) = lbc_val
+ DO ilev = ub, lb, -1
+ dwat = (q(ilev-1) - q(ilev)) * dt
+ wa_m1 = (wt_m1(ilev)+wf_m1(ilev)) * vl_s(ilev) &
+ + (dz(ilev)-wt_m1(ilev)-wf_m1(ilev)) * vl_m1(ilev)
+ IF (dwat <= - wa_m1) THEN
+ q(ilev-1) = q(ilev) - wa_m1/dt
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ ! overfilled : increase influx from bottom up
+ IF (lbc_typ == BC_DRAINAGE) THEN
+ IF (q(ub)*dt > -waquifer_m1) THEN
+ q(ub) = - waquifer_m1/dt
+ ENDIF
+ ENDIF
+
+ DO ilev = ub, lb, -1
+
+ dwat = (q(ilev-1) - q(ilev)) * dt
+ air_m1 = (vl_s(ilev) - vl_m1(ilev)) * (dz(ilev) - wt_m1(ilev) - wf_m1(ilev))
+ IF (dwat >= air_m1) THEN
+ q(ilev-1) = q(ilev) + air_m1/dt
+ ENDIF
+
+ ENDDO
+
+ IF ((ubc_typ == BC_FIX_FLUX) .and. (q(lb-1) < ubc_val)) THEN
+
+ q(lb-1) = ubc_val
+ DO ilev = lb, ub
+ dwat = (q(ilev-1) - q(ilev)) * dt
+ air_m1 = (vl_s(ilev) - vl_m1(ilev)) * (dz(ilev) - wt_m1(ilev) - wf_m1(ilev))
+ IF (dwat >= air_m1) THEN
+ q(ilev) = q(ilev-1) - air_m1/dt
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ ! update prognostic variables : dp, wf, vl, wt, zwt
+ IF (ubc_typ == BC_RAINFALL) THEN
+ dp = max(0., dp_m1 + (ubc_val - q(lb-1))*dt)
+ ENDIF
+
+ DO ilev = lb, ub
+
+ dwat = (q(ilev-1) - q(ilev)) * dt
+
+ wt(ilev) = 0.
+ wf(ilev) = 0.
+ vl(ilev) = ((wt_m1(ilev)+wf_m1(ilev)) * vl_s(ilev) &
+ + (dz(ilev)-wt_m1(ilev)-wf_m1(ilev)) * vl_m1(ilev) + dwat) / dz(ilev)
+
+ ENDDO
+
+ IF (lbc_typ == BC_DRAINAGE) THEN
+ waquifer = waquifer_m1 + q(ub)*dt
+ CALL get_zwt_from_wa ( &
+ vl_s_wa, vl_r(ub), psi_s(ub), hksat(ub), nprm, prms(:,ub), tol_v, tol_z, &
+ waquifer, sp_zi(ub), zwt)
+ ENDIF
+
+ END SUBROUTINE use_explicit_form
+
+ !----------------------------------------------------------------------
+ SUBROUTINE var_perturb_level ( jsbl, blc, &
+ dz, zc, zi, vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ is_sat, has_wf, has_wt, qin, qout, q_wf, q_wt, &
+ wf_p, vl_p, wt_p, delta, psi_p, hk_p, is_act, &
+ tol_v)
+
+ integer, intent(out) :: jsbl
+
+ real(r8), intent(in) :: blc
+
+ real(r8), intent(in) :: dz, zc, zi
+ real(r8), intent(in) :: vl_s, vl_r, psi_s, hksat
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+
+ logical, intent(in) :: is_sat, has_wf, has_wt
+ real(r8), intent(in) :: qin, qout, q_wf, q_wt
+
+ real(r8), intent(inout) :: wf_p, vl_p, wt_p
+ real(r8), intent(out) :: delta
+ real(r8), intent(inout) :: psi_p, hk_p
+ logical, intent(out) :: is_act
+
+ real(r8), intent(in) :: tol_v
+
+ ! Local variables
+ real(r8), parameter :: vstep = 1.0e-6_r8
+ real(r8), parameter :: wstep = 1.0e-1_r8
+
+ jsbl = 2
+
+ IF (has_wt) THEN
+
+ IF ((wt_p == dz) .or. &
+ ((blc >= 0) .and. (q_wt < qout) .and. (wt_p > 0) .and. (vl_p < vl_s))) THEN
+ ! reduce water table
+
+ jsbl = 3
+
+ delta = - min(wstep, wt_p * 0.1_r8)
+
+ IF (wt_p == dz) THEN
+ psi_p = psi_s - (1 - qin/hksat) * (-delta)*(zi-zc)/dz
+ vl_p = soil_vliq_from_psi (psi_p, vl_s, vl_r, psi_s, nprm, prms)
+ hk_p = soil_hk_from_psi (psi_p, psi_s, hksat, nprm, prms)
+ ENDIF
+
+ wt_p = wt_p + delta
+
+ ELSEIF ((blc < 0) .and. (q_wt > qout) .and. (vl_p < vl_s)) THEN
+ ! increase water table
+
+ jsbl = 3
+
+ delta = min(wstep, (dz - wf_p - wt_p) * 0.1_r8)
+ wt_p = wt_p + delta
+
+ ENDIF
+
+ ENDIF
+
+ IF ((jsbl == 2) .and. has_wf) THEN
+
+ IF ((wf_p == dz) .or. &
+ ((blc >= 0) .and. (qin < q_wf) .and. (wf_p > 0) .and. (vl_p < vl_s))) THEN
+ ! reduce wetting front
+
+ jsbl = 1
+
+ delta = - min(wstep, wf_p * 0.1_r8)
+ IF (wf_p == dz) THEN
+ psi_p = psi_s + (1 - qout/hksat) * (-delta)*(dz-(zi-zc))/dz
+ vl_p = soil_vliq_from_psi (psi_p, vl_s, vl_r, psi_s, nprm, prms)
+ hk_p = soil_hk_from_psi (psi_p, psi_s, hksat, nprm, prms)
+ ENDIF
+
+ wf_p = wf_p + delta
+
+ ELSEIF ((blc < 0) .and. (qin > q_wf) .and. (vl_p < vl_s)) THEN
+ ! increase wetting front
+
+ jsbl = 1
+
+ delta = min(wstep, (dz - wf_p - wt_p) * 0.1_r8)
+ wf_p = wf_p + delta
+
+ ENDIF
+
+ ENDIF
+
+ IF (jsbl == 2) THEN
+
+ IF (((blc > 0) .and. (vl_p > vl_r + tol_v)) .or. (vl_p >= vl_s)) THEN
+ ! reduce water content
+ delta = - min(vstep, (vl_p - vl_r - tol_v) * 0.5_r8)
+ ELSEIF (((blc <= 0) .and. (vl_p < vl_s)) .or. (vl_p <= vl_r+tol_v)) THEN
+ ! increase water content
+ delta = + min(vstep, (vl_s - vl_p) * 0.5_r8)
+ ELSE
+ delta = 0
+ ENDIF
+
+ vl_p = vl_p + delta
+
+ ENDIF
+
+ is_act = (delta /= 0)
+
+ IF (is_act) THEN
+ CALL check_and_update_level (dz, &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ is_sat, has_wf, has_wt, wf_p, vl_p, wt_p, psi_p, hk_p, &
+ jsbl == 2, tol_v)
+ ENDIF
+
+ END SUBROUTINE var_perturb_level
+
+ !----------------------------------------------------------------
+ SUBROUTINE var_perturb_rainfall ( &
+ blc_srf, dp, dp_p, delta, is_act)
+
+ real(r8), intent(in) :: blc_srf
+
+ real(r8), intent(in) :: dp
+ real(r8), intent(out) :: dp_p
+ real(r8), intent(out) :: delta
+ logical, intent(out) :: is_act
+
+ ! Local variables
+ real(r8), parameter :: wstep = 1.0e-1_r8
+
+ delta = 0
+
+ IF (blc_srf > 0) THEN
+ IF (dp > 0) THEN
+ delta = - min(wstep, dp * 0.5_r8)
+ ENDIF
+ ELSEIF (blc_srf < 0) THEN
+ delta = wstep
+ ENDIF
+
+ dp_p = dp + delta
+ is_act = (delta /= 0)
+
+ END SUBROUTINE var_perturb_rainfall
+
+ !----------------------------------------------------------------
+ SUBROUTINE var_perturb_drainage ( &
+ zmin, blc_btm, zwt, zwt_p, delta, is_act)
+
+ real(r8), intent(in) :: zmin
+
+ real(r8), intent(in) :: blc_btm
+
+ real(r8), intent(in) :: zwt
+ real(r8), intent(out) :: zwt_p
+ real(r8), intent(out) :: delta
+ logical, intent(out) :: is_act
+
+ ! Local variables
+ real(r8), parameter :: wstep = 1.0e-1_r8
+
+ delta = 0
+
+ IF (blc_btm > 0) THEN
+ delta = wstep
+ ELSEIF (blc_btm < 0) THEN
+ delta = - min(max((zwt-zmin)*0.5_r8,0.0), wstep)
+ ENDIF
+
+ zwt_p = zwt + delta
+ is_act = (delta /= 0)
+
+ END SUBROUTINE var_perturb_drainage
+
+
+ !----------------------------------------------------------------
+ SUBROUTINE check_and_update_level ( dz, &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, &
+ is_sat, has_wf, has_wt, &
+ wf, vl, wt, psi, hk, &
+ is_update_psi_hk, tol_v)
+
+ real(r8), intent(in) :: dz
+ real(r8), intent(in) :: vl_s, vl_r, psi_s, hksat
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+ logical, intent(in) :: is_sat, has_wf, has_wt
+
+ real(r8), intent(inout) :: wf, vl, wt
+ real(r8), intent(inout) :: psi, hk
+
+ logical, intent(in) :: is_update_psi_hk
+
+ real(r8), intent(in) :: tol_v
+
+ ! Local variables
+ real(r8) :: alpha
+
+ IF (.not. is_sat) THEN
+
+ IF (has_wf) THEN
+ wf = min(max(wf, 0._r8), dz)
+ ELSE
+ wf = 0
+ ENDIF
+
+ IF (has_wt) THEN
+ wt = min(max(wt, 0._r8), dz)
+ ELSE
+ wt = 0
+ ENDIF
+
+ IF (has_wf .and. has_wt) THEN
+ IF (wf + wt > dz) THEN
+ alpha = wf / (wf + wt)
+ wf = dz * alpha
+ wt = dz * (1.0_r8 - alpha)
+ ENDIF
+ ENDIF
+
+ vl = min(vl, vl_s)
+ vl = max(vl, tol_v)
+
+ IF (is_update_psi_hk) THEN
+ psi = soil_psi_from_vliq (vl, vl_s, vl_r, psi_s, nprm, prms)
+ hk = soil_hk_from_psi (psi, psi_s, hksat, nprm, prms)
+ ENDIF
+ ELSE
+ vl = vl_s
+ psi = psi_s
+ hk = hksat
+ ENDIF
+
+ END SUBROUTINE check_and_update_level
+
+
+ !----------------------------------------------------------------------
+ SUBROUTINE flux_all ( &
+ lb, ub, dz, sp_zc, sp_zi, &
+ vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ lev_update, is_update_sublevel, &
+ is_sat, has_wf, has_wt, &
+ wf, vl, wt, dp, zwt, psi_us, hk_us, &
+ qq, qq_wf, qq_wt, &
+ tol_q, tol_z, tol_p)
+
+ integer, intent(in) :: lb, ub
+
+ real(r8), intent(in) :: dz (lb:ub)
+ real(r8), intent(in) :: sp_zc (lb:ub)
+ real(r8), intent(in) :: sp_zi (lb-1:ub)
+
+ real(r8), intent(in) :: vl_s (lb:ub)
+ real(r8), intent(in) :: psi_s (lb:ub)
+ real(r8), intent(in) :: hksat (lb:ub)
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms (nprm,lb:ub)
+
+ integer, intent(in) :: ubc_typ
+ real(r8), intent(in) :: ubc_val
+ integer, intent(in) :: lbc_typ
+ real(r8), intent(in) :: lbc_val
+
+ logical, intent(in) :: lev_update (lb-1:ub+1)
+ logical, intent(in) :: is_update_sublevel
+
+ logical, intent(inout) :: is_sat (lb:ub)
+ logical, intent(inout) :: has_wf (lb:ub)
+ logical, intent(inout) :: has_wt (lb:ub)
+
+ real(r8), intent(inout) :: wf (lb:ub)
+ real(r8), intent(inout) :: vl (lb:ub)
+ real(r8), intent(inout) :: wt (lb:ub)
+ real(r8), intent(inout) :: dp
+ real(r8), intent(inout) :: zwt
+ real(r8), intent(in) :: psi_us (lb:ub)
+ real(r8), intent(in) :: hk_us (lb:ub)
+
+ real(r8), intent(inout) :: qq (lb-1:ub)
+ real(r8), intent(inout) :: qq_wf (lb:ub)
+ real(r8), intent(inout) :: qq_wt (lb:ub)
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_z
+ real(r8), intent(in) :: tol_p
+
+ ! Local variables
+ integer :: ilev_u, ilev_l
+ real(r8) :: hk_top, pbtm, hk_btm
+ real(r8) :: dz_this, dz_upp, dz_low
+ logical :: has_sat_zone
+ real(r8) :: psi_i, hk_i
+ real(r8) :: qtest
+
+
+ ilev_u = lb - 1
+ ilev_l = find_unsat_lev_lower (is_sat, lb, ub, ilev_u+1)
+
+ DO WHILE (.true.)
+
+ IF (lev_update(ilev_u) .or. lev_update(ilev_l)) THEN
+
+ IF (ilev_l == lb) THEN
+ ! CASE 1: water flux on top
+
+ dz_this = (dz(lb)-wt(lb)-wf(lb)) * (sp_zc(lb)-sp_zi(lb-1))/dz(lb)
+
+ SELECTCASE (ubc_typ)
+ CASE (BC_FIX_HEAD)
+
+ IF (has_wf(lb)) THEN
+ qq(lb-1) = - hksat(lb) * ((psi_s(lb) - ubc_val) / wf(lb) - 1)
+ ELSE
+ hk_top = soil_hk_from_psi (ubc_val, &
+ psi_s(lb), hksat(lb), nprm, prms(:,lb))
+ qq(lb-1) = flux_inside_hm_soil ( &
+ psi_s(lb), hksat(lb), nprm, prms(:,lb), &
+ dz_this, ubc_val, psi_us(lb), hk_top, hk_us(lb))
+ ENDIF
+
+ CASE (BC_RAINFALL)
+
+ IF (has_wf(lb) .and. (wf(lb) >= tol_z)) THEN
+
+ qq(lb-1) = - hksat(lb) * ((psi_s(lb) - dp) / wf(lb) - 1)
+
+ ELSE
+
+ IF (dp > tol_z) THEN
+ qq(lb-1) = flux_inside_hm_soil ( &
+ psi_s(lb), hksat(lb), nprm, prms(:,lb), &
+ dz_this, dp, psi_us(lb), hksat(lb), hk_us(lb))
+ ELSE
+ qtest = flux_inside_hm_soil ( &
+ psi_s(lb), hksat(lb), nprm, prms(:,lb), &
+ dz_this, psi_s(lb), psi_us(lb), hksat(lb), hk_us(lb))
+
+ qq(lb-1) = min(ubc_val, qtest)
+
+ IF (is_update_sublevel) THEN
+ IF (qq(lb-1) > qtest) THEN
+ has_wf(lb) = .true.
+ wf(lb) = 0.0
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ENDIF
+
+ CASE (BC_FIX_FLUX)
+
+ qq(lb-1) = ubc_val
+
+ IF (is_update_sublevel) THEN
+ IF ((.not. has_wf(lb)) .and. (ubc_val > hksat(lb))) THEN
+ qtest = flux_inside_hm_soil ( &
+ psi_s(lb), hksat(lb), nprm, prms(:,lb), &
+ dz_this, psi_s(lb), psi_us(lb), hksat(lb), hk_us(lb))
+ IF (qq(lb-1) > qtest) THEN
+ has_wf(lb) = .true.
+ wf(lb) = 0.0
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ENDSELECT
+
+ IF ((has_wf(lb)) .and. (dz_this >= tol_z)) THEN
+ qq_wf(lb) = flux_inside_hm_soil ( &
+ psi_s(lb), hksat(lb), nprm, prms(:,lb), &
+ dz_this, psi_s(lb), psi_us(lb), hksat(lb), hk_us(lb))
+ ELSE
+ IF (has_wf(lb)) THEN
+ qq_wf(lb) = qq(lb)
+ ELSE
+ qq_wf(lb) = qq(lb-1)
+ ENDIF
+ ENDIF
+
+ ELSEIF (ilev_u == ub) THEN
+ ! CASE 2: water flux at bottom
+
+ dz_this = (dz(ub) - wf(ub) - wt(ub)) * (sp_zi(ub) - sp_zc(ub))/ dz(ub)
+
+ SELECTCASE (lbc_typ)
+ CASE (BC_FIX_HEAD)
+
+ IF (has_wt(ub)) THEN
+ qq(ub) = - hksat(ub) * ((lbc_val - psi_s(ub))/wt(ub) - 1)
+ ELSE
+ hk_btm = soil_hk_from_psi (lbc_val, &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub))
+ qq(ub) = flux_inside_hm_soil ( &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub), &
+ dz_this, psi_us(ub), lbc_val, hk_us(ub), hk_btm)
+ ENDIF
+
+ CASE (BC_DRAINAGE)
+
+ IF (has_wt(ub)) THEN
+ IF (zwt > sp_zi(ub)) THEN
+ qq(ub) = hksat(ub)
+ ELSE
+ qq(ub) = 0
+ ENDIF
+ ELSE
+ IF (zwt > sp_zi(ub)) THEN
+ pbtm = psi_s(ub) + sp_zi(ub) - zwt
+ hk_btm = soil_hk_from_psi (pbtm, &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub))
+ qq(ub) = flux_inside_hm_soil ( &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub), &
+ dz_this, psi_us(ub), pbtm, hk_us(ub), hk_btm)
+ ELSE
+ qq(ub) = flux_inside_hm_soil ( &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub), &
+ dz_this, psi_us(ub), psi_s(ub), hk_us(ub), hksat(ub))
+
+ IF (is_update_sublevel) THEN
+ IF (qq(ub) > 0) THEN
+ has_wt(ub) = .true.
+ wt(ub) = 0
+ qq(ub) = 0
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+ CASE (BC_FIX_FLUX)
+
+ qq(ub) = lbc_val
+
+ IF (is_update_sublevel) THEN
+ IF ((.not. has_wt(ub)) .and. (lbc_val < hksat(ub))) THEN
+ qtest = flux_inside_hm_soil ( &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub), &
+ dz_this, psi_us(ub), psi_s(ub), hk_us(ub), hksat(ub))
+
+ IF (qtest > lbc_val) THEN
+ has_wt(ub) = .true.
+ wt(ub) = 0
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ENDSELECT
+
+ IF ((has_wt(ub)) .and. (dz_this >= tol_z)) THEN
+ qq_wt(ub) = flux_inside_hm_soil ( &
+ psi_s(ub), hksat(ub), nprm, prms(:,ub), &
+ dz_this, psi_us(ub), psi_s(ub), hk_us(ub), hksat(ub))
+ ELSE
+ IF (has_wt(ub)) THEN
+ qq_wt(ub) = qq(ub-1)
+ ELSE
+ qq_wt(ub) = qq(ub)
+ ENDIF
+ ENDIF
+
+ ELSE
+ ! CASE 3: inside soil column
+
+ IF ((ilev_u == lb-1) .or. (ilev_l == ub+1)) THEN
+ has_sat_zone = .true.
+ ELSEIF (has_wf(ilev_l)) THEN
+ has_sat_zone = .true.
+ IF (ilev_l == ilev_u+1) THEN
+ IF ((wf(ilev_l) < tol_z) .and. (wt(ilev_u) < tol_z)) THEN
+ has_sat_zone = .false.
+ ENDIF
+ ENDIF
+ ELSE
+ has_sat_zone = .false.
+ ENDIF
+
+ IF (has_sat_zone) THEN
+ ! CASE 3(1): inside soil column, saturated zone
+ CALL flux_sat_zone_all ( &
+ lb, ub, max(ilev_u,lb), min(ilev_l,ub), &
+ dz, sp_zc, sp_zi, vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ is_sat, has_wf, has_wt, is_update_sublevel, &
+ wf, vl, wt, dp, zwt, psi_us, hk_us, &
+ qq, qq_wt, qq_wf, tol_q, tol_z, tol_p)
+
+ ELSE
+ ! CASE 3(2): inside soil column, unsaturated zone
+
+ dz_upp = (dz(ilev_u) - wf(ilev_u)) * (sp_zi(ilev_u)-sp_zc(ilev_u))/dz(ilev_u)
+ dz_low = (dz(ilev_l) - wt(ilev_l)) * (sp_zc(ilev_l)-sp_zi(ilev_u))/dz(ilev_l)
+
+ IF ((dz_upp >= tol_z) .and. (dz_low >= tol_z)) THEN
+
+ CALL flux_at_unsaturated_interface (nprm, &
+ psi_s(ilev_u), hksat(ilev_u), prms(:,ilev_u), dz_upp, psi_us(ilev_u), hk_us(ilev_u), &
+ psi_s(ilev_l), hksat(ilev_l), prms(:,ilev_l), dz_low, psi_us(ilev_l), hk_us(ilev_l), &
+ qq_wt(ilev_u), qq_wf(ilev_l), tol_q, tol_p)
+
+ IF (abs(qq_wt(ilev_u) - qq_wf(ilev_l)) < tol_q) THEN
+
+ qq(ilev_u) = (qq_wt(ilev_u) + qq_wf(ilev_l)) * 0.5_r8
+ qq_wt(ilev_u) = qq(ilev_u)
+ qq_wf(ilev_l) = qq(ilev_u)
+
+ IF (is_update_sublevel) THEN
+ has_wt(ilev_u) = .false.
+ has_wf(ilev_l) = .false.
+ ENDIF
+
+ ELSEIF (qq_wt(ilev_u) > qq_wf(ilev_l)) THEN
+ IF (is_update_sublevel) THEN
+ has_wt(ilev_u) = .true.
+ wt(ilev_u) = 0
+
+ has_wf(ilev_l) = .true.
+ wf(ilev_l) = 0
+ ENDIF
+
+ IF (has_wt(ilev_u) .and. has_wf(ilev_l)) THEN
+ IF (psi_s(ilev_u) >= psi_s(ilev_l)) THEN
+ qq(ilev_u) = qq_wt(ilev_u)
+ ELSE
+ qq(ilev_u) = qq_wf(ilev_l)
+ ENDIF
+ ELSE
+ qq(ilev_u) = (qq_wt(ilev_u) + qq_wf(ilev_l)) * 0.5_r8
+ ENDIF
+ ENDIF
+
+ ELSEIF ((dz_upp >= tol_z) .and. (dz_low < tol_z)) THEN
+
+ psi_i = min(psi_s(ilev_u), psi_s(ilev_l))
+ hk_i = soil_hk_from_psi (psi_i, &
+ psi_s(ilev_u), hksat(ilev_u), nprm, prms(:,ilev_u))
+ qq(ilev_u) = flux_inside_hm_soil ( &
+ psi_s(ilev_u), hksat(ilev_u), nprm, prms(:,ilev_u), &
+ dz_upp, psi_us(ilev_u), psi_i, hk_us(ilev_u), hk_i)
+
+ qq_wt(ilev_u) = qq(ilev_u)
+ qq_wf(ilev_l) = qq(ilev_u)
+ qq_wt(ilev_l) = qq(ilev_u)
+
+ ELSEIF ((dz_upp < tol_z) .and. (dz_low >= tol_z)) THEN
+
+ psi_i = min(psi_s(ilev_u), psi_s(ilev_l))
+ hk_i = soil_hk_from_psi (psi_i, &
+ psi_s(ilev_l), hksat(ilev_l), nprm, prms(:,ilev_l))
+ qq(ilev_u) = flux_inside_hm_soil ( &
+ psi_s(ilev_l), hksat(ilev_l), nprm, prms(:,ilev_l), &
+ dz_low, psi_i, psi_us(ilev_l), hk_i, hk_us(ilev_l))
+
+ qq_wf(ilev_u) = qq(ilev_u)
+ qq_wt(ilev_u) = qq(ilev_u)
+ qq_wf(ilev_l) = qq(ilev_u)
+
+ ELSEIF ((dz_upp < tol_z) .and. (dz_low < tol_z)) THEN
+ ! This CASE does not exist in principle.
+
+ qq(ilev_u) = min(hksat(ilev_u), hksat(ilev_l))
+
+ qq_wf(ilev_u) = qq(ilev_u)
+ qq_wt(ilev_u) = qq(ilev_u)
+ qq_wf(ilev_l) = qq(ilev_u)
+ qq_wt(ilev_l) = qq(ilev_u)
+
+ ENDIF
+ ENDIF
+
+ ENDIF
+ ENDIF
+
+ IF (ilev_l == ub+1) THEN
+ EXIT
+ ELSE
+ ilev_u = ilev_l
+ ilev_l = find_unsat_lev_lower (is_sat, lb, ub, ilev_u+1)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE flux_all
+
+
+ !-------------------------------------------------------------------
+ SUBROUTINE flux_sat_zone_all ( &
+ lb, ub, i_stt, i_end, dz, sp_zc, sp_zi, &
+ vl_s, psi_s, hksat, nprm, prms, &
+ ubc_typ, ubc_val, lbc_typ, lbc_val, &
+ is_sat, has_wf, has_wt, is_update_sublevel, &
+ wf, vl, wt, wdsrf, zwt, psi_us, hk_us, &
+ qq, qq_wt, qq_wf, tol_q, tol_z, tol_p)
+
+ integer, intent(in) :: lb, ub
+ integer, intent(in) :: i_stt, i_end
+
+ real(r8), intent(in) :: dz (lb:ub)
+ real(r8), intent(in) :: sp_zc (lb:ub)
+ real(r8), intent(in) :: sp_zi (lb-1:ub)
+
+ real(r8), intent(in) :: vl_s (lb:ub)
+ real(r8), intent(in) :: psi_s (lb:ub)
+ real(r8), intent(in) :: hksat (lb:ub)
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms (nprm,lb:ub)
+
+ integer, intent(in) :: ubc_typ
+ real(r8), intent(in) :: ubc_val
+ integer, intent(in) :: lbc_typ
+ real(r8), intent(in) :: lbc_val
+
+ logical, intent(inout) :: is_sat (lb:ub)
+ logical, intent(inout) :: has_wf (lb:ub)
+ logical, intent(inout) :: has_wt (lb:ub)
+ logical, intent(in) :: is_update_sublevel
+
+ real(r8), intent(inout) :: wf (lb:ub)
+ real(r8), intent(inout) :: vl (lb:ub)
+ real(r8), intent(inout) :: wt (lb:ub)
+ real(r8), intent(in) :: wdsrf
+ real(r8), intent(in) :: zwt
+ real(r8), intent(in) :: psi_us (lb:ub)
+ real(r8), intent(in) :: hk_us (lb:ub)
+
+ real(r8), intent(inout) :: qq (lb-1:ub)
+ real(r8), intent(inout) :: qq_wt (lb:ub)
+ real(r8), intent(inout) :: qq_wf (lb:ub)
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_z
+ real(r8), intent(in) :: tol_p
+
+ ! Local variables
+ logical :: top_at_ground, top_at_interface, top_inside_level
+ logical :: btm_at_bottom, btm_at_interface, btm_inside_level
+
+ integer :: i_s, i_e, ilev, iface
+
+ integer :: nlev_sat
+ real(r8), allocatable :: qlc (:)
+ real(r8), allocatable :: dz_sat (:)
+ real(r8), allocatable :: psi_sat (:)
+ real(r8), allocatable :: hk_sat (:)
+
+ real(r8) :: ptop, pbtm, qtop, qupper, qlower
+ real(r8) :: dz_us_top, dz_us_btm
+
+ logical :: is_trans
+
+ top_at_ground = (i_stt == lb) .and. is_sat(i_stt)
+ top_at_interface = (.not. top_at_ground) .and. (wt(i_stt) < tol_z)
+ top_inside_level = .not. (top_at_ground .or. top_at_interface)
+
+ btm_at_bottom = (i_end == ub) .and. is_sat(i_end)
+ btm_at_interface = (.not. btm_at_bottom) .and. (wf(i_end) < tol_z)
+ btm_inside_level = .not. (btm_at_bottom .or. btm_at_interface)
+
+ IF (top_at_interface) THEN
+ i_s = i_stt + 1
+ ELSE
+ i_s = i_stt
+ ENDIF
+
+ IF (btm_at_interface) THEN
+ i_e = i_end - 1
+ ELSE
+ i_e = i_end
+ ENDIF
+
+ nlev_sat = i_e - i_s + 1
+
+ allocate (dz_sat (i_s:i_e))
+ allocate (psi_sat (i_s:i_e))
+ allocate (hk_sat (i_s:i_e))
+ allocate (qlc (i_s:i_e))
+
+ DO ilev = i_s, i_e
+ dz_sat (ilev) = dz (ilev)
+ psi_sat(ilev) = psi_s(ilev)
+ hk_sat (ilev) = hksat(ilev)
+ ENDDO
+
+ IF (top_inside_level) dz_sat(i_s) = wt(i_stt)
+ IF (btm_inside_level) dz_sat(i_e) = wf(i_end)
+
+ IF (.not. top_at_ground) THEN
+ dz_us_top = (dz(i_stt) - wt(i_stt) - wf(i_stt)) &
+ * (sp_zi(i_stt) - sp_zc(i_stt)) / dz(i_stt)
+ ENDIF
+
+ IF (.not. btm_at_bottom) THEN
+ dz_us_btm = (dz(i_end) - wt(i_end) - wf(i_end)) &
+ * (sp_zc(i_end) - sp_zi(i_end-1)) / dz(i_end)
+ ENDIF
+
+ ! Case 1
+ IF (top_at_ground .and. btm_at_bottom) THEN
+
+ ! Case 1-1
+ IF ((ubc_typ == BC_FIX_HEAD) .and. (lbc_typ == BC_FIX_HEAD)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, ubc_val, lbc_val, qlc)
+ ENDIF
+
+ ! Case 1-2
+ IF ((ubc_typ == BC_RAINFALL) .and. (lbc_typ == BC_FIX_HEAD)) THEN
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, wdsrf, lbc_val, qlc)
+
+ ENDIF
+
+ ! Case 1-3
+ IF ((ubc_typ == BC_FIX_FLUX) .and. (lbc_typ == BC_FIX_HEAD)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, psi_s(lb), lbc_val, qlc, &
+ flux_top = ubc_val)
+ ENDIF
+
+ ! Case 1-4
+ IF ((ubc_typ == BC_FIX_HEAD) .and. (lbc_typ == BC_FIX_FLUX)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, ubc_val, psi_s(ub), qlc, &
+ flux_btm = lbc_val)
+ ENDIF
+
+ ! Case 1-5
+ IF ((ubc_typ == BC_RAINFALL) .and. (lbc_typ == BC_FIX_FLUX)) THEN
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, wdsrf, psi_s(ub), qlc, &
+ flux_btm = lbc_val)
+
+ ENDIF
+
+ ! Case 1-6
+ IF ((ubc_typ == BC_FIX_FLUX) .and. (lbc_typ == BC_FIX_FLUX)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, psi_s(lb), psi_s(ub), qlc, &
+ flux_top = ubc_val, flux_btm = lbc_val)
+ ENDIF
+
+ ! Case 1-7
+ IF ((ubc_typ == BC_FIX_HEAD) .and. (lbc_typ == BC_DRAINAGE)) THEN
+ IF (zwt > sp_zi(ub)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, ubc_val, psi_s(ub), qlc)
+ ELSE
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, ubc_val, psi_s(ub), qlc, &
+ flux_btm = 0.0)
+ ENDIF
+ ENDIF
+
+ ! Case 1-8
+ IF ((ubc_typ == BC_RAINFALL) .and. (lbc_typ == BC_DRAINAGE)) THEN
+ IF (zwt > sp_zi(ub)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, wdsrf, psi_s(ub), qlc)
+ ELSE
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, wdsrf, psi_s(ub), qlc, &
+ flux_btm = 0.0)
+ ENDIF
+
+ ENDIF
+
+ ! Case 1-9
+ IF ((ubc_typ == BC_FIX_FLUX) .and. (lbc_typ == BC_DRAINAGE)) THEN
+ IF (zwt > sp_zi(ub)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, psi_s(lb), psi_s(ub), qlc, &
+ flux_top = ubc_val)
+ ELSE
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, psi_s(lb), psi_s(ub), qlc, &
+ flux_top = ubc_val, flux_btm = 0.0)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! Case 2
+ IF (top_at_ground .and. btm_at_interface) THEN
+
+ SELECTCASE (ubc_typ)
+ CASE (BC_FIX_HEAD)
+
+ CALL flux_btm_transitive_interface ( &
+ psi_s(i_end), hksat(i_end), nprm, prms(:,i_end), &
+ dz_us_btm, psi_us(i_end), hk_us(i_end), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, ubc_val, &
+ qq_wf(i_end), qlc, tol_q, tol_z, tol_p)
+
+ CASE (BC_FIX_FLUX)
+
+ CALL flux_btm_transitive_interface ( &
+ psi_s(i_end), hksat(i_end), nprm, prms(:,i_end), &
+ dz_us_btm, psi_us(i_end), hk_us(i_end), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_s(lb), &
+ qq_wf(i_end), qlc, tol_q, tol_z, tol_p, &
+ flux_top = ubc_val)
+
+ CASE (BC_RAINFALL)
+
+ CALL flux_btm_transitive_interface ( &
+ psi_s(i_end), hksat(i_end), nprm, prms(:,i_end), &
+ dz_us_btm, psi_us(i_end), hk_us(i_end), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, wdsrf, &
+ qq_wf(i_end), qlc, tol_q, tol_z, tol_p)
+
+ ENDSELECT
+
+ ENDIF
+
+ ! Case 3
+ IF (top_at_ground .and. btm_inside_level) THEN
+
+ SELECTCASE (ubc_typ)
+ CASE (BC_FIX_HEAD)
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, dz_sat, psi_sat, &
+ hk_sat, ubc_val, psi_s(i_end), qlc)
+
+ CASE (BC_FIX_FLUX)
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, dz_sat, psi_sat, &
+ hk_sat, psi_s(lb), psi_s(i_end), qlc, &
+ flux_top = ubc_val)
+
+ CASE (BC_RAINFALL)
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, dz_sat, psi_sat, &
+ hk_sat, wdsrf, psi_s(i_end), qlc)
+
+ ENDSELECT
+
+ ENDIF
+
+ ! Case 4
+ IF (top_at_interface .and. btm_at_bottom) THEN
+
+ SELECTCASE (lbc_typ)
+ CASE (BC_FIX_HEAD)
+
+ CALL flux_top_transitive_interface ( &
+ psi_s(i_stt), hksat(i_stt), nprm, prms(:,i_stt), &
+ dz_us_top, psi_us(i_stt), hk_us(i_stt), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, lbc_val, &
+ qq_wt(i_stt), qlc, tol_q, tol_z, tol_p)
+
+ CASE (BC_FIX_FLUX)
+
+ CALL flux_top_transitive_interface ( &
+ psi_s(i_stt), hksat(i_stt), nprm, prms(:,i_stt), &
+ dz_us_top, psi_us(i_stt), hk_us(i_stt), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_s(ub), &
+ qq_wt(i_stt), qlc, tol_q, tol_z, tol_p, &
+ flux_btm = lbc_val)
+
+ CASE (BC_DRAINAGE)
+
+ IF (zwt > sp_zi(ub)) THEN
+ CALL flux_top_transitive_interface ( &
+ psi_s(i_stt), hksat(i_stt), nprm, prms(:,i_stt), &
+ dz_us_top, psi_us(i_stt), hk_us(i_stt), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_s(ub), &
+ qq_wt(i_stt), qlc, tol_q, tol_z, tol_p)
+ ELSE
+ CALL flux_top_transitive_interface ( &
+ psi_s(i_stt), hksat(i_stt), nprm, prms(:,i_stt), &
+ dz_us_top, psi_us(i_stt), hk_us(i_stt), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_s(ub), &
+ qq_wt(i_stt), qlc, tol_q, tol_z, tol_p, &
+ flux_btm = 0.0)
+ ENDIF
+
+ ENDSELECT
+
+ ENDIF
+
+ ! Case 5
+ IF (top_at_interface .and. btm_at_interface) THEN
+
+ CALL flux_both_transitive_interface ( &
+ i_stt, i_end, dz(i_stt:i_end), &
+ psi_s(i_stt:i_end), hksat(i_stt:i_end), nprm, prms(:,i_stt:i_end), &
+ dz_us_top, psi_us(i_stt), hk_us(i_stt), &
+ dz_us_btm, psi_us(i_end), hk_us(i_end), &
+ qq_wt(i_stt), qq_wf(i_end), qlc, &
+ tol_q, tol_z, tol_p)
+
+ ENDIF
+
+ ! Case 6
+ IF (top_at_interface .and. btm_inside_level) THEN
+
+ CALL flux_top_transitive_interface ( &
+ psi_s(i_stt), hksat(i_stt), nprm, prms(:,i_stt), &
+ dz_us_top, psi_us(i_stt), hk_us(i_stt), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_s(i_end), &
+ qq_wt(i_stt), qlc, tol_q, tol_z, tol_p)
+
+ ENDIF
+
+ ! Case 7
+ IF (top_inside_level .and. btm_at_bottom) THEN
+
+ SELECTCASE (lbc_typ)
+ CASE (BC_FIX_HEAD)
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, dz_sat, psi_sat, &
+ hk_sat, psi_s(i_stt), lbc_val, qlc)
+
+ CASE (BC_FIX_FLUX)
+
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, psi_s(i_stt), psi_s(ub), &
+ qlc, flux_btm = lbc_val)
+
+ CASE (BC_DRAINAGE)
+
+ IF (zwt > sp_zi(ub)) THEN
+ CALL flux_sat_zone_fixed_bc (nlev_sat, dz_sat, psi_sat, &
+ hk_sat, psi_s(i_stt), psi_s(ub), qlc)
+ ELSE
+ CALL flux_sat_zone_fixed_bc (nlev_sat, &
+ dz_sat, psi_sat, hk_sat, psi_s(i_stt), psi_s(ub), &
+ qlc, flux_btm = 0.0)
+ ENDIF
+
+ ENDSELECT
+
+ ENDIF
+
+ ! Case 8
+ IF (top_inside_level .and. btm_at_interface) THEN
+
+ CALL flux_btm_transitive_interface ( &
+ psi_s(i_end), hksat(i_end), nprm, prms(:,i_end), &
+ dz_us_btm, psi_us(i_end), hk_us(i_end), &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_s(i_stt), &
+ qq_wf(i_end), qlc, tol_q, tol_z, tol_p)
+
+ ENDIF
+
+ ! Case 9
+ IF (top_inside_level .and. btm_inside_level) THEN
+
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_s(i_stt), psi_s(i_end), qlc)
+
+ ENDIF
+
+ IF (top_inside_level) THEN
+ IF (dz_us_top < tol_z) THEN
+ qq_wt(i_stt) = qq(i_stt-1)
+ ELSE
+ qq_wt(i_stt) = flux_inside_hm_soil ( &
+ psi_s(i_stt), hksat(i_stt), nprm, prms(:,i_stt), &
+ dz_us_top, psi_us(i_stt), psi_s(i_stt), hk_us(i_stt), hksat(i_stt))
+ ENDIF
+ ENDIF
+
+ IF (top_at_interface) THEN
+ IF (dz_us_top < tol_z) THEN
+ qq_wf(i_stt) = qq_wt(i_stt)
+ ENDIF
+ ENDIF
+
+ IF (top_at_ground) THEN
+
+ SELECTCASE (ubc_typ)
+ CASE (BC_FIX_HEAD)
+ qq(lb-1) = qlc(lb)
+ is_trans = .false.
+ CASE (BC_FIX_FLUX)
+ qq(lb-1) = ubc_val ! min(qlc(lb), ubc_val)
+ is_trans = (qlc(lb) > ubc_val)
+ CASE (BC_RAINFALL)
+ IF (wdsrf < tol_z) THEN
+ qq(lb-1) = min(ubc_val, qlc(lb))
+ is_trans = (qlc(lb) > ubc_val)
+ ELSE
+ qq(lb-1) = qlc(lb)
+ is_trans = .false.
+ ENDIF
+ ENDSELECT
+
+ IF (is_update_sublevel) THEN
+ IF (is_trans .and. is_sat(lb)) THEN
+ is_sat(lb) = .false.
+ has_wf(lb) = .false.
+ has_wt(lb) = .true.
+
+ wt(lb) = 0.9*dz(lb)
+ vl(lb) = vl_s(lb)
+ wf(lb) = 0
+
+ qq_wt(lb) = qq(lb-1)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ DO iface = i_stt, i_end-1
+ IF (top_at_interface .and. (iface == i_stt)) THEN
+ qupper = qq_wt(i_stt)
+ ELSE
+ qupper = qlc(iface)
+ ENDIF
+
+ IF (btm_at_interface .and. (iface == i_end-1)) THEN
+ qlower = qq_wf(i_end)
+ ELSE
+ qlower = qlc(iface+1)
+ ENDIF
+
+ IF (qlower - qupper >= tol_q) THEN
+ IF ((psi_s(iface) < psi_s(iface+1)) &
+ .or. &
+ ((psi_s(iface) == psi_s(iface+1)) .and. (is_sat(iface+1))) &
+ .or. &
+ (top_at_interface .and. (iface == i_stt))) THEN
+
+ qq(iface) = qupper
+
+ IF (is_update_sublevel .and. is_sat(iface+1)) THEN
+ is_sat(iface+1) = .false.
+ has_wf(iface+1) = .false.
+ has_wt(iface+1) = .true.
+
+ wt(iface+1) = dz(iface+1)
+ vl(iface+1) = vl_s(iface+1)
+ wf(iface+1) = 0
+
+ qq_wf(iface+1) = qq(iface)
+ qq_wt(iface+1) = qq(iface)
+
+ IF (top_at_interface .and. (iface == i_stt)) THEN
+ has_wt(iface) = .false.
+ ENDIF
+ ENDIF
+
+ ELSEIF ((psi_s(iface) > psi_s(iface+1)) &
+ .or. &
+ ((psi_s(iface) == psi_s(iface+1)) .and. (.not. is_sat(iface+1))) &
+ .or. &
+ (btm_at_interface .and. (iface == i_end-1))) THEN
+
+ qq(iface) = qlower
+
+ IF (is_update_sublevel .and. is_sat(iface)) THEN
+ is_sat(iface) = .false.
+ has_wt(iface) = .false.
+ has_wf(iface) = .true.
+
+ wf(iface) = dz(iface)
+ vl(iface) = vl_s(iface)
+ wt(iface) = 0
+
+ qq_wf(iface) = qq(iface)
+ qq_wt(iface) = qq(iface)
+
+ IF (btm_at_interface .and. (iface == i_end-1)) THEN
+ has_wf(iface+1) = .false.
+ ENDIF
+ ENDIF
+ ENDIF
+ ELSEIF (qupper - qlower >= tol_q) THEN
+ IF (top_at_interface .and. (iface == i_stt)) THEN
+ qq(iface) = qlower
+ ENDIF
+
+ IF (btm_at_interface .and. (iface == i_end-1)) THEN
+ qq(iface) = qupper
+ ENDIF
+ ELSE
+ qq(iface) = (qupper + qlower) * 0.5_r8
+ ENDIF
+ ENDDO
+
+ IF (btm_at_bottom) THEN
+ qq(ub) = qlc(ub)
+ ENDIF
+
+ IF (btm_at_interface) THEN
+ IF (dz_us_btm < tol_z) THEN
+ qq_wt(i_end) = qq_wf(i_end)
+ ENDIF
+ ENDIF
+
+ IF (btm_inside_level) THEN
+ IF (dz_us_btm < tol_z) THEN
+ qq_wf(i_end) = qq(i_end)
+ ELSE
+ qq_wf(i_end) = flux_inside_hm_soil ( &
+ psi_s(i_end), hksat(i_end), nprm, prms(:,i_end), &
+ dz_us_btm, psi_s(i_end), psi_us(i_end), hksat(i_end), hk_us(i_end))
+ ENDIF
+ ENDIF
+
+ deallocate (qlc )
+ deallocate (dz_sat )
+ deallocate (psi_sat)
+ deallocate (hk_sat )
+
+ END SUBROUTINE flux_sat_zone_all
+
+ !--------------------------------------------------------------------------
+ SUBROUTINE flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_btm, qlc, flux_top, flux_btm)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: nlev_sat
+
+ real(r8), intent(in) :: dz_sat (nlev_sat)
+ real(r8), intent(in) :: psi_sat (nlev_sat)
+ real(r8), intent(in) :: hk_sat (nlev_sat)
+
+ real(r8), intent(in) :: psi_top
+ real(r8), intent(in) :: psi_btm
+
+ real(r8), intent(inout) :: qlc (nlev_sat)
+
+ real(r8), intent(in), optional :: flux_top
+ real(r8), intent(in), optional :: flux_btm
+
+ ! Local variables
+ real(r8) :: psi (0:nlev_sat)
+ integer :: ilev, ilev_u, ilev_l
+ integer :: spr(1:nlev_sat)
+
+ IF (present(flux_top) .and. present(flux_btm)) THEN
+ IF (flux_top >= flux_btm) THEN
+ qlc(:) = flux_btm
+ RETURN
+ ENDIF
+ ENDIF
+
+ psi(0) = psi_top
+ psi(nlev_sat) = psi_btm
+
+ DO ilev = 1, nlev_sat
+ IF (ilev < nlev_sat) THEN
+ psi(ilev) = max(psi_sat(ilev),psi_sat(ilev+1))
+ ENDIF
+
+ qlc(ilev) = - hk_sat(ilev) &
+ * ((psi(ilev) - psi(ilev-1)) / dz_sat(ilev) - 1)
+
+ spr(ilev) = ilev
+ ENDDO
+
+ ilev_u = nlev_sat
+ ilev_l = ilev_u
+ DO WHILE (.true.)
+
+ IF (ilev_l < nlev_sat) THEN
+ ilev = findloc_ud(spr == spr(ilev_l+1), BACK=.true.)
+ DO WHILE (qlc(ilev_u) >= qlc(ilev))
+
+ ilev_l = ilev
+ qlc(ilev_u:ilev_l) = - (psi(ilev_l) - psi(ilev_u-1) &
+ - sum(dz_sat(ilev_u:ilev_l))) &
+ / sum(dz_sat(ilev_u:ilev_l) / hk_sat(ilev_u:ilev_l))
+
+ spr(ilev_u:ilev_l) = ilev_u
+
+ IF (ilev_l < nlev_sat) THEN
+ spr(ilev_l+1:nlev_sat) = spr(ilev_l+1:nlev_sat) - 1
+ ilev = findloc_ud(spr == spr(ilev_l+1), BACK=.true.)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF ((ilev_l == nlev_sat) .and. (present(flux_btm))) THEN
+ IF (qlc(ilev_l) > flux_btm) THEN
+ qlc(ilev_u:ilev_l) = flux_btm
+ ENDIF
+ ENDIF
+
+ IF (ilev_u > 1) THEN
+ ilev_u = ilev_u - 1
+ ilev_l = ilev_u
+ ELSE
+ IF (present(flux_top)) THEN
+ DO ilev = 1, nlev_sat
+ IF (flux_top > qlc(ilev)) THEN
+ qlc(ilev) = flux_top
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ EXIT
+ ENDIF
+
+ ENDDO
+
+ END SUBROUTINE flux_sat_zone_fixed_bc
+
+
+ !-------------------------------------------------------------------------
+ real(r8) FUNCTION flux_inside_hm_soil ( &
+ psi_s, hksat, nprm, prms, &
+ dz, psi_u, psi_l, hk_u, hk_l)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: psi_s, hksat
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+
+ real(r8), intent(in) :: dz
+ real(r8), intent(in) :: psi_u, psi_l
+ real(r8), intent(in) :: hk_u, hk_l
+
+ ! Local variables
+ real(r8) :: grad_psi
+ real(r8) :: hk_m
+ real(r8) :: r0, rr
+
+ grad_psi = (1.0_r8 - (psi_l - psi_u)/dz)
+
+ SELECTCASE (effective_hk_type)
+
+ CASE (type_upstream_mean)
+
+ IF (grad_psi < 0) THEN
+ flux_inside_hm_soil = hk_l * grad_psi
+ ELSE
+ flux_inside_hm_soil = hk_u * grad_psi
+ ENDIF
+
+ CASE (type_weighted_geometric_mean)
+
+#ifdef Campbell_SOIL_MODEL
+ ! bsw => prms(1)
+ r0 = 1.0_r8 / (3.0_r8 / prms(1) + 2.0_r8)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ ! n_gm => prms(2), L_gm => prms(3)
+ r0 = 1.0_r8 / (prms(3) * (prms(2) - 1.0_r8) + prms(2) * 2.0_r8)
+#endif
+
+ IF (grad_psi < 0) THEN
+ rr = r0
+ hk_m = soil_hk_from_psi (psi_l-dz, psi_s, hksat, nprm, prms)
+ flux_inside_hm_soil = hk_u**rr * hk_m**(1.0_r8 - rr) * grad_psi
+ ELSEIF (grad_psi == 0) THEN
+ flux_inside_hm_soil = 0
+ ELSEIF ((grad_psi > 0) .and. (grad_psi < 1)) THEN
+ rr = max(1.0_r8+r0*psi_l/dz, 1.0_r8-r0)
+ flux_inside_hm_soil = hk_u**rr * hk_l**(1.0_r8-rr) * grad_psi
+ ELSEIF (grad_psi == 1) THEN
+ flux_inside_hm_soil = hk_u
+ ELSEIF (grad_psi > 1) THEN
+ rr = r0
+ flux_inside_hm_soil = hk_u + (psi_u - psi_l)/dz * hk_u**(1.0_r8-rr) * hk_l**rr
+ ENDIF
+
+ ENDSELECT
+
+ END FUNCTION flux_inside_hm_soil
+
+
+ !--------------------------------------------------------
+ SUBROUTINE flux_at_unsaturated_interface (&
+ nprm, &
+ psi_s_u, hksat_u, prms_u, dz_u, psi_u, hk_u, &
+ psi_s_l, hksat_l, prms_l, dz_l, psi_l, hk_l, &
+ flux_u, flux_l, tol_q, tol_p)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: psi_s_u, hksat_u, prms_u(nprm)
+ real(r8), intent(in) :: psi_s_l, hksat_l, prms_l(nprm)
+
+ real(r8), intent(in) :: dz_u, psi_u, hk_u
+ real(r8), intent(in) :: dz_l, psi_l, hk_l
+
+ real(r8), intent(out) :: flux_u
+ real(r8), intent(out) :: flux_l
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_p
+
+ ! Local variables
+ real(r8) :: psi_s_min
+ real(r8) :: psi_i
+ real(r8) :: psi_i_r, psi_i_l
+ real(r8) :: psi_i_k1
+ real(r8) :: hk_i_u, hk_i_l
+ real(r8) :: fval, fval_k1
+ integer :: iter
+
+
+ psi_i_r = max(psi_u + dz_u, psi_l - dz_l)
+ psi_i_l = min(psi_u + dz_u, psi_l - dz_l)
+
+ psi_s_min = min(psi_s_u, psi_s_l)
+
+ IF (psi_i_r > psi_s_min) THEN
+ hk_i_u = soil_hk_from_psi (psi_s_min, psi_s_u, hksat_u, nprm, prms_u)
+ hk_i_l = soil_hk_from_psi (psi_s_min, psi_s_l, hksat_l, nprm, prms_l)
+
+ flux_u = flux_inside_hm_soil ( &
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_u, psi_u, psi_s_min, hk_u, hk_i_u)
+
+ flux_l = flux_inside_hm_soil (&
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_l, psi_s_min, psi_l, hk_i_l, hk_l)
+
+ IF (flux_u >= flux_l) THEN
+ RETURN
+ ELSE
+ psi_i_r = psi_s_min
+ ENDIF
+ ENDIF
+
+ psi_i = (dz_l * psi_u + dz_u * psi_l) / (dz_u + dz_l)
+ IF ((psi_i < psi_i_l) .or. (psi_i > psi_i_r)) THEN
+ psi_i = (psi_i_r + psi_i_l)/2.0_r8
+ ENDIF
+
+ iter = 0
+ DO WHILE (iter < 50)
+ hk_i_u = soil_hk_from_psi (psi_i, psi_s_u, hksat_u, nprm, prms_u)
+ hk_i_l = soil_hk_from_psi (psi_i, psi_s_l, hksat_l, nprm, prms_l)
+
+ flux_u = flux_inside_hm_soil ( &
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_u, psi_u, psi_i, hk_u, hk_i_u)
+
+ flux_l = flux_inside_hm_soil ( &
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_l, psi_i, psi_l, hk_i_l, hk_l)
+
+ fval = flux_l - flux_u
+
+ IF ((abs(fval) < tol_q) .or. (psi_i_r - psi_i_l < tol_p)) THEN
+ EXIT
+ ELSE
+ IF (iter == 0) THEN
+ IF (fval < 0) THEN
+ psi_i_l = psi_i
+ ELSE
+ psi_i_r = psi_i
+ ENDIF
+
+ psi_i_k1 = psi_i
+ fval_k1 = fval
+
+ psi_i = (psi_i_r + psi_i_l)/2.0_r8
+ ELSE
+ CALL secant_method_iteration ( &
+ fval, fval_k1, psi_i, psi_i_k1, psi_i_l, psi_i_r)
+ ENDIF
+ ENDIF
+
+ iter = iter + 1
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF (iter == 50) THEN
+ write(*,*) 'Warning : flux_at_unsaturated_interface: not converged.'
+ ENDIF
+#endif
+
+ END SUBROUTINE flux_at_unsaturated_interface
+
+ !-------------------------------------------------------------------
+ SUBROUTINE flux_top_transitive_interface ( &
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_us, psi_us, hk_us, &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_btm, &
+ q_us_up, qlc, tol_q, tol_z, tol_p, flux_btm)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: psi_s_u, hksat_u
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms_u(nprm)
+
+ real(r8), intent(in) :: dz_us
+ real(r8), intent(in) :: psi_us
+ real(r8), intent(in) :: hk_us
+
+ integer, intent(in) :: nlev_sat
+ real(r8), intent(in) :: dz_sat (nlev_sat)
+ real(r8), intent(in) :: psi_sat (nlev_sat)
+ real(r8), intent(in) :: hk_sat (nlev_sat)
+
+ real(r8), intent(in) :: psi_btm
+
+ real(r8), intent(out) :: q_us_up
+ real(r8), intent(inout) :: qlc (nlev_sat)
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_z
+ real(r8), intent(in) :: tol_p
+
+ real(r8), intent(in), optional :: flux_btm
+
+ ! Local variables
+ real(r8) :: psi_i
+ real(r8) :: psi_i_r, psi_i_l
+ real(r8) :: psi_i_k1
+ real(r8) :: hk_i
+ real(r8) :: fval, fval_k1
+ integer :: iter
+
+
+ IF (dz_us < tol_z) THEN
+
+ psi_i = max(psi_s_u, psi_sat(1))
+ IF (present(flux_btm)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc, flux_btm = flux_btm)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc)
+ ENDIF
+
+ q_us_up = qlc(1)
+
+ RETURN
+
+ ENDIF
+
+ IF (psi_s_u <= psi_sat(1)) THEN
+ ! The case psi_s_u < psi_sat(1) does not exist in principle.
+
+ psi_i = psi_s_u
+ hk_i = hksat_u
+ q_us_up = flux_inside_hm_soil ( &
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_us, psi_us, psi_i, hk_us, hk_i)
+
+ psi_i = psi_sat(1)
+ IF (present(flux_btm)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc, flux_btm = flux_btm)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc)
+ ENDIF
+
+ RETURN
+
+ ENDIF
+
+ psi_i = psi_sat(1)
+ hk_i = soil_hk_from_psi (psi_i, psi_s_u, hksat_u, nprm, prms_u)
+ q_us_up = flux_inside_hm_soil ( &
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_us, psi_us, psi_i, hk_us, hk_i)
+
+ IF (present(flux_btm)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc, flux_btm = flux_btm)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc)
+ ENDIF
+
+ IF (q_us_up <= qlc(1)) THEN
+ RETURN
+ ELSE
+ psi_i_l = psi_sat(1)
+ ENDIF
+
+ psi_i = psi_s_u
+ hk_i = hksat_u
+ q_us_up = flux_inside_hm_soil (&
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_us, psi_us, psi_i, hk_us, hk_i)
+
+ IF (present(flux_btm)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc, flux_btm = flux_btm)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc)
+ ENDIF
+
+ IF (q_us_up >= qlc(1)) THEN
+ RETURN
+ ELSE
+ psi_i_r = psi_s_u
+ ENDIF
+
+ psi_i_k1 = psi_i_r
+ fval_k1 = qlc(1) - q_us_up
+
+ psi_i = (psi_i_r + psi_i_l)/2.0_r8
+ iter = 0
+ DO WHILE (iter < 50)
+ hk_i = soil_hk_from_psi (psi_i, psi_s_u, hksat_u, nprm, prms_u)
+ q_us_up = flux_inside_hm_soil ( &
+ psi_s_u, hksat_u, nprm, prms_u, &
+ dz_us, psi_us, psi_i, hk_us, hk_i)
+
+ IF (present(flux_btm)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc, flux_btm = flux_btm)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_i, psi_btm, qlc)
+ ENDIF
+
+ fval = qlc(1) - q_us_up
+
+ IF ((abs(fval) < tol_q) .or. (psi_i_r - psi_i_l < tol_p)) THEN
+ EXIT
+ ELSE
+ CALL secant_method_iteration ( &
+ fval, fval_k1, psi_i, psi_i_k1, psi_i_l, psi_i_r)
+ ENDIF
+
+ iter = iter + 1
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF (iter == 50) THEN
+ write(*,*) 'Warning : flux_top_transitive_interface: not converged.'
+ ENDIF
+#endif
+
+ END SUBROUTINE flux_top_transitive_interface
+
+ !------------------------------------------------------------------------
+ SUBROUTINE flux_btm_transitive_interface ( &
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_us, psi_us, hk_us, &
+ nlev_sat, dz_sat, psi_sat, hk_sat, psi_top, &
+ q_us_l, qlc, tol_q, tol_z, tol_p, flux_top)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: psi_s_l, hksat_l
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms_l(nprm)
+
+ real(r8), intent(in) :: dz_us
+ real(r8), intent(in) :: psi_us
+ real(r8), intent(in) :: hk_us
+
+ integer, intent(in) :: nlev_sat
+ real(r8), intent(in) :: dz_sat (nlev_sat)
+ real(r8), intent(in) :: psi_sat (nlev_sat)
+ real(r8), intent(in) :: hk_sat (nlev_sat)
+
+ real(r8), intent(in) :: psi_top
+
+ real(r8), intent(out) :: q_us_l
+ real(r8), intent(inout) :: qlc (nlev_sat)
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_z
+ real(r8), intent(in) :: tol_p
+
+ real(r8), intent(in), optional :: flux_top
+
+ ! Local variables
+ real(r8) :: psi_i
+ real(r8) :: psi_i_r, psi_i_l
+ real(r8) :: psi_i_k1
+ real(r8) :: hk_i
+ real(r8) :: fval, fval_k1
+ integer :: iter
+
+
+ IF (dz_us < tol_z) THEN
+
+ psi_i = max(psi_sat(nlev_sat), psi_s_l)
+ IF (present(flux_top)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc, flux_top = flux_top)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc)
+ ENDIF
+
+ q_us_l = qlc(nlev_sat)
+
+ RETURN
+
+ ENDIF
+
+ IF (psi_sat(nlev_sat) >= psi_s_l) THEN
+ ! The case psi_sat(nlev_sat) > psi_s_l does not exist in principle.
+
+ psi_i = psi_s_l
+ hk_i = hksat_l
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_us, psi_i, psi_us, hk_i, hk_us)
+
+ psi_i = psi_sat(nlev_sat)
+ IF (present(flux_top)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc, flux_top = flux_top)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc)
+ ENDIF
+
+ RETURN
+
+ ENDIF
+
+ psi_i = psi_sat(nlev_sat)
+
+ IF (present(flux_top)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc, flux_top = flux_top)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc)
+ ENDIF
+
+ hk_i = soil_hk_from_psi (psi_i, psi_s_l, hksat_l, nprm, prms_l)
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_us, psi_i, psi_us, hk_i, hk_us)
+
+ IF (qlc(nlev_sat) <= q_us_l) THEN
+ RETURN
+ ELSE
+ psi_i_l = psi_sat(nlev_sat)
+ ENDIF
+
+ psi_i = psi_s_l
+
+ IF (present(flux_top)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc, flux_top = flux_top)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc)
+ ENDIF
+
+ hk_i = soil_hk_from_psi (psi_i, psi_s_l, hksat_l, nprm, prms_l)
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_us, psi_i, psi_us, hk_i, hk_us)
+
+ IF (qlc(nlev_sat) >= q_us_l) THEN
+ RETURN
+ ELSE
+ psi_i_r = psi_s_l
+ ENDIF
+
+ psi_i_k1 = psi_i_r
+ fval_k1 = q_us_l - qlc(nlev_sat)
+
+ psi_i = (psi_i_r + psi_i_l)/2.0_r8
+ iter = 0
+ DO WHILE (iter < 50)
+
+ IF (present(flux_top)) THEN
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc, flux_top = flux_top)
+ ELSE
+ CALL flux_sat_zone_fixed_bc ( &
+ nlev_sat, dz_sat, psi_sat, hk_sat, &
+ psi_top, psi_i, qlc)
+ ENDIF
+
+ hk_i = soil_hk_from_psi (psi_i, psi_s_l, hksat_l, nprm, prms_l)
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s_l, hksat_l, nprm, prms_l, &
+ dz_us, psi_i, psi_us, hk_i, hk_us)
+
+ fval = q_us_l - qlc(nlev_sat)
+
+ IF ((abs(fval) < tol_q) .or. (psi_i_r - psi_i_l < tol_p)) THEN
+ EXIT
+ ELSE
+ CALL secant_method_iteration ( &
+ fval, fval_k1, psi_i, psi_i_k1, psi_i_l, psi_i_r)
+ ENDIF
+
+ iter = iter + 1
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF (iter == 50) THEN
+ write(*,*) 'Warning : flux_btm_transitive_interface: not converged.'
+ ENDIF
+#endif
+
+ END SUBROUTINE flux_btm_transitive_interface
+
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE flux_both_transitive_interface ( &
+ ilev_us_u, ilev_us_l, &
+ dz, psi_s, hksat, nprm, prms, &
+ dz_us_u, psi_us_u, hk_us_u, &
+ dz_us_l, psi_us_l, hk_us_l, &
+ q_us_u, q_us_l, qlc, &
+ tol_q, tol_z, tol_p)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: ilev_us_u, ilev_us_l
+ real(r8), intent(in) :: dz (ilev_us_u:ilev_us_l)
+ real(r8), intent(in) :: psi_s (ilev_us_u:ilev_us_l)
+ real(r8), intent(in) :: hksat (ilev_us_u:ilev_us_l)
+
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms (nprm,ilev_us_u:ilev_us_l)
+
+ real(r8), intent(in) :: dz_us_u, psi_us_u, hk_us_u
+ real(r8), intent(in) :: dz_us_l, psi_us_l, hk_us_l
+
+ real(r8), intent(out) :: q_us_u, q_us_l
+ real(r8), intent(inout) :: qlc (ilev_us_u+1:ilev_us_l-1)
+
+ real(r8), intent(in) :: tol_q
+ real(r8), intent(in) :: tol_z
+ real(r8), intent(in) :: tol_p
+
+ ! Local variables
+ integer :: nlev_sat
+ real(r8) :: psi_i
+ real(r8) :: psi_i_r, psi_i_l
+ real(r8) :: psi_i_k1
+ real(r8) :: hk_i
+ real(r8) :: fval, fval_k1
+ integer :: iter
+
+ nlev_sat = ilev_us_l - ilev_us_u - 1
+
+ IF ((psi_s(ilev_us_u) <= psi_s(ilev_us_u+1)) &
+ .or. (dz_us_u < tol_z)) THEN
+
+ psi_i = max(psi_s(ilev_us_u), psi_s(ilev_us_u+1))
+ CALL flux_btm_transitive_interface ( &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l), &
+ dz_us_l, psi_us_l, hk_us_l, &
+ nlev_sat, dz(ilev_us_u+1:ilev_us_l-1), psi_s(ilev_us_u+1:ilev_us_l-1), &
+ hksat(ilev_us_u+1:ilev_us_l-1), psi_i, &
+ q_us_l, qlc, tol_q, tol_z, tol_p)
+
+ IF (dz_us_u < tol_z) THEN
+ q_us_u = qlc(ilev_us_u+1)
+ ELSE
+ q_us_u = flux_inside_hm_soil ( &
+ psi_s(ilev_us_u), hksat(ilev_us_u), nprm, prms(:,ilev_us_u), &
+ dz_us_u, psi_us_u, psi_s(ilev_us_u), hk_us_u, hksat(ilev_us_u))
+ ENDIF
+
+ RETURN
+ ENDIF
+
+ IF ((psi_s(ilev_us_l) <= psi_s(ilev_us_l-1)) &
+ .or. (dz_us_l < tol_z)) THEN
+
+ psi_i = max(psi_s(ilev_us_l-1), psi_s(ilev_us_l))
+ CALL flux_top_transitive_interface ( &
+ psi_s(ilev_us_u), hksat(ilev_us_u), nprm, prms(:,ilev_us_u), &
+ dz_us_u, psi_us_u, hk_us_u, &
+ nlev_sat, dz(ilev_us_u+1:ilev_us_l-1), &
+ psi_s(ilev_us_u+1:ilev_us_l-1), hksat(ilev_us_u+1:ilev_us_l-1), psi_i, &
+ q_us_u, qlc, tol_q, tol_z, tol_p)
+
+ IF (dz_us_l < tol_z) THEN
+ q_us_l = qlc(ilev_us_l-1)
+ ELSE
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l), &
+ dz_us_l, psi_s(ilev_us_l), psi_us_l, hksat(ilev_us_l), hk_us_l)
+ ENDIF
+
+ RETURN
+ ENDIF
+
+ psi_i_l = psi_s(ilev_us_l-1)
+
+ CALL flux_top_transitive_interface ( &
+ psi_s(ilev_us_u), hksat(ilev_us_u), nprm, prms(:,ilev_us_u), &
+ dz_us_u, psi_us_u, hk_us_u, &
+ nlev_sat, dz(ilev_us_u+1:ilev_us_l-1), &
+ psi_s(ilev_us_u+1:ilev_us_l-1), hksat(ilev_us_u+1:ilev_us_l-1), psi_i_l, &
+ q_us_u, qlc, tol_q/2.0_r8, tol_z, tol_p)
+
+ hk_i = soil_hk_from_psi (psi_i_l, &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l))
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l), &
+ dz_us_l, psi_i_l, psi_us_l, hk_i, hk_us_l)
+
+ IF (qlc(ilev_us_l-1) <= q_us_l) THEN
+ RETURN
+ ENDIF
+
+ psi_i_r = psi_s(ilev_us_l)
+
+ CALL flux_top_transitive_interface ( &
+ psi_s(ilev_us_u), hksat(ilev_us_u), nprm, prms(:,ilev_us_u), &
+ dz_us_u, psi_us_u, hk_us_u, &
+ nlev_sat, dz(ilev_us_u+1:ilev_us_l-1), &
+ psi_s(ilev_us_u+1:ilev_us_l-1), hksat(ilev_us_u+1:ilev_us_l-1), psi_i_r, &
+ q_us_u, qlc, tol_q/2.0_r8, tol_z, tol_p)
+
+ hk_i = soil_hk_from_psi (psi_i_r, &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l))
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l), &
+ dz_us_l, psi_i_r, psi_us_l, hk_i, hk_us_l)
+
+ IF (qlc(ilev_us_l-1) >= q_us_l ) THEN
+ RETURN
+ ENDIF
+
+ psi_i_k1 = psi_i_r
+ fval_k1 = q_us_l - qlc(ilev_us_l-1)
+
+ psi_i = (psi_i_r + psi_i_l)/2.0_r8
+ iter = 0
+ DO WHILE (iter < 50)
+
+ CALL flux_top_transitive_interface ( &
+ psi_s(ilev_us_u), hksat(ilev_us_u), nprm, prms(:,ilev_us_u), &
+ dz_us_u, psi_us_u, hk_us_u, &
+ nlev_sat, dz(ilev_us_u+1:ilev_us_l-1), &
+ psi_s(ilev_us_u+1:ilev_us_l-1), hksat(ilev_us_u+1:ilev_us_l-1), psi_i, &
+ q_us_u, qlc, tol_q/2.0_r8, tol_z, tol_p)
+
+ hk_i = soil_hk_from_psi (psi_i, &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l))
+ q_us_l = flux_inside_hm_soil ( &
+ psi_s(ilev_us_l), hksat(ilev_us_l), nprm, prms(:,ilev_us_l), &
+ dz_us_l, psi_i, psi_us_l, hk_i, hk_us_l)
+
+ fval = q_us_l - qlc(ilev_us_l-1)
+
+ IF ((abs(fval) < tol_q) .or. (psi_i_r - psi_i_l < tol_p)) THEN
+ EXIT
+ ELSE
+ CALL secant_method_iteration ( &
+ fval, fval_k1, psi_i, psi_i_k1, psi_i_l, psi_i_r)
+ ENDIF
+
+ iter = iter + 1
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF (iter == 50) THEN
+ write(*,*) 'Warning : flux_both_transitive_interface: not converged.'
+ ENDIF
+#endif
+
+ END SUBROUTINE flux_both_transitive_interface
+
+ !-----------------------------------------------------------------
+ SUBROUTINE get_zwt_from_wa ( &
+ vl_s, vl_r, psi_s, hksat, nprm, prms, tol_v, tol_z, &
+ wa, zmin, zwt)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: vl_s, vl_r, psi_s, hksat
+ integer, intent(in) :: nprm
+ real(r8), intent(in) :: prms(nprm)
+ real(r8), intent(in) :: tol_v, tol_z
+ real(r8), intent(in) :: wa, zmin
+ real(r8), intent(out) :: zwt
+
+ real(r8) :: vl
+ real(r8) :: zwt_l, zwt_r, zwt_k1
+ real(r8) :: fval, fval_k1
+ real(r8) :: psi
+ integer :: iter
+
+ IF (wa >= 0) THEN
+ zwt = zmin
+ vl = vl_s
+ RETURN
+ ENDIF
+
+ zwt = zmin + (-wa)/vl_s * 2.0
+ psi = psi_s - (zwt - zmin) * 0.5
+ vl = soil_vliq_from_psi (psi, &
+ vl_s, vl_r, psi_s, nprm, prms)
+ DO WHILE (wa <= -(zwt-zmin)*(vl_s-vl))
+ zwt = zmin + (zwt-zmin)*2 + 0.1
+ psi = psi_s - (zwt - zmin) * 0.5
+ vl = soil_vliq_from_psi (psi, &
+ vl_s, vl_r, psi_s, nprm, prms)
+ ENDDO
+
+ zwt_r = zwt
+ zwt_l = zmin
+
+ zwt_k1 = zwt_l
+ fval_k1 = wa
+
+ zwt = (zwt_l + zwt_r) / 2.0
+ iter = 0
+ DO WHILE (iter < 50)
+
+ psi = psi_s - (zwt - zmin) * 0.5
+ vl = soil_vliq_from_psi (psi, &
+ vl_s, vl_r, psi_s, nprm, prms)
+ fval = wa + (zwt-zmin)* (vl_s-vl)
+
+ IF ((abs(fval) < tol_v) .or. (zwt_r - zwt_l < tol_z)) THEN
+ EXIT
+ ELSE
+ CALL secant_method_iteration ( &
+ fval, fval_k1, zwt, zwt_k1, zwt_l, zwt_r)
+ ENDIF
+
+ iter = iter + 1
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF (iter == 50) THEN
+ write(*,*) 'Warning : get_zwt_from_wa: not converged.'
+ ENDIF
+#endif
+
+ END SUBROUTINE get_zwt_from_wa
+
+
+ !---------------------------------------------------------------------
+ SUBROUTINE solve_least_squares_problem (ndim, dr_dv, lact, rhs, dv)
+ ! By using Givens rotation.
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: ndim
+ real(r8), intent(in) :: dr_dv (ndim,ndim)
+ logical, intent(in) :: lact (ndim)
+ real(r8), intent(in) :: rhs (ndim)
+
+ real(r8), intent(out) :: dv (ndim)
+
+ ! Local variables
+ real(r8) :: Amatrix (ndim,ndim)
+ real(r8) :: res (ndim)
+ integer :: i, j, k
+ real(r8) :: tau, c, s
+ real(r8) :: tmp
+
+ Amatrix = dr_dv
+ res = rhs
+ dv = 0
+
+ DO i = 1, ndim
+ IF (lact(i)) THEN
+
+ DO j = i+1, ndim
+ IF (Amatrix(j,i) /= 0) THEN
+ IF (abs(Amatrix(j,i)) > abs(Amatrix(i,i))) THEN
+ tau = Amatrix(i,i) / Amatrix(j,i)
+ s = 1 / sqrt(1 + tau**2)
+ c = s * tau
+ ELSE
+ tau = Amatrix(j,i) / Amatrix(i,i)
+ c = 1 / sqrt(1 + tau**2)
+ s = c * tau
+ ENDIF
+
+ Amatrix(i,i) = c * Amatrix(i,i) + s * Amatrix(j,i)
+ Amatrix(j,i) = 0
+
+ DO k = i+1, ndim
+ IF (lact(k)) THEN
+ tmp = c * Amatrix(i,k) + s * Amatrix(j,k)
+ Amatrix(j,k) = - s * Amatrix(i,k) + c * Amatrix(j,k)
+ Amatrix(i,k) = tmp
+ ENDIF
+ ENDDO
+
+ tmp = c * res(i) + s * res(j)
+ res(j) = - s * res(i) + c * res(j)
+ res(i) = tmp
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDDO
+
+ dv = 0
+
+ DO i = ndim, 1, -1
+ IF (lact(i)) THEN
+
+ dv(i) = res(i)
+
+ DO k = i+1, ndim
+ IF (lact(k)) THEN
+ dv(i) = dv(i) - Amatrix(i,k) * dv(k)
+ ENDIF
+ ENDDO
+
+ dv(i) = dv(i) / Amatrix(i,i)
+
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE solve_least_squares_problem
+
+
+ !---------------------------------------------------------------------------------
+ SUBROUTINE secant_method_iteration ( &
+ fval, fval_k1, x_i, x_k1, x_l, x_r)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: fval
+ real(r8), intent(inout) :: fval_k1
+
+ real(r8), intent(inout) :: x_i, x_k1
+ real(r8), intent(inout) :: x_l, x_r
+
+ real(r8), parameter :: alp = 0.9_r8
+
+ ! Local variables
+ real(r8) :: x_k2, fval_k2
+
+ IF (fval > 0.0_r8) THEN
+ x_r = x_i
+ ELSE
+ x_l = x_i
+ ENDIF
+
+ fval_k2 = fval_k1
+ fval_k1 = fval
+
+ x_k2 = x_k1
+ x_k1 = x_i
+
+ IF (fval_k1 == fval_k2) THEN
+ x_i = (x_l + x_r) * 0.5_r8
+ ELSE
+ x_i = (fval_k1 * x_k2 - fval_k2 * x_k1) / (fval_k1 - fval_k2)
+ x_i = max(x_i, x_l * alp + x_r * (1.0_r8 - alp))
+ x_i = min(x_i, x_l * (1.0_r8 - alp) + x_r * alp)
+ ENDIF
+
+ END SUBROUTINE secant_method_iteration
+
+
+ !-------------------------------------------------------------------------------
+ integer FUNCTION find_unsat_lev_lower (is_sat, lb, ub, ilev)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lb, ub
+ logical, intent(in) :: is_sat (lb:ub)
+ integer, intent(in) :: ilev
+
+ find_unsat_lev_lower = ilev
+ DO WHILE (find_unsat_lev_lower <= ub)
+ IF (is_sat(find_unsat_lev_lower)) THEN
+ find_unsat_lev_lower = find_unsat_lev_lower + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ END FUNCTION find_unsat_lev_lower
+
+ ! -----
+ SUBROUTINE print_VSF_iteration_stat_info ()
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ integer(8), SAVE :: count_implicit_accum = 0
+ integer(8), SAVE :: count_explicit_accum = 0
+ integer(8), SAVE :: count_wet2dry_accum = 0
+ integer :: iwork
+
+#ifdef CoLMDEBUG
+ IF (p_is_compute) THEN
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, count_implicit, 1, MPI_INTEGER8, MPI_SUM, p_comm_compute, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, count_explicit, 1, MPI_INTEGER8, MPI_SUM, p_comm_compute, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, count_wet2dry , 1, MPI_INTEGER8, MPI_SUM, p_comm_compute, p_err)
+#endif
+ IF (p_iam_compute == p_root) THEN
+ count_implicit_accum = count_implicit_accum + count_implicit
+ count_explicit_accum = count_explicit_accum + count_explicit
+ count_wet2dry_accum = count_wet2dry_accum + count_wet2dry
+
+#ifdef USEMPI
+ CALL mpi_send (count_implicit, 1, MPI_INTEGER8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (count_explicit, 1, MPI_INTEGER8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (count_wet2dry, 1, MPI_INTEGER8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (count_implicit_accum, 1, MPI_INTEGER8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (count_explicit_accum, 1, MPI_INTEGER8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (count_wet2dry_accum, 1, MPI_INTEGER8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+
+#ifdef USEMPI
+ iwork = p_address_compute(p_root)
+ CALL mpi_recv (count_implicit, 1, MPI_INTEGER8, iwork, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (count_explicit, 1, MPI_INTEGER8, iwork, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (count_wet2dry , 1, MPI_INTEGER8, iwork, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (count_implicit_accum, 1, MPI_INTEGER8, iwork, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (count_explicit_accum, 1, MPI_INTEGER8, iwork, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (count_wet2dry_accum , 1, MPI_INTEGER8, iwork, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+
+ write(*,"(/,A,I13,A,I13,A,I13,A)") 'VSF scheme this step: ', &
+ count_implicit, ' (implicit)', count_explicit, ' (explicit)', count_wet2dry, ' (wet2dry)'
+ write(*,"(A,I13,A,I13,A,I13,A)") 'VSF scheme all steps: ', &
+ count_implicit_accum, ' (implicit)', count_explicit_accum, ' (explicit)', &
+ count_wet2dry_accum, ' (wet2dry)'
+ ENDIF
+
+ count_implicit = 0
+ count_explicit = 0
+ count_wet2dry = 0
+#endif
+ END SUBROUTINE print_VSF_iteration_stat_info
+
+END MODULE MOD_Hydro_SoilWater
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_VIC.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_VIC.F90
new file mode 100644
index 0000000000..cbc90062c7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_VIC.F90
@@ -0,0 +1,588 @@
+MODULE MOD_Hydro_VIC
+ USE MOD_Hydro_VIC_Variables
+ IMPLICIT NONE
+
+ PUBLIC :: compute_vic_runoff
+
+ PRIVATE :: compute_runoff_and_asat
+ PRIVATE :: calc_Q12
+ PRIVATE :: compute_zwt
+ PRIVATE :: wrap_compute_zwt
+
+ CONTAINS
+
+ ! ******************************************************************************
+ SUBROUTINE Runoff_VIC(deltim, porsl, theta_r, hksati, bsw, &
+ wice_soisno, wliq_soisno, fevpg, rootflux, ppt, &
+ b_infilt, Dsmax, Ds, Ws, c, &
+ rsur,rsubst,wliq_soisno_tmp)
+
+ USE MOD_Namelist
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ !-----------------------Arguments---------------------------------------
+ type(soil_con_struct) :: soil_con
+ type(cell_data_struct) :: cell
+
+ real(r8), intent(in) :: porsl(1:nl_soil), theta_r(1:nl_soil), hksati(1:nl_soil), bsw(1:nl_soil)
+ real(r8), intent(in) :: wice_soisno(1:nl_soil)
+ real(r8), intent(in) :: wliq_soisno(1:nl_soil)
+ real(r8), intent(in) :: fevpg
+ real(r8), intent(in) :: rootflux(1:nl_soil)
+ real(r8), intent(in) :: ppt ! /**< amount of liquid water coming to the surface */
+ real(r8), intent(in) :: deltim ! int(DEF_simulation_time%timestep)
+
+ real(r8), intent(in) :: b_infilt, Dsmax, Ds, Ws, c
+
+ real(r8), intent(inout) :: rsur, rsubst
+ real(r8), intent(out) :: wliq_soisno_tmp(1:nl_soil)
+
+ !-----------------------Local Variables---------------------------------
+ integer :: ilay
+ real(r8) :: vic_tmp(Nlayer), vic_tmp_(Nlayer)
+ !-----------------------Arguments---------------------------------------
+
+ CALL vic_para(porsl, theta_r, hksati, bsw, wice_soisno(1:nl_soil), wliq_soisno(1:nl_soil), fevpg, rootflux, &
+ b_infilt, Dsmax, Ds, Ws, c, &
+ soil_con, cell)
+
+ CALL compute_vic_runoff(soil_con, ppt*deltim, soil_con%frost_fract, cell)
+
+ DO ilay = 1, Nlayer
+ vic_tmp(ilay) = cell%layer(ilay)%moist
+ ENDDO
+ wliq_soisno_tmp = 0.
+ CALL VIC2CoLM(wliq_soisno_tmp, vic_tmp)
+
+ DO ilay = 1, Nlayer
+ vic_tmp_(ilay) = sum(cell%layer(ilay)%ice)
+ ENDDO
+ ! CALL VIC2CoLM(wice_soisno(1:nl_soil), vic_tmp_)
+
+ IF (ppt > 0.) rsur = cell%runoff/deltim
+ rsubst = cell%baseflow/deltim
+
+ END SUBROUTINE Runoff_VIC
+
+ ! /******************************************************************************
+ ! * @brief Calculate infiltration and runoff from the surface, gravity driven
+ ! * drainage between all soil layers, and generates baseflow from the
+ ! * bottom layer.
+ ! ******************************************************************************/
+ SUBROUTINE compute_vic_runoff(soil_con, ppt, frost_fract, cell)
+ USE MOD_Hydro_VIC_Variables
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ !-----------------------Arguments---------------------------------------
+ type(soil_con_struct), intent(in) :: soil_con
+ real(r8), intent(in) :: ppt ! /**< amount of liquid water coming to the surface */
+ real(r8), intent(in) :: frost_fract(:) ! /**< spatially distributed frost coverage fractions */
+ type(cell_data_struct),intent(inout) :: cell
+
+ !-----------------------Local Variables---------------------------------
+ integer :: lindex, time_step
+ integer :: last_index, tmplayer, fidx
+ real(r8) :: A
+ real(r8) :: frac
+ real(r8) :: tmp_runoff
+ real(r8) :: inflow
+ real(r8) :: resid_moist(MAX_LAYERS) ! residual moisture (mm)
+ real(r8) :: org_moist(MAX_LAYERS) ! total soil moisture (liquid and frozen) at beginning of this FUNCTION (mm)
+ real(r8) :: avail_liq(MAX_LAYERS, MAX_FROST_AREAS) ! liquid soil moisture available for evap/drainage (mm)
+ real(r8) :: liq(MAX_LAYERS)
+ real(r8) :: ice(MAX_LAYERS)
+ real(r8) :: moist(MAX_LAYERS)
+ real(r8) :: max_moist(MAX_LAYERS)
+ real(r8) :: Ksat(MAX_LAYERS)
+ real(r8) :: Q12(MAX_LAYERS - 1)
+ real(r8) :: Dsmax
+ real(r8) :: tmp_inflow
+ real(r8) :: tmp_moist
+ real(r8) :: tmp_moist_for_runoff(MAX_LAYERS)
+ real(r8) :: tmp_liq
+ real(r8) :: dt_inflow
+ real(r8) :: dt_runoff
+ real(r8) :: runoff(MAX_FROST_AREAS)
+ real(r8) :: tmp_dt_runoff(MAX_FROST_AREAS)
+ real(r8) :: baseflow(MAX_FROST_AREAS)
+ real(r8) :: dt_baseflow
+ real(r8) :: rel_moist
+ real(r8) :: evap(MAX_LAYERS, MAX_FROST_AREAS)
+ real(r8) :: sum_liq
+ real(r8) :: evap_fraction
+ real(r8) :: evap_sum
+ type(layer_data_struct), dimension(MAX_LAYERS) :: layer
+
+ real(r8) :: dltime !/**< timestep in seconds */
+ integer :: runoff_steps_per_day !/**< Number of runoff timesteps per day */
+ integer :: model_steps_per_day !/**< Number of model timesteps per day */
+ integer :: runoff_steps_per_dt
+
+ !-----------------------End Variable List-------------------------------
+
+ dltime = DEF_simulation_time%timestep
+ runoff_steps_per_day = 86400/dltime
+ model_steps_per_day = 86400/dltime
+
+ ! /** Set Temporary Variables **/
+ DO lindex = 1, Nlayer
+ resid_moist(lindex) = soil_con%resid_moist(lindex)
+ max_moist(lindex) = soil_con%max_moist(lindex)
+ Ksat(lindex) = soil_con%Ksat(lindex) / runoff_steps_per_day
+ ENDDO
+
+ ! /** Allocate and Set Values for Soil Sublayers **/
+ layer = cell%layer
+ cell%runoff = 0
+ cell%baseflow = 0
+ cell%asat = 0
+
+ runoff_steps_per_dt = runoff_steps_per_day / model_steps_per_day
+
+ ! initialize baseflow
+ DO fidx = 1, Nfrost
+ baseflow(fidx) = 0.0
+ ENDDO
+
+ DO lindex = 1, Nlayer
+ evap(lindex, 1) = layer(lindex)%evap / real(runoff_steps_per_dt)
+ org_moist(lindex) = layer(lindex)%moist
+ layer(lindex)%moist = 0.0
+
+ ! if there is positive evaporation
+ IF (evap(lindex, 1) > 0.0) THEN
+ sum_liq = 0.0
+ ! compute available soil moisture for each frost sub area
+ DO fidx = 1, Nfrost
+ avail_liq(lindex, fidx) = org_moist(lindex) - layer(lindex)%ice(fidx) - resid_moist(lindex)
+ !avail_liq(lindex, fidx) = org_moist(lindex) - resid_moist(lindex)
+ IF (avail_liq(lindex, fidx) < 0.0) THEN
+ avail_liq(lindex, fidx) = 0.0
+ ENDIF
+ sum_liq = sum_liq + avail_liq(lindex, fidx) * frost_fract(fidx)
+ ENDDO
+
+ ! compute fraction of available soil moisture that is evaporated
+ IF (sum_liq > 0.0) THEN
+ evap_fraction = evap(lindex, 1) / sum_liq
+ ELSE
+ evap_fraction = 1.0
+ ENDIF
+
+ ! distribute evaporation between frost sub areas by percentage
+ evap_sum = evap(lindex, 1)
+ DO fidx = Nfrost, 1, -1
+ evap(lindex, fidx) = avail_liq(lindex, fidx) * evap_fraction
+ avail_liq(lindex, fidx) = avail_liq(lindex, fidx) - evap(lindex, fidx)
+ evap_sum = evap_sum - evap(lindex, fidx) * frost_fract(fidx)
+ ENDDO
+ ELSE
+ ! if no evaporation
+ DO fidx = Nfrost, 2, -1
+ evap(lindex, fidx) = evap(lindex, 1)
+ ENDDO
+ ENDIF
+ ENDDO
+
+
+ DO fidx = 1, Nfrost
+ ! ppt = amount of liquid water coming to the surface
+ inflow = ppt
+
+ ! /**************************************************
+ ! Initialize Variables
+ ! **************************************************/
+ DO lindex = 1, Nlayer
+ ! Set Layer Liquid Moisture Content
+ liq(lindex) = org_moist(lindex) - layer(lindex)%ice(fidx)
+
+ ! Set Layer Frozen Moisture Content
+ ice(lindex) = layer(lindex)%ice(fidx)
+ ENDDO
+
+ ! /******************************************************
+ ! Runoff Based on Soil Moisture Level of Upper Layers
+ ! ******************************************************/
+ DO lindex = 1, Nlayer
+ tmp_moist_for_runoff(lindex) = liq(lindex) + ice(lindex)
+ ENDDO
+
+ CALL compute_runoff_and_asat(soil_con, tmp_moist_for_runoff, inflow, A, runoff(fidx))
+
+ ! Save dt_runoff based on initial runoff estimate
+ tmp_dt_runoff(fidx) = runoff(fidx) / real(runoff_steps_per_dt, kind=r8)
+
+ ! /**************************************************
+ ! Compute Flow Between Soil Layers ()
+ ! **************************************************/
+ dt_inflow = inflow / real(runoff_steps_per_dt, kind=r8)
+
+ Dsmax = soil_con%Dsmax / runoff_steps_per_day
+
+ DO time_step = 1, runoff_steps_per_dt
+ inflow = dt_inflow
+
+ ! /*************************************
+ ! Compute Drainage between Sublayers
+ ! *************************************/
+ DO lindex = 1, Nlayer - 1
+ ! Brooks & Corey relation for hydraulic conductivity
+ tmp_liq = liq(lindex) - evap(lindex, fidx) ! Assume evap is a 2D array now, adjusted indexing
+
+ IF (tmp_liq < resid_moist(lindex)) THEN
+ tmp_liq = resid_moist(lindex)
+ ENDIF
+
+ IF (tmp_liq > resid_moist(lindex)) THEN
+ CALL calc_Q12(Ksat(lindex), tmp_liq, resid_moist(lindex), max_moist(lindex), soil_con%expt(lindex),Q12(lindex))
+ ELSE
+ Q12(lindex) = 0.0
+ ENDIF
+ ENDDO
+
+ ! /**************************************************
+ ! Solve for Current Soil Layer Moisture, and
+ ! Check Versus Maximum and Minimum Moisture Contents.
+ ! **************************************************/
+ last_index = 0
+ DO lindex = 1, Nlayer - 1
+ IF (lindex == 1) THEN
+ dt_runoff = tmp_dt_runoff(fidx)
+ ELSE
+ dt_runoff = 0.0
+ ENDIF
+
+ ! transport moisture for all sublayers
+ tmp_inflow = 0.0
+
+ ! Update soil layer moisture content
+ liq(lindex) = liq(lindex) + (inflow - dt_runoff) - (Q12(lindex) + evap(lindex, fidx))
+
+ ! Verify that soil layer moisture is less than maximum
+ IF ((liq(lindex) + ice(lindex)) > max_moist(lindex)) THEN
+ tmp_inflow = (liq(lindex) + ice(lindex)) - max_moist(lindex)
+ liq(lindex) = max_moist(lindex) - ice(lindex)
+
+ IF (lindex == 1) THEN
+ Q12(lindex) = Q12(lindex) + tmp_inflow
+ tmp_inflow = 0.0
+ ELSE
+ tmplayer = lindex
+ DO WHILE (tmp_inflow > 0)
+ tmplayer = tmplayer - 1
+ IF (tmplayer < 1) THEN
+ ! If top layer saturated, add to runoff
+ runoff(fidx) = runoff(fidx) + tmp_inflow
+ tmp_inflow = 0.0
+ ELSE
+ ! else add excess soil moisture to next higher layer
+ liq(tmplayer) = liq(tmplayer) + tmp_inflow
+ IF ((liq(tmplayer) + ice(tmplayer)) > max_moist(tmplayer)) THEN
+ tmp_inflow = (liq(tmplayer) + ice(tmplayer)) - max_moist(tmplayer)
+ liq(tmplayer) = max_moist(tmplayer) - ice(tmplayer)
+ ELSE
+ tmp_inflow = 0.0
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF ! /** END trapped excess moisture **/
+ ENDIF ! /** END check if excess moisture in top layer **/
+
+ ! verify that current layer moisture is greater than minimum
+ IF (liq(lindex) < 0.0) THEN
+ ! liquid cannot fall below 0
+ Q12(lindex) = Q12(lindex) + liq(lindex)
+ liq(lindex) = 0.0
+ ENDIF
+
+ IF ((liq(lindex) + ice(lindex)) < resid_moist(lindex)) THEN
+ ! moisture cannot fall below minimum
+ Q12(lindex) = Q12(lindex) + (liq(lindex) + ice(lindex)) - resid_moist(lindex)
+ liq(lindex) = resid_moist(lindex) - ice(lindex)
+ ENDIF
+
+ inflow = Q12(lindex) + tmp_inflow
+ Q12(lindex) = Q12(lindex) + tmp_inflow
+
+ last_index = last_index + 1
+ ENDDO ! /* END loop through soil layers */
+
+ ! /**************************************************
+ ! Compute Baseflow
+ ! **************************************************/
+ ! ARNO model for the bottom soil layer (based on bottom
+ ! soil layer moisture from previous time step)
+
+ lindex = Nlayer
+
+ ! Compute relative moisture
+ rel_moist = (liq(lindex) - resid_moist(lindex)) / &
+ (max_moist(lindex) - resid_moist(lindex))
+
+ ! Compute baseflow as FUNCTION of relative moisture
+ frac = Dsmax * soil_con%Ds / soil_con%Ws
+ dt_baseflow = frac * rel_moist
+ IF (rel_moist > soil_con%Ws) THEN
+ frac = (rel_moist - soil_con%Ws) / (1 - soil_con%Ws)
+ dt_baseflow = dt_baseflow + Dsmax * (1 - soil_con%Ds / soil_con%Ws) * &
+ frac ** soil_con%c
+ ENDIF
+
+ ! Make sure baseflow isn't negative
+ IF (dt_baseflow < 0) THEN
+ dt_baseflow = 0.0
+ ENDIF
+
+ ! Extract baseflow from the bottom soil layer
+ liq(lindex) = liq(lindex) + Q12(lindex - 1) - (evap(lindex, fidx) + dt_baseflow)
+
+ ! Check Lower Sub-Layer Moistures
+ tmp_moist = 0.0
+
+ ! /* If soil moisture has gone below minimum, take water out
+ ! * of baseflow and add back to soil to make up the difference
+ ! * Note: this may lead to negative baseflow, in which case we will
+ ! * reduce evap to make up for it */
+ IF ((liq(lindex) + ice(lindex)) < resid_moist(lindex)) THEN
+ dt_baseflow = dt_baseflow + &
+ (liq(lindex) + ice(lindex)) - resid_moist(lindex)
+ liq(lindex) = resid_moist(lindex) - ice(lindex)
+ ENDIF
+
+ IF ((liq(lindex) + ice(lindex)) > max_moist(lindex)) THEN
+ ! soil moisture above maximum
+ tmp_moist = (liq(lindex) + ice(lindex)) - max_moist(lindex)
+ liq(lindex) = max_moist(lindex) - ice(lindex)
+ tmplayer = lindex
+ DO WHILE (tmp_moist > 0)
+ tmplayer = tmplayer - 1
+ IF (tmplayer < 1) THEN
+ ! If top layer saturated, add to runoff
+ runoff(fidx) = runoff(fidx) + tmp_moist
+ tmp_moist = 0.0
+ ELSE
+ ! else if sublayer exists, add excess soil moisture
+ liq(tmplayer) = liq(tmplayer) + tmp_moist
+ IF ((liq(tmplayer) + ice(tmplayer)) > max_moist(tmplayer)) THEN
+ tmp_moist = (liq(tmplayer) + ice(tmplayer)) - max_moist(tmplayer)
+ liq(tmplayer) = max_moist(tmplayer) - ice(tmplayer)
+ ELSE
+ tmp_moist = 0.0
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ baseflow(fidx) = baseflow(fidx) + dt_baseflow
+ ENDDO ! /* END of sub-dt time step loop */
+
+ ! If negative baseflow, reduce evap accordingly
+ IF (baseflow(fidx) < 0.0) THEN
+ ! layer(lindex)%evap = layer(lindex)%evap + baseflow(fidx) !!!! need check
+ baseflow(fidx) = 0.0
+ endif
+
+ ! Recompute Asat based on final moisture level of upper layers
+ do lindex = 1, Nlayer
+ tmp_moist_for_runoff(lindex) = (liq(lindex) + ice(lindex))
+ enddo
+
+ CALL compute_runoff_and_asat(soil_con, tmp_moist_for_runoff, real(0.0, kind=r8), A, tmp_runoff)
+
+ ! Store tile-wide values
+ do lindex = 1, Nlayer
+ layer(lindex)%moist = layer(lindex)%moist + &
+ ((liq(lindex) + ice(lindex)) * frost_fract(fidx))
+ enddo
+ cell%asat = cell%asat + A * frost_fract(fidx)
+ cell%runoff = cell%runoff + runoff(fidx) * frost_fract(fidx)
+ cell%baseflow = cell%baseflow + baseflow(fidx) * frost_fract(fidx)
+
+ ! ! /** Compute water table depth **/
+ ! CALL wrap_compute_zwt(soil_con, cell)
+
+ enddo
+
+ END SUBROUTINE compute_vic_runoff
+
+
+ ! ******************************************************************************
+ ! * @brief Calculate the saturated area and runoff
+ ! ******************************************************************************
+ SUBROUTINE compute_runoff_and_asat(soil_con, moist, inflow, A, runoff)
+ USE MOD_Hydro_VIC_Variables, only: soil_con_struct, Nlayer
+ IMPLICIT NONE
+ !-----------------------Arguments---------------------------------------
+ type(soil_con_struct), intent(in) :: soil_con
+ real(r8), intent(in) :: moist(Nlayer)
+ real(r8), intent(in) :: inflow
+ real(r8), intent(inout) :: A
+ real(r8), intent(inout) :: runoff
+ !-----------------------Local Variables---------------------------------
+ real(r8) :: top_moist !! total moisture (liquid and frozen) in topmost soil layers (mm)
+ real(r8) :: top_max_moist !! maximum storable moisture (liquid and frozen) in topmost soil layers (mm)
+ integer :: lindex
+ real(r8) :: ex, max_infil, i_0, basis
+ !-----------------------End Variable List-------------------------------
+
+ top_moist = 0.0
+ top_max_moist = 0.0
+ do lindex = 1, Nlayer - 1
+ top_moist = top_moist + moist(lindex)
+ top_max_moist = top_max_moist + soil_con%max_moist(lindex)
+ enddo
+ if (top_moist > top_max_moist) then
+ top_moist = top_max_moist
+ endif
+
+ ! A as in Wood et al. in JGR 97, D3, 1992 equation (1)
+ ex = soil_con%b_infilt / (1.0 + soil_con%b_infilt)
+ A = 1.0 - (1.0 - top_moist / top_max_moist)**ex
+
+ max_infil = (1.0 + soil_con%b_infilt) * top_max_moist
+ i_0 = max_infil * (1.0 - (1.0 - A)**(1.0 / soil_con%b_infilt))
+
+ ! equation (3a) Wood et al.
+ if (inflow == 0.0) then
+ runoff = 0.0
+ else if (max_infil == 0.0) then
+ runoff = inflow
+ else if ((i_0 + inflow) > max_infil) then
+ runoff = inflow - top_max_moist + top_moist
+ ! equation (3b) Wood et al. (wrong in paper)
+ else
+ basis = 1.0 - (i_0 + inflow) / max_infil
+ runoff = (inflow - top_max_moist + top_moist + &
+ top_max_moist * basis**(1.0 * (1.0 + soil_con%b_infilt)))
+ endif
+ if (runoff < 0.0) then
+ runoff = 0.0
+ endif
+ END SUBROUTINE compute_runoff_and_asat
+
+
+ ! ******************************************************************************
+ ! * @brief Calculate drainage between two layers
+ ! ******************************************************************************
+ SUBROUTINE calc_Q12(Ksat, init_moist, resid_moist, max_moist, expt, Q12)
+ IMPLICIT NONE
+ real(r8), intent(in) :: Ksat, init_moist, resid_moist, max_moist, expt
+ real(r8), intent(out) :: Q12
+
+ Q12 = init_moist - ((init_moist - resid_moist)**(1.0d0 - expt) - Ksat / &
+ (max_moist - resid_moist)**expt * (1.0d0 - expt))**(1.0d0 / (1.0d0 - expt)) - resid_moist
+
+ END SUBROUTINE calc_Q12
+
+
+ ! /******************************************************************************
+ ! * @brief Compute spatial average water table position (zwt). Water table
+ ! * position is measured in cm and is negative below the soil surface.
+ ! *****************************************************************************/
+ SUBROUTINE compute_zwt(soil_con,lindex, moist, zwt)
+ USE MOD_Hydro_VIC_Variables
+ IMPLICIT NONE
+ !-----------------------Arguments---------------------------------------
+ type(soil_con_struct), intent(in) :: soil_con
+ integer, intent(in) :: lindex
+ real(r8), intent(in) :: moist
+ real(r8), intent(out) :: zwt
+ !-----------------------Local Variables---------------------------------
+ integer :: i
+ real(r8) :: MISSING = -99999. !/**< missing value */
+ !-----------------------End Variable List-------------------------------
+
+ zwt = MISSING
+
+ ! /** Compute zwt using soil moisture v zwt curve **/
+ i = MAX_ZWTVMOIST - 1
+ do while (i >= 1 .and. moist > soil_con%zwtvmoist_moist(lindex, i))
+ i = i - 1
+ enddo
+
+ if (i == MAX_ZWTVMOIST - 1) then
+ if (moist < soil_con%zwtvmoist_moist(lindex, i)) then
+ zwt = 999.0 ! 999 indicates water table not present in this layer
+ else if (moist == soil_con%zwtvmoist_moist(lindex, i)) then
+ zwt = soil_con%zwtvmoist_zwt(lindex, i) ! Just barely enough water for a water table
+ endif
+ else
+ zwt = soil_con%zwtvmoist_zwt(lindex, i+1) + &
+ (soil_con%zwtvmoist_zwt(lindex, i) - soil_con%zwtvmoist_zwt(lindex, i+1)) * &
+ (moist - soil_con%zwtvmoist_moist(lindex, i+1)) / &
+ (soil_con%zwtvmoist_moist(lindex, i) - soil_con%zwtvmoist_moist(lindex, i+1))
+ endif
+ END SUBROUTINE compute_zwt
+
+
+ ! /******************************************************************************
+ ! * @brief Function to compute spatial average water table position (zwt) for
+ ! * individual layers as well as various total-column versions of zwt.
+ ! * Water table position is measured in cm and is negative below the
+ ! * soil surface.
+ ! *****************************************************************************/
+ SUBROUTINE wrap_compute_zwt(soil_con, cell)
+ USE MOD_Hydro_VIC_Variables
+ IMPLICIT NONE
+
+ !-----------------------Arguments---------------------------------------
+ type(soil_con_struct), intent(in) :: soil_con
+ type(cell_data_struct), intent(inout) :: cell
+ !-----------------------Local Variables---------------------------------
+ integer :: lindex
+ integer :: idx
+ real(r8) :: total_depth
+ real(r8) :: tmp_depth
+ real(r8) :: tmp_moist
+ integer, parameter :: CM_PER_M = 100 !/**< centimeters per meter */
+ real(r8), parameter :: DBL_EPSILON = 2.2204460492503131E-16
+ !-----------------------End Variable List-------------------------------
+
+ ! /** Compute total soil column depth **/
+ total_depth = 0.0
+ do lindex = 1, Nlayer
+ total_depth = total_depth + soil_con%depth(lindex)
+ enddo
+
+ ! /** Compute each layer's zwt using soil moisture v zwt curve **/
+ do lindex = 1, Nlayer
+ CALL compute_zwt(soil_con, lindex, cell%layer(lindex)%moist, cell%layer(lindex)%zwt)
+ enddo
+ if (cell%layer(Nlayer)%zwt == 999) then
+ cell%layer(Nlayer)%zwt = -total_depth * CM_PER_M
+ endif
+
+ ! /** Compute total soil column's zwt; this will be the zwt of the lowest layer that isn't completely saturated **/
+ idx = Nlayer
+ tmp_depth = total_depth
+ do while (idx >= 1 .and. soil_con%max_moist(idx) - cell%layer(idx)%moist <= DBL_EPSILON)
+ tmp_depth = tmp_depth - soil_con%depth(idx)
+ idx = idx - 1
+ enddo
+ if (idx < 1) then
+ cell%zwt = 0.0
+ else if (idx < Nlayer) then
+ if (cell%layer(idx)%zwt /= 999) then
+ cell%zwt = cell%layer(idx)%zwt
+ else
+ cell%zwt = -tmp_depth * CM_PER_M
+ endif
+ else
+ cell%zwt = cell%layer(idx)%zwt
+ endif
+
+ ! /** Compute total soil column's zwt_lumped; this will be the zwt of all N layers lumped together. **/
+ tmp_moist = 0.0
+ do lindex = 1, Nlayer
+ tmp_moist = tmp_moist + cell%layer(lindex)%moist
+ enddo
+ CALL compute_zwt(soil_con, Nlayer + 1, tmp_moist, cell%zwt_lumped)
+
+ if (cell%zwt_lumped == 999) then
+ cell%zwt_lumped = -total_depth * CM_PER_M ! // in cm;
+ endif
+ END SUBROUTINE wrap_compute_zwt
+END MODULE MOD_Hydro_VIC
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_VIC_Variables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_VIC_Variables.F90
new file mode 100644
index 0000000000..4ece3c3d1e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Hydro_VIC_Variables.F90
@@ -0,0 +1,298 @@
+MODULE MOD_Hydro_VIC_Variables
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! /***** Define the number of layers used in VIC *****/
+ integer, parameter :: Nlayer = 3 !/**< Number of soil moisture layers in model */
+ integer :: Nfrost = 1 !/**< Number of frost subareas in model */
+
+ ! /***** Define maximum array sizes for model source code *****/
+ integer, parameter :: MAX_LAYERS = 3 !/**< maximum number of soil moisture layers */
+ integer, parameter :: MAX_FROST_AREAS = 3 !/**< maximum number of frost sub-areas */
+ integer, parameter :: MAX_ZWTVMOIST = 11 !/**< maximum number of points in water table vs moisture curve for each soil layer; should include points at lower and upper boundaries of the layer */
+
+ ! /***** colm layers to vic layers *****/
+ integer, parameter, dimension(:) :: colm2vic_lay(Nlayer) = [3, 6, 10] !/**< colm layers to vic layers */
+
+ ! /******************************************************************************
+ ! * @brief This structure stores all soil variables for each layer in the
+ ! * soil column.
+ ! *****************************************************************************/
+ type layer_data_struct
+ real(r8) :: ice(MAX_FROST_AREAS) ! /**< ice content of the frozen sublayer (mm) */
+ real(r8) :: moist ! /**< moisture content of the unfrozen sublayer (mm) */
+ real(r8) :: evap ! /**< evapotranspiration from soil layer (mm) */
+ real(r8) :: zwt ! /**< water table position relative to soil surface within the layer (cm) */
+ END type layer_data_struct
+
+ ! /******************************************************************************
+ ! * @brief This structure stores soil variables for the complete soil column
+ ! * for each grid cell.
+ ! *****************************************************************************/
+ type cell_data_struct
+ real(r8) :: asat ! /**< saturated area fraction */
+ real(r8) :: baseflow ! /**< baseflow from current cell (mm/TS) */
+ real(r8) :: runoff ! /**< runoff from current cell (mm/TS) */
+ type(layer_data_struct) :: layer(MAX_LAYERS) ! /**< structure containing soil variables for each layer (see above) */
+ !!! for zwt calcaulation, not used
+ real(r8) :: zwt ! /**< average water table position [cm] - using lowest unsaturated layer */
+ real(r8) :: zwt_lumped ! /**< average water table position [cm] - lumping all layers' moisture together */
+ END type cell_data_struct
+
+ ! /******************************************************************************
+ ! * @brief This structure stores the soil parameters for a grid cell.
+ ! *****************************************************************************/
+ type soil_con_struct
+ real(r8) :: frost_fract(MAX_FROST_AREAS) ! /**< spatially distributed frost coverage fractions */
+ real(r8) :: max_moist(MAX_LAYERS) ! /**< Maximum moisture content (mm) per layer */
+ real(r8) :: resid_moist(MAX_LAYERS) ! /**< Residual moisture content of soil layer (mm) */
+ real(r8) :: Ksat(MAX_LAYERS) ! /**< Saturated hydraulic conductivity (mm/day) */
+ real(r8) :: expt(MAX_LAYERS) ! /**< Layer-specific exponent n (=3+2/lambda) in Campbell's equation for hydraulic conductivity, HBH 5.6 */
+ !!!! to be calibrated
+ real(r8) :: b_infilt ! /**< Infiltration parameter */
+ real(r8) :: Ds ! /**< Fraction of maximum subsurface flow rate */
+ real(r8) :: Ws ! /**< Fraction of maximum soil moisture */
+ real(r8) :: Dsmax ! /**< Maximum subsurface flow rate (mm/day) */
+ real(r8) :: c ! /**< Exponent in ARNO baseflow scheme */
+ real(r8) :: depth(MAX_LAYERS) ! /**< Thickness of each soil moisture layer (m) */
+ !!! for zwt calculation, not used
+ ! Bubbling pressure, HBH 5.15 (cm)
+ real(r8) :: bubble(MAX_LAYERS)
+ ! Zwt values in the zwt-v-moist curve for each layer.
+ real(r8) :: zwtvmoist_zwt(MAX_LAYERS + 2, MAX_ZWTVMOIST)
+ ! Moist values in the zwt-v-moist curve for each layer.
+ real(r8) :: zwtvmoist_moist(MAX_LAYERS + 2, MAX_ZWTVMOIST)
+ END type soil_con_struct
+
+CONTAINS
+
+
+ SUBROUTINE vic_para(porsl, theta_r, hksati, bsw, wice_soisno, wliq_soisno, fevpg, rootflux, &
+ b_infilt, Dsmax, Ds, Ws, c, &
+ soil_con, cell)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ type(soil_con_struct) , intent(inout) :: soil_con
+ type(cell_data_struct), intent(inout) :: cell
+
+ real(r8), intent(in) :: porsl(1:nl_soil), theta_r(1:nl_soil), hksati(1:nl_soil), bsw(1:nl_soil)
+ real(r8), intent(in) :: wice_soisno(1:nl_soil), wliq_soisno(1:nl_soil)
+ real(r8), intent(in) :: fevpg
+ real(r8), intent(in) :: rootflux(1:nl_soil)
+
+ real(r8), intent(in) :: b_infilt, Dsmax, Ds, Ws, c
+ real(r8) :: soil_tmp(Nlayer), ice_tmp(Nlayer)
+ integer :: lb, lp, k, ilay
+
+ real(r8) :: dltime !int(DEF_simulation_time%timestep)
+ !-----------------------END Variable List-------------------------------
+
+ dltime = DEF_simulation_time%timestep
+
+ CALL CoLM2VIC(dz_soi, soil_tmp)
+ soil_con%depth = soil_tmp
+
+ CALL CoLM2VIC_weight(porsl, soil_tmp)
+ ! convert - to mm
+ soil_con%max_moist = soil_tmp*soil_con%depth*1000
+
+ CALL CoLM2VIC_weight(theta_r, soil_tmp)
+ ! convert - to mm
+ soil_con%resid_moist = soil_tmp*soil_con%depth*1000
+
+ CALL CoLM2VIC_weight(hksati, soil_tmp)
+ ! convert mm/s to mm/day
+ soil_con%Ksat = soil_tmp*86400
+
+ CALL CoLM2VIC_weight(bsw, soil_tmp)
+ ! 2*lambda+3
+ soil_con%expt = soil_tmp*2+3
+
+ soil_con%b_infilt = b_infilt
+ soil_con%Dsmax = Dsmax
+ soil_con%Ds = Ds
+ soil_con%Ws = Ws
+ soil_con%c = c
+
+ soil_con%frost_fract = 1
+ IF (sum(wice_soisno)>0) THEN
+ Nfrost = 3
+ DO k = 1, Nfrost
+ IF (Nfrost == 1) THEN
+ soil_con%frost_fract(k) = 1.0
+ ELSEIF (Nfrost == 2) THEN
+ soil_con%frost_fract(k) = 0.5
+ ELSE
+ soil_con%frost_fract(k) = 1.0 / real(Nfrost - 1, kind=8)
+ IF (k == 1 .or. k == Nfrost) THEN
+ soil_con%frost_fract(k) = soil_con%frost_fract(k) / 2.0
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL CoLM2VIC(wliq_soisno, soil_tmp)
+ DO ilay = 1, Nlayer
+ ! mm
+ cell%layer(ilay)%moist = soil_tmp(ilay)
+ ENDDO
+
+ DO ilay=1, Nlayer
+ cell%layer(ilay)%ice(:) = 0
+ ENDDO
+
+ IF (sum(wice_soisno)>0) THEN
+ DO ilay = 1, Nlayer
+ lp = colm2vic_lay(ilay)
+ IF (ilay==1) THEN
+ lb = 1
+ ELSE
+ lb = colm2vic_lay(ilay-1)+1
+ ENDIF
+ CALL VIC_IceLay(lb, lp, wice_soisno(lb:lp), ice_tmp)
+ cell%layer(ilay)%ice(:) = ice_tmp
+ ENDDO
+ ! ELSE
+ ! DO ilay = 1, Nlayer
+ ! cell%layer(ilay)%ice(:) = 0
+ ! ENDDO
+ ENDIF
+
+ CALL CoLM2VIC(rootflux, soil_tmp)
+ ! mm/s*dltime to convert to mm
+ DO ilay = 1, Nlayer
+ cell%layer(ilay)%evap = soil_tmp(ilay)*dltime
+ ENDDO
+ cell%layer(1)%evap = cell%layer(1)%evap + fevpg*dltime
+
+ END SUBROUTINE vic_para
+
+
+ SUBROUTINE VIC_IceLay(lb, lp, colm_ice, vic_ice)
+
+ IMPLICIT NONE
+ !-----------------------Arguments---------------------------------------
+ integer , intent(in ) :: lb
+ integer , intent(in ) :: lp
+ real(kind=8), intent(in ) :: colm_ice(lb:lp)
+ real(kind=8), intent(out) :: vic_ice(3)
+ !-----------------------Local variables---------------------------------
+ integer :: idx, colm_lay
+ real(kind=8) :: totalSum
+ real(kind=8) :: multiplier
+ real(kind=8) :: ice_tmp(lp-lb+1)
+ integer :: vic_lay=3
+ !-----------------------END Variable List-------------------------------
+
+ colm_lay = lp - lb + 1
+ ice_tmp = colm_ice
+ totalSum = sum(ice_tmp)
+
+ IF (colm_lay == 1) THEN
+ vic_ice = totalSum / vic_lay
+ ELSEIF (colm_lay == 2) THEN
+ vic_ice(1) = ice_tmp(1) * 2.0 / vic_lay
+ vic_ice(3) = ice_tmp(2) * 2.0 / vic_lay
+ ELSEIF (colm_lay == 3) THEN
+ vic_ice = ice_tmp
+ ELSE
+ DO idx = 1, min(int((colm_lay-1)/vic_lay), vic_lay)
+ multiplier = merge(1.0, 0.0, colm_lay > idx*vic_lay)
+ vic_ice(1) = vic_ice(1) + ice_tmp(idx) * multiplier
+ vic_ice(3) = vic_ice(3) + ice_tmp(colm_lay-idx+1) * multiplier
+ ENDDO
+ multiplier = merge((colm_lay-idx*vic_lay)/vic_lay, 0, colm_lay <= (idx+1)*vic_lay)
+ vic_ice(1) = vic_ice(1) + ice_tmp(idx+1) * multiplier
+ vic_ice(3) = vic_ice(3) + ice_tmp(colm_lay-idx) * multiplier
+ ENDIF
+ vic_ice(2) = totalSum - vic_ice(1) - vic_ice(3)
+
+ END SUBROUTINE VIC_Icelay
+
+
+ SUBROUTINE CoLM2VIC(colm_water, vic_water)
+
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+ !-----------------------Arguments---------------------------------------
+ real, intent(in ) :: colm_water(1:nl_soil)
+ real, intent(out) :: vic_water(Nlayer)
+ !-----------------------Local variables---------------------------------
+ integer :: i_colm, i_vic
+ !-----------------------END Variable List-------------------------------
+
+ DO i_vic = 1, Nlayer
+ vic_water(i_vic) = 0
+ IF (i_vic == 1) THEN
+ DO i_colm = 1, colm2vic_lay(i_vic)
+ vic_water(i_vic) = vic_water(i_vic) + colm_water(i_colm)
+ ENDDO
+ ELSE
+ DO i_colm = colm2vic_lay(i_vic-1)+1, colm2vic_lay(i_vic)
+ vic_water(i_vic) = vic_water(i_vic) + colm_water(i_colm)
+ ENDDO
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CoLM2VIC
+
+
+ SUBROUTINE CoLM2VIC_weight(colm_water, vic_water)
+
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+ !-----------------------Arguments---------------------------------------
+ real, intent(in ) :: colm_water(1:nl_soil)
+ real, intent(out) :: vic_water(Nlayer)
+ !-----------------------Local variables---------------------------------
+ integer :: i_colm, i_vic
+ !-----------------------END Variable List-------------------------------
+
+ DO i_vic = 1, Nlayer
+ vic_water(i_vic) = 0
+ IF (i_vic == 1) THEN
+ DO i_colm = 1, colm2vic_lay(i_vic)
+ vic_water(i_vic) = vic_water(i_vic) + colm_water(i_colm)*dz_soi(i_colm)
+ ENDDO
+ vic_water(i_vic) = vic_water(i_vic)/sum(dz_soi(1:colm2vic_lay(i_vic)))
+ ELSE
+ DO i_colm = colm2vic_lay(i_vic-1)+1, colm2vic_lay(i_vic)
+ vic_water(i_vic) = vic_water(i_vic) + colm_water(i_colm)*dz_soi(i_colm)
+ ENDDO
+ vic_water(i_vic) = vic_water(i_vic)/sum(dz_soi(colm2vic_lay(i_vic-1)+1:colm2vic_lay(i_vic)))
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CoLM2VIC_weight
+
+
+ SUBROUTINE VIC2CoLM(colm_water, vic_water)
+
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+ !-----------------------Arguments---------------------------------------
+ real, intent(in ) :: vic_water(Nlayer)
+ real, intent(inout) :: colm_water(1:nl_soil)
+ !-----------------------Local variables---------------------------------
+ integer :: i_colm, i_vic
+ !-----------------------END Variable List-------------------------------
+
+ DO i_vic = 1, Nlayer
+ IF (i_vic == 1) THEN
+ DO i_colm = 1, colm2vic_lay(i_vic)
+ colm_water(i_colm) = vic_water(i_vic)*(dz_soi(i_colm)/sum(dz_soi(1:colm2vic_lay(i_vic))))
+ ENDDO
+ ELSE
+ DO i_colm = colm2vic_lay(i_vic-1)+1, colm2vic_lay(i_vic)
+ colm_water(i_colm) = vic_water(i_vic)*(dz_soi(i_colm)/sum(dz_soi(colm2vic_lay(i_vic-1)+1:colm2vic_lay(i_vic))))
+ ENDDO
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE VIC2CoLM
+
+
+END MODULE MOD_Hydro_VIC_Variables
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Vector_ReadWrite.F90 b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Vector_ReadWrite.F90
new file mode 100644
index 0000000000..35d7de3e75
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/HYDRO/MOD_Vector_ReadWrite.F90
@@ -0,0 +1,291 @@
+#include
+
+MODULE MOD_Vector_ReadWrite
+!-----------------------------------------------------------------------
+! DESCRIPTION:
+!
+! Read/Write data in vector form.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ PUBLIC :: vector_gather_and_write
+ PUBLIC :: vector_gather_map2grid_and_write
+ PUBLIC :: vector_read_and_scatter
+
+CONTAINS
+
+ ! -------
+ SUBROUTINE vector_gather_to_root ( &
+ vector, vlen, totalvlen, data_address, wdata)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: vector (:)
+ integer, intent(in) :: vlen
+ integer, intent(in) :: totalvlen
+
+ type(pointer_int32_1d), intent(in) :: data_address (0:)
+
+ real(r8), allocatable, intent(inout) :: wdata (:)
+
+ ! Local variables
+ integer :: iwork, mesg(2), isrc, ndata
+ real(r8), allocatable :: rcache(:)
+
+ IF (totalvlen <= 0) RETURN
+
+ IF (p_is_root) THEN
+ allocate (wdata (totalvlen))
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+ mesg = (/p_iam_glb, vlen/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (vlen > 0) THEN
+ CALL mpi_send (vector, vlen, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+ IF (p_is_compute .and. vlen > 0) THEN
+ wdata(data_address(p_iam_compute)%val) = vector
+ ENDIF
+
+ DO iwork = 0, p_np_compute-1
+ IF (p_address_compute(iwork) == p_iam_glb) CYCLE
+
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate(rcache (ndata))
+
+ CALL mpi_recv (rcache, ndata, MPI_REAL8, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ wdata(data_address(p_itis_compute(isrc))%val) = rcache
+
+ deallocate (rcache)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ wdata(data_address(0)%val) = vector
+#endif
+
+ END SUBROUTINE vector_gather_to_root
+
+ ! -------
+ SUBROUTINE vector_gather_and_write ( vector, vlen, totalvlen, data_address, &
+ fileout, varname, dimname, itime_in_file, longname, units)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_DataType
+ USE MOD_NetCDFSerial
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: vector (:)
+ integer, intent(in) :: vlen
+ integer, intent(in) :: totalvlen
+
+ type(pointer_int32_1d), intent(in) :: data_address (0:)
+
+ character(len=*), intent(in) :: fileout
+ character(len=*), intent(in) :: varname
+ character(len=*), intent(in) :: dimname
+
+ integer, intent(in), optional :: itime_in_file
+ character(len=*), intent(in), optional :: longname
+ character(len=*), intent(in), optional :: units
+
+ ! Local variables
+ real(r8), allocatable :: wdata(:)
+ logical :: write_attr
+
+
+ CALL vector_gather_to_root (vector, vlen, totalvlen, data_address, wdata)
+
+ IF (p_is_root) THEN
+
+ IF (present(itime_in_file)) THEN
+ CALL ncio_write_serial_time (fileout, varname, itime_in_file, wdata, &
+ dimname, 'time', DEF_HIST_CompressLevel)
+ ELSE
+ CALL ncio_write_serial (fileout, varname, wdata, &
+ dimname, DEF_REST_CompressLevel)
+ ENDIF
+
+ IF (present(itime_in_file)) THEN
+ write_attr = itime_in_file <= 1
+ ELSE
+ write_attr = .true.
+ ENDIF
+
+ IF (write_attr) THEN
+ CALL ncio_put_attr (fileout, varname, 'missing_value', spval)
+ IF (present(longname)) CALL ncio_put_attr (fileout, varname, 'long_name', longname)
+ IF (present(units )) CALL ncio_put_attr (fileout, varname, 'units', units )
+ ENDIF
+
+ deallocate (wdata)
+
+ ENDIF
+
+ END SUBROUTINE vector_gather_and_write
+
+ ! -------
+ SUBROUTINE vector_gather_map2grid_and_write ( &
+ vector, vlen, totalvlen, data_address, nlon, x_vec, nlat, y_vec, &
+ fileout, varname, lon_name, lat_name, itime_in_file, longname, units)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_DataType
+ USE MOD_NetCDFSerial
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: fileout
+ real(r8), intent(in) :: vector (:)
+ integer, intent(in) :: vlen
+ integer, intent(in) :: totalvlen
+ character(len=*), intent(in) :: varname
+ character(len=*), intent(in) :: lon_name, lat_name
+
+ type(pointer_int32_1d), intent(in) :: data_address (0:)
+
+ integer, intent(in) :: nlon, x_vec (:)
+ integer, intent(in) :: nlat, y_vec (:)
+
+ integer, intent(in), optional :: itime_in_file
+ character(len=*), intent(in), optional :: longname
+ character(len=*), intent(in), optional :: units
+
+ ! Local variables
+ integer :: i
+ real(r8), allocatable :: wdata(:), wdata2d(:,:)
+ logical :: write_attr
+
+ CALL vector_gather_to_root (vector, vlen, totalvlen, data_address, wdata)
+
+ IF (p_is_root) THEN
+
+ allocate (wdata2d (nlon,nlat))
+ wdata2d(:,:) = spval
+
+ DO i = 1, totalvlen
+ wdata2d(x_vec(i),y_vec(i)) = wdata(i)
+ ENDDO
+
+ IF (present(itime_in_file)) THEN
+ CALL ncio_write_serial_time (fileout, varname, itime_in_file, wdata2d, &
+ lon_name, lat_name, 'time', DEF_HIST_CompressLevel)
+ ELSE
+ CALL ncio_write_serial (fileout, varname, wdata2d, &
+ lon_name, lat_name, DEF_REST_CompressLevel)
+ ENDIF
+
+ IF (present(itime_in_file)) THEN
+ write_attr = itime_in_file == 1
+ ELSE
+ write_attr = .true.
+ ENDIF
+
+ IF (write_attr) THEN
+ CALL ncio_put_attr (fileout, varname, 'missing_value', spval)
+ IF (present(longname)) CALL ncio_put_attr (fileout, varname, 'long_name', longname)
+ IF (present(units )) CALL ncio_put_attr (fileout, varname, 'units', units )
+ ENDIF
+
+ deallocate (wdata )
+ deallocate (wdata2d)
+
+ ENDIF
+
+ END SUBROUTINE vector_gather_map2grid_and_write
+
+ ! -----
+ SUBROUTINE vector_read_and_scatter ( &
+ filein, vector, vlen, varname, data_address)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_DataType
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filein
+ real(r8), allocatable, intent(inout) :: vector (:)
+ integer, intent(in) :: vlen
+ character(len=*), intent(in) :: varname
+ type(pointer_int32_1d), intent(in) :: data_address (0:)
+
+ ! Local variables
+ integer :: iwork, ndata
+ real(r8), allocatable :: rdata(:), rcache(:)
+
+ IF (p_is_root) THEN
+ CALL ncio_read_serial (filein, varname, rdata)
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_root) THEN
+ DO iwork = 0, p_np_compute-1
+ IF (allocated(data_address(iwork)%val)) THEN
+
+ ndata = size(data_address(iwork)%val)
+ allocate(rcache (ndata))
+ rcache = rdata(data_address(iwork)%val)
+
+ IF (p_address_compute(iwork) == p_iam_glb) THEN
+ IF (ndata > 0) THEN
+ IF (.not. allocated(vector)) allocate(vector(ndata))
+ vector = rcache
+ ENDIF
+ ELSE
+ CALL mpi_send (rcache, ndata, MPI_REAL8, &
+ p_address_compute(iwork), mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ deallocate (rcache)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_compute .and. (.not. p_is_root)) THEN
+ IF (vlen > 0) THEN
+ IF (.not. allocated(vector)) allocate(vector(vlen))
+ CALL mpi_recv (vector, vlen, MPI_REAL8, p_address_root, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ IF (.not. allocated(vector)) allocate(vector(vlen))
+ vector = rdata(data_address(0)%val)
+#endif
+
+ IF (p_is_root) deallocate(rdata)
+
+ END SUBROUTINE vector_read_and_scatter
+
+END MODULE MOD_Vector_ReadWrite
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_3DCanopyRadiation.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_3DCanopyRadiation.F90
new file mode 100644
index 0000000000..8fbfe86df5
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_3DCanopyRadiation.F90
@@ -0,0 +1,1455 @@
+#include
+
+MODULE MOD_3DCanopyRadiation
+
+!-----------------------------------------------------------------------
+!
+! --- A 3D Canopy Radiation Transfer Model ---
+! for Plant Community (PC) Simulation
+!
+! Sun
+! ///
+! ///
+! _____ tree _____ --- Layer3
+! /||||||| |||||||
+! /||||||||| |||||||||
+! / \|||||// / \|||||//
+! / | / / | / --- Layer2
+! / | / / | / /xx\
+! / shadow |/ grass / |/ shrub/\xx/
+! __/.........|_________\\//\/......|________/..|/__ --- Layer1
+! /////////////////////////////////////////////////////////////////////
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+#ifdef LULC_IGBP_PC
+ PUBLIC :: ThreeDCanopy_wrap
+#endif
+ PUBLIC :: ThreeDCanopy
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+#ifdef LULC_IGBP_PC
+
+ SUBROUTINE ThreeDCanopy_wrap (ipatch, czen, albg, albv, tran, ssun, ssha)
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! This is a wrap SUBROUTINE to CALL 3D canopy radiative model below
+! CALL ThreeDCanopy()
+!
+! Created by Hua Yuan, 08/2019
+!
+! !REFERENCES:
+! Yuan, H., R. E. Dickinson, Y. Dai, M. J. Shaikh, L. Zhou, W. Shangguan,
+! and D. Ji, 2014: A 3D canopy radiative transfer model for global climate
+! modeling: Description, validation, and application. Journal of Climate,
+! 27, 1168-1192, https://doi.org/10.1175/JCLI-D-13-00155.1.
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW, DEF_PC_CROP_SPLIT
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_Global
+ USE MOD_Const_PFT
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ipatch
+ real(r8), intent(in) :: czen
+ real(r8), intent(in) :: albg(2,2)
+ real(r8), intent(out) :: albv(2,2)
+ real(r8), intent(out) :: tran(2,3)
+ real(r8), intent(out) :: ssun(2,2)
+ real(r8), intent(out) :: ssha(2,2)
+
+!-------------------------- Local Variables ----------------------------
+ integer :: i, p, ps, pe, pn;
+
+ ! sunlit absorption fraction calculation mode
+ ! .true. USE 3D model, otherwise USE 1D case
+ ! NOTE: The 3D version will be activated in the new release,
+ ! accompanied by a new set of canopy structure data.
+ logical, parameter :: fsun3D = .false.
+
+ ! define allocatable variables
+ integer, allocatable :: canlay(:)
+ real(r8), allocatable :: albd(:,:), albi(:,:)
+ real(r8), allocatable :: fabd(:,:), fabi(:,:), fadd(:,:)
+ real(r8), allocatable :: ftdd(:,:), ftid(:,:), ftii(:,:)
+ real(r8), allocatable :: rho (:,:), tau (:,:)
+ real(r8), allocatable :: csiz(:), chgt(:), chil(:), lsai(:)
+ real(r8), allocatable :: fsun_id(:), fsun_ii(:), psun(:)
+ real(r8), allocatable :: phi1(:), phi2(:), gdir(:), fcover(:)
+
+ ! vegetation snow optical properties, 1:vis, 2:nir
+ real(r8) :: rho_sno(2), tau_sno(2)
+ data rho_sno(1), rho_sno(2) /0.5, 0.2/
+ data tau_sno(1), tau_sno(2) /0.3, 0.2/
+!-----------------------------------------------------------------------
+
+ ! get patch PFT index
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ ! Calculate the end index of natrue PFT
+ DO i = ps, pe
+ pn = i
+ p = pftclass(i)
+ IF (DEF_PC_CROP_SPLIT .and. p.ge.15) THEN
+ pn = pn - 1
+ EXIT
+ ENDIF
+ ENDDO
+
+ ! If pn less than start index, there is no nature PFT
+ ! Otherwise, set the new end index
+ IF (pn.ge.ps) THEN
+ pe = pn
+ ELSE
+ RETURN
+ ENDIF
+
+ ! allocate memory for defined variables
+ allocate (albd (ps:pe, 2) )
+ allocate (albi (ps:pe, 2) )
+ allocate (fabd (ps:pe, 2) )
+ allocate (fabi (ps:pe, 2) )
+ allocate (fadd (ps:pe, 2) )
+ allocate (ftdd (ps:pe, 2) )
+ allocate (ftid (ps:pe, 2) )
+ allocate (ftii (ps:pe, 2) )
+ allocate (rho (ps:pe, 2) )
+ allocate (tau (ps:pe, 2) )
+ allocate (csiz (ps:pe) )
+ allocate (chgt (ps:pe) )
+ allocate (chil (ps:pe) )
+ allocate (lsai (ps:pe) )
+ allocate (canlay (ps:pe) )
+ allocate (fsun_id(ps:pe) )
+ allocate (fsun_ii(ps:pe) )
+ allocate (psun (ps:pe) )
+ allocate (phi1 (ps:pe) )
+ allocate (phi2 (ps:pe) )
+ allocate (gdir (ps:pe) )
+ allocate (fcover (ps:pe) )
+
+ ! initialization
+ albd=1.; albi=1.; fabd=0.; fabi=0.;
+ ftdd=1.; ftid=0.; ftii=1.; fadd=0.;
+ csiz(:) = (htop_p(ps:pe) - hbot_p(ps:pe)) / 2
+ chgt(:) = (htop_p(ps:pe) + hbot_p(ps:pe)) / 2
+ lsai(:) = lai_p(ps:pe) + sai_p(ps:pe)
+ fcover(ps:pe) = pftfrac(ps:pe) / sum(pftfrac(ps:pe))
+
+ ! calculate weighted plant optical properties
+ ! loop for each PFT
+ rho = 0.
+ tau = 0.
+ DO i = ps, pe
+
+ p = pftclass(i)
+ canlay(i) = canlay_p(p)
+ chil(i) = chil_p(p)
+
+ IF (lsai(i) > 0.) THEN
+ rho(i,:) = rho_p(:,1,p)*lai_p(i)/lsai(i) &
+ + rho_p(:,2,p)*sai_p(i)/lsai(i)
+ tau(i,:) = tau_p(:,1,p)*lai_p(i)/lsai(i) &
+ + tau_p(:,2,p)*sai_p(i)/lsai(i)
+ ENDIF
+
+ ! account for snow on vegetation
+ IF ( DEF_VEG_SNOW ) THEN
+ ! modify rho, tau, USE: fwet_snow_p
+ rho(i,:) = (1-fwet_snow_p(i))*rho(i,:) + fwet_snow_p(i)*rho_sno(:)
+ tau(i,:) = (1-fwet_snow_p(i))*tau(i,:) + fwet_snow_p(i)*tau_sno(:)
+ ENDIF
+
+ ENDDO
+
+ ! CALL 3D canopy radiation transfer model
+ CALL ThreeDCanopy(ps, pe, canlay, fcover(ps:pe), csiz, chgt, chil, czen, &
+ lsai, rho, tau, albg(:,1), albg(:,2), albd, albi, &
+ fabd, fabi, ftdd, ftid, ftii, fadd, psun, fsun_id, fsun_ii, &
+ thermk_p(ps:pe), fshade_p(ps:pe) )
+
+ ! calculate extkb_p, extkd_p
+ ! applied for 1D case
+ extkd_p(ps:pe) = 0.719 !used for scaling-up coefficients from leaf to canopy
+
+ ! 11/07/2018: calculate gee FUNCTION consider LAD
+ DO i = ps, pe
+ p = pftclass(i)
+ phi1(i) = 0.5 - 0.633 * chil_p(p) - 0.33 * chil_p(p) * chil_p(p)
+ phi2(i) = 0.877 * ( 1. - 2. * phi1(i) )
+ ENDDO
+
+ ! 11/07/2018: calculate gee FUNCTION consider LAD
+ gdir = phi1 + phi2*czen
+ extkb_p(ps:pe) = gdir/czen
+
+ fsun_id(:) = 0.
+ fsun_ii(:) = 0.
+
+ ! 1D sunlit leaves absorption fraction in diffuse format
+ ! Table 3, Yuan et al., (2014).
+ DO p = ps, pe
+ IF (lsai(p) > 0. .and. .not.fsun3D) THEN
+ fsun_id(p) = (1._r8 - exp(-2._r8*extkb_p(p)*lsai(p))) &
+ / (1._r8 - exp(-extkb_p(p)*lsai(p))) &
+ / 2.0_r8 * psun(p)
+
+ fsun_ii(p) = (1._r8 - exp(-extkb_p(p)*lsai(p)-lsai(p))) &
+ / (1._r8 - exp(-lsai(p))) &
+ / (1._r8 + extkb_p(p)) * psun(p)
+ ENDIF
+ ENDDO
+
+ ! Calculate albv, ssun, ssha and tran for PFTs
+ ! NOTE: CoLM (1/2,): vis/nir; (,1/2): dir/dif
+ albv(1,1) = albd(ps,1); albv(1,2) = albi(ps,1)
+ albv(2,1) = albd(ps,2); albv(2,2) = albi(ps,2)
+
+ ! ssun(band, dir/dif, pft), fabd/fadd(pft, band)
+ ssun_p(1,1,ps:pe) = (fabd(:,1)-fadd(:,1)) * fsun_id + fadd(:,1)
+ ssun_p(2,1,ps:pe) = (fabd(:,2)-fadd(:,2)) * fsun_id + fadd(:,2)
+ ssha_p(1,1,ps:pe) = (fabd(:,1)-fadd(:,1)) * (1.-fsun_id)
+ ssha_p(2,1,ps:pe) = (fabd(:,2)-fadd(:,2)) * (1.-fsun_id)
+ ssun_p(1,2,ps:pe) = fabi(:,1) * fsun_ii
+ ssun_p(2,2,ps:pe) = fabi(:,2) * fsun_ii
+ ssha_p(1,2,ps:pe) = fabi(:,1) * (1.-fsun_ii)
+ ssha_p(2,2,ps:pe) = fabi(:,2) * (1.-fsun_ii)
+
+ ssun(1,1) = sum( ssun_p(1,1,ps:pe) * pftfrac(ps:pe) )
+ ssun(2,1) = sum( ssun_p(2,1,ps:pe) * pftfrac(ps:pe) )
+ ssun(1,2) = sum( ssun_p(1,2,ps:pe) * pftfrac(ps:pe) )
+ ssun(2,2) = sum( ssun_p(2,2,ps:pe) * pftfrac(ps:pe) )
+
+ ssha(1,1) = sum( ssha_p(1,1,ps:pe) * pftfrac(ps:pe) )
+ ssha(2,1) = sum( ssha_p(2,1,ps:pe) * pftfrac(ps:pe) )
+ ssha(1,2) = sum( ssha_p(1,2,ps:pe) * pftfrac(ps:pe) )
+ ssha(2,2) = sum( ssha_p(2,2,ps:pe) * pftfrac(ps:pe) )
+
+ tran(1,1) = ftid(ps,1)
+ tran(2,1) = ftid(ps,2)
+ tran(1,3) = ftdd(ps,1)
+ tran(2,3) = ftdd(ps,2)
+ tran(1,2) = ftii(ps,1)
+ tran(2,2) = ftii(ps,2)
+
+ ! deallocate memory for defined variables
+ deallocate (albd )
+ deallocate (albi )
+ deallocate (fabd )
+ deallocate (fabi )
+ deallocate (fadd )
+ deallocate (ftdd )
+ deallocate (ftid )
+ deallocate (ftii )
+ deallocate (rho )
+ deallocate (tau )
+ deallocate (csiz )
+ deallocate (chgt )
+ deallocate (chil )
+ deallocate (lsai )
+ deallocate (canlay )
+ deallocate (fsun_id )
+ deallocate (fsun_ii )
+ deallocate (psun )
+ deallocate (phi1 )
+ deallocate (phi2 )
+ deallocate (gdir )
+ deallocate (fcover )
+
+ END SUBROUTINE ThreeDCanopy_wrap
+#endif
+
+
+ SUBROUTINE ThreeDCanopy(ps, pe, canlay, fcover, csiz, chgt, chil, coszen, &
+ lsai, rho, tau, albgrd, albgri, albd, albi, &
+ fabd, fabi, ftdd, ftid, ftii, fadd, psun, &
+ fsun_id, fsun_ii, thermk, fshade)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! ThreeDCanopy based on Dickinson (2008) using three canopy layer
+! to calculate fluxes absorbed by vegetation, reflected by vegetation,
+! and transmitted through vegetation for unit incoming direct or
+! diffuse flux given an underlying surface with known albedo.
+!
+! Created by Hua Yuan, 08/2019
+!
+! !HISTORY:
+! Before 2013: Robert E. Dickinson proposed the initial idea. Dickinson and
+! Muhammad J. Shake contributed to the code writing.
+!
+! !REFERENCES:
+! Yuan, H., R. E. Dickinson, Y. Dai, M. J. Shaikh, L. Zhou, W. Shangguan,
+! and D. Ji, 2014: A 3D canopy radiative transfer model for global climate
+! modeling: Description, validation, and application. Journal of Climate,
+! 27, 1168-1192, https://doi.org/10.1175/JCLI-D-13-00155.1.
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ integer, parameter :: numrad = 2
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer , intent(in) :: ps, pe !pft index bounds
+ integer , intent(in) :: canlay(ps:pe) !canopy level for current pft
+ real(r8), intent(in) :: fcover(ps:pe) !fractional cover of pft within a patch
+ real(r8), intent(in) :: csiz (ps:pe) !crown size of vegetation
+ real(r8), intent(in) :: chgt (ps:pe) !central height of crown
+ ! NOTE: The 'cdcw' parameter will be activated in the new release, accompanied by
+ ! a new set of canopy structure data. Currently we set cdcw = 1, i.e., sphere
+ real(r8) :: cdcw (ps:pe) !crown depth to crown width
+ real(r8), intent(in) :: chil (ps:pe) !leaf angle distribution parameter
+ real(r8), intent(in) :: lsai (ps:pe) !LAI+SAI
+ real(r8), intent(in) :: rho (ps:pe,numrad) !leaf/stem refl weighted by fraction LAI and SAI
+ real(r8), intent(in) :: tau (ps:pe,numrad) !leaf/stem tran weighted by fraction LAI and SAI
+
+ real(r8), intent(in) :: coszen !cosine solar zenith angle for next time step
+ real(r8), intent(in) :: albgrd(numrad) !ground albedo (direct) (column-level)
+ real(r8), intent(in) :: albgri(numrad) !ground albedo (diffuse)(column-level)
+
+ real(r8), intent(out) :: albd(ps:pe,numrad) !surface albedo (direct)
+ real(r8), intent(out) :: albi(ps:pe,numrad) !surface albedo (diffuse)
+ real(r8), intent(out) :: fabd(ps:pe,numrad) !flux absorbed by veg per unit direct flux
+ real(r8), intent(out) :: fabi(ps:pe,numrad) !flux absorbed by veg per unit diffuse flux
+ real(r8), intent(out) :: ftdd(ps:pe,numrad) !down direct flux below veg per unit dir flx
+ real(r8), intent(out) :: ftid(ps:pe,numrad) !down diffuse flux below veg per unit dir flx
+ real(r8), intent(out) :: ftii(ps:pe,numrad) !down diffuse flux below veg per unit dif flx
+ real(r8), intent(out) :: fadd(ps:pe,numrad) !absorbed flux in direct mode per unit direct flux
+ real(r8), intent(out) :: psun (ps:pe) !percent sunlit vegetation cover
+ real(r8), intent(out) :: fsun_id (ps:pe) !frac of dif rad abs. by sunlit leaves incident dir
+ real(r8), intent(out) :: fsun_ii (ps:pe) !frac of dif rad abs. by sunlit leaves incident dif
+ real(r8), intent(out) :: thermk (ps:pe) !direct transmittance of diffuse radiation
+ real(r8), intent(out) :: fshade (ps:pe) !shadow in diffuse case of vegetation
+
+!-------------------------- Local Variables ----------------------------
+ real(r8), parameter :: mpe = 1.0e-06_r8 !prevents overflow for division by zero
+ integer , parameter :: nlay=3 !number of canopy layers
+ real(r8), parameter :: D0=0.0_r8 !double accuracy real number
+ real(r8), parameter :: D1=1.0_r8 !double accuracy real number
+ real(r8), parameter :: D2=2.0_r8 !double accuracy real number
+ real(r8), parameter :: D3=3.0_r8 !double accuracy real number
+ real(r8), parameter :: D4=4.0_r8 !double accuracy real number
+ real(r8), parameter :: D6=6.0_r8 !double accuracy real number
+ real(r8), parameter :: D7=7.0_r8 !double accuracy real number
+ real(r8), parameter :: D8=8.0_r8 !double accuracy real number
+ real(r8), parameter :: D9=9.0_r8 !double accuracy real number
+ real(r8), parameter :: D10=10.0_r8 !double accuracy real number
+ real(r8), parameter :: D16=16.0_r8 !double accuracy real number
+ real(r8), parameter :: DH=0.5_r8 !quad accuracy real number
+ real(r16),parameter :: DDH=0.5_r16 !quad accuracy real number
+ real(r16),parameter :: DD0=0.0_r16 !quad accuracy real number
+ real(r16),parameter :: DD1=1.0_r16 !quad accuracy real number
+ real(r8) ,parameter :: pi=3.14159265358979323846_r8 !pi
+
+ integer :: ib !band index 1:vis 2:nir
+ integer :: ip,ic,ig,kband !array indices for pft,column,grid
+ integer :: kfr !variable for layer radiation coming from
+ integer :: klay !variable for layer absorbing radiation
+ integer :: kto !variable for layer radiation is transmitted to
+ integer :: lev !do loop variable
+ integer :: nn !do loop variable
+ integer :: nsoilveg !number of pfts in gridcell with veg and cosz > 0
+ integer :: nstep !time step index
+ integer :: clev !canopy level for current pft
+
+ real(r8) :: albd_col(numrad) !surface reflection (direct) for column
+ real(r8) :: albi_col(numrad) !surface reflection (diffuse) for column
+ real(r8) :: hbot_lay(nlay) !average canopy bottom in layer
+ real(r8) :: chgt_lay(nlay) !average canopy height in layer
+ real(r8) :: csiz_lay(nlay) !average canopy size in layer
+ real(r8) :: cdcw_lay(nlay) !crown depth to crown width for layers
+ real(r8) :: omg_lay(nlay,numrad) !average omega for all three layer
+ real(r8) :: rho_lay(nlay,numrad) !average rho for all three layer
+ real(r8) :: tau_lay(nlay,numrad) !average tau for all three layer
+ real(r8) :: lsai_lay(nlay) !average lsai for each layer
+ real(r8) :: cosz_lay(nlay) !0.001 <= coszen <= 1.000
+ real(r8) :: cosd_lay(nlay) !0.001 <= coszen <= 1.000
+ real(r8) :: delta !variable for increment layer in loop
+ real(r8) :: dif !diffuse radiation transmitted
+ real(r8) :: dir !direct radiation transmitted
+ real(r8) :: fabd_col(numrad) !flux absorbed by veg per unit diffuse flux
+ real(r8) :: fabd_lay(nlay,numrad) !layer absorption for direct beam
+ real(r8) :: fabi_col(numrad) !flux absorbed by veg per unit diffuse flux
+ real(r8) :: fabi_lay(nlay,numrad) !layer absorption for diffuse beam
+ real(r8) :: fabs_lay(0:4,numrad) !layer absorption for all five layers
+ real(r8) :: fabs_leq(0:4,numrad) !layer absorption for all five layers
+ real(r8) :: A(6,6) !three-layer radiation transfer equation
+ !(EQ. 19, Yuan et al., 2014)
+ real(r8) :: B(6,2) !three-layer radiation transfer equation
+ !(EQ. 19, Yuan et al., 2014)
+ real(r8) :: X(6,2) !three-layer radiation transfer equation
+ !(EQ. 19, Yuan et al., 2014)
+ real(r8) :: fabsm !pft absorption for multiple reflections
+ real(r8) :: faid_lay(nlay) !layer diffused absorption for direct beam
+ real(r8) :: faid_p !pft absorption direct beam
+ real(r8) :: faii_lay(nlay) !layer diffused absorption for diffuse beam
+ real(r8) :: faii_p !pft absorption diffuse beam
+ real(r8) :: fc0(nlay) !canopy fraction for layers
+ real(r8) :: frid_lay(nlay) !layer reflection for direct beam
+ real(r8) :: frid_p !pft reflection direct beam
+ real(r8) :: frii_lay(nlay) !layer reflection for indirect beam
+ real(r8) :: ftdd_lay(nlay) !unscattered layer transmission for direct beam
+ real(r8) :: ftdi_lay(nlay) !unscattered layer transmission for indirect beam
+ real(r8) :: ftdd_lay_orig(nlay) !unscattered layer transmission for direct beam
+ !without lad/crown_shape calibration
+ real(r8) :: ftdi_lay_orig(nlay) !unscattered layer transmission for indirect beam
+ !without lad/crown_shape calibration
+ real(r8) :: psun_lay(nlay) !percent sunlit vegetation cover for layers
+ real(r8) :: fsun_id_lay(nlay) !frac of dif rad abs. by sunlit leaf incident dir
+ real(r8) :: fsun_ii_lay(nlay) !frac of dif rad abs. by sunlit leaf incident dif
+ real(r8) :: fsun_dd_lay(nlay) !frac of dif rad abs. by sunlit leaf incident downward dir
+ real(r8) :: fsun_dw_lay(nlay) !frac of dif rad abs. by sunlit leaf incident downward dif
+ real(r8) :: fsun_up_lay(nlay) !frac of dif rad abs. by sunlit leaf incident upward dif
+ real(r8) :: ftid_lay(nlay) !diffused layer transmission for direct beam
+ real(r8) :: ftii_lay(nlay) !diffused layer transmission for diffuse beam
+ real(r8) :: ftran !pft transmittance
+ real(r8) :: gee=0.5_r8 !Ross G factor geometric blocking
+ real(r8) :: gdir(ps:pe) !G factor considering LAD for incident direct radiation
+ real(r8) :: gdif(ps:pe) !G factor considering LAD for incident diffuse radiation
+ real(r8) :: gdir_lay(nlay) !G factor considering LAD for incident direct radiation
+ real(r8) :: gdif_lay(nlay) !G factor considering LAD for incident diffuse radiation
+ real(r8) :: fcad(ps:pe) !calibration factor for LAD for direct radiation
+ real(r8) :: fcai(ps:pe) !calibration factor for LAD for diffuse radiation
+ real(r8) :: fcad_lay(nlay) !calibration factor for LAD for direct radiation
+ real(r8) :: fcai_lay(nlay) !calibration factor for LAD for diffuse radiation
+ real(r8) :: pad !probability function for absorption after two scat
+ real(r8) :: pai !probability of absorption for diffuse incident beam
+ real(r8) :: pfc !contribution of current pft in layer
+ real(r8) :: probm !prob photon reflect diffusely from ground reach canopy
+ real(r8) :: ref(0:nlay+1,0:nlay+1) !radiation reflected between five layers
+ real(r8) :: fadd_lay(nlay,numrad) !layer absorbed flux in direct mode per unit direct flux
+ real(r8) :: shad_oa(nlay,nlay) !shadow overlaps (direct beam)
+ real(r8) :: shadow_d(nlay) !layer shadow for direct beam
+ real(r8) :: shadow_i(nlay) !layer shadow for diffuse beam
+ real(r8) :: sum_fabd(3) !sum of absorption for all pfts in grid (direct)
+ real(r8) :: sum_fabi(3) !sum of absorption for all pfts in grid (diffuse)
+ real(r8) :: sum_fadd(nlay) !sum of absorbed flux in direct mode per unit direct flux
+ real(r8) :: taud_lay(nlay) !direct transmission for a layer
+ real(r8) :: taui_lay(nlay) !diffuse transmission for a layer
+ real(r8) :: trd(0:nlay+1,0:nlay+1) !direct radiation transmitted between five layers
+ real(r8) :: tri(0:4,0:4) !diffuse radiation transmitted between five layers
+ real(r8) :: tt(0:4,0:4) !unscattered direct radiation available at layer
+ real(r8) :: wl !fraction of LAI+SAI that is LAI
+ real(r8) :: ws !fraction of LAI+SAI that is SAI
+ real(r8) :: zenith !zenith angle
+ real(r8) :: ftdd_col !unscattered column transmission for direct beam
+ real(r8) :: fsun_f !forward incident light sunlit leaf absorption fraction
+ real(r8) :: fsun_b !backward incident light sunlit leaf absorption fraction
+ real(r8) :: fsun_a !temp variable 0.5*(fsun_f+fsun_b)
+ real(r8) :: fsun_d !temp variable 0.5*(fsun_f-fsun_b)
+
+ real(r8) :: shadow_pd(ps:pe) !sky shadow area
+ real(r8) :: shadow_pi(ps:pe) !sky shadow area
+ real(r8) :: shadow_sky(ps:pe) !sky shadow area
+ real(r8) :: taud(ps:pe) !transmission to direct beam
+ real(r8) :: taui(ps:pe) !transmission to diffuse beam
+ real(r8) :: omega(ps:pe,numrad) !leaf/stem transmittance weighted by frac veg
+ real(r8) :: ftdi(ps:pe,numrad) !leaf/stem transmittance weighted by frac veg
+ real(r8) :: ftdd_orig(ps:pe,numrad) !leaf/stem transmittance weighted by frac veg
+ real(r8) :: ftdi_orig(ps:pe,numrad) !leaf/stem transmittance weighted by frac veg
+ real(r8) :: cosz(ps:pe) !0.001 <= coszen <= 1.000
+ real(r8) :: cosd(ps:pe) !0.001 <= coszen <= 1.000
+ logical :: soilveg(ps:pe) !true if pft over soil with veg and cosz > 0
+
+ real(r8) :: phi1(ps:pe), phi2(ps:pe)
+!-----------------------------------------------------------------------
+
+ ! 11/07/2018: calculate gee FUNCTION consider LAD
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ cdcw = 1.
+ cosz = coszen
+ zenith = acos(coszen)
+ cosz = cosz * sqrt(1 / (cdcw**2*sin(zenith)**2 + cos(zenith)**2))
+
+ cosd = cos(60._r8/180._r8*pi)
+ zenith = 60._r8/180._r8*pi
+ cosd = cosd * sqrt(1 / (cdcw**2*sin(zenith)**2 + cos(zenith)**2))
+
+ ! 11/07/2018: calculate gee FUNCTION consider LAD
+ gdir = phi1 + phi2*cosz
+ gdif = phi1 + phi2*cosd
+
+ nsoilveg = 0
+
+ fc0 = D0
+ omg_lay = D0; rho_lay = D0; tau_lay = D0
+ chgt_lay = D0; cdcw_lay = D0; hbot_lay = D0
+ csiz_lay = D0; lsai_lay = D0
+ cosz_lay = D0; cosd_lay = D0
+ gdir_lay = D0; gdif_lay = D0
+
+ DO ip = ps, pe
+ shadow_sky(ip) = D1
+
+ ! check elai and pft weight are non-zero
+ IF ( lsai(ip)>1.e-6_r8 .and. fcover(ip)>D0 ) THEN
+
+ soilveg(ip) = .true.
+ nsoilveg = nsoilveg + 1
+
+ clev = canlay(ip)
+ fc0(clev) = fc0(clev) + fcover(ip)
+
+ csiz_lay(clev) = csiz_lay(clev) + fcover(ip)*csiz(ip)
+ chgt_lay(clev) = chgt_lay(clev) + fcover(ip)*chgt(ip)
+ cdcw_lay(clev) = cdcw_lay(clev) + fcover(ip)*cdcw(ip)
+ lsai_lay(clev) = lsai_lay(clev) + fcover(ip)*lsai(ip)
+ cosz_lay(clev) = cosz_lay(clev) + fcover(ip)*cosz(ip)
+ cosd_lay(clev) = cosd_lay(clev) + fcover(ip)*cosd(ip)
+ gdir_lay(clev) = gdir_lay(clev) + fcover(ip)*gdir(ip)
+ gdif_lay(clev) = gdif_lay(clev) + fcover(ip)*gdif(ip)
+
+ ! set optical properties
+ DO ib = 1, numrad
+ omega(ip,ib) = rho(ip,ib) + tau(ip,ib)
+
+ ! sum of tau,rho and omega for pfts in a layer
+ tau_lay(clev,ib) = tau_lay(clev,ib) + fcover(ip)*(tau(ip,ib))
+ rho_lay(clev,ib) = rho_lay(clev,ib) + fcover(ip)*(rho(ip,ib))
+ omg_lay(clev,ib) = omg_lay(clev,ib) + fcover(ip)*(omega(ip,ib))
+
+ ENDDO ! ENDDO ib=1, numrad
+ ELSE
+ soilveg(ip) = .false.
+ ENDIF
+ ENDDO ! ENDDO ip
+
+!=============================================================
+! layer average of lsai,tau,rho,omega...
+!=============================================================
+
+ DO lev = 1, 3
+ IF (fc0(lev) > D0) THEN
+ csiz_lay(lev) = max(csiz_lay(lev)/fc0(lev),D0)
+ chgt_lay(lev) = max(chgt_lay(lev)/fc0(lev),D0)
+ hbot_lay(lev) = chgt_lay(lev) - csiz_lay(lev)
+ cdcw_lay(lev) = max(cdcw_lay(lev)/fc0(lev),D0)
+ lsai_lay(lev) = max(lsai_lay(lev)/fc0(lev),D0)
+ cosz_lay(lev) = max(cosz_lay(lev)/fc0(lev),D0)
+ cosd_lay(lev) = max(cosd_lay(lev)/fc0(lev),D0)
+ DO ib = 1, numrad
+ tau_lay(lev,ib) = max(tau_lay(lev,ib)/fc0(lev),D0)
+ rho_lay(lev,ib) = max(rho_lay(lev,ib)/fc0(lev),D0)
+ omg_lay(lev,ib) = max(omg_lay(lev,ib)/fc0(lev),D0)
+ ENDDO
+ gdir_lay(lev) = max(gdir_lay(lev)/fc0(lev),D0)
+ gdif_lay(lev) = max(gdif_lay(lev)/fc0(lev),D0)
+ ENDIF
+ ENDDO ! ENDDO ib
+
+!=============================================================
+! layer shadows
+!=============================================================
+
+ shadow_d = D0
+ shadow_i = D0
+ DO lev =1, 3
+ IF ( fc0(lev)>D0 .and. cosz_lay(lev)>D0 ) THEN
+ shadow_d(lev) = (D1 - exp(-D1*fc0(lev)/cosz_lay(lev))) &
+ / (D1 - fc0(lev)*exp(-D1/cosz_lay(lev)))
+ shadow_d(lev) = max(fc0(lev), shadow_d(lev))
+ shadow_i(lev) = (D1 - exp(-D1*fc0(lev)/cosd_lay(lev))) &
+ / (D1 - fc0(lev)*exp(-D1/cosd_lay(lev)))
+ shadow_i(lev) = max(fc0(lev), shadow_i(lev))
+ ENDIF
+ ENDDO
+
+!=============================================================
+! taud and ftdd for layers
+!=============================================================
+
+ taud_lay = D0; taui_lay = D0
+ ftdd_lay = D0; ftdi_lay = D0
+ fcad_lay = D1; fcai_lay = D1
+ ftdd_lay_orig = D0
+ ftdi_lay_orig = D0
+
+ DO lev = 1, 3
+ IF ( fc0(lev)>D0 .and. lsai_lay(lev)>D0 ) THEN
+
+ taud_lay(lev) = D3/D4*gee*fc0(lev)*lsai_lay(lev) &
+ / (cosz_lay(lev)*shadow_d(lev))
+ taui_lay(lev) = D3/D4*gee*fc0(lev)*lsai_lay(lev) &
+ / (cosd_lay(lev)*shadow_i(lev))
+
+ ! 11/07/2018: LAD calibration
+ ftdd_lay_orig(lev) = tee(DD1*taud_lay(lev))
+ ftdi_lay_orig(lev) = tee(DD1*taui_lay(lev))
+
+ ! 11/07/2018: gdir/gdif = FUNCTION(xl, cos)
+ ftdd_lay(lev) = tee(DD1*taud_lay(lev)/gee*gdir_lay(lev))
+ ftdi_lay(lev) = tee(DD1*taui_lay(lev)/gee*gdif_lay(lev))
+
+ ! calibration for chil
+ fcad_lay(lev) = (D1-ftdd_lay(lev)) / (D1-ftdd_lay_orig(lev))
+ fcai_lay(lev) = (D1-ftdi_lay(lev)) / (D1-ftdi_lay_orig(lev))
+
+ ENDIF
+ ENDDO
+
+
+!=============================================================
+! absorption fraction in sunlit leaves in diffuse radiation format
+! PART I
+!=============================================================
+
+ fsun_dd_lay(:) = D0
+ fsun_dw_lay(:) = D0
+ fsun_up_lay(:) = D0
+
+ DO lev = 1, 3
+ IF ( fc0(lev)>D0 .and. lsai_lay(lev)>D0 ) THEN
+
+ fsun_f = 0.5*(1. - tee(DD1*2.*taud_lay(lev))) &
+ / (1. - tee(DD1*taud_lay(lev)))
+
+ fsun_b = 2.*(tee(DD1*taud_lay(lev)) - exp(-2.*taud_lay(lev))) &
+ / (1. - tee(DD1*taud_lay(lev)))
+
+ fsun_a = 0.5*(fsun_f + fsun_b)
+ fsun_d = 0.5*(fsun_f - fsun_b)
+
+ fsun_dd_lay(lev) = fsun_f
+ fsun_dw_lay(lev) = fsun_a + 0.5*cosz_lay(lev)*fsun_d
+ fsun_up_lay(lev) = fsun_a - 0.5*cosz_lay(lev)*fsun_d
+ ENDIF
+ ENDDO
+
+!=============================================================
+! initialize local variables for layers
+!=============================================================
+
+ albd_col = D0; albi_col = D0
+ fabd_col = D0; fabd_lay = D0
+ fabi_col = D0; fabi_lay = D0
+ frid_lay = D0; frii_lay = D0
+ tt = D0
+
+!=============================================================
+! projection shadow overlapping fractions
+!=============================================================
+
+ zenith = acos(cosz_lay(3))
+ shad_oa(3,2) = fc0(3)*OverlapArea(csiz_lay(3),chgt_lay(3)-hbot_lay(2), zenith)
+ shad_oa(3,1) = fc0(3)*OverlapArea(csiz_lay(3),chgt_lay(3)-hbot_lay(1), zenith)
+ zenith = acos(cosz_lay(2))
+ shad_oa(2,1) = fc0(2)*OverlapArea(csiz_lay(2),chgt_lay(2)-hbot_lay(1), zenith)
+
+!=============================================================
+! unscattered direct sunlight available at each layer
+! 4:sky, 3:top 2:middle 1:bottom and 0:ground layer
+!=============================================================
+
+ ftdd_col = D0; tt = D0
+
+ tt(4,3) = shadow_d(3)
+ tt(4,3) = min(D1, max(D0, tt(4,3)))
+ tt(4,2) = shadow_d(2)*(D1-shadow_d(3)+shad_oa(3,2))
+ tt(4,2) = min(1-tt(4,3), max(D0, tt(4,2)))
+ tt(4,1) = shadow_d(1)*(D1-(shadow_d(2)-shad_oa(2,1)) &
+ - (shadow_d(3)-shad_oa(3,1)) &
+ + (shadow_d(2)-shad_oa(2,1))*(shadow_d(3)-shad_oa(3,2)))
+ tt(4,1) = min(1-tt(4,3)-tt(4,2), max(D0, tt(4,1)))
+
+ tt(4,0) = D1-(shadow_d(1)+shadow_d(2)+shadow_d(3) &
+ - (shadow_d(2)-shad_oa(2,1))*shadow_d(1) &
+ - (shadow_d(3)-shad_oa(3,2))*shadow_d(2) &
+ - (shadow_d(3)-shad_oa(3,1))*shadow_d(1) &
+ + (shadow_d(2)-shad_oa(2,1))*(shadow_d(3)-shad_oa(3,2))*shadow_d(1))
+ tt(4,0) = min(1-tt(4,3)-tt(4,2)-tt(4,1), max(D0, tt(4,0)))
+
+ IF (tt(4,0) < 0) THEN
+ print *, abs(tt(4,0))
+ ENDIF
+
+ ! direct sunlight passing through top canopy layer
+ IF (shadow_d(3) > 0) THEN
+ tt(3,2) = shadow_d(2)*(shadow_d(3)-shad_oa(3,2))
+ tt(3,2) = min(shadow_d(3), max(D0, tt(3,2)))
+ tt(3,1) = shadow_d(1)*(shadow_d(3)-shad_oa(3,1) &
+ - (shadow_d(3)-shad_oa(3,2))*(shadow_d(2)-shad_oa(2,1)))
+ tt(3,1) = min(shadow_d(3)-tt(3,2), max(D0, tt(3,1)))
+ tt(3,0) = shadow_d(3)-tt(3,2)-tt(3,1)
+
+ tt(3,2) = tt(3,2)*ftdd_lay(3)
+ tt(3,1) = tt(3,1)*ftdd_lay(3)
+ tt(3,0) = tt(3,0)*ftdd_lay(3)
+ ENDIF
+
+ ! direct sunlight passing through middle canopy layer
+ IF (shadow_d(2) > 0) THEN
+ tt(2,1) = shadow_d(1)*(shadow_d(2)-shad_oa(2,1))
+ tt(2,1) = min(shadow_d(2), max(D0, tt(2,1)))
+ tt(2,0) = shadow_d(2)-tt(2,1)
+
+ tt(2,1) = tt(2,1)*ftdd_lay(2)*(tt(4,2) + tt(3,2))/shadow_d(2)
+ tt(2,0) = tt(2,0)*ftdd_lay(2)*(tt(4,2) + tt(3,2))/shadow_d(2)
+ ENDIF
+
+ ! direct sunlight passing through third canopy layer
+ IF (shadow_d(1) > 0) THEN
+ tt(1,0) = ftdd_lay(1)*(tt(4,1) + tt(3,1) + tt(2,1))!*shadow_d(1)/shadow_d(1)
+ ENDIF
+
+!=============================================
+! Aggregate direct radiation to layers
+!=============================================
+
+ tt(4,3) = tt(4,3)
+ tt(3,2) = tt(4,2) + tt(3,2)
+ tt(2,1) = tt(4,1) + tt(3,1) + tt(2,1)
+ tt(1,0) = tt(4,0) + tt(3,0) + tt(2,0) + tt(1,0)
+ ftdd_col = tt(1,0)
+
+ tt(0:4,4) = D0; tt(0:3,3) = D0
+ tt(4:4,2) = D0; tt(0:2,2) = D0
+ tt(3:4,1) = D0; tt(0:1,1) = D0
+ tt(2:4,0) = D0; tt(0:0,0) = D0
+
+
+!=======================================
+! start radiation beam loop
+! ib=1:visible band 2:nir band
+!=======================================
+
+ DO ib = 1, numrad
+
+ !===============================
+ ! get pft level tau and ftdd
+ !===============================
+
+ ! 10/12/2017
+ ftdi(:,ib) = D1
+
+ DO ip = ps, pe
+
+ taud(ip) = D0
+ taui(ip) = D0
+ shadow_pd(ip) = D0
+ shadow_pi(ip) = D0
+
+ IF (soilveg(ip)) THEN
+ clev = canlay(ip)
+
+ !================================================
+ ! fractional contribution of current pft in layer
+ !================================================
+
+ pfc = min( fcover(ip)/fc0(clev), D1)
+ shadow_pd(ip) = pfc*shadow_d(clev)
+ shadow_pi(ip) = pfc*shadow_i(clev)
+
+ !=====================================
+ ! get taud,taui at pft level
+ !=====================================
+
+ taud(ip) = D3/D4*gee*fcover(ip)*(lsai(ip)) &
+ / (cosz(ip)*shadow_pd(ip))
+
+ taui(ip) = D3/D4*gee*fcover(ip)*(lsai(ip)) &
+ / (cosd(ip)*shadow_pi(ip))
+
+ !====================================
+ ! transmission at pft level
+ !====================================
+
+ ftdd_orig(ip,ib) = tee(DD1*taud(ip))
+ ftdi_orig(ip,ib) = tee(DD1*taui(ip))
+
+ ! 11/07/2018: gdir/gdif = FUNCTION(xl, cos)
+ ftdd(ip,ib) = tee(DD1*taud(ip)/gee*gdir(ip))
+ ftdi(ip,ib) = tee(DD1*taui(ip)/gee*gdif(ip))
+
+ ! calibration for chil
+ fcad(ip) = (D1-ftdd(ip,ib)) / (D1-ftdd_orig(ip,ib))
+ fcai(ip) = (D1-ftdi(ip,ib)) / (D1-ftdi_orig(ip,ib))
+
+ ENDIF ! ENDIF soilveg
+ ENDDO ! ENDDO ip
+
+ !===============================================================
+ ! absorption, reflection and transmittance for three canopy layer
+ ! using average optical properties of layers
+ ! subroutine CanopyRad calculates fluxes for unit input radiation
+ !===============================================================
+
+ ftid_lay=D0; ftii_lay=D1
+ frid_lay=D0; frii_lay=D0
+ faid_lay=D0; faii_lay=D0
+
+ DO lev = 1, 3
+ IF (shadow_d(lev) > D0) THEN
+ CALL CanopyRad(taud_lay(lev), taui_lay(lev), ftdd_lay_orig(lev),&
+ ftdi_lay_orig(lev), cosz_lay(lev), cosd_lay(lev), shadow_d(lev), &
+ shadow_i(lev), fc0(lev), omg_lay(lev,ib), lsai_lay(lev), &
+ tau_lay(lev,ib), rho_lay(lev,ib), ftid_lay(lev), &
+ ftii_lay(lev), frid_lay(lev), frii_lay(lev),&
+ faid_lay(lev), faii_lay(lev))
+ ENDIF
+ ENDDO ! ENDDO lev
+
+ ! 11/07/2018: calibration for LAD
+ ftid_lay(:) = fcad_lay(:)*ftid_lay(:)
+ ftii_lay(:) = fcai_lay(:)*(ftii_lay(:)-ftdi_lay_orig(:)) + ftdi_lay(:)
+ frid_lay(:) = fcad_lay(:)*frid_lay(:)
+ frii_lay(:) = fcai_lay(:)*frii_lay(:)
+ faid_lay(:) = fcad_lay(:)*faid_lay(:)
+ faii_lay(:) = fcai_lay(:)*faii_lay(:)
+
+ !=============================================
+ ! Calculate layer direct beam radiation absorbed
+ ! in the sunlit canopy as direct
+ !=============================================
+
+ fadd_lay(:,ib) = D0
+
+ DO lev = 1, nlay
+ IF ( fc0(lev)>D0 .and. lsai_lay(lev)>D0 ) THEN
+ fadd_lay(lev,ib) = tt(lev+1,lev) * &
+ (D1-ftdd_lay(lev)) * (D1-omg_lay(lev,ib))
+ ENDIF
+ ENDDO
+
+ A = D0; B = D0;
+ fabs_leq = D0
+
+ ! Calculate the coefficients matrix A
+ A(1,1) = 1.0; A(1,3) = -shadow_i(3)*ftii_lay(3) + shadow_i(3) - 1.0;
+ A(2,2) = 1.0; A(2,3) = -shadow_i(3)*frii_lay(3);
+ A(3,3) = 1.0; A(3,2) = -shadow_i(2)*frii_lay(2);
+ A(3,5) = -shadow_i(2)*ftii_lay(2) + shadow_i(2) - 1.0;
+
+ A(4,4) = 1.0; A(4,5) = -shadow_i(2)*frii_lay(2);
+ A(4,2) = -shadow_i(2)*ftii_lay(2) + shadow_i(2) - 1.0;
+
+ A(5,5) = 1.0; A(5,4) = -shadow_i(1)*frii_lay(1);
+ A(5,6) =(-shadow_i(1)*ftii_lay(1) + shadow_i(1) - 1.0) * albgri(ib);
+
+ A(6,6) = 1.0 - albgri(ib)*shadow_i(1)*frii_lay(1);
+ A(6,4) = -shadow_i(1)*ftii_lay(1) + shadow_i(1) - 1.0;
+
+ ! The constant vector B at right side
+ B(1,1) = tt(4,3)*frid_lay(3); B(1,2) = shadow_i(3)*frii_lay(3);
+ B(2,1) = tt(4,3)*ftid_lay(3); B(2,2) = shadow_i(3)*ftii_lay(3) - shadow_i(3) + 1.0;
+ B(3,1) = tt(3,2)*frid_lay(2); B(3,2) = 0.0;
+ B(4,1) = tt(3,2)*ftid_lay(2); B(4,2) = 0.0;
+
+ B(5,1) = tt(2,1)*frid_lay(1) &
+ + tt(1,0)*albgrd(ib)*(shadow_i(1)*ftii_lay(1) - shadow_i(1) + 1.0);
+ B(5,2) = 0.0;
+
+ B(6,1) = tt(2,1)*ftid_lay(1) + tt(1,0)*albgrd(ib)*shadow_i(1)*frii_lay(1);
+ B(6,2) = 0.0;
+
+ ! Get the resolution
+ CALL mGauss(A, B, X)
+
+ ! ====================================================
+ ! Set back to the absorption for each layer and albedo
+ ! ====================================================
+
+ ! Albedo
+ fabs_leq(4,:) = X(1,:)
+
+ ! Three layers' absorption for incident direct radiation
+ fabs_leq(3,1) = tt(4,3)*faid_lay(3) &
+ + X(3,1) *shadow_i(3)*faii_lay(3)
+ fabs_leq(2,1) = tt(3,2)*faid_lay(2) &
+ + (X(2,1) + X(5,1)) *shadow_i(2)*faii_lay(2)
+ fabs_leq(1,1) = tt(2,1)*faid_lay(1) &
+ + (X(4,1) + X(6,1)*albgri(ib) + tt(1,0)*albgrd(ib))*shadow_i(1)*faii_lay(1)
+
+ ! Ground absorption
+ fabs_leq(0,1) = tt(1,0)*(1.0 - albgrd(ib)) + X(6,1)*(1.0 - albgri(ib))
+
+
+ ! Three layers' absorption for incident diffuse radiation
+ fabs_leq(3,2) = (1. + X(3,2)) *shadow_i(3)*faii_lay(3)
+ fabs_leq(2,2) = (X(2,2) + X(5,2)) *shadow_i(2)*faii_lay(2)
+ fabs_leq(1,2) = (X(4,2) + X(6,2)*albgri(ib)) *shadow_i(1)*faii_lay(1)
+
+ ! Ground absorption
+ fabs_leq(0,2) = X(6,2) * (1.0 - albgri(ib))
+
+
+ ! IF everything is ok, substitute fabs_lay for fabs_leq
+ ! and delete the following line and the variables defined
+ ! but not used anymore
+ fabs_lay = fabs_leq
+
+ ! set column absorption and reflection
+ fabd_lay(1:3,ib) = fabs_lay(1:3,1)
+ fabi_lay(1:3,ib) = fabs_lay(1:3,2)
+ fabd_col(ib) = fabs_lay(1,1) + fabs_lay(2,1) + fabs_lay(3,1)
+ fabi_col(ib) = fabs_lay(1,2) + fabs_lay(2,2) + fabs_lay(3,2)
+ albd_col(ib) = fabs_lay(4,1)
+ albi_col(ib) = fabs_lay(4,2)
+
+ ! calculation for sunlit fraction and sunlit absorption for each layer
+ IF (ib == 1) THEN !visible band only
+
+ psun_lay(:) = D0
+ fsun_id_lay(:) = D0
+ fsun_ii_lay(:) = D0
+
+ ! - layer 3 -
+ IF ( fc0(3)>D0 .and. lsai_lay(3)>D0 ) THEN
+ ! sunlit fraction for layers
+ psun_lay(3) = tt(4,3)/shadow_d(3)
+ ! absorption fraction in sunlit leaves in diffuse radiation format
+ ! PART II
+ fsun_id_lay(3) = (psun_lay(3)*fsun_dd_lay(3) + X(3,1)*fsun_up_lay(3)) &
+ / (psun_lay(3) + X(3,1))
+ fsun_ii_lay(3) = (1.*fsun_dw_lay(3) + X(3,2)*fsun_up_lay(3)) &
+ / (1. + X(3,2))
+ ENDIF
+
+ ! - layer 2 -
+ IF ( fc0(2)>D0 .and. lsai_lay(2)>D0 ) THEN
+ ! sunlit fraction for layers
+ psun_lay(2) = tt(3,2)/shadow_d(2)
+ ! absorption fraction in sunlit leaves in diffuse radiation format
+ ! PART II
+ fsun_id_lay(2) = (psun_lay(2)*fsun_dd_lay(2) + X(2,1)*fsun_dw_lay(2) &
+ + X(5,1)*fsun_up_lay(2)) &
+ / (psun_lay(2) + X(2,1) + X(5,1))
+ fsun_ii_lay(2) = (X(2,2)*fsun_dw_lay(2) + X(5,2)*fsun_up_lay(2)) &
+ / (X(2,2) + X(5,2))
+ ENDIF
+
+ ! - layer 1 -
+ IF ( fc0(1)>D0 .and. lsai_lay(1)>D0 ) THEN
+ ! sunlit fraction for layers
+ psun_lay(1) = tt(2,1)/shadow_d(1)
+ ! absorption fraction in sunlit leaves in diffuse radiation format
+ ! PART II
+ fsun_id_lay(1) = (psun_lay(1)*fsun_dd_lay(1) + X(4,1)*fsun_dw_lay(1) &
+ + (X(6,1)*albgri(ib) + tt(1,0)*albgrd(ib))*fsun_up_lay(1)) &
+ / (psun_lay(1) + X(4,1) + X(6,1)*albgri(ib) + tt(1,0)*albgrd(ib))
+ fsun_ii_lay(1) = (X(4,2)*fsun_dw_lay(1) + X(6,2)*albgri(ib)*fsun_up_lay(1)) &
+ / (X(4,2) + X(6,2)*albgri(ib))
+ ENDIF
+ ENDIF
+
+ ! balance check
+ IF (abs(fabd_col(ib)+albd_col(ib)+fabs_lay(0,1)-1) > 1e-6) THEN
+ print *, "Imbalance kband=1"
+ print *, fabd_col(ib)+albd_col(ib)+fabs_lay(0,1)-1
+ ENDIF
+ IF (abs(fabi_col(ib)+albi_col(ib)+fabs_lay(0,2)-1) > 1e-6) THEN
+ print *, "Imbalance kband=2"
+ print *, fabi_col(ib)+albi_col(ib)+fabs_lay(0,2)-1
+ ENDIF
+
+ !====================================================
+ ! Calculate individual PFT absorption
+ !====================================================
+
+ sum_fabd = D0
+ sum_fabi = D0
+ sum_fadd = D0
+
+ DO ip = ps, pe
+ clev = canlay(ip)
+ IF (clev == D0) CYCLE
+ IF ( shadow_d(clev)>D0 .and. soilveg(ip) ) THEN
+
+ !=================================================
+ ! fractional contribution of current pft in layer
+ !=================================================
+
+ pfc = min( fcover(ip)/fc0(clev), D1)
+
+ !=========================================
+ ! shadow contribution from ground to sky
+ !=========================================
+
+ shadow_sky(ip) = shadow_pi(ip)
+
+ !=======================================================
+ ! absorption, reflection and transmittance fluxes for
+ ! unit incident radiation over pft.
+ !=======================================================
+
+ CALL CanopyRad(taud(ip), taui(ip), ftdd_orig(ip,ib), ftdi_orig(ip,ib), &
+ cosz(ip),cosd(ip), shadow_pd(ip), shadow_pi(ip), fcover(ip),&
+ omega(ip,ib), lsai(ip), tau(ip,ib),&
+ rho(ip,ib), ftid(ip,ib), ftii(ip,ib), albd(ip,ib),&
+ albi(ip,ib), faid_p, faii_p)
+
+ ! calibration for LAD
+ ! 11/07/2018: calibration for LAD
+ ftid(ip,ib) = fcad(ip)*ftid(ip,ib)
+ ftii(ip,ib) = fcai(ip)*(ftii(ip,ib)-ftdi_orig(ip,ib)) + ftdi(ip,ib)
+ albd(ip,ib) = fcad(ip)*albd(ip,ib)
+ albi(ip,ib) = fcai(ip)*albi(ip,ib)
+ faid_p = fcad(ip)*faid_p
+ faii_p = fcai(ip)*faii_p
+
+ ! absorptions after multiple reflections for each pft
+ probm = albi(ip,ib)*shadow_sky(ip)*albgri(ib)
+ ftran = (D1-shadow_pd(ip)+shadow_pd(ip)*ftdd(ip,ib))*albgrd(ib) &
+ + shadow_pd(ip)*ftid(ip,ib)*albgri(ib)
+ fabsm = ftran*faii_p*shadow_sky(ip)/(D1-probm)
+ fabd(ip,ib) = shadow_pd(ip)*faid_p + fabsm
+
+ probm = albi(ip,ib)*shadow_sky(ip)*albgri(ib)
+ ftran = D1-shadow_pi(ip)*(D1 -ftii(ip,ib))
+ fabsm = ftran*albgri(ib)*faii_p*shadow_sky(ip)/(D1-probm)
+ fabi(ip,ib) = shadow_pi(ip)*faii_p + fabsm
+
+ ! sum of pft absorptions in column
+ sum_fabd(clev) = sum_fabd(clev) + fabd(ip,ib)
+ sum_fabi(clev) = sum_fabi(clev) + fabi(ip,ib)
+
+ ! pft absorption in sunlit as direct beam
+ fadd(ip,ib) = shadow_pd(ip) * (D1-ftdd(ip,ib)) * (D1-omega(ip,ib))
+
+ ! sum of pft absorption in sunlit as direct beam
+ sum_fadd(clev) = sum_fadd(clev) + fadd(ip,ib)
+
+ ENDIF ! ENDIF shadow & soilveg
+ ENDDO ! ENDDO ip
+
+ DO ip = ps, pe
+ clev = canlay(ip)
+
+ !===========================================================
+ ! adjust pft absorption for total column absorption per
+ ! unit column area
+ !===========================================================
+
+ IF (soilveg(ip)) THEN
+ fabd(ip,ib) = fabd(ip,ib)*fabd_lay(clev,ib) &
+ / sum_fabd(clev)/fcover(ip)
+ fabi(ip,ib) = fabi(ip,ib)*fabi_lay(clev,ib) &
+ / sum_fabi(clev)/fcover(ip)
+
+ fadd(ip,ib) = fadd(ip,ib)*fadd_lay(clev,ib) &
+ / sum_fadd(clev)/fcover(ip)
+
+ fadd(ip,ib) = min(fabd(ip,ib), fadd(ip,ib))
+
+ psun(ip) = psun_lay(clev)
+ fsun_id(ip) = fsun_id_lay(clev)
+ fsun_ii(ip) = fsun_ii_lay(clev)
+
+ ELSE
+ fabd(ip,ib) = D0
+ fabi(ip,ib) = D0
+ fadd(ip,ib) = D0
+
+ psun(ip) = D0
+ fsun_id(ip) = D0
+ fsun_ii(ip) = D0
+ ENDIF
+
+ ! column albedo is assigned to each pft in column
+ ! Added by Yuan, 06/03/2012
+ albd(ip,ib) = albd_col(ib)
+ albi(ip,ib) = albi_col(ib)
+
+ ! adjust ftdd and ftii for multi reflections between layers
+
+! 03/06/2020, yuan: NOTE! there is no physical mean of ftdd,
+! ftid, ftii anymore. they are the same for each PFT can only
+! be used to calculate the ground absorption.
+ ftdd(ip,ib) = ftdd_col
+ ftid(ip,ib) = (D1-albd(ip,ib)-fabd_col(ib)-&
+ ftdd(ip,ib)*(D1-albgrd(ib))) /(D1-albgri(ib))
+ ftii(ip,ib) = (D1-albi(ip,ib)-fabi_col(ib))/(D1-albgri(ib))
+
+ !ftdd(ip,ib) = min(max(ftdd(ip,ib),D0),D1)
+ !ftii(ip,ib) = min(max(ftii(ip,ib),D0),D1)
+ !ftid(ip,ib) = min(max(ftid(ip,ib),D0),D1)
+
+ ! check energy balance
+ !fabd(ip,ib) = D1 - albd(ip,ib) &
+ ! - ftdd(ip,ib)*(D1-albgrd(ib)) &
+ ! - ftid(ip,ib)*(D1-albgri(ib))
+ !fabi(ip,ib) = D1 - albi(ip,ib) &
+ ! - ftii(ip,ib)*(D1-albgri(ib))
+
+ ENDDO ! ENDDO ip
+ ENDDO !ENDDO ib
+
+ ! set parameters for longwave calculation
+ fshade(:) = shadow_pi(:)
+ thermk(:) = ftdi(:,1)
+
+ END SUBROUTINE ThreeDCanopy
+
+!-----------------------------------------------------------------------
+! FUNCTION tee
+!-----------------------------------------------------------------------
+
+ real(selected_real_kind(12)) FUNCTION tee(tau)
+
+ IMPLICIT NONE
+
+ real(r16), parameter :: DDH = 0.50_r16 !128-bit accuracy real
+ real(r16), parameter :: DD1 = 1.0_r16 !128-bit accuracy real
+ real(r16), parameter :: DD2 = 2.0_r16 !128-bit accuracy real
+ real(r16) :: tau ! transmittance
+
+ tee = DDH*(DD1/tau/tau-(DD1/tau/tau+DD2/tau)*exp(-DD2*tau))
+
+ END FUNCTION tee
+
+!-----------------------------------------------------------------------
+! FUNCTION overlapArea
+!-----------------------------------------------------------------------
+
+ real(selected_real_kind(12)) FUNCTION OverlapArea(radius, hgt, zenith)
+
+ IMPLICIT NONE
+
+ real(r8), parameter :: rpi = 3.14159265358979323846_R8 !pi
+ real(r8), parameter :: D0 = 0.0_r8 !128-bit accuracy real
+ real(r8), parameter :: D1 = 1.0_r8 !128-bit accuracy real
+
+ real(r8) :: radius !radius of bus
+ real(r8) :: hgt !height of canopy
+ real(r8) :: zenith !zenith angle
+ real(r8) :: cost !cosine of angle
+ real(r8) :: theta !angle
+
+ IF (radius == D0) THEN
+ OverlapArea= D0
+ RETURN
+ ENDIF
+ cost = hgt*tan(zenith)/radius/(D1+D1/cos(zenith))
+ IF (cost >= 1) THEN
+ OverlapArea= D0
+ RETURN
+ ENDIF
+ theta = acos(cost)
+ OverlapArea = (theta-cost*sin(theta))*(D1+D1/cos(zenith))/rpi
+ RETURN
+ END FUNCTION OverlapArea
+
+!-----------------------------------------------------------------------
+! FUNCTION to calculate scattering, absorption, reflection and
+! transmittance for unit input radiation
+!-----------------------------------------------------------------------
+
+ SUBROUTINE CanopyRad(tau_d, tau_i, ftdd, ftdi, cosz, cosd, &
+ shadow_d, shadow_i, fc, omg, lsai, tau_p, rho_p, &
+ ftid, ftii, frid, frii, faid, faii)
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8) :: cosz !0.001 <= coszen <= 1.000
+ real(r8) :: cosd !0.001 <= coszen <= 1.000
+ real(r8) :: faid !direct absorption
+ real(r8) :: faii !diffuse absorption
+ real(r8) :: fc !fraction of grid covered with canopy
+ real(r8) :: frid !direct reflectance
+ real(r8) :: frii !diffuse reflectance
+ real(r8) :: frio !diffuse reflectance
+ real(r8) :: ftdd !down direct flux below veg per unit dir flx
+ real(r8) :: ftdi !down direct flux below veg per unit dif flux
+ real(r8) :: ftid !direct transmittance
+ real(r8) :: ftii !diffuse transmittance
+ real(r8) :: omg !frac of intercepted rad that is scattered
+ real(r8) :: rho_p !leaf/stem reflectance weighted by fract of LAI and SAI
+ real(r8) :: shadow_d !canopy shadow for direct solar
+ real(r8) :: shadow_i !canopy shadow for diffuse solar
+ real(r8) :: tau_d !radial optical depth for direct beam
+ real(r8) :: tau_i !radial optical depth for indirect beam
+ real(r8) :: tau_p !leaf/stem transmission weighted by frac of LAI & SAI
+ real(r8) :: lsai !elai+esai
+
+ ! output variables
+ real(r8) :: phi_dif_d !difference of rad scattered forward-backward per direct beam
+ real(r8) :: phi_dif_i !difference of rad scattered forward-backward per direct beam
+ real(r8) :: phi_tot_d !total rad scattered in all direction per direct beam
+ real(r8) :: phi_tot_i !total rad scattered in all direction per diffuse beam
+ real(r8) :: phi_tot_o !total rad scattered in all direction per direct beam
+ real(r8) :: phi_dif_o !total rad scattered in all direction per diffuse beam
+ real(r8) :: pa2 !total rad scattered in all direction per direct beam
+
+!-------------------------- Local Variables ----------------------------
+ logical :: runmode = .true.
+ real(r8) :: tau
+ real(r8) :: muv !forward frac of 3D scat rad in all direction for diffuse
+ real(r8) :: ac !forward frac of 3D scat rad in all direction for diffuse
+ real(r8) :: ald !forward frac of 3D scat rad in all direction for diffuse
+ real(r8) :: ali !forward frac of 3D scat rad in all direction for diffuse
+
+ real(r8) :: wb !EQ. (2.14), Dickinson 1983, omega*beta
+ real(r8) :: alpha !EQ. (2.14), Dickinson 1983, alpha
+ real(r8) :: nd !EQ. (4), Appendix 1, Yuan, dissertation
+ real(r8) :: ni !EQ. (4), Appendix 1, Yuan, dissertation
+ real(r8) :: gee=0.5_r8 !Ross factor geometric blocking
+
+ real(r8) , parameter :: D0 = 0.0_r8 !64-bit real number
+ real(r8) , parameter :: D1 = 1.0_r8 !64-bit real number
+ real(r8) , parameter :: D2 = 2.0_r8 !64-bit real number
+ real(r8) , parameter :: D3 = 3.0_r8 !64-bit real number
+ real(r8) , parameter :: D4 = 4.0_r8 !64-bit real number
+ real(r8) , parameter :: D6 = 6.0_r8 !64-bit real number
+ real(r8) , parameter :: DH = 0.5_r8 !64-bit real number
+ real(r16), parameter :: DD1 = 1.0_r16 !128-bit real number
+
+ real(r8) , parameter :: pi = 3.14159265358979323846_R8 !pi
+!-----------------------------------------------------------------------
+
+ tau = D3/D4*gee*lsai
+
+ CALL phi(runmode, tau_d, omg, tau_p, rho_p, phi_tot_d, phi_dif_d, pa2)
+ CALL phi(runmode, tau_i, omg, tau_p, rho_p, phi_tot_i, phi_dif_i, pa2)
+ CALL phi(runmode, tau , omg, tau_p, rho_p, phi_tot_o, phi_dif_o, pa2)
+
+ IF (runmode) THEN
+ ! NOTE: modified
+ frio = DH*(phi_tot_o - DH*phi_dif_o)
+ frio = max(min(frio,D1),D0)
+
+ muv = D3*( D1 - sqrt(D1-sqrt(D3)*fc/(D2*pi)) ) + &
+ D3*( D1 - sqrt(D1-sqrt(D3)*fc/(D6*pi)) )
+
+ wb = D2/D3*rho_p + D1/D3*tau_p
+ alpha = sqrt(D1-omg) * sqrt(D1-omg+D2*wb)
+ nd = (D1 + D2*alpha) / (D1 + D2*alpha*cosz)
+ ni = (D1 + D2*alpha) / (D1 + D2*alpha*cosd)
+
+ ac = phi_tot_o * muv * (D1-tee(DD1*tau)) * (D1-omg) / (D1-omg*pa2)
+ ald = (nd-D1) * frio * fc * (D1/shadow_d - cosz/fc)
+ ali = (ni-D1) * frio * fc * (D1/shadow_i - cosd/fc)
+ ENDIF
+
+!-----------------------------------------------------------------------
+!frac indirect downward rad through canopy for black soil & direct solar
+!-----------------------------------------------------------------------
+ frid = DH*(phi_tot_d - DH*cosz*phi_dif_d)
+ frii = DH*(phi_tot_i - DH*cosd*phi_dif_i)
+
+ IF (runmode) THEN
+ frid = frid + ald - DH*ac
+ frii = frii + ali - DH*ac
+ ENDIF
+
+ frid = max(min(frid,D1),D0)
+ frii = max(min(frii,D1),D0)
+
+!---------------------------------------------------------------------
+!downward diffuse fraction from direct and diffuse sun
+!---------------------------------------------------------------------
+ ftid = DH*(phi_tot_d + DH*cosz*phi_dif_d)
+ ftii = DH*(phi_tot_i + DH*cosd*phi_dif_i) + ftdi
+
+ IF (runmode) THEN
+ ftid = ftid - DH*ald - DH*ac
+ ftii = ftii - DH*ali - DH*ac
+ ENDIF
+
+ ftid = max(min(ftid,D1),D0)
+ ftii = max(min(ftii,D1),D0)
+
+!---------------------------------------------------------------------
+! canopy absorption for direct or diffuse beams
+!---------------------------------------------------------------------
+ IF (.not. runmode) THEN
+ faid = D1 - ftdd - phi_tot_d
+ faii = D1 - ftdi - phi_tot_i
+ ELSE
+ faid = D1 - ftdd - frid - ftid
+ faii = D1 - frii - ftii
+ ENDIF
+
+ faid = max(min(faid,D1),D0)
+ faii = max(min(faii,D1),D0)
+
+ IF (shadow_d == D0) THEN
+ ! NOTE: corrected from D1 -> D0
+ ftid = D0
+ frid = D0
+ faid = D0
+ ENDIF
+ IF (shadow_i == D0) THEN
+ ftii = D1
+ frii = D0
+ faii = D0
+ ENDIF
+
+ END SUBROUTINE CanopyRad
+
+
+ SUBROUTINE phi(runmode, tau, omg, tau_p, rho_p, phi_tot, phi_dif, pa2)
+
+ IMPLICIT NONE
+
+ ! input variables
+ logical :: runmode
+ real(r8) :: omg !frac of intercepted rad that is scattered
+ real(r8) :: rho_p !leaf/stem reflectance weighted by frac of LAI and SAI
+ real(r8) :: tau !radial optical depth for direct beam
+ real(r8) :: tau_p !leaf/stem transmission weighted by frac of LAI & SAI
+
+ ! output variables
+ real(r8) :: phi_dif !difference of rad scattered forward-backward
+ real(r8) :: phi_tot !total rad scattered in all direction
+ real(r8) :: pa2 !total rad scattered in all direction
+
+ ! local variables
+ real(r8) :: pac !probability of absorption after two scatterings
+ real(r8) :: phi_1b !backward single scattered radiation
+ real(r8) :: phi_1f !forward single scattered radiation
+ real(r8) :: phi_2a !average second-order scattered radiation
+ real(r8) :: phi_2b !backward second-order scattered radiation
+ real(r8) :: phi_2f !forward second-order scattered radiation
+ real(r8) :: phi_mb !backward multiple scattered radiation
+ real(r8) :: phi_mf !forward multiple scattered radiation
+ real(r8) :: phi_tb !backward frac of 3D scat rad in all direction
+ real(r8) :: phi_tf !forward frac of 3D scat rad in all direction
+ real(r8) :: aa,bb !temporary constants
+
+ real(r8) , parameter :: D0 = 0.0_r8 !64-bit real number
+ real(r8) , parameter :: D1 = 1.0_r8 !64-bit real number
+
+ real(r16), parameter :: DD1 = 1.0_r16 !128-bit real number
+ real(r16), parameter :: DD2 = 2.0_r16 !128-bit real number
+ real(r16), parameter :: DD3 = 3.0_r16 !128-bit real number
+ real(r16), parameter :: DD4 = 4.0_r16 !128-bit real number
+ real(r16), parameter :: DD9 = 9.0_r16 !128-bit real number
+ real(r16), parameter :: DD10 = 10.0_r16 !128-bit real number
+ real(r16), parameter :: DDH = 0.5_r16 !128-bit real number
+
+!----------------------------------------------------------------------
+! single scattering terms for sphere with overlap corrections to path
+! for direct and diffuse beams
+!----------------------------------------------------------------------
+
+ ! forward first order normalized scattering
+ phi_1f = (DD1/tau/tau - (DD1/tau/tau + DD2/tau + DD2)*exp(-DD2*tau))
+
+ ! backward first order normalized scattering
+ phi_1b = DDH*(DD1 - tee(DD2*tau))
+
+!----------------------------------------------------------------------
+! sphere double scattering terms (RED 2008 Eqs. 19,20)
+!----------------------------------------------------------------------
+
+ IF (.not. runmode) THEN
+
+ ! forward double scattering
+ phi_2f = DDH*(DD4*phi_1f/DD3 + tee(DD2*tau) + tee(DD4*tau)/DD9 - &
+ DD10*tee(DD1*tau)/DD9)
+
+ ! backward double scattering
+ phi_2b = DDH*(DD1/DD3 - tee(DD2*tau) + DD2*tee(DD3*tau)/DD3)
+
+ ELSE
+ ! fitting FUNCTION for second order scattering
+ aa = 0.70_r8
+ bb = 1.74_r8
+
+ phi_2b = aa*( DD1/(bb+DD1) -DD1/(bb-D1)*tee(DD2*tau) + &
+ DD2/(bb+DD1)/(bb-DD1)*tee((DD1+bb)*tau) )
+
+ phi_2f = aa*( DD2*bb/(bb*bb-DD1)*phi_1f - &
+ (DD1/(bb+DD1)/(bb+DD1) + DD1/(bb-DD1)/(bb-DD1))*tee(DD1*tau) + &
+ DD1/(bb-DD1)/(bb-DD1)*tee(DD1*tau*bb) + &
+ DD1/(bb+DD1)/(bb+DD1)*tee(DD1*(bb+DD2)*tau) )
+ ENDIF
+
+ ! second order average scattering
+ phi_2a = DDH*(phi_2b + phi_2f)
+
+!----------------------------------------------------------------------
+! probability of absorption after two scattering
+!----------------------------------------------------------------------
+
+ ! probability of absorption for diffuse beam
+ ! corrected probability of absorption for direct beam
+ pac = DD1-phi_2a / &
+ (DD1 - tee(DD1*tau) - (rho_p*phi_1b + tau_p*phi_1f)/(tau_p+rho_p))
+
+ pac = max(min(pac,D1),D0)
+ pa2 = pac
+
+!----------------------------------------------------------------------
+!third order and higher order scatterings
+!----------------------------------------------------------------------
+
+ phi_mf = phi_2f + omg*pac*phi_2a/(DD1-omg*pac)
+ phi_mb = phi_2b + omg*pac*phi_2a/(DD1-omg*pac)
+
+!----------------------------------------------------------------------
+! total sphere scattering,forward,backward, avg & diff for direct beam
+!----------------------------------------------------------------------
+
+ phi_tf = tau_p*phi_1f + DDH*omg*omg*phi_mf
+ phi_tb = rho_p*phi_1b + DDH*omg*omg*phi_mb
+
+ phi_tot = phi_tf + phi_tb
+ phi_dif = phi_tf - phi_tb
+
+ END SUBROUTINE phi
+
+ SUBROUTINE mGauss(A, B, X)
+
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: A(6,6)
+ real(r8), intent(inout) :: B(6,2)
+ real(r8), intent(out) :: X(6,2)
+
+ integer :: i, j
+ integer :: nstep(5) = (/0, 2, 1, 2, 1/)
+
+ real(r8) :: f
+
+ ! Elimination
+ DO i = 1, 5
+ DO j = i+1, i+nstep(i)
+ IF (abs(A(i,i)) < 1.e-10) THEN
+ print *, "Error in Gauss's solution"
+ RETURN
+ ENDIF
+ f = - A(j,i)/A(i,i)
+ A(j,:) = A(j,:) + f*A(i,:)
+ B(j,:) = B(j,:) + f*B(i,:)
+ ENDDO
+ ENDDO
+
+ ! Back substitution
+ X(6,:) = B(6,:)/A(6,6)
+ DO i = 5, 1, -1
+ X(i,1) = (B(i,1) - sum(A(i,i+1:6)*X(i+1:6,1))) / A(i,i)
+ X(i,2) = (B(i,2) - sum(A(i,i+1:6)*X(i+1:6,2))) / A(i,i)
+ ENDDO
+
+ END SUBROUTINE mGauss
+
+END MODULE MOD_3DCanopyRadiation
+! --------- EOP ----------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Aerosol.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Aerosol.F90
new file mode 100644
index 0000000000..3f943a1504
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Aerosol.F90
@@ -0,0 +1,434 @@
+#include
+
+MODULE MOD_Aerosol
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SpatialMapping
+ USE MOD_Vars_Global, only: maxsnl
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: AerosolMasses
+ PUBLIC :: AerosolFluxes
+ PUBLIC :: AerosolDepInit
+ PUBLIC :: AerosolDepReadin
+
+! PUBLIC DATA MEMBERS:
+!-----------------------------------------------------------------------
+
+ logical, parameter :: use_extrasnowlayers = .false.
+ real(r8), parameter :: snw_rds_min = 54.526_r8 ! minimum allowed snow effective radius
+ ! (also "fresh snow" value) [microns]
+ real(r8), parameter :: fresh_snw_rds_max = 204.526_r8 ! maximum warm fresh snow effective radius
+
+ character(len=256) :: file_aerosol
+
+ type(grid_type) :: grid_aerosol
+ type(block_data_real8_2d) :: f_aerdep
+ type(spatial_mapping_type) :: mg2p_aerdep
+
+ integer, parameter :: start_year = 1849
+ integer, parameter :: end_year = 2001
+
+ integer :: month_p
+
+CONTAINS
+
+ SUBROUTINE AerosolMasses( dtime ,snl ,do_capsnow ,&
+ h2osno_ice ,h2osno_liq ,qflx_snwcp_ice ,snw_rds ,&
+
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 )
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate column-integrated aerosol masses, and
+! mass concentrations for radiative calculations and output
+! (based on new snow level state, after SnowFilter is rebuilt.
+! NEEDS TO BE AFTER SnowFiler is rebuilt in Hydrology2, otherwise there
+! can be zero snow layers but an active column in filter)
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ ! !ARGUMENTS:
+ !
+ real(r8),intent(in) :: dtime ! seconds in a time step [second]
+ integer, intent(in) :: snl ! number of snow layers
+
+ logical, intent(in) :: do_capsnow ! true => do snow capping
+ real(r8), intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice lens (kg/m2)
+ real(r8), intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water (kg/m2)
+ real(r8), intent(in) :: qflx_snwcp_ice ! excess snowfall due to snow capping (mm H2O /s)
+
+ real(r8), intent(inout) :: snw_rds ( maxsnl+1:0 ) ! effective snow grain radius
+ ! [microns, m^-6]
+
+ real(r8), intent(inout) :: mss_bcpho ( maxsnl+1:0 ) ! mass of hydrophobic BC in snow [kg]
+ real(r8), intent(inout) :: mss_bcphi ( maxsnl+1:0 ) ! mass of hydrophillic BC in snow [kg]
+ real(r8), intent(inout) :: mss_ocpho ( maxsnl+1:0 ) ! mass of hydrophobic OC in snow [kg]
+ real(r8), intent(inout) :: mss_ocphi ( maxsnl+1:0 ) ! mass of hydrophillic OC in snow [kg]
+ real(r8), intent(inout) :: mss_dst1 ( maxsnl+1:0 ) ! mass of dust species 1 in snow [kg]
+ real(r8), intent(inout) :: mss_dst2 ( maxsnl+1:0 ) ! mass of dust species 2 in snow [kg]
+ real(r8), intent(inout) :: mss_dst3 ( maxsnl+1:0 ) ! mass of dust species 3 in snow [kg]
+ real(r8), intent(inout) :: mss_dst4 ( maxsnl+1:0 ) ! mass of dust species 4 in snow [kg]
+
+ real(r8), intent(out) :: mss_cnc_bcphi ( maxsnl+1:0 ) ! mass concentration of BC 1 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_bcpho ( maxsnl+1:0 ) ! mass concentration of BC 2 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_ocphi ( maxsnl+1:0 ) ! mass concentration of OC 1 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_ocpho ( maxsnl+1:0 ) ! mass concentration of OC 2 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_dst1 ( maxsnl+1:0 ) ! mass concentration of dust 1 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_dst2 ( maxsnl+1:0 ) ! mass concentration of dust 2 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_dst3 ( maxsnl+1:0 ) ! mass concentration of dust 3 [kg/kg]
+ real(r8), intent(out) :: mss_cnc_dst4 ( maxsnl+1:0 ) ! mass concentration of dust 4 [kg/kg]
+
+ ! !LOCAL VARIABLES:
+ integer :: c,j ! indices
+ real(r8) :: snowmass ! liquid+ice snow mass in a layer [kg/m2]
+ real(r8) :: snowcap_scl_fct ! temporary factor used to correct for snow capping
+
+ !-----------------------------------------------------------------------
+
+ DO j = maxsnl+1, 0
+
+ ! layer mass of snow:
+ snowmass = h2osno_ice(j) + h2osno_liq(j)
+
+ IF (.not. use_extrasnowlayers) THEN
+ ! Correct the top layer aerosol mass to account for snow capping.
+ ! This approach conserves the aerosol mass concentration
+ ! (but not the aerosol mass) when snow-capping is invoked
+
+ IF (j == snl+1) THEN
+ IF (do_capsnow) THEN
+
+ snowcap_scl_fct = snowmass / (snowmass + (qflx_snwcp_ice*dtime))
+
+ mss_bcpho(j) = mss_bcpho(j)*snowcap_scl_fct
+ mss_bcphi(j) = mss_bcphi(j)*snowcap_scl_fct
+ mss_ocpho(j) = mss_ocpho(j)*snowcap_scl_fct
+ mss_ocphi(j) = mss_ocphi(j)*snowcap_scl_fct
+
+ mss_dst1(j) = mss_dst1(j)*snowcap_scl_fct
+ mss_dst2(j) = mss_dst2(j)*snowcap_scl_fct
+ mss_dst3(j) = mss_dst3(j)*snowcap_scl_fct
+ mss_dst4(j) = mss_dst4(j)*snowcap_scl_fct
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (j >= snl+1) THEN
+
+ mss_cnc_bcphi(j) = mss_bcphi(j) / snowmass
+ mss_cnc_bcpho(j) = mss_bcpho(j) / snowmass
+
+ mss_cnc_ocphi(j) = mss_ocphi(j) / snowmass
+ mss_cnc_ocpho(j) = mss_ocpho(j) / snowmass
+
+ mss_cnc_dst1(j) = mss_dst1(j) / snowmass
+ mss_cnc_dst2(j) = mss_dst2(j) / snowmass
+ mss_cnc_dst3(j) = mss_dst3(j) / snowmass
+ mss_cnc_dst4(j) = mss_dst4(j) / snowmass
+
+ ELSE
+ ! 01/10/2023, yuan: set empty snow layers to snw_rds_min
+ snw_rds(j) = snw_rds_min
+
+ mss_bcpho(j) = 0._r8
+ mss_bcphi(j) = 0._r8
+ mss_cnc_bcphi(j) = 0._r8
+ mss_cnc_bcpho(j) = 0._r8
+
+ mss_ocpho(j) = 0._r8
+ mss_ocphi(j) = 0._r8
+ mss_cnc_ocphi(j) = 0._r8
+ mss_cnc_ocpho(j) = 0._r8
+
+ mss_dst1(j) = 0._r8
+ mss_dst2(j) = 0._r8
+ mss_dst3(j) = 0._r8
+ mss_dst4(j) = 0._r8
+ mss_cnc_dst1(j) = 0._r8
+ mss_cnc_dst2(j) = 0._r8
+ mss_cnc_dst3(j) = 0._r8
+ mss_cnc_dst4(j) = 0._r8
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE AerosolMasses
+
+
+
+ SUBROUTINE AerosolFluxes( dtime, snl, forc_aer, &
+ mss_bcphi ,mss_bcpho ,mss_ocphi ,mss_ocpho ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 )
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Compute aerosol fluxes through snowpack and aerosol deposition fluxes
+! into top layer
+!
+!-----------------------------------------------------------------------
+ IMPLICIT NONE
+ !
+ !-----------------------------------------------------------------------
+ ! !ARGUMENTS:
+ real(r8),intent(in) :: dtime ! seconds in a time step [second]
+ integer, intent(in) :: snl ! number of snow layers
+
+ real(r8), intent(in) :: forc_aer (14 ) ! aerosol deposition from atmosphere [kg m-1 s-1]
+
+ real(r8), intent(inout) :: mss_bcphi (maxsnl+1:0 ) ! hydrophillic BC mass in snow [kg]
+ real(r8), intent(inout) :: mss_bcpho (maxsnl+1:0 ) ! hydrophobic BC mass in snow [kg]
+ real(r8), intent(inout) :: mss_ocphi (maxsnl+1:0 ) ! hydrophillic OC mass in snow [kg]
+ real(r8), intent(inout) :: mss_ocpho (maxsnl+1:0 ) ! hydrophobic OC mass in snow [kg]
+ real(r8), intent(inout) :: mss_dst1 (maxsnl+1:0 ) ! mass of dust species 1 in snow [kg]
+ real(r8), intent(inout) :: mss_dst2 (maxsnl+1:0 ) ! mass of dust species 2 in snow [kg]
+ real(r8), intent(inout) :: mss_dst3 (maxsnl+1:0 ) ! mass of dust species 3 in snow [kg]
+ real(r8), intent(inout) :: mss_dst4 (maxsnl+1:0 ) ! mass of dust species 4 in snow [kg]
+
+ ! !LOCAL VARIABLES:
+ real(r8) :: flx_bc_dep ! total BC deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_bc_dep_phi ! hydrophillic BC deposition (col) [kg m-1 s-1]
+ real(r8) :: flx_bc_dep_pho ! hydrophobic BC deposition (col) [kg m-1 s-1]
+ real(r8) :: flx_oc_dep ! total OC deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_oc_dep_phi ! hydrophillic OC deposition (col) [kg m-1 s-1]
+ real(r8) :: flx_oc_dep_pho ! hydrophobic OC deposition (col) [kg m-1 s-1]
+ real(r8) :: flx_dst_dep ! total dust deposition (col) [kg m-2 s-1]
+
+ real(r8) :: flx_dst_dep_wet1 ! wet dust (species 1) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_dry1 ! dry dust (species 1) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_wet2 ! wet dust (species 2) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_dry2 ! dry dust (species 2) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_wet3 ! wet dust (species 3) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_dry3 ! dry dust (species 3) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_wet4 ! wet dust (species 4) deposition (col) [kg m-2 s-1]
+ real(r8) :: flx_dst_dep_dry4 ! dry dust (species 4) deposition (col) [kg m-2 s-1]
+
+ integer :: c
+
+ !-----------------------------------------------------------------------
+ ! set aerosol deposition fluxes from forcing array
+ ! The forcing array is either set from an external file
+ ! or from fluxes received from the atmosphere model
+#ifdef MODAL_AER
+ ! Mapping for modal aerosol scheme where within-hydrometeor and
+ ! interstitial aerosol fluxes are differentiated. Here, "phi"
+ ! flavors of BC and OC correspond to within-hydrometeor
+ ! (cloud-borne) aerosol, and "pho" flavors are interstitial
+ ! aerosol. "wet" and "dry" fluxes of BC and OC specified here are
+ ! purely diagnostic
+ !
+ ! NOTE: right now the macro 'MODAL_AER' is not defined anywhere, i.e.,
+ ! the below (modal aerosol scheme) is not available and can not be
+ ! active either. It depends on the specific input aerosol deposition
+ ! data which is suitable for modal scheme. [06/15/2023, Hua Yuan]
+
+
+ flx_bc_dep_phi = forc_aer(3)
+ flx_bc_dep_pho = forc_aer(1) + forc_aer(2)
+ flx_bc_dep = forc_aer(1) + forc_aer(2) + forc_aer(3)
+
+ flx_oc_dep_phi = forc_aer(6)
+ flx_oc_dep_pho = forc_aer(4) + forc_aer(5)
+ flx_oc_dep = forc_aer(4) + forc_aer(5) + forc_aer(6)
+
+ flx_dst_dep_wet1 = forc_aer(7)
+ flx_dst_dep_dry1 = forc_aer(8)
+ flx_dst_dep_wet2 = forc_aer(9)
+ flx_dst_dep_dry2 = forc_aer(10)
+ flx_dst_dep_wet3 = forc_aer(11)
+ flx_dst_dep_dry3 = forc_aer(12)
+ flx_dst_dep_wet4 = forc_aer(13)
+ flx_dst_dep_dry4 = forc_aer(14)
+ flx_dst_dep = forc_aer(7) + forc_aer(8) + forc_aer(9) + &
+ forc_aer(10) + forc_aer(11) + forc_aer(12) + &
+ forc_aer(13) + forc_aer(14)
+#else
+
+ ! Original mapping for bulk aerosol deposition. phi and pho BC/OC
+ ! species are distinguished in model, other fluxes (e.g., dry and
+ ! wet BC/OC) are purely diagnostic.
+
+ flx_bc_dep_phi = forc_aer(1) + forc_aer(3)
+ flx_bc_dep_pho = forc_aer(2)
+ flx_bc_dep = forc_aer(1) + forc_aer(2) + forc_aer(3)
+
+ flx_oc_dep_phi = forc_aer(4) + forc_aer(6)
+ flx_oc_dep_pho = forc_aer(5)
+ flx_oc_dep = forc_aer(4) + forc_aer(5) + forc_aer(6)
+
+ flx_dst_dep_wet1 = forc_aer(7)
+ flx_dst_dep_dry1 = forc_aer(8)
+ flx_dst_dep_wet2 = forc_aer(9)
+ flx_dst_dep_dry2 = forc_aer(10)
+ flx_dst_dep_wet3 = forc_aer(11)
+ flx_dst_dep_dry3 = forc_aer(12)
+ flx_dst_dep_wet4 = forc_aer(13)
+ flx_dst_dep_dry4 = forc_aer(14)
+ flx_dst_dep = forc_aer(7) + forc_aer(8) + forc_aer(9) + &
+ forc_aer(10) + forc_aer(11) + forc_aer(12) + &
+ forc_aer(13) + forc_aer(14)
+#endif
+
+ ! aerosol deposition fluxes into top layer
+ ! This is done after the inter-layer fluxes so that some aerosol
+ ! is in the top layer after deposition, and is not immediately
+ ! washed out before radiative calculations are done
+
+ mss_bcphi(snl+1) = mss_bcphi(snl+1) + (flx_bc_dep_phi*dtime)
+ mss_bcpho(snl+1) = mss_bcpho(snl+1) + (flx_bc_dep_pho*dtime)
+ mss_ocphi(snl+1) = mss_ocphi(snl+1) + (flx_oc_dep_phi*dtime)
+ mss_ocpho(snl+1) = mss_ocpho(snl+1) + (flx_oc_dep_pho*dtime)
+
+ mss_dst1(snl+1) = mss_dst1(snl+1) + (flx_dst_dep_dry1 + flx_dst_dep_wet1)*dtime
+ mss_dst2(snl+1) = mss_dst2(snl+1) + (flx_dst_dep_dry2 + flx_dst_dep_wet2)*dtime
+ mss_dst3(snl+1) = mss_dst3(snl+1) + (flx_dst_dep_dry3 + flx_dst_dep_wet3)*dtime
+ mss_dst4(snl+1) = mss_dst4(snl+1) + (flx_dst_dep_dry4 + flx_dst_dep_wet4)*dtime
+
+ END SUBROUTINE AerosolFluxes
+
+
+ SUBROUTINE AerosolDepInit ()
+
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ real(r8), allocatable :: lat(:), lon(:)
+
+ IF (DEF_Aerosol_Clim) THEN
+ ! climatology data
+ file_aerosol = trim(DEF_dir_runtime) // &
+ '/aerosol/aerosoldep_monthly_2000_mean_0.9x1.25_c090529.nc'
+ ELSE
+ ! yearly change data
+ file_aerosol = trim(DEF_dir_runtime) // &
+ '/aerosol/aerosoldep_monthly_1849-2001_0.9x1.25_c090529.nc'
+ ENDIF
+
+ CALL ncio_read_bcast_serial (file_aerosol, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_aerosol, 'lon', lon)
+
+ CALL grid_aerosol%define_by_center (lat, lon)
+
+ CALL allocate_block_data (grid_aerosol, f_aerdep)
+
+ CALL mg2p_aerdep%build_arealweighted (grid_aerosol, landpatch)
+
+ month_p = -1
+
+ END SUBROUTINE AerosolDepInit
+
+
+ SUBROUTINE AerosolDepReadin (idate)
+
+ USE MOD_TimeManager
+ USE MOD_NetCDFBlock
+ USE MOD_Namelist
+ USE MOD_Vars_1DForcing
+#ifdef RangeCheck
+ USE MOD_RangeCheck
+#endif
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+
+ integer :: itime, year, month, mday
+
+ year = idate(1)
+ CALL julian2monthday (idate(1), idate(2), month, mday)
+
+ ! data before the start year, will use the start year
+ IF (year < start_year) year = start_year
+ ! data after the end year, will use the end year
+ IF (year > end_year ) year = end_year
+
+ IF (month.eq.month_p) RETURN
+
+ month_p = month
+
+ ! calculate itime
+ ! NOTE: aerosol deposition is monthly data
+ IF (DEF_Aerosol_Clim) THEN
+ ! for climatology data
+ itime = month
+ ELSE
+ ! for yearly change data
+ itime = (year-start_year)*12 + month
+ ENDIF
+
+ ! BCPHIDRY , hydrophilic BC dry deposition
+ CALL ncio_read_block_time (file_aerosol, 'BCPHIDRY', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(1,:))
+
+ ! BCPHODRY , hydrophobic BC dry deposition
+ CALL ncio_read_block_time (file_aerosol, 'BCPHODRY', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(2,:))
+
+ ! BCDEPWET , hydrophilic BC wet deposition
+ CALL ncio_read_block_time (file_aerosol, 'BCDEPWET', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(3,:))
+
+ ! OCPHIDRY , hydrophilic OC dry deposition
+ CALL ncio_read_block_time (file_aerosol, 'OCPHIDRY', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(4,:))
+
+ ! OCPHODRY , hydrophobic OC dry deposition
+ CALL ncio_read_block_time (file_aerosol, 'OCPHODRY', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(5,:))
+
+ ! OCDEPWET , hydrophilic OC wet deposition
+ CALL ncio_read_block_time (file_aerosol, 'OCDEPWET', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(6,:))
+
+ ! DSTX01WD , DSTX01 wet deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX01WD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(7,:))
+
+ ! DSTX01DD , DSTX01 dry deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX01DD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(8,:))
+
+ ! DSTX02WD , DSTX02 wet deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX02WD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(9,:))
+
+ ! DSTX02DD , DSTX02 dry deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX02DD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(10,:))
+
+ ! DSTX03WD , DSTX03 wet deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX03WD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(11,:))
+
+ ! DSTX03DD , DSTX03 dry deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX03DD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(12,:))
+
+ ! DSTX04WD , DSTX04 wet deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX04WD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(13,:))
+
+ ! DSTX04DD , DSTX04 dry deposition flux at bottom
+ CALL ncio_read_block_time (file_aerosol, 'DSTX04DD', grid_aerosol, itime, f_aerdep)
+ CALL mg2p_aerdep%grid2pset (f_aerdep, forc_aerdep(14,:))
+
+#ifdef RangeCheck
+ !CALL check_block_data ('aerosol', f_aerdep)
+ CALL check_vector_data (' aerosol [kg/m/s]', forc_aerdep)
+#endif
+
+
+ END SUBROUTINE AerosolDepReadin
+
+END MODULE MOD_Aerosol
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Albedo.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Albedo.F90
new file mode 100644
index 0000000000..fd5dd381ec
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Albedo.F90
@@ -0,0 +1,2079 @@
+#include
+
+MODULE MOD_Albedo
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: albland
+ PUBLIC :: snowage
+ PUBLIC :: SnowAlbedo
+ PUBLIC :: albocean
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: twostream
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ PRIVATE :: twostream_mod
+ PRIVATE :: twostream_wrap
+#endif
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE albland (ipatch,patchtype,deltim,&
+ soil_s_v_alb,soil_d_v_alb,soil_s_n_alb,soil_d_n_alb,&
+ chil,rho,tau,fveg,green,lai,sai,fwet_snow,coszen,&
+ wt,fsno,scv,scvold,sag,ssw,pg_snow,forc_t,t_grnd,t_soisno,dz_soisno,&
+ snl,wliq_soisno,wice_soisno,snw_rds,snofrz,&
+ mss_bcpho,mss_bcphi,mss_ocpho,mss_ocphi,&
+ mss_dst1,mss_dst2,mss_dst3,mss_dst4,&
+ alb,ssun,ssha,ssoi,ssno,ssno_lyr,thermk,extkb,extkd)
+
+!=======================================================================
+! Calculates fragmented albedos (direct and diffuse) in
+! wavelength regions split at 0.7um.
+!
+! (1) soil albedos: as in BATS formulations, which are the function of
+! soil color and moisture in the surface soil layer
+! (2) snow albedos: as in BATS formulations, which are inferred from
+! the calculations of Wiscombe and Warren (1980) and the snow model
+! and data of Anderson(1976), and the function of snow age, grain
+! size, solar zenith angle, pollution, the amount of the fresh snow
+! (3) canopy albedo: two-stream approximation model
+! (4) glacier albedos: as in BATS, which are set to constants (0.8 for
+! visible beam, 0.55 for near-infrared)
+! (5) lake and wetland albedos: as in BATS, which depend on cosine solar
+! zenith angle, based on data in Henderson-Sellers (1986). The
+! frozen lake and wetland albedos are set to constants (0.6 for
+! visible beam, 0.4 for near-infrared)
+! (6) over the snow covered tile, the surface albedo is estimated by a
+! linear combination of albedos for snow, canopy and bare soil (or
+! lake, wetland, glacier).
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002, 03/2014
+!
+! !REVISIONS:
+! 12/2019, Hua Yuan: added a wrap FUNCTION for PFT calculation, details
+! see twostream_wrap() added a wrap FUNCTION for PC (3D)
+! calculation, details see ThreeDCanopy_wrap()
+!
+! 03/2020, Hua Yuan: added an improved two-stream model, details see
+! twostream_mod()
+!
+! 08/2020, Hua Yuan: account for stem optical property effects in
+! twostream model
+!
+! 01/2023, Hua Yuan: CALL SNICAR model to calculate snow
+! albedo&absorption, added SNICAR related variables
+!
+! 04/2024, Hua Yuan: add option to account for vegetation snow process
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Namelist, only: DEF_USE_SNICAR
+ USE MOD_Vars_TimeInvariants, only: patchclass
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+#endif
+ USE MOD_Aerosol, only: AerosolMasses
+ USE MOD_SnowSnicar, only: SnowAge_grain
+#ifdef LULC_IGBP_PC
+ USE MOD_3DCanopyRadiation, only: ThreeDCanopy_wrap
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+! ground cover index
+ integer, intent(in) :: &
+ ipatch, &! patch index
+ patchtype ! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=land ice, 4=water body)
+ integer, intent(in) :: &
+ snl ! number of snow layers
+
+ real(r8), intent(in) :: &
+ deltim, &! seconds in a time step [second]
+ soil_s_v_alb, &! albedo of visible of the saturated soil
+ soil_d_v_alb, &! albedo of visible of the dry soil
+ soil_s_n_alb, &! albedo of near infrared of the saturated soil
+ soil_d_n_alb, &! albedo of near infrared of the dry soil
+ chil, &! leaf angle distribution factor
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+ fveg, &! fractional vegetation cover [-]
+ green, &! green leaf fraction
+ lai, &! leaf area index (LAI+SAI) [m2/m2]
+ sai, &! stem area index (LAI+SAI) [m2/m2]
+ fwet_snow, &! vegetation snow fractional cover [-]
+
+ coszen, &! cosine of solar zenith angle [-]
+ wt, &! fraction of vegetation covered by snow [-]
+ fsno, &! fraction of soil covered by snow [-]
+ ssw, &! water volumetric content of soil surface layer [m3/m3]
+ scv, &! snow cover, water equivalent [mm]
+ scvold, &! snow cover for previous time step [mm]
+ pg_snow, &! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ forc_t, &! atmospheric temperature [K]
+ t_grnd ! ground surface temperature [K]
+
+ real(r8), intent(in) :: &
+ wliq_soisno ( maxsnl+1:0 ), &! liquid water (kg/m2)
+ wice_soisno ( maxsnl+1:0 ), &! ice lens (kg/m2)
+ snofrz ( maxsnl+1:0 ), &! snow freezing rate (col,lyr) [kg m-2 s-1]
+ t_soisno ( maxsnl+1:1 ), &! soil + snow layer temperature [K]
+ dz_soisno ( maxsnl+1:1 ) ! layer thickness (m)
+
+ real(r8), intent(inout) :: &
+ snw_rds ( maxsnl+1:0 ), &! effective grain radius (col,lyr) [microns, m-6]
+ mss_bcpho ( maxsnl+1:0 ), &! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi ( maxsnl+1:0 ), &! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho ( maxsnl+1:0 ), &! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi ( maxsnl+1:0 ), &! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 ( maxsnl+1:0 ), &! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 ( maxsnl+1:0 ), &! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 ( maxsnl+1:0 ), &! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 ( maxsnl+1:0 ) ! mass of dust species 4 in snow (col,lyr) [kg]
+
+ real(r8), intent(inout) :: sag ! non dimensional snow age [-]
+
+ real(r8), intent(out) :: &
+ alb(2,2), &! averaged albedo [-]
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2), &! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd ! diffuse and scattered diffuse PAR extinction coefficient
+
+ real(r8), intent(out) :: &
+ ssoi(2,2), &! ground soil absorption [-]
+ ssno(2,2), &! ground snow absorption [-]
+ ssno_lyr(2,2,maxsnl+1:1) ! ground snow layer absorption, by SNICAR [-]
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) :: &!
+ age, &! factor to reduce visible snow alb due to snow age [-]
+ albg0, &! temporary variable [-]
+ albsoi(2,2), &! soil albedo [-]
+ albsno(2,2), &! snow albedo [-]
+ albsno_pur(2,2), &! snow albedo [-]
+ albsno_bc (2,2), &! snow albedo [-]
+ albsno_oc (2,2), &! snow albedo [-]
+ albsno_dst(2,2), &! snow albedo [-]
+ albg(2,2), &! albedo, ground
+ albv(2,2), &! albedo, vegetation [-]
+ alb_s_inc, &! decrease in soil albedo due to wetness [-]
+ beta0, &! upscattering parameter for direct beam [-]
+ cff, &! snow alb correction factor for zenith angle > 60 [-]
+ conn, &! constant (=0.5) for visible snow alb calculation [-]
+ cons, &! constant (=0.2) for nir snow albedo calculation [-]
+ czen, &! cosine of solar zenith angle > 0 [-]
+ czf, &! solar zenith correction for new snow albedo [-]
+ dfalbl, &! snow albedo for diffuse nir radiation [-]
+ dfalbs, &! snow albedo for diffuse vis radiation [-]
+ dralbl, &! snow albedo for direct nir radiation [-]
+ dralbs, &! snow albedo for direct vis radiation [-]
+ lsai, &! leaf and stem area index (LAI+SAI) [m2/m2]
+ sl, &! factor that helps control alb zenith dependence [-]
+ snal0, &! alb for visible,incident on new snow (zen ang<60) [-]
+ snal1, &! alb for NIR, incident on new snow (zen angle<60) [-]
+ upscat, &! upward scattered fraction for direct beam [-]
+ tran(2,3) ! canopy transmittances for solar radiation
+
+ integer ps, pe
+ logical do_capsnow !true => DO snow capping
+ logical use_snicar_frc !true: IF radiative forcing is calculated,
+ !first estimate clean-snow albedo
+ logical use_snicar_ad !true: use SNICAR_AD_RT, false: use SNICAR_RT
+
+ real(r8) snwcp_ice !excess precipitation due to snow capping [kg m-2 s-1]
+ real(r8) mss_cnc_bcphi ( maxsnl+1:0 ) !mass concentration of hydrophilic BC [kg/kg]
+ real(r8) mss_cnc_bcpho ( maxsnl+1:0 ) !mass concentration of hydrophobic BC [kg/kg]
+ real(r8) mss_cnc_ocphi ( maxsnl+1:0 ) !mass concentration of hydrophilic OC [kg/kg]
+ real(r8) mss_cnc_ocpho ( maxsnl+1:0 ) !mass concentration of hydrophobic OC [kg/kg]
+ real(r8) mss_cnc_dst1 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 1 [kg/kg]
+ real(r8) mss_cnc_dst2 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 2 [kg/kg]
+ real(r8) mss_cnc_dst3 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 3 [kg/kg]
+ real(r8) mss_cnc_dst4 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 4 [kg/kg]
+
+! ----------------------------------------------------------------------
+! 1. Initial set
+! ----------------------------------------------------------------------
+
+! visible and near infrared band albedo for new snow
+ snal0 = 0.85 !visible band
+ snal1 = 0.65 !near infrared
+
+! ----------------------------------------------------------------------
+! set default soil and vegetation albedos and solar absorption
+ alb (:,:) = 1. !averaged
+ albg(:,:) = 1. !ground
+ albv(:,:) = 1. !vegetation
+ ssun(:,:) = 0. !sunlit leaf absorption
+ ssha(:,:) = 0. !shaded leaf absorption
+ tran(:,1) = 0. !incident direct radiation diffuse transmittance
+ tran(:,2) = 1. !incident diffuse radiation diffuse transmittance
+ tran(:,3) = 1. !incident direct radiation direct transmittance
+
+ ! 07/06/2023, yuan: use the values of previous timestep
+ ! for nighttime longwave calculations.
+ !thermk = 1.e-3
+ IF (lai+sai <= 1.e-6) THEN
+ thermk = 1.
+ ENDIF
+ extkb = 1.
+ extkd = 0.718
+
+ albsno (:,:) = 1. !set initial snow albedo
+ albsno_pur(:,:) = 1. !set initial pure snow albedo
+ albsno_bc (:,:) = 1. !set initial BC snow albedo
+ albsno_oc (:,:) = 1. !set initial OC snow albedo
+ albsno_dst(:,:) = 1. !set initial dust snow albedo
+
+ ! soil and snow absorption
+ ssoi (:,:) = 0. !set initial soil absorption
+ ssno (:,:) = 0. !set initial snow absorption
+ ssno_lyr(:,:,:) = 0. !set initial snow layer absorption
+
+IF (patchtype == 0) THEN
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+ ssun_p(:,:,ps:pe) = 0.
+ ssha_p(:,:,ps:pe) = 0.
+ ! 07/06/2023, yuan: use the values of previous timestep.
+ !thermk_p(ps:pe) = 1.e-3
+ WHERE (lai_p(ps:pe)+sai_p(ps:pe) <= 1.e-6) thermk_p(ps:pe) = 1.
+ extkb_p(ps:pe) = 1.
+ extkd_p(ps:pe) = 0.718
+#endif
+ENDIF
+
+! ----------------------------------------------------------------------
+! Calculate column-integrated aerosol masses, and
+! mass concentrations for radiative calculations and output
+! (based on new snow level state, after SnowFilter is rebuilt.
+! NEEDS TO BE AFTER SnowFiler is rebuilt, otherwise there
+! can be zero snow layers but an active column in filter)
+IF (DEF_USE_SNICAR) THEN
+ snwcp_ice = 0.0 !excess precipitation due to snow capping [kg m-2 s-1]
+ do_capsnow = .false. !true => DO snow capping
+
+ CALL AerosolMasses( deltim, snl ,do_capsnow ,&
+ wice_soisno(:0),wliq_soisno(:0),snwcp_ice ,snw_rds ,&
+
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 )
+
+! ----------------------------------------------------------------------
+! Snow aging routine based on Flanner and Zender (2006), Linking snowpack
+! microphysics and albedo evolution, JGR, and Brun (1989), Investigation of
+! wet-snow metamorphism in respect of liquid-water content, Ann. Glacial.
+
+ CALL SnowAge_grain( deltim ,snl ,dz_soisno(:1) ,&
+ pg_snow ,snwcp_ice ,snofrz ,&
+
+ do_capsnow ,fsno ,scv ,&
+ wliq_soisno(:0),wice_soisno(:0),t_soisno(:1) ,&
+ t_grnd ,forc_t ,snw_rds )
+ENDIF
+! ----------------------------------------------------------------------
+
+ lsai = lai + sai
+ IF(coszen <= -0.3) THEN
+ RETURN !only DO albedo when coszen > -0.3
+ ENDIF
+
+ czen = max(coszen, 0.001)
+
+! ----------------------------------------------------------------------
+! 2. get albedo over land
+! ----------------------------------------------------------------------
+! 2.1 soil albedos, depends on moisture
+ IF (patchtype <= 2) THEN !soil, urban and wetland
+ alb_s_inc = max(0.11-0.40*ssw, 0.)
+ albg(1,1) = min(soil_s_v_alb + alb_s_inc, soil_d_v_alb)
+ albg(2,1) = min(soil_s_n_alb + alb_s_inc, soil_d_n_alb)
+ albg(:,2) = albg(:,1) !diffused albedos setting
+
+! 2.2 albedos for permanent ice sheet.
+ ELSEIF (patchtype == 3) THEN !permanent ice sheet
+ albg(1,:) = 0.8
+ albg(2,:) = 0.55
+
+! 2.3 albedo for inland water
+ ELSEIF (patchtype >= 4) THEN
+ albg0 = 0.05/(czen+0.15)
+ albg(:,1) = albg0
+ albg(:,2) = 0.1 !Subin (2012)
+
+ IF(t_grnd < tfrz)THEN !frozen lake and wetland
+ albg(1,:) = 0.6
+ albg(2,:) = 0.4
+ ENDIF
+ ENDIF
+
+ ! SAVE soil ground albedo
+ albsoi(:,:) = albg(:,:)
+
+! ----------------------------------------------------------------------
+! 3. albedo for snow cover.
+! - Scheme 1: snow albedo depends on snow-age, zenith angle, and thickness
+! of snow age gives reduction of visible radiation [CoLM2014].
+! - Scheme 2: SNICAR model
+! ----------------------------------------------------------------------
+ IF (scv > 0.) THEN
+
+ IF (.not. DEF_USE_SNICAR) THEN
+ cons = 0.2
+ conn = 0.5
+ sl = 2.0 !sl helps control albedo zenith dependence
+
+ ! 05/02/2023, Dai: move from CoLMMAIN.F90
+ ! update the snow age
+ IF (snl == 0) sag=0.
+ CALL snowage (deltim,t_grnd,scv,scvold,sag)
+
+ ! correction for snow age
+ age = 1.-1./(1.+sag)
+ dfalbs = snal0*(1.-cons*age)
+
+ ! czf corrects albedo of new snow for solar zenith
+ cff = ((1.+1./sl)/(1.+czen*2.*sl )- 1./sl)
+ cff = max(cff,0.)
+ czf = 0.4*cff*(1.-dfalbs)
+ dralbs = dfalbs+czf
+ dfalbl = snal1*(1.-conn*age)
+ czf = 0.4*cff*(1.-dfalbl)
+ dralbl = dfalbl+czf
+
+ albsno(1,1) = dralbs
+ albsno(2,1) = dralbl
+ albsno(1,2) = dfalbs
+ albsno(2,2) = dfalbl
+
+ ELSE
+
+ ! 01/09/2023, yuan: CALL SNICAR for snow albedo
+ use_snicar_frc = .false. ! true: IF radiative forcing is being calculated,
+ ! first estimate clean-snow albedo
+ use_snicar_ad = .true. ! use true: use SNICAR_AD_RT, false: use SNICAR_RT
+
+ CALL SnowAlbedo( use_snicar_frc ,use_snicar_ad ,czen ,&
+ albg(:,1) ,albg(:,2) ,snl ,fsno ,&
+ scv ,wliq_soisno ,wice_soisno ,snw_rds ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 ,&
+
+ albsno (:,1),albsno (:,2),albsno_pur(:,1),albsno_pur(:,2),&
+ albsno_bc (:,1),albsno_bc (:,2),albsno_oc (:,1),albsno_oc (:,2),&
+ albsno_dst(:,1),albsno_dst(:,2),ssno_lyr(1,1,:),ssno_lyr(2,1,:),&
+ ssno_lyr(1,2,:),ssno_lyr(2,2,:))
+
+ ! IF no snow layer exist
+ IF (snl == 0) THEN
+ ssno_lyr(:,:,1) = ssno_lyr(:,:,1) + ssno_lyr(:,:,0)
+ ssno_lyr(:,:,0) = 0.
+ ENDIF
+ ENDIF
+ ENDIF
+
+! 3.1 correction due to snow cover
+ albg(:,:) = (1.-fsno)*albg(:,:) + fsno*albsno(:,:)
+ alb (:,:) = albg(:,:)
+
+! ----------------------------------------------------------------------
+! 4. canopy albedos: two stream approximation or 3D canopy radiation transfer
+! ----------------------------------------------------------------------
+ IF (lai+sai > 1e-6 .and. patchtype < 3) THEN
+
+ ! initialization
+ albv(:,:) = albg(:,:)
+
+ IF (patchtype == 0) THEN !soil patches
+
+#if (defined LULC_USGS || defined LULC_IGBP)
+ CALL twostream (chil,rho,tau,green,lai,sai,fwet_snow,&
+ czen,albg,albv,tran,thermk,extkb,extkd,ssun,ssha)
+
+ ! 08/31/2023, yuan: to be consistent with PFT and PC
+ alb(:,:) = albv(:,:)
+#endif
+ ELSE !other patchtypes (/=0)
+ CALL twostream (chil,rho,tau,green,lai,sai,fwet_snow,&
+ czen,albg,albv,tran,thermk,extkb,extkd,ssun,ssha)
+
+ ! 08/31/2023, yuan: to be consistent with PFT and PC
+ alb(:,:) = albv(:,:)
+
+ ENDIF
+ ENDIF
+
+
+ IF (patchtype == 0) THEN
+#ifdef LULC_IGBP_PFT
+ CALL twostream_wrap (ipatch, czen, albg, albv, tran, ssun, ssha)
+ alb(:,:) = albv(:,:)
+#endif
+
+#ifdef LULC_IGBP_PC
+ ! Only process nature PFTs using 3D model if set DEF_PC_CROP_SPLIT true
+ CALL ThreeDCanopy_wrap (ipatch, czen, albg, albv, tran, ssun, ssha)
+
+ ! Process crop PFTs using 1D model if set DEF_PC_CROP_SPLIT true
+ CALL twostream_wrap (ipatch, czen, albg, albv, tran, ssun, ssha)
+
+ alb(:,:) = albv(:,:)
+#endif
+ ENDIF
+
+ ! treat soil/snow absorption in direct and diffuse respectively
+ ssoi(1,1) = tran(1,1)*(1.-albsoi(1,2)) + tran(1,3)*(1-albsoi(1,1))
+ ssoi(2,1) = tran(2,1)*(1.-albsoi(2,2)) + tran(2,3)*(1-albsoi(2,1))
+ ssoi(1,2) = tran(1,2)*(1.-albsoi(1,2))
+ ssoi(2,2) = tran(2,2)*(1.-albsoi(2,2))
+
+ ssno(1,1) = tran(1,1)*(1.-albsno(1,2)) + tran(1,3)*(1-albsno(1,1))
+ ssno(2,1) = tran(2,1)*(1.-albsno(2,2)) + tran(2,3)*(1-albsno(2,1))
+ ssno(1,2) = tran(1,2)*(1.-albsno(1,2))
+ ssno(2,2) = tran(2,2)*(1.-albsno(2,2))
+
+!-----------------------------------------------------------------------
+
+ END SUBROUTINE albland
+
+
+ SUBROUTINE twostream ( chil, rho, tau, green, lai, sai, fwet_snow, &
+ coszen, albg, albv, tran, thermk, extkb, extkd, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! calculation of canopy albedos via two stream approximation (direct
+! and diffuse ) and partition of incident solar
+!
+! Original author: Yongjiu Dai, June 11, 2001
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ ! static parameters associated with vegetation type
+ chil, &! leaf angle distribution factor
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+
+ ! time-space varying vegetation parameters
+ green, &! green leaf fraction
+ lai, &! leaf area index of exposed canopy (snow-free)
+ sai, &! stem area index
+ fwet_snow ! vegetation snow fractional cover [-]
+
+! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(2,2) ! albedos of ground
+
+! output
+ real(r8), intent(out) :: &
+ albv(2,2), &! albedo, vegetation [-]
+ tran(2,3), &! canopy transmittances for solar radiation
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ lsai, &! lai+sai
+ sai_, &! sai=0 for USGS, no stem
+ phi1, &! (phi-1)
+ phi2, &! (phi-2)
+ scat, &! (omega)
+ proj, &! (g(mu))
+ zmu, &! (int(mu/g(mu))
+ zmu2, &! (zmu * zmu)
+ as, &! (a-s(mu))
+ upscat, &! (omega-beta)
+ beta0, &! (beta-0)
+ psi, &! (h)
+
+ be, &! (b)
+ ce, &! (c)
+ de, &! (d)
+ fe, &! (f)
+
+ power1, &! (h*lai)
+ power2, &! (k*lai)
+ power3, &!
+
+ sigma, &!
+ s1, &!
+ s2, &!
+ p1, &!
+ p2, &!
+ p3, &!
+ p4, &!
+ f1, &!
+ f2, &!
+ h1, &!
+ h4, &!
+ m1, &!
+ m2, &!
+ m3, &!
+ n1, &!
+ n2, &!
+ n3, &!
+
+ hh1, &! (h1/sigma)
+ hh2, &! (h2)
+ hh3, &! (h3)
+ hh4, &! (h4/sigma)
+ hh5, &! (h5)
+ hh6, &! (h6)
+ hh7, &! (h7)
+ hh8, &! (h8)
+ hh9, &! (h9)
+ hh10, &! (h10)
+
+ eup(2,2), &! (integral of i_up*exp(-kx) )
+ edown(2,2) ! (integral of i_down*exp(-kx) )
+
+ ! vegetation snow optical properties
+ real(r8) :: upscat_sno = 0.5 !upscat parameter for snow
+ real(r8) :: beta0_sno = 0.5 !beta0 parameter for snow
+ real(r8) :: scat_sno(2) !snow single scattering albedo
+ data scat_sno(1), scat_sno(2) /0.8, 0.4/ ! 1:vis, 2: nir
+
+ integer iw ! band iterator
+
+!-----------------------------------------------------------------------
+! projected area of photo elements in direction of mu and
+! average inverse diffuse optical depth per unit leaf area
+
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ proj = phi1 + phi2 * coszen
+ extkb = proj / coszen
+
+ extkd = 0.719
+
+ IF (abs(phi1).gt.1.e-6 .and. abs(phi2).gt.1.e-6) THEN
+ zmu = 1. / phi2 * ( 1. - phi1 / phi2 * log ( ( phi1 + phi2 ) / phi1 ) )
+ ELSEIF (abs(phi1).le.1.e-6) THEN
+ zmu = 1./0.877
+ ELSEIF (abs(phi2).le.1.e-6) THEN
+ zmu = 1./(2.*phi1)
+ ENDIF
+ zmu2 = zmu * zmu
+
+#if (defined LULC_USGS)
+ ! yuan: to be consistent with CoLM2014, no stem considered
+ ! for twostream and leaf optical property calculations
+ sai_ = 0.
+#else
+ sai_ = sai
+#endif
+
+ lsai = lai + sai_
+ power3 = (lai+sai) / zmu
+ power3 = min( 50., power3 )
+ power3 = max( 1.e-5, power3 )
+ thermk = exp(-power3)
+
+ IF (lsai <= 1e-6) RETURN
+
+ DO iw = 1, 2 ! WAVE_BAND_LOOP
+
+!-----------------------------------------------------------------------
+! calculate average scattering coefficient, leaf projection and
+! other coefficients for two-stream model.
+!-----------------------------------------------------------------------
+
+! account for stem optical property effects
+ scat = lai/lsai * ( tau(iw,1) + rho(iw,1) ) &
+ + sai_/lsai * ( tau(iw,2) + rho(iw,2) )
+
+ as = scat / 2. * proj / ( proj + coszen * phi2 )
+ as = as * ( 1. - coszen * phi1 / ( proj + coszen * phi2 ) * &
+ log ( ( proj + coszen * phi2 + coszen * phi1 ) / ( coszen * phi1 ) ) )
+
+! account for stem optical property effects
+ upscat = lai/lsai*tau(iw,1) + sai_/lsai*tau(iw,2)
+ ! 09/12/2014, yuan: a bug, change 1. - chil -> 1. + chil
+ upscat = 0.5 * ( scat + (scat - 2.*upscat) * ((1. + chil) / 2.) ** 2 )
+ beta0 = ( 1. + zmu * extkb ) / ( scat * zmu * extkb ) * as
+
+! account for snow on vegetation
+ ! modify scat, upscat and beta0
+ ! USE: fwet_snow, snow properties, scatter vis0.8, nir0.4, upscat0.5, beta0.5
+ IF ( DEF_VEG_SNOW ) THEN
+ scat = (1.-fwet_snow)*scat + fwet_snow*scat_sno(iw)
+ upscat = ( (1.-fwet_snow)*scat*upscat + fwet_snow*scat_sno(iw)*upscat_sno ) / scat
+ beta0 = ( (1.-fwet_snow)*scat*beta0 + fwet_snow*scat_sno(iw)*beta0_sno ) / scat
+ ENDIF
+
+!-----------------------------------------------------------------------
+! intermediate variables identified in appendix of SE-85.
+!-----------------------------------------------------------------------
+
+ be = 1. - scat + upscat
+ ce = upscat
+ de = scat * zmu * extkb * beta0
+ fe = scat * zmu * extkb * ( 1. - beta0 )
+
+ psi = sqrt(be**2 - ce**2)/zmu
+ power1 = min( psi*lsai, 50. )
+ power2 = min( extkb*lsai, 50. )
+ s1 = exp( - power1 )
+ s2 = exp( - power2 )
+
+!-----------------------------------------------------------------------
+! calculation of direct albedos and canopy transmittances.
+! albv(iw,1) ( i-up )
+! tran(iw,irad) ( i-down )
+!-----------------------------------------------------------------------
+
+ p1 = be + zmu * psi
+ p2 = be - zmu * psi
+ p3 = be + zmu * extkb
+ p4 = be - zmu * extkb
+
+ f1 = 1. - albg(iw,2)*p1/ce
+ f2 = 1. - albg(iw,2)*p2/ce
+
+ h1 = - ( de * p4 + ce * fe )
+ h4 = - ( fe * p3 + ce * de )
+
+ sigma = ( zmu * extkb ) ** 2 + ( ce**2 - be**2 )
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+
+ hh1 = h1 / sigma
+ hh4 = h4 / sigma
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = ( albg(iw,1) - ( hh1 - albg(iw,2) * hh4 ) ) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = - hh4
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,1) = hh1 + hh2 + hh3
+ tran(iw,1) = hh4 * s2 + hh5 * s1 + hh6 / s1
+
+ eup(iw,1) = hh1 * (1. - s2*s2) / (2.*extkb) &
+ + hh2 * (1. - s1*s2) / (extkb + psi) &
+ + hh3 * (1. - s2/s1) / (extkb - psi)
+
+ edown(iw,1) = hh4 * (1. - s2*s2) / (2.*extkb) &
+ + hh5 * (1. - s1*s2) / (extkb + psi) &
+ + hh6 * (1. - s2/s1) / (extkb - psi)
+
+ ELSE
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = h1 / zmu2 * ( lsai + 1. / (2.*extkb) ) * s2 &
+ + albg(iw,2) / ce * ( - h1 / (2.*extkb) / zmu2 * &
+ ( p3*lsai + p4 / (2.*extkb) ) - de ) * s2 &
+ + albg(iw,1) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1./ce * ( h1*p4 / (4.*extkb*extkb) / zmu2 + de)
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,1) = - h1 / (2.*extkb*zmu2) + hh2 + hh3
+ tran(iw,1) = 1./ce * ( -h1/(2.*extkb*zmu2) * (p3*lsai + p4/(2.*extkb)) - de ) * s2 &
+ + hh5 * s1 + hh6 / s1
+
+ eup(iw,1) = (hh2 - h1/(2.*extkb*zmu2)) * (1. - s2*s2) / (2.*extkb) &
+ + hh3 * (lsai - 0.) &
+ + h1/(2.*extkb*zmu2) * ( lsai*s2*s2 - (1. - s2*s2)/(2.*extkb) )
+
+ edown(iw,1) = (hh5 - (h1*p4/(4.*extkb*extkb*zmu) + de)/ce) * (1. - s2*s2)/(2.*extkb) &
+ + hh6 * (lsai - 0.) &
+ + h1*p3/(ce*4.*extkb*extkb*zmu2) * (lsai*s2*s2 - (1. - s2*s2)/(2.*extkb) )
+
+ ENDIF
+
+ ssun(iw,1) = (1.-scat) * ( 1.-s2 + 1. / zmu * (eup(iw,1) + edown(iw,1)) )
+ ssha(iw,1) = scat * (1.-s2) &
+ + ( albg(iw,2)*tran(iw,1) + albg(iw,1)*s2 - tran(iw,1) ) - albv(iw,1) &
+ - ( 1. - scat ) / zmu * ( eup(iw,1) + edown(iw,1) )
+
+!-----------------------------------------------------------------------
+! calculation of diffuse albedos and canopy transmittances
+! albv(iw,2) ( i-up )
+! tran(iw,2) ( i-down )
+!-----------------------------------------------------------------------
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = 0.
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1.
+
+ hh7 = -m2 / (m1*n2 - m2*n1)
+ hh8 = -m1 / (m2*n1 - m1*n2)
+
+ hh9 = hh7 * p1 / ce
+ hh10 = hh8 * p2 / ce
+
+ albv(iw,2) = hh7 + hh8
+ tran(iw,2) = hh9 * s1 + hh10 / s1
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+ eup(iw,2) = hh7 * (1. - s1*s2) / (extkb + psi) &
+ + hh8 * (1. - s2/s1) / (extkb - psi)
+ edown(iw,2) = hh9 * (1. - s1*s2) / (extkb + psi) &
+ + hh10 * (1. - s2/s1) / (extkb - psi)
+ ELSE
+ eup(iw,2) = hh7 * (1. - s1*s2) / ( extkb + psi) + hh8 * (lsai - 0.)
+ edown(iw,2) = hh9 * (1. - s1*s2) / ( extkb + psi) + hh10 * (lsai - 0.)
+ ENDIF
+
+ ssun(iw,2) = (1.-scat) / zmu * (eup(iw,2) + edown(iw,2))
+ ssha(iw,2) = tran(iw,2) * ( albg(iw,2) -1. ) - ( albv(iw,2) - 1. ) &
+ - ( 1. - scat ) / zmu * ( eup(iw,2) + edown(iw,2) )
+
+ ENDDO ! WAVE_BAND_LOOP
+
+ ! 03/06/2020, yuan: add direct transmittance (s2) to
+ ! tran for incident direct case
+ ! 03/14/2020, yuan: save direct T to 3rd position of tran
+ tran(:,3) = s2
+
+ END SUBROUTINE twostream
+
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ SUBROUTINE twostream_mod ( chil, rho, tau, green, lai, sai, fwet_snow, &
+ coszen, albg, albv, tran, thermk, extkb, extkd, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! An improved two stream approximation
+!
+! Original author: Yongjiu Dai, June 11, 2001
+! Hua Yuan, 03/2020
+!
+! !REFERENCES:
+! 1) Yuan, H., Dai, Y., Dickinson, R. E., Pinty, B., Shangguan, W.,
+! Zhang, S., et al. (2017). Reexamination and further development of
+! two-stream canopy radiative transfer models for global land modeling.
+! Journal of Advances in Modeling Earth Systems, 9(1), 113-129.
+! https://doi.org/10.1002/2016MS000773
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ ! static parameters associated with vegetation type
+ chil, &! leaf angle distribution factor
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+
+ ! time-space varying vegetation parameters
+ green, &! green leaf fraction
+ lai, &! leaf area index of exposed canopy (snow-free)
+ sai, &! stem area index
+ fwet_snow ! vegetation snow fractional cover [-]
+
+! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! cosine of solar zenith angle
+ albg(2,2) ! albedos of ground
+
+! output
+ real(r8), intent(out) :: &
+ albv(2,2), &! albedo, vegetation [-]
+ tran(2,3), &! canopy transmittances for solar radiation
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ lsai, &! lai+sai
+ phi1, &! (phi-1)
+ phi2, &! (phi-2)
+ scat, &! (omega)
+ proj, &! (g(mu))
+ zmu, &! (int(mu/g(mu))
+ zmu2, &! (zmu * zmu)
+ as, &! (a-s(mu))
+ upscat, &! (omega-beta)
+ beta0, &! (beta-0)
+ psi, &! (h)
+
+ be, &! (b)
+ ce, &! (c)
+ de, &! (d)
+ fe, &! (f)
+
+ power1, &! (h*lai)
+ power2, &! (k*lai)
+ power3, &!
+
+ sigma, &!
+ s1, &!
+ s2, &!
+ p1, &!
+ p2, &!
+ p3, &!
+ p4, &!
+ f1, &!
+ f2, &!
+ h1, &!
+ h4, &!
+ m1, &!
+ m2, &!
+ m3, &!
+ n1, &!
+ n2, &!
+ n3, &!
+
+ hh1, &! (h1/sigma)
+ hh2, &! (h2)
+ hh3, &! (h3)
+ hh4, &! (h4/sigma)
+ hh5, &! (h5)
+ hh6, &! (h6)
+ hh7, &! (h7)
+ hh8, &! (h8)
+ hh9, &! (h9)
+ hh10, &! (h10)
+
+ eup, &! (integral of i_up*exp(-kx) )
+ edw ! (integral of i_down*exp(-kx) )
+
+ ! vegetation snow optical properties
+ real(r8) :: upscat_sno = 0.5 !upscatter parameter for snow
+ real(r8) :: beta0_sno = 0.5 !beta0 parameter for snow
+ real(r8) :: scat_sno(2) !snow single scattering albedo
+ data scat_sno(1), scat_sno(2) /0.8, 0.4/ ! 1:vis, 2: nir
+
+ integer iw ! band loop index
+ integer ic ! direct/diffuse loop index
+
+ ! variables for modified version
+ real(r8) :: cosz, theta, cosdif, albgblk
+ real(r8) :: tmptau, wrho, wtau
+ real(r8) :: s2d, extkbd, sall(2,2), q, ssun_rev
+
+!-----------------------------------------------------------------------
+! projected area of photo elements in direction of mu and
+! average inverse diffuse optical depth per unit leaf area
+
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ extkd = 0.719
+
+ IF (abs(phi1).gt.1.e-6 .and. abs(phi2).gt.1.e-6) THEN
+ zmu = 1. / phi2 * ( 1. - phi1 / phi2 * log ( ( phi1 + phi2 ) / phi1 ) )
+ ELSEIF (abs(phi1).le.1.e-6) THEN
+ zmu = 1./0.877
+ ELSEIF (abs(phi2).le.1.e-6) THEN
+ zmu = 1./(2.*phi1)
+ ENDIF
+ zmu2 = zmu * zmu
+
+ lsai = lai + sai
+ power3 = lsai / zmu
+ power3 = min( 50., power3 )
+ power3 = max( 1.e-5, power3 )
+ thermk = exp(-power3)
+
+ tmptau = 0.5_r8 * lsai
+ cosdif = - tmptau / log(exp(-0.87_r8*tmptau) / (1+0.92_r8*tmptau))
+
+ ! black ground case
+ albgblk = 1.e-6_r8
+
+ DO iw = 1, 2 ! WAVE_BAND_LOOP
+
+ ! ic 1: incident direct; 2: incident diffuse
+ DO ic = 1, 2
+
+ IF (ic == 2) THEN
+ cosz = max(0.001_r8, cosdif)
+ theta = acos(cosz)
+ theta = theta/3.14159*180
+
+ theta = theta + chil*5._r8
+ cosz = cos(theta/180*3.14159)
+ ELSE
+ cosz = coszen
+ ENDIF
+
+ proj = phi1 + phi2 * cosz
+ extkb = proj / cosz
+
+!-----------------------------------------------------------------------
+! calculate average scattering coefficient, leaf projection and
+! other coefficients for two-stream model.
+!-----------------------------------------------------------------------
+
+! + stem optical properties
+ wtau = lai/lsai*tau(iw,1) + sai/lsai*tau(iw,2)
+ wrho = lai/lsai*rho(iw,1) + sai/lsai*rho(iw,2)
+
+ scat = wtau + wrho
+
+ as = scat / 2. * proj / ( proj + cosz * phi2 )
+ as = as * ( 1. - cosz * phi1 / ( proj + cosz * phi2 ) * &
+ log ( ( proj + cosz * phi2 + cosz * phi1 ) / ( cosz * phi1 ) ) )
+
+! + stem optical properties
+ ! scat ~ omega
+ ! upscat ~ betail*scat
+ ! beta0 ~ betadl
+ ! scat-2.*upscat ~ rho - tau
+ upscat = lai/lsai*tau(iw,1) + sai/lsai*tau(iw,2)
+ upscat = 0.5 * ( scat + (scat - 2.*upscat) * ((1. + chil) / 2.) ** 2 )
+ beta0 = ( 1. + zmu * extkb ) / ( scat * zmu * extkb ) * as
+
+ ! [MODI 1]
+ beta0 = 0.5_r8 * ( scat + 1._r8/extkb*(1._r8+chil)**2/4._r8*(wrho-wtau) )/scat
+
+! account for snow on vegetation
+ ! modify scat, upscat and beta0
+ ! USE: fwet_snow, snow properties, scatter vis0.8, nir0.4, upscat0.5, beta0.5
+ IF ( DEF_VEG_SNOW ) THEN
+ scat = (1.-fwet_snow)*scat + fwet_snow*scat_sno(iw)
+ upscat = ( (1.-fwet_snow)*scat*upscat + fwet_snow*scat_sno(iw)*upscat_sno ) / scat
+ beta0 = ( (1.-fwet_snow)*scat*beta0 + fwet_snow*scat_sno(iw)*beta0_sno ) / scat
+ ENDIF
+
+!-----------------------------------------------------------------------
+! intermediate variables identified in appendix of SE-85.
+!-----------------------------------------------------------------------
+
+ be = 1. - scat + upscat
+ ce = upscat
+ de = scat * zmu * extkb * beta0
+ fe = scat * zmu * extkb * ( 1. - beta0 )
+
+ psi = sqrt(be**2 - ce**2)/zmu
+ power1 = min( psi*lsai, 50. )
+ power2 = min( extkb*lsai, 50. )
+ s1 = exp( - power1 )
+ s2 = exp( - power2 )
+
+!-----------------------------------------------------------------------
+! calculation of direct albedos and canopy transmittances.
+! albv(iw,1) ( i-up )
+! tran(iw,irad) ( i-down )
+!-----------------------------------------------------------------------
+
+ p1 = be + zmu * psi
+ p2 = be - zmu * psi
+ p3 = be + zmu * extkb
+ p4 = be - zmu * extkb
+
+ f1 = 1. - albgblk*p1/ce
+ f2 = 1. - albgblk*p2/ce
+
+ h1 = - ( de * p4 + ce * fe )
+ h4 = - ( fe * p3 + ce * de )
+
+ sigma = ( zmu * extkb ) ** 2 + ( ce**2 - be**2 )
+
+ IF (ic == 1) THEN
+ s2d = s2
+ extkbd = extkb
+ ENDIF
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+
+ hh1 = h1 / sigma
+ hh4 = h4 / sigma
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = ( albgblk - ( hh1 - albgblk * hh4 ) ) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = - hh4
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,ic) = hh1 + hh2 + hh3
+ tran(iw,ic) = hh4 * s2 + hh5 * s1 + hh6 / s1
+
+ eup = hh1 * (1. - s2*s2d) / (extkbd + extkb) &
+ + hh2 * (1. - s2d*s1) / (extkbd + psi) &
+ + hh3 * (1. - s2d/s1) / (extkbd - psi)
+
+ edw = hh4 * (1. - s2*s2d) / (extkbd + extkb) &
+ + hh5 * (1. - s2d*s1) / (extkbd + psi) &
+ + hh6 * (1. - s2d/s1) / (extkbd - psi)
+
+ ELSE
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = h1 / zmu2 * ( lsai + 1. / (extkb+extkbd) ) * s2 &
+ + albgblk / ce * ( - h1 / (extkb+extkbd) / zmu2 * &
+ ( p3*lsai + p4 / (extkb+extkbd) ) - de ) * s2 &
+ + albgblk * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1./ce * ( h1*p4 / ((extkb+extkbd)*(extkb+extkbd)) / zmu2 + de)
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,ic) = - h1 / ((extkb+extkbd)*zmu2) + hh2 + hh3
+ tran(iw,ic) = 1./ce * ( -h1 / ((extkb+extkbd)*zmu2) * &
+ ( p3*lsai + p4 / (extkb+extkbd) ) - de ) * s2 &
+ + hh5 * s1 + hh6 / s1
+
+ eup = (hh2 - h1/((extkb+extkbd)*zmu2)) * (1. - s2*s2d)/(extkb+extkbd) &
+ + hh3 * (lsai - 0.) &
+ + h1/((extkb+extkbd)*zmu2) * ( lsai*s2*s2d - (1. - s2*s2d)/(extkb+extkbd) )
+
+ edw = (hh5 - (h1*p4/((extkb+extkbd)*(extkb+extkbd)*zmu) + de)/ce) * &
+ (1. - s2*s2d) / (extkb+extkbd) + hh6 * (lsai - 0.) &
+ + h1*p3/(ce*(extkb+extkbd)*(extkb+extkbd)*zmu2) * &
+ ( lsai*s2*s2d - (1. - s2*s2d)/(extkb+extkbd) )
+
+ ENDIF
+
+ sall(iw,ic) = 1. - albv(iw,ic) - (1.-albgblk)*(tran(iw,ic)+s2)
+
+ IF (ic == 1) THEN
+ ssun(iw,ic) = (1.-scat) * ( 1.-s2 + 1. / zmu * (eup + edw) )
+ ELSE
+ ssun(iw,ic) = (1.-scat) * ( extkb*(1.-s2*s2d)/(extkb+extkbd) + 1. / zmu * (eup + edw) )
+ ENDIF
+
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+
+ ENDDO ! ic
+
+ ! for reversed diffuse radiation back from ground
+ eup = hh1 * (1._r8 - s2/s2d) / (extkb - extkbd) &
+ + hh2 * (1._r8 - s1/s2d) / (psi - extkbd) &
+ + hh3 * (1._r8/s1/s2d - 1._r8) / (psi + extkbd)
+
+ edw = hh4 * (1._r8 - s2/s2d) / (extkb - extkbd) &
+ + hh5 * (1._r8 - s1/s2d) / (psi - extkbd) &
+ + hh6 * (1._r8/s1/s2d - 1._r8) / (psi + extkbd)
+
+ ssun_rev = s2d * (1._r8 - scat) * &
+ ( extkb*(1._r8-s2/s2d)/(extkb-extkbd) + 1._r8 / zmu * (eup + edw ) )
+
+ ! -----------------------------------------------------------
+ ! consider the multiple reflectance between canopy and ground
+ ! -----------------------------------------------------------
+
+ ! common ratio for geometric series
+ q = albg(iw,2) * albv(iw,2)
+
+ DO ic = 1, 2 ! from 1 to 2, cannot be reversed
+
+ ! -----------------------------------------------------------
+ ! re-calculate the absorption, transmission and albedo
+ ! for direct radiation
+
+ ! 03/06/2020, yuan: tran originally meant diffuse flow, now the direct
+ ! transmittance is also included
+ ! 03/14/2020, yuan: treat soil albedo in direct/diffuse cases
+ IF (ic == 1) THEN
+ tran(iw,ic) = (s2d*albg(iw,1)*albv(iw,2) + tran(iw,ic)) / (1.-q)
+ tran(:,3) = s2d
+
+ sall(iw,ic) = sall(iw,ic) + &
+ (tran(iw,ic)*albg(iw,2) + s2d*albg(iw,1)) * sall(iw,2)
+
+ albv(iw,ic) = 1. - sall(iw,ic) - &
+ (1.-albg(iw,2))*tran(iw,ic) - (1.-albg(iw,1))*s2d
+
+ ssun(iw,ic) = ssun(iw,ic) + &
+ (tran(iw,ic)*albg(iw,2) + s2d*albg(iw,1)) * ssun_rev
+
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+
+ ELSE
+ tran(iw,ic) = (s2 + tran(iw,ic)) / (1.-q)
+
+ sall(iw,ic) = sall(iw,ic) + tran(iw,ic)*albg(iw,2)*sall(iw,2)
+ albv(iw,ic) = 1. - sall(iw,ic) - (1.-albg(iw,2))*tran(iw,ic)
+
+ ssun(iw,ic) = ssun(iw,ic) + tran(iw,ic)*albg(iw,2)*ssun_rev
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+ ENDIF
+
+ ENDDO !ic
+
+ ENDDO !iw
+
+ ! restore extkb
+ extkb = extkbd
+
+ END SUBROUTINE twostream_mod
+#endif
+
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ SUBROUTINE twostream_wrap ( ipatch, coszen, albg, &
+ albv, tran, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! A Wrap subroutine to calculate PFT radiation using two-stream model
+!
+! Created by Hua Yuan, 03/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_LandPFT
+ USE MOD_Const_PFT
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_Namelist, only: DEF_USE_PC, DEF_PC_CROP_SPLIT
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch ! patch index
+
+ ! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! cosine of solar zenith angle
+ albg(2,2) ! albedos of ground
+
+ ! output
+ real(r8), intent(inout) :: &
+ albv(2,2), &! albedo, vegetation [-]
+ tran(2,3), &! canopy transmittances for solar radiation
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- Local Variables ----------------------------
+ integer :: i, p, ps, pe
+ real(r8), allocatable :: tran_p(:,:,:)
+ real(r8), allocatable :: albv_p(:,:,:)
+
+!-----------------------------------------------------------------------
+
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ allocate ( tran_p (2,3,ps:pe) )
+ allocate ( albv_p (2,2,ps:pe) )
+
+ DO i = ps, pe
+ p = pftclass(i)
+
+ ! If defined DEF_PC_CROP_SPLIT, for crop PFTs, use 1D twostream model;
+ ! Otherwise, set their value to PC 3D model results.
+ IF ( DEF_USE_PC .and. (.not.DEF_PC_CROP_SPLIT .or. p.lt.15) ) THEN
+ albv_p(:,:,i) = albv(:,:)
+ tran_p(:,:,i) = tran(:,:)
+ CYCLE
+ ENDIF
+
+ IF (lai_p(i)+sai_p(i) > 1.e-6) THEN
+ CALL twostream_mod (chil_p(p),rho_p(:,:,p),tau_p(:,:,p),1.,lai_p(i),sai_p(i),&
+ fwet_snow_p(i),coszen,albg,albv_p(:,:,i),tran_p(:,:,i),thermk_p(i),&
+ extkb_p(i),extkd_p(i),ssun_p(:,:,i),ssha_p(:,:,i))
+ ELSE
+ albv_p(:,:,i) = albg(:,:)
+ ssun_p(:,:,i) = 0.
+ ssha_p(:,:,i) = 0.
+ tran_p(:,1,i) = 0.
+ tran_p(:,2,i) = 1.
+ tran_p(:,3,i) = 1.
+ ENDIF
+ ENDDO
+
+ albv(1,1) = sum( albv_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ albv(1,2) = sum( albv_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ albv(2,1) = sum( albv_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ albv(2,2) = sum( albv_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssun(1,1) = sum( ssun_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(1,2) = sum( ssun_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,1) = sum( ssun_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,2) = sum( ssun_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssha(1,1) = sum( ssha_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(1,2) = sum( ssha_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,1) = sum( ssha_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,2) = sum( ssha_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ tran(1,1) = sum( tran_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ tran(1,2) = sum( tran_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ tran(1,3) = sum( tran_p(1,3,ps:pe)*pftfrac(ps:pe) )
+ tran(2,1) = sum( tran_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ tran(2,2) = sum( tran_p(2,2,ps:pe)*pftfrac(ps:pe) )
+ tran(2,3) = sum( tran_p(2,3,ps:pe)*pftfrac(ps:pe) )
+
+ IF (ssun(1,1)<0 .or. ssun(1,2)<0 .or. ssun(2,1)<0 .or. ssun(2,2)<0) THEN
+ print *, 'Warning: negative ssun in albedo calculation!',ipatch
+ print *, ssun
+ ENDIF
+
+ deallocate ( tran_p )
+ deallocate ( albv_p )
+
+ END SUBROUTINE twostream_wrap
+#endif
+
+
+ SUBROUTINE snowage ( deltim,tg,scv,scvold,sag )
+
+!=======================================================================
+! Original version: Robert Dickinson
+! Update snow cover and snow age, based on BATS code
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: deltim ! seconds in a time step [second]
+ real(r8), intent(in) :: tg ! temperature of soil at surface [K]
+ real(r8), intent(in) :: scv ! snow cover, water equivalent [mm]
+ real(r8), intent(in) :: scvold ! snow cover for previous time step [mm]
+ real(r8), intent(inout) :: sag ! non dimensional snow age [-]
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) :: age1 ! snow aging factor due to crystal growth [-]
+ real(r8) :: age2 ! snow aging factor due to surface growth [-]
+ real(r8) :: age3 ! snow aging factor due to accum of other particles [-]
+ real(r8) :: arg ! temporary variable used in snow age calculation [-]
+ real(r8) :: arg2 ! temporary variable used in snow age calculation [-]
+ real(r8) :: dela ! temporary variable used in snow age calculation [-]
+ real(r8) :: dels ! temporary variable used in snow age calculation [-]
+ real(r8) :: sge ! temporary variable used in snow age calculation [-]
+
+!-----------------------------------------------------------------------
+ IF(scv <= 0.) THEN
+ sag = 0.
+!
+! Over Antarctica
+!
+ ELSEIF (scv > 800.) THEN
+ sag = 0.
+!
+! Away from Antarctica
+!
+ ELSE
+ age3 = 0.3
+ arg = 5.e3*(1./tfrz-1./tg)
+ arg2 = min(0.,10.*arg)
+ age2 = exp(arg2)
+ age1 = exp(arg)
+ dela = 1.e-6*deltim*(age1+age2+age3)
+ dels = 0.1*max(0.0,scv-scvold)
+ sge = (sag+dela)*(1.0-dels)
+ sag = max(0.0,sge)
+ ENDIF
+
+ END SUBROUTINE snowage
+
+
+ SUBROUTINE SnowAlbedo( use_snicar_frc,use_snicar_ad ,coszen_col ,&
+ albsod ,albsoi ,snl ,frac_sno ,&
+ h2osno ,h2osno_liq ,h2osno_ice ,snw_rds ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 ,&
+
+ albgrd ,albgri ,albgrd_pur ,albgri_pur ,&
+ albgrd_bc ,albgri_bc ,albgrd_oc ,albgri_oc ,&
+ albgrd_dst ,albgri_dst ,flx_absdv ,flx_absdn ,&
+ flx_absiv ,flx_absin )
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! The calling sequence is:
+! -> SNICAR_RT: snow albedos: direct beam (SNICAR)
+! or
+! SNICAR_AD_RT: snow albedos: direct beam (SNICAR-AD)
+! -> SNICAR_RT: snow albedos: diffuse (SNICAR)
+! or
+! SNICAR_AD_RT: snow albedos: diffuse (SNICAR-AD)
+!
+! !ORIGINAL:
+! 1) The Community Land Model version5.0 (CLM5.0)
+! 2) Energy Exascale Earth System Model version 2.0 (E3SM v2.0) Land Model (ELM v2.0)
+!
+! !REFERENCES:
+! 1) Flanner et al, 2021, SNICAR-ADv3: a community tool for modeling spectral snow albedo.
+! Geosci. Model Dev., 14, 7673-7704, https://doi.org/10.5194/gmd-14-7673-2021
+! 2) Hao et al., 2023, Improving snow albedo modeling in the E3SM land model (version 2.0)
+! and assessing its impacts on snow and surface fluxes over the Tibetan Plateau.
+! Geosci. Model Dev., 16, 75-94, https://doi.org/10.5194/gmd-16-75-2023
+!
+! !REVISIONS:
+! Yongjiu Dai, and Hua Yuan, December, 2022 : ASSEMBLING and FITTING
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Vars_Global, only: maxsnl
+ USE MOD_SnowSnicar, only: SNICAR_RT, SNICAR_AD_RT
+
+ ! and the evolution of snow effective radius
+ !
+ ! DAI, Dec. 28, 2022
+
+ IMPLICIT NONE
+
+!-------------------------------------------------------------------------
+! temporary setting
+
+ integer, parameter :: numrad = 2 ! number of solar radiation bands: vis, nir
+ integer, parameter :: sno_nbr_aer = 8 ! number of aerosol species in snowpack
+ logical, parameter :: DO_SNO_OC = .true. ! to include organic carbon (OC)
+ logical, parameter :: DO_SNO_AER = .true. ! to include aerosols in snow radiative calculations
+ integer, parameter :: subgridflag = 1 ! = 0 USE subgrid fluxes, = 1 not USE subgrid fluxes
+ !
+ ! !ARGUMENTS:
+ !
+ logical , intent(in) :: use_snicar_frc ! true: IF radiative forcing is being calculated,
+ ! first estimate clean-snow albedo
+ logical , intent(in) :: use_snicar_ad ! true: USE SNICAR_AD_RT, false: USE SNICAR_RT
+
+ real(r8), intent(in) :: coszen_col ! cosine of solar zenith angle
+ real(r8), intent(in) :: albsod ( numrad ) ! direct-beam soil albedo (col,bnd) [frc]
+ real(r8), intent(in) :: albsoi ( numrad ) ! diffuse soil albedo (col,bnd) [frc]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8), intent(in) :: frac_sno ! fraction of ground covered by snow (0-1)
+ real(r8), intent(in) :: h2osno ! snow water equivalent (mm H2O)
+ real(r8), intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg/m2]
+ real(r8), intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice lens content (col,lyr) [kg/m2]
+ real(r8), intent(in) :: snw_rds ( maxsnl+1:0 ) ! snow grain radius (col,lyr) [microns]
+
+ real(r8), intent(in) :: mss_cnc_bcphi ( maxsnl+1:0 ) ! mass conc. of hydrophilic BC [kg/kg]
+ real(r8), intent(in) :: mss_cnc_bcpho ( maxsnl+1:0 ) ! mass conc. of hydrophobic BC [kg/kg]
+ real(r8), intent(in) :: mss_cnc_ocphi ( maxsnl+1:0 ) ! mass conc. of hydrophilic OC [kg/kg]
+ real(r8), intent(in) :: mss_cnc_ocpho ( maxsnl+1:0 ) ! mass conc. of hydrophobic OC [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst1 ( maxsnl+1:0 ) ! mass conc. of dust aerosol 1 [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst2 ( maxsnl+1:0 ) ! mass conc. of dust aerosol 2 [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst3 ( maxsnl+1:0 ) ! mass conc. of dust aerosol 3 [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst4 ( maxsnl+1:0 ) ! mass conc. of dust aerosol 4 [kg/kg]
+
+ real(r8), intent(out) :: albgrd ( numrad ) ! ground albedo (direct)
+ real(r8), intent(out) :: albgri ( numrad ) ! ground albedo (diffuse)
+ real(r8), intent(out) :: albgrd_pur ( numrad ) ! pure snow ground albedo (direct)
+ real(r8), intent(out) :: albgri_pur ( numrad ) ! pure snow ground albedo (diffuse)
+ real(r8), intent(out) :: albgrd_bc ( numrad ) ! ground albedo without BC (direct)
+ real(r8), intent(out) :: albgri_bc ( numrad ) ! ground albedo without BC (diffuse)
+ real(r8), intent(out) :: albgrd_oc ( numrad ) ! ground albedo without OC (direct)
+ real(r8), intent(out) :: albgri_oc ( numrad ) ! ground albedo without OC (diffuse)
+ real(r8), intent(out) :: albgrd_dst ( numrad ) ! ground albedo without dust (direct)
+ real(r8), intent(out) :: albgri_dst ( numrad ) ! ground albedo without dust (diffuse)
+ real(r8), intent(out) :: flx_absdv ( maxsnl+1:1 ) ! direct flux absorption factor VIS [frc]
+ real(r8), intent(out) :: flx_absdn ( maxsnl+1:1 ) ! direct flux absorption factor NIR [frc]
+ real(r8), intent(out) :: flx_absiv ( maxsnl+1:1 ) ! diffuse flux absorption factor VIS [frc]
+ real(r8), intent(out) :: flx_absin ( maxsnl+1:1 ) ! diffuse flux absorption factor NIR [frc]
+
+ !-----------------------------------------------------------------------
+ !
+ ! !LOCAL VARIABLES:
+ integer :: i ! index for layers [idx]
+ integer :: aer ! index for sno_nbr_aer
+ integer :: ib ! band index
+ integer :: ic ! 0=unit incoming direct; 1=unit incoming diffuse
+ integer :: flg_slr ! flag for SNICAR (=1 IF direct, =2 IF diffuse)
+ integer :: flg_snw_ice ! flag for SNICAR (=1 when called from ELM, =2 when called from sea-ice)
+
+ ! mass concentration of aerosol species for forcing calculation (zero) (lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_pur (maxsnl+1:0,sno_nbr_aer)
+ ! mass concentration of aerosol species for BC forcing (lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_bc (maxsnl+1:0,sno_nbr_aer)
+ ! mass concentration of aerosol species for OC forcing (lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_oc (maxsnl+1:0,sno_nbr_aer)
+ ! mass concentration of aerosol species for dust forcing (lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_dst (maxsnl+1:0,sno_nbr_aer)
+ ! mass concentration of all aerosol species for feedback calculation (lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_fdb (maxsnl+1:0,sno_nbr_aer)
+
+ real(r8) :: albsfc (numrad) ! albedo of surface underneath snow (col,bnd)
+ real(r8) :: albsnd (numrad) ! snow albedo (direct)
+ real(r8) :: albsni (numrad) ! snow albedo (diffuse)
+ real(r8) :: albsnd_pur (numrad) ! direct pure snow albedo
+ real(r8) :: albsni_pur (numrad) ! diffuse pure snow albedo
+ real(r8) :: albsnd_bc (numrad) ! direct snow albedo without BC
+ real(r8) :: albsni_bc (numrad) ! diffuse snow albedo without BC
+ real(r8) :: albsnd_oc (numrad) ! direct snow albedo without OC
+ real(r8) :: albsni_oc (numrad) ! diffuse snow albedo without OC
+ real(r8) :: albsnd_dst (numrad) ! direct snow albedo without dust
+ real(r8) :: albsni_dst (numrad) ! diffuse snow albedo without dust
+ real(r8) :: flx_absd_snw (maxsnl+1:1,numrad) ! flux absorption for just snow (direct) [frc]
+ real(r8) :: flx_absi_snw (maxsnl+1:1,numrad) ! flux absorption for just snow (diffuse) [frc]
+ real(r8) :: foo_snw (maxsnl+1:1,numrad) ! dummy array for forcing calls
+
+ integer :: snw_rds_in (maxsnl+1:0) ! snow grain size sent to SNICAR (col,lyr) [microns]
+
+ integer , parameter :: nband =numrad ! number of solar radiation waveband classes
+
+ !-----------------------------------------------------------------------
+
+ ! Initialize output because solar radiation only done IF coszen > 0
+
+ DO ib = 1, numrad
+ albgrd(ib) = 1._r8
+ albgri(ib) = 1._r8
+ albgrd_pur(ib) = 1._r8
+ albgri_pur(ib) = 1._r8
+ albgrd_bc(ib) = 1._r8
+ albgri_bc(ib) = 1._r8
+ albgrd_oc(ib) = 1._r8
+ albgri_oc(ib) = 1._r8
+ albgrd_dst(ib) = 1._r8
+ albgri_dst(ib) = 1._r8
+ DO i=maxsnl+1,1,1
+ flx_absdv(i) = 0._r8
+ flx_absdn(i) = 0._r8
+ flx_absiv(i) = 0._r8
+ flx_absin(i) = 0._r8
+ ENDDO
+ ENDDO ! END of numrad loop
+
+ ! set variables to pass to SNICAR.
+
+ flg_snw_ice = 1
+ albsfc(:) = albsoi(:)
+ snw_rds_in(:) = nint(snw_rds(:))
+
+ ! zero aerosol input arrays
+ DO aer = 1, sno_nbr_aer
+ DO i = maxsnl+1, 0
+ mss_cnc_aer_in_frc_pur(i,aer) = 0._r8
+ mss_cnc_aer_in_frc_bc(i,aer) = 0._r8
+ mss_cnc_aer_in_frc_oc(i,aer) = 0._r8
+ mss_cnc_aer_in_frc_dst(i,aer) = 0._r8
+ mss_cnc_aer_in_fdb(i,aer) = 0._r8
+ ENDDO
+ ENDDO
+
+ ! If radiative forcing is being calculated, first estimate clean-snow albedo
+
+ IF (use_snicar_frc) THEN
+
+ ! 1. PURE SNOW ALBEDO CALCULATIONS
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsnd_pur(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsnd_pur(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsni_pur(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsni_pur(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ ! 2. BC input array:
+ ! set dust and (optionally) OC concentrations, so BC_FRC=[(BC+OC+dust)-(OC+dust)]
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_frc_bc(:,3) = mss_cnc_ocphi(:)
+ mss_cnc_aer_in_frc_bc(:,4) = mss_cnc_ocpho(:)
+ ENDIF
+ mss_cnc_aer_in_frc_bc(:,5) = mss_cnc_dst1(:)
+ mss_cnc_aer_in_frc_bc(:,6) = mss_cnc_dst2(:)
+ mss_cnc_aer_in_frc_bc(:,7) = mss_cnc_dst3(:)
+ mss_cnc_aer_in_frc_bc(:,8) = mss_cnc_dst4(:)
+
+ ! BC FORCING CALCULATIONS
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsnd_bc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsnd_bc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsni_bc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsni_bc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ ! 3. OC input array:
+ ! set BC and dust concentrations, so OC_FRC=[(BC+OC+dust)-(BC+dust)]
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_frc_oc(:,1) = mss_cnc_bcphi(:)
+ mss_cnc_aer_in_frc_oc(:,2) = mss_cnc_bcpho(:)
+
+ mss_cnc_aer_in_frc_oc(:,5) = mss_cnc_dst1(:)
+ mss_cnc_aer_in_frc_oc(:,6) = mss_cnc_dst2(:)
+ mss_cnc_aer_in_frc_oc(:,7) = mss_cnc_dst3(:)
+ mss_cnc_aer_in_frc_oc(:,8) = mss_cnc_dst4(:)
+
+ ! OC FORCING CALCULATIONS
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsnd_oc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsnd_oc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsni_oc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsni_oc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+ ENDIF ! END IF (DO_SNO_OC)
+
+ ! 4. DUST FORCING CALCULATIONS
+ ! DUST input array:
+ ! set BC and OC concentrations, so DST_FRC=[(BC+OC+dust)-(BC+OC)]
+ mss_cnc_aer_in_frc_dst(:,1) = mss_cnc_bcphi(:)
+ mss_cnc_aer_in_frc_dst(:,2) = mss_cnc_bcpho(:)
+
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_frc_dst(:,3) = mss_cnc_ocphi(:)
+ mss_cnc_aer_in_frc_dst(:,4) = mss_cnc_ocpho(:)
+ ENDIF
+
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsnd_dst(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsnd_dst(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsni_dst(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsni_dst(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ ENDIF !END IF use_snicar_frc
+
+
+ ! --------------------------------------------
+ ! CLIMATE FEEDBACK CALCULATIONS, ALL AEROSOLS:
+ ! --------------------------------------------
+ ! Set aerosol input arrays
+ ! feedback input arrays have been zeroed
+ ! set soot and dust aerosol concentrations:
+ IF (DO_SNO_AER) THEN
+ mss_cnc_aer_in_fdb(:,1) = mss_cnc_bcphi(:)
+ mss_cnc_aer_in_fdb(:,2) = mss_cnc_bcpho(:)
+
+ ! DO_SNO_OC is set in SNICAR_varpar. Default case is to ignore OC concentrations because:
+ ! 1) Knowledge of their optical properties is primitive
+ ! 2) When 'water-soluble' OPAC optical properties are applied to OC in snow,
+ ! it has a negligible darkening effect.
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_fdb(:,3) = mss_cnc_ocphi(:)
+ mss_cnc_aer_in_fdb(:,4) = mss_cnc_ocpho(:)
+ ENDIF
+
+ mss_cnc_aer_in_fdb(:,5) = mss_cnc_dst1(:)
+ mss_cnc_aer_in_fdb(:,6) = mss_cnc_dst2(:)
+ mss_cnc_aer_in_fdb(:,7) = mss_cnc_dst3(:)
+ mss_cnc_aer_in_fdb(:,8) = mss_cnc_dst4(:)
+ ENDIF
+
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsnd(:), &
+ flx_absd_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsnd(:), &
+ flx_absd_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsni(:), &
+ flx_absi_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsni(:), &
+ flx_absi_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+
+ ! ground albedos and snow-fraction weighting of snow absorption factors
+ DO ib = 1, nband
+ IF (coszen_col > 0._r8) THEN
+ ! ground albedo was originally computed in SoilAlbedo, but is now computed here
+ ! because the order of SoilAlbedo and SNICAR_RT/SNICAR_AD_RT
+ ! was switched for SNICAR/SNICAR_AD_RT.
+ ! 09/01/2023, yuan: change to only snow albedo, the same below
+ !albgrd(ib) = albsod(ib)*(1._r8-frac_sno) + albsnd(ib)*frac_sno
+ !albgri(ib) = albsoi(ib)*(1._r8-frac_sno) + albsni(ib)*frac_sno
+ albgrd(ib) = albsnd(ib)
+ albgri(ib) = albsni(ib)
+
+ ! albedos for radiative forcing calculations:
+ IF (use_snicar_frc) THEN
+ ! pure snow albedo for all-aerosol radiative forcing
+ !albgrd_pur(ib) = albsod(ib)*(1.-frac_sno) + albsnd_pur(ib)*frac_sno
+ !albgri_pur(ib) = albsoi(ib)*(1.-frac_sno) + albsni_pur(ib)*frac_sno
+ albgrd_pur(ib) = albsnd_pur(ib)
+ albgri_pur(ib) = albsni_pur(ib)
+
+ ! BC forcing albedo
+ !albgrd_bc(ib) = albsod(ib)*(1.-frac_sno) + albsnd_bc(ib)*frac_sno
+ !albgri_bc(ib) = albsoi(ib)*(1.-frac_sno) + albsni_bc(ib)*frac_sno
+ albgrd_bc(ib) = albsnd_bc(ib)
+ albgri_bc(ib) = albsni_bc(ib)
+
+ IF (DO_SNO_OC) THEN
+ ! OC forcing albedo
+ !albgrd_oc(ib) = albsod(ib)*(1.-frac_sno) + albsnd_oc(ib)*frac_sno
+ !albgri_oc(ib) = albsoi(ib)*(1.-frac_sno) + albsni_oc(ib)*frac_sno
+ albgrd_oc(ib) = albsnd_oc(ib)
+ albgri_oc(ib) = albsni_oc(ib)
+ ENDIF
+
+ ! dust forcing albedo
+ !albgrd_dst(ib) = albsod(ib)*(1.-frac_sno) + albsnd_dst(ib)*frac_sno
+ !albgri_dst(ib) = albsoi(ib)*(1.-frac_sno) + albsni_dst(ib)*frac_sno
+ albgrd_dst(ib) = albsnd_dst(ib)
+ albgri_dst(ib) = albsni_dst(ib)
+ ENDIF
+
+ ! also in this loop (but optionally in a different loop for vectorized code)
+ ! weight snow layer radiative absorption factors based on snow fraction and soil albedo
+ ! (NEEDED FOR ENERGY CONSERVATION)
+ DO i = maxsnl+1,1,1
+ IF (subgridflag == 0 ) THEN
+ IF (ib == 1) THEN
+ flx_absdv(i) = flx_absd_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsod(ib))*(flx_absd_snw(i,ib)/(1.-albsnd(ib))))
+ flx_absiv(i) = flx_absi_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsoi(ib))*(flx_absi_snw(i,ib)/(1.-albsni(ib))))
+ ELSEIF (ib == 2) THEN
+ flx_absdn(i) = flx_absd_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsod(ib))*(flx_absd_snw(i,ib)/(1.-albsnd(ib))))
+ flx_absin(i) = flx_absi_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsoi(ib))*(flx_absi_snw(i,ib)/(1.-albsni(ib))))
+ ENDIF
+ ELSE
+ IF (ib == 1) THEN
+ flx_absdv(i) = flx_absd_snw(i,ib)!*(1.-albsnd(ib))
+ flx_absiv(i) = flx_absi_snw(i,ib)!*(1.-albsni(ib))
+ ELSEIF (ib == 2) THEN
+ flx_absdn(i) = flx_absd_snw(i,ib)!*(1.-albsnd(ib))
+ flx_absin(i) = flx_absi_snw(i,ib)!*(1.-albsni(ib))
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE SnowAlbedo
+
+
+ SUBROUTINE albocean (oro, scv, coszrs, alb)
+
+!-----------------------------------------------------------------------
+!
+! Compute surface albedos
+!
+! Computes surface albedos for direct/diffuse incident radiation for
+! two spectral intervals:
+! s = 0.2-0.7 micro-meters
+! l = 0.7-5.0 micro-meters
+!
+! Albedos specified as follows:
+!
+! Ocean Uses solar zenith angle to compute albedo for direct
+! radiation; diffuse radiation values constant; albedo
+! independent of spectral interval and other physical
+! factors such as ocean surface wind speed.
+!
+! Ocean with Surface albs specified; combined with overlying snow
+! sea ice
+!
+! For more details , see Briegleb, Bruce P., 1992: Delta-Eddington
+! Approximation for Solar Radiation in the NCAR Community Climate Model,
+! Journal of Geophysical Research, Vol 97, D7, pp7603-7612).
+!
+! Yongjiu Dai and Xin-Zhong Liang (08/01/2001)
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: oro ! /ocean(0)/seaice(2) flag
+ real(r8), intent(in) :: scv ! snow water equivalent) [mm]
+ real(r8), intent(in) :: coszrs ! Cosine solar zenith angle
+
+ real(r8), intent(out) :: alb(2,2) ! srf alb for direct (diffuse) rad 0.2-0.7 micro-ms
+ ! Srf alb for direct (diffuse) rad 0.7-5.0 micro-ms
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) frsnow ! horizontal fraction of snow cover
+ real(r8) snwhgt ! physical snow height
+ real(r8) rghsnw ! roughness for horizontal snow cover fractn
+
+ real(r8) sasdir ! snow alb for direct rad 0.2-0.7 micro-ms
+ real(r8) saldir ! snow alb for direct rad 0.7-5.0 micro-ms
+ real(r8) sasdif ! snow alb for diffuse rad 0.2-0.7 micro-ms
+ real(r8) saldif ! snow alb for diffuse rad 0.7-5.0 micro-ms
+
+ real(r8), parameter :: asices = 0.70 ! sea ice albedo for 0.2-0.7 micro-meters [-]
+ real(r8), parameter :: asicel = 0.50 ! sea ice albedo for 0.7-5.0 micro-meters [-]
+ real(r8), parameter :: asnows = 0.95 ! snow albedo for 0.2-0.7 micro-meters [-]
+ real(r8), parameter :: asnowl = 0.70 ! snow albedo for 0.7-5.0 micro-meters
+
+!-----------------------------------------------------------------------
+! initialize all ocean/sea ice surface albedos to zero
+
+ alb(:,:) = 0.
+ IF(coszrs<=0.0) RETURN
+
+ IF(nint(oro)==2)THEN
+ alb(1,1) = asices
+ alb(2,1) = asicel
+ alb(1,2) = alb(1,1)
+ alb(2,2) = alb(2,1)
+ sasdif = asnows
+ saldif = asnowl
+
+ IF(scv>0.)THEN
+ IF (coszrs<0.5) THEN
+ ! zenith angle regime 1 ( coszrs < 0.5 ).
+ ! set direct snow albedos (limit to 0.98 max)
+ sasdir = min(0.98,sasdif+(1.-sasdif)*0.5*(3./(1.+4.*coszrs)-1.))
+ saldir = min(0.98,saldif+(1.-saldif)*0.5*(3./(1.+4.*coszrs)-1.))
+ ELSE
+ ! zenith angle regime 2 ( coszrs >= 0.5 )
+ sasdir = asnows
+ saldir = asnowl
+ ENDIF
+
+ ! compute both diffuse and direct total albedos
+ snwhgt = 20.*scv / 1000.
+ rghsnw = 0.25
+ frsnow = snwhgt/(rghsnw+snwhgt)
+ alb(1,1) = alb(1,1)*(1.-frsnow) + sasdir*frsnow
+ alb(2,1) = alb(2,1)*(1.-frsnow) + saldir*frsnow
+ alb(1,2) = alb(1,2)*(1.-frsnow) + sasdif*frsnow
+ alb(2,2) = alb(2,2)*(1.-frsnow) + saldif*frsnow
+ ENDIF
+ ENDIF
+
+! ice-free ocean albedos function of solar zenith angle only, and
+! independent of spectral interval:
+
+ IF(nint(oro)==0)THEN
+ alb(2,1) = .026/(coszrs**1.7+.065) &
+ + .15*(coszrs-0.1)*(coszrs-0.5)*(coszrs-1.)
+ alb(1,1) = alb(2,1)
+ alb(1,2) = 0.06
+ alb(2,2) = 0.06
+ ENDIF
+
+ END SUBROUTINE albocean
+
+END MODULE MOD_Albedo
+! --------- EOP ----------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Albedo_HiRes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Albedo_HiRes.F90
new file mode 100644
index 0000000000..2c9b2ef86c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Albedo_HiRes.F90
@@ -0,0 +1,3374 @@
+#include
+
+#ifdef HYPERSPECTRAL
+MODULE MOD_Albedo_HiRes
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: albland_HiRes
+ PUBLIC :: snowage
+ PUBLIC :: SnowAlbedo
+ PUBLIC :: albocean
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: twostream
+ PRIVATE :: twostream_hires
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ PRIVATE :: twostream_mod
+ PRIVATE :: twostream_wrap
+ PRIVATE :: twostream_hires_mod
+ PRIVATE :: twostream_hires_wrap
+#endif
+ PRIVATE :: BSM_soil_moisture, calculate_tav, calculate_wgt_variable
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE albland_HiRes (ipatch, patchtype, deltim,&
+ soil_s_v_alb,soil_d_v_alb,soil_s_n_alb,soil_d_n_alb,&
+ chil,rho,tau,fveg,green,lai,sai,fwet_snow,coszen,&
+ wt,fsno,scv,scvold,sag,ssw,pg_snow,forc_t,t_grnd,t_soisno,dz_soisno,&
+ snl,wliq_soisno,wice_soisno,snw_rds,snofrz,&
+ mss_bcpho,mss_bcphi,mss_ocpho,mss_ocphi,&
+ mss_dst1,mss_dst2,mss_dst3,mss_dst4,&
+ alb,ssun,ssha,ssoi,ssno,ssno_lyr,thermk,extkb,extkd,&
+
+ ! new parameters for high res
+ alb_hires ,&
+ dir_frac , dif_frac, &
+ reflectance, transmittance, &
+ soil_alb, kw, nw, porsl, &
+ reflectance_out, transmittance_out,&
+ doy, patchlatr, patchlonr ,&
+ ! new parameters for urban
+ urban_albedo, mean_albedo ,&
+ lat_north, lat_south, lon_west, lon_east)
+
+!=======================================================================
+! Calculates fragmented albedos (direct and diffuse) in
+! wavelength regions split at 0.7um.
+!
+! (1) soil albedos: as in BATS formulations, which are the function of
+! soil color and moisture in the surface soil layer
+! (2) snow albedos: as in BATS formulations, which are inferred from
+! the calculations of Wiscombe and Warren (1980) and the snow model
+! and data of Anderson(1976), and the function of snow age, grain size,
+! solar zenith angle, pollution, the amount of the fresh snow
+! (3) canopy albedo: two-stream approximation model
+! (4) glacier albedos: as in BATS, which are set to constants (0.8 for visible beam,
+! 0.55 for near-infrared)
+! (5) lake and wetland albedos: as in BATS, which depend on cosine solar zenith angle,
+! based on data in Henderson-Sellers (1986). The frozen lake and wetland albedos
+! are set to constants (0.6 for visible beam, 0.4 for near-infrared)
+! (6) over the snow covered tile, the surface albedo is estimated by a linear
+! combination of albedos for snow, canopy and bare soil (or lake, wetland, glacier).
+!
+! Original author : Yongjiu Dai, 09/15/1999; 08/30/2002, 03/2014
+!
+! !REVISIONS:
+! 12/2019, Hua Yuan: added a wrap FUNCTION for PFT calculation, details see
+! twostream_wrap() added a wrap FUNCTION for PC (3D) calculation,
+! details see ThreeDCanopy_wrap()
+!
+! 03/2020, Hua Yuan: added an improved two-stream model, details see
+! twostream_mod()
+!
+! 08/2020, Hua Yuan: account for stem optical property effects in twostream
+! model
+!
+! 01/2023, Hua Yuan: CALL SNICAR model to calculate snow albedo&absorption,
+! added SNICAR related variables
+!
+! 04/2024, Hua Yuan: add option to account for vegetation snow process
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Namelist, only: DEF_USE_SNICAR, DEF_HighResSoil
+ USE MOD_Vars_TimeInvariants, only: patchclass
+ USE MOD_HighRes_Parameters, only: rad2deg
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+#endif
+ USE MOD_Aerosol, only: AerosolMasses
+ USE MOD_SnowSnicar_HiRes, only: SnowAge_grain
+#ifdef LULC_IGBP_PC
+ USE MOD_3DCanopyRadiation, only: ThreeDCanopy_wrap
+#endif
+
+ ! IEEE arithmetic module for isnan function, only for debug
+ ! use, intrinsic :: IEEE_ARITHMETIC, only: IEEE_IS_NAN, IEEE_SUPPORT_DATATYPE
+
+ IMPLICIT NONE
+
+!------------------------- Dummy Arguments -----------------------------
+! ground cover index
+ integer, intent(in) :: &
+ ipatch, &! patch index
+ patchtype ! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=land ice, 4=deep lake)
+ integer, intent(in) :: &
+ snl, &! number of snow layers
+ doy
+
+ real(r8), intent(in) :: &
+ patchlatr, &! patch latitude (radian)
+ patchlonr ! patch longitude (radian)
+
+ real(r8), intent(in) :: &
+ deltim, &! seconds in a time step [second]
+ soil_s_v_alb, &! albedo of visible of the saturated soil
+ soil_d_v_alb, &! albedo of visible of the dry soil
+ soil_s_n_alb, &! albedo of near infrared of the saturated soil
+ soil_d_n_alb, &! albedo of near infrared of the dry soil
+ chil, &! leaf angle distribution factor
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+ fveg, &! fractional vegetation cover [-]
+ green, &! green leaf fraction
+ lai, &! leaf area index (LAI+SAI) [m2/m2]
+ sai, &! stem area index (LAI+SAI) [m2/m2]
+ fwet_snow, &! vegetation snow fractional cover [-]
+
+ coszen, &! cosine of solar zenith angle [-]
+ wt, &! fraction of vegetation covered by snow [-]
+ fsno, &! fraction of soil covered by snow [-]
+ ssw, &! water volumetric content of soil surface layer [m3/m3]
+ scv, &! snow cover, water equivalent [mm]
+ scvold, &! snow cover for previous time step [mm]
+ pg_snow, &! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ forc_t, &! atmospheric temperature [K]
+ t_grnd, &! ground surface temperature [K]
+ porsl
+
+ real(r8), intent(in) :: &
+ wliq_soisno ( maxsnl+1:0 ), &! liquid water (kg/m2)
+ wice_soisno ( maxsnl+1:0 ), &! ice lens (kg/m2)
+ snofrz ( maxsnl+1:0 ), &! snow freezing rate (col,lyr) [kg m-2 s-1]
+ t_soisno ( maxsnl+1:1 ), &! soil + snow layer temperature [K]
+ dz_soisno ( maxsnl+1:1 ), &! layer thickness (m)
+
+ dir_frac (211) ,&!
+ dif_frac (211) ,&!
+ reflectance (0:15,211,2) ,&! reflectance (PFT, wavelength, dir/dif)
+ transmittance(0:15,211,2) ,&! transmittance (PFT, wavelength, dir/dif)
+ soil_alb (211) ,&! soil albedo [-]
+ kw (211) ,&! soil albedo [-]
+ nw (211) ! soil albedo [-]
+
+
+ real(r8), intent(inout) :: &
+ snw_rds ( maxsnl+1:0 ), &! effective grain radius (col,lyr) [microns, m-6]
+ mss_bcpho ( maxsnl+1:0 ), &! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi ( maxsnl+1:0 ), &! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho ( maxsnl+1:0 ), &! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi ( maxsnl+1:0 ), &! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 ( maxsnl+1:0 ), &! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 ( maxsnl+1:0 ), &! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 ( maxsnl+1:0 ), &! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 ( maxsnl+1:0 ) ! mass of dust species 4 in snow (col,lyr) [kg]
+
+ real(r8), intent(inout) :: sag ! non dimensional snow age [-]
+
+ real(r8), intent(out) :: &
+ alb(2,2), &! averaged albedo [-]
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2), &! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd ! diffuse and scattered diffuse PAR extinction coefficient
+
+ real(r8), intent(out) :: &
+ alb_hires (211, 2) ,&! high resolution albedo, (wavelength, dir/dif)
+ reflectance_out (211, 0:15) ,&!
+ transmittance_out(211, 0:15)
+
+ real(r8), intent(out) :: &
+ ssoi(2,2), &! ground soil absorption [-]
+ ssno(2,2), &! ground snow absorption [-]
+ ssno_lyr(2,2,maxsnl+1:1) ! ground snow layer absorption, by SNICAR [-]
+
+ ! New inout parameters for urban
+ real(r8), ALLOCATABLE, intent(in) :: &
+ urban_albedo(:,:,:), &! (cluster_id, season,wavelength)
+ mean_albedo(:, :), &! (season, wavelength)
+ lat_north(:), lat_south(:),&
+ lon_west (:), lon_east(:)
+
+
+!-------------------------- Local variables ----------------------------
+
+ real(r8) :: &!
+ age, &! factor to reduce visible snow alb due to snow age [-]
+ albg0, &! temporary varaiable [-]
+ albsoi(2,2), &! soil albedo [-]
+ albsno(2,2), &! snow albedo [-]
+ albsno_pur(2,2), &! snow albedo [-]
+ albsno_bc (2,2), &! snow albedo [-]
+ albsno_oc (2,2), &! snow albedo [-]
+ albsno_dst(2,2), &! snow albedo [-]
+ albg(2,2), &! albedo, ground
+ albv(2,2), &! albedo, vegetation [-]
+ alb_s_inc, &! decrease in soil albedo due to wetness [-]
+ beta0, &! upscattering parameter for direct beam [-]
+ cff, &! snow alb correction factor for zenith angle > 60 [-]
+ conn, &! constant (=0.5) for visible snow alb calculation [-]
+ cons, &! constant (=0.2) for nir snow albedo calculation [-]
+ czen, &! cosine of solar zenith angle > 0 [-]
+ czf, &! solar zenith correction for new snow albedo [-]
+ dfalbl, &! snow albedo for diffuse nir radiation [-]
+ dfalbs, &! snow albedo for diffuse vis radiation [-]
+ dralbl, &! snow albedo for direct nir radiation [-]
+ dralbs, &! snow albedo for direct vis radiation [-]
+ lsai, &! leaf and stem area index (LAI+SAI) [m2/m2]
+ sl, &! factor that helps control alb zenith dependence [-]
+ snal0, &! alb for visible,incident on new snow (zen ang<60) [-]
+ snal1, &! alb for NIR, incident on new snow (zen angle<60) [-]
+ upscat, &! upward scattered fraction for direct beam [-]
+ tran(2,3) ! canopy transmittances for solar radiation
+
+!-------------------------- Local high resolution variables ----------------------------
+ real(r8) :: &!
+
+ ! sun fraction
+ fsds_vis_dir_frac(29 ) ,&
+ fsds_nir_dir_frac(182) ,&
+ fsds_vis_dif_frac(29 ) ,&
+ fsds_nir_dif_frac(182) ,&
+
+ ! ground
+ albg_hires(211, 2) ,&
+
+ ! soil
+ albsoi_hires(211, 2) ,&
+
+ ! snow
+ alb_sno_hires(211, 2) ,&! high resolution albedo, (wavelength, dir/dif)
+
+ alb_sno_5band (5, 2) ,&
+ albsno_pur_5band(5, 2) ,&! snow albedo [-]
+ albsno_bc_5band (5, 2) ,&! snow albedo [-]
+ albsno_oc_5band (5, 2) ,&! snow albedo [-]
+ albsno_dst_5band(5, 2) ,&! snow albedo [-]
+
+ ! vegetation
+ rho_hires(211, 2) ,&
+ tau_hires(211, 2) ,&
+ albv_hires(211, 2) ,&
+ tran_hires(211, 3) ,&
+ scat_hires(211) ,&
+ ssun_hires(211, 2) ,&
+ ssha_hires(211, 2)
+
+ INTEGER, PARAMETER, DIMENSION(6) :: band_index = (/ &
+ 1, 30, 60, 80, 110, 212 &! 400, 700, 1000, 1200, 1500, 2500 nm
+ /)
+
+ real(r8) :: smc
+ integer :: i, j, ibnd, start_index, end_index ! index for 5 bands [idx]
+
+ integer ps, pe
+ logical do_capsnow !true => DO snow capping
+ logical use_snicar_frc !true: IF radiative forcing is being calculated, first estimate clean-snow albedo
+ logical use_snicar_ad !true: use SNICAR_AD_RT, false: use SNICAR_RT
+
+ real(r8) snwcp_ice !excess precipitation due to snow capping [kg m-2 s-1]
+ real(r8) mss_cnc_bcphi ( maxsnl+1:0 ) !mass concentration of hydrophilic BC (col,lyr) [kg/kg]
+ real(r8) mss_cnc_bcpho ( maxsnl+1:0 ) !mass concentration of hydrophobic BC (col,lyr) [kg/kg]
+ real(r8) mss_cnc_ocphi ( maxsnl+1:0 ) !mass concentration of hydrophilic OC (col,lyr) [kg/kg]
+ real(r8) mss_cnc_ocpho ( maxsnl+1:0 ) !mass concentration of hydrophobic OC (col,lyr) [kg/kg]
+ real(r8) mss_cnc_dst1 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 1 (col,lyr) [kg/kg]
+ real(r8) mss_cnc_dst2 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 2 (col,lyr) [kg/kg]
+ real(r8) mss_cnc_dst3 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 3 (col,lyr) [kg/kg]
+ real(r8) mss_cnc_dst4 ( maxsnl+1:0 ) !mass concentration of dust aerosol species 4 (col,lyr) [kg/kg]
+
+ logical :: has_nan
+
+ real(r8) :: lat, lon
+ INTEGER :: num_urban_lat, num_urban_lon
+ INTEGER :: i_cluster
+ INTEGER :: season_index
+! ----------------------------------------------------------------------
+! 1. Initial set
+! ----------------------------------------------------------------------
+! set fsds
+ fsds_vis_dir_frac(:) = dir_frac(1:29)
+ fsds_nir_dir_frac(:) = dir_frac(30:211)
+ fsds_vis_dif_frac(:) = dif_frac(1:29)
+ fsds_nir_dif_frac(:) = dif_frac(30:211)
+
+! visible and near infrared band albedo for new snow
+ snal0 = 0.85 !visible band
+ snal1 = 0.65 !near infrared
+
+! ----------------------------------------------------------------------
+! set default soil and vegetation albedos and solar absorption
+ alb (:,:) = 1. !averaged
+ albg(:,:) = 1. !ground
+ albv(:,:) = 1. !vegetation
+ ssun(:,:) = 0. !sunlit leaf absorption
+ ssha(:,:) = 0. !shaded leaf absorption
+
+ alb_hires (:,:) = 1. ! high resolution albedo
+ albg_hires(:,:) = 1. ! high resolution ground albedo
+ albv_hires(:,:) = 1. ! high resolution vegetation albedo
+ ssun_hires (:,:) = 0.
+ ssha_hires (:,:) = 0.
+
+ ! albsoi_hires (:,:) = 1.
+
+ tran(:,1) = 0. !incident direct radiation diffuse transmittance
+ tran(:,2) = 1. !incident diffuse radiation diffuse transmittance
+ tran(:,3) = 1. !incident direct radiation direct transmittance
+
+ tran_hires(:,1) = 0. !incident direct radiation diffuse transmittance
+ tran_hires(:,2) = 1. !incident diffuse radiation diffuse transmittance
+ tran_hires(:,3) = 1. !incident direct radiation direct transmittance
+
+ reflectance_out (:,:) = -999.
+ transmittance_out(:,:) = -999.
+
+ ! 07/06/2023, yuan: use the values of previous timestep.
+ ! for nighttime longwave calculations.
+ !thermk = 1.e-3
+ IF (lai+sai <= 1.e-6) THEN
+ thermk = 1.
+ ENDIF
+ extkb = 1.
+ extkd = 0.718
+
+ albsno (:,:) = 1. !set initial snow albedo
+ albsno_pur(:,:) = 1. !set initial pure snow albedo
+ albsno_bc (:,:) = 1. !set initial BC snow albedo
+ albsno_oc (:,:) = 1. !set initial OC snow albedo
+ albsno_dst(:,:) = 1. !set initial dust snow albedo
+
+ alb_sno_hires (:,:) = 1.! high resolution albedo, (wavelength, dir/dif)
+ albsno_pur_5band(:,:) = 1.
+ albsno_bc_5band (:,:) = 1.
+ albsno_oc_5band (:,:) = 1.
+ albsno_dst_5band(:,:) = 1.
+
+ ! soil and snow absorption
+ ssoi (:,:) = 0. !set initial soil absorption
+ ssno (:,:) = 0. !set initial snow absorption
+ ssno_lyr(:,:,:) = 0. !set initial snow layer absorption
+
+IF (patchtype == 0) THEN
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+ ssun_p(:,:,ps:pe) = 0.
+ ssha_p(:,:,ps:pe) = 0.
+
+ ssun_hires_p(:,:,ps:pe) = 0.
+ ssha_hires_p(:,:,ps:pe) = 0.
+ ! 07/06/2023, yuan: use the values of previous timestep.
+ !thermk_p(ps:pe) = 1.e-3
+ WHERE (lai_p(ps:pe)+sai_p(ps:pe) <= 1.e-6) thermk_p(ps:pe) = 1.
+ extkb_p(ps:pe) = 1.
+ extkd_p(ps:pe) = 0.718
+#endif
+ENDIF
+
+! ----------------------------------------------------------------------
+! Calculate column-integrated aerosol masses, and
+! mass concentrations for radiative calculations and output
+! (based on new snow level state, after SnowFilter is rebuilt.
+! NEEDS TO BE AFTER SnowFiler is rebuilt, otherwise there
+! can be zero snow layers but an active column in filter)
+IF (DEF_USE_SNICAR) THEN
+ snwcp_ice = 0.0 !excess precipitation due to snow capping [kg m-2 s-1]
+ do_capsnow = .false. !true => DO snow capping
+
+ CALL AerosolMasses( deltim, snl ,do_capsnow ,&
+ wice_soisno(:0),wliq_soisno(:0),snwcp_ice ,snw_rds ,&
+
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 )
+
+! ----------------------------------------------------------------------
+! Snow aging routine based on Flanner and Zender (2006), Linking snowpack
+! microphysics and albedo evolution, JGR, and Brun (1989), Investigation of
+! wet-snow metamorphism in respect of liquid-water content, Ann. Glaciol.
+
+ CALL SnowAge_grain( deltim ,snl ,dz_soisno(:1) ,&
+ pg_snow ,snwcp_ice ,snofrz ,&
+
+ do_capsnow ,fsno ,scv ,&
+ wliq_soisno (:0),wice_soisno(:0),&
+ t_soisno (:1),t_grnd ,&
+ forc_t ,snw_rds )
+END IF
+! ----------------------------------------------------------------------
+
+ lsai = lai + sai
+ IF(coszen <= -0.3) THEN
+ RETURN !only DO albedo when coszen > -0.3
+ ENDIF
+
+ czen = max(coszen, 0.001)
+
+! ----------------------------------------------------------------------
+! 2. get albedo over land
+! ----------------------------------------------------------------------
+! 2.1 soil albedos, depends on moisture
+
+ ! IF (patchtype <= 2) THEN !soil, urban and wetland
+ IF (patchtype == 0) THEN !soil
+
+ ! calculate broadband albedos
+ alb_s_inc = max(0.11-0.40*ssw, 0.)
+ albg(1,1) = min(soil_s_v_alb + alb_s_inc, soil_d_v_alb)
+ albg(2,1) = min(soil_s_n_alb + alb_s_inc, soil_d_n_alb)
+ albg(:,2) = albg(:,1) !diffused albedos setting
+
+ IF ( DEF_HighResSoil ) THEN
+ ! calculate high res soil albedos
+ CALL BSM_soil_moisture( ssw * 100., porsl * 100., soil_alb, kw, nw, albg_hires )
+
+ ! calculate broadband albedos
+ CALL calculate_wgt_variable(albg_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, albg(1,1), albg(2,1))
+ CALL calculate_wgt_variable(albg_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, albg(1,2), albg(2,2))
+
+ ELSE
+
+ ! calculate high res soil albedos
+ albg_hires(1 :29 ,1) = albg(1,1)
+ albg_hires(30:211,1) = albg(2,1)
+ albg_hires(1 :29 ,2) = albg(1,2)
+ albg_hires(30:211,2) = albg(2,2)
+
+ END IF
+
+ !DEBUG: Temporarily handle the missing values of soil albedo in certain grids
+ IF (soil_alb(1) < 0.01) THEN
+ albg_hires(1:29 ,1) = albg(1,1)
+ albg_hires(30:211 ,1) = albg(2,1)
+ albg_hires(1:29 ,2) = albg(1,2)
+ albg_hires(30:211 ,2) = albg(2,2)
+ END IF
+
+ ELSE IF(patchtype == 1) THEN !urban
+
+ ! select constant albedo for urban
+ lat = rad2deg(patchlatr)
+ lon = rad2deg(patchlonr)
+
+ ! 根据lat、lon边界选择cluster_id
+ i_cluster = 0
+ DO i = 1, SIZE(lat_north)
+ IF (lat >= lat_south(i) .and. lat <= lat_north(i) .and. &
+ lon >= lon_west(i) .and. lon <= lon_east(i)) THEN
+ i_cluster = i
+ EXIT
+ END IF
+ END DO
+
+ ! 根据季节选择albedo
+ ! 季节指数: 1=冬季, 2=春季, 3=夏季, 4=秋季
+ IF (doy >= 355 .or. doy < 80) THEN
+ season_index = 1 ! 冬季
+ ELSE IF (doy >= 80 .and. doy < 172) THEN
+ season_index = 2 ! 春季
+ ELSE IF (doy >= 172 .and. doy < 266) THEN
+ season_index = 3 ! 夏季
+ ELSE
+ season_index = 4 ! 秋季
+ END IF
+
+ ! 提取反照率数据
+ IF (i_cluster > 0 .and. allocated(urban_albedo)) THEN
+ albg_hires(:, 1) = urban_albedo(i_cluster, season_index, :)
+ albg_hires(:, 2) = urban_albedo(i_cluster, season_index, :)
+ ELSE
+ ! 如果未找到合适的cluster或数据未分配,使用mean_albedo
+ IF (allocated(mean_albedo)) THEN
+ albg_hires(:, 1) = mean_albedo(season_index, :)
+ albg_hires(:, 2) = mean_albedo(season_index, :)
+ ELSE
+ ! 如果都没有数据,使用默认值
+ albg_hires(1 :29 ,1) = 0.12
+ albg_hires(30:211,1) = 0.20
+ albg_hires(1 :29 ,2) = 0.12
+ albg_hires(30:211,2) = 0.20
+ END IF
+ END IF
+
+ ! 计算宽波段反照率 (VIS 和 NIR)
+ CALL calculate_wgt_variable(albg_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, albg(1,1), albg(2,1))
+ CALL calculate_wgt_variable(albg_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, albg(1,2), albg(2,2))
+
+ ELSE IF (patchtype == 2) THEN !wetland
+ ! calculate broadband albedos
+ alb_s_inc = max(0.11-0.40*ssw, 0.)
+ albg(1,1) = min(soil_s_v_alb + alb_s_inc, soil_d_v_alb)
+ albg(2,1) = min(soil_s_n_alb + alb_s_inc, soil_d_n_alb)
+ albg(:,2) = albg(:,1) !diffused albedos setting
+
+ albg_hires(1 :29 ,1) = albg(1,1)
+ albg_hires(1 :29 ,2) = albg(1,2)
+ albg_hires(30:211,1) = albg(2,1)
+ albg_hires(30:211,2) = albg(2,2)
+
+! 2.2 albedos for permanent ice sheet.
+ ELSE IF(patchtype == 3) THEN !permanent ice sheet
+ albg(1,:) = 0.8
+ albg(2,:) = 0.55
+
+ albg_hires(1 :29 ,:) = 0.8
+ albg_hires(30:211,:) = 0.55
+
+! 2.3 albedo for inland water
+ ELSE IF(patchtype >= 4) THEN
+ albg0 = 0.05/(czen+0.15)
+ albg(:,1) = albg0
+ albg(:,2) = 0.1 !Subin (2012)
+
+ albg_hires(:,1) = albg0
+ albg_hires(:,2) = 0.1
+
+ IF(t_grnd < tfrz)THEN !frozen lake and wetland
+ albg(1,:) = 0.6
+ albg(2,:) = 0.4
+
+ albg_hires(1 :29 ,:) = 0.6
+ albg_hires(30:211,:) = 0.4
+ ENDIF
+ ENDIF
+
+ ! SAVE soil ground albedo
+ albsoi (:,:) = albg (:,:)
+ albsoi_hires(:,:) = albg_hires(:,:)
+
+ ! ----------------------------------------------------------------------
+! 3. albedo for snow cover.
+! - Scheme 1: snow albedo depends on snow-age, zenith angle, and thickness
+! of snow age gives reduction of visible radiation [CoLM2014].
+! - Scheme 2: SNICAR model
+! ----------------------------------------------------------------------
+ IF (scv > 0.) THEN
+
+ IF (.not. DEF_USE_SNICAR) THEN
+ cons = 0.2
+ conn = 0.5
+ sl = 2.0 !sl helps control albedo zenith dependence
+
+ ! 05/02/2023, Dai: move from CoLMMAIN.F90
+ ! update the snow age
+ IF (snl == 0) sag=0.
+ CALL snowage (deltim,t_grnd,scv,scvold,sag)
+
+ ! correction for snow age
+ age = 1.-1./(1.+sag)
+ dfalbs = snal0*(1.-cons*age)
+
+ ! czf corrects albedo of new snow for solar zenith
+ cff = ((1.+1./sl)/(1.+czen*2.*sl )- 1./sl)
+ cff = max(cff,0.)
+ czf = 0.4*cff*(1.-dfalbs)
+ dralbs = dfalbs+czf
+ dfalbl = snal1*(1.-conn*age)
+ czf = 0.4*cff*(1.-dfalbl)
+ dralbl = dfalbl+czf
+
+ albsno(1,1) = dralbs
+ albsno(2,1) = dralbl
+ albsno(1,2) = dfalbs
+ albsno(2,2) = dfalbl
+
+ ELSE
+
+ ! 01/09/2023, yuan: CALL SNICAR for snow albedo
+ use_snicar_frc = .false. ! true: IF radiative forcing is being calculated, first estimate clean-snow albedo
+ use_snicar_ad = .true. ! use true: use SNICAR_AD_RT, false: use SNICAR_RT
+
+ CALL SnowAlbedo( use_snicar_frc ,use_snicar_ad ,coszen ,&
+ albg_hires(:,1),albg_hires(:,2),snl ,fsno ,&
+ scv ,wliq_soisno ,wice_soisno ,snw_rds ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 ,&
+
+ alb_sno_5band (:,1),alb_sno_5band (:,2),albsno_pur_5band(:,1),albsno_pur_5band(:,2),&
+ albsno_bc_5band (:,1),albsno_bc_5band (:,2),albsno_oc_5band (:,1),albsno_oc_5band (:,2),&
+ albsno_dst_5band(:,1),albsno_dst_5band(:,2),ssno_lyr(1,1,:) ,ssno_lyr(2,1,:) ,&
+ ssno_lyr(1,2,:) ,ssno_lyr(2,2,:) ,dir_frac ,dif_frac )
+
+ ! IF no snow layer exist
+ IF (snl == 0) THEN
+ ssno_lyr(:,:,1) = ssno_lyr(:,:,1) + ssno_lyr(:,:,0)
+ ssno_lyr(:,:,0) = 0.
+ ENDIF
+ ENDIF
+ ENDIF
+
+! 3.1 correction due to snow cover
+ ! albg(:,:) = (1.-fsno)*albg(:,:) + fsno*albsno(:,:)
+ ! alb (:,:) = albg(:,:)
+
+ do ibnd = 1, 5
+ start_index = band_index(ibnd)
+ end_index = band_index(ibnd+1) - 1
+
+ alb_sno_hires(start_index:end_index, 1) = alb_sno_5band(ibnd, 1)
+ alb_sno_hires(start_index:end_index, 2) = alb_sno_5band(ibnd, 2)
+ end do
+
+ albg_hires(:,1) = (1.-fsno)*albg_hires(:,1) + fsno*alb_sno_hires(:,1)
+ albg_hires(:,2) = (1.-fsno)*albg_hires(:,2) + fsno*alb_sno_hires(:,2)
+
+ alb_hires(:,1) = albg_hires(:,1)
+ alb_hires(:,2) = albg_hires(:,2)
+
+ CALL calculate_wgt_variable(albg_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, albg(1,1), albg(2,1))
+ CALL calculate_wgt_variable(albg_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, albg(1,2), albg(2,2))
+
+ alb (:,:) = albg(:,:)
+
+! ----------------------------------------------------------------------
+! 4. canopy albedos: two stream approximation or 3D canopy radiation transfer
+! ----------------------------------------------------------------------
+ IF (lai+sai > 1e-6 .and. patchtype < 3) THEN
+ ! initialization
+ albv(:,:) = albg(:,:)
+
+ IF (patchtype == 0) THEN !soil patches
+
+#if (defined LULC_USGS || defined LULC_IGBP)
+ ! High resolution vegetation
+ write(*,*) "NOT SUPPORT NOW!!!!!!!"
+ CALL twostream_hires (chil,reflectance,transmittance,green,lai,sai, fwet_snow,&
+ czen,albg_hires,albv_hires,tran_hires,thermk,extkb,extkd,ssun_hires,ssha_hires)
+
+ CALL calculate_wgt_variable(albg_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, alb(1,1), alb(2,1))
+ CALL calculate_wgt_variable(albg_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, alb(1,2), alb(2,2))
+
+ CALL calculate_wgt_variable(ssun_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, ssun(1,1), ssun(2,1))
+ CALL calculate_wgt_variable(ssun_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, ssun(1,2), ssun(2,2))
+
+ CALL calculate_wgt_variable(ssha_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, ssha(1,1), ssha(2,1))
+ CALL calculate_wgt_variable(ssha_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, ssha(1,2), ssha(2,2))
+
+ alb_hires(:,:) = albv_hires(:,:)
+
+ ! ! two-band albedo
+ ! CALL twostream (chil,rho,tau,green,lai,sai,fwet_snow,&
+ ! czen,albg,albv,tran,thermk,extkb,extkd,ssun,ssha)
+
+ ! 08/31/2023, yuan: to be consistent with PFT and PC
+ !albv(:,:) = (1.- wt)*albv(:,:) + wt*albsno(:,:)
+ !alb (:,:) = (1.-fveg)*albg(:,:) + fveg*albv(:,:)
+
+ ! alb(:,:) = albv(:,:)
+
+#endif
+ ELSE !other patchtypes (/=0)
+ CALL twostream (chil,rho,tau,green,lai,sai,fwet_snow,&
+ czen,albg,albv,tran,thermk,extkb,extkd,ssun,ssha)
+
+ ! 08/31/2023, yuan: to be consistent with PFT and PC
+ !albv(:,:) = (1.- wt)*albv(:,:) + wt*albsno(:,:)
+ !alb (:,:) = (1.-fveg)*albg(:,:) + fveg*albv(:,:)
+ alb(:,:) = albv(:,:)
+
+ alb_hires(1:29 ,1) = albv_hires(1,1)
+ alb_hires(30:211,1) = albv_hires(2,1)
+ alb_hires(1:29 ,2) = albv_hires(1,2)
+ alb_hires(30:211,2) = albv_hires(2,2)
+
+ tran_hires(1:29 ,1) = tran(1,1)
+ tran_hires(30:211,1) = tran(2,1)
+ tran_hires(1:29 ,2) = tran(1,2)
+ tran_hires(30:211,2) = tran(2,2)
+ tran_hires(1:29 ,3) = tran(1,3)
+ tran_hires(30:211,3) = tran(2,3)
+ ENDIF
+ ENDIF
+
+
+ IF (patchtype == 0) THEN
+
+#ifdef LULC_IGBP_PFT
+ CALL twostream_hires_wrap (ipatch, czen, albg_hires, &
+ albv_hires, tran_hires, ssun_hires, ssha_hires, &
+ reflectance, transmittance, &
+ fsds_vis_dir_frac, fsds_nir_dir_frac, &
+ fsds_vis_dif_frac, fsds_nir_dif_frac, &
+ ssw, reflectance_out, transmittance_out, doy)
+
+ ! convert alb(:,:) = albv(:,:) -> hyperspectral
+ CALL calculate_wgt_variable(albv_hires(:,1), fsds_vis_dir_frac, fsds_nir_dir_frac, alb(1,1), alb(2,1))
+ CALL calculate_wgt_variable(albv_hires(:,2), fsds_vis_dif_frac, fsds_nir_dif_frac, alb(1,2), alb(2,2))
+
+ alb_hires(:,:) = albv_hires(:,:)
+#endif
+
+#ifdef LULC_IGBP_PC
+ !NOTE: if patchclass is CROPLAND, using twostream model
+ IF (patchclass(ipatch) == CROPLAND) THEN
+ CALL twostream_wrap (ipatch, czen, albg, albv, tran, ssun, ssha)
+ alb(:,:) = albv(:,:)
+ ELSE
+ CALL ThreeDCanopy_wrap (ipatch, czen, albg, albv, tran, ssun, ssha)
+ alb(:,:) = albv(:,:)
+ ENDIF
+#endif
+ ENDIF
+
+ ! treat soil/snow albedo in direct and diffuse respectively
+ CALL calculate_wgt_variable((tran_hires(:,1)*(1.-albsoi_hires(:,2)) + tran_hires(:,3)*(1.-albsoi_hires(:,1))), fsds_vis_dir_frac, fsds_nir_dir_frac, ssoi(1,1), ssoi(2,1))
+ CALL calculate_wgt_variable((tran_hires(:,2)*(1.-albsoi_hires(:,2))), fsds_vis_dif_frac, fsds_nir_dif_frac, ssoi(1,2), ssoi(2,2))
+
+ CALL calculate_wgt_variable((tran_hires(:,1)*(1.-alb_sno_hires(:,2)) + tran_hires(:,3)*(1.-alb_sno_hires(:,1))), fsds_vis_dir_frac, fsds_nir_dir_frac, ssno(1,1), ssno(2,1))
+ CALL calculate_wgt_variable((tran_hires(:,2)*(1.-alb_sno_hires(:,2))), fsds_vis_dif_frac, fsds_nir_dif_frac, ssno(1,2), ssno(2,2))
+
+!-----------------------------------------------------------------------
+
+ END SUBROUTINE albland_HiRes
+
+
+ SUBROUTINE twostream ( chil, rho, tau, green, lai, sai, fwet_snow, &
+ coszen, albg, albv, tran, thermk, extkb, extkd, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! calculation of canopy albedos via two stream approximation (direct
+! and diffuse ) and partition of incident solar
+!
+! Original author: Yongjiu Dai, June 11, 2001
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ IMPLICIT NONE
+
+! parameters
+ real(r8), intent(in) :: &
+ ! static parameters associated with vegetation type
+ chil, &! leaf angle distribution factor
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+
+ ! time-space varying vegetation parameters
+ green, &! green leaf fraction
+ lai, &! leaf area index of exposed canopy (snow-free)
+ sai, &! stem area index
+ fwet_snow ! vegetation snow fractional cover [-]
+
+! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(2,2) ! albedos of ground
+
+! output
+ real(r8), intent(out) :: &
+ albv(2,2), &! albedo, vegetation [-]
+ tran(2,3), &! canopy transmittances for solar radiation
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- local -----------------------------------
+ real(r8) :: &
+ lsai, &! lai+sai
+ sai_, &! sai=0 for USGS, no stem
+ phi1, &! (phi-1)
+ phi2, &! (phi-2)
+ scat, &! (omega)
+ proj, &! (g(mu))
+ zmu, &! (int(mu/g(mu))
+ zmu2, &! (zmu * zmu)
+ as, &! (a-s(mu))
+ upscat, &! (omega-beta)
+ beta0, &! (beta-0)
+ psi, &! (h)
+
+ be, &! (b)
+ ce, &! (c)
+ de, &! (d)
+ fe, &! (f)
+
+ power1, &! (h*lai)
+ power2, &! (k*lai)
+ power3, &!
+
+ sigma, &!
+ s1, &!
+ s2, &!
+ p1, &!
+ p2, &!
+ p3, &!
+ p4, &!
+ f1, &!
+ f2, &!
+ h1, &!
+ h4, &!
+ m1, &!
+ m2, &!
+ m3, &!
+ n1, &!
+ n2, &!
+ n3, &!
+
+ hh1, &! (h1/sigma)
+ hh2, &! (h2)
+ hh3, &! (h3)
+ hh4, &! (h4/sigma)
+ hh5, &! (h5)
+ hh6, &! (h6)
+ hh7, &! (h7)
+ hh8, &! (h8)
+ hh9, &! (h9)
+ hh10, &! (h10)
+
+ eup(2,2), &! (integral of i_up*exp(-kx) )
+ edown(2,2) ! (integral of i_down*exp(-kx) )
+
+ ! vegetation snow optical properties
+ real(r8) :: upscat_sno = 0.5 !upscat parameter for snow
+ real(r8) :: beta0_sno = 0.5 !beta0 parameter for snow
+ real(r8) :: scat_sno(2) !snow single scattering albedo
+ data scat_sno(1), scat_sno(2) /0.8, 0.4/ ! 1:vis, 2: nir
+
+ integer iw ! band iterator
+
+!-----------------------------------------------------------------------
+! projected area of phytoelements in direction of mu and
+! average inverse diffuse optical depth per unit leaf area
+
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ proj = phi1 + phi2 * coszen
+ extkb = proj / coszen
+
+ extkd = 0.719
+
+ IF (abs(phi1).gt.1.e-6 .and. abs(phi2).gt.1.e-6) THEN
+ zmu = 1. / phi2 * ( 1. - phi1 / phi2 * log ( ( phi1 + phi2 ) / phi1 ) )
+ ELSE IF (abs(phi1).le.1.e-6) THEN
+ zmu = 1./0.877
+ ELSE IF (abs(phi2).le.1.e-6) THEN
+ zmu = 1./(2.*phi1)
+ ENDIF
+ zmu2 = zmu * zmu
+
+#if(defined LULC_USGS)
+ ! yuan: to be consistance with CoLM2014, no stem considered
+ ! for twostream and leaf optical property calculations
+ sai_ = 0.
+#else
+ sai_ = sai
+#endif
+
+ lsai = lai + sai_
+ power3 = (lai+sai) / zmu
+ power3 = min( 50., power3 )
+ power3 = max( 1.e-5, power3 )
+ thermk = exp(-power3)
+
+ IF (lsai <= 1e-6) RETURN
+
+ DO iw = 1, 2 ! WAVE_BAND_LOOP
+
+!-----------------------------------------------------------------------
+! calculate average scattering coefficient, leaf projection and
+! other coefficients for two-stream model.
+!-----------------------------------------------------------------------
+
+! account for stem optical property effects
+ scat = lai/lsai * ( tau(iw,1) + rho(iw,1) ) &
+ + sai_/lsai * ( tau(iw,2) + rho(iw,2) )
+
+ as = scat / 2. * proj / ( proj + coszen * phi2 )
+ as = as * ( 1. - coszen * phi1 / ( proj + coszen * phi2 ) * &
+ log ( ( proj + coszen * phi2 + coszen * phi1 ) / ( coszen * phi1 ) ) )
+
+! account for stem optical property effects
+ !TODO-done: betao -> beta0
+ upscat = lai/lsai*tau(iw,1) + sai_/lsai*tau(iw,2)
+ ! 09/12/2014, yuan: a bug, change 1. - chil -> 1. + chil
+ upscat = 0.5 * ( scat + (scat - 2.*upscat) * ((1. + chil) / 2.) ** 2 )
+ beta0 = ( 1. + zmu * extkb ) / ( scat * zmu * extkb ) * as
+
+! account for snow on vegetation
+ ! modify scat, upscat and beta0
+ ! USE: fwet_snow, snow properties, scatter vis0.8, nir0.4, upscat0.5, beta0.5
+ IF ( DEF_VEG_SNOW ) THEN
+ scat = (1.-fwet_snow)*scat + fwet_snow*scat_sno(iw)
+ upscat = ( (1.-fwet_snow)*scat*upscat + fwet_snow*scat_sno(iw)*upscat_sno ) / scat
+ beta0 = ( (1.-fwet_snow)*scat*beta0 + fwet_snow*scat_sno(iw)*beta0_sno ) / scat
+ ENDIF
+
+!-----------------------------------------------------------------------
+! intermediate variables identified in appendix of SE-85.
+!-----------------------------------------------------------------------
+
+ be = 1. - scat + upscat
+ ce = upscat
+ de = scat * zmu * extkb * beta0
+ fe = scat * zmu * extkb * ( 1. - beta0 )
+
+ psi = sqrt(be**2 - ce**2)/zmu
+ power1 = min( psi*lsai, 50. )
+ power2 = min( extkb*lsai, 50. )
+ s1 = exp( - power1 )
+ s2 = exp( - power2 )
+
+!-----------------------------------------------------------------------
+! calculation of direct albedos and canopy transmittances.
+! albv(iw,1) ( i-up )
+! tran(iw,irad) ( i-down )
+!-----------------------------------------------------------------------
+
+ p1 = be + zmu * psi
+ p2 = be - zmu * psi
+ p3 = be + zmu * extkb
+ p4 = be - zmu * extkb
+
+ f1 = 1. - albg(iw,2)*p1/ce
+ f2 = 1. - albg(iw,2)*p2/ce
+
+ h1 = - ( de * p4 + ce * fe )
+ h4 = - ( fe * p3 + ce * de )
+
+ sigma = ( zmu * extkb ) ** 2 + ( ce**2 - be**2 )
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+
+ hh1 = h1 / sigma
+ hh4 = h4 / sigma
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = ( albg(iw,1) - ( hh1 - albg(iw,2) * hh4 ) ) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = - hh4
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,1) = hh1 + hh2 + hh3
+ tran(iw,1) = hh4 * s2 + hh5 * s1 + hh6 / s1
+
+ eup(iw,1) = hh1 * (1. - s2*s2) / (2.*extkb) &
+ + hh2 * (1. - s1*s2) / (extkb + psi) &
+ + hh3 * (1. - s2/s1) / (extkb - psi)
+
+ edown(iw,1) = hh4 * (1. - s2*s2) / (2.*extkb) &
+ + hh5 * (1. - s1*s2) / (extkb + psi) &
+ + hh6 * (1. - s2/s1) / (extkb - psi)
+
+ ELSE
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = h1 / zmu2 * ( lsai + 1. / (2.*extkb) ) * s2 &
+ + albg(iw,2) / ce * ( - h1 / (2.*extkb) / zmu2 * &
+ ( p3*lsai + p4 / (2.*extkb) ) - de ) * s2 &
+ + albg(iw,1) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1./ce * ( h1*p4 / (4.*extkb*extkb) / zmu2 + de)
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,1) = - h1 / (2.*extkb*zmu2) + hh2 + hh3
+ tran(iw,1) = 1./ce * ( -h1/(2.*extkb*zmu2) * (p3*lsai + p4/(2.*extkb)) - de ) * s2 &
+ + hh5 * s1 + hh6 / s1
+
+ eup(iw,1) = (hh2 - h1/(2.*extkb*zmu2)) * (1. - s2*s2) / (2.*extkb) &
+ + hh3 * (lsai - 0.) &
+ + h1/(2.*extkb*zmu2) * ( lsai*s2*s2 - (1. - s2*s2)/(2.*extkb) )
+
+ edown(iw,1) = (hh5 - (h1*p4/(4.*extkb*extkb*zmu) + de)/ce) * (1. - s2*s2)/(2.*extkb) &
+ + hh6 * (lsai - 0.) &
+ + h1*p3/(ce*4.*extkb*extkb*zmu2) * (lsai*s2*s2 - (1. - s2*s2)/(2.*extkb) )
+
+ ENDIF
+
+ ssun(iw,1) = (1.-scat) * ( 1.-s2 + 1. / zmu * (eup(iw,1) + edown(iw,1)) )
+ ssha(iw,1) = scat * (1.-s2) &
+ + ( albg(iw,2)*tran(iw,1) + albg(iw,1)*s2 - tran(iw,1) ) - albv(iw,1) &
+ - ( 1. - scat ) / zmu * ( eup(iw,1) + edown(iw,1) )
+
+!-----------------------------------------------------------------------
+! calculation of diffuse albedos and canopy transmittances
+! albv(iw,2) ( i-up )
+! tran(iw,2) ( i-down )
+!-----------------------------------------------------------------------
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = 0.
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1.
+
+ hh7 = -m2 / (m1*n2 - m2*n1)
+ hh8 = -m1 / (m2*n1 - m1*n2)
+
+ hh9 = hh7 * p1 / ce
+ hh10 = hh8 * p2 / ce
+
+ albv(iw,2) = hh7 + hh8
+ tran(iw,2) = hh9 * s1 + hh10 / s1
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+ eup(iw,2) = hh7 * (1. - s1*s2) / (extkb + psi) &
+ + hh8 * (1. - s2/s1) / (extkb - psi)
+ edown(iw,2) = hh9 * (1. - s1*s2) / (extkb + psi) &
+ + hh10 * (1. - s2/s1) / (extkb - psi)
+ ELSE
+ eup(iw,2) = hh7 * (1. - s1*s2) / ( extkb + psi) + hh8 * (lsai - 0.)
+ edown(iw,2) = hh9 * (1. - s1*s2) / ( extkb + psi) + hh10 * (lsai - 0.)
+ ENDIF
+
+ ssun(iw,2) = (1.-scat) / zmu * (eup(iw,2) + edown(iw,2))
+ ssha(iw,2) = tran(iw,2) * ( albg(iw,2) -1. ) - ( albv(iw,2) - 1. ) &
+ - ( 1. - scat ) / zmu * ( eup(iw,2) + edown(iw,2) )
+
+ ENDDO ! WAVE_BAND_LOOP
+
+! 03/06/2020, yuan: add direct transmittance (s2) to
+! tran for incident direct case
+! 03/14/2020, yuan: save direct T to 3rd position of tran
+ tran(:,3) = s2
+
+ END SUBROUTINE twostream
+
+ SUBROUTINE twostream_hires ( chil, rho, tau, green, lai, sai, fwet_snow, &
+ coszen, albg, albv, tran, thermk, extkb, extkd, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! calculation of canopy albedos via two stream approximation (direct
+! and diffuse ) and partition of incident solar
+!
+! Original author: Yongjiu Dai, June 11, 2001
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ IMPLICIT NONE
+
+! parameters
+ real(r8), intent(in) :: &
+ ! static parameters associated with vegetation type
+ chil, &! leaf angle distribution factor
+ rho(211,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(211,2), &! leaf transmittance (iw=iband, il=life and dead)
+
+ ! time-space varying vegetation parameters
+ green, &! green leaf fraction
+ lai, &! leaf area index of exposed canopy (snow-free)
+ sai, &! stem area index
+ fwet_snow ! vegetation snow fractional cover [-]
+
+! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(211,2) ! albedos of ground
+
+! output
+ real(r8), intent(out) :: &
+ albv(211,2), &! albedo, vegetation [-]
+ tran(211,3), &! canopy transmittances for solar radiation
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ ssun(211,2), &! sunlit canopy absorption for solar radiation
+ ssha(211,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- local -----------------------------------
+ real(r8) :: &
+ lsai, &! lai+sai
+ sai_, &! sai=0 for USGS, no stem
+ phi1, &! (phi-1)
+ phi2, &! (phi-2)
+ scat, &! (omega)
+ proj, &! (g(mu))
+ zmu, &! (int(mu/g(mu))
+ zmu2, &! (zmu * zmu)
+ as, &! (a-s(mu))
+ upscat, &! (omega-beta)
+ beta0, &! (beta-0)
+ psi, &! (h)
+
+ be, &! (b)
+ ce, &! (c)
+ de, &! (d)
+ fe, &! (f)
+
+ power1, &! (h*lai)
+ power2, &! (k*lai)
+ power3, &!
+
+ sigma, &!
+ s1, &!
+ s2, &!
+ p1, &!
+ p2, &!
+ p3, &!
+ p4, &!
+ f1, &!
+ f2, &!
+ h1, &!
+ h4, &!
+ m1, &!
+ m2, &!
+ m3, &!
+ n1, &!
+ n2, &!
+ n3, &!
+
+ hh1, &! (h1/sigma)
+ hh2, &! (h2)
+ hh3, &! (h3)
+ hh4, &! (h4/sigma)
+ hh5, &! (h5)
+ hh6, &! (h6)
+ hh7, &! (h7)
+ hh8, &! (h8)
+ hh9, &! (h9)
+ hh10, &! (h10)
+
+ eup(211,2), &! (integral of i_up*exp(-kx) )
+ edown(211,2) ! (integral of i_down*exp(-kx) )
+
+ ! vegetation snow optical properties
+ real(r8) :: upscat_sno = 0.5 !upscat parameter for snow
+ real(r8) :: beta0_sno = 0.5 !beta0 parameter for snow
+ real(r8) :: scat_sno(2) !snow single scattering albedo
+ data scat_sno(1), scat_sno(2) /0.8, 0.4/ ! 1:vis, 2: nir
+
+ integer iw ! band iterator
+
+!-----------------------------------------------------------------------
+! projected area of phytoelements in direction of mu and
+! average inverse diffuse optical depth per unit leaf area
+
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ proj = phi1 + phi2 * coszen
+ extkb = proj / coszen
+
+ extkd = 0.719
+
+ IF (abs(phi1).gt.1.e-6 .and. abs(phi2).gt.1.e-6) THEN
+ zmu = 1. / phi2 * ( 1. - phi1 / phi2 * log ( ( phi1 + phi2 ) / phi1 ) )
+ ELSE IF (abs(phi1).le.1.e-6) THEN
+ zmu = 1./0.877
+ ELSE IF (abs(phi2).le.1.e-6) THEN
+ zmu = 1./(2.*phi1)
+ ENDIF
+ zmu2 = zmu * zmu
+
+#if(defined LULC_USGS)
+ ! yuan: to be consistance with CoLM2014, no stem considered
+ ! for twostream and leaf optical property calculations
+ sai_ = 0.
+#else
+ sai_ = sai
+#endif
+
+ lsai = lai + sai_
+ power3 = (lai+sai) / zmu
+ power3 = min( 50., power3 )
+ power3 = max( 1.e-5, power3 )
+ thermk = exp(-power3)
+
+ IF (lsai <= 1e-6) RETURN
+
+ DO iw = 1, 211 ! WAVE_BAND_LOOP ! loop from 1 to 211
+
+!-----------------------------------------------------------------------
+! calculate average scattering coefficient, leaf projection and
+! other coefficients for two-stream model.
+!-----------------------------------------------------------------------
+
+! account for stem optical property effects
+ scat = lai/lsai * ( tau(iw,1) + rho(iw,1) ) &
+ + sai_/lsai * ( tau(iw,2) + rho(iw,2) )
+
+ as = scat / 2. * proj / ( proj + coszen * phi2 )
+ as = as * ( 1. - coszen * phi1 / ( proj + coszen * phi2 ) * &
+ log ( ( proj + coszen * phi2 + coszen * phi1 ) / ( coszen * phi1 ) ) )
+
+! account for stem optical property effects
+ !TODO-done: betao -> beta0
+ upscat = lai/lsai*tau(iw,1) + sai_/lsai*tau(iw,2)
+ ! 09/12/2014, yuan: a bug, change 1. - chil -> 1. + chil
+ upscat = 0.5 * ( scat + (scat - 2.*upscat) * ((1. + chil) / 2.) ** 2 )
+ beta0 = ( 1. + zmu * extkb ) / ( scat * zmu * extkb ) * as
+
+! account for snow on vegetation
+ ! modify scat, upscat and beta0
+ ! USE: fwet_snow, snow properties, scatter vis0.8, nir0.4, upscat0.5, beta0.5
+ IF ( DEF_VEG_SNOW ) THEN
+ scat = (1.-fwet_snow)*scat + fwet_snow*scat_sno(iw)
+ upscat = ( (1.-fwet_snow)*scat*upscat + fwet_snow*scat_sno(iw)*upscat_sno ) / scat
+ beta0 = ( (1.-fwet_snow)*scat*beta0 + fwet_snow*scat_sno(iw)*beta0_sno ) / scat
+ ENDIF
+
+!-----------------------------------------------------------------------
+! intermediate variables identified in appendix of SE-85.
+!-----------------------------------------------------------------------
+
+ be = 1. - scat + upscat
+ ce = upscat
+ de = scat * zmu * extkb * beta0
+ fe = scat * zmu * extkb * ( 1. - beta0 )
+
+ psi = sqrt(be**2 - ce**2)/zmu
+ power1 = min( psi*lsai, 50. )
+ power2 = min( extkb*lsai, 50. )
+ s1 = exp( - power1 )
+ s2 = exp( - power2 )
+
+!-----------------------------------------------------------------------
+! calculation of direct albedos and canopy transmittances.
+! albv(iw,1) ( i-up )
+! tran(iw,irad) ( i-down )
+!-----------------------------------------------------------------------
+
+ p1 = be + zmu * psi
+ p2 = be - zmu * psi
+ p3 = be + zmu * extkb
+ p4 = be - zmu * extkb
+
+ f1 = 1. - albg(iw,2)*p1/ce
+ f2 = 1. - albg(iw,2)*p2/ce
+
+ h1 = - ( de * p4 + ce * fe )
+ h4 = - ( fe * p3 + ce * de )
+
+ sigma = ( zmu * extkb ) ** 2 + ( ce**2 - be**2 )
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+
+ hh1 = h1 / sigma
+ hh4 = h4 / sigma
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = ( albg(iw,1) - ( hh1 - albg(iw,2) * hh4 ) ) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = - hh4
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,1) = hh1 + hh2 + hh3
+ tran(iw,1) = hh4 * s2 + hh5 * s1 + hh6 / s1
+
+ eup(iw,1) = hh1 * (1. - s2*s2) / (2.*extkb) &
+ + hh2 * (1. - s1*s2) / (extkb + psi) &
+ + hh3 * (1. - s2/s1) / (extkb - psi)
+
+ edown(iw,1) = hh4 * (1. - s2*s2) / (2.*extkb) &
+ + hh5 * (1. - s1*s2) / (extkb + psi) &
+ + hh6 * (1. - s2/s1) / (extkb - psi)
+
+ ELSE
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = h1 / zmu2 * ( lsai + 1. / (2.*extkb) ) * s2 &
+ + albg(iw,2) / ce * ( - h1 / (2.*extkb) / zmu2 * &
+ ( p3*lsai + p4 / (2.*extkb) ) - de ) * s2 &
+ + albg(iw,1) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1./ce * ( h1*p4 / (4.*extkb*extkb) / zmu2 + de)
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,1) = - h1 / (2.*extkb*zmu2) + hh2 + hh3
+ tran(iw,1) = 1./ce * ( -h1/(2.*extkb*zmu2) * (p3*lsai + p4/(2.*extkb)) - de ) * s2 &
+ + hh5 * s1 + hh6 / s1
+
+ eup(iw,1) = (hh2 - h1/(2.*extkb*zmu2)) * (1. - s2*s2) / (2.*extkb) &
+ + hh3 * (lsai - 0.) &
+ + h1/(2.*extkb*zmu2) * ( lsai*s2*s2 - (1. - s2*s2)/(2.*extkb) )
+
+ edown(iw,1) = (hh5 - (h1*p4/(4.*extkb*extkb*zmu) + de)/ce) * (1. - s2*s2)/(2.*extkb) &
+ + hh6 * (lsai - 0.) &
+ + h1*p3/(ce*4.*extkb*extkb*zmu2) * (lsai*s2*s2 - (1. - s2*s2)/(2.*extkb) )
+
+ ENDIF
+
+ ssun(iw,1) = (1.-scat) * ( 1.-s2 + 1. / zmu * (eup(iw,1) + edown(iw,1)) )
+ ssha(iw,1) = scat * (1.-s2) &
+ + ( albg(iw,2)*tran(iw,1) + albg(iw,1)*s2 - tran(iw,1) ) - albv(iw,1) &
+ - ( 1. - scat ) / zmu * ( eup(iw,1) + edown(iw,1) )
+
+!-----------------------------------------------------------------------
+! calculation of diffuse albedos and canopy transmittances
+! albv(iw,2) ( i-up )
+! tran(iw,2) ( i-down )
+!-----------------------------------------------------------------------
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = 0.
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1.
+
+ hh7 = -m2 / (m1*n2 - m2*n1)
+ hh8 = -m1 / (m2*n1 - m1*n2)
+
+ hh9 = hh7 * p1 / ce
+ hh10 = hh8 * p2 / ce
+
+ albv(iw,2) = hh7 + hh8
+ tran(iw,2) = hh9 * s1 + hh10 / s1
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+ eup(iw,2) = hh7 * (1. - s1*s2) / (extkb + psi) &
+ + hh8 * (1. - s2/s1) / (extkb - psi)
+ edown(iw,2) = hh9 * (1. - s1*s2) / (extkb + psi) &
+ + hh10 * (1. - s2/s1) / (extkb - psi)
+ ELSE
+ eup(iw,2) = hh7 * (1. - s1*s2) / ( extkb + psi) + hh8 * (lsai - 0.)
+ edown(iw,2) = hh9 * (1. - s1*s2) / ( extkb + psi) + hh10 * (lsai - 0.)
+ ENDIF
+
+ ssun(iw,2) = (1.-scat) / zmu * (eup(iw,2) + edown(iw,2))
+ ssha(iw,2) = tran(iw,2) * ( albg(iw,2) -1. ) - ( albv(iw,2) - 1. ) &
+ - ( 1. - scat ) / zmu * ( eup(iw,2) + edown(iw,2) )
+
+ ENDDO ! WAVE_BAND_LOOP
+
+! 03/06/2020, yuan: add direct transmittance (s2) to
+! tran for incident direct case
+! 03/14/2020, yuan: save direct T to 3rd position of tran
+ tran(:,3) = s2
+
+ END SUBROUTINE twostream_hires
+
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ SUBROUTINE twostream_mod ( chil, rho, tau, green, lai, sai, fwet_snow, &
+ coszen, albg, albv, tran, thermk, extkb, extkd, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! An improved two stream approximation
+!
+! Original author: Yongjiu Dai, June 11, 2001
+! Hua Yuan, 03/2020
+!
+! REFERENCES:
+! 1) Yuan, H., Dai, Y., Dickinson, R. E., Pinty, B., Shangguan, W., Zhang, S.,
+! et al. (2017). Reexamination and further development of two-stream canopy
+! radiative transfer models for global land modeling. Journal of Advances in
+! Modeling Earth Systems, 9(1), 113–129. https://doi.org/10.1002/2016MS000773
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ IMPLICIT NONE
+
+! parameters
+ real(r8), intent(in) :: &
+ ! static parameters associated with vegetation type
+ chil, &! leaf angle distribution factor
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+
+ ! time-space varying vegetation parameters
+ green, &! green leaf fraction
+ lai, &! leaf area index of exposed canopy (snow-free)
+ sai, &! stem area index
+ fwet_snow ! vegetation snow fractional cover [-]
+
+! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(2,2) ! albedos of ground
+
+! output
+ real(r8), intent(out) :: &
+ albv(2,2), &! albedo, vegetation [-]
+ tran(2,3), &! canopy transmittances for solar radiation
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- local -----------------------------------
+ real(r8) :: &
+ lsai, &! lai+sai
+ phi1, &! (phi-1)
+ phi2, &! (phi-2)
+ scat, &! (omega)
+ proj, &! (g(mu))
+ zmu, &! (int(mu/g(mu))
+ zmu2, &! (zmu * zmu)
+ as, &! (a-s(mu))
+ upscat, &! (omega-beta)
+ beta0, &! (beta-0)
+ psi, &! (h)
+
+ be, &! (b)
+ ce, &! (c)
+ de, &! (d)
+ fe, &! (f)
+
+ power1, &! (h*lai)
+ power2, &! (k*lai)
+ power3, &!
+
+ sigma, &!
+ s1, &!
+ s2, &!
+ p1, &!
+ p2, &!
+ p3, &!
+ p4, &!
+ f1, &!
+ f2, &!
+ h1, &!
+ h4, &!
+ m1, &!
+ m2, &!
+ m3, &!
+ n1, &!
+ n2, &!
+ n3, &!
+
+ hh1, &! (h1/sigma)
+ hh2, &! (h2)
+ hh3, &! (h3)
+ hh4, &! (h4/sigma)
+ hh5, &! (h5)
+ hh6, &! (h6)
+ hh7, &! (h7)
+ hh8, &! (h8)
+ hh9, &! (h9)
+ hh10, &! (h10)
+
+ eup, &! (integral of i_up*exp(-kx) )
+ edw ! (integral of i_down*exp(-kx) )
+
+ ! vegetation snow optical properties
+ real(r8) :: upscat_sno = 0.5 !upscat parameter for snow
+ real(r8) :: beta0_sno = 0.5 !beta0 parameter for snow
+ real(r8) :: scat_sno(2) !snow single scattering albedo
+ data scat_sno(1), scat_sno(2) /0.8, 0.4/ ! 1:vis, 2: nir
+
+ integer iw ! band loop index
+ integer ic ! direct/diffuse loop index
+
+ ! variables for modified version
+ real(r8) :: cosz, theta, cosdif, albgblk
+ real(r8) :: tmptau, wrho, wtau
+ real(r8) :: s2d, extkbd, sall(2,2), q, ssun_rev
+
+!-----------------------------------------------------------------------
+! projected area of phytoelements in direction of mu and
+! average inverse diffuse optical depth per unit leaf area
+
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ extkd = 0.719
+
+ IF (abs(phi1).gt.1.e-6 .and. abs(phi2).gt.1.e-6) THEN
+ zmu = 1. / phi2 * ( 1. - phi1 / phi2 * log ( ( phi1 + phi2 ) / phi1 ) )
+ ELSE IF (abs(phi1).le.1.e-6) THEN
+ zmu = 1./0.877
+ ELSE IF (abs(phi2).le.1.e-6) THEN
+ zmu = 1./(2.*phi1)
+ ENDIF
+ zmu2 = zmu * zmu
+
+ lsai = lai + sai
+ power3 = lsai / zmu
+ power3 = min( 50., power3 )
+ power3 = max( 1.e-5, power3 )
+ thermk = exp(-power3)
+
+ tmptau = 0.5_r8 * lsai
+ cosdif = - tmptau / log(exp(-0.87_r8*tmptau) / (1+0.92_r8*tmptau))
+
+ ! black ground case
+ albgblk = 1.e-6_r8
+
+ DO iw = 1, 2 ! WAVE_BAND_LOOP
+
+ ! ic 1: incident direct; 2: incident diffuse
+ DO ic = 1, 2
+
+ IF (ic == 2) THEN
+ cosz = max(0.001_r8, cosdif)
+ theta = acos(cosz)
+ theta = theta/3.14159*180
+
+ theta = theta + chil*5._r8
+ cosz = cos(theta/180*3.14159)
+ ELSE
+ cosz = coszen
+ ENDIF
+
+ proj = phi1 + phi2 * cosz
+ extkb = proj / cosz
+
+!-----------------------------------------------------------------------
+! calculate average scattering coefficient, leaf projection and
+! other coefficients for two-stream model.
+!-----------------------------------------------------------------------
+
+! + stem optical properties
+ wtau = lai/lsai*tau(iw,1) + sai/lsai*tau(iw,2)
+ wrho = lai/lsai*rho(iw,1) + sai/lsai*rho(iw,2)
+
+ scat = wtau + wrho
+
+ as = scat / 2. * proj / ( proj + cosz * phi2 )
+ as = as * ( 1. - cosz * phi1 / ( proj + cosz * phi2 ) * &
+ log ( ( proj + cosz * phi2 + cosz * phi1 ) / ( cosz * phi1 ) ) )
+
+! + stem optical properties
+ ! scat ~ omega
+ ! upscat ~ betail*scat
+ ! beta0 ~ betadl
+ ! scat-2.*upscat ~ rho - tau
+ upscat = lai/lsai*tau(iw,1) + sai/lsai*tau(iw,2)
+ upscat = 0.5 * ( scat + (scat - 2.*upscat) * ((1. + chil) / 2.) ** 2 )
+ beta0 = ( 1. + zmu * extkb ) / ( scat * zmu * extkb ) * as
+
+ ! [MODI 1]
+ beta0 = 0.5_r8 * ( scat + 1._r8/extkb*(1._r8+chil)**2/4._r8*(wrho-wtau) )/scat
+
+! account for snow on vegetation
+ ! modify scat, upscat and beta0
+ ! USE: fwet_snow, snow properties, scatter vis0.8, nir0.4, upscat0.5, beta0.5
+ IF ( DEF_VEG_SNOW ) THEN
+ scat = (1.-fwet_snow)*scat + fwet_snow*scat_sno(iw)
+ upscat = ( (1.-fwet_snow)*scat*upscat + fwet_snow*scat_sno(iw)*upscat_sno ) / scat
+ beta0 = ( (1.-fwet_snow)*scat*beta0 + fwet_snow*scat_sno(iw)*beta0_sno ) / scat
+ ENDIF
+
+!-----------------------------------------------------------------------
+! intermediate variables identified in appendix of SE-85.
+!-----------------------------------------------------------------------
+
+ be = 1. - scat + upscat
+ ce = upscat
+ de = scat * zmu * extkb * beta0
+ fe = scat * zmu * extkb * ( 1. - beta0 )
+
+ psi = sqrt(be**2 - ce**2)/zmu
+ power1 = min( psi*lsai, 50. )
+ power2 = min( extkb*lsai, 50. )
+ s1 = exp( - power1 )
+ s2 = exp( - power2 )
+
+!-----------------------------------------------------------------------
+! calculation of direct albedos and canopy transmittances.
+! albv(iw,1) ( i-up )
+! tran(iw,irad) ( i-down )
+!-----------------------------------------------------------------------
+
+ p1 = be + zmu * psi
+ p2 = be - zmu * psi
+ p3 = be + zmu * extkb
+ p4 = be - zmu * extkb
+
+ f1 = 1. - albgblk*p1/ce
+ f2 = 1. - albgblk*p2/ce
+
+ h1 = - ( de * p4 + ce * fe )
+ h4 = - ( fe * p3 + ce * de )
+
+ sigma = ( zmu * extkb ) ** 2 + ( ce**2 - be**2 )
+
+ IF (ic == 1) THEN
+ s2d = s2
+ extkbd = extkb
+ ENDIF
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+
+ hh1 = h1 / sigma
+ hh4 = h4 / sigma
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = ( albgblk - ( hh1 - albgblk * hh4 ) ) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = - hh4
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,ic) = hh1 + hh2 + hh3
+ tran(iw,ic) = hh4 * s2 + hh5 * s1 + hh6 / s1
+
+ eup = hh1 * (1. - s2*s2d) / (extkbd + extkb) &
+ + hh2 * (1. - s2d*s1) / (extkbd + psi) &
+ + hh3 * (1. - s2d/s1) / (extkbd - psi)
+
+ edw = hh4 * (1. - s2*s2d) / (extkbd + extkb) &
+ + hh5 * (1. - s2d*s1) / (extkbd + psi) &
+ + hh6 * (1. - s2d/s1) / (extkbd - psi)
+
+ ELSE
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = h1 / zmu2 * ( lsai + 1. / (extkb+extkbd) ) * s2 &
+ + albgblk / ce * ( - h1 / (extkb+extkbd) / zmu2 * &
+ ( p3*lsai + p4 / (extkb+extkbd) ) - de ) * s2 &
+ + albgblk * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1./ce * ( h1*p4 / ((extkb+extkbd)*(extkb+extkbd)) / zmu2 + de)
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,ic) = - h1 / ((extkb+extkbd)*zmu2) + hh2 + hh3
+ tran(iw,ic) = 1./ce * ( -h1 / ((extkb+extkbd)*zmu2) * &
+ ( p3*lsai + p4 / (extkb+extkbd) ) - de ) * s2 &
+ + hh5 * s1 + hh6 / s1
+
+ eup = (hh2 - h1/((extkb+extkbd)*zmu2)) * (1. - s2*s2d)/(extkb+extkbd) &
+ + hh3 * (lsai - 0.) &
+ + h1/((extkb+extkbd)*zmu2) * ( lsai*s2*s2d - (1. - s2*s2d)/(extkb+extkbd) )
+
+ edw = (hh5 - (h1*p4/((extkb+extkbd)*(extkb+extkbd)*zmu) + de)/ce) * &
+ (1. - s2*s2d) / (extkb+extkbd) + hh6 * (lsai - 0.) &
+ + h1*p3/(ce*(extkb+extkbd)*(extkb+extkbd)*zmu2) * &
+ ( lsai*s2*s2d - (1. - s2*s2d)/(extkb+extkbd) )
+
+ ENDIF
+
+ sall(iw,ic) = 1. - albv(iw,ic) - (1.-albgblk)*(tran(iw,ic)+s2)
+
+ IF (ic == 1) THEN
+ ssun(iw,ic) = (1.-scat) * ( 1.-s2 + 1. / zmu * (eup + edw) )
+ ELSE
+ ssun(iw,ic) = (1.-scat) * ( extkb*(1.-s2*s2d)/(extkb+extkbd) + 1. / zmu * (eup + edw) )
+ ENDIF
+
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+
+ ENDDO ! ic
+
+ ! for reversed diffuse radiation back from ground
+ eup = hh1 * (1._r8 - s2/s2d) / (extkb - extkbd) &
+ + hh2 * (1._r8 - s1/s2d) / (psi - extkbd) &
+ + hh3 * (1._r8/s1/s2d - 1._r8) / (psi + extkbd)
+
+ edw = hh4 * (1._r8 - s2/s2d) / (extkb - extkbd) &
+ + hh5 * (1._r8 - s1/s2d) / (psi - extkbd) &
+ + hh6 * (1._r8/s1/s2d - 1._r8) / (psi + extkbd)
+
+ ssun_rev = s2d * (1._r8 - scat) * &
+ ( extkb*(1._r8-s2/s2d)/(extkb-extkbd) + 1._r8 / zmu * (eup + edw ) )
+
+ ! -----------------------------------------------------------
+ ! consider the multiple reflectance between canopy and ground
+ ! -----------------------------------------------------------
+
+ ! common ratio for geometric series
+ q = albg(iw,2) * albv(iw,2)
+
+ DO ic = 1, 2 ! from 1 to 2, cannot be reversed
+
+ ! -----------------------------------------------------------
+ ! re-calculate the absorption, transmission and albedo
+ ! for direct radiation
+
+! 03/06/2020, yuan: tran originally meant diffuse flow, now the direct
+! transmittance is also included
+! 03/14/2020, yuan: treat soil albedo in direct/diffuse cases
+ IF (ic == 1) THEN
+ tran(iw,ic) = (s2d*albg(iw,1)*albv(iw,2) + tran(iw,ic)) / (1.-q)
+ tran(:,3) = s2d
+
+ sall(iw,ic) = sall(iw,ic) + &
+ (tran(iw,ic)*albg(iw,2) + s2d*albg(iw,1)) * sall(iw,2)
+
+ albv(iw,ic) = 1. - sall(iw,ic) - &
+ (1.-albg(iw,2))*tran(iw,ic) - (1.-albg(iw,1))*s2d
+
+ ssun(iw,ic) = ssun(iw,ic) + &
+ (tran(iw,ic)*albg(iw,2) + s2d*albg(iw,1)) * ssun_rev
+
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+
+ ELSE
+ tran(iw,ic) = (s2 + tran(iw,ic)) / (1.-q)
+
+ sall(iw,ic) = sall(iw,ic) + tran(iw,ic)*albg(iw,2)*sall(iw,2)
+ albv(iw,ic) = 1. - sall(iw,ic) - (1.-albg(iw,2))*tran(iw,ic)
+
+ ssun(iw,ic) = ssun(iw,ic) + tran(iw,ic)*albg(iw,2)*ssun_rev
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+ ENDIF
+
+ ENDDO !ic
+
+ End DO !iw
+
+ ! restore extkb
+ extkb = extkbd
+
+ END SUBROUTINE twostream_mod
+
+
+ SUBROUTINE twostream_hires_mod ( chil, rho, tau, green, lai, sai, fwet_snow, &
+ coszen, albg, albv, tran, thermk, extkb, extkd, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! An improved two stream approximation
+!
+! Original author: Yongjiu Dai, June 11, 2001
+! Hua Yuan, 03/2020
+!
+! REFERENCES:
+! 1) Yuan, H., Dai, Y., Dickinson, R. E., Pinty, B., Shangguan, W., Zhang, S.,
+! et al. (2017). Reexamination and further development of two-stream canopy
+! radiative transfer models for global land modeling. Journal of Advances in
+! Modeling Earth Systems, 9(1), 113–129. https://doi.org/10.1002/2016MS000773
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ IMPLICIT NONE
+
+! parameters
+ real(r8), intent(in) :: &
+ ! static parameters associated with vegetation type
+ chil, &! leaf angle distribution factor
+ rho(211,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(211,2), &! leaf transmittance (iw=iband, il=life and dead)
+
+ ! time-space varying vegetation parameters
+ green, &! green leaf fraction
+ lai, &! leaf area index of exposed canopy (snow-free)
+ sai, &! stem area index
+ fwet_snow ! vegetation snow fractional cover [-]
+
+! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(211,2) ! albedos of ground
+
+! output
+ real(r8), intent(out) :: &
+ albv(211,2), &! albedo, vegetation [-]
+ tran(211,3), &! canopy transmittances for solar radiation
+ thermk, &! canopy gap fraction for tir radiation
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ ssun(211,2), &! sunlit canopy absorption for solar radiation
+ ssha(211,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+!-------------------------- local -----------------------------------
+ real(r8) :: &
+ lsai, &! lai+sai
+ phi1, &! (phi-1)
+ phi2, &! (phi-2)
+ scat, &! (omega)
+ proj, &! (g(mu))
+ zmu, &! (int(mu/g(mu))
+ zmu2, &! (zmu * zmu)
+ as, &! (a-s(mu))
+ upscat, &! (omega-beta)
+ beta0, &! (beta-0)
+ psi, &! (h)
+
+ be, &! (b)
+ ce, &! (c)
+ de, &! (d)
+ fe, &! (f)
+
+ power1, &! (h*lai)
+ power2, &! (k*lai)
+ power3, &!
+
+ sigma, &!
+ s1, &!
+ s2, &!
+ p1, &!
+ p2, &!
+ p3, &!
+ p4, &!
+ f1, &!
+ f2, &!
+ h1, &!
+ h4, &!
+ m1, &!
+ m2, &!
+ m3, &!
+ n1, &!
+ n2, &!
+ n3, &!
+
+ hh1, &! (h1/sigma)
+ hh2, &! (h2)
+ hh3, &! (h3)
+ hh4, &! (h4/sigma)
+ hh5, &! (h5)
+ hh6, &! (h6)
+ hh7, &! (h7)
+ hh8, &! (h8)
+ hh9, &! (h9)
+ hh10, &! (h10)
+
+ eup, &! (integral of i_up*exp(-kx) )
+ edw ! (integral of i_down*exp(-kx) )
+
+ ! vegetation snow optical properties
+ real(r8) :: upscat_sno = 0.5 !upscat parameter for snow
+ real(r8) :: beta0_sno = 0.5 !beta0 parameter for snow
+ real(r8) :: scat_sno(2) !snow single scattering albedo
+ data scat_sno(1), scat_sno(2) /0.8, 0.4/ ! 1:vis, 2: nir
+ real(r8) :: scat_sno_tmp
+
+ integer iw ! band loop index
+ integer ic ! direct/diffuse loop index
+
+ ! variables for modified version
+ real(r8) :: cosz, theta, cosdif, albgblk
+ real(r8) :: tmptau, wrho, wtau
+ real(r8) :: s2d, extkbd, sall(211,2), q, ssun_rev
+
+!-----------------------------------------------------------------------
+! projected area of phytoelements in direction of mu and
+! average inverse diffuse optical depth per unit leaf area
+
+ phi1 = 0.5 - 0.633 * chil - 0.33 * chil * chil
+ phi2 = 0.877 * ( 1. - 2. * phi1 )
+
+ extkd = 0.719
+
+ IF (abs(phi1).gt.1.e-6 .and. abs(phi2).gt.1.e-6) THEN
+ zmu = 1. / phi2 * ( 1. - phi1 / phi2 * log ( ( phi1 + phi2 ) / phi1 ) )
+ ELSE IF (abs(phi1).le.1.e-6) THEN
+ zmu = 1./0.877
+ ELSE IF (abs(phi2).le.1.e-6) THEN
+ zmu = 1./(2.*phi1)
+ ENDIF
+ zmu2 = zmu * zmu
+
+ lsai = lai + sai
+ power3 = lsai / zmu
+ power3 = min( 50., power3 )
+ power3 = max( 1.e-5, power3 )
+ thermk = exp(-power3)
+
+ tmptau = 0.5_r8 * lsai
+ cosdif = - tmptau / log(exp(-0.87_r8*tmptau) / (1+0.92_r8*tmptau))
+
+ ! black ground case
+ albgblk = 1.e-6_r8
+
+ DO iw = 1, 211 ! WAVE_BAND_LOOP
+
+ ! ic 1: incident direct; 2: incident diffuse
+ DO ic = 1, 2
+
+ IF (ic == 2) THEN
+ cosz = max(0.001_r8, cosdif)
+ theta = acos(cosz)
+ theta = theta/3.14159*180
+
+ theta = theta + chil*5._r8
+ cosz = cos(theta/180*3.14159)
+ ELSE
+ cosz = coszen
+ ENDIF
+
+ proj = phi1 + phi2 * cosz
+ extkb = proj / cosz
+
+!-----------------------------------------------------------------------
+! calculate average scattering coefficient, leaf projection and
+! other coefficients for two-stream model.
+!-----------------------------------------------------------------------
+
+! + stem optical properties
+ wtau = lai/lsai*tau(iw,1) + sai/lsai*tau(iw,2)
+ wrho = lai/lsai*rho(iw,1) + sai/lsai*rho(iw,2)
+
+ scat = wtau + wrho
+
+ as = scat / 2. * proj / ( proj + cosz * phi2 )
+ as = as * ( 1. - cosz * phi1 / ( proj + cosz * phi2 ) * &
+ log ( ( proj + cosz * phi2 + cosz * phi1 ) / ( cosz * phi1 ) ) )
+
+! + stem optical properties
+ ! scat ~ omega
+ ! upscat ~ betail*scat
+ ! beta0 ~ betadl
+ ! scat-2.*upscat ~ rho - tau
+ upscat = lai/lsai*tau(iw,1) + sai/lsai*tau(iw,2)
+ upscat = 0.5 * ( scat + (scat - 2.*upscat) * ((1. + chil) / 2.) ** 2 )
+ beta0 = ( 1. + zmu * extkb ) / ( scat * zmu * extkb ) * as
+
+ ! [MODI 1]
+ beta0 = 0.5_r8 * ( scat + 1._r8/extkb*(1._r8+chil)**2/4._r8*(wrho-wtau) )/scat
+
+! account for snow on vegetation
+ ! modify scat, upscat and beta0
+ ! USE: fwet_snow, snow properties, scatter vis0.8, nir0.4, upscat0.5, beta0.5
+ IF ( DEF_VEG_SNOW ) THEN
+ if (iw < 30) then
+ scat_sno_tmp = scat_sno(1)
+ else
+ scat_sno_tmp = scat_sno(2)
+ end if
+ scat = (1.-fwet_snow)*scat + fwet_snow*scat_sno_tmp
+ upscat = ( (1.-fwet_snow)*scat*upscat + fwet_snow*scat_sno_tmp*upscat_sno ) / scat
+ beta0 = ( (1.-fwet_snow)*scat*beta0 + fwet_snow*scat_sno_tmp*beta0_sno ) / scat
+ ENDIF
+
+!-----------------------------------------------------------------------
+! intermediate variables identified in appendix of SE-85.
+!-----------------------------------------------------------------------
+
+ be = 1. - scat + upscat
+ ce = upscat
+ de = scat * zmu * extkb * beta0
+ fe = scat * zmu * extkb * ( 1. - beta0 )
+
+ psi = sqrt(be**2 - ce**2)/zmu
+ power1 = min( psi*lsai, 50. )
+ power2 = min( extkb*lsai, 50. )
+ s1 = exp( - power1 )
+ s2 = exp( - power2 )
+
+!-----------------------------------------------------------------------
+! calculation of direct albedos and canopy transmittances.
+! albv(iw,1) ( i-up )
+! tran(iw,irad) ( i-down )
+!-----------------------------------------------------------------------
+
+ p1 = be + zmu * psi
+ p2 = be - zmu * psi
+ p3 = be + zmu * extkb
+ p4 = be - zmu * extkb
+
+ f1 = 1. - albgblk*p1/ce
+ f2 = 1. - albgblk*p2/ce
+
+ h1 = - ( de * p4 + ce * fe )
+ h4 = - ( fe * p3 + ce * de )
+
+ sigma = ( zmu * extkb ) ** 2 + ( ce**2 - be**2 )
+
+ IF (ic == 1) THEN
+ s2d = s2
+ extkbd = extkb
+ ENDIF
+
+ IF (abs(sigma) .gt. 1.e-10) THEN
+
+ hh1 = h1 / sigma
+ hh4 = h4 / sigma
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = ( albgblk - ( hh1 - albgblk * hh4 ) ) * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = - hh4
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,ic) = hh1 + hh2 + hh3
+ tran(iw,ic) = hh4 * s2 + hh5 * s1 + hh6 / s1
+
+ eup = hh1 * (1. - s2*s2d) / (extkbd + extkb) &
+ + hh2 * (1. - s2d*s1) / (extkbd + psi) &
+ + hh3 * (1. - s2d/s1) / (extkbd - psi)
+
+ edw = hh4 * (1. - s2*s2d) / (extkbd + extkb) &
+ + hh5 * (1. - s2d*s1) / (extkbd + psi) &
+ + hh6 * (1. - s2d/s1) / (extkbd - psi)
+
+ ELSE
+
+ m1 = f1 * s1
+ m2 = f2 / s1
+ m3 = h1 / zmu2 * ( lsai + 1. / (extkb+extkbd) ) * s2 &
+ + albgblk / ce * ( - h1 / (extkb+extkbd) / zmu2 * &
+ ( p3*lsai + p4 / (extkb+extkbd) ) - de ) * s2 &
+ + albgblk * s2
+
+ n1 = p1 / ce
+ n2 = p2 / ce
+ n3 = 1./ce * ( h1*p4 / ((extkb+extkbd)*(extkb+extkbd)) / zmu2 + de)
+
+ hh2 = (m3*n2 - m2*n3) / (m1*n2 - m2*n1)
+ hh3 = (m3*n1 - m1*n3) / (m2*n1 - m1*n2)
+
+ hh5 = hh2 * p1 / ce
+ hh6 = hh3 * p2 / ce
+
+ albv(iw,ic) = - h1 / ((extkb+extkbd)*zmu2) + hh2 + hh3
+ tran(iw,ic) = 1./ce * ( -h1 / ((extkb+extkbd)*zmu2) * &
+ ( p3*lsai + p4 / (extkb+extkbd) ) - de ) * s2 &
+ + hh5 * s1 + hh6 / s1
+
+ eup = (hh2 - h1/((extkb+extkbd)*zmu2)) * (1. - s2*s2d)/(extkb+extkbd) &
+ + hh3 * (lsai - 0.) &
+ + h1/((extkb+extkbd)*zmu2) * ( lsai*s2*s2d - (1. - s2*s2d)/(extkb+extkbd) )
+
+ edw = (hh5 - (h1*p4/((extkb+extkbd)*(extkb+extkbd)*zmu) + de)/ce) * &
+ (1. - s2*s2d) / (extkb+extkbd) + hh6 * (lsai - 0.) &
+ + h1*p3/(ce*(extkb+extkbd)*(extkb+extkbd)*zmu2) * &
+ ( lsai*s2*s2d - (1. - s2*s2d)/(extkb+extkbd) )
+
+ ENDIF
+
+ sall(iw,ic) = 1. - albv(iw,ic) - (1.-albgblk)*(tran(iw,ic)+s2)
+
+ IF (ic == 1) THEN
+ ssun(iw,ic) = (1.-scat) * ( 1.-s2 + 1. / zmu * (eup + edw) )
+ ELSE
+ ssun(iw,ic) = (1.-scat) * ( extkb*(1.-s2*s2d)/(extkb+extkbd) + 1. / zmu * (eup + edw) )
+ ENDIF
+
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+
+ ENDDO ! ic
+
+ ! for reversed diffuse radiation back from ground
+ eup = hh1 * (1._r8 - s2/s2d) / (extkb - extkbd) &
+ + hh2 * (1._r8 - s1/s2d) / (psi - extkbd) &
+ + hh3 * (1._r8/s1/s2d - 1._r8) / (psi + extkbd)
+
+ edw = hh4 * (1._r8 - s2/s2d) / (extkb - extkbd) &
+ + hh5 * (1._r8 - s1/s2d) / (psi - extkbd) &
+ + hh6 * (1._r8/s1/s2d - 1._r8) / (psi + extkbd)
+
+ ssun_rev = s2d * (1._r8 - scat) * &
+ ( extkb*(1._r8-s2/s2d)/(extkb-extkbd) + 1._r8 / zmu * (eup + edw ) )
+
+ ! -----------------------------------------------------------
+ ! consider the multiple reflectance between canopy and ground
+ ! -----------------------------------------------------------
+
+ ! common ratio for geometric series
+ q = albg(iw,2) * albv(iw,2)
+
+ DO ic = 1, 2 ! from 1 to 2, cannot be reversed
+
+ ! -----------------------------------------------------------
+ ! re-calculate the absorption, transmission and albedo
+ ! for direct radiation
+
+! 03/06/2020, yuan: tran originally meant diffuse flow, now the direct
+! transmittance is also included
+! 03/14/2020, yuan: treat soil albedo in direct/diffuse cases
+ IF (ic == 1) THEN
+ tran(iw,ic) = (s2d*albg(iw,1)*albv(iw,2) + tran(iw,ic)) / (1.-q)
+ tran(:,3) = s2d
+
+ sall(iw,ic) = sall(iw,ic) + &
+ (tran(iw,ic)*albg(iw,2) + s2d*albg(iw,1)) * sall(iw,2)
+
+ albv(iw,ic) = 1. - sall(iw,ic) - &
+ (1.-albg(iw,2))*tran(iw,ic) - (1.-albg(iw,1))*s2d
+
+ ssun(iw,ic) = ssun(iw,ic) + &
+ (tran(iw,ic)*albg(iw,2) + s2d*albg(iw,1)) * ssun_rev
+
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+
+ ELSE
+ tran(iw,ic) = (s2 + tran(iw,ic)) / (1.-q)
+
+ sall(iw,ic) = sall(iw,ic) + tran(iw,ic)*albg(iw,2)*sall(iw,2)
+ albv(iw,ic) = 1. - sall(iw,ic) - (1.-albg(iw,2))*tran(iw,ic)
+
+ ssun(iw,ic) = ssun(iw,ic) + tran(iw,ic)*albg(iw,2)*ssun_rev
+ ssha(iw,ic) = sall(iw,ic) - ssun(iw,ic)
+ ENDIF
+
+ ENDDO !ic
+
+ End DO !iw
+
+ ! restore extkb
+ extkb = extkbd
+
+ END SUBROUTINE twostream_hires_mod
+#endif
+
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ SUBROUTINE twostream_wrap ( ipatch, coszen, albg, &
+ albv, tran, ssun, ssha )
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! A Wrap subroutine to calculate PFT radiation using two-stream model
+!
+! Created by Hua Yuan, 03/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_LandPFT
+ USE MOD_Const_PFT
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ IMPLICIT NONE
+
+ ! parameters
+ integer, intent(in) :: &
+ ipatch ! patch index
+
+ ! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(2,2) ! albedos of ground
+
+ ! output
+ real(r8), intent(out) :: &
+ albv(2,2), &! albedo, vegetation [-]
+ tran(2,3), &! canopy transmittances for solar radiation
+ ssun(2,2), &! sunlit canopy absorption for solar radiation
+ ssha(2,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+ integer :: i, p, ps, pe
+ real(r8), allocatable :: tran_p(:,:,:)
+ real(r8), allocatable :: albv_p(:,:,:)
+
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ allocate ( tran_p (2,3,ps:pe) )
+ allocate ( albv_p (2,2,ps:pe) )
+
+ DO i = ps, pe
+ p = pftclass(i)
+ IF (lai_p(i)+sai_p(i) > 1.e-6) THEN
+ CALL twostream_mod (chil_p(p),rho_p(:,:,p),tau_p(:,:,p),1.,lai_p(i),sai_p(i),&
+ fwet_snow_p(i),coszen,albg,albv_p(:,:,i),tran_p(:,:,i),thermk_p(i),&
+ extkb_p(i),extkd_p(i),ssun_p(:,:,i),ssha_p(:,:,i))
+ ELSE
+ albv_p(:,:,i) = albg(:,:)
+ ssun_p(:,:,i) = 0.
+ ssha_p(:,:,i) = 0.
+ tran_p(:,1,i) = 0.
+ tran_p(:,2,i) = 1.
+ tran_p(:,3,i) = 1.
+ ENDIF
+ ENDDO
+
+ albv(1,1) = sum( albv_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ albv(1,2) = sum( albv_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ albv(2,1) = sum( albv_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ albv(2,2) = sum( albv_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssun(1,1) = sum( ssun_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(1,2) = sum( ssun_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,1) = sum( ssun_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,2) = sum( ssun_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssha(1,1) = sum( ssha_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(1,2) = sum( ssha_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,1) = sum( ssha_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,2) = sum( ssha_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ tran(1,1) = sum( tran_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ tran(1,2) = sum( tran_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ tran(1,3) = sum( tran_p(1,3,ps:pe)*pftfrac(ps:pe) )
+ tran(2,1) = sum( tran_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ tran(2,2) = sum( tran_p(2,2,ps:pe)*pftfrac(ps:pe) )
+ tran(2,3) = sum( tran_p(2,3,ps:pe)*pftfrac(ps:pe) )
+
+ !NOTE: fordebug only below
+ IF (ssun(1,1)<0 .or. ssun(1,2)<0 .or. ssun(2,1)<0 .or. ssun(2,2)<0) THEN
+ print *, 'Warning:negative albedo',ipatch
+ print *, ssun
+ ENDIF
+
+ deallocate ( tran_p )
+ deallocate ( albv_p )
+
+ END SUBROUTINE twostream_wrap
+
+ SUBROUTINE twostream_hires_wrap ( ipatch, coszen, albg, &
+ albv, tran, ssun, ssha, &
+ reflectance, transmittance ,&
+ fsds_vis_dir_frac, fsds_nir_dir_frac,&
+ fsds_vis_dif_frac, fsds_nir_dif_frac,&
+ ssw, reflectance_out, transmittance_out, doy )
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! A Wrap subroutine to calculate PFT radiation using two-stream model
+!
+! Created by Hua Yuan, 03/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_LandPFT
+ USE MOD_Const_PFT
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_HighRes_Parameters , only: update_params_PROSPECT!, satellite_PROSPECT
+ USE MOD_Namelist, only: DEF_HighResVeg, DEF_PROSPECT!, DEF_Satellite_Params
+
+ IMPLICIT NONE
+
+ ! parameters
+ integer, intent(in) :: &
+ ipatch, &! patch index
+ doy
+
+ ! environmental variables
+ real(r8), intent(in) :: &
+ coszen, &! consine of solar zenith angle
+ albg(211,2) ! albedos of ground
+
+ ! high resolution optical properties
+ real(r8), intent(in) :: &
+ reflectance (0:15,211,2), &! leaf reflectance
+ transmittance(0:15,211,2), &! leaf transmittance
+ fsds_vis_dir_frac(29 ) ,&
+ fsds_nir_dir_frac(182) ,&
+ fsds_vis_dif_frac(29 ) ,&
+ fsds_nir_dif_frac(182) ,&
+ ssw
+
+ ! output
+ real(r8), intent(out) :: &
+ albv(211,2), &! albedo, vegetation [-]
+ tran(211,3), &! canopy transmittances for solar radiation
+ ssun(211,2), &! sunlit canopy absorption for solar radiation
+ ssha(211,2) ! shaded canopy absorption for solar radiation,
+ ! normalized by the incident flux
+
+ real(r8), intent(inout) :: &
+ reflectance_out (211,0:15), &! leaf reflectance
+ transmittance_out(211,0:15) ! leaf transmittance
+
+ integer :: i, p, ps, pe, iwl
+ real(r8) :: reflectance_p (211, 2)
+ real(r8) :: transmittance_p(211, 2)
+
+ real(r8), allocatable :: tran_p(:,:,:)
+ real(r8), allocatable :: albv_p(:,:,:)
+
+ real(r8) :: rho_hires(211), tau_hires(211)
+
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ allocate ( tran_p (211,3,ps:pe) )
+ allocate ( albv_p (211,2,ps:pe) )
+
+ DO i = ps, pe
+ p = pftclass(i)
+ IF (lai_p(i)+sai_p(i) > 1.e-6) THEN
+
+ ! IF use PROSPECT, update the high resolution optical properties
+ ! IF ( DEF_PROSPECT .AND. DEF_Satellite_Params ) THEN
+ ! CALL satellite_PROSPECT(p, reflectance, transmittance ,&
+ ! reflectance_p, transmittance_p,&
+ ! ssw, doy)
+ ! ELSE IF ( DEF_PROSPECT ) THEN
+ IF ( DEF_PROSPECT ) THEN
+ CALL update_params_PROSPECT(p, reflectance, transmittance ,&
+ reflectance_p, transmittance_p,&
+ ssw)
+ ELSE
+ reflectance_p = reflectance (p,:,:)
+ transmittance_p = transmittance(p,:,:)
+ ENDIF
+
+ reflectance_out (:,p) = reflectance_p (:,1)
+ transmittance_out(:,p) = transmittance_p(:,1)
+
+ CALL twostream_hires_mod (chil_p(p),reflectance_p,transmittance_p,1.,lai_p(i),sai_p(i),&
+ fwet_snow_p(i),coszen,albg,albv_p(:,:,i),tran_p(:,:,i),thermk_p(i),&
+ extkb_p(i),extkd_p(i),ssun_hires_p(:,:,i),ssha_hires_p(:,:,i))
+
+ CALL calculate_wgt_variable(ssun_hires_p(:,1,i), fsds_vis_dir_frac, fsds_nir_dir_frac, ssun_p(1,1,i), ssun_p(2,1,i))
+ CALL calculate_wgt_variable(ssun_hires_p(:,2,i), fsds_vis_dif_frac, fsds_nir_dif_frac, ssun_p(1,2,i), ssun_p(2,2,i))
+
+ CALL calculate_wgt_variable(ssha_hires_p(:,1,i), fsds_vis_dir_frac, fsds_nir_dir_frac, ssha_p(1,1,i), ssha_p(2,1,i))
+ CALL calculate_wgt_variable(ssha_hires_p(:,2,i), fsds_vis_dif_frac, fsds_nir_dif_frac, ssha_p(1,2,i), ssha_p(2,2,i))
+
+ ELSE
+ albv_p(:,:,i) = albg(:,:)
+
+ ssun_hires_p(:,:,i) = 0.
+ ssha_hires_p(:,:,i) = 0.
+
+ ssun_p(:,:,i) = 0.
+ ssha_p(:,:,i) = 0.
+ tran_p(:,1,i) = 0.
+ tran_p(:,2,i) = 1.
+ tran_p(:,3,i) = 1.
+ ENDIF
+ ENDDO
+
+ DO iwl = 1, 211
+ albv(iwl,1) = SUM( albv_p(iwl,1,ps:pe)*pftfrac(ps:pe) )
+ albv(iwl,2) = SUM( albv_p(iwl,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssun(iwl,1) = sum( ssun_hires_p(iwl,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(iwl,2) = sum( ssun_hires_p(iwl,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssha(iwl,1) = sum( ssha_hires_p(iwl,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(iwl,2) = sum( ssha_hires_p(iwl,2,ps:pe)*pftfrac(ps:pe) )
+
+ tran(iwl,1) = sum( tran_p(iwl,1,ps:pe)*pftfrac(ps:pe) )
+ tran(iwl,2) = sum( tran_p(iwl,2,ps:pe)*pftfrac(ps:pe) )
+ tran(iwl,3) = sum( tran_p(iwl,3,ps:pe)*pftfrac(ps:pe) )
+ END DO
+
+ !NOTE: fordebug only below
+ IF ( ANY(ssun < 0) ) THEN
+ print *, 'Warning:negative albedo',ipatch
+ print *, ssun
+ ENDIF
+
+ deallocate ( tran_p )
+ deallocate ( albv_p )
+
+ END SUBROUTINE twostream_hires_wrap
+#endif
+
+
+ SUBROUTINE snowage ( deltim,tg,scv,scvold,sag )
+
+!=======================================================================
+! Original version: Robert Dickinson
+! Update snow cover and snow age, based on BATS code
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only : tfrz
+ IMPLICIT NONE
+
+!-------------------------- Dummy Argument -----------------------------
+
+ real(r8), intent(in) :: deltim ! seconds in a time step [second]
+ real(r8), intent(in) :: tg ! temperature of soil at surface [K]
+ real(r8), intent(in) :: scv ! snow cover, water equivalent [mm]
+ real(r8), intent(in) :: scvold ! snow cover for previous time step [mm]
+ real(r8), intent(inout) :: sag ! non dimensional snow age [-]
+
+!-------------------------- Local variables ----------------------------
+
+ real(r8) :: age1 ! snow aging factor due to crystal growth [-]
+ real(r8) :: age2 ! snow aging factor due to surface growth [-]
+ real(r8) :: age3 ! snow aging factor due to accum of other particles [-]
+ real(r8) :: arg ! temporary variable used in snow age calculation [-]
+ real(r8) :: arg2 ! temporary variable used in snow age calculation [-]
+ real(r8) :: dela ! temporary variable used in snow age calculation [-]
+ real(r8) :: dels ! temporary variable used in snow age calculation [-]
+ real(r8) :: sge ! temporary variable used in snow age calculation [-]
+
+!-----------------------------------------------------------------------
+ IF(scv <= 0.) THEN
+ sag = 0.
+!
+! Over antarctica
+!
+ ELSE IF (scv > 800.) THEN
+ sag = 0.
+!
+! Away from antarctica
+!
+ ELSE
+ age3 = 0.3
+ arg = 5.e3*(1./tfrz-1./tg)
+ arg2 = min(0.,10.*arg)
+ age2 = exp(arg2)
+ age1 = exp(arg)
+ dela = 1.e-6*deltim*(age1+age2+age3)
+ dels = 0.1*max(0.0,scv-scvold)
+ sge = (sag+dela)*(1.0-dels)
+ sag = max(0.0,sge)
+ ENDIF
+
+ END SUBROUTINE snowage
+
+
+ SUBROUTINE SnowAlbedo( use_snicar_frc,use_snicar_ad ,coszen_col ,&
+ albsod ,albsoi ,snl ,frac_sno ,&
+ h2osno ,h2osno_liq ,h2osno_ice ,snw_rds ,&
+
+ mss_cnc_bcphi ,mss_cnc_bcpho ,mss_cnc_ocphi ,mss_cnc_ocpho ,&
+ mss_cnc_dst1 ,mss_cnc_dst2 ,mss_cnc_dst3 ,mss_cnc_dst4 ,&
+
+ albgrd ,albgri ,albgrd_pur ,albgri_pur ,&
+ albgrd_bc ,albgri_bc ,albgrd_oc ,albgri_oc ,&
+ albgrd_dst ,albgri_dst ,flx_absdv ,flx_absdn ,&
+ flx_absiv ,flx_absin ,dir_frac ,dif_frac )
+
+ ! !DESCRIPTION:
+ ! The calling sequence is:
+ ! -> SNICAR_RT: snow albedos: direct beam (SNICAR)
+ ! or
+ ! SNICAR_AD_RT: snow albedos: direct beam (SNICAR-AD)
+ ! -> SNICAR_RT: snow albedos: diffuse (SNICAR)
+ ! or
+ ! SNICAR_AD_RT: snow albedos: diffuse (SNICAR-AD)
+ !
+ ! ORIGINAL:
+ ! 1) The Community Land Model version5.0 (CLM5.0)
+ ! 2) Energy Exascale Earth System Model version 2.0 (E3SM v2.0) Land Model (ELM v2.0)
+ !
+ ! REFERENCES:
+ ! 1) Flanner et al, 2021, SNICAR-ADv3: a community tool for modeling spectral snow albedo.
+ ! Geosci. Model Dev., 14, 7673–7704, https://doi.org/10.5194/gmd-14-7673-2021
+ ! 2) Hao et al., 2023, Improving snow albedo modeling in the E3SM land model (version 2.0)
+ ! and assessing its impacts on snow and surface fluxes over the Tibetan Plateau.
+ ! Geosci. Model Dev., 16, 75–94, https://doi.org/10.5194/gmd-16-75-2023
+ !
+ ! REVISIONS:
+ ! Yongjiu Dai, and Hua Yuan, December, 2022 : ASSEMBLING and FITTING
+
+ !-----------------------------------------------------------------------
+ ! !USES:
+ USE MOD_Vars_Global, only: maxsnl
+ USE MOD_SnowSnicar_HiRes, only: SNICAR_RT, SNICAR_AD_RT
+
+ ! and the evolution of snow effective radius
+ !
+ ! DAI, Dec. 28, 2022
+
+ IMPLICIT NONE
+
+!-------------------------------------------------------------------------
+! temporay setting
+
+ integer, parameter :: numrad = 5 ! number of solar radiation bands: vis, nir
+ integer, parameter :: numhires = 211 ! number of solar radiation bands: vis, nir
+ integer, parameter :: sno_nbr_aer = 8 ! number of aerosol species in snowpack
+ logical, parameter :: DO_SNO_OC = .true. ! parameter to include organic carbon (OC)
+ logical, parameter :: DO_SNO_AER = .true. ! parameter to include aerosols in snowpack radiative calculations
+ integer, parameter :: subgridflag = 1 ! = 0 USE subgrid fluxes, = 1 not USE subgrid fluxes
+ !
+ ! !ARGUMENTS:
+ !
+ logical , intent(in) :: use_snicar_frc ! true: IF radiative forcing is being calculated, first estimate clean-snow albedo
+ logical , intent(in) :: use_snicar_ad ! true: USE SNICAR_AD_RT, false: USE SNICAR_RT
+
+ real(r8), intent(in) :: coszen_col ! cosine of solar zenith angle
+ real(r8), intent(in) :: albsod ( numhires ) ! direct-beam soil albedo (col,bnd) [frc]
+ real(r8), intent(in) :: albsoi ( numhires ) ! diffuse soil albedo (col,bnd) [frc]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8), intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+ real(r8), intent(in) :: h2osno ! snow water equivalent (mm H2O)
+ real(r8), intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg/m2]
+ real(r8), intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice lens content (col,lyr) [kg/m2]
+ real(r8), intent(in) :: snw_rds ( maxsnl+1:0 ) ! snow grain radius (col,lyr) [microns]
+
+ real(r8), intent(in) :: mss_cnc_bcphi ( maxsnl+1:0 ) ! mass concentration of hydrophilic BC (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_bcpho ( maxsnl+1:0 ) ! mass concentration of hydrophobic BC (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_ocphi ( maxsnl+1:0 ) ! mass concentration of hydrophilic OC (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_ocpho ( maxsnl+1:0 ) ! mass concentration of hydrophobic OC (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst1 ( maxsnl+1:0 ) ! mass concentration of dust aerosol species 1 (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst2 ( maxsnl+1:0 ) ! mass concentration of dust aerosol species 2 (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst3 ( maxsnl+1:0 ) ! mass concentration of dust aerosol species 3 (col,lyr) [kg/kg]
+ real(r8), intent(in) :: mss_cnc_dst4 ( maxsnl+1:0 ) ! mass concentration of dust aerosol species 4 (col,lyr) [kg/kg]
+
+ real(r8) , intent(in) :: dir_frac ( numhires ) !
+ real(r8) , intent(in) :: dif_frac ( numhires ) !
+
+ real(r8), intent(out) :: albgrd ( numrad ) ! ground albedo (direct)
+ real(r8), intent(out) :: albgri ( numrad ) ! ground albedo (diffuse)
+ real(r8), intent(out) :: albgrd_pur ( numrad ) ! pure snow ground albedo (direct)
+ real(r8), intent(out) :: albgri_pur ( numrad ) ! pure snow ground albedo (diffuse)
+ real(r8), intent(out) :: albgrd_bc ( numrad ) ! ground albedo without BC (direct)
+ real(r8), intent(out) :: albgri_bc ( numrad ) ! ground albedo without BC (diffuse)
+ real(r8), intent(out) :: albgrd_oc ( numrad ) ! ground albedo without OC (direct)
+ real(r8), intent(out) :: albgri_oc ( numrad ) ! ground albedo without OC (diffuse)
+ real(r8), intent(out) :: albgrd_dst ( numrad ) ! ground albedo without dust (direct)
+ real(r8), intent(out) :: albgri_dst ( numrad ) ! ground albedo without dust (diffuse)
+ real(r8), intent(out) :: flx_absdv ( maxsnl+1:1 ) ! direct flux absorption factor (col,lyr): VIS [frc]
+ real(r8), intent(out) :: flx_absdn ( maxsnl+1:1 ) ! direct flux absorption factor (col,lyr): NIR [frc]
+ real(r8), intent(out) :: flx_absiv ( maxsnl+1:1 ) ! diffuse flux absorption factor (col,lyr): VIS [frc]
+ real(r8), intent(out) :: flx_absin ( maxsnl+1:1 ) ! diffuse flux absorption factor (col,lyr): NIR [frc]
+
+ !-----------------------------------------------------------------------
+ !
+ ! !LOCAL VARIABLES:
+
+ integer :: i ! index for layers [idx]
+ integer :: ibnd, start_index, end_index ! index for 5 bands [idx]
+ integer :: aer ! index for sno_nbr_aer
+ integer :: ib ! band index
+ integer :: ic ! 0=unit incoming direct; 1=unit incoming diffuse
+ integer :: flg_slr ! flag for SNICAR (=1 IF direct, =2 IF diffuse)
+ integer :: flg_snw_ice ! flag for SNICAR (=1 when called from ELM, =2 when called from sea-ice)
+
+ real(r8) :: mss_cnc_aer_in_frc_pur (maxsnl+1:0,sno_nbr_aer) ! mass concentration of aerosol species for forcing calculation (zero) (col,lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_bc (maxsnl+1:0,sno_nbr_aer) ! mass concentration of aerosol species for BC forcing (col,lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_oc (maxsnl+1:0,sno_nbr_aer) ! mass concentration of aerosol species for OC forcing (col,lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_frc_dst (maxsnl+1:0,sno_nbr_aer) ! mass concentration of aerosol species for dust forcing (col,lyr,aer) [kg kg-1]
+ real(r8) :: mss_cnc_aer_in_fdb (maxsnl+1:0,sno_nbr_aer) ! mass concentration of all aerosol species for feedback calculation (col,lyr,aer) [kg kg-1]
+
+ real(r8) :: albsfc (numrad) ! albedo of surface underneath snow (col,bnd)
+ real(r8) :: albsnd (numrad) ! snow albedo (direct)
+ real(r8) :: albsni (numrad) ! snow albedo (diffuse)
+ real(r8) :: albsnd_pur (numrad) ! direct pure snow albedo (radiative forcing)
+ real(r8) :: albsni_pur (numrad) ! diffuse pure snow albedo (radiative forcing)
+ real(r8) :: albsnd_bc (numrad) ! direct snow albedo without BC (radiative forcing)
+ real(r8) :: albsni_bc (numrad) ! diffuse snow albedo without BC (radiative forcing)
+ real(r8) :: albsnd_oc (numrad) ! direct snow albedo without OC (radiative forcing)
+ real(r8) :: albsni_oc (numrad) ! diffuse snow albedo without OC (radiative forcing)
+ real(r8) :: albsnd_dst (numrad) ! direct snow albedo without dust (radiative forcing)
+ real(r8) :: albsni_dst (numrad) ! diffuse snow albedo without dust (radiative forcing)
+ real(r8) :: flx_absd_snw (maxsnl+1:1,numrad) ! flux absorption factor for just snow (direct) [frc]
+ real(r8) :: flx_absi_snw (maxsnl+1:1,numrad) ! flux absorption factor for just snow (diffuse) [frc]
+ real(r8) :: foo_snw (maxsnl+1:1,numrad) ! dummy array for forcing calls
+
+ integer :: snw_rds_in (maxsnl+1:0) ! snow grain size sent to SNICAR (col,lyr) [microns]
+
+ integer , parameter :: nband =numrad ! number of solar radiation waveband classes
+ INTEGER, PARAMETER, DIMENSION(6) :: band_index = (/ &
+ 1, 30, 60, 80, 110, 212 &! 400, 700, 1000, 1200, 1500, 2500 nm
+ /)
+
+ !-----------------------------------------------------------------------
+
+ ! Initialize output because solar radiation only done IF coszen > 0
+
+ DO ib = 1, numrad
+ albgrd(ib) = 0._r8
+ albgri(ib) = 0._r8
+ albgrd_pur(ib) = 0._r8
+ albgri_pur(ib) = 0._r8
+ albgrd_bc(ib) = 0._r8
+ albgri_bc(ib) = 0._r8
+ albgrd_oc(ib) = 0._r8
+ albgri_oc(ib) = 0._r8
+ albgrd_dst(ib) = 0._r8
+ albgri_dst(ib) = 0._r8
+ DO i=maxsnl+1,1,1
+ flx_absdv(i) = 0._r8
+ flx_absdn(i) = 0._r8
+ flx_absiv(i) = 0._r8
+ flx_absin(i) = 0._r8
+ ENDDO
+ ENDDO ! END of numrad loop
+
+ ! set variables to pass to SNICAR.
+
+ flg_snw_ice = 1
+
+ do ibnd = 1, 5
+ start_index = band_index(ibnd)
+ end_index = band_index(ibnd+1) - 1
+
+ albsfc(ibnd) = SUM(albsoi (start_index:end_index) *&
+ dif_frac(start_index:end_index)) /&
+ SUM(dif_frac(start_index:end_index))
+ end do
+
+ snw_rds_in(:) = nint(snw_rds(:))
+
+ ! zero aerosol input arrays
+ DO aer = 1, sno_nbr_aer
+ DO i = maxsnl+1, 0
+ mss_cnc_aer_in_frc_pur(i,aer) = 0._r8
+ mss_cnc_aer_in_frc_bc(i,aer) = 0._r8
+ mss_cnc_aer_in_frc_oc(i,aer) = 0._r8
+ mss_cnc_aer_in_frc_dst(i,aer) = 0._r8
+ mss_cnc_aer_in_fdb(i,aer) = 0._r8
+ ENDDO
+ ENDDO
+
+ ! If radiative forcing is being calculated, first estimate clean-snow albedo
+
+ IF (use_snicar_frc) THEN
+
+ ! 1. PURE SNOW ALBEDO CALCULATIONS
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsnd_pur(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsnd_pur(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsni_pur(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_pur(:, :), &
+ albsfc(:), &
+ albsni_pur(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ ! 2. BC input array:
+ ! set dust and (optionally) OC concentrations, so BC_FRC=[(BC+OC+dust)-(OC+dust)]
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_frc_bc(:,3) = mss_cnc_ocphi(:)
+ mss_cnc_aer_in_frc_bc(:,4) = mss_cnc_ocpho(:)
+ ENDIF
+ mss_cnc_aer_in_frc_bc(:,5) = mss_cnc_dst1(:)
+ mss_cnc_aer_in_frc_bc(:,6) = mss_cnc_dst2(:)
+ mss_cnc_aer_in_frc_bc(:,7) = mss_cnc_dst3(:)
+ mss_cnc_aer_in_frc_bc(:,8) = mss_cnc_dst4(:)
+
+ ! BC FORCING CALCULATIONS
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsnd_bc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsnd_bc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsni_bc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_bc(:, :), &
+ albsfc(:), &
+ albsni_bc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ ! 3. OC input array:
+ ! set BC and dust concentrations, so OC_FRC=[(BC+OC+dust)-(BC+dust)]
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_frc_oc(:,1) = mss_cnc_bcphi(:)
+ mss_cnc_aer_in_frc_oc(:,2) = mss_cnc_bcpho(:)
+
+ mss_cnc_aer_in_frc_oc(:,5) = mss_cnc_dst1(:)
+ mss_cnc_aer_in_frc_oc(:,6) = mss_cnc_dst2(:)
+ mss_cnc_aer_in_frc_oc(:,7) = mss_cnc_dst3(:)
+ mss_cnc_aer_in_frc_oc(:,8) = mss_cnc_dst4(:)
+
+ ! OC FORCING CALCULATIONS
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsnd_oc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsnd_oc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsni_oc(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_oc(:, :), &
+ albsfc(:), &
+ albsni_oc(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+ ENDIF ! END IF (DO_SNO_OC)
+
+ ! 4. DUST FORCING CALCULATIONS
+ ! DUST input array:
+ ! set BC and OC concentrations, so DST_FRC=[(BC+OC+dust)-(BC+OC)]
+ mss_cnc_aer_in_frc_dst(:,1) = mss_cnc_bcphi(:)
+ mss_cnc_aer_in_frc_dst(:,2) = mss_cnc_bcpho(:)
+
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_frc_dst(:,3) = mss_cnc_ocphi(:)
+ mss_cnc_aer_in_frc_dst(:,4) = mss_cnc_ocpho(:)
+ ENDIF
+
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsnd_dst(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsnd_dst(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsni_dst(:), &
+ foo_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_frc_dst(:, :), &
+ albsfc(:), &
+ albsni_dst(:), &
+ foo_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ ENDIF !END IF use_snicar_frc
+
+
+ ! --------------------------------------------
+ ! CLIMATE FEEDBACK CALCULATIONS, ALL AEROSOLS:
+ ! --------------------------------------------
+ ! Set aerosol input arrays
+ ! feedback input arrays have been zeroed
+ ! set soot and dust aerosol concentrations:
+ IF (DO_SNO_AER) THEN
+ mss_cnc_aer_in_fdb(:,1) = mss_cnc_bcphi(:)
+ mss_cnc_aer_in_fdb(:,2) = mss_cnc_bcpho(:)
+
+ ! DO_SNO_OC is set in SNICAR_varpar. Default case is to ignore OC concentrations because:
+ ! 1) Knowledge of their optical properties is primitive
+ ! 2) When 'water-soluble' OPAC optical properties are applied to OC in snow,
+ ! it has a negligible darkening effect.
+ IF (DO_SNO_OC) THEN
+ mss_cnc_aer_in_fdb(:,3) = mss_cnc_ocphi(:)
+ mss_cnc_aer_in_fdb(:,4) = mss_cnc_ocpho(:)
+ ENDIF
+
+ mss_cnc_aer_in_fdb(:,5) = mss_cnc_dst1(:)
+ mss_cnc_aer_in_fdb(:,6) = mss_cnc_dst2(:)
+ mss_cnc_aer_in_fdb(:,7) = mss_cnc_dst3(:)
+ mss_cnc_aer_in_fdb(:,8) = mss_cnc_dst4(:)
+ ENDIF
+
+ flg_slr = 1 ! direct-beam
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsnd(:), &
+ flx_absd_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsnd(:), &
+ flx_absd_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+ flg_slr = 2 ! diffuse
+ IF (use_snicar_ad) THEN
+ CALL SNICAR_AD_RT(flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsni(:), &
+ flx_absi_snw(:, :) )
+ ELSE
+ CALL SNICAR_RT (flg_snw_ice, &
+ flg_slr, &
+ coszen_col, &
+ snl, &
+ h2osno, &
+ frac_sno, &
+ h2osno_liq(:), &
+ h2osno_ice(:), &
+ snw_rds_in(:), &
+ mss_cnc_aer_in_fdb(:, :), &
+ albsfc(:), &
+ albsni(:), &
+ flx_absi_snw(:, :) )
+ ENDIF ! END IF use_snicar_ad
+
+
+ ! ground albedos and snow-fraction weighting of snow absorption factors
+ DO ib = 1, nband
+ IF (coszen_col > 0._r8) THEN
+ ! ground albedo was originally computed in SoilAlbedo, but is now computed here
+ ! because the order of SoilAlbedo and SNICAR_RT/SNICAR_AD_RT was switched for SNICAR/SNICAR_AD_RT.
+ ! 09/01/2023, yuan: change to only snow albedo, the same below
+ !albgrd(ib) = albsod(ib)*(1._r8-frac_sno) + albsnd(ib)*frac_sno
+ !albgri(ib) = albsoi(ib)*(1._r8-frac_sno) + albsni(ib)*frac_sno
+ albgrd(ib) = albsnd(ib)
+ albgri(ib) = albsni(ib)
+
+ ! albedos for radiative forcing calculations:
+ IF (use_snicar_frc) THEN
+ ! pure snow albedo for all-aerosol radiative forcing
+ !albgrd_pur(ib) = albsod(ib)*(1.-frac_sno) + albsnd_pur(ib)*frac_sno
+ !albgri_pur(ib) = albsoi(ib)*(1.-frac_sno) + albsni_pur(ib)*frac_sno
+ albgrd_pur(ib) = albsnd_pur(ib)
+ albgri_pur(ib) = albsni_pur(ib)
+
+ ! BC forcing albedo
+ !albgrd_bc(ib) = albsod(ib)*(1.-frac_sno) + albsnd_bc(ib)*frac_sno
+ !albgri_bc(ib) = albsoi(ib)*(1.-frac_sno) + albsni_bc(ib)*frac_sno
+ albgrd_bc(ib) = albsnd_bc(ib)
+ albgri_bc(ib) = albsni_bc(ib)
+
+ IF (DO_SNO_OC) THEN
+ ! OC forcing albedo
+ !albgrd_oc(ib) = albsod(ib)*(1.-frac_sno) + albsnd_oc(ib)*frac_sno
+ !albgri_oc(ib) = albsoi(ib)*(1.-frac_sno) + albsni_oc(ib)*frac_sno
+ albgrd_oc(ib) = albsnd_oc(ib)
+ albgri_oc(ib) = albsni_oc(ib)
+ ENDIF
+
+ ! dust forcing albedo
+ !albgrd_dst(ib) = albsod(ib)*(1.-frac_sno) + albsnd_dst(ib)*frac_sno
+ !albgri_dst(ib) = albsoi(ib)*(1.-frac_sno) + albsni_dst(ib)*frac_sno
+ albgrd_dst(ib) = albsnd_dst(ib)
+ albgri_dst(ib) = albsni_dst(ib)
+ ENDIF
+
+ ! also in this loop (but optionally in a different loop for vectorized code)
+ ! weight snow layer radiative absorption factors based on snow fraction and soil albedo
+ ! (NEEDED FOR ENERGY CONSERVATION)
+ DO i = maxsnl+1,1,1
+ IF (subgridflag == 0 ) THEN
+ IF (ib == 1) THEN
+ flx_absdv(i) = flx_absd_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsod(ib))*(flx_absd_snw(i,ib)/(1.-albsnd(ib))))
+ flx_absiv(i) = flx_absi_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsoi(ib))*(flx_absi_snw(i,ib)/(1.-albsni(ib))))
+ elseif (ib == 2) THEN
+ flx_absdn(i) = flx_absd_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsod(ib))*(flx_absd_snw(i,ib)/(1.-albsnd(ib))))
+ flx_absin(i) = flx_absi_snw(i,ib)*frac_sno + &
+ ((1.-frac_sno)*(1-albsoi(ib))*(flx_absi_snw(i,ib)/(1.-albsni(ib))))
+ ENDIF
+ ELSE
+ IF (ib == 1) THEN
+ flx_absdv(i) = flx_absd_snw(i,ib)!*(1.-albsnd(ib))
+ flx_absiv(i) = flx_absi_snw(i,ib)!*(1.-albsni(ib))
+ elseif (ib == 2) THEN
+ flx_absdn(i) = flx_absd_snw(i,ib)!*(1.-albsnd(ib))
+ flx_absin(i) = flx_absi_snw(i,ib)!*(1.-albsni(ib))
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE SnowAlbedo
+
+ SUBROUTINE albocean (oro, scv, coszrs, alb)
+
+!-----------------------------------------------------------------------
+!
+! Compute surface albedos
+!
+! Computes surface albedos for direct/diffuse incident radiation for
+! two spectral intervals:
+! s = 0.2-0.7 micro-meters
+! l = 0.7-5.0 micro-meters
+!
+! Albedos specified as follows:
+!
+! Ocean Uses solar zenith angle to compute albedo for direct
+! radiation; diffuse radiation values constant; albedo
+! independent of spectral interval and other physical
+! factors such as ocean surface wind speed.
+!
+! Ocean with Surface albs specified; combined with overlying snow
+! sea ice
+!
+! For more details , see Briegleb, Bruce P., 1992: Delta-Eddington
+! Approximation for Solar Radiation in the NCAR Community Climate Model,
+! Journal of Geophysical Research, Vol 97, D7, pp7603-7612).
+!
+! yongjiu dai and xin-zhong liang (08/01/2001)
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!------------------------------Arguments--------------------------------
+
+ real(r8), intent(in) :: oro ! /ocean(0)/seaice(2) flag
+ real(r8), intent(in) :: scv ! snow water equivalent) [mm]
+ real(r8), intent(in) :: coszrs ! Cosine solar zenith angle
+
+ real(r8), intent(out) :: alb(2,2) ! srf alb for direct (diffuse) rad 0.2-0.7 micro-ms
+ ! Srf alb for direct (diffuse) rad 0.7-5.0 micro-ms
+
+!---------------------------Local variables-----------------------------
+
+ real(r8) frsnow ! horizontal fraction of snow cover
+ real(r8) snwhgt ! physical snow height
+ real(r8) rghsnw ! roughness for horizontal snow cover fractn
+
+ real(r8) sasdir ! snow alb for direct rad 0.2-0.7 micro-ms
+ real(r8) saldir ! snow alb for direct rad 0.7-5.0 micro-ms
+ real(r8) sasdif ! snow alb for diffuse rad 0.2-0.7 micro-ms
+ real(r8) saldif ! snow alb for diffuse rad 0.7-5.0 micro-ms
+
+ real(r8), parameter :: asices = 0.70 ! sea ice albedo for 0.2-0.7 micro-meters [-]
+ real(r8), parameter :: asicel = 0.50 ! sea ice albedo for 0.7-5.0 micro-meters [-]
+ real(r8), parameter :: asnows = 0.95 ! snow albedo for 0.2-0.7 micro-meters [-]
+ real(r8), parameter :: asnowl = 0.70 ! snow albedo for 0.7-5.0 micro-meters
+
+!-----------------------------------------------------------------------
+! initialize all ocean/sea ice surface albedos to zero
+
+ alb(:,:) = 0.
+ IF(coszrs<=0.0) RETURN
+
+ IF(nint(oro)==2)THEN
+ alb(1,1) = asices
+ alb(2,1) = asicel
+ alb(1,2) = alb(1,1)
+ alb(2,2) = alb(2,1)
+ sasdif = asnows
+ saldif = asnowl
+
+ IF(scv>0.)THEN
+ IF (coszrs<0.5) THEN
+ ! zenith angle regime 1 ( coszrs < 0.5 ).
+ ! set direct snow albedos (limit to 0.98 max)
+ sasdir = min(0.98,sasdif+(1.-sasdif)*0.5*(3./(1.+4.*coszrs)-1.))
+ saldir = min(0.98,saldif+(1.-saldif)*0.5*(3./(1.+4.*coszrs)-1.))
+ ELSE
+ ! zenith angle regime 2 ( coszrs >= 0.5 )
+ sasdir = asnows
+ saldir = asnowl
+ ENDIF
+
+ ! compute both diffuse and direct total albedos
+ snwhgt = 20.*scv / 1000.
+ rghsnw = 0.25
+ frsnow = snwhgt/(rghsnw+snwhgt)
+ alb(1,1) = alb(1,1)*(1.-frsnow) + sasdir*frsnow
+ alb(2,1) = alb(2,1)*(1.-frsnow) + saldir*frsnow
+ alb(1,2) = alb(1,2)*(1.-frsnow) + sasdif*frsnow
+ alb(2,2) = alb(2,2)*(1.-frsnow) + saldif*frsnow
+ ENDIF
+ ENDIF
+
+! ice-free ocean albedos function of solar zenith angle only, and
+! independent of spectral interval:
+
+ IF(nint(oro)==0)THEN
+ alb(2,1) = .026/(coszrs**1.7+.065) &
+ + .15*(coszrs-0.1)*(coszrs-0.5)*(coszrs-1.)
+ alb(1,1) = alb(2,1)
+ alb(1,2) = 0.06
+ alb(2,2) = 0.06
+ ENDIF
+
+ END SUBROUTINE albocean
+
+
+ pure function calculate_tav(alpha, nr) result(tav)
+ real(r8), intent(in) :: alpha
+ real(r8), dimension(211), intent(in) :: nr
+ real(r8) :: rd, n2(211), n_p(211), nm(211), a(211), k(211), sa
+ real(r8) :: b1(211), b2(211), b(211), b3(211), a3(211)
+ real(r8) :: ts(211), tp1(211), tp2(211), tp3(211), tp4(211), tp5(211), tp(211)
+ real(r8), dimension(211) :: tav
+
+ rd = 3.141592653589793 / 180.0
+ n2 = nr**2
+ n_p = n2 + 1.0
+ nm = n2 - 1.0
+ a = (nr + 1.0) * (nr + 1.0) / 2.0
+ k = -(n2 - 1.0) * (n2 - 1.0) / 4.0
+ sa = sin(alpha * rd)
+
+ b1 = 0.0
+ if (alpha /= 90.0) then
+ b1 = sqrt((sa**2 - n_p / 2.0) * (sa**2 - n_p / 2.0) + k)
+ end if
+
+ b2 = sa**2 - n_p / 2.0
+ b = b1 - b2
+ b3 = b**3
+ a3 = a**3
+
+ ts = (k**2 / (6.0 * b3) + k / b - b / 2.0) - (k**2 / (6.0 * a3) + k / a - a / 2.0)
+
+ tp1 = -2.0 * n2 * (b - a) / (n_p**2)
+ tp2 = -2.0 * n2 * n_p * log(b / a) / (nm**2)
+ tp3 = n2 * (1.0 / b - 1.0 / a) / 2.0
+ tp4 = 16.0 * n2**2 * (n2**2 + 1.0) * log((2.0 * n_p * b - nm**2) / (2.0 * n_p * a - nm**2)) / (n_p**3 * nm**2)
+ tp5 = 16.0 * n2**3 * (1.0 / (2.0 * n_p * b - nm**2) - 1.0 / (2.0 * n_p * a - nm**2)) / n_p**3
+ tp = tp1 + tp2 + tp3 + tp4 + tp5
+ tav = (ts + tp) / (2.0 * sa**2)
+
+ end function calculate_tav
+
+ pure FUNCTION poisson_pmf(k, lambda) RESULT(pmf)
+ IMPLICIT NONE
+ INTEGER, INTENT(IN) :: k(:)
+ REAL(r8), INTENT(IN) :: lambda
+ REAL(r8) :: pmf(SIZE(k))
+ INTEGER :: i
+
+ DO i = 1, SIZE(k)
+ pmf(i) = EXP(-lambda) * lambda**REAL(k(i), KIND=r8) / FACTORIAL_R8( k(i) )
+ END DO
+
+ END FUNCTION poisson_pmf
+
+ pure FUNCTION FACTORIAL_R8(k) RESULT(fact)
+ IMPLICIT NONE
+ INTEGER, INTENT(IN) :: k
+ INTEGER :: i
+ REAL(r8) :: fact
+
+ fact = 1.0_r8
+ IF (k <= 0) RETURN
+ DO i = 1, k
+ fact = fact * REAL(i, KIND=r8)
+ END DO
+ END FUNCTION FACTORIAL_R8
+
+ SUBROUTINE BSM_soil_moisture( &
+ ! input
+ soil_moisture, smc, albedo_dry, kw, nw, &
+ ! output
+ albedo_wet)
+
+ IMPLICIT NONE
+
+ ! Arguments
+ real(r8), intent(in) :: soil_moisture
+ real(r8), intent(in) :: smc
+ real(r8), intent(in) :: albedo_dry(211)
+ real(r8), intent(in) :: kw(211)
+ real(r8), intent(in) :: nw(211)
+
+ real(r8), intent(out) :: albedo_wet(211, 2)
+
+ ! Parameters
+ real(r8), parameter :: deleff = 0.0150 ! BSM soil model: film thickness not supplied, set to default of 0.015 m
+
+ INTEGER, DIMENSION(7) :: k_arr = (/0, 1, 2, 3, 4, 5, 6/)
+ INTEGER :: nk, i
+ REAL(r8) :: mu
+ REAL(r8) :: rbac(211), p(211), Rw(211)
+ REAL(r8) :: fmul(7), tw(211, 7)
+ REAL(r8) :: Rwet_k(211, 7)
+ REAL(r8) :: kw_tmp(211, 7), numerator_tmp(211, 7), denominator_tmp(211, 7), dot_product_result(211)
+
+ ! ===== Start of executable code =====
+ nk = SIZE(k_arr)
+
+ mu = (soil_moisture - 5.0) / smc
+
+ IF (mu <= 0.0) THEN ! below 5 % SM -> model assumes no effect
+ albedo_wet(:, 1) = albedo_dry
+ albedo_wet(:, 2) = albedo_dry
+ ELSE
+ rbac = 1.0 - (1.0 - albedo_dry) * (albedo_dry * calculate_tav(90.0, 2.0 / nw) / calculate_tav(90.0, (/ (2.0, i = 1, 211) /)) + 1.0 - albedo_dry)
+
+ p = 1.0 - calculate_tav(90.0, nw) / nw**2
+
+ Rw = 1.0 - calculate_tav(40.0, nw)
+
+ fmul = poisson_pmf(k_arr, mu)
+
+ do i = 1, nk
+ kw_tmp(:, i) = kw * k_arr(i)
+ tw(:, i) = exp(-2.0 * kw_tmp(:, i) * deleff)
+
+ numerator_tmp(:, i) = Rw + (1.0 - Rw) * (1.0 - p) * tw(:, i) * rbac
+ denominator_tmp(:, i) = 1.0 - p * tw(:, i) * rbac
+ end do
+
+ ! Rwet_k = Rw + (1.0 - Rw) * (1.0 - p) * tw * rbac / (1.0 - p * tw * rbac)
+ Rwet_k = numerator_tmp / denominator_tmp
+
+ do i = 1, 211
+ dot_product_result(i) = SUM(Rwet_k(i, 2:nk) * fmul(2:nk))
+ end do
+ albedo_wet(:, 1) = (albedo_dry * fmul(1)) + dot_product_result
+ albedo_wet(:, 2) = albedo_wet(:, 1)
+ END IF
+
+ END SUBROUTINE BSM_soil_moisture
+
+ SUBROUTINE calculate_wgt_variable( variable, frac_vis, frac_nir, variable_vis, variable_nir )
+
+ ! Arguments
+ INTEGER, PARAMETER :: num_vis = 29 ! 400 - 690 nm
+ INTEGER, PARAMETER :: num_nir = 182 ! 700 - 2500 nm
+
+ real(r8), intent(in) :: variable(211)
+ real(r8), intent(in) :: frac_vis(num_vis)
+ real(r8), intent(in) :: frac_nir(num_nir)
+
+ real(r8), intent(out) :: variable_vis
+ real(r8), intent(out) :: variable_nir
+
+ real(r8), parameter :: eps = 1.0e-12_r8
+ real(r8) :: sum_vis, sum_nir
+
+ sum_vis = SUM(frac_vis)
+ sum_nir = SUM(frac_nir)
+
+ variable_vis = SUM(frac_vis * variable(1:num_vis)) / sum_vis
+ variable_nir = SUM(frac_nir * variable(num_vis+1:211)) / sum_nir
+
+ END SUBROUTINE calculate_wgt_variable
+
+END MODULE MOD_Albedo_HiRes
+#endif
+! --------- EOP ----------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_AssimStomataConductance.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_AssimStomataConductance.F90
new file mode 100644
index 0000000000..e4df0a565b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_AssimStomataConductance.F90
@@ -0,0 +1,844 @@
+#include
+
+MODULE MOD_AssimStomataConductance
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: stomata
+ PUBLIC :: update_photosyn
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: sortin
+ PRIVATE :: calc_photo_params
+ PRIVATE :: WUE_solver
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE stomata (vmax25,effcon,c3c4,slti,hlti,shti, &
+ hhti,trda,trdm,trop,g1,g0,gradm,binter,tm, &
+ psrf,po2m,pco2m,pco2a,ea,ei,tlef,par, &
+!Ozone stress variables
+ o3coefv,o3coefg, &
+!End ozone stress variables
+!WUE stomata model parameter
+ lambda, &
+!End WUE stomata model parameter
+ rb,ra,rstfac,cint,assim,respc,rst )
+
+!=======================================================================
+!
+! !DESCRIPTION:
+! calculation of canopy photosynthetic rate using the integrated
+! model relating assimilation and stomatal conductance.
+!
+! Original author: Yongjiu Dai, 08/11/2001
+!
+! !REFERENCES:
+! Dai et al., 2004: A two-big-leaf model for canopy temperature,
+! photosynthesis and stomatal conductance. J. Climate, 17: 2281-2299.
+!
+!
+! units are converted from mks to biological units in this routine.
+!
+! units
+! -------
+!
+! pco2m, pco2a, pco2i, po2m : pascals
+! co2a, co2s, co2i, h2oa, h2os, h2oa : mol mol-1
+! vmax25, respcp, assim, gs, gb, ga : mol m-2 s-1
+! effcon : mol co2 mol quanta-1
+! 1/rb, 1/ra, 1/rst : m s-1
+!
+! conversions
+! -------------
+!
+! 1 mol h2o = 0.018 kg
+! 1 mol co2 = 0.044 kg
+! h2o (mol mol-1) = ea / psrf ( pa pa-1 )
+! h2o (mol mol-1) = q*mm/(q*mm + 1)
+! gs (co2) = gs (h2o) * 1./1.6
+! gs (mol m-2 s-1 ) = gs (m s-1) * 44.6*tf/t*p/po
+! par (mol m-2 s-1 ) = par(w m-2) * 4.6*1.e-6
+! mm (molair/molh2o) = 1.611
+!
+! !REVISIONS:
+! 2021, Xingjie Lu: Add ozone stree and WUE model
+!
+!----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8),intent(in) :: &
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2 / mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+
+ trop, &! temperature coefficient in gs-a model (298.16)
+ slti, &! slope of low temperature inhibition function (0.2)
+ hlti, &! 1/2 point of low temperature inhibition function (288.16)
+ shti, &! slope of high temperature inhibition function (0.3)
+ hhti, &! 1/2 point of high temperature inhibition function (313.16)
+ trda, &! temperature coefficient in gs-a model (1.3)
+ trdm, &! temperature coefficient in gs-a model (328.16)
+ g1, &! conductance-photosynthesis slope parameter for medlyn model
+ g0, &! conductance-photosynthesis intercept for medlyn model
+ gradm, &! conductance-photosynthesis slope parameter
+ binter ! conductance-photosynthesis intercept
+ integer, intent(in) :: &
+ c3c4 ! 1 for c3, 0 for c4
+ real(r8),intent(in) :: &
+ tm, &! atmospheric air temperature (K)
+ psrf, &! surface atmospheric pressure (pa)
+ po2m, &! O2 concentration in atmos. (pascals)
+ pco2m, &! CO2 concentration in atmos. (pascals)
+ pco2a, &! CO2 concentration in canopy air space (pa)
+ ea, &! canopy air space vapor pressure (pa)
+ ei, &! saturation h2o vapor pressure in leaf stomata (pa)
+ tlef, &! leaf temperature (K)
+ par, &! photosynthetic active radiation (W m-2)
+!Ozone stress variables
+ o3coefv, &
+ o3coefg, &
+!End ozone stress variables
+
+!WUE stomata model parameter
+ lambda, &! marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+!End WUE stomata model parameter
+
+ rb, &! boundary resistance from canopy to cas (s m-1)
+ ra, &! aerodynamic resistance from cas to reference height (s m-1)
+ rstfac ! canopy resistance stress factors to soil moisture
+
+ real(r8),intent(in), dimension(3) :: &
+ cint ! scaling up from leaf to canopy
+
+ real(r8),intent(out) :: &! ATTENTION : all for canopy not leaf
+ assim, &! canopy assimilation rate (mol m-2 s-1)
+ respc, &! canopy respiration (mol m-2 s-1)
+ rst ! canopy stomatal resistance (s m-1)
+
+ real(r8) gammas
+
+!-------------------------- Local Variables ----------------------------
+
+ integer, parameter :: iterationtotal = 6 ! total iteration number in pco2i calculation
+
+ real(r8) &
+ c3, &! c3 vegetation : 1; 0 for c4
+ c4, &! c4 vegetation : 1; 0 for c3
+ rrkk, &! kc (1+o2/ko)
+
+ vm, &! maximum catalytic activity of Rubison (mol co2 m-2 s-1)
+ epar, &! electron transport rate (mol electron m-2 s-1)
+ bintc, &! residual stomatal conductance for co2 (mol co2 m-2 s-1)
+ acp, &! temporary variable for stomata model (mol co2 m-2 s-1)
+ vpd, &! vapor pressure deficit (kpa)
+
+ tprcor, &! coefficient for unit transfer
+ gbh2o, &! one side leaf boundary layer conductance (mol m-2 s-1)
+ gsh2o, &! canopy conductance (mol m-2 s-1)
+
+ atheta, &! wc, we coupling parameter
+ btheta, &! wc & we, ws coupling parameter
+ omss, &! intermediate calculation for oms
+ omc, &! rubisco limited assimilation (omega-c: mol m-2 s-1)
+ ome, &! light limited assimilation (omega-e: mol m-2 s-1)
+ oms, &! sink limited assimilation (omega-s: mol m-2 s-1)
+ omp, &! intermediate calculation for omc, ome
+
+ co2m, &! co2 concentration in atmos (mol mol-1)
+ co2a, &! co2 concentration at cas (mol mol-1)
+ co2s, &! co2 concentration at canopy surface (mol mol-1)
+ co2st, &! co2 concentration at canopy surface (mol mol-1)
+ co2i, &! internal co2 concentration (mol mol-1)
+ pco2in, &! internal co2 concentration at the new iteration (pa)
+ pco2i, &! internal co2 concentration (pa)
+ pco2i_c, &! internal co2 concentration when Rubisco is limited (pa)
+ pco2i_e, &! internal co2 concentration when RuBP regeneration is limited (pa)
+ es, &! canopy surface h2o vapor pressure (pa)
+
+ sqrtin, &! intermediate calculation for quadratic
+ assmt, &! net assimilation with a positive limitation (mol co2 m-2 s-1)
+ assimn, &! net assimilation (mol co2 m-2 s-1)
+ hcdma, &! a-1
+ aquad, &! a: ax^2 + bx + c = 0
+ bquad, &! b: ax^2 + bx + c = 0
+ cquad ! c: ax^2 + bx + c = 0
+
+ real(r8) :: &
+ eyy(iterationtotal), &! differnce of pco2i at two iteration step
+ pco2y(iterationtotal), &! adjusted to total iteration number
+ range !
+
+ integer ic
+!-----------------------------------------------------------------------
+
+ CALL calc_photo_params(tlef, po2m, par , psrf, rstfac, rb, effcon, vmax25, c3c4, &
+ trop, slti, hlti, shti, hhti, trda, trdm, cint, &
+ vm, epar, respc, omss, gbh2o, gammas, rrkk, c3, c4)
+
+ bintc = binter * max( 0.1, rstfac )
+ bintc = bintc * cint(3)
+
+!-----------------------------------------------------------------------
+! first guess is midway between compensation point and maximum
+! assimilation rate. ! pay attention on this iteration
+
+ tprcor = 44.6*273.16*psrf/1.013e5
+
+ co2m = pco2m/psrf ! mol mol-1
+ co2a = pco2a/psrf
+
+ range = pco2m * ( 1. - 1.6/gradm ) - gammas
+
+ DO ic = 1, iterationtotal ! loop for total iteration number
+ pco2y(ic) = 0.
+ eyy(ic) = 0.
+ ENDDO
+
+ ITERATION_LOOP: DO ic = 1, iterationtotal
+
+ !IF(.not. DEF_USE_WUEST .or. epar .lt. 1.e-12)THEN
+ IF(.not. DEF_USE_WUEST .or. abs(c4 - 1) .lt. 0.001)THEN
+ CALL sortin(eyy, pco2y, range, gammas, ic, iterationtotal)
+ pco2i = pco2y(ic)
+ pco2i_c = pco2i
+ pco2i_e = pco2i
+ ELSE
+ CALL WUE_solver(gammas, lambda, co2a, ei, ea, psrf, pco2i_c, pco2i_e)
+ ENDIF
+
+!-----------------------------------------------------------------------
+! NET ASSIMILATION
+! the leaf assimilation (or gross photosynthesis) rate is described
+! as the minimum of three limiting rates:
+! omc: the efficiency of the photosynthetic enzyme system (Rubisco-limited);
+! ome: the amount of PAR captured by leaf chlorophyll;
+! oms: the capacity of the leaf to export or utilize the products of photosynthesis.
+! to aviod the abrupt transitions, two quadratic equations are used:
+! atheta*omp^2 - omp*(omc+ome) + omc*ome = 0
+! btheta*assim^2 - assim*(omp+oms) + omp*oms = 0
+!-----------------------------------------------------------------------
+
+ atheta = 0.877
+ btheta = 0.95
+
+ ! As if DEF_USE_WUEST=.false., pco2i_c=pco2i_e=pco2i
+ omc = vm * ( pco2i_c-gammas ) / ( pco2i_c + rrkk ) * c3 + vm * c4
+ ome = epar * ( pco2i_e-gammas ) / ( pco2i_e+2.*gammas ) * c3 + epar * c4
+ !IF(.not. DEF_USE_WUEST .or. epar .lt. 1.e-12)THEN
+ IF(.not. DEF_USE_WUEST .or. abs(c4 - 1) .lt. 0.001)THEN
+ oms = omss * c3 + omss*pco2i * c4
+
+ sqrtin= max( 0., ( (ome+omc)**2 - 4.*atheta*ome*omc ) )
+ omp = ( ( ome+omc ) - sqrt( sqrtin ) ) / ( 2.*atheta )
+ sqrtin= max( 0., ( (omp+oms)**2 - 4.*btheta*omp*oms ) )
+ assim = max( 0., ( ( oms+omp ) - sqrt( sqrtin ) ) / ( 2.*btheta ))
+ ELSE
+ assim = max( 0., min(omc, ome))
+ ENDIF
+ !print*,'assimn',assim,omc,ome
+ assimn= ( assim - respc) ! mol m-2 s-1
+
+!-----------------------------------------------------------------------
+! STOMATAL CONDUCTANCE
+!
+! (1) pathway for co2 flux
+! co2m
+! o
+! |
+! |
+! < |
+! 1.37/gsh2o > | Ac-Rd-Rsoil
+! < v
+! |
+! <--- Ac-Rd |
+! o------/\/\/\/\/\------o------/\/\/\/\/\------o
+! co2i 1.6/gsh2o co2s 1.37/gbh2o co2a
+! | ^
+! | | Rsoil
+! | |
+!
+! (2) pathway for water vapor flux
+!
+! em
+! o
+! |
+! |
+! < ^
+! 1/gsh2o > | Ea
+! < |
+! |
+! ---> Ec !
+! o------/\/\/\/\/\------o------/\/\/\/\/\------o
+! ei 1/gsh2o es 1/gbh2o ea
+! | ^
+! | | Eg
+! | |
+!
+! (3) the relationship between net assimilation and tomatal conductance :
+! gsh2o = m * An * [es/ei] / [pco2s/p] + b
+! es = [gsh2o *ei + gbh2o * ea] / [gsh2o + gbh2o]
+! ===>
+! a*gsh2o^2 + b*gsh2o + c = 0
+!
+!-----------------------------------------------------------------------
+
+ co2s = co2a - 1.37*assimn/gbh2o ! mol mol-1
+
+ co2st = min( co2s, co2a )
+ co2st = max( co2st,1.e-5 )
+
+ assmt = max( 1.e-12, assimn )
+
+ !IF(DEF_USE_WUEST .and. epar .ge. 1.e-12)THEN
+ IF(DEF_USE_WUEST .and. .not. abs(c4 - 1) .lt. 0.001)THEN
+ IF(omc .lt. ome)THEN
+ pco2i = pco2i_c
+ ELSE
+ pco2i = pco2i_e
+ ENDIF
+ gsh2o = assmt / (co2a - pco2i/psrf)*1.6
+ pco2in = pco2i ! No need to iteratively solve pco2i for WUE model.
+ ! Let pco2in = pco2i to exit loop.
+ IF(pco2i .gt. pco2a)THEN
+ write(*,*) 'warning: pco2i greater than pco2a, use bb model'
+ ENDIF
+ ELSE
+ IF(DEF_USE_MEDLYNST)THEN
+ vpd = amax1((ei - ea),50._r8) * 1.e-3 ! in kpa
+ acp = 1.6*assmt/co2st ! in mol m-2 s-1
+ aquad = 1._r8
+ bquad = -2*(g0*1.e-6 + acp) - (g1*acp)**2/(gbh2o*vpd) ! in mol m-2 s-1
+ cquad = (g0*1.e-6)**2 + (2*g0*1.e-6+acp*(1-g1**2)/vpd)*acp ! in (mol m-2 s-1)**2
+
+ sqrtin= max( 0., ( bquad**2 - 4.*aquad*cquad ) )
+ gsh2o = ( -bquad + sqrt ( sqrtin ) ) / (2.*aquad)
+
+ ELSE
+ hcdma = ei*co2st / ( gradm*assmt )
+
+ aquad = hcdma
+ bquad = gbh2o*hcdma - ei - bintc*hcdma
+ cquad = -gbh2o*( ea + hcdma*bintc )
+
+ sqrtin= max( 0., ( bquad**2 - 4.*aquad*cquad ) )
+ gsh2o = ( -bquad + sqrt ( sqrtin ) ) / (2.*aquad)
+
+ es = ( gsh2o-bintc ) * hcdma ! pa
+ es = min( es, ei )
+ es = max( es, 1.e-2)
+
+ gsh2o = es/hcdma + bintc ! mol m-2 s-1
+ ENDIF
+
+ pco2in = ( co2s - 1.6 * assimn / gsh2o )*psrf ! pa
+ ENDIF
+ eyy(ic) = pco2i - pco2in ! pa
+
+!-----------------------------------------------------------------------
+
+ IF( abs(eyy(ic)) .lt. 0.1 ) EXIT
+
+ ENDDO ITERATION_LOOP
+
+! convert gsh2o (mol m-2 s-1) to resistance rst ( s m-1)
+ rst = min( 1.e6, 1./(gsh2o*tlef/tprcor) ) ! s m-1
+
+ END SUBROUTINE stomata
+
+
+
+ SUBROUTINE sortin( eyy, pco2y, range, gammas, ic, iterationtotal )
+
+!-----------------------------------------------------------------------
+! arranges successive pco2/error pairs in order of increasing pco2.
+! estimates next guess for pco2 using combination of linear and
+! quadratic fits.
+!
+! original author: P. J. Sellers (SiB2)
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ic,iterationtotal
+ real(r8), intent(in) :: range
+ real(r8), intent(in) :: gammas
+ real(r8), intent(inout), dimension(iterationtotal) :: eyy, pco2y
+
+!-------------------------- Local Variables ----------------------------
+ integer i, j, n, i1, i2, i3, is, isp, ix
+ real(r8) a, b, pmin, emin, eyy_a
+ real(r8) pco2b, pco2yl, pco2yq
+ real(r8) ac1, ac2, bc1, bc2, cc1, cc2
+ real(r8) bterm, aterm, cterm
+
+!-----------------------------------------------------------------------
+
+ IF( ic .ge. 4 ) go to 500
+ eyy_a = 1.0
+ IF(eyy(1).lt.0.) eyy_a = -1.0
+ pco2y(1) = gammas + 0.5*range
+ pco2y(2) = gammas + range*( 0.5 - 0.3*eyy_a )
+ pco2y(3) = pco2y(1) - (pco2y(1)-pco2y(2))/(eyy(1)-eyy(2)+1.e-10)*eyy(1)
+
+ pmin = min( pco2y(1), pco2y(2) )
+ emin = min( eyy(1), eyy(2) )
+ IF ( emin .gt. 0. .and. pco2y(3) .gt. pmin ) pco2y(3) = gammas
+ go to 200
+500 continue
+
+ n = ic - 1
+ DO 1000 j = 2, n
+ a = eyy(j)
+ b = pco2y(j)
+ DO 2000 i = j-1,1,-1
+ IF(eyy(i) .le. a ) go to 100
+ eyy(i+1) = eyy(i)
+ pco2y(i+1) = pco2y(i)
+2000 continue
+ i = 0
+100 eyy(i+1) = a
+ pco2y(i+1) = b
+1000 continue
+
+ pco2b = 0.
+ is = 1
+ DO 3000 ix = 1, n
+ IF( eyy(ix) .lt. 0. ) pco2b = pco2y(ix)
+ IF( eyy(ix) .lt. 0. ) is = ix
+3000 continue
+ i1 = is-1
+ i1 = max(1, i1)
+ i1 = min(n-2, i1)
+ i2 = i1 + 1
+ i3 = i1 + 2
+ isp = is + 1
+ isp = min( isp, n )
+ is = isp - 1
+
+ pco2yl=pco2y(is) - (pco2y(is)-pco2y(isp))/(eyy(is)-eyy(isp)+1.e-10)*eyy(is)
+
+!----------------------------------------------------------------------
+! method using a quadratic fit
+!----------------------------------------------------------------------
+
+ ac1 = eyy(i1)*eyy(i1) - eyy(i2)*eyy(i2)
+ ac2 = eyy(i2)*eyy(i2) - eyy(i3)*eyy(i3)
+ bc1 = eyy(i1) - eyy(i2)
+ bc2 = eyy(i2) - eyy(i3)
+ cc1 = pco2y(i1) - pco2y(i2)
+ cc2 = pco2y(i2) - pco2y(i3)
+ bterm = (cc1*ac2-cc2*ac1)/(bc1*ac2-ac1*bc2+1.e-10)
+ aterm = (cc1-bc1*bterm)/(ac1+1.e-10)
+ cterm = pco2y(i2) - aterm*eyy(i2)*eyy(i2) - bterm*eyy(i2)
+ pco2yq= cterm
+ pco2yq= max( pco2yq, pco2b )
+ pco2y(ic) = ( pco2yl+pco2yq)/2.
+
+200 continue
+
+ pco2y(ic) = max ( pco2y(ic), 0.01 )
+
+ END SUBROUTINE sortin
+
+ SUBROUTINE calc_photo_params(tlef, po2m, par , psrf, rstfac, rb, effcon, vmax25, c3c4, &
+ trop, slti, hlti, shti, hhti, trda, trdm, cint, &
+ vm, epar, respc, omss, gbh2o, gammas, rrkk, c3, c4)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8),intent(in) :: &
+ tlef, &! leaf temperature (K)
+ po2m, &! O2 concentration in atmos. (pascals)
+ par, &! photosynthetic active radiation (W m-2)
+ rstfac, &! canopy resistance stress factors to soil moisture
+ rb, &! boundary resistance from canopy to cas (s m-1)
+
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2 / mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ ! the range : 30.e-6 <-> 100.e-6 (mol co2 m-2 s-1)
+ trop, &! temperature coefficient in gs-a model (298.16)
+ slti, &! slope of low temperature inhibition function (0.2)
+ hlti, &! 1/2 point of low temperature inhibition function (288.16)
+ shti, &! slope of high temperature inhibition function (0.3)
+ hhti, &! 1/2 point of high temperature inhibition function (313.16)
+ trda, &! temperature coefficient in gs-a model (1.3)
+ trdm, &! temperature coefficient in gs-a model (328.16)
+ psrf ! surface atmospheric pressure (pa)
+
+ integer, intent(in) :: &
+ c3c4 ! 1 for c3, 0 for c4
+
+ real(r8),intent(in), dimension(3) :: &
+ cint ! scaling up from leaf to canopy
+
+ real(r8),intent(out) :: &
+ vm, &! maximum catalytic activity of Rubison (mol co2 m-2 s-1)
+ epar, &! electron transport rate (mol electron m-2 s-1)
+ respc, &! canopy respiration (mol m-2 s-1)
+ omss, &! intermediate calcuation for oms
+ gbh2o, &! one side leaf boundary layer conductance (mol m-2 s-1)
+ gammas, &! CO2 compensation point
+ rrkk, &! kc (1+o2/ko)
+ c3, &! c3 vegetation : 1; 0 for c4
+ c4 ! c4 vegetation : 1; 0 for c3
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ qt, &! (tleaf - 298.16) / 10
+ kc, &! Michaelis-Menten constant for co2
+ ko, &! Michaelis-Menten constant for o2
+ templ, &! intermediate value
+ temph, &! intermediate value
+ rgas, &! universal gas contant (8.314 J mol-1 K-1)
+ jmax25, &! potential rate of whole-chain electron transport at 25 C
+ jmax, &! potential rate of whole-chain electron transport (mol electron m-2 s-1)
+ respcp, &! respiration fraction of vmax (mol co2 m-2 s-1)
+ tprcor ! coefficient for unit transfer
+
+!-----------------------------------------------------------------------
+
+ c3 = 0.
+ IF (c3c4.eq.1) c3 = 1.
+ c4 = 1. - c3
+
+!-----------------------------------------------------------------------
+! dependence on leaf temperature
+! gammas - CO2 compensation point in the absence of day respiration
+! ko - Michaelis-Menton constant for carboxylation by Rubisco
+! kc - Michaelis-Menton constant for oxygenation by Rubisco
+!-----------------------------------------------------------------------
+
+ qt = 0.1*( tlef - trop )
+
+ kc = 30. * 2.1**qt
+ ko = 30000. * 1.2**qt
+ gammas = 0.5 * po2m / (2600. * 0.57**qt) * c3 ! = 0. for c4 plant ???
+
+ rrkk = kc * ( 1. + po2m/ko ) * c3
+
+!----------------------------------------------------------------------
+! maximun capacity
+! vm - maximum catalytic activity of Rubisco in the presence of
+! saturating level of RuP2 and CO2 (mol m-2s-1)
+! jmax - potential rate of whole-chain electron transport (mol m-2s-1)
+! epar - electron transport rate for a given absorbed photon radiation
+! respc - dark resipration (mol m-2s-1)
+! omss - capacity of the leaf to export or utilize the products of photosynthesis.
+! binter - coefficient from observation, 0.01 for c3 plant, 0.04 for c4 plant
+!-----------------------------------------------------------------------
+
+ vm = vmax25 * 2.1**qt ! (mol m-2 s-1)
+ templ = 1. + exp(slti*(hlti-tlef))
+ temph = 1. + exp(shti*(tlef-hhti))
+ vm = vm / temph * rstfac * c3 + vm / (templ*temph) * rstfac * c4
+ vm = vm * cint(1)
+
+ rgas = 8.314467591 ! universal gas constant (J mol-1 K-1)
+!---> jmax25 = 2.39 * vmax25 - 14.2e-6 ! (mol m-2 s-1)
+!---> jmax25 = 2.1 * vmax25 ! (mol m-2 s-1)
+!/05/2014/
+ jmax25 = 1.97 * vmax25 ! (mol m-2 s-1)
+ jmax = jmax25 * exp( 37.e3 * (tlef - trop) / (rgas*trop*tlef) ) * &
+ ( 1. + exp( (710.*trop-220.e3)/(rgas*trop) ) ) / &
+ ( 1. + exp( (710.*tlef-220.e3)/(rgas*tlef) ) )
+ ! 37000 (J mol-1)
+ ! 220000 (J mol-1)
+ ! 710 (J K-1)
+
+ jmax = jmax * rstfac
+ jmax = jmax * cint(2)
+
+!---> epar = min(4.6e-6 * par * effcon, 0.25*jmax)
+! /05/2014/
+ epar = min(4.6e-6 * par * effcon, jmax)
+
+ respcp = 0.015 * c3 + 0.025 * c4
+ respc = respcp * vmax25 * 2.0**qt / ( 1. + exp( trda*(tlef-trdm )) ) * rstfac
+! respc = 0.7e-6 * 2.0**qt / ( 1. + exp( trda*(tlef-trdm )) ) * rstfac
+ respc = respc * cint(1)
+
+ omss = ( vmax25/2. ) * (1.8**qt) / templ * rstfac * c3 &
+ + ( vmax25/5. ) * (1.8**qt) * rstfac * c4
+ omss = omss * cint(1)
+
+!-----------------------------------------------------------------------
+ tprcor = 44.6*273.16*psrf/1.013e5
+
+! one side leaf boundary layer conductance for water vapor [=1/(2*rb)]
+! ATTENTION: rb in CLM is for one side leaf, but for SiB2 rb for
+! 2-side leaf, so the gbh2o shold be " 0.5/rb * tprcor/tlef "
+! gbh2o = 0.5/rb * tprcor/tlef ! mol m-2 s-1
+ gbh2o = 1./rb * tprcor/tlef ! mol m-2 s-1
+
+! rb is for single leaf, but here the flux is for canopy, thus
+ ! Xingjie Lu: rb has already been converted to canopy scale,
+ ! thus, there is no need for gbh2o *cint(3) (sunlit/shaded LAI)
+! gbh2o = gbh2o * cint(3)
+
+ END SUBROUTINE calc_photo_params
+
+ SUBROUTINE update_photosyn(tlef, po2m, pco2m, pco2a, par, psrf, rstfac, rb, gsh2o,&
+ effcon, vmax25, c3c4, gradm, trop, slti, hlti, shti, hhti, trda, trdm, cint,&
+ assim, respc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8),intent(in) :: &
+ tlef, &! leaf temperature (K)
+ po2m, &! O2 concentration in atmos. (pascals)
+ pco2m, &! CO2 concentration in atmos. (pascals)
+ pco2a, &! CO2 concentration in canopy air space (pa)
+ par, &! photosynthetic active radiation (W m-2)
+ psrf, &! surface atmospheric pressure (pa)
+ rstfac, &! canopy resistance stress factors to soil moisture
+ rb, &! boundary resistance from canopy to cas (s m-1)
+ gsh2o, &! canopy conductance (mol m-2 s-1)
+
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2 / mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ ! the range : 30.e-6 <-> 100.e-6 (mol co2 m-2 s-1)
+ gradm, &! conductance-photosynthesis slope parameter
+ trop, &! temperature coefficient in gs-a model (298.16)
+ slti, &! slope of low temperature inhibition function (0.2)
+ hlti, &! 1/2 point of low temperature inhibition function (288.16)
+ shti, &! slope of high temperature inhibition function (0.3)
+ hhti, &! 1/2 point of high temperature inhibition function (313.16)
+ trda, &! temperature coefficient in gs-a model (1.3)
+ trdm ! temperature coefficient in gs-a model (328.16)
+
+ integer, intent(in) :: &
+ c3c4 ! 1 for c3, 0 for c4
+
+ real(r8),intent(in), dimension(3) :: &
+ cint ! scaling up from leaf to canopy
+
+ real(r8),intent(out) :: &
+ assim, &! canopy assimilation rate (mol m-2 s-1)
+ respc ! canopy respiration (mol m-2 s-1)
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ vm, &! maximum catalytic activity of Rubison (mol co2 m-2 s-1)
+ epar, &! electron transport rate (mol electron m-2 s-1)
+ gbh2o, &! one side leaf boundary layer conductance (mol m-2 s-1)
+ gammas, &! CO2 compensation point
+ rrkk, &! kc (1+o2/ko)
+ c3, &! c3 vegetation : 1; 0 for c4
+ c4 ! c4 vegetation : 1; 0 for c3
+
+ real(r8) :: &
+ atheta, &! wc, we coupling parameter
+ btheta, &! wc & we, ws coupling parameter
+ omss, &! intermediate calcuation for oms
+ omc, &! rubisco limited assimilation (omega-c: mol m-2 s-1)
+ ome, &! light limited assimilation (omega-e: mol m-2 s-1)
+ oms, &! sink limited assimilation (omega-s: mol m-2 s-1)
+ omp, &! intermediate calcuation for omc, ome
+
+ co2a, &! co2 concentration at cas (mol mol-1)
+ co2s, &! co2 concentration at canopy surface (mol mol-1)
+ co2st, &! co2 concentration at canopy surface (mol mol-1)
+ co2i, &! internal co2 concentration (mol mol-1)
+ pco2in, &! internal co2 concentration at the new iteration (pa)
+ pco2i, &! internal co2 concentration (pa)
+ es, &! canopy surface h2o vapor pressure (pa)
+
+ sqrtin, &! intermediate calculation for quadratic
+ assmt, &! net assimilation with a positive limitation (mol co2 m-2 s-1)
+ assimn ! net assimilation (mol co2 m-2 s-1)
+
+ integer, parameter :: iterationtotal = 6 ! total iteration number in pco2i calculation
+
+ real(r8) :: &
+ eyy(iterationtotal), &! differnce of pco2i at two iteration step
+ pco2y(iterationtotal), &! adjusted to total iteration number
+ range !
+
+ integer ic
+!-----------------------------------------------------------------------
+
+ CALL calc_photo_params(tlef, po2m, par , psrf, rstfac, rb, effcon, vmax25, c3c4, &
+ trop, slti, hlti, shti, hhti, trda, trdm, cint, &
+ vm, epar, respc, omss, gbh2o, gammas, rrkk, c3, c4)
+
+ co2a = pco2a/psrf
+
+ range = pco2m * ( 1. - 1.6/gradm ) - gammas
+
+ DO ic = 1, iterationtotal ! loop for total iteration number
+ pco2y(ic) = 0.
+ eyy(ic) = 0.
+ ENDDO
+
+ ITERATION_LOOP_UPDATE: DO ic = 1, iterationtotal
+
+ CALL sortin(eyy, pco2y, range, gammas, ic, iterationtotal)
+ pco2i = pco2y(ic)
+
+!-----------------------------------------------------------------------
+! NET ASSIMILATION
+! the leaf assimilation (or gross photosynthesis) rate is described
+! as the minimum of three limiting rates:
+! omc: the efficiency of the photosynthetic enzyme system (Rubisco-limited);
+! ome: the amount of PAR captured by leaf chlorophyll;
+! oms: the capacity of the leaf to export or utilize the products of photosynthesis.
+! to aviod the abrupt transitions, two quadratic equations are used:
+! atheta*omp^2 - omp*(omc+ome) + omc*ome = 0
+! btheta*assim^2 - assim*(omp+oms) + omp*oms = 0
+!-----------------------------------------------------------------------
+
+ atheta = 0.877
+ btheta = 0.95
+
+ omc = vm * ( pco2i-gammas ) / ( pco2i + rrkk ) * c3 + vm * c4
+ ome = epar * ( pco2i-gammas ) / ( pco2i+2.*gammas ) * c3 + epar * c4
+ IF(.not. DEF_USE_WUEST .or. abs(c4 - 1) .lt. 0.001)THEN
+ oms = omss * c3 + omss*pco2i * c4
+
+ sqrtin= max( 0., ( (ome+omc)**2 - 4.*atheta*ome*omc ) )
+ omp = ( ( ome+omc ) - sqrt( sqrtin ) ) / ( 2.*atheta )
+ sqrtin= max( 0., ( (omp+oms)**2 - 4.*btheta*omp*oms ) )
+ assim = max( 0., ( ( oms+omp ) - sqrt( sqrtin ) ) / ( 2.*btheta ))
+ ELSE
+ assim = max( 0., min(omc, ome))
+ ENDIF
+
+ assimn= ( assim - respc) ! mol m-2 s-1
+
+!-----------------------------------------------------------------------
+! STOMATAL CONDUCTANCE
+!
+! (1) pathway for co2 flux
+! co2m
+! o
+! |
+! |
+! < |
+! 1.37/gsh2o > | Ac-Rd-Rsoil
+! < v
+! |
+! <--- Ac-Rd |
+! o------/\/\/\/\/\------o------/\/\/\/\/\------o
+! co2i 1.6/gsh2o co2s 1.37/gbh2o co2a
+! | ^
+! | | Rsoil
+! | |
+!
+! (2) pathway for water vapor flux
+!
+! em
+! o
+! |
+! |
+! < ^
+! 1/gsh2o > | Ea
+! < |
+! |
+! ---> Ec !
+! o------/\/\/\/\/\------o------/\/\/\/\/\------o
+! ei 1/gsh2o es 1/gbh2o ea
+! | ^
+! | | Eg
+! | |
+!
+! (3) the relationship between net assimilation and tomatal conductance :
+! gsh2o = m * An * [es/ei] / [pco2s/p] + b
+! es = [gsh2o *ei + gbh2o * ea] / [gsh2o + gbh2o]
+! ===>
+! a*gsh2o^2 + b*gsh2o + c = 0
+!
+!-----------------------------------------------------------------------
+
+ co2s = co2a - 1.37*assimn/gbh2o ! mol mol-1
+ co2st = min( co2s, co2a )
+ co2st = max( co2st,1.e-5 )
+
+ assmt = max( 1.e-12, assimn )
+
+
+ pco2in = ( co2s - 1.6 * assmt / gsh2o )*psrf ! pa
+
+ eyy(ic) = pco2i - pco2in ! pa
+
+!-----------------------------------------------------------------------
+
+ IF( abs(eyy(ic)) .lt. 0.1 ) EXIT
+
+ ENDDO ITERATION_LOOP_UPDATE
+
+ END SUBROUTINE update_photosyn
+
+ SUBROUTINE WUE_solver(gammas, lambda, co2a, ei, ea, psrf, pco2i_c, pco2i_e)
+
+!-----------------------------------------------------------------------
+! Solve internal co2 concentration for Rubisco limit and RuBP regeneration limit.
+!
+! When Rubisco is limit (omc < ome), solve following equation (Liang et al., 2023, S18a)
+! for pco2i_c:
+! {1-(1.6*D)/[lambda*(gammas+rrkk)]} * co2i_c^2 &
+! - {2*co2a+[1.6*D*(rrkk-gammas)]/[lambda*(gammas+rrkk)]-(1.6*D)/lambda} * co2i_c &
+! + {co2a^2 - (1.6*D*co2a)/lambda + (1.6*D*rrkk*gammas)/[lambda*(gammas+rrkk)]} = 0
+!
+! When RuBP is limit (omc>=ome), solve following equation (Liang et al., 2023, S18b)
+! for pco2i_e:
+! [1-(1.6*D)/(3*lambda*gammas)] * co2i_e^2 &
+! - [2*co2a-(3.2*D)/(3*lambda)] * co2i_e &
+! + [co2a^2 - (1.6*D*co2a)/lambda + (3.2*D*gammas)/(3*lambda)] = 0
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8),intent(in) :: &
+ gammas, &! CO2 compensation point (pa)
+ lambda, &! marginal water use efficiency ((mol h2o) (mol co2)-1)
+ co2a, &! co2 concentration at cas ((mol co2) (mol air)-1)
+ ea, &! canopy air space vapor pressure (pa)
+ ei, &! saturation h2o vapor pressure in leaf stomata (pa)
+ psrf ! air pressure (pa)
+
+ real(r8),intent(out) :: &
+ pco2i_c, &! internal co2 concentration when Rubisco is limited (pa)
+ pco2i_e ! internal co2 concentration when RuBP regeneration is limited (pa)
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ D, &! leaf-to-air-vapour mole fraction difference ((mol h2o) (mol air)-1)
+ co2i_c, &! internal co2 concentration when Rubisco is limited ((mol co2) (mol air)-1)
+ co2i_e ! internal co2 concentration when RuBP is limited ((mol co2) (mol air)-1)
+
+!-----------------------------------------------------------------------
+
+ ! solve co2i_c
+ D = amax1((ei - ea),50._r8) / psrf
+
+ co2i_c = co2a - sqrt(1.6*D*(amax1(co2a-gammas/psrf,0._r8))/lambda)
+ co2i_e = co2a - co2a / ( 1 + 1.37 * sqrt(lambda * gammas/psrf / D))
+
+ pco2i_c = co2i_c * psrf
+ pco2i_e = co2i_e * psrf
+
+ END SUBROUTINE WUE_solver
+
+END MODULE MOD_AssimStomataConductance
+! -------------- EOP ---------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_CanopyLayerProfile.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_CanopyLayerProfile.F90
new file mode 100644
index 0000000000..4f9da1a27e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_CanopyLayerProfile.F90
@@ -0,0 +1,730 @@
+#include
+
+MODULE MOD_CanopyLayerProfile
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER SUBROUTINE/FUNCTIONS:
+
+ PUBLIC :: uprofile, kprofile
+ PUBLIC :: uintegral, uintegralz, kintegral
+ PUBLIC :: ueffect, ueffectz, fuint, fkint, frd
+ PUBLIC :: udiff, kdiff, ufindroots, kfindroots
+
+ PUBLIC :: cal_z0_displa
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+ real(r8) FUNCTION uprofile(utop, fc, bee, alpha, z0mg, htop, hbot, z)
+
+ USE MOD_Precision
+ USE MOD_FrictionVelocity
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: utop
+ real(r8), intent(in) :: fc
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: z0mg
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+ real(r8), intent(in) :: z
+
+ real(r8) :: ulog,uexp
+
+ ! A simple version of wind profile based on Dai et al., 2019.
+ ! A combination of u of canopy area and bare soil wighted by
+ ! their fractional cover.
+ !
+ ! - Canopy area wind: min(uexp, ulog) - bare soil: ulog
+ ! fc: vegetation fractional cover, bee: free parameter = 1.
+
+ ulog = utop*log(z/z0mg)/log(htop/z0mg)
+ uexp = utop*exp(-alpha*(1-(z-hbot)/(htop-hbot)))
+
+ uprofile = bee*fc*min(uexp,ulog) + (1-bee*fc)*ulog
+
+ RETURN
+ END FUNCTION uprofile
+
+
+ ! Exchange coefficient K profile based on Dai et al., 2019.
+ real(r8) FUNCTION kprofile(ktop, fc, bee, alpha, &
+ displah, htop, hbot, obu, ustar, z)
+
+ USE MOD_Precision
+ USE MOD_FrictionVelocity
+ IMPLICIT NONE
+
+ real(r8), parameter :: com1 = 0.4
+ real(r8), parameter :: com2 = 0.08
+
+ real(r8), intent(in) :: ktop
+ real(r8), intent(in) :: fc
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: displah
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+ real(r8), intent(in) :: obu
+ real(r8), intent(in) :: ustar
+ real(r8), intent(in) :: z
+
+ real(r8) :: fac
+ real(r8) :: kcob, klin, kexp
+
+ klin = ktop*z/htop
+
+ fac = 1. / (1.+exp(-(displah-com1)/com2))
+ kcob = 1. / (fac/klin + (1.-fac)/kmoninobuk(0.,obu,ustar,z))
+
+ kexp = ktop*exp(-alpha*(htop-z)/(htop-hbot))
+ kprofile = 1./( bee*fc/min(kexp,kcob) + (1-bee*fc)/kcob )
+
+ RETURN
+ END FUNCTION kprofile
+
+
+ ! numerical solution for wind profile integration (not used now)
+ real(r8) FUNCTION uintegral(utop, fc, bee, alpha, z0mg, htop, hbot)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: utop
+ real(r8), intent(in) :: fc
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: z0mg
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+
+ integer :: i, n
+ real(r8) :: dz, z, u
+
+ ! 09/26/2017: change fixed n -> fixed dz
+ dz = 0.001
+ n = int( (htop-hbot) / dz ) + 1
+
+ uintegral = 0.
+
+ DO i = 1, n
+ IF (i < n) THEN
+ z = htop - (i-0.5)*dz
+ ELSE
+ dz = htop - hbot - (n-1)*dz
+ z = hbot + 0.5*dz
+ ENDIF
+
+ u = uprofile(utop, fc, bee, alpha, z0mg, htop, hbot, z)
+
+ u = max(0._r8, u)
+ !uintegral = uintegral + sqrt(u)*dz / (htop-hbot)
+ ! 03/04/2020, yuan: NOTE: the above is hard to solve
+ !NOTE: The integral cannot be solved analytically after
+ !the square root sign of u, and the integral can be approximated
+ !directly for u, In this way, there is no need to square
+ uintegral = uintegral + u*dz / (htop-hbot)
+ ENDDO
+
+ RETURN
+ END FUNCTION uintegral
+
+
+ ! numerical solution for wind profile integration (not used now)
+ real(r8) FUNCTION uintegralz(utop, fc, bee, alpha, z0mg, &
+ htop, hbot, ztop, zbot)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: utop
+ real(r8), intent(in) :: fc
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: z0mg
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+ real(r8), intent(in) :: ztop
+ real(r8), intent(in) :: zbot
+
+ integer :: i, n
+ real(r8) :: dz, z, u
+
+ ! 09/26/2017: change fixed n -> fixed dz
+ dz = 0.001
+ n = int( (ztop-zbot) / dz ) + 1
+
+ uintegralz = 0.
+
+ DO i = 1, n
+ IF (i < n) THEN
+ z = ztop - (i-0.5)*dz
+ ELSE
+ dz = ztop - zbot - (n-1)*dz
+ z = zbot + 0.5*dz
+ ENDIF
+
+ u = uprofile(utop, fc, bee, alpha, z0mg, htop, hbot, z)
+
+ u = max(0._r8, u)
+ !uintegral = uintegral + sqrt(u)*dz / (htop-hbot)
+ ! 03/04/2020, yuan: NOTE: the above is hard to solve
+ !NOTE: The integral cannot be solved analytically after
+ !the square root sign of u, and the integral can be approximated
+ !directly for u, In this way, there is no need to square
+ uintegralz = uintegralz + u*dz / (ztop-zbot)
+ ENDDO
+
+ RETURN
+ END FUNCTION uintegralz
+
+
+ real(r8) FUNCTION ueffect(utop, htop, hbot, &
+ z0mg, alpha, bee, fc)
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: utop
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+ real(r8), intent(in) :: z0mg
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: fc
+
+ real(r8) :: roots(2), uint
+ integer :: rootn
+
+ rootn = 0
+ uint = 0.
+
+ ! The dichotomy method to find the root satisfies a certain accuracy,
+ ! assuming that there are at most 2 roots
+ CALL ufindroots(htop,hbot,(htop+hbot)/2., &
+ utop, htop, hbot, z0mg, alpha, roots, rootn)
+
+ IF (rootn == 0) THEN !no root
+ uint = uint + fuint(utop, htop, hbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+ ENDIF
+
+ IF (rootn == 1) THEN
+ uint = uint + fuint(utop, htop, roots(1), &
+ htop, hbot, z0mg, alpha, bee, fc)
+ uint = uint + fuint(utop, roots(1), hbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+ ENDIF
+
+ IF (rootn == 2) THEN
+ uint = uint + fuint(utop, htop, roots(1), &
+ htop, hbot, z0mg, alpha, bee, fc)
+ uint = uint + fuint(utop, roots(1), roots(2), &
+ htop, hbot, z0mg, alpha, bee, fc)
+ uint = uint + fuint(utop, roots(2), hbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+ ENDIF
+
+ ueffect = uint / (htop-hbot)
+
+ RETURN
+ END FUNCTION ueffect
+
+
+ ! Calculate the effective wind speed between ztop and zbot
+ real(r8) FUNCTION ueffectz(utop, htop, hbot, &
+ ztop, zbot, z0mg, alpha, bee, fc)
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: utop
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+ real(r8), intent(in) :: ztop
+ real(r8), intent(in) :: zbot
+ real(r8), intent(in) :: z0mg
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: fc
+
+ real(r8) :: roots(2), uint
+ integer :: rootn
+
+ rootn = 0
+ uint = 0.
+
+ ! The dichotomy method to find the root satisfies a certain accuracy,
+ ! assuming that there are at most 2 roots
+ CALL ufindroots(ztop,zbot,(ztop+zbot)/2., &
+ utop, htop, hbot, z0mg, alpha, roots, rootn)
+
+ IF (rootn == 0) THEN !no root
+ uint = uint + fuint(utop, ztop, zbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+ ENDIF
+
+ IF (rootn == 1) THEN
+ uint = uint + fuint(utop, ztop, roots(1), &
+ htop, hbot, z0mg, alpha, bee, fc)
+ uint = uint + fuint(utop, roots(1), zbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+ ENDIF
+
+ IF (rootn == 2) THEN
+ uint = uint + fuint(utop, ztop, roots(1), &
+ htop, hbot, z0mg, alpha, bee, fc)
+ uint = uint + fuint(utop, roots(1), roots(2), &
+ htop, hbot, z0mg, alpha, bee, fc)
+ uint = uint + fuint(utop, roots(2), zbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+ ENDIF
+
+ ueffectz = uint / (ztop-zbot)
+
+ RETURN
+ END FUNCTION ueffectz
+
+
+ real(r8) FUNCTION fuint(utop, ztop, zbot, &
+ htop, hbot, z0mg, alpha, bee, fc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: utop, ztop, zbot
+ real(r8), intent(in) :: htop, hbot
+ real(r8), intent(in) :: z0mg, alpha
+ real(r8), intent(in) :: bee, fc
+
+ ! local variables
+ real(r8) :: fuexpint, fulogint
+
+ fulogint = utop/log(htop/z0mg) *&
+ (ztop*log(ztop/z0mg) - zbot*log(zbot/z0mg) + zbot - ztop)
+
+ IF (udiff((ztop+zbot)/2.,utop,htop,hbot,z0mg,alpha) <= 0) THEN
+ ! uexp is smaller
+ fuexpint = utop*(htop-hbot)/alpha*( &
+ exp(-alpha*(htop-ztop)/(htop-hbot))-&
+ exp(-alpha*(htop-zbot)/(htop-hbot)) )
+
+ fuint = bee*fc*fuexpint + (1.-bee*fc)*fulogint
+ ELSE
+ ! ulog is smaller
+ fuint = fulogint
+ ENDIF
+
+ RETURN
+ END FUNCTION fuint
+
+
+ RECURSIVE SUBROUTINE ufindroots(ztop,zbot,zmid, &
+ utop, htop, hbot, z0mg, alpha, roots, rootn)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: ztop, zbot, zmid
+ real(r8), intent(in) :: utop, htop, hbot
+ real(r8), intent(in) :: z0mg, alpha
+
+ real(r8), intent(inout) :: roots(2)
+ integer, intent(inout) :: rootn
+
+ ! local variables
+ real(r8) :: udiff_ub, udiff_lb
+
+ udiff_ub = udiff(ztop,utop,htop,hbot,z0mg,alpha)
+ udiff_lb = udiff(zmid,utop,htop,hbot,z0mg,alpha)
+
+ IF (udiff_ub*udiff_lb == 0) THEN
+ IF (udiff_lb == 0) THEN !root found
+ rootn = rootn + 1
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: U root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = zmid
+ ENDIF
+ ELSEIF (udiff_ub*udiff_lb < 0) THEN
+ IF (ztop-zmid < 0.01) THEN
+ rootn = rootn + 1 !root found
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: U root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = (ztop+zmid)/2.
+ ELSE
+ CALL ufindroots(ztop,zmid,(ztop+zmid)/2., &
+ utop, htop, hbot, z0mg, alpha, roots, rootn)
+ ENDIF
+ ENDIF
+
+ udiff_ub = udiff(zmid,utop,htop,hbot,z0mg,alpha)
+ udiff_lb = udiff(zbot,utop,htop,hbot,z0mg,alpha)
+
+ IF (udiff_ub*udiff_lb == 0) THEN
+ IF (udiff_ub == 0) THEN !root found
+ rootn = rootn + 1
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: U root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = zmid
+ ENDIF
+ ELSEIF (udiff_ub*udiff_lb < 0) THEN
+ IF (zmid-zbot < 0.01) THEN
+ rootn = rootn + 1 !root found
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: U root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = (zmid+zbot)/2.
+ ELSE
+ CALL ufindroots(zmid,zbot,(zmid+zbot)/2., &
+ utop, htop, hbot, z0mg, alpha, roots, rootn)
+ ENDIF
+ ENDIF
+ END SUBROUTINE ufindroots
+
+
+ real(r8) FUNCTION udiff(z, utop, htop, hbot, z0mg, alpha)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: z, utop, htop, hbot
+ real(r8), intent(in) :: z0mg, alpha
+
+ real(r8) :: uexp, ulog
+
+ uexp = utop*exp(-alpha*(htop-z)/(htop-hbot))
+ ulog = utop*log(z/z0mg)/log(htop/z0mg)
+
+ udiff = uexp - ulog
+
+ RETURN
+ END FUNCTION udiff
+
+
+ ! numerical solution for K profile integration (not used now)
+ real(r8) FUNCTION kintegral(ktop, fc, bee, alpha, z0mg, &
+ displah, htop, hbot, obu, ustar, ztop, zbot)
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: ktop
+ real(r8), intent(in) :: fc
+ real(r8), intent(in) :: bee
+ real(r8), intent(in) :: alpha
+ real(r8), intent(in) :: z0mg
+ real(r8), intent(in) :: displah
+ real(r8), intent(in) :: htop
+ real(r8), intent(in) :: hbot
+ real(r8), intent(in) :: obu
+ real(r8), intent(in) :: ustar
+ real(r8), intent(in) :: ztop
+ real(r8), intent(in) :: zbot
+
+ integer :: i, n
+ real(r8) :: dz, z, k
+
+ kintegral = 0.
+
+ IF (ztop <= zbot) THEN
+ RETURN
+ ENDIF
+
+ ! 09/26/2017: change fixed n -> fixed dz
+ dz = 0.001
+ n = int( (ztop-zbot) / dz ) + 1
+
+ DO i = 1, n
+ IF (i < n) THEN
+ z = ztop - (i-0.5)*dz
+ ELSE
+ dz = ztop - zbot - (n-1)*dz
+ z = zbot + 0.5*dz
+ ENDIF
+
+ k = kprofile(ktop, fc, bee, alpha, &
+ displah, htop, hbot, obu, ustar, z)
+
+ kintegral = kintegral + 1./k * dz
+
+ ENDDO
+
+ RETURN
+ END FUNCTION kintegral
+
+
+ real(r8) FUNCTION frd(ktop, htop, hbot, &
+ ztop, zbot, displah, z0h, obu, ustar, &
+ z0mg, alpha, bee, fc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: ktop, htop, hbot
+ real(r8), intent(in) :: ztop, zbot
+ real(r8), intent(in) :: displah, z0h, obu, ustar
+ real(r8), intent(in) :: z0mg, alpha, bee, fc
+
+ ! local parameters
+ real(r8), parameter :: com1 = 0.4
+ real(r8), parameter :: com2 = 0.08
+
+ real(r8) :: roots(2), fac, kint
+ integer :: rootn
+
+ rootn = 0
+ kint = 0.
+
+ ! calculate fac
+ fac = 1. / (1.+exp(-(displah-com1)/com2))
+ roots(:) = 0.
+
+ CALL kfindroots(ztop,zbot,(ztop+zbot)/2., &
+ ktop, htop, hbot, obu, ustar, fac, alpha, roots, rootn)
+
+ IF (rootn == 0) THEN !no root
+ kint = kint + fkint(ktop, ztop, zbot, htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+ ENDIF
+
+ IF (rootn == 1) THEN
+ kint = kint + fkint(ktop, ztop, roots(1), htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+ kint = kint + fkint(ktop, roots(1), zbot, htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+ ENDIF
+
+ IF (rootn == 2) THEN
+ kint = kint + fkint(ktop, ztop, roots(1), htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+ kint = kint + fkint(ktop, roots(1), roots(2), htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+ kint = kint + fkint(ktop, roots(2), zbot, htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+ ENDIF
+
+ frd = kint
+
+ RETURN
+ END FUNCTION frd
+
+
+ real(r8) FUNCTION fkint(ktop, ztop, zbot, htop, hbot, &
+ z0h, obu, ustar, fac, alpha, bee, fc)
+
+ USE MOD_Precision
+ USE MOD_FrictionVelocity
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: ktop, ztop, zbot
+ real(r8), intent(in) :: htop, hbot
+ real(r8), intent(in) :: z0h, obu, ustar, fac, alpha
+ real(r8), intent(in) :: bee, fc
+
+ ! local variables
+ real(r8) :: fkexpint, fkcobint
+
+ !NOTE:
+ ! klin = ktop*z/htop
+ ! kcob = 1./(fac/klin + (1.-fac)/kmoninobuk(0.,obu,ustar,z))
+ fkcobint = fac*htop/ktop*(log(ztop)-log(zbot)) +&
+ (1.-fac)*kintmoninobuk(0.,z0h,obu,ustar,ztop,zbot)
+
+ IF (kdiff((ztop+zbot)/2.,ktop,htop,hbot,obu,ustar,fac,alpha) <= 0) THEN
+ ! kexp is smaller
+ IF (alpha > 0) THEN
+ fkexpint = -(htop-hbot)/alpha/ktop*( &
+ exp(alpha*(htop-ztop)/(htop-hbot))-&
+ exp(alpha*(htop-zbot)/(htop-hbot)) )
+ ELSE
+ fkexpint = (ztop-zbot)/ktop
+ ENDIF
+
+ fkint = bee*fc*fkexpint + (1.-bee*fc)*fkcobint
+ ELSE
+ ! kcob is smaller
+ fkint = fkcobint
+ ENDIF
+
+ RETURN
+ END FUNCTION fkint
+
+
+ RECURSIVE SUBROUTINE kfindroots(ztop,zbot,zmid, &
+ ktop, htop, hbot, obu, ustar, fac, alpha, roots, rootn)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: ztop, zbot, zmid
+ real(r8), intent(in) :: ktop, htop, hbot
+ real(r8), intent(in) :: obu, ustar, fac, alpha
+
+ real(r8), intent(inout) :: roots(2)
+ integer, intent(inout) :: rootn
+
+ ! local variables
+ real(r8) :: kdiff_ub, kdiff_lb
+
+ ! CALL recursive SUBROUTINE kfindroots
+ kdiff_ub = kdiff(ztop,ktop,htop,hbot,obu,ustar,fac,alpha)
+ kdiff_lb = kdiff(zmid,ktop,htop,hbot,obu,ustar,fac,alpha)
+
+ IF (kdiff_ub*kdiff_lb == 0) THEN
+ IF (kdiff_lb == 0) THEN !root found
+ rootn = rootn + 1
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: K root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = zmid
+ ENDIF
+ ELSEIF (kdiff_ub*kdiff_lb < 0) THEN
+ IF (ztop-zmid < 0.01) THEN
+ rootn = rootn + 1 !root found
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: K root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = (ztop+zmid)/2.
+ ELSE
+ CALL kfindroots(ztop,zmid,(ztop+zmid)/2., &
+ ktop, htop, hbot, obu, ustar, fac, alpha, roots, rootn)
+ ENDIF
+ ENDIF
+
+ kdiff_ub = kdiff(zmid,ktop,htop,hbot,obu,ustar,fac,alpha)
+ kdiff_lb = kdiff(zbot,ktop,htop,hbot,obu,ustar,fac,alpha)
+
+ IF (kdiff_ub*kdiff_lb == 0) THEN
+ IF (kdiff_ub == 0) THEN !root found
+ rootn = rootn + 1
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: K root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = zmid
+ ENDIF
+ ELSEIF (kdiff_ub*kdiff_lb < 0) THEN
+ IF (zmid-zbot < 0.01) THEN
+ rootn = rootn + 1 !root found
+ IF (rootn > 2) THEN
+ rootn = 2
+ print *, "Warning: K root number > 2, only the first 2 are used!"
+ RETURN !CALL abort
+ ENDIF
+ roots(rootn) = (zmid+zbot)/2.
+ ELSE
+ CALL kfindroots(zmid,zbot,(zmid+zbot)/2., &
+ ktop, htop, hbot, obu, ustar, fac, alpha, roots, rootn)
+ ENDIF
+ ENDIF
+ END SUBROUTINE kfindroots
+
+
+ real(r8) FUNCTION kdiff(z, ktop, htop, hbot, &
+ obu, ustar, fac, alpha)
+
+ USE MOD_Precision
+ USE MOD_FrictionVelocity
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: z, ktop, htop, hbot
+ real(r8), intent(in) :: obu, ustar, fac, alpha
+
+ real(r8) :: kexp, klin, kcob
+
+ kexp = ktop*exp(-alpha*(htop-z)/(htop-hbot))
+
+ klin = ktop*z/htop
+ kcob = 1./(fac/klin + (1.-fac)/kmoninobuk(0.,obu,ustar,z))
+
+ kdiff = kexp - kcob
+
+ RETURN
+ END FUNCTION kdiff
+
+
+ SUBROUTINE cal_z0_displa (lai, h, fc, z0, displa)
+
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: lai
+ real(r8), intent(in) :: h
+ real(r8), intent(in) :: fc
+ real(r8), intent(out) :: z0
+ real(r8), intent(out) :: displa
+
+ real(r8), parameter :: Cd = 0.2 !leaf drag coefficient
+ real(r8), parameter :: cd1 = 7.5 !a free parameter for d/h calculation, Raupach 1992, 1994
+ real(r8), parameter :: psih = 0.193 !psih = ln(cw) - 1 + cw^-1, cw = 2, Raupach 1994
+
+ ! local variables
+ real(r8) :: fai, sqrtdragc, temp1, delta , lai0
+
+ ! when assume z0=0.01, displa=0
+ ! to calculate lai0, delta displa
+ !----------------------------------------------------
+ sqrtdragc = -vonkar/(log(0.01/h) - psih)
+ sqrtdragc = max(sqrtdragc, 0.0031**0.5)
+ IF (sqrtdragc .le. 0.3) THEN
+ fai = (sqrtdragc**2-0.003) / 0.3
+ fai = min(fai, fc*(1-exp(-20.)))
+ ELSE
+ fai = 0.29
+ print *, "z0m, displa error!"
+ ENDIF
+
+ ! calculate delta displa when z0 = 0.01
+ lai0 = -log(1.-fai/fc)/0.5
+ temp1 = (2.*cd1*fai)**0.5
+ delta = -h * ( fc*1.1*log(1. + (Cd*lai0*fc)**0.25) + &
+ (1.-fc)*(1.-(1.-exp(-temp1))/temp1) )
+
+ ! calculate z0m, displa
+ !----------------------------------------------------
+ ! NOTE: potential bug below, only apply for spheric
+ ! crowns. For other cases, fc*(...) ==> a*fc*(...)
+ fai = fc*(1. - exp(-0.5*lai))
+ sqrtdragc = min( (0.003+0.3*fai)**0.5, 0.3 )
+ temp1 = (2.*cd1*fai)**0.5
+
+ IF (lai > lai0) THEN
+ displa = delta + h*( &
+ ( fc)*1.1*log(1. + (Cd*lai*fc)**0.25) + &
+ (1-fc)*(1.-(1.-exp(-temp1))/temp1) )
+ ELSE
+ displa = h*( &
+ ( fc)*1.1*log(1. + (Cd*lai*fc)**0.25) + &
+ (1-fc)*(1.-(1.-exp(-temp1))/temp1) )
+ ENDIF
+
+ displa = max(displa, 0.)
+ z0 = (h-displa) * exp(-vonkar/sqrtdragc + psih)
+
+ IF (z0 < 0.01) THEN
+ z0 = 0.01
+ displa = 0.
+ ENDIF
+
+ END SUBROUTINE cal_z0_displa
+
+END MODULE MOD_CanopyLayerProfile
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_CheckEquilibrium.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_CheckEquilibrium.F90
new file mode 100644
index 0000000000..d479bf8cea
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_CheckEquilibrium.F90
@@ -0,0 +1,685 @@
+#include
+
+MODULE MOD_CheckEquilibrium
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Check equilibrium state.
+!
+! Created by Shupeng Zhang, 10/2024
+!----------------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE netcdf
+ USE MOD_NetCDFSerial
+ USE MOD_SpatialMapping
+ USE MOD_Forcing, only: forcmask_pch
+ USE MOD_Vars_Global, only: spval
+
+ ! ----- Variables -----
+ integer :: nyearcheck
+
+ integer :: timestrlen
+ character(len=24) :: timeform
+
+ real(r8), allocatable :: tws_last (:)
+ real(r8), allocatable :: tws_this (:)
+
+ real(r8), allocatable :: prcp_year (:)
+ real(r8), allocatable :: et_year (:)
+ real(r8), allocatable :: rnof_year (:)
+ real(r8), allocatable :: rchg_year (:)
+
+ real(r8), allocatable :: patcharea (:) ! m^2
+
+ character(len=256) :: mesg_equilibrium
+
+#ifndef SinglePoint
+ type(grid_type) :: gridcheck
+ type(grid_concat_type) :: gcheck_concat
+ type(spatial_mapping_type) :: map_check
+
+ integer :: check_data_id = 0
+#endif
+
+ PUBLIC :: CheckEqb_init
+ PUBLIC :: CheckEquilibrium
+ PUBLIC :: CheckEqb_final
+
+CONTAINS
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE CheckEqb_init (n_spinupcycle, lc_year)
+
+ USE MOD_Utils
+ USE MOD_Vars_Global, only: nl_soil
+ USE MOD_Forcing, only: gforc
+ USE MOD_LandPatch, only: numpatch, landpatch
+ USE MOD_Pixel, only: pixel
+ USE MOD_Mesh, only: mesh
+ USE MOD_Vars_TimeVariables, only: wdsrf, ldew, scv, wetwat, &
+ wliq_soisno, wice_soisno, wa
+ IMPLICIT NONE
+
+ integer, intent(in) :: n_spinupcycle
+ integer, intent(in) :: lc_year
+
+ ! Local Variable
+ integer :: ilev, ip, ie, ipxl
+ character(len=256) :: filename, cyear
+ real(r8) :: totaldtws, totalprcp, pct_dtws_prcp
+
+
+ IF (.not. DEF_CheckEquilibrium) RETURN
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ allocate (tws_last (numpatch)); tws_last (:) = spval;
+ allocate (tws_this (numpatch)); tws_this (:) = spval;
+ allocate (prcp_year (numpatch)); prcp_year(:) = spval;
+ allocate (et_year (numpatch)); et_year (:) = spval;
+ allocate (rnof_year (numpatch)); rnof_year(:) = spval;
+ allocate (rchg_year (numpatch)); rchg_year(:) = spval;
+
+ ENDIF
+ ENDIF
+
+ IF (n_spinupcycle >= 10000) THEN
+ timestrlen = 16
+ timeform = "('spinup',I5.5,'-',I4.4)"
+ ELSEIF (n_spinupcycle >= 1000) THEN
+ timestrlen = 15
+ timeform = "('spinup',I4.4,'-',I4.4)"
+ ELSEIF (n_spinupcycle >= 100) THEN
+ timestrlen = 14
+ timeform = "('spinup',I3.3,'-',I4.4)"
+ ELSEIF (n_spinupcycle >= 10) THEN
+ timestrlen = 13
+ timeform = "('spinup',I2.2,'-',I4.4)"
+ ELSE
+ timestrlen = 12
+ timeform = "('spinup',I1.1,'-',I4.4)"
+ ENDIF
+
+ mesg_equilibrium = ''
+
+#ifndef SinglePoint
+ ! grid
+#ifdef GRIDBASED
+ write(cyear,'(i4.4)') lc_year
+ filename = trim(DEF_dir_landdata) // '/mesh/' //trim(cyear) // '/mesh.nc'
+ CALL gridcheck%define_from_file (filename)
+#else
+ CALL gridcheck%define_by_copy (gforc)
+#endif
+ ! grid info for output
+ CALL gcheck_concat%set (gridcheck)
+ ! mapping from patch to grid
+ CALL map_check%build_arealweighted (gridcheck, landpatch)
+#endif
+
+ IF ((p_is_compute) .and. (numpatch > 0)) THEN
+ tws_last = wdsrf ! 1. surface water
+ CALL add_spv (ldew, tws_last) ! 2. water on foliage
+ CALL add_spv (scv , tws_last) ! 3. snow cover water equivalent
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ CALL add_spv (wetwat, tws_last) ! 4. water in wetland
+ ENDIF
+ DO ilev = 1, nl_soil
+ CALL add_spv (wliq_soisno(ilev,:), tws_last) ! 5. liquid water in soil
+ CALL add_spv (wice_soisno(ilev,:), tws_last) ! 6. ice in soil
+ ENDDO
+ CALL add_spv (wa, tws_last) ! 7. water in aquifer
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+ allocate (patcharea (numpatch))
+ patcharea(:) = 0.
+ DO ip = 1, numpatch
+ ie = landpatch%ielm(ip)
+ DO ipxl = landpatch%ipxstt(ip), landpatch%ipxend(ip)
+ patcharea(ip) = patcharea(ip) + 1.0e6 * areaquad ( &
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDDO
+ IF (landpatch%has_shared) THEN
+ patcharea(ip) = patcharea(ip) * landpatch%pctshared(ip)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ENDIF
+
+ nyearcheck = 0
+
+ END SUBROUTINE CheckEqb_init
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE CheckEqb_final ()
+
+ IMPLICIT NONE
+
+ IF (.not. DEF_CheckEquilibrium) RETURN
+
+ IF (allocated(tws_last )) deallocate(tws_last )
+ IF (allocated(tws_this )) deallocate(tws_this )
+ IF (allocated(prcp_year)) deallocate(prcp_year)
+ IF (allocated(et_year )) deallocate(et_year )
+ IF (allocated(rnof_year)) deallocate(rnof_year)
+ IF (allocated(rchg_year)) deallocate(rchg_year)
+ IF (allocated(patcharea)) deallocate(patcharea)
+
+ END SUBROUTINE CheckEqb_final
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE CheckEquilibrium ( &
+ idate, deltim, i_spinupcycle, is_spinup, dir_out, casename)
+
+ USE MOD_Precision
+ USE MOD_TimeManager
+ USE MOD_DataType
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_Vars_Global, only: nl_soil
+ USE MOD_Vars_1DForcing, only: forc_prc, forc_prl
+ USE MOD_Vars_1DFluxes, only: fevpa, rnof, rsur
+ USE MOD_Vars_TimeInvariants, only: patchtype, patchmask
+ USE MOD_Vars_TimeVariables, only: wdsrf, ldew, scv, wetwat, wliq_soisno, &
+ wice_soisno, wa, zwt
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ integer, intent(in) :: i_spinupcycle
+ logical, intent(in) :: is_spinup
+
+ character(len=*), intent(in) :: dir_out
+ character(len=*), intent(in) :: casename
+
+ ! Local variables
+ logical :: docheck
+ integer :: ilev
+ character(len=256) :: filename, timestr
+ integer :: ncid, time_id, str_id, varid
+ real(r8) :: totaldtws, totalprcp, pct_dtws_prcp
+
+ real(r8), allocatable :: rchg (:)
+ real(r8), allocatable :: dtws (:)
+ logical, allocatable :: filter (:)
+ real(r8), allocatable :: vecone (:)
+ type(block_data_real8_2d) :: sumarea
+
+
+ IF (.not. DEF_CheckEquilibrium) RETURN
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ CALL add_spv (forc_prc, prcp_year, deltim)
+ CALL add_spv (forc_prl, prcp_year, deltim)
+ CALL add_spv (fevpa, et_year, deltim)
+ CALL add_spv (rnof, rnof_year, deltim)
+
+ allocate (rchg (numpatch))
+ rchg = spval
+ WHERE ((forc_prc /= spval) .and. (forc_prl /= spval) .and. (fevpa /= spval) .and. (rsur /= spval))
+ rchg = forc_prc + forc_prl - fevpa - rsur
+ END WHERE
+
+ CALL add_spv (rchg, rchg_year, deltim)
+
+ deallocate (rchg)
+ ENDIF
+ ENDIF
+
+ docheck = isendofyear (idate, deltim)
+
+ IF (docheck) THEN
+
+ IF ((p_is_compute) .and. (numpatch > 0)) THEN
+ tws_this = wdsrf ! 1. surface water
+ CALL add_spv (ldew, tws_this) ! 2. water on foliage
+ CALL add_spv (scv , tws_this) ! 3. snow cover water equivalent
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ CALL add_spv (wetwat, tws_this) ! 4. water in wetland
+ ENDIF
+ DO ilev = 1, nl_soil
+ CALL add_spv (wliq_soisno(ilev,:), tws_this) ! 5. liquid water in soil
+ CALL add_spv (wice_soisno(ilev,:), tws_this) ! 6. ice in soil
+ ENDDO
+ CALL add_spv (wa, tws_this) ! 7. water in aquifer
+ ENDIF
+
+ nyearcheck = nyearcheck + 1
+
+ IF (nyearcheck >= 1) THEN
+
+ IF (p_is_compute) THEN
+
+ totaldtws = 0.
+ totalprcp = 0.
+
+ IF (numpatch > 0) THEN
+
+ allocate (filter (numpatch))
+ filter = patchmask
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+#ifdef CatchLateralFlow
+ filter = filter .and. (patchtype <= 4)
+#else
+ filter = filter .and. (patchtype <= 2)
+#endif
+
+ allocate (dtws (numpatch))
+ WHERE (filter)
+ dtws = tws_this - tws_last
+ ELSEWHERE
+ dtws = spval
+ END WHERE
+
+ IF (any(filter)) THEN
+ totaldtws = sum(dtws*patcharea, mask=filter)
+ totalprcp = sum(prcp_year*patcharea, mask=filter)
+ ENDIF
+
+ allocate (vecone (numpatch))
+ vecone(:) = 1.
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, totaldtws, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+ CALL mpi_allreduce (MPI_IN_PLACE, totalprcp, 1, MPI_REAL8, MPI_SUM, p_comm_compute, p_err)
+
+ IF (totalprcp > 0.) THEN
+ pct_dtws_prcp = totaldtws/totalprcp
+ ELSE
+ pct_dtws_prcp = spval
+ ENDIF
+
+ IF (p_iam_compute == p_root) THEN
+ CALL mpi_send (pct_dtws_prcp, 1, MPI_REAL8, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ IF (is_spinup) THEN
+ write(timestr,timeform) i_spinupcycle, idate(1)
+ ELSE
+ write(timestr,'(I4.4)') idate(1)
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_recv (pct_dtws_prcp, 1, MPI_REAL8, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+ IF (pct_dtws_prcp /= spval) THEN
+ write(mesg_equilibrium,'(A,F0.2,3A)') 'Total delTWS/precipitation is ', &
+ pct_dtws_prcp*100., '% in ', trim(timestr), '. Check history for detail.'
+ ELSE
+ write(mesg_equilibrium,'(3A)') 'Precipitation is 0 ', trim(timestr), '.'
+ ENDIF
+
+ filename = trim(dir_out) // '/' // trim(casename) //'_check_equilibrium.nc'
+
+ IF (nyearcheck == 1) THEN
+
+ CALL ncio_create_file (trim(filename))
+
+ CALL ncio_define_dimension(filename, 'iyear', 0)
+ CALL ncio_define_dimension(filename, 'timestr', timestrlen)
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ CALL nccheck( nf90_inq_dimid(ncid, 'iyear', time_id) )
+ CALL nccheck( nf90_inq_dimid(ncid, 'timestr', str_id ) )
+ CALL nccheck( nf90_redef(ncid) )
+ CALL nccheck( nf90_def_var(ncid, 'iyear', NF90_CHAR, (/str_id,time_id/), varid) )
+ CALL nccheck( nf90_put_att(ncid, varid, 'long_name', 'iyear in all spinup cycles') )
+ CALL nccheck( nf90_enddef(ncid) )
+ CALL nccheck( nf90_close(ncid) )
+
+#ifndef SinglePoint
+ CALL ncio_define_dimension(filename, 'lat' , gcheck_concat%ginfo%nlat)
+ CALL ncio_define_dimension(filename, 'lon' , gcheck_concat%ginfo%nlon)
+
+ CALL ncio_write_serial (filename, 'lat', gcheck_concat%ginfo%lat_c, 'lat')
+ CALL ncio_put_attr (filename, 'lat', 'long_name', 'latitude')
+ CALL ncio_put_attr (filename, 'lat', 'units', 'degrees_north')
+
+ CALL ncio_write_serial (filename, 'lon', gcheck_concat%ginfo%lon_c, 'lon')
+ CALL ncio_put_attr (filename, 'lon', 'long_name', 'longitude')
+ CALL ncio_put_attr (filename, 'lon', 'units', 'degrees_east')
+#else
+ CALL ncio_define_dimension(filename, 'patch', numpatch)
+#endif
+
+ ENDIF
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, 'iyear', varid) )
+ CALL nccheck( nf90_put_var(ncid, varid, timestr(1:timestrlen), &
+ (/1,nyearcheck/), (/timestrlen,1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+#ifndef SinglePoint
+ IF (p_is_active) CALL allocate_block_data (gridcheck, sumarea)
+
+ CALL map_check%get_sumarea (sumarea, filter)
+
+ IF (nyearcheck == 1) THEN
+ CALL map_and_write_check_var ( &
+ vecone, filename, 'landarea', -1, sumarea, filter, &
+ 'area of land excluding water bodies and glaciers in grid', 'km^2', &
+ amount_in_grid = .true.)
+ ENDIF
+
+ CALL map_and_write_check_var ( &
+ dtws, filename, 'tws_change', nyearcheck, sumarea, filter, &
+ 'Change in terrestrial water storage', 'mm')
+ CALL map_and_write_check_var ( &
+ prcp_year, filename, 'total_precipitation', nyearcheck, sumarea, filter, &
+ 'total precipitation in a year', 'mm')
+ CALL map_and_write_check_var ( &
+ et_year, filename, 'total_evapotranspiration', nyearcheck, sumarea, filter, &
+ 'total evapotranspiration in a year', 'mm')
+ CALL map_and_write_check_var ( &
+ rnof_year, filename, 'total_runoff', nyearcheck, sumarea, filter, &
+ 'total runoff in a year', 'mm')
+ CALL map_and_write_check_var ( &
+ rchg_year, filename, 'total_recharge', nyearcheck, sumarea, filter, &
+ 'total recharge to ground water in a year', 'mm')
+ CALL map_and_write_check_var ( &
+ zwt, filename, 'zwt', nyearcheck, sumarea, filter, &
+ 'depth to water table', 'm')
+#else
+ CALL ncio_write_serial_time (filename, 'tws_change', &
+ nyearcheck, dtws, 'patch', 'iyear')
+ IF (nyearcheck == 1) THEN
+ CALL ncio_put_attr (filename, 'tws_change', 'long_name', &
+ 'Change in terrestrial water storage')
+ CALL ncio_put_attr (filename, 'tws_change', 'units', 'mm')
+ CALL ncio_put_attr (filename, 'tws_change', 'missing_value', spval)
+ ENDIF
+
+ CALL ncio_write_serial_time (filename, 'total_precipitation', &
+ nyearcheck, prcp_year, 'patch', 'iyear')
+ IF (nyearcheck == 1) THEN
+ CALL ncio_put_attr (filename, 'total_precipitation', 'long_name', &
+ 'total precipitation in a year')
+ CALL ncio_put_attr (filename, 'total_precipitation', 'units', 'mm')
+ CALL ncio_put_attr (filename, 'total_precipitation', 'missing_value', spval)
+ ENDIF
+
+ CALL ncio_write_serial_time (filename, 'total_evapotranspiration', &
+ nyearcheck, et_year, 'patch', 'iyear')
+ IF (nyearcheck == 1) THEN
+ CALL ncio_put_attr (filename, 'total_evapotranspiration', 'long_name', &
+ 'total evapotranspiration in a year')
+ CALL ncio_put_attr (filename, 'total_evapotranspiration', 'units', 'mm')
+ CALL ncio_put_attr (filename, 'total_evapotranspiration', 'missing_value', spval)
+ ENDIF
+
+ CALL ncio_write_serial_time (filename, 'total_runoff', &
+ nyearcheck, rnof_year, 'patch', 'iyear')
+ IF (nyearcheck == 1) THEN
+ CALL ncio_put_attr (filename, 'total_runoff', 'long_name', &
+ 'total runoff in a year')
+ CALL ncio_put_attr (filename, 'total_runoff', 'units', 'mm')
+ CALL ncio_put_attr (filename, 'total_runoff', 'missing_value', spval)
+ ENDIF
+
+ CALL ncio_write_serial_time (filename, 'total_recharge', &
+ nyearcheck, rchg_year, 'patch', 'iyear')
+ IF (nyearcheck == 1) THEN
+ CALL ncio_put_attr (filename, 'total_recharge', 'long_name', &
+ 'total recharge to ground water in a year')
+ CALL ncio_put_attr (filename, 'total_recharge', 'units', 'mm')
+ CALL ncio_put_attr (filename, 'total_recharge', 'missing_value', spval)
+ ENDIF
+
+ CALL ncio_write_serial_time (filename, 'zwt', &
+ nyearcheck, zwt, 'patch', 'iyear')
+ IF (nyearcheck == 1) THEN
+ CALL ncio_put_attr (filename, 'zwt', 'long_name', 'depth to water table')
+ CALL ncio_put_attr (filename, 'zwt', 'units', 'm')
+ CALL ncio_put_attr (filename, 'zwt', 'missing_value', spval)
+ ENDIF
+#endif
+ ENDIF
+
+ IF ((p_is_compute) .and. (numpatch > 0)) THEN
+ prcp_year(:) = spval
+ et_year (:) = spval
+ rnof_year(:) = spval
+ rchg_year(:) = spval
+ tws_last = tws_this
+ ENDIF
+
+ IF (allocated(dtws )) deallocate(dtws )
+ IF (allocated(filter)) deallocate(filter)
+ IF (allocated(vecone)) deallocate(vecone)
+
+ ENDIF
+
+ END SUBROUTINE CheckEquilibrium
+
+ !-----------------------------------------------------------------------
+#ifndef SinglePoint
+ SUBROUTINE map_and_write_check_var ( &
+ vector, filename, varname, itime_in_file, sumarea, filter, &
+ longname, units, amount_in_grid)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: vector(:)
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ logical, intent(in), optional :: amount_in_grid
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+
+ ! Local variables
+ type(block_data_real8_2d) :: data_xy_2d
+ integer :: xblk, yblk, xloc, yloc, xcnt, ycnt, xbdsp, ybdsp, xgdsp, ygdsp
+ integer :: iblkme, iblk, jblk, idata, ixseg, iyseg
+ integer :: rmesg(3), smesg(3), isrc
+ real(r8), allocatable :: rbuf(:,:), sbuf(:,:), vdata(:,:)
+ logical :: amount
+
+ IF (p_is_active) CALL allocate_block_data (gridcheck, data_xy_2d)
+ CALL map_check%pset2grid (vector, data_xy_2d, spv = spval, msk = filter)
+
+ amount = .false.
+ IF (present(amount_in_grid)) amount = amount_in_grid
+
+ IF (.not. amount) THEN
+ IF (p_is_active) THEN
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ DO yloc = 1, gridcheck%ycnt(yblk)
+ DO xloc = 1, gridcheck%xcnt(xblk)
+
+ IF (sumarea%blk(xblk,yblk)%val(xloc,yloc) > 0.00001) THEN
+ IF (data_xy_2d%blk(xblk,yblk)%val(xloc,yloc) /= spval) THEN
+ data_xy_2d%blk(xblk,yblk)%val(xloc,yloc) &
+ = data_xy_2d%blk(xblk,yblk)%val(xloc,yloc) &
+ / sumarea%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+ ELSE
+ data_xy_2d%blk(xblk,yblk)%val(xloc,yloc) = spval
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDDO
+ ENDIF
+ ENDIF
+
+ check_data_id = mod(check_data_id,100) + 1
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+
+ allocate (vdata (gcheck_concat%ginfo%nlon, gcheck_concat%ginfo%nlat))
+ vdata(:,:) = spval
+
+#ifdef USEMPI
+ DO idata = 1, gcheck_concat%ndatablk
+ CALL mpi_recv (rmesg, 3, MPI_INTEGER, MPI_ANY_SOURCE, &
+ check_data_id, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ ixseg = rmesg(2)
+ iyseg = rmesg(3)
+
+ xgdsp = gcheck_concat%xsegs(ixseg)%gdsp
+ ygdsp = gcheck_concat%ysegs(iyseg)%gdsp
+ xcnt = gcheck_concat%xsegs(ixseg)%cnt
+ ycnt = gcheck_concat%ysegs(iyseg)%cnt
+
+ allocate (rbuf(xcnt,ycnt))
+
+ CALL mpi_recv (rbuf, xcnt*ycnt, MPI_REAL8, &
+ isrc, check_data_id, p_comm_glb, p_stat, p_err)
+
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt) = rbuf
+ deallocate (rbuf)
+
+ ENDDO
+#else
+ DO iyseg = 1, gcheck_concat%nyseg
+ DO ixseg = 1, gcheck_concat%nxseg
+ iblk = gcheck_concat%xsegs(ixseg)%blk
+ jblk = gcheck_concat%ysegs(iyseg)%blk
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+ xbdsp = gcheck_concat%xsegs(ixseg)%bdsp
+ ybdsp = gcheck_concat%ysegs(iyseg)%bdsp
+ xgdsp = gcheck_concat%xsegs(ixseg)%gdsp
+ ygdsp = gcheck_concat%ysegs(iyseg)%gdsp
+ xcnt = gcheck_concat%xsegs(ixseg)%cnt
+ ycnt = gcheck_concat%ysegs(iyseg)%cnt
+
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt) = &
+ data_xy_2d%blk(iblk,jblk)%val(xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+ ENDIF
+ ENDDO
+ ENDDO
+#endif
+
+ IF (itime_in_file >= 1) THEN
+ CALL ncio_write_serial_time (filename, varname, itime_in_file, vdata, &
+ 'lon', 'lat', 'iyear', compress = 1)
+ ELSE
+ CALL ncio_write_serial (filename, varname, vdata, 'lon', 'lat', compress = 1)
+ ENDIF
+
+ IF (itime_in_file <= 1) THEN
+ CALL ncio_put_attr (filename, varname, 'long_name', longname)
+ CALL ncio_put_attr (filename, varname, 'units', units)
+ CALL ncio_put_attr (filename, varname, 'missing_value', spval)
+ ENDIF
+
+ deallocate (vdata)
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+ DO iyseg = 1, gcheck_concat%nyseg
+ DO ixseg = 1, gcheck_concat%nxseg
+
+ iblk = gcheck_concat%xsegs(ixseg)%blk
+ jblk = gcheck_concat%ysegs(iyseg)%blk
+
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+
+ xbdsp = gcheck_concat%xsegs(ixseg)%bdsp
+ ybdsp = gcheck_concat%ysegs(iyseg)%bdsp
+ xcnt = gcheck_concat%xsegs(ixseg)%cnt
+ ycnt = gcheck_concat%ysegs(iyseg)%cnt
+
+ allocate (sbuf (xcnt,ycnt))
+ sbuf = data_xy_2d%blk(iblk,jblk)%val(xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+
+ smesg = (/p_iam_glb, ixseg, iyseg/)
+ CALL mpi_send (smesg, 3, MPI_INTEGER, &
+ p_address_root, check_data_id, p_comm_glb, p_err)
+ CALL mpi_send (sbuf, xcnt*ycnt, MPI_REAL8, &
+ p_address_root, check_data_id, p_comm_glb, p_err)
+
+ deallocate (sbuf)
+
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+#endif
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE map_and_write_check_var
+#endif
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE add_spv (var, s, dt)
+
+ USE MOD_Precision
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: var(:)
+ real(r8), intent(inout) :: s (:)
+ real(r8), intent(in), optional :: dt
+ ! Local variables
+ integer :: i
+
+ IF (present(dt)) THEN
+ DO i = lbound(var,1), ubound(var,1)
+ IF (var(i) /= spval) THEN
+ IF (s(i) /= spval) THEN
+ s(i) = s(i) + var(i)*dt
+ ELSE
+ s(i) = var(i)*dt
+ ENDIF
+ ENDIF
+ ENDDO
+ ELSE
+ DO i = lbound(var,1), ubound(var,1)
+ IF (var(i) /= spval) THEN
+ IF (s(i) /= spval) THEN
+ s(i) = s(i) + var(i)
+ ELSE
+ s(i) = var(i)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE add_spv
+
+END MODULE MOD_CheckEquilibrium
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_LC.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_LC.F90
new file mode 100644
index 0000000000..a265a0bc59
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_LC.F90
@@ -0,0 +1,878 @@
+#include
+
+MODULE MOD_Const_LC
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Constant values set for land cover types
+!
+! Created by Hua Yuan, 08/2019
+!
+! !REVISIONS:
+! 08/2019, Hua Yuan: initial version adapted from IniTimeConst.F90 of CoLM2014
+! 08/2019, Hua Yuan: added constants values for IGBP land cover types
+! 05/2023, Xingjie Lu: added Plant Hydraulics Parameters
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS
+
+ IMPLICIT NONE
+ SAVE
+
+#ifdef LULC_USGS
+
+! GLCC USGS Land Use/Land Cover System Legend
+!-----------------------------------------------------------------------
+! 0 Ocean
+! 1 Urban and Built-Up Land
+! 2 Dryland Cropland and Pasture
+! 3 Irrigated Cropland and Pasture
+! 4 Mixed Dryland/Irrigated Cropland and Pasture
+! 5 Cropland/Grassland Mosaic
+! 6 Cropland/Woodland Mosaic
+! 7 Grassland
+! 8 Shrubland
+! 9 Mixed Shrubland/Grassland
+!10 Savanna
+!11 Deciduous Broadleaf Forest
+!12 Deciduous Needleleaf Forest
+!13 Evergreen Broadleaf Forest
+!14 Evergreen Needleleaf Forest
+!15 Mixed Forest
+!16 Inland Water
+!17 Herbaceous Wetland
+!18 Wooded Wetland
+!19 Barren or Sparsely Vegetated
+!20 Herbaceous Tundra
+!21 Wooded Tundra
+!22 Mixed Tundra
+!23 Bare Ground Tundra
+!24 Snow or Ice
+
+ character(len=256) :: patchclassname (0:N_land_classification) = &
+ (/'0 Ocean ', &
+ '1 Urban and Built-Up Land ', &
+ '2 Dryland Cropland and Pasture ', &
+ '3 Irrigated Cropland and Pasture ', &
+ '4 Mixed Dryland/Irrigated Cropland and Pasture', &
+ '5 Cropland/Grassland Mosaic ', &
+ '6 Cropland/Woodland Mosaic ', &
+ '7 Grassland ', &
+ '8 Shrubland ', &
+ '9 Mixed Shrubland/Grassland ', &
+ '10 Savanna ', &
+ '11 Deciduous Broadleaf Forest ', &
+ '12 Deciduous Needleleaf Forest ', &
+ '13 Evergreen Broadleaf Forest ', &
+ '14 Evergreen Needleleaf Forest ', &
+ '15 Mixed Forest ', &
+ '16 Inland Water ', &
+ '17 Herbaceous Wetland ', &
+ '18 Wooded Wetland ', &
+ '19 Barren or Sparsely Vegetated ', &
+ '20 Herbaceous Tundra ', &
+ '21 Wooded Tundra ', &
+ '22 Mixed Tundra ', &
+ '23 Bare Ground Tundra ', &
+ '24 Snow or Ice '/)
+
+ ! land patch types
+ ! 0: soil, 1: urban, 2: wetland, 3: ice, 4: lake
+ integer , parameter, dimension(N_land_classification) :: patchtypes_usgs &
+ = (/1, 0, 0, 0, 0, 0, 0, 0,&
+ 0, 0, 0, 0, 0, 0, 0, 4,&
+ 2, 2, 0, 0, 0, 0, 0, 3/)
+
+ ! Look-up table canopy top height
+ !NOTE: now read from input NetCDF file
+ !NOTE: woody wetland 35m?
+ ! shrub land 0.5m? grass like land 1m? all set to 0.5
+ real(r8), parameter, dimension(N_land_classification) :: htop0_usgs &
+ !=(/ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5,&
+ ! 0.5, 1.0, 20.0, 17.0, 35.0, 17.0, 20.0, 1.0,&
+ ! 1.0, 35.0, 0.5, 1.0, 1.0, 1.0, 1.0, 1.0/)
+ =(/ 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5,&
+ 0.5, 0.5, 20.0, 17.0, 35.0, 17.0, 20.0, 0.5,&
+ 0.5, 17.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5/)
+
+ ! Look-up table canopy bottom height
+ ! 01/06/2020, yuan: adjust hbot: grass/shrub -> 0, tree->1
+ real(r8), parameter, dimension(N_land_classification) :: hbot0_usgs &
+ !=(/0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.1,&
+ ! 0.1, 0.1, 11.5, 8.5, 1.0, 8.5, 10.0, 0.1,&
+ ! 0.1, 1.0, 0.1, 0.01, 0.01, 0.01, 0.01, 0.01/)
+ =(/ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,&
+ 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0,&
+ 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0/)
+
+ ! defulat vegetation fractional cover
+ real(r8), parameter, dimension(N_land_classification) :: fveg0_usgs &
+ = 1.0 !(/.../)
+
+ ! Look-up table stem area index
+ !NOTE: now read from input NetCDF file
+ real(r8), parameter, dimension(N_land_classification) :: sai0_usgs &
+ !=(/0.2, 0.2, 0.3, 0.3, 0.5, 0.5, 1.0, 0.5,&
+ ! 1.0, 0.5, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0,&
+ ! 2.0, 2.0, 0.0, 0.1, 0.1, 0.1, 0.0, 0.0/)
+ =(/0.2, 0.2, 0.3, 0.3, 0.5, 0.5, 1.0, 0.5,&
+ 1.0, 0.5, 2.0, 2.0, 2.0, 2.0, 2.0, 0.0,&
+ 0.2, 2.0, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0/)
+
+ ! ratio to calculate roughness length z0m
+ real(r8), parameter, dimension(N_land_classification) :: z0mr_usgs = 0.1
+
+ ! ratio to calculate displacement height d
+ real(r8), parameter, dimension(N_land_classification) :: displar_usgs = 0.667
+
+ ! inverse sqrt of leaf dimension [m**-0.5, m=4 cm]
+ real(r8), parameter, dimension(N_land_classification) :: sqrtdi_usgs = 5.0
+
+ ! leaf angle distribution parameter
+ real(r8), parameter, dimension(N_land_classification) :: chil_usgs &
+ = (/-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, 0.010,&
+ 0.010, -0.300, 0.250, 0.010, 0.100, 0.010, 0.125, -0.300,&
+ -0.300, 0.100, 0.010, -0.300, -0.300, -0.300, -0.300, -0.300/)
+
+ ! reflectance of green leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: rhol_vis_usgs &
+ = (/0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.100,&
+ 0.100, 0.105, 0.100, 0.070, 0.100, 0.070, 0.070, 0.105,&
+ 0.105, 0.100, 0.100, 0.105, 0.105, 0.105, 0.105, 0.105/)
+
+ ! reflectance of dead leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: rhos_vis_usgs &
+ = (/0.360, 0.360, 0.360, 0.360, 0.360, 0.360, 0.360, 0.160,&
+ 0.160, 0.360, 0.160, 0.160, 0.160, 0.160, 0.160, 0.360,&
+ 0.360, 0.160, 0.160, 0.360, 0.360, 0.360, 0.360, 0.360/)
+
+ ! reflectance of green leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: rhol_nir_usgs &
+ = (/0.580, 0.580, 0.580, 0.580, 0.580, 0.580, 0.580, 0.450,&
+ 0.450, 0.580, 0.450, 0.350, 0.450, 0.350, 0.400, 0.580,&
+ 0.580, 0.450, 0.450, 0.580, 0.580, 0.580, 0.580, 0.580/)
+
+ ! reflectance of dead leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: rhos_nir_usgs &
+ = (/0.580, 0.580, 0.580, 0.580, 0.580, 0.580, 0.580, 0.390,&
+ 0.390, 0.580, 0.390, 0.390, 0.390, 0.390, 0.390, 0.580,&
+ 0.580, 0.390, 0.390, 0.580, 0.580, 0.580, 0.580, 0.580/)
+
+ ! transmittance of green leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: taul_vis_usgs &
+ = (/0.070, 0.070, 0.070, 0.070, 0.070, 0.070, 0.070, 0.070,&
+ 0.070, 0.070, 0.050, 0.050, 0.050, 0.050, 0.050, 0.070,&
+ 0.070, 0.050, 0.070, 0.070, 0.070, 0.070, 0.070, 0.070/)
+
+ ! transmittance of dead leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: taus_vis_usgs &
+ = (/0.220, 0.220, 0.220, 0.220, 0.220, 0.220, 0.220, 0.001,&
+ 0.001, 0.220, 0.001, 0.001, 0.001, 0.001, 0.001, 0.220,&
+ 0.220, 0.001, 0.001, 0.220, 0.220, 0.220, 0.220, 0.220/)
+
+ ! transmittance of green leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: taul_nir_usgs &
+ = (/0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250,&
+ 0.250, 0.250, 0.250, 0.100, 0.250, 0.100, 0.150, 0.250,&
+ 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250/)
+
+ ! transmittance of dead leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: taus_nir_usgs &
+ = (/0.380, 0.380, 0.380, 0.380, 0.380, 0.380, 0.380, 0.001,&
+ 0.001, 0.380, 0.001, 0.001, 0.001, 0.001, 0.001, 0.380,&
+ 0.380, 0.001, 0.001, 0.380, 0.380, 0.380, 0.380, 0.380/)
+
+ ! maximum carboxylation rate at 25 C at canopy top
+ ! /06/03/2014/ based on Bonan et al., 2010 (Table 2)
+ real(r8), parameter, dimension(N_land_classification) :: vmax25_usgs &
+ = (/100.0, 57.0, 57.0, 57.0, 52.0, 52.0, 52.0, 52.0,&
+ 52.0, 52.0, 52.0, 57.0, 72.0, 54.0, 52.0, 57.0,&
+ 52.0, 52.0, 52.0, 52.0, 52.0, 52.0, 52.0, 52.0/)
+
+ ! quantum efficiency
+ !TODO: no C4, 0.05 may have problem
+ real(r8), parameter, dimension(N_land_classification) :: effcon_usgs &
+ = (/0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08,&
+ 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08,&
+ 0.08, 0.08, 0.08, 0.05, 0.05, 0.05, 0.05, 0.05/)
+
+ !c3c4 flag
+ integer, parameter, dimension(N_land_classification) :: c3c4_usgs &
+ = (/1, 1, 1, 1, 1, 1, 1, 1,&
+ 1, 1, 1, 1, 1, 1, 1, 1,&
+ 1, 1, 1, 0, 0, 0, 0, 0/)
+
+ ! conductance-photosynthesis slope parameter
+ !TODO: no C4, 4.0 may have problem
+ real(r8), parameter, dimension(N_land_classification) :: g1_usgs &
+ = (/4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0,&
+ 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0,&
+ 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0/)
+
+ ! conductance-photosynthesis intercept
+ real(r8), parameter, dimension(N_land_classification) :: g0_usgs &
+ = (/100, 100, 100, 100, 100, 100, 100, 100,&
+ 100, 100, 100, 100, 100, 100, 100, 100,&
+ 100, 100, 100, 100, 100, 100, 100, 100/)
+
+ ! conductance-photosynthesis slope parameter
+ !TODO: no C4, 4.0 may have problem
+ real(r8), parameter, dimension(N_land_classification) :: gradm_usgs &
+ = (/9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0,&
+ 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0,&
+ 9.0, 9.0, 9.0, 4.0, 4.0, 4.0, 4.0, 4.0/)
+
+ ! conductance-photosynthesis intercept
+ real(r8), parameter, dimension(N_land_classification) :: binter_usgs &
+ = (/0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,&
+ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,&
+ 0.01, 0.01, 0.01, 0.04, 0.04, 0.04, 0.04, 0.04/)
+
+ ! respiration fraction
+ real(r8), parameter, dimension(N_land_classification) :: respcp_usgs &
+ = (/0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015,&
+ 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015,&
+ 0.015, 0.015, 0.015, 0.025, 0.025, 0.025, 0.025, 0.025/)
+
+ ! slope of high temperature inhibition FUNCTION (s1)
+ real(r8), parameter, dimension(N_land_classification) :: shti_usgs = 0.3
+
+ ! slope of low temperature inhibition FUNCTION (s3)
+ real(r8), parameter, dimension(N_land_classification) :: slti_usgs = 0.2
+
+ ! temperature coefficient in gs-a model (s5)
+ real(r8), parameter, dimension(N_land_classification) :: trda_usgs = 1.3
+
+ ! temperature coefficient in gs-a model (s6)
+ real(r8), parameter, dimension(N_land_classification) :: trdm_usgs = 328.0
+
+ ! temperature coefficient in gs-a model (273.16+25)
+ real(r8), parameter, dimension(N_land_classification) :: trop_usgs = 298.0
+
+ ! 1/2 point of high temperature inhibition FUNCTION (s2)
+ real(r8), parameter, dimension(N_land_classification) :: hhti_usgs &
+ =(/308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 313.0,&
+ 313.0, 308.0, 311.0, 303.0, 313.0, 303.0, 307.0, 308.0,&
+ 308.0, 313.0, 313.0, 313.0, 313.0, 313.0, 313.0, 308.0/)
+
+ ! 1/2 point of low temperature inhibition FUNCTION (s4)
+ real(r8), parameter, dimension(N_land_classification) :: hlti_usgs &
+ =(/281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 283.0,&
+ 283.0, 281.0, 283.0, 278.0, 288.0, 278.0, 281.0, 281.0,&
+ 281.0, 288.0, 283.0, 288.0, 288.0, 288.0, 288.0, 281.0/)
+
+ ! coefficient of leaf nitrogen allocation
+ real(r8), parameter, dimension(N_land_classification) :: extkn_usgs = 0.5
+
+ ! depth at 50% roots
+ real(r8), parameter, dimension(N_land_classification) :: d50_usgs &
+ =(/23.0, 21.0, 23.0, 22.0, 15.7, 19.0, 9.3, 47.0,&
+ 28.2, 21.7, 16.0, 16.0, 15.0, 15.0, 15.5, 1.0,&
+ 9.3, 15.5, 27.0, 9.0, 9.0, 9.0, 9.0, 1.0/)
+
+ ! coefficient of root profile
+ real(r8), parameter, dimension(N_land_classification) :: beta_usgs &
+ =(/-1.757, -1.835, -1.757, -1.796, -1.577, -1.738, -1.359, -3.245,&
+ -2.302, -1.654, -1.681, -1.681, -1.632, -1.632, -1.656, -1.000,&
+ -1.359, -1.656, -2.051, -2.621, -2.621, -2.621, -2.621, -1.000/)
+
+ ! Table 2. Zeng, 2001
+ ! urban ==> cropland
+ ! water/glacier ==> grass
+ real(r8), parameter, dimension(N_land_classification) :: roota_usgs &
+ =(/ 5.558, 5.558, 5.558, 5.558, 8.149, 5.558, 10.740, 7.022,&
+ 8.881, 7.920, 5.990, 7.066, 7.344, 6.706, 4.453, 10.740,&
+ 10.740, 4.453, 8.992, 8.992, 8.992, 8.992, 4.372, 10.740/)
+
+ real(r8), parameter, dimension(N_land_classification) :: rootb_usgs &
+ =(/ 2.614, 2.614, 2.614, 2.614, 2.611, 2.614, 2.608, 1.415,&
+ 2.012, 1.964, 1.955, 1.953, 1.303, 2.175, 1.631, 2.608,&
+ 2.608, 1.631, 8.992, 8.992, 8.992, 8.992, 0.978, 2.608/)
+
+ ! Plant Hydraulics Parameters
+ real(r8), parameter, dimension(N_land_classification) :: kmax_sun0_usgs &
+ = (/ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 0., 2.e-008, 2.e-008,&
+ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008/)
+
+ real(r8), parameter, dimension(N_land_classification) :: kmax_sha0_usgs &
+ = (/ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 0., 2.e-008, 2.e-008,&
+ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008/)
+
+ real(r8), parameter, dimension(N_land_classification) :: kmax_xyl0_usgs &
+ = (/ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 0., 2.e-008, 2.e-008,&
+ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008/)
+
+ real(r8), parameter, dimension(N_land_classification) :: kmax_root0_usgs &
+ = (/ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008,&
+ 2.e-008, 2.e-008, 2.e-008, 0., 2.e-008, 2.e-008,&
+ 0., 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008/)
+
+ ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_sun0_usgs &
+ = (/-150000.0,-340000.0,-340000.0,-340000.0,-340000.0,-343636.4,&
+ -340000.0,-393333.3,-366666.7,-340000.0,-270000.0,-380000.0,&
+ -260000.0,-465000.0,-330000.0,-150000.0,-340000.0,-347272.7,&
+ -150000.0,-340000.0,-342500.0,-341250.0,-150000.0,-150000.0/) *1
+
+ ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_sha0_usgs &
+ = (/-150000.0,-340000.0,-340000.0,-340000.0,-340000.0,-343636.4,&
+ -340000.0,-393333.3,-366666.7,-340000.0,-270000.0,-380000.0,&
+ -260000.0,-465000.0,-330000.0,-150000.0,-340000.0,-347272.7,&
+ -150000.0,-340000.0,-342500.0,-341250.0,-150000.0,-150000.0/) *1
+
+ ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_xyl0_usgs &
+ = (/-200000.0,-340000.0,-340000.0,-340000.0,-340000.0,-343636.4,&
+ -340000.0,-393333.3,-366666.7,-340000.0,-270000.0,-380000.0,&
+ -260000.0,-465000.0,-330000.0,-200000.0,-340000.0,-347272.7,&
+ -200000.0,-340000.0,-342500.0,-341250.0,-200000.0,-200000.0/) *1
+
+ ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_root0_usgs &
+ = (/-200000.0,-340000.0,-340000.0,-340000.0,-340000.0,-343636.4,&
+ -340000.0,-393333.3,-366666.7,-340000.0,-270000.0,-380000.0,&
+ -260000.0,-465000.0,-330000.0,-200000.0,-340000.0,-347272.7,&
+ -200000.0,-340000.0,-342500.0,-341250.0,-200000.0,-200000.0/)*1
+
+ ! shape-fitting parameter for vulnerability curve (-)
+ real(r8), parameter, dimension(N_land_classification) :: ck0_usgs &
+ = (/ 0., 3.95, 3.95, 3.95, 3.95, 3.95, &
+ 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, &
+ 3.95, 3.95, 3.95, 0., 3.95, 3.95, &
+ 0., 3.95, 3.95, 3.95, 0., 0./)
+
+ ! lambda for WUE stomata model
+ real(r8), parameter, dimension(N_land_classification) :: lambda_usgs &
+ = (/1000., 1000., 1000., 1000., 1000., 1000., &
+ 1000., 1000., 1000., 1000., 1000., 1000., &
+ 1000., 1000., 1000., 1000., 1000., 1000., &
+ 1000., 1000., 1000., 1000., 1000., 1000./)
+!end plant hydraulic parameters
+#else
+
+! MODIS IGBP Land Use/Land Cover System Legend
+!-----------------------------------------------------------------------
+! 0 Ocean
+! 1 Evergreen Needleleaf Forests
+! 2 Evergreen Broadleaf Forests
+! 3 Deciduous Needleleaf Forests
+! 4 Deciduous Broadleaf Forests
+! 5 Mixed Forests
+! 6 Closed Shrublands
+! 7 Open Shrublands
+! 8 Woody Savannas
+! 9 Savannas
+!10 Grasslands
+!11 Permanent Wetlands
+!12 Croplands
+!13 Urban and Built-up Lands
+!14 Cropland/Natural Vegetation Mosaics
+!15 Permanent Snow and Ice
+!16 Barren
+!17 Water Bodies
+
+ character(len=256) :: patchclassname (0:N_land_classification) = &
+ (/'0 Ocean ', '1 Evergreen Needleleaf Forests ', &
+ '2 Evergreen Broadleaf Forests ', '3 Deciduous Needleleaf Forests ', &
+ '4 Deciduous Broadleaf Forests ', '5 Mixed Forests ', &
+ '6 Closed Shrublands ', '7 Open Shrublands ', &
+ '8 Woody Savannas ', '9 Savannas ', &
+ '10 Grasslands ', '11 Permanent Wetlands ', &
+ '12 Croplands ', '13 Urban and Built-up Lands ', &
+ '14 Cropland/Natural Vegetation Mosaics', '15 Permanent Snow and Ice ', &
+ '16 Barren ', '17 Water Bodies ' /)
+
+ ! land patch types
+ ! 0: soil, 1: urban, 2: wetland, 3: ice, 4: lake
+ integer , parameter, dimension(N_land_classification) :: patchtypes_igbp &
+ = (/0, 0, 0, 0, 0, 0, 0, 0,&
+ 0, 0, 2, 0, 1, 0, 3, 0,&
+ 4 /)
+
+ ! Look-up table canopy top height
+ !NOTE: now read from input NetCDF file
+ ! shrub land 0.5m? grass like land 1m? all set to 0.5
+ real(r8), parameter, dimension(N_land_classification) :: htop0_igbp &
+ !=(/17.0, 35.0, 17.0, 20.0, 20.0, 0.5, 0.5, 1.0,&
+ ! 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,&
+ ! 1.0 /)
+ =(/17.0, 35.0, 17.0, 20.0, 20.0, 0.5, 0.5, 1.0,&
+ 0.5, 0.5, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5,&
+ 0.5 /)
+
+ ! Look-up table canopy bottom height
+ ! 01/06/2020, yuan: adjust hbop: grass/shrub -> 0, tree->1
+ real(r8), parameter, dimension(N_land_classification) :: hbot0_igbp &
+ !=(/ 8.5, 1.0, 8.5, 11.5, 10.0, 0.1, 0.1, 0.1,&
+ ! 0.1, 0.01, 0.01, 0.01, 0.3, 0.01, 0.01, 0.01,&
+ ! 0.01 /)
+ =(/ 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0,&
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,&
+ 0.0 /)
+
+ ! Look-up table vegetation fractional cover
+ real(r8), parameter, dimension(N_land_classification) :: fveg0_igbp &
+ = 1.0 !(/.../)
+
+ ! Look-up table stem area index
+ !NOTE: now read from input NetCDF file
+ real(r8), parameter, dimension(N_land_classification) :: sai0_igbp &
+ =(/2.0, 2.0, 2.0, 2.0, 2.0, 0.5, 0.5, 0.5,&
+ 0.5, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0, 0.0,&
+ 0.0 /)
+
+ ! ratio to calculate roughness length z0m
+ real(r8), parameter, dimension(N_land_classification) :: z0mr_igbp = 0.1
+
+ ! ratio to calculate displacement height d
+ real(r8), parameter, dimension(N_land_classification) :: displar_igbp = 0.667
+
+ ! inverse&sqrt leaf specific dimension size 4 cm
+ real(r8), parameter, dimension(N_land_classification) :: sqrtdi_igbp = 5.0
+
+ ! leaf angle distribution parameter
+ real(r8), parameter, dimension(N_land_classification) :: chil_igbp &
+ = (/ 0.010, 0.100, 0.010, 0.250, 0.125, 0.010, 0.010, 0.010,&
+ 0.010, -0.300, 0.100, -0.300, 0.010, -0.300, 0.010, 0.010,&
+ 0.010 /)
+
+ ! reflectance of green leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: rhol_vis_igbp &
+ = (/0.070, 0.100, 0.070, 0.100, 0.070, 0.105, 0.105, 0.105,&
+ 0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105, 0.105,&
+ 0.105 /)
+
+ ! reflectance of dead leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: rhos_vis_igbp &
+ = (/0.160, 0.160, 0.160, 0.160, 0.160, 0.160, 0.160, 0.160,&
+ 0.160, 0.360, 0.160, 0.360, 0.160, 0.360, 0.160, 0.160,&
+ 0.160 /)
+
+ ! reflectance of green leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: rhol_nir_igbp &
+ = (/0.350, 0.450, 0.350, 0.450, 0.400, 0.450, 0.450, 0.580,&
+ 0.580, 0.580, 0.450, 0.580, 0.450, 0.580, 0.450, 0.450,&
+ 0.580 /)
+
+ ! reflectance of dead leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: rhos_nir_igbp &
+ = (/0.390, 0.390, 0.390, 0.390, 0.390, 0.390, 0.390, 0.390,&
+ 0.390, 0.580, 0.390, 0.580, 0.390, 0.580, 0.390, 0.390,&
+ 0.580 /)
+
+ ! transmittance of green leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: taul_vis_igbp &
+ = (/0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050,&
+ 0.050, 0.070, 0.050, 0.070, 0.050, 0.070, 0.050, 0.050,&
+ 0.050 /)
+
+ ! transmittance of dead leaf in visible band
+ real(r8), parameter, dimension(N_land_classification) :: taus_vis_igbp &
+ = (/0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,&
+ 0.001, 0.220, 0.001, 0.220, 0.001, 0.220, 0.001, 0.001,&
+ 0.001 /)
+
+ ! transmittance of green leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: taul_nir_igbp &
+ = (/0.100, 0.250, 0.100, 0.250, 0.150, 0.250, 0.250, 0.250,&
+ 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250,&
+ 0.250 /)
+
+ ! transmittance of dead leaf in near infrared band
+ real(r8), parameter, dimension(N_land_classification) :: taus_nir_igbp &
+ = (/0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,&
+ 0.001, 0.380, 0.001, 0.380, 0.001, 0.380, 0.001, 0.001,&
+ 0.001 /)
+
+ ! maximum carboxylation rate at 25 C at canopy top
+ ! /06/03/2014/ based on Bonan et al., 2010 (Table 2)
+ real(r8), parameter, dimension(N_land_classification) :: vmax25_igbp &
+ = (/ 54.0, 72.0, 57.0, 52.0, 52.0, 52.0, 52.0, 52.0,&
+ 52.0, 52.0, 52.0, 57.0,100.0, 57.0, 52.0, 52.0,&
+ 52.0 /)
+
+ ! quantum efficiency
+ !TODO: no C4
+ real(r8), parameter, dimension(N_land_classification) :: effcon_igbp &
+ = (/0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08,&
+ 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08,&
+ 0.08 /)
+
+ !c3c4 flag
+ integer, parameter, dimension(N_land_classification) :: c3c4_igbp &
+ = (/1, 1, 1, 1, 1, 1, 1, 1,&
+ 1, 1, 1, 1, 1, 1, 1, 1,&
+ 1 /)
+
+ ! conductance-photosynthesis slope parameter
+ real(r8), parameter, dimension(N_land_classification) :: g1_igbp &
+ = (/9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0,&
+ 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0,&
+ 9.0 /)
+
+ ! conductance-photosynthesis intercept
+ real(r8), parameter, dimension(N_land_classification) :: g0_igbp &
+ = (/100, 100, 100, 100, 100, 100, 100, 100,&
+ 100, 100, 100, 100, 100, 100, 100, 100,&
+ 100 /)
+
+ ! conductance-photosynthesis slope parameter
+ real(r8), parameter, dimension(N_land_classification) :: gradm_igbp &
+ = (/9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0,&
+ 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0,&
+ 9.0 /)
+
+ ! conductance-photosynthesis intercept
+ real(r8), parameter, dimension(N_land_classification) :: binter_igbp &
+ = (/0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,&
+ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01,&
+ 0.01 /)
+
+ ! respiration fraction
+ real(r8), parameter, dimension(N_land_classification) :: respcp_igbp &
+ = (/0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015,&
+ 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015,&
+ 0.015 /)
+
+ ! slope of high temperature inhibition FUNCTION (s1)
+ real(r8), parameter, dimension(N_land_classification) :: shti_igbp = 0.3
+
+ ! slope of low temperature inhibition FUNCTION (s3)
+ real(r8), parameter, dimension(N_land_classification) :: slti_igbp = 0.2
+
+ ! temperature coefficient in gs-a model (s5)
+ real(r8), parameter, dimension(N_land_classification) :: trda_igbp = 1.3
+
+ ! temperature coefficient in gs-a model (s6)
+ real(r8), parameter, dimension(N_land_classification) :: trdm_igbp = 328.0
+
+ ! temperature coefficient in gs-a model (273.16+25)
+ real(r8), parameter, dimension(N_land_classification) :: trop_igbp = 298.0
+
+ ! 1/2 point of high temperature inhibition FUNCTION (s2)
+ real(r8), parameter, dimension(N_land_classification) :: hhti_igbp &
+ =(/303.0, 313.0, 303.0, 311.0, 307.0, 308.0, 313.0, 313.0,&
+ 313.0, 308.0, 313.0, 308.0, 308.0, 308.0, 303.0, 313.0,&
+ 308.0 /)
+
+ ! 1/2 point of low temperature inhibition FUNCTION (s4)
+ real(r8), parameter, dimension(N_land_classification) :: hlti_igbp &
+ =(/278.0, 288.0, 278.0, 283.0, 281.0, 281.0, 288.0, 288.0,&
+ 288.0, 281.0, 283.0, 281.0, 281.0, 281.0, 278.0, 288.0,&
+ 281.0 /)
+
+ ! coefficient of leaf nitrogen allocation
+ real(r8), parameter, dimension(N_land_classification) :: extkn_igbp = 0.5
+
+ ! depth at 50% roots
+ real(r8), parameter, dimension(N_land_classification) :: d50_igbp &
+ =(/15.0, 15.0, 16.0, 16.0, 15.5, 19.0, 28.0, 18.5,&
+ 28.0, 9.0, 9.0, 22.0, 23.0, 22.0, 1.0, 9.0,&
+ 1.0 /)
+ ! coefficient of root profile
+ real(r8), parameter, dimension(N_land_classification) :: beta_igbp &
+ =(/-1.623, -1.623, -1.681, -1.681, -1.652, -1.336, -1.909, -1.582,&
+ -1.798, -1.359, -1.359, -1.796, -1.757, -1.796, -1.000, -2.261,&
+ -1.000 /)
+
+ ! Table 2. Zeng, 2001
+ ! water/glacier ==> grass
+ ! urban ==> cropland
+ real(r8), parameter, dimension(N_land_classification) :: roota_igbp &
+ =(/ 6.706, 7.344, 7.066, 5.990, 4.453, 6.326, 7.718, 7.604,&
+ 8.235, 10.740, 10.740, 5.558, 5.558, 5.558, 10.740, 4.372,&
+ 10.740 /)
+
+ real(r8), parameter, dimension(N_land_classification) :: rootb_igbp &
+ =(/ 2.175, 1.303, 1.953, 1.955, 1.631, 1.567, 1.262, 2.300,&
+ 1.627, 2.608, 2.608, 2.614, 2.614, 2.614, 2.608, 0.978,&
+ 2.608 /)
+
+ ! Plant Hydraulics Parameters
+ real(r8), parameter, dimension(N_land_classification) :: kmax_sun0_igbp &
+ = (/2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008 /)
+
+ real(r8), parameter, dimension(N_land_classification) :: kmax_sha0_igbp &
+ = (/2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008 /)
+
+ real(r8), parameter, dimension(N_land_classification) :: kmax_xyl0_igbp &
+ = (/2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008 /)
+
+ real(r8), parameter, dimension(N_land_classification) :: kmax_root0_igbp &
+ = (/2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008, &
+ 2.e-008, 2.e-008, 2.e-008, 2.e-008, 2.e-008 /)
+
+ ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_sun0_igbp &
+ = (/-465000.0, -260000.0, -380000.0, -270000.0, -330000.0, -393333.3, &
+ -393333.3, -340000.0, -340000.0, -340000.0, -343636.4, -340000.0, &
+ -150000.0, -343636.4, -150000.0, -150000.0, -150000.0/) *1
+
+ ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_sha0_igbp &
+ = (/-465000.0, -260000.0, -380000.0, -270000.0, -330000.0, -393333.3, &
+ -393333.3, -340000.0, -340000.0, -340000.0, -343636.4, -340000.0, &
+ -150000.0, -343636.4, -150000.0, -150000.0, -150000.0/) *1
+
+ ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_xyl0_igbp &
+ = (/-465000.0, -260000.0, -380000.0, -270000.0, -330000.0, -393333.3, &
+ -393333.3, -340000.0, -340000.0, -340000.0, -343636.4, -340000.0, &
+ -200000.0, -343636.4, -200000.0, -200000.0, -200000.0/) *1
+
+ ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8), parameter, dimension(N_land_classification) :: psi50_root0_igbp &
+ = (/-465000.0, -260000.0, -380000.0, -270000.0, -330000.0, -393333.3, &
+ -393333.3, -340000.0, -340000.0, -340000.0, -343636.4, -340000.0, &
+ -200000.0, -343636.4, -200000.0, -200000.0, -200000.0/) *1
+
+ ! shape-fitting parameter for vulnerability curve (-)
+ real(r8), parameter, dimension(N_land_classification) :: ck0_igbp &
+ = (/3.95, 3.95, 3.95, 3.95, 3.95, 3.95, &
+ 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, &
+ 3.95, 3.95, 3.95, 3.95, 3.95 /)
+ !end plant hydraulic parameters
+
+ ! lambda for WUE stomata model
+ real(r8), parameter, dimension(N_land_classification) :: lambda_igbp &
+ = (/1000., 1000., 1000., 1000., 1000., 1000., &
+ 1000., 1000., 1000., 1000., 1000., 1000., &
+ 1000., 1000., 1000., 1000., 1000./)
+#endif
+
+ real(r8), dimension(N_land_classification) :: &
+ patchtypes, &! land patch types
+ htop0, &! canopy top height
+ hbot0, &! canopy bottom height
+ fveg0, &! canopy vegetation fractional cover
+ sai0, &! canopy stem area index
+ chil, &! leaf angle distribution factor
+ z0mr, &! ratio to calculate roughness length z0m
+ displar, &! ratio to calculate displacement height d
+ sqrtdi, &! inverse sqrt of leaf dimension [m**-0.5]
+
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ effcon, &! quantum efficiency
+ g1, &! conductance-photosynthesis slope parameter
+ g0, &! conductance-photosynthesis intercept
+ gradm, &! conductance-photosynthesis slope parameter
+ binter, &! conductance-photosynthesis intercept
+ respcp, &! respiration fraction
+ shti, &! slope of high temperature inhibition function (s1)
+ slti, &! slope of low temperature inhibition function (s3)
+ trda, &! temperature coefficient in gs-a model (s5)
+ trdm, &! temperature coefficient in gs-a model (s6)
+ trop, &! temperature coefficient in gs-a model (273.16+25)
+ hhti, &! 1/2 point of high temperature inhibition function (s2)
+ hlti, &! 1/2 point of low temperature inhibition function (s4)
+ extkn, &! coefficient of leaf nitrogen allocation
+
+ lambda, &! marginal water cost of carbon gain (mol mol-1)
+
+ d50, &! depth at 50% roots
+ beta ! coefficient of root profile
+
+ integer, dimension(N_land_classification) :: c3c4 ! c3c4 flag
+
+! Plant Hydraulic Parameters
+ real(r8), dimension(N_land_classification) :: &
+ kmax_sun, &! Plant Hydraulics Parameters (TODO@Xingjie Lu, please give more details)
+ kmax_sha, &! Plant Hydraulics Parameters
+ kmax_xyl, &! Plant Hydraulics Parameters
+ kmax_root, &! Plant Hydraulics Parameters
+ psi50_sun, &! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ psi50_sha, &! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ psi50_xyl, &! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ psi50_root, &! water potential at 50% loss of root tissue conductance (mmH2O)
+ ck ! shape-fitting parameter for vulnerability curve (-)
+! end plant hydraulic parameters
+
+ real(r8), PRIVATE, dimension(N_land_classification) :: &
+ roota, &! root fraction para
+ rootb ! root fraction para
+
+ real(r8) :: &
+ rho(2,2,N_land_classification),&! leaf reflectance
+ tau(2,2,N_land_classification) ! leaf transmittance
+
+ ! scheme 1: Schenk and Jackson, 2002, 2: Zeng 2001
+ integer, PRIVATE :: ROOTFR_SCHEME = 1
+
+ ! fraction of roots in each soil layer
+ real(r8), dimension(nl_soil,N_land_classification) :: rootfr
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: Init_LC_Const
+
+CONTAINS
+
+ SUBROUTINE Init_LC_Const
+
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ integer :: i, nsl
+
+#ifdef LULC_USGS
+ patchtypes (:) = patchtypes_usgs (:)
+ htop0 (:) = htop0_usgs (:)
+ hbot0 (:) = hbot0_usgs (:)
+ fveg0 (:) = fveg0_usgs (:)
+ sai0 (:) = sai0_usgs (:)
+ z0mr (:) = z0mr_usgs (:)
+ displar (:) = displar_usgs (:)
+ sqrtdi (:) = sqrtdi_usgs (:)
+ chil (:) = chil_usgs (:)
+ vmax25 (:) = vmax25_usgs (:) * 1.e-6
+ effcon (:) = effcon_usgs (:)
+ c3c4 (:) = c3c4_usgs (:)
+ g1 (:) = g1_usgs (:)
+ g0 (:) = g0_usgs (:)
+ gradm (:) = gradm_usgs (:)
+ binter (:) = binter_usgs (:)
+ respcp (:) = respcp_usgs (:)
+ shti (:) = shti_usgs (:)
+ slti (:) = slti_usgs (:)
+ trda (:) = trda_usgs (:)
+ trdm (:) = trdm_usgs (:)
+ trop (:) = trop_usgs (:)
+ hhti (:) = hhti_usgs (:)
+ hlti (:) = hlti_usgs (:)
+ extkn (:) = extkn_usgs (:)
+ d50 (:) = d50_usgs (:)
+ beta (:) = beta_usgs (:)
+IF (DEF_USE_PLANTHYDRAULICS) THEN
+ kmax_sun (:) = kmax_sun0_usgs (:)
+ kmax_sha (:) = kmax_sha0_usgs (:)
+ kmax_xyl (:) = kmax_xyl0_usgs (:)
+ kmax_root (:) = kmax_root0_usgs (:)
+ psi50_sun (:) = psi50_sun0_usgs (:)
+ psi50_sha (:) = psi50_sha0_usgs (:)
+ psi50_xyl (:) = psi50_xyl0_usgs (:)
+ psi50_root (:) = psi50_root0_usgs(:)
+ ck (:) = ck0_usgs (:)
+ENDIF
+IF (DEF_USE_WUEST)THEN
+ lambda (:) = lambda_usgs (:)
+ENDIF
+ roota (:) = roota_usgs (:)
+ rootb (:) = rootb_usgs (:)
+ rho (1,1,:) = rhol_vis_usgs (:)
+ rho (2,1,:) = rhol_nir_usgs (:)
+ rho (1,2,:) = rhos_vis_usgs (:)
+ rho (2,2,:) = rhos_nir_usgs (:)
+ tau (1,1,:) = taul_vis_usgs (:)
+ tau (2,1,:) = taul_nir_usgs (:)
+ tau (1,2,:) = taus_vis_usgs (:)
+ tau (2,2,:) = taus_nir_usgs (:)
+#else
+ patchtypes (:) = patchtypes_igbp (:)
+ htop0 (:) = htop0_igbp (:)
+ hbot0 (:) = hbot0_igbp (:)
+ fveg0 (:) = fveg0_igbp (:)
+ sai0 (:) = sai0_igbp (:)
+ z0mr (:) = z0mr_igbp (:)
+ displar (:) = displar_igbp (:)
+ sqrtdi (:) = sqrtdi_igbp (:)
+ chil (:) = chil_igbp (:)
+ vmax25 (:) = vmax25_igbp (:) * 1.e-6
+ effcon (:) = effcon_igbp (:)
+ c3c4 (:) = c3c4_igbp (:)
+ g1 (:) = g1_igbp (:)
+ g0 (:) = g0_igbp (:)
+ gradm (:) = gradm_igbp (:)
+ binter (:) = binter_igbp (:)
+ respcp (:) = respcp_igbp (:)
+ shti (:) = shti_igbp (:)
+ slti (:) = slti_igbp (:)
+ trda (:) = trda_igbp (:)
+ trdm (:) = trdm_igbp (:)
+ trop (:) = trop_igbp (:)
+ hhti (:) = hhti_igbp (:)
+ hlti (:) = hlti_igbp (:)
+ extkn (:) = extkn_igbp (:)
+ d50 (:) = d50_igbp (:)
+ beta (:) = beta_igbp (:)
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ kmax_sun (:) = kmax_sun0_igbp (:)
+ kmax_sha (:) = kmax_sha0_igbp (:)
+ kmax_xyl (:) = kmax_xyl0_igbp (:)
+ kmax_root (:) = kmax_root0_igbp (:)
+ psi50_sun (:) = psi50_sun0_igbp (:)
+ psi50_sha (:) = psi50_sha0_igbp (:)
+ psi50_xyl (:) = psi50_xyl0_igbp (:)
+ psi50_root (:) = psi50_root0_igbp(:)
+ ck (:) = ck0_igbp (:)
+ENDIF
+IF (DEF_USE_WUEST)THEN
+ lambda (:) = lambda_igbp (:)
+ENDIF
+ roota (:) = roota_igbp (:)
+ rootb (:) = rootb_igbp (:)
+ rho (1,1,:) = rhol_vis_igbp (:)
+ rho (2,1,:) = rhol_nir_igbp (:)
+ rho (1,2,:) = rhos_vis_igbp (:)
+ rho (2,2,:) = rhos_nir_igbp (:)
+ tau (1,1,:) = taul_vis_igbp (:)
+ tau (2,1,:) = taul_nir_igbp (:)
+ tau (1,2,:) = taus_vis_igbp (:)
+ tau (2,2,:) = taus_nir_igbp (:)
+#endif
+
+ ! ----------------------------------------------------------
+ ! The definition of global root distribution is based on
+ ! Schenk and Jackson, 2002: The Global Biogeography of Roots.
+ ! Ecological Monagraph 72(3): 311-328.
+ ! ----------------------------------------------------------
+ IF (ROOTFR_SCHEME == 1) THEN
+ DO i = 1, N_land_classification
+ rootfr(1,i)=1./(1.+(zi_soi(1)*100./d50(i))**beta(i))
+ rootfr(nl_soil,i)=1.-1./(1.+(zi_soi(nl_soil-1)*100./d50(i))**beta(i))
+
+ DO nsl=2,nl_soil-1
+ rootfr(nsl,i)=1./(1.+(zi_soi(nsl)*100./d50(i))**beta(i)) &
+ -1./(1.+(zi_soi(nsl-1)*100./d50(i))**beta(i))
+ ENDDO
+ ENDDO
+ ELSE
+ DO i = 1, N_land_classification
+ rootfr(1,i) = 1. - 0.5*( &
+ exp(-roota(i) * zi_soi(1)) &
+ + exp(-rootb(i) * zi_soi(1)) )
+
+ rootfr(nl_soil,i) = 0.5*( &
+ exp(-roota(i) * zi_soi(nl_soil)) &
+ + exp(-rootb(i) * zi_soi(nl_soil)) )
+
+ DO nsl = 2, nl_soil-1
+ rootfr(nsl,i) = 0.5*( &
+ exp(-roota(i) * zi_soi(nsl-1)) &
+ + exp(-rootb(i) * zi_soi(nsl-1)) &
+ - exp(-roota(i) * zi_soi(nsl)) &
+ - exp(-rootb(i) * zi_soi(nsl)) )
+ ENDDO
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE Init_LC_Const
+
+END MODULE MOD_Const_LC
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_PFT.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_PFT.F90
new file mode 100644
index 0000000000..0ae52b2ce0
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_PFT.F90
@@ -0,0 +1,1817 @@
+#include
+
+MODULE MOD_Const_PFT
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Set constants for plant functional types (PFTs)
+!
+! Created by Hua Yuan, 08/2019
+!
+! !REVISIONS:
+! 10/2021, Xingjie Lu: added for crop PFTs
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_TimeManager, only: get_calday
+
+ IMPLICIT NONE
+ SAVE
+
+! Plant Functional Type classification
+!-----------------------------------------------------------------------
+! 0 not vegetated
+! 1 needleleaf evergreen temperate tree
+! 2 needleleaf evergreen boreal tree
+! 3 needleleaf deciduous boreal tree
+! 4 broadleaf evergreen tropical tree
+! 5 broadleaf evergreen temperate tree
+! 6 broadleaf deciduous tropical tree
+! 7 broadleaf deciduous temperate tree
+! 8 broadleaf deciduous boreal tree
+! 9 broadleaf evergreen shrub
+!10 broadleaf deciduous temperate shrub
+!11 broadleaf deciduous boreal shrub
+!12 c3 arctic grass
+!13 c3 non-arctic grass
+!14 c4 grass
+!15 c3 crop
+!16 c3_irrigated
+!17 temperate_corn
+!18 irrigated_temperate_corn
+!19 spring_wheat
+!20 irrigated_spring_wheat
+!21 winter_wheat
+!22 irrigated_winter_wheat
+!23 temperate_soybean
+!24 irrigated_temperate_soybean
+!25 barley
+!26 irrigated_barley
+!27 winter_barley
+!28 irrigated_winter_barley
+!29 rye
+!30 irrigated_rye
+!31 winter_rye
+!32 irrigated_winter_rye
+!33 cassava
+!34 irrigated_cassava
+!35 citrus
+!36 irrigated_citrus
+!37 cocoa
+!38 irrigated_cocoa
+!39 coffee
+!40 irrigated_coffee
+!41 cotton
+!42 irrigated_cotton
+!43 datepalm
+!44 irrigated_datepalm
+!45 foddergrass
+!46 irrigated_foddergrass
+!47 grapes
+!48 irrigated_grapes
+!49 groundnuts
+!50 irrigated_groundnuts
+!51 millet
+!52 irrigated_millet
+!53 oilpalm
+!54 irrigated_oilpalm
+!55 potatoes
+!56 irrigated_potatoes
+!57 pulses
+!58 irrigated_pulses
+!59 rapeseed
+!60 irrigated_rapeseed
+!61 rice
+!62 irrigated_rice
+!63 sorghum
+!64 irrigated_sorghum
+!65 sugarbeet
+!66 irrigated_sugarbeet
+!67 sugarcane
+!68 irrigated_sugarcane
+!69 sunflower
+!70 irrigated_sunflower
+!71 miscanthus
+!72 irrigated_miscanthus
+!73 switchgrass
+!74 irrigated_switchgrass
+!75 tropical_corn
+!76 irrigated_tropical_corn
+!77 tropical_soybean
+!78 irrigated_tropical_soybean
+
+ character(len=256) :: pftclassname (0:N_PFT+N_CFT-1) = &
+ (/'0 not vegetated ', '1 needleleaf evergreen temperate tree ', &
+ '2 needleleaf evergreen boreal tree ', '3 needleleaf deciduous boreal tree ', &
+ '4 broadleaf evergreen tropical tree ', '5 broadleaf evergreen temperate tree ', &
+ '6 broadleaf deciduous tropical tree ', '7 broadleaf deciduous temperate tree ', &
+ '8 broadleaf deciduous boreal tree ', '9 broadleaf evergreen shrub ', &
+ '10 broadleaf deciduous temperate shrub', '11 broadleaf deciduous boreal shrub ', &
+ '12 c3 arctic grass ', '13 c3 non-arctic grass ', &
+ '14 c4 grass ', '15 c3 crop ' &
+#ifdef CROP
+ ,'16 c3_irrigated ', '17 temperate_corn ', &
+ '18 irrigated_temperate_corn ', '19 spring_wheat ', &
+ '20 irrigated_spring_wheat ', '21 winter_wheat ', &
+ '22 irrigated_winter_wheat ', '23 temperate_soybean ', &
+ '24 irrigated_temperate_soybean ', '25 barley ', &
+ '26 irrigated_barley ', '27 winter_barley ', &
+ '28 irrigated_winter_barley ', '29 rye ', &
+ '30 irrigated_rye ', '31 winter_rye ', &
+ '32 irrigated_winter_rye ', '33 cassava ', &
+ '34 irrigated_cassava ', '35 citrus ', &
+ '36 irrigated_citrus ', '37 cocoa ', &
+ '38 irrigated_cocoa ', '39 coffee ', &
+ '40 irrigated_coffee ', '41 cotton ', &
+ '42 irrigated_cotton ', '43 datepalm ', &
+ '44 irrigated_datepalm ', '45 foddergrass ', &
+ '46 irrigated_foddergrass ', '47 grapes ', &
+ '48 irrigated_grapes ', '49 groundnuts ', &
+ '50 irrigated_groundnuts ', '51 millet ', &
+ '52 irrigated_millet ', '53 oilpalm ', &
+ '54 irrigated_oilpalm ', '55 potatoes ', &
+ '56 irrigated_potatoes ', '57 pulses ', &
+ '58 irrigated_pulses ', '59 rapeseed ', &
+ '60 irrigated_rapeseed ', '61 rice ', &
+ '62 irrigated_rice ', '63 sorghum ', &
+ '64 irrigated_sorghum ', '65 sugarbeet ', &
+ '66 irrigated_sugarbeet ', '67 sugarcane ', &
+ '68 irrigated_sugarcane ', '69 sunflower ', &
+ '70 irrigated_sunflower ', '71 miscanthus ', &
+ '72 irrigated_miscanthus ', '73 switchgrass ', &
+ '74 irrigated_switchgrass ', '75 tropical_corn ', &
+ '76 irrigated_tropical_corn ', '77 tropical_soybean ', &
+ '78 irrigated_tropical_soybean ' &
+#endif
+ /)
+
+ ! canopy layer number
+ integer , parameter :: canlay_p(0:N_PFT+N_CFT-1) &
+ = (/0, 2, 2, 2, 2, 2, 2, 2 &
+ , 2, 1, 1, 1, 1, 1, 1, 1 &
+#ifdef CROP
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1, 1 &
+ , 1, 1, 1, 1, 1, 1, 1 &
+#endif
+ /)
+
+ ! canopy top height
+ real(r8), parameter :: htop0_p(0:N_PFT+N_CFT-1) &
+ =(/ 0.5, 17.0, 17.0, 14.0, 35.0, 35.0, 18.0, 20.0&
+ ,20.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+#ifdef CROP
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5&
+ , 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 &
+#endif
+ /)
+
+ ! canopy bottom height
+ ! 01/06/2020, yuan: adjust htop: grass/shrub -> 0, tree->1
+ real(r8), parameter :: hbot0_p(0:N_PFT+N_CFT-1) &
+ !TODO: check the setting values
+ !=(/0.01, 8.5, 8.5, 7.0, 1.0, 1.0, 10.0, 11.5&
+ ! 11.5, 0.1, 0.1, 0.1, 0.01, 0.01, 0.01, 0.01/)
+ =(/0.00, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0&
+ , 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+#ifdef CROP
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0&
+ , 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 &
+#endif
+ /)
+
+ ! default vegetation fractional cover
+ real(r8), parameter :: fveg0_p(0:N_PFT+N_CFT-1) &
+ = 1.0 !(/.../)
+
+ ! default stem area index
+ real(r8), parameter :: sai0_p(0:N_PFT+N_CFT-1) &
+ =(/0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0&
+ , 2.0, 0.5, 0.5, 0.5, 0.2, 0.2, 0.2, 0.2&
+#ifdef CROP
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 &
+#endif
+ /)
+
+ ! ratio to calculate roughness length z0m
+ real(r8), parameter :: z0mr_p(0:N_PFT+N_CFT-1) = 0.1
+
+ ! ratio to calculate displacement height d
+ real(r8), parameter :: displar_p(0:N_PFT+N_CFT-1) = 0.667
+
+ ! inverse&sqrt leaf specific dimension size 4 cm
+ real(r8), parameter :: sqrtdi_p(0:N_PFT+N_CFT-1) = 5.0
+
+ ! leaf angle distribution parameter
+ real(r8), parameter :: chil_p(0:N_PFT+N_CFT-1) &
+ = (/-0.300, 0.010, 0.010, 0.010, 0.100, 0.100, 0.010, 0.250&
+ , 0.250, 0.010, 0.250, 0.250, -0.300, -0.300, -0.300, -0.300&
+#ifdef CROP
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300&
+ ,-0.300, -0.300, -0.300, -0.300, -0.300, -0.300, -0.300 &
+#endif
+ /)
+
+ ! reflectance of green leaf in visible band
+#if (defined LULC_IGBP_PC)
+ ! Leaf optical properties adapted from measured data (Dong et al., 2021)
+ real(r8), parameter :: rhol_vis_p(0:N_PFT+N_CFT-1) &
+ = (/0.110, 0.070, 0.070, 0.070, 0.100, 0.110, 0.100, 0.100&
+ , 0.100, 0.070, 0.100, 0.100, 0.110, 0.110, 0.110, 0.110&
+#else
+ real(r8), parameter :: rhol_vis_p(0:N_PFT+N_CFT-1) &
+ = (/0.110, 0.070, 0.070, 0.070, 0.100, 0.100, 0.100, 0.100&
+ , 0.100, 0.070, 0.100, 0.100, 0.110, 0.110, 0.110, 0.110&
+#endif
+#ifdef CROP
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110&
+ , 0.110, 0.110, 0.110, 0.110, 0.110, 0.110, 0.110 &
+#endif
+ /)
+
+ ! reflectance of dead leaf in visible band
+ real(r8), parameter :: rhos_vis_p(0:N_PFT+N_CFT-1) &
+ = (/0.310, 0.160, 0.160, 0.160, 0.160, 0.160, 0.160, 0.160&
+ , 0.160, 0.160, 0.160, 0.160, 0.310, 0.310, 0.310, 0.310&
+#ifdef CROP
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310&
+ , 0.310, 0.310, 0.310, 0.310, 0.310, 0.310, 0.310 &
+#endif
+ /)
+
+ ! reflectance of green leaf in near infrared band
+#if (defined LULC_IGBP_PC)
+ ! Leaf optical properties adapted from measured data (Dong et al., 2021)
+ real(r8), parameter :: rhol_nir_p(0:N_PFT+N_CFT-1) &
+ = (/0.350, 0.360, 0.370, 0.360, 0.450, 0.460, 0.450, 0.420&
+ , 0.450, 0.350, 0.450, 0.450, 0.350, 0.350, 0.350, 0.350&
+#else
+ real(r8), parameter :: rhol_nir_p(0:N_PFT+N_CFT-1) &
+ = (/0.350, 0.350, 0.350, 0.350, 0.450, 0.450, 0.450, 0.450&
+ , 0.450, 0.350, 0.450, 0.450, 0.350, 0.350, 0.350, 0.350&
+#endif
+#ifdef CROP
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350&
+ , 0.350, 0.350, 0.350, 0.350, 0.350, 0.350, 0.350 &
+#endif
+ /)
+
+ ! reflectance of dead leaf in near infrared band
+ real(r8), parameter :: rhos_nir_p(0:N_PFT+N_CFT-1) &
+ = (/0.530, 0.390, 0.390, 0.390, 0.390, 0.390, 0.390, 0.390&
+ , 0.390, 0.390, 0.390, 0.390, 0.530, 0.530, 0.530, 0.530&
+#ifdef CROP
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530&
+ , 0.530, 0.530, 0.530, 0.530, 0.530, 0.530, 0.530 &
+#endif
+ /)
+
+ ! transmittance of green leaf in visible band
+#if (defined LULC_IGBP_PC)
+ ! Leaf optical properties adapted from measured data (Dong et al., 2021)
+ real(r8), parameter :: taul_vis_p(0:N_PFT+N_CFT-1) &
+ = (/0.050, 0.050, 0.050, 0.050, 0.050, 0.060, 0.050, 0.060&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+#else
+ real(r8), parameter :: taul_vis_p(0:N_PFT+N_CFT-1) &
+ = (/0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+#endif
+#ifdef CROP
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050&
+ , 0.050, 0.050, 0.050, 0.050, 0.050, 0.050, 0.050 &
+#endif
+ /)
+
+ ! transmittance of dead leaf in visible band
+ real(r8), parameter :: taus_vis_p(0:N_PFT+N_CFT-1) &
+ = (/0.120, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001&
+ , 0.001, 0.001, 0.001, 0.001, 0.120, 0.120, 0.120, 0.120&
+#ifdef CROP
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120&
+ , 0.120, 0.120, 0.120, 0.120, 0.120, 0.120, 0.120 &
+#endif
+ /)
+
+ ! transmittance of green leaf in near infrared band
+#if (defined LULC_IGBP_PC)
+ ! Leaf optical properties adapted from measured data (Dong et al., 2021)
+ real(r8), parameter :: taul_nir_p(0:N_PFT+N_CFT-1) &
+ = (/0.340, 0.280, 0.290, 0.380, 0.250, 0.330, 0.250, 0.430&
+ , 0.400, 0.100, 0.250, 0.250, 0.340, 0.340, 0.340, 0.340&
+#else
+ real(r8), parameter :: taul_nir_p(0:N_PFT+N_CFT-1) &
+ = (/0.340, 0.100, 0.100, 0.100, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.100, 0.250, 0.250, 0.340, 0.340, 0.340, 0.340&
+#endif
+#ifdef CROP
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340&
+ , 0.340, 0.340, 0.340, 0.340, 0.340, 0.340, 0.340 &
+#endif
+ /)
+
+ ! transmittance of dead leaf in near infrared band
+ real(r8), parameter :: taus_nir_p(0:N_PFT+N_CFT-1) &
+ = (/0.250, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001&
+ , 0.001, 0.001, 0.001, 0.001, 0.250, 0.250, 0.250, 0.250&
+#ifdef CROP
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250&
+ , 0.250, 0.250, 0.250, 0.250, 0.250, 0.250, 0.250 &
+#endif
+ /)
+
+ ! maximum carboxylation rate at 25 C at canopy top
+ ! /06/03/2014/ based on Bonan et al., 2011 (Table 2)
+ !real(r8), parameter :: vmax25_p(0:N_PFT+N_CFT-1) &
+ ! = (/ 52.0, 61.0, 54.0, 57.0, 72.0, 72.0, 52.0, 52.0&
+ ! , 52.0, 72.0, 52.0, 52.0, 52.0, 52.0, 52.0, 57.0&
+ ! /07/27/2022/ based on Bonan et al., 2011 (Table 2, VmaxF(N))
+ ! Temporarilly tune Vegetation parameter to match VGM model (soil too wet)
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), parameter :: vmax25_p(0:N_PFT+N_CFT-1) &
+! = (/ 52.0, 16.1, 16.5, 22.5, 12.3, 10.7, 16.2, 15.1&
+! , 15.3, 21.4, 22.0, 26.6, 34.2, 20.6, 10.0, 57.0&
+! = (/ 52.0, 56.0, 54.0, 57.0, 18.0, 23.0, 31.3, 36.1&
+! , 52.0, 40.0, 37.5, 52.0, 52.0, 52.0, 13.4, 57.0&
+ = (/ 52.0, 25.2, 26.5, 34.1, 13.2, 15.7, 20.3, 24.2&
+ , 28.0, 33.1, 33.4, 48.5, 55.7, 41.5, 10.0, 57.0&
+#ifdef CROP
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0 &
+#endif
+ /) * 1.e-6
+#else
+ real(r8), parameter :: vmax25_p(0:N_PFT+N_CFT-1) &
+! = (/ 52.0, 55.0, 42.0, 29.0, 41.0, 51.0, 36.0, 30.0&
+! , 40.0, 36.0, 30.0, 19.0, 21.0, 26.0, 25.0, 57.0&
+ = (/ 52.0, 56.0, 54.0, 57.0, 18.0, 23.0, 31.3, 36.1&
+ , 52.0, 40.0, 37.5, 52.0, 52.0, 52.0, 13.4, 57.0&
+#ifdef CROP
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0&
+ , 57.0, 57.0, 57.0, 57.0, 57.0, 57.0, 57.0 &
+#endif
+ /) * 1.e-6
+#endif
+
+ ! quantum efficiency
+ real(r8), parameter :: effcon_p(0:N_PFT+N_CFT-1) &
+ = (/0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.05, 0.08&
+#ifdef CROP
+ , 0.08, 0.05, 0.05, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08&
+ , 0.08, 0.08, 0.08, 0.05, 0.05, 0.08, 0.08 &
+#endif
+ /)
+
+ !C3C4 switch 1: C3, 0: C4
+ integer, parameter :: c3c4_p(0:N_PFT+N_CFT-1) &
+ = (/1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 0, 1&
+#ifdef CROP
+ , 1, 0, 0, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 1, 1, 1, 1, 1&
+ , 1, 1, 1, 0, 0, 1, 1 &
+#endif
+ /)
+
+ ! conductance-photosynthesis slope parameter
+ real(r8), parameter :: g1_p(0:N_PFT+N_CFT-1) &
+ = (/4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+#ifdef CROP
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0&
+ , 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0 &
+#endif
+ /)
+
+ ! conductance-photosynthesis intercept
+ real(r8), parameter :: g0_p(0:N_PFT+N_CFT-1) &
+ = (/100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+#ifdef CROP
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100, 100&
+ , 100, 100, 100, 100, 100, 100, 100 &
+#endif
+ /)
+
+ ! conductance-photosynthesis slope parameter
+ real(r8), parameter :: gradm_p(0:N_PFT+N_CFT-1) &
+ = (/9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 4.0, 9.0&
+#ifdef CROP
+ , 9.0, 4.0, 4.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0&
+ , 9.0, 9.0, 9.0, 4.0, 4.0, 9.0, 9.0 &
+#endif
+ /)
+
+ ! conductance-photosynthesis intercept
+ real(r8), parameter :: binter_p(0:N_PFT+N_CFT-1) &
+ = (/0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.04, 0.01&
+#ifdef CROP
+ , 0.01, 0.04, 0.04, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01&
+ , 0.01, 0.01, 0.01, 0.04, 0.04, 0.01, 0.01 &
+#endif
+ /)
+
+ ! respiration fraction
+ real(r8), parameter :: respcp_p(0:N_PFT+N_CFT-1) &
+ = (/0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.025, 0.015&
+#ifdef CROP
+ , 0.015, 0.025, 0.025, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015&
+ , 0.015, 0.015, 0.015, 0.025, 0.025, 0.015, 0.015 &
+#endif
+ /)
+
+ ! slope of high temperature inhibition FUNCTION (s1)
+ real(r8), parameter :: shti_p(0:N_PFT+N_CFT-1) = 0.3
+
+ ! slope of low temperature inhibition FUNCTION (s3)
+ real(r8), parameter :: slti_p(0:N_PFT+N_CFT-1) = 0.2
+
+ ! temperature coefficient in gs-a model (s5)
+ real(r8), parameter :: trda_p(0:N_PFT+N_CFT-1) = 1.3
+
+ ! temperature coefficient in gs-a model (s6)
+ real(r8), parameter :: trdm_p(0:N_PFT+N_CFT-1) = 328.0
+
+ ! temperature coefficient in gs-a model (273.16+25)
+ real(r8), parameter :: trop_p(0:N_PFT+N_CFT-1) = 298.0
+
+ ! 1/2 point of high temperature inhibition FUNCTION (s2)
+ real(r8), parameter :: hhti_p(0:N_PFT+N_CFT-1) &
+ =(/308.0, 303.0, 303.0, 303.0, 313.0, 313.0, 311.0, 311.0&
+ ,311.0, 313.0, 313.0, 303.0, 303.0, 308.0, 313.0, 308.0&
+#ifdef CROP
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0&
+ ,308.0, 308.0, 308.0, 308.0, 308.0, 308.0, 308.0 &
+#endif
+ /)
+
+ ! 1/2 point of low temperature inhibition FUNCTION (s4)
+ real(r8), parameter :: hlti_p(0:N_PFT+N_CFT-1) &
+ =(/281.0, 278.0, 278.0, 278.0, 288.0, 288.0, 283.0, 283.0&
+ ,283.0, 283.0, 283.0, 278.0, 278.0, 281.0, 288.0, 281.0&
+#ifdef CROP
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0&
+ ,281.0, 281.0, 281.0, 281.0, 281.0, 281.0, 281.0 &
+#endif
+ /)
+
+ ! coefficient of leaf nitrogen allocation
+ real(r8), parameter :: extkn_p(0:N_PFT+N_CFT-1) = 0.5
+
+ real(r8) :: &
+#ifndef CROP
+ rho_p(2,2,0:N_PFT-1), &!leaf reflectance
+ tau_p(2,2,0:N_PFT-1) !leaf transmittance
+#else
+ rho_p(2,2,0:N_PFT+N_CFT-1), &!leaf reflectance
+ tau_p(2,2,0:N_PFT+N_CFT-1) !leaf transmittance
+#endif
+
+ ! depth at 50% roots
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: d50_p &
+ =(/27.0, 21.0, 12.0, 12.0, 15.0, 23.0, 16.0, 23.0&
+ ,12.0, 23.5, 23.5, 23.5, 9.0, 7.0, 16.0, 22.0&
+#ifdef CROP
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0&
+ ,22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0 &
+#endif
+ /)
+
+ ! coefficient of root profile
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: beta_p &
+ =(/-2.051, -1.835, -1.880, -1.880, -1.632, -1.757, -1.681, -1.757&
+ , -1.880, -1.623, -1.623, -1.623, -2.621, -1.176, -1.452, -1.796&
+#ifdef CROP
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796&
+ , -1.796, -1.796, -1.796, -1.796, -1.796, -1.796, -1.796 &
+#endif
+ /)
+
+ ! woody (1) or grass (0)
+ integer , parameter, dimension(0:N_PFT+N_CFT-1) :: woody &
+ =(/0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 &
+#ifdef CROP
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 &
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 &
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 &
+ , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 &
+#endif
+ /)
+
+ ! Set the root distribution parameters of PFT
+ real(r8), PRIVATE, parameter :: roota(0:N_PFT+N_CFT-1) &
+ =(/ 0.0, 7.0, 7.0, 7.0, 7.0, 7.0, 6.0, 6.0&
+ , 6.0, 7.0, 7.0, 7.0, 11.0, 11.0, 11.0, 6.0&
+#ifdef CROP
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0&
+ , 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0 &
+#endif
+ /)
+
+ real(r8), PRIVATE, parameter :: rootb(0:N_PFT+N_CFT-1) &
+ =(/ 0.0, 2.0, 2.0, 2.0, 1.0, 1.0, 2.0, 2.0&
+ , 2.0, 1.5, 1.5, 1.5, 2.0, 2.0, 2.0, 3.0&
+#ifdef CROP
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0&
+ , 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 &
+#endif
+ /)
+
+
+! bgc PFT constants
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: grperc = 0.11_r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: grpnow = 1._r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: lf_flab = 0.25_r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: lf_fcel = 0.5_r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: lf_flig = 0.25_r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fr_flab = 0.25_r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fr_fcel = 0.5_r8
+
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fr_flig = 0.25_r8
+
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isshrub & ! True => is a shrub
+ =(/.False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .True., .True., .True., .False., .False., .False., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isgrass & ! True => is a grass
+ =(/.False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .True., .True., .True., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ ! True => is tropical broadleaf evergreen tree
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isbetr &
+ =(/.False., .False., .False., .False., .True., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ ! True => is a broadleaf deciduous tree
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isbdtr &
+ =(/.False., .False., .False., .False., .False., .False., .True., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isevg & ! True => is a evergreen tree
+ =(/.False., .True., .True., .False., .True., .True., .False., .False. &
+ , .False., .True., .False., .False., .False., .False., .False., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ ! True => is a seasonal deciduous tree
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: issed &
+ =(/.False., .False., .False., .True., .False., .False., .False., .True. &
+ , .True., .False., .False., .True., .True., .False., .False., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isstd & ! True => is a stress deciduous tree
+ =(/.False., .False., .False., .False., .False., .False., .True., .False. &
+ , .False., .False., .True., .False., .False., .True., .True., .True. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isbare & ! True => is a bare land
+ =(/.True., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: iscrop & ! True => is a crop land
+ =(/.False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .True. &
+#ifdef CROP
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True. &
+#endif
+ /)
+
+ logical , parameter, dimension(0:N_PFT+N_CFT-1) :: isnatveg &! True => is a natural vegetation
+ =(/.False., .True., .True., .True., .True., .True., .True., .True. &
+ , .True., .True., .True., .True., .True., .True., .True., .False. &
+#ifdef CROP
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fsr_pft &
+ =(/ 0., 0.26, 0.26, 0.26, 0.25, 0.25, 0.25, 0.25 &
+ , 0.25, 0.28, 0.28, 0.28, 0.33, 0.33, 0.33, 0.33 &
+#ifdef CROP
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+ , 0.33, 0.33, 0.33, 0.33, 0.33, 0.33, 0.33 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fd_pft &
+ =(/ 0., 24., 24., 24., 24., 24., 24., 24. &
+ , 24., 24., 24., 24., 24., 24., 24., 24. &
+#ifdef CROP
+ , 24., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: leafcn &
+ =(/ 1., 58., 58., 25.8131130614352 &
+ , 29.603315571344, 29.603315571344, 23.4521575984991, 23.4521575984991 &
+ , 23.4521575984991, 36.4166059723234, 23.2558139534884, 23.2558139534884 &
+ , 28.0269058295964, 28.0269058295964, 35.3606789250354, 28.0269058295964 &
+#ifdef CROP
+ , 25., 25., 25., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 20. &
+ , 20., 20., 20., 25. &
+ , 25., 20., 20., 20. &
+ , 20., 20., 20., 25. &
+ , 25., 20., 20. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: frootcn &
+ =(/ 1., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+#ifdef CROP
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42., 42.&
+ , 42., 42., 42., 42., 42., 42., 42. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: livewdcn &
+ =(/ 1., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: deadwdcn &
+ =(/ 1., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500., 500.&
+ , 500., 500., 500., 500., 500., 500., 500. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: graincn &
+ =(/-999., -999., -999., -999., -999., -999., -999., -999.&
+ , -999., -999., -999., -999., -999., -999., -999., -999.&
+#ifdef CROP
+ , -999., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50., 50.&
+ , 50., 50., 50., 50., 50., 50., 50. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: lflitcn &
+ =(/ 1., 70., 80., 50., 60., 60., 50., 50.&
+ , 50., 60., 50., 50., 50., 50., 50., 50.&
+#ifdef CROP
+ , 50., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25., 25.&
+ , 25., 25., 25., 25., 25., 25., 25. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: leaf_long &
+ =(/ 0., 3.30916666666667, 3.30916666666667, 0.506666666666667&
+ , 1.4025, 1.4025, 0.48333333333333, 0.483333333333333&
+ , 0.483333333333333, 1.32333333333333, 0.39, 0.39&
+ , 0.320833333333333, 0.32083333333333, 0.14, 0.320833333333333&
+#ifdef CROP
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1., 1.&
+ , 1., 1., 1. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: cc_leaf &
+ =(/ 0., 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: cc_lstem &
+ =(/ 0., 0.3, 0.3, 0.3, 0.27, 0.27, 0.27, 0.27&
+ , 0.27, 0.35, 0.35, 0.35, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: cc_dstem &
+ =(/ 0., 0.3, 0.3, 0.3, 0.27, 0.27, 0.27, 0.27&
+ , 0.27, 0.35, 0.35, 0.35, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: cc_other &
+ =(/ 0., 0.5, 0.5, 0.5, 0.45, 0.45, 0.45, 0.45&
+ , 0.45, 0.55, 0.55, 0.55, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fm_leaf &
+ =(/ 0., 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fm_lstem &
+ =(/ 0., 0.5, 0.5, 0.5, 0.45, 0.45, 0.35, 0.35&
+ , 0.45, 0.55, 0.55, 0.55, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fm_lroot &
+ =(/ 0., 0.15, 0.15, 0.15, 0.13, 0.13, 0.1, 0.1&
+ , 0.13, 0.17, 0.17, 0.17, 0.2, 0.2, 0.2, 0.2&
+#ifdef CROP
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fm_root &
+ =(/ 0., 0.15, 0.15, 0.15, 0.13, 0.13, 0.1, 0.1&
+ , 0.13, 0.17, 0.17, 0.17, 0.2, 0.2, 0.2, 0.2&
+#ifdef CROP
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fm_droot &
+ =(/ 0., 0.15, 0.15, 0.15, 0.13, 0.13, 0.1, 0.1&
+ , 0.13, 0.17, 0.17, 0.17, 0.2, 0.2, 0.2, 0.2&
+#ifdef CROP
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2&
+ , 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fm_other &
+ =(/ 0., 0.5, 0.5, 0.5, 0.45, 0.45, 0.35, 0.35&
+ , 0.45, 0.55, 0.55, 0.55, 0.8, 0.8, 0.8, 0.8&
+#ifdef CROP
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8&
+ , 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: froot_leaf &
+ =(/ 0., 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5&
+ , 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5&
+#ifdef CROP
+ , 1., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2., 2.&
+ , 2., 2., 2., 2., 2., 2., 2. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: croot_stem &
+ =(/ 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3&
+ , 0.3, 0.3, 0.3, 0.3, 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: stem_leaf &
+ =(/ 0., 2.3, 2.3, 1., 2.3, 1.5, 1., 2.3&
+ , 2.3, 1.4, 0.24, 0.24, 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: flivewd &
+ =(/ 0., 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1&
+ , 0.1, 0.5, 0.5, 0.1, 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: fcur2 &
+ =(/ 0., 1., 1., 0., 1., 1., 0., 0.&
+ , 0., 1., 0., 0., 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1., 1.&
+ , 1., 1., 1., 1., 1., 1., 1. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: dsladlai &
+ =(/ 0., 0.00125, 0.001, 0.003, 0.00122, 0.0015, 0.0027, 0.0027&
+ , 0.0027, 0., 0., 0., 0., 0., 0., 0.&
+#ifdef CROP
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0., 0.&
+ , 0., 0., 0., 0., 0., 0., 0. &
+#endif
+ /)
+
+ real(r8), parameter, dimension(0:N_PFT+N_CFT-1) :: slatop &
+ =(/ 0., 0.01222, 0.01122, 0.02432, 0.03143, 0.02728, 0.03385, 0.03541&
+ , 0.0447, 0.01332, 0.02255, 0.01564, 0.01077, 0.02663, 0.01983, 0.04024&
+#ifdef CROP
+ , 0.035, 0.05, 0.05, 0.035, 0.035, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.05, 0.05, 0.035, 0.035, 0.035&
+ , 0.035, 0.035, 0.035, 0.05, 0.05, 0.035, 0.035 &
+#endif
+ /)
+!--- crop variables ---
+ ! Max fertilizer to be applied in total (kg N/m2)
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: manure &
+ = (/ 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+#ifdef CROP
+ , 0., 0.0020, 0.0020, 0.0020, 0.0020, 0.0020, 0.0020, 0.0020 &
+ , 0.0020, 0.0020, 0.0020, 0.0020, 0.0020, 0.0020, 0.0020, 0.0020 &
+ , 0.0020, 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0.0020, 0.0020, 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0.0020, 0.0020, 0. &
+ , 0., 0., 0., 0.0020, 0.0020, 0., 0., 0. &
+ , 0., 0., 0., 0.0020, 0.0020, 0.0020, 0.0020 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: lfemerg & ! parameter used in CNPhenology
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.11, 0.11, 0.07, 0.07, 0.03, 0.03, 0.15 &
+ , 0.15, 0.07, 0.07, 0.03, 0.03, 0.07, 0.07, 0.03 &
+ , 0.03, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 0.07, 0.07, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 0.12, 0.12, -999.9 &
+ , -999.9, -999.9, -999.9, 0.11, 0.11, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 0.11, 0.11, 0.15, 0.15 &
+#endif
+ /)
+
+ integer, parameter, dimension(0:N_PFT+N_CFT-1) :: mxmat & ! parameter used in CNPhenology
+ = (/-999, -999, -999, -999, -999, -99 , -999, -999 &
+ , -999, -999, -999, -999, -999, -999, -999, -999 &
+#ifdef CROP
+ , -999, 150, 150, 150, 150, 270, 270, 150 &
+ , 150, 150, 150, 270, 270, 150, 150, 270 &
+ , 270, -999, -999, -999, -999, -999, -999, -999 &
+ , -999, 150, 150, -999, -999, -999, -999, -999 &
+ , -999, -999, -999, -999, -999, -999, -999, -999 &
+ , -999, -999, -999, -999, -999, 150, 150, -999 &
+ , -999, -999, -999, 300, 300, -999, -999, -999 &
+ , -999, -999, -999, 150, 150, 150, 150 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: grnfill & ! parameter used in CNPhenology
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.64, 0.64, 0.6, 0.6, 0.67, 0.67, 0.69 &
+ , 0.69, 0.6, 0.6, 0.67, 0.67, 0.6, 0.6, 0.67 &
+ , 0.67, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 0.6, 0.6, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 0.68, 0.68, -999.9 &
+ , -999.9, -999.9, -999.9, 0.64, 0.64, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 0.64, 0.64, 0.69, 0.69 &
+#endif
+ /)
+
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: baset & ! parameter used in accFlds
+ = (/0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+#ifdef CROP
+ , 0., 8., 8., 0., 0., 0., 0., 10. &
+ , 10., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 10., 10., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 0., 0., 0. &
+ , 0., 0., 0., 0., 0., 10., 10., 0. &
+ , 0., 0., 0., 10., 10., 0., 0., 0. &
+ , 0., 0., 0., 8., 8., 10., 10. &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: astemf & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.0, 0.0, 0.05, 0.05, 0.05, 0.05, 0.05 &
+ , 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05 &
+ , 0.05, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 0.3, 0.3, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 0.05, 0.05, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 0.0, 0.0, 0.05, 0.05 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: arooti & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.4, 0.4, 0.1, 0.1, 0.1, 0.1, 0.2 &
+ , 0.2, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 0.1, 0.1, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 0.1, 0.1, -999.9 &
+ , -999.9, -999.9, -999.9, 0.4, 0.4, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 0.4, 0.4, 0.2, 0.2 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: arootf & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.05, 0.05, 0.0, 0.0, 0.0, 0.0, 0.1 &
+ , 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 &
+ , 0.0, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 0.2, 0.2, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 0.0, 0.0, -999.9 &
+ , -999.9, -999.9, -999.9, 0.05, 0.05, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 0.05, 0.05, 0.1, 0.1 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) ::fleafi & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.8, 0.8, 0.9, 0.9, 0.9, 0.9, 0.9 &
+ , 0.9, 0.85, 0.85, 0.9, 0.9, 0.9, 0.9, 0.9 &
+ , 0.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 0.85, 0.85, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 0.75, 0.75, -999.9 &
+ , -999.9, -999.9, -999.9, 0.8, 0.8, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 0.8, 0.8, 0.85, 0.85 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: bfact & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+ , 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: declfact & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+ , 1.05, 1.05, 1.05, 1.05, 1.05, 1.05, 1.05 &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: allconss & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 2., 2., 1., 1., 1., 1., 5. &
+ , 5., 1., 1., 1., 1., 1., 1., 1. &
+ , 1., -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 5., 5., -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 1., 1., -999.9 &
+ , -999.9, -999.9, -999.9, 2., 2., -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 2., 2., 5., 5. &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: allconsl & ! parameter used in CNAllocation
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 5., 5., 3., 3., 3., 3., 2. &
+ , 2., 3., 3., 3., 3., 3., 3., 3. &
+ , 3., -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 2., 2., -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 3., 3., -999.9 &
+ , -999.9, -999.9, -999.9, 5., 5., -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 5., 5., 2., 2. &
+#endif
+ /)
+
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: fleafcn & ! C:N during grain fill; leaf
+ = (/999., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 999., 999., 999. &
+#ifdef CROP
+ , 999., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65., 65. &
+ , 65., 65., 65., 65., 65., 65., 65. &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: fstemcn & ! C:N during grain fill; stem
+ = (/999., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 999., 999., 999. &
+#ifdef CROP
+ , 999., 120., 120., 100., 100., 100., 100., 130. &
+ , 130., 100., 100., 100., 100., 100., 100., 100. &
+ , 100., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 130., 130., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 100., 100., 999. &
+ , 999., 999., 999., 120., 120., 999., 999., 999. &
+ , 999., 999., 999., 120., 120., 130., 130. &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: ffrootcn & ! C:N during grain fill; fine root
+ = (/999., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 999., 999., 999. &
+#ifdef CROP
+ , 999., 0., 0., 40., 40., 40., 40., 0. &
+ , 0., 40., 40., 40., 40., 40., 40., 40. &
+ , 40., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 0., 0., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 999., 999., 999. &
+ , 999., 999., 999., 999., 999., 40., 40., 999. &
+ , 999., 999., 999., 0., 0., 999., 999., 999. &
+ , 999., 999., 999., 0., 0., 0., 0. &
+#endif
+ /)
+
+ real(r8),parameter, dimension(0:N_PFT+N_CFT-1) :: laimx & ! maximum leaf area index
+ = (/-999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+#ifdef CROP
+ , -999.9, 5., 5., 7., 7., 7., 7., 6. &
+ , 6., 7., 7., 7., 7., 7., 7., 7. &
+ , 7., -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, 6., 6., -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, -999.9, -999.9, 7., 7., -999.9 &
+ , -999.9, -999.9, -999.9, 5., 5., -999.9, -999.9, -999.9 &
+ , -999.9, -999.9, -999.9, 5., 5., 6., 6. &
+#endif
+ /)
+#ifdef CROP
+ integer, parameter, dimension(0:N_PFT+N_CFT-1) :: mergetoclmpft & ! merge crop functional types
+ = (/0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 &
+ , 19, 20, 21, 22, 23, 24, 19, 20, 21, 22, 19, 20, 21, 22, 61, 62, 19, 20, 61 &
+ , 62, 61, 62, 41, 42, 41, 42, 19, 20, 19, 20, 61, 62, 75, 76, 61, 62, 19, 20 &
+ , 19, 20, 19, 20, 61, 62, 75, 76, 19, 20, 67, 68, 19, 20, 75, 76, 75, 76, 75 &
+ , 76, 77, 78/)
+#endif
+! end bgc variables
+
+! Plant Hydraulics Parameters
+ real(r8), parameter :: kmax_sun_p(0:N_PFT+N_CFT-1) &
+ = (/ 0.,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#ifdef CROP
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#endif
+ /)
+
+ real(r8), parameter :: kmax_sha_p(0:N_PFT+N_CFT-1) &
+ = (/ 0.,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#ifdef CROP
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#endif
+ /)
+ real(r8), parameter :: kmax_xyl_p(0:N_PFT+N_CFT-1) &
+ = (/ 0.,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#ifdef CROP
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#endif
+ /)
+
+ real(r8), parameter :: kmax_root_p(0:N_PFT+N_CFT-1) &
+ = (/ 0.,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#ifdef CROP
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+ ,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007,1.e-007&
+#endif
+ /)
+
+ ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ real(r8), parameter :: psi50_sun_p(0:N_PFT+N_CFT-1) &
+ = (/-150000, -530000, -400000, -380000, -250000, -270000, -340000, -270000&
+ ,-200000, -400000, -390000, -390000, -340000, -340000, -340000, -340000&
+#ifdef CROP
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000&
+#endif
+ /)
+
+ ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ real(r8), parameter :: psi50_sha_p(0:N_PFT+N_CFT-1) &
+ = (/-150000, -530000, -400000, -380000, -250000, -270000, -340000, -270000&
+ ,-200000, -400000, -390000, -390000, -340000, -340000, -340000, -340000&
+#ifdef CROP
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000&
+#endif
+ /)
+
+ ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ real(r8), parameter :: psi50_xyl_p(0:N_PFT+N_CFT-1) &
+ = (/-200000, -530000, -400000, -380000, -250000, -270000, -340000, -270000&
+ ,-200000, -400000, -390000, -390000, -340000, -340000, -340000, -340000&
+#ifdef CROP
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000&
+#endif
+ /)
+
+ ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8), parameter :: psi50_root_p(0:N_PFT+N_CFT-1) &
+ = (/-200000, -530000, -400000, -380000, -250000, -270000, -340000, -270000&
+ ,-200000, -400000, -390000, -390000, -340000, -340000, -340000, -340000&
+#ifdef CROP
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000, -340000&
+ ,-340000, -340000, -340000, -340000, -340000, -340000, -340000&
+#endif
+ /)
+
+ ! shape-fitting parameter for vulnerability curve (-)
+ real(r8), parameter :: ck_p(0:N_PFT+N_CFT-1) &
+ = (/3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+#ifdef CROP
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+ ,3.95, 3.95, 3.95, 3.95, 3.95, 3.95, 3.95&
+#endif
+ /)
+!end plant hydraulic parameters
+
+ ! Temporally tune Vegetation parameter to match VGM model (soil too wet)
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), parameter :: lambda_p(0:N_PFT+N_CFT-1) &
+ = (/1000., 222., 383., 467., 2500., 500., 737., 428.&
+ , 199., 749., 751., 200., 150., 480., 800., 1000.&
+#ifdef CROP
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+#endif
+ /)
+#else
+ real(r8), parameter :: lambda_p(0:N_PFT+N_CFT-1) &
+ = (/1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+#ifdef CROP
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+ ,1000., 1000., 1000., 1000., 1000., 1000., 1000.&
+#endif
+ /)
+#endif
+ ! irrigation parameter for irrigated crop
+ logical , parameter :: irrig_crop(0:N_PFT+N_CFT-1) &
+ =(/.False., .False., .False., .False., .False., .False., .False., .False. &
+ , .False., .False., .False., .False., .False., .False., .False., .False. &
+#ifdef CROP
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True., .False. &
+ , .True., .False., .True., .False., .True., .False., .True. &
+#endif
+ /)
+
+
+ ! scheme 1: Schenk and Jackson, 2002, 2: Zeng 2001
+ integer, PRIVATE :: ROOTFR_SCHEME = 1
+
+ !fraction of roots in each soil layer
+#ifdef CROP
+ real(r8), dimension(nl_soil,N_PFT+N_CFT) :: &
+ rootfr_p(1:nl_soil, 0:N_PFT+N_CFT-1)
+#else
+ real(r8), dimension(nl_soil,N_PFT) :: &
+ rootfr_p(1:nl_soil, 0:N_PFT-1)
+#endif
+
+ integer, PRIVATE :: i, nsl
+
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: Init_PFT_Const
+
+CONTAINS
+
+ SUBROUTINE Init_PFT_Const
+
+ IMPLICIT NONE
+
+ rho_p(1,1,:) = rhol_vis_p(:)
+ rho_p(2,1,:) = rhol_nir_p(:)
+ rho_p(1,2,:) = rhos_vis_p(:)
+ rho_p(2,2,:) = rhos_nir_p(:)
+ tau_p(1,1,:) = taul_vis_p(:)
+ tau_p(2,1,:) = taul_nir_p(:)
+ tau_p(1,2,:) = taus_vis_p(:)
+ tau_p(2,2,:) = taus_nir_p(:)
+
+IF (ROOTFR_SCHEME == 1) THEN
+#ifdef CROP
+ DO i = 0, N_PFT+N_CFT-1
+#else
+ DO i = 0, N_PFT-1
+#endif
+ rootfr_p(1,i)=1./(1.+(zi_soi(1)*100./d50_p(i))**beta_p(i))
+ rootfr_p(nl_soil,i)=1.-1./(1.+(zi_soi(nl_soil-1)*100./d50_p(i))**beta_p(i))
+
+ DO nsl=2,nl_soil-1
+ rootfr_p(nsl,i)=1./(1.+(zi_soi(nsl)*100./d50_p(i))**beta_p(i)) &
+ -1./(1.+(zi_soi(nsl-1)*100./d50_p(i))**beta_p(i))
+ ENDDO
+ ENDDO
+ELSE
+ ! PFT rootfr_p (Zeng, 2001)
+#ifdef CROP
+ DO i = 0, N_PFT+N_CFT-1
+#else
+ DO i = 0, N_PFT-1
+#endif
+ rootfr_p(1,i) = 1. - 0.5*( &
+ exp(-roota(i) * zi_soi(1)) &
+ + exp(-rootb(i) * zi_soi(1)) )
+
+ rootfr_p(nl_soil,i) = 0.5*( &
+ exp(-roota(i) * zi_soi(nl_soil)) &
+ + exp(-rootb(i) * zi_soi(nl_soil)) )
+
+ DO nsl = 2, nl_soil-1
+ rootfr_p(nsl,i) = 0.5*( &
+ exp(-roota(i) * zi_soi(nsl-1)) &
+ + exp(-rootb(i) * zi_soi(nsl-1)) &
+ - exp(-roota(i) * zi_soi(nsl)) &
+ - exp(-rootb(i) * zi_soi(nsl)) )
+ ENDDO
+ ENDDO
+ENDIF
+
+
+ END SUBROUTINE Init_PFT_Const
+
+END MODULE MOD_Const_PFT
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_Physical.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_Physical.F90
new file mode 100644
index 0000000000..2a9e8e5b6e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Const_Physical.F90
@@ -0,0 +1,30 @@
+MODULE MOD_Const_Physical
+
+!=======================================================================
+! physical constants
+!=======================================================================
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ PUBLIC
+ real(r8), parameter :: denice = 917. ! density of ice [kg/m3]
+ real(r8), parameter :: denh2o = 1000. ! density of liquid water [kg/m3]
+ real(r8), parameter :: cpliq = 4188. ! Specific heat of water [J/kg/K]
+ real(r8), parameter :: cpice = 2117.27 ! Specific heat of ice [J/kg/K]
+ real(r8), parameter :: cpair = 1004.64 ! specific heat of dry air [J/kg/K]
+ real(r8), parameter :: hfus = 0.3336e6 ! latent heat of fusion for ice [J/kg]
+ real(r8), parameter :: hvap = 2.5104e6 ! latent heat of evap for water [J/kg]
+ real(r8), parameter :: hsub = 2.8440e6 ! latent heat of sublimation [J/kg]
+ real(r8), parameter :: tkair = 0.023 ! thermal conductivity of air [W/m/k]
+ real(r8), parameter :: tkice = 2.290 ! thermal conductivity of ice [W/m/k]
+ real(r8), parameter :: tkwat = 0.6 ! thermal conductivity of water [W/m/k]
+ real(r8), parameter :: tfrz = 273.16 ! freezing temperature [K]
+ real(r8), parameter :: rgas = 287.04 ! gas constant for dry air [J/kg/K]
+ real(r8), parameter :: roverg = 4.71047e4 ! rw/g = (8.3144/0.018)/(9.80616)*1000. mm/K
+ real(r8), parameter :: rwat = 461.296 ! gas constant for water vapor [J/(kg K)]
+ real(r8), parameter :: grav = 9.80616 ! gravity constant [m/s2]
+ real(r8), parameter :: vonkar = 0.4 ! von Karman constant [-]
+ real(r8), parameter :: stefnc = 5.67e-8 ! Stefan-Boltzmann constant [W/m2/K4]
+
+END MODULE MOD_Const_Physical
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_CropReadin.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_CropReadin.F90
new file mode 100644
index 0000000000..cafdfd6086
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_CropReadin.F90
@@ -0,0 +1,377 @@
+#include
+
+#ifdef CROP
+MODULE MOD_CropReadin
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: CROP_readin
+
+CONTAINS
+
+ SUBROUTINE CROP_readin ()
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Read in crop planting date from data, and fertilization from data.
+! Save these data in patch vector.
+!
+! Original: Shupeng Zhang, Zhongwang Wei, and Xingjie Lu, 2022
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ USE MOD_SpatialMapping
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_TimeVariables
+
+ USE MOD_Vars_Global
+ USE MOD_LandPFT
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_RangeCheck
+ USE MOD_Block
+
+ IMPLICIT NONE
+
+ character(len=256) :: file_crop
+ type(grid_type) :: grid_crop
+ type(block_data_real8_2d) :: f_xy_crop
+ type(spatial_mapping_type) :: mg2patch_crop
+ type(spatial_mapping_type) :: mg2pft_crop
+ character(len=256) :: file_irrig
+ type(grid_type) :: grid_irrig
+ type(block_data_int32_2d) :: f_xy_irrig
+ type(spatial_mapping_type) :: mg2pft_irrig
+
+ character(len=256) :: file_irrigalloc
+ type(grid_type) :: grid_irrigalloc
+ type(block_data_real8_2d) :: f_xy_irrigalloc
+ type(spatial_mapping_type) :: mg2p_irrigalloc
+
+ character(len=256) :: file_fert
+ type(grid_type) :: grid_fert
+ type(block_data_real8_2d) :: f_xy_fert
+ type(spatial_mapping_type) :: mg2pft_fert
+
+ real(r8),allocatable :: pdrice2_tmp (:)
+ real(r8),allocatable :: plantdate_tmp (:)
+ real(r8),allocatable :: fertnitro_tmp (:)
+ integer ,allocatable :: irrig_method_tmp (:)
+
+ real(r8),allocatable :: fertilizer_tmp (:)
+ real(r8),allocatable :: manure_tmp (:)
+
+ ! Local variables
+ real(r8), allocatable :: lat(:), lon(:)
+ real(r8) :: missing_value
+ integer :: cft, npatch, ipft
+ character(len=2) :: cx
+ integer :: iblkme, iblk, jblk
+ integer :: maxvalue, minvalue
+
+ ! READ in crops
+
+ file_crop = trim(DEF_dir_runtime) // '/crop/plantdt-colm-64cfts-rice2_fillcoast.nc'
+
+ CALL ncio_read_bcast_serial (file_crop, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_crop, 'lon', lon)
+
+ CALL grid_crop%define_by_center (lat, lon)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_crop, f_xy_crop)
+ ENDIF
+
+ ! missing value
+ IF (p_is_root) THEN
+ CALL ncio_get_attr (file_crop, 'pdrice2', 'missing_value', missing_value)
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_bcast (missing_value, 1, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#endif
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_crop, 'pdrice2', grid_crop, f_xy_crop)
+ ENDIF
+
+ CALL mg2patch_crop%build_arealweighted (grid_crop, landpatch)
+ CALL mg2patch_crop%set_missing_value (f_xy_crop, missing_value)
+
+ CALL mg2pft_crop%build_arealweighted (grid_crop, landpft)
+ CALL mg2pft_crop%set_missing_value (f_xy_crop, missing_value)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) allocate(pdrice2_tmp (numpatch))
+ IF (numpft > 0) allocate(plantdate_tmp (numpft))
+ IF (numpft > 0) allocate(fertnitro_tmp (numpft))
+ IF (numpft > 0) allocate(irrig_method_tmp (numpft))
+ ENDIF
+
+ ! (1) Read in plant date for rice2.
+ file_crop = trim(DEF_dir_runtime) // '/crop/plantdt-colm-64cfts-rice2_fillcoast.nc'
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_crop, 'pdrice2', grid_crop, f_xy_crop)
+ ENDIF
+
+ CALL mg2patch_crop%grid2pset (f_xy_crop, pdrice2_tmp)
+
+ IF (p_is_compute) THEN
+ DO npatch = 1, numpatch
+ IF (pdrice2_tmp(npatch) /= spval) THEN
+ pdrice2 (npatch) = int(pdrice2_tmp (npatch))
+ ELSE
+ pdrice2 (npatch) = 0
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef RangeCheck
+ CALL check_vector_data ('plant date value for rice2 ', pdrice2)
+#endif
+
+ ! (2) Read in plant date.
+ IF (p_is_compute) THEN
+ IF (numpft > 0) plantdate_p(:) = -99999999._r8
+ ENDIF
+
+ file_crop = trim(DEF_dir_runtime) // '/crop/plantdt-colm-64cfts-rice2_fillcoast.nc'
+ DO cft = 15, 78
+ write(cx, '(i2.2)') cft
+ IF (p_is_active) THEN
+ CALL ncio_read_block_time (file_crop, &
+ 'PLANTDATE_CFT_'//trim(cx), grid_crop, 1, f_xy_crop)
+ ENDIF
+
+ CALL mg2pft_crop%grid2pset (f_xy_crop, plantdate_tmp)
+
+ IF (p_is_compute) THEN
+ DO ipft = 1, numpft
+ IF(landpft%settyp(ipft) .eq. cft)THEN
+ plantdate_p(ipft) = plantdate_tmp(ipft)
+ IF(plantdate_p(ipft) <= 0._r8) THEN
+ plantdate_p(ipft) = -99999999._r8
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+#ifdef RangeCheck
+ CALL check_vector_data ('plantdate_pfts value ', plantdate_p)
+#endif
+
+ ! (3) Read in fertlization
+ IF (DEF_FERT_SOURCE == 1) THEN
+ IF (p_is_compute) THEN
+ IF (numpft > 0) fertnitro_p(:) = -99999999._r8
+ ENDIF
+
+ file_fert = trim(DEF_dir_runtime) // '/crop/fertnitro_fillcoast.nc'
+ DO cft = 15, 78
+ write(cx, '(i2.2)') cft
+ IF (p_is_active) THEN
+ CALL ncio_read_block_time (file_fert, &
+ 'CONST_FERTNITRO_CFT_'//trim(cx), grid_crop, 1, f_xy_crop)
+ ENDIF
+
+ CALL mg2pft_crop%grid2pset (f_xy_crop, fertnitro_tmp)
+
+ IF (p_is_compute) THEN
+ DO ipft = 1, numpft
+ IF(landpft%settyp(ipft) .eq. cft)THEN
+ fertnitro_p(ipft) = fertnitro_tmp(ipft)
+ IF(fertnitro_p(ipft) <= 0._r8) THEN
+ fertnitro_p(ipft) = 0._r8
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ELSEIF (DEF_FERT_SOURCE == 2)THEN
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+ allocate(fertilizer_tmp(numpft))
+ allocate(manure_tmp(numpft))
+ ENDIF
+ ENDIF
+
+ file_fert = trim(DEF_dir_runtime) // '/crop/fertilizer_2015soc.nc'
+
+ CALL ncio_read_bcast_serial (file_fert, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_fert, 'lon', lon)
+ CALL grid_fert%define_by_center (lat, lon)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_fert, f_xy_fert)
+ ENDIF
+
+ CALL mg2pft_fert%build_arealweighted (grid_fert, landpft)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ IF (p_is_compute) THEN
+ fertnitro_p(:) = -99999999._r8
+ manunitro_p(:) = -99999999._r8
+ ENDIF
+
+ ! read manure
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_fert, 'manure', grid_fert, f_xy_fert)
+ ENDIF
+
+ CALL mg2pft_fert%grid2pset (f_xy_fert, manure_tmp)
+
+ IF (p_is_compute) THEN
+ DO ipft = 1, numpft
+ IF (landpft%settyp(ipft) .ge. 15) THEN
+ manunitro_p(ipft) = manure_tmp(ipft)
+ IF (manunitro_p(ipft) < 0._r8) THEN
+ manunitro_p(ipft) = 0._r8
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! read fertilizer
+ DO cft = 1, 64
+ IF (p_is_active) THEN
+ CALL ncio_read_block_time (file_fert, 'fertilizer', grid_fert, cft, f_xy_fert)
+ ENDIF
+
+ CALL mg2pft_fert%grid2pset (f_xy_fert, fertilizer_tmp)
+
+ IF (p_is_compute) THEN
+ DO ipft = 1, numpft
+ IF (landpft%settyp(ipft) .eq. cft+14) THEN
+ fertnitro_p(ipft) = fertilizer_tmp(ipft)
+ IF (fertnitro_p(ipft) < 0._r8) THEN
+ fertnitro_p(ipft) = 0._r8
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+ IF (allocated (fertilizer_tmp)) deallocate(fertilizer_tmp)
+ IF (allocated (manure_tmp)) deallocate(manure_tmp)
+ ENDIF
+
+#ifdef RangeCheck
+ CALL check_vector_data ('fert nitro value ', fertnitro_p)
+#endif
+
+ ! (4) Read in irrigation method
+ !file_irrig = trim(DEF_dir_runtime) // '/crop/surfdata_irrigation_method.nc'
+ file_irrig = trim(DEF_dir_runtime) // '/crop/surfdata_irrigation_method_96x144.nc'
+
+ CALL ncio_read_bcast_serial (file_irrig, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_irrig, 'lon', lon)
+
+ CALL grid_irrig%define_by_center (lat, lon)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_irrig, f_xy_irrig)
+ ENDIF
+
+ CALL mg2pft_irrig%build_arealweighted (grid_irrig, landpft)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) irrig_method_p(:) = -99999999
+ ENDIF
+
+ DO cft = 1, N_CFT
+ IF (p_is_active) THEN
+ CALL ncio_read_block_time (file_irrig, 'irrigation_method', grid_irrig, cft, f_xy_irrig)
+ ENDIF
+
+ CALL mg2pft_irrig%grid2pset_dominant (f_xy_irrig, irrig_method_tmp)
+
+ IF (p_is_compute) THEN
+ DO ipft = 1, numpft
+
+ IF(landpft%settyp(ipft) .eq. cft + 14)THEN
+ irrig_method_p(ipft) = irrig_method_tmp(ipft)
+ IF(irrig_method_p(ipft) < 0) THEN
+ irrig_method_p(ipft) = -99999999
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+#ifdef RangeCheck
+ CALL check_vector_data ('irrigation method ', irrig_method_p)
+#endif
+
+ IF (allocated (pdrice2_tmp )) deallocate(pdrice2_tmp )
+ IF (allocated (plantdate_tmp)) deallocate(plantdate_tmp)
+ IF (allocated (fertnitro_tmp)) deallocate(fertnitro_tmp)
+ IF (allocated (irrig_method_tmp)) deallocate(irrig_method_tmp)
+
+ IF (DEF_IRRIGATION_ALLOCATION == 3) THEN
+ ! (5) Read in irrigation allocated to groundwater
+ file_irrigalloc = trim(DEF_dir_runtime) // '/crop/surfdata_irrigation_allocation.nc'
+
+ CALL ncio_read_bcast_serial (file_irrigalloc, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_irrigalloc, 'lon', lon)
+
+ CALL grid_irrigalloc%define_by_center (lat, lon)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_irrigalloc, f_xy_irrigalloc)
+ ENDIF
+
+ call mg2p_irrigalloc%build_arealweighted (grid_irrigalloc, landpatch)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ IF (p_is_compute) THEN
+ irrig_gw_alloc(:) = 0._r8
+ ENDIF
+
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_irrigalloc, 'irrig_gw_alloc', grid_irrigalloc, f_xy_irrigalloc)
+ ENDIF
+
+ call mg2p_irrigalloc%grid2pset (f_xy_irrigalloc, irrig_gw_alloc)
+
+#ifdef RangeCheck
+ CALL check_vector_data ('irrigation goundwater allocation ', irrig_gw_alloc)
+#endif
+
+ ! (6) Read in irrigation allocated to surfacewater
+ IF (p_is_compute) THEN
+ irrig_sw_alloc(:) = 0._r8
+ ENDIF
+
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_irrigalloc, 'irrig_sw_alloc', grid_irrigalloc, f_xy_irrigalloc)
+ ENDIF
+
+ call mg2p_irrigalloc%grid2pset (f_xy_irrigalloc, irrig_sw_alloc)
+
+#ifdef RangeCheck
+ CALL check_vector_data ('irrigation surfacewater allocation ', irrig_sw_alloc)
+#endif
+ ENDIF
+
+ END SUBROUTINE CROP_readin
+
+END MODULE MOD_CropReadin
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Eroot.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Eroot.F90
new file mode 100644
index 0000000000..333547bc1f
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Eroot.F90
@@ -0,0 +1,156 @@
+#include
+
+MODULE MOD_Eroot
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: eroot
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE eroot (nl_soil,trsmx0,porsl, &
+#ifdef Campbell_SOIL_MODEL
+ bsw, &
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm, &
+#endif
+ psi0,rootfr, dz_soisno,t_soisno,wliq_soisno,rootr,etrc,rstfac)
+
+!=======================================================================
+! !DESCRIPTION:
+! effective root fraction and maximum possible transpiration rate
+!
+! Original author: Yongjiu Dai, 08/30/2002
+!
+! !REVISIONS:
+! 09/2021, Shupeng Zhang and Xingjie Lu: add vanGenuchten scheme to
+! calculate soil water potential.
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denh2o
+ USE MOD_Namelist, only: DEF_RSTFAC
+ USE MOD_Const_Physical, only: tfrz
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ USE MOD_Hydro_SoilFunction, only: soil_psi_from_vliq, soil_vliq_from_psi
+#endif
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: nl_soil ! upper bound of array
+
+ real(r8), intent(in) :: trsmx0 ! max transpiration for moist soil+100% veg.[mm/s]
+ real(r8), intent(in) :: porsl(1:nl_soil) ! soil porosity [-]
+#ifdef Campbell_SOIL_MODEL
+ real(r8), intent(in) :: bsw(1:nl_soil) ! Clapp-Hornberger "B"
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), intent(in) :: theta_r (1:nl_soil)
+ real(r8), intent(in) :: alpha_vgm(1:nl_soil)
+ real(r8), intent(in) :: n_vgm (1:nl_soil)
+ real(r8), intent(in) :: L_vgm (1:nl_soil)
+ real(r8), intent(in) :: sc_vgm (1:nl_soil)
+ real(r8), intent(in) :: fc_vgm (1:nl_soil)
+#endif
+ real(r8), intent(in) :: psi0(1:nl_soil) ! saturated soil suction (mm) (NEGATIVE)
+ real(r8), intent(in) :: rootfr(1:nl_soil) ! fraction of roots in a layer,
+ real(r8), intent(in) :: dz_soisno(1:nl_soil) ! layer thickness (m)
+ real(r8), intent(in) :: t_soisno(1:nl_soil) ! soil/snow skin temperature (K)
+ real(r8), intent(in) :: wliq_soisno(1:nl_soil) ! liquid water (kg/m2)
+
+ real(r8), intent(out) :: rootr(1:nl_soil) ! root resistance of a layer, all layers add to 1
+ real(r8), intent(out) :: etrc ! maximum possible transpiration rate (mm h2o/s)
+ real(r8), intent(out) :: rstfac ! factor of soil water stress for photosynthesis
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) roota ! accumulates root resistance factors
+ real(r8) rresis(1:nl_soil) ! soil water contribution to root resistance
+ real(r8) s_node ! vol_liq/porosity
+ real(r8) smpmax ! wilting point potential in mm
+ real(r8) smp_node ! matrix potential
+
+ !new method to calculate root resistance
+ real(r8) :: smpswc = -1.5e5 ! soil water potential at wilting point (mm)
+ real(r8) :: smpsfc = -3.3e3 ! soil water potential at field capacity (mm)
+ real(r8) :: liqswc, liqsfc, liqsat ! liquid water content at wilting point, field capacity, and saturation (kg/m2)
+
+ integer i ! loop counter
+
+!-----------------------------------------------------------------------
+ IF (DEF_RSTFAC == 1) THEN
+ ! transpiration potential(etrc) and root resistance factors (rstfac)
+
+ roota = 1.e-10 ! must be non-zero to begin
+ DO i = 1, nl_soil
+
+ IF(t_soisno(i)>tfrz .and. porsl(i)>=1.e-6)THEN
+ smpmax = -1.5e5
+ s_node = max(wliq_soisno(i)/(1000.*dz_soisno(i)*porsl(i)),0.001)
+ s_node = min(1., s_node)
+#ifdef Campbell_SOIL_MODEL
+ smp_node = max(smpmax, psi0(i)*s_node**(-bsw(i)))
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ smp_node = soil_psi_from_vliq ( s_node*(porsl(i)-theta_r(i)) + theta_r(i), &
+ porsl(i), theta_r(i), psi0(i), &
+ 5, (/alpha_vgm(i), n_vgm(i), L_vgm(i), sc_vgm(i), fc_vgm(i)/))
+ smp_node = max(smpmax, smp_node)
+#endif
+ rresis(i) =(1.-smp_node/smpmax)/(1.-psi0(i)/smpmax)
+ rootr(i) = rootfr(i)*rresis(i)
+ roota = roota + rootr(i)
+ ELSE
+ rootr(i) = 0.
+ ENDIF
+ ENDDO
+ ELSEIF (DEF_RSTFAC == 2) THEN
+ !new method to calculate root resistance
+ roota = 1.e-10
+ DO i = 1, nl_soil
+ IF(t_soisno(i)>tfrz .and. porsl(i)>=1.e-6)THEN
+#ifdef Campbell_SOIL_MODEL
+ liqswc = denh2o*dz_soisno(i)*porsl(i)*((smpswc/psi0(i))**(-1/bsw(i)))
+ liqsfc = denh2o*dz_soisno(i)*porsl(i)*((smpsfc/psi0(i))**(-1/bsw(i)))
+ liqsat = denh2o*dz_soisno(i)*porsl(i)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ liqswc = soil_vliq_from_psi(smpswc, porsl(i), theta_r(i), psi0(i), 5, (/alpha_vgm(i), n_vgm(i), L_vgm(i), sc_vgm(i), fc_vgm(i)/))
+ liqswc = denh2o*dz_soisno(i)*liqswc
+ liqsfc = soil_vliq_from_psi(smpsfc, porsl(i), theta_r(i), psi0(i), 5, (/alpha_vgm(i), n_vgm(i), L_vgm(i), sc_vgm(i), fc_vgm(i)/))
+ liqsfc = denh2o*dz_soisno(i)*liqsfc
+ liqsat = denh2o*dz_soisno(i)*porsl(i)
+#endif
+ rresis(i) = (wliq_soisno(i)-liqswc)/(liqsfc-liqswc)
+ rresis(i) = min(1.0, rresis(i))
+ rresis(i) = max(0.0, rresis(i))
+ rootr(i) = rootfr(i)*rresis(i)
+ roota = roota + rootr(i)
+ ELSE
+ rootr(i) = 0.
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! normalize root resistances to get layer contribution to ET
+ rootr(:) = rootr(:)/roota
+
+ ! determine maximum possible transpiration rate
+ etrc = trsmx0*roota
+ rstfac = roota
+
+ END SUBROUTINE eroot
+
+END MODULE MOD_Eroot
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_FireData.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_FireData.F90
new file mode 100644
index 0000000000..153f26922b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_FireData.F90
@@ -0,0 +1,139 @@
+#include
+
+#ifdef BGC
+MODULE MOD_FireData
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This module read in fire data.
+!
+! Original:
+! 2023, Lu Xingjie and Zhang Shupeng: prepare the original version of
+! the fire data module.
+!-----------------------------------------------------------------------
+
+ USE MOD_Grid
+ USE MOD_SpatialMapping
+ USE MOD_Vars_TimeInvariants, only: abm_lf, gdp_lf, peatf_lf
+ USE MOD_Vars_TimeVariables, only: hdm_lf
+ IMPLICIT NONE
+
+ character(len=256) :: file_fire
+
+ type(grid_type) :: grid_fire
+ type(spatial_mapping_type) :: mg2p_fire
+
+CONTAINS
+
+ SUBROUTINE init_fire_data (YY)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! open fire netcdf file from DEF_dir_runtime, read latitude and
+! longitude info. Initialize fire data read in.
+!-----------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: YY
+
+ ! Local Variables
+ real(r8), allocatable :: lat(:), lon(:)
+ type(block_data_real8_2d) :: f_xy_fire
+
+ file_fire = trim(DEF_dir_runtime) // '/fire/abm_colm_double_fillcoast.nc'
+
+ CALL ncio_read_bcast_serial (file_fire, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_fire, 'lon', lon)
+
+ CALL grid_fire%define_by_center (lat, lon)
+
+ CALL mg2p_fire%build_arealweighted (grid_fire, landpatch)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_fire, f_xy_fire)
+ ENDIF
+
+ file_fire = trim(DEF_dir_runtime) // '/fire/abm_colm_double_fillcoast.nc'
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_fire, 'abm', grid_fire, f_xy_fire)
+ ENDIF
+ CALL mg2p_fire%grid2pset (f_xy_fire, abm_lf)
+#ifdef RangeCheck
+ CALL check_vector_data ('abm', abm_lf)
+#endif
+
+ file_fire = trim(DEF_dir_runtime) // '/fire/peatf_colm_360x720_c100428.nc'
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_fire, 'peatf', grid_fire, f_xy_fire)
+ ENDIF
+ CALL mg2p_fire%grid2pset (f_xy_fire, peatf_lf)
+#ifdef RangeCheck
+ CALL check_vector_data ('peatf', peatf_lf)
+#endif
+
+ file_fire = trim(DEF_dir_runtime) // '/fire/gdp_colm_360x720_c100428.nc'
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_fire, 'gdp', grid_fire, f_xy_fire)
+ ENDIF
+ CALL mg2p_fire%grid2pset (f_xy_fire, gdp_lf)
+#ifdef RangeCheck
+ CALL check_vector_data ('gdp', gdp_lf)
+#endif
+
+ CALL update_hdm_data (YY)
+
+ END SUBROUTINE init_fire_data
+
+ SUBROUTINE update_hdm_data (YY)
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Read in the Fire data from CLM5 dataset (month when crop fire peak
+! (abm), GDP, peatland fraction (peatf), and population density
+!
+! Original: Xingjie Lu and Shupeng Zhang, 2022
+!-----------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_DataType
+ USE MOD_Namelist
+ USE MOD_NetCDFBlock
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: YY
+
+ ! Local Variables
+ type(block_data_real8_2d) :: f_xy_fire
+ integer :: itime
+
+ itime = max(1850,min(YY,2016)) - 1849
+
+ file_fire = trim(DEF_dir_runtime) &
+ // '/fire/colmforc.Li_2017_HYDEv3.2_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2016_c180202.nc'
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_fire, f_xy_fire)
+ CALL ncio_read_block_time (file_fire, 'hdm', grid_fire, itime, f_xy_fire)
+ ENDIF
+
+ CALL mg2p_fire%grid2pset (f_xy_fire, hdm_lf)
+
+#ifdef RangeCheck
+ CALL check_vector_data ('hdm', hdm_lf)
+#endif
+
+ END SUBROUTINE update_hdm_data
+
+END MODULE MOD_FireData
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Forcing.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Forcing.F90
new file mode 100644
index 0000000000..feff68e280
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Forcing.F90
@@ -0,0 +1,1810 @@
+#include
+
+MODULE MOD_Forcing
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! read in the atmospheric forcing using user defined interpolation method or
+! downscaling forcing
+!
+! !REVISIONS:
+! Yongjiu Dai and Hua Yuan, 04/2014: initial code from CoLM2014 (metdata.F90,
+! GETMET.F90 and rd_forcing.F90
+!
+! Shupeng Zhang, 05/2023: 1) porting codes to MPI parallel version
+! 2) codes for dealing with missing forcing value
+! 3) interface for downscaling
+!
+! !TODO...(need complement)
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE MOD_SpatialMapping
+ USE MOD_UserSpecifiedForcing
+ USE MOD_TimeManager
+ USE MOD_SPMD_Task
+ USE MOD_MonthlyinSituCO2MaunaLoa
+ USE MOD_Vars_Global, only: pi
+ USE MOD_OrbCoszen
+ USE MOD_UserDefFun
+
+ IMPLICIT NONE
+
+ type (grid_type), PUBLIC :: gforc
+
+ type (spatial_mapping_type) :: mg2p_forc ! area weighted mapping from forcing to model unit
+
+ real(r8) :: forc_missing_value
+ logical, allocatable :: forcmask_pch (:)
+
+ ! for Forcing_Downscaling
+ type(block_data_real8_2d) :: topo_grid, maxelv_grid
+
+ type(pointer_real8_1d), allocatable :: forc_topo_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_maxelv_grid (:)
+
+ type(pointer_real8_1d), allocatable :: forc_t_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_th_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_q_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_pbot_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_rho_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_prc_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_prl_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_lwrad_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_swrad_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_hgt_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_us_grid (:)
+ type(pointer_real8_1d), allocatable :: forc_vs_grid (:)
+
+ type(pointer_real8_1d), allocatable :: forc_t_part (:)
+ type(pointer_real8_1d), allocatable :: forc_th_part (:)
+ type(pointer_real8_1d), allocatable :: forc_q_part (:)
+ type(pointer_real8_1d), allocatable :: forc_pbot_part (:)
+ type(pointer_real8_1d), allocatable :: forc_rhoair_part (:)
+ type(pointer_real8_1d), allocatable :: forc_prc_part (:)
+ type(pointer_real8_1d), allocatable :: forc_prl_part (:)
+ type(pointer_real8_1d), allocatable :: forc_frl_part (:)
+ type(pointer_real8_1d), allocatable :: forc_swrad_part (:)
+ type(pointer_real8_1d), allocatable :: forc_us_part (:)
+ type(pointer_real8_1d), allocatable :: forc_vs_part (:)
+
+ logical, allocatable :: glacierss (:)
+
+ ! local variables
+ integer :: deltim_int ! model time step length
+ ! real(r8) :: deltim_real ! model time step length
+
+ ! for SinglePoint
+ type(timestamp), allocatable :: forctime (:)
+ integer, allocatable :: iforctime(:)
+
+ logical :: forcing_read_ahead
+ real(r8), allocatable :: forc_disk(:,:)
+
+ type(timestamp), allocatable :: tstamp_LB(:) ! time stamp of low boundary data
+ type(timestamp), allocatable :: tstamp_UB(:) ! time stamp of up boundary data
+
+ type(block_data_real8_2d) :: avgcos ! time-average of cos(zenith)
+ type(block_data_real8_2d) :: metdata ! forcing data
+#ifdef URBAN_MODEL
+ type(block_data_real8_2d) :: rainf
+ type(block_data_real8_2d) :: snowf
+#endif
+
+ type(block_data_real8_2d), allocatable :: forcn (:) ! forcing data
+ type(block_data_real8_2d), allocatable :: forcn_LB (:) ! forcing data at lower boundary
+ type(block_data_real8_2d), allocatable :: forcn_UB (:) ! forcing data at upper boundary
+
+ PUBLIC :: forcing_init
+ PUBLIC :: read_forcing
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+ SUBROUTINE forcing_init (dir_forcing, deltatime, ststamp, lc_year, etstamp, lulcc_call)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_LandPatch
+#ifdef CROP
+ USE MOD_LandCrop
+#endif
+ USE MOD_UserSpecifiedForcing
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFVector
+ USE MOD_NetCDFBlock
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_1DForcing
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: dir_forcing
+ real(r8), intent(in) :: deltatime ! model time step
+ type(timestamp), intent(in) :: ststamp
+ integer, intent(in) :: lc_year ! which year of land cover data used
+ type(timestamp), intent(in), optional :: etstamp
+ logical, intent(in), optional :: lulcc_call ! whether it is a lulcc CALL
+
+ ! Local variables
+ integer :: idate(3)
+ type(timestamp) :: tstamp
+ character(len=256) :: filename, lndname, cyear
+ integer :: ivar, year, month, day, time_i
+ integer :: ielm, istt, iend
+ type(block_data_real8_2d) :: areagrid
+
+ integer :: iblkme, xblk, yblk, xloc, yloc
+
+ CALL init_user_specified_forcing
+
+ ! CO2 data initialization
+ CALL init_monthly_co2_mlo
+
+ ! get value of fmetdat and deltim
+ deltim_int = int(deltatime)
+ ! deltim_real = deltatime
+
+ ! set initial values
+ IF (allocated(tstamp_LB)) deallocate(tstamp_LB)
+ IF (allocated(tstamp_UB)) deallocate(tstamp_UB)
+ allocate (tstamp_LB(NVAR))
+ allocate (tstamp_UB(NVAR))
+ tstamp_LB(:) = timestamp(-1, -1, -1)
+ tstamp_UB(:) = timestamp(-1, -1, -1)
+
+ idate = (/ststamp%year, ststamp%day, ststamp%sec/)
+ CALL adj2begin (idate)
+
+ CALL metread_latlon (dir_forcing, idate)
+
+ IF (p_is_active) THEN
+
+ IF (allocated(forcn )) deallocate(forcn )
+ IF (allocated(forcn_LB)) deallocate(forcn_LB)
+ IF (allocated(forcn_UB)) deallocate(forcn_UB)
+ allocate (forcn (NVAR))
+ allocate (forcn_LB (NVAR))
+ allocate (forcn_UB (NVAR))
+
+ DO ivar = 1, NVAR
+ CALL allocate_block_data (gforc, forcn (ivar))
+ CALL allocate_block_data (gforc, forcn_LB(ivar))
+ CALL allocate_block_data (gforc, forcn_UB(ivar))
+ ENDDO
+
+ ! allocate memory for forcing data
+ CALL allocate_block_data (gforc, metdata) ! forcing data
+ CALL allocate_block_data (gforc, avgcos ) ! time-average of cos(zenith)
+#if (defined URBAN_MODEL && defined SinglePoint)
+ CALL allocate_block_data (gforc, rainf)
+ CALL allocate_block_data (gforc, snowf)
+#endif
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate (forcmask_pch(numpatch)); forcmask_pch(:) = .true.
+ ENDIF
+ ENDIF
+
+ IF (DEF_forcing%has_missing_value) THEN
+
+ tstamp = idate
+ CALL setstampLB(tstamp, 1, year, month, day, time_i)
+ filename = trim(dir_forcing)//trim(metfilename(year, month, day, 1))
+ tstamp_LB(1) = timestamp(-1, -1, -1)
+
+ IF (p_is_root) THEN
+ CALL ncio_get_attr (filename, vname(1), trim(DEF_forcing%missing_value_name), &
+ forc_missing_value)
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_bcast (forc_missing_value, 1, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#endif
+
+ CALL ncio_read_block_time (filename, vname(1), gforc, time_i, metdata)
+
+ ENDIF
+
+ IF (trim(DEF_Forcing_Interp_Method) == 'arealweight') THEN
+ IF (present(lulcc_call)) CALL mg2p_forc%forc_free_mem
+ CALL mg2p_forc%build_arealweighted (gforc, landpatch)
+ ELSEIF (trim(DEF_Forcing_Interp_Method) == 'bilinear') THEN
+ IF (present(lulcc_call)) CALL mg2p_forc%forc_free_mem
+ CALL mg2p_forc%build_bilinear (gforc, landpatch)
+ ENDIF
+
+ IF (DEF_forcing%has_missing_value) THEN
+ CALL mg2p_forc%set_missing_value (metdata, forc_missing_value, forcmask_pch)
+ ENDIF
+
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ forc_topo = elvmean
+ WHERE(forc_topo == spval) forc_topo = 0.
+ ENDIF
+
+ IF ((DEF_USE_Forcing_Downscaling).or.(DEF_USE_Forcing_Downscaling_Simple)) THEN
+
+ IF (p_is_active) CALL allocate_block_data (gforc, topo_grid)
+ CALL mg2p_forc%pset2grid (forc_topo, topo_grid, msk = patchmask)
+
+ IF (p_is_active) CALL allocate_block_data (gforc, areagrid)
+ CALL mg2p_forc%get_sumarea(areagrid, patchmask)
+ CALL block_data_division (topo_grid, areagrid)
+
+ IF (p_is_active) CALL allocate_block_data (gforc, maxelv_grid)
+ CALL mg2p_forc%pset2grid_max (forc_topo, maxelv_grid, msk = patchmask)
+
+
+ CALL mg2p_forc%allocate_part (forc_topo_grid )
+ CALL mg2p_forc%allocate_part (forc_maxelv_grid)
+
+ CALL mg2p_forc%allocate_part (forc_t_grid )
+ CALL mg2p_forc%allocate_part (forc_th_grid )
+ CALL mg2p_forc%allocate_part (forc_q_grid )
+ CALL mg2p_forc%allocate_part (forc_pbot_grid )
+ CALL mg2p_forc%allocate_part (forc_rho_grid )
+ CALL mg2p_forc%allocate_part (forc_prc_grid )
+ CALL mg2p_forc%allocate_part (forc_prl_grid )
+ CALL mg2p_forc%allocate_part (forc_lwrad_grid )
+ CALL mg2p_forc%allocate_part (forc_swrad_grid )
+ CALL mg2p_forc%allocate_part (forc_hgt_grid )
+ CALL mg2p_forc%allocate_part (forc_us_grid )
+ CALL mg2p_forc%allocate_part (forc_vs_grid )
+
+ CALL mg2p_forc%allocate_part (forc_t_part )
+ CALL mg2p_forc%allocate_part (forc_th_part )
+ CALL mg2p_forc%allocate_part (forc_q_part )
+ CALL mg2p_forc%allocate_part (forc_pbot_part )
+ CALL mg2p_forc%allocate_part (forc_rhoair_part)
+ CALL mg2p_forc%allocate_part (forc_prc_part )
+ CALL mg2p_forc%allocate_part (forc_prl_part )
+ CALL mg2p_forc%allocate_part (forc_frl_part )
+ CALL mg2p_forc%allocate_part (forc_swrad_part )
+ CALL mg2p_forc%allocate_part (forc_us_part )
+ CALL mg2p_forc%allocate_part (forc_vs_part )
+
+ CALL mg2p_forc%grid2part (topo_grid, forc_topo_grid )
+ CALL mg2p_forc%grid2part (maxelv_grid, forc_maxelv_grid)
+
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ allocate (glacierss(numpatch))
+ glacierss(:) = patchtype(:) == 3
+ ENDIF
+
+ ENDIF
+
+ forcing_read_ahead = .false.
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+ IF (USE_SITE_ForcingReadAhead .and. present(etstamp)) THEN
+ forcing_read_ahead = .true.
+ CALL metread_time (dir_forcing, ststamp, etstamp, deltatime)
+ ELSE
+ CALL metread_time (dir_forcing)
+ ENDIF
+ allocate (iforctime(NVAR))
+ ENDIF
+
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+
+ filename = trim(dir_forcing)//trim(fprefix(1))
+
+#ifndef URBAN_MODEL
+ IF (ncio_var_exist(filename,'reference_height_v')) THEN
+ CALL ncio_read_serial (filename, 'reference_height_v', Height_V)
+ ENDIF
+
+ IF (ncio_var_exist(filename,'reference_height_t')) THEN
+ CALL ncio_read_serial (filename, 'reference_height_t', Height_T)
+ ENDIF
+
+ IF (ncio_var_exist(filename,'reference_height_q')) THEN
+ CALL ncio_read_serial (filename, 'reference_height_q', Height_Q)
+ ENDIF
+#else
+ IF (ncio_var_exist(filename,'measurement_height_above_ground')) THEN
+ CALL ncio_read_serial (filename, 'measurement_height_above_ground', Height_V)
+ CALL ncio_read_serial (filename, 'measurement_height_above_ground', Height_T)
+ CALL ncio_read_serial (filename, 'measurement_height_above_ground', Height_Q)
+ ENDIF
+#endif
+
+ ENDIF
+
+ END SUBROUTINE forcing_init
+
+ ! ---- forcing finalize ----
+ SUBROUTINE forcing_final ()
+
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+ IF (allocated(forcmask_pch)) deallocate(forcmask_pch)
+ IF (allocated(glacierss )) deallocate(glacierss )
+ IF (allocated(forctime )) deallocate(forctime )
+ IF (allocated(iforctime )) deallocate(iforctime )
+ IF (allocated(forc_disk )) deallocate(forc_disk )
+ IF (allocated(tstamp_LB )) deallocate(tstamp_LB )
+ IF (allocated(tstamp_UB )) deallocate(tstamp_UB )
+
+ IF ((DEF_USE_Forcing_Downscaling).or.(DEF_USE_Forcing_Downscaling_Simple)) THEN
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ CALL mg2p_forc%deallocate_part (forc_topo_grid )
+ CALL mg2p_forc%deallocate_part (forc_maxelv_grid)
+
+ CALL mg2p_forc%deallocate_part (forc_t_grid )
+ CALL mg2p_forc%deallocate_part (forc_th_grid )
+ CALL mg2p_forc%deallocate_part (forc_q_grid )
+ CALL mg2p_forc%deallocate_part (forc_pbot_grid )
+ CALL mg2p_forc%deallocate_part (forc_rho_grid )
+ CALL mg2p_forc%deallocate_part (forc_prc_grid )
+ CALL mg2p_forc%deallocate_part (forc_prl_grid )
+ CALL mg2p_forc%deallocate_part (forc_lwrad_grid )
+ CALL mg2p_forc%deallocate_part (forc_swrad_grid )
+ CALL mg2p_forc%deallocate_part (forc_hgt_grid )
+ CALL mg2p_forc%deallocate_part (forc_us_grid )
+ CALL mg2p_forc%deallocate_part (forc_vs_grid )
+
+ CALL mg2p_forc%deallocate_part (forc_t_part )
+ CALL mg2p_forc%deallocate_part (forc_th_part )
+ CALL mg2p_forc%deallocate_part (forc_q_part )
+ CALL mg2p_forc%deallocate_part (forc_pbot_part )
+ CALL mg2p_forc%deallocate_part (forc_rhoair_part)
+ CALL mg2p_forc%deallocate_part (forc_prc_part )
+ CALL mg2p_forc%deallocate_part (forc_prl_part )
+ CALL mg2p_forc%deallocate_part (forc_frl_part )
+ CALL mg2p_forc%deallocate_part (forc_swrad_part )
+ CALL mg2p_forc%deallocate_part (forc_us_part )
+ CALL mg2p_forc%deallocate_part (forc_vs_part )
+
+ ENDIF
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE forcing_final
+
+ ! ------------
+ SUBROUTINE forcing_reset ()
+
+ IMPLICIT NONE
+
+ tstamp_LB(:) = timestamp(-1, -1, -1)
+ tstamp_UB(:) = timestamp(-1, -1, -1)
+
+ END SUBROUTINE forcing_reset
+
+
+!-----------------------------------------------------------------------
+ SUBROUTINE read_forcing (idate, dir_forcing, is_spinup)
+ USE MOD_OrbCosazi
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_Const_Physical, only: rgas, grav
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_TimeVariables, only: alb
+ USE MOD_Vars_1DForcing
+ USE MOD_Vars_2DForcing
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_LandPatch
+ USE MOD_RangeCheck
+ USE MOD_UserSpecifiedForcing
+ USE MOD_ForcingDownscaling, only: rair, cpair, downscale_forcings, downscale_wind, downscale_wind_simple
+ USE MOD_NetCDFVector
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ character(len=*), intent(in) :: dir_forcing
+ logical, intent(in) :: is_spinup
+
+ ! local variables:
+ integer :: ivar, istt, iend, id(3)
+ integer :: iblkme, ib, jb, i, j, ilon, ilat, np, ipart, ne
+ real(r8) :: calday ! Julian cal day (1.xx to 365.xx)
+ real(r8) :: sunang, cloud, difrat, vnrat
+ real(r8) :: a, hsolar, ratio_rvrf
+ type(block_data_real8_2d) :: forc_xy_solarin
+ integer :: ii
+ character(10) :: cyear = "2005"
+ character(256):: lndname
+
+ type(timestamp) :: mtstamp
+ integer :: dtLB, dtUB
+ real(r8) :: cosz, coszen(numpatch), cosa, cosazi(numpatch), balb
+ integer :: year, month, mday
+ logical :: has_u,has_v
+ real solar, frl, prcp, tm, us, vs, pres, qm
+ real(r8) :: pco2m
+ real(r8), dimension(12, numpatch) :: spaceship !NOTE: 12 is the dimension size of spaceship
+ integer target_server, ierr
+
+ IF (p_is_active) THEN
+ !------------------------------------------------------------
+ ! READ in THE ATMOSPHERIC FORCING
+ ! read lower and upper boundary forcing data
+ CALL metreadLBUB(idate, dir_forcing, is_spinup)
+ ! set model time stamp
+ id(:) = idate(:)
+ !CALL adj2end(id)
+ mtstamp = id
+ has_u = .true.
+ has_v = .true.
+ ! loop for variables
+ DO ivar = 1, NVAR
+ IF (ivar == 5 .and. trim(vname(ivar)) == 'NULL') has_u = .false.
+ IF (ivar == 6 .and. trim(vname(ivar)) == 'NULL') has_v = .false.
+ IF (trim(vname(ivar)) == 'NULL') CYCLE ! no data, CYCLE
+ IF (trim(tintalgo(ivar)) == 'NULL') CYCLE
+
+ ! to make sure the forcing data calculated is in the range of time
+ ! interval [LB, UB]
+ IF ( (mtstamp < tstamp_LB(ivar)) .or. (tstamp_UB(ivar) < mtstamp) ) THEN
+ write(6, *) "the data required is out of range! STOP!"; CALL CoLM_stop()
+ ENDIF
+
+ ! calculate distance to lower/upper boundary
+ dtLB = mtstamp - tstamp_LB(ivar)
+ dtUB = tstamp_UB(ivar) - mtstamp
+
+ ! linear method, for T, Pres, Q, W, LW
+ IF (tintalgo(ivar) == 'linear') THEN
+ IF ( (dtLB+dtUB) > 0 ) THEN
+ CALL block_data_linear_interp ( &
+ forcn_LB(ivar), real(dtUB,r8)/real(dtLB+dtUB,r8), &
+ forcn_UB(ivar), real(dtLB,r8)/real(dtLB+dtUB,r8), &
+ forcn(ivar))
+ ELSE
+ CALL block_data_copy (forcn_LB(ivar), forcn(ivar))
+ ENDIF
+ ENDIF
+
+ ! for precipitation, two algorithms available
+ ! nearest method, for precipitation
+ IF (tintalgo(ivar) == 'nearest') THEN
+ IF (dtLB <= dtUB) THEN
+ CALL block_data_copy (forcn_LB(ivar), forcn(ivar))
+ ELSE
+ CALL block_data_copy (forcn_UB(ivar), forcn(ivar))
+ ENDIF
+ ENDIF
+
+ ! set all the same value, for precipitation
+ IF (tintalgo(ivar) == 'uniform') THEN
+ IF (trim(timelog(ivar)) == 'forward') THEN
+ CALL block_data_copy (forcn_LB(ivar), forcn(ivar))
+ ELSE
+ CALL block_data_copy (forcn_UB(ivar), forcn(ivar))
+ ENDIF
+ ENDIF
+
+ ! coszen method, for SW
+ IF (tintalgo(ivar) == 'coszen') THEN
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+
+ DO j = 1, gforc%ycnt(jb)
+ DO i = 1, gforc%xcnt(ib)
+
+ ilat = gforc%ydsp(jb) + j
+ ilon = gforc%xdsp(ib) + i
+ IF (ilon > gforc%nlon) ilon = ilon - gforc%nlon
+
+ calday = calendarday(mtstamp)
+ cosz = orb_coszen(calday, gforc%rlon(ilon), gforc%rlat(ilat))
+ cosz = max(0.001, cosz)
+ ! 10/24/2024, yuan: deal with time log with backward or forward
+ IF (trim(timelog(ivar)) == 'forward') THEN
+ forcn(ivar)%blk(ib,jb)%val(i,j) = &
+ cosz / avgcos%blk(ib,jb)%val(i,j) * forcn_LB(ivar)%blk(ib,jb)%val(i,j)
+ ELSE
+ forcn(ivar)%blk(ib,jb)%val(i,j) = &
+ cosz / avgcos%blk(ib,jb)%val(i,j) * forcn_UB(ivar)%blk(ib,jb)%val(i,j)
+ ENDIF
+
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDIF
+
+ ENDDO
+
+ ! preprocess for forcing data, only for QIAN data right now?
+ CALL metpreprocess (gforc, forcn, &
+ DEF_forcing%has_missing_value, forcn_UB(1), forc_missing_value)
+
+ CALL allocate_block_data (gforc, forc_xy_solarin)
+
+ CALL block_data_copy (forcn(1), forc_xy_t )
+ CALL block_data_copy (forcn(2), forc_xy_q )
+ CALL block_data_copy (forcn(3), forc_xy_psrf )
+ CALL block_data_copy (forcn(3), forc_xy_pbot )
+ CALL block_data_copy (forcn(4), forc_xy_prl, sca = 2/3._r8)
+ CALL block_data_copy (forcn(4), forc_xy_prc, sca = 1/3._r8)
+ CALL block_data_copy (forcn(7), forc_xy_solarin)
+ CALL block_data_copy (forcn(8), forc_xy_frl )
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL block_data_copy (forcn(9), forc_xy_hpbl )
+ ENDIF
+
+ IF (has_u .and. has_v) THEN
+ CALL block_data_copy (forcn(5), forc_xy_us )
+ CALL block_data_copy (forcn(6), forc_xy_vs )
+ ELSEIF (has_u) THEN
+ CALL block_data_copy (forcn(5), forc_xy_us , sca = 1/sqrt(2.0_r8))
+ CALL block_data_copy (forcn(5), forc_xy_vs , sca = 1/sqrt(2.0_r8))
+ ELSEIF (has_v) THEN
+ CALL block_data_copy (forcn(6), forc_xy_us , sca = 1/sqrt(2.0_r8))
+ CALL block_data_copy (forcn(6), forc_xy_vs , sca = 1/sqrt(2.0_r8))
+ ELSE
+ IF (.not.trim(DEF_forcing%dataset) == 'CPL7') THEN
+ write(6, *) "At least one of the wind components must be provided! STOP!";
+ CALL CoLM_stop()
+ ENDIF
+ ENDIF
+
+ CALL flush_block_data (forc_xy_hgt_u, real(HEIGHT_V,r8))
+ CALL flush_block_data (forc_xy_hgt_t, real(HEIGHT_T,r8))
+ CALL flush_block_data (forc_xy_hgt_q, real(HEIGHT_Q,r8))
+
+ IF (solarin_all_band) THEN
+
+ IF (trim(DEF_forcing%dataset) == 'QIAN') THEN
+ !---------------------------------------------------------------
+ ! 04/2014, yuan: NOTE! codes from CLM4.5-CESM1.2.0
+ ! relationship between incoming NIR or VIS radiation and ratio of
+ ! direct to diffuse radiation calculated based on one year's worth of
+ ! hourly CAM output from CAM version cam3_5_55
+ !---------------------------------------------------------------
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+
+ DO j = 1, gforc%ycnt(jb)
+ DO i = 1, gforc%xcnt(ib)
+
+ hsolar = forc_xy_solarin%blk(ib,jb)%val(i,j)*0.5_R8
+
+ ! NIR (dir, diff)
+ ratio_rvrf = min(0.99_R8,max(0.29548_R8 + 0.00504_R8*hsolar &
+ -1.4957e-05_R8*hsolar**2 + 1.4881e-08_R8*hsolar**3,0.01_R8))
+ forc_xy_soll %blk(ib,jb)%val(i,j) = ratio_rvrf*hsolar
+ forc_xy_solld%blk(ib,jb)%val(i,j) = (1._R8 - ratio_rvrf)*hsolar
+
+ ! VIS (dir, diff)
+ ratio_rvrf = min(0.99_R8,max(0.17639_R8 + 0.00380_R8*hsolar &
+ -9.0039e-06_R8*hsolar**2 + 8.1351e-09_R8*hsolar**3,0.01_R8))
+ forc_xy_sols %blk(ib,jb)%val(i,j) = ratio_rvrf*hsolar
+ forc_xy_solsd%blk(ib,jb)%val(i,j) = (1._R8 - ratio_rvrf)*hsolar
+
+ ENDDO
+ ENDDO
+ ENDDO
+
+ ELSE
+ !---------------------------------------------------------------
+ ! as the downward solar is in full band, an empirical expression
+ ! will be used to divide fractions of band and incident
+ ! (visible, near-infrad, dirct, diffuse)
+ ! Julian calday (1.xx to 365.xx)
+ !---------------------------------------------------------------
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+
+ DO j = 1, gforc%ycnt(jb)
+ DO i = 1, gforc%xcnt(ib)
+
+ IF (DEF_forcing%has_missing_value) THEN
+ IF (forcn_UB(1)%blk(ib,jb)%val(i,j) == forc_missing_value) THEN
+ CYCLE
+ ENDIF
+ ENDIF
+
+ ilat = gforc%ydsp(jb) + j
+ ilon = gforc%xdsp(ib) + i
+ IF (ilon > gforc%nlon) ilon = ilon - gforc%nlon
+
+ a = max(0., forc_xy_solarin%blk(ib,jb)%val(i,j))
+ calday = calendarday(idate)
+ sunang = orb_coszen (calday, gforc%rlon(ilon), gforc%rlat(ilat))
+
+ IF (sunang .eq. 0)THEN
+ cloud = 0.
+ ELSE
+ cloud = (1160.*sunang-a)/(963.*sunang)
+ ENDIF
+ cloud = max(cloud,0.)
+ cloud = min(cloud,1.)
+ cloud = max(0.58,cloud)
+
+ difrat = 0.0604/(sunang-0.0223)+0.0683
+ IF(difrat.lt.0.) difrat = 0.
+ IF(difrat.gt.1.) difrat = 1.
+
+ difrat = difrat+(1.0-difrat)*cloud
+ vnrat = (580.-cloud*464.)/((580.-cloud*499.)+(580.-cloud*464.))
+
+ forc_xy_sols %blk(ib,jb)%val(i,j) = a*(1.0-difrat)*vnrat
+ forc_xy_soll %blk(ib,jb)%val(i,j) = a*(1.0-difrat)*(1.0-vnrat)
+ forc_xy_solsd%blk(ib,jb)%val(i,j) = a*difrat*vnrat
+ forc_xy_solld%blk(ib,jb)%val(i,j) = a*difrat*(1.0-vnrat)
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+
+ ! [GET ATMOSPHERE CO2 CONCENTRATION DATA]
+ year = idate(1)
+ CALL julian2monthday (idate(1), idate(2), month, mday)
+ pco2m = get_monthly_co2_mlo(year, month)*1.e-6
+ CALL block_data_copy (forc_xy_pbot, forc_xy_pco2m, sca = pco2m )
+ CALL block_data_copy (forc_xy_pbot, forc_xy_po2m , sca = 0.209_r8 )
+
+ ENDIF
+
+ IF ((.not. DEF_USE_Forcing_Downscaling).and.(.not. DEF_USE_Forcing_Downscaling_Simple)) THEN
+
+ ! Mapping the 2d atmospheric fields [lon_points]x[lat_points]
+ ! -> the 1d vector of subgrid points [numpatch]
+ CALL mg2p_forc%grid2pset (forc_xy_pco2m, forc_pco2m)
+ CALL mg2p_forc%grid2pset (forc_xy_po2m , forc_po2m )
+ CALL mg2p_forc%grid2pset (forc_xy_us , forc_us )
+ CALL mg2p_forc%grid2pset (forc_xy_vs , forc_vs )
+
+ CALL mg2p_forc%grid2pset (forc_xy_psrf , forc_psrf )
+
+ CALL mg2p_forc%grid2pset (forc_xy_sols , forc_sols )
+ CALL mg2p_forc%grid2pset (forc_xy_soll , forc_soll )
+ CALL mg2p_forc%grid2pset (forc_xy_solsd, forc_solsd)
+ CALL mg2p_forc%grid2pset (forc_xy_solld, forc_solld)
+
+ CALL mg2p_forc%grid2pset (forc_xy_hgt_t, forc_hgt_t)
+ CALL mg2p_forc%grid2pset (forc_xy_hgt_u, forc_hgt_u)
+ CALL mg2p_forc%grid2pset (forc_xy_hgt_q, forc_hgt_q)
+
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL mg2p_forc%grid2pset (forc_xy_hpbl, forc_hpbl)
+ ENDIF
+
+ CALL mg2p_forc%grid2pset (forc_xy_t , forc_t )
+ CALL mg2p_forc%grid2pset (forc_xy_q , forc_q )
+ CALL mg2p_forc%grid2pset (forc_xy_prc , forc_prc )
+ CALL mg2p_forc%grid2pset (forc_xy_prl , forc_prl )
+ CALL mg2p_forc%grid2pset (forc_xy_pbot , forc_pbot )
+ CALL mg2p_forc%grid2pset (forc_xy_frl , forc_frl )
+
+ IF (p_is_compute) THEN
+
+ DO np = 1, numpatch
+
+ IF (.not. forcmask_pch(np)) CYCLE
+
+ ! The standard measuring conditions for temperature are two meters above the ground
+ ! Scientists have measured the most frigid temperature ever
+ ! recorded on the continent's eastern highlands: about (180K) colder than dry ice.
+ IF(forc_t(np) < 180.) forc_t(np) = 180.
+ ! the highest air temp was found in Kuwait 326 K, Sulaibya 2012-07-31;
+ ! Pakistan, Sindh 2010-05-26; Iraq, Nasiriyah 2011-08-03
+ IF(forc_t(np) > 326.) forc_t(np) = 326.
+
+ forc_rhoair(np) = (forc_pbot(np) &
+ - 0.378*forc_q(np)*forc_pbot(np)/(0.622+0.378*forc_q(np)))&
+ / (rgas*forc_t(np))
+
+ ENDDO
+
+ ENDIF
+
+ ELSE
+ ! ------------------------------------------------------
+ ! Forcing downscaling module
+ ! ------------------------------------------------------
+ ! init forcing on patches
+ CALL mg2p_forc%grid2pset (forc_xy_pco2m, forc_pco2m)
+ CALL mg2p_forc%grid2pset (forc_xy_po2m , forc_po2m )
+ CALL mg2p_forc%grid2pset (forc_xy_us , forc_us )
+ CALL mg2p_forc%grid2pset (forc_xy_vs , forc_vs )
+ CALL mg2p_forc%grid2pset (forc_xy_psrf , forc_psrf )
+ CALL mg2p_forc%grid2pset (forc_xy_sols , forc_sols )
+ CALL mg2p_forc%grid2pset (forc_xy_soll , forc_soll )
+ CALL mg2p_forc%grid2pset (forc_xy_solsd, forc_solsd)
+ CALL mg2p_forc%grid2pset (forc_xy_solld, forc_solld)
+ CALL mg2p_forc%grid2pset (forc_xy_solarin, forc_swrad)
+ CALL mg2p_forc%grid2pset (forc_xy_hgt_t, forc_hgt_t)
+ CALL mg2p_forc%grid2pset (forc_xy_hgt_u, forc_hgt_u)
+ CALL mg2p_forc%grid2pset (forc_xy_hgt_q, forc_hgt_q)
+ CALL mg2p_forc%grid2pset (forc_xy_t , forc_t )
+ CALL mg2p_forc%grid2pset (forc_xy_pbot , forc_pbot )
+ CALL mg2p_forc%grid2pset (forc_xy_q , forc_q )
+ CALL mg2p_forc%grid2pset (forc_xy_frl , forc_frl )
+
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL mg2p_forc%grid2pset (forc_xy_hpbl, forc_hpbl)
+ ENDIF
+
+ ! Mapping the 2d atmospheric fields [lon_points]x[lat_points]
+ ! -> the 1d vector of subgrid points [numelm]
+ ! by selected mapping methods
+ CALL mg2p_forc%grid2part (forc_xy_t , forc_t_grid )
+ CALL mg2p_forc%grid2part (forc_xy_q , forc_q_grid )
+ CALL mg2p_forc%grid2part (forc_xy_prc , forc_prc_grid )
+ CALL mg2p_forc%grid2part (forc_xy_prl , forc_prl_grid )
+ CALL mg2p_forc%grid2part (forc_xy_pbot , forc_pbot_grid )
+ CALL mg2p_forc%grid2part (forc_xy_frl , forc_lwrad_grid)
+ CALL mg2p_forc%grid2part (forc_xy_hgt_t, forc_hgt_grid )
+ CALL mg2p_forc%grid2part (forc_xy_solarin, forc_swrad_grid)
+ CALL mg2p_forc%grid2part (forc_xy_us, forc_us_grid )
+ CALL mg2p_forc%grid2part (forc_xy_vs, forc_vs_grid )
+
+ calday = calendarday(idate)
+
+ IF (p_is_compute) THEN
+ DO np = 1, numpatch ! patches
+
+ ! calculate albedo of each patches
+ IF (forc_sols(np)+forc_solsd(np)+forc_soll(np)+forc_solld(np) == 0.) THEN
+ balb = 0
+ ELSE
+ balb = ( alb(1,1,np)*forc_sols (np) + alb(1,2,np)*forc_solsd(np) &
+ + alb(2,1,np)*forc_soll (np) + alb(2,2,np)*forc_solld(np) ) &
+ / (forc_sols(np)+forc_solsd(np)+forc_soll(np)+forc_solld(np))
+ ENDIF
+
+ DO ipart = 1, mg2p_forc%npart(np) ! part loop of each patch
+
+ IF (mg2p_forc%areapart(np)%val(ipart) == 0.) CYCLE
+
+ ! The standard measuring conditions for temperature are two meters above
+ ! the ground. Scientists have measured the most frigid temperature ever
+ ! recorded on the continent's eastern highlands: about (180K) colder than
+ ! dry ice.
+ IF (forc_t_grid(np)%val(ipart) < 180.) forc_t_grid(np)%val(ipart) = 180.
+ ! the highest air temp was found in Kuwait 326 K, Sulaibya 2012-07-31;
+ ! Pakistan, Sindh 2010-05-26; Iraq, Nasiriyah 2011-08-03
+ IF (forc_t_grid(np)%val(ipart) > 326.) forc_t_grid(np)%val(ipart) = 326.
+
+ forc_rho_grid(np)%val(ipart) = (forc_pbot_grid(np)%val(ipart) &
+ - 0.378*forc_q_grid(np)%val(ipart)*forc_pbot_grid(np)%val(ipart) &
+ /(0.622+0.378*forc_q_grid(np)%val(ipart)))/(rgas*forc_t_grid(np)%val(ipart))
+
+ forc_th_grid(np)%val(ipart) = forc_t_grid(np)%val(ipart) &
+ * (1.e5/forc_pbot_grid(np)%val(ipart)) ** (rair/cpair)
+
+ ! calculate sun zenith angle and sun azimuth angle and turn to degree
+ coszen(np) = orb_coszen(calday, patchlonr(np), patchlatr(np))
+ cosazi(np) = orb_cosazi(calday, patchlonr(np), patchlatr(np), coszen(np))
+
+ ! downscale forcing from grid to part
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ ! Complex downscaling with topographic effects
+ CALL downscale_forcings ( &
+ glacierss(np), &
+
+ ! non-adjusted forcing
+ forc_topo_grid(np)%val(ipart), forc_maxelv_grid(np)%val(ipart), &
+ forc_t_grid(np)%val(ipart), forc_th_grid(np)%val(ipart), &
+ forc_q_grid(np)%val(ipart), forc_pbot_grid(np)%val(ipart), &
+ forc_rho_grid(np)%val(ipart), forc_prc_grid(np)%val(ipart), &
+ forc_prl_grid(np)%val(ipart), forc_lwrad_grid(np)%val(ipart), &
+ forc_hgt_grid(np)%val(ipart), forc_swrad_grid(np)%val(ipart), &
+ forc_us_grid(np)%val(ipart), forc_vs_grid(np)%val(ipart), &
+
+ ! topography-based factor on patch
+ slp_type_patches(:,np), asp_type_patches(:,np), cur_patches(np), &
+
+ ! other factors
+ calday, coszen(np), cosazi(np), &
+
+ ! adjusted forcing
+ forc_topo(np), forc_t_part(np)%val(ipart), &
+ forc_th_part(np)%val(ipart), forc_q_part(np)%val(ipart), &
+ forc_pbot_part(np)%val(ipart), forc_rhoair_part(np)%val(ipart), &
+ forc_prc_part(np)%val(ipart), forc_prl_part(np)%val(ipart), &
+
+ forc_frl_part(np)%val(ipart), forc_swrad_part(np)%val(ipart), &
+ forc_us_part(np)%val(ipart), forc_vs_part(np)%val(ipart), &
+
+ ! optional factors for complex downscaling
+ area_type_patches(:,np), svf_patches(np), balb, &
+#ifdef SinglePoint
+ sf_lut_patches (:,:,np) &
+#else
+ sf_curve_patches(:,:,np) &
+#endif
+ )
+
+ ELSEIF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ ! Simple downscaling without optional parameters
+ CALL downscale_forcings ( &
+ glacierss(np), &
+
+ ! non-adjusted forcing
+ forc_topo_grid(np)%val(ipart), forc_maxelv_grid(np)%val(ipart), &
+ forc_t_grid(np)%val(ipart), forc_th_grid(np)%val(ipart), &
+ forc_q_grid(np)%val(ipart), forc_pbot_grid(np)%val(ipart), &
+ forc_rho_grid(np)%val(ipart), forc_prc_grid(np)%val(ipart), &
+ forc_prl_grid(np)%val(ipart), forc_lwrad_grid(np)%val(ipart), &
+ forc_hgt_grid(np)%val(ipart), forc_swrad_grid(np)%val(ipart), &
+ forc_us_grid(np)%val(ipart), forc_vs_grid(np)%val(ipart), &
+
+ ! topography-based factor on patch
+ slp_type_patches(:,np), asp_type_patches(:,np), cur_patches(np), &
+
+ ! other factors
+ calday, coszen(np), cosazi(np), &
+
+ ! adjusted forcing
+ forc_topo(np), forc_t_part(np)%val(ipart), &
+ forc_th_part(np)%val(ipart), forc_q_part(np)%val(ipart), &
+ forc_pbot_part(np)%val(ipart), forc_rhoair_part(np)%val(ipart), &
+ forc_prc_part(np)%val(ipart), forc_prl_part(np)%val(ipart), &
+
+ forc_frl_part(np)%val(ipart), forc_swrad_part(np)%val(ipart), &
+ forc_us_part(np)%val(ipart), forc_vs_part(np)%val(ipart) &
+ )
+
+ ENDIF
+
+ ENDDO
+ ENDDO
+ ENDIF
+
+ ! mapping parts to patches
+ CALL mg2p_forc%part2pset (forc_t_part, forc_t )
+ CALL mg2p_forc%part2pset (forc_q_part, forc_q )
+ CALL mg2p_forc%part2pset (forc_pbot_part, forc_pbot )
+ CALL mg2p_forc%part2pset (forc_rhoair_part, forc_rhoair)
+ CALL mg2p_forc%part2pset (forc_prc_part, forc_prc )
+ CALL mg2p_forc%part2pset (forc_prl_part, forc_prl )
+ CALL mg2p_forc%part2pset (forc_frl_part, forc_frl )
+ CALL mg2p_forc%part2pset (forc_swrad_part, forc_swrad )
+ CALL mg2p_forc%part2pset (forc_us_part, forc_us )
+ CALL mg2p_forc%part2pset (forc_vs_part, forc_vs )
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ forc_psrf = forc_pbot
+ ENDIF
+ ENDIF
+
+ ! wind downscaling
+ IF (p_is_compute) THEN
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ DO np = 1, numpatch
+ IF ((forc_us(np)==spval).or.(forc_vs(np)==spval)) cycle
+ CALL downscale_wind(forc_us(np), forc_vs(np), slp_type_patches(:,np), &
+ asp_type_patches(:,np), area_type_patches(:,np), cur_patches(np))
+ ENDDO
+
+ ELSEIF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ DO np = 1, numpatch
+ IF ((forc_us(np)==spval).or.(forc_vs(np)==spval)) cycle
+ CALL downscale_wind_simple(forc_us(np), forc_vs(np), slp_type_patches(:,np), &
+ asp_type_patches(:,np), cur_patches(np))
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+#ifndef SinglePoint
+ IF (trim(DEF_DS_precipitation_adjust_scheme) == 'III') THEN
+ ! Sisi Chen, Lu Li, Yongjiu Dai et al., 2024, JGR
+ ! Using MPI to pass the forcing variable field to Python to
+ ! accomplish precipitation downscaling
+ IF (p_is_compute) THEN
+ spaceship(1,1:numpatch) = forc_topo
+ spaceship(2,1:numpatch) = forc_t
+ spaceship(3,1:numpatch) = forc_pbot
+ spaceship(4,1:numpatch) = forc_q
+ spaceship(5,1:numpatch) = forc_frl
+ spaceship(6,1:numpatch) = forc_swrad
+ spaceship(7,1:numpatch) = forc_us
+ spaceship(8,1:numpatch) = forc_vs
+ spaceship(9,1:numpatch) = INT(calday)
+ spaceship(10,1:numpatch) = patchlatr
+ spaceship(11,1:numpatch) = patchlonr
+
+ target_server = p_iam_glb/5+p_np_glb
+ CALL MPI_SEND(spaceship,12*numpatch,MPI_REAL8,target_server,0,MPI_COMM_WORLD,ierr)
+ CALL MPI_RECV(forc_prc,numpatch,MPI_REAL8,target_server,0,MPI_COMM_WORLD,&
+ MPI_STATUS_IGNORE,ierr)
+
+ forc_prl = forc_prc/3600*2/3._r8
+ forc_prc = forc_prc/3600*1/3._r8
+ ENDIF
+ ENDIF
+
+ ! mapping forc_prl to forc_prl_part, forc_prc to forc_prc_part
+ IF (p_is_compute) THEN
+ DO np = 1, numpatch ! patches
+ DO ipart = 1, mg2p_forc%npart(np) ! part loop of each patch
+ IF (mg2p_forc%areapart(np)%val(ipart) == 0.) CYCLE
+
+ forc_prl_part(np)%val(ipart) = forc_prl(np)
+ forc_prc_part(np)%val(ipart) = forc_prc(np)
+
+ ENDDO
+ ENDDO
+ ENDIF
+
+ ! Conservation of convective and large scale precipitation in the grid of forcing
+ CALL mg2p_forc%normalize (forc_xy_prc, forc_prc_part)
+ CALL mg2p_forc%normalize (forc_xy_prl, forc_prl_part)
+
+ ! mapping parts to patches
+ CALL mg2p_forc%part2pset (forc_prc_part, forc_prc)
+ CALL mg2p_forc%part2pset (forc_prl_part, forc_prl)
+
+ ! Conservation of short- and long- waves radiation in the grid of forcing
+ CALL mg2p_forc%normalize (forc_xy_solarin, forc_swrad_part)
+ CALL mg2p_forc%normalize (forc_xy_frl, forc_frl_part )
+ CALL mg2p_forc%part2pset (forc_frl_part, forc_frl )
+ CALL mg2p_forc%part2pset (forc_swrad_part, forc_swrad )
+#endif
+
+ ! divide fractions of downscaled shortwave radiation
+ IF (p_is_compute) THEN
+ DO j = 1, numpatch
+ a = forc_swrad(j)
+ IF (isnan_ud(a)) a = 0
+ calday = calendarday(idate)
+ sunang = orb_coszen (calday, patchlonr(j), patchlatr(j))
+ IF (sunang.eq.0) THEN
+ cloud = 0.
+ ELSE
+ cloud = (1160.*sunang-a)/(963.*sunang)
+ ENDIF
+ cloud = max(cloud,0.0001)
+ cloud = min(cloud,1.)
+ cloud = max(0.58,cloud)
+
+ difrat = 0.0604/(sunang-0.0223)+0.0683
+ IF(difrat.lt.0.) difrat = 0.
+ IF(difrat.gt.1.) difrat = 1.
+
+ difrat = difrat+(1.0-difrat)*cloud
+ vnrat = (580.-cloud*464.)/((580.-cloud*499.)+(580.-cloud*464.))
+
+ forc_sols(j) = a*(1.0-difrat)*vnrat
+ forc_soll(j) = a*(1.0-difrat)*(1.0-vnrat)
+ forc_solsd(j) = a*difrat*vnrat
+ forc_solld(j) = a*difrat*(1.0-vnrat)
+ ENDDO
+ ENDIF
+ ENDIF
+
+#ifdef RangeCheck
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ IF (p_is_root) write(*,'(/, A20)') 'Checking forcing ...'
+
+ CALL check_vector_data ('Forcing us [m/s] ', forc_us )
+ CALL check_vector_data ('Forcing vs [m/s] ', forc_vs )
+ CALL check_vector_data ('Forcing t [kelvin]', forc_t )
+ CALL check_vector_data ('Forcing q [kg/kg] ', forc_q )
+ CALL check_vector_data ('Forcing prc [mm/s] ', forc_prc )
+ CALL check_vector_data ('Forcing psrf [pa] ', forc_psrf )
+ CALL check_vector_data ('Forcing prl [mm/s] ', forc_prl )
+ CALL check_vector_data ('Forcing sols [W/m2] ', forc_sols )
+ CALL check_vector_data ('Forcing soll [W/m2] ', forc_soll )
+ CALL check_vector_data ('Forcing solsd [W/m2] ', forc_solsd)
+ CALL check_vector_data ('Forcing solld [W/m2] ', forc_solld)
+ CALL check_vector_data ('Forcing frl [W/m2] ', forc_frl )
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL check_vector_data ('Forcing hpbl ', forc_hpbl )
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+#endif
+
+ END SUBROUTINE read_forcing
+
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! read lower and upper boundary forcing data, a major interface of this
+! MODULE
+!
+! !REVISIONS:
+! 04/2014, Hua Yuan: initial code
+!
+!-----------------------------------------------------------------------
+ SUBROUTINE metreadLBUB (idate, dir_forcing, is_spinup)
+
+ USE MOD_UserSpecifiedForcing
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_DataType
+ USE MOD_Block
+ USE MOD_NetCDFBlock
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ character(len=*), intent(in) :: dir_forcing
+ logical, intent(in) :: is_spinup
+
+ ! Local variables
+ integer :: ivar, year, month, day, time_i
+ integer :: iblkme, ib, jb, i, j
+ type(timestamp) :: mtstamp
+ character(len=256) :: filename
+
+ mtstamp = idate
+
+ DO ivar = 1, NVAR
+
+ IF (trim(vname(ivar)) == 'NULL') CYCLE ! no data, CYCLE
+
+ ! lower and upper boundary data already exist, CYCLE
+ IF ( .not.(tstamp_LB(ivar)=='NULL') .and. .not.(tstamp_UB(ivar)=='NULL') .and. &
+ tstamp_LB(ivar)<=mtstamp .and. mtstampendyr .or. (month>endmo .and. year==endyr) ) THEN
+ write(*,*) 'model year/month: ', year, month
+ write(*,*) 'forcing end year/month defined: ', endyr, endmo
+ print *, 'Warning: reaching the END of forcing data defined!'
+ ENDIF
+
+ ! read forcing data
+ filename = trim(dir_forcing)//trim(metfilename(year, month, day, ivar, is_spinup))
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+
+ IF (forcing_read_ahead) THEN
+ metdata%blk(gblock%xblkme(1),gblock%yblkme(1))%val = forc_disk(time_i,ivar)
+ ELSE
+#ifndef URBAN_MODEL
+ CALL ncio_read_site_time (filename, vname(ivar), time_i, metdata)
+#else
+ IF (trim(vname(ivar)) == 'Rainf') THEN
+ CALL ncio_read_site_time (filename, 'Rainf', time_i, rainf)
+ CALL ncio_read_site_time (filename, 'Snowf', time_i, snowf)
+
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+
+ metdata%blk(ib,jb)%val(1,1) = rainf%blk(ib,jb)%val(1,1) &
+ + snowf%blk(ib,jb)%val(1,1)
+ ENDDO
+ ELSE
+ CALL ncio_read_site_time (filename, vname(ivar), time_i, metdata)
+ ENDIF
+#endif
+ ENDIF
+ ELSE
+ CALL ncio_read_block_time (filename, vname(ivar), gforc, time_i, metdata)
+ ENDIF
+
+ CALL block_data_copy (metdata, forcn_UB(ivar))
+
+ ! calculate time average coszen, for shortwave radiation
+ IF (ivar == 7) THEN
+ CALL calavgcos(idate)
+ ENDIF
+ ENDIF
+
+ ENDDO
+
+ END SUBROUTINE metreadLBUB
+
+
+!-----------------------------------------------------------------------
+ SUBROUTINE metread_latlon (dir_forcing, idate)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_UserSpecifiedForcing
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: dir_forcing
+ integer, intent(in) :: idate(3)
+
+ ! Local variables
+ character(len=256) :: filename
+ integer :: year, month, day, time_i
+ type(timestamp) :: mtstamp
+ real(r8), allocatable :: latxy (:,:) ! latitude values in 2d
+ real(r8), allocatable :: lonxy (:,:) ! longitude values in 2d
+ real(r8), allocatable :: lon_in(:)
+ real(r8), allocatable :: lat_in(:)
+
+ IF (trim(DEF_forcing%dataset) == 'POINT' .or. trim(DEF_forcing%dataset) == 'CPL7' ) THEN
+ CALL gforc%define_by_ndims (360, 180)
+ ELSE
+
+ mtstamp = idate
+
+ CALL setstampLB(mtstamp, 1, year, month, day, time_i)
+ filename = trim(dir_forcing)//trim(metfilename(year, month, day, 1))
+ tstamp_LB(1) = timestamp(-1, -1, -1)
+
+ IF (dim2d) THEN
+ CALL ncio_read_bcast_serial (filename, latname, latxy)
+ CALL ncio_read_bcast_serial (filename, lonname, lonxy)
+
+ allocate (lat_in (size(latxy,2)))
+ allocate (lon_in (size(lonxy,1)))
+ lat_in = latxy(1,:)
+ lon_in = lonxy(:,1)
+
+ deallocate (latxy)
+ deallocate (lonxy)
+ ELSE
+ CALL ncio_read_bcast_serial (filename, latname, lat_in)
+ CALL ncio_read_bcast_serial (filename, lonname, lon_in)
+ ENDIF
+
+ IF (.not. DEF_forcing%regional) THEN
+ CALL gforc%define_by_center (lat_in, lon_in)
+ ELSE
+ CALL gforc%define_by_center (lat_in, lon_in, &
+ south = DEF_forcing%regbnd(1), north = DEF_forcing%regbnd(2), &
+ west = DEF_forcing%regbnd(3), east = DEF_forcing%regbnd(4))
+ ENDIF
+
+ deallocate (lat_in)
+ deallocate (lon_in)
+ ENDIF
+
+ CALL gforc%set_rlon ()
+ CALL gforc%set_rlat ()
+
+ END SUBROUTINE metread_latlon
+
+!-----------------------------------------------------------------------
+ SUBROUTINE metread_time (dir_forcing, ststamp, etstamp, deltime)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_UserSpecifiedForcing
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: dir_forcing
+ type(timestamp), intent(in), optional :: ststamp, etstamp
+ real(r8), intent(in), optional :: deltime
+
+ ! Local variables
+ character(len=256) :: filename
+ character(len=256) :: timeunit, timestr
+ real(r8), allocatable :: forctime_sec(:), metcache(:,:,:)
+ integer :: year, month, day, hour, minute, second
+ integer :: itime, maxday, id(3)
+ integer*8 :: sec_long
+ integer :: ivar, ntime, its, ite, it
+ real(r8) firstsec
+
+ type(timestamp) :: etstamp_f
+ type(timestamp), allocatable :: forctime_ (:)
+
+
+ filename = trim(dir_forcing)//trim(fprefix(1))
+
+ CALL ncio_read_serial (filename, 'time', forctime_sec)
+ CALL ncio_get_attr (filename, 'time', 'units', timeunit)
+
+ timestr = timeunit(15:18) // ' ' // timeunit(20:21) // ' ' // timeunit(23:24) &
+ // ' ' // timeunit(26:27) // ' ' // timeunit(29:30) // ' ' // timeunit(32:33)
+ read(timestr,*) year, month, day, hour, minute, second
+
+ allocate (forctime (size(forctime_sec)))
+
+ id(1) = year
+ id(2) = get_calday(month*100+day, isleapyear(year))
+ id(3) = hour*3600 + minute*60 + second
+
+ firstsec = forctime_sec(1)
+ DO WHILE (firstsec > 86400)
+ CALL ticktime (86400., id)
+ firstsec = firstsec - 86400
+ ENDDO
+ CALL ticktime (firstsec, id)
+
+ !forctime(1)%year = year
+ !forctime(1)%day = get_calday(month*100+day, isleapyear(year))
+ !forctime(1)%sec = hour*3600 + minute*60 + second + forctime_sec(1)
+
+ !id(:) = (/forctime(1)%year, forctime(1)%day, forctime(1)%sec/)
+ CALL adj2end(id)
+ forctime(1) = id
+
+ ntime = size(forctime)
+
+ DO itime = 2, ntime
+ id(:) = (/forctime(itime-1)%year, forctime(itime-1)%day, forctime(itime-1)%sec/)
+ CALL ticktime (forctime_sec(itime)-forctime_sec(itime-1), id)
+ forctime(itime) = id
+ ENDDO
+
+ IF (forcing_read_ahead) THEN
+
+ CALL ticktime (deltime, id)
+ etstamp_f = id
+
+ IF ((ststamp < forctime(1)) .or. (etstamp_f < etstamp)) THEN
+ write(*,*) 'Error: Forcing does not cover simulation period!'
+ write(*,*) 'Model start ', ststamp, ' -> Model END ', etstamp
+ write(*,*) 'Forc start ', forctime(1), ' -> Forc END ', etstamp_f
+ CALL CoLM_stop ()
+ ELSE
+ its = 1
+ DO WHILE (.not. (ststamp < forctime(its+1)))
+ its = its + 1
+ IF (its >= ntime) EXIT
+ ENDDO
+
+ ite = ntime
+ DO WHILE (etstamp < forctime(ite-1))
+ ite = ite - 1
+ IF (ite <= 1) EXIT
+ ENDDO
+
+ ntime = ite-its+1
+
+ allocate (forctime_(ntime))
+ DO it = 1, ntime
+ forctime_(it) = forctime(it+its-1)
+ ENDDO
+
+ deallocate (forctime)
+ allocate (forctime (ntime))
+ DO it = 1, ntime
+ forctime(it) = forctime_(it)
+ ENDDO
+
+ deallocate(forctime_)
+ ENDIF
+
+ allocate (forc_disk (size(forctime),NVAR))
+
+ filename = trim(dir_forcing)//trim(metfilename(-1,-1,-1,-1))
+ DO ivar = 1, NVAR
+ IF (trim(vname(ivar)) /= 'NULL') THEN
+#ifndef URBAN_MODEL
+ CALL ncio_read_period_serial (filename, vname(ivar), its, ite, metcache)
+ forc_disk(:,ivar) = metcache(1,1,:)
+#else
+ IF (trim(vname(ivar)) == 'Rainf') THEN
+ CALL ncio_read_period_serial (filename, 'Rainf', its, ite, metcache)
+ forc_disk(:,ivar) = metcache(1,1,:)
+
+ CALL ncio_read_period_serial (filename, 'Snowf', its, ite, metcache)
+ forc_disk(:,ivar) = forc_disk(:,ivar) + metcache(1,1,:)
+ ELSE
+ CALL ncio_read_period_serial (filename, vname(ivar), its, ite, metcache)
+ forc_disk(:,ivar) = metcache(1,1,:)
+ ENDIF
+#endif
+ ENDIF
+ ENDDO
+
+ IF (allocated(metcache)) deallocate(metcache)
+ ENDIF
+
+ END SUBROUTINE metread_time
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! set the lower boundary time stamp and record information,
+! a KEY FUNCTION of this MODULE
+!
+! - for time stamp, set it regularly as the model time step.
+! - for record information, account for:
+! o year alternation
+! o month alternation
+! o leap year
+! o required data just beyond the first record
+!
+! !REVISIONS:
+! 04/2014, Hua Yuan: initial code
+!
+!-----------------------------------------------------------------------
+ SUBROUTINE setstampLB(mtstamp, var_i, year, month, mday, time_i)
+
+ IMPLICIT NONE
+ type(timestamp), intent(in) :: mtstamp
+ integer, intent(in) :: var_i
+ integer, intent(out) :: year
+ integer, intent(out) :: month
+ integer, intent(out) :: mday
+ integer, intent(out) :: time_i
+
+ integer :: i, day, sec, ntime
+ integer :: months(0:12)
+
+ year = mtstamp%year
+ day = mtstamp%day
+ sec = mtstamp%sec
+
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+
+ ntime = size(forctime)
+ time_i = 1
+
+ IF ((mtstamp < forctime(1)) .or. (forctime(ntime) < mtstamp)) THEN
+ write(*,*) 'Error: Forcing does not cover simulation period!'
+ write(*,*) 'Need ', mtstamp, ', Forc start ', forctime(1), ', Forc END', forctime(ntime)
+ CALL CoLM_stop ()
+ ELSE
+ DO WHILE (.not. (mtstamp < forctime(time_i+1)))
+ time_i = time_i + 1
+ ENDDO
+ iforctime(var_i) = time_i
+ tstamp_LB(var_i) = forctime(iforctime(var_i))
+ ENDIF
+
+ RETURN
+ ENDIF
+
+ tstamp_LB(var_i)%year = year
+ tstamp_LB(var_i)%day = day
+
+ ! in the case of one year one file
+ IF ( trim(groupby) == 'year' ) THEN
+
+ ! calculate the initial second
+ sec = 86400*(day-1) + sec
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ sec = (time_i-1)*dtime(var_i) + offset(var_i) - 86400*(day-1)
+ tstamp_LB(var_i)%sec = sec
+
+ ! set time stamp (ststamp_LB)
+ IF (sec < 0) THEN
+ tstamp_LB(var_i)%sec = 86400 + sec
+ tstamp_LB(var_i)%day = day - 1
+ IF (tstamp_LB(var_i)%day == 0) THEN
+ tstamp_LB(var_i)%year = year - 1
+ IF ( isleapyear(tstamp_LB(var_i)%year) ) THEN
+ tstamp_LB(var_i)%day = 366
+ ELSE
+ tstamp_LB(var_i)%day = 365
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! set record info (year, time_i)
+ IF ( sec<0 .or. (sec==0 .and. offset(var_i).NE.0) ) THEN
+
+ ! IF the required data just behind the first record
+ ! -> set to the first record
+ IF ( year==startyr .and. month==startmo .and. day==1 ) THEN
+ sec = offset(var_i)
+
+ ! ELSE, set to one record backward
+ ELSE
+ sec = 86400 + sec
+ day = day - 1
+ IF (day == 0) THEN
+ year = year - 1
+ IF ( isleapyear(year) ) THEN
+ day = 366
+ ELSE
+ day = 365
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF ! ENDIF (sec <= 0)
+
+ ! in case of leapyear with a non-leapyear calendar
+ ! USE the data 1 day before after FEB 28th (Julian day 59).
+ IF ( .not. leapyear .and. isleapyear(year) .and. day>59 ) THEN
+ day = day - 1
+ ENDIF
+
+ ! get record time index
+ sec = 86400*(day-1) + sec
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ ENDIF
+
+ ! in the case of one month one file
+ IF ( trim(groupby) == 'month' ) THEN
+
+ IF ( isleapyear(year) ) THEN
+ months = (/0,31,60,91,121,152,182,213,244,274,305,335,366/)
+ ELSE
+ months = (/0,31,59,90,120,151,181,212,243,273,304,334,365/)
+ ENDIF
+
+ ! calculate initial month and day values
+ CALL julian2monthday(year, day, month, mday)
+
+ ! calculate initial second value
+ sec = 86400*(mday-1) + sec
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ sec = (time_i-1)*dtime(var_i) + offset(var_i) - 86400*(mday-1)
+ tstamp_LB(var_i)%sec = sec
+
+ ! set time stamp (ststamp_LB)
+ IF (sec < 0) THEN
+ tstamp_LB(var_i)%sec = 86400 + sec
+ tstamp_LB(var_i)%day = day - 1
+ IF (tstamp_LB(var_i)%day == 0) THEN
+ tstamp_LB(var_i)%year = year - 1
+ IF ( isleapyear(tstamp_LB(var_i)%year) ) THEN
+ tstamp_LB(var_i)%day = 366
+ ELSE
+ tstamp_LB(var_i)%day = 365
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! set record info (year, month, time_i)
+ IF ( sec<0 .or. (sec==0 .and. offset(var_i).ne.0) ) THEN
+
+ ! IF just behind the first record -> set to first record
+ IF ( year==startyr .and. month==startmo .and. mday==1 ) THEN
+ sec = offset(var_i)
+
+ ! set to one record backward
+ ELSE
+ sec = 86400 + sec
+ mday = mday - 1
+ IF (mday == 0) THEN
+ month = month - 1
+ ! bug found by Zhu Siguang & Zhang Xiangxiang, 05/19/2014
+ ! move the below line in the 'ELSE' statement
+ !mday = months(month) - months(month-1)
+ IF (month == 0) THEN
+ month = 12
+ year = year - 1
+ mday = 31
+ ELSE
+ mday = months(month) - months(month-1)
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! in case of leapyear with a non-leapyear calendar
+ ! USE the data 1 day before, i.e., FEB 28th.
+ IF ( .not. leapyear .and. isleapyear(year) .and. month==2 .and. mday==29 ) THEN
+ mday = 28
+ ENDIF
+
+ ! get record time index
+ sec = 86400*(mday-1) + sec
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ ENDIF
+
+ ! in the case of one day one file
+ IF ( trim(groupby) == 'day' ) THEN
+
+ ! calculate initial month and day values
+ CALL julian2monthday(year, day, month, mday)
+
+ ! calculate initial second value
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ sec = (time_i-1)*dtime(var_i) + offset(var_i)
+ tstamp_LB(var_i)%sec = sec
+
+ ! set time stamp (ststamp_LB)
+ IF (sec < 0) THEN
+ tstamp_LB(var_i)%sec = 86400 + sec
+ tstamp_LB(var_i)%day = day - 1
+ IF (tstamp_LB(var_i)%day == 0) THEN
+ tstamp_LB(var_i)%year = year - 1
+ IF ( isleapyear(tstamp_LB(var_i)%year) ) THEN
+ tstamp_LB(var_i)%day = 366
+ ELSE
+ tstamp_LB(var_i)%day = 365
+ ENDIF
+ ENDIF
+
+ IF ( year==startyr .and. month==startmo .and. mday==1 ) THEN
+ sec = offset(var_i)
+ ! set to one record backward
+ ELSE
+ sec = 86400 + sec
+ year = tstamp_LB(var_i)%year
+ CALL julian2monthday(tstamp_LB(var_i)%year, tstamp_LB(var_i)%day, month, mday)
+ ENDIF
+ ENDIF
+
+ ! in case of leapyear with a non-leapyear calendar
+ ! USE the data 1 day before, i.e., FEB 28th.
+ IF ( .not. leapyear .and. isleapyear(year) .and. month==2 .and. mday==29 ) THEN
+ mday = 28
+ ENDIF
+
+ ! get record time index
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ ENDIF
+
+ IF (time_i <= 0) THEN
+ write(6, *) "got the wrong time record of forcing! STOP!"; CALL CoLM_stop()
+ ENDIF
+
+ RETURN
+
+ END SUBROUTINE setstampLB
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! set the upper boundary time stamp and record information,
+! a KEY FUNCTION of this MODULE
+!
+! !REVISIONS:
+! 04/2014, Hua Yuan: initial code
+!
+!-----------------------------------------------------------------------
+ SUBROUTINE setstampUB(var_i, year, month, mday, time_i)
+
+ IMPLICIT NONE
+ integer, intent(in) :: var_i
+ integer, intent(out) :: year
+ integer, intent(out) :: month
+ integer, intent(out) :: mday
+ integer, intent(out) :: time_i
+
+ integer :: day, sec
+ integer :: months(0:12)
+
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+ IF ( tstamp_UB(var_i) == 'NULL' ) THEN
+ tstamp_UB(var_i) = forctime(iforctime(var_i)+1)
+ ELSE
+ iforctime(var_i) = iforctime(var_i) + 1
+ tstamp_LB(var_i) = forctime(iforctime(var_i))
+ tstamp_UB(var_i) = forctime(iforctime(var_i)+1)
+ ENDIF
+
+ time_i = iforctime(var_i)+1
+ year = tstamp_UB(var_i)%year
+ day = tstamp_UB(var_i)%day
+
+ CALL julian2monthday(year, day, month, mday)
+
+ RETURN
+ ENDIF
+
+ ! calculate the time stamp
+ IF ( tstamp_UB(var_i) == 'NULL' ) THEN
+ tstamp_UB(var_i) = tstamp_LB(var_i) + dtime(var_i)
+ ELSE
+ tstamp_LB(var_i) = tstamp_UB(var_i)
+ tstamp_UB(var_i) = tstamp_UB(var_i) + dtime(var_i)
+ ENDIF
+
+ ! calculate initial year, day, and second values
+ year = tstamp_UB(var_i)%year
+ day = tstamp_UB(var_i)%day
+ sec = tstamp_UB(var_i)%sec
+
+ IF ( trim(groupby) == 'year' ) THEN
+
+ ! adjust year value
+ IF ( sec==86400 .and. offset(var_i).eq.0 ) THEN
+ sec = 0
+ day = day + 1
+ IF( isleapyear(year) .and. day==367) THEN
+ year = year + 1; day = 1
+ ENDIF
+ IF( .not. isleapyear(year) .and. day==366) THEN
+ year = year + 1; day = 1
+ ENDIF
+ ENDIF
+
+ ! in case of leapyear with a non-leapyear calendar
+ ! USE the data 1 day before after FEB 28th (Julian day 59).
+ IF ( .not. leapyear .and. isleapyear(year) .and. day>59 ) THEN
+ day = day - 1
+ ENDIF
+
+ ! set record index
+ sec = 86400*(day-1) + sec
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ ENDIF
+
+ IF ( trim(groupby) == 'month' ) THEN
+
+ IF ( isleapyear(year) ) THEN
+ months = (/0,31,60,91,121,152,182,213,244,274,305,335,366/)
+ ELSE
+ months = (/0,31,59,90,120,151,181,212,243,273,304,334,365/)
+ ENDIF
+
+ ! calculate initial month and day values
+ CALL julian2monthday(year, day, month, mday)
+
+ ! record in the next day, adjust year, month and second values
+ IF ( sec==86400 .and. offset(var_i).eq.0 ) THEN
+ sec = 0
+ mday = mday + 1
+ IF ( mday > (months(month)-months(month-1)) ) THEN
+ mday = 1
+ ! bug found by Zhu Siguang, 05/25/2014
+ ! move the below line in the 'ELSE' statement
+ !month = month + 1
+ IF (month == 12) THEN
+ month = 1
+ year = year + 1
+ ELSE
+ month = month + 1
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! in case of leapyear with a non-leapyear calendar
+ ! for day 29th Feb, USE the data 1 day before, i.e., 28th FEB.
+ IF ( .not. leapyear .and. isleapyear(year) .and. month==2 .and. mday==29 ) THEN
+ mday = 28
+ ENDIF
+
+ ! set record index
+ sec = 86400*(mday-1) + sec
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ ENDIF
+
+ IF ( trim(groupby) == 'day' ) THEN
+ IF ( isleapyear(year) ) THEN
+ months = (/0,31,60,91,121,152,182,213,244,274,305,335,366/)
+ ELSE
+ months = (/0,31,59,90,120,151,181,212,243,273,304,334,365/)
+ ENDIF
+
+ ! calculate initial month and day values
+ CALL julian2monthday(year, day, month, mday)
+ !mday = day
+
+ ! record in the next day, adjust year, month and second values
+ IF ( sec==86400 .and. offset(var_i).eq.0 ) THEN
+ sec = 0
+ mday = mday + 1
+ IF ( mday > (months(month)-months(month-1)) ) THEN
+ mday = 1
+ ! bug found by Zhu Siguang, 05/25/2014
+ ! move the below line in the 'ELSE' statement
+ !month = month + 1
+ IF (month == 12) THEN
+ month = 1
+ year = year + 1
+ ELSE
+ month = month + 1
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ! in case of leapyear with a non-leapyear calendar
+ ! for day 29th Feb, USE the data 1 day before, i.e., 28th FEB.
+ IF ( .not. leapyear .and. isleapyear(year) .and. month==2 .and. mday==29 ) THEN
+ mday = 28
+ ENDIF
+
+ ! set record index
+ time_i = floor( (sec-offset(var_i)) *1. / dtime(var_i) ) + 1
+ ENDIF
+
+ IF (time_i < 0) THEN
+ write(6, *) "got the wrong time record of forcing! STOP!"; CALL CoLM_stop()
+ ENDIF
+
+ RETURN
+
+ END SUBROUTINE setstampUB
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! calculate time average coszen value between [LB, UB]
+!
+! !REVISIONS:
+! 04/2014, Hua Yuan: this method is adapted from CLM
+!
+!-----------------------------------------------------------------------
+ SUBROUTINE calavgcos(idate)
+
+ USE MOD_Block
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+
+ integer :: ntime, iblkme, ib, jb, i, j, ilon, ilat
+ real(r8) :: calday, cosz
+ type(timestamp) :: tstamp
+
+ tstamp = idate !tstamp_LB(7)
+ ntime = 0
+ DO WHILE (tstamp < tstamp_UB(7))
+ ntime = ntime + 1
+ tstamp = tstamp + deltim_int
+ ENDDO
+
+ tstamp = idate !tstamp_LB(7)
+ CALL flush_block_data (avgcos, 0._r8)
+
+ DO WHILE (tstamp < tstamp_UB(7))
+
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+ DO j = 1, gforc%ycnt(jb)
+ DO i = 1, gforc%xcnt(ib)
+
+ ilat = gforc%ydsp(jb) + j
+ ilon = gforc%xdsp(ib) + i
+ IF (ilon > gforc%nlon) ilon = ilon - gforc%nlon
+
+ calday = calendarday(tstamp)
+ cosz = orb_coszen(calday, gforc%rlon(ilon), gforc%rlat(ilat))
+ cosz = max(0.001, cosz)
+ avgcos%blk(ib,jb)%val(i,j) = avgcos%blk(ib,jb)%val(i,j) &
+ + cosz / real(ntime,r8) ! * deltim_real /real(tstamp_UB(7)-tstamp_LB(7))
+
+ ENDDO
+ ENDDO
+ ENDDO
+
+ tstamp = tstamp + deltim_int
+
+ ENDDO
+
+ END SUBROUTINE calavgcos
+
+END MODULE MOD_Forcing
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_ForcingDownscaling.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_ForcingDownscaling.F90
new file mode 100644
index 0000000000..c557b30784
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_ForcingDownscaling.F90
@@ -0,0 +1,1049 @@
+#include
+
+MODULE MOD_ForcingDownscaling
+
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+! Downscaling meteorological forcings
+!
+! !INITIAL:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISIONS:
+! Updated by Yongjiu Dai, January 16, 2023
+! Revised by Lu Li, January 24, 2024
+! Revised by Sisi Chen, Lu Li, June, 2024
+!-----------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Qsadv
+ USE MOD_Namelist
+ USE MOD_Const_Physical
+ USE MOD_Vars_Global
+ USE MOD_UserDefFun
+
+ IMPLICIT NONE
+
+ real(r8), parameter :: SHR_CONST_MWDAIR = 28.966_r8 ! molecular weight dry air [kg/kmole]
+ real(r8), parameter :: SHR_CONST_MWWV = 18.016_r8 ! molecular weight water vapor
+ real(r8), parameter :: SHR_CONST_AVOGAD = 6.02214e26_r8 ! Avogadro's number [molecules/kmole]
+ real(r8), parameter :: SHR_CONST_BOLTZ = 1.38065e-23_r8 ! Boltzmann's constant [J/K/molecule]
+ ! Universal gas constant [J/K/kmole]
+ real(r8), parameter :: SHR_CONST_RGAS = SHR_CONST_AVOGAD*SHR_CONST_BOLTZ
+ ! Dry air gas constant [J/K/kg]
+ real(r8), parameter :: rair = SHR_CONST_RGAS/SHR_CONST_MWDAIR
+
+ ! On the windward side of the range, annual mean lapse rates of 3.9-5.2 (deg km-1), substantially
+ ! smaller than the often-assumed 6.5 (deg km-1). The data sets show similar seasonal and diurnal
+ ! variability, with lapse rates smallest (2.5-3.5 deg km-1) in late-summer minimum temperatures,
+ ! and largest (6.5-7.5 deg km-1) in spring maximum temperatures. Geographic (windward versus lee
+ ! side) differences in lapse rates are substantial. [Minder et al., 2010, Surface temperature
+ ! lapse rates over complex terrain: Lessons from the Cascade Mountains. JGR, 115,
+ ! doi:10.1029/2009JD013493]
+ !
+ ! Kunkel, K. E., 1989: Simple procedures for extrapolation of humidity variables in the
+ ! mountainous western United States. J. Climate, 2, 656-669. lapse_rate = /Jan -
+ ! Dec/4.4,5.9,7.1,7.8,8.1,8.2,8.1,8.1,7.7,6.8,5.5,4.7/ (deg km-1)
+ real(r8), parameter :: lapse_rate = 0.006_r8 ! surface temperature lapse rate (deg m-1)
+
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: downscale_forcings ! Downscale atmospheric forcing
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: rhos ! calculate atmospheric density
+
+!-----------------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------------
+
+ PURE FUNCTION rhos(qbot, pbot, tbot)
+
+!-----------------------------------------------------------------------------
+! DESCRIPTION:
+! Compute atmospheric density (kg/m**3)
+!-----------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ ! ARGUMENTS:
+ real(r8) :: rhos ! function result: atmospheric density (kg/m**3)
+ real(r8), intent(in) :: qbot ! atmospheric specific humidity (kg/kg)
+ real(r8), intent(in) :: pbot ! atmospheric pressure (Pa)
+ real(r8), intent(in) :: tbot ! atmospheric temperature (K)
+
+ ! LOCAL VARIABLES:
+ real(r8) :: egcm
+ real(r8) :: wv_to_dair_weight_ratio ! ratio of molecular weight of water vapor to dry air [-]
+
+ wv_to_dair_weight_ratio = SHR_CONST_MWWV/SHR_CONST_MWDAIR
+
+ egcm = qbot*pbot / (wv_to_dair_weight_ratio + (1._r8 - wv_to_dair_weight_ratio)*qbot)
+ rhos = (pbot - (1._r8 - wv_to_dair_weight_ratio)*egcm) / (rair*tbot)
+
+ END FUNCTION rhos
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE downscale_forcings (&
+ glaciers, &
+
+ ! non-adjusted forcing
+ forc_topo_g ,forc_maxelv_g ,forc_t_g ,forc_th_g ,forc_q_g ,&
+ forc_pbot_g ,forc_rho_g ,forc_prc_g ,forc_prl_g ,forc_lwrad_g ,&
+ forc_hgt_g ,forc_swrad_g ,forc_us_g ,forc_vs_g , &
+
+ ! topography-based factor on patch
+ slp_type_c, asp_type_c, cur_c, &
+
+ ! other factors
+ julian_day, coszen, cosazi, &
+
+ ! adjusted forcing
+ forc_topo_c ,forc_t_c ,forc_th_c ,forc_q_c ,forc_pbot_c ,&
+ forc_rho_c ,forc_prc_c ,forc_prl_c ,forc_lwrad_c, forc_swrad_c, &
+ forc_us_c ,forc_vs_c, &
+
+ ! optional parameters for full downscaling
+ area_type_c, svf_c, alb, &
+#ifdef SinglePoint
+ sf_lut_c &
+#else
+ sf_curve_c &
+#endif
+ )
+
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+! Downscale atmospheric forcing fields.
+!
+! Downscaling is done based on the difference between each land model
+! column's elevation and the atmosphere's surface elevation (which is
+! the elevation at which the atmospheric forcings are valid).
+!
+! Note that the downscaling procedure can result in changes in grid
+! cell mean values compared to what was provided by the atmosphere. We
+! conserve fluxes of mass and energy, but allow states such as
+! temperature to differ.
+!-----------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ integer, parameter :: S = 1370 ! solar constant (W/m**2)
+ real(r8), parameter :: thr = 85*PI/180 ! threshold of zenith angle
+
+ ! ARGUMENTS:
+ logical, intent(in) :: glaciers ! true: glacier column (itypwat = 3)
+ real(r8), intent(in) :: julian_day ! day of year
+ real(r8), intent(in) :: coszen ! cosine of sun zenith angle at an hour
+ real(r8), intent(in) :: cosazi ! cosine of sun azimuth angle at an hour
+
+ ! topography-based factor
+ real(r8), intent(in) :: cur_c ! curvature
+ ! topographic aspect of each type of one patch(rad) - can be different dimensions
+ real(r8), intent(in) :: asp_type_c (:)
+ ! topographic slope of each character of one patch - can be different dimensions
+ real(r8), intent(in) :: slp_type_c (:)
+
+ ! optional parameters for complex downscaling
+ real(r8), intent(in), optional :: alb ! blue sky albedo
+ real(r8), intent(in), optional :: svf_c ! sky view factor
+ ! area percentage of each character of one patch
+ real(r8), intent(in), optional :: area_type_c(:)
+#ifdef SinglePoint
+ ! look up table of shadow mask of a patch
+ real(r8), intent(in), optional :: sf_lut_c (:,:)
+#else
+ ! curve of shadow mask of a patch
+ real(r8), intent(in), optional :: sf_curve_c (:,:)
+#endif
+
+ ! non-downscaled fields:
+ real(r8), intent(in) :: forc_topo_g ! atmospheric surface height [m]
+ real(r8), intent(in) :: forc_maxelv_g ! max atmospheric surface height [m]
+ real(r8), intent(in) :: forc_t_g ! atmospheric temperature [Kelvin]
+ real(r8), intent(in) :: forc_th_g ! atmospheric potential temperature [Kelvin]
+ real(r8), intent(in) :: forc_q_g ! atmospheric specific humidity [kg/kg]
+ real(r8), intent(in) :: forc_pbot_g ! atmospheric pressure [Pa]
+ real(r8), intent(in) :: forc_rho_g ! atmospheric density [kg/m**3]
+ real(r8), intent(in) :: forc_prc_g ! convective precipitation in grid [mm/s]
+ real(r8), intent(in) :: forc_prl_g ! large-scale precipitation in grid [mm/s]
+ real(r8), intent(in) :: forc_lwrad_g ! grid downward longwave [W/m**2]
+ real(r8), intent(in) :: forc_swrad_g ! grid downward shortwave [W/m**2]
+ real(r8), intent(in) :: forc_hgt_g ! atmospheric reference height [m]
+ real(r8), intent(in) :: forc_us_g ! eastward wind [m/s]
+ real(r8), intent(in) :: forc_vs_g ! northward wind [m/s]
+
+ ! downscaled fields:
+ real(r8), intent(in) :: forc_topo_c ! column surface height [m]
+ real(r8), intent(out) :: forc_t_c ! atmospheric temperature [Kelvin]
+ real(r8), intent(out) :: forc_th_c ! atmospheric potential temperature [Kelvin]
+ real(r8), intent(out) :: forc_q_c ! atmospheric specific humidity [kg/kg]
+ real(r8), intent(out) :: forc_pbot_c ! atmospheric pressure [Pa]
+ real(r8), intent(out) :: forc_rho_c ! atmospheric density [kg/m**3]
+ real(r8), intent(out) :: forc_prc_c ! column convective precipitation [mm/s]
+ real(r8), intent(out) :: forc_prl_c ! column large-scale precipitation [mm/s]
+ real(r8), intent(out) :: forc_lwrad_c ! column downward longwave [W/m**2]
+ real(r8), intent(out) :: forc_swrad_c ! column downward shortwave [W/m**2]
+ real(r8), intent(out) :: forc_us_c ! column eastward wind [m/s]
+ real(r8), intent(out) :: forc_vs_c ! column northward wind [m/s]
+
+ ! Local variables for topo downscaling:
+ real(r8) :: hsurf_g, hsurf_c
+ real(r8) :: Hbot, zbot
+ real(r8) :: tbot_g, pbot_g, thbot_g, qbot_g, qs_g, es_g, rhos_g
+ real(r8) :: tbot_c, pbot_c, thbot_c, qbot_c, qs_c, es_c, rhos_c
+ real(r8) :: rhos_c_estimate, rhos_g_estimate
+ real(r8) :: dum1, dum2
+ real(r8) :: max_elev_c ! the maximum column level elevation value within the grid
+ real(r8) :: delta_prc_c ! deviation of the column convective prec. from the grid level prec.
+ real(r8) :: delta_prl_c ! deviation of the column large-scale prec. from the grid level prec.
+
+!-----------------------------------------------------------------------------
+
+ ! --------------------------------------------------------------------------------------
+ ! 1. adjust air temperature, potential temperature, specific humidity, pressure, density
+ ! --------------------------------------------------------------------------------------
+ hsurf_g = forc_topo_g ! gridcell sfc elevation
+ tbot_g = forc_t_g ! atm sfc temp
+ thbot_g = forc_th_g ! atm sfc pot temp
+ qbot_g = forc_q_g ! atm sfc spec humid
+ pbot_g = forc_pbot_g ! atm sfc pressure
+ rhos_g = forc_rho_g ! atm density
+ zbot = forc_hgt_g ! atm ref height
+
+ hsurf_c = forc_topo_c ! column sfc elevation
+ tbot_c = tbot_g-lapse_rate*(hsurf_c-hsurf_g) ! adjust [temp] for column
+ Hbot = rair*0.5_r8*(tbot_g+tbot_c)/grav ! scale ht at avg temp
+ pbot_c = pbot_g*exp(-(hsurf_c-hsurf_g)/Hbot) ! adjust [press] for column
+
+ ! Derivation of potential temperature calculation:
+ !
+ ! The textbook definition would be:
+ ! thbot_c = tbot_c * (p0/pbot_c)^(rair/cpair)
+ !
+ ! Note that pressure is related to scale height as:
+ ! pbot_c = p0 * exp(-zbot/Hbot)
+ !
+ ! Plugging this in to the textbook definition, then manipulating, we get:
+ ! thbot_c = tbot_c * (p0/(p0*exp(-zbot/Hbot)))^(rair/cpair)
+ ! = tbot_c * (1/exp(-zbot/Hbot))^(rair/cpair)
+ ! = tbot_c * (exp(zbot/Hbot))^(rair/cpair)
+ ! = tbot_c * exp((zbot/Hbot) * (rair/cpair))
+
+ ! But we want everything expressed in delta form, resulting in:
+ ! adjust [pot temp] for column
+ thbot_c = thbot_g + (tbot_c - tbot_g)*exp((zbot/Hbot)*(rair/cpair))
+
+ CALL Qsadv(tbot_g,pbot_g,es_g,dum1,qs_g,dum2) ! es, qs for gridcell
+ CALL Qsadv(tbot_c,pbot_c,es_c,dum1,qs_c,dum2) ! es, qs for column
+ qbot_c = qbot_g*(qs_c/qs_g) ! adjust [q] for column
+
+ rhos_c_estimate = rhos(qbot=qbot_c, pbot=pbot_c, tbot=tbot_c)
+ rhos_g_estimate = rhos(qbot=qbot_g, pbot=pbot_g, tbot=tbot_g)
+ rhos_c = rhos_g * (rhos_c_estimate / rhos_g_estimate) ! adjust [density] for column
+
+ ! save
+ forc_t_c = tbot_c
+ forc_th_c = thbot_c
+ forc_q_c = qbot_c
+ forc_pbot_c = pbot_c
+ forc_rho_c = rhos_c
+
+ ! --------------------------------------------------------------------------------------
+ ! 2. adjust wind speed
+ ! --------------------------------------------------------------------------------------
+ forc_us_c = forc_us_g
+ forc_vs_c = forc_vs_g
+
+ ! --------------------------------------------------------------------------------------
+ ! 3. adjust longwave radiation and shortwave radiation
+ ! --------------------------------------------------------------------------------------
+ CALL downscale_longwave (glaciers, &
+ forc_topo_g, forc_t_g, forc_q_g, forc_pbot_g, forc_lwrad_g, &
+ forc_topo_c, forc_t_c, forc_q_c, forc_pbot_c, forc_lwrad_c)
+
+ ! Check if optional parameters are present for complex downscaling
+ IF (present(area_type_c) .and. present(svf_c) .and. present(alb) .and. &
+#ifdef SinglePoint
+ present(sf_lut_c) &
+#else
+ present(sf_curve_c) &
+#endif
+ ) THEN
+ ! Complex downscaling with topographic effects
+ CALL downscale_shortwave(&
+ forc_topo_g, forc_pbot_g, forc_swrad_g, &
+ forc_topo_c, forc_pbot_c, forc_swrad_c, &
+ julian_day, coszen, cosazi, alb, &
+ slp_type_c, asp_type_c, svf_c, &
+#ifdef SinglePoint
+ sf_lut_c, &
+#else
+ sf_curve_c, &
+#endif
+ area_type_c)
+ ELSE
+ ! Simple downscaling
+ CALL downscale_shortwave_simple(&
+ forc_topo_g, forc_pbot_g, forc_swrad_g, &
+ forc_topo_c, forc_pbot_c, forc_swrad_c, &
+ julian_day, coszen, cosazi, &
+ slp_type_c, asp_type_c)
+ ENDIF
+
+ ! --------------------------------------------------------------------------------------
+ ! 4. adjust precipitation
+ ! --------------------------------------------------------------------------------------
+ IF (trim(DEF_DS_precipitation_adjust_scheme) == 'I') THEN
+ ! Tesfa et al, 2020: Exploring Topography-Based Methods for Downscaling
+ ! Subgrid Precipitation for Use in Earth System Models. Equation (5)
+ ! https://doi.org/ 10.1029/2019JD031456
+
+ IF (forc_maxelv_g /= 0.) THEN
+ delta_prc_c = forc_prc_g * (forc_topo_c - forc_topo_g) / forc_maxelv_g
+ ELSE
+ delta_prc_c = 0.
+ ENDIF
+ forc_prc_c = forc_prc_g + delta_prc_c ! convective precipitation [mm/s]
+ IF (forc_prc_c<=0) forc_prc_c = forc_prc_g ! the limit value is non-negative
+ IF (forc_prc_c==0) forc_prc_c = 1.0e-10_r8 ! avoid denominator being 0 when conserving water quantity
+
+ IF (forc_maxelv_g /= 0.) THEN
+ delta_prl_c = forc_prl_g * (forc_topo_c - forc_topo_g) / forc_maxelv_g
+ ELSE
+ delta_prl_c = 0.
+ ENDIF
+ forc_prl_c = forc_prl_g + delta_prl_c ! large scale precipitation [mm/s]
+ IF (forc_prl_c<=0) forc_prl_c = forc_prl_g ! the limit value is non-negative
+ IF (forc_prl_c==0) forc_prl_c = 1.0e-10_r8 ! avoid denominator being 0 when conserving water quantity
+
+ ELSEIF (trim(DEF_DS_precipitation_adjust_scheme) == 'II') THEN
+ ! Liston, G. E. and Elder, K.: A meteorological distribution system
+ ! for high-resolution terrestrial modeling (MicroMet), J. Hydrometeorol., 7, 217-234, 2006.
+ ! Equation (33) and Table 1: chi range from January to December:
+ ! [0.35,0.35,0.35,0.30,0.25,0.20,0.20,0.20,0.20,0.25,0.30,0.35] (1/km)
+
+ delta_prc_c = forc_prc_g *1.0*0.27*(forc_topo_c - forc_topo_g) &
+ /(1.0 - 0.27*(forc_topo_c - forc_topo_g))
+ forc_prc_c = forc_prc_g + delta_prc_c ! large scale precipitation [mm/s]
+
+ delta_prl_c = forc_prl_g *1.0*0.27*(forc_topo_c - forc_topo_g) &
+ /(1.0 - 0.27*(forc_topo_c - forc_topo_g))
+ forc_prl_c = forc_prl_g + delta_prl_c ! large scale precipitation [mm/s]
+ ENDIF
+
+ IF (forc_prl_c < 0) THEN
+ write(*,*) 'negative prl', forc_prl_g, forc_maxelv_g, forc_topo_c, forc_topo_g
+ forc_prl_c = 0.
+ ENDIF
+
+ IF (forc_prc_c < 0) THEN
+ write(*,*) 'negative prc', forc_prc_g, forc_maxelv_g, forc_topo_c, forc_topo_g
+ forc_prc_c = 0.
+ ENDIF
+
+ END SUBROUTINE downscale_forcings
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE downscale_wind(forc_us_g, forc_vs_g, &
+ slp_type_c, asp_type_c, area_type_c, cur_c)
+
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+! Downscale wind speed
+!
+! Liston, G. E. and Elder, K.: A meteorological distribution system for
+! high-resolution terrestrial modeling (MicroMet), J. Hydrometeorol.,
+! 7, 217-234, 2006.
+!-----------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ ! ARGUMENTS:
+ real(r8), intent(inout) :: forc_us_g ! eastward wind (m/s)
+ real(r8), intent(inout) :: forc_vs_g ! northward wind (m/s)
+
+ real(r8), intent(in) :: cur_c ! curvature
+ ! topographic aspect of each character of one patch
+ real(r8), intent(in) :: asp_type_c (1:num_slope_type)
+ ! topographic slope of each character of one patch
+ real(r8), intent(in) :: slp_type_c (1:num_slope_type)
+ ! area percentage of each character of one patch
+ real(r8), intent(in) :: area_type_c (1:num_slope_type)
+
+ ! local variables
+ real(r8) :: wind_dir ! wind direction
+ real(r8) :: ws_g ! non-downscaled wind speed
+ real(r8) :: wind_dir_slp (1:num_slope_type) ! the slope in the direction of the wind
+ real(r8) :: ws_c_type(1:num_slope_type) ! downscaled wind speed of each type in each patch
+ real(r8) :: ws_c ! downscaled wind speed
+ real(r8) :: scale_factor ! Combined scaling factor for regulating wind speed
+ integer :: g, c, i
+
+!-----------------------------------------------------------------------------
+
+ ! calculate wind direction
+ IF (forc_us_g == 0.) THEN
+ wind_dir = PI/2
+ ELSE
+ wind_dir = atan(forc_vs_g /forc_us_g)
+ ENDIF
+
+ ! non-adjusted wind speed
+ ws_g = sqrt(forc_vs_g *forc_vs_g +forc_us_g *forc_us_g )
+
+ ! compute the slope in the direction of the wind
+ DO i = 1, num_slope_type
+ wind_dir_slp(i) = slp_type_c(i)*cos(wind_dir-asp_type_c(i))
+ ENDDO
+
+ ! compute wind speed adjustment
+ DO i = 1, num_slope_type
+ scale_factor = (1+(0.58*wind_dir_slp(i))+0.42*cur_c)
+ ! Limiting the scope of proportionality adjustments
+ IF (scale_factor>1.5) THEN
+ scale_factor = 1.5
+ ELSEIF (scale_factor<-1.5) THEN
+ scale_factor = -1.5
+ ENDIF
+ ws_c_type(i) = ws_g *scale_factor*area_type_c(i)
+ ENDDO
+
+ ! adjusted wind speed
+ ws_c = sum(ws_c_type(:))
+ forc_us_g = ws_c*cos(wind_dir)
+ forc_vs_g = ws_c*sin(wind_dir)
+
+ END SUBROUTINE downscale_wind
+
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE downscale_wind_simple(forc_us_g, forc_vs_g, &
+ slp_type_c, area_type_c, cur_c)
+
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+! Downscale wind speed using a simple method for land-atmosphere coupling models
+!-----------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ ! ARGUMENTS:
+ real(r8), intent(inout) :: forc_us_g ! eastward wind (m/s)
+ real(r8), intent(inout) :: forc_vs_g ! northward wind (m/s)
+
+ real(r8), intent(in) :: cur_c ! curvature
+ ! topographic slope of each character of one patch
+ real(r8), intent(in) :: slp_type_c (1:num_aspect_type)
+ ! area percentage of each character of one patch
+ real(r8), intent(in) :: area_type_c (1:num_aspect_type)
+
+ ! local variables
+ real(r8) :: asp_type_c(1:num_aspect_type) ! topographic aspect of each type of one patch (rad)
+ real(r8) :: slp_type_c_rad ! Convert tan slope value to slope angle value
+
+ real(r8) :: wind_dir ! wind direction
+ real(r8) :: ws_g ! non-downscaled wind speed
+ real(r8) :: wind_dir_slp (1:num_aspect_type) ! the slope in the direction of the wind
+ real(r8) :: ws_c_type(1:num_aspect_type) ! downscaled wind speed of each type in each patch
+ real(r8) :: ws_c ! downscaled wind speed
+ real(r8) :: scale_factor ! Combined scaling factor for regulating wind speed
+ integer :: u_sign, v_sign, i, wind_dir_u, wind_dir_v
+
+ ! Initialize aspect type
+ asp_type_c(1) = 0.0_r8*PI/180 ! north
+ asp_type_c(2) = 45.0_r8*PI/180 ! northeast
+ asp_type_c(3) = 90.0_r8*PI/180 ! east
+ asp_type_c(4) = 135.0_r8*PI/180 ! southeast
+ asp_type_c(5) = 180.0_r8*PI/180 ! south
+ asp_type_c(6) = 225.0_r8*PI/180 ! southwest
+ asp_type_c(7) = 270.0_r8*PI/180 ! west
+ asp_type_c(8) = 315.0_r8*PI/180 ! northwest
+ asp_type_c(9) = -9999.0_r8 ! flat
+!-----------------------------------------------------------------------------
+
+ ! calculate wind direction
+ IF (forc_us_g == 0.) THEN
+ wind_dir = PI/2
+ ELSE
+ wind_dir = atan2(forc_vs_g, forc_us_g)
+ ENDIF
+
+ ! convert to 0-2*PI range
+ !wind_dir = wind_dir + 3*PI/2
+ !wind_dir = mod(wind_dir, 2*PI)
+
+ ! 0° is north
+ IF (wind_dir > PI/2) THEN
+ wind_dir = 2*PI - wind_dir + PI/2
+ ELSE
+ wind_dir = PI/2 - wind_dir
+ ENDIF
+
+ ! non-adjusted wind speed
+ ws_g = sqrt(forc_vs_g *forc_vs_g +forc_us_g *forc_us_g )
+
+ ! log the + - sign of the u,v direction
+ IF (forc_us_g >= 0.0_r8) THEN
+ u_sign = 1
+ ELSE
+ u_sign = -1
+ ENDIF
+ IF (forc_vs_g >= 0.0_r8) THEN
+ v_sign = 1
+ ELSE
+ v_sign = -1
+ ENDIF
+
+
+ ! compute the slope in the direction of the wind
+ DO i = 1, num_aspect_type
+ IF (slp_type_c(i) == -1.0e36) THEN
+ ! no slope in the direction of the aspect
+ wind_dir_slp(i) = -1.0e36
+ ELSE
+ ! slope in the direction of the wind
+ slp_type_c_rad = atan(slp_type_c(i))
+ wind_dir_slp(i) = slp_type_c_rad*cos(wind_dir-asp_type_c(i))
+ ENDIF
+ ENDDO
+
+ ! compute wind speed adjustment
+ DO i = 1, num_aspect_type
+ ! For the flat area, we do not adjust the wind speed
+ IF (asp_type_c(i) == -9999.0_r8) THEN
+ scale_factor = 1.0_r8
+ ELSE IF ((wind_dir_slp(i) == -1.0e36).or.(cur_c == -1.0e36)) THEN
+ ! no slope in the direction of the aspect
+ scale_factor = -1.0e36
+ ELSE
+ scale_factor = (1+(0.58*wind_dir_slp(i))+0.42*cur_c)
+ !write(*,*) 'scale_factor', scale_factor, 'wind_dir_slp(i)', wind_dir_slp(i), 'cur_c', cur_c
+ ENDIF
+
+ ! Limiting the scope of proportionality adjustments
+ IF (scale_factor>1.5) THEN
+ scale_factor = 1.5
+ ELSEIF (scale_factor<-1.5) THEN
+ scale_factor = -1.5
+ ENDIF
+
+ ! Downscale wind speed for each type in each patch
+ IF ((scale_factor == -1.0e36).or.(area_type_c(i) == -1.0e36)) THEN
+ ws_c_type(i) = -1.0e36
+ ELSE
+ ws_c_type(i) = ws_g *scale_factor*area_type_c(i)
+ ENDIF
+
+ ENDDO
+
+ ! adjusted wind speed
+ ws_c = sum(ws_c_type(:),mask=ws_c_type(:) /= -1.0e36)
+
+ ! caculate u and v components of the wind
+ IF (wind_dir > PI/2) THEN
+ wind_dir = 2*PI - wind_dir + PI/2
+ ELSE
+ wind_dir = PI/2 - wind_dir
+ ENDIF
+
+ forc_us_g = u_sign*sqrt((ws_c*cos(wind_dir))**2)
+ forc_vs_g = v_sign*sqrt((ws_c*sin(wind_dir))**2)
+
+ END SUBROUTINE downscale_wind_simple
+!-----------------------------------------------------------------------------
+
+ SUBROUTINE downscale_longwave (glaciers, &
+ forc_topo_g, forc_t_g, forc_q_g, forc_pbot_g, forc_lwrad_g, &
+ forc_topo_c, forc_t_c, forc_q_c, forc_pbot_c, forc_lwrad_c)
+
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+! Downscale longwave radiation
+!-----------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ ! ARGUMENTS:
+ logical, intent(in) :: glaciers ! true: glacier column
+
+ real(r8), intent(in) :: forc_topo_g ! atmospheric surface height (m)
+ real(r8), intent(in) :: forc_t_g ! atmospheric temperature [Kelvin]
+ real(r8), intent(in) :: forc_q_g ! atmospheric specific humidity [kg/kg]
+ real(r8), intent(in) :: forc_pbot_g ! atmospheric pressure [Pa]
+ real(r8), intent(in) :: forc_lwrad_g ! downward longwave (W/m**2)
+
+ real(r8), intent(in) :: forc_topo_c ! column surface height (m)
+ real(r8), intent(in) :: forc_t_c ! atmospheric temperature [Kelvin]
+ real(r8), intent(in) :: forc_q_c ! atmospheric specific humidity [kg/kg]
+ real(r8), intent(in) :: forc_pbot_c ! atmospheric pressure [Pa]
+ real(r8), intent(out):: forc_lwrad_c ! downward longwave (W/m**2)
+
+ ! LOCAL VARIABLES:
+ real(r8) :: hsurf_c ! column-level elevation (m)
+ real(r8) :: hsurf_g ! gridcell-level elevation (m)
+
+ real(r8) :: pv_g ! the water vapor pressure at grid cell (hPa)
+ real(r8) :: pv_c ! the water vapor pressure at column (hPa)
+ real(r8) :: emissivity_clearsky_g ! clear-sky emissivity at grid cell
+ real(r8) :: emissivity_clearsky_c ! clear-sky emissivity at grid column
+ real(r8) :: emissivity_allsky_g ! all-sky emissivity at grid cell
+ real(r8) :: es_g, es_c, dum1, dum2, dum3
+
+ real(r8), parameter :: lapse_rate_longwave = 0.032_r8 ! longwave radiation lapse rate (W m-2 m-1)
+ ! relative limit for how much longwave downscaling can be done (unitless)
+ real(r8), parameter :: longwave_downscaling_limit = 0.5_r8
+
+!--------------------------------------------------------------------------
+
+ ! Initialize (needs to be done for ALL active columns)
+ forc_lwrad_c = forc_lwrad_g
+ hsurf_g = forc_topo_g
+ hsurf_c = forc_topo_c
+
+ IF (trim(DEF_DS_longwave_adjust_scheme) == 'I') THEN
+ ! Fiddes and Gruber, 2014, TopoSCALE v.1.0: downscaling gridded climate data in complex
+ ! terrain. Geosci. Model Dev., 7, 387-405. doi:10.5194/gmd-7-387-2014. Equation (1) (2)
+ ! (3); here, the empirical parameters x1 and x2 are different from Konzelmann et al. (1994)
+ ! where x1 = 0.443 and x2 = 8 (optimal for measurements on the Greenland ice sheet)
+
+ CALL Qsadv(forc_t_g, forc_pbot_g, es_g,dum1,dum2,dum3)
+ CALL Qsadv(forc_t_c, forc_pbot_c, es_c,dum1,dum2,dum3)
+ pv_g = forc_q_g*es_g/100._r8 ! (hPa)
+ pv_c = forc_q_c*es_c/100._r8 ! (hPa)
+
+ emissivity_clearsky_g = 0.23_r8 + 0.43_r8*(pv_g/forc_t_g)**(1._r8/5.7_r8)
+ emissivity_clearsky_c = 0.23_r8 + 0.43_r8*(pv_c/forc_t_c)**(1._r8/5.7_r8)
+ emissivity_allsky_g = forc_lwrad_g / (5.67e-8_r8*forc_t_g**4)
+
+ forc_lwrad_c = &
+ (emissivity_clearsky_c + (emissivity_allsky_g - emissivity_clearsky_g)) &
+ * 5.67e-8_r8*forc_t_c**4
+ ELSE
+ ! Longwave radiation is downscaled by assuming a linear decrease in downwelling longwave
+ ! radiation with increasing elevation (0.032 W m-2 m-1, limited to 0.5 - 1.5 times the
+ ! gridcell mean value, then normalized to conserve gridcell total energy) (Van Tricht et
+ ! al., 2016, TC) Figure 6, doi:10.5194/tc-10-2379-2016
+
+ IF (glaciers) THEN
+ forc_lwrad_c = forc_lwrad_g - lapse_rate_longwave * (hsurf_c-hsurf_g)
+
+ ! Here we assume that deltaLW = (dLW/dT)*(dT/dz)*deltaz
+ ! We get dLW/dT = 4*eps*sigma*T^3 = 4*LW/T from the Stefan-Boltzmann law,
+ ! evaluated at the mean temp. We assume the same temperature lapse rate as above.
+
+ ELSE
+ forc_lwrad_c = forc_lwrad_g &
+ - 4.0_r8 * forc_lwrad_g/(0.5_r8*(forc_t_c+forc_t_g)) &
+ * lapse_rate * (hsurf_c - hsurf_g)
+ ENDIF
+ ENDIF
+
+ ! But ensure that we don't depart too far from the atmospheric forcing value:
+ ! negative values of lwrad are certainly bad, but small positive values might
+ ! also be bad. We can especially run into trouble due to the normalization: a
+ ! small lwrad value in one column can lead to a big normalization factor,
+ ! leading to huge lwrad values in other columns.
+
+ forc_lwrad_c = min(forc_lwrad_c, forc_lwrad_g * (1._r8 + longwave_downscaling_limit))
+ forc_lwrad_c = max(forc_lwrad_c, forc_lwrad_g * (1._r8 - longwave_downscaling_limit))
+
+ END SUBROUTINE downscale_longwave
+
+!-----------------------------------------------------------------------------
+ SUBROUTINE downscale_shortwave( &
+ forc_topo_g, forc_pbot_g, forc_swrad_g, &
+ forc_topo_c, forc_pbot_c, forc_swrad_c, &
+ julian_day, coszen, cosazi, alb, &
+ slp_type_c, asp_type_c, svf_c, &
+#ifdef SinglePoint
+ sf_lut_c, &
+#else
+ sf_curve_c, &
+#endif
+ area_type_c)
+
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Rouf, T., Mei, Y., Maggioni, V., Houser, P., & Noonan, M. (2020). A
+! Physically Based Atmospheric Variables Downscaling Technique. Journal
+! of Hydrometeorology, 21(1), 93-108.
+! https://doi.org/10.1175/JHM-D-19-0109.1
+!
+! Sisi Chen, Lu Li, Yongjiu Dai, et al. Exploring Topography
+! Downscaling Methods for Hyper-Resolution Land Surface Modeling.
+! Authorea. April 25, 2024. DOI: 10.22541/au.171403656.68476353/v1
+!
+! Must be done after downscaling of surface pressure
+!-----------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ integer, parameter :: S = 1370 ! solar constant (W/m**2)
+ real(r8), parameter :: thr = 85*PI/180 ! threshold of zenith
+ ! relative limit for how much shortwave downscaling can be done (unitless)
+ real(r8), parameter :: shortwave_downscaling_limit = 0.5_r8
+
+ ! ARGUMENTS:
+ real(r8), intent(in) :: julian_day ! day of year
+ real(r8), intent(in) :: coszen ! zenith angle at an hour
+ real(r8), intent(in) :: cosazi ! azimuth angle at an hour
+ real(r8), intent(in) :: alb ! blue sky albedo
+
+ real(r8), intent(in) :: forc_topo_g ! atmospheric surface height (m)
+ real(r8), intent(in) :: forc_pbot_g ! atmospheric pressure [Pa]
+ real(r8), intent(in) :: forc_swrad_g ! downward shortwave (W/m**2)
+
+ real(r8), intent(in) :: forc_topo_c ! column surface height (m)
+ real(r8), intent(in) :: forc_pbot_c ! atmospheric pressure [Pa]
+ real(r8), intent(out):: forc_swrad_c ! downward shortwave (W/m**2)
+
+ real(r8), intent(in) :: svf_c ! sky view factor
+# ifdef SinglePoint
+ ! look up table of shadow mask of a patch
+ real(r8), intent(in) :: sf_lut_c (1:num_azimuth,1:num_zenith)
+# else
+ ! curve of shadow mask of a patch
+ real(r8), intent(in) :: sf_curve_c (1:num_azimuth,1:num_zenith_parameter)
+# endif
+ ! topographic aspect of each character of one patch (°)
+ real(r8), intent(in) :: asp_type_c (1:num_slope_type)
+ ! topographic slope of each character of one patch
+ real(r8), intent(in) :: slp_type_c (1:num_slope_type)
+ ! area percentage of each character of one patch
+ real(r8), intent(in) :: area_type_c(1:num_slope_type)
+
+ ! LOCAL VARIABLES:
+ real(r8) :: zen_rad, zen_deg, azi_rad, azi_deg ! rad and deg of sun zenith and azimuth angle
+ integer :: idx_azi, idx_zen ! index used to cal shadow factor from
+ ! look up table
+ real(r8) :: sf_c ! shadow factor
+ real(r8) :: rt_R ! The ratio of the current distance between
+ ! the sun and the earth
+ real(r8) :: toa_swrad ! top of atmosphere shortwave radiation
+ real(r8) :: clr_idx ! atmospheric transparency
+ real(r8) :: diff_wgt ! diffuse weight
+ real(r8) :: k_c ! column broadband attenuation coefficient [Pa^-1]
+ real(r8) :: opt_factor ! optical length factor
+ real(r8) :: a_p
+ real(r8) :: svf, balb
+
+ real(r8) :: diff_swrad_g, beam_swrad_g ! diffuse and beam radiation
+ real(r8) :: diff_swrad_c, beam_swrad_c, refl_swrad_c! downscaled diffuse, beam radiation
+ ! and reflect radiation
+ real(r8) :: beam_swrad_type (1:num_slope_type) ! beam radiation of one characterized patch
+ real(r8) :: refl_swrad_type (1:num_slope_type) ! refl. radiation of one characterized patch
+ real(r8) :: tcf_type (1:num_slope_type) ! terrain configure factor
+ real(r8) :: cosill_type (1:num_slope_type) ! illumination angle (cos) at defined types
+
+ real(r8) :: zenith_segment, a1, a2 ! Segmented function segmentation
+ ! points (rad), parameter1, parameter2
+
+ integer :: i
+
+!-----------------------------------------------------------------------------
+
+ ! calculate shadow factor according to sun zenith and azimuth angle
+ zen_rad = acos(coszen)
+ azi_rad = acos(cosazi)
+ azi_deg = azi_rad*180.0/PI ! turn deg
+
+ idx_azi = INT(azi_deg*num_azimuth/360)
+
+ IF (idx_azi==0) idx_azi = 1
+
+#ifdef SinglePoint
+ zen_deg = zen_rad*180/PI ! turn deg
+ idx_zen = INT(zen_deg*num_zenith/90)
+ IF (idx_zen==0) idx_zen = 1
+ !constrain the upper boundary of zenith angle to 90 deg
+ IF (idx_zen>num_zenith) idx_zen = num_zenith
+
+ sf_c = sf_lut_c(idx_azi, idx_zen)
+#else
+ ! Constructing a shadow factor function from zenith angle parameters
+ ! shadow factor = exp(-1*exp(a1*zenith+a2))
+ zenith_segment = sf_curve_c(idx_azi, 1) ! Segmented function segmentation points (rad)
+ a1 = sf_curve_c(idx_azi, 2) ! parameter of function
+ a2 = sf_curve_c(idx_azi, 3) ! parameter of function
+
+ IF (zen_rad <= zenith_segment) THEN
+ sf_c = 1.
+ ELSEIF (a1<=1e-10) THEN
+ sf_c = 1.
+ ELSE
+ sf_c = exp(-1*exp(min(a1*zen_rad+a2,3.5)))
+ ENDIF
+#endif
+
+ IF (sf_c<0) sf_c = 0
+ IF (sf_c>1) sf_c = 1
+
+ ! calculate top-of-atmosphere incident shortwave radiation
+ rt_R = 1-0.01672*cos(0.9856*(julian_day-4))
+ toa_swrad = S*(rt_R**2)*coszen
+
+ ! calculate clearness index
+ IF (toa_swrad.eq.0) THEN
+ clr_idx = 0
+ ELSE
+ clr_idx = forc_swrad_g/toa_swrad
+ ENDIF
+ IF (clr_idx>1) clr_idx = 1
+
+ ! calculate diffuse weight
+ ! Ruiz-Arias, J. A., Alsamamra, H., Tovar-Pescador, J., & Pozo-Vázquez, D. (2010).
+ ! Proposal of a regressive model for the hourly diffuse solar radiation under all sky
+ ! conditions. Energy Conversion and Management, 51(5), 881-893.
+ ! https://doi.org/10.1016/j.enconman.2009.11.024
+ diff_wgt = 0.952-1.041*exp(-1*exp(min(2.3-4.702*clr_idx,3.5)))
+ IF (diff_wgt>1) diff_wgt = 1
+ IF (diff_wgt<0) diff_wgt = 0
+
+ ! calculate diffuse and beam radiation
+ diff_swrad_g = forc_swrad_g*diff_wgt
+ beam_swrad_g = forc_swrad_g*(1-diff_wgt)
+
+ ! calculate broadband attenuation coefficient [Pa^-1]
+ IF (clr_idx.le.0) THEN
+ k_c = 0
+ ELSE
+ k_c = log(clr_idx)/forc_pbot_c
+ ENDIF
+
+ ! calculate factor to account for the difference of optical path length
+ ! due to pressure difference
+ opt_factor = exp(k_c*(forc_pbot_g-forc_pbot_c))
+ ! Control the boundary of optical path length
+ IF ((opt_factor>10000).or.(opt_factor<-10000)) opt_factor = 0
+
+ ! Adjust the zenith angle so that the range of zenith angles is less than 85°
+ IF (zen_rad>thr) zen_rad=thr
+
+ ! loop for four defined types to downscale beam radiation
+ DO i = 1, num_slope_type
+ ! calculate the cosine of solar illumination angle, cos(θ),
+ ! ranging between −1 and 1, indicates if the sun is below or
+ ! above the local horizon (note that values lower than 0 are set to 0 indicate self shadow)
+ cosill_type(i) = cos(slp_type_c(i))+tan(zen_rad)*sin(slp_type_c(i))*cos(asp_type_c(i))
+ IF (cosill_type(i)>1) cosill_type(i) = 1
+ IF (cosill_type(i)<0) cosill_type(i) = 0
+
+ ! downscaling beam radiation
+ a_p = area_type_c(i)
+ IF (a_p.gt.1.0) a_p = 1
+ IF (a_p.lt.0) a_p = 0
+ beam_swrad_type(i) = sf_c*cosill_type(i)*opt_factor*a_p*beam_swrad_g
+ ENDDO
+ beam_swrad_c = sum(beam_swrad_type)
+
+ ! downscaling diffuse radiation
+ svf = svf_c
+ IF (svf>1) svf = 1
+ IF (svf<0) svf = 0
+ diff_swrad_c = svf*diff_swrad_g
+
+ ! downscaling reflected radiation
+ balb = alb
+ DO i = 1, num_slope_type
+ tcf_type(i) = (1+cos(slp_type_c(i)))/2-svf
+ IF (tcf_type(i)<0) tcf_type(i) = 0
+
+ IF (isnan_ud(alb)) THEN
+ refl_swrad_type(i) = -1.0e36
+ ELSE
+ IF ((balb<0).or.(balb>1)) balb = 0
+ refl_swrad_type(i) = balb*tcf_type(i)*(beam_swrad_c*coszen+(1-svf)*diff_swrad_c)
+ ENDIF
+ ENDDO
+ refl_swrad_c = sum(refl_swrad_type, mask = refl_swrad_type /= -1.0e36)
+ forc_swrad_c = beam_swrad_c+diff_swrad_c+refl_swrad_c
+
+ ! But ensure that we don't depart too far from the atmospheric forcing value:
+ ! negative values of swrad are certainly bad, but small positive values might
+ ! also be bad. We can especially run into trouble due to the normalization: a
+ ! small swrad value in one column can lead to a big normalization factor,
+ ! leading to huge swrad values in other columns.
+
+ forc_swrad_c = min(forc_swrad_c, &
+ forc_swrad_g * (1._r8 + shortwave_downscaling_limit))
+ forc_swrad_c = max(forc_swrad_c, &
+ forc_swrad_g * (1._r8 - shortwave_downscaling_limit))
+ ! Ensure that the denominator is not 0 during shortwave normalization
+ IF (forc_swrad_c==0.) forc_swrad_c = 0.0001
+
+ END SUBROUTINE downscale_shortwave
+
+!-----------------------------------------------------------------------------
+ SUBROUTINE downscale_shortwave_simple( &
+ forc_topo_g, forc_pbot_g, forc_swrad_g, &
+ forc_topo_c, forc_pbot_c, forc_swrad_c, &
+ julian_day, coszen, cosazi, &
+ slp_type_c, area_type_c)
+!-----------------------------------------------------------------------------
+! !DESCRIPTION:
+! This subroutine performs a simple downscaling of shortwave radiation for
+! land-atmosphere coupling models. The adjustments are only made for direct
+! radiation without considering the impact of shadow factor.
+!
+ IMPLICIT NONE
+
+ integer, parameter :: S = 1370 ! solar constant (W/m**2)
+ real(r8), parameter :: thr = 85*PI/180 ! threshold of zenith
+ ! relative limit for how much shortwave downscaling can be done (unitless)
+ real(r8), parameter :: shortwave_downscaling_limit = 0.2_r8
+
+ ! ARGUMENTS:
+ real(r8), intent(in) :: julian_day ! day of year
+ real(r8), intent(in) :: coszen ! zenith angle at an hour
+ real(r8), intent(in) :: cosazi ! azimuth angle at an hour
+
+ real(r8), intent(in) :: forc_topo_g ! atmospheric surface height (m)
+ real(r8), intent(in) :: forc_pbot_g ! atmospheric pressure [Pa]
+ real(r8), intent(in) :: forc_swrad_g ! downward shortwave (W/m**2)
+
+ real(r8), intent(in) :: forc_topo_c ! column surface height (m)
+ real(r8), intent(in) :: forc_pbot_c ! atmospheric pressure [Pa]
+ real(r8), intent(out):: forc_swrad_c ! downward shortwave (W/m**2)
+
+ ! tan value of topographic slope of each direction of one patch
+ real(r8), intent(in) :: slp_type_c (1:num_aspect_type)
+ ! area percentage of each character of one patch
+ real(r8), intent(in) :: area_type_c(1:num_aspect_type)
+
+ ! LOCAL VARIABLES:
+
+ real(r8) :: asp_type_c (1:num_aspect_type) ! topographic aspect fraction of one patch (%100) num_aspect_type = 1:north, 2:northeast, 3:east,
+ ! 4:southeast, 5:south, 6:southwest, 7:west, 8:northwest, 9:flat
+ real(r8) :: slp_type_c_rad ! Convert tan slope value to slope angle value
+
+ real(r8) :: zen_rad, azi_rad ! rad of sun zenith and azimuth angle
+ integer :: idx_azi, idx_zen ! index used to cal shadow factor from
+ ! look up table
+ real(r8) :: sf_c ! shadow factor
+ real(r8) :: rt_R ! The ratio of the current distance between
+ ! the sun and the earth
+ real(r8) :: toa_swrad ! top of atmosphere shortwave radiation
+ real(r8) :: clr_idx ! atmospheric transparency
+ real(r8) :: diff_wgt ! diffuse weight
+ real(r8) :: k_c ! column broadband attenuation coefficient [Pa^-1]
+ real(r8) :: opt_factor ! optical length factor
+ real(r8) :: a_p
+ real(r8) :: diff_swrad_g, beam_swrad_g ! diffuse and beam radiation
+ real(r8) :: diff_swrad_c, beam_swrad_c ! downscaled diffuse, beam radiation
+
+ real(r8) :: beam_swrad_type (1:num_aspect_type) ! beam radiation of one characterized patch
+ real(r8) :: cosill_type (1:num_aspect_type) ! illumination angle (cos) at defined types
+
+ integer :: i
+!------------------------------------------------------------------------------
+
+ ! Initialize aspect type
+ asp_type_c(1) = 0.0_r8*PI/180 ! north
+ asp_type_c(2) = 45.0_r8*PI/180 ! northeast
+ asp_type_c(3) = 90.0_r8*PI/180 ! east
+ asp_type_c(4) = 135.0_r8*PI/180 ! southeast
+ asp_type_c(5) = 180.0_r8*PI/180 ! south
+ asp_type_c(6) = 225.0_r8*PI/180 ! southwest
+ asp_type_c(7) = 270.0_r8*PI/180 ! west
+ asp_type_c(8) = 315.0_r8*PI/180 ! northwest
+ asp_type_c(9) = -9999.0_r8 ! flat
+
+ ! calculate shadow factor according to sun zenith and azimuth angle
+ zen_rad = acos(coszen)
+ azi_rad = acos(cosazi)
+
+ ! calculate top-of-atmosphere incident shortwave radiation
+ rt_R = 1-0.01672*cos(0.9856*(julian_day-4))
+ toa_swrad = S*(rt_R**2)*coszen
+
+ ! calculate clearness index
+ IF (toa_swrad < 1.e-7) THEN
+ clr_idx = 0
+ ELSE
+ clr_idx = forc_swrad_g/toa_swrad
+ ENDIF
+ IF (clr_idx>1) clr_idx = 1
+
+ ! calculate diffuse weight
+ ! Ruiz-Arias, J. A., Alsamamra, H., Tovar-Pescador, J., & Pozo-Vázquez, D. (2010).
+ ! Proposal of a regressive model for the hourly diffuse solar radiation under all sky
+ ! conditions. Energy Conversion and Management, 51(5), 881-893.
+ ! https://doi.org/10.1016/j.enconman.2009.11.024
+ diff_wgt = 0.952-1.041*exp(-1*exp(min(2.3-4.702*clr_idx,3.5)))
+ IF (diff_wgt>1) diff_wgt = 1
+ IF (diff_wgt<0) diff_wgt = 0
+
+ ! calculate diffuse and beam radiation
+ diff_swrad_g = forc_swrad_g*diff_wgt
+ beam_swrad_g = forc_swrad_g*(1-diff_wgt)
+
+ ! calculate broadband attenuation coefficient [Pa^-1]
+ IF (clr_idx.le.0) THEN
+ k_c = 0
+ ELSE
+ k_c = log(clr_idx)/forc_pbot_c
+ ENDIF
+
+ ! calculate factor to account for the difference of optical path length
+ ! due to pressure difference
+ opt_factor = exp(k_c*(forc_pbot_g-forc_pbot_c))
+ ! Control the boundary of optical path length
+ IF ((opt_factor>10000).or.(opt_factor<-10000)) opt_factor = 0
+
+ ! Adjust the zenith angle so that the range of zenith angles is less than 85°
+ IF (zen_rad>thr) zen_rad = thr
+
+ ! loop for four defined types to downscale beam radiation
+ DO i = 1, num_aspect_type
+ ! calculate the cosine of solar illumination angle, cos(θ),
+ ! ranging between −1 and 1, indicates if the sun is below or
+ ! above the local horizon (note that values lower than 0 are set to 0 indicate self shadow)
+ IF (i == 9) THEN
+ ! flat area, no slope
+ cosill_type(i) = 1.0_r8
+ ELSE
+ slp_type_c_rad = atan(slp_type_c(i))
+ cosill_type(i) = cos(slp_type_c_rad)+tan(zen_rad)*sin(slp_type_c_rad)*cos(asp_type_c(i))
+ ENDIF
+
+ ! Ensure that the cosine of illumination angle is between 0 and 1
+ IF (cosill_type(i)>1) cosill_type(i) = 1
+ IF (cosill_type(i)<0) cosill_type(i) = 0
+
+ ! downscaling beam radiation
+ a_p = area_type_c(i)
+ IF (a_p.gt.1.0) a_p = 1
+ IF (a_p.lt.0) a_p = 0
+ beam_swrad_type(i) = cosill_type(i)*opt_factor*a_p*beam_swrad_g
+ ENDDO
+ beam_swrad_c = sum(beam_swrad_type)
+
+ ! do not downscale diffuse radiation
+ diff_swrad_c = diff_swrad_g
+
+ forc_swrad_c = beam_swrad_c+diff_swrad_c
+
+ ! But ensure that we don't depart too far from the atmospheric forcing value:
+ ! negative values of swrad are certainly bad, but small positive values might
+ ! also be bad. We can especially run into trouble due to the normalization: a
+ ! small swrad value in one column can lead to a big normalization factor,
+ ! leading to huge swrad values in other columns.
+
+ forc_swrad_c = min(forc_swrad_c, &
+ forc_swrad_g * (1._r8 + shortwave_downscaling_limit))
+ forc_swrad_c = max(forc_swrad_c, &
+ forc_swrad_g * (1._r8 - shortwave_downscaling_limit))
+ ! Ensure that the denominator is not 0 during shortwave normalization
+ IF (forc_swrad_c < 1.e-4) forc_swrad_c = 0.0001
+
+ END SUBROUTINE downscale_shortwave_simple
+
+
+
+END MODULE MOD_ForcingDownscaling
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_FrictionVelocity.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_FrictionVelocity.F90
new file mode 100644
index 0000000000..2a93a983f3
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_FrictionVelocity.F90
@@ -0,0 +1,572 @@
+MODULE MOD_FrictionVelocity
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: moninobuk
+ PUBLIC :: moninobukm
+ PUBLIC :: moninobukini
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: psi
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE moninobuk(hu,ht,hq,displa,z0m,z0h,z0q,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+
+!-----------------------------------------------------------------------
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! calculation of friction velocity, relation for potential temperature
+! and humidity profiles of surface boundary layer.
+! the scheme is based on the work of Zeng et al. (1998):
+! Intercomparison of bulk aerodynamic algorithms for the computation of
+! sea surface fluxes using TOGA CORE and TAO data. J. Climate, Vol.
+! 11: 2628-2644
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: hu ! observational height of wind [m]
+ real(r8), intent(in) :: ht ! observational height of temperature [m]
+ real(r8), intent(in) :: hq ! observational height of humidity [m]
+ real(r8), intent(in) :: displa ! displacement height [m]
+ real(r8), intent(in) :: z0m ! roughness length, momentum [m]
+ real(r8), intent(in) :: z0h ! roughness length, sensible heat [m]
+ real(r8), intent(in) :: z0q ! roughness length, latent heat [m]
+ real(r8), intent(in) :: obu ! monin-obukhov length (m)
+ real(r8), intent(in) :: um ! wind speed including the stability effect [m/s]
+
+ real(r8), intent(out) :: ustar ! friction velocity [m/s]
+ real(r8), intent(out) :: fh2m ! relation for temperature at 2m
+ real(r8), intent(out) :: fq2m ! relation for specific humidity at 2m
+ real(r8), intent(out) :: fm10m ! integral of profile FUNCTION for momentum at 10m
+ real(r8), intent(out) :: fm ! integral of profile FUNCTION for momentum
+ real(r8), intent(out) :: fh ! integral of profile FUNCTION for heat
+ real(r8), intent(out) :: fq ! integral of profile FUNCTION for moisture
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) zetam ! transition point of flux-gradient relation (wind profile)
+ real(r8) zetat ! transition point of flux-gradient relation (temp. profile)
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+
+! real(r8), external :: psi ! stability FUNCTION for unstable case
+!-----------------------------------------------------------------------
+! adjustment factors for unstable (moz < 0) or stable (moz > 0) conditions.
+
+! wind profile
+ zldis=hu-displa
+ zeta=zldis/obu
+ zetam=1.574
+ IF(zeta < -zetam)THEN ! zeta < -1
+ fm = log(-zetam*obu/z0m) - psi(1,-zetam) &
+ + psi(1,z0m/obu) + 1.14*((-zeta)**0.333-(zetam)**0.333)
+ ustar = vonkar*um / fm
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fm = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ustar = vonkar*um / fm
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fm = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ustar = vonkar*um / fm
+ ELSE ! 1 < zeta, phi=5+zeta
+ fm = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ustar = vonkar*um / fm
+ ENDIF
+
+ ! for 10 meter wind-velocity
+ zldis=10.+z0m
+ zeta=zldis/obu
+ zetam=1.574
+ IF(zeta < -zetam)THEN ! zeta < -1
+ fm10m = log(-zetam*obu/z0m) - psi(1,-zetam) &
+ + psi(1,z0m/obu) + 1.14*((-zeta)**0.333-(zetam)**0.333)
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fm10m = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fm10m = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fm10m = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! temperature profile
+ zldis=ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for 2 meter screen temperature
+ zldis=2.+z0h ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh2m = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh2m = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh2m = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh2m = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! humidity profile
+ zldis=hq-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq = log(-zetat*obu/z0q) - psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fq = log(zldis/z0q) - psi(2,zeta) + psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fq = log(zldis/z0q) + 5.*zeta - 5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq = log(obu/z0q) + 5. - 5.*z0q/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for 2 meter screen humidity
+ zldis=2.+z0h
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq2m = log(-zetat*obu/z0q)-psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.) THEN ! -1 <= zeta < 0
+ fq2m = log(zldis/z0q)-psi(2,zeta)+psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.) THEN ! 0 <= zeta <= 1
+ fq2m = log(zldis/z0q)+5.*zeta-5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq2m = log(obu/z0q)+5.-5.*z0q/obu+(5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ END SUBROUTINE moninobuk
+
+
+ SUBROUTINE moninobukm(hu,ht,hq,displa,z0m,z0h,z0q,obu,um,displat,z0mt,&
+ ustar,fh2m,fq2m,htop,fmtop,fm,fh,fq,fht,fqt,phih)
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! calculation of friction velocity, relation for potential temperature
+! and humidity profiles of surface boundary layer. the scheme is based
+! on the work of Zeng et al. (1998): Intercomparison of bulk aerodynamic
+! algorithms for the computation of sea surface fluxes using TOGA CORE
+! and TAO data. J. Climate, Vol. 11: 2628-2644
+!
+! !REVISIONS:
+! 09/2017, Hua Yuan: adapted from moninobuk FUNCTION to calculate canopy
+! top fm, fq and phih for roughness sublayer u/k profile
+! calculation.
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: hu ! observational height of wind [m]
+ real(r8), intent(in) :: ht ! observational height of temperature [m]
+ real(r8), intent(in) :: hq ! observational height of humidity [m]
+ real(r8), intent(in) :: displa ! displacement height [m]
+ real(r8), intent(in) :: displat ! displacement height of the top layer [m]
+ real(r8), intent(in) :: z0m ! roughness length, momentum [m]
+ real(r8), intent(in) :: z0h ! roughness length, sensible heat [m]
+ real(r8), intent(in) :: z0q ! roughness length, latent heat [m]
+ real(r8), intent(in) :: z0mt ! roughness length of the top layer, latent heat [m]
+ real(r8), intent(in) :: htop ! canopy top height of the top layer [m]
+ real(r8), intent(in) :: obu ! monin-obukhov length (m)
+ real(r8), intent(in) :: um ! wind speed including the stability effect [m/s]
+
+ real(r8), intent(out) :: ustar ! friction velocity [m/s]
+ real(r8), intent(out) :: fh2m ! relation for temperature at 2m
+ real(r8), intent(out) :: fq2m ! relation for specific humidity at 2m
+ real(r8), intent(out) :: fmtop ! integral of profile FUNCTION for momentum at 10m
+ real(r8), intent(out) :: fm ! integral of profile FUNCTION for momentum
+ real(r8), intent(out) :: fh ! integral of profile FUNCTION for heat
+ real(r8), intent(out) :: fq ! integral of profile FUNCTION for moisture
+ real(r8), intent(out) :: fht ! integral of profile FUNCTION for heat at the top layer
+ real(r8), intent(out) :: fqt ! integral of profile FUNCTION for moisture at the top layer
+ real(r8), intent(out) :: phih ! phi(h), similarity FUNCTION for sensible heat
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) zetam ! transition point of flux-gradient relation (wind profile)
+ real(r8) zetat ! transition point of flux-gradient relation (temp. profile)
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+
+! real(r8), external :: psi ! stability FUNCTION for unstable case
+!-----------------------------------------------------------------------
+! adjustment factors for unstable (moz < 0) or stable (moz > 0) conditions.
+
+! wind profile
+ zldis=hu-displa
+ zeta=zldis/obu
+ zetam=1.574
+ IF(zeta < -zetam)THEN ! zeta < -1
+ fm = log(-zetam*obu/z0m) - psi(1,-zetam) &
+ + psi(1,z0m/obu) + 1.14*((-zeta)**0.333-(zetam)**0.333)
+ ustar = vonkar*um / fm
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fm = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ustar = vonkar*um / fm
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fm = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ustar = vonkar*um / fm
+ ELSE ! 1 < zeta, phi=5+zeta
+ fm = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ustar = vonkar*um / fm
+ ENDIF
+
+ ! for canopy top wind-velocity
+ !NOTE: changed for canopy top wind-velocity (no wake assumed)
+ zldis=htop-displa
+ zeta=zldis/obu
+ zetam=1.574
+ IF(zeta < -zetam)THEN ! zeta < -1
+ fmtop = log(-zetam*obu/z0m) - psi(1,-zetam) &
+ + psi(1,z0m/obu) + 1.14*((-zeta)**0.333-(zetam)**0.333)
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fmtop = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fmtop = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fmtop = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! temperature profile
+ zldis=ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for 2 meter screen temperature
+ zldis=2.+z0h ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh2m = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh2m = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh2m = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh2m = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for top layer temperature
+ zldis=displat+z0mt-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fht = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fht = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fht = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fht = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for canopy top phi(h)
+ ! CESM TECH NOTE EQ. (5.31)
+ zldis=htop-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ phih = 0.9*vonkar**(1.333)*(-zeta)**(-0.333)
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ phih = (1. - 16.*zeta)**(-0.5)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ phih = 1. + 5.*zeta
+ ELSE ! 1 < zeta, phi=5+zeta
+ phih = 5. + zeta
+ ENDIF
+
+! humidity profile
+ zldis=hq-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq = log(-zetat*obu/z0q) - psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fq = log(zldis/z0q) - psi(2,zeta) + psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fq = log(zldis/z0q) + 5.*zeta - 5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq = log(obu/z0q) + 5. - 5.*z0q/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for 2 meter screen humidity
+ zldis=2.+z0h
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq2m = log(-zetat*obu/z0q)-psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.) THEN ! -1 <= zeta < 0
+ fq2m = log(zldis/z0q)-psi(2,zeta)+psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.) THEN ! 0 <= zeta <= 1
+ fq2m = log(zldis/z0q)+5.*zeta-5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq2m = log(obu/z0q)+5.-5.*z0q/obu+(5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ ! for top layer humidity
+ zldis=displat+z0mt-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fqt = log(-zetat*obu/z0q)-psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.) THEN ! -1 <= zeta < 0
+ fqt = log(zldis/z0q)-psi(2,zeta)+psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.) THEN ! 0 <= zeta <= 1
+ fqt = log(zldis/z0q)+5.*zeta-5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fqt = log(obu/z0q)+5.-5.*z0q/obu+(5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ END SUBROUTINE moninobukm
+
+ real(r8) FUNCTION kmoninobuk(displa,obu,ustar,z)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! k profile calculation for bare ground case
+!
+! Created by Hua Yuan, 09/2017
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: displa ! displacement height [m]
+ real(r8), intent(in) :: obu ! monin-obukhov length (m)
+ real(r8), intent(in) :: ustar ! friction velocity [m/s]
+ real(r8), intent(in) :: z ! height of windspeed [m]
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) zetam ! transition point of flux-gradient relation (wind profile)
+ real(r8) zetat ! transition point of flux-gradient relation (temp. profile)
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+ real(r8) phih ! phi(h), similarity FUNCTION for sensible heat
+
+!-----------------------------------------------------------------------
+
+ IF ( z .le. displa ) THEN
+ kmoninobuk = 0.
+ RETURN
+ ENDIF
+
+ ! for canopy top phi(h)
+ zldis=z-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ phih = 0.9*vonkar**(1.333)*(-zeta)**(-0.333)
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ phih = (1. - 16.*zeta)**(-0.5)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ phih = 1. + 5.*zeta
+ ELSE ! 1 < zeta, phi=5+zeta
+ phih = 5. + zeta
+ ENDIF
+
+ kmoninobuk = vonkar*(z-displa)*ustar/phih
+
+ END FUNCTION kmoninobuk
+
+ real(r8) FUNCTION kintmoninobuk(displa,z0h,obu,ustar,ztop,zbot)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! k profile integration for bare ground case
+!
+! Created by Hua Yuan, 09/2017
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: displa ! displacement height [m]
+ real(r8), intent(in) :: z0h ! roughness length, sensible heat [m]
+ real(r8), intent(in) :: obu ! monin-obukhov length (m)
+ real(r8), intent(in) :: ustar ! friction velocity [m/s]
+ real(r8), intent(in) :: ztop ! height top
+ real(r8), intent(in) :: zbot ! height bottom
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) zetam ! transition point of flux-gradient relation (wind profile)
+ real(r8) zetat ! transition point of flux-gradient relation (temp. profile)
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+
+ real(r8) :: fh_top, fh_bot ! integral of profile FUNCTION for heat
+
+!-----------------------------------------------------------------------
+
+ zldis=ztop-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh_top = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh_top = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh_top = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh_top = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ zldis=zbot-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh_bot = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh_bot = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh_bot = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh_bot = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ kintmoninobuk = (fh_top-fh_bot)/(vonkar*ustar)
+
+ END FUNCTION kintmoninobuk
+
+
+ SUBROUTINE moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0m,um,obu)
+
+! ======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! initialization of Monin-Obukhov length,
+! the scheme is based on the work of Zeng et al. (1998):
+! Intercomparison of bulk aerodynamic algorithms for the computation
+! of sea surface fluxes using TOGA CORE and TAO data. J. Climate, Vol.
+! 11: 2628-2644
+! ======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: grav, vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: ur ! wind speed at reference height [m/s]
+ real(r8), intent(in) :: thm ! intermediate variable (tm+0.0098*ht)
+ real(r8), intent(in) :: th ! potential temperature [kelvin]
+ real(r8), intent(in) :: thv ! virtual potential temperature (kelvin)
+ real(r8), intent(in) :: dth ! diff of virtual temp. between ref. height and surface
+ real(r8), intent(in) :: dthv ! diff of vir. poten. temp. between ref. height and surface
+ real(r8), intent(in) :: dqh ! diff of humidity between ref. height and surface
+ real(r8), intent(in) :: zldis ! reference height "minus" zero displacement height [m]
+ real(r8), intent(in) :: z0m ! roughness length, momentum [m]
+
+ real(r8), intent(out) :: um ! wind speed including the stability effect [m/s]
+ real(r8), intent(out) :: obu ! monin-obukhov length (m)
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) wc ! convective velocity [m/s]
+ real(r8) rib ! bulk Richardson number
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+
+!-----------------------------------------------------------------------
+! Initial values of u* and convective velocity
+
+ wc=0.5
+ IF(dthv >= 0.)THEN
+ um=max(ur,0.1)
+ ELSE
+ um=sqrt(ur*ur+wc*wc)
+ ENDIF
+
+ rib=grav*zldis*dthv/(thv*um*um)
+
+ IF(rib >= 0.)THEN ! neutral or stable
+ zeta = rib*log(zldis/z0m)/(1.-5.*min(rib,0.19))
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE ! unstable
+ zeta = rib*log(zldis/z0m)
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu=zldis/zeta
+
+ END SUBROUTINE moninobukini
+
+
+ real(r8) FUNCTION psi(k,zeta)
+
+!=======================================================================
+! stability FUNCTION for unstable case (rib < 0)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer k
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+ real(r8) chik !
+
+ chik = (1.-16.*zeta)**0.25
+ IF(k == 1)THEN
+ psi = 2.*log((1.+chik)*0.5)+log((1.+chik*chik)*0.5)-2.*atan(chik)+2.*atan(1.)
+ ELSE
+ psi = 2.*log((1.+chik*chik)*0.5)
+ ENDIF
+
+ END FUNCTION psi
+
+END MODULE MOD_FrictionVelocity
+! --------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Glacier.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Glacier.F90
new file mode 100644
index 0000000000..07f8a0894c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Glacier.F90
@@ -0,0 +1,1142 @@
+#include
+
+MODULE MOD_Glacier
+
+!-----------------------------------------------------------------------
+! Energy and Mass Balance Model of LAND ICE (GLACIER / ICE SHEET)
+!
+! Original author: Yongjiu Dai, /05/2014/
+!
+! !REVISIONS:
+! 01/2023, Hua Yuan: added GLACIER_WATER_snicar() to account for SNICAR
+! model effects on snow water [see snowwater_snicar()], snow
+! layers combine [see snowlayerscombine_snicar()], snow layers
+! divide [see snowlayersdivide_snicar()]
+!
+! 01/2023, Hua Yuan: added snow layer absorption in GLACIER_TEMP()
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: GLACIER_TEMP
+ PUBLIC :: GLACIER_WATER
+ PUBLIC :: GLACIER_WATER_snicar
+
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: groundfluxes_glacier
+ PRIVATE :: groundtem_glacier
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE GLACIER_TEMP (patchtype,lb ,nl_ice ,deltim ,&
+ zlnd ,zsno ,capr ,cnfac ,&
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_hpbl ,&
+ forc_rhoair ,forc_psrf ,coszen ,sabg ,&
+ forc_frl ,fsno ,dz_icesno ,z_icesno ,&
+ zi_icesno ,t_icesno ,wice_icesno ,wliq_icesno ,&
+ scv ,snowdp ,imelt ,taux ,&
+ tauy ,fsena ,fevpa ,lfevpa ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ qseva ,qsdew ,qsubl ,qfros ,&
+ sm ,tref ,qref ,trad ,&
+ errore ,emis ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,pg_rain ,&
+ pg_snow ,t_precip ,snofrz ,sabg_snow_lyr)
+
+!-----------------------------------------------------------------------
+! this is the main SUBROUTINE to execute the calculation of thermal processes
+! and surface fluxes of the land ice (glacier and ice sheet)
+!
+! Original author: Yongjiu Dai and Nan Wei, /05/2014/
+! Modified by Nan Wei, 07/2017/ interaction btw prec and land ice
+! FLOW DIAGRAM FOR GLACIER_TEMP.F90
+!
+! GLACIER_TEMP ===> qsadv
+! groundfluxes | ---------> |moninobukini
+! | |moninobuk
+!
+! groundTem | ---------> |meltf
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: hvap,hsub,rgas,cpair,stefnc,tfrz,cpliq,cpice
+ USE MOD_FrictionVelocity
+ USE MOD_Qsadv
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: &
+ patchtype,& ! land patch type (0=soil, 1=urban and built-up,
+ ! 2=wetland, 3=land ice, 4=land water bodies, 99 = ocean)
+ lb, &! lower bound of array
+ nl_ice ! upper bound of array
+
+ real(r8), intent(in) :: &
+ deltim, &! model time step [second]
+ zlnd, &! roughness length for ice surface [m]
+ zsno, &! roughness length for snow [m]
+ capr, &! tuning factor to turn first layer T into surface T
+ cnfac, &! Crank Nicholson factor between 0 and 1
+
+ ! Atmospherical variables and observational height
+ forc_hgt_u, &! observational height of wind [m]
+ forc_hgt_t, &! observational height of temperature [m]
+ forc_hgt_q, &! observational height of humidity [m]
+ forc_us, &! wind component in eastward direction [m/s]
+ forc_vs, &! wind component in northward direction [m/s]
+ forc_t, &! temperature at agcm reference height [kelvin]
+ forc_q, &! specific humidity at agcm reference height [kg/kg]
+ forc_rhoair, &! density air [kg/m3]
+ forc_psrf, &! atmosphere pressure at the surface [pa]
+ t_precip, &! snowfall/rainfall temperature [kelvin]
+ pg_rain, &! rainfall [kg/(m2 s)]
+ pg_snow, &! snowfall [kg/(m2 s)]
+ forc_hpbl, &! atmospheric boundary layer height [m]
+
+ ! Radiative fluxes
+ coszen, &! cosine of the solar zenith angle
+ sabg, &! solar radiation absorbed by ground [W/m2]
+ forc_frl, &! atmospheric infrared (longwave) radiation [W/m2]
+
+ ! State variable (1)
+ fsno, &! fraction of ground covered by snow
+ dz_icesno(lb:nl_ice), &! layer thickness [m]
+ z_icesno (lb:nl_ice), &! node depth [m]
+ zi_icesno(lb-1:nl_ice) ! interface depth [m]
+
+ real(r8), intent(in) :: &
+ sabg_snow_lyr (lb:1) ! snow layer absorption [W/m-2]
+
+ ! State variables (2)
+ real(r8), intent(inout) :: &
+ t_icesno(lb:nl_ice), &! snow/ice temperature [K]
+ wice_icesno(lb:nl_ice),&! ice lens [kg/m2]
+ wliq_icesno(lb:nl_ice),&! liquid water [kg/m2]
+ scv, &! snow cover, water equivalent [mm, kg/m2]
+ snowdp ! snow depth [m]
+
+ real(r8), intent(inout) :: &
+ snofrz (lb:0) ! snow freezing rate (lyr) [kg m-2 s-1]
+
+ integer, intent(out) :: &
+ imelt(lb:nl_ice) ! flag for melting or freezing [-]
+
+ ! Output fluxes
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fsena, &! sensible heat to atmosphere [W/m2]
+ lfevpa, &! latent heat flux to atmosphere [W/m2]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+ olrg, &! outgoing long-wave radiation to atmosphere
+ fgrnd, &! ground heat flux [W/m2]
+
+ fevpa, &! evapotranspiration to atmosphere (mm h2o/s)
+ qseva, &! ground surface evaporation rate (mm h2o/s)
+ qsdew, &! ground surface dew formation (mm h2o /s) [+]
+ qsubl, &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros, &! surface dew added to snow pack (mm h2o /s) [+]
+
+ sm, &! rate of snowmelt [kg/(m2 s)]
+ tref, &! 2 m height air temperature [kelvin]
+ qref, &! 2 m height air specific humidity
+ trad, &! radiative temperature [K]
+
+ emis, &! averaged bulk surface emissivity
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! u* in similarity theory [m/s]
+ qstar, &! q* in similarity theory [kg/kg]
+ tstar, &! t* in similarity theory [K]
+ fm, &! integral of profile FUNCTION for momentum
+ fh, &! integral of profile FUNCTION for heat
+ fq ! integral of profile FUNCTION for moisture
+
+!-------------------------- Local Variables ----------------------------
+ integer i,j
+
+ real(r8) :: &
+ cgrnd, &! deriv. of ice energy flux wrt to ice temp [w/m2/k]
+ cgrndl, &! deriv, of ice sensible heat flux wrt ice temp [w/m2/k]
+ cgrnds, &! deriv of ice latent heat flux wrt ice temp [w/m**2/k]
+ degdT, &! d(eg)/dT
+ dqgdT, &! d(qg)/dT
+ eg, &! water vapor pressure at temperature T [pa]
+ egsmax, &! max. evaporation which ice can provide at one time step
+ egidif, &! the excess of evaporation over "egsmax"
+ emg, &! ground emissivity (0.96)
+ errore, &! energy balance error [w/m2]
+ fact(lb:nl_ice), &! used in computing tridiagonal matrix
+ htvp, &! latent heat of vapor of water (or sublimation) [j/kg]
+ qg, &! ground specific humidity [kg/kg]
+ qsatg, &! saturated humidity [kg/kg]
+ qsatgdT, &! d(qsatg)/dT
+ qred, &! ice surface relative humidity
+ thm, &! intermediate variable (forc_t+0.0098*forc_hgt_t)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ t_grnd, &! ground surface temperature [K]
+ t_icesno_bef(lb:nl_ice), &! ice/snow temperature before update
+ tinc, &! temperature difference of two time step
+ ur, &! wind speed at reference height [m/s]
+ xmf ! total latent heat of phase change of ground water
+
+!=======================================================================
+! [1] Initial set and propositional variables
+!=======================================================================
+
+ ! temperature and water mass from previous time step
+ t_grnd = t_icesno(lb)
+ t_icesno_bef(lb:) = t_icesno(lb:)
+
+ ! emissivity
+ emg = 0.97
+
+ ! latent heat, assumed that the sublimation occurs only as wliq_icesno=0
+ htvp = hvap
+ IF(wliq_icesno(lb)<=0. .and. wice_icesno(lb)>0.) htvp = hsub
+
+ ! potential temperature at the reference height
+ thm = forc_t + 0.0098*forc_hgt_t ! intermediate variable equivalent to
+ ! forc_t*(pgcm/forc_psrf)**(rgas/cpair)
+ th = forc_t*(100000./forc_psrf)**(rgas/cpair) ! potential T
+ thv = th*(1.+0.61*forc_q) ! virtual potential T
+ ur = max(0.1,sqrt(forc_us*forc_us+forc_vs*forc_vs)) ! limit set to 0.1
+
+!=======================================================================
+! [2] specific humidity and its derivative at ground surface
+!=======================================================================
+
+ qred = 1.
+ CALL qsadv(t_grnd,forc_psrf,eg,degdT,qsatg,qsatgdT)
+
+ qg = qred*qsatg
+ dqgdT = qred*qsatgdT
+
+!=======================================================================
+! [3] Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+!=======================================================================
+
+ CALL groundfluxes_glacier (zlnd,zsno,forc_hgt_u,forc_hgt_t,forc_hgt_q,&
+ forc_us,forc_vs,forc_t,forc_q,forc_rhoair,forc_psrf, &
+ ur,thm,th,thv,t_grnd,qg,dqgdT,htvp,&
+ forc_hpbl,&
+ fsno,cgrnd,cgrndl,cgrnds,&
+ taux,tauy,fsena,fevpa,fseng,fevpg,tref,qref,&
+ z0m,zol,rib,ustar,qstar,tstar,fm,fh,fq)
+
+!=======================================================================
+! [4] Ground temperature
+!=======================================================================
+
+ CALL groundtem_glacier (patchtype,lb,nl_ice,deltim,&
+ capr,cnfac,dz_icesno,z_icesno,zi_icesno,&
+ t_icesno,wice_icesno,wliq_icesno,scv,snowdp,&
+ forc_frl,sabg,sabg_snow_lyr,fseng,fevpg,cgrnd,htvp,emg,&
+ imelt,snofrz,sm,xmf,fact,pg_rain,pg_snow,t_precip)
+
+!=======================================================================
+! [5] Correct fluxes to present ice temperature
+!=======================================================================
+
+ t_grnd = t_icesno(lb)
+ tinc = t_icesno(lb) - t_icesno_bef(lb)
+ fseng = fseng + tinc*cgrnds
+ fevpg = fevpg + tinc*cgrndl
+
+! calculation of evaporative potential; flux in kg m-2 s-1.
+! egidif holds the excess energy IF all water is evaporated
+! during the timestep. this energy is later added to the sensible heat flux.
+
+ egsmax = (wice_icesno(lb)+wliq_icesno(lb)) / deltim
+
+ egidif = max( 0., fevpg - egsmax )
+ fevpg = min ( fevpg, egsmax )
+ fseng = fseng + htvp*egidif
+
+! total fluxes to atmosphere
+ fsena = fseng
+ fevpa = fevpg
+ lfevpa= htvp*fevpg ! W/m^2 (accounting for sublimation)
+
+ qseva = 0.
+ qsubl = 0.
+ qfros = 0.
+ qsdew = 0.
+
+ IF(fevpg >= 0)THEN
+ qseva = min(wliq_icesno(lb)/deltim, fevpg)
+ qsubl = fevpg - qseva
+ ELSE
+ IF(t_grnd < tfrz)THEN
+ qfros = abs(fevpg)
+ ELSE
+ qsdew = abs(fevpg)
+ ENDIF
+ ENDIF
+
+! ground heat flux
+ fgrnd = sabg + emg*forc_frl &
+ - emg*stefnc*t_icesno_bef(lb)**3*(t_icesno_bef(lb) + 4.*tinc) &
+ - (fseng+fevpg*htvp) &
+ + cpliq * pg_rain * (t_precip - t_icesno(lb)) &
+ + cpice * pg_snow * (t_precip - t_icesno(lb))
+
+! outgoing long-wave radiation from ground
+ olrg = (1.-emg)*forc_frl + emg*stefnc * t_icesno_bef(lb)**4 &
+! for conservation we put the increase of ground longwave to outgoing
+ + 4.*emg*stefnc*t_icesno_bef(lb)**3*tinc
+
+! averaged bulk surface emissivity
+ emis = emg
+
+! radiative temperature
+ trad = (olrg/stefnc)**0.25
+
+!=======================================================================
+! [6] energy balance error
+!=======================================================================
+
+ errore = sabg + forc_frl - olrg - fsena - lfevpa - xmf &
+ + cpliq * pg_rain * (t_precip-t_icesno(lb)) &
+ + cpice * pg_snow * (t_precip-t_icesno(lb))
+ DO j = lb, nl_ice
+ errore = errore - (t_icesno(j)-t_icesno_bef(j))/fact(j)
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF(abs(errore)>.2)THEN
+ write(6,*) 'GLACIER_TEMP.F90 : energy balance violation'
+ write(6,100) errore,sabg,forc_frl,olrg,fsena,lfevpa,xmf,t_precip,t_icesno(lb)
+ STOP
+ ENDIF
+100 format(10(f7.3))
+#endif
+
+ END SUBROUTINE GLACIER_TEMP
+
+
+
+ SUBROUTINE groundfluxes_glacier (zlnd,zsno,hu,ht,hq,&
+ us,vs,tm,qm,rhoair,psrf,&
+ ur,thm,th,thv,t_grnd,qg,dqgdT,htvp,&
+ hpbl,&
+ fsno,cgrnd,cgrndl,cgrnds,&
+ taux,tauy,fsena,fevpa,fseng,fevpg,tref,qref,&
+ z0m,zol,rib,ustar,qstar,tstar,fm,fh,fq)
+
+!=======================================================================
+! this is the main SUBROUTINE to execute the calculation of thermal processes
+! and surface fluxes of land ice (glacier and ice sheet)
+!
+! Original author: Yongjiu Dai and Nan Wei, /05/2014/
+!
+! !REVISIONS:
+! 05/2023, Shaofeng Liu: add option to CALL moninobuk_leddy, the LargeEddy
+! surface turbulence scheme (LZD2022); make a proper update of um.
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpair,vonkar,grav
+ USE MOD_FrictionVelocity
+ USE MOD_Namelist, only: DEF_USE_CBL_HEIGHT
+ USE MOD_TurbulenceLEddy
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ zlnd, &! roughness length for ice [m]
+ zsno, &! roughness length for snow [m]
+
+ ! atmospherical variables and observational height
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ tm, &! temperature at agcm reference height [kelvin] [not used]
+ qm, &! specific humidity at agcm reference height [kg/kg]
+ rhoair, &! density air [kg/m3]
+ psrf, &! atmosphere pressure at the surface [pa] [not used]
+
+ fsno, &! fraction of ground covered by snow
+
+ ur, &! wind speed at reference height [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+
+ t_grnd, &! ground surface temperature [K]
+ qg, &! ground specific humidity [kg/kg]
+ dqgdT, &! d(qg)/dT
+ htvp ! latent heat of vapor of water (or sublimation) [j/kg]
+ real(r8), intent(in) :: &
+ hpbl ! atmospheric boundary layer height [m]
+
+
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fsena, &! sensible heat to atmosphere [W/m2]
+ fevpa, &! evapotranspiration to atmosphere [mm/s]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+ cgrnd, &! deriv. of ice energy flux wrt to ice temp [w/m2/k]
+ cgrndl, &! deriv, of ice sensible heat flux wrt ice temp [w/m2/k]
+ cgrnds, &! deriv of ice latent heat flux wrt ice temp [w/m**2/k]
+ tref, &! 2 m height air temperature [kelvin]
+ qref, &! 2 m height air humidity
+
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile FUNCTION for momentum
+ fh, &! integral of profile FUNCTION for heat
+ fq ! integral of profile FUNCTION for moisture
+
+!-------------------------- Local Variables ----------------------------
+ integer niters, &! maximum number of iterations for surface temperature
+ iter, &! iteration index
+ nmozsgn ! number of times moz changes sign
+
+ real(r8) :: &
+ beta, &! coefficient of convective velocity [-]
+ displax, &! zero-displacement height [m]
+ dth, &! diff of virtual temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ obuold, &! monin-obukhov length from previous iteration
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ raih, &! temporary variable [kg/m2/s]
+ raiw, &! temporary variable [kg/m2/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile FUNCTION for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ um, &! wind speed including the stability effect [m/s]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ zii, &! convective boundary height [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ z0mg, &! roughness length over ground, momentum [m]
+ z0hg, &! roughness length over ground, sensible heat [m]
+ z0qg ! roughness length over ground, latent heat [m]
+
+!-----------------------------------------------------------------------
+! initial roughness length
+ IF(fsno > 0.)THEN
+ ! z0mg = zsno
+ z0mg = 0.002 ! Table 1 of Brock et al., (2006)
+ z0hg = z0mg
+ z0qg = z0mg
+ ELSE
+ ! z0mg = zlnd
+ z0mg = 0.001 ! Table 1 of Brock et al., (2006)
+ z0hg = z0mg
+ z0qg = z0mg
+ ENDIF
+
+! potential temperature at the reference height
+ beta = 1. ! - (in computing W_*)
+ zii = 1000. ! m (pbl height)
+ z0m = z0mg
+
+!-----------------------------------------------------------------------
+! Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+!-----------------------------------------------------------------------
+! Initialization variables
+ nmozsgn = 0
+ obuold = 0.
+
+ dth = thm-t_grnd
+ dqh = qm-qg
+ dthv = dth*(1.+0.61*qm)+0.61*th*dqh
+ zldis = hu-0.
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mg,um,obu)
+
+! Evaluated stability-dependent variables using moz from prior iteration
+ niters=6
+
+ !----------------------------------------------------------------
+ ITERATION : DO iter = 1, niters ! begin stability iteration
+ !----------------------------------------------------------------
+ displax = 0.
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobuk_leddy(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um, hpbl, &
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ELSE
+ CALL moninobuk(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ENDIF
+
+ tstar = vonkar/fh*dth
+ qstar = vonkar/fq*dqh
+
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ thvstar=tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta=zldis*vonkar*grav*thvstar/(ustar**2*thv)
+ IF(zeta >= 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF(zeta >= 0.)THEN
+ um = max(ur,0.1)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ zii = max(5.*hu,hpbl)
+ ENDIF !//TODO: Shaofeng, 2023.05.18
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu < 0.) nmozsgn = nmozsgn+1
+ IF (nmozsgn >= 4) EXIT
+
+ obuold = obu
+
+ !----------------------------------------------------------------
+ ENDDO ITERATION ! END stability iteration
+ !----------------------------------------------------------------
+
+! Get derivative of fluxes with respect to ground temperature
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/fh*ustar)
+ raw = 1./(vonkar/fq*ustar)
+
+ raih = rhoair*cpair/rah
+ raiw = rhoair/raw
+ cgrnds = raih
+ cgrndl = raiw*dqgdT
+ cgrnd = cgrnds + htvp*cgrndl
+
+ zol = zeta
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+! surface fluxes of momentum, sensible and latent
+! using ground temperatures from previous time step
+ taux = -rhoair*us/ram
+ tauy = -rhoair*vs/ram
+ fseng = -raih*dth
+ fevpg = -raiw*dqh
+
+ fsena = fseng
+ fevpa = fevpg
+
+! 2 m height air temperature
+ tref = (thm + vonkar/fh*dth * (fh2m/vonkar - fh/vonkar))
+ qref = ( qm + vonkar/fq*dqh * (fq2m/vonkar - fq/vonkar))
+
+ END SUBROUTINE groundfluxes_glacier
+
+
+
+ SUBROUTINE groundtem_glacier (patchtype,lb,nl_ice,deltim,&
+ capr,cnfac,dz_icesno,z_icesno,zi_icesno,&
+ t_icesno,wice_icesno,wliq_icesno,scv,snowdp,&
+ forc_frl,sabg,sabg_snow_lyr,fseng,fevpg,cgrnd,htvp,emg,&
+ imelt,snofrz,sm,xmf,fact,pg_rain,pg_snow,t_precip)
+
+!=======================================================================
+! SNOW and LAND ICE temperatures
+! o The volumetric heat capacity is calculated as a linear combination
+! in terms of the volumetric fraction of the constituent phases.
+! o The thermal conductivity of snow/ice is computed from the
+! formulation used in SNTHERM (Jordan 1991) and Yen (1981),
+! respectively.
+! o Boundary conditions:
+! F = Rnet - Hg - LEg (top) + HPR, F= 0 (base of the land ice column).
+! o Ice/snow temperature is predicted from heat conduction in 10 ice
+! layers and up to 5 snow layers. The thermal conductivities at the
+! interfaces between two neighbor layers (j, j+1) are derived from an
+! assumption that the flux across the interface is equal to that from
+! the node j to the interface and the flux from the interface to the
+! node j+1. The equation is solved using the Crank-Nicholson method
+! and resulted in a tridiagonal system equation.
+!
+! Phase change (see meltf.F90)
+!
+! Original author: Yongjiu Dai, /05/2014/
+!
+! !REVISIONS:
+! 01/2023, Hua Yuan: account for snow layer absorption (SNICAR) in
+! ground heat flux, temperature and melt calculation.
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_SNICAR
+ USE MOD_Const_Physical, only: stefnc,cpice,cpliq,denh2o,denice,tfrz,tkwat,tkice,tkair
+ USE MOD_PhaseChange
+ USE MOD_Utils
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: patchtype !land patch type (0=soil, 1=urban and built-up,
+ !2=wetland, 3=land ice, 4=land water bodies, 99 = ocean)
+ integer, intent(in) :: lb !lower bound of array
+ integer, intent(in) :: nl_ice !upper bound of array
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: capr !tuning factor to turn first layer T into surface T
+ real(r8), intent(in) :: cnfac !Crank Nicholson factor between 0 and 1
+
+ real(r8), intent(in) :: dz_icesno(lb:nl_ice) !layer thickness [m]
+ real(r8), intent(in) :: z_icesno (lb:nl_ice) !node depth [m]
+ real(r8), intent(in) :: zi_icesno(lb-1:nl_ice) !interface depth [m]
+
+ real(r8), intent(in) :: sabg !solar radiation absorbed by ground [W/m2]
+ real(r8), intent(in) :: forc_frl !atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), intent(in) :: fseng !sensible heat flux from ground [W/m2]
+ real(r8), intent(in) :: fevpg !evaporation heat flux from ground [mm/s]
+ real(r8), intent(in) :: cgrnd !deriv. of ice energy flux wrt to ice temp [W/m2/k]
+ real(r8), intent(in) :: htvp !latent heat of vapor of water (or sublimation) [J/kg]
+ real(r8), intent(in) :: emg !ground emissivity (0.97 for snow,
+ real(r8), intent(in) :: t_precip !snowfall/rainfall temperature [kelvin]
+ real(r8), intent(in) :: pg_rain !rainfall [kg/(m2 s)]
+ real(r8), intent(in) :: pg_snow !snowfall [kg/(m2 s)]
+
+ real(r8), intent(in) :: sabg_snow_lyr (lb:1) !snow layer absorption [W/m-2]
+
+ real(r8), intent(inout) :: t_icesno (lb:nl_ice) !snow and ice temperature [K]
+ real(r8), intent(inout) :: wice_icesno(lb:nl_ice) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_icesno(lb:nl_ice) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv !snow cover, water equivalent [mm, kg/m2]
+ real(r8), intent(inout) :: snowdp !snow depth [m]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change of ground water
+ real(r8), intent(out) :: fact(lb:nl_ice) !used in computing tridiagonal matrix
+ integer, intent(out) :: imelt(lb:nl_ice) !flag for melting or freezing [-]
+
+ real(r8), intent(out) :: snofrz(lb:0) !snow freezing rate (lyr) [kg m-2 s-1]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) rhosnow ! partial density of water (ice + liquid)
+ real(r8) cv(lb:nl_ice) ! heat capacity [J/(m2 K)]
+ real(r8) thk(lb:nl_ice) ! thermal conductivity of layer
+ real(r8) tk(lb:nl_ice) ! thermal conductivity [W/(m K)]
+
+ real(r8) at(lb:nl_ice) !"a" vector for tridiagonal matrix
+ real(r8) bt(lb:nl_ice) !"b" vector for tridiagonal matrix
+ real(r8) ct(lb:nl_ice) !"c" vector for tridiagonal matrix
+ real(r8) rt(lb:nl_ice) !"r" vector for tridiagonal solution
+
+ real(r8) fn (lb:nl_ice) ! heat diffusion through the layer interface [W/m2]
+ real(r8) fn1 (lb:nl_ice) ! heat diffusion through the layer interface [W/m2]
+ real(r8) dzm ! used in computing tridiagonal matrix
+ real(r8) dzp ! used in computing tridiagonal matrix
+
+ real(r8) t_icesno_bef(lb:nl_ice) ! snow/ice temperature before update
+ real(r8) wice_icesno_bef(lb:0) ! ice lens [kg/m2]
+ real(r8) hs ! net energy flux into the surface (w/m2)
+ real(r8) dhsdt ! d(hs)/dT
+ real(r8) brr(lb:nl_ice) ! temporary set
+
+ integer i,j
+
+ real(r8) :: porsl(1:nl_ice) ! not used
+ real(r8) :: psi0 (1:nl_ice) ! not used
+#ifdef Campbell_SOIL_MODEL
+ real(r8) :: bsw(1:nl_ice) ! not used
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8) :: theta_r (1:nl_ice), &
+ alpha_vgm(1:nl_ice), &
+ n_vgm (1:nl_ice), &
+ L_vgm (1:nl_ice), &
+ sc_vgm (1:nl_ice), &
+ fc_vgm (1:nl_ice)
+#endif
+
+!-----------------------------------------------------------------------
+! SNOW and LAND ICE heat capacity
+ cv(1:) = wice_icesno(1:)*cpice + wliq_icesno(1:)*cpliq
+ IF(lb==1 .and. scv>0.) cv(1) = cv(1) + cpice*scv
+
+ IF(lb<=0)THEN
+ cv(:0) = cpliq*wliq_icesno(:0) + cpice*wice_icesno(:0)
+ ENDIF
+
+! SNOW and LAND ICE thermal conductivity [W/(m K)]
+ DO j = lb, nl_ice
+ thk(j) = tkwat
+ IF(t_icesno(j)<=tfrz) thk(j) = 9.828*exp(-0.0057*t_icesno(j))
+ ENDDO
+
+ IF(lb < 1)THEN
+ DO j = lb, 0
+ rhosnow = (wice_icesno(j)+wliq_icesno(j))/dz_icesno(j)
+
+ ! presently option [1] is the default option
+ ! [1] Jordan (1991) pp. 18
+ thk(j) = tkair+(7.75e-5*rhosnow+1.105e-6*rhosnow*rhosnow)*(tkice-tkair)
+
+ ! [2] Sturm et al (1997)
+ ! thk(j) = 0.0138 + 1.01e-3*rhosnow + 3.233e-6*rhosnow**2
+ ! [3] Ostin and Andersson presented in Sturm et al., (1997)
+ ! thk(j) = -0.871e-2 + 0.439e-3*rhosnow + 1.05e-6*rhosnow**2
+ ! [4] Jansson(1901) presented in Sturm et al. (1997)
+ ! thk(j) = 0.0293 + 0.7953e-3*rhosnow + 1.512e-12*rhosnow**2
+ ! [5] Douville et al., (1995)
+ ! thk(j) = 2.2*(rhosnow/denice)**1.88
+ ! [6] van Dusen (1992) presented in Sturm et al. (1997)
+ ! thk(j) = 0.021 + 0.42e-3*rhosnow + 0.22e-6*rhosnow**2
+ ENDDO
+ ENDIF
+
+! Thermal conductivity at the layer interface
+ DO j = lb, nl_ice-1
+
+! the following consideration is try to avoid the snow conductivity
+! to be dominant in the thermal conductivity of the interface.
+! Because when the distance of bottom snow node to the interface
+! is larger than that of interface to top ice node,
+! the snow thermal conductivity will be dominant, and the result is that
+! lees heat transfer between snow and ice
+ IF((j==0) .and. (z_icesno(j+1)-zi_icesno(j)=1)THEN
+ gwat = pg_rain + sm - qseva
+ ELSE
+ CALL snowwater (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_icesno(lb:0),wice_icesno(lb:0),wliq_icesno(lb:0),gwat)
+ ENDIF
+
+!=======================================================================
+! [2] surface runoff and infiltration
+!=======================================================================
+
+ IF(snl<0)THEN
+ ! Compaction rate for snow
+ ! Natural compaction and metamorphosis. The compaction rate
+ ! is recalculated for every new timestep
+ lb = snl + 1 ! lower bound of array
+ CALL snowcompaction (lb,deltim,&
+ imelt(lb:0),fiold(lb:0),t_icesno(lb:0),&
+ wliq_icesno(lb:0),wice_icesno(lb:0),forc_us,forc_vs,dz_icesno(lb:0))
+
+ ! Combine thin snow elements
+ lb = maxsnl + 1
+ CALL snowlayerscombine (lb,snl,&
+ z_icesno(lb:1),dz_icesno(lb:1),zi_icesno(lb-1:1),&
+ wliq_icesno(lb:1),wice_icesno(lb:1),t_icesno(lb:1),scv,snowdp)
+
+ ! Divide thick snow elements
+ IF(snl<0) &
+ CALL snowlayersdivide (lb,snl,&
+ z_icesno(lb:0),dz_icesno(lb:0),zi_icesno(lb-1:0),&
+ wliq_icesno(lb:0),wice_icesno(lb:0),t_icesno(lb:0))
+ ENDIF
+
+ IF (snl > maxsnl) THEN
+ wice_icesno(maxsnl+1:snl) = 0.
+ wliq_icesno(maxsnl+1:snl) = 0.
+ t_icesno (maxsnl+1:snl) = 0.
+ z_icesno (maxsnl+1:snl) = 0.
+ dz_icesno (maxsnl+1:snl) = 0.
+ ENDIF
+
+ IF(lb >= 1)THEN
+ wliq_icesno(1) = max(1.e-8, wliq_icesno(1) + qsdew * deltim)
+ wice_icesno(1) = max(1.e-8, wice_icesno(1) + (qfros-qsubl) * deltim)
+ ENDIF
+
+ END SUBROUTINE GLACIER_WATER
+
+
+ SUBROUTINE GLACIER_WATER_snicar ( nl_ice ,maxsnl ,deltim ,&
+ z_icesno ,dz_icesno ,zi_icesno ,t_icesno ,&
+ wliq_icesno ,wice_icesno ,pg_rain ,pg_snow ,&
+ sm ,scv ,snowdp ,imelt ,&
+ fiold ,snl ,qseva ,qsdew ,&
+ qsubl ,qfros ,gwat ,ssi ,&
+ wimp ,forc_us ,forc_vs ,&
+ ! SNICAR
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 )
+
+!=======================================================================
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o, tfrz
+ USE MOD_SnowLayersCombineDivide
+ USE MOD_SoilSnowHydrology
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: nl_ice ! upper bound of array
+ integer, intent(in) :: maxsnl ! maximum number of snow layers
+
+ real(r8), intent(in) :: &
+ deltim , &! time step (s)
+ ssi , &! irreducible water saturation of snow
+ wimp , &! water impermeable IF porosity less than wimp
+ pg_rain , &! rainfall (mm h2o/s)
+ pg_snow , &! snowfall (mm h2o/s)
+ sm , &! snow melt (mm h2o/s)
+ qseva , &! ground surface evaporation rate (mm h2o/s)
+ qsdew , &! ground surface dew formation (mm h2o /s) [+]
+ qsubl , &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros , &! surface dew added to snow pack (mm h2o /s) [+]
+ fiold(maxsnl+1:nl_ice) ! fraction of ice relative to the total water
+
+ ! flag for: melting=1, freezing=2, nothing happened=0
+ integer, intent(in) :: imelt(maxsnl+1:nl_ice)
+ integer, intent(inout) :: snl ! lower bound of array
+
+ real(r8), intent(inout) :: &
+ z_icesno (maxsnl+1:nl_ice) , &! layer depth (m)
+ dz_icesno (maxsnl+1:nl_ice) , &! layer thickness (m)
+ zi_icesno (maxsnl :nl_ice) , &! interface level below a "z" level (m)
+ t_icesno (maxsnl+1:nl_ice) , &! snow/ice skin temperature (K)
+ wice_icesno(maxsnl+1:nl_ice) , &! ice lens (kg/m2)
+ wliq_icesno(maxsnl+1:nl_ice) , &! liquid water (kg/m2)
+ scv , &! snow mass (kg/m2)
+ snowdp ! snow depth (m)
+
+ real(r8), intent(out) :: &
+ gwat ! net water input from top (mm/s)
+
+ real(r8), intent(in) :: forc_us
+ real(r8), intent(in) :: forc_vs
+
+! Aerosol Fluxes (Jan. 07, 2023)
+ ! aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+ real(r8), intent(in) :: forc_aer ( 14 )
+
+ real(r8), intent(inout) :: &
+ mss_bcpho (maxsnl+1:0), &! mass of hydrophobic BC in snow (lyr) [kg]
+ mss_bcphi (maxsnl+1:0), &! mass of hydrophillic BC in snow (lyr) [kg]
+ mss_ocpho (maxsnl+1:0), &! mass of hydrophobic OC in snow (lyr) [kg]
+ mss_ocphi (maxsnl+1:0), &! mass of hydrophillic OC in snow (lyr) [kg]
+ mss_dst1 (maxsnl+1:0), &! mass of dust species 1 in snow (lyr) [kg]
+ mss_dst2 (maxsnl+1:0), &! mass of dust species 2 in snow (lyr) [kg]
+ mss_dst3 (maxsnl+1:0), &! mass of dust species 3 in snow (lyr) [kg]
+ mss_dst4 (maxsnl+1:0) ! mass of dust species 4 in snow (lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+
+!-------------------------- Local Variables ----------------------------
+
+ integer lb, j
+
+!=======================================================================
+! [1] update the liquid water within snow layer and the water onto the
+! ice surface
+!
+! Snow melting is treated in a realistic fashion, with meltwater
+! percolating downward through snow layers as long as the snow is
+! unsaturated. Once the underlying snow is saturated, any additional
+! meltwater runs off. When glacier ice melts, however, the meltwater is
+! assumed to remain in place until it refreezes. In warm parts of the
+! ice sheet, the meltwater does not refreeze, but stays in place
+! indefinitely.
+!=======================================================================
+
+ lb = snl + 1
+ IF (lb>=1)THEN
+ gwat = pg_rain + sm - qseva
+ ELSE
+ CALL snowwater_snicar (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_icesno(lb:0),wice_icesno(lb:0),wliq_icesno(lb:0),gwat,&
+ forc_aer,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ENDIF
+
+!=======================================================================
+! [2] surface runoff and infiltration
+!=======================================================================
+
+ IF(snl<0)THEN
+ ! Compaction rate for snow
+ ! Natural compaction and metamorphosis. The compaction rate
+ ! is recalculated for every new timestep
+ lb = snl + 1 ! lower bound of array
+ CALL snowcompaction (lb,deltim,&
+ imelt(lb:0),fiold(lb:0),t_icesno(lb:0),&
+ wliq_icesno(lb:0),wice_icesno(lb:0),forc_us,forc_vs,dz_icesno(lb:0))
+
+ ! Combine thin snow elements
+ lb = maxsnl + 1
+ CALL snowlayerscombine_snicar (lb,snl,&
+ z_icesno(lb:1),dz_icesno(lb:1),zi_icesno(lb-1:1),&
+ wliq_icesno(lb:1),wice_icesno(lb:1),t_icesno(lb:1),scv,snowdp,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+
+ ! Divide thick snow elements
+ IF(snl<0) &
+ CALL snowlayersdivide_snicar (lb,snl,&
+ z_icesno(lb:0),dz_icesno(lb:0),zi_icesno(lb-1:0),&
+ wliq_icesno(lb:0),wice_icesno(lb:0),t_icesno(lb:0),&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ENDIF
+
+ IF (snl > maxsnl) THEN
+ wice_icesno(maxsnl+1:snl) = 0.
+ wliq_icesno(maxsnl+1:snl) = 0.
+ t_icesno (maxsnl+1:snl) = 0.
+ z_icesno (maxsnl+1:snl) = 0.
+ dz_icesno (maxsnl+1:snl) = 0.
+ ENDIF
+
+ IF(lb >= 1)THEN
+ wliq_icesno(1) = max(1.e-8, wliq_icesno(1) + qsdew * deltim)
+ wice_icesno(1) = max(1.e-8, wice_icesno(1) + (qfros-qsubl) * deltim)
+ ENDIF
+
+ END SUBROUTINE GLACIER_WATER_snicar
+
+END MODULE MOD_Glacier
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_GroundFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_GroundFluxes.F90
new file mode 100644
index 0000000000..0aad77fe8e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_GroundFluxes.F90
@@ -0,0 +1,264 @@
+MODULE MOD_GroundFluxes
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: GroundFluxes
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE GroundFluxes (zlnd, zsno, hu, ht, hq, hpbl, &
+ us, vs, tm, qm, rhoair, psrf, &
+ ur, thm, th, thv, t_grnd, qg, rss, dqgdT, htvp, &
+ fsno, cgrnd, cgrndl, cgrnds, &
+ t_soil, t_snow, q_soil, q_snow, &
+ taux, tauy, fseng, fseng_soil, fseng_snow, &
+ fevpg, fevpg_soil, fevpg_snow, tref, qref, &
+ z0m, z0hg, zol, rib, ustar, qstar, tstar, fm, fh, fq)
+
+!-----------------------------------------------------------------------
+! This is the main SUBROUTINE to execute the calculation of thermal
+! processes and surface fluxes
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002
+!
+! !REVISIONS:
+! 09/2019, Hua Yuan: removed sigf to be consistent with PFT runs, removed
+! fsena, fevpa, renamed z0ma to z0m.
+!
+! 05/2023, Shaofeng Liu: add option to call moninobuk_leddy, the LargeEddy
+! surface turbulence scheme (LZD2022); make a proper update of um.
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpair,vonkar,grav
+ USE MOD_FrictionVelocity
+ USE mod_namelist, only: DEF_USE_CBL_HEIGHT,DEF_RSS_SCHEME
+ USE MOD_TurbulenceLEddy
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+
+ ! atmospherical variables and observational height
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ hpbl, &! atmospheric boundary layer height [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ tm, &! temperature at agcm reference height [kelvin] [not used]
+ qm, &! specific humidity at agcm reference height [kg/kg]
+ rhoair, &! density air [kg/m3]
+ psrf, &! atmosphere pressure at the surface [pa] [not used]
+
+ fsno, &! fraction of ground covered by snow
+
+ ur, &! wind speed at reference height [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+
+ t_grnd, &! ground surface temperature [K]
+ t_soil, &! ground soil temperature [K]
+ t_snow, &! ground snow temperature [K]
+ qg, &! ground specific humidity [kg/kg]
+ q_soil, &! ground soil specific humidity [kg/kg]
+ q_snow, &! ground snow specific humidity [kg/kg]
+ dqgdT, &! d(qg)/dT
+ rss, &! soil surface resistance for evaporation [s/m]
+ htvp ! latent heat of vapor of water (or sublimation) [j/kg]
+
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fseng_soil,&! sensible heat flux from ground soil [W/m2]
+ fseng_snow,&! sensible heat flux from ground snow [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+ fevpg_soil,&! evaporation heat flux from ground soil [mm/s]
+ fevpg_snow,&! evaporation heat flux from ground snow [mm/s]
+ cgrnd, &! deriv. of soil energy flux wrt to soil temp [w/m2/k]
+ cgrndl, &! deriv, of soil sensible heat flux wrt soil temp [w/m2/k]
+ cgrnds, &! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+ tref, &! 2 m height air temperature [kelvin]
+ qref, &! 2 m height air humidity
+
+ z0m, &! effective roughness [m]
+ z0hg, &! roughness length over ground, sensible heat [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile FUNCTION for momentum
+ fh, &! integral of profile FUNCTION for heat
+ fq ! integral of profile FUNCTION for moisture
+
+!-------------------------- Local Variables ----------------------------
+ integer niters, &! maximum number of iterations for surface temperature
+ iter, &! iteration index
+ nmozsgn ! number of times moz changes sign
+
+ real(r8) :: &
+ beta, &! coefficient of convective velocity [-]
+ displax, &! zero-displacement height [m]
+ dth, &! diff of virtual temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ obuold, &! monin-obukhov length from previous iteration
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ raih, &! temporary variable [kg/m2/s]
+ raiw, &! temporary variable [kg/m2/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile FUNCTION for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ um, &! wind speed including the stability effect [m/s]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ zii, &! convective boundary height [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ z0mg, &! roughness length over ground, momentum [m]
+ z0qg ! roughness length over ground, latent heat [m]
+
+!-----------------------------------------------------------------------
+ ! initial roughness length
+ ! 09/2019, yuan: change to a combination of zlnd and zsno
+ z0mg = (1.-fsno)*zlnd + fsno*zsno
+ z0hg = z0mg
+ z0qg = z0mg
+
+ ! potential temperature at the reference height
+ beta = 1. ! - (in computing W_*)
+ zii = 1000. ! m (pbl height)
+ z0m = z0mg
+
+ !-----------------------------------------------------------------------
+ ! Compute sensible and latent fluxes and their derivatives with respect
+ ! to ground temperature using ground temperatures from previous time step.
+ !-----------------------------------------------------------------------
+ ! Initialization variables
+ nmozsgn = 0
+ obuold = 0.
+
+ dth = thm-t_grnd
+ dqh = qm-qg
+ dthv = dth*(1.+0.61*qm)+0.61*th*dqh
+ zldis = hu-0.
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mg,um,obu)
+
+ ! Evaluated stability-dependent variables using moz from prior iteration
+ niters=6
+
+ !----------------------------------------------------------------
+ ITERATION : DO iter = 1, niters ! begin stability iteration
+ !----------------------------------------------------------------
+ displax = 0.
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobuk_leddy(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um,hpbl, &
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ELSE
+ CALL moninobuk(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ENDIF
+
+ tstar = vonkar/fh*dth
+ qstar = vonkar/fq*dqh
+
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ ! 2023.04.06, weinan
+ !thvstar=tstar+0.61*th*qstar
+ thvstar=tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta=zldis*vonkar*grav*thvstar/(ustar**2*thv)
+ IF(zeta >= 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF(zeta >= 0.)THEN
+ um = max(ur,0.1)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ zii = max(5.*hu,hpbl)
+ ENDIF !//TODO: Shaofeng, 2023.05.18
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu < 0.) nmozsgn = nmozsgn+1
+ IF (nmozsgn >= 4) EXIT
+
+ obuold = obu
+
+ !----------------------------------------------------------------
+ ENDDO ITERATION ! END stability iteration
+ !----------------------------------------------------------------
+
+ ! Get derivative of fluxes with respect to ground temperature
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/fh*ustar)
+ raw = 1./(vonkar/fq*ustar)
+
+ raih = rhoair*cpair/rah
+
+ ! 08/23/2019, yuan: add soil surface resistance (rss)
+ IF (dqh > 0.) THEN
+ raiw = rhoair/raw !dew case. assume no soil resistance
+ ELSE
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ raiw = rss*rhoair/raw
+ ELSE
+ raiw = rhoair/(raw+rss)
+ ENDIF
+ ENDIF
+
+ cgrnds = raih
+ cgrndl = raiw*dqgdT
+ cgrnd = cgrnds + htvp*cgrndl
+
+ zol = zeta
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+ ! surface fluxes of momentum, sensible and latent
+ ! using ground temperatures from previous time step
+ taux = -rhoair*us/ram
+ tauy = -rhoair*vs/ram
+ fseng = -raih*dth
+ fevpg = -raiw*dqh
+
+ fseng_soil = -raih * (thm - t_soil)
+ fseng_snow = -raih * (thm - t_snow)
+ fevpg_soil = -raiw * ( qm - q_soil)
+ fevpg_snow = -raiw * ( qm - q_snow)
+
+ ! 2 m height air temperature
+ tref = thm + vonkar/fh*dth * (fh2m/vonkar - fh/vonkar)
+ qref = qm + vonkar/fq*dqh * (fq2m/vonkar - fq/vonkar)
+
+ END SUBROUTINE GroundFluxes
+
+END MODULE MOD_GroundFluxes
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_GroundTemperature.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_GroundTemperature.F90
new file mode 100644
index 0000000000..bf41b8b68b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_GroundTemperature.F90
@@ -0,0 +1,447 @@
+#include
+
+MODULE MOD_GroundTemperature
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: GroundTemperature
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE GroundTemperature (patchtype,is_dry_lake,lb,nl_soil,deltim,&
+ capr,cnfac,vf_quartz,vf_gravels,vf_om,vf_sand,wf_gravels,wf_sand,&
+ porsl,psi0,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm,&
+ sc_vgm , fc_vgm,&
+#endif
+ csol,k_solids,dksatu,dksatf,dkdry,&
+ BA_alpha,BA_beta,&
+ sigf,dz_soisno,z_soisno,zi_soisno,&
+ t_soisno,t_grnd,t_soil,t_snow,wice_soisno,wliq_soisno,scv,snowdp,fsno,&
+ frl,dlrad,sabg,sabg_soil,sabg_snow,sabg_snow_lyr,&
+ fseng,fseng_soil,fseng_snow,fevpg,fevpg_soil,fevpg_snow,cgrnd,htvp,emg,&
+ imelt,snofrz,sm,xmf,fact,pg_rain,pg_snow,t_precip)
+
+!=======================================================================
+! Snow and soil temperatures
+! o The volumetric heat capacity is calculated as a linear combination
+! in terms of the volumetric fraction of the constituent phases.
+! o The thermal conductivity of soil is computed from
+! the algorithm of Johansen (as reported by Farouki 1981), and of snow
+! is from the formulation used in SNTHERM (Jordan 1991).
+! o Boundary conditions:
+! F = Rnet - Hg - LEg + Hpr(top), F= 0 (base of the soil column).
+! o Soil / snow temperature is predicted from heat conduction
+! in 10 soil layers and up to 5 snow layers. The thermal
+! conductivities at the interfaces between two neighbor layers (j,
+! j+1) are derived from an assumption that the flux across the
+! interface is equal to that from the node j to the interface and the
+! flux from the interface to the node j+1. The equation is solved
+! using the Crank-Nicholson method and resulted in a tridiagonal
+! system equation.
+!
+! Phase change (see meltf.F90)
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002; 05/2018
+!
+! !REVISIONS:
+! 07/2017, Nan Wei: interaction btw prec and land surface
+! 01/2019, Nan Wei: USE the new version of soil thermal parameters to
+! calculate soil temperature
+! 01/2023, Hua Yuan: modified ground heat flux, temperature and meltf
+! calculation for SNICAR model
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: stefnc,denh2o,denice,tfrz,cpice,cpliq,tkwat,tkice,tkair
+ USE MOD_Namelist, only: DEF_USE_SNICAR, DEF_SPLIT_SOILSNOW
+ USE MOD_PhaseChange
+ USE MOD_SoilThermalParameters
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: lb !lower bound of array
+ integer, intent(in) :: nl_soil !upper bound of array
+ integer, intent(in) :: patchtype !land patch type
+ !(0=soil,1=urban or built-up,2=wetland,
+ !3=land ice, 4=deep lake, 5=shallow lake)
+ logical, intent(in) :: is_dry_lake
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: capr !tuning factor
+ !to turn first layer T into surface T
+ real(r8), intent(in) :: cnfac !Crank Nicholson factor between 0 and 1
+
+ real(r8), intent(in) :: vf_quartz (1:nl_soil) !volumetric fraction of quartz in mineral soil
+ real(r8), intent(in) :: vf_gravels(1:nl_soil) !volumetric fraction of gravels
+ real(r8), intent(in) :: vf_om (1:nl_soil) !volumetric fraction of organic matter
+ real(r8), intent(in) :: vf_sand (1:nl_soil) !volumetric fraction of sand
+ real(r8), intent(in) :: wf_gravels(1:nl_soil) !gravimetric fraction of gravels
+ real(r8), intent(in) :: wf_sand (1:nl_soil) !gravimetric fraction of sand
+
+ real(r8), intent(in) :: porsl(1:nl_soil) !soil porosity [-]
+ real(r8), intent(in) :: psi0 (1:nl_soil) !soil water suction, negative potential [mm]
+#ifdef Campbell_SOIL_MODEL
+ real(r8), intent(in) :: bsw(1:nl_soil) !clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), intent(in) :: theta_r (1:nl_soil), & !
+ alpha_vgm(1:nl_soil), & !
+ n_vgm (1:nl_soil), & !
+ L_vgm (1:nl_soil), & !
+ sc_vgm (1:nl_soil), & !
+ fc_vgm (1:nl_soil)
+#endif
+ real(r8), intent(in) :: csol (1:nl_soil) !heat capacity of soil solids [J/(m3 K)]
+ real(r8), intent(in) :: k_solids (1:nl_soil) !thermal cond. of minerals soil [W/m-K]
+ real(r8), intent(in) :: dksatu (1:nl_soil) !thermal cond. of sat. unfrozen soil [W/m-K]
+ real(r8), intent(in) :: dksatf (1:nl_soil) !thermal cond. of sat. frozen soil [W/m-K]
+ real(r8), intent(in) :: dkdry (1:nl_soil) !thermal cond. of dry soil [W/m-K]
+ real(r8), intent(in) :: BA_alpha (1:nl_soil) !alpha in Balland and Arp(2005) thermal cond.
+ real(r8), intent(in) :: BA_beta (1:nl_soil) !beta in Balland and Arp(2005) thermal cond.
+
+ real(r8), intent(in) :: sigf !frac. of veg, excluding snow-covered veg [-]
+ real(r8), intent(in) :: dz_soisno(lb:nl_soil) !layer thickness [m]
+ real(r8), intent(in) :: z_soisno (lb:nl_soil) !node depth [m]
+ real(r8), intent(in) :: zi_soisno(lb-1:nl_soil) !interface depth [m]
+
+ real(r8), intent(in) :: sabg_snow_lyr(lb:1) !snow layer absorption [W/m-2]
+
+ real(r8), intent(in) :: t_grnd !ground surface temperature [K]
+ real(r8), intent(in) :: t_soil !ground soil temperature [K]
+ real(r8), intent(in) :: t_snow !ground snow temperature [K]
+ real(r8), intent(in) :: sabg !solar radiation absorbed by ground [W/m2]
+ real(r8), intent(in) :: sabg_soil !solar radiation absorbed by soil [W/m2]
+ real(r8), intent(in) :: sabg_snow !solar radiation absorbed by snow [W/m2]
+ real(r8), intent(in) :: frl !atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), intent(in) :: dlrad !downward longwave radiation blow the canopy [W/m2]
+ real(r8), intent(in) :: fseng !sensible heat flux from ground [W/m2]
+ real(r8), intent(in) :: fseng_soil !sensible heat flux from ground soil [W/m2]
+ real(r8), intent(in) :: fseng_snow !sensible heat flux from ground snow [W/m2]
+ real(r8), intent(in) :: fevpg !evaporation heat flux from ground [mm/s]
+ real(r8), intent(in) :: fevpg_soil !evaporation heat flux from ground soil [mm/s]
+ real(r8), intent(in) :: fevpg_snow !evaporation heat flux from ground snow [mm/s]
+ real(r8), intent(in) :: cgrnd !deriv. of soil energy flux wrt to soil temp [w/m2/k]
+ real(r8), intent(in) :: htvp !latent heat of vapor of water (or sublimation) [j/kg]
+ real(r8), intent(in) :: emg !ground emissivity (0.97 for snow, 0.96 for soil)
+ real(r8), intent(in) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(in) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(in) :: t_precip !snowfall/rainfall temperature [kelvin]
+
+ real(r8), intent(inout) :: t_soisno (lb:nl_soil) !soil temperature [K]
+ real(r8), intent(inout) :: wice_soisno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:nl_soil) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv !snow cover, water equivalent [mm, kg/m2]
+ real(r8), intent(inout) :: snowdp !snow depth [m]
+ real(r8), intent(in) :: fsno !snow fractional cover [-]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change of ground water
+ real(r8), intent(out) :: fact (lb:nl_soil) !used in computing tridiagonal matrix
+ integer, intent(out) :: imelt(lb:nl_soil) !flag for melting or freezing [-]
+
+ real(r8), intent(out) :: snofrz(lb:0) !snow freezing rate (lyr) [kg m-2 s-1]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) cv (lb:nl_soil) !heat capacity [J/(m2 K)]
+ real(r8) tk (lb:nl_soil) !thermal conductivity [W/(m K)]
+ real(r8) hcap(1:nl_soil) !J/(m3 K)
+ real(r8) thk(lb:nl_soil) !W/(m K)
+
+ real(r8) at (lb:nl_soil) !"a" vector for tridiagonal matrix
+ real(r8) bt (lb:nl_soil) !"b" vector for tridiagonal matrix
+ real(r8) ct (lb:nl_soil) !"c" vector for tridiagonal matrix
+ real(r8) rt (lb:nl_soil) !"r" vector for tridiagonal solution
+
+ real(r8) fn (lb:nl_soil) !heat diffusion through the layer interface [W/m2]
+ real(r8) fn1(lb:nl_soil) !heat diffusion through the layer interface [W/m2]
+ real(r8) dzm !used in computing tridiagonal matrix
+ real(r8) dzp !used in computing tridiagonal matrix
+
+ real(r8) t_soisno_bef(lb:nl_soil) !soil/snow temperature before update
+ real(r8) wice_soisno_bef(lb:0) !ice lens [kg/m2]
+ real(r8) hs !net energy flux into the surface (w/m2)
+ real(r8) hs_soil !net energy flux into the surface soil (w/m2)
+ real(r8) hs_snow !net energy flux into the surface snow (w/m2)
+ real(r8) dhsdT !d(hs)/dT
+ real(r8) brr (lb:nl_soil) !temporary set
+ real(r8) vf_water(1:nl_soil) !volumetric fraction liquid water within soil
+ real(r8) vf_ice (1:nl_soil) !volumetric fraction ice lens within soil
+ real(r8) rhosnow !partial density of water (ice + liquid)
+ integer i,j
+
+!-----------------------------------------------------------------------
+! soil ground and wetland heat capacity
+ DO i = 1, nl_soil
+ vf_water(i) = wliq_soisno(i)/(dz_soisno(i)*denh2o)
+ vf_ice(i) = wice_soisno(i)/(dz_soisno(i)*denice)
+ CALL soil_hcap_cond(vf_gravels(i),vf_om(i),vf_sand(i),porsl(i),&
+ wf_gravels(i),wf_sand(i),k_solids(i),&
+ csol(i),dkdry(i),dksatu(i),dksatf(i),&
+ BA_alpha(i),BA_beta(i),&
+ t_soisno(i),vf_water(i),vf_ice(i),hcap(i),thk(i))
+ cv(i) = hcap(i)*dz_soisno(i)
+ ENDDO
+ IF(lb==1 .and. scv>0.) cv(1) = cv(1) + cpice*scv
+
+! Snow heat capacity
+ IF(lb <= 0)THEN
+ cv(:0) = cpliq*wliq_soisno(:0) + cpice*wice_soisno(:0)
+ ENDIF
+
+! Snow thermal conductivity
+ IF(lb <= 0)THEN
+ DO i = lb, 0
+ rhosnow = (wice_soisno(i)+wliq_soisno(i))/dz_soisno(i)
+
+ ! presently option [1] is the default option
+ ! [1] Jordan (1991) pp. 18
+ thk(i) = tkair+(7.75e-5*rhosnow+1.105e-6*rhosnow*rhosnow)*(tkice-tkair)
+
+ ! [2] Sturm et al (1997)
+ ! thk(i) = 0.0138 + 1.01e-3*rhosnow + 3.233e-6*rhosnow**2
+ ! [3] Ostin and Andersson presented in Sturm et al., (1997)
+ ! thk(i) = -0.871e-2 + 0.439e-3*rhosnow + 1.05e-6*rhosnow**2
+ ! [4] Jansson(1901) presented in Sturm et al. (1997)
+ ! thk(i) = 0.0293 + 0.7953e-3*rhosnow + 1.512e-12*rhosnow**2
+ ! [5] Douville et al., (1995)
+ ! thk(i) = 2.2*(rhosnow/denice)**1.88
+ ! [6] van Dusen (1992) presented in Sturm et al. (1997)
+ ! thk(i) = 0.021 + 0.42e-3*rhosnow + 0.22e-6*rhosnow**2
+
+ ENDDO
+ ENDIF
+
+! Thermal conductivity at the layer interface
+ DO i = lb, nl_soil-1
+
+! the following consideration is try to avoid the snow conductivity
+! to be dominant in the thermal conductivity of the interface.
+! Because when the distance of bottom snow node to the interface
+! is larger than that of interface to top soil node,
+! the snow thermal conductivity will be dominant, and the result is that
+! lees heat transfer between snow and soil
+ IF((i==0) .and. (z_soisno(i+1)-zi_soisno(i)100% cover
+ IF (DEF_USE_SNICAR .and. lb < 1) THEN
+ hs = sabg_snow_lyr(lb) + sabg_soil + dlrad*emg &
+ - (fseng+fevpg*htvp) &
+ + cpliq*pg_rain*(t_precip-t_grnd) &
+ + cpice*pg_snow*(t_precip-t_grnd)
+ ELSE
+ hs = sabg + dlrad*emg &
+ - (fseng+fevpg*htvp) &
+ + cpliq*pg_rain*(t_precip-t_grnd) &
+ + cpice*pg_snow*(t_precip-t_grnd)
+ ENDIF
+
+ IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ hs = hs - emg*stefnc*t_grnd**4
+ ELSE
+ ! 03/08/2020, yuan: separate soil and snow
+ hs = hs - fsno*emg*stefnc*t_snow**4 &
+ - (1.-fsno)*emg*stefnc*t_soil**4
+
+ ! 03/08/2020, yuan: calculate hs_soil, hs_snow for
+ ! soil/snow fractional cover separately.
+ hs_soil = dlrad*emg &
+ - emg*stefnc*t_soil**4 &
+ - (fseng_soil+fevpg_soil*htvp) &
+ + cpliq*pg_rain*(t_precip-t_soil) &
+ + cpice*pg_snow*(t_precip-t_soil)
+
+ hs_soil = hs_soil*(1.-fsno) + sabg_soil
+
+ hs_snow = dlrad*emg &
+ - emg*stefnc*t_snow**4 &
+ - (fseng_snow+fevpg_snow*htvp) &
+ + cpliq*pg_rain*(t_precip-t_snow) &
+ + cpice*pg_snow*(t_precip-t_snow)
+
+ IF (DEF_USE_SNICAR .and. lb < 1) THEN
+ hs_snow = hs_snow*fsno + sabg_snow_lyr(lb)
+ ELSE
+ hs_snow = hs_snow*fsno + sabg_snow
+ ENDIF
+
+ dhsdT = -cgrnd - 4.*emg*stefnc*t_grnd**3 - cpliq*pg_rain - cpice*pg_snow
+
+ IF (abs(sabg_soil+sabg_snow-sabg)>1.e-6 .or. abs(hs_soil+hs_snow-hs)>1.e-6) THEN
+ print *, "MOD_GroundTemperature.F90: Error in spliting soil and snow surface!"
+ print *, "sabg:", sabg, "sabg_soil:", sabg_soil, "sabg_snow", sabg_snow
+ print *, "hs", hs, "hs_soil", hs_soil, "hs_snow:", hs_snow, "fsno:", fsno
+ print *, "hs_soil+hs_snow", hs_soil+hs_snow, "sabg_soil+sabg_snow:", sabg_soil+sabg_snow
+ print *, "lb:", lb, "sabg_snow_lyr:", sabg_snow_lyr
+ CALL CoLM_stop()
+ ENDIF
+ ENDIF
+
+ dhsdT = -cgrnd - 4.*emg*stefnc*t_grnd**3 - cpliq*pg_rain - cpice*pg_snow
+ t_soisno_bef(lb:) = t_soisno(lb:)
+
+ j = lb
+ fact(j) = deltim / cv(j) * dz_soisno(j) &
+ / (0.5*(z_soisno(j)-zi_soisno(j-1)+capr*(z_soisno(j+1)-zi_soisno(j-1))))
+
+ DO j = lb + 1, nl_soil
+ fact(j) = deltim/cv(j)
+ ENDDO
+
+ DO j = lb, nl_soil - 1
+ fn(j) = tk(j)*(t_soisno(j+1)-t_soisno(j))/(z_soisno(j+1)-z_soisno(j))
+ ENDDO
+ fn(nl_soil) = 0.
+
+! set up vector r and vectors a, b, c that define tridiagonal matrix
+ j = lb
+ dzp = z_soisno(j+1)-z_soisno(j)
+ at(j) = 0.
+ ct(j) = -(1.-cnfac)*fact(j)*tk(j)/dzp
+
+ ! the first layer
+ IF (j<1 .and. DEF_SPLIT_SOILSNOW) THEN ! snow covered and split soil and snow
+ bt(j) = 1+(1.-cnfac)*fact(j)*tk(j)/dzp-fact(j)*fsno*dhsdT
+ rt(j) = t_soisno(j) +fact(j)*( hs_snow - fsno*dhsdT*t_soisno(j) + cnfac*fn(j) )
+ ELSE ! not a snow layer or don't split soil and snow
+ bt(j) = 1+(1.-cnfac)*fact(j)*tk(j)/dzp-fact(j)*dhsdT
+ rt(j) = t_soisno(j) +fact(j)*( hs - dhsdT*t_soisno(j) + cnfac*fn(j) )
+ ENDIF
+
+ DO j = lb + 1, nl_soil - 1
+
+ dzm = (z_soisno(j)-z_soisno(j-1))
+ dzp = (z_soisno(j+1)-z_soisno(j))
+
+ IF (j < 1) THEN ! snow layer
+ at(j) = - (1.-cnfac)*fact(j)* tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm)
+ ct(j) = - (1.-cnfac)*fact(j)* tk(j)/dzp
+ IF (DEF_USE_SNICAR) THEN
+ rt(j) = t_soisno(j) + fact(j)*sabg_snow_lyr(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ELSE
+ rt(j) = t_soisno(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ENDIF
+ ENDIF
+
+ IF (j == 1) THEN ! the first soil layer
+ at(j) = - (1.-cnfac)*fact(j)* tk(j-1)/dzm
+ ct(j) = - (1.-cnfac)*fact(j)* tk(j)/dzp
+ IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm)
+ rt(j) = t_soisno(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ELSE
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm) &
+ - (1.-fsno)*dhsdT*fact(j)
+ rt(j) = t_soisno(j) + cnfac*fact(j)*( fn(j) - fn(j-1) ) &
+ + fact(j)*( hs_soil - (1.-fsno)*dhsdT*t_soisno(j) )
+ ENDIF
+ ENDIF
+
+ IF (j > 1) THEN ! inner soil layer
+ at(j) = - (1.-cnfac)*fact(j)* tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm)
+ ct(j) = - (1.-cnfac)*fact(j)* tk(j)/dzp
+ rt(j) = t_soisno(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ENDIF
+
+ ENDDO
+
+ j = nl_soil
+ dzm = (z_soisno(j)-z_soisno(j-1))
+ at(j) = - (1.-cnfac)*fact(j)*tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*tk(j-1)/dzm
+ ct(j) = 0.
+ rt(j) = t_soisno(j) - cnfac*fact(j)*fn(j-1)
+
+! solve for t_soisno
+ i = size(at)
+ CALL tridia (i ,at ,bt ,ct ,rt ,t_soisno)
+!=======================================================================
+! melting or freezing
+!=======================================================================
+
+ DO j = lb, nl_soil - 1
+ fn1(j) = tk(j)*(t_soisno(j+1)-t_soisno(j))/(z_soisno(j+1)-z_soisno(j))
+ ENDDO
+ fn1(nl_soil) = 0.
+
+ j = lb
+ brr(j) = cnfac*fn(j) + (1.-cnfac)*fn1(j)
+
+ DO j = lb + 1, nl_soil
+ brr(j) = cnfac*(fn(j)-fn(j-1)) + (1.-cnfac)*(fn1(j)-fn1(j-1))
+ ENDDO
+
+
+ IF (DEF_USE_SNICAR) THEN
+
+ wice_soisno_bef(lb:0) = wice_soisno(lb:0)
+
+ CALL meltf_snicar (patchtype,is_dry_lake,lb,nl_soil,deltim, &
+ fact(lb:),brr(lb:),hs,hs_soil,hs_snow,fsno,sabg_snow_lyr(lb:),dhsdT, &
+ t_soisno_bef(lb:),t_soisno(lb:),wliq_soisno(lb:),wice_soisno(lb:),imelt(lb:), &
+ scv,snowdp,sm,xmf,porsl,psi0,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r,alpha_vgm,n_vgm,L_vgm,&
+ sc_vgm,fc_vgm,&
+#endif
+ dz_soisno(1:nl_soil))
+
+ ! layer freezing mass flux (positive):
+ DO j = lb, 0
+ IF (imelt(j)==2 .and. j<1) THEN
+ snofrz(j) = max(0._r8,(wice_soisno(j)-wice_soisno_bef(j)))/deltim
+ ENDIF
+ ENDDO
+
+ ELSE
+ CALL meltf (patchtype,is_dry_lake,lb,nl_soil,deltim, &
+ fact(lb:),brr(lb:),hs,hs_soil,hs_snow,fsno,dhsdT, &
+ t_soisno_bef(lb:),t_soisno(lb:),wliq_soisno(lb:),wice_soisno(lb:),imelt(lb:), &
+ scv,snowdp,sm,xmf,porsl,psi0,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r,alpha_vgm,n_vgm,L_vgm,&
+ sc_vgm,fc_vgm,&
+#endif
+ dz_soisno(1:nl_soil))
+ ENDIF
+
+!-----------------------------------------------------------------------
+
+ END SUBROUTINE GroundTemperature
+
+END MODULE MOD_GroundTemperature
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_HighRes_Parameters.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HighRes_Parameters.F90
new file mode 100644
index 0000000000..bb64bd23c7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HighRes_Parameters.F90
@@ -0,0 +1,550 @@
+#include
+
+MODULE MOD_HighRes_Parameters
+
+!-----------------------------------------------------------------------
+! USES:
+USE MOD_Precision
+USE MOD_NetCDFSerial
+USE MOD_Namelist, only : DEF_USE_SNICAR, DEF_HighResSoil, DEF_HighResVeg, DEF_PROSPECT !, DEF_Satellite_Params
+USE MOD_Namelist, only : DEF_HighResUrban_albedo
+! USE MOD_Namelist, only : DEF_file_soiloptics, DEF_file_satellite_params, DEF_sla_varname
+IMPLICIT NONE
+SAVE
+
+REAL(r8) :: reflectance ( 0:15, 211, 2 ) ! (species, leaf/stem, wavelength)
+REAL(r8) :: transmittance ( 0:15, 211, 2 ) ! (species, leaf/stem, wavelength)
+! REAL(r8) :: soil_alb ( 211 ) ! (wavelength)
+REAL(r8) :: kw ( 211 ) ! (wavelength)
+REAL(r8) :: nw ( 211 ) ! (wavelength)
+REAL(r8) :: clr_frac ( 211, 89, 5 ) ! (wvl_ctr, SZA, loc )
+REAL(r8) :: cld_frac ( 211, 5 ) ! (wvl_ctr, loc, )
+! Urban hyperspectral albedo
+REAL(r8), ALLOCATABLE :: urban_albedo( :, :, : ) ! (cluster_id, season wavelength)
+REAL(r8), ALLOCATABLE :: mean_albedo ( :, : ) ! (season, wavelength)
+REAL(r8), ALLOCATABLE :: lat_north ( : ) ! (cluster_id)
+REAL(r8), ALLOCATABLE :: lat_south ( : ) ! (cluster_id)
+REAL(r8), ALLOCATABLE :: lon_east ( : ) ! (cluster_id)
+REAL(r8), ALLOCATABLE :: lon_west ( : ) ! (cluster_id)
+
+! ! ONLY VALID when DEF_Satellite_Params is TRUE
+! REAL(r8) :: chl_satellite(366)
+! REAL(r8) :: sla_satellite
+
+PUBLIC :: flux_frac_init
+PUBLIC :: leaf_property_init
+! PUBLIC :: surface_albedo_single_init
+PUBLIC :: get_water_optical_properties
+PUBLIC :: get_loc_params
+! PUBLIC :: satellite_PROSPECT_init
+
+CONTAINS
+!-----------------------------------------------------------------------
+
+subroutine flux_frac_init( )
+
+ USE NETCDF
+ IMPLICIT NONE
+ !-------------------------------------------------------------------
+ INTEGER :: i, ncid, varid
+ CHARACTER(len=256) :: file_path
+ !-------------------------------------------------------------------
+
+ ! open the file base on the SZA and latitude
+ file_path = "/ddn_lustre/weiliren/data/CoLM_hires_params/fsds/swnb_480bnd_fsds.nc"
+
+ ! open the file
+ CALL nccheck( nf90_open(trim(file_path), NF90_NOWRITE, ncid) , trace=trim(file_path)//' cannot open' )
+
+ ! get the variable id
+
+ CALL nccheck( nf90_open(trim(file_path), NF90_NOWRITE, ncid) , trace=trim(file_path)//' cannot open' )
+
+ ! get the variable id
+ CALL nccheck( nf90_inq_varid(ncid, 'flx_frc_cld', varid) , trace=trim(file_path)//' cannot get varid' )
+ CALL nccheck( nf90_get_var(ncid, varid, cld_frac) , trace=trim(file_path)//' cannot get data' )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'flx_frc_clr', varid) , trace=trim(file_path)//' cannot get varid' )
+ CALL nccheck( nf90_get_var(ncid, varid, clr_frac) , trace=trim(file_path)//' cannot get data' )
+
+ ! close the file
+ CALL nccheck( nf90_close(ncid) , trace=trim(file_path)//' cannot close' )
+end subroutine flux_frac_init
+
+
+subroutine leaf_property_init( rho_p, tau_p )
+ ! Plant Functional Type classification
+ !---------------------------
+ ! 0 not vegetated
+ ! 1 needleleaf evergreen temperate tree
+ ! 2 needleleaf evergreen boreal tree
+ ! 3 needleleaf deciduous boreal tree
+ ! 4 broadleaf evergreen tropical tree
+ ! 5 broadleaf evergreen temperate tree
+ ! 6 broadleaf deciduous tropical tree
+ ! 7 broadleaf deciduous temperate tree
+ ! 8 broadleaf deciduous boreal tree
+ ! 9 broadleaf evergreen shrub
+ !10 broadleaf deciduous temperate shrub
+ !11 broadleaf deciduous boreal shrub
+ !12 c3 arctic grass
+ !13 c3 non-arctic grass
+ !14 c4 grass
+ !15 c3 crop
+ !16 c3_irrigated
+
+ USE NETCDF
+ IMPLICIT NONE
+ !-------------------------------------------------------------------
+ REAL(r8), INTENT(IN) :: rho_p(2, 2, 0:15), tau_p(2, 2, 0:15) ! (leaf/stem, vis/nir, species)
+ INTEGER :: i, j, ncid, varid, ndims, dimids(3), dimlen(3)
+ CHARACTER(len=256) :: file_path
+ REAL(r8), allocatable :: reflectance_temp(:,:,:), transmittance_temp(:,:,:)
+ !-------------------------------------------------------------------
+ ! open the file base on the SZA and latitude
+
+ ! Parameters for hyperspectral leaf properties
+ IF ( DEF_HighResVeg .OR. DEF_PROSPECT ) THEN
+
+ file_path = "/ddn_lustre/weiliren/data/CoLM_hires_params/leaf_optical_properties/colm_PFT_params.nc"
+
+ ! open the file
+ CALL nccheck( nf90_open(trim(file_path), NF90_NOWRITE, ncid) , trace=trim(file_path)//' cannot open' )
+
+ ! get the variable id
+ CALL nccheck( nf90_inq_varid(ncid, 'reflectance', varid) , trace=trim(file_path)//' cannot get varid' )
+ CALL nccheck( nf90_inquire_variable(ncid, varid, dimids=dimids) , trace=trim(file_path)//' cannot get var dims' )
+
+ do i = 1, size(dimlen)
+ CALL nccheck( nf90_inquire_dimension(ncid, dimids(i), len=dimlen(i)) )
+ end do
+
+ ! allocate the memory, and get the reflectance data
+ allocate( reflectance_temp( dimlen(1), dimlen(2), dimlen(3) ) )
+ CALL nccheck( nf90_get_var(ncid, varid, reflectance_temp) )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'transmittance', varid) , trace=trim(file_path)//' cannot get varid' )
+ CALL nccheck( nf90_inquire_variable(ncid, varid, dimids=dimids) , trace=trim(file_path)//' cannot get var dims' )
+
+ ! allocate the memory, and get the transmittance data
+ allocate( transmittance_temp( dimlen(1), dimlen(2), dimlen(3) ) )
+ CALL nccheck( nf90_get_var(ncid, varid, transmittance_temp) )
+
+ ! close the file
+ CALL nccheck( nf90_close(ncid) , trace=trim(file_path)//' cannot close' )
+
+ do i = 0, 15
+ do j = 1, 2
+ reflectance (i, :, j) = reflectance_temp (:, j, i+1)
+ transmittance(i, :, j) = transmittance_temp(:, j, i+1)
+ end do
+ end do
+
+ DEALLOCATE( reflectance_temp )
+ DEALLOCATE( transmittance_temp )
+
+ ELSE
+
+ do i = 0, 15
+ reflectance(i, 1 :29 , 1) = rho_p(1, 1, i)
+ reflectance(i, 1 :29 , 2) = rho_p(1, 2, i)
+ reflectance(i, 30:211, 1) = rho_p(2, 1, i)
+ reflectance(i, 30:211, 2) = rho_p(2, 2, i)
+
+ transmittance(i, 1 :29 , 1) = tau_p(1, 1, i)
+ transmittance(i, 1 :29 , 2) = tau_p(1, 2, i)
+ transmittance(i, 30:211, 1) = tau_p(2, 1, i)
+ transmittance(i, 30:211, 2) = tau_p(2, 2, i)
+ end do
+
+ END IF
+
+ ! 3. Close file
+
+end subroutine leaf_property_init
+
+
+! No longer used
+! subroutine surface_albedo_single_init( )
+! IMPLICIT NONE
+! INTEGER :: i, unit
+! !-------------------------------------------------------------------
+
+! unit = 10
+
+! if (DEF_file_soiloptics == 'Null') then
+! write(*,*) "Error: soiloptics file is not defined"
+! stop
+! end if
+! open(unit=unit, file=DEF_file_soiloptics, status='old', action='read')
+
+! do i = 1, 211
+! read(unit,*) soil_alb(i)
+! end do
+! close(unit)
+! end subroutine surface_albedo_single_init
+
+
+SUBROUTINE get_water_optical_properties( )
+ IMPLICIT NONE
+ INTEGER :: i, unit
+
+ unit = 10
+ open(unit=unit, file='/ddn_lustre/weiliren/data/CoLM_hires_params/water_params.txt', status='old')
+
+ do i = 1, 211
+ read(unit,*) kw(i), nw(i)
+ end do
+ close(unit)
+END SUBROUTINE get_water_optical_properties
+
+
+real function rad2deg(angle_in_rad)
+ real, intent(in) :: angle_in_rad
+ rad2deg = angle_in_rad * (180.0 / 3.14159265358979323846)
+end function rad2deg
+
+
+SUBROUTINE get_loc_params( fsds, idate, coszen, lat, lon, clr_frac_all, cld_frac_all, dir_frac, dif_frac )
+ USE MOD_OrbCoszen
+ USE MOD_TimeManager
+
+ implicit none
+ real(r8), intent(in) :: fsds
+ integer, INTENT(in) :: idate(3)
+ real(r8), intent(in) :: coszen
+ real(r8), intent(in) :: lat, lon
+ real(r8), intent(in) :: clr_frac_all( 211, 89, 5 )
+ real(r8), intent(in) :: cld_frac_all( 211, 5 )
+
+ real, intent(out) :: dir_frac(211)
+ real, intent(out) :: dif_frac(211)
+
+ INTEGER :: loc_index, sza
+ real(r8) :: lat_deg, sunang, cloud, difrat, vnrat, calday, a
+
+ ! index = 1 - 90
+ sza = int(rad2deg(acos(min(1._r8,max(-1._r8,coszen))))) + 1
+ sza = max(1, min(ubound(clr_frac_all,2), sza)) ! 自动适配
+
+ ! combine cloud and clear sky fraction
+ a = max(0., fsds)
+ calday = calendarday(idate)
+ sunang = orb_coszen(calday, lon, lat)
+
+ ! turn lat from radians to degrees
+ lat_deg = abs(rad2deg(lat))
+
+ ! check if the lat in tropical/temperate/polar
+ IF (lat_deg >= 0.0 .AND. lat_deg < 23.5) THEN
+ loc_index = 5
+
+ ELSE IF (lat_deg >= 23.5 .AND. lat_deg < 66.5) THEN
+ ! temperate summer
+ IF (calday > 91 .AND. calday < 274) THEN
+ loc_index = 4
+ ELSE
+ loc_index = 3
+ END IF
+
+ ELSE IF (lat_deg >= 66.5 .AND. lat_deg <= 90.0) THEN
+ IF (calday > 91 .AND. calday < 274) THEN
+ loc_index = 2
+ ELSE
+ loc_index = 1
+ END IF
+
+ ENDIF
+
+ dir_frac = clr_frac_all(:, sza, loc_index)
+ dif_frac = cld_frac_all(:, loc_index)
+
+END SUBROUTINE get_loc_params
+
+! SUBROUTINE satellite_PROSPECT_init()
+! USE NETCDF
+! IMPLICIT NONE
+! !-------------------------------------------------------------------
+! INTEGER :: i, j, ncid, varid
+! INTEGER, ALLOCATABLE :: dimids(:)
+! !-------------------------------------------------------------------
+! if (DEF_file_satellite_params == 'null') then
+! write(*,*) "ERROR: DEF_file_satellite_params is not set"
+! stop
+! end if
+
+! ! 1. Open file
+! CALL nccheck( nf90_open(trim(DEF_file_satellite_params), NF90_NOWRITE, ncid), trace=trim(DEF_file_satellite_params)//' cannot open' )
+
+! ! 2. Read data: chl
+! CALL nccheck( nf90_inq_varid(ncid, 'chl', varid), trace=trim(DEF_file_satellite_params)//' cannot find variable' )
+! CALL nccheck( nf90_inquire_variable(ncid, varid, dimids=dimids), trace=trim(DEF_file_satellite_params)//' cannot inquire variable' )
+! CALL nccheck( nf90_get_var(ncid, varid, chl_satellite), trace='chl cannot get variable' )
+
+! ! 2. Read data: sla
+! CALL nccheck( nf90_inq_varid(ncid, DEF_sla_varname, varid), trace=trim(DEF_file_satellite_params)//' cannot find variable' )
+! CALL nccheck( nf90_inquire_variable(ncid, varid, dimids=dimids), trace=trim(DEF_file_satellite_params)//' cannot inquire variable' )
+! CALL nccheck( nf90_get_var(ncid, varid, sla_satellite), trace=trim(DEF_sla_varname)//' cannot get variable' )
+
+! ! 3. Close file
+! call nccheck( nf90_close(ncid) )
+! END SUBROUTINE satellite_PROSPECT_init
+
+
+! ======== Calculate Reflectance & Transmittance using PROSPECT ========
+SUBROUTINE update_params_PROSPECT(ipft, reflectance_in, transmittance_in,&
+ reflectance_p, transmittance_p ,&
+ soilmoisture )
+ USE MOD_prospect_DB
+ USE MOD_dataSpec_PDB, only : nw
+ IMPLICIT NONE
+ !-------------------------------------------------------------------
+ REAL(r8), PARAMETER :: SLA(0: 15) & ! unit g/m^2
+ = (/ 0.0 , 0.0100, 0.0100, 0.0202, 0.0190, 0.0190, 0.0308, 0.0308 &
+ , 0.0308, 0.0180, 0.0307, 0.0307, 0.0402, 0.0402, 0.0385, 0.0402 /)
+
+ REAL(r8), PARAMETER :: vmax25_p(0: 15) & !
+ = (/ 52.0, 55.0, 42.0, 29.0, 41.0, 51.0, 36.0, 30.0 &
+ , 40.0, 36.0, 30.0, 19.0, 21.0, 26.0, 25.0, 57.0 /) * 1.e-6
+
+ INTEGER , INTENT(IN) :: ipft
+ REAL(r8), INTENT(IN) :: reflectance_in(16, 211, 2), transmittance_in(16, 211, 2)
+ REAL(r8), INTENT(IN) :: soilmoisture
+
+ REAL(r8), INTENT(OUT) :: reflectance_p(211, 2), transmittance_p(211, 2)
+
+ ! Params for PROSPECT
+ REAL(r8) :: N ! leaf structure coefficient (n_layer)
+ REAL(r8) :: Cab ! Chlorophyll Content
+ REAL(r8) :: Car ! Carotenoid, unit [μg cm^−2]
+ REAL(r8) :: Anth ! Anthocyanin
+ REAL(r8) :: Cbrown ! Brown Pigment
+ REAL(r8) :: Cw ! Equivalent Water Thickness
+ REAL(r8) :: Cm ! Dry Matter Content (g cm^-2)
+ REAL(r8) :: RT(nw, 2) ! nw = 2101, defined in dataSpec_PDB
+
+ ! temporary variables
+ REAL(r8) :: vmax25 ! maximum carboxylation rate at 25 C at canopy top, unit [mol m-2 s-1]
+
+ INTEGER :: i, j
+ !-------------------------------------------------------------------
+ ! 1. Set Car, Cbrown, Anth
+ Car = 8.0
+ Cbrown = 0.01
+ Anth = 0.0
+
+ ! 2. Calculate N & Cm
+ ! SLA: Specific Leaf Area, unit [m^2 g-1] -> [cm^2 mg-1]
+ N = (0.9 * (SLA(ipft) * 10.) + 0.025) / ((SLA(ipft) * 10.) - 0.01)
+ ! Cm: Dry Matter Content, unit [g cm^-2] <- SLA [m^2 g-1]
+ Cm = 1.0 / (SLA(ipft) * 1.e4)
+
+ ! 3. Calculate Cab
+ vmax25 = vmax25_p(ipft)
+ Cab = ((vmax25 * 1.e6) - 3.72) / 1.3
+
+ ! 4. Calculate Cw
+ Cw = 0.01 - (( 0.01 - 0. ) * exp( -5.5 * soilmoisture ))
+
+ ! 5. Calculate reflectance & transmittance
+ CALL prospect_DB(N,Cab,Car,Anth,Cbrown,Cw,Cm,RT)
+
+ j = 1
+ do i = 1, nw, 10
+ reflectance_p(j, 1) = RT(i, 1)
+ transmittance_p(j, 1) = RT(i, 2)
+ j = j + 1
+ end do
+
+ reflectance_p(:,2) = reflectance_in(ipft, :, 2)
+ transmittance_p(:,2) = transmittance_in(ipft, :, 2)
+END SUBROUTINE update_params_PROSPECT
+! ======================================================================
+
+! SUBROUTINE satellite_PROSPECT(ipft, reflectance_in, transmittance_in,&
+! reflectance_p, transmittance_p ,&
+! soilmoisture, doy )
+! USE MOD_prospect_DB
+! USE MOD_dataSpec_PDB, only : nw
+! IMPLICIT NONE
+! !-------------------------------------------------------------------
+
+! INTEGER , INTENT(IN) :: ipft
+! REAL(r8), INTENT(IN) :: reflectance_in(16, 211, 2), transmittance_in(16, 211, 2)
+! REAL(r8), INTENT(IN) :: soilmoisture
+! INTEGER, INTENT(IN) :: doy
+
+! REAL(r8), INTENT(OUT) :: reflectance_p(211, 2), transmittance_p(211, 2)
+
+! ! Params for PROSPECT
+! REAL(r8) :: N ! leaf structure coefficient (n_layer)
+! REAL(r8) :: Cab ! Chlorophyll Content
+! REAL(r8) :: Car ! Carotenoid, unit [μg cm^−2]
+! REAL(r8) :: Anth ! Anthocyanin
+! REAL(r8) :: Cbrown ! Brown Pigment
+! REAL(r8) :: Cw ! Equivalent Water Thickness
+! REAL(r8) :: Cm ! Dry Matter Content (g cm^-2)
+! REAL(r8) :: RT(nw, 2) ! nw = 2101, defined in dataSpec_PDB
+! INTEGER :: i, j
+
+! !NOTE: All from Wang 2025 NC
+! ! 1. Set Car, Cbrown, Anth
+! Cbrown = 0.0
+! Anth = 0.0
+
+! ! 2. Calculate N & Cm
+! ! SLA: Specific Leaf Area, unit [cm^2 mg-1]
+! N = 1.4
+! ! N = (0.9 * sla_satellite + 0.025) / (sla_satellite - 0.01)
+! ! Cm: Dry Matter Content, unit [g cm^-2] <- SLA [cm^2 mg-1]
+! Cm = 1.0 / (sla_satellite * 1.e3)
+
+! ! 3. Calculate Cab
+! Cab = chl_satellite(doy)
+! Car = Cab / 7.
+
+! ! 4. Calculate Cw
+! Cw = 0.009 ! cm
+! ! Cw = 0.01 - (( 0.01 - 0. ) * exp( -5.5 * soilmoisture ))
+
+! ! 5. Calculate reflectance & transmittance
+! CALL prospect_DB(N,Cab,Car,Anth,Cbrown,Cw,Cm,RT)
+
+! j = 1
+! do i = 1, nw, 10
+! reflectance_p(j, 1) = RT(i, 1)
+! transmittance_p(j, 1) = RT(i, 2)
+! j = j + 1
+! end do
+
+! reflectance_p(:,2) = reflectance_in(ipft, :, 2)
+! transmittance_p(:,2) = transmittance_in(ipft, :, 2)
+
+! END SUBROUTINE satellite_PROSPECT
+
+SUBROUTINE readin_urban_albedo()
+
+ USE NETCDF
+ IMPLICIT NONE
+ INTEGER :: ncid, ndims, dimids(3), dimlen(3)
+ INTEGER :: albedo_varid, mean_albedo_varid, &
+ lat_north_varid, lat_south_varid, &
+ lon_east_varid , lon_west_varid
+ CHARACTER(len=256) :: file_path
+ INTEGER :: i
+
+ ! 设置文件路径
+ file_path = DEF_HighResUrban_albedo
+
+ ! 打开 NetCDF 文件
+ CALL nccheck( nf90_open(trim(file_path), NF90_NOWRITE, ncid) , &
+ trace=trim(file_path)//' cannot open' )
+
+ ! 获取变量 ID
+ CALL nccheck( nf90_inq_varid(ncid, 'urban_albedo', albedo_varid) , &
+ trace=trim(file_path)//' cannot get varid' )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'mean_albedo', mean_albedo_varid) , &
+ trace=trim(file_path)//' cannot get varid' )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'lat_north', lat_north_varid) , &
+ trace=trim(file_path)//' cannot get varid' )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'lat_south', lat_south_varid) , &
+ trace=trim(file_path)//' cannot get varid' )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'lon_east', lon_east_varid) , &
+ trace=trim(file_path)//' cannot get varid' )
+
+ CALL nccheck( nf90_inq_varid(ncid, 'lon_west', lon_west_varid) , &
+ trace=trim(file_path)//' cannot get varid' )
+
+ ! 获取变量维度信息
+ CALL nccheck( nf90_inquire_variable(ncid, albedo_varid, ndims=ndims, dimids=dimids) , &
+ trace=trim(file_path)//' cannot get var dims' )
+
+ ! 获取各维度长度
+ do i = 1, ndims
+ CALL nccheck( nf90_inquire_dimension(ncid, dimids(i), len=dimlen(i)) )
+ end do
+
+ ! 分配内存
+ if (.not. allocated(urban_albedo)) then
+ allocate( urban_albedo(dimlen(1), dimlen(2), dimlen(3)) ) ! (cluster_id, season, wavelength)
+ end if
+
+ if (.not. allocated(mean_albedo)) then
+ allocate( mean_albedo(dimlen(2), dimlen(3)) ) ! (season, wavelength)
+ end if
+
+ if (.not. allocated(lat_north)) then
+ allocate( lat_north(dimlen(1)) ) ! (cluster_id)
+ end if
+
+ if (.not. allocated(lat_south)) then
+ allocate( lat_south(dimlen(1)) ) ! (cluster_id)
+ end if
+
+ if (.not. allocated(lon_east)) then
+ allocate( lon_east(dimlen(1)) ) ! (cluster_id)
+ end if
+
+ if (.not. allocated(lon_west)) then
+ allocate( lon_west(dimlen(1)) ) ! (cluster_id)
+ end if
+
+ ! 读取数据
+ CALL nccheck( nf90_get_var(ncid, albedo_varid, urban_albedo) , &
+ trace=trim(file_path)//' cannot get data' )
+
+ CALL nccheck( nf90_get_var(ncid, mean_albedo_varid, mean_albedo) , &
+ trace=trim(file_path)//' cannot get data' )
+
+ CALL nccheck( nf90_get_var(ncid, lat_north_varid, lat_north) , &
+ trace=trim(file_path)//' cannot get data' )
+
+ CALL nccheck( nf90_get_var(ncid, lat_south_varid, lat_south) , &
+ trace=trim(file_path)//' cannot get data' )
+
+ CALL nccheck( nf90_get_var(ncid, lon_east_varid, lon_east) , &
+ trace=trim(file_path)//' cannot get data' )
+
+ CALL nccheck( nf90_get_var(ncid, lon_west_varid, lon_west) , &
+ trace=trim(file_path)//' cannot get data' )
+
+ ! 关闭文件
+ CALL nccheck( nf90_close(ncid) , &
+ trace=trim(file_path)//' cannot close' )
+
+END SUBROUTINE readin_urban_albedo
+
+SUBROUTINE deallocate_urban_albedo()
+ IMPLICIT NONE
+
+ IF (ALLOCATED(urban_albedo)) THEN
+ DEALLOCATE(urban_albedo)
+ END IF
+
+ IF (ALLOCATED(mean_albedo)) THEN
+ DEALLOCATE(mean_albedo)
+ END IF
+
+ IF (ALLOCATED(lat_north)) THEN
+ DEALLOCATE(lat_north)
+ END IF
+
+ IF (ALLOCATED(lat_south)) THEN
+ DEALLOCATE(lat_south)
+ END IF
+
+ IF (ALLOCATED(lon_east)) THEN
+ DEALLOCATE(lon_east)
+ END IF
+
+ IF (ALLOCATED(lon_west)) THEN
+ DEALLOCATE(lon_west)
+ END IF
+
+END SUBROUTINE deallocate_urban_albedo
+
+END MODULE MOD_HighRes_Parameters
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Hist.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Hist.F90
new file mode 100644
index 0000000000..e60eeee954
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Hist.F90
@@ -0,0 +1,5033 @@
+#include
+
+MODULE MOD_Hist
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Write out gridded model results to history files.
+!
+! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+!
+! !REVISIONS:
+! Shupeng Zhang, 05/2023: 1) porting codes to MPI parallel version
+!
+! TODO...(need complement)
+!----------------------------------------------------------------------------
+
+ USE MOD_Vars_1DAccFluxes
+ USE MOD_Vars_Global, only: spval
+ USE MOD_NetCDFSerial
+
+ USE MOD_HistGridded
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ USE MOD_HistVector
+#endif
+#ifdef SinglePoint
+ USE MOD_HistSingle
+#endif
+#ifdef CatchLateralFlow
+ USE MOD_Catch_Hist
+#endif
+#ifdef GridRiverLakeFlow
+ USE MOD_Grid_RiverLakeHist
+#endif
+#ifdef EXTERNAL_LAKE
+ USE MOD_Lake_Hist
+#endif
+
+ PUBLIC :: hist_init
+ PUBLIC :: hist_out
+ PUBLIC :: hist_final
+
+ character(len=10) :: HistForm ! 'Gridded', 'Vector', 'Single'
+
+ character(len=256) :: file_last = 'null'
+
+!--------------------------------------------------------------------------
+CONTAINS
+
+ SUBROUTINE hist_init (dir_hist, lulcc_call)
+
+ IMPLICIT NONE
+
+ character(len=*) , intent(in) :: dir_hist
+ logical, optional, intent(in) :: lulcc_call
+
+ CALL allocate_acc_fluxes ()
+ CALL FLUSH_acc_fluxes ()
+
+ HistForm = 'Gridded'
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ IF (DEF_HISTORY_IN_VECTOR) THEN
+ HistForm = 'Vector'
+ ENDIF
+#endif
+#ifdef SinglePoint
+ HistForm = 'Single'
+#endif
+
+ IF (HistForm == 'Gridded') THEN
+ IF (present(lulcc_call)) THEN
+ CALL hist_gridded_init (dir_hist, lulcc_call)
+ ELSE
+ CALL hist_gridded_init (dir_hist)
+ ENDIF
+#ifdef SinglePoint
+ ELSEIF (HistForm == 'Single') THEN
+ CALL hist_single_init ()
+#endif
+ ENDIF
+
+#ifdef CatchLateralFlow
+ CALL hist_basin_init ()
+#endif
+
+#ifdef GridRiverLakeFlow
+ CALL hist_grid_riverlake_init (HistForm)
+#endif
+
+ END SUBROUTINE hist_init
+
+
+ SUBROUTINE hist_final ()
+
+ IMPLICIT NONE
+
+ CALL deallocate_acc_fluxes ()
+
+#ifdef SinglePoint
+ CALL hist_single_final ()
+#endif
+
+#ifdef CatchLateralFlow
+ CALL hist_basin_final ()
+#endif
+
+#ifdef GridRiverLakeFlow
+ CALL hist_grid_riverlake_final ()
+#endif
+
+ END SUBROUTINE hist_final
+
+
+ SUBROUTINE hist_out (idate, deltim, itstamp, etstamp, ptstamp, &
+ dir_hist, casename)
+
+!=======================================================================
+! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_TimeManager
+ USE MOD_SPMD_Task
+ USE MOD_Vars_1DAccFluxes, filter_dt_ => filter_dt
+ USE MOD_Vars_1DFluxes, only: nsensor
+ USE MOD_Vars_TimeVariables, only: wa, wat, wetwat, wdsrf
+ USE MOD_Block
+ USE MOD_DataType
+ USE MOD_LandPatch
+ USE MOD_SpatialMapping
+ USE MOD_Vars_TimeInvariants, only: patchtype, patchclass, patchmask
+#ifdef URBAN_MODEL
+ USE MOD_LandUrban
+#endif
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_LandPFT, only: patch_pft_s
+#endif
+ USE MOD_Forcing, only: forcmask_pch
+#ifdef DataAssimilation
+ USE MOD_DA_TWS, only: fslp_k_mon
+ USE MOD_Vars_Global
+ USE MOD_DA_Vars_TimeVariables
+ USE MOD_Const_Physical, only: denh2o
+#endif
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ type(timestamp), intent(in) :: itstamp
+ type(timestamp), intent(in) :: etstamp
+ type(timestamp), intent(in) :: ptstamp
+
+ character(len=*), intent(in) :: dir_hist
+ character(len=*), intent(in) :: casename
+
+ ! Local variables
+ logical :: lwrite
+ character(len=256) :: file_hist
+ integer :: itime_in_file
+ integer :: month, day
+ integer :: days_month(1:12)
+ character(len=10) :: cdate
+
+ type(block_data_real8_2d) :: sumarea
+ type(block_data_real8_2d) :: sumarea_dt
+ type(block_data_real8_2d) :: sumarea_urb
+ type(block_data_real8_2d) :: sumarea_one
+ real(r8), allocatable :: vecacc (:)
+ real(r8), allocatable :: nac_one (:)
+ logical, allocatable :: filter (:)
+ logical, allocatable :: filter_dt (:)
+
+#ifdef CROP
+ type(block_data_real8_2d) :: sumarea_crop
+ type(block_data_real8_2d) :: sumarea_irrig
+ logical, allocatable :: filter_crop (:)
+ logical, allocatable :: filter_irrig (:)
+#endif
+
+ integer i, u
+#ifdef URBAN_MODEL
+ logical, allocatable :: filter_urb (:)
+#endif
+
+#ifdef DataAssimilation
+ integer :: np
+ real(r8), allocatable :: a_wliq_h2osoi_5cm (:)
+ real(r8), allocatable :: a_t_soisno_5cm (:)
+ real(r8), allocatable :: a_wliq_soisno_ens_mean (:,:)
+ real(r8), allocatable :: a_wliq_soisno_5cm_ens (:,:)
+ real(r8), allocatable :: a_wliq_h2osoi_5cm_a (:)
+ real(r8), allocatable :: a_t_soisno_ens_mean (:,:)
+ real(r8), allocatable :: a_t_soisno_5cm_ens (:,:)
+ real(r8), allocatable :: a_t_soisno_5cm_a (:)
+ real(r8), allocatable :: a_t_brt_smap_a (:,:)
+ real(r8), allocatable :: a_t_brt_fy3d_a (:,:)
+ real(r8), allocatable :: a_wliq_soisno_5cm_ens_std (:)
+ real(r8), allocatable :: a_t_soisno_5cm_ens_std (:)
+ real(r8), allocatable :: a_t_brt_smap_ens_std (:,:)
+ real(r8), allocatable :: a_t_brt_fy3d_ens_std (:,:)
+#endif
+
+ IF (itstamp <= ptstamp) THEN
+ CALL FLUSH_acc_fluxes ()
+ RETURN
+ ELSE
+ CALL accumulate_fluxes ()
+ ENDIF
+
+ select CASE (trim(adjustl(DEF_HIST_FREQ)))
+ CASE ('TIMESTEP')
+ lwrite = .true.
+ CASE ('HOURLY')
+ lwrite = isendofhour (idate, deltim) .or. (.not. (itstamp < etstamp))
+ CASE ('DAILY')
+ lwrite = isendofday (idate, deltim) .or. (.not. (itstamp < etstamp))
+ CASE ('MONTHLY')
+ lwrite = isendofmonth(idate, deltim) .or. (.not. (itstamp < etstamp))
+ CASE ('YEARLY')
+ lwrite = isendofyear (idate, deltim) .or. (.not. (itstamp < etstamp))
+ CASE default
+ lwrite = .false.
+ write(*,*) &
+ 'Warning : Please USE one of TIMESTEP/HOURLY/DAILY/MONTHLY/YEARLY for history frequency.'
+ write(*,*) &
+ ' Set to FALSE by default. '
+ END select
+
+ IF (lwrite) THEN
+
+ CALL julian2monthday(idate(1), idate(2), month, day)
+
+ days_month = (/31,28,31,30,31,30,31,31,30,31,30,31/)
+ IF (isleapyear(idate(1))) days_month(2) = 29
+
+ IF ( trim(DEF_HIST_groupby) == 'YEAR' ) THEN
+ write(cdate,'(i4.4)') idate(1)
+#ifdef SinglePoint
+ IF (USE_SITE_HistWriteBack) THEN
+ memory_to_disk = isendofyear(idate,deltim) .or. (.not. (itstamp < etstamp))
+ ENDIF
+#endif
+ ELSEIF ( trim(DEF_HIST_groupby) == 'MONTH' ) THEN
+ write(cdate,'(i4.4,"-",i2.2)') idate(1), month
+#ifdef SinglePoint
+ IF (USE_SITE_HistWriteBack) THEN
+ memory_to_disk = isendofmonth(idate,deltim) .or. (.not. (itstamp < etstamp))
+ ENDIF
+#endif
+ ELSEIF ( trim(DEF_HIST_groupby) == 'DAY' ) THEN
+ write(cdate,'(i4.4,"-",i2.2,"-",i2.2)') idate(1), month, day
+#ifdef SinglePoint
+ IF (USE_SITE_HistWriteBack) THEN
+ memory_to_disk = isendofday(idate,deltim) .or. (.not. (itstamp < etstamp))
+ ENDIF
+#endif
+ ELSE
+ write(*,*) 'Warning : Please USE one of DAY/MONTH/YEAR for history group.'
+ ENDIF
+
+ file_hist = trim(dir_hist) // '/' // trim(casename) //'_hist_'//trim(cdate)//'.nc'
+
+ CALL hist_write_time (file_hist, file_last, 'time', idate, itime_in_file)
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate (filter (numpatch))
+ allocate (filter_dt (numpatch))
+ allocate (vecacc (numpatch))
+ ENDIF
+#ifdef URBAN_MODEL
+ IF (numurban > 0) THEN
+ allocate (filter_urb (numurban))
+ ENDIF
+#endif
+#ifdef CROP
+ IF (numpatch > 0) THEN
+ allocate (filter_crop (numpatch))
+ allocate (filter_irrig (numpatch))
+ ENDIF
+#endif
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (p_is_active) THEN
+ CALL allocate_block_data (ghist, sumarea)
+ CALL allocate_block_data (ghist, sumarea_dt)
+#ifdef URBAN_MODEL
+ CALL allocate_block_data (ghist, sumarea_urb)
+#endif
+#ifdef CROP
+ CALL allocate_block_data (ghist, sumarea_crop)
+ CALL allocate_block_data (ghist, sumarea_irrig)
+#endif
+ ENDIF
+ ENDIF
+
+ ! ---------------------------------------------------
+ ! Meteorological forcing and patch mask filter applying.
+ ! ---------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype < 99
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ filter_dt = filter .and. patchmask .and. (nac_dt > 0)
+
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ CALL mp2g_hist%get_sumarea (sumarea_dt, filter_dt)
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (trim(file_hist) /= trim(file_last)) THEN
+ CALL hist_write_var_real8_2d (file_hist, 'landarea', ghist, -1, sumarea, &
+ compress = 1, longname = 'land area', units = 'km2')
+ CALL hist_write_var_real8_2d (file_hist, 'landfraction', ghist, -1, landfraction, &
+ compress = 1, longname = 'land fraction', units = '-')
+ ENDIF
+ ENDIF
+
+#ifdef CROP
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ filter_crop(:) = patchtype < 99
+ filter_crop(:) = patchclass == 12
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter_crop = filter_crop .and. forcmask_pch
+ ENDIF
+
+ filter_crop = filter_crop .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea_crop, filter_crop)
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (trim(file_hist) /= trim(file_last)) THEN
+ CALL hist_write_var_real8_2d (file_hist, 'croparea', ghist, 1, sumarea_crop, &
+ compress = 1, longname = 'crop area', units = 'km2')
+ ENDIF
+ ENDIF
+
+ IF (DEF_USE_IRRIGATION) THEN
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF((pftclass(patch_pft_s(i)).GE.npcropmin).and.(MOD(pftclass(patch_pft_s(i)),2).EQ.0))THEN
+ filter_irrig(i) = .true.
+ ELSE
+ filter_irrig(i) = .false.
+ ENDIF
+ ELSE
+ filter_irrig(i) = .false.
+ ENDIF
+ ENDDO
+ IF (DEF_forcing%has_missing_value) THEN
+ filter_irrig = filter_irrig .and. forcmask_pch
+ ENDIF
+ filter_irrig = filter_irrig .and. patchmask
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea_irrig, filter_irrig)
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (trim(file_hist) /= trim(file_last)) THEN
+ CALL hist_write_var_real8_2d (file_hist, 'irrigarea', ghist, 1, sumarea_irrig, &
+ compress = 1, longname = 'irrigation area', units = 'km2')
+ ENDIF
+ ENDIF
+#endif
+
+ ! wind in eastward direction [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_us, &
+ a_us, file_hist, 'f_xy_us', itime_in_file, sumarea, filter, &
+ 'wind in eastward direction', 'm/s')
+
+ ! wind in northward direction [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_vs, &
+ a_vs, file_hist, 'f_xy_vs', itime_in_file, sumarea, filter, &
+ 'wind in northward direction','m/s')
+
+ ! temperature at reference height [kelvin]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_t, &
+ a_t, file_hist, 'f_xy_t', itime_in_file, sumarea, filter, &
+ 'temperature at reference height','kelvin')
+
+ ! specific humidity at reference height [kg/kg]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_q, &
+ a_q, file_hist, 'f_xy_q', itime_in_file, sumarea, filter, &
+ 'specific humidity at reference height','kg/kg')
+
+ ! convective precipitation [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_prc, &
+ a_prc, file_hist, 'f_xy_prc', itime_in_file, sumarea, filter, &
+ 'convective precipitation','mm/s')
+
+ ! large scale precipitation [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_prl, &
+ a_prl, file_hist, 'f_xy_prl', itime_in_file, sumarea, filter, &
+ 'large scale precipitation','mm/s')
+
+ ! atmospheric pressure at the surface [pa]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_pbot, &
+ a_pbot, file_hist, 'f_xy_pbot', itime_in_file, sumarea, filter, &
+ 'atmospheric pressure at the surface','pa')
+
+ ! atmospheric infrared (longwave) radiation [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_frl, &
+ a_frl, file_hist, 'f_xy_frl', itime_in_file, sumarea, filter, &
+ 'atmospheric infrared (longwave) radiation','W/m2')
+
+ ! downward solar radiation at surface [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_solarin, &
+ a_solarin, file_hist, 'f_xy_solarin', itime_in_file, sumarea, filter, &
+ 'downward solar radiation at surface','W/m2')
+
+ ! rain [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_rain, &
+ a_rain, file_hist, 'f_xy_rain', itime_in_file, sumarea, filter, &
+ 'rain','mm/s')
+
+ ! snow [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_snow, &
+ a_snow, file_hist, 'f_xy_snow', itime_in_file, sumarea, filter, &
+ 'snow','mm/s')
+
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ ! atmospheric boundary layer height [m]
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_hpbl, &
+ a_hpbl, file_hist, 'f_xy_hpbl', itime_in_file, sumarea, filter, &
+ 'boundary layer height','m')
+ ENDIF
+
+ IF (DEF_USE_OZONESTRESS)THEN
+ CALL write_history_variable_2d ( DEF_hist_vars%o3uptakesun, &
+ a_o3uptakesun, file_hist, 'f_o3uptakesun', itime_in_file, sumarea, filter, &
+ 'Accumulated ozone uptake by sunlit leaf','mmol O3 m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%o3uptakesha, &
+ a_o3uptakesha, file_hist, 'f_o3uptakesha', itime_in_file, sumarea, filter, &
+ 'Accumulated ozone uptake by shaded leaf','mmol O3 m-2')
+ ENDIF
+
+ ! ------------------------------------------------------------------------------------------
+ ! Mapping the fluxes and state variables at patch [numpatch] to grid
+ ! ------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype < 99
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! wind stress: E-W [kg/m/s2]
+ CALL write_history_variable_2d ( DEF_hist_vars%taux, &
+ a_taux, file_hist, 'f_taux', itime_in_file, sumarea, filter, &
+ 'wind stress: E-W','kg/m/s2')
+
+ ! wind stress: N-S [kg/m/s2]
+ CALL write_history_variable_2d ( DEF_hist_vars%tauy, &
+ a_tauy, file_hist, 'f_tauy', itime_in_file, sumarea, filter, &
+ 'wind stress: N-S','kg/m/s2')
+
+ ! sensible heat from canopy height to atmosphere [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%fsena, &
+ a_fsena, file_hist, 'f_fsena', itime_in_file, sumarea, filter, &
+ 'sensible heat from canopy height to atmosphere','W/m2')
+
+ ! latent heat flux from canopy height to atmosphere [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%lfevpa, &
+ a_lfevpa, file_hist, 'f_lfevpa', itime_in_file, sumarea, filter, &
+ 'latent heat flux from canopy height to atmosphere','W/m2')
+
+ ! evapotranspiration from canopy to atmosphere [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%fevpa, &
+ a_fevpa, file_hist, 'f_fevpa', itime_in_file, sumarea, filter, &
+ 'evapotranspiration from canopy height to atmosphere','mm/s')
+
+ ! sensible heat from leaves [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%fsenl, &
+ a_fsenl, file_hist, 'f_fsenl', itime_in_file, sumarea, filter, &
+ 'sensible heat from leaves','W/m2')
+
+ ! evaporation+transpiration from leaves [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%fevpl, &
+ a_fevpl, file_hist, 'f_fevpl', itime_in_file, sumarea, filter, &
+ 'evaporation+transpiration from leaves','mm/s')
+
+ ! transpiration rate [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%etr, &
+ a_etr, file_hist, 'f_etr', itime_in_file, sumarea, filter, &
+ 'transpiration rate','mm/s')
+
+ ! sensible heat flux from ground [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%fseng, &
+ a_fseng, file_hist, 'f_fseng', itime_in_file, sumarea, filter, &
+ 'sensible heat flux from ground','W/m2')
+
+ ! evaporation heat flux from ground [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%fevpg, &
+ a_fevpg, file_hist, 'f_fevpg', itime_in_file, sumarea, filter, &
+ 'evaporation flux from ground','mm/s')
+
+ ! ground heat flux [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%fgrnd, &
+ a_fgrnd, file_hist, 'f_fgrnd', itime_in_file, sumarea, filter, &
+ 'ground heat flux','W/m2')
+
+ ! solar absorbed by sunlit canopy [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%sabvsun, &
+ a_sabvsun, file_hist, 'f_sabvsun', itime_in_file, sumarea, filter, &
+ 'solar absorbed by sunlit canopy','W/m2')
+
+ ! solar absorbed by shaded [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%sabvsha, &
+ a_sabvsha, file_hist, 'f_sabvsha', itime_in_file, sumarea, filter, &
+ 'solar absorbed by shaded','W/m2')
+
+ ! solar absorbed by ground [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%sabg, &
+ a_sabg, file_hist, 'f_sabg', itime_in_file, sumarea, filter, &
+ 'solar absorbed by ground','W/m2')
+
+ ! outgoing long-wave radiation from ground+canopy [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%olrg, &
+ a_olrg, file_hist, 'f_olrg', itime_in_file, sumarea, filter, &
+ 'outgoing long-wave radiation from ground+canopy','W/m2')
+
+ ! net radiation [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%rnet, &
+ a_rnet, file_hist, 'f_rnet', itime_in_file, sumarea, filter, &
+ 'net radiation','W/m2')
+
+ ! the error of water balance [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xerr, &
+ a_xerr, file_hist, 'f_xerr', itime_in_file, sumarea, filter, &
+ 'the error of water banace','mm/s')
+
+ ! the error of energy balance [W/m2]
+ CALL write_history_variable_2d ( DEF_hist_vars%zerr, &
+ a_zerr, file_hist, 'f_zerr', itime_in_file, sumarea, filter, &
+ 'the error of energy balance','W/m2')
+
+ ! surface runoff [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%rsur, &
+ a_rsur, file_hist, 'f_rsur', itime_in_file, sumarea, filter, &
+ 'surface runoff','mm/s')
+
+#ifndef CatchLateralFlow
+ ! saturation excess surface runoff [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%rsur_se, &
+ a_rsur_se, file_hist, 'f_rsur_se', itime_in_file, sumarea, filter, &
+ 'saturation excess surface runoff','mm/s')
+
+ ! infiltration excess surface runoff [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%rsur_ie, &
+ a_rsur_ie, file_hist, 'f_rsur_ie', itime_in_file, sumarea, filter, &
+ 'infiltration excess surface runoff','mm/s')
+#endif
+
+ ! subsurface runoff [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%rsub, &
+ a_rsub, file_hist, 'f_rsub', itime_in_file, sumarea, filter, &
+ 'subsurface runoff','mm/s')
+
+ ! total runoff [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%rnof, &
+ a_rnof, file_hist, 'f_rnof', itime_in_file, sumarea, filter, &
+ 'total runoff','mm/s')
+
+#ifdef DataAssimilation
+ IF (DEF_DA_TWS_GRACE) THEN
+ ! slope factors for runoff [-]
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ vecacc = fslp_k_mon(month, :)
+ WHERE (vecacc /= spval) vecacc = vecacc*nac
+ ENDIF
+ CALL write_history_variable_2d(.true., &
+ vecacc, file_hist, 'f_slope_factor_k', itime_in_file, sumarea, filter, &
+ 'slope factor [k] for runoff', '-')
+ ENDIF
+#endif
+
+#ifdef CatchLateralFlow
+ ! rate of surface water depth change [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xwsur, &
+ a_xwsur, file_hist, 'f_xwsur', itime_in_file, sumarea, filter, &
+ 'rate of surface water depth change','mm/s')
+
+ ! rate of ground water change [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%xwsub, &
+ a_xwsub, file_hist, 'f_xwsub', itime_in_file, sumarea, filter, &
+ 'rate of ground water change','mm/s')
+
+ ! fraction of flooded area [-]
+ CALL write_history_variable_2d ( DEF_hist_vars%fldarea, &
+ a_fldarea, file_hist, 'f_fldarea', itime_in_file, sumarea, filter, &
+ 'fraction of flooded area','-')
+#endif
+
+ ! interception [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%qintr, &
+ a_qintr, file_hist, 'f_qintr', itime_in_file, sumarea, filter, &
+ 'interception','mm/s')
+
+ ! infiltration [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%qinfl, &
+ a_qinfl, file_hist, 'f_qinfl', itime_in_file, sumarea, filter, &
+ 'f_qinfl','mm/s')
+
+ ! throughfall [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%qdrip, &
+ a_qdrip, file_hist, 'f_qdrip', itime_in_file, sumarea, filter, &
+ 'total throughfall','mm/s')
+
+ ! total water storage [mm]
+ CALL write_history_variable_2d ( DEF_hist_vars%wat, &
+ a_wat, file_hist, 'f_wat', itime_in_file, sumarea, filter, &
+ 'total water storage','mm')
+
+ ! instantaneous total water storage [mm]
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ vecacc = wat
+ WHERE(vecacc /= spval) vecacc = vecacc * nac
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%wat_inst, &
+ vecacc, file_hist, 'f_wat_inst', itime_in_file, sumarea, filter, &
+ 'instantaneous total water storage','mm')
+
+ ! canopy assimilation rate [mol m-2 s-1]
+ CALL write_history_variable_2d ( DEF_hist_vars%assim, &
+ a_assim, file_hist, 'f_assim', itime_in_file, sumarea, filter, &
+ 'canopy assimilation rate','mol m-2 s-1')
+
+ ! respiration (plant+soil) [mol m-2 s-1]
+ CALL write_history_variable_2d ( DEF_hist_vars%respc, &
+ a_respc, file_hist, 'f_respc', itime_in_file, sumarea, filter, &
+ 'respiration (plant+soil)','mol m-2 s-1')
+
+ ! groundwater recharge rate [mm/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%qcharge &
+ .and. (.not.DEF_USE_VariablySaturatedFlow), &
+ a_qcharge, file_hist, 'f_qcharge', itime_in_file, sumarea, filter, &
+ 'groundwater recharge rate','mm/s')
+
+ ! ground surface temperature [K]
+ CALL write_history_variable_2d ( DEF_hist_vars%t_grnd, &
+ a_t_grnd, file_hist, 'f_t_grnd', itime_in_file, sumarea, filter, &
+ 'ground surface temperature','K')
+
+ ! leaf temperature [K]
+ CALL write_history_variable_2d ( DEF_hist_vars%tleaf, &
+ a_tleaf, file_hist, 'f_tleaf', itime_in_file, sumarea, filter, &
+ 'leaf temperature','K')
+
+ ! depth of water on foliage [mm]
+ CALL write_history_variable_2d ( DEF_hist_vars%ldew, &
+ a_ldew, file_hist, 'f_ldew', itime_in_file, sumarea, filter, &
+ 'depth of water on foliage','mm')
+
+ ! snow cover, water equivalent [mm]
+ CALL write_history_variable_2d ( DEF_hist_vars%scv, &
+ a_scv, file_hist, 'f_scv', itime_in_file, sumarea, filter, &
+ 'snow cover, water equivalent','mm')
+
+ ! snow depth [meter]
+ CALL write_history_variable_2d ( DEF_hist_vars%snowdp, &
+ a_snowdp, file_hist, 'f_snowdp', itime_in_file, sumarea, filter, &
+ 'snow depth','meter')
+
+ ! fraction of snow cover on ground
+ CALL write_history_variable_2d ( DEF_hist_vars%fsno, &
+ a_fsno, file_hist, 'f_fsno', itime_in_file, sumarea, filter, &
+ 'fraction of snow cover on ground','-')
+
+ ! fraction of saturation area on ground
+ CALL write_history_variable_2d ( DEF_hist_vars%frcsat, &
+ a_frcsat, file_hist, 'f_frcsat', itime_in_file, sumarea, filter, &
+ 'fraction of saturation area on ground','-')
+
+ ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL write_history_variable_2d ( DEF_hist_vars%sigf, &
+ a_sigf, file_hist, 'f_sigf', itime_in_file, sumarea, filter, &
+ 'fraction of veg cover, excluding snow-covered veg','-')
+
+ ! leaf greenness
+ CALL write_history_variable_2d ( DEF_hist_vars%green, &
+ a_green, file_hist, 'f_green', itime_in_file, sumarea, filter, &
+ 'leaf greenness','-')
+
+ ! leaf area index
+ CALL write_history_variable_2d ( DEF_hist_vars%lai, &
+ a_lai, file_hist, 'f_lai', itime_in_file, sumarea, filter, &
+ 'leaf area index','m2/m2')
+
+ ! leaf area index
+ CALL write_history_variable_2d ( DEF_hist_vars%laisun, &
+ a_laisun, file_hist, 'f_laisun', itime_in_file, sumarea, filter, &
+ 'sunlit leaf area index','m2/m2')
+
+ ! leaf area index
+ CALL write_history_variable_2d ( DEF_hist_vars%laisha, &
+ a_laisha, file_hist, 'f_laisha', itime_in_file, sumarea, filter, &
+ 'shaded leaf area index','m2/m2')
+
+ ! stem area index
+ CALL write_history_variable_2d ( DEF_hist_vars%sai, &
+ a_sai, file_hist, 'f_sai', itime_in_file, sumarea, filter, &
+ 'stem area index','m2/m2')
+
+ ! averaged albedo [visible, direct; direct, diffuse]
+ CALL write_history_variable_4d ( DEF_hist_vars%alb, &
+ a_alb, file_hist, 'f_alb', itime_in_file, &
+ 'band', 1, 2, 'rtyp', 1, 2, sumarea_dt, filter_dt, &
+ 'averaged albedo','-',nac_dt)
+
+ ! averaged bulk surface emissivity
+ CALL write_history_variable_2d ( DEF_hist_vars%emis, &
+ a_emis, file_hist, 'f_emis', itime_in_file, sumarea, filter, &
+ 'averaged bulk surface emissivity','-')
+
+ ! effective roughness [m]
+ CALL write_history_variable_2d ( DEF_hist_vars%z0m, &
+ a_z0m, file_hist, 'f_z0m', itime_in_file, sumarea, filter, &
+ 'effective roughness','m')
+
+ ! radiative temperature of surface [K]
+ CALL write_history_variable_2d ( DEF_hist_vars%trad, &
+ a_trad, file_hist, 'f_trad', itime_in_file, sumarea, filter, &
+ 'radiative temperature of surface','kelvin')
+
+ ! 2 m height air temperature [kelvin]
+ CALL write_history_variable_2d ( DEF_hist_vars%tref, &
+ a_tref, file_hist, 'f_tref', itime_in_file, sumarea, filter, &
+ '2 m height air temperature','kelvin')
+
+IF (DEF_Output_2mWMO) THEN
+ ! 2 m WMO air temperature [kelvin]
+ CALL write_history_variable_2d ( DEF_hist_vars%t2m_wmo, &
+ a_t2m_wmo, file_hist, 'f_t2m_wmo', itime_in_file, sumarea, filter, &
+ '2 m WMO air temperature','kelvin')
+ENDIF
+
+ ! 2 m height air specific humidity [kg/kg]
+ CALL write_history_variable_2d ( DEF_hist_vars%qref, &
+ a_qref, file_hist, 'f_qref', itime_in_file, sumarea, filter, &
+ '2 m height air specific humidity','kg/kg')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype == 2
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (trim(file_hist) /= trim(file_last)) THEN
+ CALL hist_write_var_real8_2d (file_hist, 'area_wetland', ghist, -1, sumarea, &
+ compress = 1, longname = 'area of wetland', units = 'km2')
+ ENDIF
+ ENDIF
+
+ ! wetland water storage [mm]
+ IF (DEF_USE_Dynamic_Wetland) THEN
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ vecacc = a_wdsrf
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%wetwat, &
+ vecacc, file_hist, 'f_wetwat', itime_in_file, sumarea, filter, &
+ 'wetland water storage','mm')
+ ELSE
+ CALL write_history_variable_2d ( DEF_hist_vars%wetwat, &
+ a_wetwat, file_hist, 'f_wetwat', itime_in_file, sumarea, filter, &
+ 'wetland water storage','mm')
+ ENDIF
+
+ ! instantaneous wetland water storage [mm]
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ vecacc = wetwat
+ WHERE(vecacc /= spval) vecacc = vecacc * nac
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%wetwat_inst, &
+ vecacc, file_hist, 'f_wetwat_inst', itime_in_file, sumarea, filter, &
+ 'instantaneous wetland water storage','mm')
+
+ IF (p_is_compute .and. (numpatch > 0)) THEN
+ vecacc = a_zwt
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%wetzwt, &
+ vecacc, file_hist, 'f_wetzwt', itime_in_file, sumarea, filter, &
+ 'the depth to water table in wetland','m')
+
+ ! ------------------------------------------------------------------
+ ! Mapping the urban variables at patch [numurban] to grid
+ ! ------------------------------------------------------------------
+
+#ifdef URBAN_MODEL
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i = 1, numpatch
+ IF (patchtype(i) == 1) THEN
+ u = patch2urban(i)
+
+ filter_urb(u) = .true.
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter_urb(u) = filter_urb(u) .and. forcmask_pch(i)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist_urb%get_sumarea (sumarea_urb, filter_urb)
+ ENDIF
+
+ ! sensible heat from building roof [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fsen_roof, &
+ a_senroof, file_hist, 'f_fsenroof', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible heat from urban roof [W/m2]','W/m2')
+
+ ! sensible heat from building sunlit wall [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fsen_wsun, &
+ a_senwsun, file_hist, 'f_fsenwsun', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible heat from urban sunlit wall [W/m2]','W/m2')
+
+ ! sensible heat from building shaded wall [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fsen_wsha, &
+ a_senwsha, file_hist, 'f_fsenwsha', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible heat from urban shaded wall [W/m2]','W/m2')
+
+ ! sensible heat from impervious ground [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fsen_gimp, &
+ a_sengimp, file_hist, 'f_fsengimp', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible heat from urban impervious ground [W/m2]','W/m2')
+
+ ! sensible heat from pervious ground [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fsen_gper, &
+ a_sengper, file_hist, 'f_fsengper', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible heat from urban pervious ground [W/m2]','W/m2')
+
+ ! sensible heat from urban tree [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fsen_urbl, &
+ a_senurbl, file_hist, 'f_fsenurbl', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible heat from urban tree [W/m2]','W/m2')
+
+ ! latent heat flux from building roof [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%lfevp_roof, &
+ a_lfevproof, file_hist, 'f_lfevproof', itime_in_file, sumarea_urb, filter_urb, &
+ 'latent heat from urban roof [W/m2]','W/m2')
+
+ ! latent heat flux from impervious ground [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%lfevp_gimp, &
+ a_lfevpgimp, file_hist, 'f_lfevpgimp', itime_in_file, sumarea_urb, filter_urb, &
+ 'latent heat from urban impervious ground [W/m2]','W/m2')
+
+ ! latent heat flux from pervious ground [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%lfevp_gper, &
+ a_lfevpgper, file_hist, 'f_lfevpgper', itime_in_file, sumarea_urb, filter_urb, &
+ 'latent heat from urban pervious ground [W/m2]','W/m2')
+
+ ! latent heat flux from urban tree [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%lfevp_urbl, &
+ a_lfevpurbl, file_hist, 'f_lfevpurbl', itime_in_file, sumarea_urb, filter_urb, &
+ 'latent heat from urban tree [W/m2]','W/m2')
+
+ ! sensible flux from heat or cool AC [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fhac, &
+ a_fhac, file_hist, 'f_fhac', itime_in_file, sumarea_urb, filter_urb, &
+ 'sensible flux from heat or cool AC [W/m2]','W/m2')
+
+ ! waste heat flux from heat or cool AC [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fwst, &
+ a_fwst, file_hist, 'f_fwst', itime_in_file, sumarea_urb, filter_urb, &
+ 'waste heat flux from heat or cool AC [W/m2]','W/m2')
+
+ ! flux from inner and outer air exchange [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fach, &
+ a_fach, file_hist, 'f_fach', itime_in_file, sumarea_urb, filter_urb, &
+ 'flux from inner and outter air exchange [W/m2]','W/m2')
+
+ ! flux from total heating/cooling [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%fhah, &
+ a_fhah, file_hist, 'f_fhah', itime_in_file, sumarea_urb, filter_urb, &
+ 'flux from heating/cooling [W/m2]','W/m2')
+
+ ! flux from metabolism [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%meta, &
+ a_meta, file_hist, 'f_fmeta', itime_in_file, sumarea_urb, filter_urb, &
+ 'flux from human metabolism [W/m2]','W/m2')
+
+ ! flux from vehicle [W/m2]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%vehc, &
+ a_vehc, file_hist, 'f_fvehc', itime_in_file, sumarea_urb, filter_urb, &
+ 'flux from traffic [W/m2]','W/m2')
+
+ ! temperature of inner building [K]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%t_room, &
+ a_t_room, file_hist, 'f_t_room', itime_in_file, sumarea_urb, filter_urb, &
+ 'temperature of inner building [K]','kelvin')
+
+ ! temperature of outer building [K]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%tafu, &
+ a_tafu, file_hist, 'f_tafu', itime_in_file, sumarea_urb, filter_urb, &
+ 'temperature of outer building [K]','kelvin')
+
+ ! temperature of building roof [K]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%t_roof, &
+ a_troof, file_hist, 'f_t_roof', itime_in_file, sumarea_urb, filter_urb, &
+ 'temperature of urban roof [K]','kelvin')
+
+ ! temperature of building wall [K]
+ CALL write_history_variable_urb_2d ( DEF_hist_vars%t_wall, &
+ a_twall, file_hist, 'f_t_wall', itime_in_file, sumarea_urb, filter_urb, &
+ 'temperature of urban wall [K]','kelvin')
+#endif
+
+ ! ------------------------------------------------------------------
+ ! Mapping the fluxes and state variables at patch [numpatch] to grid
+ ! ------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ filter(:) = patchtype < 99
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! 1: assimsun enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%assimsun, &
+ a_assimsun, file_hist, 'f_assimsun', itime_in_file, sumarea, filter, &
+ 'Photosynthetic assimilation rate of sunlit leaf for needleleaf evergreen temperate tree',&
+ 'mol m-2 s-1')
+
+ ! 1: assimsha enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%assimsha, &
+ a_assimsha, file_hist, 'f_assimsha', itime_in_file, sumarea, filter, &
+ 'Photosynthetic assimilation rate of shaded leaf for needleleaf evergreen temperate tree',&
+ 'mol m-2 s-1')
+
+ ! 1: etrsun enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%etrsun, &
+ a_etrsun, file_hist, 'f_etrsun', itime_in_file, sumarea, filter, &
+ 'Transpiration rate of sunlit leaf for needleleaf evergreen temperate tree','mm s-1')
+
+ ! 1: etrsha enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%etrsha, &
+ a_etrsha, file_hist, 'f_etrsha', itime_in_file, sumarea, filter, &
+ 'Transpiration rate of shaded leaf for needleleaf evergreen temperate tree','mm s-1')
+
+ ! rstfacsun
+ CALL write_history_variable_2d ( DEF_hist_vars%rstfacsun, &
+ a_rstfacsun, file_hist, 'f_rstfacsun', itime_in_file, sumarea, filter, &
+ 'Ecosystem level Water stress factor on sunlit canopy','unitless')
+
+ ! rstfacsha
+ CALL write_history_variable_2d ( DEF_hist_vars%rstfacsha, &
+ a_rstfacsha, file_hist, 'f_rstfacsha', itime_in_file, sumarea, filter, &
+ 'Ecosystem level Water stress factor on shaded canopy','unitless')
+
+ ! gssun
+ CALL write_history_variable_2d ( DEF_hist_vars%gssun, &
+ a_gssun, file_hist, 'f_gssun', itime_in_file, sumarea, filter, &
+ 'Ecosystem level canopy conductance on sunlit canopy','mol m-2 s-1')
+
+ ! gssha
+ CALL write_history_variable_2d ( DEF_hist_vars%gssha, &
+ a_gssha, file_hist, 'f_gssha', itime_in_file, sumarea, filter, &
+ 'Ecosystem level canopy conductance on shaded canopy','mol m-2 s-1')
+
+ ! soil resistance [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%rss, &
+ a_rss, file_hist, 'f_rss', itime_in_file, sumarea, filter, &
+ 'soil surface resistance','s/m')
+
+#ifdef BGC
+ ! leaf carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc, &
+ a_leafc, file_hist, 'f_leafc', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool','gC/m2')
+
+ ! leaf carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_storage, &
+ a_leafc_storage, file_hist, 'f_leafc_storage', itime_in_file, sumarea, filter, &
+ 'leaf carbon storage pool','gC/m2')
+
+ ! leaf carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_xfer, &
+ a_leafc_xfer, file_hist, 'f_leafc_xfer', itime_in_file, sumarea, filter, &
+ 'leaf carbon transfer pool','gC/m2')
+
+ ! fine root carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootc, &
+ a_frootc, file_hist, 'f_frootc', itime_in_file, sumarea, filter, &
+ 'fine root carbon display pool','gC/m2')
+
+ ! fine root carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootc_storage, &
+ a_frootc_storage, file_hist, 'f_frootc_storage', itime_in_file, sumarea, filter, &
+ 'fine root carbon storage pool','gC/m2')
+
+ ! fine root carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootc_xfer, &
+ a_frootc_xfer, file_hist, 'f_frootc_xfer', itime_in_file, sumarea, filter, &
+ 'fine root carbon transfer pool','gC/m2')
+
+ ! live stem carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemc, &
+ a_livestemc, file_hist, 'f_livestemc', itime_in_file, sumarea, filter, &
+ 'live stem carbon display pool','gC/m2')
+
+ ! live stem carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemc_storage, &
+ a_livestemc_storage, file_hist, 'f_livestemc_storage', itime_in_file, sumarea, filter,&
+ 'live stem carbon storage pool','gC/m2')
+
+ ! live stem carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemc_xfer, &
+ a_livestemc_xfer, file_hist, 'f_livestemc_xfer', itime_in_file, sumarea, filter, &
+ 'live stem carbon transfer pool','gC/m2')
+
+ ! dead stem carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemc, &
+ a_deadstemc, file_hist, 'f_deadstemc', itime_in_file, sumarea, filter, &
+ 'dead stem carbon display pool','gC/m2')
+
+ ! dead stem carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemc_storage, &
+ a_deadstemc_storage, file_hist, 'f_deadstemc_storage', itime_in_file, sumarea, filter,&
+ 'dead stem carbon storage pool','gC/m2')
+
+ ! dead stem carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemc_xfer, &
+ a_deadstemc_xfer, file_hist, 'f_deadstemc_xfer', itime_in_file, sumarea, filter, &
+ 'dead stem carbon transfer pool','gC/m2')
+
+ ! live coarse root carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootc, &
+ a_livecrootc, file_hist, 'f_livecrootc', itime_in_file, sumarea, filter, &
+ 'live coarse root carbon display pool','gC/m2')
+
+ ! live coarse root carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootc_storage, &
+ a_livecrootc_storage, file_hist, 'f_livecrootc_storage', &
+ itime_in_file, sumarea, filter, &
+ 'live coarse root carbon storage pool','gC/m2')
+
+ ! live coarse root carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootc_xfer, &
+ a_livecrootc_xfer, file_hist, 'f_livecrootc_xfer', itime_in_file, sumarea, filter, &
+ 'live coarse root carbon transfer pool','gC/m2')
+
+ ! dead coarse root carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootc, &
+ a_deadcrootc, file_hist, 'f_deadcrootc', itime_in_file, sumarea, filter, &
+ 'dead coarse root carbon display pool','gC/m2')
+
+ ! dead coarse root carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootc_storage, &
+ a_deadcrootc_storage, file_hist, 'f_deadcrootc_storage', &
+ itime_in_file, sumarea, filter, &
+ 'dead coarse root carbon storage pool','gC/m2')
+
+ ! dead coarse root carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootc_xfer, &
+ a_deadcrootc_xfer, file_hist, 'f_deadcrootc_xfer', itime_in_file, sumarea, filter, &
+ 'dead coarse root carbon transfer pool','gC/m2')
+
+#ifdef CROP
+ ! grain carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%grainc, &
+ a_grainc, file_hist, 'f_grainc', itime_in_file, sumarea, filter, &
+ 'grain carbon display pool','gC/m2')
+
+ ! grain carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%grainc_storage, &
+ a_grainc_storage, file_hist, 'f_grainc_storage', itime_in_file, sumarea, filter, &
+ 'grain carbon storage pool','gC/m2')
+
+ ! grain carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%grainc_xfer, &
+ a_grainc_xfer, file_hist, 'f_grainc_xfer', itime_in_file, sumarea, filter, &
+ 'grain carbon transfer pool','gC/m2')
+#endif
+
+ ! leaf nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafn, &
+ a_leafn, file_hist, 'f_leafn', itime_in_file, sumarea, filter, &
+ 'leaf nitrogen display pool','gN/m2')
+
+ ! leaf nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafn_storage, &
+ a_leafn_storage, file_hist, 'f_leafn_storage', itime_in_file, sumarea, filter, &
+ 'leaf nitrogen storage pool','gN/m2')
+
+ ! leaf nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafn_xfer, &
+ a_leafn_xfer, file_hist, 'f_leafn_xfer', itime_in_file, sumarea, filter, &
+ 'leaf nitrogen transfer pool','gN/m2')
+
+ ! fine root nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootn, &
+ a_frootn, file_hist, 'f_frootn', itime_in_file, sumarea, filter, &
+ 'fine root nitrogen display pool','gN/m2')
+
+ ! fine root nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootn_storage, &
+ a_frootn_storage, file_hist, 'f_frootn_storage', itime_in_file, sumarea, filter, &
+ 'fine root nitrogen storage pool','gN/m2')
+
+ ! fine root nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootn_xfer, &
+ a_frootn_xfer, file_hist, 'f_frootn_xfer', itime_in_file, sumarea, filter, &
+ 'fine root nitrogen transfer pool','gN/m2')
+
+ ! live stem nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemn, &
+ a_livestemn, file_hist, 'f_livestemn', itime_in_file, sumarea, filter, &
+ 'live stem nitrogen display pool','gN/m2')
+
+ ! live stem nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemn_storage, &
+ a_livestemn_storage, file_hist, 'f_livestemn_storage', &
+ itime_in_file, sumarea, filter, &
+ 'live stem nitrogen storage pool','gN/m2')
+
+ ! live stem nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemn_xfer, &
+ a_livestemn_xfer, file_hist, 'f_livestemn_xfer', itime_in_file, sumarea, filter, &
+ 'live stem nitrogen transfer pool','gN/m2')
+
+ ! dead stem nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemn, &
+ a_deadstemn, file_hist, 'f_deadstemn', itime_in_file, sumarea, filter, &
+ 'dead stem nitrogen display pool','gN/m2')
+
+ ! dead stem nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemn_storage, &
+ a_deadstemn_storage, file_hist, 'f_deadstemn_storage', &
+ itime_in_file, sumarea, filter, &
+ 'dead stem nitrogen storage pool','gN/m2')
+
+ ! dead stem nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemn_xfer, &
+ a_deadstemn_xfer, file_hist, 'f_deadstemn_xfer', itime_in_file, sumarea, filter, &
+ 'dead stem nitrogen transfer pool','gN/m2')
+
+ ! live coarse root nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootn, &
+ a_livecrootn, file_hist, 'f_livecrootn', itime_in_file, sumarea, filter, &
+ 'live coarse root nitrogen display pool','gN/m2')
+
+ ! live coarse root nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootn_storage, &
+ a_livecrootn_storage, file_hist, 'f_livecrootn_storage', &
+ itime_in_file, sumarea, filter, &
+ 'live coarse root nitrogen storage pool','gN/m2')
+
+ ! live coarse root nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootn_xfer, &
+ a_livecrootn_xfer, file_hist, 'f_livecrootn_xfer', itime_in_file, sumarea, filter, &
+ 'live coarse root nitrogen transfer pool','gN/m2')
+
+ ! dead coarse root nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootn, &
+ a_deadcrootn, file_hist, 'f_deadcrootn', itime_in_file, sumarea, filter, &
+ 'dead coarse root nitrogen display pool','gN/m2')
+
+ ! dead coarse root nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootn_storage, &
+ a_deadcrootn_storage, file_hist, 'f_deadcrootn_storage', &
+ itime_in_file, sumarea, filter, &
+ 'dead coarse root nitrogen storage pool','gN/m2')
+
+ ! dead coarse root nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootn_xfer, &
+ a_deadcrootn_xfer, file_hist, 'f_deadcrootn_xfer', itime_in_file, sumarea, filter, &
+ 'dead coarse root nitrogen transfer pool','gN/m2')
+
+#ifdef CROP
+ ! grain nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%grainn, &
+ a_grainn, file_hist, 'f_grainn', itime_in_file, sumarea, filter, &
+ 'grain nitrogen display pool','gN/m2')
+
+ ! grain nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%grainn_storage, &
+ a_grainn_storage, file_hist, 'f_grainn_storage', itime_in_file, sumarea, filter, &
+ 'grain nitrogen storage pool','gN/m2')
+
+ ! grain nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%grainn_xfer, &
+ a_grainn_xfer, file_hist, 'f_grainn_xfer', itime_in_file, sumarea, filter, &
+ 'grain nitrogen transfer pool','gN/m2')
+#endif
+
+ ! retranslocation nitrogen pool
+ CALL write_history_variable_2d ( DEF_hist_vars%retrasn, &
+ a_retransn, file_hist, 'f_retrasn', itime_in_file, sumarea, filter, &
+ 'retranslocation nitrogen pool','gN/m2')
+
+ ! gross primary productivity
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp, &
+ a_gpp, file_hist, 'f_gpp', itime_in_file, sumarea, filter, &
+ 'gross primary productivity','gC/m2/s')
+
+ ! gross primary productivity
+ CALL write_history_variable_2d ( DEF_hist_vars%downreg, &
+ a_downreg, file_hist, 'f_downreg', itime_in_file, sumarea, filter, &
+ 'gpp downregulation due to N limitation','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fpg, &
+ a_fpg, file_hist, 'f_fpg', itime_in_file, sumarea, filter, &
+ 'fraction of gpp potential','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fpi, &
+ a_fpi, file_hist, 'f_fpi', itime_in_file, sumarea, filter, &
+ 'fraction of immobalization','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totvegc, &
+ a_totvegc, file_hist, 'f_totvegc', itime_in_file, sumarea, filter, &
+ 'total vegetation carbon','gC m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totlitc, &
+ a_totlitc, file_hist, 'f_totlitc', itime_in_file, sumarea, filter, &
+ 'total litter carbon','gC m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totsomc, &
+ a_totsomc, file_hist, 'f_totsomc', itime_in_file, sumarea, filter, &
+ 'total soil organic carbon','gC m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totcwdc, &
+ a_totcwdc, file_hist, 'f_totcwdc', itime_in_file, sumarea, filter, &
+ 'total coarse woody debris carbon','gC m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totcolc, &
+ a_totcolc, file_hist, 'f_totcolc', itime_in_file, sumarea, filter, &
+ 'total ecosystem carbon','gC m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totvegn, &
+ a_totvegn, file_hist, 'f_totvegn', itime_in_file, sumarea, filter, &
+ 'total vegetation nitrogen','gN m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totlitn, &
+ a_totlitn, file_hist, 'f_totlitn', itime_in_file, sumarea, filter, &
+ 'total litter nitrogen','gN m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totsomn, &
+ a_totsomn, file_hist, 'f_totsomn', itime_in_file, sumarea, filter, &
+ 'total soil organic nitrogen','gN m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totcwdn, &
+ a_totcwdn, file_hist, 'f_totcwdn', itime_in_file, sumarea, filter, &
+ 'total coarse woody debris nitrogen','gN m-2')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%totcoln, &
+ a_totcoln, file_hist, 'f_totcoln', itime_in_file, sumarea, filter, &
+ 'total ecosystem nitrogen','gN m-2')
+
+ ! autotrophic respiration
+ CALL write_history_variable_2d ( DEF_hist_vars%ar , &
+ a_ar, file_hist, 'f_ar', itime_in_file, sumarea, filter, &
+ 'autotrophic respiration','gC/m2/s')
+
+! ! CWD production
+! CALL write_history_variable_2d ( DEF_hist_vars%cwdprod , &
+! a_cwdprod, file_hist, 'f_cwdprod', itime_in_file, sumarea, filter, &
+! 'CWD production','gC/m2/s')
+!
+! ! CWD decomposition
+! CALL write_history_variable_2d ( DEF_hist_vars%cwddecomp , &
+! a_cwddecomp, file_hist, 'f_cwddecomp', itime_in_file, sumarea, filter, &
+! 'CWD decomposition','gC/m2/s')
+
+ ! heterotrophic respiration
+ CALL write_history_variable_2d ( DEF_hist_vars%hr , &
+ a_hr, file_hist, 'f_hr', itime_in_file, sumarea, filter, &
+ 'heterotrophic respiration','gC/m2/s')
+
+#ifdef CROP
+ ! crop phase
+ CALL write_history_variable_2d ( DEF_hist_vars%cphase, &
+ a_cphase, file_hist, 'f_cphase', itime_in_file, sumarea, filter, &
+ 'crop phase','unitless')
+
+ ! heat unit index
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_hui (:)
+ ENDIF
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%hui, &
+ vecacc, file_hist, 'f_hui', itime_in_file, sumarea, filter, &
+ 'heat unit index','unitless')
+
+ ! gdd needed to harvest
+ CALL write_history_variable_2d ( DEF_hist_vars%gddmaturity, &
+ a_gddmaturity, file_hist, 'f_gddmaturity', itime_in_file, sumarea, filter, &
+ 'gdd needed to harvest','ddays')
+
+ ! gdd past planting date for crop
+ CALL write_history_variable_2d ( DEF_hist_vars%gddplant, &
+ a_gddplant, file_hist, 'f_gddplant', itime_in_file, sumarea, filter, &
+ 'gdd past planting date for crop','ddays')
+
+ ! vernalization response
+ CALL write_history_variable_2d ( DEF_hist_vars%vf, &
+ a_vf, file_hist, 'f_vf', itime_in_file, sumarea, filter, &
+ 'vernalization response', 'unitless')
+
+ ! 1-yr crop production carbon
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprod1c, &
+ a_cropprod1c, file_hist, 'f_cropprod1c', itime_in_file, sumarea, filter, &
+ '1-yr crop production carbon','gC/m2')
+
+ ! loss rate of 1-yr crop production carbon
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprod1c_loss, &
+ a_cropprod1c_loss, file_hist, 'f_cropprod1c_loss', itime_in_file, sumarea, filter, &
+ 'loss rate of 1-yr crop production carbon','gC/m2/s')
+
+ ! crop seed deficit
+ CALL write_history_variable_2d ( DEF_hist_vars%cropseedc_deficit, &
+ a_cropseedc_deficit, file_hist, 'f_cropseedc_deficit', &
+ itime_in_file, sumarea, filter, &
+ 'crop seed deficit','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ ! grain to crop production carbon
+ CALL write_history_variable_2d ( DEF_hist_vars%grainc_to_cropprodc, &
+ vecacc, file_hist, 'f_grainc_to_cropprodc', itime_in_file, sumarea, filter, &
+ 'grain to crop production carbon','gC/m2/s')
+
+ ! grain to crop seed carbon
+ CALL write_history_variable_2d ( DEF_hist_vars%grainc_to_seed, &
+ a_grainc_to_seed, file_hist, 'f_grainc_to_seed', itime_in_file, sumarea, filter, &
+ 'grain to crop seed carbon','gC/m2/s')
+ ! grain to crop seed carbon
+ CALL write_history_variable_2d ( DEF_hist_vars%fert_to_sminn, &
+ a_fert_to_sminn, file_hist, 'f_fert_to_sminn', itime_in_file, sumarea, filter, &
+ 'fertilization','gN/m2/s')
+
+ IF (DEF_USE_IRRIGATION) THEN
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF((pftclass(patch_pft_s(i)).GE.npcropmin).and.(MOD(pftclass(patch_pft_s(i)),2).EQ.0))THEN
+ filter_irrig(i) = .true.
+ ELSE
+ filter_irrig(i) = .false.
+ ENDIF
+ ELSE
+ filter_irrig(i) = .false.
+ ENDIF
+ ENDDO
+ IF (DEF_forcing%has_missing_value) THEN
+ filter_irrig = filter_irrig .and. forcmask_pch
+ ENDIF
+ filter_irrig = filter_irrig .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea_irrig, filter_irrig)
+ ENDIF
+
+ ! total irrigation amounts at growing season
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_sum_irrig (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%sum_irrig, &
+ vecacc, file_hist, 'f_sum_irrig', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'total irrigation amounts at growing season','kg/m2')
+
+ ! total irrigation amounts demand at growing season
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_sum_deficit_irrig (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%sum_deficit_irrig, &
+ vecacc, file_hist, 'f_sum_deficit_irrig', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'total irrigation amounts demand at growing season','kg/m2')
+
+ ! total irrigation times at growing season
+ CALL write_history_variable_2d ( DEF_hist_vars%sum_irrig_count, &
+ a_sum_irrig_count, file_hist, 'f_sum_irrig_count', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'total irrigation times at growing season','-')
+
+ ! irrigation waterstorage [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_waterstorage (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%waterstorage, &
+ vecacc, file_hist, 'f_waterstorage', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation waterstorage','kg/m2')
+
+ ! irrigation demand for ground water [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_groundwater_demand (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%groundwater_demand, &
+ vecacc, file_hist, 'f_groundwater_demand', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation demand for ground water','kg/m2')
+
+ ! irrigation supply from ground water [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_groundwater_supply (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%groundwater_supply, &
+ vecacc, file_hist, 'f_groundwater_supply', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation supply from ground water','kg/m2')
+
+ ! irrigation demand for reservoir or river [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_reservoirriver_demand (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%reservoirriver_demand, &
+ vecacc, file_hist, 'f_reservoirriver_demand', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation demand for reservoir or river','kg/m2')
+
+ ! irrigation supply from reservoir or river [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_reservoirriver_supply (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%reservoirriver_supply, &
+ vecacc, file_hist, 'f_reservoirriver_supply', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation supply from reservoir or river','kg/m2')
+
+ ! irrigation supply from reservoir [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_reservoir_supply (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%reservoirriver_supply, &
+ vecacc, file_hist, 'f_reservoir_supply', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation supply from reservoir','kg/m2')
+
+ ! irrigation supply from river [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_river_supply (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%reservoirriver_supply, &
+ vecacc, file_hist, 'f_river_supply', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation supply from river','kg/m2')
+
+ ! irrigation supply from runoff [kg/m2]
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_runoff_supply (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%reservoirriver_supply, &
+ vecacc, file_hist, 'f_runoff_supply', itime_in_file, sumarea_irrig, filter_irrig, &
+ 'irrigation supply from runoff','kg/m2')
+ ENDIF
+#endif
+
+ ! grain to crop seed carbon
+ CALL write_history_variable_2d ( DEF_hist_vars%ndep_to_sminn, &
+ a_ndep_to_sminn, file_hist, 'f_ndep_to_sminn', itime_in_file, sumarea, filter, &
+ 'nitrogen deposition','gN/m2/s')
+
+ IF(DEF_USE_DiagMatrix)THEN
+ ! leaf carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafcCap, &
+ a_leafcCap, file_hist, 'f_leafcCap', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool Capacity','gC/m2')
+
+ ! leaf carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_storageCap, &
+ a_leafc_storageCap, file_hist, 'f_leafc_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'leaf carbon storage pool capacity','gC/m2')
+
+ ! leaf carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_xferCap, &
+ a_leafc_xferCap, file_hist, 'f_leafc_xferCap', itime_in_file, sumarea, filter, &
+ 'leaf carbon transfer pool capacity','gC/m2')
+
+ ! fine root carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootcCap, &
+ a_frootcCap, file_hist, 'f_frootcCap', itime_in_file, sumarea, filter, &
+ 'fine root carbon display pool Capacity','gC/m2')
+
+ ! fine root carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootc_storageCap, &
+ a_frootc_storageCap, file_hist, 'f_frootc_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'fine root carbon storage pool capacity','gC/m2')
+
+ ! fine root carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootc_xferCap, &
+ a_frootc_xferCap, file_hist, 'f_frootc_xferCap', itime_in_file, sumarea, filter, &
+ 'fine root carbon transfer pool capacity','gC/m2')
+
+ ! live stem carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemcCap, &
+ a_livestemcCap, file_hist, 'f_livestemcCap', itime_in_file, sumarea, filter, &
+ 'live stem carbon display pool Capacity','gC/m2')
+
+ ! live stem carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemc_storageCap, &
+ a_livestemc_storageCap, file_hist, 'f_livestemc_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'live stem carbon storage pool capacity','gC/m2')
+
+ ! live stem carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemc_xferCap, &
+ a_livestemc_xferCap, file_hist, 'f_livestemc_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'live stem carbon transfer pool capacity','gC/m2')
+
+ ! dead stem carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemcCap, &
+ a_deadstemcCap, file_hist, 'f_deadstemcCap', itime_in_file, sumarea, filter, &
+ 'dead stem carbon display pool Capacity','gC/m2')
+
+ ! dead stem carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemc_storageCap, &
+ a_deadstemc_storageCap, file_hist, 'f_deadstemc_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead stem carbon storage pool capacity','gC/m2')
+
+ ! dead stem carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemc_xferCap, &
+ a_deadstemc_xferCap, file_hist, 'f_deadstemc_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead stem carbon transfer pool capacity','gC/m2')
+
+ ! live coarse root carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootcCap, &
+ a_livecrootcCap, file_hist, 'f_livecrootcCap', itime_in_file, sumarea, filter, &
+ 'live coarse root carbon display pool Capacity','gC/m2')
+
+ ! live coarse root carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootc_storageCap, &
+ a_livecrootc_storageCap, file_hist, 'f_livecrootc_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'live coarse root carbon storage pool capacity','gC/m2')
+
+ ! live coarse root carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootc_xferCap, &
+ a_livecrootc_xferCap, file_hist, 'f_livecrootc_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'live coarse root carbon transfer pool capacity','gC/m2')
+
+ ! dead coarse root carbon display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootcCap, &
+ a_deadcrootcCap, file_hist, 'f_deadcrootcCap', itime_in_file, sumarea, filter, &
+ 'dead coarse root carbon display pool Capacity','gC/m2')
+
+ ! dead coarse root carbon storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootc_storageCap, &
+ a_deadcrootc_storageCap, file_hist, 'f_deadcrootc_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead coarse root carbon storage pool capacity','gC/m2')
+
+ ! dead coarse root carbon transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootc_xferCap, &
+ a_deadcrootc_xferCap, file_hist, 'f_deadcrootc_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead coarse root carbon transfer pool capacity','gC/m2')
+
+ ! leaf nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafnCap, &
+ a_leafnCap, file_hist, 'f_leafnCap', itime_in_file, sumarea, filter, &
+ 'leaf nitrogen display pool Capacity','gC/m2')
+
+ ! leaf nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafn_storageCap, &
+ a_leafn_storageCap, file_hist, 'f_leafn_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'leaf nitrogen storage pool capacity','gC/m2')
+
+ ! leaf nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%leafn_xferCap, &
+ a_leafn_xferCap, file_hist, 'f_leafn_xferCap', itime_in_file, sumarea, filter, &
+ 'leaf nitrogen transfer pool capacity','gC/m2')
+
+ ! fine root nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootnCap, &
+ a_frootnCap, file_hist, 'f_frootnCap', itime_in_file, sumarea, filter, &
+ 'fine root nitrogen display pool Capacity','gC/m2')
+
+ ! fine root nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootn_storageCap, &
+ a_frootn_storageCap, file_hist, 'f_frootn_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'fine root nitrogen storage pool capacity','gC/m2')
+
+ ! fine root nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%frootn_xferCap, &
+ a_frootn_xferCap, file_hist, 'f_frootn_xferCap', itime_in_file, sumarea, filter, &
+ 'fine root nitrogen transfer pool capacity','gC/m2')
+
+ ! live stem nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemnCap, &
+ a_livestemnCap, file_hist, 'f_livestemnCap', itime_in_file, sumarea, filter, &
+ 'live stem nitrogen display pool Capacity','gC/m2')
+
+ ! live stem nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemn_storageCap, &
+ a_livestemn_storageCap, file_hist, 'f_livestemn_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'live stem nitrogen storage pool capacity','gC/m2')
+
+ ! live stem nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livestemn_xferCap, &
+ a_livestemn_xferCap, file_hist, 'f_livestemn_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'live stem nitrogen transfer pool capacity','gC/m2')
+
+ ! dead stem nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemnCap, &
+ a_deadstemnCap, file_hist, 'f_deadstemnCap', itime_in_file, sumarea, filter, &
+ 'dead stem nitrogen display pool Capacity','gC/m2')
+
+ ! dead stem nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemn_storageCap, &
+ a_deadstemn_storageCap, file_hist, 'f_deadstemn_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead stem nitrogen storage pool capacity','gC/m2')
+
+ ! dead stem nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadstemn_xferCap, &
+ a_deadstemn_xferCap, file_hist, 'f_deadstemn_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead stem nitrogen transfer pool capacity','gC/m2')
+
+ ! live coarse root nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootnCap, &
+ a_livecrootnCap, file_hist, 'f_livecrootnCap', itime_in_file, sumarea, filter, &
+ 'live coarse root nitrogen display pool Capacity','gC/m2')
+
+ ! live coarse root nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootn_storageCap, &
+ a_livecrootn_storageCap, file_hist, 'f_livecrootn_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'live coarse root nitrogen storage pool capacity','gC/m2')
+
+ ! live coarse root nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%livecrootn_xferCap, &
+ a_livecrootn_xferCap, file_hist, 'f_livecrootn_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'live coarse root nitrogen transfer pool capacity','gC/m2')
+
+ ! dead coarse root nitrogen display pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootnCap, &
+ a_deadcrootnCap, file_hist, 'f_deadcrootnCap', itime_in_file, sumarea, filter, &
+ 'dead coarse root nitrogen display pool Capacity','gC/m2')
+
+ ! dead coarse root nitrogen storage pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootn_storageCap, &
+ a_deadcrootn_storageCap, file_hist, 'f_deadcrootn_storageCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead coarse root nitrogen storage pool capacity','gC/m2')
+
+ ! dead coarse root nitrogen transfer pool
+ CALL write_history_variable_2d ( DEF_hist_vars%deadcrootn_xferCap, &
+ a_deadcrootn_xferCap, file_hist, 'f_deadcrootn_xferCap', &
+ itime_in_file, sumarea, filter, &
+ 'dead coarse root nitrogen transfer pool capacity','gC/m2')
+
+ ENDIF
+
+ IF(DEF_USE_OZONESTRESS)THEN
+ ! ozone concentration
+ CALL write_history_variable_2d ( DEF_hist_vars%xy_ozone, &
+ a_ozone, file_hist, 'f_xy_ozone', itime_in_file, sumarea, filter, &
+ 'Ozone concentration','mol/mol')
+ ENDIF
+
+ ! litter 1 carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr1c_vr, &
+ a_litr1c_vr, file_hist, 'f_litr1c_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 1 carbon density in soil layers','gC/m3')
+
+ ! litter 2 carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr2c_vr, &
+ a_litr2c_vr, file_hist, 'f_litr2c_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 2 carbon density in soil layers','gC/m3')
+
+ ! litter 3 carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr3c_vr, &
+ a_litr3c_vr, file_hist, 'f_litr3c_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 3 carbon density in soil layers','gC/m3')
+
+ ! soil 1 carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil1c_vr, &
+ a_soil1c_vr, file_hist, 'f_soil1c_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 1 carbon density in soil layers','gC/m3')
+
+ ! soil 2 carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil2c_vr, &
+ a_soil2c_vr, file_hist, 'f_soil2c_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 2 carbon density in soil layers','gC/m3')
+
+ ! soil 3 carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil3c_vr, &
+ a_soil3c_vr, file_hist, 'f_soil3c_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 3 carbon density in soil layers','gC/m3')
+
+ ! coarse woody debris carbon density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%cwdc_vr, &
+ a_cwdc_vr, file_hist, 'f_cwdc_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'coarse woody debris carbon density in soil layers','gC/m3')
+
+ ! litter 1 nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr1n_vr, &
+ a_litr1n_vr, file_hist, 'f_litr1n_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 1 nitrogen density in soil layers','gN/m3')
+
+ ! litter 2 nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr2n_vr, &
+ a_litr2n_vr, file_hist, 'f_litr2n_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 2 nitrogen density in soil layers','gN/m3')
+
+ ! litter 3 nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr3n_vr, &
+ a_litr3n_vr, file_hist, 'f_litr3n_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 3 nitrogen density in soil layers','gN/m3')
+
+ ! soil 1 nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil1n_vr, &
+ a_soil1n_vr, file_hist, 'f_soil1n_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 1 nitrogen density in soil layers','gN/m3')
+
+ ! soil 2 nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil2n_vr, &
+ a_soil2n_vr, file_hist, 'f_soil2n_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 2 nitrogen density in soil layers','gN/m3')
+
+ ! soil 3 nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil3n_vr, &
+ a_soil3n_vr, file_hist, 'f_soil3n_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 3 nitrogen density in soil layers','gN/m3')
+
+ ! coarse woody debris nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%cwdn_vr, &
+ a_cwdn_vr, file_hist, 'f_cwdn_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'coarse woody debris nitrogen density in soil layers','gN/m3')
+
+ ! mineral nitrogen density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%sminn_vr, &
+ a_sminn_vr, file_hist, 'f_sminn_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'mineral nitrogen density in soil layers','gN/m3')
+
+ ! total nitrogen percentage in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%totsoiln_vr, &
+ a_totsoiln_vr, file_hist, 'f_totsoiln_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,&
+ 'Total nitrogen in soil layers, percentage of total soil nitrogen in total soil mass','%')
+
+ ! bulk density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%BD_all, &
+ a_BD_all, file_hist, 'f_BD_all', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'bulk density in soil layers','kg/m3')
+
+ ! field capacity in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%wfc, &
+ a_wfc, file_hist, 'f_wfc', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'field capacity in soil layers','m3/m3')
+
+ ! organic matter density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%OM_density, &
+ a_OM_density, file_hist, 'f_OM_density', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'organic matter density in soil layers','kg/m3')
+
+ IF (DEF_USE_NITRIF) THEN
+ ! O2 soil Concentration for non-inundated area
+ CALL write_history_variable_3d ( DEF_hist_vars%CONC_O2_UNSAT, &
+ a_conc_o2_unsat, file_hist, 'f_CONC_O2_UNSAT', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'O2 soil Concentration for non-inundated area','mol/m3')
+
+ ! O2 consumption from HR and AR for non-inundated area
+ CALL write_history_variable_3d ( DEF_hist_vars%O2_DECOMP_DEPTH_UNSAT, &
+ a_o2_decomp_depth_unsat, file_hist, 'f_O2_DECOMP_DEPTH_UNSAT', &
+ itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'O2 consumption from HR and AR for non-inundated area','mol/m3/s')
+ ENDIF
+
+ IF (DEF_USE_FIRE) THEN
+ CALL write_history_variable_2d ( DEF_hist_vars%abm, &
+ vecacc, file_hist, 'f_abm', itime_in_file, sumarea, filter, &
+ 'peak crop fire month','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%gdp, &
+ vecacc, file_hist, 'f_gdp', itime_in_file, sumarea, filter, &
+ 'gdp','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%peatf, &
+ vecacc, file_hist, 'f_peatf', itime_in_file, sumarea, filter, &
+ 'peatf','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%hdm, &
+ vecacc, file_hist, 'f_hdm', itime_in_file, sumarea, filter, &
+ 'hdm','unitless')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%lnfm, &
+ vecacc, file_hist, 'f_lnfm', itime_in_file, sumarea, filter, &
+ 'lnfm','unitless')
+ ENDIF
+
+ IF(DEF_USE_DiagMatrix)THEN
+ ! litter 1 carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr1cCap_vr, &
+ a_litr1cCap_vr, file_hist, 'f_litr1cCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 1 carbon capacity density in soil layers','gC/m3')
+
+ ! litter 2 carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr2cCap_vr, &
+ a_litr2cCap_vr, file_hist, 'f_litr2cCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 2 carbon capacity density in soil layers','gC/m3')
+
+ ! litter 3 carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr3cCap_vr, &
+ a_litr3cCap_vr, file_hist, 'f_litr3cCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 3 carbon capacity density in soil layers','gC/m3')
+
+ ! soil 1 carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil1cCap_vr, &
+ a_soil1cCap_vr, file_hist, 'f_soil1cCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 1 carbon capacity density in soil layers','gC/m3')
+
+ ! soil 2 carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil2cCap_vr, &
+ a_soil2cCap_vr, file_hist, 'f_soil2cCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 2 carbon capacity density in soil layers','gC/m3')
+
+ ! soil 3 carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil3cCap_vr, &
+ a_soil3cCap_vr, file_hist, 'f_soil3cCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 3 carbon capacity density in soil layers','gC/m3')
+
+ ! coarse woody debris carbon capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%cwdcCap_vr, &
+ a_cwdcCap_vr, file_hist, 'f_cwdcCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'coarse woody debris carbon capacity density in soil layers','gC/m3')
+
+ ! litter 1 nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr1nCap_vr, &
+ a_litr1nCap_vr, file_hist, 'f_litr1nCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 1 nitrogen capacity density in soil layers','gN/m3')
+
+ ! litter 2 nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr2nCap_vr, &
+ a_litr2nCap_vr, file_hist, 'f_litr2nCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 2 nitrogen capacity density in soil layers','gN/m3')
+
+ ! litter 3 nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%litr3nCap_vr, &
+ a_litr3nCap_vr, file_hist, 'f_litr3nCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'litter 3 nitrogen capacity density in soil layers','gN/m3')
+
+ ! soil 1 nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil1nCap_vr, &
+ a_soil1nCap_vr, file_hist, 'f_soil1nCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 1 nitrogen capacity density in soil layers','gN/m3')
+
+ ! soil 2 nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil2nCap_vr, &
+ a_soil2nCap_vr, file_hist, 'f_soil2nCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 2 nitrogen capacity density in soil layers','gN/m3')
+
+ ! soil 3 nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%soil3nCap_vr, &
+ a_soil3nCap_vr, file_hist, 'f_soil3nCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,'soil 3 nitrogen capacity density in soil layers','gN/m3')
+
+ ! coarse woody debris nitrogen capacity density in soil layers
+ CALL write_history_variable_3d ( DEF_hist_vars%cwdnCap_vr, &
+ a_cwdnCap_vr, file_hist, 'f_cwdnCap_vr', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter,&
+ 'coarse woody debris nitrogen capacity density in soil layers','gN/m3')
+
+ ! Temperature environmental scalar
+ CALL write_history_variable_3d ( DEF_hist_vars%t_scalar, &
+ a_t_scalar, file_hist, 'f_t_scalar', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter, 'Temperature environmental scalar','unitless')
+
+ ! Water environmental scalar
+ CALL write_history_variable_3d ( DEF_hist_vars%w_scalar, &
+ a_w_scalar, file_hist, 'f_w_scalar', itime_in_file, 'soil', 1, nl_soil, &
+ sumarea, filter, 'Water environmental scalar','unitless')
+
+ ENDIF
+
+
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) .ne. 12 .and. patchtype(i) .eq. 0)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! 1: gpp enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_enftemp, &
+ a_gpp_enftemp, file_hist, 'f_gpp_enftemp', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for needleleaf evergreen temperate tree','gC/m2/s')
+
+ ! 1: leaf carbon display pool enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_enftemp, &
+ a_leafc_enftemp, file_hist, 'f_leafc_enftemp', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for needleleaf evergreen temperate tree','gC/m2')
+
+ ! 1: leaf area index enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_enftemp, &
+ a_lai_enftemp, file_hist, 'f_lai_enftemp', itime_in_file, sumarea, filter, &
+ 'leaf area index for needleleaf evergreen temperate tree','m2/m2')
+
+ ! 1: npp enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_enftemp, &
+ a_npp_enftemp, file_hist, 'f_npp_enftemp', itime_in_file, sumarea, filter, &
+ 'npp for needleleaf evergreen temperate tree','m2/m2')
+
+ ! 1: npp to leafc enf temperate
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_enftemp, &
+ a_npptoleafc_enftemp, file_hist, 'f_npptoleafc_enftemp', itime_in_file, sumarea, filter, &
+ 'npp to leafc for needleleaf evergreen temperate tree','m2/m2')
+
+ ! 2: gpp enf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_enfboreal, &
+ a_gpp_enfboreal, file_hist, 'f_gpp_enfboreal', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for needleleaf evergreen boreal tree','gC/m2/s')
+
+ ! 2: leaf carbon display pool enf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_enfboreal, &
+ a_leafc_enfboreal, file_hist, 'f_leafc_enfboreal', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for needleleaf evergreen boreal tree','gC/m2')
+
+ ! 2: leaf area index enf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_enfboreal, &
+ a_lai_enfboreal, file_hist, 'f_lai_enfboreal', itime_in_file, sumarea, filter, &
+ 'leaf area index for needleleaf evergreen boreal tree','m2/m2')
+
+ ! 2: npp enf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_enfboreal, &
+ a_npp_enfboreal, file_hist, 'f_npp_enfboreal', itime_in_file, sumarea, filter, &
+ 'npp for needleleaf evergreen boreal tree','m2/m2')
+
+ ! 2: npp to leafc enf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_enfboreal, &
+ a_npptoleafc_enfboreal, file_hist, 'f_npptoleafc_enfboreal', itime_in_file, sumarea, filter, &
+ 'npp to leafc for needleleaf evergreen boreal tree','m2/m2')
+
+ ! 3: gpp dnf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_dnfboreal, &
+ a_gpp_dnfboreal, file_hist, 'f_gpp_dnfboreal', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for needleleaf deciduous boreal tree','gC/m2/s')
+
+ ! 3: leaf carbon display pool dnf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_dnfboreal, &
+ a_leafc_dnfboreal, file_hist, 'f_leafc_dnfboreal', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for needleleaf deciduous boreal tree','gC/m2')
+
+ ! 3: leaf area index dnf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_dnfboreal, &
+ a_lai_dnfboreal, file_hist, 'f_lai_dnfboreal', itime_in_file, sumarea, filter, &
+ 'leaf area index for needleleaf deciduous boreal tree','m2/m2')
+
+ ! 3: npp dnf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_dnfboreal, &
+ a_npp_dnfboreal, file_hist, 'f_npp_dnfboreal', itime_in_file, sumarea, filter, &
+ 'npp for needleleaf deciduous boreal tree','m2/m2')
+
+ ! 3: npp to leafc dnf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_dnfboreal, &
+ a_npptoleafc_dnfboreal, file_hist, 'f_npptoleafc_dnfboreal', itime_in_file, sumarea, filter, &
+ 'npp to leafc for needleleaf deciduous boreal tree','m2/m2')
+
+ ! 4: gpp ebf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_ebftrop, &
+ a_gpp_ebftrop, file_hist, 'f_gpp_ebftrop', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf evergreen tropical tree','gC/m2/s')
+
+ ! 4: leaf carbon display pool ebf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_ebftrop, &
+ a_leafc_ebftrop, file_hist, 'f_leafc_ebftrop', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf evergreen tropical tree','gC/m2')
+
+ ! 4: leaf area index ebf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_ebftrop, &
+ a_lai_ebftrop, file_hist, 'f_lai_ebftrop', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf evergreen tropical tree','m2/m2')
+
+ ! 4: npp ebf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_ebftrop, &
+ a_npp_ebftrop, file_hist, 'f_npp_ebftrop', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf evergreen tropical tree','m2/m2')
+
+ ! 4: npp to leafc ebf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_ebftrop, &
+ a_npptoleafc_ebftrop, file_hist, 'f_npptoleafc_ebftrop', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf evergreen tropical tree','m2/m2')
+
+ ! 5: gpp ebf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_ebftemp, &
+ a_gpp_ebftemp, file_hist, 'f_gpp_ebftemp', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf evergreen temperate tree','gC/m2/s')
+
+ ! 5: leaf carbon display pool ebf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_ebftemp, &
+ a_leafc_ebftemp, file_hist, 'f_leafc_ebftemp', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf evergreen temperate tree','gC/m2')
+
+ ! 5: leaf area index ebf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_ebftemp, &
+ a_lai_ebftemp, file_hist, 'f_lai_ebftemp', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf evergreen temperate tree','m2/m2')
+
+ ! 5: npp ebf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_ebftemp, &
+ a_npp_ebftemp, file_hist, 'f_npp_ebftemp', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf evergreen temperate tree','m2/m2')
+
+ ! 5: npp to leafc ebf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_ebftemp, &
+ a_npptoleafc_ebftemp, file_hist, 'f_npptoleafc_ebftemp', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf evergreen temperate tree','m2/m2')
+
+ ! 6: gpp dbf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_dbftrop, &
+ a_gpp_dbftrop, file_hist, 'f_gpp_dbftrop', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf deciduous tropical tree','gC/m2/s')
+
+ ! 6: leaf carbon display pool dbf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_dbftrop, &
+ a_leafc_dbftrop, file_hist, 'f_leafc_dbftrop', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf deciduous tropical tree','gC/m2')
+
+ ! 6: leaf area index dbf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_dbftrop, &
+ a_lai_dbftrop, file_hist, 'f_lai_dbftrop', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf evergreen temperate tree','m2/m2')
+
+ ! 6: npp dbf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_dbftrop, &
+ a_npp_dbftrop, file_hist, 'f_npp_dbftrop', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf evergreen temperate tree','m2/m2')
+
+ ! 6: npp to leafc dbf trop
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_dbftrop, &
+ a_npptoleafc_dbftrop, file_hist, 'f_npptoleafc_dbftrop', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf evergreen temperate tree','m2/m2')
+
+ ! 7: gpp dbf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_dbftemp, &
+ a_gpp_dbftemp, file_hist, 'f_gpp_dbftemp', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf deciduous temperate tree','gC/m2/s')
+
+ ! 7: leaf carbon display pool dbf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_dbftemp, &
+ a_leafc_dbftemp, file_hist, 'f_leafc_dbftemp', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf deciduous temperate tree','gC/m2')
+
+ ! 7: leaf area index dbf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_dbftemp, &
+ a_lai_dbftemp, file_hist, 'f_lai_dbftemp', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf decidous temperate tree','m2/m2')
+
+ ! 7: npp dbf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_dbftemp, &
+ a_npp_dbftemp, file_hist, 'f_npp_dbftemp', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf decidous temperate tree','m2/m2')
+
+ ! 7: npp to leafc dbf temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_dbftemp, &
+ a_npptoleafc_dbftemp, file_hist, 'f_npptoleafc_dbftemp', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf decidous temperate tree','m2/m2')
+
+ ! 8: gpp dbf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_dbfboreal, &
+ a_gpp_dbfboreal, file_hist, 'f_gpp_dbfboreal', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf deciduous boreal tree','gC/m2/s')
+
+ ! 8: leaf carbon display pool dbf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_dbfboreal, &
+ a_leafc_dbfboreal, file_hist, 'f_leafc_dbfboreal', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf deciduous boreal tree','gC/m2')
+
+ ! 8: leaf area index dbf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_dbfboreal, &
+ a_lai_dbfboreal, file_hist, 'f_lai_dbfboreal', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf decidous boreal tree','m2/m2')
+
+ ! 8: npp dbf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_dbfboreal, &
+ a_npp_dbfboreal, file_hist, 'f_npp_dbfboreal', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf decidous boreal tree','m2/m2')
+
+ ! 8: npp to leafc dbf boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_dbfboreal, &
+ a_npptoleafc_dbfboreal, file_hist, 'f_npptoleafc_dbfboreal', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf decidous boreal tree','m2/m2')
+
+ ! 9: gpp ebs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_ebstemp, &
+ a_gpp_ebstemp, file_hist, 'f_gpp_ebstemp', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf evergreen temperate shrub','gC/m2/s')
+
+ ! 9: leaf carbon display pool ebs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_ebstemp, &
+ a_leafc_ebstemp, file_hist, 'f_leafc_ebstemp', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf evergreen temperate shrub','gC/m2')
+
+ ! 9: leaf area index ebs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_ebstemp, &
+ a_lai_ebstemp, file_hist, 'f_lai_ebstemp', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf evergreen temperate shrub','m2/m2')
+
+ ! 9: npp ebs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_ebstemp, &
+ a_npp_ebstemp, file_hist, 'f_npp_ebstemp', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf evergreen temperate shrub','m2/m2')
+
+ ! 9: npp to leafc ebs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_ebstemp, &
+ a_npptoleafc_ebstemp, file_hist, 'f_npptoleafc_ebstemp', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf evergreen temperate shrub','m2/m2')
+
+ ! 10: gpp dbs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_dbstemp, &
+ a_gpp_dbstemp, file_hist, 'f_gpp_dbstemp', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf deciduous temperate shrub','gC/m2/s')
+
+ ! 10: leaf carbon display pool dbs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_dbstemp, &
+ a_leafc_dbstemp, file_hist, 'f_leafc_dbstemp', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf deciduous temperate shrub','gC/m2')
+
+ ! 10: leaf area index dbs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_dbstemp, &
+ a_lai_dbstemp, file_hist, 'f_lai_dbstemp', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf deciduous temperate shrub','m2/m2')
+
+ ! 10: npp dbs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_dbstemp, &
+ a_npp_dbstemp, file_hist, 'f_npp_dbstemp', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf deciduous temperate shrub','m2/m2')
+
+ ! 10: npp to leafc dbs temp
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_dbstemp, &
+ a_npptoleafc_dbstemp, file_hist, 'f_npptoleafc_dbstemp', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf deciduous temperate shrub','m2/m2')
+
+ ! 11: gpp dbs boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_dbsboreal, &
+ a_gpp_dbsboreal, file_hist, 'f_gpp_dbsboreal', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for broadleaf deciduous boreal shrub','gC/m2/s')
+
+ ! 11: leaf carbon display pool dbs boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_dbsboreal, &
+ a_leafc_dbsboreal, file_hist, 'f_leafc_dbsboreal', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for broadleaf deciduous boreal shrub','gC/m2')
+
+ ! 11: leaf area index dbs boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_dbsboreal, &
+ a_lai_dbsboreal, file_hist, 'f_lai_dbsboreal', itime_in_file, sumarea, filter, &
+ 'leaf area index for broadleaf deciduous boreal shrub','m2/m2')
+
+ ! 11: npp dbs boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_dbsboreal, &
+ a_npp_dbsboreal, file_hist, 'f_npp_dbsboreal', itime_in_file, sumarea, filter, &
+ 'npp for broadleaf deciduous boreal shrub','m2/m2')
+
+ ! 11: npp to leafc dbs boreal
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_dbsboreal, &
+ a_npptoleafc_dbsboreal, file_hist, 'f_npptoleafc_dbsboreal', itime_in_file, sumarea, filter, &
+ 'npp to leafc for broadleaf deciduous boreal shrub','m2/m2')
+
+ ! 12: gpp arctic c3 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_c3arcgrass, &
+ a_gpp_c3arcgrass, file_hist, 'f_gpp_c3arcgrass', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for c3 arctic grass','gC/m2/s')
+
+ ! 12: leaf carbon display pool c3 arctic grass
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_c3arcgrass, &
+ a_leafc_c3arcgrass, file_hist, 'f_leafc_c3arcgrass', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for c3 arctic grass','gC/m2')
+
+ ! 12: leaf area index c3 arctic grass
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_c3arcgrass, &
+ a_lai_c3arcgrass, file_hist, 'f_lai_c3arcgrass', itime_in_file, sumarea, filter, &
+ 'leaf area index for c3 arctic grass','gC/m2')
+
+ ! 12: npp c3 arctic grass
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_c3arcgrass, &
+ a_npp_c3arcgrass, file_hist, 'f_npp_c3arcgrass', itime_in_file, sumarea, filter, &
+ 'npp for c3 arctic grass','gC/m2')
+
+ ! 12: npp to leafc c3 arctic grass
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_c3arcgrass, &
+ a_npptoleafc_c3arcgrass, file_hist, 'f_npptoleafc_c3arcgrass', itime_in_file, sumarea, filter, &
+ 'npp to leafc for c3 arctic grass','gC/m2')
+
+ ! 13: gpp c3 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_c3grass, &
+ a_gpp_c3grass, file_hist, 'f_gpp_c3grass', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for c3 grass','gC/m2/s')
+
+ ! 13: leaf carbon display pool arctic c3 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_c3grass, &
+ a_leafc_c3grass, file_hist, 'f_leafc_c3grass', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for c3 arctic grass','gC/m2')
+
+ ! 13: leaf area index arctic c3 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_c3grass, &
+ a_lai_c3grass, file_hist, 'f_lai_c3grass', itime_in_file, sumarea, filter, &
+ 'leaf area index for c3 arctic grass','gC/m2')
+
+ ! 13: npp arctic c3 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_c3grass, &
+ a_npp_c3grass, file_hist, 'f_npp_c3grass', itime_in_file, sumarea, filter, &
+ 'npp for c3 arctic grass','gC/m2')
+
+ ! 13: npp to leafc arctic c3 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_c3grass, &
+ a_npptoleafc_c3grass, file_hist, 'f_npptoleafc_c3grass', itime_in_file, sumarea, filter, &
+ 'npp to leafc for c3 arctic grass','gC/m2')
+
+ ! 14: gpp c4 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%gpp_c4grass, &
+ a_gpp_c4grass, file_hist, 'f_gpp_c4grass', itime_in_file, sumarea, filter, &
+ 'gross primary productivity for c4 grass','gC/m2/s')
+
+ ! 14: leaf carbon display pool arctic c4 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%leafc_c4grass, &
+ a_leafc_c4grass, file_hist, 'f_leafc_c4grass', itime_in_file, sumarea, filter, &
+ 'leaf carbon display pool for c4 arctic grass','gC/m2')
+
+ ! 14: leaf area index arctic c4 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%lai_c4grass, &
+ a_lai_c4grass, file_hist, 'f_lai_c4grass', itime_in_file, sumarea, filter, &
+ 'leaf area index for c4 arctic grass','gC/m2')
+
+ ! 14: npp arctic c4 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%npp_c4grass, &
+ a_npp_c4grass, file_hist, 'f_npp_c4grass', itime_in_file, sumarea, filter, &
+ 'npp for c4 arctic grass','gC/m2')
+
+ ! 14: npp to leafc arctic c4 grass
+ CALL write_history_variable_2d ( DEF_hist_vars%npptoleafc_c4grass, &
+ a_npptoleafc_c4grass, file_hist, 'f_npptoleafc_c4grass', itime_in_file, sumarea, filter, &
+ 'npp to leafc for c4 arctic grass','gC/m2')
+
+#ifdef CROP
+!*****************************************
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_manunitro (:)
+ ENDIF
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%manunitro, &
+ vecacc, file_hist, 'f_manunitro', itime_in_file, sumarea, filter, &
+ 'nitrogen in manure','gN/m2/yr')
+
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 19 .or. pftclass(patch_pft_s(i)) .eq. 20)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_hui (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%huiswheat, &
+ vecacc, file_hist, 'f_huiswheat', itime_in_file, sumarea, filter, &
+ 'heat unit index (rainfed spring wheat)','unitless')
+
+!************************************************************
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 17 .or. pftclass(patch_pft_s(i)) .eq. 18 &
+! .or. pftclass(patch_pft_s(i)) .eq. 75 .or. pftclass(patch_pft_s(i)) .eq. 76)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdcorn, &
+! a_pdcorn, file_hist, 'f_pdcorn', &
+! itime_in_file, sumarea, filter, 'planting date of corn', 'day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 19 .or. pftclass(patch_pft_s(i)) .eq. 20)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdswheat, &
+! a_pdswheat, file_hist, 'f_pdswheat', &
+! itime_in_file, sumarea, filter,'planting date of spring wheat','day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 21 .or. pftclass(patch_pft_s(i)) .eq. 22)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdwwheat, &
+! a_pdwwheat, file_hist, 'f_pdwwheat', &
+! itime_in_file, sumarea, filter,'planting date of winter wheat','day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 23 .or. pftclass(patch_pft_s(i)) .eq. 24 &
+! .or. pftclass(patch_pft_s(i)) .eq. 77 .or. pftclass(patch_pft_s(i)) .eq. 78)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdsoybean, &
+! a_pdsoybean, file_hist, 'f_pdsoybean', &
+! itime_in_file, sumarea, filter,'planting date of soybean','day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 41 .or. pftclass(patch_pft_s(i)) .eq. 42)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdcotton, &
+! a_pdcotton, file_hist, 'f_pdcotton', &
+! itime_in_file, sumarea, filter,'planting date of cotton','day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 61 .or. pftclass(patch_pft_s(i)) .eq. 62)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdrice1, &
+! a_pdrice1, file_hist, 'f_pdrice1', &
+! itime_in_file, sumarea, filter,'planting date of rice1','day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 67 .or. pftclass(patch_pft_s(i)) .eq. 68)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdrice2, &
+! a_pdrice2, file_hist, 'f_pdrice2', &
+! itime_in_file, sumarea, filter,'planting date of rice2','day')
+!
+! IF (p_is_compute) THEN
+! IF (numpatch > 0) THEN
+! DO i=1,numpatch
+! IF(patchclass(i) == 12)THEN
+! IF(pftclass(patch_pft_s(i)) .eq. 67 .or. pftclass(patch_pft_s(i)) .eq. 68)THEN
+! filter(i) = .true.
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ELSE
+! filter(i) = .false.
+! ENDIF
+! ENDDO
+! ENDIF
+! ENDIF
+!
+! IF (HistForm == 'Gridded') THEN
+! CALL mp2g_hist%get_sumarea (sumarea, filter)
+! ENDIF
+!
+! CALL write_history_variable_2d ( DEF_hist_vars%pdsugarcane, &
+! a_pdsugarcane, file_hist, 'f_pdsugarcane', &
+! itime_in_file, sumarea, filter,'planting date of sugarcane','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 17 .or. pftclass(patch_pft_s(i)) .eq. 18 &
+ .or. pftclass(patch_pft_s(i)) .eq. 75 .or. pftclass(patch_pft_s(i)) .eq. 76)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_corn, &
+ a_fertnitro_corn, file_hist, 'f_fertnitro_corn', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for corn','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 19 .or. pftclass(patch_pft_s(i)) .eq. 20)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_swheat, &
+ a_fertnitro_swheat, file_hist, 'f_fertnitro_swheat', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for spring wheat','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 21 .or. pftclass(patch_pft_s(i)) .eq. 22)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_wwheat, &
+ a_fertnitro_wwheat, file_hist, 'f_fertnitro_wwheat', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for winter wheat','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 23 .or. pftclass(patch_pft_s(i)) .eq. 24 &
+ .or. pftclass(patch_pft_s(i)) .eq. 77 .or. pftclass(patch_pft_s(i)) .eq. 78)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_soybean, &
+ a_fertnitro_soybean, file_hist, 'f_fertnitro_soybean', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for soybean','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 41 .or. pftclass(patch_pft_s(i)) .eq. 42)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_cotton, &
+ a_fertnitro_cotton, file_hist, 'f_fertnitro_cotton', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for cotton','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 61 .or. pftclass(patch_pft_s(i)) .eq. 62)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_rice1, &
+ a_fertnitro_rice1, file_hist, 'f_fertnitro_rice1', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for rice1','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 61 .or. pftclass(patch_pft_s(i)) .eq. 62)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_rice2, &
+ a_fertnitro_rice2, file_hist, 'f_fertnitro_rice2', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for rice2','gN/m2/yr')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 67 .or. pftclass(patch_pft_s(i)) .eq. 68)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%fertnitro_sugarcane, &
+ a_fertnitro_sugarcane, file_hist, 'f_fertnitro_sugarcane', &
+ itime_in_file, sumarea, filter,'nitrogen fertilizer for sugarcane','gN/m2/yr')
+
+ IF(DEF_USE_IRRIGATION)THEN
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 17)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_corn, &
+ a_irrig_method_corn, file_hist, 'f_irrig_method_corn', &
+ itime_in_file, sumarea, filter,'irrigation method for corn','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.19 .or. pftclass(patch_pft_s(i)).eq.20)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_swheat, &
+ a_irrig_method_swheat, file_hist, 'f_irrig_method_swheat', &
+ itime_in_file, sumarea, filter,'irrigation method for spring wheat','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.21 .or. pftclass(patch_pft_s(i)).eq.22)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_wwheat, &
+ a_irrig_method_wwheat, file_hist, 'f_irrig_method_wwheat', &
+ itime_in_file, sumarea, filter,'irrigation method for winter wheat','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.23 .or. pftclass(patch_pft_s(i)).eq.24 &
+ .or. pftclass(patch_pft_s(i)).eq.77 .or. pftclass(patch_pft_s(i)).eq.78)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_soybean, &
+ a_irrig_method_soybean, file_hist, 'f_irrig_method_soybean', &
+ itime_in_file, sumarea, filter,'irrigation method for soybean','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.41 .or. pftclass(patch_pft_s(i)).eq.42)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_cotton, &
+ a_irrig_method_cotton, file_hist, 'f_irrig_method_cotton', &
+ itime_in_file, sumarea, filter,'irrigation method for cotton','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.61 .or. pftclass(patch_pft_s(i)).eq.62)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_rice1, &
+ a_irrig_method_rice1, file_hist, 'f_irrig_method_rice1', &
+ itime_in_file, sumarea, filter,'irrigation method for rice1','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.61 .or. pftclass(patch_pft_s(i)).eq.62)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_rice2, &
+ a_irrig_method_rice2, file_hist, 'f_irrig_method_rice2', &
+ itime_in_file, sumarea, filter,'irrigation method for rice2','-')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)).eq.67 .or. pftclass(patch_pft_s(i)).eq.68)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%irrig_method_sugarcane, &
+ a_irrig_method_sugarcane, file_hist, 'f_irrig_method_sugarcane', &
+ itime_in_file, sumarea, filter,'irrigation method for sugarcane','-')
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 17)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed temperate corn
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_temp_corn, &
+ vecacc, file_hist, 'f_plantdate_rainfed_temp_corn', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed temperate corn)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 18)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated temperate corn
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_temp_corn, &
+ vecacc, file_hist, 'f_plantdate_irrigated_temp_corn', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated temperate corn)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 19)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed spring wheat
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_spwheat, &
+ vecacc, file_hist, 'f_plantdate_rainfed_spwheat', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed spring wheat)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 20)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated spring wheat
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_spwheat, &
+ vecacc, file_hist, 'f_plantdate_irrigated_spwheat', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated spring wheat)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 21)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed winter wheat
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_wtwheat, &
+ vecacc, file_hist, 'f_plantdate_rainfed_wtwheat', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed winter wheat)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 22)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated winter wheat
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_wtwheat, &
+ vecacc, file_hist, 'f_plantdate_irrigated_wtwheat', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated winter wheat)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 23)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed temperate soybean
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_temp_soybean, &
+ vecacc, file_hist, 'f_plantdate_rainfed_temp_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed temperate soybean)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 24)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated temperate soybean
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_temp_soybean, &
+ vecacc, file_hist, 'f_plantdate_irrigated_temp_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated temperate soybean)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 41)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed cotton
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_cotton, &
+ vecacc, file_hist, 'f_plantdate_rainfed_cotton', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed cotton)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 42)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated cotton
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_cotton, &
+ vecacc, file_hist, 'f_plantdate_irrigated_cotton', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated cotton)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 61)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed rice
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_rice, &
+ vecacc, file_hist, 'f_plantdate_rainfed_rice', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed rice)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 62)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated rice
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_rice, &
+ vecacc, file_hist, 'f_plantdate_irrigated_rice', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated rice)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 67)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed sugarcane
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_sugarcane, &
+ vecacc, file_hist, 'f_plantdate_rainfed_sugarcane', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed sugarcane)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 68)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated sugarcane
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_sugarcane, &
+ vecacc, file_hist, 'f_plantdate_irrigated_sugarcane', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated sugarcane)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 75)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed trop corn
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_trop_corn, &
+ vecacc, file_hist, 'f_plantdate_rainfed_trop_corn', itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed trop corn)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 76)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated trop corn
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_trop_corn, &
+ vecacc, file_hist, 'f_plantdate_irrigated_trop_corn', itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated trop corn)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 77)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of rainfed trop soybean
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_rainfed_trop_soybean, &
+ vecacc, file_hist, 'f_plantdate_rainfed_trop_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop planting date (rainfed trop soybean)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 78)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of irrigated trop soybean
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_irrigated_trop_soybean, &
+ vecacc, file_hist, 'f_plantdate_irrigated_trop_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop planting date (irrigated trop soybean)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 15)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! planting date of unmanaged crop production
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_plantdate (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%plantdate_unmanagedcrop, &
+ vecacc, file_hist, 'f_plantdate_unmanagedcrop', itime_in_file, sumarea, filter, &
+ 'Crop planting date (unmanaged crop production)','day')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 17)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to corn production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_temp_corn, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_temp_corn', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed temperate corn)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 18)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to corn production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_temp_corn, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_temp_corn', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated temperate corn)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 19)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to spring wheat production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_spwheat, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_spwheat', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed spring wheat)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 20)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to spring wheat production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_spwheat, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_spwheat', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated spring wheat)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 21)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to winter wheat production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_wtwheat, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_wtwheat', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed winter wheat)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 22)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to winter wheat production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_wtwheat, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_wtwheat', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated winter wheat)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 23)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to soybean production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_temp_soybean, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_temp_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed temperate soybean)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 24)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to soybean production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_temp_soybean, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_temp_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated temperate soybean)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 41)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to cotton production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_cotton, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_cotton', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed cotton)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 42)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to cotton production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_cotton, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_cotton', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated cotton)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 61)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to rice production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_rice, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_rice', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed rice)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 62)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to rice production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_rice, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_rice', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated rice)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 67)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to sugarcane production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_sugarcane, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_sugarcane', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed sugarcane)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 68)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to sugarcane production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_sugarcane, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_sugarcane', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated sugarcane)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 75)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to sugarcane production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_trop_corn, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_trop_corn', itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed_trop_corn)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 76)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to sugarcane production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_trop_corn, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_trop_corn', itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated_trop_corn)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 77)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to sugarcane production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_rainfed_trop_soybean, &
+ vecacc, file_hist, 'f_cropprodc_rainfed_trop_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop production (rainfed trop soybean)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 78)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to sugarcane production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_irrigated_trop_soybean, &
+ vecacc, file_hist, 'f_cropprodc_irrigated_trop_soybean', &
+ itime_in_file, sumarea, filter, &
+ 'Crop production (irrigated trop soybean)','gC/m2/s')
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO i=1,numpatch
+ IF(patchclass(i) == 12)THEN
+ IF(pftclass(patch_pft_s(i)) .eq. 15)THEN
+ filter(i) = .true.
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ELSE
+ filter(i) = .false.
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! grain to unmanaged crop production carbon
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ vecacc (:) = a_grainc_to_cropprodc (:)
+ ENDIF
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%cropprodc_unmanagedcrop, &
+ vecacc, file_hist, 'f_cropprodc_unmanagedcrop', itime_in_file, sumarea, filter, &
+ 'Crop production (unmanaged crop production)','gC/m2/s')
+#endif
+#endif
+ ! --------------------------------------------------------------------
+ ! Temperature and water (excluding land water bodies and ocean patches)
+ ! [soil => 0; urban and built-up => 1; wetland => 2; land ice => 3;
+ ! land water bodies => 4; ocean => 99]
+ ! --------------------------------------------------------------------
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype <= 3
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! soil temperature [K]
+ CALL write_history_variable_3d ( DEF_hist_vars%t_soisno, &
+ a_t_soisno, file_hist, 'f_t_soisno', &
+ itime_in_file, 'soilsnow', maxsnl+1, nl_soil-maxsnl, &
+ sumarea, filter, 'soil temperature','K')
+
+ ! liquid water in soil layers [kg/m2]
+ CALL write_history_variable_3d ( DEF_hist_vars%wliq_soisno, &
+ a_wliq_soisno, file_hist, 'f_wliq_soisno', &
+ itime_in_file, 'soilsnow', maxsnl+1, nl_soil-maxsnl, &
+ sumarea, filter,'liquid water in soil layers','kg/m2')
+
+ ! ice lens in soil layers [kg/m2]
+ CALL write_history_variable_3d ( DEF_hist_vars%wice_soisno, &
+ a_wice_soisno, file_hist, 'f_wice_soisno', &
+ itime_in_file, 'soilsnow', maxsnl+1, nl_soil-maxsnl, &
+ sumarea, filter, 'ice lens in soil layers', 'kg/m2')
+
+
+#ifdef DataAssimilation
+ IF (p_is_compute) THEN
+ allocate (a_wliq_h2osoi_5cm (numpatch )); a_wliq_h2osoi_5cm = spval
+ allocate (a_t_soisno_5cm (numpatch )); a_t_soisno_5cm = spval
+
+ allocate (a_wliq_soisno_ens_mean(maxsnl+1:nl_soil,numpatch)); a_wliq_soisno_ens_mean = spval
+ allocate (a_wliq_soisno_5cm_ens (DEF_DA_ENS_NUM,numpatch )); a_wliq_soisno_5cm_ens = spval
+ allocate (a_wliq_h2osoi_5cm_a (numpatch )); a_wliq_h2osoi_5cm_a = spval
+
+ allocate (a_t_soisno_ens_mean (maxsnl+1:nl_soil,numpatch)); a_t_soisno_ens_mean = spval
+ allocate (a_t_soisno_5cm_ens (DEF_DA_ENS_NUM,numpatch )); a_t_soisno_5cm_ens = spval
+ allocate (a_t_soisno_5cm_a (numpatch )); a_t_soisno_5cm_a = spval
+
+ allocate (a_t_brt_smap_a (2,numpatch )); a_t_brt_smap_a = spval
+ allocate (a_t_brt_fy3d_a (2,numpatch )); a_t_brt_fy3d_a = spval
+
+ allocate (a_wliq_soisno_5cm_ens_std(numpatch )); a_wliq_soisno_5cm_ens_std = spval
+ allocate (a_t_soisno_5cm_ens_std (numpatch )); a_t_soisno_5cm_ens_std = spval
+ allocate (a_t_brt_smap_ens_std (2,numpatch )); a_t_brt_smap_ens_std = spval
+ allocate (a_t_brt_fy3d_ens_std (2,numpatch )); a_t_brt_fy3d_ens_std = spval
+ END IF
+
+ IF (p_is_compute) THEN
+!#############################################################################
+! States before DA
+!#############################################################################
+ ! calculate surface liquid soil moisture (0-5cm) before DA
+ a_wliq_h2osoi_5cm = (a_wliq_soisno(1,:) + a_wliq_soisno(2,:) + &
+ a_wliq_soisno(3, :)*(0.05 - 0.0451)/(0.0906 - 0.0451))/(0.05*denh2o)
+
+ ! calculate surface liquid soil moisture (0-5cm) before DA
+ a_t_soisno_5cm = (a_t_soisno(1,:)*0.0175 + a_t_soisno(2,:)*(0.0451 - 0.0175))/(0.0451)
+
+!#############################################################################
+! States after DA
+!#############################################################################
+ ! calculate surface liquid soil moisture (0-5cm) after DA
+ a_wliq_soisno_ens_mean = sum(a_wliq_soisno_ens, dim=2) / DEF_DA_ENS_NUM
+ a_wliq_soisno_5cm_ens = (a_wliq_soisno_ens(1,:,:) + a_wliq_soisno_ens(2,:,:) + &
+ a_wliq_soisno_ens(3,:,:)*(0.05-0.0451)/(0.0906-0.0451))/(0.05*denh2o)
+ a_wliq_h2osoi_5cm_a = (a_wliq_soisno_ens_mean(1,:) + a_wliq_soisno_ens_mean(2,:) + &
+ a_wliq_soisno_ens_mean(3,:)*(0.05 - 0.0451)/(0.0906 - 0.0451))/(0.05*denh2o)
+
+ ! calculate surface soil temperature (0-5cm) before DA & after DA
+ a_t_soisno_ens_mean = sum(a_t_soisno_ens, dim=2) / DEF_DA_ENS_NUM
+ a_t_soisno_5cm_ens = (a_t_soisno_ens(1,:,:)*0.0175 + a_t_soisno_ens(2,:,:)*(0.0451 - 0.0175))/(0.0451)
+ a_t_soisno_5cm_a = (a_t_soisno_ens_mean(1,:)*0.0175 + a_t_soisno_ens_mean(2,:)*(0.0451 - 0.0175))/(0.0451)
+
+!#############################################################################
+! brightness temperature after DA
+!#############################################################################
+ a_t_brt_smap_a = sum(a_t_brt_smap_ens, dim=2) / DEF_DA_ENS_NUM
+ a_t_brt_fy3d_a = sum(a_t_brt_fy3d_ens, dim=2) / DEF_DA_ENS_NUM
+
+!#############################################################################
+! Standard deviation of states and brightness temperature
+!#############################################################################
+ ! calculate standard deviation of surface soil moisture, temperature and brightness temperature
+ DO np = 1, numpatch
+ a_wliq_soisno_5cm_ens_std(np) = &
+ sqrt(sum((a_wliq_soisno_5cm_ens(:,np)-a_wliq_h2osoi_5cm_a(np))**2)/real(DEF_DA_ENS_NUM-1))
+ a_t_soisno_5cm_ens_std(np) = &
+ sqrt(sum((a_t_soisno_5cm_ens(:,np)-a_t_soisno_5cm_a(np))**2)/real(DEF_DA_ENS_NUM-1))
+ IF (DEF_DA_SM_SMAP) THEN
+ IF (patchtype(np) >= 3) cycle
+ a_t_brt_smap_ens_std(1,np) = &
+ sqrt(sum((a_t_brt_smap_ens(1,:,np)-a_t_brt_smap_a(1,np))**2)/real(DEF_DA_ENS_NUM-1))
+ a_t_brt_smap_ens_std(2,np) = &
+ sqrt(sum((a_t_brt_smap_ens(2,:,np)-a_t_brt_smap_a(2,np))**2)/real(DEF_DA_ENS_NUM-1))
+ ENDIF
+ IF (DEF_DA_SM_FY) THEN
+ IF (patchtype(np) >= 3) cycle
+ a_t_brt_fy3d_ens_std(1,np) = &
+ sqrt(sum((a_t_brt_fy3d_ens(1,:,np)-a_t_brt_fy3d_a(1,np))**2)/real(DEF_DA_ENS_NUM-1))
+ a_t_brt_fy3d_ens_std(2,np) = &
+ sqrt(sum((a_t_brt_fy3d_ens(2,:,np)-a_t_brt_fy3d_a(2,np))**2)/real(DEF_DA_ENS_NUM-1))
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! surface soil moisture (0-5cm) before and after DA
+ CALL write_history_variable_2d(DEF_hist_vars%DA_wliq_h2osoi_5cm, &
+ a_wliq_h2osoi_5cm, file_hist, 'f_wliq_h2osoi_5cm', itime_in_file, &
+ sumarea, filter, 'Volumetric liquid water content in 0-5cm', 'm3/m3')
+ CALL write_history_variable_2d(DEF_hist_vars%DA_wliq_h2osoi_5cm_a, &
+ a_wliq_h2osoi_5cm_a, file_hist, 'f_wliq_h2osoi_5cm_a', itime_in_file, &
+ sumarea, filter, 'Analysis volumetric liquid water content in 0-5cm', 'm3/m3')
+
+ ! surface soil temperature (0-5cm) before and after DA
+ CALL write_history_variable_2d(DEF_hist_vars%DA_t_soisno_5cm, &
+ a_t_soisno_5cm, file_hist, 'f_t_soisno_5cm', itime_in_file, &
+ sumarea, filter, 'Soil temperature in 0-5cm', 'K')
+ CALL write_history_variable_2d(DEF_hist_vars%DA_t_soisno_5cm_a, &
+ a_t_soisno_5cm_a, file_hist, 'f_t_soisno_5cm_a', itime_in_file, &
+ sumarea, filter, 'Analysis soil temperature in 0-5cm', 'K')
+
+ ! ensemble soil moisture & temperature in soil layers [kg/m2]
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ CALL write_history_variable_4d(DEF_hist_vars%DA_wliq_soisno_ens, &
+ a_wliq_soisno_ens, file_hist, 'f_wliq_soisno_ens', itime_in_file, 'soilsnow', maxsnl + 1, nl_soil - maxsnl, &
+ 'ens', 1, DEF_DA_ENS_NUM, sumarea, filter, 'ensemble liquid water in soil layers', 'kg/m2')
+ CALL write_history_variable_4d(DEF_hist_vars%DA_t_soisno_ens, &
+ a_t_soisno_ens, file_hist, 'f_t_soisno_ens', itime_in_file, 'soilsnow', maxsnl + 1, nl_soil - maxsnl, &
+ 'ens', 1, DEF_DA_ENS_NUM, sumarea, filter, 'ensemble soil temperature', 'K')
+ ENDIF
+
+ ! standard deviation of ensemble surface soil moisture and temperature (0-5cm)
+ CALL write_history_variable_2d(DEF_hist_vars%DA_wliq_soisno_5cm_ens_std, &
+ a_wliq_soisno_5cm_ens_std, file_hist, 'f_wliq_soisno_ens_5cm_ens_std', itime_in_file, &
+ sumarea, filter, 'Standard deviation of ensemble volumetric liquid water content in 0-5cm', 'm3/m3')
+ CALL write_history_variable_2d(DEF_hist_vars%DA_t_soisno_5cm_ens_std, &
+ a_t_soisno_5cm_ens_std, file_hist, 'f_t_soisno_ens_5cm_ens_std', itime_in_file, &
+ sumarea, filter, 'Standard deviation of ensemble soil temperature in 0-5cm', 'K')
+
+ ! --------------------------------------------------------------------
+ ! brightness temperature (excluding land ice, land water bodies and ocean patches)
+ ! [soil => 0; urban and built-up => 1; wetland => 2; land ice => 3;
+ ! land water bodies => 4; ocean => 99]
+ ! --------------------------------------------------------------------
+
+ IF (HistForm == 'Gridded') THEN
+ IF (p_is_active) THEN
+ CALL allocate_block_data(ghist, sumarea)
+ END IF
+ END IF
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype <= 2
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ END IF
+
+ filter = filter .and. patchmask
+ END IF
+ END IF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea(sumarea, filter)
+ END IF
+
+ ! brightness temperature for SMAP and FY satellites
+ IF (DEF_DA_SM_SMAP) THEN
+ CALL write_history_variable_3d(DEF_hist_vars%DA_t_brt_smap, &
+ a_t_brt_smap, file_hist, 'f_t_brt_smap', itime_in_file, 'band', 1, 2, sumarea, filter, &
+ 'H- & V- polarized brightness temperature for SMAP satellite (L-band, 1.4GHz)', 'K')
+ CALL write_history_variable_3d(DEF_hist_vars%DA_t_brt_smap_a, &
+ a_t_brt_smap_a, file_hist, 'f_t_brt_smap_a', itime_in_file, 'band', 1, 2, sumarea, filter, &
+ 'Analysis H- & V- polarized brightness temperature for SMAP satellite (L-band,1.4GHz)', 'K')
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ CALL write_history_variable_4d(DEF_hist_vars%DA_t_brt_smap_ens, &
+ a_t_brt_smap_ens, file_hist, 'f_t_brt_smap_ens', itime_in_file, 'band', 1, 2, 'ens', 1, DEF_DA_ENS_NUM, &
+ sumarea, filter, 'ensemble H- & V- polarized brightness temperature for SMAP satellite (L-band,1.4GHz)', 'K')
+ END IF
+ CALL write_history_variable_3d(DEF_hist_vars%DA_t_brt_smap_ens_std, &
+ a_t_brt_smap_ens_std, file_hist, 'f_t_brt_smap_ens_std', itime_in_file, 'band', 1, 2, &
+ sumarea, filter, 'Standard deviation of H- & V- polarized brightness temperature for SMAP satellite (L-band,1.4GHz)', 'K')
+ ENDIF
+
+ IF (DEF_DA_SM_FY) THEN
+ CALL write_history_variable_3d(DEF_hist_vars%DA_t_brt_fy3d, &
+ a_t_brt_fy3d, file_hist, 'f_t_brt_fy3d', itime_in_file, 'band', 1, 2, sumarea, filter, &
+ 'H- & V- polarized brightness temperature for FY satellite (X-band, 10.65GHz)', 'K')
+ CALL write_history_variable_3d(DEF_hist_vars%DA_t_brt_fy3d_a, &
+ a_t_brt_fy3d_a, file_hist, 'f_t_brt_fy3d_a', itime_in_file, 'band', 1, 2, sumarea, filter, &
+ 'Analysis H- & V- polarized brightness temperature for FY satellite (X-band, 10.65GHz)', 'K')
+ IF (DEF_DA_ENS_NUM > 1) THEN
+ CALL write_history_variable_4d(DEF_hist_vars%DA_t_brt_fy3d_ens, &
+ a_t_brt_fy3d_ens, file_hist, 'f_t_brt_fy3d_ens', itime_in_file, 'band', 1, 2, 'ens', 1, DEF_DA_ENS_NUM, &
+ sumarea, filter, 'ensemble H- & V- polarized brightness temperature for FY satellite (X-band, 10.65GHz)', 'K')
+ END IF
+ CALL write_history_variable_3d(DEF_hist_vars%DA_t_brt_fy3d_ens_std, &
+ a_t_brt_fy3d_ens_std, file_hist, 'f_t_brt_fy3d_ens_std', itime_in_file, 'band', 1, 2, &
+ sumarea, filter, 'Standard deviation of H- & V- polarized brightness temperature for FY satellite (X-band, 10.65GHz)', 'K')
+ ENDIF
+
+ IF (p_is_compute) THEN
+ deallocate (a_wliq_h2osoi_5cm)
+ deallocate (a_t_soisno_5cm)
+ deallocate (a_wliq_soisno_ens_mean)
+ deallocate (a_wliq_soisno_5cm_ens)
+ deallocate (a_wliq_h2osoi_5cm_a)
+ deallocate (a_t_soisno_ens_mean)
+ deallocate (a_t_soisno_5cm_ens)
+ deallocate (a_t_soisno_5cm_a)
+ deallocate (a_t_brt_smap_a)
+ deallocate (a_t_brt_fy3d_a)
+ deallocate (a_wliq_soisno_5cm_ens_std)
+ deallocate (a_t_soisno_5cm_ens_std)
+ deallocate (a_t_brt_smap_ens_std)
+ deallocate (a_t_brt_fy3d_ens_std)
+ END IF
+
+#endif
+
+ ! --------------------------------------------------------------------
+ ! additional diagnostic variables for output (vegetated land only <=2)
+ ! [soil => 0; urban and built-up => 1; wetland => 2; land ice => 3;
+ ! land water bodies => 4; ocean => 99]
+ ! --------------------------------------------------------------------
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype <= 2
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! volumetric soil water in layers [m3/m3]
+ CALL write_history_variable_3d ( DEF_hist_vars%h2osoi, &
+ a_h2osoi, file_hist, 'f_h2osoi', itime_in_file, 'soil', 1, nl_soil, sumarea, filter, &
+ 'volumetric water in soil layers','m3/m3')
+
+ IF (DEF_USE_VariablySaturatedFlow) THEN
+ ! water flux between water layers [mm h2o/s]
+ CALL write_history_variable_3d ( DEF_hist_vars%qlayer, &
+ a_qlayer, file_hist, 'f_qlayer', itime_in_file, 'soilinterface', 0, nl_soil+1, &
+ sumarea, filter, 'water flux between soil layers','mm/s')
+ ENDIF
+
+ ! fraction of root water uptake from each soil layer, all layers add to 1,
+ ! when PHS is not defined water exchange between soil layers and root.
+ ! Positive: soil->root [mm h2o/s], when PHS is defined
+ CALL write_history_variable_3d ( DEF_hist_vars%rootr, &
+ a_rootr, file_hist, 'f_rootr', itime_in_file, 'soil', 1, nl_soil, sumarea, filter, &
+ 'root water uptake', 'mm h2o/s')
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ ! vegetation water potential [mm]
+ CALL write_history_variable_3d ( DEF_hist_vars%vegwp, &
+ a_vegwp, file_hist, 'f_vegwp', &
+ itime_in_file, 'vegnodes', 1, nvegwcs, sumarea, filter, &
+ 'vegetation water potential', 'mm')
+ ENDIF
+
+ ! water table depth [m]
+ CALL write_history_variable_2d ( DEF_hist_vars%zwt, &
+ a_zwt, file_hist, 'f_zwt', itime_in_file, sumarea, filter, &
+ 'the depth to water table','m')
+
+ ! --------------------------------------------------------------------
+ ! depth of surface water (including land ice and ocean patches)
+ ! --------------------------------------------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = (patchtype <= 4)
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! water storage in aquifer [mm]
+ CALL write_history_variable_2d ( DEF_hist_vars%wa, &
+ a_wa, file_hist, 'f_wa', itime_in_file, sumarea, filter, &
+ 'water storage in aquifer','mm')
+
+ ! instantaneous water storage in aquifer [mm]
+ IF (p_is_compute) THEN
+ vecacc = wa
+ WHERE(vecacc /= spval) vecacc = vecacc * nac
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%wa_inst, &
+ vecacc, file_hist, 'f_wa_inst', itime_in_file, sumarea, filter, &
+ 'instantaneous water storage in aquifer','mm')
+
+ ! depth of surface water [mm]
+ CALL write_history_variable_2d ( DEF_hist_vars%wdsrf, &
+ a_wdsrf, file_hist, 'f_wdsrf', itime_in_file, sumarea, filter, &
+ 'depth of surface water','mm')
+
+ ! instantaneous depth of surface water [mm]
+ IF (p_is_compute) THEN
+ vecacc = wdsrf
+ WHERE(vecacc /= spval) vecacc = vecacc * nac
+ ENDIF
+ CALL write_history_variable_2d ( DEF_hist_vars%wdsrf_inst, &
+ vecacc, file_hist, 'f_wdsrf_inst', itime_in_file, sumarea, filter, &
+ 'instantaneous depth of surface water','mm')
+
+ ! -----------------------------------------------
+ ! Land water bodies' ice fraction and temperature
+ ! -----------------------------------------------
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ filter(:) = patchtype == 4
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (trim(file_hist) /= trim(file_last)) THEN
+ CALL hist_write_var_real8_2d (file_hist, 'area_lake', ghist, -1, sumarea, &
+ compress = 1, longname = 'area of lake', units = 'km2')
+ ENDIF
+ ENDIF
+
+ ! lake layer depth [m]
+ CALL write_history_variable_3d ( DEF_hist_vars%dz_lake .and. DEF_USE_Dynamic_Lake, &
+ a_dz_lake, file_hist, 'f_dz_lake', itime_in_file, 'lake', 1, nl_lake, sumarea, filter, &
+ 'lake layer thickness','m')
+
+ ! lake temperature [K]
+ CALL write_history_variable_3d ( DEF_hist_vars%t_lake, &
+ a_t_lake, file_hist, 'f_t_lake', itime_in_file, 'lake', 1, nl_lake, sumarea, filter, &
+ 'lake temperature','K')
+
+ ! lake ice fraction cover [0-1]
+ CALL write_history_variable_3d ( DEF_hist_vars%lake_icefrac, &
+ a_lake_icefrac, file_hist, 'f_lake_icefrac', itime_in_file, 'lake', 1, nl_lake, &
+ sumarea, filter, 'lake ice fraction cover','0-1')
+
+ ! lake water deficit due to evaporation [mm/s]
+ IF (.not. DEF_USE_Dynamic_Lake) THEN
+ CALL write_history_variable_2d ( DEF_hist_vars%lake_deficit, &
+ a_lake_deficit, file_hist, 'f_lake_deficit', itime_in_file, sumarea, filter, &
+ 'lake water deficit due to evaporation','mm/s')
+ ENDIF
+
+#ifdef EXTERNAL_LAKE
+ CALL LakeVarsSaveHist (nl_lake, file_hist, HistForm, itime_in_file, sumarea, filter)
+#endif
+
+ ! --------------------------------
+ ! Retrieve through averaged fluxes
+ ! --------------------------------
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ filter(:) = patchtype < 99
+
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+
+ filter = filter .and. patchmask
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! u* in similarity theory [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%ustar, &
+ a_ustar, file_hist, 'f_ustar', itime_in_file, sumarea, filter, &
+ 'u* in similarity theory based on patch','m/s')
+
+ ! u* in similarity theory [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%ustar2, &
+ a_ustar2, file_hist, 'f_ustar2', itime_in_file, sumarea, filter, &
+ 'u* in similarity theory based on grid','m/s')
+
+ ! t* in similarity theory [K]
+ CALL write_history_variable_2d ( DEF_hist_vars%tstar, &
+ a_tstar, file_hist, 'f_tstar', itime_in_file, sumarea, filter, &
+ 't* in similarity theory','K')
+
+ ! q* in similarity theory [kg/kg]
+ CALL write_history_variable_2d ( DEF_hist_vars%qstar, &
+ a_qstar, file_hist, 'f_qstar', itime_in_file, sumarea, filter, &
+ 'q* in similarity theory', 'kg/kg')
+
+ ! dimensionless height (z/L) used in Monin-Obukhov theory
+ CALL write_history_variable_2d ( DEF_hist_vars%zol, &
+ a_zol, file_hist, 'f_zol', itime_in_file, sumarea, filter, &
+ 'dimensionless height (z/L) used in Monin-Obukhov theory','-')
+
+ ! bulk Richardson number in surface layer
+ CALL write_history_variable_2d ( DEF_hist_vars%rib, &
+ a_rib, file_hist, 'f_rib', itime_in_file, sumarea, filter, &
+ 'bulk Richardson number in surface layer','-')
+
+ ! integral of profile FUNCTION for momentum
+ CALL write_history_variable_2d ( DEF_hist_vars%fm, &
+ a_fm, file_hist, 'f_fm', itime_in_file, sumarea, filter, &
+ 'integral of profile FUNCTION for momentum','-')
+
+ ! integral of profile FUNCTION for heat
+ CALL write_history_variable_2d ( DEF_hist_vars%fh, &
+ a_fh, file_hist, 'f_fh', itime_in_file, sumarea, filter, &
+ 'integral of profile FUNCTION for heat','-')
+
+ ! integral of profile FUNCTION for moisture
+ CALL write_history_variable_2d ( DEF_hist_vars%fq, &
+ a_fq, file_hist, 'f_fq', itime_in_file, sumarea, filter, &
+ 'integral of profile FUNCTION for moisture','-')
+
+ ! 10m u-velocity [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%us10m, &
+ a_us10m, file_hist, 'f_us10m', itime_in_file, sumarea, filter, &
+ '10m u-velocity','m/s')
+
+ ! 10m v-velocity [m/s]
+ CALL write_history_variable_2d ( DEF_hist_vars%vs10m, &
+ a_vs10m, file_hist, 'f_vs10m', itime_in_file, sumarea, filter, &
+ '10m v-velocity','m/s')
+
+ ! integral of profile FUNCTION for momentum at 10m [-]
+ CALL write_history_variable_2d ( DEF_hist_vars%fm10m, &
+ a_fm10m, file_hist, 'f_fm10m', itime_in_file, sumarea, filter, &
+ 'integral of profile FUNCTION for momentum at 10m','-')
+
+ ! total reflected solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%sr, &
+ a_sr, file_hist, 'f_sr', itime_in_file, sumarea, filter, &
+ 'reflected solar radiation at surface [W/m2]','W/m2')
+
+ ! incident direct beam vis solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solvd, &
+ a_solvd, file_hist, 'f_solvd', itime_in_file, sumarea, filter, &
+ 'incident direct beam vis solar radiation (W/m2)','W/m2')
+
+ ! incident diffuse beam vis solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solvi, &
+ a_solvi, file_hist, 'f_solvi', itime_in_file, sumarea, filter, &
+ 'incident diffuse beam vis solar radiation (W/m2)','W/m2')
+
+ ! incident direct beam nir solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solnd, &
+ a_solnd, file_hist, 'f_solnd', itime_in_file, sumarea, filter, &
+ 'incident direct beam nir solar radiation (W/m2)','W/m2')
+
+ ! incident diffuse beam nir solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solni, &
+ a_solni, file_hist, 'f_solni', itime_in_file, sumarea, filter, &
+ 'incident diffuse beam nir solar radiation (W/m2)','W/m2')
+
+ ! reflected direct beam vis solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srvd, &
+ a_srvd, file_hist, 'f_srvd', itime_in_file, sumarea, filter, &
+ 'reflected direct beam vis solar radiation (W/m2)','W/m2')
+
+ ! reflected diffuse beam vis solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srvi, &
+ a_srvi, file_hist, 'f_srvi', itime_in_file, sumarea, filter, &
+ 'reflected diffuse beam vis solar radiation (W/m2)','W/m2')
+
+ ! reflected direct beam nir solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srnd, &
+ a_srnd, file_hist, 'f_srnd', itime_in_file, sumarea, filter, &
+ 'reflected direct beam nir solar radiation (W/m2)','W/m2')
+
+ ! reflected diffuse beam nir solar radiation (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srni, &
+ a_srni, file_hist, 'f_srni', itime_in_file, sumarea, filter, &
+ 'reflected diffuse beam nir solar radiation (W/m2)','W/m2')
+
+ ! local noon fluxes
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ filter(:) = nac_ln > 0
+ IF (DEF_forcing%has_missing_value) THEN
+ filter = filter .and. forcmask_pch
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ ! incident direct beam vis solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solvdln, &
+ a_solvdln, file_hist, 'f_solvdln', itime_in_file, sumarea, filter, &
+ 'incident direct beam vis solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! incident diffuse beam vis solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solviln, &
+ a_solviln, file_hist, 'f_solviln', itime_in_file, sumarea, filter, &
+ 'incident diffuse beam vis solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! incident direct beam nir solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solndln, &
+ a_solndln, file_hist, 'f_solndln', itime_in_file, sumarea, filter, &
+ 'incident direct beam nir solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! incident diffuse beam nir solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%solniln, &
+ a_solniln, file_hist, 'f_solniln', itime_in_file, sumarea, filter, &
+ 'incident diffuse beam nir solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! reflected direct beam vis solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srvdln, &
+ a_srvdln, file_hist, 'f_srvdln', itime_in_file, sumarea, filter, &
+ 'reflected direct beam vis solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! reflected diffuse beam vis solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srviln, &
+ a_srviln, file_hist, 'f_srviln', itime_in_file, sumarea, filter, &
+ 'reflected diffuse beam vis solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! reflected direct beam nir solar radiation at local noon (W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srndln, &
+ a_srndln, file_hist, 'f_srndln', itime_in_file, sumarea, filter, &
+ 'reflected direct beam nir solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+ ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+ CALL write_history_variable_2d ( DEF_hist_vars%srniln, &
+ a_srniln, file_hist, 'f_srniln', itime_in_file, sumarea, filter, &
+ 'reflected diffuse beam nir solar radiation at local noon(W/m2)','W/m2',nac_ln)
+
+
+ IF ((p_is_compute) .and. (numpatch > 0)) THEN
+ filter = (patchtype == 0) .and. patchmask
+ IF (DEF_forcing%has_missing_value) filter = filter .and. forcmask_pch
+ ENDIF
+ IF (HistForm == 'Gridded') THEN
+ CALL mp2g_hist%get_sumarea (sumarea, filter)
+ ENDIF
+
+ CALL write_history_variable_3d ( DEF_hist_vars%sensors, &
+ a_sensors, file_hist, 'f_sensors', itime_in_file, 'sensor', 1, nsensor, &
+ sumarea, filter, 'variable sensors','user defined')
+
+#ifdef CatchLateralFlow
+ CALL hist_basin_out (file_hist, idate)
+#endif
+
+#ifdef GridRiverLakeFlow
+ CALL hist_grid_riverlake_out (file_hist, HistForm, idate, &
+ itime_in_file, trim(file_hist)/=trim(file_last))
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate (nac_one (numpatch))
+ nac_one = 1.
+ ENDIF
+ ENDIF
+
+ IF (HistForm == 'Gridded') THEN
+ IF (p_is_active) CALL allocate_block_data (ghist, sumarea_one)
+ IF (p_is_active) CALL flush_block_data (sumarea_one, 1.)
+ ENDIF
+
+ CALL write_history_variable_2d ( DEF_hist_vars%riv_height, a_wdsrf_ucat_pch, &
+ file_hist, 'f_wdpth_ucat_regrid', itime_in_file, sumarea_ucat, filter_ucat, &
+ 'regridded deepest water depth in river and flood plain', 'm', nac_one)
+
+ CALL write_history_variable_2d ( DEF_hist_vars%riv_veloct, a_veloc_riv_pch, &
+ file_hist, 'f_veloc_riv_regrid', itime_in_file, sumarea_ucat, filter_ucat, &
+ 'regridded water velocity in river', 'm/s', nac_one)
+
+ CALL write_history_variable_2d ( DEF_hist_vars%discharge, a_discharge_pch, &
+ file_hist, 'f_discharge', itime_in_file, sumarea_one, filter_ucat, &
+ 'regridded discharge in river and flood plain', 'm^3/s', &
+ nac_one, input_mode = 'total')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%discharge, a_dis_rmth_pch, &
+ file_hist, 'f_discharge_rivermouth_regrid', itime_in_file, sumarea_one, &
+ filter_ucat, 'regridded river mouth discharge into ocean', 'm^3/s', &
+ nac_one, input_mode = 'total')
+
+ CALL write_history_variable_2d ( DEF_hist_vars%floodfrc, a_floodfrc_pch, &
+ file_hist, 'f_floodfrc', itime_in_file, sumarea_inpm, filter_inpm, &
+ 'flooded area fraction', '100%', nac_one)
+
+ IF (trim(HistForm) == 'Gridded') THEN
+ CALL write_history_variable_2d ( DEF_hist_vars%floodarea, a_floodfrc_pch, &
+ file_hist, 'f_floodarea', itime_in_file, sumarea_one, filter_inpm, &
+ 'flooded area', 'km^2', nac_one)
+ ENDIF
+
+ IF (allocated(nac_one )) deallocate (nac_one )
+#endif
+
+ IF (allocated(filter )) deallocate (filter )
+ IF (allocated(filter_dt )) deallocate (filter_dt )
+#ifdef URBAN_MODEL
+ IF (allocated(filter_urb)) deallocate (filter_urb)
+#endif
+
+ CALL FLUSH_acc_fluxes ()
+
+#ifdef SinglePoint
+ IF (USE_SITE_HistWriteBack .and. memory_to_disk) THEN
+ itime_mem = 0
+ ENDIF
+#endif
+
+ file_last = file_hist
+
+ ENDIF
+
+ END SUBROUTINE hist_out
+
+
+ SUBROUTINE write_history_variable_2d ( is_hist, &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, &
+ longname, units, acc_num, input_mode)
+
+ USE MOD_Vars_1DAccFluxes, only: nac
+
+ IMPLICIT NONE
+
+ logical, intent(in) :: is_hist
+
+ real(r8), intent(inout) :: acc_vec(:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+ real(r8), intent(in), optional :: acc_num(:)
+
+ character(len=*), intent(in), optional :: input_mode
+
+ IF (.not. is_hist) RETURN
+
+#ifndef SinglePoint
+ IF ( .not. present(acc_num) ) THEN
+ IF (p_is_compute) &
+ WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+ ELSE
+ IF (p_is_compute) &
+ WHERE (acc_vec/=spval .and. acc_num>0) acc_vec = acc_vec / acc_num
+ ENDIF
+#else
+ IF ( .not. present(acc_num) ) THEN
+ WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+ ELSE
+ WHERE (acc_vec/=spval .and. acc_num>0) acc_vec = acc_vec / acc_num
+ ENDIF
+#endif
+
+ select CASE (HistForm)
+ CASE ('Gridded')
+ IF (present(input_mode)) THEN
+ CALL flux_map_and_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, longname, units, input_mode)
+ ELSE
+ CALL flux_map_and_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, longname, units)
+ ENDIF
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ CASE ('Vector')
+ IF (present(input_mode)) THEN
+ CALL aggregate_to_vector_and_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, filter, longname, units, input_mode)
+ ELSE
+ CALL aggregate_to_vector_and_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, filter, longname, units)
+ ENDIF
+#endif
+#ifdef SinglePoint
+ CASE ('Single')
+ CALL single_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, longname, units)
+#endif
+ END select
+
+ END SUBROUTINE write_history_variable_2d
+
+
+#ifdef URBAN_MODEL
+ SUBROUTINE write_history_variable_urb_2d ( is_hist, &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, &
+ longname, units)
+
+ IMPLICIT NONE
+
+ logical, intent(in) :: is_hist
+
+ real(r8), intent(inout) :: acc_vec(:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+
+ IF (.not. is_hist) RETURN
+
+ select CASE (HistForm)
+ CASE ('Gridded')
+ CALL flux_map_and_write_urb_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, longname, units)
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ CASE ('Vector')
+ !TODO: currently, it is not applicable to urban variables
+ CALL aggregate_to_vector_and_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, filter, longname, units)
+#endif
+#ifdef SinglePoint
+ CASE ('Single')
+ CALL single_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, longname, units)
+#endif
+ END select
+
+ END SUBROUTINE write_history_variable_urb_2d
+#endif
+
+
+ SUBROUTINE write_history_variable_3d ( is_hist, &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, &
+ sumarea, filter, longname, units)
+
+ IMPLICIT NONE
+
+ logical, intent(in) :: is_hist
+
+ real(r8), intent(inout) :: acc_vec(:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name
+ integer, intent(in) :: lb1, ndim1
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+ character (len=*), intent(in) :: longname
+ character (len=*), intent(in) :: units
+
+ ! Local variables
+ integer :: iblkme, xblk, yblk, xloc, yloc, i1
+ integer :: compress
+
+ IF (.not. is_hist) RETURN
+
+ select CASE (HistForm)
+ CASE ('Gridded')
+ CALL flux_map_and_write_3d ( &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, &
+ sumarea, filter, longname, units)
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ CASE ('Vector')
+ CALL aggregate_to_vector_and_write_3d ( &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, &
+ filter, longname, units)
+#endif
+#ifdef SinglePoint
+ CASE ('Single')
+ CALL single_write_3d (acc_vec, file_hist, varname, itime_in_file, &
+ dim1name, ndim1, longname, units)
+#endif
+ END select
+
+ END SUBROUTINE write_history_variable_3d
+
+
+ SUBROUTINE write_history_variable_4d ( is_hist, &
+ acc_vec, file_hist, varname, itime_in_file, &
+ dim1name, lb1, ndim1, dim2name, lb2, ndim2, &
+ sumarea, filter, longname, units, acc_num)
+
+ IMPLICIT NONE
+
+ logical, intent(in) :: is_hist
+
+ real(r8), intent(inout) :: acc_vec(:,:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name, dim2name
+ integer, intent(in) :: lb1, ndim1, lb2, ndim2
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+ character (len=*), intent(in) :: longname
+ character (len=*), intent(in) :: units
+ real(r8), intent(in), optional:: acc_num(:)
+
+ ! Local variables
+ integer :: i1, i2
+
+ IF (.not. is_hist) RETURN
+
+#ifndef SinglePoint
+ IF ( .not. present(acc_num) ) THEN
+ IF (p_is_compute) &
+ WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+ ELSE
+ IF (p_is_compute) THEN
+ DO i1 = lbound(acc_vec,1), ubound(acc_vec,1)
+ DO i2 = lbound(acc_vec,2), ubound(acc_vec,2)
+ WHERE (acc_vec(i1,i2,:)/=spval .and. acc_num>0) &
+ acc_vec(i1,i2,:) = acc_vec(i1,i2,:) / acc_num
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+#else
+ IF ( .not. present(acc_num) ) THEN
+ WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+ ELSE
+ DO i1 = lbound(acc_vec,1), ubound(acc_vec,1)
+ DO i2 = lbound(acc_vec,2), ubound(acc_vec,2)
+ WHERE (acc_vec(i1,i2,:)/=spval .and. acc_num>0) &
+ acc_vec(i1,i2,:) = acc_vec(i1,i2,:) / acc_num
+ ENDDO
+ ENDDO
+ ENDIF
+#endif
+
+ select CASE (HistForm)
+ CASE ('Gridded')
+ CALL flux_map_and_write_4d ( &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, &
+ dim2name, lb2, ndim2, sumarea, filter, longname, units)
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ CASE ('Vector')
+ CALL aggregate_to_vector_and_write_4d ( &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, &
+ dim2name, lb2, ndim2, filter, longname, units)
+#endif
+#ifdef SinglePoint
+ CASE ('Single')
+ CALL single_write_4d (acc_vec, file_hist, varname, itime_in_file, &
+ dim1name, ndim1, dim2name, ndim2, longname, units)
+#endif
+ END select
+
+ END SUBROUTINE write_history_variable_4d
+
+
+ SUBROUTINE hist_write_time (filename, filelast, dataname, time, itime)
+
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: filelast
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: time(3)
+ integer, intent(out) :: itime
+
+ select CASE (HistForm)
+ CASE ('Gridded')
+ CALL hist_gridded_write_time (filename, filelast, dataname, time, itime)
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+ CASE ('Vector')
+ CALL hist_vector_write_time (filename, filelast, dataname, time, itime)
+#endif
+#ifdef SinglePoint
+ CASE ('Single')
+ CALL hist_single_write_time (filename, filelast, dataname, time, itime)
+#endif
+ END select
+
+ END SUBROUTINE hist_write_time
+
+END MODULE MOD_Hist
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistGridded.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistGridded.F90
new file mode 100644
index 0000000000..051f429903
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistGridded.F90
@@ -0,0 +1,1079 @@
+#include
+
+MODULE MOD_HistGridded
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Write out gridded model results to history files.
+!
+! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+!
+! !REVISIONS:
+! Shupeng Zhang, 05/2023: 1) porting codes to MPI parallel version
+!
+! TODO...(need complement)
+!----------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SpatialMapping
+ USE MOD_Namelist
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+#ifdef USEMPI
+ USE MOD_HistWriteBack
+#endif
+
+ type(grid_type), target :: ghist
+ type(spatial_mapping_type) :: mp2g_hist
+ type(spatial_mapping_type) :: mp2g_hist_urb
+
+ type(block_data_real8_2d) :: landfraction
+
+ type(grid_concat_type) :: hist_concat
+
+ integer :: hist_data_id
+
+!--------------------------------------------------------------------------
+CONTAINS
+
+ SUBROUTINE hist_gridded_init (dir_hist, lulcc_call)
+
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global
+ USE MOD_Block
+ USE MOD_LandPatch
+#ifdef URBAN_MODEL
+ USE MOD_LandUrban
+#endif
+ USE MOD_Vars_1DAccFluxes
+ USE MOD_Forcing, only: gforc
+#ifdef SinglePoint
+ USE MOD_SingleSrfData
+#endif
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ character(len=*) , intent(in) :: dir_hist
+ logical, optional, intent(in) :: lulcc_call
+
+ ! Local Variables
+ type(block_data_real8_2d) :: gridarea
+ integer :: iblkme, xblk, yblk, xloc, yloc, xglb, yglb
+
+ IF (DEF_hist_grid_as_forcing) THEN
+ CALL ghist%define_by_copy (gforc)
+ ELSE
+ CALL ghist%define_by_res (DEF_hist_lon_res, DEF_hist_lat_res)
+ ENDIF
+
+ IF (present(lulcc_call)) CALL mp2g_hist%forc_free_mem
+ CALL mp2g_hist%build_arealweighted (ghist, landpatch)
+
+#ifdef URBAN_MODEL
+ IF (present(lulcc_call)) CALL mp2g_hist_urb%forc_free_mem
+ CALL mp2g_hist_urb%build_arealweighted (ghist, landurban)
+#endif
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (ghist, landfraction)
+ CALL allocate_block_data (ghist, gridarea)
+
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+ DO yloc = 1, ghist%ycnt(yblk)
+ DO xloc = 1, ghist%xcnt(xblk)
+ xglb = ghist%xdsp(xblk) + xloc
+ yglb = ghist%ydsp(yblk) + yloc
+ gridarea%blk(xblk,yblk)%val(xloc,yloc) = areaquad ( &
+ ghist%lat_s(yglb), ghist%lat_n(yglb), ghist%lon_w(xglb), ghist%lon_e(xglb))
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDIF
+
+ CALL mp2g_hist%get_sumarea (landfraction)
+ CALL block_data_division (landfraction, gridarea)
+
+ CALL hist_concat%set (ghist)
+#ifdef SinglePoint
+ hist_concat%ginfo%lat_c(:) = SITE_lat_location
+ hist_concat%ginfo%lon_c(:) = SITE_lon_location
+#endif
+
+ IF (trim(DEF_HIST_mode) == 'one') THEN
+ hist_data_id = 10001
+ ENDIF
+
+ END SUBROUTINE hist_gridded_init
+
+
+ SUBROUTINE flux_map_and_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, &
+ longname, units, input_mode)
+
+ USE MOD_Block
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+ character(len=*), intent(in), optional :: input_mode
+
+ ! Local variables
+ type(block_data_real8_2d) :: flux_xy_2d
+ integer :: iblkme, xblk, yblk, xloc, yloc
+ integer :: compress
+
+ IF (p_is_active) CALL allocate_block_data (ghist, flux_xy_2d)
+
+ IF (present(input_mode)) THEN
+ CALL mp2g_hist%pset2grid (acc_vec, flux_xy_2d, spv = spval, msk = filter, input_mode = input_mode)
+ ELSE
+ CALL mp2g_hist%pset2grid (acc_vec, flux_xy_2d, spv = spval, msk = filter)
+ ENDIF
+
+ IF (p_is_active) THEN
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ DO yloc = 1, ghist%ycnt(yblk)
+ DO xloc = 1, ghist%xcnt(xblk)
+
+ IF (sumarea%blk(xblk,yblk)%val(xloc,yloc) > 0.00001) THEN
+ IF (flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) /= spval) THEN
+ flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) &
+ = flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) &
+ / sumarea%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+ ELSE
+ flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) = spval
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDDO
+ ENDIF
+
+ compress = DEF_HIST_CompressLevel
+ CALL hist_write_var_real8_2d (file_hist, varname, ghist, itime_in_file, &
+ flux_xy_2d, compress, longname, units)
+
+ END SUBROUTINE flux_map_and_write_2d
+
+
+ SUBROUTINE flux_map_and_write_urb_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, sumarea, filter, &
+ longname, units)
+
+ USE MOD_Block
+ USE MOD_Vars_1DAccFluxes, only: nac
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+
+ ! Local variables
+ type(block_data_real8_2d) :: flux_xy_2d
+ integer :: iblkme, xblk, yblk, xloc, yloc
+ integer :: compress
+
+ IF (p_is_compute) WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+ IF (p_is_active) CALL allocate_block_data (ghist, flux_xy_2d)
+
+ CALL mp2g_hist_urb%pset2grid (acc_vec, flux_xy_2d, spv = spval, msk = filter)
+
+ IF (p_is_active) THEN
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ DO yloc = 1, ghist%ycnt(yblk)
+ DO xloc = 1, ghist%xcnt(xblk)
+
+ IF (sumarea%blk(xblk,yblk)%val(xloc,yloc) > 0.00001) THEN
+ IF (flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) /= spval) THEN
+ flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) &
+ = flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) &
+ / sumarea%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+ ELSE
+ flux_xy_2d%blk(xblk,yblk)%val(xloc,yloc) = spval
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDDO
+ ENDIF
+
+ compress = DEF_HIST_CompressLevel
+ CALL hist_write_var_real8_2d (file_hist, varname, ghist, itime_in_file, flux_xy_2d, &
+ compress, longname, units)
+
+ END SUBROUTINE flux_map_and_write_urb_2d
+
+
+ SUBROUTINE flux_map_and_write_3d ( &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, sumarea, filter, &
+ longname, units)
+
+ USE MOD_Block
+ USE MOD_Vars_1DAccFluxes, only: nac
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name
+ integer, intent(in) :: lb1, ndim1
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+ character (len=*), intent(in) :: longname
+ character (len=*), intent(in) :: units
+
+ ! Local variables
+ type(block_data_real8_3d) :: flux_xy_3d
+ integer :: iblkme, xblk, yblk, xloc, yloc, i1
+ integer :: compress
+
+ IF (p_is_compute) THEN
+ WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+ ENDIF
+ IF (p_is_active) THEN
+ CALL allocate_block_data (ghist, flux_xy_3d, ndim1, lb1)
+ ENDIF
+
+ CALL mp2g_hist%pset2grid (acc_vec, flux_xy_3d, spv = spval, msk = filter)
+
+ IF (p_is_active) THEN
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ DO yloc = 1, ghist%ycnt(yblk)
+ DO xloc = 1, ghist%xcnt(xblk)
+
+ IF (sumarea%blk(xblk,yblk)%val(xloc,yloc) > 0.00001) THEN
+ DO i1 = flux_xy_3d%lb1, flux_xy_3d%ub1
+ IF (flux_xy_3d%blk(xblk,yblk)%val(i1,xloc,yloc) /= spval) THEN
+ flux_xy_3d%blk(xblk,yblk)%val(i1,xloc,yloc) &
+ = flux_xy_3d%blk(xblk,yblk)%val(i1,xloc,yloc) &
+ / sumarea%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+ ENDDO
+ ELSE
+ flux_xy_3d%blk(xblk,yblk)%val(:,xloc,yloc) = spval
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDDO
+ ENDIF
+
+ compress = DEF_HIST_CompressLevel
+ CALL hist_write_var_real8_3d (file_hist, varname, dim1name, ghist, &
+ itime_in_file, flux_xy_3d, compress, longname, units)
+
+ END SUBROUTINE flux_map_and_write_3d
+
+
+ SUBROUTINE flux_map_and_write_4d ( &
+ acc_vec, file_hist, varname, itime_in_file, &
+ dim1name, lb1, ndim1, dim2name, lb2, ndim2, &
+ sumarea, filter, longname, units)
+
+ USE MOD_Block
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:,:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name, dim2name
+ integer, intent(in) :: lb1, ndim1, lb2, ndim2
+
+ type(block_data_real8_2d), intent(in) :: sumarea
+ logical, intent(in) :: filter(:)
+ character (len=*), intent(in) :: longname
+ character (len=*), intent(in) :: units
+
+ ! Local variables
+ type(block_data_real8_4d) :: flux_xy_4d
+ integer :: iblkme, xblk, yblk, xloc, yloc, i1, i2
+ integer :: compress
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (ghist, flux_xy_4d, ndim1, ndim2, lb1 = lb1, lb2 = lb2)
+ ENDIF
+
+ CALL mp2g_hist%pset2grid (acc_vec, flux_xy_4d, spv = spval, msk = filter)
+
+ IF (p_is_active) THEN
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ DO yloc = 1, ghist%ycnt(yblk)
+ DO xloc = 1, ghist%xcnt(xblk)
+
+ IF (sumarea%blk(xblk,yblk)%val(xloc,yloc) > 0.00001) THEN
+ DO i1 = flux_xy_4d%lb1, flux_xy_4d%ub1
+ DO i2 = flux_xy_4d%lb2, flux_xy_4d%ub2
+ IF (flux_xy_4d%blk(xblk,yblk)%val(i1,i2,xloc,yloc) /= spval) THEN
+ flux_xy_4d%blk(xblk,yblk)%val(i1,i2,xloc,yloc) &
+ = flux_xy_4d%blk(xblk,yblk)%val(i1,i2,xloc,yloc) &
+ / sumarea%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+ ENDDO
+ ENDDO
+ ELSE
+ flux_xy_4d%blk(xblk,yblk)%val(:,:,xloc,yloc) = spval
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDDO
+ ENDIF
+
+ compress = DEF_HIST_CompressLevel
+ CALL hist_write_var_real8_4d (file_hist, varname, dim1name, dim2name, &
+ ghist, itime_in_file, flux_xy_4d, compress, longname, units)
+
+ END SUBROUTINE flux_map_and_write_4d
+
+
+ SUBROUTINE hist_gridded_write_time ( &
+ filename, filelast, dataname, time, itime)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: filelast
+ character (len=*), intent(in) :: dataname
+
+ integer, intent(in) :: time(3)
+ integer, intent(out) :: itime
+
+ ! Local variables
+ character(len=256) :: fileblock
+ integer :: iblkme, iblk, jblk
+ logical :: fexists
+
+ itime = 0
+ IF (trim(DEF_HIST_mode) == 'one') THEN
+ IF (p_is_root) THEN
+#ifdef USEMPI
+ IF (DEF_HIST_WriteBack) THEN
+ CALL hist_writeback_latlon_time (filename, filelast, dataname, time, hist_concat)
+ itime = 1
+ ELSE
+#endif
+ inquire (file=filename, exist=fexists)
+ IF ((.not. fexists) .or. (trim(filename) /= trim(filelast))) THEN
+
+ CALL ncio_create_file (trim(filename))
+ CALL ncio_define_dimension(filename, 'time', 0)
+ CALL ncio_define_dimension(filename, 'lat' , hist_concat%ginfo%nlat)
+ CALL ncio_define_dimension(filename, 'lon' , hist_concat%ginfo%nlon)
+
+ CALL ncio_write_serial (filename, 'lat', hist_concat%ginfo%lat_c, 'lat')
+ CALL ncio_put_attr (filename, 'lat', 'long_name', 'latitude')
+ CALL ncio_put_attr (filename, 'lat', 'units', 'degrees_north')
+
+ CALL ncio_write_serial (filename, 'lon', hist_concat%ginfo%lon_c, 'lon')
+ CALL ncio_put_attr (filename, 'lon', 'long_name', 'longitude')
+ CALL ncio_put_attr (filename, 'lon', 'units', 'degrees_east')
+
+#ifndef SinglePoint
+ CALL ncio_write_serial (filename, 'lat_s', hist_concat%ginfo%lat_s, 'lat')
+ CALL ncio_write_serial (filename, 'lat_n', hist_concat%ginfo%lat_n, 'lat')
+ CALL ncio_write_serial (filename, 'lon_w', hist_concat%ginfo%lon_w, 'lon')
+ CALL ncio_write_serial (filename, 'lon_e', hist_concat%ginfo%lon_e, 'lon')
+#endif
+
+ CALL ncio_write_colm_dimension (filename)
+
+ ENDIF
+
+ CALL ncio_write_time (filename, dataname, time, itime, DEF_HIST_FREQ)
+
+#ifdef USEMPI
+ ENDIF
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (itime, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#endif
+
+ ELSEIF (trim(DEF_HIST_mode) == 'block') THEN
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (ghist%ycnt(jblk) <= 0) CYCLE
+ IF (ghist%xcnt(iblk) <= 0) CYCLE
+
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+
+ inquire (file=fileblock, exist=fexists)
+ IF ((.not. fexists) .or. (trim(filename) /= trim(filelast))) THEN
+ CALL ncio_create_file (trim(fileblock))
+ CALL ncio_define_dimension (fileblock, 'time', 0)
+ CALL hist_write_grid_info (fileblock, ghist, iblk, jblk)
+ ENDIF
+
+ CALL ncio_write_time (fileblock, dataname, time, itime, DEF_HIST_FREQ)
+
+ ENDDO
+
+ ENDIF
+#ifdef USEMPI
+#ifdef MPAS_EMBEDDED_COLM
+ CALL mpi_allreduce (MPI_IN_PLACE, itime, 1, MPI_INTEGER, MPI_MAX, p_comm_group, p_err)
+#else
+ IF (.not. p_is_root) CALL mpi_bcast (itime, 1, MPI_INTEGER, p_root, p_comm_group, p_err)
+#endif
+#endif
+
+ ENDIF
+
+ END SUBROUTINE hist_gridded_write_time
+
+
+ SUBROUTINE hist_write_var_real8_2d ( &
+ filename, dataname, grid, itime, wdata, compress, longname, units)
+
+ USE MOD_Block
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: itime
+
+ type (block_data_real8_2d), intent(in) :: wdata
+
+ integer, intent(in) :: compress
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk, idata, ixseg, iyseg
+ integer :: xcnt, ycnt, xbdsp, ybdsp, xgdsp, ygdsp
+ integer :: rmesg(3), smesg(3), isrc
+ character(len=256) :: fileblock
+ real(r8), allocatable :: rbuf(:,:), sbuf(:,:), vdata(:,:)
+
+ IF (trim(DEF_HIST_mode) == 'one') THEN
+
+ IF (p_is_root) THEN
+
+#ifdef USEMPI
+ IF (.not. DEF_HIST_WriteBack) THEN
+
+ allocate (vdata (hist_concat%ginfo%nlon, hist_concat%ginfo%nlat))
+ vdata(:,:) = spval
+
+ DO idata = 1, hist_concat%ndatablk
+ CALL mpi_recv (rmesg, 3, MPI_INTEGER, MPI_ANY_SOURCE, &
+ hist_data_id, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ ixseg = rmesg(2)
+ iyseg = rmesg(3)
+
+ xgdsp = hist_concat%xsegs(ixseg)%gdsp
+ ygdsp = hist_concat%ysegs(iyseg)%gdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ allocate (rbuf(xcnt,ycnt))
+
+ CALL mpi_recv (rbuf, xcnt*ycnt, MPI_REAL8, &
+ isrc, hist_data_id, p_comm_glb, p_stat, p_err)
+
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt) = rbuf
+ deallocate (rbuf)
+
+ ENDDO
+
+ ELSE
+ IF (itime == -1) THEN
+ CALL hist_writeback_var_header (hist_data_id, filename, dataname, &
+ 2, 'lon', 'lat', '', '', '', compress, longname, units)
+ ELSE
+ CALL hist_writeback_var_header (hist_data_id, filename, dataname, &
+ 3, 'lon', 'lat', 'time', '', '', compress, longname, units)
+ ENDIF
+ ENDIF
+#else
+ allocate (vdata (hist_concat%ginfo%nlon, hist_concat%ginfo%nlat))
+ vdata(:,:) = spval
+
+ DO iyseg = 1, hist_concat%nyseg
+ DO ixseg = 1, hist_concat%nxseg
+ iblk = hist_concat%xsegs(ixseg)%blk
+ jblk = hist_concat%ysegs(iyseg)%blk
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+ xbdsp = hist_concat%xsegs(ixseg)%bdsp
+ ybdsp = hist_concat%ysegs(iyseg)%bdsp
+ xgdsp = hist_concat%xsegs(ixseg)%gdsp
+ ygdsp = hist_concat%ysegs(iyseg)%gdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt) = &
+ wdata%blk(iblk,jblk)%val(xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+ ENDIF
+ ENDDO
+ ENDDO
+#endif
+
+#ifdef USEMPI
+ IF (.not. DEF_HIST_WriteBack) THEN
+#endif
+ IF (itime >= 1) THEN
+
+ CALL ncio_write_serial_time (filename, dataname, itime, vdata, &
+ 'lon', 'lat', 'time', compress)
+
+ ELSEIF (itime == -1) THEN
+ CALL ncio_write_serial (filename, dataname, vdata, 'lon', 'lat', compress)
+ ENDIF
+
+ IF (itime <= 1) THEN
+ CALL ncio_put_attr (filename, dataname, 'long_name', longname)
+ CALL ncio_put_attr (filename, dataname, 'units', units)
+ CALL ncio_put_attr (filename, dataname, 'missing_value', spval)
+ ENDIF
+
+ deallocate (vdata)
+#ifdef USEMPI
+ ENDIF
+#endif
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+ DO iyseg = 1, hist_concat%nyseg
+ DO ixseg = 1, hist_concat%nxseg
+
+ iblk = hist_concat%xsegs(ixseg)%blk
+ jblk = hist_concat%ysegs(iyseg)%blk
+
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+
+ xbdsp = hist_concat%xsegs(ixseg)%bdsp
+ ybdsp = hist_concat%ysegs(iyseg)%bdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ allocate (sbuf (xcnt,ycnt))
+ sbuf = wdata%blk(iblk,jblk)%val(xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+
+ IF (.not. DEF_HIST_WriteBack) THEN
+ smesg = (/p_iam_glb, ixseg, iyseg/)
+ CALL mpi_send (smesg, 3, MPI_INTEGER, &
+ p_address_root, hist_data_id, p_comm_glb, p_err)
+ CALL mpi_send (sbuf, xcnt*ycnt, MPI_REAL8, &
+ p_address_root, hist_data_id, p_comm_glb, p_err)
+ ELSE
+ CALL hist_writeback_var (hist_data_id, ixseg, iyseg, wdata2d = sbuf)
+ ENDIF
+
+ deallocate (sbuf)
+
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+#endif
+
+ hist_data_id = mod(hist_data_id-10000,10000) + 100001
+
+ ELSEIF (trim(DEF_HIST_mode) == 'block') THEN
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ IF ((grid%xcnt(iblk) == 0) .or. (grid%ycnt(jblk) == 0)) CYCLE
+
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+
+ IF (itime >= 1) THEN
+
+ CALL ncio_write_serial_time (fileblock, dataname, itime, &
+ wdata%blk(iblk,jblk)%val, 'lon', 'lat', 'time', compress)
+
+ ELSEIF (itime == -1) THEN
+ CALL ncio_write_serial (fileblock, dataname, &
+ wdata%blk(iblk,jblk)%val, 'lon', 'lat', compress)
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE hist_write_var_real8_2d
+
+
+ SUBROUTINE hist_write_var_real8_3d ( &
+ filename, dataname, dim1name, grid, itime, wdata, compress, longname, units)
+
+ USE MOD_Block
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ character (len=*), intent(in) :: dim1name
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: itime
+
+ type (block_data_real8_3d), intent(in) :: wdata
+
+ integer, intent(in) :: compress
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk, idata, ixseg, iyseg
+ integer :: xcnt, ycnt, ndim1, xbdsp, ybdsp, xgdsp, ygdsp, idim1
+ integer :: rmesg(4), smesg(4), isrc
+ character(len=256) :: fileblock
+ real(r8), allocatable :: rbuf(:,:,:), sbuf(:,:,:), vdata(:,:,:)
+
+ IF (trim(DEF_HIST_mode) == 'one') THEN
+
+ IF (p_is_root) THEN
+
+#ifdef USEMPI
+ IF (.not. DEF_HIST_WriteBack) THEN
+
+ DO idata = 1, hist_concat%ndatablk
+
+ CALL mpi_recv (rmesg, 4, MPI_INTEGER, MPI_ANY_SOURCE, &
+ hist_data_id, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ ixseg = rmesg(2)
+ iyseg = rmesg(3)
+ ndim1 = rmesg(4)
+
+ xgdsp = hist_concat%xsegs(ixseg)%gdsp
+ ygdsp = hist_concat%ysegs(iyseg)%gdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ allocate (rbuf (ndim1,xcnt,ycnt))
+
+ CALL mpi_recv (rbuf, ndim1*xcnt*ycnt, MPI_REAL8, &
+ isrc, hist_data_id, p_comm_glb, p_stat, p_err)
+
+ IF (idata == 1) THEN
+ allocate (vdata (hist_concat%ginfo%nlon, hist_concat%ginfo%nlat, ndim1))
+ vdata(:,:,:) = spval
+ ENDIF
+
+ DO idim1 = 1, ndim1
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt, idim1) = rbuf(idim1,:,:)
+ ENDDO
+
+ deallocate (rbuf)
+ ENDDO
+
+ ELSE
+ CALL hist_writeback_var_header (hist_data_id, filename, dataname, &
+ 4, 'lon', 'lat', dim1name, 'time', '', compress, longname, units)
+ ENDIF
+#else
+ ndim1 = wdata%ub1 - wdata%lb1 + 1
+ allocate (vdata (hist_concat%ginfo%nlon, hist_concat%ginfo%nlat, ndim1))
+ vdata(:,:,:) = spval
+
+ DO iyseg = 1, hist_concat%nyseg
+ DO ixseg = 1, hist_concat%nxseg
+ iblk = hist_concat%xsegs(ixseg)%blk
+ jblk = hist_concat%ysegs(iyseg)%blk
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+ xbdsp = hist_concat%xsegs(ixseg)%bdsp
+ ybdsp = hist_concat%ysegs(iyseg)%bdsp
+ xgdsp = hist_concat%xsegs(ixseg)%gdsp
+ ygdsp = hist_concat%ysegs(iyseg)%gdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ DO idim1 = 1, ndim1
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt,idim1) = &
+ wdata%blk(iblk,jblk)%val(wdata%lb1+idim1-1,xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+ ENDDO
+ ENDIF
+ ENDDO
+ ENDDO
+#endif
+
+
+#ifdef USEMPI
+ IF (.not. DEF_HIST_WriteBack) THEN
+#endif
+ CALL ncio_define_dimension (filename, dim1name, ndim1)
+
+ CALL ncio_write_serial_time (filename, dataname, itime, &
+ vdata, 'lon', 'lat', dim1name, 'time', compress)
+
+ IF (itime == 1) THEN
+ CALL ncio_put_attr (filename, dataname, 'long_name', longname)
+ CALL ncio_put_attr (filename, dataname, 'units', units)
+ CALL ncio_put_attr (filename, dataname, 'missing_value', spval)
+ ENDIF
+
+ deallocate (vdata)
+#ifdef USEMPI
+ ENDIF
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+
+ DO iyseg = 1, hist_concat%nyseg
+ DO ixseg = 1, hist_concat%nxseg
+
+ iblk = hist_concat%xsegs(ixseg)%blk
+ jblk = hist_concat%ysegs(iyseg)%blk
+
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+
+ xbdsp = hist_concat%xsegs(ixseg)%bdsp
+ ybdsp = hist_concat%ysegs(iyseg)%bdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+ ndim1 = size(wdata%blk(iblk,jblk)%val,1)
+
+ allocate (sbuf (ndim1,xcnt,ycnt))
+ sbuf = wdata%blk(iblk,jblk)%val(:, xbdsp+1:xbdsp+xcnt, ybdsp+1:ybdsp+ycnt)
+
+ IF (.not. DEF_HIST_WriteBack) THEN
+ smesg = (/p_iam_glb, ixseg, iyseg, ndim1/)
+ CALL mpi_send (smesg, 4, MPI_INTEGER, &
+ p_address_root, hist_data_id, p_comm_glb, p_err)
+ CALL mpi_send (sbuf, ndim1*xcnt*ycnt, MPI_REAL8, &
+ p_address_root, hist_data_id, p_comm_glb, p_err)
+ ELSE
+ CALL hist_writeback_var (hist_data_id, ixseg, iyseg, wdata3d = sbuf)
+ ENDIF
+
+ deallocate (sbuf)
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+#endif
+
+ hist_data_id = mod(hist_data_id-10000,10000) + 100001
+
+ ELSEIF (trim(DEF_HIST_mode) == 'block') THEN
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ IF ((grid%xcnt(iblk) == 0) .or. (grid%ycnt(jblk) == 0)) CYCLE
+
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+
+ CALL ncio_define_dimension (fileblock, dim1name, wdata%ub1-wdata%lb1+1)
+
+ CALL ncio_write_serial_time (fileblock, dataname, itime, &
+ wdata%blk(iblk,jblk)%val, dim1name, 'lon', 'lat', 'time', compress)
+
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE hist_write_var_real8_3d
+
+
+ SUBROUTINE hist_write_var_real8_4d ( &
+ filename, dataname, dim1name, dim2name, grid, itime, wdata, compress, longname, units)
+
+ USE MOD_Block
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ character (len=*), intent(in) :: dim1name, dim2name
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: itime
+
+ type (block_data_real8_4d), intent(in) :: wdata
+
+ integer, intent(in) :: compress
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk, idata, ixseg, iyseg
+ integer :: xcnt, ycnt, ndim1, ndim2, xbdsp, ybdsp, xgdsp, ygdsp, idim1, idim2
+ integer :: rmesg(5), smesg(5), isrc
+ character(len=256) :: fileblock
+ real(r8), allocatable :: rbuf(:,:,:,:), sbuf(:,:,:,:), vdata(:,:,:,:)
+
+ IF (trim(DEF_HIST_mode) == 'one') THEN
+
+ IF (p_is_root) THEN
+
+#ifdef USEMPI
+ IF (.not. DEF_HIST_WriteBack) THEN
+
+ DO idata = 1, hist_concat%ndatablk
+
+ CALL mpi_recv (rmesg, 5, MPI_INTEGER, MPI_ANY_SOURCE, &
+ hist_data_id, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ ixseg = rmesg(2)
+ iyseg = rmesg(3)
+ ndim1 = rmesg(4)
+ ndim2 = rmesg(5)
+
+ xgdsp = hist_concat%xsegs(ixseg)%gdsp
+ ygdsp = hist_concat%ysegs(iyseg)%gdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ allocate (rbuf (ndim1,ndim2,xcnt,ycnt))
+
+ CALL mpi_recv (rbuf, ndim1*ndim2*xcnt*ycnt, MPI_REAL8, &
+ isrc, hist_data_id, p_comm_glb, p_stat, p_err)
+
+ IF (idata == 1) THEN
+ allocate (vdata (hist_concat%ginfo%nlon,hist_concat%ginfo%nlat,ndim1,ndim2))
+ vdata(:,:,:,:) = spval
+ ENDIF
+
+ DO idim1 = 1, ndim1
+ DO idim2 = 1, ndim2
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt, idim1, idim2) = rbuf(idim1,idim2,:,:)
+ ENDDO
+ ENDDO
+
+ deallocate (rbuf)
+ ENDDO
+
+ ELSE
+ CALL hist_writeback_var_header (hist_data_id, filename, dataname, &
+ 5, 'lon', 'lat', dim1name, dim2name, 'time', compress, longname, units)
+ ENDIF
+#else
+ ndim1 = wdata%ub1 - wdata%lb1 + 1
+ ndim2 = wdata%ub2 - wdata%lb2 + 1
+ allocate (vdata (hist_concat%ginfo%nlon,hist_concat%ginfo%nlat,ndim1,ndim2))
+ vdata(:,:,:,:) = spval
+
+ DO iyseg = 1, hist_concat%nyseg
+ DO ixseg = 1, hist_concat%nxseg
+ iblk = hist_concat%xsegs(ixseg)%blk
+ jblk = hist_concat%ysegs(iyseg)%blk
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+ xbdsp = hist_concat%xsegs(ixseg)%bdsp
+ ybdsp = hist_concat%ysegs(iyseg)%bdsp
+ xgdsp = hist_concat%xsegs(ixseg)%gdsp
+ ygdsp = hist_concat%ysegs(iyseg)%gdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ DO idim1 = 1, ndim1
+ DO idim2 = 1, ndim2
+ vdata (xgdsp+1:xgdsp+xcnt, ygdsp+1:ygdsp+ycnt, idim1, idim2) = &
+ wdata%blk(iblk,jblk)%val(idim1,idim2,xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDDO
+ ENDDO
+
+#endif
+
+#ifdef USEMPI
+ IF (.not. DEF_HIST_WriteBack) THEN
+#endif
+ CALL ncio_define_dimension (filename, dim1name, ndim1)
+ CALL ncio_define_dimension (filename, dim2name, ndim2)
+
+ CALL ncio_write_serial_time (filename, dataname, itime, vdata, &
+ 'lon', 'lat', dim1name, dim2name, 'time', compress)
+
+ IF (itime == 1) THEN
+ CALL ncio_put_attr (filename, dataname, 'long_name', longname)
+ CALL ncio_put_attr (filename, dataname, 'units', units)
+ CALL ncio_put_attr (filename, dataname, 'missing_value', spval)
+ ENDIF
+
+ deallocate (vdata)
+#ifdef USEMPI
+ ENDIF
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+
+ DO iyseg = 1, hist_concat%nyseg
+ DO ixseg = 1, hist_concat%nxseg
+
+ iblk = hist_concat%xsegs(ixseg)%blk
+ jblk = hist_concat%ysegs(iyseg)%blk
+
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+
+ xbdsp = hist_concat%xsegs(ixseg)%bdsp
+ ybdsp = hist_concat%ysegs(iyseg)%bdsp
+ xcnt = hist_concat%xsegs(ixseg)%cnt
+ ycnt = hist_concat%ysegs(iyseg)%cnt
+
+ ndim1 = size(wdata%blk(iblk,jblk)%val,1)
+ ndim2 = size(wdata%blk(iblk,jblk)%val,2)
+ allocate (sbuf (ndim1,ndim2,xcnt,ycnt))
+ sbuf = wdata%blk(iblk,jblk)%val(:,:,xbdsp+1:xbdsp+xcnt,ybdsp+1:ybdsp+ycnt)
+
+ IF (.not. DEF_HIST_WriteBack) THEN
+ smesg = (/p_iam_glb, ixseg, iyseg, ndim1, ndim2/)
+ CALL mpi_send (smesg, 5, MPI_INTEGER, &
+ p_address_root, hist_data_id, p_comm_glb, p_err)
+ CALL mpi_send (sbuf, ndim1*ndim2*xcnt*ycnt, MPI_REAL8, &
+ p_address_root, hist_data_id, p_comm_glb, p_err)
+ ELSE
+ CALL hist_writeback_var (hist_data_id, ixseg, iyseg, wdata4d = sbuf)
+ ENDIF
+
+ deallocate (sbuf)
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+#endif
+
+ hist_data_id = mod(hist_data_id-10000,10000) + 100001
+
+ ELSEIF (trim(DEF_HIST_mode) == 'block') THEN
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ IF ((grid%xcnt(iblk) == 0) .or. (grid%ycnt(jblk) == 0)) CYCLE
+
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+
+ CALL ncio_define_dimension (fileblock, dim1name, wdata%ub1-wdata%lb1+1)
+ CALL ncio_define_dimension (fileblock, dim2name, wdata%ub2-wdata%lb2+1)
+
+ CALL ncio_write_serial_time (fileblock, dataname, itime, &
+ wdata%blk(iblk,jblk)%val, dim1name, dim2name, 'lon', 'lat', 'time', compress)
+
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE hist_write_var_real8_4d
+
+
+ SUBROUTINE hist_write_grid_info (fileblock, grid, iblk, jblk)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: fileblock
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: iblk, jblk
+
+ ! Local variable
+ integer :: yl, yu, xl, xu, nx
+ real(r8), allocatable :: lat_s(:), lat_n(:), lon_w(:), lon_e(:)
+
+ allocate (lon_w (grid%xcnt(iblk)))
+ allocate (lon_e (grid%xcnt(iblk)))
+ allocate (lat_s (grid%ycnt(jblk)))
+ allocate (lat_n (grid%ycnt(jblk)))
+
+ yl = grid%ydsp(jblk) + 1
+ yu = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ lat_s = grid%lat_s(yl:yu)
+ lat_n = grid%lat_n(yl:yu)
+
+ IF (grid%xdsp(iblk) + grid%xcnt(iblk) > grid%nlon) THEN
+ xl = grid%xdsp(iblk) + 1
+ xu = grid%nlon
+ nx = grid%nlon - grid%xdsp(iblk)
+ lon_w(1:nx) = grid%lon_w(xl:xu)
+ lon_e(1:nx) = grid%lon_e(xl:xu)
+
+ xl = 1
+ xu = grid%xcnt(iblk) - nx
+ lon_w(nx+1:grid%xcnt(iblk)) = grid%lon_w(xl:xu)
+ lon_e(nx+1:grid%xcnt(iblk)) = grid%lon_e(xl:xu)
+ ELSE
+ xl = grid%xdsp(iblk) + 1
+ xu = grid%xdsp(iblk) + grid%xcnt(iblk)
+ lon_w = grid%lon_w(xl:xu)
+ lon_e = grid%lon_e(xl:xu)
+ ENDIF
+
+ CALL ncio_define_dimension (fileblock, 'lat', grid%ycnt(jblk))
+ CALL ncio_define_dimension (fileblock, 'lon', grid%xcnt(iblk))
+ CALL ncio_write_serial (fileblock, 'lat_s', lat_s, 'lat')
+ CALL ncio_write_serial (fileblock, 'lat_n', lat_n, 'lat')
+ CALL ncio_write_serial (fileblock, 'lon_w', lon_w, 'lon')
+ CALL ncio_write_serial (fileblock, 'lon_e', lon_e, 'lon')
+
+ CALL ncio_write_colm_dimension (fileblock)
+
+ END SUBROUTINE hist_write_grid_info
+
+END MODULE MOD_HistGridded
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistSingle.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistSingle.F90
new file mode 100644
index 0000000000..2c1b748491
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistSingle.F90
@@ -0,0 +1,370 @@
+#include
+
+#ifdef SinglePoint
+MODULE MOD_HistSingle
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Write out model results at sites to history files.
+!
+! Created by Shupeng Zhang, July 2023
+!
+! TODO...(need complement)
+!----------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_Namelist, only: USE_SITE_HistWriteBack
+ USE MOD_SPMD_Task
+
+ logical :: memory_to_disk
+
+ integer :: ntime_mem
+ integer :: itime_mem
+ integer, allocatable :: time_memory (:)
+
+ ! -- data type --
+ type hist_memory_type
+ character(len=256) :: varname
+ real(r8), allocatable :: v2d (:,:)
+ real(r8), allocatable :: v3d (:,:,:)
+ real(r8), allocatable :: v4d (:,:,:,:)
+ type(hist_memory_type), pointer :: next
+ END type hist_memory_type
+
+ type(hist_memory_type), target :: hist_memory
+ type(hist_memory_type), pointer :: thisvar, nextvar
+
+CONTAINS
+
+ ! -- initialize history IO --
+ SUBROUTINE hist_single_init ()
+
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ ! Local Variables
+ real(r8) :: secs_group, secs_write
+
+ IF (USE_SITE_HistWriteBack) THEN
+
+ IF ( trim(DEF_HIST_groupby) == 'YEAR' ) THEN
+ secs_group = 366*24*3600
+ ELSEIF ( trim(DEF_HIST_groupby) == 'MONTH' ) THEN
+ secs_group = 31*24*3600
+ ELSEIF ( trim(DEF_HIST_groupby) == 'DAY' ) THEN
+ secs_group = 24*3600
+ ENDIF
+
+ select CASE (trim(adjustl(DEF_HIST_FREQ)))
+ CASE ('TIMESTEP')
+ secs_write = DEF_simulation_time%timestep
+ CASE ('HOURLY')
+ secs_write = 3600
+ CASE ('DAILY')
+ secs_write = 24*3600
+ CASE ('MONTHLY')
+ secs_write = 31*24*3600
+ CASE ('YEARLY')
+ secs_write = 366*24*3600
+ END select
+
+ ntime_mem = ceiling(secs_group / secs_write) + 2
+
+ allocate (time_memory (ntime_mem))
+
+ itime_mem = 0
+
+ hist_memory%next => null()
+ hist_memory%varname = ''
+
+ thisvar => hist_memory
+
+ ENDIF
+
+ END SUBROUTINE hist_single_init
+
+ ! -- finalize history IO --
+ SUBROUTINE hist_single_final ()
+
+ IMPLICIT NONE
+
+ IF (USE_SITE_HistWriteBack) THEN
+
+ thisvar => hist_memory%next
+ DO WHILE (associated(thisvar))
+ nextvar => thisvar%next
+ IF (allocated(thisvar%v2d)) deallocate(thisvar%v2d)
+ IF (allocated(thisvar%v3d)) deallocate(thisvar%v3d)
+ IF (allocated(thisvar%v4d)) deallocate(thisvar%v4d)
+ deallocate(thisvar)
+ thisvar => nextvar
+ ENDDO
+
+ deallocate (time_memory)
+
+ ENDIF
+
+ END SUBROUTINE hist_single_final
+
+ ! -- write history time --
+ SUBROUTINE hist_single_write_time (filename, filelast, dataname, time, itime)
+
+ USE MOD_Namelist
+ USE MOD_TimeManager
+ USE MOD_SingleSrfData
+ USE MOD_NetCDFSerial
+ USE MOD_Landpatch, only: numpatch
+#ifdef URBAN_MODEL
+ USE MOD_Landurban, only: numurban
+#endif
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: filelast
+ character (len=*), intent(in) :: dataname
+
+ integer, intent(in) :: time(3)
+ integer, intent(out) :: itime
+
+ ! Local variables
+ integer :: minutes
+ logical :: fexists
+
+ inquire (file=filename, exist=fexists)
+ IF ((.not. fexists) .or. (trim(filename) /= trim(filelast))) THEN
+ CALL ncio_create_file (trim(filename))
+ CALL ncio_define_dimension(filename, 'patch', numpatch)
+
+ CALL ncio_write_serial (filename, 'lat', SITE_lat_location)
+ CALL ncio_put_attr (filename, 'lat', 'long_name', 'latitude')
+ CALL ncio_put_attr (filename, 'lat', 'units', 'degrees_north')
+
+ CALL ncio_write_serial (filename, 'lon', SITE_lon_location)
+ CALL ncio_put_attr (filename, 'lon', 'long_name', 'longitude')
+ CALL ncio_put_attr (filename, 'lon', 'units', 'degrees_east')
+
+ CALL ncio_write_colm_dimension (filename)
+
+ IF (.not. USE_SITE_HistWriteBack) THEN
+ CALL ncio_define_dimension(filename, 'time', 0)
+ ENDIF
+
+ ENDIF
+
+ IF (USE_SITE_HistWriteBack) THEN
+
+ minutes = minutes_since_1900 (time(1), time(2), time(3))
+
+ select CASE (trim(adjustl(DEF_HIST_FREQ)))
+ CASE ('HOURLY')
+ minutes = minutes - 30
+ CASE ('DAILY')
+ minutes = minutes - 720
+ CASE ('MONTHLY')
+ minutes = minutes - 21600
+ CASE ('YEARLY')
+ minutes = minutes - 262800
+ END select
+
+ itime_mem = itime_mem + 1
+ time_memory(itime_mem) = minutes
+
+ IF (memory_to_disk) THEN
+ CALL ncio_define_dimension(filename, 'time', itime_mem)
+ CALL ncio_write_serial (filename, dataname, time_memory(1:itime_mem), 'time')
+ CALL ncio_put_attr (filename, dataname, 'long_name', 'time')
+ CALL ncio_put_attr (filename, dataname, 'units', 'minutes since 1900-1-1 0:0:0')
+ ENDIF
+
+ thisvar => hist_memory
+
+ ELSE
+ CALL ncio_write_time (filename, dataname, time, itime, DEF_HIST_FREQ)
+ ENDIF
+
+ END SUBROUTINE hist_single_write_time
+
+ ! -- write 2D data --
+ SUBROUTINE single_write_2d ( &
+ acc_vec, file_hist, varname, itime_in_file, longname, units)
+
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ IF (USE_SITE_HistWriteBack) THEN
+
+ IF (.not. associated(thisvar%next)) THEN
+ allocate (thisvar%next)
+ thisvar => thisvar%next
+
+ thisvar%next => null()
+ thisvar%varname = varname
+ allocate(thisvar%v2d (size(acc_vec),ntime_mem))
+ ELSE
+ thisvar => thisvar%next
+ ENDIF
+
+ IF (thisvar%varname /= varname) THEN
+ write(*,*) 'Warning: history variable in memory is wrong: ' &
+ // trim(thisvar%varname) // ' should be ' // trim(varname)
+ CALL CoLM_stop ()
+ ENDIF
+
+ thisvar%v2d(:,itime_mem) = acc_vec(:)
+
+ IF (memory_to_disk) THEN
+ CALL ncio_write_serial (file_hist, varname, &
+ thisvar%v2d(:,1:itime_mem), 'patch', 'time')
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+
+ ELSE
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ 'patch', 'time')
+ IF (itime_in_file == 1) THEN
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE single_write_2d
+
+ ! -- write 3D data --
+ SUBROUTINE single_write_3d ( &
+ acc_vec, file_hist, varname, itime_in_file, dim1name, ndim1, longname, units)
+
+ USE MOD_Vars_1DAccFluxes, only: nac
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name
+ integer, intent(in) :: ndim1
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ WHERE (acc_vec /= spval) acc_vec = acc_vec / nac
+
+ IF (USE_SITE_HistWriteBack) THEN
+
+ IF (.not. associated(thisvar%next)) THEN
+ allocate (thisvar%next)
+ thisvar => thisvar%next
+
+ thisvar%next => null()
+ thisvar%varname = varname
+ allocate(thisvar%v3d (ndim1,size(acc_vec,2),ntime_mem))
+ ELSE
+ thisvar => thisvar%next
+ ENDIF
+
+ IF (thisvar%varname /= varname) THEN
+ write(*,*) 'Warning: history variable in memory is wrong: ' &
+ // trim(thisvar%varname) // ' should be ' // trim(varname)
+ CALL CoLM_stop ()
+ ENDIF
+
+ thisvar%v3d(:,:,itime_mem) = acc_vec
+
+ IF (memory_to_disk) THEN
+ CALL ncio_define_dimension (file_hist, dim1name, ndim1)
+ CALL ncio_write_serial (file_hist, varname, thisvar%v3d(:,:,1:itime_mem), &
+ dim1name, 'patch', 'time')
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+
+ ELSE
+ CALL ncio_define_dimension (file_hist, dim1name, ndim1)
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ dim1name, 'patch', 'time')
+ IF (itime_in_file == 1) THEN
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE single_write_3d
+
+ ! -- write 4D data --
+ SUBROUTINE single_write_4d ( &
+ acc_vec, file_hist, varname, itime_in_file, &
+ dim1name, ndim1, dim2name, ndim2, longname, units)
+
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: acc_vec(:,:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name
+ integer, intent(in) :: ndim1
+ character(len=*), intent(in) :: dim2name
+ integer, intent(in) :: ndim2
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ IF (USE_SITE_HistWriteBack) THEN
+
+ IF (.not. associated(thisvar%next)) THEN
+ allocate (thisvar%next)
+ thisvar => thisvar%next
+
+ thisvar%next => null()
+ thisvar%varname = varname
+ allocate(thisvar%v4d (ndim1,ndim2,size(acc_vec,3),ntime_mem))
+ ELSE
+ thisvar => thisvar%next
+ ENDIF
+
+ IF (thisvar%varname /= varname) THEN
+ write(*,*) 'Warning: history variable in memory is wrong: ' &
+ // trim(thisvar%varname) // ' should be ' // trim(varname)
+ CALL CoLM_stop ()
+ ENDIF
+
+ thisvar%v4d(:,:,:,itime_mem) = acc_vec
+
+ IF (memory_to_disk) THEN
+ CALL ncio_define_dimension (file_hist, dim1name, ndim1)
+ CALL ncio_define_dimension (file_hist, dim2name, ndim2)
+ CALL ncio_write_serial (file_hist, varname, thisvar%v4d(:,:,:,1:itime_mem), &
+ dim1name, dim2name, 'patch', 'time')
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+
+ ELSE
+ CALL ncio_define_dimension (file_hist, dim1name, ndim1)
+ CALL ncio_define_dimension (file_hist, dim2name, ndim2)
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ dim1name, dim2name, 'patch', 'time')
+ IF (itime_in_file == 1) THEN
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE single_write_4d
+
+END MODULE MOD_HistSingle
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistVector.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistVector.F90
new file mode 100644
index 0000000000..3311b4e2e2
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistVector.F90
@@ -0,0 +1,623 @@
+#include
+
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+MODULE MOD_HistVector
+
+!----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Write out vectorized model results to history files.
+!
+! Created by Shupeng Zhang, May 2023
+!
+! TODO...(need complement)
+!----------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Vars_Global, only: spval
+ USE MOD_Mesh
+ USE MOD_LandElm
+#ifdef CATCHMENT
+ USE MOD_LandHRU
+#endif
+ USE MOD_Pixelset
+ USE MOD_NetCDFSerial
+#ifdef CATCHMENT
+ USE MOD_HRUVector
+#else
+ USE MOD_ElmVector
+#endif
+
+CONTAINS
+
+ ! -- write history time --
+ SUBROUTINE hist_vector_write_time (filename, filelast, dataname, time, itime_in_file)
+
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: filelast
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: time(3)
+ integer, intent(out) :: itime_in_file
+
+ ! Local Variables
+ logical :: fexists
+
+ IF (p_is_root) THEN
+
+ inquire (file=filename, exist=fexists)
+ IF ((.not. fexists) .or. (trim(filename) /= trim(filelast))) THEN
+ CALL ncio_create_file (trim(filename))
+ CALL ncio_define_dimension(filename, 'time', 0)
+
+#ifdef CATCHMENT
+ CALL ncio_define_dimension(filename, 'hydrounit', totalnumhru)
+
+ CALL ncio_write_serial (filename, 'bsn_hru', eindx_hru, 'hydrounit')
+ CALL ncio_put_attr (filename, 'bsn_hru', 'long_name', &
+ 'basin index of hydrological units in mesh')
+
+ CALL ncio_write_serial (filename, 'typ_hru' , htype_hru, 'hydrounit')
+ CALL ncio_put_attr (filename, 'typ_hru' , 'long_name', &
+ 'index of hydrological units inside basin')
+#else
+ CALL ncio_define_dimension(filename, 'element', totalnumelm)
+ CALL ncio_write_serial (filename, 'elmindex', eindex_glb, 'element')
+ CALL ncio_put_attr (filename, 'elmindex', 'long_name', &
+ 'element index in mesh')
+#endif
+
+ CALL ncio_write_colm_dimension (filename)
+
+ ENDIF
+
+ CALL ncio_write_time (filename, dataname, time, itime_in_file, DEF_HIST_FREQ)
+
+ ENDIF
+
+ END SUBROUTINE hist_vector_write_time
+
+
+ SUBROUTINE aggregate_to_vector_and_write_2d ( &
+ acc_vec_patch, file_hist, varname, itime_in_file, filter, &
+ longname, units, input_mode)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_LandPatch
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: acc_vec_patch (:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ logical, intent(in) :: filter(:)
+
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ character(len=*), intent(in), optional :: input_mode
+
+ ! Local variables
+ integer :: numset, totalnumset, iset, istt, iend, iwork, mesg(2), isrc, ndata, compress
+ logical, allocatable :: mask(:)
+ real(r8), allocatable :: frac(:)
+ real(r8), allocatable :: acc_vec(:), rcache(:)
+ real(r8) :: sumwt
+ character(len=256) :: inmode
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_compute) THEN
+#ifdef CATCHMENT
+ numset = numhru
+#else
+ numset = numelm
+#endif
+
+ inmode = 'average'
+ IF (present(input_mode)) inmode = trim(input_mode)
+
+ IF (numset > 0) THEN
+
+ allocate (acc_vec (numset))
+ acc_vec(:) = spval
+
+ DO iset = 1, numset
+#ifdef CATCHMENT
+ istt = hru_patch%substt(iset)
+ iend = hru_patch%subend(iset)
+#else
+ istt = elm_patch%substt(iset)
+ iend = elm_patch%subend(iset)
+#endif
+
+ IF ((istt > 0) .and. (iend >= istt)) THEN
+ allocate (mask(istt:iend))
+ allocate (frac(istt:iend))
+ mask = (acc_vec_patch(istt:iend) /= spval) .and. filter(istt:iend)
+ IF (any(mask)) THEN
+ IF (trim(inmode) == 'average') THEN
+#ifdef CATCHMENT
+ frac = hru_patch%subfrc(istt:iend)
+#else
+ frac = elm_patch%subfrc(istt:iend)
+#endif
+ sumwt = sum(frac, mask = mask)
+ acc_vec(iset) = sum(frac * acc_vec_patch(istt:iend), mask = mask)
+ acc_vec(iset) = acc_vec(iset) / sumwt
+ ELSE
+ acc_vec(iset) = sum(acc_vec_patch(istt:iend), mask = mask)
+ ENDIF
+ ENDIF
+ deallocate(mask)
+ deallocate(frac)
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef USEMPI
+ mesg = (/p_iam_glb, numset/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numset > 0) THEN
+ CALL mpi_send (acc_vec, numset, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+#ifdef CATCHMENT
+ totalnumset = totalnumhru
+#else
+ totalnumset = totalnumelm
+#endif
+
+ IF (.not. allocated(acc_vec)) THEN
+ allocate (acc_vec (totalnumset))
+ ENDIF
+
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate(rcache (ndata))
+ CALL mpi_recv (rcache, ndata, MPI_REAL8, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+#ifdef CATCHMENT
+ acc_vec(hru_data_address(p_itis_compute(isrc))%val) = rcache
+#else
+ acc_vec(elm_data_address(p_itis_compute(isrc))%val) = rcache
+#endif
+
+ deallocate (rcache)
+ ENDIF
+ ENDDO
+#else
+#ifdef CATCHMENT
+ acc_vec(hru_data_address(0)%val) = acc_vec
+#else
+ acc_vec(elm_data_address(0)%val) = acc_vec
+#endif
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ compress = DEF_HIST_CompressLevel
+
+ IF (itime_in_file >= 1) THEN
+#ifdef CATCHMENT
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ 'hydrounit', 'time', compress)
+#else
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ 'element', 'time', compress)
+#endif
+ ELSE
+#ifdef CATCHMENT
+ CALL ncio_write_serial (file_hist, varname, acc_vec, 'hydrounit', compress)
+#else
+ CALL ncio_write_serial (file_hist, varname, acc_vec, 'element', compress)
+#endif
+ ENDIF
+
+ IF (itime_in_file <= 1) THEN
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+
+ ENDIF
+
+ IF (allocated(acc_vec)) deallocate (acc_vec)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE aggregate_to_vector_and_write_2d
+
+
+ SUBROUTINE aggregate_to_vector_and_write_3d ( &
+ acc_vec_patch, file_hist, varname, itime_in_file, dim1name, lb1, ndim1, filter, &
+ longname, units)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_LandPatch
+ USE MOD_Vars_1DAccFluxes, only: nac
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: acc_vec_patch (lb1:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name
+ integer, intent(in) :: lb1, ndim1
+
+ logical, intent(in) :: filter(:)
+
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ ! Local variables
+ integer :: numset, totalnumset, iset, istt, iend, iwork, mesg(2), isrc, ndata, compress
+ integer :: ub1, i1
+ logical, allocatable :: mask(:)
+ real(r8), allocatable :: frac(:)
+ real(r8), allocatable :: acc_vec(:,:), rcache(:,:)
+ real(r8) :: sumwt
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ ub1 = lb1 + ndim1 - 1
+
+ IF (p_is_compute) THEN
+#ifdef CATCHMENT
+ numset = numhru
+#else
+ numset = numelm
+#endif
+
+ IF (numset > 0) THEN
+
+ allocate (acc_vec (lb1:ub1,numset))
+
+ acc_vec(:,:) = spval
+
+ DO iset = 1, numset
+#ifdef CATCHMENT
+ istt = hru_patch%substt(iset)
+ iend = hru_patch%subend(iset)
+#else
+ istt = elm_patch%substt(iset)
+ iend = elm_patch%subend(iset)
+#endif
+
+ IF ((istt > 0) .and. (iend >= istt)) THEN
+ allocate (mask(istt:iend))
+ allocate (frac(istt:iend))
+ DO i1 = lb1, ub1
+ mask = (acc_vec_patch(i1,istt:iend) /= spval) .and. filter(istt:iend)
+ IF (any(mask)) THEN
+#ifdef CATCHMENT
+ frac = hru_patch%subfrc(istt:iend)
+#else
+ frac = elm_patch%subfrc(istt:iend)
+#endif
+ sumwt = sum(frac, mask = mask)
+ acc_vec(i1,iset) = sum(frac * acc_vec_patch(i1,istt:iend), mask = mask)
+ acc_vec(i1,iset) = acc_vec(i1,iset) / sumwt / nac
+ ENDIF
+ ENDDO
+ deallocate(mask)
+ deallocate(frac)
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef USEMPI
+ mesg = (/p_iam_glb, numset/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numset > 0) THEN
+ CALL mpi_send (acc_vec, ndim1 * numset, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+#ifdef CATCHMENT
+ totalnumset = totalnumhru
+#else
+ totalnumset = totalnumelm
+#endif
+
+ IF (.not. allocated(acc_vec)) THEN
+ allocate (acc_vec (ndim1,totalnumset))
+ ENDIF
+
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate(rcache (ndim1,ndata))
+ CALL mpi_recv (rcache, ndim1*ndata, MPI_REAL8, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ DO i1 = 1, ndim1
+#ifdef CATCHMENT
+ acc_vec(i1,hru_data_address(p_itis_compute(isrc))%val) = rcache(i1,:)
+#else
+ acc_vec(i1,elm_data_address(p_itis_compute(isrc))%val) = rcache(i1,:)
+#endif
+
+ ENDDO
+
+ deallocate (rcache)
+ ENDIF
+ ENDDO
+#else
+ DO i1 = lb1, ub1
+#ifdef CATCHMENT
+ acc_vec(i1,hru_data_address(0)%val) = acc_vec(i1,:)
+#else
+ acc_vec(i1,elm_data_address(0)%val) = acc_vec(i1,:)
+#endif
+ ENDDO
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ CALL ncio_define_dimension (file_hist, dim1name, ndim1)
+
+ compress = DEF_HIST_CompressLevel
+
+ IF (itime_in_file >= 1) THEN
+#ifdef CATCHMENT
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ dim1name, 'hydrounit', 'time', compress)
+#else
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ dim1name, 'element', 'time', compress)
+#endif
+ ELSE
+#ifdef CATCHMENT
+ CALL ncio_write_serial (file_hist, varname, acc_vec, &
+ dim1name, 'hydrounit', compress)
+#else
+ CALL ncio_write_serial (file_hist, varname, acc_vec, &
+ dim1name, 'element', compress)
+#endif
+ ENDIF
+
+ IF (itime_in_file <= 1) THEN
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+
+ ENDIF
+
+ IF (allocated(acc_vec)) deallocate (acc_vec)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE aggregate_to_vector_and_write_3d
+
+
+ SUBROUTINE aggregate_to_vector_and_write_4d ( &
+ acc_vec_patch, file_hist, varname, itime_in_file, &
+ dim1name, lb1, ndim1, dim2name, lb2, ndim2, filter, &
+ longname, units)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_LandPatch
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: acc_vec_patch (lb1:,lb2:,:)
+ character(len=*), intent(in) :: file_hist
+ character(len=*), intent(in) :: varname
+ integer, intent(in) :: itime_in_file
+ character(len=*), intent(in) :: dim1name, dim2name
+ integer, intent(in) :: lb1, ndim1, lb2, ndim2
+
+ logical, intent(in) :: filter(:)
+
+ character(len=*), intent(in) :: longname
+ character(len=*), intent(in) :: units
+
+ ! Local variables
+ integer :: numset, totalnumset, iset, istt, iend, iwork, mesg(2), isrc, ndata, compress
+ integer :: ub1, i1, ub2, i2
+ logical, allocatable :: mask(:)
+ real(r8), allocatable :: frac(:)
+ real(r8), allocatable :: acc_vec(:,:,:), rcache(:,:,:)
+ real(r8) :: sumwt
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ ub1 = lb1 + ndim1 - 1
+ ub2 = lb2 + ndim2 - 1
+
+ IF (p_is_compute) THEN
+#ifdef CATCHMENT
+ numset = numhru
+#else
+ numset = numelm
+#endif
+
+ IF (numset > 0) THEN
+
+ allocate (acc_vec (lb1:ub1,lb2:ub2,numset))
+
+ acc_vec(:,:,:) = spval
+
+ DO iset = 1, numset
+#ifdef CATCHMENT
+ istt = hru_patch%substt(iset)
+ iend = hru_patch%subend(iset)
+#else
+ istt = elm_patch%substt(iset)
+ iend = elm_patch%subend(iset)
+#endif
+
+ IF ((istt > 0) .and. (iend >= istt)) THEN
+ allocate (mask(istt:iend))
+ allocate (frac(istt:iend))
+ DO i1 = lb1, ub1
+ DO i2 = lb2, ub2
+ mask = (acc_vec_patch(i1,i2,istt:iend) /= spval) .and. filter(istt:iend)
+ IF (any(mask)) THEN
+#ifdef CATCHMENT
+ frac = hru_patch%subfrc(istt:iend)
+#else
+ frac = elm_patch%subfrc(istt:iend)
+#endif
+ sumwt = sum(frac, mask = mask)
+ acc_vec(i1,i2,iset) = sum(frac * acc_vec_patch(i1,i2,istt:iend), mask = mask)
+ acc_vec(i1,i2,iset) = acc_vec(i1,i2,iset) / sumwt
+ ENDIF
+ ENDDO
+ ENDDO
+ deallocate(mask)
+ deallocate(frac)
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef USEMPI
+ mesg = (/p_iam_glb, numset/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numset > 0) THEN
+ CALL mpi_send (acc_vec, ndim1 * ndim2 * numset, MPI_REAL8, &
+ p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+#ifdef CATCHMENT
+ totalnumset = totalnumhru
+#else
+ totalnumset = totalnumelm
+#endif
+
+ IF (.not. allocated(acc_vec)) THEN
+ allocate (acc_vec (ndim1,ndim2,totalnumset))
+ ENDIF
+
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate(rcache (ndim1,ndim2,ndata))
+ CALL mpi_recv (rcache, ndim1 * ndim2 * ndata, MPI_REAL8, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ DO i1 = 1, ndim1
+ DO i2 = 1, ndim2
+#ifdef CATCHMENT
+ acc_vec(i1,i2,hru_data_address(p_itis_compute(isrc))%val) = rcache(i1,i2,:)
+#else
+ acc_vec(i1,i2,elm_data_address(p_itis_compute(isrc))%val) = rcache(i1,i2,:)
+#endif
+ ENDDO
+ ENDDO
+
+ deallocate (rcache)
+ ENDIF
+ ENDDO
+#else
+ DO i1 = lb1, ub1
+ DO i2 = lb2, ub2
+#ifdef CATCHMENT
+ acc_vec(i1,i2,hru_data_address(0)%val) = acc_vec(i1,i2,:)
+#else
+ acc_vec(i1,i2,elm_data_address(0)%val) = acc_vec(i1,i2,:)
+#endif
+ ENDDO
+ ENDDO
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ CALL ncio_define_dimension (file_hist, dim1name, ndim1)
+ CALL ncio_define_dimension (file_hist, dim2name, ndim2)
+
+ compress = DEF_HIST_CompressLevel
+
+ IF (itime_in_file >= 1) THEN
+#ifdef CATCHMENT
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ dim1name, dim2name, 'hydrounit', 'time', compress)
+#else
+ CALL ncio_write_serial_time (file_hist, varname, itime_in_file, acc_vec, &
+ dim1name, dim2name, 'element', 'time', compress)
+#endif
+ ELSE
+#ifdef CATCHMENT
+ CALL ncio_write_serial (file_hist, varname, acc_vec, &
+ dim1name, dim2name, 'hydrounit', compress)
+#else
+ CALL ncio_write_serial (file_hist, varname, acc_vec, &
+ dim1name, dim2name, 'element', compress)
+#endif
+ ENDIF
+
+ IF (itime_in_file <= 1) THEN
+ CALL ncio_put_attr (file_hist, varname, 'long_name', longname)
+ CALL ncio_put_attr (file_hist, varname, 'units', units)
+ CALL ncio_put_attr (file_hist, varname, 'missing_value', spval)
+ ENDIF
+
+ ENDIF
+
+ IF (allocated(acc_vec)) deallocate (acc_vec)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE aggregate_to_vector_and_write_4d
+
+
+END MODULE MOD_HistVector
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistWriteBack.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistWriteBack.F90
new file mode 100644
index 0000000000..05397d1516
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_HistWriteBack.F90
@@ -0,0 +1,743 @@
+#include
+
+#ifdef USEMPI
+MODULE MOD_HistWriteBack
+!----------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Write out data to history files by a dedicated process.
+!
+! Author: Shupeng Zhang, 11/2023
+!----------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+
+ ! type of send buffer
+ type :: HistSendBufferType
+ integer :: dataid
+ integer :: datatag
+ integer :: sendreqs (3)
+ integer :: sendint4 (5)
+ character(len=256) :: sendchar (9)
+ real(r8), allocatable :: senddata (:)
+ type(HistSendBufferType), pointer :: next
+ END type HistSendBufferType
+
+ ! Sending Variables
+ type(HistSendBufferType), pointer :: HistSendBuffer
+ type(HistSendBufferType), pointer :: LastSendBuffer
+
+ ! type of times
+ type :: timenodetype
+ character(len=256) :: filename
+ character(len=256) :: filelast
+ character(len=256) :: timename
+ integer :: time(3)
+ integer :: req (4)
+ type(timenodetype), pointer :: next
+ END type timenodetype
+
+ ! time nodes
+ integer :: dataid_zero = 0
+ integer :: req_zero
+ type(timenodetype), pointer :: timenodes, lasttime
+
+ ! dimension information
+ logical :: SDimInited = .false.
+
+ ! 1: grid-based
+ integer :: nGridData, nxGridSeg, nyGridSeg
+ integer, allocatable :: xGridDsp(:), xGridCnt(:)
+ integer, allocatable :: yGridDsp(:), yGridCnt(:)
+
+ integer :: nlat, nlon
+ real(r8), allocatable :: lat_c(:), lat_s(:), lat_n(:)
+ real(r8), allocatable :: lon_c(:), lon_w(:), lon_e(:)
+
+ ! Memory limits
+ integer*8, parameter :: MaxHistMemSize = 1073741824_8 ! 1024^3
+ integer*8 :: TotalMemSize = 0
+
+ integer :: itime_in_file_wb
+
+ ! tags
+ integer, parameter :: tag_next = 1
+ integer, parameter :: tag_time = 2
+ integer, parameter :: tag_dims = 3
+
+CONTAINS
+
+ SUBROUTINE hist_writeback_daemon ()
+
+ USE MOD_Namelist, only: DEF_HIST_FREQ
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ ! Local Variables
+ integer :: dataid, tag
+ integer :: time(3), ndims, ndim1, ndim2, dimlens(4), compress
+ integer :: i, idata, isrc, ixseg, iyseg, xdsp, ydsp, xcnt, ycnt, idim1, idim2
+
+ integer :: recvint4 (5)
+ character(len=256) :: recvchar (9)
+ real(r8), allocatable :: datathis (:)
+
+ character(len=256) :: filename, filelast, dataname, longname, units
+ character(len=256) :: dim1name, dim2name, dim3name, dim4name, dim5name
+ logical :: fexists
+
+ real(r8), allocatable :: wdata1d(:), wdata2d(:,:), wdata3d(:,:,:), wdata4d(:,:,:,:)
+ real(r8), allocatable :: tmp3d(:,:,:), tmp4d(:,:,:,:)
+
+
+ DO WHILE (.true.)
+
+ CALL mpi_recv (dataid, 1, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_next, p_comm_glb_plus, p_stat, p_err)
+
+ IF (dataid < 0) THEN
+
+ EXIT
+
+ ELSEIF (dataid == 0) THEN
+
+ CALL mpi_recv (filename, 256, MPI_CHARACTER, &
+ MPI_ANY_SOURCE, tag_time, p_comm_glb_plus, p_stat, p_err)
+
+ CALL mpi_recv (filelast, 256, MPI_CHARACTER, &
+ MPI_ANY_SOURCE, tag_time, p_comm_glb_plus, p_stat, p_err)
+
+ CALL mpi_recv (dataname, 256, MPI_CHARACTER, &
+ MPI_ANY_SOURCE, tag_time, p_comm_glb_plus, p_stat, p_err)
+
+ CALL mpi_recv (time, 3, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_time, p_comm_glb_plus, p_stat, p_err)
+
+ IF (.not. SDimInited) THEN
+
+ CALL mpi_recv (nGridData, 1, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (nxGridSeg, 1, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (nyGridSeg, 1, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+
+ allocate (xGridDsp (nxGridSeg))
+ allocate (xGridCnt (nxGridSeg))
+ allocate (yGridDsp (nyGridSeg))
+ allocate (yGridCnt (nyGridSeg))
+
+ CALL mpi_recv (xGridDsp, nxGridSeg, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (xGridCnt, nxGridSeg, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (yGridDsp, nyGridSeg, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (yGridCnt, nyGridSeg, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+
+ CALL mpi_recv (nlat, 1, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+
+ allocate(lat_c(nlat))
+ allocate(lat_s(nlat))
+ allocate(lat_n(nlat))
+
+ CALL mpi_recv (lat_c, nlat, MPI_REAL8, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (lat_s, nlat, MPI_REAL8, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (lat_n, nlat, MPI_REAL8, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+
+ CALL mpi_recv (nlon, 1, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+
+ allocate(lon_c(nlon))
+ allocate(lon_w(nlon))
+ allocate(lon_e(nlon))
+
+ CALL mpi_recv (lon_c, nlon, MPI_REAL8, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (lon_w, nlon, MPI_REAL8, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+ CALL mpi_recv (lon_e, nlon, MPI_REAL8, &
+ MPI_ANY_SOURCE, tag_dims, p_comm_glb_plus, p_stat, p_err)
+
+ SDimInited = .true.
+
+ ENDIF
+
+ inquire (file=filename, exist=fexists)
+ IF ((.not. fexists) .or. (trim(filename) /= trim(filelast))) THEN
+
+ CALL ncio_create_file (trim(filename))
+
+ CALL ncio_define_dimension(filename, 'time', 0)
+
+ CALL ncio_define_dimension(filename, 'lat', nlat)
+ CALL ncio_define_dimension(filename, 'lon', nlon)
+
+ CALL ncio_write_serial (filename, 'lat', lat_c, 'lat')
+ CALL ncio_write_serial (filename, 'lon', lon_c, 'lon')
+ CALL ncio_write_serial (filename, 'lat_s', lat_s, 'lat')
+ CALL ncio_write_serial (filename, 'lat_n', lat_n, 'lat')
+ CALL ncio_write_serial (filename, 'lon_w', lon_w, 'lon')
+ CALL ncio_write_serial (filename, 'lon_e', lon_e, 'lon')
+
+ CALL ncio_put_attr (filename, 'lat', 'long_name', 'latitude')
+ CALL ncio_put_attr (filename, 'lat', 'units', 'degrees_north')
+ CALL ncio_put_attr (filename, 'lon', 'long_name', 'longitude')
+ CALL ncio_put_attr (filename, 'lon', 'units', 'degrees_east')
+
+ CALL ncio_write_colm_dimension (filename)
+
+ ENDIF
+
+ CALL ncio_write_time (filename, dataname, time, itime_in_file_wb, DEF_HIST_FREQ)
+
+ ELSE
+
+ !--------------------------------
+ ! receive and write history data.
+ !--------------------------------
+
+ ! (1) data header
+ tag = dataid*10
+ CALL mpi_recv (recvint4(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, tag, p_comm_glb_plus, p_stat, p_err)
+
+ ndims = recvint4(1)
+ compress = recvint4(2)
+
+ CALL mpi_recv (recvchar(1:9), 256*9, MPI_CHARACTER, &
+ MPI_ANY_SOURCE, tag, p_comm_glb_plus, p_stat, p_err)
+
+ filename = recvchar(1)
+ dataname = recvchar(2)
+ dim1name = recvchar(3)
+ dim2name = recvchar(4)
+ dim3name = recvchar(5)
+ dim4name = recvchar(6)
+ dim5name = recvchar(7)
+ longname = recvchar(8)
+ units = recvchar(9)
+
+ ! (2) data
+ tag = dataid*10+1
+
+ DO idata = 1, nGridData
+
+ CALL mpi_recv (recvint4(1:5), 5, MPI_INTEGER, MPI_ANY_SOURCE, &
+ tag, p_comm_glb_plus, p_stat, p_err)
+
+ isrc = recvint4(1)
+ ixseg = recvint4(2)
+ iyseg = recvint4(3)
+ ndim1 = recvint4(4)
+ ndim2 = recvint4(5)
+
+ xdsp = xGridDsp(ixseg)
+ ydsp = yGridDsp(iyseg)
+ xcnt = xGridCnt(ixseg)
+ ycnt = yGridCnt(iyseg)
+
+ SELECTCASE (ndims)
+ CASE (2:3)
+
+ dimlens = (/nlon, nlat, 0, 0/)
+
+ IF (.not. allocated(wdata2d)) THEN
+ allocate (wdata2d (nlon,nlat))
+ ENDIF
+
+ allocate (datathis(xcnt*ycnt))
+ CALL mpi_recv (datathis, xcnt*ycnt, MPI_REAL8, &
+ isrc, tag, p_comm_glb_plus, p_stat, p_err)
+
+ wdata2d(xdsp+1:xdsp+xcnt, ydsp+1:ydsp+ycnt) = &
+ reshape(datathis,(/xcnt,ycnt/))
+
+ CASE (4)
+
+ dimlens = (/ndim1, nlon, nlat, 0/)
+
+ IF (.not. allocated(wdata3d)) THEN
+ allocate (wdata3d (nlon,nlat,ndim1))
+ allocate (tmp3d (ndim1,nlon,nlat))
+ ENDIF
+
+ allocate (datathis(ndim1*xcnt*ycnt))
+ CALL mpi_recv (datathis, ndim1*xcnt*ycnt, MPI_REAL8, &
+ isrc, tag, p_comm_glb_plus, p_stat, p_err)
+
+ tmp3d = reshape(datathis,(/ndim1,xcnt,ycnt/))
+ DO idim1 = 1, ndim1
+ wdata3d(xdsp+1:xdsp+xcnt, ydsp+1:ydsp+ycnt, idim1) = tmp3d(idim1, :, :)
+ ENDDO
+
+ CASE (5)
+
+ dimlens = (/ndim1, ndim2, nlon, nlat/)
+
+ IF (.not. allocated(wdata4d)) THEN
+ allocate (wdata4d (nlon,nlat,ndim1,ndim2))
+ allocate (tmp4d (ndim1,ndim2,nlon,nlat))
+ ENDIF
+
+ allocate (datathis(ndim1*ndim2*xcnt*ycnt))
+ CALL mpi_recv (datathis, ndim1*ndim2*xcnt*ycnt, MPI_REAL8, &
+ isrc, tag, p_comm_glb_plus, p_stat, p_err)
+
+ tmp4d = reshape(datathis,(/ndim1, ndim2, xcnt, ycnt/))
+
+ DO idim1 = 1, ndim1
+ DO idim2 = 1, ndim2
+ wdata4d(xdsp+1:xdsp+xcnt, ydsp+1:ydsp+ycnt, idim1, idim2) = &
+ tmp4d(idim1, idim2, :, :)
+ ENDDO
+ ENDDO
+
+ ENDSELECT
+
+ deallocate (datathis)
+
+ ENDDO
+
+
+ IF (ndims >= 4) CALL ncio_define_dimension (filename, dim3name, dimlens(1))
+ IF (ndims >= 5) CALL ncio_define_dimension (filename, dim4name, dimlens(2))
+
+ SELECTCASE (ndims)
+ CASE (2) ! for variables with [lon,lat]
+
+ CALL ncio_write_serial (filename, dataname, wdata2d, dim1name, dim2name, compress)
+
+ deallocate(wdata2d)
+ CASE (3) ! for variables with [lon,lat,time]
+
+ CALL ncio_write_serial_time (filename, dataname, itime_in_file_wb, wdata2d, &
+ dim1name, dim2name, dim3name, compress)
+
+ deallocate(wdata2d)
+ CASE (4) ! for variables with [lon,lat,dim3,time]
+
+ CALL ncio_write_serial_time (filename, dataname, itime_in_file_wb, wdata3d, &
+ dim1name, dim2name, dim3name, dim4name, compress)
+
+ deallocate(tmp3d )
+ deallocate(wdata3d)
+ CASE (5) ! for variables with [lon,lat,dim3,dim4,time]
+
+ CALL ncio_write_serial_time (filename, dataname, itime_in_file_wb, wdata4d, &
+ dim1name, dim2name, dim3name, dim4name, dim5name, compress)
+
+ deallocate(tmp4d )
+ deallocate(wdata4d)
+ ENDSELECT
+
+ IF (itime_in_file_wb <= 1) THEN
+ CALL ncio_put_attr (filename, dataname, 'long_name', longname)
+ CALL ncio_put_attr (filename, dataname, 'units', units)
+ CALL ncio_put_attr (filename, dataname, 'missing_value', spval)
+ ENDIF
+
+ write(*,'(3A,I0,2A)') 'HIST WriteBack: ', trim(basename(filename)), &
+ ' (time ', itime_in_file_wb, '): ', trim(dataname)
+
+ ENDIF
+
+ ENDDO
+
+ END SUBROUTINE hist_writeback_daemon
+
+ ! -----
+ SUBROUTINE hist_writeback_latlon_time (filename, filelast, timename, time, HistConcat)
+
+ USE MOD_Namelist
+ USE MOD_Grid
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: filelast
+ character (len=*), intent(in) :: timename
+ integer, intent(in) :: time(3)
+ type(grid_concat_type), intent(in) :: HistConcat
+
+ ! Local Variables
+ integer :: i
+ logical :: senddone
+ integer :: sendstat(MPI_STATUS_SIZE,4)
+ type(timenodetype), pointer :: tempnode
+
+ IF (.not. associated(timenodes)) THEN
+ allocate (timenodes)
+ lasttime => timenodes
+ ELSE
+ allocate (lasttime%next)
+ lasttime => lasttime%next
+ ENDIF
+
+ lasttime%filename = filename
+ lasttime%filelast = filelast
+ lasttime%timename = timename
+ lasttime%time = time
+ lasttime%next => null()
+
+ CALL mpi_isend (dataid_zero, 1, MPI_INTEGER, &
+ p_address_history_task, tag_next, p_comm_glb_plus, req_zero, p_err)
+
+ CALL mpi_isend (lasttime%filename, 256, MPI_CHARACTER, &
+ p_address_history_task, tag_time, p_comm_glb_plus, lasttime%req(1), p_err)
+
+ CALL mpi_isend (lasttime%filelast, 256, MPI_CHARACTER, &
+ p_address_history_task, tag_time, p_comm_glb_plus, lasttime%req(2), p_err)
+
+ CALL mpi_isend (lasttime%timename, 256, MPI_CHARACTER, &
+ p_address_history_task, tag_time, p_comm_glb_plus, lasttime%req(3), p_err)
+
+ CALL mpi_isend (lasttime%time, 3, MPI_INTEGER, &
+ p_address_history_task, tag_time, p_comm_glb_plus, lasttime%req(4), p_err)
+
+
+ IF (.not. SDimInited) THEN
+
+ nGridData = HistConcat%ndatablk
+ nxGridSeg = HistConcat%nxseg
+ nyGridSeg = HistConcat%nyseg
+
+ allocate (xGridDsp (nxGridSeg))
+ allocate (xGridCnt (nxGridSeg))
+ allocate (yGridDsp (nyGridSeg))
+ allocate (yGridCnt (nyGridSeg))
+
+ DO i = 1, nxGridSeg
+ xGridDsp(i) = HistConcat%xsegs(i)%gdsp
+ xGridCnt(i) = HistConcat%xsegs(i)%cnt
+ ENDDO
+
+ DO i = 1, nyGridSeg
+ yGridDsp(i) = HistConcat%ysegs(i)%gdsp
+ yGridCnt(i) = HistConcat%ysegs(i)%cnt
+ ENDDO
+
+ CALL mpi_send (nGridData, 1, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (nxGridSeg, 1, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (nyGridSeg, 1, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+
+ CALL mpi_send (xGridDsp, nxGridSeg, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (xGridCnt, nxGridSeg, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (yGridDsp, nyGridSeg, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (yGridCnt, nyGridSeg, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+
+ nlat = HistConcat%ginfo%nlat
+ nlon = HistConcat%ginfo%nlon
+ allocate(lat_c(nlat)); lat_c = HistConcat%ginfo%lat_c
+ allocate(lat_s(nlat)); lat_s = HistConcat%ginfo%lat_s
+ allocate(lat_n(nlat)); lat_n = HistConcat%ginfo%lat_n
+ allocate(lon_c(nlon)); lon_c = HistConcat%ginfo%lon_c
+ allocate(lon_w(nlon)); lon_w = HistConcat%ginfo%lon_w
+ allocate(lon_e(nlon)); lon_e = HistConcat%ginfo%lon_e
+
+ CALL mpi_send (nlat, 1, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (lat_c, nlat, MPI_REAL8, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (lat_s, nlat, MPI_REAL8, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (lat_n, nlat, MPI_REAL8, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (nlon, 1, MPI_INTEGER, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (lon_c, nlon, MPI_REAL8, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (lon_w, nlon, MPI_REAL8, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+ CALL mpi_send (lon_e, nlon, MPI_REAL8, p_address_history_task, tag_dims, &
+ p_comm_glb_plus, p_err)
+
+ SDimInited = .true.
+
+ ENDIF
+
+ DO WHILE (associated(timenodes%next))
+
+ CALL MPI_TestAll (4, timenodes%req, senddone, sendstat(:,1:4), p_err)
+
+ IF (senddone) THEN
+ tempnode => timenodes
+ timenodes => timenodes%next
+ deallocate(tempnode)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE hist_writeback_latlon_time
+
+ ! -----
+ SUBROUTINE hist_writeback_var_header (dataid, filename, dataname, &
+ ndims, dim1name, dim2name, dim3name, dim4name, dim5name, &
+ compress, longname, units)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: dataid
+ character(len=*), intent(in) :: filename, dataname
+ integer, intent(in) :: ndims
+ character(len=*), intent(in) :: dim1name, dim2name, dim3name, dim4name, dim5name
+ integer, intent(in) :: compress
+ character(len=*), intent(in) :: longname, units
+
+ ! Local Variables
+ logical :: senddone
+ integer :: sendstat(MPI_STATUS_SIZE,3)
+ type(HistSendBufferType), pointer :: TempSendBuffer
+
+ ! append sending buffer
+ IF (.not. associated(HistSendBuffer)) THEN
+ allocate (HistSendBuffer)
+ LastSendBuffer => HistSendBuffer
+ ELSE
+ allocate (LastSendBuffer%next)
+ LastSendBuffer => LastSendBuffer%next
+ ENDIF
+
+ LastSendBuffer%next => null()
+
+ ! clean sending buffer and free memory
+ DO WHILE (associated(HistSendBuffer%next))
+
+ CALL MPI_Testall (3, HistSendBuffer%sendreqs, senddone, sendstat(:,1:3), p_err)
+
+ IF (senddone) THEN
+
+ TempSendBuffer => HistSendBuffer
+ HistSendBuffer => HistSendBuffer%next
+
+ IF (allocated(TempSendBuffer%senddata)) THEN
+ deallocate (TempSendBuffer%senddata)
+ ENDIF
+ deallocate (TempSendBuffer)
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ LastSendBuffer%dataid = dataid
+ LastSendBuffer%datatag = dataid*10
+
+ LastSendBuffer%sendint4(1:2) = (/ndims, compress/)
+
+ LastSendBuffer%sendchar(1) = filename
+ LastSendBuffer%sendchar(2) = dataname
+ LastSendBuffer%sendchar(3) = dim1name
+ LastSendBuffer%sendchar(4) = dim2name
+ LastSendBuffer%sendchar(5) = dim3name
+ LastSendBuffer%sendchar(6) = dim4name
+ LastSendBuffer%sendchar(7) = dim5name
+ LastSendBuffer%sendchar(8) = longname
+ LastSendBuffer%sendchar(9) = units
+
+ CALL mpi_isend (LastSendBuffer%dataid, 1, MPI_INTEGER, &
+ p_address_history_task, tag_next, p_comm_glb_plus, LastSendBuffer%sendreqs(1), p_err)
+
+ CALL mpi_isend (LastSendBuffer%sendint4(1:2), 2, MPI_INTEGER, &
+ p_address_history_task, LastSendBuffer%datatag, &
+ p_comm_glb_plus, LastSendBuffer%sendreqs(2), p_err)
+
+ CALL mpi_isend (LastSendBuffer%sendchar, 256*9, MPI_CHARACTER, &
+ p_address_history_task, LastSendBuffer%datatag, &
+ p_comm_glb_plus, LastSendBuffer%sendreqs(3), p_err)
+
+ END SUBROUTINE hist_writeback_var_header
+
+ ! -----
+ SUBROUTINE hist_writeback_var ( dataid, ixseg, iyseg, &
+ wdata1d, wdata2d, wdata3d, wdata4d)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: dataid, ixseg, iyseg
+
+ real(r8), intent(in), optional :: wdata1d(:)
+ real(r8), intent(in), optional :: wdata2d(:,:)
+ real(r8), intent(in), optional :: wdata3d(:,:,:)
+ real(r8), intent(in), optional :: wdata4d(:,:,:,:)
+
+ ! Local Variables
+ integer :: totalsize, ndim1, ndim2
+ logical :: senddone
+ integer :: sendstat(MPI_STATUS_SIZE,2)
+ type(HistSendBufferType), pointer :: TempSendBuffer
+
+ ! append sending buffer
+ IF (.not. associated(HistSendBuffer)) THEN
+ allocate (HistSendBuffer)
+ LastSendBuffer => HistSendBuffer
+ TotalMemSize = 0
+ ELSE
+ allocate (LastSendBuffer%next)
+ LastSendBuffer => LastSendBuffer%next
+ ENDIF
+
+ LastSendBuffer%next => null()
+
+ ! clean sending buffer and free memory
+ DO WHILE (associated(HistSendBuffer%next))
+
+ IF (TotalMemSize > MaxHistMemSize) THEN
+ CALL MPI_Waitall (2, HistSendBuffer%sendreqs(1:2), sendstat(:,1:2), p_err)
+ ELSE
+ CALL MPI_Testall (2, HistSendBuffer%sendreqs(1:2), senddone, sendstat(:,1:2), p_err)
+ IF (.not. senddone) EXIT
+ ENDIF
+
+ TotalMemSize = TotalMemSize - size(HistSendBuffer%senddata)
+
+ TempSendBuffer => HistSendBuffer
+ HistSendBuffer => HistSendBuffer%next
+ deallocate(TempSendBuffer%senddata)
+ deallocate(TempSendBuffer)
+
+ ENDDO
+
+ LastSendBuffer%datatag = dataid*10+1
+
+ ndim1 = 0
+ ndim2 = 0
+
+ IF (present(wdata2d)) THEN
+
+ totalsize = size(wdata2d)
+ allocate(LastSendBuffer%senddata(totalsize))
+ LastSendBuffer%senddata = reshape(wdata2d, (/totalsize/))
+
+ ELSEIF (present(wdata3d)) THEN
+
+ ndim1 = size(wdata3d,1)
+ totalsize = size(wdata3d)
+ allocate(LastSendBuffer%senddata(totalsize))
+ LastSendBuffer%senddata = reshape(wdata3d, (/totalsize/))
+
+ ELSEIF (present(wdata4d)) THEN
+
+ ndim1 = size(wdata4d,1)
+ ndim2 = size(wdata4d,2)
+ totalsize = size(wdata4d)
+ allocate(LastSendBuffer%senddata(totalsize))
+ LastSendBuffer%senddata = reshape(wdata4d, (/totalsize/))
+
+ ENDIF
+
+ TotalMemSize = TotalMemSize + totalsize
+
+ LastSendBuffer%sendint4(1:5) = (/p_iam_glb_plus, ixseg, iyseg, ndim1, ndim2/)
+
+ CALL mpi_isend (LastSendBuffer%sendint4(1:5), 5, MPI_INTEGER, &
+ p_address_history_task, LastSendBuffer%datatag, &
+ p_comm_glb_plus, LastSendBuffer%sendreqs(1), p_err)
+
+ CALL mpi_isend (LastSendBuffer%senddata, totalsize, MPI_REAL8, &
+ p_address_history_task, LastSendBuffer%datatag, &
+ p_comm_glb_plus, LastSendBuffer%sendreqs(2), p_err)
+
+ END SUBROUTINE hist_writeback_var
+
+ ! -----
+ SUBROUTINE hist_writeback_exit ()
+
+ IMPLICIT NONE
+
+ ! Local Variables
+ integer :: dataid, nreq
+ integer :: sendstat(MPI_STATUS_SIZE,4)
+ type(timenodetype), pointer :: tempnode
+ type(HistSendBufferType), pointer :: TempSendBuffer
+
+ lasttime => null()
+ DO WHILE (associated(timenodes))
+
+ CALL MPI_WaitAll (4, timenodes%req, sendstat(:,1:4), p_err)
+
+ tempnode => timenodes
+ timenodes => timenodes%next
+ deallocate(tempnode)
+ ENDDO
+
+ LastSendBuffer => null()
+ DO WHILE (associated(HistSendBuffer))
+
+ IF (allocated(HistSendBuffer%senddata)) THEN
+ CALL MPI_Waitall (2, HistSendBuffer%sendreqs(1:2), sendstat(:,1:2), p_err)
+ deallocate(HistSendBuffer%senddata)
+ ELSE
+ CALL MPI_Waitall (3, HistSendBuffer%sendreqs(1:3), sendstat(:,1:3), p_err)
+ ENDIF
+
+ TempSendBuffer => HistSendBuffer
+ HistSendBuffer => HistSendBuffer%next
+ deallocate (TempSendBuffer)
+
+ ENDDO
+
+ IF (allocated(xGridDsp)) deallocate(xGridDsp)
+ IF (allocated(yGridDsp)) deallocate(yGridDsp)
+ IF (allocated(xGridCnt)) deallocate(xGridCnt)
+ IF (allocated(yGridCnt)) deallocate(yGridCnt)
+ IF (allocated(lat_c )) deallocate(lat_c )
+ IF (allocated(lat_s )) deallocate(lat_s )
+ IF (allocated(lat_n )) deallocate(lat_n )
+ IF (allocated(lon_c )) deallocate(lon_c )
+ IF (allocated(lon_w )) deallocate(lon_w )
+ IF (allocated(lon_e )) deallocate(lon_e )
+
+
+ IF (.not. p_is_history_task) THEN
+ CALL mpi_barrier (p_comm_glb, p_err)
+ ENDIF
+
+ IF (p_is_root) THEN
+ dataid = -1
+ CALL mpi_send (dataid, 1, MPI_INTEGER, p_address_history_task, &
+ tag_next, p_comm_glb_plus, p_err)
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb_plus, p_err)
+
+ END SUBROUTINE hist_writeback_exit
+
+ ! ----
+ character(len=256) FUNCTION basename (fullname)
+
+ IMPLICIT NONE
+ character(len=*), intent(in) :: fullname
+
+ ! Local variables
+ integer :: i, n
+
+ i = len_trim (fullname)
+ DO WHILE (i > 0)
+ IF (fullname(i:i) == '/') EXIT
+ i = i - 1
+ ENDDO
+
+ IF (i > 0) THEN
+ basename = fullname(i+1:)
+ ELSE
+ basename = fullname
+ ENDIF
+
+ END FUNCTION basename
+
+END MODULE MOD_HistWriteBack
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Irrigation.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Irrigation.F90
new file mode 100644
index 0000000000..69deecce49
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Irrigation.F90
@@ -0,0 +1,538 @@
+#include
+#ifdef CROP
+MODULE MOD_Irrigation
+
+! DESCRIPTION:
+! This MODULE has all irrigation related subroutines for irrigated crop at either IGBP/USGS or PFT Land type classification and even in the C and N cycle.
+ USE MOD_Precision
+ USE MOD_TimeManager
+ USE MOD_Namelist, only: DEF_simulation_time, DEF_IRRIGATION_ALLOCATION, DEF_USE_VariablySaturatedFlow
+ USE MOD_Const_Physical, only: tfrz, denice, denh2o
+ USE MOD_Const_PFT, only: irrig_crop
+ USE MOD_LandPFT, only : patch_pft_s, patch_pft_e
+ USE MOD_Vars_Global, only: irrig_start_time, irrig_max_depth, irrig_threshold_fraction, irrig_supply_fraction, irrig_min_cphase, irrig_max_cphase, irrig_time_per_day, &
+ irrig_method_drip, irrig_method_sprinkler, irrig_method_flood, irrig_method_paddy
+ USE MOD_Qsadv, only: qsadv
+ USE MOD_Vars_TimeInvariants, only: pondmx, &
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, fc_vgm, sc_vgm,&
+#endif
+ porsl, psi0, bsw
+ USE MOD_Vars_TimeVariables, only: tref, t_soisno, wliq_soisno, wice_soisno, zwt, wa, &
+ irrig_rate, sum_irrig, sum_deficit_irrig, sum_irrig_count, n_irrig_steps_left, &
+ tairday, usday, vsday, pairday, rnetday, fgrndday, potential_evapotranspiration,&
+ groundwater_demand, groundwater_supply, reservoirriver_demand, reservoirriver_supply, &
+ reservoir_supply, river_supply, runoff_supply, &
+ waterstorage, deficit_irrig, actual_irrig, irrig_gw_alloc, irrig_sw_alloc, zwt_stand
+ USE MOD_Vars_PFTimeInvariants, only: pftclass
+ USE MOD_Vars_PFTimeVariables, only: irrig_method_p
+ USE MOD_BGC_Vars_PFTimeVariables, only: cphase_p
+ USE MOD_Vars_1DForcing, only: forc_t, forc_frl, forc_psrf, forc_us, forc_vs
+ USE MOD_Vars_1DFluxes, only: sabg, sabvsun, sabvsha, olrg, fgrnd
+ USE MOD_Hydro_SoilFunction, only: soil_vliq_from_psi
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ PUBLIC :: CalIrrigationNeeded
+ PUBLIC :: CalIrrigationApplicationFluxes
+
+CONTAINS
+
+ SUBROUTINE CalIrrigationNeeded(i,idate,nl_soil,nbedrock,z_soi,zi_soi,dz_soi,deltim,dlon,npcropmin)
+
+ ! DESCRIPTION:
+ ! This SUBROUTINE is used to calculate how much irrigation needed in each irrigated crop patch
+ integer , intent(in) :: i
+ integer , intent(in) :: idate(3)
+ integer , intent(in) :: nl_soil
+ integer , intent(in) :: nbedrock
+ real(r8), intent(in) :: z_soi(1:nl_soil)
+ real(r8), intent(in) :: zi_soi(1:nl_soil)
+ real(r8), intent(in) :: dz_soi(1:nl_soil)
+ real(r8), intent(in) :: deltim
+ real(r8), intent(in) :: dlon
+ integer , intent(in) :: npcropmin
+
+ ! local
+ integer :: ps, pe, m
+ integer :: irrig_nsteps_per_day
+ logical :: check_for_irrig
+ ps = patch_pft_s(i)
+ pe = patch_pft_e(i)
+
+ ! initialize irrigation
+ deficit_irrig(i) = 0._r8
+ actual_irrig(i) = 0._r8
+ groundwater_demand(i) = 0._r8
+ groundwater_supply(i) = 0._r8
+ reservoirriver_demand(i) = 0._r8
+ reservoirriver_supply(i) = 0._r8
+ reservoir_supply(i) = 0._r8
+ river_supply(i) = 0._r8
+ runoff_supply(i) = 0._r8
+
+ ! zero irrigation at the begin of the new year
+ if (idate(2) == 1 .and. idate(3) == deltim)then
+ sum_irrig(i) = 0._r8
+ sum_deficit_irrig(i) = 0._r8
+ sum_irrig_count(i) = 0._r8
+ zwt_stand(i) = zwt(i) + 1._r8
+ zwt_stand(i) = max(0., zwt_stand(i))
+ zwt_stand(i) = min(80., zwt_stand(i))
+ end if
+
+ ! ! calculate last day potential evapotranspiration
+ ! CALL CalPotentialEvapotranspiration(i,idate,dlon,deltim)
+
+ ! calculate whether irrigation needed
+ CALL PointNeedsCheckForIrrig(i,ps,pe,idate,deltim,dlon,npcropmin,check_for_irrig)
+
+ ! calculate irrigation needed
+ IF (check_for_irrig) THEN
+ CALL CalIrrigationPotentialNeeded(i,ps,pe,nl_soil,nbedrock,z_soi,dz_soi)
+ call CalIrrigationLimitedSupply(i,nl_soil,deltim,dz_soi,zi_soi)
+ ENDIF
+
+ ! calculate irrigation rate kg/m2->mm/s
+ IF ((check_for_irrig) .and. (deficit_irrig(i) > 0)) THEN
+ sum_deficit_irrig(i) = sum_deficit_irrig(i) + deficit_irrig(i)
+ ENDIF
+ IF ((check_for_irrig) .and. (actual_irrig(i) > 0)) THEN
+ irrig_nsteps_per_day = nint(irrig_time_per_day/deltim)
+ irrig_rate(i) = actual_irrig(i)/deltim/irrig_nsteps_per_day
+ n_irrig_steps_left(i) = irrig_nsteps_per_day
+ sum_irrig(i) = sum_irrig(i) + actual_irrig(i)
+ sum_irrig_count(i) = sum_irrig_count(i) + 1._r8
+ ENDIF
+ END SUBROUTINE CalIrrigationNeeded
+
+ SUBROUTINE CalIrrigationPotentialNeeded(i,ps,pe,nl_soil,nbedrock,z_soi,dz_soi)
+
+ ! DESCRIPTION:
+ ! This SUBROUTINE is used to calculate how much irrigation needed in each irrigated crop patch without water supply restriction
+ integer , intent(in) :: i
+ integer , intent(in) :: ps, pe
+ integer , intent(in) :: nbedrock
+ integer , intent(in) :: nl_soil
+ real(r8), intent(in) :: z_soi(1:nl_soil)
+ real(r8), intent(in) :: dz_soi(1:nl_soil)
+
+ ! local variables
+ integer :: j
+ integer :: m
+ logical :: reached_max_depth
+ real(r8) :: h2osoi_liq_tot
+ real(r8) :: h2osoi_liq_target_tot
+ real(r8) :: h2osoi_liq_wilting_point_tot
+ real(r8) :: h2osoi_liq_field_capacity_tot
+ real(r8) :: h2osoi_liq_saturation_capacity_tot
+ real(r8) :: h2osoi_liq_wilting_point(1:nl_soil)
+ real(r8) :: h2osoi_liq_field_capacity(1:nl_soil)
+ real(r8) :: h2osoi_liq_saturation_capacity(1:nl_soil)
+ real(r8) :: h2osoi_liq_at_threshold
+
+ real(r8) :: smpswc = -1.5e5
+ real(r8) :: smpsfc = -3.3e3
+
+ ! initialize local variables
+ reached_max_depth = .false.
+ h2osoi_liq_tot = 0._r8
+ h2osoi_liq_target_tot = 0._r8
+ h2osoi_liq_wilting_point_tot = 0._r8
+ h2osoi_liq_field_capacity_tot = 0._r8
+ h2osoi_liq_saturation_capacity_tot = 0._r8
+
+ ! calculate wilting point and field capacity
+ DO j = 1, nl_soil
+ IF (t_soisno(j,i) > tfrz .and. porsl(j,i) >= 1.e-6) THEN
+#ifdef Campbell_SOIL_MODEL
+ h2osoi_liq_wilting_point(j) = denh2o*dz_soi(j)*porsl(j,i)*((smpswc/psi0(j,i))**(-1/bsw(j,i)))
+ h2osoi_liq_field_capacity(j) = denh2o*dz_soi(j)*porsl(j,i)*((smpsfc/psi0(j,i))**(-1/bsw(j,i)))
+ h2osoi_liq_saturation_capacity(j) = denh2o*dz_soi(j)*porsl(j,i)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ h2osoi_liq_wilting_point(j) = soil_vliq_from_psi(smpswc, porsl(j,i), theta_r(j,i), psi0(j,i), 5, &
+ (/alpha_vgm(j,i), n_vgm(j,i), L_vgm(j,i), sc_vgm(j,i), fc_vgm(j,i)/))
+ h2osoi_liq_wilting_point(j) = denh2o*dz_soi(j)*h2osoi_liq_wilting_point(j)
+ h2osoi_liq_field_capacity(j) = soil_vliq_from_psi(smpsfc, porsl(j,i), theta_r(j,i), psi0(j,i), 5, &
+ (/alpha_vgm(j,i), n_vgm(j,i), L_vgm(j,i), sc_vgm(j,i), fc_vgm(j,i)/))
+ h2osoi_liq_field_capacity(j) = denh2o*dz_soi(j)*h2osoi_liq_field_capacity(j)
+ h2osoi_liq_saturation_capacity(j) = denh2o*dz_soi(j)*porsl(j,i)
+#endif
+ ENDIF
+ ENDDO
+
+ ! calculate total irrigation needed in all soil layers
+ DO m = ps, pe
+ DO j = 1, nl_soil
+ IF (.not. reached_max_depth) THEN
+ IF (z_soi(j) > irrig_max_depth) THEN
+ reached_max_depth = .true.
+ ELSEIF (j > nbedrock) THEN
+ reached_max_depth = .true.
+ ELSEIF (t_soisno(j,i) <= tfrz) THEN
+ reached_max_depth = .true.
+ ELSE
+ h2osoi_liq_tot = h2osoi_liq_tot + wliq_soisno(j,i)
+ h2osoi_liq_wilting_point_tot = h2osoi_liq_wilting_point_tot + h2osoi_liq_wilting_point(j)
+ h2osoi_liq_field_capacity_tot = h2osoi_liq_field_capacity_tot + h2osoi_liq_field_capacity(j)
+ h2osoi_liq_saturation_capacity_tot = h2osoi_liq_saturation_capacity_tot + h2osoi_liq_saturation_capacity(j)
+ ENDIF
+ ENDIF
+ ENDDO
+ IF (irrig_method_p(m) == irrig_method_drip .or. irrig_method_p(m) == irrig_method_sprinkler .or. &
+ irrig_method_p(m) == irrig_method_flood) THEN
+ ! flood irrigation threshold at field capacity, but irrigation amount at saturation capacity
+ h2osoi_liq_target_tot = h2osoi_liq_field_capacity_tot
+ ELSEIF (irrig_method_p(m) == irrig_method_paddy) THEN
+ h2osoi_liq_target_tot = h2osoi_liq_saturation_capacity_tot
+ ELSE
+ ! default irrigation is sprinkler irrigation
+ h2osoi_liq_target_tot = h2osoi_liq_field_capacity_tot
+ ENDIF
+ ENDDO
+
+ ! calculate irrigation threshold
+ deficit_irrig(i) = 0._r8
+ h2osoi_liq_at_threshold = h2osoi_liq_wilting_point_tot + irrig_threshold_fraction * (h2osoi_liq_target_tot - h2osoi_liq_wilting_point_tot)
+
+ ! calculate total irrigation
+ DO m = ps, pe
+ IF (h2osoi_liq_tot < h2osoi_liq_at_threshold) THEN
+ IF (irrig_method_p(m) == irrig_method_sprinkler) THEN
+ deficit_irrig(i) = irrig_supply_fraction * (h2osoi_liq_field_capacity_tot - h2osoi_liq_tot)
+ ! deficit_irrig(i) = irrig_supply_fraction * (h2osoi_liq_field_capacity_tot - h2osoi_liq_tot + potential_evapotranspiration(i))
+ ELSEIF (irrig_method_p(m) == irrig_method_flood) THEN
+ deficit_irrig(i) = irrig_supply_fraction * (h2osoi_liq_saturation_capacity_tot - h2osoi_liq_tot)
+ ELSE
+ deficit_irrig(i) = irrig_supply_fraction * (h2osoi_liq_field_capacity_tot - h2osoi_liq_tot)
+ ENDIF
+ ELSE
+ deficit_irrig(i) = 0
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE CalIrrigationPotentialNeeded
+
+ SUBROUTINE CalIrrigationApplicationFluxes(i,deltim,qflx_irrig_drip,qflx_irrig_sprinkler,qflx_irrig_flood,qflx_irrig_paddy)
+ ! DESCRIPTION:
+ ! This SUBROUTINE is used to calculate irrigation application fluxes for each irrigated crop patch
+ integer , intent(in) :: i
+ real(r8), intent(in) :: deltim
+ real(r8), intent(out):: qflx_irrig_drip,qflx_irrig_sprinkler,qflx_irrig_flood,qflx_irrig_paddy
+
+ integer :: ps, pe, m
+
+ ps = patch_pft_s(i)
+ pe = patch_pft_e(i)
+
+ qflx_irrig_drip = 0._r8
+ qflx_irrig_sprinkler = 0._r8
+ qflx_irrig_flood = 0._r8
+ qflx_irrig_paddy = 0._r8
+
+ ! add irrigation fluxes to precipitation or land surface
+ DO m = ps, pe
+ IF (n_irrig_steps_left(i) > 0) THEN
+ n_irrig_steps_left(i) = n_irrig_steps_left(i) -1
+ IF (waterstorage(i) - irrig_rate(i)*deltim < 0._r8) irrig_rate(i) = waterstorage(i)/deltim
+ waterstorage(i) = max(waterstorage(i) - irrig_rate(i)*deltim, 0._r8)
+ IF (irrig_method_p(m) == irrig_method_drip) THEN
+ qflx_irrig_drip = irrig_rate(i)
+ ELSEIF (irrig_method_p(m) == irrig_method_sprinkler) THEN
+ qflx_irrig_sprinkler = irrig_rate(i)
+ ELSEIF (irrig_method_p(m) == irrig_method_flood) THEN
+ qflx_irrig_flood = irrig_rate(i)
+ ELSEIF (irrig_method_p(m) == irrig_method_paddy) THEN
+ qflx_irrig_paddy = irrig_rate(i)
+ ELSE
+ qflx_irrig_sprinkler = irrig_rate(i)
+ ENDIF
+ ELSE
+ irrig_rate(i) = 0._r8
+ ENDIF
+ ENDDO
+ END SUBROUTINE CalIrrigationApplicationFluxes
+
+ SUBROUTINE PointNeedsCheckForIrrig(i,ps,pe,idate,deltim,dlon,npcropmin,check_for_irrig)
+ ! DESCRIPTION:
+ ! This SUBROUTINE is used to calculate whether irrigation needed in each patch
+ integer , intent(in) :: i
+ integer , intent(in) :: ps, pe
+ integer , intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ real(r8), intent(in) :: dlon
+ integer , intent(in) :: npcropmin
+ logical , intent(out):: check_for_irrig
+
+ ! local variable
+ integer :: m, ivt
+ real(r8):: ldate(3)
+ real(r8):: seconds_since_irrig_start_time
+
+ ! adjust flood irrigation in rice to paddy irrigaiton
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF ((ivt == 62) .and. (irrig_method_p(m) == irrig_method_flood)) THEN
+ irrig_method_p(m) = irrig_method_paddy
+ ENDIF
+ ENDDO
+
+ DO m = ps, pe
+ ivt = pftclass(m)
+ IF ((ivt >= npcropmin) .and. (irrig_crop(ivt)) .and. &
+ (cphase_p(m) >= irrig_min_cphase) .and. (cphase_p(m)= 0._r8) .and. (seconds_since_irrig_start_time < deltim)) THEN
+ check_for_irrig = .true.
+ ELSE
+ check_for_irrig = .false.
+ ENDIF
+ ELSE
+ check_for_irrig = .false.
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE PointNeedsCheckForIrrig
+
+ ! SUBROUTINE CalPotentialEvapotranspiration(i,idate,dlon,deltim)
+ ! ! DESCRIPTION:
+ ! ! This SUBROUTINE is used to calculate daily potential evapotranspiration
+ ! integer , intent(in) :: i
+ ! integer , intent(in) :: idate(3)
+ ! real(r8), intent(in) :: dlon
+ ! real(r8), intent(in) :: deltim
+ ! ! local variable
+ ! real(r8):: ldate(3)
+ ! real(r8):: seconds_since_irrig_start_time
+ ! real(r8) :: es,esdT,qs,qsdT ! saturation vapour pressure
+ ! real(r8) :: evsat ! vapour pressure
+ ! real(r8) :: ur ! wind speed
+ ! real(r8) :: delta ! slope of saturation vapour pressure curve
+ ! real(r8) :: gamma ! Psychrometric constant
+
+ ! IF (DEF_simulation_time%greenwich) THEN
+ ! CALL gmt2local(idate, dlon, ldate)
+ ! seconds_since_irrig_start_time = ldate(3) - irrig_start_time + deltim
+ ! ELSE
+ ! seconds_since_irrig_start_time = idate(3) - irrig_start_time + deltim
+ ! ENDIF
+
+ ! IF (((seconds_since_irrig_start_time-deltim) >= 0) .and. ((seconds_since_irrig_start_time-deltim) < deltim)) THEN
+ ! tairday(i) = (forc_t(i)-tfrz)*deltim/86400
+ ! usday(i) = forc_us(i)*deltim/86400
+ ! vsday(i) = forc_vs(i)*deltim/86400
+ ! pairday(i) = forc_psrf(i)*deltim/86400/1000
+ ! rnetday(i) = (sabg(i)+sabvsun(i)+sabvsha(i)-olrg(i)+forc_frl(i))*deltim/1000000
+ ! fgrndday(i) = fgrnd(i)*deltim/1000000
+ ! ELSE
+ ! tairday(i) = tairday(i) + (forc_t(i)-tfrz)*deltim/86400
+ ! usday(i) = usday(i) + forc_us(i)*deltim/86400
+ ! vsday(i) = vsday(i) + forc_vs(i)*deltim/86400
+ ! pairday(i) = pairday(i) + forc_psrf(i)*deltim/86400/1000
+ ! rnetday(i) = rnetday(i) + (sabg(i)+sabvsun(i)+sabvsha(i)-olrg(i)+forc_frl(i))*deltim/1000000
+ ! fgrndday(i) = fgrndday(i) + fgrnd(i)*deltim/1000000
+ ! ENDIF
+
+ ! IF ((seconds_since_irrig_start_time >= 0) .and. (seconds_since_irrig_start_time < deltim)) THEN
+ ! CALL qsadv(tairday(i),pairday(i),es,esdT,qs,qsdT)
+ ! IF (tairday(i) > 0)THEN
+ ! evsat = 0.611*EXP(17.27*tairday(i)/(tairday(i)+237.3))
+ ! ELSE
+ ! evsat = 0.611*EXP(21.87*tairday(i)/(tairday(i)+265.5))
+ ! ENDIF
+ ! ur = max(0.1,sqrt(usday(i)*usday(i)+vsday(i)*vsday(i)))
+ ! delta = 4098*evsat/((tairday(i)+237.3)*(tairday(i)+237.3))
+ ! gamma = 0.665*0.001*pairday(i)
+ ! potential_evapotranspiration(i) = (0.408*delta*(rnetday(i)-fgrndday(i))+gamma*(900/(tairday(i)+273))*ur* &
+ ! (evsat-es))/(delta+(gamma*(1+0.34*ur)))
+ ! ENDIF
+ ! END SUBROUTINE CalPotentialEvapotranspiration
+
+ SUBROUTINE CalIrrigationLimitedSupply(i,nl_soil,deltim,dz_soi,zi_soi)
+ ! DESCRIPTION:
+ ! This subroutine is used to calculate how much irrigation supplied in each irrigated crop patch with water supply restriction
+ integer, intent(in) :: i
+ integer, intent(in) :: nl_soil
+ real(r8), intent(in) :: deltim
+ real(r8), intent(in) :: dz_soi(1:nl_soil)
+ real(r8), intent(in) :: zi_soi(1:nl_soil)
+
+ real(r8) :: waterstorage_supply
+
+ IF (deficit_irrig(i) > 0._r8) THEN
+ IF (DEF_IRRIGATION_ALLOCATION == 1) THEN
+ actual_irrig(i) = deficit_irrig(i)
+ waterstorage(i) = waterstorage(i) + actual_irrig(i)
+ ELSEIF (DEF_IRRIGATION_ALLOCATION == 2) THEN
+ waterstorage_supply = min(waterstorage(i), deficit_irrig(i))
+ waterstorage_supply = max(waterstorage_supply, 0._r8)
+ actual_irrig(i) = actual_irrig(i) + waterstorage_supply
+ ! irrigation withdraw from ground water (unconfined and confined)
+ IF (deficit_irrig(i) > actual_irrig(i)) THEN
+ groundwater_demand(i) = max(deficit_irrig(i) - actual_irrig(i), 0._r8)
+ CALL CalGroudwaterWithdrawal(i,nl_soil,deltim,dz_soi,zi_soi)
+ actual_irrig(i) = actual_irrig(i) + groundwater_supply(i)
+ waterstorage(i) = waterstorage(i) + groundwater_supply(i)
+ ENDIF
+ ELSEIF (DEF_IRRIGATION_ALLOCATION == 3) THEN
+ waterstorage_supply = min(waterstorage(i), deficit_irrig(i))
+ waterstorage_supply = max(waterstorage_supply, 0._r8)
+ actual_irrig(i) = actual_irrig(i) + waterstorage_supply
+ ! irrigation withdraw from ground water (unconfined and confined)
+ IF (deficit_irrig(i) > actual_irrig(i)) THEN
+ groundwater_demand(i) = max((deficit_irrig(i) - actual_irrig(i))*irrig_gw_alloc(i), 0._r8)
+ CALL CalGroudwaterWithdrawal(i,nl_soil,deltim,dz_soi,zi_soi)
+ actual_irrig(i) = actual_irrig(i) + groundwater_supply(i)
+ waterstorage(i) = waterstorage(i) + groundwater_supply(i)
+ ENDIF
+ ENDIF
+ ENDIF
+ END SUBROUTINE CalIrrigationLimitedSupply
+
+
+ SUBROUTINE CalGroudwaterWithdrawal(i,nl_soil,deltim,dz_soi,zi_soi)
+ ! DESCRIPTION:
+ ! This subroutine is used to calculate irrigation withdrawals for groudwater
+ integer, intent(in) :: i
+ integer, intent(in) :: nl_soil
+ real(r8), intent(in) :: deltim
+ real(r8), intent(in) :: dz_soi(1:nl_soil)
+ real(r8), intent(in) :: zi_soi(1:nl_soil)
+
+ IF (.not. DEF_USE_VariablySaturatedFlow) THEN
+ CALL CalWithdrawalWATER(i,nl_soil,deltim,dz_soi,zi_soi)
+ ELSE
+ groundwater_supply(i) = groundwater_demand(i)
+ ENDIF
+ END SUBROUTINE CalGroudwaterWithdrawal
+
+
+
+ subroutine CalWithdrawalWATER(i,nl_soil,deltim,dz_soi,zi_soi)
+ ! DESCRIPTION:
+ ! This subroutine is used to calculate how much irrigation supplied in each irrigated crop patch with groundwater supply restriction
+ IMPLICIT NONE
+ integer, INTENT(in) :: i
+ integer, INTENT(in) :: nl_soil
+ real(r8), INTENT(in) :: deltim ! land model time step (sec)
+ real(r8), INTENT(in) :: dz_soi (1:nl_soil) ! layer depth (m)
+ real(r8), INTENT(in) :: zi_soi (1:nl_soil) ! interface level below a "z" level (m)
+
+ ! LOCAL ARGUMENTS
+ integer :: j ! indices
+ integer :: jwt ! index of the soil layer right above the water table (-)
+ real(r8) :: dzmm(1:nl_soil) ! layer thickness (mm)
+ real(r8) :: vol_ice(1:nl_soil)! partitial volume of ice lens in layer
+ real(r8) :: eff_porosity(1:nl_soil)! effective porosity = porosity - vol_ice
+ real(r8) :: xs ! water needed to bring soil moisture to watmin (mm)
+ real(r8) :: xsi ! excess soil water above saturation at layer i (mm)
+ real(r8) :: xs1 ! excess soil water above saturation at layer 1 (mm)
+ real(r8) :: pump_total
+ real(r8) :: pump_layer
+ real(r8) :: max_groundwater_supply
+ real(r8) :: s_y
+ real(r8) :: rous ! specific yield [-]
+ ! -------------------------------------------------------------------------
+
+ do j = 1, nl_soil
+ vol_ice(j) = min(porsl(j,i), wice_soisno(j,i)/(dz_soi(j)*denice))
+ eff_porosity(j) = max(0.01, porsl(j,i)-vol_ice(j))
+ end do
+
+ ! Convert layer thicknesses from m to mm
+ DO j = 1,nl_soil
+ dzmm(j) = dz_soi(j)*1000.
+ ENDDO
+
+ ! The layer index of the first unsaturated layer,
+ ! i.e., the layer right above the water table
+ jwt = nl_soil
+ ! allow jwt to equal zero when zwt is in top layer
+ DO j = 1, nl_soil
+ IF(zwt(i) <= zi_soi(j)) THEN
+ jwt = j-1
+ exit
+ ENDIF
+ ENDDO
+
+ rous = porsl(nl_soil,i)*(1.-(1.-1.e3*zwt(i)/psi0(nl_soil,i))**(-1./bsw(nl_soil,i)))
+ rous = max(rous,0.02)
+
+ !-- Water table is below the soil column ----------------------------------------
+ IF (jwt == nl_soil) THEN
+ max_groundwater_supply = max(1.e3*(zwt_stand(i)-zwt(i))*rous, 0._r8)
+ groundwater_supply(i) = min(groundwater_demand(i), max_groundwater_supply)
+ wa(i) = wa(i) - groundwater_supply(i)
+ zwt(i) = max(0., zwt(i) + groundwater_supply(i)/1000./rous)
+ wliq_soisno(nl_soil,i) = wliq_soisno(nl_soil,i) + max(0.,(wa(i)-5000.))
+ wa(i) = min(wa(i), 5000.)
+ ELSE
+ !-- Water table within soil layers 1-9 ------------------------------------------
+ !============================== RSUB_TOP =========================================
+ !-- Now remove water via pump
+ pump_total = - groundwater_demand(i)
+ DO j = jwt+1, nl_soil
+ ! use analytical expression for specific yield
+ s_y = porsl(j,i) * ( 1. - (1.-1.e3*zwt(i)/psi0(j,i))**(-1./bsw(j,i)))
+ s_y = max(s_y,0.02)
+
+ pump_layer = max(pump_total, -(s_y*(zi_soi(j)-zwt(i))*1.e3))
+ pump_layer = min(pump_layer, 0.)
+ wliq_soisno(j,i) = wliq_soisno(j,i) + pump_layer
+
+ pump_total = pump_total - pump_layer
+ groundwater_supply(i) = groundwater_supply(i) - pump_layer
+
+ IF (pump_total >= 0.) THEN
+ zwt(i) = max(0.,zwt(i) - pump_layer/s_y/1000.)
+ exit
+ ELSE
+ zwt(i) = zi_soi(j)
+ ENDIF
+ ENDDO
+ !-- Remove residual drainage ------------------------------------------------
+ max_groundwater_supply = max(1.e3*(zwt_stand(i)-zwt(i))*rous, 0._r8)
+ pump_total = min(-pump_total, max_groundwater_supply)
+ pump_total = max(pump_total, 0._r8)
+ groundwater_supply(i) = groundwater_supply(i) + pump_total
+ zwt(i) = max(0., zwt(i) + pump_total/1000./rous)
+ wa(i) = wa(i) - pump_total
+
+ !-- Recompute jwt ---------------------------------------------------------------
+ ! allow jwt to equal zero when zwt is in top layer
+ jwt = nl_soil
+ DO j = 1, nl_soil
+ IF (zwt(i) <= zi_soi(j)) THEN
+ jwt = j-1
+ exit
+ ENDIF
+ ENDDO
+ ENDIF ! end of jwt if construct
+
+ zwt(i) = max(0.0,zwt(i))
+ zwt(i) = min(80.,zwt(i))
+
+
+ ! Correction [2]
+ ! NON-physically based corection on wliq_soisno
+ ! Limit wliq_soisno to be greater than or equal to watmin.
+ ! Get water needed to bring wliq_soisno equal watmin from lower layer.
+ ! If insufficient water in soil layers, get from aquifer water
+ xs = 0.
+ DO j = 1, nl_soil
+ IF (wliq_soisno(j,i) < 0.) THEN
+ xs = xs + wliq_soisno(j,i)
+ wliq_soisno(j,i) = 0.
+ ENDIF
+ ENDDO
+ wa(i) = wa(i) + xs
+ END SUBROUTINE CalWithdrawalWATER
+
+END MODULE MOD_Irrigation
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_LAIEmpirical.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LAIEmpirical.F90
new file mode 100644
index 0000000000..93ac924bf9
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LAIEmpirical.F90
@@ -0,0 +1,139 @@
+#include
+
+MODULE MOD_LAIEmpirical
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: LAI_empirical
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE LAI_empirical(ivt,nl_soil,rootfr,t,lai,sai,fveg,green)
+
+!-----------------------------------------------------------------------
+! provides leaf and stem area parameters
+! Original author: Yongjiu Dai, 08/31/2002
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ivt !land cover type
+ integer, intent(in) :: nl_soil !number of soil layers
+
+ real(r8), intent(in) :: rootfr(1:nl_soil) !root fraction
+ real(r8), intent(in) :: t(1:nl_soil) !soil temperature
+ real(r8), intent(out) :: lai !leaf area index
+ real(r8), intent(out) :: sai !Stem area index
+ real(r8), intent(out) :: fveg !fractional cover of vegetation
+ real(r8), intent(out) :: green !greenness
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) f !
+ real(r8) roota !accumulates root fraction
+ integer jrt !number of soil layers with 90% root fraction
+ integer j !number of soil layers
+
+!-----------------------------------------------------------------------
+#if (defined LULC_USGS)
+! Maximum fractional cover of vegetation [-]
+ real(r8), dimension(24), parameter :: &
+ vegc=(/1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, &
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, &
+ 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0 /)
+! Maximum leaf area index, the numbers are based on the data of
+! "worldwide historical estimates of leaf area index, 1932-2000" :
+! http://www.daac.ornl.gov/global_vegetation/HistoricalLai/data"
+ real(r8), dimension(24), parameter :: &
+ xla=(/1.50, 3.29, 4.18, 3.50, 2.50, 3.60, 2.02, 1.53, &
+ 2.00, 0.85, 4.43, 4.42, 4.56, 3.95, 4.50, 0.00, &
+ 4.00, 3.63, 0.00, 0.64, 1.60, 1.00, 0.00, 0.00 /)
+! Minimum leaf area index
+ real(r8), dimension(24), parameter :: &
+ xla0=(/1.00, 0.50, 0.50, 0.50, 1.00, 0.50, 0.50, 0.50, &
+ 0.50, 0.30, 0.50, 0.50, 4.00, 4.00, 4.00, 0.00, &
+ 3.00, 3.00, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 /)
+! Stem area index [-]
+ real(r8), dimension(24), parameter :: &
+ sai0=(/0.20, 0.20, 0.30, 0.30, 0.50, 0.50, 1.00, 0.50, &
+ 1.00, 0.50, 2.00, 2.00, 2.00, 2.00, 2.00, 0.00, &
+ 2.00, 2.00, 0.00, 0.10, 0.10, 0.10, 0.00, 0.00 /)
+#elif (defined SIB2_CLASSIFICATION)
+ real(r8), dimension(11), parameter :: &
+ vegc=(/1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0/)
+ real(r8), dimension(11), parameter :: &
+ xla =(/4.8, 3.9, 5.6, 5.5, 4.6, 1.7, 1.3, 2.1, 3.6, 0.0, 0.0/)
+ real(r8), dimension(11), parameter :: &
+ xla0=(/4.0, 0.6, 0.5, 5.0, 0.5, 0.3, 0.6, 0.4, 0.2, 0.0, 0.0/)
+ real(r8), dimension(11), parameter :: &
+ sai0=(/1.6, 1.8, 1.6, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, 0.0/)
+#elif (defined BATS_CLASSIFICATION)
+ real(r8), dimension(19), parameter :: &
+ vegc=(/1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0,&
+ 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0/)
+ real(r8), dimension(19), parameter :: &
+ xla =(/5.1, 1.6, 4.8, 4.8, 4.8, 5.4, 4.8, 0.0, 3.6, 4.8,&
+ 0.6, 0.0, 4.8, 0.0, 0.0, 4.8, 4.8, 4.8, 4.8/)
+ real(r8), dimension(19), parameter :: &
+ xla0=(/0.425, 0.4, 4.0, 0.8, 0.8, 4.5, 0.4, 0.0, 0.3, 0.4,&
+ 0.05, 0.0, 0.4, 0.0, 0.0, 4.0, 0.8, 2.4, 2.4/)
+ real(r8), dimension(19), parameter :: &
+ sai0=(/0.425, 3.2, 1.6, 1.6, 1.6, 1.8, 1.6, 0.0, 0.3, 0.4,&
+ 0.2, 0.0, 1.6, 0.0, 0.0, 1.6, 1.6, 1.6, 1.6/)
+#elif (defined OGE_CLASSIFICATION)
+
+#else
+!#elif(defined LULC_IGBP)
+ real(r8), dimension(17), parameter :: &
+ vegc=(/1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0,&
+ 1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0/)
+ real(r8), dimension(17), parameter :: &
+ xla =(/4.8, 5.4, 4.8, 4.8, 4.7, 4.7, 1.6, 4.7, 4.8, 1.7,&
+ 4.6, 4.9, 3.8, 4.8, 0.0, 0.06, 0.0/)
+ real(r8), dimension(17), parameter :: &
+ xla0=(/4.0, 4.5, 0.8, 0.8, 2.2, 1.6, 0.15, 1.8, 0.9, 0.4,&
+ 0.4, 0.4, 0.9, 2.0, 0.0, 0.006, 0.0/)
+ real(r8), dimension(17), parameter :: &
+ sai0=(/1.6, 1.8, 1.6, 1.6, 1.5, 1.5, 0.45, 1.4, 1.6, 3.1,&
+ 1.6, 0.4, 1.1, 1.3, 0.0, 0.14, 0.0/)
+#endif
+
+!-----------------------------------------------------------------------
+ roota = 0.
+ jrt = 1
+ DO j = 1, nl_soil
+ roota = roota + rootfr(j)
+ IF(roota>0.9)THEN
+ jrt = j
+ EXIT
+ ENDIF
+ ENDDO
+
+! Adjust leaf area index for seasonal variation
+
+ f = max(0.0,1.-0.0016*max(298.-t(jrt),0.0)**2)
+ lai = xla(ivt) + (xla0(ivt)-xla(ivt))*(1.-f)
+
+! Sum leaf area index and stem area index
+ sai = sai0(ivt)
+
+! Fractional vegetation cover
+ fveg = vegc(ivt)
+
+ green = 0.0
+ IF(fveg > 0.) green = 1.0
+
+ END SUBROUTINE LAI_empirical
+
+END MODULE MOD_LAIEmpirical
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_LAIReadin.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LAIReadin.F90
new file mode 100644
index 0000000000..367999943b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LAIReadin.F90
@@ -0,0 +1,219 @@
+#include
+
+MODULE MOD_LAIReadin
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: LAI_readin
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE LAI_readin (year, time, dir_landdata)
+!=======================================================================
+! Read in the LAI, the LAI dataset was created by Yuan et al. (2011)
+! http://globalchange.bnu.edu.cn
+!
+! Created by Yongjiu Dai, March, 2014
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_UserDefFun
+ USE MOD_NetCDFVector
+ USE MOD_LandPatch
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_TimeVariables
+
+ USE MOD_Vars_Global
+ USE MOD_Const_LC
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT
+ USE MOD_Vars_PFTimeVariables
+#endif
+#ifdef SinglePoint
+ USE MOD_SingleSrfdata
+#endif
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: year, time
+ character(len=256), intent(in) :: dir_landdata
+
+ ! Local variables
+ integer :: iyear, itime
+ character(len=256) :: cyear, ctime
+ character(len=256) :: landdir, lndname
+ integer :: m, npatch, pc
+
+#ifdef LULC_USGS
+ real(r8), dimension(24), parameter :: & ! Maximum fractional cover of vegetation [-]
+ vegc=(/1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, &
+ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, &
+ 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0 /)
+#endif
+
+ ! READ in Leaf area index and stem area index
+
+ landdir = trim(dir_landdata) // '/LAI'
+
+#ifdef SinglePoint
+#ifndef URBAN_MODEL
+ IF (USE_SITE_LAI) THEN
+ iyear = minloc(abs(SITE_LAI_year-year), dim=1)
+ ELSE
+ iyear = findloc_ud(SITE_LAI_year == min(DEF_LAI_END_YEAR, max(DEF_LAI_START_YEAR,year)))
+ ENDIF
+
+ IF (.not. DEF_LAI_MONTHLY) THEN
+ itime = (time-1)/8 + 1
+ ENDIF
+#endif
+#endif
+
+#if (defined LULC_USGS || defined LULC_IGBP)
+
+#ifdef SinglePoint
+#ifndef URBAN_MODEL
+ IF (DEF_LAI_MONTHLY) THEN
+ tlai(:) = SITE_LAI_monthly(time,iyear)
+ tsai(:) = SITE_SAI_monthly(time,iyear)
+ ELSE
+ tlai(:) = SITE_LAI_8day(itime,iyear)
+ ENDIF
+#endif
+#else
+ IF (DEF_LAI_MONTHLY) THEN
+ write(cyear,'(i4.4)') min(DEF_LAI_END_YEAR, max(DEF_LAI_START_YEAR,year) )
+ write(ctime,'(i2.2)') time
+
+ lndname = trim(landdir)//'/'//trim(cyear)//'/LAI_patches'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'LAI_patches', landpatch, tlai)
+
+ lndname = trim(landdir)//'/'//trim(cyear)//'/SAI_patches'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'SAI_patches', landpatch, tsai)
+ ELSE
+ write(cyear,'(i4.4)') min(DEF_LAI_END_YEAR, max(DEF_LAI_START_YEAR,year) )
+ write(ctime,'(i3.3)') time
+ lndname = trim(landdir)//'/'//trim(cyear)//'/LAI_patches'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'LAI_patches', landpatch, tlai)
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ DO npatch = 1, numpatch
+ m = patchclass(npatch)
+#ifdef URBAN_MODEL
+ IF(m == URBAN) CYCLE
+#endif
+ IF(m == 0 .or. m == WATERBODY)THEN
+ fveg(npatch) = 0.
+ tlai(npatch) = 0.
+ tsai(npatch) = 0.
+ green(npatch) = 0.
+ ELSE
+ fveg(npatch) = fveg0(m) !fraction of veg. cover
+ IF (fveg0(m) > 0) THEN
+ tlai(npatch) = tlai(npatch)/fveg0(m) !leaf area index
+ IF (DEF_LAI_MONTHLY) THEN
+ tsai(npatch) = tsai(npatch)/fveg0(m) !stem are index
+ ELSE
+ tsai(npatch) = sai0(m) !stem are index
+ ENDIF
+ green(npatch) = 1. !fraction of green leaf
+ ELSE
+ tlai(npatch) = 0.
+ tsai(npatch) = 0.
+ green(npatch) = 0.
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+#ifdef SinglePoint
+
+#ifndef URBAN_MODEL
+ IF (.not. DEF_USE_LAIFEEDBACK)THEN
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ tlai_p(:) = pack(SITE_LAI_pfts_monthly(:,time,iyear), SITE_pctpfts > 0.)
+ tsai_p(:) = pack(SITE_SAI_pfts_monthly(:,time,iyear), SITE_pctpfts > 0.)
+ tlai(:) = sum (SITE_LAI_pfts_monthly(:,time,iyear) * SITE_pctpfts)
+ tsai(:) = sum (SITE_SAI_pfts_monthly(:,time,iyear) * SITE_pctpfts)
+ ELSE
+ tlai(:) = SITE_LAI_monthly(time,iyear)
+ tsai(:) = SITE_SAI_monthly(time,iyear)
+ ENDIF
+ ELSE
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ tsai_p(:) = pack(SITE_SAI_pfts_monthly(:,time,iyear), SITE_pctpfts > 0.)
+ tsai(:) = sum (SITE_SAI_pfts_monthly(:,time,iyear) * SITE_pctpfts)
+ ELSE
+ tsai(:) = SITE_SAI_monthly(time,iyear)
+ ENDIF
+ ENDIF
+#endif
+#else
+
+ write(cyear,'(i4.4)') min(DEF_LAI_END_YEAR, max(DEF_LAI_START_YEAR,year) )
+ write(ctime,'(i2.2)') time
+ IF (.not. DEF_USE_LAIFEEDBACK)THEN
+ lndname = trim(landdir)//'/'//trim(cyear)//'/LAI_patches'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'LAI_patches', landpatch, tlai )
+ ENDIF
+ lndname = trim(landdir)//'/'//trim(cyear)//'/SAI_patches'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'SAI_patches', landpatch, tsai )
+ IF (.not. DEF_USE_LAIFEEDBACK)THEN
+ lndname = trim(landdir)//'/'//trim(cyear)//'/LAI_pfts'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'LAI_pfts', landpft, tlai_p )
+ ENDIF
+ lndname = trim(landdir)//'/'//trim(cyear)//'/SAI_pfts'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'SAI_pfts', landpft, tsai_p )
+
+#endif
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO npatch = 1, numpatch
+ m = patchclass(npatch)
+
+#ifdef URBAN_MODEL
+ IF (m == URBAN) CYCLE
+#endif
+ !TODO@yuan: may need to revise patch LAI/SAI
+ green(npatch) = 1.
+ fveg (npatch) = fveg0(m)
+
+ IF (m == WATERBODY) THEN
+ fveg(npatch) = 0.
+ tlai(npatch) = 0.
+ tsai(npatch) = 0.
+ green(npatch) = 0.
+ ENDIF
+
+ ENDDO
+ ENDIF
+ ENDIF
+
+#endif
+
+ END SUBROUTINE LAI_readin
+
+END MODULE MOD_LAIReadin
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Lake.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Lake.F90
new file mode 100644
index 0000000000..98305452ad
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Lake.F90
@@ -0,0 +1,2186 @@
+#include
+
+MODULE MOD_Lake
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Simulating energy balance processes of land water body
+!
+! !REFERENCES:
+! Dai et al, 2018, The lake scheme of the common land model and its performance evaluation.
+! Chinese Science Bulletin, 63(28-29), 3002-3021, https://doi.org/10.1360/N972018-00609
+!
+! Original author: Yongjiu Dai 04/2014/
+!
+! !REVISIONS:
+! Nan Wei, 01/2018: interaction btw prec and lake surface including phase change of prec and water body
+! Nan Wei, 06/2018: update heat conductivity of water body and soil below and snow hydrology
+! Hua Yuan, 01/2023: added snow layer absorption in melting calculation
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: newsnow_lake
+ PUBLIC :: laketem
+ PUBLIC :: snowwater_lake
+
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: roughness_lake
+ PRIVATE :: hConductivity_lake
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+
+ SUBROUTINE newsnow_lake ( USE_Dynamic_Lake, &
+ ! "in" arguments
+ ! ---------------
+ maxsnl , nl_lake , deltim , dz_lake ,&
+ pg_rain , pg_snow , t_precip , bifall ,&
+
+ ! "inout" arguments
+ ! ------------------
+ t_lake , zi_soisno , z_soisno ,&
+ dz_soisno , t_soisno , wliq_soisno , wice_soisno ,&
+ fiold , snl , sag , scv ,&
+ snowdp , lake_icefrac )
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Add new snow nodes and interaction btw prec and lake surface including phase
+! change of prec and water body
+!
+! Original author: Yongjiu Dai, 04/2014
+!
+! !REVISIONS:
+! Nan Wei, 01/2018: update interaction btw prec and lake surface
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz, denh2o, cpliq, cpice, hfus
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ logical, intent(in) :: USE_Dynamic_Lake
+
+ integer, intent(in) :: maxsnl ! maximum number of snow layers
+ integer, intent(in) :: nl_lake ! number of soil layers
+ real(r8), intent(in) :: deltim ! seconds in a time step [second]
+ real(r8), intent(inout) :: pg_rain ! liquid water onto ground [kg/(m2 s)]
+ real(r8), intent(inout) :: pg_snow ! ice onto ground [kg/(m2 s)]
+ real(r8), intent(in) :: t_precip ! snowfall/rainfall temperature [kelvin]
+ real(r8), intent(in) :: bifall ! bulk density of newly fallen dry snow [kg/m3]
+
+ real(r8), intent(inout) :: dz_lake(1:nl_lake) ! lake layer thickness (m)
+ real(r8), intent(inout) :: zi_soisno(maxsnl:0) ! interface level below a "z" level (m)
+ real(r8), intent(inout) :: z_soisno(maxsnl+1:0) ! snow layer depth (m)
+ real(r8), intent(inout) :: dz_soisno(maxsnl+1:0) ! snow layer thickness (m)
+ real(r8), intent(inout) :: t_soisno(maxsnl+1:0) ! snow layer temperature [K]
+ real(r8), intent(inout) :: wliq_soisno(maxsnl+1:0) ! snow layer liquid water (kg/m2)
+ real(r8), intent(inout) :: wice_soisno(maxsnl+1:0) ! snow layer ice lens (kg/m2)
+ real(r8), intent(inout) :: fiold(maxsnl+1:0) ! fraction of ice relative to the total water
+ integer, intent(inout) :: snl ! number of snow layers
+ real(r8), intent(inout) :: sag ! non dimensional snow age [-]
+ real(r8), intent(inout) :: scv ! snow mass (kg/m2)
+ real(r8), intent(inout) :: snowdp ! snow depth (m)
+ real(r8), intent(inout) :: lake_icefrac(1:nl_lake) ! mass fraction of lake layer that is frozen
+ real(r8), intent(inout) :: t_lake(1:nl_lake) ! lake layer temperature (m)
+
+!-------------------------- Local Variables ----------------------------
+
+ integer lb
+ integer newnode ! signification when new snow node is set, (1=yes, 0=non)
+ real(r8) dz_snowf ! layer thickness rate change due to precipitation [m/s]
+ real(r8) a, b, c, d, e, f, g, h
+ real(r8) wice_lake(1:nl_lake), wliq_lake(1:nl_lake), tw
+
+!-----------------------------------------------------------------------
+
+ newnode = 0
+ dz_snowf = pg_snow/bifall
+ snowdp = snowdp + dz_snowf*deltim
+ scv = scv + pg_snow*deltim ! snow water equivalent (mm)
+
+
+ zi_soisno(0) = 0.
+
+ IF (snl==0 .and. snowdp < 0.01) THEN ! no snow layer, energy exchange between prec and lake surface
+
+ a = cpliq*pg_rain*deltim*(t_precip-tfrz) !cool down rainfall to tfrz
+ b = pg_rain*deltim*hfus !all rainfall frozen
+ c = cpice*denh2o*dz_lake(1)*lake_icefrac(1)*(tfrz-t_lake(1)) !warm up lake surface ice to tfrz
+ d = denh2o*dz_lake(1)*lake_icefrac(1)*hfus !all lake surface ice melt
+ e = cpice*pg_snow*deltim*(tfrz-t_precip) !warm up snowfall to tfrz
+ f = pg_snow*deltim*hfus !all snowfall melt
+ g = cpliq*denh2o*dz_lake(1)*(1-lake_icefrac(1))*(t_lake(1)-tfrz) !cool down lake surface water to tfrz
+ h = denh2o*dz_lake(1)*(1-lake_icefrac(1))*hfus !all lake surface water frozen
+ sag = 0.0
+
+ IF (lake_icefrac(1) > 0.999) THEN
+ ! all rainfall frozen, release heat to warm up frozen lake surface
+ IF (a+b<=c) THEN
+ tw=min(tfrz,t_precip)
+ t_lake(1)=(a+b+cpice*(pg_rain+pg_snow)*deltim*tw+cpice*denh2o*dz_lake(1)*t_lake(1)*lake_icefrac(1))/&
+ (cpice*denh2o*dz_lake(1)*lake_icefrac(1)+cpice*(pg_rain+pg_snow)*deltim)
+ scv = scv+pg_rain*deltim
+ snowdp = snowdp + pg_rain*deltim/bifall
+ pg_snow = pg_snow+pg_rain
+ pg_rain = 0.0
+ ! prec tem at tfrz, partial rainfall frozen ->release heat -> warm up lake surface to tfrz (no latent heat)
+ ELSEIF (a<=c) THEN
+ t_lake(1)=tfrz
+ scv = scv + (c-a)/hfus
+ snowdp = snowdp + (c-a)/(hfus*bifall)
+ pg_snow = pg_snow + min(pg_rain,(c-a)/(hfus*deltim))
+ pg_rain = max(0.0,pg_rain - (c-a)/(hfus*deltim))
+ ! lake surface tem at tfrz, partial lake surface melt -> absorb heat -> cool down rainfall to tfrz (no latent heat)
+ ELSEIF (a<=c+d) THEN
+ t_lake(1)=tfrz
+ wice_lake(1) = denh2o*dz_lake(1) - (a-c)/hfus
+ wliq_lake(1) = (a-c)/hfus
+ lake_icefrac(1) = wice_lake(1)/(wice_lake(1) + wliq_lake(1))
+ ! all lake surface melt, absorb heat to cool down rainfall
+ ELSE !(a>c+d)
+ t_lake(1)=(cpliq*pg_rain*deltim*t_precip+cpliq*denh2o*dz_lake(1)*tfrz-c-d)/&
+ (cpliq*denh2o*dz_lake(1)+cpliq*pg_rain*deltim)
+ lake_icefrac(1) = 0.0
+ ENDIF
+
+ IF (snowdp>=0.01) THEN !frozen rain may make new snow layer
+ snl = -1
+ newnode = 1
+ dz_soisno(0) = snowdp ! meter
+ z_soisno (0) = -0.5*dz_soisno(0)
+ zi_soisno(-1) = -dz_soisno(0)
+ sag = 0. ! snow age
+
+ t_soisno (0) = t_lake(1) ! K
+ wice_soisno(0) = scv ! kg/m2
+ wliq_soisno(0) = 0. ! kg/m2
+ fiold(0) = 1.
+ ENDIF
+
+ ELSEIF (lake_icefrac(1) >= 0.001) THEN
+ IF (pg_rain > 0.0 .and. pg_snow > 0.0) THEN
+ t_lake(1)=tfrz
+ ELSEIF (pg_rain > 0.0) THEN
+ IF (a>=d) THEN
+ t_lake(1)=(cpliq*pg_rain*deltim*t_precip+cpliq*denh2o*dz_lake(1)*tfrz-d)/&
+ (cpliq*denh2o*dz_lake(1)+cpliq*pg_rain*deltim)
+ lake_icefrac(1) = 0.0
+ ELSE
+ t_lake(1)=tfrz
+ wice_lake(1) = denh2o*dz_lake(1)*lake_icefrac(1) - a/hfus
+ wliq_lake(1) = denh2o*dz_lake(1)*(1-lake_icefrac(1)) + a/hfus
+ lake_icefrac(1) = wice_lake(1)/(wice_lake(1) + wliq_lake(1))
+ ENDIF
+ ELSEIF (pg_snow > 0.0) THEN
+ IF (e>=h) THEN
+ t_lake(1)=(h+cpice*denh2o*dz_lake(1)*tfrz+cpice*pg_snow*deltim*t_precip)/&
+ (cpice*pg_snow*deltim+cpice*denh2o*dz_lake(1))
+ lake_icefrac(1) = 1.0
+ ELSE
+ t_lake(1)=tfrz
+ wice_lake(1) = denh2o*dz_lake(1)*lake_icefrac(1) + e/hfus
+ wliq_lake(1) = denh2o*dz_lake(1)*(1-lake_icefrac(1)) - e/hfus
+ lake_icefrac(1) = wice_lake(1)/(wice_lake(1) + wliq_lake(1))
+ ENDIF
+ ENDIF
+
+ ELSE
+ ! all snowfall melt, absorb heat to cool down lake surface water
+ IF (e+f<=g) THEN
+ tw=max(tfrz,t_precip)
+ t_lake(1)=(cpliq*denh2o*dz_lake(1)*t_lake(1)*(1-lake_icefrac(1))+cpliq*(pg_rain+pg_snow)*deltim*tw-e-f)/&
+ (cpliq*(pg_rain+pg_snow)*deltim+cpliq*denh2o*dz_lake(1)*(1-lake_icefrac(1)))
+ scv = scv - pg_snow*deltim
+ snowdp = snowdp - dz_snowf*deltim
+ pg_rain = pg_rain + pg_snow
+ pg_snow = 0.0
+ ! prec tem at tfrz, partial snowfall melt ->absorb heat -> cool down lake surface to tfrz (no latent heat)
+ ELSEIF (e<=g) THEN
+ t_lake(1) = tfrz
+ scv = scv - (g-e)/hfus
+ snowdp = snowdp - (g-e)/(hfus*bifall)
+ pg_rain = pg_rain + min(pg_snow, (g-e)/(hfus*deltim))
+ pg_snow = max(0.0, pg_snow - (g-e)/(hfus*deltim))
+ ! lake surface tem at tfrz, partial lake surface frozen -> release heat -> warm up snowfall to tfrz (no latent heat)
+ ELSEIF (e<=g+h) THEN
+ t_lake(1) = tfrz
+ wice_lake(1) = (e-g)/hfus
+ wliq_lake(1) = denh2o*dz_lake(1) - (e-g)/hfus
+ lake_icefrac(1) = wice_lake(1)/(wice_lake(1) + wliq_lake(1))
+ ! all lake surface frozen, release heat to warm up snowfall
+ ELSE !(e>g+h)
+ t_lake(1) = (g+h+cpice*denh2o*dz_lake(1)*tfrz+cpice*pg_snow*deltim*t_precip)/&
+ (cpice*pg_snow*deltim+cpice*denh2o*dz_lake(1))
+ lake_icefrac(1) = 1.0
+ ENDIF
+ ENDIF
+
+ IF (USE_Dynamic_Lake .and. (snl == 0)) THEN
+
+ wliq_lake(1) = dz_lake(1) * (1-lake_icefrac(1)) + pg_rain*deltim*1.e-3
+ wice_lake(1) = dz_lake(1) * lake_icefrac(1)
+ dz_lake(1) = wliq_lake(1) + wice_lake(1)
+ lake_icefrac(1) = wice_lake(1) / dz_lake(1)
+
+ CALL adjust_lake_layer (nl_lake, dz_lake, t_lake, lake_icefrac)
+
+ ENDIF
+
+ ELSEIF (snl==0 .and. snowdp >= 0.01) THEN
+
+ ! only ice part of snowfall is added here, the liquid part will be added later
+ snl = -1
+ newnode = 1
+ dz_soisno(0) = snowdp ! meter
+ z_soisno (0) = -0.5*dz_soisno(0)
+ zi_soisno(-1) = -dz_soisno(0)
+ sag = 0. ! snow age
+
+ t_soisno (0) = min(tfrz, t_precip) ! K
+ wice_soisno(0) = scv ! kg/m2
+ wliq_soisno(0) = 0. ! kg/m2
+ fiold(0) = 1.
+
+ ELSE ! ( snl<0 .and. newnode ==0 )
+
+ lb = snl + 1
+ t_soisno(lb) = ( (wice_soisno(lb)*cpice+wliq_soisno(lb)*cpliq)*t_soisno(lb) &
+ + (pg_rain*cpliq + pg_snow*cpice)*deltim*t_precip ) &
+ / ( wice_soisno(lb)*cpice + wliq_soisno(lb)*cpliq &
+ + pg_rain*deltim*cpliq + pg_snow*deltim*cpice )
+
+ t_soisno(lb) = min(tfrz, t_soisno(lb))
+ wice_soisno(lb) = wice_soisno(lb)+deltim*pg_snow
+ dz_soisno(lb) = dz_soisno(lb)+dz_snowf*deltim
+ z_soisno(lb) = zi_soisno(lb) - 0.5*dz_soisno(lb)
+ zi_soisno(lb-1) = zi_soisno(lb) - dz_soisno(lb)
+
+ ENDIF
+
+ END SUBROUTINE newsnow_lake
+
+
+
+ SUBROUTINE laketem (&
+ ! "in" arguments
+ ! -------------------
+ patchtype , maxsnl , nl_soil , nl_lake ,&
+ dlat , deltim , forc_hgt_u , forc_hgt_t,&
+ forc_hgt_q , forc_us , forc_vs , forc_t ,&
+ forc_q , forc_rhoair , forc_psrf , forc_sols ,&
+ forc_soll , forc_solsd , forc_solld , sabg ,&
+ forc_frl , dz_soisno , z_soisno , zi_soisno ,&
+ dz_lake , lakedepth , vf_quartz , vf_gravels,&
+ vf_om , vf_sand , wf_gravels , wf_sand ,&
+ porsl , csol , k_solids , &
+ dksatu , dksatf , dkdry , &
+ BA_alpha , BA_beta , hpbl , &
+
+ ! "inout" arguments
+ ! -------------------
+ t_grnd , scv , snowdp , t_soisno ,&
+ wliq_soisno , wice_soisno , imelt_soisno , t_lake ,&
+ lake_icefrac , savedtke1 , &
+
+! SNICAR model variables
+ snofrz ,sabg_snow_lyr, &
+! END SNICAR model variables
+
+ ! "out" arguments
+ ! -------------------
+ taux , tauy , fsena ,&
+ fevpa , lfevpa , fseng , fevpg ,&
+ qseva , qsubl , qsdew , qfros ,&
+ olrg , fgrnd , tref , qref ,&
+ trad , emis , z0m , zol ,&
+ rib , ustar , qstar , tstar ,&
+ fm , fh , fq , sm ,&
+ urban_call)
+
+! ------------------------ code history ---------------------------
+! purpose: lake temperature and snow on frozen lake
+! initial Yongjiu Dai, 2000
+! Zack Subin, 2009
+! Yongjiu Dai, /12/2012/, /04/2014/, 06/2018
+! Nan Wei, /06/2018/
+!
+! ------------------------ notes ----------------------------------
+! Lakes have variable depth, possible snow layers above, freezing &
+! thawing of lake water, and soil layers with active temperature and
+! gas diffusion below.
+!
+! Calculates temperatures in the 25-30 layer column of (possible) snow,
+! lake water, soil, and bedrock beneath lake. Snow and soil
+! temperatures are determined as in SoilTemperature, except for
+! appropriate boundary conditions at the top of the snow (the flux is
+! fixed to be the ground heat flux), the bottom of the snow (adjacent
+! to top lake layer), and the top of the soil (adjacent to the bottom
+! lake layer). Also, the soil is kept fully saturated. The whole
+! column is solved simultaneously as one tridiagonal matrix.
+!
+! calculate lake temperatures from one-dimensional thermal
+! stratification model based on eddy diffusion concepts to represent
+! vertical mixing of heat
+!
+! d ts d d ts 1 ds
+! ---- = -- [(km + ke) ----] + -- --
+! dt dz dz cw dz
+! where: ts = temperature (kelvin)
+! t = time (s)
+! z = depth (m)
+! km = molecular diffusion coefficient (m**2/s)
+! ke = eddy diffusion coefficient (m**2/s)
+! cw = heat capacity (j/m**3/kelvin)
+! s = heat source term (w/m**2)
+!
+! use crank-nicholson method to set up tridiagonal system of equations to
+! solve for ts at time n+1, where the temperature equation for layer i is
+! r_i = a_i [ts_i-1] n+1 + b_i [ts_i] n+1 + c_i [ts_i+1] n+1
+! the solution conserves energy as
+! cw*([ts( 1)] n+1 - [ts( 1)] n)*dz( 1)/dt + ... +
+! cw*([ts(nl_lake)] n+1 - [ts(nl_lake)] n)*dz(nl_lake)/dt = fin
+! where
+! [ts] n = old temperature (kelvin)
+! [ts] n+1 = new temperature (kelvin)
+! fin = heat flux into lake (w/m**2)
+! = beta*sabg_snow_lyr(1)+forc_frl-olrg-fsena-lfevpa-hm + phi(1) + ... + phi(nl_lake)
+!
+! !REVISIONS:
+! Yongjiu Dai and Hua Yuan, 01/2023: added SNICAR for layer solar absorption, ground heat
+! flux, temperature and freezing mass calculations
+! Shaofeng Liu, 05/2023: add option to call moninobuk_leddy, the LargeEddy
+! surface turbulence scheme (LZD2022);
+! make a proper update of um.
+!
+! -----------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz,hvap,hfus,hsub,tkwat,tkice,tkair,stefnc,&
+ vonkar,grav,cpliq,cpice,cpair,denh2o,denice,rgas
+ USE MOD_FrictionVelocity
+ USE MOD_Namelist, only: DEF_USE_CBL_HEIGHT, DEF_USE_SNICAR
+ USE MOD_TurbulenceLEddy
+ USE MOD_Qsadv
+ USE MOD_SoilThermalParameters
+ USE MOD_Utils
+
+ IMPLICIT NONE
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: patchtype ! land patch type (4=deep lake, 5=shallow lake)
+ integer, intent(in) :: maxsnl ! maximum number of snow layers
+ integer, intent(in) :: nl_soil ! number of soil layers
+ integer, intent(in) :: nl_lake ! number of lake layers
+
+ real(r8), intent(in) :: dlat ! latitude (radians)
+ real(r8), intent(in) :: deltim ! seconds in a time step (s)
+ real(r8), intent(in) :: forc_hgt_u ! observational height of wind [m]
+ real(r8), intent(in) :: forc_hgt_t ! observational height of temperature [m]
+ real(r8), intent(in) :: forc_hgt_q ! observational height of humidity [m]
+ real(r8), intent(in) :: forc_us ! wind component in eastward direction [m/s]
+ real(r8), intent(in) :: forc_vs ! wind component in northward direction [m/s]
+ real(r8), intent(in) :: forc_t ! temperature at agcm reference height [kelvin]
+ real(r8), intent(in) :: forc_q ! specific humidity at agcm reference height [kg/kg]
+ real(r8), intent(in) :: forc_rhoair ! density air [kg/m3]
+ real(r8), intent(in) :: forc_psrf ! atmosphere pressure at the surface [pa]
+ real(r8), intent(in) :: forc_sols ! atm vis direct beam solar rad onto srf [W/m2]
+ real(r8), intent(in) :: forc_soll ! atm nir direct beam solar rad onto srf [W/m2]
+ real(r8), intent(in) :: forc_solsd ! atm vis diffuse solar rad onto srf [W/m2]
+ real(r8), intent(in) :: forc_solld ! atm nir diffuse solar rad onto srf [W/m2]
+ real(r8), intent(in) :: forc_frl ! atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), intent(in) :: sabg ! solar radiation absorbed by ground [W/m2]
+
+ real(r8), intent(in) :: dz_soisno(maxsnl+1:nl_soil) ! soil/snow layer thickness (m)
+ real(r8), intent(in) :: z_soisno(maxsnl+1:nl_soil) ! soil/snow node depth [m]
+ real(r8), intent(in) :: zi_soisno(maxsnl:nl_soil) ! soil/snow depth of layer interface [m]
+
+ real(r8), intent(in) :: dz_lake(nl_lake) ! lake layer thickness (m)
+ real(r8), intent(in) :: lakedepth ! column lake depth (m)
+
+ real(r8), intent(in) :: vf_quartz (1:nl_soil) ! volumetric fraction of quartz within mineral soil
+ real(r8), intent(in) :: vf_gravels(1:nl_soil) ! volumetric fraction of gravels
+ real(r8), intent(in) :: vf_om (1:nl_soil) ! volumetric fraction of organic matter
+ real(r8), intent(in) :: vf_sand (1:nl_soil) ! volumetric fraction of sand
+ real(r8), intent(in) :: wf_gravels(1:nl_soil) ! gravimetric fraction of gravels
+ real(r8), intent(in) :: wf_sand (1:nl_soil) ! gravimetric fraction of sand
+ real(r8), intent(in) :: porsl(1:nl_soil) ! soil porosity [-]
+
+ real(r8), intent(in) :: csol(1:nl_soil) ! heat capacity of soil solids [J/(m3 K)]
+ real(r8), intent(in) :: k_solids(1:nl_soil) ! thermal conductivity of mineralssoil [W/m-K]
+ real(r8), intent(in) :: dksatu(1:nl_soil) ! thermal conductivity of saturated unfrozen soil [W/m-K]
+ real(r8), intent(in) :: dksatf(1:nl_soil) ! thermal conductivity of saturated frozen soil [W/m-K]
+ real(r8), intent(in) :: dkdry(1:nl_soil) ! thermal conductivity of dry soil [W/m-K]
+ real(r8), intent(in) :: BA_alpha(1:nl_soil) ! alpha in Balland and Arp(2005) thermal conductivity scheme
+ real(r8), intent(in) :: BA_beta(1:nl_soil) ! beta in Balland and Arp(2005) thermal conductivity scheme
+ real(r8), intent(in) :: hpbl ! atmospheric boundary layer height [m]
+
+ real(r8), intent(inout) :: t_grnd ! surface temperature (kelvin)
+ real(r8), intent(inout) :: scv ! snow water equivalent [mm]
+ real(r8), intent(inout) :: snowdp ! snow depth [mm]
+
+ real(r8), intent(inout) :: t_soisno (maxsnl+1:nl_soil) ! soil/snow temperature [K]
+ real(r8), intent(inout) :: wliq_soisno (maxsnl+1:nl_soil) ! soil/snow liquid water (kg/m2)
+ real(r8), intent(inout) :: wice_soisno (maxsnl+1:nl_soil) ! soil/snow ice lens (kg/m2)
+ integer, intent(inout) :: imelt_soisno(maxsnl+1:nl_soil) ! soil/snow flag for melting (=1), freezing (=2), Not=0 (new)
+
+ real(r8), intent(inout) :: t_lake(nl_lake) ! lake temperature (kelvin)
+ real(r8), intent(inout) :: lake_icefrac(nl_lake) ! lake mass fraction of lake layer that is frozen
+ real(r8), intent(inout) :: savedtke1 ! top level eddy conductivity (W/m K)
+
+! SNICAR model variables
+ real(r8), intent(out) :: snofrz (maxsnl+1:0) ! snow freezing rate (col,lyr) [kg m-2 s-1]
+ real(r8), intent(in) :: sabg_snow_lyr(maxsnl+1:1) ! solar radiation absorbed by ground [W/m2]
+! END SNICAR model variables
+
+ real(r8), intent(out) :: taux ! wind stress: E-W [kg/m/s**2]
+ real(r8), intent(out) :: tauy ! wind stress: N-S [kg/m/s**2]
+ real(r8), intent(out) :: fsena ! sensible heat from canopy height to atmosphere [W/m2]
+ real(r8), intent(out) :: fevpa ! evapotranspiration from canopy height to atmosphere [mm/s]
+ real(r8), intent(out) :: lfevpa ! latent heat flux from canopy height to atmosphere [W/m2]
+
+ real(r8), intent(out) :: fseng ! sensible heat flux from ground [W/m2]
+ real(r8), intent(out) :: fevpg ! evaporation heat flux from ground [mm/s]
+
+ real(r8), intent(out) :: qseva ! ground surface evaporation rate (mm h2o/s)
+ real(r8), intent(out) :: qsubl ! sublimation rate from snow pack (mm H2O /s) [+]
+ real(r8), intent(out) :: qsdew ! surface dew added to snow pack (mm H2O /s) [+]
+ real(r8), intent(out) :: qfros ! ground surface frosting formation (mm H2O /s) [+]
+
+ real(r8), intent(out) :: olrg ! outgoing long-wave radiation from ground+canopy
+ real(r8), intent(out) :: fgrnd ! ground heat flux [W/m2]
+
+ real(r8), intent(out) :: tref ! 2 m height air temperature [kelvin]
+ real(r8), intent(out) :: qref ! 2 m height air specific humidity
+ real(r8), intent(out) :: trad ! radiative temperature [K]
+
+ real(r8), intent(out) :: emis ! averaged bulk surface emissivity
+ real(r8), intent(out) :: z0m ! effective roughness [m]
+ real(r8), intent(out) :: zol ! dimensionless height (z/L) used in Monin-Obukhov theory
+ real(r8), intent(out) :: rib ! bulk Richardson number in surface layer
+ real(r8), intent(out) :: ustar ! u* in similarity theory [m/s]
+ real(r8), intent(out) :: qstar ! q* in similarity theory [kg/kg]
+ real(r8), intent(out) :: tstar ! t* in similarity theory [K]
+ real(r8), intent(out) :: fm ! integral of profile function for momentum
+ real(r8), intent(out) :: fh ! integral of profile function for heat
+ real(r8), intent(out) :: fq ! integral of profile function for moisture
+ real(r8), intent(out) :: sm ! rate of snowmelt [mm/s, kg/(m2 s)]
+ logical, optional, intent(in) :: urban_call ! whether it is a urban CALL
+
+!-------------------------- Local Variables ----------------------------
+! ---------------- local variables in surface temp and fluxes calculation -----------------
+ integer idlak ! index of lake, 1 = deep lake, 2 = shallow lake
+ real(r8) z_lake (nl_lake) ! lake node depth (middle point of layer) (m)
+
+ real(r8) ax ! used in iteration loop for calculating t_grnd (numerator of NR solution)
+ real(r8) bx ! used in iteration loop for calculating t_grnd (denomin. of NR solution)
+ real(r8) beta1 ! coefficient of conective velocity [-]
+ real(r8) degdT ! d(eg)/dT
+ real(r8) displax ! zero- displacement height [m]
+ real(r8) dqh ! diff of humidity between ref. height and surface
+ real(r8) dth ! diff of virtual temp. between ref. height and surface
+ real(r8) dthv ! diff of vir. poten. temp. between ref. height and surface
+ real(r8) dzsur ! 1/2 the top layer thickness (m)
+ real(r8) tsur ! top layer temperature
+ real(r8) rhosnow ! partial density of water (ice + liquid)
+ real(r8) eg ! water vapor pressure at temperature T [pa]
+ real(r8) emg ! ground emissivity (0.97 for snow,
+ real(r8) errore ! lake temperature energy conservation error (w/m**2)
+ real(r8) hm ! energy residual [W/m2]
+ real(r8) htvp ! latent heat of vapor of water (or sublimation) [j/kg]
+ real(r8) obu ! monin-obukhov length (m)
+ real(r8) obuold ! monin-obukhov length of previous iteration
+ real(r8) qsatg ! saturated humidity [kg/kg]
+ real(r8) qsatgdT ! d(qsatg)/dT
+
+ real(r8) ram ! aerodynamical resistance [s/m]
+ real(r8) rah ! thermal resistance [s/m]
+ real(r8) raw ! moisture resistance [s/m]
+ real(r8) stftg3 ! emg*sb*t_grnd*t_grnd*t_grnd
+ real(r8) fh2m ! relation for temperature at 2m
+ real(r8) fq2m ! relation for specific humidity at 2m
+ real(r8) fm10m ! integral of profile function for momentum at 10m
+ real(r8) t_grnd_bef0 ! initial ground temperature
+ real(r8) t_grnd_bef ! initial ground temperature
+ real(r8) thm ! intermediate variable (forc_t+0.0098*forc_hgt_t)
+ real(r8) th ! potential temperature (kelvin)
+ real(r8) thv ! virtual potential temperature (kelvin)
+ real(r8) thvstar ! virtual potential temperature scaling parameter
+ real(r8) tksur ! thermal conductivity of snow/soil (w/m/kelvin)
+ real(r8) um ! wind speed including the stability effect [m/s]
+ real(r8) ur ! wind speed at reference height [m/s]
+ real(r8) visa ! kinematic viscosity of dry air [m2/s]
+ real(r8) wc ! convective velocity [m/s]
+ real(r8) wc2 ! wc*wc
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+ real(r8) zii ! convective boundary height [m]
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) z0mg ! roughness length over ground, momentum [m]
+ real(r8) z0hg ! roughness length over ground, sensible heat [m]
+ real(r8) z0qg ! roughness length over ground, latent heat [m]
+
+ real(r8) wliq_lake(nl_lake) ! lake liquid water (kg/m2)
+ real(r8) wice_lake(nl_lake) ! lake ice lens (kg/m2)
+ real(r8) vf_water(1:nl_soil) ! volumetric fraction liquid water within underlying soil
+ real(r8) vf_ice(1:nl_soil) ! volumetric fraction ice lens within underlying soil
+
+ real(r8) fgrnd1 ! ground heat flux into the first snow/lake layer [W/m2]
+
+! ---------------- local variables in lake/snow/soil temperature calculation --------------
+ real(r8), parameter :: cur0 = 0.01 ! min. Charnock parameter
+ real(r8), parameter :: curm = 0.1 ! maximum Charnock parameter
+ real(r8), parameter :: fcrit = 22. ! critical dimensionless fetch for Charnock parameter (Vickers & Mahrt 1997)
+ ! but converted to USE u instead of u* (Subin et al. 2011)
+ real(r8), parameter :: mixfact = 5. ! Mixing enhancement factor.
+ real(r8), parameter :: depthcrit = 25. ! (m) Depth beneath which to enhance mixing
+ real(r8), parameter :: fangmult = 5. ! Multiplier for unfrozen diffusivity
+ real(r8), parameter :: minmultdepth = 20. ! (m) Minimum depth for imposing fangmult
+ real(r8), parameter :: cnfac = 0.5 ! Crank Nicholson factor between 0 and 1
+
+ !--------------------
+ real(r8) fetch ! lake fetch (m)
+ real(r8) cur ! Charnock parameter (-)
+ real(r8) betavis !
+ real(r8) betaprime ! Effective beta
+ real(r8) tdmax ! temperature of maximum water density
+ real(r8) cfus ! effective heat of fusion per unit volume
+ real(r8) tkice_eff ! effective conductivity since layer depth is constant
+ real(r8) cice_eff ! effective heat capacity of ice (using density of
+ ! water because layer depth is not adjusted when freezing
+ real(r8) cwat ! specific heat capacity of water (j/m**3/kelvin)
+
+ !--------------------
+ real(r8) rhow(nl_lake) ! density of water (kg/m**3)
+ real(r8) fin ! heat flux into lake - flux out of lake (w/m**2)
+ real(r8) phi(nl_lake) ! solar radiation absorbed by layer (w/m**2)
+ real(r8) phi_soil ! solar radiation into top soil layer (W/m^2)
+ real(r8) phidum ! temporary value of phi
+
+ integer imelt_lake(1:nl_lake) ! lake flag for melting or freezing snow and soil layer [-]
+ real(r8) cv_lake(1:nl_lake) ! heat capacity [J/(m2 K)]
+ real(r8) tk_lake(1:nl_lake) ! thermal conductivity at layer node [W/(m K)]
+ real(r8) cv_soisno(maxsnl+1:nl_soil) ! heat capacity of soil/snow [J/(m2 K)]
+ real(r8) tk_soisno(maxsnl+1:nl_soil) ! thermal conductivity of soil/snow [W/(m K)] (at interface below, except for j=0)
+ real(r8) hcap(1:nl_soil) ! J/(m3 K)
+ real(r8) thk(maxsnl+1:nl_soil) ! W/(m K)
+ real(r8) tktopsoil ! thermal conductivity of the top soil layer [W/(m K)]
+
+ real(r8) t_soisno_bef(maxsnl+1:nl_soil) ! beginning soil/snow temp for E cons. check [K]
+ real(r8) t_lake_bef(1:nl_lake) ! beginning lake temp for energy conservation check [K]
+ real(r8) wice_soisno_bef(maxsnl+1:0) ! ice lens [kg/m2]
+
+ real(r8) cvx (maxsnl+1:nl_lake+nl_soil) ! heat capacity for whole column [J/(m2 K)]
+ real(r8) tkix (maxsnl+1:nl_lake+nl_soil) ! thermal conductivity at layer interfaces for whole column [W/(m K)]
+ real(r8) phix (maxsnl+1:nl_lake+nl_soil) ! solar source term for whole column [W/m**2]
+ real(r8) zx (maxsnl+1:nl_lake+nl_soil) ! interface depth (+ below surface) for whole column [m]
+ real(r8) tx (maxsnl+1:nl_lake+nl_soil) ! temperature of whole column [K]
+ real(r8) tx_bef (maxsnl+1:nl_lake+nl_soil) ! beginning lake/snow/soil temp for energy conservation check [K]
+ real(r8) factx (maxsnl+1:nl_lake+nl_soil) ! coefficient used in computing tridiagonal matrix
+ real(r8) fnx (maxsnl+1:nl_lake+nl_soil) ! heat diffusion through the layer interface below [W/m2]
+ real(r8) a (maxsnl+1:nl_lake+nl_soil) ! "a" vector for tridiagonal matrix
+ real(r8) b (maxsnl+1:nl_lake+nl_soil) ! "b" vector for tridiagonal matrix
+ real(r8) c (maxsnl+1:nl_lake+nl_soil) ! "c" vector for tridiagonal matrix
+ real(r8) r (maxsnl+1:nl_lake+nl_soil) ! "r" vector for tridiagonal solution
+ real(r8) fn1 (maxsnl+1:nl_lake+nl_soil) ! heat diffusion through the layer interface below [W/m2]
+ real(r8) brr (maxsnl+1:nl_lake+nl_soil) !
+ integer imelt_x(maxsnl+1:nl_lake+nl_soil) ! flag for melting (=1), freezing (=2), Not=0 (new)
+
+ real(r8) dzm ! used in computing tridiagonal matrix [m]
+ real(r8) dzp ! used in computing tridiagonal matrix [m]
+ real(r8) zin ! depth at top of layer (m)
+ real(r8) zout ! depth at bottom of layer (m)
+ real(r8) rsfin ! relative flux of solar radiation into layer
+ real(r8) rsfout ! relative flux of solar radiation out of layer
+ real(r8) eta ! light extinction coefficient (/m): depends on lake type
+ real(r8) za(2) ! base of surface absorption layer (m): depends on lake type
+ !--------------------
+
+ real(r8) hs ! net ground heat flux into the surface
+ real(r8) dhsdT ! temperature derivative of "hs"
+ real(r8) heatavail ! available energy for melting or freezing (J/m^2)
+ real(r8) heatrem ! energy residual or loss after melting or freezing
+ real(r8) melt ! actual melting (+) or freezing (-) [kg/m2]
+ real(r8) xmf ! total per-column latent heat abs. from phase change (J/m^2)
+ !--------------------
+
+ real(r8) ocvts ! (cwat*(t_lake[n ])*dz_lake
+ real(r8) ncvts ! (cwat*(t_lake[n+1])*dz_lake
+ real(r8) esum1 ! temp for checking energy (J/m^2)
+ real(r8) esum2 ! ""
+ real(r8) zsum ! temp for putting ice at the top during convection (m)
+ real(r8) errsoi ! soil/lake energy conservation error (W/m^2)
+
+ real(r8) iceav ! used in calc aver ice for convectively mixed layers
+ real(r8) qav ! used in calc aver heat content for conv. mixed layers
+ real(r8) tav ! used in aver temp for convectively mixed layers
+ real(r8) tav_froz ! used in aver temp for convectively mixed layers (C)
+ real(r8) tav_unfr ! "
+ real(r8) nav ! used in aver temp for convectively mixed layers
+
+ real(r8) fevpg_lim ! temporary evap_soi limited by top snow layer content [mm/s]
+ real(r8) scv_temp ! temporary h2osno [kg/m^2]
+ real(r8) tmp !
+ real(r8) h_fin !
+ real(r8) h_finDT !
+ real(r8) del_T_grnd!
+ !real(r8) savedtke1
+
+ integer iter ! iteration index
+ integer convernum ! number of time when del_T_grnd < 0.01
+ integer nmozsgn ! number of times moz changes sign
+
+! assign iteration parameters
+ integer, parameter :: itmax = 40 ! maximum number of iteration
+ integer, parameter :: itmin = 6 ! minimum number of iteration
+ real(r8),parameter :: delmax = 3.0 ! maximum change in lake temperature [K]
+ real(r8),parameter :: dtmin = 0.01 ! max limit for temperature convergence [K]
+ real(r8),parameter :: dlemin = 0.1 ! max limit for energy flux convergence [w/m2]
+
+ !--------------------
+
+ integer nl_sls ! abs(snl)+nl_lake+nl_soil
+ integer snl ! number of snow layers (minimum -5)
+ integer lb ! lower bound of arrays
+ integer jprime ! j - nl_lake
+
+ integer i,j ! do loop or array index
+
+! ======================================================================
+!*[1] constants and model parameters
+! ======================================================================
+
+
+! constants for lake temperature model
+ za = (/0.5, 0.6/)
+ cwat = cpliq*denh2o ! water heat capacity per unit volume
+ cice_eff = cpice*denh2o ! use water density because layer depth is not adjusted for freezing
+ cfus = hfus*denh2o ! latent heat per unit volume
+ tkice_eff = tkice * denice/denh2o ! effective conductivity since layer depth is constant
+ emg = 0.97 ! surface emissivity
+
+! define snow layer on ice lake
+ snl = 0
+ DO j=maxsnl+1,0
+ IF(wliq_soisno(j)+wice_soisno(j)>0.) snl=snl-1
+ ENDDO
+ lb = snl + 1
+
+! latent heat
+ IF (t_grnd > tfrz )THEN
+ htvp = hvap
+ ELSE
+ htvp = hsub
+ ENDIF
+
+! define levels
+ z_lake(1) = dz_lake(1) / 2.
+ DO j = 2, nl_lake
+ z_lake(j) = z_lake(j-1) + (dz_lake(j-1) + dz_lake(j))/2.
+ ENDDO
+
+! Base on lake depth, assuming that small lakes are likely to be shallower
+! Estimate crudely based on lake depth
+ IF (z_lake(nl_lake) < 4.) THEN
+ idlak = 1
+ fetch = 100. ! shallow lake
+ ELSE
+ idlak = 2
+ fetch = 25.*z_lake(nl_lake) ! deep lake
+ ENDIF
+
+
+! ======================================================================
+!*[2] pre-processing for the calculation of the surface temperature and fluxes
+! ======================================================================
+
+ IF (.not. DEF_USE_SNICAR .or. present(urban_call)) THEN
+ IF (snl == 0) THEN
+ ! calculate the nir fraction of absorbed solar.
+ betaprime = (forc_soll+forc_solld)/max(1.e-5,forc_sols+forc_soll+forc_solsd+forc_solld)
+ betavis = 0. ! The fraction of the visible (e.g. vis not nir from atm) sunlight
+ ! absorbed in ~1 m of water (the surface layer za_lake).
+ ! This is roughly the fraction over 700 nm but may depend on the details
+ ! of atmospheric radiative transfer.
+ ! As long as NIR = 700 nm and up, this can be zero.
+ betaprime = betaprime + (1.0-betaprime)*betavis
+ ELSE
+ ! or frozen but no snow layers or
+ ! currently ignore the transmission of solar in snow and ice layers
+ ! to be updated in the future version
+ betaprime = 1.0
+ ENDIF
+
+ ELSE
+ ! calculate the nir fraction of absorbed solar.
+ betaprime = (forc_soll+forc_solld)/max(1.e-5,forc_sols+forc_soll+forc_solsd+forc_solld)
+ betavis = 0. ! The fraction of the visible (e.g. vis not nir from atm) sunlight
+ ! absorbed in ~1 m of water (the surface layer za_lake).
+ ! This is roughly the fraction over 700 nm but may depend on the details
+ ! of atmospheric radiative transfer.
+ ! As long as NIR = 700 nm and up, this can be zero.
+ betaprime = betaprime + (1.0-betaprime)*betavis
+ ENDIF
+
+ CALL qsadv(t_grnd,forc_psrf,eg,degdT,qsatg,qsatgdT)
+! potential temperature at the reference height
+ beta1=1. ! - (in computing W_*)
+ zii = 1000. ! m (pbl height)
+ thm = forc_t + 0.0098*forc_hgt_t ! intermediate variable equivalent to
+ ! forc_t*(pgcm/forc_psrf)**(rgas/cpair)
+ th = forc_t*(100000./forc_psrf)**(rgas/cpair) ! potential T
+ thv = th*(1.+0.61*forc_q) ! virtual potential T
+ ur = max(0.1,sqrt(forc_us*forc_us+forc_vs*forc_vs)) ! limit set to 0.1
+
+! Initialization variables
+ nmozsgn = 0
+ obuold = 0.
+ dth = thm-t_grnd
+ dqh = forc_q-qsatg
+ dthv = dth*(1.+0.61*forc_q)+0.61*th*dqh
+ zldis = forc_hgt_u-0.
+
+! Roughness lengths, allow all roughness lengths to be prognostic
+ ustar=0.06
+ wc=0.5
+
+ ! Kinematic viscosity of dry air (m2/s)- Andreas (1989) CRREL Rep. 89-11
+ visa=1.326e-5*(1.+6.542e-3*(forc_t-tfrz) &
+ + 8.301e-6*(forc_t-tfrz)**2 - 4.84e-9*(forc_t-tfrz)**3)
+
+ cur = cur0 + curm * exp( max( -(fetch*grav/ur/ur)**(1./3.)/fcrit, & ! Fetch-limited
+ -(z_lake(nl_lake)*grav)**0.5/ur ) ) ! depth-limited
+
+ IF(dthv.ge.0.) THEN
+ um=max(ur,0.1)
+ ELSE
+ um=sqrt(ur*ur+wc*wc)
+ ENDIF
+
+ DO i=1,5
+ z0mg=0.013*ustar*ustar/grav+0.11*visa/ustar
+ ustar=vonkar*um/log(zldis/z0mg)
+ ENDDO
+
+ CALL roughness_lake (snl,t_grnd,t_lake(1),lake_icefrac(1),forc_psrf,&
+ cur,ustar,z0mg,z0hg,z0qg)
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mg,um,obu)
+
+ IF (snl == 0) THEN
+ dzsur = dz_lake(1)/2.
+ ELSE
+ dzsur = z_soisno(lb)-zi_soisno(lb-1)
+ ENDIF
+
+
+ iter = 1
+ del_T_grnd = 1.0 ! t_grnd diff
+ convernum = 0 ! number of time when del_T_grnd <= 0.01
+
+
+! ======================================================================
+!*[3] Begin stability iteration and temperature and fluxes calculation
+! ======================================================================
+
+
+ ! =====================================
+ ITERATION : DO WHILE (iter <= itmax)
+ ! =====================================
+
+ t_grnd_bef = t_grnd
+
+ IF (t_grnd_bef > tfrz .and. t_lake(1) > tfrz .and. snl == 0) THEN
+ tksur = savedtke1 !water molecular conductivity
+ tsur = t_lake(1)
+ htvp = hvap
+ ELSEIF (snl == 0) THEN !frozen but no snow layers
+ tksur = tkice ! This is an approximation because the whole layer may not be frozen, and it is not
+ ! accounting for the physical (but not nominal) expansion of the frozen layer.
+ tsur = t_lake(1)
+ htvp = hsub
+ ELSE
+ ! need to calculate thermal conductivity of the top snow layer
+ rhosnow = (wice_soisno(lb)+wliq_soisno(lb))/dz_soisno(lb)
+ tksur = tkair + (7.75e-5*rhosnow + 1.105e-6*rhosnow*rhosnow)*(tkice-tkair)
+ tsur = t_soisno(lb)
+ htvp = hsub
+ ENDIF
+
+! Evaluated stability-dependent variables using moz from prior iteration
+ displax = 0.
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobuk_leddy(forc_hgt_u,forc_hgt_t,forc_hgt_q,displax,z0mg,z0hg,z0qg,obu,um, hpbl, &
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ELSE
+ CALL moninobuk(forc_hgt_u,forc_hgt_t,forc_hgt_q,displax,z0mg,z0hg,z0qg,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ENDIF
+
+! Get derivative of fluxes with respect to ground temperature
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/fh*ustar)
+ raw = 1./(vonkar/fq*ustar)
+ stftg3 = emg*stefnc*t_grnd_bef*t_grnd_bef*t_grnd_bef
+
+ ax = betaprime*sabg + emg*forc_frl + 3.*stftg3*t_grnd_bef &
+ + forc_rhoair*cpair/rah*thm &
+ - htvp*forc_rhoair/raw*(qsatg-qsatgdT*t_grnd_bef - forc_q) &
+ + tksur*tsur/dzsur
+
+ bx = 4.*stftg3 + forc_rhoair*cpair/rah &
+ + htvp*forc_rhoair/raw*qsatgdT + tksur/dzsur
+
+ t_grnd = ax/bx
+
+ !-----------------------------------------------------------------
+ ! h_fin = betaprime*sabg + emg*forc_frl + 3.*stftg3*t_grnd_bef & !
+ ! + forc_rhoair*cpair/rah*thm & !
+ ! - htvp*forc_rhoair/raw*(qsatg-qsatgdT*t_grnd_bef - forc_q) !
+ ! h_finDT = 4.*stftg3 + forc_rhoair*cpair/rah & !
+ ! + htvp*forc_rhoair/raw*qsatgdT !
+ ! del_T_grnd = t_grnd - t_grnd_bef !
+ !----------------------------------------------------------------!
+
+! surface fluxes of momentum, sensible and latent
+! using ground temperatures from previous time step
+
+ fseng = forc_rhoair*cpair*(t_grnd-thm)/rah
+ fevpg = forc_rhoair*(qsatg+qsatgdT*(t_grnd-t_grnd_bef)-forc_q)/raw
+
+ CALL qsadv(t_grnd,forc_psrf,eg,degdT,qsatg,qsatgdT)
+ dth = thm-t_grnd
+ dqh = forc_q-qsatg
+ tstar = vonkar/fh*dth
+ qstar = vonkar/fq*dqh
+ thvstar = tstar*(1.+0.61*forc_q)+0.61*th*qstar
+ zeta = zldis*vonkar*grav*thvstar/(ustar**2*thv)
+ IF(zeta >= 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+ IF(zeta >= 0.)THEN
+ um = max(ur,0.1)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ zii = max(5.*forc_hgt_u,hpbl)
+ ENDIF !//TODO: Shaofeng, 2023.05.18
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta1*beta1*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ CALL roughness_lake (snl,t_grnd,t_lake(1),lake_icefrac(1),forc_psrf,&
+ cur,ustar,z0mg,z0hg,z0qg)
+
+ iter = iter + 1
+ del_T_grnd = abs(t_grnd - t_grnd_bef)
+
+ IF(iter .gt. itmin) THEN
+ IF(del_T_grnd <= dtmin) THEN
+ convernum = convernum + 1
+ ENDIF
+ IF(convernum >= 4) EXIT
+ ENDIF
+
+ ! ===============================================
+ ENDDO ITERATION ! end of stability iteration
+ ! ===============================================
+
+!*----------------------------------------------------------------------
+!*Zack Subin, 3/27/09
+!*Since they are now a function of whatever t_grnd was before cooling
+!*to freezing temperature, then this value should be used in the derivative correction term.
+!*Allow convection if ground temp is colder than lake but warmer than 4C, or warmer than
+!*lake which is warmer than freezing but less than 4C.
+ tdmax = tfrz + 4.0
+ IF ( (snl < 0 .or. t_lake(1) <= tfrz) .and. t_grnd > tfrz) THEN
+ t_grnd_bef = t_grnd
+ t_grnd = tfrz
+ fseng = forc_rhoair*cpair*(t_grnd-thm)/rah
+ fevpg = forc_rhoair*(qsatg+qsatgdT*(t_grnd-t_grnd_bef)-forc_q)/raw
+ ELSEIF ( (t_lake(1) > t_grnd .and. t_grnd > tdmax) .or. &
+ (t_lake(1) < t_grnd .and. t_lake(1) > tfrz .and. t_grnd < tdmax) ) THEN
+ ! Convective mixing will occur at surface
+ t_grnd_bef = t_grnd
+ t_grnd = t_lake(1)
+ fseng = forc_rhoair*cpair*(t_grnd-thm)/rah
+ fevpg = forc_rhoair*(qsatg+qsatgdT*(t_grnd-t_grnd_bef)-forc_q)/raw
+ ENDIF
+!*----------------------------------------------------------------------
+
+! net longwave from ground to atmosphere
+ stftg3 = emg*stefnc*t_grnd_bef*t_grnd_bef*t_grnd_bef
+ olrg = (1.-emg)*forc_frl + emg*stefnc*t_grnd_bef**4 + 4.*stftg3*(t_grnd - t_grnd_bef)
+ IF (t_grnd > tfrz )THEN
+ htvp = hvap
+ ELSE
+ htvp = hsub
+ ENDIF
+
+!The actual heat flux from the ground interface into the lake, not including the light that penetrates the surface.
+ fgrnd1 = betaprime*sabg + forc_frl - olrg - fseng - htvp*fevpg
+
+ ! January 12, 2023 by Yongjiu Dai
+ IF (DEF_USE_SNICAR .and. .not. present(urban_call)) THEN
+ hs = sabg_snow_lyr(lb) + forc_frl - olrg - fseng - htvp*fevpg
+ dhsdT = 0.0
+ ENDIF
+
+!------------------------------------------------------------
+! Set up vector r and vectors a, b, c that define tridiagonal matrix
+! snow and lake and soil layer temperature
+!------------------------------------------------------------
+
+!------------------------------------------------------------
+! Lake density
+!------------------------------------------------------------
+
+ DO j = 1, nl_lake
+ rhow(j) = (1.-lake_icefrac(j))*denh2o*(1.0-1.9549e-05*(abs(t_lake(j)-277.))**1.68) &
+ + lake_icefrac(j)*denice
+ ! allow for ice fraction; assume constant ice density.
+ ! this is not the correct average-weighting but that's OK because the density will only
+ ! be used for convection for lakes with ice, and the ice fraction will dominate the
+ ! density differences between layers.
+ ! using this average will make sure that surface ice is treated properly during
+ ! convective mixing.
+ ENDDO
+
+!------------------------------------------------------------
+! Diffusivity and implied thermal "conductivity" = diffusivity * cwat
+!------------------------------------------------------------
+
+ DO j = 1, nl_lake
+ cv_lake(j) = dz_lake(j) * (cwat*(1.-lake_icefrac(j)) + cice_eff*lake_icefrac(j))
+ ENDDO
+
+ CALL hConductivity_lake(nl_lake,snl,t_grnd,&
+ z_lake,t_lake,lake_icefrac,rhow,&
+ dlat,ustar,z0mg,lakedepth,depthcrit,tk_lake,savedtke1)
+
+!------------------------------------------------------------
+! Set the thermal properties of the snow above frozen lake and underlying soil
+! and check initial energy content.
+!------------------------------------------------------------
+
+ lb = snl+1
+ DO i = 1, nl_soil
+ vf_water(i) = wliq_soisno(i)/(dz_soisno(i)*denh2o)
+ vf_ice(i) = wice_soisno(i)/(dz_soisno(i)*denice)
+ CALL soil_hcap_cond(vf_gravels(i),vf_om(i),vf_sand(i),porsl(i),&
+ wf_gravels(i),wf_sand(i),k_solids(i),&
+ csol(i),dkdry(i),dksatu(i),dksatf(i),&
+ BA_alpha(i),BA_beta(i),&
+ t_soisno(i),vf_water(i),vf_ice(i),hcap(i),thk(i))
+ cv_soisno(i) = hcap(i)*dz_soisno(i)
+ ENDDO
+
+! Snow heat capacity and conductivity
+ IF(lb <=0 )THEN
+ DO j = lb, 0
+ cv_soisno(j) = cpliq*wliq_soisno(j) + cpice*wice_soisno(j)
+ rhosnow = (wice_soisno(j)+wliq_soisno(j))/dz_soisno(j)
+ thk(j) = tkair + (7.75e-5*rhosnow + 1.105e-6*rhosnow*rhosnow)*(tkice-tkair)
+ ENDDO
+ ENDIF
+
+! Thermal conductivity at the layer interface
+ DO i = lb, nl_soil-1
+
+! the following consideration is try to avoid the snow conductivity
+! to be dominant in the thermal conductivity of the interface.
+! Because when the distance of bottom snow node to the interface
+! is larger than that of interface to top soil node,
+! the snow thermal conductivity will be dominant, and the result is that
+! lees heat transfer between snow and soil
+
+! modified by Nan Wei, 08/25/2014
+ IF (i /= 0) THEN
+ tk_soisno(i) = thk(i)*thk(i+1)*(z_soisno(i+1)-z_soisno(i)) &
+ /(thk(i)*(z_soisno(i+1)-zi_soisno(i))+thk(i+1)*(zi_soisno(i)-z_soisno(i)))
+ ELSE
+ tk_soisno(i) = thk(i)
+ ENDIF
+ ENDDO
+ tk_soisno(nl_soil) = 0.
+ tktopsoil = thk(1)
+
+! Sum cv_lake*t_lake for energy check
+! Include latent heat term, and use tfrz as reference temperature
+! to prevent abrupt change in heat content due to changing heat capacity with phase change.
+
+ ! This will need to be over all soil / lake / snow layers. Lake is below.
+ ocvts = 0.
+ DO j = 1, nl_lake
+ ocvts = ocvts + cv_lake(j)*(t_lake(j)-tfrz) + cfus*dz_lake(j)*(1.-lake_icefrac(j))
+ ENDDO
+
+ ! Now DO for soil / snow layers
+ DO j = lb, nl_soil
+ ocvts = ocvts + cv_soisno(j)*(t_soisno(j)-tfrz) + hfus*wliq_soisno(j)
+ IF (j == 1 .and. scv > 0. .and. j == lb) THEN
+ ocvts = ocvts - scv*hfus
+ ENDIF
+ ENDDO
+
+ ! Set up solar source terms (phix)
+ ! Modified January 12, 2023 by Yongjiu Dai
+ IF (.not. DEF_USE_SNICAR .or. present(urban_call)) THEN
+ IF ((t_grnd > tfrz .and. t_lake(1) > tfrz .and. snl == 0)) THEN !no snow cover, unfrozen layer lakes
+ DO j = 1, nl_lake
+ ! extinction coefficient from surface data (1/m), if no eta from surface data,
+ ! set eta, the extinction coefficient, according to L Hakanson, Aquatic Sciences, 1995
+ ! (regression of secchi depth with lake depth for small glacial basin lakes), and the
+ ! Poole & Atkins expression for extinction coefficient of 1.7 / secchi Depth (m).
+
+ eta = 1.1925*max(lakedepth,1.)**(-0.424)
+ zin = z_lake(j) - 0.5*dz_lake(j)
+ zout = z_lake(j) + 0.5*dz_lake(j)
+ rsfin = exp( -eta*max( zin-za(idlak),0. ) ) ! the radiation within surface layer (z= 0.0) THEN
+ IF(lb <= 0)THEN
+ qseva = min(wliq_soisno(lb)/deltim, fevpg)
+ qsubl = fevpg - qseva
+ ELSE
+ qseva = min((1.-lake_icefrac(1))*1000.*dz_lake(1)/deltim, fevpg)
+ qsubl = fevpg - qseva
+ ENDIF
+ ELSE
+ IF (t_grnd < tfrz) THEN
+ qfros = abs(fevpg)
+ ELSE
+ qsdew = abs(fevpg)
+ ENDIF
+ ENDIF
+
+
+#if (defined CoLMDEBUG)
+ ! sum energy content and total energy into lake for energy check. any errors will be from the
+ ! tridiagonal solution.
+ esum1 = 0.0
+ esum2 = 0.0
+ DO j = lb, nl_lake + nl_soil
+ esum1 = esum1 + (tx(j)-tx_bef(j))*cvx(j)
+ esum2 = esum2 + (tx(j)-tfrz)*cvx(j)
+ ENDDO
+ ! fgrnd includes all the solar radiation absorbed in the lake,
+ errsoi = esum1/deltim - fgrnd
+ IF(abs(errsoi) > 0.1) THEN
+ write(6,*)'energy conservation error in LAND WATER COLUMN during tridiagonal solution,', &
+ 'error (W/m^2):', errsoi, fgrnd
+ ENDIF
+#endif
+
+
+!------------------------------------------------------------
+!*[4] Phase change
+!------------------------------------------------------------
+
+ sm = 0.0
+ xmf = 0.0
+ imelt_soisno(:) = 0
+ imelt_lake(:) = 0
+
+ IF (DEF_USE_SNICAR .and. .not. present(urban_call)) THEN
+ wice_soisno_bef(lb:0) = wice_soisno(lb:0)
+ ENDIF
+
+ ! Check for case of snow without snow layers and top lake layer temp above freezing.
+
+ IF (snl == 0 .and. scv > 0. .and. t_lake(1) > tfrz) THEN
+ heatavail = (t_lake(1) - tfrz) * cv_lake(1)
+ melt = min(scv, heatavail/hfus)
+ heatrem = max(heatavail - melt*hfus, 0.) !catch small negative value to keep t at tfrz
+ t_lake(1) = tfrz + heatrem/(cv_lake(1))
+
+ snowdp = max(0., snowdp*(1. - melt/scv))
+ scv = scv - melt
+
+ IF (scv < 1.e-12) scv = 0. ! prevent tiny residuals
+ IF (snowdp < 1.e-12) snowdp = 0. ! prevent tiny residuals
+ sm = sm + melt/deltim
+ xmf = xmf + melt*hfus
+ ENDIF
+
+ ! Lake phase change
+ DO j = 1,nl_lake
+ IF (t_lake(j) > tfrz .and. lake_icefrac(j) > 0.) THEN ! melting
+ imelt_lake(j) = 1
+ heatavail = (t_lake(j) - tfrz) * cv_lake(j)
+ melt = min(lake_icefrac(j)*denh2o*dz_lake(j), heatavail/hfus)
+ !denh2o is used because layer thickness is not adjusted for freezing
+ heatrem = max(heatavail - melt*hfus, 0.) !catch small negative value to keep t at tfrz
+ ELSEIF (t_lake(j) < tfrz .and. lake_icefrac(j) < 1.) THEN !freezing
+ imelt_lake(j) = 2
+ heatavail = (t_lake(j) - tfrz) * cv_lake(j)
+ melt = max(-(1.-lake_icefrac(j))*denh2o*dz_lake(j), heatavail/hfus)
+ !denh2o is used because layer thickness is not adjusted for freezing
+ heatrem = min(heatavail - melt*hfus, 0.) !catch small positive value to keep t at tfrz
+ ENDIF
+ ! Update temperature and ice fraction.
+ IF (imelt_lake(j) > 0) THEN
+ lake_icefrac(j) = lake_icefrac(j) - melt/(denh2o*dz_lake(j))
+ IF (lake_icefrac(j) > 1.-1.e-12) lake_icefrac(j) = 1. ! prevent tiny residuals
+ IF (lake_icefrac(j) < 1.e-12) lake_icefrac(j) = 0. ! prevent tiny residuals
+ cv_lake(j) = cv_lake(j) + melt*(cpliq-cpice) ! update heat capacity
+ t_lake(j) = tfrz + heatrem/cv_lake(j)
+ xmf = xmf + melt*hfus
+ ENDIF
+ ENDDO
+
+ ! snow & soil phase change. currently, does not DO freezing point depression.
+ DO j = snl+1,nl_soil
+ IF (t_soisno(j) > tfrz .and. wice_soisno(j) > 0.) THEN ! melting
+ imelt_soisno(j) = 1
+ heatavail = (t_soisno(j) - tfrz) * cv_soisno(j)
+ melt = min(wice_soisno(j), heatavail/hfus)
+ heatrem = max(heatavail - melt*hfus, 0.) !catch small negative value to keep t at tfrz
+ IF (j <= 0) sm = sm + melt/deltim
+ ELSEIF (t_soisno(j) < tfrz .and. wliq_soisno(j) > 0.) THEN !freezing
+ imelt_soisno(j) = 2
+ heatavail = (t_soisno(j) - tfrz) * cv_soisno(j)
+ melt = max(-wliq_soisno(j), heatavail/hfus)
+ heatrem = min(heatavail - melt*hfus, 0.) !catch small positive value to keep t at tfrz
+ ENDIF
+
+ ! Update temperature and soil components.
+ IF (imelt_soisno(j) > 0) THEN
+ wice_soisno(j) = wice_soisno(j) - melt
+ wliq_soisno(j) = wliq_soisno(j) + melt
+ IF (wice_soisno(j) < 1.e-12) wice_soisno(j) = 0. ! prevent tiny residuals
+ IF (wliq_soisno(j) < 1.e-12) wliq_soisno(j) = 0. ! prevent tiny residuals
+ cv_soisno(j) = cv_soisno(j) + melt*(cpliq-cpice) ! update heat capacity
+ t_soisno(j) = tfrz + heatrem/cv_soisno(j)
+ xmf = xmf + melt*hfus
+ ENDIF
+ ENDDO
+ !------------------------------------------------------------
+
+ IF (DEF_USE_SNICAR .and. .not. present(urban_call)) THEN
+ !for SNICAR: layer freezing mass flux (positive):
+ DO j = lb, 0
+ IF (imelt_soisno(j)==2 .and. j<1) THEN
+ snofrz(j) = max(0._r8,(wice_soisno(j)-wice_soisno_bef(j)))/deltim
+ ENDIF
+ ENDDO
+ ENDIF
+
+#if (defined CoLMDEBUG)
+ ! second energy check and water check. now check energy balance before and after phase
+ ! change, considering the possibility of changed heat capacity during phase change, by
+ ! using initial heat capacity in the first step, final heat capacity in the second step,
+ ! and differences from tfrz only to avoid enthalpy correction for (cpliq-cpice)*melt*tfrz.
+ ! also check soil water sum.
+ DO j = 1, nl_lake
+ esum2 = esum2 - (t_lake(j)-tfrz)*cv_lake(j)
+ ENDDO
+
+ DO j = lb, nl_soil
+ esum2 = esum2 - (t_soisno(j)-tfrz)*cv_soisno(j)
+ ENDDO
+
+ esum2 = esum2 - xmf
+ errsoi = esum2/deltim
+
+ IF(abs(errsoi) > 0.1) THEN
+ write(6,*) 'energy conservation error in LAND WATER COLUMN during phase change, error (W/m^2):', errsoi
+ ENDIF
+
+#endif
+
+!------------------------------------------------------------
+!*[5] Convective mixing: make sure fracice*dz is conserved, heat content c*dz*T is conserved, and
+! all ice ends up at the top. Done over all lakes even IF frozen.
+! Either an unstable density profile or ice in a layer below an incompletely frozen layer will trigger.
+!------------------------------------------------------------
+
+ ! recalculate density
+ DO j = 1, nl_lake
+ rhow(j) = (1.-lake_icefrac(j))*1000.*(1.0-1.9549e-05*(abs(t_lake(j)-277.))**1.68) &
+ + lake_icefrac(j)*denice
+ ENDDO
+
+ DO j = 1, nl_lake-1
+ qav = 0.
+ nav = 0.
+ iceav = 0.
+
+ IF (rhow(j)>rhow(j+1) .or. (lake_icefrac(j)<1.0 .and. lake_icefrac(j+1)>0.)) THEN
+ DO i = 1, j+1
+ qav = qav + dz_lake(i)*(t_lake(i)-tfrz) * &
+ ((1. - lake_icefrac(i))*cwat + lake_icefrac(i)*cice_eff)
+ iceav = iceav + lake_icefrac(i)*dz_lake(i)
+ nav = nav + dz_lake(i)
+ ENDDO
+
+ qav = qav/nav
+ iceav = iceav/nav
+ !IF the average temperature is above freezing, put the extra energy into the water.
+ !IF it is below freezing, take it away from the ice.
+ IF (qav > 0.) THEN
+ tav_froz = 0. !Celsius
+ tav_unfr = qav / ((1. - iceav)*cwat)
+ ELSEIF (qav < 0.) THEN
+ tav_froz = qav / (iceav*cice_eff)
+ tav_unfr = 0. !Celsius
+ ELSE
+ tav_froz = 0.
+ tav_unfr = 0.
+ ENDIF
+ ENDIF
+
+ IF (nav > 0.) THEN
+ DO i = 1, j+1
+
+ !put all the ice at the top.
+ !if the average temperature is above freezing, put the extra energy into the water.
+ !if it is below freezing, take it away from the ice.
+ !for the layer with both ice & water, be careful to use the average temperature
+ !that preserves the correct total heat content given what the heat capacity of that
+ !layer will actually be.
+
+ IF (i == 1) zsum = 0.
+ IF ((zsum+dz_lake(i))/nav <= iceav) THEN
+ lake_icefrac(i) = 1.
+ t_lake(i) = tav_froz + tfrz
+ ELSEIF (zsum/nav < iceav) THEN
+ lake_icefrac(i) = (iceav*nav - zsum) / dz_lake(i)
+ ! Find average value that preserves correct heat content.
+ t_lake(i) = ( lake_icefrac(i)*tav_froz*cice_eff &
+ + (1. - lake_icefrac(i))*tav_unfr*cwat ) &
+ / ( lake_icefrac(i)*cice_eff + (1-lake_icefrac(i))*cwat ) + tfrz
+ ELSE
+ lake_icefrac(i) = 0.
+ t_lake(i) = tav_unfr + tfrz
+ ENDIF
+ zsum = zsum + dz_lake(i)
+
+ rhow(i) = (1.-lake_icefrac(i))*1000.*(1.-1.9549e-05*(abs(t_lake(i)-277.))**1.68) &
+ + lake_icefrac(i)*denice
+ ENDDO
+ ENDIF
+ ENDDO
+
+!------------------------------------------------------------
+!*[6] Re-evaluate thermal properties and sum energy content.
+!------------------------------------------------------------
+ ! for lake
+ DO j = 1, nl_lake
+ cv_lake(j) = dz_lake(j) * (cwat*(1.-lake_icefrac(j)) + cice_eff*lake_icefrac(j))
+ ENDDO
+
+ ! do as above to sum energy content
+ ncvts = 0.
+ DO j = 1, nl_lake
+ ncvts = ncvts + cv_lake(j)*(t_lake(j)-tfrz) + cfus*dz_lake(j)*(1.-lake_icefrac(j))
+ ENDDO
+
+ DO j = lb, nl_soil
+ ncvts = ncvts + cv_soisno(j)*(t_soisno(j)-tfrz) + hfus*wliq_soisno(j)
+ IF (j == 1 .and. scv > 0. .and. j == lb) THEN
+ ncvts = ncvts - scv*hfus
+ ENDIF
+ ENDDO
+
+ ! check energy conservation.
+ errsoi = (ncvts-ocvts)/deltim - fgrnd
+ IF (abs(errsoi) < 0.10) THEN
+ fseng = fseng - errsoi
+ fsena = fseng
+ fgrnd = fgrnd + errsoi
+ errsoi = 0.
+ ELSE
+ print*, "energy conservation error in LAND WATER COLUMN during convective mixing", errsoi,fgrnd,ncvts,ocvts
+ ENDIF
+
+
+ END SUBROUTINE laketem
+
+
+
+ SUBROUTINE snowwater_lake ( USE_Dynamic_Lake, &
+ ! "in" arguments
+ ! ---------------------------
+ maxsnl , nl_soil , nl_lake , deltim ,&
+ ssi , wimp , porsl , pg_rain ,&
+ pg_snow , dz_lake , imelt , fiold ,&
+ qseva , qsubl , qsdew , qfros ,&
+
+ ! "inout" arguments
+ ! ---------------------------
+ z_soisno , dz_soisno , zi_soisno , t_soisno ,&
+ wice_soisno , wliq_soisno , t_lake , lake_icefrac ,&
+ qout_snowb , &
+ fseng , fgrnd , snl , scv ,&
+ snowdp , sm , forc_us , forc_vs ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho , mss_bcphi , mss_ocpho , mss_ocphi ,&
+ mss_dst1 , mss_dst2 , mss_dst3 , mss_dst4 ,&
+! END SNICAR model variables
+ urban_call )
+
+!-----------------------------------------------------------------------------------------------
+! Calculation of Lake Hydrology. Lake water mass is kept constant. The
+! soil is simply maintained at volumetric saturation if ice melting
+! frees up pore space.
+!
+! Called:
+! -> snowwater: change of snow mass and snow water onto soil
+! -> snowcompaction: compaction of snow layers
+! -> combinesnowlayers: combine snow layers that are thinner than minimum
+! -> dividesnowlayers: subdivide snow layers that are thicker than maximum
+!
+! Initial: Yongjiu Dai, December, 2012
+! April, 2014
+! !REVISIONS:
+! Nan Wei, 06/2018: update snow hydrology above lake
+! Yongjiu Dai, 01/2023: added for SNICAR model effects for snowwater,
+! combinesnowlayers, dividesnowlayers processes by calling snowwater_snicar(),
+! SnowLayersCombine_snicar, SnowLayersDivide_snicar()
+!-----------------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denh2o, denice, hfus, tfrz, cpliq, cpice
+ USE MOD_SoilSnowHydrology
+ USE MOD_SnowLayersCombineDivide
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ logical, intent(in) :: USE_Dynamic_Lake
+
+ integer, intent(in) :: maxsnl ! maximum number of snow layers
+ integer, intent(in) :: nl_soil ! number of soil layers
+ integer, intent(in) :: nl_lake ! number of soil layers
+
+ real(r8), intent(in) :: deltim ! seconds in a time step (sec)
+ real(r8), intent(in) :: ssi ! irreducible water saturation of snow
+ real(r8), intent(in) :: wimp ! water impermeable if porosity less than wimp
+ real(r8), intent(in) :: porsl(1:nl_soil) ! volumetric soil water at saturation (porosity)
+
+ real(r8), intent(in) :: pg_rain ! rainfall incident on ground [mm/s]
+ real(r8), intent(in) :: pg_snow ! snowfall incident on ground [mm/s]
+
+ real(r8), intent(inout) :: dz_lake(1:nl_lake) ! layer thickness for lake (m)
+
+ integer, intent(in) :: imelt(maxsnl+1:0) ! signifies if node in melting (imelt = 1)
+ real(r8), intent(in) :: fiold(maxsnl+1:0) ! fraction of ice relative to the total water content at the previous time step
+ real(r8), intent(in) :: qseva ! ground surface evaporation rate (mm h2o/s)
+ real(r8), intent(in) :: qsubl ! sublimation rate from snow pack (mm H2O /s) [+]
+ real(r8), intent(in) :: qsdew ! surface dew added to snow pack (mm H2O /s) [+]
+ real(r8), intent(in) :: qfros ! ground surface frosting formation (mm H2O /s) [+]
+
+ real(r8), intent(inout) :: z_soisno (maxsnl+1:nl_soil) ! layer depth (m)
+ real(r8), intent(inout) :: dz_soisno (maxsnl+1:nl_soil) ! layer thickness depth (m)
+ real(r8), intent(inout) :: zi_soisno (maxsnl:nl_soil) ! interface depth (m)
+ real(r8), intent(inout) :: t_soisno (maxsnl+1:nl_soil) ! snow temperature (Kelvin)
+ real(r8), intent(inout) :: wice_soisno(maxsnl+1:nl_soil) ! ice lens (kg/m2)
+ real(r8), intent(inout) :: wliq_soisno(maxsnl+1:nl_soil) ! liquid water (kg/m2)
+ real(r8), intent(inout) :: t_lake (1:nl_lake) ! lake temperature (Kelvin)
+ real(r8), intent(inout) :: lake_icefrac(1:nl_lake) ! mass fraction of lake layer that is frozen
+ real(r8), intent(inout) :: qout_snowb ! rate of water out of snow bottom (mm/s)
+
+ real(r8), intent(inout) :: fseng ! total sensible heat flux (W/m**2) [+ to atm]
+ real(r8), intent(inout) :: fgrnd ! heat flux into snow / lake (W/m**2) [+ = into soil]
+
+ integer , intent(inout) :: snl ! number of snow layers
+ real(r8), intent(inout) :: scv ! snow water (mm H2O)
+ real(r8), intent(inout) :: snowdp ! snow height (m)
+ real(r8), intent(inout) :: sm ! rate of snow melt (mm H2O /s)
+
+ real(r8), intent(in) :: forc_us
+ real(r8), intent(in) :: forc_vs
+
+! SNICAR model variables
+! Aerosol Fluxes (Jan. 07, 2023 by Yongjiu Dai)
+ real(r8), intent(in) :: forc_aer ( 14 ) ! aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+
+ logical, optional, intent(in) :: urban_call ! whether it is a urban CALL
+
+ real(r8), intent(inout) :: &
+ mss_bcpho (maxsnl+1:0), &! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi (maxsnl+1:0), &! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho (maxsnl+1:0), &! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi (maxsnl+1:0), &! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 (maxsnl+1:0), &! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 (maxsnl+1:0), &! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 (maxsnl+1:0), &! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 (maxsnl+1:0) ! mass of dust species 4 in snow (col,lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+! END SNICAR model variables
+
+!-------------------------- Local Variables ----------------------------
+ logical has_snow_bef
+ integer j ! indices
+ integer lb ! lower bound of array
+
+ real(r8) xmf ! snow melt heat flux (W/m**2)
+
+ real(r8) sumsnowice ! sum of snow ice if snow layers found above unfrozen lake [kg/m&2]
+ real(r8) sumsnowliq ! sum of snow liquid if snow layers found above unfrozen lake [kg/m&2]
+ logical unfrozen ! true if top lake layer is unfrozen with snow layers above
+ real(r8) heatsum ! used in case above [J/m^2]
+ real(r8) heatrem ! used in case above [J/m^2]
+ real(r8) dw_soil
+
+ real(r8) a, b, c, d
+ real(r8) wice_lake(1:nl_lake) ! ice lens (kg/m2)
+ real(r8) wliq_lake(1:nl_lake) ! liquid water (kg/m2)
+ real(r8) t_ave, frac_
+!-----------------------------------------------------------------------
+
+ ! for runoff calculation (assumed no mass change in the land water bodies)
+ lb = snl + 1
+ qout_snowb = 0.0
+
+ IF (USE_Dynamic_Lake) THEN
+ has_snow_bef = (snl < 0)
+ ENDIF
+
+ ! ----------------------------------------------------------
+ !*[1] snow layer on frozen lake
+ ! ----------------------------------------------------------
+ IF (snl < 0) THEN
+ lb = snl + 1
+ IF (DEF_USE_SNICAR .and. .not. present(urban_call)) THEN
+ CALL snowwater_SNICAR (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),qout_snowb, &
+ forc_aer,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ELSE
+ CALL snowwater (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),qout_snowb)
+ ENDIF
+
+ ! Natural compaction and metamorphosis.
+ lb = snl + 1
+ CALL snowcompaction (lb,deltim, &
+ imelt(lb:0),fiold(lb:0),t_soisno(lb:0),&
+ wliq_soisno(lb:0),wice_soisno(lb:0),forc_us,forc_vs,dz_soisno(lb:0))
+
+ ! Combine thin snow elements
+ lb = maxsnl + 1
+ IF (DEF_USE_SNICAR .and. .not. present(urban_call)) THEN
+ CALL snowlayerscombine_SNICAR (lb, snl,&
+ z_soisno(lb:1),dz_soisno(lb:1),zi_soisno(lb-1:0),&
+ wliq_soisno(lb:1),wice_soisno(lb:1), t_soisno(lb:1),scv,snowdp, &
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0))
+ ELSE
+ CALL snowlayerscombine (lb, snl,&
+ z_soisno(lb:1),dz_soisno(lb:1),zi_soisno(lb-1:0),&
+ wliq_soisno(lb:1),wice_soisno(lb:1),&
+ t_soisno(lb:1),scv,snowdp)
+ ENDIF
+
+ ! Divide thick snow elements
+ IF (snl < 0) THEN
+ IF (DEF_USE_SNICAR .and. .not. present(urban_call)) THEN
+ CALL snowlayersdivide_SNICAR (lb,snl,z_soisno(lb:0),dz_soisno(lb:0),zi_soisno(lb-1:0),&
+ wliq_soisno(lb:0),wice_soisno(lb:0),t_soisno(lb:0) ,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ELSE
+ CALL snowlayersdivide (lb,snl,z_soisno(lb:0),dz_soisno(lb:0),zi_soisno(lb-1:0),&
+ wliq_soisno(lb:0),wice_soisno(lb:0),t_soisno(lb:0))
+ ENDIF
+ ENDIF
+
+ ! ----------------------------------------------------------
+ !*[2] check for single completely unfrozen snow layer over lake.
+ ! Modeling this ponding is unnecessary and can cause instability after the timestep
+ ! when melt is completed, as the temperature after melt can be excessive
+ ! because the fluxes were calculated with a fixed ground temperature of freezing, but the
+ ! phase change was unable to restore the temperature to freezing. (Zack Subnin 05/2010)
+ ! ----------------------------------------------------------
+
+ IF (snl == -1 .and. wice_soisno(0) == 0.) THEN
+ ! Remove layer
+ ! Take extra heat of layer and release to sensible heat in order to maintain energy conservation.
+ heatrem = cpliq*wliq_soisno(0)*(t_soisno(0) - tfrz)
+ fseng = fseng + heatrem/deltim
+ fgrnd = fgrnd - heatrem/deltim
+
+ snl = 0
+ scv = 0.
+ snowdp = 0.
+ qout_snowb = qout_snowb + wliq_soisno(0)/deltim
+ wliq_soisno(0) = 0.
+ ENDIF
+
+ ENDIF
+
+ ! ----------------------------------------------------------
+ !*[3] check for snow layers above lake with unfrozen top layer. Mechanically,
+ ! the snow will fall into the lake and melt or turn to ice. IF the top layer has
+ ! sufficient heat to melt the snow without freezing, THEN that will be done.
+ ! Otherwise, the top layer will undergo freezing, but only IF the top layer will
+ ! not freeze completely. Otherwise, let the snow layers persist and melt by diffusion.
+ ! ----------------------------------------------------------
+
+ IF (t_lake(1) > tfrz .and. snl < 0 .and. lake_icefrac(1) < 0.001) THEN ! for unfrozen lake
+ unfrozen = .true.
+ ELSE
+ unfrozen = .false.
+ ENDIF
+
+ sumsnowice = 0.
+ sumsnowliq = 0.
+ heatsum = 0.0
+ DO j = snl+1,0
+ IF (unfrozen) THEN
+ sumsnowice = sumsnowice + wice_soisno(j)
+ sumsnowliq = sumsnowliq + wliq_soisno(j)
+ heatsum = heatsum + wice_soisno(j)*cpice*(tfrz-t_soisno(j)) &
+ + wliq_soisno(j)*cpliq*(tfrz-t_soisno(j))
+ ENDIF
+ ENDDO
+
+ IF (unfrozen) THEN
+ ! changed by weinan as the subroutine newsnow_lake
+ ! Remove snow and subtract the latent heat from the top layer.
+
+ t_ave = tfrz - heatsum/(sumsnowice*cpice + sumsnowliq*cpliq)
+
+ a = heatsum
+ b = sumsnowice*hfus
+ c = (t_lake(1) - tfrz)*cpliq*denh2o*dz_lake(1)
+ d = denh2o*dz_lake(1)*hfus
+
+ ! all snow melt
+ IF (c>=a+b)THEN
+ t_lake(1) = (cpliq*(denh2o*dz_lake(1)*t_lake(1) + (sumsnowice+sumsnowliq)*tfrz) - a - b) / &
+ (cpliq*(denh2o*dz_lake(1) + sumsnowice + sumsnowliq))
+ sm = sm + scv/deltim
+ qout_snowb = qout_snowb + scv/deltim
+ scv = 0.
+ snowdp = 0.
+ snl = 0
+ ! lake partially freezing to melt all snow
+ ELSEIF(c+d >= a+b)THEN
+ t_lake(1) = tfrz
+ sm = sm + scv/deltim
+ qout_snowb = qout_snowb + scv/deltim
+ scv = 0.
+ snowdp = 0.
+ snl = 0
+ lake_icefrac(1) = (a+b-c)/d
+
+ ! snow do not melt while all lake freezing
+ ! ELSEIF(c+d < a) THEN
+ ! t_lake(1) = (c+d + cpice*(sumsnowice*t_ave+denh2o*dz_lake(1)*tfrz) + cpliq*sumsnowliq*t_ave)/&
+ ! (cpice*(sumsnowice+denh2o*dz_lake(1))+cpliq*sumsnowliq)
+ ! lake_icefrac(1) = 1.0
+ ENDIF
+ ENDIF
+
+
+ ! ----------------------------------------------------------
+ !*[4] Soil water and ending water balance
+ ! ----------------------------------------------------------
+ ! Here this consists only of making sure that soil is saturated even as it melts and
+ ! pore space opens up. Conversely, if excess ice is melting and the liquid water exceeds the
+ ! saturation value, then remove water.
+
+ dw_soil = 0.
+
+ DO j = 1, nl_soil
+ dw_soil = dw_soil + wliq_soisno(j) + wice_soisno(j)
+
+ a = wliq_soisno(j)/(dz_soisno(j)*denh2o) + wice_soisno(j)/(dz_soisno(j)*denice)
+
+ IF (a < porsl(j)) THEN
+ wliq_soisno(j) = max(0., (porsl(j)*dz_soisno(j) - wice_soisno(j)/denice)*denh2o )
+ wice_soisno(j) = max(0., (porsl(j)*dz_soisno(j) - wliq_soisno(j)/denh2o)*denice )
+ ELSE
+ wliq_soisno(j) = max(0., wliq_soisno(j) - (a - porsl(j))*denh2o*dz_soisno(j) )
+ wice_soisno(j) = max(0., (porsl(j)*dz_soisno(j) - wliq_soisno(j)/denh2o)*denice )
+ ENDIF
+
+ IF (wliq_soisno(j) > porsl(j)*denh2o*dz_soisno(j)) THEN
+ wliq_soisno(j) = porsl(j)*denh2o*dz_soisno(j)
+ wice_soisno(j) = 0.0
+ ENDIF
+
+ dw_soil = dw_soil - wliq_soisno(j) - wice_soisno(j)
+ ENDDO
+
+ IF (USE_Dynamic_Lake) THEN
+
+ IF (has_snow_bef) THEN
+ wliq_lake(1) = dz_lake(1) * (1-lake_icefrac(1)) + qout_snowb*deltim*1.e-3
+ wice_lake(1) = dz_lake(1) * lake_icefrac(1)
+ ELSE
+ wliq_lake(1) = dz_lake(1) * (1-lake_icefrac(1)) + (sm + qsdew - qseva)*deltim*1.e-3
+ wice_lake(1) = dz_lake(1) * lake_icefrac(1) + (qfros - qsubl)*deltim*1.e-3
+ IF (wliq_lake(1) < 0.) THEN
+ wice_lake(1) = wice_lake(1) + wliq_lake(1)
+ wliq_lake(1) = 0.
+ ENDIF
+ IF (wice_lake(1) < 0.) THEN
+ wliq_lake(1) = wliq_lake(1) + wice_lake(1)
+ wice_lake(1) = 0.
+ ENDIF
+ ENDIF
+
+ dz_lake(1) = wliq_lake(1) + wice_lake(1)
+ dz_lake(1) = max(dz_lake(1), 1.e-6)
+ lake_icefrac(1) = wice_lake(1) / dz_lake(1)
+ lake_icefrac(1) = min(max(lake_icefrac(1), 0.), 1.)
+
+ dz_lake(nl_lake) = dz_lake(nl_lake) + dw_soil/1.e3
+
+ IF (dz_lake(nl_lake) < 0.) THEN
+ j = nl_lake
+ DO WHILE (dz_lake(j) < 0.)
+ IF (j > 1) dz_lake(j-1) = dz_lake(j-1) + dz_lake(j)
+ dz_lake(j) = 0.
+ j = j - 1
+ IF (j == 0) EXIT
+ ENDDO
+ ENDIF
+
+ CALL adjust_lake_layer (nl_lake, dz_lake, t_lake, lake_icefrac)
+
+ ENDIF
+
+ END SUBROUTINE snowwater_lake
+
+
+
+ SUBROUTINE roughness_lake (snl,t_grnd,t_lake,lake_icefrac,forc_psrf,&
+ cur,ustar,z0mg,z0hg,z0qg)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate lake surface roughness
+!
+! Original:
+! The Community Land Model version 4.5 (CLM4.5)
+!
+! !REVISIONS:
+! Yongjiu Dai, Nan Wei, 01/2018
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz,vonkar,grav
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: snl ! number of snow layers
+ real(r8), intent(in) :: t_grnd ! ground temperature
+ real(r8), intent(in) :: t_lake(1) ! surface lake layer temperature [K]
+ real(r8), intent(in) :: lake_icefrac(1) ! surface lake layer ice mass fraction [0-1]
+ real(r8), intent(in) :: forc_psrf ! atmosphere pressure at the surface [pa]
+
+ real(r8), intent(in) :: cur ! Charnock parameter (-)
+ real(r8), intent(in) :: ustar ! u* in similarity theory [m/s]
+
+ real(r8), intent(out) :: z0mg ! roughness length over ground, momentum [m]
+ real(r8), intent(out) :: z0hg ! roughness length over ground, sensible heat [m]
+ real(r8), intent(out) :: z0qg ! roughness length over ground, latent heat [m]
+
+ real(r8), parameter :: cus = 0.1 ! empirical constant for roughness under smooth flow
+ real(r8), parameter :: kva0 = 1.51e-5 ! kinematic viscosity of air (m^2/s) at 20C and 1.013e5 Pa
+ real(r8), parameter :: prn = 0.713 ! Prandtl # for air at neutral stability
+ real(r8), parameter :: sch = 0.66 ! Schmidt # for water in air at neutral stability
+
+ real(r8) kva ! kinematic viscosity of air at ground temperature and forcing pressure
+ real(r8) sqre0 ! root of roughness Reynolds number
+!-----------------------------------------------------------------------
+
+ IF (t_grnd > tfrz .and. t_lake(1) > tfrz .and. snl == 0) THEN
+ kva = kva0 * (t_grnd/293.15)**1.5 * 1.013e5/forc_psrf ! kinematic viscosity of air
+ z0mg = max(cus*kva/max(ustar,1.e-4),cur*ustar*ustar/grav) ! momentum roughness length
+ z0mg = max(z0mg, 1.0e-5) ! This limit is redundant with current values.
+ sqre0 = (max(z0mg*ustar/kva,0.1))**0.5 ! square root of roughness Reynolds number
+ z0hg = z0mg * exp( -vonkar/prn*( 4.*sqre0 - 3.2) ) ! SH roughness length
+ z0qg = z0mg * exp( -vonkar/sch*( 4.*sqre0 - 4.2) ) ! LH roughness length
+ z0qg = max(z0qg, 1.0e-5) ! Minimum allowed roughness length for unfrozen lakes
+ z0hg = max(z0hg, 1.0e-5) ! set low so it is only to avoid floating point exceptions
+ ELSEIF (snl == 0) THEN ! frozen lake with ice, and no snow cover
+ z0mg = 0.001 ! z0mg won't have changed
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+ ELSE ! use roughness over snow
+ z0mg = 0.0024 ! z0mg won't have changed
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+ ENDIF
+
+ END SUBROUTINE roughness_lake
+
+
+
+ SUBROUTINE hConductivity_lake(nl_lake,snl,t_grnd,&
+ z_lake,t_lake,lake_icefrac,rhow,&
+ dlat,ustar,z0mg,lakedepth,depthcrit,tk_lake, savedtke1)
+
+!-----------------------------------------------------------------------
+! Diffusivity and implied thermal "conductivity" = diffusivity * cwat
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz,tkwat,tkice,tkair,&
+ vonkar,grav,cpliq,cpice,cpair,denh2o,denice
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: nl_lake ! number of soil layers
+ integer, intent(in) :: snl ! number of snow layers
+ real(r8), intent(in) :: t_grnd ! ground surface temperature [k]
+ real(r8), intent(in) :: z_lake(nl_lake) ! lake node depth (middle point of layer) (m)
+ real(r8), intent(in) :: t_lake(nl_lake) ! lake temperature (kelvin)
+ real(r8), intent(in) :: lake_icefrac(nl_lake) ! lake mass fraction of lake layer that is frozen
+ real(r8), intent(in) :: rhow(nl_lake) ! density of water (kg/m**3)
+
+ real(r8), intent(in) :: dlat ! latitude (radians)
+ real(r8), intent(in) :: ustar ! u* in similarity theory [m/s]
+ real(r8), intent(in) :: z0mg ! roughness length over ground, momentum [m]
+ real(r8), intent(in) :: lakedepth ! column lake depth (m)
+ real(r8), intent(in) :: depthcrit ! (m) Depth beneath which to enhance mixing
+
+
+ real(r8), intent(out) :: tk_lake(nl_lake) ! thermal conductivity at layer node [W/(m K)]
+ real(r8), intent(out) :: savedtke1 ! top level eddy conductivity (W/mK)
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) kme(nl_lake) ! molecular + eddy diffusion coefficient (m**2/s)
+ real(r8) cwat ! specific heat capacity of water (j/m**3/kelvin)
+ real(r8) den ! used in calculating ri
+ real(r8) drhodz ! d [rhow] /dz (kg/m**4)
+ real(r8) fangkm ! (m^2/s) extra diffusivity based on Fang & Stefan 1996
+ real(r8) ke ! eddy diffusion coefficient (m**2/s)
+ real(r8) km ! molecular diffusion coefficient (m**2/s)
+ real(r8) ks ! coefficient for calculation of decay of eddy diffusivity with depth
+ real(r8) n2 ! brunt-vaisala frequency (/s**2)
+ real(r8) num ! used in calculating ri
+ real(r8) ri ! richardson number
+ real(r8) tkice_eff ! effective conductivity since layer depth is constant
+ real(r8) tmp !
+ real(r8) u2m ! 2 m wind speed (m/s
+ real(r8) ws ! surface friction velocity (m/s)
+
+ real(r8), parameter :: mixfact = 5. ! Mixing enhancement factor.
+ real(r8), parameter :: p0 = 1. ! neutral value of turbulent prandtl number
+
+
+ integer j
+
+! -------------------------------------------------------------------
+
+ cwat = cpliq*denh2o
+ tkice_eff = tkice * denice/denh2o ! effective conductivity since layer depth is constant
+ km = tkwat/cwat ! a constant (molecular diffusivity)
+ u2m = max(0.1,ustar/vonkar*log(2./z0mg))
+ ws = 1.2e-03 * u2m
+ ks = 6.6 * sqrt( abs(sin(dlat)) ) * (u2m**(-1.84))
+
+ DO j = 1, nl_lake-1
+ drhodz = (rhow(j+1)-rhow(j)) / (z_lake(j+1)-z_lake(j))
+ n2 = max(7.5e-5, grav / rhow(j) * drhodz)
+ num = 40. * n2 * (vonkar*z_lake(j))**2
+ tmp = -2.*ks*z_lake(j) ! to avoid underflow computing
+ IF(tmp < -40.) tmp = -40. !
+ den = max( (ws**2) * exp(tmp), 1.e-10 )
+ ri = ( -1. + sqrt( max(1.+num/den, 0.) ) ) / 20.
+
+ IF ((t_grnd > tfrz .and. t_lake(1) > tfrz .and. snl == 0) ) THEN
+ tmp = -ks*z_lake(j) ! to avoid underflow computing
+ IF(tmp < -40.) tmp = -40. !
+ ke = vonkar*ws*z_lake(j)/p0 * exp(tmp) / (1.+37.*ri*ri)
+ kme(j) = km + ke
+
+ fangkm = 1.039e-8_r8 * max(n2,7.5e-5)**(-0.43) ! Fang & Stefan 1996, citing Ellis et al 1991
+ kme(j) = kme(j) + fangkm
+
+ IF (lakedepth >= depthcrit) THEN
+ kme(j) = kme(j) * mixfact ! Mixing enhancement factor for lake deep than 25m.
+ ENDIF
+ tk_lake(j) = kme(j)*cwat
+ ELSE
+ kme(j) = km
+ fangkm = 1.039e-8 * max(n2,7.5e-5)**(-0.43)
+ kme(j) = kme(j) + fangkm
+ IF (lakedepth >= depthcrit) THEN
+ kme(j) = kme(j) * mixfact
+ ENDIF
+ tk_lake(j) = kme(j)*cwat*tkice_eff / ((1.-lake_icefrac(j))*tkice_eff &
+ + kme(j)*cwat*lake_icefrac(j))
+ ENDIF
+ ENDDO
+
+ kme(nl_lake) = kme(nl_lake-1)
+ savedtke1 = kme(1)*cwat
+
+ IF ((t_grnd > tfrz .and. t_lake(1) > tfrz .and. snl == 0) ) THEN
+ tk_lake(nl_lake) = tk_lake(nl_lake-1)
+ ELSE
+ tk_lake(nl_lake) = kme(nl_lake)*cwat*tkice_eff / ( (1.-lake_icefrac(nl_lake))*tkice_eff &
+ + kme(nl_lake)*cwat*lake_icefrac(nl_lake) )
+ ENDIF
+
+ END SUBROUTINE hConductivity_lake
+
+
+ SUBROUTINE adjust_lake_layer (nl_lake, dz_lake, t_lake, lake_icefrac)
+
+ USE MOD_Const_Physical
+ IMPLICIT NONE
+
+ integer, intent(in) :: nl_lake
+ real(r8), intent(inout) :: dz_lake (nl_lake) ! lake layer thickness (m)
+ real(r8), intent(inout) :: t_lake (nl_lake) ! lake temperature (kelvin)
+ real(r8), intent(inout) :: lake_icefrac(nl_lake) ! lake mass fraction of lake layer that is frozen
+
+ ! Local Variables
+ integer :: i, j
+ real(r8) :: wdsrfm, depthratio, resi, resj
+ real(r8) :: ticesum, tliqsum, wicesum, wliqsum, olp, tliq, tice, a, b, c, d
+ real(r8) :: dz_lake_new (nl_lake)
+ real(r8) :: t_lake_new (nl_lake)
+ real(r8) :: lake_icefrac_new (nl_lake)
+ real(r8), parameter :: dzlak(10) = (/0.1, 1., 2., 3., 4., 5., 7., 7., 10.45, 10.45/) ! m
+
+ wdsrfm = sum(dz_lake)
+
+ IF(wdsrfm > 1.)THEN
+ depthratio = wdsrfm / sum(dzlak(1:nl_lake))
+ dz_lake_new(1) = dzlak(1)
+ dz_lake_new(2:nl_lake-1) = dzlak(2:nl_lake-1)*depthratio
+ dz_lake_new(nl_lake) = dzlak(nl_lake)*depthratio - (dz_lake_new(1) - dzlak(1)*depthratio)
+ ELSEIF(wdsrfm > 0. .and. wdsrfm <= 1.)THEN
+ dz_lake_new(:) = wdsrfm / nl_lake
+ ENDIF
+
+ j = 1
+ resj = dz_lake(j)
+
+ DO i = 1, nl_lake
+
+ ticesum = 0.
+ tliqsum = 0.
+ wicesum = 0.
+ wliqsum = 0.
+
+ resi = dz_lake_new(i)
+ DO WHILE (resi > 1.e-8)
+
+ olp = min(resi, resj)
+ ticesum = ticesum + olp * lake_icefrac(j) * t_lake(j)
+ wicesum = wicesum + olp * lake_icefrac(j)
+ tliqsum = tliqsum + olp * (1-lake_icefrac(j)) * t_lake(j)
+ wliqsum = wliqsum + olp * (1-lake_icefrac(j))
+
+ resi = resi - olp
+ resj = resj - olp
+
+ IF (resj == 0.) THEN
+ IF (j == nl_lake) THEN
+ EXIT
+ ELSE
+ j = j + 1
+ resj = dz_lake(j)
+ ENDIF
+ ENDIF
+
+ ENDDO
+
+ IF (wicesum > 0.) tice = ticesum / wicesum
+ IF (wliqsum > 0.) tliq = tliqsum / wliqsum
+
+ IF ((wliqsum > 0.) .and. (wicesum > 0.)) THEN
+
+ a = cpliq*wliqsum*(tliq-tfrz)
+ b = cpice*wicesum*(tfrz-tice)
+ c = wicesum*hfus
+ d = wliqsum*hfus
+
+ IF (a >= b + c) THEN
+ wicesum = 0.
+ wliqsum = dz_lake_new(i)
+ t_lake_new(i) = tfrz + (a-b-c)/(wliqsum*cpliq)
+ ELSEIF (a >= b) THEN
+ wicesum = wicesum - (a-b)/hfus
+ t_lake_new(i) = tfrz
+ ELSEIF (a + d < b) THEN
+ wicesum = dz_lake_new(i)
+ t_lake_new(i) = tfrz - (b-a-d)/(wicesum*cpice)
+ ELSE ! (b-d <= a < b)
+ wicesum = wicesum + (b-a)/hfus
+ t_lake_new(i) = tfrz
+ ENDIF
+
+ ELSEIF (wliqsum > 0.) THEN
+ t_lake_new(i) = tliq
+ ELSEIF (wicesum > 0.) THEN
+ t_lake_new(i) = tice
+ ENDIF
+
+ lake_icefrac_new(i) = wicesum / dz_lake_new(i)
+
+ ENDDO
+
+ dz_lake = dz_lake_new
+ lake_icefrac = lake_icefrac_new
+ t_lake = t_lake_new
+
+ END SUBROUTINE adjust_lake_layer
+
+
+END MODULE MOD_Lake
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafInterception.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafInterception.F90
new file mode 100644
index 0000000000..2628092057
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafInterception.F90
@@ -0,0 +1,2458 @@
+#include
+MODULE MOD_LeafInterception
+! -----------------------------------------------------------------
+! !DESCRIPTION:
+! For calculating vegetation canopy precipitation interception.
+!
+! This module computes canopy interception and evaporation fluxes.
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+ !* :SUBROUTINE:"LEAF_interception_CoLM2014" : Leaf interception and drainage schemes based on colm2014 version
+ !* :SUBROUTINE:"LEAF_interception_CoLM202x" : Leaf interception and drainage schemes besed on new colm version (under development)
+ !* :SUBROUTINE:"LEAF_interception_CLM4" : Leaf interception and drainage schemes modified from CLM4
+ !* :SUBROUTINE:"LEAF_interception_CLM5" : Leaf interception and drainage schemes modified from CLM5
+ !* :SUBROUTINE:"LEAF_interception_NOAHMP" : Leaf interception and drainage schemes modified from Noah-MP
+ !* :SUBROUTINE:"LEAF_interception_MATSIRO" : Leaf interception and drainage schemes modified from MATSIRO 2021 version
+ !* :SUBROUTINE:"LEAF_interception_VIC" : Leaf interception and drainage schemes modified from VIC
+ !* :SUBROUTINE:"LEAF_interception_JULES" : Leaf interception and drainage schemes modified from JULES
+ !* :SUBROUTINE:"LEAF_interception_pftwrap" : wrapper for pft land use classification
+
+!REVISION HISTORY:
+!----------------
+ ! 2026.01 Zhongwang Wei: Fully revise CLM4,5,Noah-MP,MATSIRO,VIC and JULES schemes.
+ ! 2024.04 Hua Yuan: add option to account for vegetation snow process based on Niu et al., 2004
+ ! 2023.07 Hua Yuan: remove wrapper PC by using PFT leaf interception
+ ! 2023.06 Shupeng Zhang @ SYSU
+ ! 2023.02.23 Zhongwang Wei @ SYSU
+ ! 2021.12.12 Zhongwang Wei @ SYSU
+ ! 2020.10.21 Zhongwang Wei @ SYSU
+ ! 2019.06 Hua Yuan: 1) add wrapper for PFT and PC, and 2) remove sigf by using lai+sai
+ ! 2014.04 Yongjiu Dai
+ ! 2002.08.31 Yongjiu Dai
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz, denh2o, denice, cpliq, cpice, hfus
+ USE MOD_Namelist, only: DEF_Interception_scheme, DEF_VEG_SNOW
+
+ IMPLICIT NONE
+
+ real(r8), parameter :: CICE = 2.094E06 !specific heat capacity of ice (j/m3/k)
+ real(r8), parameter :: bp = 20.
+ real(r8), parameter :: CWAT = 4.188E06 !specific heat capacity of water (j/m3/k)
+ real(r8), parameter :: pcoefs(2,2) = reshape((/20.0_r8, 0.206e-8_r8, 0.0001_r8, 0.9999_r8/), (/2,2/))
+
+ ! Minimum significant precipitation rate threshold [mm/s]
+ ! Used across all schemes for numerical stability
+ real(r8), parameter :: PRECIP_THRESHOLD = 1.0e-8_r8
+
+ ! Tolerance for interception water balance checks [mm]
+ ! Used by check_interception_balance subroutine under CoLMDEBUG
+ real(r8), parameter :: INTERCEPTION_BALANCE_TOL = 1.0e-5_r8
+
+ !----------------------- Dummy argument --------------------------------
+ real(r8) :: satcap ! maximum allowed water on canopy [mm]
+ real(r8) :: satcap_rain ! maximum allowed rain on canopy [mm]
+ real(r8) :: satcap_snow ! maximum allowed snow on canopy [mm]
+ real(r8) :: lsai ! sum of leaf area index and stem area index [-]
+ real(r8) :: chiv ! leaf angle distribution factor
+ real(r8) :: ppc ! convective precipitation in time-step [mm]
+ real(r8) :: ppl ! large-scale precipitation in time-step [mm]
+ real(r8) :: p0 ! precipitation in time-step [mm]
+ real(r8) :: fpi ! coefficient of interception
+ real(r8) :: fpi_rain ! coefficient of interception of rain
+ real(r8) :: fpi_snow ! coefficient of interception of snow
+ real(r8) :: alpha_rain ! coefficient of interception of rain
+ real(r8) :: alpha_snow ! coefficient of interception of snow
+ real(r8) :: pinf ! interception of precipitation in time step [mm]
+ real(r8) :: tti_rain ! direct rain throughfall in time step [mm]
+ real(r8) :: tti_snow ! direct snow throughfall in time step [mm]
+ real(r8) :: tex_rain ! canopy rain drainage in time step [mm]
+ real(r8) :: tex_snow ! canopy snow drainage in time step [mm]
+ real(r8) :: vegt ! sigf*lsai
+ real(r8) :: xs ! proportion of the grid area where the intercepted rainfall
+ ! plus the preexisting canopy water storage
+ real(r8) :: unl_snow_temp,U10,unl_snow_wind,unl_snow
+ real(r8) :: ap, cp, aa1, bb1, exrain, arg, w
+ real(r8) :: thru_rain, thru_snow
+ real(r8) :: xsc_rain, xsc_snow
+
+ real(r8) :: fvegc ! vegetation fraction
+ real(r8) :: FT ! the temperature factor for snow unloading
+ real(r8) :: FV ! the wind factor for snow unloading
+ real(r8) :: ICEDRIP ! snow unloading
+
+ real(r8) :: ldew_smelt
+ real(r8) :: ldew_frzc
+ real(r8) :: FP
+ real(r8) :: int_rain
+ real(r8) :: int_snow
+
+CONTAINS
+
+ SUBROUTINE LEAF_interception_CoLM2014 (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,qintr,qintr_rain,qintr_snow)
+!DESCRIPTION
+!===========
+ ! Calculation of interception and drainage of precipitation
+ ! the treatment are based on Sellers et al. (1996)
+
+!Original Author:
+!-------------------
+ !canopy interception scheme modified by Yongjiu Dai based on Sellers et al. (1996)
+
+!References:
+!-------------------
+ !---Dai, Y., Zeng, X., Dickinson, R.E., Baker, I., Bonan, G.B., BosiloVICh,
+ ! M.G., Denning, A.S., Dirmeyer, P.A., Houser, P.R., Niu, G. and Oleson,
+ ! K.W., 2003. The common land model. Bulletin of the American
+ ! Meteorological Society, 84(8), pp.1013-1024.
+
+ !---Lawrence, D.M., Thornton, P.E., Oleson, K.W. and Bonan, G.B., 2007. The
+ ! partitioning of evapotranspiration into transpiration, soil evaporation,
+ ! and canopy evaporation in a GCM: Impacts on land-atmosphere interaction.
+ ! Journal of Hydrometeorology, 8(4), pp.862-880.
+
+ !---Oleson, K., Dai, Y., Bonan, B., BosiloVIChm, M., Dickinson, R.,
+ ! Dirmeyer, P., Hoffman, F., Houser, P., Levis, S., Niu, G.Y. and
+ ! Thornton, P., 2004. Technical description of the community land model
+ ! (CLM).
+
+ !---Sellers, P.J., Randall, D.A., Collatz, G.J., Berry, J.A., Field, C.B.,
+ ! Dazlich, D.A., Zhang, C., Collelo, G.D. and Bounoua, L., 1996. A revised
+ ! land surface parameterization (SiB2) for atmospheric GCMs. Part I:
+ ! Model formulation. Journal of climate, 9(4), pp.676-705.
+
+ !---Sellers, P.J., Tucker, C.J., Collatz, G.J., Los, S.O., Justice, C.O.,
+ ! Dazlich, D.A. and Randall, D.A., 1996. A revised land surface
+ ! parameterization (SiB2) for atmospheric GCMs. Part II: The generation of
+ ! global fields of terrestrial biophysical parameters from satellite data.
+ ! Journal of climate, 9(4), pp.706-737.
+
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ !---2024.04.16 Hua Yuan: add option to account for vegetation snow process based on Niu et al., 2004
+ !---2023.02.21 Zhongwang Wei @ SYSU : Snow and rain interception
+ !---2021.12.08 Zhongwang Wei @ SYSU
+ !---2019.06 Hua Yuan: remove sigf and USE lai+sai for judgement.
+ !---2014.04 Yongjiu Dai
+ !---2002.08.31 Yongjiu Dai
+!=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler ! irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: bifall !bulk density of newly fallen dry snow [kg/m3]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(in) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of water on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+!-----------------------------------------------------------------------
+
+ IF (lai+sai > 1e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+ satcap = dewmx*vegt
+ satcap_rain = satcap
+ satcap_snow = 6.6*(0.27+46./bifall)*vegt ! Niu et al., 2004
+ satcap_snow = 48.*satcap ! Simple one without snow density input
+
+ p0 = (prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler)*deltim
+ ppc = (prc_rain + prc_snow)*deltim
+ ppl = (prl_rain + prl_snow + qflx_irrig_sprinkler)*deltim
+
+ w = ldew+p0
+ IF (tleaf > tfrz) THEN
+ xsc_rain = max(0., ldew-satcap)
+ xsc_snow = 0.
+ ELSE
+ xsc_rain = 0.
+ xsc_snow = max(0., ldew-satcap)
+ ENDIF
+
+ ldew = ldew - (xsc_rain + xsc_snow)
+
+ !TODO-done: account for vegetation snow
+ IF ( DEF_VEG_SNOW ) THEN
+ xsc_rain = max(0., ldew_rain-satcap_rain)
+ xsc_snow = max(0., ldew_snow-satcap_snow)
+ ldew_rain = ldew_rain - xsc_rain
+ ldew_snow = ldew_snow - xsc_snow
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ap = pcoefs(2,1)
+ cp = pcoefs(2,2)
+
+ IF (p0 > 1.e-8) THEN
+ ap = ppc/p0 * pcoefs(1,1) + ppl/p0 * pcoefs(2,1)
+ cp = ppc/p0 * pcoefs(1,2) + ppl/p0 * pcoefs(2,2)
+
+ !----------------------------------------------------------------------
+ ! proportional saturated area (xs) and leaf drainage(tex)
+ !-----------------------------------------------------------------------
+ chiv = chil
+ IF ( abs(chiv) .le. 0.01 ) chiv = 0.01
+ aa1 = 0.5 - 0.633 * chiv - 0.33 * chiv * chiv
+ bb1 = 0.877 * ( 1. - 2. * aa1 )
+ exrain = aa1 + bb1
+
+ ! coefficient of interception
+ ! set fraction of potential interception to max 0.25 (Lawrence et al. 2007)
+ ! assume alpha_rain = alpha_snow
+ alpha_rain = 0.25
+ fpi = alpha_rain * ( 1.-exp(-exrain*lsai) )
+ tti_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * ( 1.-fpi )
+ tti_snow = (prc_snow+prl_snow)*deltim * ( 1.-fpi )
+
+ xs = 1.
+ IF (p0*fpi>1.e-9) THEN
+ arg = (satcap-ldew)/(p0*fpi*ap) - cp/ap
+ IF (arg>1.e-9) THEN
+ xs = -1./bp * log( arg )
+ xs = min( xs, 1. )
+ xs = max( xs, 0. )
+ ENDIF
+ ENDIF
+
+ ! assume no fall down of the intercepted snowfall in a time step
+ ! drainage
+ tex_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * fpi * (ap/bp*(1.-exp(-bp*xs))+cp*xs) &
+ - max(0., (satcap-ldew)) * xs
+ tex_rain = max( tex_rain, 0. )
+ ! Ensure physical constraint: tex_rain + tti_rain <= total rain input
+ tex_rain = min( tex_rain, (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim - tti_rain )
+ tex_snow = 0.
+
+ ! 04/11/2024, yuan:
+ !TODO-done: account for snow on vegetation,
+ IF ( DEF_VEG_SNOW ) THEN
+
+ ! re-calculate leaf rain drainage using ldew_rain
+
+ xs = 1.
+ IF (p0*fpi>1.e-9) THEN
+ arg = (satcap_rain-ldew_rain)/(p0*fpi*ap) - cp/ap
+ IF (arg>1.e-9) THEN
+ xs = -1./bp * log( arg )
+ xs = min( xs, 1. )
+ xs = max( xs, 0. )
+ ENDIF
+ ENDIF
+
+ tex_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * fpi * (ap/bp*(1.-exp(-bp*xs))+cp*xs) &
+ - max(0., (satcap_rain-ldew_rain)) * xs
+ tex_rain = max( tex_rain, 0. )
+ ! Ensure physical constraint: tex_rain + tti_rain <= total rain input
+ tex_rain = min( tex_rain, (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim - tti_rain )
+
+ ! re-calculate the snow loading rate
+
+ fvegc = 1. - exp(-0.52*lsai)
+ FP = (ppc + ppl) / (10.*ppc + ppl)
+ qintr_snow = fvegc * (prc_snow+prl_snow) * FP
+ qintr_snow = min (qintr_snow, (satcap_snow-ldew_snow)/deltim * (1.-exp(-(prc_snow+prl_snow)*deltim/satcap_snow)) )
+ qintr_snow = max (qintr_snow, 0.)
+
+ ! snow unloading rate
+
+ FT = max(0.0, (tleaf - tfrz) / 1.87e5)
+ FV = sqrt(forc_us*forc_us + forc_vs*forc_vs) / 1.56e5
+ tex_snow = max(0., ldew_snow/deltim) * (FV+FT)
+ tti_snow = (1.0-fvegc)*(prc_snow+prl_snow) + (fvegc*(prc_snow+prl_snow) - qintr_snow)
+
+ ! rate -> mass
+
+ tti_snow = tti_snow * deltim
+ tex_snow = tex_snow * deltim
+ ENDIF
+
+#if (defined CoLMDEBUG)
+ IF (tex_rain+tex_snow+tti_rain+tti_snow-p0 > 1.e-10 .and. .not.DEF_VEG_SNOW) THEN
+ write(6,*) 'tex_ + tti_ > p0 in interception code : ',ldew,tex_rain,tex_snow,tti_rain,tti_snow,p0
+ ENDIF
+#endif
+
+ ELSE
+ ! all intercepted by canopy leaves for very small precipitation
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ ENDIF
+
+ !----------------------------------------------------------------------
+ ! total throughfall (thru) and store augmentation
+ !----------------------------------------------------------------------
+
+ thru_rain = tti_rain + tex_rain
+ thru_snow = tti_snow + tex_snow
+ pinf = p0 - (thru_rain + thru_snow)
+ ldew = ldew + pinf
+
+ !TODO-done: IF DEF_VEG_SNOW, update ldew_rain, ldew_snow
+ IF ( DEF_VEG_SNOW ) THEN
+ ldew_rain = ldew_rain + (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim - thru_rain
+ ldew_snow = ldew_snow + (prc_snow+prl_snow)*deltim - thru_snow
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ pg_rain = (xsc_rain + thru_rain) / deltim
+ pg_snow = (xsc_snow + thru_snow) / deltim
+ qintr = pinf / deltim
+
+ qintr_rain = prc_rain + prl_rain + qflx_irrig_sprinkler - thru_rain / deltim
+ qintr_snow = prc_snow + prl_snow - thru_snow / deltim
+
+#if (defined CoLMDEBUG)
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code: '
+ write(6,*) w, ldew, (pg_rain+pg_snow)*deltim, satcap
+ CALL abort
+ ENDIF
+
+ IF (DEF_VEG_SNOW .and. abs(ldew-ldew_rain-ldew_snow) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code when DEF_VEG_SNOW: '
+ write(6,*) ldew, ldew_rain, ldew_snow
+ CALL abort
+ ENDIF
+#endif
+
+ ELSE
+ ! 07/15/2023, yuan: #bug found for ldew value reset.
+ !NOTE: this bug should exist in other interception schemes @Zhongwang.
+ IF (ldew > 0.) THEN
+ IF (tleaf > tfrz) THEN
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew/deltim
+ pg_snow = prc_snow + prl_snow
+ ELSE
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ pg_snow = prc_snow + prl_snow + ldew/deltim
+ ENDIF
+ ELSE
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ pg_snow = prc_snow + prl_snow
+ ENDIF
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+
+ ENDIF
+
+ END SUBROUTINE LEAF_interception_CoLM2014
+
+ SUBROUTINE LEAF_interception_CoLM202x (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,&
+ qintr,qintr_rain,qintr_snow)
+!DESCRIPTION
+!===========
+ ! Calculation of interception and drainage of precipitation (under development)
+ ! the scheme developed by Zhongwang wei @ SYSU (not finished yet)
+
+!Original Author:
+!-------------------
+ !---Zhongwang Wei @ SYSU
+
+!References:
+!-------------------
+ !---Zhong, F., Jiang, S., van Dijk, A.I., Ren, L., Schellekens, J. and Miralles, D.G., 2022.
+ ! Revisiting large-scale interception patterns constrained by a synthesis of global experimental
+ ! data. Hydrology and Earth System Sciences, 26(21), pp.5647-5667.
+ !---
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ !---2023.04.30 Zhongwang Wei @ SYSU : Snow and rain interception
+!=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler ! irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(in) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of water on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+ IF (lai+sai > 1e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+ satcap = dewmx*vegt
+
+ p0 = (prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler)*deltim
+ ppc = (prc_rain+prc_snow)*deltim
+ ppl = (prl_rain+prl_snow+qflx_irrig_sprinkler)*deltim
+
+ w = ldew+p0
+
+ IF (tleaf > tfrz) THEN
+ xsc_rain = max(0., ldew-satcap)
+ xsc_snow = 0.
+ ELSE
+ xsc_rain = 0.
+ xsc_snow = max(0., ldew-satcap)
+ ENDIF
+ ldew = ldew - (xsc_rain + xsc_snow)
+
+ ap = pcoefs(2,1)
+ cp = pcoefs(2,2)
+
+ IF (p0 > 1.e-8) THEN
+ ap = ppc/p0 * pcoefs(1,1) + ppl/p0 * pcoefs(2,1)
+ cp = ppc/p0 * pcoefs(1,2) + ppl/p0 * pcoefs(2,2)
+ !----------------------------------------------------------------------
+ ! proportional saturated area (xs) and leaf drainage(tex)
+ !-----------------------------------------------------------------------
+ chiv = chil
+ IF ( abs(chiv) .le. 0.01 ) chiv = 0.01
+ aa1 = 0.5 - 0.633 * chiv - 0.33 * chiv * chiv
+ bb1 = 0.877 * ( 1. - 2. * aa1 )
+ exrain = aa1 + bb1
+
+ ! coefficient of interception
+ ! set fraction of potential interception to max 0.25 (Lawrence et al. 2007)
+ alpha_rain = 0.25
+ fpi = alpha_rain * ( 1.-exp(-exrain*lsai) )
+ tti_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * ( 1.-fpi )
+ tti_snow = (prc_snow+prl_snow)*deltim * ( 1.-fpi )
+
+ xs = 1.
+ IF (p0*fpi>1.e-9) THEN
+ arg = (satcap-ldew)/(p0*fpi*ap) - cp/ap
+ IF (arg>1.e-9) THEN
+ xs = -1./bp * log( arg )
+ xs = min( xs, 1. )
+ xs = max( xs, 0. )
+ ENDIF
+ ENDIF
+
+ ! assume no fall down of the intercepted snowfall in a time step drainage
+ tex_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * fpi * (ap/bp*(1.-exp(-bp*xs))+cp*xs) &
+ - max(0., (satcap-ldew)) * xs
+ tex_rain = max( tex_rain, 0. )
+ ! Ensure physical constraint: tex_rain + tti_rain <= total rain input
+ tex_rain = min( tex_rain, (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim - tti_rain )
+ tex_snow = 0.
+
+#if (defined CoLMDEBUG)
+ IF (tex_rain+tex_snow+tti_rain+tti_snow-p0 > 1.e-10) THEN
+ write(6,*) 'tex_ + tti_ > p0 in interception code : '
+ ENDIF
+#endif
+
+ ELSE
+ ! all intercepted by canopy leves for very small precipitation
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ ENDIF
+
+ !----------------------------------------------------------------------
+ ! total throughfall (thru) and store augmentation
+ !----------------------------------------------------------------------
+
+ thru_rain = tti_rain + tex_rain
+ thru_snow = tti_snow + tex_snow
+ pinf = p0 - (thru_rain + thru_snow)
+ ldew = ldew + pinf
+
+ pg_rain = (xsc_rain + thru_rain) / deltim
+ pg_snow = (xsc_snow + thru_snow) / deltim
+ qintr = pinf / deltim
+
+ qintr_rain = prc_rain + prl_rain + qflx_irrig_sprinkler - thru_rain / deltim
+ qintr_snow = prc_snow + prl_snow - thru_snow / deltim
+
+
+#if (defined CoLMDEBUG)
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code : '
+ write(6,*) w, ldew, (pg_rain+pg_snow)*deltim, satcap
+ CALL abort
+ ENDIF
+
+ CALL check_interception_balance('CoLM202x', &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+#endif
+
+ ELSE
+ ! 07/15/2023, Hua Yuan: bug found for ldew value reset when vegetation disappears
+ ! Yuan's fix: Release canopy water based on temperature
+ ! Note: CoLM202x doesn't separate rain/snow storage, so temperature-based
+ ! release is appropriate (no phase conservation issue for unified storage)
+ IF (ldew > 0.) THEN
+ IF (tleaf > tfrz) THEN
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew/deltim
+ pg_snow = prc_snow + prl_snow
+ ELSE
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ pg_snow = prc_snow + prl_snow + ldew/deltim
+ ENDIF
+ ELSE
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ pg_snow = prc_snow + prl_snow
+ ENDIF
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+ ENDIF
+ END SUBROUTINE LEAF_interception_CoLM202x
+
+ SUBROUTINE LEAF_interception_CLM4 (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+!DESCRIPTION
+!===========
+ ! Canopy interception following CLM4.5 official implementation
+ ! - Interception efficiency: fpi = 0.25*(1-exp(-0.5*LSAI))
+ ! - Drainage method: Simple bucket overflow (when storage exceeds capacity)
+ ! - Verified against CLM4.5 source code: CTSM-clm4_5_18_r272/src_clm40/biogeophys/Hydrology1Mod.F90
+ !
+ ! Key features:
+ ! - No pre-drainage step (unlike some earlier CoLM versions)
+ ! - No spatial heterogeneity consideration (uniform canopy capacity)
+ ! - Immediate overflow drainage when capacity is exceeded
+
+!Original Author:
+!-------------------
+ !Lawrence, D.M.
+
+!References:
+!-------------------
+ !---Lawrence, D.M., Thornton, P.E., Oleson, K.W. and Bonan, G.B., 2007.
+ ! The partitioning of evapotranspiration into transpiration, soil evaporation,
+ ! and canopy evaporation in a GCM: Impacts on land-atmosphere interaction. Journal of Hydrometeorology, 8(4), pp.862-880.
+ !---Oleson, K.W., Lawrence, D.M., Bonan, G.B., Drewniak, B., Huang, M., Koven, C.D., Levis, S., Li, F., Riley, W.J., Subin, Z.M. and Swenson, S.C., 2013.
+ ! Technical description of version 4.5 of the Community Land Model (CLM). NCAR Technical Note NCAR/TN-503+ STR.
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ ! 2023.02.21 Zhongwang Wei @ SYSU : Snow and rain interception
+ ! 2021.12.08 Zhongwang Wei @ SYSU
+ ! 2014.04 Yongjiu Dai
+ ! 2002.08.31 Yongjiu Dai
+!=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(in) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of water on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+ IF (lai+sai > 1e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+ satcap = dewmx*vegt
+
+ p0 = (prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler)*deltim
+ ppc = (prc_rain+prc_snow)*deltim
+ ppl = (prl_rain+prl_snow+qflx_irrig_sprinkler)*deltim
+
+ w = ldew+p0
+
+ IF (tleaf > tfrz) THEN
+ xsc_rain = max(0., ldew-satcap)
+ xsc_snow = 0.
+ ELSE
+ xsc_rain = 0.
+ xsc_snow = max(0., ldew-satcap)
+ ENDIF
+
+ ldew = ldew - (xsc_rain + xsc_snow)
+
+ IF (p0 > 1.e-8) THEN
+ exrain =0.5
+ ! coefficient of interception
+ ! set fraction of potential interception to max 0.25 (Lawrence et al. 2007)
+ alpha_rain = 0.25
+ fpi = alpha_rain * ( 1.-exp(-exrain*lsai) )
+ tti_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * ( 1.-fpi )
+ tti_snow = (prc_snow+prl_snow)*deltim * ( 1.-fpi )
+
+ ! assume no fall down of the intercepted snowfall in a time step
+ ! drainage
+ tex_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * fpi + ldew - satcap
+ tex_rain = max(tex_rain, 0. )
+ ! Ensure physical constraint: tex_rain + tti_rain <= total rain input
+ tex_rain = min( tex_rain, (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim - tti_rain )
+ tex_snow = 0.
+
+#if (defined CoLMDEBUG)
+ IF (tex_rain+tex_snow+tti_rain+tti_snow-p0 > 1.e-10) THEN
+ write(6,*) 'tex_ + tti_ > p0 in interception code : '
+ ENDIF
+#endif
+
+
+ ELSE
+ ! all intercepted by canopy leaves for very small precipitation
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ ENDIF
+
+ !----------------------------------------------------------------------
+ ! total throughfall (thru) and store augmentation
+ !----------------------------------------------------------------------
+ thru_rain = tti_rain + tex_rain
+ thru_snow = tti_snow + tex_snow
+ pinf = p0 - (thru_rain + thru_snow)
+ ldew = ldew + pinf
+
+ pg_rain = (xsc_rain + thru_rain) / deltim
+ pg_snow = (xsc_snow + thru_snow) / deltim
+ qintr = pinf / deltim
+
+ qintr_rain = prc_rain + prl_rain + qflx_irrig_sprinkler - thru_rain / deltim
+ qintr_snow = prc_snow + prl_snow - thru_snow / deltim
+
+
+#if (defined CoLMDEBUG)
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code : '
+ write(6,*) w, ldew, (pg_rain+pg_snow)*deltim, satcap
+ CALL abort
+ ENDIF
+#endif
+
+ ELSE
+ ! 07/15/2023, yuan: #bug found for ldew value reset.
+ IF (ldew > 0.) THEN
+ IF (tleaf > tfrz) THEN
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew/deltim
+ pg_snow = prc_snow + prl_snow
+ ELSE
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ pg_snow = prc_snow + prl_snow + ldew/deltim
+ ENDIF
+ ELSE
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ pg_snow = prc_snow + prl_snow
+ ENDIF
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+ ENDIF
+
+ END SUBROUTINE LEAF_interception_CLM4
+
+ SUBROUTINE LEAF_interception_CLM5 (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,&
+ qintr,qintr_rain,qintr_snow)
+
+!DESCRIPTION
+!===========
+ ! Canopy interception following CLM5.0 official implementation
+ ! - Separate treatment for rain and snow interception
+ ! - Rain interception: fpi = tanh(LSAI) [or 0.25*(1-exp(-0.5*LSAI))]
+ ! - Snow interception: fpi = 1-exp(-0.5*LSAI)
+ ! - Liquid water capacity: 0.1*(LAI+SAI) mm
+ ! - Snow capacity: 6.0*(LAI+SAI) mm
+ ! - Simple bucket overflow drainage based on temperature
+ ! - Snow unloading due to wind and temperature
+ ! - Verified against CLM5 source: CanopyHydrologyMod.F90
+ !
+ ! Key features:
+ ! - No pre-drainage step (fixed from earlier version)
+ ! - Drainage based on storage, not interception (critical fix)
+ ! - Temperature-dependent rain/snow drainage
+ ! - Physics-based snow unloading
+
+!Original Author:
+!-------------------
+ !Lawrence, D.M.
+
+!References:
+!-------------------
+ !---Lawrence, D.M., Thornton, P.E., Oleson, K.W. and Bonan, G.B., 2007.
+ ! The partitioning of evapotranspiration into transpiration, soil evaporation,
+ ! and canopy evaporation in a GCM: Impacts on land-atmosphere interaction. Journal of Hydrometeorology, 8(4), pp.862-880.
+ !---Lawrence, D.M., Fisher, R.A., Koven, C.D., Oleson, K.W., Swenson, S.C., Bonan, G., Collier, N., Ghimire, B.,
+ ! van Kampenhout, L., Kennedy, D. and Kluzek, E., 2019. The Community Land Model version 5:
+ ! Description of new features, benchmarking, and impact of forcing uncertainty.
+ ! Journal of Advances in Modeling Earth Systems, 11(12), pp.4245-4287.
+ !---Fan, Y., Meijide, A., Lawrence, D.M., Roupsard, O., Carlson, K.M., Chen, H.Y.,
+ ! Röll, A., Niu, F. and Knohl, A., 2019. Reconciling canopy interception parameterization
+ ! and rainfall forcing frequency in the Community Land Model for simulating evapotranspiration
+ ! of rainforests and oil palm plantations in Indonesia. Journal of Advances in Modeling Earth Systems, 11(3), pp.732-751.
+
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ ! 2023.02.21 Zhongwang Wei @ SYSU
+ ! 2021.12.08 Zhongwang Wei @ SYSU
+!=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(in) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of water on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+ real(r8) :: xsnorun, xliqrun,qflx_prec_intr_rain,qflx_prec_intr_snow
+
+ IF (lai+sai > 1e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+ p0 = (prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler)*deltim
+
+ ! Ensure ldew is consistent with components at entry
+ ! CLM5 operates on ldew_rain/ldew_snow and sets ldew = ldew_rain + ldew_snow at exit
+ ! At entry from initialization or restart, ldew may be inconsistent
+ ldew = ldew_rain + ldew_snow
+
+ w = ldew+p0 ! For mass balance check
+
+ ! Canopy capacity - CLM5 official values
+ ! Verified against CanopyHydrologyMod.F90 lines 320, 329-330
+ satcap_rain = dewmx*vegt ! liquid water capacity = 0.1*(LAI+SAI)
+ satcap_snow = satcap_rain*60.0 ! snow capacity = 6.0*(LAI+SAI)
+
+ IF(p0 > 1.e-8) THEN
+ ! Interception efficiency - CLM5 formulas
+ ! Rain: CLM5 line 323 (tanh option) or line 325 (exponential option)
+ ! Snow: CLM5 line 332
+ ! Note: CoLM uses tanh for rain; CLM5 default is exponential (CLM4.5)
+ alpha_rain = 1.0
+ alpha_snow = 1.0
+ fpi_rain = alpha_rain * tanh(lsai)
+ fpi_snow = alpha_snow * ( 1.-exp(-0.5*lsai) )
+
+ ! Direct throughfall - CLM5 lines 334, 337, 341
+ tti_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * ( 1.-fpi_rain )
+ tti_snow = (prc_snow+prl_snow)*deltim * ( 1.-fpi_snow )
+
+ ! Intercepted precipitation - CLM5 line 345
+ qflx_prec_intr_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * fpi_rain
+ qflx_prec_intr_snow = (prc_snow+prl_snow)*deltim * fpi_snow
+
+ ! Water storage of intercepted precipitation - CLM5 lines 347-348
+ ! Add interception to storage BEFORE calculating drainage
+ ldew_rain = max(0., ldew_rain + qflx_prec_intr_rain)
+ ldew_snow = max(0., ldew_snow + qflx_prec_intr_snow)
+
+ ! Initialize drainage
+ tex_rain = 0.
+ tex_snow = 0.
+ unl_snow = 0.
+
+ ! Snow unloading due to wind and temperature - CLM5 lines ~420-450
+ ! (in CLM5 this is in separate unloading section, but physics is same)
+ IF(ldew_snow > 1.e-8) THEN
+ U10 = sqrt(forc_us*forc_us+forc_vs*forc_vs)
+ unl_snow_temp = ldew_snow*(tleaf-tfrz)/(1.87*1.e5)
+ unl_snow_temp = max(unl_snow_temp,0.0)
+ unl_snow_wind = U10*ldew_snow/(1.56*1.e5)
+ unl_snow_wind = max(unl_snow_wind,0.0)
+ unl_snow = unl_snow_temp+unl_snow_wind
+ unl_snow = min(unl_snow,ldew_snow)
+ ldew_snow = ldew_snow - unl_snow
+ ENDIF
+
+ ! Simple bucket overflow drainage - CLM5 lines 367-379
+ ! Separate handling for rain and snow based on temperature
+ IF (tleaf > tfrz) THEN
+ ! Above freezing: liquid water drainage
+ xliqrun = max(0., (ldew_rain - satcap_rain)/deltim)
+ IF (xliqrun > 0.) THEN
+ tex_rain = xliqrun * deltim
+ ldew_rain = satcap_rain
+ ENDIF
+ ELSE
+ ! Below freezing: snow falling off canopy
+ xsnorun = max(0., (ldew_snow - satcap_snow)/deltim)
+ IF (xsnorun > 0.) THEN
+ tex_snow = xsnorun * deltim
+ ldew_snow = satcap_snow
+ ENDIF
+ ENDIF
+
+ ELSE
+ ! No precipitation - no interception or drainage
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ unl_snow = 0.
+ ENDIF
+
+ !----------------------------------------------------------------------
+ ! Total water reaching ground and interception
+ !----------------------------------------------------------------------
+ thru_rain = tti_rain + tex_rain
+ thru_snow = tti_snow + tex_snow + unl_snow
+ ldew = ldew_rain + ldew_snow
+
+ pg_rain = thru_rain / deltim
+ pg_snow = thru_snow / deltim
+ qintr = (p0 - thru_rain - thru_snow) / deltim
+ qintr_rain = (prc_rain + prl_rain + qflx_irrig_sprinkler) - thru_rain / deltim
+ qintr_snow = (prc_snow + prl_snow) - thru_snow / deltim
+
+#if (defined CoLMDEBUG)
+ ! Mass balance check
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'Mass balance error in CLM5 interception:'
+ write(6,*) 'Error:', w, 'ldew:', ldew, 'outflow:', (pg_rain+pg_snow)*deltim
+ write(6,*) 'satcap_rain:', satcap_rain, 'satcap_snow:', satcap_snow
+ CALL abort
+ ENDIF
+
+ CALL check_interception_balance('CLM5', &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+#endif
+
+ ELSE
+ ! 07/15/2023, Hua Yuan: bug found for ldew value reset when vegetation disappears
+ ! 2026-01-16 improvement: Maintain phase conservation for rain/snow separated schemes
+ ! Yuan's original fix released water based on temperature, which violates phase conservation
+ ! for schemes that separate rain and snow storage (ldew_rain vs ldew_snow)
+ !
+ ! Yuan's original code (2023-07-15):
+ ! IF (ldew > 0.) THEN
+ ! IF (tleaf > tfrz) THEN
+ ! pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew/deltim
+ ! pg_snow = prc_snow + prl_snow
+ ! ELSE
+ ! pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ ! pg_snow = prc_snow + prl_snow + ldew/deltim
+ ! ENDIF
+ ! ELSE
+ ! pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler
+ ! pg_snow = prc_snow + prl_snow
+ ! ENDIF
+ !
+ ! Improved version: Release liquid and solid water separately to preserve phase states
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew_rain/deltim
+ pg_snow = prc_snow + prl_snow + ldew_snow/deltim
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+ ENDIF
+
+ END SUBROUTINE LEAF_interception_CLM5
+
+ SUBROUTINE LEAF_interception_NOAHMP(deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf, &
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,qintr,qintr_rain,qintr_snow)
+!DESCRIPTION
+!===========
+ ! Interception and drainage of precipitation
+ ! the treatment are modified from Noah-MP 5.0
+
+!Original Author:
+!-------------------
+ !---Guo-Yue Niu
+
+!References:
+!-------------------
+ !---Yang, M., Zuo, R., Li, X. and Wang, L., 2019. Improvement test for the canopy interception parameterization scheme
+ ! in the community land model. Sola, 15, pp.166-171.
+ !---Niu, G.Y., Yang, Z.L., Mitchell, K.E., Chen, F., Ek, M.B., Barlage, M., Kumar, A.,
+ ! Manning, K., Niyogi, D., Rosero, E. and Tewari, M., 2011. The community Noah land
+ ! surface model with multiparameterization options (Noah‐MP): 1. Model description and evaluation
+ ! with local‐scale measurements. Journal of Geophysical Research: Atmospheres, 116(D12).
+ !---He, C., Valayamkunnath, P., Barlage, M., Chen, F., Gochis, D., Cabell, R., Schneider, T.,
+ ! Rasmussen, R., Niu, G.Y., Yang, Z.L. and Niyogi, D., 2023. Modernizing the open-source
+ ! community Noah-MP land surface model (version 5.0) with enhanced modularity,
+ ! interoperability, and applicability. EGUsphere, 2023, pp.1-31.
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ ! 2026.02.11 Zhongwang Wei @ SYSU - Added input clamping, comment fixes
+ ! 2023.02.21 Zhongwang Wei @ SYSU
+ ! 2021.12.08 Zhongwang Wei @ SYSU
+!=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(inout) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of liquid on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of solid (frozen) on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+ ! Local variables
+ real(r8) :: PrecipAreaFrac !fraction of gridcell receiving precipitation [-]
+ real(r8) :: BDFALL
+ IF (lai+sai > 1e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+ ! Calculate vegetation fraction from LAI (alternative to input VegFrac)
+ fvegc=max(0.05,1.0-exp(-0.52*lsai))
+
+ ! Maximum canopy water - Noah-MP lines 82, 105
+ ! Note: Official Noah-MP uses VegFrac as input variable
+ ! CoLM uses fvegc calculated from LAI, which is also physically reasonable
+ satcap_rain = fvegc * dewmx*vegt
+ BDFALL = 67.92+51.25*EXP(MIN(2.5,(tleaf-273.15))/2.59)
+ satcap_snow = fvegc * 6.6*(0.27+46./BDFALL) * lsai
+ satcap_snow = max(0.0,satcap_snow)
+
+ ! Input clamping: prevent negative precipitation (numerical noise)
+ ! from causing mass balance failures
+ p0 = MAX(0.0_r8, prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler) * deltim
+ ppc = MAX(0.0_r8, prc_rain + prc_snow) * deltim
+ ppl = MAX(0.0_r8, p0 - ppc)
+
+ ! Estimate PrecipAreaFrac based on precipitation type - Noah-MP line 47
+ ! Convective precipitation typically covers ~10% of gridcell
+ ! Stratiform precipitation typically covers ~100% of gridcell
+ IF (p0 > 1.e-8) THEN
+ PrecipAreaFrac = (0.1*ppc + 1.0*ppl) / p0
+ PrecipAreaFrac = max(0.1, min(1.0, PrecipAreaFrac)) ! constrain to [0.1, 1.0]
+ ELSE
+ PrecipAreaFrac = 1.0
+ ENDIF
+
+ ! Ensure ldew is consistent with components at entry
+ ! NoahMP modifies ldew in-place; if ldew != ldew_rain + ldew_snow
+ ! at entry (e.g., from initialization or restart), mass balance drifts
+ ldew = ldew_rain + ldew_snow
+
+ w = ldew+p0
+
+ ! Initialize excess water variables
+ xsc_rain = 0.0
+ xsc_snow = 0.0
+
+ !snow unloading - Noah-MP lines 113-120
+ IF (ldew_snow>1.e-8) THEN
+ FT = MAX(0.0,(tair - 270.15) / 1.87E5)
+ FV = SQRT(forc_us*forc_us + forc_vs*forc_vs) / 1.56E5
+ ICEDRIP = MAX(0.,ldew_snow) * (FV+FT) !MB: removed /DT
+ ICEDRIP = MIN(ICEDRIP,ldew_snow)
+ xsc_snow = xsc_snow+ICEDRIP
+ ldew_snow = ldew_snow - ICEDRIP
+ ENDIF
+
+ ! phase change and excess !
+ IF (tleaf > tfrz) THEN
+ IF (ldew_snow>1.e-8) THEN
+ ldew_smelt = MIN(ldew_snow,(tleaf-tfrz)*CICE*ldew_snow/DENICE/(HFUS))
+ ldew_smelt = MAX(ldew_smelt,0.0)
+ ldew_snow = ldew_snow-ldew_smelt
+ ldew_rain = ldew_rain+ldew_smelt
+ xsc_rain = xsc_rain + MAX(0., ldew_rain-satcap_rain)
+ ldew_rain = ldew_rain - MAX(0., ldew_rain-satcap_rain)
+ ENDIF
+ ! tleaf = fvegc*tfrz+ (1.0-fwet)*tleaf
+ ELSE
+ IF (ldew_rain>1.e-8) THEN
+ ldew_frzc = MIN(ldew_rain,(tfrz-tleaf)*CWAT*ldew_rain/DENH2O/(HFUS))
+ ldew_frzc = MAX(ldew_frzc,0.0)
+ ldew_snow = ldew_snow+ldew_frzc
+ ldew_rain = ldew_rain-ldew_frzc
+ xsc_snow = xsc_snow + MAX(0., ldew_snow-satcap_snow)
+ ldew_snow = ldew_snow - MAX(0., ldew_snow-satcap_snow)
+ ENDIF
+ !tleaf = fvegc*tfrz+ (1.0-fwet)*tleaf
+ ENDIF
+ ! Resync ldew with components after phase change (CoLM2014 pattern)
+ ldew = ldew_rain + ldew_snow
+
+ IF (p0 > 1.e-8) THEN
+
+ ! Throughfall: direct precipitation through vegetation gaps - Noah-MP lines 91, 119
+ tti_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim * ( 1.-fvegc )
+ tti_snow = (prc_snow+prl_snow)*deltim * ( 1.-fvegc )
+
+ ! Interception and drip calculation - Noah-MP lines 86-90, 109-118
+ ! Interception rate [mm/s]
+ int_rain = fvegc * (prc_rain+prl_rain+qflx_irrig_sprinkler) * PrecipAreaFrac ! max interception capability
+ int_rain = min(int_rain, (satcap_rain-ldew_rain)/deltim * &
+ (1.0-exp(-(prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim/satcap_rain)))
+ int_rain = max(0., int_rain)
+
+ int_snow = fvegc * (prc_snow+prl_snow) * PrecipAreaFrac ! max interception capability
+ int_snow = min(int_snow, (satcap_snow-ldew_snow)/deltim * &
+ (1.0-exp(-(prc_snow+prl_snow)*deltim/satcap_snow)))
+ int_snow = max(0., int_snow)
+
+ ! Drip: excess precipitation on vegetation that cannot be intercepted
+ tex_rain = (prc_rain+prl_rain+qflx_irrig_sprinkler)*fvegc*deltim - int_rain*deltim
+ tex_snow = (prc_snow+prl_snow)*fvegc*deltim - int_snow*deltim
+#if (defined CoLMDEBUG)
+ IF (tex_rain+tex_snow+tti_rain+tti_snow-p0 > 1.e-10) THEN
+ write(6,*) 'tex_ + tti_ > p0 in interception code : '
+ ENDIF
+#endif
+ ELSE
+ ! all intercepted by canopy leaves for very small precipitation
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ ENDIF
+
+ !BDFALL = 67.92+51.25*EXP(MIN(2.5,(SFCTMP-TFRZ))/2.59)
+
+ !----------------------------------------------------------------------
+ ! total throughfall (thru) and store augmentation
+ !----------------------------------------------------------------------
+
+ thru_rain = tti_rain + tex_rain
+ thru_snow = tti_snow + tex_snow
+ pinf = p0 - (thru_rain + thru_snow)
+
+ ! Update rain/snow components following CoLM2014 pattern (lines 322-324)
+ ldew_rain = ldew_rain + (prc_rain+prl_rain+qflx_irrig_sprinkler)*deltim - thru_rain
+ ldew_snow = ldew_snow + (prc_snow+prl_snow)*deltim - thru_snow
+ ldew = ldew_rain + ldew_snow
+
+ pg_rain = (xsc_rain + thru_rain) / deltim
+ pg_snow = (xsc_snow + thru_snow) / deltim
+ qintr = pinf / deltim
+
+ qintr_rain = prc_rain + prl_rain + qflx_irrig_sprinkler - thru_rain / deltim
+ qintr_snow = prc_snow + prl_snow - thru_snow / deltim
+
+#if (defined CoLMDEBUG)
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code : '
+ write(6,*) w, ldew, (pg_rain+pg_snow)*deltim !, satcap
+ CALL abort
+ ENDIF
+
+ CALL check_interception_balance('NoahMP', &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+#endif
+
+ ELSE
+ ! 07/15/2023, Hua Yuan: bug found for ldew value reset when vegetation disappears
+ ! Release canopy water separately by phase to preserve phase conservation
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew_rain/deltim
+ pg_snow = prc_snow + prl_snow + ldew_snow/deltim
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+
+ ENDIF
+
+ END SUBROUTINE LEAF_interception_NOAHMP
+
+
+ SUBROUTINE LEAF_interception_MATSIRO (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf, &
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,qintr,&
+ qintr_rain,qintr_snow)
+!DESCRIPTION
+!===========
+ ! Interception and drainage of precipitation
+ ! the treatment are modified from MATSIRO 6 (under development)
+
+!Original Author:
+!-------------------
+ !---MATSIRO6 document writing team∗
+
+!References:
+!-------------------
+ !---Tatebe, H., Ogura, T., Nitta, T., Komuro, Y., Ogochi, K., Takemura, T., Sudo, K., Sekiguchi, M.,
+ ! Abe, M., Saito, F. and Chikira, M., 2019. Description and basic evaluation of simulated mean state,
+ ! internal variability, and climate sensitivity in MIROC6. Geoscientific Model Development, 12(7), pp.2727-2765. 116(D12).
+ !---Takata, K., Emori, S. and Watanabe, T., 2003. Development of the minimal advanced treatments of surface interaction and
+ ! runoff. Global and planetary Change, 38(1-2), pp.209-222.
+ !---Guo, Q., Kino, K., Li, S., Nitta, T., Takeshima, A., Suzuki, K.T., Yoshida, N. and Yoshimura, K., 2021.
+ ! Description of MATSIRO6.
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ ! 2026.02.11 Zhongwang Wei @ SYSU - Added input clamping, comment fixes
+ ! 2023.02.21 Zhongwang Wei @ SYSU
+ ! 2021.12.08 Zhongwang Wei @ SYSU
+!=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(inout) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of liquid on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of solid (frozen) on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+ !local
+ real(r8) :: fint, Ac, dewmx_MATSIRO,ldew_rain_s, ldew_snow_s,ldew_rain_n, ldew_snow_n
+ real(r8) :: tex_rain_n,tex_rain_s,tex_snow_n,tex_snow_s,tti_rain_n,tti_rain_s,tti_snow_n,tti_snow_s
+
+ !the canopy water capacity per leaf area index is set to 0.2mm
+ dewmx_MATSIRO = 0.2
+ !the fraction of the convective precipitation area is assumed to be uniform (0.1)
+ Ac = 0.1
+
+ IF (lai+sai > 1e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+ ! Input clamping: prevent negative precipitation (numerical noise)
+ ! from causing mass balance failures
+ p0 = MAX(0.0_r8, prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler) * deltim
+ ppc = MAX(0.0_r8, prc_rain + prc_snow) * deltim
+ ppl = MAX(0.0_r8, p0 - ppc)
+
+ satcap_rain = dewmx_MATSIRO*vegt
+ satcap_snow = dewmx_MATSIRO*vegt
+
+ ! Ensure ldew is consistent with components at entry
+ ! MATSIRO modifies ldew in-place; inconsistency at entry propagates to output
+ ldew = ldew_rain + ldew_snow
+
+ w = ldew+p0
+
+ xsc_rain = max(0., ldew_rain-satcap_rain)
+ xsc_snow = max(0., ldew_snow-satcap_snow)
+
+ ldew_rain = ldew_rain-xsc_rain
+ ldew_snow = ldew_snow-xsc_snow
+ ! phase change and excess !
+ IF (tleaf > tfrz) THEN
+ IF (ldew_snow>1.e-8) THEN
+ ldew_smelt = MIN(ldew_snow,(tleaf-tfrz)*CICE*ldew_snow/DENICE/(HFUS))
+ ldew_smelt = MAX(ldew_smelt,0.0)
+ ldew_snow = ldew_snow-ldew_smelt
+ ldew_rain = ldew_rain+ldew_smelt
+ xsc_rain = xsc_rain + MAX(0., ldew_rain-satcap_rain)
+ ldew_rain = ldew_rain - MAX(0., ldew_rain-satcap_rain)
+ ENDIF
+ ! tleaf = fvegc*tfrz+ (1.0-fwet)*tleaf
+ ELSE
+ IF (ldew_rain>1.e-8) THEN
+ ldew_frzc = MIN(ldew_rain,(tfrz-tleaf)*CWAT*ldew_rain/DENH2O/(HFUS))
+ ldew_frzc = MAX(ldew_frzc,0.0)
+ ldew_snow = ldew_snow+ldew_frzc
+ ldew_rain = ldew_rain-ldew_frzc
+ xsc_snow = xsc_snow + MAX(0., ldew_snow-satcap_snow)
+ ldew_snow = ldew_snow - MAX(0., ldew_snow-satcap_snow)
+ ENDIF
+ !tleaf = fvegc*tfrz+ (1.0-fwet)*tleaf
+ ENDIF
+ ! Resync ldew with components after phase change (CoLM2014 pattern)
+ ldew = ldew_rain + ldew_snow
+
+ IF (p0 > 1.e-8) THEN
+ ! Interception efficiency - MATSIRO formulation
+ ! MATSIRO uses simple linear saturation following Takata et al. (2003)
+ ! Reference: Takata, K., Emori, S., and Watanabe, T. (2003). "Development of the
+ ! minimal advanced treatments of surface interaction and runoff", Global and
+ ! Planetary Change, 38, 209-222, doi:10.1016/S0921-8181(03)00030-4
+ ! Verified against official MATSIRO source code (matsiro.f90):
+ ! fctint = min(grlai(ud), 1.d0)
+ ! When LAI+SAI ≤ 1: efficiency equals LAI+SAI
+ ! When LAI+SAI > 1: efficiency saturates at 100%
+ fpi_rain = min(1.0, lai+sai)
+ fpi_snow = min(1.0, lai+sai)
+
+ !-----------------------------------------------------------------------
+ ! Storm area
+ !-----------------------------------------------------------------------
+ ldew_rain_s = ldew_rain + ((prl_rain+qflx_irrig_sprinkler) * fpi_rain + prc_rain * fpi_rain / Ac) * deltim
+ ldew_snow_s = ldew_snow + (prl_snow * fpi_snow + prc_snow * fpi_snow / Ac) * deltim
+ !
+ tti_rain_s = (prl_rain+qflx_irrig_sprinkler + prc_rain/Ac) * (1.d0-fpi_rain) * deltim
+ tti_snow_s = (prl_snow + prc_snow/Ac) * (1.d0-fpi_snow) * deltim
+
+ !
+ ! Rutter exponential drainage formula (Rutter et al. 1975)
+ ! tex = overflow + k1 * exp(k2 * storage)
+ !
+ ! Physical constants from Rutter et al. (1975):
+ ! - cwb_adrp1 = 1.14e-11 [m/s]: Base dripping coefficient
+ ! Represents minimum drainage rate when canopy is near saturation
+ ! - cwb_adrp2 = 3.7e3 [1/m]: Exponential saturation factor
+ ! Controls how rapidly drainage increases with storage
+ ! Higher values = more sensitive to storage amount
+ ! - min(50.0, ...): Overflow protection to prevent EXP(large_number)
+ ! Caps exponent at 50 to avoid numerical overflow
+ ! (exp(50) ≈ 5e21, near double precision limit)
+ !
+ ! Unit conversion: 1.14e-11 [m/s] × 1000 [mm/m] = 1.14e-8 [mm/s]
+ !
+ tex_rain_s = max(ldew_rain_s - satcap_rain, 0.d0) + (1.14d-11)*1000.*deltim*exp(min(50.0d0, min(ldew_rain_s,satcap_rain)/1000.* 3.7d3))
+ tex_rain_s = min(tex_rain_s, ldew_rain_s)
+ ldew_rain_s = ldew_rain_s - tex_rain_s
+
+ ! Snow drainage using same Rutter formula (see rain drainage comments above)
+ tex_snow_s = max(ldew_snow_s - satcap_snow, 0.d0) + (1.14d-11)*1000.*deltim*exp(min(50.0d0, min(ldew_snow_s,satcap_snow)/1000.0* 3.7d3))
+ tex_snow_s = min(tex_snow_s, ldew_snow_s)
+ ldew_snow_s = ldew_snow_s - tex_snow_s
+
+ !-------------------------------------------------------------------------
+ ! Non-storm area
+ !-------------------------------------------------------------------------
+ ldew_rain_n = ldew_rain + (prl_rain+qflx_irrig_sprinkler) * fpi_rain * deltim
+ ldew_snow_n = ldew_snow + prl_snow * fpi_snow * deltim
+
+ !
+ tti_rain_n = (prl_rain+qflx_irrig_sprinkler) * (1.d0-fpi_rain) * deltim
+ tti_snow_n = (prl_snow) * (1.d0-fpi_snow) * deltim
+
+ ! Rutter drainage for non-storm area (same formula as storm area)
+ tex_rain_n = max(ldew_rain_n - satcap_rain, 0.d0) + (1.14d-11)*1000.*deltim*exp(min(50.0d0, min(ldew_rain_n,satcap_rain)/1000.* 3.7d3))
+ tex_rain_n = min(tex_rain_n, ldew_rain_n)
+ ldew_rain_n = ldew_rain_n - tex_rain_n
+
+ ! Snow drainage for non-storm area (same Rutter formula)
+ tex_snow_n = max(ldew_snow_n - satcap_snow, 0.d0) + (1.14d-11)*1000.*deltim*exp(min(50.0d0, min(ldew_snow_n,satcap_snow)/1000.* 3.7d3))
+ tex_snow_n = min(tex_snow_n, ldew_snow_n)
+ ldew_snow_n = ldew_snow_n - tex_snow_n
+ !-------------------------------------------------------------------------
+ !-------------------------------------------------------------------------
+ ! Average
+ !-------------------------------------------------------------------------
+ ldew_rain = ldew_rain_n + (ldew_rain_s - ldew_rain_n) * Ac
+ ldew_snow = ldew_snow_n + (ldew_snow_s - ldew_snow_n) * Ac
+ ldew_rain = max(0.0,ldew_rain)
+ ldew_snow = max(0.0,ldew_snow)
+
+ tti_rain = tti_rain_n*(1-Ac)+tti_rain_s*Ac
+ tti_snow = tti_snow_n+(tti_snow_s-tti_snow_n) * Ac
+ tti_rain = max(0.0,tti_rain)
+ tti_snow = max(0.0,tti_snow)
+
+ tex_rain = tex_rain_n+(tex_rain_s-tex_rain_n)*Ac
+ tex_snow = tex_snow_n+(tex_snow_s-tex_snow_n)*Ac
+ tex_rain = max(0.0,tex_rain)
+ tex_snow = max(0.0,tex_snow)
+ !-------------------------------------------------------------------------
+
+! NOTE: The check "tex+tti > p0" is not applicable to MATSIRO scheme.
+! Rutter exponential drainage drains pre-existing canopy water (ldew),
+! so tex+tti can legitimately exceed p0. The real mass balance check
+! is performed below (w residual check with abort).
+
+ ELSE
+ ! all intercepted by canopy leaves for very small precipitation
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ ENDIF
+
+ !BDFALL = 67.92+51.25*EXP(MIN(2.5,(SFCTMP-TFRZ))/2.59)
+
+ !----------------------------------------------------------------------
+ ! total throughfall (thru) and store augmentation
+ !----------------------------------------------------------------------
+
+ thru_rain = tti_rain + tex_rain
+ thru_snow = tti_snow + tex_snow
+ pinf = p0 - (thru_rain + thru_snow)
+
+ ! Resync ldew with components following CoLM2014 pattern (line 324)
+ ! In the precip case, ldew_rain/ldew_snow were updated via weighted average
+ ! In the no-precip case, they remain at post-phase-change values (tiny p0 < 1e-8 ignored)
+ ldew = ldew_rain + ldew_snow
+
+ pg_rain = (xsc_rain + thru_rain) / deltim
+ pg_snow = (xsc_snow + thru_snow) / deltim
+ qintr = pinf / deltim
+
+ qintr_rain = prc_rain + prl_rain + qflx_irrig_sprinkler - thru_rain / deltim
+ qintr_snow = prc_snow + prl_snow - thru_snow / deltim
+#if (defined CoLMDEBUG)
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code : '
+ write(6,*) w, ldew, (pg_rain+pg_snow)*deltim !, satcap
+ CALL abort
+ ENDIF
+
+ CALL check_interception_balance('MATSIRO', &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+#endif
+
+ ELSE
+ ! No vegetation: all precipitation passes through, release any stored water
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew_rain/deltim
+ pg_snow = prc_snow + prl_snow + ldew_snow/deltim
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+ ENDIF
+ END SUBROUTINE LEAF_interception_MATSIRO
+
+ SUBROUTINE LEAF_interception_VIC (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf, &
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+!DESCRIPTION
+!===========
+ ! Calculation of interception and drainage of precipitation
+ ! the treatment are based on VIC 5.0 (under development)
+
+!Original Author:
+!-------------------
+ !---Hamman, J.J. AND Liang X.
+
+!References:
+!-------------------
+ !---Hamman, J.J., Nijssen, B., Bohn, T.J., Gergel, D.R. and Mao, Y., 2018.
+ ! The Variable Infiltration Capacity model version 5 (VIC-5): Infrastructure
+ ! improvements for new applications and reproducibility. Geoscientific Model Development,
+ ! 11(8), pp.3481-3496.
+ !---Liang, X., Lettenmaier, D.P., Wood, E.F. and Burges, S.J., 1994.
+ ! A simple hydrologically based model of land surface water and energy fluxes
+ ! for general circulation models. Journal of Geophysical Research: Atmospheres, 99(D7),
+ ! pp.14415-14428.
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!REVISION HISTORY
+!----------------
+ ! 2026.02.11 Zhongwang Wei @ SYSU - Added input clamping, comment fixes
+ ! 2023.02.21 Zhongwang Wei @ SYSU
+ ! 2021.12.08 Zhongwang Wei @ SYSU
+!=======================================================================
+
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(inout) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of liquid on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of solid (frozen) on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+ real(r8) :: Imax1,Lr,Snow,Rain,DeltaSnowInt,Wind,BlownSnow,sigf_safe
+ real(r8) :: MaxInt,Overload,IntRainFract,IntSnowFract,ldew_smelt,MaxWaterInt
+
+ IF (lai+sai > 1e-6 .and. sigf > 1.e-6) THEN
+ lsai = lai + sai
+ vegt = lsai
+
+ ! Ensure ldew is consistent with components at entry (grid-scale)
+ ! VIC sets ldew = ldew_rain + ldew_snow at exit; inconsistency at entry
+ ! from initialization or restart causes mass balance check to fail
+ ldew = ldew_rain + ldew_snow
+
+ ! VIC vegetation fraction handling (snow_intercept.c line 132-133)
+ ! Convert grid-scale storage to per-vegetation values
+ ! Physical meaning: Storage variables represent water on vegetated fraction only
+ IF (sigf > 1.e-6) THEN
+ sigf_safe = max(sigf, 0.01)
+ ldew_rain = ldew_rain / sigf_safe
+ ldew_snow = ldew_snow / sigf_safe
+ ENDIF
+
+ !the maximum bearing capacity of the tree regardless of air temp (Imax1)
+ Imax1=4.0*lsai*0.0005 *1000.0 ! in mm
+ MaxInt=0.1*lsai
+ IF (tair>-272.15) THEN
+ Lr=4.0
+ ELSEIF (tair<=-272.15 .and. tair>=-270.15) THEN
+ Lr=1.5*(tair-273.15)+5.5
+ ELSE
+ Lr=1.0
+ ENDIF
+
+ satcap_snow=0.0005 *Lr *lsai * 1000.0 ! in mm !!!
+ !/* Calculate total liquid water capacity on branches and in intercepted snow */
+ ! VIC physical design: Total liquid water capacity includes two components:
+ ! 1. Liquid water held in snow matrix (mature/ripe snow at 0°C)
+ ! 2. Liquid water on leaf surfaces
+ !
+ ! Physical basis: Intercepted snow is a porous medium that can retain liquid water
+ ! in its interstitial spaces when it reaches 0°C (mature/ripe snow state).
+ ! This is a fundamental concept in snow hydrology (Colbeck 1972, Jordan 1991).
+ !
+ ! Formula: satcap_rain = SNOW_LIQUID_WATER_CAPACITY * ldew_snow + MaxInt
+ ! - Term 1 (0.035*ldew_snow): Irreducible liquid water content in snow matrix
+ ! The 0.035 coefficient represents typical irreducible water saturation (~3.5% by mass)
+ ! This same parameter is used for ground snowpack in VIC (snow_melt.c, ice_melt.c)
+ ! - Term 2 (MaxInt=0.1*lsai): Liquid water on leaf/branch surfaces
+ !
+ ! Physical meaning: When intercepted snow becomes ripe (0°C), it can simultaneously hold:
+ ! - Solid ice framework (ldew_snow)
+ ! - Liquid water in pore spaces (up to 3.5% of snow mass)
+ ! - Additional liquid water on vegetation surfaces (MaxInt)
+ ! When snow completely melts (ldew_snow=0), capacity reverts to leaf-only (MaxInt)
+ !
+ ! Reference: Andreadis et al. (2009) "Modeling snow accumulation and ablation
+ ! processes in forested environments", WRR, doi:10.1029/2008WR007042
+ !
+ ! Rain capacity = snow matrix water retention + leaf surface capacity
+ ! When snow melts completely (ldew_snow→0), capacity reverts to just MaxInt
+ satcap_rain = 0.035 * ldew_snow + MaxInt ! in mm
+
+ ! Input clamping: prevent negative precipitation (numerical noise)
+ ! from causing mass balance failures
+ p0 = MAX(0.0_r8, prc_rain + prc_snow + prl_rain + prl_snow + qflx_irrig_sprinkler) * deltim
+ ppc = MAX(0.0_r8, prc_rain + prc_snow) * deltim
+ ppl = MAX(0.0_r8, p0 - ppc)
+ w = ldew+p0
+
+ xsc_rain = max(0., ldew_rain-satcap_rain)
+ xsc_snow = max(0., ldew_snow-satcap_snow)
+
+ ldew_rain = ldew_rain-xsc_rain
+ ldew_snow = ldew_snow-xsc_snow
+ ! phase change and excess !
+ IF (tleaf > tfrz) THEN
+ IF (ldew_snow>1.e-8) THEN
+ ldew_smelt = MIN(ldew_snow,(tleaf-tfrz)*CICE*ldew_snow/DENICE/(HFUS))
+ ldew_smelt = MAX(ldew_smelt,0.0)
+ ldew_snow = ldew_snow-ldew_smelt
+ ldew_rain = ldew_rain+ldew_smelt
+ xsc_rain = xsc_rain + MAX(0., ldew_rain-satcap_rain)
+ ldew_rain = ldew_rain - MAX(0., ldew_rain-satcap_rain)
+ ENDIF
+ ! tleaf = fvegc*tfrz+ (1.0-fwet)*tleaf
+ ELSE
+ IF (ldew_rain>1.e-8) THEN
+ ldew_frzc = MIN(ldew_rain,(tfrz-tleaf)*CWAT*ldew_rain/DENH2O/(HFUS))
+ ldew_frzc = MAX(ldew_frzc,0.0)
+ ldew_snow = ldew_snow+ldew_frzc
+ ldew_rain = ldew_rain-ldew_frzc
+ xsc_snow = xsc_snow + MAX(0., ldew_snow-satcap_snow)
+ ldew_snow = ldew_snow - MAX(0., ldew_snow-satcap_snow)
+ ENDIF
+ !tleaf = fvegc*tfrz+ (1.0-fwet)*tleaf
+ ENDIF
+
+ ! Note: ldew will be resynced as ldew = ldew_rain + ldew_snow at output (line ~1806)
+ ! No in-place ldew update needed here (CoLM2014 pattern: resync at end)
+
+ IF (p0 > 1.e-8) THEN
+ ! VIC physical interception algorithm (snow_intercept.c lines 165-176, 224-236)
+ ! Snow: Dynamic capacity-based model
+ ! Rain: Empirical efficiency (CLM5 formulation retained for liquid phase)
+
+ ! Snow interception: VIC physical algorithm
+ ! Interception efficiency decreases as canopy snow load approaches capacity
+ ! This prevents unphysical continuous interception when branches are saturated
+ Snow = (prc_snow+prl_snow)*deltim
+ IF (satcap_snow > 1.e-6 .and. Snow > 1.e-8) THEN
+ ! DeltaSnowInt = (1 - IntSnow/MaxSnowInt) * SnowFall
+ ! Physical meaning: Interception efficiency = available capacity / max capacity
+ DeltaSnowInt = (1.0 - ldew_snow/satcap_snow) * Snow
+
+ ! Ensure intercepted amount doesn't exceed available capacity
+ IF (DeltaSnowInt + ldew_snow > satcap_snow) THEN
+ DeltaSnowInt = satcap_snow - ldew_snow
+ ENDIF
+
+ ! Ensure non-negative
+ IF (DeltaSnowInt < 0.0) THEN
+ DeltaSnowInt = 0.0
+ ENDIF
+ ELSE
+ DeltaSnowInt = 0.0
+ ENDIF
+
+ ! VIC throughfall calculation (snow_intercept.c line 204)
+ ! Throughfall = vegetation area unintercepted + bare area all
+ ! Physical meaning:
+ ! - In vegetated fraction (sigf): only non-intercepted part passes through
+ ! - In bare fraction (1-sigf): all precipitation passes through
+ !
+ ! Use sigf_safe consistently with the storage scaling above. Mixing sigf_safe
+ ! for state variables with raw sigf for throughfall creates small residuals
+ ! in the debug mass-balance check when sigf is very small.
+ tti_snow = (Snow - DeltaSnowInt) * sigf_safe + Snow * (1.0 - sigf_safe)
+ ldew_snow = ldew_snow + DeltaSnowInt
+
+ ! Rain interception: Original VIC capacity-based algorithm
+ ! Physical mechanism: Rain is intercepted based on available canopy storage capacity,
+ ! not a fixed efficiency function. When capacity is available, rain is intercepted;
+ ! when saturated, excess drains as throughfall.
+ ! Reference: Andreadis et al. (2009) WRR, VIC snow_intercept.c lines 218-236
+ ! This differs from CLM5's empirical efficiency approach (tanh function)
+ Rain = (prc_rain+prl_rain+ qflx_irrig_sprinkler)*deltim
+ MaxWaterInt = satcap_rain ! Capacity already computed at line 1538
+
+ ! Capacity-based interception (VIC original algorithm)
+ ! If there is available capacity, intercept rain; otherwise it becomes throughfall
+ IF (ldew_rain + Rain <= MaxWaterInt) THEN
+ ! All rain can be intercepted (capacity not exceeded)
+ ldew_rain = ldew_rain + Rain
+ ! Throughfall: only bare area contribution
+ tti_rain = Rain * (1.0 - sigf_safe)
+ ELSE
+ ! Capacity exceeded: excess becomes throughfall
+ ! Throughfall = vegetated area excess + bare area all
+ tti_rain = (ldew_rain + Rain - MaxWaterInt) * sigf_safe + Rain * (1.0 - sigf_safe)
+ ! Storage saturated at maximum capacity
+ ldew_rain = MaxWaterInt
+ ENDIF
+
+ tex_rain = max(0.0,ldew_rain-satcap_rain)
+ tex_snow = max(0.0,ldew_snow-satcap_snow)
+
+ ldew_rain = ldew_rain - tex_rain
+ ldew_snow = ldew_snow - tex_snow
+
+ !unload of snow
+ !* Reduce the amount of intercepted snow if windy and cold.
+ !Ringyo Shikenjo Tokyo, #54, 1952.
+ !Bulletin of the Govt. Forest Exp. Station,
+ !Govt. Forest Exp. Station, Meguro, Tokyo, Japan.
+ !FORSTX 634.9072 R475r #54.
+ !Page 146, Figure 10.
+
+ !Reduce the amount of intercepted snow if snowing, windy, and
+ !cold (< -3 to -5 C).
+ !Schmidt and Troendle 1992 western snow conference paper. */
+ !Note: Use tair (air temperature) instead of tleaf to match
+ !the original observations by Storck et al. (2002)
+ Wind= SQRT(forc_us*forc_us + forc_vs*forc_vs)
+ IF (tair-273.15<-3.0 .and. Wind> 1.0) THEN
+ BlownSnow=(0.2*Wind -0.2)* ldew_snow
+ BlownSnow = min(ldew_snow,BlownSnow)
+ tex_snow = tex_snow + BlownSnow
+ ldew_snow = ldew_snow - BlownSnow
+ ENDIF
+ !/* at this point we have calculated the amount of snowfall intercepted and
+ !/* the amount of rainfall intercepted. These values have been
+ !/* appropriately subtracted from SnowFall and RainFall to determine
+ !/* SnowThroughfall and RainThroughfall. However, we can end up with the
+ !/* condition that the total intercepted rain plus intercepted snow is
+ !/* greater than the maximum bearing capacity of the tree regardless of air
+ !/* temp (Imax1). The following routine will adjust ldew_rain and ldew_snow
+ !/* by triggering mass release due to overloading. Of course since ldew_rain
+ !/* and ldew_snow are mixed, we need to slough them of as fixed fractions */
+ IF (ldew_rain + ldew_snow > Imax1) THEN
+ ! /*THEN trigger structural unloading*/
+ Overload = (ldew_snow + ldew_rain) - Imax1
+ ! Prevent division by zero in extreme low LAI conditions
+ IF (ldew_rain + ldew_snow > 1.e-10) THEN
+ IntRainFract = ldew_rain / (ldew_rain + ldew_snow)
+ IntSnowFract = 1.0 - IntRainFract
+ ELSE
+ ! Default to equal partition when total is negligible
+ IntRainFract = 0.5
+ IntSnowFract = 0.5
+ ENDIF
+ ldew_rain = ldew_rain - Overload * IntRainFract
+ ldew_snow = ldew_snow - Overload * IntSnowFract
+ tex_rain = tex_rain + Overload*IntRainFract
+ tex_snow = tex_snow + Overload*IntSnowFract
+ ENDIF
+
+! NOTE: The check "tex+tti > p0" is not applicable to VIC scheme.
+! VIC's tex includes drainage of pre-existing canopy water (ldew) from
+! capacity overflow, wind unloading, and structural overloading.
+! Additionally, tti includes bare-fraction precipitation.
+! The real mass balance check is performed below (w residual check with abort).
+
+ ELSE
+ ! all intercepted by canopy leaves for very small precipitation
+ tti_rain = 0.
+ tti_snow = 0.
+ tex_rain = 0.
+ tex_snow = 0.
+ ENDIF
+
+
+ ! tex_rain/tex_snow are per-vegetation quantities, must scale by sigf_safe
+ ! to convert to grid-scale before adding to grid-scale tti_rain/tti_snow
+ thru_rain = tti_rain + tex_rain * sigf_safe
+ thru_snow = tti_snow + tex_snow * sigf_safe
+
+ ! VIC safety check: When snow completely melts, liquid water capacity
+ ! reverts from (0.035*ldew_snow + MaxInt) to just (MaxInt)
+ ! Must drain excess water that can no longer be held
+ ! Reference: VIC snow_intercept.c lines 522-526
+ IF (ldew_snow < 1.e-6 .and. ldew_rain > MaxInt) THEN
+ thru_rain = thru_rain + (ldew_rain - MaxInt) * sigf_safe
+ ldew_rain = MaxInt
+ ENDIF
+
+ ! VIC vegetation fraction handling (snow_intercept.c line 515-520)
+ ! Convert per-vegetation storage back to grid-scale values
+ ! Use sigf_safe consistently with the division at entry (line 1534-1535)
+ IF (sigf > 1.e-6) THEN
+ ldew_rain = ldew_rain * sigf_safe
+ ldew_snow = ldew_snow * sigf_safe
+ ENDIF
+
+ ! Update total canopy water storage (grid-scale)
+ ldew = ldew_rain + ldew_snow
+ pinf = p0 - (thru_rain + thru_snow)
+
+ ! xsc_rain/xsc_snow are per-vegetation, scale to grid-scale
+ pg_rain = (xsc_rain * sigf_safe + thru_rain) / deltim
+ pg_snow = (xsc_snow * sigf_safe + thru_snow) / deltim
+ qintr = pinf / deltim
+
+ qintr_rain = prc_rain + prl_rain + qflx_irrig_sprinkler - thru_rain / deltim
+ qintr_snow = prc_snow + prl_snow - thru_snow / deltim
+#if (defined CoLMDEBUG)
+ w = w - ldew - (pg_rain+pg_snow)*deltim
+ IF (abs(w) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'something wrong in interception code : '
+ write(6,*) w, ldew, (pg_rain+pg_snow)*deltim !, satcap
+ CALL abort
+ ENDIF
+
+ CALL check_interception_balance('VIC', &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+#endif
+
+ ELSE
+ ! No vegetation: all precipitation passes through, release any stored water
+ pg_rain = prc_rain + prl_rain + qflx_irrig_sprinkler + ldew_rain/deltim
+ pg_snow = prc_snow + prl_snow + ldew_snow/deltim
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+ ENDIF
+ END SUBROUTINE LEAF_interception_VIC
+
+ SUBROUTINE LEAF_interception_JULES(deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf, &
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,qintr,qintr_rain,qintr_snow)
+ !DESCRIPTION
+ !===========
+ ! Official JULES canopy interception scheme
+ ! Rain: Rutter (1971) penetration model (sieve_jls_mod.F90)
+ ! Snow: Exponential saturation model with unloading (canopysnow_mod.F90)
+ !
+ ! 2026-02 Fixes:
+ ! - Added vegetation fraction (sigf) scaling: interception occurs on vegetated area only.
+ ! - Added non-negative clamping for precipitation inputs to ensure mass balance.
+ ! - Fixed mass balance check: ldew resync before sigf division (VIC pattern).
+
+ !Original Author:
+ !-------------------
+ !---Rutter et al. (1971, 1975) - Rain interception model
+ !---JULES team (Best et al. 2011) - Snow interception model
+ !---Zhongwang Wei @ SYSU - CoLM implementation
+
+ !References:
+ !-------------------
+ !---Rutter et al. (1971): A predictive model of rainfall interception in forests, 1.
+ ! Derivation of the model from observations in a plantation of Corsican pine.
+ ! Agricultural Meteorology, 9, 367-384.
+ !---Rutter et al. (1975): A predictive model of rainfall interception in forests, 2.
+ ! Generalization of the model and comparison with observations in some coniferous
+ ! and hardwood stands. Journal of Applied Ecology, 12, 367-380.
+ !---Best et al. (2011): The Joint UK Land Environment Simulator (JULES), model description -
+ ! Part 1: Energy and water fluxes. Geosci. Model Dev. 4:677-699.
+ !---Clark et al. (2011): The Joint UK Land Environment Simulator (JULES), model description -
+ ! Part 2: Carbon fluxes and vegetation dynamics. Geosci. Model Dev. 4:701-722.
+
+ !ANCILLARY FUNCTIONS AND SUBROUTINES
+ !-------------------
+
+ !REVISION HISTORY
+ !----------------
+ ! 2026.02.11 Zhongwang Wei @ SYSU - Added wind-dependent snow unloading (JULES fidelity D3)
+ ! 2026.02.11 Zhongwang Wei @ SYSU - Added sigf scaling, input clamping, mass balance fix
+ ! 2026.01.16 Zhongwang Wei @ SYSU - Converted to official JULES Rutter model
+ ! 2023.02.21 Zhongwang Wei @ SYSU
+ ! 2021.12.08 Zhongwang Wei @ SYSU
+ !=======================================================================
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm] (unused in JULES; retained for interface compatibility)
+ real(r8), intent(in) :: forc_us !wind speed [m/s]
+ real(r8), intent(in) :: forc_vs !wind speed [m/s]
+ real(r8), intent(in) :: chil !leaf angle distribution factor (unused in JULES)
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water flux [mm/s]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(inout) :: tleaf !sunlit canopy leaf temperature [K] (read-only in JULES)
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of liquid on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of solid on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length (unused in JULES)
+ real(r8), intent(in) :: hu !forcing height of U (unused in JULES)
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s) [NOTE: can be negative during canopy release]
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s) [NOTE: can be negative during canopy release]
+
+ ! Local variables
+ real(r8) :: snowinterceptfact ! Snow interception efficiency (0.7)
+ real(r8) :: snowunloadfact ! Snow unloading factor due to melt (0.4)
+ real(r8) :: unload_rate_cnst ! Constant background unloading rate [s⁻¹]
+ real(r8) :: unload_rate_u ! Wind-dependent unloading rate [s⁻¹/(m/s)]
+ real(r8) :: unload_backgrnd ! Total background unloading rate [s⁻¹]
+ real(r8) :: Wind ! Wind speed [m/s]
+ real(r8) :: area ! Precipitation area fraction
+ real(r8) :: can_cpy_rain ! Canopy capacity for rain [mm]
+ real(r8) :: can_cpy_snow ! Canopy capacity for snow [mm]
+ real(r8) :: r_rain ! Rain rate [mm/s] (clamped, non-negative)
+ real(r8) :: r_snow ! Snow rate [mm/s] (clamped, non-negative)
+ real(r8) :: can_ratio ! Canopy saturation ratio (can_wcnt/can_cpy)
+ real(r8) :: aexp ! Exponential term in Rutter model
+ real(r8) :: tfall_rain ! Rain throughfall [mm/s]
+ real(r8) :: tfall_snow ! Snow throughfall [mm/s]
+ real(r8) :: intercept_rain ! Rain interception in timestep [mm]
+ real(r8) :: intercept_snow ! Snow interception in timestep [mm]
+ real(r8) :: unload_snow ! Snow unloading in timestep [mm]
+ real(r8) :: melt_rate ! Canopy snow melt rate [mm/s]
+ real(r8) :: melt_factor ! Dimensionless melt energy ratio: CICE/(DENICE*HFUS)
+ real(r8) :: frz_factor ! Dimensionless freeze energy ratio: CWAT/(DENH2O*HFUS)
+ real(r8) :: smallp ! Small positive number
+ real(r8) :: lsai_l ! total LAI+SAI (local)
+ real(r8) :: p0_l, ppc_l, ppl_l ! precipitation sums (local)
+ real(r8) :: w_l ! mass balance check variable (local)
+ real(r8) :: ldew_frzc ! freezing water amount
+ real(r8) :: xsc_rain, xsc_snow ! excess water drained after phase change
+ real(r8) :: sigf_safe ! safe vegetation fraction (>= 0.01)
+ real(r8) :: thru_rain, thru_snow ! grid-scale throughfall [mm]
+
+ IF (lai+sai > 1e-6 .AND. sigf > 1.e-6) THEN
+ lsai_l = lai + sai
+
+ !======================================================================
+ ! Input Clamping (Mass Balance Safety)
+ !======================================================================
+ ! Negative precipitation inputs (numerical noise) cause mass balance failures.
+ ! Clamp all inputs to 0.0 before any calculations.
+ r_rain = MAX(0.0_r8, prc_rain + prl_rain + qflx_irrig_sprinkler)
+ r_snow = MAX(0.0_r8, prc_snow + prl_snow)
+
+ ! Clamp canopy state: negative values from restart or upstream bugs
+ ! would be amplified by sigf division and cause mass balance abort
+ ldew_rain = MAX(0.0_r8, ldew_rain)
+ ldew_snow = MAX(0.0_r8, ldew_snow)
+
+ !======================================================================
+ ! JULES Parameters - Official values from JULES source code
+ !======================================================================
+ snowinterceptfact = 0.7 ! Snow interception efficiency (jules_snow_mod.F90)
+ snowunloadfact = 0.4 ! Snow unloading factor (canopysnow_mod.F90)
+ unload_rate_cnst = 2.31e-6 ! Constant background unloading rate [s⁻¹]
+ unload_rate_u = 5.56e-7 ! Wind-dependent unloading rate [s⁻¹/(m/s)]
+ Wind = SQRT(forc_us**2 + forc_vs**2)
+ unload_backgrnd = unload_rate_cnst + unload_rate_u * Wind
+ can_cpy_snow = 4.4 * lsai_l ! Snow capacity [mm] (snowloadlai parameter)
+ can_cpy_rain = 0.1 * lsai_l ! Rain capacity [mm] (JULES PFT parameter)
+ smallp = EPSILON(1.0_r8) ! Machine epsilon for numerical stability
+
+ !======================================================================
+ ! Precipitation totals and mass balance reference (GRID-SCALE)
+ !======================================================================
+ ! Use clamped rates for consistency
+ p0_l = (r_rain + r_snow) * deltim
+ ppc_l = MAX(0.0_r8, prc_rain + prc_snow) * deltim
+ ppl_l = p0_l - ppc_l
+ ! Clamp ppl_l to avoid negative from clamping differences
+ ppl_l = MAX(0.0_r8, ppl_l)
+
+ IF (p0_l > 1.e-8) THEN
+ ! Convective precip ~10% of grid, stratiform ~100% of grid
+ area = (0.1*ppc_l + 1.0*ppl_l) / p0_l
+ area = max(0.1, min(1.0, area))
+ ELSE
+ area = 1.0
+ ENDIF
+
+ ! Ensure ldew is consistent with components at entry (GRID-SCALE)
+ ! Must be done BEFORE sigf division to keep w_l in grid-scale units
+ ldew = ldew_rain + ldew_snow
+
+ ! Mass balance reference: grid-scale storage + grid-scale precipitation
+ w_l = ldew + p0_l
+
+ !======================================================================
+ ! Vegetation Fraction Scaling (sigf)
+ !======================================================================
+ ! JULES physics operates on the vegetated area only.
+ ! Convert grid-averaged storage to per-vegetation values.
+ ! (Matching VIC pattern: divide before physics, multiply after)
+ ! Note: outer guard guarantees sigf > 1e-6; floor at 0.01 prevents
+ ! extreme amplification when sigf is very small but positive.
+ sigf_safe = max(sigf, 0.01_r8)
+ ldew_rain = ldew_rain / sigf_safe
+ ldew_snow = ldew_snow / sigf_safe
+
+ !======================================================================
+ ! Phase change (melting/freezing) - Do BEFORE interception
+ !======================================================================
+ ! Pre-compute dimensionless energy ratios to avoid large intermediate
+ ! products (e.g. CICE*ldew_snow ~1e8) that can trap under -ffpe-trap.
+ ! melt_factor = CICE / (DENICE * HFUS) ≈ 0.00684 [K⁻¹]
+ ! frz_factor = CWAT / (DENH2O * HFUS) ≈ 0.01256 [K⁻¹]
+ melt_factor = CICE / (DENICE * HFUS)
+ frz_factor = CWAT / (DENH2O * HFUS)
+
+ IF (tleaf > tfrz) THEN
+ ! Canopy snow melting
+ IF (ldew_snow > 1.e-8) THEN
+ melt_rate = MIN(ldew_snow/deltim, &
+ (tleaf - tfrz) * melt_factor * ldew_snow / deltim)
+ melt_rate = MAX(melt_rate, 0.0_r8)
+ ldew_snow = ldew_snow - melt_rate * deltim
+ ldew_snow = MAX(ldew_snow, 0.0_r8) ! prevent -eps from FP rounding
+ ldew_rain = ldew_rain + melt_rate * deltim
+ ELSE
+ melt_rate = 0.0_r8
+ ENDIF
+ ELSE
+ ! Canopy rain freezing
+ IF (ldew_rain > 1.e-8) THEN
+ ldew_frzc = MIN(ldew_rain, &
+ (tfrz - tleaf) * frz_factor * ldew_rain)
+ ldew_frzc = MAX(ldew_frzc, 0.0_r8)
+ ldew_snow = ldew_snow + ldew_frzc
+ ldew_rain = ldew_rain - ldew_frzc
+ ldew_rain = MAX(ldew_rain, 0.0_r8) ! prevent -eps from FP rounding
+ ENDIF
+ melt_rate = 0.0_r8
+ ENDIF
+
+ !======================================================================
+ ! Drain excess water after phase change
+ ! When snow melts to rain, ldew_rain can greatly exceed can_cpy_rain
+ ! When rain freezes to snow, ldew_snow can exceed can_cpy_snow
+ !======================================================================
+ xsc_rain = 0.0
+ xsc_snow = 0.0
+ IF (ldew_rain > can_cpy_rain) THEN
+ xsc_rain = ldew_rain - can_cpy_rain
+ ldew_rain = can_cpy_rain
+ ENDIF
+ IF (ldew_snow > can_cpy_snow) THEN
+ xsc_snow = ldew_snow - can_cpy_snow
+ ldew_snow = can_cpy_snow
+ ENDIF
+
+ !======================================================================
+ ! RAIN INTERCEPTION: Rutter (1971) Penetration Model
+ ! From JULES sieve_jls_mod.F90 lines 125-142
+ !======================================================================
+ IF (can_cpy_rain > 0.0 .AND. r_rain > smallp) THEN
+ ! Exponential term (JULES lines 126-132)
+ aexp = exp(max(-50.0_r8, -area * can_cpy_rain / (r_rain * deltim)))
+
+ ! Canopy saturation ratio (JULES lines 134-136)
+ can_ratio = ldew_rain / can_cpy_rain
+ can_ratio = MAX(0.0, MIN(can_ratio, 1.0))
+
+ ! Rutter throughfall formula (JULES line 137)
+ tfall_rain = r_rain * ((1.0 - can_ratio) * aexp + can_ratio)
+ ELSE
+ tfall_rain = r_rain
+ ENDIF
+
+ ! Update canopy water content (JULES line 142)
+ intercept_rain = (r_rain - tfall_rain) * deltim
+ ldew_rain = ldew_rain + intercept_rain
+
+ ! Post-Rutter drainage: discrete timestep can overshoot capacity
+ IF (ldew_rain > can_cpy_rain) THEN
+ tfall_rain = tfall_rain + (ldew_rain - can_cpy_rain) / deltim
+ ldew_rain = can_cpy_rain
+ ENDIF
+
+ !======================================================================
+ ! SNOW INTERCEPTION: Exponential Saturation Model with Unloading
+ ! From JULES canopysnow_mod.F90 lines 131-145
+ !======================================================================
+ ! Snow unloading occurs regardless of snowfall (continuous process)
+ unload_snow = snowunloadfact * melt_rate * deltim &
+ + unload_backgrnd * ldew_snow * deltim
+ unload_snow = MAX(MIN(unload_snow, ldew_snow), 0.0)
+ ldew_snow = ldew_snow - unload_snow
+
+ IF (r_snow > smallp) THEN
+ ! Snow interception (JULES lines 131-132)
+ intercept_snow = snowinterceptfact * (can_cpy_snow - ldew_snow) * &
+ (1.0 - EXP(MAX(-50.0_r8, -r_snow * deltim / can_cpy_snow)))
+ intercept_snow = MAX(0.0, intercept_snow)
+
+ ! Update canopy snow
+ ldew_snow = ldew_snow + intercept_snow
+
+ ! Snowfall to ground = snowfall - intercepted + unloaded
+ tfall_snow = r_snow - intercept_snow / deltim + unload_snow / deltim
+
+ ! Post-interception drainage
+ IF (ldew_snow > can_cpy_snow) THEN
+ tfall_snow = tfall_snow + (ldew_snow - can_cpy_snow) / deltim
+ ldew_snow = can_cpy_snow
+ ENDIF
+ ELSE
+ intercept_snow = 0.0
+ ! No snowfall, but unloaded snow still reaches ground
+ tfall_snow = r_snow + unload_snow / deltim
+ ENDIF
+
+ !======================================================================
+ ! Output fluxes: Per-vegetation → Grid-scale (VIC pattern)
+ !======================================================================
+ ! tfall_rain/tfall_snow are per-vegetation throughfall rates [mm/s]
+ ! xsc_rain/xsc_snow are per-vegetation excess [mm]
+ ! Combine: vegetated area throughfall + bare ground direct precipitation
+
+ ! Grid-scale throughfall [mm] (for mass balance check)
+ ! IMPORTANT: Use sigf_safe consistently (not sigf) to ensure exact mass balance
+ ! When sigf < 0.01, sigf_safe = 0.01 != sigf, mixing them creates a residual
+ thru_rain = (tfall_rain * deltim + xsc_rain) * sigf_safe + r_rain * deltim * (1.0 - sigf_safe)
+ thru_snow = (tfall_snow * deltim + xsc_snow) * sigf_safe + r_snow * deltim * (1.0 - sigf_safe)
+
+ ! Convert throughfall to rate [mm/s]
+ pg_rain = thru_rain / deltim
+ pg_snow = thru_snow / deltim
+
+ ! Rescale state variables back to grid-averaged
+ ldew_rain = ldew_rain * sigf_safe
+ ldew_snow = ldew_snow * sigf_safe
+
+ ! Update total canopy water (grid-scale)
+ ldew = ldew_rain + ldew_snow
+
+ ! Interception = total input - total output - storage change
+ ! Using the VIC approach: qintr = (p0 - thru) / deltim
+ qintr = (p0_l - thru_rain - thru_snow) / deltim
+
+ ! Phase-separated interception rates
+ ! NOTE: These can be NEGATIVE when pre-existing canopy storage drains
+ ! (e.g., excess from phase change or prior timestep). Negative values
+ ! represent net canopy release, not a mass balance error.
+ ! Algebraic identity: qintr_rain + qintr_snow == qintr (exact).
+ qintr_rain = r_rain - pg_rain
+ qintr_snow = r_snow - pg_snow
+
+#if (defined CoLMDEBUG)
+ ! Mass balance check: w_l (grid-scale old storage + precip) should equal
+ ! new grid-scale storage + grid-scale ground flux
+ w_l = w_l - ldew - (pg_rain + pg_snow) * deltim
+ IF (abs(w_l) > 1.e-6) THEN
+ write(6,*) 'JULES interception mass balance error: ', w_l
+ write(6,*) 'ldew=', ldew, ' pg*dt=', (pg_rain+pg_snow)*deltim
+ CALL abort
+ ENDIF
+
+ CALL check_interception_balance('JULES', &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+#endif
+ ELSE
+ ! No vegetation: all precipitation passes through, release any stored water
+ ! Clamp raw precipitation to prevent negative pg (matching vegetated branch)
+ pg_rain = MAX(0.0_r8, prc_rain + prl_rain + qflx_irrig_sprinkler) + ldew_rain/deltim
+ pg_snow = MAX(0.0_r8, prc_snow + prl_snow) + ldew_snow/deltim
+
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ qintr = 0.
+ qintr_rain = 0.
+ qintr_snow = 0.
+ ENDIF
+ END SUBROUTINE LEAF_interception_JULES
+
+ SUBROUTINE LEAF_interception_wrap(deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf, &
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall, &
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain, &
+ pg_snow,qintr,qintr_rain,qintr_snow )
+!DESCRIPTION
+!===========
+ !wrapper for calculation of canopy interception using USGS or IGBP land cover classification
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+
+!Original Author:
+!-------------------
+ !---Shupeng Zhang
+
+!References:
+
+
+!REVISION HISTORY
+!----------------
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: chil !leaf angle distribution factor
+ real(r8), intent(in) :: prc_rain !convective rainfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water [mm/s]
+ real(r8), intent(in) :: bifall !bulk density of newly fallen dry snow [kg/m3]
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: tair !air temperature [K]
+ real(r8), intent(inout) :: tleaf !sunlit canopy leaf temperature [K]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_rain !depth of liquid on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of liquid on foliage [mm]
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+
+
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+ IF (DEF_Interception_scheme==1) THEN
+ CALL LEAF_interception_CoLM2014 (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+ ELSEIF (DEF_Interception_scheme==2) THEN
+ CALL LEAF_interception_CLM4 (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+ ELSEIF (DEF_Interception_scheme==3) THEN
+ CALL LEAF_interception_CLM5(deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+ ELSEIF (DEF_Interception_scheme==4) THEN
+ CALL LEAF_interception_NoahMP (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+ ELSEIF (DEF_Interception_scheme==5) THEN
+ CALL LEAF_interception_matsiro (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+
+ ELSEIF (DEF_Interception_scheme==6) THEN
+ CALL LEAF_interception_vic (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+
+ ELSEIF (DEF_Interception_scheme==7) THEN
+ CALL LEAF_interception_JULES (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+
+ ELSEIF (DEF_Interception_scheme==8) THEN
+ CALL LEAF_interception_colm202x (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tair,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,&
+ pg_snow,qintr,qintr_rain,qintr_snow)
+ ENDIF
+
+ END SUBROUTINE LEAF_interception_wrap
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ SUBROUTINE LEAF_interception_pftwrap (ipatch,deltim,dewmx,forc_us,forc_vs,forc_t,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,hu,pg_rain,pg_snow,qintr,qintr_rain,qintr_snow)
+
+! -----------------------------------------------------------------
+! !DESCRIPTION:
+! wrapper for calculation of canopy interception for PFTs within a land cover type.
+!
+! Created by Hua Yuan, 06/2019
+!
+! !REVISION HISTORY:
+! 2023.02.21 Zhongwang Wei @ SYSU: add different options of canopy interception for PFTs
+!
+! -----------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_LandPFT
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_Vars_1DPFTFluxes
+ USE MOD_Const_PFT
+ IMPLICIT NONE
+
+ integer, intent(in) :: ipatch !patch index
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: dewmx !maximum dew [mm]
+ real(r8), intent(in) :: forc_us !wind speed
+ real(r8), intent(in) :: forc_vs !wind speed
+ real(r8), intent(in) :: forc_t !air temperature
+ real(r8), intent(in) :: z0m !roughness length
+ real(r8), intent(in) :: hu !forcing height of U
+ real(r8), intent(inout) :: ldew_rain !depth of water on foliage [mm]
+ real(r8), intent(inout) :: ldew_snow !depth of water on foliage [mm]
+ real(r8), intent(in) :: prc_rain !convective ranfall [mm/s]
+ real(r8), intent(in) :: prc_snow !convective snowfall [mm/s]
+ real(r8), intent(in) :: prl_rain !large-scale rainfall [mm/s]
+ real(r8), intent(in) :: prl_snow !large-scale snowfall [mm/s]
+ real(r8), intent(in) :: qflx_irrig_sprinkler !irrigation and sprinkler water [mm/s]
+ real(r8), intent(in) :: bifall ! bulk density of newly fallen dry snow [kg/m3]
+
+ real(r8), intent(inout) :: ldew !depth of water on foliage [mm]
+ real(r8), intent(out) :: pg_rain !rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: pg_snow !snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(out) :: qintr !interception [kg/(m2 s)]
+ real(r8), intent(out) :: qintr_rain !rainfall interception (mm h2o/s)
+ real(r8), intent(out) :: qintr_snow !snowfall interception (mm h2o/s)
+
+ integer i, p, ps, pe
+#ifdef CROP
+ integer :: irrig_flag ! 1 if sprinker, 2 if others
+#endif
+ real(r8) pg_rain_tmp, pg_snow_tmp
+
+ pg_rain_tmp = 0.
+ pg_snow_tmp = 0.
+
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ IF (DEF_Interception_scheme==1) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_CoLM2014 (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==2) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_clm4 (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==3) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_clm5 (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==4) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_NoahMP (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==5) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_MATSIRO (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==6) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_VIC (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==7) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_JULES (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ELSEIF (DEF_Interception_scheme==8) THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL LEAF_interception_CoLM202x (deltim,dewmx,forc_us,forc_vs,chil_p(p),sigf_p(i),lai_p(i),sai_p(i),forc_t,tleaf_p(i),&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,&
+ ldew_p(i),ldew_rain_p(i),ldew_snow_p(i),z0m_p(i),hu,pg_rain,pg_snow,qintr_p(i),qintr_rain_p(i),qintr_snow_p(i))
+ pg_rain_tmp = pg_rain_tmp + pg_rain*pftfrac(i)
+ pg_snow_tmp = pg_snow_tmp + pg_snow*pftfrac(i)
+ ENDDO
+ ENDIF
+
+ pg_rain = pg_rain_tmp
+ pg_snow = pg_snow_tmp
+ ldew = sum( ldew_p(ps:pe) * pftfrac(ps:pe))
+ ldew_rain = sum( ldew_rain_p(ps:pe) * pftfrac(ps:pe))
+ ldew_snow = sum( ldew_snow_p(ps:pe) * pftfrac(ps:pe))
+ qintr = sum(qintr_p(ps:pe) * pftfrac(ps:pe))
+ qintr_rain = sum(qintr_rain_p(ps:pe) * pftfrac(ps:pe))
+ qintr_snow = sum(qintr_snow_p(ps:pe) * pftfrac(ps:pe))
+
+ END SUBROUTINE LEAF_interception_pftwrap
+#endif
+
+ SUBROUTINE check_interception_balance(scheme_name, &
+ ldew, ldew_rain, ldew_snow, pg_rain, pg_snow, &
+ qintr, qintr_rain, qintr_snow)
+
+ ! Validates interception water balance consistency.
+ ! Called from CoLMDEBUG blocks after each scheme completes.
+
+ character(len=*), intent(in) :: scheme_name
+ real(r8), intent(in) :: ldew, ldew_rain, ldew_snow
+ real(r8), intent(in) :: pg_rain, pg_snow
+ real(r8), intent(in) :: qintr, qintr_rain, qintr_snow
+
+ ! Check A: component consistency (ldew == ldew_rain + ldew_snow)
+ IF (abs(ldew - (ldew_rain + ldew_snow)) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'Component consistency error in ', scheme_name, ':'
+ write(6,*) 'ldew=', ldew, ' ldew_rain+ldew_snow=', ldew_rain+ldew_snow
+ write(6,*) 'diff=', ldew - (ldew_rain + ldew_snow)
+ CALL abort
+ ENDIF
+
+ ! Check B: non-negativity
+ IF (ldew < -INTERCEPTION_BALANCE_TOL .or. &
+ ldew_rain < -INTERCEPTION_BALANCE_TOL .or. &
+ ldew_snow < -INTERCEPTION_BALANCE_TOL .or. &
+ pg_rain < -INTERCEPTION_BALANCE_TOL .or. &
+ pg_snow < -INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'Negative value error in ', scheme_name, ':'
+ write(6,*) 'ldew=', ldew, ' ldew_rain=', ldew_rain, ' ldew_snow=', ldew_snow
+ write(6,*) 'pg_rain=', pg_rain, ' pg_snow=', pg_snow
+ CALL abort
+ ENDIF
+
+ ! Check C: flux consistency (qintr == qintr_rain + qintr_snow)
+ IF (abs(qintr - (qintr_rain + qintr_snow)) > INTERCEPTION_BALANCE_TOL) THEN
+ write(6,*) 'Flux consistency error in ', scheme_name, ':'
+ write(6,*) 'qintr=', qintr, ' qintr_rain+qintr_snow=', qintr_rain+qintr_snow
+ write(6,*) 'diff=', qintr - (qintr_rain + qintr_snow)
+ CALL abort
+ ENDIF
+
+ END SUBROUTINE check_interception_balance
+
+END MODULE MOD_LeafInterception
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafTemperature.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafTemperature.F90
new file mode 100644
index 0000000000..48a3f61941
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafTemperature.F90
@@ -0,0 +1,1568 @@
+#include
+
+MODULE MOD_LeafTemperature
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_CBL_HEIGHT, DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, &
+ DEF_RSS_SCHEME, DEF_Interception_scheme, DEF_SPLIT_SOILSNOW, &
+ DEF_VEG_SNOW
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: LeafTemperature
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: dewfraction
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE LeafTemperature ( &
+ ipatch ,ivt ,deltim ,csoilc ,dewmx ,htvp ,&
+ lai ,sai ,htop ,hbot ,sqrtdi ,effcon ,&
+ vmax25 ,c3c4 ,slti ,hlti ,shti ,hhti ,trda ,&
+ trdm ,trop ,g1 ,g0 ,gradm ,binter ,&
+ extkn ,extkb ,extkd ,hu ,ht ,hq ,&
+ us ,vs ,thm ,th ,thv ,qm ,&
+ psrf ,rhoair ,parsun ,parsha ,sabv ,frl ,&
+ fsun ,thermk ,rstfacsun ,rstfacsha ,gssun ,gssha ,&
+ po2m ,pco2m ,z0h_g ,obug ,ustarg ,zlnd ,&
+ zsno ,fsno ,sigf ,etrc ,tg ,qg ,&
+ rss ,t_soil ,t_snow ,q_soil ,q_snow ,dqgdT ,&
+ emg ,tl ,ldew ,ldew_rain ,ldew_snow ,fwet_snow ,&
+ taux ,tauy ,fseng ,fseng_soil ,fseng_snow ,fevpg ,&
+ fevpg_soil ,fevpg_snow ,cgrnd ,cgrndl ,cgrnds ,tref ,&
+ qref ,rst ,assim ,respc ,fsenl ,fevpl ,&
+ etr ,dlrad ,ulrad ,z0m ,zol ,rib ,&
+ ustar ,qstar ,tstar ,fm ,fh ,fq ,&
+ rootfr ,&
+!Plant Hydraulic variables
+ kmax_sun ,kmax_sha ,kmax_xyl ,kmax_root ,psi50_sun ,psi50_sha ,&
+ psi50_xyl ,psi50_root ,ck ,vegwp ,gs0sun ,gs0sha ,&
+ assimsun ,etrsun ,assimsha ,etrsha ,&
+!Ozone stress variables
+ o3coefv_sun,o3coefv_sha,o3coefg_sun,o3coefg_sha,&
+ lai_old ,o3uptakesun,o3uptakesha,forc_ozone ,&
+!End ozone stress variables
+!WUE stomata model parameter
+ lambda ,&
+!End WUE stomata model parameter
+ hpbl ,&
+ qintr_rain ,qintr_snow ,t_precip ,hprl ,dheatl ,smp ,&
+ hk ,hksati ,rootflux )
+
+!=======================================================================
+! !DESCRIPTION:
+! Foliage energy conservation is given by foliage energy budget equation
+! Rnet - Hf - LEf = 0
+! The equation is solved by Newton-Raphson iteration, in which this
+! iteration includes the calculation of the photosynthesis and stomatal
+! resistance, and the integration of turbulent flux profiles. The
+! sensible and latent heat transfer between foliage and atmosphere and
+! ground is linked by the equations:
+! Ha = Hf + Hg and Ea = Ef + Eg
+!
+! Original author: Yongjiu Dai, August 15, 2001
+!
+! !REVISIONS:
+!
+! 09/2014, Hua Yuan: imbalanced energy due to T/q adjustment is
+! allocated to sensible heat flux.
+!
+! 10/2017, Hua Yuan: added options for z0, displa, rb and rd
+! calculation (Dai, Y., Yuan, H., Xin, Q., Wang, D.,
+! Shangguan, W., Zhang, S., et al. (2019). Different
+! representations of canopy structure—A large source of
+! uncertainty in global land surface modeling. Agricultural
+! and Forest Meteorology, 269-270, 119-135.
+! https://doi.org/10.1016/j.agrformet.2019.02.006
+!
+! 10/2019, Hua Yuan: change only the leaf temperature from two-leaf
+! to one-leaf (due to large differences may exist between
+! sunlit/shaded leaf temperature.
+!
+! 01/2021, Xingjie Lu and Nan Wei: added plant hydraulic process
+! interface.
+!
+! 01/2021, Nan Wei: added interaction btw prec and canopy.
+!
+! 05/2023, Shaofeng Liu: add option to call moninobuk_leddy, the
+! LargeEddy surface turbulence scheme (LZD2022); make a proper
+! update of um.
+!
+! 04/2024, Hua Yuan: add option to account for vegetation snow process.
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: vonkar, grav, hvap, hsub, cpair, stefnc, cpliq, cpice, &
+ hfus, tfrz, denice, denh2o
+ USE MOD_FrictionVelocity
+ USE MOD_CanopyLayerProfile
+ USE MOD_TurbulenceLEddy
+ USE MOD_AssimStomataConductance
+ USE MOD_UserSpecifiedForcing, only: HEIGHT_mode
+ USE MOD_Vars_TimeInvariants, only: patchclass
+ USE MOD_Const_LC, only: z0mr, displar
+ USE MOD_PlantHydraulic, only:PlantHydraulicStress_twoleaf, getvegwp_twoleaf
+ USE MOD_Ozone, only: CalcOzoneStress
+ USE MOD_Qsadv
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: ipatch,ivt
+ real(r8), intent(in) :: &
+ deltim, &! seconds in a time step [second]
+ csoilc, &! drag coefficient for soil under canopy [-]
+ dewmx, &! maximum dew
+ htvp ! latent heat of evaporation (/sublimation) [J/kg]
+
+! vegetation parameters
+ real(r8), intent(inout) :: &
+ sai ! stem area index [-]
+ real(r8), intent(in) :: &
+ sqrtdi, &! inverse sqrt of leaf dimension [m**-0.5]
+ htop, &! PFT crown top height [m]
+ hbot, &! PFT crown bot height [m]
+
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2 / mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ ! the range : 30.e-6 <-> 100.e-6 (mol co2 m-2 s-1)
+ shti, &! slope of high temperature inhibition function (s1)
+ hhti, &! 1/2 point of high temperature inhibition function (s2)
+ slti, &! slope of low temperature inhibition function (s3)
+ hlti, &! 1/2 point of low temperature inhibition function (s4)
+ trda, &! temperature coefficient in gs-a model (s5)
+ trdm, &! temperature coefficient in gs-a model (s6)
+ trop, &! temperature coefficient in gs-a model (273+25)
+ g1, &! conductance-photosynthesis slope parameter for medlyn model
+ g0, &! conductance-photosynthesis intercept for medlyn model
+ gradm, &! conductance-photosynthesis slope parameter
+ binter, &! conductance-photosynthesis intercept
+!Ozone WUE stomata model parameter
+ lambda, &! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+!End WUE stomata model parameter
+ extkn ! coefficient of leaf nitrogen allocation
+ integer , intent(in) :: &
+ c3c4 ! 1 for c3, 0 for c4
+ real(r8), intent(in) :: & ! for plant hydraulic scheme
+ kmax_sun, &! Plant Hydraulics Parameters
+ kmax_sha, &! Plant Hydraulics Parameters
+ kmax_xyl, &! Plant Hydraulics Parameters
+ kmax_root, &! Plant Hydraulics Parameters
+ psi50_sun, &! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ psi50_sha, &! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ psi50_xyl, &! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ psi50_root, &! water potential at 50% loss of root tissue conductance (mmH2O)
+ ck ! shape-fitting parameter for vulnerability curve (-)
+ real(r8), intent(inout) :: &
+ vegwp(1:nvegwcs),&! vegetation water potential
+ gs0sun, &! maximum stomata conductance of sunlit leaf
+ gs0sha ! maximum stomata conductance of shaded leaf
+
+! input variables
+ real(r8), intent(in) :: &
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ qm, &! specific humidity at reference height [kg/kg]
+ psrf, &! pressure at reference height [pa]
+ rhoair, &! density air [kg/m**3]
+
+ lai, &! adjusted leaf area index for seasonal variation [-]
+ parsun, &! par absorbed per unit lai [w/m**2]
+ parsha, &! par absorbed per unit lai [w/m**2]
+ sabv, &! solar radiation absorbed by vegetation [W/m2]
+ frl, &! atmospheric infrared (longwave) radiation [W/m2]
+ fsun, &! sunlit fraction of canopy
+
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ thermk, &! canopy gap fraction for tir radiation
+
+ po2m, &! atmospheric partial pressure o2 (pa)
+ pco2m, &! atmospheric partial pressure co2 (pa)
+
+ z0h_g, &! bare soil roughness length, sensible heat [m]
+ obug, &! bare soil obu
+ ustarg, &! bare soil ustar
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+ fsno, &! fraction of snow cover on ground
+
+ sigf, &! fraction of veg cover, excluding snow-covered veg [-]
+ etrc, &! maximum possible transpiration rate (mm/s)
+ tg, &! ground surface temperature [K]
+ t_soil, &! ground surface soil temperature [K]
+ t_snow, &! ground surface snow temperature [K]
+ qg, &! specific humidity at ground surface [kg/kg]
+ q_soil, &! specific humidity at ground soil surface [kg/kg]
+ q_snow, &! specific humidity at ground snow surface [kg/kg]
+ dqgdT, &! temperature derivative of "qg"
+ rss, &! soil surface resistance [s/m]
+ emg ! vegetation emissivity
+
+ real(r8), intent(in) :: &
+ t_precip, &! snowfall/rainfall temperature [kelvin]
+ qintr_rain, &! rainfall interception (mm h2o/s)
+ qintr_snow, &! snowfall interception (mm h2o/s)
+ smp (1:nl_soil), &! soil matrix potential
+ rootfr (1:nl_soil), &! root fraction
+ hksati (1:nl_soil), &! hydraulic conductivity at saturation [mm h2o/s]
+ hk (1:nl_soil) ! soil hydraulic conductance
+ real(r8), intent(in) :: &
+ hpbl ! atmospheric boundary layer height [m]
+
+ real(r8), intent(inout) :: &
+ tl, &! leaf temperature [K]
+ ldew, &! depth of water on foliage [mm]
+ ldew_rain, &! depth of rain on foliage [mm]
+ ldew_snow ! depth of snow on foliage [mm]
+
+ real(r8), intent(out) :: &
+ fwet_snow ! vegetation snow fractional cover [-]
+
+ real(r8), intent(inout) :: &
+!Ozone stress variables
+ lai_old ,&! lai in last time step
+ o3uptakesun,&! Ozone does, sunlit leaf (mmol O3/m^2)
+ o3uptakesha,&! Ozone does, shaded leaf (mmol O3/m^2)
+ forc_ozone
+!End ozone stress variables
+
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fseng_soil, &! sensible heat flux from ground soil [W/m2]
+ fseng_snow, &! sensible heat flux from ground snow [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+ fevpg_soil, &! evaporation heat flux from ground soil [mm/s]
+ fevpg_snow, &! evaporation heat flux from ground snow [mm/s]
+ cgrnd, &! deriv. of soil energy flux wrt to soil temp [w/m2/k]
+ cgrndl, &! deriv, of soil sensible heat flux wrt soil temp [w/m2/k]
+ cgrnds, &! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+ tref, &! 2 m height air temperature (kelvin)
+ qref, &! 2 m height air specific humidity
+ rstfacsun, &! factor of soil water stress to transpiration on sunlit leaf
+ rstfacsha, &! factor of soil water stress to transpiration on shaded leaf
+ gssun, &! stomata conductance of sunlit leaf
+ gssha, &! stomata conductance of shaded leaf
+ rootflux(1:nl_soil) ! root water uptake from different layers
+
+ real(r8), intent(inout) :: &
+ assimsun, &! sunlit leaf assimilation rate [umol co2 /m**2/ s] [+]
+ etrsun, &! transpiration rate of sunlit leaf [mm/s]
+ assimsha, &! shaded leaf assimilation rate [umol co2 /m**2/ s] [+]
+ etrsha ! transpiration rate of shaded leaf [mm/s]
+
+ real(r8), intent(out) :: &
+ rst, &! stomatal resistance
+ assim, &! rate of assimilation
+ respc, &! rate of respiration
+ fsenl, &! sensible heat from leaves [W/m2]
+ fevpl, &! evaporation+transpiration from leaves [mm/s]
+ etr, &! transpiration rate [mm/s]
+ dlrad, &! downward longwave radiation blow the canopy [W/m2]
+ ulrad, &! upward longwave radiation above the canopy [W/m2]
+ hprl, &! precipitation sensible heat from canopy
+ dheatl, &! vegetation heat change [W/m2]
+
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+ real(r8), intent(inout) :: &
+!Ozone stress variables
+ o3coefv_sun,&! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefv_sha,&! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefg_sun,&! Ozone stress factor for stomata on shaded leaf
+ o3coefg_sha ! Ozone stress factor for stomata on shaded leaf
+!End ozone stress variables
+
+!-------------------------- Local Variables ----------------------------
+! assign iteration parameters
+ integer, parameter :: itmax = 40 !maximum number of iteration
+ integer, parameter :: itmin = 6 !minimum number of iteration
+ real(r8),parameter :: delmax = 3.0 !maximum change in leaf temperature [K]
+ real(r8),parameter :: dtmin = 0.01 !max limit for temperature convergence [K]
+ real(r8),parameter :: dlemin = 0.1 !max limit for energy flux convergence [w/m2]
+
+ real(r8) dtl(0:itmax+1) !difference of tl between two iterative step
+
+ real(r8) :: &
+ displa, &! displacement height [m]
+ hu_, &! adjusted observational height of wind [m]
+ ht_, &! adjusted observational height of temperature [m]
+ hq_, &! adjusted observational height of humidity [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ zii, &! convective boundary layer height [m]
+ z0mv, &! roughness length, momentum [m]
+ z0hv, &! roughness length, sensible heat [m]
+ z0qv, &! roughness length, latent heat [m]
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ beta, &! coefficient of convective velocity [-]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ dth, &! diff of virtual temp. between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ um, &! wind speed including the stability effect [m/s]
+ ur, &! wind speed at reference height [m/s]
+ uaf, &! velocity of air within foliage [m/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile function for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ taf, &! air temperature within canopy space [K]
+ qaf, &! humidity of canopy air [kg/kg]
+ eah, &! canopy air vapor pressure (pa)
+ pco2g, &! co2 pressure (pa) at ground surface (pa)
+ pco2a, &! canopy air co2 pressure (pa)
+
+ fdry, &! fraction of foliage that is green and dry [-]
+ fwet, &! fraction of foliage covered by water [-]
+ cf, &! heat transfer coefficient from leaves [-]
+ rb, &! leaf boundary layer resistance [s/m]
+ rbsun, &! Sunlit leaf boundary layer resistance [s/m]
+ rbsha, &! Shaded leaf boundary layer resistance [s/m]
+ rd, &! aerodynamical resistance between ground and canopy air
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ clai, &! canopy heat capacity [Jm-2K-1]
+ cah, &! heat conductance for air [m/s]
+ cgh, &! heat conductance for ground [m/s]
+ cfh, &! heat conductance for leaf [m/s]
+ caw, &! latent heat conductance for air [m/s]
+ cgw, &! latent heat conductance for ground [m/s]
+ cfw, &! latent heat conductance for leaf [m/s]
+ wtshi, &! sensible heat resistance for air, grd and leaf [-]
+ wtsqi, &! latent heat resistance for air, grd and leaf [-]
+ wta0, &! normalized heat conductance for air [-]
+ wtg0, &! normalized heat conductance for ground [-]
+ wtl0, &! normalized heat conductance for air and leaf [-]
+ wtaq0, &! normalized latent heat conductance for air [-]
+ wtgq0, &! normalized heat conductance for ground [-]
+ wtlq0, &! normalized latent heat cond. for air and leaf [-]
+
+ ei, &! vapor pressure on leaf surface [pa]
+ deidT, &! derivative of "ei" on "tl" [pa/K]
+ qsatl, &! leaf specific humidity [kg/kg]
+ qsatldT, &! derivative of "qsatl" on "tlef"
+
+ del, &! absolute change in leaf temp in current iteration [K]
+ del2, &! change in leaf temperature in previous iteration [K]
+ dele, &! change in heat fluxes from leaf [W/m2]
+ dele2, &! change in heat fluxes from leaf in previous iteration [W/m2]
+ det, &! maximum leaf temp. change in two consecutive iter [K]
+ dee, &! maximum leaf heat fluxes change in two consecutive iter [W/m2]
+
+ obuold, &! monin-obukhov length from previous iteration
+ tlbef, &! leaf temperature from previous iteration [K]
+ ecidif, &! excess energies [W/m2]
+ err, &! balance error
+
+ rssun, &! sunlit leaf stomatal resistance [s/m]
+ rssha, &! shaded leaf stomatal resistance [s/m]
+ fsha, &! shaded fraction of canopy
+ laisun, &! sunlit leaf area index, one-sided
+ laisha, &! shaded leaf area index, one-sided
+ respcsun, &! sunlit leaf respiration rate [umol co2 /m**2/ s] [+]
+ respcsha, &! shaded leaf respiration rate [umol co2 /m**2/ s] [+]
+ rsoil, &! soil respiration
+ gah2o, &! conductance between canopy and atmosphere
+ gdh2o, &! conductance between canopy and ground
+ tprcor ! tf*psur*100./1.013e5
+
+ integer it, nmozsgn
+
+ real(r8) delta, fac
+ real(r8) evplwet, evplwet_dtl, etr_dtl, elwmax, elwdif, etr0, sumrootr
+ real(r8) irab, dirab_dtl, fsenl_dtl, fevpl_dtl
+ real(r8) w, csoilcn, z0mg, cintsun(3), cintsha(3)
+ real(r8) fevpl_bef, fevpl_noadj, dtl_noadj, htvpl, erre
+ real(r8) qevpl, qdewl, qsubl, qfrol, qmelt, qfrz
+
+ real(r8) lt, egvf
+
+ real(r8) :: sqrtdragc !sqrt(drag coefficient)
+ real(r8) :: fai !canopy frontal area index
+ real(r8) :: a_k71 !exponential extinction factor for u/k decline within canopy (Kondo 1971)
+ real(r8) :: fqt, fht, fmtop
+ real(r8) :: utop, ueff, ktop
+ real(r8) :: phih, z0qg, z0hg
+ real(r8) :: hsink, displasink
+ real(r8) gb_mol
+ real(r8),dimension(nl_soil) :: k_soil_root ! radial root and soil conductance
+ real(r8),dimension(nl_soil) :: k_ax_root ! axial root conductance
+
+ integer, parameter :: zd_opt = 3 ! z0 and d with vertical profile consideration
+ integer, parameter :: rb_opt = 3 ! rb with vertical profile consideration
+ integer, parameter :: rd_opt = 3 ! rd with vertical profile consideration
+
+!-----------------------------------------------------------------------
+
+! initialization of errors and iteration parameters
+ it = 1 !counter for leaf temperature iteration
+ del = 0.0 !change in leaf temperature from previous iteration
+ dele = 0.0 !latent head flux from leaf for previous iteration
+
+ dtl(0) = 0.
+ fevpl_bef = 0.
+
+ fht = 0. !integral of profile function for heat
+ fqt = 0. !integral of profile function for moisture
+
+!-----------------------------------------------------------------------
+! scaling-up coefficients from leaf to canopy
+!-----------------------------------------------------------------------
+
+ fsha = 1. -fsun
+ laisun = lai*fsun
+ laisha = lai*fsha
+
+! scaling-up coefficients from leaf to canopy
+ cintsun(1) = (1.-exp(-(0.110+extkb)*lai))/(0.110+extkb)
+ cintsun(2) = (1.-exp(-(extkb+extkd)*lai))/(extkb+extkd)
+ cintsun(3) = (1.-exp(-extkb*lai))/extkb
+
+ cintsha(1) = (1.-exp(-0.110*lai))/0.110 - cintsun(1)
+ cintsha(2) = (1.-exp(-extkd*lai))/extkd - cintsun(2)
+ cintsha(3) = lai - cintsun(3)
+
+!-----------------------------------------------------------------------
+! get fraction of wet and dry canopy surface (fwet & fdry)
+! initial saturated vapor pressure and humidity and their derivation
+!-----------------------------------------------------------------------
+
+ !clai = 4.2 * 1000. * 0.2
+ clai = 0.0
+
+ ! 0.2mm*LSAI, account for leaf (plus dew) heat capacity
+ IF ( DEF_VEG_SNOW ) THEN
+ clai = 0.2*(lai+sai)*cpliq + ldew_rain*cpliq + ldew_snow*cpice
+ ENDIF
+
+ CALL dewfraction (sigf,lai,sai,dewmx,ldew,ldew_rain,ldew_snow,fwet,fdry)
+
+ CALL qsadv(tl,psrf,ei,deiDT,qsatl,qsatlDT)
+
+!-----------------------------------------------------------------------
+! initial for fluxes profile
+!-----------------------------------------------------------------------
+
+ nmozsgn = 0 !number of times moz changes sign
+ obuold = 0. !monin-obukhov length from previous iteration
+ zii = 1000. !m (pbl height)
+ beta = 1. !- (in computing W_*)
+ z0mg = (1.-fsno)*zlnd + fsno*zsno
+ z0hg = z0mg
+ z0qg = z0mg
+
+ z0m = htop * z0mr(patchclass(ipatch))
+ displa = htop * displar(patchclass(ipatch))
+
+ z0mv = z0m; z0hv = z0m; z0qv = z0m
+
+ ! Modify aerodynamic parameters for sparse/dense canopy (X. Zeng)
+ lt = min(lai+sai, 2.)
+ egvf = (1._r8 - exp(-lt)) / (1._r8 - exp(-2.))
+ displa = egvf * displa
+ z0mv = exp(egvf * log(z0mv) + (1._r8 - egvf) * log(z0mg))
+
+ z0hv = z0mv
+ z0qv = z0mv
+
+! 10/17/2017, yuan: z0m and displa with vertical profile solution
+ IF (zd_opt == 3) THEN
+
+ CALL cal_z0_displa(lai+sai, htop, 1., z0mv, displa)
+
+ ! NOTE: adjusted for small displa
+ displasink = max(htop/2., displa)
+ hsink = z0mv + displasink
+
+ z0hv = z0mv
+ z0qv = z0mv
+
+ ENDIF
+
+ fai = 1. - exp(-0.5*(lai+sai))
+ sqrtdragc = min( (0.003+0.3*fai)**0.5, 0.3 )
+
+ a_k71 = htop/(htop-displa)/(vonkar/sqrtdragc)
+
+ taf = 0.5 * (tg + thm)
+ qaf = 0.5 * (qm + qg)
+
+ pco2a = pco2m
+ tprcor = 44.6*273.16*psrf/1.013e5
+ rsoil = 0. !respiration (mol m-2 s-1)
+! rsoil = 1.22e-6*exp(308.56*(1./56.02-1./(tg-227.13)))
+! rsoil = rstfac * 0.23 * 15. * 2.**((tg-273.16-10.)/10.) * 1.e-6
+! rsoil = 5.22 * 1.e-6
+ rsoil = 0.22 * 1.e-6
+
+ ur = max(0.1, sqrt(us*us+vs*vs)) !limit set to 0.1
+ dth = thm - taf
+ dqh = qm - qaf
+ dthv = dth*(1.+0.61*qm) + 0.61*th*dqh
+
+ hu_ = hu; ht_ = ht; hq_ = hq;
+
+ IF (trim(HEIGHT_mode) == 'absolute') THEN
+
+ IF (hu <= htop+1) THEN
+ hu_ = htop + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of u less than htop+1, set it to htop+1.'
+ ENDIF
+
+ IF (ht <= htop+1) THEN
+ ht_ = htop + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of t less than htop+1, set it to htop+1.'
+ ENDIF
+
+ IF (hq <= htop+1) THEN
+ hq_ = htop + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of q less than htop+1, set it to htop+1.'
+ ENDIF
+
+ ELSE ! relative height
+ hu_ = htop + hu
+ ht_ = htop + ht
+ hq_ = htop + hq
+ ENDIF
+
+ zldis = hu_ - displa
+
+ IF(zldis <= 0.0) THEN
+ write(6,*) 'the obs height of u less than the zero displacement heght'
+ CALL abort
+ ENDIF
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mv,um,obu)
+
+! ======================================================================
+! BEGIN stability iteration
+! ======================================================================
+
+ DO WHILE (it .le. itmax)
+
+ tlbef = tl
+
+ del2 = del
+ dele2 = dele
+
+ IF (tl > tfrz) THEN
+ htvpl = hvap
+ ELSE
+ htvpl = hsub
+ ENDIF
+
+!-----------------------------------------------------------------------
+! Aerodynamical resistances
+!-----------------------------------------------------------------------
+! Evaluate stability-dependent variables using moz from prior iteration
+ IF (rd_opt == 3) THEN
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobukm_leddy(hu_,ht_,hq_,displa,z0mv,z0hv,z0qv,obu,um, &
+ displasink,z0mv,hpbl,ustar,fh2m,fq2m, &
+ htop,fmtop,fm,fh,fq,fht,fqt,phih)
+ ELSE
+ CALL moninobukm(hu_,ht_,hq_,displa,z0mv,z0hv,z0qv,obu,um, &
+ displasink,z0mv,ustar,fh2m,fq2m, &
+ htop,fmtop,fm,fh,fq,fht,fqt,phih)
+ ENDIF
+ ! Aerodynamic resistance
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/(fh-fht)*ustar)
+ raw = 1./(vonkar/(fq-fqt)*ustar)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobuk_leddy(hu_,ht_,hq_,displa,z0mv,z0hv,z0qv,obu,um,hpbl, &
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ELSE
+ CALL moninobuk(hu_,ht_,hq_,displa,z0mv,z0hv,z0qv,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+ ENDIF
+ ! Aerodynamic resistance
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/fh*ustar)
+ raw = 1./(vonkar/fq*ustar)
+ ENDIF
+
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+! Bulk boundary layer resistance of leaves
+ uaf = ustar
+ cf = 0.01*sqrtdi/sqrt(uaf)
+ rb = 1/(cf*uaf)
+
+! 11/17/2017, yuan: 3D rb calculation (with vertical profile consideration)
+! 03/13/2020, yuan: added analytical solution
+ IF (rb_opt == 3) THEN
+ utop = ustar/vonkar * fmtop
+ ueff = ueffect(utop, htop, z0mg, z0mg, a_k71, 1._r8, 1._r8)
+ cf = 0.01*sqrtdi*sqrt(ueff)
+ rb = 1./cf
+ ENDIF
+
+! rd = 1./(csoilc*uaf) ! BATS legacy
+! w = exp(-0.5*(lai+sai)) ! Dickinson's modification :
+! csoilc = ( 1.-w + w*um/uaf)/rah ! "rah" here is the resistance over
+! rd = 1./(csoilc*uaf) ! bare ground fraction
+
+! modified by Xubin Zeng's suggestion at 08-07-2002
+ w = exp(-(lai+sai))
+ csoilcn = (vonkar/(0.13*(z0mg*uaf/1.5e-5)**0.45))*w + csoilc*(1.-w)
+ rd = 1./(csoilcn*uaf)
+
+! 11/17/2017, yuan: 3D rd calculation with vertical profile solution
+! 03/13/2020, yuan: added analytical solution
+ IF (rd_opt == 3) THEN
+ ktop = vonkar * (htop-displa) * ustar / phih
+ rd = frd(ktop, htop, z0qg, hsink, z0qg, displa/htop, &
+ z0qg, obug, ustar, z0mg, a_k71, 1._r8, 1._r8)
+ ENDIF
+
+!-----------------------------------------------------------------------
+! stomatal resistances
+!-----------------------------------------------------------------------
+
+ IF(lai .gt. 0.001) THEN
+
+ eah = qaf * psrf / ( 0.622 + 0.378 * qaf ) !pa
+
+ ! If use PHS, calculate maximum stomata conductance (minimum stomata resistance)
+ ! by setting rstfac = 1. (no water stress). When use PHS, stomata only calculate
+ ! non-stress stomata conductance, assimilation rate and leaf respiration
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ rstfacsun = 1.
+ rstfacsha = 1.
+ ENDIF
+
+ ! leaf to canopy level
+ rbsun = rb / laisun
+ rbsha = rb / laisha
+
+ ! Sunlit leaves
+ CALL stomata (vmax25 ,effcon ,c3c4 ,slti ,hlti ,&
+ shti ,hhti ,trda ,trdm ,trop ,&
+ g1 ,g0 ,gradm ,binter ,thm ,&
+ psrf ,po2m ,pco2m ,pco2a ,eah ,&
+ ei ,tl ,parsun ,&
+ !Ozone stress variables
+ o3coefv_sun ,o3coefg_sun ,&
+ !End ozone stress variables
+ !Ozone WUE stomata model parameter
+ lambda ,&
+ !End WUE stomata model parameter
+ rbsun ,raw ,rstfacsun,cintsun ,&
+ assimsun ,respcsun ,rssun )
+
+ ! Shaded leaves
+ CALL stomata (vmax25 ,effcon ,c3c4 ,slti ,hlti ,&
+ shti ,hhti ,trda ,trdm ,trop ,&
+ g1 ,g0 ,gradm ,binter ,thm ,&
+ psrf ,po2m ,pco2m ,pco2a ,eah ,&
+ ei ,tl ,parsha ,&
+ ! Ozone stress variables
+ o3coefv_sha ,o3coefg_sha ,&
+ ! End ozone stress variables
+ ! Ozone WUE stomata model parameter
+ lambda ,&
+ ! End WUE stomata model parameter
+ rbsha ,raw ,rstfacsha,cintsha ,&
+ assimsha ,respcsha ,rssha )
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+
+ gs0sun = min( 1.e6, 1./(rssun*tl/tprcor) )/ laisun * 1.e6 * o3coefg_sun
+ gs0sha = min( 1.e6, 1./(rssha*tl/tprcor) )/ laisha * 1.e6 * o3coefg_sha
+
+ sai = amax1(sai,0.1)
+ ! PHS update actual stomata conductance (resistance), assimilation rate
+ ! and leaf respiration. above stomatal resistances are for the canopy,
+ ! the stomatal resistances and the "rb" in the following calculations are
+ ! the average for single leaf. thus,
+ CALL PlantHydraulicStress_twoleaf ( nl_soil ,nvegwcs ,&
+ z_soi ,dz_soi ,rootfr ,psrf ,qsatl ,&
+ qaf ,tl ,rb ,rss ,raw ,&
+ rd ,rstfacsun ,rstfacsha ,cintsun ,cintsha ,&
+ laisun ,laisha ,rhoair ,fwet ,sai ,&
+ kmax_sun ,kmax_sha ,kmax_xyl ,kmax_root ,psi50_sun ,&
+ psi50_sha ,psi50_xyl ,psi50_root ,htop ,ck ,&
+ smp ,hk ,hksati ,vegwp ,etrsun ,&
+ etrsha ,rootflux ,qg ,qm ,gs0sun ,&
+ gs0sha ,k_soil_root,k_ax_root ,gssun ,gssha )
+
+ etr = etrsun + etrsha
+ gssun = gssun * laisun
+ gssha = gssha * laisha
+
+ CALL update_photosyn(tl, po2m, pco2m, pco2a, parsun, psrf, rstfacsun, rb, gssun, &
+ effcon, vmax25, c3c4, gradm, trop, slti, hlti, shti, hhti, trda, &
+ trdm, cintsun, assimsun, respcsun)
+
+ CALL update_photosyn(tl, po2m, pco2m, pco2a, parsha, psrf, rstfacsha, rb, gssha, &
+ effcon, vmax25, c3c4, gradm, trop, slti, hlti, shti, hhti, trda, &
+ trdm, cintsha, assimsha, respcsha)
+
+ rssun = tprcor/tl * 1.e6 / gssun
+ rssha = tprcor/tl * 1.e6 / gssha
+ ENDIF
+
+ ELSE
+ rssun = 2.e20; assimsun = 0.; respcsun = 0.
+ rssha = 2.e20; assimsha = 0.; respcsha = 0.
+ gssun = 0._r8
+ gssha = 0._r8
+
+ ! 07/2023, yuan: a bug for imbalanced water, rootflux only change
+ ! in DEF_USE_PLANTHYDRAULICS case in this routine.
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ etr = 0.
+ etrsun = 0._r8
+ etrsha = 0._r8
+ rootflux = 0.
+ ENDIF
+ ENDIF
+
+! above stomatal resistances are for the canopy, the stomatal resistances
+! and the "rb" in the following calculations are the average for single leaf. thus,
+ rssun = rssun * laisun
+ rssha = rssha * laisha
+
+!-----------------------------------------------------------------------
+! dimensional and non-dimensional sensible and latent heat conductances
+! for canopy and soil flux calculations.
+!-----------------------------------------------------------------------
+
+ delta = 0.0
+ IF(qsatl-qaf .gt. 0.) delta = 1.0
+
+ cah = 1. / rah
+ cgh = 1. / rd
+ cfh = (lai + sai) / rb
+
+ caw = 1. / raw
+ IF (qg < qaf) THEN
+ cgw = 1. / rd !dew case. no soil resistance
+ ELSE
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ cgw = rss / rd
+ ELSE
+ cgw = 1. / (rd + rss)
+ ENDIF
+ ENDIF
+ cfw = (1.-delta*(1.-fwet))*(lai+sai)/rb + (1.-fwet)*delta* &
+ ( laisun/(rb+rssun) + laisha/(rb+rssha) )
+
+ wtshi = 1. / ( cah + cgh + cfh )
+ wtsqi = 1. / ( caw + cgw + cfw )
+
+ wta0 = cah * wtshi
+ wtg0 = cgh * wtshi
+ wtl0 = cfh * wtshi
+
+ wtaq0 = caw * wtsqi
+ wtgq0 = cgw * wtsqi
+ wtlq0 = cfw * wtsqi
+
+!-----------------------------------------------------------------------
+! IR radiation, sensible and latent heat fluxes and their derivatives
+!-----------------------------------------------------------------------
+! the partial derivatives of areodynamical resistance are ignored
+! which cannot be determined analytically
+ fac = 1. - thermk
+
+! longwave absorption and their derivatives
+ ! 10/16/2017, yuan: added reflected longwave by the ground
+
+IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ irab = (frl - 2. * stefnc * tl**4 + emg*stefnc*tg**4 ) * fac &
+ + (1-emg)*thermk*fac*frl + (1-emg)*(1-thermk)*fac*stefnc*tl**4
+ELSE
+ irab = (frl - 2. * stefnc * tl**4 &
+ + (1.-fsno)*emg*stefnc*t_soil**4 &
+ + fsno*emg*stefnc*t_snow**4 ) * fac &
+ + (1-emg)*thermk*fac*frl + (1-emg)*(1-thermk)*fac*stefnc*tl**4
+ENDIF
+ dirab_dtl = - 8. * stefnc * tl**3 * fac &
+ + 4.*(1-emg)*(1-thermk)*fac*stefnc*tl**3
+
+! sensible heat fluxes and their derivatives
+ fsenl = rhoair * cpair * cfh * ( (wta0 + wtg0)*tl - wta0*thm - wtg0*tg )
+ fsenl_dtl = rhoair * cpair * cfh * (wta0 + wtg0)
+
+! latent heat fluxes and their derivatives
+
+ etr = rhoair * (1.-fwet) * delta &
+ * ( laisun/(rb+rssun) + laisha/(rb+rssha) ) &
+ * ( (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg )
+
+ etrsun = rhoair * (1.-fwet) * delta &
+ * ( laisun/(rb+rssun) ) * ( (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg )
+ etrsha = rhoair * (1.-fwet) * delta &
+ * ( laisha/(rb+rssha) ) * ( (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg )
+
+ etr_dtl = rhoair * (1.-fwet) * delta &
+ * ( laisun/(rb+rssun) + laisha/(rb+rssha) ) &
+ * (wtaq0 + wtgq0)*qsatlDT
+
+ IF (.not. DEF_USE_PLANTHYDRAULICS) THEN
+ IF(etr.ge.etrc)THEN
+ etr = etrc
+ etr_dtl = 0.
+ ENDIF
+ ELSE
+ IF(rstfacsun .lt. 1.e-2 .or. etrsun .le. 0.)etrsun = 0._r8
+ IF(rstfacsha .lt. 1.e-2 .or. etrsha .le. 0.)etrsha = 0._r8
+ etr = etrsun + etrsha
+ IF(abs(etr - sum(rootflux)) .gt. 1.e-7)THEN
+ write(6,*) 'Warning: water balance violation in vegetation PHS', &
+ ipatch,p_iam_glb, etr, sum(rootflux), abs(etr-sum(rootflux))
+ CALL CoLM_stop()
+ ENDIF
+ ENDIF
+
+ evplwet = rhoair * (1.-delta*(1.-fwet)) * (lai+sai) / rb &
+ * ( (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg )
+ evplwet_dtl = rhoair * (1.-delta*(1.-fwet)) * (lai+sai) / rb &
+ * (wtaq0 + wtgq0)*qsatlDT
+
+ IF(evplwet.ge.ldew/deltim)THEN
+ evplwet = ldew/deltim
+ evplwet_dtl = 0.
+ ENDIF
+
+ fevpl = etr + evplwet
+ fevpl_dtl = etr_dtl + evplwet_dtl
+
+ ! 07/09/2014, yuan: added for energy balance
+ erre = 0.
+ fevpl_noadj = fevpl
+ IF ( fevpl*fevpl_bef < 0. ) THEN
+ erre = -0.9*fevpl
+ fevpl = 0.1*fevpl
+ ENDIF
+
+!-----------------------------------------------------------------------
+! difference of temperatures by quasi-newton-raphson method for the non-linear system equations
+! MARK#dtl
+!-----------------------------------------------------------------------
+
+ dtl(it) = (sabv + irab - fsenl - hvap*fevpl &
+ + cpliq*qintr_rain*(t_precip-tl) + cpice*qintr_snow*(t_precip-tl)) &
+ / (clai/deltim - dirab_dtl + fsenl_dtl + hvap*fevpl_dtl &
+ + cpliq*qintr_rain + cpice*qintr_snow)
+
+ dtl_noadj = dtl(it)
+
+ ! check magnitude of change in leaf temperature limit to maximum allowed value
+
+ ! 06/12/2014, yuan: .lt. -> .le.
+ IF(it .le. itmax) THEN
+
+ ! put brakes on large temperature excursions
+ IF(abs(dtl(it)).gt.delmax)THEN
+ dtl(it) = delmax*dtl(it)/abs(dtl(it))
+ ENDIF
+
+ ! 06/12/2014, yuan: .lt. -> .le.
+ ! NOTE: could be a bug IF dtl*dtl==0, changed from lt->le
+ IF((it.ge.2) .and. (dtl(it-1)*dtl(it).le.0.))THEN
+ dtl(it) = 0.5*(dtl(it-1) + dtl(it))
+ ENDIF
+
+ ENDIF
+
+ tl = tlbef + dtl(it)
+
+!-----------------------------------------------------------------------
+! square roots differences of temperatures and fluxes for use as the condition of convergences
+!-----------------------------------------------------------------------
+
+ del = sqrt( dtl(it)*dtl(it) )
+ dele = dtl(it) * dtl(it) * ( dirab_dtl**2 + fsenl_dtl**2 + (hvap*fevpl_dtl)**2 )
+ dele = sqrt(dele)
+
+!-----------------------------------------------------------------------
+! saturated vapor pressures and canopy air temperature, canopy air humidity
+!-----------------------------------------------------------------------
+! Recalculate leaf saturated vapor pressure (ei_)for updated leaf temperature
+! and adjust specific humidity (qsatl_) proportionately
+ CALL qsadv(tl,psrf,ei,deiDT,qsatl,qsatlDT)
+
+! update vegetation/ground surface temperature, canopy air temperature,
+! canopy air humidity
+ taf = wta0*thm + wtg0*tg + wtl0*tl
+ qaf = wtaq0*qm + wtgq0*qg + wtlq0*qsatl
+
+! update co2 partial pressure within canopy air
+ gah2o = 1.0/raw * tprcor/thm !mol m-2 s-1
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ gdh2o = rss/rd * tprcor/thm !mol m-2 s-1
+ ELSE
+ gdh2o = 1.0/(rd+rss) * tprcor/thm !mol m-2 s-1
+ ENDIF
+ pco2a = pco2m - 1.37*psrf/max(0.446,gah2o) * &
+ (assimsun + assimsha - respcsun -respcsha - rsoil)
+
+!-----------------------------------------------------------------------
+! Update monin-obukhov length and wind speed including the stability effect
+!-----------------------------------------------------------------------
+
+ dth = thm - taf
+ dqh = qm - qaf
+
+ tstar = vonkar/(fh-fht)*dth
+ qstar = vonkar/(fq-fqt)*dqh
+
+ thvstar = tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta = zldis*vonkar*grav*thvstar / (ustar**2*thv)
+ IF(zeta .ge. 0.)THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF(zeta .ge. 0.)THEN
+ um = max(ur,.1)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ zii = max(5.*hu_,hpbl)
+ ENDIF !//TODO: Shaofeng, 2023.05.18
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF(obuold*obu .lt. 0.) nmozsgn = nmozsgn+1
+ IF(nmozsgn .ge. 4) obu = zldis/(-0.01)
+ obuold = obu
+
+!-----------------------------------------------------------------------
+! Test for convergence
+!-----------------------------------------------------------------------
+
+ it = it+1
+
+ IF(it .gt. itmin) THEN
+ fevpl_bef = fevpl
+ det = max(del,del2)
+ ! 10/03/2017, yuan: possible bugs here, solution:
+ ! define dee, change del => dee
+ dee = max(dele,dele2)
+ IF(det .lt. dtmin .and. dee .lt. dlemin) EXIT
+ ENDIF
+
+ ENDDO
+
+ IF(DEF_USE_OZONESTRESS)THEN
+ CALL CalcOzoneStress(o3coefv_sun,o3coefg_sun,forc_ozone,psrf,th,ram,&
+ rssun,rb,lai,lai_old,ivt,o3uptakesun,sabv,deltim)
+ CALL CalcOzoneStress(o3coefv_sha,o3coefg_sha,forc_ozone,psrf,th,ram,&
+ rssha,rb,lai,lai_old,ivt,o3uptakesha,sabv,deltim)
+ lai_old = lai
+ assimsun = assimsun * o3coefv_sun
+ assimsha = assimsha * o3coefv_sha
+! rssun = rssun / o3coefg_sun
+! rssha = rssha / o3coefg_sha
+ ELSE
+ o3coefv_sun = 1.0_r8
+ o3coefg_sun = 1.0_r8
+ o3coefv_sha = 1.0_r8
+ o3coefg_sha = 1.0_r8
+ ENDIF
+
+! ======================================================================
+! END stability iteration
+! ======================================================================
+
+ z0m = z0mv
+ zol = zeta
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+! canopy fluxes and total assimilation amd respiration
+
+ IF(lai .gt. 0.001) THEN
+ rst = 1./(laisun/rssun + laisha/rssha)
+ ELSE
+ rssun = 2.0e4 ; rssha = 2.0e4
+ assimsun = 0. ; assimsha = 0.
+ respcsun = 0. ; respcsha = 0.
+ rst = 2.0e4
+ ENDIF
+ assim = assimsun + assimsha
+ respc = respcsun + respcsha! + rsoil
+
+! canopy fluxes and total assimilation amd respiration
+ fsenl = fsenl + fsenl_dtl*dtl(it-1) &
+ ! yuan: add the imbalanced energy below due to T adjustment to sensible heat
+ + (dtl_noadj-dtl(it-1)) * (clai/deltim - dirab_dtl + fsenl_dtl + hvap*fevpl_dtl &
+ + cpliq * qintr_rain + cpice * qintr_snow) &
+ ! yuan: add the imbalanced energy below due to q adjustment to sensible heat
+ + hvap*erre
+
+ etr0 = etr
+ etr = etr + etr_dtl*dtl(it-1)
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ !TODO@yuan: rootflux may not be consistent with etr,
+ ! water imbalance could happen.
+ IF (abs(etr0) .ge. 1.e-15) THEN
+ rootflux = rootflux * etr / etr0
+ ELSE
+ rootflux = rootflux + dz_soi / sum(dz_soi) * etr_dtl* dtl(it-1)
+ ENDIF
+
+! !NOTE: temporal solution to make etr and rootflux consistent.
+! !TODO: need double check
+! sumrootr = sum(rootr(:), rootr(:)>0.)
+! IF (abs(sumrootr) > 0.) THEN
+! rootr(:) = max(rootr(:),0.) * (etr/sumrootr)
+! ELSE
+! rootr(:) = etr*rootfr(:)
+! ENDIF
+ ENDIF
+
+ evplwet = evplwet + evplwet_dtl*dtl(it-1)
+ fevpl = fevpl_noadj
+ fevpl = fevpl + fevpl_dtl*dtl(it-1)
+
+ elwmax = ldew/deltim
+ elwdif = max(0., evplwet-elwmax)
+ evplwet = min(evplwet, elwmax)
+
+ fevpl = fevpl - elwdif
+ fsenl = fsenl + hvap*elwdif
+
+ taux = - rhoair*us/ram
+ tauy = - rhoair*vs/ram
+
+!-----------------------------------------------------------------------
+! fluxes from ground to canopy space
+!-----------------------------------------------------------------------
+
+ fseng = cpair*rhoair*cgh*(tg-taf)
+! 03/07/2020, yuan: calculate fseng_soil/snow
+ !NOTE: taf = wta0*thm + wtg0*tg + wtl0*tl
+ fseng_soil = cpair*rhoair*cgh*((1.-wtg0)*t_soil - wta0*thm - wtl0*tl)
+ fseng_snow = cpair*rhoair*cgh*((1.-wtg0)*t_snow - wta0*thm - wtl0*tl)
+
+! 03/07/2020, yuan: calculate fevpg_soil/snow
+ !NOTE: qaf = wtaq0*qm + wtgq0*qg + wtlq0*qsatl
+ fevpg = rhoair*cgw*(qg-qaf)
+ fevpg_soil = rhoair*cgw*((1.-wtgq0)*q_soil - wtaq0*qm - wtlq0*qsatl)
+ fevpg_snow = rhoair*cgw*((1.-wtgq0)*q_snow - wtaq0*qm - wtlq0*qsatl)
+
+!-----------------------------------------------------------------------
+! downward (upward) longwave radiation below (above) the canopy and prec. sensible heat
+!-----------------------------------------------------------------------
+
+ ! 10/16/2017, yuan: added reflected longwave by the ground
+ dlrad = thermk * frl &
+ + stefnc * fac * tlbef**3 * (tlbef + 4.*dtl(it-1))
+
+IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ ulrad = stefnc * ( fac * tlbef**3 * (tlbef + 4.*dtl(it-1)) &
+ + thermk*emg*tg**4 ) &
+ + (1-emg)*thermk*thermk*frl &
+ + (1-emg)*thermk*fac*stefnc*tlbef**4 &
+ + 4.*(1-emg)*thermk*fac*stefnc*tlbef**3*dtl(it-1)
+ELSE
+ ulrad = stefnc * ( fac * tlbef**3 * (tlbef + 4.*dtl(it-1)) &
+ + (1.-fsno)*thermk*emg*t_soil**4 &
+ + fsno*thermk*emg*t_snow**4 ) &
+ + (1-emg)*thermk*thermk*frl &
+ + (1-emg)*thermk*fac*stefnc*tlbef**4 &
+ + 4.*(1-emg)*thermk*fac*stefnc*tlbef**3*dtl(it-1)
+ENDIF
+ ! precipitation sensible heat from canopy
+ hprl = cpliq * qintr_rain*(t_precip-tl) + cpice * qintr_snow*(t_precip-tl)
+
+ ! vegetation heat change
+ dheatl = clai/deltim*dtl(it-1)
+
+!-----------------------------------------------------------------------
+! Derivative of soil energy flux with respect to soil temperature (cgrnd)
+!-----------------------------------------------------------------------
+
+ cgrnds = cpair*rhoair*cgh*(1.-wtg0)
+ cgrndl = rhoair*cgw*(1.-wtgq0)*dqgdT
+ cgrnd = cgrnds + cgrndl*htvp
+
+!-----------------------------------------------------------------------
+! balance check
+! (the computational error was created by the assumed 'dtl' in MARK#dtl)
+!-----------------------------------------------------------------------
+
+ err = sabv + irab + dirab_dtl*dtl(it-1) - fsenl - hvap*fevpl + hprl &
+ ! account for vegetation heat change
+ - dheatl
+
+#if (defined CoLMDEBUG)
+ IF(abs(err) .gt. .2) &
+ write(6,*) 'energy imbalance in LeafTemperature.F90',it-1,&
+ err,sabv,irab,fsenl,hvap*fevpl,hprl,dheatl
+#endif
+
+!-----------------------------------------------------------------------
+! Update dew accumulation (kg/m2)
+!-----------------------------------------------------------------------
+ IF (DEF_Interception_scheme .eq. 1) THEN
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 2) THEN !CLM4.5
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 3) THEN !CLM5
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 4) THEN !Noah-MP
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 5) THEN !MATSIRO
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 6) THEN !VIC
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 7) THEN !JULES
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 8) THEN !CoLM202X
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+ ELSE
+ CALL abort
+ ENDIF
+
+ ! Bug fix: When DEF_VEG_SNOW is false, only ldew is updated above
+ ! (via ldew = max(0., ldew - evplwet*deltim)), but ldew_rain/ldew_snow
+ ! remain unchanged. Downstream interception routines (schemes 1, 3-8)
+ ! resync ldew = ldew_rain + ldew_snow at entry, which would silently
+ ! revert the evaporation adjustment. Fix by scaling components proportionally.
+ IF (.not. DEF_VEG_SNOW) THEN
+ IF (ldew_rain + ldew_snow > 1.e-10) THEN
+ ldew_rain = ldew * (ldew_rain / (ldew_rain + ldew_snow))
+ ldew_snow = ldew - ldew_rain
+ ELSEIF (ldew > 0.) THEN
+ ! Components were zero but ldew > 0 (condensation case)
+ IF (tl > tfrz) THEN
+ ldew_rain = ldew
+ ldew_snow = 0.
+ ELSE
+ ldew_rain = 0.
+ ldew_snow = ldew
+ ENDIF
+ ELSE
+ ldew_rain = 0.
+ ldew_snow = 0.
+ ENDIF
+ ENDIF
+
+ IF ( DEF_VEG_SNOW ) THEN
+ ! update fwet_snow
+ fwet_snow = 0
+ IF(ldew_snow > 0.) THEN
+ fwet_snow = ((10./(48.*(lai+sai)))*ldew_snow)**.666666666666
+ ! Check for maximum limit of fwet_snow
+ fwet_snow = min(fwet_snow,1.0)
+ ENDIF
+
+ ! phase change
+
+ qmelt = 0.
+ qfrz = 0.
+
+ !TODO: double check below
+ IF (ldew_snow.gt.1.e-6 .and. tl.gt.tfrz) THEN
+ qmelt = min(ldew_snow/deltim,(tl-tfrz)*cpice*ldew_snow/(deltim*hfus))
+ ldew_snow = max(0.,ldew_snow - qmelt*deltim)
+ ldew_rain = max(0.,ldew_rain + qmelt*deltim)
+ !NOTE: There may be some problem, energy imbalance
+ ! However, detailed treatment could be somewhat trivial
+ tl = fwet_snow*tfrz + (1.-fwet_snow)*tl !Niu et al., 2004
+ ENDIF
+
+ IF (ldew_rain.gt.1.e-6 .and. tl.lt.tfrz) THEN
+ qfrz = min(ldew_rain/deltim,(tfrz-tl)*cpliq*ldew_rain/(deltim*hfus))
+ ldew_rain = max(0.,ldew_rain - qfrz*deltim)
+ ldew_snow = max(0.,ldew_snow + qfrz*deltim)
+ !NOTE: There may be some problem, energy imbalance
+ ! However, detailed treatment could be somewhat trivial
+ tl = fwet_snow*tfrz + (1.-fwet_snow)*tl !Niu et al., 2004
+ ENDIF
+ ENDIF
+
+!-----------------------------------------------------------------------
+! 2 m height air temperature
+!-----------------------------------------------------------------------
+ tref = thm + vonkar/(fh-fht)*dth * (fh2m/vonkar - fh/vonkar)
+ qref = qm + vonkar/(fq-fqt)*dqh * (fq2m/vonkar - fq/vonkar)
+
+ END SUBROUTINE LeafTemperature
+!----------------------------------------------------------------------
+
+ SUBROUTINE dewfraction (sigf,lai,sai,dewmx,ldew,ldew_rain,ldew_snow,fwet,fdry)
+ !DESCRIPTION
+ !===========
+ ! determine fraction of foliage covered by water and
+ ! fraction of foliage that is dry and transpiring
+
+ !Original Author:
+ !-------------------
+ !---Yongjiu Dai
+
+ !References:
+ !-------------------
+ !---Dai, Y., Zeng, X., Dickinson, R.E., Baker, I., Bonan, G.B., BosiloVICh, M.G., Denning,
+ ! A.S., Dirmeyer, P.A., Houser, P.R., Niu, G. and Oleson, K.W., 2003. The common land
+ ! model. Bulletin of the American Meteorological Society, 84(8), pp.1013-1024.
+
+ !ANCILLARY FUNCTIONS AND SUBROUTINES
+ !-------------------
+
+ !REVISION HISTORY
+ !----------------
+ !---2024.04.16 Hua Yuan: add option to account for vegetation snow process
+ !---2021.12.08 Zhongwang Wei @ SYSU
+ !---2018.06 Hua Yuan: remove sigf, to compatible with PFT
+ !---1999.09.15 Yongjiu Dai
+ !=======================================================================
+
+ USE MOD_Precision
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: dewmx !maximum allowed dew [0.1 mm]
+ real(r8), intent(in) :: ldew !depth of water on foliage [kg/m2/s]
+ real(r8), intent(in) :: ldew_rain !depth of rain on foliage [kg/m2/s]
+ real(r8), intent(in) :: ldew_snow !depth of snow on foliage [kg/m2/s]
+ real(r8), intent(out) :: fwet !fraction of foliage covered by water&snow [-]
+ real(r8), intent(out) :: fdry !fraction of foliage that is green and dry [-]
+
+ real(r8) :: lsai !lai + sai
+ real(r8) :: dewmxi !inverse of maximum allowed dew [1/mm]
+ real(r8) :: vegt !sigf*lsai, NOTE: remove sigf
+ real(r8) :: satcap_rain !saturation capacity of foliage for rain [kg/m2]
+ real(r8) :: satcap_snow !saturation capacity of foliage for snow [kg/m2]
+ real(r8) :: fwet_rain !fraction of foliage covered by water [-]
+ real(r8) :: fwet_snow !fraction of foliage covered by snow [-]
+
+ !-----------------------------------------------------------------------
+ ! Fwet is the fraction of all vegetation surfaces which are wet
+ ! including stem area which contribute to evaporation
+ lsai = lai + sai ! effective leaf area index
+ dewmxi = 1.0/dewmx
+ ! 06/2018, yuan: remove sigf, to compatible with PFT
+ vegt = lsai
+
+ fwet = 0
+ IF (ldew > 0.) THEN
+ fwet = ((dewmxi/vegt)*ldew)**.666666666666
+ ! Check for maximum limit of fwet
+ fwet = min(fwet,1.0)
+ ENDIF
+
+ ! account for vegetation snow
+ ! calculate fwet_rain, fwet_snow, fwet
+ IF ( DEF_VEG_SNOW ) THEN
+
+ fwet_rain = 0
+ IF(ldew_rain > 0.) THEN
+ fwet_rain = ((dewmxi/vegt)*ldew_rain)**.666666666666
+ ! Check for maximum limit of fwet_rain
+ fwet_rain = min(fwet_rain,1.0)
+ ENDIF
+
+ fwet_snow = 0
+ IF(ldew_snow > 0.) THEN
+ fwet_snow = ((dewmxi/(48.*vegt))*ldew_snow)**.666666666666
+ ! Check for maximum limit of fwet_snow
+ fwet_snow = min(fwet_snow,1.0)
+ ENDIF
+
+ fwet = fwet_rain + fwet_snow - fwet_rain*fwet_snow
+ fwet = min(fwet,1.0)
+ ENDIF
+
+ ! fdry is the fraction of lai which is dry because only leaves can
+ ! transpire. Adjusted for stem area which does not transpire
+ fdry = (1.-fwet)*lai/lsai
+
+ END SUBROUTINE dewfraction
+
+END MODULE MOD_LeafTemperature
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafTemperaturePC.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafTemperaturePC.F90
new file mode 100644
index 0000000000..df68a494b7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LeafTemperaturePC.F90
@@ -0,0 +1,2145 @@
+#include
+
+MODULE MOD_LeafTemperaturePC
+
+!-----------------------------------------------------------------------
+!
+! --- Leaf Temperature and Turbulence Modeling ---
+! for Plant Community (PC) Simulation
+!
+! o Reference hight
+! |
+! |
+! _____ tree | _____ --- Layer3
+! ||||||| | |||||||
+! |||||||||--\/\/\/o |||||||||
+! \|||||/ | \|||||/
+! | | | --- Layer2
+! | | | shrub /xx\
+! | grass -/\/-o--------|---\/\/\--\xx/
+! ____________|_____\\//____________|___________||__ --- Layer1
+! /////////////////////////////////////////////////////////////////////
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_CBL_HEIGHT, DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, &
+ DEF_RSS_SCHEME, DEF_Interception_scheme, DEF_SPLIT_SOILSNOW, &
+ DEF_VEG_SNOW
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: LeafTemperaturePC
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: dewfraction
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE LeafTemperaturePC ( &
+ ipatch ,ps ,pe ,deltim ,csoilc ,dewmx ,&
+ htvp ,pftclass ,fcover ,htop ,hbot ,lai ,&
+ sai ,extkb ,extkd ,hu ,ht ,hq ,&
+ us ,vs ,forc_t ,thm ,th ,thv ,&
+ qm ,psrf ,rhoair ,parsun ,parsha ,fsun ,&
+ sabv ,frl ,thermk ,fshade ,rstfacsun ,rstfacsha ,&
+ gssun ,gssha ,po2m ,pco2m ,z0h_g ,obug ,&
+ ustarg ,zlnd ,zsno ,fsno ,sigf ,etrc ,&
+ tg ,qg ,rss ,dqgdT ,emg ,t_soil ,&
+ t_snow ,q_soil ,q_snow ,z0mpc ,tl ,ldew ,&
+ ldew_rain ,ldew_snow ,fwet_snow ,taux ,tauy ,fseng ,&
+ fseng_soil ,fseng_snow ,fevpg ,fevpg_soil ,fevpg_snow ,cgrnd ,&
+ cgrndl ,cgrnds ,tref ,qref ,rst ,assim ,&
+ respc ,fsenl ,fevpl ,etr ,dlrad ,ulrad ,&
+ z0m ,zol ,rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,vegwp ,gs0sun ,gs0sha ,&
+ assimsun ,etrsun ,assimsha ,etrsha ,&
+!Ozone stress variables
+ o3coefv_sun,o3coefv_sha,o3coefg_sun,o3coefg_sha,&
+ lai_old ,o3uptakesun,o3uptakesha,forc_ozone ,&
+!End ozone stress variables
+ hpbl, &
+ qintr_rain ,qintr_snow ,t_precip ,hprl ,&
+ dheatl ,smp ,hk ,hksati ,&
+ rootflux )
+
+!=======================================================================
+!
+! !DESCRIPTION:
+! Leaf temperature resolved for Plant Community (3D) case Foliage
+! energy conservation for each PFT is given by foliage energy budget
+! equation:
+! Rnet - Hf - LEf = 0
+! The equation is solved by Newton-Raphson iteration, in which this
+! iteration includes the calculation of the photosynthesis and stomatal
+! resistance, and the integration of turbulent flux profiles. The
+! sensible and latent heat transfer between foliage and atmosphere and
+! ground is linked by the equations:
+! Ha = Hf + Hg and Ea = Ef + Eg
+!
+! Original author: Hua Yuan and Yongjiu Dai, September, 2017
+!
+!
+! !REFERENCES:
+! 1) Dai, Y., Yuan, H., Xin, Q., Wang, D., Shangguan, W., Zhang, S., et
+! al. (2019). Different representations of canopy structure—A large
+! source of uncertainty in global land surface modeling. Agricultural
+! and Forest Meteorology, 269-270, 119-135.
+! https://doi.org/10.1016/j.agrformet.2019.02.006
+!
+! !REVISIONS:
+!
+! 01/2021, Xingjie Lu and Nan Wei: added plant hydraulic process
+! interface.
+!
+! 01/2021, Nan Wei: added interaction btw prec and canopy.
+!
+! 05/2023, Shaofeng Liu: add option to call moninobuk_leddy, the
+! LargeEddy surface turbulence scheme (LZD2022); make a proper
+! update of um.
+!
+! 04/2024, Hua Yuan: add option to account for vegetation snow process.
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: vonkar, grav, hvap, hsub, cpair, stefnc, &
+ cpliq, cpice, hfus, tfrz, denice, denh2o
+ USE MOD_Const_PFT
+ USE MOD_FrictionVelocity
+ USE MOD_CanopyLayerProfile
+ USE MOD_TurbulenceLEddy
+ USE MOD_Qsadv
+ USE MOD_AssimStomataConductance
+ USE MOD_PlantHydraulic, only: PlantHydraulicStress_twoleaf
+ USE MOD_Ozone, only: CalcOzoneStress
+ USE MOD_UserSpecifiedForcing, only: HEIGHT_mode
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: ipatch
+ integer, intent(in) :: &
+ ps, &! start PFT index in a patch
+ pe ! end PFT index in a patch
+
+ real(r8), intent(in) :: &
+ deltim, &! seconds in a time step [second]
+ csoilc, &! drag coefficient for soil under canopy [-]
+ dewmx, &! maximum dew
+ htvp ! latent heat of evaporation (/sublimation) [J/kg]
+
+! vegetation parameters
+ integer, dimension(ps:pe), intent(in) :: &
+ pftclass ! PFT class
+
+ real(r8), dimension(ps:pe), intent(in) :: &
+ fcover, &! PFT fractional coverage [-]
+ htop, &! PFT crown top height [m]
+ hbot, &! PFT crown bottom height [m]
+ lai, &! adjusted leaf area index for seasonal variation [-]
+ sai ! stem area index [-]
+
+ real(r8), intent(inout) :: &
+ vegwp(1:nvegwcs,ps:pe), &! vegetation water potential
+ gs0sun(ps:pe), &! maximum stomata conductance of sunlit leaf
+ gs0sha(ps:pe) ! maximum stomata conductance of shaded leaf
+
+! input variables
+ real(r8), intent(in) :: &
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ forc_t, &! temperature at agcm reference height [kelvin]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ qm, &! specific humidity at reference height [kg/kg]
+ psrf, &! pressure at reference height [pa]
+ rhoair, &! density air [kg/m**3]
+
+ parsun(ps:pe), &! par absorbed per unit sunlit lai [w/m**2]
+ parsha(ps:pe), &! par absorbed per unit shaded lai [w/m**2]
+ fsun (ps:pe), &! sunlit fraction of canopy
+ sabv (ps:pe), &! solar radiation absorbed by vegetation [W/m2]
+ frl, &! atmospheric infrared (longwave) radiation [W/m2]
+
+ extkb (ps:pe), &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd (ps:pe), &! diffuse and scattered diffuse PAR extinction coefficient
+ thermk(ps:pe), &! canopy gap fraction for tir radiation
+ fshade(ps:pe), &! shadow for each PFT
+
+ po2m, &! atmospheric partial pressure o2 (pa)
+ pco2m, &! atmospheric partial pressure co2 (pa)
+
+ z0h_g, &! bare soil roughness length, sensible heat [m]
+ obug, &! bare soil obu
+ ustarg, &! bare soil ustar
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+ fsno, &! fraction of snow cover on ground
+
+ sigf (ps:pe), &! fraction of veg cover, excluding snow-covered veg [-]
+ etrc (ps:pe), &! maximum possible transpiration rate (mm/s)
+ tg, &! ground surface temperature [K]
+ t_soil, &! ground surface soil temperature [K]
+ t_snow, &! ground surface snow temperature [K]
+ qg, &! specific humidity at ground surface [kg/kg]
+ q_soil, &! specific humidity at ground surface soil [kg/kg]
+ q_snow, &! specific humidity at ground surface snow [kg/kg]
+ dqgdT, &! temperature derivative of "qg"
+ rss, &! soil surface resistance [s/m]
+ emg ! vegetation emissivity
+
+ real(r8), intent(in) :: &
+ t_precip, &! snowfall/rainfall temperature [kelvin]
+ qintr_rain(ps:pe), &! rainfall interception (mm h2o/s)
+ qintr_snow(ps:pe), &! snowfall interception (mm h2o/s)
+ smp (1:nl_soil), &! precipitation sensible heat from canopy
+ hksati (1:nl_soil), &! hydraulic conductivity at saturation [mm h2o/s]
+ hk (1:nl_soil) ! soil hydraulic conductance
+
+ real(r8), intent(in) :: &
+ hpbl ! atmospheric boundary layer height [m]
+
+ real(r8), dimension(ps:pe), intent(inout) :: &
+ tl, &! leaf temperature [K]
+ ldew, &! depth of water on foliage [mm]
+ ldew_rain, &! depth of rain on foliage [mm]
+ ldew_snow, &! depth of snow on foliage [mm]
+ fwet_snow, &! vegetation snow fractional cover [-]
+!Ozone stress variables
+ lai_old , &! lai in last time step
+ o3uptakesun, &! Ozone does, sunlit leaf (mmol O3/m^2)
+ o3uptakesha, &! Ozone does, shaded leaf (mmol O3/m^2)
+ o3coefv_sun, &! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefv_sha, &! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefg_sun, &! Ozone stress factor for stomata on shaded leaf
+ o3coefg_sha, &! Ozone stress factor for stomata on shaded leaf
+!End ozone stress variables
+ rstfacsun, &! factor of soil water stress to transpiration on sunlit leaf
+ rstfacsha, &! factor of soil water stress to transpiration on shaded leaf
+ gssun, &! stomata conductance of sunlit leaf
+ gssha ! stomata conductance of shaded leaf
+
+ real(r8), dimension(ps:pe), intent(inout) :: &
+ assimsun, &! sunlit leaf assimilation rate [umol co2 /m**2/ s] [+]
+ etrsun, &! transpiration rate of sunlit leaf [mm/s]
+ assimsha, &! shaded leaf assimilation rate [umol co2 /m**2/ s] [+]
+ etrsha ! transpiration rate of shaded leaf [mm/s]
+
+!Ozone stress variables
+ real(r8), intent(inout) :: forc_ozone
+!End ozone stress variables
+
+ real(r8), intent(inout) :: &
+ dlrad, &! downward longwave radiation blow the canopy [W/m2]
+ ulrad, &! upward longwave radiation above the canopy [W/m2]
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fseng_soil, &! sensible heat flux from ground soil [W/m2]
+ fseng_snow, &! sensible heat flux from ground snow [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+ fevpg_soil, &! evaporation heat flux from ground soil [mm/s]
+ fevpg_snow, &! evaporation heat flux from ground snow [mm/s]
+ tref, &! 2 m height air temperature (kelvin)
+ qref, &! 2 m height air specific humidity
+ rootflux(nl_soil,ps:pe) ! root water uptake from different layers
+
+ real(r8), dimension(ps:pe), intent(out) :: &
+ z0mpc, &! z0m for individual PFT
+ rst, &! stomatal resistance
+ assim, &! rate of assimilation
+ respc, &! rate of respiration
+ fsenl, &! sensible heat from leaves [W/m2]
+ fevpl, &! evaporation+transpiration from leaves [mm/s]
+ etr, &! transpiration rate [mm/s]
+ hprl, &! precipitation sensible heat from canopy
+ dheatl ! vegetation heat change [W/m2]
+
+ real(r8), intent(inout) :: &
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+ real(r8), intent(inout) :: &
+ cgrnd, &! deriv. of soil energy flux wrt to soil temp [w/m2/k]
+ cgrndl, &! deriv, of soil latent heat flux wrt soil temp [w/m2/k]
+ cgrnds ! deriv of soil sensible heat flux wrt soil temp [w/m**2/k]
+
+!-------------------------- Local Variables ----------------------------
+! assign iteration parameters
+ integer, parameter :: itmax = 40 !maximum number of iteration
+ integer, parameter :: itmin = 6 !minimum number of iteration
+ real(r8),parameter :: delmax = 3.0 !maximum change in leaf temperature [K]
+ real(r8),parameter :: dtmin = 0.01 !max limit for temperature convergence [K]
+ real(r8),parameter :: dlemin = 0.1 !max limit for energy flux convergence [w/m2]
+
+ real(r8) dtl(0:itmax+1,ps:pe) !difference of tl between two iterative step
+
+ !TODO: read from mod_const_pft.F90
+ real(r8), dimension(ps:pe) :: &
+ canlay, &! PFT canopy layer number
+ sqrtdi ! inverse sqrt of leaf dimension [m**-0.5]
+
+ !TODO: read from mod_const_pft.F90 file
+ real(r8), dimension(ps:pe) :: &
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2 / mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ ! the range : 30.e-6 <-> 100.e-6 (mol co2 m-2 s-1)
+ shti, &! slope of high temperature inhibition function (s1)
+ hhti, &! 1/2 point of high temperature inhibition function (s2)
+ slti, &! slope of low temperature inhibition function (s3)
+ hlti, &! 1/2 point of low temperature inhibition function (s4)
+ trda, &! temperature coefficient in gs-a model (s5)
+ trdm, &! temperature coefficient in gs-a model (s6)
+ trop, &! temperature coefficient in gs-a model (273+25)
+ g1, &! conductance-photosynthesis slope parameter for medlyn model
+ g0, &! conductance-photosynthesis intercept for medlyn model
+ gradm, &! conductance-photosynthesis slope parameter
+ binter, &! conductance-photosynthesis intercept
+ lambda, &! marginal water cost of carbon gain
+ extkn ! coefficient of leaf nitrogen allocation
+
+ integer, dimension(ps:pe) :: &
+ c3c4 ! C3/C4 plant type
+
+ real(r8), dimension(ps:pe) :: &
+ kmax_sun, &! Plant Hydraulics Parameters
+ kmax_sha, &! Plant Hydraulics Parameters
+ kmax_xyl, &! Plant Hydraulics Parameters
+ kmax_root, &! Plant Hydraulics Parameters
+ psi50_sun, &! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ psi50_sha, &! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ psi50_xyl, &! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ psi50_root, &! water potential at 50% loss of root tissue conductance (mmH2O)
+ ck ! shape-fitting parameter for vulnerability curve (-)
+
+ real(r8) :: &
+ rootfr(nl_soil,ps:pe) ! root fraction
+
+ real(r8) :: &
+ hu_, &! adjusted observational height of wind [m]
+ ht_, &! adjusted observational height of temperature [m]
+ hq_, &! adjusted observational height of humidity [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ zii, &! convective boundary layer height [m]
+ z0mv, &! roughness length, momentum [m]
+ z0hv, &! roughness length, sensible heat [m]
+ z0qv, &! roughness length, latent heat [m]
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ beta, &! coefficient of convective velocity [-]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ dth, &! diff of virtual temp. between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ um, &! wind speed including the stability effect [m/s]
+ ur, &! wind speed at reference height [m/s]
+ uaf, &! velocity of air within foliage [m/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile function for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ eah, &! canopy air vapor pressure (pa)
+ pco2g, &! co2 pressure (pa) at ground surface (pa)
+ pco2a, &! canopy air co2 pressure (pa)
+
+ cf, &! heat transfer coefficient from leaves [-]
+ rbsun, &! bulk boundary layer resistance of sunlit fraction of canopy
+ rbsha, &! bulk boundary layer resistance of shaded fraction of canopy
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+
+ det, &! maximum leaf temp. change in two consecutive iter [K]
+ dee, &! maximum leaf heat fluxes change in two consecutive iter [W/m2]
+ obuold, &! monin-obukhov length from previous iteration
+ err, &! balance error
+
+ rsoil, &! soil respiration
+ gah2o, &! conductance between canopy and atmosphere
+ gdh2o, &! conductance between canopy and ground
+ tprcor, &! tf*psur*100./1.013e5
+
+ fht, &! integral of profile function for heat at the top layer
+ fqt, &! integral of profile function for moisture at the top layer
+ phih, &! phi(h), similarity function for sensible heat
+
+ clai (ps:pe), &! canopy heat capacity [Jm-2K-1]
+ fdry (ps:pe), &! fraction of foliage that is green and dry [-]
+ fwet (ps:pe), &! fraction of foliage covered by water [-]
+ rb (ps:pe), &! leaf boundary layer resistance [s/m]
+ cfh (ps:pe), &! heat conductance for leaf [m/s]
+ cfw (ps:pe), &! latent heat conductance for leaf [m/s]
+ wlh (ps:pe), &! normalized heat conductance for air and leaf [-]
+ wlq (ps:pe), &! normalized latent heat cond. for air and leaf [-]
+
+ ei (ps:pe), &! vapor pressure on leaf surface [pa]
+ deidT (ps:pe), &! derivative of "ei" on "tl" [pa/K]
+ qsatl (ps:pe), &! leaf specific humidity [kg/kg]
+ qsatldT (ps:pe), &! derivative of "qsatl" on "tlef"
+
+ del (ps:pe), &! absolute change in leaf temp in current iteration [K]
+ del2 (ps:pe), &! change in leaf temperature in previous iteration [K]
+ dele (ps:pe), &! change in heat fluxes from leaf [W/m2]
+ dele2 (ps:pe), &! change in heat fluxes from leaf in previous iteration [W/m2]
+
+ tlbef (ps:pe), &! leaf temperature from previous iteration [K]
+ fsha (ps:pe), &! shaded fraction of canopy
+ laisun (ps:pe), &! sunlit leaf area index, one-sided
+ laisha (ps:pe), &! shaded leaf area index, one-sided
+ rssun (ps:pe), &! sunlit leaf stomatal resistance [s/m]
+ rssha (ps:pe), &! shaded leaf stomatal resistance [s/m]
+ respcsun (ps:pe), &! sunlit leaf respiration rate [umol co2 /m**2/ s] [+]
+ respcsha (ps:pe) ! shaded leaf respiration rate [umol co2 /m**2/ s] [+]
+
+ integer it, nmozsgn
+
+ real(r8) w, csoilcn, z0mg, z0hg, z0qg, elwmax, elwdif, sumrootflux
+ real(r8) cintsun(3, ps:pe), cintsha(3, ps:pe)
+ real(r8),dimension(ps:pe) :: delta, fac, etr0
+ real(r8),dimension(ps:pe) :: irab, dirab_dtl, fsenl_dtl, fevpl_dtl
+ real(r8),dimension(ps:pe) :: evplwet, evplwet_dtl, etr_dtl
+ real(r8),dimension(ps:pe) :: fevpl_bef, fevpl_noadj, dtl_noadj, htvpl, erre
+ real(r8),dimension(ps:pe) :: qevpl, qdewl, qsubl, qfrol, qmelt, qfrz
+ real(r8),dimension(ps:pe) :: gb_mol_sun,gb_mol_sha
+ real(r8),dimension(nl_soil) :: k_soil_root ! radial root and soil conductance
+ real(r8),dimension(nl_soil) :: k_ax_root ! axial root conductance
+
+ ! .................................................................
+ ! definition for 3d run
+ ! .................................................................
+
+ integer , parameter :: nlay = 3
+
+ real(r8), parameter :: &
+ c1 = 0.320, &! parameter to calculate drag coefficients of Massman's method
+ c2 = 0.264, &! parameter to calculate drag coefficients of Massman's method
+ c3 = 15.1, &! parameter to calculate drag coefficients of Massman's method
+ iw = 0.5, &! parameter to calculate alpha of Goudriaa's method
+ Cd = 0.2, &! leaf drag coefficient
+ cd1 = 7.5, &! a free parameter for d/h calculation, Raupach 1992, 1994
+ psih = 0.193 ! psih = ln(cw) - 1 + cw^-1, cw = 2, Raupach 1994
+
+ real(r8) :: sqrtdragc! sqrt(drag coefficient)
+ real(r8) :: lm ! mix length within canopy
+ real(r8) :: fai ! canopy frontal area index
+
+ real(r8), dimension(0:nlay) :: &
+ z0m_lays, &! roughness length for momentum for the layer and below
+ z0h_lays, &! roughness length for SH for the layer and below
+ z0q_lays, &! roughness length for LH for the layer and below
+ displa_lays, &! displacement height for the layer and below
+ fcover_lays ! vegetation fractional cover for this layer and above
+
+ real(r8), dimension(ps:pe) :: &
+ lsai ! lai + sai
+
+ real(r8), dimension(nlay) :: &
+ htop_lay, &! canopy crown top for each layer
+ hbot_lay, &! canopy crown bottom for each layer
+ fcover_lay, &! vegetation fractional coverage for each layer
+ lsai_lay, &! (lai+sai) for each layer
+ a_lay, &! exp. extinction factor for u/k decline within canopy
+ a_lay_i63, &! exp. extinction factor for u/k decline within canopy (Inoue 1963)
+ a_lay_k71, &! exp. extinction factor for u/k decline within canopy (Kondo 1971)
+ a_lay_g77, &! exp. extinction factor for u/k decline within canopy (Groudrian 1977)
+ a_lay_m97, &! exp extinction factor for u/k decline within canopy (Massman 1997)
+ utop_lay, &! wind speed at layer top [m/s]
+ ubot_lay, &! wind speed at layer bottom [m/s]
+ ueff_lay, &! effective wind speed within canopy layer [m/s]
+ ueff_lay_, &! effective wind speed within canopy layer [m/s]
+ ueff_lay_norm, &! normalized effective wind speed within canopy layer [m/s]
+ ktop_lay, &! eddy coefficient at layer top
+ kbot_lay, &! eddy coefficient at layer bottom
+ z0m_lay, &! roughness length for the vegetation covered area
+ displa_lay, &! displacement height for the vegetation covered area
+ taf, &! air temperature within canopy space [K]
+ qaf, &! humidity of canopy air [kg/kg]
+ rd, &! aerodynamic resistance between layers [s/m]
+ cah, &! heat conductance for air [m/s]
+ cgh, &! heat conductance for ground [m/s]
+ caw, &! latent heat conductance for air [m/s]
+ cgw, &! latent heat conductance for ground [m/s]
+ wtshi, &! sensible heat resistance for air, grd and leaf [-]
+ wtsqi, &! latent heat resistance for air, grd and leaf [-]
+ wah, &! normalized heat conductance for air [-]
+ wgh, &! normalized heat conductance for ground [-]
+ waq, &! normalized latent heat conductance for air [-]
+ wgq, &! normalized heat conductance for ground [-]
+ wlhl, &! sum of normalized heat conductance for air and leaf
+ wlql ! sum of normalized heat conductance for air and leaf
+
+ real(r8) :: ktop, utop, fmtop, bee, tmpw1, tmpw2, fact, facq
+
+ logical is_vegetated_patch
+ integer i, p, clev
+ integer toplay, botlay, upplay, numlay
+ integer d_opt, rb_opt, rd_opt
+
+ real(r8) :: displa, ttaf, tqaf
+
+ ! variables for longwave transfer calculation
+ ! .................................................................
+ real(r8) :: tdn(0:4,0:4) !downward transfer coefficient matrix for LW
+ real(r8) :: tup(0:4,0:4) !upward transfer coefficient matrix for LW
+ real(r8) :: thermk_lay(nlay) !transmittance of longwave radiation for each layer
+ real(r8) :: fshade_lay(nlay) !shadow of each layer
+ real(r8) :: L(nlay) !longwave radiation emitted by canopy layer
+ real(r8) :: Ltd(nlay) !transmitted downward longwave radiation from canopy layer
+ real(r8) :: Ltu(nlay) !transmitted upward longwave radiation from canopy layer
+ real(r8) :: Lin(0:4) !incoming longwave radiation for each layer
+ real(r8) :: Ld(0:4) !total downward longwave radiation for each layer
+ real(r8) :: Lu(0:4) !total upward longwave radiation for each layer
+ real(r8) :: Lg !emitted longwave radiation from ground
+ real(r8) :: Lv(ps:pe) !absorbed longwave radiation for each pft
+ real(r8) :: dLv(ps:pe) !LW change due to temperature change
+ real(r8) :: dLvpar(nlay) !temporal variable for calculating dLv
+
+!-----------------------------------------------------------------------
+
+! only process with vegetated patches
+
+ lsai(:) = lai(:) + sai(:)
+ is_vegetated_patch = .false.
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ is_vegetated_patch = .true.
+ ELSE
+ tl(i) = forc_t
+ ENDIF
+ ENDDO
+
+ ! When there is no vegetation in this Plant Community Patch, RETURN
+ IF (.not. is_vegetated_patch) THEN
+ RETURN
+ ENDIF
+
+! initialization of errors and iteration parameters
+ it = 1 !counter for leaf temperature iteration
+ del(:) = 0.0 !change in leaf temperature from previous iteration
+ dele(:) = 0.0 !latent head flux from leaf for previous iteration
+
+ dtl(:,:) = 0.
+ fevpl_bef(:) = 0.
+
+ d_opt = 2
+ rd_opt = 3
+ rb_opt = 3
+
+! initial values for z0hg, z0qg
+ z0mg = (1.-fsno)*zlnd + fsno*zsno
+ z0hg = z0mg
+ z0qg = z0mg
+
+! initialization of PFT constants
+ DO i = ps, pe
+ p = pftclass(i)
+
+ canlay (i) = canlay_p (p)
+ sqrtdi (i) = sqrtdi_p (p)
+
+ effcon (i) = effcon_p (p)
+ vmax25 (i) = vmax25_p (p)
+ c3c4 (i) = c3c4_p (p)
+ shti (i) = shti_p (p)
+ hhti (i) = hhti_p (p)
+ slti (i) = slti_p (p)
+ hlti (i) = hlti_p (p)
+ trda (i) = trda_p (p)
+ trdm (i) = trdm_p (p)
+ trop (i) = trop_p (p)
+ g1 (i) = g1_p (p)
+ g0 (i) = g0_p (p)
+ gradm (i) = gradm_p (p)
+ binter (i) = binter_p (p)
+ lambda (i) = lambda_p (p)
+ extkn (i) = extkn_p (p)
+
+ kmax_sun (i) = kmax_sun_p (p)
+ kmax_sha (i) = kmax_sha_p (p)
+ kmax_xyl (i) = kmax_xyl_p (p)
+ kmax_root (i) = kmax_root_p (p)
+ psi50_sun (i) = psi50_sun_p (p)
+ psi50_sha (i) = psi50_sha_p (p)
+ psi50_xyl (i) = psi50_xyl_p (p)
+ psi50_root (i) = psi50_root_p (p)
+ ck (i) = ck_p (p)
+
+ rootfr (:,i) = rootfr_p (:,p)
+ ENDDO
+
+!-----------------------------------------------------------------------
+! scaling-up coefficients from leaf to canopy
+!-----------------------------------------------------------------------
+
+! note: need to separate to sunlit/shaded pars
+!-----------------------------------------------------------------------
+
+! partition visible canopy absorption to sunlit and shaded fractions
+! to get average absorbed par for sunlit and shaded leaves
+ fsha(:) = 1. - fsun(:)
+ laisun(:) = lai(:)*fsun(:)
+ laisha(:) = lai(:)*fsha(:)
+
+ cintsun(1,:) = (1.-exp(-(0.110+extkb)*lai))/(0.110+extkb)
+ cintsun(2,:) = (1.-exp(-(extkb+extkd)*lai))/(extkb+extkd)
+ cintsun(3,:) = (1.-exp(-extkb*lai))/extkb
+
+ cintsha(1,:) = (1.-exp(-0.110*lai))/0.110 - cintsun(1,:)
+ cintsha(2,:) = (1.-exp(-extkd*lai))/extkd - cintsun(2,:)
+ cintsha(3,:) = lai(:) - cintsun(3,:)
+
+!-----------------------------------------------------------------------
+! get fraction of wet and dry canopy surface (fwet & fdry)
+! initial saturated vapor pressure and humidity and their derivation
+!-----------------------------------------------------------------------
+
+ DO i = ps, pe
+
+ clai(i) = 0.0
+
+ ! 0.2mm*LSAI, account for leaf (plus dew) heat capacity
+ IF ( DEF_VEG_SNOW ) THEN
+ clai(i) = 0.2*lsai(i)*cpliq + ldew_rain(i)*cpliq + ldew_snow(i)*cpice
+ ENDIF
+
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ CALL dewfraction (sigf(i),lai(i),sai(i),dewmx,&
+ ldew(i),ldew_rain(i),ldew_snow(i),fwet(i),fdry(i))
+ CALL qsadv(tl(i),psrf,ei(i),deiDT(i),qsatl(i),qsatlDT(i))
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! initial for fluxes profile
+!-----------------------------------------------------------------------
+
+ nmozsgn = 0 !number of times moz changes sign
+ obuold = 0. !monin-obukhov length from previous iteration
+ zii = 1000. !m (pbl height)
+ beta = 1. !- (in computing W_*)
+
+!-----------------------------------------------------------------------
+! calculate layer average properties: height (htop_lay, hbot_lay), lsai_lay, ...
+! !!NOTE: adjustment may needed for htop_lay/hbot_lay
+!-----------------------------------------------------------------------
+ htop_lay(:) = 0
+ hbot_lay(:) = 0
+ lsai_lay(:) = 0
+ fcover_lay(:) = 0
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ clev = canlay(i)
+ htop_lay(clev) = htop_lay(clev) + htop(i) * fcover(i)
+ hbot_lay(clev) = hbot_lay(clev) + hbot(i) * fcover(i)
+ lsai_lay(clev) = lsai_lay(clev) + lsai(i) * fcover(i)
+ fcover_lay(clev) = fcover_lay(clev) + fcover(i)
+ ENDIF
+ ENDDO
+
+ DO i = 1, nlay
+ IF (fcover_lay(i) > 0) THEN
+ htop_lay(i) = htop_lay(i) / fcover_lay(i)
+ hbot_lay(i) = hbot_lay(i) / fcover_lay(i)
+ lsai_lay(i) = lsai_lay(i) / fcover_lay(i)
+ ENDIF
+ ENDDO
+
+ ! calculate fcover_lays
+! 03/16/2020, yuan: determine to set fc=0 or fcover above for
+! gaps between layers, 0 maybe more consistent
+ fcover_lays(0) = sum(fcover_lay(:))
+ fcover_lays(1) = sum(fcover_lay(1:3))
+ fcover_lays(2) = sum(fcover_lay(2:3))
+ fcover_lays(3) = sum(fcover_lay(3:3))
+ fcover_lays(:) = 0.
+
+!-----------------------------------------------------------------------
+! scaling factor bee
+!-----------------------------------------------------------------------
+! 09/26/2017, yuan: NOTE! bee value, the default is 1
+ bee = 1.
+
+!-----------------------------------------------------------------------
+! calculate z0m and displa for PFTs
+!-----------------------------------------------------------------------
+ DO i = ps, pe
+ IF (lsai(i) > 1.e-6) THEN
+ CALL cal_z0_displa(lsai(i), htop(i), 1., z0mpc(i), displa)
+ ELSE
+ z0mpc(i) = z0mg
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! calculate z0m and displa for layers
+!-----------------------------------------------------------------------
+
+ displa_lay (:) = 0.
+ displa_lays(:) = 0.
+ z0m_lay (:) = 0.
+ z0m_lays (:) = 0.
+
+ DO i = 1, nlay
+ IF (fcover_lay(i)>0 .and. lsai_lay(i)>0) THEN
+ CALL cal_z0_displa(lsai_lay(i), htop_lay(i), 1., z0m_lay(i), displa_lay(i))
+ CALL cal_z0_displa(lsai_lay(i), htop_lay(i), fcover_lay(i), z0m_lays(i), displa_lays(i))
+ ENDIF
+ ENDDO
+
+ ! ground
+ z0m_lays (0) = z0mg
+ displa_lays(0) = 0.
+
+ ! 10/05/2017: robust check
+ WHERE (z0m_lays(:) < z0mg) z0m_lays(:) = z0mg
+ WHERE (z0m_lay (:) < z0mg) z0m_lay (:) = z0mg
+
+ ! maximum assumption
+ z0m_lays(1) = maxval(z0m_lays(0:1))
+ z0m_lays(2) = maxval(z0m_lays(0:2))
+ z0m_lays(3) = maxval(z0m_lays(0:3))
+
+ displa_lays(1) = maxval(displa_lays(0:1))
+ displa_lays(2) = maxval(displa_lays(0:2))
+ displa_lays(3) = maxval(displa_lays(0:3))
+
+ ! roughness length and displacement height for sensible
+ ! and latent heat transfer
+ z0h_lays(:) = z0m_lays(:)
+ z0q_lays(:) = z0m_lays(:)
+
+!-----------------------------------------------------------------------
+! calculate layer a_lay
+!-----------------------------------------------------------------------
+ ! initialization
+ a_lay (:) = 0.
+ a_lay_i63(:) = 0.
+ a_lay_k71(:) = 0.
+ a_lay_g77(:) = 0.
+ a_lay_m97(:) = 0.
+
+ DO i = 1, nlay
+ IF (fcover_lay(i)>0 .and. lsai_lay(i)>0) THEN
+
+ ! mixing length and sqrt(drag coefficient)
+ lm = vonkar*(htop_lay(i) - displa_lay(i))
+
+ ! Raupach, 1992
+ fai = 1. - exp(-0.5*lsai_lay(i))
+ sqrtdragc = min( (0.003+0.3*fai)**0.5, 0.3 )
+
+ ! Inoue, 1963
+ a_lay_i63(i) = htop_lay(i) * &
+ (Cd*lsai_lay(i)/(2.*htop_lay(i)*lm**2))**(1./3.)
+
+ ! Kondo, 1971
+ a_lay_k71(i) = htop_lay(i)/(htop_lay(i)-displa_lay(i))/ &
+ (vonkar/sqrtdragc)
+
+ ! Goudriaan, 1977
+ a_lay_g77(i) = (Cd*lsai_lay(i)*htop_lay(i)/lm)**0.5
+
+ ! Massman, 1997
+ a_lay_m97(i) = Cd*lsai_lay(i) / (2.*sqrtdragc**2)
+
+ a_lay(i) = a_lay_k71(i)
+
+ displa_lay(i) = max(htop_lay(i)/2., displa_lay(i))
+
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! calculate layer info
+! how may layers, top layer and bottom layer number
+!-----------------------------------------------------------------------
+
+ toplay = 0
+ botlay = 0
+ numlay = 0
+
+ DO i = nlay, 1, -1
+ IF (fcover_lay(i)>0 .and. lsai_lay(i)>0) THEN
+
+ ! to count the layer number
+ numlay = numlay + 1
+ IF (toplay .eq. 0) THEN
+ ! set the top layer to current layer
+ toplay = i
+ ENDIF
+
+ ! set this layer to be the bottom layer
+ botlay = i
+
+ displa_lay(i) = max(displa_lay(i), hbot_lay(i))
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! calculate transmittance of longwave radiation for each layer
+! diffuse case
+!-----------------------------------------------------------------------
+
+ thermk_lay(:) = 0.
+ fshade_lay(:) = 0.
+
+ DO i = ps, pe
+ IF (fshade(i)>0 .and. canlay(i)>0) THEN
+ clev = canlay(i)
+ thermk_lay(clev) = thermk_lay(clev) + fshade(i) * thermk(i)
+ fshade_lay(clev) = fshade_lay(clev) + fshade(i)
+ ENDIF
+ ENDDO
+
+ DO i = 1, nlay
+ IF (fshade_lay(i) > 0) THEN
+ thermk_lay(i) = thermk_lay(i) / fshade_lay(i)
+ ELSE
+ thermk_lay(i) = 1.
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! calculate the transfer matrix for long-wave radiation transfer
+! direct case
+! NOTE: don't need to calculate at each step
+!-----------------------------------------------------------------------
+
+ tdn(:,:) = 0.
+ tup(:,:) = 0.
+
+ tdn(1,0) = 1.
+ tdn(2,0) = 1 - fshade_lay(1)
+ tdn(3,0) = 1 - fshade_lay(1) - fshade_lay(2) + fshade_lay(1)*fshade_lay(2)
+ tdn(4,0) = 1 - fshade_lay(1) - fshade_lay(2) - fshade_lay(3) &
+ + fshade_lay(1)*fshade_lay(2) &
+ + fshade_lay(1)*fshade_lay(3) &
+ + fshade_lay(2)*fshade_lay(3) &
+ - fshade_lay(1)*fshade_lay(2)*fshade_lay(3)
+
+ tdn(2,1) = fshade_lay(1)
+ tdn(3,1) = (1 - fshade_lay(2))*fshade_lay(1)
+ tdn(4,1) = (1 - fshade_lay(2) - fshade_lay(3) + fshade_lay(2)*fshade_lay(3))*fshade_lay(1)
+
+ tdn(3,2) = fshade_lay(2)
+ tdn(4,2) = (1 - fshade_lay(3))*fshade_lay(2)
+ tdn(4,3) = fshade_lay(3)
+
+ tup(0,1) = fshade_lay(1)
+ tup(0,2) = (1 - fshade_lay(1))*fshade_lay(2)
+ tup(1,2) = fshade_lay(2)
+
+ tup(0,3) = (1 - fshade_lay(1) - fshade_lay(2) + fshade_lay(1)*fshade_lay(2))*fshade_lay(3)
+ tup(1,3) = (1 - fshade_lay(2))*fshade_lay(3)
+ tup(2,3) = fshade_lay(3)
+
+ tup(0,4) = tdn(4,0)
+ tup(1,4) = 1 - fshade_lay(2) - fshade_lay(3) + fshade_lay(2)*fshade_lay(3)
+ tup(2,4) = 1 - fshade_lay(3)
+ tup(3,4) = 1.
+
+!-----------------------------------------------------------------------
+! calculate parameters for delta(Lv) for LW radiation transfer
+!-----------------------------------------------------------------------
+ dLvpar(1) = 1.
+ dLvpar(2) = ( (1-fshade_lay(1)) + thermk_lay(1)*fshade_lay(1) )**2
+ dLvpar(3) = ( tdn(3,0) &
+ + thermk_lay(2)*fshade_lay(2)*(1-fshade_lay(1)+thermk_lay(1)*fshade_lay(1)) &
+ + (1-fshade_lay(2))*thermk_lay(1)*fshade_lay(1) )**2
+
+!-----------------------------------------------------------------------
+! first guess for taf and qaf for each layer
+! a large difference from previous schemes
+!-----------------------------------------------------------------------
+ taf(:) = 0.
+ qaf(:) = 0.
+
+ ! 05/02/2016: set taf/qaf according to layer number
+ IF (numlay .eq. 1) THEN
+ taf(toplay) = 0.5 * (tg + thm)
+ qaf(toplay) = 0.5 * (qm + qg )
+ ENDIF
+
+ IF (numlay .eq. 2) THEN
+ taf(botlay) = (2.*tg + thm)/3.
+ qaf(botlay) = (2.*qg + qm )/3.
+ taf(toplay) = (tg + 2.*thm)/3.
+ qaf(toplay) = (qg + 2.*qm )/3.
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+ taf(1) = (3.*tg + thm)/4.
+ qaf(1) = (3.*qg + qm )/4.
+ taf(2) = (tg + thm )/2.
+ qaf(2) = (qg + qm )/2.
+ taf(3) = (tg + 3.*thm)/4.
+ qaf(3) = (qg + 3.*qm )/4.
+ ENDIF
+
+!-----------------------------------------------------------------------
+! some environment variables
+! how to calculate rsoil and what is its usage?
+!-----------------------------------------------------------------------
+ pco2a = pco2m
+ tprcor = 44.6*273.16*psrf/1.013e5
+ rsoil = 0. !respiration (mol m-2 s-1)
+! rsoil = 1.22e-6*exp(308.56*(1./56.02-1./(tg-227.13)))
+! rsoil = rstfac * 0.23 * 15. * 2.**((tg-273.16-10.)/10.) * 1.e-6
+! rsoil = 5.22 * 1.e-6
+ rsoil = 0.22 * 1.e-6
+
+! initialization and input values for Monin-Obukhov
+ ! have been set before
+ z0mv = z0m_lays(3); z0hv = z0m_lays(3); z0qv = z0m_lays(3)
+ ur = max(0.1, sqrt(us*us+vs*vs)) !limit set to 0.1
+ dth = thm - taf(toplay)
+ dqh = qm - qaf(toplay)
+ dthv = dth*(1.+0.61*qm) + 0.61*th*dqh
+
+ hu_ = hu; ht_ = ht; hq_ = hq;
+
+ IF (trim(HEIGHT_mode) == 'absolute') THEN
+
+ IF (hu <= htop_lay(toplay)+1) THEN
+ hu_ = htop_lay(toplay) + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of u less than htop+1, set it to htop+1.'
+ ENDIF
+
+ IF (ht <= htop_lay(toplay)+1) THEN
+ ht_ = htop_lay(toplay) + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of t less than htop+1, set it to htop+1.'
+ ENDIF
+
+ IF (hq <= htop_lay(toplay)+1) THEN
+ hq_ = htop_lay(toplay) + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of q less than htop+1, set it to htop+1.'
+ ENDIF
+
+ ELSE ! relative height
+ hu_ = htop_lay(toplay) + hu
+ ht_ = htop_lay(toplay) + ht
+ hq_ = htop_lay(toplay) + hq
+ ENDIF
+
+ zldis = hu_ - displa_lays(3)
+
+ IF(zldis <= 0.0) THEN
+ write(6,*) 'the obs height of u less than the zero displacement heght'
+ CALL abort
+ ENDIF
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mv,um,obu)
+
+! ======================================================================
+! BEGIN stability iteration
+! ======================================================================
+
+ DO WHILE (it .le. itmax)
+
+ tlbef = tl
+
+ del2 = del
+ dele2 = dele
+
+ DO i = ps, pe
+ IF (tl(i) > tfrz) THEN
+ htvpl(i) = hvap
+ ELSE
+ htvpl(i) = hsub
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! Aerodynamical resistances
+!-----------------------------------------------------------------------
+! Evaluate stability-dependent variables using moz from prior iteration
+
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobukm_leddy(hu_,ht_,hq_,displa_lays(toplay),z0mv,z0hv,z0qv,obu,um, &
+ displa_lay(toplay),z0m_lay(toplay),hpbl,ustar,fh2m,fq2m, &
+ htop_lay(toplay),fmtop,fm,fh,fq,fht,fqt,phih)
+ ELSE
+ CALL moninobukm(hu_,ht_,hq_,displa_lays(toplay),z0mv,z0hv,z0qv,obu,um, &
+ displa_lay(toplay),z0m_lay(toplay),ustar,fh2m,fq2m, &
+ htop_lay(toplay),fmtop,fm,fh,fq,fht,fqt,phih)
+ ENDIF
+
+! Aerodynamic resistance
+ ! 09/16/2017:
+ ! note that for ram, it is the resistance from Href to z0mv+displa
+ ! however, for rah and raw is only from Href to canopy effective
+ ! exchange height.
+ ! so rah/raw is not comparable with that of 1D case
+ ram = 1./(ustar*ustar/um)
+
+ ! 05/02/2016: calculate resistance from the top layer (effective exchange
+ ! height) to reference height
+ rah = 1./(vonkar/(fh-fht)*ustar)
+ raw = 1./(vonkar/(fq-fqt)*ustar)
+
+! update roughness length for sensible/latent heat
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ z0h_lays(0) = z0hg
+ z0q_lays(0) = z0qg
+
+ z0h_lays(1) = maxval(z0h_lays(0:1))
+ z0h_lays(2) = maxval(z0h_lays(0:2))
+ z0h_lays(3) = maxval(z0h_lays(0:3))
+
+ z0q_lays(:) = z0h_lays(:)
+ z0hv = z0h_lays(3)
+ z0qv = z0q_lays(3)
+
+! ......................................................................
+! new method to calculate rd and ueffect
+! the kernel part of 3d model
+! ......................................................................
+
+ ! initialization
+ rd(:) = 0.
+ upplay = 0
+
+ ! calculate canopy top wind speed (utop) and exchange coefficient (ktop)
+ ! need to update each time as obu changed after each iteration
+ utop = ustar/vonkar * fmtop
+ ktop = vonkar * (htop_lay(toplay)-displa_lays(toplay)) * ustar / phih
+
+ ! start layer loop
+ DO i = toplay, 1, -1
+
+ IF (fcover_lay(i)>0 .and. lsai_lay(i)>0) THEN
+
+ IF (i .eq. toplay) THEN
+ utop_lay(i) = utop
+ ktop_lay(i) = ktop
+ ELSE
+ ! calculate utop of this layer
+ utop_lay(i) = uprofile(ubot_lay(upplay), fcover_lays(upplay), bee, 0., &
+ z0mg, hbot_lay(upplay), htop_lay(i), htop_lay(i))
+
+ ! calculate ktop of this layer
+ ktop_lay(i) = kprofile(kbot_lay(upplay), fcover_lays(upplay), bee, 0., &
+ displa_lays(toplay)/htop_lay(toplay), &
+ hbot_lay(upplay), htop_lay(i), obug, ustarg, htop_lay(i))
+
+ ! areodynamic resistance between this layer top and above layer bottom
+ ! 03/15/2020, yuan: vertical gaps between layers
+ ! fc = fcover_lays(upplay) or just 0?
+ rd(upplay) = rd(upplay) + frd(kbot_lay(upplay), hbot_lay(upplay), htop_lay(i), &
+ hbot_lay(upplay), htop_lay(i), &
+ displa_lays(toplay)/htop_lay(toplay), &
+ z0h_g, obug, ustarg, z0mg, 0., bee, fcover_lays(upplay))
+
+ ENDIF
+
+ ! for robust check
+ hbot_lay(i) = max(hbot_lay(i), displa_lays(i-1)+z0m_lays(i-1))
+
+ ! wind speed at layer bottom
+ ubot_lay(i) = uprofile(utop_lay(i), fcover_lay(i), bee, a_lay(i), &
+ z0mg, htop_lay(i), hbot_lay(i), hbot_lay(i))
+
+ IF (it == 1) THEN
+ ueff_lay_norm(i) = ueffect(1., htop_lay(i), hbot_lay(i), &
+ z0mg, a_lay(i), bee, fcover_lay(i))
+ ENDIF
+ ueff_lay(i) = utop_lay(i)*ueff_lay_norm(i)
+
+ ! normalized eddy coefficient (K) at layer bottom
+ kbot_lay(i) = kprofile(ktop_lay(i), fcover_lay(i), bee, a_lay(i), &
+ displa_lays(toplay)/htop_lay(toplay), &
+ htop_lay(i), hbot_lay(i), obug, ustarg, hbot_lay(i))
+
+ ! areodynamic resistance from effective fluxes exchange height of
+ ! of this layer to the top of this layer
+ IF (upplay > 0) THEN
+ rd(upplay) = rd(upplay) + frd(ktop_lay(i), htop_lay(i), hbot_lay(i), &
+ htop_lay(i), displa_lay(i)+z0m_lay(i), &
+ displa_lays(toplay)/htop_lay(toplay), &
+ z0h_g, obug, ustarg, z0mg, a_lay(i), bee, fcover_lay(i))
+ ENDIF
+
+ rd(i) = rd(i) + frd(ktop_lay(i), htop_lay(i), hbot_lay(i), &
+ displa_lay(i)+z0m_lay(i), max(z0qg,hbot_lay(i)), &
+ displa_lays(toplay)/htop_lay(toplay), z0h_g, obug, ustarg, &
+ z0mg, a_lay(i), bee, fcover_lay(i))
+
+ upplay = i
+
+ ENDIF
+ ENDDO
+
+! ......................................................................
+! areodynamic resistance between ground and the upper layer bottom
+! ......................................................................
+
+ ! uncomment the below when the upper codes change to hbot_lay
+ !rd(botlay) = rd(botlay) + kintegral(kbot_lay(botlay), fcover_lays(botlay), bee, 0., &
+ ! z0mg, displa_lays(toplay)/htop_lay(toplay), &
+ ! hbot_lay(botlay), z0qg, obug, ustarg, hbot_lay(botlay), z0qg )
+
+ rd(botlay) = rd(botlay) + frd(kbot_lay(botlay), hbot_lay(botlay), z0qg, &
+ hbot_lay(botlay), z0qg, displa_lays(toplay)/htop_lay(toplay), &
+ z0h_g, obug, ustarg, z0mg, 0., bee, fcover_lays(botlay))
+
+! ......................................................................
+! Bulk boundary layer resistance of leaves
+! ......................................................................
+ rb(:) = 0.
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ clev = canlay(i)
+ cf = 0.01*sqrtdi(i)*sqrt(ueff_lay(clev))
+ rb(i) = 1./cf
+ ENDIF
+ ENDDO
+
+ ! 10/01/2017, back to 1D case
+ IF (rb_opt == 1) THEN
+ uaf = ustar
+ cf = 0.01*sqrtdi(2)/sqrt(uaf)
+ rb(:) = 1/(cf*uaf)
+ ENDIF
+
+! rd = 1./(csoilc*uaf) ! BATS legacy
+! w = exp(-0.5*(lai+sai)) ! Dickinson's modification :
+! csoilc = ( 1.-w + w*um/uaf)/rah ! "rah" here is the resistance over
+! rd = 1./(csoilc*uaf) ! bare ground fraction
+
+ ! 10/01/2017, back to 1D case
+ IF (rd_opt == 1 ) THEN
+! modified by Xubin Zeng's suggestion at 08-07-2002
+ uaf = ustar
+ w = exp(-(lai(2)+sai(2)))
+ csoilcn = (vonkar/(0.13*(z0mg*uaf/1.5e-5)**0.45))*w + csoilc*(1.-w)
+ rd(:) = 1./(csoilcn*uaf)
+ ENDIF
+
+!-----------------------------------------------------------------------
+! stomatal resistances
+!-----------------------------------------------------------------------
+
+ DO i = ps, pe
+ p = pftclass(i)
+ IF(fcover(i)>0 .and. lai(i)>0.001) THEN
+
+ rbsun = rb(i) / laisun(i)
+ rbsha = rb(i) / laisha(i)
+
+ clev = canlay(i)
+ eah = qaf(clev) * psrf / ( 0.622 + 0.378 * qaf(clev) ) !pa
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ rstfacsun(i) = 1.
+ rstfacsha(i) = 1.
+ ENDIF
+
+! note: calculate resistance for sunlit/shaded leaves
+!-----------------------------------------------------------------------
+ CALL stomata ( vmax25(i) ,effcon(i) ,c3c4(i) ,slti(i) ,hlti(i) ,&
+ shti(i) ,hhti(i) ,trda(i) ,trdm(i) ,trop(i) ,&
+ g1(i) ,g0(i) ,gradm(i) ,binter(i) ,thm ,&
+ psrf ,po2m ,pco2m ,pco2a ,eah ,&
+ ei(i) ,tl(i) ,parsun(i) ,&
+!Ozone stress variables
+ o3coefv_sun(i), o3coefg_sun(i),&
+!End ozone stress variables
+ lambda(i), &
+ rbsun ,raw ,rstfacsun(i),cintsun(:,i),&
+ assimsun(i),respcsun(i),rssun(i) )
+
+ CALL stomata ( vmax25(i) ,effcon(i) ,c3c4(i) ,slti(i) ,hlti(i) ,&
+ shti(i) ,hhti(i) ,trda(i) ,trdm(i) ,trop(i) ,&
+ g1(i) ,g0(i) ,gradm(i) ,binter(i) ,thm ,&
+ psrf ,po2m ,pco2m ,pco2a ,eah ,&
+ ei(i) ,tl(i) ,parsha(i) ,&
+!Ozone stress variables
+ o3coefv_sha(i), o3coefg_sha(i),&
+!End ozone stress variables
+!WUE stomata model parameter
+ lambda(i) ,&
+!WUE stomata model parameter
+ rbsha ,raw ,rstfacsha(i),cintsha(:,i),&
+ assimsha(i),respcsha(i),rssha(i) )
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+
+ gs0sun(i) = min( 1.e6, 1./(rssun(i)*tl(i)/tprcor) )/ laisun(i) * 1.e6 * o3coefg_sun(i)
+ gs0sha(i) = min( 1.e6, 1./(rssha(i)*tl(i)/tprcor) )/ laisha(i) * 1.e6 * o3coefg_sha(i)
+
+ CALL PlantHydraulicStress_twoleaf (nl_soil ,nvegwcs ,z_soi ,&
+ dz_soi ,rootfr(:,i) ,psrf ,qsatl(i) ,qaf(clev) ,&
+ tl(i) ,rbsun ,rss ,raw ,sum(rd(1:clev)),&
+ rstfacsun(i) ,rstfacsha(i) ,cintsun(:,i) ,cintsha(:,i) ,laisun(i) ,&
+ laisha(i) ,rhoair ,fwet(i) ,sai(i) ,kmax_sun(i) ,&
+ kmax_sha(i) ,kmax_xyl(i) ,kmax_root(i) ,psi50_sun(i) ,psi50_sha(i) ,&
+ psi50_xyl(i) ,psi50_root(i),htop(i) ,ck(i) ,smp ,&
+ hk ,hksati ,vegwp(:,i) ,etrsun(i) ,etrsha(i) ,&
+ rootflux(:,i),qg ,qm ,gs0sun(i) ,gs0sha(i) ,&
+ k_soil_root ,k_ax_root ,gssun(i) ,gssha(i) )
+
+ etr(i) = etrsun(i) + etrsha(i)
+ gssun(i) = gssun(i) * laisun(i) * 1.e-6
+ gssha(i) = gssha(i) * laisha(i) * 1.e-6
+
+ CALL update_photosyn(tl(i), po2m, pco2m, pco2a, parsun(i), psrf, rstfacsun(i), &
+ rb(i), gssun(i), effcon(i), vmax25(i), c3c4(i), gradm(i), trop(i), slti(i), hlti(i), &
+ shti(i), hhti(i), trda(i), trdm(i), cintsun(:,i), assimsun(i), respcsun(i))
+
+ CALL update_photosyn(tl(i), po2m, pco2m, pco2a, parsha(i), psrf, rstfacsha(i), &
+ rb(i), gssha(i), effcon(i), vmax25(i), c3c4(i), gradm(i), trop(i), slti(i), hlti(i), &
+ shti(i), hhti(i), trda(i), trdm(i), cintsha(:,i), assimsha(i), respcsha(i))
+
+ ! leaf scale stomata resistance
+ rssun(i) = tprcor / tl(i) / gssun(i)
+ rssha(i) = tprcor / tl(i) / gssha(i)
+
+ ENDIF
+
+ ELSE
+ rssun(i) = 2.e4; assimsun(i) = 0.; respcsun(i) = 0.
+ rssha(i) = 2.e4; assimsha(i) = 0.; respcsha(i) = 0.
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ etr(i) = 0.
+ rootflux(:,i) = 0.
+ ENDIF
+ ENDIF
+ ENDDO
+
+! above stomatal resistances are for the canopy, the stomatal resistances
+! and the "rb" in the following calculations are the average for single leaf. thus,
+ rssun = rssun * laisun
+ rssha = rssha * laisha
+
+!-----------------------------------------------------------------------
+! dimensional and non-dimensional sensible and latent heat conductances
+! for canopy and soil flux calculations.
+!-----------------------------------------------------------------------
+
+ cfh(:) = 0.
+ cfw(:) = 0.
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+
+ clev = canlay(i)
+ delta(i) = 0.0
+ IF(qsatl(i)-qaf(clev) .gt. 0.) delta(i) = 1.0
+
+ cfh(i) = lsai(i) / rb(i)
+
+! note: combine sunlit and shaded leaves
+!-----------------------------------------------------------------------
+ cfw(i) = (1.-delta(i)*(1.-fwet(i)))*lsai(i)/rb(i) + &
+ (1.-fwet(i))*delta(i)* &
+ ( laisun(i)/(rb(i)+rssun(i)) + laisha(i)/(rb(i)+rssha(i)) )
+ ENDIF
+ ENDDO
+
+ ! initialization
+ cah(:) = 0.
+ caw(:) = 0.
+ cgh(:) = 0.
+ cgw(:) = 0.
+
+ DO i = 1, nlay
+ IF (fcover_lay(i)>0 .and. lsai_lay(i)>0) THEN
+ IF (i == toplay) THEN
+ cah(i) = 1. / rah
+ caw(i) = 1. / raw
+ ELSE
+ cah(i) = 1. / rd(i+1)
+ caw(i) = 1. / rd(i+1)
+ ENDIF
+
+ cgh(i) = 1. / rd(i)
+ IF (i == botlay) THEN
+ IF (qg < qaf(botlay)) THEN
+ cgw(i) = 1. / rd(i) !dew case. no soil resistance
+ ELSE
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ cgw(i) = rss/ rd(i)
+ ELSE
+ cgw(i) = 1. / (rd(i) + rss)
+ ENDIF
+ ENDIF
+ ELSE
+ cgw(i) = 1. / rd(i)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! calculate wtshi, wtsqi
+ wtshi(:) = cah(:) + cgh(:)
+ wtsqi(:) = caw(:) + cgw(:)
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ clev = canlay(i)
+ wtshi(clev) = wtshi(clev) + fcover(i)*cfh(i)
+ wtsqi(clev) = wtsqi(clev) + fcover(i)*cfw(i)
+ ENDIF
+ ENDDO
+
+ DO i = 1, nlay
+ IF (fcover_lay(i)>0 .and. lsai_lay(i)>0) THEN
+ wtshi(i) = 1./wtshi(i)
+ wtsqi(i) = 1./wtsqi(i)
+ ENDIF
+ ENDDO
+
+ wah(:) = cah(:) * wtshi(:)
+ wgh(:) = cgh(:) * wtshi(:)
+
+ waq(:) = caw(:) * wtsqi(:)
+ wgq(:) = cgw(:) * wtsqi(:)
+
+ ! calculate wlh, wlhl, wlq, wlql
+ wlhl(:) = 0.
+ wlql(:) = 0.
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ clev = canlay(i)
+
+ wlh(i) = cfh(i) * wtshi(clev) * fcover(i)
+ wlhl(clev) = wlhl(clev) + wlh(i)*tl(i)
+
+ wlq(i) = cfw(i) * wtsqi(clev) * fcover(i)
+ wlql(clev) = wlql(clev) + wlq(i)*qsatl(i)
+ ENDIF
+ ENDDO
+
+ ! to solve taf(:) and qaf(:)
+ IF (numlay .eq. 1) THEN
+
+ taf(toplay) = wah(toplay)*thm + wgh(toplay)*tg + wlhl(toplay)
+ qaf(toplay) = waq(toplay)*qm + wgq(toplay)*qg + wlql(toplay)
+ fact = 1.
+ facq = 1.
+
+ ENDIF
+
+ IF (numlay .eq. 2) THEN
+
+ tmpw1 = wgh(botlay)*tg + wlhl(botlay)
+ fact = 1. - wgh(toplay)*wah(botlay)
+ taf(toplay) = ( wah(toplay)*thm + wgh(toplay)*tmpw1 + wlhl(toplay) ) / fact
+
+ tmpw1 = wgq(botlay)*qg + wlql(botlay)
+ facq = 1. - wgq(toplay)*waq(botlay)
+ qaf(toplay) = ( waq(toplay)*qm + wgq(toplay)*tmpw1 + wlql(toplay) ) / facq
+
+ taf(botlay) = wah(botlay)*taf(toplay) + wgh(botlay)*tg + wlhl(botlay)
+ qaf(botlay) = waq(botlay)*qaf(toplay) + wgq(botlay)*qg + wlql(botlay)
+
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+
+ tmpw1 = wah(3)*thm + wlhl(3)
+ tmpw2 = wgh(1)*tg + wlhl(1)
+ fact = 1. - wah(2)*wgh(3) - wgh(2)*wah(1)
+ taf(2) = ( wah(2)*tmpw1 + wgh(2)*tmpw2 + wlhl(2) ) / fact
+
+ tmpw1 = waq(3)*qm + wlql(3)
+ tmpw2 = wgq(1)*qg + wlql(1)
+ facq = 1. - waq(2)*wgq(3) - wgq(2)*waq(1)
+ qaf(2) = ( waq(2)*tmpw1 + wgq(2)*tmpw2 + wlql(2) ) / facq
+
+ taf(1) = wah(1)*taf(2) + wgh(1)*tg + wlhl(1)
+ qaf(1) = waq(1)*qaf(2) + wgq(1)*qg + wlql(1)
+
+ taf(3) = wah(3)*thm + wgh(3)*taf(2) + wlhl(3)
+ qaf(3) = waq(3)*qm + wgq(3)*qaf(2) + wlql(3)
+
+ ENDIF
+
+!-----------------------------------------------------------------------
+! IR radiation, sensible and latent heat fluxes and their derivatives
+!-----------------------------------------------------------------------
+! the partial derivatives of areodynamical resistance are ignored
+! which cannot be determined analytically
+
+! calculate L for each canopy layer
+ L(:) = 0.
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ clev = canlay(i)
+ ! according to absorption = emissivity, fcover -> fshade
+ L(clev) = L(clev) + fshade(i) * (1-thermk(i)) * stefnc * tl(i)**4
+ ENDIF
+ ENDDO
+
+! calculate Ltd
+ Ltd(:) = 0.
+ Ltd(3) = thermk_lay(3) * tdn(4,3) * frl
+ Ltd(2) = thermk_lay(2) * ( tdn(4,2)*frl + tdn(3,2)*(Ltd(3) + L(3)) )
+ Ltd(1) = thermk_lay(1) * ( tdn(4,1)*frl + tdn(3,1)*(Ltd(3) + L(3)) + &
+ tdn(2,1)*(Ltd(2) + L(2)) )
+
+! calculate Ld = Ltd + L
+ Ld(0) = 0.
+ Ld(4) = frl
+ Ld(1:3) = Ltd + L
+
+! calculate Lin = Ld * tdn
+ Lin(:) = matmul(Ld(:), tdn(:,:))
+
+! calculate Lg = (1-emg)*dlrad + emg*stefnc*tg**4
+! dlrad = Lin(0)
+IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ Lg = (1 - emg)*Lin(0) + emg*stefnc*tg**4
+ELSE
+ Lg = (1 - emg)*Lin(0) &
+ + (1.-fsno)*emg*stefnc*t_soil**4 &
+ + fsno*emg*stefnc*t_snow**4
+ENDIF
+
+! calculate Ltu
+ Ltu(1) = thermk_lay(1) * tup(0,1) * Lg
+ Ltu(2) = thermk_lay(2) * ( tup(0,2)*Lg + tup(1,2)*(Ltu(1) + L(1)) )
+ Ltu(3) = thermk_lay(3) * ( tup(0,3)*Lg + tup(1,3)*(Ltu(1) + L(1)) + &
+ tup(2,3)*(Ltu(2) + L(2)) )
+
+! calculate Lu = Ltu + L
+ Lu(0) = Lg
+ Lu(4) = 0.
+ Lu(1:3) = Ltu + L
+
+! calculate Lin = Lin + Lu*tup
+ Lin(:) = Lin(:) + matmul(Lu(:), tup(:,:))
+
+! calculate Lv
+ Lv(:) = 0.
+ DO i = ps, pe
+ IF (fshade(i)>0 .and. canlay(i)>0) THEN
+ clev = canlay(i)
+ Lv(i) = fshade(i)/fshade_lay(clev) * (1-thermk(i)) * Lin(clev) / fcover(i) &
+ - 2. * fshade(i) * (1-thermk(i)) * stefnc * tl(i)**4 / fcover(i)
+ ENDIF
+ ENDDO
+
+! calculate delta(Lv)
+ dLv(:) = 0.
+ DO i = ps, pe
+ IF (fshade(i)>0 .and. canlay(i)>0) THEN
+ clev = canlay(i)
+ dLv(i) = (4.*dLvpar(clev)*(1-emg)*fshade(i)*(1-thermk(i)) - 8.) &
+ * fshade(i) * (1-thermk(i)) * stefnc * tl(i)**3 / fcover(i)
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+
+ irab(:) = Lv(:)
+ dirab_dtl(:) = dLv(:)
+
+ DO i = ps, pe
+
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+
+ clev = canlay(i)
+ fac(i) = 1. - thermk(i)
+
+! sensible heat fluxes and their derivatives
+ fsenl(i) = rhoair * cpair * cfh(i) * (tl(i) - taf(clev))
+
+ ! 09/25/2017: re-written, check it carefully
+ ! When numlay<3, no matter how to calculate, /fact is consistent
+ IF (numlay < 3 .or. clev == 2) THEN
+ fsenl_dtl(i) = rhoair * cpair * cfh(i) * (1. - wlh(i)/fact)
+ ELSE
+ IF (clev == 1) THEN
+ fsenl_dtl(i) = rhoair * cpair * cfh(i) &
+ !* (1. - (1.-wah(2)*wgh(3))*wlh(i)/fact) or
+ * (1. - wah(1)*wgh(2)*wlh(i)/fact - wlh(i))
+ ENDIF
+ IF (clev == 3) THEN
+ fsenl_dtl(i) = rhoair * cpair * cfh(i) &
+ !* (1. - (1.-wgh(2)*wah(1))*wlh(i)/fact) or
+ * (1. - wgh(3)*wah(2)*wlh(i)/fact - wlh(i))
+ ENDIF
+ ENDIF
+
+! latent heat fluxes and their derivatives
+
+ etr(i) = rhoair * (1.-fwet(i)) * delta(i) &
+ * ( laisun(i)/(rb(i)+rssun(i)) + laisha(i)/(rb(i)+rssha(i)) ) &
+ * ( qsatl(i) - qaf(clev) )
+
+ ! 09/25/2017: re-written
+ IF (numlay < 3 .or. clev == 2) THEN
+ etr_dtl(i) = rhoair * (1.-fwet(i)) * delta(i) &
+ * ( laisun(i)/(rb(i)+rssun(i)) + laisha(i)/(rb(i)+rssha(i)) ) &
+ * (1. - wlq(i)/facq)*qsatlDT(i)
+ ELSE
+ IF (clev == 1) THEN
+ etr_dtl(i) = rhoair * (1.-fwet(i)) * delta(i) &
+ * ( laisun(i)/(rb(i)+rssun(i)) + laisha(i)/(rb(i)+rssha(i)) ) &
+ !* (1. - (1.-waq(2)*wgq(3))*wlq(i)/facq)*qsatlDT(i) or
+ * (1. - waq(1)*wgq(2)*wlq(i)/facq - wlq(i))*qsatlDT(i)
+ ENDIF
+ IF (clev == 3) THEN
+ etr_dtl(i) = rhoair * (1.-fwet(i)) * delta(i) &
+ * ( laisun(i)/(rb(i)+rssun(i)) + laisha(i)/(rb(i)+rssha(i)) ) &
+ !* (1. - (1.-wgq(2)*waq(1))*wlq(i)/facq)*qsatlDT(i) or
+ * (1. - wgq(3)*waq(2)*wlq(i)/facq - wlq(i))*qsatlDT(i)
+ ENDIF
+ ENDIF
+
+ IF (.not. DEF_USE_PLANTHYDRAULICS) THEN
+ IF(etr(i).ge.etrc(i))THEN
+ etr(i) = etrc(i)
+ etr_dtl(i) = 0.
+ ENDIF
+ ENDIF
+
+ evplwet(i) = rhoair * (1.-delta(i)*(1.-fwet(i))) * lsai(i)/rb(i) &
+ * ( qsatl(i) - qaf(clev) )
+
+ ! 09/25/2017: re-written
+ IF (numlay < 3 .or. clev == 2) THEN
+ evplwet_dtl(i) = rhoair * (1.-delta(i)*(1.-fwet(i))) * lsai(i)/rb(i) &
+ * (1. - wlq(i)/facq)*qsatlDT(i)
+ ELSE
+ IF (clev == 1) THEN
+ evplwet_dtl(i) = rhoair * (1.-delta(i)*(1.-fwet(i))) * lsai(i)/rb(i) &
+ !* (1. - (1-waq(2)*wgq(3))*wlq(i)/facq)*qsatlDT(i) or
+ * (1. - waq(1)*wgq(2)*wlq(i)/facq - wlq(i))*qsatlDT(i)
+ ENDIF
+ IF (clev == 3) THEN
+ evplwet_dtl(i) = rhoair * (1.-delta(i)*(1.-fwet(i))) * lsai(i)/rb(i) &
+ !* (1. - (1.-wgq(2)*waq(1))*wlq(i)/facq)*qsatlDT(i) or
+ * (1. - wgq(3)*waq(2)*wlq(i)/facq - wlq(i))*qsatlDT(i)
+ ENDIF
+ ENDIF
+
+ ! 03/02/2018: convert evplwet from fc to whole area
+ ! because ldew right now is for the whole area
+ ! 09/05/2019: back to fc area
+ IF(evplwet(i).ge.ldew(i)/deltim)THEN
+ evplwet(i) = ldew(i)/deltim
+ evplwet_dtl(i) = 0.
+ ENDIF
+
+ fevpl(i) = etr(i) + evplwet(i)
+ fevpl_dtl(i) = etr_dtl(i) + evplwet_dtl(i)
+
+ erre(i) = 0.
+ fevpl_noadj(i) = fevpl(i)
+ IF ( fevpl(i)*fevpl_bef(i) < 0. ) THEN
+ erre(i) = -0.9*fevpl(i)
+ fevpl(i) = 0.1*fevpl(i)
+ ENDIF
+
+!-----------------------------------------------------------------------
+! difference of temperatures by quasi-newton-raphson method for the non-linear system equations
+! MARK#dtl
+!-----------------------------------------------------------------------
+
+ dtl(it,i) = (sabv(i) + irab(i) - fsenl(i) - hvap*fevpl(i) &
+ + cpliq*qintr_rain(i)*(t_precip-tl(i)) &
+ + cpice*qintr_snow(i)*(t_precip-tl(i))) &
+ / (clai(i)/deltim - dirab_dtl(i) + fsenl_dtl(i) + hvap*fevpl_dtl(i) &
+ + cpliq*qintr_rain(i) + cpice*qintr_snow(i))
+
+ dtl_noadj(i) = dtl(it,i)
+
+ ! check magnitude of change in leaf temperature limit to maximum allowed value
+
+ IF (it .le. itmax) THEN
+
+ ! put brakes on large temperature excursions
+ IF(abs(dtl(it,i)).gt.delmax)THEN
+ dtl(it,i) = delmax*dtl(it,i)/abs(dtl(it,i))
+ ENDIF
+
+ ! NOTE: could be a bug if dtl*dtl==0, changed from lt->le
+ IF((it.ge.2) .and. (dtl(it-1,i)*dtl(it,i).le.0.))THEN
+ dtl(it,i) = 0.5*(dtl(it-1,i) + dtl(it,i))
+ ENDIF
+
+ ENDIF
+
+ tl(i) = tlbef(i) + dtl(it,i)
+
+!-----------------------------------------------------------------------
+! square roots differences of temperatures and fluxes for USE as the condition of convergences
+!-----------------------------------------------------------------------
+
+ del(i) = sqrt( dtl(it,i)*dtl(it,i) )
+ dele(i) = dtl(it,i) * dtl(it,i) * &
+ ( dirab_dtl(i)**2 + fsenl_dtl(i)**2 + (hvap*fevpl_dtl(i))**2 )
+ dele(i) = sqrt(dele(i))
+
+!-----------------------------------------------------------------------
+! saturated vapor pressures and canopy air temperature, canopy air humidity
+!-----------------------------------------------------------------------
+! Recalculate leaf saturated vapor pressure (ei_)for updated leaf temperature
+! and adjust specific humidity (qsatl_) proportionately
+ CALL qsadv(tl(i),psrf,ei(i),deiDT(i),qsatl(i),qsatlDT(i))
+
+ ENDIF
+ ENDDO !END pft loop
+
+! update vegetation/ground surface temperature, canopy air temperature,
+! canopy air humidity
+
+ ! calculate wlhl, wlql
+ wlhl(:) = 0.
+ wlql(:) = 0.
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+ clev = canlay(i)
+ wlhl(clev) = wlhl(clev) + wlh(i)*tl(i)
+ wlql(clev) = wlql(clev) + wlq(i)*qsatl(i)
+ ENDIF
+ ENDDO
+
+ IF (numlay .eq. 1) THEN
+
+ taf(toplay) = wah(toplay)*thm + wgh(toplay)*tg + wlhl(toplay)
+ qaf(toplay) = waq(toplay)*qm + wgq(toplay)*qg + wlql(toplay)
+ fact = 1.
+ facq = 1.
+
+ ENDIF
+
+ IF (numlay .eq. 2) THEN
+
+ tmpw1 = wgh(botlay)*tg + wlhl(botlay)
+ fact = 1. - wgh(toplay)*wah(botlay)
+ taf(toplay) = (wah(toplay)*thm + wgh(toplay)*tmpw1 + wlhl(toplay)) / fact
+
+ tmpw1 = wgq(botlay)*qg + wlql(botlay)
+ facq = 1. - wgq(toplay)*waq(botlay)
+ qaf(toplay) = (waq(toplay)*qm + wgq(toplay)*tmpw1 + wlql(toplay)) / facq
+
+ taf(botlay) = wah(botlay)*taf(toplay) + wgh(botlay)*tg + wlhl(botlay)
+ qaf(botlay) = waq(botlay)*qaf(toplay) + wgq(botlay)*qg + wlql(botlay)
+
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+
+ tmpw1 = wah(3)*thm + wlhl(3)
+ tmpw2 = wgh(1)*tg + wlhl(1)
+ fact = 1. - wah(2)*wgh(3) - wgh(2)*wah(1)
+ taf(2) = (wah(2)*tmpw1 + wgh(2)*tmpw2 + wlhl(2)) / fact
+
+ tmpw1 = waq(3)*qm + wlql(3)
+ tmpw2 = wgq(1)*qg + wlql(1)
+ facq = 1. - waq(2)*wgq(3) - wgq(2)*waq(1)
+ qaf(2) = (waq(2)*tmpw1 + wgq(2)*tmpw2 + wlql(2)) / facq
+
+ taf(1) = wah(1)*taf(2) + wgh(1)*tg + wlhl(1)
+ qaf(1) = waq(1)*qaf(2) + wgq(1)*qg + wlql(1)
+
+ taf(3) = wah(3)*thm + wgh(3)*taf(2) + wlhl(3)
+ qaf(3) = waq(3)*qm + wgq(3)*qaf(2) + wlql(3)
+
+ ENDIF
+
+! update co2 partial pressure within canopy air
+ ! 05/02/2016: may have some problem with gdh2o, however,
+ ! this variable seems never used here. Different height
+ ! level vegetation should have different gdh2o, i.e.,
+ ! different rd(layer) values.
+ gah2o = 1.0/raw * tprcor/thm !mol m-2 s-1
+
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ gdh2o = rss/rd(botlay) * tprcor/thm !mol m-2 s-1
+ ELSE
+ gdh2o = 1.0/(rd(botlay)+rss) * tprcor/thm !mol m-2 s-1
+ ENDIF
+ pco2a = pco2m - 1.37*psrf/max(0.446,gah2o) * &
+ sum(fcover*(assimsun + assimsha - respcsun - respcsha - rsoil))
+
+!-----------------------------------------------------------------------
+! Update monin-obukhov length and wind speed including the stability effect
+!-----------------------------------------------------------------------
+
+ dth = thm - taf(toplay)
+ dqh = qm - qaf(toplay)
+
+ tstar = vonkar/(fh-fht)*dth
+ qstar = vonkar/(fq-fqt)*dqh
+
+ thvstar = tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta = zldis*vonkar*grav*thvstar / (ustar**2*thv)
+ IF(zeta .ge. 0.)THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF(zeta .ge. 0.)THEN
+ um = max(ur,.1)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ zii = max(5.*hu_,hpbl)
+ ENDIF !//TODO: Shaofeng, 2023.05.18
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF(obuold*obu .lt. 0.) nmozsgn = nmozsgn+1
+ IF(nmozsgn .ge. 4) obu = zldis/(-0.01)
+ obuold = obu
+
+!-----------------------------------------------------------------------
+! Test for convergence
+!-----------------------------------------------------------------------
+
+ it = it+1
+
+ IF(it .gt. itmin) THEN
+ fevpl_bef = fevpl
+ det = maxval(max(del,del2))
+ ! 10/03/2017, yuan: possible bugs here, solution:
+ ! define dee, change del => dee
+ dee = maxval(max(dele,dele2))
+ IF(det .lt. dtmin .and. dee .lt. dlemin) EXIT
+ ENDIF
+
+ ENDDO
+
+! ======================================================================
+! END stability iteration
+! ======================================================================
+
+ IF(DEF_USE_OZONESTRESS)THEN
+ DO i = ps, pe
+ p = pftclass(i)
+ CALL CalcOzoneStress(o3coefv_sun(i),o3coefg_sun(i),forc_ozone,psrf,th,ram,&
+ rssun(i),rb(i),lai(i),lai_old(i),p,o3uptakesun(i),sabv(i),deltim)
+ CALL CalcOzoneStress(o3coefv_sha(i),o3coefg_sha(i),forc_ozone,psrf,th,ram,&
+ rssha(i),rb(i),lai(i),lai_old(i),p,o3uptakesha(i),sabv(i),deltim)
+ lai_old(i) = lai(i)
+ assimsun(i) = assimsun(i) * o3coefv_sun(i)
+ assimsha(i) = assimsha(i) * o3coefv_sha(i)
+! rssun (i) = rssun (i) / o3coefg_sun(i)
+! rssha (i) = rssha (i) / o3coefg_sha(i)
+ ENDDO
+ ELSE
+ DO i = ps, pe
+ o3coefv_sun(i) = 1.0_r8
+ o3coefg_sun(i) = 1.0_r8
+ o3coefv_sha(i) = 1.0_r8
+ o3coefg_sha(i) = 1.0_r8
+ ENDDO
+ ENDIF
+
+ z0m = z0mv
+ zol = zeta
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+! canopy fluxes and total assimilation and respiration
+
+ DO i = ps, pe
+ IF (fcover(i)>0 .and. lsai(i)>1.e-6) THEN
+
+ IF(lai(i) .gt. 0.001) THEN
+ rst(i) = 1./(laisun(i)/rssun(i) + laisha(i)/rssha(i))
+ ELSE
+ rssun(i) = 2.0e4 ; rssha(i) = 2.0e4
+ assimsun(i) = 0. ; assimsha(i) = 0.
+ respcsun(i) = 0. ; respcsha(i) = 0.
+ rst(i) = 2.0e4
+ ENDIF
+ assim(i) = assimsun(i) + assimsha(i)
+ respc(i) = respcsun(i) + respcsha(i) + rsoil
+
+! canopy fluxes and total assimilation and respiration
+ fsenl(i) = fsenl(i) + fsenl_dtl(i)*dtl(it-1,i) &
+ ! add the imbalanced energy below due to T adjustment to sensible heat
+ + (dtl_noadj(i)-dtl(it-1,i)) * (clai(i)/deltim - dirab_dtl(i) &
+ + fsenl_dtl(i) + hvap*fevpl_dtl(i) &
+ + cpliq*qintr_rain(i) + cpice*qintr_snow(i)) &
+ ! add the imbalanced energy below due to q adjustment to sensible heat
+ + hvap*erre(i)
+
+ etr0(i) = etr(i)
+ etr (i) = etr(i) + etr_dtl(i)*dtl(it-1,i)
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ !TODO@yuan: rootflux may not be consistent with etr,
+ ! water imbalance could happen.
+ IF(abs(etr0(i)) .ge. 1.e-15)THEN
+ rootflux(:,i) = rootflux(:,i) * etr(i) / etr0(i)
+ ELSE
+ rootflux(:,i) = rootflux(:,i) + dz_soi / sum(dz_soi) * etr_dtl(i)* dtl(it-1,i)
+ ENDIF
+
+ !NOTE: temporal solution to make etr and rootflux consistent.
+ !TODO: need double check
+ sumrootflux = sum(rootflux(:,i), rootflux(:,i)>0.)
+ IF (abs(sumrootflux) > 0.) THEN
+ rootflux(:,i) = max(rootflux(:,i),0.) * (etr(i)/sumrootflux)
+ ELSE
+ rootflux(:,i) = etr(i)*rootfr(:,i)
+ ENDIF
+ ENDIF
+
+ evplwet(i) = evplwet(i) + evplwet_dtl(i)*dtl(it-1,i)
+ fevpl (i) = fevpl_noadj(i)
+ fevpl (i) = fevpl(i) + fevpl_dtl(i)*dtl(it-1,i)
+
+ elwmax = ldew(i)/deltim
+
+ ! 03/02/2018, yuan: convert fc to whole area
+ ! because ldew now is for the whole area
+ ! may need to change to canopy covered area
+ ! 09/14/2019, yuan: change back to canopy area
+ elwdif = max(0., evplwet(i)-elwmax)
+ evplwet(i) = min(evplwet(i), elwmax)
+
+ fevpl(i) = fevpl(i) - elwdif
+ fsenl(i) = fsenl(i) + hvap*elwdif
+
+ ! precipitation sensible heat from canopy
+ hprl (i) = cpliq*qintr_rain(i)*(t_precip-tl(i)) + cpice*qintr_snow(i)*(t_precip-tl(i))
+
+ ! vegetation heat change
+ dheatl(i) = clai(i)/deltim*dtl(it-1,i)
+
+!-----------------------------------------------------------------------
+! Update dew accumulation (kg/m2)
+!-----------------------------------------------------------------------
+ IF (DEF_Interception_scheme .eq. 1) THEN !colm2014
+
+ ldew(i) = max(0., ldew(i)-evplwet(i)*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl(i) > tfrz) THEN
+ qevpl(i) = max (evplwet(i), 0.)
+ qdewl(i) = abs (min (evplwet(i), 0.) )
+ qsubl(i) = 0.
+ qfrol(i) = 0.
+
+ IF (qevpl(i) > ldew_rain(i)/deltim) THEN
+ qsubl(i) = qevpl(i) - ldew_rain(i)/deltim
+ qevpl(i) = ldew_rain(i)/deltim
+ ENDIF
+ ELSE
+ qevpl(i) = 0.
+ qdewl(i) = 0.
+ qsubl(i) = max (evplwet(i), 0.)
+ qfrol(i) = abs (min (evplwet(i), 0.) )
+
+ IF (qsubl(i) > ldew_snow(i)/deltim) THEN
+ qevpl(i) = qsubl(i) - ldew_snow(i)/deltim
+ qsubl(i) = ldew_snow(i)/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain(i) = ldew_rain(i) + (qdewl(i)-qevpl(i))*deltim
+ ldew_snow(i) = ldew_snow(i) + (qfrol(i)-qsubl(i))*deltim
+
+ ldew(i) = ldew_rain(i) + ldew_snow(i)
+ ENDIF
+
+ ELSEIF (DEF_Interception_scheme .eq. 2) THEN!CLM4.5
+ ldew(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ELSEIF (DEF_Interception_scheme .eq. 3) THEN !CLM5
+ IF (ldew_rain(i) .gt. evplwet(i)*deltim) THEN
+ ldew_rain(i) = ldew_rain(i)-evplwet(i)*deltim
+ ldew_snow(i) = ldew_snow(i)
+ ldew(i)=ldew_rain(i)+ldew_snow(i)
+ ELSE
+ ldew_rain(i) = 0.0
+ ldew_snow(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ldew (i) = ldew_snow(i)
+ ENDIF
+ ELSEIF (DEF_Interception_scheme .eq. 4) THEN !Noah-MP
+ IF (ldew_rain(i) .gt. evplwet(i)*deltim) THEN
+ ldew_rain(i) = ldew_rain(i)-evplwet(i)*deltim
+ ldew_snow(i) = ldew_snow(i)
+ ldew(i)=ldew_rain(i)+ldew_snow(i)
+ ELSE
+ ldew_rain(i) = 0.0
+ ldew_snow(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ldew (i) = ldew_snow(i)
+ ENDIF
+ ELSEIF (DEF_Interception_scheme .eq. 5) THEN !MATSIRO
+ IF (ldew_rain(i) .gt. evplwet(i)*deltim) THEN
+ ldew_rain(i) = ldew_rain(i)-evplwet(i)*deltim
+ ldew_snow(i) = ldew_snow(i)
+ ldew(i)=ldew_rain(i)+ldew_snow(i)
+ ELSE
+ ldew_rain(i) = 0.0
+ ldew_snow(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ldew (i) = ldew_snow(i)
+ ENDIF
+ ELSEIF (DEF_Interception_scheme .eq. 6) THEN !VIC
+ IF (ldew_rain(i) .gt. evplwet(i)*deltim) THEN
+ ldew_rain(i) = ldew_rain(i)-evplwet(i)*deltim
+ ldew_snow(i) = ldew_snow(i)
+ ldew(i)=ldew_rain(i)+ldew_snow(i)
+ ELSE
+ ldew_rain(i) = 0.0
+ ldew_snow(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ldew (i) = ldew_snow(i)
+ ENDIF
+ ELSEIF (DEF_Interception_scheme .eq. 7) THEN !JULES
+ IF (ldew_rain(i) .gt. evplwet(i)*deltim) THEN
+ ldew_rain(i) = ldew_rain(i)-evplwet(i)*deltim
+ ldew_snow(i) = ldew_snow(i)
+ ldew(i)=ldew_rain(i)+ldew_snow(i)
+ ELSE
+ ldew_rain(i) = 0.0
+ ldew_snow(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ldew (i) = ldew_snow(i)
+ ENDIF
+ ELSEIF (DEF_Interception_scheme .eq. 8) THEN !CoLM202x
+ IF (ldew_rain(i) .gt. evplwet(i)*deltim) THEN
+ ldew_rain(i) = ldew_rain(i)-evplwet(i)*deltim
+ ldew_snow(i) = ldew_snow(i)
+ ldew(i)=ldew_rain(i)+ldew_snow(i)
+ ELSE
+ ldew_rain(i) = 0.0
+ ldew_snow(i) = max(0., ldew(i)-evplwet(i)*deltim)
+ ldew (i) = ldew_snow(i)
+ ENDIF
+ ELSE
+ CALL abort
+ ENDIF
+
+ IF ( DEF_VEG_SNOW ) THEN
+ ! update fwet_snow
+ fwet_snow(i) = 0
+ IF(ldew_snow(i) > 0.) THEN
+ fwet_snow(i) = ((10./(48.*lsai(i)))*ldew_snow(i))**.666666666666
+ ! Check for maximum limit of fwet_snow
+ fwet_snow(i) = min(fwet_snow(i),1.0)
+ ENDIF
+
+ ! phase change
+
+ qmelt(i) = 0.
+ qfrz(i) = 0.
+
+ IF (ldew_snow(i).gt.1.e-6 .and. tl(i).gt.tfrz) THEN
+ qmelt(i) = min(ldew_snow(i)/deltim,(tl(i)-tfrz)*cpice*ldew_snow(i)/(deltim*hfus))
+ ldew_snow(i) = max(0.,ldew_snow(i) - qmelt(i)*deltim)
+ ldew_rain(i) = max(0.,ldew_rain(i) + qmelt(i)*deltim)
+ !NOTE: There may be some problem, energy imbalance
+ ! However, detailed treatment could be somewhat trivial
+ tl(i) = fwet_snow(i)*tfrz + (1.-fwet_snow(i))*tl(i) !Niu et al., 2004
+ ENDIF
+
+ IF (ldew_rain(i).gt.1.e-6 .and. tl(i).lt.tfrz) THEN
+ qfrz(i) = min(ldew_rain(i)/deltim,(tfrz-tl(i))*cpliq*ldew_rain(i)/(deltim*hfus))
+ ldew_rain(i) = max(0.,ldew_rain(i) - qfrz(i)*deltim)
+ ldew_snow(i) = max(0.,ldew_snow(i) + qfrz(i)*deltim)
+ !NOTE: There may be some problem, energy imbalance
+ ! However, detailed treatment could be somewhat trivial
+ tl(i) = fwet_snow(i)*tfrz + (1.-fwet_snow(i))*tl(i) !Niu et al., 2004
+ ENDIF
+ ENDIF
+
+!-----------------------------------------------------------------------
+! balance check
+! (the computational error was created by the assumed 'dtl' in MARK#dtl)
+!-----------------------------------------------------------------------
+
+ err = sabv(i) + irab(i) + dirab_dtl(i)*dtl(it-1,i) &
+ - fsenl(i) - hvap*fevpl(i) + hprl(i) &
+ ! account for vegetation heat change
+ - dheatl(i)
+
+#if (defined CoLMDEBUG)
+ IF(abs(err) .gt. .2) &
+ write(6,*) 'energy imbalance in LeafTemperaturePC.F90', &
+ i,it-1,err,sabv(i),irab(i),fsenl(i),hvap*fevpl(i),hprl(i),dheatl(i)
+#endif
+ ENDIF
+ ENDDO
+
+!-----------------------------------------------------------------------
+! downward (upward) longwave radiation below (above) the canopy
+!-----------------------------------------------------------------------
+ dlrad = Lin(0) &
+ + sum( 4.* fshade * (1-thermk) * stefnc * tlbef**3 * dtl(it-1,:) )
+
+ ulrad = Lin(4) - sum( fcover * dLv * dtl(it-1,:) ) &
+ - emg * sum( 4.* fshade * (1-thermk) * stefnc * tlbef**3 * dtl(it-1,:) )
+
+!-----------------------------------------------------------------------
+! wind stresses
+!-----------------------------------------------------------------------
+
+ taux = - rhoair*us/ram
+ tauy = - rhoair*vs/ram
+
+!-----------------------------------------------------------------------
+! fluxes from ground to canopy space
+!-----------------------------------------------------------------------
+
+! 03/07/2020, yuan: TODO-done, calculate fseng_soil/snow, fevpg_soil/snow
+ IF (numlay .eq. 1) THEN
+ ttaf = thm
+ tqaf = qm
+ ENDIF
+
+ IF (numlay .eq. 2) THEN
+ ttaf = taf(toplay)
+ tqaf = qaf(toplay)
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+ ttaf = taf(2)
+ tqaf = qaf(2)
+ ENDIF
+
+ !NOTE: the below EQs for check purpose only
+ ! taf = wah*thm + wgh*tg + wlh*tl
+ ! taf(1) = wah(1)*taf(2) + wgh(1)*tg + wlhl(1)
+ ! qaf(1) = waq(1)*qaf(2) + wgq(1)*qg + wlql(1)
+ ! taf(botlay) = wah(botlay)*taf(toplay) + wgh(botlay)*tg + wlhl(botlay)
+ ! qaf(botlay) = waq(botlay)*qaf(toplay) + wgq(botlay)*qg + wlql(botlay)
+ ! taf(toplay) = wah(toplay)*thm + wgh(toplay)*tg + wlhl(toplay)
+ ! qaf(toplay) = waq(toplay)*qm + wgq(toplay)*qg + wlql(toplay)
+
+ fseng = cpair*rhoair*cgh(botlay)*(tg-taf(botlay))
+ fseng_soil = cpair*rhoair*cgh(botlay)*((1.-wgh(botlay))*t_soil-wah(botlay)*ttaf-wlhl(botlay))
+ fseng_snow = cpair*rhoair*cgh(botlay)*((1.-wgh(botlay))*t_snow-wah(botlay)*ttaf-wlhl(botlay))
+
+ fevpg = rhoair*cgw(botlay)*(qg-qaf(botlay))
+ fevpg_soil = rhoair*cgw(botlay)*((1.-wgq(botlay))*q_soil-waq(botlay)*tqaf-wlql(botlay))
+ fevpg_snow = rhoair*cgw(botlay)*((1.-wgq(botlay))*q_snow-waq(botlay)*tqaf-wlql(botlay))
+
+!-----------------------------------------------------------------------
+! Derivative of soil energy flux with respect to soil temperature (cgrnd)
+!-----------------------------------------------------------------------
+
+ !NOTE: When numlay<3, no matter how to get the solution, /fact is consistent
+ IF (numlay < 3) THEN
+ cgrnds = cpair*rhoair*cgh(botlay)*(1.-wgh(botlay)/fact)
+ cgrndl = rhoair*cgw(botlay)*(1.-wgq(botlay)/facq)*dqgdT
+ ELSE
+ cgrnds = cpair*rhoair*cgh(botlay)*(1.-wah(1)*wgh(2)*wgh(1)/fact-wgh(1))
+ cgrndl = rhoair*cgw(botlay)*(1.-waq(1)*wgq(2)*wgq(1)/facq-wgq(1))*dqgdT
+ ENDIF
+
+ cgrnd = cgrnds + cgrndl*htvp
+
+!-----------------------------------------------------------------------
+! 2 m height air temperature
+!-----------------------------------------------------------------------
+
+ tref = thm + vonkar/(fh-fht)*dth * (fh2m/vonkar - fh/vonkar)
+ qref = qm + vonkar/(fq-fqt)*dqh * (fq2m/vonkar - fq/vonkar)
+
+ END SUBROUTINE LeafTemperaturePC
+!----------------------------------------------------------------------
+
+
+ SUBROUTINE dewfraction (sigf,lai,sai,dewmx,ldew,ldew_rain,ldew_snow,fwet,fdry)
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! determine fraction of foliage covered by water and
+! fraction of foliage that is dry and transpiring
+!
+! !REVISIONS:
+! 2024.04.16, Hua Yuan: add option to account for vegetation snow process
+! 2018.06 , Hua Yuan: remove sigf, to compatible with PFT
+!=======================================================================
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: dewmx !maximum allowed dew [0.1 mm]
+ real(r8), intent(in) :: ldew !depth of water on foliage [kg/m2/s]
+ real(r8), intent(in) :: ldew_rain !depth of rain on foliage [kg/m2/s]
+ real(r8), intent(in) :: ldew_snow !depth of snow on foliage [kg/m2/s]
+ real(r8), intent(out) :: fwet !fraction of foliage covered by water&snow [-]
+ real(r8), intent(out) :: fdry !fraction of foliage that is green and dry [-]
+
+ real(r8) :: lsai !lai + sai
+ real(r8) :: dewmxi !inverse of maximum allowed dew [1/mm]
+ real(r8) :: vegt !sigf*lsai, NOTE: remove sigf
+ real(r8) :: fwet_rain !fraction of foliage covered by water [-]
+ real(r8) :: fwet_snow !fraction of foliage covered by snow [-]
+
+!-----------------------------------------------------------------------
+! Fwet is the fraction of all vegetation surfaces which are wet
+! including stem area which contribute to evaporation
+ lsai = lai + sai
+ dewmxi = 1.0/dewmx
+ ! 06/2018, yuan: remove sigf, to compatible with PFT
+ vegt = lsai
+
+ fwet = 0
+ IF (ldew > 0.) THEN
+ fwet = ((dewmxi/vegt)*ldew)**.666666666666
+ ! Check for maximum limit of fwet
+ fwet = min(fwet,1.0)
+ ENDIF
+
+ ! account for vegetation snow
+ ! calculate fwet_rain, fwet_snow, fwet
+ IF ( DEF_VEG_SNOW ) THEN
+
+ fwet_rain = 0
+ IF(ldew_rain > 0.) THEN
+ fwet_rain = ((dewmxi/vegt)*ldew_rain)**.666666666666
+ ! Check for maximum limit of fwet_rain
+ fwet_rain = min(fwet_rain,1.0)
+ ENDIF
+
+ fwet_snow = 0
+ IF(ldew_snow > 0.) THEN
+ fwet_snow = ((dewmxi/(48.*vegt))*ldew_snow)**.666666666666
+ ! Check for maximum limit of fwet_snow
+ fwet_snow = min(fwet_snow,1.0)
+ ENDIF
+
+ fwet = fwet_rain + fwet_snow - fwet_rain*fwet_snow
+ fwet = min(fwet,1.0)
+ ENDIF
+
+ ! fdry is the fraction of lai which is dry because only leaves can
+ ! transpire. Adjusted for stem area which does not transpire
+ fdry = (1.-fwet)*lai/lsai
+
+ END SUBROUTINE dewfraction
+
+END MODULE MOD_LeafTemperaturePC
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_LightningData.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LightningData.F90
new file mode 100644
index 0000000000..365fd4e68c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_LightningData.F90
@@ -0,0 +1,116 @@
+#include
+
+#ifdef BGC
+MODULE MOD_LightningData
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This module read in lightning data for fire subroutine
+!
+! !ORIGINAL:
+! Zhang Shupeng, 2022, prepare the original version of the lightning data module.
+!-----------------------------------------------------------------------
+
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SpatialMapping
+ USE MOD_BGC_Vars_TimeVariables, only: lnfm
+ IMPLICIT NONE
+
+ character(len=256) :: file_lightning
+ type(grid_type) :: grid_lightning
+
+ type(block_data_real8_2d) :: f_lnfm
+
+ type (spatial_mapping_type) :: mg2p_lnfm
+
+CONTAINS
+
+ SUBROUTINE init_lightning_data (idate)
+
+!-----------------------------------------------------------------------
+! !DESCTIPTION:
+! open lightning netcdf file from DEF_dir_rawdata, read latitude and longitude info.
+! Initialize lightning data read in.
+!-----------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_TimeManager
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+
+ ! Local Variables
+ real(r8), allocatable :: lat(:), lon(:)
+ integer :: itime
+
+ file_lightning = trim(DEF_dir_runtime) // &
+ '/fire/clmforc.Li_2012_climo1995-2011.T62.lnfm_Total_c140423.nc'
+
+ CALL ncio_read_bcast_serial (file_lightning, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_lightning, 'lon', lon)
+
+ CALL grid_lightning%define_by_center (lat, lon)
+
+ CALL allocate_block_data (grid_lightning, f_lnfm)
+
+ CALL mg2p_lnfm%build_arealweighted (grid_lightning, landpatch)
+
+ itime = (idate(2)-1)*8 + min(idate(3)/10800+1,8)
+ IF (itime .gt. 2920)itime = itime - 8 ! for the leap year
+
+ CALL ncio_read_block_time (file_lightning, 'lnfm', grid_lightning, itime, f_lnfm)
+#ifdef RangeCheck
+ CALL check_block_data ('lightning', f_lnfm)
+#endif
+
+ END SUBROUTINE init_lightning_data
+
+
+ SUBROUTINE update_lightning_data (time, deltim)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! read lightning data during simulation
+!-----------------------------------------------------------------------
+
+ USE MOD_TimeManager
+ USE MOD_NetCDFBlock
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ type(timestamp), intent(in) :: time
+ real(r8), intent(in) :: deltim
+
+ ! Local Variables
+ type(timestamp) :: time_next
+ integer :: itime, itime_next
+
+ itime = (time%day-1)*8 + min(time%sec/10800+1,8)
+ IF (mod(time%sec,10800) == 0) itime = itime - 1
+
+ time_next = time + int(deltim)
+ itime_next = (time_next%day-1)*8 + max(0,time_next%sec-1)/10800+1
+
+ IF (itime_next /= itime) THEN
+ itime_next = min(itime_next,2920)
+ CALL ncio_read_block_time (file_lightning, 'lnfm', grid_lightning, itime_next, f_lnfm)
+#ifdef RangeCheck
+ CALL check_block_data ('lightning', f_lnfm)
+#endif
+
+ CALL mg2p_lnfm%grid2pset (f_lnfm, lnfm)
+#ifdef RangeCheck
+ CALL check_vector_data ('lightning', lnfm)
+#endif
+ ENDIF
+
+ END SUBROUTINE update_lightning_data
+
+END MODULE MOD_LightningData
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_MonthlyinSituCO2MaunaLoa.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_MonthlyinSituCO2MaunaLoa.F90
new file mode 100644
index 0000000000..22899d863e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_MonthlyinSituCO2MaunaLoa.F90
@@ -0,0 +1,746 @@
+#include
+
+!"-------------------------------------------------------------------------------------------"
+!" Atmospheric CO2 concentrations (ppm) derived from in situ air measurements "
+!" at Mauna Loa, Observatory, Hawaii: Latitude 19.5°N Longitude 155.6°W Elevation 3397m "
+!" "
+!" Source: R. F. Keeling, S. J. Walker, S. C. Piper and A. F. Bollenbacher "
+!" Scripps CO2 Program ( http://scrippsco2.ucsd.edu ) "
+!" Scripps Institution of Oceanography (SIO) "
+!" University of California "
+!" La Jolla, California USA 92093-0244 "
+!" "
+!" Status of data and correspondence: "
+!" "
+!" These data are subject to revision based on recalibration of standard gases. Questions "
+!" about the data should be directed to Dr. Ralph Keeling (rkeeling@ucsd.edu), Stephen Walker"
+!" (sjwalker@ucsd.edu) and Stephen Piper (scpiper@ucsd.edu), Scripps CO2 Program. "
+!" "
+!" Baseline data in this file through 03-May-2022 from archive dated 04-May-2022 09:22:14 "
+!" "
+!"-------------------------------------------------------------------------------------------"
+!" "
+!" Please cite as: "
+!" "
+!" C. D. Keeling, S. C. Piper, R. B. Bacastow, M. Wahlen, T. P. Whorf, M. Heimann, and "
+!" H. A. Meijer, Exchanges of atmospheric CO2 and 13CO2 with the terrestrial biosphere and "
+!" oceans from 1978 to 2000. I. Global aspects, SIO Reference Series, No. 01-06, Scripps "
+!" Institution of Oceanography, San Diego, 88 pages, 2001. "
+!" "
+!" If it is necessary to cite a peer-reviewed article, please cite as: "
+!" "
+!" C. D. Keeling, S. C. Piper, R. B. Bacastow, M. Wahlen, T. P. Whorf, M. Heimann, and "
+!" H. A. Meijer, Atmospheric CO2 and 13CO2 exchange with the terrestrial biosphere and "
+!" oceans from 1978 to 2000: observations and carbon cycle implications, pages 83-113, "
+!" in "A History of Atmospheric CO2 and its effects on Plants, Animals, and Ecosystems", "
+!" editors, Ehleringer, J.R., T. E. Cerling, M. D. Dearing, Springer Verlag, "
+!" New York, 2005. "
+!" "
+!"-------------------------------------------------------------------------------------------"
+
+MODULE MOD_MonthlyinSituCO2MaunaLoa
+! -------------------------------
+!
+! !DESCRIPTION:
+! Monthly atmospheric CO2 concentrations (ppm) for model input derived from
+! in situ air measurements at Mauna Loa, Observatory, Hawaii
+!
+! Created by Hua Yuan, 05/2022
+!
+! !REVISIONS:
+! !---2023.02.23 Zhongwang Wei @ SYSU: Added CO2 data (TODO:details?@zhongwang)
+! in init_monthly_co2_mlo()
+! !---2022.12.12 Zhongwang Wei @ SYSU: Added history and SSP CO2 data in init_monthly_co2_mlo()
+! -------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_SSP
+ IMPLICIT NONE
+ SAVE
+
+ ! define the CO2 data time range
+ integer, parameter :: syear = 1849
+ integer, parameter :: eyear = 2100
+ integer, parameter :: smonth = 1
+ integer, parameter :: emonth = 12
+
+ real(r8), dimension(syear:eyear, 12) :: co2mlo
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: init_monthly_co2_mlo
+ PUBLIC :: get_monthly_co2_mlo
+
+CONTAINS
+
+ SUBROUTINE init_monthly_co2_mlo
+ !DESCRIPTION
+ !===========
+ !---This MODULE is used for initialize the CO2 concentration.
+
+ !ANCILLARY FUNCTIONS AND SUBROUTINES
+ !-------------------
+
+ !Original Author:
+ !-------------------
+ !Hua Yuan @ SYSU 2021.05.05
+
+ !References:
+ !-------------------
+ !---1850-1957 obtained from
+ ! https://data.isimip.org/datasets/0497b2a7-fd37-4fe0-8d05-ea3057272731/ Matthias Büchner,
+ ! Christopher Reyer (2022): ISIMIP3b atmospheric composition input data (v1.1). ISIMIP
+ ! Repository. https://doi.org/10.48364/ISIMIP.482153.1
+ !---1958-2022 obtained from https://www.esrl.noaa.gov/gmd/ccgg/trends/data.html
+ !---!May 2022 ~ Dec 2022 data obtained from
+ ! https://gml.noaa.gov/webdata/ccgg/trends/co2/co2_mm_mlo.txt (Mauna Loa, Hawaii)
+ !---Due to the eruption of the Mauna Loa Volcano, measurements from Mauna Loa Observatory were
+ ! suspended as of Nov. 29. 2022 New Observations starting in December 2022 are from a site
+ ! at the Maunakea Observatories, approximately 21 miles north of the Mauna Loa Observatory.
+ !---CMIP6 co2 data is obtainted from :
+ ! Matthias Büchner, Christopher Reyer (2022): ISIMIP3b atmospheric composition input data
+ ! (v1.1). ISIMIP Repository. https://doi.org/10.48364/ISIMIP.482153.1
+
+ !REVISION HISTORY
+ !----------------
+ !---2023.02.23 Zhongwang Wei @ SYSU
+ !---2022.12.12 Zhongwang Wei @ SYSU
+ !---2021.05.05 Hua Yuan @ SYSU
+
+ IMPLICIT NONE
+
+ ! fillvalue
+ co2mlo(:,:) = -99.99 !monthly mean CO2 concentration in ppm
+ !1850-1957 obtained from
+ !https://data.isimip.org/datasets/0497b2a7-fd37-4fe0-8d05-ea3057272731/ Matthias Büchner,
+ !Christopher Reyer (2022): ISIMIP3b atmospheric composition input data (v1.1). ISIMIP
+ !Repository. https://doi.org/10.48364/ISIMIP.482153.1
+ !added by Zhongwang Wei @ SYSU 2022.12.12
+ co2mlo( 1849 ,:) = (/ 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 /)
+ co2mlo( 1850 ,:) = (/ 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 , 284.73 /)
+ co2mlo( 1851 ,:) = (/ 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 , 284.88 /)
+ co2mlo( 1852 ,:) = (/ 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 , 285.00 /)
+ co2mlo( 1853 ,:) = (/ 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 , 285.13 /)
+ co2mlo( 1854 ,:) = (/ 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 , 285.28 /)
+ co2mlo( 1855 ,:) = (/ 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 , 285.43 /)
+ co2mlo( 1856 ,:) = (/ 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 , 285.58 /)
+ co2mlo( 1857 ,:) = (/ 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 , 285.73 /)
+ co2mlo( 1858 ,:) = (/ 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 , 285.90 /)
+ co2mlo( 1859 ,:) = (/ 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 , 286.08 /)
+ co2mlo( 1860 ,:) = (/ 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 , 286.23 /)
+ co2mlo( 1861 ,:) = (/ 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 , 286.38 /)
+ co2mlo( 1862 ,:) = (/ 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 , 286.50 /)
+ co2mlo( 1863 ,:) = (/ 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 , 286.63 /)
+ co2mlo( 1864 ,:) = (/ 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 , 286.78 /)
+ co2mlo( 1865 ,:) = (/ 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 , 286.90 /)
+ co2mlo( 1866 ,:) = (/ 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 , 287.00 /)
+ co2mlo( 1867 ,:) = (/ 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 , 287.10 /)
+ co2mlo( 1868 ,:) = (/ 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 , 287.23 /)
+ co2mlo( 1869 ,:) = (/ 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 , 287.38 /)
+ co2mlo( 1870 ,:) = (/ 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 , 287.53 /)
+ co2mlo( 1871 ,:) = (/ 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 , 287.70 /)
+ co2mlo( 1872 ,:) = (/ 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 , 287.90 /)
+ co2mlo( 1873 ,:) = (/ 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 , 288.13 /)
+ co2mlo( 1874 ,:) = (/ 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 , 288.40 /)
+ co2mlo( 1875 ,:) = (/ 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 , 288.70 /)
+ co2mlo( 1876 ,:) = (/ 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 , 289.03 /)
+ co2mlo( 1877 ,:) = (/ 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 , 289.40 /)
+ co2mlo( 1878 ,:) = (/ 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 , 289.80 /)
+ co2mlo( 1879 ,:) = (/ 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 , 290.23 /)
+ co2mlo( 1880 ,:) = (/ 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 , 290.70 /)
+ co2mlo( 1881 ,:) = (/ 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 , 291.20 /)
+ co2mlo( 1882 ,:) = (/ 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 , 291.68 /)
+ co2mlo( 1883 ,:) = (/ 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 , 292.13 /)
+ co2mlo( 1884 ,:) = (/ 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 , 292.58 /)
+ co2mlo( 1885 ,:) = (/ 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 , 292.98 /)
+ co2mlo( 1886 ,:) = (/ 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 , 293.30 /)
+ co2mlo( 1887 ,:) = (/ 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 , 293.58 /)
+ co2mlo( 1888 ,:) = (/ 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 , 293.80 /)
+ co2mlo( 1889 ,:) = (/ 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 , 294.00 /)
+ co2mlo( 1890 ,:) = (/ 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 , 294.18 /)
+ co2mlo( 1891 ,:) = (/ 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 , 294.33 /)
+ co2mlo( 1892 ,:) = (/ 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 , 294.48 /)
+ co2mlo( 1893 ,:) = (/ 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 , 294.60 /)
+ co2mlo( 1894 ,:) = (/ 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 , 294.70 /)
+ co2mlo( 1895 ,:) = (/ 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 , 294.80 /)
+ co2mlo( 1896 ,:) = (/ 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 , 294.90 /)
+ co2mlo( 1897 ,:) = (/ 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 , 295.03 /)
+ co2mlo( 1898 ,:) = (/ 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 , 295.23 /)
+ co2mlo( 1899 ,:) = (/ 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 , 295.50 /)
+ co2mlo( 1900 ,:) = (/ 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 , 295.80 /)
+ co2mlo( 1901 ,:) = (/ 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 , 296.13 /)
+ co2mlo( 1902 ,:) = (/ 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 , 296.48 /)
+ co2mlo( 1903 ,:) = (/ 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 , 296.83 /)
+ co2mlo( 1904 ,:) = (/ 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 , 297.20 /)
+ co2mlo( 1905 ,:) = (/ 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 , 297.63 /)
+ co2mlo( 1906 ,:) = (/ 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 , 298.08 /)
+ co2mlo( 1907 ,:) = (/ 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 , 298.50 /)
+ co2mlo( 1908 ,:) = (/ 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 , 298.90 /)
+ co2mlo( 1909 ,:) = (/ 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 , 299.30 /)
+ co2mlo( 1910 ,:) = (/ 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 , 299.70 /)
+ co2mlo( 1911 ,:) = (/ 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 , 300.08 /)
+ co2mlo( 1912 ,:) = (/ 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 , 300.43 /)
+ co2mlo( 1913 ,:) = (/ 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 , 300.78 /)
+ co2mlo( 1914 ,:) = (/ 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 , 301.10 /)
+ co2mlo( 1915 ,:) = (/ 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 , 301.40 /)
+ co2mlo( 1916 ,:) = (/ 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 , 301.73 /)
+ co2mlo( 1917 ,:) = (/ 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 , 302.08 /)
+ co2mlo( 1918 ,:) = (/ 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 , 302.40 /)
+ co2mlo( 1919 ,:) = (/ 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 , 302.70 /)
+ co2mlo( 1920 ,:) = (/ 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 , 303.03 /)
+ co2mlo( 1921 ,:) = (/ 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 , 303.40 /)
+ co2mlo( 1922 ,:) = (/ 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 , 303.78 /)
+ co2mlo( 1923 ,:) = (/ 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 , 304.13 /)
+ co2mlo( 1924 ,:) = (/ 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 , 304.53 /)
+ co2mlo( 1925 ,:) = (/ 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 , 304.98 /)
+ co2mlo( 1926 ,:) = (/ 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 , 305.40 /)
+ co2mlo( 1927 ,:) = (/ 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 , 305.83 /)
+ co2mlo( 1928 ,:) = (/ 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 , 306.30 /)
+ co2mlo( 1929 ,:) = (/ 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 , 306.78 /)
+ co2mlo( 1930 ,:) = (/ 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 , 307.23 /)
+ co2mlo( 1931 ,:) = (/ 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 , 307.70 /)
+ co2mlo( 1932 ,:) = (/ 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 , 308.18 /)
+ co2mlo( 1933 ,:) = (/ 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 , 308.60 /)
+ co2mlo( 1934 ,:) = (/ 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 , 309.00 /)
+ co2mlo( 1935 ,:) = (/ 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 , 309.40 /)
+ co2mlo( 1936 ,:) = (/ 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 , 309.75 /)
+ co2mlo( 1937 ,:) = (/ 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 , 310.00 /)
+ co2mlo( 1938 ,:) = (/ 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 , 310.18 /)
+ co2mlo( 1939 ,:) = (/ 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 /)
+ co2mlo( 1940 ,:) = (/ 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 /)
+ co2mlo( 1941 ,:) = (/ 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 , 310.38 /)
+ co2mlo( 1942 ,:) = (/ 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 , 310.30 /)
+ co2mlo( 1943 ,:) = (/ 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 /)
+ co2mlo( 1944 ,:) = (/ 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 /)
+ co2mlo( 1945 ,:) = (/ 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 , 310.10 /)
+ co2mlo( 1946 ,:) = (/ 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 , 310.13 /)
+ co2mlo( 1947 ,:) = (/ 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 , 310.20 /)
+ co2mlo( 1948 ,:) = (/ 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 , 310.33 /)
+ co2mlo( 1949 ,:) = (/ 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 , 310.50 /)
+ co2mlo( 1950 ,:) = (/ 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 , 310.75 /)
+ co2mlo( 1951 ,:) = (/ 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 , 311.10 /)
+ co2mlo( 1952 ,:) = (/ 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 , 311.50 /)
+ co2mlo( 1953 ,:) = (/ 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 , 311.93 /)
+ co2mlo( 1954 ,:) = (/ 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 , 312.43 /)
+ co2mlo( 1955 ,:) = (/ 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 , 313.00 /)
+ co2mlo( 1956 ,:) = (/ 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 , 313.60 /)
+ co2mlo( 1957 ,:) = (/ 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 , 314.23 /)
+ !co2mlo( 1958 ,:) = (/ 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 , 314.85 /)
+ !co2mlo( 1959 ,:) = (/ 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 , 315.50 /)
+ !co2mlo( 1960 ,:) = (/ 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 , 316.27 /)
+ !co2mlo( 1961 ,:) = (/ 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 , 317.08 /)
+ !co2mlo( 1962 ,:) = (/ 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 , 317.80 /)
+ !co2mlo( 1963 ,:) = (/ 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 , 318.40 /)
+ !co2mlo( 1964 ,:) = (/ 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 , 318.93 /)
+ !co2mlo( 1965 ,:) = (/ 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 , 319.65 /)
+ !co2mlo( 1966 ,:) = (/ 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 , 320.65 /)
+ !co2mlo( 1967 ,:) = (/ 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 , 321.61 /)
+ !co2mlo( 1968 ,:) = (/ 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 , 322.64 /)
+ !co2mlo( 1969 ,:) = (/ 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 , 323.90 /)
+ !co2mlo( 1970 ,:) = (/ 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 , 324.99 /)
+ !co2mlo( 1971 ,:) = (/ 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 , 325.86 /)
+ !co2mlo( 1972 ,:) = (/ 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 , 327.14 /)
+ !co2mlo( 1973 ,:) = (/ 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 , 328.68 /)
+ !co2mlo( 1974 ,:) = (/ 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 , 329.74 /)
+ !co2mlo( 1975 ,:) = (/ 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 , 330.59 /)
+ !co2mlo( 1976 ,:) = (/ 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 , 331.75 /)
+ !co2mlo( 1977 ,:) = (/ 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 , 333.27 /)
+ !co2mlo( 1978 ,:) = (/ 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 , 334.85 /)
+ !co2mlo( 1979 ,:) = (/ 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 , 336.53 /)
+ !co2mlo( 1980 ,:) = (/ 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 , 338.36 /)
+ !co2mlo( 1981 ,:) = (/ 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 , 339.73 /)
+ !co2mlo( 1982 ,:) = (/ 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 , 340.79 /)
+ !co2mlo( 1983 ,:) = (/ 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 , 342.20 /)
+ !co2mlo( 1984 ,:) = (/ 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 , 343.78 /)
+ !co2mlo( 1985 ,:) = (/ 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 , 345.28 /)
+ !co2mlo( 1986 ,:) = (/ 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 , 346.80 /)
+ !co2mlo( 1987 ,:) = (/ 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 , 348.65 /)
+ !co2mlo( 1988 ,:) = (/ 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 , 350.74 /)
+ !co2mlo( 1989 ,:) = (/ 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 , 352.49 /)
+ !co2mlo( 1990 ,:) = (/ 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 , 353.86 /)
+ !co2mlo( 1991 ,:) = (/ 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 , 355.02 /)
+ !co2mlo( 1992 ,:) = (/ 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 , 355.89 /)
+ !co2mlo( 1993 ,:) = (/ 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 , 356.78 /)
+ !co2mlo( 1994 ,:) = (/ 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 , 358.13 /)
+ !co2mlo( 1995 ,:) = (/ 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 , 359.84 /)
+ !co2mlo( 1996 ,:) = (/ 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 , 361.46 /)
+ !co2mlo( 1997 ,:) = (/ 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 , 363.16 /)
+ !co2mlo( 1998 ,:) = (/ 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 , 365.32 /)
+ !co2mlo( 1999 ,:) = (/ 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 , 367.35 /)
+ !co2mlo( 2000 ,:) = (/ 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 , 368.87 /)
+ !co2mlo( 2001 ,:) = (/ 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 , 370.47 /)
+ !co2mlo( 2002 ,:) = (/ 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 , 372.52 /)
+ !co2mlo( 2003 ,:) = (/ 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 , 374.76 /)
+ !co2mlo( 2004 ,:) = (/ 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 , 376.81 /)
+ !co2mlo( 2005 ,:) = (/ 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 , 378.81 /)
+ !co2mlo( 2006 ,:) = (/ 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 , 380.93 /)
+ !co2mlo( 2007 ,:) = (/ 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 , 382.70 /)
+ !co2mlo( 2008 ,:) = (/ 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 , 384.77 /)
+ !co2mlo( 2009 ,:) = (/ 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 , 386.28 /)
+ !co2mlo( 2010 ,:) = (/ 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 , 388.57 /)
+ !co2mlo( 2011 ,:) = (/ 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 , 390.49 /)
+ !co2mlo( 2012 ,:) = (/ 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 , 392.52 /)
+ !co2mlo( 2013 ,:) = (/ 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 , 395.31 /)
+ !co2mlo( 2014 ,:) = (/ 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 , 397.12 /)
+
+ !NOTE: the below numbers can be manually updated IF new records are available [Unit: ppm]
+ co2mlo(1958,:) = (/ 314.85, 314.85, 315.71, 317.45, 317.51, 317.25, 315.86, 314.93, 313.21, 312.43, 313.33, 314.67 /)
+ co2mlo(1959,:) = (/ 315.58, 316.49, 316.65, 317.72, 318.29, 318.15, 316.54, 314.80, 313.84, 313.33, 314.81, 315.58 /)
+ co2mlo(1960,:) = (/ 316.43, 316.98, 317.58, 319.03, 320.03, 319.58, 318.18, 315.90, 314.17, 313.83, 315.00, 316.19 /)
+ co2mlo(1961,:) = (/ 316.89, 317.70, 318.54, 319.48, 320.58, 319.77, 318.56, 316.79, 314.99, 315.31, 316.10, 317.01 /)
+ co2mlo(1962,:) = (/ 317.94, 318.55, 319.68, 320.57, 321.02, 320.62, 319.61, 317.40, 316.24, 315.42, 316.69, 317.70 /)
+ co2mlo(1963,:) = (/ 318.74, 319.07, 319.86, 321.38, 322.25, 321.48, 319.74, 317.77, 316.21, 315.99, 317.07, 318.35 /)
+ co2mlo(1964,:) = (/ 319.57, 320.03, 320.74, 321.83, 322.25, 321.89, 320.44, 318.69, 316.71, 316.87, 317.68, 318.71 /)
+ co2mlo(1965,:) = (/ 319.44, 320.44, 320.89, 322.14, 322.17, 321.87, 321.21, 318.87, 317.82, 317.30, 318.87, 319.42 /)
+ co2mlo(1966,:) = (/ 320.62, 321.60, 322.39, 323.70, 324.08, 323.75, 322.38, 320.36, 318.64, 318.10, 319.78, 321.02 /)
+ co2mlo(1967,:) = (/ 322.33, 322.50, 323.03, 324.41, 325.00, 324.09, 322.54, 320.92, 319.25, 319.39, 320.73, 321.95 /)
+ co2mlo(1968,:) = (/ 322.57, 323.15, 323.89, 325.02, 325.57, 325.36, 324.14, 322.11, 320.33, 320.25, 321.32, 322.89 /)
+ co2mlo(1969,:) = (/ 324.00, 324.41, 325.63, 326.66, 327.38, 326.71, 325.88, 323.66, 322.38, 321.78, 322.85, 324.11 /)
+ co2mlo(1970,:) = (/ 325.06, 325.99, 326.93, 328.13, 328.08, 327.67, 326.34, 324.68, 323.10, 323.07, 324.01, 325.13 /)
+ co2mlo(1971,:) = (/ 326.17, 326.68, 327.18, 327.79, 328.93, 328.57, 327.36, 325.43, 323.36, 323.56, 324.80, 326.01 /)
+ co2mlo(1972,:) = (/ 326.77, 327.63, 327.75, 329.72, 330.07, 329.09, 328.04, 326.32, 324.84, 325.20, 326.50, 327.55 /)
+ co2mlo(1973,:) = (/ 328.55, 329.56, 330.30, 331.50, 332.48, 332.07, 330.87, 329.31, 327.52, 327.19, 328.17, 328.65 /)
+ co2mlo(1974,:) = (/ 329.36, 330.71, 331.49, 332.65, 333.10, 332.26, 331.18, 329.40, 327.44, 327.38, 328.46, 329.58 /)
+ co2mlo(1975,:) = (/ 330.41, 331.41, 332.04, 333.32, 333.98, 333.61, 331.91, 330.06, 328.56, 328.35, 329.50, 330.77 /)
+ co2mlo(1976,:) = (/ 331.76, 332.58, 333.50, 334.59, 334.89, 334.34, 333.06, 330.95, 329.31, 328.95, 330.32, 331.69 /)
+ co2mlo(1977,:) = (/ 332.94, 333.43, 334.71, 336.08, 336.76, 336.28, 334.93, 332.76, 331.60, 331.17, 332.41, 333.86 /)
+ co2mlo(1978,:) = (/ 334.98, 335.40, 336.65, 337.76, 338.02, 337.91, 336.55, 334.69, 332.77, 332.56, 333.93, 334.96 /)
+ co2mlo(1979,:) = (/ 336.24, 336.77, 337.97, 338.89, 339.48, 339.30, 337.74, 336.10, 333.93, 333.87, 335.30, 336.74 /)
+ co2mlo(1980,:) = (/ 338.03, 338.37, 340.09, 340.78, 341.48, 341.19, 339.57, 337.61, 335.90, 336.03, 337.12, 338.23 /)
+ co2mlo(1981,:) = (/ 339.25, 340.50, 341.40, 342.52, 342.93, 342.27, 340.50, 338.45, 336.71, 336.88, 338.38, 339.63 /)
+ co2mlo(1982,:) = (/ 340.77, 341.63, 342.72, 343.59, 344.16, 343.37, 342.07, 339.83, 338.00, 337.88, 339.28, 340.51 /)
+ co2mlo(1983,:) = (/ 341.40, 342.54, 343.12, 344.96, 345.78, 345.34, 344.00, 342.40, 339.88, 340.01, 341.16, 342.98 /)
+ co2mlo(1984,:) = (/ 343.82, 344.62, 345.38, 347.15, 347.52, 346.88, 345.47, 343.34, 341.13, 341.40, 343.02, 344.25 /)
+ co2mlo(1985,:) = (/ 344.99, 346.01, 347.43, 348.34, 348.92, 348.24, 346.54, 344.64, 343.06, 342.78, 344.21, 345.53 /)
+ co2mlo(1986,:) = (/ 346.28, 346.93, 347.83, 349.53, 350.19, 349.53, 347.92, 345.88, 344.83, 344.16, 345.64, 346.88 /)
+ co2mlo(1987,:) = (/ 348.00, 348.47, 349.40, 350.97, 351.84, 351.25, 349.50, 348.09, 346.44, 346.09, 347.54, 348.69 /)
+ co2mlo(1988,:) = (/ 350.16, 351.47, 351.96, 353.33, 353.97, 353.55, 352.14, 350.19, 348.50, 348.66, 349.85, 351.12 /)
+ co2mlo(1989,:) = (/ 352.55, 352.86, 353.48, 355.21, 355.47, 354.92, 353.70, 351.47, 349.61, 349.79, 351.10, 352.32 /)
+ co2mlo(1990,:) = (/ 353.46, 354.50, 355.19, 356.00, 356.96, 356.04, 354.62, 352.71, 350.77, 350.99, 352.64, 354.02 /)
+ co2mlo(1991,:) = (/ 354.53, 355.55, 356.96, 358.40, 359.14, 358.04, 355.98, 353.81, 351.95, 352.02, 353.55, 354.79 /)
+ co2mlo(1992,:) = (/ 355.79, 356.52, 357.61, 358.95, 359.46, 359.05, 356.82, 354.80, 352.81, 353.11, 353.96, 355.20 /)
+ co2mlo(1993,:) = (/ 356.50, 356.97, 358.18, 359.26, 360.08, 359.40, 357.38, 355.33, 353.50, 353.80, 355.15, 356.62 /)
+ co2mlo(1994,:) = (/ 358.19, 358.73, 359.79, 361.09, 361.52, 360.77, 359.38, 357.31, 355.68, 355.83, 357.42, 358.87 /)
+ co2mlo(1995,:) = (/ 359.81, 360.84, 361.48, 363.30, 363.64, 363.11, 361.75, 359.31, 357.91, 357.62, 359.42, 360.56 /)
+ co2mlo(1996,:) = (/ 361.91, 363.11, 363.88, 364.58, 365.29, 364.84, 363.52, 361.35, 359.32, 359.48, 360.64, 362.21 /)
+ co2mlo(1997,:) = (/ 363.07, 363.87, 364.44, 366.23, 366.68, 365.52, 364.36, 362.39, 360.08, 360.67, 362.32, 364.16 /)
+ co2mlo(1998,:) = (/ 365.22, 366.04, 367.20, 368.50, 369.19, 368.77, 367.53, 365.67, 363.80, 364.13, 365.36, 366.87 /)
+ co2mlo(1999,:) = (/ 368.05, 368.77, 369.49, 371.04, 370.90, 370.25, 369.17, 366.83, 364.54, 365.04, 366.58, 367.92 /)
+ co2mlo(2000,:) = (/ 369.05, 369.37, 370.42, 371.57, 371.74, 371.60, 370.02, 368.03, 366.53, 366.64, 368.20, 369.44 /)
+ co2mlo(2001,:) = (/ 370.20, 371.42, 372.04, 372.78, 373.94, 373.23, 371.54, 369.47, 367.88, 368.01, 369.60, 371.15 /)
+ co2mlo(2002,:) = (/ 372.36, 373.00, 373.44, 374.77, 375.48, 375.33, 373.95, 371.41, 370.63, 370.18, 372.01, 373.71 /)
+ co2mlo(2003,:) = (/ 374.61, 375.55, 376.04, 377.58, 378.28, 378.07, 376.54, 374.42, 372.92, 372.94, 374.29, 375.63 /)
+ co2mlo(2004,:) = (/ 376.73, 377.31, 378.33, 380.44, 380.56, 379.49, 377.71, 375.77, 373.99, 374.17, 375.79, 377.39 /)
+ co2mlo(2005,:) = (/ 378.29, 379.56, 380.06, 382.01, 382.21, 382.05, 380.63, 378.64, 376.38, 376.77, 378.27, 379.92 /)
+ co2mlo(2006,:) = (/ 381.33, 381.98, 382.53, 384.33, 384.89, 383.99, 382.25, 380.44, 378.77, 379.03, 380.11, 381.62 /)
+ co2mlo(2007,:) = (/ 382.55, 383.68, 384.31, 386.20, 386.38, 385.85, 384.42, 381.81, 380.83, 380.83, 382.32, 383.58 /)
+ co2mlo(2008,:) = (/ 385.04, 385.81, 385.80, 386.74, 388.49, 388.02, 386.22, 384.05, 383.05, 382.75, 383.98, 385.08 /)
+ co2mlo(2009,:) = (/ 386.63, 387.10, 388.50, 389.54, 390.15, 389.60, 388.05, 386.06, 384.64, 384.32, 386.05, 387.48 /)
+ co2mlo(2010,:) = (/ 388.55, 390.08, 391.02, 392.39, 393.24, 392.26, 390.35, 388.53, 386.85, 387.18, 388.69, 389.83 /)
+ co2mlo(2011,:) = (/ 391.33, 391.96, 392.49, 393.40, 394.33, 393.75, 392.64, 390.25, 389.05, 388.98, 390.30, 391.86 /)
+ co2mlo(2012,:) = (/ 393.13, 393.42, 394.43, 396.51, 396.96, 395.97, 394.60, 392.61, 391.20, 391.09, 393.03, 394.42 /)
+ co2mlo(2013,:) = (/ 395.69, 396.94, 397.35, 398.44, 400.06, 398.95, 397.45, 395.49, 393.47, 393.77, 395.27, 396.90 /)
+ co2mlo(2014,:) = (/ 398.01, 398.18, 399.56, 401.44, 401.98, 401.41, 399.17, 397.30, 395.49, 395.74, 397.32, 398.88 /)
+ co2mlo(2015,:) = (/ 399.94, 400.40, 401.60, 403.53, 404.04, 402.81, 401.54, 398.93, 397.43, 398.22, 400.17, 401.82 /)
+ co2mlo(2016,:) = (/ 402.58, 404.09, 404.79, 407.50, 407.59, 406.94, 404.43, 402.17, 400.95, 401.43, 403.57, 404.48 /)
+ co2mlo(2017,:) = (/ 406.00, 406.57, 406.99, 408.88, 409.84, 409.05, 407.13, 405.17, 403.20, 403.57, 405.10, 406.68 /)
+ co2mlo(2018,:) = (/ 407.98, 408.36, 409.21, 410.24, 411.23, 410.81, 408.83, 407.02, 405.52, 405.93, 408.04, 409.17 /)
+ co2mlo(2019,:) = (/ 410.85, 411.59, 411.91, 413.46, 414.76, 413.89, 411.78, 410.01, 408.48, 408.40, 410.16, 411.81 /)
+ co2mlo(2020,:) = (/ 413.30, 414.05, 414.45, 416.11, 417.15, 416.29, 414.42, 412.52, 411.18, 411.12, 412.88, 413.89 /)
+ co2mlo(2021,:) = (/ 415.15, 416.47, 417.16, 418.24, 418.95, 418.70, 416.65, 414.34, 412.90, 413.55, 414.82, 416.43 /)
+ co2mlo(2022,:) = (/ 418.01, 418.99, 418.45, 420.02, 420.99, 420.99, 418.90, 417.19, 415.95, 415.78, 417.51, 418.95 /)
+ !noted by Zhongwang Wei
+ !May 2022 ~ Dec 2022 data obtained from
+ !https://gml.noaa.gov/webdata/ccgg/trends/co2/co2_mm_mlo.txt (Mauna Loa, Hawaii) Due to the
+ !eruption of the Mauna Loa Volcano, measurements from Mauna Loa Observatory were suspended as
+ !of Nov. 29. 2022 New Observations starting in December 2022 are from a site at the Maunakea
+ !Observatories, approximately 21 miles north of the Mauna Loa Observatory.
+ !CMIP6 co2 data is obtainted from :
+ !Matthias Büchner, Christopher Reyer (2022): ISIMIP3b atmospheric composition input data
+ !(v1.1). ISIMIP Repository. https://doi.org/10.48364/ISIMIP.482153.1
+ !added by Zhongwang Wei @ SYSU 2022.12.12
+ select CASE (trim(DEF_SSP))
+ CASE ('126')
+ !co2mlo(2015,:) = (/ 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95 /)
+ !co2mlo(2016,:) = (/ 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12 /)
+ !co2mlo(2017,:) = (/ 405.75, 405.75, 405.75, 405.75, 405.75, 405.75, 405.75, 405.75, 405.75, 405.75, 405.75, 405.75 /)
+ !co2mlo(2018,:) = (/ 408.59, 408.59, 408.59, 408.59, 408.59, 408.59, 408.59, 408.59, 408.59, 408.59, 408.59, 408.59 /)
+ !co2mlo(2019,:) = (/ 411.42, 411.42, 411.42, 411.42, 411.42, 411.42, 411.42, 411.42, 411.42, 411.42, 411.42, 411.42 /)
+ !co2mlo(2020,:) = (/ 414.23, 414.23, 414.23, 414.23, 414.23, 414.23, 414.23, 414.23, 414.23, 414.23, 414.23, 414.23 /)
+ !co2mlo(2021,:) = (/ 417.04, 417.04, 417.04, 417.04, 417.04, 417.04, 417.04, 417.04, 417.04, 417.04, 417.04, 417.04 /)
+ !co2mlo(2022,:) = (/ 419.81, 419.81, 419.81, 419.81, 419.81, 419.81, 419.81, 419.81, 419.81, 419.81, 419.81, 419.81 /)
+ co2mlo(2023,:) = (/ 422.50, 422.50, 422.50, 422.50, 422.50, 422.50, 422.50, 422.50, 422.50, 422.50, 422.50, 422.50 /)
+ co2mlo(2024,:) = (/ 425.12, 425.12, 425.12, 425.12, 425.12, 425.12, 425.12, 425.12, 425.12, 425.12, 425.12, 425.12 /)
+ co2mlo(2025,:) = (/ 427.67, 427.67, 427.67, 427.67, 427.67, 427.67, 427.67, 427.67, 427.67, 427.67, 427.67, 427.67 /)
+ co2mlo(2026,:) = (/ 430.17, 430.17, 430.17, 430.17, 430.17, 430.17, 430.17, 430.17, 430.17, 430.17, 430.17, 430.17 /)
+ co2mlo(2027,:) = (/ 432.60, 432.60, 432.60, 432.60, 432.60, 432.60, 432.60, 432.60, 432.60, 432.60, 432.60, 432.60 /)
+ co2mlo(2028,:) = (/ 434.97, 434.97, 434.97, 434.97, 434.97, 434.97, 434.97, 434.97, 434.97, 434.97, 434.97, 434.97 /)
+ co2mlo(2029,:) = (/ 437.29, 437.29, 437.29, 437.29, 437.29, 437.29, 437.29, 437.29, 437.29, 437.29, 437.29, 437.29 /)
+ co2mlo(2030,:) = (/ 439.56, 439.56, 439.56, 439.56, 439.56, 439.56, 439.56, 439.56, 439.56, 439.56, 439.56, 439.56 /)
+ co2mlo(2031,:) = (/ 441.78, 441.78, 441.78, 441.78, 441.78, 441.78, 441.78, 441.78, 441.78, 441.78, 441.78, 441.78 /)
+ co2mlo(2032,:) = (/ 443.93, 443.93, 443.93, 443.93, 443.93, 443.93, 443.93, 443.93, 443.93, 443.93, 443.93, 443.93 /)
+ co2mlo(2033,:) = (/ 445.99, 445.99, 445.99, 445.99, 445.99, 445.99, 445.99, 445.99, 445.99, 445.99, 445.99, 445.99 /)
+ co2mlo(2034,:) = (/ 447.97, 447.97, 447.97, 447.97, 447.97, 447.97, 447.97, 447.97, 447.97, 447.97, 447.97, 447.97 /)
+ co2mlo(2035,:) = (/ 449.87, 449.87, 449.87, 449.87, 449.87, 449.87, 449.87, 449.87, 449.87, 449.87, 449.87, 449.87 /)
+ co2mlo(2036,:) = (/ 451.68, 451.68, 451.68, 451.68, 451.68, 451.68, 451.68, 451.68, 451.68, 451.68, 451.68, 451.68 /)
+ co2mlo(2037,:) = (/ 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43 /)
+ co2mlo(2038,:) = (/ 455.09, 455.09, 455.09, 455.09, 455.09, 455.09, 455.09, 455.09, 455.09, 455.09, 455.09, 455.09 /)
+ co2mlo(2039,:) = (/ 456.68, 456.68, 456.68, 456.68, 456.68, 456.68, 456.68, 456.68, 456.68, 456.68, 456.68, 456.68 /)
+ co2mlo(2040,:) = (/ 458.20, 458.20, 458.20, 458.20, 458.20, 458.20, 458.20, 458.20, 458.20, 458.20, 458.20, 458.20 /)
+ co2mlo(2041,:) = (/ 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65 /)
+ co2mlo(2042,:) = (/ 461.02, 461.02, 461.02, 461.02, 461.02, 461.02, 461.02, 461.02, 461.02, 461.02, 461.02, 461.02 /)
+ co2mlo(2043,:) = (/ 462.31, 462.31, 462.31, 462.31, 462.31, 462.31, 462.31, 462.31, 462.31, 462.31, 462.31, 462.31 /)
+ co2mlo(2044,:) = (/ 463.54, 463.54, 463.54, 463.54, 463.54, 463.54, 463.54, 463.54, 463.54, 463.54, 463.54, 463.54 /)
+ co2mlo(2045,:) = (/ 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68 /)
+ co2mlo(2046,:) = (/ 465.75, 465.75, 465.75, 465.75, 465.75, 465.75, 465.75, 465.75, 465.75, 465.75, 465.75, 465.75 /)
+ co2mlo(2047,:) = (/ 466.75, 466.75, 466.75, 466.75, 466.75, 466.75, 466.75, 466.75, 466.75, 466.75, 466.75, 466.75 /)
+ co2mlo(2048,:) = (/ 467.68, 467.68, 467.68, 467.68, 467.68, 467.68, 467.68, 467.68, 467.68, 467.68, 467.68, 467.68 /)
+ co2mlo(2049,:) = (/ 468.53, 468.53, 468.53, 468.53, 468.53, 468.53, 468.53, 468.53, 468.53, 468.53, 468.53, 468.53 /)
+ co2mlo(2050,:) = (/ 469.31, 469.31, 469.31, 469.31, 469.31, 469.31, 469.31, 469.31, 469.31, 469.31, 469.31, 469.31 /)
+ co2mlo(2051,:) = (/ 470.02, 470.02, 470.02, 470.02, 470.02, 470.02, 470.02, 470.02, 470.02, 470.02, 470.02, 470.02 /)
+ co2mlo(2052,:) = (/ 470.66, 470.66, 470.66, 470.66, 470.66, 470.66, 470.66, 470.66, 470.66, 470.66, 470.66, 470.66 /)
+ co2mlo(2053,:) = (/ 471.25, 471.25, 471.25, 471.25, 471.25, 471.25, 471.25, 471.25, 471.25, 471.25, 471.25, 471.25 /)
+ co2mlo(2054,:) = (/ 471.78, 471.78, 471.78, 471.78, 471.78, 471.78, 471.78, 471.78, 471.78, 471.78, 471.78, 471.78 /)
+ co2mlo(2055,:) = (/ 472.25, 472.25, 472.25, 472.25, 472.25, 472.25, 472.25, 472.25, 472.25, 472.25, 472.25, 472.25 /)
+ co2mlo(2056,:) = (/ 472.66, 472.66, 472.66, 472.66, 472.66, 472.66, 472.66, 472.66, 472.66, 472.66, 472.66, 472.66 /)
+ co2mlo(2057,:) = (/ 473.02, 473.02, 473.02, 473.02, 473.02, 473.02, 473.02, 473.02, 473.02, 473.02, 473.02, 473.02 /)
+ co2mlo(2058,:) = (/ 473.32, 473.32, 473.32, 473.32, 473.32, 473.32, 473.32, 473.32, 473.32, 473.32, 473.32, 473.32 /)
+ co2mlo(2059,:) = (/ 473.56, 473.56, 473.56, 473.56, 473.56, 473.56, 473.56, 473.56, 473.56, 473.56, 473.56, 473.56 /)
+ co2mlo(2060,:) = (/ 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75 /)
+ co2mlo(2061,:) = (/ 473.88, 473.88, 473.88, 473.88, 473.88, 473.88, 473.88, 473.88, 473.88, 473.88, 473.88, 473.88 /)
+ co2mlo(2062,:) = (/ 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96 /)
+ co2mlo(2063,:) = (/ 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00 /)
+ co2mlo(2064,:) = (/ 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00, 474.00 /)
+ co2mlo(2065,:) = (/ 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96, 473.96 /)
+ co2mlo(2066,:) = (/ 473.87, 473.87, 473.87, 473.87, 473.87, 473.87, 473.87, 473.87, 473.87, 473.87, 473.87, 473.87 /)
+ co2mlo(2067,:) = (/ 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75, 473.75 /)
+ co2mlo(2068,:) = (/ 473.58, 473.58, 473.58, 473.58, 473.58, 473.58, 473.58, 473.58, 473.58, 473.58, 473.58, 473.58 /)
+ co2mlo(2069,:) = (/ 473.36, 473.36, 473.36, 473.36, 473.36, 473.36, 473.36, 473.36, 473.36, 473.36, 473.36, 473.36 /)
+ co2mlo(2070,:) = (/ 473.11, 473.11, 473.11, 473.11, 473.11, 473.11, 473.11, 473.11, 473.11, 473.11, 473.11, 473.11 /)
+ co2mlo(2071,:) = (/ 472.81, 472.81, 472.81, 472.81, 472.81, 472.81, 472.81, 472.81, 472.81, 472.81, 472.81, 472.81 /)
+ co2mlo(2072,:) = (/ 472.46, 472.46, 472.46, 472.46, 472.46, 472.46, 472.46, 472.46, 472.46, 472.46, 472.46, 472.46 /)
+ co2mlo(2073,:) = (/ 472.04, 472.04, 472.04, 472.04, 472.04, 472.04, 472.04, 472.04, 472.04, 472.04, 472.04, 472.04 /)
+ co2mlo(2074,:) = (/ 471.56, 471.56, 471.56, 471.56, 471.56, 471.56, 471.56, 471.56, 471.56, 471.56, 471.56, 471.56 /)
+ co2mlo(2075,:) = (/ 471.02, 471.02, 471.02, 471.02, 471.02, 471.02, 471.02, 471.02, 471.02, 471.02, 471.02, 471.02 /)
+ co2mlo(2076,:) = (/ 470.41, 470.41, 470.41, 470.41, 470.41, 470.41, 470.41, 470.41, 470.41, 470.41, 470.41, 470.41 /)
+ co2mlo(2077,:) = (/ 469.75, 469.75, 469.75, 469.75, 469.75, 469.75, 469.75, 469.75, 469.75, 469.75, 469.75, 469.75 /)
+ co2mlo(2078,:) = (/ 469.02, 469.02, 469.02, 469.02, 469.02, 469.02, 469.02, 469.02, 469.02, 469.02, 469.02, 469.02 /)
+ co2mlo(2079,:) = (/ 468.24, 468.24, 468.24, 468.24, 468.24, 468.24, 468.24, 468.24, 468.24, 468.24, 468.24, 468.24 /)
+ co2mlo(2080,:) = (/ 467.39, 467.39, 467.39, 467.39, 467.39, 467.39, 467.39, 467.39, 467.39, 467.39, 467.39, 467.39 /)
+ co2mlo(2081,:) = (/ 466.48, 466.48, 466.48, 466.48, 466.48, 466.48, 466.48, 466.48, 466.48, 466.48, 466.48, 466.48 /)
+ co2mlo(2082,:) = (/ 465.54, 465.54, 465.54, 465.54, 465.54, 465.54, 465.54, 465.54, 465.54, 465.54, 465.54, 465.54 /)
+ co2mlo(2083,:) = (/ 464.56, 464.56, 464.56, 464.56, 464.56, 464.56, 464.56, 464.56, 464.56, 464.56, 464.56, 464.56 /)
+ co2mlo(2084,:) = (/ 463.56, 463.56, 463.56, 463.56, 463.56, 463.56, 463.56, 463.56, 463.56, 463.56, 463.56, 463.56 /)
+ co2mlo(2085,:) = (/ 462.53, 462.53, 462.53, 462.53, 462.53, 462.53, 462.53, 462.53, 462.53, 462.53, 462.53, 462.53 /)
+ co2mlo(2086,:) = (/ 461.47, 461.47, 461.47, 461.47, 461.47, 461.47, 461.47, 461.47, 461.47, 461.47, 461.47, 461.47 /)
+ co2mlo(2087,:) = (/ 460.38, 460.38, 460.38, 460.38, 460.38, 460.38, 460.38, 460.38, 460.38, 460.38, 460.38, 460.38 /)
+ co2mlo(2088,:) = (/ 459.26, 459.26, 459.26, 459.26, 459.26, 459.26, 459.26, 459.26, 459.26, 459.26, 459.26, 459.26 /)
+ co2mlo(2089,:) = (/ 458.10, 458.10, 458.10, 458.10, 458.10, 458.10, 458.10, 458.10, 458.10, 458.10, 458.10, 458.10 /)
+ co2mlo(2090,:) = (/ 456.92, 456.92, 456.92, 456.92, 456.92, 456.92, 456.92, 456.92, 456.92, 456.92, 456.92, 456.92 /)
+ co2mlo(2091,:) = (/ 455.71, 455.71, 455.71, 455.71, 455.71, 455.71, 455.71, 455.71, 455.71, 455.71, 455.71, 455.71 /)
+ co2mlo(2092,:) = (/ 454.50, 454.50, 454.50, 454.50, 454.50, 454.50, 454.50, 454.50, 454.50, 454.50, 454.50, 454.50 /)
+ co2mlo(2093,:) = (/ 453.32, 453.32, 453.32, 453.32, 453.32, 453.32, 453.32, 453.32, 453.32, 453.32, 453.32, 453.32 /)
+ co2mlo(2094,:) = (/ 452.16, 452.16, 452.16, 452.16, 452.16, 452.16, 452.16, 452.16, 452.16, 452.16, 452.16, 452.16 /)
+ co2mlo(2095,:) = (/ 451.02, 451.02, 451.02, 451.02, 451.02, 451.02, 451.02, 451.02, 451.02, 451.02, 451.02, 451.02 /)
+ co2mlo(2096,:) = (/ 449.91, 449.91, 449.91, 449.91, 449.91, 449.91, 449.91, 449.91, 449.91, 449.91, 449.91, 449.91 /)
+ co2mlo(2097,:) = (/ 448.81, 448.81, 448.81, 448.81, 448.81, 448.81, 448.81, 448.81, 448.81, 448.81, 448.81, 448.81 /)
+ co2mlo(2098,:) = (/ 447.73, 447.73, 447.73, 447.73, 447.73, 447.73, 447.73, 447.73, 447.73, 447.73, 447.73, 447.73 /)
+ co2mlo(2099,:) = (/ 446.67, 446.67, 446.67, 446.67, 446.67, 446.67, 446.67, 446.67, 446.67, 446.67, 446.67, 446.67 /)
+ co2mlo(2100,:) = (/ 445.62, 445.62, 445.62, 445.62, 445.62, 445.62, 445.62, 445.62, 445.62, 445.62, 445.62, 445.62 /)
+ !added by Zhongwang Wei @ SYSU 2022.12.12
+ CASE ('245')
+ print *,'245'
+ !co2mlo(2015,:) = (/ 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95 /)
+ !co2mlo(2016,:) = (/ 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12 /)
+ !co2mlo(2017,:) = (/ 405.76, 405.76, 405.76, 405.76, 405.76, 405.76, 405.76, 405.76, 405.76, 405.76, 405.81, 405.81 /)
+ !co2mlo(2018,:) = (/ 408.63, 408.63, 408.63, 408.63, 408.63, 408.63, 408.63, 408.63, 408.63, 408.63, 408.83, 408.83 /)
+ !co2mlo(2019,:) = (/ 411.51, 411.51, 411.51, 411.51, 411.51, 411.51, 411.51, 411.51, 411.51, 411.51, 411.95, 411.95 /)
+ !co2mlo(2020,:) = (/ 414.39, 414.39, 414.39, 414.39, 414.39, 414.39, 414.39, 414.39, 414.39, 414.39, 415.15, 415.15 /)
+ !co2mlo(2021,:) = (/ 417.29, 417.29, 417.29, 417.29, 417.29, 417.29, 417.29, 417.29, 417.29, 417.29, 418.46, 418.46 /)
+ !co2mlo(2022,:) = (/ 420.20, 420.20, 420.20, 420.20, 420.20, 420.20, 420.20, 420.20, 420.20, 420.20, 421.84, 421.84 /)
+ co2mlo(2023,:) = (/ 423.12, 423.12, 423.12, 423.12, 423.12, 423.12, 423.12, 423.12, 423.12, 423.12, 425.28, 425.28 /)
+ co2mlo(2024,:) = (/ 426.07, 426.07, 426.07, 426.07, 426.07, 426.07, 426.07, 426.07, 426.07, 426.07, 428.78, 428.78 /)
+ co2mlo(2025,:) = (/ 429.03, 429.03, 429.03, 429.03, 429.03, 429.03, 429.03, 429.03, 429.03, 429.03, 432.35, 432.35 /)
+ co2mlo(2026,:) = (/ 432.01, 432.01, 432.01, 432.01, 432.01, 432.01, 432.01, 432.01, 432.01, 432.01, 435.97, 435.97 /)
+ co2mlo(2027,:) = (/ 435.01, 435.01, 435.01, 435.01, 435.01, 435.01, 435.01, 435.01, 435.01, 435.01, 439.67, 439.67 /)
+ co2mlo(2028,:) = (/ 438.03, 438.03, 438.03, 438.03, 438.03, 438.03, 438.03, 438.03, 438.03, 438.03, 443.43, 443.43 /)
+ co2mlo(2029,:) = (/ 441.08, 441.08, 441.08, 441.08, 441.08, 441.08, 441.08, 441.08, 441.08, 441.08, 447.26, 447.26 /)
+ co2mlo(2030,:) = (/ 444.14, 444.14, 444.14, 444.14, 444.14, 444.14, 444.14, 444.14, 444.14, 444.14, 451.16, 451.16 /)
+ co2mlo(2031,:) = (/ 447.23, 447.23, 447.23, 447.23, 447.23, 447.23, 447.23, 447.23, 447.23, 447.23, 455.14, 455.14 /)
+ co2mlo(2032,:) = (/ 450.33, 450.33, 450.33, 450.33, 450.33, 450.33, 450.33, 450.33, 450.33, 450.33, 459.17, 459.17 /)
+ co2mlo(2033,:) = (/ 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 453.43, 463.24, 463.24 /)
+ co2mlo(2034,:) = (/ 456.54, 456.54, 456.54, 456.54, 456.54, 456.54, 456.54, 456.54, 456.54, 456.54, 467.36, 467.36 /)
+ co2mlo(2035,:) = (/ 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 459.65, 471.54, 471.54 /)
+ co2mlo(2036,:) = (/ 462.77, 462.77, 462.77, 462.77, 462.77, 462.77, 462.77, 462.77, 462.77, 462.77, 475.76, 475.76 /)
+ co2mlo(2037,:) = (/ 465.90, 465.90, 465.90, 465.90, 465.90, 465.90, 465.90, 465.90, 465.90, 465.90, 480.04, 480.04 /)
+ co2mlo(2038,:) = (/ 469.03, 469.03, 469.03, 469.03, 469.03, 469.03, 469.03, 469.03, 469.03, 469.03, 484.38, 484.38 /)
+ co2mlo(2039,:) = (/ 472.18, 472.18, 472.18, 472.18, 472.18, 472.18, 472.18, 472.18, 472.18, 472.18, 488.77, 488.77 /)
+ co2mlo(2040,:) = (/ 475.34, 475.34, 475.34, 475.34, 475.34, 475.34, 475.34, 475.34, 475.34, 475.34, 493.22, 493.22 /)
+ co2mlo(2041,:) = (/ 478.50, 478.50, 478.50, 478.50, 478.50, 478.50, 478.50, 478.50, 478.50, 478.50, 497.73, 497.73 /)
+ co2mlo(2042,:) = (/ 481.67, 481.67, 481.67, 481.67, 481.67, 481.67, 481.67, 481.67, 481.67, 481.67, 502.29, 502.29 /)
+ co2mlo(2043,:) = (/ 484.84, 484.84, 484.84, 484.84, 484.84, 484.84, 484.84, 484.84, 484.84, 484.84, 506.90, 506.90 /)
+ co2mlo(2044,:) = (/ 488.00, 488.00, 488.00, 488.00, 488.00, 488.00, 488.00, 488.00, 488.00, 488.00, 511.56, 511.56 /)
+ co2mlo(2045,:) = (/ 491.15, 491.15, 491.15, 491.15, 491.15, 491.15, 491.15, 491.15, 491.15, 491.15, 516.26, 516.26 /)
+ co2mlo(2046,:) = (/ 494.30, 494.30, 494.30, 494.30, 494.30, 494.30, 494.30, 494.30, 494.30, 494.30, 521.02, 521.02 /)
+ co2mlo(2047,:) = (/ 497.45, 497.45, 497.45, 497.45, 497.45, 497.45, 497.45, 497.45, 497.45, 497.45, 525.83, 525.83 /)
+ co2mlo(2048,:) = (/ 500.59, 500.59, 500.59, 500.59, 500.59, 500.59, 500.59, 500.59, 500.59, 500.59, 530.69, 530.69 /)
+ co2mlo(2049,:) = (/ 503.73, 503.73, 503.73, 503.73, 503.73, 503.73, 503.73, 503.73, 503.73, 503.73, 535.61, 535.61 /)
+ co2mlo(2050,:) = (/ 506.87, 506.87, 506.87, 506.87, 506.87, 506.87, 506.87, 506.87, 506.87, 506.87, 540.58, 540.58 /)
+ co2mlo(2051,:) = (/ 510.01, 510.01, 510.01, 510.01, 510.01, 510.01, 510.01, 510.01, 510.01, 510.01, 545.61, 545.61 /)
+ co2mlo(2052,:) = (/ 513.14, 513.14, 513.14, 513.14, 513.14, 513.14, 513.14, 513.14, 513.14, 513.14, 550.69, 550.69 /)
+ co2mlo(2053,:) = (/ 516.23, 516.23, 516.23, 516.23, 516.23, 516.23, 516.23, 516.23, 516.23, 516.23, 555.82, 555.82 /)
+ co2mlo(2054,:) = (/ 519.29, 519.29, 519.29, 519.29, 519.29, 519.29, 519.29, 519.29, 519.29, 519.29, 561.00, 561.00 /)
+ co2mlo(2055,:) = (/ 522.33, 522.33, 522.33, 522.33, 522.33, 522.33, 522.33, 522.33, 522.33, 522.33, 566.24, 566.24 /)
+ co2mlo(2056,:) = (/ 525.33, 525.33, 525.33, 525.33, 525.33, 525.33, 525.33, 525.33, 525.33, 525.33, 571.53, 571.53 /)
+ co2mlo(2057,:) = (/ 528.31, 528.31, 528.31, 528.31, 528.31, 528.31, 528.31, 528.31, 528.31, 528.31, 576.87, 576.87 /)
+ co2mlo(2058,:) = (/ 531.26, 531.26, 531.26, 531.26, 531.26, 531.26, 531.26, 531.26, 531.26, 531.26, 582.27, 582.27 /)
+ co2mlo(2059,:) = (/ 534.19, 534.19, 534.19, 534.19, 534.19, 534.19, 534.19, 534.19, 534.19, 534.19, 587.72, 587.72 /)
+ co2mlo(2060,:) = (/ 537.08, 537.08, 537.08, 537.08, 537.08, 537.08, 537.08, 537.08, 537.08, 537.08, 593.23, 593.23 /)
+ co2mlo(2061,:) = (/ 539.96, 539.96, 539.96, 539.96, 539.96, 539.96, 539.96, 539.96, 539.96, 539.96, 598.80, 598.80 /)
+ co2mlo(2062,:) = (/ 542.79, 542.79, 542.79, 542.79, 542.79, 542.79, 542.79, 542.79, 542.79, 542.79, 604.42, 604.42 /)
+ co2mlo(2063,:) = (/ 545.59, 545.59, 545.59, 545.59, 545.59, 545.59, 545.59, 545.59, 545.59, 545.59, 610.11, 610.11 /)
+ co2mlo(2064,:) = (/ 548.33, 548.33, 548.33, 548.33, 548.33, 548.33, 548.33, 548.33, 548.33, 548.33, 615.85, 615.85 /)
+ co2mlo(2065,:) = (/ 551.04, 551.04, 551.04, 551.04, 551.04, 551.04, 551.04, 551.04, 551.04, 551.04, 621.65, 621.65 /)
+ co2mlo(2066,:) = (/ 553.70, 553.70, 553.70, 553.70, 553.70, 553.70, 553.70, 553.70, 553.70, 553.70, 627.50, 627.50 /)
+ co2mlo(2067,:) = (/ 556.32, 556.32, 556.32, 556.32, 556.32, 556.32, 556.32, 556.32, 556.32, 556.32, 633.42, 633.42 /)
+ co2mlo(2068,:) = (/ 558.89, 558.89, 558.89, 558.89, 558.89, 558.89, 558.89, 558.89, 558.89, 558.89, 639.40, 639.40 /)
+ co2mlo(2069,:) = (/ 561.43, 561.43, 561.43, 561.43, 561.43, 561.43, 561.43, 561.43, 561.43, 561.43, 645.44, 645.44 /)
+ co2mlo(2070,:) = (/ 563.92, 563.92, 563.92, 563.92, 563.92, 563.92, 563.92, 563.92, 563.92, 563.92, 651.54, 651.54 /)
+ co2mlo(2071,:) = (/ 566.38, 566.38, 566.38, 566.38, 566.38, 566.38, 566.38, 566.38, 566.38, 566.38, 657.71, 657.71 /)
+ co2mlo(2072,:) = (/ 568.77, 568.77, 568.77, 568.77, 568.77, 568.77, 568.77, 568.77, 568.77, 568.77, 663.93, 663.93 /)
+ co2mlo(2073,:) = (/ 571.08, 571.08, 571.08, 571.08, 571.08, 571.08, 571.08, 571.08, 571.08, 571.08, 670.22, 670.22 /)
+ co2mlo(2074,:) = (/ 573.31, 573.31, 573.31, 573.31, 573.31, 573.31, 573.31, 573.31, 573.31, 573.31, 676.57, 676.57 /)
+ co2mlo(2075,:) = (/ 575.47, 575.47, 575.47, 575.47, 575.47, 575.47, 575.47, 575.47, 575.47, 575.47, 682.98, 682.98 /)
+ co2mlo(2076,:) = (/ 577.54, 577.54, 577.54, 577.54, 577.54, 577.54, 577.54, 577.54, 577.54, 577.54, 689.46, 689.46 /)
+ co2mlo(2077,:) = (/ 579.54, 579.54, 579.54, 579.54, 579.54, 579.54, 579.54, 579.54, 579.54, 579.54, 696.00, 696.00 /)
+ co2mlo(2078,:) = (/ 581.46, 581.46, 581.46, 581.46, 581.46, 581.46, 581.46, 581.46, 581.46, 581.46, 702.61, 702.61 /)
+ co2mlo(2079,:) = (/ 583.30, 583.30, 583.30, 583.30, 583.30, 583.30, 583.30, 583.30, 583.30, 583.30, 709.27, 709.27 /)
+ co2mlo(2080,:) = (/ 585.07, 585.07, 585.07, 585.07, 585.07, 585.07, 585.07, 585.07, 585.07, 585.07, 716.01, 716.01 /)
+ co2mlo(2081,:) = (/ 586.77, 586.77, 586.77, 586.77, 586.77, 586.77, 586.77, 586.77, 586.77, 586.77, 722.81, 722.81 /)
+ co2mlo(2082,:) = (/ 588.38, 588.38, 588.38, 588.38, 588.38, 588.38, 588.38, 588.38, 588.38, 588.38, 729.68, 729.68 /)
+ co2mlo(2083,:) = (/ 589.89, 589.89, 589.89, 589.89, 589.89, 589.89, 589.89, 589.89, 589.89, 589.89, 736.63, 736.63 /)
+ co2mlo(2084,:) = (/ 591.30, 591.30, 591.30, 591.30, 591.30, 591.30, 591.30, 591.30, 591.30, 591.30, 743.66, 743.66 /)
+ co2mlo(2085,:) = (/ 592.61, 592.61, 592.61, 592.61, 592.61, 592.61, 592.61, 592.61, 592.61, 592.61, 750.76, 750.76 /)
+ co2mlo(2086,:) = (/ 593.82, 593.82, 593.82, 593.82, 593.82, 593.82, 593.82, 593.82, 593.82, 593.82, 757.95, 757.95 /)
+ co2mlo(2087,:) = (/ 594.94, 594.94, 594.94, 594.94, 594.94, 594.94, 594.94, 594.94, 594.94, 594.94, 765.22, 765.22 /)
+ co2mlo(2088,:) = (/ 595.97, 595.97, 595.97, 595.97, 595.97, 595.97, 595.97, 595.97, 595.97, 595.97, 772.56, 772.56 /)
+ co2mlo(2089,:) = (/ 596.90, 596.90, 596.90, 596.90, 596.90, 596.90, 596.90, 596.90, 596.90, 596.90, 779.98, 779.98 /)
+ co2mlo(2090,:) = (/ 597.73, 597.73, 597.73, 597.73, 597.73, 597.73, 597.73, 597.73, 597.73, 597.73, 787.49, 787.49 /)
+ co2mlo(2091,:) = (/ 598.48, 598.48, 598.48, 598.48, 598.48, 598.48, 598.48, 598.48, 598.48, 598.48, 795.07, 795.07 /)
+ co2mlo(2092,:) = (/ 599.15, 599.15, 599.15, 599.15, 599.15, 599.15, 599.15, 599.15, 599.15, 599.15, 802.74, 802.74 /)
+ co2mlo(2093,:) = (/ 599.78, 599.78, 599.78, 599.78, 599.78, 599.78, 599.78, 599.78, 599.78, 599.78, 810.49, 810.49 /)
+ co2mlo(2094,:) = (/ 600.35, 600.35, 600.35, 600.35, 600.35, 600.35, 600.35, 600.35, 600.35, 600.35, 818.33, 818.33 /)
+ co2mlo(2095,:) = (/ 600.89, 600.89, 600.89, 600.89, 600.89, 600.89, 600.89, 600.89, 600.89, 600.89, 826.25, 826.25 /)
+ co2mlo(2096,:) = (/ 601.37, 601.37, 601.37, 601.37, 601.37, 601.37, 601.37, 601.37, 601.37, 601.37, 834.27, 834.27 /)
+ co2mlo(2097,:) = (/ 601.80, 601.80, 601.80, 601.80, 601.80, 601.80, 601.80, 601.80, 601.80, 601.80, 842.37, 842.37 /)
+ co2mlo(2098,:) = (/ 602.18, 602.18, 602.18, 602.18, 602.18, 602.18, 602.18, 602.18, 602.18, 602.18, 850.55, 850.55 /)
+ co2mlo(2099,:) = (/ 602.51, 602.51, 602.51, 602.51, 602.51, 602.51, 602.51, 602.51, 602.51, 602.51, 858.83, 858.83 /)
+ co2mlo(2100,:) = (/ 602.78, 602.78, 602.78, 602.78, 602.78, 602.78, 602.78, 602.78, 602.78, 602.78, 867.19, 867.19 /)
+ !added by Zhongwang Wei @ SYSU 2022.12.12
+ CASE ('370')
+ !co2mlo(2015,:) = (/ 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95 /)
+ !co2mlo(2016,:) = (/ 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12 /)
+ !co2mlo(2017,:) = (/ 405.81, 405.81, 405.81, 405.81, 405.81, 405.81, 405.81, 405.81, 405.81, 405.81, 405.81, 405.81 /)
+ !co2mlo(2018,:) = (/ 408.83, 408.83, 408.83, 408.83, 408.83, 408.83, 408.83, 408.83, 408.83, 408.83, 408.83, 408.83 /)
+ !co2mlo(2019,:) = (/ 411.95, 411.95, 411.95, 411.95, 411.95, 411.95, 411.95, 411.95, 411.95, 411.95, 411.95, 411.95 /)
+ !co2mlo(2020,:) = (/ 415.15, 415.15, 415.15, 415.15, 415.15, 415.15, 415.15, 415.15, 415.15, 415.15, 415.15, 415.15 /)
+ !co2mlo(2021,:) = (/ 418.46, 418.46, 418.46, 418.46, 418.46, 418.46, 418.46, 418.46, 418.46, 418.46, 418.46, 418.46 /)
+ !co2mlo(2022,:) = (/ 421.84, 421.84, 421.84, 421.84, 421.84, 421.84, 421.84, 421.84, 421.84, 421.84, 421.84, 421.84 /)
+ co2mlo(2023,:) = (/ 425.28, 425.28, 425.28, 425.28, 425.28, 425.28, 425.28, 425.28, 425.28, 425.28, 425.28, 425.28 /)
+ co2mlo(2024,:) = (/ 428.78, 428.78, 428.78, 428.78, 428.78, 428.78, 428.78, 428.78, 428.78, 428.78, 428.78, 428.78 /)
+ co2mlo(2025,:) = (/ 432.35, 432.35, 432.35, 432.35, 432.35, 432.35, 432.35, 432.35, 432.35, 432.35, 432.35, 432.35 /)
+ co2mlo(2026,:) = (/ 435.97, 435.97, 435.97, 435.97, 435.97, 435.97, 435.97, 435.97, 435.97, 435.97, 435.97, 435.97 /)
+ co2mlo(2027,:) = (/ 439.67, 439.67, 439.67, 439.67, 439.67, 439.67, 439.67, 439.67, 439.67, 439.67, 439.67, 439.67 /)
+ co2mlo(2028,:) = (/ 443.43, 443.43, 443.43, 443.43, 443.43, 443.43, 443.43, 443.43, 443.43, 443.43, 443.43, 443.43 /)
+ co2mlo(2029,:) = (/ 447.26, 447.26, 447.26, 447.26, 447.26, 447.26, 447.26, 447.26, 447.26, 447.26, 447.26, 447.26 /)
+ co2mlo(2030,:) = (/ 451.16, 451.16, 451.16, 451.16, 451.16, 451.16, 451.16, 451.16, 451.16, 451.16, 451.16, 451.16 /)
+ co2mlo(2031,:) = (/ 455.14, 455.14, 455.14, 455.14, 455.14, 455.14, 455.14, 455.14, 455.14, 455.14, 455.14, 455.14 /)
+ co2mlo(2032,:) = (/ 459.17, 459.17, 459.17, 459.17, 459.17, 459.17, 459.17, 459.17, 459.17, 459.17, 459.17, 459.17 /)
+ co2mlo(2033,:) = (/ 463.24, 463.24, 463.24, 463.24, 463.24, 463.24, 463.24, 463.24, 463.24, 463.24, 463.24, 463.24 /)
+ co2mlo(2034,:) = (/ 467.36, 467.36, 467.36, 467.36, 467.36, 467.36, 467.36, 467.36, 467.36, 467.36, 467.36, 467.36 /)
+ co2mlo(2035,:) = (/ 471.54, 471.54, 471.54, 471.54, 471.54, 471.54, 471.54, 471.54, 471.54, 471.54, 471.54, 471.54 /)
+ co2mlo(2036,:) = (/ 475.76, 475.76, 475.76, 475.76, 475.76, 475.76, 475.76, 475.76, 475.76, 475.76, 475.76, 475.76 /)
+ co2mlo(2037,:) = (/ 480.04, 480.04, 480.04, 480.04, 480.04, 480.04, 480.04, 480.04, 480.04, 480.04, 480.04, 480.04 /)
+ co2mlo(2038,:) = (/ 484.38, 484.38, 484.38, 484.38, 484.38, 484.38, 484.38, 484.38, 484.38, 484.38, 484.38, 484.38 /)
+ co2mlo(2039,:) = (/ 488.77, 488.77, 488.77, 488.77, 488.77, 488.77, 488.77, 488.77, 488.77, 488.77, 488.77, 488.77 /)
+ co2mlo(2040,:) = (/ 493.22, 493.22, 493.22, 493.22, 493.22, 493.22, 493.22, 493.22, 493.22, 493.22, 493.22, 493.22 /)
+ co2mlo(2041,:) = (/ 497.73, 497.73, 497.73, 497.73, 497.73, 497.73, 497.73, 497.73, 497.73, 497.73, 497.73, 497.73 /)
+ co2mlo(2042,:) = (/ 502.29, 502.29, 502.29, 502.29, 502.29, 502.29, 502.29, 502.29, 502.29, 502.29, 502.29, 502.29 /)
+ co2mlo(2043,:) = (/ 506.90, 506.90, 506.90, 506.90, 506.90, 506.90, 506.90, 506.90, 506.90, 506.90, 506.90, 506.90 /)
+ co2mlo(2044,:) = (/ 511.56, 511.56, 511.56, 511.56, 511.56, 511.56, 511.56, 511.56, 511.56, 511.56, 511.56, 511.56 /)
+ co2mlo(2045,:) = (/ 516.26, 516.26, 516.26, 516.26, 516.26, 516.26, 516.26, 516.26, 516.26, 516.26, 516.26, 516.26 /)
+ co2mlo(2046,:) = (/ 521.02, 521.02, 521.02, 521.02, 521.02, 521.02, 521.02, 521.02, 521.02, 521.02, 521.02, 521.02 /)
+ co2mlo(2047,:) = (/ 525.83, 525.83, 525.83, 525.83, 525.83, 525.83, 525.83, 525.83, 525.83, 525.83, 525.83, 525.83 /)
+ co2mlo(2048,:) = (/ 530.69, 530.69, 530.69, 530.69, 530.69, 530.69, 530.69, 530.69, 530.69, 530.69, 530.69, 530.69 /)
+ co2mlo(2049,:) = (/ 535.61, 535.61, 535.61, 535.61, 535.61, 535.61, 535.61, 535.61, 535.61, 535.61, 535.61, 535.61 /)
+ co2mlo(2050,:) = (/ 540.58, 540.58, 540.58, 540.58, 540.58, 540.58, 540.58, 540.58, 540.58, 540.58, 540.58, 540.58 /)
+ co2mlo(2051,:) = (/ 545.61, 545.61, 545.61, 545.61, 545.61, 545.61, 545.61, 545.61, 545.61, 545.61, 545.61, 545.61 /)
+ co2mlo(2052,:) = (/ 550.69, 550.69, 550.69, 550.69, 550.69, 550.69, 550.69, 550.69, 550.69, 550.69, 550.69, 550.69 /)
+ co2mlo(2053,:) = (/ 555.82, 555.82, 555.82, 555.82, 555.82, 555.82, 555.82, 555.82, 555.82, 555.82, 555.82, 555.82 /)
+ co2mlo(2054,:) = (/ 561.00, 561.00, 561.00, 561.00, 561.00, 561.00, 561.00, 561.00, 561.00, 561.00, 561.00, 561.00 /)
+ co2mlo(2055,:) = (/ 566.24, 566.24, 566.24, 566.24, 566.24, 566.24, 566.24, 566.24, 566.24, 566.24, 566.24, 566.24 /)
+ co2mlo(2056,:) = (/ 571.53, 571.53, 571.53, 571.53, 571.53, 571.53, 571.53, 571.53, 571.53, 571.53, 571.53, 571.53 /)
+ co2mlo(2057,:) = (/ 576.87, 576.87, 576.87, 576.87, 576.87, 576.87, 576.87, 576.87, 576.87, 576.87, 576.87, 576.87 /)
+ co2mlo(2058,:) = (/ 582.27, 582.27, 582.27, 582.27, 582.27, 582.27, 582.27, 582.27, 582.27, 582.27, 582.27, 582.27 /)
+ co2mlo(2059,:) = (/ 587.72, 587.72, 587.72, 587.72, 587.72, 587.72, 587.72, 587.72, 587.72, 587.72, 587.72, 587.72 /)
+ co2mlo(2060,:) = (/ 593.23, 593.23, 593.23, 593.23, 593.23, 593.23, 593.23, 593.23, 593.23, 593.23, 593.23, 593.23 /)
+ co2mlo(2061,:) = (/ 598.80, 598.80, 598.80, 598.80, 598.80, 598.80, 598.80, 598.80, 598.80, 598.80, 598.80, 598.80 /)
+ co2mlo(2062,:) = (/ 604.42, 604.42, 604.42, 604.42, 604.42, 604.42, 604.42, 604.42, 604.42, 604.42, 604.42, 604.42 /)
+ co2mlo(2063,:) = (/ 610.11, 610.11, 610.11, 610.11, 610.11, 610.11, 610.11, 610.11, 610.11, 610.11, 610.11, 610.11 /)
+ co2mlo(2064,:) = (/ 615.85, 615.85, 615.85, 615.85, 615.85, 615.85, 615.85, 615.85, 615.85, 615.85, 615.85, 615.85 /)
+ co2mlo(2065,:) = (/ 621.65, 621.65, 621.65, 621.65, 621.65, 621.65, 621.65, 621.65, 621.65, 621.65, 621.65, 621.65 /)
+ co2mlo(2066,:) = (/ 627.50, 627.50, 627.50, 627.50, 627.50, 627.50, 627.50, 627.50, 627.50, 627.50, 627.50, 627.50 /)
+ co2mlo(2067,:) = (/ 633.42, 633.42, 633.42, 633.42, 633.42, 633.42, 633.42, 633.42, 633.42, 633.42, 633.42, 633.42 /)
+ co2mlo(2068,:) = (/ 639.40, 639.40, 639.40, 639.40, 639.40, 639.40, 639.40, 639.40, 639.40, 639.40, 639.40, 639.40 /)
+ co2mlo(2069,:) = (/ 645.44, 645.44, 645.44, 645.44, 645.44, 645.44, 645.44, 645.44, 645.44, 645.44, 645.44, 645.44 /)
+ co2mlo(2070,:) = (/ 651.54, 651.54, 651.54, 651.54, 651.54, 651.54, 651.54, 651.54, 651.54, 651.54, 651.54, 651.54 /)
+ co2mlo(2071,:) = (/ 657.71, 657.71, 657.71, 657.71, 657.71, 657.71, 657.71, 657.71, 657.71, 657.71, 657.71, 657.71 /)
+ co2mlo(2072,:) = (/ 663.93, 663.93, 663.93, 663.93, 663.93, 663.93, 663.93, 663.93, 663.93, 663.93, 663.93, 663.93 /)
+ co2mlo(2073,:) = (/ 670.22, 670.22, 670.22, 670.22, 670.22, 670.22, 670.22, 670.22, 670.22, 670.22, 670.22, 670.22 /)
+ co2mlo(2074,:) = (/ 676.57, 676.57, 676.57, 676.57, 676.57, 676.57, 676.57, 676.57, 676.57, 676.57, 676.57, 676.57 /)
+ co2mlo(2075,:) = (/ 682.98, 682.98, 682.98, 682.98, 682.98, 682.98, 682.98, 682.98, 682.98, 682.98, 682.98, 682.98 /)
+ co2mlo(2076,:) = (/ 689.46, 689.46, 689.46, 689.46, 689.46, 689.46, 689.46, 689.46, 689.46, 689.46, 689.46, 689.46 /)
+ co2mlo(2077,:) = (/ 696.00, 696.00, 696.00, 696.00, 696.00, 696.00, 696.00, 696.00, 696.00, 696.00, 696.00, 696.00 /)
+ co2mlo(2078,:) = (/ 702.61, 702.61, 702.61, 702.61, 702.61, 702.61, 702.61, 702.61, 702.61, 702.61, 702.61, 702.61 /)
+ co2mlo(2079,:) = (/ 709.27, 709.27, 709.27, 709.27, 709.27, 709.27, 709.27, 709.27, 709.27, 709.27, 709.27, 709.27 /)
+ co2mlo(2080,:) = (/ 716.01, 716.01, 716.01, 716.01, 716.01, 716.01, 716.01, 716.01, 716.01, 716.01, 716.01, 716.01 /)
+ co2mlo(2081,:) = (/ 722.81, 722.81, 722.81, 722.81, 722.81, 722.81, 722.81, 722.81, 722.81, 722.81, 722.81, 722.81 /)
+ co2mlo(2082,:) = (/ 729.68, 729.68, 729.68, 729.68, 729.68, 729.68, 729.68, 729.68, 729.68, 729.68, 729.68, 729.68 /)
+ co2mlo(2083,:) = (/ 736.63, 736.63, 736.63, 736.63, 736.63, 736.63, 736.63, 736.63, 736.63, 736.63, 736.63, 736.63 /)
+ co2mlo(2084,:) = (/ 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66 /)
+ co2mlo(2085,:) = (/ 750.76, 750.76, 750.76, 750.76, 750.76, 750.76, 750.76, 750.76, 750.76, 750.76, 750.76, 750.76 /)
+ co2mlo(2086,:) = (/ 757.95, 757.95, 757.95, 757.95, 757.95, 757.95, 757.95, 757.95, 757.95, 757.95, 757.95, 757.95 /)
+ co2mlo(2087,:) = (/ 765.22, 765.22, 765.22, 765.22, 765.22, 765.22, 765.22, 765.22, 765.22, 765.22, 765.22, 765.22 /)
+ co2mlo(2088,:) = (/ 772.56, 772.56, 772.56, 772.56, 772.56, 772.56, 772.56, 772.56, 772.56, 772.56, 772.56, 772.56 /)
+ co2mlo(2089,:) = (/ 779.98, 779.98, 779.98, 779.98, 779.98, 779.98, 779.98, 779.98, 779.98, 779.98, 779.98, 779.98 /)
+ co2mlo(2090,:) = (/ 787.49, 787.49, 787.49, 787.49, 787.49, 787.49, 787.49, 787.49, 787.49, 787.49, 787.49, 787.49 /)
+ co2mlo(2091,:) = (/ 795.07, 795.07, 795.07, 795.07, 795.07, 795.07, 795.07, 795.07, 795.07, 795.07, 795.07, 795.07 /)
+ co2mlo(2092,:) = (/ 802.74, 802.74, 802.74, 802.74, 802.74, 802.74, 802.74, 802.74, 802.74, 802.74, 802.74, 802.74 /)
+ co2mlo(2093,:) = (/ 810.49, 810.49, 810.49, 810.49, 810.49, 810.49, 810.49, 810.49, 810.49, 810.49, 810.49, 810.49 /)
+ co2mlo(2094,:) = (/ 818.33, 818.33, 818.33, 818.33, 818.33, 818.33, 818.33, 818.33, 818.33, 818.33, 818.33, 818.33 /)
+ co2mlo(2095,:) = (/ 826.25, 826.25, 826.25, 826.25, 826.25, 826.25, 826.25, 826.25, 826.25, 826.25, 826.25, 826.25 /)
+ co2mlo(2096,:) = (/ 834.27, 834.27, 834.27, 834.27, 834.27, 834.27, 834.27, 834.27, 834.27, 834.27, 834.27, 834.27 /)
+ co2mlo(2097,:) = (/ 842.37, 842.37, 842.37, 842.37, 842.37, 842.37, 842.37, 842.37, 842.37, 842.37, 842.37, 842.37 /)
+ co2mlo(2098,:) = (/ 850.55, 850.55, 850.55, 850.55, 850.55, 850.55, 850.55, 850.55, 850.55, 850.55, 850.55, 850.55 /)
+ co2mlo(2099,:) = (/ 858.83, 858.83, 858.83, 858.83, 858.83, 858.83, 858.83, 858.83, 858.83, 858.83, 858.83, 858.83 /)
+ co2mlo(2100,:) = (/ 867.19, 867.19, 867.19, 867.19, 867.19, 867.19, 867.19, 867.19, 867.19, 867.19, 867.19, 867.19 /)
+ !added by Zhongwang Wei @ SYSU 2022.12.12
+ CASE ('585')
+ !co2mlo(2015,:) = (/ 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95, 399.95 /)
+ !co2mlo(2016,:) = (/ 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12, 403.12 /)
+ !co2mlo(2017,:) = (/ 405.79, 405.79, 405.79, 405.79, 405.79, 405.79, 405.79, 405.79, 405.79, 405.79, 405.79, 405.79 /)
+ !co2mlo(2018,:) = (/ 408.76, 408.76, 408.76, 408.76, 408.76, 408.76, 408.76, 408.76, 408.76, 408.76, 408.76, 408.76 /)
+ !co2mlo(2019,:) = (/ 411.79, 411.79, 411.79, 411.79, 411.79, 411.79, 411.79, 411.79, 411.79, 411.79, 411.79, 411.79 /)
+ !co2mlo(2020,:) = (/ 414.89, 414.89, 414.89, 414.89, 414.89, 414.89, 414.89, 414.89, 414.89, 414.89, 414.89, 414.89 /)
+ !co2mlo(2021,:) = (/ 418.06, 418.06, 418.06, 418.06, 418.06, 418.06, 418.06, 418.06, 418.06, 418.06, 418.06, 418.06 /)
+ !co2mlo(2022,:) = (/ 421.33, 421.33, 421.33, 421.33, 421.33, 421.33, 421.33, 421.33, 421.33, 421.33, 421.33, 421.33 /)
+ co2mlo(2023,:) = (/ 424.72, 424.72, 424.72, 424.72, 424.72, 424.72, 424.72, 424.72, 424.72, 424.72, 424.72, 424.72 /)
+ co2mlo(2024,:) = (/ 428.22, 428.22, 428.22, 428.22, 428.22, 428.22, 428.22, 428.22, 428.22, 428.22, 428.22, 428.22 /)
+ co2mlo(2025,:) = (/ 431.83, 431.83, 431.83, 431.83, 431.83, 431.83, 431.83, 431.83, 431.83, 431.83, 431.83, 431.83 /)
+ co2mlo(2026,:) = (/ 435.55, 435.55, 435.55, 435.55, 435.55, 435.55, 435.55, 435.55, 435.55, 435.55, 435.55, 435.55 /)
+ co2mlo(2027,:) = (/ 439.38, 439.38, 439.38, 439.38, 439.38, 439.38, 439.38, 439.38, 439.38, 439.38, 439.38, 439.38 /)
+ co2mlo(2028,:) = (/ 443.31, 443.31, 443.31, 443.31, 443.31, 443.31, 443.31, 443.31, 443.31, 443.31, 443.31, 443.31 /)
+ co2mlo(2029,:) = (/ 447.36, 447.36, 447.36, 447.36, 447.36, 447.36, 447.36, 447.36, 447.36, 447.36, 447.36, 447.36 /)
+ co2mlo(2030,:) = (/ 451.51, 451.51, 451.51, 451.51, 451.51, 451.51, 451.51, 451.51, 451.51, 451.51, 451.51, 451.51 /)
+ co2mlo(2031,:) = (/ 455.78, 455.78, 455.78, 455.78, 455.78, 455.78, 455.78, 455.78, 455.78, 455.78, 455.78, 455.78 /)
+ co2mlo(2032,:) = (/ 460.16, 460.16, 460.16, 460.16, 460.16, 460.16, 460.16, 460.16, 460.16, 460.16, 460.16, 460.16 /)
+ co2mlo(2033,:) = (/ 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68, 464.68 /)
+ co2mlo(2034,:) = (/ 469.33, 469.33, 469.33, 469.33, 469.33, 469.33, 469.33, 469.33, 469.33, 469.33, 469.33, 469.33 /)
+ co2mlo(2035,:) = (/ 474.11, 474.11, 474.11, 474.11, 474.11, 474.11, 474.11, 474.11, 474.11, 474.11, 474.11, 474.11 /)
+ co2mlo(2036,:) = (/ 479.02, 479.02, 479.02, 479.02, 479.02, 479.02, 479.02, 479.02, 479.02, 479.02, 479.02, 479.02 /)
+ co2mlo(2037,:) = (/ 484.07, 484.07, 484.07, 484.07, 484.07, 484.07, 484.07, 484.07, 484.07, 484.07, 484.07, 484.07 /)
+ co2mlo(2038,:) = (/ 489.25, 489.25, 489.25, 489.25, 489.25, 489.25, 489.25, 489.25, 489.25, 489.25, 489.25, 489.25 /)
+ co2mlo(2039,:) = (/ 494.57, 494.57, 494.57, 494.57, 494.57, 494.57, 494.57, 494.57, 494.57, 494.57, 494.57, 494.57 /)
+ co2mlo(2040,:) = (/ 500.02, 500.02, 500.02, 500.02, 500.02, 500.02, 500.02, 500.02, 500.02, 500.02, 500.02, 500.02 /)
+ co2mlo(2041,:) = (/ 505.61, 505.61, 505.61, 505.61, 505.61, 505.61, 505.61, 505.61, 505.61, 505.61, 505.61, 505.61 /)
+ co2mlo(2042,:) = (/ 511.34, 511.34, 511.34, 511.34, 511.34, 511.34, 511.34, 511.34, 511.34, 511.34, 511.34, 511.34 /)
+ co2mlo(2043,:) = (/ 517.23, 517.23, 517.23, 517.23, 517.23, 517.23, 517.23, 517.23, 517.23, 517.23, 517.23, 517.23 /)
+ co2mlo(2044,:) = (/ 523.27, 523.27, 523.27, 523.27, 523.27, 523.27, 523.27, 523.27, 523.27, 523.27, 523.27, 523.27 /)
+ co2mlo(2045,:) = (/ 529.46, 529.46, 529.46, 529.46, 529.46, 529.46, 529.46, 529.46, 529.46, 529.46, 529.46, 529.46 /)
+ co2mlo(2046,:) = (/ 535.81, 535.81, 535.81, 535.81, 535.81, 535.81, 535.81, 535.81, 535.81, 535.81, 535.81, 535.81 /)
+ co2mlo(2047,:) = (/ 542.31, 542.31, 542.31, 542.31, 542.31, 542.31, 542.31, 542.31, 542.31, 542.31, 542.31, 542.31 /)
+ co2mlo(2048,:) = (/ 548.98, 548.98, 548.98, 548.98, 548.98, 548.98, 548.98, 548.98, 548.98, 548.98, 548.98, 548.98 /)
+ co2mlo(2049,:) = (/ 555.80, 555.80, 555.80, 555.80, 555.80, 555.80, 555.80, 555.80, 555.80, 555.80, 555.80, 555.80 /)
+ co2mlo(2050,:) = (/ 562.78, 562.78, 562.78, 562.78, 562.78, 562.78, 562.78, 562.78, 562.78, 562.78, 562.78, 562.78 /)
+ co2mlo(2051,:) = (/ 569.93, 569.93, 569.93, 569.93, 569.93, 569.93, 569.93, 569.93, 569.93, 569.93, 569.93, 569.93 /)
+ co2mlo(2052,:) = (/ 577.26, 577.26, 577.26, 577.26, 577.26, 577.26, 577.26, 577.26, 577.26, 577.26, 577.26, 577.26 /)
+ co2mlo(2053,:) = (/ 584.78, 584.78, 584.78, 584.78, 584.78, 584.78, 584.78, 584.78, 584.78, 584.78, 584.78, 584.78 /)
+ co2mlo(2054,:) = (/ 592.51, 592.51, 592.51, 592.51, 592.51, 592.51, 592.51, 592.51, 592.51, 592.51, 592.51, 592.51 /)
+ co2mlo(2055,:) = (/ 600.43, 600.43, 600.43, 600.43, 600.43, 600.43, 600.43, 600.43, 600.43, 600.43, 600.43, 600.43 /)
+ co2mlo(2056,:) = (/ 608.55, 608.55, 608.55, 608.55, 608.55, 608.55, 608.55, 608.55, 608.55, 608.55, 608.55, 608.55 /)
+ co2mlo(2057,:) = (/ 616.87, 616.87, 616.87, 616.87, 616.87, 616.87, 616.87, 616.87, 616.87, 616.87, 616.87, 616.87 /)
+ co2mlo(2058,:) = (/ 625.39, 625.39, 625.39, 625.39, 625.39, 625.39, 625.39, 625.39, 625.39, 625.39, 625.39, 625.39 /)
+ co2mlo(2059,:) = (/ 634.11, 634.11, 634.11, 634.11, 634.11, 634.11, 634.11, 634.11, 634.11, 634.11, 634.11, 634.11 /)
+ co2mlo(2060,:) = (/ 643.04, 643.04, 643.04, 643.04, 643.04, 643.04, 643.04, 643.04, 643.04, 643.04, 643.04, 643.04 /)
+ co2mlo(2061,:) = (/ 652.17, 652.17, 652.17, 652.17, 652.17, 652.17, 652.17, 652.17, 652.17, 652.17, 652.17, 652.17 /)
+ co2mlo(2062,:) = (/ 661.51, 661.51, 661.51, 661.51, 661.51, 661.51, 661.51, 661.51, 661.51, 661.51, 661.51, 661.51 /)
+ co2mlo(2063,:) = (/ 671.04, 671.04, 671.04, 671.04, 671.04, 671.04, 671.04, 671.04, 671.04, 671.04, 671.04, 671.04 /)
+ co2mlo(2064,:) = (/ 680.79, 680.79, 680.79, 680.79, 680.79, 680.79, 680.79, 680.79, 680.79, 680.79, 680.79, 680.79 /)
+ co2mlo(2065,:) = (/ 690.74, 690.74, 690.74, 690.74, 690.74, 690.74, 690.74, 690.74, 690.74, 690.74, 690.74, 690.74 /)
+ co2mlo(2066,:) = (/ 700.90, 700.90, 700.90, 700.90, 700.90, 700.90, 700.90, 700.90, 700.90, 700.90, 700.90, 700.90 /)
+ co2mlo(2067,:) = (/ 711.27, 711.27, 711.27, 711.27, 711.27, 711.27, 711.27, 711.27, 711.27, 711.27, 711.27, 711.27 /)
+ co2mlo(2068,:) = (/ 721.85, 721.85, 721.85, 721.85, 721.85, 721.85, 721.85, 721.85, 721.85, 721.85, 721.85, 721.85 /)
+ co2mlo(2069,:) = (/ 732.65, 732.65, 732.65, 732.65, 732.65, 732.65, 732.65, 732.65, 732.65, 732.65, 732.65, 732.65 /)
+ co2mlo(2070,:) = (/ 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66, 743.66 /)
+ co2mlo(2071,:) = (/ 754.89, 754.89, 754.89, 754.89, 754.89, 754.89, 754.89, 754.89, 754.89, 754.89, 754.89, 754.89 /)
+ co2mlo(2072,:) = (/ 766.32, 766.32, 766.32, 766.32, 766.32, 766.32, 766.32, 766.32, 766.32, 766.32, 766.32, 766.32 /)
+ co2mlo(2073,:) = (/ 777.93, 777.93, 777.93, 777.93, 777.93, 777.93, 777.93, 777.93, 777.93, 777.93, 777.93, 777.93 /)
+ co2mlo(2074,:) = (/ 789.72, 789.72, 789.72, 789.72, 789.72, 789.72, 789.72, 789.72, 789.72, 789.72, 789.72, 789.72 /)
+ co2mlo(2075,:) = (/ 801.69, 801.69, 801.69, 801.69, 801.69, 801.69, 801.69, 801.69, 801.69, 801.69, 801.69, 801.69 /)
+ co2mlo(2076,:) = (/ 813.85, 813.85, 813.85, 813.85, 813.85, 813.85, 813.85, 813.85, 813.85, 813.85, 813.85, 813.85 /)
+ co2mlo(2077,:) = (/ 826.19, 826.19, 826.19, 826.19, 826.19, 826.19, 826.19, 826.19, 826.19, 826.19, 826.19, 826.19 /)
+ co2mlo(2078,:) = (/ 838.73, 838.73, 838.73, 838.73, 838.73, 838.73, 838.73, 838.73, 838.73, 838.73, 838.73, 838.73 /)
+ co2mlo(2079,:) = (/ 851.45, 851.45, 851.45, 851.45, 851.45, 851.45, 851.45, 851.45, 851.45, 851.45, 851.45, 851.45 /)
+ co2mlo(2080,:) = (/ 864.37, 864.37, 864.37, 864.37, 864.37, 864.37, 864.37, 864.37, 864.37, 864.37, 864.37, 864.37 /)
+ co2mlo(2081,:) = (/ 877.48, 877.48, 877.48, 877.48, 877.48, 877.48, 877.48, 877.48, 877.48, 877.48, 877.48, 877.48 /)
+ co2mlo(2082,:) = (/ 890.71, 890.71, 890.71, 890.71, 890.71, 890.71, 890.71, 890.71, 890.71, 890.71, 890.71, 890.71 /)
+ co2mlo(2083,:) = (/ 903.98, 903.98, 903.98, 903.98, 903.98, 903.98, 903.98, 903.98, 903.98, 903.98, 903.98, 903.98 /)
+ co2mlo(2084,:) = (/ 917.30, 917.30, 917.30, 917.30, 917.30, 917.30, 917.30, 917.30, 917.30, 917.30, 917.30, 917.30 /)
+ co2mlo(2085,:) = (/ 930.67, 930.67, 930.67, 930.67, 930.67, 930.67, 930.67, 930.67, 930.67, 930.67, 930.67, 930.67 /)
+ co2mlo(2086,:) = (/ 944.09, 944.09, 944.09, 944.09, 944.09, 944.09, 944.09, 944.09, 944.09, 944.09, 944.09, 944.09 /)
+ co2mlo(2087,:) = (/ 957.57, 957.57, 957.57, 957.57, 957.57, 957.57, 957.57, 957.57, 957.57, 957.57, 957.57, 957.57 /)
+ co2mlo(2088,:) = (/ 971.10, 971.10, 971.10, 971.10, 971.10, 971.10, 971.10, 971.10, 971.10, 971.10, 971.10, 971.10 /)
+ co2mlo(2089,:) = (/ 984.68, 984.68, 984.68, 984.68, 984.68, 984.68, 984.68, 984.68, 984.68, 984.68, 984.68, 984.68 /)
+ co2mlo(2090,:) = (/ 998.32, 998.32, 998.32, 998.32, 998.32, 998.32, 998.32, 998.32, 998.32, 998.32, 998.32, 998.32 /)
+ co2mlo(2091,:) = (/ 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02, 1012.02 /)
+ co2mlo(2092,:) = (/ 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74, 1025.74 /)
+ co2mlo(2093,:) = (/ 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45, 1039.45 /)
+ co2mlo(2094,:) = (/ 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15, 1053.15 /)
+ co2mlo(2095,:) = (/ 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85, 1066.85 /)
+ co2mlo(2096,:) = (/ 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53, 1080.53 /)
+ co2mlo(2097,:) = (/ 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21, 1094.21 /)
+ co2mlo(2098,:) = (/ 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89, 1107.89 /)
+ co2mlo(2099,:) = (/ 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55, 1121.55 /)
+ co2mlo(2100,:) = (/ 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21, 1135.21 /)
+ END select
+
+ END SUBROUTINE init_monthly_co2_mlo
+
+ real(r8) FUNCTION get_monthly_co2_mlo (year, month)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: year
+ integer, intent(in) :: month
+
+ IF (yeareyear .or. year==eyear.and.month>4) THEN
+ print *, "Warning: Requested CO2 data beyond the latest record!"
+ print *, "Set to the latest one..."
+ get_monthly_co2_mlo = co2mlo(eyear, emonth)
+ RETURN
+ ENDIF
+
+ get_monthly_co2_mlo = co2mlo(year, month)
+ !print *, "Set CO2 value [ppm,year,month]:",get_monthly_co2_mlo,year,month
+ RETURN
+
+ END FUNCTION get_monthly_co2_mlo
+
+END MODULE MOD_MonthlyinSituCO2MaunaLoa
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_NdepData.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NdepData.F90
new file mode 100644
index 0000000000..4fcb84bd62
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NdepData.F90
@@ -0,0 +1,230 @@
+#include
+
+#ifdef BGC
+MODULE MOD_NdepData
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This module read in ndep data.
+!
+! !ORIGINAL:
+! Lu Xingjie and Zhang Shupeng, 2023, prepare the original version of
+! the ndep data module.
+!
+! !REVISIONS:
+! 08/2023, Shang Fang: add year and month input for reading Nitrogen deposition
+!-----------------------------------------------------------------------
+
+ USE MOD_Grid
+ USE MOD_SpatialMapping
+ USE MOD_BGC_Vars_TimeVariables, only: ndep
+ USE MOD_BGC_Vars_1DFluxes, only: ndep_to_sminn
+ IMPLICIT NONE
+
+ character(len=256) :: file_ndep
+
+ type(grid_type) :: grid_ndep
+ type(spatial_mapping_type) :: mg2p_ndep
+
+CONTAINS
+
+ SUBROUTINE init_ndep_data_annually (YY)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! open ndep netcdf file from DEF_dir_runtime, read latitude and longitude info.
+! Initialize ndep data read in.
+!-----------------------------------------------------------------------
+
+ USE MOD_TimeManager
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ integer, intent(in) :: YY
+
+ ! Local Variables
+ real(r8), allocatable :: lat(:), lon(:)
+
+ file_ndep = trim(DEF_dir_runtime) // &
+ '/ndep/fndep_colm_hist_simyr1849-2006_1.9x2.5_c100428.nc'
+
+ CALL ncio_read_bcast_serial (file_ndep, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_ndep, 'lon', lon)
+
+ CALL grid_ndep%define_by_center (lat, lon)
+
+ CALL mg2p_ndep%build_arealweighted (grid_ndep, landpatch)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ CALL update_ndep_data_annually (YY, iswrite = .true.)
+
+ END SUBROUTINE init_ndep_data_annually
+
+ SUBROUTINE init_ndep_data_monthly (YY,MM)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! open ndep netcdf file from DEF_dir_runtime, read latitude and
+! longitude info. Initialize ndep data read in.
+!-----------------------------------------------------------------------
+
+ USE MOD_TimeManager
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ integer, intent(in) :: YY,MM
+
+ ! Local Variables
+ real(r8), allocatable :: lat(:), lon(:)
+
+ file_ndep = trim(DEF_dir_runtime) // '/ndep/fndep_colm_monthly.nc'
+
+ CALL ncio_read_bcast_serial (file_ndep, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_ndep, 'lon', lon)
+
+ CALL grid_ndep%define_by_center (lat, lon)
+
+ CALL mg2p_ndep%build_arealweighted (grid_ndep, landpatch)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ CALL update_ndep_data_monthly (YY, MM ,iswrite = .true.)
+
+ END SUBROUTINE init_ndep_data_monthly
+
+ SUBROUTINE update_ndep_data_annually (YY, iswrite)
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Read in the Nitrogen deposition data from CLM5.
+!
+! !REFERENCES:
+! Galloway, J.N., et al. 2004. Nitrogen cycles: past, present, and
+! future. Biogeochem. 70:153-226.
+!
+! !ORIGINAL:
+! Created by Xingjie Lu and Shupeng Zhang, 2022
+!-----------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only: DEF_USE_PN
+ USE MOD_DataType
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ USE MOD_Vars_TimeInvariants
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: YY
+ logical, intent(in) :: iswrite
+
+ ! Local Variables
+ type(block_data_real8_2d) :: f_xy_ndep
+ integer :: itime, npatch, m
+
+ itime = max(min(YY,2006),1849) - 1848
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_ndep, f_xy_ndep)
+ CALL ncio_read_block_time (file_ndep, 'NDEP_year', grid_ndep, itime, f_xy_ndep)
+ ENDIF
+
+ CALL mg2p_ndep%grid2pset (f_xy_ndep, ndep)
+
+ IF (p_is_compute .and. iswrite) THEN
+ IF (numpatch > 0) THEN
+ DO npatch = 1, numpatch
+ m = patchclass(npatch)
+ IF(m == 0)THEN
+ ndep_to_sminn(npatch) = 0.
+ ELSE
+ IF(DEF_USE_PN)THEN
+ ndep_to_sminn(npatch) = ndep(npatch) / 3600. / 365. / 24. * 5
+ ELSE
+ ndep_to_sminn(npatch) = ndep(npatch) / 3600. / 365. / 24.
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+#ifdef RangeCheck
+ CALL check_vector_data ('ndep', ndep)
+#endif
+
+ END SUBROUTINE update_ndep_data_annually
+
+ SUBROUTINE update_ndep_data_monthly (YY, MM, iswrite)
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Read in the Nitrogen deposition data from CLM5.
+!
+! !REFERENCES:
+! Galloway, J.N., et al. 2004. Nitrogen cycles: past, present, and
+! future. Biogeochem. 70:153-226.
+!
+! !ORIGINAL:
+! Created by Xingjie Lu and Shupeng Zhang, 2022
+!
+!-----------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only: DEF_USE_PN
+ USE MOD_DataType
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ USE MOD_Vars_TimeInvariants
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: YY,MM
+ logical, intent(in) :: iswrite
+
+ ! Local Variables
+ type(block_data_real8_2d) :: f_xy_ndep
+ integer :: itime, npatch, m
+
+ itime = (max(min(YY,2006),1849) - 1849)*12 + MM
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_ndep, f_xy_ndep)
+ CALL ncio_read_block_time (file_ndep, 'NDEP_month', grid_ndep, itime, f_xy_ndep)
+ ENDIF
+
+ CALL mg2p_ndep%grid2pset (f_xy_ndep, ndep)
+
+ IF (p_is_compute .and. iswrite) THEN
+ IF (numpatch > 0) THEN
+ DO npatch = 1, numpatch
+ m = patchclass(npatch)
+ IF(m == 0)THEN
+ ndep_to_sminn(npatch) = 0.
+ ELSE
+ IF(DEF_USE_PN)THEN
+ ndep_to_sminn(npatch) = ndep(npatch) / 3600. / 365. / 24. * 5
+ ELSE
+ ndep_to_sminn(npatch) = ndep(npatch) / 3600. / 365. / 24.
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+#ifdef RangeCheck
+ CALL check_vector_data ('ndep', ndep)
+#endif
+
+ END SUBROUTINE update_ndep_data_monthly
+
+END MODULE MOD_NdepData
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_NetSolar.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NetSolar.F90
new file mode 100644
index 0000000000..68a54de178
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NetSolar.F90
@@ -0,0 +1,323 @@
+#include
+
+MODULE MOD_NetSolar
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: netsolar
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE netsolar (ipatch,idate,deltim,dlon,patchtype,&
+ forc_sols,forc_soll,forc_solsd,forc_solld,&
+ alb,ssun,ssha,lai,sai,rho,tau,ssoi,ssno,ssno_lyr,fsno,&
+ parsun,parsha,sabvsun,sabvsha,sabg,sabg_soil,sabg_snow,sabg_snow_lyr,&
+ sr,solvd,solvi,solnd,solni,srvd,srvi,srnd,srni,&
+ solvdln,solviln,solndln,solniln,srvdln,srviln,srndln,srniln)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Net solar absorbed by surface
+!
+! Original author: Yongjiu Dai, 09/15/1999; 09/11/2001
+!
+! !REVISIONS:
+! 05/2014, Hua Yuan: added for solar radiation output [vars: so*, sr*]
+!
+! 08/2014, Hua Yuan: added for local noon calculation
+!
+! 08/2020, Hua Yuan: added for PFT and PC calculation
+!
+! 12/2022, Hua Yuan: calculated snow layer absorption by SNICAR model
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Namelist, only: DEF_USE_SNICAR
+ USE MOD_TimeManager, only: isgreenwich
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_Vars_1DPFTFluxes
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ipatch !patch index
+ integer, intent(in) :: idate(3) !model time
+ integer, intent(in) :: patchtype !land patch type (99-sea)
+
+ real(r8), intent(in) :: dlon !longitude in radians
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+
+ real(r8), intent(in) :: &
+ forc_sols, &! atm vis direct beam solar rad onto srf [W/m2]
+ forc_soll, &! atm nir direct beam solar rad onto srf [W/m2]
+ forc_solsd, &! atm vis diffuse solar rad onto srf [W/m2]
+ forc_solld ! atm nir diffuse solar rad onto srf [W/m2]
+
+ real(r8), dimension(1:2,1:2), intent(in) :: &
+ alb ! averaged albedo [-]
+
+ real(r8), dimension(1:2,1:2), intent(inout) :: &
+ ssun, &! sunlit canopy absorption for solar radiation
+ ssha, &! shaded canopy absorption for solar radiation
+ ssoi, &! ground soil absorption [-]
+ ssno ! ground snow absorption [-]
+
+ real(r8), dimension(1:2,1:2,maxsnl+1:1), intent(inout) :: &
+ ssno_lyr ! snow layer absorption
+
+ real(r8), intent(in) :: &
+ lai, &! leaf area index
+ sai, &! stem area index
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2) ! leaf transmittance (iw=iband, il=life and dead)
+
+ real(r8), intent(in) :: &
+ fsno ! snow fractional cover
+
+ real(r8), intent(out) :: &
+ parsun, &! PAR absorbed by sunlit vegetation [W/m2]
+ parsha, &! PAR absorbed by shaded vegetation [W/m2]
+ sabvsun, &! solar absorbed by sunlit vegetation [W/m2]
+ sabvsha, &! solar absorbed by shaded vegetation [W/m2]
+ sabg, &! solar absorbed by ground [W/m2]
+! 03/06/2020, yuan:
+ sabg_soil, &! solar absorbed by ground soil [W/m2]
+ sabg_snow, &! solar absorbed by ground snow [W/m2]
+ sr, &! total reflected solar radiation (W/m2)
+ solvd, &! incident direct beam vis solar radiation (W/m2)
+ solvi, &! incident diffuse beam vis solar radiation (W/m2)
+ solnd, &! incident direct beam nir solar radiation (W/m2)
+ solni, &! incident diffuse beam nir solar radiation (W/m2)
+ srvd, &! reflected direct beam vis solar radiation (W/m2)
+ srvi, &! reflected diffuse beam vis solar radiation (W/m2)
+ srnd, &! reflected direct beam nir solar radiation (W/m2)
+ srni, &! reflected diffuse beam nir solar radiation (W/m2)
+ solvdln, &! incident direct beam vis solar radiation at local noon(W/m2)
+ solviln, &! incident diffuse beam vis solar radiation at local noon(W/m2)
+ solndln, &! incident direct beam nir solar radiation at local noon(W/m2)
+ solniln, &! incident diffuse beam nir solar radiation at local noon(W/m2)
+ srvdln, &! reflected direct beam vis solar radiation at local noon(W/m2)
+ srviln, &! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ srndln, &! reflected direct beam nir solar radiation at local noon(W/m2)
+ srniln ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+
+ real(r8), intent(out) :: &
+ sabg_snow_lyr(maxsnl+1:1) ! solar absorbed by snow layers [W/m2]
+
+!-------------------------- Local Variables ----------------------------
+ integer :: local_secs
+ real(r8) :: radpsec, sabvg, sabg_noadj
+
+ integer ps, pe, p
+
+!-----------------------------------------------------------------------
+
+ sabvsun = 0.
+ sabvsha = 0.
+ parsun = 0.
+ parsha = 0.
+
+ IF (lai+sai <= 1.e-6) THEN
+ ssun(:,:) = 0.
+ ssha(:,:) = 0.
+ ENDIF
+
+ sabg = 0.
+ sabg_soil = 0.
+ sabg_snow = 0.
+ sabg_snow_lyr(:) = 0.
+
+ IF (patchtype == 0) THEN
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ sabvsun_p(ps:pe) = 0.
+ sabvsha_p(ps:pe) = 0.
+ parsun_p (ps:pe) = 0.
+ parsha_p (ps:pe) = 0.
+
+ DO p = ps, pe
+ IF (lai_p(p)+sai_p(p) <= 1.e-6) THEN
+ ssun_p(:,:,p) = 0.
+ ssha_p(:,:,p) = 0.
+ ENDIF
+ ENDDO
+
+ ssun(1,1) = sum( ssun_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(1,2) = sum( ssun_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,1) = sum( ssun_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,2) = sum( ssun_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssha(1,1) = sum( ssha_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(1,2) = sum( ssha_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,1) = sum( ssha_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,2) = sum( ssha_p(2,2,ps:pe)*pftfrac(ps:pe) )
+#endif
+ ENDIF
+
+ IF (forc_sols+forc_soll+forc_solsd+forc_solld > 0.) THEN
+ IF (patchtype < 4) THEN !non lake and ocean
+ ! Radiative fluxes onto surface
+ parsun = forc_sols*ssun(1,1) + forc_solsd*ssun(1,2)
+ parsha = forc_sols*ssha(1,1) + forc_solsd*ssha(1,2)
+ sabvsun = forc_sols*ssun(1,1) + forc_solsd*ssun(1,2) &
+ + forc_soll*ssun(2,1) + forc_solld*ssun(2,2)
+ sabvsha = forc_sols*ssha(1,1) + forc_solsd*ssha(1,2) &
+ + forc_soll*ssha(2,1) + forc_solld*ssha(2,2)
+ sabvg = forc_sols *(1.-alb(1,1)) + forc_solsd*(1.-alb(1,2)) &
+ + forc_soll *(1.-alb(2,1)) + forc_solld*(1.-alb(2,2))
+ sabg = sabvg - sabvsun - sabvsha
+
+ IF (patchtype == 0) THEN
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+ parsun_p (ps:pe) = forc_sols*ssun_p(1,1,ps:pe) + forc_solsd*ssun_p(1,2,ps:pe)
+ parsha_p (ps:pe) = forc_sols*ssha_p(1,1,ps:pe) + forc_solsd*ssha_p(1,2,ps:pe)
+ sabvsun_p(ps:pe) = forc_sols*ssun_p(1,1,ps:pe) + forc_solsd*ssun_p(1,2,ps:pe) &
+ + forc_soll*ssun_p(2,1,ps:pe) + forc_solld*ssun_p(2,2,ps:pe)
+ sabvsha_p(ps:pe) = forc_sols*ssha_p(1,1,ps:pe) + forc_solsd*ssha_p(1,2,ps:pe) &
+ + forc_soll*ssha_p(2,1,ps:pe) + forc_solld*ssha_p(2,2,ps:pe)
+#endif
+ ENDIF
+
+ ELSE !lake and ocean
+ sabvg = forc_sols *(1.-alb(1,1)) + forc_soll *(1.-alb(2,1)) &
+ + forc_solsd*(1.-alb(1,2)) + forc_solld*(1.-alb(2,2))
+ sabg = sabvg
+ ENDIF
+
+ ! calculate soil and snow solar absorption
+ sabg_soil = forc_sols*ssoi(1,1) + forc_solsd*ssoi(1,2) &
+ + forc_soll*ssoi(2,1) + forc_solld*ssoi(2,2)
+ sabg_snow = forc_sols*ssno(1,1) + forc_solsd*ssno(1,2) &
+ + forc_soll*ssno(2,1) + forc_solld*ssno(2,2)
+
+ sabg_soil = sabg_soil * (1.-fsno)
+ sabg_snow = sabg_snow * fsno
+
+ ! balance check and adjustment for soil and snow absorption
+ ! this could happen when there is adjustment to ssun,ssha
+ IF (abs(sabg_soil+sabg_snow-sabg)>1.e-6) THEN
+ IF (.not. (idate(2)==1 .and. idate(3)==int(deltim))) THEN
+ print *, "MOD_NetSolar.F90: NOTE imbalance in spliting soil and snow surface!", &
+ sabg_soil+sabg_snow-sabg
+ print *, "Patchtype = ", patchtype
+ print *, "sabg:", sabg, "sabg_soil:", sabg_soil, "sabg_snow", sabg_snow
+ print *, "sabg_soil+sabg_snow:", sabg_soil+sabg_snow, "fsno:", fsno
+ ENDIF
+
+ sabg_noadj = sabg_soil + sabg_snow
+
+ IF (sabg_noadj > 0.) THEN
+ sabg_soil = sabg_soil * sabg/sabg_noadj
+ sabg_snow = sabg_snow * sabg/sabg_noadj
+ ssoi(:,:) = ssoi(:,:) * sabg/sabg_noadj
+ ssno(:,:) = ssno(:,:) * sabg/sabg_noadj
+ ENDIF
+ ENDIF
+
+ ! snow layer absorption calculation and adjustment for SNICAR model
+ IF (DEF_USE_SNICAR) THEN
+ ! adjust snow layer absorption due to multiple reflection between ground and canopy
+ IF(sum(ssno_lyr(1,1,:))>0.) THEN
+ ssno_lyr(1,1,:) = ssno(1,1) * ssno_lyr(1,1,:)/sum(ssno_lyr(1,1,:))
+ ELSE
+ ssno_lyr(1,1,1) = ssno(1,1)
+ ENDIF
+
+ IF(sum(ssno_lyr(1,2,:))>0.) THEN
+ ssno_lyr(1,2,:) = ssno(1,2) * ssno_lyr(1,2,:)/sum(ssno_lyr(1,2,:))
+ ELSE
+ ssno_lyr(1,2,1) = ssno(1,2)
+ ENDIF
+
+ IF(sum(ssno_lyr(2,1,:))>0.) THEN
+ ssno_lyr(2,1,:) = ssno(2,1) * ssno_lyr(2,1,:)/sum(ssno_lyr(2,1,:))
+ ELSE
+ ssno_lyr(2,1,1) = ssno(2,1)
+ ENDIF
+
+ IF(sum(ssno_lyr(2,2,:))>0.) THEN
+ ssno_lyr(2,2,:) = ssno(2,2) * ssno_lyr(2,2,:)/sum(ssno_lyr(2,2,:))
+ ELSE
+ ssno_lyr(2,2,1) = ssno(2,2)
+ ENDIF
+
+ ! snow layer absorption
+ sabg_snow_lyr(:) = forc_sols*ssno_lyr(1,1,:) + forc_solsd*ssno_lyr(1,2,:) &
+ + forc_soll*ssno_lyr(2,1,:) + forc_solld*ssno_lyr(2,2,:)
+
+ ! convert to the whole area multiplied by snow fractional cover
+ sabg_snow_lyr(:) = sabg_snow_lyr(:)*fsno
+
+ ! attribute the first layer absorption to soil absorption
+ sabg_soil = sabg_soil + sabg_snow_lyr(1)
+ sabg_snow = sabg_snow - sabg_snow_lyr(1)
+
+ ! make the soil absorption consistent
+ sabg_snow_lyr(1) = sabg_soil
+ ENDIF
+
+ ENDIF
+
+ solvd = forc_sols
+ solvi = forc_solsd
+ solnd = forc_soll
+ solni = forc_solld
+ srvd = solvd*alb(1,1)
+ srvi = solvi*alb(1,2)
+ srnd = solnd*alb(2,1)
+ srni = solni*alb(2,2)
+ sr = srvd + srvi + srnd + srni
+
+ ! calculate the local secs
+ radpsec = pi/12./3600.
+ IF ( isgreenwich ) THEN
+ local_secs = idate(3) + nint((dlon/radpsec)/deltim)*deltim
+ local_secs = mod(local_secs,86400)
+ ELSE
+ local_secs = idate(3)
+ ENDIF
+
+ IF (local_secs == 86400/2) THEN
+ solvdln = forc_sols
+ solviln = forc_solsd
+ solndln = forc_soll
+ solniln = forc_solld
+ srvdln = solvdln*alb(1,1)
+ srviln = solviln*alb(1,2)
+ srndln = solndln*alb(2,1)
+ srniln = solniln*alb(2,2)
+ ELSE
+ solvdln = spval
+ solviln = spval
+ solndln = spval
+ solniln = spval
+ srvdln = spval
+ srviln = spval
+ srndln = spval
+ srniln = spval
+ ENDIF
+
+ END SUBROUTINE netsolar
+
+END MODULE MOD_NetSolar
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_NetSolar_Hyper.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NetSolar_Hyper.F90
new file mode 100644
index 0000000000..7cf6d7d780
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NetSolar_Hyper.F90
@@ -0,0 +1,356 @@
+#include
+
+MODULE MOD_NetSolar_Hyper
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: netsolar_hyper
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE netsolar_hyper (ipatch,idate,deltim,dlon,patchtype,&
+ forc_sols,forc_soll,forc_solsd,forc_solld,&
+ alb,ssun,ssha,lai,sai,rho,tau,ssoi,ssno,ssno_lyr,fsno,&
+ parsun,parsha,sabvsun,sabvsha,sabg,sabg_soil,sabg_snow,sabg_snow_lyr,&
+ sr,solvd,solvi,solnd,solni,srvd,srvi,srnd,srni,&
+ solvdln,solviln,solndln,solniln,srvdln,srviln,srndln,srniln,&
+ dir_frac, dif_frac, alb_hires,&
+ sol_dir_ln_hires,sol_dif_ln_hires,&
+ sr_dir_ln_hires ,sr_dif_ln_hires )
+!
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Net solar absorbed by surface
+!
+! Original author: Yongjiu Dai, 09/15/1999; 09/11/2001
+!
+! !REVISIONS:
+! 05/2014, Hua Yuan: added for solar radiation output [vars: so*, sr*]
+!
+! 08/2014, Hua Yuan: added for local noon calculation
+!
+! 08/2020, Hua Yuan: added for PFT and PC calculation
+!
+! 12/2022, Hua Yuan: calculated snow layer absorption by SNICAR model
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Namelist, only: DEF_USE_SNICAR
+ USE MOD_TimeManager, only: isgreenwich
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_Vars_1DPFTFluxes
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ipatch !patch index
+ integer, intent(in) :: idate(3) !model time
+ integer, intent(in) :: patchtype !land patch type (99-sea)
+
+ real(r8), intent(in) :: dlon !longitude in radians
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+
+ real(r8), intent(in) :: &
+ forc_sols, &! atm vis direct beam solar rad onto srf [W/m2]
+ forc_soll, &! atm nir direct beam solar rad onto srf [W/m2]
+ forc_solsd, &! atm vis diffuse solar rad onto srf [W/m2]
+ forc_solld ! atm nir diffuse solar rad onto srf [W/m2]
+
+ real(r8), dimension(1:2,1:2), intent(in) :: &
+ alb ! averaged albedo [-]
+
+ real(r8), dimension(1:2,1:2), intent(inout) :: &
+ ssun, &! sunlit canopy absorption for solar radiation
+ ssha, &! shaded canopy absorption for solar radiation
+ ssoi, &! ground soil absorption [-]
+ ssno ! ground snow absorption [-]
+
+ real(r8), dimension(1:2,1:2,maxsnl+1:1), intent(inout) :: &
+ ssno_lyr ! snow layer absorption
+
+ real(r8), intent(in) :: &
+ lai, &! leaf area index
+ sai, &! stem area index
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2) ! leaf transmittance (iw=iband, il=life and dead)
+
+ real(r8), intent(in) :: &
+ fsno ! snow fractional cover
+
+ real(r8), intent(out) :: &
+ parsun, &! PAR absorbed by sunlit vegetation [W/m2]
+ parsha, &! PAR absorbed by shaded vegetation [W/m2]
+ sabvsun, &! solar absorbed by sunlit vegetation [W/m2]
+ sabvsha, &! solar absorbed by shaded vegetation [W/m2]
+ sabg, &! solar absorbed by ground [W/m2]
+! 03/06/2020, yuan:
+ sabg_soil, &! solar absorbed by ground soil [W/m2]
+ sabg_snow, &! solar absorbed by ground snow [W/m2]
+ sr, &! total reflected solar radiation (W/m2)
+ solvd, &! incident direct beam vis solar radiation (W/m2)
+ solvi, &! incident diffuse beam vis solar radiation (W/m2)
+ solnd, &! incident direct beam nir solar radiation (W/m2)
+ solni, &! incident diffuse beam nir solar radiation (W/m2)
+ srvd, &! reflected direct beam vis solar radiation (W/m2)
+ srvi, &! reflected diffuse beam vis solar radiation (W/m2)
+ srnd, &! reflected direct beam nir solar radiation (W/m2)
+ srni, &! reflected diffuse beam nir solar radiation (W/m2)
+ solvdln, &! incident direct beam vis solar radiation at local noon(W/m2)
+ solviln, &! incident diffuse beam vis solar radiation at local noon(W/m2)
+ solndln, &! incident direct beam nir solar radiation at local noon(W/m2)
+ solniln, &! incident diffuse beam nir solar radiation at local noon(W/m2)
+ srvdln, &! reflected direct beam vis solar radiation at local noon(W/m2)
+ srviln, &! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ srndln, &! reflected direct beam nir solar radiation at local noon(W/m2)
+ srniln ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+
+ real(r8), intent(out) :: &
+ sabg_snow_lyr(maxsnl+1:1) ! solar absorbed by snow layers [W/m2]
+
+ ! variables for high resolution
+ real(r8), intent(in) :: &
+ dir_frac (211) ,&
+ dif_frac (211) ,&
+ alb_hires(211, 2)
+
+ real(r8), intent(out) :: &
+ sol_dir_ln_hires(211) ,&
+ sol_dif_ln_hires(211) ,&
+ sr_dir_ln_hires (211) ,&
+ sr_dif_ln_hires (211)
+
+
+! ----------------local variables ---------------------------------
+ integer :: local_secs
+ real(r8) :: radpsec, sabvg, sabg_noadj
+
+ integer ps, pe, p
+
+!-----------------------------------------------------------------------
+
+ sabvsun = 0.
+ sabvsha = 0.
+ parsun = 0.
+ parsha = 0.
+
+ IF (lai+sai <= 1.e-6) THEN
+ ssun(:,:) = 0.
+ ssha(:,:) = 0.
+ ENDIF
+
+ sabg = 0.
+ sabg_soil = 0.
+ sabg_snow = 0.
+ sabg_snow_lyr(:) = 0.
+
+ IF (patchtype == 0) THEN
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ sabvsun_p(ps:pe) = 0.
+ sabvsha_p(ps:pe) = 0.
+ parsun_p (ps:pe) = 0.
+ parsha_p (ps:pe) = 0.
+
+ DO p = ps, pe
+ IF (lai_p(p)+sai_p(p) <= 1.e-6) THEN
+ ssun_p(:,:,p) = 0.
+ ssha_p(:,:,p) = 0.
+ ENDIF
+ ENDDO
+
+ ssun(1,1) = sum( ssun_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(1,2) = sum( ssun_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,1) = sum( ssun_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssun(2,2) = sum( ssun_p(2,2,ps:pe)*pftfrac(ps:pe) )
+
+ ssha(1,1) = sum( ssha_p(1,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(1,2) = sum( ssha_p(1,2,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,1) = sum( ssha_p(2,1,ps:pe)*pftfrac(ps:pe) )
+ ssha(2,2) = sum( ssha_p(2,2,ps:pe)*pftfrac(ps:pe) )
+#endif
+ ENDIF
+
+ IF (forc_sols+forc_soll+forc_solsd+forc_solld > 0.) THEN
+ IF (patchtype < 4) THEN !non lake and ocean
+ ! Radiative fluxes onto surface
+ parsun = forc_sols*ssun(1,1) + forc_solsd*ssun(1,2)
+ parsha = forc_sols*ssha(1,1) + forc_solsd*ssha(1,2)
+ sabvsun = forc_sols*ssun(1,1) + forc_solsd*ssun(1,2) &
+ + forc_soll*ssun(2,1) + forc_solld*ssun(2,2)
+ sabvsha = forc_sols*ssha(1,1) + forc_solsd*ssha(1,2) &
+ + forc_soll*ssha(2,1) + forc_solld*ssha(2,2)
+ sabvg = forc_sols *(1.-alb(1,1)) + forc_solsd*(1.-alb(1,2)) &
+ + forc_soll *(1.-alb(2,1)) + forc_solld*(1.-alb(2,2))
+ sabg = sabvg - sabvsun - sabvsha
+
+ IF (patchtype == 0) THEN
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+ parsun_p (ps:pe) = forc_sols*ssun_p(1,1,ps:pe) + forc_solsd*ssun_p(1,2,ps:pe)
+ parsha_p (ps:pe) = forc_sols*ssha_p(1,1,ps:pe) + forc_solsd*ssha_p(1,2,ps:pe)
+ sabvsun_p(ps:pe) = forc_sols*ssun_p(1,1,ps:pe) + forc_solsd*ssun_p(1,2,ps:pe) &
+ + forc_soll*ssun_p(2,1,ps:pe) + forc_solld*ssun_p(2,2,ps:pe)
+ sabvsha_p(ps:pe) = forc_sols*ssha_p(1,1,ps:pe) + forc_solsd*ssha_p(1,2,ps:pe) &
+ + forc_soll*ssha_p(2,1,ps:pe) + forc_solld*ssha_p(2,2,ps:pe)
+#endif
+ ENDIF
+
+ ELSE !lake and ocean
+ sabvg = forc_sols *(1.-alb(1,1)) + forc_soll *(1.-alb(2,1)) &
+ + forc_solsd*(1.-alb(1,2)) + forc_solld*(1.-alb(2,2))
+ sabg = sabvg
+ ENDIF
+
+ ! calculate soil and snow solar absorption
+ sabg_soil = forc_sols*ssoi(1,1) + forc_solsd*ssoi(1,2) &
+ + forc_soll*ssoi(2,1) + forc_solld*ssoi(2,2)
+ sabg_snow = forc_sols*ssno(1,1) + forc_solsd*ssno(1,2) &
+ + forc_soll*ssno(2,1) + forc_solld*ssno(2,2)
+
+ sabg_soil = sabg_soil * (1.-fsno)
+ sabg_snow = sabg_snow * fsno
+
+ ! balance check and adjustment for soil and snow absorption
+ ! this could happen when there is adjustment to ssun,ssha
+ !NOTE: some times the imbalance may occur in URBAN patch
+ IF (abs(sabg_soil+sabg_snow-sabg)>1.e-6) THEN
+ ! IF (.not. (idate(2)==1 .and. idate(3)==int(deltim))) THEN
+ ! print *, "Patchtype = ", patchtype
+ ! print *, "MOD_NetSolar.F90: NOTE imbalance in spliting soil and snow surface!", &
+ ! sabg_soil+sabg_snow-sabg
+ ! print *, "sabg:", sabg, "sabg_soil:", sabg_soil, "sabg_snow", sabg_snow
+ ! print *, "sabg_soil+sabg_snow:", sabg_soil+sabg_snow, "fsno:", fsno
+ ! print *, "sabvg=",sabvg," sabvsun=",sabvsun," sabvsha=",sabvsha
+ ! print *, "alb=",alb
+ ! print *, "forc_sols=",forc_sols," forc_solsd=",forc_solsd
+ ! print *, "ssoi=",ssoi
+ ! ENDIF
+
+ sabg_noadj = sabg_soil + sabg_snow
+
+ IF (sabg_noadj > 0.) THEN
+ sabg_soil = sabg_soil * sabg/sabg_noadj
+ sabg_snow = sabg_snow * sabg/sabg_noadj
+ ssoi(:,:) = ssoi(:,:) * sabg/sabg_noadj
+ ssno(:,:) = ssno(:,:) * sabg/sabg_noadj
+ ENDIF
+ ENDIF
+
+ ! snow layer absorption calculation and adjustment for SNICAR model
+ IF (DEF_USE_SNICAR) THEN
+ ! adjust snow layer absorption due to multiple reflection between ground and canopy
+ IF(sum(ssno_lyr(1,1,:))>0.) THEN
+ ssno_lyr(1,1,:) = ssno(1,1) * ssno_lyr(1,1,:)/sum(ssno_lyr(1,1,:))
+ ELSE
+ ssno_lyr(1,1,1) = ssno(1,1)
+ ENDIF
+
+ IF(sum(ssno_lyr(1,2,:))>0.) THEN
+ ssno_lyr(1,2,:) = ssno(1,2) * ssno_lyr(1,2,:)/sum(ssno_lyr(1,2,:))
+ ELSE
+ ssno_lyr(1,2,1) = ssno(1,2)
+ ENDIF
+
+ IF(sum(ssno_lyr(2,1,:))>0.) THEN
+ ssno_lyr(2,1,:) = ssno(2,1) * ssno_lyr(2,1,:)/sum(ssno_lyr(2,1,:))
+ ELSE
+ ssno_lyr(2,1,1) = ssno(2,1)
+ ENDIF
+
+ IF(sum(ssno_lyr(2,2,:))>0.) THEN
+ ssno_lyr(2,2,:) = ssno(2,2) * ssno_lyr(2,2,:)/sum(ssno_lyr(2,2,:))
+ ELSE
+ ssno_lyr(2,2,1) = ssno(2,2)
+ ENDIF
+
+ ! snow layer absorption
+ sabg_snow_lyr(:) = forc_sols*ssno_lyr(1,1,:) + forc_solsd*ssno_lyr(1,2,:) &
+ + forc_soll*ssno_lyr(2,1,:) + forc_solld*ssno_lyr(2,2,:)
+
+ ! convert to the whole area multiplied by snow fractional cover
+ sabg_snow_lyr(:) = sabg_snow_lyr(:)*fsno
+
+ ! attribute the first layer absorption to soil absorption
+ sabg_soil = sabg_soil + sabg_snow_lyr(1)
+ sabg_snow = sabg_snow - sabg_snow_lyr(1)
+
+ ! make the soil absorption consistent
+ sabg_snow_lyr(1) = sabg_soil
+ ENDIF
+
+ ENDIF
+
+ solvd = forc_sols
+ solvi = forc_solsd
+ solnd = forc_soll
+ solni = forc_solld
+ srvd = solvd*alb(1,1)
+ srvi = solvi*alb(1,2)
+ srnd = solnd*alb(2,1)
+ srni = solni*alb(2,2)
+ sr = srvd + srvi + srnd + srni
+
+ ! calculate the local secs
+ radpsec = pi/12./3600.
+ IF ( isgreenwich ) THEN
+ local_secs = idate(3) + nint((dlon/radpsec)/deltim)*deltim
+ local_secs = mod(local_secs,86400)
+ ELSE
+ local_secs = idate(3)
+ ENDIF
+
+ IF (local_secs == 86400/2) THEN
+ solvdln = forc_sols
+ solviln = forc_solsd
+ solndln = forc_soll
+ solniln = forc_solld
+ srvdln = solvdln*alb(1,1)
+ srviln = solviln*alb(1,2)
+ srndln = solndln*alb(2,1)
+ srniln = solniln*alb(2,2)
+
+ ! calculate the high resolution solar radiation, maybe not called "_ln"
+ sol_dir_ln_hires = (forc_sols + forc_soll ) * dir_frac(:)
+ sol_dif_ln_hires = (forc_solsd + forc_solld) * dif_frac(:)
+ sr_dir_ln_hires = sol_dir_ln_hires(:) * alb_hires(:,1)
+ sr_dif_ln_hires = sol_dif_ln_hires(:) * alb_hires(:,2)
+
+ ELSE
+ solvdln = spval
+ solviln = spval
+ solndln = spval
+ solniln = spval
+ srvdln = spval
+ srviln = spval
+ srndln = spval
+ srniln = spval
+
+ sol_dir_ln_hires = spval
+ sol_dif_ln_hires = spval
+ sr_dir_ln_hires = spval
+ sr_dif_ln_hires = spval
+ ENDIF
+
+ END SUBROUTINE netsolar_hyper
+
+END MODULE MOD_NetSolar_Hyper
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_NewSnow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NewSnow.F90
new file mode 100644
index 0000000000..d5bea0a205
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NewSnow.F90
@@ -0,0 +1,125 @@
+MODULE MOD_NewSnow
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: newsnow
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE newsnow (patchtype,maxsnl,deltim,t_grnd,pg_rain,pg_snow,bifall,&
+ t_precip,zi_soisno,z_soisno,dz_soisno,t_soisno,&
+ wliq_soisno,wice_soisno,fiold,snl,sag,scv,snowdp,fsno,wetwat)
+
+!=======================================================================
+! add new snow nodes.
+! Original author: Yongjiu Dai, 09/15/1999; 08/31/2002, 07/2013, 04/2014
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_VariablySaturatedFlow
+ USE MOD_Const_Physical, only: tfrz, cpliq, cpice
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: maxsnl ! maximum number of snow layers
+ integer, intent(in) :: patchtype ! land patch type (0=soil, 1=urban and built-up,
+ ! 2=wetland, 3=land ice, 4=land water bodies, 99=ocean)
+ real(r8), intent(in) :: deltim ! model time step [second]
+ real(r8), intent(in) :: t_grnd ! ground surface temperature [k]
+ real(r8), intent(in) :: pg_rain ! rainfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(in) :: pg_snow ! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ real(r8), intent(in) :: bifall ! bulk density of newly fallen dry snow [kg/m3]
+ real(r8), intent(in) :: t_precip ! snowfall/rainfall temperature [kelvin]
+
+ real(r8), intent(inout) :: zi_soisno(maxsnl:0) ! interface level below a "z" level (m)
+ real(r8), intent(inout) :: z_soisno(maxsnl+1:0) ! layer depth (m)
+ real(r8), intent(inout) :: dz_soisno(maxsnl+1:0) ! layer thickness (m)
+ real(r8), intent(inout) :: t_soisno(maxsnl+1:0) ! soil + snow layer temperature [K]
+ real(r8), intent(inout) :: wliq_soisno(maxsnl+1:0) ! liquid water (kg/m2)
+ real(r8), intent(inout) :: wice_soisno(maxsnl+1:0) ! ice lens (kg/m2)
+ real(r8), intent(inout) :: fiold(maxsnl+1:0) ! fraction of ice relative to the total water
+ integer , intent(inout) :: snl ! number of snow layers
+ real(r8), intent(inout) :: sag ! non dimensional snow age [-]
+ real(r8), intent(inout) :: scv ! snow mass (kg/m2)
+ real(r8), intent(inout) :: snowdp ! snow depth (m)
+ real(r8), intent(inout) :: fsno ! fraction of soil covered by snow [-]
+
+ real(r8), intent(inout), optional :: wetwat ! wetland water [mm]
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) dz_snowf ! layer thickness rate change due to precipitation [mm/s]
+ integer newnode ! signification when new snow node is set, (1=yes, 0=no)
+ integer lb
+
+!-----------------------------------------------------------------------
+
+ newnode = 0
+
+ dz_snowf = pg_snow/bifall
+ snowdp = snowdp + dz_snowf*deltim
+ scv = scv + pg_snow*deltim ! snow water equivalent (mm)
+
+ IF(patchtype==2 .and. t_grnd>tfrz)THEN ! snowfall on warmer wetland
+ IF (present(wetwat) .and. DEF_USE_VariablySaturatedFlow) THEN
+ wetwat = wetwat + scv
+ ENDIF
+ scv=0.; snowdp=0.; sag=0.; fsno = 0.
+ ENDIF
+
+ zi_soisno(0) = 0.
+
+! when the snow accumulation exceeds 10 mm, initialize a snow layer
+
+ IF(snl==0 .and. pg_snow>0.0 .and. snowdp>=0.01)THEN
+ snl = -1
+ newnode = 1
+ dz_soisno(0) = snowdp ! meter
+ z_soisno (0) = -0.5*dz_soisno(0)
+ zi_soisno(-1) = -dz_soisno(0)
+
+ sag = 0. ! snow age
+ t_soisno (0) = min(tfrz, t_precip) ! K
+ wice_soisno(0) = scv ! kg/m2
+ wliq_soisno(0) = 0. ! kg/m2
+ fiold(0) = 1.
+ fsno = min(1.,tanh(0.1*pg_snow*deltim))
+ ENDIF
+
+ ! --------------------------------------------------
+ ! snowfall on snow pack
+ ! --------------------------------------------------
+ ! the change of ice partial density of surface node due to precipitation
+ ! only ice part of snowfall is added here, the liquid part will be added latter
+
+ IF(snl<0 .and. newnode==0)THEN
+ lb = snl + 1
+
+ wice_soisno(lb) = wice_soisno(lb)+deltim*pg_snow
+ dz_soisno(lb) = dz_soisno(lb)+dz_snowf*deltim
+ z_soisno(lb) = zi_soisno(lb) - 0.5*dz_soisno(lb)
+ zi_soisno(lb-1) = zi_soisno(lb) - dz_soisno(lb)
+
+ ! update fsno by new snow event, add to previous fsno
+ ! shape factor for accumulation of snow = 0.1
+ fsno = 1. - (1. - tanh(0.1*pg_snow*deltim))*(1. - fsno)
+ fsno = min(1., fsno)
+
+ ENDIF
+
+ END SUBROUTINE newsnow
+
+END MODULE MOD_NewSnow
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_NitrifData.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NitrifData.F90
new file mode 100644
index 0000000000..21729cfff0
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_NitrifData.F90
@@ -0,0 +1,171 @@
+#include
+
+#ifdef BGC
+MODULE MOD_NitrifData
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This module read in nitrif data.
+!
+! !ORIGINAL:
+! Lu Xingjie and Zhang Shupeng, 2023, prepare the original version of the nitrif data module.
+!-----------------------------------------------------------------------
+
+ USE MOD_Grid
+ USE MOD_SpatialMapping
+ USE MOD_BGC_Vars_TimeVariables, only: tCONC_O2_UNSAT, tO2_DECOMP_DEPTH_UNSAT
+ IMPLICIT NONE
+
+ type(grid_type) :: grid_nitrif
+ type(spatial_mapping_type) :: mg2p_nitrif
+
+CONTAINS
+
+ SUBROUTINE init_nitrif_data (time)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! open nitrif netcdf file from DEF_dir_runtime, read latitude and
+! longitude info. Initialize nitrif data read in.
+!-----------------------------------------------------------------------
+
+ USE MOD_TimeManager
+ USE MOD_Namelist
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ type(timestamp), intent(in) :: time
+
+ ! Local Variables
+ character(len=256) :: file_nitrif
+ real(r8), allocatable :: lat(:), lon(:)
+ integer :: month, mday
+
+ file_nitrif = trim(DEF_dir_runtime)//'/nitrif/CONC_O2_UNSAT/CONC_O2_UNSAT_l01.nc'
+
+ CALL ncio_read_bcast_serial (file_nitrif, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_nitrif, 'lon', lon)
+
+ CALL grid_nitrif%define_by_center (lat, lon)
+
+ CALL mg2p_nitrif%build_arealweighted (grid_nitrif, landpatch)
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ CALL julian2monthday (time%year, time%day, month, mday)
+
+ CALL update_nitrif_data (month)
+
+ END SUBROUTINE init_nitrif_data
+
+ ! ----------
+ SUBROUTINE update_nitrif_data (month)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_DataType
+ USE MOD_Vars_Global, only: nl_soil
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ USE MOD_Vars_TimeInvariants
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: month
+
+ ! Local Variables
+ character(len=256) :: file_nitrif
+ type(block_data_real8_2d) :: f_xy_nitrif
+ real(r8), allocatable :: tCONC_O2_UNSAT_tmp(:)
+ real(r8), allocatable :: tO2_DECOMP_DEPTH_UNSAT_tmp(:)
+ character(len=2) :: cx
+ integer :: nsl, npatch, m
+
+ IF (p_is_compute) THEN
+ allocate(tCONC_O2_UNSAT_tmp (numpatch))
+ allocate(tO2_DECOMP_DEPTH_UNSAT_tmp(numpatch))
+ ENDIF
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_nitrif, f_xy_nitrif)
+ ENDIF
+
+ DO nsl = 1, nl_soil
+
+ write(cx,'(i2.2)') nsl
+ file_nitrif = trim(DEF_dir_runtime)//&
+ '/nitrif/CONC_O2_UNSAT/CONC_O2_UNSAT_l'//trim(cx)//'.nc'
+ IF (p_is_active) THEN
+ CALL ncio_read_block_time (file_nitrif, &
+ 'CONC_O2_UNSAT', grid_nitrif, month, f_xy_nitrif)
+ ENDIF
+
+ CALL mg2p_nitrif%grid2pset (f_xy_nitrif, tCONC_O2_UNSAT_tmp)
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO npatch = 1, numpatch
+ m = patchclass(npatch)
+ IF( m == 0 )THEN
+ tCONC_O2_UNSAT(nsl,npatch) = 0.
+ ELSE
+ tCONC_O2_UNSAT(nsl,npatch) = tCONC_O2_UNSAT_tmp(npatch)
+ ENDIF
+ IF (tCONC_O2_UNSAT(nsl,npatch) < 1E-10) THEN
+ tCONC_O2_UNSAT(nsl,npatch)=0.0
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+ ENDDO
+
+#ifdef RangeCheck
+ CALL check_vector_data ('CONC_O2_UNSAT', tCONC_O2_UNSAT)
+#endif
+
+ DO nsl = 1, nl_soil
+
+ write(cx,'(i2.2)') nsl
+ file_nitrif = trim(DEF_dir_runtime)//&
+ '/nitrif/O2_DECOMP_DEPTH_UNSAT/O2_DECOMP_DEPTH_UNSAT_l'//trim(cx)//'.nc'
+ IF (p_is_active) THEN
+ CALL ncio_read_block_time (file_nitrif, &
+ 'O2_DECOMP_DEPTH_UNSAT', grid_nitrif, month, f_xy_nitrif)
+ ENDIF
+
+ CALL mg2p_nitrif%grid2pset (f_xy_nitrif, tO2_DECOMP_DEPTH_UNSAT_tmp)
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ DO npatch = 1, numpatch
+ m = patchclass(npatch)
+ IF( m == 0 )THEN
+ tO2_DECOMP_DEPTH_UNSAT(nsl,npatch) = 0.
+ ELSE
+ tO2_DECOMP_DEPTH_UNSAT(nsl,npatch) = tO2_DECOMP_DEPTH_UNSAT_tmp(npatch)
+ ENDIF
+ IF (tO2_DECOMP_DEPTH_UNSAT(nsl,npatch) < 1E-10) THEN
+ tO2_DECOMP_DEPTH_UNSAT(nsl,npatch)=0.0
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+ ENDDO
+
+#ifdef RangeCheck
+ CALL check_vector_data ('O2_DECOMP_DEPTH_UNSAT', tO2_DECOMP_DEPTH_UNSAT)
+#endif
+
+ IF (p_is_compute) THEN
+ deallocate (tCONC_O2_UNSAT_tmp)
+ deallocate (tO2_DECOMP_DEPTH_UNSAT_tmp)
+ ENDIF
+
+ END SUBROUTINE update_nitrif_data
+
+END MODULE MOD_NitrifData
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_OrbCosazi.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_OrbCosazi.F90
new file mode 100644
index 0000000000..5f8288c7d9
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_OrbCosazi.F90
@@ -0,0 +1,70 @@
+#include
+
+MODULE MOD_OrbCosazi
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: orb_cosazi
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ FUNCTION orb_cosazi(calday, dlon, dlat, coszen)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: calday !Julian cal day (1.xx to 365.xx)
+ real(r8), intent(in) :: dlat !Centered latitude (radians)
+ real(r8), intent(in) :: dlon !Centered longitude (radians)
+ real(r8), intent(in) :: coszen !cosine of sun zenith angle
+ real(r8) :: orb_cosazi !cosine of sun azimuth angle
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) declin !Solar declination (radians)
+ real(r8) eccf !Earth-sun distance factor (ie. (1/r)**2)
+ real(r8) lambm !Lambda m, mean long of perihelion (rad)
+ real(r8) lmm !Intermediate argument involving lambm
+ real(r8) lamb !Lambda, the earths long of perihelion
+ real(r8) invrho !Inverse normalized sun/earth distance
+ real(r8) sinl !Sine of lmm
+ real(r8) pi !3.14159265358979323846...
+ real(r8), parameter :: &
+ dayspy=365.0, &!days per year
+ ve=80.5, &!Calday of vernal equinox assumes Jan 1 = calday 1
+ eccen=1.672393084E-2, &!Eccentricity
+ obliqr=0.409214646, &!Earths obliquity in radians
+ lambm0=-3.2625366E-2, &!Mean long of perihelion at the vernal equinox (radians)
+ mvelpp=4.92251015 !moving vernal equinox longitude of
+ !perihelion plus pi (radians)
+!-----------------------------------------------------------------------
+
+ pi = 4.*atan(1.)
+ lambm = lambm0 + (calday - ve)*2.*pi/dayspy
+ lmm = lambm - mvelpp
+
+ sinl = sin(lmm)
+ lamb = lambm + eccen*(2.*sinl + eccen*(1.25*sin(2.*lmm) &
+ + eccen*((13.0/12.0)*sin(3.*lmm) - 0.25*sinl)))
+ invrho = (1. + eccen*cos(lamb - mvelpp)) / (1. - eccen*eccen)
+
+ declin = asin(sin(obliqr)*sin(lamb))
+ eccf = invrho*invrho
+
+ orb_cosazi = (-1*cos(declin)*cos(calday*2.0*pi+dlon) - &
+ coszen*cos(dlat))/(sin(dlat)*sqrt(1-coszen*coszen))
+
+ IF (orb_cosazi<-1) orb_cosazi = -1
+ IF (orb_cosazi>1 ) orb_cosazi = 1
+
+ END FUNCTION orb_cosazi
+
+END MODULE MOD_OrbCosazi
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_OrbCoszen.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_OrbCoszen.F90
new file mode 100644
index 0000000000..ab8ced757f
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_OrbCoszen.F90
@@ -0,0 +1,84 @@
+#include
+
+MODULE MOD_OrbCoszen
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: orb_coszen
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ FUNCTION orb_coszen(calday,dlon,dlat)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! FUNCTION to return the cosine of the solar zenith angle. Assumes
+! 365.0 days/year. Compute earth/orbit parameters using formula
+! suggested by Duane Thresher. Use formulas from Berger, Andre 1978:
+! Long-Term Variations of Daily Insolation and Quaternary Climatic
+! Changes. J. of the Atmo. Sci. 35:2362-2367.
+!
+! Original version: Erik Kluzek, Oct/1997, Brian Kauffman, Jan/98
+! CCSM2.0 standard
+! Yongjiu Dai (07/23/2002)
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: calday !Julian cal day (1.xx to 365.xx)
+ real(r8), intent(in) :: dlat !Centered latitude (radians)
+ real(r8), intent(in) :: dlon !Centered longitude (radians)
+ real(r8) :: orb_coszen
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) declin !Solar declination (radians)
+ real(r8) eccf !Earth-sun distance factor (ie. (1/r)**2)
+ real(r8) lambm !Lambda m, mean long of perihelion (rad)
+ real(r8) lmm !Intermediate argument involving lambm
+ real(r8) lamb !Lambda, the earths long of perihelion
+ real(r8) invrho !Inverse normalized sun/earth distance
+ real(r8) sinl !Sine of lmm
+ real(r8) pi !3.14159265358979323846...
+ real(r8), parameter :: &
+ dayspy=365.0, &!days per year
+ ve=80.5, &!Calday of vernal equinox assumes Jan 1 = calday 1
+ eccen=1.672393084E-2, &!Eccentricity
+ obliqr=0.409214646, &!Earths obliquity in radians
+ lambm0=-3.2625366E-2, &!Mean long of perihelion at the vernal equinox (radians)
+ mvelpp=4.92251015 !moving vernal equinox longitude of
+ !perihelion plus pi (radians)
+!-----------------------------------------------------------------------
+
+ pi = 4.*atan(1.)
+ lambm = lambm0 + (calday - ve)*2.*pi/dayspy
+ lmm = lambm - mvelpp
+
+ sinl = sin(lmm)
+ lamb = lambm + eccen*(2.*sinl + eccen*(1.25*sin(2.*lmm) &
+ + eccen*((13.0/12.0)*sin(3.*lmm) - 0.25*sinl)))
+ invrho = (1. + eccen*cos(lamb - mvelpp)) / (1. - eccen*eccen)
+
+ declin = asin(sin(obliqr)*sin(lamb))
+ eccf = invrho*invrho
+
+ orb_coszen = sin(dlat)*sin(declin) &
+ - cos(dlat)*cos(declin)*cos(calday*2.0*pi+dlon)
+
+ END FUNCTION orb_coszen
+
+END MODULE MOD_OrbCoszen
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Ozone.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Ozone.F90
new file mode 100644
index 0000000000..20904245a8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Ozone.F90
@@ -0,0 +1,275 @@
+#include
+
+Module MOD_Ozone
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This module hold the plant physiological response to the ozone,
+! including vcmax response and stomata response. Ozone concentration
+! can be either readin through Mod_OzoneData module or set to constant.
+!
+! Original:
+! The Community Land Model version 5.0 (CLM5.0)
+!
+! !REVISIONS:
+! 2022, Xingjie Lu: revised the CLM5 code to be compatible with CoLM
+! code structure.
+! 2024, Fang Li : used the new ozone stress parameterization scheme
+! based on Li et al. (2024; GMD)
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: rgas
+ USE MOD_Const_PFT, only: isevg, leaf_long, woody
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SpatialMapping
+ USE MOD_Vars_1DForcing, only: forc_ozone
+ USE MOD_Namelist, only: DEF_USE_OZONEDATA
+ IMPLICIT NONE
+
+ character(len=256) :: file_ozone
+
+ type(grid_type) :: grid_ozone
+
+ type(block_data_real8_2d) :: f_ozone
+
+ type(spatial_mapping_type) :: mg2p_ozone
+
+ SAVE
+
+ PUBLIC :: CalcOzoneStress
+ PUBLIC :: init_ozone_data
+ PUBLIC :: update_ozone_data
+
+CONTAINS
+
+ SUBROUTINE CalcOzoneStress (o3coefv,o3coefg, forc_ozone, forc_psrf, th, ram, &
+ rs, rb, lai, lai_old, ivt, o3uptake, sabv, deltim)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate Ozone Stress on both vcmax and stomata conductance.
+!
+! convert o3 from mol/mol to nmol m^-3
+!-----------------------------------------------------------------------
+ real(r8), intent(out) :: o3coefv
+ real(r8), intent(out) :: o3coefg
+ real(r8), intent(inout) :: forc_ozone !ozone concentration (ppbv)
+ real(r8), intent(in) :: forc_psrf
+ real(r8), intent(in) :: th
+ real(r8), intent(in) :: ram
+ real(r8), intent(in) :: rs
+ real(r8), intent(in) :: rb
+ real(r8), intent(in) :: lai
+ real(r8), intent(in) :: lai_old
+ integer , intent(in) :: ivt
+ real(r8), intent(inout) :: o3uptake
+ real(r8), intent(in) :: deltim
+ real(r8), intent(in) :: sabv !solar radiation absorbed by vegetation (W/m**2)
+
+ real(r8) :: o3concnmolm3 ! o3 concentration (nmol/m^3)
+ real(r8) :: o3flux ! instantaneous o3 flux (nmol m^-2 s^-1)
+ real(r8) :: o3fluxcrit ! instantaneous o3 flux beyond threshold (nmol m^-2 s^-1)
+ real(r8) :: o3fluxperdt ! o3 flux per timestep (mmol m^-2)
+ real(r8) :: leafturn ! leaf turnover time / mortality rate (per hour)
+ real(r8) :: decay ! o3uptake decay rate based on leaf lifetime (mmol m^-2)
+ real(r8) :: lai_thresh ! LAI threshold for LAIs that asymptote and don't
+ real(r8) :: o3_flux_threshold !threshold below which o3flux is set to 0 (nmol m^-2 s^-1)
+
+ real(r8), parameter :: ko3 = 1.51_r8 !F. Li
+
+
+ IF(.not. DEF_USE_OZONEDATA)THEN
+ forc_ozone = 100._r8 ! ozone partial pressure [ppbv]
+ ENDIF
+
+ o3concnmolm3 = forc_ozone * (forc_psrf/(th * 8.314 ))
+
+ ! calculate instantaneous flux
+ o3flux = o3concnmolm3/ (ko3*rs+ rb + ram)
+
+ ! set lai_thresh
+ IF (isevg(ivt)) THEN
+ lai_thresh=0._r8 !so evergreens grow year-round
+ ELSE ! for deciduous vegetation
+ IF(ivt == 10)THEN !temperate shrub
+ lai_thresh=0.3_r8
+ ELSE
+ lai_thresh=0.5_r8
+ end if
+ end if
+
+
+ ! set o3 flux threshold
+ o3_flux_threshold=10._r8
+ IF(ivt >= 1 .and. ivt <= 3)THEN !Needleleaf tree
+ o3_flux_threshold=0.8_r8
+ ENDIF
+ IF(ivt >= 4 .and. ivt <= 8)THEN !Broadleaf tree
+ o3_flux_threshold=1.0_r8
+ ENDIF
+ IF(ivt >= 9 .and. ivt <= 11)THEN !Shrub
+ o3_flux_threshold=6.0_r8
+ ENDIF
+ IF(ivt >= 12 .and. ivt <= 14)THEN !Grass
+ o3_flux_threshold = 1.6_r8
+ ENDIF
+ IF(ivt >= 15)THEN !Crop
+ o3_flux_threshold = 0.5_r8
+ ENDIF
+
+
+ IF (o3flux < o3_flux_threshold) THEN
+ o3fluxcrit = 0._r8
+ ELSE
+ o3fluxcrit = o3flux - o3_flux_threshold
+ ENDIF
+
+ ! calculate o3 flux per timestep
+ IF(sabv > 0._r8)THEN !daytime
+ o3fluxperdt = o3fluxcrit * deltim * 0.000001_r8
+ ELSE
+ o3fluxperdt = 0._r8
+ ENDIF
+
+ IF (lai > lai_thresh) THEN
+ ! o3 uptake decay
+ IF (isevg(ivt)) THEN
+ leafturn = 2._r8/(leaf_long(ivt)*365._r8*24._r8)
+ decay = o3uptake * leafturn * deltim/3600._r8
+ ELSE
+ decay = o3uptake * max(0._r8,(1._r8-lai_old/lai))
+ ENDIF
+
+ !cumulative uptake (mmol m^-2)
+ o3uptake = min(90._r8, max(0._r8, o3uptake + o3fluxperdt - decay))
+
+ ELSE
+ o3uptake = 0._r8
+ ENDIF
+
+ IF (o3uptake == 0._r8) THEN
+ ! No o3 damage IF no o3 uptake
+ o3coefv = 1._r8
+ o3coefg = 1._r8
+ ELSE
+ ! Determine parameter values for this pft
+ IF(ivt >= 1 .and. ivt <= 3)THEN !Needleleaf tree
+ o3coefv = max(0._r8, min(1._r8, 1.005_r8 - 0.0064_r8 * o3uptake))
+ o3coefg = max(0._r8, min(1._r8, 0.965_r8 * o3uptake ** (-0.041)))
+ ENDIF
+ IF(ivt >= 4 .and. ivt <= 8)THEN !Broadleaf tree
+ o3coefv = max(0._r8, min(1._r8, 0.943_r8 * exp(-0.0085*o3uptake)))
+ o3coefg = max(0._r8, min(1._r8, 0.943_r8 * exp(-0.0058*o3uptake)))
+ ENDIF
+ IF(ivt >= 9 .and. ivt <= 11)THEN !Shrub
+ o3coefv = max(0._r8, min(1._r8, 1.000_r8-0.074_r8 * log(o3uptake)))
+ o3coefg = max(0._r8, min(1._r8, 0.991_r8-0.060_r8 * log(o3uptake)))
+ ENDIF
+ IF(ivt >= 12 .and. ivt <= 14)THEN !Grass
+ o3coefv = max(0._r8, min(1._r8, 0.997_r8 - 0.016_r8 * o3uptake))
+ o3coefg = max(0._r8, min(1._r8, 0.989_r8 - 0.045_r8 * log(o3uptake)))
+ ENDIF
+ IF(ivt >= 15)THEN !Crop
+ o3coefv = max(0._r8, min(1._r8, 0.909_r8 - 0.028_r8 * log(o3uptake)))
+ o3coefg = max(0._r8, min(1._r8, 1.005_r8 - 0.169_r8 * tanh(o3uptake)))
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE CalcOzoneStress
+
+
+ SUBROUTINE init_ozone_data (idate)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! open ozone netcdf file from DEF_dir_rawdata, read latitude and
+! longitude info. Initialize Ozone data read in.
+!-----------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_TimeManager
+ USE MOD_Grid
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ USE MOD_LandPatch
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+
+ ! Local Variables
+ real(r8), allocatable :: lat(:), lon(:)
+ integer :: itime
+ integer :: iyear, month, mday
+ character(len=8) :: syear, smonth
+
+! CALL julian2monthday(idate(1),idate(2),month,mday)
+! iyear = idate(1)
+! IF(idate(1) .lt. 2013)iyear = 2013
+! IF(idate(1) .gt. 2021)iyear = 2021
+! write(syear,"(I4.4)") iyear
+! write(smonth,"(I2.2)") month
+ file_ozone = trim(DEF_dir_runtime) // '/Ozone//Global/OZONE-setgrid.nc'
+! file_ozone = '/share/home/dq010/CoLM/data/rawdata/CROP-NITRIF/CoLMruntime/Ozone//Global/OZONE-setgrid.nc'
+
+ CALL ncio_read_bcast_serial (file_ozone, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_ozone, 'lon', lon)
+
+ CALL grid_ozone%define_by_center (lat, lon)
+
+ CALL allocate_block_data (grid_ozone, f_ozone)
+
+ CALL mg2p_ozone%build_arealweighted (grid_ozone, landpatch)
+
+ itime = (idate(3) - 1800) / 10800 + (min(idate(2),365) - 1) * 8 + 1
+
+ CALL ncio_read_block_time (file_ozone, 'OZONE', grid_ozone, itime, f_ozone)
+#ifdef RangeCheck
+ CALL check_block_data ('Ozone', f_ozone)
+#endif
+
+ END SUBROUTINE init_ozone_data
+
+ SUBROUTINE update_ozone_data (time, deltim)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! read ozone data during simulation
+!-----------------------------------------------------------------------
+
+ USE MOD_TimeManager
+ USE MOD_Namelist
+ USE MOD_NetCDFBlock
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ type(timestamp), intent(in) :: time
+ real(r8), intent(in) :: deltim
+
+ ! Local Variables
+ type(timestamp) :: time_next
+ integer :: month, mday
+ integer :: iyear, itime
+ character(len=8) :: syear, smonth
+
+ file_ozone = trim(DEF_dir_runtime) // '/Ozone/Global/OZONE-setgrid.nc'
+! file_ozone = '/share/home/dq010/CoLM/data/rawdata/CROP-NITRIF/CoLMruntime/Ozone/Global/OZONE-setgrid.nc'
+ IF(time%sec/10800 .ne. (time%sec+int(deltim))/10800)then
+ itime = (time%sec - int(deltim)) / 10800 + (min(time%day,365) - 1) * 8 + 1
+ CALL ncio_read_block_time (file_ozone, 'OZONE', grid_ozone, itime, f_ozone)
+#ifdef RangeCheck
+ CALL check_block_data ('Ozone', f_ozone)
+#endif
+
+ CALL mg2p_ozone%grid2pset (f_ozone, forc_ozone)
+#ifdef RangeCheck
+ CALL check_vector_data ('Ozone', forc_ozone)
+#endif
+ ENDIF
+
+ END SUBROUTINE update_ozone_data
+
+END MODULE MOD_Ozone
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_PhaseChange.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_PhaseChange.F90
new file mode 100644
index 0000000000..a7127f8c58
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_PhaseChange.F90
@@ -0,0 +1,823 @@
+#include
+
+MODULE MOD_PhaseChange
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: meltf
+ PUBLIC :: meltf_snicar
+ PUBLIC :: meltf_urban
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE meltf (patchtype,is_dry_lake,lb,nl_soil,deltim, &
+ fact,brr,hs,hs_soil,hs_snow,fsno,dhsdT, &
+ t_soisno_bef,t_soisno,wliq_soisno,wice_soisno,imelt, &
+ scv,snowdp,sm,xmf,porsl,psi0,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r,alpha_vgm,n_vgm,L_vgm,&
+ sc_vgm,fc_vgm,&
+#endif
+ dz)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! calculation of the phase change within snow and soil layers:
+! (1) check the conditions which the phase change may take place,
+! i.e., the layer temperature is great than the freezing point
+! and the ice mass is not equal to zero (i.e., melting),
+! or layer temperature is less than the freezing point
+! and the liquid water mass is not equal to zero (i.e., freezing);
+! (2) assess the rate of phase change from the energy excess (or deficit)
+! after setting the layer temperature to freezing point;
+! (3) re-adjust the ice and liquid mass, and the layer temperature
+!
+! Original author: Yongjiu Dai, /09/1999/, /03/2014/
+!
+! !REVISIONS:
+! 08/2020, Hua Yuan: separate soil/snow heat flux, exclude glacier (3)
+! 04/2023, Nan Wei: supercooled soil water is included IF supercool is defined.
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Hydro_SoilFunction
+ USE MOD_Const_Physical, only: tfrz, hfus, grav
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: patchtype !land patch type
+ !(0=soil,1=urban or built-up,2=wetland,
+ !3=land ice, 4=deep lake, 5=shallow lake)
+ logical, intent(in) :: is_dry_lake
+ integer, intent(in) :: nl_soil !upper bound of array (i.e., soil layers)
+ integer, intent(in) :: lb !lower bound of array (i.e., snl +1)
+ real(r8), intent(in) :: deltim !time step [second]
+ real(r8), intent(in) :: t_soisno_bef(lb:nl_soil) !temperature at previous time step [K]
+ real(r8), intent(in) :: brr (lb:nl_soil) !
+ real(r8), intent(in) :: fact(lb:nl_soil) !temporary variables
+ real(r8), intent(in) :: hs !net ground heat flux into the surface
+ real(r8), intent(in) :: hs_soil !net ground heat flux into the surface soil
+ real(r8), intent(in) :: hs_snow !net ground heat flux into the surface snow
+ real(r8), intent(in) :: fsno !snow fractional cover
+ real(r8), intent(in) :: dhsdT !temperature derivative of "hs"
+ real(r8), intent(in) :: porsl(1:nl_soil) !soil porosity [-]
+ real(r8), intent(in) :: psi0 (1:nl_soil) !soil water suction, negative potential [mm]
+#ifdef Campbell_SOIL_MODEL
+ real(r8), intent(in) :: bsw(1:nl_soil) !clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), intent(in) :: theta_r (1:nl_soil), &
+ alpha_vgm(1:nl_soil), &
+ n_vgm (1:nl_soil), &
+ L_vgm (1:nl_soil), &
+ sc_vgm (1:nl_soil), &
+ fc_vgm (1:nl_soil)
+#endif
+ real(r8), intent(in) :: dz(1:nl_soil) !soil layer thickness [m]
+
+ real(r8), intent(inout) :: t_soisno (lb:nl_soil) !temperature at current time step [K]
+ real(r8), intent(inout) :: wice_soisno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:nl_soil) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv !snow mass [kg/m2]
+ real(r8), intent(inout) :: snowdp !snow depth [m]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [mm/s, kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change
+ integer, intent(out) :: imelt(lb:nl_soil) !flag for melting or freezing [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: hm(lb:nl_soil) !energy residual [W/m2]
+ real(r8) :: xm(lb:nl_soil) !melting or freezing within a time step [kg/m2]
+ real(r8) :: heatr !energy residual or loss after melting or freezing
+ real(r8) :: temp1 !temporary variables [kg/m2]
+ real(r8) :: temp2 !temporary variables [kg/m2]
+ real(r8) :: smp
+ real(r8) :: supercool(1:nl_soil) !the maximum liquid water when soil T below the tfrz [mm3/mm3]
+ real(r8), dimension(lb:nl_soil) :: wmass0, wice0, wliq0
+ real(r8) :: propor, tinc, we, scvold
+ integer j
+
+!-----------------------------------------------------------------------
+ sm = 0.
+ xmf = 0.
+ DO j = lb, nl_soil
+ imelt(j) = 0
+ hm(j) = 0.
+ xm(j) = 0.
+ wice0(j) = wice_soisno(j)
+ wliq0(j) = wliq_soisno(j)
+ wmass0(j) = wice_soisno(j) + wliq_soisno(j)
+ ENDDO
+
+ scvold=scv
+ we=0.
+ IF(lb<=0) we = sum(wice_soisno(lb:0)+wliq_soisno(lb:0))
+
+! supercooling water
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ DO j = 1, nl_soil
+ supercool(j) = 0.0
+ IF(t_soisno(j) < tfrz .and. ((patchtype <=2) .or. is_dry_lake)) THEN
+ smp = hfus * (t_soisno(j)-tfrz)/(grav*t_soisno(j)) * 1000. ! mm
+ IF (porsl(j) > 0.) THEN
+#ifdef Campbell_SOIL_MODEL
+ supercool(j) = porsl(j)*(smp/psi0(j))**(-1.0/bsw(j))
+#else
+ supercool(j) = soil_vliq_from_psi(smp, porsl(j), theta_r(j), -10.0, 5, &
+ (/alpha_vgm(j), n_vgm(j), L_vgm(j), sc_vgm(j), fc_vgm(j)/))
+#endif
+ ELSE
+ supercool(j) = 0.
+ ENDIF
+ supercool(j) = supercool(j)*dz(j)*1000. ! mm
+ ENDIF
+ ENDDO
+ ENDIF
+
+ DO j = lb, nl_soil
+ ! Melting identification
+ ! IF ice exists above melt point, melt some to liquid.
+ IF(wice_soisno(j) > 0. .and. t_soisno(j) > tfrz)THEN
+ imelt(j) = 1
+ t_soisno(j) = tfrz
+ ENDIF
+
+ ! Freezing identification
+ ! IF liquid exists below melt point, freeze some to ice.
+ IF(j <= 0)THEN
+ IF(wliq_soisno(j) > 0. .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ELSE
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ IF(wliq_soisno(j) > supercool(j) .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ELSE
+ IF(wliq_soisno(j) > 0. .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+! If snow exists, but its thickness less than the critical value (0.01 m)
+ IF(lb == 1 .and. scv > 0.)THEN
+ IF(t_soisno(1) > tfrz)THEN
+ imelt(1) = 1
+ t_soisno(1) = tfrz
+ ENDIF
+ ENDIF
+
+! Calculate the energy surplus and loss for melting and freezing
+ DO j = lb, nl_soil
+ IF(imelt(j) > 0)THEN
+ tinc = t_soisno(j)-t_soisno_bef(j)
+
+ IF(j > lb)THEN ! => not the top layer
+ IF (j==1 .and. DEF_SPLIT_SOILSNOW .and. ((patchtype<3) .or. is_dry_lake)) THEN
+ ! -> interface soil layer
+ ! 03/08/2020, yuan: separate soil/snow heat flux, exclude glacier(3)
+ hm(j) = hs_soil + (1.-fsno)*dhsdT*tinc + brr(j) - tinc/fact(j)
+ ELSE ! -> internal layers other than the interface soil layer
+ hm(j) = brr(j) - tinc/fact(j)
+ ENDIF
+ ELSE ! => top layer
+ IF (j==1 .or. (.not.DEF_SPLIT_SOILSNOW) .or. patchtype==3) THEN
+ ! -> soil layer
+ hm(j) = hs + dhsdT*tinc + brr(j) - tinc/fact(j)
+ ELSE ! -> snow cover
+ ! 03/08/2020, yuan: separate soil/snow heat flux, exclude glacier(3)
+ hm(j) = hs_snow + fsno*dhsdT*tinc + brr(j) - tinc/fact(j)
+ ENDIF
+ ENDIF
+
+ ENDIF
+ ENDDO
+
+ DO j = lb, nl_soil
+ IF(imelt(j) == 1 .and. hm(j) < 0.) THEN
+ hm(j) = 0.
+ imelt(j) = 0
+ ENDIF
+! this error was checked carefully, it results from the computed error
+! of "Tridiagonal-Matrix" in SUBROUTINE "thermal".
+ IF(imelt(j) == 2 .and. hm(j) > 0.) THEN
+ hm(j) = 0.
+ imelt(j) = 0
+ ENDIF
+ ENDDO
+
+! The rate of melting and freezing
+ DO j = lb, nl_soil
+ IF(imelt(j) > 0 .and. abs(hm(j)) > .0) THEN
+ xm(j) = hm(j)*deltim/hfus ! kg/m2
+
+ ! IF snow exists, but its thickness less than the critical value (1 cm)
+ ! Note: more work is need on how to tune the snow depth at this case
+ IF(j == 1 .and. lb == 1 .and. scv > 0. .and. xm(j) > 0.)THEN
+ temp1 = scv ! kg/m2
+ scv = max(0.,temp1-xm(j))
+ propor = scv/temp1
+ snowdp = propor * snowdp
+ heatr = hm(j) - hfus*(temp1-scv)/deltim ! W/m2
+ IF(heatr > 0.) THEN
+ xm(j) = heatr*deltim/hfus ! kg/m2
+ hm(j) = heatr ! W/m2
+ ELSE
+ xm(j) = 0.
+ hm(j) = 0.
+ ENDIF
+ sm = max(0.,(temp1-scv))/deltim ! kg/(m2 s)
+ xmf = hfus*sm
+ ENDIF
+
+ heatr = 0.
+ IF(xm(j) > 0.) THEN
+ wice_soisno(j) = max(0., wice0(j)-xm(j))
+ heatr = hm(j) - hfus*(wice0(j)-wice_soisno(j))/deltim
+ ELSE
+ IF(j <= 0) THEN ! snow
+ wice_soisno(j) = min(wmass0(j), wice0(j)-xm(j))
+ ELSE
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ IF(wmass0(j) < supercool(j)) THEN
+ wice_soisno(j) = 0.
+ ELSE
+ wice_soisno(j) = min(wmass0(j)-supercool(j), wice0(j)-xm(j))
+ ENDIF
+ ELSE
+ wice_soisno(j) = min(wmass0(j), wice0(j)-xm(j))
+ ENDIF
+ ENDIF
+ heatr = hm(j) - hfus*(wice0(j)-wice_soisno(j))/deltim
+ ENDIF
+
+ wliq_soisno(j) = max(0.,wmass0(j)-wice_soisno(j))
+
+ IF(abs(heatr) > 0.)THEN
+ IF(j > lb)THEN ! => not the top layer
+ IF (j==1 .and. DEF_SPLIT_SOILSNOW .and. ((patchtype<3) .or. is_dry_lake)) THEN
+ ! -> interface soil layer
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*(1.-fsno)*dhsdT)
+ ELSE ! -> internal layers other than the interface soil layer
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr
+ ENDIF
+ ELSE ! => top layer
+ IF (j==1 .or. (.not.DEF_SPLIT_SOILSNOW) .or. patchtype==3) THEN
+ ! -> soil layer
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*dhsdT)
+ ELSE ! -> snow cover
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*fsno*dhsdT)
+ ENDIF
+ ENDIF
+
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ IF(j <= 0 .or. patchtype == 3)THEN !snow
+ IF(wliq_soisno(j)*wice_soisno(j) > 0.) t_soisno(j) = tfrz
+ ENDIF
+ ELSE
+ IF(wliq_soisno(j)*wice_soisno(j) > 0.) t_soisno(j) = tfrz
+ ENDIF
+ ENDIF
+
+ xmf = xmf + hfus * (wice0(j)-wice_soisno(j))/deltim
+
+ IF(imelt(j) == 1 .and. j < 1) &
+ sm = sm + max(0.,(wice0(j)-wice_soisno(j)))/deltim
+
+ ENDIF
+ ENDDO
+
+ !scvold=scv
+ IF(lb<=0) THEN
+ we = sum(wice_soisno(lb:0)+wliq_soisno(lb:0))-we
+ IF(abs(we)>1.e-6) THEN
+ print*, 'meltf err : ', we
+ CALL CoLM_stop()
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE meltf
+
+
+ SUBROUTINE meltf_snicar (patchtype,is_dry_lake,lb,nl_soil,deltim, &
+ fact,brr,hs,hs_soil,hs_snow,fsno,sabg_snow_lyr,dhsdT, &
+ t_soisno_bef,t_soisno,wliq_soisno,wice_soisno,imelt, &
+ scv,snowdp,sm,xmf,porsl,psi0,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r,alpha_vgm,n_vgm,L_vgm,&
+ sc_vgm,fc_vgm,&
+#endif
+ dz)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! calculation of the phase change within snow and soil layers:
+! (1) check the conditions which the phase change may take place,
+! i.e., the layer temperature is great than the freezing point
+! and the ice mass is not equal to zero (i.e., melting),
+! or layer temperature is less than the freezing point
+! and the liquid water mass is not equal to zero (i.e., freezing);
+! (2) assess the rate of phase change from the energy excess (or deficit)
+! after setting the layer temperature to freezing point;
+! (3) re-adjust the ice and liquid mass, and the layer temperature
+!
+! Original author: Yongjiu Dai, /09/1999/, /03/2014/
+!
+! !REVISIONS:
+! 08/2020, Hua Yuan: separate soil/snow heat flux, exclude glacier (3)
+! 01/2023, Hua Yuan: added snow layer absorption in melting calculation
+! 04/2023, Nan Wei: supercooled soil water is included IF supercool is defined.
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Hydro_SoilFunction
+ USE MOD_Const_Physical, only: tfrz, hfus, grav
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: patchtype !land patch type
+ !(0=soil,1=urban or built-up,2=wetland,
+ !3=land ice, 4=deep lake, 5=shallow lake)
+ logical, intent(in) :: is_dry_lake
+ integer, intent(in) :: nl_soil !upper bound of array (i.e., soil layers)
+ integer, intent(in) :: lb !lower bound of array (i.e., snl +1)
+ real(r8), intent(in) :: deltim !time step [second]
+ real(r8), intent(in) :: t_soisno_bef(lb:nl_soil) !temperature at previous time step [K]
+ real(r8), intent(in) :: brr (lb:nl_soil) !
+ real(r8), intent(in) :: fact(lb:nl_soil) !temporary variables
+ real(r8), intent(in) :: hs !net ground heat flux into the surface
+ real(r8), intent(in) :: hs_soil !net ground heat flux into the surface soil
+ real(r8), intent(in) :: hs_snow !net ground heat flux into the surface snow
+ real(r8), intent(in) :: fsno !snow fractional cover
+ real(r8), intent(in) :: dhsdT !temperature derivative of "hs"
+ real(r8), intent(in) :: sabg_snow_lyr (lb:1) !snow layer absorption [W/m-2]
+ real(r8), intent(in) :: porsl(1:nl_soil) !soil porosity [-]
+ real(r8), intent(in) :: psi0 (1:nl_soil) !soil water suction, negative potential [mm]
+#ifdef Campbell_SOIL_MODEL
+ real(r8), intent(in) :: bsw(1:nl_soil) !clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), intent(in) :: theta_r (1:nl_soil), &
+ alpha_vgm(1:nl_soil), &
+ n_vgm (1:nl_soil), &
+ L_vgm (1:nl_soil), &
+ sc_vgm (1:nl_soil), &
+ fc_vgm (1:nl_soil)
+#endif
+ real(r8), intent(in) :: dz(1:nl_soil) !soil layer thickness [m]
+
+ real(r8), intent(inout) :: t_soisno (lb:nl_soil) !temperature at current time step [K]
+ real(r8), intent(inout) :: wice_soisno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:nl_soil) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv !snow mass [kg/m2]
+ real(r8), intent(inout) :: snowdp !snow depth [m]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [mm/s, kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change
+ integer, intent(out) :: imelt(lb:nl_soil) !flag for melting or freezing [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: hm(lb:nl_soil) !energy residual [W/m2]
+ real(r8) :: xm(lb:nl_soil) !melting or freezing within a time step [kg/m2]
+ real(r8) :: heatr !energy residual or loss after melting or freezing
+ real(r8) :: temp1 !temporary variables [kg/m2]
+ real(r8) :: temp2 !temporary variables [kg/m2]
+ real(r8) :: smp
+ real(r8) :: supercool(1:nl_soil) !the maximum liquid water when soil T below the tfrz [mm3/mm3]
+ real(r8), dimension(lb:nl_soil) :: wmass0, wice0, wliq0
+ real(r8) :: propor, tinc, we, scvold
+ integer j
+
+!-----------------------------------------------------------------------
+
+ sm = 0.
+ xmf = 0.
+ DO j = lb, nl_soil
+ imelt(j) = 0
+ hm(j) = 0.
+ xm(j) = 0.
+ wice0(j) = wice_soisno(j)
+ wliq0(j) = wliq_soisno(j)
+ wmass0(j) = wice_soisno(j) + wliq_soisno(j)
+ ENDDO
+
+ scvold=scv
+ we=0.
+ IF(lb<=0) we = sum(wice_soisno(lb:0)+wliq_soisno(lb:0))
+
+! supercooling water
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ DO j = 1, nl_soil
+ supercool(j) = 0.0
+ IF(t_soisno(j) < tfrz .and. ((patchtype <= 2) .or. is_dry_lake)) THEN
+ smp = hfus * (t_soisno(j)-tfrz)/(grav*t_soisno(j)) * 1000. ! mm
+ IF (porsl(j) > 0.) THEN
+#ifdef Campbell_SOIL_MODEL
+ supercool(j) = porsl(j)*(smp/psi0(j))**(-1.0/bsw(j))
+#else
+ supercool(j) = soil_vliq_from_psi(smp, porsl(j), theta_r(j), -10.0, 5, &
+ (/alpha_vgm(j), n_vgm(j), L_vgm(j), sc_vgm(j), fc_vgm(j)/))
+#endif
+ ELSE
+ supercool(j) = 0.
+ ENDIF
+ supercool(j) = supercool(j)*dz(j)*1000. ! mm
+ ENDIF
+ ENDDO
+ ENDIF
+
+
+ DO j = lb, nl_soil
+ ! Melting identification
+ ! IF ice exists above melt point, melt some to liquid.
+ IF(wice_soisno(j) > 0. .and. t_soisno(j) > tfrz)THEN
+ imelt(j) = 1
+ t_soisno(j) = tfrz
+ ENDIF
+
+ ! Freezing identification
+ ! IF liquid exists below melt point, freeze some to ice.
+ IF(j <= 0)THEN
+ IF(wliq_soisno(j) > 0. .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ELSE
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ IF(wliq_soisno(j) > supercool(j) .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ELSE
+ IF(wliq_soisno(j) > 0. .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+! If snow exists, but its thickness less than the critical value (0.01 m)
+ IF(lb == 1 .and. scv > 0.)THEN
+ IF(t_soisno(1) > tfrz)THEN
+ imelt(1) = 1
+ t_soisno(1) = tfrz
+ ENDIF
+ ENDIF
+
+! Calculate the energy surplus and loss for melting and freezing
+ DO j = lb, nl_soil
+ IF(imelt(j) > 0)THEN
+ tinc = t_soisno(j)-t_soisno_bef(j)
+
+ IF(j > lb)THEN ! => not the top layer
+ IF (j==1 .and. DEF_SPLIT_SOILSNOW .and. ((patchtype<3).or.is_dry_lake)) THEN
+ ! -> interface soil layer
+ ! 03/08/2020, yuan: separate soil/snow heat flux, exclude glacier(3)
+ hm(j) = hs_soil + (1.-fsno)*dhsdT*tinc + brr(j) - tinc/fact(j)
+ ELSE ! -> internal layers other than the interface soil layer
+ IF (j<1 .or. (j==1 .and. patchtype==3)) THEN
+ hm(j) = brr(j) - tinc/fact(j) + sabg_snow_lyr(j)
+ ELSE
+ hm(j) = brr(j) - tinc/fact(j)
+ ENDIF
+ ENDIF
+ ELSE ! => top layer
+ IF (j==1 .or. (.not.DEF_SPLIT_SOILSNOW) .or. patchtype==3) THEN
+ ! -> soil layer
+ hm(j) = hs + dhsdT*tinc + brr(j) - tinc/fact(j)
+ ELSE ! -> snow cover
+ ! 03/08/2020, yuan: separate soil/snow heat flux, exclude glacier(3)
+ hm(j) = hs_snow + fsno*dhsdT*tinc + brr(j) - tinc/fact(j)
+ ENDIF
+ ENDIF
+
+ ENDIF
+ ENDDO
+
+ DO j = lb, nl_soil
+ IF(imelt(j) == 1 .and. hm(j) < 0.) THEN
+ hm(j) = 0.
+ imelt(j) = 0
+ ENDIF
+! this error was checked carefully, it results from the computed error
+! of "Tridiagonal-Matrix" in SUBROUTINE "thermal".
+ IF(imelt(j) == 2 .and. hm(j) > 0.) THEN
+ hm(j) = 0.
+ imelt(j) = 0
+ ENDIF
+ ENDDO
+
+! The rate of melting and freezing
+ DO j = lb, nl_soil
+ IF(imelt(j) > 0 .and. abs(hm(j)) > .0) THEN
+ xm(j) = hm(j)*deltim/hfus ! kg/m2
+
+ ! IF snow exists, but its thickness less than the critical value (1 cm)
+ ! Note: more work is need on how to tune the snow depth at this case
+ IF(j == 1 .and. lb == 1 .and. scv > 0. .and. xm(j) > 0.)THEN
+ temp1 = scv ! kg/m2
+ scv = max(0.,temp1-xm(j))
+ propor = scv/temp1
+ snowdp = propor * snowdp
+ heatr = hm(j) - hfus*(temp1-scv)/deltim ! W/m2
+ IF(heatr > 0.) THEN
+ xm(j) = heatr*deltim/hfus ! kg/m2
+ hm(j) = heatr ! W/m2
+ ELSE
+ xm(j) = 0.
+ hm(j) = 0.
+ ENDIF
+ sm = max(0.,(temp1-scv))/deltim ! kg/(m2 s)
+ xmf = hfus*sm
+ ENDIF
+
+ heatr = 0.
+ IF(xm(j) > 0.) THEN
+ wice_soisno(j) = max(0., wice0(j)-xm(j))
+ heatr = hm(j) - hfus*(wice0(j)-wice_soisno(j))/deltim
+ ELSE
+ IF(j <= 0) THEN ! snow
+ wice_soisno(j) = min(wmass0(j), wice0(j)-xm(j))
+ ELSE
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ IF(wmass0(j) < supercool(j)) THEN
+ wice_soisno(j) = 0.
+ ELSE
+ wice_soisno(j) = min(wmass0(j)-supercool(j), wice0(j)-xm(j))
+ ENDIF
+ ELSE
+ wice_soisno(j) = min(wmass0(j), wice0(j)-xm(j))
+ ENDIF
+ ENDIF
+ heatr = hm(j) - hfus*(wice0(j)-wice_soisno(j))/deltim
+ ENDIF
+
+ wliq_soisno(j) = max(0.,wmass0(j)-wice_soisno(j))
+
+ IF(abs(heatr) > 0.)THEN
+ IF(j > lb)THEN ! => not the top layer
+ IF (j==1 .and. DEF_SPLIT_SOILSNOW .and. ((patchtype<3).or.is_dry_lake)) THEN
+ ! -> interface soil layer
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*(1.-fsno)*dhsdT)
+ ELSE ! -> internal layers other than the interface soil layer
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr
+ ENDIF
+ ELSE ! => top layer
+ IF (j==1 .or. (.not.DEF_SPLIT_SOILSNOW) .or. patchtype==3) THEN
+ ! -> soil layer
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*dhsdT)
+ ELSE ! -> snow cover
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*fsno*dhsdT)
+ ENDIF
+ ENDIF
+
+ IF (DEF_USE_SUPERCOOL_WATER) THEN
+ IF(j <= 0 .or. patchtype == 3)THEN !snow
+ IF(wliq_soisno(j)*wice_soisno(j) > 0.) t_soisno(j) = tfrz
+ ENDIF
+ ELSE
+ IF(wliq_soisno(j)*wice_soisno(j) > 0.) t_soisno(j) = tfrz
+ ENDIF
+
+ ENDIF
+
+ xmf = xmf + hfus * (wice0(j)-wice_soisno(j))/deltim
+
+ IF(imelt(j) == 1 .and. j < 1) &
+ sm = sm + max(0.,(wice0(j)-wice_soisno(j)))/deltim
+
+ ENDIF
+ ENDDO
+
+ !scvold=scv
+ IF(lb<=0) THEN
+ we = sum(wice_soisno(lb:0)+wliq_soisno(lb:0))-we
+ IF(abs(we)>1.e-6) THEN
+ print*, 'meltf err : ', we
+ CALL CoLM_stop()
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE meltf_snicar
+
+ SUBROUTINE meltf_urban (lb,nl_soil,deltim, &
+ fact,brr,hs,dhsdT, &
+ t_soisno_bef,t_soisno,wliq_soisno,wice_soisno,imelt, &
+ scv,snowdp,sm,xmf)
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! calculation of the phase change within snow and soil layers:
+!
+! (1) check the conditions which the phase change may take place,
+! i.e., the layer temperature is great than the freezing point
+! and the ice mass is not equal to zero (i.e., melting),
+! or layer temperature is less than the freezing point
+! and the liquid water mass is not equal to zero (i.e., freezing);
+! (2) assess the rate of phase change from the energy excess (or deficit)
+! after setting the layer temperature to freezing point;
+! (3) re-adjust the ice and liquid mass, and the layer temperature
+!
+! Original author: Yongjiu Dai, /09/1999/, /03/2014/
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Const_Physical, only: tfrz, hfus
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: nl_soil !upper bound of array (i.e., soil layers)
+ integer, intent(in) :: lb !lower bound of array (i.e., snl +1)
+ real(r8), intent(in) :: deltim !time step [second]
+ real(r8), intent(in) :: t_soisno_bef(lb:nl_soil) !temperature at previous time step [K]
+ real(r8), intent(in) :: brr (lb:nl_soil) !
+ real(r8), intent(in) :: fact(lb:nl_soil) !temporary variables
+ real(r8), intent(in) :: hs !net ground heat flux into the surface
+ real(r8), intent(in) :: dhsdT !temperature derivative of "hs"
+
+ real(r8), intent(inout) :: t_soisno (lb:nl_soil) !temperature at current time step [K]
+ real(r8), intent(inout) :: wice_soisno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:nl_soil) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv !snow mass [kg/m2]
+ real(r8), intent(inout) :: snowdp !snow depth [m]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [mm/s, kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change
+ integer, intent(out) :: imelt(lb:nl_soil) !flag for melting or freezing [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: hm(lb:nl_soil) !energy residual [W/m2]
+ real(r8) :: xm(lb:nl_soil) !melting or freezing within a time step [kg/m2]
+ real(r8) :: heatr !energy residual or loss after melting or freezing
+ real(r8) :: temp1 !temporary variables [kg/m2]
+ real(r8) :: temp2 !temporary variables [kg/m2]
+
+ real(r8), dimension(lb:nl_soil) :: wmass0, wice0, wliq0
+ real(r8) :: propor, tinc, we, scvold
+ integer j
+
+!-----------------------------------------------------------------------
+
+ sm = 0.
+ xmf = 0.
+ DO j = lb, nl_soil
+ imelt(j) = 0
+ hm(j) = 0.
+ xm(j) = 0.
+ wice0(j) = wice_soisno(j)
+ wliq0(j) = wliq_soisno(j)
+ wmass0(j) = wice_soisno(j) + wliq_soisno(j)
+ ENDDO
+
+ scvold=scv
+ we=0.
+ IF(lb<=0) we = sum(wice_soisno(lb:0)+wliq_soisno(lb:0))
+
+ DO j = lb, nl_soil
+ ! Melting identification
+ ! IF ice exists above melt point, melt some to liquid.
+ IF(wice_soisno(j) > 0. .and. t_soisno(j) > tfrz)THEN
+ imelt(j) = 1
+ t_soisno(j) = tfrz
+ ENDIF
+
+ ! Freezing identification
+ ! IF liquid exists below melt point, freeze some to ice.
+ IF(wliq_soisno(j) > 0. .and. t_soisno(j) < tfrz) THEN
+ imelt(j) = 2
+ t_soisno(j) = tfrz
+ ENDIF
+ ENDDO
+
+! If snow exists, but its thickness less than the critical value (0.01 m)
+ IF(lb == 1 .and. scv > 0.)THEN
+ IF(t_soisno(1) > tfrz)THEN
+ imelt(1) = 1
+ t_soisno(1) = tfrz
+ ENDIF
+ ENDIF
+
+! Calculate the energy surplus and loss for melting and freezing
+ DO j = lb, nl_soil
+ IF(imelt(j) > 0)THEN
+ tinc = t_soisno(j)-t_soisno_bef(j)
+ IF(j > lb)THEN
+ hm(j) = brr(j) - tinc/fact(j)
+ ELSE
+ hm(j) = hs + dhsdT*tinc + brr(j) - tinc/fact(j)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO j = lb, nl_soil
+ IF(imelt(j) == 1 .and. hm(j) < 0.) THEN
+ hm(j) = 0.
+ imelt(j) = 0
+ ENDIF
+! this error was checked carefully, it results from the computed error
+! of "Tridiagonal-Matrix" in SUBROUTINE "thermal".
+ IF(imelt(j) == 2 .and. hm(j) > 0.) THEN
+ hm(j) = 0.
+ imelt(j) = 0
+ ENDIF
+ ENDDO
+
+! The rate of melting and freezing
+ DO j = lb, nl_soil
+ IF(imelt(j) > 0 .and. abs(hm(j)) > .0) THEN
+ xm(j) = hm(j)*deltim/hfus ! kg/m2
+
+ ! IF snow exists, but its thickness less than the critical value (1 cm)
+ ! Note: more work is need on how to tune the snow depth at this case
+ IF(j == 1 .and. lb == 1 .and. scv > 0. .and. xm(j) > 0.)THEN
+ temp1 = scv ! kg/m2
+ scv = max(0.,temp1-xm(j))
+ propor = scv/temp1
+ snowdp = propor * snowdp
+ heatr = hm(j) - hfus*(temp1-scv)/deltim ! W/m2
+ IF(heatr > 0.) THEN
+ xm(j) = heatr*deltim/hfus ! kg/m2
+ hm(j) = heatr ! W/m2
+ ELSE
+ xm(j) = 0.
+ hm(j) = 0.
+ ENDIF
+ sm = max(0.,(temp1-scv))/deltim ! kg/(m2 s)
+ xmf = hfus*sm
+ ENDIF
+
+ heatr = 0.
+ IF(xm(j) > 0.) THEN
+ wice_soisno(j) = max(0., wice0(j)-xm(j))
+ heatr = hm(j) - hfus*(wice0(j)-wice_soisno(j))/deltim
+ ELSE
+ wice_soisno(j) = min(wmass0(j), wice0(j)-xm(j))
+ heatr = hm(j) - hfus*(wice0(j)-wice_soisno(j))/deltim
+ ENDIF
+
+ wliq_soisno(j) = max(0.,wmass0(j)-wice_soisno(j))
+
+ IF(abs(heatr) > 0.)THEN
+ IF(j > lb)THEN
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr
+ ELSE
+ t_soisno(j) = t_soisno(j) + fact(j)*heatr/(1.-fact(j)*dhsdT)
+ ENDIF
+ IF(wliq_soisno(j)*wice_soisno(j) > 0.) t_soisno(j) = tfrz
+ ENDIF
+
+ xmf = xmf + hfus * (wice0(j)-wice_soisno(j))/deltim
+
+ IF(imelt(j) == 1 .and. j < 1) &
+ sm = sm + max(0.,(wice0(j)-wice_soisno(j)))/deltim
+
+ ENDIF
+ ENDDO
+
+ !scvold=scv
+ IF(lb<=0) THEN
+ we = sum(wice_soisno(lb:0)+wliq_soisno(lb:0))-we
+ IF(abs(we)>1.e-6) THEN
+ print*, 'meltf err : ', we
+ CALL CoLM_stop()
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE meltf_urban
+
+END MODULE MOD_PhaseChange
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_PlantHydraulic.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_PlantHydraulic.F90
new file mode 100644
index 0000000000..f85365c619
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_PlantHydraulic.F90
@@ -0,0 +1,1096 @@
+
+MODULE MOD_PlantHydraulic
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_RSS_SCHEME
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: PlantHydraulicStress_twoleaf
+ PUBLIC :: getvegwp_twoleaf
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: calcstress_twoleaf
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+
+ SUBROUTINE PlantHydraulicStress_twoleaf (nl_soil ,nvegwcs ,z_soi ,&
+ dz_soi ,rootfr ,psrf ,qsatl ,&
+ qaf ,tl ,rb ,rss ,&
+ ra ,rd ,rstfacsun ,rstfacsha ,cintsun ,&
+ cintsha ,laisun ,laisha ,rhoair ,fwet ,&
+ sai ,kmax_sun ,kmax_sha ,kmax_xyl ,kmax_root ,&
+ psi50_sun ,psi50_sha ,psi50_xyl ,psi50_root ,htop ,&
+ ck ,smp ,hk ,hksati ,vegwp ,&
+ etrsun ,etrsha ,rootflux ,qg ,&
+ qm ,gs0sun ,gs0sha ,k_soil_root,k_ax_root ,&
+ gssun ,gssha)
+
+!=======================================================================
+!
+! calculation of plant hydraulic stress
+!
+! Author: Xingjie Lu, 16/01/2019, modified from CLM5 plant_hydraulic_stress module
+!
+!----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer ,intent(in) :: nl_soil ! upper bound of array
+ integer ,intent(in) :: nvegwcs ! upper bound of array
+ real(r8),intent(in), dimension(nl_soil) :: &
+ z_soi, &! soil node depth (m)
+ dz_soi ! soil layer thicknesses (m)
+ real(r8),intent(inout), dimension(nvegwcs) :: &
+ vegwp ! vegetation water potential
+ real(r8),intent(inout):: &
+ gs0sun, & ! maximum stomata conductance of sunlit leaf
+ gs0sha ! maximum stomata conductance of shaded leaf
+
+ real(r8),intent(in) :: &
+ rss, &! soil surface resistance [s/m]
+ psrf, &! surface atmospheric pressure (pa)
+ qg, &! specific humidity at ground surface [kg/kg]
+ qm ! specific humidity at reference height [kg/kg]
+
+ real(r8),intent(in) :: &
+ qsatl, &! leaf specific humidity [kg/kg]
+ qaf, &! humidity of canopy air [kg/kg]
+ tl, &! leaf temperature (K)
+
+ rb, &! boundary resistance from canopy to cas (s m-1)
+ rd, &! aerodynamical resistance between ground and canopy air
+ ra ! aerodynamic resistance from cas to reference height (s m-1)
+
+ real(r8),intent(inout) :: &
+ rstfacsun, &! canopy resistance stress factors to soil moisture for sunlit leaf
+ rstfacsha ! canopy resistance stress factors to soil moisture for shaded leaf
+
+ real(r8),intent(in) :: &
+ laisun, &! sunlit leaf area index, one-sided
+ laisha, &! shaded leaf area index, one-sided
+ sai, &! stem area index
+ kmax_sun, &
+ kmax_sha, &
+ kmax_xyl, &
+ kmax_root, &
+ psi50_sun, &! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ psi50_sha, &! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ psi50_xyl, &! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ psi50_root, &! water potential at 50% loss of root tissue conductance (mmH2O)
+ htop, &! canopy top [m]
+ ck, &! shape-fitting parameter for vulnerability curve (-)
+ rhoair, &! density [kg/m**3]
+ fwet ! fraction of foliage that is wet [-]
+
+ real(r8),intent(in), dimension(3) :: &
+ cintsun, &! scaling up from sunlit leaf to canopy
+ cintsha ! scaling up from shaded leaf to canopy
+
+ real(r8),intent(in), dimension(nl_soil) :: &
+ smp, &! soil matrix potential
+ rootfr, &! root fraction
+ hksati, &! hydraulic conductivity at saturation [mm h2o/s]
+ hk ! soil hydraulic conductance [mm h2o/s]
+
+
+ real(r8),intent(out) :: &! ATTENTION : all for canopy not leaf
+ etrsun, &! transpiration from sunlit leaf (mm/s)
+ etrsha ! transpiration from shaded leaf (mm/s)
+
+ real(r8),intent(out),dimension(nl_soil) :: &
+ rootflux ! root water uptake from different layers
+
+ real(r8),intent(inout),dimension(nl_soil) :: k_soil_root ! radial root and soil conductance
+ real(r8),intent(inout),dimension(nl_soil) :: k_ax_root ! axial root conductance
+ real(r8),intent(inout) :: gssun ! sunlit leaf conductance
+ real(r8),intent(inout) :: gssha ! shaded leaf conductance
+
+!-------------------------- Local Variables ----------------------------
+
+ integer, parameter :: iterationtotal = 6
+
+ real(r8) c3, &! c3 vegetation : 1; 0 for c4
+
+ tprcor, &! coefficient for unit transfer
+ gb_mol ! one side leaf boundary layer conductance of sunlit leaf (leaf scale:umol H2O m-2 s-1)
+
+ real(r8), dimension(nl_soil) :: &
+ fs !root conductance scale factor (reduction in conductance due to decreasing (more negative) root water potential)
+ real(r8), dimension(nl_soil) :: &
+ rai ! soil-root interface conductance [mm/s]
+
+ real(r8) soilflux ! soil-root interface conductance [mm/s]
+ real(r8) soil_conductance ! soil conductance
+ real(r8) root_conductance ! root conductance
+ real(r8) r_soil ! root spacing [m]
+ real(r8) root_biomass_density ! root biomass density [g/m3]
+ real(r8) root_cross_sec_area ! root cross sectional area [m2]
+ real(r8) root_length_density ! root length density [m/m3]
+ real(r8) croot_average_length ! average coarse root length [m]
+ real(r8) rs_resis ! combined soil-root resistance [s]
+ real(r8) cf ! s m**2/umol -> s/m
+
+ real(r8), parameter :: croot_lateral_length = 0.25_r8 ! specified lateral coarse root length [m]
+ real(r8), parameter :: c_to_b = 2.0_r8 ! (g biomass /g C)
+ real(r8), parameter :: rpi = 3.14159265358979_r8
+ integer , parameter :: root = 4
+ real(r8), parameter :: toldb = 1.e-2_r8 ! tolerance for satisfactory bsun/bsha solution
+ real(r8), parameter :: K_axs = 2.0e-1
+
+ ! temporary input
+ real(r8), parameter :: froot_carbon = 288.392056287006_r8
+ real(r8), parameter :: root_radius = 2.9e-4_r8
+ real(r8), parameter :: root_density = 310000._r8
+ real(r8), parameter :: froot_leaf = 1.5_r8
+ real(r8), parameter :: krmax = 3.981071705534969e-009_r8
+
+ real(r8),dimension(nvegwcs) :: x ! vegetation water potential
+
+ integer j
+
+!----------------calculate root-soil interface conductance-----------------
+ DO j = 1,nl_soil
+
+ ! calculate conversion from conductivity to conductance
+ root_biomass_density = c_to_b * froot_carbon * rootfr(j) / dz_soi(j)
+ ! ensure minimum root biomass (using 1gC/m2)
+ root_biomass_density = max(c_to_b*1._r8,root_biomass_density)
+
+ ! Root length density: m root per m3 soil
+ root_cross_sec_area = rpi*root_radius**2
+ root_length_density = root_biomass_density / (root_density * root_cross_sec_area)
+
+ ! Root-area index (RAI)
+ rai(j) = (sai+laisun+laisha) * froot_leaf * rootfr(j)
+
+ ! fix coarse root_average_length to specified length
+ croot_average_length = croot_lateral_length
+
+ ! calculate r_soil using Gardner/spa equation (Bonan, GMD, 2014)
+ r_soil = sqrt(1./(rpi*root_length_density))
+
+ ! length scale approach
+ soil_conductance = min(hksati(j),hk(j))/(1.e3*r_soil)
+
+ ! USE vegetation plc function to adjust root conductance
+ fs(j)= plc(amax1(smp(j),-1._r8),psi50_root,ck)
+
+ ! krmax is root conductance per area per length
+ root_conductance = (fs(j)*rai(j)*krmax)/(croot_average_length + z_soi(j))
+ soil_conductance = max(soil_conductance, 1.e-16_r8)
+ root_conductance = max(root_conductance, 1.e-16_r8)
+
+ ! sum resistances in soil and root
+ rs_resis = 1._r8/soil_conductance + 1._r8/root_conductance
+
+ ! conductance is inverse resistance
+ ! explicitly set conductance to zero for top soil layer
+ IF(rai(j)*rootfr(j) > 0._r8) THEN
+ k_soil_root(j) = 1._r8/rs_resis
+ ELSE
+ k_soil_root(j) = 0.
+ ENDIF
+ k_ax_root(j) = (rootfr(j)/(dz_soi(j)*1000))*K_axs*0.6
+ ENDDO
+!=======================================================================
+
+ tprcor = 44.6*273.16*psrf/1.013e5
+ cf = tprcor/tl * 1.e6_r8 ! gb->gbmol conversion factor
+
+ ! one side leaf boundary layer conductance for water vapor [=1/(2*rb)]
+ ! ATTENTION: rb in CLM is for one side leaf, but for SiB2 rb for
+ ! 2-side leaf, so the gbh2o shold be " 0.5/rb * tprcor/tl "
+ gb_mol = 1./rb * cf ! resistance to conductance (s/m -> umol/m**2/s)
+
+ x = vegwp(1:nvegwcs)
+
+ CALL calcstress_twoleaf(x, nvegwcs, rstfacsun, rstfacsha, etrsun, etrsha, rootflux,&
+ gb_mol, gs0sun, gs0sha, qsatl, qaf, qg, qm, rhoair, &
+ psrf, fwet, laisun, laisha, sai, htop, tl, kmax_sun, &
+ kmax_sha, kmax_xyl, kmax_root, psi50_sun, psi50_sha, psi50_xyl, psi50_root, ck, &
+ nl_soil, z_soi, rss, ra, rd, smp, k_soil_root, k_ax_root, gssun, gssha)
+
+ vegwp(1:nvegwcs) = x
+
+ END SUBROUTINE PlantHydraulicStress_twoleaf
+
+ SUBROUTINE calcstress_twoleaf(x,nvegwcs,rstfacsun, rstfacsha, etrsun, etrsha, rootflux,&
+ gb_mol, gs0sun, gs0sha, qsatl, qaf, qg, qm,rhoair,&
+ psrf, fwet, laisun, laisha, sai, htop, tl, kmax_sun, kmax_sha, kmax_xyl, kmax_root, &
+ psi50_sun, psi50_sha, psi50_xyl, psi50_root, ck, nl_soil, z_soi, rss, raw, rd, smp, &
+ k_soil_root, k_ax_root, gssun, gssha)
+ !
+ ! DESCRIPTIONS
+ ! compute the transpiration stress using a plant hydraulics approach
+ ! calls spacF, spacA, and getvegwp
+ !
+ ! !ARGUMENTS:
+ integer, intent(in) :: nvegwcs
+ real(r8), intent(inout) :: x(nvegwcs) ! working copy of vegwp(p,:)
+ real(r8), intent(out) :: rstfacsun ! sunlit canopy transpiration wetness factor (0 to 1)
+ real(r8), intent(out) :: rstfacsha ! shaded sunlit canopy transpiration wetness factor (0 to 1)
+ real(r8), intent(out) :: etrsun ! transpiration from sunlit leaf (mm/s)
+ real(r8), intent(out) :: etrsha ! transpiration from shaded leaf (mm/s)
+ real(r8), intent(out) :: rootflux(nl_soil) ! root water uptake from different layers
+
+ integer, intent(in) :: nl_soil
+ real(r8), intent(in) :: z_soi(nl_soil)
+ real(r8), intent(in) :: gb_mol ! leaf boundary layer conductance (umol H2O/m**2/s)
+ real(r8), intent(in) :: gs0sun ! sunlit Ball-Berry minimum leaf conductance (umol H2O/m**2/s)
+ real(r8), intent(in) :: gs0sha ! shaded Ball-Berry minimum leaf conductance (umol H2O/m**2/s)
+ real(r8), intent(in) :: qsatl ! leaf specific humidity [kg/kg]
+ real(r8), intent(in) :: qaf ! humidity of canopy air [kg/kg]
+ real(r8), intent(in) :: qg ! specific humidity at ground surface [kg/kg]
+ real(r8), intent(in) :: qm ! specific humidity at reference height [kg/kg]
+ real(r8), intent(in) :: rhoair ! density [kg/m**3]
+ real(r8), intent(in) :: psrf ! atmospheric pressure [Pa]
+ real(r8), intent(in) :: fwet ! fraction of foliage that is green and dry [-]
+ real(r8), intent(in) :: rss ! soil surface resistance [s/m]
+ real(r8), intent(in) :: raw ! moisture resistance [s/m]
+ real(r8), intent(in) :: rd ! aerodynamical resistance between ground and canopy air
+ real(r8), intent(in) :: laisun ! Sunlit leaf area index
+ real(r8), intent(in) :: laisha ! Shaded leaf area index
+ real(r8), intent(in) :: sai ! stem area index
+ real(r8), intent(in) :: htop ! canopy top [m]
+ real(r8), intent(in) :: tl ! leaf temperature
+ real(r8), intent(in) :: kmax_sun
+ real(r8), intent(in) :: kmax_sha
+ real(r8), intent(in) :: kmax_xyl
+ real(r8), intent(in) :: kmax_root
+ real(r8), intent(in) :: psi50_sun ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_sha ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_xyl ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_root ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8), intent(in) :: ck !
+ real(r8), intent(in) :: smp(nl_soil) ! soil matrix potential
+ real(r8), intent(in) :: k_soil_root(nl_soil) ! soil-root interface conductance [mm/s]
+ real(r8), intent(in) :: k_ax_root(nl_soil) ! root axial-direction conductance [mm/s]
+ real(r8), intent(out) :: gssun ! sunlit leaf conductance
+ real(r8), intent(out) :: gssha ! shaded leaf conductance
+
+
+ real(r8) :: wtl ! water conductance for leaf [m/s]
+ real(r8) :: A(nvegwcs,nvegwcs) ! matrix relating d(vegwp) and f: d(vegwp)=A*f
+ real(r8) :: f(nvegwcs) ! flux divergence (mm/s)
+ real(r8) :: dx(nvegwcs) ! change in vegwp from one iter to the next [mm]
+ real(r8) :: qflx_sun ! [kg/m2/s]
+ real(r8) :: qflx_sha ! [kg/m2/s]
+ real(r8) :: qeroot,dqeroot
+ real(r8),dimension(nl_soil) :: xroot ! local gs_mol copies
+ integer :: i,j ! index
+ real(r8) :: cf ! s m**2/umol -> s/m
+ integer :: iter,iterqflx ! newton's method iteration number
+ logical :: flag ! signal that matrix was not invertible
+ logical :: night ! signal to store vegwp within this routine, b/c it is night-time and full suite won't be called
+ integer, parameter :: itmax=50 ! EXIT newton's method IF iters>itmax
+ real(r8),parameter :: toldx=1.e-9 !tolerances for a satisfactory solution
+ real(r8),parameter :: tolf = 1.e-6_r8
+ real(r8),parameter :: tolf_leafxyl = 1.e-16_r8
+ real(r8),parameter :: tolf_root = 1.e-14_r8 !tolerances for a satisfactory solution
+ logical :: havegs ! signals direction of calculation gs->qflx or qflx->gs
+ logical :: haroot ! signals direction of calculation x_root_top->qeroot or qeroot->x_root_top
+ real(r8) :: soilflux ! total soil column transpiration [mm/s]
+ real(r8) :: x_root_top
+ real(r8) :: x_root_top1
+ real(r8) :: x_root_top2
+ real(r8) :: dxsoiltop
+ real(r8) :: maxscale
+ real(r8), parameter :: tol_lai=1.e-7_r8 ! minimum lai WHERE transpiration is calc'd
+ integer, parameter :: leafsun=1
+ integer, parameter :: leafsha=2
+ integer, parameter :: xyl=3
+ integer, parameter :: root=4
+ real(r8) fsto1,fsto2,fx,fr,grav1
+ real(r8) tprcor
+ !------------------------------------------------------------------------------
+
+ !temporary flag for night time vegwp(sun)>0
+
+ gssun=gs0sun
+ gssha=gs0sha
+ CALL getqflx_gs2qflx_twoleaf(gb_mol,gssun,gssha,qflx_sun,qflx_sha,qsatl,qaf,&
+ rhoair,psrf,laisun,laisha,sai,fwet,tl,rss,raw,rd,qg,qm)
+ x_root_top = x(root)
+
+ IF(qflx_sun .gt. 0 .or. qflx_sha .gt. 0)THEN
+ CALL getrootqflx_x2qe(nl_soil,smp,x_root_top ,z_soi,k_soil_root,k_ax_root,qeroot,dqeroot)
+
+ CALL spacAF_twoleaf(x,nvegwcs,dx,nl_soil,qflx_sun,qflx_sha,laisun,laisha,sai,htop,&
+ qeroot,dqeroot,kmax_sun,kmax_sha,kmax_xyl,kmax_root,&
+ psi50_sun,psi50_sha,psi50_xyl,psi50_root,ck)
+
+ IF ( maxval(abs(dx)) > 200000._r8) THEN
+ maxscale = min(maxval(abs(dx)),maxval(abs(x))) / 2
+ dx = maxscale * dx / maxval(abs(dx))! * log(maxval(abs(dx))/maxscale) !rescale step to max of 50000
+ ENDIF
+
+ x=x+dx
+
+ ! this is a catch to force spac gradient to atmosphere
+ IF ( x(xyl) > x(root) ) x(xyl) = x(root)
+ IF ( x(leafsun) > x(xyl) ) x(leafsun) = x(xyl)
+ IF ( x(leafsha) > x(xyl) ) x(leafsha) = x(xyl)
+
+ ! compute attenuated flux; the actual transpiration
+ etrsun=qflx_sun*plc(x(leafsun),psi50_sun,ck)
+ etrsha=qflx_sha*plc(x(leafsha),psi50_sha,ck)
+
+ ! retrieve stressed stomatal conductance
+ CALL getqflx_qflx2gs_twoleaf(gb_mol,gssun,gssha,etrsun,etrsha,qsatl,qaf,&
+ rhoair,psrf,laisun,laisha,sai,fwet,tl,rss,raw,rd,qg,qm)
+
+ tprcor = 44.6*273.16*psrf/1.013e5
+ ! compute water stress
+ ! .. generally -> B= gs_stressed / gs_unstressed
+ ! .. when gs=0 -> B= plc( x )
+ rstfacsun = amax1(gssun/gs0sun,1.e-2_r8)
+ rstfacsha = amax1(gssha/gs0sha,1.e-2_r8)
+ qeroot = etrsun + etrsha
+ CALL getrootqflx_qe2x(nl_soil,smp,z_soi,k_soil_root,k_ax_root,qeroot,xroot,x_root_top)
+ x(root) = x_root_top
+ DO j = 1,nl_soil
+ rootflux(j) = k_soil_root(j)*(smp(j)-xroot(j))
+ ENDDO
+ ELSE
+ IF ( x(xyl) > x(root) ) x(xyl) = x(root)
+ IF ( x(leafsun) > x(xyl) ) x(leafsun) = x(xyl)
+ IF ( x(leafsha) > x(xyl) ) x(leafsha) = x(xyl)
+ etrsun = 0._r8
+ etrsha = 0._r8
+ rstfacsun = amax1(plc(x(leafsun),psi50_sun,ck),1.e-2_r8)
+ rstfacsha = amax1(plc(x(leafsha),psi50_sha,ck),1.e-2_r8)
+ gssun = gs0sun * rstfacsun
+ gssha = gs0sha * rstfacsha
+ rootflux = 0._r8
+ ENDIF
+
+ soilflux = sum(rootflux(:))
+
+ END SUBROUTINE calcstress_twoleaf
+
+ !------------------------------------------------------------------------------
+ SUBROUTINE spacAF_twoleaf(x,nvegwcs,dx,nl_soil,qflx_sun,qflx_sha,laisun,laisha,sai,htop,&
+ qeroot,dqeroot,kmax_sun,kmax_sha,kmax_xyl,kmax_root,&
+ psi50_sun,psi50_sha,psi50_xyl,psi50_root,ck)
+!-----------------------------------------------------------------------
+! !DESCRIPTION
+! Returns invA, the inverse matrix relating delta(vegwp) to f
+! d(vegwp)=invA*f
+! evaluated at vegwp(p)
+!
+! The methodology is currently hardcoded for linear algebra assuming the
+! number of vegetation segments is four. Thus the matrix A and it's inverse
+! invA are both 4x4 matrices. A more general method could be done using for
+! example a LINPACK linear algebra solver.
+!
+!-----------------------------------------------------------------------
+! !ARGUMENTS:
+ integer , intent(in) :: nvegwcs
+ real(r8), intent(in) :: x(nvegwcs) ! working copy of veg water potential for patch p [mm H2O]
+ real(r8), intent(out) :: dx(nvegwcs) ! matrix relating d(vegwp) and f: d(vegwp)=invA*f
+ integer , intent(in) :: nl_soil
+ real(r8), intent(in) :: qflx_sun ! Sunlit leaf transpiration [kg/m2/s]
+ real(r8), intent(in) :: qflx_sha ! Shaded leaf transpiration [kg/m2/s]
+ real(r8), intent(in) :: laisun ! Sunlit leaf area index
+ real(r8), intent(in) :: laisha ! Shaded leaf area index
+ real(r8), intent(in) :: sai ! Stem area index
+ real(r8), intent(in) :: htop ! Canopy top [m]
+ real(r8), intent(in) :: qeroot ! soil-root interface conductance [mm/s]
+ real(r8), intent(in) :: dqeroot ! soil-root interface conductance [mm/s]
+ real(r8), intent(in) :: kmax_sun
+ real(r8), intent(in) :: kmax_sha
+ real(r8), intent(in) :: kmax_xyl
+ real(r8), intent(in) :: kmax_root
+ real(r8), intent(in) :: psi50_sun ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_sha ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_xyl ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_root ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8), intent(in) :: ck
+ !
+ ! !LOCAL VARIABLES:
+ real(r8) wtl ! heat conductance for leaf [m/s]
+ real(r8) fsto1 ! sunlit transpiration reduction function [-]
+ real(r8) fsto2 ! shaded transpiration reduction function [-]
+ real(r8) fx ! fraction of maximum conductance, xylem-to-leaf [-]
+ real(r8) fr ! fraction of maximum conductance, root-to-xylem [-]
+ real(r8) dfsto1 ! 1st derivative of fsto1 w.r.t. change in vegwp
+ real(r8) dfsto2 ! 1st derivative of fsto2 w.r.t. change in vegwp
+ real(r8) dfx ! 1st derivative of fx w.r.t. change in vegwp
+ real(r8) dfr ! 1st derivative of fr w.r.t. change in vegwp
+ real(r8) A11, A13, A22, A23, A31, A32, A33, A34, A43, A44 ! matrix relating vegwp to flux divergence f=A*d(vegwp)
+ real(r8) leading ! inverse of determiniant
+ real(r8) determ ! determinant of matrix
+ real(r8) grav1 ! gravitational potential surface to canopy top (mm H2O)
+ real(r8) invfactor !
+ real(r8) f(nvegwcs)
+ real(r8), parameter :: tol_lai=1.e-7_r8 ! minimum lai WHERE transpiration is calc'd
+ integer, parameter :: leafsun=1
+ integer, parameter :: leafsha=2
+ integer, parameter :: xyl=3
+ integer, parameter :: root=4
+ integer :: j ! index
+ !------------------------------------------------------------------------------
+
+ grav1 = htop*1000._r8
+
+ !compute conductance attenuation for each segment
+ fsto1 = plc(x(leafsun),psi50_sun,ck)
+ fsto2 = plc(x(leafsha),psi50_sha,ck)
+ fx = plc(x(xyl),psi50_xyl,ck)
+ fr = plc(x(root),psi50_root,ck)
+
+ !compute 1st deriv of conductance attenuation for each segment
+ dfsto1 = d1plc(x(leafsun),psi50_sun,ck)
+ dfsto2 = d1plc(x(leafsha),psi50_sha,ck)
+ dfx = d1plc(x(xyl),psi50_xyl,ck)
+ dfr = d1plc(x(root),psi50_root,ck)
+
+
+ A11 = - laisun * kmax_sun * fx - qflx_sun * dfsto1
+ A13 = laisun * kmax_sun * dfx * (x(xyl)-x(leafsun)) + laisun * kmax_sun * fx
+ A22 = - laisha * kmax_sha * fx - qflx_sha * dfsto2
+ A23 = laisha * kmax_sha * dfx * (x(xyl)-x(leafsha)) + laisha * kmax_sha * fx
+ A31 = laisun * kmax_sun * fx
+ A32 = laisha * kmax_sha * fx
+ A33 = - laisun * kmax_sun * dfx * (x(xyl)-x(leafsun)) - laisun * kmax_sun * fx&
+ - laisha * kmax_sha * dfx * (x(xyl)-x(leafsha)) - laisha * kmax_sha * fx&
+ - sai * kmax_xyl / htop * fr
+ A34 = sai * kmax_xyl / htop * dfr * (x(root)-x(xyl)-grav1) + sai * kmax_xyl / htop * fr
+ A43 = sai * kmax_xyl / htop * fr
+ A44 = - sai * kmax_xyl / htop * fr&
+ - sai * kmax_xyl / htop * dfr * (x(root)-x(xyl)-grav1) + dqeroot
+
+ !compute flux divergence across each plant segment
+ f(leafsun) = qflx_sun * fsto1 - laisun * kmax_sun * fx * (x(xyl)-x(leafsun))
+ f(leafsha) = qflx_sha * fsto2 - laisha * kmax_sha * fx * (x(xyl)-x(leafsha))
+ f(xyl) = laisun * kmax_sun * fx * (x(xyl)-x(leafsun))&
+ + laisha * kmax_sha * fx * (x(xyl)-x(leafsha)) &
+ - sai * kmax_xyl / htop * fr * (x(root)-x(xyl)-grav1)
+ f(root) = sai * kmax_xyl / htop * fr * (x(root)-x(xyl)-grav1) - qeroot
+
+ IF(qflx_sha > 0 )THEN
+ determ=A44*A22*A33*A11-A44*A22*A31*A13-A44*A32*A23*A11-A43*A11*A22*A34
+
+ IF(determ .ne. 0)THEN
+ dx(leafsun) = ((A22*A33*A44 - A22*A34*A43 - A23*A32*A44)*f(leafsun) + A13*A32*A44*f(leafsha) &
+ - A13*A22*A44*f(xyl) + A13*A22*A34*f(root)) / determ
+ dx(leafsha) = ( A23*A31*A44*f(leafsun) + (A11*A33*A44 - A11*A34*A43 - A13*A31*A44)*f(leafsha) &
+ - A11*A23*A44*f(xyl) + A11*A23*A34*f(root)) / determ
+ dx(xyl) = (-A22*A31*A44*f(leafsun) - A11*A32*A44*f(leafsha) &
+ + A11*A22*A44*f(xyl) - A11*A22*A34*f(root)) / determ
+ dx(root) = ( A22*A31*A43*f(leafsun) + A11*A32*A43*f(leafsha) &
+ - A11*A22*A43*f(xyl) +(A11*A22*A33 - A11*A23*A32 - A13*A22*A31)*f(root)) / determ
+ ELSE
+ dx = 0._r8
+ ENDIF
+ ELSE
+ A33 = - laisun * kmax_sun * dfx * (x(xyl)-x(leafsun)) - laisun * kmax_sun * fx - sai * kmax_xyl / htop * fr
+ f(xyl) = laisun * kmax_sun * fx * (x(xyl)-x(leafsun)) - sai * kmax_xyl / htop * fr * (x(root)-x(xyl)-grav1)
+ determ=A11*A33*A44-A34*A11*A43-A13*A31*A44
+ IF(determ .ne. 0)THEN
+ dx(leafsun) = (- A13*A44*f(xyl) + A13*A34*f(root) + (A33*A44 - A34*A43)*f(leafsun)) / determ
+ dx(xyl) = ( A11*A44*f(xyl) - A11*A34*f(root) - A31*A44*f(leafsun)) / determ
+ dx(root) = (- A11*A43*f(xyl) + (A11*A33 - A13*A31)*f(root) + A31*A43*f(leafsun)) / determ
+
+ dx(leafsha) = x(leafsun) - x(leafsha) + dx(leafsun)
+ ELSE
+ dx = 0._r8
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE spacAF_twoleaf
+
+ SUBROUTINE getvegwp_twoleaf(x, nvegwcs, nl_soil, z_soi, gb_mol, gs_mol_sun, gs_mol_sha, &
+ qsatl, qaf,qg,qm,rhoair, psrf, fwet, laisun, laisha, htop, sai, tl, rss, &
+ raw, rd, smp, k_soil_root, k_ax_root, kmax_xyl, kmax_root, rstfacsun, rstfacsha, &
+ psi50_sun, psi50_sha, psi50_xyl, psi50_root, ck, rootflux, etrsun, etrsha)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculates transpiration and returns corresponding vegwp in x
+!
+! !USES:
+! calls getqflx
+!-----------------------------------------------------------------------
+ USE MOD_Const_Physical, only: tfrz
+ IMPLICIT NONE
+ !
+ ! !ARGUMENTS:
+ integer, intent(in) :: nvegwcs
+ real(r8), intent(out) :: x(nvegwcs) ! working copy of veg water potential for patch p
+ integer, intent(in) :: nl_soil ! number of soil layers
+ real(r8), intent(in) :: z_soi(nl_soil) ! node depth [m]
+ real(r8), intent(in) :: gb_mol ! Leaf boundary layer conductance [umol H2O/m**2/s]
+ real(r8), intent(inout) :: gs_mol_sun ! Ball-Berry leaf conductance [umol H2O/m**2/s]
+ real(r8), intent(inout) :: gs_mol_sha ! Ball-Berry leaf conductance [umol H2O/m**2/s]
+ real(r8), intent(in) :: qsatl ! Sunlit leaf specific humidity [kg/kg]
+ real(r8), intent(in) :: qaf ! humidity of canopy air [kg/kg]
+ real(r8), intent(in) :: qg ! specific humidity at ground surface [kg/kg]
+ real(r8), intent(in) :: qm ! specific humidity at reference height [kg/kg]
+ real(r8), intent(in) :: rhoair ! density [kg/m**3]
+ real(r8), intent(in) :: psrf ! atmospheric pressure [Pa]
+ real(r8), intent(in) :: fwet ! fraction of foliage that is green and dry [-]
+ real(r8), intent(in) :: laisun ! Sunlit leaf area index
+ real(r8), intent(in) :: laisha ! Shaded leaf area index
+ real(r8), intent(in) :: htop ! canopy top [m]
+ real(r8), intent(in) :: sai ! stem area index
+ real(r8), intent(in) :: tl ! leaf temperature
+ real(r8), intent(in) :: kmax_xyl
+ real(r8), intent(in) :: kmax_root
+ real(r8), intent(in) :: rstfacsun
+ real(r8), intent(in) :: rstfacsha
+ real(r8), intent(in) :: psi50_sun ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_sha ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_xyl ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ real(r8), intent(in) :: psi50_root ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8), intent(in) :: ck !
+ real(r8), intent(in) :: rss ! soil surface resistance [s/m]
+ real(r8), intent(in) :: raw ! moisture resistance [s/m]
+ real(r8), intent(in) :: rd ! aerodynamical resistance between ground and canopy air
+ real(r8), intent(in) :: smp(nl_soil) ! soil matrix potential
+ real(r8), intent(in) :: k_soil_root(nl_soil) ! soil-root interface conductance [mm/s]
+ real(r8), intent(in) :: k_ax_root(nl_soil) ! root axial-direction conductance [mm/s]
+ real(r8), intent(out) :: etrsun ! transpiration from sunlit leaf (mm/s)
+ real(r8), intent(out) :: etrsha ! transpiration from shaded leaf (mm/s)
+ real(r8), intent(out) :: rootflux(nl_soil) ! root water uptake from different layers
+ !
+ ! !LOCAL VARIABLES:
+! real(r8) qflx_sun ! Sunlit leaf transpiration [kg/m2/s]
+! real(r8) qflx_sha ! Shaded leaf transpiration [kg/m2/s]
+ real(r8) qeroot
+ real(r8) dummy
+ real(r8) fx ! fraction of maximum conductance, xylem-to-leaf [-]
+ real(r8) fr ! fraction of maximum conductance, root-to-xylem [-]
+ real(r8) x_root_top
+ real(r8) xroot(nl_soil)
+ real(r8) grav1 ! gravitational potential surface to canopy top (mm H2O)
+ real(r8) grav2(nl_soil) ! soil layer gravitational potential relative to surface (mm H2O)
+ integer j ! index
+ logical havegs ! signals direction of calculation gs->qflx or qflx->gs
+ logical haroot ! signals direction of calculation x_root_top->qeroot or qeroot->x_root_top
+ integer, parameter :: leafsun=1
+ integer, parameter :: leafsha=2
+ integer, parameter :: xyl=3
+ integer, parameter :: root=4
+ real(r8) :: soilflux ! total soil column transpiration [mm/s]
+
+ !----------------------------------------------------------------------
+ grav1 = 1000._r8 * htop
+ grav2(1:nl_soil) = 1000._r8 * z_soi(1:nl_soil)
+
+ !compute transpiration demand
+ havegs=.true.
+ CALL getqflx_gs2qflx_twoleaf(gb_mol,gs_mol_sun,gs_mol_sha,etrsun,etrsha,qsatl,qaf, &
+ rhoair,psrf,laisun,laisha,sai,fwet,tl,rss,raw,rd,qg,qm,rstfacsun,rstfacsha)
+
+ !calculate root water potential
+ qeroot = etrsun + etrsha
+
+ CALL getrootqflx_qe2x(nl_soil,smp,z_soi,k_soil_root,k_ax_root,qeroot,xroot,x_root_top)
+ x(root) = x_root_top
+
+ !calculate xylem water potential
+ fr = plc(x(root),psi50_root,ck)
+ x(xyl) = x(root) - grav1 - (etrsun+etrsha)/(fr*kmax_root/htop*sai)
+
+ !calculate sun/sha leaf water potential
+ fx = plc(x(xyl),psi50_xyl,ck)
+ x(leafsha) = x(xyl) - (etrsha/(fx*kmax_xyl*laisha))
+ x(leafsun) = x(xyl) - (etrsun/(fx*kmax_xyl*laisun))
+
+
+ !calculate soil flux
+ DO j = 1,nl_soil
+ rootflux(j) = k_soil_root(j)*(smp(j)-xroot(j))
+ ENDDO
+
+ soilflux = sum(rootflux(:))
+
+ END SUBROUTINE getvegwp_twoleaf
+
+ SUBROUTINE getqflx_gs2qflx_twoleaf(gb_mol,gs_mol_sun,gs_mol_sha,qflx_sun,qflx_sha,qsatl,qaf,&
+ rhoair,psrf,laisun,laisha,sai,fwet,tl,rss,raw,rd,qg,qm,rstfacsun,rstfacsha)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! calculate sunlit and shaded transpiration using gb_MOL and gs_MOL
+!
+!-----------------------------------------------------------------------
+ IMPLICIT NONE
+
+ ! !ARGUMENTS:
+ real(r8), intent(in) :: gb_mol ! leaf boundary layer conductance (mol H2O/m**2/s), leaf scale
+ real(r8), intent(inout) :: gs_mol_sun ! Ball-Berry leaf conductance (mol H2O/m**2/s), leaf scale
+ real(r8), intent(inout) :: gs_mol_sha ! Ball-Berry leaf conductance (mol H2O/m**2/s), leaf scale
+ real(r8), intent(inout) :: qflx_sun ! Sunlit leaf transpiration [kg/m2/s]
+ real(r8), intent(inout) :: qflx_sha ! Shaded leaf transpiration [kg/m2/s]
+ real(r8), intent(in) :: qsatl ! leaf specific humidity [kg/kg]
+ real(r8), intent(in) :: qaf ! humidity of canopy air [kg/kg]
+ real(r8), intent(in) :: qg ! specific humidity at ground surface [kg/kg]
+ real(r8), intent(in) :: qm ! specific humidity at reference height [kg/kg]
+ real(r8), intent(in) :: rhoair ! density (kg/m**3)
+ real(r8), intent(in) :: psrf ! atmospheric pressure (Pa)
+ real(r8), intent(in) :: laisun ! sunlit leaf area index (m2/m2)
+ real(r8), intent(in) :: laisha ! shaded leaf area index (m2/m2)
+ real(r8), intent(in) :: sai ! stem area index (m2/m2)
+ real(r8), intent(in) :: fwet ! fraction of foliage that is green and dry [-]
+ real(r8), intent(in) :: tl ! shaded leaf temperature
+ real(r8), intent(in) :: rss ! soil surface resistance [s/m]
+ real(r8), intent(in) :: raw ! moisture resistance [s/m]
+ real(r8), intent(in) :: rd ! aerodynamical resistance between ground and canopy air
+ real(r8),optional, intent(in) :: rstfacsun
+ real(r8),optional, intent(in) :: rstfacsha
+
+ !
+ ! !LOCAL VARIABLES:
+ real(r8) cf ! (umol/m**3) r = cf./g gmol(umol/m**2/s) -> r(s/m)
+ real(r8) tprcor ! tf*psur*100./1.013e5
+
+ real(r8) wtaq0 ! normalized latent heat conductance for air [-]
+ real(r8) wtgq0 ! normalized latent heat conductance for ground [-]
+ real(r8) wtlq0 ! normalized latent heat cond. for air and sunlit leaf [-]
+ real(r8) wtsqi ! latent heat resistance for air, grd and leaf [-]
+
+ real(r8) delta
+ real(r8) caw ! latent heat conductance for air [m/s]
+ real(r8) cgw ! latent heat conductance for ground [m/s]
+ real(r8) cfw ! latent heat conductance for leaf [m/s]
+
+ !----------------------------------------------------------------------
+ tprcor = 44.6*273.16*psrf/1.013e5
+ cf = tprcor/tl * 1.e6_r8 ! gb->gbmol conversion factor
+
+ delta = 0.0
+ IF(qsatl-qaf .gt. 0.) delta = 1.0
+
+ caw = 1. / raw
+ IF (qg < qaf)THEN
+ cgw = 1. / rd
+ ELSE
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ cgw = rss / rd
+ ELSE
+ cgw = 1. / (rd + rss)
+ ENDIF
+ ENDIF
+ cfw = (1.-delta*(1.-fwet)) * (laisun+laisha+sai)*gb_mol/cf + (1.-fwet)*delta*&
+ (laisun/(1._r8/gb_mol+1._r8/gs_mol_sun)/cf+laisha/(1._r8/gb_mol+1._r8/gs_mol_sha)/cf)
+ wtsqi = 1. / ( caw + cgw + cfw )
+
+ wtaq0 = caw * wtsqi
+ wtgq0 = cgw * wtsqi
+ wtlq0 = cfw * wtsqi
+
+ qflx_sun = rhoair * (1.-fwet) * delta &
+ * laisun / (1./gb_mol+1./gs_mol_sun)/cf &
+ * ( (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg )
+! IF(qflx_sun < 1.e-7_r8)THEN
+! qflx_sun = 0._r8
+! ENDIF
+ IF(present(rstfacsun))THEN
+ IF(rstfacsun .le. 1.e-2)qflx_sun = 0._r8
+ ENDIF
+ qflx_sha = rhoair * (1.-fwet) * delta &
+ * laisha / (1./gb_mol+1./gs_mol_sha)/cf &
+ * ( (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg )
+! IF(qflx_sha < 1.e-7)THEN
+! qflx_sha = 0._r8
+! ENDIF
+ IF(present(rstfacsha))THEN
+ IF(rstfacsha .le. 1.e-2)qflx_sha = 0._r8
+ ENDIF
+
+ END SUBROUTINE getqflx_gs2qflx_twoleaf
+
+ SUBROUTINE getqflx_qflx2gs_twoleaf(gb_mol,gs_mol_sun,gs_mol_sha,qflx_sun,qflx_sha,qsatl,qaf, &
+ rhoair,psrf,laisun,laisha,sai,fwet,tl,rss,raw,rd,qg,qm)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! calculate sunlit and shaded transpiration using gb_MOL and gs_MOL
+!-----------------------------------------------------------------------
+ IMPLICIT NONE
+
+ ! !ARGUMENTS:
+ real(r8), intent(in) :: gb_mol ! leaf boundary layer conductance (mol H2O/m**2/s), leaf scale
+ real(r8), intent(inout) :: gs_mol_sun ! Ball-Berry leaf conductance (mol H2O/m**2/s), leaf scale
+ real(r8), intent(inout) :: gs_mol_sha ! Ball-Berry leaf conductance (mol H2O/m**2/s), leaf scale
+ real(r8), intent(inout) :: qflx_sun ! Sunlit leaf transpiration [kg/m2/s]
+ real(r8), intent(inout) :: qflx_sha ! Shaded leaf transpiration [kg/m2/s]
+ real(r8), intent(in) :: qsatl ! leaf specific humidity [kg/kg]
+ real(r8), intent(in) :: qaf ! humidity of canopy air [kg/kg]
+ real(r8), intent(in) :: qg ! specific humidity at ground surface [kg/kg]
+ real(r8), intent(in) :: qm ! specific humidity at reference height [kg/kg]
+ real(r8), intent(in) :: rhoair ! density (kg/m**3)
+ real(r8), intent(in) :: psrf ! atmospheric pressure (Pa)
+ real(r8), intent(in) :: laisun ! sunlit leaf area index (m2/m2)
+ real(r8), intent(in) :: laisha ! shaded leaf area index (m2/m2)
+ real(r8), intent(in) :: sai ! stem area index (m2/m2)
+ real(r8), intent(in) :: fwet ! fraction of foliage that is green and dry [-]
+ real(r8), intent(in) :: tl ! leaf temperature
+ real(r8), intent(in) :: rss ! soil surface resistance [s/m]
+ real(r8), intent(in) :: raw ! moisture resistance [s/m]
+ real(r8), intent(in) :: rd ! aerodynamical resistance between ground and canopy air
+
+ !
+ ! !LOCAL VARIABLES:
+ real(r8) wtlsun ! heat conductance for sunlit leaf boundary [m/s]
+ real(r8) wtlsha ! heat conductance for shaded leaf boundary [m/s]
+ real(r8) cf ! s m**2/umol -> s/m
+ real(r8) tprcor !tf*psur*100./1.013e5
+
+ real(r8) wtaq0 ! normalized latent heat conductance for air [-]
+ real(r8) wtgq0 ! normalized latent heat conductance for ground [-]
+ real(r8) wtlsunq0 ! normalized latent heat cond. for air and sunlit leaf [-]
+ real(r8) wtlshaq0 ! normalized latent heat cond. for air and shaded leaf [-]
+
+ real(r8) delta
+ real(r8) caw ! latent heat conductance for air [m/s]
+ real(r8) cgw ! latent heat conductance for ground [m/s]
+ real(r8) cwet ! latent heat conductance for wet leaf [m/s]
+ real(r8) csunw_dry ! latent heat conductance for sunlit dry leaf [m/s]
+ real(r8) cshaw_dry ! latent heat conductance for shaded dry leaf [m/s]
+ real(r8) cqi_wet ! latent heat conductance for air, grd and wet leaf [-]
+ real(r8) cqi_leaf ! (wtaq0 + wtgq0)*qsatl - wtaq0*qm - wtgq0*qg [m/s]
+ real(r8) A1,B1,C1,A2,B2,C2 ! in binary quadratic equations
+
+ !----------------------------------------------------------------------
+ IF(qflx_sun .gt. 0 .or. qflx_sha .gt. 0)THEN
+ tprcor = 44.6*273.16*psrf/1.013e5
+ cf = tprcor/tl * 1.e6_r8 ! gb->gbmol conversion factor
+
+ delta = 0.0
+ IF(qsatl-qaf .gt. 0.) delta = 1.0
+
+ caw = 1. / raw
+ IF (qg < qaf)THEN
+ cgw = 1. / rd
+ ELSE
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ cgw = rss / rd
+ ELSE
+ cgw = 1. / (rd + rss)
+ ENDIF
+ ENDIF
+ cwet = (1.-delta*(1.-fwet)) * (laisun + laisha + sai) * gb_mol / cf
+ cqi_wet = caw + cgw + cwet
+ cqi_leaf = caw * (qsatl - qm) + cgw * (qsatl - qg)
+
+ ! Solve equations:
+ ! A1 * csunw_dry + B1 * cfshaw_dry = C1
+ ! A2 * csunw_dry + B2 * cfshaw_dry = C2
+
+ A1 = cqi_leaf - qflx_sun / rhoair
+ B1 = - qflx_sun / rhoair
+ C1 = qflx_sun * cqi_wet / rhoair
+ A2 = - qflx_sha / rhoair
+ B2 = cqi_leaf - qflx_sha / rhoair
+ C2 = qflx_sha * cqi_wet / rhoair
+
+ csunw_dry = (B1*C2 - B2*C1)/(B1*A2 - B2*A1)
+ cshaw_dry = (A1*C2 - A2*C1)/(A1*B2 - B1*A2)
+
+ IF (qflx_sun > 0._r8) THEN
+ gs_mol_sun = 1._r8 / ((1. - fwet) * delta * laisun / csunw_dry / cf - 1._r8 / gb_mol)
+ ENDIF
+ IF (qflx_sha > 0._r8) THEN
+ gs_mol_sha = 1._r8 / ((1. - fwet) * delta * laisha / cshaw_dry / cf - 1._r8 / gb_mol)
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE getqflx_qflx2gs_twoleaf
+
+ SUBROUTINE getrootqflx_x2qe(nl_soil,smp,x_root_top,z_soisno,krad,kax,qeroot,dqeroot)
+
+ USE MOD_Utils
+!-----------------------------------------------------------------------
+! !DESCRIPTION
+! Return root water potential at top soil node. Return soil-root water flux.
+!
+!-----------------------------------------------------------------------
+
+ integer , intent(in) :: nl_soil
+ real(r8), intent(in) :: smp (nl_soil)
+ real(r8), intent(in) :: x_root_top
+ real(r8), intent(in) :: z_soisno (nl_soil)
+ real(r8), intent(in) :: krad (nl_soil)
+ real(r8), intent(in) :: kax (nl_soil)
+ real(r8), intent(out) :: qeroot
+ real(r8), intent(out) :: dqeroot
+
+! Local variables
+ real(r8) den_AHR,den1,den2 ! used in calculating HR(Amenu model)
+ real(r8) amx_hr(nl_soil-1) ! "a" left off diagonal of tridiagonal matrix
+ real(r8) bmx_hr(nl_soil-1) ! "b" diagonal column for tridiagonal matrix
+ real(r8) cmx_hr(nl_soil-1) ! "c" right off diagonal tridiagonal matrix
+ real(r8) rmx_hr(nl_soil-1) ! "r" forcing term of tridiagonal matrix
+ real(r8) drmx_hr(nl_soil-1) ! "dr" forcing term of tridiagonal matrix for d/dxroot(1)
+ real(r8) x(nl_soil-1) ! root water potential from layer 2 to nl_soil
+ real(r8) dx(nl_soil-1) ! derivate of root water potential from layer 2 to nl_soil (dxroot(:)/dxroot(1))
+ real(r8) xroot(nl_soil) ! root water potential from layer 2 to nl_soil
+ real(r8) zmm(1:nl_soil) ! layer depth [mm]
+ real(r8) qeroot_nl(1:nl_soil) ! root water potential from layer 2 to nl_soil
+ real(r8) dxroot2 ! dxroot(2)/dxroot(1)
+ integer j
+
+ ! Because the depths in this routine are in mm, USE local
+ ! variable arrays instead of pointers
+ DO j = 1, nl_soil
+ zmm(j) = z_soisno(j)*1000.
+ ENDDO
+
+ xroot(1) = x_root_top + zmm(1)
+ ! For the 2nd soil layer
+ j = 2
+ den1 = zmm(j) - zmm(j-1)
+ den2 = zmm(j+1) - zmm(j)
+ amx_hr(j-1) = 0
+ bmx_hr(j-1) = kax(j-1)/den1 + kax(j)/den2 + krad(j)
+ cmx_hr(j-1) = -kax(j)/den2
+ rmx_hr(j-1) = krad(j)*smp(j) + kax(j-1) - kax(j) + kax(j-1)/den1*xroot(1)
+ drmx_hr(j-1) = kax(j-1)/den1
+
+ ! For the middile soil layers
+ DO j = 3, nl_soil - 1
+ den1 = zmm(j) - zmm(j-1)
+ den2 = zmm(j+1) - zmm(j)
+ amx_hr (j-1) = -kax(j-1)/den1
+ bmx_hr (j-1) = kax(j-1)/den1 + kax(j)/den2 + krad(j)
+ cmx_hr (j-1) = -kax(j)/den2
+ rmx_hr (j-1) = krad(j)*smp(j) + kax(j-1) - kax(j)
+ drmx_hr(j-1) = 0._r8
+ ENDDO
+
+ ! For the bottom soil layer
+ j = nl_soil
+ den_AHR = zmm(j) - zmm(j-1)
+ amx_hr (j-1) = -kax(j-1)/den_AHR
+ bmx_hr (j-1) = kax(j-1)/den_AHR + krad(j)
+ cmx_hr (j-1) = 0
+ rmx_hr (j-1) = krad(j)*smp(j) + kax(j-1)
+ drmx_hr(j-1) = 0._r8
+
+ ! Solve for root pressure potential using tridiagonal matric solver x = A^-1 * r
+ CALL tridia (nl_soil-1 ,amx_hr ,bmx_hr ,cmx_hr ,rmx_hr ,x)
+
+ DO j = 2,nl_soil
+ xroot(j) = x(j-1)
+ ENDDO
+
+ ! Solve the dx(:)/dxroot(1) = A^-1 * dr
+ CALL tridia (nl_soil-1 ,amx_hr ,bmx_hr ,cmx_hr ,drmx_hr, dx)
+
+ dxroot2 = dx(1)
+
+ ! calculate the water flux
+ j = 1
+ den2 = zmm(j+1) - zmm(j)
+ qeroot = krad(j) * (smp(1) - xroot(1)) + (xroot(2) - xroot(1)) * kax(j)/den2 - kax(j)
+
+ ! calculate the dqeroot/dx_root_top;
+ dqeroot = - krad(j) + (dxroot2 - 1) * kax(j)/den2
+ DO j = 1,nl_soil
+ qeroot_nl(j) = krad(j)*(smp(j) - xroot(j))
+ ENDDO
+
+ END SUBROUTINE getrootqflx_x2qe
+
+ SUBROUTINE getrootqflx_qe2x(nl_soil,smp,z_soisno,krad,kax,qeroot,xroot,x_root_top)
+
+ USE MOD_Utils
+!-----------------------------------------------------------------------
+! !DESCRIPTION
+! Return root water potential at top soil node. Return soil-root water flux.
+!-----------------------------------------------------------------------
+
+ integer, intent(in) :: nl_soil
+ real(r8), intent(in) :: smp (nl_soil)
+ real(r8), intent(in) :: z_soisno (nl_soil)
+ real(r8), intent(in) :: krad (nl_soil)
+ real(r8), intent(in) :: kax (nl_soil)
+ real(r8), intent(in) :: qeroot
+ real(r8), intent(out) :: xroot (nl_soil)
+ real(r8), intent(out) :: x_root_top
+
+! Local variables
+ real(r8) den_AHR,den1,den2 ! used in calculating HR(Amenu model)
+ real(r8) amx_hr(nl_soil) ! "a" left off diagonal of tridiagonal matrix
+ real(r8) bmx_hr(nl_soil) ! "b" diagonal column for tridiagonal matrix
+ real(r8) cmx_hr(nl_soil) ! "c" right off diagonal tridiagonal matrix
+ real(r8) rmx_hr(nl_soil) ! "r" forcing term of tridiagonal matrix
+ real(r8) x(nl_soil) ! root water potential from layer 2 to nl_soil
+ real(r8) zmm(1:nl_soil) ! layer depth [mm]
+ real(r8) qeroot_nl(1:nl_soil) ! root water potential from layer 2 to nl_soil
+ integer j
+
+ ! Because the depths in this routine are in mm, USE local
+ ! variable arrays instead of pointers
+ DO j = 1, nl_soil
+ zmm(j) = z_soisno(j)*1000.
+ ENDDO
+
+ j = 1
+ den2 = zmm(j+1) - zmm(j)
+ amx_hr(j) = 0
+ bmx_hr(j) = kax(j)/den2 + krad(j)
+ cmx_hr(j) = -kax(j)/den2
+ rmx_hr(j) = krad(j)*smp(j) - qeroot - kax(j)
+
+ ! For the middile soil layers
+ DO j = 2, nl_soil - 1
+ den1 = zmm(j) - zmm(j-1)
+ den2 = zmm(j+1) - zmm(j)
+ amx_hr(j) = -kax(j-1)/den1
+ bmx_hr(j) = kax(j-1)/den1 + kax(j)/den2 + krad(j)
+ cmx_hr(j) = -kax(j)/den2
+ rmx_hr(j) = krad(j)*smp(j) + kax(j-1) - kax(j)
+ ENDDO
+
+ ! For the bottom soil layer
+ j = nl_soil
+ den_AHR = zmm(j) - zmm(j-1)
+ amx_hr(j) = -kax(j-1)/den_AHR
+ bmx_hr(j) = kax(j-1)/den_AHR + krad(j)
+ cmx_hr(j) = 0
+ rmx_hr(j) = krad(j)*smp(j) + kax(j-1)
+
+ ! Solve for root pressure potential using tridiagonal matric solver
+ CALL tridia (nl_soil ,amx_hr ,bmx_hr ,cmx_hr ,rmx_hr ,x)
+
+ xroot(1:nl_soil) = x(1:nl_soil)
+ x_root_top = xroot(1) - zmm(1)
+
+ END SUBROUTINE getrootqflx_qe2x
+
+ FUNCTION plc(x,psi50,ck)
+!-----------------------------------------------------------------------
+! !DESCRIPTION
+! Return value of vulnerability curve at x
+!
+!-----------------------------------------------------------------------
+
+! !ARGUMENTS
+ real(r8) , intent(in) :: x ! water potential input
+! integer , intent(in) :: level ! veg segment lvl (1:nvegwcs)
+! integer , intent(in) :: plc_method !
+ real(r8) , intent(in) :: psi50 ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_sun ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_sha ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_xyl ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_root ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8) , intent(in) :: ck
+ real(r8) :: plc ! attenuated conductance [0:1] 0=no flow
+ !
+ ! !PARAMETERS
+! integer , parameter :: vegetation_weibull=0 ! case number
+! integer , parameter :: leafsun = 1 ! index for sunlit leaf
+! integer , parameter :: leafsha = 2 ! index for shaded leaf
+! integer , parameter :: xyl = 3 ! index for xylem
+! integer , parameter :: root = 4 ! index for root
+
+ ! !LOCAL VARIABLES
+ !real(r8) psi50,tmp
+ real(r8) tmp
+ integer i
+
+ !------------------------------------------------------------------------------
+! select CASE(level)
+! CASE (leafsun)
+! psi50 = psi50_sun
+! CASE (leafsha)
+! psi50 = psi50_sha
+! CASE (xyl)
+! psi50 = psi50_xyl
+! CASE (root)
+! psi50 = psi50_root
+! CASE default
+! write(*,*),'must choose level from 1 to 4 (sunlit leaf to root)'
+! END select
+
+! select CASE (plc_method)
+ !possible to add other methods later
+! CASE (vegetation_weibull)
+ tmp = amax1(-(x/psi50)**ck,-500._r8)
+! IF(tmp .lt. -500._r8)THEN
+! plc = 0._r8
+! ELSE
+ plc=2._r8**tmp
+! ENDIF
+ IF ( plc < 0.00001_r8) plc = 1.e-5_r8
+! CASE default
+! write(*,*),'must choose plc method'
+! END select
+
+ END FUNCTION plc
+ !--------------------------------------------------------------------------------
+
+ FUNCTION d1plc(x,psi50,ck)
+!-----------------------------------------------------------------------
+! !DESCRIPTION
+! Return 1st derivative of vulnerability curve at x
+!-----------------------------------------------------------------------
+
+! !ARGUMENTS
+ real(r8) , intent(in) :: x ! water potential input
+! integer , intent(in) :: level ! veg segment lvl (1:nvegwcs)
+! integer , intent(in) :: plc_method ! 0 for vegetation, 1 for soil
+ real(r8) , intent(in) :: psi50 ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_sun ! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_sha ! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_xyl ! water potential at 50% loss of xylem tissue conductance (mmH2O)
+! real(r8) , intent(in) :: psi50_root ! water potential at 50% loss of root tissue conductance (mmH2O)
+ real(r8) , intent(in) :: ck
+ real(r8) :: d1plc ! first deriv of plc curve at x
+ !
+ ! !PARAMETERS
+! integer , parameter :: vegetation_weibull=0 ! CASE number
+! integer , parameter :: leafsun = 1 ! index for sunlit leaf
+! integer , parameter :: leafsha = 2 ! index for shaded leaf
+! integer , parameter :: xyl = 3 ! index for xylem
+! integer , parameter :: root = 4 ! index for root
+
+ ! !LOCAL VARIABLES
+! real(r8) psi50,tmp
+ real(r8) tmp
+ !------------------------------------------------------------------------------
+! select CASE(level)
+! CASE (leafsun)
+! psi50 = psi50_sun
+! CASE (leafsha)
+! psi50 = psi50_sha
+! CASE (xyl)
+! psi50 = psi50_xyl
+! CASE (root)
+! psi50 = psi50_root
+! CASE default
+! write(*,*),'must choose level from 1 to 4 (sunlit leaf to root)'
+! END select
+
+! select CASE (plc_method)
+ !possible to add other methods later
+! CASE (vegetation_weibull)
+ tmp = amax1(-(x/psi50)**ck,-500._r8)
+! IF(tmp .lt. -500._r8)THEN
+! d1plc = 0._r8
+! ELSE
+ d1plc= ck * log(2._r8) * (2._r8**tmp) * tmp / x
+! ENDIF
+! CASE default
+! write(*,*),'must choose plc method'
+! END select
+
+ END FUNCTION d1plc
+
+
+END MODULE MOD_PlantHydraulic
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Qsadv.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Qsadv.F90
new file mode 100644
index 0000000000..efc004e67c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Qsadv.F90
@@ -0,0 +1,108 @@
+MODULE MOD_Qsadv
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: qsadv
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE qsadv(T,p,es,esdT,qs,qsdT)
+
+!-----------------------------------------------------------------------
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! Description: computes saturation mixing ratio and change in saturation
+! mixing ratio with respect to temperature
+!
+! Reference: polynomial approximations from:
+! Piotr J. Flatau,et al,1992: polynomial fits to saturation
+! vapor pressure. Journal of Applied meteorology,31,1507-1513.
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: T ! temperature (K)
+ real(r8), intent(in) :: p ! surface atmospheric pressure (pa)
+
+ real(r8), intent(out) :: es ! vapor pressure (pa)
+ real(r8), intent(out) :: esdT ! d(es)/d(T)
+ real(r8), intent(out) :: qs ! humidity (kg/kg)
+ real(r8), intent(out) :: qsdT ! d(qs)/d(T)
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) td,vp,vp1,vp2
+ real(r8) a0,a1,a2,a3,a4,a5,a6,a7,a8
+ real(r8) b0,b1,b2,b3,b4,b5,b6,b7,b8
+
+ real(r8) c0,c1,c2,c3,c4,c5,c6,c7,c8
+ real(r8) d0,d1,d2,d3,d4,d5,d6,d7,d8
+
+! for water vapor (temperature range 0C-100C)
+ data a0/6.11213476 /,a1/ 0.444007856 /,a2/0.143064234e-01/ &
+ ,a3/0.264461437e-03/,a4/ 0.305903558e-05/,a5/0.196237241e-07/ &
+ ,a6/0.892344772e-10/,a7/-0.373208410e-12/,a8/0.209339997e-15/
+
+! for derivative:water vapor
+ data b0/0.444017302 /,b1/ 0.286064092e-01/,b2/ 0.794683137e-03/ &
+ ,b3/ 0.121211669e-04/,b4/ 0.103354611e-06/,b5/ 0.404125005e-09/ &
+ ,b6/-0.788037859e-12/,b7/-0.114596802e-13/,b8/ 0.381294516e-16/
+
+! for ice (temperature range -75C-0C)
+ data c0/6.11123516 /,c1/0.503109514 /,c2/0.188369801e-01/ &
+ ,c3/0.420547422e-03/,c4/0.614396778e-05/,c5/0.602780717e-07/ &
+ ,c6/0.387940929e-09/,c7/0.149436277e-11/,c8/0.262655803e-14/
+
+! for derivative:ice
+ data d0/0.503277922 /,d1/0.377289173e-01/,d2/0.126801703e-02/ &
+ ,d3/0.249468427e-04/,d4/0.313703411e-06/,d5/0.257180651e-08/ &
+ ,d6/0.133268878e-10/,d7/0.394116744e-13/,d8/0.498070196e-16/
+
+!-----------------------------------------------------------------------
+
+ td = T-273.16
+
+! IF (td < -75.0 .or. td > 75.0) THEN
+ !* print *, "qsadv: abnormal temperature", T
+! ENDIF
+
+ IF (td < -75.0) td = -75.0
+ IF (td > 75.0) td = 75.0
+
+ IF (td >= 0.0)THEN
+ es = a0 + td*(a1 + td*(a2 + td*(a3 + td*(a4 &
+ + td*(a5 + td*(a6 + td*(a7 + td*a8)))))))
+ esdT = b0 + td*(b1 + td*(b2 + td*(b3 + td*(b4 &
+ + td*(b5 + td*(b6 + td*(b7 + td*b8)))))))
+ ELSE
+ es = c0 + td*(c1 + td*(c2 + td*(c3 + td*(c4 &
+ + td*(c5 + td*(c6 + td*(c7 + td*c8)))))))
+ esdT = d0 + td*(d1 + td*(d2 + td*(d3 + td*(d4 &
+ + td*(d5 + td*(d6 + td*(d7 + td*d8)))))))
+ ENDIF
+
+ es = es * 100. ! pa
+ esdT = esdT * 100. ! pa/K
+
+ vp = 1.0 / (p - 0.378*es)
+ vp1 = 0.622 * vp
+ vp2 = vp1 * vp
+
+ qs = es * vp1 ! kg/kg
+ qsdT = esdT * vp2 * p ! 1 / K
+
+ END SUBROUTINE qsadv
+
+END MODULE MOD_Qsadv
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_RainSnowTemp.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_RainSnowTemp.F90
new file mode 100644
index 0000000000..b47a49573e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_RainSnowTemp.F90
@@ -0,0 +1,308 @@
+#include
+
+MODULE MOD_RainSnowTemp
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: rain_snow_temp
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE rain_snow_temp (patchtype,&
+ forc_t,forc_q,forc_psrf,forc_prc,forc_prl,forc_us,forc_vs,tcrit,&
+ prc_rain,prc_snow,prl_rain,prl_snow,t_precip,bifall)
+
+!=======================================================================
+! define the rate of rainfall and snowfall and precipitation water temp
+! Original author: Yongjiu Dai, 09/1999; 08/31/2002, 04/2014, 01/2023
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_WetBulb
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: patchtype ! land patch type (3=glaciers)
+
+ real(r8), intent(in) :: forc_t ! temperature at agcm reference height [kelvin]
+ real(r8), intent(in) :: forc_q ! specific humidity at agcm reference height [kg/kg]
+ real(r8), intent(in) :: forc_psrf ! atmosphere pressure at the surface [pa]
+ real(r8), intent(in) :: forc_prc ! convective precipitation [mm/s]
+ real(r8), intent(in) :: forc_prl ! large scale precipitation [mm/s]
+ real(r8), intent(in) :: forc_us ! wind speed in eastward direction [m/s]
+ real(r8), intent(in) :: forc_vs ! wind speed in northward direction [m/s]
+
+ real(r8), intent(in) :: tcrit ! critical temp. to determine rain or snow
+
+ real(r8), intent(out) :: prc_rain ! convective rainfall [kg/(m2 s)]
+ real(r8), intent(out) :: prc_snow ! convective snowfall [kg/(m2 s)]
+ real(r8), intent(out) :: prl_rain ! large scale rainfall [kg/(m2 s)]
+ real(r8), intent(out) :: prl_snow ! large scale snowfall [kg/(m2 s)]
+ real(r8), intent(out) :: t_precip ! snowfall/rainfall temperature [kelvin]
+ real(r8), intent(out) :: bifall ! bulk density of newly fallen dry snow [kg/m3]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: flfall ! fraction of liquid water within falling precip.
+
+ real(r8) :: all_snow_t ! temperature at which all precip falls entirely as snow (K)
+ real(r8) :: frac_rain_slope ! slope of the frac_rain vs. temperature relationship
+ real(r8) :: all_snow_t_c ! Temperature at which precip falls entirely as rain (deg C)
+ real(r8) :: all_rain_t_c ! Temperature at which precip falls entirely as snow (deg C)
+
+ logical :: glaciers ! true: glacier column
+ real(r8) :: t_for_bifall_degC ! temperature to USE in bifall equation (deg C)
+ real(r8) :: forc_wind ! wind speed [m/s]
+ real(r8) :: t_hydro ! temperature of falling hydrometeor [deg C]
+!-----------------------------------------------------------------------
+
+! wet-bulb temperature
+ CALL wetbulb(forc_t,forc_psrf,forc_q,t_precip)
+
+ IF (trim(DEF_precip_phase_discrimination_scheme) == 'I') THEN
+ ! Wang, Y.H., Broxton, P., Fang, Y., Behrangi, A., Barlage, M., Zeng, X., & Niu, G.Y. (2019).
+ ! A Wet-Bulb Temperature Based Rain-Snow Partitioning Scheme Improves Snowpack Prediction
+ ! Over the Drier Western United States. Geophysical Research Letters, 46, 13,825-13,835.
+ !
+ ! Behrangi et al. (2018) On distinguishing snowfall from rainfall
+ ! using near-surface atmospheric information: Comparative analysis,
+ ! uncertainties and hydrologic importance. Q J R Meteorol Soc. 144 (Suppl. 1):89-102
+
+ IF(t_precip - tfrz > 3.0)THEN
+ flfall = 1.0 ! fraction of liquid water within falling precip
+ ELSEIF (t_precip - tfrz >= -2.0)THEN
+ !Figure 5c of Behrangi et al. (2018)
+ flfall = max(0.0, 1.0 - 1.0/(1.0+5.00e-5*exp(2.0*(t_precip-tfrz+4.))))
+ !Equation 1 of Wang et al. (2019)
+ !* flfall = max(0.0, 1.0 - 1.0/(1.0+6.99e-5*exp(2.0*(t_precip-tfrz+3.97))))
+ ELSE
+ flfall = 0.0
+ ENDIF
+
+ ELSEIF (trim(DEF_precip_phase_discrimination_scheme) == 'II') THEN
+ glaciers = .false.
+ IF (patchtype == 3) glaciers = .true.
+
+ IF(glaciers) THEN
+ all_snow_t_c = -2.0
+ all_rain_t_c = 0.0
+ ELSE
+ all_snow_t_c = 0.0
+ all_rain_t_c = 2.0
+ ENDIF
+
+ all_snow_t = all_snow_t_c + tfrz
+ frac_rain_slope = 1._r8 / (all_rain_t_c - all_snow_t_c)
+
+ ! Re-partition precipitation into rain/snow for a single column.
+ ! Rain and snow variables should be set initially, and are updated here
+
+ flfall = min(1.0_r8, max(0.0_r8,(forc_t - all_snow_t)*frac_rain_slope))
+ ELSEIF (trim(DEF_precip_phase_discrimination_scheme) == 'III') THEN
+ ! Phillip Harder and John Pomeroy (2013)
+ ! Estimating precipitation phase using a psychrometric energy
+ ! balance method . Hydrol Process, 27, 1901-1914
+ ! Hydromet_Temp [K]
+ CALL hydromet_temp(forc_psrf,(forc_t-273.15),forc_q,t_hydro)
+
+ IF(t_hydro > 3.0)THEN
+ flfall = 1.0 ! fraction of liquid water within falling precip
+ ELSEIF ((t_hydro >= -3.0).and.(t_hydro <= 3.0))THEN
+ flfall = max(0.0, 1.0/(1.0+2.50286*0.125006**t_hydro))
+ ELSE
+ flfall = 0.0
+ ENDIF
+
+ ELSE
+ ! the upper limit of air temperature is set for snowfall, this cut-off
+ ! was selected based on Fig. 1, Plate 3-1, of Snow Hydrology (1956).
+ ! the percentage of liquid water by mass, which is arbitrarily set to
+ ! vary linearly with air temp, from 0% at 273.16 to 40% max at 275.16.
+
+ IF(forc_t>tfrz+2.0)THEN
+ flfall = 1.0 ! fraction of liquid water within falling precip.
+ ELSE
+ flfall = max(0.0, -54.632+0.2*forc_t)
+ ENDIF
+
+ ENDIF
+
+ ! new scheme for "bifall" from CLM5.0
+ CALL NewSnowBulkDensity(forc_t,forc_us,forc_vs,bifall)
+
+ prc_rain = forc_prc*flfall ! convective rainfall (mm/s)
+ prl_rain = forc_prl*flfall ! large scale rainfall (mm/s)
+ prc_snow = forc_prc*(1.-flfall) ! convective snowfall (mm/s)
+ prl_snow = forc_prl*(1.-flfall) ! large scale snowfall (mm/s)
+
+ ! -------------------------------------------------------------
+ ! temperature of rainfall or snowfall
+ ! -------------------------------------------------------------
+
+ IF (forc_t > 275.65) THEN
+ IF (t_precip < tfrz) t_precip = tfrz
+ ELSE
+ t_precip = min(tfrz,t_precip)
+ IF(flfall > 1.e-6)THEN
+ t_precip = tfrz - sqrt((1.0/flfall)-1.0)/100.0
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE rain_snow_temp
+
+
+ SUBROUTINE NewSnowBulkDensity(forc_t,forc_us,forc_vs,bifall)
+!=======================================================================
+! Scheme for bulk density of newly fallen dry snow
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz
+
+ real(r8), intent(in) :: forc_t ! temperature at agcm reference height [kelvin]
+ real(r8), intent(in) :: forc_us ! wind speed in eastward direction [m/s]
+ real(r8), intent(in) :: forc_vs ! wind speed in northward direction [m/s]
+
+ real(r8), intent(out) :: bifall ! bulk density of newly fallen dry snow [kg/m3]
+
+ real(r8) :: t_for_bifall_degC ! temperature to USE in bifall equation (deg C)
+ real(r8) :: forc_wind ! wind speed [m/s]
+
+ !-----------------------------------------------------------------------
+
+ IF (forc_t > tfrz + 2.0) THEN
+ bifall = 50.0 + 1.7*(17.0)**1.5
+ ELSEIF (forc_t > tfrz - 15.0) THEN
+ bifall = 50.0 + 1.7*(forc_t - tfrz + 15.0)**1.5
+ ELSE
+ ! Andrew Slater: A temp of about -15C gives the nicest
+ ! "blower" powder, but as you get colder the flake size decreases so
+ ! density goes up. e.g. the smaller snow crystals from the Arctic and Antarctic winters
+ IF (forc_t > tfrz - 57.55) THEN
+ t_for_bifall_degC = (forc_t-tfrz)
+ ELSE
+ ! Below -57.55 deg C, the following function starts to decrease with
+ ! decreasing temperatures. Limit the function to avoid this turning over.
+ t_for_bifall_degC = -57.55
+ ENDIF
+ bifall = -(50.0/15.0 + 0.0333*15.0)*t_for_bifall_degC - 0.0333*t_for_bifall_degC**2
+ ENDIF
+
+ forc_wind = sqrt(forc_us**2 + forc_vs**2)
+ IF (forc_wind > 0.1) THEN
+ ! Density offset for wind-driven compaction, initial ideas based on Liston et. al (2007) J.
+ ! Glaciology, 53(181), 241-255. Modified for a continuous wind impact and slightly more
+ ! sensitive to wind - Andrew Slater, 2016
+ bifall = bifall + (266.861 * ((1.0 + TANH(forc_wind/5.0))/2.0)**8.8)
+ ENDIF
+
+ END SUBROUTINE NewSnowBulkDensity
+
+ !!==============================================
+
+ SUBROUTINE hydromet_temp(ppa, pta, pqa, pti)
+!-----------------------------------------------------------------------------
+! !DESCRIPTION
+! Computes the temperature of a falling hydrometeor based on Harder, P., Pomeroy, J. (2013).
+!
+! Original Author:
+! ----------------
+! V. Vionnet (11/2020)
+!
+! !REFERENCES:
+! Harder, P., Pomeroy, J. (2013).
+! Estimating precipitation phase using a psychrometric energy balance method
+! Hydrological Processes 27(13), 1901-1914. https://dx.doi.org/10.1002/hyp.9799
+
+! !REVISIONS:
+! 2023.07.30 Aobo Tan & Zhongwang Wei @ SYSU
+!
+!-----------------------------------------------------------------------------
+
+ real(r8), intent(in) :: ppa ! Air pressure (Pa)
+ real(r8), intent(in) :: pta ! Air temperature (deg C)
+ real(r8), intent(in) :: pqa ! Air specific humidity (kg/kg)
+ real(r8), intent(out) :: pti ! Hydrometeor temperature in deg C
+
+ real(r8) :: zd ! Diffusivity of water vapour in air [m^2 s^-1]
+ real(r8) :: zlambda ! Thermal conductivity of air [J m^-1 s^-1 K^-1]
+ real(r8) :: zl ! Latent heat of sublimation or vaporization [J kg^-1]
+ real(r8) :: zrhoda ! Density of dry air [kg m^-3]
+ real(r8) :: zrh ! Relative humidity [-]
+ real(r8) :: rho_vast_diff, esat, rho_vast
+ real(r8) :: zt, ztint, zf, zfdiff, evsat
+ integer :: JITER
+ integer :: JJ, I, NN
+
+ ! 1. Compute diffusivity of water vapour in air [m^2 s^-1] (Thorpe and Mason, 1966)
+ zd = 2.063e-5 * ((pta + 273.15) / 273.15) ** 1.75
+
+ ! 2. Compute thermal conductivity of air [J m^-1 s^-1 K^-1]
+ zlambda = 0.000063 * (pta + 273.15) + 0.00673
+
+ ! 3. Compute latent heat of sublimation or vaporization (depending on air temperature)
+ IF (pta < 0.) THEN
+ zl = 1000.0 * (2834.1 - 0.29 * pta - 0.004 * pta ** 2.)
+
+ ELSE
+ zl = 1000.0 * (2501.0 - (2.361 * pta))
+ ENDIF
+
+ ! 4. Compute density of dry air [kg m^-3]
+ zrhoda = ppa / (287.04 * (pta + 273.15))
+
+ ! 5. Compute saturated water vapour pressure [Pa]
+ IF (pta > 0) THEN
+ evsat = 611.0 * EXP(17.27 * pta / (pta + 237.3))
+ ELSE
+ evsat = 611.0 * EXP(21.87 * pta / (pta + 265.5))
+ ENDIF
+
+ ! 6. Solve iteratively to get Ti in Harder and Pomeroy (2013) using a Newton-Raphson approach
+ ! Set the first guess to pta
+ zt = pta
+
+ ! Loop until convergence
+ DO JITER = 1, 10
+ ztint = zt
+
+ IF (zt > 0) THEN
+ esat = 611.0 * EXP(17.27 * zt / (zt + 237.3))
+ ELSE
+ esat = 611.0 * EXP(21.87 * zt / (zt + 265.5))
+ ENDIF
+
+ rho_vast = esat / (461.5 * (zt + 273.15)) ! Saturated water vapour density
+
+ zf = zt - pta - zd * zl / zlambda * (pqa * zrhoda - rho_vast)
+
+ IF (zt > 0) THEN
+ rho_vast_diff = 611.0 / (461.5 * (zt + 273.15)) * EXP(17.27 * zt / (zt + 237.3)) * &
+ (-1 / (zt + 273.15) + 17.27 * 237.3 / ((zt + 237.3) ** 2.))
+ ELSE
+ rho_vast_diff = 611.0 / (461.5 * (zt + 273.15)) * EXP(21.87 * zt / (zt + 265.5)) * &
+ (-1 / (zt + 273.15) + 21.87 * 265.5 / ((zt + 265.5) ** 2.))
+ ENDIF
+
+ zfdiff = 1 + zd * zl / zlambda * rho_vast_diff
+ zt = ztint - zf / zfdiff
+ IF (ABS(zt - ztint) .lt. 0.01) EXIT
+ ENDDO
+
+ pti = zt
+
+ END SUBROUTINE hydromet_temp
+
+END MODULE MOD_RainSnowTemp
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Runoff.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Runoff.F90
new file mode 100644
index 0000000000..32c623c28d
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Runoff.F90
@@ -0,0 +1,440 @@
+#include
+
+MODULE MOD_Runoff
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: SurfaceRunoff_TOPMOD
+ PUBLIC :: SubsurfaceRunoff_TOPMOD
+ PUBLIC :: Runoff_XinAnJiang
+ PUBLIC :: Runoff_SimpleVIC
+ PUBLIC :: SubsurfaceRunoff_SimpleVIC
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+ SUBROUTINE SurfaceRunoff_TOPMOD (nl_soil,wimp,porsl,psi0,hksati,&
+ fsatmax,fsatdcf,&
+ z_soisno,dz_soisno,zi_soisno,&
+ eff_porosity,icefrac,zwt,gwat,&
+ rsur,rsur_se,rsur_ie,&
+ topoweti,alp_twi,chi_twi,mu_twi,frcsat,eta_out)
+
+!=======================================================================
+! the original code was provide by Robert E. Dickinson based on
+! following clues: a water table level determination level added
+! including highland and lowland levels and fractional area of wetland
+! (water table above the surface. Runoff is parametrized from the
+! lowlands in terms of precip incident on wet areas and a base flow,
+! where these are estimated using ideas from TOPMODEL.
+!
+! Author : Yongjiu Dai, 07/29/2002, Guoyue Niu, 06/2012
+!=======================================================================
+
+ USE MOD_Namelist, only: DEF_TOPMOD_method
+ USE MOD_IncompleteGamma, only: GRATIO
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: nl_soil ! number of soil layers
+ real(r8), intent(in) :: &
+ ! wtfact, &! (updated to gridded 'fsatmax' data)
+ ! fraction of model area with high water table
+ wimp, &! water impermeable if porosity less than wimp
+ porsl(1:nl_soil), &! saturated volumetric soil water content(porosity)
+ psi0(1:nl_soil), &! saturated soil suction (mm) (NEGATIVE)
+ hksati(1:nl_soil), &! hydraulic conductivity at saturation (mm h2o/s)
+ fsatmax, &! maximum fraction of saturation area [-]
+ fsatdcf, &! decay factor in calc of fraction of saturation area [1/m]
+ z_soisno(1:nl_soil), &! layer depth (m)
+ dz_soisno(1:nl_soil), &! layer thickness (m)
+ zi_soisno(0:nl_soil), &! interface level below a "z" level (m)
+ eff_porosity(1:nl_soil), &! effective porosity = porosity - vol_ice
+ icefrac(1:nl_soil), &! ice fraction (-)
+ gwat, &! net water input from top
+ zwt ! the depth from ground (soil) surface to water table [m]
+
+ real(r8), intent(out) :: rsur ! surface runoff (mm h2o/s)
+ real(r8), intent(out), optional :: rsur_se! saturation excess surface runoff (mm h2o/s)
+ real(r8), intent(out), optional :: rsur_ie! infiltration excess surface runoff (mm h2o/s)
+
+ real(r8), intent(in), optional :: topoweti
+ real(r8), intent(in), optional :: alp_twi, chi_twi, mu_twi
+ real(r8), intent(out), optional :: frcsat
+ real(r8), intent(out), optional :: eta_out
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8), parameter :: vdcf = 2.0
+
+ real(r8) qinmax ! maximum infiltration capability
+ real(r8) fsat ! fractional area with water table at surface
+
+ real(r8) eta, pgr0, pgr1, qgr, gfun
+ integer niter
+
+ ! updated to gridded 'fsatdcf' (by Shupeng Zhang)
+ ! real(r8), parameter :: fff = 0.5 ! runoff decay factor (m-1)
+
+!-----------------------------------------------------------------------
+
+! fraction of saturated area (updated to gridded 'fsatmax' and 'fsatdcf')
+ !fsat = wtfact*min(1.0,exp(-0.5*fff*zwt))
+ IF ((DEF_TOPMOD_method == 0) .or. (DEF_TOPMOD_method == 1)) THEN
+
+ fsat = fsatmax * exp(- fsatdcf * vdcf * zwt)
+
+ ELSE
+
+ IF (zwt <= 0.) THEN
+
+ fsat = 1.
+ eta = mu_twi
+
+ ELSE
+
+ eta = topoweti
+ niter = 0
+ DO WHILE (niter < 20)
+ niter = niter + 1
+ CALL GRATIO (alp_twi+1, (eta-mu_twi)/chi_twi, pgr1, qgr, 0)
+ CALL GRATIO (alp_twi, (eta-mu_twi)/chi_twi, pgr0, qgr, 0)
+ gfun = ((eta-mu_twi)*pgr0 - chi_twi*alp_twi*pgr1)/vdcf - zwt
+
+ IF (abs(gfun) > 1.e-6) THEN
+ eta = mu_twi + (chi_twi * alp_twi * pgr1 + vdcf*zwt) / pgr0
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ IF (abs(gfun) > 1.e-6) THEN
+ write(*,*) 'Fail to converge in TOPModel: (alp,chi,mu,twi,zwt,gfun) = ', &
+ alp_twi, chi_twi, mu_twi, topoweti, zwt, gfun
+ ENDIF
+
+ CALL GRATIO (alp_twi, (eta-mu_twi)/chi_twi, pgr0, qgr, 0)
+
+ fsat = qgr
+
+ ENDIF
+
+ IF (present(eta_out)) THEN
+ eta_out = eta
+ ENDIF
+
+ ENDIF
+
+ IF (present(frcsat)) THEN
+ frcsat = fsat
+ ENDIF
+
+! Maximum infiltration capacity
+ qinmax = minval(10.**(-6.0*icefrac(1:min(3,nl_soil)))*hksati(1:min(3,nl_soil)))
+ IF(eff_porosity(1) WaterDepthMax ) then
+ !RunoffSurface = (WaterDepthInit + w_int) - WaterDepthMax
+ RunoffSurface = watin - wsat_int + w_int
+ ELSE
+ InfilVarTmp = 1.0 - ((WaterDepthInit +watin ) / WaterDepthMax)
+ RunoffSurface =watin - wsat_int + w_int + wsat_int * (InfilVarTmp**(1.0+BVIC))
+ ENDIF
+
+ IF ( RunoffSurface < 0.0 ) RunoffSurface = 0.0
+ IF ( RunoffSurface > watin) RunoffSurface = watin
+
+ infil = watin - RunoffSurface
+ rsur= RunoffSurface * 1000. / deltim
+ rsubst = 0.
+ ENDIF
+
+ END SUBROUTINE Runoff_SimpleVIC
+
+ ! -------------------------------------------------------------------------
+ SUBROUTINE SubsurfaceRunoff_SimpleVIC ( &
+ nl_soil, z_soisno, dz_soisno, wice_soisno, porsl, psi0, hksati, theta_r, &
+ nprms, prms, zwt, rsubst)
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o
+ USE MOD_Vars_TimeInvariants, only: smpmax
+ USE MOD_Hydro_SoilFunction, only: soil_vliq_from_psi
+ IMPLICIT NONE
+
+ integer, intent(in) :: nl_soil ! number of soil layers
+
+ real(r8), intent(in) :: &
+ z_soisno (1:nl_soil), & ! layer depth (m)
+ dz_soisno (1:nl_soil), & ! layer thickness (m)
+ wice_soisno(1:nl_soil), & ! ice lens (kg/m2)
+ porsl (1:nl_soil), & ! saturated volumetric soil water content(porosity)
+ psi0 (1:nl_soil), & ! saturated soil suction (mm) (NEGATIVE)
+ hksati (1:nl_soil), & ! hydraulic conductivity at saturation (mm h2o/s)
+ theta_r (1:nl_soil) ! residual moisture content [-]
+
+ integer, intent(in) :: nprms
+ real(r8), intent(in) :: prms(nprms, 1:nl_soil)
+
+ real(r8), intent(in) :: zwt ! [m]
+
+ real(r8), intent(out) :: rsubst ! subsurface runoff (mm h2o/s)
+
+ ! Local Variables
+ real(r8), parameter :: Ds = 0.061 ! a fraction of Dsmax
+ real(r8), parameter :: Ws = 0.646 ! a fraction of the potential water storage as Wmb-Wwb
+ real(r8) :: Dsmax ! maximum subsurface flow
+ real(r8) :: Wwb ! (layer 8+9, from 0.83m to 2.30m) water storage at wilting point
+ real(r8) :: Wmb ! (layer 8+9, from 0.83m to 2.30m) maximum water storage
+ real(r8) :: Wlb ! (layer 8+9, from 0.83m to 2.30m) liquid water storage
+ real(r8) :: Wab ! (layer 8+9, from 0.83m to 2.30m) relative water storage
+
+ real(r8) :: vol_ice, icefrac, eff_porosity, imped, hk
+ real(r8), parameter :: e_ice=6.0 ! soil ice impedance factor
+ integer :: ilev
+
+ Wwb = 0.
+ Wmb = 0.
+ Wlb = 0.
+ Dsmax = 0.
+ DO ilev = 8, 9
+ vol_ice = max(min(porsl(ilev), wice_soisno(ilev)/(dz_soisno(ilev)*denice)), 0.)
+ eff_porosity = porsl(ilev) - vol_ice
+
+ Wwb = Wwb + dz_soisno(ilev) * denh2o * &
+ soil_vliq_from_psi (smpmax, eff_porosity, theta_r(ilev), psi0(ilev), nprms, prms(:,ilev))
+
+ Wmb = Wmb + eff_porosity*dz_soisno(ilev)*denh2o
+
+ Wlb = Wlb + dz_soisno(ilev) * denh2o * &
+ soil_vliq_from_psi ( psi0(ilev)-max((zwt-z_soisno(ilev))*1.e3, 0.), &
+ eff_porosity, theta_r(ilev), psi0(ilev), nprms, prms(:,ilev))
+
+ icefrac = vol_ice/porsl(ilev)
+ imped = 10.**(-e_ice*icefrac)
+ hk = imped * hksati(ilev)
+ Dsmax = max(Dsmax, hk)
+ ENDDO
+
+ Wab = (Wlb-Wwb) / (Wmb-Wwb)
+ Wab = min(max(Wab, 0.), 1.)
+
+ IF (Wab <= Ws) THEN
+ rsubst = Dsmax * Ds * (Wab/Ws)
+ ELSE
+ rsubst = Dsmax * Ds * (Wab/Ws) + Dsmax * (1-Ds/Ws) * ((Wab-Ws)/(1-Ws))**2
+ ENDIF
+
+ END SUBROUTINE SubsurfaceRunoff_SimpleVIC
+
+END MODULE MOD_Runoff
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SimpleOcean.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SimpleOcean.F90
new file mode 100644
index 0000000000..85c9ac548b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SimpleOcean.F90
@@ -0,0 +1,680 @@
+#include
+
+MODULE MOD_SimpleOcean
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: socean
+
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: seafluxes
+ PRIVATE :: srftsb
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE socean (dosst,deltim,oro,hu,ht,hq,&
+ us,vs,tm,qm,rhoair,psrf,sabg,frl,tssea,tssub,scv,&
+ taux,tauy,fsena,fevpa,lfevpa,fseng,fevpg,tref,qref,&
+ z0m,zol,rib,ustar,qstar,tstar,fm,fh,fq,emis,olrg)
+!-----------------------------------------------------------------------
+! Simple Ocean Model
+! 1. calculate sea surface fluxes, based on CLM
+! 2. calculate sea surface albedos and seaice/snow temperatures
+! as in NCAR CCM3.6.16
+! Original authors : Yongjiu Dai and Xin-Zhong Liang (08/30/2001)
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz, hvap, hsub, stefnc, vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, parameter :: psrfty=7 ! Number of surface types
+ integer, parameter :: plsice=4 ! number of seaice levels
+
+ logical, intent(in) :: dosst ! true to update sst/ice/snow before calculation
+ real(r8), intent(in) :: deltim ! seconds in a time-step (s)
+ real(r8), intent(in) :: hu ! agcm reference height of wind [m]
+ real(r8), intent(in) :: ht ! agcm reference height of temperature [m]
+ real(r8), intent(in) :: hq ! agcm reference height of humidity [m]
+ real(r8), intent(in) :: us ! wind component in eastward direction [m/s]
+ real(r8), intent(in) :: vs ! wind component in northward direction [m/s]
+ real(r8), intent(in) :: tm ! temperature at agcm reference height [kelvin]
+ real(r8), intent(in) :: qm ! specific humidity at agcm reference height [kg/kg]
+ real(r8), intent(in) :: rhoair ! density air [kg/m3]
+ real(r8), intent(in) :: psrf ! atmosphere pressure at the surface [pa] [not used]
+ real(r8), intent(in) :: sabg ! surface solar absorbed flux [W/m2]
+ real(r8), intent(in) :: frl ! downward longwave radiation [W/m2]
+
+ real(r8), intent(inout) :: oro ! ocean(0)/seaice(2)/ flag
+ real(r8), intent(inout) :: scv ! snow water equivalent depth (mm)
+ real(r8), intent(inout) :: tssub(plsice) ! surface/sub-surface temperatures [K]
+ real(r8), intent(out) :: tssea ! sea surface temperature [K]
+
+ real(r8), intent(out) :: taux ! wind stress: E-W [kg/m/s**2]
+ real(r8), intent(out) :: tauy ! wind stress: N-S [kg/m/s**2]
+ real(r8), intent(out) :: fsena ! sensible heat from reference height to atmosphere [W/m2]
+ real(r8), intent(out) :: fevpa ! evaporation from reference height to atmosphere [mm/s]
+ real(r8), intent(out) :: lfevpa ! latent heat from reference height to atmosphere [W/m2]
+ real(r8), intent(out) :: fseng ! sensible heat flux from ground [W/m2]
+ real(r8), intent(out) :: fevpg ! evaporation heat flux from ground [mm/s]
+
+ real(r8), intent(out) :: tref ! 2 m height air temperature [kelvin]
+ real(r8), intent(out) :: qref ! 2 m height air humidity
+ real(r8), intent(out) :: z0m ! effective roughness [m]
+ real(r8), intent(out) :: zol ! dimensionless height (z/L) used in Monin-Obukhov theory
+ real(r8), intent(out) :: rib ! bulk Richardson number in surface layer
+ real(r8), intent(out) :: ustar ! friction velocity [m/s]
+ real(r8), intent(out) :: tstar ! temperature scaling parameter
+ real(r8), intent(out) :: qstar ! moisture scaling parameter
+ real(r8), intent(out) :: fm ! integral of profile FUNCTION for momentum
+ real(r8), intent(out) :: fh ! integral of profile FUNCTION for heat
+ real(r8), intent(out) :: fq ! integral of profile FUNCTION for moisture
+ real(r8), intent(out) :: emis ! averaged bulk surface emissivity
+ real(r8), intent(out) :: olrg ! longwave up flux at surface [W/m2]
+
+!-------------------------- Local Variables ----------------------------
+ integer isrfty ! surface type index (1-7)
+ real(r8) cgrndl ! deriv, of soil sensible heat flux wrt soil temp [w/m2/k]
+ real(r8) cgrnds ! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+ real(r8) dshf ! Ts partial derivative for sensible heat flux
+ real(r8) dlhf ! Ts partial derivative for latent heat flux
+ real(r8) fnt ! net surface flux for input conditions [W/m2]
+ real(r8) dfntdt ! net surface flux ts partial derivative [W/m2]
+ real(r8) tsbsf(plsice) ! Non-adjusted srfc/sub-srfc temperatures
+ real(r8) snowh ! snow depth (liquid water equivalent) [m]
+ real(r8) sicthk ! sea-ice thickness [m]
+
+ real(r8), parameter :: emisi = 1.0 ! (0.97) surface emissivity for ice or snow [-]
+ real(r8), parameter :: emisw = 1.0 ! (0.97) surface emissivity for water [-]
+ real(r8), parameter :: tsice = 271.36 ! freezing point of sea ice [K]
+ real(r8), parameter :: thsice = 2.0 ! initial thickness of sea ice [m]
+ real(r8), parameter :: snsice = 0.005 ! initial snow water equivalent over sea ice [m]
+
+ integer j
+
+!-----------------------------------------------------------------------
+
+ snowh = scv/1000.
+
+ IF(dosst)THEN
+! update sea temperatures and sea ice distribution
+! as well as snow cover over sea ice
+ IF(nint(oro).eq.2 .and. tssea.gt.tsice) THEN
+ oro = 0.0 ! old sea ice melt out
+ snowh = 0.
+ scv = 0.
+ sicthk = 0.
+ DO j = 1,plsice
+ tssub(j) = tssea
+ ENDDO
+ ELSEIF(nint(oro).eq.0 .and. tssea.le.tsice) THEN
+ oro = 2.0 ! new sea ice formed
+ snowh = snsice
+ scv = snowh*1000.
+ sicthk = thsice
+ DO j = 1,plsice
+ tssub(j) = tssea
+ ENDDO
+ ENDIF
+ ENDIF
+
+ tssea = tssub(1)
+
+! compute surface fluxes, derivatives, and exchange coefficients
+ CALL seafluxes (oro,hu,ht,hq,&
+ us,vs,tm,qm,rhoair,psrf,tssea,&
+ taux,tauy,fsena,fevpa,fseng,fevpg,tref,qref,&
+ z0m,zol,rib,ustar,qstar,tstar,fm,fh,fq,cgrndl,cgrnds)
+
+ IF(nint(oro).eq.0)THEN ! ocean
+ lfevpa = fevpa*hvap
+ olrg = stefnc*emisw*tssea**4 + (1.-emisw)*frl
+ emis = emisw
+
+ ELSEIF(nint(oro).eq.2)THEN ! sea ice
+ lfevpa = fevpa*hsub
+
+ ! net surface flux and derivate at current surface temperature
+ dshf = cgrnds
+ dlhf = hsub*cgrndl
+ olrg = stefnc*emisi*tssea**4 + (1.-emisi)*frl
+
+ fnt = sabg + frl - olrg - fsena - lfevpa
+ dfntdt = -(dshf + dlhf) - stefnc*emisi*4.*tssea**3
+
+ ! initialize surface/subsurface temperatures for srftsb
+ DO j=1,plsice
+ tsbsf(j) = tssub(j)
+ ENDDO
+
+ ! set sea ice surface type
+ isrfty = 2
+
+ ! diffusion calculation for temperature
+ CALL srftsb(isrfty,deltim,fnt,dfntdt,snowh,tsbsf)
+
+ DO j=1,plsice
+ tsbsf(j) = min(tsbsf(j),tfrz)
+ tssub(j) = tsbsf(j)
+ ENDDO
+ tssea = tssub(1)
+
+ olrg = stefnc*emisi*tssea**4 + (1.-emisi)*frl
+ emis = emisi
+
+ ENDIF
+
+ END SUBROUTINE socean
+
+
+
+ SUBROUTINE seafluxes (oro,hu,ht,hq,&
+ us,vs,tm,qm,rhoair,psrf,tssea,&
+ taux,tauy,fsena,fevpa,fseng,fevpg,tref,qref,&
+ z0m,zol,rib,ustar,qstar,tstar,fm,fh,fq,cgrndl,cgrnds)
+
+!=======================================================================
+! this is the main SUBROUTINE to execute the calculation of thermal processes
+! and surface fluxes
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpair,rgas,vonkar,grav
+ USE MOD_FrictionVelocity
+ USE MOD_Qsadv
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: &
+ oro, &! ocean(0)/seaice(2)/ flag
+
+ ! atmospherical variables and agcm reference height
+ hu, &! agcm reference height of wind [m]
+ ht, &! agcm reference height of temperature [m]
+ hq, &! agcm reference height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ tm, &! temperature at agcm reference height [kelvin]
+ qm, &! specific humidity at agcm reference height [kg/kg]
+ rhoair, &! density air [kg/m3]
+ psrf, &! atmosphere pressure at the surface [pa] [not used]
+
+ tssea ! sea surface temperature [K]
+
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fsena, &! sensible heat from agcm reference height to atmosphere [W/m2]
+ fevpa, &! evaporation from agcm reference height to atmosphere [mm/s]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+
+ tref, &! 2 m height air temperature [kelvin]
+ qref, &! 2 m height air humidity
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile FUNCTION for momentum
+ fh, &! integral of profile FUNCTION for heat
+ fq, &! integral of profile FUNCTION for moisture
+ cgrndl, &! deriv, of soil sensible heat flux wrt soil temp [w/m2/k]
+ cgrnds ! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+
+!-------------------------- Local Variables ----------------------------
+ integer i
+ integer niters,&! maximum number of iterations for surface temperature
+ iter, &! iteration index
+ nmozsgn ! number of times moz changes sign
+
+ real(r8) :: &
+ beta, &! coefficient of convective velocity [-]
+ displax, &! zero-displacement height [m]
+ dth, &! diff of virtual temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ eg, &! water vapor pressure at temperature T [Pa]
+ degdT, &! d(eg)/dT
+ obu, &! monin-obukhov length (m)
+ obuold, &! monin-obukhov length from previous iteration
+ qsatg, &! ground saturated specific humidity [kg/kg]
+ qsatgdT, &! d(qsatg)/dT
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ raih, &! temporary variable [kg/m2/s]
+ raiw, &! temporary variable [kg/m2/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile FUNCTION for momentum at 10m
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ thvstar, &! virtual potential temperature scaling parameter
+ um, &! wind speed including the stablity effect [m/s]
+ ur, &! wind speed at reference height [m/s]
+ visa, &! kinematic viscosity of dry air [m2/s]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ xt, &!
+ xq, &!
+ zii, &! convective boundary height [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ z0mg, &! roughness length over ground, momentum [m]
+ z0hg, &! roughness length over ground, sensible heat [m]
+ z0qg ! roughness length over ground, latent heat [m]
+
+ real, parameter :: zsice = 0.04 ! sea ice aerodynamic roughness length [m]
+
+!-----------------------------------------------------------------------
+! potential temperature at the reference height
+ beta = 1. ! - (in computing W_*)
+ zii = 1000. ! m (pbl height)
+
+!-----------------------------------------------------------------------
+! Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+!-----------------------------------------------------------------------
+! Initialization variables
+ nmozsgn = 0
+ obuold = 0.
+
+ CALL qsadv(tssea,psrf,eg,degdT,qsatg,qsatgdT)
+
+! potential temperature at the reference height
+ thm = tm + 0.0098*ht ! intermediate variable equivalent to
+ ! tm*(pgcm/psrf)**(rgas/cpair)
+ th = tm*(100000./psrf)**(rgas/cpair) ! potential T
+ thv = th*(1.+0.61*qm) ! virtual potential T
+ ur = max(0.1,sqrt(us*us+vs*vs)) ! limit set to 0.1
+
+ dth = thm-tssea
+ dqh = qm-qsatg
+ dthv = dth*(1.+0.61*qm)+0.61*th*dqh
+ zldis = hu-0.
+
+ IF(nint(oro).eq.0)THEN ! ocean
+ ! Kinematic viscosity of dry air (m2/s)- Andreas (1989) CRREL Rep. 89-11
+ visa=1.326e-5*(1.+6.542e-3*tm + 8.301e-6*tm**2 - 4.84e-9*tm**3)
+
+ ! loop to obtain initial and good ustar and zo
+ ustar=0.06
+ wc=0.5
+ IF(dthv.ge.0.) THEN
+ um=max(ur,0.1)
+ ELSE
+ um=sqrt(ur*ur+wc*wc)
+ ENDIF
+
+ DO i=1,5
+ z0mg=0.013*ustar*ustar/grav+0.11*visa/ustar
+ ustar=vonkar*um/log(zldis/z0mg)
+ ENDDO
+
+ ELSEIF(nint(oro).eq.2)THEN ! sea ice
+ z0mg = zsice
+ z0qg = z0mg
+ z0hg = z0mg
+ ENDIF
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mg,um,obu)
+
+! Evaluated stability-dependent variables using moz from prior iteration
+ niters=10
+ displax = 0.
+
+ !----------------------------------------------------------------
+ ITERATION : DO iter = 1, niters ! begin stability iteration
+ !----------------------------------------------------------------
+
+ IF(nint(oro).eq.0)THEN ! ocean
+ z0mg=0.013*ustar*ustar/grav + 0.11*visa/ustar
+ xq=2.67*(ustar*z0mg/visa)**0.25 - 2.57
+ xt= xq
+ z0qg=z0mg/exp(xq)
+ z0hg=z0mg/exp(xt)
+ ENDIF
+
+ CALL moninobuk(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+
+ tstar = vonkar/fh*dth
+ qstar = vonkar/fq*dqh
+
+ thvstar=tstar*(1.+0.61*qm)+0.61*th*qstar
+ zol=zldis*vonkar*grav*thvstar/(ustar**2*thv)
+ IF(zol >= 0.) THEN ! stable
+ zol = min(2.,max(zol,1.e-6))
+ ELSE ! unstable
+ zol = max(-100.,min(zol,-1.e-6))
+ ENDIF
+ obu = zldis/zol
+
+ IF(zol >= 0.)THEN
+ um = max(ur,0.1)
+ ELSE
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu < 0.) nmozsgn = nmozsgn+1
+ IF(nmozsgn >= 4) EXIT
+
+ obuold = obu
+
+ !----------------------------------------------------------------
+ ENDDO ITERATION ! END stability iteration
+ !----------------------------------------------------------------
+
+! Get derivative of fluxes with respect to ground temperature
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/fh*ustar)
+ raw = 1./(vonkar/fq*ustar)
+
+ raih = rhoair*cpair/rah
+ raiw = rhoair/raw
+ cgrnds = raih
+ cgrndl = raiw*qsatgdT
+
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+! surface fluxes of momentum, sensible and latent
+! using ground temperatures from previous time step
+ taux = -rhoair*us/ram
+ tauy = -rhoair*vs/ram
+
+ fseng = -raih*dth
+ fevpg = -raiw*dqh
+ fsena = fseng
+ fevpa = fevpg
+
+! 2 m height air temperature
+ tref = thm + vonkar/fh*dth * (fh2m/vonkar - fh/vonkar)
+ qref = qm + vonkar/fq*dqh * (fq2m/vonkar - fq/vonkar)
+ z0m = z0mg
+
+ END SUBROUTINE seafluxes
+
+
+
+ SUBROUTINE srftsb(isrfty,deltim,fnt,dfntdt,snowh,tsbsf)
+
+!-----------------------------------------------------------------------
+! Compute surface and subsurface temperatures over sea-ice surfaces.
+!
+! Sea ice temperatures are specified in 'plsice' layers of fixed
+! thickness and thermal properties. The forecast temperatures are
+! determined from a backward/IMPLICIT diffusion calculation using
+! linearized sensible/latent heat fluxes. The bottom ocean temperature
+! is fixed at -2C, allowing heat flux exchange with underlying ocean.
+!
+! Sub-surface layers are indexed 1 at the surface, increasing downwards
+! to plsice. Layers have mid-points and interfaces between layers.
+!
+! Temperatures are defined at mid-points, WHILE fluxes between layers
+! and the top/bottom media are defined at layer interfaces.
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tkice, tkair
+ USE MOD_Utils
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, parameter :: psrfty = 7 ! Number of surface types
+ integer, parameter :: plsice = 4 ! number of seaice levels
+
+ integer, intent(in) :: isrfty ! surface type index (1 - 7)
+ real(r8), intent(in) :: deltim ! seconds i a time step (s)
+ real(r8), intent(in) :: fnt ! top surface/atmosphere net energy flux
+ real(r8), intent(in) :: dfntdt ! ts partial derivative of net sfc flux
+ real(r8), intent(in) :: snowh ! snow depth (liquid water equivalent) [m]
+
+ real(r8), intent(inout) :: tsbsf(1:plsice) ! surface/sub-surface tmps
+
+!-------------------------- Local Variables ----------------------------
+
+ integer :: j, jndx ! sub-surface layer index
+
+ real(r8) cmass (1:plsice) ! specific heat of soil (J/kg/K)
+ real(r8) rho (1:plsice) ! mass densty of sub-sfc mat (kg/m3)
+ real(r8) tk (1:plsice) ! thermal conductivity (watts/m/K)
+ real(r8) diag (1:plsice) ! diagonal matrix elements
+ real(r8) htsrc (1:plsice) ! external heat source (W/m3)
+ real(r8) rhs (1:plsice) ! rhs of tri-diagonal matrix equation
+ real(r8) sbdiag(1:plsice) ! sub-diagonal matrix elements
+ real(r8) spdiag(1:plsice) ! super-diagonal matrix elements
+ real(r8) tin (1:plsice) ! initial sub-surface temperatures
+ real(r8) z (0:plsice) ! interface geometrical depth (m)
+ real(r8) ws (1:plsice) ! working storage for mtdlss
+
+ real(r8) cmty ! layer mass heat capacity
+ real(r8) fbt ! ocean heat flux into sea-ice
+ real(r8) rhty ! layer mass density
+ real(r8) thck ! layer thickness
+ real(r8) tkty ! layer thermal conductivity
+ real(r8) cmsnow ! Snow mass heat capacity
+ real(r8) crt ! cmass*rho*rdtime
+ real(r8) delz ! layer thickness
+ real(r8) delzmn ! thick from mid-point to lyr above mid-point
+ real(r8) delzpl ! thick from mid-point to lyr below mid-point
+ real(r8) fmns ! 1/(delz*delzmn)
+ real(r8) fpls ! 1/(delz*delzpl)
+ real(r8) msnow ! mass path of snow
+ real(r8) mlice ! mass path of ice
+ real(r8) rdtime ! inverse model time step
+ real(r8) rhsnow ! snow mass density
+ real(r8) rztop ! 1/ztop
+ real(r8) tkbot ! bottom layer top interf thermal conduct
+ real(r8) tkmns ! layer bottom interface thermal conduct
+ real(r8) tkpls ! layer top interface thermal conductivity
+ real(r8) tksnow ! snow thermal conductivity
+ real(r8) tktop ! top layer bottom interface thermal conduct
+ real(r8) tmp ! crt - dfntdt(i)*rztop
+ real(r8) zbot ! bottom layer thickness
+ real(r8) zm ! present layer mid-point depth
+ real(r8) zmmn ! layer above mid-point depth
+ real(r8) zmpl ! layer below mid-point depth
+ real(r8) zsnow ! snow geometric depth
+ real(r8) ztop ! top layer thickness
+ logical scvr ! true IF surface snow covered
+
+!--------------------------Data Statements------------------------------
+! specified (and invariant) thermal properties for surface types
+
+ real, parameter :: cmair = 1.00e3 ! mass specific heat of air [J/kg/K]
+ real, parameter :: cmice = 2.07e3 ! mass specific heat of ice [J/kg/K]
+ real, parameter :: frcair = 0.90 ! fraction of air assumed in mix of ice
+ real, parameter :: rhair = 1.25 ! mass density of surface air [kg/m3]
+ real, parameter :: rhice = 9.20e2 ! mass density of ice [kg/m3]
+ real, parameter :: snwedp = 10.0 ! snow:water equivalent depth factor [-]
+
+ real(r8),parameter,dimension(psrfty,plsice) :: &!mass specific heat (J/kg/K)
+ cmtype = reshape(&
+ (/4.20e3,2.07e3,2.07e3,1.04e3,7.20e2,5.60e2,4.16e2,&
+ 4.20e3,2.07e3,2.07e3,1.04e3,7.20e2,5.60e2,4.16e2,&
+ 4.20e3,2.07e3,2.07e3,1.04e3,7.20e2,5.60e2,4.16e2,&
+ 4.20e3,2.07e3,2.07e3,1.04e3,7.20e2,5.60e2,4.16e2/), (/7,4/))
+
+ real(r8),parameter,dimension(psrfty,plsice) :: &! mass density (kg/m3)
+ rhtype = reshape(&
+ (/1.00e3,9.20e2,9.20e2,2.50e3,2.50e3,2.50e3,2.50e3,&
+ 1.00e3,9.20e2,9.20e2,2.50e3,2.50e3,2.50e3,2.50e3,&
+ 1.00e3,9.20e2,9.20e2,2.50e3,2.50e3,2.50e3,2.50e3,&
+ 1.00e3,9.20e2,9.20e2,2.50e3,2.50e3,2.50e3,2.50e3/),(/7,4/))
+
+ real(r8),parameter,dimension(psrfty,plsice) :: &!layer thicknesses (m)
+ thckly = reshape(&
+ (/ 2., .500, .250, .050, .090, .080, .120, &
+ 5., .500, .500, .366, .390, .435, .492, &
+ 10., .500, .500,1.369,1.459,1.628,1.841, &
+ 33., .500,8.500,6.990,7.450,8.310,9.400/), (/7,4/))
+
+ real(r8),parameter,dimension(psrfty,plsice) :: &!thermal conductivity (W/m/K)
+ tktype = reshape(&
+ (/15.0 ,2.200 ,2.200 ,1.408 ,1.104 ,1.071 ,1.019 , &
+ 15.0 ,2.200 ,2.200 ,1.408 ,1.104 ,1.071 ,1.019 , &
+ 15.0 ,2.200 ,2.200 ,1.408 ,1.104 ,1.071 ,1.019 , &
+ 15.0 ,2.200 ,2.200 ,1.408 ,1.104 ,1.071 ,1.019 /), (/7,4/))
+
+!-----------------------------------------------------------------------
+
+ rdtime = 1./deltim
+
+! calculate snow properties
+ cmsnow = (1.-frcair)*cmice + frcair*cmair
+ rhsnow = (1.-frcair)*rhice + frcair*rhair
+ tksnow = (1.-frcair)*tkice + frcair*tkair
+
+! no external heat source
+ DO j=1,plsice
+ htsrc(j) = 0.0
+ ENDDO
+
+! define logical for snow covered surfaces:
+ scvr = snowh.gt.0.
+
+! define thermal properties for each sub/surface layer, starting
+! with the top layer
+ jndx = isrfty
+ thck = thckly(jndx,1)
+ cmty = cmtype(jndx,1)
+ rhty = rhtype(jndx,1)
+ tkty = tktype(jndx,1)
+
+! initialize fields for no snow cover
+ z(0) = 0.0
+ z(1) = thck
+ cmass(1) = cmty
+ rho(1) = rhty
+ tk(1) = tkty
+
+! modify layer 1 fields for snow cover IF present
+! snow equivalent depth times snow liquid water depth gives the physical
+! depth of snow for thermal conduction computation; snow is mixed
+! uniformly by mass with the top surface layer
+ IF(scvr) THEN
+ zsnow = snowh*snwedp
+ msnow = rhsnow*zsnow
+ mlice = rhty*thck
+ rho(1) = (msnow*rhsnow + mlice*rhty)/(msnow+mlice)
+ cmass(1) = (msnow*cmsnow + mlice*cmty)/(msnow+mlice)
+ tk(1) = (msnow*tksnow + mlice*tkty)/(msnow+mlice)
+ z(1) = (msnow+mlice) / rho(1)
+ ENDIF
+
+! set surface thermal properties for the lower sub/surface layers:
+ DO j=2,plsice
+ jndx = isrfty
+ thck = thckly(jndx,j)
+ cmass(j) = cmtype(jndx,j)
+ rho(j) = rhtype(jndx,j)
+ tk(j) = tktype(jndx,j)
+ z(j) = z(j-1) + thck
+ ENDDO
+
+! define set of linear equations for temperature
+ DO j=1,plsice
+ tin(j) = tsbsf(j)
+ ENDDO
+
+! IF sea ice, compute heat flux from underlying ocean, assumed to be at
+! the temperature of -2C
+ fbt = 0.0
+ IF(isrfty.eq.2) THEN
+ zbot = 0.5*(z(plsice) - z(plsice-1))
+ fbt = -tk(plsice)*(271.16 - tin(plsice))/zbot
+ ENDIF
+
+! set up linear equations
+ sbdiag(1) = 0.
+ spdiag(plsice) = 0.
+
+! single layer
+ IF (plsice.eq.1) THEN
+ rztop = 1./(z(1) - z(0))
+ crt = (cmass(1)*rho(1)*rdtime)
+ diag(1) = crt - dfntdt*rztop
+ rhs(1) = diag(1)*tin(1) + fnt*rztop - fbt*rztop + htsrc(1)
+
+! more than one layer: top layer first
+ ELSEIF (plsice.gt.1) THEN
+
+ crt = cmass(1)*rho(1)*rdtime
+ ztop = z(1) - z(0)
+ rztop = 1./ztop
+ tktop = 0.5*(tk(1) + tk(2))
+ zmpl = 0.5*(z(2) + z(1))
+ zm = 0.5*(z(1) + z(0))
+ delzpl = zmpl - zm
+ fpls = 1./(ztop*delzpl)
+ tmp = crt - dfntdt*rztop
+
+ diag(1) = tmp + tktop*fpls
+ spdiag(1) = -tktop*fpls
+ rhs(1) = tmp*tin(1) + fnt*rztop + htsrc(1)
+
+! intermediate layers
+ DO j=2,plsice-1
+ crt = cmass(j)*rho(j)*rdtime
+ delz = z(j) - z(j-1)
+ zmpl = 0.5*(z(j+1) + z(j))
+ zm = 0.5*(z(j) + z(j-1))
+ zmmn = 0.5*(z(j-1) + z(j-2))
+ delzpl = zmpl - zm
+ delzmn = zm - zmmn
+ fpls = 1./(delz*delzpl)
+ fmns = 1./(delz*delzmn)
+ tkpls = 0.5*(tk(j+1)+tk(j))
+ tkmns = 0.5*(tk(j)+tk(j-1))
+
+ sbdiag(j) = -tkmns*fmns
+ diag(j) = crt + (tkpls*fpls + tkmns*fmns)
+ spdiag(j) = -tkpls*fpls
+ rhs(j) = crt*tin(j) + htsrc(j)
+ ENDDO
+
+! bottom layer
+ crt = cmass(plsice)*rho(plsice)*rdtime
+ zbot = z(plsice) - z(plsice-1)
+ zm = 0.5*(z(plsice) + z(plsice-1))
+ zmmn = 0.5*(z(plsice-1) + z(plsice-2))
+ delzmn = zm - zmmn
+ tkbot = 0.5*(tk(plsice-1) + tk(plsice))
+ fmns = 1./(zbot*delzmn)
+ sbdiag(plsice) = -tkbot*fmns
+ diag(plsice) = crt + (tkbot*fmns)
+ rhs(plsice) = crt*tin(plsice) - fbt/zbot + htsrc(plsice)
+ ENDIF
+
+ IF(plsice.eq.1) THEN
+ tsbsf(1) = rhs(1)/diag(1)
+ ELSE
+ CALL tridia (plsice,sbdiag,diag,spdiag,rhs,tsbsf)
+ ENDIF
+
+ END SUBROUTINE srftsb
+
+END MODULE MOD_SimpleOcean
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowFraction.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowFraction.F90
new file mode 100644
index 0000000000..91b23f156a
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowFraction.F90
@@ -0,0 +1,175 @@
+#include
+
+MODULE MOD_SnowFraction
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: snowfraction
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ PUBLIC :: snowfraction_pftwrap
+#endif
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE snowfraction (lai,sai,z0m,zlnd,scv,snowdp,wt,sigf,fsno)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Provide snow cover fraction
+!
+! Original author: Yongjiu Dai, /09/1999/, /04/2014/
+!
+! !REVISIONS:
+! 10/2019, Hua Yuan: removed fveg to be compatible with PFT
+! classification
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: scv ! snow water equivalent [mm or kg/m3]
+ real(r8), intent(in) :: snowdp ! snow depth [m]
+ real(r8), intent(in) :: z0m ! aerodynamic roughness length [m]
+ real(r8), intent(in) :: zlnd ! aerodynamic roughness length over soil surface [m]
+ real(r8), intent(in) :: lai ! leaf area index [-]
+ real(r8), intent(in) :: sai ! stem area index [-]
+
+ real(r8), intent(out) :: wt ! fraction of vegetation covered with snow [-]
+ real(r8), intent(out) :: sigf ! fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(out) :: fsno ! fraction of soil covered by snow [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: fmelt ! dimensionless melting factor
+ real(r8), parameter :: m = 1.0 ! the value of m used in CLM4.5 is 1.0.
+ ! WHILE the value of m given by Niu et al (2007) is 1.6
+ ! WHILE Niu (2012) suggested 3.0
+
+!-----------------------------------------------------------------------
+ IF(lai+sai > 1e-6) THEN
+ ! Fraction of vegetation buried (covered) by snow
+ wt = 0.1*snowdp/z0m
+ wt = wt/(1.+wt)
+
+ ! Fraction of vegetation cover free of snow
+ sigf = 1. - wt
+ ELSE
+ wt = 0.
+ sigf = 1.
+ ENDIF
+
+! 10/16/2019, yuan:
+ !IF(sigf < 0.001) sigf = 0.
+ !IF(sigf > 0.999) sigf = 1.
+
+! Fraction of soil covered by snow
+ fsno = 0.0
+ IF(snowdp > 0.) THEN
+ fmelt = (scv/snowdp/100.) ** m
+ fsno = tanh(snowdp/(2.5 * zlnd * fmelt))
+ ENDIF
+
+ END SUBROUTINE snowfraction
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ SUBROUTINE snowfraction_pftwrap (ipatch,zlnd,scv,snowdp,wt,sigf,fsno)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! A wrap SUBROUTINE to calculate snow cover fraction for PFT|PC run
+!
+! !REVISIONS:
+!
+! 06/2019, Hua Yuan: initial code adapted from snowfraction() by
+! Yongjiu Dai
+!
+! 08/2019, Hua Yuan: removed fveg to be compatible with PFT
+! classification
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_LandPFT
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ipatch ! patch index
+
+ real(r8), intent(in) :: zlnd ! aerodynamic roughness length over soil surface [m]
+ real(r8), intent(in) :: scv ! snow water equivalent [mm or kg/m3]
+ real(r8), intent(in) :: snowdp ! snow depth [m]
+
+ real(r8), intent(out) :: wt ! fraction of vegetation covered with snow [-]
+ real(r8), intent(out) :: sigf ! fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(out) :: fsno ! fraction of soil covered by snow [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: fmelt ! dimensionless melting factor
+ real(r8), parameter :: m = 1.0 ! the value of m used in CLM4.5 is 1.0.
+ ! WHILE the value of m given by Niu et al (2007) is 1.6
+ ! WHILE Niu (2012) suggested 3.0
+
+ integer i, p, ps, pe
+ real(r8) wt_tmp
+!-----------------------------------------------------------------------
+
+ wt_tmp = 0.
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ DO i = ps, pe
+ p = pftclass(i)
+
+ IF(tlai_p(i)+tsai_p(i) > 1.e-6) THEN
+ ! Fraction of vegetation buried (covered) by snow
+ wt = 0.1*snowdp/z0m_p(i)
+ wt = wt/(1.+wt)
+
+ ! Fraction of vegetation cover free of snow
+ sigf_p(i) = 1. - wt
+ ELSE
+ wt = 0.
+ sigf_p(i) = 1.
+ ENDIF
+
+ ! snow on vegetation, USE snowdp to calculate buried fraction
+ IF ( DEF_VEG_SNOW .and. tlai_p(i)+tsai_p(i) > 1.e-6 ) THEN
+ ! for trees, use hbot, htop to determine how much lsai being buried.
+ IF (p.gt.0 .and. p.le.8) THEN
+ wt = max(0., (snowdp-hbot_p(i))) / (htop_p(i)-hbot_p(i))
+ wt = min(wt, 1.)
+ sigf_p(i) = 1. - wt
+ ENDIF
+ ENDIF
+
+ wt_tmp = wt_tmp + wt*pftfrac(i)
+ ENDDO
+
+ wt = wt_tmp
+ sigf = sum(sigf_p(ps:pe) * pftfrac(ps:pe))
+
+ ! Fraction of soil covered by snow
+ fsno = 0.0
+ IF(snowdp > 0.) THEN
+ fmelt = (scv/snowdp/100.) ** m
+ fsno = tanh(snowdp/(2.5 * zlnd * fmelt))
+ ENDIF
+
+ END SUBROUTINE snowfraction_pftwrap
+#endif
+
+END MODULE MOD_SnowFraction
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowLayersCombineDivide.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowLayersCombineDivide.F90
new file mode 100644
index 0000000000..e108a351d0
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowLayersCombineDivide.F90
@@ -0,0 +1,1290 @@
+#include
+
+MODULE MOD_SnowLayersCombineDivide
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: snowcompaction
+ PUBLIC :: snowlayerscombine
+ PUBLIC :: SnowLayersCombine_snicar
+ PUBLIC :: snowlayersdivide
+ PUBLIC :: SnowLayersDivide_snicar
+
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: combo
+ PRIVATE :: winddriftcompaction
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+
+ SUBROUTINE snowcompaction (lb,deltim,imelt,fiold,&
+ t_soisno,wliq_soisno,wice_soisno,forc_us,forc_vs,dz_soisno)
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+! Revision: Yongjiu Dai, /07/31/2023
+!
+! Four of metamorphisms of changing snow characteristics are
+! implemented, i.e., destructive, overburden, melt and wind drift. The
+! treatments of the destructive compaction was from SNTHERM.89 and
+! SNTHERM.99 (1991, 1999). The contribution due to melt metamorphism is
+! simply taken as a ratio of snow ice fraction after the melting versus
+! before the melting. The treatments of the overburden compaction and
+! the drifting compaction were borrowed from CLM5.0 which based on
+! Vionnet et al. (2012) and van Kampenhout et al (2017).
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o, tfrz
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: lb ! lower bound of array
+ real(r8), intent(in) :: deltim ! seconds i a time step [second]
+ integer, intent(in) :: imelt(lb:0) ! signifies IF node in melting (imelt = 1)
+ real(r8), intent(in) :: fiold(lb:0) ! fraction of ice relative to the total water content
+ ! at the previous time step
+ real(r8), intent(in) :: t_soisno(lb:0) ! nodal temperature [K]
+ real(r8), intent(in) :: wice_soisno(lb:0) ! ice lens [kg/m2]
+ real(r8), intent(in) :: wliq_soisno(lb:0) ! liquid water [kg/m2]
+ real(r8), intent(in) :: forc_us ! wind speed in eastward direction [m/s]
+ real(r8), intent(in) :: forc_vs ! wind speed in northward direction [m/s]
+
+ real(r8), intent(inout) :: dz_soisno(lb:0) ! layer thickness [m]
+
+!-------------------------- Local Variables ----------------------------
+ integer j ! Numeber of doing loop
+
+ real(r8), parameter :: c1 = 2.777e-7 ! [m2/(kg s)]
+ real(r8), parameter :: c2 = 23.0e-3 ! [m3/kg]
+ real(r8), parameter :: c3 = 2.777e-6 ! [1/s]
+ real(r8), parameter :: c4 = 0.04 ! [1/K]
+ real(r8), parameter :: c5 = 2.0 !
+ real(r8), parameter :: c6 = 5.15e-7 !
+ real(r8), parameter :: c7 = 4.0 !
+ ! Upper Limit on Destructive Metamorphism Compaction [kg/m3]
+ real(r8), parameter :: dm = 100.0
+ real(r8), parameter :: eta0 = 9.e5 ! The Viscosity Coefficient Eta0 [kg-s/m2]
+
+ real(r8) :: burden ! pressure of overlying snow [kg/m2]
+ real(r8) :: ddz1 ! rate of settling of snowpack due to destructive metamorphism.
+ real(r8) :: ddz2 ! rate of compaction of snowpack due to overburden.
+ real(r8) :: ddz3 ! rate of compaction of snowpack due to melt [1/s]
+ real(r8) :: ddz4 ! rate of compaction of snowpack due to wind drift.
+
+ real(r8) :: dexpf ! expf=exp(-c4*(273.15-t_soisno)).
+ real(r8) :: fi ! fraction of ice relative to the total water content at current time step
+ real(r8) :: td ! t_soisno - tfrz [K]
+ real(r8) :: pdzdtc ! nodal rate of change in fractional-thickness due to compaction [fraction/s]
+ real(r8) :: void ! void (1 - vol_ice - vol_liq)
+ real(r8) :: wx ! water mass (ice+liquid) [kg/m2]
+ real(r8) :: bi ! partial density of ice [kg/m3]
+
+ real(r8) :: zpseudo ! wind drift compaction / pseudo depth
+ ! (only valid IF wind_dependent_snow_density is .true.)
+ logical :: mobile ! current snow layer is mobile, i.e. susceptible to wind drift
+ ! (only valid IF wind_dependent_snow_density is .true.)
+ real(r8) :: f1, f2, eta, forc_wind
+
+!-----------------------------------------------------------------------
+ ! Begin calculation - note that the following column loops are only invoked IF lb < 0
+
+ burden = 0.0
+ zpseudo = 0.0
+ mobile = .true.
+
+ DO j = lb, 0
+ wx = wice_soisno(j) + wliq_soisno(j)
+ void = 1.0-(wice_soisno(j)/denice + wliq_soisno(j)/denh2o)/dz_soisno(j)
+
+! Disallow compaction for water saturated node and lower ice lens node.
+ IF(void <= 0.001 .or. wice_soisno(j) <= .1)THEN
+ burden = burden+wx
+
+ ! saturated node is immobile
+ ! This is only needed IF wind_dependent_snow_density is true, but it's
+ ! simplest just to update mobile always
+ mobile = .false.
+
+ CYCLE
+ ENDIF
+
+ bi = wice_soisno(j) / dz_soisno(j)
+ fi = wice_soisno(j) / wx
+ td = tfrz-t_soisno(j)
+
+ dexpf = exp(-c4*td)
+
+! Compaction due to destructive metamorphism
+ ddz1 = -c3*dexpf
+ IF(bi > dm) ddz1 = ddz1*exp(-46.0e-3*(bi-dm))
+
+! Liquid water term
+ IF(wliq_soisno(j) > 0.01*dz_soisno(j)) ddz1=ddz1*c5
+
+! Compaction due to overburden
+!* ddz2 = -burden*exp(-0.08*td-c2*bi)/eta0
+ f1 = 1.0/(1.0+60.0*wliq_soisno(j)/(denh2o*dz_soisno(j)))
+ f2 = 4.0 ! currently fixed to maximum value, holds in absence of angular grains
+ eta = f1*f2*(bi/450.0)*exp(0.1*td + c2*bi)*7.62237e6
+ ddz2 = -(burden+wx/2.0) / eta
+
+! Compaction occurring during melt
+ IF(imelt(j) == 1)THEN
+ ddz3 = - 1.0/deltim * max(0.0,(fiold(j) - fi)/fiold(j))
+ ELSE
+ ddz3 = 0.0
+ ENDIF
+
+! Compaction occurring due to wind drift
+ forc_wind = sqrt(forc_us**2+forc_vs**2)
+ CALL winddriftcompaction( bi,forc_wind,dz_soisno(j),zpseudo,mobile,ddz4 )
+
+! Time rate of fractional change in dz (units of s-1)
+ pdzdtc = ddz1 + ddz2 + ddz3 + ddz4
+
+! The change in dz_soisno due to compaction
+! Limit compaction to be no greater than fully saturated layer thickness
+ dz_soisno(j) = dz_soisno(j)*(1.0+pdzdtc*deltim)
+ dz_soisno(j) = max(dz_soisno(j),(wice_soisno(j)/denice+ wliq_soisno(j)/denh2o))
+
+! Pressure of overlying snow
+ burden = burden+wx
+
+ ENDDO
+
+ END SUBROUTINE snowcompaction
+
+
+
+ SUBROUTINE winddriftcompaction(bi,forc_wind,dz,zpseudo,mobile,compaction_rate)
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! Compute wind drift compaction for a single column and level. Also
+! updates zpseudo and mobile for this column. However, zpseudo remains
+! unchanged IF mobile is already false or becomes false within this
+! SUBROUTINE.
+!
+! The structure of the updates done here for zpseudo and mobile
+! requires that this SUBROUTINE be called first for the top layer of
+! snow, THEN for the 2nd layer down, etc. - and finally for the bottom
+! layer. Before beginning the loops over layers, mobile should be
+! initialized to .true. and zpseudo should be initialized to 0.
+!
+! !REVISIONS: Yongjiu Dai, /07/31/2023
+!
+! !USES:
+ USE MOD_Precision
+ !
+ ! !ARGUMENTS:
+ real(r8) , intent(in) :: bi ! partial density of ice [kg/m3]
+ real(r8) , intent(in) :: forc_wind ! atmospheric wind speed [m/s]
+ real(r8) , intent(in) :: dz ! layer depth for this column and level [m]
+ ! wind drift compaction / pseudo depth for this column at this layer
+ real(r8) , intent(inout) :: zpseudo
+ ! whether this snow column is still mobile at this layer (i.e., susceptible to wind drift)
+ logical , intent(inout) :: mobile
+ ! rate of compaction of snowpack due to wind drift, for the current column and layer
+ real(r8) , intent(out) :: compaction_rate
+ !
+ ! !LOCAL VARIABLES:
+ real(r8) :: Frho ! Mobility density factor [-]
+ real(r8) :: MO ! Mobility index [-]
+ real(r8) :: SI ! Driftability index [-]
+ real(r8) :: gamma_drift ! Scaling factor for wind drift time scale [-]
+ real(r8) :: tau_inverse ! Inverse of the effective time scale [1/s]
+
+ real(r8), parameter :: rho_min = 50._r8 ! wind drift compaction / minimum density [kg/m3]
+ real(r8), parameter :: rho_max = 350._r8 ! wind drift compaction / maximum density [kg/m3]
+ ! wind drift compaction / grain size (fixed value for now)
+ real(r8), parameter :: drift_gs = 0.35e-3_r8
+ real(r8), parameter :: drift_sph = 1.0_r8 ! wind drift compaction / sphericity
+ real(r8), parameter :: tau_ref = 48._r8 * 3600._r8 ! wind drift compaction / reference time [s]
+
+ !-----------------------------------------------------------------------
+
+ IF (mobile) THEN
+ Frho = 1.25_r8 - 0.0042_r8*(max(rho_min, bi)-rho_min)
+ ! assuming dendricity = 0, sphericity = 1, grain size = 0.35 mm Non-dendritic snow
+ MO = 0.34_r8 * (-0.583_r8*drift_gs - 0.833_r8*drift_sph + 0.833_r8) + 0.66_r8*Frho
+ SI = -2.868_r8 * exp(-0.085_r8*forc_wind) + 1._r8 + MO
+
+ IF (SI > 0.0_r8) THEN
+ SI = min(SI, 3.25_r8)
+ ! Increase zpseudo (wind drift / pseudo depth) to the middle of
+ ! the pseudo-node for the sake of the following calculation
+ zpseudo = zpseudo + 0.5_r8 * dz * (3.25_r8 - SI)
+ gamma_drift = SI*exp(-zpseudo/0.1_r8)
+ tau_inverse = gamma_drift / tau_ref
+ compaction_rate = -max(0.0_r8, rho_max-bi) * tau_inverse
+ ! Further increase zpseudo to the bottom of the pseudo-node for
+ ! the sake of calculations done on the underlying layer (i.e.,
+ ! the next time through the j loop).
+ zpseudo = zpseudo + 0.5_r8 * dz * (3.25_r8 - SI)
+ ELSE ! SI <= 0
+ mobile = .false.
+ compaction_rate = 0._r8
+ ENDIF
+ ELSE ! .not. mobile
+ compaction_rate = 0._r8
+ ENDIF
+
+ END SUBROUTINE winddriftcompaction
+
+
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE snowlayerscombine (lb,snl, &
+ z_soisno,dz_soisno,zi_soisno,wliq_soisno,wice_soisno,t_soisno,scv,snowdp)
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! checks for elements which are below prescribed minimum for thickness
+! or mass. If snow element thickness or mass is less than a prescribed
+! minimum, it is combined with neighboring element to be best combine
+! with, and executes the combination of mass and energy in
+! clm_combo.f90
+!
+!=======================================================================
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: lb ! lower bound of array
+
+! numbering from 1 (bottom) mss (surface)
+ real(r8), intent(inout) :: wice_soisno(lb:1) ! ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:1) ! liquid water {kg/m2]
+ real(r8), intent(inout) :: t_soisno (lb:1) ! node temperature [K]
+ real(r8), intent(inout) :: dz_soisno (lb:1) ! layer thickness [m]
+ real(r8), intent(inout) :: z_soisno (lb:1) ! node depth [m]
+ real(r8), intent(inout) :: zi_soisno (lb-1:1) ! depth of layer interface [m]
+ real(r8), intent(inout) :: snowdp ! snow depth [m]
+ real(r8), intent(inout) :: scv ! snow mass - water equivalent [kg/m2]
+ integer, intent(inout) :: snl ! Number of snow
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: drr ! thickness of the combined [m]
+ real(r8) :: dzmin(5) ! minimum of snow layer 1 (top) to msn0 (bottom)
+ real(r8) :: zwice ! total ice mass in snow
+ real(r8) :: zwliq ! total liquid water in snow
+
+ integer :: i ! number of DO looping
+ integer :: j ! node index
+ integer :: k ! number of DO looping
+ integer :: l ! node index
+ integer :: msn_old ! number of snow layer 1 (top) to msn0 (bottom)
+ integer :: mssi ! node index
+ integer :: neibor ! adjacent node selected for combination
+
+ data dzmin /0.010, 0.015, 0.025, 0.055, 0.115/
+
+!-----------------------------------------------------------------------
+! check the mass of ice lens of snow, when the total less than a small value,
+! combine it with the underlying neighbor
+ msn_old = snl
+ DO j = msn_old+1, 0
+ IF(wice_soisno(j) <= .1)THEN
+ wliq_soisno(j+1) = wliq_soisno(j+1) + wliq_soisno(j)
+ wice_soisno(j+1) = wice_soisno(j+1) + wice_soisno(j)
+
+! shift all elements above this down one.
+ IF(j > snl+1 .and. snl < -1)THEN
+ DO i = j, snl+2, -1
+ t_soisno(i) = t_soisno(i-1)
+ wliq_soisno(i) = wliq_soisno(i-1)
+ wice_soisno(i) = wice_soisno(i-1)
+ dz_soisno(i) = dz_soisno(i-1)
+ ENDDO
+ ENDIF
+
+ snl = snl + 1
+!* write(6,*) 'one snow layer is gone'
+
+ ENDIF
+
+ ENDDO
+
+ IF(snl == 0)THEN
+ scv = 0.
+ snowdp = 0.
+!* write(6,*) 'all snow has gone'
+ RETURN
+ ELSE
+ scv = 0.
+ snowdp = 0.
+ zwice = 0.
+ zwliq = 0.
+ DO j = snl + 1, 0
+ scv = scv + wice_soisno(j) + wliq_soisno(j)
+ snowdp = snowdp + dz_soisno(j)
+ zwice = zwice + wice_soisno(j)
+ zwliq = zwliq + wliq_soisno(j)
+ ENDDO
+ ENDIF
+!-----------------------------------------------------------------------
+! check the snow depth
+
+ IF(snowdp < 0.01)THEN !!! all snow gone
+
+ snl = 0
+ scv = zwice
+ IF(scv <= 0.) snowdp = 0.
+
+! the liquid water assumed ponding on soil surface
+ wliq_soisno(1) = wliq_soisno(1) + zwliq
+!* write(6,'(17h all snow is gone)')
+ RETURN
+
+ ELSE !!! snow layers combined
+
+! two or more layers
+
+ IF(snl < -1)THEN
+ msn_old = snl
+ mssi = 1
+ DO i = msn_old+1, 0
+
+! If top node is removed, combine with bottom neighbor
+ IF(dz_soisno(i) < dzmin(mssi))THEN
+ IF(i == snl+1)THEN
+ neibor = i + 1
+
+! If the bottom neighbor is not snow, combine with the top neighbor
+ ELSEIF(i == 0)THEN
+ neibor = i - 1
+
+! If NONE of the above special cases apply, combine with the thinnest neighbor
+ ELSE
+ neibor = i + 1
+ IF((dz_soisno(i-1)+dz_soisno(i)) < (dz_soisno(i+1)+dz_soisno(i))) neibor = i-1
+ ENDIF
+
+! Node l and j are combined and stored as node j.
+
+ IF(neibor > i)THEN
+ j = neibor
+ l = i
+ ELSE
+ j = i
+ l = neibor
+ ENDIF
+ CALL combo ( dz_soisno(j), wliq_soisno(j), wice_soisno(j), t_soisno(j),&
+ dz_soisno(l), wliq_soisno(l), wice_soisno(l), t_soisno(l) )
+
+! Now shift all elements above this down one.
+
+ IF(j-1 > snl+1) THEN
+ DO k = j-1, snl+2, -1
+ t_soisno(k) = t_soisno(k-1)
+ wice_soisno(k) = wice_soisno(k-1)
+ wliq_soisno(k) = wliq_soisno(k-1)
+ dz_soisno(k) = dz_soisno(k-1)
+ ENDDO
+ ENDIF
+
+ snl = snl + 1
+
+!* write(6,'(7h Nodes ,i4,4h and,i4,14h combined into,i4)') l,j,j
+
+ IF(snl >= -1) EXIT
+
+! The layer thickness great than the prescribed minimum value
+
+ ELSE
+ mssi = mssi + 1
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+! Reset the node depth and the depth of layer interface
+
+ zi_soisno(0) = 0.
+ DO k = 0, snl+1, -1
+ z_soisno(k) = zi_soisno(k) - 0.5*dz_soisno(k)
+ zi_soisno(k-1) = zi_soisno(k) - dz_soisno(k)
+ ENDDO
+
+ ENDIF !!! snow layers combined
+
+ END SUBROUTINE snowlayerscombine
+
+
+
+ SUBROUTINE snowlayersdivide(lb,snl,z_soisno,dz_soisno,zi_soisno,wliq_soisno,wice_soisno,t_soisno)
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! subdivides snow layer when its thickness exceed the prescribed maximum
+!=======================================================================
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: lb ! lower bound of array
+ integer, intent(inout) :: snl ! Number of snow
+ real(r8), intent(inout) :: wice_soisno(lb:0) ! ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:0) ! liquid water [kg/m2]
+ real(r8), intent(inout) :: t_soisno (lb:0) ! Node temperature [K]
+ real(r8), intent(inout) :: dz_soisno (lb:0) ! Layer thickness [m]
+ real(r8), intent(inout) :: z_soisno (lb:0) ! Node depth [m]
+ real(r8), intent(inout) :: zi_soisno (lb-1:0) ! Depth of layer interface [m]
+
+!-------------------------- Local Variables ----------------------------
+
+! numbering from 1 (surface) msno (bottom)
+ real(r8) :: drr ! thickness of the combined [m]
+ real(r8) :: dzsno(5) ! Snow layer thickness [m]
+ real(r8) :: swice(5) ! Partial volume of ice [m3/m3]
+ real(r8) :: swliq(5) ! Partial volume of liquid water [m3/m3]
+ real(r8) :: tsno(5) ! Nodel temperature [K]
+
+ integer k ! number of DO looping
+ integer msno ! number of snow layer 1 (top) to msno (bottom)
+
+ real(r8) zwice,zwliq,propor
+
+!-----------------------------------------------------------------------
+
+ msno = abs(snl)
+ DO k = 1, msno
+ dzsno(k) = dz_soisno (k + snl)
+ swice(k) = wice_soisno(k + snl)
+ swliq(k) = wliq_soisno(k + snl)
+ tsno(k) = t_soisno (k + snl)
+ ENDDO
+
+ IF(msno == 1)THEN
+ IF(dzsno(1) > 0.03)THEN
+ msno = 2
+! Specified a new snow layer
+ dzsno(1) = dzsno(1)/2.
+ swice(1) = swice(1)/2.
+ swliq(1) = swliq(1)/2.
+
+ dzsno(2) = dzsno(1)
+ swice(2) = swice(1)
+ swliq(2) = swliq(1)
+ tsno(2) = tsno(1)
+! write(6,*)'Subdivided Top Node into two layer (1/2)'
+ ENDIF
+ ENDIF
+
+ IF(msno > 1)THEN
+ IF(dzsno(1) > 0.02)THEN
+ drr = dzsno(1) - 0.02
+ propor = drr/dzsno(1)
+ zwice = propor*swice(1)
+ zwliq = propor*swliq(1)
+
+ propor = 0.02/dzsno(1)
+ swice(1) = propor*swice(1)
+ swliq(1) = propor*swliq(1)
+ dzsno(1) = 0.02
+
+ CALL combo(dzsno(2),swliq(2),swice(2),tsno(2), &
+ drr,zwliq,zwice,tsno(1))
+
+! write(6,*) 'Subdivided Top Node &
+! 20 mm combined into underlying neighbor'
+
+ IF(msno <= 2 .and. dzsno(2) > 0.07)THEN
+! subdivided a new layer
+ msno = 3
+ dzsno(2) = dzsno(2)/2.
+ swice(2) = swice(2)/2.
+ swliq(2) = swliq(2)/2.
+
+ dzsno(3) = dzsno(2)
+ swice(3) = swice(2)
+ swliq(3) = swliq(2)
+ tsno(3) = tsno(2)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF(msno > 2)THEN
+ IF(dzsno(2) > 0.05)THEN
+ drr = dzsno(2) - 0.05
+ propor = drr/dzsno(2)
+ zwice = propor*swice(2)
+ zwliq = propor*swliq(2)
+
+ propor = 0.05/dzsno(2)
+ swice(2) = propor*swice(2)
+ swliq(2) = propor*swliq(2)
+ dzsno(2) = 0.05
+
+ CALL combo(dzsno(3),swliq(3),swice(3),tsno(3), &
+ drr, zwliq, zwice, tsno(2))
+
+! write(6,*)'Subdivided 50 mm from the subsurface layer &
+! &and combined into underlying neighbor'
+
+ IF(msno <= 3 .and. dzsno(3) > 0.18)THEN
+! subdivided a new layer
+ msno = 4
+ dzsno(3) = dzsno(3)/2.
+ swice(3) = swice(3)/2.
+ swliq(3) = swliq(3)/2.
+
+ dzsno(4) = dzsno(3)
+ swice(4) = swice(3)
+ swliq(4) = swliq(3)
+ tsno(4) = tsno(3)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF(msno > 3)THEN
+ IF(dzsno(3) > 0.11)THEN
+ drr = dzsno(3) - 0.11
+ propor = drr/dzsno(3)
+ zwice = propor*swice(3)
+ zwliq = propor*swliq(3)
+
+ propor = 0.11/dzsno(3)
+ swice(3) = propor*swice(3)
+ swliq(3) = propor*swliq(3)
+ dzsno(3) = 0.11
+
+ CALL combo(dzsno(4),swliq(4),swice(4),tsno(4), &
+ drr, zwliq, zwice, tsno(3))
+
+! write(6,*)'Subdivided 110 mm from the third Node &
+! &and combined into underlying neighbor'
+
+ IF(msno <= 4 .and. dzsno(4) > 0.41)THEN
+! subdivided a new layer
+ msno = 5
+ dzsno(4) = dzsno(4)/2.
+ swice(4) = swice(4)/2.
+ swliq(4) = swliq(4)/2.
+
+ dzsno(5) = dzsno(4)
+ swice(5) = swice(4)
+ swliq(5) = swliq(4)
+ tsno(5) = tsno(4)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF(msno > 4)THEN
+ IF(dzsno(4) > 0.23)THEN
+ drr = dzsno(4) - 0.23
+ propor = drr/dzsno(4)
+ zwice = propor*swice(4)
+ zwliq = propor*swliq(4)
+
+ propor = 0.23/dzsno(4)
+ swice(4) = propor*swice(4)
+ swliq(4) = propor*swliq(4)
+ dzsno(4) = 0.23
+
+ CALL combo(dzsno(5),swliq(5),swice(5),tsno(5), &
+ drr, zwliq, zwice, tsno(4))
+
+! write(6,*)'Subdivided 230 mm from the fourth Node &
+! 'and combined into underlying neighbor'
+ ENDIF
+ ENDIF
+
+ snl = - msno
+
+ DO k = snl+1, 0
+ dz_soisno(k) = dzsno(k - snl)
+ wice_soisno(k) = swice(k - snl)
+ wliq_soisno(k) = swliq(k - snl)
+ t_soisno(k) = tsno (k - snl)
+ ENDDO
+
+ zi_soisno(0) = 0.
+ DO k = 0, snl+1, -1
+ z_soisno(k) = zi_soisno(k) - 0.5*dz_soisno(k)
+ zi_soisno(k-1) = zi_soisno(k) - dz_soisno(k)
+ ENDDO
+
+ END SUBROUTINE snowlayersdivide
+
+
+
+ SUBROUTINE combo ( dz_soisno, wliq_soisno, wice_soisno, t, &
+ dz2, wliq2, wice2, t2 )
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! combines two elements and returns the following combined
+! variabless: dz_soisno, t, wliq_soisno, wice_soisno.
+! the combined temperature is based on the equation:
+! the sum of the enthalpies of the two elements = that of the combined element.
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpice, cpliq, hfus, tfrz
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: dz2 ! nodal thickness of 2 elements being combined [m]
+ real(r8), intent(in) :: wliq2 ! liquid water of element 2 [kg/m2]
+ real(r8), intent(in) :: wice2 ! ice of element 2 [kg/m2]
+ real(r8), intent(in) :: t2 ! nodal temperature of element 2 [K]
+
+ real(r8), intent(inout) :: dz_soisno ! nodal thickness of 1 elements being combined [m]
+ real(r8), intent(inout) :: wliq_soisno ! liquid water of element 1
+ real(r8), intent(inout) :: wice_soisno ! ice of element 1 [kg/m2]
+ real(r8), intent(inout) :: t ! node temperature of elment 1 [K]
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) dzc ! Total thickness of nodes 1 and 2 (dzc=dz_soisno+dz2).
+ real(r8) wliqc ! Combined liquid water [kg/m2]
+ real(r8) wicec ! Combined ice [kg/m2]
+ real(r8) tc ! Combined node temperature [K]
+ real(r8) h ! enthalpy of element 1 [J/m2]
+ real(r8) h2 ! enthalpy of element 2 [J/m2]
+ real(r8) hc ! temporary
+
+!-----------------------------------------------------------------------
+
+ dzc = dz_soisno+dz2
+ wicec = (wice_soisno+wice2)
+ wliqc = (wliq_soisno+wliq2)
+ h = (cpice*wice_soisno+cpliq*wliq_soisno)*(t-tfrz)+hfus*wliq_soisno
+ h2 = (cpice*wice2+cpliq*wliq2)*(t2-tfrz)+hfus*wliq2
+
+ hc = h + h2
+ IF(hc < 0.)THEN
+ tc = tfrz + hc/(cpice*wicec+cpliq*wliqc)
+ ELSEIF(hc.le.hfus*wliqc)THEN
+ tc = tfrz
+ ELSE
+ tc = tfrz + (hc - hfus*wliqc)/(cpice*wicec+cpliq*wliqc)
+ ENDIF
+
+ dz_soisno = dzc
+ wice_soisno = wicec
+ wliq_soisno = wliqc
+ t = tc
+
+ END SUBROUTINE combo
+
+
+ SUBROUTINE SnowLayersCombine_snicar (lb,snl, &
+ z_soisno,dz_soisno,zi_soisno,wliq_soisno,wice_soisno,t_soisno,scv,snowdp,&
+
+! Aerosol Fluxes (Jan. 07, 2023)
+ mss_bcpho, mss_bcphi, mss_ocpho, mss_ocphi,&
+ mss_dst1 , mss_dst2 , mss_dst3 , mss_dst4 )
+! Aerosol Fluxes (Jan. 07, 2023)
+
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999; January 07, 2023
+!
+! checks for elements which are below prescribed minimum for thickness or mass.
+! If snow element thickness or mass is less than a prescribed minimum,
+! it is combined with neighboring element to be best combine with,
+! and executes the combination of mass and energy in clm_combo.f90
+!
+! !REVISIONS:
+! Yongjiu Dai, 01/2023: added Aerosol fluxes from SNICAR model
+!=======================================================================
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: lb ! lower bound of array
+
+! numbering from 1 (bottom) mss (surface)
+ real(r8), intent(inout) :: wice_soisno(lb:1) ! ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:1) ! liquid water {kg/m2]
+ real(r8), intent(inout) :: t_soisno (lb:1) ! node temperature [K]
+ real(r8), intent(inout) :: dz_soisno (lb:1) ! layer thickness [m]
+ real(r8), intent(inout) :: z_soisno (lb:1) ! node depth [m]
+ real(r8), intent(inout) :: zi_soisno (lb-1:1) ! depth of layer interface [m]
+ real(r8), intent(inout) :: snowdp ! snow depth [m]
+ real(r8), intent(inout) :: scv ! snow mass - water equivalent [kg/m2]
+ integer, intent(inout) :: snl ! Number of snow
+
+! Aerosol Fluxes (Jan. 07, 2023)
+ real(r8), intent(inout) :: &
+ mss_bcpho (lb:0), &! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi (lb:0), &! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho (lb:0), &! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi (lb:0), &! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 (lb:0), &! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 (lb:0), &! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 (lb:0), &! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 (lb:0) ! mass of dust species 4 in snow (col,lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: drr ! thickness of the combined [m]
+ real(r8) :: dzmin(5) ! minimum of snow layer 1 (top) to msn0 (bottom)
+ real(r8) :: zwice ! total ice mass in snow
+ real(r8) :: zwliq ! total liquid water in snow
+
+ integer :: i ! number of DO looping
+ integer :: j ! node index
+ integer :: k ! number of DO looping
+ integer :: l ! node index
+ integer :: msn_old ! number of snow layer 1 (top) to msn0 (bottom)
+ integer :: mssi ! node index
+ integer :: neibor ! adjacent node selected for combination
+
+ data dzmin /0.010, 0.015, 0.025, 0.055, 0.115/
+
+!-----------------------------------------------------------------------
+! check the mass of ice lens of snow, when the total less than a small value,
+! combine it with the underlying neighbor
+ msn_old = snl
+ DO j = msn_old+1, 0
+ IF(wice_soisno(j) <= .1)THEN
+ wliq_soisno(j+1) = wliq_soisno(j+1) + wliq_soisno(j)
+ wice_soisno(j+1) = wice_soisno(j+1) + wice_soisno(j)
+
+!Aerosol Fluxes (January 07, 2023)
+ IF (j < 0) THEN ! 01/11/2023, yuan: add j < 0
+ mss_bcphi(j+1) = mss_bcphi(j+1) + mss_bcphi(j)
+ mss_bcpho(j+1) = mss_bcpho(j+1) + mss_bcpho(j)
+ mss_ocphi(j+1) = mss_ocphi(j+1) + mss_ocphi(j)
+ mss_ocpho(j+1) = mss_ocpho(j+1) + mss_ocpho(j)
+ mss_dst1 (j+1) = mss_dst1 (j+1) + mss_dst1 (j)
+ mss_dst2 (j+1) = mss_dst2 (j+1) + mss_dst2 (j)
+ mss_dst3 (j+1) = mss_dst3 (j+1) + mss_dst3 (j)
+ mss_dst4 (j+1) = mss_dst4 (j+1) + mss_dst4 (j)
+ ENDIF
+!Aerosol Fluxes (January 07, 2023)
+
+
+! shift all elements above this down one.
+ IF(j > snl+1 .and. snl < -1)THEN
+ DO i = j, snl+2, -1
+ t_soisno(i) = t_soisno(i-1)
+ wliq_soisno(i) = wliq_soisno(i-1)
+ wice_soisno(i) = wice_soisno(i-1)
+ dz_soisno(i) = dz_soisno(i-1)
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_bcphi(i) = mss_bcphi(i-1)
+ mss_bcpho(i) = mss_bcpho(i-1)
+ mss_ocphi(i) = mss_ocphi(i-1)
+ mss_ocpho(i) = mss_ocpho(i-1)
+ mss_dst1 (i) = mss_dst1 (i-1)
+ mss_dst2 (i) = mss_dst2 (i-1)
+ mss_dst3 (i) = mss_dst3 (i-1)
+ mss_dst4 (i) = mss_dst4 (i-1)
+!Aerosol Fluxes (January 07, 2023)
+ ENDDO
+ ENDIF
+
+ snl = snl + 1
+!* write(6,*) 'one snow layer is gone'
+
+ ENDIF
+
+ ENDDO
+
+ IF(snl == 0)THEN
+ scv = 0._r8
+ snowdp = 0._r8
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_bcphi(:) = 0._r8
+ mss_bcpho(:) = 0._r8
+ mss_ocphi(:) = 0._r8
+ mss_ocpho(:) = 0._r8
+ mss_dst1 (:) = 0._r8
+ mss_dst2 (:) = 0._r8
+ mss_dst3 (:) = 0._r8
+ mss_dst4 (:) = 0._r8
+!Aerosol Fluxes (January 07, 2023)
+
+!* write(6,*) 'all snow has gone'
+ RETURN
+ ELSE
+ scv = 0._r8
+ snowdp = 0._r8
+ zwice = 0._r8
+ zwliq = 0._r8
+ DO j = snl + 1, 0
+ scv = scv + wice_soisno(j) + wliq_soisno(j)
+ snowdp = snowdp + dz_soisno(j)
+ zwice = zwice + wice_soisno(j)
+ zwliq = zwliq + wliq_soisno(j)
+ ENDDO
+ ENDIF
+!-----------------------------------------------------------------------
+! check the snow depth
+
+ IF(snowdp < 0.01_r8)THEN !!! all snow gone
+
+ snl = 0
+ scv = zwice
+ IF(scv <= 0._r8) snowdp = 0._r8
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_bcphi(:) = 0._r8
+ mss_bcpho(:) = 0._r8
+ mss_ocphi(:) = 0._r8
+ mss_ocpho(:) = 0._r8
+ mss_dst1 (:) = 0._r8
+ mss_dst2 (:) = 0._r8
+ mss_dst3 (:) = 0._r8
+ mss_dst4 (:) = 0._r8
+!Aerosol Fluxes (January 07, 2023)
+
+! the liquid water assumed ponding on soil surface
+ wliq_soisno(1) = wliq_soisno(1) + zwliq
+!* write(6,'(17h all snow is gone)')
+ RETURN
+
+ ELSE !!! snow layers combined
+
+! two or more layers
+
+ IF(snl < -1)THEN
+ msn_old = snl
+ mssi = 1
+ DO i = msn_old+1, 0
+
+! If top node is removed, combine with bottom neighbor
+ IF(dz_soisno(i) < dzmin(mssi))THEN
+ IF(i == snl+1)THEN
+ neibor = i + 1
+
+! If the bottom neighbor is not snow, combine with the top neighbor
+ ELSEIF(i == 0)THEN
+ neibor = i - 1
+
+! If NONE of the above special cases apply, combine with the thinnest neighbor
+ ELSE
+ neibor = i + 1
+ IF((dz_soisno(i-1)+dz_soisno(i)) < (dz_soisno(i+1)+dz_soisno(i))) neibor = i-1
+ ENDIF
+
+! Node l and j are combined and stored as node j.
+
+ IF(neibor > i)THEN
+ j = neibor
+ l = i
+ ELSE
+ j = i
+ l = neibor
+ ENDIF
+ CALL combo ( dz_soisno(j), wliq_soisno(j), wice_soisno(j), t_soisno(j),&
+ dz_soisno(l), wliq_soisno(l), wice_soisno(l), t_soisno(l) )
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_bcphi(j) = mss_bcphi(j) + mss_bcphi(l)
+ mss_bcpho(j) = mss_bcpho(j) + mss_bcpho(l)
+ mss_ocphi(j) = mss_ocphi(j) + mss_ocphi(l)
+ mss_ocpho(j) = mss_ocpho(j) + mss_ocpho(l)
+ mss_dst1 (j) = mss_dst1 (j) + mss_dst1 (l)
+ mss_dst2 (j) = mss_dst2 (j) + mss_dst2 (l)
+ mss_dst3 (j) = mss_dst3 (j) + mss_dst3 (l)
+ mss_dst4 (j) = mss_dst4 (j) + mss_dst4 (l)
+!Aerosol Fluxes (January 07, 2023)
+
+
+! Now shift all elements above this down one.
+
+ IF(j-1 > snl+1) THEN
+ DO k = j-1, snl+2, -1
+ t_soisno(k) = t_soisno(k-1)
+ wice_soisno(k) = wice_soisno(k-1)
+ wliq_soisno(k) = wliq_soisno(k-1)
+ dz_soisno(k) = dz_soisno(k-1)
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_bcphi(k) = mss_bcphi(k-1)
+ mss_bcpho(k) = mss_bcpho(k-1)
+ mss_ocphi(k) = mss_ocphi(k-1)
+ mss_ocpho(k) = mss_ocpho(k-1)
+ mss_dst1 (k) = mss_dst1 (k-1)
+ mss_dst2 (k) = mss_dst2 (k-1)
+ mss_dst3 (k) = mss_dst3 (k-1)
+ mss_dst4 (k) = mss_dst4 (k-1)
+!Aerosol Fluxes (January 07, 2023)
+ ENDDO
+ ENDIF
+
+ snl = snl + 1
+
+!* write(6,'(7h Nodes ,i4,4h and,i4,14h combined into,i4)') l,j,j
+
+ IF(snl >= -1) EXIT
+
+! The layer thickness great than the prescribed minimum value
+
+ ELSE
+ mssi = mssi + 1
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+! Reset the node depth and the depth of layer interface
+
+ zi_soisno(0) = 0._r8
+ DO k = 0, snl+1, -1
+ z_soisno(k) = zi_soisno(k) - 0.5_r8*dz_soisno(k)
+ zi_soisno(k-1) = zi_soisno(k) - dz_soisno(k)
+ ENDDO
+
+ ENDIF !!! snow layers combined
+
+ END SUBROUTINE SnowLayersCombine_snicar
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowLayersDivide_snicar (lb,snl,z_soisno,dz_soisno,zi_soisno,&
+ wliq_soisno,wice_soisno,t_soisno,&
+
+! Aerosol Fluxes (Jan. 07, 2023)
+ mss_bcpho, mss_bcphi, mss_ocpho, mss_ocphi,&
+ mss_dst1 , mss_dst2 , mss_dst3 , mss_dst4 )
+! Aerosol Fluxes (Jan. 07, 2023)
+
+
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999, January 07, 2023
+!
+! subdivides snow layer when its thickness exceed the prescribed maximum
+!
+! !REVISIONS:
+! Yongjiu Dai, 01/2023: added Aerosol fluxes from SNICAR model
+!=======================================================================
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: lb ! lower bound of array
+ integer, intent(inout) :: snl ! Number of snow
+ real(r8), intent(inout) :: wice_soisno(lb:0) ! ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_soisno(lb:0) ! liquid water [kg/m2]
+ real(r8), intent(inout) :: t_soisno (lb:0) ! Node temperature [K]
+ real(r8), intent(inout) :: dz_soisno (lb:0) ! Layer thickness [m]
+ real(r8), intent(inout) :: z_soisno (lb:0) ! Node depth [m]
+ real(r8), intent(inout) :: zi_soisno (lb-1:0) ! Depth of layer interface [m]
+
+! Aerosol Fluxes (Jan. 07, 2023)
+ real(r8), intent(inout) :: &
+ mss_bcpho (lb:0), &! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi (lb:0), &! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho (lb:0), &! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi (lb:0), &! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 (lb:0), &! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 (lb:0), &! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 (lb:0), &! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 (lb:0) ! mass of dust species 4 in snow (col,lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+
+!-------------------------- Local Variables ----------------------------
+
+! numbering from 1 (surface) msno (bottom)
+ real(r8) :: drr ! thickness of the combined [m]
+ real(r8) :: dzsno(5) ! Snow layer thickness [m]
+ real(r8) :: swice(5) ! Partial volume of ice [m3/m3]
+ real(r8) :: swliq(5) ! Partial volume of liquid water [m3/m3]
+ real(r8) :: tsno(5) ! Node temperature [K]
+
+ integer k ! number of DO looping
+ integer msno ! number of snow layer 1 (top) to msno (bottom)
+
+ real(r8) zwice,zwliq,propor
+
+!Aerosol Fluxes (January 07, 2023)
+ real(r8) mss_aerosol(5,8)
+ real(r8) z_mss_aerosol(8)
+!Aerosol Fluxes (January 07, 2023)
+
+!-----------------------------------------------------------------------
+
+ msno = abs(snl)
+ DO k = 1, msno
+ dzsno(k) = dz_soisno (k + snl)
+ swice(k) = wice_soisno(k + snl)
+ swliq(k) = wliq_soisno(k + snl)
+ tsno (k) = t_soisno (k + snl)
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(k, 1) = mss_bcphi(k+snl)
+ mss_aerosol(k, 2) = mss_bcpho(k+snl)
+ mss_aerosol(k, 3) = mss_ocphi(k+snl)
+ mss_aerosol(k, 4) = mss_ocpho(k+snl)
+ mss_aerosol(k, 5) = mss_dst1 (k+snl)
+ mss_aerosol(k, 6) = mss_dst2 (k+snl)
+ mss_aerosol(k, 7) = mss_dst3 (k+snl)
+ mss_aerosol(k, 8) = mss_dst4 (k+snl)
+!Aerosol Fluxes (January 07, 2023)
+
+ ENDDO
+
+ IF(msno == 1)THEN
+ IF(dzsno(1) > 0.03)THEN
+ msno = 2
+! Specified a new snow layer
+ dzsno(1) = dzsno(1)/2.
+ swice(1) = swice(1)/2.
+ swliq(1) = swliq(1)/2.
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(1,:) = mss_aerosol(1,:)/2.
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(2) = dzsno(1)
+ swice(2) = swice(1)
+ swliq(2) = swliq(1)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(2,:) = mss_aerosol(1,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ tsno(2) = tsno(1)
+
+! write(6,*)'Subdivided Top Node into two layer (1/2)'
+ ENDIF
+ ENDIF
+
+ IF(msno > 1)THEN
+ IF(dzsno(1) > 0.02)THEN
+ drr = dzsno(1) - 0.02
+ propor = drr/dzsno(1)
+ zwice = propor*swice(1)
+ zwliq = propor*swliq(1)
+!Aerosol Fluxes (January 07, 2023)
+ z_mss_aerosol(:) = propor*mss_aerosol(1,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ propor = 0.02/dzsno(1)
+ swice(1) = propor*swice(1)
+ swliq(1) = propor*swliq(1)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(1,:) = propor*mss_aerosol(1,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(1) = 0.02
+
+ CALL combo(dzsno(2),swliq(2),swice(2),tsno(2), &
+ drr,zwliq,zwice,tsno(1))
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(2,:) = z_mss_aerosol(:) + mss_aerosol(2,:)
+!Aerosol Fluxes (January 07, 2023)
+
+! write(6,*) 'Subdivided Top Node &
+! 20 mm combined into underlying neighbor'
+
+ IF(msno <= 2 .and. dzsno(2) > 0.07)THEN
+! subdivided a new layer
+ msno = 3
+ dzsno(2) = dzsno(2)/2.
+ swice(2) = swice(2)/2.
+ swliq(2) = swliq(2)/2.
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(2,:) = mss_aerosol(2,:)/2.
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(3) = dzsno(2)
+ swice(3) = swice(2)
+ swliq(3) = swliq(2)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(3,:) = mss_aerosol(2,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ tsno(3) = tsno(2)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF(msno > 2)THEN
+ IF(dzsno(2) > 0.05)THEN
+ drr = dzsno(2) - 0.05
+ propor = drr/dzsno(2)
+ zwice = propor*swice(2)
+ zwliq = propor*swliq(2)
+!Aerosol Fluxes (January 07, 2023)
+ z_mss_aerosol(:) = propor*mss_aerosol(2,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ propor = 0.05/dzsno(2)
+ swice(2) = propor*swice(2)
+ swliq(2) = propor*swliq(2)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(2,:) = propor*mss_aerosol(2,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(2) = 0.05
+
+ CALL combo(dzsno(3),swliq(3),swice(3),tsno(3), &
+ drr, zwliq, zwice, tsno(2))
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(3,:) = z_mss_aerosol(:) + mss_aerosol(3,:)
+!Aerosol Fluxes (January 07, 2023)
+
+! write(6,*)'Subdivided 50 mm from the subsurface layer &
+! &and combined into underlying neighbor'
+
+ IF(msno <= 3 .and. dzsno(3) > 0.18)THEN
+! subdivided a new layer
+ msno = 4
+ dzsno(3) = dzsno(3)/2.
+ swice(3) = swice(3)/2.
+ swliq(3) = swliq(3)/2.
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(3,:) = mss_aerosol(3,:)/2.
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(4) = dzsno(3)
+ swice(4) = swice(3)
+ swliq(4) = swliq(3)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(4,:) = mss_aerosol(3,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ tsno(4) = tsno(3)
+
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF(msno > 3)THEN
+ IF(dzsno(3) > 0.11)THEN
+ drr = dzsno(3) - 0.11
+ propor = drr/dzsno(3)
+ zwice = propor*swice(3)
+ zwliq = propor*swliq(3)
+!Aerosol Fluxes (January 07, 2023)
+ z_mss_aerosol(:) = propor*mss_aerosol(3,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ propor = 0.11/dzsno(3)
+ swice(3) = propor*swice(3)
+ swliq(3) = propor*swliq(3)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(3,:) = propor*mss_aerosol(3,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(3) = 0.11
+
+ CALL combo(dzsno(4),swliq(4),swice(4),tsno(4), &
+ drr, zwliq, zwice, tsno(3))
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(4,:) = z_mss_aerosol(:) + mss_aerosol(4,:)
+!Aerosol Fluxes (January 07, 2023)
+
+! write(6,*)'Subdivided 110 mm from the third Node &
+! &and combined into underlying neighbor'
+
+ IF(msno <= 4 .and. dzsno(4) > 0.41)THEN
+! subdivided a new layer
+ msno = 5
+ dzsno(4) = dzsno(4)/2.
+ swice(4) = swice(4)/2.
+ swliq(4) = swliq(4)/2.
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(4,:) = mss_aerosol(4,:)/2.
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(5) = dzsno(4)
+ swice(5) = swice(4)
+ swliq(5) = swliq(4)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(5,:) = mss_aerosol(4,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ tsno(5) = tsno(4)
+
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF(msno > 4)THEN
+ IF(dzsno(4) > 0.23)THEN
+ drr = dzsno(4) - 0.23
+ propor = drr/dzsno(4)
+ zwice = propor*swice(4)
+ zwliq = propor*swliq(4)
+!Aerosol Fluxes (January 07, 2023)
+ z_mss_aerosol(:) = propor*mss_aerosol(4,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ propor = 0.23/dzsno(4)
+ swice(4) = propor*swice(4)
+ swliq(4) = propor*swliq(4)
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(4,:) = propor*mss_aerosol(4,:)
+!Aerosol Fluxes (January 07, 2023)
+
+ dzsno(4) = 0.23
+
+ CALL combo(dzsno(5),swliq(5),swice(5),tsno(5), &
+ drr, zwliq, zwice, tsno(4))
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_aerosol(5,:) = z_mss_aerosol(:) + mss_aerosol(5,:)
+!Aerosol Fluxes (January 07, 2023)
+
+! write(6,*)'Subdivided 230 mm from the fourth Node &
+! 'and combined into underlying neighbor'
+ ENDIF
+ ENDIF
+
+ snl = - msno
+
+ DO k = snl+1, 0
+ dz_soisno(k) = dzsno(k - snl)
+ wice_soisno(k) = swice(k - snl)
+ wliq_soisno(k) = swliq(k - snl)
+
+!Aerosol Fluxes (January 07, 2023)
+ mss_bcphi(k) = mss_aerosol(k - snl, 1)
+ mss_bcpho(k) = mss_aerosol(k - snl, 2)
+ mss_ocphi(k) = mss_aerosol(k - snl, 3)
+ mss_ocpho(k) = mss_aerosol(k - snl, 4)
+ mss_dst1 (k) = mss_aerosol(k - snl, 5)
+ mss_dst2 (k) = mss_aerosol(k - snl, 6)
+ mss_dst3 (k) = mss_aerosol(k - snl, 7)
+ mss_dst4 (k) = mss_aerosol(k - snl, 8)
+!Aerosol Fluxes (January 07, 2023)
+
+ t_soisno(k) = tsno (k - snl)
+
+ ENDDO
+
+ zi_soisno(0) = 0.
+ DO k = 0, snl+1, -1
+ z_soisno(k) = zi_soisno(k) - 0.5*dz_soisno(k)
+ zi_soisno(k-1) = zi_soisno(k) - dz_soisno(k)
+ ENDDO
+
+ END SUBROUTINE SnowLayersDivide_snicar
+
+END MODULE MOD_SnowLayersCombineDivide
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowSnicar.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowSnicar.F90
new file mode 100644
index 0000000000..74df71130c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowSnicar.F90
@@ -0,0 +1,3000 @@
+#include
+
+MODULE MOD_SnowSnicar
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate albedo of snow containing impurities and the evolution of
+! snow effective radius
+!
+! Original:
+! 1) The Community Land Model version 5.0 (CLM5.0)
+! 2) Energy Exascale Earth System Model version 2.0 (E3SM v2.0) Land
+! Model (ELM v2.0)
+!
+! !REFERENCES:
+! 1) Flanner et al, 2021, SNICAR-ADv3: a community tool for modeling
+! spectral snow albedo. Geosci. Model Dev., 14, 7673-7704,
+! https://doi.org/10.5194/gmd-14-7673-2021
+! 2) Hao et al., 2023, Improving snow albedo modeling in the E3SM land
+! model (version 2.0) and assessing its impacts on snow and surface
+! fluxes over the Tibetan Plateau. Geosci. Model Dev., 16, 75-94,
+! https://doi.org/10.5194/gmd-16-75-2023
+!
+! !REVISIONS:
+! Yongjiu Dai, and Hua Yuan, December, 2022 : ASSEMBLING and FITTING
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: maxsnl
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+! SAVE
+ real(R8),parameter :: SHR_CONST_PI = 3.14159265358979323846_R8
+ real(R8),parameter :: SHR_CONST_RHOICE = 0.917e3_R8 ! density of ice (kg/m^3)
+
+ integer, parameter :: iulog = 6 ! "stdout" log file unit number, default is 6
+ integer, parameter :: numrad = 2 ! number of solar radiation bands: vis, nir
+
+!--------------------------------------------------------------------
+! DAI, Dec. 29, 2022
+! Temporary setting
+
+ logical, parameter :: use_extrasnowlayers = .false.
+ character(len=256), parameter :: snow_shape = 'sphere' ! (=1), 'spheroid'(=2), 'hexagonal_plate'(=3), 'koch_snowflake'(=4)
+ logical, parameter :: use_dust_snow_internal_mixing = .false.
+ character(len=256), parameter :: snicar_atm_type = 'default' ! Atmospheric profile used to obtain surface-incident spectral flux distribution
+ ! and subsequent broadband albedo
+ ! = 'mid-latitude_winter' ! => 1
+ ! = 'mid-latitude_summer' ! => 2
+ ! = 'sub-Arctic_winter' ! => 3
+ ! = 'sub-Arctic_summer' ! => 4
+ ! = 'summit_Greenland' ! => 5 (sub-Arctic summer, surface pressure of 796hPa)
+ ! = 'high_mountain' ! => 6 (summer, surface pressure of 556 hPa)
+!DAI, Dec. 29, 2022
+!-----------------------------------------------------------------------
+
+ ! !PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: SNICAR_RT ! Snow albedo and vertically-resolved solar absorption
+ PUBLIC :: SNICAR_AD_RT ! Snow albedo and vertically-resolved solar absorption by adding-doubling solution
+ ! To USE this subroutine, set use_snicar_ad = true
+ PUBLIC :: SnowAge_grain ! Snow effective grain size evolution
+ PUBLIC :: SnowAge_init ! Initial read in of snow-aging file
+ PUBLIC :: SnowOptics_init ! Initial read in of snow-optics file
+ !
+ ! !PUBLIC DATA MEMBERS:
+ integer, PUBLIC, parameter :: sno_nbr_aer = 8 ! number of aerosol species in snowpack
+ ! (indices described above) [nbr]
+ logical, PUBLIC, parameter :: DO_SNO_OC = .false. ! parameter to include organic carbon (OC)
+ ! in snowpack radiative calculations
+ logical, PUBLIC, parameter :: DO_SNO_AER = .true. ! parameter to include aerosols in snowpack radiative calculations
+ ! !PRIVATE DATA MEMBERS:
+ integer, parameter :: numrad_snw = 5 ! number of spectral bands used in snow model [nbr]
+ integer, parameter :: nir_bnd_bgn = 2 ! first band index in near-IR spectrum [idx]
+ integer, parameter :: nir_bnd_end = 5 ! ending near-IR band index [idx]
+ integer, parameter :: idx_Mie_snw_mx = 1471 ! number of effective radius indices used in Mie lookup table [idx]
+ integer, parameter :: idx_T_max = 11 ! maximum temperature index used in aging lookup table [idx]
+ integer, parameter :: idx_T_min = 1 ! minimum temperature index used in aging lookup table [idx]
+ integer, parameter :: idx_Tgrd_max = 31 ! maximum temperature gradient index used in aging lookup table [idx]
+ integer, parameter :: idx_Tgrd_min = 1 ! minimum temperature gradient index used in aging lookup table [idx]
+ integer, parameter :: idx_rhos_max = 8 ! maximum snow density index used in aging lookup table [idx]
+ integer, parameter :: idx_rhos_min = 1 ! minimum snow density index used in aging lookup table [idx]
+
+#ifdef MODAL_AER
+ ! NOTE: right now the macro 'MODAL_AER' is not defined anywhere, i.e.,
+ ! the below (modal aerosol scheme) is not available and can not be
+ ! active either. It depends on the specific input aerosol deposition
+ ! data which is suitable for modal scheme. [06/15/2023, Hua Yuan]
+ !mgf++
+ integer, parameter :: idx_bc_nclrds_min = 1 ! minimum index for BC particle size in optics lookup table
+ integer, parameter :: idx_bc_nclrds_max = 10 ! maximum index for BC particle size in optics lookup table
+ integer, parameter :: idx_bcint_icerds_min = 1 ! minimum index for snow grain size in optics lookup table for within-ice BC
+ integer, parameter :: idx_bcint_icerds_max = 8 ! maximum index for snow grain size in optics lookup table for within-ice BC
+ !mgf--
+#endif
+
+ integer, parameter :: snw_rds_max_tbl = 1500 ! maximum effective radius defined in Mie lookup table [microns]
+ integer, parameter :: snw_rds_min_tbl = 30 ! minimum effective radius defined in Mie lookup table [microns]
+ real(r8), parameter :: snw_rds_max = 1500._r8 ! maximum allowed snow effective radius [microns]
+ real(r8), parameter :: snw_rds_min = 54.526_r8 ! minimum allowed snow effective radius (also "fresh snow" value) [microns
+ real(r8), parameter :: snw_rds_refrz = 1000._r8 ! effective radius of re-frozen snow [microns]
+ real(r8), parameter :: min_snw = 1.0E-30_r8 ! minimum snow mass required for SNICAR RT calculation [kg m-2]
+ !real(r8), parameter :: C1_liq_Brun89 = 1.28E-17_r8 ! constant for liquid water grain growth [m3 s-1],
+ ! from Brun89
+ real(r8), parameter :: C1_liq_Brun89 = 0._r8 ! constant for liquid water grain growth [m3 s-1],
+ ! from Brun89: zeroed to accomodate dry snow aging
+ real(r8), parameter :: C2_liq_Brun89 = 4.22E-13_r8 ! constant for liquid water grain growth [m3 s-1],
+ ! from Brun89: corrected for LWC in units of percent
+
+ real(r8), parameter :: tim_cns_bc_rmv = 2.2E-8_r8 ! time constant for removal of BC in snow on sea-ice
+ ! [s-1] (50% mass removal/year)
+ real(r8), parameter :: tim_cns_oc_rmv = 2.2E-8_r8 ! time constant for removal of OC in snow on sea-ice
+ ! [s-1] (50% mass removal/year)
+ real(r8), parameter :: tim_cns_dst_rmv = 2.2E-8_r8 ! time constant for removal of dust in snow on sea-ice
+ ! [s-1] (50% mass removal/year)
+ !$acc declare copyin(C1_liq_Brun89, C2_liq_Brun89, &
+ !$acc tim_cns_bc_rmv, tim_cns_oc_rmv, tim_cns_dst_rmv)
+
+ ! scaling of the snow aging rate (tuning option):
+ logical :: flg_snoage_scl = .false. ! flag for scaling the snow aging rate by some arbitrary factor
+ real(r8), parameter :: xdrdt = 1.0_r8 ! arbitrary factor applied to snow aging rate
+ ! snow and aerosol Mie parameters:
+ ! (arrays declared here, but are set in iniTimeConst)
+ ! (idx_Mie_snw_mx is number of snow radii with defined parameters (i.e. from 30um to 1500um))
+
+ ! direct-beam weighted ice optical properties
+ real(r8), allocatable :: ss_alb_snw_drc (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: asm_prm_snw_drc (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_snw_drc(:,:) ! (idx_Mie_snw_mx,numrad_snw);
+
+ ! diffuse radiation weighted ice optical properties
+ real(r8), allocatable :: ss_alb_snw_dfs (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: asm_prm_snw_dfs (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_snw_dfs(:,:) ! (idx_Mie_snw_mx,numrad_snw);
+
+ ! direct & diffuse flux
+ real(r8), allocatable :: flx_wgt_dir (:,:,:) ! (6, 90, numrad_snw) ! direct flux, six atmospheric types, 0-89 SZA
+ real(r8), allocatable :: flx_wgt_dif (:,:) ! (6, numrad_snw) ! diffuse flux, six atmospheric types
+
+ ! snow grain shape
+ integer, parameter :: snow_shape_sphere = 1
+ integer, parameter :: snow_shape_spheroid = 2
+ integer, parameter :: snow_shape_hexagonal_plate = 3
+ integer, parameter :: snow_shape_koch_snowflake = 4
+
+ ! atmospheric condition for SNICAR-AD
+ integer, parameter :: atm_type_default = 0
+ integer, parameter :: atm_type_mid_latitude_winter = 1
+ integer, parameter :: atm_type_mid_latitude_summer = 2
+ integer, parameter :: atm_type_sub_Arctic_winter = 3
+ integer, parameter :: atm_type_sub_Arctic_summer = 4
+ integer, parameter :: atm_type_summit_Greenland = 5
+ integer, parameter :: atm_type_high_mountain = 6
+
+#ifdef MODAL_AER
+ !mgf++
+ ! Size-dependent BC optical properties. Currently a fixed BC size is
+ ! assumed, but this framework enables optical properties to be
+ ! assigned based on the BC effective radius, should this be
+ ! implemented in the future.
+ !
+ ! within-ice BC (i.e., BC that was deposited within hydrometeors)
+ real(r8), allocatable :: ss_alb_bc1 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: asm_prm_bc1 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: ext_cff_mss_bc1(:,:) ! (numrad_snw,idx_bc_nclrds_max);
+
+ ! external BC
+ real(r8), allocatable :: ss_alb_bc2 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: asm_prm_bc2 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: ext_cff_mss_bc2(:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ !mgf--
+#else
+ ! hydrophiliic BC
+ real(r8), allocatable :: ss_alb_bc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_bc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_bc1(:) ! (numrad_snw);
+
+ ! hydrophobic BC
+ real(r8), allocatable :: ss_alb_bc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_bc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_bc2(:) ! (numrad_snw);
+#endif
+
+ ! hydrophobic OC
+ real(r8), allocatable :: ss_alb_oc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_oc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_oc1(:) ! (numrad_snw);
+
+ ! hydrophilic OC
+ real(r8), allocatable :: ss_alb_oc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_oc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_oc2(:) ! (numrad_snw);
+
+ ! dust species 1:
+ real(r8), allocatable :: ss_alb_dst1 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst1 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst1(:) ! (numrad_snw);
+
+ ! dust species 2:
+ real(r8), allocatable :: ss_alb_dst2 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst2 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst2(:) ! (numrad_snw);
+
+ ! dust species 3:
+ real(r8), allocatable :: ss_alb_dst3 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst3 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst3(:) ! (numrad_snw);
+
+ ! dust species 4:
+ real(r8), allocatable :: ss_alb_dst4 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst4 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst4(:) ! (numrad_snw);
+
+#ifdef MODAL_AER
+ ! Absorption enhancement factors for within-ice BC
+ real(r8), allocatable :: bcenh (:,:,:) ! (numrad_snw,idx_bc_nclrds_max,idx_bcint_icerds_max);
+#endif
+
+ ! best-fit parameters for snow aging defined over:
+ ! 11 temperatures from 225 to 273 K
+ ! 31 temperature gradients from 0 to 300 K/m
+ ! 8 snow densities from 0 to 350 kg/m3
+ ! (arrays declared here, but are set in iniTimeConst)
+ !
+ real(r8), allocatable :: snowage_tau (:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) ! snow aging parameter retrieved from lookup table [hour]
+ real(r8), allocatable :: snowage_kappa (:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) ! snow aging parameter retrieved from lookup table [unitless]
+ real(r8), allocatable :: snowage_drdt0 (:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) ! snow aging parameter retrieved from lookup table [um hr-1]
+
+ !
+ ! !REVISION HISTORY:
+ ! Created by Mark Flanner
+ !-----------------------------------------------------------------------
+
+CONTAINS
+
+ SUBROUTINE SNICAR_RT (flg_snw_ice, flg_slr_in, &
+ coszen, snl, h2osno, frac_sno, &
+ h2osno_liq, h2osno_ice, snw_rds, &
+ mss_cnc_aer_in, albsfc, albout, flx_abs)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Determine reflectance of, and vertically-resolved solar absorption in,
+! snow with impurities.
+!
+! Original references on physical models of snow reflectance include:
+! Wiscombe and Warren [1980] and Warren and Wiscombe [1980],
+! Journal of Atmospheric Sciences, 37,
+!
+! The multi-layer solution for multiple-scattering used here is from:
+! Toon et al. [1989], Rapid calculation of radiative heating rates
+! and photodissociation rates in inhomogeneous multiple scattering atmospheres,
+! J. Geophys. Res., 94, D13, 16287-16301
+!
+! The implementation of the SNICAR model in CLM/CSIM is described in:
+! Flanner, M., C. Zender, J. Randerson, and P. Rasch [2007],
+! Present-day climate forcing and response from black carbon in snow,
+! J. Geophys. Res., 112, D11202, doi: 10.1029/2006JD008003
+!
+! !USES:
+!
+!-----------------------------------------------------------------------
+! !ARGUMENTS:
+
+ IMPLICIT NONE
+
+ integer , intent(in) :: flg_snw_ice ! flag: =1 when called from CLM, =2 when called from CSIM
+ integer , intent(in) :: flg_slr_in ! flag: =1 for direct-beam incident flux,=2 for diffuse incident flux
+ real(r8) , intent(in) :: coszen ! cosine of solar zenith angle for next time step (col) [unitless]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8) , intent(in) :: h2osno ! snow liquid water equivalent (col) [kg/m2]
+ real(r8) , intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+
+ real(r8) , intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg/m2]
+ real(r8) , intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice content (col,lyr) [kg/m2]
+ integer , intent(in) :: snw_rds ( maxsnl+1:0 ) ! snow effective radius (col,lyr) [microns, m^-6]
+ real(r8) , intent(in) :: mss_cnc_aer_in ( maxsnl+1:0 , 1:sno_nbr_aer ) ! mass concentration of all aerosol species (col,lyr,aer) [kg/kg]
+ real(r8) , intent(in) :: albsfc ( 1:numrad ) ! albedo of surface underlying snow (col,bnd) [frc]
+ real(r8) , intent(out) :: albout ( 1:numrad ) ! snow albedo, averaged into 2 bands (=0 IF no sun or no snow) (col,bnd) [frc]
+ real(r8) , intent(out) :: flx_abs ( maxsnl+1:1 , 1:numrad ) ! absorbed flux in each layer per unit flux incident (col, lyr, bnd)
+ !
+ ! !LOCAL VARIABLES:
+ !
+ ! variables for snow radiative transfer calculations
+
+ ! Local variables representing single-column values of arrays:
+ integer :: snl_lcl ! negative number of snow layers [nbr]
+ integer :: snw_rds_lcl(maxsnl+1:0) ! snow effective radius [m^-6]
+ real(r8):: flx_slrd_lcl(1:numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1)
+ real(r8):: flx_slri_lcl(1:numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1)
+ real(r8):: mss_cnc_aer_lcl(maxsnl+1:0,1:sno_nbr_aer) ! aerosol mass concentration (lyr,aer_nbr) [kg/kg]
+ real(r8):: h2osno_lcl ! total column snow mass [kg/m2]
+ real(r8):: h2osno_liq_lcl(maxsnl+1:0) ! liquid water mass [kg/m2]
+ real(r8):: h2osno_ice_lcl(maxsnl+1:0) ! ice mass [kg/m2]
+ real(r8):: albsfc_lcl(1:numrad_snw) ! albedo of underlying surface [frc]
+ real(r8):: ss_alb_snw_lcl(maxsnl+1:0) ! single-scatter albedo of ice grains (lyr) [frc]
+ real(r8):: asm_prm_snw_lcl(maxsnl+1:0) ! asymmetry parameter of ice grains (lyr) [frc]
+ real(r8):: ext_cff_mss_snw_lcl(maxsnl+1:0) ! mass extinction coefficient of ice grains (lyr) [m2/kg]
+ real(r8):: ss_alb_aer_lcl(sno_nbr_aer) ! single-scatter albedo of aerosol species (aer_nbr) [frc]
+ real(r8):: asm_prm_aer_lcl(sno_nbr_aer) ! asymmetry parameter of aerosol species (aer_nbr) [frc]
+ real(r8):: ext_cff_mss_aer_lcl(sno_nbr_aer) ! mass extinction coefficient of aerosol species (aer_nbr) [m2/kg]
+
+#ifdef MODAL_AER
+ !mgf++
+ real(r8) :: rds_bcint_lcl(maxsnl+1:0) ! effective radius of within-ice BC [nm]
+ real(r8) :: rds_bcext_lcl(maxsnl+1:0) ! effective radius of external BC [nm]
+ !mgf--
+#endif
+
+
+ ! Other local variables
+ integer :: APRX_TYP ! two-stream approximation type
+ ! (1=Eddington, 2=Quadrature, 3=Hemispheric Mean) [nbr]
+ integer :: DELTA ! flag to USE Delta approximation (Joseph, 1976)
+ ! (1= USE, 0= don't USE)
+ real(r8):: flx_wgt(1:numrad_snw) ! weights applied to spectral bands,
+ ! specific to direct and diffuse cases (bnd) [frc]
+
+ integer :: flg_nosnl ! flag: =1 IF there is snow, but zero snow layers,
+ ! =0 IF at least 1 snow layer [flg]
+ integer :: trip ! flag: =1 to redo RT calculation IF result is unrealistic
+ integer :: flg_dover ! defines conditions for RT redo (explained below)
+
+ real(r8):: albedo ! temporary snow albedo [frc]
+ real(r8):: flx_sum ! temporary summation variable for NIR weighting
+ real(r8):: albout_lcl(numrad_snw) ! snow albedo by band [frc]
+ real(r8):: flx_abs_lcl(maxsnl+1:1,numrad_snw) ! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc]
+
+ real(r8):: L_snw(maxsnl+1:0) ! h2o mass (liquid+solid) in snow layer (lyr) [kg/m2]
+ real(r8):: tau_snw(maxsnl+1:0) ! snow optical depth (lyr) [unitless]
+ real(r8):: L_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol mass in snow layer (lyr,nbr_aer) [kg/m2]
+ real(r8):: tau_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol optical depth (lyr,nbr_aer) [unitless]
+ real(r8):: tau_sum ! cumulative (snow+aerosol) optical depth [unitless]
+ real(r8):: tau_elm(maxsnl+1:0) ! column optical depth from layer bottom to snowpack top (lyr) [unitless]
+ real(r8):: omega_sum ! temporary summation of single-scatter albedo of all aerosols [frc]
+ real(r8):: g_sum ! temporary summation of asymmetry parameter of all aerosols [frc]
+
+ real(r8):: tau(maxsnl+1:0) ! weighted optical depth of snow+aerosol layer (lyr) [unitless]
+ real(r8):: omega(maxsnl+1:0) ! weighted single-scatter albedo of snow+aerosol layer (lyr) [frc]
+ real(r8):: g(maxsnl+1:0) ! weighted asymmetry parameter of snow+aerosol layer (lyr) [frc]
+ real(r8):: tau_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) optical depth of snow+aerosol layer
+ ! (lyr) [unitless]
+ real(r8):: omega_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) SSA of snow+aerosol layer (lyr) [frc]
+ real(r8):: g_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) asymmetry paramater of snow+aerosol layer
+ ! (lyr) [frc]
+
+ integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= numrad_snw) [idx]
+ integer :: rds_idx ! snow effective radius index for retrieving
+ ! Mie parameters from lookup table [idx]
+ integer :: snl_btm ! index of bottom snow layer (0) [idx]
+ integer :: snl_top ! index of top snow layer (-4 to 0) [idx]
+ integer :: fc ! column filter index
+ integer :: i ! layer index [idx]
+ integer :: j ! aerosol number index [idx]
+ integer :: n ! tridiagonal matrix index [idx]
+ integer :: m ! secondary layer index [idx]
+ integer :: nint_snw_rds_min ! nearest integer value of snw_rds_min
+
+ real(r8):: F_direct(maxsnl+1:0) ! direct-beam radiation at bottom of layer interface (lyr) [W/m^2]
+ real(r8):: F_net(maxsnl+1:0) ! net radiative flux at bottom of layer interface (lyr) [W/m^2]
+ real(r8):: F_abs(maxsnl+1:0) ! net absorbed radiative energy (lyr) [W/m^2]
+ real(r8):: F_abs_sum ! total absorbed energy in column [W/m^2]
+ real(r8):: F_sfc_pls ! upward radiative flux at snowpack top [W/m^2]
+ real(r8):: F_btm_net ! net flux at bottom of snowpack [W/m^2]
+ real(r8):: F_sfc_net ! net flux at top of snowpack [W/m^2]
+ real(r8):: energy_sum ! sum of all energy terms; should be 0.0 [W/m^2]
+ real(r8):: F_direct_btm ! direct-beam radiation at bottom of snowpack [W/m^2]
+ real(r8):: mu_not ! cosine of solar zenith angle (used locally) [frc]
+
+ integer :: err_idx ! counter for number of times through error loop [nbr]
+ real(r8):: pi ! 3.1415...
+
+ ! intermediate variables for radiative transfer approximation:
+ real(r8):: gamma1(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: gamma2(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: gamma3(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: gamma4(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: lambda(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: GAMMA(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: mu_one ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: e1(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: e2(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: e3(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: e4(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: C_pls_btm(maxsnl+1:0) ! intermediate variable: upward flux at bottom interface (lyr) [W/m2]
+ real(r8):: C_mns_btm(maxsnl+1:0) ! intermediate variable: downward flux at bottom interface (lyr) [W/m2]
+ real(r8):: C_pls_top(maxsnl+1:0) ! intermediate variable: upward flux at top interface (lyr) [W/m2]
+ real(r8):: C_mns_top(maxsnl+1:0) ! intermediate variable: downward flux at top interface (lyr) [W/m2]
+ real(r8):: A(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: B(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: D(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: E(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: AS(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: DS(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: X(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: Y(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ !-----------------------------------------------------------------------
+#ifdef MODAL_AER
+ !mgf++
+ integer :: idx_bcint_icerds ! index of ice effective radius for optical properties lookup table
+ integer :: idx_bcint_nclrds ! index of within-ice BC effective radius for optical properties lookup table
+ integer :: idx_bcext_nclrds ! index of external BC effective radius for optical properties lookup table
+ real(r8):: enh_fct ! extinction/absorption enhancement factor for within-ice BC
+ real(r8):: tmp1 ! temporary variable
+ !mgf--
+#endif
+
+ ! Enforce expected array sizes
+
+ ! associate(&
+ ! snl => col_pp%snl , & ! Input: [integer (:)] negative number of snow layers (col) [nbr]
+ ! h2osno => col_ws%h2osno , & ! Input: [real(r8) (:)] snow liquid water equivalent (col) [kg/m2]
+ ! frac_sno => col_ws%frac_sno_eff & ! Input: [real(r8) (:)] fraction of ground covered by snow (0 to 1)
+ ! )
+
+ ! Define constants
+ pi = SHR_CONST_PI
+ nint_snw_rds_min = nint(snw_rds_min)
+
+ ! always USE Delta approximation for snow
+ DELTA = 1
+
+ ! (when called from CSIM, there is only one column)
+
+ ! Zero absorbed radiative fluxes:
+ DO i=maxsnl+1,1,1
+ flx_abs_lcl(:,:) = 0._r8
+ flx_abs(i,:) = 0._r8
+ ENDDO
+
+ ! set snow/ice mass to be used for RT:
+ IF (flg_snw_ice == 1) THEN
+ h2osno_lcl = h2osno
+ ELSE
+ h2osno_lcl = h2osno_ice(0)
+ ENDIF
+
+ ! Qualifier for computing snow RT:
+ ! 1) sunlight from atmosphere model
+ ! 2) minimum amount of snow on ground.
+ ! Otherwise, set snow albedo to zero
+ IF ((coszen > 0._r8) .and. (h2osno_lcl > min_snw)) THEN
+
+ ! Set variables specific to CLM
+ IF (flg_snw_ice == 1) THEN
+ ! If there is snow, but zero snow layers, we must create a layer locally.
+ ! This layer is presumed to have the fresh snow effective radius.
+ IF (snl > -1) THEN
+ flg_nosnl = 1
+ snl_lcl = -1
+ h2osno_ice_lcl(0) = h2osno_lcl
+ h2osno_liq_lcl(0) = 0._r8
+ snw_rds_lcl(0) = nint_snw_rds_min
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = snl
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ ENDIF
+
+ snl_btm = 0
+ snl_top = snl_lcl+1
+
+ ! Set variables specific to CSIM
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = -1
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ snl_btm = 0
+ snl_top = 0
+ ENDIF
+
+#ifdef MODAL_AER
+ !mgf++
+ !
+ ! Assume fixed BC effective radii of 100nm. This is close to
+ ! the effective radius of 95nm (number median radius of
+ ! 40nm) assumed for freshly-emitted BC in MAM. Future
+ ! implementations may prognose the BC effective radius in
+ ! snow.
+ rds_bcint_lcl(:) = 100._r8
+ rds_bcext_lcl(:) = 100._r8
+ !mgf--
+#endif
+
+ ! Set local aerosol array
+ DO j=1,sno_nbr_aer
+ mss_cnc_aer_lcl(:,j) = mss_cnc_aer_in(:,j)
+ ENDDO
+
+
+ ! Set spectral underlying surface albedos to their corresponding VIS or NIR albedos
+ albsfc_lcl(1) = albsfc(1)
+ albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(2)
+
+
+ ! Error check for snow grain size:
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ DO i=snl_top,snl_btm,1
+ IF ((snw_rds_lcl(i) < snw_rds_min_tbl) .or. (snw_rds_lcl(i) > snw_rds_max_tbl)) THEN
+ write (iulog,*) "SNICAR ERROR: snow grain radius of out of bounds."
+ write (iulog,*) "flg_snw_ice= ", flg_snw_ice
+ write (iulog,*) " level: ", i, " snl(c)= ", snl_lcl
+ write (iulog,*) "h2osno(c)= ", h2osno_lcl
+ CALL abort
+ ENDIF
+ ENDDO
+ ENDIF
+#endif
+
+ ! Incident flux weighting parameters
+ ! - sum of all VIS bands must equal 1
+ ! - sum of all NIR bands must equal 1
+ !
+ ! Spectral bands (5-band CASE)
+ ! Band 1: 0.3-0.7um (VIS)
+ ! Band 2: 0.7-1.0um (NIR)
+ ! Band 3: 1.0-1.2um (NIR)
+ ! Band 4: 1.2-1.5um (NIR)
+ ! Band 5: 1.5-5.0um (NIR)
+ !
+ ! The following weights are appropriate for surface-incident flux in a mid-latitude winter atmosphere
+ !
+ ! 3-band weights
+ IF (numrad_snw==3) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.66628670195247_r8
+ flx_wgt(3) = 0.33371329804753_r8
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.77887652162877_r8
+ flx_wgt(3) = 0.22112347837123_r8
+ ENDIF
+
+ ! 5-band weights
+ ELSEIF(numrad_snw==5) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.49352158521175_r8
+ flx_wgt(3) = 0.18099494230665_r8
+ flx_wgt(4) = 0.12094898498813_r8
+ flx_wgt(5) = 0.20453448749347_r8
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.58581507618433_r8
+ flx_wgt(3) = 0.20156903770812_r8
+ flx_wgt(4) = 0.10917889346386_r8
+ flx_wgt(5) = 0.10343699264369_r8
+ ENDIF
+ ENDIF
+
+ ! Loop over snow spectral bands
+ DO bnd_idx = 1,numrad_snw
+
+ mu_not = coszen ! must set here, because of error handling
+ flg_dover = 1 ! default is to redo
+ err_idx = 0 ! number of times through loop
+
+ DO WHILE (flg_dover > 0)
+
+ ! DEFAULT APPROXIMATIONS:
+ ! VIS: Delta-Eddington
+ ! NIR (all): Delta-Hemispheric Mean
+ ! WARNING: DO NOT USE DELTA-EDDINGTON FOR NIR DIFFUSE - this sometimes results in negative albedo
+ !
+ ! ERROR CONDITIONS:
+ ! Conditions which cause "trip", resulting in redo of RT approximation:
+ ! 1. negative absorbed flux
+ ! 2. total absorbed flux greater than incident flux
+ ! 3. negative albedo
+ ! NOTE: These errors have only been encountered in spectral bands 4 and 5
+ !
+ ! ERROR HANDLING
+ ! 1st error (flg_dover=2): switch approximation (Edd->HM or HM->Edd)
+ ! 2nd error (flg_dover=3): change zenith angle by 0.02 (this happens about 1 in 10^6 cases)
+ ! 3rd error (flg_dover=4): switch approximation with new zenith
+ ! Subsequent errors: repeatedly change zenith and approximations...
+
+ IF (bnd_idx == 1) THEN
+ IF (flg_dover == 2) THEN
+ APRX_TYP = 3
+ ELSEIF (flg_dover == 3) THEN
+ APRX_TYP = 1
+ IF (coszen > 0.5_r8) THEN
+ mu_not = mu_not - 0.02_r8
+ ELSE
+ mu_not = mu_not + 0.02_r8
+ ENDIF
+ ELSEIF (flg_dover == 4) THEN
+ APRX_TYP = 3
+ ELSE
+ APRX_TYP = 1
+ ENDIF
+
+ ELSE
+ IF (flg_dover == 2) THEN
+ APRX_TYP = 1
+ ELSEIF (flg_dover == 3) THEN
+ APRX_TYP = 3
+ IF (coszen > 0.5_r8) THEN
+ mu_not = mu_not - 0.02_r8
+ ELSE
+ mu_not = mu_not + 0.02_r8
+ ENDIF
+ ELSEIF (flg_dover == 4) THEN
+ APRX_TYP = 1
+ ELSE
+ APRX_TYP = 3
+ ENDIF
+
+ ENDIF
+
+ ! Set direct or diffuse incident irradiance to 1
+ ! (This has to be within the bnd loop because mu_not is adjusted in rare cases)
+ IF (flg_slr_in == 1) THEN
+ flx_slrd_lcl(bnd_idx) = 1._r8/(mu_not*pi) ! this corresponds to incident irradiance of 1.0
+ flx_slri_lcl(bnd_idx) = 0._r8
+ ELSE
+ flx_slrd_lcl(bnd_idx) = 0._r8
+ flx_slri_lcl(bnd_idx) = 1._r8
+ ENDIF
+
+ ! Pre-emptive error handling: aerosols can reap havoc on these absorptive bands.
+ ! Since extremely high soot concentrations have a negligible effect on these bands, zero them.
+ IF ( (numrad_snw == 5).and.((bnd_idx == 5).or.(bnd_idx == 4)) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ IF ( (numrad_snw == 3).and.(bnd_idx == 3) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ ! Define local Mie parameters based on snow grain size and aerosol species,
+ ! retrieved from a lookup table.
+ IF (flg_slr_in == 1) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (direct radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_drc(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_drc(rds_idx,bnd_idx)
+ ENDDO
+ ELSEIF (flg_slr_in == 2) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (diffuse radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_dfs(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_dfs(rds_idx,bnd_idx)
+ ENDDO
+ ENDIF
+
+!H. Wang
+ ! aerosol species 1 optical properties
+ ! ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ ! asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ! ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ! ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ ! asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ! ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+!H. Wang
+ ! aerosol species 3 optical properties
+ ss_alb_aer_lcl(3) = ss_alb_oc1(bnd_idx)
+ asm_prm_aer_lcl(3) = asm_prm_oc1(bnd_idx)
+ ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc1(bnd_idx)
+
+ ! aerosol species 4 optical properties
+ ss_alb_aer_lcl(4) = ss_alb_oc2(bnd_idx)
+ asm_prm_aer_lcl(4) = asm_prm_oc2(bnd_idx)
+ ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc2(bnd_idx)
+
+ ! aerosol species 5 optical properties
+ ss_alb_aer_lcl(5) = ss_alb_dst1(bnd_idx)
+ asm_prm_aer_lcl(5) = asm_prm_dst1(bnd_idx)
+ ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(bnd_idx)
+
+ ! aerosol species 6 optical properties
+ ss_alb_aer_lcl(6) = ss_alb_dst2(bnd_idx)
+ asm_prm_aer_lcl(6) = asm_prm_dst2(bnd_idx)
+ ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(bnd_idx)
+
+ ! aerosol species 7 optical properties
+ ss_alb_aer_lcl(7) = ss_alb_dst3(bnd_idx)
+ asm_prm_aer_lcl(7) = asm_prm_dst3(bnd_idx)
+ ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(bnd_idx)
+
+ ! aerosol species 8 optical properties
+ ss_alb_aer_lcl(8) = ss_alb_dst4(bnd_idx)
+ asm_prm_aer_lcl(8) = asm_prm_dst4(bnd_idx)
+ ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(bnd_idx)
+
+
+ ! 1. snow and aerosol layer column mass (L_snw, L_aer [kg/m^2])
+ ! 2. optical Depths (tau_snw, tau_aer)
+ ! 3. weighted Mie properties (tau, omega, g)
+
+ ! Weighted Mie parameters of each layer
+ DO i=snl_top,snl_btm,1
+#ifdef MODAL_AER
+ !mgf++ within-ice and external BC optical properties
+ !
+ ! Lookup table indices for BC optical properties,
+ ! dependent on snow grain size and BC particle
+ ! size.
+
+ ! valid for 25 < snw_rds < 1625 um:
+ IF (snw_rds_lcl(i) < 125) THEN
+ tmp1 = snw_rds_lcl(i)/50
+ idx_bcint_icerds = nint(tmp1)
+ ELSEIF (snw_rds_lcl(i) < 175) THEN
+ idx_bcint_icerds = 2
+ ELSE
+ tmp1 = (snw_rds_lcl(i)/250)+2
+ idx_bcint_icerds = nint(tmp1)
+ ENDIF
+
+ ! valid for 25 < bc_rds < 525 nm
+ idx_bcint_nclrds = nint(rds_bcint_lcl(i)/50)
+ idx_bcext_nclrds = nint(rds_bcext_lcl(i)/50)
+
+ ! check bounds:
+ IF (idx_bcint_icerds < idx_bcint_icerds_min) idx_bcint_icerds = idx_bcint_icerds_min
+ IF (idx_bcint_icerds > idx_bcint_icerds_max) idx_bcint_icerds = idx_bcint_icerds_max
+ IF (idx_bcint_nclrds < idx_bc_nclrds_min) idx_bcint_nclrds = idx_bc_nclrds_min
+ IF (idx_bcint_nclrds > idx_bc_nclrds_max) idx_bcint_nclrds = idx_bc_nclrds_max
+ IF (idx_bcext_nclrds < idx_bc_nclrds_min) idx_bcext_nclrds = idx_bc_nclrds_min
+ IF (idx_bcext_nclrds > idx_bc_nclrds_max) idx_bcext_nclrds = idx_bc_nclrds_max
+
+ ! retrieve absorption enhancement factor for within-ice BC
+ enh_fct = bcenh(bnd_idx,idx_bcint_nclrds,idx_bcint_icerds)
+
+ ! get BC optical properties (moved from above)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx,idx_bcint_nclrds)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx,idx_bcint_nclrds)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx,idx_bcint_nclrds)*enh_fct
+
+ ! aerosol species 2 optical properties (external BC)
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx,idx_bcext_nclrds)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx,idx_bcext_nclrds)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx,idx_bcext_nclrds)
+
+#else
+ ! bulk aerosol treatment (BC optical properties independent
+ ! of BC and ice grain size)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+#endif
+ !mgf--
+
+ L_snw(i) = h2osno_ice_lcl(i)+h2osno_liq_lcl(i)
+ tau_snw(i) = L_snw(i)*ext_cff_mss_snw_lcl(i)
+
+ DO j=1,sno_nbr_aer
+ L_aer(i,j) = L_snw(i)*mss_cnc_aer_lcl(i,j)
+ tau_aer(i,j) = L_aer(i,j)*ext_cff_mss_aer_lcl(j)
+ ENDDO
+
+ tau_sum = 0._r8
+ omega_sum = 0._r8
+ g_sum = 0._r8
+
+ DO j=1,sno_nbr_aer
+ tau_sum = tau_sum + tau_aer(i,j)
+ omega_sum = omega_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j))
+ g_sum = g_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j)*asm_prm_aer_lcl(j))
+ ENDDO
+
+ tau(i) = tau_sum + tau_snw(i)
+ omega(i) = (1/tau(i))*(omega_sum+(ss_alb_snw_lcl(i)*tau_snw(i)))
+ g(i) = (1/(tau(i)*omega(i)))*(g_sum+ (asm_prm_snw_lcl(i)*ss_alb_snw_lcl(i)*tau_snw(i)))
+ ENDDO
+
+ ! DELTA transformations, IF requested
+ IF (DELTA == 1) THEN
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)/(1+g(i))
+ omega_star(i) = ((1-(g(i)**2))*omega(i)) / (1-(omega(i)*(g(i)**2)))
+ tau_star(i) = (1-(omega(i)*(g(i)**2)))*tau(i)
+ ENDDO
+ ELSE
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)
+ omega_star(i) = omega(i)
+ tau_star(i) = tau(i)
+ ENDDO
+ ENDIF
+
+ ! Total column optical depth:
+ ! tau_elm(i) = total optical depth above the bottom of layer i
+ tau_elm(snl_top) = 0._r8
+ DO i=snl_top+1,snl_btm,1
+ tau_elm(i) = tau_elm(i-1)+tau_star(i-1)
+ ENDDO
+
+ ! Direct radiation at bottom of snowpack:
+ F_direct_btm = albsfc_lcl(bnd_idx)*mu_not * &
+ exp(-(tau_elm(snl_btm)+tau_star(snl_btm))/mu_not)*pi*flx_slrd_lcl(bnd_idx)
+
+ ! Intermediates
+ ! Gamma values are approximation-specific.
+
+ ! Eddington
+ IF (APRX_TYP==1) THEN
+ DO i=snl_top,snl_btm,1
+ gamma1(i) = (7-(omega_star(i)*(4+(3*g_star(i)))))/4
+ gamma2(i) = -(1-(omega_star(i)*(4-(3*g_star(i)))))/4
+ gamma3(i) = (2-(3*g_star(i)*mu_not))/4
+ gamma4(i) = 1-gamma3(i)
+ mu_one = 0.5
+ ENDDO
+
+ ! Quadrature
+ ELSEIF (APRX_TYP==2) THEN
+ DO i=snl_top,snl_btm,1
+ gamma1(i) = (3**0.5)*(2-(omega_star(i)*(1+g_star(i))))/2
+ gamma2(i) = omega_star(i)*(3**0.5)*(1-g_star(i))/2
+ gamma3(i) = (1-((3**0.5)*g_star(i)*mu_not))/2
+ gamma4(i) = 1-gamma3(i)
+ mu_one = 1/(3**0.5)
+ ENDDO
+
+ ! Hemispheric Mean
+ ELSEIF (APRX_TYP==3) THEN
+ DO i=snl_top,snl_btm,1
+ gamma1(i) = 2 - (omega_star(i)*(1+g_star(i)))
+ gamma2(i) = omega_star(i)*(1-g_star(i))
+ gamma3(i) = (1-((3**0.5)*g_star(i)*mu_not))/2
+ gamma4(i) = 1-gamma3(i)
+ mu_one = 0.5
+ ENDDO
+ ENDIF
+
+ ! Intermediates for tri-diagonal solution
+ DO i=snl_top,snl_btm,1
+ lambda(i) = sqrt(abs((gamma1(i)**2) - (gamma2(i)**2)))
+ GAMMA(i) = gamma2(i)/(gamma1(i)+lambda(i))
+
+ e1(i) = 1+(GAMMA(i)*exp(-lambda(i)*tau_star(i)))
+ e2(i) = 1-(GAMMA(i)*exp(-lambda(i)*tau_star(i)))
+ e3(i) = GAMMA(i) + exp(-lambda(i)*tau_star(i))
+ e4(i) = GAMMA(i) - exp(-lambda(i)*tau_star(i))
+ ENDDO !ENDDO over snow layers
+
+ ! Intermediates for tri-diagonal solution
+ DO i=snl_top,snl_btm,1
+ IF (flg_slr_in == 1) THEN
+
+ C_pls_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-(tau_elm(i)+tau_star(i))/mu_not)* &
+ (((gamma1(i)-(1/mu_not))*gamma3(i))+ &
+ (gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ C_mns_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-(tau_elm(i)+tau_star(i))/mu_not)* &
+ (((gamma1(i)+(1/mu_not))*gamma4(i))+ &
+ (gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ C_pls_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-tau_elm(i)/mu_not)*(((gamma1(i)-(1/mu_not))* &
+ gamma3(i))+(gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ C_mns_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-tau_elm(i)/mu_not)*(((gamma1(i)+(1/mu_not))* &
+ gamma4(i))+(gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ ELSE
+ C_pls_btm(i) = 0._r8
+ C_mns_btm(i) = 0._r8
+ C_pls_top(i) = 0._r8
+ C_mns_top(i) = 0._r8
+ ENDIF
+ ENDDO
+
+ ! Coefficients for tridiaganol matrix solution
+ DO i=2*snl_lcl+1,0,1
+
+ !Boundary values for i=1 and i=2*snl_lcl, specifics for i=odd and i=even
+ IF (i==(2*snl_lcl+1)) THEN
+ A(i) = 0
+ B(i) = e1(snl_top)
+ D(i) = -e2(snl_top)
+ E(i) = flx_slri_lcl(bnd_idx)-C_mns_top(snl_top)
+
+ ELSEIF(i==0) THEN
+ A(i) = e1(snl_btm)-(albsfc_lcl(bnd_idx)*e3(snl_btm))
+ B(i) = e2(snl_btm)-(albsfc_lcl(bnd_idx)*e4(snl_btm))
+ D(i) = 0
+ E(i) = F_direct_btm-C_pls_btm(snl_btm)+(albsfc_lcl(bnd_idx)*C_mns_btm(snl_btm))
+
+ ELSEIF(mod(i,2)==-1) THEN ! If odd and i>=3 (n=1 for i=3)
+ n=floor(i/2.0)
+ A(i) = (e2(n)*e3(n))-(e4(n)*e1(n))
+ B(i) = (e1(n)*e1(n+1))-(e3(n)*e3(n+1))
+ D(i) = (e3(n)*e4(n+1))-(e1(n)*e2(n+1))
+ E(i) = (e3(n)*(C_pls_top(n+1)-C_pls_btm(n)))+(e1(n)*(C_mns_btm(n)-C_mns_top(n+1)))
+
+ ELSEIF(mod(i,2)==0) THEN ! If even and i<=2*snl_lcl
+ n=(i/2)
+ A(i) = (e2(n+1)*e1(n))-(e3(n)*e4(n+1))
+ B(i) = (e2(n)*e2(n+1))-(e4(n)*e4(n+1))
+ D(i) = (e1(n+1)*e4(n+1))-(e2(n+1)*e3(n+1))
+ E(i) = (e2(n+1)*(C_pls_top(n+1)-C_pls_btm(n)))+(e4(n+1)*(C_mns_top(n+1)-C_mns_btm(n)))
+ ENDIF
+ ENDDO
+
+ AS(0) = A(0)/B(0)
+ DS(0) = E(0)/B(0)
+
+ DO i=-1,(2*snl_lcl+1),-1
+ X(i) = 1/(B(i)-(D(i)*AS(i+1)))
+ AS(i) = A(i)*X(i)
+ DS(i) = (E(i)-(D(i)*DS(i+1)))*X(i)
+ ENDDO
+
+ Y(2*snl_lcl+1) = DS(2*snl_lcl+1)
+ DO i=(2*snl_lcl+2),0,1
+ Y(i) = DS(i)-(AS(i)*Y(i-1))
+ ENDDO
+
+ ! Downward direct-beam and net flux (F_net) at the base of each layer:
+ DO i=snl_top,snl_btm,1
+ F_direct(i) = mu_not*pi*flx_slrd_lcl(bnd_idx)*exp(-(tau_elm(i)+tau_star(i))/mu_not)
+ F_net(i) = (Y(2*i-1)*(e1(i)-e3(i))) + (Y(2*i)*(e2(i)-e4(i))) + &
+ C_pls_btm(i) - C_mns_btm(i) - F_direct(i)
+ ENDDO
+
+ ! Upward flux at snowpack top:
+ F_sfc_pls = (Y(2*snl_lcl+1)*(exp(-lambda(snl_top)*tau_star(snl_top))+ &
+ GAMMA(snl_top))) + (Y(2*snl_lcl+2)*(exp(-lambda(snl_top)* &
+ tau_star(snl_top))-GAMMA(snl_top))) + C_pls_top(snl_top)
+
+ ! Net flux at bottom = absorbed radiation by underlying surface:
+ F_btm_net = -F_net(snl_btm)
+
+
+ ! Bulk column albedo and surface net flux
+ albedo = F_sfc_pls/((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx))
+ F_sfc_net = F_sfc_pls - ((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx))
+
+ trip = 0
+ ! Absorbed flux in each layer
+ DO i=snl_top,snl_btm,1
+ IF(i==snl_top) THEN
+ F_abs(i) = F_net(i)-F_sfc_net
+ ELSE
+ F_abs(i) = F_net(i)-F_net(i-1)
+ ENDIF
+ flx_abs_lcl(i,bnd_idx) = F_abs(i)
+
+
+ ! ERROR check: negative absorption
+ IF (flx_abs_lcl(i,bnd_idx) < -0.00001) THEN
+ trip = 1
+ ENDIF
+ ENDDO
+
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+
+ IF (flg_nosnl == 1) THEN
+ ! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer
+ !flx_abs_lcl(:,bnd_idx) = 0._r8
+ !flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net
+
+ ! changed on 20070408:
+ ! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation
+ ! handles the CASE of no snow layers. Then, IF a snow layer is addded between now and
+ ! SurfaceRadiation (called in CanopyHydrology), absorbed energy will be properly distributed.
+ flx_abs_lcl(0,bnd_idx) = F_abs(0)
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+
+ ENDIF
+
+ !Underflow check (we've already tripped the error condition above)
+ DO i=snl_top,1,1
+ IF (flx_abs_lcl(i,bnd_idx) < 0._r8) THEN
+ flx_abs_lcl(i,bnd_idx) = 0._r8
+ ENDIF
+ ENDDO
+
+ F_abs_sum = 0._r8
+ DO i=snl_top,snl_btm,1
+ F_abs_sum = F_abs_sum + F_abs(i)
+ ENDDO
+
+
+ !ERROR check: absorption greater than incident flux
+ ! (should make condition more generic than "1._r8")
+ IF (F_abs_sum > 1._r8) THEN
+ trip = 1
+ ENDIF
+
+ !ERROR check:
+ IF ((albedo < 0._r8).and.(trip==0)) THEN
+ trip = 1
+ ENDIF
+
+ ! Set conditions for redoing RT calculation
+ IF ((trip == 1).and.(flg_dover == 1)) THEN
+ flg_dover = 2
+ ELSEIF ((trip == 1).and.(flg_dover == 2)) THEN
+ flg_dover = 3
+ ELSEIF ((trip == 1).and.(flg_dover == 3)) THEN
+ flg_dover = 4
+ ELSEIF((trip == 1).and.(flg_dover == 4).and.(err_idx < 20)) THEN
+ flg_dover = 3
+ err_idx = err_idx + 1
+ ELSEIF((trip == 1).and.(flg_dover == 4).and.(err_idx >= 20)) THEN
+ flg_dover = 0
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ write(iulog,*) "SNICAR ERROR: FOUND A WORMHOLE. STUCK IN INFINITE LOOP! Called from: ", flg_snw_ice
+ write(iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(0)
+ write(iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
+ write(iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write(iulog,*) "SNICAR STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1)
+ write(iulog,*) "SNICAR STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2)
+ write(iulog,*) "SNICAR STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3)
+ write(iulog,*) "SNICAR STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4)
+ write(iulog,*) "SNICAR STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5)
+ write(iulog,*) "SNICAR STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6)
+ write(iulog,*) "frac_sno: ", frac_sno
+ CALL abort
+ ENDIF
+#endif
+ ELSE
+ flg_dover = 0
+ ENDIF
+
+ ENDDO !ENDDO WHILE (flg_dover > 0)
+
+ ! Energy conservation check:
+ ! Incident direct+diffuse radiation equals (absorbed+bulk_transmitted+bulk_reflected)
+ energy_sum = (mu_not*pi*flx_slrd_lcl(bnd_idx)) + flx_slri_lcl(bnd_idx) - (F_abs_sum + F_btm_net + F_sfc_pls)
+ IF (abs(energy_sum) > 0.00001_r8) THEN
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ write(iulog,*) "SNICAR ERROR: Energy conservation error of : ", energy_sum
+ CALL abort
+ ENDIF
+#endif
+ ENDIF
+
+ albout_lcl(bnd_idx) = albedo
+
+ ! Check that albedo is less than 1
+ IF (albout_lcl(bnd_idx) > 1.0) THEN
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ write(iulog,*) "SNICAR ERROR: Albedo > 1.0: "
+ write(iulog,*) "SNICAR STATS: bnd_idx= ",bnd_idx
+ write (iulog,*) "SNICAR STATS: albout_lcl(bnd)= ",albout_lcl(bnd_idx), &
+ " albsfc_lcl(bnd_idx)= ",albsfc_lcl(bnd_idx)
+ write (iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write (iulog,*) "SNICAR STATS: coszen= ", coszen, " flg_slr= ", flg_slr_in
+
+ write (iulog,*) "SNICAR STATS: soot(-4)= ", mss_cnc_aer_lcl(-4,1)
+ write (iulog,*) "SNICAR STATS: soot(-3)= ", mss_cnc_aer_lcl(-3,1)
+ write (iulog,*) "SNICAR STATS: soot(-2)= ", mss_cnc_aer_lcl(-2,1)
+ write (iulog,*) "SNICAR STATS: soot(-1)= ", mss_cnc_aer_lcl(-1,1)
+ write (iulog,*) "SNICAR STATS: soot(0)= ", mss_cnc_aer_lcl(0,1)
+
+ write (iulog,*) "SNICAR STATS: L_snw(-4)= ", L_snw(-4)
+ write (iulog,*) "SNICAR STATS: L_snw(-3)= ", L_snw(-3)
+ write (iulog,*) "SNICAR STATS: L_snw(-2)= ", L_snw(-2)
+ write (iulog,*) "SNICAR STATS: L_snw(-1)= ", L_snw(-1)
+ write (iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
+
+ write (iulog,*) "SNICAR STATS: snw_rds(-4)= ", snw_rds(-4)
+ write (iulog,*) "SNICAR STATS: snw_rds(-3)= ", snw_rds(-3)
+ write (iulog,*) "SNICAR STATS: snw_rds(-2)= ", snw_rds(-2)
+ write (iulog,*) "SNICAR STATS: snw_rds(-1)= ", snw_rds(-1)
+ write (iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(0)
+
+ CALL abort
+ ENDIF
+#endif
+ ENDIF
+
+ ENDDO ! loop over wvl bands
+
+
+ ! Weight output NIR albedo appropriately
+ albout(1) = albout_lcl(1)
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx)
+ ENDDO
+ albout(2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+
+ ! Weight output NIR absorbed layer fluxes (flx_abs) appropriately
+ flx_abs(:,1) = flx_abs_lcl(:,1)
+ DO i=snl_top,1,1
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx)
+ ENDDO
+ flx_abs(i,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+ ENDDO
+
+ ! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo
+ ELSEIF ( (coszen > 0._r8) .and. (h2osno_lcl < min_snw) .and. (h2osno_lcl > 0._r8) ) THEN
+ albout(1) = albsfc(1)
+ albout(2) = albsfc(2)
+
+ ! There is either zero snow, or no sun
+ ELSE
+ albout(1) = 0._r8
+ albout(2) = 0._r8
+ ENDIF ! IF column has snow and coszen > 0
+
+ ! END associate
+
+ END SUBROUTINE SNICAR_RT
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SNICAR_AD_RT (flg_snw_ice, flg_slr_in, &
+ coszen, snl, h2osno, frac_sno, &
+ h2osno_liq, h2osno_ice, snw_rds, &
+ mss_cnc_aer_in, albsfc, albout, flx_abs)
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Determine reflectance of, and vertically-resolved solar absorption in,
+! snow with impurities, with updated shortwave scheme
+!
+! The multi-layer solution for multiple-scattering used here is from:
+! Briegleb, P. and Light, B.: A Delta-Eddington mutiple scattering
+! parameterization for solar radiation in the sea ice component of the
+! community climate system model, 2007.
+!
+! The implementation of the SNICAR-AD model in ELM is described in:
+! Dang et al., Inter-comparison and improvement of 2-stream shortwave
+! radiative transfer models for unified treatment of cryospheric surfaces
+! in ESMs, in review, 2019
+!
+! To USE this subtroutine, set use_snicar_ad = true in ELM
+!
+! IF config_use_snicar_ad = true in MPAS-seaice
+! Snow on land and snow on sea ice will be treated
+! with the same model for their solar radiative properties.
+!
+! The inputs and outputs are the same to SUBROUTINE SNICAR_RT
+!
+! !USES:
+!-----------------------------------------------------------------------
+! !ARGUMENTS:
+
+ IMPLICIT NONE
+
+ integer , intent(in) :: flg_snw_ice ! flag: =1 when called from CLM, =2 when called from CSIM
+ integer , intent(in) :: flg_slr_in ! flag: =1 for direct-beam incident flux,=2 for diffuse incident flux
+ real(r8) , intent(in) :: coszen ! cosine of solar zenith angle for next time step (col) [unitless]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8) , intent(in) :: h2osno ! snow liquid water equivalent (col) [kg/m2]
+ real(r8) , intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+
+ real(r8) , intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg/m2]
+ real(r8) , intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice content (col,lyr) [kg/m2]
+ integer , intent(in) :: snw_rds ( maxsnl+1:0 ) ! snow effective radius (col,lyr) [microns, m^-6]
+ real(r8) , intent(in) :: mss_cnc_aer_in ( maxsnl+1:0 , 1:sno_nbr_aer ) ! mass concentration of all aerosol species (col,lyr,aer) [kg/kg]
+ real(r8) , intent(in) :: albsfc ( 1:numrad ) ! albedo of surface underlying snow (col,bnd) [frc]
+ real(r8) , intent(out) :: albout ( 1:numrad ) ! snow albedo, averaged into 2 bands (=0 IF no sun or no snow) (col,bnd) [frc]
+ real(r8) , intent(out) :: flx_abs ( maxsnl+1:1 , 1:numrad ) ! absorbed flux in each layer per unit flux incident (col, lyr, bnd)
+ !
+ ! !LOCAL VARIABLES:
+ !
+ ! variables for snow radiative transfer calculations
+
+ ! Local variables representing single-column values of arrays:
+ integer :: snl_lcl ! negative number of snow layers [nbr]
+ integer :: snw_rds_lcl(maxsnl+1:0) ! snow effective radius [m^-6]
+ real(r8):: flx_slrd_lcl(1:numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1)
+ real(r8):: flx_slri_lcl(1:numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1)
+ real(r8):: mss_cnc_aer_lcl(maxsnl+1:0,1:sno_nbr_aer) ! aerosol mass concentration (lyr,aer_nbr) [kg/kg]
+ real(r8):: h2osno_lcl ! total column snow mass [kg/m2]
+ real(r8):: h2osno_liq_lcl(maxsnl+1:0) ! liquid water mass [kg/m2]
+ real(r8):: h2osno_ice_lcl(maxsnl+1:0) ! ice mass [kg/m2]
+ real(r8):: albsfc_lcl(1:numrad_snw) ! albedo of underlying surface [frc]
+ real(r8):: ss_alb_snw_lcl(maxsnl+1:0) ! single-scatter albedo of ice grains (lyr) [frc]
+ real(r8):: asm_prm_snw_lcl(maxsnl+1:0) ! asymmetry parameter of ice grains (lyr) [frc]
+ real(r8):: ext_cff_mss_snw_lcl(maxsnl+1:0) ! mass extinction coefficient of ice grains (lyr) [m2/kg]
+ real(r8):: ss_alb_aer_lcl(sno_nbr_aer) ! single-scatter albedo of aerosol species (aer_nbr) [frc]
+ real(r8):: asm_prm_aer_lcl(sno_nbr_aer) ! asymmetry parameter of aerosol species (aer_nbr) [frc]
+ real(r8):: ext_cff_mss_aer_lcl(sno_nbr_aer) ! mass extinction coefficient of aerosol species (aer_nbr) [m2/kg]
+
+#ifdef MODAL_AER
+ !mgf++
+ real(r8) :: rds_bcint_lcl(maxsnl+1:0) ! effective radius of within-ice BC [nm]
+ real(r8) :: rds_bcext_lcl(maxsnl+1:0) ! effective radius of external BC [nm]
+ !mgf--
+#endif
+
+
+ ! Other local variables
+ integer :: DELTA ! flag to USE Delta approximation (Joseph, 1976)
+ ! (1= USE, 0= don't USE)
+ real(r8):: flx_wgt(1:numrad_snw) ! weights applied to spectral bands,
+ ! specific to direct and diffuse cases (bnd) [frc]
+ integer :: flg_nosnl ! flag: =1 IF there is snow, but zero snow layers,
+ ! =0 IF at least 1 snow layer [flg]
+ ! integer :: trip ! flag: =1 to redo RT calculation IF result is unrealistic
+ ! integer :: flg_dover ! defines conditions for RT redo (explained below)
+
+ real(r8):: albedo ! temporary snow albedo [frc]
+ real(r8):: flx_sum ! temporary summation variable for NIR weighting
+ real(r8):: albout_lcl(numrad_snw) ! snow albedo by band [frc]
+ real(r8):: flx_abs_lcl(maxsnl+1:1,numrad_snw) ! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc]
+
+ real(r8):: L_snw(maxsnl+1:0) ! h2o mass (liquid+solid) in snow layer (lyr) [kg/m2]
+ real(r8):: tau_snw(maxsnl+1:0) ! snow optical depth (lyr) [unitless]
+ real(r8):: L_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol mass in snow layer (lyr,nbr_aer) [kg/m2]
+ real(r8):: tau_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol optical depth (lyr,nbr_aer) [unitless]
+ real(r8):: tau_sum ! cumulative (snow+aerosol) optical depth [unitless]
+ real(r8):: tau_elm(maxsnl+1:0) ! column optical depth from layer bottom to snowpack top (lyr) [unitless]
+ real(r8):: omega_sum ! temporary summation of single-scatter albedo of all aerosols [frc]
+ real(r8):: g_sum ! temporary summation of asymmetry parameter of all aerosols [frc]
+
+ real(r8):: tau(maxsnl+1:0) ! weighted optical depth of snow+aerosol layer (lyr) [unitless]
+ real(r8):: omega(maxsnl+1:0) ! weighted single-scatter albedo of snow+aerosol layer (lyr) [frc]
+ real(r8):: g(maxsnl+1:0) ! weighted asymmetry parameter of snow+aerosol layer (lyr) [frc]
+ real(r8):: tau_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) optical depth of snow+aerosol layer
+ ! (lyr) [unitless]
+ real(r8):: omega_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) SSA of snow+aerosol layer (lyr) [frc]
+ real(r8):: g_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) asymmetry paramater of snow+aerosol layer
+ ! (lyr) [frc]
+
+ ! integer :: c_idx ! column indices [idx]
+ integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= numrad_snw) [idx]
+ integer :: rds_idx ! snow effective radius index for retrieving
+ ! Mie parameters from lookup table [idx]
+ integer :: snl_btm ! index of bottom snow layer (0) [idx]
+ integer :: snl_top ! index of top snow layer (-4 to 0) [idx]
+ integer :: fc ! column filter index
+ integer :: i ! layer index [idx]
+ integer :: j ! aerosol number index [idx]
+ integer :: m ! secondary layer index [idx]
+ integer :: nint_snw_rds_min ! nearest integer value of snw_rds_min
+
+ real(r8):: F_abs(maxsnl+1:0) ! net absorbed radiative energy (lyr) [W/m^2]
+ real(r8):: F_abs_sum ! total absorbed energy in column [W/m^2]
+ real(r8):: F_sfc_pls ! upward radiative flux at snowpack top [W/m^2]
+ real(r8):: F_btm_net ! net flux at bottom of snowpack [W/m^2]
+ real(r8):: energy_sum ! sum of all energy terms; should be 0.0 [W/m^2]
+ real(r8):: mu_not ! cosine of solar zenith angle (used locally) [frc]
+
+ integer :: err_idx ! counter for number of times through error loop [nbr]
+ real(r8):: pi ! 3.1415...
+
+ integer :: snw_shp_lcl(maxsnl+1:0) ! Snow grain shape option:
+ ! 1=sphere; 2=spheroid; 3=hexagonal plate; 4=koch snowflake
+ real(r8):: snw_fs_lcl(maxsnl+1:0) ! Shape factor: ratio of nonspherical grain effective radii to that of equal-volume sphere
+ ! 0=USE recommended default value
+ ! others(0 1 (i.e. nonspherical)
+ real(r8):: snw_ar_lcl(maxsnl+1:0) ! % Aspect ratio: ratio of grain width to length
+ ! 0=USE recommended default value
+ ! others(0.1 1 (i.e. nonspherical)
+ real(r8):: &
+ diam_ice , & ! effective snow grain diameter
+ fs_sphd , & ! shape factor for spheroid
+ fs_hex0 , & ! shape factor for hexagonal plate
+ fs_hex , & ! shape factor for hexagonal plate (reference)
+ fs_koch , & ! shape factor for koch snowflake
+ AR_tmp , & ! aspect ratio for spheroid
+ g_ice_Cg_tmp(7) , & ! temporary for calculation of asymetry factor
+ gg_ice_F07_tmp(7) , & ! temporary for calculation of asymetry factor
+ g_ice_F07 , & ! temporary for calculation of asymetry factor
+ g_ice , & ! asymmetry factor
+ gg_F07_intp , & ! temporary for calculation of asymetry factor (interpolated)
+ g_Cg_intp , & ! temporary for calculation of asymetry factor (interpolated)
+ R_1_omega_tmp , & ! temporary for dust-snow mixing calculation
+ C_dust_total ! dust concentration
+
+ integer :: atm_type_index ! index for atmospheric type
+ integer :: slr_zen ! integer value of solar zenith angle
+
+ ! SNICAR_AD new variables, follow sea-ice shortwave conventions
+ real(r8):: &
+ trndir(maxsnl+1:1) , & ! solar beam down transmission from top
+ trntdr(maxsnl+1:1) , & ! total transmission to direct beam for layers above
+ trndif(maxsnl+1:1) , & ! diffuse transmission to diffuse beam for layers above
+ rupdir(maxsnl+1:1) , & ! reflectivity to direct radiation for layers below
+ rupdif(maxsnl+1:1) , & ! reflectivity to diffuse radiation for layers below
+ rdndif(maxsnl+1:1) , & ! reflectivity to diffuse radiation for layers above
+ dfdir(maxsnl+1:1) , & ! down-up flux at interface due to direct beam at top surface
+ dfdif(maxsnl+1:1) , & ! down-up flux at interface due to diffuse beam at top surface
+ dftmp(maxsnl+1:1) ! temporary variable for down-up flux at interface
+
+ real(r8):: &
+ rdir(maxsnl+1:0) , & ! layer reflectivity to direct radiation
+ rdif_a(maxsnl+1:0) , & ! layer reflectivity to diffuse radiation from above
+ rdif_b(maxsnl+1:0) , & ! layer reflectivity to diffuse radiation from below
+ tdir(maxsnl+1:0) , & ! layer transmission to direct radiation (solar beam + diffuse)
+ tdif_a(maxsnl+1:0) , & ! layer transmission to diffuse radiation from above
+ tdif_b(maxsnl+1:0) , & ! layer transmission to diffuse radiation from below
+ trnlay(maxsnl+1:0) ! solar beam transm for layer (direct beam only)
+
+ real(r8):: &
+ ts , & ! layer delta-scaled extinction optical depth
+ ws , & ! layer delta-scaled single scattering albedo
+ gs , & ! layer delta-scaled asymmetry parameter
+ extins , & ! extinction
+ alp , & ! temporary for alpha
+ gam , & ! temporary for agamm
+ amg , & ! alp - gam
+ apg , & ! alp + gam
+ ue , & ! temporary for u
+ refk , & ! interface multiple scattering
+ refkp1 , & ! interface multiple scattering for k+1
+ refkm1 , & ! interface multiple scattering for k-1
+ tdrrdir , & ! direct tran times layer direct ref
+ tdndif ! total down diffuse = tot tran - direct tran
+
+ real(r8) :: &
+ alpha , & ! term in direct reflectivity and transmissivity
+ agamm , & ! term in direct reflectivity and transmissivity
+ el , & ! term in alpha,agamm,n,u
+ taus , & ! scaled extinction optical depth
+ omgs , & ! scaled single particle scattering albedo
+ asys , & ! scaled asymmetry parameter
+ u , & ! term in diffuse reflectivity and transmissivity
+ n , & ! term in diffuse reflectivity and transmissivity
+ lm , & ! temporary for el
+ mu , & ! cosine solar zenith for either snow or water
+ ne ! temporary for n
+
+ ! perpendicular and parallel relative to plane of incidence and scattering
+ real(r8) :: &
+ R1 , & ! perpendicular polarization reflection amplitude
+ R2 , & ! parallel polarization reflection amplitude
+ T1 , & ! perpendicular polarization transmission amplitude
+ T2 , & ! parallel polarization transmission amplitude
+ Rf_dir_a , & ! fresnel reflection to direct radiation
+ Tf_dir_a , & ! fresnel transmission to direct radiation
+ Rf_dif_a , & ! fresnel reflection to diff radiation from above
+ Rf_dif_b , & ! fresnel reflection to diff radiation from below
+ Tf_dif_a , & ! fresnel transmission to diff radiation from above
+ Tf_dif_b ! fresnel transmission to diff radiation from below
+
+ real(r8) :: &
+ gwt , & ! gaussian weight
+ swt , & ! sum of weights
+ trn , & ! layer transmission
+ rdr , & ! rdir for gaussian integration
+ tdr , & ! tdir for gaussian integration
+ smr , & ! accumulator for rdif gaussian integration
+ smt , & ! accumulator for tdif gaussian integration
+ exp_min ! minimum exponential value
+
+ integer :: &
+ ng , & ! gaussian integration index
+ snl_btm_itf , & ! index of bottom snow layer interfaces (1) [idx]
+ ngmax = 8 ! gaussian integration index
+
+ ! Gaussian integration angle and coefficients
+ real(r8) :: difgauspt(1:8) , difgauswt(1:8)
+
+ ! constants used in algorithm
+ real(r8) :: &
+ c0 = 0.0_r8 , &
+ c1 = 1.0_r8 , &
+ c3 = 3.0_r8 , &
+ c4 = 4.0_r8 , &
+ c6 = 6.0_r8 , &
+ cp01 = 0.01_r8 , &
+ cp5 = 0.5_r8 , &
+ cp75 = 0.75_r8 , &
+ c1p5 = 1.5_r8 , &
+ trmin = 0.001_r8 , &
+ argmax = 10.0_r8 ! maximum argument of exponential
+
+ ! cconstant coefficients used for SZA parameterization
+ real(r8) :: &
+ sza_a0 = 0.085730_r8 , &
+ sza_a1 = -0.630883_r8 , &
+ sza_a2 = 1.303723_r8 , &
+ sza_b0 = 1.467291_r8 , &
+ sza_b1 = -3.338043_r8 , &
+ sza_b2 = 6.807489_r8 , &
+ puny = 1.0e-11_r8 , &
+ mu_75 = 0.2588_r8 ! cosine of 75 degree
+
+ ! coefficients used for SZA parameterization
+ real(r8) :: &
+ sza_c1 , & ! coefficient, SZA parameteirzation
+ sza_c0 , & ! coefficient, SZA parameterization
+ sza_factor , & ! factor used to adjust NIR direct albedo
+ flx_sza_adjust , & ! direct NIR flux adjustment from sza_factor
+ mu0 ! incident solar zenith angle
+
+ !-----------------------------------------------------------------------
+#ifdef MODAL_AER
+ !mgf++
+ integer :: idx_bcint_icerds ! index of ice effective radius for optical properties lookup table
+ integer :: idx_bcint_nclrds ! index of within-ice BC effective radius for optical properties lookup table
+ integer :: idx_bcext_nclrds ! index of external BC effective radius for optical properties lookup table
+ real(r8):: enh_fct ! extinction/absorption enhancement factor for within-ice BC
+ real(r8):: tmp1 ! temporary variable
+ !mgf--
+#endif
+
+ ! Constants for non-spherical ice particles and dust-snow internal mixing
+ real(r8) :: g_b2(7)
+ real(r8) :: g_b1(7)
+ real(r8) :: g_b0(7)
+ real(r8) :: g_F07_c2(7)
+ real(r8) :: g_F07_c1(7)
+ real(r8) :: g_F07_c0(7)
+ real(r8) :: g_F07_p2(7)
+ real(r8) :: g_F07_p1(7)
+ real(r8) :: g_F07_p0(7)
+ real(r8) :: dust_clear_d0(3)
+ real(r8) :: dust_clear_d1(3)
+ real(r8) :: dust_clear_d2(3)
+ real(r8) :: dust_cloudy_d0(3)
+ real(r8) :: dust_cloudy_d1(3)
+ real(r8) :: dust_cloudy_d2(3)
+
+ !!! factors for considering snow grain shape
+ data g_b0(:) / 9.76029E-01_r8, 9.67798E-01_r8, 1.00111E+00_r8, 1.00224E+00_r8,&
+ 9.64295E-01_r8, 9.97475E-01_r8, 9.97475E-01_r8/
+ data g_b1(:) / 5.21042E-01_r8, 4.96181E-01_r8, 1.83711E-01_r8, 1.37082E-01_r8,&
+ 5.50598E-02_r8, 8.48743E-02_r8, 8.48743E-02_r8/
+ data g_b2(:) /-2.66792E-04_r8, 1.14088E-03_r8, 2.37011E-04_r8,-2.35905E-04_r8,&
+ 8.40449E-04_r8,-4.71484E-04_r8,-4.71484E-04_r8/
+
+ data g_F07_c2(:) / 1.349959E-1_r8, 1.115697E-1_r8, 9.853958E-2_r8, 5.557793E-2_r8,&
+ -1.233493E-1_r8, 0.0_r8, 0.0_r8/
+ data g_F07_c1(:) /-3.987320E-1_r8,-3.723287E-1_r8,-3.924784E-1_r8,-3.259404E-1_r8,&
+ 4.429054E-2_r8,-1.726586E-1_r8,-1.726586E-1_r8/
+ data g_F07_c0(:) / 7.938904E-1_r8, 8.030084E-1_r8, 8.513932E-1_r8, 8.692241E-1_r8,&
+ 7.085850E-1_r8, 6.412701E-1_r8, 6.412701E-1_r8/
+ data g_F07_p2(:) / 3.165543E-3_r8, 2.014810E-3_r8, 1.780838E-3_r8, 6.987734E-4_r8,&
+ -1.882932E-2_r8,-2.277872E-2_r8,-2.277872E-2_r8/
+ data g_F07_p1(:) / 1.140557E-1_r8, 1.143152E-1_r8, 1.143814E-1_r8, 1.071238E-1_r8,&
+ 1.353873E-1_r8, 1.914431E-1_r8, 1.914431E-1_r8/
+ data g_F07_p0(:) / 5.292852E-1_r8, 5.425909E-1_r8, 5.601598E-1_r8, 6.023407E-1_r8,&
+ 6.473899E-1_r8, 4.634944E-1_r8, 4.634944E-1_r8/
+
+ !!! factors for considring dust-snow internal mixing
+ data dust_clear_d0(:) /1.0413E+00_r8,1.0168E+00_r8,1.0189E+00_r8/
+ data dust_clear_d1(:) /1.0016E+00_r8,1.0070E+00_r8,1.0840E+00_r8/
+ data dust_clear_d2(:) /2.4208E-01_r8,1.5300E-03_r8,1.1230E-04_r8/
+
+ data dust_cloudy_d0(:) /1.0388E+00_r8,1.0167E+00_r8,1.0189E+00_r8/
+ data dust_cloudy_d1(:) /1.0015E+00_r8,1.0061E+00_r8,1.0823E+00_r8/
+ data dust_cloudy_d2(:) /2.5973E-01_r8,1.6200E-03_r8,1.1721E-04_r8/
+
+ ! Enforce expected array sizes
+
+ ! associate(&
+ ! snl => col_pp%snl , & ! Input: [integer (:)] negative number of snow layers (col) [nbr]
+ ! h2osno => col_ws%h2osno , & ! Input: [real(r8) (:)] snow liquid water equivalent (col) [kg/m2]
+ ! frac_sno => col_ws%frac_sno_eff & ! Input: [real(r8) (:)] fraction of ground covered by snow (0 to 1)
+ ! )
+
+ ! Define constants
+ pi = SHR_CONST_PI
+ nint_snw_rds_min = nint(snw_rds_min)
+
+ ! always USE Delta approximation for snow
+ DELTA = 1
+
+ !Gaussian integration angle and coefficients for diffuse radiation
+ difgauspt(1:8) & ! gaussian angles (radians)
+ = (/ 0.9894009_r8, 0.9445750_r8, &
+ 0.8656312_r8, 0.7554044_r8, &
+ 0.6178762_r8, 0.4580168_r8, &
+ 0.2816036_r8, 0.0950125_r8/)
+ difgauswt(1:8) & ! gaussian weights
+ = (/ 0.0271525_r8, 0.0622535_r8, &
+ 0.0951585_r8, 0.1246290_r8, &
+ 0.1495960_r8, 0.1691565_r8, &
+ 0.1826034_r8, 0.1894506_r8/)
+
+ snw_shp_lcl(:) = snow_shape_sphere
+ snw_fs_lcl(:) = 0._r8
+ snw_ar_lcl(:) = 0._r8
+ atm_type_index = atm_type_default
+
+ ! Define snow grain shape
+ IF (trim(snow_shape) == 'sphere') THEN
+ snw_shp_lcl(:) = snow_shape_sphere
+ ELSEIF (trim(snow_shape) == 'spheroid') THEN
+ snw_shp_lcl(:) = snow_shape_spheroid
+ ELSEIF (trim(snow_shape) == 'hexagonal_plate') THEN
+ snw_shp_lcl(:) = snow_shape_hexagonal_plate
+ ELSEIF (trim(snow_shape) == 'koch_snowflake') THEN
+ snw_shp_lcl(:) = snow_shape_koch_snowflake
+ ELSE
+ IF (p_is_root) THEN
+ write(iulog,*) "snow_shape = ", snow_shape
+ CALL abort
+ ENDIF
+ ENDIF
+
+ ! Define atmospheric type
+ IF (trim(snicar_atm_type) == 'default') THEN
+ atm_type_index = atm_type_default
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_winter') THEN
+ atm_type_index = atm_type_mid_latitude_winter
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_summer') THEN
+ atm_type_index = atm_type_mid_latitude_summer
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_winter') THEN
+ atm_type_index = atm_type_sub_Arctic_winter
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_summer') THEN
+ atm_type_index = atm_type_sub_Arctic_summer
+ ELSEIF (trim(snicar_atm_type) == 'summit_Greenland') THEN
+ atm_type_index = atm_type_summit_Greenland
+ ELSEIF (trim(snicar_atm_type) == 'high_mountain') THEN
+ atm_type_index = atm_type_high_mountain
+ ELSE
+ IF (p_is_root) THEN
+ write(iulog,*) "snicar_atm_type = ", snicar_atm_type
+ CALL abort
+ ENDIF
+ ENDIF
+
+ ! (when called from CSIM, there is only one column)
+
+ ! Zero absorbed radiative fluxes:
+ DO i=maxsnl+1,1,1
+ flx_abs_lcl(:,:) = 0._r8
+ flx_abs(i,:) = 0._r8
+ ENDDO
+
+ ! set snow/ice mass to be used for RT:
+ IF (flg_snw_ice == 1) THEN
+ h2osno_lcl = h2osno
+ ELSE
+ h2osno_lcl = h2osno_ice(0)
+ ENDIF
+
+ ! Qualifier for computing snow RT:
+ ! 1) sunlight from atmosphere model
+ ! 2) minimum amount of snow on ground.
+ ! Otherwise, set snow albedo to zero
+ IF ((coszen > 0._r8) .and. (h2osno_lcl > min_snw) ) THEN
+
+ ! Set variables specific to ELM
+ IF (flg_snw_ice == 1) THEN
+ ! If there is snow, but zero snow layers, we must create a layer locally.
+ ! This layer is presumed to have the fresh snow effective radius.
+ IF (snl > -1) THEN
+ flg_nosnl = 1
+ snl_lcl = -1
+ h2osno_ice_lcl(0) = h2osno_lcl
+ h2osno_liq_lcl(0) = 0._r8
+ snw_rds_lcl(0) = nint_snw_rds_min
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = snl
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ ENDIF
+
+ snl_btm = 0
+ snl_top = snl_lcl+1
+
+ ! Set variables specific to CSIM
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = -1
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ snl_btm = 0
+ snl_top = 0
+ ENDIF ! END IF flg_snw_ice == 1
+
+#ifdef MODAL_AER
+ !mgf++
+ !
+ ! Assume fixed BC effective radii of 100nm. This is close to
+ ! the effective radius of 95nm (number median radius of
+ ! 40nm) assumed for freshly-emitted BC in MAM. Future
+ ! implementations may prognose the BC effective radius in
+ ! snow.
+ rds_bcint_lcl(:) = 100._r8
+ rds_bcext_lcl(:) = 100._r8
+ !mgf--
+#endif
+
+ ! Set local aerosol array
+ DO j=1,sno_nbr_aer
+ mss_cnc_aer_lcl(:,j) = mss_cnc_aer_in(:,j)
+ ENDDO
+
+ ! Set spectral underlying surface albedos to their corresponding VIS or NIR albedos
+ albsfc_lcl(1) = albsfc(1)
+ albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(2)
+
+ ! Error check for snow grain size:
+ IF (p_is_root) THEN
+ DO i=snl_top,snl_btm,1
+ IF ((snw_rds_lcl(i) < snw_rds_min_tbl) .or. (snw_rds_lcl(i) > snw_rds_max_tbl)) THEN
+ write (iulog,*) "SNICAR ERROR: snow grain radius of ", snw_rds_lcl(i), " out of bounds."
+ write (iulog,*) "flg_snw_ice= ", flg_snw_ice
+ write (iulog,*) " level: ", i, " snl(c)= ", snl_lcl
+ write (iulog,*) "h2osno(c)= ", h2osno_lcl
+ CALL abort
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! Incident flux weighting parameters
+ ! - sum of all VIS bands must equal 1
+ ! - sum of all NIR bands must equal 1
+ !
+ ! Spectral bands (5-band CASE)
+ ! Band 1: 0.3-0.7um (VIS)
+ ! Band 2: 0.7-1.0um (NIR)
+ ! Band 3: 1.0-1.2um (NIR)
+ ! Band 4: 1.2-1.5um (NIR)
+ ! Band 5: 1.5-5.0um (NIR)
+ !
+ ! The following weights are appropriate for surface-incident flux in a mid-latitude winter atmosphere
+ !
+ ! 3-band weights
+ IF (numrad_snw==3) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.66628670195247_r8
+ flx_wgt(3) = 0.33371329804753_r8
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.77887652162877_r8
+ flx_wgt(3) = 0.22112347837123_r8
+ ENDIF
+
+ ! 5-band weights
+ ELSEIF(numrad_snw==5) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ IF (atm_type_index == atm_type_default) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.49352158521175_r8
+ flx_wgt(3) = 0.18099494230665_r8
+ flx_wgt(4) = 0.12094898498813_r8
+ flx_wgt(5) = 0.20453448749347_r8
+ ELSE
+ slr_zen = nint(acos(coszen) * 180._r8 / pi)
+ IF (slr_zen>89) THEN
+ slr_zen = 89
+ ENDIF
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = flx_wgt_dir(atm_type_index, slr_zen+1, 2)
+ flx_wgt(3) = flx_wgt_dir(atm_type_index, slr_zen+1, 3)
+ flx_wgt(4) = flx_wgt_dir(atm_type_index, slr_zen+1, 4)
+ flx_wgt(5) = flx_wgt_dir(atm_type_index, slr_zen+1, 5)
+ ENDIF
+
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ IF (atm_type_index == atm_type_default) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.58581507618433_r8
+ flx_wgt(3) = 0.20156903770812_r8
+ flx_wgt(4) = 0.10917889346386_r8
+ flx_wgt(5) = 0.10343699264369_r8
+ ELSE
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = flx_wgt_dif(atm_type_index, 2)
+ flx_wgt(3) = flx_wgt_dif(atm_type_index, 3)
+ flx_wgt(4) = flx_wgt_dif(atm_type_index, 4)
+ flx_wgt(5) = flx_wgt_dif(atm_type_index, 5)
+ ENDIF
+ ENDIF
+ ENDIF ! END IF numrad_snw
+
+ ! Loop over snow spectral bands
+
+ exp_min = exp(-argmax)
+ DO bnd_idx = 1,numrad_snw
+
+ ! note that we can remove flg_dover since this algorithm is
+ ! stable for mu_not > 0.01
+
+ ! mu_not is cosine solar zenith angle above the fresnel level; make
+ ! sure mu_not is large enough for stable and meaningful radiation
+ ! solution: .01 is like sun just touching horizon with its lower edge
+ ! equivalent to mu0 in sea-ice shortwave model ice_shortwave.F90
+ mu_not = max(coszen, cp01)
+
+
+ ! Set direct or diffuse incident irradiance to 1
+ ! (This has to be within the bnd loop because mu_not is adjusted in rare cases)
+ IF (flg_slr_in == 1) THEN
+ flx_slrd_lcl(bnd_idx) = 1._r8/(mu_not*pi) ! this corresponds to incident irradiance of 1.0
+ flx_slri_lcl(bnd_idx) = 0._r8
+ ELSE
+ flx_slrd_lcl(bnd_idx) = 0._r8
+ flx_slri_lcl(bnd_idx) = 1._r8
+ ENDIF
+
+ ! Pre-emptive error handling: aerosols can reap havoc on these absorptive bands.
+ ! Since extremely high soot concentrations have a negligible effect on these bands, zero them.
+ IF ( (numrad_snw == 5).and.((bnd_idx == 5).or.(bnd_idx == 4)) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ IF ( (numrad_snw == 3).and.(bnd_idx == 3) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ ! Define local Mie parameters based on snow grain size and aerosol species,
+ ! retrieved from a lookup table.
+ IF (flg_slr_in == 1) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (direct radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_drc(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_drc(rds_idx,bnd_idx)
+ ENDDO
+ ELSEIF (flg_slr_in == 2) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (diffuse radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_dfs(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_dfs(rds_idx,bnd_idx)
+ ENDDO
+ ENDIF
+
+ ! Calculate the asymetry factors under different snow grain shapes
+ DO i=snl_top,snl_btm,1
+ IF(snw_shp_lcl(i) == snow_shape_spheroid) THEN ! spheroid
+ diam_ice = 2._r8*snw_rds_lcl(i)
+ IF(snw_fs_lcl(i) == 0._r8) THEN
+ fs_sphd = 0.929_r8
+ ELSE
+ fs_sphd = snw_fs_lcl(i)
+ ENDIF
+ fs_hex = 0.788_r8
+ IF(snw_ar_lcl(i) == 0._r8) THEN
+ AR_tmp = 0.5_r8
+ ELSE
+ AR_tmp = snw_ar_lcl(i)
+ ENDIF
+ g_ice_Cg_tmp = g_b0 * ((fs_sphd/fs_hex)**g_b1) * (diam_ice**g_b2)
+ gg_ice_F07_tmp = g_F07_c0 + g_F07_c1 * AR_tmp + g_F07_c2 * (AR_tmp**2)
+ ELSEIF(snw_shp_lcl(i) == snow_shape_hexagonal_plate) THEN ! hexagonal plate
+ diam_ice = 2._r8*snw_rds_lcl(i)
+ IF(snw_fs_lcl(i) == 0._r8) THEN
+ fs_hex0 = 0.788_r8
+ ELSE
+ fs_hex0 = snw_fs_lcl(i)
+ ENDIF
+ fs_hex = 0.788_r8
+ IF(snw_ar_lcl(i) == 0._r8) THEN
+ AR_tmp = 2.5_r8
+ ELSE
+ AR_tmp = snw_ar_lcl(i)
+ ENDIF
+ g_ice_Cg_tmp = g_b0 * ((fs_hex0/fs_hex)**g_b1) * (diam_ice**g_b2)
+ gg_ice_F07_tmp = g_F07_p0 + g_F07_p1 * log(AR_tmp) + g_F07_p2 * ((log(AR_tmp))**2)
+ ELSEIF(snw_shp_lcl(i) == snow_shape_koch_snowflake) THEN ! Koch snowflake
+ diam_ice = 2._r8 * snw_rds_lcl(i) /0.544_r8
+ IF(snw_fs_lcl(i) == 0._r8) THEN
+ fs_koch = 0.712_r8
+ ELSE
+ fs_koch = snw_fs_lcl(i)
+ ENDIF
+ fs_hex = 0.788_r8
+ IF(snw_ar_lcl(i) == 0._r8) THEN
+ AR_tmp = 2.5_r8
+ ELSE
+ AR_tmp = snw_ar_lcl(i)
+ ENDIF
+ g_ice_Cg_tmp = g_b0 * ((fs_koch/fs_hex)**g_b1) * (diam_ice**g_b2)
+ gg_ice_F07_tmp = g_F07_p0 + g_F07_p1 * log(AR_tmp) + g_F07_p2 * ((log(AR_tmp))**2)
+ ENDIF
+
+ ! Linear interpolation for calculating the asymetry factor at band_idx.
+ IF(snw_shp_lcl(i) > 1) THEN
+ IF(bnd_idx == 1) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(2)-g_ice_Cg_tmp(1))/(1.055_r8-0.475_r8)*(0.5_r8-0.475_r8) +g_ice_Cg_tmp(1)
+ gg_F07_intp = (gg_ice_F07_tmp(2)-gg_ice_F07_tmp(1))/(1.055_r8-0.475_r8)*(0.5_r8-0.475_r8)+gg_ice_F07_tmp(1)
+ ELSEIF(bnd_idx == 2) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(2)-g_ice_Cg_tmp(1))/(1.055_r8-0.475_r8)*(0.85_r8-0.475_r8)+g_ice_Cg_tmp(1)
+ gg_F07_intp = (gg_ice_F07_tmp(2)-gg_ice_F07_tmp(1))/(1.055_r8-0.475_r8)*(0.85_r8-0.475_r8)+gg_ice_F07_tmp(1)
+ ELSEIF(bnd_idx == 3) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(3)-g_ice_Cg_tmp(2))/(1.655_r8-1.055_r8)*(1.1_r8-1.055_r8)&
+ +g_ice_Cg_tmp(2)
+ gg_F07_intp = (gg_ice_F07_tmp(3)-gg_ice_F07_tmp(2))/(1.655_r8-1.055_r8)*(1.1_r8-1.055_r8)&
+ +gg_ice_F07_tmp(2)
+ ELSEIF(bnd_idx == 4) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(3)-g_ice_Cg_tmp(2))/(1.655_r8-1.055_r8)*(1.35_r8-1.055_r8)&
+ +g_ice_Cg_tmp(2)
+ gg_F07_intp = (gg_ice_F07_tmp(3)-gg_ice_F07_tmp(2))/(1.655_r8-1.055_r8)*(1.35_r8-1.055_r8)&
+ +gg_ice_F07_tmp(2)
+ ELSEIF(bnd_idx == 5) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(6)-g_ice_Cg_tmp(5))/(3.75_r8-3.0_r8)*(3.25_r8-3.0_r8)&
+ +g_ice_Cg_tmp(5)
+ gg_F07_intp = (gg_ice_F07_tmp(6)-gg_ice_F07_tmp(5))/(3.75_r8-3.0_r8)*(3.25_r8-3.0_r8)&
+ +gg_ice_F07_tmp(5)
+ ENDIF
+ g_ice_F07 = gg_F07_intp + (1._r8 - gg_F07_intp) / ss_alb_snw_lcl(i) / 2._r8
+ g_ice = g_ice_F07 * g_Cg_intp
+ asm_prm_snw_lcl(i) = g_ice
+ ENDIF
+
+ IF(asm_prm_snw_lcl(i) > 0.99_r8) THEN
+ asm_prm_snw_lcl(i) = 0.99_r8
+ ENDIF
+
+ ENDDO
+ !!!-END
+
+ !H. Wang
+ ! aerosol species 1 optical properties
+ ! ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ ! asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ! ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ! ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ ! asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ! ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+ !H. Wang
+ ! aerosol species 3 optical properties
+ ss_alb_aer_lcl(3) = ss_alb_oc1(bnd_idx)
+ asm_prm_aer_lcl(3) = asm_prm_oc1(bnd_idx)
+ ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc1(bnd_idx)
+
+ ! aerosol species 4 optical properties
+ ss_alb_aer_lcl(4) = ss_alb_oc2(bnd_idx)
+ asm_prm_aer_lcl(4) = asm_prm_oc2(bnd_idx)
+ ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc2(bnd_idx)
+
+ ! aerosol species 5 optical properties
+ ss_alb_aer_lcl(5) = ss_alb_dst1(bnd_idx)
+ asm_prm_aer_lcl(5) = asm_prm_dst1(bnd_idx)
+ ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(bnd_idx)
+
+ ! aerosol species 6 optical properties
+ ss_alb_aer_lcl(6) = ss_alb_dst2(bnd_idx)
+ asm_prm_aer_lcl(6) = asm_prm_dst2(bnd_idx)
+ ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(bnd_idx)
+
+ ! aerosol species 7 optical properties
+ ss_alb_aer_lcl(7) = ss_alb_dst3(bnd_idx)
+ asm_prm_aer_lcl(7) = asm_prm_dst3(bnd_idx)
+ ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(bnd_idx)
+
+ ! aerosol species 8 optical properties
+ ss_alb_aer_lcl(8) = ss_alb_dst4(bnd_idx)
+ asm_prm_aer_lcl(8) = asm_prm_dst4(bnd_idx)
+ ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(bnd_idx)
+
+
+ ! 1. snow and aerosol layer column mass (L_snw, L_aer [kg/m^2])
+ ! 2. optical Depths (tau_snw, tau_aer)
+ ! 3. weighted Mie properties (tau, omega, g)
+
+ ! Weighted Mie parameters of each layer
+ DO i=snl_top,snl_btm,1
+#ifdef MODAL_AER
+ !mgf++ within-ice and external BC optical properties
+ !
+ ! Lookup table indices for BC optical properties,
+ ! dependent on snow grain size and BC particle
+ ! size.
+
+ ! valid for 25 < snw_rds < 1625 um:
+ IF (snw_rds_lcl(i) < 125) THEN
+ tmp1 = snw_rds_lcl(i)/50
+ idx_bcint_icerds = nint(tmp1)
+ ELSEIF (snw_rds_lcl(i) < 175) THEN
+ idx_bcint_icerds = 2
+ ELSE
+ tmp1 = (snw_rds_lcl(i)/250)+2
+ idx_bcint_icerds = nint(tmp1)
+ ENDIF
+
+ ! valid for 25 < bc_rds < 525 nm
+ idx_bcint_nclrds = nint(rds_bcint_lcl(i)/50)
+ idx_bcext_nclrds = nint(rds_bcext_lcl(i)/50)
+
+ ! check bounds:
+ IF (idx_bcint_icerds < idx_bcint_icerds_min) idx_bcint_icerds = idx_bcint_icerds_min
+ IF (idx_bcint_icerds > idx_bcint_icerds_max) idx_bcint_icerds = idx_bcint_icerds_max
+ IF (idx_bcint_nclrds < idx_bc_nclrds_min) idx_bcint_nclrds = idx_bc_nclrds_min
+ IF (idx_bcint_nclrds > idx_bc_nclrds_max) idx_bcint_nclrds = idx_bc_nclrds_max
+ IF (idx_bcext_nclrds < idx_bc_nclrds_min) idx_bcext_nclrds = idx_bc_nclrds_min
+ IF (idx_bcext_nclrds > idx_bc_nclrds_max) idx_bcext_nclrds = idx_bc_nclrds_max
+
+ ! retrieve absorption enhancement factor for within-ice BC
+ enh_fct = bcenh(bnd_idx,idx_bcint_nclrds,idx_bcint_icerds)
+
+ ! get BC optical properties (moved from above)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx,idx_bcint_nclrds)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx,idx_bcint_nclrds)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx,idx_bcint_nclrds)*enh_fct
+
+ ! aerosol species 2 optical properties (external BC)
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx,idx_bcext_nclrds)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx,idx_bcext_nclrds)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx,idx_bcext_nclrds)
+
+#else
+ ! bulk aerosol treatment (BC optical properties independent
+ ! of BC and ice grain size)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+#endif
+
+ ! Calculate single-scattering albedo for internal mixing of dust-snow
+ IF (use_dust_snow_internal_mixing) THEN
+ IF (bnd_idx < 4) THEN
+ C_dust_total = mss_cnc_aer_lcl(i,5) + mss_cnc_aer_lcl(i,6) &
+ + mss_cnc_aer_lcl(i,7) + mss_cnc_aer_lcl(i,8)
+ C_dust_total = C_dust_total * 1.0E+06_r8
+ IF(C_dust_total > 0._r8) THEN
+ IF (flg_slr_in == 1) THEN
+ R_1_omega_tmp = dust_clear_d0(bnd_idx) &
+ + dust_clear_d2(bnd_idx)*(C_dust_total**dust_clear_d1(bnd_idx))
+ ELSE
+ R_1_omega_tmp = dust_cloudy_d0(bnd_idx) &
+ + dust_cloudy_d2(bnd_idx)*(C_dust_total**dust_cloudy_d1(bnd_idx))
+ ENDIF
+ ss_alb_snw_lcl(i) = 1.0_r8 - (1.0_r8 - ss_alb_snw_lcl(i)) *R_1_omega_tmp
+ ENDIF
+ ENDIF
+ DO j = 5,8,1
+ ss_alb_aer_lcl(j) = 0._r8
+ asm_prm_aer_lcl(j) = 0._r8
+ ext_cff_mss_aer_lcl(j) = 0._r8
+ ENDDO
+ ENDIF
+
+ !mgf--
+
+ L_snw(i) = h2osno_ice_lcl(i)+h2osno_liq_lcl(i)
+ tau_snw(i) = L_snw(i)*ext_cff_mss_snw_lcl(i)
+
+ DO j=1,sno_nbr_aer
+ IF (use_dust_snow_internal_mixing .and. (j >= 5)) THEN
+ L_aer(i,j) = 0._r8
+ ELSE
+ L_aer(i,j) = L_snw(i)*mss_cnc_aer_lcl(i,j)
+ ENDIF
+ tau_aer(i,j) = L_aer(i,j)*ext_cff_mss_aer_lcl(j)
+ ENDDO
+
+ tau_sum = 0._r8
+ omega_sum = 0._r8
+ g_sum = 0._r8
+
+ DO j=1,sno_nbr_aer
+ tau_sum = tau_sum + tau_aer(i,j)
+ omega_sum = omega_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j))
+ g_sum = g_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j)*asm_prm_aer_lcl(j))
+ ENDDO
+
+ tau(i) = tau_sum + tau_snw(i)
+ omega(i) = (1/tau(i))*(omega_sum+(ss_alb_snw_lcl(i)*tau_snw(i)))
+ g(i) = (1/(tau(i)*omega(i)))*(g_sum+ (asm_prm_snw_lcl(i)*ss_alb_snw_lcl(i)*tau_snw(i)))
+ ENDDO ! endWeighted Mie parameters of each layer
+
+ ! DELTA transformations, IF requested
+ IF (DELTA == 1) THEN
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)/(1+g(i))
+ omega_star(i) = ((1-(g(i)**2))*omega(i)) / (1-(omega(i)*(g(i)**2)))
+ tau_star(i) = (1-(omega(i)*(g(i)**2)))*tau(i)
+ ENDDO
+ ELSE
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)
+ omega_star(i) = omega(i)
+ tau_star(i) = tau(i)
+ ENDDO
+ ENDIF
+
+ ! Begin radiative transfer solver
+ ! Given input vertical profiles of optical properties, evaluate the
+ ! monochromatic Delta-Eddington adding-doubling solution
+
+ ! note that trndir, trntdr, trndif, rupdir, rupdif, rdndif
+ ! are variables at the layer interface,
+ ! for snow with layers rangeing from snl_top to snl_btm
+ ! there are snl_top to snl_btm+1 layer interface
+ snl_btm_itf = snl_btm + 1
+
+ DO i = snl_top,snl_btm_itf,1
+ trndir(i) = c0
+ trntdr(i) = c0
+ trndif(i) = c0
+ rupdir(i) = c0
+ rupdif(i) = c0
+ rdndif(i) = c0
+ ENDDO
+
+ ! initialize top interface of top layer
+ trndir(snl_top) = c1
+ trntdr(snl_top) = c1
+ trndif(snl_top) = c1
+ rdndif(snl_top) = c0
+
+ ! begin main level loop
+ ! for layer interfaces except for the very bottom
+ DO i = snl_top,snl_btm,1
+
+ ! initialize all layer apparent optical properties to 0
+ rdir (i) = c0
+ rdif_a(i) = c0
+ rdif_b(i) = c0
+ tdir (i) = c0
+ tdif_a(i) = c0
+ tdif_b(i) = c0
+ trnlay(i) = c0
+
+ ! compute next layer Delta-eddington solution only IF total transmission
+ ! of radiation to the interface just above the layer exceeds trmin.
+
+ IF (trntdr(i) > trmin ) THEN
+
+ ! calculation over layers with penetrating radiation
+
+ ! delta-transformed single-scattering properties
+ ! of this layer
+ ts = tau_star(i)
+ ws = omega_star(i)
+ gs = g_star(i)
+
+ ! Delta-Eddington solution expressions
+ ! n(uu,et) = ((uu+c1)*(uu+c1)/et ) - ((uu-c1)*(uu-c1)*et)
+ ! u(w,gg,e) = c1p5*(c1 - w*gg)/e
+ ! el(w,gg) = sqrt(c3*(c1-w)*(c1 - w*gg))
+ lm = sqrt(c3*(c1-ws)*(c1 - ws*gs)) !lm = el(ws,gs)
+ ue = c1p5*(c1 - ws*gs)/lm !ue = u(ws,gs,lm)
+ extins = max(exp_min, exp(-lm*ts))
+ ne = ((ue+c1)*(ue+c1)/extins) - ((ue-c1)*(ue-c1)*extins) !ne = n(ue,extins)
+
+ ! first calculation of rdif, tdif using Delta-Eddington formulas
+ ! rdif_a(k) = (ue+c1)*(ue-c1)*(c1/extins - extins)/ne
+ rdif_a(i) = (ue**2-c1)*(c1/extins - extins)/ne
+ tdif_a(i) = c4*ue/ne
+
+ ! evaluate rdir,tdir for direct beam
+ trnlay(i) = max(exp_min, exp(-ts/mu_not))
+
+ ! Delta-Eddington solution expressions
+ ! alpha(w,uu,gg,e) = p75*w*uu*((c1 + gg*(c1-w))/(c1 - e*e*uu*uu))
+ ! agamm(w,uu,gg,e) = p5*w*((c1 + c3*gg*(c1-w)*uu*uu)/(c1-e*e*uu*uu))
+ ! alp = alpha(ws,mu_not,gs,lm)
+ ! gam = agamm(ws,mu_not,gs,lm)
+ alp = cp75*ws*mu_not*((c1 + gs*(c1-ws))/(c1 - lm*lm*mu_not*mu_not))
+ gam = cp5*ws*((c1 + c3*gs*(c1-ws)*mu_not*mu_not)/(c1-lm*lm*mu_not*mu_not))
+ apg = alp + gam
+ amg = alp - gam
+
+ rdir(i) = apg*rdif_a(i) + amg*(tdif_a(i)*trnlay(i) - c1)
+ tdir(i) = apg*tdif_a(i) + (amg* rdif_a(i)-apg+c1)*trnlay(i)
+
+ ! recalculate rdif,tdif using direct angular integration over rdir,tdir,
+ ! since Delta-Eddington rdif formula is not well-behaved (it is usually
+ ! biased low and can even be negative); USE ngmax angles and gaussian
+ ! integration for most accuracy:
+ R1 = rdif_a(i) ! USE R1 as temporary
+ T1 = tdif_a(i) ! USE T1 as temporary
+ swt = c0
+ smr = c0
+ smt = c0
+ DO ng=1,ngmax
+ mu = difgauspt(ng)
+ gwt = difgauswt(ng)
+ swt = swt + mu*gwt
+ trn = max(exp_min, exp(-ts/mu))
+ ! alp = alpha(ws,mu,gs,lm)
+ ! gam = agamm(ws,mu,gs,lm)
+ alp = cp75*ws*mu*((c1 + gs*(c1-ws))/(c1 - lm*lm*mu*mu))
+ gam = cp5*ws*((c1 + c3*gs*(c1-ws)*mu*mu)/(c1-lm*lm*mu*mu))
+ apg = alp + gam
+ amg = alp - gam
+ rdr = apg*R1 + amg*T1*trn - amg
+ tdr = apg*T1 + amg*R1*trn - apg*trn + trn
+ smr = smr + mu*rdr*gwt
+ smt = smt + mu*tdr*gwt
+ ENDDO ! ng
+ rdif_a(i) = smr/swt
+ tdif_a(i) = smt/swt
+
+ ! homogeneous layer
+ rdif_b(i) = rdif_a(i)
+ tdif_b(i) = tdif_a(i)
+
+ ENDIF ! trntdr(k) > trmin
+
+ ! Calculate the solar beam transmission, total transmission, and
+ ! reflectivity for diffuse radiation from below at interface i,
+ ! the top of the current layer k:
+ !
+ ! layers interface
+ !
+ ! --------------------- i-1
+ ! i-1
+ ! --------------------- i
+ ! i
+ ! ---------------------
+
+ trndir(i+1) = trndir(i)*trnlay(i)
+ refkm1 = c1/(c1 - rdndif(i)*rdif_a(i))
+ tdrrdir = trndir(i)*rdir(i)
+ tdndif = trntdr(i) - trndir(i)
+ trntdr(i+1) = trndir(i)*tdir(i) + &
+ (tdndif + tdrrdir*rdndif(i))*refkm1*tdif_a(i)
+ rdndif(i+1) = rdif_b(i) + &
+ (tdif_b(i)*rdndif(i)*refkm1*tdif_a(i))
+ trndif(i+1) = trndif(i)*refkm1*tdif_a(i)
+
+ ENDDO ! END main level loop
+
+
+ ! compute reflectivity to direct and diffuse radiation for layers
+ ! below by adding succesive layers starting from the underlying
+ ! ground and working upwards:
+ !
+ ! layers interface
+ !
+ ! --------------------- i
+ ! i
+ ! --------------------- i+1
+ ! i+1
+ ! ---------------------
+
+ ! set the underlying ground albedo == albedo of near-IR
+ ! unless bnd_idx == 1, for visible
+ rupdir(snl_btm_itf) = albsfc(2)
+ rupdif(snl_btm_itf) = albsfc(2)
+ IF (bnd_idx == 1) THEN
+ rupdir(snl_btm_itf) = albsfc(1)
+ rupdif(snl_btm_itf) = albsfc(1)
+ ENDIF
+
+ DO i=snl_btm,snl_top,-1
+ ! interface scattering
+ refkp1 = c1/( c1 - rdif_b(i)*rupdif(i+1))
+ ! dir from top layer plus exp tran ref from lower layer, interface
+ ! scattered and tran thru top layer from below, plus diff tran ref
+ ! from lower layer with interface scattering tran thru top from below
+ rupdir(i) = rdir(i) &
+ + ( trnlay(i) *rupdir(i+1) &
+ + (tdir(i)-trnlay(i))*rupdif(i+1))*refkp1*tdif_b(i)
+ ! dif from top layer from above, plus dif tran upwards reflected and
+ ! interface scattered which tran top from below
+ rupdif(i) = rdif_a(i) + tdif_a(i)*rupdif(i+1)*refkp1*tdif_b(i)
+ ENDDO ! i
+
+ ! net flux (down-up) at each layer interface from the
+ ! snow top (i = snl_top) to bottom interface above land (i = snl_btm_itf)
+ ! the interface reflectivities and transmissivities required
+ ! to evaluate interface fluxes are returned from solution_dEdd;
+ ! now compute up and down fluxes for each interface, using the
+ ! combined layer properties at each interface:
+ !
+ ! layers interface
+ !
+ ! --------------------- i
+ ! i
+ ! ---------------------
+
+ DO i = snl_top, snl_btm_itf
+ ! interface scattering
+ refk = c1/(c1 - rdndif(i)*rupdif(i))
+ ! dir tran ref from below times interface scattering, plus diff
+ ! tran and ref from below times interface scattering
+ ! fdirup(i) = (trndir(i)*rupdir(i) + &
+ ! (trntdr(i)-trndir(i)) &
+ ! *rupdif(i))*refk
+ ! dir tran plus total diff trans times interface scattering plus
+ ! dir tran with up dir ref and down dif ref times interface scattering
+ ! fdirdn(i) = trndir(i) + (trntdr(i) &
+ ! - trndir(i) + trndir(i) &
+ ! *rupdir(i)*rdndif(i))*refk
+ ! diffuse tran ref from below times interface scattering
+ ! fdifup(i) = trndif(i)*rupdif(i)*refk
+ ! diffuse tran times interface scattering
+ ! fdifdn(i) = trndif(i)*refk
+
+ ! netflux, down - up
+ ! dfdir = fdirdn - fdirup
+ dfdir(i) = trndir(i) &
+ + (trntdr(i)-trndir(i)) * (c1 - rupdif(i)) * refk &
+ - trndir(i)*rupdir(i) * (c1 - rdndif(i)) * refk
+ IF (dfdir(i) < puny) dfdir(i) = c0
+ ! dfdif = fdifdn - fdifup
+ dfdif(i) = trndif(i) * (c1 - rupdif(i)) * refk
+ IF (dfdif(i) < puny) dfdif(i) = c0
+ ENDDO ! k
+
+ ! SNICAR_AD_RT is called twice for direct and diffuse incident fluxes
+ ! direct incident
+ IF (flg_slr_in == 1) THEN
+ albedo = rupdir(snl_top)
+ dftmp = dfdir
+ refk = c1/(c1 - rdndif(snl_top)*rupdif(snl_top))
+ F_sfc_pls = (trndir(snl_top)*rupdir(snl_top) + &
+ (trntdr(snl_top)-trndir(snl_top)) &
+ *rupdif(snl_top))*refk
+ !diffuse incident
+ ELSE
+ albedo = rupdif(snl_top)
+ dftmp = dfdif
+ refk = c1/(c1 - rdndif(snl_top)*rupdif(snl_top))
+ F_sfc_pls = trndif(snl_top)*rupdif(snl_top)*refk
+ ENDIF
+
+ ! Absorbed flux in each layer
+ DO i=snl_top,snl_btm,1
+ F_abs(i) = dftmp(i)-dftmp(i+1)
+ flx_abs_lcl(i,bnd_idx) = F_abs(i)
+
+ ! ERROR check: negative absorption
+ IF (p_is_root) THEN
+ IF (flx_abs_lcl(i,bnd_idx) < -0.00001) THEN
+ write (iulog,"(a,e13.6,a,i6)") "SNICAR ERROR: negative absoption : ", flx_abs_lcl(i,bnd_idx)
+ write(iulog,*) "SNICAR_AD STATS: snw_rds(0)= ", snw_rds(0)
+ write(iulog,*) "SNICAR_AD STATS: L_snw(0)= ", L_snw(0)
+ write(iulog,*) "SNICAR_AD STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write(iulog,*) "SNICAR_AD STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1)
+ write(iulog,*) "SNICAR_AD STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2)
+ write(iulog,*) "SNICAR_AD STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3)
+ write(iulog,*) "SNICAR_AD STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4)
+ write(iulog,*) "SNICAR_AD STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5)
+ write(iulog,*) "SNICAR_AD STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6)
+ CALL abort
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! absobed flux by the underlying ground
+ F_btm_net = dftmp(snl_btm_itf)
+
+ ! note here, snl_btm_itf = 1 by snow column set up in CLM
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+
+ IF (flg_nosnl == 1) THEN
+ ! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer
+ !flx_abs_lcl(:,bnd_idx) = 0._r8
+ !flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net
+
+ ! changed on 20070408:
+ ! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation
+ ! handles the CASE of no snow layers. Then, IF a snow layer is addded between now and
+ ! SurfaceRadiation (called in CanopyHydrology), absorbed energy will be properly distributed.
+ flx_abs_lcl(0,bnd_idx) = F_abs(0)
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+ ENDIF
+
+ !Underflow check (we've already tripped the error condition above)
+ DO i=snl_top,1,1
+ IF (flx_abs_lcl(i,bnd_idx) < 0._r8) THEN
+ flx_abs_lcl(i,bnd_idx) = 0._r8
+ ENDIF
+ ENDDO
+
+ F_abs_sum = 0._r8
+ DO i=snl_top,snl_btm,1
+ F_abs_sum = F_abs_sum + F_abs(i)
+ ENDDO
+
+ !ENDDO !ENDDO WHILE (flg_dover > 0)
+
+ ! Energy conservation check:
+ ! Incident direct+diffuse radiation equals (absorbed+bulk_transmitted+bulk_reflected)
+ energy_sum = (mu_not*pi*flx_slrd_lcl(bnd_idx)) + flx_slri_lcl(bnd_idx) - (F_abs_sum + F_btm_net + F_sfc_pls)
+ IF (p_is_root) THEN
+ IF (abs(energy_sum) > 0.00001_r8) THEN
+ write (iulog,"(a,e13.6,a,i6)") "SNICAR ERROR: Energy conservation error of : ", energy_sum
+ write(iulog,*) "F_abs_sum: ",F_abs_sum
+ write(iulog,*) "F_btm_net: ",F_btm_net
+ write(iulog,*) "F_sfc_pls: ",F_sfc_pls
+ write(iulog,*) "mu_not*pi*flx_slrd_lcl(bnd_idx): ", mu_not*pi*flx_slrd_lcl(bnd_idx)
+ write(iulog,*) "flx_slri_lcl(bnd_idx)", flx_slri_lcl(bnd_idx)
+ write(iulog,*) "bnd_idx", bnd_idx
+ write(iulog,*) "F_abs", F_abs
+ write(iulog,*) "albedo", albedo
+ CALL abort
+ ENDIF
+ ENDIF
+
+ albout_lcl(bnd_idx) = albedo
+ ! Check that albedo is less than 1
+ IF (p_is_root) THEN
+ IF (albout_lcl(bnd_idx) > 1.0) THEN
+ write (iulog,*) "SNICAR ERROR: Albedo > 1.0: "
+ write (iulog,*) "SNICAR STATS: bnd_idx= ",bnd_idx
+ write (iulog,*) "SNICAR STATS: albout_lcl(bnd)= ",albout_lcl(bnd_idx), &
+ " albsfc_lcl(bnd_idx)= ",albsfc_lcl(bnd_idx)
+ write (iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write (iulog,*) "SNICAR STATS: coszen= ", coszen, " flg_slr= ", flg_slr_in
+
+ write (iulog,*) "SNICAR STATS: soot(-4)= ", mss_cnc_aer_lcl(-4,1)
+ write (iulog,*) "SNICAR STATS: soot(-3)= ", mss_cnc_aer_lcl(-3,1)
+ write (iulog,*) "SNICAR STATS: soot(-2)= ", mss_cnc_aer_lcl(-2,1)
+ write (iulog,*) "SNICAR STATS: soot(-1)= ", mss_cnc_aer_lcl(-1,1)
+ write (iulog,*) "SNICAR STATS: soot(0)= ", mss_cnc_aer_lcl(0,1)
+
+ write (iulog,*) "SNICAR STATS: L_snw(-4)= ", L_snw(-4)
+ write (iulog,*) "SNICAR STATS: L_snw(-3)= ", L_snw(-3)
+ write (iulog,*) "SNICAR STATS: L_snw(-2)= ", L_snw(-2)
+ write (iulog,*) "SNICAR STATS: L_snw(-1)= ", L_snw(-1)
+ write (iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
+
+ write (iulog,*) "SNICAR STATS: snw_rds(-4)= ", snw_rds(-4)
+ write (iulog,*) "SNICAR STATS: snw_rds(-3)= ", snw_rds(-3)
+ write (iulog,*) "SNICAR STATS: snw_rds(-2)= ", snw_rds(-2)
+ write (iulog,*) "SNICAR STATS: snw_rds(-1)= ", snw_rds(-1)
+ write (iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(0)
+
+ CALL abort
+ ENDIF
+ ENDIF
+
+ ENDDO ! loop over wvl bands
+
+
+ ! Weight output NIR albedo appropriately
+ albout(1) = albout_lcl(1)
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx)
+ ENDDO
+ albout(2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+
+ ! Weight output NIR absorbed layer fluxes (flx_abs) appropriately
+ flx_abs(:,1) = flx_abs_lcl(:,1)
+ DO i=snl_top,1,1
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx)
+ ENDDO
+ flx_abs(i,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+ ENDDO
+
+ ! near-IR direct albedo/absorption adjustment for high solar zenith angles
+ ! solar zenith angle parameterization
+ ! calculate the scaling factor for NIR direct albedo IF SZA>75 degree
+ IF ((mu_not < mu_75) .and. (flg_slr_in == 1)) THEN
+ sza_c1 = sza_a0 + sza_a1 * mu_not + sza_a2 * mu_not**2
+ sza_c0 = sza_b0 + sza_b1 * mu_not + sza_b2 * mu_not**2
+ sza_factor = sza_c1 * (log10(snw_rds_lcl(snl_top) * c1) - c6) + sza_c0
+ flx_sza_adjust = albout(2) * (sza_factor-c1) * sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+ albout(2) = albout(2) * sza_factor
+ flx_abs(snl_top,2) = flx_abs(snl_top,2) - flx_sza_adjust
+ ENDIF
+
+ ! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo
+ ELSEIF ( (coszen > 0._r8) .and. (h2osno_lcl < min_snw) .and. (h2osno_lcl > 0._r8) ) THEN
+ albout(1) = albsfc(1)
+ albout(2) = albsfc(2)
+
+ ! There is either zero snow, or no sun
+ ELSE
+ albout(1) = 0._r8
+ albout(2) = 0._r8
+ ENDIF ! IF column has snow and coszen > 0
+
+ ! END associate
+
+ END SUBROUTINE SNICAR_AD_RT
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowAge_grain( dtime , snl , dz ,&
+ qflx_snow_grnd , qflx_snwcp_ice , qflx_snofrz_lyr ,&
+ do_capsnow , frac_sno , h2osno ,&
+ h2osno_liq , h2osno_ice , t_soisno ,&
+ t_grnd , forc_t , snw_rds )
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Updates the snow effective grain size (radius).
+! Contributions to grain size evolution are from:
+! 1. vapor redistribution (dry snow)
+! 2. liquid water redistribution (wet snow)
+! 3. re-freezing of liquid water
+!
+! Vapor redistribution: Method is to retrieve 3 best-bit parameters that
+! depend on snow temperature, temperature gradient, and density,
+! that are derived from the microphysical model described in:
+! Flanner and Zender (2006), Linking snowpack microphysics and albedo
+! evolution, J. Geophys. Res., 111, D12208, doi:10.1029/2005JD006834.
+! The parametric equation has the form:
+! dr/dt = drdt_0*(tau/(dr_fresh+tau))^(1/kappa), WHERE:
+! r is the effective radius,
+! tau and kappa are best-fit parameters,
+! drdt_0 is the initial rate of change of effective radius, and
+! dr_fresh is the difference between the current and fresh snow states
+! (r_current - r_fresh).
+!
+! Liquid water redistribution: Apply the grain growth FUNCTION from:
+! Brun, E. (1989), Investigation of wet-snow metamorphism in respect of
+! liquid-water content, Annals of Glaciology, 13, 22-26.
+! There are two parameters that describe the grain growth rate as
+! a FUNCTION of snow liquid water content (LWC). The "LWC=0" parameter
+! is zeroed here because we are accounting for dry snowing with a
+! different representation
+!
+! Re-freezing of liquid water: Assume that re-frozen liquid water clumps
+! into an arbitrarily large effective grain size (snw_rds_refrz).
+! The phenomenon is observed (Grenfell), but so far unquantified, as far as
+! I am aware.
+!
+! !USES:
+!
+! DAI, Dec. 29, 2022
+!-----------------------------------------------------------------------
+! !ARGUMENTS:
+
+ IMPLICIT NONE
+
+ real(r8) , intent(in) :: dtime ! land model time step [sec]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8) , intent(in) :: dz ( maxsnl+1:1 ) ! layer thickness (col,lyr) [m]
+
+ real(r8) , intent(in) :: qflx_snow_grnd ! snow on ground after interception (col) [kg m-2 s-1]
+ real(r8) , intent(in) :: qflx_snwcp_ice ! excess precipitation due to snow capping [kg m-2 s-1]
+ real(r8) , intent(in) :: qflx_snofrz_lyr ( maxsnl+1:0 ) ! snow freezing rate (col,lyr) [kg m-2 s-1]
+
+ logical , intent(in) :: do_capsnow ! true => DO snow capping
+ real(r8) , intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+ real(r8) , intent(in) :: h2osno ! snow water (col) [mm H2O]
+ real(r8) , intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg m-2]
+ real(r8) , intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice content (col,lyr) [kg m-2]
+
+ real(r8) , intent(in) :: t_soisno ( maxsnl+1:1 ) ! soil and snow temperature (col,lyr) [K]
+ real(r8) , intent(in) :: t_grnd ! ground temperature (col) [K]
+ real(r8) , intent(in) :: forc_t ! Atmospheric temperature (col) [K]
+
+ real(r8) , intent(inout) :: snw_rds ( maxsnl+1:0 ) ! effective grain radius (col,lyr) [microns, m-6]
+
+ ! DAI, Dec. 29, 2022
+ !-----------------------------------------------------------------------
+ !
+ ! !LOCAL VARIABLES:
+ integer :: snl_top ! top snow layer index [idx]
+ integer :: snl_btm ! bottom snow layer index [idx]
+ integer :: i ! layer index [idx]
+ ! integer :: c_idx ! column index [idx]
+ integer :: fc ! snow column filter index [idx]
+ integer :: T_idx ! snow aging lookup table temperature index [idx]
+ integer :: Tgrd_idx ! snow aging lookup table temperature gradient index [idx]
+ integer :: rhos_idx ! snow aging lookup table snow density index [idx]
+ real(r8) :: t_snotop ! temperature at upper layer boundary [K]
+ real(r8) :: t_snobtm ! temperature at lower layer boundary [K]
+ real(r8) :: dTdz(maxsnl:0) ! snow temperature gradient (col,lyr) [K m-1]
+ real(r8) :: bst_tau ! snow aging parameter retrieved from lookup table [hour]
+ real(r8) :: bst_kappa ! snow aging parameter retrieved from lookup table [unitless]
+ real(r8) :: bst_drdt0 ! snow aging parameter retrieved from lookup table [um hr-1]
+ real(r8) :: dr ! incremental change in snow effective radius [um]
+ real(r8) :: dr_wet ! incremental change in snow effective radius from wet growth [um]
+ real(r8) :: dr_fresh ! difference between fresh snow r_e and current r_e [um]
+ real(r8) :: newsnow ! fresh snowfall [kg m-2]
+ real(r8) :: refrzsnow ! re-frozen snow [kg m-2]
+ real(r8) :: frc_newsnow ! fraction of layer mass that is new snow [frc]
+ real(r8) :: frc_oldsnow ! fraction of layer mass that is old snow [frc]
+ real(r8) :: frc_refrz ! fraction of layer mass that is re-frozen snow [frc]
+ real(r8) :: frc_liq ! fraction of layer mass that is liquid water[frc]
+ real(r8) :: rhos ! snow density [kg m-3]
+ real(r8) :: h2osno_lyr ! liquid + solid H2O in snow layer [kg m-2]
+ real(r8) :: cdz(maxsnl+1:0) ! column average layer thickness [m]
+ real(r8) :: snw_rds_fresh ! fresh snow radius [microns]
+
+ real(r8) :: snot_top ! temperature in top snow layer (col) [K]
+ real(r8) :: dTdz_top ! temperature gradient in top layer (col) [K m-1]
+ real(r8) :: snw_rds_top ! effective grain radius, top layer (col) [microns, m-6]
+ real(r8) :: sno_liq_top ! liquid water fraction (mass) in top snow layer (col) [frc]
+
+ !--------------------------------------------------------------------------!
+
+ ! associate( &
+ ! snl => col_pp%snl , & ! Input: [integer (:) ] negative number of snow layers (col) [nbr]
+ ! dz => col_pp%dz , & ! Input: [real(r8) (:,:) ] layer thickness (col,lyr) [m]
+
+ ! qflx_snow_grnd => col_wf%qflx_snow_grnd , & ! Input: [real(r8) (:) ] snow on ground after interception (col) [kg m-2 s-1]
+ ! qflx_snwcp_ice => col_wf%qflx_snwcp_ice , & ! Input: [real(r8) (:) ] excess precipitation due to snow capping [kg m-2 s-1]
+ ! qflx_snofrz_lyr => col_wf%qflx_snofrz_lyr , & ! Input: [real(r8) (:,:) ] snow freezing rate (col,lyr) [kg m-2 s-1]
+
+ ! do_capsnow => col_ws%do_capsnow , & ! Input: [logical (:) ] true => DO snow capping
+ ! frac_sno => col_ws%frac_sno_eff , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1)
+ ! h2osno => col_ws%h2osno , & ! Input: [real(r8) (:) ] snow water (col) [mm H2O]
+ ! h2osno_liq => col_ws%h2osno_liq , & ! Input: [real(r8) (:,:) ] liquid water content (col,lyr) [kg m-2]
+ ! h2osno_ice => col_ws%h2osno_ice , & ! Input: [real(r8) (:,:) ] ice content (col,lyr) [kg m-2]
+ ! snw_rds => col_ws%snw_rds , & ! Output: [real(r8) (:,:) ] effective grain radius (col,lyr) [microns, m-6]
+ ! snw_rds_top => col_ws%snw_rds_top , & ! Output: [real(r8) (:) ] effective grain radius, top layer (col) [microns, m-6]
+ ! sno_liq_top => col_ws%sno_liq_top , & ! Output: [real(r8) (:) ] liquid water fraction (mass) in top snow layer (col) [frc]
+
+ ! t_soisno => col_es%t_soisno , & ! Input: [real(r8) (:,:) ] soil and snow temperature (col,lyr) [K]
+ ! t_grnd => col_es%t_grnd , & ! Input: [real(r8) (:) ] ground temperature (col) [K]
+ ! snot_top => col_es%snot_top , & ! Output: [real(r8) (:) ] temperature in top snow layer (col) [K]
+ ! dTdz_top => col_es%dTdz_top & ! Output: [real(r8) (:) ] temperature gradient in top layer (col) [K m-1]
+ ! )
+
+
+ IF (snl < 0 .and. h2osno > 0._r8) THEN
+
+ snl_btm = 0
+ snl_top = snl + 1
+
+ cdz(snl_top:snl_btm)=frac_sno*dz(snl_top:snl_btm)
+
+ ! loop over snow layers
+ DO i = snl_top, snl_btm, 1
+ !
+ !********** 1. DRY SNOW AGING ***********
+ !
+ h2osno_lyr = h2osno_liq(i) + h2osno_ice(i)
+
+ ! temperature gradient
+ IF (i == snl_top) THEN
+ ! top layer
+ t_snotop = t_soisno(snl_top)
+ t_snobtm = (t_soisno(i+1)*dz(i) &
+ + t_soisno(i)*dz(i+1)) &
+ / (dz(i)+dz(i+1))
+ ELSE
+ t_snotop = (t_soisno(i-1)*dz(i) &
+ + t_soisno(i)*dz(i-1)) &
+ / (dz(i)+dz(i-1))
+ t_snobtm = (t_soisno(i+1)*dz(i) &
+ + t_soisno(i)*dz(i+1)) &
+ / (dz(i)+dz(i+1))
+ ENDIF
+
+ dTdz(i) = abs((t_snotop - t_snobtm) / cdz(i))
+
+ ! snow density
+ rhos = (h2osno_liq(i)+h2osno_ice(i)) / cdz(i)
+
+ ! make sure rhos doesn't drop below 50 (see rhos_idx below)
+ rhos=max(50._r8,rhos)
+
+ ! best-fit table indecies
+ T_idx = nint((t_soisno(i)-223) / 5) + 1
+ Tgrd_idx = nint(dTdz(i) / 10) + 1
+ rhos_idx = nint((rhos-50) / 50) + 1
+
+ ! boundary check:
+ IF (T_idx < idx_T_min) THEN
+ T_idx = idx_T_min
+ ENDIF
+ IF (T_idx > idx_T_max) THEN
+ T_idx = idx_T_max
+ ENDIF
+ IF (Tgrd_idx < idx_Tgrd_min) THEN
+ Tgrd_idx = idx_Tgrd_min
+ ENDIF
+ IF (Tgrd_idx > idx_Tgrd_max) THEN
+ Tgrd_idx = idx_Tgrd_max
+ ENDIF
+ IF (rhos_idx < idx_rhos_min) THEN
+ rhos_idx = idx_rhos_min
+ ENDIF
+ IF (rhos_idx > idx_rhos_max) THEN
+ rhos_idx = idx_rhos_max
+ ENDIF
+
+ ! best-fit parameters
+ bst_tau = snowage_tau(rhos_idx,Tgrd_idx,T_idx)
+ bst_kappa = snowage_kappa(rhos_idx,Tgrd_idx,T_idx)
+ bst_drdt0 = snowage_drdt0(rhos_idx,Tgrd_idx,T_idx)
+
+ ! change in snow effective radius, using best-fit parameters
+ ! added checks suggested by mgf. --HW 10/15/2015
+ dr_fresh = snw_rds(i)-snw_rds_min
+
+#ifdef MODAL_AER
+ IF ( abs(dr_fresh) < 1.0e-8_r8 ) THEN
+ dr_fresh = 0.0_r8
+ ELSEIF ( dr_fresh < 0.0_r8 ) THEN
+ IF (p_is_root) THEN
+ write(iulog,*) "dr_fresh = ", dr_fresh, snw_rds(i), snw_rds_min
+ CALL abort
+ ENDIF
+ ENDIF
+
+ dr = (bst_drdt0*(bst_tau/(dr_fresh+bst_tau))**(1._r8/bst_kappa)) * (dtime/3600._r8)
+#else
+ dr = (bst_drdt0*(bst_tau/(dr_fresh+bst_tau))**(1/bst_kappa)) * (dtime/3600)
+#endif
+ !
+ !********** 2. WET SNOW AGING ***********
+ !
+ ! We are assuming wet and dry evolution occur simultaneously, and
+ ! the contributions from both can be summed.
+ ! This is justified by setting the linear offset constant C1_liq_Brun89 to zero [Brun, 1989]
+
+ ! liquid water faction
+ frc_liq = min(0.1_r8, (h2osno_liq(i) / (h2osno_liq(i)+h2osno_ice(i))))
+
+ !dr_wet = 1E6_r8*(dtime*(C1_liq_Brun89 + C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*(snw_rds(i)/1E6)**(2)))
+ !simplified, units of microns:
+ dr_wet = 1E18_r8*(dtime*(C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*snw_rds(i)**(2)))
+
+ dr = dr + dr_wet
+
+ !
+ !********** 3. SNOWAGE SCALING (TURNED OFF BY DEFAULT) *************
+ !
+ ! Multiply rate of change of effective radius by some constant, xdrdt
+ IF (flg_snoage_scl) THEN
+ dr = dr*xdrdt
+ ENDIF
+
+ !
+ !********** 4. INCREMENT EFFECTIVE RADIUS, ACCOUNTING FOR: ***********
+ ! DRY AGING
+ ! WET AGING
+ ! FRESH SNOW
+ ! RE-FREEZING
+ !
+ ! new snowfall [kg/m2]
+ IF (do_capsnow .and. .not. use_extrasnowlayers) THEN
+ newsnow = max(0._r8, (qflx_snwcp_ice*dtime))
+ ELSE
+ newsnow = max(0._r8, (qflx_snow_grnd*dtime))
+ ENDIF
+
+ ! snow that has re-frozen [kg/m2]
+ refrzsnow = max(0._r8, (qflx_snofrz_lyr(i)*dtime))
+
+ ! fraction of layer mass that is re-frozen
+ frc_refrz = refrzsnow / h2osno_lyr
+
+ ! fraction of layer mass that is new snow
+ IF (i == snl_top) THEN
+ frc_newsnow = newsnow / h2osno_lyr
+ ELSE
+ frc_newsnow = 0._r8
+ ENDIF
+
+ IF ((frc_refrz + frc_newsnow) > 1._r8) THEN
+ frc_refrz = frc_refrz / (frc_refrz + frc_newsnow)
+ frc_newsnow = 1._r8 - frc_refrz
+ frc_oldsnow = 0._r8
+ ELSE
+ frc_oldsnow = 1._r8 - frc_refrz - frc_newsnow
+ ENDIF
+
+ ! temperature dependent fresh grain size
+ snw_rds_fresh = FreshSnowRadius (forc_t)
+
+ ! mass-weighted mean of fresh snow, old snow, and re-frozen snow effective radius
+ snw_rds(i) = (snw_rds(i)+dr)*frc_oldsnow + snw_rds_fresh*frc_newsnow + snw_rds_refrz*frc_refrz
+ !
+ !********** 5. CHECK BOUNDARIES ***********
+ !
+ ! boundary check
+ IF (snw_rds(i) < snw_rds_min) THEN
+ snw_rds(i) = snw_rds_min
+ ENDIF
+
+ IF (snw_rds(i) > snw_rds_max) THEN
+ snw_rds(i) = snw_rds_max
+ ENDIF
+
+ ! set top layer variables for history files
+ IF (i == snl_top) THEN
+ snot_top = t_soisno(i)
+ dTdz_top = dTdz(i)
+ snw_rds_top = snw_rds(i)
+ sno_liq_top = h2osno_liq(i) / (h2osno_liq(i)+h2osno_ice(i))
+ ENDIF
+
+ ENDDO
+ ENDIF ! ENDIF (snl < 0 )
+
+ ! Special CASE: snow on ground, but not enough to have defined a snow layer:
+ ! set snw_rds to fresh snow grain size:
+
+ IF (snl >= 0 .and. h2osno > 0._r8) THEN
+ snw_rds(0) = snw_rds_min
+ ENDIF
+
+ ! END associate
+
+ END SUBROUTINE SnowAge_grain
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowOptics_init( fsnowoptics )
+
+ USE MOD_NetCDFSerial
+
+ IMPLICIT NONE
+
+ character(len=256), intent(in) :: fsnowoptics ! snow optical properties file name
+ character(len= 32) :: subname = 'SnowOptics_init' ! SUBROUTINE name
+ integer :: atm_type_index ! index for atmospheric type
+
+ logical :: readvar ! determine IF variable was read from NetCDF file
+ !-----------------------------------------------------------------------
+
+ readvar = .true.
+
+ atm_type_index = atm_type_default
+ ! Define atmospheric type
+ IF (trim(snicar_atm_type) == 'default') THEN
+ atm_type_index = atm_type_default
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_winter') THEN
+ atm_type_index = atm_type_mid_latitude_winter
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_summer') THEN
+ atm_type_index = atm_type_mid_latitude_summer
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_winter') THEN
+ atm_type_index = atm_type_sub_Arctic_winter
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_summer') THEN
+ atm_type_index = atm_type_sub_Arctic_summer
+ ELSEIF (trim(snicar_atm_type) == 'summit_Greenland') THEN
+ atm_type_index = atm_type_summit_Greenland
+ ELSEIF (trim(snicar_atm_type) == 'high_mountain') THEN
+ atm_type_index = atm_type_high_mountain
+ ELSE
+ IF (p_is_root) THEN
+ write(iulog,*) "snicar_atm_type = ", snicar_atm_type
+ CALL abort
+ ENDIF
+ ENDIF
+
+ !
+ ! Open optics file:
+ IF (p_is_root) THEN
+ write(iulog,*) 'Attempting to read snow optical properties .....'
+ write(iulog,*) subname,trim(fsnowoptics)
+ ENDIF
+
+ ! direct-beam snow Mie parameters:
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ice_drc', ss_alb_snw_drc)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ice_drc', asm_prm_snw_drc)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ice_drc', ext_cff_mss_snw_drc)
+
+ ! diffuse snow Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ice_dfs', ss_alb_snw_dfs)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ice_dfs', asm_prm_snw_dfs)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ice_dfs', ext_cff_mss_snw_dfs)
+
+ !!! Direct and diffuse flux under different atmospheric conditions
+ ! Direct-beam incident spectral flux:
+ CALL ncio_read_bcast_serial (fsnowoptics, 'flx_wgt_dir', flx_wgt_dir)
+
+ ! Diffuse incident spectral flux:
+ CALL ncio_read_bcast_serial (fsnowoptics, 'flx_wgt_dif', flx_wgt_dif)
+
+#ifdef MODAL_AER
+ ! size-dependent BC parameters and BC enhancement factors
+ IF (p_is_root) THEN
+ write(iulog,*) 'Attempting to read optical properties for within-ice BC (modal aerosol treatment) ...'
+ ENDIF
+ !
+ ! BC species 1 Mie parameters
+ !
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bc_mam', ss_alb_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bc_mam', asm_prm_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bc_mam', ext_cff_mss_bc1)
+ !
+ ! BC species 2 Mie parameters (identical, before enhancement factors applied)
+ !
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bc_mam', ss_alb_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bc_mam', asm_prm_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bc_mam', ext_cff_mss_bc2)
+ !
+ ! size-dependent BC absorption enhancement factors for within-ice BC
+ CALL ncio_read_bcast_serial (fsnowoptics, 'bcint_enh_mam', bcenh)
+ !
+#else
+ ! bulk aerosol treatment
+ ! BC species 1 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bcphil', ss_alb_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bcphil', asm_prm_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bcphil', ext_cff_mss_bc1)
+
+ !
+ ! BC species 2 Mie parameters
+ !
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bcphob', ss_alb_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bcphob', asm_prm_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bcphob', ext_cff_mss_bc2)
+ !
+#endif
+ !
+ ! OC species 1 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ocphil', ss_alb_oc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ocphil', asm_prm_oc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ocphil', ext_cff_mss_oc1)
+ !
+ ! OC species 2 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ocphob', ss_alb_oc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ocphob', asm_prm_oc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ocphob', ext_cff_mss_oc2)
+ !
+ ! dust species 1 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust01', ss_alb_dst1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust01', asm_prm_dst1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust01', ext_cff_mss_dst1)
+ !
+ ! dust species 2 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust02', ss_alb_dst2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust02', asm_prm_dst2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust02', ext_cff_mss_dst2)
+ !
+ ! dust species 3 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust03', ss_alb_dst3)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust03', asm_prm_dst3)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust03', ext_cff_mss_dst3)
+ !
+ ! dust species 4 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust04', ss_alb_dst4)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust04', asm_prm_dst4)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust04', ext_cff_mss_dst4)
+ !
+ !
+
+ IF (p_is_root) THEN
+ write(iulog,*) 'Successfully read snow optical properties'
+ ENDIF
+
+
+ ! print some diagnostics:
+ IF (p_is_root) THEN
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for direct-beam ice, rds=100um: ', &
+ ss_alb_snw_drc(71,1), ss_alb_snw_drc(71,2), ss_alb_snw_drc(71,3), &
+ ss_alb_snw_drc(71,4), ss_alb_snw_drc(71,5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for diffuse ice, rds=100um: ', &
+ ss_alb_snw_dfs(71,1), ss_alb_snw_dfs(71,2), ss_alb_snw_dfs(71,3), &
+ ss_alb_snw_dfs(71,4), ss_alb_snw_dfs(71,5)
+ IF (DO_SNO_OC) THEN
+ write (iulog,*) 'SNICAR: Including OC aerosols from snow radiative transfer calculations'
+ ELSE
+ write (iulog,*) 'SNICAR: Excluding OC aerosols from snow radiative transfer calculations'
+ ENDIF
+ ENDIF
+ !
+#ifdef MODAL_AER
+ IF (p_is_root) THEN
+ ! unique dimensionality for modal aerosol optical properties
+ write (iulog,*) 'SNICAR: Subset of Mie single scatter albedos for BC: ', &
+ ss_alb_bc1(1,1), ss_alb_bc1(1,2), ss_alb_bc1(2,1), ss_alb_bc1(5,1), ss_alb_bc1(1,10), ss_alb_bc2(1,10)
+ write (iulog,*) 'SNICAR: Subset of Mie mass extinction coefficients for BC: ', &
+ ext_cff_mss_bc2(1,1), ext_cff_mss_bc2(1,2), ext_cff_mss_bc2(2,1), ext_cff_mss_bc2(5,1), ext_cff_mss_bc2(1,10),&
+ ext_cff_mss_bc1(1,10)
+ write (iulog,*) 'SNICAR: Subset of Mie asymmetry parameters for BC: ', &
+ asm_prm_bc1(1,1), asm_prm_bc1(1,2), asm_prm_bc1(2,1), asm_prm_bc1(5,1), asm_prm_bc1(1,10), asm_prm_bc2(1,10)
+ write (iulog,*) 'SNICAR: Subset of BC absorption enhancement factors: ', &
+ bcenh(1,1,1), bcenh(1,2,1), bcenh(1,1,2), bcenh(2,1,1), bcenh(5,10,1), bcenh(5,1,8), bcenh(5,10,8)
+ ENDIF
+#else
+ IF (p_is_root) THEN
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic BC: ', &
+ ss_alb_bc1(1), ss_alb_bc1(2), ss_alb_bc1(3), ss_alb_bc1(4), ss_alb_bc1(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic BC: ', &
+ ss_alb_bc2(1), ss_alb_bc2(2), ss_alb_bc2(3), ss_alb_bc2(4), ss_alb_bc2(5)
+ ENDIF
+#endif
+
+ IF (p_is_root) THEN
+ IF (DO_SNO_OC) THEN
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic OC: ', &
+ ss_alb_oc1(1), ss_alb_oc1(2), ss_alb_oc1(3), ss_alb_oc1(4), ss_alb_oc1(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic OC: ', &
+ ss_alb_oc2(1), ss_alb_oc2(2), ss_alb_oc2(3), ss_alb_oc2(4), ss_alb_oc2(5)
+ ENDIF
+
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 1: ', &
+ ss_alb_dst1(1), ss_alb_dst1(2), ss_alb_dst1(3), ss_alb_dst1(4), ss_alb_dst1(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 2: ', &
+ ss_alb_dst2(1), ss_alb_dst2(2), ss_alb_dst2(3), ss_alb_dst2(4), ss_alb_dst2(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 3: ', &
+ ss_alb_dst3(1), ss_alb_dst3(2), ss_alb_dst3(3), ss_alb_dst3(4), ss_alb_dst3(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 4: ', &
+ ss_alb_dst4(1), ss_alb_dst4(2), ss_alb_dst4(3), ss_alb_dst4(4), ss_alb_dst4(5)
+ write(iulog,*)
+ ENDIF
+
+ END SUBROUTINE SnowOptics_init
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowAge_init( fsnowaging )
+
+ USE MOD_NetCDFSerial
+
+ IMPLICIT NONE
+
+ character(len=256), intent(in) :: fsnowaging ! snow aging parameters file name
+ character(len= 32) :: subname = 'SnowAge_init' ! SUBROUTINE name
+ !
+ ! Open snow aging (effective radius evolution) file:
+ IF (p_is_root) THEN
+ write(iulog,*) 'Attempting to read snow aging parameters .....'
+ write(iulog,*) subname,trim(fsnowaging)
+ ENDIF
+
+ !
+ ! SNOW aging parameters
+ !
+ CALL ncio_read_bcast_serial (fsnowaging, 'tau', snowage_tau)
+ CALL ncio_read_bcast_serial (fsnowaging, 'kappa', snowage_kappa)
+ CALL ncio_read_bcast_serial (fsnowaging, 'drdsdt0', snowage_drdt0)
+
+ !
+ IF (p_is_root) THEN
+ write(iulog,*) 'Successfully read snow aging properties'
+ ENDIF
+ !
+ ! print some diagnostics:
+ IF (p_is_root) THEN
+ write (iulog,*) 'SNICAR: snowage tau for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_tau(3,11,9)
+ write (iulog,*) 'SNICAR: snowage kappa for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_kappa(3,11,9)
+ write (iulog,*) 'SNICAR: snowage dr/dt_0 for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_drdt0(3,11,9)
+ ENDIF
+
+ END SUBROUTINE SnowAge_init
+ !-----------------------------------------------------------------------
+
+
+ real(r8) FUNCTION FreshSnowRadius (forc_t)
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Returns fresh snow grain radius, which is linearly dependent on temperature.
+! This is implemented to remedy an outstanding bias that SNICAR has in initial
+! grain size. See e.g. Sandells et al, 2017 for a discussion (10.5194/tc-11-229-2017).
+!
+! Yang et al. (2017), 10.1016/j.jqsrt.2016.03.033
+! discusses grain size observations, which suggest a temperature dependence.
+!
+! !REVISION HISTORY:
+! Author: Leo VanKampenhout
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Aerosol, only: fresh_snw_rds_max
+
+ ! !ARGUMENTS:
+ real(r8), intent(in) :: forc_t ! atmospheric temperature (Kelvin)
+ !
+ ! !LOCAL VARIABLES:
+ !-----------------------------------------------------------------------
+ real(r8), parameter :: tmin = tfrz - 30._r8 ! start of linear ramp
+ real(r8), parameter :: tmax = tfrz - 0._r8 ! END of linear ramp
+ real(r8), parameter :: gs_min = snw_rds_min ! minimum value
+ real(r8) :: gs_max ! maximum value
+
+ IF ( fresh_snw_rds_max <= snw_rds_min )THEN
+ FreshSnowRadius = snw_rds_min
+ ELSE
+ gs_max = fresh_snw_rds_max
+
+ IF (forc_t < tmin) THEN
+ FreshSnowRadius = gs_min
+ ELSEIF (forc_t > tmax) THEN
+ FreshSnowRadius = gs_max
+ ELSE
+ FreshSnowRadius = (tmax-forc_t)/(tmax-tmin)*gs_min + &
+ (forc_t-tmin)/(tmax-tmin)*gs_max
+ ENDIF
+ ENDIF
+
+ END FUNCTION FreshSnowRadius
+
+END MODULE MOD_SnowSnicar
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowSnicar_HiRes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowSnicar_HiRes.F90
new file mode 100644
index 0000000000..10dad47088
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SnowSnicar_HiRes.F90
@@ -0,0 +1,2994 @@
+#include
+
+!-------------------------------------------------------------------------
+MODULE MOD_SnowSnicar_HiRes
+
+ !-----------------------------------------------------------------------
+ ! DESCRIPTION:
+ ! Calculate albedo of snow containing impurities
+ ! and the evolution of snow effective radius
+ !
+ ! ORIGINAL:
+ ! 1) The Community Land Model version 5.0 (CLM5.0)
+ ! 2) Energy Exascale Earth System Model version 2.0 (E3SM v2.0) Land Model (ELM v2.0)
+ !
+ ! REFERENCES:
+ ! 1) Flanner et al, 2021, SNICAR-ADv3: a community tool for modeling spectral snow albedo.
+ ! Geosci. Model Dev., 14, 7673–7704, https://doi.org/10.5194/gmd-14-7673-2021
+ ! 2) Hao et al., 2023, Improving snow albedo modeling in the E3SM land model (version 2.0)
+ ! and assessing its impacts on snow and surface fluxes over the Tibetan Plateau.
+ ! Geosci. Model Dev., 16, 75–94, https://doi.org/10.5194/gmd-16-75-2023
+ !
+ ! REVISIONS:
+ ! Yongjiu Dai, and Hua Yuan, December, 2022 : ASSEMBLING and FITTING
+ !
+ ! !USES:
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: maxsnl
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+! SAVE
+ real(R8),parameter :: SHR_CONST_PI = 3.14159265358979323846_R8
+ real(R8),parameter :: SHR_CONST_RHOICE = 0.917e3_R8 ! density of ice (kg/m^3)
+
+ integer, parameter :: iulog = 6 ! "stdout" log file unit number, default is 6
+ integer, parameter :: numrad = 5 ! number of solar radiation bands: vis, nir
+
+!--------------------------------------------------------------------
+! DAI, Dec. 29, 2022
+! Temporay setting
+
+ logical, parameter :: use_extrasnowlayers = .false.
+ character(len=256), parameter :: snow_shape = 'sphere' ! (=1), 'spheroid'(=2), 'hexagonal_plate'(=3), 'koch_snowflake'(=4)
+ logical, parameter :: use_dust_snow_internal_mixing = .false.
+ character(len=256), parameter :: snicar_atm_type = 'default' ! Atmospheric profile used to obtain surface-incident spectral flux distribution
+ ! and subsequent broadband albedo
+ ! = 'mid-latitude_winter' ! => 1
+ ! = 'mid-latitude_summer' ! => 2
+ ! = 'sub-Arctic_winter' ! => 3
+ ! = 'sub-Arctic_summer' ! => 4
+ ! = 'summit_Greenland' ! => 5 (sub-Arctic summer, surface pressure of 796hPa)
+ ! = 'high_mountain' ! => 6 (summer, surface pressure of 556 hPa)
+!DAI, Dec. 29, 2022
+!-----------------------------------------------------------------------
+
+ ! !PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: SNICAR_RT ! Snow albedo and vertically-resolved solar absorption
+ PUBLIC :: SNICAR_AD_RT ! Snow albedo and vertically-resolved solar absorption by adding-doubling solution
+ ! To USE this subtroutine, set use_snicar_ad = true
+ PUBLIC :: SnowAge_grain ! Snow effective grain size evolution
+ PUBLIC :: SnowAge_init ! Initial read in of snow-aging file
+ PUBLIC :: SnowOptics_init ! Initial read in of snow-optics file
+ !
+ ! !PUBLIC DATA MEMBERS:
+ integer, PUBLIC, parameter :: sno_nbr_aer = 8 ! number of aerosol species in snowpack
+ ! (indices described above) [nbr]
+ logical, PUBLIC, parameter :: DO_SNO_OC = .false. ! parameter to include organic carbon (OC)
+ ! in snowpack radiative calculations
+ logical, PUBLIC, parameter :: DO_SNO_AER = .true. ! parameter to include aerosols in snowpack radiative calculations
+ ! !PRIVATE DATA MEMBERS:
+ integer, parameter :: numrad_snw = 5 ! number of spectral bands used in snow model [nbr]
+ integer, parameter :: nir_bnd_bgn = 2 ! first band index in near-IR spectrum [idx]
+ integer, parameter :: nir_bnd_end = 5 ! ending near-IR band index [idx]
+ integer, parameter :: idx_Mie_snw_mx = 1471 ! number of effective radius indices used in Mie lookup table [idx]
+ integer, parameter :: idx_T_max = 11 ! maxiumum temperature index used in aging lookup table [idx]
+ integer, parameter :: idx_T_min = 1 ! minimum temperature index used in aging lookup table [idx]
+ integer, parameter :: idx_Tgrd_max = 31 ! maxiumum temperature gradient index used in aging lookup table [idx]
+ integer, parameter :: idx_Tgrd_min = 1 ! minimum temperature gradient index used in aging lookup table [idx]
+ integer, parameter :: idx_rhos_max = 8 ! maxiumum snow density index used in aging lookup table [idx]
+ integer, parameter :: idx_rhos_min = 1 ! minimum snow density index used in aging lookup table [idx]
+
+#ifdef MODAL_AER
+ ! NOTE: right now the macro 'MODAL_AER' is not defined anywhere, i.e.,
+ ! the below (modal aerosol scheme) is not available and can not be
+ ! active either. It depends on the specific input aerosol deposition
+ ! data which is suitable for modal scheme. [06/15/2023, Hua Yuan]
+ !mgf++
+ integer, parameter :: idx_bc_nclrds_min = 1 ! minimum index for BC particle size in optics lookup table
+ integer, parameter :: idx_bc_nclrds_max = 10 ! maximum index for BC particle size in optics lookup table
+ integer, parameter :: idx_bcint_icerds_min = 1 ! minimum index for snow grain size in optics lookup table for within-ice BC
+ integer, parameter :: idx_bcint_icerds_max = 8 ! maximum index for snow grain size in optics lookup table for within-ice BC
+ !mgf--
+#endif
+
+ integer, parameter :: snw_rds_max_tbl = 1500 ! maximum effective radius defined in Mie lookup table [microns]
+ integer, parameter :: snw_rds_min_tbl = 30 ! minimium effective radius defined in Mie lookup table [microns]
+ real(r8), parameter :: snw_rds_max = 1500._r8 ! maximum allowed snow effective radius [microns]
+ real(r8), parameter :: snw_rds_min = 54.526_r8 ! minimum allowed snow effective radius (also "fresh snow" value) [microns
+ real(r8), parameter :: snw_rds_refrz = 1000._r8 ! effective radius of re-frozen snow [microns]
+ real(r8), parameter :: min_snw = 1.0E-30_r8 ! minimum snow mass required for SNICAR RT calculation [kg m-2]
+ !real(r8), parameter :: C1_liq_Brun89 = 1.28E-17_r8 ! constant for liquid water grain growth [m3 s-1],
+ ! from Brun89
+ real(r8), parameter :: C1_liq_Brun89 = 0._r8 ! constant for liquid water grain growth [m3 s-1],
+ ! from Brun89: zeroed to accomodate dry snow aging
+ real(r8), parameter :: C2_liq_Brun89 = 4.22E-13_r8 ! constant for liquid water grain growth [m3 s-1],
+ ! from Brun89: corrected for LWC in units of percent
+
+ real(r8), parameter :: tim_cns_bc_rmv = 2.2E-8_r8 ! time constant for removal of BC in snow on sea-ice
+ ! [s-1] (50% mass removal/year)
+ real(r8), parameter :: tim_cns_oc_rmv = 2.2E-8_r8 ! time constant for removal of OC in snow on sea-ice
+ ! [s-1] (50% mass removal/year)
+ real(r8), parameter :: tim_cns_dst_rmv = 2.2E-8_r8 ! time constant for removal of dust in snow on sea-ice
+ ! [s-1] (50% mass removal/year)
+ !$acc declare copyin(C1_liq_Brun89, C2_liq_Brun89, &
+ !$acc tim_cns_bc_rmv, tim_cns_oc_rmv, tim_cns_dst_rmv)
+
+ ! scaling of the snow aging rate (tuning option):
+ logical :: flg_snoage_scl = .false. ! flag for scaling the snow aging rate by some arbitrary factor
+ real(r8), parameter :: xdrdt = 1.0_r8 ! arbitrary factor applied to snow aging rate
+ ! snow and aerosol Mie parameters:
+ ! (arrays declared here, but are set in iniTimeConst)
+ ! (idx_Mie_snw_mx is number of snow radii with defined parameters (i.e. from 30um to 1500um))
+
+ ! direct-beam weighted ice optical properties
+ real(r8), allocatable :: ss_alb_snw_drc (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: asm_prm_snw_drc (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_snw_drc(:,:) ! (idx_Mie_snw_mx,numrad_snw);
+
+ ! diffuse radiation weighted ice optical properties
+ real(r8), allocatable :: ss_alb_snw_dfs (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: asm_prm_snw_dfs (:,:) ! (idx_Mie_snw_mx,numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_snw_dfs(:,:) ! (idx_Mie_snw_mx,numrad_snw);
+
+ ! direct & diffuse flux
+ real(r8), allocatable :: flx_wgt_dir (:,:,:) ! (6, 90, numrad_snw) ! direct flux, six atmospheric types, 0-89 SZA
+ real(r8), allocatable :: flx_wgt_dif (:,:) ! (6, numrad_snw) ! diffuse flux, six atmospheric types
+
+ ! snow grain shape
+ integer, parameter :: snow_shape_sphere = 1
+ integer, parameter :: snow_shape_spheroid = 2
+ integer, parameter :: snow_shape_hexagonal_plate = 3
+ integer, parameter :: snow_shape_koch_snowflake = 4
+
+ ! atmospheric condition for SNICAR-AD
+ integer, parameter :: atm_type_default = 0
+ integer, parameter :: atm_type_mid_latitude_winter = 1
+ integer, parameter :: atm_type_mid_latitude_summer = 2
+ integer, parameter :: atm_type_sub_Arctic_winter = 3
+ integer, parameter :: atm_type_sub_Arctic_summer = 4
+ integer, parameter :: atm_type_summit_Greenland = 5
+ integer, parameter :: atm_type_high_mountain = 6
+
+#ifdef MODAL_AER
+ !mgf++
+ ! Size-dependent BC optical properties. Currently a fixed BC size is
+ ! assumed, but this framework enables optical properties to be
+ ! assigned based on the BC effective radius, should this be
+ ! implemented in the future.
+ !
+ ! within-ice BC (i.e., BC that was deposited within hydrometeors)
+ real(r8), allocatable :: ss_alb_bc1 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: asm_prm_bc1 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: ext_cff_mss_bc1(:,:) ! (numrad_snw,idx_bc_nclrds_max);
+
+ ! external BC
+ real(r8), allocatable :: ss_alb_bc2 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: asm_prm_bc2 (:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ real(r8), allocatable :: ext_cff_mss_bc2(:,:) ! (numrad_snw,idx_bc_nclrds_max);
+ !mgf--
+#else
+ ! hydrophiliic BC
+ real(r8), allocatable :: ss_alb_bc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_bc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_bc1(:) ! (numrad_snw);
+
+ ! hydrophobic BC
+ real(r8), allocatable :: ss_alb_bc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_bc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_bc2(:) ! (numrad_snw);
+#endif
+
+ ! hydrophobic OC
+ real(r8), allocatable :: ss_alb_oc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_oc1 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_oc1(:) ! (numrad_snw);
+
+ ! hydrophilic OC
+ real(r8), allocatable :: ss_alb_oc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_oc2 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_oc2(:) ! (numrad_snw);
+
+ ! dust species 1:
+ real(r8), allocatable :: ss_alb_dst1 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst1 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst1(:) ! (numrad_snw);
+
+ ! dust species 2:
+ real(r8), allocatable :: ss_alb_dst2 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst2 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst2(:) ! (numrad_snw);
+
+ ! dust species 3:
+ real(r8), allocatable :: ss_alb_dst3 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst3 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst3(:) ! (numrad_snw);
+
+ ! dust species 4:
+ real(r8), allocatable :: ss_alb_dst4 (:) ! (numrad_snw);
+ real(r8), allocatable :: asm_prm_dst4 (:) ! (numrad_snw);
+ real(r8), allocatable :: ext_cff_mss_dst4(:) ! (numrad_snw);
+
+#ifdef MODAL_AER
+ ! Absorption enhancement factors for within-ice BC
+ real(r8), allocatable :: bcenh (:,:,:) ! (numrad_snw,idx_bc_nclrds_max,idx_bcint_icerds_max);
+#endif
+
+ ! best-fit parameters for snow aging defined over:
+ ! 11 temperatures from 225 to 273 K
+ ! 31 temperature gradients from 0 to 300 K/m
+ ! 8 snow densities from 0 to 350 kg/m3
+ ! (arrays declared here, but are set in iniTimeConst)
+ !
+ real(r8), allocatable :: snowage_tau (:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) ! snow aging parameter retrieved from lookup table [hour]
+ real(r8), allocatable :: snowage_kappa (:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) ! snow aging parameter retrieved from lookup table [unitless]
+ real(r8), allocatable :: snowage_drdt0 (:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) ! snow aging parameter retrieved from lookup table [um hr-1]
+
+ !
+ ! !REVISION HISTORY:
+ ! Created by Mark Flanner
+ !-----------------------------------------------------------------------
+
+CONTAINS
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE SNICAR_RT (flg_snw_ice, flg_slr_in, &
+ coszen, snl, h2osno, frac_sno, &
+ h2osno_liq, h2osno_ice, snw_rds, &
+ mss_cnc_aer_in, albsfc, albout, flx_abs)
+ !
+ ! !DESCRIPTION:
+ ! Determine reflectance of, and vertically-resolved solar absorption in,
+ ! snow with impurities.
+ !
+ ! Original references on physical models of snow reflectance include:
+ ! Wiscombe and Warren [1980] and Warren and Wiscombe [1980],
+ ! Journal of Atmospheric Sciences, 37,
+ !
+ ! The multi-layer solution for multiple-scattering used here is from:
+ ! Toon et al. [1989], Rapid calculation of radiative heating rates
+ ! and photodissociation rates in inhomogeneous multiple scattering atmospheres,
+ ! J. Geophys. Res., 94, D13, 16287-16301
+ !
+ ! The implementation of the SNICAR model in CLM/CSIM is described in:
+ ! Flanner, M., C. Zender, J. Randerson, and P. Rasch [2007],
+ ! Present-day climate forcing and response from black carbon in snow,
+ ! J. Geophys. Res., 112, D11202, doi: 10.1029/2006JD008003
+ !
+ ! !USES:
+ !
+ ! !ARGUMENTS:
+
+ IMPLICIT NONE
+
+ integer , intent(in) :: flg_snw_ice ! flag: =1 when called from CLM, =2 when called from CSIM
+ integer , intent(in) :: flg_slr_in ! flag: =1 for direct-beam incident flux,=2 for diffuse incident flux
+ real(r8) , intent(in) :: coszen ! cosine of solar zenith angle for next time step (col) [unitless]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8) , intent(in) :: h2osno ! snow liquid water equivalent (col) [kg/m2]
+ real(r8) , intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+
+ real(r8) , intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg/m2]
+ real(r8) , intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice content (col,lyr) [kg/m2]
+ integer , intent(in) :: snw_rds ( maxsnl+1:0 ) ! snow effective radius (col,lyr) [microns, m^-6]
+ real(r8) , intent(in) :: mss_cnc_aer_in ( maxsnl+1:0 , 1:sno_nbr_aer ) ! mass concentration of all aerosol species (col,lyr,aer) [kg/kg]
+ real(r8) , intent(in) :: albsfc ( 1:numrad ) ! albedo of surface underlying snow (col,bnd) [frc]
+ real(r8) , intent(out) :: albout ( 1:numrad ) ! snow albedo, averaged into 2 bands (=0 IF no sun or no snow) (col,bnd) [frc]
+ real(r8) , intent(out) :: flx_abs ( maxsnl+1:1 , 1:numrad ) ! absorbed flux in each layer per unit flux incident (col, lyr, bnd)
+ !
+ ! !LOCAL VARIABLES:
+ !
+ ! variables for snow radiative transfer calculations
+
+ ! Local variables representing single-column values of arrays:
+ integer :: snl_lcl ! negative number of snow layers [nbr]
+ integer :: snw_rds_lcl(maxsnl+1:0) ! snow effective radius [m^-6]
+ real(r8):: flx_slrd_lcl(1:numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1)
+ real(r8):: flx_slri_lcl(1:numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1)
+ real(r8):: mss_cnc_aer_lcl(maxsnl+1:0,1:sno_nbr_aer) ! aerosol mass concentration (lyr,aer_nbr) [kg/kg]
+ real(r8):: h2osno_lcl ! total column snow mass [kg/m2]
+ real(r8):: h2osno_liq_lcl(maxsnl+1:0) ! liquid water mass [kg/m2]
+ real(r8):: h2osno_ice_lcl(maxsnl+1:0) ! ice mass [kg/m2]
+ real(r8):: albsfc_lcl(1:numrad_snw) ! albedo of underlying surface [frc]
+ real(r8):: ss_alb_snw_lcl(maxsnl+1:0) ! single-scatter albedo of ice grains (lyr) [frc]
+ real(r8):: asm_prm_snw_lcl(maxsnl+1:0) ! asymmetry parameter of ice grains (lyr) [frc]
+ real(r8):: ext_cff_mss_snw_lcl(maxsnl+1:0) ! mass extinction coefficient of ice grains (lyr) [m2/kg]
+ real(r8):: ss_alb_aer_lcl(sno_nbr_aer) ! single-scatter albedo of aerosol species (aer_nbr) [frc]
+ real(r8):: asm_prm_aer_lcl(sno_nbr_aer) ! asymmetry parameter of aerosol species (aer_nbr) [frc]
+ real(r8):: ext_cff_mss_aer_lcl(sno_nbr_aer) ! mass extinction coefficient of aerosol species (aer_nbr) [m2/kg]
+
+#ifdef MODAL_AER
+ !mgf++
+ real(r8) :: rds_bcint_lcl(maxsnl+1:0) ! effective radius of within-ice BC [nm]
+ real(r8) :: rds_bcext_lcl(maxsnl+1:0) ! effective radius of external BC [nm]
+ !mgf--
+#endif
+
+
+ ! Other local variables
+ integer :: APRX_TYP ! two-stream approximation type
+ ! (1=Eddington, 2=Quadrature, 3=Hemispheric Mean) [nbr]
+ integer :: DELTA ! flag to USE Delta approximation (Joseph, 1976)
+ ! (1= USE, 0= don't USE)
+ real(r8):: flx_wgt(1:numrad_snw) ! weights applied to spectral bands,
+ ! specific to direct and diffuse cases (bnd) [frc]
+
+ integer :: flg_nosnl ! flag: =1 IF there is snow, but zero snow layers,
+ ! =0 IF at least 1 snow layer [flg]
+ integer :: trip ! flag: =1 to redo RT calculation IF result is unrealistic
+ integer :: flg_dover ! defines conditions for RT redo (explained below)
+
+ real(r8):: albedo ! temporary snow albedo [frc]
+ real(r8):: flx_sum ! temporary summation variable for NIR weighting
+ real(r8):: albout_lcl(numrad_snw) ! snow albedo by band [frc]
+ real(r8):: flx_abs_lcl(maxsnl+1:1,numrad_snw) ! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc]
+
+ real(r8):: L_snw(maxsnl+1:0) ! h2o mass (liquid+solid) in snow layer (lyr) [kg/m2]
+ real(r8):: tau_snw(maxsnl+1:0) ! snow optical depth (lyr) [unitless]
+ real(r8):: L_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol mass in snow layer (lyr,nbr_aer) [kg/m2]
+ real(r8):: tau_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol optical depth (lyr,nbr_aer) [unitless]
+ real(r8):: tau_sum ! cumulative (snow+aerosol) optical depth [unitless]
+ real(r8):: tau_elm(maxsnl+1:0) ! column optical depth from layer bottom to snowpack top (lyr) [unitless]
+ real(r8):: omega_sum ! temporary summation of single-scatter albedo of all aerosols [frc]
+ real(r8):: g_sum ! temporary summation of asymmetry parameter of all aerosols [frc]
+
+ real(r8):: tau(maxsnl+1:0) ! weighted optical depth of snow+aerosol layer (lyr) [unitless]
+ real(r8):: omega(maxsnl+1:0) ! weighted single-scatter albedo of snow+aerosol layer (lyr) [frc]
+ real(r8):: g(maxsnl+1:0) ! weighted asymmetry parameter of snow+aerosol layer (lyr) [frc]
+ real(r8):: tau_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) optical depth of snow+aerosol layer
+ ! (lyr) [unitless]
+ real(r8):: omega_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) SSA of snow+aerosol layer (lyr) [frc]
+ real(r8):: g_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) asymmetry paramater of snow+aerosol layer
+ ! (lyr) [frc]
+
+ integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= numrad_snw) [idx]
+ integer :: rds_idx ! snow effective radius index for retrieving
+ ! Mie parameters from lookup table [idx]
+ integer :: snl_btm ! index of bottom snow layer (0) [idx]
+ integer :: snl_top ! index of top snow layer (-4 to 0) [idx]
+ integer :: fc ! column filter index
+ integer :: i ! layer index [idx]
+ integer :: j ! aerosol number index [idx]
+ integer :: n ! tridiagonal matrix index [idx]
+ integer :: m ! secondary layer index [idx]
+ integer :: nint_snw_rds_min ! nearest integer value of snw_rds_min
+
+ real(r8):: F_direct(maxsnl+1:0) ! direct-beam radiation at bottom of layer interface (lyr) [W/m^2]
+ real(r8):: F_net(maxsnl+1:0) ! net radiative flux at bottom of layer interface (lyr) [W/m^2]
+ real(r8):: F_abs(maxsnl+1:0) ! net absorbed radiative energy (lyr) [W/m^2]
+ real(r8):: F_abs_sum ! total absorbed energy in column [W/m^2]
+ real(r8):: F_sfc_pls ! upward radiative flux at snowpack top [W/m^2]
+ real(r8):: F_btm_net ! net flux at bottom of snowpack [W/m^2]
+ real(r8):: F_sfc_net ! net flux at top of snowpack [W/m^2]
+ real(r8):: energy_sum ! sum of all energy terms; should be 0.0 [W/m^2]
+ real(r8):: F_direct_btm ! direct-beam radiation at bottom of snowpack [W/m^2]
+ real(r8):: mu_not ! cosine of solar zenith angle (used locally) [frc]
+
+ integer :: err_idx ! counter for number of times through error loop [nbr]
+ real(r8):: pi ! 3.1415...
+
+ ! intermediate variables for radiative transfer approximation:
+ real(r8):: gamma1(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: gamma2(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: gamma3(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: gamma4(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: lambda(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: GAMMA(maxsnl+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: mu_one ! two-stream coefficient from Toon et al. (lyr) [unitless]
+ real(r8):: e1(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: e2(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: e3(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: e4(maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (lyr)
+ real(r8):: C_pls_btm(maxsnl+1:0) ! intermediate variable: upward flux at bottom interface (lyr) [W/m2]
+ real(r8):: C_mns_btm(maxsnl+1:0) ! intermediate variable: downward flux at bottom interface (lyr) [W/m2]
+ real(r8):: C_pls_top(maxsnl+1:0) ! intermediate variable: upward flux at top interface (lyr) [W/m2]
+ real(r8):: C_mns_top(maxsnl+1:0) ! intermediate variable: downward flux at top interface (lyr) [W/m2]
+ real(r8):: A(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: B(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: D(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: E(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: AS(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: DS(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: X(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ real(r8):: Y(2*maxsnl+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr)
+ !-----------------------------------------------------------------------
+#ifdef MODAL_AER
+ !mgf++
+ integer :: idx_bcint_icerds ! index of ice effective radius for optical properties lookup table
+ integer :: idx_bcint_nclrds ! index of within-ice BC effective radius for optical properties lookup table
+ integer :: idx_bcext_nclrds ! index of external BC effective radius for optical properties lookup table
+ real(r8):: enh_fct ! extinction/absorption enhancement factor for within-ice BC
+ real(r8):: tmp1 ! temporary variable
+ !mgf--
+#endif
+
+ ! Enforce expected array sizes
+
+ ! associate(&
+ ! snl => col_pp%snl , & ! Input: [integer (:)] negative number of snow layers (col) [nbr]
+ ! h2osno => col_ws%h2osno , & ! Input: [real(r8) (:)] snow liquid water equivalent (col) [kg/m2]
+ ! frac_sno => col_ws%frac_sno_eff & ! Input: [real(r8) (:)] fraction of ground covered by snow (0 to 1)
+ ! )
+
+ ! Define constants
+ pi = SHR_CONST_PI
+ nint_snw_rds_min = nint(snw_rds_min)
+
+ ! always USE Delta approximation for snow
+ DELTA = 1
+
+ ! (when called from CSIM, there is only one column)
+
+ ! Zero absorbed radiative fluxes:
+ DO i=maxsnl+1,1,1
+ flx_abs_lcl(:,:) = 0._r8
+ flx_abs(i,:) = 0._r8
+ ENDDO
+
+ ! set snow/ice mass to be used for RT:
+ IF (flg_snw_ice == 1) THEN
+ h2osno_lcl = h2osno
+ ELSE
+ h2osno_lcl = h2osno_ice(0)
+ ENDIF
+
+ ! Qualifier for computing snow RT:
+ ! 1) sunlight from atmosphere model
+ ! 2) minimum amount of snow on ground.
+ ! Otherwise, set snow albedo to zero
+ IF ((coszen > 0._r8) .and. (h2osno_lcl > min_snw)) THEN
+
+ ! Set variables specific to CLM
+ IF (flg_snw_ice == 1) THEN
+ ! If there is snow, but zero snow layers, we must create a layer locally.
+ ! This layer is presumed to have the fresh snow effective radius.
+ IF (snl > -1) THEN
+ flg_nosnl = 1
+ snl_lcl = -1
+ h2osno_ice_lcl(0) = h2osno_lcl
+ h2osno_liq_lcl(0) = 0._r8
+ snw_rds_lcl(0) = nint_snw_rds_min
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = snl
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ ENDIF
+
+ snl_btm = 0
+ snl_top = snl_lcl+1
+
+ ! Set variables specific to CSIM
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = -1
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ snl_btm = 0
+ snl_top = 0
+ ENDIF
+
+#ifdef MODAL_AER
+ !mgf++
+ !
+ ! Assume fixed BC effective radii of 100nm. This is close to
+ ! the effective radius of 95nm (number median radius of
+ ! 40nm) assumed for freshly-emitted BC in MAM. Future
+ ! implementations may prognose the BC effective radius in
+ ! snow.
+ rds_bcint_lcl(:) = 100._r8
+ rds_bcext_lcl(:) = 100._r8
+ !mgf--
+#endif
+
+ ! Set local aerosol array
+ DO j=1,sno_nbr_aer
+ mss_cnc_aer_lcl(:,j) = mss_cnc_aer_in(:,j)
+ ENDDO
+
+
+ ! Set spectral underlying surface albedos to their corresponding VIS or NIR albedos
+ albsfc_lcl(1) = albsfc(1)
+ albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(2)
+
+
+ ! Error check for snow grain size:
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ DO i=snl_top,snl_btm,1
+ IF ((snw_rds_lcl(i) < snw_rds_min_tbl) .or. (snw_rds_lcl(i) > snw_rds_max_tbl)) THEN
+ write (iulog,*) "SNICAR ERROR: snow grain radius of out of bounds."
+ write (iulog,*) "flg_snw_ice= ", flg_snw_ice
+ write (iulog,*) " level: ", i, " snl(c)= ", snl_lcl
+ write (iulog,*) "h2osno(c)= ", h2osno_lcl
+ CALL abort
+ ENDIF
+ ENDDO
+ ENDIF
+#endif
+
+ ! Incident flux weighting parameters
+ ! - sum of all VIS bands must equal 1
+ ! - sum of all NIR bands must equal 1
+ !
+ ! Spectral bands (5-band CASE)
+ ! Band 1: 0.3-0.7um (VIS)
+ ! Band 2: 0.7-1.0um (NIR)
+ ! Band 3: 1.0-1.2um (NIR)
+ ! Band 4: 1.2-1.5um (NIR)
+ ! Band 5: 1.5-5.0um (NIR)
+ !
+ ! The following weights are appropriate for surface-incident flux in a mid-latitude winter atmosphere
+ !
+ ! 3-band weights
+ IF (numrad_snw==3) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.66628670195247_r8
+ flx_wgt(3) = 0.33371329804753_r8
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.77887652162877_r8
+ flx_wgt(3) = 0.22112347837123_r8
+ ENDIF
+
+ ! 5-band weights
+ ELSEIF(numrad_snw==5) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.49352158521175_r8
+ flx_wgt(3) = 0.18099494230665_r8
+ flx_wgt(4) = 0.12094898498813_r8
+ flx_wgt(5) = 0.20453448749347_r8
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.58581507618433_r8
+ flx_wgt(3) = 0.20156903770812_r8
+ flx_wgt(4) = 0.10917889346386_r8
+ flx_wgt(5) = 0.10343699264369_r8
+ ENDIF
+ ENDIF
+
+ ! Loop over snow spectral bands
+ DO bnd_idx = 1,numrad_snw
+
+ mu_not = coszen ! must set here, because of error handling
+ flg_dover = 1 ! default is to redo
+ err_idx = 0 ! number of times through loop
+
+ DO WHILE (flg_dover > 0)
+
+ ! DEFAULT APPROXIMATIONS:
+ ! VIS: Delta-Eddington
+ ! NIR (all): Delta-Hemispheric Mean
+ ! WARNING: DO NOT USE DELTA-EDDINGTON FOR NIR DIFFUSE - this sometimes results in negative albedo
+ !
+ ! ERROR CONDITIONS:
+ ! Conditions which cause "trip", resulting in redo of RT approximation:
+ ! 1. negative absorbed flux
+ ! 2. total absorbed flux greater than incident flux
+ ! 3. negative albedo
+ ! NOTE: These errors have only been encountered in spectral bands 4 and 5
+ !
+ ! ERROR HANDLING
+ ! 1st error (flg_dover=2): switch approximation (Edd->HM or HM->Edd)
+ ! 2nd error (flg_dover=3): change zenith angle by 0.02 (this happens about 1 in 10^6 cases)
+ ! 3rd error (flg_dover=4): switch approximation with new zenith
+ ! Subsequent errors: repeatedly change zenith and approximations...
+
+ IF (bnd_idx == 1) THEN
+ IF (flg_dover == 2) THEN
+ APRX_TYP = 3
+ ELSEIF (flg_dover == 3) THEN
+ APRX_TYP = 1
+ IF (coszen > 0.5_r8) THEN
+ mu_not = mu_not - 0.02_r8
+ ELSE
+ mu_not = mu_not + 0.02_r8
+ ENDIF
+ ELSEIF (flg_dover == 4) THEN
+ APRX_TYP = 3
+ ELSE
+ APRX_TYP = 1
+ ENDIF
+
+ ELSE
+ IF (flg_dover == 2) THEN
+ APRX_TYP = 1
+ ELSEIF (flg_dover == 3) THEN
+ APRX_TYP = 3
+ IF (coszen > 0.5_r8) THEN
+ mu_not = mu_not - 0.02_r8
+ ELSE
+ mu_not = mu_not + 0.02_r8
+ ENDIF
+ ELSEIF (flg_dover == 4) THEN
+ APRX_TYP = 1
+ ELSE
+ APRX_TYP = 3
+ ENDIF
+
+ ENDIF
+
+ ! Set direct or diffuse incident irradiance to 1
+ ! (This has to be within the bnd loop because mu_not is adjusted in rare cases)
+ IF (flg_slr_in == 1) THEN
+ flx_slrd_lcl(bnd_idx) = 1._r8/(mu_not*pi) ! this corresponds to incident irradiance of 1.0
+ flx_slri_lcl(bnd_idx) = 0._r8
+ ELSE
+ flx_slrd_lcl(bnd_idx) = 0._r8
+ flx_slri_lcl(bnd_idx) = 1._r8
+ ENDIF
+
+ ! Pre-emptive error handling: aerosols can reap havoc on these absorptive bands.
+ ! Since extremely high soot concentrations have a negligible effect on these bands, zero them.
+ IF ( (numrad_snw == 5).and.((bnd_idx == 5).or.(bnd_idx == 4)) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ IF ( (numrad_snw == 3).and.(bnd_idx == 3) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ ! Define local Mie parameters based on snow grain size and aerosol species,
+ ! retrieved from a lookup table.
+ IF (flg_slr_in == 1) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (direct radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_drc(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_drc(rds_idx,bnd_idx)
+ ENDDO
+ ELSEIF (flg_slr_in == 2) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (diffuse radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_dfs(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_dfs(rds_idx,bnd_idx)
+ ENDDO
+ ENDIF
+
+!H. Wang
+ ! aerosol species 1 optical properties
+ ! ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ ! asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ! ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ! ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ ! asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ! ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+!H. Wang
+ ! aerosol species 3 optical properties
+ ss_alb_aer_lcl(3) = ss_alb_oc1(bnd_idx)
+ asm_prm_aer_lcl(3) = asm_prm_oc1(bnd_idx)
+ ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc1(bnd_idx)
+
+ ! aerosol species 4 optical properties
+ ss_alb_aer_lcl(4) = ss_alb_oc2(bnd_idx)
+ asm_prm_aer_lcl(4) = asm_prm_oc2(bnd_idx)
+ ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc2(bnd_idx)
+
+ ! aerosol species 5 optical properties
+ ss_alb_aer_lcl(5) = ss_alb_dst1(bnd_idx)
+ asm_prm_aer_lcl(5) = asm_prm_dst1(bnd_idx)
+ ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(bnd_idx)
+
+ ! aerosol species 6 optical properties
+ ss_alb_aer_lcl(6) = ss_alb_dst2(bnd_idx)
+ asm_prm_aer_lcl(6) = asm_prm_dst2(bnd_idx)
+ ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(bnd_idx)
+
+ ! aerosol species 7 optical properties
+ ss_alb_aer_lcl(7) = ss_alb_dst3(bnd_idx)
+ asm_prm_aer_lcl(7) = asm_prm_dst3(bnd_idx)
+ ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(bnd_idx)
+
+ ! aerosol species 8 optical properties
+ ss_alb_aer_lcl(8) = ss_alb_dst4(bnd_idx)
+ asm_prm_aer_lcl(8) = asm_prm_dst4(bnd_idx)
+ ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(bnd_idx)
+
+
+ ! 1. snow and aerosol layer column mass (L_snw, L_aer [kg/m^2])
+ ! 2. optical Depths (tau_snw, tau_aer)
+ ! 3. weighted Mie properties (tau, omega, g)
+
+ ! Weighted Mie parameters of each layer
+ DO i=snl_top,snl_btm,1
+#ifdef MODAL_AER
+ !mgf++ within-ice and external BC optical properties
+ !
+ ! Lookup table indices for BC optical properties,
+ ! dependent on snow grain size and BC particle
+ ! size.
+
+ ! valid for 25 < snw_rds < 1625 um:
+ IF (snw_rds_lcl(i) < 125) THEN
+ tmp1 = snw_rds_lcl(i)/50
+ idx_bcint_icerds = nint(tmp1)
+ ELSEIF (snw_rds_lcl(i) < 175) THEN
+ idx_bcint_icerds = 2
+ ELSE
+ tmp1 = (snw_rds_lcl(i)/250)+2
+ idx_bcint_icerds = nint(tmp1)
+ ENDIF
+
+ ! valid for 25 < bc_rds < 525 nm
+ idx_bcint_nclrds = nint(rds_bcint_lcl(i)/50)
+ idx_bcext_nclrds = nint(rds_bcext_lcl(i)/50)
+
+ ! check bounds:
+ IF (idx_bcint_icerds < idx_bcint_icerds_min) idx_bcint_icerds = idx_bcint_icerds_min
+ IF (idx_bcint_icerds > idx_bcint_icerds_max) idx_bcint_icerds = idx_bcint_icerds_max
+ IF (idx_bcint_nclrds < idx_bc_nclrds_min) idx_bcint_nclrds = idx_bc_nclrds_min
+ IF (idx_bcint_nclrds > idx_bc_nclrds_max) idx_bcint_nclrds = idx_bc_nclrds_max
+ IF (idx_bcext_nclrds < idx_bc_nclrds_min) idx_bcext_nclrds = idx_bc_nclrds_min
+ IF (idx_bcext_nclrds > idx_bc_nclrds_max) idx_bcext_nclrds = idx_bc_nclrds_max
+
+ ! retrieve absorption enhancement factor for within-ice BC
+ enh_fct = bcenh(bnd_idx,idx_bcint_nclrds,idx_bcint_icerds)
+
+ ! get BC optical properties (moved from above)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx,idx_bcint_nclrds)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx,idx_bcint_nclrds)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx,idx_bcint_nclrds)*enh_fct
+
+ ! aerosol species 2 optical properties (external BC)
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx,idx_bcext_nclrds)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx,idx_bcext_nclrds)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx,idx_bcext_nclrds)
+
+#else
+ ! bulk aerosol treatment (BC optical properties independent
+ ! of BC and ice grain size)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+#endif
+ !mgf--
+
+ L_snw(i) = h2osno_ice_lcl(i)+h2osno_liq_lcl(i)
+ tau_snw(i) = L_snw(i)*ext_cff_mss_snw_lcl(i)
+
+ DO j=1,sno_nbr_aer
+ L_aer(i,j) = L_snw(i)*mss_cnc_aer_lcl(i,j)
+ tau_aer(i,j) = L_aer(i,j)*ext_cff_mss_aer_lcl(j)
+ ENDDO
+
+ tau_sum = 0._r8
+ omega_sum = 0._r8
+ g_sum = 0._r8
+
+ DO j=1,sno_nbr_aer
+ tau_sum = tau_sum + tau_aer(i,j)
+ omega_sum = omega_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j))
+ g_sum = g_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j)*asm_prm_aer_lcl(j))
+ ENDDO
+
+ tau(i) = tau_sum + tau_snw(i)
+ omega(i) = (1/tau(i))*(omega_sum+(ss_alb_snw_lcl(i)*tau_snw(i)))
+ g(i) = (1/(tau(i)*omega(i)))*(g_sum+ (asm_prm_snw_lcl(i)*ss_alb_snw_lcl(i)*tau_snw(i)))
+ ENDDO
+
+ ! DELTA transformations, IF requested
+ IF (DELTA == 1) THEN
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)/(1+g(i))
+ omega_star(i) = ((1-(g(i)**2))*omega(i)) / (1-(omega(i)*(g(i)**2)))
+ tau_star(i) = (1-(omega(i)*(g(i)**2)))*tau(i)
+ ENDDO
+ ELSE
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)
+ omega_star(i) = omega(i)
+ tau_star(i) = tau(i)
+ ENDDO
+ ENDIF
+
+ ! Total column optical depth:
+ ! tau_elm(i) = total optical depth above the bottom of layer i
+ tau_elm(snl_top) = 0._r8
+ DO i=snl_top+1,snl_btm,1
+ tau_elm(i) = tau_elm(i-1)+tau_star(i-1)
+ ENDDO
+
+ ! Direct radiation at bottom of snowpack:
+ F_direct_btm = albsfc_lcl(bnd_idx)*mu_not * &
+ exp(-(tau_elm(snl_btm)+tau_star(snl_btm))/mu_not)*pi*flx_slrd_lcl(bnd_idx)
+
+ ! Intermediates
+ ! Gamma values are approximation-specific.
+
+ ! Eddington
+ IF (APRX_TYP==1) THEN
+ DO i=snl_top,snl_btm,1
+ gamma1(i) = (7-(omega_star(i)*(4+(3*g_star(i)))))/4
+ gamma2(i) = -(1-(omega_star(i)*(4-(3*g_star(i)))))/4
+ gamma3(i) = (2-(3*g_star(i)*mu_not))/4
+ gamma4(i) = 1-gamma3(i)
+ mu_one = 0.5
+ ENDDO
+
+ ! Quadrature
+ ELSEIF (APRX_TYP==2) THEN
+ DO i=snl_top,snl_btm,1
+ gamma1(i) = (3**0.5)*(2-(omega_star(i)*(1+g_star(i))))/2
+ gamma2(i) = omega_star(i)*(3**0.5)*(1-g_star(i))/2
+ gamma3(i) = (1-((3**0.5)*g_star(i)*mu_not))/2
+ gamma4(i) = 1-gamma3(i)
+ mu_one = 1/(3**0.5)
+ ENDDO
+
+ ! Hemispheric Mean
+ ELSEIF (APRX_TYP==3) THEN
+ DO i=snl_top,snl_btm,1
+ gamma1(i) = 2 - (omega_star(i)*(1+g_star(i)))
+ gamma2(i) = omega_star(i)*(1-g_star(i))
+ gamma3(i) = (1-((3**0.5)*g_star(i)*mu_not))/2
+ gamma4(i) = 1-gamma3(i)
+ mu_one = 0.5
+ ENDDO
+ ENDIF
+
+ ! Intermediates for tri-diagonal solution
+ DO i=snl_top,snl_btm,1
+ lambda(i) = sqrt(abs((gamma1(i)**2) - (gamma2(i)**2)))
+ GAMMA(i) = gamma2(i)/(gamma1(i)+lambda(i))
+
+ e1(i) = 1+(GAMMA(i)*exp(-lambda(i)*tau_star(i)))
+ e2(i) = 1-(GAMMA(i)*exp(-lambda(i)*tau_star(i)))
+ e3(i) = GAMMA(i) + exp(-lambda(i)*tau_star(i))
+ e4(i) = GAMMA(i) - exp(-lambda(i)*tau_star(i))
+ ENDDO !ENDDO over snow layers
+
+ ! Intermediates for tri-diagonal solution
+ DO i=snl_top,snl_btm,1
+ IF (flg_slr_in == 1) THEN
+
+ C_pls_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-(tau_elm(i)+tau_star(i))/mu_not)* &
+ (((gamma1(i)-(1/mu_not))*gamma3(i))+ &
+ (gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ C_mns_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-(tau_elm(i)+tau_star(i))/mu_not)* &
+ (((gamma1(i)+(1/mu_not))*gamma4(i))+ &
+ (gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ C_pls_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-tau_elm(i)/mu_not)*(((gamma1(i)-(1/mu_not))* &
+ gamma3(i))+(gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ C_mns_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* &
+ exp(-tau_elm(i)/mu_not)*(((gamma1(i)+(1/mu_not))* &
+ gamma4(i))+(gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2)))
+
+ ELSE
+ C_pls_btm(i) = 0._r8
+ C_mns_btm(i) = 0._r8
+ C_pls_top(i) = 0._r8
+ C_mns_top(i) = 0._r8
+ ENDIF
+ ENDDO
+
+ ! Coefficients for tridiaganol matrix solution
+ DO i=2*snl_lcl+1,0,1
+
+ !Boundary values for i=1 and i=2*snl_lcl, specifics for i=odd and i=even
+ IF (i==(2*snl_lcl+1)) THEN
+ A(i) = 0
+ B(i) = e1(snl_top)
+ D(i) = -e2(snl_top)
+ E(i) = flx_slri_lcl(bnd_idx)-C_mns_top(snl_top)
+
+ ELSEIF(i==0) THEN
+ A(i) = e1(snl_btm)-(albsfc_lcl(bnd_idx)*e3(snl_btm))
+ B(i) = e2(snl_btm)-(albsfc_lcl(bnd_idx)*e4(snl_btm))
+ D(i) = 0
+ E(i) = F_direct_btm-C_pls_btm(snl_btm)+(albsfc_lcl(bnd_idx)*C_mns_btm(snl_btm))
+
+ ELSEIF(mod(i,2)==-1) THEN ! If odd and i>=3 (n=1 for i=3)
+ n=floor(i/2.0)
+ A(i) = (e2(n)*e3(n))-(e4(n)*e1(n))
+ B(i) = (e1(n)*e1(n+1))-(e3(n)*e3(n+1))
+ D(i) = (e3(n)*e4(n+1))-(e1(n)*e2(n+1))
+ E(i) = (e3(n)*(C_pls_top(n+1)-C_pls_btm(n)))+(e1(n)*(C_mns_btm(n)-C_mns_top(n+1)))
+
+ ELSEIF(mod(i,2)==0) THEN ! If even and i<=2*snl_lcl
+ n=(i/2)
+ A(i) = (e2(n+1)*e1(n))-(e3(n)*e4(n+1))
+ B(i) = (e2(n)*e2(n+1))-(e4(n)*e4(n+1))
+ D(i) = (e1(n+1)*e4(n+1))-(e2(n+1)*e3(n+1))
+ E(i) = (e2(n+1)*(C_pls_top(n+1)-C_pls_btm(n)))+(e4(n+1)*(C_mns_top(n+1)-C_mns_btm(n)))
+ ENDIF
+ ENDDO
+
+ AS(0) = A(0)/B(0)
+ DS(0) = E(0)/B(0)
+
+ DO i=-1,(2*snl_lcl+1),-1
+ X(i) = 1/(B(i)-(D(i)*AS(i+1)))
+ AS(i) = A(i)*X(i)
+ DS(i) = (E(i)-(D(i)*DS(i+1)))*X(i)
+ ENDDO
+
+ Y(2*snl_lcl+1) = DS(2*snl_lcl+1)
+ DO i=(2*snl_lcl+2),0,1
+ Y(i) = DS(i)-(AS(i)*Y(i-1))
+ ENDDO
+
+ ! Downward direct-beam and net flux (F_net) at the base of each layer:
+ DO i=snl_top,snl_btm,1
+ F_direct(i) = mu_not*pi*flx_slrd_lcl(bnd_idx)*exp(-(tau_elm(i)+tau_star(i))/mu_not)
+ F_net(i) = (Y(2*i-1)*(e1(i)-e3(i))) + (Y(2*i)*(e2(i)-e4(i))) + &
+ C_pls_btm(i) - C_mns_btm(i) - F_direct(i)
+ ENDDO
+
+ ! Upward flux at snowpack top:
+ F_sfc_pls = (Y(2*snl_lcl+1)*(exp(-lambda(snl_top)*tau_star(snl_top))+ &
+ GAMMA(snl_top))) + (Y(2*snl_lcl+2)*(exp(-lambda(snl_top)* &
+ tau_star(snl_top))-GAMMA(snl_top))) + C_pls_top(snl_top)
+
+ ! Net flux at bottom = absorbed radiation by underlying surface:
+ F_btm_net = -F_net(snl_btm)
+
+
+ ! Bulk column albedo and surface net flux
+ albedo = F_sfc_pls/((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx))
+ F_sfc_net = F_sfc_pls - ((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx))
+
+ trip = 0
+ ! Absorbed flux in each layer
+ DO i=snl_top,snl_btm,1
+ IF(i==snl_top) THEN
+ F_abs(i) = F_net(i)-F_sfc_net
+ ELSE
+ F_abs(i) = F_net(i)-F_net(i-1)
+ ENDIF
+ flx_abs_lcl(i,bnd_idx) = F_abs(i)
+
+
+ ! ERROR check: negative absorption
+ IF (flx_abs_lcl(i,bnd_idx) < -0.00001) THEN
+ trip = 1
+ ENDIF
+ ENDDO
+
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+
+ IF (flg_nosnl == 1) THEN
+ ! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer
+ !flx_abs_lcl(:,bnd_idx) = 0._r8
+ !flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net
+
+ ! changed on 20070408:
+ ! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation
+ ! handles the CASE of no snow layers. Then, IF a snow layer is addded between now and
+ ! SurfaceRadiation (called in CanopyHydrology), absorbed energy will be properly distributed.
+ flx_abs_lcl(0,bnd_idx) = F_abs(0)
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+
+ ENDIF
+
+ !Underflow check (we've already tripped the error condition above)
+ DO i=snl_top,1,1
+ IF (flx_abs_lcl(i,bnd_idx) < 0._r8) THEN
+ flx_abs_lcl(i,bnd_idx) = 0._r8
+ ENDIF
+ ENDDO
+
+ F_abs_sum = 0._r8
+ DO i=snl_top,snl_btm,1
+ F_abs_sum = F_abs_sum + F_abs(i)
+ ENDDO
+
+
+ !ERROR check: absorption greater than incident flux
+ ! (should make condition more generic than "1._r8")
+ IF (F_abs_sum > 1._r8) THEN
+ trip = 1
+ ENDIF
+
+ !ERROR check:
+ IF ((albedo < 0._r8).and.(trip==0)) THEN
+ trip = 1
+ ENDIF
+
+ ! Set conditions for redoing RT calculation
+ IF ((trip == 1).and.(flg_dover == 1)) THEN
+ flg_dover = 2
+ ELSEIF ((trip == 1).and.(flg_dover == 2)) THEN
+ flg_dover = 3
+ ELSEIF ((trip == 1).and.(flg_dover == 3)) THEN
+ flg_dover = 4
+ ELSEIF((trip == 1).and.(flg_dover == 4).and.(err_idx < 20)) THEN
+ flg_dover = 3
+ err_idx = err_idx + 1
+ ELSEIF((trip == 1).and.(flg_dover == 4).and.(err_idx >= 20)) THEN
+ flg_dover = 0
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ write(iulog,*) "SNICAR ERROR: FOUND A WORMHOLE. STUCK IN INFINITE LOOP! Called from: ", flg_snw_ice
+ write(iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(0)
+ write(iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
+ write(iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write(iulog,*) "SNICAR STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1)
+ write(iulog,*) "SNICAR STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2)
+ write(iulog,*) "SNICAR STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3)
+ write(iulog,*) "SNICAR STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4)
+ write(iulog,*) "SNICAR STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5)
+ write(iulog,*) "SNICAR STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6)
+ write(iulog,*) "frac_sno: ", frac_sno
+ CALL abort
+ ENDIF
+#endif
+ ELSE
+ flg_dover = 0
+ ENDIF
+
+ ENDDO !ENDDO WHILE (flg_dover > 0)
+
+ ! Energy conservation check:
+ ! Incident direct+diffuse radiation equals (absorbed+bulk_transmitted+bulk_reflected)
+ energy_sum = (mu_not*pi*flx_slrd_lcl(bnd_idx)) + flx_slri_lcl(bnd_idx) - (F_abs_sum + F_btm_net + F_sfc_pls)
+ IF (abs(energy_sum) > 0.00001_r8) THEN
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ write(iulog,*) "SNICAR ERROR: Energy conservation error of : ", energy_sum
+ CALL abort
+ ENDIF
+#endif
+ ENDIF
+
+ albout_lcl(bnd_idx) = albedo
+
+ ! Check that albedo is less than 1
+ IF (albout_lcl(bnd_idx) > 1.0) THEN
+#ifndef _OPENACC
+ IF (p_is_root) THEN
+ write(iulog,*) "SNICAR ERROR: Albedo > 1.0: "
+ write(iulog,*) "SNICAR STATS: bnd_idx= ",bnd_idx
+ write (iulog,*) "SNICAR STATS: albout_lcl(bnd)= ",albout_lcl(bnd_idx), &
+ " albsfc_lcl(bnd_idx)= ",albsfc_lcl(bnd_idx)
+ write (iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write (iulog,*) "SNICAR STATS: coszen= ", coszen, " flg_slr= ", flg_slr_in
+
+ write (iulog,*) "SNICAR STATS: soot(-4)= ", mss_cnc_aer_lcl(-4,1)
+ write (iulog,*) "SNICAR STATS: soot(-3)= ", mss_cnc_aer_lcl(-3,1)
+ write (iulog,*) "SNICAR STATS: soot(-2)= ", mss_cnc_aer_lcl(-2,1)
+ write (iulog,*) "SNICAR STATS: soot(-1)= ", mss_cnc_aer_lcl(-1,1)
+ write (iulog,*) "SNICAR STATS: soot(0)= ", mss_cnc_aer_lcl(0,1)
+
+ write (iulog,*) "SNICAR STATS: L_snw(-4)= ", L_snw(-4)
+ write (iulog,*) "SNICAR STATS: L_snw(-3)= ", L_snw(-3)
+ write (iulog,*) "SNICAR STATS: L_snw(-2)= ", L_snw(-2)
+ write (iulog,*) "SNICAR STATS: L_snw(-1)= ", L_snw(-1)
+ write (iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
+
+ write (iulog,*) "SNICAR STATS: snw_rds(-4)= ", snw_rds(-4)
+ write (iulog,*) "SNICAR STATS: snw_rds(-3)= ", snw_rds(-3)
+ write (iulog,*) "SNICAR STATS: snw_rds(-2)= ", snw_rds(-2)
+ write (iulog,*) "SNICAR STATS: snw_rds(-1)= ", snw_rds(-1)
+ write (iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(0)
+
+ CALL abort
+ ENDIF
+#endif
+ ENDIF
+
+ ENDDO ! loop over wvl bands
+
+
+ ! Weight output NIR albedo appropriately
+ albout(1) = albout_lcl(1)
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx)
+ ENDDO
+ albout(2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+
+ ! Weight output NIR absorbed layer fluxes (flx_abs) appropriately
+ flx_abs(:,1) = flx_abs_lcl(:,1)
+ DO i=snl_top,1,1
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx)
+ ENDDO
+ flx_abs(i,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+ ENDDO
+
+ ! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo
+ ELSEIF ( (coszen > 0._r8) .and. (h2osno_lcl < min_snw) .and. (h2osno_lcl > 0._r8) ) THEN
+ albout(1) = albsfc(1)
+ albout(2) = albsfc(2)
+
+ ! There is either zero snow, or no sun
+ ELSE
+ albout(1) = 0._r8
+ albout(2) = 0._r8
+ ENDIF ! IF column has snow and coszen > 0
+
+ ! END associate
+
+ END SUBROUTINE SNICAR_RT
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SNICAR_AD_RT (flg_snw_ice, flg_slr_in, &
+ coszen, snl, h2osno, frac_sno, &
+ h2osno_liq, h2osno_ice, snw_rds, &
+ mss_cnc_aer_in, albsfc, albout, flx_abs)
+ !
+ ! !DESCRIPTION:
+ ! Determine reflectance of, and vertically-resolved solar absorption in,
+ ! snow with impurities, with updated shortwave scheme
+ !
+ ! The multi-layer solution for multiple-scattering used here is from:
+ ! Briegleb, P. and Light, B.: A Delta-Eddington mutiple scattering
+ ! parameterization for solar radiation in the sea ice component of the
+ ! community climate system model, 2007.
+ !
+ ! The implementation of the SNICAR-AD model in ELM is described in:
+ ! Dang et al., Inter-comparison and improvement of 2-stream shortwave
+ ! radiative transfer models for unified treatment of cryospheric surfaces
+ ! in ESMs, in review, 2019
+ !
+ ! To USE this subtroutine, set use_snicar_ad = true in ELM
+ !
+ ! IF config_use_snicar_ad = true in MPAS-seaice
+ ! Snow on land and snow on sea ice will be treated
+ ! with the same model for their solar radiative properties.
+ !
+ ! The inputs and outputs are the same to SUBROUTINE SNICAR_RT
+ !
+ ! !USES:
+ !
+ ! !ARGUMENTS:
+
+ IMPLICIT NONE
+
+ integer , intent(in) :: flg_snw_ice ! flag: =1 when called from CLM, =2 when called from CSIM
+ integer , intent(in) :: flg_slr_in ! flag: =1 for direct-beam incident flux,=2 for diffuse incident flux
+ real(r8) , intent(in) :: coszen ! cosine of solar zenith angle for next time step (col) [unitless]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8) , intent(in) :: h2osno ! snow liquid water equivalent (col) [kg/m2]
+ real(r8) , intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+
+ real(r8) , intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg/m2]
+ real(r8) , intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice content (col,lyr) [kg/m2]
+ integer , intent(in) :: snw_rds ( maxsnl+1:0 ) ! snow effective radius (col,lyr) [microns, m^-6]
+ real(r8) , intent(in) :: mss_cnc_aer_in ( maxsnl+1:0 , 1:sno_nbr_aer ) ! mass concentration of all aerosol species (col,lyr,aer) [kg/kg]
+ real(r8) , intent(in) :: albsfc ( 1:numrad ) ! albedo of surface underlying snow (col,bnd) [frc]
+ real(r8) , intent(out) :: albout ( 1:numrad ) ! snow albedo, averaged into 2 bands (=0 IF no sun or no snow) (col,bnd) [frc]
+ real(r8) , intent(out) :: flx_abs ( maxsnl+1:1 , 1:numrad ) ! absorbed flux in each layer per unit flux incident (col, lyr, bnd)
+ !
+ ! !LOCAL VARIABLES:
+ !
+ ! variables for snow radiative transfer calculations
+
+ ! Local variables representing single-column values of arrays:
+ integer :: snl_lcl ! negative number of snow layers [nbr]
+ integer :: snw_rds_lcl(maxsnl+1:0) ! snow effective radius [m^-6]
+ real(r8):: flx_slrd_lcl(1:numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1)
+ real(r8):: flx_slri_lcl(1:numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1)
+ real(r8):: mss_cnc_aer_lcl(maxsnl+1:0,1:sno_nbr_aer) ! aerosol mass concentration (lyr,aer_nbr) [kg/kg]
+ real(r8):: h2osno_lcl ! total column snow mass [kg/m2]
+ real(r8):: h2osno_liq_lcl(maxsnl+1:0) ! liquid water mass [kg/m2]
+ real(r8):: h2osno_ice_lcl(maxsnl+1:0) ! ice mass [kg/m2]
+ real(r8):: albsfc_lcl(1:numrad_snw) ! albedo of underlying surface [frc]
+ real(r8):: ss_alb_snw_lcl(maxsnl+1:0) ! single-scatter albedo of ice grains (lyr) [frc]
+ real(r8):: asm_prm_snw_lcl(maxsnl+1:0) ! asymmetry parameter of ice grains (lyr) [frc]
+ real(r8):: ext_cff_mss_snw_lcl(maxsnl+1:0) ! mass extinction coefficient of ice grains (lyr) [m2/kg]
+ real(r8):: ss_alb_aer_lcl(sno_nbr_aer) ! single-scatter albedo of aerosol species (aer_nbr) [frc]
+ real(r8):: asm_prm_aer_lcl(sno_nbr_aer) ! asymmetry parameter of aerosol species (aer_nbr) [frc]
+ real(r8):: ext_cff_mss_aer_lcl(sno_nbr_aer) ! mass extinction coefficient of aerosol species (aer_nbr) [m2/kg]
+
+#ifdef MODAL_AER
+ !mgf++
+ real(r8) :: rds_bcint_lcl(maxsnl+1:0) ! effective radius of within-ice BC [nm]
+ real(r8) :: rds_bcext_lcl(maxsnl+1:0) ! effective radius of external BC [nm]
+ !mgf--
+#endif
+
+
+ ! Other local variables
+ integer :: DELTA ! flag to USE Delta approximation (Joseph, 1976)
+ ! (1= USE, 0= don't USE)
+ real(r8):: flx_wgt(1:numrad_snw) ! weights applied to spectral bands,
+ ! specific to direct and diffuse cases (bnd) [frc]
+ integer :: flg_nosnl ! flag: =1 IF there is snow, but zero snow layers,
+ ! =0 IF at least 1 snow layer [flg]
+ ! integer :: trip ! flag: =1 to redo RT calculation IF result is unrealistic
+ ! integer :: flg_dover ! defines conditions for RT redo (explained below)
+
+ real(r8):: albedo ! temporary snow albedo [frc]
+ real(r8):: flx_sum ! temporary summation variable for NIR weighting
+ real(r8):: albout_lcl(numrad_snw) ! snow albedo by band [frc]
+ real(r8):: flx_abs_lcl(maxsnl+1:1,numrad_snw) ! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc]
+
+ real(r8):: L_snw(maxsnl+1:0) ! h2o mass (liquid+solid) in snow layer (lyr) [kg/m2]
+ real(r8):: tau_snw(maxsnl+1:0) ! snow optical depth (lyr) [unitless]
+ real(r8):: L_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol mass in snow layer (lyr,nbr_aer) [kg/m2]
+ real(r8):: tau_aer(maxsnl+1:0,sno_nbr_aer) ! aerosol optical depth (lyr,nbr_aer) [unitless]
+ real(r8):: tau_sum ! cumulative (snow+aerosol) optical depth [unitless]
+ real(r8):: tau_elm(maxsnl+1:0) ! column optical depth from layer bottom to snowpack top (lyr) [unitless]
+ real(r8):: omega_sum ! temporary summation of single-scatter albedo of all aerosols [frc]
+ real(r8):: g_sum ! temporary summation of asymmetry parameter of all aerosols [frc]
+
+ real(r8):: tau(maxsnl+1:0) ! weighted optical depth of snow+aerosol layer (lyr) [unitless]
+ real(r8):: omega(maxsnl+1:0) ! weighted single-scatter albedo of snow+aerosol layer (lyr) [frc]
+ real(r8):: g(maxsnl+1:0) ! weighted asymmetry parameter of snow+aerosol layer (lyr) [frc]
+ real(r8):: tau_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) optical depth of snow+aerosol layer
+ ! (lyr) [unitless]
+ real(r8):: omega_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) SSA of snow+aerosol layer (lyr) [frc]
+ real(r8):: g_star(maxsnl+1:0) ! transformed (i.e. Delta-Eddington) asymmetry paramater of snow+aerosol layer
+ ! (lyr) [frc]
+
+ ! integer :: c_idx ! column indices [idx]
+ integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= numrad_snw) [idx]
+ integer :: rds_idx ! snow effective radius index for retrieving
+ ! Mie parameters from lookup table [idx]
+ integer :: snl_btm ! index of bottom snow layer (0) [idx]
+ integer :: snl_top ! index of top snow layer (-4 to 0) [idx]
+ integer :: fc ! column filter index
+ integer :: i ! layer index [idx]
+ integer :: j ! aerosol number index [idx]
+ integer :: m ! secondary layer index [idx]
+ integer :: nint_snw_rds_min ! nearest integer value of snw_rds_min
+
+ real(r8):: F_abs(maxsnl+1:0) ! net absorbed radiative energy (lyr) [W/m^2]
+ real(r8):: F_abs_sum ! total absorbed energy in column [W/m^2]
+ real(r8):: F_sfc_pls ! upward radiative flux at snowpack top [W/m^2]
+ real(r8):: F_btm_net ! net flux at bottom of snowpack [W/m^2]
+ real(r8):: energy_sum ! sum of all energy terms; should be 0.0 [W/m^2]
+ real(r8):: mu_not ! cosine of solar zenith angle (used locally) [frc]
+
+ integer :: err_idx ! counter for number of times through error loop [nbr]
+ real(r8):: pi ! 3.1415...
+
+ integer :: snw_shp_lcl(maxsnl+1:0) ! Snow grain shape option:
+ ! 1=sphere; 2=spheroid; 3=hexagonal plate; 4=koch snowflake
+ real(r8):: snw_fs_lcl(maxsnl+1:0) ! Shape factor: ratio of nonspherical grain effective radii to that of equal-volume sphere
+ ! 0=USE recommended default value
+ ! others(0 1 (i.e. nonspherical)
+ real(r8):: snw_ar_lcl(maxsnl+1:0) ! % Aspect ratio: ratio of grain width to length
+ ! 0=USE recommended default value
+ ! others(0.1 1 (i.e. nonspherical)
+ real(r8):: &
+ diam_ice , & ! effective snow grain diameter
+ fs_sphd , & ! shape factor for spheroid
+ fs_hex0 , & ! shape factor for hexagonal plate
+ fs_hex , & ! shape factor for hexagonal plate (reference)
+ fs_koch , & ! shape factor for koch snowflake
+ AR_tmp , & ! aspect ratio for spheroid
+ g_ice_Cg_tmp(7) , & ! temporary for calculation of asymetry factor
+ gg_ice_F07_tmp(7) , & ! temporary for calculation of asymetry factor
+ g_ice_F07 , & ! temporary for calculation of asymetry factor
+ g_ice , & ! asymmetry factor
+ gg_F07_intp , & ! temporary for calculation of asymetry factor (interpolated)
+ g_Cg_intp , & ! temporary for calculation of asymetry factor (interpolated)
+ R_1_omega_tmp , & ! temporary for dust-snow mixing calculation
+ C_dust_total ! dust concentration
+
+ integer :: atm_type_index ! index for atmospheric type
+ integer :: slr_zen ! integer value of solar zenith angle
+
+ ! SNICAR_AD new variables, follow sea-ice shortwave conventions
+ real(r8):: &
+ trndir(maxsnl+1:1) , & ! solar beam down transmission from top
+ trntdr(maxsnl+1:1) , & ! total transmission to direct beam for layers above
+ trndif(maxsnl+1:1) , & ! diffuse transmission to diffuse beam for layers above
+ rupdir(maxsnl+1:1) , & ! reflectivity to direct radiation for layers below
+ rupdif(maxsnl+1:1) , & ! reflectivity to diffuse radiation for layers below
+ rdndif(maxsnl+1:1) , & ! reflectivity to diffuse radiation for layers above
+ dfdir(maxsnl+1:1) , & ! down-up flux at interface due to direct beam at top surface
+ dfdif(maxsnl+1:1) , & ! down-up flux at interface due to diffuse beam at top surface
+ dftmp(maxsnl+1:1) ! temporary variable for down-up flux at interface
+
+ real(r8):: &
+ rdir(maxsnl+1:0) , & ! layer reflectivity to direct radiation
+ rdif_a(maxsnl+1:0) , & ! layer reflectivity to diffuse radiation from above
+ rdif_b(maxsnl+1:0) , & ! layer reflectivity to diffuse radiation from below
+ tdir(maxsnl+1:0) , & ! layer transmission to direct radiation (solar beam + diffuse)
+ tdif_a(maxsnl+1:0) , & ! layer transmission to diffuse radiation from above
+ tdif_b(maxsnl+1:0) , & ! layer transmission to diffuse radiation from below
+ trnlay(maxsnl+1:0) ! solar beam transm for layer (direct beam only)
+
+ real(r8):: &
+ ts , & ! layer delta-scaled extinction optical depth
+ ws , & ! layer delta-scaled single scattering albedo
+ gs , & ! layer delta-scaled asymmetry parameter
+ extins , & ! extinction
+ alp , & ! temporary for alpha
+ gam , & ! temporary for agamm
+ amg , & ! alp - gam
+ apg , & ! alp + gam
+ ue , & ! temporary for u
+ refk , & ! interface multiple scattering
+ refkp1 , & ! interface multiple scattering for k+1
+ refkm1 , & ! interface multiple scattering for k-1
+ tdrrdir , & ! direct tran times layer direct ref
+ tdndif ! total down diffuse = tot tran - direct tran
+
+ real(r8) :: &
+ alpha , & ! term in direct reflectivity and transmissivity
+ agamm , & ! term in direct reflectivity and transmissivity
+ el , & ! term in alpha,agamm,n,u
+ taus , & ! scaled extinction optical depth
+ omgs , & ! scaled single particle scattering albedo
+ asys , & ! scaled asymmetry parameter
+ u , & ! term in diffuse reflectivity and transmissivity
+ n , & ! term in diffuse reflectivity and transmissivity
+ lm , & ! temporary for el
+ mu , & ! cosine solar zenith for either snow or water
+ ne ! temporary for n
+
+ ! perpendicular and parallel relative to plane of incidence and scattering
+ real(r8) :: &
+ R1 , & ! perpendicular polarization reflection amplitude
+ R2 , & ! parallel polarization reflection amplitude
+ T1 , & ! perpendicular polarization transmission amplitude
+ T2 , & ! parallel polarization transmission amplitude
+ Rf_dir_a , & ! fresnel reflection to direct radiation
+ Tf_dir_a , & ! fresnel transmission to direct radiation
+ Rf_dif_a , & ! fresnel reflection to diff radiation from above
+ Rf_dif_b , & ! fresnel reflection to diff radiation from below
+ Tf_dif_a , & ! fresnel transmission to diff radiation from above
+ Tf_dif_b ! fresnel transmission to diff radiation from below
+
+ real(r8) :: &
+ gwt , & ! gaussian weight
+ swt , & ! sum of weights
+ trn , & ! layer transmission
+ rdr , & ! rdir for gaussian integration
+ tdr , & ! tdir for gaussian integration
+ smr , & ! accumulator for rdif gaussian integration
+ smt , & ! accumulator for tdif gaussian integration
+ exp_min ! minimum exponential value
+
+ integer :: &
+ ng , & ! gaussian integration index
+ snl_btm_itf , & ! index of bottom snow layer interfaces (1) [idx]
+ ngmax = 8 ! gaussian integration index
+
+ ! Gaussian integration angle and coefficients
+ real(r8) :: difgauspt(1:8) , difgauswt(1:8)
+
+ ! constants used in algorithm
+ real(r8) :: &
+ c0 = 0.0_r8 , &
+ c1 = 1.0_r8 , &
+ c3 = 3.0_r8 , &
+ c4 = 4.0_r8 , &
+ c6 = 6.0_r8 , &
+ cp01 = 0.01_r8 , &
+ cp5 = 0.5_r8 , &
+ cp75 = 0.75_r8 , &
+ c1p5 = 1.5_r8 , &
+ trmin = 0.001_r8 , &
+ argmax = 10.0_r8 ! maximum argument of exponential
+
+ ! cconstant coefficients used for SZA parameterization
+ real(r8) :: &
+ sza_a0 = 0.085730_r8 , &
+ sza_a1 = -0.630883_r8 , &
+ sza_a2 = 1.303723_r8 , &
+ sza_b0 = 1.467291_r8 , &
+ sza_b1 = -3.338043_r8 , &
+ sza_b2 = 6.807489_r8 , &
+ puny = 1.0e-11_r8 , &
+ mu_75 = 0.2588_r8 ! cosine of 75 degree
+
+ ! coefficients used for SZA parameterization
+ real(r8) :: &
+ sza_c1 , & ! coefficient, SZA parameteirzation
+ sza_c0 , & ! coefficient, SZA parameterization
+ sza_factor , & ! factor used to adjust NIR direct albedo
+ flx_sza_adjust , & ! direct NIR flux adjustment from sza_factor
+ mu0 ! incident solar zenith angle
+
+ !-----------------------------------------------------------------------
+#ifdef MODAL_AER
+ !mgf++
+ integer :: idx_bcint_icerds ! index of ice effective radius for optical properties lookup table
+ integer :: idx_bcint_nclrds ! index of within-ice BC effective radius for optical properties lookup table
+ integer :: idx_bcext_nclrds ! index of external BC effective radius for optical properties lookup table
+ real(r8):: enh_fct ! extinction/absorption enhancement factor for within-ice BC
+ real(r8):: tmp1 ! temporary variable
+ !mgf--
+#endif
+
+ ! Constants for non-spherical ice particles and dust-snow internal mixing
+ real(r8) :: g_b2(7)
+ real(r8) :: g_b1(7)
+ real(r8) :: g_b0(7)
+ real(r8) :: g_F07_c2(7)
+ real(r8) :: g_F07_c1(7)
+ real(r8) :: g_F07_c0(7)
+ real(r8) :: g_F07_p2(7)
+ real(r8) :: g_F07_p1(7)
+ real(r8) :: g_F07_p0(7)
+ real(r8) :: dust_clear_d0(3)
+ real(r8) :: dust_clear_d1(3)
+ real(r8) :: dust_clear_d2(3)
+ real(r8) :: dust_cloudy_d0(3)
+ real(r8) :: dust_cloudy_d1(3)
+ real(r8) :: dust_cloudy_d2(3)
+
+ !!! factors for considering snow grain shape
+ data g_b0(:) / 9.76029E-01_r8, 9.67798E-01_r8, 1.00111E+00_r8, 1.00224E+00_r8,&
+ 9.64295E-01_r8, 9.97475E-01_r8, 9.97475E-01_r8/
+ data g_b1(:) / 5.21042E-01_r8, 4.96181E-01_r8, 1.83711E-01_r8, 1.37082E-01_r8,&
+ 5.50598E-02_r8, 8.48743E-02_r8, 8.48743E-02_r8/
+ data g_b2(:) /-2.66792E-04_r8, 1.14088E-03_r8, 2.37011E-04_r8,-2.35905E-04_r8,&
+ 8.40449E-04_r8,-4.71484E-04_r8,-4.71484E-04_r8/
+
+ data g_F07_c2(:) / 1.349959E-1_r8, 1.115697E-1_r8, 9.853958E-2_r8, 5.557793E-2_r8,&
+ -1.233493E-1_r8, 0.0_r8, 0.0_r8/
+ data g_F07_c1(:) /-3.987320E-1_r8,-3.723287E-1_r8,-3.924784E-1_r8,-3.259404E-1_r8,&
+ 4.429054E-2_r8,-1.726586E-1_r8,-1.726586E-1_r8/
+ data g_F07_c0(:) / 7.938904E-1_r8, 8.030084E-1_r8, 8.513932E-1_r8, 8.692241E-1_r8,&
+ 7.085850E-1_r8, 6.412701E-1_r8, 6.412701E-1_r8/
+ data g_F07_p2(:) / 3.165543E-3_r8, 2.014810E-3_r8, 1.780838E-3_r8, 6.987734E-4_r8,&
+ -1.882932E-2_r8,-2.277872E-2_r8,-2.277872E-2_r8/
+ data g_F07_p1(:) / 1.140557E-1_r8, 1.143152E-1_r8, 1.143814E-1_r8, 1.071238E-1_r8,&
+ 1.353873E-1_r8, 1.914431E-1_r8, 1.914431E-1_r8/
+ data g_F07_p0(:) / 5.292852E-1_r8, 5.425909E-1_r8, 5.601598E-1_r8, 6.023407E-1_r8,&
+ 6.473899E-1_r8, 4.634944E-1_r8, 4.634944E-1_r8/
+
+ !!! factors for considring dust-snow internal mixing
+ data dust_clear_d0(:) /1.0413E+00_r8,1.0168E+00_r8,1.0189E+00_r8/
+ data dust_clear_d1(:) /1.0016E+00_r8,1.0070E+00_r8,1.0840E+00_r8/
+ data dust_clear_d2(:) /2.4208E-01_r8,1.5300E-03_r8,1.1230E-04_r8/
+
+ data dust_cloudy_d0(:) /1.0388E+00_r8,1.0167E+00_r8,1.0189E+00_r8/
+ data dust_cloudy_d1(:) /1.0015E+00_r8,1.0061E+00_r8,1.0823E+00_r8/
+ data dust_cloudy_d2(:) /2.5973E-01_r8,1.6200E-03_r8,1.1721E-04_r8/
+
+ ! Enforce expected array sizes
+
+ ! associate(&
+ ! snl => col_pp%snl , & ! Input: [integer (:)] negative number of snow layers (col) [nbr]
+ ! h2osno => col_ws%h2osno , & ! Input: [real(r8) (:)] snow liquid water equivalent (col) [kg/m2]
+ ! frac_sno => col_ws%frac_sno_eff & ! Input: [real(r8) (:)] fraction of ground covered by snow (0 to 1)
+ ! )
+
+ ! Define constants
+ pi = SHR_CONST_PI
+ nint_snw_rds_min = nint(snw_rds_min)
+
+ ! always USE Delta approximation for snow
+ DELTA = 1
+
+ !Gaussian integration angle and coefficients for diffuse radiation
+ difgauspt(1:8) & ! gaussian angles (radians)
+ = (/ 0.9894009_r8, 0.9445750_r8, &
+ 0.8656312_r8, 0.7554044_r8, &
+ 0.6178762_r8, 0.4580168_r8, &
+ 0.2816036_r8, 0.0950125_r8/)
+ difgauswt(1:8) & ! gaussian weights
+ = (/ 0.0271525_r8, 0.0622535_r8, &
+ 0.0951585_r8, 0.1246290_r8, &
+ 0.1495960_r8, 0.1691565_r8, &
+ 0.1826034_r8, 0.1894506_r8/)
+
+ snw_shp_lcl(:) = snow_shape_sphere
+ snw_fs_lcl(:) = 0._r8
+ snw_ar_lcl(:) = 0._r8
+ atm_type_index = atm_type_default
+
+ ! Define snow grain shape
+ IF (trim(snow_shape) == 'sphere') THEN
+ snw_shp_lcl(:) = snow_shape_sphere
+ ELSEIF (trim(snow_shape) == 'spheroid') THEN
+ snw_shp_lcl(:) = snow_shape_spheroid
+ ELSEIF (trim(snow_shape) == 'hexagonal_plate') THEN
+ snw_shp_lcl(:) = snow_shape_hexagonal_plate
+ ELSEIF (trim(snow_shape) == 'koch_snowflake') THEN
+ snw_shp_lcl(:) = snow_shape_koch_snowflake
+ ELSE
+ IF (p_is_root) THEN
+ write(iulog,*) "snow_shape = ", snow_shape
+ CALL abort
+ ENDIF
+ ENDIF
+
+ ! Define atmospheric type
+ IF (trim(snicar_atm_type) == 'default') THEN
+ atm_type_index = atm_type_default
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_winter') THEN
+ atm_type_index = atm_type_mid_latitude_winter
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_summer') THEN
+ atm_type_index = atm_type_mid_latitude_summer
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_winter') THEN
+ atm_type_index = atm_type_sub_Arctic_winter
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_summer') THEN
+ atm_type_index = atm_type_sub_Arctic_summer
+ ELSEIF (trim(snicar_atm_type) == 'summit_Greenland') THEN
+ atm_type_index = atm_type_summit_Greenland
+ ELSEIF (trim(snicar_atm_type) == 'high_mountain') THEN
+ atm_type_index = atm_type_high_mountain
+ ELSE
+ IF (p_is_root) THEN
+ write(iulog,*) "snicar_atm_type = ", snicar_atm_type
+ CALL abort
+ ENDIF
+ ENDIF
+
+ ! (when called from CSIM, there is only one column)
+
+ ! Zero absorbed radiative fluxes:
+ DO i=maxsnl+1,1,1
+ flx_abs_lcl(:,:) = 0._r8
+ flx_abs(i,:) = 0._r8
+ ENDDO
+
+ ! set snow/ice mass to be used for RT:
+ IF (flg_snw_ice == 1) THEN
+ h2osno_lcl = h2osno
+ ELSE
+ h2osno_lcl = h2osno_ice(0)
+ ENDIF
+
+ ! Qualifier for computing snow RT:
+ ! 1) sunlight from atmosphere model
+ ! 2) minimum amount of snow on ground.
+ ! Otherwise, set snow albedo to zero
+ IF ((coszen > 0._r8) .and. (h2osno_lcl > min_snw) ) THEN
+
+ ! Set variables specific to ELM
+ IF (flg_snw_ice == 1) THEN
+ ! If there is snow, but zero snow layers, we must create a layer locally.
+ ! This layer is presumed to have the fresh snow effective radius.
+ IF (snl > -1) THEN
+ flg_nosnl = 1
+ snl_lcl = -1
+ h2osno_ice_lcl(0) = h2osno_lcl
+ h2osno_liq_lcl(0) = 0._r8
+ snw_rds_lcl(0) = nint_snw_rds_min
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = snl
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ ENDIF
+
+ snl_btm = 0
+ snl_top = snl_lcl+1
+
+ ! Set variables specific to CSIM
+ ELSE
+ flg_nosnl = 0
+ snl_lcl = -1
+ h2osno_liq_lcl(:) = h2osno_liq(:)
+ h2osno_ice_lcl(:) = h2osno_ice(:)
+ snw_rds_lcl(:) = snw_rds(:)
+ snl_btm = 0
+ snl_top = 0
+ ENDIF ! END IF flg_snw_ice == 1
+
+#ifdef MODAL_AER
+ !mgf++
+ !
+ ! Assume fixed BC effective radii of 100nm. This is close to
+ ! the effective radius of 95nm (number median radius of
+ ! 40nm) assumed for freshly-emitted BC in MAM. Future
+ ! implementations may prognose the BC effective radius in
+ ! snow.
+ rds_bcint_lcl(:) = 100._r8
+ rds_bcext_lcl(:) = 100._r8
+ !mgf--
+#endif
+
+ ! Set local aerosol array
+ DO j=1,sno_nbr_aer
+ mss_cnc_aer_lcl(:,j) = mss_cnc_aer_in(:,j)
+ ENDDO
+
+ ! Set spectral underlying surface albedos to their corresponding VIS or NIR albedos
+ albsfc_lcl(1) = albsfc(1)
+ albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(2)
+
+ ! Error check for snow grain size:
+ IF (p_is_root) THEN
+ DO i=snl_top,snl_btm,1
+ IF ((snw_rds_lcl(i) < snw_rds_min_tbl) .or. (snw_rds_lcl(i) > snw_rds_max_tbl)) THEN
+ write (iulog,*) "SNICAR ERROR: snow grain radius of ", snw_rds_lcl(i), " out of bounds."
+ write (iulog,*) "flg_snw_ice= ", flg_snw_ice
+ write (iulog,*) " level: ", i, " snl(c)= ", snl_lcl
+ write (iulog,*) "h2osno(c)= ", h2osno_lcl
+ CALL abort
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! Incident flux weighting parameters
+ ! - sum of all VIS bands must equal 1
+ ! - sum of all NIR bands must equal 1
+ !
+ ! Spectral bands (5-band CASE)
+ ! Band 1: 0.3-0.7um (VIS)
+ ! Band 2: 0.7-1.0um (NIR)
+ ! Band 3: 1.0-1.2um (NIR)
+ ! Band 4: 1.2-1.5um (NIR)
+ ! Band 5: 1.5-5.0um (NIR)
+ !
+ ! The following weights are appropriate for surface-incident flux in a mid-latitude winter atmosphere
+ !
+ ! 3-band weights
+ IF (numrad_snw==3) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.66628670195247_r8
+ flx_wgt(3) = 0.33371329804753_r8
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.77887652162877_r8
+ flx_wgt(3) = 0.22112347837123_r8
+ ENDIF
+
+ ! 5-band weights
+ ELSEIF(numrad_snw==5) THEN
+ ! Direct:
+ IF (flg_slr_in == 1) THEN
+ IF (atm_type_index == atm_type_default) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.49352158521175_r8
+ flx_wgt(3) = 0.18099494230665_r8
+ flx_wgt(4) = 0.12094898498813_r8
+ flx_wgt(5) = 0.20453448749347_r8
+ ELSE
+ slr_zen = nint(acos(coszen) * 180._r8 / pi)
+ IF (slr_zen>89) THEN
+ slr_zen = 89
+ ENDIF
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = flx_wgt_dir(atm_type_index, slr_zen+1, 2)
+ flx_wgt(3) = flx_wgt_dir(atm_type_index, slr_zen+1, 3)
+ flx_wgt(4) = flx_wgt_dir(atm_type_index, slr_zen+1, 4)
+ flx_wgt(5) = flx_wgt_dir(atm_type_index, slr_zen+1, 5)
+ ENDIF
+
+ ! Diffuse:
+ ELSEIF (flg_slr_in == 2) THEN
+ IF (atm_type_index == atm_type_default) THEN
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = 0.58581507618433_r8
+ flx_wgt(3) = 0.20156903770812_r8
+ flx_wgt(4) = 0.10917889346386_r8
+ flx_wgt(5) = 0.10343699264369_r8
+ ELSE
+ flx_wgt(1) = 1._r8
+ flx_wgt(2) = flx_wgt_dif(atm_type_index, 2)
+ flx_wgt(3) = flx_wgt_dif(atm_type_index, 3)
+ flx_wgt(4) = flx_wgt_dif(atm_type_index, 4)
+ flx_wgt(5) = flx_wgt_dif(atm_type_index, 5)
+ ENDIF
+ ENDIF
+ ENDIF ! END IF numrad_snw
+
+ ! Loop over snow spectral bands
+
+ exp_min = exp(-argmax)
+ DO bnd_idx = 1,numrad_snw
+
+ ! note that we can remove flg_dover since this algorithm is
+ ! stable for mu_not > 0.01
+
+ ! mu_not is cosine solar zenith angle above the fresnel level; make
+ ! sure mu_not is large enough for stable and meaningful radiation
+ ! solution: .01 is like sun just touching horizon with its lower edge
+ ! equivalent to mu0 in sea-ice shortwave model ice_shortwave.F90
+ mu_not = max(coszen, cp01)
+
+
+ ! Set direct or diffuse incident irradiance to 1
+ ! (This has to be within the bnd loop because mu_not is adjusted in rare cases)
+ IF (flg_slr_in == 1) THEN
+ flx_slrd_lcl(bnd_idx) = 1._r8/(mu_not*pi) ! this corresponds to incident irradiance of 1.0
+ flx_slri_lcl(bnd_idx) = 0._r8
+ ELSE
+ flx_slrd_lcl(bnd_idx) = 0._r8
+ flx_slri_lcl(bnd_idx) = 1._r8
+ ENDIF
+
+ ! Pre-emptive error handling: aerosols can reap havoc on these absorptive bands.
+ ! Since extremely high soot concentrations have a negligible effect on these bands, zero them.
+ IF ( (numrad_snw == 5).and.((bnd_idx == 5).or.(bnd_idx == 4)) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ IF ( (numrad_snw == 3).and.(bnd_idx == 3) ) THEN
+ mss_cnc_aer_lcl(:,:) = 0._r8
+ ENDIF
+
+ ! Define local Mie parameters based on snow grain size and aerosol species,
+ ! retrieved from a lookup table.
+ IF (flg_slr_in == 1) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (direct radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_drc(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_drc(rds_idx,bnd_idx)
+ ENDDO
+ ELSEIF (flg_slr_in == 2) THEN
+ DO i=snl_top,snl_btm,1
+ rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1
+ ! snow optical properties (diffuse radiation)
+ ss_alb_snw_lcl(i) = ss_alb_snw_dfs(rds_idx,bnd_idx)
+ asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx)
+ ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_dfs(rds_idx,bnd_idx)
+ ENDDO
+ ENDIF
+
+ ! Calculate the asymetry factors under different snow grain shapes
+ DO i=snl_top,snl_btm,1
+ IF(snw_shp_lcl(i) == snow_shape_spheroid) THEN ! spheroid
+ diam_ice = 2._r8*snw_rds_lcl(i)
+ IF(snw_fs_lcl(i) == 0._r8) THEN
+ fs_sphd = 0.929_r8
+ ELSE
+ fs_sphd = snw_fs_lcl(i)
+ ENDIF
+ fs_hex = 0.788_r8
+ IF(snw_ar_lcl(i) == 0._r8) THEN
+ AR_tmp = 0.5_r8
+ ELSE
+ AR_tmp = snw_ar_lcl(i)
+ ENDIF
+ g_ice_Cg_tmp = g_b0 * ((fs_sphd/fs_hex)**g_b1) * (diam_ice**g_b2)
+ gg_ice_F07_tmp = g_F07_c0 + g_F07_c1 * AR_tmp + g_F07_c2 * (AR_tmp**2)
+ ELSEIF(snw_shp_lcl(i) == snow_shape_hexagonal_plate) THEN ! hexagonal plate
+ diam_ice = 2._r8*snw_rds_lcl(i)
+ IF(snw_fs_lcl(i) == 0._r8) THEN
+ fs_hex0 = 0.788_r8
+ ELSE
+ fs_hex0 = snw_fs_lcl(i)
+ ENDIF
+ fs_hex = 0.788_r8
+ IF(snw_ar_lcl(i) == 0._r8) THEN
+ AR_tmp = 2.5_r8
+ ELSE
+ AR_tmp = snw_ar_lcl(i)
+ ENDIF
+ g_ice_Cg_tmp = g_b0 * ((fs_hex0/fs_hex)**g_b1) * (diam_ice**g_b2)
+ gg_ice_F07_tmp = g_F07_p0 + g_F07_p1 * log(AR_tmp) + g_F07_p2 * ((log(AR_tmp))**2)
+ ELSEIF(snw_shp_lcl(i) == snow_shape_koch_snowflake) THEN ! Koch snowflake
+ diam_ice = 2._r8 * snw_rds_lcl(i) /0.544_r8
+ IF(snw_fs_lcl(i) == 0._r8) THEN
+ fs_koch = 0.712_r8
+ ELSE
+ fs_koch = snw_fs_lcl(i)
+ ENDIF
+ fs_hex = 0.788_r8
+ IF(snw_ar_lcl(i) == 0._r8) THEN
+ AR_tmp = 2.5_r8
+ ELSE
+ AR_tmp = snw_ar_lcl(i)
+ ENDIF
+ g_ice_Cg_tmp = g_b0 * ((fs_koch/fs_hex)**g_b1) * (diam_ice**g_b2)
+ gg_ice_F07_tmp = g_F07_p0 + g_F07_p1 * log(AR_tmp) + g_F07_p2 * ((log(AR_tmp))**2)
+ ENDIF
+
+ ! Linear interpolation for calculating the asymetry factor at band_idx.
+ IF(snw_shp_lcl(i) > 1) THEN
+ IF(bnd_idx == 1) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(2)-g_ice_Cg_tmp(1))/(1.055_r8-0.475_r8)*(0.5_r8-0.475_r8) +g_ice_Cg_tmp(1)
+ gg_F07_intp = (gg_ice_F07_tmp(2)-gg_ice_F07_tmp(1))/(1.055_r8-0.475_r8)*(0.5_r8-0.475_r8)+gg_ice_F07_tmp(1)
+ ELSEIF(bnd_idx == 2) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(2)-g_ice_Cg_tmp(1))/(1.055_r8-0.475_r8)*(0.85_r8-0.475_r8)+g_ice_Cg_tmp(1)
+ gg_F07_intp = (gg_ice_F07_tmp(2)-gg_ice_F07_tmp(1))/(1.055_r8-0.475_r8)*(0.85_r8-0.475_r8)+gg_ice_F07_tmp(1)
+ ELSEIF(bnd_idx == 3) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(3)-g_ice_Cg_tmp(2))/(1.655_r8-1.055_r8)*(1.1_r8-1.055_r8)&
+ +g_ice_Cg_tmp(2)
+ gg_F07_intp = (gg_ice_F07_tmp(3)-gg_ice_F07_tmp(2))/(1.655_r8-1.055_r8)*(1.1_r8-1.055_r8)&
+ +gg_ice_F07_tmp(2)
+ ELSEIF(bnd_idx == 4) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(3)-g_ice_Cg_tmp(2))/(1.655_r8-1.055_r8)*(1.35_r8-1.055_r8)&
+ +g_ice_Cg_tmp(2)
+ gg_F07_intp = (gg_ice_F07_tmp(3)-gg_ice_F07_tmp(2))/(1.655_r8-1.055_r8)*(1.35_r8-1.055_r8)&
+ +gg_ice_F07_tmp(2)
+ ELSEIF(bnd_idx == 5) THEN
+ g_Cg_intp = (g_ice_Cg_tmp(6)-g_ice_Cg_tmp(5))/(3.75_r8-3.0_r8)*(3.25_r8-3.0_r8)&
+ +g_ice_Cg_tmp(5)
+ gg_F07_intp = (gg_ice_F07_tmp(6)-gg_ice_F07_tmp(5))/(3.75_r8-3.0_r8)*(3.25_r8-3.0_r8)&
+ +gg_ice_F07_tmp(5)
+ ENDIF
+ g_ice_F07 = gg_F07_intp + (1._r8 - gg_F07_intp) / ss_alb_snw_lcl(i) / 2._r8
+ g_ice = g_ice_F07 * g_Cg_intp
+ asm_prm_snw_lcl(i) = g_ice
+ ENDIF
+
+ IF(asm_prm_snw_lcl(i) > 0.99_r8) THEN
+ asm_prm_snw_lcl(i) = 0.99_r8
+ ENDIF
+
+ ENDDO
+ !!!-END
+
+ !H. Wang
+ ! aerosol species 1 optical properties
+ ! ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ ! asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ! ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ! ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ ! asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ! ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+ !H. Wang
+ ! aerosol species 3 optical properties
+ ss_alb_aer_lcl(3) = ss_alb_oc1(bnd_idx)
+ asm_prm_aer_lcl(3) = asm_prm_oc1(bnd_idx)
+ ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc1(bnd_idx)
+
+ ! aerosol species 4 optical properties
+ ss_alb_aer_lcl(4) = ss_alb_oc2(bnd_idx)
+ asm_prm_aer_lcl(4) = asm_prm_oc2(bnd_idx)
+ ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc2(bnd_idx)
+
+ ! aerosol species 5 optical properties
+ ss_alb_aer_lcl(5) = ss_alb_dst1(bnd_idx)
+ asm_prm_aer_lcl(5) = asm_prm_dst1(bnd_idx)
+ ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(bnd_idx)
+
+ ! aerosol species 6 optical properties
+ ss_alb_aer_lcl(6) = ss_alb_dst2(bnd_idx)
+ asm_prm_aer_lcl(6) = asm_prm_dst2(bnd_idx)
+ ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(bnd_idx)
+
+ ! aerosol species 7 optical properties
+ ss_alb_aer_lcl(7) = ss_alb_dst3(bnd_idx)
+ asm_prm_aer_lcl(7) = asm_prm_dst3(bnd_idx)
+ ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(bnd_idx)
+
+ ! aerosol species 8 optical properties
+ ss_alb_aer_lcl(8) = ss_alb_dst4(bnd_idx)
+ asm_prm_aer_lcl(8) = asm_prm_dst4(bnd_idx)
+ ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(bnd_idx)
+
+
+ ! 1. snow and aerosol layer column mass (L_snw, L_aer [kg/m^2])
+ ! 2. optical Depths (tau_snw, tau_aer)
+ ! 3. weighted Mie properties (tau, omega, g)
+
+ ! Weighted Mie parameters of each layer
+ DO i=snl_top,snl_btm,1
+#ifdef MODAL_AER
+ !mgf++ within-ice and external BC optical properties
+ !
+ ! Lookup table indices for BC optical properties,
+ ! dependent on snow grain size and BC particle
+ ! size.
+
+ ! valid for 25 < snw_rds < 1625 um:
+ IF (snw_rds_lcl(i) < 125) THEN
+ tmp1 = snw_rds_lcl(i)/50
+ idx_bcint_icerds = nint(tmp1)
+ ELSEIF (snw_rds_lcl(i) < 175) THEN
+ idx_bcint_icerds = 2
+ ELSE
+ tmp1 = (snw_rds_lcl(i)/250)+2
+ idx_bcint_icerds = nint(tmp1)
+ ENDIF
+
+ ! valid for 25 < bc_rds < 525 nm
+ idx_bcint_nclrds = nint(rds_bcint_lcl(i)/50)
+ idx_bcext_nclrds = nint(rds_bcext_lcl(i)/50)
+
+ ! check bounds:
+ IF (idx_bcint_icerds < idx_bcint_icerds_min) idx_bcint_icerds = idx_bcint_icerds_min
+ IF (idx_bcint_icerds > idx_bcint_icerds_max) idx_bcint_icerds = idx_bcint_icerds_max
+ IF (idx_bcint_nclrds < idx_bc_nclrds_min) idx_bcint_nclrds = idx_bc_nclrds_min
+ IF (idx_bcint_nclrds > idx_bc_nclrds_max) idx_bcint_nclrds = idx_bc_nclrds_max
+ IF (idx_bcext_nclrds < idx_bc_nclrds_min) idx_bcext_nclrds = idx_bc_nclrds_min
+ IF (idx_bcext_nclrds > idx_bc_nclrds_max) idx_bcext_nclrds = idx_bc_nclrds_max
+
+ ! retrieve absorption enhancement factor for within-ice BC
+ enh_fct = bcenh(bnd_idx,idx_bcint_nclrds,idx_bcint_icerds)
+
+ ! get BC optical properties (moved from above)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx,idx_bcint_nclrds)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx,idx_bcint_nclrds)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx,idx_bcint_nclrds)*enh_fct
+
+ ! aerosol species 2 optical properties (external BC)
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx,idx_bcext_nclrds)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx,idx_bcext_nclrds)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx,idx_bcext_nclrds)
+
+#else
+ ! bulk aerosol treatment (BC optical properties independent
+ ! of BC and ice grain size)
+ ! aerosol species 1 optical properties (within-ice BC)
+ ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx)
+ asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx)
+ ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx)
+
+ ! aerosol species 2 optical properties
+ ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx)
+ asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx)
+ ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx)
+#endif
+
+ ! Calculate single-scattering albedo for internal mixing of dust-snow
+ IF (use_dust_snow_internal_mixing) THEN
+ IF (bnd_idx < 4) THEN
+ C_dust_total = mss_cnc_aer_lcl(i,5) + mss_cnc_aer_lcl(i,6) &
+ + mss_cnc_aer_lcl(i,7) + mss_cnc_aer_lcl(i,8)
+ C_dust_total = C_dust_total * 1.0E+06_r8
+ IF(C_dust_total > 0._r8) THEN
+ IF (flg_slr_in == 1) THEN
+ R_1_omega_tmp = dust_clear_d0(bnd_idx) &
+ + dust_clear_d2(bnd_idx)*(C_dust_total**dust_clear_d1(bnd_idx))
+ ELSE
+ R_1_omega_tmp = dust_cloudy_d0(bnd_idx) &
+ + dust_cloudy_d2(bnd_idx)*(C_dust_total**dust_cloudy_d1(bnd_idx))
+ ENDIF
+ ss_alb_snw_lcl(i) = 1.0_r8 - (1.0_r8 - ss_alb_snw_lcl(i)) *R_1_omega_tmp
+ ENDIF
+ ENDIF
+ DO j = 5,8,1
+ ss_alb_aer_lcl(j) = 0._r8
+ asm_prm_aer_lcl(j) = 0._r8
+ ext_cff_mss_aer_lcl(j) = 0._r8
+ ENDDO
+ ENDIF
+
+ !mgf--
+
+ L_snw(i) = h2osno_ice_lcl(i)+h2osno_liq_lcl(i)
+ tau_snw(i) = L_snw(i)*ext_cff_mss_snw_lcl(i)
+
+ DO j=1,sno_nbr_aer
+ IF (use_dust_snow_internal_mixing .and. (j >= 5)) THEN
+ L_aer(i,j) = 0._r8
+ ELSE
+ L_aer(i,j) = L_snw(i)*mss_cnc_aer_lcl(i,j)
+ ENDIF
+ tau_aer(i,j) = L_aer(i,j)*ext_cff_mss_aer_lcl(j)
+ ENDDO
+
+ tau_sum = 0._r8
+ omega_sum = 0._r8
+ g_sum = 0._r8
+
+ DO j=1,sno_nbr_aer
+ tau_sum = tau_sum + tau_aer(i,j)
+ omega_sum = omega_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j))
+ g_sum = g_sum + (tau_aer(i,j)*ss_alb_aer_lcl(j)*asm_prm_aer_lcl(j))
+ ENDDO
+
+ tau(i) = tau_sum + tau_snw(i)
+ omega(i) = (1/tau(i))*(omega_sum+(ss_alb_snw_lcl(i)*tau_snw(i)))
+ g(i) = (1/(tau(i)*omega(i)))*(g_sum+ (asm_prm_snw_lcl(i)*ss_alb_snw_lcl(i)*tau_snw(i)))
+ ENDDO ! endWeighted Mie parameters of each layer
+
+ ! DELTA transformations, IF requested
+ IF (DELTA == 1) THEN
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)/(1+g(i))
+ omega_star(i) = ((1-(g(i)**2))*omega(i)) / (1-(omega(i)*(g(i)**2)))
+ tau_star(i) = (1-(omega(i)*(g(i)**2)))*tau(i)
+ ENDDO
+ ELSE
+ DO i=snl_top,snl_btm,1
+ g_star(i) = g(i)
+ omega_star(i) = omega(i)
+ tau_star(i) = tau(i)
+ ENDDO
+ ENDIF
+
+ ! Begin radiative transfer solver
+ ! Given input vertical profiles of optical properties, evaluate the
+ ! monochromatic Delta-Eddington adding-doubling solution
+
+ ! note that trndir, trntdr, trndif, rupdir, rupdif, rdndif
+ ! are variables at the layer interface,
+ ! for snow with layers rangeing from snl_top to snl_btm
+ ! there are snl_top to snl_btm+1 layer interface
+ snl_btm_itf = snl_btm + 1
+
+ DO i = snl_top,snl_btm_itf,1
+ trndir(i) = c0
+ trntdr(i) = c0
+ trndif(i) = c0
+ rupdir(i) = c0
+ rupdif(i) = c0
+ rdndif(i) = c0
+ ENDDO
+
+ ! initialize top interface of top layer
+ trndir(snl_top) = c1
+ trntdr(snl_top) = c1
+ trndif(snl_top) = c1
+ rdndif(snl_top) = c0
+
+ ! begin main level loop
+ ! for layer interfaces except for the very bottom
+ DO i = snl_top,snl_btm,1
+
+ ! initialize all layer apparent optical properties to 0
+ rdir (i) = c0
+ rdif_a(i) = c0
+ rdif_b(i) = c0
+ tdir (i) = c0
+ tdif_a(i) = c0
+ tdif_b(i) = c0
+ trnlay(i) = c0
+
+ ! compute next layer Delta-eddington solution only IF total transmission
+ ! of radiation to the interface just above the layer exceeds trmin.
+
+ IF (trntdr(i) > trmin ) THEN
+
+ ! calculation over layers with penetrating radiation
+
+ ! delta-transformed single-scattering properties
+ ! of this layer
+ ts = tau_star(i)
+ ws = omega_star(i)
+ gs = g_star(i)
+
+ ! Delta-Eddington solution expressions
+ ! n(uu,et) = ((uu+c1)*(uu+c1)/et ) - ((uu-c1)*(uu-c1)*et)
+ ! u(w,gg,e) = c1p5*(c1 - w*gg)/e
+ ! el(w,gg) = sqrt(c3*(c1-w)*(c1 - w*gg))
+ lm = sqrt(c3*(c1-ws)*(c1 - ws*gs)) !lm = el(ws,gs)
+ ue = c1p5*(c1 - ws*gs)/lm !ue = u(ws,gs,lm)
+ extins = max(exp_min, exp(-lm*ts))
+ ne = ((ue+c1)*(ue+c1)/extins) - ((ue-c1)*(ue-c1)*extins) !ne = n(ue,extins)
+
+ ! first calculation of rdif, tdif using Delta-Eddington formulas
+ ! rdif_a(k) = (ue+c1)*(ue-c1)*(c1/extins - extins)/ne
+ rdif_a(i) = (ue**2-c1)*(c1/extins - extins)/ne
+ tdif_a(i) = c4*ue/ne
+
+ ! evaluate rdir,tdir for direct beam
+ trnlay(i) = max(exp_min, exp(-ts/mu_not))
+
+ ! Delta-Eddington solution expressions
+ ! alpha(w,uu,gg,e) = p75*w*uu*((c1 + gg*(c1-w))/(c1 - e*e*uu*uu))
+ ! agamm(w,uu,gg,e) = p5*w*((c1 + c3*gg*(c1-w)*uu*uu)/(c1-e*e*uu*uu))
+ ! alp = alpha(ws,mu_not,gs,lm)
+ ! gam = agamm(ws,mu_not,gs,lm)
+ alp = cp75*ws*mu_not*((c1 + gs*(c1-ws))/(c1 - lm*lm*mu_not*mu_not))
+ gam = cp5*ws*((c1 + c3*gs*(c1-ws)*mu_not*mu_not)/(c1-lm*lm*mu_not*mu_not))
+ apg = alp + gam
+ amg = alp - gam
+
+ rdir(i) = apg*rdif_a(i) + amg*(tdif_a(i)*trnlay(i) - c1)
+ tdir(i) = apg*tdif_a(i) + (amg* rdif_a(i)-apg+c1)*trnlay(i)
+
+ ! recalculate rdif,tdif using direct angular integration over rdir,tdir,
+ ! since Delta-Eddington rdif formula is not well-behaved (it is usually
+ ! biased low and can even be negative); USE ngmax angles and gaussian
+ ! integration for most accuracy:
+ R1 = rdif_a(i) ! USE R1 as temporary
+ T1 = tdif_a(i) ! USE T1 as temporary
+ swt = c0
+ smr = c0
+ smt = c0
+ DO ng=1,ngmax
+ mu = difgauspt(ng)
+ gwt = difgauswt(ng)
+ swt = swt + mu*gwt
+ trn = max(exp_min, exp(-ts/mu))
+ ! alp = alpha(ws,mu,gs,lm)
+ ! gam = agamm(ws,mu,gs,lm)
+ alp = cp75*ws*mu*((c1 + gs*(c1-ws))/(c1 - lm*lm*mu*mu))
+ gam = cp5*ws*((c1 + c3*gs*(c1-ws)*mu*mu)/(c1-lm*lm*mu*mu))
+ apg = alp + gam
+ amg = alp - gam
+ rdr = apg*R1 + amg*T1*trn - amg
+ tdr = apg*T1 + amg*R1*trn - apg*trn + trn
+ smr = smr + mu*rdr*gwt
+ smt = smt + mu*tdr*gwt
+ ENDDO ! ng
+ rdif_a(i) = smr/swt
+ tdif_a(i) = smt/swt
+
+ ! homogeneous layer
+ rdif_b(i) = rdif_a(i)
+ tdif_b(i) = tdif_a(i)
+
+ ENDIF ! trntdr(k) > trmin
+
+ ! Calculate the solar beam transmission, total transmission, and
+ ! reflectivity for diffuse radiation from below at interface i,
+ ! the top of the current layer k:
+ !
+ ! layers interface
+ !
+ ! --------------------- i-1
+ ! i-1
+ ! --------------------- i
+ ! i
+ ! ---------------------
+
+ trndir(i+1) = trndir(i)*trnlay(i)
+ refkm1 = c1/(c1 - rdndif(i)*rdif_a(i))
+ tdrrdir = trndir(i)*rdir(i)
+ tdndif = trntdr(i) - trndir(i)
+ trntdr(i+1) = trndir(i)*tdir(i) + &
+ (tdndif + tdrrdir*rdndif(i))*refkm1*tdif_a(i)
+ rdndif(i+1) = rdif_b(i) + &
+ (tdif_b(i)*rdndif(i)*refkm1*tdif_a(i))
+ trndif(i+1) = trndif(i)*refkm1*tdif_a(i)
+
+ ENDDO ! END main level loop
+
+
+ ! compute reflectivity to direct and diffuse radiation for layers
+ ! below by adding succesive layers starting from the underlying
+ ! ground and working upwards:
+ !
+ ! layers interface
+ !
+ ! --------------------- i
+ ! i
+ ! --------------------- i+1
+ ! i+1
+ ! ---------------------
+
+ ! set the underlying ground albedo == albedo of near-IR
+ ! unless bnd_idx == 1, for visible
+ rupdir(snl_btm_itf) = albsfc(2)
+ rupdif(snl_btm_itf) = albsfc(2)
+ IF (bnd_idx == 1) THEN
+ rupdir(snl_btm_itf) = albsfc(1)
+ rupdif(snl_btm_itf) = albsfc(1)
+ ENDIF
+
+ DO i=snl_btm,snl_top,-1
+ ! interface scattering
+ refkp1 = c1/( c1 - rdif_b(i)*rupdif(i+1))
+ ! dir from top layer plus exp tran ref from lower layer, interface
+ ! scattered and tran thru top layer from below, plus diff tran ref
+ ! from lower layer with interface scattering tran thru top from below
+ rupdir(i) = rdir(i) &
+ + ( trnlay(i) *rupdir(i+1) &
+ + (tdir(i)-trnlay(i))*rupdif(i+1))*refkp1*tdif_b(i)
+ ! dif from top layer from above, plus dif tran upwards reflected and
+ ! interface scattered which tran top from below
+ rupdif(i) = rdif_a(i) + tdif_a(i)*rupdif(i+1)*refkp1*tdif_b(i)
+ ENDDO ! i
+
+ ! net flux (down-up) at each layer interface from the
+ ! snow top (i = snl_top) to bottom interface above land (i = snl_btm_itf)
+ ! the interface reflectivities and transmissivities required
+ ! to evaluate interface fluxes are returned from solution_dEdd;
+ ! now compute up and down fluxes for each interface, using the
+ ! combined layer properties at each interface:
+ !
+ ! layers interface
+ !
+ ! --------------------- i
+ ! i
+ ! ---------------------
+
+ DO i = snl_top, snl_btm_itf
+ ! interface scattering
+ refk = c1/(c1 - rdndif(i)*rupdif(i))
+ ! dir tran ref from below times interface scattering, plus diff
+ ! tran and ref from below times interface scattering
+ ! fdirup(i) = (trndir(i)*rupdir(i) + &
+ ! (trntdr(i)-trndir(i)) &
+ ! *rupdif(i))*refk
+ ! dir tran plus total diff trans times interface scattering plus
+ ! dir tran with up dir ref and down dif ref times interface scattering
+ ! fdirdn(i) = trndir(i) + (trntdr(i) &
+ ! - trndir(i) + trndir(i) &
+ ! *rupdir(i)*rdndif(i))*refk
+ ! diffuse tran ref from below times interface scattering
+ ! fdifup(i) = trndif(i)*rupdif(i)*refk
+ ! diffuse tran times interface scattering
+ ! fdifdn(i) = trndif(i)*refk
+
+ ! netflux, down - up
+ ! dfdir = fdirdn - fdirup
+ dfdir(i) = trndir(i) &
+ + (trntdr(i)-trndir(i)) * (c1 - rupdif(i)) * refk &
+ - trndir(i)*rupdir(i) * (c1 - rdndif(i)) * refk
+ IF (dfdir(i) < puny) dfdir(i) = c0
+ ! dfdif = fdifdn - fdifup
+ dfdif(i) = trndif(i) * (c1 - rupdif(i)) * refk
+ IF (dfdif(i) < puny) dfdif(i) = c0
+ ENDDO ! k
+
+ ! SNICAR_AD_RT is called twice for direct and diffuse incident fluxes
+ ! direct incident
+ IF (flg_slr_in == 1) THEN
+ albedo = rupdir(snl_top)
+ dftmp = dfdir
+ refk = c1/(c1 - rdndif(snl_top)*rupdif(snl_top))
+ F_sfc_pls = (trndir(snl_top)*rupdir(snl_top) + &
+ (trntdr(snl_top)-trndir(snl_top)) &
+ *rupdif(snl_top))*refk
+ !diffuse incident
+ ELSE
+ albedo = rupdif(snl_top)
+ dftmp = dfdif
+ refk = c1/(c1 - rdndif(snl_top)*rupdif(snl_top))
+ F_sfc_pls = trndif(snl_top)*rupdif(snl_top)*refk
+ ENDIF
+
+ ! Absorbed flux in each layer
+ DO i=snl_top,snl_btm,1
+ F_abs(i) = dftmp(i)-dftmp(i+1)
+ flx_abs_lcl(i,bnd_idx) = F_abs(i)
+
+ ! ERROR check: negative absorption
+ IF (p_is_root) THEN
+ IF (flx_abs_lcl(i,bnd_idx) < -0.00001) THEN
+ write (iulog,"(a,e13.6,a,i6)") "SNICAR ERROR: negative absoption : ", flx_abs_lcl(i,bnd_idx)
+ write(iulog,*) "SNICAR_AD STATS: snw_rds(0)= ", snw_rds(0)
+ write(iulog,*) "SNICAR_AD STATS: L_snw(0)= ", L_snw(0)
+ write(iulog,*) "SNICAR_AD STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write(iulog,*) "SNICAR_AD STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1)
+ write(iulog,*) "SNICAR_AD STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2)
+ write(iulog,*) "SNICAR_AD STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3)
+ write(iulog,*) "SNICAR_AD STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4)
+ write(iulog,*) "SNICAR_AD STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5)
+ write(iulog,*) "SNICAR_AD STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6)
+ CALL abort
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! absobed flux by the underlying ground
+ F_btm_net = dftmp(snl_btm_itf)
+
+ ! note here, snl_btm_itf = 1 by snow column set up in CLM
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+
+ IF (flg_nosnl == 1) THEN
+ ! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer
+ !flx_abs_lcl(:,bnd_idx) = 0._r8
+ !flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net
+
+ ! changed on 20070408:
+ ! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation
+ ! handles the CASE of no snow layers. Then, IF a snow layer is addded between now and
+ ! SurfaceRadiation (called in CanopyHydrology), absorbed energy will be properly distributed.
+ flx_abs_lcl(0,bnd_idx) = F_abs(0)
+ flx_abs_lcl(1,bnd_idx) = F_btm_net
+ ENDIF
+
+ !Underflow check (we've already tripped the error condition above)
+ DO i=snl_top,1,1
+ IF (flx_abs_lcl(i,bnd_idx) < 0._r8) THEN
+ flx_abs_lcl(i,bnd_idx) = 0._r8
+ ENDIF
+ ENDDO
+
+ F_abs_sum = 0._r8
+ DO i=snl_top,snl_btm,1
+ F_abs_sum = F_abs_sum + F_abs(i)
+ ENDDO
+
+ !ENDDO !ENDDO WHILE (flg_dover > 0)
+
+ ! Energy conservation check:
+ ! Incident direct+diffuse radiation equals (absorbed+bulk_transmitted+bulk_reflected)
+ energy_sum = (mu_not*pi*flx_slrd_lcl(bnd_idx)) + flx_slri_lcl(bnd_idx) - (F_abs_sum + F_btm_net + F_sfc_pls)
+ IF (p_is_root) THEN
+ IF (abs(energy_sum) > 0.00001_r8) THEN
+ write (iulog,"(a,e13.6,a,i6)") "SNICAR ERROR: Energy conservation error of : ", energy_sum
+ write(iulog,*) "F_abs_sum: ",F_abs_sum
+ write(iulog,*) "F_btm_net: ",F_btm_net
+ write(iulog,*) "F_sfc_pls: ",F_sfc_pls
+ write(iulog,*) "mu_not*pi*flx_slrd_lcl(bnd_idx): ", mu_not*pi*flx_slrd_lcl(bnd_idx)
+ write(iulog,*) "flx_slri_lcl(bnd_idx)", flx_slri_lcl(bnd_idx)
+ write(iulog,*) "bnd_idx", bnd_idx
+ write(iulog,*) "F_abs", F_abs
+ write(iulog,*) "albedo", albedo
+ CALL abort
+ ENDIF
+ ENDIF
+
+ albout_lcl(bnd_idx) = albedo
+ ! Check that albedo is less than 1
+ IF (p_is_root) THEN
+ IF (albout_lcl(bnd_idx) > 1.0) THEN
+ write (iulog,*) "SNICAR ERROR: Albedo > 1.0: "
+ write (iulog,*) "SNICAR STATS: bnd_idx= ",bnd_idx
+ write (iulog,*) "SNICAR STATS: albout_lcl(bnd)= ",albout_lcl(bnd_idx), &
+ " albsfc_lcl(bnd_idx)= ",albsfc_lcl(bnd_idx)
+ write (iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl
+ write (iulog,*) "SNICAR STATS: coszen= ", coszen, " flg_slr= ", flg_slr_in
+
+ write (iulog,*) "SNICAR STATS: soot(-4)= ", mss_cnc_aer_lcl(-4,1)
+ write (iulog,*) "SNICAR STATS: soot(-3)= ", mss_cnc_aer_lcl(-3,1)
+ write (iulog,*) "SNICAR STATS: soot(-2)= ", mss_cnc_aer_lcl(-2,1)
+ write (iulog,*) "SNICAR STATS: soot(-1)= ", mss_cnc_aer_lcl(-1,1)
+ write (iulog,*) "SNICAR STATS: soot(0)= ", mss_cnc_aer_lcl(0,1)
+
+ write (iulog,*) "SNICAR STATS: L_snw(-4)= ", L_snw(-4)
+ write (iulog,*) "SNICAR STATS: L_snw(-3)= ", L_snw(-3)
+ write (iulog,*) "SNICAR STATS: L_snw(-2)= ", L_snw(-2)
+ write (iulog,*) "SNICAR STATS: L_snw(-1)= ", L_snw(-1)
+ write (iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0)
+
+ write (iulog,*) "SNICAR STATS: snw_rds(-4)= ", snw_rds(-4)
+ write (iulog,*) "SNICAR STATS: snw_rds(-3)= ", snw_rds(-3)
+ write (iulog,*) "SNICAR STATS: snw_rds(-2)= ", snw_rds(-2)
+ write (iulog,*) "SNICAR STATS: snw_rds(-1)= ", snw_rds(-1)
+ write (iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(0)
+
+ CALL abort
+ ENDIF
+ ENDIF
+
+ ENDDO ! loop over wvl bands
+
+
+ ! Weight output NIR albedo appropriately
+ albout(1) = albout_lcl(1)
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx)
+ ENDDO
+ albout(2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+
+ ! Weight output NIR absorbed layer fluxes (flx_abs) appropriately
+ flx_abs(:,1) = flx_abs_lcl(:,1)
+ DO i=snl_top,1,1
+ flx_sum = 0._r8
+ DO bnd_idx= nir_bnd_bgn,nir_bnd_end
+ flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx)
+ ENDDO
+ flx_abs(i,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+ ENDDO
+
+ ! near-IR direct albedo/absorption adjustment for high solar zenith angles
+ ! solar zenith angle parameterization
+ ! calculate the scaling factor for NIR direct albedo IF SZA>75 degree
+ IF ((mu_not < mu_75) .and. (flg_slr_in == 1)) THEN
+ sza_c1 = sza_a0 + sza_a1 * mu_not + sza_a2 * mu_not**2
+ sza_c0 = sza_b0 + sza_b1 * mu_not + sza_b2 * mu_not**2
+ sza_factor = sza_c1 * (log10(snw_rds_lcl(snl_top) * c1) - c6) + sza_c0
+ flx_sza_adjust = albout(2) * (sza_factor-c1) * sum(flx_wgt(nir_bnd_bgn:nir_bnd_end))
+ albout(2) = albout(2) * sza_factor
+ flx_abs(snl_top,2) = flx_abs(snl_top,2) - flx_sza_adjust
+ ENDIF
+
+ ! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo
+ ELSEIF ( (coszen > 0._r8) .and. (h2osno_lcl < min_snw) .and. (h2osno_lcl > 0._r8) ) THEN
+ albout(1) = albsfc(1)
+ albout(2) = albsfc(2)
+
+ ! There is either zero snow, or no sun
+ ELSE
+ albout(1) = 0._r8
+ albout(2) = 0._r8
+ ENDIF ! IF column has snow and coszen > 0
+
+ ! END associate
+
+ END SUBROUTINE SNICAR_AD_RT
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowAge_grain( dtime , snl , dz , &
+ qflx_snow_grnd , qflx_snwcp_ice , qflx_snofrz_lyr , &
+ do_capsnow , frac_sno , h2osno , &
+ h2osno_liq , h2osno_ice , &
+ t_soisno , t_grnd , &
+ forc_t , snw_rds )
+ !
+ ! !DESCRIPTION:
+ ! Updates the snow effective grain size (radius).
+ ! Contributions to grain size evolution are from:
+ ! 1. vapor redistribution (dry snow)
+ ! 2. liquid water redistribution (wet snow)
+ ! 3. re-freezing of liquid water
+ !
+ ! Vapor redistribution: Method is to retrieve 3 best-bit parameters that
+ ! depend on snow temperature, temperature gradient, and density,
+ ! that are derived from the microphysical model described in:
+ ! Flanner and Zender (2006), Linking snowpack microphysics and albedo
+ ! evolution, J. Geophys. Res., 111, D12208, doi:10.1029/2005JD006834.
+ ! The parametric equation has the form:
+ ! dr/dt = drdt_0*(tau/(dr_fresh+tau))^(1/kappa), WHERE:
+ ! r is the effective radius,
+ ! tau and kappa are best-fit parameters,
+ ! drdt_0 is the initial rate of change of effective radius, and
+ ! dr_fresh is the difference between the current and fresh snow states
+ ! (r_current - r_fresh).
+ !
+ ! Liquid water redistribution: Apply the grain growth FUNCTION from:
+ ! Brun, E. (1989), Investigation of wet-snow metamorphism in respect of
+ ! liquid-water content, Annals of Glaciology, 13, 22-26.
+ ! There are two parameters that describe the grain growth rate as
+ ! a FUNCTION of snow liquid water content (LWC). The "LWC=0" parameter
+ ! is zeroed here because we are accounting for dry snowing with a
+ ! different representation
+ !
+ ! Re-freezing of liquid water: Assume that re-frozen liquid water clumps
+ ! into an arbitrarily large effective grain size (snw_rds_refrz).
+ ! The phenomenon is observed (Grenfell), but so far unquantified, as far as
+ ! I am aware.
+ !
+ ! !USES:
+ !
+ ! DAI, Dec. 29, 2022
+ !-----------------------------------------------------------------------
+ ! !ARGUMENTS:
+
+ IMPLICIT NONE
+
+ real(r8) , intent(in) :: dtime ! land model time step [sec]
+
+ integer , intent(in) :: snl ! negative number of snow layers (col) [nbr]
+ real(r8) , intent(in) :: dz ( maxsnl+1:1 ) ! layer thickness (col,lyr) [m]
+
+ real(r8) , intent(in) :: qflx_snow_grnd ! snow on ground after interception (col) [kg m-2 s-1]
+ real(r8) , intent(in) :: qflx_snwcp_ice ! excess precipitation due to snow capping [kg m-2 s-1]
+ real(r8) , intent(in) :: qflx_snofrz_lyr ( maxsnl+1:0 ) ! snow freezing rate (col,lyr) [kg m-2 s-1]
+
+ logical , intent(in) :: do_capsnow ! true => DO snow capping
+ real(r8) , intent(in) :: frac_sno ! fraction of ground covered by snow (0 to 1)
+ real(r8) , intent(in) :: h2osno ! snow water (col) [mm H2O]
+ real(r8) , intent(in) :: h2osno_liq ( maxsnl+1:0 ) ! liquid water content (col,lyr) [kg m-2]
+ real(r8) , intent(in) :: h2osno_ice ( maxsnl+1:0 ) ! ice content (col,lyr) [kg m-2]
+
+ real(r8) , intent(in) :: t_soisno ( maxsnl+1:1 ) ! soil and snow temperature (col,lyr) [K]
+ real(r8) , intent(in) :: t_grnd ! ground temperature (col) [K]
+ real(r8) , intent(in) :: forc_t ! Atmospheric temperature (col) [K]
+
+ real(r8) , intent(inout) :: snw_rds ( maxsnl+1:0 ) ! effective grain radius (col,lyr) [microns, m-6]
+
+ ! DAI, Dec. 29, 2022
+ !-----------------------------------------------------------------------
+ !
+ ! !LOCAL VARIABLES:
+ integer :: snl_top ! top snow layer index [idx]
+ integer :: snl_btm ! bottom snow layer index [idx]
+ integer :: i ! layer index [idx]
+ ! integer :: c_idx ! column index [idx]
+ integer :: fc ! snow column filter index [idx]
+ integer :: T_idx ! snow aging lookup table temperature index [idx]
+ integer :: Tgrd_idx ! snow aging lookup table temperature gradient index [idx]
+ integer :: rhos_idx ! snow aging lookup table snow density index [idx]
+ real(r8) :: t_snotop ! temperature at upper layer boundary [K]
+ real(r8) :: t_snobtm ! temperature at lower layer boundary [K]
+ real(r8) :: dTdz(maxsnl:0) ! snow temperature gradient (col,lyr) [K m-1]
+ real(r8) :: bst_tau ! snow aging parameter retrieved from lookup table [hour]
+ real(r8) :: bst_kappa ! snow aging parameter retrieved from lookup table [unitless]
+ real(r8) :: bst_drdt0 ! snow aging parameter retrieved from lookup table [um hr-1]
+ real(r8) :: dr ! incremental change in snow effective radius [um]
+ real(r8) :: dr_wet ! incremental change in snow effective radius from wet growth [um]
+ real(r8) :: dr_fresh ! difference between fresh snow r_e and current r_e [um]
+ real(r8) :: newsnow ! fresh snowfall [kg m-2]
+ real(r8) :: refrzsnow ! re-frozen snow [kg m-2]
+ real(r8) :: frc_newsnow ! fraction of layer mass that is new snow [frc]
+ real(r8) :: frc_oldsnow ! fraction of layer mass that is old snow [frc]
+ real(r8) :: frc_refrz ! fraction of layer mass that is re-frozen snow [frc]
+ real(r8) :: frc_liq ! fraction of layer mass that is liquid water[frc]
+ real(r8) :: rhos ! snow density [kg m-3]
+ real(r8) :: h2osno_lyr ! liquid + solid H2O in snow layer [kg m-2]
+ real(r8) :: cdz(maxsnl+1:0) ! column average layer thickness [m]
+ real(r8) :: snw_rds_fresh ! fresh snow radius [microns]
+
+ real(r8) :: snot_top ! temperature in top snow layer (col) [K]
+ real(r8) :: dTdz_top ! temperature gradient in top layer (col) [K m-1]
+ real(r8) :: snw_rds_top ! effective grain radius, top layer (col) [microns, m-6]
+ real(r8) :: sno_liq_top ! liquid water fraction (mass) in top snow layer (col) [frc]
+
+ !--------------------------------------------------------------------------!
+
+ ! associate( &
+ ! snl => col_pp%snl , & ! Input: [integer (:) ] negative number of snow layers (col) [nbr]
+ ! dz => col_pp%dz , & ! Input: [real(r8) (:,:) ] layer thickness (col,lyr) [m]
+
+ ! qflx_snow_grnd => col_wf%qflx_snow_grnd , & ! Input: [real(r8) (:) ] snow on ground after interception (col) [kg m-2 s-1]
+ ! qflx_snwcp_ice => col_wf%qflx_snwcp_ice , & ! Input: [real(r8) (:) ] excess precipitation due to snow capping [kg m-2 s-1]
+ ! qflx_snofrz_lyr => col_wf%qflx_snofrz_lyr , & ! Input: [real(r8) (:,:) ] snow freezing rate (col,lyr) [kg m-2 s-1]
+
+ ! do_capsnow => col_ws%do_capsnow , & ! Input: [logical (:) ] true => DO snow capping
+ ! frac_sno => col_ws%frac_sno_eff , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1)
+ ! h2osno => col_ws%h2osno , & ! Input: [real(r8) (:) ] snow water (col) [mm H2O]
+ ! h2osno_liq => col_ws%h2osno_liq , & ! Input: [real(r8) (:,:) ] liquid water content (col,lyr) [kg m-2]
+ ! h2osno_ice => col_ws%h2osno_ice , & ! Input: [real(r8) (:,:) ] ice content (col,lyr) [kg m-2]
+ ! snw_rds => col_ws%snw_rds , & ! Output: [real(r8) (:,:) ] effective grain radius (col,lyr) [microns, m-6]
+ ! snw_rds_top => col_ws%snw_rds_top , & ! Output: [real(r8) (:) ] effective grain radius, top layer (col) [microns, m-6]
+ ! sno_liq_top => col_ws%sno_liq_top , & ! Output: [real(r8) (:) ] liquid water fraction (mass) in top snow layer (col) [frc]
+
+ ! t_soisno => col_es%t_soisno , & ! Input: [real(r8) (:,:) ] soil and snow temperature (col,lyr) [K]
+ ! t_grnd => col_es%t_grnd , & ! Input: [real(r8) (:) ] ground temperature (col) [K]
+ ! snot_top => col_es%snot_top , & ! Output: [real(r8) (:) ] temperature in top snow layer (col) [K]
+ ! dTdz_top => col_es%dTdz_top & ! Output: [real(r8) (:) ] temperature gradient in top layer (col) [K m-1]
+ ! )
+
+
+ IF (snl < 0 .and. h2osno > 0._r8) THEN
+
+ snl_btm = 0
+ snl_top = snl + 1
+
+ cdz(snl_top:snl_btm)=frac_sno*dz(snl_top:snl_btm)
+
+ ! loop over snow layers
+ DO i = snl_top, snl_btm, 1
+ !
+ !********** 1. DRY SNOW AGING ***********
+ !
+ h2osno_lyr = h2osno_liq(i) + h2osno_ice(i)
+
+ ! temperature gradient
+ IF (i == snl_top) THEN
+ ! top layer
+ t_snotop = t_soisno(snl_top)
+ t_snobtm = (t_soisno(i+1)*dz(i) &
+ + t_soisno(i)*dz(i+1)) &
+ / (dz(i)+dz(i+1))
+ ELSE
+ t_snotop = (t_soisno(i-1)*dz(i) &
+ + t_soisno(i)*dz(i-1)) &
+ / (dz(i)+dz(i-1))
+ t_snobtm = (t_soisno(i+1)*dz(i) &
+ + t_soisno(i)*dz(i+1)) &
+ / (dz(i)+dz(i+1))
+ ENDIF
+
+ dTdz(i) = abs((t_snotop - t_snobtm) / cdz(i))
+
+ ! snow density
+ rhos = (h2osno_liq(i)+h2osno_ice(i)) / cdz(i)
+
+ ! make sure rhos doesn't drop below 50 (see rhos_idx below)
+ rhos=max(50._r8,rhos)
+
+ ! best-fit table indecies
+ T_idx = nint((t_soisno(i)-223) / 5) + 1
+ Tgrd_idx = nint(dTdz(i) / 10) + 1
+ rhos_idx = nint((rhos-50) / 50) + 1
+
+ ! boundary check:
+ IF (T_idx < idx_T_min) THEN
+ T_idx = idx_T_min
+ ENDIF
+ IF (T_idx > idx_T_max) THEN
+ T_idx = idx_T_max
+ ENDIF
+ IF (Tgrd_idx < idx_Tgrd_min) THEN
+ Tgrd_idx = idx_Tgrd_min
+ ENDIF
+ IF (Tgrd_idx > idx_Tgrd_max) THEN
+ Tgrd_idx = idx_Tgrd_max
+ ENDIF
+ IF (rhos_idx < idx_rhos_min) THEN
+ rhos_idx = idx_rhos_min
+ ENDIF
+ IF (rhos_idx > idx_rhos_max) THEN
+ rhos_idx = idx_rhos_max
+ ENDIF
+
+ ! best-fit parameters
+ bst_tau = snowage_tau(rhos_idx,Tgrd_idx,T_idx)
+ bst_kappa = snowage_kappa(rhos_idx,Tgrd_idx,T_idx)
+ bst_drdt0 = snowage_drdt0(rhos_idx,Tgrd_idx,T_idx)
+
+ ! change in snow effective radius, using best-fit parameters
+ ! added checks suggested by mgf. --HW 10/15/2015
+ dr_fresh = snw_rds(i)-snw_rds_min
+
+#ifdef MODAL_AER
+ IF ( abs(dr_fresh) < 1.0e-8_r8 ) THEN
+ dr_fresh = 0.0_r8
+ ELSEIF ( dr_fresh < 0.0_r8 ) THEN
+ IF (p_is_root) THEN
+ write(iulog,*) "dr_fresh = ", dr_fresh, snw_rds(i), snw_rds_min
+ CALL abort
+ ENDIF
+ ENDIF
+
+ dr = (bst_drdt0*(bst_tau/(dr_fresh+bst_tau))**(1._r8/bst_kappa)) * (dtime/3600._r8)
+#else
+ dr = (bst_drdt0*(bst_tau/(dr_fresh+bst_tau))**(1/bst_kappa)) * (dtime/3600)
+#endif
+ !
+ !********** 2. WET SNOW AGING ***********
+ !
+ ! We are assuming wet and dry evolution occur simultaneously, and
+ ! the contributions from both can be summed.
+ ! This is justified by setting the linear offset constant C1_liq_Brun89 to zero [Brun, 1989]
+
+ ! liquid water faction
+ frc_liq = min(0.1_r8, (h2osno_liq(i) / (h2osno_liq(i)+h2osno_ice(i))))
+
+ !dr_wet = 1E6_r8*(dtime*(C1_liq_Brun89 + C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*(snw_rds(i)/1E6)**(2)))
+ !simplified, units of microns:
+ dr_wet = 1E18_r8*(dtime*(C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*snw_rds(i)**(2)))
+
+ dr = dr + dr_wet
+
+ !
+ !********** 3. SNOWAGE SCALING (TURNED OFF BY DEFAULT) *************
+ !
+ ! Multiply rate of change of effective radius by some constant, xdrdt
+ IF (flg_snoage_scl) THEN
+ dr = dr*xdrdt
+ ENDIF
+
+ !
+ !********** 4. INCREMENT EFFECTIVE RADIUS, ACCOUNTING FOR: ***********
+ ! DRY AGING
+ ! WET AGING
+ ! FRESH SNOW
+ ! RE-FREEZING
+ !
+ ! new snowfall [kg/m2]
+ IF (do_capsnow .and. .not. use_extrasnowlayers) THEN
+ newsnow = max(0._r8, (qflx_snwcp_ice*dtime))
+ ELSE
+ newsnow = max(0._r8, (qflx_snow_grnd*dtime))
+ ENDIF
+
+ ! snow that has re-frozen [kg/m2]
+ refrzsnow = max(0._r8, (qflx_snofrz_lyr(i)*dtime))
+
+ ! fraction of layer mass that is re-frozen
+ frc_refrz = refrzsnow / h2osno_lyr
+
+ ! fraction of layer mass that is new snow
+ IF (i == snl_top) THEN
+ frc_newsnow = newsnow / h2osno_lyr
+ ELSE
+ frc_newsnow = 0._r8
+ ENDIF
+
+ IF ((frc_refrz + frc_newsnow) > 1._r8) THEN
+ frc_refrz = frc_refrz / (frc_refrz + frc_newsnow)
+ frc_newsnow = 1._r8 - frc_refrz
+ frc_oldsnow = 0._r8
+ ELSE
+ frc_oldsnow = 1._r8 - frc_refrz - frc_newsnow
+ ENDIF
+
+ ! temperature dependent fresh grain size
+ snw_rds_fresh = FreshSnowRadius (forc_t)
+
+ ! mass-weighted mean of fresh snow, old snow, and re-frozen snow effective radius
+ snw_rds(i) = (snw_rds(i)+dr)*frc_oldsnow + snw_rds_fresh*frc_newsnow + snw_rds_refrz*frc_refrz
+ !
+ !********** 5. CHECK BOUNDARIES ***********
+ !
+ ! boundary check
+ IF (snw_rds(i) < snw_rds_min) THEN
+ snw_rds(i) = snw_rds_min
+ ENDIF
+
+ IF (snw_rds(i) > snw_rds_max) THEN
+ snw_rds(i) = snw_rds_max
+ ENDIF
+
+ ! set top layer variables for history files
+ IF (i == snl_top) THEN
+ snot_top = t_soisno(i)
+ dTdz_top = dTdz(i)
+ snw_rds_top = snw_rds(i)
+ sno_liq_top = h2osno_liq(i) / (h2osno_liq(i)+h2osno_ice(i))
+ ENDIF
+
+ ENDDO
+ ENDIF ! ENDIF (snl < 0 )
+
+ ! Special CASE: snow on ground, but not enough to have defined a snow layer:
+ ! set snw_rds to fresh snow grain size:
+
+ IF (snl >= 0 .and. h2osno > 0._r8) THEN
+ snw_rds(0) = snw_rds_min
+ ENDIF
+
+ ! END associate
+
+ END SUBROUTINE SnowAge_grain
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowOptics_init( fsnowoptics )
+
+ USE MOD_NetCDFSerial
+
+ IMPLICIT NONE
+
+ character(len=256), intent(in) :: fsnowoptics ! snow optical properties file name
+ character(len= 32) :: subname = 'SnowOptics_init' ! SUBROUTINE name
+ integer :: atm_type_index ! index for atmospheric type
+
+ logical :: readvar ! determine IF variable was read from NetCDF file
+ !-----------------------------------------------------------------------
+
+ readvar = .true.
+
+ atm_type_index = atm_type_default
+ ! Define atmospheric type
+ IF (trim(snicar_atm_type) == 'default') THEN
+ atm_type_index = atm_type_default
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_winter') THEN
+ atm_type_index = atm_type_mid_latitude_winter
+ ELSEIF (trim(snicar_atm_type) == 'mid-latitude_summer') THEN
+ atm_type_index = atm_type_mid_latitude_summer
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_winter') THEN
+ atm_type_index = atm_type_sub_Arctic_winter
+ ELSEIF (trim(snicar_atm_type) == 'sub-Arctic_summer') THEN
+ atm_type_index = atm_type_sub_Arctic_summer
+ ELSEIF (trim(snicar_atm_type) == 'summit_Greenland') THEN
+ atm_type_index = atm_type_summit_Greenland
+ ELSEIF (trim(snicar_atm_type) == 'high_mountain') THEN
+ atm_type_index = atm_type_high_mountain
+ ELSE
+ IF (p_is_root) THEN
+ write(iulog,*) "snicar_atm_type = ", snicar_atm_type
+ CALL abort
+ ENDIF
+ ENDIF
+
+ !
+ ! Open optics file:
+ IF (p_is_root) THEN
+ write(iulog,*) 'Attempting to read snow optical properties .....'
+ write(iulog,*) subname,trim(fsnowoptics)
+ ENDIF
+
+ ! direct-beam snow Mie parameters:
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ice_drc', ss_alb_snw_drc)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ice_drc', asm_prm_snw_drc)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ice_drc', ext_cff_mss_snw_drc)
+
+ ! diffuse snow Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ice_dfs', ss_alb_snw_dfs)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ice_dfs', asm_prm_snw_dfs)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ice_dfs', ext_cff_mss_snw_dfs)
+
+ !!! Direct and diffuse flux under different atmospheric conditions
+ ! Direct-beam incident spectral flux:
+ CALL ncio_read_bcast_serial (fsnowoptics, 'flx_wgt_dir', flx_wgt_dir)
+
+ ! Diffuse incident spectral flux:
+ CALL ncio_read_bcast_serial (fsnowoptics, 'flx_wgt_dif', flx_wgt_dif)
+
+#ifdef MODAL_AER
+ ! size-dependent BC parameters and BC enhancement factors
+ IF (p_is_root) THEN
+ write(iulog,*) 'Attempting to read optical properties for within-ice BC (modal aerosol treatment) ...'
+ ENDIF
+ !
+ ! BC species 1 Mie parameters
+ !
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bc_mam', ss_alb_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bc_mam', asm_prm_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bc_mam', ext_cff_mss_bc1)
+ !
+ ! BC species 2 Mie parameters (identical, before enhancement factors applied)
+ !
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bc_mam', ss_alb_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bc_mam', asm_prm_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bc_mam', ext_cff_mss_bc2)
+ !
+ ! size-dependent BC absorption enhancement factors for within-ice BC
+ CALL ncio_read_bcast_serial (fsnowoptics, 'bcint_enh_mam', bcenh)
+ !
+#else
+ ! bulk aerosol treatment
+ ! BC species 1 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bcphil', ss_alb_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bcphil', asm_prm_bc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bcphil', ext_cff_mss_bc1)
+
+ !
+ ! BC species 2 Mie parameters
+ !
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_bcphob', ss_alb_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_bcphob', asm_prm_bc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_bcphob', ext_cff_mss_bc2)
+ !
+#endif
+ !
+ ! OC species 1 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ocphil', ss_alb_oc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ocphil', asm_prm_oc1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ocphil', ext_cff_mss_oc1)
+ !
+ ! OC species 2 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_ocphob', ss_alb_oc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_ocphob', asm_prm_oc2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_ocphob', ext_cff_mss_oc2)
+ !
+ ! dust species 1 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust01', ss_alb_dst1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust01', asm_prm_dst1)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust01', ext_cff_mss_dst1)
+ !
+ ! dust species 2 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust02', ss_alb_dst2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust02', asm_prm_dst2)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust02', ext_cff_mss_dst2)
+ !
+ ! dust species 3 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust03', ss_alb_dst3)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust03', asm_prm_dst3)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust03', ext_cff_mss_dst3)
+ !
+ ! dust species 4 Mie parameters
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ss_alb_dust04', ss_alb_dst4)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'asm_prm_dust04', asm_prm_dst4)
+ CALL ncio_read_bcast_serial (fsnowoptics, 'ext_cff_mss_dust04', ext_cff_mss_dst4)
+ !
+ !
+
+ IF (p_is_root) THEN
+ write(iulog,*) 'Successfully read snow optical properties'
+ ENDIF
+
+
+ ! print some diagnostics:
+ IF (p_is_root) THEN
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for direct-beam ice, rds=100um: ', &
+ ss_alb_snw_drc(71,1), ss_alb_snw_drc(71,2), ss_alb_snw_drc(71,3), &
+ ss_alb_snw_drc(71,4), ss_alb_snw_drc(71,5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for diffuse ice, rds=100um: ', &
+ ss_alb_snw_dfs(71,1), ss_alb_snw_dfs(71,2), ss_alb_snw_dfs(71,3), &
+ ss_alb_snw_dfs(71,4), ss_alb_snw_dfs(71,5)
+ IF (DO_SNO_OC) THEN
+ write (iulog,*) 'SNICAR: Including OC aerosols from snow radiative transfer calculations'
+ ELSE
+ write (iulog,*) 'SNICAR: Excluding OC aerosols from snow radiative transfer calculations'
+ ENDIF
+ ENDIF
+ !
+#ifdef MODAL_AER
+ IF (p_is_root) THEN
+ ! unique dimensionality for modal aerosol optical properties
+ write (iulog,*) 'SNICAR: Subset of Mie single scatter albedos for BC: ', &
+ ss_alb_bc1(1,1), ss_alb_bc1(1,2), ss_alb_bc1(2,1), ss_alb_bc1(5,1), ss_alb_bc1(1,10), ss_alb_bc2(1,10)
+ write (iulog,*) 'SNICAR: Subset of Mie mass extinction coefficients for BC: ', &
+ ext_cff_mss_bc2(1,1), ext_cff_mss_bc2(1,2), ext_cff_mss_bc2(2,1), ext_cff_mss_bc2(5,1), ext_cff_mss_bc2(1,10),&
+ ext_cff_mss_bc1(1,10)
+ write (iulog,*) 'SNICAR: Subset of Mie asymmetry parameters for BC: ', &
+ asm_prm_bc1(1,1), asm_prm_bc1(1,2), asm_prm_bc1(2,1), asm_prm_bc1(5,1), asm_prm_bc1(1,10), asm_prm_bc2(1,10)
+ write (iulog,*) 'SNICAR: Subset of BC absorption enhancement factors: ', &
+ bcenh(1,1,1), bcenh(1,2,1), bcenh(1,1,2), bcenh(2,1,1), bcenh(5,10,1), bcenh(5,1,8), bcenh(5,10,8)
+ ENDIF
+#else
+ IF (p_is_root) THEN
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic BC: ', &
+ ss_alb_bc1(1), ss_alb_bc1(2), ss_alb_bc1(3), ss_alb_bc1(4), ss_alb_bc1(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic BC: ', &
+ ss_alb_bc2(1), ss_alb_bc2(2), ss_alb_bc2(3), ss_alb_bc2(4), ss_alb_bc2(5)
+ ENDIF
+#endif
+
+ IF (p_is_root) THEN
+ IF (DO_SNO_OC) THEN
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic OC: ', &
+ ss_alb_oc1(1), ss_alb_oc1(2), ss_alb_oc1(3), ss_alb_oc1(4), ss_alb_oc1(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic OC: ', &
+ ss_alb_oc2(1), ss_alb_oc2(2), ss_alb_oc2(3), ss_alb_oc2(4), ss_alb_oc2(5)
+ ENDIF
+
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 1: ', &
+ ss_alb_dst1(1), ss_alb_dst1(2), ss_alb_dst1(3), ss_alb_dst1(4), ss_alb_dst1(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 2: ', &
+ ss_alb_dst2(1), ss_alb_dst2(2), ss_alb_dst2(3), ss_alb_dst2(4), ss_alb_dst2(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 3: ', &
+ ss_alb_dst3(1), ss_alb_dst3(2), ss_alb_dst3(3), ss_alb_dst3(4), ss_alb_dst3(5)
+ write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 4: ', &
+ ss_alb_dst4(1), ss_alb_dst4(2), ss_alb_dst4(3), ss_alb_dst4(4), ss_alb_dst4(5)
+ write(iulog,*)
+ ENDIF
+
+ END SUBROUTINE SnowOptics_init
+ !-----------------------------------------------------------------------
+
+
+ SUBROUTINE SnowAge_init( fsnowaging )
+
+ USE MOD_NetCDFSerial
+
+ IMPLICIT NONE
+
+ character(len=256), intent(in) :: fsnowaging ! snow aging parameters file name
+ character(len= 32) :: subname = 'SnowAge_init' ! SUBROUTINE name
+ !
+ ! Open snow aging (effective radius evolution) file:
+ IF (p_is_root) THEN
+ write(iulog,*) 'Attempting to read snow aging parameters .....'
+ write(iulog,*) subname,trim(fsnowaging)
+ ENDIF
+
+ !
+ ! SNOW aging parameters
+ !
+ CALL ncio_read_bcast_serial (fsnowaging, 'tau', snowage_tau)
+ CALL ncio_read_bcast_serial (fsnowaging, 'kappa', snowage_kappa)
+ CALL ncio_read_bcast_serial (fsnowaging, 'drdsdt0', snowage_drdt0)
+
+ !
+ IF (p_is_root) THEN
+ write(iulog,*) 'Successfully read snow aging properties'
+ ENDIF
+ !
+ ! print some diagnostics:
+ IF (p_is_root) THEN
+ write (iulog,*) 'SNICAR: snowage tau for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_tau(3,11,9)
+ write (iulog,*) 'SNICAR: snowage kappa for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_kappa(3,11,9)
+ write (iulog,*) 'SNICAR: snowage dr/dt_0 for T=263K, dTdz = 100 K/m, rhos = 150 kg/m3: ', snowage_drdt0(3,11,9)
+ ENDIF
+
+ END SUBROUTINE SnowAge_init
+ !-----------------------------------------------------------------------
+
+
+ real(r8) FUNCTION FreshSnowRadius (forc_t)
+ !
+ ! !DESCRIPTION:
+ ! Returns fresh snow grain radius, which is linearly dependent on temperature.
+ ! This is implemented to remedy an outstanding bias that SNICAR has in initial
+ ! grain size. See e.g. Sandells et al, 2017 for a discussion (10.5194/tc-11-229-2017).
+ !
+ ! Yang et al. (2017), 10.1016/j.jqsrt.2016.03.033
+ ! discusses grain size observations, which suggest a temperature dependence.
+ !
+ ! !REVISION HISTORY:
+ ! Author: Leo VanKampenhout
+ !
+ ! !USES:
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Aerosol, only: fresh_snw_rds_max
+
+ ! !ARGUMENTS:
+ real(r8), intent(in) :: forc_t ! atmospheric temperature (Kelvin)
+ !
+ ! !LOCAL VARIABLES:
+ !-----------------------------------------------------------------------
+ real(r8), parameter :: tmin = tfrz - 30._r8 ! start of linear ramp
+ real(r8), parameter :: tmax = tfrz - 0._r8 ! END of linear ramp
+ real(r8), parameter :: gs_min = snw_rds_min ! minimum value
+ real(r8) :: gs_max ! maximum value
+
+ IF ( fresh_snw_rds_max <= snw_rds_min )THEN
+ FreshSnowRadius = snw_rds_min
+ ELSE
+ gs_max = fresh_snw_rds_max
+
+ IF (forc_t < tmin) THEN
+ FreshSnowRadius = gs_min
+ ELSEIF (forc_t > tmax) THEN
+ FreshSnowRadius = gs_max
+ ELSE
+ FreshSnowRadius = (tmax-forc_t)/(tmax-tmin)*gs_min + &
+ (forc_t-tmin)/(tmax-tmin)*gs_max
+ ENDIF
+ ENDIF
+
+ END FUNCTION FreshSnowRadius
+
+END MODULE MOD_SnowSnicar_HiRes
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilSnowHydrology.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilSnowHydrology.F90
new file mode 100644
index 0000000000..372873169a
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilSnowHydrology.F90
@@ -0,0 +1,2327 @@
+#include
+
+MODULE MOD_SoilSnowHydrology
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS, DEF_USE_SNICAR, &
+ DEF_URBAN_RUN, DEF_USE_IRRIGATION, &
+ DEF_SPLIT_SOILSNOW, DEF_Runoff_SCHEME, &
+ DEF_DA_TWS_GRACE, DEF_Optimize_Baseflow, &
+ DEF_USE_Dynamic_Wetland
+ USE MOD_LandPatch, only: landpatch
+ USE MOD_Runoff
+ USE MOD_Hydro_VIC
+ USE MOD_Hydro_VIC_Variables
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: WATER_2014
+ PUBLIC :: WATER_VSF
+ PUBLIC :: snowwater
+ PUBLIC :: soilwater
+ PUBLIC :: snowwater_snicar
+
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: groundwater
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+
+ SUBROUTINE WATER_2014 (ipatch,patchtype,lb ,nl_soil ,deltim ,&
+ z_soisno ,dz_soisno ,zi_soisno ,bsw ,porsl ,&
+ psi0 ,hksati ,theta_r ,fsatmax ,fsatdcf ,&
+ elvstd ,BVIC ,rootr ,rootflux ,t_soisno ,&
+ wliq_soisno ,wice_soisno ,smp ,hk ,pg_rain ,&
+ sm ,etr ,qseva ,qsdew ,qsubl ,&
+ qfros ,qseva_soil ,qsdew_soil ,qsubl_soil ,qfros_soil ,&
+ qseva_snow ,qsdew_snow ,qsubl_snow ,qfros_snow ,fsno ,&
+ rsur ,rnof ,qinfl ,pondmx ,ssi ,&
+ wimp ,smpmin ,zwt ,wdsrf ,wa ,&
+ qcharge ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+ qflx_irrig_drip ,qflx_irrig_flood ,qflx_irrig_paddy )
+
+!=======================================================================
+! this is the main SUBROUTINE to execute the calculation of
+! hydrological processes
+!
+! Original author: Yongjiu Dai, /09/1999/, /08/2002/, /04/2014/
+!
+! FLOW DIAGRAM FOR WATER_2014.F90
+!
+! WATER_2014 ===> snowwater
+! SurfaceRunoff_TOPMOD
+! soilwater
+! SubsurfaceRunoff_TOPMOD
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o, tfrz
+ USE MOD_Vars_TimeInvariants, only: vic_b_infilt, vic_Dsmax, vic_Ds, vic_Ws, vic_c
+ USE MOD_Vars_1DFluxes, only: fevpg
+#ifdef CROP
+ USE MOD_Vars_Global, only : irrig_method_paddy, pondmxc
+ use MOD_LandPFT, only : patch_pft_s, patch_pft_e
+ use MOD_Vars_PFTimeVariables, only: irrig_method_p
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch ,&! patch index
+ patchtype ! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=land ice, 4=land water bodies, 99=ocean
+
+ integer, intent(in) :: &
+ lb ,&! lower bound of array
+ nl_soil ! upper bound of array
+
+ real(r8), intent(in) :: &
+ deltim ,&! time step (s)
+ ! wtfact ,&! (updated to gridded 'fsatmax' data) fraction of model area with high water table
+ pondmx ,&! ponding depth (mm)
+ ssi ,&! irreducible water saturation of snow
+ wimp ,&! water impermeable if porosity less than wimp
+ smpmin ,&! restriction for min of soil poten. (mm)
+ elvstd ,&! standard deviation of elevation (m)
+ BVIC ,&!
+
+ z_soisno (lb:nl_soil) ,&! layer depth (m)
+ dz_soisno(lb:nl_soil) ,&! layer thickness (m)
+ zi_soisno(lb-1:nl_soil) ,&! interface level below a "z" level (m)
+
+ bsw(1:nl_soil) ,&! Clapp-Hornberger "B"
+ porsl(1:nl_soil) ,&! saturated volumetric soil water content(porosity)
+ psi0(1:nl_soil) ,&! saturated soil suction (mm) (NEGATIVE)
+ hksati(1:nl_soil) ,&! hydraulic conductivity at saturation (mm h2o/s)
+ theta_r(1:nl_soil) ,&! residual moisture content [-]
+ fsatmax ,&! maximum saturated area fraction [-]
+ fsatdcf ,&! decay factor in calculation of saturated area fraction [1/m]
+ rootr(1:nl_soil) ,&! water uptake fraction from different layers, all layers add to 1.0
+ rootflux(1:nl_soil) ,&! root uptake from different layer, all layers add to transpiration
+
+ t_soisno(lb:nl_soil) ,&! soil/snow skin temperature (K)
+ pg_rain ,&! rainfall after removal of interception (mm h2o/s)
+ sm ,&! snow melt (mm h2o/s)
+ etr ,&! actual transpiration (mm h2o/s)
+ qseva ,&! ground surface evaporation rate (mm h2o/s)
+ qsdew ,&! ground surface dew formation (mm h2o /s) [+]
+ qsubl ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qseva_soil ,&! ground soil surface evaporation rate (mm h2o/s)
+ qsdew_soil ,&! ground soil surface dew formation (mm h2o /s) [+]
+ qsubl_soil ,&! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qfros_soil ,&! surface dew added to soil ice pack (mm h2o /s) [+]
+ qseva_snow ,&! ground snow surface evaporation rate (mm h2o/s)
+ qsdew_snow ,&! ground snow surface dew formation (mm h2o /s) [+]
+ qsubl_snow ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros_snow ,&! surface dew added to snow pack (mm h2o /s) [+]
+ fsno ! snow fractional cover
+
+ real(r8), intent(inout) :: &
+ wice_soisno(lb:nl_soil) ,&! ice lens (kg/m2)
+ wliq_soisno(lb:nl_soil) ! liquid water (kg/m2)
+
+ real(r8), intent(out) :: &
+ smp(1:nl_soil) ,&! soil matrix potential [mm]
+ hk (1:nl_soil) ! hydraulic conductivity [mm h2o/m]
+
+ real(r8), intent(inout) :: &
+ zwt ,&! the depth from ground (soil) surface to water table [m]
+ wdsrf ,&! depth of surface water [mm]
+ wa ! water storage in aquifer [mm]
+
+ real(r8), intent(out) :: &
+ rsur ,&! surface runoff (mm h2o/s)
+ rnof ,&! total runoff (mm h2o/s)
+ qinfl ,&! infiltration rate (mm h2o/s)
+ qcharge ! groundwater recharge (positive to aquifer) [mm/s]
+
+! SNICAR model variables
+! Aerosol Fluxes (Jan. 07, 2023)
+ real(r8), intent(in) :: forc_aer ( 14 ) ! aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+
+ real(r8), intent(inout) :: &
+ mss_bcpho (lb:0) ,&! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi (lb:0) ,&! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho (lb:0) ,&! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi (lb:0) ,&! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 (lb:0) ,&! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 (lb:0) ,&! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 (lb:0) ,&! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 (lb:0) ! mass of dust species 4 in snow (col,lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+! END SNICAR model variables
+
+! irrigation variable
+ real(r8), intent(in) :: &
+ qflx_irrig_drip , &! irrigation flux from drip irrigation [mm/s]
+ qflx_irrig_flood , &! irrigation flux from flood irrigation [mm/s]
+ qflx_irrig_paddy ! irrigation flux from paddy irrigation [mm/s]
+
+!-------------------------- Local Variables ----------------------------
+
+ integer j ! loop counter
+
+ real(r8) :: &
+ eff_porosity(1:nl_soil) ,&! effective porosity = porosity - vol_ice
+ dwat(1:nl_soil) ,&! change in soil water
+ gwat ,&! net water input from top (mm/s)
+ rsubst ,&! subsurface runoff (mm h2o/s)
+ vol_liq(1:nl_soil) ,&! partial volume of liquid water in layer
+ vol_ice(1:nl_soil) ,&! partial volume of ice lens in layer
+ icefrac(1:nl_soil) ,&! ice fraction (-)
+ zmm (1:nl_soil) ,&! layer depth (mm)
+ dzmm(1:nl_soil) ,&! layer thickness (mm)
+ zimm(0:nl_soil) ! interface level below a "z" level (mm)
+
+ real(r8) :: err_solver, w_sum
+ real(r8) :: gwat_prev
+ integer :: ps, pe, m
+
+ real(r8) :: wliq_soisno_tmp(1:nl_soil)
+
+!=======================================================================
+! [1] update the liquid water within snow layer and the water onto soil
+!=======================================================================
+
+
+IF ((.not.DEF_SPLIT_SOILSNOW) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+
+ IF (lb>=1)THEN
+ gwat = pg_rain + sm - qseva
+ ELSE
+ IF ((.not.DEF_USE_SNICAR) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+ CALL snowwater (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat)
+ ELSE
+ CALL snowwater_snicar (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat,&
+ forc_aer,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ENDIF
+ ENDIF
+
+ELSE
+
+ IF (lb>=1)THEN
+ gwat = pg_rain + sm - qseva_soil
+ ELSE
+ IF (.not. DEF_USE_SNICAR) THEN
+ CALL snowwater (lb,deltim,ssi,wimp,&
+ pg_rain*fsno,qseva_snow,qsdew_snow,qsubl_snow,qfros_snow,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat)
+ ELSE
+ CALL snowwater_snicar (lb,deltim,ssi,wimp,&
+ pg_rain*fsno,qseva_snow,qsdew_snow,qsubl_snow,qfros_snow,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat,&
+ forc_aer,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ENDIF
+ gwat = gwat + pg_rain*(1-fsno) - qseva_soil
+ ENDIF
+ENDIF
+
+#ifdef CROP
+ IF(DEF_USE_IRRIGATION)THEN
+ gwat = gwat + qflx_irrig_drip + qflx_irrig_flood + qflx_irrig_paddy
+ gwat = gwat + wdsrf/deltim
+ ENDIF
+#endif
+
+!=======================================================================
+! [2] surface runoff and infiltration
+!=======================================================================
+
+IF(patchtype<=1)THEN ! soil ground only
+
+ ! For water balance check, the sum of water in soil column before the calculation
+ w_sum = sum(wliq_soisno(1:)) + sum(wice_soisno(1:)) + wa
+
+ ! porosity of soil, partial volume of ice and liquid
+ DO j = 1, nl_soil
+ vol_ice(j) = min(porsl(j), wice_soisno(j)/(dz_soisno(j)*denice))
+ eff_porosity(j) = max(0.01, porsl(j)-vol_ice(j))
+ vol_liq(j) = min(eff_porosity(j), wliq_soisno(j)/(dz_soisno(j)*denh2o))
+ IF(porsl(j) < 1.e-6)THEN
+ icefrac(j) = 0.
+ ELSE
+ icefrac(j) = min(1.,vol_ice(j)/porsl(j))
+ ENDIF
+ ENDDO
+
+ ! surface runoff including water table and surface saturated area
+
+ rsur = 0.
+ rsubst = 0.
+
+ IF (DEF_Runoff_SCHEME == 0) THEN
+ ! 0: runoff scheme from TOPMODEL
+
+ IF (gwat > 0.) THEN
+ CALL SurfaceRunoff_TOPMOD (nl_soil,wimp,porsl,psi0,hksati,fsatmax,fsatdcf,&
+ z_soisno(1:),dz_soisno(1:),zi_soisno(0:),&
+ eff_porosity,icefrac,zwt,gwat,rsur)
+ ELSE
+ rsur = 0.
+ ENDIF
+
+ ELSEIF (DEF_Runoff_SCHEME == 1) THEN
+ ! 1: runoff scheme from VIC model
+
+ wliq_soisno_tmp(:) = 0
+ CALL Runoff_VIC(deltim, porsl, theta_r, hksati, bsw, &
+ wice_soisno(1:nl_soil), wliq_soisno(1:nl_soil), fevpg(ipatch), rootflux, gwat, &
+ vic_b_infilt(ipatch), vic_Dsmax(ipatch), vic_Ds(ipatch), vic_Ws(ipatch), vic_c(ipatch),&
+ rsur, rsubst, wliq_soisno_tmp(1:nl_soil))
+
+ ELSEIF (DEF_Runoff_SCHEME == 2) THEN
+ ! 2: runoff scheme from XinAnJiang model
+
+ CALL Runoff_XinAnJiang (&
+ nl_soil, dz_soisno(1:nl_soil), eff_porosity(1:nl_soil), vol_liq(1:nl_soil), &
+ elvstd, gwat, deltim, rsur, rsubst)
+
+ ELSEIF (DEF_Runoff_SCHEME == 3) THEN
+ ! 3: runoff scheme from Simple VIC model
+ CALL Runoff_SimpleVIC (&
+ nl_soil, dz_soisno(1:nl_soil), eff_porosity(1:nl_soil), vol_liq(1:nl_soil), &
+ BVIC, gwat, deltim, rsur, rsubst)
+
+ ENDIF
+#ifdef CROP
+ IF(patchtype==0)THEN
+ IF(DEF_USE_IRRIGATION)THEN
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+ DO m = ps, pe
+ IF(irrig_method_p(m) == irrig_method_paddy)THEN
+ wdsrf = rsur*deltim
+ rsur = 0.
+ IF(wdsrf.gt.pondmxc)THEN
+ wdsrf = pondmxc
+ rsur = rsur + (wdsrf - pondmxc)/deltim
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+#endif
+ ! infiltration into surface soil layer
+ qinfl = gwat - rsur - wdsrf/deltim
+
+!=======================================================================
+! [3] determine the change of soil water
+!=======================================================================
+
+ ! convert length units from m to mm
+ zmm(1:) = z_soisno(1:)*1000.
+ dzmm(1:) = dz_soisno(1:)*1000.
+ zimm(0:) = zi_soisno(0:)*1000.
+
+ CALL soilwater(patchtype,nl_soil,deltim,wimp,smpmin,&
+ qinfl,etr,z_soisno(1:),dz_soisno(1:),zi_soisno(0:),&
+ t_soisno(1:),vol_liq,vol_ice,smp,hk,icefrac,eff_porosity,&
+ porsl,hksati,bsw,psi0,rootr,rootflux,&
+ zwt,dwat,qcharge)
+
+ ! update the mass of liquid water
+ DO j= 1, nl_soil
+ wliq_soisno(j) = wliq_soisno(j)+dwat(j)*dzmm(j)
+ ENDDO
+
+
+!=======================================================================
+! [4] subsurface runoff and the corrections
+!=======================================================================
+
+ CALL groundwater (nl_soil,deltim,pondmx,&
+ eff_porosity,icefrac,dz_soisno(1:),zi_soisno(0:),&
+ wice_soisno(1:),wliq_soisno(1:),&
+ porsl,psi0,bsw,zwt,wa,&
+ qcharge,rsubst)
+
+ ! total runoff (mm/s)
+ rnof = rsubst + rsur
+ ! Renew the ice and liquid mass due to condensation
+IF ((.not.DEF_SPLIT_SOILSNOW) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+ IF(lb >= 1)THEN
+ ! make consistent with how evap_grnd removed in infiltration
+ wliq_soisno(1) = max(0., wliq_soisno(1) + qsdew * deltim)
+ wice_soisno(1) = max(0., wice_soisno(1) + (qfros-qsubl) * deltim)
+ ENDIF
+
+ err_solver = (sum(wliq_soisno(1:))+sum(wice_soisno(1:))+wa+wdsrf) - w_sum &
+ - (gwat-etr-rnof)*deltim
+
+ IF(lb >= 1)THEN
+ err_solver = err_solver-(qsdew+qfros-qsubl)*deltim
+ ENDIF
+
+ELSE
+ wliq_soisno(1) = max(0., wliq_soisno(1) + qsdew_soil * deltim)
+ wice_soisno(1) = max(0., wice_soisno(1) + (qfros_soil-qsubl_soil) * deltim)
+
+ err_solver = (sum(wliq_soisno(1:))+sum(wice_soisno(1:))+wa+wdsrf) - w_sum &
+ - (gwat-etr-rnof)*deltim
+
+ err_solver = err_solver-(qsdew_soil+qfros_soil-qsubl_soil)*deltim
+ENDIF
+
+#if (defined CoLMDEBUG)
+ IF(abs(err_solver) > 1.e-3)THEN
+ write(6,*) 'Warning: water balance violation after all soilwater calculation', err_solver
+ ENDIF
+#endif
+
+
+!=======================================================================
+! [6] assumed hydrological scheme for the wetland and glacier
+!=======================================================================
+
+ELSE
+ IF(patchtype==2)THEN ! WETLAND
+ ! 09/20/2019, by Chaoqun Li: a potential bug below
+ ! surface runoff could > total runoff
+ ! original CoLM: rusr=0., qinfl=gwat, rsubst=0., rnof=0.
+ ! i.e., all water to be infiltration
+ qinfl = 0.
+ rsur = max(0.,gwat)
+ rsubst = 0.
+ rnof = 0.
+ DO j = 1, nl_soil
+ IF(t_soisno(j)>tfrz)THEN
+ wice_soisno(j) = 0.0
+ wliq_soisno(j) = porsl(j)*dz_soisno(j)*1000.
+ ENDIF
+ ENDDO
+ ENDIF
+ IF(patchtype==3)THEN ! LAND ICE
+ rsur = max(0.0,gwat)
+ qinfl = 0.
+ rsubst = 0.
+ rnof = rsur
+ wice_soisno(1:nl_soil) = dz_soisno(1:nl_soil)*1000.
+ wliq_soisno(1:nl_soil) = 0.0
+ ENDIF
+
+ wa = 4800.
+ zwt = 0.
+ qcharge = 0.
+
+ENDIF
+
+ END SUBROUTINE WATER_2014
+
+!-----------------------------------------------------------------------
+ SUBROUTINE WATER_VSF (ipatch, patchtype,is_dry_lake, lb, nl_soil, deltim ,&
+ z_soisno ,dz_soisno ,zi_soisno ,bsw ,theta_r ,&
+ fsatmax ,fsatdcf ,topoweti ,alp_twi ,chi_twi ,&
+ mu_twi ,elvstd ,BVIC ,&
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm ,n_vgm ,L_vgm ,sc_vgm ,fc_vgm ,&
+#endif
+ porsl ,psi0 ,hksati ,rootr ,rootflux ,&
+ t_soisno ,wliq_soisno ,wice_soisno ,smp ,hk ,&
+ pg_rain ,sm ,etr ,qseva ,qsdew ,&
+ qsubl ,qfros ,qseva_soil ,qsdew_soil ,qsubl_soil ,&
+ qfros_soil ,qseva_snow ,qsdew_snow ,qsubl_snow ,qfros_snow ,&
+ fsno ,frcsat ,rsur ,rsur_se ,rsur_ie ,&
+ rsubst ,rnof ,qinfl ,qlayer ,ssi ,&
+ pondmx ,wimp ,zwt ,wdsrf ,wa ,&
+ wetwat ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+! irrigation variable
+ qflx_irrig_drip ,qflx_irrig_flood ,qflx_irrig_paddy )
+
+!===================================================================================
+! this is the main SUBROUTINE to execute the calculation of soil water processes
+!
+! Original author: Yongjiu Dai, /09/1999/, /08/2002/, /04/2014/
+!
+! Modified by Shupeng Zhang /07/2023/ to USE Variably Saturated Flow algorithm
+! Reference :
+! Dai, Y., Zhang, S., Yuan, H., & Wei, N. (2019).
+! Modeling Variably Saturated Flow in Stratified Soils
+! With Explicit Tracking of Wetting Front and Water Table Locations.
+! Water Resources Research. doi:10.1029/2019wr025368
+!
+!===================================================================================
+
+ USE MOD_Precision
+ USE MOD_Hydro_SoilWater
+ USE MOD_Vars_TimeInvariants, only: wetwatmax
+ USE MOD_Const_Physical, only: denice, denh2o, tfrz
+ USE MOD_Vars_TimeInvariants, only: vic_b_infilt, vic_Dsmax, vic_Ds, vic_Ws, vic_c
+ USE MOD_Vars_1DFluxes, only: fevpg
+ USE MOD_Opt_Baseflow, only: scale_baseflow
+#ifdef DataAssimilation
+ USE MOD_DA_TWS, only: fslp_k
+#endif
+#ifdef CROP
+ USE MOD_Vars_Global, only : irrig_method_paddy, pondmxc
+ use MOD_LandPFT, only : patch_pft_s, patch_pft_e
+ use MOD_Vars_PFTimeVariables, only: irrig_method_p
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch ,& ! patch index
+ patchtype ! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=land ice, 4=land water bodies, 99=ocean
+ logical, intent(in) :: is_dry_lake
+
+ integer, intent(in) :: &
+ lb , &! lower bound of array
+ nl_soil ! upper bound of array
+
+ real(r8), intent(in) :: &
+ deltim , &! time step (s)
+ ! wtfact , &! (updated to gridded 'fsatmax' data) fraction of model area with high water table
+ ssi , &! irreducible water saturation of snow
+ pondmx , &! ponding depth (mm)
+ wimp , &! water impermeable IF porosity less than wimp
+ elvstd , &! standard deviation of elevation (m)
+ BVIC , &!
+ z_soisno (lb:nl_soil) , &! layer depth (m)
+ dz_soisno(lb:nl_soil) , &! layer thickness (m)
+ zi_soisno(lb-1:nl_soil) , &! interface level below a "z" level (m)
+ bsw (1:nl_soil), & ! clapp and hornberger "b" parameter [-]
+ theta_r (1:nl_soil), & ! residual moisture content [-]
+ fsatmax , & ! maximum saturated area fraction [-]
+ fsatdcf , & ! decay factor in calculation of saturated area fraction [1/m]
+ topoweti , & ! mean topographic wetness index
+ alp_twi , & ! alpha in three parameter gamma distribution of twi
+ chi_twi , & ! chi in three parameter gamma distribution of twi
+ mu_twi , & ! mu in three parameter gamma distribution of twi
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm(1:nl_soil), & ! a parameter corresponding approximately to the inverse of the air-entry value
+ n_vgm (1:nl_soil), & ! a shape parameter [dimensionless]
+ L_vgm (1:nl_soil), & ! pore-connectivity parameter [dimensionless]
+ sc_vgm (1:nl_soil), & ! saturation at the air entry value in the classical vanGenuchten model [-]
+ fc_vgm (1:nl_soil), & ! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+ porsl(1:nl_soil) , &! saturated volumetric soil water content(porosity)
+ psi0(1:nl_soil) , &! saturated soil suction (mm) (NEGATIVE)
+ hksati(1:nl_soil), &! hydraulic conductivity at saturation (mm h2o/s)
+ rootr(1:nl_soil) , &! water uptake fraction from different layers, all layers add to 1.0
+ rootflux(1:nl_soil),&! root uptake from different layer, all layers add to transpiration
+
+ t_soisno(lb:nl_soil), &! soil/snow skin temperature (K)
+ pg_rain , &! rainfall after removal of interception (mm h2o/s)
+ sm , &! snow melt (mm h2o/s)
+ etr , &! actual transpiration (mm h2o/s)
+ qseva , &! ground surface evaporation rate (mm h2o/s)
+ qsdew , &! ground surface dew formation (mm h2o /s) [+]
+ qsubl , &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros , &! surface dew added to snow pack (mm h2o /s) [+]
+ qseva_soil , &! ground soil surface evaporation rate (mm h2o/s)
+ qsdew_soil , &! ground soil surface dew formation (mm h2o /s) [+]
+ qsubl_soil , &! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qfros_soil , &! surface dew added to soil ice pack (mm h2o /s) [+]
+ qseva_snow , &! ground snow surface evaporation rate (mm h2o/s)
+ qsdew_snow , &! ground snow surface dew formation (mm h2o /s) [+]
+ qsubl_snow , &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros_snow , &! surface dew added to snow pack (mm h2o /s) [+]
+ fsno ! snow fractional cover
+ real(r8), intent(inout) :: &
+ wice_soisno(lb:nl_soil) , &! ice lens (kg/m2)
+ wliq_soisno(lb:nl_soil) ! liquid water (kg/m2)
+
+ real(r8), intent(out) :: &
+ smp(1:nl_soil) , &! soil matrix potential [mm]
+ hk (1:nl_soil) ! hydraulic conductivity [mm h2o/s]
+
+ real(r8), intent(inout) :: &
+ zwt , &! the depth from ground (soil) surface to water table [m]
+ wdsrf , &! depth of surface water [mm]
+ wa , &! water storage in aquifer [mm]
+ wetwat ! water storage in wetland [mm]
+
+ real(r8), intent(out) :: &
+ frcsat , &! fraction of saturation area
+ rsur , &! surface runoff (mm h2o/s)
+ rsur_se , &! saturation excess surface runoff (mm h2o/s)
+ rsur_ie , &! infiltration excess surface runoff (mm h2o/s)
+ rsubst , &! subsurface runoff (mm h2o/s)
+ rnof , &! total runoff (mm h2o/s)
+ qinfl , &! infiltration rate (mm h2o/s)
+ qlayer(0:nl_soil) ! water flux between soil layer [mm h2o/s]
+
+
+
+! SNICAR model variables
+! Aerosol Fluxes (Jan. 07, 2023)
+ real(r8), intent(in) :: forc_aer ( 14 ) ! aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+
+ real(r8), intent(inout) :: &
+ mss_bcpho (lb:0), &! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi (lb:0), &! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho (lb:0), &! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi (lb:0), &! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 (lb:0), &! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 (lb:0), &! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 (lb:0), &! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 (lb:0) ! mass of dust species 4 in snow (col,lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+! END SNICAR model variables
+
+! irrigation variable
+ real(r8), intent(in) :: &
+ qflx_irrig_drip , &! irrigation flux from drip irrigation [mm/s]
+ qflx_irrig_flood , &! irrigation flux from flood irrigation [mm/s]
+ qflx_irrig_paddy ! irrigation flux from paddy irrigation [mm/s]
+
+!-------------------------- Local Variables ----------------------------
+
+ integer j ! loop counter
+
+ real(r8) :: &
+ eff_porosity(1:nl_soil), &! effective porosity = porosity - vol_ice
+ gwat , &! net water input from top (mm/s)
+ drainmax , &! drainage max (mm h2o/s)
+ vol_liq(1:nl_soil), &! partial volume of liquid water in layer
+ vol_ice(1:nl_soil), &! partial volume of ice lens in layer
+ icefrac(1:nl_soil) ! ice fraction (-)
+
+ real(r8) :: eta
+
+ real(r8) :: err_solver, w_sum, wresi(1:nl_soil)
+ real(r8) :: qgtop
+
+ real(r8) :: zwtmm
+ real(r8) :: sp_zc(1:nl_soil), sp_zi(0:nl_soil), sp_dz(1:nl_soil) ! in mm
+ logical :: is_permeable(1:nl_soil)
+ real(r8) :: dzsum, dz
+ real(r8) :: icefracsum, fracice_rsub, imped
+ real(r8) :: wblc
+
+#ifdef Campbell_SOIL_MODEL
+ integer, parameter :: nprms = 1
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ integer, parameter :: nprms = 5
+#endif
+ real(r8) :: prms(nprms, 1:nl_soil)
+ type(soil_con_struct ) :: soil_con
+ type(cell_data_struct) :: cell
+ real(r8) :: wliq_soisno_tmp(1:nl_soil)
+
+ real(r8), parameter :: e_ice=6.0 !soil ice impedance factor
+
+ integer :: ps, pe, m
+
+
+#ifdef Campbell_SOIL_MODEL
+ prms(1,:) = bsw(1:nl_soil)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ prms(1,1:nl_soil) = alpha_vgm(1:nl_soil)
+ prms(2,1:nl_soil) = n_vgm (1:nl_soil)
+ prms(3,1:nl_soil) = L_vgm (1:nl_soil)
+ prms(4,1:nl_soil) = sc_vgm (1:nl_soil)
+ prms(5,1:nl_soil) = fc_vgm (1:nl_soil)
+#endif
+
+!=======================================================================
+! [1] update the liquid water within snow layer and the water onto soil
+!=======================================================================
+
+IF ((.not.DEF_SPLIT_SOILSNOW) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+
+ IF (lb>=1)THEN
+ gwat = pg_rain + sm - qseva
+ ELSE
+
+ IF ((.not.DEF_USE_SNICAR) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+ CALL snowwater (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat)
+ ELSE
+ CALL snowwater_snicar (lb,deltim,ssi,wimp,&
+ pg_rain,qseva,qsdew,qsubl,qfros,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat,&
+ forc_aer,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ENDIF
+ ENDIF
+
+ELSE
+
+ IF (lb>=1)THEN
+ gwat = pg_rain + sm - qseva_soil
+ ELSE
+ IF (.not. DEF_USE_SNICAR) THEN
+ CALL snowwater (lb,deltim,ssi,wimp,&
+ pg_rain*fsno,qseva_snow,qsdew_snow,qsubl_snow,qfros_snow,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat)
+ ELSE
+ CALL snowwater_snicar (lb,deltim,ssi,wimp,&
+ pg_rain*fsno,qseva_snow,qsdew_snow,qsubl_snow,qfros_snow,&
+ dz_soisno(lb:0),wice_soisno(lb:0),wliq_soisno(lb:0),gwat,&
+ forc_aer,&
+ mss_bcpho(lb:0), mss_bcphi(lb:0), mss_ocpho(lb:0), mss_ocphi(lb:0),&
+ mss_dst1(lb:0), mss_dst2(lb:0), mss_dst3(lb:0), mss_dst4(lb:0) )
+ ENDIF
+ gwat = gwat + pg_rain*(1-fsno) - qseva_soil
+ ENDIF
+ENDIF
+
+
+#ifdef CROP
+ IF(DEF_USE_IRRIGATION)THEN
+ gwat = gwat + qflx_irrig_drip + qflx_irrig_flood + qflx_irrig_paddy
+ ENDIF
+#endif
+
+!=======================================================================
+! [2] surface runoff and infiltration
+!=======================================================================
+
+IF((patchtype<=1) .or. is_dry_lake &
+ .or. (DEF_USE_Dynamic_Wetland .and. (patchtype==2)))THEN ! soil ground only
+
+ ! For water balance check, the sum of water in soil column before the calculation
+ w_sum = sum(wliq_soisno(1:nl_soil)) + sum(wice_soisno(1:nl_soil)) + wa + wdsrf
+
+ ! Due to the increase in volume after freezing, the total volume of water and
+ ! ice may exceed the porosity of the soil. This excess water is temporarily
+ ! stored in "wresi". After calculating the movement of soil water, "wresi"
+ ! is added back to "wliq_soisno".
+ wresi(1:nl_soil) = 0.
+ ! porosity of soil, partial volume of ice and liquid
+ DO j = 1, nl_soil
+ vol_ice(j) = min(porsl(j), wice_soisno(j)/(dz_soisno(j)*denice))
+ IF(porsl(j) < 1.e-6)THEN
+ icefrac(j) = 0.
+ ELSE
+ icefrac(j) = min(1.,vol_ice(j)/porsl(j))
+ ENDIF
+
+ eff_porosity(j) = max(wimp, porsl(j)-vol_ice(j))
+ is_permeable(j) = eff_porosity(j) > max(wimp, theta_r(j))
+ IF (is_permeable(j)) THEN
+ vol_liq(j) = wliq_soisno(j)/(dz_soisno(j)*denh2o)
+ vol_liq(j) = min(eff_porosity(j), max(0., vol_liq(j)))
+ wresi(j) = wliq_soisno(j) - dz_soisno(j) * denh2o * vol_liq(j)
+ ELSE
+ vol_liq(j) = 0.
+ ENDIF
+ ENDDO
+
+ ! surface runoff including water table and surface saturated area
+
+ rsur = 0.
+ rsubst = 0.
+ rsur_ie = 0.
+ rsur_se = 0.
+
+#ifndef CatchLateralFlow
+ IF (patchtype <= 1) THEN
+
+ IF (DEF_Runoff_SCHEME == 0) THEN
+
+ CALL SurfaceRunoff_TOPMOD (nl_soil,wimp,porsl,psi0,hksati,fsatmax,fsatdcf,&
+ z_soisno(1:),dz_soisno(1:),zi_soisno(0:),&
+ eff_porosity,icefrac,zwt,gwat,rsur,rsur_se,rsur_ie,topoweti,alp_twi,chi_twi,mu_twi,frcsat,eta)
+
+ CALL SubsurfaceRunoff_TOPMOD (nl_soil, icefrac, dz_soisno(1:), zi_soisno(0:), &
+ zwt, rsubst, hksati, topoweti, eta)
+
+ ELSEIF (DEF_Runoff_SCHEME == 1) THEN
+ ! 1: runoff scheme from VIC model
+
+ CALL Runoff_VIC(deltim, porsl, theta_r, hksati, bsw, &
+ wice_soisno(1:nl_soil), wliq_soisno(1:nl_soil), fevpg(ipatch), rootflux, gwat, &
+ vic_b_infilt(ipatch), vic_Dsmax(ipatch), vic_Ds(ipatch), vic_Ws(ipatch), vic_c(ipatch),&
+ rsur, rsubst, wliq_soisno_tmp)
+
+ rsur_se = rsur
+ rsur_ie = 0.
+
+ ELSEIF (DEF_Runoff_SCHEME == 2) THEN
+ ! 2: runoff scheme from XinAnJiang model
+
+ CALL Runoff_XinAnJiang (&
+ nl_soil, dz_soisno(1:nl_soil), eff_porosity(1:nl_soil), vol_liq(1:nl_soil), &
+ elvstd, gwat, deltim, rsur, rsubst, frcsat)
+
+ rsur_se = rsur
+ rsur_ie = 0.
+
+ ELSEIF (DEF_Runoff_SCHEME == 3) THEN
+ ! 3: runoff scheme from simplified VIC model
+
+ CALL Runoff_SimpleVIC (&
+ nl_soil, dz_soisno(1:nl_soil), eff_porosity(1:nl_soil), vol_liq(1:nl_soil), &
+ BVIC, gwat, deltim, rsur, rsubst, frcsat)
+
+ ! CALL SubsurfaceRunoff_SimpleVIC ( &
+ ! nl_soil, z_soisno(1:nl_soil), dz_soisno(1:nl_soil), wice_soisno(1:nl_soil), &
+ ! porsl(1:nl_soil), psi0(1:nl_soil), hksati(1:nl_soil), theta_r(1:nl_soil), &
+ ! nprms, prms(:,1:nl_soil), zwt, rsubst)
+
+ rsur_se = rsur
+ rsur_ie = 0.
+
+ ENDIF
+
+ rsubst = rsubst * scale_baseflow(ipatch)
+
+#ifdef DataAssimilation
+ IF (DEF_DA_TWS_GRACE) THEN
+ rsur = max(min(rsur * fslp_k(ipatch), gwat), 0.)
+ rsubst = rsubst * fslp_k(ipatch)
+ ENDIF
+#endif
+
+#ifdef CROP
+ IF(patchtype.eq.0 .AND. DEF_USE_IRRIGATION)THEN
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+ DO m = ps, pe
+ IF(irrig_method_p(m).eq.irrig_method_paddy)THEN
+ rsur = 0
+ ENDIF
+ ENDDO
+ ENDIF
+#endif
+ ENDIF
+#else
+ ! for catchment based lateral flow,
+ ! "rsur" is calculated in HYDRO/MOD_Catch_HillslopeFlow.F90
+ ! "rsub" is calculated in HYDRO/MOD_Catch_SubsurfaceFlow.F90
+#endif
+
+ ! infiltration into surface soil layer
+ qgtop = gwat - rsur
+
+!=======================================================================
+! [3] determine the change of soil water
+!=======================================================================
+
+ ! convert length units from m to mm
+ zwtmm = zwt * 1000.0
+ sp_zc(1:nl_soil) = z_soisno (1:nl_soil) * 1000.0 ! from meter to mm
+ sp_zi(0:nl_soil) = zi_soisno(0:nl_soil) * 1000.0 ! from meter to mm
+
+ ! check consistency between water table location and liquid water content
+ IF (wa < 0.) THEN
+ IF (zwtmm <= sp_zi(nl_soil)) THEN
+ CALL get_zwt_from_wa ( &
+ porsl(nl_soil), theta_r(nl_soil), psi0(nl_soil), hksati(nl_soil), &
+ nprms, prms(:,nl_soil), 1.e-5, 1.e-8, wa, sp_zi(nl_soil), zwtmm)
+ ENDIF
+ ELSE
+ DO j = 1, nl_soil
+ IF ((vol_liq(j) < eff_porosity(j)-1.e-8) .and. (zwtmm <= sp_zi(j-1))) THEN
+ zwtmm = sp_zi(j)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ! update "vol_liq" in the level containing water table
+ ! "vol_liq" in this level refers to volume content in unsaturated part
+ IF (zwtmm < sp_zi(nl_soil)) THEN
+ DO j = nl_soil, 1, -1
+ IF ((zwtmm >= sp_zi(j-1)) .and. (zwtmm < sp_zi(j))) THEN
+
+ IF ((zwtmm > sp_zi(j-1)) .and. (is_permeable(j))) THEN
+ vol_liq(j) = (wliq_soisno(j)*1000.0/denh2o - eff_porosity(j)*(sp_zi(j)-zwtmm)) &
+ / (zwtmm - sp_zi(j-1))
+ IF (vol_liq(j) < 0.) THEN
+ zwtmm = sp_zi(j)
+ vol_liq(j) = wliq_soisno(j)*1000.0/denh2o / (sp_zi(j) - sp_zi(j-1))
+ ENDIF
+
+ vol_liq(j) = max(0., min(eff_porosity(j), vol_liq(j)))
+ wresi(j) = wliq_soisno(j)*1000.0/denh2o - eff_porosity(j)*(sp_zi(j)-zwtmm) &
+ - vol_liq(j) * (zwtmm - sp_zi(j-1))
+ ENDIF
+
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ wdsrf = max(0., wdsrf)
+
+ IF ((.not. is_permeable(1)) .and. (qgtop < 0.)) THEN
+ IF (wdsrf > 0) THEN
+ wdsrf = wdsrf + qgtop * deltim
+ IF (wdsrf < 0) THEN
+ wliq_soisno(1) = max(0., wliq_soisno(1) + wdsrf)
+ wdsrf = 0
+ ENDIF
+ ELSE
+ wliq_soisno(1) = max(0., wliq_soisno(1) + qgtop * deltim)
+ ENDIF
+
+ qgtop = 0.
+
+ ENDIF
+
+ CALL soil_water_vertical_movement ( &
+ nl_soil, deltim, sp_zc(1:nl_soil), sp_zi(0:nl_soil), &
+ is_permeable(1:nl_soil), eff_porosity(1:nl_soil), theta_r(1:nl_soil), psi0(1:nl_soil), &
+ hksati(1:nl_soil), nprms, prms(:,1:nl_soil), porsl(nl_soil), qgtop, &
+ etr, rootr(1:nl_soil), rootflux(1:nl_soil), rsubst, &
+ qinfl, wdsrf, zwtmm, wa, &
+ vol_liq(1:nl_soil), smp(1:nl_soil), hk(1:nl_soil), qlayer(0:nl_soil),&
+ 1.e-3, wblc)
+
+ ! update the mass of liquid water
+ DO j = nl_soil, 1, -1
+ IF (is_permeable(j)) THEN
+ IF (zwtmm < sp_zi(j)) THEN
+ IF (zwtmm >= sp_zi(j-1)) THEN
+ wliq_soisno(j) = denh2o * ((eff_porosity(j)*(sp_zi(j)-zwtmm)) &
+ + vol_liq(j) * (zwtmm - sp_zi(j-1)))/1000.0
+ ELSE
+ wliq_soisno(j) = denh2o * (eff_porosity(j)*(sp_zi(j)-sp_zi(j-1)))/1000.0
+ ENDIF
+ ELSE
+ wliq_soisno(j) = denh2o * (vol_liq(j)*(sp_zi(j)-sp_zi(j-1)))/1000.0
+ ENDIF
+
+ wliq_soisno(j) = wliq_soisno(j) + wresi(j)
+ ENDIF
+ ENDDO
+
+ zwt = zwtmm/1000.0
+
+ ! Renew the ice and liquid mass due to condensation
+IF ((.not.DEF_SPLIT_SOILSNOW) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+ IF(lb >= 1)THEN
+ ! make consistent with how evap_grnd removed in infiltration
+ wliq_soisno(1) = max(0., wliq_soisno(1) + qsdew * deltim)
+ wice_soisno(1) = max(0., wice_soisno(1) + (qfros-qsubl) * deltim)
+ ENDIF
+ELSE
+ wliq_soisno(1) = max(0., wliq_soisno(1) + qsdew_soil * deltim)
+ wice_soisno(1) = max(0., wice_soisno(1) + (qfros_soil-qsubl_soil) * deltim)
+ENDIF
+
+ ! water imbalance mainly due to insufficient liquid water for evapotranspiration
+ IF (wblc > 0.) THEN
+ DO j = 1, nl_soil
+ IF (wice_soisno(j) > wblc) THEN
+ wice_soisno(j) = wice_soisno(j) - wblc
+ wblc = 0.
+ EXIT
+ ELSE
+ wblc = wblc - wice_soisno(j)
+ wice_soisno(j) = 0.
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifndef CatchLateralFlow
+#ifdef CROP
+ IF(patchtype.eq.0 .AND. DEF_USE_IRRIGATION)THEN
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+ DO m = ps, pe
+ IF(irrig_method_p(m).eq.irrig_method_paddy .AND. wdsrf.gt.pondmxc)THEN
+ rsur = rsur + (wdsrf - pondmxc)/deltim
+ rsur_ie = rsur_ie + (wdsrf - pondmxc) / deltim
+ wdsrf = pondmxc
+ ELSEIF(irrig_method_p(m).ne.irrig_method_paddy .AND. wdsrf.gt.pondmx)THEN
+ rsur = rsur + (wdsrf - pondmx) / deltim
+ rsur_ie = rsur_ie + (wdsrf - pondmx) / deltim
+ wdsrf = pondmx
+ ENDIF
+ ENDDO
+
+ IF (zwt <= 0.) THEN
+ rsur_ie = 0.
+ rsur_se = rsur
+ ENDIF
+ ! total runoff (mm/s)
+ rnof = rsubst + rsur
+ ELSE
+#endif
+ IF (patchtype <= 1) THEN
+ IF (wdsrf > pondmx) THEN
+ rsur = rsur + (wdsrf - pondmx) / deltim
+ rsur_ie = rsur_ie + (wdsrf - pondmx) / deltim
+ wdsrf = pondmx
+ ENDIF
+
+ IF (zwt <= 0.) THEN
+ rsur_ie = 0.
+ rsur_se = rsur
+ ENDIF
+
+ ! total runoff (mm/s)
+ rnof = rsubst + rsur
+ ELSEIF (patchtype == 2) THEN ! for wetland
+ IF (wdsrf > wetwatmax) THEN
+ rsur_se = (wdsrf - wetwatmax) / deltim
+ wdsrf = wetwatmax
+ ENDIF
+
+ rsur = rsur_se
+ ! total runoff (mm/s)
+ rnof = rsur
+ ELSE ! for dry lake
+ rnof = 0.
+ ENDIF
+#ifdef CROP
+ ENDIF
+#endif
+#endif
+
+ DO j = 1, nl_soil
+ IF(t_soisno(j) <= tfrz) THEN
+ ! consider impedance factor
+ vol_ice(j) = max(min(porsl(j), wice_soisno(j)/(dz_soisno(j)*denice)), 0.)
+ icefrac(j) = vol_ice(j)/porsl(j)
+ imped = 10.**(-e_ice*icefrac(j))
+ hk(j) = imped * hk(j)
+ ENDIF
+ ENDDO
+
+#ifndef CatchLateralFlow
+ err_solver = (sum(wliq_soisno(1:))+sum(wice_soisno(1:))+wa+wdsrf) - w_sum &
+ - (gwat-etr-rsur-rsubst)*deltim
+#else
+ err_solver = (sum(wliq_soisno(1:))+sum(wice_soisno(1:))+wa+wdsrf) - w_sum &
+ - (gwat-etr)*deltim
+#endif
+
+IF ((.not.DEF_SPLIT_SOILSNOW) .or. (patchtype==1 .and. DEF_URBAN_RUN)) THEN
+ IF(lb >= 1)THEN
+ err_solver = err_solver - (qsdew+qfros-qsubl)*deltim
+ ENDIF
+ELSE
+ err_solver = err_solver-(qsdew_soil+qfros_soil-qsubl_soil)*deltim
+ENDIF
+
+#if (defined CoLMDEBUG)
+ IF(abs(err_solver) > 1.e-3)THEN
+ write(6,'(A,E20.5,A,I0)') 'Warning (WATER_VSF): water balance violation', err_solver, &
+ ' in element ', landpatch%eindex(ipatch)
+ ENDIF
+ IF (any(wliq_soisno < -1.e-3)) THEN
+ write(6,'(A,10E20.5)') 'Warning (WATER_VSF): negative soil water', wliq_soisno(1:nl_soil)
+ ENDIF
+#endif
+
+!=======================================================================
+! [6] assumed hydrological scheme for the wetland
+!=======================================================================
+
+ELSE
+ IF(patchtype==2)THEN ! WETLAND
+ qinfl = 0.
+ zwt = 0.
+
+
+ IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ IF (lb >= 1) THEN
+ wetwat = wdsrf + wa + wetwat + (gwat - etr + qsdew + qfros - qsubl) * deltim
+ ELSE
+ wetwat = wdsrf + wa + wetwat + (gwat - etr) * deltim
+ ENDIF
+ ELSE
+ wetwat = wdsrf + wa + wetwat + (gwat - etr + qsdew_soil + qfros_soil - qsubl_soil) * deltim
+ ENDIF
+
+ wresi(:) = 0.
+ DO j = 1, nl_soil
+ IF(t_soisno(j)>tfrz)THEN
+ wresi(j) = max(wliq_soisno(j) - porsl(j)*dz_soisno(j)*1000., 0.)
+ wliq_soisno(j) = wliq_soisno(j) - wresi(j)
+ ENDIF
+ ENDDO
+
+ wetwat = wetwat + sum(wresi)
+
+ IF (wetwat > wetwatmax) THEN
+ wdsrf = wetwat - wetwatmax
+ wetwat = wetwatmax
+ wa = 0.
+ ELSEIF (wetwat < 0) THEN
+ wa = wetwat
+ wdsrf = 0.
+ wetwat = 0.
+ ELSE
+ wdsrf = 0.
+ wa = 0.
+ ENDIF
+
+ frcsat = 1.
+
+#ifndef CatchLateralFlow
+ IF (wdsrf > pondmx) THEN
+ rsur = (wdsrf - pondmx) / deltim
+ wdsrf = pondmx
+ ELSE
+ rsur = 0.
+ ENDIF
+ rnof = rsur
+ rsur_se = rsur
+ rsur_ie = 0.
+#endif
+ ENDIF
+
+ENDIF
+
+ END SUBROUTINE WATER_VSF
+
+
+ SUBROUTINE snowwater (lb,deltim,ssi,wimp, &
+ pg_rain,qseva,qsdew,qsubl,qfros, &
+ dz_soisno,wice_soisno,wliq_soisno,qout_snowb)
+
+!-----------------------------------------------------------------------
+! Original author: Yongjiu Dai, /09/1999; /04/2014
+!
+! Water flow within snow is computed by an explicit and non-physical based
+! scheme, which permits a part of liquid water over the holding capacity (a
+! tentative value is used, i.e., equal to 0.033*porosity) to percolate into the
+! underlying layer, except the case of that the porosity of one of the two
+! neighboring layers is less than 0.05, the zero flow is assumed. The water
+! flow out of the bottom snow pack will participate as the input of the soil
+! water and runoff.
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o ! physical constant
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ lb ! lower bound of array
+
+ real(r8), intent(in) :: &
+ deltim, &! seconds in a time step (s)
+ ssi, &! irreducible water saturation of snow
+ wimp, &! water impermeable if porosity less than wimp
+ dz_soisno(lb:0), &! layer thickness (m)
+
+ pg_rain, &! rainfall after removal of interception (mm h2o/s)
+ qseva, &! ground surface evaporation rate (mm h2o/s)
+ qsdew, &! ground surface dew formation (mm h2o /s) [+]
+ qsubl, &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros ! surface dew added to snow pack (mm h2o /s) [+]
+
+ real(r8), intent(inout) :: &
+ wice_soisno(lb:0),&! ice lens (kg/m2)
+ wliq_soisno(lb:0) ! liquid water (kg/m2)
+
+ real(r8), intent(out) :: &
+ qout_snowb ! rate of water out of snow bottom (mm/s)
+
+!-------------------------- Local Variables ----------------------------
+ integer j ! k do loop/array indices
+
+ real(r8) :: &
+ qin, &! water flow into the element (mm/s)
+ qout, &! water flow out of the element (mm/s)
+ zwice, &! the sum of ice mass of snow cover (kg/m2)
+ wgdif, &! ice mass after minus sublimation
+ vol_liq(lb:0), &! partial volume of liquid water in layer
+ vol_ice(lb:0), &! partial volume of ice lens in layer
+ eff_porosity(lb:0) ! effective porosity = porosity - vol_ice
+
+!=======================================================================
+! renew the mass of ice lens (wice_soisno) and liquid (wliq_soisno) in the
+! surface snow layer, resulted by sublimation (frost) / evaporation (condense)
+
+ wgdif = wice_soisno(lb) + (qfros - qsubl)*deltim
+ wice_soisno(lb) = wgdif
+ IF(wgdif < 0.)THEN
+ wice_soisno(lb) = 0.
+ wliq_soisno(lb) = wliq_soisno(lb) + wgdif
+ ENDIF
+
+ wliq_soisno(lb) = wliq_soisno(lb) + (pg_rain + qsdew - qseva)*deltim
+ IF (wliq_soisno(lb) < 0.) THEN
+ wice_soisno(lb) = wice_soisno(lb) + wliq_soisno(lb)
+ wice_soisno(lb) = max(wice_soisno(lb), 0.)
+ wliq_soisno(lb) = 0.
+ ENDIF
+
+! Porosity and partial volume
+ DO j = lb, 0
+ vol_ice(j) = min(1., wice_soisno(j)/(dz_soisno(j)*denice))
+ eff_porosity(j) = max(0.01, 1. - vol_ice(j))
+ vol_liq(j) = min(eff_porosity(j), wliq_soisno(j)/(dz_soisno(j)*denh2o))
+ ENDDO
+
+! Capillary force within snow could be two or more orders of magnitude less
+! than those of gravity, this term may be ignored. Here we could keep the
+! gravity term only. The general expression for water flow is "K * ss**3",
+! however, no effective parameterization for "K". Thus, a very simple treatment
+! (not physical based) is introduced: when the liquid water of layer exceeds
+! the layer's holding capacity, the excess meltwater adds to the underlying
+! neighbor layer.
+
+ qin = 0.
+ DO j= lb, 0
+ wliq_soisno(j) = wliq_soisno(j) + qin
+
+ IF(j <= -1)THEN
+ ! no runoff over snow surface, just ponding on surface
+ IF(eff_porosity(j) mss_bcphi(j)) THEN
+ qout_bc_phi = mss_bcphi(j)
+ ENDIF
+ mss_bcphi(j) = mss_bcphi(j) - qout_bc_phi
+ qin_bc_phi = qout_bc_phi
+
+ ! BCPHO:
+ ! 1. flux with meltwater:
+ qout_bc_pho = qout*scvng_fct_mlt_bcpho*(mss_bcpho(j)/mss_liqice(j))
+ IF (qout_bc_pho > mss_bcpho(j)) THEN
+ qout_bc_pho = mss_bcpho(j)
+ ENDIF
+ mss_bcpho(j) = mss_bcpho(j) - qout_bc_pho
+ qin_bc_pho = qout_bc_pho
+
+ ! OCPHI:
+ ! 1. flux with meltwater:
+ qout_oc_phi = qout*scvng_fct_mlt_ocphi*(mss_ocphi(j)/mss_liqice(j))
+ IF (qout_oc_phi > mss_ocphi(j)) THEN
+ qout_oc_phi = mss_ocphi(j)
+ ENDIF
+ mss_ocphi(j) = mss_ocphi(j) - qout_oc_phi
+ qin_oc_phi = qout_oc_phi
+
+ ! OCPHO:
+ ! 1. flux with meltwater:
+ qout_oc_pho = qout*scvng_fct_mlt_ocpho*(mss_ocpho(j)/mss_liqice(j))
+ IF (qout_oc_pho > mss_ocpho(j)) THEN
+ qout_oc_pho = mss_ocpho(j)
+ ENDIF
+ mss_ocpho(j) = mss_ocpho(j) - qout_oc_pho
+ qin_oc_pho = qout_oc_pho
+
+ ! DUST 1:
+ ! 1. flux with meltwater:
+ qout_dst1 = qout*scvng_fct_mlt_dst1*(mss_dst1(j)/mss_liqice(j))
+ IF (qout_dst1 > mss_dst1(j)) THEN
+ qout_dst1 = mss_dst1(j)
+ ENDIF
+ mss_dst1(j) = mss_dst1(j) - qout_dst1
+ qin_dst1 = qout_dst1
+
+ ! DUST 2:
+ ! 1. flux with meltwater:
+ qout_dst2 = qout*scvng_fct_mlt_dst2*(mss_dst2(j)/mss_liqice(j))
+ IF (qout_dst2 > mss_dst2(j)) THEN
+ qout_dst2 = mss_dst2(j)
+ ENDIF
+ mss_dst2(j) = mss_dst2(j) - qout_dst2
+ qin_dst2 = qout_dst2
+
+ ! DUST 3:
+ ! 1. flux with meltwater:
+ qout_dst3 = qout*scvng_fct_mlt_dst3*(mss_dst3(j)/mss_liqice(j))
+ IF (qout_dst3 > mss_dst3(j)) THEN
+ qout_dst3 = mss_dst3(j)
+ ENDIF
+ mss_dst3(j) = mss_dst3(j) - qout_dst3
+ qin_dst3 = qout_dst3
+
+ ! DUST 4:
+ ! 1. flux with meltwater:
+ qout_dst4 = qout*scvng_fct_mlt_dst4*(mss_dst4(j)/mss_liqice(j))
+ IF (qout_dst4 > mss_dst4(j)) THEN
+ qout_dst4 = mss_dst4(j)
+ ENDIF
+ mss_dst4(j) = mss_dst4(j) - qout_dst4
+ qin_dst4 = qout_dst4
+! Aerosol Fluxes (Jan. 07, 2023)
+
+ ENDDO
+
+ qout_snowb = qout/deltim
+
+
+! Aerosol Fluxes (Jan. 07, 2023)
+! Compute aerosol fluxes through snowpack and aerosol deposition fluxes into top layere
+!-----------------------------------------------------------------------
+! set aerosol deposition fluxes from forcing array
+! The forcing array is either set from an external file
+! or from fluxes received from the atmosphere model
+#ifdef MODAL_AER
+ ! Mapping for modal aerosol scheme where within-hydrometeor and
+ ! interstitial aerosol fluxes are differentiated. Here, "phi"
+ ! flavors of BC and OC correspond to within-hydrometeor
+ ! (cloud-borne) aerosol, and "pho" flavors are interstitial
+ ! aerosol. "wet" and "dry" fluxes of BC and OC specified here are
+ ! purely diagnostic
+ !
+ ! NOTE: right now the macro 'MODAL_AER' is not defined anywhere, i.e.,
+ ! the below (modal aerosol scheme) is not available and can not be
+ ! active either. It depends on the specific input aerosol deposition
+ ! data which is suitable for modal scheme. [06/15/2023, Hua Yuan]
+
+ flx_bc_dep_phi = forc_aer(3)
+ flx_bc_dep_pho = forc_aer(1) + forc_aer(2)
+ flx_bc_dep = forc_aer(1) + forc_aer(2) + forc_aer(3)
+
+ flx_oc_dep_phi = forc_aer(6)
+ flx_oc_dep_pho = forc_aer(4) + forc_aer(5)
+ flx_oc_dep = forc_aer(4) + forc_aer(5) + forc_aer(6)
+
+ flx_dst_dep_wet1 = forc_aer(7)
+ flx_dst_dep_dry1 = forc_aer(8)
+ flx_dst_dep_wet2 = forc_aer(9)
+ flx_dst_dep_dry2 = forc_aer(10)
+ flx_dst_dep_wet3 = forc_aer(11)
+ flx_dst_dep_dry3 = forc_aer(12)
+ flx_dst_dep_wet4 = forc_aer(13)
+ flx_dst_dep_dry4 = forc_aer(14)
+ flx_dst_dep = forc_aer(7) + forc_aer(8) + forc_aer(9) + &
+ forc_aer(10) + forc_aer(11) + forc_aer(12) + &
+ forc_aer(13) + forc_aer(14)
+#else
+ ! Original mapping for bulk aerosol deposition. phi and pho BC/OC
+ ! species are distinguished in model, other fluxes (e.g., dry and
+ ! wet BC/OC) are purely diagnostic.
+
+ flx_bc_dep_phi = forc_aer(1) + forc_aer(3)
+ flx_bc_dep_pho = forc_aer(2)
+ flx_bc_dep = forc_aer(1) + forc_aer(2) + forc_aer(3)
+
+ flx_oc_dep_phi = forc_aer(4) + forc_aer(6)
+ flx_oc_dep_pho = forc_aer(5)
+ flx_oc_dep = forc_aer(4) + forc_aer(5) + forc_aer(6)
+
+ flx_dst_dep_wet1 = forc_aer(7)
+ flx_dst_dep_dry1 = forc_aer(8)
+ flx_dst_dep_wet2 = forc_aer(9)
+ flx_dst_dep_dry2 = forc_aer(10)
+ flx_dst_dep_wet3 = forc_aer(11)
+ flx_dst_dep_dry3 = forc_aer(12)
+ flx_dst_dep_wet4 = forc_aer(13)
+ flx_dst_dep_dry4 = forc_aer(14)
+ flx_dst_dep = forc_aer(7) + forc_aer(8) + forc_aer(9) + &
+ forc_aer(10) + forc_aer(11) + forc_aer(12) + &
+ forc_aer(13) + forc_aer(14)
+#endif
+
+ ! aerosol deposition fluxes into top layer
+ ! This is done after the inter-layer fluxes so that some aerosol
+ ! is in the top layer after deposition, and is not immediately
+ ! washed out before radiative calculations are done
+
+ mss_bcphi(lb) = mss_bcphi(lb) + (flx_bc_dep_phi*deltim)
+ mss_bcpho(lb) = mss_bcpho(lb) + (flx_bc_dep_pho*deltim)
+ mss_ocphi(lb) = mss_ocphi(lb) + (flx_oc_dep_phi*deltim)
+ mss_ocpho(lb) = mss_ocpho(lb) + (flx_oc_dep_pho*deltim)
+
+ mss_dst1(lb) = mss_dst1(lb) + (flx_dst_dep_dry1 + flx_dst_dep_wet1)*deltim
+ mss_dst2(lb) = mss_dst2(lb) + (flx_dst_dep_dry2 + flx_dst_dep_wet2)*deltim
+ mss_dst3(lb) = mss_dst3(lb) + (flx_dst_dep_dry3 + flx_dst_dep_wet3)*deltim
+ mss_dst4(lb) = mss_dst4(lb) + (flx_dst_dep_dry4 + flx_dst_dep_wet4)*deltim
+
+#ifdef MODAL_AER
+ !
+ ! Transfer BC and OC from the within-ice state to the external
+ ! state based on snow sublimation and re-freezing of liquid water.
+ ! Re-freezing effect is inactived by default because of
+ ! uncertainty in how this process operates.
+
+ DO j= lb, 0
+ IF (j >= lb) THEN
+ IF (j == lb) THEN
+ ! snow that has sublimated [kg/m2] (top layer only)
+ subsnow = max(0._r8, (qsubl*deltim))
+
+ ! fraction of layer mass that has sublimated:
+ IF ((wliq_soisno(j) + wice_soisno(j)) > 0._r8) THEN
+ frc_sub = subsnow / (wliq_soisno(j) + wice_soisno(j))
+ ELSE
+ frc_sub = 0._r8
+ ENDIF
+ ELSE
+ ! prohibit sublimation effect to operate on sub-surface layers:
+ frc_sub = 0._r8
+ ENDIF
+
+ ! fraction of layer mass transformed (sublimation only)
+ frc_transfer = frc_sub
+
+ ! cap the fraction at 1
+ IF (frc_transfer > 1._r8) THEN
+ frc_transfer = 1._r8
+ ENDIF
+
+ ! transfer proportionate mass of BC and OC:
+ dm_int = mss_bcphi(j)*frc_transfer
+ mss_bcphi(j) = mss_bcphi(j) - dm_int
+ mss_bcpho(j) = mss_bcpho(j) + dm_int
+
+ dm_int = mss_ocphi(j)*frc_transfer
+ mss_ocphi(j) = mss_ocphi(j) - dm_int
+ mss_ocpho(j) = mss_ocpho(j) + dm_int
+
+ ENDIF
+ ENDDO
+#endif
+! Aerosol Fluxes (Jan. 7, 2023)
+
+ END SUBROUTINE SnowWater_snicar
+
+
+ SUBROUTINE soilwater(patchtype,nl_soil,deltim,wimp,smpmin,&
+ qinfl,etr,z_soisno,dz_soisno,zi_soisno,&
+ t_soisno,vol_liq,vol_ice,smp,hk,icefrac,eff_porosity,&
+ porsl,hksati,bsw,psi0,rootr,rootflux,&
+ zwt,dwat,qcharge)
+
+!-----------------------------------------------------------------------
+! Original author: Yongjiu Dai, 09/1999, 04/2014, 07/2014
+!
+! some new parameterization are added, which are based on CLM4.5
+!
+! Soil moisture is predicted from a 10-layer model (as with soil
+! temperature), in which the vertical soil moisture transport is governed
+! by infiltration, runoff, gradient diffusion, gravity, and root
+! extraction through canopy transpiration. The net water applied to the
+! surface layer is the snowmelt plus precipitation plus the throughfall
+! of canopy dew minus surface runoff and evaporation.
+!
+! The vertical water flow in an unsaturated porous media is described by
+! Darcy's law, and the hydraulic conductivity and the soil negative
+! potential vary with soil water content and soil texture based on the work
+! of Clapp and Hornberger (1978) and Cosby et al. (1984). The equation is
+! integrated over the layer thickness, in which the time rate of change in
+! water mass must equal the net flow across the bounding interface, plus the
+! rate of internal source or sink. The terms of water flow across the layer
+! interfaces are linearly expanded by using first-order Taylor expansion.
+! The equations result in a tridiagonal system equation.
+!
+! Note: length units here are all millimeter
+! (in temperature SUBROUTINE uses same soil layer
+! structure required but lengths are m)
+!
+! Richards equation:
+!
+! d wat d d psi
+! ----- = -- [ k(----- - 1) ] + S
+! dt dz dz
+!
+! where: wat = volume of water per volume of soil (mm**3/mm**3)
+! psi = soil matrix potential (mm)
+! dt = time step (s)
+! z = depth (mm) (positive downward)
+! dz = thickness (mm)
+! qin = inflow at top (mm h2o /s)
+! qout= outflow at bottom (mm h2o /s)
+! s = source/sink flux (mm h2o /s)
+! k = hydraulic conductivity (mm h2o /s)
+!
+! d qin d qin
+! qin[n+1] = qin[n] + -------- d wat(j-1) + --------- d wat(j)
+! d wat(j-1) d wat(j)
+! ==================|=================
+! < qin
+!
+! d wat(j)/dt * dz = qin[n+1] - qout[n+1] + S(j)
+!
+! > qout
+! ==================|=================
+! d qout d qout
+! qout[n+1] = qout[n] + --------- d wat(j) + --------- d wat(j+1)
+! d wat(j) d wat(j+1)
+!
+!
+! Solution: linearize k and psi about d wat and use tridiagonal
+! system of equations to solve for d wat,
+! where for layer j
+!
+!
+! r_j = a_j [d wat_j-1] + b_j [d wat_j] + c_j [d wat_j+1]
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: grav,hfus,tfrz,denh2o,denice
+ USE MOD_Utils
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer , intent(in) :: patchtype ! land patch type
+ integer , intent(in) :: nl_soil ! number of soil layers
+ real(r8), intent(in) :: deltim ! land model time step (sec)
+ real(r8), intent(in) :: wimp ! water impermeable if porosity less than wimp
+ real(r8), intent(in) :: smpmin ! restriction for min of soil potential (mm)
+
+ real(r8), intent(in) :: qinfl ! infiltration (mm H2O /s)
+ real(r8), intent(in) :: etr ! vegetation transpiration (mm H2O/s) (+ = to atm)
+
+ real(r8), intent(in) :: z_soisno (1:nl_soil) ! layer depth (m)
+ real(r8), intent(in) :: dz_soisno(1:nl_soil) ! layer thickness (m)
+ real(r8), intent(in) :: zi_soisno(0:nl_soil) ! interface level below a "z" level (m)
+
+ real(r8), intent(in) :: t_soisno (1:nl_soil) ! soil temperature (Kelvin)
+ real(r8), intent(in) :: vol_liq (1:nl_soil) ! liquid volumetric water content
+ real(r8), intent(in) :: vol_ice (1:nl_soil) ! ice volumetric water content
+ real(r8), intent(in) :: icefrac (1:nl_soil)
+ real(r8), intent(in) :: eff_porosity(1:nl_soil) ! effective porosity = porosity - vol_ice
+
+ real(r8), intent(in) :: porsl (1:nl_soil) ! volumetric soil water at saturation (porosity)
+ real(r8), intent(in) :: hksati (1:nl_soil) ! hydraulic conductivity at saturation (mm H2O /s)
+ real(r8), intent(in) :: bsw (1:nl_soil) ! Clapp and Hornberger "b"
+ real(r8), intent(in) :: psi0 (1:nl_soil) ! minimum soil suction (mm) [-]
+ real(r8), intent(in) :: rootr (1:nl_soil) ! effective fraction of roots in each soil layer
+ real(r8), intent(in) :: rootflux(1:nl_soil)! root uptake from different layers, all layers add to transpiration
+ real(r8), intent(in) :: zwt ! the depth from ground (soil) surface to water table [m]
+
+ real(r8), intent(out) :: dwat(1:nl_soil) ! change of soil water [m3/m3]
+ real(r8), intent(out) :: qcharge ! aquifer recharge rate (positive to aquifer) (mm/s)
+ real(r8), intent(out) :: smp(1:nl_soil) ! soil matrix potential [mm]
+ real(r8), intent(out) :: hk (1:nl_soil) ! hydraulic conductivity [mm h2o/s]
+
+!-------------------------- Local Variables ----------------------------
+
+ integer :: j ! do loop indices
+ real(r8) :: amx(1:nl_soil) ! "a" left off diagonal of tridiagonal matrix
+ real(r8) :: bmx(1:nl_soil) ! "b" diagonal column for tridiagonal matrix
+ real(r8) :: cmx(1:nl_soil) ! "c" right off diagonal tridiagonal matrix
+ real(r8) :: rmx(1:nl_soil) ! "r" forcing term of tridiagonal matrix
+ real(r8) :: zmm(1:nl_soil) ! layer depth [mm]
+ real(r8) :: dzmm(1:nl_soil) ! layer thickness [mm]
+ real(r8) :: zimm(0:nl_soil) ! layer interface depth [mm]
+ real(r8) :: den(1:nl_soil) ! used in calculating qin, qout
+ real(r8) :: alpha(1:nl_soil) ! used in calculating qin, qout
+ real(r8) :: qin(1:nl_soil) ! flux of water into soil layer [mm h2o/s]
+ real(r8) :: qout(1:nl_soil) ! flux of water out of soil layer [mm h2o/s]
+ real(r8) :: dqidw0(1:nl_soil) ! d(qin)/d(vol_liq(j-1))
+ real(r8) :: dqidw1(1:nl_soil) ! d(qin)/d(vol_liq(j))
+ real(r8) :: dqodw1(1:nl_soil) ! d(qout)/d(vol_liq(j))
+ real(r8) :: dqodw2(1:nl_soil) ! d(qout)/d(vol_liq(j+1))
+ real(r8) :: dsmpdw(1:nl_soil) ! d(smp)/d(vol_liq)
+ real(r8) :: s_node ! soil wetness
+ real(r8) :: s1 ! "s" at interface of layer
+ real(r8) :: s2 ! k*s**(2b+2)
+ real(r8) :: dhkdw1(1:nl_soil) ! d(hk)/d(vol_liq(j))
+ real(r8) :: dhkdw2(1:nl_soil) ! d(hk)/d(vol_liq(j+1))
+ real(r8) :: imped(1:nl_soil) !
+ real(r8) :: errorw ! mass balance error for this time step
+
+ integer :: jwt ! index of the soil layer right above the water table (-)
+
+ real(r8), parameter :: e_ice=6.0 !soil ice impedance factor
+!-----------------------------------------------------------------------
+
+ !compute jwt index
+ ! The layer index of the first unsaturated layer,
+ ! i.e., the layer right above the water table
+
+ jwt = nl_soil
+ ! allow jwt to equal zero when zwt is in top layer
+ DO j = 1, nl_soil
+ IF(zwt <= zi_soisno(j)) THEN
+ jwt = j-1
+ EXIT
+ ENDIF
+ ENDDO
+
+ ! Because the depths in this routine are in mm, use local
+ ! variable arrays instead of pointers
+ DO j = 1, nl_soil
+ zmm(j) = z_soisno(j)*1000.
+ dzmm(j) = dz_soisno(j)*1000.
+ zimm(j) = zi_soisno(j)*1000.
+ ENDDO
+
+ zimm(0) = 0.0
+
+ ! Compute matric potential and derivative based on liquid water content only
+ DO j = 1, nl_soil
+ IF(DEF_USE_PLANTHYDRAULICS .and. (patchtype/=1 .or. (.not.DEF_URBAN_RUN)))THEN
+ IF(t_soisno(j)>=tfrz) THEN
+ IF(porsl(j)<1.e-6)THEN ! bed rock
+ s_node = 0.001
+ smp(j) = psi0(j)
+ dsmpdw(j) = 0.
+ ELSE
+ s_node = max(vol_liq(j)/porsl(j),0.01)
+ s_node = min(1.0,s_node)
+ smp(j) = psi0(j)*s_node**(-bsw(j))
+ smp(j) = max(smpmin,smp(j))
+ dsmpdw(j) = -bsw(j)*smp(j)/(s_node*porsl(j))
+ ENDIF
+ ELSE
+ ! when ice is present, the matric potential is only related to temperature
+ ! by (Fuchs et al., 1978: Soil Sci. Soc. Amer. J. 42(3):379-385)
+ ! Unit 1 Joule = 1 (kg m2/s2), J/kg /(m/s2) ==> m ==> 1e3 mm
+ smp(j) = 1.e3 * 0.3336e6/9.80616*(t_soisno(j)-tfrz)/t_soisno(j)
+ smp(j) = max(smpmin, smp(j)) ! Limit soil suction
+ dsmpdw(j) = 0.
+ ENDIF
+ ELSE
+ IF(t_soisno(j)>=tfrz) THEN
+ IF(porsl(j)<1.e-6)THEN ! bed rock
+ s_node = 0.001
+ smp(j) = psi0(j)
+ dsmpdw(j) = 0.
+ ELSE
+ s_node = max(vol_liq(j)/porsl(j),0.01)
+ s_node = min(1.0,s_node)
+ smp(j) = psi0(j)*s_node**(-bsw(j))
+ smp(j) = max(smpmin,smp(j))
+ dsmpdw(j) = -bsw(j)*smp(j)/(s_node*porsl(j))
+ ENDIF
+ ELSE
+ ! when ice is present, the matric potential is only related to temperature
+ ! by (Fuchs et al., 1978: Soil Sci. Soc. Amer. J. 42(3):379-385)
+ ! Unit 1 Joule = 1 (kg m2/s2), J/kg /(m/s2) ==> m ==> 1e3 mm
+ smp(j) = 1.e3 * 0.3336e6/9.80616*(t_soisno(j)-tfrz)/t_soisno(j)
+ smp(j) = max(smpmin, smp(j)) ! Limit soil suction
+ dsmpdw(j) = 0.
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! Hydraulic conductivity and soil matric potential and their derivatives
+ DO j = 1, nl_soil
+
+ IF(j < nl_soil)THEN
+ den(j) = (zmm(j+1)-zmm(j))
+ alpha(j) = (smp(j+1)-smp(j))/den(j) - 1.
+ ELSE
+ den(j) = 0. ! not used
+ alpha(j) = 0. ! not used
+ ENDIF
+
+ IF((eff_porosity(j) < wimp) .or. (eff_porosity(min(nl_soil,j+1)) < wimp) &
+ .or. (vol_liq(j) <= 1.e-3))THEN
+ imped(j) = 0.
+ hk(j) = 0.
+ dhkdw1(j) = 0.
+ dhkdw2(j) = 0.
+ ELSE
+ ! The average conductivity between two heterogeneous medium layers (j and j + 1),
+ ! are computed using different methods
+ IF(j < nl_soil)THEN
+! Method I: UPSTREAM MEAN
+ IF(alpha(j) <= 0.)THEN
+ hk(j) = hksati(j) * (vol_liq(j)/porsl(j))**(2.*bsw(j)+3.)
+ dhkdw1(j) = hksati(j) * (2.*bsw(j)+3.)*(vol_liq(j)/porsl(j))**(2.*bsw(j)+2.)/porsl(j)
+ dhkdw2(j) = 0.
+ ELSE
+ hk(j) = hksati(j+1) * (vol_liq(j+1)/porsl(j+1))**(2.*bsw(j+1)+3.)
+ dhkdw1(j) = 0.
+ dhkdw2(j) = hksati(j+1) * (2.*bsw(j+1)+3.)*(vol_liq(j+1)/porsl(j+1))**(2.*bsw(j+1)+2.)/porsl(j+1)
+ ENDIF
+! Method II:
+ ! ! The harmonic averaging of the saturated conductivities
+ ! hksat_interface = (zmm(j+1)-zmm(j))/((zimm(j)-zmm(j))/hksati(j)+(zmm(j+1)-zimm(j))/hksati(j+1))
+ ! s1 = (vol_liq(j)*(zimm(j)-zmm(j)) + vol_liq(j+1)*(zmm(j+1)-zimm(j))) &
+ ! / (porsl(j)*(zimm(j)-zmm(j)) + porsl(j+1)*(zmm(j+1)-zimm(j)))
+ ! s1 = min(1.,s1)
+ ! s2 = hksat_interface*s1**(2.*bsw(j)+2.)
+ ! hk(j) = s1*s2
+ ! dhkdw1(j) = (2.*bsw(j)+3.)*s2*(zimm(j)-zmm(j))/(porsl(j)*(zimm(j)-zmm(j))+porsl(j+1)*(zmm(j+1)-zimm(j)))
+ ! dhkdw2(j) = (2.*bsw(j)+3.)*s2*(zmm(j+1)-zimm(j))/(porsl(j)*(zimm(j)-zmm(j))+porsl(j+1)*(zmm(j+1)-zimm(j)))
+
+ ELSE
+ hk(j) = hksati(j) * (vol_liq(j)/porsl(j))**(2.*bsw(j)+3.)
+ dhkdw1(j) = hksati(j) * (2.*bsw(j)+3.)*(vol_liq(j)/porsl(j))**(2.*bsw(j)+2.)/porsl(j)
+ dhkdw2(j) = 0.
+ ENDIF
+
+ ! replace fracice with impedance factor
+ imped(j)=10.**(-e_ice*(0.5*(icefrac(j)+icefrac(min(nl_soil,j+1)))))
+ hk(j) = imped(j) * hk(j)
+ dhkdw1(j) = imped(j) * dhkdw1(j)
+ dhkdw2(j) = imped(j) * dhkdw2(j)
+ ENDIF
+ ENDDO
+
+
+ ! Set up r, a, b, and c vectors for tridiagonal solution
+
+ ! Node j=1 (top)
+
+ j = 1
+ qin(j) = qinfl
+
+ qout(j) = -hk(j)*alpha(j)
+ dqodw1(j) = -(alpha(j)*dhkdw1(j) - hk(j)*dsmpdw(j)/den(j))
+ dqodw2(j) = -(alpha(j)*dhkdw2(j) + hk(j)*dsmpdw(j+1)/den(j))
+
+ amx(j) = 0.
+ bmx(j) = dzmm(j)/deltim + dqodw1(j)
+ cmx(j) = dqodw2(j)
+ IF(DEF_USE_PLANTHYDRAULICS .and. (patchtype/=1 .or. (.not.DEF_URBAN_RUN)))THEN
+ rmx(j) = qin(j) - qout(j) - rootflux(j)
+ ELSE
+ rmx(j) = qin(j) - qout(j) - etr*rootr(j)
+ ENDIF
+
+ ! Nodes j=2 to j=nl_soil-1
+
+ DO j = 2, nl_soil - 1
+ qin(j) = -hk(j-1)*alpha(j-1)
+ dqidw0(j) = -(alpha(j-1)*dhkdw1(j-1) - hk(j-1)*dsmpdw(j-1)/den(j-1))
+ dqidw1(j) = -(alpha(j-1)*dhkdw2(j-1) + hk(j-1)*dsmpdw(j)/den(j-1))
+
+ qout(j) = -hk(j)*alpha(j)
+ dqodw1(j) = -(alpha(j)*dhkdw1(j) - hk(j)*dsmpdw(j)/den(j))
+ dqodw2(j) = -(alpha(j)*dhkdw2(j) + hk(j)*dsmpdw(j+1)/den(j))
+
+ amx(j) = -dqidw0(j)
+ bmx(j) = dzmm(j)/deltim - dqidw1(j) + dqodw1(j)
+ cmx(j) = dqodw2(j)
+ IF(DEF_USE_PLANTHYDRAULICS .and. (patchtype/=1 .or. (.not.DEF_URBAN_RUN)))THEN
+ rmx(j) = qin(j) - qout(j) - rootflux(j)
+ ELSE
+ rmx(j) = qin(j) - qout(j) - etr*rootr(j)
+ ENDIF
+ ENDDO
+
+ ! Node j=nl_soil (bottom)
+
+ j = nl_soil
+ qin(j) = -hk(j-1)*alpha(j-1)
+ dqidw0(j) = -(alpha(j-1)*dhkdw1(j-1) - hk(j-1)*dsmpdw(j-1)/den(j-1))
+ dqidw1(j) = -(alpha(j-1)*dhkdw2(j-1) + hk(j-1)*dsmpdw(j)/den(j-1))
+
+ ! IF(j > jwt) THEN ! water table is in soil column
+ ! qout(j) = 0.
+ ! dqodw1(j) = 0.
+ ! dqodw2(j) = 0.
+ ! ELSE
+ qout(j) = hk(j)
+ dqodw1(j) = dhkdw1(j)
+ dqodw2(j) = 0.
+ ! ENDIF
+
+ amx(j) = -dqidw0(j)
+ bmx(j) = dzmm(j)/deltim - dqidw1(j) + dqodw1(j)
+ cmx(j) = dqodw2(j)
+ IF(DEF_USE_PLANTHYDRAULICS .and. (patchtype/=1 .or. (.not.DEF_URBAN_RUN)))THEN
+ rmx(j) = qin(j) - qout(j) - rootflux(j)
+ ELSE
+ rmx(j) = qin(j) - qout(j) - etr*rootr(j)
+ ENDIF
+
+ ! Solve for dwat
+
+ CALL tridia (nl_soil, amx, bmx, cmx, rmx, dwat )
+
+#if (defined CoLMDEBUG)
+ ! The mass balance error (mm) for this time step is
+ errorw = -deltim*(qin(1)-qout(nl_soil)-dqodw1(nl_soil)*dwat(nl_soil))
+ DO j = 1, nl_soil
+ IF(DEF_USE_PLANTHYDRAULICS .and. (patchtype/=1 .or. (.not.DEF_URBAN_RUN)))THEN
+ errorw = errorw+dwat(j)*dzmm(j)+rootflux(j)*deltim
+ ELSE
+ errorw = errorw+dwat(j)*dzmm(j)+etr*rootr(j)*deltim
+ ENDIF
+ ENDDO
+
+ IF(abs(errorw) > 1.e-3)THEN
+ write(6,*) 'mass balance error in time step =',errorw
+ ENDIF
+#endif
+
+ ! Recharge rate qcharge to groundwater (positive to aquifer)
+ qcharge = qout(nl_soil) + dqodw1(nl_soil)*dwat(nl_soil)
+
+
+ END SUBROUTINE soilwater
+
+
+ SUBROUTINE groundwater (nl_soil,deltim,pondmx,&
+ eff_porosity,icefrac,&
+ dz_soisno,zi_soisno,wice_soisno,wliq_soisno,&
+ porsl,psi0,bsw,zwt,wa,&
+ qcharge,rsubst)
+
+! -------------------------------------------------------------------------
+
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer , intent(in) :: nl_soil !
+ real(r8), intent(in) :: deltim ! land model time step (sec)
+ real(r8), intent(in) :: pondmx !
+
+ real(r8), intent(in) :: eff_porosity(1:nl_soil) ! effective porosity = porosity - vol_ice
+ real(r8), intent(in) :: icefrac(1:nl_soil) ! ice fraction (-)
+
+ real(r8), intent(in) :: dz_soisno (1:nl_soil) ! layer depth (m)
+ real(r8), intent(in) :: zi_soisno (0:nl_soil) ! interface level below a "z" level (m)
+ real(r8), intent(inout) :: wice_soisno(1:nl_soil) ! ice lens (kg/m2)
+ real(r8), intent(inout) :: wliq_soisno(1:nl_soil) ! liquid water (kg/m2)
+
+ real(r8), intent(in) :: porsl(1:nl_soil) ! volumetric soil water at saturation (porosity)
+ real(r8), intent(in) :: psi0(1:nl_soil) ! minimum soil suction (mm) [-]
+ real(r8), intent(in) :: bsw(1:nl_soil) ! Clapp and Hornberger "b"
+
+ real(r8), intent(inout) :: zwt ! the depth from ground (soil) surface to water table [m]
+ real(r8), intent(inout) :: wa ! water in the unconfined aquifer (mm)
+ real(r8), intent(in) :: qcharge ! aquifer recharge rate (positive to aquifer) (mm/s)
+ real(r8), intent(inout) :: rsubst ! subsurface runoff (positive = out of soil column) (mm H2O /s)
+
+!-------------------------- Local Variables ----------------------------
+ integer :: j ! indices
+ integer :: jwt ! index of the soil layer right above the water table (-)
+ real(r8) :: xs ! water needed to bring soil moisture to watmin (mm)
+ real(r8) :: dzmm(1:nl_soil) ! layer thickness (mm)
+ real(r8) :: xsi ! excess soil water above saturation at layer i (mm)
+ real(r8) :: xsia ! available pore space at layer i (mm)
+ real(r8) :: xs1 ! excess soil water above saturation at layer 1 (mm)
+ real(r8) :: ws ! summation of pore space of layers below water table (mm)
+ real(r8) :: s_node ! soil wetness (-)
+ real(r8) :: available_wliq_soisno ! available soil liquid water in a layer
+ real(r8) :: qcharge_tot !
+ real(r8) :: qcharge_layer !
+ real(r8) :: drainage !
+ real(r8) :: drainage_tot !
+ real(r8) :: drainage_layer !
+ real(r8) :: s_y !
+ real(r8) :: rous ! specific yield [-]
+
+ real(r8) :: wt
+ real(r8) :: wtsub
+ real(r8) :: dzsum
+ real(r8) :: icefracsum
+ real(r8) :: fracice_rsub
+ real(r8) :: imped
+
+
+ real(r8), parameter :: watmin = 0.01 ! Limit irreducible wrapping liquid water
+ ! a tunable constant
+ real(r8), parameter :: rsbmx = 5.0 ! baseflow coefficient [mm/s]
+ real(r8), parameter :: timean = 10.5 ! global mean topographic index
+
+! -------------------------------------------------------------------------
+
+! ! Convert layer thicknesses from m to mm
+
+ DO j = 1,nl_soil
+ dzmm(j) = dz_soisno(j)*1000.
+ ENDDO
+
+! ! The layer index of the first unsaturated layer,
+! ! i.e., the layer right above the water table
+
+ jwt = nl_soil
+ ! allow jwt to equal zero when zwt is in top layer
+ DO j = 1, nl_soil
+ IF(zwt <= zi_soisno(j)) THEN
+ jwt = j-1
+ EXIT
+ ENDIF
+ ENDDO
+
+!============================== QCHARGE =========================================
+! Water table changes due to qcharge
+! use analytical expression for aquifer specific yield
+ rous = porsl(nl_soil)*(1.-(1.-1.e3*zwt/psi0(nl_soil))**(-1./bsw(nl_soil)))
+ rous = max(rous,0.02)
+
+ wa = wa + qcharge*deltim
+!
+!---------------------------------------
+ ! water table is below the soil column
+ IF(jwt == nl_soil) THEN
+ zwt = max(0.,zwt - (qcharge*deltim)/1000./rous)
+ ELSE
+ ! water table within soil layers 1-9
+ ! try to raise water table to account for qcharge
+
+ qcharge_tot = qcharge * deltim
+
+ IF(qcharge_tot > 0.) THEN ! rising water table
+ DO j = jwt+1, 1,-1
+ ! use analytical expression for specific yield
+
+ s_y = porsl(j) * (1.-(1.-1.e3*zwt/psi0(j))**(-1./bsw(j)))
+ s_y=max(s_y,0.02)
+
+ qcharge_layer = min(qcharge_tot,(s_y*(zwt-zi_soisno(j-1))*1.e3))
+ qcharge_layer = max(qcharge_layer,0.)
+
+ zwt = max(0.,zwt - qcharge_layer/s_y/1000.)
+
+ qcharge_tot = qcharge_tot - qcharge_layer
+ IF (qcharge_tot <= 0.) EXIT
+ ENDDO
+ ELSE ! deepening water table (negative qcharge)
+ DO j = jwt+1, nl_soil
+ ! use analytical expression for specific yield
+ s_y = porsl(j) * (1.-(1.-1.e3*zwt/psi0(j))**(-1./bsw(j)))
+ s_y=max(s_y,0.02)
+ qcharge_layer = max(qcharge_tot,-(s_y*(zi_soisno(j) - zwt)*1.e3))
+ qcharge_layer = min(qcharge_layer,0.)
+ qcharge_tot = qcharge_tot - qcharge_layer
+
+ IF (qcharge_tot >= 0.) THEN
+ zwt = max(0.,zwt - qcharge_layer/s_y/1000.)
+ EXIT
+ ELSE
+ zwt = zi_soisno(j)
+ ENDIF
+ ENDDO
+ IF (qcharge_tot > 0.) zwt = max(0.,zwt - qcharge_tot/1000./rous)
+ ENDIF
+ ENDIF
+
+!-- Topographic runoff ----------------------------------------------------------
+ IF (DEF_Runoff_SCHEME == 0) THEN
+ CALL SubsurfaceRunoff_TOPMOD (nl_soil, icefrac, dz_soisno, zi_soisno, zwt, rsubst)
+ ENDIF
+
+ drainage = rsubst
+
+ ! dzsum = 0.
+ ! icefracsum = 0.
+ ! DO j = max(jwt,1), nl_soil
+ ! dzsum = dzsum + dzmm(j)
+ ! icefracsum = icefracsum + icefrac(j) * dzmm(j)
+ ! ENDDO
+ ! ! add ice impedance factor to baseflow
+ ! fracice_rsub = max(0.,exp(-3.*(1.-(icefracsum/dzsum)))-exp(-3.))/(1.0-exp(-3.))
+ ! imped = max(0.,1.-fracice_rsub)
+ ! drainage = imped * 5.5e-3 * exp(-2.5*zwt) ! drainage (positive = out of soil column)
+
+!-- Water table is below the soil column ----------------------------------------
+ IF(jwt == nl_soil) THEN
+ wa = wa - drainage * deltim
+ zwt = max(0.,zwt + (drainage * deltim)/1000./rous)
+ wliq_soisno(nl_soil) = wliq_soisno(nl_soil) + max(0.,(wa-5000.))
+ wa = min(wa, 5000.)
+ ELSE
+!-- Water table within soil layers 1-9 ------------------------------------------
+!============================== RSUB_TOP =========================================
+ !-- Now remove water via drainage
+ drainage_tot = - drainage * deltim
+ DO j = jwt+1, nl_soil
+ ! use analytical expression for specific yield
+ s_y = porsl(j) * ( 1. - (1.-1.e3*zwt/psi0(j))**(-1./bsw(j)))
+ s_y = max(s_y,0.02)
+
+ drainage_layer = max(drainage_tot, -(s_y*(zi_soisno(j)-zwt)*1.e3))
+ drainage_layer = min(drainage_layer,0.)
+ wliq_soisno(j) = wliq_soisno(j) + drainage_layer
+
+ drainage_tot = drainage_tot - drainage_layer
+
+ IF(drainage_tot >= 0.)THEN
+ zwt = max(0.,zwt - drainage_layer/s_y/1000.)
+ EXIT
+ ELSE
+ zwt = zi_soisno(j)
+ ENDIF
+ ENDDO
+
+!-- Remove residual drainage ------------------------------------------------
+ zwt = max(0.,zwt - drainage_tot/1000./rous)
+ wa = wa + drainage_tot
+
+!-- Recompute jwt ---------------------------------------------------------------
+ ! allow jwt to equal zero when zwt is in top layer
+ jwt = nl_soil
+ DO j = 1, nl_soil
+ IF(zwt <= zi_soisno(j)) THEN
+ jwt = j-1
+ EXIT
+ ENDIF
+ ENDDO
+
+ ENDIF ! end of jwt IF construct
+
+ zwt = max(0.0,zwt)
+ zwt = min(80.,zwt)
+
+ rsubst = drainage
+
+
+ ! Correction [1]
+ ! NON-physically based correction on wliq_soisno
+ ! excessive water above saturation added to the above unsaturated layer like a bucket
+ ! IF column over saturated, excess water goes to runoff
+
+ DO j = nl_soil,2,-1
+ xsi = max(wliq_soisno(j)-eff_porosity(j)*dzmm(j),0.)
+ wliq_soisno(j) = min(eff_porosity(j)*dzmm(j), wliq_soisno(j))
+ wliq_soisno(j-1) = wliq_soisno(j-1) + xsi
+ ENDDO
+
+ ! 12/2022, note by yuan: a potential bug below which needs check,
+ ! if wice_soisno(1) > pondmx + porsl*dzmm, so xs1>0, in that case,
+ ! wliq_soisno(1) will be nagtive, and xs1 is positive.
+ xs1 = wliq_soisno(1) - (pondmx+porsl(1)*dzmm(1)-wice_soisno(1))
+ IF(xs1 > 0.)THEN
+ wliq_soisno(1) = pondmx+porsl(1)*dzmm(1)-wice_soisno(1)
+ ELSE
+ xs1 = 0.
+ ENDIF
+
+ rsubst = rsubst + xs1 / deltim
+
+
+ ! Correction [2]
+ ! NON-physically based correction on wliq_soisno
+ ! Limit wliq_soisno to be greater than or equal to watmin.
+ ! Get water needed to bring wliq_soisno equal watmin from lower layer.
+ ! If insufficient water in soil layers, get from aquifer water
+
+ xs = 0.
+ DO j = 1, nl_soil
+ IF (wliq_soisno(j) < 0.) THEN
+ xs = xs + wliq_soisno(j)
+ wliq_soisno(j) = 0.
+ ENDIF
+ ENDDO
+
+ ! Sub-surface runoff and drainage
+ rsubst = rsubst + xs/deltim
+ IF (rsubst < 0.) THEN
+ wa = wa + rsubst*deltim
+ rsubst = 0.
+ ENDIF
+
+! DO j = 1, nl_soil-1
+! IF (wice_soisno(j)*wice_soisno(j+1) < 1.e-6)THEN
+! IF (wliq_soisno(j) < watmin) THEN
+! xs = watmin - wliq_soisno(j)
+! ! deepen water table IF water is passed from below zwt layer
+! IF(j == jwt) THEN
+! zwt = max(0.,zwt + xs/eff_porosity(j)/1000.)
+! ENDIF
+! ELSE
+! xs = 0.
+! ENDIF
+! wliq_soisno(j ) = wliq_soisno(j ) + xs
+! wliq_soisno(j+1) = wliq_soisno(j+1) - xs
+! ENDIF
+! ENDDO
+
+! ! Get water for bottom layer from layers above if possible
+! IF(wliq_soisno(nl_soil) < watmin)THEN
+! xs = watmin-wliq_soisno(nl_soil)
+! DO j = nl_soil-1, 1, -1
+! available_wliq_soisno = max(wliq_soisno(j)-watmin-xs,0.)
+! IF(available_wliq_soisno >= xs)THEN
+! wliq_soisno(nl_soil) = wliq_soisno(nl_soil) + xs
+! wliq_soisno(j ) = wliq_soisno(j ) - xs
+! xs = 0.
+! EXIT
+! ELSE
+! wliq_soisno(nl_soil) = wliq_soisno(nl_soil) + available_wliq_soisno
+! wliq_soisno(j ) = wliq_soisno(j ) - available_wliq_soisno
+! xs = xs - available_wliq_soisno
+! ENDIF
+! ENDDO
+! ELSE
+! xs = 0.
+! ENDIF
+
+! ! Needed in case there is no water to be found
+! wliq_soisno(nl_soil) = wliq_soisno(nl_soil) + xs
+
+! ! Sub-surface runoff and drainage
+! rsubst = rsubst - xs/deltim
+
+ END SUBROUTINE groundwater
+
+
+END MODULE MOD_SoilSnowHydrology
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilSurfaceResistance.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilSurfaceResistance.F90
new file mode 100644
index 0000000000..2807042e88
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilSurfaceResistance.F90
@@ -0,0 +1,319 @@
+#include
+
+MODULE MOD_SoilSurfaceResistance
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate the soil surface resistance with multiple parameterization
+! schemes
+!
+! Created by Zhuo Liu and Hua Yuan, 06/2023
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+! !USE
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: SoilSurfaceResistance
+
+ ! soil-gas diffusivity schemes:
+ ! 1: BBC (Buckingham-Burdine-Campbell Model), Moldrup et al., 1999.
+ ! 2: P_WLR (Penman Water Linear Reduction Model), Moldrup et al., 2000
+ ! 3: MI_WLR (Millington Water Linear Reduction Model), Moldrup et al., 2000
+ ! 4: MA_WLR (Marshal Water Linear Reduction Model), Moldrup et al., 2000
+ ! 5: M_Q, Millington and Quirk, 1961
+ ! 6: 3POE (Three-Porosity-Encased), Moldrup et al., 2005
+#ifdef Campbell_SOIL_MODEL
+ integer, parameter :: soil_gas_diffusivity_scheme = 1
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ integer, parameter :: soil_gas_diffusivity_scheme = 6
+#endif
+
+
+CONTAINS
+!-----------------------------------------------------------------------
+
+ SUBROUTINE SoilSurfaceResistance (nl_soil,forc_rhoair,hksati,porsl,psi0, &
+#ifdef Campbell_SOIL_MODEL
+ bsw, &
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm, &
+#endif
+ dz_soisno,t_soisno,wliq_soisno,wice_soisno,fsno,qg,rss)
+
+!=======================================================================
+! !DESCRIPTION:
+! Main SUBROUTINE to CALL soil resistance model
+! - Options for soil surface resistance schemes
+! 1: SL14, Swenson and Lawrence (2014)
+! 2: SZ09, Sakaguchi and Zeng (2009)
+! 3: TR13, Tang and Riley (2013)
+! 4: LP92, Lee and Pielke (1992)
+! 5: S92, Sellers et al (1992)
+!
+! NOTE: Support for both Campbell and VG soil parameters.
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denice, denh2o
+ USE MOD_Namelist, only: DEF_RSS_SCHEME
+ USE MOD_Hydro_SoilFunction
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ nl_soil ! upper bound of array
+
+ real(r8), intent(in) :: &
+ forc_rhoair, &! density air [kg/m**3]
+ hksati (1:nl_soil), &! hydraulic conductivity at saturation [mm h2o/s]
+ porsl (1:nl_soil), &! soil porosity [-]
+ psi0 (1:nl_soil), &! saturated soil suction [mm] (NEGATIVE)
+#ifdef Campbell_SOIL_MODEL
+ bsw (1:nl_soil), &! clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r (1:nl_soil), &! residual moisture content [-]
+ ! a parameter corresponding approximately to the inverse of the air-entry value
+ alpha_vgm (1:nl_soil), &
+ n_vgm (1:nl_soil), &! pore-connectivity parameter [dimensionless]
+ L_vgm (1:nl_soil), &! a shape parameter [dimensionless]
+ ! saturation at the air entry value in the classical vanGenuchten model [-]
+ sc_vgm (1:nl_soil), &
+ ! a scaling factor by using air entry value in the Mualem model [-]
+ fc_vgm (1:nl_soil), &
+#endif
+ dz_soisno (1:nl_soil), &! layer thickness [m]
+ t_soisno (1:nl_soil), &! soil/snow skin temperature [K]
+ wliq_soisno (1:nl_soil), &! liquid water [kg/m2]
+ wice_soisno (1:nl_soil), &! ice lens [kg/m2]
+ fsno, &! fractional snow cover [-]
+ qg ! ground specific humidity [kg/kg]
+
+ real(r8), intent(out) :: &
+ rss ! soil surface resistance [s/m]
+
+!-------------------------- Local Variables ----------------------------
+
+ REAL(r8) :: &
+ wx, &! partial volume of ice and water of surface layer
+ vol_liq, &! water content by volume [m3/m3]
+ s_node, &! vol_liq/porosity
+ smp_node, &! matrix potential [m]
+ eff_porosity, &! effective porosity = porosity - vol_ice
+ aird, &! “air-dry” soil moisture value
+ d0, &! water vapor diffusivity in open air [m2/s]
+ eps, &! air filled pore space
+ dg, &! gaseous diffusivity [m2/s]
+ dsl, &! soil dry surface layer thickness [m]
+ dw, &! aqueous diffusivity [m2/s]
+ hk, &! hydraulic conductivity [m h2o/s]
+ m_vgm, &! pore-connectivity related parameter [dimensionless]
+ S, &! Van Genuchten relative saturation [-]
+ wfc, &! field capacity of the first layer soil
+ rg_1, &! inverse of vapor diffusion resistance [m/s]
+ rw_1, &! inverse of volatilization resistance [m/s]
+ rss_1, &! inverse of soil surface resistance [m/s]
+ tao, &! tortuosity of the vapor flow paths through the soil matrix
+ eps100, &! air-filled porosity at −1000 mm of water matric potential
+ fac, &! temporal variable for calculating wx/porsl
+ fac_fc, &! temporal variable for calculating wx/wfc
+ B ! bunsen solubility coefficient
+
+!-----------------------------------------------------------------------
+
+ ! calculate the top soil volumetric water content (m3/m3), soil matrix potential
+ ! and soil hydraulic conductivity
+ vol_liq = max(wliq_soisno(1),1.0e-6_r8)/(denh2o*dz_soisno(1))
+ s_node = min(1., vol_liq/porsl(1))
+
+ ! calculate effective soil porosity
+ eff_porosity = max(0.01_r8,porsl(1)-min(porsl(1), wice_soisno(1)/(dz_soisno(1)*denice)))
+
+
+#ifdef Campbell_SOIL_MODEL
+ smp_node = (psi0(1)/1000.)*s_node**(-bsw(1))
+ hk = (hksati(1)/1000.)*(vol_liq/porsl(1))**(2.*bsw(1)+3.)
+
+ ! calculate air free pore space
+ aird = porsl(1)*(psi0(1)/-1.e7_r8)**(1./bsw(1))
+#endif
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ smp_node = soil_psi_from_vliq (s_node*(porsl(1)-theta_r(1)) + theta_r(1), &
+ porsl(1), theta_r(1), psi0(1), &
+ 5, (/alpha_vgm(1), n_vgm(1), L_vgm(1), sc_vgm(1), fc_vgm(1)/))
+ hk = soil_hk_from_psi (smp_node, psi0(1), hksati(1), &
+ 5, (/alpha_vgm(1), n_vgm(1), L_vgm(1), sc_vgm(1), fc_vgm(1)/))
+
+ smp_node = smp_node/1000.
+ hk = hk/1000.
+
+ ! calculate air free pore space
+ aird = soil_vliq_from_psi (-1.e7_r8, porsl(1), theta_r(1), psi0(1), &
+ 5, (/alpha_vgm(1), n_vgm(1), L_vgm(1), sc_vgm(1), fc_vgm(1)/))
+#endif
+
+ ! D0 : 2.12e-5 unit: m2 s-1
+ ! ref1: CLM5 Documentation formula (5.81)
+ ! ref2: Sakaguchi and Zeng, 2009
+ ! ref3: Tang and Riley, 2013. Figure 2, 3, 4, and 5.
+ d0 = 2.12e-5*(t_soisno(1)/273.15)**1.75
+ eps = porsl(1) - aird
+
+
+ SELECTCASE (soil_gas_diffusivity_scheme)
+
+ ! 1: BBC
+ CASE (1)
+#ifdef Campbell_SOIL_MODEL
+ tao = eps*eps*(eps/porsl(1))**(3._r8/max(3._r8,bsw(1)))
+#endif
+
+ ! 2: P_WLR
+ CASE (2)
+ tao = 0.66*eps*(eps/porsl(1))
+
+ ! 3: MI_WLR
+ CASE (3)
+ tao = eps**(4._r8/3._r8)*(eps/porsl(1))
+
+ ! 4: MA_WLR
+ CASE (4)
+ tao = eps**(3./2.)*(eps/porsl(1))
+
+ ! 5: M_Q
+ CASE (5)
+ tao = eps**(4._r8/3._r8)*(eps/porsl(1))**(2.0_r8)
+
+ ! 6: 3POE
+ CASE (6)
+#ifdef Campbell_SOIL_MODEL
+ eps100 = porsl(1) - porsl(1)*(psi0(1)/-1000.)**(1./bsw(1))
+#endif
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ eps100 = porsl(1) - soil_vliq_from_psi (-1000., porsl(1), theta_r(1), psi0(1), &
+ 5, (/alpha_vgm(1), n_vgm(1), L_vgm(1), sc_vgm(1), fc_vgm(1)/))
+#endif
+ tao = porsl(1)*porsl(1)*(eps/porsl(1))**(2.+log(eps100**0.25_r8)/log(eps100/porsl(1)))
+
+ ENDSELECT
+
+
+ ! calculate gas and water diffusivity (dg and dw)
+ dg = d0*tao
+
+ !NOTE: dw is only for TR13 scheme
+#ifdef Campbell_SOIL_MODEL
+ ! TR13, Eq.(A5):
+ dw = -hk*bsw(1)*smp_node/vol_liq
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ ! TR13, Eqs. (A2), (A7), (A8) and (A10):
+ ! dw = -hk*(m-1)/(k*m*(theta_s-theta_r))*S**(-1/m)*(1-S**(1/m))**(-m)
+ ! where k=alpha_vgm, S=(1+(-k*smp_node)**(n))**(-m), m=m_vgm=1-1/n_vgm
+ m_vgm = 1. - 1./n_vgm(1)
+ S = (1. + (- alpha_vgm(1)*smp_node)**(n_vgm(1)))**(-m_vgm)
+ dw = -hk*(m_vgm-1.)/(alpha_vgm(1)*m_vgm*(porsl(1)-theta_r(1))) &
+ * S**(-1./m_vgm)*(1.-S**(1./m_vgm))**(-m_vgm)
+#endif
+
+ SELECTCASE (DEF_RSS_SCHEME)
+
+!-----------------------------------------------------------------------
+ ! calculate rss by SL14
+ CASE (1)
+ dsl = dz_soisno(1)*max(1.e-6_r8,(0.8*eff_porosity - vol_liq)) &
+ /max(1.e-6_r8,(0.8*porsl(1)- aird))
+
+ dsl = max(dsl,0._r8)
+ dsl = min(dsl,0.2_r8)
+
+ rss = dsl/dg
+
+!-----------------------------------------------------------------------
+ ! calculate rss by SZ09
+ CASE (2)
+ dsl = dz_soisno(1)*(exp((1._r8 - vol_liq/porsl(1))**5) - 1._r8)/ (exp(1._r8) - 1._r8)
+ dsl = min(dsl,0.2_r8)
+ dsl = max(dsl,0._r8)
+
+ rss = dsl/dg
+
+!-----------------------------------------------------------------------
+ ! calculate rss by TR13
+ CASE (3)
+ ! TR13, Eq. (11) and Eq. (12):
+ B = denh2o/(qg*forc_rhoair)
+ ! TR13, Eq. (13):
+ rg_1 = 2.0_r8*dg*eps/dz_soisno(1)
+ rw_1 = 2.0_r8*dw*B*vol_liq/dz_soisno(1)
+ rss_1 = rg_1 + rw_1
+ rss = 1.0/rss_1
+
+!-----------------------------------------------------------------------
+ ! LP92 beta scheme
+ CASE (4)
+ wx = (max(wliq_soisno(1),1.e-6)/denh2o+wice_soisno(1)/denice)/dz_soisno(1)
+ fac = min(1._r8, wx/porsl(1))
+ fac = max(fac , 0.001_r8)
+#ifdef Campbell_SOIL_MODEL
+ wfc = porsl(1)*(0.1/(86400.*hksati(1)))**(1./(2.*bsw(1)+3.))
+ !NOTE: CoLM wfc = (-339.9/soil_psi_s_l(ipatch))**(-1.0*soil_lambda_l(ipatch))
+ ! * soil_theta_s_l(ipatch)
+ !wfc = porsl(1)*(-3399._r8/psi0(1))**(-1./bsw(1))
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ wfc = theta_r(1)+(porsl(1)-theta_r(1))*(1+(alpha_vgm(1)*339.9)**n_vgm(1))**(1.0/n_vgm(1)-1)
+#endif
+
+ ! Lee and Pielke 1992 beta
+ IF (wx < wfc ) THEN !when water content of ths top layer is less than that at F.C.
+ fac_fc = min(1._r8, wx/wfc)
+ fac_fc = max(fac_fc,0.001_r8)
+ rss = 0.25_r8*(1._r8 - cos(fac_fc*3.1415926))**2._r8
+ ELSE !when water content of ths top layer is more than that at F.C.
+ rss = 1._r8
+ ENDIF
+
+!-----------------------------------------------------------------------
+ ! Sellers, 1992
+ CASE (5)
+ wx = (max(wliq_soisno(1),1.e-6)/denh2o+wice_soisno(1)/denice)/dz_soisno(1)
+ fac = min(1._r8, wx/porsl(1))
+ fac = max(fac , 0.001_r8)
+ !rss = exp(8.206-4.255*fac) !original Sellers (1992)
+ rss = exp(8.206-6.0*fac) !adjusted Sellers (1992) to decrease rss
+ !for wet soil according to Noah-MP v5
+ ENDSELECT
+
+!-----------------------------------------------------------------------
+ ! account for snow fractional cover for rss
+ IF (DEF_RSS_SCHEME .ne. 4) THEN
+ ! with 1/rss = fsno/rss_snow + (1-fsno)/rss_soil,
+ ! assuming rss_snow = 1, so rss is calibrated as:
+ IF (1.-fsno+fsno*rss > 0.) THEN
+ rss = rss / (1.-fsno+fsno*rss)
+ ELSE
+ rss = 0.
+ ENDIF
+ rss = min(1.e6_r8,rss)
+ ENDIF
+
+ ! account for snow fractional cover for LP92 beta scheme
+ !NOTE: rss here is for soil beta value
+ IF (DEF_RSS_SCHEME .eq. 4) THEN
+ ! modify soil beta by snow cover, assuming soil beta for snow surface is 1.
+ rss = (1.-fsno)*rss + fsno
+ ENDIF
+
+ END Subroutine SoilSurfaceResistance
+
+END MODULE MOD_SoilSurfaceResistance
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilThermalParameters.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilThermalParameters.F90
new file mode 100644
index 0000000000..980ae7db1e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_SoilThermalParameters.F90
@@ -0,0 +1,524 @@
+#include
+
+MODULE MOD_SoilThermalParameters
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: hCapacity
+ PUBLIC :: hConductivity
+ PUBLIC :: soil_hcap_cond
+
+
+! PRIVATE MEMBER FUNCTIONS:
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE hCapacity (patchtype,lb,nl_soil,csol,porsl,wice_soisno,wliq_soisno,scv,dz_soisno,cv)
+
+
+!-----------------------------------------------------------------------
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! calculation of heat capacities of snow / soil layers the volumetric
+! heat capacity is calculated as a linear combination in terms of the
+! volumetric fraction of the constituent phases. Only used in urban
+! model. TODO: merge with SUBROUTINE soil_hcap_cond
+!
+! !REVISIONS:
+! 07/19/2014, Yongjiu Dai: treat the wetland as soil column instead of
+! water body.
+! 08/16/2014, Nan Wei: recalculate the heat capacity of soil layers
+! underneath the lake
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpice,cpliq
+ IMPLICIT NONE
+
+ integer, intent(in) :: lb ! lower bound of array
+ integer, intent(in) :: nl_soil ! upper bound of array
+ integer, intent(in) :: patchtype ! land patch type (0=soil, 1=urban, 2=wetland,
+ real(r8), intent(in) :: csol(1:nl_soil) ! heat capacity of soil soilds [J/(m3 K)]
+ real(r8), intent(in) :: porsl(1:nl_soil) ! soil porosity
+ real(r8), intent(in) :: wice_soisno(lb:nl_soil) ! ice lens [kg/m2]
+ real(r8), intent(in) :: wliq_soisno(lb:nl_soil) ! liquid water [kg/m2]
+ real(r8), intent(in) :: dz_soisno(lb:nl_soil) ! layer thickness [m]
+ real(r8), intent(in) :: scv ! snow water equivalent [mm]
+ real(r8), intent(out) :: cv(lb:nl_soil) ! heat capacity [J/(m2 K)]
+
+!-----------------------------------------------------------------------
+! Soil heat capacity, which from de Vires (1963)
+
+ IF(patchtype<=2 .or. patchtype==4)THEN ! soil ground and wetland and lake
+ cv(1:) = csol(1:)*(1.-porsl(1:))*dz_soisno(1:) &
+ + wice_soisno(1:)*cpice + wliq_soisno(1:)*cpliq
+ ELSE ! glacier/ice sheet
+ cv(1:) = wice_soisno(1:)*cpice + wliq_soisno(1:)*cpliq
+ ENDIF
+ IF(lb==1 .and. scv>0.) cv(1) = cv(1) + cpice*scv
+
+! Snow heat capacity
+ IF(lb<=0)THEN
+ cv(:0) = cpliq*wliq_soisno(:0) + cpice*wice_soisno(:0)
+ ENDIF
+
+ END SUBROUTINE hCapacity
+
+
+ SUBROUTINE hConductivity (patchtype,lb,nl_soil,&
+ dkdry,dksatu,porsl,dz_soisno,z_soisno,zi_soisno,&
+ t_soisno,wice_soisno,wliq_soisno,tk,tktopsoil)
+
+!-----------------------------------------------------------------------
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! calculation of thermal conductivities of snow / soil layers The
+! thermal conductivity of soil is computed from the algorithm of
+! Johansen (as reported by Farouki 1981), and of snow is from the
+! formulation used in SNTHERM (Jordan 1991).
+!
+! The thermal conductivities at the interfaces between two neighbor
+! layers (j, j+1) are derived from an assumption that the flux across
+! the interface is equal to that from the node j to the interface and
+! the flux from the interface to the node j+1.
+!
+! Only used in urban model. TODO: merge with subroutine soil_hcap_cond
+!
+! !REVISIONS:
+! 07/19/2014, Yongjiu Dai: treat the wetland as soil column instead of
+! water body.
+! 08/16/2014, Nan Wei: recalculate the heat conductivity of soil layers
+! underneath the lake
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: denh2o,denice,tfrz,tkwat,tkice,tkair
+ IMPLICIT NONE
+
+ integer, intent(in) :: lb !lower bound of array
+ integer, intent(in) :: nl_soil !upper bound of array
+ integer, intent(in) :: patchtype !land patch type (0=soil, 1=urban, 2=wetland,
+ !3=land ice, 4=deep lake, 5=shallow lake)
+ real(r8), intent(in) :: dkdry(1:nl_soil) !thermal conductivity for dry soil [W/m-K]
+ real(r8), intent(in) :: dksatu(1:nl_soil) !Thermal conductivity of saturated soil [W/m-K]
+ real(r8), intent(in) :: porsl(1:nl_soil) !fractional volume between soil grains=1.-dmvol
+ real(r8), intent(in) :: dz_soisno(lb:nl_soil) !layer thickness [m]
+ real(r8), intent(in) :: z_soisno(lb:nl_soil) !node depth [m]
+ real(r8), intent(in) :: zi_soisno(lb-1:nl_soil) !interface depth [m]
+ real(r8), intent(in) :: t_soisno(lb:nl_soil) !Nodal temperature [K]
+ real(r8), intent(in) :: wice_soisno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(in) :: wliq_soisno(lb:nl_soil) !liquid water [kg/m2]
+
+ real(r8), intent(out) :: tk(lb:nl_soil) !thermal conductivity [W/(m K)]
+ real(r8), optional, intent(out) :: tktopsoil
+
+! local
+ real(r8) rhosnow ! partial density of water (ice + liquid)
+ real(r8) dksat ! thermal conductivity for saturated soil (j/(k s m))
+ real(r8) dke ! kersten number
+ real(r8) fl ! fraction of liquid or unfrozen water to total water
+ real(r8) satw ! relative total water content of soil.
+ real(r8) thk(lb:nl_soil) ! thermal conductivity of layer
+ real(r8) xicevol
+
+ integer i
+
+!-----------------------------------------------------------------------
+! Thermal conductivity of soil from Farouki (1981),
+ DO i = 1, nl_soil
+
+ IF(patchtype<=2 .or. patchtype==4)THEN !soil ground, wetland and lake
+ thk(i) = dkdry(i) !rock or dry soil
+
+ IF(porsl(i)>1.e-05 .and. (wice_soisno(i)+wliq_soisno(i)) > 0.0)THEN
+ satw = (wliq_soisno(i)/denh2o+wice_soisno(i)/denice)/(dz_soisno(i)*porsl(i))
+ satw = min(1., satw)
+ IF(satw>.1e-6)THEN
+ IF (patchtype==4) satw = 1.
+ fl = wliq_soisno(i)/(wice_soisno(i)+wliq_soisno(i))
+ IF(t_soisno(i) >= tfrz) THEN ! Unfrozen soil
+ dke = log10(satw) + 1.0
+ dke = max(dke, 0.)
+ dksat = dksatu(i)
+ ELSE ! Frozen soil
+ dke = satw
+ dksat = dksatu(i)*(2.29/0.57)**((1.-fl)*porsl(i))
+ ENDIF
+ thk(i) = dke*dksat + (1.-dke)*dkdry(i)
+ IF (patchtype==4) THEN
+ satw = (wliq_soisno(i)/denh2o+wice_soisno(i)/denice)/(dz_soisno(i)*porsl(i))
+ IF(satw > 1.0)THEN
+ xicevol = (satw-1.0)*porsl(i)
+ thk(i) = (thk(i) + xicevol*tkice)/(1.0 + xicevol)/(1.0 + xicevol)
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+ IF(present(tktopsoil))tktopsoil = thk(1)
+ ELSEIF (patchtype == 3)THEN ! glacier
+ thk(i) = tkwat
+ IF(t_soisno(i)=lb) THEN
+ tk(i) = thk(i)
+ ENDIF
+ ENDIF
+! - END -
+ ENDDO
+ tk(nl_soil) = 0.
+
+ END SUBROUTINE hConductivity
+
+ SUBROUTINE soil_hcap_cond(vf_gravels_s,vf_om_s,vf_sand_s,vf_pores_s,&
+ wf_gravels_s,wf_sand_s,k_solids,&
+ csol,kdry,ksat_u,ksat_f,&
+ BA_alpha,BA_beta,&
+ temperature,vf_water,vf_ice,hcap,thk)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Calculate bulk soil heat capacity and soil thermal conductivity with
+! 8 optional schemes The default soil thermal conductivity scheme is
+! the fourth one (Balland V. and P. A. Arp, 2005)
+!
+! !REFERENCES:
+! Dai et al.,2019: Evaluation of Soil Thermal Conductivity Schemes for
+! Use in Land Surface Modeling J. of Advances in Modeling Earth
+! Systems, DOI: 10.1029/2019MS001723
+!
+! !Original author: Yongjiu Dai, 02/2018/
+!
+! !REVISIONS:
+! 06/2018, Nan Wei: add to CoLM/main
+! 09/2022, Nan Wei: add soil thermal conductivity of Hailong He (Yan &
+! He et al., 2019)
+! -----------------------------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Const_Physical,only:tfrz
+ USE MOD_Namelist
+
+ IMPLICIT NONE
+ real(r8), intent(in) :: vf_gravels_s ! volumetric fraction of gravels within soil solids
+ real(r8), intent(in) :: vf_om_s ! volumetric fraction of organic matter within soil solids
+ real(r8), intent(in) :: vf_sand_s ! volumetric fraction of sand within soil soilds
+ real(r8), intent(in) :: vf_pores_s ! volumetric pore space of the soil
+
+ real(r8), intent(in) :: wf_gravels_s ! gravimetric fraction of gravels
+ real(r8), intent(in) :: wf_sand_s ! gravimetric fraction of sand within soil soilds
+ real(r8), intent(in) :: k_solids ! thermal conductivity of soil solids
+
+ real(r8), intent(in) :: temperature !
+ real(r8), intent(in) :: vf_water !
+ real(r8), intent(in) :: vf_ice !
+
+ real(r8), intent(in) :: csol ! heat capacity of dry soil [J/(m3 K)]
+ real(r8), intent(in) :: kdry ! thermal conductivity for dry soil [W/m/K]
+ real(r8), intent(in) :: ksat_u ! thermal conductivity of unfrozen saturated soil [W/m/K]
+ real(r8), intent(in) :: ksat_f ! thermal conductivity of frozen saturated soil [W/m/K]
+ real(r8), intent(in) :: BA_alpha ! alpha in Balland and Arp(2005) thermal conductivity scheme
+ real(r8), intent(in) :: BA_beta ! beta in Balland and Arp(2005) thermal conductivity scheme
+
+ real(r8), intent(out) :: hcap ! J/(m3 K)
+ real(r8), intent(out) :: thk ! W/(m K)
+
+ real(r8) c_water, c_ice
+ real(r8) a, kappa, alpha, beta
+ real(r8) aa,aaa,nwm,nw_nwm,x,ga,gc
+ integer i
+
+ real(r8) sr ! wetness or degree of saturation = (vf_water+vf_ice)/vf_pores_s
+ real(r8) ke ! Kersten number or normalized thermal conductivity
+ real(r8) k_air,k_water,k_ice
+
+! =========================================================================================
+! The heat capacity and thermal conductivity [J(m3 K)]
+! =========================================================================================
+!* c_water = 4.18e6 ! J/(m3 K)
+!* c_ice = 1.88e6 ! J/(m3 K)
+ c_water = 4.188e6 ! J/(m3 K) = 4188[J/(kg K)]*1000(kg/m3)
+ c_ice = 1.94153e6 ! J/(m3 K) = 2117.27[J/(kg K)]*917(kg/m3)
+
+ hcap = csol + vf_water*c_water + vf_ice*c_ice
+
+! -----------------------------------------------------------------------------------------
+! Setting
+! -----------------------------------------------------------------------------------------
+ k_air = 0.024 ! (W/m/K)
+ k_water = 0.57 ! (W/m/K)
+ k_ice = 2.29 ! (W/m/K)
+
+ a = vf_gravels_s + vf_sand_s
+
+ sr = (vf_water+vf_ice)/vf_pores_s
+! sr = max(1.0e-6, sr)
+ sr = min(1.0, sr)
+
+ IF(sr >= 1.0e-10) THEN
+ select CASE (DEF_THERMAL_CONDUCTIVITY_SCHEME)
+ CASE (1)
+! -----------------------------------------------------------------------------------------
+! [1] Oleson et al., 2013: Technical Description of version 4.5 of the Community Land Model
+! (CLM). NCAR/TN-503+STR (Section 6.3: Soil and Snow Thermal Properties)
+! -----------------------------------------------------------------------------------------
+ IF(temperature > tfrz)THEN ! Unfrozen soil
+ ke = log10(sr) + 1.0
+ ELSE ! Fozen or partially frozen soils
+ ke = sr
+ ENDIF
+
+ CASE (2)
+! -----------------------------------------------------------------------------------------
+! [2] Johansen O (1975): Thermal conductivity of soils. PhD Thesis. Trondheim, Norway:
+! University of Trondheim. US army Crops of Engineerings,
+! CRREL English Translation 637.
+! -----------------------------------------------------------------------------------------
+ IF(temperature > tfrz)THEN ! Unfrozen soils
+ IF(a > 0.4)THEN ! coarse-grained
+ ke = 0.7*log10(max(sr,0.05)) + 1.0
+ ELSE ! Fine-grained
+ ke = log10(max(sr,0.1)) + 1.0
+ ENDIF
+ ELSE ! Frozen or partially frozen soils
+ ke = sr
+ ENDIF
+
+ CASE (3)
+! -----------------------------------------------------------------------------------------
+! [3] Cote, J., and J.-M. Konrad (2005), A generalized thermal conductivity model for soils
+! and construction materials. Canadian Geotechnical Journal, 42(2): 443-458.
+! -----------------------------------------------------------------------------------------
+ IF(temperature > tfrz)THEN ! Unfrozen soils
+! kappa = Unfrozen
+! /gravels and coarse sand /4.60/
+! /medium and fine sands /3.55/
+! /silty and clayey soils /1.90/
+! /organic fibrous soils (peat)/0.60/
+ IF(a > 0.40)THEN
+ kappa = 4.60
+ ELSEIF(a > 0.25)THEN
+ kappa = 3.55
+ ELSEIF(a > 0.01)THEN
+ kappa = 1.90
+ ELSE
+ kappa = 0.60
+ ENDIF
+
+ ELSE ! Frozen or partially frozen soils
+! kappa = Frozen
+! /gravels and coarse sand /1.70/
+! /medium and fine sands /0.95/
+! /silty and clayey soils /0.85/
+! /organic fibrous soils (peat)/0.25/
+ IF(a > 0.40)THEN
+ kappa = 1.70
+ ELSEIF(a > 0.25)THEN
+ kappa = 0.95
+ ELSEIF(a > 0.01)THEN
+ kappa = 0.85
+ ELSE
+ kappa = 0.25
+ ENDIF
+ ENDIF
+ ke = kappa*sr/(1.0+(kappa-1.0)*sr)
+
+ CASE (4)
+! -----------------------------------------------------------------------------------------
+! [4] Balland V. and P. A. Arp, 2005: Modeling soil thermal conductivities over a wide
+! range of conditions. J. Environ. Eng. Sci. 4: 549-558.
+! be careful in specifying all k affecting fractions as VOLUME FRACTION,
+! whether these fractions are part of the bulk volume, the pore space, or the solid space.
+! -----------------------------------------------------------------------------------------
+ IF(temperature > tfrz)THEN ! Unfrozen soil
+! alpha = 0.24 ! adjustable parameter
+! beta = 18.1 ! adjustable parameter
+
+ ke = sr**(0.5*(1.0+vf_om_s-BA_alpha*vf_sand_s-vf_gravels_s)) &
+ * ((1.0/(1.0+exp(-BA_beta*sr)))**3-((1.0-sr)/2.0)**3)**(1.0-vf_om_s)
+ ELSE ! Frozen or partially frozen soils
+ ke = sr**(1.0+vf_om_s)
+ ENDIF
+
+ CASE (5)
+! -----------------------------------------------------------------------------------------
+! [5] Lu et al., 2007: An improved model for predicting soil thermal conductivity from
+! water content at room temperature. Soil Sci. Soc. Am. J. 71:8-14
+! -----------------------------------------------------------------------------------------
+ IF(a > 0.4)THEN ! Coarse-textured soils = soils with sand fractions >40 (%)
+ alpha = 0.728
+ beta = 1.165
+ ELSE ! Fine-textured soils = soils with sand fractions <40 (%)
+ alpha = 0.37
+ beta = 1.29
+ ENDIF
+
+ IF(temperature > tfrz)THEN ! Unfrozen soils
+ ke = exp(alpha*(1.0-sr**(alpha-beta)))
+ ELSE ! Frozen or partially frozen soils
+ ke = sr
+ ENDIF
+ END select
+ ELSE
+ ke = 0.0
+ ENDIF
+
+ IF (DEF_THERMAL_CONDUCTIVITY_SCHEME >= 1 .and. DEF_THERMAL_CONDUCTIVITY_SCHEME <=5) THEN
+ ke = max(ke, 0.0)
+ ke = min(ke, 1.0)
+ IF(temperature > tfrz)THEN ! Unfrozen soil
+ thk = (ksat_u-kdry)*ke + kdry
+ ELSE ! Frozen or partially frozen soils
+ thk = (ksat_f-kdry)*ke + kdry
+ ENDIF
+ ENDIF
+
+ IF(DEF_THERMAL_CONDUCTIVITY_SCHEME == 6) THEN
+! -----------------------------------------------------------------------------------------
+! [6] Series-Parallel Models (Tarnawski and Leong, 2012)
+! -----------------------------------------------------------------------------------------
+ a = wf_gravels_s+wf_sand_s
+
+! a fitting parameter of the soil solid uniform passage
+ aa = 0.0237 - 0.0175*a**3
+
+! a fitting parameter of a minuscule portion of soil water (nw)
+! plus a minuscule portion of soil air (na)
+ nwm = 0.088 - 0.037*a**3
+
+! the degree of saturation of the minuscle pore space
+ x = 0.6 - 0.3*a**3
+ IF(sr < 1.0e-6)THEN
+ nw_nwm = 0.0
+ ELSE
+ nw_nwm = exp(1.0-sr**(-x))
+ ENDIF
+
+ IF(temperature > tfrz)THEN ! Unfrozen soil
+ thk = k_solids*aa + (1.0-vf_pores_s-aa+nwm)**2 &
+ / ((1.0-vf_pores_s-aa)/k_solids+nwm/(k_water*nw_nwm+k_air*(1.0-nw_nwm))) &
+ + k_water*(vf_pores_s*sr-nwm*nw_nwm) &
+ + k_air*(vf_pores_s*(1.0-sr)-nwm*(1.0-nw_nwm))
+ ELSE
+ thk = k_solids*aa + (1.0-vf_pores_s-aa+nwm)**2 &
+ / ((1.0-vf_pores_s-aa)/k_solids+nwm/(k_ice*nw_nwm+k_air*(1.0-nw_nwm))) &
+ + k_ice*(vf_pores_s*sr-nwm*nw_nwm) &
+ + k_air*(vf_pores_s*(1.0-sr)-nwm*(1.0-nw_nwm))
+ ENDIF
+ ENDIF
+
+ IF(DEF_THERMAL_CONDUCTIVITY_SCHEME == 7) THEN
+! -----------------------------------------------------------------------------------------
+! [7] Thermal properties of soils, in Physics of Plant Environment,
+! ed. by W.R. van Wijk (North-Holland, Amsterdam, 1963), pp. 210-235
+! -----------------------------------------------------------------------------------------
+ IF(sr*vf_pores_s <= 0.09)THEN
+ ga = 0.013+0.944*sr*vf_pores_s
+ ELSE
+ ga = 0.333 - (1.-sr)*vf_pores_s/vf_pores_s*(0.333-0.035)
+ ENDIF
+ gc = 1.0-2.0*ga
+
+ IF(temperature > tfrz)THEN ! Unfrozen soil
+ aa = (2.0/(1.0+(k_air/k_water-1.0)*ga) & ! the shape factor
+ + 1.0/(1.0+(k_air/k_water-1.0)*gc))/3.0
+ aaa = (2.0/(1.0+(k_solids/k_water-1.0)*0.125) & ! the shape factor
+ + 1.0/(1.0+(k_solids/k_water-1.0)*(1.0-2.0*0.125)))/3.0
+
+ thk = (sr*vf_pores_s*k_water + (1.-sr)*vf_pores_s*aa*k_air + &
+ (1.-vf_pores_s)*aaa*k_solids) &
+ / (sr*vf_pores_s + (1.-sr)*vf_pores_s*aa + (1.-vf_pores_s)*aaa)
+ ELSE
+ aa = (2.0/(1.0+(k_air/k_ice-1.0)*ga) & ! the shape factor
+ + 1.0/(1.0+(k_air/k_ice-1.0)*gc))/3.0
+ aaa = (2.0/(1.0+(k_solids/k_ice-1.0)*0.125) & ! the shape factor
+ + 1.0/(1.0+(k_solids/k_ice-1.0)*(1.0-2.0*0.125)))/3.0
+
+ thk = (sr*vf_pores_s*k_ice + (1.-sr)*vf_pores_s*aa*k_air + &
+ (1.-vf_pores_s)*aaa*k_solids) &
+ / (sr*vf_pores_s + (1.-sr)*vf_pores_s*aa + (1.-vf_pores_s)*aaa)
+ ENDIF
+ ENDIF
+
+ IF(DEF_THERMAL_CONDUCTIVITY_SCHEME == 8) THEN
+! -----------------------------------------------------------------------------------------
+! [8] Yan & He et al., 2019: A generalized model for estimating effective soil thermal conductivity
+! based on the Kasubuchi algorithm, Geoderma, Vol 353, 227-242
+! -----------------------------------------------------------------------------------------
+ beta = -0.303*ksat_u - 0.201*wf_sand_s + 1.532
+ IF(vf_water > 0.01)THEN
+ ke = (1+(vf_pores_s/beta)**(-1.0*beta))/(1+(vf_water/beta)**(-1.0*beta))
+ ELSE
+ ke = 0.0
+ ENDIF
+
+ ke = max(ke, 0.0)
+ ke = min(ke, 1.0)
+
+ IF(temperature > tfrz)THEN ! Unfrozen soil
+ thk = (ksat_u-kdry)*ke + kdry
+ ELSE ! Frozen or partially frozen soils
+ thk = (ksat_f-kdry)*ke + kdry
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE soil_hcap_cond
+
+END MODULE MOD_SoilThermalParameters
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Thermal.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Thermal.F90
new file mode 100644
index 0000000000..bc5571c3d1
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Thermal.F90
@@ -0,0 +1,1392 @@
+#include
+
+MODULE MOD_Thermal
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: THERMAL
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE THERMAL (ipatch ,patchtype,is_dry_lake,lb ,deltim ,&
+ trsmx0 ,zlnd ,zsno ,csoilc ,&
+ dewmx ,capr ,cnfac ,vf_quartz ,&
+ vf_gravels ,vf_om ,vf_sand ,wf_gravels ,&
+ wf_sand ,csol ,porsl ,psi0 ,&
+#ifdef Campbell_SOIL_MODEL
+ bsw ,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r ,alpha_vgm ,n_vgm ,L_vgm ,&
+ sc_vgm ,fc_vgm , &
+#endif
+ k_solids ,dksatu ,dksatf ,dkdry ,&
+ BA_alpha ,BA_beta ,lai ,laisun ,&
+ laisha ,sai ,htop ,hbot ,&
+ sqrtdi ,rootfr ,rstfacsun_out ,rstfacsha_out ,&
+ rss ,gssun_out ,gssha_out ,assimsun_out ,&
+ etrsun_out ,assimsha_out ,etrsha_out ,&
+!photosynthesis and plant hydraulic variables
+ effcon ,vmax25 ,c3c4 ,hksati ,smp ,hk ,&
+ kmax_sun ,kmax_sha ,kmax_xyl ,kmax_root ,&
+ psi50_sun ,psi50_sha ,psi50_xyl ,psi50_root ,&
+ ck ,vegwp ,gs0sun ,gs0sha ,&
+!Ozone stress variables
+ o3coefv_sun ,o3coefv_sha ,o3coefg_sun ,o3coefg_sha ,&
+ lai_old ,o3uptakesun ,o3uptakesha ,forc_ozone ,&
+!end ozone stress variables
+!Ozone WUE stomata model parameter
+ lambda ,&! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+!End WUE stomata model parameter
+ slti ,hlti ,shti ,hhti ,&
+ trda ,trdm ,trop ,g1 ,&
+ g0 ,gradm ,binter ,extkn ,&
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_rhoair ,&
+ forc_psrf ,forc_pco2m ,forc_hpbl ,forc_po2m ,&
+ coszen ,parsun ,parsha ,sabvsun ,&
+ sabvsha ,sabg ,sabg_soil ,sabg_snow ,&
+ frl ,extkb ,extkd ,thermk ,&
+ fsno ,sigf ,dz_soisno ,z_soisno ,&
+ zi_soisno ,tleaf ,t_soisno ,wice_soisno ,&
+ wliq_soisno ,ldew ,ldew_rain ,ldew_snow ,&
+ fwet_snow ,scv ,snowdp ,imelt ,&
+ taux ,tauy ,fsena ,fevpa ,&
+ lfevpa ,fsenl ,fevpl ,etr ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ rootr ,rootflux ,qseva ,qsdew ,&
+ qsubl ,qfros ,qseva_soil ,qsdew_soil ,&
+ qsubl_soil ,qfros_soil ,qseva_snow ,qsdew_snow ,&
+ qsubl_snow ,qfros_snow ,sm ,tref ,&
+ qref ,trad ,rst ,assim ,&
+ respc ,errore ,emis ,z0m ,&
+ zol ,rib ,ustar ,qstar ,&
+ tstar ,fm ,fh ,fq ,&
+ pg_rain ,pg_snow ,t_precip ,qintr_rain ,&
+ qintr_snow ,snofrz ,sabg_snow_lyr )
+
+!=======================================================================
+! this is the main subroutine to execute the calculation
+! of thermal processes and surface fluxes
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002
+!
+! FLOW DIAGRAM FOR THERMAL.F90
+!
+! THERMAL ===> qsadv
+! GroundFluxes
+! eroot |dewfraction
+! LeafTemperature | |qsadv
+! LeafTemperaturePC | ----------> |moninobukini
+! |moninobuk
+! |MOD_AssimStomataConductance
+!
+! GroundTemperature ----------> meltf
+!
+!
+! !REVISIONS:
+! 08/2019, Hua Yuan: added initial codes for PFT and Plant Community
+! (PC) vegetation classification processes
+!
+! 01/2021, Nan Wei: added variables passing of plant hydraulics and
+! precipitation sensible heat with canopy and ground for PFT
+! and Plant Community (PC)
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_PFT
+ USE MOD_Const_Physical, only: denh2o,roverg,hvap,hsub,rgas,cpair,&
+ stefnc,denice,tfrz,vonkar,grav,cpliq,cpice
+ USE MOD_FrictionVelocity
+ USE MOD_Eroot
+ USE MOD_GroundFluxes
+ USE MOD_LeafTemperature
+ USE MOD_LeafTemperaturePC
+ USE MOD_GroundTemperature
+ USE MOD_Qsadv
+ USE MOD_SoilSurfaceResistance
+ USE MOD_Vars_TimeVariables, only: qsfc
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT, only: patch_pft_s, patch_pft_e
+ USE MOD_Vars_TimeInvariants, only: patchclass
+ USE MOD_Vars_TimeVariables, only: &
+ lai_enftemp, lai_enfboreal, lai_dnfboreal, lai_ebftrop, lai_ebftemp, lai_dbftrop, lai_dbftemp, &
+ lai_dbfboreal, lai_ebstemp, lai_dbstemp, lai_dbsboreal, lai_c3arcgrass, lai_c3grass, lai_c4grass
+ USE MOD_Vars_PFTimeInvariants
+ USE MOD_Vars_PFTimeVariables
+ USE MOD_Vars_1DPFTFluxes
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ USE MOD_Hydro_SoilFunction, only: soil_psi_from_vliq
+#endif
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS, DEF_RSS_SCHEME, DEF_SPLIT_SOILSNOW, &
+ DEF_USE_LCT,DEF_USE_PFT,DEF_USE_PC,DEF_PC_CROP_SPLIT
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ integer, intent(in) :: &
+ ipatch, &! patch index
+ lb, &! lower bound of array
+ patchtype ! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=glacier/ice sheet, 4=land water bodies)
+ logical, intent(in) :: is_dry_lake
+
+ real(r8), intent(inout) :: &
+ sai ! stem area index [-]
+ real(r8), intent(in) :: &
+ deltim, &! model time step [second]
+ trsmx0, &! max transpiration for moist soil+100% veg. [mm/s]
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+ csoilc, &! drag coefficient for soil under canopy [-]
+ dewmx, &! maximum dew
+ capr, &! tuning factor to turn first layer T into surface T
+ cnfac, &! Crank Nicholson factor between 0 and 1
+
+ ! soil physical parameters
+ vf_quartz (1:nl_soil), &! volumetric fraction of quartz within mineral soil
+ vf_gravels(1:nl_soil), &! volumetric fraction of gravels
+ vf_om (1:nl_soil), &! volumetric fraction of organic matter
+ vf_sand (1:nl_soil), &! volumetric fraction of sand
+ wf_gravels(1:nl_soil), &! gravimetric fraction of gravels
+ wf_sand (1:nl_soil), &! gravimetric fraction of sand
+ csol (1:nl_soil), &! heat capacity of soil solids [J/(m3 K)]
+ porsl (1:nl_soil), &! soil porosity [-]
+ psi0 (1:nl_soil), &! soil water suction, negative potential [mm]
+#ifdef Campbell_SOIL_MODEL
+ bsw(1:nl_soil), &! clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r (1:nl_soil), &! residual moisture content [-]
+ alpha_vgm (1:nl_soil), &! a parameter corresponding approximately to the inverse of the air-entry value
+ n_vgm (1:nl_soil), &! pore-connectivity parameter [dimensionless]
+ L_vgm (1:nl_soil), &! a shape parameter [dimensionless]
+ sc_vgm (1:nl_soil), &! saturation at the air entry value in the classical vanGenuchten model [-]
+ fc_vgm (1:nl_soil), &! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+ k_solids (1:nl_soil), &! thermal conductivity of minerals soil [W/m-K]
+ dkdry (1:nl_soil), &! thermal conductivity of dry soil [W/m-K]
+ dksatu (1:nl_soil), &! thermal conductivity of saturated unfrozen soil [W/m-K]
+ dksatf (1:nl_soil), &! thermal conductivity of saturated frozen soil [W/m-K]
+ hksati (1:nl_soil), &! hydraulic conductivity at saturation [mm h2o/s]
+ BA_alpha (1:nl_soil), &! alpha in Balland and Arp(2005) thermal conductivity scheme
+ BA_beta (1:nl_soil), &! beta in Balland and Arp(2005) thermal conductivity scheme
+
+ ! vegetation parameters
+ lai, &! adjusted leaf area index for seasonal variation [-]
+ htop, &! canopy crown top height [m]
+ hbot, &! canopy crown bottom height [m]
+ sqrtdi, &! inverse sqrt of leaf dimension [m**-0.5]
+ rootfr(1:nl_soil), &! root fraction
+
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2/mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ kmax_sun, &! Plant Hydraulics Parameters
+ kmax_sha, &! Plant Hydraulics Parameters
+ kmax_xyl, &! Plant Hydraulics Parameters
+ kmax_root, &! Plant Hydraulics Parameters
+ psi50_sun, &! water potential at 50% loss of sunlit leaf tissue conductance (mmH2O)
+ psi50_sha, &! water potential at 50% loss of shaded leaf tissue conductance (mmH2O)
+ psi50_xyl, &! water potential at 50% loss of xylem tissue conductance (mmH2O)
+ psi50_root, &! water potential at 50% loss of root tissue conductance (mmH2O)
+ ck, &! shape-fitting parameter for vulnerability curve (-)
+ slti, &! slope of low temperature inhibition function [s3]
+ hlti, &! 1/2 point of low temperature inhibition function [s4]
+ shti, &! slope of high temperature inhibition function [s1]
+ hhti, &! 1/2 point of high temperature inhibition function [s2]
+ trda, &! temperature coefficient in gs-a model [s5]
+ trdm, &! temperature coefficient in gs-a model [s6]
+ trop, &! temperature coefficient in gs-a model
+ g1, &! conductance-photosynthesis slope parameter for medlyn model
+ g0, &! conductance-photosynthesis intercept for medlyn model
+ gradm, &! conductance-photosynthesis slope parameter
+ binter, &! conductance-photosynthesis intercept
+ extkn, &! coefficient of leaf nitrogen allocation
+
+ ! atmospherical variables and observational height
+ forc_hgt_u, &! observational height of wind [m]
+ forc_hgt_t, &! observational height of temperature [m]
+ forc_hgt_q, &! observational height of humidity [m]
+ forc_us, &! wind component in eastward direction [m/s]
+ forc_vs, &! wind component in northward direction [m/s]
+ forc_t, &! temperature at agcm reference height [kelvin]
+ forc_q, &! specific humidity at agcm reference height [kg/kg]
+ forc_rhoair, &! density air [kg/m3]
+ forc_psrf, &! atmosphere pressure at the surface [pa]
+ forc_pco2m, &! CO2 concentration in atmos. (pascals)
+ forc_po2m, &! O2 concentration in atmos. (pascals)
+ forc_hpbl, &! atmospheric boundary layer height [m]
+ pg_rain, &! rainfall onto ground including canopy runoff [kg/(m2 s)]
+ pg_snow, &! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ t_precip, &! snowfall/rainfall temperature [kelvin]
+ qintr_rain, &! rainfall interception (mm h2o/s)
+ qintr_snow, &! snowfall interception (mm h2o/s)
+
+ ! radiative fluxes
+ coszen, &! cosine of the solar zenith angle
+ parsun, &! photosynthetic active radiation by sunlit leaves (W m-2)
+ parsha, &! photosynthetic active radiation by shaded leaves (W m-2)
+ sabvsun, &! solar radiation absorbed by vegetation [W/m2]
+ sabvsha, &! solar radiation absorbed by vegetation [W/m2]
+ sabg, &! solar radiation absorbed by ground [W/m2]
+ sabg_soil, &! solar radiation absorbed by ground soil [W/m2]
+ sabg_snow, &! solar radiation absorbed by ground snow [W/m2]
+ frl, &! atmospheric infrared (longwave) radiation [W/m2]
+ extkb, &! (k, g(mu)/mu) direct solar extinction coefficient
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ thermk, &! canopy gap fraction for tir radiation
+
+ ! state variable (1)
+ fsno, &! fraction of ground covered by snow
+ sigf, &! fraction of veg cover, excluding snow-covered veg [-]
+ dz_soisno(lb:nl_soil), &! layer thickness [m]
+ z_soisno (lb:nl_soil), &! node depth [m]
+ zi_soisno(lb-1:nl_soil) ! interface depth [m]
+
+ integer , intent(in) :: &
+ c3c4 ! C3/C4 plant type
+
+ real(r8), intent(in) :: &
+ sabg_snow_lyr(lb:1) ! snow layer absorption
+
+ ! state variables (2)
+ real(r8), intent(inout) :: &
+ vegwp(1:nvegwcs), &! vegetation water potential
+ gs0sun, &! working copy of sunlit stomata conductance
+ gs0sha, &! working copy of shaded stomata conductance
+!Ozone stress variables
+ lai_old , &! lai in last time step
+ o3uptakesun, &! Ozone does, sunlit leaf (mmol O3/m^2)
+ o3uptakesha, &! Ozone does, shaded leaf (mmol O3/m^2)
+ forc_ozone , &! Ozone
+!end ozone stress variables
+
+!Ozone WUE stomata model parameter
+ lambda, &! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+!End WUE stomata model parameter
+
+ tleaf, &! shaded leaf temperature [K]
+ t_soisno(lb:nl_soil), &! soil temperature [K]
+ wice_soisno(lb:nl_soil), &! ice lens [kg/m2]
+ wliq_soisno(lb:nl_soil) ! liquid water [kg/m2]
+
+ real(r8), intent(in) :: &
+ smp(1:nl_soil) , &! soil matrix potential [mm]
+ hk(1:nl_soil) ! hydraulic conductivity [mm h2o/s]
+
+ real(r8), intent(inout) :: &
+ ldew, &! depth of water on foliage [kg/(m2 s)]
+ ldew_rain, &! depth of rain on foliage [kg/(m2 s)]
+ ldew_snow, &! depth of rain on foliage [kg/(m2 s)]
+ fwet_snow, &! vegetation canopy snow fractional cover [-]
+ scv, &! snow cover, water equivalent [mm, kg/m2]
+ snowdp ! snow depth [m]
+
+ real(r8), intent(out) :: &
+ snofrz (lb:0) !snow freezing rate (col,lyr) [kg m-2 s-1]
+
+ integer, intent(out) :: &
+ imelt(lb:nl_soil) ! flag for melting or freezing [-]
+
+ real(r8), intent(out) :: &
+ laisun, &! sunlit leaf area index
+ laisha, &! shaded leaf area index
+ gssun_out, &! sunlit stomata conductance
+ gssha_out, &! shaded stomata conductance
+ rstfacsun_out, &! factor of soil water stress on sunlit leaf
+ rstfacsha_out ! factor of soil water stress on shaded leaf
+
+ real(r8), intent(out) :: &
+ assimsun_out , &! diagnostic sunlit leaf assim value for output
+ etrsun_out , &! diagnostic sunlit leaf etr value for output
+ assimsha_out , &! diagnostic shaded leaf assim for output
+ etrsha_out ! diagnostic shaded leaf etr for output
+
+ ! Output fluxes
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fsena, &! sensible heat from canopy height to atmosphere [W/m2]
+ fevpa, &! evapotranspiration from canopy height to atmosphere [mm/s]
+ lfevpa, &! latent heat flux from canopy height to atmosphere [W/m2]
+ fsenl, &! sensible heat from leaves [W/m2]
+ fevpl, &! evaporation+transpiration from leaves [mm/s]
+ etr, &! transpiration rate [mm/s]
+ fseng, &! sensible heat flux from ground [W/m2]
+ fevpg, &! evaporation heat flux from ground [mm/s]
+ olrg, &! outgoing long-wave radiation from ground+canopy
+ fgrnd, &! ground heat flux [W/m2]
+ rootr(1:nl_soil), &! water uptake fraction from different layers, all layers add to 1.0
+ rootflux(1:nl_soil), &! root uptake from different layer, all layers add to transpiration
+
+ qseva, &! ground surface evaporation rate (mm h2o/s)
+ qsdew, &! ground surface dew formation (mm h2o /s) [+]
+ qsubl, &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros, &! surface dew added to snow pack (mm h2o /s) [+]
+ qseva_soil, &! ground soil surface evaporation rate (mm h2o/s)
+ qsdew_soil, &! ground soil surface dew formation (mm h2o /s) [+]
+ qsubl_soil, &! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qfros_soil, &! surface dew added to soil ice pack (mm h2o /s) [+]
+ qseva_snow, &! ground snow surface evaporation rate (mm h2o/s)
+ qsdew_snow, &! ground snow surface dew formation (mm h2o /s) [+]
+ qsubl_snow, &! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros_snow, &! surface dew added to snow pack (mm h2o /s) [+]
+
+ sm, &! rate of snowmelt [kg/(m2 s)]
+ tref, &! 2 m height air temperature [kelvin]
+ qref, &! 2 m height air specific humidity
+ trad, &! radiative temperature [K]
+ rss, &! bare soil resistance for evaporation [s/m]
+ rst, &! stomatal resistance (s m-1)
+ assim, &! assimilation
+ respc, &! respiration
+
+ ! additional variables required by coupling with WRF or RSM model
+ emis, &! averaged bulk surface emissivity
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! u* in similarity theory [m/s]
+ qstar, &! q* in similarity theory [kg/kg]
+ tstar, &! t* in similarity theory [K]
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+!Ozone stress variables
+ real(r8),intent(inout) :: &
+ o3coefv_sun,&! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefv_sha,&! Ozone stress factor for photosynthesis on sunlit leaf
+ o3coefg_sun,&! Ozone stress factor for stomata on shaded leaf
+ o3coefg_sha ! Ozone stress factor for stomata on shaded leaf
+!end ozone stress variables
+
+
+!-------------------------- Local Variables ----------------------------
+
+ integer i,j
+
+ real(r8) :: &
+ fseng_soil, &! sensible heat flux from soil fraction
+ fseng_snow, &! sensible heat flux from snow fraction
+ fevpg_soil, &! latent heat flux from soil fraction
+ fevpg_snow, &! latent heat flux from snow fraction
+
+ cgrnd, &! deriv. of soil energy flux wrt to soil temp [w/m2/k]
+ cgrndl, &! deriv, of soil sensible heat flux wrt soil temp [w/m2/k]
+ cgrnds, &! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+ degdT, &! d(eg)/dT
+ dqgdT, &! d(qg)/dT
+ dlrad, &! downward longwave radiation blow the canopy [W/m2]
+ eg, &! water vapor pressure at temperature T [pa]
+ egsmax, &! max. evaporation which soil can provide at one time step
+ egidif, &! the excess of evaporation over "egsmax"
+ emg, &! ground emissivity (0.97 for snow,
+ ! glaciers and water surface; 0.96 for soil and wetland)
+ errore, &! energy balnce error [w/m2]
+ etrc, &! maximum possible transpiration rate [mm/s]
+ fac, &! soil wetness of surface layer
+ fact(lb:nl_soil), &! used in computing tridiagonal matrix
+ fsun, &! fraction of sunlit canopy
+ hr, &! relative humidity
+ htvp, &! latent heat of vapor of water (or sublimation) [j/kg]
+ olru, &! olrg excluding dwonwelling reflection [W/m2]
+ olrb, &! olrg assuming blackbody emission [W/m2]
+ psit, &! negative potential of soil
+ qg, &! ground specific humidity [kg/kg]
+! 03/07/2020, yuan:
+ q_soil, &! ground soil specific humidity [kg/kg]
+ q_snow, &! ground snow specific humidity [kg/kg]
+ qsatg, &! saturated humidity [kg/kg]
+ qsatgdT, &! d(qsatg)/dT
+ qred, &! soil surface relative humidity
+ sabv, &! solar absorbed by canopy [W/m2]
+ thm, &! intermediate variable (forc_t+0.0098*forc_hgt_t)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ rstfac, &! factor of soil water stress
+ t_grnd, &! ground surface temperature [K]
+ t_grnd_bef, &! ground surface temperature [K]
+ t_soil, &! ground soil temperature
+ t_snow, &! ground snow temperature
+ t_soisno_bef(lb:nl_soil), &! soil/snow temperature before update
+ tinc, &! temperature difference of two time step
+ ur, &! wind speed at reference height [m/s]
+ ulrad, &! upward longwave radiation above the canopy [W/m2]
+ wice0(lb:nl_soil), &! ice mass from previous time-step
+ wliq0(lb:nl_soil), &! liquid mass from previous time-step
+ wx, &! patial volume of ice and water of surface layer
+ xmf, &! total latent heat of phase change of ground water [W/m2]
+ hprl, &! precipitation sensible heat from canopy [W/m2]
+ dheatl ! vegetation heat change [W/m2]
+
+ real(r8) :: z0m_g,z0h_g,zol_g,obu_g,rib_g,ustar_g,qstar_g,tstar_g
+ real(r8) :: fm10m,fm_g,fh_g,fq_g,fh2m,fq2m,um,obu
+
+ integer p, ps, pe, pn
+
+ real(r8), allocatable :: rootr_p (:,:)
+ real(r8), allocatable :: rootflux_p (:,:)
+ real(r8), allocatable :: etrc_p (:)
+ real(r8), allocatable :: rstfac_p (:)
+ real(r8), allocatable :: rstfacsun_p (:)
+ real(r8), allocatable :: rstfacsha_p (:)
+ real(r8), allocatable :: gssun_p (:)
+ real(r8), allocatable :: gssha_p (:)
+ real(r8), allocatable :: fsun_p (:)
+ real(r8), allocatable :: sabv_p (:)
+ real(r8), allocatable :: fcover (:)
+
+! 03/06/2020, yuan: added
+ real(r8), allocatable :: fseng_soil_p (:)
+ real(r8), allocatable :: fseng_snow_p (:)
+ real(r8), allocatable :: fevpg_soil_p (:)
+ real(r8), allocatable :: fevpg_snow_p (:)
+ real(r8), allocatable :: cgrnd_p (:)
+ real(r8), allocatable :: cgrnds_p (:)
+ real(r8), allocatable :: cgrndl_p (:)
+ real(r8), allocatable :: dlrad_p (:)
+ real(r8), allocatable :: ulrad_p (:)
+ real(r8), allocatable :: zol_p (:)
+ real(r8), allocatable :: rib_p (:)
+ real(r8), allocatable :: ustar_p (:)
+ real(r8), allocatable :: qstar_p (:)
+ real(r8), allocatable :: tstar_p (:)
+ real(r8), allocatable :: fm_p (:)
+ real(r8), allocatable :: fh_p (:)
+ real(r8), allocatable :: fq_p (:)
+ real(r8), allocatable :: hprl_p (:)
+ real(r8), allocatable :: assimsun_p (:)
+ real(r8), allocatable :: etrsun_p (:)
+ real(r8), allocatable :: assimsha_p (:)
+ real(r8), allocatable :: etrsha_p (:)
+ real(r8), allocatable :: dheatl_p (:)
+
+
+!=======================================================================
+! [1] Initial set and propositional variables
+!=======================================================================
+
+ ! emissivity
+ emg = 0.96
+ IF (scv>0. .or. patchtype==3) emg = 0.97
+
+ ! fluxes
+ taux = 0.; tauy = 0.
+ fsena = 0.; fevpa = 0.
+ lfevpa = 0.; fsenl = 0.
+ fevpl = 0.; etr = 0.
+ fseng = 0.; fevpg = 0.
+
+ cgrnds = 0.; cgrndl = 0.
+ cgrnd = 0.; tref = 0.
+ qref = 0.; rst = 2.0e4
+ assim = 0.; respc = 0.
+ hprl = 0.; dheatl = 0.
+
+ emis = 0.; z0m = 0.
+ zol = 0.; rib = 0.
+ ustar = 0.; qstar = 0.
+ tstar = 0.; rootr = 0.
+ rootflux = 0.
+
+ dlrad = frl
+
+ t_soil = t_soisno(1)
+ t_snow = t_soisno(lb)
+
+IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ t_grnd = t_soisno(lb)
+ ulrad = frl*(1.-emg) + emg*stefnc*t_grnd**4
+ELSE
+ t_grnd = fsno*t_snow + (1.-fsno)*t_soil
+ ulrad = frl*(1.-emg) &
+ + fsno*emg*stefnc*t_snow**4 &
+ + (1.-fsno)*emg*stefnc*t_soil**4
+ENDIF
+
+ ! temperature and water mass from previous time step
+ t_soisno_bef(lb:) = t_soisno(lb:)
+ t_grnd_bef = t_grnd
+ wice0(lb:) = wice_soisno(lb:)
+ wliq0(lb:) = wliq_soisno(lb:)
+
+ ! latent heat, assumed that the sublimation occurred only as wliq_soisno=0
+ htvp = hvap
+ IF (wliq_soisno(lb)<=0. .and. wice_soisno(lb)>0.) htvp = hsub
+
+ ! potential temperature at the reference height
+ thm = forc_t + 0.0098*forc_hgt_t !intermediate variable equivalent to
+ !forc_t*(pgcm/forc_psrf)**(rgas/cpair)
+ th = forc_t*(100000./forc_psrf)**(rgas/cpair) !potential T
+ thv = th*(1.+0.61*forc_q) !virtual potential T
+ ur = max(0.1,sqrt(forc_us*forc_us+forc_vs*forc_vs)) !limit set to 0.1
+
+
+!=======================================================================
+! [2] specific humidity and its derivative at ground surface
+!=======================================================================
+
+ qred = 1.
+ hr = 1.
+
+ IF ((patchtype<=1) .or. is_dry_lake &
+ .or. (DEF_USE_Dynamic_Wetland .and. (patchtype==2))) THEN !soil ground
+ wx = (wliq_soisno(1)/denh2o + wice_soisno(1)/denice)/dz_soisno(1)
+ IF (porsl(1) < 1.e-6) THEN !bed rock
+ fac = 0.001
+ ELSE
+ fac = min(1.,wx/porsl(1))
+ fac = max( fac, 0.001 )
+ ENDIF
+
+#ifdef Campbell_SOIL_MODEL
+ psit = psi0(1) * fac ** (- bsw(1) ) !psit = max(smpmin, psit)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ psit = soil_psi_from_vliq ( fac*(porsl(1)-theta_r(1)) + theta_r(1), &
+ porsl(1), theta_r(1), psi0(1), &
+ 5, (/alpha_vgm(1), n_vgm(1), L_vgm(1), sc_vgm(1), fc_vgm(1)/))
+#endif
+ psit = max( -1.e8, psit )
+ hr = exp(psit/roverg/t_grnd)
+ qred = (1.-fsno)*hr + fsno
+ ENDIF
+
+IF (.not. DEF_SPLIT_SOILSNOW) THEN
+ CALL qsadv(t_grnd,forc_psrf,eg,degdT,qsatg,qsatgdT)
+
+ qg = qred*qsatg
+ dqgdT = qred*qsatgdT
+
+ IF (qsatg > forc_q .and. forc_q > qred*qsatg) THEN
+ qg = forc_q; dqgdT = 0.
+ ENDIF
+
+ q_soil = qg
+ q_snow = qg
+
+ELSE
+ CALL qsadv(t_soil,forc_psrf,eg,degdT,qsatg,qsatgdT)
+
+ q_soil = hr*qsatg
+ dqgdT = (1.-fsno)*hr*qsatgdT
+
+ IF(qsatg > forc_q .and. forc_q > hr*qsatg)THEN
+ q_soil = forc_q; dqgdT = 0.
+ ENDIF
+
+ CALL qsadv(t_snow,forc_psrf,eg,degdT,qsatg,qsatgdT)
+
+ q_snow = qsatg
+ dqgdT = dqgdT + fsno*qsatgdT
+
+ ! weighted average qg
+ qg = (1.-fsno)*q_soil + fsno*q_snow
+ ENDIF
+ IF (allocated(qsfc)) qsfc(ipatch) = qg
+
+ ! calculate soil surface resistance (rss)
+ ! ------------------------------------------------
+ !NOTE: (1) DEF_RSS_SCHEME=0 means no rss considered
+ ! (2) Do NOT calculate rss for the first timestep
+ IF (DEF_RSS_SCHEME>0 .and. rss/=spval) THEN
+
+ !NOTE: If the beta scheme is used, the rss is not soil resistance,
+ !but soil beta factor (soil wetness relative to field capacity [0-1]).
+ CALL SoilSurfaceResistance (nl_soil,forc_rhoair,hksati,porsl,psi0, &
+#ifdef Campbell_SOIL_MODEL
+ bsw, &
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm, &
+#endif
+ dz_soisno,t_soisno,wliq_soisno,wice_soisno,fsno,qg,rss)
+ ELSE
+ IF (DEF_RSS_SCHEME == 4) THEN
+ rss = 1. !LP92
+ ELSE
+ rss = 0. !the other RSS schemes
+ ENDIF
+ ENDIF
+
+!=======================================================================
+! [3] Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+! TODO: modify code description
+!=======================================================================
+
+ ! Always CALL GroundFluxes for bare ground CASE
+ CALL GroundFluxes (zlnd,zsno,forc_hgt_u,forc_hgt_t,forc_hgt_q,forc_hpbl, &
+ forc_us,forc_vs,forc_t,forc_q,forc_rhoair,forc_psrf, &
+ ur,thm,th,thv,t_grnd,qg,rss,dqgdT,htvp, &
+ fsno,cgrnd,cgrndl,cgrnds, &
+ t_soil,t_snow,q_soil,q_snow, &
+ !taux,tauy,fseng,fevpg,tref,qref, &
+ taux,tauy,fseng,fseng_soil,fseng_snow, &
+ fevpg,fevpg_soil,fevpg_snow,tref,qref, &
+ z0m_g,z0h_g,zol_g,rib_g,ustar_g,qstar_g,tstar_g,fm_g,fh_g,fq_g)
+
+ obu_g = forc_hgt_u / zol_g
+
+
+!=======================================================================
+! [4] Canopy temperature, fluxes from the canopy
+!=======================================================================
+
+IF ( patchtype==0.and.DEF_USE_LCT .or. patchtype>0 ) THEN
+
+ sabv = sabvsun + sabvsha
+
+ IF (lai+sai > 1e-6) THEN
+
+ ! soil water stress factor on stomatal resistance
+ CALL eroot (nl_soil,trsmx0,porsl,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm, &
+#endif
+ psi0,rootfr,dz_soisno,t_soisno,wliq_soisno,rootr,etrc,rstfac)
+
+ ! fraction of sunlit and shaded leaves of canopy
+ fsun = ( 1. - exp(-min(extkb*lai,40.))) / max( min(extkb*lai,40.), 1.e-6 )
+
+ IF (coszen<=0.0 .or. sabv<1.) fsun = 0.5
+
+ laisun = lai*fsun
+ laisha = lai*(1-fsun)
+ rstfacsun_out = rstfac
+ rstfacsha_out = rstfac
+
+ CALL LeafTemperature(ipatch,1,deltim,csoilc ,dewmx ,htvp ,&
+ lai ,sai ,htop ,hbot ,sqrtdi ,&
+ effcon ,vmax25 ,c3c4 ,slti ,hlti ,shti ,&
+ hhti ,trda ,trdm ,trop ,g1 ,&
+ g0 ,gradm ,binter ,extkn ,extkb ,&
+ extkd ,forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,thm ,th ,thv ,forc_q ,&
+ forc_psrf ,forc_rhoair ,parsun ,parsha ,sabv ,&
+ frl ,fsun ,thermk ,rstfacsun_out,rstfacsha_out,&
+ gssun_out ,gssha_out ,forc_po2m ,forc_pco2m ,z0h_g ,&
+ obu_g ,ustar_g ,zlnd ,zsno ,fsno ,&
+ sigf ,etrc ,t_grnd ,qg ,rss ,&
+ t_soil ,t_snow ,q_soil ,q_snow ,dqgdT ,&
+ emg ,tleaf ,ldew ,ldew_rain ,ldew_snow ,&
+ fwet_snow ,taux ,tauy ,&
+ fseng ,fseng_soil ,fseng_snow ,&
+ fevpg ,fevpg_soil ,fevpg_snow ,&
+ cgrnd ,cgrndl ,cgrnds ,&
+ tref ,qref ,rst ,assim ,respc ,&
+ fsenl ,fevpl ,etr ,dlrad ,ulrad ,&
+ z0m ,zol ,rib ,ustar ,qstar ,&
+ tstar ,fm ,fh ,fq ,rootfr ,&
+ kmax_sun ,kmax_sha ,kmax_xyl ,kmax_root ,psi50_sun ,&
+ psi50_sha ,psi50_xyl ,psi50_root ,ck ,vegwp ,&
+ gs0sun ,gs0sha ,&
+ assimsun_out,etrsun_out ,assimsha_out ,etrsha_out ,&
+!Ozone stress variables
+ o3coefv_sun ,o3coefv_sha ,o3coefg_sun ,o3coefg_sha ,&
+ lai_old ,o3uptakesun ,o3uptakesha ,forc_ozone ,&
+!end ozone stress variables
+!Ozone WUE stomata model parameter
+ lambda ,&! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+!End WUE stomata model parameter
+ forc_hpbl ,&
+ qintr_rain ,qintr_snow ,t_precip ,hprl ,dheatl ,&
+ smp ,hk(1:) ,hksati(1:) ,rootflux(1:) )
+ ELSE
+ tleaf = forc_t
+ laisun = 0.
+ laisha = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ fwet_snow = 0.
+ ldew = 0.
+ rstfacsun_out = 0.
+ rstfacsha_out = 0.
+ assimsun_out = 0.
+ assimsha_out = 0.
+ etrsun_out = 0.
+ etrsha_out = 0.
+ gssun_out = 0.
+ gssha_out = 0.
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ vegwp = -2.5e4
+ ENDIF
+ ENDIF
+
+ENDIF
+
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+IF (patchtype == 0) THEN
+
+ ps = patch_pft_s(ipatch)
+ pe = patch_pft_e(ipatch)
+
+ allocate ( rootr_p (nl_soil, ps:pe) )
+ allocate ( rootflux_p(nl_soil,ps:pe))
+ allocate ( etrc_p (ps:pe) )
+ allocate ( rstfac_p (ps:pe) )
+ allocate ( rstfacsun_p (ps:pe) )
+ allocate ( rstfacsha_p (ps:pe) )
+ allocate ( gssun_p (ps:pe) )
+ allocate ( gssha_p (ps:pe) )
+ allocate ( fsun_p (ps:pe) )
+ allocate ( sabv_p (ps:pe) )
+ allocate ( fcover (ps:pe) )
+
+ allocate ( fseng_soil_p (ps:pe) )
+ allocate ( fseng_snow_p (ps:pe) )
+ allocate ( fevpg_soil_p (ps:pe) )
+ allocate ( fevpg_snow_p (ps:pe) )
+ allocate ( cgrnd_p (ps:pe) )
+ allocate ( cgrnds_p (ps:pe) )
+ allocate ( cgrndl_p (ps:pe) )
+ allocate ( dlrad_p (ps:pe) )
+ allocate ( ulrad_p (ps:pe) )
+ allocate ( zol_p (ps:pe) )
+ allocate ( rib_p (ps:pe) )
+ allocate ( ustar_p (ps:pe) )
+ allocate ( qstar_p (ps:pe) )
+ allocate ( tstar_p (ps:pe) )
+ allocate ( fm_p (ps:pe) )
+ allocate ( fh_p (ps:pe) )
+ allocate ( fq_p (ps:pe) )
+
+ allocate ( hprl_p (ps:pe) )
+ allocate ( assimsun_p (ps:pe) )
+ allocate ( etrsun_p (ps:pe) )
+ allocate ( assimsha_p (ps:pe) )
+ allocate ( etrsha_p (ps:pe) )
+ allocate ( dheatl_p (ps:pe) )
+
+ sabv_p(ps:pe) = sabvsun_p(ps:pe) + sabvsha_p(ps:pe)
+ sabv = sabvsun + sabvsha
+
+ DO i = ps, pe
+ p = pftclass(i)
+
+ IF (lai_p(i)+sai_p(i) > 1e-6) THEN
+
+ CALL eroot (nl_soil,trsmx0,porsl,&
+#ifdef Campbell_SOIL_MODEL
+ bsw, &
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm, &
+#endif
+ psi0,rootfr_p(:,p),&
+ dz_soisno,t_soisno,wliq_soisno,rootr_p(:,i),etrc_p(i),rstfac_p(i))
+
+ ! fraction of sunlit and shaded leaves of canopy
+ fsun_p(i) = ( 1. - exp(-min(extkb_p(i)*lai_p(i),40.))) &
+ / max( min(extkb_p(i)*lai_p(i),40.), 1.e-6 )
+
+ IF (coszen<=0.0 .or. sabv_p(i)<1.) fsun_p(i) = 0.5
+
+ laisun_p(i) = lai_p(i)*fsun_p(i)
+ laisha_p(i) = lai_p(i)*(1-fsun_p(i))
+ rstfacsun_p(i) = rstfac_p(i)
+ rstfacsha_p(i) = rstfac_p(i)
+ ELSE
+ laisun_p(i) = 0.
+ laisha_p(i) = 0.
+ ldew_rain_p(i) = 0.
+ ldew_snow_p(i) = 0.
+ fwet_snow_p(i) = 0.
+ ldew_p(i) = 0.
+ rootr_p(:,i) = 0.
+ rootflux_p(:,i)= 0.
+ rstfacsun_p(i) = 0.
+ rstfacsha_p(i) = 0.
+ dheatl_p(i) = 0.
+ ENDIF
+ ENDDO
+
+ IF (.not. DEF_USE_LAIFEEDBACK)THEN
+ lai_enftemp (ipatch) = 0._r8
+ lai_enfboreal (ipatch) = 0._r8
+ lai_dnfboreal (ipatch) = 0._r8
+ lai_ebftrop (ipatch) = 0._r8
+ lai_ebftemp (ipatch) = 0._r8
+ lai_dbftrop (ipatch) = 0._r8
+ lai_dbftemp (ipatch) = 0._r8
+ lai_dbfboreal (ipatch) = 0._r8
+ lai_ebstemp (ipatch) = 0._r8
+ lai_dbstemp (ipatch) = 0._r8
+ lai_dbsboreal (ipatch) = 0._r8
+ lai_c3arcgrass (ipatch) = 0._r8
+ lai_c3grass (ipatch) = 0._r8
+ lai_c4grass (ipatch) = 0._r8
+ DO i = ps, pe
+ p = pftclass(i)
+ IF(p .eq. 1)THEN
+ lai_enftemp (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 2)THEN
+ lai_enfboreal (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 3)THEN
+ lai_dnfboreal (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 4)THEN
+ lai_ebftrop (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 5)THEN
+ lai_ebftemp (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 6)THEN
+ lai_dbftrop (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 7)THEN
+ lai_dbftemp (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 8)THEN
+ lai_dbfboreal (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 9)THEN
+ lai_ebstemp (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 10)THEN
+ lai_dbstemp (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 11)THEN
+ lai_dbsboreal (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 12)THEN
+ lai_c3arcgrass(ipatch) = lai_p(i)
+ ELSE IF(p .eq. 13)THEN
+ lai_c3grass (ipatch) = lai_p(i)
+ ELSE IF(p .eq. 14)THEN
+ lai_c4grass (ipatch) = lai_p(i)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ DO i = ps, pe
+ p = pftclass(i)
+
+ ! Dealing with PFTs for PC:
+ ! If defined DEF_PC_CROP_SPLIT, for crop PFTs, use 1D twostream model;
+ ! Otherwise, skip to run PC 3D model.
+ IF ( DEF_USE_PC .and. (.not.DEF_PC_CROP_SPLIT .or. p.lt.15) ) THEN
+ CYCLE
+ ENDIF
+
+ IF (lai_p(i)+sai_p(i) > 1e-6) THEN
+
+ CALL LeafTemperature(ipatch,p,deltim ,csoilc ,dewmx ,htvp ,&
+ lai_p(i) ,sai_p(i) ,htop_p(i) ,hbot_p(i) ,sqrtdi_p(p) ,&
+ effcon_p(p) ,vmax25_p(p) ,c3c4_p(p) ,slti_p(p) ,hlti_p(p) ,shti_p(p) ,&
+ hhti_p(p) ,trda_p(p) ,trdm_p(p) ,trop_p(p) ,g1_p(p) ,&
+ g0_p(p) ,gradm_p(p) ,binter_p(p) ,extkn_p(p) ,extkb_p(i) ,&
+ extkd_p(i) ,forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,thm ,th ,thv ,forc_q ,&
+ forc_psrf ,forc_rhoair ,parsun_p(i) ,parsha_p(i) ,sabv_p(i) ,&
+ frl ,fsun_p(i) ,thermk_p(i) ,rstfacsun_p(i) ,rstfacsha_p(i) ,&
+ gssun_p(i) ,gssha_p(i) ,forc_po2m ,forc_pco2m ,z0h_g ,&
+ obu_g ,ustar_g ,zlnd ,zsno ,fsno ,&
+ sigf_p(i) ,etrc_p(i) ,t_grnd ,qg ,rss ,&
+ t_soil ,t_snow ,q_soil ,q_snow ,dqgdT ,&
+ emg ,tleaf_p(i) ,ldew_p(i) ,ldew_rain_p(i) ,ldew_snow_p(i) ,&
+ fwet_snow_p(i) ,taux_p(i) ,tauy_p(i) ,&
+ fseng_p(i) ,fseng_soil_p(i) ,fseng_snow_p(i) ,&
+ fevpg_p(i) ,fevpg_soil_p(i) ,fevpg_snow_p(i) ,&
+ cgrnd_p(i) ,cgrndl_p(i) ,cgrnds_p(i) ,&
+ tref_p(i) ,qref_p(i) ,rst_p(i) ,assim_p(i) ,respc_p(i) ,&
+ fsenl_p(i) ,fevpl_p(i) ,etr_p(i) ,dlrad_p(i) ,ulrad_p(i) ,&
+ z0m_p(i) ,zol_p(i) ,rib_p(i) ,ustar_p(i) ,qstar_p(i) ,&
+ tstar_p(i) ,fm_p(i) ,fh_p(i) ,fq_p(i) ,rootfr_p(:,p) ,&
+ kmax_sun_p(p) ,kmax_sha_p(p) ,kmax_xyl_p(p) ,kmax_root_p(p) ,psi50_sun_p(p) ,&
+ psi50_sha_p(p) ,psi50_xyl_p(p) ,psi50_root_p(p) ,ck_p(p) ,vegwp_p(:,i) ,&
+ gs0sun_p(i) ,gs0sha_p(i) ,&
+ assimsun_p(i) ,etrsun_p(i) ,assimsha_p(i) ,etrsha_p(i) ,&
+!Ozone stress variables
+ o3coefv_sun_p(i),o3coefv_sha_p(i),o3coefg_sun_p(i),o3coefg_sha_p(i),&
+ lai_old_p(i) ,o3uptakesun_p(i),o3uptakesha_p(i),forc_ozone ,&
+!end ozone stress variables
+!Ozone WUE stomata model parameter
+ lambda_p(p) ,&! Marginal water cost of carbon gain ((mol h2o) (mol co2)-1)
+!End WUE stomata model parameter
+ forc_hpbl ,&
+ qintr_rain_p(i) ,qintr_snow_p(i) ,t_precip ,hprl_p(i) ,dheatl_p(i) ,&
+ smp ,hk(1:) ,hksati(1:) ,rootflux_p(1:,i) )
+ ELSE
+
+ CALL GroundFluxes (zlnd,zsno,forc_hgt_u,forc_hgt_t,forc_hgt_q,forc_hpbl, &
+ forc_us,forc_vs,forc_t,forc_q,forc_rhoair,forc_psrf, &
+ ur,thm,th,thv,t_grnd,qg,rss,dqgdT,htvp, &
+ fsno,cgrnd_p(i),cgrndl_p(i),cgrnds_p(i), &
+ t_soil,t_snow,q_soil,q_snow, &
+ taux_p(i),tauy_p(i),fseng_p(i),fseng_soil_p(i),fseng_snow_p(i), &
+ fevpg_p(i),fevpg_soil_p(i),fevpg_snow_p(i),tref_p(i),qref_p(i), &
+ z0m_p(i),z0h_g,zol_p(i),rib_p(i),ustar_p(i),&
+ qstar_p(i),tstar_p(i),fm_p(i),fh_p(i),fq_p(i))
+
+ tleaf_p (i) = forc_t
+ gssun_p (i) = 0.
+ gssha_p (i) = 0.
+ assimsun_p (i) = 0.
+ etrsun_p (i) = 0.
+ assimsha_p (i) = 0.
+ etrsha_p (i) = 0.
+ rst_p (i) = 2.0e4
+ assim_p (i) = 0.
+ respc_p (i) = 0.
+ fsenl_p (i) = 0.
+ fevpl_p (i) = 0.
+ etr_p (i) = 0.
+ dlrad_p (i) = frl
+
+IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ ulrad_p (i) = frl*(1.-emg) + emg*stefnc*t_grnd**4
+ELSE
+ ulrad_p (i) = frl*(1.-emg) &
+ + fsno*emg*stefnc*t_snow**4 &
+ + (1.-fsno)*emg*stefnc*t_soil**4
+ENDIF
+ hprl_p (i) = 0.
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ vegwp_p(:,i) = -2.5e4
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ! Calculate end index of natrue PFTs
+ DO i = ps, pe
+ pn = i
+ p = pftclass(i)
+ IF (DEF_PC_CROP_SPLIT .and. p.ge.15) THEN
+ pn = pn - 1
+ EXIT
+ ENDIF
+ ENDDO
+
+IF ( DEF_USE_PC .and. pn.ge.ps ) THEN
+
+ pe = pn
+
+ ! initialization
+ rst_p (ps:pe) = 2.0e4
+ assim_p (ps:pe) = 0.
+ respc_p (ps:pe) = 0.
+ fsenl_p (ps:pe) = 0.
+ fevpl_p (ps:pe) = 0.
+ etr_p (ps:pe) = 0.
+ hprl_p (ps:pe) = 0.
+ assimsun_p (ps:pe) = 0.
+ assimsha_p (ps:pe) = 0.
+ etrsun_p (ps:pe) = 0.
+ etrsha_p (ps:pe) = 0.
+ gssun_p (ps:pe) = 0.
+ gssha_p (ps:pe) = 0.
+ fcover (ps:pe) = pftfrac(ps:pe) / sum(pftfrac(ps:pe))
+ z0m_p (ps:pe) = (1.-fsno)*zlnd + fsno*zsno
+ z0m = sum( z0m_p (ps:pe)*pftfrac(ps:pe) )
+
+ IF (DEF_USE_PLANTHYDRAULICS) THEN
+ vegwp_p (:,ps:pe) = -2.5e4
+ ENDIF
+
+ CALL LeafTemperaturePC (ipatch,ps,pe ,deltim ,csoilc ,dewmx ,&
+ htvp ,pftclass(ps:pe) ,fcover(ps:pe) ,htop_p(ps:pe) ,hbot_p(ps:pe) ,&
+ lai_p(ps:pe) ,sai_p(ps:pe) ,extkb_p(ps:pe) ,extkd_p(ps:pe) ,forc_hgt_u ,&
+ forc_hgt_t ,forc_hgt_q ,forc_us ,forc_vs ,forc_t ,&
+ thm ,th ,thv ,forc_q ,forc_psrf ,&
+ forc_rhoair ,parsun_p(ps:pe) ,parsha_p(ps:pe) ,fsun_p(:) ,sabv_p(:) ,&
+ frl ,thermk_p(ps:pe) ,fshade_p(ps:pe) ,rstfacsun_p(:) ,rstfacsha_p(:) ,&
+ gssun_p(:) ,gssha_p(:) ,forc_po2m ,forc_pco2m ,z0h_g ,&
+ obu_g ,ustar_g ,zlnd ,zsno ,fsno ,&
+ sigf_p(ps:pe) ,etrc_p(:) ,t_grnd ,qg,rss ,dqgdT ,&
+ emg ,t_soil ,t_snow ,q_soil ,q_snow ,&
+ z0m_p(ps:pe) ,tleaf_p(ps:pe) ,ldew_p(ps:pe) ,ldew_rain_p(ps:pe),ldew_snow_p(ps:pe),&
+ fwet_snow_p(ps:pe),taux ,tauy ,fseng ,fseng_soil ,&
+ fseng_snow ,fevpg ,fevpg_soil ,fevpg_snow ,cgrnd ,&
+ cgrndl ,cgrnds ,tref ,qref ,rst_p(ps:pe) ,&
+ assim_p(ps:pe) ,respc_p(ps:pe) ,fsenl_p(ps:pe) ,fevpl_p(ps:pe) ,etr_p(ps:pe) ,&
+ dlrad ,ulrad ,z0m ,zol ,rib ,&
+ ustar ,qstar ,tstar ,fm ,fh ,&
+ fq ,vegwp_p(:,ps:pe) ,gs0sun_p(ps:pe) ,gs0sha_p(ps:pe) ,assimsun_p(:) ,&
+ etrsun_p(:) ,assimsha_p(:) ,etrsha_p(:) ,&
+!Ozone stress variables
+ o3coefv_sun_p(ps:pe) ,o3coefv_sha_p(ps:pe) ,o3coefg_sun_p(ps:pe) ,o3coefg_sha_p(ps:pe) ,&
+ lai_old_p(ps:pe) ,o3uptakesun_p(ps:pe) ,o3uptakesha_p(ps:pe) ,forc_ozone ,&
+!End ozone stress variables
+ forc_hpbl ,&
+ qintr_rain_p(ps:pe) ,qintr_snow_p(ps:pe) ,t_precip ,hprl_p(:) ,&
+ dheatl_p(ps:pe) ,smp ,hk(1:) ,hksati(1:) ,&
+ rootflux_p(:,:) )
+
+ dlrad_p (ps:pe) = dlrad
+ ulrad_p (ps:pe) = ulrad
+ tref_p (ps:pe) = tref
+ qref_p (ps:pe) = qref
+ taux_p (ps:pe) = taux
+ tauy_p (ps:pe) = tauy
+ fseng_p (ps:pe) = fseng
+ fseng_soil_p (ps:pe) = fseng_soil
+ fseng_snow_p (ps:pe) = fseng_snow
+ fevpg_p (ps:pe) = fevpg
+ fevpg_soil_p (ps:pe) = fevpg_soil
+ fevpg_snow_p (ps:pe) = fevpg_snow
+ cgrnd_p (ps:pe) = cgrnd
+ cgrndl_p (ps:pe) = cgrndl
+ cgrnds_p (ps:pe) = cgrnds
+ z0m_p (ps:pe) = z0m
+ zol_p (ps:pe) = zol
+ rib_p (ps:pe) = rib
+ ustar_p (ps:pe) = ustar
+ qstar_p (ps:pe) = qstar
+ tstar_p (ps:pe) = tstar
+ fm_p (ps:pe) = fm
+ fh_p (ps:pe) = fh
+ fq_p (ps:pe) = fq
+ENDIF
+
+ pe = patch_pft_e(ipatch)
+
+ ! aggregate PFTs to a patch
+ laisun = sum( laisun_p (ps:pe)*pftfrac(ps:pe) )
+ laisha = sum( laisha_p (ps:pe)*pftfrac(ps:pe) )
+ tleaf = sum( tleaf_p (ps:pe)*pftfrac(ps:pe) )
+ ldew_rain = sum( ldew_rain_p (ps:pe)*pftfrac(ps:pe) )
+ ldew_snow = sum( ldew_snow_p (ps:pe)*pftfrac(ps:pe) )
+ fwet_snow = sum( fwet_snow_p (ps:pe)*pftfrac(ps:pe) )
+ ldew = sum( ldew_p (ps:pe)*pftfrac(ps:pe) )
+ ! may have problem with rst, but the same for LC
+ rst = sum( rst_p (ps:pe)*pftfrac(ps:pe) )
+ assim = sum( assim_p (ps:pe)*pftfrac(ps:pe) )
+ respc = sum( respc_p (ps:pe)*pftfrac(ps:pe) )
+ fsenl = sum( fsenl_p (ps:pe)*pftfrac(ps:pe) )
+ fevpl = sum( fevpl_p (ps:pe)*pftfrac(ps:pe) )
+ etr = sum( etr_p (ps:pe)*pftfrac(ps:pe) )
+
+ dlrad = sum( dlrad_p (ps:pe)*pftfrac(ps:pe) )
+ ulrad = sum( ulrad_p (ps:pe)*pftfrac(ps:pe) )
+ tref = sum( tref_p (ps:pe)*pftfrac(ps:pe) )
+ qref = sum( qref_p (ps:pe)*pftfrac(ps:pe) )
+ taux = sum( taux_p (ps:pe)*pftfrac(ps:pe) )
+ tauy = sum( tauy_p (ps:pe)*pftfrac(ps:pe) )
+ fseng = sum( fseng_p (ps:pe)*pftfrac(ps:pe) )
+ fseng_soil = sum( fseng_soil_p(ps:pe)*pftfrac(ps:pe) )
+ fseng_snow = sum( fseng_snow_p(ps:pe)*pftfrac(ps:pe) )
+ fevpg = sum( fevpg_p (ps:pe)*pftfrac(ps:pe) )
+ fevpg_soil = sum( fevpg_soil_p(ps:pe)*pftfrac(ps:pe) )
+ fevpg_snow = sum( fevpg_snow_p(ps:pe)*pftfrac(ps:pe) )
+ cgrnd = sum( cgrnd_p (ps:pe)*pftfrac(ps:pe) )
+ cgrndl = sum( cgrndl_p (ps:pe)*pftfrac(ps:pe) )
+ cgrnds = sum( cgrnds_p (ps:pe)*pftfrac(ps:pe) )
+ z0m = sum( z0m_p (ps:pe)*pftfrac(ps:pe) )
+ zol = sum( zol_p (ps:pe)*pftfrac(ps:pe) )
+ rib = sum( rib_p (ps:pe)*pftfrac(ps:pe) )
+ ustar = sum( ustar_p (ps:pe)*pftfrac(ps:pe) )
+ qstar = sum( qstar_p (ps:pe)*pftfrac(ps:pe) )
+ tstar = sum( tstar_p (ps:pe)*pftfrac(ps:pe) )
+ fm = sum( fm_p (ps:pe)*pftfrac(ps:pe) )
+ fh = sum( fh_p (ps:pe)*pftfrac(ps:pe) )
+ fq = sum( fq_p (ps:pe)*pftfrac(ps:pe) )
+
+ rstfacsun_out = sum( rstfacsun_p (ps:pe)*pftfrac(ps:pe) )
+ rstfacsha_out = sum( rstfacsha_p (ps:pe)*pftfrac(ps:pe) )
+ gssun_out = sum( gssun_p (ps:pe)*pftfrac(ps:pe) )
+ gssha_out = sum( gssha_p (ps:pe)*pftfrac(ps:pe) )
+ assimsun_out = sum( assimsun_p (ps:pe)*pftfrac(ps:pe) )
+ etrsun_out = sum( etrsun_p (ps:pe)*pftfrac(ps:pe) )
+ assimsha_out = sum( assimsha_p (ps:pe)*pftfrac(ps:pe) )
+ etrsha_out = sum( etrsha_p (ps:pe)*pftfrac(ps:pe) )
+ hprl = sum( hprl_p (ps:pe)*pftfrac(ps:pe) )
+ dheatl = sum( dheatl_p (ps:pe)*pftfrac(ps:pe) )
+IF (DEF_USE_OZONESTRESS)THEN
+ o3uptakesun = sum(o3uptakesun_p(ps:pe)*pftfrac(ps:pe) )
+ o3uptakesha = sum(o3uptakesha_p(ps:pe)*pftfrac(ps:pe) )
+END IF
+
+ IF(DEF_USE_PLANTHYDRAULICS)THEN
+ DO j = 1, nvegwcs
+ vegwp(j) = sum( vegwp_p(j,ps:pe)*pftfrac(ps:pe) )
+ ENDDO
+
+ IF (abs(etr) > 0.) THEN
+ DO j = 1, nl_soil
+ rootflux(j) = sum(rootflux_p(j,ps:pe)*pftfrac(ps:pe))
+ ENDDO
+ ENDIF
+ ELSE
+ IF (abs(etr) > 0.) THEN
+ DO j = 1, nl_soil
+ rootr(j) = sum(rootr_p(j,ps:pe)*etr_p(ps:pe)*pftfrac(ps:pe)) / etr
+ ENDDO
+ ENDIF
+ ENDIF
+
+ deallocate ( rootflux_p )
+ deallocate ( etrc_p )
+ deallocate ( rstfac_p )
+ deallocate ( rstfacsun_p )
+ deallocate ( rstfacsha_p )
+ deallocate ( gssun_p )
+ deallocate ( gssha_p )
+ deallocate ( fsun_p )
+ deallocate ( sabv_p )
+ deallocate ( fcover )
+
+ deallocate ( fseng_soil_p)
+ deallocate ( fseng_snow_p)
+ deallocate ( fevpg_soil_p)
+ deallocate ( fevpg_snow_p)
+ deallocate ( cgrnd_p )
+ deallocate ( cgrnds_p )
+ deallocate ( cgrndl_p )
+ deallocate ( dlrad_p )
+ deallocate ( ulrad_p )
+ deallocate ( zol_p )
+ deallocate ( rib_p )
+ deallocate ( ustar_p )
+ deallocate ( qstar_p )
+ deallocate ( tstar_p )
+ deallocate ( fm_p )
+ deallocate ( fh_p )
+ deallocate ( fq_p )
+
+ deallocate ( hprl_p )
+ deallocate ( assimsun_p )
+ deallocate ( etrsun_p )
+ deallocate ( assimsha_p )
+ deallocate ( etrsha_p )
+ deallocate ( dheatl_p )
+
+ENDIF
+#endif
+
+
+!=======================================================================
+! [5] Ground temperature
+!=======================================================================
+
+ CALL GroundTemperature (patchtype,is_dry_lake,lb,nl_soil,deltim,&
+ capr,cnfac,vf_quartz,vf_gravels,vf_om,vf_sand,wf_gravels,wf_sand,&
+ porsl,psi0,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm,&
+ sc_vgm , fc_vgm,&
+#endif
+ csol,k_solids,dksatu,dksatf,dkdry,&
+ BA_alpha,BA_beta,&
+ sigf,dz_soisno,z_soisno,zi_soisno,&
+ t_soisno,t_grnd,t_soil,t_snow,wice_soisno,wliq_soisno,scv,snowdp,fsno,&
+ frl,dlrad,sabg,sabg_soil,sabg_snow,sabg_snow_lyr,&
+ fseng,fseng_soil,fseng_snow,fevpg,fevpg_soil,fevpg_snow,cgrnd,htvp,emg,&
+ imelt,snofrz,sm,xmf,fact,pg_rain,pg_snow,t_precip)
+
+!=======================================================================
+! [6] Correct fluxes to present soil temperature
+!=======================================================================
+
+ IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ t_grnd = t_soisno(lb)
+ tinc = t_soisno(lb) - t_soisno_bef(lb)
+ ELSE
+ t_grnd = fsno*t_soisno(lb) + (1.0-fsno)*t_soisno(1)
+ tinc = t_grnd - t_grnd_bef
+ ENDIF
+
+ fseng = fseng + tinc*cgrnds
+ fseng_soil = fseng_soil + tinc*cgrnds
+ fseng_snow = fseng_snow + tinc*cgrnds
+ fevpg = fevpg + tinc*cgrndl
+ fevpg_soil = fevpg_soil + tinc*cgrndl
+ fevpg_snow = fevpg_snow + tinc*cgrndl
+
+! calculation of evaporative potential; flux in kg m-2 s-1.
+! egidif holds the excess energy IF all water is evaporated
+! during the timestep. This energy is later added to the sensible heat flux.
+
+ qseva = 0.
+ qsubl = 0.
+ qfros = 0.
+ qsdew = 0.
+ qseva_soil = 0.
+ qsubl_soil = 0.
+ qfros_soil = 0.
+ qsdew_soil = 0.
+ qseva_snow = 0.
+ qsubl_snow = 0.
+ qfros_snow = 0.
+ qsdew_snow = 0.
+
+
+IF (.not. DEF_SPLIT_SOILSNOW) THEN
+ egsmax = (wice_soisno(lb)+wliq_soisno(lb)) / deltim
+ egidif = max( 0., fevpg - egsmax )
+ fevpg = min( fevpg, egsmax )
+ fseng = fseng + htvp*egidif
+
+ IF (fevpg >= 0.) THEN
+! not allow for sublimation in melting (melting ==> evap. ==> sublimation)
+ qseva = min(wliq_soisno(lb)/deltim, fevpg)
+ qsubl = fevpg - qseva
+ ELSE
+ IF (t_grnd < tfrz) THEN
+ qfros = abs(fevpg)
+ ELSE
+ qsdew = abs(fevpg)
+ ENDIF
+ ENDIF
+
+ELSE
+ IF (lb < 1) THEN ! snow layer exist
+ egsmax = (wice_soisno(lb)+wliq_soisno(lb)) / deltim
+ egidif = max( 0., fevpg_snow - egsmax )
+ fevpg_snow = min ( fevpg_snow, egsmax )
+ fseng_snow = fseng_snow + htvp*egidif
+ ELSE ! no snow layer, attribute to soil
+ fevpg_soil = fevpg_soil*(1.-fsno) + fevpg_snow*fsno
+ ENDIF
+
+ egsmax = (wice_soisno(1)+wliq_soisno(1)) / deltim
+ egidif = max( 0., fevpg_soil - egsmax )
+ fevpg_soil = min ( fevpg_soil, egsmax )
+ fseng_soil = fseng_soil + htvp*egidif
+
+ IF (lb < 1) THEN ! snow layer exist
+ fseng = fseng_soil*(1.-fsno) + fseng_snow*fsno
+ fevpg = fevpg_soil*(1.-fsno) + fevpg_snow*fsno
+ ELSE ! no snow layer, attribute to soil
+ fseng = fseng_soil; fseng_snow = 0.
+ fevpg = fevpg_soil; fevpg_snow = 0.
+ ENDIF
+
+ IF(fevpg_snow >= 0.)THEN
+! not allow for sublimation in melting (melting ==> evap. ==> sublimation)
+ qseva_snow = min(wliq_soisno(lb)/deltim, fevpg_snow)
+ qsubl_snow = fevpg_snow - qseva_snow
+ qseva_snow = qseva_snow*fsno
+ qsubl_snow = qsubl_snow*fsno
+ ELSE
+ ! snow temperature < tfrz
+ IF(t_soisno(lb) < tfrz)THEN
+ qfros_snow = abs(fevpg_snow*fsno)
+ ELSE
+ qsdew_snow = abs(fevpg_snow*fsno)
+ ENDIF
+ ENDIF
+
+ IF(fevpg_soil >= 0.)THEN
+! not allow for sublimation in melting (melting ==> evap. ==> sublimation)
+ qseva_soil = min(wliq_soisno(1)/deltim, fevpg_soil)
+ qsubl_soil = fevpg_soil - qseva_soil
+ ELSE
+ ! soil temperature < tfrz
+ IF(t_soisno(1) < tfrz)THEN
+ qfros_soil = abs(fevpg_soil)
+ ELSE
+ qsdew_soil = abs(fevpg_soil)
+ ENDIF
+ ENDIF
+
+ IF (lb < 1) THEN ! snow layer exists
+ qseva_soil = qseva_soil*(1.-fsno)
+ qsubl_soil = qsubl_soil*(1.-fsno)
+ qfros_soil = qfros_soil*(1.-fsno)
+ qsdew_soil = qsdew_soil*(1.-fsno)
+ ENDIF
+ENDIF
+
+
+! total fluxes to atmosphere
+ fsena = fsenl + fseng
+ fevpa = fevpl + fevpg
+ lfevpa = hvap*fevpl + htvp*fevpg ! W/m^2 (accounting for sublimation)
+
+! ground heat flux
+IF (.not.DEF_SPLIT_SOILSNOW) THEN
+ fgrnd = sabg + dlrad*emg &
+ - emg*stefnc*t_grnd_bef**4 &
+ - emg*stefnc*t_grnd_bef**3*(4.*tinc) &
+ - (fseng+fevpg*htvp) &
+ + cpliq*pg_rain*(t_precip-t_grnd) &
+ + cpice*pg_snow*(t_precip-t_grnd)
+ELSE
+ fgrnd = sabg + dlrad*emg &
+ - fsno*emg*stefnc*t_snow**4 &
+ - (1.-fsno)*emg*stefnc*t_soil**4 &
+ - emg*stefnc*t_grnd_bef**3*(4.*tinc) &
+ - (fseng+fevpg*htvp) &
+ + cpliq*pg_rain*(t_precip-t_grnd) &
+ + cpice*pg_snow*(t_precip-t_grnd)
+ENDIF
+
+! outgoing long-wave radiation from canopy + ground
+ olrg = ulrad &
+! for conservation we put the increase of ground longwave to outgoing
+ + 4.*emg*stefnc*t_grnd_bef**3*tinc
+
+! averaged bulk surface emissivity
+ olrb = stefnc*t_grnd_bef**3*(4.*tinc)
+ olru = ulrad + emg*olrb
+ olrb = ulrad + olrb
+ emis = olru / olrb
+
+! radiative temperature
+ IF (olrg < 0) THEN
+ print *, "MOD_Thermal.F90: Error! Negative outgoing longwave radiation flux: "
+ write(6,*) ipatch, olrg, tinc, ulrad
+ write(6,*) ipatch,errore,sabv,sabg,frl,olrg,fsenl,fseng,hvap*fevpl,htvp*fevpg,xmf,fgrnd
+ ENDIF
+
+ trad = (olrg/stefnc)**0.25
+
+! additional variables required by WRF and RSM model
+ IF (lai+sai <= 1e-6) THEN
+ ustar = ustar_g
+ tstar = tstar_g
+ qstar = qstar_g
+ rib = rib_g
+ zol = zol_g
+ z0m = z0m_g
+ fm = fm_g
+ fh = fh_g
+ fq = fq_g
+ ENDIF
+
+
+!=======================================================================
+! [7] energy balance error
+!=======================================================================
+
+ ! one way to check energy balance
+ errore = sabv + sabg + frl - olrg - fsena - lfevpa - fgrnd - dheatl + hprl &
+ + cpliq*pg_rain*(t_precip-t_grnd) + cpice*pg_snow*(t_precip-t_grnd)
+
+ ! another way to check energy balance
+ errore = sabv + sabg + frl - olrg - fsena - lfevpa - xmf - dheatl + hprl &
+ + cpliq*pg_rain*(t_precip-t_grnd) + cpice*pg_snow*(t_precip-t_grnd)
+
+ DO j = lb, nl_soil
+ errore = errore - (t_soisno(j)-t_soisno_bef(j))/fact(j)
+ ENDDO
+
+#if (defined CoLMDEBUG)
+ IF (abs(errore) > .5) THEN
+ write(6,*) 'MOD_Thermal.F90: energy balance violation'
+ write(6,*) ipatch,errore,sabv,sabg,frl,olrg,fsenl,fseng,hvap*fevpl,htvp*fevpg,xmf,hprl
+ write(6,*) cpliq*pg_rain*(t_precip-t_grnd), cpice*pg_snow*(t_precip-t_grnd)
+ CALL CoLM_stop ()
+ ENDIF
+100 format(10(f15.3))
+#endif
+
+ END SUBROUTINE THERMAL
+
+END MODULE MOD_Thermal
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_TurbulenceLEddy.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_TurbulenceLEddy.F90
new file mode 100644
index 0000000000..6ab6cbff0f
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_TurbulenceLEddy.F90
@@ -0,0 +1,465 @@
+MODULE MOD_TurbulenceLEddy
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: moninobuk_leddy
+ PUBLIC :: moninobukm_leddy
+
+
+! PRIVATE MEMBER FUNCTIONS:
+ PRIVATE :: psi
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE moninobuk_leddy(hu,ht,hq,displa,z0m,z0h,z0q,obu,um, hpbl, &
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+
+!=======================================================================
+!
+! Implement the LZD2022 scheme (Liu et al., 2022), which accounts for
+! large eddy effects by including the boundary layer height in the phim
+! FUNCTION, to compute friction velocity, relation for potential
+! temperature and humidity profiles of surface boundary layer.
+!
+! !REFERENCES:
+! [1] Zeng et al., 1998: Intercomparison of bulk aerodynamic algorithms
+! for the computation of sea surface fluxes using TOGA CORE and TAO
+! data. J. Climate, 11: 2628-2644.
+! [2] Liu et al., 2022: A surface flux estimation scheme accounting for
+! large-eddy effects for land surface modeling. GRL, 49,
+! e2022GL101754.
+!
+! Created by Shaofeng Liu, May 5, 2023
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+
+ real(r8), intent(in) :: hu ! observational height of wind [m]
+ real(r8), intent(in) :: ht ! observational height of temperature [m]
+ real(r8), intent(in) :: hq ! observational height of humidity [m]
+ real(r8), intent(in) :: displa ! displacement height [m]
+ real(r8), intent(in) :: z0m ! roughness length, momentum [m]
+ real(r8), intent(in) :: z0h ! roughness length, sensible heat [m]
+ real(r8), intent(in) :: z0q ! roughness length, latent heat [m]
+ real(r8), intent(in) :: obu ! monin-obukhov length (m)
+ real(r8), intent(in) :: um ! wind speed including the stability effect [m/s]
+ real(r8), intent(in) :: hpbl ! atmospheric boundary layer height [m]
+
+ real(r8), intent(out) :: ustar ! friction velocity [m/s]
+ real(r8), intent(out) :: fh2m ! relation for temperature at 2m
+ real(r8), intent(out) :: fq2m ! relation for specific humidity at 2m
+ real(r8), intent(out) :: fm10m ! integral of profile FUNCTION for momentum at 10m
+ real(r8), intent(out) :: fm ! integral of profile FUNCTION for momentum
+ real(r8), intent(out) :: fh ! integral of profile FUNCTION for heat
+ real(r8), intent(out) :: fq ! integral of profile FUNCTION for moisture
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) zetam, &
+ zetam2 ! transition point of flux-gradient relation (wind profile)
+ real(r8) zetat ! transition point of flux-gradient relation (temp. profile)
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+ real(r8) zetazi ! hpbl/obu, dimensionless height used in the LZD2022 scheme
+ real(r8) Bm ! Coefficient of the LZD2022 scheme: Bm = 0.0047*(-hpbl/L) + 0.1854
+ real(r8) Bm2 ! max(Bm, 0.2722)
+
+! real(r8), external :: psi ! stability FUNCTION for unstable CASE
+!-----------------------------------------------------------------------
+! adjustment factors for unstable (moz < 0) or stable (moz > 0) conditions.
+
+! wind profile
+ zldis=hu-displa
+ zeta=zldis/obu
+!
+! Begin: Shaofeng Liu, 2023.05.05
+!
+ zetazi = max(5.*hu, hpbl)/obu
+ IF(zetazi >= 0.) THEN !stable
+ zetazi = min(200.,max(zetazi,1.e-5))
+ ELSE !unstable
+ zetazi = max(-1.e4,min(zetazi,-1.e-5))
+ ENDIF
+
+ Bm = 0.0047 * (-zetazi) + 0.1854
+ zetam = 0.5*Bm**4 * ( -16. - sqrt(256. + 4./Bm**4) )
+ Bm2 = max(Bm, 0.2722)
+ zetam2 = min(zetam, -0.13)
+
+ IF(zeta < zetam2)THEN ! zeta < zetam2
+ fm = log(zetam2*obu/z0m) - psi(1,zetam2) &
+ + psi(1,z0m/obu) - 2.*Bm2 * ( (-zeta)**(-0.5)-(-zetam2)**(-0.5) )
+ ustar = vonkar*um / fm
+!
+! End: Shaofeng Liu, 2023.05.05
+!
+ ELSEIF (zeta < 0.)THEN ! zetam2 <= zeta < 0
+ fm = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ustar = vonkar*um / fm
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fm = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ustar = vonkar*um / fm
+ ELSE ! 1 < zeta, phi=5+zeta
+ fm = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ustar = vonkar*um / fm
+ ENDIF
+
+! for 10 meter wind-velocity
+ zldis=10.+z0m
+ zeta=zldis/obu
+!
+! Begin: Shaofeng Liu, 2023.05.18
+!
+ IF(zeta < zetam2)THEN ! zeta < zetam2
+ fm10m = log(zetam2*obu/z0m) - psi(1,zetam2) &
+ + psi(1,z0m/obu) - 2.*Bm2 * ( (-zeta)**(-0.5)-(-zetam2)**(-0.5) )
+!
+! End: Shaofeng Liu, 2023.05.18
+!
+ ELSEIF (zeta < 0.)THEN ! zetam2 <= zeta < 0
+ fm10m = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fm10m = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fm10m = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! temperature profile
+ zldis=ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for 2 meter screen temperature
+ zldis=2.+z0h ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh2m = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh2m = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh2m = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh2m = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! humidity profile
+ zldis=hq-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq = log(-zetat*obu/z0q) - psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fq = log(zldis/z0q) - psi(2,zeta) + psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fq = log(zldis/z0q) + 5.*zeta - 5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq = log(obu/z0q) + 5. - 5.*z0q/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for 2 meter screen humidity
+ zldis=2.+z0h
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq2m = log(-zetat*obu/z0q)-psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.) THEN ! -1 <= zeta < 0
+ fq2m = log(zldis/z0q)-psi(2,zeta)+psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.) THEN ! 0 <= zeta <= 1
+ fq2m = log(zldis/z0q)+5.*zeta-5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq2m = log(obu/z0q)+5.-5.*z0q/obu+(5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ END SUBROUTINE moninobuk_leddy
+
+
+ SUBROUTINE moninobukm_leddy(hu,ht,hq,displa,z0m,z0h,z0q,obu,um,displat,z0mt, hpbl, &
+ ustar,fh2m,fq2m,htop,fmtop,fm,fh,fq,fht,fqt,phih)
+
+!=======================================================================
+!
+! !DESCRIPTION:
+!
+!
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! calculation of friction velocity, relation for potential temperature and
+! humidity profiles of surface boundary layer. the scheme is based on the work
+! of Zeng et al. (1998): Intercomparison of bulk aerodynamic algorithms for the
+! computation of sea surface fluxes using TOGA CORE and TAO data. J. Climate,
+! Vol. 11: 2628-2644
+!
+! !REVISIONS:
+! Hua Yuan, 09/2017: adapted from moninobuk FUNCTION to calculate canopy top
+! fm, fq and phih for roughness sublayer u/k profile calculation
+! Shaofeng Liu, 05/2023: implement the LZD2022 scheme (Liu et al., 2022), which
+! accounts for large eddy effects by including the
+! boundary leyer height in the phim FUNCTION.
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar
+ IMPLICIT NONE
+
+! ---------------------- dummy argument --------------------------------
+
+ real(r8), intent(in) :: hu ! observational height of wind [m]
+ real(r8), intent(in) :: ht ! observational height of temperature [m]
+ real(r8), intent(in) :: hq ! observational height of humidity [m]
+ real(r8), intent(in) :: displa ! displacement height [m]
+ real(r8), intent(in) :: displat ! displacement height of the top layer [m]
+ real(r8), intent(in) :: z0m ! roughness length, momentum [m]
+ real(r8), intent(in) :: z0h ! roughness length, sensible heat [m]
+ real(r8), intent(in) :: z0q ! roughness length, latent heat [m]
+ real(r8), intent(in) :: z0mt ! roughness length of the top layer, latent heat [m]
+ real(r8), intent(in) :: htop ! canopy top height of the top layer [m]
+ real(r8), intent(in) :: obu ! monin-obukhov length (m)
+ real(r8), intent(in) :: um ! wind speed including the stability effect [m/s]
+ real(r8), intent(in) :: hpbl ! atmospheric boundary layer height [m]
+
+ real(r8), intent(out) :: ustar ! friction velocity [m/s]
+ real(r8), intent(out) :: fh2m ! relation for temperature at 2m
+ real(r8), intent(out) :: fq2m ! relation for specific humidity at 2m
+ real(r8), intent(out) :: fmtop ! integral of profile FUNCTION for momentum at 10m
+ real(r8), intent(out) :: fm ! integral of profile FUNCTION for momentum
+ real(r8), intent(out) :: fh ! integral of profile FUNCTION for heat
+ real(r8), intent(out) :: fq ! integral of profile FUNCTION for moisture
+ real(r8), intent(out) :: fht ! integral of profile FUNCTION for heat at the top layer
+ real(r8), intent(out) :: fqt ! integral of profile FUNCTION for moisture at the top layer
+ real(r8), intent(out) :: phih ! phi(h), similarity FUNCTION for sensible heat
+
+!------------------------ local variables ------------------------------
+
+ real(r8) zldis ! reference height "minus" zero displacement height [m]
+ real(r8) zetam, &
+ zetam2 ! transition point of flux-gradient relation (wind profile)
+ real(r8) zetat ! transition point of flux-gradient relation (temp. profile)
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+ real(r8) zetazi ! hpbl/obu, dimensionless height used in the LZD2022 scheme
+ real(r8) Bm ! Coefficient of the LZD2022 scheme: Bm = 0.0047*(-hpbl/L) + 0.1854
+ real(r8) Bm2 ! max(Bm, 0.2722)
+
+! real(r8), external :: psi ! stability FUNCTION for unstable CASE
+!-----------------------------------------------------------------------
+! adjustment factors for unstable (moz < 0) or stable (moz > 0) conditions.
+
+! wind profile
+ zldis=hu-displa
+ zeta=zldis/obu
+!
+! Begin: Shaofeng Liu, 2023.05.05
+!
+! zetazi = hpbl/obu
+ zetazi = max(5.*hu, hpbl)/obu
+ IF(zetazi >= 0.) THEN !stable
+ zetazi = min(200.,max(zetazi,1.e-5))
+ ELSE !unstable
+ zetazi = max(-1.e4,min(zetazi,-1.e-5))
+ ENDIF
+
+ Bm = 0.0047 * (-zetazi) + 0.1854
+ zetam = 0.5*Bm**4 * ( -16. - sqrt(256. + 4./Bm**4) )
+ Bm2 = max(Bm, 0.2722)
+ zetam2 = min(zetam, -0.13)
+
+ IF(zeta < zetam2)THEN ! zeta < zetam2
+ fm = log(zetam2*obu/z0m) - psi(1,zetam2) &
+ + psi(1,z0m/obu) - 2.*Bm2 * ( (-zeta)**(-0.5)-(-zetam2)**(-0.5) )
+ ustar = vonkar*um / fm
+!
+! End: Shaofeng Liu, 2023.05.05
+!
+ ELSEIF (zeta < 0.)THEN ! zetam2 <= zeta < 0
+ fm = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ustar = vonkar*um / fm
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fm = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ustar = vonkar*um / fm
+ ELSE ! 1 < zeta, phi=5+zeta
+ fm = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ustar = vonkar*um / fm
+ ENDIF
+
+! for canopy top wind-velocity
+!NOTE: changed for canopy top wind-velocity (no wake assumed)
+ zldis=htop-displa
+ zeta=zldis/obu
+!
+! Begin: Shaofeng Liu, 2023.05.18
+!
+! zetam=1.574
+ IF(zeta < zetam2)THEN ! zeta < zetam2
+ fmtop = log(zetam2*obu/z0m) - psi(1,zetam2) &
+ + psi(1,z0m/obu) - 2.*Bm2 * ( (-zeta)**(-0.5)-(-zetam2)**(-0.5) )
+!
+! End: Shaofeng Liu, 2023.05.18
+!
+ ELSEIF (zeta < 0.)THEN ! zetam2 <= zeta < 0
+ fmtop = log(zldis/z0m) - psi(1,zeta) + psi(1,z0m/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fmtop = log(zldis/z0m) + 5.*zeta - 5.*z0m/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fmtop = log(obu/z0m) + 5. - 5.*z0m/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! temperature profile
+ zldis=ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for 2 meter screen temperature
+ zldis=2.+z0h ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fh2m = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fh2m = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fh2m = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fh2m = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for top layer temperature
+ zldis=displat+z0mt-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fht = log(-zetat*obu/z0h)-psi(2,-zetat) &
+ + psi(2,z0h/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fht = log(zldis/z0h) - psi(2,zeta) + psi(2,z0h/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fht = log(zldis/z0h) + 5.*zeta - 5.*z0h/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fht = log(obu/z0h) + 5. - 5.*z0h/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for canopy top phi(h)
+! CESM TECH NOTE eq. (5.31)
+ zldis=htop-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ phih = 0.9*vonkar**(1.333)*(-zeta)**(-0.333)
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ phih = (1. - 16.*zeta)**(-0.5)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ phih = 1. + 5.*zeta
+ ELSE ! 1 < zeta, phi=5+zeta
+ phih = 5. + zeta
+ ENDIF
+
+! humidity profile
+ zldis=hq-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq = log(-zetat*obu/z0q) - psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.)THEN ! -1 <= zeta < 0
+ fq = log(zldis/z0q) - psi(2,zeta) + psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.)THEN ! 0 <= zeta <= 1
+ fq = log(zldis/z0q) + 5.*zeta - 5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq = log(obu/z0q) + 5. - 5.*z0q/obu + (5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for 2 meter screen humidity
+ zldis=2.+z0h
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fq2m = log(-zetat*obu/z0q)-psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.) THEN ! -1 <= zeta < 0
+ fq2m = log(zldis/z0q)-psi(2,zeta)+psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.) THEN ! 0 <= zeta <= 1
+ fq2m = log(zldis/z0q)+5.*zeta-5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fq2m = log(obu/z0q)+5.-5.*z0q/obu+(5.*log(zeta)+zeta-1.)
+ ENDIF
+
+! for top layer humidity
+ zldis=displat+z0mt-displa ! ht-displa
+ zeta=zldis/obu
+ zetat=0.465
+ IF(zeta < -zetat)THEN ! zeta < -1
+ fqt = log(-zetat*obu/z0q)-psi(2,-zetat) &
+ + psi(2,z0q/obu) + 0.8*((zetat)**(-0.333)-(-zeta)**(-0.333))
+ ELSEIF (zeta < 0.) THEN ! -1 <= zeta < 0
+ fqt = log(zldis/z0q)-psi(2,zeta)+psi(2,z0q/obu)
+ ELSEIF (zeta <= 1.) THEN ! 0 <= zeta <= 1
+ fqt = log(zldis/z0q)+5.*zeta-5.*z0q/obu
+ ELSE ! 1 < zeta, phi=5+zeta
+ fqt = log(obu/z0q)+5.-5.*z0q/obu+(5.*log(zeta)+zeta-1.)
+ ENDIF
+
+ END SUBROUTINE moninobukm_leddy
+
+
+
+ real(r8) FUNCTION psi(k,zeta)
+
+!=======================================================================
+! stability FUNCTION for unstable CASE (rib < 0)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer k
+ real(r8) zeta ! dimensionless height used in Monin-Obukhov theory
+ real(r8) chik !
+
+ chik = (1.-16.*zeta)**0.25
+ IF(k == 1)THEN
+ psi = 2.*log((1.+chik)*0.5)+log((1.+chik*chik)*0.5)-2.*atan(chik)+2.*atan(1.)
+ ELSE
+ psi = 2.*log((1.+chik*chik)*0.5)
+ ENDIF
+
+ END FUNCTION psi
+
+
+END MODULE MOD_TurbulenceLEddy
+! --------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_UserSpecifiedForcing.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_UserSpecifiedForcing.F90
new file mode 100644
index 0000000000..692a8a5be6
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_UserSpecifiedForcing.F90
@@ -0,0 +1,969 @@
+#include
+
+MODULE MOD_UserSpecifiedForcing
+
+!DESCRIPTION
+!===========
+ !---This MODULE is used for read atmospheric forcing dataset from various sources.
+ ! ------------------------------------------------------------
+ ! Read forcing data from :
+ ! 1) PRINCETON 2) GSWP2 3) GSWP3
+ ! 4) QIAN 5) CRUNCEPV4 6) CRUNCEPV7
+ ! 7) ERA5LAND 8) ERA5 9) MSWX
+ ! 10) WFDE5 11) CRUJRA 12) WFDEI
+ ! 13) JRA55 14) GDAS 15) CLDAS
+ ! 16) CMFD 17) TPMFD 18) CMIP6
+ ! 19) POINT 20) JRA3Q 21) CRA40
+ !
+ ! PLEASE modify the following codes when specified forcing used
+ ! ------------------------------------------------------------
+!Original Author:
+!-------------------
+ !---Shupeng Zhang and Zhongwang Wei
+
+!References:
+!-------------------
+ !---In preparation
+
+!ANCILLARY FUNCTIONS AND SUBROUTINES
+!-------------------
+ !* :SUBROUTINE:"init_user_specified_forcing" : initialization of the selected forcing dataset
+ !* :SUBROUTINE:"metfilename" : identify the forcing file name
+ !* :SUBROUTINE:"metpreprocess" : preprocess the forcing data
+
+!REVISION HISTORY
+ !----------------
+ ! 2023.05.01 Shupeng Zhang and Zhongwang Wei @ SYSU
+ ! 2021.12.02 Shupeng Zhang and Zhongwang Wei @ SYSU
+ ! Siguang Zhu and Nan Wei, 10/2014: metpreprocess for forc_q calibration
+ ! Hua Yuan, 04/2014: initial code of forcing structure for CoLM2014
+
+ USE MOD_Precision
+
+ IMPLICIT NONE
+
+ character(len=256) :: dataset
+
+ logical :: solarin_all_band ! whether solar radiation in all bands is available
+
+ character(len=256) :: HEIGHT_mode ! observation height mode
+ real(r8) :: HEIGHT_V ! observation height of wind speed
+ real(r8) :: HEIGHT_T ! observation height of air temperature
+ real(r8) :: HEIGHT_Q ! observation height of specific humidity
+
+ integer :: NVAR ! variable number of forcing data
+ integer :: startyr ! start year of forcing data
+ integer :: startmo ! start month of forcing data
+ integer :: endyr ! END year of forcing data
+ integer :: endmo ! END month of forcing data
+
+ integer, allocatable :: dtime(:) ! time interval of forcing data
+ integer, allocatable :: offset(:) ! offset of forcing data
+
+ logical :: leapyear ! leapyear calendar
+ logical :: data2d ! data in 2 dimension (lon, lat)
+ logical :: hightdim ! have "z" dimension
+ logical :: dim2d ! lat/lon value in 2 dimension (lon, lat)
+
+ character(len=256) :: latname ! dimension name of latitude
+ character(len=256) :: lonname ! dimension name of longitude
+
+ character(len=256) :: groupby ! file grouped by year/month
+
+ character(len=256), allocatable :: fprefix(:) ! file prefix
+ character(len=256), allocatable :: vname(:) ! variable name
+ character(len=256), allocatable :: timelog(:) ! variable time log info
+ character(len=256), allocatable :: tintalgo(:) ! interpolation algorithm
+
+ ! ----- public subroutines -----
+ PUBLIC :: init_user_specified_forcing ! initialization of the selected forcing dataset
+ PUBLIC :: metfilename ! identify the forcing file name
+ PUBLIC :: metpreprocess ! preprocess the forcing data
+
+CONTAINS
+
+ ! ----------------
+ SUBROUTINE init_user_specified_forcing
+
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ ! Local variables
+ integer :: ivar,NVAR_default
+
+ NVAR = DEF_forcing%NVAR
+ NVAR_default=NVAR
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ NVAR=NVAR+1
+ ENDIF
+
+ IF (allocated(dtime )) deallocate(dtime)
+ IF (allocated(offset)) deallocate(offset)
+ allocate (dtime (NVAR))
+ allocate (offset (NVAR))
+
+ IF (allocated(fprefix )) deallocate(fprefix )
+ IF (allocated(vname )) deallocate(vname )
+ IF (allocated(timelog )) deallocate(timelog )
+ IF (allocated(tintalgo)) deallocate(tintalgo)
+ allocate (fprefix (NVAR))
+ allocate (vname (NVAR))
+ allocate (timelog (NVAR))
+ allocate (tintalgo (NVAR))
+
+ solarin_all_band = DEF_forcing%solarin_all_band ! whether solar radiation in all bands
+ HEIGHT_mode = DEF_forcing%HEIGHT_mode ! observation height mode
+ HEIGHT_V = DEF_forcing%HEIGHT_V ! observation height of wind speed
+ HEIGHT_T = DEF_forcing%HEIGHT_T ! observation height of air temperature
+ HEIGHT_Q = DEF_forcing%HEIGHT_Q ! observation height of specific humidity
+
+ startyr = DEF_forcing%startyr ! start year of forcing data
+ startmo = DEF_forcing%startmo ! start month of forcing data
+ endyr = DEF_forcing%endyr ! end year of forcing data
+ endmo = DEF_forcing%endmo ! end month of forcing data
+ dtime(:) = DEF_forcing%dtime(:) ! time interval of forcing data
+ offset(:) = DEF_forcing%offset(:) ! offset of forcing data
+
+ leapyear = DEF_forcing%leapyear ! whether leapyear calendar
+ data2d = DEF_forcing%data2d ! whether data in 2 dimension (lon, lat)
+ hightdim = DEF_forcing%hightdim ! whether have "z" dimension (height)
+ dim2d = DEF_forcing%dim2d ! whether lat/lon in 2 dimension (lon,lat)
+
+ latname = DEF_forcing%latname ! dimension name of latitude
+ lonname = DEF_forcing%lonname ! dimension name of longitude
+
+ groupby = DEF_forcing%groupby ! file grouped by year/month
+
+ DO ivar = 1, NVAR_default
+ fprefix (ivar) = DEF_forcing%fprefix(ivar) ! file prefix
+ vname (ivar) = DEF_forcing%vname(ivar) ! variable name
+ timelog (ivar) = DEF_forcing%timelog(ivar) ! variable name
+ tintalgo(ivar) = DEF_forcing%tintalgo(ivar) ! interpolation algorithm
+ ENDDO
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ fprefix (NVAR) = DEF_forcing%CBL_fprefix
+ vname (NVAR) = DEF_forcing%CBL_vname
+ tintalgo(NVAR) = DEF_forcing%CBL_tintalgo
+ dtime (NVAR) = DEF_forcing%CBL_dtime
+ offset (NVAR) = DEF_forcing%CBL_offset
+ ENDIF
+ END SUBROUTINE init_user_specified_forcing
+
+ ! ----------------
+ FUNCTION metfilename(year, month, day, var_i, is_spinup)
+
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ integer, intent(in) :: year
+ integer, intent(in) :: month
+ integer, intent(in) :: day
+ integer, intent(in) :: var_i
+
+ logical, intent(in), optional :: is_spinup
+
+ character(len=256) :: metfilename
+ character(len=256) :: yearstr
+ character(len=256) :: monthstr
+
+ write(yearstr, '(I4.4)') year
+ write(monthstr, '(I2.2)') month
+
+ IF (present(is_spinup)) THEN
+ IF (DEF_USE_ClimForcing_for_Spinup .and. is_spinup) THEN
+ yearstr = 'clim'
+ ENDIF
+ ENDIF
+
+ select CASE (trim(DEF_forcing%dataset))
+ CASE ('PRINCETON') ! Princeton forcing data
+ !DESCRIPTION
+ !===========
+ !---Princeton Global Meteorological Forcing Dataset for Land Surface Modeling
+
+ !data source:
+ !-------------------
+ !---https://rda.ucar.edu/datasets/ds314.0/
+
+ !References:
+ !-------------------
+ !---Sheffield, J., G. Goteti, and E. F. Wood, 2006: Development of a 50-year
+ ! high-resolution global dataset of meteorological forcings for land surface modeling J.
+ ! Climate, 19(13), 3088-3111.
+
+ !REVISION HISTORY
+ !----------------
+ !---2022.05.01 Zhongwang Wei @ SYSU: remove the "z" dimension
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'-'//trim(yearstr)//'.nc'
+ CASE ('GSWP3') ! GSWP3 forcing data
+ !DESCRIPTION
+ !===========
+ !---Global Meteorological Forcing Dataset for Global Soil Wetness Project Phase 3
+
+ !data source:
+ !-------------------
+ !---http://hydro.iis.u-tokyo.ac.jp/GSWP3/
+ !---https://www.isimip.org/gettingstarted/input-data-bias-adjustment/details/4/
+
+ !References:
+ !-------------------
+ !---Dirmeyer, P. A., Gao, X., Zhao, M., Guo, Z., Oki, T. and Hanasaki, N. (2006) GSWP-2:
+ ! Multimodel Analysis and Implications for Our Perception of the Land Surface. Bulletin
+ ! of the American Meteorological Society, 87(10), 1381-98.
+
+ !REVISION HISTORY
+ !----------------
+ !---
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'-'//trim(monthstr)//'.nc'
+ CASE ('QIAN') ! Qian forcing data
+ !DESCRIPTION
+ !===========
+ !---Qian Global Meteorological Forcing Dataset from 1948 to 2004
+
+ !data source:
+ !-------------------
+ !---Not available now!
+
+ !References:
+ !-------------------
+ !---Qian T., and co-authors, 2006: Simulation of Global Land Surface Conditions from 1948
+ ! to 2004. Part I: Forcing Data and Evaluations. J. Hydrometeorol., 7, 953-975.
+
+ !REVISION HISTORY
+ !----------------
+ !---
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'-'//trim(monthstr)//'.nc'
+ CASE ('CRUNCEPV4') ! CRUNCEP V4 forcing data
+ !DESCRIPTION
+ !===========
+ !---CRUNCEP Version 4 - Atmospheric Forcing Data for the Community Land Model
+
+ !data source:
+ !-------------------
+ !---http://dods.extra.cea.fr/data/p529viov/cruncep/V5_1901_2013/
+
+ !References:
+ !-------------------
+ !---Viovy, N. (2010), CRU‐NCEP dataset.
+ ! [Available at: http://dods.extra.cea.fr/data/p529viov/cruncep/readme.htm.]
+
+ !REVISION HISTORY
+ !----------------
+ !---
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'-'//trim(monthstr)//'.nc'
+ CASE ('CRUNCEPV7') ! CRUNCEP V7 forcing data
+ !DESCRIPTION
+ !===========
+ !---CRUNCEP Version 7 - Atmospheric Forcing Data for the Community Land Model
+
+ !data source:
+ !-------------------
+ !---https://rda.ucar.edu/datasets/ds314.3/
+
+ !References:
+ !-------------------
+ !---Viovy, Nicolas. (2018). CRUNCEP Version 7 -
+ ! Atmospheric Forcing Data for the Community Land Model.
+ ! Research Data Archive at the National Center for Atmospheric Research,
+ ! Computational and Information Systems Laboratory.
+ ! https://doi.org/10.5065/PZ8F-F017. Accessed 05 May 2023.
+
+ !REVISION HISTORY
+ !----------------
+ !---
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'-'//trim(monthstr)//'.nc'
+ CASE ('ERA5LAND') ! ERA5-Land forcing data
+ !DESCRIPTION
+ !===========
+ !---enhanced global dataset for the land component of the fifth
+ ! generation of European ReAnalysis (ERA5)
+
+ !data source:
+ !-------------------
+ !---https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-land?tab=form
+
+ !References:
+ !-------------------
+ !---Muñoz-Sabater, J., Dutra, E., Agustí-Panareda, A., Albergel, C., Arduini, G., Balsamo,
+ ! G., Boussetta, S., Choulga, M., Harrigan, S., Hersbach, H. and Martens, B., 2021.
+ ! ERA5-Land: A state-of-the-art global reanalysis dataset for land applications. Earth
+ ! System Science Data, 13(9), pp.4349-4383.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: zip file to reduce the size of the data;
+ ! remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'_'//trim(monthstr)
+ select CASE (var_i)
+ CASE (1)
+ metfilename = trim(metfilename) // '_2m_temperature.nc'
+ CASE (2)
+ metfilename = trim(metfilename) //'_specific_humidity.nc'
+ CASE (3)
+ metfilename = trim(metfilename) //'_surface_pressure.nc'
+ CASE (4)
+ metfilename = trim(metfilename) //'_total_precipitation_m_hr.nc'
+ CASE (5)
+ metfilename = trim(metfilename) //'_10m_u_component_of_wind.nc'
+ CASE (6)
+ metfilename = trim(metfilename) //'_10m_v_component_of_wind.nc'
+ CASE (7)
+ metfilename = trim(metfilename) //'_surface_solar_radiation_downwards_w_m2.nc'
+ CASE (8)
+ metfilename = trim(metfilename) //'_surface_thermal_radiation_downwards_w_m2.nc'
+ END select
+ CASE ('ERA5') ! ERA5 forcing data
+ !DESCRIPTION
+ !===========
+ !---The fifth generation of European ReAnalysis (ERA5)
+
+ !data source:
+ !-------------------
+ !---https://cds.climate.copernicus.eu/cdsapp#!
+ ! /dataset/reanalysis-era5-single-levels?tab=overview
+
+ !References:
+ !-------------------
+ !---Hersbach, H., Bell, B., Berrisford, P., Hirahara, S., Horányi, A., Muñoz‐Sabater, J.,
+ ! Nicolas, J., Peubey, C., Radu, R., Schepers, D. and Simmons, A., 2020. The ERA5 global
+ ! reanalysis. Quarterly Journal of the Royal Meteorological Society, 146(730),
+ ! pp.1999-2049.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: zip file to reduce the size of the data; remove
+ ! offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'_'//trim(monthstr)
+ select CASE (var_i)
+ CASE (1)
+ metfilename = trim(metfilename) // '_2m_temperature.nc4'
+ CASE (2)
+ metfilename = trim(metfilename) //'_q.nc4'
+ CASE (3)
+ metfilename = trim(metfilename) //'_surface_pressure.nc4'
+ CASE (4)
+ metfilename = trim(metfilename) //'_mean_total_precipitation_rate.nc4'
+ CASE (5)
+ metfilename = trim(metfilename) //'_10m_u_component_of_wind.nc4'
+ CASE (6)
+ metfilename = trim(metfilename) //'_10m_v_component_of_wind.nc4'
+ CASE (7)
+ metfilename = trim(metfilename) //'_mean_surface_downward_short_wave_radiation_flux.nc4'
+ CASE (8)
+ metfilename = trim(metfilename) //'_mean_surface_downward_long_wave_radiation_flux.nc4'
+ END select
+ CASE ('MSWX') ! MSWX forcing data
+ !DESCRIPTION
+ !===========
+ !---Multi-Source Weather forcing data
+
+ !data source:
+ !-------------------
+ !---https://www.gloh2o.org/mswx/
+
+ !References:
+ !-------------------
+ !---Beck, H.E., van Dijk, A.I., Larraondo, P.R., McVicar, T.R., Pan, M., Dutra, E. and
+ ! Miralles, D.G., 2022. MSWX: Global 3-hourly 0.1 bias-corrected meteorological data
+ ! including near-real-time updates and forecast ensembles. Bulletin of the American
+ ! Meteorological Society, 103(3), pp.E710-E732.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: Regroup data into monthly
+
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'_'//trim(monthstr)//'.nc'
+ CASE ('WFDE5')
+ !DESCRIPTION
+ !===========
+ !---WATCH Forcing Data methodology applied to ERA5 reanalysis data
+
+ !data source:
+ !-------------------
+ !---https://doi.org/10.24381/cds.20d54e34
+
+ !References:
+ !-------------------
+ !---Cucchi, M., Weedon, G.P., Amici, A., Bellouin, N., Lange, S., Müller Schmied, H.,
+ ! Hersbach, H. and Buontempo, C., 2020. WFDE5: bias-adjusted ERA5 reanalysis data
+ ! for impact studies. Earth System Science Data, 12(3), pp.2097-2120.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: zip file to reduce the size of the data;
+ ! remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//trim(monthstr)//'_v2.1.nc'
+ CASE ('CRUJRA')
+ !DESCRIPTION
+ !===========
+ !---Collection of CRU JRA forcing datasets of gridded land surface blend
+ ! of Climatic Research Unit (CRU) and Japanese reanalysis (JRA) data
+
+ !data source:
+ !-------------------
+ !---https://catalogue.ceda.ac.uk/uuid/863a47a6d8414b6982e1396c69a9efe8
+
+ !References:
+ !-------------------
+ !---University of East Anglia Climatic Research Unit; Harris, I.C. (2019):
+ ! CRU JRA: Collection of CRU JRA forcing datasets of gridded land surface blend
+ ! of Climatic Research Unit (CRU) and Japanese reanalysis (JRA) data..
+ ! Centre for Environmental Data Analysis, date of citation.
+ !http://catalogue.ceda.ac.uk/uuid/863a47a6d8414b6982e1396c69a9efe8
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: zip file to reduce the size of the data;
+ ! remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'.365d.noc.nc'
+
+
+ CASE ('WFDEI')
+ !DESCRIPTION
+ !===========
+ !---WATCH Forcing Data methodology applied to ERA-Interim reanalysis data
+
+ !data source:
+ !-------------------
+ !---https://doi.org/10.24381/cds.20d54e34
+
+ !References:
+ !-------------------
+ !---Weedon, G.P., Balsamo, G., Bellouin, N., Gomes, S., Best, M.J. and Viterbo, P., 2014.
+ ! The WFDEI meteorological forcing data set: WATCH Forcing Data methodology applied
+ ! to ERA‐Interim reanalysis data. Water Resources Research, 50(9), pp.7505-7514.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: zip file to reduce the size of the data;
+ ! remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//'-'//trim(monthstr)//'.nc'
+ CASE ('JRA3Q')
+ !DESCRIPTION
+ !===========
+ !---Japanese Reanalysis for Three Quarters of a Century
+
+ !data source:
+ !-------------------
+ !---https://rda.ucar.edu/datasets/ds640.0/
+
+ !References:
+ !-------------------
+ !---Kosaka Y., S. Kobayashi, Y. Harada, C. Kobayashi, H. Naoe, K. Yoshimoto, M. Harada, N.
+ ! Goto, J. Chiba, K. Miyaoka, R. Sekiguchi, M. Deushi, H. Kamahori, T. Nakaegawa; T.
+ ! Y.Tanaka, T. Tokuhiro, Y. Sato, Y. Matsushita, and K. Onogi, 2024: The JRA-3Q
+ ! reanalysis. J. Meteor. Soc. Japan, 102, https://doi.org/10.2151/jmsj.2024-004.
+
+
+ !REVISION HISTORY
+ !----------------
+ !---2024.03.04 Zhongwang Wei @ SYSU: remove offset and scale_factor
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'_'//trim(monthstr)//'.nc'
+
+ CASE ('JRA55')
+ !DESCRIPTION
+ !===========
+ !---the Japanese 55-year Reanalysis
+
+ !data source:
+ !-------------------
+ !---https://jra.kishou.go.jp/JRA-55/index_en.html
+
+ !References:
+ !-------------------
+ !---Kobayashi, S., Y. Ota, Y. Harada, A. Ebita, M. Moriya, H. Onoda, K. Onogi,
+ ! H. Kamahori, C. Kobayashi, H. Endo, K. Miyaoka, and K. Takahashi , 2015:
+ ! The JRA-55 Reanalysis: General specifications and basic characteristics.
+ ! J. Meteor. Soc. Japan, 93, 5-48, doi:10.2151/jmsj.2015-001.
+ !---Harada, Y., H. Kamahori, C. Kobayashi, H. Endo, S. Kobayashi, Y. Ota, H. Onoda,
+ ! K. Onogi, K. Miyaoka, and K. Takahashi, 2016: The JRA-55 Reanalysis: Representation
+ ! of atmospheric circulation and climate variability, J. Meteor. Soc. Japan, 94,
+ ! 269-302, doi:10.2151/jmsj.2016-015.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: zip file to reduce the size of the data;
+ ! remove offset and scale_factor
+
+
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//trim(monthstr)//'.nc'
+
+
+ CASE ('GDAS')
+ !DESCRIPTION
+ !===========
+ !--- Forcing Data From Global Data Assimilation System
+
+ !data source:
+ !-------------------
+ !--https://disc.sci.gsfc.nasa.gov/datasets/GLDAS_NOAH025_3H_V2.1/summary
+
+ !References:
+ !-------------------
+ !---Beaudoing, H. and M. Rodell, NASA/GSFC/HSL (2020), GLDAS Noah Land Surface Model L4 3
+ ! hourly 0.25 x 0.25 degree V2.1, Greenbelt, Maryland, USA, Goddard Earth Sciences Data
+ ! and Information Services Center (GES DISC), Accessed: [Data Access Date],
+ ! 10.5067/E7TYRXPJKWOQ
+ !---Rodell, M., P.R. Houser, U. Jambor, J. Gottschalck, K. Mitchell, C. Meng, K. Arsenault,
+ ! B. Cosgrove, J. Radakovich, M. Bosilovich, J.K. Entin, J.P. Walker, D. Lohmann, and D.
+ ! Toll, 2004: The Global Land Data Assimilation System, Bull. Amer. Meteor. Soc., 85,
+ ! 381-394, doi:10.1175/BAMS-85-3-381
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: merge the data into monthly file;
+ ! zip file to reduce the size of the data; remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//trim(monthstr)//'.nc4'
+ CASE ('CLDAS')
+
+ !DESCRIPTION
+ !===========
+ !---The Real-Time Product Dataset Of The China Meteorological Administration
+ ! Land Data Assimilation System
+
+ !data source:
+ !-------------------
+ !--CMA, not pulicly available
+
+ !References:
+ !-------------------
+ !---Xia, Y.L.; Hao, Z.C.; Shi, C.X.; Li, Y.H.; Meng, J.; Xu, T.R.; Wu, X.Y.; Zhang, B.Q.
+ ! Regional and global land data assimilation systems: Innovations, challenges, and
+ ! prospects. J. Meteorol. Res. 2019, 33, 159-189.
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: gap filling for the missing data;
+ ! zip file to reduce the size of the data; remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//'-'//trim(yearstr)//trim(monthstr)//'.nc'
+ CASE ('CMFD')
+ !DESCRIPTION
+ !===========
+ !--- The China Meteorological Forcing Dataset
+
+ !data source:
+ !-------------------
+ !--https://data.tpdc.ac.cn/en/data/8028b944-daaa-4511-8769-965612652c49/
+
+ !References:
+ !-------------------
+ !---He, J., Yang, K., Tang, W., Lu, H., Qin, J., Chen, Y. and Li, X., 2020.
+ ! The first high-resolution meteorological forcing dataset for land process
+ ! studies over China. Scientific data, 7(1), p.25.
+
+ !REVISION HISTORY
+ !----------------
+ !---
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//trim(monthstr)//'.nc4'
+ CASE ('CMFDv2')
+ !DESCRIPTION
+ !===========
+ !--- The China Meteorological Forcing Dataset version 2.0
+
+ !data source:
+ !-------------------
+ !--https://data.tpdc.ac.cn/en/data/e60dfd96-5fd8-493f-beae-e8e5d24dece4
+
+ !References:
+ !-------------------
+ !---He, J., Yang, K., Li, X., Tang, W., Shao, C., Jiang, Y., Ding, B. 2024.
+ ! The China Meteorological Forcing Dataset (CMFD) version 2.0.
+ ! National Tibetan Plateau/Third Pole Environment Data Center,
+ ! https://doi.org/10.11888/Atmos.tpdc.300398. https://cstr.cn/18406.11.Atmos.tpdc.300398.
+
+ !REVISION HISTORY
+ !----------------
+ !---
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//trim(monthstr)//'.nc'
+ CASE ('CMIP6')
+ !DESCRIPTION
+ !===========
+ !---the Climate Model Intercomparison Project Phase 6 (CMIP6) forcing data sets
+
+ !data source:
+ !-------------------
+ !---https://esgf-node.llnl.gov/projects/cmip6/
+
+ !References:
+ !-------------------
+ !---
+
+ !REVISION HISTORY
+ !----------------
+ !---2021.11.01 Zhongwang Wei @ SYSU: regroup the data into monthly file;
+ ! zip file to reduce the size of the data; remove offset and scale_factor
+
+
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'.nc'
+
+ CASE ('CRA40')
+ !DESCRIPTION
+ !===========
+ !---CMA first-generation global atmospheric reanalysis (RA) covering 1979-2018 (CRA-40)
+
+ !data source:
+ !-------------------
+ !---https://data.cma.cn/en
+
+ !References:
+ !-------------------
+ !---Liu, Z., Jiang, L., Shi, C. et al. CRA-40/Atmosphere—The First-Generation Chinese
+ ! Atmospheric Reanalysis (1979-2018): System Description and Performance Evaluation. J
+ ! Meteorol Res 37, 1-19 (2023). https://doi.org/10.1007/s13351-023-2086-x
+
+
+
+ !REVISION HISTORY
+ !----------------
+ !---2024.04.10 Zhongwang Wei @ SYSU: regroup the data into annual file;
+ ! zip file to reduce the size of the data; remove offset and scale_factor
+
+
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'.nc'
+ CASE ('TPMFD')
+ !DESCRIPTION
+ !===========
+ !---A high-resolution near-surface meteorological forcing dataset for the Third Pole region
+
+ !data source:
+ !-------------------
+ !---https://data.tpdc.ac.cn/zh-hans/data/44a449ce-e660-44c3-bbf2-31ef7d716ec7
+
+ !References:
+ !-------------------
+ !---Yang, K., Jiang, Y., Tang, W., He, J., Shao, C., Zhou, X., Lu, H.,
+ ! Chen, Y., Li, X., Shi, J. (2023). A high-resolution near-surface
+ ! meteorological forcing dataset for the Third Pole region (TPMFD, 1979-2020).
+ ! National Tibetan Plateau/Third Pole Environment Data Center,
+ ! https://doi.org/10.11888/Atmos.tpdc.300398. https://cstr.cn/18406.11.Atmos.tpdc.300398.
+
+ !REVISION HISTORY
+ !----------------
+ !---2023.11.01 Zhongwang Wei @ SYSU: regroup the data into monthly file;
+ ! zip file to reduce the size of the data; remove offset and scale_factor
+
+ metfilename = '/'//trim(fprefix(var_i))//trim(yearstr)//trim(monthstr)//'.nc'
+ CASE ('IsoGSM')
+ !DESCRIPTION
+ !===========
+ !--- Isotopes-incorporated Global Spectral Model (IsoGSM)
+
+ !data source:
+ !-------------------
+ !---https://isotope.iis.u-tokyo.ac.jp/about-our-lab?lang=en
+
+ !References:
+ !-------------------
+ !---Bong, H., Cauquoin, A., Okazaki, A., Chang, E.-C., Werner, M., Wei, Z., et al. (2024).
+ ! Process-based intercomparison of water isotope-enabled models and reanalysis nudging effects.
+ ! Journal of Geophysical Research: Atmospheres, 129, e2023JD038719.
+ ! https://doi.org/10.1029/2023JD038719
+
+ !REVISION HISTORY
+ !----------------
+ !---2025.03.23 Zhongwang Wei @ SYSU: add the isotope forcing data
+
+ metfilename = '/'//trim(fprefix(var_i))//'_'//trim(yearstr)//'.nc'
+
+
+ CASE ('POINT')
+ metfilename = '/'//trim(fprefix(1))
+ END select
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ select CASE (var_i)
+ CASE (9)
+ metfilename = '/'//trim(fprefix(9))//'_'//trim(yearstr)//'_'//trim(monthstr)//&
+ '_boundary_layer_height.nc4'
+ END select
+ ENDIF
+ END FUNCTION metfilename
+
+ ! preprocess for forcing data [not applicable yet for PRINCETON]
+ ! ------------------------------------------------------------
+ SUBROUTINE metpreprocess(grid, forcn, has_missing_value, forcfirst, missing_value)
+
+ USE MOD_Const_Physical
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Qsadv
+ IMPLICIT NONE
+ type(grid_type), intent(in) :: grid
+ type(block_data_real8_2d), intent(inout) :: forcn(:)
+ type(block_data_real8_2d), intent(in) :: forcfirst
+ logical, intent(in) :: has_missing_value
+ real(r8), intent(in) :: missing_value
+
+ integer :: iblkme, ib, jb, i, j
+ real(r8) :: es, esdT, qsat_tmp, dqsat_tmpdT, e, ea
+
+ !----------------------------------------------------------------------------
+ ! use polynomials to calculate saturation vapor pressure and derivative with
+ ! respect to temperature: over water when t > 0 c and over ice when t <= 0 c
+ ! required to convert relative humidity to specific humidity
+ !----------------------------------------------------------------------------
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+#ifdef SinglePoint
+ CALL qsadv(forcn(1)%blk(gblock%xblkme(1),gblock%yblkme(1))%val(1,1), &
+ forcn(3)%blk(gblock%xblkme(1),gblock%yblkme(1))%val(1,1), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(gblock%xblkme(1),gblock%yblkme(1))%val(1,1)) THEN
+ forcn(2)%blk(gblock%xblkme(1),gblock%yblkme(1))%val(1,1) = qsat_tmp
+ ENDIF
+#endif
+ ELSE
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+
+ DO j = 1, grid%ycnt(jb)
+ DO i = 1, grid%xcnt(ib)
+
+ IF (has_missing_value) THEN
+ IF (forcfirst%blk(ib,jb)%val(i,j) == missing_value) THEN
+ CYCLE
+ ENDIF
+ ENDIF
+
+ select CASE (trim(DEF_forcing%dataset))
+
+ CASE ('PRINCETON')
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('GSWP2')
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('GSWP3')
+ IF (forcn(1)%blk(ib,jb)%val(i,j)<212.0) forcn(1)%blk(ib,jb)%val(i,j) = 212.0
+ IF (forcn(4)%blk(ib,jb)%val(i,j)<0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('QIAN')
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ e = forcn(3)%blk(ib,jb)%val(i,j) * forcn(2)%blk(ib,jb)%val(i,j) &
+ / (0.622_R8 + 0.378_R8 * forcn(2)%blk(ib,jb)%val(i,j))
+ ea = 0.70_R8 + 5.95e-05_R8 * 0.01_R8 * e &
+ * exp(1500.0_R8/forcn(1)%blk(ib,jb)%val(i,j))
+ forcn(8)%blk(ib,jb)%val(i,j) = ea * stefnc * forcn(1)%blk(ib,jb)%val(i,j)**4
+
+ CASE ('CRUNCEPV4')
+
+ IF (forcn(1)%blk(ib,jb)%val(i,j) < 212.0) forcn(1)%blk(ib,jb)%val(i,j) = 212.0
+ IF (forcn(4)%blk(ib,jb)%val(i,j) < 0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+ IF (forcn(7)%blk(ib,jb)%val(i,j) < 0.0) forcn(7)%blk(ib,jb)%val(i,j) = 0.0
+ ! 12th grade of Typhoon 32.7-36.9 m/s
+ IF (abs(forcn(5)%blk(ib,jb)%val(i,j)) > 40.0) forcn(5)%blk(ib,jb)%val(i,j) = &
+ 40.0*forcn(5)%blk(ib,jb)%val(i,j)/abs(forcn(5)%blk(ib,jb)%val(i,j))
+ IF (abs(forcn(6)%blk(ib,jb)%val(i,j)) > 40.0) forcn(6)%blk(ib,jb)%val(i,j) = &
+ 40.0*forcn(6)%blk(ib,jb)%val(i,j)/abs(forcn(6)%blk(ib,jb)%val(i,j))
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('CRUNCEPV7')
+
+ IF (forcn(1)%blk(ib,jb)%val(i,j) < 212.0) forcn(1)%blk(ib,jb)%val(i,j) = 212.0
+ IF (forcn(4)%blk(ib,jb)%val(i,j) < 0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+ IF (forcn(7)%blk(ib,jb)%val(i,j) < 0.0) forcn(7)%blk(ib,jb)%val(i,j) = 0.0
+ ! 12th grade of Typhoon 32.7-36.9 m/s
+ ! NOTE by Wenzong: This is a problem when running a GNU-compiled PROGRAM,
+ ! because there is no data of forcn(5), temporarily comment the code below
+ ! IF (abs(forcn(5)%blk(ib,jb)%val(i,j))>40.0) forcn(5)%blk(ib,jb)%val(i,j) = &
+ ! 40.0*forcn(5)%blk(ib,jb)%val(i,j)/abs(forcn(5)%blk(ib,jb)%val(i,j))
+ IF (abs(forcn(6)%blk(ib,jb)%val(i,j)) > 40.0) forcn(6)%blk(ib,jb)%val(i,j) = &
+ 40.0*forcn(6)%blk(ib,jb)%val(i,j)/abs(forcn(6)%blk(ib,jb)%val(i,j))
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('ERA5LAND')
+
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j) * 1000./3600.
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('ERA5')
+
+ IF (forcn(4)%blk(ib,jb)%val(i,j) < 0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+ IF (abs(forcn(5)%blk(ib,jb)%val(i,j)) > 40.0) &
+ forcn(5)%blk(ib,jb)%val(i,j) = 40.0*sign(1.0,forcn(5)%blk(ib,jb)%val(i,j))
+ IF (abs(forcn(6)%blk(ib,jb)%val(i,j)) > 40.0) &
+ forcn(6)%blk(ib,jb)%val(i,j) = 40.0*sign(1.0,forcn(6)%blk(ib,jb)%val(i,j))
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+ IF (forcn(4)%blk(ib,jb)%val(i,j) < 0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+
+ CASE ('MSWX')
+
+ forcn(1)%blk(ib,jb)%val(i,j)=forcn(1)%blk(ib,jb)%val(i,j)+273.15
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)/10800.
+ IF (forcn(4)%blk(ib,jb)%val(i,j)>1000.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+ IF (forcn(2)%blk(ib,jb)%val(i,j)<0.5E-05) &
+ forcn(2)%blk(ib,jb)%val(i,j) = 0.5E-05
+
+ CASE ('WFDE5')
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('WFDEI')
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('CLDAS') ! CLDAS forcing
+
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)/3600.
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('CMFD') ! CMFD forcing
+
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)/3600.
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+ CASE ('CMFDv2') ! CMFDv2 forcing
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('CRUJRA') ! CRUJRA forcing
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)/21600.
+ forcn(7)%blk(ib,jb)%val(i,j)=forcn(7)%blk(ib,jb)%val(i,j)/21600.
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('GDAS') ! GDAS forcing
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('JRA55') ! JRA55 forcing
+
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)/86400.0 !mm/s
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('JRA3Q') ! JRA3Q forcing
+
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('TPMFD') ! TPMFD forcing
+
+ forcn(4)%blk(ib,jb)%val(i,j)=forcn(4)%blk(ib,jb)%val(i,j)/3600.!convert to mm/s
+ forcn(3)%blk(ib,jb)%val(i,j)=forcn(3)%blk(ib,jb)%val(i,j)*100. !convert to pa
+
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ CASE ('CMIP6') ! CMIP6 forcing
+
+ IF (forcn(4)%blk(ib,jb)%val(i,j) < 0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+ IF (forcn(4)%blk(ib,jb)%val(i,j) < 0.0) forcn(4)%blk(ib,jb)%val(i,j) = 0.0
+
+ CASE ('IsoGSM') ! IsoGSM forcing
+ CALL qsadv (forcn(1)%blk(ib,jb)%val(i,j), forcn(3)%blk(ib,jb)%val(i,j), &
+ es,esdT,qsat_tmp,dqsat_tmpdT)
+ IF (qsat_tmp < forcn(2)%blk(ib,jb)%val(i,j)) THEN
+ forcn(2)%blk(ib,jb)%val(i,j) = qsat_tmp
+ ENDIF
+
+ END select
+
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE metpreprocess
+
+END MODULE MOD_UserSpecifiedForcing
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DAccFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DAccFluxes.F90
new file mode 100644
index 0000000000..ee50c2aa0f
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DAccFluxes.F90
@@ -0,0 +1,2970 @@
+#include
+
+MODULE MOD_Vars_1DAccFluxes
+
+ USE MOD_Precision
+#ifdef DataAssimilation
+ USE MOD_DA_Vars_TimeVariables
+ USE MOD_DA_Vars_1DFluxes
+ USE MOD_Namelist
+#endif
+#ifdef EXTERNAL_LAKE
+ USE MOD_Lake_1DAccVars
+#endif
+
+ real(r8) :: nac ! number of accumulation
+ real(r8), allocatable :: nac_ln (:)
+ real(r8), allocatable :: nac_dt (:)
+ logical, allocatable :: filter_dt (:)
+
+ real(r8), allocatable :: a_us (:)
+ real(r8), allocatable :: a_vs (:)
+ real(r8), allocatable :: a_t (:)
+ real(r8), allocatable :: a_q (:)
+ real(r8), allocatable :: a_prc (:)
+ real(r8), allocatable :: a_prl (:)
+ real(r8), allocatable :: a_pbot (:)
+ real(r8), allocatable :: a_frl (:)
+ real(r8), allocatable :: a_solarin (:)
+ real(r8), allocatable :: a_hpbl (:)
+
+ real(r8), allocatable :: a_taux (:)
+ real(r8), allocatable :: a_tauy (:)
+ real(r8), allocatable :: a_fsena (:)
+ real(r8), allocatable :: a_lfevpa (:)
+ real(r8), allocatable :: a_fevpa (:)
+ real(r8), allocatable :: a_fsenl (:)
+ real(r8), allocatable :: a_fevpl (:)
+ real(r8), allocatable :: a_etr (:)
+ real(r8), allocatable :: a_fseng (:)
+ real(r8), allocatable :: a_fevpg (:)
+ real(r8), allocatable :: a_fgrnd (:)
+ real(r8), allocatable :: a_sabvsun (:)
+ real(r8), allocatable :: a_sabvsha (:)
+ real(r8), allocatable :: a_sabg (:)
+ real(r8), allocatable :: a_olrg (:)
+ real(r8), allocatable :: a_rnet (:)
+ real(r8), allocatable :: a_xerr (:)
+ real(r8), allocatable :: a_zerr (:)
+ real(r8), allocatable :: a_rsur (:)
+ real(r8), allocatable :: a_rsur_se (:)
+ real(r8), allocatable :: a_rsur_ie (:)
+ real(r8), allocatable :: a_rsub (:)
+ real(r8), allocatable :: a_rnof (:)
+#ifdef CatchLateralFlow
+ real(r8), allocatable :: a_xwsur (:)
+ real(r8), allocatable :: a_xwsub (:)
+ real(r8), allocatable :: a_fldarea (:)
+#endif
+ real(r8), allocatable :: a_qintr (:)
+ real(r8), allocatable :: a_qinfl (:)
+ real(r8), allocatable :: a_qdrip (:)
+ real(r8), allocatable :: a_rstfacsun (:)
+ real(r8), allocatable :: a_rstfacsha (:)
+ real(r8), allocatable :: a_gssun (:)
+ real(r8), allocatable :: a_gssha (:)
+ real(r8), allocatable :: a_rss (:)
+ real(r8), allocatable :: a_wdsrf (:)
+ real(r8), allocatable :: a_zwt (:)
+ real(r8), allocatable :: a_wa (:)
+ real(r8), allocatable :: a_wat (:)
+ real(r8), allocatable :: a_wetwat (:)
+ real(r8), allocatable :: a_assim (:)
+ real(r8), allocatable :: a_respc (:)
+ real(r8), allocatable :: a_assimsun (:)
+ real(r8), allocatable :: a_assimsha (:)
+ real(r8), allocatable :: a_etrsun (:)
+ real(r8), allocatable :: a_etrsha (:)
+
+ real(r8), allocatable :: a_qcharge (:)
+
+ real(r8), allocatable :: a_t_grnd (:)
+ real(r8), allocatable :: a_tleaf (:)
+ real(r8), allocatable :: a_ldew (:)
+ real(r8), allocatable :: a_ldew_rain (:)
+ real(r8), allocatable :: a_ldew_snow (:)
+ real(r8), allocatable :: a_scv (:)
+ real(r8), allocatable :: a_snowdp (:)
+ real(r8), allocatable :: a_fsno (:)
+ real(r8), allocatable :: a_frcsat (:)
+ real(r8), allocatable :: a_sigf (:)
+ real(r8), allocatable :: a_green (:)
+ real(r8), allocatable :: a_lai (:)
+ real(r8), allocatable :: a_laisun (:)
+ real(r8), allocatable :: a_laisha (:)
+ real(r8), allocatable :: a_sai (:)
+ real(r8), allocatable :: a_alb (:,:,:)
+
+#ifdef HYPERSPECTRAL
+ real(r8), allocatable :: a_alb_hires (:,:,:)
+ real(r8), allocatable :: a_reflectance_out (:,:,:)
+ real(r8), allocatable :: a_transmittance_out (:,:,:)
+#endif
+ real(r8), allocatable :: a_emis (:)
+ real(r8), allocatable :: a_z0m (:)
+ real(r8), allocatable :: a_trad (:)
+ real(r8), allocatable :: a_tref (:)
+ real(r8), allocatable :: a_t2m_wmo (:)
+ real(r8), allocatable :: a_qref (:)
+ real(r8), allocatable :: a_rain (:)
+ real(r8), allocatable :: a_snow (:)
+
+ real(r8), allocatable :: a_o3uptakesun(:)
+ real(r8), allocatable :: a_o3uptakesha(:)
+
+#ifdef DataAssimilation
+ real(r8), allocatable :: a_h2osoi_ens (:,:,:)
+ real(r8), allocatable :: a_t_brt_smap_ens (:,:,:)
+ real(r8), allocatable :: a_t_brt_fy3d_ens (:,:,:)
+ real(r8), allocatable :: a_t_brt_smap (:,:)
+ real(r8), allocatable :: a_t_brt_fy3d (:,:)
+ real(r8), allocatable :: a_wliq_soisno_ens(:,:,:)
+ real(r8), allocatable :: a_wice_soisno_ens(:,:,:)
+ real(r8), allocatable :: a_t_soisno_ens (:,:,:)
+#endif
+
+#ifdef URBAN_MODEL
+ real(r8), allocatable :: a_t_room (:) !temperature of inner building [K]
+ real(r8), allocatable :: a_tafu (:) !temperature of outer building [K]
+ real(r8), allocatable :: a_fhac (:) !sensible flux from heat or cool AC [W/m2]
+ real(r8), allocatable :: a_fwst (:) !waste heat flux from heat or cool AC [W/m2]
+ real(r8), allocatable :: a_fach (:) !flux from inner and outer air exchange [W/m2]
+ real(r8), allocatable :: a_fahe (:) !flux from metabolic and vehicle [W/m2]
+ real(r8), allocatable :: a_fhah (:) !sensible flux from heating [W/m2]
+ real(r8), allocatable :: a_vehc (:) !flux from vehicle [W/m2]
+ real(r8), allocatable :: a_meta (:) !flux from metabolic [W/m2]
+
+ real(r8), allocatable :: a_senroof (:) !sensible heat flux from roof [W/m2]
+ real(r8), allocatable :: a_senwsun (:) !sensible heat flux from sunlit wall [W/m2]
+ real(r8), allocatable :: a_senwsha (:) !sensible heat flux from shaded wall [W/m2]
+ real(r8), allocatable :: a_sengimp (:) !sensible heat flux from impervious road [W/m2]
+ real(r8), allocatable :: a_sengper (:) !sensible heat flux from pervious road [W/m2]
+ real(r8), allocatable :: a_senurbl (:) !sensible heat flux from urban vegetation [W/m2]
+
+ real(r8), allocatable :: a_lfevproof (:) !latent heat flux from roof [W/m2]
+ real(r8), allocatable :: a_lfevpgimp (:) !latent heat flux from impervious road [W/m2]
+ real(r8), allocatable :: a_lfevpgper (:) !latent heat flux from pervious road [W/m2]
+ real(r8), allocatable :: a_lfevpurbl (:) !latent heat flux from urban vegetation [W/m2]
+
+ real(r8), allocatable :: a_troof (:) !temperature of roof [K]
+ real(r8), allocatable :: a_twall (:) !temperature of wall [K]
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ real(r8), allocatable :: a_lai_enftemp (:) !1
+ real(r8), allocatable :: a_lai_enfboreal (:) !2
+ real(r8), allocatable :: a_lai_dnfboreal (:) !3
+ real(r8), allocatable :: a_lai_ebftrop (:) !4
+ real(r8), allocatable :: a_lai_ebftemp (:) !5
+ real(r8), allocatable :: a_lai_dbftrop (:) !6
+ real(r8), allocatable :: a_lai_dbftemp (:) !7
+ real(r8), allocatable :: a_lai_dbfboreal (:) !8
+ real(r8), allocatable :: a_lai_ebstemp (:) !9
+ real(r8), allocatable :: a_lai_dbstemp (:) !10
+ real(r8), allocatable :: a_lai_dbsboreal (:) !11
+ real(r8), allocatable :: a_lai_c3arcgrass (:) !12
+ real(r8), allocatable :: a_lai_c3grass (:) !13
+ real(r8), allocatable :: a_lai_c4grass (:) !14
+#endif
+
+#ifdef BGC
+ real(r8), allocatable :: a_leafc (:)
+ real(r8), allocatable :: a_leafc_storage (:)
+ real(r8), allocatable :: a_leafc_xfer (:)
+ real(r8), allocatable :: a_frootc (:)
+ real(r8), allocatable :: a_frootc_storage (:)
+ real(r8), allocatable :: a_frootc_xfer (:)
+ real(r8), allocatable :: a_livestemc (:)
+ real(r8), allocatable :: a_livestemc_storage (:)
+ real(r8), allocatable :: a_livestemc_xfer (:)
+ real(r8), allocatable :: a_deadstemc (:)
+ real(r8), allocatable :: a_deadstemc_storage (:)
+ real(r8), allocatable :: a_deadstemc_xfer (:)
+ real(r8), allocatable :: a_livecrootc (:)
+ real(r8), allocatable :: a_livecrootc_storage (:)
+ real(r8), allocatable :: a_livecrootc_xfer (:)
+ real(r8), allocatable :: a_deadcrootc (:)
+ real(r8), allocatable :: a_deadcrootc_storage (:)
+ real(r8), allocatable :: a_deadcrootc_xfer (:)
+ real(r8), allocatable :: a_grainc (:)
+ real(r8), allocatable :: a_grainc_storage (:)
+ real(r8), allocatable :: a_grainc_xfer (:)
+ real(r8), allocatable :: a_leafn (:)
+ real(r8), allocatable :: a_leafn_storage (:)
+ real(r8), allocatable :: a_leafn_xfer (:)
+ real(r8), allocatable :: a_frootn (:)
+ real(r8), allocatable :: a_frootn_storage (:)
+ real(r8), allocatable :: a_frootn_xfer (:)
+ real(r8), allocatable :: a_livestemn (:)
+ real(r8), allocatable :: a_livestemn_storage (:)
+ real(r8), allocatable :: a_livestemn_xfer (:)
+ real(r8), allocatable :: a_deadstemn (:)
+ real(r8), allocatable :: a_deadstemn_storage (:)
+ real(r8), allocatable :: a_deadstemn_xfer (:)
+ real(r8), allocatable :: a_livecrootn (:)
+ real(r8), allocatable :: a_livecrootn_storage (:)
+ real(r8), allocatable :: a_livecrootn_xfer (:)
+ real(r8), allocatable :: a_deadcrootn (:)
+ real(r8), allocatable :: a_deadcrootn_storage (:)
+ real(r8), allocatable :: a_deadcrootn_xfer (:)
+ real(r8), allocatable :: a_grainn (:)
+ real(r8), allocatable :: a_grainn_storage (:)
+ real(r8), allocatable :: a_grainn_xfer (:)
+ real(r8), allocatable :: a_retransn (:)
+ real(r8), allocatable :: a_gpp (:)
+ real(r8), allocatable :: a_downreg (:)
+ real(r8), allocatable :: a_ar (:)
+ real(r8), allocatable :: a_cwdprod (:)
+ real(r8), allocatable :: a_cwddecomp (:)
+ real(r8), allocatable :: a_hr (:)
+ real(r8), allocatable :: a_fpg (:)
+ real(r8), allocatable :: a_fpi (:)
+ real(r8), allocatable :: a_totvegc (:)
+ real(r8), allocatable :: a_totlitc (:)
+ real(r8), allocatable :: a_totcwdc (:)
+ real(r8), allocatable :: a_totsomc (:)
+ real(r8), allocatable :: a_totcolc (:)
+ real(r8), allocatable :: a_totvegn (:)
+ real(r8), allocatable :: a_totlitn (:)
+ real(r8), allocatable :: a_totcwdn (:)
+ real(r8), allocatable :: a_totsomn (:)
+ real(r8), allocatable :: a_totcoln (:)
+ real(r8), allocatable :: a_gpp_enftemp (:) !1
+ real(r8), allocatable :: a_gpp_enfboreal (:) !2
+ real(r8), allocatable :: a_gpp_dnfboreal (:) !3
+ real(r8), allocatable :: a_gpp_ebftrop (:) !4
+ real(r8), allocatable :: a_gpp_ebftemp (:) !5
+ real(r8), allocatable :: a_gpp_dbftrop (:) !6
+ real(r8), allocatable :: a_gpp_dbftemp (:) !7
+ real(r8), allocatable :: a_gpp_dbfboreal (:) !8
+ real(r8), allocatable :: a_gpp_ebstemp (:) !9
+ real(r8), allocatable :: a_gpp_dbstemp (:) !10
+ real(r8), allocatable :: a_gpp_dbsboreal (:) !11
+ real(r8), allocatable :: a_gpp_c3arcgrass (:) !12
+ real(r8), allocatable :: a_gpp_c3grass (:) !13
+ real(r8), allocatable :: a_gpp_c4grass (:) !14
+ real(r8), allocatable :: a_npp_enftemp (:) !1
+ real(r8), allocatable :: a_npp_enfboreal (:) !2
+ real(r8), allocatable :: a_npp_dnfboreal (:) !3
+ real(r8), allocatable :: a_npp_ebftrop (:) !4
+ real(r8), allocatable :: a_npp_ebftemp (:) !5
+ real(r8), allocatable :: a_npp_dbftrop (:) !6
+ real(r8), allocatable :: a_npp_dbftemp (:) !7
+ real(r8), allocatable :: a_npp_dbfboreal (:) !8
+ real(r8), allocatable :: a_npp_ebstemp (:) !9
+ real(r8), allocatable :: a_npp_dbstemp (:) !10
+ real(r8), allocatable :: a_npp_dbsboreal (:) !11
+ real(r8), allocatable :: a_npp_c3arcgrass (:) !12
+ real(r8), allocatable :: a_npp_c3grass (:) !13
+ real(r8), allocatable :: a_npp_c4grass (:) !14
+ real(r8), allocatable :: a_npptoleafc_enftemp (:) !1
+ real(r8), allocatable :: a_npptoleafc_enfboreal (:) !2
+ real(r8), allocatable :: a_npptoleafc_dnfboreal (:) !3
+ real(r8), allocatable :: a_npptoleafc_ebftrop (:) !4
+ real(r8), allocatable :: a_npptoleafc_ebftemp (:) !5
+ real(r8), allocatable :: a_npptoleafc_dbftrop (:) !6
+ real(r8), allocatable :: a_npptoleafc_dbftemp (:) !7
+ real(r8), allocatable :: a_npptoleafc_dbfboreal (:) !8
+ real(r8), allocatable :: a_npptoleafc_ebstemp (:) !9
+ real(r8), allocatable :: a_npptoleafc_dbstemp (:) !10
+ real(r8), allocatable :: a_npptoleafc_dbsboreal (:) !11
+ real(r8), allocatable :: a_npptoleafc_c3arcgrass (:) !12
+ real(r8), allocatable :: a_npptoleafc_c3grass (:) !13
+ real(r8), allocatable :: a_npptoleafc_c4grass (:) !14
+ real(r8), allocatable :: a_leafc_enftemp (:) !1
+ real(r8), allocatable :: a_leafc_enfboreal (:) !2
+ real(r8), allocatable :: a_leafc_dnfboreal (:) !3
+ real(r8), allocatable :: a_leafc_ebftrop (:) !4
+ real(r8), allocatable :: a_leafc_ebftemp (:) !5
+ real(r8), allocatable :: a_leafc_dbftrop (:) !6
+ real(r8), allocatable :: a_leafc_dbftemp (:) !7
+ real(r8), allocatable :: a_leafc_dbfboreal (:) !8
+ real(r8), allocatable :: a_leafc_ebstemp (:) !9
+ real(r8), allocatable :: a_leafc_dbstemp (:) !10
+ real(r8), allocatable :: a_leafc_dbsboreal (:) !11
+ real(r8), allocatable :: a_leafc_c3arcgrass (:) !12
+ real(r8), allocatable :: a_leafc_c3grass (:) !13
+ real(r8), allocatable :: a_leafc_c4grass (:) !14
+ real(r8), allocatable :: a_O2_DECOMP_DEPTH_UNSAT (:,:)
+ real(r8), allocatable :: a_CONC_O2_UNSAT (:,:)
+#ifdef CROP
+ real(r8), allocatable :: a_pdcorn (:)
+ real(r8), allocatable :: a_pdswheat (:)
+ real(r8), allocatable :: a_pdwwheat (:)
+ real(r8), allocatable :: a_pdsoybean (:)
+ real(r8), allocatable :: a_pdcotton (:)
+ real(r8), allocatable :: a_pdrice1 (:)
+ real(r8), allocatable :: a_pdrice2 (:)
+ real(r8), allocatable :: a_pdsugarcane (:)
+ real(r8), allocatable :: a_plantdate (:)
+ real(r8), allocatable :: a_manunitro (:)
+ real(r8), allocatable :: a_fertnitro_corn (:)
+ real(r8), allocatable :: a_fertnitro_swheat (:)
+ real(r8), allocatable :: a_fertnitro_wwheat (:)
+ real(r8), allocatable :: a_fertnitro_soybean (:)
+ real(r8), allocatable :: a_fertnitro_cotton (:)
+ real(r8), allocatable :: a_fertnitro_rice1 (:)
+ real(r8), allocatable :: a_fertnitro_rice2 (:)
+ real(r8), allocatable :: a_fertnitro_sugarcane (:)
+ real(r8), allocatable :: a_irrig_method_corn (:)
+ real(r8), allocatable :: a_irrig_method_swheat (:)
+ real(r8), allocatable :: a_irrig_method_wwheat (:)
+ real(r8), allocatable :: a_irrig_method_soybean (:)
+ real(r8), allocatable :: a_irrig_method_cotton (:)
+ real(r8), allocatable :: a_irrig_method_rice1 (:)
+ real(r8), allocatable :: a_irrig_method_rice2 (:)
+ real(r8), allocatable :: a_irrig_method_sugarcane(:)
+
+ real(r8), allocatable :: a_cphase (:)
+ real(r8), allocatable :: a_gddplant (:)
+ real(r8), allocatable :: a_gddmaturity (:)
+ real(r8), allocatable :: a_vf (:)
+ real(r8), allocatable :: a_hui (:)
+ real(r8), allocatable :: a_cropprod1c (:)
+ real(r8), allocatable :: a_cropprod1c_loss (:)
+ real(r8), allocatable :: a_cropseedc_deficit (:)
+ real(r8), allocatable :: a_grainc_to_cropprodc (:)
+ real(r8), allocatable :: a_grainc_to_seed (:)
+ real(r8), allocatable :: a_fert_to_sminn (:)
+
+ real(r8), allocatable :: a_sum_irrig (:)
+ real(r8), allocatable :: a_sum_deficit_irrig (:)
+ real(r8), allocatable :: a_sum_irrig_count (:)
+ real(r8), allocatable :: a_waterstorage (:)
+ real(r8), allocatable :: a_groundwater_demand (:)
+ real(r8), allocatable :: a_groundwater_supply (:)
+ real(r8), allocatable :: a_reservoirriver_demand(:)
+ real(r8), allocatable :: a_reservoirriver_supply(:)
+ real(r8), allocatable :: a_reservoir_supply (:)
+ real(r8), allocatable :: a_river_supply (:)
+ real(r8), allocatable :: a_runoff_supply (:)
+#endif
+ real(r8), allocatable :: a_ndep_to_sminn (:)
+ real(r8), allocatable :: a_abm (:)
+ real(r8), allocatable :: a_gdp (:)
+ real(r8), allocatable :: a_peatf (:)
+ real(r8), allocatable :: a_hdm (:)
+ real(r8), allocatable :: a_lnfm (:)
+ real(r8), allocatable :: a_leafcCap (:)
+ real(r8), allocatable :: a_leafc_storageCap (:)
+ real(r8), allocatable :: a_leafc_xferCap (:)
+ real(r8), allocatable :: a_frootcCap (:)
+ real(r8), allocatable :: a_frootc_storageCap (:)
+ real(r8), allocatable :: a_frootc_xferCap (:)
+ real(r8), allocatable :: a_livestemcCap (:)
+ real(r8), allocatable :: a_livestemc_storageCap (:)
+ real(r8), allocatable :: a_livestemc_xferCap (:)
+ real(r8), allocatable :: a_deadstemcCap (:)
+ real(r8), allocatable :: a_deadstemc_storageCap (:)
+ real(r8), allocatable :: a_deadstemc_xferCap (:)
+ real(r8), allocatable :: a_livecrootcCap (:)
+ real(r8), allocatable :: a_livecrootc_storageCap (:)
+ real(r8), allocatable :: a_livecrootc_xferCap (:)
+ real(r8), allocatable :: a_deadcrootcCap (:)
+ real(r8), allocatable :: a_deadcrootc_storageCap (:)
+ real(r8), allocatable :: a_deadcrootc_xferCap (:)
+ real(r8), allocatable :: a_leafnCap (:)
+ real(r8), allocatable :: a_leafn_storageCap (:)
+ real(r8), allocatable :: a_leafn_xferCap (:)
+ real(r8), allocatable :: a_frootnCap (:)
+ real(r8), allocatable :: a_frootn_storageCap (:)
+ real(r8), allocatable :: a_frootn_xferCap (:)
+ real(r8), allocatable :: a_livestemnCap (:)
+ real(r8), allocatable :: a_livestemn_storageCap (:)
+ real(r8), allocatable :: a_livestemn_xferCap (:)
+ real(r8), allocatable :: a_deadstemnCap (:)
+ real(r8), allocatable :: a_deadstemn_storageCap (:)
+ real(r8), allocatable :: a_deadstemn_xferCap (:)
+ real(r8), allocatable :: a_livecrootnCap (:)
+ real(r8), allocatable :: a_livecrootn_storageCap (:)
+ real(r8), allocatable :: a_livecrootn_xferCap (:)
+ real(r8), allocatable :: a_deadcrootnCap (:)
+ real(r8), allocatable :: a_deadcrootn_storageCap (:)
+ real(r8), allocatable :: a_deadcrootn_xferCap (:)
+#endif
+! Ozone stress variables
+ real(r8), allocatable :: a_ozone (:)
+! End ozone stress variables
+
+ real(r8), allocatable :: a_t_soisno (:,:)
+ real(r8), allocatable :: a_wliq_soisno (:,:)
+ real(r8), allocatable :: a_wice_soisno (:,:)
+ real(r8), allocatable :: a_h2osoi (:,:)
+ real(r8), allocatable :: a_qlayer (:,:)
+ real(r8), allocatable :: a_lake_deficit (:)
+ real(r8), allocatable :: a_rootr (:,:)
+ real(r8), allocatable :: a_BD_all (:,:)
+ real(r8), allocatable :: a_wfc (:,:)
+ real(r8), allocatable :: a_OM_density (:,:)
+!Plant Hydraulic parameters
+ real(r8), allocatable :: a_vegwp (:,:)
+!END plant hydraulic parameters
+ real(r8), allocatable :: a_dz_lake (:,:)
+ real(r8), allocatable :: a_t_lake (:,:)
+ real(r8), allocatable :: a_lake_icefrac(:,:)
+
+#ifdef BGC
+ real(r8), allocatable :: a_litr1c_vr (:,:)
+ real(r8), allocatable :: a_litr2c_vr (:,:)
+ real(r8), allocatable :: a_litr3c_vr (:,:)
+ real(r8), allocatable :: a_soil1c_vr (:,:)
+ real(r8), allocatable :: a_soil2c_vr (:,:)
+ real(r8), allocatable :: a_soil3c_vr (:,:)
+ real(r8), allocatable :: a_cwdc_vr (:,:)
+ real(r8), allocatable :: a_litr1n_vr (:,:)
+ real(r8), allocatable :: a_litr2n_vr (:,:)
+ real(r8), allocatable :: a_litr3n_vr (:,:)
+ real(r8), allocatable :: a_soil1n_vr (:,:)
+ real(r8), allocatable :: a_soil2n_vr (:,:)
+ real(r8), allocatable :: a_soil3n_vr (:,:)
+ real(r8), allocatable :: a_cwdn_vr (:,:)
+ real(r8), allocatable :: a_totsoiln_vr (:,:)
+ real(r8), allocatable :: a_litr1cCap_vr(:,:)
+ real(r8), allocatable :: a_litr2cCap_vr(:,:)
+ real(r8), allocatable :: a_litr3cCap_vr(:,:)
+ real(r8), allocatable :: a_soil1cCap_vr(:,:)
+ real(r8), allocatable :: a_soil2cCap_vr(:,:)
+ real(r8), allocatable :: a_soil3cCap_vr(:,:)
+ real(r8), allocatable :: a_cwdcCap_vr (:,:)
+ real(r8), allocatable :: a_litr1nCap_vr(:,:)
+ real(r8), allocatable :: a_litr2nCap_vr(:,:)
+ real(r8), allocatable :: a_litr3nCap_vr(:,:)
+ real(r8), allocatable :: a_soil1nCap_vr(:,:)
+ real(r8), allocatable :: a_soil2nCap_vr(:,:)
+ real(r8), allocatable :: a_soil3nCap_vr(:,:)
+ real(r8), allocatable :: a_cwdnCap_vr (:,:)
+ real(r8), allocatable :: a_t_scalar (:,:)
+ real(r8), allocatable :: a_w_scalar (:,:)
+ real(r8), allocatable :: a_sminn_vr (:,:)
+ real(r8), allocatable :: decomp_vr_tmp (:,:)
+#endif
+
+ real(r8), allocatable :: a_ustar (:)
+ real(r8), allocatable :: a_ustar2 (:)
+ real(r8), allocatable :: a_tstar (:)
+ real(r8), allocatable :: a_qstar (:)
+ real(r8), allocatable :: a_zol (:)
+ real(r8), allocatable :: a_rib (:)
+ real(r8), allocatable :: a_fm (:)
+ real(r8), allocatable :: a_fh (:)
+ real(r8), allocatable :: a_fq (:)
+
+ real(r8), allocatable :: a_us10m (:)
+ real(r8), allocatable :: a_vs10m (:)
+ real(r8), allocatable :: a_fm10m (:)
+
+ real(r8), allocatable :: a_sr (:)
+ real(r8), allocatable :: a_solvd (:)
+ real(r8), allocatable :: a_solvi (:)
+ real(r8), allocatable :: a_solnd (:)
+ real(r8), allocatable :: a_solni (:)
+ real(r8), allocatable :: a_srvd (:)
+ real(r8), allocatable :: a_srvi (:)
+ real(r8), allocatable :: a_srnd (:)
+ real(r8), allocatable :: a_srni (:)
+ real(r8), allocatable :: a_solvdln (:)
+ real(r8), allocatable :: a_solviln (:)
+ real(r8), allocatable :: a_solndln (:)
+ real(r8), allocatable :: a_solniln (:)
+ real(r8), allocatable :: a_srvdln (:)
+ real(r8), allocatable :: a_srviln (:)
+ real(r8), allocatable :: a_srndln (:)
+ real(r8), allocatable :: a_srniln (:)
+#ifdef HYPERSPECTRAL
+ real(r8), allocatable :: a_sol_dir_ln_hires(:,:)
+ real(r8), allocatable :: a_sol_dif_ln_hires(:,:)
+ real(r8), allocatable :: a_sr_dir_ln_hires (:,:)
+ real(r8), allocatable :: a_sr_dif_ln_hires (:,:)
+#endif
+ real(r8), allocatable :: a_sensors (:,:)
+
+ PUBLIC :: allocate_acc_fluxes
+ PUBLIC :: deallocate_acc_fluxes
+ PUBLIC :: flush_acc_fluxes
+ PUBLIC :: accumulate_fluxes
+
+CONTAINS
+
+ SUBROUTINE allocate_acc_fluxes
+
+ USE MOD_SPMD_Task
+ USE MOD_LandElm
+ USE MOD_LandPatch
+ USE MOD_LandUrban, only: numurban
+ USE MOD_Vars_1DFluxes, only: nsensor
+#ifdef CROP
+ USE MOD_LandCrop
+#endif
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ allocate (a_us (numpatch))
+ allocate (a_vs (numpatch))
+ allocate (a_t (numpatch))
+ allocate (a_q (numpatch))
+ allocate (a_prc (numpatch))
+ allocate (a_prl (numpatch))
+ allocate (a_pbot (numpatch))
+ allocate (a_frl (numpatch))
+ allocate (a_solarin (numpatch))
+ allocate (a_hpbl (numpatch))
+
+ allocate (a_taux (numpatch))
+ allocate (a_tauy (numpatch))
+ allocate (a_fsena (numpatch))
+ allocate (a_lfevpa (numpatch))
+ allocate (a_fevpa (numpatch))
+ allocate (a_fsenl (numpatch))
+ allocate (a_fevpl (numpatch))
+ allocate (a_etr (numpatch))
+ allocate (a_fseng (numpatch))
+ allocate (a_fevpg (numpatch))
+ allocate (a_fgrnd (numpatch))
+ allocate (a_sabvsun (numpatch))
+ allocate (a_sabvsha (numpatch))
+ allocate (a_sabg (numpatch))
+ allocate (a_olrg (numpatch))
+ allocate (a_rnet (numpatch))
+ allocate (a_xerr (numpatch))
+ allocate (a_zerr (numpatch))
+ allocate (a_rsur (numpatch))
+ allocate (a_rsur_se (numpatch))
+ allocate (a_rsur_ie (numpatch))
+ allocate (a_rsub (numpatch))
+ allocate (a_rnof (numpatch))
+#ifdef CatchLateralFlow
+ allocate (a_xwsur (numpatch))
+ allocate (a_xwsub (numpatch))
+ allocate (a_fldarea (numpatch))
+#endif
+ allocate (a_qintr (numpatch))
+ allocate (a_qinfl (numpatch))
+ allocate (a_qdrip (numpatch))
+ allocate (a_rstfacsun (numpatch))
+ allocate (a_rstfacsha (numpatch))
+ allocate (a_gssun (numpatch))
+ allocate (a_gssha (numpatch))
+ allocate (a_rss (numpatch))
+ allocate (a_wdsrf (numpatch))
+
+ allocate (a_zwt (numpatch))
+ allocate (a_wa (numpatch))
+ allocate (a_wat (numpatch))
+ allocate (a_wetwat (numpatch))
+ allocate (a_assim (numpatch))
+ allocate (a_respc (numpatch))
+
+ allocate (a_assimsun (numpatch))
+ allocate (a_assimsha (numpatch))
+ allocate (a_etrsun (numpatch))
+ allocate (a_etrsha (numpatch))
+
+ allocate (a_qcharge (numpatch))
+
+ allocate (a_t_grnd (numpatch))
+ allocate (a_tleaf (numpatch))
+ allocate (a_ldew_rain (numpatch))
+ allocate (a_ldew_snow (numpatch))
+ allocate (a_ldew (numpatch))
+ allocate (a_scv (numpatch))
+ allocate (a_snowdp (numpatch))
+ allocate (a_fsno (numpatch))
+ allocate (a_frcsat (numpatch))
+ allocate (a_sigf (numpatch))
+ allocate (a_green (numpatch))
+ allocate (a_lai (numpatch))
+ allocate (a_laisun (numpatch))
+ allocate (a_laisha (numpatch))
+ allocate (a_sai (numpatch))
+
+ allocate (a_alb (2 ,2,numpatch))
+#ifdef HYPERSPECTRAL
+ allocate (a_alb_hires (211,2,numpatch))
+ allocate (a_reflectance_out (211,16,numpatch))
+ allocate (a_transmittance_out(211,16,numpatch))
+#endif
+ allocate (a_emis (numpatch))
+ allocate (a_z0m (numpatch))
+ allocate (a_trad (numpatch))
+ allocate (a_tref (numpatch))
+ allocate (a_t2m_wmo (numpatch))
+ allocate (a_qref (numpatch))
+ allocate (a_rain (numpatch))
+ allocate (a_snow (numpatch))
+
+ allocate (a_o3uptakesun(numpatch))
+ allocate (a_o3uptakesha(numpatch))
+
+#ifdef DataAssimilation
+ allocate (a_h2osoi_ens (1:nl_soil,DEF_DA_ENS_NUM,numpatch))
+ allocate (a_t_brt_smap_ens (2,DEF_DA_ENS_NUM,numpatch))
+ allocate (a_t_brt_fy3d_ens (2,DEF_DA_ENS_NUM,numpatch))
+ allocate (a_t_brt_smap (2,numpatch))
+ allocate (a_t_brt_fy3d (2,numpatch))
+ allocate (a_wliq_soisno_ens(maxsnl+1:nl_soil,DEF_DA_ENS_NUM,numpatch))
+ allocate (a_wice_soisno_ens(maxsnl+1:nl_soil,DEF_DA_ENS_NUM,numpatch))
+ allocate (a_t_soisno_ens (maxsnl+1:nl_soil,DEF_DA_ENS_NUM,numpatch))
+#endif
+
+#ifdef URBAN_MODEL
+ IF (numurban > 0) THEN
+ allocate (a_t_room (numurban))
+ allocate (a_tafu (numurban))
+ allocate (a_fhac (numurban))
+ allocate (a_fwst (numurban))
+ allocate (a_fach (numurban))
+ allocate (a_fahe (numurban))
+ allocate (a_fhah (numurban))
+ allocate (a_vehc (numurban))
+ allocate (a_meta (numurban))
+
+ allocate (a_senroof (numurban))
+ allocate (a_senwsun (numurban))
+ allocate (a_senwsha (numurban))
+ allocate (a_sengimp (numurban))
+ allocate (a_sengper (numurban))
+ allocate (a_senurbl (numurban))
+
+ allocate (a_lfevproof (numurban))
+ allocate (a_lfevpgimp (numurban))
+ allocate (a_lfevpgper (numurban))
+ allocate (a_lfevpurbl (numurban))
+
+ allocate (a_troof (numurban))
+ allocate (a_twall (numurban))
+ ENDIF
+#endif
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ allocate (a_lai_enftemp (numpatch))
+ allocate (a_lai_enfboreal (numpatch))
+ allocate (a_lai_dnfboreal (numpatch))
+ allocate (a_lai_ebftrop (numpatch))
+ allocate (a_lai_ebftemp (numpatch))
+ allocate (a_lai_dbftrop (numpatch))
+ allocate (a_lai_dbftemp (numpatch))
+ allocate (a_lai_dbfboreal (numpatch))
+ allocate (a_lai_ebstemp (numpatch))
+ allocate (a_lai_dbstemp (numpatch))
+ allocate (a_lai_dbsboreal (numpatch))
+ allocate (a_lai_c3arcgrass (numpatch))
+ allocate (a_lai_c3grass (numpatch))
+ allocate (a_lai_c4grass (numpatch))
+#endif
+#ifdef BGC
+ allocate (a_leafc (numpatch))
+ allocate (a_leafc_storage (numpatch))
+ allocate (a_leafc_xfer (numpatch))
+ allocate (a_frootc (numpatch))
+ allocate (a_frootc_storage (numpatch))
+ allocate (a_frootc_xfer (numpatch))
+ allocate (a_livestemc (numpatch))
+ allocate (a_livestemc_storage (numpatch))
+ allocate (a_livestemc_xfer (numpatch))
+ allocate (a_deadstemc (numpatch))
+ allocate (a_deadstemc_storage (numpatch))
+ allocate (a_deadstemc_xfer (numpatch))
+ allocate (a_livecrootc (numpatch))
+ allocate (a_livecrootc_storage (numpatch))
+ allocate (a_livecrootc_xfer (numpatch))
+ allocate (a_deadcrootc (numpatch))
+ allocate (a_deadcrootc_storage (numpatch))
+ allocate (a_deadcrootc_xfer (numpatch))
+ allocate (a_grainc (numpatch))
+ allocate (a_grainc_storage (numpatch))
+ allocate (a_grainc_xfer (numpatch))
+ allocate (a_leafn (numpatch))
+ allocate (a_leafn_storage (numpatch))
+ allocate (a_leafn_xfer (numpatch))
+ allocate (a_frootn (numpatch))
+ allocate (a_frootn_storage (numpatch))
+ allocate (a_frootn_xfer (numpatch))
+ allocate (a_livestemn (numpatch))
+ allocate (a_livestemn_storage (numpatch))
+ allocate (a_livestemn_xfer (numpatch))
+ allocate (a_deadstemn (numpatch))
+ allocate (a_deadstemn_storage (numpatch))
+ allocate (a_deadstemn_xfer (numpatch))
+ allocate (a_livecrootn (numpatch))
+ allocate (a_livecrootn_storage (numpatch))
+ allocate (a_livecrootn_xfer (numpatch))
+ allocate (a_deadcrootn (numpatch))
+ allocate (a_deadcrootn_storage (numpatch))
+ allocate (a_deadcrootn_xfer (numpatch))
+ allocate (a_grainn (numpatch))
+ allocate (a_grainn_storage (numpatch))
+ allocate (a_grainn_xfer (numpatch))
+ allocate (a_retransn (numpatch))
+ allocate (a_gpp (numpatch))
+ allocate (a_downreg (numpatch))
+ allocate (a_ar (numpatch))
+ allocate (a_cwdprod (numpatch))
+ allocate (a_cwddecomp (numpatch))
+ allocate (a_hr (numpatch))
+ allocate (a_fpg (numpatch))
+ allocate (a_fpi (numpatch))
+ allocate (a_totvegc (numpatch))
+ allocate (a_totlitc (numpatch))
+ allocate (a_totcwdc (numpatch))
+ allocate (a_totsomc (numpatch))
+ allocate (a_totcolc (numpatch))
+ allocate (a_totvegn (numpatch))
+ allocate (a_totlitn (numpatch))
+ allocate (a_totcwdn (numpatch))
+ allocate (a_totsomn (numpatch))
+ allocate (a_totcoln (numpatch))
+ allocate (a_gpp_enftemp (numpatch)) !1
+ allocate (a_gpp_enfboreal (numpatch)) !2
+ allocate (a_gpp_dnfboreal (numpatch)) !3
+ allocate (a_gpp_ebftrop (numpatch)) !4
+ allocate (a_gpp_ebftemp (numpatch)) !5
+ allocate (a_gpp_dbftrop (numpatch)) !6
+ allocate (a_gpp_dbftemp (numpatch)) !7
+ allocate (a_gpp_dbfboreal (numpatch)) !8
+ allocate (a_gpp_ebstemp (numpatch)) !9
+ allocate (a_gpp_dbstemp (numpatch)) !10
+ allocate (a_gpp_dbsboreal (numpatch)) !11
+ allocate (a_gpp_c3arcgrass (numpatch)) !12
+ allocate (a_gpp_c3grass (numpatch)) !13
+ allocate (a_gpp_c4grass (numpatch)) !14
+ allocate (a_npp_enftemp (numpatch)) !1
+ allocate (a_npp_enfboreal (numpatch)) !2
+ allocate (a_npp_dnfboreal (numpatch)) !3
+ allocate (a_npp_ebftrop (numpatch)) !4
+ allocate (a_npp_ebftemp (numpatch)) !5
+ allocate (a_npp_dbftrop (numpatch)) !6
+ allocate (a_npp_dbftemp (numpatch)) !7
+ allocate (a_npp_dbfboreal (numpatch)) !8
+ allocate (a_npp_ebstemp (numpatch)) !9
+ allocate (a_npp_dbstemp (numpatch)) !10
+ allocate (a_npp_dbsboreal (numpatch)) !11
+ allocate (a_npp_c3arcgrass (numpatch)) !12
+ allocate (a_npp_c3grass (numpatch)) !13
+ allocate (a_npp_c4grass (numpatch)) !14
+ allocate (a_npptoleafc_enftemp (numpatch)) !1
+ allocate (a_npptoleafc_enfboreal (numpatch)) !2
+ allocate (a_npptoleafc_dnfboreal (numpatch)) !3
+ allocate (a_npptoleafc_ebftrop (numpatch)) !4
+ allocate (a_npptoleafc_ebftemp (numpatch)) !5
+ allocate (a_npptoleafc_dbftrop (numpatch)) !6
+ allocate (a_npptoleafc_dbftemp (numpatch)) !7
+ allocate (a_npptoleafc_dbfboreal (numpatch)) !8
+ allocate (a_npptoleafc_ebstemp (numpatch)) !9
+ allocate (a_npptoleafc_dbstemp (numpatch)) !10
+ allocate (a_npptoleafc_dbsboreal (numpatch)) !11
+ allocate (a_npptoleafc_c3arcgrass (numpatch)) !12
+ allocate (a_npptoleafc_c3grass (numpatch)) !13
+ allocate (a_npptoleafc_c4grass (numpatch)) !14
+ allocate (a_leafc_enftemp (numpatch)) !1
+ allocate (a_leafc_enfboreal (numpatch)) !2
+ allocate (a_leafc_dnfboreal (numpatch)) !3
+ allocate (a_leafc_ebftrop (numpatch)) !4
+ allocate (a_leafc_ebftemp (numpatch)) !5
+ allocate (a_leafc_dbftrop (numpatch)) !6
+ allocate (a_leafc_dbftemp (numpatch)) !7
+ allocate (a_leafc_dbfboreal (numpatch)) !8
+ allocate (a_leafc_ebstemp (numpatch)) !9
+ allocate (a_leafc_dbstemp (numpatch)) !10
+ allocate (a_leafc_dbsboreal (numpatch)) !11
+ allocate (a_leafc_c3arcgrass (numpatch)) !12
+ allocate (a_leafc_c3grass (numpatch)) !13
+ allocate (a_leafc_c4grass (numpatch)) !14
+
+ allocate (a_O2_DECOMP_DEPTH_UNSAT (1:nl_soil,numpatch))
+ allocate (a_CONC_O2_UNSAT (1:nl_soil,numpatch))
+
+#ifdef CROP
+ allocate (a_pdcorn (numpatch))
+ allocate (a_pdswheat (numpatch))
+ allocate (a_pdwwheat (numpatch))
+ allocate (a_pdsoybean (numpatch))
+ allocate (a_pdcotton (numpatch))
+ allocate (a_pdrice1 (numpatch))
+ allocate (a_pdrice2 (numpatch))
+ allocate (a_pdsugarcane (numpatch))
+ allocate (a_plantdate (numpatch))
+ allocate (a_manunitro (numpatch))
+ allocate (a_fertnitro_corn (numpatch))
+ allocate (a_fertnitro_swheat (numpatch))
+ allocate (a_fertnitro_wwheat (numpatch))
+ allocate (a_fertnitro_soybean (numpatch))
+ allocate (a_fertnitro_cotton (numpatch))
+ allocate (a_fertnitro_rice1 (numpatch))
+ allocate (a_fertnitro_rice2 (numpatch))
+ allocate (a_fertnitro_sugarcane(numpatch))
+ allocate (a_irrig_method_corn (numpatch))
+ allocate (a_irrig_method_swheat (numpatch))
+ allocate (a_irrig_method_wwheat (numpatch))
+ allocate (a_irrig_method_soybean (numpatch))
+ allocate (a_irrig_method_cotton (numpatch))
+ allocate (a_irrig_method_rice1 (numpatch))
+ allocate (a_irrig_method_rice2 (numpatch))
+ allocate (a_irrig_method_sugarcane(numpatch))
+ allocate (a_cphase (numpatch))
+ allocate (a_hui (numpatch))
+ allocate (a_gddmaturity (numpatch))
+ allocate (a_gddplant (numpatch))
+ allocate (a_vf (numpatch))
+ allocate (a_cropprod1c (numpatch))
+ allocate (a_cropprod1c_loss (numpatch))
+ allocate (a_cropseedc_deficit (numpatch))
+ allocate (a_grainc_to_cropprodc(numpatch))
+ allocate (a_grainc_to_seed (numpatch))
+ allocate (a_fert_to_sminn (numpatch))
+
+ allocate (a_sum_irrig (numpatch))
+ allocate (a_sum_deficit_irrig (numpatch))
+ allocate (a_sum_irrig_count (numpatch))
+ allocate (a_waterstorage (numpatch))
+ allocate (a_groundwater_demand (numpatch))
+ allocate (a_groundwater_supply (numpatch))
+ allocate (a_reservoirriver_demand(numpatch))
+ allocate (a_reservoirriver_supply(numpatch))
+ allocate (a_reservoir_supply (numpatch))
+ allocate (a_river_supply (numpatch))
+ allocate (a_runoff_supply (numpatch))
+#endif
+ allocate (a_ndep_to_sminn (numpatch))
+
+ allocate (a_abm (numpatch))
+ allocate (a_gdp (numpatch))
+ allocate (a_peatf (numpatch))
+ allocate (a_hdm (numpatch))
+ allocate (a_lnfm (numpatch))
+
+ allocate (a_leafcCap (numpatch))
+ allocate (a_leafc_storageCap (numpatch))
+ allocate (a_leafc_xferCap (numpatch))
+ allocate (a_frootcCap (numpatch))
+ allocate (a_frootc_storageCap (numpatch))
+ allocate (a_frootc_xferCap (numpatch))
+ allocate (a_livestemcCap (numpatch))
+ allocate (a_livestemc_storageCap (numpatch))
+ allocate (a_livestemc_xferCap (numpatch))
+ allocate (a_deadstemcCap (numpatch))
+ allocate (a_deadstemc_storageCap (numpatch))
+ allocate (a_deadstemc_xferCap (numpatch))
+ allocate (a_livecrootcCap (numpatch))
+ allocate (a_livecrootc_storageCap (numpatch))
+ allocate (a_livecrootc_xferCap (numpatch))
+ allocate (a_deadcrootcCap (numpatch))
+ allocate (a_deadcrootc_storageCap (numpatch))
+ allocate (a_deadcrootc_xferCap (numpatch))
+ allocate (a_leafnCap (numpatch))
+ allocate (a_leafn_storageCap (numpatch))
+ allocate (a_leafn_xferCap (numpatch))
+ allocate (a_frootnCap (numpatch))
+ allocate (a_frootn_storageCap (numpatch))
+ allocate (a_frootn_xferCap (numpatch))
+ allocate (a_livestemnCap (numpatch))
+ allocate (a_livestemn_storageCap (numpatch))
+ allocate (a_livestemn_xferCap (numpatch))
+ allocate (a_deadstemnCap (numpatch))
+ allocate (a_deadstemn_storageCap (numpatch))
+ allocate (a_deadstemn_xferCap (numpatch))
+ allocate (a_livecrootnCap (numpatch))
+ allocate (a_livecrootn_storageCap (numpatch))
+ allocate (a_livecrootn_xferCap (numpatch))
+ allocate (a_deadcrootnCap (numpatch))
+ allocate (a_deadcrootn_storageCap (numpatch))
+ allocate (a_deadcrootn_xferCap (numpatch))
+#endif
+! Ozone stress variables
+ allocate (a_ozone (numpatch))
+! End ozone stress variables
+ allocate (a_t_soisno (maxsnl+1:nl_soil,numpatch))
+ allocate (a_wliq_soisno (maxsnl+1:nl_soil,numpatch))
+ allocate (a_wice_soisno (maxsnl+1:nl_soil,numpatch))
+ allocate (a_h2osoi (1:nl_soil, numpatch))
+ allocate (a_qlayer (0:nl_soil, numpatch))
+ allocate (a_lake_deficit (numpatch))
+ allocate (a_rootr (1:nl_soil, numpatch))
+ allocate (a_BD_all (1:nl_soil, numpatch))
+ allocate (a_wfc (1:nl_soil, numpatch))
+ allocate (a_OM_density (1:nl_soil, numpatch))
+!Plant Hydraulic parameters
+ allocate (a_vegwp (1:nvegwcs, numpatch))
+!End Plant Hydraulic parameters
+ allocate (a_dz_lake (nl_lake, numpatch))
+ allocate (a_t_lake (nl_lake, numpatch))
+ allocate (a_lake_icefrac(nl_lake, numpatch))
+
+#ifdef BGC
+ allocate (a_litr1c_vr (1:nl_soil, numpatch))
+ allocate (a_litr2c_vr (1:nl_soil, numpatch))
+ allocate (a_litr3c_vr (1:nl_soil, numpatch))
+ allocate (a_soil1c_vr (1:nl_soil, numpatch))
+ allocate (a_soil2c_vr (1:nl_soil, numpatch))
+ allocate (a_soil3c_vr (1:nl_soil, numpatch))
+ allocate (a_cwdc_vr (1:nl_soil, numpatch))
+ allocate (a_litr1n_vr (1:nl_soil, numpatch))
+ allocate (a_litr2n_vr (1:nl_soil, numpatch))
+ allocate (a_litr3n_vr (1:nl_soil, numpatch))
+ allocate (a_soil1n_vr (1:nl_soil, numpatch))
+ allocate (a_soil2n_vr (1:nl_soil, numpatch))
+ allocate (a_soil3n_vr (1:nl_soil, numpatch))
+ allocate (a_cwdn_vr (1:nl_soil, numpatch))
+ allocate (a_totsoiln_vr (1:nl_soil, numpatch))
+ allocate (a_sminn_vr (1:nl_soil, numpatch))
+ allocate (decomp_vr_tmp (1:nl_soil, numpatch))
+
+ allocate (a_litr1cCap_vr(1:nl_soil, numpatch))
+ allocate (a_litr2cCap_vr(1:nl_soil, numpatch))
+ allocate (a_litr3cCap_vr(1:nl_soil, numpatch))
+ allocate (a_soil1cCap_vr(1:nl_soil, numpatch))
+ allocate (a_soil2cCap_vr(1:nl_soil, numpatch))
+ allocate (a_soil3cCap_vr(1:nl_soil, numpatch))
+ allocate (a_cwdcCap_vr (1:nl_soil, numpatch))
+ allocate (a_litr1nCap_vr(1:nl_soil, numpatch))
+ allocate (a_litr2nCap_vr(1:nl_soil, numpatch))
+ allocate (a_litr3nCap_vr(1:nl_soil, numpatch))
+ allocate (a_soil1nCap_vr(1:nl_soil, numpatch))
+ allocate (a_soil2nCap_vr(1:nl_soil, numpatch))
+ allocate (a_soil3nCap_vr(1:nl_soil, numpatch))
+ allocate (a_cwdnCap_vr (1:nl_soil, numpatch))
+ allocate (a_t_scalar (1:nl_soil, numpatch))
+ allocate (a_w_scalar (1:nl_soil, numpatch))
+#endif
+
+ allocate (a_ustar (numpatch))
+ allocate (a_ustar2 (numpatch))
+ allocate (a_tstar (numpatch))
+ allocate (a_qstar (numpatch))
+ allocate (a_zol (numpatch))
+ allocate (a_rib (numpatch))
+ allocate (a_fm (numpatch))
+ allocate (a_fh (numpatch))
+ allocate (a_fq (numpatch))
+
+ allocate (a_us10m (numpatch))
+ allocate (a_vs10m (numpatch))
+ allocate (a_fm10m (numpatch))
+
+ allocate (a_sr (numpatch))
+ allocate (a_solvd (numpatch))
+ allocate (a_solvi (numpatch))
+ allocate (a_solnd (numpatch))
+ allocate (a_solni (numpatch))
+ allocate (a_srvd (numpatch))
+ allocate (a_srvi (numpatch))
+ allocate (a_srnd (numpatch))
+ allocate (a_srni (numpatch))
+ allocate (a_solvdln (numpatch))
+ allocate (a_solviln (numpatch))
+ allocate (a_solndln (numpatch))
+ allocate (a_solniln (numpatch))
+ allocate (a_srvdln (numpatch))
+ allocate (a_srviln (numpatch))
+ allocate (a_srndln (numpatch))
+ allocate (a_srniln (numpatch))
+#ifdef HYPERSPECTRAL
+ allocate (a_sol_dir_ln_hires(211, numpatch))
+ allocate (a_sol_dif_ln_hires(211, numpatch))
+ allocate (a_sr_dir_ln_hires (211, numpatch))
+ allocate (a_sr_dif_ln_hires (211, numpatch))
+#endif
+ allocate (a_sensors (nsensor,numpatch))
+
+ allocate (nac_ln (numpatch))
+ allocate (nac_dt (numpatch))
+ allocate (filter_dt (numpatch))
+
+ ENDIF
+ ENDIF
+
+#ifdef EXTERNAL_LAKE
+ CALL allocate_LakeAccVars
+#endif
+
+ IF (p_is_compute) THEN
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+ ENDIF
+
+ END SUBROUTINE allocate_acc_fluxes
+
+ SUBROUTINE deallocate_acc_fluxes ()
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_LandUrban, only: numurban
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ deallocate (a_us )
+ deallocate (a_vs )
+ deallocate (a_t )
+ deallocate (a_q )
+ deallocate (a_prc )
+ deallocate (a_prl )
+ deallocate (a_pbot )
+ deallocate (a_frl )
+ deallocate (a_solarin)
+ deallocate (a_hpbl )
+
+ deallocate (a_taux )
+ deallocate (a_tauy )
+ deallocate (a_fsena )
+ deallocate (a_lfevpa )
+ deallocate (a_fevpa )
+ deallocate (a_fsenl )
+ deallocate (a_fevpl )
+ deallocate (a_etr )
+ deallocate (a_fseng )
+ deallocate (a_fevpg )
+ deallocate (a_fgrnd )
+ deallocate (a_sabvsun )
+ deallocate (a_sabvsha )
+ deallocate (a_sabg )
+ deallocate (a_olrg )
+ deallocate (a_rnet )
+ deallocate (a_xerr )
+ deallocate (a_zerr )
+ deallocate (a_rsur )
+ deallocate (a_rsur_se )
+ deallocate (a_rsur_ie )
+ deallocate (a_rsub )
+ deallocate (a_rnof )
+#ifdef CatchLateralFlow
+ deallocate (a_xwsur )
+ deallocate (a_xwsub )
+ deallocate (a_fldarea )
+#endif
+ deallocate (a_qintr )
+ deallocate (a_qinfl )
+ deallocate (a_qdrip )
+ deallocate (a_rstfacsun )
+ deallocate (a_rstfacsha )
+ deallocate (a_gssun )
+ deallocate (a_gssha )
+ deallocate (a_rss )
+ deallocate (a_wdsrf )
+
+ deallocate (a_zwt )
+ deallocate (a_wa )
+ deallocate (a_wat )
+ deallocate (a_wetwat )
+ deallocate (a_assim )
+ deallocate (a_respc )
+
+ deallocate (a_assimsun ) !1
+ deallocate (a_assimsha ) !1
+ deallocate (a_etrsun ) !1
+ deallocate (a_etrsha ) !1
+
+ deallocate (a_qcharge )
+
+ deallocate (a_t_grnd )
+ deallocate (a_tleaf )
+ deallocate (a_ldew_rain )
+ deallocate (a_ldew_snow )
+ deallocate (a_ldew )
+ deallocate (a_scv )
+ deallocate (a_snowdp )
+ deallocate (a_fsno )
+ deallocate (a_frcsat )
+ deallocate (a_sigf )
+ deallocate (a_green )
+ deallocate (a_lai )
+ deallocate (a_laisun )
+ deallocate (a_laisha )
+ deallocate (a_sai )
+
+ deallocate (a_alb )
+#ifdef HYPERSPECTRAL
+ deallocate (a_alb_hires )
+ deallocate (a_reflectance_out )
+ deallocate (a_transmittance_out)
+#endif
+
+ deallocate (a_emis )
+ deallocate (a_z0m )
+ deallocate (a_trad )
+ deallocate (a_tref )
+ deallocate (a_t2m_wmo )
+ deallocate (a_qref )
+ deallocate (a_rain )
+ deallocate (a_snow )
+
+ deallocate (a_o3uptakesun)
+ deallocate (a_o3uptakesha)
+
+#ifdef DataAssimilation
+ deallocate (a_h2osoi_ens )
+ deallocate (a_t_brt_smap_ens )
+ deallocate (a_t_brt_fy3d_ens )
+ deallocate (a_t_brt_fy3d )
+ deallocate (a_t_brt_smap )
+ deallocate (a_wliq_soisno_ens)
+ deallocate (a_wice_soisno_ens)
+ deallocate (a_t_soisno_ens )
+#endif
+
+#ifdef URBAN_MODEL
+ IF (numurban > 0) THEN
+ deallocate (a_t_room )
+ deallocate (a_tafu )
+ deallocate (a_fhac )
+ deallocate (a_fwst )
+ deallocate (a_fach )
+ deallocate (a_fahe )
+ deallocate (a_fhah )
+ deallocate (a_vehc )
+ deallocate (a_meta )
+
+ deallocate (a_senroof )
+ deallocate (a_senwsun )
+ deallocate (a_senwsha )
+ deallocate (a_sengimp )
+ deallocate (a_sengper )
+ deallocate (a_senurbl )
+
+ deallocate (a_lfevproof )
+ deallocate (a_lfevpgimp )
+ deallocate (a_lfevpgper )
+ deallocate (a_lfevpurbl )
+
+ deallocate (a_troof )
+ deallocate (a_twall )
+ ENDIF
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ deallocate (a_lai_enftemp )
+ deallocate (a_lai_enfboreal )
+ deallocate (a_lai_dnfboreal )
+ deallocate (a_lai_ebftrop )
+ deallocate (a_lai_ebftemp )
+ deallocate (a_lai_dbftrop )
+ deallocate (a_lai_dbftemp )
+ deallocate (a_lai_dbfboreal )
+ deallocate (a_lai_ebstemp )
+ deallocate (a_lai_dbstemp )
+ deallocate (a_lai_dbsboreal )
+ deallocate (a_lai_c3arcgrass )
+ deallocate (a_lai_c3grass )
+ deallocate (a_lai_c4grass )
+#endif
+
+#ifdef BGC
+ deallocate (a_leafc )
+ deallocate (a_leafc_storage )
+ deallocate (a_leafc_xfer )
+ deallocate (a_frootc )
+ deallocate (a_frootc_storage )
+ deallocate (a_frootc_xfer )
+ deallocate (a_livestemc )
+ deallocate (a_livestemc_storage )
+ deallocate (a_livestemc_xfer )
+ deallocate (a_deadstemc )
+ deallocate (a_deadstemc_storage )
+ deallocate (a_deadstemc_xfer )
+ deallocate (a_livecrootc )
+ deallocate (a_livecrootc_storage )
+ deallocate (a_livecrootc_xfer )
+ deallocate (a_deadcrootc )
+ deallocate (a_deadcrootc_storage )
+ deallocate (a_deadcrootc_xfer )
+ deallocate (a_grainc )
+ deallocate (a_grainc_storage )
+ deallocate (a_grainc_xfer )
+ deallocate (a_leafn )
+ deallocate (a_leafn_storage )
+ deallocate (a_leafn_xfer )
+ deallocate (a_frootn )
+ deallocate (a_frootn_storage )
+ deallocate (a_frootn_xfer )
+ deallocate (a_livestemn )
+ deallocate (a_livestemn_storage )
+ deallocate (a_livestemn_xfer )
+ deallocate (a_deadstemn )
+ deallocate (a_deadstemn_storage )
+ deallocate (a_deadstemn_xfer )
+ deallocate (a_livecrootn )
+ deallocate (a_livecrootn_storage )
+ deallocate (a_livecrootn_xfer )
+ deallocate (a_deadcrootn )
+ deallocate (a_deadcrootn_storage )
+ deallocate (a_deadcrootn_xfer )
+ deallocate (a_grainn )
+ deallocate (a_grainn_storage )
+ deallocate (a_grainn_xfer )
+ deallocate (a_retransn )
+ deallocate (a_gpp )
+ deallocate (a_downreg )
+ deallocate (a_ar )
+ deallocate (a_cwdprod )
+ deallocate (a_cwddecomp )
+ deallocate (a_hr )
+ deallocate (a_fpg )
+ deallocate (a_fpi )
+ deallocate (a_totvegc )
+ deallocate (a_totlitc )
+ deallocate (a_totcwdc )
+ deallocate (a_totsomc )
+ deallocate (a_totcolc )
+ deallocate (a_totvegn )
+ deallocate (a_totlitn )
+ deallocate (a_totcwdn )
+ deallocate (a_totsomn )
+ deallocate (a_totcoln )
+ deallocate (a_gpp_enftemp ) !1
+ deallocate (a_gpp_enfboreal ) !2
+ deallocate (a_gpp_dnfboreal ) !3
+ deallocate (a_gpp_ebftrop ) !4
+ deallocate (a_gpp_ebftemp ) !5
+ deallocate (a_gpp_dbftrop ) !6
+ deallocate (a_gpp_dbftemp ) !7
+ deallocate (a_gpp_dbfboreal ) !8
+ deallocate (a_gpp_ebstemp ) !9
+ deallocate (a_gpp_dbstemp ) !10
+ deallocate (a_gpp_dbsboreal ) !11
+ deallocate (a_gpp_c3arcgrass ) !12
+ deallocate (a_gpp_c3grass ) !13
+ deallocate (a_gpp_c4grass ) !14
+ deallocate (a_npp_enftemp ) !1
+ deallocate (a_npp_enfboreal ) !2
+ deallocate (a_npp_dnfboreal ) !3
+ deallocate (a_npp_ebftrop ) !4
+ deallocate (a_npp_ebftemp ) !5
+ deallocate (a_npp_dbftrop ) !6
+ deallocate (a_npp_dbftemp ) !7
+ deallocate (a_npp_dbfboreal ) !8
+ deallocate (a_npp_ebstemp ) !9
+ deallocate (a_npp_dbstemp ) !10
+ deallocate (a_npp_dbsboreal ) !11
+ deallocate (a_npp_c3arcgrass ) !12
+ deallocate (a_npp_c3grass ) !13
+ deallocate (a_npp_c4grass ) !14
+ deallocate (a_npptoleafc_enftemp ) !1
+ deallocate (a_npptoleafc_enfboreal ) !2
+ deallocate (a_npptoleafc_dnfboreal ) !3
+ deallocate (a_npptoleafc_ebftrop ) !4
+ deallocate (a_npptoleafc_ebftemp ) !5
+ deallocate (a_npptoleafc_dbftrop ) !6
+ deallocate (a_npptoleafc_dbftemp ) !7
+ deallocate (a_npptoleafc_dbfboreal ) !8
+ deallocate (a_npptoleafc_ebstemp ) !9
+ deallocate (a_npptoleafc_dbstemp ) !10
+ deallocate (a_npptoleafc_dbsboreal ) !11
+ deallocate (a_npptoleafc_c3arcgrass ) !12
+ deallocate (a_npptoleafc_c3grass ) !13
+ deallocate (a_npptoleafc_c4grass ) !14
+ deallocate (a_leafc_enftemp ) !1
+ deallocate (a_leafc_enfboreal ) !2
+ deallocate (a_leafc_dnfboreal ) !3
+ deallocate (a_leafc_ebftrop ) !4
+ deallocate (a_leafc_ebftemp ) !5
+ deallocate (a_leafc_dbftrop ) !6
+ deallocate (a_leafc_dbftemp ) !7
+ deallocate (a_leafc_dbfboreal ) !8
+ deallocate (a_leafc_ebstemp ) !9
+ deallocate (a_leafc_dbstemp ) !10
+ deallocate (a_leafc_dbsboreal ) !11
+ deallocate (a_leafc_c3arcgrass ) !12
+ deallocate (a_leafc_c3grass ) !13
+ deallocate (a_leafc_c4grass ) !14
+
+ deallocate (a_O2_DECOMP_DEPTH_UNSAT )
+ deallocate (a_CONC_O2_UNSAT )
+
+#ifdef CROP
+ deallocate (a_pdcorn )
+ deallocate (a_pdswheat )
+ deallocate (a_pdwwheat )
+ deallocate (a_pdsoybean )
+ deallocate (a_pdcotton )
+ deallocate (a_pdrice1 )
+ deallocate (a_pdrice2 )
+ deallocate (a_pdsugarcane )
+ deallocate (a_plantdate )
+ deallocate (a_manunitro )
+ deallocate (a_fertnitro_corn )
+ deallocate (a_fertnitro_swheat )
+ deallocate (a_fertnitro_wwheat )
+ deallocate (a_fertnitro_soybean )
+ deallocate (a_fertnitro_cotton )
+ deallocate (a_fertnitro_rice1 )
+ deallocate (a_fertnitro_rice2 )
+ deallocate (a_fertnitro_sugarcane)
+ deallocate (a_irrig_method_corn )
+ deallocate (a_irrig_method_swheat )
+ deallocate (a_irrig_method_wwheat )
+ deallocate (a_irrig_method_soybean )
+ deallocate (a_irrig_method_cotton )
+ deallocate (a_irrig_method_rice1 )
+ deallocate (a_irrig_method_rice2 )
+ deallocate (a_irrig_method_sugarcane)
+ deallocate (a_cphase )
+ deallocate (a_hui )
+ deallocate (a_vf )
+ deallocate (a_gddmaturity )
+ deallocate (a_gddplant )
+ deallocate (a_cropprod1c )
+ deallocate (a_cropprod1c_loss )
+ deallocate (a_cropseedc_deficit )
+ deallocate (a_grainc_to_cropprodc)
+ deallocate (a_grainc_to_seed )
+ deallocate (a_fert_to_sminn )
+
+ deallocate (a_sum_irrig )
+ deallocate (a_sum_deficit_irrig )
+ deallocate (a_sum_irrig_count )
+ deallocate (a_waterstorage )
+ deallocate (a_groundwater_demand )
+ deallocate (a_groundwater_supply )
+ deallocate (a_reservoirriver_demand)
+ deallocate (a_reservoirriver_supply)
+ deallocate (a_reservoir_supply )
+ deallocate (a_river_supply )
+ deallocate (a_runoff_supply )
+#endif
+ deallocate (a_ndep_to_sminn )
+
+ deallocate (a_abm )
+ deallocate (a_gdp )
+ deallocate (a_peatf )
+ deallocate (a_hdm )
+ deallocate (a_lnfm )
+
+ deallocate (a_leafcCap )
+ deallocate (a_leafc_storageCap )
+ deallocate (a_leafc_xferCap )
+ deallocate (a_frootcCap )
+ deallocate (a_frootc_storageCap )
+ deallocate (a_frootc_xferCap )
+ deallocate (a_livestemcCap )
+ deallocate (a_livestemc_storageCap )
+ deallocate (a_livestemc_xferCap )
+ deallocate (a_deadstemcCap )
+ deallocate (a_deadstemc_storageCap )
+ deallocate (a_deadstemc_xferCap )
+ deallocate (a_livecrootcCap )
+ deallocate (a_livecrootc_storageCap)
+ deallocate (a_livecrootc_xferCap )
+ deallocate (a_deadcrootcCap )
+ deallocate (a_deadcrootc_storageCap)
+ deallocate (a_deadcrootc_xferCap )
+ deallocate (a_leafnCap )
+ deallocate (a_leafn_storageCap )
+ deallocate (a_leafn_xferCap )
+ deallocate (a_frootnCap )
+ deallocate (a_frootn_storageCap )
+ deallocate (a_frootn_xferCap )
+ deallocate (a_livestemnCap )
+ deallocate (a_livestemn_storageCap )
+ deallocate (a_livestemn_xferCap )
+ deallocate (a_deadstemnCap )
+ deallocate (a_deadstemn_storageCap )
+ deallocate (a_deadstemn_xferCap )
+ deallocate (a_livecrootnCap )
+ deallocate (a_livecrootn_storageCap)
+ deallocate (a_livecrootn_xferCap )
+ deallocate (a_deadcrootnCap )
+ deallocate (a_deadcrootn_storageCap)
+ deallocate (a_deadcrootn_xferCap )
+#endif
+! Ozone stress variables
+ deallocate (a_ozone )
+! END ozone stress variables
+
+ deallocate (a_t_soisno )
+ deallocate (a_wliq_soisno )
+ deallocate (a_wice_soisno )
+ deallocate (a_h2osoi )
+ deallocate (a_qlayer )
+ deallocate (a_lake_deficit)
+ deallocate (a_rootr )
+ deallocate (a_BD_all )
+ deallocate (a_wfc )
+ deallocate (a_OM_density )
+!Plant Hydraulic parameters
+ deallocate (a_vegwp )
+!END plant hydraulic parameters
+ deallocate (a_dz_lake )
+ deallocate (a_t_lake )
+ deallocate (a_lake_icefrac)
+#ifdef BGC
+ deallocate (a_litr1c_vr )
+ deallocate (a_litr2c_vr )
+ deallocate (a_litr3c_vr )
+ deallocate (a_soil1c_vr )
+ deallocate (a_soil2c_vr )
+ deallocate (a_soil3c_vr )
+ deallocate (a_cwdc_vr )
+ deallocate (a_litr1n_vr )
+ deallocate (a_litr2n_vr )
+ deallocate (a_litr3n_vr )
+ deallocate (a_soil1n_vr )
+ deallocate (a_soil2n_vr )
+ deallocate (a_soil3n_vr )
+ deallocate (a_cwdn_vr )
+ deallocate (a_totsoiln_vr )
+ deallocate (a_sminn_vr )
+ deallocate (decomp_vr_tmp )
+ deallocate (a_litr1cCap_vr)
+ deallocate (a_litr2cCap_vr)
+ deallocate (a_litr3cCap_vr)
+ deallocate (a_soil1cCap_vr)
+ deallocate (a_soil2cCap_vr)
+ deallocate (a_soil3cCap_vr)
+ deallocate (a_cwdcCap_vr )
+ deallocate (a_litr1nCap_vr)
+ deallocate (a_litr2nCap_vr)
+ deallocate (a_litr3nCap_vr)
+ deallocate (a_soil1nCap_vr)
+ deallocate (a_soil2nCap_vr)
+ deallocate (a_soil3nCap_vr)
+ deallocate (a_cwdnCap_vr )
+ deallocate (a_t_scalar )
+ deallocate (a_w_scalar )
+#endif
+
+ deallocate (a_ustar )
+ deallocate (a_ustar2 )
+ deallocate (a_tstar )
+ deallocate (a_qstar )
+ deallocate (a_zol )
+ deallocate (a_rib )
+ deallocate (a_fm )
+ deallocate (a_fh )
+ deallocate (a_fq )
+
+ deallocate (a_us10m )
+ deallocate (a_vs10m )
+ deallocate (a_fm10m )
+
+ deallocate (a_sr )
+ deallocate (a_solvd )
+ deallocate (a_solvi )
+ deallocate (a_solnd )
+ deallocate (a_solni )
+ deallocate (a_srvd )
+ deallocate (a_srvi )
+ deallocate (a_srnd )
+ deallocate (a_srni )
+ deallocate (a_solvdln )
+ deallocate (a_solviln )
+ deallocate (a_solndln )
+ deallocate (a_solniln )
+ deallocate (a_srvdln )
+ deallocate (a_srviln )
+ deallocate (a_srndln )
+ deallocate (a_srniln )
+#ifdef HYPERSPECTRAL
+ deallocate (a_sol_dir_ln_hires)
+ deallocate (a_sol_dif_ln_hires)
+ deallocate (a_sr_dir_ln_hires )
+ deallocate (a_sr_dif_ln_hires )
+#endif
+ deallocate (a_sensors )
+
+ deallocate (nac_ln )
+ deallocate (nac_dt )
+ deallocate (filter_dt )
+
+ ENDIF
+ ENDIF
+
+#ifdef EXTERNAL_LAKE
+ CALL deallocate_LakeAccVars
+#endif
+
+ END SUBROUTINE deallocate_acc_fluxes
+
+ !-----------------------
+ SUBROUTINE FLUSH_acc_fluxes ()
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_LandUrban, only: numurban
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ nac = 0
+
+ IF (numpatch > 0) THEN
+
+ ! flush the Fluxes for accumulation
+ a_us (:) = spval
+ a_vs (:) = spval
+ a_t (:) = spval
+ a_q (:) = spval
+ a_prc (:) = spval
+ a_prl (:) = spval
+ a_pbot (:) = spval
+ a_frl (:) = spval
+ a_solarin (:) = spval
+ a_hpbl (:) = spval
+
+ a_taux (:) = spval
+ a_tauy (:) = spval
+ a_fsena (:) = spval
+ a_lfevpa (:) = spval
+ a_fevpa (:) = spval
+ a_fsenl (:) = spval
+ a_fevpl (:) = spval
+ a_etr (:) = spval
+ a_fseng (:) = spval
+ a_fevpg (:) = spval
+ a_fgrnd (:) = spval
+ a_sabvsun (:) = spval
+ a_sabvsha (:) = spval
+ a_sabg (:) = spval
+ a_olrg (:) = spval
+ a_rnet (:) = spval
+ a_xerr (:) = spval
+ a_zerr (:) = spval
+ a_rsur (:) = spval
+ a_rsur_se (:) = spval
+ a_rsur_ie (:) = spval
+ a_rsub (:) = spval
+ a_rnof (:) = spval
+#ifdef CatchLateralFlow
+ a_xwsur (:) = spval
+ a_xwsub (:) = spval
+ a_fldarea (:) = spval
+#endif
+ a_qintr (:) = spval
+ a_qinfl (:) = spval
+ a_qdrip (:) = spval
+ a_rstfacsun (:) = spval
+ a_rstfacsha (:) = spval
+ a_gssun (:) = spval
+ a_gssha (:) = spval
+ a_rss (:) = spval
+
+ a_wdsrf (:) = spval
+ a_zwt (:) = spval
+ a_wa (:) = spval
+ a_wat (:) = spval
+ a_wetwat (:) = spval
+ a_assim (:) = spval
+ a_respc (:) = spval
+ a_assimsun (:) = spval
+ a_assimsha (:) = spval
+ a_etrsun (:) = spval
+ a_etrsha (:) = spval
+
+ a_qcharge (:) = spval
+
+ a_t_grnd (:) = spval
+ a_tleaf (:) = spval
+ a_ldew_rain (:) = spval
+ a_ldew_snow (:) = spval
+ a_ldew (:) = spval
+ a_scv (:) = spval
+ a_snowdp (:) = spval
+ a_fsno (:) = spval
+ a_frcsat (:) = spval
+ a_sigf (:) = spval
+ a_green (:) = spval
+ a_lai (:) = spval
+ a_laisun (:) = spval
+ a_laisha (:) = spval
+ a_sai (:) = spval
+
+ a_alb (:,:,:) = spval
+
+#ifdef HYPERSPECTRAL
+ a_alb_hires (:,:,:) = spval
+#endif
+
+ a_emis (:) = spval
+ a_z0m (:) = spval
+ a_trad (:) = spval
+ a_tref (:) = spval
+ a_t2m_wmo (:) = spval
+ a_qref (:) = spval
+ a_rain (:) = spval
+ a_snow (:) = spval
+
+ a_o3uptakesun(:) = spval
+ a_o3uptakesha(:) = spval
+
+#ifdef DataAssimilation
+ a_h2osoi_ens (:,:,:) = spval
+ a_t_brt_smap_ens (:,:,:) = spval
+ a_t_brt_fy3d_ens (:,:,:) = spval
+ a_t_brt_fy3d (:,:) = spval
+ a_t_brt_smap (:,:) = spval
+ a_wliq_soisno_ens(:,:,:) = spval
+ a_wice_soisno_ens(:,:,:) = spval
+ a_t_soisno_ens (:,:,:) = spval
+#endif
+
+#ifdef URBAN_MODEL
+ IF (numurban > 0) THEN
+ a_t_room (:) = spval
+ a_tafu (:) = spval
+ a_fhac (:) = spval
+ a_fwst (:) = spval
+ a_fach (:) = spval
+ a_fahe (:) = spval
+ a_fhah (:) = spval
+ a_vehc (:) = spval
+ a_meta (:) = spval
+
+ a_senroof (:) = spval
+ a_senwsun (:) = spval
+ a_senwsha (:) = spval
+ a_sengimp (:) = spval
+ a_sengper (:) = spval
+ a_senurbl (:) = spval
+
+ a_lfevproof(:) = spval
+ a_lfevpgimp(:) = spval
+ a_lfevpgper(:) = spval
+ a_lfevpurbl(:) = spval
+
+ a_troof (:) = spval
+ a_twall (:) = spval
+ ENDIF
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ a_lai_enftemp (:) = spval
+ a_lai_enfboreal (:) = spval
+ a_lai_dnfboreal (:) = spval
+ a_lai_ebftrop (:) = spval
+ a_lai_ebftemp (:) = spval
+ a_lai_dbftrop (:) = spval
+ a_lai_dbftemp (:) = spval
+ a_lai_dbfboreal (:) = spval
+ a_lai_ebstemp (:) = spval
+ a_lai_dbstemp (:) = spval
+ a_lai_dbsboreal (:) = spval
+ a_lai_c3arcgrass (:) = spval
+ a_lai_c3grass (:) = spval
+ a_lai_c4grass (:) = spval
+#endif
+#ifdef BGC
+ a_leafc (:) = spval
+ a_leafc_storage (:) = spval
+ a_leafc_xfer (:) = spval
+ a_frootc (:) = spval
+ a_frootc_storage (:) = spval
+ a_frootc_xfer (:) = spval
+ a_livestemc (:) = spval
+ a_livestemc_storage (:) = spval
+ a_livestemc_xfer (:) = spval
+ a_deadstemc (:) = spval
+ a_deadstemc_storage (:) = spval
+ a_deadstemc_xfer (:) = spval
+ a_livecrootc (:) = spval
+ a_livecrootc_storage (:) = spval
+ a_livecrootc_xfer (:) = spval
+ a_deadcrootc (:) = spval
+ a_deadcrootc_storage (:) = spval
+ a_deadcrootc_xfer (:) = spval
+ a_grainc (:) = spval
+ a_grainc_storage (:) = spval
+ a_grainc_xfer (:) = spval
+ a_leafn (:) = spval
+ a_leafn_storage (:) = spval
+ a_leafn_xfer (:) = spval
+ a_frootn (:) = spval
+ a_frootn_storage (:) = spval
+ a_frootn_xfer (:) = spval
+ a_livestemn (:) = spval
+ a_livestemn_storage (:) = spval
+ a_livestemn_xfer (:) = spval
+ a_deadstemn (:) = spval
+ a_deadstemn_storage (:) = spval
+ a_deadstemn_xfer (:) = spval
+ a_livecrootn (:) = spval
+ a_livecrootn_storage (:) = spval
+ a_livecrootn_xfer (:) = spval
+ a_deadcrootn (:) = spval
+ a_deadcrootn_storage (:) = spval
+ a_deadcrootn_xfer (:) = spval
+ a_grainn (:) = spval
+ a_grainn_storage (:) = spval
+ a_grainn_xfer (:) = spval
+ a_retransn (:) = spval
+ a_gpp (:) = spval
+ a_downreg (:) = spval
+ a_ar (:) = spval
+ a_cwdprod (:) = spval
+ a_cwddecomp (:) = spval
+ a_hr (:) = spval
+ a_fpg (:) = spval
+ a_fpi (:) = spval
+ a_totvegc (:) = spval
+ a_totlitc (:) = spval
+ a_totcwdc (:) = spval
+ a_totsomc (:) = spval
+ a_totcolc (:) = spval
+ a_totvegn (:) = spval
+ a_totlitn (:) = spval
+ a_totcwdn (:) = spval
+ a_totsomn (:) = spval
+ a_totcoln (:) = spval
+ a_gpp_enftemp (:) = spval
+ a_gpp_enfboreal (:) = spval
+ a_gpp_dnfboreal (:) = spval
+ a_gpp_ebftrop (:) = spval
+ a_gpp_ebftemp (:) = spval
+ a_gpp_dbftrop (:) = spval
+ a_gpp_dbftemp (:) = spval
+ a_gpp_dbfboreal (:) = spval
+ a_gpp_ebstemp (:) = spval
+ a_gpp_dbstemp (:) = spval
+ a_gpp_dbsboreal (:) = spval
+ a_gpp_c3arcgrass (:) = spval
+ a_gpp_c3grass (:) = spval
+ a_gpp_c4grass (:) = spval
+ a_npp_enftemp (:) = spval
+ a_npp_enfboreal (:) = spval
+ a_npp_dnfboreal (:) = spval
+ a_npp_ebftrop (:) = spval
+ a_npp_ebftemp (:) = spval
+ a_npp_dbftrop (:) = spval
+ a_npp_dbftemp (:) = spval
+ a_npp_dbfboreal (:) = spval
+ a_npp_ebstemp (:) = spval
+ a_npp_dbstemp (:) = spval
+ a_npp_dbsboreal (:) = spval
+ a_npp_c3arcgrass (:) = spval
+ a_npp_c3grass (:) = spval
+ a_npp_c4grass (:) = spval
+ a_npptoleafc_enftemp (:) = spval
+ a_npptoleafc_enfboreal (:) = spval
+ a_npptoleafc_dnfboreal (:) = spval
+ a_npptoleafc_ebftrop (:) = spval
+ a_npptoleafc_ebftemp (:) = spval
+ a_npptoleafc_dbftrop (:) = spval
+ a_npptoleafc_dbftemp (:) = spval
+ a_npptoleafc_dbfboreal (:) = spval
+ a_npptoleafc_ebstemp (:) = spval
+ a_npptoleafc_dbstemp (:) = spval
+ a_npptoleafc_dbsboreal (:) = spval
+ a_npptoleafc_c3arcgrass (:) = spval
+ a_npptoleafc_c3grass (:) = spval
+ a_npptoleafc_c4grass (:) = spval
+ a_leafc_enftemp (:) = spval
+ a_leafc_enfboreal (:) = spval
+ a_leafc_dnfboreal (:) = spval
+ a_leafc_ebftrop (:) = spval
+ a_leafc_ebftemp (:) = spval
+ a_leafc_dbftrop (:) = spval
+ a_leafc_dbftemp (:) = spval
+ a_leafc_dbfboreal (:) = spval
+ a_leafc_ebstemp (:) = spval
+ a_leafc_dbstemp (:) = spval
+ a_leafc_dbsboreal (:) = spval
+ a_leafc_c3arcgrass (:) = spval
+ a_leafc_c3grass (:) = spval
+ a_leafc_c4grass (:) = spval
+
+ a_O2_DECOMP_DEPTH_UNSAT (:,:) = spval
+ a_CONC_O2_UNSAT (:,:) = spval
+#ifdef CROP
+ a_pdcorn (:) = spval
+ a_pdswheat (:) = spval
+ a_pdwwheat (:) = spval
+ a_pdsoybean (:) = spval
+ a_pdcotton (:) = spval
+ a_pdrice1 (:) = spval
+ a_pdrice2 (:) = spval
+ a_pdsugarcane (:) = spval
+ a_plantdate (:) = spval
+ a_manunitro (:) = spval
+ a_fertnitro_corn (:) = spval
+ a_fertnitro_swheat (:) = spval
+ a_fertnitro_wwheat (:) = spval
+ a_fertnitro_soybean (:) = spval
+ a_fertnitro_cotton (:) = spval
+ a_fertnitro_rice1 (:) = spval
+ a_fertnitro_rice2 (:) = spval
+ a_fertnitro_sugarcane(:) = spval
+ a_irrig_method_corn (:) = spval
+ a_irrig_method_swheat (:) = spval
+ a_irrig_method_wwheat (:) = spval
+ a_irrig_method_soybean (:) = spval
+ a_irrig_method_cotton (:) = spval
+ a_irrig_method_rice1 (:) = spval
+ a_irrig_method_rice2 (:) = spval
+ a_irrig_method_sugarcane(:) = spval
+ a_cphase (:) = spval
+ a_vf (:) = spval
+ a_gddmaturity (:) = spval
+ a_gddplant (:) = spval
+ a_hui (:) = spval
+ a_cropprod1c (:) = spval
+ a_cropprod1c_loss (:) = spval
+ a_cropseedc_deficit (:) = spval
+ a_grainc_to_cropprodc(:) = spval
+ a_grainc_to_seed (:) = spval
+ a_fert_to_sminn (:) = spval
+
+ a_sum_irrig (:) = spval
+ a_sum_deficit_irrig (:) = spval
+ a_sum_irrig_count (:) = spval
+ a_waterstorage (:) = spval
+ a_groundwater_demand (:) = spval
+ a_groundwater_supply (:) = spval
+ a_reservoirriver_demand(:) = spval
+ a_reservoirriver_supply(:) = spval
+ a_reservoir_supply (:) = spval
+ a_river_supply (:) = spval
+ a_runoff_supply (:) = spval
+#endif
+ a_ndep_to_sminn (:) = spval
+
+ a_abm (:) = spval
+ a_gdp (:) = spval
+ a_peatf (:) = spval
+ a_hdm (:) = spval
+ a_lnfm (:) = spval
+
+ a_leafcCap (:) = spval
+ a_leafc_storageCap (:) = spval
+ a_leafc_xferCap (:) = spval
+ a_frootcCap (:) = spval
+ a_frootc_storageCap (:) = spval
+ a_frootc_xferCap (:) = spval
+ a_livestemcCap (:) = spval
+ a_livestemc_storageCap (:) = spval
+ a_livestemc_xferCap (:) = spval
+ a_deadstemcCap (:) = spval
+ a_deadstemc_storageCap (:) = spval
+ a_deadstemc_xferCap (:) = spval
+ a_livecrootcCap (:) = spval
+ a_livecrootc_storageCap(:) = spval
+ a_livecrootc_xferCap (:) = spval
+ a_deadcrootcCap (:) = spval
+ a_deadcrootc_storageCap(:) = spval
+ a_deadcrootc_xferCap (:) = spval
+ a_leafnCap (:) = spval
+ a_leafn_storageCap (:) = spval
+ a_leafn_xferCap (:) = spval
+ a_frootnCap (:) = spval
+ a_frootn_storageCap (:) = spval
+ a_frootn_xferCap (:) = spval
+ a_livestemnCap (:) = spval
+ a_livestemn_storageCap (:) = spval
+ a_livestemn_xferCap (:) = spval
+ a_deadstemnCap (:) = spval
+ a_deadstemn_storageCap (:) = spval
+ a_deadstemn_xferCap (:) = spval
+ a_livecrootnCap (:) = spval
+ a_livecrootn_storageCap(:) = spval
+ a_livecrootn_xferCap (:) = spval
+ a_deadcrootnCap (:) = spval
+ a_deadcrootn_storageCap(:) = spval
+ a_deadcrootn_xferCap (:) = spval
+#endif
+ a_ozone (:) = spval
+
+ a_t_soisno (:,:) = spval
+ a_wliq_soisno (:,:) = spval
+ a_wice_soisno (:,:) = spval
+ a_h2osoi (:,:) = spval
+ a_qlayer (:,:) = spval
+ a_lake_deficit (:) = spval
+ a_rootr (:,:) = spval
+ a_BD_all (:,:) = spval
+ a_wfc (:,:) = spval
+ a_OM_density (:,:) = spval
+!Plant Hydraulic parameters
+ a_vegwp (:,:) = spval
+!END plant hydraulic parameters
+ a_dz_lake (:,:) = spval
+ a_t_lake (:,:) = spval
+ a_lake_icefrac (:,:) = spval
+#ifdef BGC
+ a_litr1c_vr (:,:) = spval
+ a_litr2c_vr (:,:) = spval
+ a_litr3c_vr (:,:) = spval
+ a_soil1c_vr (:,:) = spval
+ a_soil2c_vr (:,:) = spval
+ a_soil3c_vr (:,:) = spval
+ a_cwdc_vr (:,:) = spval
+ a_litr1n_vr (:,:) = spval
+ a_litr2n_vr (:,:) = spval
+ a_litr3n_vr (:,:) = spval
+ a_soil1n_vr (:,:) = spval
+ a_soil2n_vr (:,:) = spval
+ a_soil3n_vr (:,:) = spval
+ a_cwdn_vr (:,:) = spval
+ a_totsoiln_vr (:,:) = spval
+
+ a_litr1cCap_vr (:,:) = spval
+ a_litr2cCap_vr (:,:) = spval
+ a_litr3cCap_vr (:,:) = spval
+ a_soil1cCap_vr (:,:) = spval
+ a_soil2cCap_vr (:,:) = spval
+ a_soil3cCap_vr (:,:) = spval
+ a_cwdcCap_vr (:,:) = spval
+ a_litr1nCap_vr (:,:) = spval
+ a_litr2nCap_vr (:,:) = spval
+ a_litr3nCap_vr (:,:) = spval
+ a_soil1nCap_vr (:,:) = spval
+ a_soil2nCap_vr (:,:) = spval
+ a_soil3nCap_vr (:,:) = spval
+ a_cwdnCap_vr (:,:) = spval
+
+ a_t_scalar (:,:) = spval
+ a_w_scalar (:,:) = spval
+
+ a_sminn_vr (:,:) = spval
+#endif
+
+ a_ustar (:) = spval
+ a_ustar2(:) = spval
+ a_tstar (:) = spval
+ a_qstar (:) = spval
+ a_zol (:) = spval
+ a_rib (:) = spval
+ a_fm (:) = spval
+ a_fh (:) = spval
+ a_fq (:) = spval
+
+ a_us10m (:) = spval
+ a_vs10m (:) = spval
+ a_fm10m (:) = spval
+
+ a_sr (:) = spval
+ a_solvd (:) = spval
+ a_solvi (:) = spval
+ a_solnd (:) = spval
+ a_solni (:) = spval
+ a_srvd (:) = spval
+ a_srvi (:) = spval
+ a_srnd (:) = spval
+ a_srni (:) = spval
+ a_solvdln (:) = spval
+ a_solviln (:) = spval
+ a_solndln (:) = spval
+ a_solniln (:) = spval
+ a_srvdln (:) = spval
+ a_srviln (:) = spval
+ a_srndln (:) = spval
+ a_srniln (:) = spval
+#ifdef HYPERSPECTRAL
+ a_sol_dir_ln_hires(:,:) = spval
+ a_sol_dif_ln_hires(:,:) = spval
+ a_sr_dir_ln_hires (:,:) = spval
+ a_sr_dif_ln_hires (:,:) = spval
+#endif
+ a_sensors(:,:) = spval
+
+ nac_ln (:) = 0
+ nac_dt (:) = 0
+ filter_dt (:) = .true.
+
+ ENDIF
+ ENDIF
+
+#ifdef EXTERNAL_LAKE
+ CALL Flush_LakeAccVars
+#endif
+
+ END SUBROUTINE FLUSH_acc_fluxes
+
+ SUBROUTINE accumulate_fluxes
+! ----------------------------------------------------------------------
+! perform the grid average mapping: average a subgrid input 1d vector
+! of length numpatch to a output 2d array of length [ghist%xcnt,ghist%ycnt]
+!
+! Created by Yongjiu Dai, 03/2014
+!---------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE mod_forcing, only: forcmask_pch
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandElm
+ USE MOD_LandPatch, only: numpatch, elm_patch
+ USE MOD_LandUrban, only: numurban
+ USE MOD_Const_Physical, only: vonkar, stefnc, cpair, rgas, grav
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_1DForcing
+ USE MOD_Vars_1DFluxes
+ USE MOD_FrictionVelocity
+ USE MOD_Namelist, only: DEF_USE_CBL_HEIGHT, DEF_USE_OZONESTRESS, DEF_USE_PLANTHYDRAULICS, DEF_USE_NITRIF
+ USE MOD_TurbulenceLEddy
+ USE MOD_Vars_Global
+#ifdef CatchLateralFlow
+ USE MOD_Catch_Vars_1DFluxes
+ USE MOD_Catch_Hist, only: accumulate_fluxes_basin
+#endif
+
+ IMPLICIT NONE
+
+ ! Local Variables
+
+ real(r8), allocatable :: r_trad (:)
+ real(r8), allocatable :: r_ustar (:)
+ real(r8), allocatable :: r_ustar2 (:) !define a temporary for estimating us10m only, output should be r_ustar. Shaofeng, 2023.05.20
+ real(r8), allocatable :: r_tstar (:)
+ real(r8), allocatable :: r_qstar (:)
+ real(r8), allocatable :: r_zol (:)
+ real(r8), allocatable :: r_rib (:)
+ real(r8), allocatable :: r_fm (:)
+ real(r8), allocatable :: r_fh (:)
+ real(r8), allocatable :: r_fq (:)
+
+ real(r8), allocatable :: r_us10m (:)
+ real(r8), allocatable :: r_vs10m (:)
+ real(r8), allocatable :: r_fm10m (:)
+
+ logical, allocatable :: filter (:)
+
+ !---------------------------------------------------------------------
+ integer ib, jb, i, j, ielm, istt, iend
+ real(r8) sumwt
+ real(r8) rhoair,thm,th,thv,ur,displa_av,zldis,hgt_u,hgt_t,hgt_q
+ real(r8) hpbl ! atmospheric boundary layer height [m]
+ real(r8) z0m_av,z0h_av,z0q_av,us,vs,tm,qm,psrf,taux_e,tauy_e,fsena_e,fevpa_e
+ real(r8) r_ustar_e, r_tstar_e, r_qstar_e, r_zol_e, r_ustar2_e, r_fm10m_e
+ real(r8) r_fm_e, r_fh_e, r_fq_e, r_rib_e, r_us10m_e, r_vs10m_e
+ real(r8) obu,fh2m,fq2m
+ real(r8) um,thvstar,beta,zii,wc,wc2
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ ! count for time steps
+ nac = nac + 1
+
+ ! count for local noon time steps
+ DO i = 1, numpatch
+ IF (solvdln(i) /= spval) THEN
+ nac_ln(i) = nac_ln(i) + 1
+ ENDIF
+ ENDDO
+
+ ! set daytime filter
+ filter_dt(:) = coszen(:) > 0
+
+ ! count for daytime time steps
+ WHERE ( filter_dt(:) ) nac_dt(:) = nac_dt(:) + 1
+
+ CALL acc1d (forc_us , a_us )
+ CALL acc1d (forc_vs , a_vs )
+ CALL acc1d (forc_t , a_t )
+ CALL acc1d (forc_q , a_q )
+ CALL acc1d (forc_prc , a_prc )
+ CALL acc1d (forc_prl , a_prl )
+ CALL acc1d (forc_pbot , a_pbot )
+ CALL acc1d (forc_frl , a_frl )
+
+ CALL acc1d (forc_sols , a_solarin )
+ CALL acc1d (forc_soll , a_solarin )
+ CALL acc1d (forc_solsd , a_solarin )
+ CALL acc1d (forc_solld , a_solarin )
+
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL acc1d (forc_hpbl , a_hpbl)
+ ENDIF
+
+ CALL acc1d (taux , a_taux )
+ CALL acc1d (tauy , a_tauy )
+ CALL acc1d (fsena , a_fsena )
+ CALL acc1d (lfevpa , a_lfevpa )
+ CALL acc1d (fevpa , a_fevpa )
+ CALL acc1d (fsenl , a_fsenl )
+ CALL acc1d (fevpl , a_fevpl )
+ CALL acc1d (etr , a_etr )
+ CALL acc1d (fseng , a_fseng )
+ CALL acc1d (fevpg , a_fevpg )
+ CALL acc1d (fgrnd , a_fgrnd )
+ CALL acc1d (sabvsun , a_sabvsun )
+ CALL acc1d (sabvsha , a_sabvsha )
+ CALL acc1d (sabg , a_sabg )
+ CALL acc1d (olrg , a_olrg )
+
+ IF (DEF_forcing%has_missing_value) THEN
+ WHERE (forcmask_pch)
+ rnet = sabg + sabvsun + sabvsha - olrg + forc_frl
+ END WHERE
+ ELSE
+ WHERE(patchmask)
+ rnet = sabg + sabvsun + sabvsha - olrg + forc_frl
+ END WHERE
+ ENDIF
+ CALL acc1d (rnet , a_rnet )
+
+ CALL acc1d (xerr , a_xerr )
+ CALL acc1d (zerr , a_zerr )
+ CALL acc1d (rsur , a_rsur )
+#ifndef CatchLateralFlow
+ CALL acc1d (rsur_se , a_rsur_se )
+ CALL acc1d (rsur_ie , a_rsur_ie )
+#endif
+ CALL acc1d (rsub , a_rsub )
+ CALL acc1d (rnof , a_rnof )
+#ifdef CatchLateralFlow
+ CALL acc1d (xwsur , a_xwsur )
+ CALL acc1d (xwsub , a_xwsub )
+ CALL acc1d (fldarea , a_fldarea )
+#endif
+ CALL acc1d (qintr , a_qintr )
+ CALL acc1d (qinfl , a_qinfl )
+ CALL acc1d (qdrip , a_qdrip )
+
+ CALL acc1d (rstfacsun_out , a_rstfacsun )
+ CALL acc1d (rstfacsha_out , a_rstfacsha )
+
+ CALL acc1d (gssun_out , a_gssun )
+ CALL acc1d (gssha_out , a_gssha )
+
+ CALL acc1d (rss , a_rss )
+ CALL acc1d (wdsrf , a_wdsrf )
+ CALL acc1d (zwt , a_zwt )
+ CALL acc1d (wa , a_wa )
+ CALL acc1d (wat , a_wat )
+ CALL acc1d (wetwat , a_wetwat )
+ CALL acc1d (assim , a_assim )
+ CALL acc1d (respc , a_respc )
+ CALL acc1d (assimsun_out , a_assimsun )
+ CALL acc1d (assimsha_out , a_assimsha )
+ CALL acc1d (etrsun_out , a_etrsun )
+ CALL acc1d (etrsha_out , a_etrsha )
+
+ CALL acc1d (qcharge , a_qcharge )
+
+ CALL acc1d (t_grnd , a_t_grnd )
+ CALL acc1d (tleaf , a_tleaf )
+ CALL acc1d (ldew_rain , a_ldew_rain )
+ CALL acc1d (ldew_snow , a_ldew_snow )
+ CALL acc1d (ldew , a_ldew )
+ CALL acc1d (scv , a_scv )
+ CALL acc1d (snowdp , a_snowdp )
+ CALL acc1d (fsno , a_fsno )
+ CALL acc1d (frcsat , a_frcsat )
+ CALL acc1d (sigf , a_sigf )
+ CALL acc1d (green , a_green )
+ CALL acc1d (lai , a_lai )
+ CALL acc1d (laisun , a_laisun )
+ CALL acc1d (laisha , a_laisha )
+ CALL acc1d (sai , a_sai )
+
+ ! only acc for daytime for albedo
+ CALL acc3d (alb , a_alb, filter_dt )
+#ifdef HYPERSPECTRAL
+ CALL acc3d (alb_hires , a_alb_hires, filter_dt )
+#endif
+
+ CALL acc1d (emis , a_emis )
+ CALL acc1d (z0m , a_z0m )
+
+ allocate (r_trad (numpatch)) ; r_trad(:) = spval
+ DO i = 1, numpatch
+ IF (DEF_forcing%has_missing_value) THEN
+ IF (.not. forcmask_pch(i)) CYCLE
+ ENDIF
+
+ IF (.not. patchmask(i)) CYCLE
+ r_trad(i) = (olrg(i)/stefnc)**0.25
+ ENDDO
+ CALL acc1d (r_trad , a_trad )
+ deallocate (r_trad )
+
+ CALL acc1d (tref , a_tref )
+ CALL acc1d (qref , a_qref )
+
+ ! set 2m WMO temperature
+ DO ielm = 1, numelm
+
+ istt = elm_patch%substt(ielm)
+ iend = elm_patch%subend(ielm)
+
+ ! landelm%settyp=1 means 2m WMO patch exist,
+ ! which is the last end patch in a element.
+ IF (landelm%settyp(ielm)==1 .and. forcmask_pch(iend)) THEN
+ ! all set to the 2m WMO patch tref
+ t2m_wmo(istt:iend) = tref(iend)
+ ELSE
+ ! if no 2m WMO patch, keep t2m_wmo to tref
+ t2m_wmo(istt:iend) = tref(istt:iend)
+ ENDIF
+ ENDDO
+
+ CALL acc1d (t2m_wmo, a_t2m_wmo)
+
+ CALL acc1d (forc_rain, a_rain )
+ CALL acc1d (forc_snow, a_snow )
+
+ IF (DEF_USE_OZONESTRESS)THEN
+ CALL acc1d(o3uptakesun,a_o3uptakesun)
+ CALL acc1d(o3uptakesha,a_o3uptakesha)
+ ENDIF
+
+#ifdef DataAssimilation
+ CALL acc3d (h2osoi_ens , a_h2osoi_ens )
+ CALL acc3d (t_brt_smap_ens , a_t_brt_smap_ens )
+ CALL acc2d (t_brt_smap , a_t_brt_smap )
+ CALL acc3d (t_brt_fy3d_ens , a_t_brt_fy3d_ens )
+ CALL acc2d (t_brt_fy3d , a_t_brt_fy3d )
+ CALL acc3d (wliq_soisno_ens, a_wliq_soisno_ens)
+ CALL acc3d (wice_soisno_ens, a_wice_soisno_ens)
+ CALL acc3d (t_soisno_ens , a_t_soisno_ens )
+#endif
+
+#ifdef URBAN_MODEL
+ IF (numurban > 0) THEN
+ CALL acc1d(t_room , a_t_room )
+ CALL acc1d(tafu , a_tafu )
+ CALL acc1d(fhac , a_fhac )
+ CALL acc1d(fwst , a_fwst )
+ CALL acc1d(fach , a_fach )
+ CALL acc1d(fahe , a_fahe )
+ CALL acc1d(fhah , a_fhah )
+ CALL acc1d(vehc , a_vehc )
+ CALL acc1d(meta , a_meta )
+
+ CALL acc1d(fsen_roof , a_senroof )
+ CALL acc1d(fsen_wsun , a_senwsun )
+ CALL acc1d(fsen_wsha , a_senwsha )
+ CALL acc1d(fsen_gimp , a_sengimp )
+ CALL acc1d(fsen_gper , a_sengper )
+ CALL acc1d(fsen_urbl , a_senurbl )
+
+ CALL acc1d(lfevp_roof , a_lfevproof )
+ CALL acc1d(lfevp_gimp , a_lfevpgimp )
+ CALL acc1d(lfevp_gper , a_lfevpgper )
+ CALL acc1d(lfevp_urbl , a_lfevpurbl )
+
+ CALL acc1d(t_roof , a_troof )
+ CALL acc1d(t_wall , a_twall )
+ ENDIF
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL acc1d (lai_enftemp , a_lai_enftemp )
+ CALL acc1d (lai_enfboreal , a_lai_enfboreal )
+ CALL acc1d (lai_dnfboreal , a_lai_dnfboreal )
+ CALL acc1d (lai_ebftrop , a_lai_ebftrop )
+ CALL acc1d (lai_ebftemp , a_lai_ebftemp )
+ CALL acc1d (lai_dbftrop , a_lai_dbftrop )
+ CALL acc1d (lai_dbftemp , a_lai_dbftemp )
+ CALL acc1d (lai_dbfboreal , a_lai_dbfboreal )
+ CALL acc1d (lai_ebstemp , a_lai_ebstemp )
+ CALL acc1d (lai_dbstemp , a_lai_dbstemp )
+ CALL acc1d (lai_dbsboreal , a_lai_dbsboreal )
+ CALL acc1d (lai_c3arcgrass , a_lai_c3arcgrass )
+ CALL acc1d (lai_c3grass , a_lai_c3grass )
+ CALL acc1d (lai_c4grass , a_lai_c4grass )
+#endif
+#ifdef BGC
+ CALL acc1d (leafc , a_leafc )
+ CALL acc1d (leafc_storage , a_leafc_storage )
+ CALL acc1d (leafc_xfer , a_leafc_xfer )
+ CALL acc1d (frootc , a_frootc )
+ CALL acc1d (frootc_storage , a_frootc_storage )
+ CALL acc1d (frootc_xfer , a_frootc_xfer )
+ CALL acc1d (livestemc , a_livestemc )
+ CALL acc1d (livestemc_storage , a_livestemc_storage )
+ CALL acc1d (livestemc_xfer , a_livestemc_xfer )
+ CALL acc1d (deadstemc , a_deadstemc )
+ CALL acc1d (deadstemc_storage , a_deadstemc_storage )
+ CALL acc1d (deadstemc_xfer , a_deadstemc_xfer )
+ CALL acc1d (livecrootc , a_livecrootc )
+ CALL acc1d (livecrootc_storage , a_livecrootc_storage )
+ CALL acc1d (livecrootc_xfer , a_livecrootc_xfer )
+ CALL acc1d (deadcrootc , a_deadcrootc )
+ CALL acc1d (deadcrootc_storage , a_deadcrootc_storage )
+ CALL acc1d (deadcrootc_xfer , a_deadcrootc_xfer )
+ CALL acc1d (grainc , a_grainc )
+ CALL acc1d (grainc_storage , a_grainc_storage )
+ CALL acc1d (grainc_xfer , a_grainc_xfer )
+ CALL acc1d (leafn , a_leafn )
+ CALL acc1d (leafn_storage , a_leafn_storage )
+ CALL acc1d (leafn_xfer , a_leafn_xfer )
+ CALL acc1d (frootn , a_frootn )
+ CALL acc1d (frootn_storage , a_frootn_storage )
+ CALL acc1d (frootn_xfer , a_frootn_xfer )
+ CALL acc1d (livestemn , a_livestemn )
+ CALL acc1d (livestemn_storage , a_livestemn_storage )
+ CALL acc1d (livestemn_xfer , a_livestemn_xfer )
+ CALL acc1d (deadstemn , a_deadstemn )
+ CALL acc1d (deadstemn_storage , a_deadstemn_storage )
+ CALL acc1d (deadstemn_xfer , a_deadstemn_xfer )
+ CALL acc1d (livecrootn , a_livecrootn )
+ CALL acc1d (livecrootn_storage , a_livecrootn_storage )
+ CALL acc1d (livecrootn_xfer , a_livecrootn_xfer )
+ CALL acc1d (deadcrootn , a_deadcrootn )
+ CALL acc1d (deadcrootn_storage , a_deadcrootn_storage )
+ CALL acc1d (deadcrootn_xfer , a_deadcrootn_xfer )
+ CALL acc1d (grainn , a_grainn )
+ CALL acc1d (grainn_storage , a_grainn_storage )
+ CALL acc1d (grainn_xfer , a_grainn_xfer )
+ CALL acc1d (retransn , a_retransn )
+ CALL acc1d (gpp , a_gpp )
+ CALL acc1d (downreg , a_downreg )
+ CALL acc1d (ar , a_ar )
+ CALL acc1d (cwdprod , a_cwdprod )
+ CALL acc1d (cwddecomp , a_cwddecomp )
+ CALL acc1d (decomp_hr , a_hr )
+ CALL acc1d (fpg , a_fpg )
+ CALL acc1d (fpi , a_fpi )
+ CALL acc1d (totvegc , a_totvegc )
+ CALL acc1d (totlitc , a_totlitc )
+ CALL acc1d (totcwdc , a_totcwdc )
+ CALL acc1d (totsomc , a_totsomc )
+ CALL acc1d (totcolc , a_totcolc )
+ CALL acc1d (totvegn , a_totvegn )
+ CALL acc1d (totlitn , a_totlitn )
+ CALL acc1d (totcwdn , a_totcwdn )
+ CALL acc1d (totsomn , a_totsomn )
+ CALL acc1d (totcoln , a_totcoln )
+ CALL acc1d (gpp_enftemp , a_gpp_enftemp )
+ CALL acc1d (gpp_enfboreal , a_gpp_enfboreal )
+ CALL acc1d (gpp_dnfboreal , a_gpp_dnfboreal )
+ CALL acc1d (gpp_ebftrop , a_gpp_ebftrop )
+ CALL acc1d (gpp_ebftemp , a_gpp_ebftemp )
+ CALL acc1d (gpp_dbftrop , a_gpp_dbftrop )
+ CALL acc1d (gpp_dbftemp , a_gpp_dbftemp )
+ CALL acc1d (gpp_dbfboreal , a_gpp_dbfboreal )
+ CALL acc1d (gpp_ebstemp , a_gpp_ebstemp )
+ CALL acc1d (gpp_dbstemp , a_gpp_dbstemp )
+ CALL acc1d (gpp_dbsboreal , a_gpp_dbsboreal )
+ CALL acc1d (gpp_c3arcgrass , a_gpp_c3arcgrass )
+ CALL acc1d (gpp_c3grass , a_gpp_c3grass )
+ CALL acc1d (gpp_c4grass , a_gpp_c4grass )
+ CALL acc1d (npp_enftemp , a_npp_enftemp )
+ CALL acc1d (npp_enfboreal , a_npp_enfboreal )
+ CALL acc1d (npp_dnfboreal , a_npp_dnfboreal )
+ CALL acc1d (npp_ebftrop , a_npp_ebftrop )
+ CALL acc1d (npp_ebftemp , a_npp_ebftemp )
+ CALL acc1d (npp_dbftrop , a_npp_dbftrop )
+ CALL acc1d (npp_dbftemp , a_npp_dbftemp )
+ CALL acc1d (npp_dbfboreal , a_npp_dbfboreal )
+ CALL acc1d (npp_ebstemp , a_npp_ebstemp )
+ CALL acc1d (npp_dbstemp , a_npp_dbstemp )
+ CALL acc1d (npp_dbsboreal , a_npp_dbsboreal )
+ CALL acc1d (npp_c3arcgrass , a_npp_c3arcgrass )
+ CALL acc1d (npp_c3grass , a_npp_c3grass )
+ CALL acc1d (npp_c4grass , a_npp_c4grass )
+ CALL acc1d (npptoleafc_enftemp , a_npptoleafc_enftemp )
+ CALL acc1d (npptoleafc_enfboreal , a_npptoleafc_enfboreal )
+ CALL acc1d (npptoleafc_dnfboreal , a_npptoleafc_dnfboreal )
+ CALL acc1d (npptoleafc_ebftrop , a_npptoleafc_ebftrop )
+ CALL acc1d (npptoleafc_ebftemp , a_npptoleafc_ebftemp )
+ CALL acc1d (npptoleafc_dbftrop , a_npptoleafc_dbftrop )
+ CALL acc1d (npptoleafc_dbftemp , a_npptoleafc_dbftemp )
+ CALL acc1d (npptoleafc_dbfboreal , a_npptoleafc_dbfboreal )
+ CALL acc1d (npptoleafc_ebstemp , a_npptoleafc_ebstemp )
+ CALL acc1d (npptoleafc_dbstemp , a_npptoleafc_dbstemp )
+ CALL acc1d (npptoleafc_dbsboreal , a_npptoleafc_dbsboreal )
+ CALL acc1d (npptoleafc_c3arcgrass , a_npptoleafc_c3arcgrass )
+ CALL acc1d (npptoleafc_c3grass , a_npptoleafc_c3grass )
+ CALL acc1d (npptoleafc_c4grass , a_npptoleafc_c4grass )
+ CALL acc1d (leafc_enftemp , a_leafc_enftemp )
+ CALL acc1d (leafc_enfboreal , a_leafc_enfboreal )
+ CALL acc1d (leafc_dnfboreal , a_leafc_dnfboreal )
+ CALL acc1d (leafc_ebftrop , a_leafc_ebftrop )
+ CALL acc1d (leafc_ebftemp , a_leafc_ebftemp )
+ CALL acc1d (leafc_dbftrop , a_leafc_dbftrop )
+ CALL acc1d (leafc_dbftemp , a_leafc_dbftemp )
+ CALL acc1d (leafc_dbfboreal , a_leafc_dbfboreal )
+ CALL acc1d (leafc_ebstemp , a_leafc_ebstemp )
+ CALL acc1d (leafc_dbstemp , a_leafc_dbstemp )
+ CALL acc1d (leafc_dbsboreal , a_leafc_dbsboreal )
+ CALL acc1d (leafc_c3arcgrass , a_leafc_c3arcgrass )
+ CALL acc1d (leafc_c3grass , a_leafc_c3grass )
+ CALL acc1d (leafc_c4grass , a_leafc_c4grass )
+ IF(DEF_USE_NITRIF)THEN
+ CALL acc2d (to2_decomp_depth_unsat, a_O2_DECOMP_DEPTH_UNSAT)
+ CALL acc2d (tconc_o2_unsat , a_CONC_O2_UNSAT )
+ ENDIF
+#ifdef CROP
+ CALL acc1d (pdcorn , a_pdcorn )
+ CALL acc1d (pdswheat , a_pdswheat )
+ CALL acc1d (pdwwheat , a_pdwwheat )
+ CALL acc1d (pdsoybean , a_pdsoybean )
+ CALL acc1d (pdcotton , a_pdcotton )
+ CALL acc1d (pdrice1 , a_pdrice1 )
+ CALL acc1d (pdrice2 , a_pdrice2 )
+ CALL acc1d (pdsugarcane , a_pdsugarcane )
+ CALL acc1d (plantdate , a_plantdate )
+ CALL acc1d (manunitro , a_manunitro )
+ CALL acc1d (fertnitro_corn , a_fertnitro_corn )
+ CALL acc1d (fertnitro_swheat , a_fertnitro_swheat )
+ CALL acc1d (fertnitro_wwheat , a_fertnitro_wwheat )
+ CALL acc1d (fertnitro_soybean , a_fertnitro_soybean )
+ CALL acc1d (fertnitro_cotton , a_fertnitro_cotton )
+ CALL acc1d (fertnitro_rice1 , a_fertnitro_rice1 )
+ CALL acc1d (fertnitro_rice2 , a_fertnitro_rice2 )
+ CALL acc1d (fertnitro_sugarcane, a_fertnitro_sugarcane)
+ CALL acc1d (real(irrig_method_corn ,r8), a_irrig_method_corn )
+ CALL acc1d (real(irrig_method_swheat ,r8), a_irrig_method_swheat )
+ CALL acc1d (real(irrig_method_wwheat ,r8), a_irrig_method_wwheat )
+ CALL acc1d (real(irrig_method_soybean ,r8), a_irrig_method_soybean )
+ CALL acc1d (real(irrig_method_cotton ,r8), a_irrig_method_cotton )
+ CALL acc1d (real(irrig_method_rice1 ,r8), a_irrig_method_rice1 )
+ CALL acc1d (real(irrig_method_rice2 ,r8), a_irrig_method_rice2 )
+ CALL acc1d (real(irrig_method_sugarcane,r8), a_irrig_method_sugarcane)
+ CALL acc1d (cphase , a_cphase )
+ CALL acc1d (hui , a_hui )
+ CALL acc1d (vf , a_vf )
+ CALL acc1d (gddmaturity , a_gddmaturity )
+ CALL acc1d (gddplant , a_gddplant )
+ CALL acc1d (cropprod1c , a_cropprod1c )
+ CALL acc1d (cropprod1c_loss , a_cropprod1c_loss )
+ CALL acc1d (cropseedc_deficit , a_cropseedc_deficit )
+ CALL acc1d (grainc_to_cropprodc, a_grainc_to_cropprodc)
+ CALL acc1d (grainc_to_seed , a_grainc_to_seed )
+ CALL acc1d (fert_to_sminn , a_fert_to_sminn )
+
+ a_sum_irrig = sum_irrig
+ a_sum_irrig_count = sum_irrig_count
+ a_waterstorage = waterstorage
+ CALL acc1d (groundwater_demand , a_groundwater_demand )
+ CALL acc1d (groundwater_supply , a_groundwater_supply )
+ CALL acc1d (reservoirriver_demand, a_reservoirriver_demand)
+ CALL acc1d (reservoirriver_supply, a_reservoirriver_supply)
+ CALL acc1d (reservoir_supply , a_reservoir_supply)
+ CALL acc1d (river_supply , a_river_supply)
+ CALL acc1d (runoff_supply , a_runoff_supply)
+#endif
+ CALL acc1d (ndep_to_sminn , a_ndep_to_sminn )
+ IF(DEF_USE_FIRE)THEN
+ CALL acc1d (abm_lf , a_abm )
+ CALL acc1d (gdp_lf , a_gdp )
+ CALL acc1d (peatf_lf , a_peatf )
+ CALL acc1d (hdm_lf , a_hdm )
+ CALL acc1d (lnfm , a_lnfm )
+ ENDIF
+ IF(DEF_USE_DiagMatrix)THEN
+ CALL acc1d (leafcCap ,a_leafcCap )
+ CALL acc1d (leafc_storageCap ,a_leafc_storageCap )
+ CALL acc1d (leafc_xferCap ,a_leafc_xferCap )
+ CALL acc1d (frootcCap ,a_frootcCap )
+ CALL acc1d (frootc_storageCap ,a_frootc_storageCap )
+ CALL acc1d (frootc_xferCap ,a_frootc_xferCap )
+ CALL acc1d (livestemcCap ,a_livestemcCap )
+ CALL acc1d (livestemc_storageCap ,a_livestemc_storageCap )
+ CALL acc1d (livestemc_xferCap ,a_livestemc_xferCap )
+ CALL acc1d (deadstemcCap ,a_deadstemcCap )
+ CALL acc1d (deadstemc_storageCap ,a_deadstemc_storageCap )
+ CALL acc1d (deadstemc_xferCap ,a_deadstemc_xferCap )
+ CALL acc1d (livecrootcCap ,a_livecrootcCap )
+ CALL acc1d (livecrootc_storageCap,a_livecrootc_storageCap)
+ CALL acc1d (livecrootc_xferCap ,a_livecrootc_xferCap )
+ CALL acc1d (deadcrootcCap ,a_deadcrootcCap )
+ CALL acc1d (deadcrootc_storageCap,a_deadcrootc_storageCap)
+ CALL acc1d (deadcrootc_xferCap ,a_deadcrootc_xferCap )
+ CALL acc1d (leafnCap ,a_leafnCap )
+ CALL acc1d (leafn_storageCap ,a_leafn_storageCap )
+ CALL acc1d (leafn_xferCap ,a_leafn_xferCap )
+ CALL acc1d (frootnCap ,a_frootnCap )
+ CALL acc1d (frootn_storageCap ,a_frootn_storageCap )
+ CALL acc1d (frootn_xferCap ,a_frootn_xferCap )
+ CALL acc1d (livestemnCap ,a_livestemnCap )
+ CALL acc1d (livestemn_storageCap ,a_livestemn_storageCap )
+ CALL acc1d (livestemn_xferCap ,a_livestemn_xferCap )
+ CALL acc1d (deadstemnCap ,a_deadstemnCap )
+ CALL acc1d (deadstemn_storageCap ,a_deadstemn_storageCap )
+ CALL acc1d (deadstemn_xferCap ,a_deadstemn_xferCap )
+ CALL acc1d (livecrootnCap ,a_livecrootnCap )
+ CALL acc1d (livecrootn_storageCap,a_livecrootn_storageCap)
+ CALL acc1d (livecrootn_xferCap ,a_livecrootn_xferCap )
+ CALL acc1d (deadcrootnCap ,a_deadcrootnCap )
+ CALL acc1d (deadcrootn_storageCap,a_deadcrootn_storageCap)
+ CALL acc1d (deadcrootn_xferCap ,a_deadcrootn_xferCap )
+ ENDIF
+#endif
+ IF(DEF_USE_OZONESTRESS)THEN
+ CALL acc1d (forc_ozone , a_ozone )
+ ENDIF
+
+ IF (.not. DEF_USE_Dynamic_Lake) THEN
+ CALL acc1d (lake_deficit, a_lake_deficit)
+ ENDIF
+
+ CALL acc2d (t_soisno , a_t_soisno )
+ CALL acc2d (wliq_soisno , a_wliq_soisno )
+ CALL acc2d (wice_soisno , a_wice_soisno )
+
+ CALL acc2d (h2osoi , a_h2osoi )
+ CALL acc2d (qlayer , a_qlayer )
+ CALL acc2d (rootr , a_rootr )
+ CALL acc2d (BD_all , a_BD_all )
+ CALL acc2d (wfc , a_wfc )
+ CALL acc2d (OM_density , a_OM_density )
+ IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL acc2d (vegwp , a_vegwp )
+ ENDIF
+ IF (DEF_USE_Dynamic_Lake) THEN
+ CALL acc2d (dz_lake , a_dz_lake )
+ ENDIF
+ CALL acc2d (t_lake , a_t_lake )
+ CALL acc2d (lake_icefrac, a_lake_icefrac )
+#ifdef BGC
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_met_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr1c_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_cel_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr2c_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_lig_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr3c_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_soil1,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil1c_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_soil2,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil2c_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_soil3,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil3c_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr(j,i_cwd,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_cwdc_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_met_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr1n_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_cel_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr2n_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_lig_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr3n_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_soil1,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil1n_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_soil2,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil2n_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_soil3,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil3n_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr(j,i_cwd,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_cwdn_vr )
+ CALL acc2d (totsoiln_vr , a_totsoiln_vr )
+
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_met_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr1cCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_cel_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr2cCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_lig_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr3cCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_soil1,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil1cCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_soil2,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil2cCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_soil3,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil3cCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_cpools_vr_Cap(j,i_cwd,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_cwdcCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_met_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr1nCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_cel_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr2nCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_lig_lit,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_litr3nCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_soil1,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil1nCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_soil2,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil2nCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_soil3,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_soil3nCap_vr )
+ DO i = 1, numpatch
+ DO j = 1, nl_soil
+ decomp_vr_tmp(j,i) = decomp_npools_vr_Cap(j,i_cwd,i)
+ ENDDO
+ ENDDO
+ CALL acc2d (decomp_vr_tmp, a_cwdnCap_vr )
+ CALL acc2d (sminn_vr , a_sminn_vr )
+
+ CALL acc2d (t_scalar , a_t_scalar )
+ CALL acc2d (w_scalar , a_w_scalar )
+#endif
+ allocate (r_ustar (numpatch)); r_ustar (:) = spval
+ allocate (r_ustar2 (numpatch)); r_ustar2(:) = spval !Shaofeng, 2023.05.20
+ allocate (r_tstar (numpatch)); r_tstar (:) = spval
+ allocate (r_qstar (numpatch)); r_qstar (:) = spval
+ allocate (r_zol (numpatch)); r_zol (:) = spval
+ allocate (r_rib (numpatch)); r_rib (:) = spval
+ allocate (r_fm (numpatch)); r_fm (:) = spval
+ allocate (r_fh (numpatch)); r_fh (:) = spval
+ allocate (r_fq (numpatch)); r_fq (:) = spval
+ allocate (r_us10m (numpatch)); r_us10m (:) = spval
+ allocate (r_vs10m (numpatch)); r_vs10m (:) = spval
+ allocate (r_fm10m (numpatch)); r_fm10m (:) = spval
+
+ DO ielm = 1, numelm
+
+ istt = elm_patch%substt(ielm)
+ iend = elm_patch%subend(ielm)
+
+ allocate (filter (istt:iend))
+ filter(:) = .true.
+
+ filter(:) = patchmask(istt:iend)
+
+ IF (DEF_forcing%has_missing_value) THEN
+ WHERE (.not. forcmask_pch(istt:iend)) filter = .false.
+ filter = filter .and. forcmask_pch(istt:iend)
+ ENDIF
+
+ IF (.not. any(filter)) THEN
+ deallocate(filter)
+ CYCLE
+ ENDIF
+
+ sumwt = sum(elm_patch%subfrc(istt:iend), mask = filter)
+
+ ! Aggregate variables from patches to element (gridcell in latitude-longitude mesh)
+ z0m_av = sum(z0m (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ hgt_u = sum(forc_hgt_u (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ hgt_t = sum(forc_hgt_t (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ hgt_q = sum(forc_hgt_q (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ us = sum(forc_us (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ vs = sum(forc_vs (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ tm = sum(forc_t (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ qm = sum(forc_q (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ psrf = sum(forc_psrf (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ taux_e = sum(taux (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ tauy_e = sum(tauy (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ fsena_e = sum(fsena (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ fevpa_e = sum(fevpa (istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ hpbl = sum(forc_hpbl(istt:iend) * elm_patch%subfrc(istt:iend), mask = filter) / sumwt
+ ENDIF
+
+ z0h_av = z0m_av
+ z0q_av = z0m_av
+
+ displa_av = 2./3.*z0m_av/0.07
+
+ hgt_u = max(hgt_u, 5.+displa_av)
+ hgt_t = max(hgt_t, 5.+displa_av)
+ hgt_q = max(hgt_q, 5.+displa_av)
+
+ zldis = hgt_u-displa_av
+
+ rhoair = (psrf - 0.378*qm*psrf/(0.622+0.378*qm)) / (rgas*tm)
+
+ r_ustar_e = sqrt(max(1.e-6,sqrt(taux_e**2+tauy_e**2))/rhoair)
+ r_tstar_e = -fsena_e/(rhoair*r_ustar_e)/cpair
+ r_qstar_e = -fevpa_e/(rhoair*r_ustar_e)
+
+ thm = tm + 0.0098*hgt_t
+ th = tm*(100000./psrf)**(rgas/cpair)
+ thv = th*(1.+0.61*qm)
+
+ r_zol_e = zldis*vonkar*grav * (r_tstar_e*(1.+0.61*qm)+0.61*th*r_qstar_e) &
+ / (r_ustar_e**2*thv)
+
+ IF(r_zol_e >= 0.)THEN !stable
+ r_zol_e = min(2.,max(r_zol_e,1.e-6))
+ ELSE !unstable
+ r_zol_e = max(-100.,min(r_zol_e,-1.e-6))
+ ENDIF
+
+ beta = 1.
+ zii = 1000.
+
+ thvstar=r_tstar_e*(1.+0.61*qm)+0.61*th*r_qstar_e
+ ur = sqrt(us*us+vs*vs)
+ IF(r_zol_e >= 0.)THEN
+ um = max(ur,0.1)
+ ELSE
+ IF (DEF_USE_CBL_HEIGHT) THEN !//TODO: Shaofeng, 2023.05.18
+ zii = max(5.*hgt_u,hpbl)
+ ENDIF !//TODO: Shaofeng, 2023.05.18
+ wc = (-grav*r_ustar_e*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = max(0.1,sqrt(ur*ur+wc2))
+ ENDIF
+
+ obu = zldis/r_zol_e
+ IF (DEF_USE_CBL_HEIGHT) THEN
+ CALL moninobuk_leddy(hgt_u,hgt_t,hgt_q,displa_av,z0m_av,z0h_av,z0q_av,&
+ obu,um, hpbl, r_ustar2_e,fh2m,fq2m,r_fm10m_e,r_fm_e,r_fh_e,r_fq_e) !Shaofeng, 2023.05.20
+ ELSE
+ CALL moninobuk(hgt_u,hgt_t,hgt_q,displa_av,z0m_av,z0h_av,z0q_av,&
+ obu,um,r_ustar2_e,fh2m,fq2m,r_fm10m_e,r_fm_e,r_fh_e,r_fq_e) !Shaofeng, 2023.05.20
+ ENDIF
+
+ ! bug found by chen qiying 2013/07/01
+ r_rib_e = r_zol_e /vonkar * r_ustar2_e**2 / (vonkar/r_fh_e*um**2)
+ r_rib_e = min(5.,r_rib_e)
+
+ r_us10m_e = us/um * r_ustar2_e /vonkar * r_fm10m_e
+ r_vs10m_e = vs/um * r_ustar2_e /vonkar * r_fm10m_e
+
+ ! Assign values from element (gridcell in latitude-longitude mesh) to patches.
+ ! Notice that all values on patches in an element are equal.
+ r_ustar (istt:iend) = r_ustar_e
+ r_ustar2(istt:iend) = r_ustar2_e
+ r_tstar (istt:iend) = r_tstar_e
+ r_qstar (istt:iend) = r_qstar_e
+ r_zol (istt:iend) = r_zol_e
+ r_rib (istt:iend) = r_rib_e
+ r_fm (istt:iend) = r_fm_e
+ r_fh (istt:iend) = r_fh_e
+ r_fq (istt:iend) = r_fq_e
+ r_us10m (istt:iend) = r_us10m_e
+ r_vs10m (istt:iend) = r_vs10m_e
+ r_fm10m (istt:iend) = r_fm10m_e
+
+ deallocate(filter)
+
+ ENDDO
+
+ CALL acc1d (r_ustar , a_ustar )
+ CALL acc1d (r_ustar2 , a_ustar2 )
+ CALL acc1d (r_tstar , a_tstar )
+ CALL acc1d (r_qstar , a_qstar )
+ CALL acc1d (r_zol , a_zol )
+ CALL acc1d (r_rib , a_rib )
+ CALL acc1d (r_fm , a_fm )
+ CALL acc1d (r_fh , a_fh )
+ CALL acc1d (r_fq , a_fq )
+
+ CALL acc1d (r_us10m , a_us10m )
+ CALL acc1d (r_vs10m , a_vs10m )
+ CALL acc1d (r_fm10m , a_fm10m )
+
+ deallocate (r_ustar )
+ deallocate (r_ustar2) !Shaofeng, 2023.05.20
+ deallocate (r_tstar )
+ deallocate (r_qstar )
+ deallocate (r_zol )
+ deallocate (r_rib )
+ deallocate (r_fm )
+ deallocate (r_fh )
+ deallocate (r_fq )
+
+ deallocate (r_us10m )
+ deallocate (r_vs10m )
+ deallocate (r_fm10m )
+
+ CALL acc1d (sr , a_sr )
+ CALL acc1d (solvd , a_solvd )
+ CALL acc1d (solvi , a_solvi )
+ CALL acc1d (solnd , a_solnd )
+ CALL acc1d (solni , a_solni )
+ CALL acc1d (srvd , a_srvd )
+ CALL acc1d (srvi , a_srvi )
+ CALL acc1d (srnd , a_srnd )
+ CALL acc1d (srni , a_srni )
+ CALL acc1d (solvdln , a_solvdln )
+ CALL acc1d (solviln , a_solviln )
+ CALL acc1d (solndln , a_solndln )
+ CALL acc1d (solniln , a_solniln )
+ CALL acc1d (srvdln , a_srvdln )
+ CALL acc1d (srviln , a_srviln )
+ CALL acc1d (srndln , a_srndln )
+ CALL acc1d (srniln , a_srniln )
+
+ CALL acc2d (sensors , a_sensors )
+#ifdef HYPERSPECTRAL
+ CALL acc2d (sol_dir_ln_hires, a_sol_dir_ln_hires)
+ CALL acc2d (sol_dif_ln_hires, a_sol_dif_ln_hires)
+ CALL acc2d (sr_dir_ln_hires , a_sr_dir_ln_hires )
+ CALL acc2d (sr_dif_ln_hires , a_sr_dif_ln_hires )
+#endif
+
+ ENDIF
+ ENDIF
+
+#ifdef CatchLateralFlow
+ CALL accumulate_fluxes_basin ()
+#endif
+
+#ifdef EXTERNAL_LAKE
+ CALL accumulate_LakeTimeVars
+#endif
+
+ END SUBROUTINE accumulate_fluxes
+
+
+ !------
+ SUBROUTINE acc1d (var, s)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: spval
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: var(:)
+ real(r8), intent(inout) :: s (:)
+ ! Local variables
+ integer :: i
+
+ DO i = lbound(var,1), ubound(var,1)
+ IF (var(i) /= spval) THEN
+ IF (s(i) /= spval) THEN
+ s(i) = s(i) + var(i)
+ ELSE
+ s(i) = var(i)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE acc1d
+
+ !------
+ SUBROUTINE acc2d (var, s)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: spval
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: var(:,:)
+ real(r8), intent(inout) :: s (:,:)
+ ! Local variables
+ integer :: i1, i2
+
+ DO i2 = lbound(var,2), ubound(var,2)
+ DO i1 = lbound(var,1), ubound(var,1)
+ IF (var(i1,i2) /= spval) THEN
+ IF (s(i1,i2) /= spval) THEN
+ s(i1,i2) = s(i1,i2) + var(i1,i2)
+ ELSE
+ s(i1,i2) = var(i1,i2)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE acc2d
+
+ !------
+ SUBROUTINE acc3d (var, s, filter)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: spval
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: var(:,:,:)
+ real(r8), intent(inout) :: s (:,:,:)
+ logical, intent(in), optional :: filter(:)
+
+ ! Local variables
+ integer :: i1, i2, i3
+
+ DO i3 = lbound(var,3), ubound(var,3)
+
+ IF ( present(filter) ) THEN
+ IF ( .not. filter(i3) ) CYCLE
+ ENDIF
+
+ DO i2 = lbound(var,2), ubound(var,2)
+ DO i1 = lbound(var,1), ubound(var,1)
+ IF (var(i1,i2,i3) /= spval) THEN
+ IF (s(i1,i2,i3) /= spval) THEN
+ s(i1,i2,i3) = s(i1,i2,i3) + var(i1,i2,i3)
+ ELSE
+ s(i1,i2,i3) = var(i1,i2,i3)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE acc3d
+
+END MODULE MOD_Vars_1DAccFluxes
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DFluxes.F90
new file mode 100644
index 0000000000..1eed919be9
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DFluxes.F90
@@ -0,0 +1,305 @@
+#include
+
+MODULE MOD_Vars_1DFluxes
+!-----------------------------------------------------------------------
+! Created by Yongjiu Dai, 03/2014
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_Vars_1DPFTFluxes
+#endif
+#ifdef BGC
+ USE MOD_BGC_Vars_1DFluxes
+#endif
+#ifdef CatchLateralFlow
+ USE MOD_Catch_Vars_1DFluxes
+#endif
+#ifdef URBAN_MODEL
+ USE MOD_Urban_Vars_1DFluxes
+#endif
+#ifdef DataAssimilation
+ USE MOD_DA_Vars_1DFluxes
+#endif
+ IMPLICIT NONE
+ SAVE
+
+!-----------------------------------------------------------------------
+! Fluxes
+!-----------------------------------------------------------------------
+ real(r8), allocatable :: taux (:) !wind stress: E-W [kg/m/s2]
+ real(r8), allocatable :: tauy (:) !wind stress: N-S [kg/m/s2]
+ real(r8), allocatable :: fsena (:) !sensible heat from canopy height to atmosphere [W/m2]
+ real(r8), allocatable :: lfevpa (:) !latent heat flux from canopy height to atmosphere [W/m2]
+ real(r8), allocatable :: fevpa (:) !evapotranspiration from canopy to atmosphere [mm/s]
+ real(r8), allocatable :: fsenl (:) !sensible heat from leaves [W/m2]
+ real(r8), allocatable :: fevpl (:) !evaporation+transpiration from leaves [mm/s]
+ real(r8), allocatable :: etr (:) !transpiration rate [mm/s]
+ real(r8), allocatable :: fseng (:) !sensible heat flux from ground [W/m2]
+ real(r8), allocatable :: fevpg (:) !evaporation heat flux from ground [mm/s]
+ real(r8), allocatable :: fgrnd (:) !ground heat flux [W/m2]
+ real(r8), allocatable :: sabvsun(:) !solar absorbed by sunlit vegetation [W/m2]
+ real(r8), allocatable :: sabvsha(:) !solar absorbed by shaded vegetation [W/m2]
+ real(r8), allocatable :: sabg (:) !solar absorbed by ground [W/m2]
+ real(r8), allocatable :: sr (:) !total reflected solar radiation (W/m2)
+ real(r8), allocatable :: solvd (:) !incident direct beam vis solar radiation (W/m2)
+ real(r8), allocatable :: solvi (:) !incident diffuse beam vis solar radiation (W/m2)
+ real(r8), allocatable :: solnd (:) !incident direct beam nir solar radiation (W/m2)
+ real(r8), allocatable :: solni (:) !incident diffuse beam nir solar radiation (W/m2)
+ real(r8), allocatable :: srvd (:) !reflected direct beam vis solar radiation (W/m2)
+ real(r8), allocatable :: srvi (:) !reflected diffuse beam vis solar radiation (W/m2)
+ real(r8), allocatable :: srnd (:) !reflected direct beam nir solar radiation (W/m2)
+ real(r8), allocatable :: srni (:) !reflected diffuse beam nir solar radiation (W/m2)
+ real(r8), allocatable :: solvdln(:) !incident direct beam vis solar radiation at local noon (W/m2)
+ real(r8), allocatable :: solviln(:) !incident diffuse beam vis solar radiation at local noon (W/m2)
+ real(r8), allocatable :: solndln(:) !incident direct beam nir solar radiation at local noon (W/m2)
+ real(r8), allocatable :: solniln(:) !incident diffuse beam nir solar radiation at local noon (W/m2)
+ real(r8), allocatable :: srvdln (:) !reflected direct beam vis solar radiation at local noon (W/m2)
+ real(r8), allocatable :: srviln (:) !reflected diffuse beam vis solar radiation at local noon (W/m2)
+ real(r8), allocatable :: srndln (:) !reflected direct beam nir solar radiation at local noon (W/m2)
+ real(r8), allocatable :: srniln (:) !reflected diffuse beam nir solar radiation at local noon (W/m2)
+#ifdef HYPERSPECTRAL
+ real(r8), allocatable :: sol_dir_ln_hires(:,:) !incident direct beam vis solar radiation at local noon (W/m2)
+ real(r8), allocatable :: sol_dif_ln_hires(:,:) !incident diffuse beam vis solar radiation at local noon (W/m2)
+ real(r8), allocatable :: sr_dir_ln_hires (:,:) !reflected direct beam nir solar radiation at local noon (W/m2)
+ real(r8), allocatable :: sr_dif_ln_hires (:,:) !reflected diffuse beam nir solar radiation at local noon (W/m2)
+#endif
+ real(r8), allocatable :: olrg (:) !outgoing long-wave radiation from ground+canopy [W/m2]
+ real(r8), allocatable :: rnet (:) !net radiation by surface [W/m2]
+ real(r8), allocatable :: xerr (:) !the error of water balance [mm/s]
+ real(r8), allocatable :: zerr (:) !the error of energy balance [W/m2]
+ real(r8), allocatable :: frcsat (:) !fraction of saturation area [-]
+ real(r8), allocatable :: rsur (:) !surface runoff (mm h2o/s)
+ real(r8), allocatable :: rsur_se(:) !saturation excess surface runoff (mm h2o/s)
+ real(r8), allocatable :: rsur_ie(:) !infiltration excess surface runoff (mm h2o/s)
+ real(r8), allocatable :: rsub (:) !subsurface runoff (mm h2o/s)
+ real(r8), allocatable :: rnof (:) !total runoff (mm h2o/s)
+ real(r8), allocatable :: qintr (:) !interception (mm h2o/s)
+ real(r8), allocatable :: qinfl (:) !infiltration (mm h2o/s)
+ real(r8), allocatable :: qdrip (:) !throughfall (mm h2o/s)
+ real(r8), allocatable :: assim (:) !canopy assimilation rate (mol m-2 s-1)
+ real(r8), allocatable :: respc (:) !canopy respiration (mol m-2 s-1)
+
+ real(r8), allocatable :: qcharge(:) !groundwater recharge [mm/s]
+
+ real(r8), allocatable :: qlayer (:,:) !water flux at between soil layer [mm h2o/s]
+ real(r8), allocatable :: lake_deficit (:) !lake deficit due to evaporation (mm h2o/s)
+
+ real(r8), allocatable :: oroflag(:) !/ocean(0)/seaice(2) flag
+
+ integer, parameter :: nsensor = 1
+ real(r8), allocatable :: sensors(:,:)
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_Fluxes
+ PUBLIC :: deallocate_1D_Fluxes
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_Fluxes
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ ! -------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ allocate ( taux (numpatch) ) ; taux (:) = spval ! wind stress: E-W [kg/m/s2]
+ allocate ( tauy (numpatch) ) ; tauy (:) = spval ! wind stress: N-S [kg/m/s2]
+ allocate ( fsena (numpatch) ) ; fsena (:) = spval ! sensible heat from canopy height to atmosphere [W/m2]
+ allocate ( lfevpa (numpatch) ) ; lfevpa (:) = spval ! latent heat flux from canopy height to atmosphere [W/m2]
+ allocate ( fevpa (numpatch) ) ; fevpa (:) = spval ! evapotranspiration from canopy to atmosphere [mm/s]
+ allocate ( fsenl (numpatch) ) ; fsenl (:) = spval ! sensible heat from leaves [W/m2]
+ allocate ( fevpl (numpatch) ) ; fevpl (:) = spval ! evaporation+transpiration from leaves [mm/s]
+ allocate ( etr (numpatch) ) ; etr (:) = spval ! transpiration rate [mm/s]
+ allocate ( fseng (numpatch) ) ; fseng (:) = spval ! sensible heat flux from ground [W/m2]
+ allocate ( fevpg (numpatch) ) ; fevpg (:) = spval ! evaporation heat flux from ground [mm/s]
+ allocate ( fgrnd (numpatch) ) ; fgrnd (:) = spval ! ground heat flux [W/m2]
+ allocate ( sabvsun(numpatch) ) ; sabvsun(:) = spval ! solar absorbed by sunlit vegetation [W/m2]
+ allocate ( sabvsha(numpatch) ) ; sabvsha(:) = spval ! solar absorbed by shaded vegetation [W/m2]
+ allocate ( sabg (numpatch) ) ; sabg (:) = spval ! solar absorbed by ground [W/m2]
+ allocate ( sr (numpatch) ) ; sr (:) = spval ! incident direct beam vis solar radiation (W/m2)
+ allocate ( solvd (numpatch) ) ; solvd (:) = spval ! incident direct beam vis solar radiation (W/m2)
+ allocate ( solvi (numpatch) ) ; solvi (:) = spval ! incident diffuse beam vis solar radiation (W/m2)
+ allocate ( solnd (numpatch) ) ; solnd (:) = spval ! incident direct beam nir solar radiation (W/m2)
+ allocate ( solni (numpatch) ) ; solni (:) = spval ! incident diffuse beam nir solar radiation (W/m2)
+ allocate ( srvd (numpatch) ) ; srvd (:) = spval ! reflected direct beam vis solar radiation (W/m2)
+ allocate ( srvi (numpatch) ) ; srvi (:) = spval ! reflected diffuse beam vis solar radiation (W/m2)
+ allocate ( srnd (numpatch) ) ; srnd (:) = spval ! reflected direct beam nir solar radiation (W/m2)
+ allocate ( srni (numpatch) ) ; srni (:) = spval ! reflected diffuse beam nir solar radiation (W/m2)
+ allocate ( solvdln(numpatch) ) ; solvdln(:) = spval ! incident direct beam vis solar radiation at local noon(W/m2)
+ allocate ( solviln(numpatch) ) ; solviln(:) = spval ! incident diffuse beam vis solar radiation at local noon(W/m2)
+ allocate ( solndln(numpatch) ) ; solndln(:) = spval ! incident direct beam nir solar radiation at local noon(W/m2)
+ allocate ( solniln(numpatch) ) ; solniln(:) = spval ! incident diffuse beam nir solar radiation at local noon(W/m2)
+ allocate ( srvdln (numpatch) ) ; srvdln (:) = spval ! reflected direct beam vis solar radiation at local noon(W/m2)
+ allocate ( srviln (numpatch) ) ; srviln (:) = spval ! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ allocate ( srndln (numpatch) ) ; srndln (:) = spval ! reflected direct beam nir solar radiation at local noon(W/m2)
+ allocate ( srniln (numpatch) ) ; srniln (:) = spval ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+#ifdef HYPERSPECTRAL
+ allocate ( sol_dir_ln_hires(211,numpatch) ) ; sol_dir_ln_hires(:,:) = spval ! incident direct beam vis solar radiation at local noon(W/m2)
+ allocate ( sol_dif_ln_hires(211,numpatch) ) ; sol_dif_ln_hires(:,:) = spval ! incident diffuse beam vis solar radiation at local noon(W/m2)
+ allocate ( sr_dir_ln_hires (211,numpatch) ) ; sr_dir_ln_hires (:,:) = spval ! reflected direct beam nir solar radiation at local noon(W/m2)
+ allocate ( sr_dif_ln_hires (211,numpatch) ) ; sr_dif_ln_hires (:,:) = spval ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+#endif
+ allocate ( olrg (numpatch) ) ; olrg (:) = spval ! outgoing long-wave radiation from ground+canopy [W/m2]
+ allocate ( rnet (numpatch) ) ; rnet (:) = spval ! net radiation by surface [W/m2]
+ allocate ( xerr (numpatch) ) ; xerr (:) = spval ! the error of water balance [mm/s]
+ allocate ( zerr (numpatch) ) ; zerr (:) = spval ! the error of energy balance [W/m2]
+
+ allocate ( frcsat (numpatch) ) ; frcsat (:) = spval ! fraction of saturation area [-]
+ allocate ( rsur (numpatch) ) ; rsur (:) = spval ! surface runoff (mm h2o/s)
+ allocate ( rsur_se(numpatch) ) ; rsur_se(:) = spval ! saturation excess surface runoff (mm h2o/s)
+ allocate ( rsur_ie(numpatch) ) ; rsur_ie(:) = spval ! infiltration excess surface runoff (mm h2o/s)
+ allocate ( rsub (numpatch) ) ; rsub (:) = spval ! subsurface runoff (mm h2o/s)
+ allocate ( rnof (numpatch) ) ; rnof (:) = spval ! total runoff (mm h2o/s)
+ allocate ( qintr (numpatch) ) ; qintr (:) = spval ! interception (mm h2o/s)
+ allocate ( qinfl (numpatch) ) ; qinfl (:) = spval ! infiltration (mm h2o/s)
+ allocate ( qdrip (numpatch) ) ; qdrip (:) = spval ! throughfall (mm h2o/s)
+ allocate ( assim (numpatch) ) ; assim (:) = spval ! canopy assimilation rate (mol m-2 s-1)
+ allocate ( respc (numpatch) ) ; respc (:) = spval ! canopy respiration (mol m-2 s-1)
+
+ allocate ( qcharge(numpatch) ) ; qcharge(:) = spval ! groundwater recharge [mm/s]
+
+ allocate ( qlayer (0:nl_soil,numpatch) ); qlayer(:,:) = spval ! water flux between soil layer [mm h2o/s]
+ allocate ( lake_deficit (numpatch) ); lake_deficit(:) = spval ! lake deficit due to evaporation (mm h2o/s)
+
+ allocate ( oroflag(numpatch) ) ; oroflag(:) = 1.0 ! /ocean(0)/seaice(2) flag
+
+ allocate ( sensors(nsensor,numpatch) ); sensors(:,:) = spval !
+
+ ENDIF
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL allocate_1D_PFTFluxes
+#endif
+
+#ifdef BGC
+ CALL allocate_1D_BGCFluxes
+#endif
+
+#ifdef CatchLateralFlow
+ CALL allocate_1D_CatchFluxes
+#endif
+
+#ifdef URBAN_MODEL
+ CALL allocate_1D_UrbanFluxes
+#endif
+
+#ifdef DataAssimilation
+ CALL allocate_1D_DAFluxes
+#endif
+
+ END SUBROUTINE allocate_1D_Fluxes
+
+ SUBROUTINE deallocate_1D_Fluxes ()
+ ! --------------------------------------------------------------------
+ ! deallocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ deallocate ( taux ) ! wind stress: E-W [kg/m/s2]
+ deallocate ( tauy ) ! wind stress: N-S [kg/m/s2]
+ deallocate ( fsena ) ! sensible heat from canopy height to atmosphere [W/m2]
+ deallocate ( lfevpa ) ! latent heat flux from canopy height to atmosphere [W/m2]
+ deallocate ( fevpa ) ! evapotranspiration from canopy to atmosphere [mm/s]
+ deallocate ( fsenl ) ! sensible heat from leaves [W/m2]
+ deallocate ( fevpl ) ! evaporation+transpiration from leaves [mm/s]
+ deallocate ( etr ) ! transpiration rate [mm/s]
+ deallocate ( fseng ) ! sensible heat flux from ground [W/m2]
+ deallocate ( fevpg ) ! evaporation heat flux from ground [mm/s]
+ deallocate ( fgrnd ) ! ground heat flux [W/m2]
+ deallocate ( sabvsun ) ! solar absorbed by sunlit vegetation [W/m2]
+ deallocate ( sabvsha ) ! solar absorbed by shaded vegetation [W/m2]
+ deallocate ( sabg ) ! solar absorbed by ground [W/m2]
+ deallocate ( sr ) ! incident direct beam vis solar radiation (W/m2)
+ deallocate ( solvd ) ! incident direct beam vis solar radiation (W/m2)
+ deallocate ( solvi ) ! incident diffuse beam vis solar radiation (W/m2)
+ deallocate ( solnd ) ! incident direct beam nir solar radiation (W/m2)
+ deallocate ( solni ) ! incident diffuse beam nir solar radiation (W/m2)
+ deallocate ( srvd ) ! reflected direct beam vis solar radiation (W/m2)
+ deallocate ( srvi ) ! reflected diffuse beam vis solar radiation (W/m2)
+ deallocate ( srnd ) ! reflected direct beam nir solar radiation (W/m2)
+ deallocate ( srni ) ! reflected diffuse beam nir solar radiation (W/m2)
+ deallocate ( solvdln ) ! incident direct beam vis solar radiation at local noon(W/m2)
+ deallocate ( solviln ) ! incident diffuse beam vis solar radiation at local noon(W/m2)
+ deallocate ( solndln ) ! incident direct beam nir solar radiation at local noon(W/m2)
+ deallocate ( solniln ) ! incident diffuse beam nir solar radiation at local noon(W/m2)
+ deallocate ( srvdln ) ! reflected direct beam vis solar radiation at local noon(W/m2)
+ deallocate ( srviln ) ! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ deallocate ( srndln ) ! reflected direct beam nir solar radiation at local noon(W/m2)
+ deallocate ( srniln ) ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+#ifdef HYPERSPECTRAL
+ deallocate ( sol_dir_ln_hires ) ! incident direct beam vis solar radiation at local noon(W/m2)
+ deallocate ( sol_dif_ln_hires ) ! incident diffuse beam vis solar radiation at local noon(W/m2)
+ deallocate ( sr_dir_ln_hires ) ! reflected direct beam nir solar radiation at local noon(W/m2)
+ deallocate ( sr_dif_ln_hires ) ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+#endif
+ deallocate ( olrg ) ! outgoing long-wave radiation from ground+canopy [W/m2]
+ deallocate ( rnet ) ! net radiation by surface [W/m2]
+ deallocate ( xerr ) ! the error of water balance [mm/s]
+ deallocate ( zerr ) ! the error of energy balance [W/m2]
+ deallocate ( frcsat ) ! fraction of saturation area [-]
+ deallocate ( rsur ) ! surface runoff (mm h2o/s)
+ deallocate ( rsur_se ) ! saturation excess surface runoff (mm h2o/s)
+ deallocate ( rsur_ie ) ! infiltration excess surface runoff (mm h2o/s)
+ deallocate ( rsub ) ! subsurface runoff (mm h2o/s)
+ deallocate ( rnof ) ! total runoff (mm h2o/s)
+ deallocate ( qintr ) ! interception (mm h2o/s)
+ deallocate ( qinfl ) ! infiltration (mm h2o/s)
+ deallocate ( qdrip ) ! throughfall (mm h2o/s)
+ deallocate ( assim ) ! canopy assimilation rate (mol m-2 s-1)
+ deallocate ( respc ) ! canopy respiration (mol m-2 s-1)
+
+ deallocate ( qcharge ) ! groundwater recharge [mm/s]
+ deallocate ( qlayer ) ! water flux between soil layer [mm h2o/s]
+ deallocate ( lake_deficit ) ! lake deficit due to evaporation (mm h2o/s)
+
+ deallocate ( oroflag ) !
+
+ deallocate ( sensors ) !
+
+ ENDIF
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL deallocate_1D_PFTFluxes
+#endif
+
+#ifdef BGC
+ CALL deallocate_1D_BGCFluxes
+#endif
+
+#ifdef CatchLateralFlow
+ CALL deallocate_1D_CatchFluxes
+#endif
+
+#ifdef URBAN_MODEL
+ CALL deallocate_1D_UrbanFluxes
+#endif
+
+#ifdef DataAssimilation
+ CALL deallocate_1D_DAFluxes
+#endif
+
+ END SUBROUTINE deallocate_1D_Fluxes
+
+END MODULE MOD_Vars_1DFluxes
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DForcing.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DForcing.F90
new file mode 100644
index 0000000000..d071335bc7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DForcing.F90
@@ -0,0 +1,167 @@
+#include
+
+MODULE MOD_Vars_1DForcing
+!-----------------------------------------------------------------------
+! Meteorological Forcing
+!
+! Created by Yongjiu Dai, 03/2014
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ IMPLICIT NONE
+ SAVE
+
+!-----------------------------------------------------------------------
+ real(r8), allocatable :: forc_pco2m (:) ! CO2 concentration in atmos. (pascals)
+ real(r8), allocatable :: forc_po2m (:) ! O2 concentration in atmos. (pascals)
+ real(r8), allocatable :: forc_us (:) ! wind in eastward direction [m/s]
+ real(r8), allocatable :: forc_vs (:) ! wind in northward direction [m/s]
+ real(r8), allocatable :: forc_t (:) ! temperature at reference height [kelvin]
+ real(r8), allocatable :: forc_q (:) ! specific humidity at reference height [kg/kg]
+ real(r8), allocatable :: forc_prc (:) ! convective precipitation [mm/s]
+ real(r8), allocatable :: forc_prl (:) ! large scale precipitation [mm/s]
+ real(r8), allocatable :: forc_rain (:) ! rain [mm/s]
+ real(r8), allocatable :: forc_snow (:) ! snow [mm/s]
+ real(r8), allocatable :: forc_psrf (:) ! atmospheric pressure at the surface [pa]
+ real(r8), allocatable :: forc_pbot (:) ! atm bottom level pressure (or reference height) (pa)
+ real(r8), allocatable :: forc_sols (:) ! atm vis direct beam solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_soll (:) ! atm nir direct beam solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_solsd (:) ! atm vis diffuse solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_solld (:) ! atm nir diffuse solar rad onto srf [W/m2]
+ real(r8), allocatable :: forc_frl (:) ! atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), allocatable :: forc_swrad (:) ! atmospheric shortwave radiation [W/m2]
+ real(r8), allocatable :: forc_hgt_u (:) ! observational height of wind [m]
+ real(r8), allocatable :: forc_hgt_t (:) ! observational height of temperature [m]
+ real(r8), allocatable :: forc_hgt_q (:) ! observational height of humidity [m]
+ real(r8), allocatable :: forc_rhoair(:) ! air density [kg/m3]
+ real(r8), allocatable :: forc_ozone (:) ! air density [kg/m3]
+#ifdef HYPERSPECTRAL
+ real(r8), allocatable :: forc_solarin(:) ! incident solar radiation [W/m2]
+#endif
+
+ real(r8), allocatable :: forc_topo (:) ! topography [m]
+
+ real(r8), allocatable :: forc_hpbl (:) ! atmospheric boundary layer height [m]
+ real(r8), allocatable :: forc_aerdep(:,:) ! atmospheric aerosol deposition data [kg/m/s]
+
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_Forcing
+ PUBLIC :: deallocate_1D_Forcing
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+CONTAINS
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_Forcing
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ ! -------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_Mesh
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ allocate (forc_pco2m (numpatch) ) ! CO2 concentration in atmos. (pascals)
+ allocate (forc_po2m (numpatch) ) ! O2 concentration in atmos. (pascals)
+ allocate (forc_us (numpatch) ) ! wind in eastward direction [m/s]
+ allocate (forc_vs (numpatch) ) ! wind in northward direction [m/s]
+ allocate (forc_t (numpatch) ) ! temperature at reference height [kelvin]
+ allocate (forc_q (numpatch) ) ! specific humidity at reference height [kg/kg]
+ allocate (forc_prc (numpatch) ) ! convective precipitation [mm/s]
+ allocate (forc_prl (numpatch) ) ! large scale precipitation [mm/s]
+ allocate (forc_rain (numpatch) ) ! rain [mm/s]
+ allocate (forc_snow (numpatch) ) ! snow [mm/s]
+ allocate (forc_psrf (numpatch) ) ! atmospheric pressure at the surface [pa]
+ allocate (forc_pbot (numpatch) ) ! atm bottom level pressure (or reference height) (pa)
+#ifdef HYPERSPECTRAL
+ allocate (forc_solarin(numpatch) ) ! solar rad onto srf [W/m2]
+#endif
+ allocate (forc_sols (numpatch) ) ! atm vis direct beam solar rad onto srf [W/m2]
+ allocate (forc_soll (numpatch) ) ! atm nir direct beam solar rad onto srf [W/m2]
+ allocate (forc_solsd (numpatch) ) ! atm vis diffuse solar rad onto srf [W/m2]
+ allocate (forc_solld (numpatch) ) ! atm nir diffuse solar rad onto srf [W/m2]
+ allocate (forc_frl (numpatch) ) ! atmospheric infrared (longwave) radiation [W/m2]
+ allocate (forc_swrad (numpatch) ) ! atmospheric shortwave radiation [W/m2]
+ allocate (forc_hgt_u (numpatch) ) ! observational height of wind [m]
+ allocate (forc_hgt_t (numpatch) ) ! observational height of temperature [m]
+ allocate (forc_hgt_q (numpatch) ) ! observational height of humidity [m]
+ allocate (forc_rhoair (numpatch) ) ! air density [kg/m3]
+ allocate (forc_ozone (numpatch) ) ! air density [kg/m3]
+
+ allocate (forc_hpbl (numpatch) ) ! atmospheric boundary layer height [m]
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ allocate (forc_topo (numpatch))
+ ENDIF
+
+ allocate (forc_aerdep(14,numpatch) ) ! atmospheric aerosol deposition data [kg/m/s]
+
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE allocate_1D_Forcing
+
+
+ SUBROUTINE deallocate_1D_Forcing ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Mesh
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ deallocate ( forc_pco2m ) ! CO2 concentration in atmos. (pascals)
+ deallocate ( forc_po2m ) ! O2 concentration in atmos. (pascals)
+ deallocate ( forc_us ) ! wind in eastward direction [m/s]
+ deallocate ( forc_vs ) ! wind in northward direction [m/s]
+ deallocate ( forc_t ) ! temperature at reference height [kelvin]
+ deallocate ( forc_q ) ! specific humidity at reference height [kg/kg]
+ deallocate ( forc_prc ) ! convective precipitation [mm/s]
+ deallocate ( forc_prl ) ! large scale precipitation [mm/s]
+ deallocate ( forc_rain ) ! rain [mm/s]
+ deallocate ( forc_snow ) ! snow [mm/s]
+ deallocate ( forc_psrf ) ! atmospheric pressure at the surface [pa]
+ deallocate ( forc_pbot ) ! atm bottom level pressure (or reference height) (pa)
+#ifdef HYPERSPECTRAL
+ deallocate ( forc_solarin) ! solar rad onto srf [W/m2]
+#endif
+ deallocate ( forc_sols ) ! atm vis direct beam solar rad onto srf [W/m2]
+ deallocate ( forc_soll ) ! atm nir direct beam solar rad onto srf [W/m2]
+ deallocate ( forc_solsd ) ! atm vis diffuse solar rad onto srf [W/m2]
+ deallocate ( forc_solld ) ! atm nir diffuse solar rad onto srf [W/m2]
+ deallocate ( forc_frl ) ! atmospheric infrared (longwave) radiation [W/m2]
+ deallocate ( forc_swrad ) ! atmospheric shortwave radiation [W/m2]
+ deallocate ( forc_hgt_u ) ! observational height of wind [m]
+ deallocate ( forc_hgt_t ) ! observational height of temperature [m]
+ deallocate ( forc_hgt_q ) ! observational height of humidity [m]
+ deallocate ( forc_rhoair ) ! air density [kg/m3]
+ deallocate ( forc_ozone ) ! Ozone partial pressure [mol/mol]
+
+ deallocate ( forc_hpbl ) ! atmospheric boundary layer height [m]
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ deallocate (forc_topo)
+ ENDIF
+
+ deallocate ( forc_aerdep ) ! atmospheric aerosol deposition data [kg/m/s]
+
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE deallocate_1D_Forcing
+
+END MODULE MOD_Vars_1DForcing
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DPFTFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DPFTFluxes.F90
new file mode 100644
index 0000000000..0809c19479
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_1DPFTFluxes.F90
@@ -0,0 +1,173 @@
+#include
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+MODULE MOD_Vars_1DPFTFluxes
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Define PFT flux variables
+!
+! Created by Hua Yuan, 08/2019
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+#ifdef BGC
+ USE MOD_BGC_Vars_1DPFTFluxes
+#endif
+ IMPLICIT NONE
+ SAVE
+
+!-----------------------------------------------------------------------
+! Fluxes
+!-----------------------------------------------------------------------
+ real(r8), allocatable :: taux_p (:) !wind stress: E-W [kg/m/s2]
+ real(r8), allocatable :: tauy_p (:) !wind stress: N-S [kg/m/s2]
+ real(r8), allocatable :: fsenl_p (:) !sensible heat from leaves [W/m2]
+ real(r8), allocatable :: fevpl_p (:) !evaporation+transpiration from leaves [mm/s]
+ real(r8), allocatable :: etr_p (:) !transpiration rate [mm/s]
+ real(r8), allocatable :: fseng_p (:) !sensible heat flux from ground [W/m2]
+ real(r8), allocatable :: fevpg_p (:) !evaporation heat flux from ground [mm/s]
+ real(r8), allocatable :: parsun_p (:) !solar absorbed by sunlit vegetation [W/m2]
+ real(r8), allocatable :: parsha_p (:) !solar absorbed by shaded vegetation [W/m2]
+ real(r8), allocatable :: sabvsun_p(:) !solar absorbed by sunlit vegetation [W/m2]
+ real(r8), allocatable :: sabvsha_p(:) !solar absorbed by shaded vegetation [W/m2]
+ real(r8), allocatable :: qintr_p (:) !interception (mm h2o/s)
+ real(r8), allocatable :: qintr_rain_p(:) !rainfall interception (mm h2o/s)
+ real(r8), allocatable :: qintr_snow_p(:) !snowfall interception (mm h2o/s)
+ real(r8), allocatable :: assim_p (:) !canopy assimilation rate (mol m-2 s-1)
+ real(r8), allocatable :: respc_p (:) !canopy respiration (mol m-2 s-1)
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_PFTFluxes
+ PUBLIC :: deallocate_1D_PFTFluxes
+ PUBLIC :: set_1D_PFTFluxes
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_PFTFluxes
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM PFT 1d [numpft] variables
+ ! -------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+
+ allocate (taux_p (numpft)) ; taux_p (:) = spval !wind stress: E-W [kg/m/s2]
+ allocate (tauy_p (numpft)) ; tauy_p (:) = spval !wind stress: N-S [kg/m/s2]
+ allocate (fsenl_p (numpft)) ; fsenl_p (:) = spval !sensible heat from leaves [W/m2]
+ allocate (fevpl_p (numpft)) ; fevpl_p (:) = spval !evaporation+transpiration from leaves [mm/s]
+ allocate (etr_p (numpft)) ; etr_p (:) = spval !transpiration rate [mm/s]
+ allocate (fseng_p (numpft)) ; fseng_p (:) = spval !sensible heat flux from ground [W/m2]
+ allocate (fevpg_p (numpft)) ; fevpg_p (:) = spval !evaporation heat flux from ground [mm/s]
+ allocate (parsun_p (numpft)) ; parsun_p (:) = spval !solar absorbed by sunlit vegetation [W/m2]
+ allocate (parsha_p (numpft)) ; parsha_p (:) = spval !solar absorbed by shaded vegetation [W/m2]
+ allocate (sabvsun_p (numpft)) ; sabvsun_p (:) = spval !solar absorbed by sunlit vegetation [W/m2]
+ allocate (sabvsha_p (numpft)) ; sabvsha_p (:) = spval !solar absorbed by shaded vegetation [W/m2]
+ allocate (qintr_p (numpft)) ; qintr_p (:) = spval !interception (mm h2o/s)
+ allocate (qintr_rain_p (numpft)) ; qintr_rain_p (:) = spval !rainfall interception (mm h2o/s)
+ allocate (qintr_snow_p (numpft)) ; qintr_snow_p (:) = spval !snowfall interception (mm h2o/s)
+ allocate (assim_p (numpft)) ; assim_p (:) = spval !canopy assimilation rate (mol m-2 s-1)
+ allocate (respc_p (numpft)) ; respc_p (:) = spval !canopy respiration (mol m-2 s-1)
+
+ ENDIF
+ ENDIF
+
+#ifdef BGC
+ CALL allocate_1D_BGCPFTFluxes
+#endif
+
+ END SUBROUTINE allocate_1D_PFTFluxes
+
+ SUBROUTINE deallocate_1D_PFTFluxes
+ ! -------------------------------------------------------------------
+ ! deallocates memory for CoLM PFT 1d [numpft] variables
+ ! -------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+
+ deallocate (taux_p )
+ deallocate (tauy_p )
+ deallocate (fsenl_p )
+ deallocate (fevpl_p )
+ deallocate (etr_p )
+ deallocate (fseng_p )
+ deallocate (fevpg_p )
+ deallocate (parsun_p )
+ deallocate (parsha_p )
+ deallocate (sabvsun_p )
+ deallocate (sabvsha_p )
+ deallocate (qintr_p )
+ deallocate (qintr_rain_p )
+ deallocate (qintr_snow_p )
+ deallocate (assim_p )
+ deallocate (respc_p )
+
+ ENDIF
+ ENDIF
+
+#ifdef BGC
+ CALL deallocate_1D_BGCPFTFluxes
+#endif
+
+ END SUBROUTINE deallocate_1D_PFTFluxes
+
+ SUBROUTINE set_1D_PFTFluxes(Values, Nan)
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM PFT 1d [numpft] variables
+ ! -------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+ IMPLICIT NONE
+
+ real(r8),intent(in) :: Values
+ real(r8),intent(in) :: Nan
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+
+ taux_p (:) = Values !wind stress: E-W [kg/m/s2]
+ tauy_p (:) = Values !wind stress: N-S [kg/m/s2]
+ fsenl_p (:) = Values !sensible heat from leaves [W/m2]
+ fevpl_p (:) = Values !evaporation+transpiration from leaves [mm/s]
+ etr_p (:) = Values !transpiration rate [mm/s]
+ fseng_p (:) = Values !sensible heat flux from ground [W/m2]
+ fevpg_p (:) = Values !evaporation heat flux from ground [mm/s]
+ parsun_p (:) = Values !solar absorbed by sunlit vegetation [W/m2]
+ parsha_p (:) = Values !solar absorbed by shaded vegetation [W/m2]
+ sabvsun_p (:) = Values !solar absorbed by sunlit vegetation [W/m2]
+ sabvsha_p (:) = Values !solar absorbed by shaded vegetation [W/m2]
+ qintr_p (:) = Values !interception (mm h2o/s)
+ qintr_rain_p(:) = Values !rainfall interception (mm h2o/s)
+ qintr_snow_p(:) = Values !snowfall interception (mm h2o/s)
+ assim_p (:) = Values !canopy assimilation rate (mol m-2 s-1)
+ respc_p (:) = Values !canopy respiration (mol m-2 s-1)
+
+ ENDIF
+ ENDIF
+
+#ifdef BGC
+ CALL set_1D_BGCPFTFluxes (Values, Nan)
+#endif
+
+ END SUBROUTINE set_1D_PFTFluxes
+
+END MODULE MOD_Vars_1DPFTFluxes
+
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_2DForcing.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_2DForcing.F90
new file mode 100644
index 0000000000..e0c961ef9e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_2DForcing.F90
@@ -0,0 +1,81 @@
+#include
+
+MODULE MOD_Vars_2DForcing
+!-----------------------------------------------------------------------
+! Meteorogical Forcing
+!
+! Created by Yongjiu Dai, 03/2014
+!-----------------------------------------------------------------------
+
+ USE MOD_DataType
+ IMPLICIT NONE
+ SAVE
+
+!-----------------------------------------------------------------------
+ type(block_data_real8_2d) :: forc_xy_pco2m ! CO2 concentration in atmos. (pascals)
+ type(block_data_real8_2d) :: forc_xy_po2m ! O2 concentration in atmos. (pascals)
+ type(block_data_real8_2d) :: forc_xy_us ! wind in eastward direction [m/s]
+ type(block_data_real8_2d) :: forc_xy_vs ! wind in northward direction [m/s]
+ type(block_data_real8_2d) :: forc_xy_t ! temperature at reference height [kelvin]
+ type(block_data_real8_2d) :: forc_xy_q ! specific humidity at reference height [kg/kg]
+ type(block_data_real8_2d) :: forc_xy_prc ! convective precipitation [mm/s]
+ type(block_data_real8_2d) :: forc_xy_prl ! large scale precipitation [mm/s]
+ type(block_data_real8_2d) :: forc_xy_psrf ! atmospheric pressure at the surface [pa]
+ type(block_data_real8_2d) :: forc_xy_pbot ! atm bottom level pressure (or reference height) (pa)
+ type(block_data_real8_2d) :: forc_xy_sols ! atm vis direct beam solar rad onto srf [W/m2]
+ type(block_data_real8_2d) :: forc_xy_soll ! atm nir direct beam solar rad onto srf [W/m2]
+ type(block_data_real8_2d) :: forc_xy_solsd ! atm vis diffuse solar rad onto srf [W/m2]
+ type(block_data_real8_2d) :: forc_xy_solld ! atm nir diffuse solar rad onto srf [W/m2]
+ type(block_data_real8_2d) :: forc_xy_frl ! atmospheric infrared (longwave) radiation [W/m2]
+ type(block_data_real8_2d) :: forc_xy_hgt_u ! observational height of wind [m]
+ type(block_data_real8_2d) :: forc_xy_hgt_t ! observational height of temperature [m]
+ type(block_data_real8_2d) :: forc_xy_hgt_q ! observational height of humidity [m]
+ type(block_data_real8_2d) :: forc_xy_rhoair ! air density [kg/m3]
+ type(block_data_real8_2d) :: forc_xy_hpbl ! atmospheric boundary layer height [m]
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_2D_Forcing
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_2D_Forcing (grid)
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM 2d [lon_points,lat_points] variables
+ ! -------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_Grid
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+
+ IF (p_is_active) THEN
+
+ CALL allocate_block_data (grid, forc_xy_pco2m ) ! CO2 concentration in atmos. (pascals)
+ CALL allocate_block_data (grid, forc_xy_po2m ) ! O2 concentration in atmos. (pascals)
+ CALL allocate_block_data (grid, forc_xy_us ) ! wind in eastward direction [m/s]
+ CALL allocate_block_data (grid, forc_xy_vs ) ! wind in northward direction [m/s]
+ CALL allocate_block_data (grid, forc_xy_t ) ! temperature at reference height [kelvin]
+ CALL allocate_block_data (grid, forc_xy_q ) ! specific humidity at reference height [kg/kg]
+ CALL allocate_block_data (grid, forc_xy_prc ) ! convective precipitation [mm/s]
+ CALL allocate_block_data (grid, forc_xy_prl ) ! large scale precipitation [mm/s]
+ CALL allocate_block_data (grid, forc_xy_psrf ) ! atmospheric pressure at the surface [pa]
+ CALL allocate_block_data (grid, forc_xy_pbot ) ! atm bottom level pressure (or reference height) (pa)
+ CALL allocate_block_data (grid, forc_xy_sols ) ! atm vis direct beam solar rad onto srf [W/m2]
+ CALL allocate_block_data (grid, forc_xy_soll ) ! atm nir direct beam solar rad onto srf [W/m2]
+ CALL allocate_block_data (grid, forc_xy_solsd ) ! atm vis diffuse solar rad onto srf [W/m2]
+ CALL allocate_block_data (grid, forc_xy_solld ) ! atm nir diffuse solar rad onto srf [W/m2]
+ CALL allocate_block_data (grid, forc_xy_frl ) ! atmospheric infrared (longwave) radiation [W/m2]
+ CALL allocate_block_data (grid, forc_xy_hgt_u ) ! observational height of wind [m]
+ CALL allocate_block_data (grid, forc_xy_hgt_t ) ! observational height of temperature [m]
+ CALL allocate_block_data (grid, forc_xy_hgt_q ) ! observational height of humidity [m]
+ CALL allocate_block_data (grid, forc_xy_rhoair) ! air density [kg/m3]
+ CALL allocate_block_data (grid, forc_xy_hpbl ) ! atmospheric boundary layer height [m]
+ ENDIF
+
+ END SUBROUTINE allocate_2D_Forcing
+
+END MODULE MOD_Vars_2DForcing
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_Global.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_Global.F90
new file mode 100644
index 0000000000..473bebe5c8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_Global.F90
@@ -0,0 +1,168 @@
+#include
+
+MODULE MOD_Vars_Global
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Define some global variables
+!
+! !REVISIONS:
+! Hua Yuan, 08/2019: initial version partly adapted from CoLM2014
+! TODO ...
+!
+!-----------------------------------------------------------------------
+! !USES:
+ USE MOD_Precision
+ USE MOD_Namelist
+ IMPLICIT NONE
+ SAVE
+
+#ifdef LULC_USGS
+ ! GLCC USGS number of land cover category
+ integer, parameter :: N_land_classification = 24
+ ! GLCC USGS land cover named index (could be added IF needed)
+ integer, parameter :: URBAN = 1
+ integer, parameter :: WATERBODY = 16
+ integer, parameter :: WETLAND = 17
+ integer, parameter :: CROPLAND = 7
+ integer, parameter :: GLACIERS = 24
+#else
+ ! MODIS IGBP number of land cover category
+ integer, parameter :: N_land_classification = 17
+ ! MODIS IGBP land cover named index (could be added IF needed)
+ integer, parameter :: WETLAND = 11
+ integer, parameter :: CROPLAND = 12
+ integer, parameter :: URBAN = 13
+ integer, parameter :: GLACIERS = 15
+ integer, parameter :: WATERBODY = 17
+#endif
+
+ ! number of plant functional types
+#ifndef CROP
+ integer, parameter :: N_PFT = 16
+ integer, parameter :: N_CFT = 0
+#else
+ integer, parameter :: N_PFT = 15
+ integer, parameter :: N_CFT = 64
+#endif
+
+ ! urban type number
+ integer :: N_URB
+
+ ! vertical layer number
+ integer, parameter :: maxsnl = -5
+ integer, parameter :: nl_soil = 10
+ integer, parameter :: nl_soil_full = 15
+
+ integer, parameter :: nl_lake = 10
+ integer, parameter :: nl_roof = 10
+ integer, parameter :: nl_wall = 10
+ integer, parameter :: nvegwcs = 4 ! number of vegetation water potential nodes
+ integer, parameter :: nwl = 211 ! number of hyperspectral wavelengths
+ ! used for downscaling
+ integer, parameter :: num_slope_type = 4
+ integer, parameter :: num_aspect_type = 9
+ integer, parameter :: num_zenith = 101
+ integer, parameter :: num_zenith_parameter = 3
+ integer, parameter :: num_azimuth = 16
+
+ ! bgc variables
+ integer, parameter :: ndecomp_pools = 7
+ integer, parameter :: ndecomp_transitions = 10
+ integer, parameter :: npcropmin = 17
+ real(r8),parameter :: zmin_bedrock = 0.4
+ integer, parameter :: nbedrock = 10
+ integer, parameter :: ndecomp_pools_vr = ndecomp_pools * nl_soil
+
+ ! crop index
+ integer, parameter :: noveg = 0
+ integer, parameter :: nbrdlf_evr_shrub = 9
+ integer, parameter :: nbrdlf_dcd_brl_shrub = 11
+ integer, parameter :: nc3crop = 15
+ integer, parameter :: nc3irrig = 16
+ integer, parameter :: ntmp_corn = 17 ! temperate_corn
+ integer, parameter :: nirrig_tmp_corn = 18 ! irrigated temperate corn
+ integer, parameter :: nswheat = 19 ! spring wheat
+ integer, parameter :: nirrig_swheat = 20 ! irrigated spring wheat
+ integer, parameter :: nwwheat = 21 ! winter wheat
+ integer, parameter :: nirrig_wwheat = 22 ! irrigated winter wheat
+ integer, parameter :: ntmp_soybean = 23 ! temperate soybean
+ integer, parameter :: nirrig_tmp_soybean = 24 ! irrigated temperate soybean
+ integer, parameter :: ncotton = 41 ! cotton
+ integer, parameter :: nirrig_cotton = 42 ! irrigated cotton
+ integer, parameter :: nrice = 61 ! rice
+ integer, parameter :: nirrig_rice = 62 ! irrigated rice
+ integer, parameter :: nsugarcane = 67 ! sugarcane
+ integer, parameter :: nirrig_sugarcane = 68 ! irrigated sugarcane
+ integer, parameter :: nmiscanthus = 71 ! miscanthus
+ integer, parameter :: nirrig_miscanthus = 72 ! irrigated miscanthus
+ integer, parameter :: nswitchgrass = 73 ! switchgrass
+ integer, parameter :: nirrig_switchgrass = 74 ! irrigated switchgrass
+ integer, parameter :: ntrp_corn = 75 ! tropical corn
+ integer, parameter :: nirrig_trp_corn = 76 ! irrigated tropical corn
+ integer, parameter :: ntrp_soybean = 77 ! tropical soybean
+ integer, parameter :: nirrig_trp_soybean = 78 ! irrigated tropical soybean
+
+ real(r8) :: z_soi (1:nl_soil) ! node depth [m]
+ real(r8) :: dz_soi(1:nl_soil) ! soil node thickness [m]
+ real(r8) :: zi_soi(1:nl_soil) ! interface level below a zsoi level [m]
+
+ real(r8), parameter :: spval = -1.e36_r8 ! missing value
+ integer , parameter :: spval_i4 = -9999 ! missing value
+ real(r8), parameter :: PI = 4*atan(1.) ! pi value
+ real(r8), parameter :: deg2rad = 1.745329251994330e-2_r8 ! degree to radius
+
+ integer , parameter :: irrig_start_time = 21600 ! local time of irrigation start
+ real(r8), parameter :: irrig_max_depth = 1._r8 ! max irrigation depth
+ real(r8), parameter :: irrig_threshold_fraction = 1._r8 ! irrigation thershold
+ real(r8), parameter :: irrig_supply_fraction = 1._r8 ! irrigation supply thershold
+ real(r8), parameter :: irrig_min_cphase = 1._r8 ! crop phenology when begin irrigation
+ real(r8), parameter :: irrig_max_cphase = 4._r8 ! crop phenology when end irrigation
+ integer , parameter :: irrig_time_per_day = 14400 ! irrigation last time
+ integer , parameter :: irrig_method_drip = 1 ! irrigation method
+ integer , parameter :: irrig_method_sprinkler = 2 ! irrigation method
+ integer , parameter :: irrig_method_flood = 3 ! irrigation method
+ integer , parameter :: irrig_method_paddy = 4 ! irrigation method
+ real(r8), parameter :: pondmxc = 100.0 ! ponding depth (mm)
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: Init_GlobalVars
+
+CONTAINS
+
+ SUBROUTINE Init_GlobalVars
+
+ IMPLICIT NONE
+
+ integer :: nsl
+
+ ! node depths of each soil layer
+ DO nsl = 1, nl_soil
+ z_soi(nsl) = 0.025*(exp(0.5*(nsl-0.5))-1.)
+ ENDDO
+
+ ! thickness between two soil layer interfaces
+ dz_soi(1) = 0.5*(z_soi(1)+z_soi(2)) !=zi_soi(1)
+ dz_soi(nl_soil) = z_soi(nl_soil)-z_soi(nl_soil-1)
+ DO nsl = 2, nl_soil-1
+ dz_soi(nsl) = 0.5*(z_soi(nsl+1)-z_soi(nsl-1))
+ ENDDO
+
+ ! interface depths of soil layers
+ zi_soi(1) = dz_soi(1)
+ DO nsl = 2, nl_soil
+ zi_soi(nsl) = zi_soi(nsl-1) + dz_soi(nsl)
+ ENDDO
+
+ ! set urban class number
+ IF (DEF_URBAN_type_scheme == 1) THEN
+ N_URB = 3
+ ELSE IF(DEF_URBAN_type_scheme == 2) THEN
+ N_URB = 10
+ ENDIF
+
+ !ndecomp_pools_vr = ndecomp_pools * nl_soil
+
+ END SUBROUTINE Init_GlobalVars
+
+END MODULE MOD_Vars_Global
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_TimeInvariants.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_TimeInvariants.F90
new file mode 100644
index 0000000000..d7d7224079
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_TimeInvariants.F90
@@ -0,0 +1,1143 @@
+#include
+
+!-----------------------------------------------------------------------
+! Created by Yongjiu Dai, 03/2014
+!-----------------------------------------------------------------------
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+MODULE MOD_Vars_PFTimeInvariants
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Define PFT time invariables
+!
+! Added by Hua Yuan, 08/2019
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+ SAVE
+
+ ! for LULC_IGBP_PFT and LULC_IGBP_PC
+ integer , allocatable :: pftclass (:) !PFT type
+ real(r8), allocatable :: pftfrac (:) !PFT fractional cover
+ real(r8), allocatable :: htop_p (:) !canopy top height [m]
+ real(r8), allocatable :: hbot_p (:) !canopy bottom height [m]
+#ifdef CROP
+ real(r8), allocatable :: cropfrac (:) !Crop fractional cover
+#endif
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_PFTimeInvariants
+ PUBLIC :: READ_PFTimeInvariants
+ PUBLIC :: WRITE_PFTimeInvariants
+ PUBLIC :: deallocate_PFTimeInvariants
+#ifdef RangeCheck
+ PUBLIC :: check_PFTimeInvariants
+#endif
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_PFTimeInvariants
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM PFT 1d [numpft] variables
+ ! -------------------------------------------------------------------
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ USE MOD_LandPFT, only: numpft
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+ allocate (pftclass (numpft))
+ allocate (pftfrac (numpft))
+ allocate (htop_p (numpft))
+ allocate (hbot_p (numpft))
+ ENDIF
+
+#ifdef CROP
+ IF (numpatch > 0) THEN
+ allocate (cropfrac (numpatch))
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE allocate_PFTimeInvariants
+
+ SUBROUTINE READ_PFTimeInvariants (file_restart)
+
+ USE MOD_NetCDFVector
+ USE MOD_LandPatch
+ USE MOD_LandPFT
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ IF (numpft > 0) THEN
+ CALL ncio_read_vector (file_restart, 'pftclass', landpft, pftclass) !
+ CALL ncio_read_vector (file_restart, 'pftfrac ', landpft, pftfrac ) !
+ CALL ncio_read_vector (file_restart, 'htop_p ', landpft, htop_p ) !
+ CALL ncio_read_vector (file_restart, 'hbot_p ', landpft, hbot_p ) !
+ ENDIF
+#ifdef CROP
+ IF (numpatch > 0) CALL ncio_read_vector (file_restart, 'cropfrac ', landpatch, cropfrac) !
+#endif
+
+ END SUBROUTINE READ_PFTimeInvariants
+
+ SUBROUTINE WRITE_PFTimeInvariants (file_restart)
+
+ USE MOD_NetCDFVector
+ USE MOD_LandPFT
+ USE MOD_LandPatch
+ USE MOD_Namelist
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ ! Local variables
+ character(len=*), intent(in) :: file_restart
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ IF (numpft > 0) THEN
+ CALL ncio_create_file_vector (file_restart, landpft)
+ CALL ncio_define_dimension_vector (file_restart, landpft, 'pft')
+
+ CALL ncio_write_vector (file_restart, 'pftclass', 'pft', landpft, pftclass, compress) !
+ CALL ncio_write_vector (file_restart, 'pftfrac ', 'pft', landpft, pftfrac , compress) !
+ CALL ncio_write_vector (file_restart, 'htop_p ', 'pft', landpft, htop_p , compress) !
+ CALL ncio_write_vector (file_restart, 'hbot_p ', 'pft', landpft, hbot_p , compress) !
+ ENDIF
+
+#ifdef CROP
+ IF (numpatch > 0) THEN
+ IF (numpft <= 0) CALL ncio_create_file_vector (file_restart, landpatch)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+ CALL ncio_write_vector (file_restart, 'cropfrac', 'patch', landpatch, cropfrac, compress) !
+ ENDIF
+#endif
+
+ END SUBROUTINE WRITE_PFTimeInvariants
+
+ SUBROUTINE deallocate_PFTimeInvariants
+ ! -------------------------------------------------------------------
+ ! Deallocates memory for CoLM PFT 1d [numpft] variables
+ ! -------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+ deallocate (pftclass)
+ deallocate (pftfrac )
+ deallocate (htop_p )
+ deallocate (hbot_p )
+ ENDIF
+#ifdef CROP
+ IF (numpatch > 0) deallocate (cropfrac)
+#endif
+ ENDIF
+
+ END SUBROUTINE deallocate_PFTimeInvariants
+
+#ifdef RangeCheck
+ SUBROUTINE check_PFTimeInvariants ()
+
+ USE MOD_RangeCheck
+ IMPLICIT NONE
+
+ CALL check_vector_data ('pftfrac', pftfrac) !
+ CALL check_vector_data ('htop_p ', htop_p ) !
+ CALL check_vector_data ('hbot_p ', hbot_p ) !
+#ifdef CROP
+ CALL check_vector_data ('cropfrac', cropfrac) !
+#endif
+
+ END SUBROUTINE check_PFTimeInvariants
+#endif
+
+END MODULE MOD_Vars_PFTimeInvariants
+#endif
+
+MODULE MOD_Vars_TimeInvariants
+! -------------------------------
+! Created by Yongjiu Dai, 03/2014
+! -------------------------------
+
+ USE MOD_Precision
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_Vars_PFTimeInvariants
+#endif
+#ifdef BGC
+ USE MOD_BGC_Vars_TimeInvariants
+#endif
+#ifdef URBAN_MODEL
+ USE MOD_Urban_Vars_TimeInvariants
+#endif
+ IMPLICIT NONE
+ SAVE
+
+! -----------------------------------------------------------------
+! surface classification and soil information
+ integer, allocatable :: patchclass (:) !index of land cover type of the patches at the fraction > 0
+ integer, allocatable :: patchtype (:) !land patch type
+ logical, allocatable :: patchmask (:) !patch mask
+
+ real(r8), allocatable :: patchlatr (:) !latitude in radians
+ real(r8), allocatable :: patchlonr (:) !longitude in radians
+
+ real(r8), allocatable :: lakedepth (:) !lake depth
+ real(r8), allocatable :: dz_lake (:,:) !new lake scheme
+
+ real(r8), allocatable :: soil_s_v_alb (:) !albedo of visible of the saturated soil
+ real(r8), allocatable :: soil_d_v_alb (:) !albedo of visible of the dry soil
+ real(r8), allocatable :: soil_s_n_alb (:) !albedo of near infrared of the saturated soil
+ real(r8), allocatable :: soil_d_n_alb (:) !albedo of near infrared of the dry soil
+#ifdef HYPERSPECTRAL
+ real(r8), allocatable :: soil_alb (:,:) ! hyper spectral soil albedo. (numpatch, nwl)
+#endif
+ real(r8), allocatable :: vf_quartz (:,:) !volumetric fraction of quartz within mineral soil
+ real(r8), allocatable :: vf_gravels (:,:) !volumetric fraction of gravels
+ real(r8), allocatable :: vf_om (:,:) !volumetric fraction of organic matter
+ real(r8), allocatable :: vf_sand (:,:) !volumetric fraction of sand
+ real(r8), allocatable :: vf_clay (:,:) !volumetric fraction of clay
+ real(r8), allocatable :: wf_gravels (:,:) !gravimetric fraction of gravels
+ real(r8), allocatable :: wf_sand (:,:) !gravimetric fraction of sand
+ real(r8), allocatable :: wf_clay (:,:) !gravimetric fraction of clay
+ real(r8), allocatable :: wf_om (:,:) !gravimetric fraction of om
+#ifdef DataAssimilation
+ real(r8), allocatable :: wf_silt (:,:) !gravimetric fraction of silt
+#endif
+ real(r8), allocatable :: OM_density (:,:) !OM density (kg/m3)
+ real(r8), allocatable :: BD_all (:,:) !bulk density of soil (GRAVELS + ORGANIC MATTER + Mineral Soils,kg/m3)
+
+ real(r8), allocatable :: wfc (:,:) !field capacity
+ real(r8), allocatable :: porsl (:,:) !fraction of soil that is voids [-]
+ real(r8), allocatable :: psi0 (:,:) !minimum soil suction [mm] (NOTE: "-" valued)
+ real(r8), allocatable :: bsw (:,:) !clapp and hornberger "b" parameter [-]
+ real(r8), allocatable :: theta_r (:,:) !residual moisture content [-]
+ real(r8), allocatable :: BVIC (:) !b parameter in Fraction of saturated soil in a grid calculated by VIC
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), allocatable :: alpha_vgm (:,:) !a parameter corresponding approximately to the inverse of the air-entry value
+ real(r8), allocatable :: L_vgm (:,:) !pore-connectivity parameter [dimensionless]
+ real(r8), allocatable :: n_vgm (:,:) !a shape parameter [dimensionless]
+ real(r8), allocatable :: sc_vgm (:,:) !saturation at the air entry value in the classical vanGenuchten model [-]
+ real(r8), allocatable :: fc_vgm (:,:) !a scaling factor by using air entry value in the Mualem model [-]
+#endif
+
+ integer, allocatable :: soiltext (:) !USDA soil texture class
+
+ real(r8), allocatable :: fsatmax (:) !maximum saturated area fraction [-]
+ real(r8), allocatable :: fsatdcf (:) !decay factor in calculation of saturated area fraction [1/m]
+
+ real(r8), allocatable :: topoweti (:) !topographic wetness index [log m]
+ real(r8), allocatable :: alp_twi (:) !alpha in three parameter gamma distribution of twi
+ real(r8), allocatable :: chi_twi (:) !chi in three parameter gamma distribution of twi
+ real(r8), allocatable :: mu_twi (:) !mu in three parameter gamma distribution of twi
+
+ real(r8), allocatable :: vic_b_infilt (:)
+ real(r8), allocatable :: vic_Dsmax (:)
+ real(r8), allocatable :: vic_Ds (:)
+ real(r8), allocatable :: vic_Ws (:)
+ real(r8), allocatable :: vic_c (:)
+
+ real(r8), allocatable :: hksati (:,:) !hydraulic conductivity at saturation [mm h2o/s]
+ real(r8), allocatable :: csol (:,:) !heat capacity of soil solids [J/(m3 K)]
+ real(r8), allocatable :: k_solids (:,:) !thermal conductivity of soil solids [W/m-K]
+ real(r8), allocatable :: dksatu (:,:) !thermal conductivity of saturated soil [W/m-K]
+ real(r8), allocatable :: dksatf (:,:) !thermal conductivity of saturated frozen soil [W/m-K]
+ real(r8), allocatable :: dkdry (:,:) !thermal conductivity for dry soil [W/(m-K)]
+ real(r8), allocatable :: BA_alpha (:,:) !alpha in Balland and Arp(2005) thermal conductivity scheme
+ real(r8), allocatable :: BA_beta (:,:) !beta in Balland and Arp(2005) thermal conductivity scheme
+ real(r8), allocatable :: htop (:) !canopy top height [m]
+ real(r8), allocatable :: hbot (:) !canopy bottom height [m]
+
+ real(r8), allocatable :: dbedrock (:) !depth to bedrock
+ integer , allocatable :: ibedrock (:) !bedrock level
+
+ real(r8), allocatable :: elvmean (:) !elevation above sea level [m]
+ real(r8), allocatable :: elvstd (:) !standard deviation of elevation [m]
+ real(r8), allocatable :: slpratio (:) !slope ratio [-]
+
+ real(r8) :: zlnd !roughness length for soil [m]
+ real(r8) :: zsno !roughness length for snow [m]
+ real(r8) :: csoilc !drag coefficient for soil under canopy [-]
+ real(r8) :: dewmx !maximum dew
+ ! 'wtfact' is updated to gridded 'fsatmax' data.
+ ! real(r8) :: wtfact !fraction of model area with high water table
+ real(r8) :: capr !tuning factor to turn first layer T into surface T
+ real(r8) :: cnfac !Crank Nicholson factor between 0 and 1
+ real(r8) :: ssi !irreducible water saturation of snow
+ real(r8) :: wimp !water impermeable IF porosity less than wimp
+ real(r8) :: pondmx !ponding depth (mm)
+ real(r8) :: smpmax !wilting point potential in mm
+ real(r8) :: smpmin !restriction for min of soil poten. (mm)
+ real(r8) :: smpmax_hr !wilting point potential in mm for heterotrophic respiration
+ real(r8) :: smpmin_hr !restriction for min of soil poten for heterotrophic respiration. (mm)
+ real(r8) :: trsmx0 !max transpiration for moist soil+100% veg. [mm/s]
+ real(r8) :: tcrit !critical temp. to determine rain or snow
+ real(r8) :: wetwatmax !maximum wetland water (mm)
+
+ ! Used for downscaling
+ real(r8), allocatable :: svf_patches (:) !sky view factor
+ real(r8), allocatable :: cur_patches (:) !curvature
+ real(r8), allocatable :: sf_lut_patches (:,:,:) !look up table of shadow factor of a patch
+ real(r8), allocatable :: sf_curve_patches(:,:,:) !curve parameters of shadow factor of a patch
+ real(r8), allocatable :: asp_type_patches (:,:) !topographic aspect of each character of one patch
+ real(r8), allocatable :: slp_type_patches (:,:) !topographic slope of each character of one patch
+ real(r8), allocatable :: area_type_patches (:,:) !area percentage of each character of one patch
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_TimeInvariants
+ PUBLIC :: deallocate_TimeInvariants
+ PUBLIC :: READ_TimeInvariants
+ PUBLIC :: WRITE_TimeInvariants
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_TimeInvariants ()
+ ! -------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ ! -------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ allocate (patchclass (numpatch))
+ allocate (patchtype (numpatch))
+ allocate (patchmask (numpatch))
+
+ allocate (patchlonr (numpatch))
+ allocate (patchlatr (numpatch))
+
+ allocate (lakedepth (numpatch))
+ allocate (dz_lake (nl_lake,numpatch))
+
+ allocate (soil_s_v_alb (numpatch))
+ allocate (soil_d_v_alb (numpatch))
+ allocate (soil_s_n_alb (numpatch))
+ allocate (soil_d_n_alb (numpatch))
+#ifdef HYPERSPECTRAL
+ allocate (soil_alb (nwl, numpatch))
+#endif
+
+ allocate (vf_quartz (nl_soil,numpatch))
+ allocate (vf_gravels (nl_soil,numpatch))
+ allocate (vf_om (nl_soil,numpatch))
+ allocate (vf_sand (nl_soil,numpatch))
+ allocate (vf_clay (nl_soil,numpatch))
+ allocate (wf_gravels (nl_soil,numpatch))
+ allocate (wf_sand (nl_soil,numpatch))
+ allocate (wf_clay (nl_soil,numpatch))
+ allocate (wf_om (nl_soil,numpatch))
+#ifdef DataAssimilation
+ allocate (wf_silt (nl_soil,numpatch))
+#endif
+ allocate (OM_density (nl_soil,numpatch))
+ allocate (BD_all (nl_soil,numpatch))
+ allocate (wfc (nl_soil,numpatch))
+ allocate (porsl (nl_soil,numpatch))
+ allocate (psi0 (nl_soil,numpatch))
+ allocate (bsw (nl_soil,numpatch))
+ allocate (theta_r (nl_soil,numpatch))
+ allocate (BVIC (numpatch))
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ allocate (alpha_vgm (nl_soil,numpatch))
+ allocate (L_vgm (nl_soil,numpatch))
+ allocate (n_vgm (nl_soil,numpatch))
+ allocate (sc_vgm (nl_soil,numpatch))
+ allocate (fc_vgm (nl_soil,numpatch))
+#endif
+ allocate (soiltext (numpatch))
+
+ allocate (fsatmax (numpatch))
+ allocate (fsatdcf (numpatch))
+ allocate (topoweti (numpatch))
+ allocate (alp_twi (numpatch))
+ allocate (chi_twi (numpatch))
+ allocate (mu_twi (numpatch))
+
+ allocate (vic_b_infilt (numpatch))
+ allocate (vic_Dsmax (numpatch))
+ allocate (vic_Ds (numpatch))
+ allocate (vic_Ws (numpatch))
+ allocate (vic_c (numpatch))
+
+ allocate (hksati (nl_soil,numpatch))
+ allocate (csol (nl_soil,numpatch))
+ allocate (k_solids (nl_soil,numpatch))
+ allocate (dksatu (nl_soil,numpatch))
+ allocate (dksatf (nl_soil,numpatch))
+ allocate (dkdry (nl_soil,numpatch))
+ allocate (BA_alpha (nl_soil,numpatch))
+ allocate (BA_beta (nl_soil,numpatch))
+ allocate (htop (numpatch))
+ allocate (hbot (numpatch))
+ allocate (dbedrock (numpatch))
+ allocate (ibedrock (numpatch))
+ allocate (elvmean (numpatch))
+ allocate (elvstd (numpatch))
+ allocate (slpratio (numpatch))
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ ! Used for downscaling
+ allocate (svf_patches (numpatch))
+ allocate (asp_type_patches (num_slope_type,numpatch))
+ allocate (slp_type_patches (num_slope_type,numpatch))
+ allocate (area_type_patches (num_slope_type,numpatch))
+ allocate (cur_patches (numpatch))
+#ifdef SinglePoint
+ allocate (sf_lut_patches (num_azimuth,num_zenith,numpatch))
+#else
+ allocate (sf_curve_patches (num_azimuth,num_zenith_parameter,numpatch))
+#endif
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ ! Used for downscaling
+ allocate (asp_type_patches (num_aspect_type,numpatch))
+ allocate (slp_type_patches (num_aspect_type,numpatch))
+ allocate (cur_patches (numpatch))
+ ENDIF
+
+ ENDIF
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL allocate_PFTimeInvariants
+#endif
+
+#ifdef BGC
+ CALL allocate_BGCTimeInvariants
+#endif
+
+#ifdef URBAN_MODEL
+ CALL allocate_UrbanTimeInvariants
+#endif
+
+ END SUBROUTINE allocate_TimeInvariants
+
+ !---------------------------------------
+ SUBROUTINE READ_TimeInvariants (lc_year, casename, dir_restart)
+
+ !====================================================================
+ ! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+ !====================================================================
+
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFVector
+ USE MOD_NetCDFSerial
+#ifdef RangeCheck
+ USE MOD_RangeCheck
+#endif
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+ USE MOD_Const_LC, only: patchtypes
+
+ IMPLICIT NONE
+
+ integer , intent(in) :: lc_year
+ character(len=*), intent(in) :: casename
+ character(len=*), intent(in) :: dir_restart
+
+ ! Local variables
+ character(len=256) :: file_restart, cyear, lndname
+
+ write(cyear,'(i4.4)') lc_year
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_const' // '_lc' // trim(cyear) // '.nc'
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpatch > 0) THEN
+#endif
+
+ CALL ncio_read_vector (file_restart, 'patchclass', landpatch, patchclass) !
+ CALL ncio_read_vector (file_restart, 'patchtype' , landpatch, patchtype ) !
+ CALL ncio_read_vector (file_restart, 'patchmask' , landpatch, patchmask ) !
+
+ CALL ncio_read_vector (file_restart, 'patchlonr' , landpatch, patchlonr ) !
+ CALL ncio_read_vector (file_restart, 'patchlatr' , landpatch, patchlatr ) !
+
+ CALL ncio_read_vector (file_restart, 'lakedepth', landpatch, lakedepth) !
+ CALL ncio_read_vector (file_restart, 'dz_lake' , nl_lake, landpatch, dz_lake) !
+
+ CALL ncio_read_vector (file_restart, 'soil_s_v_alb', landpatch, soil_s_v_alb) ! albedo of visible of the saturated soil
+ CALL ncio_read_vector (file_restart, 'soil_d_v_alb', landpatch, soil_d_v_alb) ! albedo of visible of the dry soil
+ CALL ncio_read_vector (file_restart, 'soil_s_n_alb', landpatch, soil_s_n_alb) ! albedo of near infrared of the saturated soil
+ CALL ncio_read_vector (file_restart, 'soil_d_n_alb', landpatch, soil_d_n_alb) ! albedo of near infrared of the dry soil
+#ifdef HYPERSPECTRAL
+ CALL ncio_read_vector (file_restart, 'soil_alb' , nwl, landpatch, soil_alb ) ! hyper spectral soil albedo. (numpatch, nwl)
+#endif
+
+ CALL ncio_read_vector (file_restart, 'vf_quartz ', nl_soil, landpatch, vf_quartz ) ! volumetric fraction of quartz within mineral soil
+ CALL ncio_read_vector (file_restart, 'vf_gravels', nl_soil, landpatch, vf_gravels) ! volumetric fraction of gravels
+ CALL ncio_read_vector (file_restart, 'vf_om ', nl_soil, landpatch, vf_om ) ! volumetric fraction of organic matter
+ CALL ncio_read_vector (file_restart, 'vf_sand ', nl_soil, landpatch, vf_sand ) ! volumetric fraction of sand
+ CALL ncio_read_vector (file_restart, 'vf_clay ', nl_soil, landpatch, vf_clay ,defval = 0.1 ) ! volumetric fraction of clay
+ CALL ncio_read_vector (file_restart, 'wf_gravels', nl_soil, landpatch, wf_gravels) ! gravimetric fraction of gravels
+ CALL ncio_read_vector (file_restart, 'wf_sand ', nl_soil, landpatch, wf_sand ) ! gravimetric fraction of sand
+ CALL ncio_read_vector (file_restart, 'wf_clay ', nl_soil, landpatch, wf_clay ) ! gravimetric fraction of clay
+ CALL ncio_read_vector (file_restart, 'wf_om ', nl_soil, landpatch, wf_om ) ! gravimetric fraction of om
+ CALL ncio_read_vector (file_restart, 'OM_density', nl_soil, landpatch, OM_density) ! OM density
+ CALL ncio_read_vector (file_restart, 'BD_all ', nl_soil, landpatch, BD_all ) ! bulk density of soil
+ CALL ncio_read_vector (file_restart, 'wfc ', nl_soil, landpatch, wfc ) ! field capacity
+ CALL ncio_read_vector (file_restart, 'porsl ' , nl_soil, landpatch, porsl ) ! fraction of soil that is voids [-]
+ CALL ncio_read_vector (file_restart, 'psi0 ' , nl_soil, landpatch, psi0 ) ! minimum soil suction [mm] (NOTE: "-" valued)
+ CALL ncio_read_vector (file_restart, 'bsw ' , nl_soil, landpatch, bsw ) ! clapp and hornberger "b" parameter [-]
+ CALL ncio_read_vector (file_restart, 'theta_r ' , nl_soil, landpatch, theta_r ) ! residual moisture content [-]
+ CALL ncio_read_vector (file_restart, 'BVIC ' , landpatch, BVIC ) ! b parameter in Fraction of saturated soil in a grid calculated by VIC
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ CALL ncio_read_vector (file_restart, 'alpha_vgm' , nl_soil, landpatch, alpha_vgm ) ! a parameter corresponding approximately to the inverse of the air-entry value
+ CALL ncio_read_vector (file_restart, 'L_vgm ' , nl_soil, landpatch, L_vgm ) ! pore-connectivity parameter [dimensionless]
+ CALL ncio_read_vector (file_restart, 'n_vgm ' , nl_soil, landpatch, n_vgm ) ! a shape parameter [dimensionless]
+ CALL ncio_read_vector (file_restart, 'sc_vgm ' , nl_soil, landpatch, sc_vgm ) ! saturation at the air entry value in the classical vanGenuchten model [-]
+ CALL ncio_read_vector (file_restart, 'fc_vgm ' , nl_soil, landpatch, fc_vgm ) ! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+#ifdef DataAssimilation
+ IF (numpatch > 0 .and. p_is_compute) wf_silt = 1.0_r8 - wf_gravels - wf_sand - wf_clay - wf_om
+#endif
+
+ CALL ncio_read_vector (file_restart, 'soiltext', landpatch, soiltext, defval = 0 )
+
+ IF (DEF_Runoff_SCHEME == 0) THEN
+ CALL ncio_read_vector (file_restart, 'topoweti', landpatch, topoweti, defval = 9.27 )
+ CALL ncio_read_vector (file_restart, 'fsatmax ', landpatch, fsatmax , defval = 0.38 )
+ CALL ncio_read_vector (file_restart, 'fsatdcf ', landpatch, fsatdcf , defval = 0.55 )
+ CALL ncio_read_vector (file_restart, 'alp_twi ', landpatch, alp_twi , defval = 1.34 )
+ CALL ncio_read_vector (file_restart, 'chi_twi ', landpatch, chi_twi , defval = 1.61 )
+ CALL ncio_read_vector (file_restart, 'mu_twi ', landpatch, mu_twi , defval = 6.95 )
+ ENDIF
+
+ CALL ncio_read_vector (file_restart, 'vic_b_infilt', landpatch, vic_b_infilt)
+ CALL ncio_read_vector (file_restart, 'vic_Dsmax' , landpatch, vic_Dsmax )
+ CALL ncio_read_vector (file_restart, 'vic_Ds' , landpatch, vic_Ds )
+ CALL ncio_read_vector (file_restart, 'vic_Ws' , landpatch, vic_Ws )
+ CALL ncio_read_vector (file_restart, 'vic_c' , landpatch, vic_c )
+
+ CALL ncio_read_vector (file_restart, 'hksati ' , nl_soil, landpatch, hksati ) ! hydraulic conductivity at saturation [mm h2o/s]
+ CALL ncio_read_vector (file_restart, 'csol ' , nl_soil, landpatch, csol ) ! heat capacity of soil solids [J/(m3 K)]
+ CALL ncio_read_vector (file_restart, 'k_solids', nl_soil, landpatch, k_solids) ! thermal conductivity of soil solids [W/m-K]
+ CALL ncio_read_vector (file_restart, 'dksatu ' , nl_soil, landpatch, dksatu ) ! thermal conductivity of unfrozen saturated soil [W/m-K]
+ CALL ncio_read_vector (file_restart, 'dksatf ' , nl_soil, landpatch, dksatf ) ! thermal conductivity of frozen saturated soil [W/m-K]
+ CALL ncio_read_vector (file_restart, 'dkdry ' , nl_soil, landpatch, dkdry ) ! thermal conductivity for dry soil [W/(m-K)]
+ CALL ncio_read_vector (file_restart, 'BA_alpha', nl_soil, landpatch, BA_alpha) ! alpha in Balland and Arp(2005) thermal conductivity scheme
+ CALL ncio_read_vector (file_restart, 'BA_beta' , nl_soil, landpatch, BA_beta ) ! beta in Balland and Arp(2005) thermal conductivity scheme
+ CALL ncio_read_vector (file_restart, 'htop' , landpatch, htop) !
+ CALL ncio_read_vector (file_restart, 'hbot' , landpatch, hbot) !
+
+ IF(DEF_USE_BEDROCK)THEN
+ CALL ncio_read_vector (file_restart, 'debdrock' , landpatch, dbedrock) !
+ CALL ncio_read_vector (file_restart, 'ibedrock' , landpatch, ibedrock) !
+ ENDIF
+
+ CALL ncio_read_vector (file_restart, 'elvmean ', landpatch, elvmean ) !
+ CALL ncio_read_vector (file_restart, 'elvstd ', landpatch, elvstd ) !
+ CALL ncio_read_vector (file_restart, 'slpratio', landpatch, slpratio) !
+
+#ifdef MPAS_EMBEDDED_COLM
+ ENDIF
+#endif
+
+ CALL ncio_read_bcast_serial (file_restart, 'zlnd ', zlnd ) ! roughness length for soil [m]
+ CALL ncio_read_bcast_serial (file_restart, 'zsno ', zsno ) ! roughness length for snow [m]
+ CALL ncio_read_bcast_serial (file_restart, 'csoilc', csoilc) ! drag coefficient for soil under canopy [-]
+ CALL ncio_read_bcast_serial (file_restart, 'dewmx ', dewmx ) ! maximum dew
+ ! CALL ncio_read_bcast_serial (file_restart, 'wtfact', wtfact) ! fraction of model area with high water table
+ CALL ncio_read_bcast_serial (file_restart, 'capr ', capr ) ! tuning factor to turn first layer T into surface T
+ CALL ncio_read_bcast_serial (file_restart, 'cnfac ', cnfac ) ! Crank Nicholson factor between 0 and 1
+ CALL ncio_read_bcast_serial (file_restart, 'ssi ', ssi ) ! irreducible water saturation of snow
+ CALL ncio_read_bcast_serial (file_restart, 'wimp ', wimp ) ! water impermeable IF porosity less than wimp
+ CALL ncio_read_bcast_serial (file_restart, 'pondmx', pondmx) ! ponding depth (mm)
+ CALL ncio_read_bcast_serial (file_restart, 'smpmax', smpmax) ! wilting point potential in mm
+ CALL ncio_read_bcast_serial (file_restart, 'smpmin', smpmin) ! restriction for min of soil poten. (mm)
+ CALL ncio_read_bcast_serial (file_restart, 'smpmax_hr', smpmax_hr) ! wilting point potential in mm
+ CALL ncio_read_bcast_serial (file_restart, 'smpmin_hr', smpmin_hr) ! restriction for min of soil poten. (mm)
+ CALL ncio_read_bcast_serial (file_restart, 'trsmx0', trsmx0) ! max transpiration for moist soil+100% veg. [mm/s]
+ CALL ncio_read_bcast_serial (file_restart, 'tcrit ', tcrit ) ! critical temp. to determine rain or snow
+ CALL ncio_read_bcast_serial (file_restart, 'wetwatmax', wetwatmax) ! maximum wetland water (mm)
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpatch > 0) THEN
+#endif
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL ncio_read_vector (file_restart, 'slp_type_patches' , num_slope_type, landpatch, slp_type_patches)
+ CALL ncio_read_vector (file_restart, 'svf_patches' , landpatch, svf_patches )
+ CALL ncio_read_vector (file_restart, 'asp_type_patches' , num_slope_type, landpatch, asp_type_patches)
+ CALL ncio_read_vector (file_restart, 'area_type_patches', num_slope_type, landpatch, area_type_patches)
+ CALL ncio_read_vector (file_restart, 'cur_patches' , landpatch, cur_patches )
+#ifdef SinglePoint
+ CALL ncio_read_vector (file_restart, 'sf_lut_patches' , num_azimuth , num_zenith, landpatch, sf_lut_patches)
+#else
+ CALL ncio_read_vector (file_restart, 'sf_curve_patches' , num_azimuth , num_zenith_parameter, landpatch, sf_curve_patches)
+#endif
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ CALL ncio_read_vector (file_restart, 'slp_type_patches' , num_aspect_type, landpatch, slp_type_patches)
+ CALL ncio_read_vector (file_restart, 'asp_type_patches' , num_aspect_type, landpatch, asp_type_patches)
+ CALL ncio_read_vector (file_restart, 'cur_patches' , landpatch, cur_patches )
+ ENDIF
+
+#ifdef MPAS_EMBEDDED_COLM
+ ENDIF
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+#ifdef SinglePoint
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_pft_const' // '_lc' // trim(cyear) // '.nc'
+ CALL READ_PFTimeInvariants (file_restart)
+ ENDIF
+#else
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_pft_const' // '_lc' // trim(cyear) // '.nc'
+ CALL READ_PFTimeInvariants (file_restart)
+#endif
+#endif
+
+#if (defined BGC)
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_bgc_const' // '_lc' // trim(cyear) // '.nc'
+ CALL READ_BGCTimeInvariants (file_restart)
+#endif
+
+#if (defined URBAN_MODEL)
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_urb_const' // '_lc' // trim(cyear) // '.nc'
+ CALL READ_UrbanTimeInvariants (file_restart)
+#endif
+
+#ifdef RangeCheck
+ CALL check_TimeInvariants ()
+#endif
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write(*,*) 'Loading Time Invariants done.'
+ ENDIF
+
+ END SUBROUTINE READ_TimeInvariants
+
+ !---------------------------------------
+ SUBROUTINE WRITE_TimeInvariants (lc_year, casename, dir_restart)
+
+ !====================================================================
+ ! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+ !====================================================================
+
+ USE MOD_Namelist, only: DEF_REST_CompressLevel, DEF_USE_BEDROCK
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFVector
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ integer , intent(in) :: lc_year
+ character(len=*), intent(in) :: casename
+ character(len=*), intent(in) :: dir_restart
+
+ ! Local Variables
+ character(len=256) :: file_restart, cyear
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ write(cyear,'(i4.4)') lc_year
+
+ IF (p_is_root) THEN
+ CALL system('mkdir -p ' // trim(dir_restart)//'/const')
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_const' //'_lc'// trim(cyear) // '.nc'
+
+ CALL ncio_create_file_vector (file_restart, landpatch)
+
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil', nl_soil)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'lake', nl_lake)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'band', 2)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'rtyp', 2)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'snow', -maxsnl )
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'snowp1', -maxsnl+1 )
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soilsnow', nl_soil-maxsnl)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil', nl_soil)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'lake', nl_lake)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'type', num_slope_type)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'azi', num_azimuth)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'zen', num_zenith)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'zen_p', num_zenith_parameter)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'type_a', num_aspect_type)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'wavelength', nwl)
+
+ CALL ncio_write_vector (file_restart, 'patchclass', 'patch', landpatch, patchclass) !
+ CALL ncio_write_vector (file_restart, 'patchtype' , 'patch', landpatch, patchtype ) !
+ CALL ncio_write_vector (file_restart, 'patchmask' , 'patch', landpatch, patchmask ) !
+
+ CALL ncio_write_vector (file_restart, 'patchlonr' , 'patch', landpatch, patchlonr ) !
+ CALL ncio_write_vector (file_restart, 'patchlatr' , 'patch', landpatch, patchlatr ) !
+
+ CALL ncio_write_vector (file_restart, 'lakedepth' , 'patch', landpatch, lakedepth , compress) !
+ CALL ncio_write_vector (file_restart, 'dz_lake' , 'lake', nl_lake, 'patch', landpatch, dz_lake, compress) !
+
+ CALL ncio_write_vector (file_restart, 'soil_s_v_alb', 'patch', landpatch, soil_s_v_alb, compress) ! albedo of visible of the saturated soil
+ CALL ncio_write_vector (file_restart, 'soil_d_v_alb', 'patch', landpatch, soil_d_v_alb, compress) ! albedo of visible of the dry soil
+ CALL ncio_write_vector (file_restart, 'soil_s_n_alb', 'patch', landpatch, soil_s_n_alb, compress) ! albedo of near infrared of the saturated soil
+ CALL ncio_write_vector (file_restart, 'soil_d_n_alb', 'patch', landpatch, soil_d_n_alb, compress) ! albedo of near infrared of the dry soil
+#ifdef HYPERSPECTRAL
+ CALL ncio_write_vector (file_restart, 'soil_alb' , 'wavelength', nwl, 'patch', landpatch, soil_alb, compress) ! hyper spectral soil albedo. (numpatch, nwl)
+#endif
+
+ CALL ncio_write_vector (file_restart, 'vf_quartz ', 'soil', nl_soil, 'patch', landpatch, vf_quartz , compress) ! volumetric fraction of quartz within mineral soil
+ CALL ncio_write_vector (file_restart, 'vf_gravels', 'soil', nl_soil, 'patch', landpatch, vf_gravels, compress) ! volumetric fraction of gravels
+ CALL ncio_write_vector (file_restart, 'vf_om ', 'soil', nl_soil, 'patch', landpatch, vf_om , compress) ! volumetric fraction of organic matter
+ CALL ncio_write_vector (file_restart, 'vf_sand ', 'soil', nl_soil, 'patch', landpatch, vf_sand , compress) ! volumetric fraction of sand
+ CALL ncio_write_vector (file_restart, 'vf_clay ', 'soil', nl_soil, 'patch', landpatch, vf_clay , compress) ! volumetric fraction of clay
+ CALL ncio_write_vector (file_restart, 'wf_gravels', 'soil', nl_soil, 'patch', landpatch, wf_gravels, compress) ! gravimetric fraction of gravels
+ CALL ncio_write_vector (file_restart, 'wf_sand ', 'soil', nl_soil, 'patch', landpatch, wf_sand , compress) ! gravimetric fraction of sand
+ CALL ncio_write_vector (file_restart, 'wf_clay ', 'soil', nl_soil, 'patch', landpatch, wf_clay , compress) ! gravimetric fraction of clay
+ CALL ncio_write_vector (file_restart, 'wf_om ', 'soil', nl_soil, 'patch', landpatch, wf_om , compress) ! gravimetric fraction of om
+ CALL ncio_write_vector (file_restart, 'OM_density', 'soil', nl_soil, 'patch', landpatch, OM_density, compress) ! OM_density
+ CALL ncio_write_vector (file_restart, 'BD_all ', 'soil', nl_soil, 'patch', landpatch, BD_all , compress) ! bulk density of soil
+ CALL ncio_write_vector (file_restart, 'wfc ', 'soil', nl_soil, 'patch', landpatch, wfc , compress) ! field capacity
+ CALL ncio_write_vector (file_restart, 'porsl ', 'soil', nl_soil, 'patch', landpatch, porsl , compress) ! fraction of soil that is voids [-]
+ CALL ncio_write_vector (file_restart, 'psi0 ', 'soil', nl_soil, 'patch', landpatch, psi0 , compress) ! minimum soil suction [mm] (NOTE: "-" valued)
+ CALL ncio_write_vector (file_restart, 'bsw ', 'soil', nl_soil, 'patch', landpatch, bsw , compress) ! clapp and hornberger "b" parameter [-]
+ CALL ncio_write_vector (file_restart, 'theta_r ' , 'soil', nl_soil, 'patch', landpatch, theta_r , compress) ! residual moisture content [-]
+ CALL ncio_write_vector (file_restart, 'BVIC ' , 'patch', landpatch, BVIC, compress) ! b parameter in Fraction of saturated soil in a grid calculated by VIC
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ CALL ncio_write_vector (file_restart, 'alpha_vgm' , 'soil', nl_soil, 'patch', landpatch, alpha_vgm , compress) ! a parameter corresponding approximately to the inverse of the air-entry value
+ CALL ncio_write_vector (file_restart, 'L_vgm ' , 'soil', nl_soil, 'patch', landpatch, L_vgm , compress) ! pore-connectivity parameter [dimensionless]
+ CALL ncio_write_vector (file_restart, 'n_vgm ' , 'soil', nl_soil, 'patch', landpatch, n_vgm , compress) ! a shape parameter [dimensionless]
+ CALL ncio_write_vector (file_restart, 'sc_vgm ' , 'soil', nl_soil, 'patch', landpatch, sc_vgm , compress) ! saturation at the air entry value in the classical vanGenuchten model [-]
+ CALL ncio_write_vector (file_restart, 'fc_vgm ' , 'soil', nl_soil, 'patch', landpatch, fc_vgm , compress) ! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+
+ CALL ncio_write_vector (file_restart, 'soiltext', 'patch', landpatch, soiltext)
+
+ IF (DEF_Runoff_SCHEME == 0) THEN
+ CALL ncio_write_vector (file_restart, 'topoweti', 'patch', landpatch, topoweti)
+ CALL ncio_write_vector (file_restart, 'fsatmax ', 'patch', landpatch, fsatmax )
+ CALL ncio_write_vector (file_restart, 'fsatdcf ', 'patch', landpatch, fsatdcf )
+ CALL ncio_write_vector (file_restart, 'alp_twi ', 'patch', landpatch, alp_twi )
+ CALL ncio_write_vector (file_restart, 'chi_twi ', 'patch', landpatch, chi_twi )
+ CALL ncio_write_vector (file_restart, 'mu_twi ', 'patch', landpatch, mu_twi )
+ ENDIF
+
+ CALL ncio_write_vector (file_restart, 'vic_b_infilt', 'patch', landpatch, vic_b_infilt)
+ CALL ncio_write_vector (file_restart, 'vic_Dsmax' , 'patch', landpatch, vic_Dsmax )
+ CALL ncio_write_vector (file_restart, 'vic_Ds' , 'patch', landpatch, vic_Ds )
+ CALL ncio_write_vector (file_restart, 'vic_Ws' , 'patch', landpatch, vic_Ws )
+ CALL ncio_write_vector (file_restart, 'vic_c' , 'patch', landpatch, vic_c )
+
+ CALL ncio_write_vector (file_restart, 'hksati ' , 'soil', nl_soil, 'patch', landpatch, hksati , compress) ! hydraulic conductivity at saturation [mm h2o/s]
+ CALL ncio_write_vector (file_restart, 'csol ' , 'soil', nl_soil, 'patch', landpatch, csol , compress) ! heat capacity of soil solids [J/(m3 K)]
+ CALL ncio_write_vector (file_restart, 'k_solids ' , 'soil', nl_soil, 'patch', landpatch, k_solids , compress) ! thermal conductivity of soil solids [W/m-K]
+ CALL ncio_write_vector (file_restart, 'dksatu ' , 'soil', nl_soil, 'patch', landpatch, dksatu , compress) ! thermal conductivity of saturated soil [W/m-K]
+ CALL ncio_write_vector (file_restart, 'dksatf ' , 'soil', nl_soil, 'patch', landpatch, dksatf , compress) ! thermal conductivity of saturated soil [W/m-K]
+ CALL ncio_write_vector (file_restart, 'dkdry ' , 'soil', nl_soil, 'patch', landpatch, dkdry , compress) ! thermal conductivity for dry soil [W/(m-K)]
+ CALL ncio_write_vector (file_restart, 'BA_alpha ' , 'soil', nl_soil, 'patch', landpatch, BA_alpha , compress) ! alpha in Balland and Arp(2005) thermal conductivity scheme
+ CALL ncio_write_vector (file_restart, 'BA_beta ' , 'soil', nl_soil, 'patch', landpatch, BA_beta , compress) ! beta in Balland and Arp(2005) thermal conductivity scheme
+
+ CALL ncio_write_vector (file_restart, 'htop' , 'patch', landpatch, htop) !
+ CALL ncio_write_vector (file_restart, 'hbot' , 'patch', landpatch, hbot) !
+
+ IF(DEF_USE_BEDROCK)THEN
+ CALL ncio_write_vector (file_restart, 'debdrock' , 'patch', landpatch, dbedrock)
+ CALL ncio_write_vector (file_restart, 'ibedrock' , 'patch', landpatch, ibedrock)
+ ENDIF
+
+ CALL ncio_write_vector (file_restart, 'elvmean ', 'patch', landpatch, elvmean )
+ CALL ncio_write_vector (file_restart, 'elvstd ', 'patch', landpatch, elvstd )
+ CALL ncio_write_vector (file_restart, 'slpratio', 'patch', landpatch, slpratio)
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL ncio_write_vector (file_restart, 'svf_patches', 'patch', landpatch, svf_patches)
+ CALL ncio_write_vector (file_restart, 'cur_patches', 'patch', landpatch, cur_patches)
+ CALL ncio_write_vector (file_restart, 'slp_type_patches', 'type', num_slope_type, 'patch', landpatch, slp_type_patches)
+ CALL ncio_write_vector (file_restart, 'asp_type_patches', 'type', num_slope_type, 'patch', landpatch, asp_type_patches)
+ CALL ncio_write_vector (file_restart, 'area_type_patches', 'type', num_slope_type, 'patch', landpatch, area_type_patches)
+#ifdef SinglePoint
+ CALL ncio_write_vector (file_restart, 'sf_lut_patches', 'azi' , num_azimuth,'zen', num_zenith, 'patch', landpatch, sf_lut_patches)
+#else
+ CALL ncio_write_vector (file_restart, 'sf_curve_patches', 'azi' , num_azimuth,'zen_p', num_zenith_parameter, 'patch', landpatch, sf_curve_patches)
+#endif
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ CALL ncio_write_vector (file_restart, 'cur_patches', 'patch', landpatch, cur_patches)
+ CALL ncio_write_vector (file_restart, 'slp_type_patches', 'type_a', num_aspect_type, 'patch', landpatch, slp_type_patches)
+ CALL ncio_write_vector (file_restart, 'asp_type_patches', 'type_a', num_aspect_type, 'patch', landpatch, asp_type_patches)
+ ENDIF
+
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ if (p_is_root) then
+
+#if (!defined(VectorInOneFileS) && !defined(VectorInOneFileP))
+ CALL ncio_create_file (file_restart)
+#endif
+
+ CALL ncio_write_serial (file_restart, 'zlnd ', zlnd ) ! roughness length for soil [m]
+ CALL ncio_write_serial (file_restart, 'zsno ', zsno ) ! roughness length for snow [m]
+ CALL ncio_write_serial (file_restart, 'csoilc', csoilc) ! drag coefficient for soil under canopy [-]
+ CALL ncio_write_serial (file_restart, 'dewmx ', dewmx ) ! maximum dew
+ ! CALL ncio_write_serial (file_restart, 'wtfact', wtfact) ! fraction of model area with high water table
+ CALL ncio_write_serial (file_restart, 'capr ', capr ) ! tuning factor to turn first layer T into surface T
+ CALL ncio_write_serial (file_restart, 'cnfac ', cnfac ) ! Crank Nicholson factor between 0 and 1
+ CALL ncio_write_serial (file_restart, 'ssi ', ssi ) ! irreducible water saturation of snow
+ CALL ncio_write_serial (file_restart, 'wimp ', wimp ) ! water impermeable if porosity less than wimp
+ CALL ncio_write_serial (file_restart, 'pondmx', pondmx) ! ponding depth (mm)
+ CALL ncio_write_serial (file_restart, 'smpmax', smpmax) ! wilting point potential in mm
+ CALL ncio_write_serial (file_restart, 'smpmin', smpmin) ! restriction for min of soil poten. (mm)
+ CALL ncio_write_serial (file_restart, 'smpmax_hr', smpmax_hr) ! wilting point potential in mm
+ CALL ncio_write_serial (file_restart, 'smpmin_hr', smpmin_hr) ! restriction for min of soil poten. (mm)
+ CALL ncio_write_serial (file_restart, 'trsmx0', trsmx0) ! max transpiration for moist soil+100% veg. [mm/s]
+ CALL ncio_write_serial (file_restart, 'tcrit ', tcrit ) ! critical temp. to determine rain or snow
+ CALL ncio_write_serial (file_restart, 'wetwatmax', wetwatmax) ! maximum wetland water (mm)
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_pft_const' //'_lc'// trim(cyear) // '.nc'
+ CALL WRITE_PFTimeInvariants (file_restart)
+#endif
+
+#if (defined BGC)
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_bgc_const' //'_lc'// trim(cyear) // '.nc'
+ CALL WRITE_BGCTimeInvariants (file_restart)
+#endif
+
+#if (defined URBAN_MODEL)
+ file_restart = trim(dir_restart) // '/const/' // trim(casename) //'_restart_urb_const' //'_lc'// trim(cyear) // '.nc'
+ CALL WRITE_UrbanTimeInvariants (file_restart)
+#endif
+
+ END SUBROUTINE WRITE_TimeInvariants
+
+ SUBROUTINE deallocate_TimeInvariants ()
+
+ USE MOD_Namelist, only: DEF_USE_Forcing_Downscaling, DEF_USE_Forcing_Downscaling_Simple
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+
+ IMPLICIT NONE
+
+ ! --------------------------------------------------
+ ! Deallocates memory for CoLM 1d [numpatch] variables
+ ! --------------------------------------------------
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ deallocate (patchclass )
+ deallocate (patchtype )
+ deallocate (patchmask )
+
+ deallocate (patchlonr )
+ deallocate (patchlatr )
+
+ deallocate (lakedepth )
+ deallocate (dz_lake )
+
+ deallocate (soil_s_v_alb )
+ deallocate (soil_d_v_alb )
+ deallocate (soil_s_n_alb )
+ deallocate (soil_d_n_alb )
+#ifdef HYPERSPECTRAL
+ deallocate (soil_alb )
+#endif
+
+ deallocate (vf_quartz )
+ deallocate (vf_gravels )
+ deallocate (vf_om )
+ deallocate (vf_sand )
+ deallocate (vf_clay )
+ deallocate (wf_gravels )
+ deallocate (wf_sand )
+ deallocate (wf_clay )
+ deallocate (wf_om )
+#ifdef DataAssimilation
+ deallocate (wf_silt )
+#endif
+ deallocate (OM_density )
+ deallocate (BD_all )
+ deallocate (wfc )
+ deallocate (porsl )
+ deallocate (psi0 )
+ deallocate (bsw )
+ deallocate (theta_r )
+ deallocate (BVIC )
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ deallocate (alpha_vgm )
+ deallocate (L_vgm )
+ deallocate (n_vgm )
+ deallocate (sc_vgm )
+ deallocate (fc_vgm )
+#endif
+ deallocate (soiltext )
+
+ deallocate (fsatmax )
+ deallocate (fsatdcf )
+ deallocate (topoweti )
+ deallocate (alp_twi )
+ deallocate (chi_twi )
+ deallocate (mu_twi )
+
+ deallocate (vic_b_infilt )
+ deallocate (vic_Dsmax )
+ deallocate (vic_Ds )
+ deallocate (vic_Ws )
+ deallocate (vic_c )
+
+ deallocate (hksati )
+ deallocate (csol )
+ deallocate (k_solids )
+ deallocate (dksatu )
+ deallocate (dksatf )
+ deallocate (dkdry )
+ deallocate (BA_alpha )
+ deallocate (BA_beta )
+
+ deallocate (htop )
+ deallocate (hbot )
+
+ deallocate (dbedrock )
+ deallocate (ibedrock )
+
+ deallocate (elvmean )
+ deallocate (elvstd )
+ deallocate (slpratio )
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ deallocate(slp_type_patches )
+ deallocate(svf_patches )
+ deallocate(asp_type_patches )
+ deallocate(area_type_patches )
+#ifdef SinglePoint
+ deallocate(sf_lut_patches )
+#else
+ deallocate(sf_curve_patches )
+#endif
+ deallocate(cur_patches )
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ deallocate(slp_type_patches )
+ deallocate(asp_type_patches )
+ deallocate(cur_patches )
+ ENDIF
+
+ ENDIF
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL deallocate_PFTimeInvariants
+#endif
+
+#ifdef BGC
+ CALL deallocate_BGCTimeInvariants
+#endif
+
+#ifdef URBAN_MODEL
+ CALL deallocate_UrbanTimeInvariants
+#endif
+ END SUBROUTINE deallocate_TimeInvariants
+
+#ifdef RangeCheck
+ SUBROUTINE check_TimeInvariants ()
+
+ USE MOD_SPMD_Task
+ USE MOD_RangeCheck
+ USE MOD_Namelist, only: DEF_Runoff_SCHEME, DEF_TOPMOD_method, DEF_USE_BEDROCK, &
+ DEF_USE_Forcing_Downscaling, DEF_USE_Forcing_Downscaling_Simple
+
+ IMPLICIT NONE
+
+ real(r8), allocatable :: tmpcheck(:,:)
+
+ IF (p_is_root) THEN
+ write(*,'(/,A29)') 'Checking Time Invariants ...'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ CALL check_vector_data ('lakedepth [m] ', lakedepth ) !
+ CALL check_vector_data ('dz_lake [m] ', dz_lake ) ! new lake scheme
+
+ CALL check_vector_data ('soil_s_v_alb [-] ', soil_s_v_alb) ! albedo of visible of the saturated soil
+ CALL check_vector_data ('soil_d_v_alb [-] ', soil_d_v_alb) ! albedo of visible of the dry soil
+ CALL check_vector_data ('soil_s_n_alb [-] ', soil_s_n_alb) ! albedo of near infrared of the saturated soil
+ CALL check_vector_data ('soil_d_n_alb [-] ', soil_d_n_alb) ! albedo of near infrared of the dry soil
+#ifdef HYPERSPECTRAL
+ CALL check_vector_data ('soil_alb [-] ', soil_alb ) ! hyper spectral soil albedo.
+#endif
+ CALL check_vector_data ('vf_quartz [m3/m3] ', vf_quartz ) ! volumetric fraction of quartz within mineral soil
+ CALL check_vector_data ('vf_gravels [m3/m3] ', vf_gravels ) ! volumetric fraction of gravels
+ CALL check_vector_data ('vf_sand [m3/m3] ', vf_sand ) ! volumetric fraction of sand
+ CALL check_vector_data ('vf_clay [m3/m3] ', vf_clay ) ! volumetric fraction of clay
+ CALL check_vector_data ('vf_om [m3/m3] ', vf_om ) ! volumetric fraction of organic matter
+ CALL check_vector_data ('wf_gravels [kg/kg] ', wf_gravels ) ! gravimetric fraction of gravels
+ CALL check_vector_data ('wf_sand [kg/kg] ', wf_sand ) ! gravimetric fraction of sand
+ CALL check_vector_data ('wf_clay [kg/kg] ', wf_clay ) ! gravimetric fraction of clay
+ CALL check_vector_data ('wf_om [kg/kg] ', wf_om ) ! gravimetric fraction of om
+ CALL check_vector_data ('OM_density [kg/m3] ', OM_density ) ! OM density
+ CALL check_vector_data ('BD_all [kg/m3] ', BD_all ) ! bulk density of soils
+ CALL check_vector_data ('wfc [m3/m3] ', wfc ) ! field capacity
+ CALL check_vector_data ('porsl [m3/m3] ', porsl ) ! fraction of soil that is voids [-]
+ CALL check_vector_data ('psi0 [mm] ', psi0 ) ! minimum soil suction [mm] (NOTE: "-" valued)
+ CALL check_vector_data ('bsw [-] ', bsw ) ! clapp and hornberger "b" parameter [-]
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ CALL check_vector_data ('theta_r [m3/m3] ', theta_r ) ! residual moisture content [-]
+ CALL check_vector_data ('alpha_vgm [-] ', alpha_vgm ) ! a parameter corresponding approximately to the inverse of the air-entry value
+ CALL check_vector_data ('L_vgm [-] ', L_vgm ) ! pore-connectivity parameter [dimensionless]
+ CALL check_vector_data ('n_vgm [-] ', n_vgm ) ! a shape parameter [dimensionless]
+ CALL check_vector_data ('sc_vgm [-] ', sc_vgm ) ! saturation at the air entry value in the classical vanGenuchten model [-]
+ CALL check_vector_data ('fc_vgm [-] ', fc_vgm ) ! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+
+ IF ((DEF_Runoff_SCHEME == 0) .and. (DEF_TOPMOD_method == 1)) THEN
+ CALL check_vector_data ('mean twi [log m] ', topoweti) !
+ CALL check_vector_data ('max sat frac area [-]', fsatmax ) !
+ CALL check_vector_data ('sat frac area decay ', fsatdcf ) !
+ ENDIF
+
+ IF ((DEF_Runoff_SCHEME == 0) .and. (DEF_TOPMOD_method == 2)) THEN
+ CALL check_vector_data ('mean twi [log m] ', topoweti) !
+ CALL check_vector_data ('twi alpha in 3-gamma ', alp_twi )
+ CALL check_vector_data ('twi chi in 3-gamma ', chi_twi )
+ CALL check_vector_data ('twi mu in 3-gamma ', mu_twi )
+ ENDIF
+
+ CALL check_vector_data ('hksati [mm/s] ', hksati ) ! hydraulic conductivity at saturation [mm h2o/s]
+ CALL check_vector_data ('csol [J/m3/K]', csol ) ! heat capacity of soil solids [J/(m3 K)]
+ CALL check_vector_data ('k_solids [W/m/K] ', k_solids ) ! thermal conductivity of soil solids [W/m-K]
+ CALL check_vector_data ('dksatu [W/m/K] ', dksatu ) ! thermal conductivity of unfrozen saturated soil [W/m-K]
+ CALL check_vector_data ('dksatf [W/m/K] ', dksatf ) ! thermal conductivity of frozen saturated soil [W/m-K]
+ CALL check_vector_data ('dkdry [W/m/K] ', dkdry ) ! thermal conductivity for dry soil [W/(m-K)]
+ CALL check_vector_data ('BA_alpha [-] ', BA_alpha ) ! alpha in Balland and Arp(2005) thermal conductivity scheme
+ CALL check_vector_data ('BA_beta [-] ', BA_beta ) ! beta in Balland and Arp(2005) thermal conductivity scheme
+
+ CALL check_vector_data ('soiltexture [-] ', soiltext, -1) !
+
+ CALL check_vector_data ('htop [m] ', htop )
+ CALL check_vector_data ('hbot [m] ', hbot )
+
+ IF(DEF_USE_BEDROCK)THEN
+ CALL check_vector_data ('dbedrock [m] ', dbedrock ) !
+ ENDIF
+
+ CALL check_vector_data ('elvmean [m] ', elvmean ) !
+ CALL check_vector_data ('elvstd [m] ', elvstd ) !
+ CALL check_vector_data ('slpratio [-] ', slpratio ) !
+
+ IF (DEF_Runoff_SCHEME == 3) THEN
+ CALL check_vector_data ('BVIC [-] ', BVIC ) !
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL check_vector_data ('slp_type [rad] ', slp_type_patches ) ! slope
+ CALL check_vector_data ('svf [-] ', svf_patches ) ! sky view factor
+ CALL check_vector_data ('asp_type [rad] ', asp_type_patches ) ! aspect
+ CALL check_vector_data ('area_type [-] ', area_type_patches) ! area percent
+ CALL check_vector_data ('cur [-] ', cur_patches )
+#ifdef SinglePoint
+ CALL check_vector_data ('sf_lut [-] ', sf_lut_patches ) ! shadow mask
+#else
+ IF (allocated(sf_curve_patches)) allocate(tmpcheck(size(sf_curve_patches,1),size(sf_curve_patches,3)))
+
+ IF (allocated(sf_curve_patches)) tmpcheck = sf_curve_patches(:,1,:)
+ CALL check_vector_data ('1 sf_curve p [-] ', tmpcheck) ! shadow mask
+ IF (allocated(sf_curve_patches)) tmpcheck = sf_curve_patches(:,2,:)
+ CALL check_vector_data ('2 sf_curve p [-] ', tmpcheck) ! shadow mask
+ IF (allocated(sf_curve_patches)) tmpcheck = sf_curve_patches(:,3,:)
+ CALL check_vector_data ('3 sf_curve p [-] ', tmpcheck) ! shadow mask
+
+ IF (allocated(tmpcheck)) deallocate(tmpcheck)
+#endif
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling_Simple) THEN
+ CALL check_vector_data ('slp_type [rad] ', slp_type_patches ) ! slope
+ CALL check_vector_data ('asp_type [-] ', asp_type_patches ) ! aspect fraction of direction of patches
+ CALL check_vector_data ('cur [-] ', cur_patches )
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write(*,'(/,A)') 'Checking Constants ...'
+ write(*,'(A,E20.10)') 'zlnd [m] ', zlnd ! roughness length for soil [m]
+ write(*,'(A,E20.10)') 'zsno [m] ', zsno ! roughness length for snow [m]
+ write(*,'(A,E20.10)') 'csoilc [-] ', csoilc ! drag coefficient for soil under canopy [-]
+ write(*,'(A,E20.10)') 'dewmx [mm] ', dewmx ! maximum dew
+ ! write(*,'(A,E20.10)') 'wtfact [-] ', wtfact ! fraction of model area with high water table
+ write(*,'(A,E20.10)') 'capr [-] ', capr ! tuning factor to turn first layer T into surface T
+ write(*,'(A,E20.10)') 'cnfac [-] ', cnfac ! Crank Nicholson factor between 0 and 1
+ write(*,'(A,E20.10)') 'ssi [-] ', ssi ! irreducible water saturation of snow
+ write(*,'(A,E20.10)') 'wimp [m3/m3]', wimp ! water impermeable IF porosity less than wimp
+ write(*,'(A,E20.10)') 'pondmx [mm] ', pondmx ! ponding depth (mm)
+ write(*,'(A,E20.10)') 'smpmax [mm] ', smpmax ! wilting point potential in mm
+ write(*,'(A,E20.10)') 'smpmin [mm] ', smpmin ! restriction for min of soil poten. (mm)
+ write(*,'(A,E20.10)') 'smpmax_hr [mm]', smpmax_hr ! wilting point potential in mm
+ write(*,'(A,E20.10)') 'smpmin_hr [mm]', smpmin_hr ! restriction for min of soil poten. (mm)
+ write(*,'(A,E20.10)') 'trsmx0 [mm/s] ', trsmx0 ! max transpiration for moist soil+100% veg. [mm/s]
+ write(*,'(A,E20.10)') 'tcrit [K] ', tcrit ! critical temp. to determine rain or snow
+ write(*,'(A,E20.10)') 'wetwatmax [mm]', wetwatmax ! maximum wetland water (mm)
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL check_PFTimeInvariants
+#endif
+
+#ifdef BGC
+ CALL check_BGCTimeInvariants
+#endif
+
+ END SUBROUTINE check_TimeInvariants
+#endif
+
+END MODULE MOD_Vars_TimeInvariants
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_TimeVariables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_TimeVariables.F90
new file mode 100644
index 0000000000..0b6d23dc00
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_Vars_TimeVariables.F90
@@ -0,0 +1,1679 @@
+#include
+
+!-----------------------------------------------------------------------
+! Created by Yongjiu Dai, 03/2014
+!-----------------------------------------------------------------------
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+MODULE MOD_Vars_PFTimeVariables
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Define PFT time variables
+!
+! Added by Hua Yuan, 08/2019
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_TimeManager
+#ifdef BGC
+ USE MOD_BGC_Vars_PFTimeVariables
+#endif
+
+ IMPLICIT NONE
+ SAVE
+!-----------------------------------------------------------------------
+! Time-varying state variables which required by restart run
+
+ ! for LULC_IGBP_PFT or LULC_IGBP_PC
+ real(r8), allocatable :: tleaf_p (:) !shaded leaf temperature [K]
+ real(r8), allocatable :: ldew_p (:) !depth of water on foliage [mm]
+ real(r8), allocatable :: ldew_rain_p (:) !depth of rain on foliage [mm]
+ real(r8), allocatable :: ldew_snow_p (:) !depth of snow on foliage [mm]
+ real(r8), allocatable :: fwet_snow_p (:) !vegetation snow fractional cover [-]
+ real(r8), allocatable :: sigf_p (:) !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), allocatable :: tlai_p (:) !leaf area index
+ real(r8), allocatable :: lai_p (:) !leaf area index
+ real(r8), allocatable :: laisun_p (:) !sunlit leaf area index
+ real(r8), allocatable :: laisha_p (:) !shaded leaf area index
+ real(r8), allocatable :: tsai_p (:) !stem area index
+ real(r8), allocatable :: sai_p (:) !stem area index
+ real(r8), allocatable :: ssun_p (:,:,:) !sunlit canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssha_p (:,:,:) !shaded canopy absorption for solar radiation (0-1)
+
+#ifdef HYPERSPECTRAL
+ real(r8), allocatable :: ssun_hires_p (:,:,:) !sunlit canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssha_hires_p (:,:,:) !shaded canopy absorption for solar radiation (0-1)
+#endif
+
+ real(r8), allocatable :: thermk_p (:) !canopy gap fraction for tir radiation
+ real(r8), allocatable :: fshade_p (:) !canopy shade fraction for tir radiation
+ real(r8), allocatable :: extkb_p (:) !(k, g(mu)/mu) direct solar extinction coefficient
+ real(r8), allocatable :: extkd_p (:) !diffuse and scattered diffuse PAR extinction coefficient
+ !TODO@yuan: to check the below for PC whether they are needed
+ real(r8), allocatable :: tref_p (:) !2 m height air temperature [kelvin]
+ real(r8), allocatable :: t2m_wmo_p (:) !2 m WMO air temperature [kelvin]
+ real(r8), allocatable :: qref_p (:) !2 m height air specific humidity
+ real(r8), allocatable :: rst_p (:) !canopy stomatal resistance (s/m)
+ real(r8), allocatable :: z0m_p (:) !effective roughness [m]
+! Plant Hydraulic variables
+ real(r8), allocatable :: vegwp_p (:,:) !vegetation water potential [mm]
+ real(r8), allocatable :: gs0sun_p (:) !working copy of sunlit stomata conductance
+ real(r8), allocatable :: gs0sha_p (:) !working copy of shaded stomata conductance
+! END plant hydraulic variables
+! Ozone Stress Variables
+ real(r8), allocatable :: o3coefv_sun_p(:) !Ozone stress factor for photosynthesis on sunlit leaf
+ real(r8), allocatable :: o3coefv_sha_p(:) !Ozone stress factor for photosynthesis on shaded leaf
+ real(r8), allocatable :: o3coefg_sun_p(:) !Ozone stress factor for stomata on sunlit leaf
+ real(r8), allocatable :: o3coefg_sha_p(:) !Ozone stress factor for stomata on shaded leaf
+ real(r8), allocatable :: lai_old_p (:) !lai in last time step
+ real(r8), allocatable :: o3uptakesun_p(:) !Ozone does, sunlit leaf (mmol O3/m^2)
+ real(r8), allocatable :: o3uptakesha_p(:) !Ozone does, shaded leaf (mmol O3/m^2)
+! END Ozone Stress Variables
+! irrigation variables
+ integer , allocatable :: irrig_method_p(:)!irrigation method
+! END irrigation variables
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_PFTimeVariables
+ PUBLIC :: deallocate_PFTimeVariables
+ PUBLIC :: READ_PFTimeVariables
+ PUBLIC :: WRITE_PFTimeVariables
+#ifdef RangeCheck
+ PUBLIC :: check_PFTimeVariables
+#endif
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_PFTimeVariables ()
+ !--------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpft] variables
+ !--------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+ allocate (tleaf_p (numpft)) ; tleaf_p (:) = spval !leaf temperature [K]
+ allocate (ldew_p (numpft)) ; ldew_p (:) = spval !depth of water on foliage [mm]
+ allocate (ldew_rain_p (numpft)) ; ldew_rain_p (:) = spval !depth of rain on foliage [mm]
+ allocate (ldew_snow_p (numpft)) ; ldew_snow_p (:) = spval !depth of snow on foliage [mm]
+ allocate (fwet_snow_p (numpft)) ; fwet_snow_p (:) = spval !vegetation snow fractional cover [-]
+ allocate (sigf_p (numpft)) ; sigf_p (:) = spval !fraction of veg cover, excluding snow-covered veg [-]
+ allocate (tlai_p (numpft)) ; tlai_p (:) = spval !leaf area index
+ allocate (lai_p (numpft)) ; lai_p (:) = spval !leaf area index
+ allocate (laisun_p (numpft)) ; laisun_p (:) = spval !leaf area index
+ allocate (laisha_p (numpft)) ; laisha_p (:) = spval !leaf area index
+ allocate (tsai_p (numpft)) ; tsai_p (:) = spval !stem area index
+ allocate (sai_p (numpft)) ; sai_p (:) = spval !stem area index
+ allocate (ssun_p (2,2,numpft)) ; ssun_p (:,:,:) = spval !sunlit canopy absorption for solar radiation (0-1)
+ allocate (ssha_p (2,2,numpft)) ; ssha_p (:,:,:) = spval !shaded canopy absorption for solar radiation (0-1)
+
+#ifdef HYPERSPECTRAL
+ allocate (ssun_hires_p (211,2,numpft)) ; ssun_hires_p (:,:,:) = spval !sunlit canopy absorption for solar radiation (0-1)
+ allocate (ssha_hires_p (211,2,numpft)) ; ssha_hires_p (:,:,:) = spval !shaded canopy absorption for solar radiation (0-1)
+#endif
+
+ allocate (thermk_p (numpft)) ; thermk_p (:) = spval !canopy gap fraction for tir radiation
+ allocate (fshade_p (numpft)) ; fshade_p (:) = spval !canopy shade fraction for tir radiation
+ allocate (extkb_p (numpft)) ; extkb_p (:) = spval !(k, g(mu)/mu) direct solar extinction coefficient
+ allocate (extkd_p (numpft)) ; extkd_p (:) = spval !diffuse and scattered diffuse PAR extinction coefficient
+ allocate (tref_p (numpft)) ; tref_p (:) = spval !2 m height air temperature [kelvin]
+ allocate (t2m_wmo_p (numpft)) ; t2m_wmo_p (:) = spval !2 m WMO air temperature [kelvin]
+ allocate (qref_p (numpft)) ; qref_p (:) = spval !2 m height air specific humidity
+ allocate (rst_p (numpft)) ; rst_p (:) = spval !canopy stomatal resistance (s/m)
+ allocate (z0m_p (numpft)) ; z0m_p (:) = spval !effective roughness [m]
+! Plant Hydraulic variables
+ allocate (vegwp_p(1:nvegwcs,numpft)); vegwp_p (:,:) = spval
+ allocate (gs0sun_p (numpft)); gs0sun_p (:) = spval
+ allocate (gs0sha_p (numpft)); gs0sha_p (:) = spval
+! END plant hydraulic variables
+! Allocate Ozone Stress Variables
+ allocate (o3coefv_sun_p(numpft)) ; o3coefv_sun_p(:) = spval !Ozone stress factor for photosynthesis on sunlit leaf
+ allocate (o3coefv_sha_p(numpft)) ; o3coefv_sha_p(:) = spval !Ozone stress factor for photosynthesis on shaded leaf
+ allocate (o3coefg_sun_p(numpft)) ; o3coefg_sun_p(:) = spval !Ozone stress factor for stomata on sunlit leaf
+ allocate (o3coefg_sha_p(numpft)) ; o3coefg_sha_p(:) = spval !Ozone stress factor for stomata on shaded leaf
+ allocate (lai_old_p (numpft)) ; lai_old_p (:) = spval !lai in last time step
+ allocate (o3uptakesun_p(numpft)) ; o3uptakesun_p(:) = spval !Ozone does, sunlit leaf (mmol O3/m^2)
+ allocate (o3uptakesha_p(numpft)) ; o3uptakesha_p(:) = spval !Ozone does, shaded leaf (mmol O3/m^2)
+! END allocate Ozone Stress Variables
+ allocate (irrig_method_p(numpft)); irrig_method_p(:) = 0! irrigation method
+
+ ENDIF
+ ENDIF
+
+#ifdef BGC
+ CALL allocate_BGCPFTimeVariables
+#endif
+
+ END SUBROUTINE allocate_PFTimeVariables
+
+ SUBROUTINE READ_PFTimeVariables (file_restart)
+
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, DEF_USE_IRRIGATION
+ USE MOD_NetCDFVector
+ USE MOD_LandPFT
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpft <= 0) RETURN
+#endif
+
+ CALL ncio_read_vector (file_restart, 'tleaf_p ', landpft, tleaf_p )
+ CALL ncio_read_vector (file_restart, 'ldew_p ', landpft, ldew_p )
+ CALL ncio_read_vector (file_restart, 'ldew_rain_p',landpft, ldew_rain_p )
+ CALL ncio_read_vector (file_restart, 'ldew_snow_p',landpft, ldew_snow_p )
+ CALL ncio_read_vector (file_restart, 'fwet_snow_p',landpft, fwet_snow_p )
+ CALL ncio_read_vector (file_restart, 'sigf_p ', landpft, sigf_p )
+ CALL ncio_read_vector (file_restart, 'tlai_p ', landpft, tlai_p )
+ CALL ncio_read_vector (file_restart, 'lai_p ', landpft, lai_p )
+! CALL ncio_read_vector (file_restart, 'laisun_p ', landpft, laisun_p )
+! CALL ncio_read_vector (file_restart, 'laisha_p ', landpft, laisha_p )
+ CALL ncio_read_vector (file_restart, 'tsai_p ', landpft, tsai_p )
+ CALL ncio_read_vector (file_restart, 'sai_p ', landpft, sai_p )
+ CALL ncio_read_vector (file_restart, 'ssun_p ', 2,2, landpft, ssun_p )
+ CALL ncio_read_vector (file_restart, 'ssha_p ', 2,2, landpft, ssha_p )
+
+#ifdef HYPERSPECTRAL
+ CALL ncio_read_vector (file_restart, 'ssun_hires_p ', 211,2, landpft, ssun_hires_p )
+ CALL ncio_read_vector (file_restart, 'ssha_hires_p ', 211,2, landpft, ssha_hires_p )
+#endif
+
+ CALL ncio_read_vector (file_restart, 'thermk_p ', landpft, thermk_p )
+ CALL ncio_read_vector (file_restart, 'fshade_p ', landpft, fshade_p )
+ CALL ncio_read_vector (file_restart, 'extkb_p ', landpft, extkb_p )
+ CALL ncio_read_vector (file_restart, 'extkd_p ', landpft, extkd_p )
+ CALL ncio_read_vector (file_restart, 'tref_p ', landpft, tref_p )
+ CALL ncio_read_vector (file_restart, 'qref_p ', landpft, qref_p )
+ CALL ncio_read_vector (file_restart, 'rst_p ', landpft, rst_p )
+ CALL ncio_read_vector (file_restart, 'z0m_p ', landpft, z0m_p )
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL ncio_read_vector (file_restart, 'vegwp_p ', nvegwcs, landpft, vegwp_p )
+ CALL ncio_read_vector (file_restart, 'gs0sun_p ', landpft, gs0sun_p )
+ CALL ncio_read_vector (file_restart, 'gs0sha_p ', landpft, gs0sha_p )
+ENDIF
+IF(DEF_USE_OZONESTRESS)THEN
+ CALL ncio_read_vector (file_restart, 'lai_old_p ', landpft, lai_old_p , defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'o3uptakesun_p', landpft, o3uptakesun_p, defval = 0._r8)
+ CALL ncio_read_vector (file_restart, 'o3uptakesha_p', landpft, o3uptakesha_p, defval = 0._r8)
+ENDIF
+IF(DEF_USE_IRRIGATION)THEN
+ CALL ncio_read_vector (file_restart,'irrig_method_p', landpft,irrig_method_p, defval = 0)
+ENDIF
+
+#ifdef BGC
+ CALL read_BGCPFTimeVariables (file_restart)
+#endif
+
+ END SUBROUTINE READ_PFTimeVariables
+
+ SUBROUTINE WRITE_PFTimeVariables (file_restart)
+
+ USE MOD_Namelist, only: DEF_REST_CompressLevel, DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, &
+ DEF_USE_IRRIGATION
+ USE MOD_LandPFT
+ USE MOD_NetCDFVector
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ ! Local variables
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpft <= 0) RETURN
+#endif
+
+ CALL ncio_create_file_vector (file_restart, landpft)
+ CALL ncio_define_dimension_vector (file_restart, landpft, 'pft')
+ CALL ncio_define_dimension_vector (file_restart, landpft, 'band', 2)
+ CALL ncio_define_dimension_vector (file_restart, landpft, 'rtyp', 2)
+
+ CALL ncio_define_dimension_vector (file_restart, landpft, 'wavelength', 211)
+
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL ncio_define_dimension_vector (file_restart, landpft, 'vegnodes', nvegwcs)
+ENDIF
+
+ CALL ncio_write_vector (file_restart, 'tleaf_p ', 'pft', landpft, tleaf_p , compress)
+ CALL ncio_write_vector (file_restart, 'ldew_p ', 'pft', landpft, ldew_p , compress)
+ CALL ncio_write_vector (file_restart, 'ldew_rain_p','pft',landpft,ldew_rain_p,compress)
+ CALL ncio_write_vector (file_restart, 'ldew_snow_p','pft',landpft,ldew_snow_p,compress)
+ CALL ncio_write_vector (file_restart, 'fwet_snow_p','pft',landpft,fwet_snow_p,compress)
+ CALL ncio_write_vector (file_restart, 'sigf_p ', 'pft', landpft, sigf_p , compress)
+ CALL ncio_write_vector (file_restart, 'tlai_p ', 'pft', landpft, tlai_p , compress)
+ CALL ncio_write_vector (file_restart, 'lai_p ', 'pft', landpft, lai_p , compress)
+! CALL ncio_write_vector (file_restart, 'laisun_p ', 'pft', landpft, laisun_p , compress)
+! CALL ncio_write_vector (file_restart, 'laisha_p ', 'pft', landpft, laisha_p , compress)
+ CALL ncio_write_vector (file_restart, 'tsai_p ', 'pft', landpft, tsai_p , compress)
+ CALL ncio_write_vector (file_restart, 'sai_p ', 'pft', landpft, sai_p , compress)
+ CALL ncio_write_vector (file_restart, 'ssun_p ', 'band', 2, 'rtyp', 2, 'pft', landpft, ssun_p, compress)
+ CALL ncio_write_vector (file_restart, 'ssha_p ', 'band', 2, 'rtyp', 2, 'pft', landpft, ssha_p, compress)
+
+#ifdef HYPERSPECTRAL
+ CALL ncio_write_vector (file_restart, 'ssun_hires_p', 'wavelength', 211, 'rtyp', 2, 'pft', landpft, ssun_hires_p, compress)
+ CALL ncio_write_vector (file_restart, 'ssha_hires_p', 'wavelength', 211, 'rtyp', 2, 'pft', landpft, ssha_hires_p, compress)
+#endif
+
+ CALL ncio_write_vector (file_restart, 'thermk_p ', 'pft', landpft, thermk_p , compress)
+ CALL ncio_write_vector (file_restart, 'fshade_p ', 'pft', landpft, fshade_p , compress)
+ CALL ncio_write_vector (file_restart, 'extkb_p ', 'pft', landpft, extkb_p , compress)
+ CALL ncio_write_vector (file_restart, 'extkd_p ', 'pft', landpft, extkd_p , compress)
+ CALL ncio_write_vector (file_restart, 'tref_p ', 'pft', landpft, tref_p , compress)
+ CALL ncio_write_vector (file_restart, 'qref_p ', 'pft', landpft, qref_p , compress)
+ CALL ncio_write_vector (file_restart, 'rst_p ', 'pft', landpft, rst_p , compress)
+ CALL ncio_write_vector (file_restart, 'z0m_p ', 'pft', landpft, z0m_p , compress)
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL ncio_write_vector (file_restart, 'vegwp_p ', 'vegnodes', nvegwcs, 'pft', landpft, vegwp_p, compress)
+ CALL ncio_write_vector (file_restart, 'gs0sun_p ', 'pft', landpft, gs0sun_p , compress)
+ CALL ncio_write_vector (file_restart, 'gs0sha_p ', 'pft', landpft, gs0sha_p , compress)
+ENDIF
+IF(DEF_USE_OZONESTRESS)THEN
+ CALL ncio_write_vector (file_restart, 'lai_old_p ', 'pft', landpft, lai_old_p , compress)
+ CALL ncio_write_vector (file_restart, 'o3uptakesun_p', 'pft', landpft, o3uptakesun_p, compress)
+ CALL ncio_write_vector (file_restart, 'o3uptakesha_p', 'pft', landpft, o3uptakesha_p, compress)
+ENDIF
+IF(DEF_USE_IRRIGATION)THEN
+ CALL ncio_write_vector (file_restart,'irrig_method_p','pft', landpft, irrig_method_p, compress)
+ENDIF
+
+#ifdef BGC
+ CALL WRITE_BGCPFTimeVariables (file_restart)
+#endif
+
+ END SUBROUTINE WRITE_PFTimeVariables
+
+
+ SUBROUTINE deallocate_PFTimeVariables
+ !--------------------------------------------------------------------
+ ! Deallocates memory for CoLM 1d [numpft/numpc] variables
+ !--------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandPFT
+
+ IF (p_is_compute) THEN
+ IF (numpft > 0) THEN
+ deallocate (tleaf_p ) ! leaf temperature [K]
+ deallocate (ldew_p ) ! depth of water on foliage [mm]
+ deallocate (ldew_rain_p ) ! depth of rain on foliage [mm]
+ deallocate (ldew_snow_p ) ! depth of snow on foliage [mm]
+ deallocate (fwet_snow_p ) ! vegetation snow fractional cover [-]
+ deallocate (sigf_p ) ! fraction of veg cover, excluding snow-covered veg [-]
+ deallocate (tlai_p ) ! leaf area index
+ deallocate (lai_p ) ! leaf area index
+ deallocate (laisun_p ) ! leaf area index
+ deallocate (laisha_p ) ! leaf area index
+ deallocate (tsai_p ) ! stem area index
+ deallocate (sai_p ) ! stem area index
+ deallocate (ssun_p ) ! sunlit canopy absorption for solar radiation (0-1)
+ deallocate (ssha_p ) ! shaded canopy absorption for solar radiation (0-1)
+
+#ifdef HYPERSPECTRAL
+ deallocate (ssun_hires_p ) ! sunlit canopy absorption for solar radiation (0-1)
+ deallocate (ssha_hires_p ) ! shaded canopy absorption for solar radiation (0-1)
+#endif
+
+ deallocate (thermk_p ) ! canopy gap fraction for tir radiation
+ deallocate (fshade_p ) ! canopy gap fraction for tir radiation
+ deallocate (extkb_p ) ! (k, g(mu)/mu) direct solar extinction coefficient
+ deallocate (extkd_p ) ! diffuse and scattered diffuse PAR extinction coefficient
+ deallocate (tref_p ) ! 2 m height air temperature [kelvin]
+ deallocate (t2m_wmo_p ) ! 2 m WMO air temperature [kelvin]
+ deallocate (qref_p ) ! 2 m height air specific humidity
+ deallocate (rst_p ) ! canopy stomatal resistance (s/m)
+ deallocate (z0m_p ) ! effective roughness [m]
+! Plant Hydraulic variables
+ deallocate (vegwp_p ) ! vegetation water potential [mm]
+ deallocate (gs0sun_p ) ! working copy of sunlit stomata conductance
+ deallocate (gs0sha_p ) ! working copy of shaded stomata conductance
+! END plant hydraulic variables
+! Ozone Stress variables
+ deallocate (o3coefv_sun_p ) ! Ozone stress factor for photosynthesis on sunlit leaf
+ deallocate (o3coefv_sha_p ) ! Ozone stress factor for photosynthesis on shaded leaf
+ deallocate (o3coefg_sun_p ) ! Ozone stress factor for stomata on sunlit leaf
+ deallocate (o3coefg_sha_p ) ! Ozone stress factor for stomata on shaded leaf
+ deallocate (lai_old_p ) ! lai in last time step
+ deallocate (o3uptakesun_p ) ! Ozone does, sunlit leaf (mmol O3/m^2)
+ deallocate (o3uptakesha_p ) ! Ozone does, shaded leaf (mmol O3/m^2)
+ deallocate (irrig_method_p )
+! Ozone Stress variables
+ ENDIF
+ ENDIF
+
+#ifdef BGC
+ CALL deallocate_BGCPFTimeVariables
+#endif
+
+ END SUBROUTINE deallocate_PFTimeVariables
+
+#ifdef RangeCheck
+ SUBROUTINE check_PFTimeVariables
+
+ USE MOD_RangeCheck
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, DEF_USE_IRRIGATION
+
+ IMPLICIT NONE
+
+ CALL check_vector_data (' tleaf_p', tleaf_p )
+ CALL check_vector_data (' ldew_p', ldew_p )
+ CALL check_vector_data (' ldew_rain_p', ldew_rain_p )
+ CALL check_vector_data (' ldew_snow_p', ldew_snow_p )
+ CALL check_vector_data (' fwet_snow_p', fwet_snow_p )
+ CALL check_vector_data (' sigf_p', sigf_p )
+ CALL check_vector_data (' tlai_p', tlai_p )
+ CALL check_vector_data (' lai_p', lai_p )
+ CALL check_vector_data (' laisun_p', lai_p )
+ CALL check_vector_data (' laisha_p', lai_p )
+ CALL check_vector_data (' tsai_p', tsai_p )
+ CALL check_vector_data (' sai_p', sai_p )
+ CALL check_vector_data (' ssun_p', ssun_p )
+ CALL check_vector_data (' ssha_p', ssha_p )
+ CALL check_vector_data (' thermk_p', thermk_p )
+ CALL check_vector_data (' fshade_p', fshade_p )
+ CALL check_vector_data (' extkb_p', extkb_p )
+ CALL check_vector_data (' extkd_p', extkd_p )
+ CALL check_vector_data (' tref_p', tref_p )
+ CALL check_vector_data (' t2m_wmo_p', t2m_wmo_p )
+ CALL check_vector_data (' qref_p', qref_p )
+ CALL check_vector_data (' rst_p', rst_p )
+ CALL check_vector_data (' z0m_p', z0m_p )
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL check_vector_data (' vegwp_p', vegwp_p )
+ CALL check_vector_data (' gs0sun_p', gs0sun_p )
+ CALL check_vector_data (' gs0sha_p', gs0sha_p )
+ENDIF
+IF(DEF_USE_OZONESTRESS)THEN
+ CALL check_vector_data (' o3coefv_sun_p', o3coefv_sun_p )
+ CALL check_vector_data (' o3coefv_sha_p', o3coefv_sha_p )
+ CALL check_vector_data (' o3coefg_sun_p', o3coefg_sun_p )
+ CALL check_vector_data (' o3coefg_sha_p', o3coefg_sha_p )
+ CALL check_vector_data (' lai_old_p', lai_old_p )
+ CALL check_vector_data (' o3uptakesun_p', o3uptakesun_p )
+ CALL check_vector_data (' o3uptakesha_p', o3uptakesha_p )
+ENDIF
+IF(DEF_USE_IRRIGATION)THEN
+ CALL check_vector_data ('irrig_method_p', irrig_method_p )
+ENDIF
+
+#ifdef BGC
+ CALL check_BGCPFTimeVariables
+#endif
+
+ END SUBROUTINE check_PFTimeVariables
+#endif
+
+END MODULE MOD_Vars_PFTimeVariables
+#endif
+
+
+MODULE MOD_Vars_TimeVariables
+! -------------------------------
+! Created by Yongjiu Dai, 03/2014
+! -------------------------------
+
+ USE MOD_Precision
+ USE MOD_TimeManager
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_Vars_PFTimeVariables
+#endif
+#ifdef BGC
+ USE MOD_BGC_Vars_TimeVariables
+#endif
+#ifdef CatchLateralFlow
+ USE MOD_Catch_Vars_TimeVariables
+#endif
+#ifdef GridRiverLakeFlow
+ USE MOD_Grid_RiverLakeTimeVars
+#endif
+#ifdef URBAN_MODEL
+ USE MOD_Urban_Vars_TimeVariables
+#endif
+#ifdef EXTERNAL_LAKE
+ USE MOD_Lake_TimeVars
+#endif
+#ifdef DataAssimilation
+ USE MOD_DA_Vars_TimeVariables
+#endif
+
+ IMPLICIT NONE
+ SAVE
+! -----------------------------------------------------------------
+! Time-varying state variables which required by restart run
+ real(r8), allocatable :: z_sno (:,:) ! node depth [m]
+ real(r8), allocatable :: dz_sno (:,:) ! interface depth [m]
+ real(r8), allocatable :: t_soisno (:,:) ! soil temperature [K]
+ real(r8), allocatable :: wliq_soisno (:,:) ! liquid water in layers [kg/m2]
+ real(r8), allocatable :: wice_soisno (:,:) ! ice lens in layers [kg/m2]
+ real(r8), allocatable :: h2osoi (:,:) ! volumetric soil water in layers [m3/m3]
+ real(r8), allocatable :: smp (:,:) ! soil matrix potential [mm]
+ real(r8), allocatable :: hk (:,:) ! hydraulic conductivity [mm h2o/s]
+ real(r8), allocatable :: rootr (:,:) ! transpiration contribution fraction from different layers
+ real(r8), allocatable :: rootflux (:,:) ! water exchange between soil and root. Positive: soil->root [?]
+!Plant Hydraulic variables
+ real(r8), allocatable :: vegwp (:,:) ! vegetation water potential [mm]
+ real(r8), allocatable :: gs0sun (:) ! working copy of sunlit stomata conductance
+ real(r8), allocatable :: gs0sha (:) ! working copy of shaded stomata conductance
+!END plant hydraulic variables
+!Ozone stress variables
+ real(r8), allocatable :: o3coefv_sun (:) ! Ozone stress factor for photosynthesis on sunlit leaf
+ real(r8), allocatable :: o3coefv_sha (:) ! Ozone stress factor for photosynthesis on shaded leaf
+ real(r8), allocatable :: o3coefg_sun (:) ! Ozone stress factor for stomata on sunlit leaf
+ real(r8), allocatable :: o3coefg_sha (:) ! Ozone stress factor for stomata on shaded leaf
+ real(r8), allocatable :: lai_old (:) ! lai in last time step
+ real(r8), allocatable :: o3uptakesun (:) ! Ozone does, sunlit leaf (mmol O3/m^2)
+ real(r8), allocatable :: o3uptakesha (:) ! Ozone does, shaded leaf (mmol O3/m^2)
+!END ozone stress variables
+ real(r8), allocatable :: rstfacsun_out (:) ! factor of soil water stress on sunlit leaf
+ real(r8), allocatable :: rstfacsha_out (:) ! factor of soil water stress on shaded leaf
+ real(r8), allocatable :: gssun_out (:) ! stomata conductance on sunlit leaf
+ real(r8), allocatable :: gssha_out (:) ! stomata conductance on shaded leaf
+ real(r8), allocatable :: t_grnd (:) ! ground surface temperature [K]
+
+ real(r8), allocatable :: assimsun_out (:) ! diagnostic sunlit leaf assim value for output
+ real(r8), allocatable :: assimsha_out (:) ! diagnostic sunlit leaf etr value for output
+ real(r8), allocatable :: etrsun_out (:) ! diagnostic shaded leaf assim for output
+ real(r8), allocatable :: etrsha_out (:) ! diagnostic shaded leaf etr for output
+
+ real(r8), allocatable :: tleaf (:) ! leaf temperature [K]
+ real(r8), allocatable :: ldew (:) ! depth of water on foliage [mm]
+ real(r8), allocatable :: ldew_rain (:) ! depth of rain on foliage [mm]
+ real(r8), allocatable :: ldew_snow (:) ! depth of rain on foliage [mm]
+ real(r8), allocatable :: fwet_snow (:) ! vegetation snow fractional cover [-]
+ real(r8), allocatable :: sag (:) ! non dimensional snow age [-]
+ real(r8), allocatable :: scv (:) ! snow cover, water equivalent [mm]
+ real(r8), allocatable :: snowdp (:) ! snow depth [meter]
+ real(r8), allocatable :: fveg (:) ! fraction of vegetation cover
+ real(r8), allocatable :: fsno (:) ! fraction of snow cover on ground
+ real(r8), allocatable :: sigf (:) ! fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), allocatable :: green (:) ! leaf greenness
+ real(r8), allocatable :: tlai (:) ! leaf area index
+ real(r8), allocatable :: lai (:) ! leaf area index
+ real(r8), allocatable :: laisun (:) ! leaf area index for sunlit leaf
+ real(r8), allocatable :: laisha (:) ! leaf area index for shaded leaf
+ real(r8), allocatable :: tsai (:) ! stem area index
+ real(r8), allocatable :: sai (:) ! stem area index
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ real(r8), allocatable :: lai_enftemp (:) ! lai for needleleaf evergreen temperate tree (m2 m-2)
+ real(r8), allocatable :: lai_enfboreal (:) ! lai for needleleaf evergreen boreal tree (m2 m-2)
+ real(r8), allocatable :: lai_dnfboreal (:) ! lai for needleleaf deciduous boreal tree (m2 m-2)
+ real(r8), allocatable :: lai_ebftrop (:) ! lai for broadleaf evergreen tropical tree (m2 m-2)
+ real(r8), allocatable :: lai_ebftemp (:) ! lai for broadleaf evergreen temperate tree (m2 m-2)
+ real(r8), allocatable :: lai_dbftrop (:) ! lai for broadleaf deciduous tropical tree (m2 m-2)
+ real(r8), allocatable :: lai_dbftemp (:) ! lai for broadleaf deciduous temperate tree (m2 m-2)
+ real(r8), allocatable :: lai_dbfboreal (:) ! lai for broadleaf deciduous boreal tree (m2 m-2)
+ real(r8), allocatable :: lai_ebstemp (:) ! lai for broadleaf evergreen temperate shrub (m2 m-2)
+ real(r8), allocatable :: lai_dbstemp (:) ! lai for broadleaf deciduous temperate shrub (m2 m-2)
+ real(r8), allocatable :: lai_dbsboreal (:) ! lai for broadleaf deciduous boreal shrub (m2 m-2)
+ real(r8), allocatable :: lai_c3arcgrass(:) ! lai for c3 arctic grass (m2 m-2)
+ real(r8), allocatable :: lai_c3grass (:) ! lai for c3 grass (m2 m-2)
+ real(r8), allocatable :: lai_c4grass (:) ! lai for c4 grass (m2 m-2)
+#endif
+
+ real(r8), allocatable :: coszen (:) ! cosine of solar zenith angle
+ real(r8), allocatable :: alb (:,:,:) ! averaged albedo [-]
+ real(r8), allocatable :: ssun (:,:,:) ! sunlit canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssha (:,:,:) ! shaded canopy absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssoi (:,:,:) ! soil absorption for solar radiation (0-1)
+ real(r8), allocatable :: ssno (:,:,:) ! snow absorption for solar radiation (0-1)
+#ifdef HYPERSPECTRAL
+ ! new variables for hyperspectral scheme
+ real(r8), allocatable :: alb_hires (:,:,:) ! averaged albedo [-]
+ real(r8), allocatable :: reflectance_out (:,:,:) ! averaged albedo [-]
+ real(r8), allocatable :: transmittance_out (:,:,:) ! averaged albedo [-]
+#endif
+ real(r8), allocatable :: thermk (:) ! canopy gap fraction for tir radiation
+ real(r8), allocatable :: extkb (:) ! (k, g(mu)/mu) direct solar extinction coefficient
+ real(r8), allocatable :: extkd (:) ! diffuse and scattered diffuse PAR extinction coefficient
+ real(r8), allocatable :: zwt (:) ! the depth to water table [m]
+ real(r8), allocatable :: wa (:) ! water storage in aquifer [mm]
+ real(r8), allocatable :: wetwat (:) ! water storage in wetland [mm]
+ real(r8), allocatable :: wat (:) ! total water storage [mm]
+ real(r8), allocatable :: wdsrf (:) ! depth of surface water [mm]
+ real(r8), allocatable :: rss (:) ! soil surface resistance [s/m]
+
+ real(r8), allocatable :: t_lake (:,:) ! lake layer temperature [K]
+ real(r8), allocatable :: lake_icefrac(:,:) ! lake mass fraction of lake layer that is frozen
+ real(r8), allocatable :: savedtke1 (:) ! top level eddy conductivity (W/m K)
+
+ real(r8), allocatable :: snw_rds (:,:) ! effective grain radius (col,lyr) [microns, m-6]
+ real(r8), allocatable :: mss_bcpho (:,:) ! mass of hydrophobic BC in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_bcphi (:,:) ! mass of hydrophillic BC in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_ocpho (:,:) ! mass of hydrophobic OC in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_ocphi (:,:) ! mass of hydrophillic OC in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_dst1 (:,:) ! mass of dust species 1 in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_dst2 (:,:) ! mass of dust species 2 in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_dst3 (:,:) ! mass of dust species 3 in snow (col,lyr) [kg]
+ real(r8), allocatable :: mss_dst4 (:,:) ! mass of dust species 4 in snow (col,lyr) [kg]
+ real(r8), allocatable :: ssno_lyr(:,:,:,:) ! snow layer absorption [-]
+
+ real(r8), allocatable :: trad (:) ! radiative temperature of surface [K]
+ real(r8), allocatable :: tref (:) ! 2 m height air temperature [kelvin]
+ real(r8), allocatable :: t2m_wmo (:) ! 2 m WMO air temperature [kelvin]
+ real(r8), allocatable :: qref (:) ! 2 m height air specific humidity
+ real(r8), allocatable :: qsfc (:) ! bulk surface/ground specific humidity [kg/kg]
+ real(r8), allocatable :: rst (:) ! canopy stomatal resistance (s/m)
+ real(r8), allocatable :: emis (:) ! averaged bulk surface emissivity
+ real(r8), allocatable :: z0m (:) ! effective roughness [m]
+ real(r8), allocatable :: displa (:) ! zero displacement height [m]
+ real(r8), allocatable :: zol (:) ! dimensionless height (z/L) used in Monin-Obukhov theory
+ real(r8), allocatable :: rib (:) ! bulk Richardson number in surface layer
+ real(r8), allocatable :: ustar (:) ! u* in similarity theory [m/s]
+ real(r8), allocatable :: qstar (:) ! q* in similarity theory [kg/kg]
+ real(r8), allocatable :: tstar (:) ! t* in similarity theory [K]
+ real(r8), allocatable :: fm (:) ! integral of profile FUNCTION for momentum
+ real(r8), allocatable :: fh (:) ! integral of profile FUNCTION for heat
+ real(r8), allocatable :: fq (:) ! integral of profile FUNCTION for moisture
+
+ real(r8), allocatable :: irrig_rate (:) ! irrigation rate [mm s-1]
+ real(r8), allocatable :: actual_irrig (:) ! actual irrigation amount [kg/m2]
+ real(r8), allocatable :: deficit_irrig (:) ! irrigation amount [kg/m2]
+ real(r8), allocatable :: sum_irrig (:) ! total irrigation amount [kg/m2]
+ real(r8), allocatable :: sum_deficit_irrig (:) ! total irrigation amount demand [kg/m2]
+ real(r8), allocatable :: sum_irrig_count (:) ! total irrigation counts [-]
+ integer , allocatable :: n_irrig_steps_left (:) ! left steps for once irrigation [-]
+ real(r8), allocatable :: waterstorage (:) ! water of water storage pool (from reservoir and river) [kg/m2]
+ real(r8), allocatable :: waterstorage_supply (:) ! irrigation supply from water storage pool [kg/m2]
+ real(r8), allocatable :: groundwater_demand (:) ! irrigation demand for ground water [kg/m2]
+ real(r8), allocatable :: groundwater_supply (:) ! irrigation supply from ground water [kg/m2]
+ real(r8), allocatable :: reservoirriver_demand(:)! irrigation demand for reservoir or river [kg/m2]
+ real(r8), allocatable :: reservoirriver_supply(:)! irrigation supply from reservoir or river [kg/m2]
+ real(r8), allocatable :: reservoir_supply (:)! irrigation supply from reservoir [kg/m2]
+ real(r8), allocatable :: river_supply (:)! irrigation supply from river [kg/m2]
+ real(r8), allocatable :: runoff_supply (:)! irrigation supply from runoff [kg/m2]
+ real(r8), allocatable :: tairday (:) ! daily mean temperature [degree C]
+ real(r8), allocatable :: usday (:) ! daily mean wind component in eastward direction [m/s]
+ real(r8), allocatable :: vsday (:) ! daily mean wind component in northward direction [m/s]
+ real(r8), allocatable :: pairday (:) ! daily mean pressure [kPa]
+ real(r8), allocatable :: rnetday (:) ! daily net radiation flux [MJ/m2/day]
+ real(r8), allocatable :: fgrndday (:) ! daily ground heat flux [MJ/m2/day]
+ real(r8), allocatable :: potential_evapotranspiration (:) ! daily potential evapotranspiration [mm/day]
+
+ integer , allocatable :: irrig_method_corn (:) ! irrigation method for corn (0-3)
+ integer , allocatable :: irrig_method_swheat (:) ! irrigation method for spring wheat (0-3)
+ integer , allocatable :: irrig_method_wwheat (:) ! irrigation method for winter wheat (0-3)
+ integer , allocatable :: irrig_method_soybean (:) ! irrigation method for soybean (0-3)
+ integer , allocatable :: irrig_method_cotton (:) ! irrigation method for cotton (0-3)
+ integer , allocatable :: irrig_method_rice1 (:) ! irrigation method for rice1 (0-3)
+ integer , allocatable :: irrig_method_rice2 (:) ! irrigation method for rice2 (0-3)
+ integer , allocatable :: irrig_method_sugarcane (:) ! irrigation method for sugarcane (0-3)
+
+ real(r8), allocatable :: irrig_gw_alloc (:) ! irrigation demand allocated to groundwater [kg/kg]
+ real(r8), allocatable :: irrig_sw_alloc (:) ! irrigation demand allocated to surfacewater [kg/kg]
+ real(r8), allocatable :: zwt_stand (:) ! initial the depth to water table [m]
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_TimeVariables
+ PUBLIC :: deallocate_TimeVariables
+ PUBLIC :: READ_TimeVariables
+ PUBLIC :: WRITE_TimeVariables
+#ifdef RangeCheck
+ PUBLIC :: check_TimeVariables
+#endif
+
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_TimeVariables
+ !--------------------------------------------------------------------
+ ! Allocates memory for CoLM 1d [numpatch] variables
+ !--------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ allocate (z_sno (maxsnl+1:0, numpatch)); z_sno (:,:) = spval
+ allocate (dz_sno (maxsnl+1:0, numpatch)); dz_sno (:,:) = spval
+ allocate (t_soisno (maxsnl+1:nl_soil,numpatch)); t_soisno (:,:) = spval
+ allocate (wliq_soisno(maxsnl+1:nl_soil,numpatch)); wliq_soisno (:,:) = spval
+ allocate (wice_soisno(maxsnl+1:nl_soil,numpatch)); wice_soisno (:,:) = spval
+ allocate (smp (1:nl_soil,numpatch)); smp (:,:) = spval
+ allocate (hk (1:nl_soil,numpatch)); hk (:,:) = spval
+ allocate (h2osoi (1:nl_soil,numpatch)); h2osoi (:,:) = spval
+ allocate (rootr (1:nl_soil,numpatch)); rootr (:,:) = spval
+ allocate (rootflux (1:nl_soil,numpatch)); rootflux (:,:) = spval
+!Plant Hydraulic variables
+ allocate (vegwp (1:nvegwcs,numpatch)); vegwp (:,:) = spval
+ allocate (gs0sun (numpatch)); gs0sun (:) = spval
+ allocate (gs0sha (numpatch)); gs0sha (:) = spval
+!END plant hydraulic variables
+!Ozone Stress variables
+ allocate (o3coefv_sun (numpatch)); o3coefv_sun (:) = spval
+ allocate (o3coefv_sha (numpatch)); o3coefv_sha (:) = spval
+ allocate (o3coefg_sun (numpatch)); o3coefg_sun (:) = spval
+ allocate (o3coefg_sha (numpatch)); o3coefg_sha (:) = spval
+ allocate (lai_old (numpatch)); lai_old (:) = spval
+ allocate (o3uptakesun (numpatch)); o3uptakesun (:) = spval
+ allocate (o3uptakesha (numpatch)); o3uptakesha (:) = spval
+!END ozone stress variables
+
+ allocate (rstfacsun_out (numpatch)); rstfacsun_out (:) = spval
+ allocate (rstfacsha_out (numpatch)); rstfacsha_out (:) = spval
+ allocate (gssun_out (numpatch)); gssun_out (:) = spval
+ allocate (gssha_out (numpatch)); gssha_out (:) = spval
+ allocate (assimsun_out (numpatch)); assimsun_out (:) = spval
+ allocate (assimsha_out (numpatch)); assimsha_out (:) = spval
+ allocate (etrsun_out (numpatch)); etrsun_out (:) = spval
+ allocate (etrsha_out (numpatch)); etrsha_out (:) = spval
+
+ allocate (t_grnd (numpatch)); t_grnd (:) = spval
+ allocate (tleaf (numpatch)); tleaf (:) = spval
+ allocate (ldew (numpatch)); ldew (:) = spval
+ allocate (ldew_rain (numpatch)); ldew_rain (:) = spval
+ allocate (ldew_snow (numpatch)); ldew_snow (:) = spval
+ allocate (fwet_snow (numpatch)); fwet_snow (:) = spval
+ allocate (sag (numpatch)); sag (:) = spval
+ allocate (scv (numpatch)); scv (:) = spval
+ allocate (snowdp (numpatch)); snowdp (:) = spval
+ allocate (fveg (numpatch)); fveg (:) = spval
+ allocate (fsno (numpatch)); fsno (:) = spval
+ allocate (sigf (numpatch)); sigf (:) = spval
+ allocate (green (numpatch)); green (:) = spval
+ allocate (tlai (numpatch)); tlai (:) = spval
+ allocate (lai (numpatch)); lai (:) = spval
+ allocate (laisun (numpatch)); laisun (:) = spval
+ allocate (laisha (numpatch)); laisha (:) = spval
+ allocate (tsai (numpatch)); tsai (:) = spval
+ allocate (sai (numpatch)); sai (:) = spval
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ allocate (lai_enftemp (numpatch)); lai_enftemp (:) = spval
+ allocate (lai_enfboreal (numpatch)); lai_enfboreal (:) = spval
+ allocate (lai_dnfboreal (numpatch)); lai_dnfboreal (:) = spval
+ allocate (lai_ebftrop (numpatch)); lai_ebftrop (:) = spval
+ allocate (lai_ebftemp (numpatch)); lai_ebftemp (:) = spval
+ allocate (lai_dbftrop (numpatch)); lai_dbftrop (:) = spval
+ allocate (lai_dbftemp (numpatch)); lai_dbftemp (:) = spval
+ allocate (lai_dbfboreal (numpatch)); lai_dbfboreal (:) = spval
+ allocate (lai_ebstemp (numpatch)); lai_ebstemp (:) = spval
+ allocate (lai_dbstemp (numpatch)); lai_dbstemp (:) = spval
+ allocate (lai_dbsboreal (numpatch)); lai_dbsboreal (:) = spval
+ allocate (lai_c3arcgrass (numpatch)); lai_c3arcgrass(:) = spval
+ allocate (lai_c3grass (numpatch)); lai_c3grass (:) = spval
+ allocate (lai_c4grass (numpatch)); lai_c4grass (:) = spval
+#endif
+ allocate (coszen (numpatch)); coszen (:) = spval
+ allocate (alb (2,2,numpatch)); alb (:,:,:) = spval
+ allocate (ssun (2,2,numpatch)); ssun (:,:,:) = spval
+ allocate (ssha (2,2,numpatch)); ssha (:,:,:) = spval
+ allocate (ssoi (2,2,numpatch)); ssoi (:,:,:) = spval
+ allocate (ssno (2,2,numpatch)); ssno (:,:,:) = spval
+#ifdef HYPERSPECTRAL
+ ! high resolution parameters
+ allocate (alb_hires (211,2,numpatch)); alb_hires (:,:,:) = spval
+ allocate (reflectance_out (211,0:15,numpatch)); reflectance_out (:,:,:) = spval
+ allocate (transmittance_out (211,0:15,numpatch)); transmittance_out(:,:,:) = spval
+#endif
+ allocate (thermk (numpatch)); thermk (:) = spval
+ allocate (extkb (numpatch)); extkb (:) = spval
+ allocate (extkd (numpatch)); extkd (:) = spval
+ allocate (zwt (numpatch)); zwt (:) = spval
+ allocate (wa (numpatch)); wa (:) = spval
+ allocate (wetwat (numpatch)); wetwat (:) = spval
+ allocate (wat (numpatch)); wat (:) = spval
+ allocate (wdsrf (numpatch)); wdsrf (:) = spval
+ allocate (rss (numpatch)); rss (:) = spval
+ allocate (t_lake (nl_lake,numpatch)); t_lake (:,:) = spval
+ allocate (lake_icefrac (nl_lake,numpatch)); lake_icefrac(:,:) = spval
+ allocate (savedtke1 (numpatch)); savedtke1 (:) = spval
+
+ allocate (snw_rds (maxsnl+1:0,numpatch)); snw_rds (:,:) = spval
+ allocate (mss_bcpho (maxsnl+1:0,numpatch)); mss_bcpho (:,:) = spval
+ allocate (mss_bcphi (maxsnl+1:0,numpatch)); mss_bcphi (:,:) = spval
+ allocate (mss_ocpho (maxsnl+1:0,numpatch)); mss_ocpho (:,:) = spval
+ allocate (mss_ocphi (maxsnl+1:0,numpatch)); mss_ocphi (:,:) = spval
+ allocate (mss_dst1 (maxsnl+1:0,numpatch)); mss_dst1 (:,:) = spval
+ allocate (mss_dst2 (maxsnl+1:0,numpatch)); mss_dst2 (:,:) = spval
+ allocate (mss_dst3 (maxsnl+1:0,numpatch)); mss_dst3 (:,:) = spval
+ allocate (mss_dst4 (maxsnl+1:0,numpatch)); mss_dst4 (:,:) = spval
+ allocate (ssno_lyr (2,2,maxsnl+1:1,numpatch)); ssno_lyr(:,:,:,:) = spval
+
+ allocate (trad (numpatch)); trad (:) = spval
+ allocate (tref (numpatch)); tref (:) = spval
+ allocate (t2m_wmo (numpatch)); t2m_wmo (:) = spval
+ allocate (qref (numpatch)); qref (:) = spval
+ allocate (qsfc (numpatch)); qsfc (:) = spval
+ allocate (rst (numpatch)); rst (:) = spval
+ allocate (emis (numpatch)); emis (:) = spval
+ allocate (z0m (numpatch)); z0m (:) = spval
+ allocate (displa (numpatch)); displa (:) = spval
+ allocate (zol (numpatch)); zol (:) = spval
+ allocate (rib (numpatch)); rib (:) = spval
+ allocate (ustar (numpatch)); ustar (:) = spval
+ allocate (qstar (numpatch)); qstar (:) = spval
+ allocate (tstar (numpatch)); tstar (:) = spval
+ allocate (fm (numpatch)); fm (:) = spval
+ allocate (fh (numpatch)); fh (:) = spval
+ allocate (fq (numpatch)); fq (:) = spval
+
+ allocate ( irrig_rate (numpatch)); irrig_rate (:) = spval
+ allocate ( deficit_irrig (numpatch)); deficit_irrig (:) = spval
+ allocate ( actual_irrig (numpatch)); actual_irrig (:) = spval
+ allocate ( sum_irrig (numpatch)); sum_irrig (:) = spval
+ allocate ( sum_deficit_irrig (numpatch)); sum_deficit_irrig (:) = spval
+ allocate ( sum_irrig_count (numpatch)); sum_irrig_count (:) = spval
+ allocate ( n_irrig_steps_left (numpatch)); n_irrig_steps_left (:) = spval_i4
+ allocate ( waterstorage (numpatch)); waterstorage (:) = spval
+ allocate ( waterstorage_supply (numpatch)); waterstorage_supply (:) = spval
+ allocate ( groundwater_demand (numpatch)); groundwater_demand (:) = spval
+ allocate ( groundwater_supply (numpatch)); groundwater_supply (:) = spval
+ allocate ( reservoirriver_demand (numpatch)); reservoirriver_demand (:) = spval
+ allocate ( reservoirriver_supply (numpatch)); reservoirriver_supply (:) = spval
+ allocate ( reservoir_supply (numpatch)); reservoir_supply (:) = spval
+ allocate ( river_supply (numpatch)); river_supply (:) = spval
+ allocate ( runoff_supply (numpatch)); runoff_supply (:) = spval
+ allocate ( tairday (numpatch)); tairday (:) = spval
+ allocate ( usday (numpatch)); usday (:) = spval
+ allocate ( vsday (numpatch)); vsday (:) = spval
+ allocate ( pairday (numpatch)); pairday (:) = spval
+ allocate ( rnetday (numpatch)); rnetday (:) = spval
+ allocate ( fgrndday (numpatch)); fgrndday (:) = spval
+ allocate ( potential_evapotranspiration(numpatch)); potential_evapotranspiration(:) = spval
+
+ allocate ( irrig_method_corn (numpatch)); irrig_method_corn (:) = spval_i4
+ allocate ( irrig_method_swheat (numpatch)); irrig_method_swheat (:) = spval_i4
+ allocate ( irrig_method_wwheat (numpatch)); irrig_method_wwheat (:) = spval_i4
+ allocate ( irrig_method_soybean (numpatch)); irrig_method_soybean (:) = spval_i4
+ allocate ( irrig_method_cotton (numpatch)); irrig_method_cotton (:) = spval_i4
+ allocate ( irrig_method_rice1 (numpatch)); irrig_method_rice1 (:) = spval_i4
+ allocate ( irrig_method_rice2 (numpatch)); irrig_method_rice2 (:) = spval_i4
+ allocate ( irrig_method_sugarcane (numpatch)); irrig_method_sugarcane (:) = spval_i4
+
+ allocate ( irrig_gw_alloc (numpatch)); irrig_gw_alloc (:) = spval
+ allocate ( irrig_sw_alloc (numpatch)); irrig_sw_alloc (:) = spval
+ allocate ( zwt_stand (numpatch)); zwt_stand (:) = spval
+ ENDIF
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL allocate_PFTimeVariables
+#endif
+
+#ifdef BGC
+ CALL allocate_BGCTimeVariables
+#endif
+
+#ifdef CatchLateralFlow
+ CALL allocate_CatchTimeVariables
+#endif
+
+#ifdef GridRiverLakeFlow
+ CALL allocate_GridRiverLakeTimeVars
+#endif
+
+#ifdef URBAN_MODEL
+ CALL allocate_UrbanTimeVariables
+#endif
+
+#ifdef EXTERNAL_LAKE
+ CALL allocate_LakeTimeVars
+#endif
+
+#ifdef DataAssimilation
+ CALL allocate_DATimeVariables
+#endif
+
+ END SUBROUTINE allocate_TimeVariables
+
+
+
+ SUBROUTINE deallocate_TimeVariables ()
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch, only: numpatch
+ IMPLICIT NONE
+
+ !--------------------------------------------------------------------
+ ! Deallocates memory for CoLM 1d [numpatch] variables
+ !--------------------------------------------------------------------
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+
+ deallocate (z_sno )
+ deallocate (dz_sno )
+ deallocate (t_soisno )
+ deallocate (wliq_soisno )
+ deallocate (wice_soisno )
+ deallocate (smp )
+ deallocate (hk )
+ deallocate (h2osoi )
+ deallocate (rootr )
+ deallocate (rootflux )
+!Plant Hydraulic variables
+ deallocate (vegwp )
+ deallocate (gs0sun )
+ deallocate (gs0sha )
+!END plant hydraulic variables
+!Ozone stress variables
+ deallocate (o3coefv_sun ) ! Ozone stress factor for photosynthesis on sunlit leaf
+ deallocate (o3coefv_sha ) ! Ozone stress factor for photosynthesis on shaded leaf
+ deallocate (o3coefg_sun ) ! Ozone stress factor for stomata on sunlit leaf
+ deallocate (o3coefg_sha ) ! Ozone stress factor for stomata on shaded leaf
+ deallocate (lai_old ) ! lai in last time step
+ deallocate (o3uptakesun ) ! Ozone does, sunlit leaf (mmol O3/m^2)
+ deallocate (o3uptakesha ) ! Ozone does, shaded leaf (mmol O3/m^2)
+!END Ozone stress variables
+ deallocate (rstfacsun_out )
+ deallocate (rstfacsha_out )
+ deallocate (gssun_out )
+ deallocate (gssha_out )
+ deallocate (assimsun_out )
+ deallocate (assimsha_out )
+ deallocate (etrsun_out )
+ deallocate (etrsha_out )
+
+ deallocate (t_grnd )
+ deallocate (tleaf )
+ deallocate (ldew )
+ deallocate (ldew_rain )
+ deallocate (ldew_snow )
+ deallocate (fwet_snow )
+ deallocate (sag )
+ deallocate (scv )
+ deallocate (snowdp )
+ deallocate (fveg )
+ deallocate (fsno )
+ deallocate (sigf )
+ deallocate (green )
+ deallocate (tlai )
+ deallocate (lai )
+ deallocate (laisun )
+ deallocate (laisha )
+ deallocate (tsai )
+ deallocate (sai )
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ deallocate (lai_enftemp )
+ deallocate (lai_enfboreal )
+ deallocate (lai_dnfboreal )
+ deallocate (lai_ebftrop )
+ deallocate (lai_ebftemp )
+ deallocate (lai_dbftrop )
+ deallocate (lai_dbftemp )
+ deallocate (lai_dbfboreal )
+ deallocate (lai_ebstemp )
+ deallocate (lai_dbstemp )
+ deallocate (lai_dbsboreal )
+ deallocate (lai_c3arcgrass )
+ deallocate (lai_c3grass )
+ deallocate (lai_c4grass )
+#endif
+ deallocate (coszen )
+ deallocate (alb )
+ deallocate (ssun )
+ deallocate (ssha )
+ deallocate (ssoi )
+ deallocate (ssno )
+ deallocate (thermk )
+ deallocate (extkb )
+ deallocate (extkd )
+ deallocate (zwt )
+ deallocate (wa )
+ deallocate (wetwat )
+ deallocate (wat )
+ deallocate (wdsrf )
+ deallocate (rss )
+
+ deallocate (t_lake ) ! new lake scheme
+ deallocate (lake_icefrac ) ! new lake scheme
+ deallocate (savedtke1 ) ! new lake scheme
+
+ deallocate (snw_rds )
+ deallocate (mss_bcpho )
+ deallocate (mss_bcphi )
+ deallocate (mss_ocpho )
+ deallocate (mss_ocphi )
+ deallocate (mss_dst1 )
+ deallocate (mss_dst2 )
+ deallocate (mss_dst3 )
+ deallocate (mss_dst4 )
+ deallocate (ssno_lyr )
+
+ deallocate (trad )
+ deallocate (tref )
+ deallocate (t2m_wmo )
+ deallocate (qref )
+ deallocate (qsfc )
+ deallocate (rst )
+ deallocate (emis )
+ deallocate (z0m )
+ deallocate (displa )
+ deallocate (zol )
+ deallocate (rib )
+ deallocate (ustar )
+ deallocate (qstar )
+ deallocate (tstar )
+ deallocate (fm )
+ deallocate (fh )
+ deallocate (fq )
+
+ deallocate (irrig_rate )
+ deallocate (deficit_irrig )
+ deallocate (actual_irrig )
+ deallocate (sum_irrig )
+ deallocate (sum_deficit_irrig )
+ deallocate (sum_irrig_count )
+ deallocate (n_irrig_steps_left )
+ deallocate (waterstorage )
+ deallocate (waterstorage_supply )
+ deallocate (groundwater_demand )
+ deallocate (groundwater_supply )
+ deallocate (reservoirriver_demand )
+ deallocate (reservoirriver_supply )
+ deallocate (reservoir_supply )
+ deallocate (river_supply )
+ deallocate (runoff_supply )
+ deallocate (tairday )
+ deallocate (usday )
+ deallocate (vsday )
+ deallocate (pairday )
+ deallocate (rnetday )
+ deallocate (fgrndday )
+ deallocate (potential_evapotranspiration)
+
+ deallocate (irrig_method_corn )
+ deallocate (irrig_method_swheat )
+ deallocate (irrig_method_wwheat )
+ deallocate (irrig_method_soybean )
+ deallocate (irrig_method_cotton )
+ deallocate (irrig_method_rice1 )
+ deallocate (irrig_method_rice2 )
+ deallocate (irrig_method_sugarcane )
+
+ deallocate (irrig_gw_alloc )
+ deallocate (irrig_sw_alloc )
+ deallocate (zwt_stand )
+
+ ENDIF
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL deallocate_PFTimeVariables
+#endif
+
+#if (defined BGC)
+ CALL deallocate_BGCTimeVariables
+#endif
+
+#ifdef CatchLateralFlow
+ CALL deallocate_CatchTimeVariables
+#endif
+
+#ifdef GridRiverLakeFlow
+ CALL deallocate_GridRiverLakeTimeVars
+#endif
+
+#if (defined URBAN_MODEL)
+ CALL deallocate_UrbanTimeVariables
+#endif
+
+#ifdef EXTERNAL_LAKE
+ CALL deallocate_LakeTimeVars
+#endif
+
+#ifdef DataAssimilation
+ CALL deallocate_DATimeVariables
+#endif
+
+ END SUBROUTINE deallocate_TimeVariables
+
+
+ !---------------------------------------
+ FUNCTION save_to_restart (idate, deltim, itstamp, ptstamp, etstamp) result(rwrite)
+
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ logical :: rwrite
+
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ type(timestamp), intent(in) :: itstamp, ptstamp, etstamp
+
+
+ ! added by yuan, 08/31/2014
+ SELECTCASE (trim(adjustl(DEF_WRST_FREQ)))
+ CASE ('TIMESTEP')
+ rwrite = .true.
+ CASE ('HOURLY')
+ rwrite = isendofhour (idate, deltim)
+ CASE ('DAILY')
+ rwrite = isendofday(idate, deltim)
+ CASE ('MONTHLY')
+ rwrite = isendofmonth(idate, deltim)
+ CASE ('YEARLY')
+ rwrite = isendofyear(idate, deltim)
+ CASE default
+ rwrite = .false.
+ write(*,*) 'Warning: Please USE one of TIMESTEP/HOURLY/DAILY/MONTHLY/YEARLY for restart frequency.'
+ write(*,*) ' Set to FALSE by default. '
+ ENDSELECT
+
+ IF (rwrite) THEN
+ rwrite = ((ptstamp <= itstamp) .or. isendofyear(idate,deltim))
+ ENDIF
+
+ rwrite = rwrite .or. (.not. (itstamp < etstamp))
+
+ END FUNCTION save_to_restart
+
+
+ SUBROUTINE WRITE_TimeVariables (idate, lc_year, site, dir_restart)
+
+ !====================================================================
+ ! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+ !====================================================================
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only: DEF_REST_CompressLevel, DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, &
+ DEF_USE_IRRIGATION, DEF_USE_Dynamic_Lake, SITE_landtype
+ USE MOD_LandPatch
+ USE MOD_NetCDFVector
+ USE MOD_Vars_Global
+ USE MOD_Vars_TimeInvariants, only: dz_lake
+ USE MOD_Const_LC, only: patchtypes
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ integer, intent(in) :: lc_year !year of land cover type data
+ character(len=*), intent(in) :: site
+ character(len=*), intent(in) :: dir_restart
+
+ ! Local variables
+ character(len=256) :: file_restart
+ character(len=14) :: cdate
+ character(len=256) :: cyear !character for lc_year
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ ! land cover type year
+ write(cyear,'(i4.4)') lc_year
+ write(cdate,'(i4.4,"-",i3.3,"-",i5.5)') idate(1), idate(2), idate(3)
+
+ IF (p_is_root) THEN
+ CALL system('mkdir -p ' // trim(dir_restart)//'/'//trim(cdate))
+ ENDIF
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpatch > 0) THEN
+#endif
+
+ CALL ncio_create_file_vector (file_restart, landpatch)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'snow', -maxsnl )
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'snowp1', -maxsnl+1 )
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soilsnow', nl_soil-maxsnl)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'soil', nl_soil)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'lake', nl_lake)
+
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'vegnodes', nvegwcs)
+ENDIF
+
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'band', 2)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'rtyp', 2)
+#ifdef HYPERSPECTRAL
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'wavelength', 211)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'PFT', 16)
+#endif
+ ! Time-varying state variables which required by restart run
+ CALL ncio_write_vector (file_restart, 'z_sno ' , 'snow', -maxsnl, 'patch', landpatch, z_sno , compress) ! node depth [m]
+ CALL ncio_write_vector (file_restart, 'dz_sno ' , 'snow', -maxsnl, 'patch', landpatch, dz_sno, compress) ! interface depth [m]
+ CALL ncio_write_vector (file_restart, 't_soisno' , 'soilsnow', nl_soil-maxsnl, 'patch', landpatch, t_soisno , compress) ! soil temperature [K]
+ CALL ncio_write_vector (file_restart, 'wliq_soisno', 'soilsnow', nl_soil-maxsnl, 'patch', landpatch, wliq_soisno, compress) ! liquid water in layers [kg/m2]
+ CALL ncio_write_vector (file_restart, 'wice_soisno', 'soilsnow', nl_soil-maxsnl, 'patch', landpatch, wice_soisno, compress) ! ice lens in layers [kg/m2]
+ CALL ncio_write_vector (file_restart, 'smp', 'soil', nl_soil, 'patch', landpatch, smp, compress) ! soil matrix potential [mm]
+ CALL ncio_write_vector (file_restart, 'hk', 'soil', nl_soil, 'patch', landpatch, hk, compress) ! hydraulic conductivity [mm h2o/s]
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL ncio_write_vector (file_restart, 'vegwp', 'vegnodes', nvegwcs, 'patch', landpatch, vegwp, compress) ! vegetation water potential [mm]
+ CALL ncio_write_vector (file_restart, 'gs0sun', 'patch', landpatch, gs0sun, compress) ! working copy of sunlit stomata conductance
+ CALL ncio_write_vector (file_restart, 'gs0sha', 'patch', landpatch, gs0sha, compress) ! working copy of shalit stomata conductance
+ENDIF
+IF(DEF_USE_OZONESTRESS)THEN
+ CALL ncio_write_vector (file_restart, 'lai_old ', 'patch', landpatch, lai_old , compress)
+ CALL ncio_write_vector (file_restart, 'o3uptakesun', 'patch', landpatch, o3uptakesun, compress)
+ CALL ncio_write_vector (file_restart, 'o3uptakesha', 'patch', landpatch, o3uptakesha, compress)
+ CALL ncio_write_vector (file_restart, 'o3coefv_sun', 'patch', landpatch, o3coefv_sun, compress)
+ CALL ncio_write_vector (file_restart, 'o3coefv_sha', 'patch', landpatch, o3coefv_sha, compress)
+ CALL ncio_write_vector (file_restart, 'o3coefg_sun', 'patch', landpatch, o3coefg_sun, compress)
+ CALL ncio_write_vector (file_restart, 'o3coefg_sha', 'patch', landpatch, o3coefg_sha, compress)
+ENDIF
+ CALL ncio_write_vector (file_restart, 't_grnd ' , 'patch', landpatch, t_grnd , compress) ! ground surface temperature [K]
+ CALL ncio_write_vector (file_restart, 'tleaf ' , 'patch', landpatch, tleaf , compress) ! leaf temperature [K]
+ CALL ncio_write_vector (file_restart, 'ldew ' , 'patch', landpatch, ldew , compress) ! depth of water on foliage [mm]
+ CALL ncio_write_vector (file_restart, 'ldew_rain' , 'patch', landpatch, ldew_rain , compress) ! depth of water on foliage [mm]
+ CALL ncio_write_vector (file_restart, 'ldew_snow' , 'patch', landpatch, ldew_snow , compress) ! depth of water on foliage [mm]
+ CALL ncio_write_vector (file_restart, 'fwet_snow' , 'patch', landpatch, fwet_snow , compress) ! vegetation snow fractional cover [-]
+ CALL ncio_write_vector (file_restart, 'sag ' , 'patch', landpatch, sag , compress) ! non dimensional snow age [-]
+ CALL ncio_write_vector (file_restart, 'scv ' , 'patch', landpatch, scv , compress) ! snow cover, water equivalent [mm]
+ CALL ncio_write_vector (file_restart, 'snowdp ' , 'patch', landpatch, snowdp , compress) ! snow depth [meter]
+ CALL ncio_write_vector (file_restart, 'fveg ' , 'patch', landpatch, fveg , compress) ! fraction of vegetation cover
+ CALL ncio_write_vector (file_restart, 'fsno ' , 'patch', landpatch, fsno , compress) ! fraction of snow cover on ground
+ CALL ncio_write_vector (file_restart, 'sigf ' , 'patch', landpatch, sigf , compress) ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL ncio_write_vector (file_restart, 'green ' , 'patch', landpatch, green , compress) ! leaf greenness
+ CALL ncio_write_vector (file_restart, 'lai ' , 'patch', landpatch, lai , compress) ! leaf area index
+ CALL ncio_write_vector (file_restart, 'tlai ' , 'patch', landpatch, tlai , compress) ! leaf area index
+ CALL ncio_write_vector (file_restart, 'sai ' , 'patch', landpatch, sai , compress) ! stem area index
+ CALL ncio_write_vector (file_restart, 'tsai ' , 'patch', landpatch, tsai , compress) ! stem area index
+ CALL ncio_write_vector (file_restart, 'coszen ' , 'patch', landpatch, coszen , compress) ! cosine of solar zenith angle
+ CALL ncio_write_vector (file_restart, 'alb ' , 'band', 2, 'rtyp', 2, 'patch', landpatch, alb , compress) ! averaged albedo [-]
+ CALL ncio_write_vector (file_restart, 'ssun ' , 'band', 2, 'rtyp', 2, 'patch', landpatch, ssun, compress) ! sunlit canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'ssha ' , 'band', 2, 'rtyp', 2, 'patch', landpatch, ssha, compress) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'ssoi ' , 'band', 2, 'rtyp', 2, 'patch', landpatch, ssoi, compress) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_write_vector (file_restart, 'ssno ' , 'band', 2, 'rtyp', 2, 'patch', landpatch, ssno, compress) ! shaded canopy absorption for solar radiation (0-1)
+#ifdef HYPERSPECTRAL
+ CALL ncio_write_vector (file_restart, 'alb_hires' , 'wavelength', 211, 'rtyp', 2, 'patch', landpatch, alb_hires , compress) ! averaged albedo [-]
+ CALL ncio_write_vector (file_restart, 'reflectance_out' , 'wavelength', 211, 'PFT', 16, 'patch', landpatch, reflectance_out , compress) ! averaged albedo [-]
+ CALL ncio_write_vector (file_restart, 'transmittance_out', 'wavelength', 211, 'PFT', 16, 'patch', landpatch, transmittance_out, compress) ! averaged albedo [-]
+#endif
+
+ CALL ncio_write_vector (file_restart, 'thermk ' , 'patch', landpatch, thermk , compress) ! canopy gap fraction for tir radiation
+ CALL ncio_write_vector (file_restart, 'extkb ' , 'patch', landpatch, extkb , compress) ! (k, g(mu)/mu) direct solar extinction coefficient
+ CALL ncio_write_vector (file_restart, 'extkd ' , 'patch', landpatch, extkd , compress) ! diffuse and scattered diffuse PAR extinction coefficient
+ CALL ncio_write_vector (file_restart, 'zwt ' , 'patch', landpatch, zwt , compress) ! the depth to water table [m]
+ CALL ncio_write_vector (file_restart, 'wa ' , 'patch', landpatch, wa , compress) ! water storage in aquifer [mm]
+ CALL ncio_write_vector (file_restart, 'wetwat ' , 'patch', landpatch, wetwat , compress) ! water storage in wetland [mm]
+ CALL ncio_write_vector (file_restart, 'wdsrf ' , 'patch', landpatch, wdsrf , compress) ! depth of surface water [mm]
+ CALL ncio_write_vector (file_restart, 'rss ' , 'patch', landpatch, rss , compress) ! soil surface resistance [s/m]
+
+IF (DEF_USE_Dynamic_Lake) THEN
+ CALL ncio_write_vector (file_restart, 'dz_lake' , 'lake', nl_lake, 'patch', landpatch, dz_lake , compress)
+ENDIF
+ CALL ncio_write_vector (file_restart, 't_lake ' , 'lake', nl_lake, 'patch', landpatch, t_lake , compress)
+ CALL ncio_write_vector (file_restart, 'lake_icefrc', 'lake', nl_lake, 'patch', landpatch, lake_icefrac, compress)
+ CALL ncio_write_vector (file_restart, 'savedtke1 ', 'patch', landpatch, savedtke1 , compress)
+ CALL ncio_write_vector (file_restart, 'snw_rds ', 'snow', -maxsnl, 'patch', landpatch, snw_rds , compress)
+ CALL ncio_write_vector (file_restart, 'mss_bcpho', 'snow', -maxsnl, 'patch', landpatch, mss_bcpho, compress)
+ CALL ncio_write_vector (file_restart, 'mss_bcphi', 'snow', -maxsnl, 'patch', landpatch, mss_bcphi, compress)
+ CALL ncio_write_vector (file_restart, 'mss_ocpho', 'snow', -maxsnl, 'patch', landpatch, mss_ocpho, compress)
+ CALL ncio_write_vector (file_restart, 'mss_ocphi', 'snow', -maxsnl, 'patch', landpatch, mss_ocphi, compress)
+ CALL ncio_write_vector (file_restart, 'mss_dst1 ', 'snow', -maxsnl, 'patch', landpatch, mss_dst1 , compress)
+ CALL ncio_write_vector (file_restart, 'mss_dst2 ', 'snow', -maxsnl, 'patch', landpatch, mss_dst2 , compress)
+ CALL ncio_write_vector (file_restart, 'mss_dst3 ', 'snow', -maxsnl, 'patch', landpatch, mss_dst3 , compress)
+ CALL ncio_write_vector (file_restart, 'mss_dst4 ', 'snow', -maxsnl, 'patch', landpatch, mss_dst4 , compress)
+ CALL ncio_write_vector (file_restart, 'ssno_lyr', 'band', 2, 'rtyp', 2, 'snowp1', -maxsnl+1, 'patch', landpatch, ssno_lyr, compress)
+
+ ! Additional va_vectorriables required by regional model (such as WRF ) RSM)
+ CALL ncio_write_vector (file_restart, 'trad ', 'patch', landpatch, trad , compress) ! radiative temperature of surface [K]
+ CALL ncio_write_vector (file_restart, 'tref ', 'patch', landpatch, tref , compress) ! 2 m height air temperature [kelvin]
+ CALL ncio_write_vector (file_restart, 'qref ', 'patch', landpatch, qref , compress) ! 2 m height air specific humidity
+ CALL ncio_write_vector (file_restart, 'rst ', 'patch', landpatch, rst , compress) ! canopy stomatal resistance (s/m)
+ CALL ncio_write_vector (file_restart, 'emis ', 'patch', landpatch, emis , compress) ! averaged bulk surface emissivity
+ CALL ncio_write_vector (file_restart, 'z0m ', 'patch', landpatch, z0m , compress) ! effective roughness [m]
+ CALL ncio_write_vector (file_restart, 'zol ', 'patch', landpatch, zol , compress) ! dimensionless height (z/L) used in Monin-Obukhov theory
+ CALL ncio_write_vector (file_restart, 'rib ', 'patch', landpatch, rib , compress) ! bulk Richardson number in surface layer
+ CALL ncio_write_vector (file_restart, 'ustar', 'patch', landpatch, ustar, compress) ! u* in similarity theory [m/s]
+ CALL ncio_write_vector (file_restart, 'qstar', 'patch', landpatch, qstar, compress) ! q* in similarity theory [kg/kg]
+ CALL ncio_write_vector (file_restart, 'tstar', 'patch', landpatch, tstar, compress) ! t* in similarity theory [K]
+ CALL ncio_write_vector (file_restart, 'fm ', 'patch', landpatch, fm , compress) ! integral of profile FUNCTION for momentum
+ CALL ncio_write_vector (file_restart, 'fh ', 'patch', landpatch, fh , compress) ! integral of profile FUNCTION for heat
+ CALL ncio_write_vector (file_restart, 'fq ', 'patch', landpatch, fq , compress) ! integral of profile FUNCTION for moisture
+
+IF (DEF_USE_IRRIGATION) THEN
+ CALL ncio_write_vector (file_restart, 'irrig_rate ' , 'patch',landpatch,irrig_rate , compress)
+ CALL ncio_write_vector (file_restart, 'sum_irrig ' , 'patch',landpatch,sum_irrig , compress)
+ CALL ncio_write_vector (file_restart, 'sum_deficit_irrig ' , 'patch',landpatch,sum_deficit_irrig , compress)
+ CALL ncio_write_vector (file_restart, 'sum_irrig_count ' , 'patch',landpatch,sum_irrig_count , compress)
+ CALL ncio_write_vector (file_restart, 'n_irrig_steps_left ' , 'patch',landpatch,n_irrig_steps_left , compress)
+ CALL ncio_write_vector (file_restart, 'waterstorage ' , 'patch',landpatch,waterstorage , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_corn ' , 'patch',landpatch,irrig_method_corn , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_swheat ' , 'patch',landpatch,irrig_method_swheat , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_wwheat ' , 'patch',landpatch,irrig_method_wwheat , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_soybean ' , 'patch',landpatch,irrig_method_soybean , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_cotton ' , 'patch',landpatch,irrig_method_cotton , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_rice1 ' , 'patch',landpatch,irrig_method_rice1 , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_rice2 ' , 'patch',landpatch,irrig_method_rice2 , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_method_sugarcane' , 'patch',landpatch,irrig_method_sugarcane, compress)
+ CALL ncio_write_vector (file_restart, 'irrig_gw_alloc ' , 'patch',landpatch,irrig_gw_alloc , compress)
+ CALL ncio_write_vector (file_restart, 'irrig_sw_alloc ' , 'patch',landpatch,irrig_sw_alloc , compress)
+ CALL ncio_write_vector (file_restart, 'zwt_stand ' , 'patch',landpatch,zwt_stand , compress)
+ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+#ifdef SinglePoint
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_pft_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_PFTimeVariables (file_restart)
+ ENDIF
+#else
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_pft_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_PFTimeVariables (file_restart)
+#endif
+#endif
+
+#if (defined BGC)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_bgc_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_BGCTimeVariables (file_restart)
+#endif
+
+#if (defined CatchLateralFlow)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_basin_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_CatchTimeVariables (file_restart)
+#endif
+
+#if (defined URBAN_MODEL)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_urban_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_UrbanTimeVariables (file_restart)
+#endif
+
+#ifdef EXTERNAL_LAKE
+ CALL WRITE_LakeTimeVars (idate, lc_year, site, dir_restart)
+#endif
+
+#ifdef DataAssimilation
+ CALL WRITE_DATimeVariables (idate, lc_year, site, dir_restart)
+#endif
+
+#ifdef MPAS_EMBEDDED_COLM
+ ENDIF
+#endif
+
+#ifdef GridRiverLakeFlow
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_gridriver_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL WRITE_GridRiverLakeTimeVars (file_restart)
+#endif
+
+ END SUBROUTINE WRITE_TimeVariables
+
+
+ SUBROUTINE READ_TimeVariables (idate, lc_year, site, dir_restart)
+
+ !====================================================================
+ ! Original version: Yongjiu Dai, September 15, 1999, 03/2014
+ !====================================================================
+
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFVector
+#ifdef RangeCheck
+ USE MOD_RangeCheck
+#endif
+ USE MOD_LandPatch
+ USE MOD_Vars_Global
+ USE MOD_Vars_TimeInvariants, only: dz_lake
+ USE MOD_Const_LC, only: patchtypes
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ integer, intent(in) :: lc_year !year of land cover type data
+ character(len=*), intent(in) :: site
+ character(len=*), intent(in) :: dir_restart
+
+ ! Local variables
+ character(len=256) :: file_restart
+ character(len=14) :: cdate, cyear
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write(*,*) 'Loading Time Variables ...'
+ ENDIF
+
+ ! land cover type year
+ write(cyear,'(i4.4)') lc_year
+
+ write(cdate,'(i4.4,"-",i3.3,"-",i5.5)') idate(1), idate(2), idate(3)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpatch > 0) THEN
+#endif
+
+ ! Time-varying state variables which required by restart run
+ CALL ncio_read_vector (file_restart, 'z_sno ' , -maxsnl, landpatch, z_sno ) ! node depth [m]
+ CALL ncio_read_vector (file_restart, 'dz_sno ' , -maxsnl, landpatch, dz_sno) ! interface depth [m]
+ CALL ncio_read_vector (file_restart, 't_soisno' , nl_soil-maxsnl, landpatch, t_soisno ) ! soil temperature [K]
+ CALL ncio_read_vector (file_restart, 'wliq_soisno', nl_soil-maxsnl, landpatch, wliq_soisno) ! liquid water in layers [kg/m2]
+ CALL ncio_read_vector (file_restart, 'wice_soisno', nl_soil-maxsnl, landpatch, wice_soisno) ! ice lens in layers [kg/m2]
+ CALL ncio_read_vector (file_restart, 'smp', nl_soil, landpatch, smp ) ! soil matrix potential [mm]
+ CALL ncio_read_vector (file_restart, 'hk', nl_soil, landpatch, hk ) ! hydraulic conductivity [mm h2o/s]
+IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL ncio_read_vector (file_restart, 'vegwp', nvegwcs, landpatch, vegwp ) ! vegetation water potential [mm]
+ CALL ncio_read_vector (file_restart, 'gs0sun ', landpatch, gs0sun ) ! working copy of sunlit stomata conductance
+ CALL ncio_read_vector (file_restart, 'gs0sha ', landpatch, gs0sha ) ! working copy of shaded stomata conductance
+ENDIF
+ CALL ncio_read_vector (file_restart, 't_grnd ' , landpatch, t_grnd ) ! ground surface temperature [K]
+ CALL ncio_read_vector (file_restart, 'tleaf ' , landpatch, tleaf ) ! leaf temperature [K]
+ CALL ncio_read_vector (file_restart, 'ldew ' , landpatch, ldew ) ! depth of water on foliage [mm]
+ CALL ncio_read_vector (file_restart, 'ldew_rain' , landpatch, ldew_rain ) ! depth of rain on foliage [mm]
+ CALL ncio_read_vector (file_restart, 'ldew_snow' , landpatch, ldew_snow ) ! depth of snow on foliage [mm]
+ CALL ncio_read_vector (file_restart, 'fwet_snow' , landpatch, fwet_snow ) ! vegetation snow fractional cover [-]
+ CALL ncio_read_vector (file_restart, 'sag ' , landpatch, sag ) ! non dimensional snow age [-]
+ CALL ncio_read_vector (file_restart, 'scv ' , landpatch, scv ) ! snow cover, water equivalent [mm]
+ CALL ncio_read_vector (file_restart, 'snowdp ' , landpatch, snowdp ) ! snow depth [meter]
+ CALL ncio_read_vector (file_restart, 'fveg ' , landpatch, fveg ) ! fraction of vegetation cover
+ CALL ncio_read_vector (file_restart, 'fsno ' , landpatch, fsno ) ! fraction of snow cover on ground
+ CALL ncio_read_vector (file_restart, 'sigf ' , landpatch, sigf ) ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL ncio_read_vector (file_restart, 'green ' , landpatch, green ) ! leaf greenness
+ CALL ncio_read_vector (file_restart, 'lai ' , landpatch, lai ) ! leaf area index
+ CALL ncio_read_vector (file_restart, 'tlai ' , landpatch, tlai ) ! leaf area index
+ CALL ncio_read_vector (file_restart, 'sai ' , landpatch, sai ) ! stem area index
+ CALL ncio_read_vector (file_restart, 'tsai ' , landpatch, tsai ) ! stem area index
+ CALL ncio_read_vector (file_restart, 'coszen ' , landpatch, coszen ) ! cosine of solar zenith angle
+IF(DEF_USE_OZONESTRESS)THEN
+ CALL ncio_read_vector (file_restart, 'lai_old ', landpatch, lai_old )
+ CALL ncio_read_vector (file_restart, 'o3uptakesun', landpatch, o3uptakesun)
+ CALL ncio_read_vector (file_restart, 'o3uptakesha', landpatch, o3uptakesha)
+ CALL ncio_read_vector (file_restart, 'o3coefv_sun', landpatch, o3coefv_sun)
+ CALL ncio_read_vector (file_restart, 'o3coefv_sha', landpatch, o3coefv_sha)
+ CALL ncio_read_vector (file_restart, 'o3coefg_sun', landpatch, o3coefg_sun)
+ CALL ncio_read_vector (file_restart, 'o3coefg_sha', landpatch, o3coefg_sha)
+ENDIF
+ CALL ncio_read_vector (file_restart, 'alb ' , 2, 2, landpatch, alb ) ! averaged albedo [-]
+ CALL ncio_read_vector (file_restart, 'ssun ' , 2, 2, landpatch, ssun ) ! sunlit canopy absorption for solar radiation (0-1)
+ CALL ncio_read_vector (file_restart, 'ssha ' , 2, 2, landpatch, ssha ) ! shaded canopy absorption for solar radiation (0-1)
+ CALL ncio_read_vector (file_restart, 'ssoi ' , 2, 2, landpatch, ssoi ) ! soil absorption for solar radiation (0-1)
+ CALL ncio_read_vector (file_restart, 'ssno ' , 2, 2, landpatch, ssno ) ! snow absorption for solar radiation (0-1)
+#ifdef HYPERSPECTRAL
+ CALL ncio_read_vector (file_restart, 'alb_hires ' , 211, 2, landpatch, alb_hires ) ! averaged albedo [-]
+ CALL ncio_read_vector (file_restart, 'reflectance_out' , 211, 16, landpatch, reflectance_out ) ! averaged albedo [-]
+ CALL ncio_read_vector (file_restart, 'transmittance_out', 211, 16, landpatch, transmittance_out) ! averaged albedo [-]
+#endif
+
+ CALL ncio_read_vector (file_restart, 'thermk ' , landpatch, thermk ) ! canopy gap fraction for tir radiation
+ CALL ncio_read_vector (file_restart, 'extkb ' , landpatch, extkb ) ! (k, g(mu)/mu) direct solar extinction coefficient
+ CALL ncio_read_vector (file_restart, 'extkd ' , landpatch, extkd ) ! diffuse and scattered diffuse PAR extinction coefficient
+ CALL ncio_read_vector (file_restart, 'zwt ' , landpatch, zwt ) ! the depth to water table [m]
+ CALL ncio_read_vector (file_restart, 'wa ' , landpatch, wa ) ! water storage in aquifer [mm]
+ CALL ncio_read_vector (file_restart, 'wetwat ' , landpatch, wetwat ) ! water storage in wetland [mm]
+ CALL ncio_read_vector (file_restart, 'wdsrf ' , landpatch, wdsrf ) ! depth of surface water [mm]
+ CALL ncio_read_vector (file_restart, 'rss ' , landpatch, rss ) ! soil surface resistance [s/m]
+
+IF (DEF_USE_Dynamic_Lake) THEN
+ CALL ncio_read_vector (file_restart, 'dz_lake' , nl_lake, landpatch, dz_lake )
+ENDIF
+ CALL ncio_read_vector (file_restart, 't_lake ' , nl_lake, landpatch, t_lake )
+ CALL ncio_read_vector (file_restart, 'lake_icefrc', nl_lake, landpatch, lake_icefrac)
+ CALL ncio_read_vector (file_restart, 'savedtke1', landpatch, savedtke1)
+
+ CALL ncio_read_vector (file_restart, 'snw_rds ', -maxsnl, landpatch, snw_rds )
+ CALL ncio_read_vector (file_restart, 'mss_bcpho', -maxsnl, landpatch, mss_bcpho)
+ CALL ncio_read_vector (file_restart, 'mss_bcphi', -maxsnl, landpatch, mss_bcphi)
+ CALL ncio_read_vector (file_restart, 'mss_ocpho', -maxsnl, landpatch, mss_ocpho)
+ CALL ncio_read_vector (file_restart, 'mss_ocphi', -maxsnl, landpatch, mss_ocphi)
+ CALL ncio_read_vector (file_restart, 'mss_dst1 ', -maxsnl, landpatch, mss_dst1 )
+ CALL ncio_read_vector (file_restart, 'mss_dst2 ', -maxsnl, landpatch, mss_dst2 )
+ CALL ncio_read_vector (file_restart, 'mss_dst3 ', -maxsnl, landpatch, mss_dst3 )
+ CALL ncio_read_vector (file_restart, 'mss_dst4 ', -maxsnl, landpatch, mss_dst4 )
+ CALL ncio_read_vector (file_restart, 'ssno_lyr', 2,2, -maxsnl+1, landpatch, ssno_lyr)
+
+ ! Additional variables required by regional model (such as WRF ) RSM)
+ CALL ncio_read_vector (file_restart, 'trad ', landpatch, trad ) ! radiative temperature of surface [K]
+ CALL ncio_read_vector (file_restart, 'tref ', landpatch, tref ) ! 2 m height air temperature [kelvin]
+ CALL ncio_read_vector (file_restart, 'qref ', landpatch, qref ) ! 2 m height air specific humidity
+ CALL ncio_read_vector (file_restart, 'rst ', landpatch, rst ) ! canopy stomatal resistance (s/m)
+ CALL ncio_read_vector (file_restart, 'emis ', landpatch, emis ) ! averaged bulk surface emissivity
+ CALL ncio_read_vector (file_restart, 'z0m ', landpatch, z0m ) ! effective roughness [m]
+ CALL ncio_read_vector (file_restart, 'zol ', landpatch, zol ) ! dimensionless height (z/L) used in Monin-Obukhov theory
+ CALL ncio_read_vector (file_restart, 'rib ', landpatch, rib ) ! bulk Richardson number in surface layer
+ CALL ncio_read_vector (file_restart, 'ustar', landpatch, ustar) ! u* in similarity theory [m/s]
+ CALL ncio_read_vector (file_restart, 'qstar', landpatch, qstar) ! q* in similarity theory [kg/kg]
+ CALL ncio_read_vector (file_restart, 'tstar', landpatch, tstar) ! t* in similarity theory [K]
+ CALL ncio_read_vector (file_restart, 'fm ', landpatch, fm ) ! integral of profile FUNCTION for momentum
+ CALL ncio_read_vector (file_restart, 'fh ', landpatch, fh ) ! integral of profile FUNCTION for heat
+ CALL ncio_read_vector (file_restart, 'fq ', landpatch, fq ) ! integral of profile FUNCTION for moisture
+
+IF (DEF_USE_IRRIGATION) THEN
+ CALL ncio_read_vector (file_restart, 'irrig_rate ' , landpatch, irrig_rate )
+ CALL ncio_read_vector (file_restart, 'sum_irrig ' , landpatch, sum_irrig )
+ CALL ncio_read_vector (file_restart, 'sum_deficit_irrig ' , landpatch, sum_deficit_irrig )
+ CALL ncio_read_vector (file_restart, 'sum_irrig_count ' , landpatch, sum_irrig_count )
+ CALL ncio_read_vector (file_restart, 'n_irrig_steps_left ' , landpatch, n_irrig_steps_left )
+ CALL ncio_read_vector (file_restart, 'waterstorage ' , landpatch, waterstorage )
+ CALL ncio_read_vector (file_restart, 'irrig_method_corn ' , landpatch, irrig_method_corn )
+ CALL ncio_read_vector (file_restart, 'irrig_method_swheat ' , landpatch, irrig_method_swheat )
+ CALL ncio_read_vector (file_restart, 'irrig_method_wwheat ' , landpatch, irrig_method_wwheat )
+ CALL ncio_read_vector (file_restart, 'irrig_method_soybean ' , landpatch, irrig_method_soybean )
+ CALL ncio_read_vector (file_restart, 'irrig_method_cotton ' , landpatch, irrig_method_cotton )
+ CALL ncio_read_vector (file_restart, 'irrig_method_rice1 ' , landpatch, irrig_method_rice1 )
+ CALL ncio_read_vector (file_restart, 'irrig_method_rice2 ' , landpatch, irrig_method_rice2 )
+ CALL ncio_read_vector (file_restart, 'irrig_method_sugarcane' , landpatch, irrig_method_sugarcane)
+ CALL ncio_read_vector (file_restart, 'irrig_gw_alloc ' , landpatch, irrig_gw_alloc )
+ CALL ncio_read_vector (file_restart, 'irrig_sw_alloc ' , landpatch, irrig_sw_alloc )
+ CALL ncio_read_vector (file_restart, 'zwt_stand ' , landpatch, zwt_stand )
+ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+#ifdef SinglePoint
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_pft_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL READ_PFTimeVariables (file_restart)
+ ENDIF
+#else
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_pft_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL READ_PFTimeVariables (file_restart)
+#endif
+#endif
+
+#if (defined BGC)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_bgc_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL READ_BGCTimeVariables (file_restart)
+#endif
+
+#if (defined CatchLateralFlow)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_basin_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL READ_CatchTimeVariables (file_restart)
+#endif
+
+#ifdef MPAS_EMBEDDED_COLM
+ ENDIF
+#endif
+
+#ifdef GridRiverLakeFlow
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_gridriver_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL READ_GridRiverLakeTimeVars (file_restart)
+#endif
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (numpatch > 0) THEN
+#endif
+
+#if (defined URBAN_MODEL)
+ file_restart = trim(dir_restart)// '/'//trim(cdate)//'/' // trim(site) //'_restart_urban_'//trim(cdate)//'_lc'//trim(cyear)//'.nc'
+ CALL READ_UrbanTimeVariables (file_restart)
+#endif
+
+#ifdef EXTERNAL_LAKE
+ CALL READ_LakeTimeVars(idate, lc_year, site, dir_restart)
+#endif
+
+#ifdef DataAssimilation
+ CALL READ_DATimeVariables (idate, lc_year, site, dir_restart)
+#endif
+
+#ifdef RangeCheck
+ CALL check_TimeVariables
+#endif
+
+#ifdef MPAS_EMBEDDED_COLM
+ ENDIF
+#endif
+
+ IF (p_is_root) THEN
+ write(*,*) 'Loading Time Variables done.'
+ ENDIF
+
+ END SUBROUTINE READ_TimeVariables
+
+
+#ifdef RangeCheck
+ SUBROUTINE check_TimeVariables ()
+
+ USE MOD_SPMD_Task
+ USE MOD_RangeCheck
+ USE MOD_Namelist, only: DEF_USE_PLANTHYDRAULICS, DEF_USE_OZONESTRESS, DEF_USE_IRRIGATION, &
+ DEF_USE_SNICAR, DEF_USE_Dynamic_Lake
+ USE MOD_Vars_TimeInvariants, only: dz_lake
+
+ IMPLICIT NONE
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ IF (p_is_root) THEN
+ write(*,'(/,A27)') 'Checking Time Variables ...'
+ ENDIF
+
+ CALL check_vector_data ('t_grnd [K] ', t_grnd ) ! ground surface temperature [K]
+ CALL check_vector_data ('tleaf [K] ', tleaf ) ! leaf temperature [K]
+ CALL check_vector_data ('ldew [mm] ', ldew ) ! depth of water on foliage [mm]
+ CALL check_vector_data ('ldew_rain [mm] ', ldew_rain ) ! depth of rain on foliage [mm]
+ CALL check_vector_data ('ldew_snow [mm] ', ldew_snow ) ! depth of snow on foliage [mm]
+ CALL check_vector_data ('fwet_snow [mm] ', fwet_snow ) ! vegetation snow fractional cover [-]
+ CALL check_vector_data ('sag [-] ', sag ) ! non dimensional snow age [-]
+ CALL check_vector_data ('scv [mm] ', scv ) ! snow cover, water equivalent [mm]
+ CALL check_vector_data ('snowdp [m] ', snowdp ) ! snow depth [meter]
+ CALL check_vector_data ('fveg [-] ', fveg ) ! fraction of vegetation cover
+ CALL check_vector_data ('fsno [-] ', fsno ) ! fraction of snow cover on ground
+ CALL check_vector_data ('sigf [-] ', sigf ) ! fraction of veg cover, excluding snow-covered veg [-]
+ CALL check_vector_data ('green [-] ', green ) ! leaf greenness
+ CALL check_vector_data ('lai [-] ', lai ) ! leaf area index
+ CALL check_vector_data ('tlai [-] ', tlai ) ! leaf area index
+ CALL check_vector_data ('sai [-] ', sai ) ! stem area index
+ CALL check_vector_data ('tsai [-] ', tsai ) ! stem area index
+ CALL check_vector_data ('coszen [-] ', coszen ) ! cosine of solar zenith angle
+ CALL check_vector_data ('alb [-] ', alb ) ! averaged albedo [-]
+ CALL check_vector_data ('ssun [-] ', ssun ) ! sunlit canopy absorption for solar radiation (0-1)
+ CALL check_vector_data ('ssha [-] ', ssha ) ! shaded canopy absorption for solar radiation (0-1)
+ CALL check_vector_data ('ssoi [-] ', ssoi ) ! soil absorption for solar radiation (0-1)
+ CALL check_vector_data ('ssno [-] ', ssno ) ! snow absorption for solar radiation (0-1)
+ CALL check_vector_data ('thermk [-] ', thermk ) ! canopy gap fraction for tir radiation
+ CALL check_vector_data ('extkb [-] ', extkb ) ! (k, g(mu)/mu) direct solar extinction coefficient
+ CALL check_vector_data ('extkd [-] ', extkd ) ! diffuse and scattered diffuse PAR extinction coefficient
+ CALL check_vector_data ('zwt [m] ', zwt ) ! the depth to water table [m]
+ CALL check_vector_data ('wa [mm] ', wa ) ! water storage in aquifer [mm]
+ CALL check_vector_data ('wetwat [mm] ', wetwat ) ! water storage in wetland [mm]
+ CALL check_vector_data ('wdsrf [mm] ', wdsrf ) ! depth of surface water [mm]
+ CALL check_vector_data ('rss [s/m] ', rss ) ! soil surface resistance [s/m]
+IF (DEF_USE_Dynamic_Lake) THEN
+ CALL check_vector_data ('dz_lake [m] ', dz_lake )!
+ENDIF
+ CALL check_vector_data ('t_lake [K] ', t_lake )!
+ CALL check_vector_data ('lake_icefrc [-] ', lake_icefrac)!
+ CALL check_vector_data ('savedtke1 [W/m K]', savedtke1 )!
+ CALL check_vector_data ('z_sno [m] ', z_sno ) ! node depth [m]
+ CALL check_vector_data ('dz_sno [m] ', dz_sno) ! interface depth [m]
+ CALL check_vector_data ('t_soisno [K] ', t_soisno ) ! soil temperature [K]
+ CALL check_vector_data ('wliq_soisno [kg/m2]', wliq_soisno) ! liquid water in layers [kg/m2]
+ CALL check_vector_data ('wice_soisno [kg/m2]', wice_soisno) ! ice lens in layers [kg/m2]
+ CALL check_vector_data ('smp [mm] ', smp ) ! soil matrix potential [mm]
+ CALL check_vector_data ('hk [mm/s] ', hk ) ! hydraulic conductivity [mm h2o/s]
+ CALL check_vector_data ('qsfc [kg/kg]', qsfc ) ! bulk surface/ground specific humidity
+ IF(DEF_USE_PLANTHYDRAULICS)THEN
+ CALL check_vector_data ('vegwp [m] ', vegwp ) ! vegetation water potential [mm]
+ CALL check_vector_data ('gs0sun [] ', gs0sun ) ! working copy of sunlit stomata conductance
+ CALL check_vector_data ('gs0sha [] ', gs0sha ) ! working copy of shaded stomata conductance
+ENDIF
+IF(DEF_USE_OZONESTRESS)THEN
+ CALL check_vector_data ('o3coefv_sun ', o3coefv_sun)
+ CALL check_vector_data ('o3coefv_sha ', o3coefv_sha)
+ CALL check_vector_data ('o3coefg_sun ', o3coefg_sun)
+ CALL check_vector_data ('o3coefg_sha ', o3coefg_sha)
+ CALL check_vector_data ('lai_old ', lai_old )
+ CALL check_vector_data ('o3uptakesun ', o3uptakesun)
+ CALL check_vector_data ('o3uptakesha ', o3uptakesha)
+ENDIF
+
+IF (DEF_USE_SNICAR) THEN
+ CALL check_vector_data ('snw_rds [m-6] ', snw_rds )
+ CALL check_vector_data ('mss_bcpho [Kg] ', mss_bcpho )
+ CALL check_vector_data ('mss_bcphi [Kg] ', mss_bcphi )
+ CALL check_vector_data ('mss_ocpho [Kg] ', mss_ocpho )
+ CALL check_vector_data ('mss_ocphi [Kg] ', mss_ocphi )
+ CALL check_vector_data ('mss_dst1 [Kg] ', mss_dst1 )
+ CALL check_vector_data ('mss_dst2 [Kg] ', mss_dst2 )
+ CALL check_vector_data ('mss_dst3 [Kg] ', mss_dst3 )
+ CALL check_vector_data ('mss_dst4 [Kg] ', mss_dst4 )
+ CALL check_vector_data ('ssno_lyr [-] ', ssno_lyr )
+ENDIF
+
+IF (DEF_USE_IRRIGATION) THEN
+ CALL check_vector_data ('irrig_rate ' , irrig_rate )
+ CALL check_vector_data ('deficit_irrig ' , deficit_irrig )
+ CALL check_vector_data ('actual_irrig ' , actual_irrig )
+ CALL check_vector_data ('sum_irrig ' , sum_irrig )
+ CALL check_vector_data ('sum_deficit_irrig ' , sum_deficit_irrig )
+ CALL check_vector_data ('sum_irrig_count ' , sum_irrig_count )
+ CALL check_vector_data ('n_irrig_steps_left ' , n_irrig_steps_left )
+ CALL check_vector_data ('waterstorage ' , waterstorage )
+ CALL check_vector_data ('waterstorage_supply ' , waterstorage_supply )
+ CALL check_vector_data ('groundwater_demand ' , groundwater_demand )
+ CALL check_vector_data ('groundwater_supply ' , groundwater_supply )
+ CALL check_vector_data ('reservoirriver_demand ' , reservoirriver_demand )
+ CALL check_vector_data ('reservoirriver_supply ' , reservoirriver_supply )
+ CALL check_vector_data ('irrig_method_corn ' , irrig_method_corn )
+ CALL check_vector_data ('irrig_method_swheat ' , irrig_method_swheat )
+ CALL check_vector_data ('irrig_method_wwheat ' , irrig_method_wwheat )
+ CALL check_vector_data ('irrig_method_soybean ' , irrig_method_soybean )
+ CALL check_vector_data ('irrig_method_cotton ' , irrig_method_cotton )
+ CALL check_vector_data ('irrig_method_rice1 ' , irrig_method_rice1 )
+ CALL check_vector_data ('irrig_method_rice2 ' , irrig_method_rice2 )
+ CALL check_vector_data ('irrig_method_sugarcane' , irrig_method_sugarcane)
+ CALL check_vector_data ('irrig_gw_alloc ' , irrig_gw_alloc )
+ CALL check_vector_data ('irrig_sw_alloc ' , irrig_sw_alloc )
+ CALL check_vector_data ('zwt_stand ' , zwt_stand )
+ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ CALL check_PFTimeVariables
+#endif
+
+#if (defined BGC)
+ CALL check_BGCTimeVariables
+#endif
+
+#ifdef EXTERNAL_LAKE
+ CALL CHECK_LakeTimeVars
+#endif
+
+#ifdef DataAssimilation
+ IF (DEF_DA_ENS_NUM > 1) CALL check_DATimeVariables
+#endif
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE check_TimeVariables
+#endif
+
+
+END MODULE MOD_Vars_TimeVariables
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_VicParaReadin.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_VicParaReadin.F90
new file mode 100644
index 0000000000..ea31551991
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_VicParaReadin.F90
@@ -0,0 +1,146 @@
+#include
+
+MODULE MOD_VicParaReadin
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ ! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: vicpara_readin
+CONTAINS
+
+ SUBROUTINE vicpara_readin ()
+ ! ===========================================================
+ ! ! DESCRIPTION:
+ ! Read in vic parameter from data
+
+ ! ===========================================================
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFBlock
+ ! USE MOD_Mapping_Grid2Pset
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Vars_TimeVariables
+ ! USE MOD_Grid
+ ! USE MOD_DataType
+ USE MOD_SpatialMapping
+ USE MOD_Vars_Global
+ USE MOD_LandPatch
+ USE MOD_RangeCheck
+ USE MOD_Block
+
+
+ IMPLICIT NONE
+ character(len=256) :: file_vic_para
+
+ type(grid_type) :: grid_b_infilt
+ type(grid_type) :: grid_Ws
+ type(grid_type) :: grid_Ds
+ type(grid_type) :: grid_DsM
+
+ type(block_data_real8_2d) :: f_xy_b_infilt
+ type(block_data_real8_2d) :: f_xy_Ws
+ type(block_data_real8_2d) :: f_xy_Ds
+ type(block_data_real8_2d) :: f_xy_DsM
+
+ type(spatial_mapping_type) :: mg2patch_b_infilt
+ type(spatial_mapping_type) :: mg2patch_Ws
+ type(spatial_mapping_type) :: mg2patch_Ds
+ type(spatial_mapping_type) :: mg2patch_DsM
+
+ real(r8) ,allocatable :: b_infilt_tmp (:)
+ real(r8) ,allocatable :: Ws_tmp (:)
+ real(r8) ,allocatable :: Ds_tmp (:)
+ real(r8) ,allocatable :: DsM_tmp (:)
+ ! Local variables
+ real(r8), allocatable :: lat(:), lon(:)
+ real(r8) :: missing_value
+ integer :: cft, npatch, ipft
+
+ file_vic_para = trim(DEF_file_VIC_OPT)
+
+ CALL ncio_read_bcast_serial (file_vic_para, 'lat', lat)
+ CALL ncio_read_bcast_serial (file_vic_para, 'lon', lon)
+
+
+ CALL grid_b_infilt%define_by_center (lat, lon)
+ CALL grid_Ws%define_by_center (lat, lon)
+ CALL grid_Ds%define_by_center (lat, lon)
+ CALL grid_DsM%define_by_center (lat, lon)
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (grid_b_infilt, f_xy_b_infilt)
+ CALL allocate_block_data (grid_Ws, f_xy_Ws)
+ CALL allocate_block_data (grid_Ds, f_xy_Ds)
+ CALL allocate_block_data (grid_DsM, f_xy_DsM)
+ ENDIF
+
+ IF (p_is_active) THEN
+ CALL ncio_read_block (file_vic_para,'b', grid_b_infilt, f_xy_b_infilt)
+ CALL ncio_read_block (file_vic_para,'Ws', grid_Ws, f_xy_Ws)
+ CALL ncio_read_block (file_vic_para,'Ds', grid_Ds, f_xy_Ds)
+ CALL ncio_read_block (file_vic_para,'DsM', grid_DsM, f_xy_DsM)
+ ENDIF
+
+ CALL mg2patch_b_infilt%build_arealweighted (grid_b_infilt, landpatch)
+ CALL mg2patch_Ws%build_arealweighted (grid_Ws, landpatch)
+ CALL mg2patch_Ds%build_arealweighted (grid_Ds, landpatch)
+ CALL mg2patch_DsM%build_arealweighted (grid_DsM, landpatch)
+
+
+
+ IF (allocated(lon)) deallocate(lon)
+ IF (allocated(lat)) deallocate(lat)
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) allocate (b_infilt_tmp (numpatch))
+ IF (numpatch > 0) allocate (Ws_tmp (numpatch))
+ IF (numpatch > 0) allocate (Ds_tmp (numpatch))
+ IF (numpatch > 0) allocate (DsM_tmp (numpatch))
+ ENDIF
+
+ CALL mg2patch_b_infilt%grid2pset (f_xy_b_infilt, b_infilt_tmp(:))
+ CALL mg2patch_Ws%grid2pset (f_xy_Ws, Ws_tmp(:))
+ CALL mg2patch_Ds%grid2pset (f_xy_Ds, Ds_tmp(:))
+ CALL mg2patch_DsM%grid2pset (f_xy_DsM, DsM_tmp(:))
+
+ IF (p_is_compute) THEN
+ vic_b_infilt(:) = -9999
+ vic_Dsmax(:) = -9999
+ vic_Ds(:) = -9999
+ vic_Ws(:) = -9999
+ vic_c = 2
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO ipft = 1, numpatch
+ !WRITE(*,*) 'Values of vic_b_infilt: ', DsM_tmp(ipft)
+ vic_b_infilt(ipft) = b_infilt_tmp(ipft)
+ vic_Ws(ipft) = Ws_tmp(ipft)
+ vic_Ds(ipft) = Ds_tmp(ipft)
+ vic_Dsmax(ipft) = DsM_tmp(ipft)
+ vic_c(ipft)=2
+ ENDDO
+ ! 输出 vic_b_infilt 数组的值
+ !WRITE(*,*) 'Values of vic_b_infilt: ', vic_b_infilt
+ ENDIF
+
+#ifdef RangeCheck
+ CALL check_vector_data ('vic_b_infilt', vic_b_infilt)
+ CALL check_vector_data ('vic_Ws', vic_Ws)
+ CALL check_vector_data ('vic_Ds', vic_Ds)
+ CALL check_vector_data ('vic_Dsmax', vic_Dsmax)
+#endif
+ IF (allocated (b_infilt_tmp)) deallocate (b_infilt_tmp)
+ IF (allocated (Ws_tmp)) deallocate (Ws_tmp)
+ IF (allocated (Ds_tmp)) deallocate (Ds_tmp)
+ IF (allocated (DsM_tmp)) deallocate (DsM_tmp)
+
+ END SUBROUTINE vicpara_readin
+END MODULE MOD_VicParaReadin
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_WetBulb.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_WetBulb.F90
new file mode 100644
index 0000000000..ca93a95083
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_WetBulb.F90
@@ -0,0 +1,119 @@
+MODULE MOD_WetBulb
+
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: wetbulb
+
+
+!-----------------------------------------------------------------------
+
+ CONTAINS
+
+!-----------------------------------------------------------------------
+
+
+ SUBROUTINE wetbulb(t,p,q,twc)
+
+!=======================================================================
+! Wet-bulb temperature
+!
+! Yongjiu Dai, 07/2013
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz, hvap, cpair
+ USE MOD_Qsadv
+
+ IMPLICIT NONE
+ real(r8), intent(in) :: t ! air temperature [K]
+ real(r8), intent(in) :: p ! atmos pressure [pa]
+ real(r8), intent(in) :: q ! air specific humidity [kg/kg]
+ real(r8), intent(out) :: twc ! wet bulb temperature [K]
+
+ integer i
+ real(r8) es, esdT, qs, qsdT, r, rws
+
+! ----------------------------------------------------------
+! real(r8) tcair ! dry-bulb temperature in celsius
+! real(r8) bp ! approximate average barometric pressure [mb]
+! real(r8) ea ! water vapor pressure in air [mb]
+! real(r8) eas ! saturated water vapor pressure in air [mb]
+! real(r8) delt ! delt=eas*4278.63/((tcair+242.792)*(tcair+242.792))
+! real(r8) tav ! average of dry-bulb temperature and wet bulb temperature in celsius
+! real(r8) eav ! eav=2.7489E8*exp(-4278.63/(tav+242.792))
+! real(r8) rh ! relative humidity
+! ----------------------------------------------------------
+! WETBULB computes wet-bulb temperatures from dry-bulb (tkair) and
+! vapor pressure of air(ea). routine adapted from e. anderson, p. 188.
+! ----------------------------------------------------------
+! CALL qsadv(t,p,es,esdT,qs,qsdT)
+! rh = min(1.0,q/qs)
+! bp = p/100.0 ! mb
+! eas = es/100.0 ! mb
+! ea = eas ! mb
+! delt = esdT/100. ! mb/K
+!
+! tcair = t - tfrz
+!
+!* eas = 2.7489e8*exp(-4278.63/(tcair+242.792))
+!* delt = eas*4278.63/((tcair+242.792)*(tcair+242.792))
+!
+! DO i = 1, 3
+! twc = delt*tcair+6.6e-4 *bp*tcair+7.59e-7*bp*tcair*tcair+ea-eas
+! twc = twc/(delt+6.6e-4*bp+7.59e-7*bp*tcair) ! in celsius
+!
+! tav = 0.5*(tcair+twc)+tfrz
+! CALL qsadv(tav,p,es,esdT,qs,qsdT)
+! eav = es/100.
+! delt = esdT/100.
+!
+!* tav = 0.5*(tcair+twc)
+!* eav = 2.7489e8*exp(-4278.63/(tav+242.792))
+!* delt = eav*4278.63/((tav+242.792)*(tav+242.792))
+! ENDDO
+! twc = twc + tfrz
+! ----------------------------------------------------------
+
+! ----------------------------------------------------------
+! the defining equation for the wetbulb temp Twb is
+! f(Twb) = Twb-T - Lv/Cp [r-rs(Twb)] = 0,
+! WHERE
+! T = the dry-bulb temp (K),
+! Lv = the latent heat of vaporization (J/kg/K),
+! Cp = the specific heat of air at constant pressure,
+! r = the water vapor mixing ratio [q/(1-q)],
+! rs(Twb) = the saturation mixing ratio at wetbulb temp.
+! http://www.asp.ucar.edu/colloquium/1992/notes/paet1/node81.html
+! ----------------------------------------------------------
+ CALL qsadv(t,p,es,esdT,qs,qsdT)
+ r = q/(1.0-q)
+ IF (q >= qs) r = qs/(1.0-qs)
+ twc = t
+ DO i = 1, 6
+ CALL qsadv(twc,p,es,esdT,qs,qsdT)
+ rws= qs/(1.0-qs)
+ twc = (twc + t + hvap/cpair*(r-rws))/2.0
+ ENDDO
+
+!*----------------------------------------------------------
+!*wetbulb temp as air temp and relative humidity at standard sea level pressure.
+!*valid for RH% (5%-99%), T (-20C-50C). R. Stull, 2011: Wet-bulb temperature form
+!*relative humidity and air temperature. J. Appl. Meteor. and Climatol., vol 50, 2267-2269.
+!*----------------------------------------------------------
+!* tcair = t - tfrz
+!* CALL qsadv(t,p,es,esdT,qs,qsdT)
+!* rh = min(1.0,q/qs)
+!* twc = tcair*atan(0.151977*(rh*100.+8.313659)**0.5) &
+!* + atan(tcair+rh*100.)-atan(rh*100.-1.676331) &
+!* + 0.00391838*(rh*100.)**1.5*atan(0.023101*rh*100.)-4.686035
+!* twc = twc + tfrz
+!*----------------------------------------------------------
+
+ END SUBROUTINE wetbulb
+
+END MODULE MOD_WetBulb
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_dataSpec_PDB.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_dataSpec_PDB.F90
new file mode 100644
index 0000000000..c66187ab10
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_dataSpec_PDB.F90
@@ -0,0 +1,1181 @@
+! ********************************************************************************
+! dataSpec_PDB.f90
+! ********************************************************************************
+! lambda = wavelength (nm)
+! refractive = refractive index of leaf material
+! k_Cab = specific absorption coefficient of chlorophyll (a+b) (cm2.�g-1)
+! k_Car = specific absorption coefficient of carotenoids (cm2.�g-1)
+! k_Anth = specific absorption coefficient of Anthocyanins (cm2.�g-1)
+! k_Cw = specific absorption coefficient of water (cm-1)
+! k_Cm = specific absorption coefficient of dry matter (cm2.g-1)
+! k_Bp = specific absorption coefficient of brown pigments (arbitrary units)
+! ********************************************************************************
+! Reference:
+! F�ret, Gitelson, Noble & Jacqumoud (2017). PROSPECT-D: Towards modeling
+! leaf optical properties through a complete lifecycle
+! Remote Sensing of Environment, 193:204�215
+! DOI: http://doi.org/10.1016/j.rse.2017.03.004
+! The specific absorption coefficient of brown pigments is provided by F. Baret
+! (EMMAH, INRA Avignon, baret@avignon.inra.fr) and used with his autorization.
+! ********************************************************************************
+! version 6.0 (16 January 2017)
+! ********************************************************************************
+
+module MOD_dataSpec_PDB
+
+USE MOD_Precision
+implicit none
+integer, parameter :: nw=2101
+integer i, lambda(nw)
+real(r8) refractive(nw), k_Cab(nw), k_Car(nw), k_Anth(nw), k_Brown(nw), k_Cw(nw), k_Cm(nw)
+
+
+! ********************************************************************************
+! Wavelength
+! ********************************************************************************
+ data (lambda(i),i=1,100)/&
+400,401,402,403,404,405,406,407,408,409,&
+410,411,412,413,414,415,416,417,418,419,&
+420,421,422,423,424,425,426,427,428,429,&
+430,431,432,433,434,435,436,437,438,439,&
+440,441,442,443,444,445,446,447,448,449,&
+450,451,452,453,454,455,456,457,458,459,&
+460,461,462,463,464,465,466,467,468,469,&
+470,471,472,473,474,475,476,477,478,479,&
+480,481,482,483,484,485,486,487,488,489,&
+490,491,492,493,494,495,496,497,498,499/
+ data (lambda(i),i=101,200)/&
+500,501,502,503,504,505,506,507,508,509,&
+510,511,512,513,514,515,516,517,518,519,&
+520,521,522,523,524,525,526,527,528,529,&
+530,531,532,533,534,535,536,537,538,539,&
+540,541,542,543,544,545,546,547,548,549,&
+550,551,552,553,554,555,556,557,558,559,&
+560,561,562,563,564,565,566,567,568,569,&
+570,571,572,573,574,575,576,577,578,579,&
+580,581,582,583,584,585,586,587,588,589,&
+590,591,592,593,594,595,596,597,598,599/
+ data (lambda(i),i=201,300)/&
+600,601,602,603,604,605,606,607,608,609,&
+610,611,612,613,614,615,616,617,618,619,&
+620,621,622,623,624,625,626,627,628,629,&
+630,631,632,633,634,635,636,637,638,639,&
+640,641,642,643,644,645,646,647,648,649,&
+650,651,652,653,654,655,656,657,658,659,&
+660,661,662,663,664,665,666,667,668,669,&
+670,671,672,673,674,675,676,677,678,679,&
+680,681,682,683,684,685,686,687,688,689,&
+690,691,692,693,694,695,696,697,698,699/
+ data (lambda(i),i=301,400)/&
+700,701,702,703,704,705,706,707,708,709,&
+710,711,712,713,714,715,716,717,718,719,&
+720,721,722,723,724,725,726,727,728,729,&
+730,731,732,733,734,735,736,737,738,739,&
+740,741,742,743,744,745,746,747,748,749,&
+750,751,752,753,754,755,756,757,758,759,&
+760,761,762,763,764,765,766,767,768,769,&
+770,771,772,773,774,775,776,777,778,779,&
+780,781,782,783,784,785,786,787,788,789,&
+790,791,792,793,794,795,796,797,798,799/
+ data (lambda(i),i=401,500)/&
+800,801,802,803,804,805,806,807,808,809,&
+810,811,812,813,814,815,816,817,818,819,&
+820,821,822,823,824,825,826,827,828,829,&
+830,831,832,833,834,835,836,837,838,839,&
+840,841,842,843,844,845,846,847,848,849,&
+850,851,852,853,854,855,856,857,858,859,&
+860,861,862,863,864,865,866,867,868,869,&
+870,871,872,873,874,875,876,877,878,879,&
+880,881,882,883,884,885,886,887,888,889,&
+890,891,892,893,894,895,896,897,898,899/
+ data (lambda(i),i=501,600)/&
+900,901,902,903,904,905,906,907,908,909,&
+910,911,912,913,914,915,916,917,918,919,&
+920,921,922,923,924,925,926,927,928,929,&
+930,931,932,933,934,935,936,937,938,939,&
+940,941,942,943,944,945,946,947,948,949,&
+950,951,952,953,954,955,956,957,958,959,&
+960,961,962,963,964,965,966,967,968,969,&
+970,971,972,973,974,975,976,977,978,979,&
+980,981,982,983,984,985,986,987,988,989,&
+990,991,992,993,994,995,996,997,998,999/
+ data (lambda(i),i=601,700)/&
+1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,&
+1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,&
+1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,&
+1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,&
+1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,&
+1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,&
+1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,&
+1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,&
+1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,&
+1090,1091,1092,1093,1094,1095,1096,1097,1098,1099/
+ data (lambda(i),i=701,800)/&
+1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,&
+1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,&
+1120,1121,1122,1123,1124,1125,1126,1127,1128,1129,&
+1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,&
+1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,&
+1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,&
+1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,&
+1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,&
+1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,&
+1190,1191,1192,1193,1194,1195,1196,1197,1198,1199/
+ data (lambda(i),i=801,900)/&
+1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,&
+1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,&
+1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,&
+1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,&
+1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,&
+1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,&
+1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,&
+1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,&
+1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,&
+1290,1291,1292,1293,1294,1295,1296,1297,1298,1299/
+ data (lambda(i),i=901,1000)/&
+1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,&
+1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,&
+1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,&
+1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,&
+1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,&
+1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,&
+1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,&
+1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,&
+1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,&
+1390,1391,1392,1393,1394,1395,1396,1397,1398,1399/
+ data (lambda(i),i=1001,1100)/&
+1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,&
+1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,&
+1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,&
+1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,&
+1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,&
+1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,&
+1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,&
+1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,&
+1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,&
+1490,1491,1492,1493,1494,1495,1496,1497,1498,1499/
+ data (lambda(i),i=1101,1200)/&
+1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,&
+1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,&
+1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,&
+1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,&
+1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,&
+1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,&
+1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,&
+1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,&
+1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,&
+1590,1591,1592,1593,1594,1595,1596,1597,1598,1599/
+ data (lambda(i),i=1201,1300)/&
+1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,&
+1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,&
+1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,&
+1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,&
+1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,&
+1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,&
+1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,&
+1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,&
+1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,&
+1690,1691,1692,1693,1694,1695,1696,1697,1698,1699/
+ data (lambda(i),i=1301,1400)/&
+1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,&
+1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,&
+1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,&
+1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,&
+1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,&
+1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,&
+1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,&
+1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,&
+1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,&
+1790,1791,1792,1793,1794,1795,1796,1797,1798,1799/
+ data (lambda(i),i=1401,1500)/&
+1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,&
+1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,&
+1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,&
+1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,&
+1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,&
+1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,&
+1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,&
+1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,&
+1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,&
+1890,1891,1892,1893,1894,1895,1896,1897,1898,1899/
+ data (lambda(i),i=1501,1600)/&
+1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,&
+1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,&
+1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,&
+1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,&
+1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,&
+1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,&
+1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,&
+1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,&
+1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,&
+1990,1991,1992,1993,1994,1995,1996,1997,1998,1999/
+ data (lambda(i),i=1601,1700)/&
+2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,&
+2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,&
+2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,&
+2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,&
+2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,&
+2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,&
+2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,&
+2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,&
+2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,&
+2090,2091,2092,2093,2094,2095,2096,2097,2098,2099/
+ data (lambda(i),i=1701,1800)/&
+2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,&
+2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,&
+2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,&
+2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,&
+2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,&
+2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,&
+2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,&
+2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,&
+2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,&
+2190,2191,2192,2193,2194,2195,2196,2197,2198,2199/
+ data (lambda(i),i=1801,1900)/&
+2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,&
+2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,&
+2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,&
+2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,&
+2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,&
+2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,&
+2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,&
+2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,&
+2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,&
+2290,2291,2292,2293,2294,2295,2296,2297,2298,2299/
+ data (lambda(i),i=1901,2000)/&
+2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,&
+2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,&
+2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,&
+2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,&
+2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,&
+2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,&
+2360,2361,2362,2363,2364,2365,2366,2367,2368,2369,&
+2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,&
+2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,&
+2390,2391,2392,2393,2394,2395,2396,2397,2398,2399/
+ data (lambda(i),i=2001,2101)/&
+2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,&
+2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,&
+2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,&
+2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,&
+2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,&
+2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,&
+2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,&
+2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,&
+2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,&
+2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,&
+2500./
+
+! ********************************************************************************
+! Refractive index
+! ********************************************************************************
+
+ data (refractive(i),i=1,100)/&
+1.5115,1.5115,1.5115,1.5115,1.5115,1.5115,1.5108,1.5101,1.5095,1.5088,&
+1.5081,1.5076,1.5071,1.5065,1.506,1.5055,1.505,1.5046,1.5041,1.5037,&
+1.5032,1.5029,1.5026,1.5022,1.5019,1.5016,1.5013,1.501,1.5008,1.5005,&
+1.5002,1.5,1.4997,1.4995,1.4992,1.499,1.4988,1.4986,1.4984,1.4982,&
+1.498,1.4977,1.4974,1.4972,1.4969,1.4966,1.4964,1.4962,1.4959,1.4957,&
+1.4955,1.4953,1.4951,1.4949,1.4947,1.4945,1.4943,1.4942,1.494,1.4939,&
+1.4937,1.4935,1.4934,1.4932,1.4931,1.4929,1.4928,1.4927,1.4925,1.4924,&
+1.4923,1.4922,1.492,1.4919,1.4917,1.4916,1.4915,1.4914,1.4912,1.4911,&
+1.491,1.4909,1.4907,1.4906,1.4904,1.4903,1.4902,1.49,1.4899,1.4897,&
+1.4896,1.4895,1.4893,1.4892,1.489,1.4889,1.4887,1.4885,1.4884,1.4882/
+ data (refractive(i),i=101,200)/&
+1.488,1.4878,1.4876,1.4875,1.4873,1.4871,1.4869,1.4867,1.4865,1.4863,&
+1.4861,1.4859,1.4856,1.4854,1.4851,1.4849,1.4846,1.4844,1.4841,1.4839,&
+1.4836,1.4833,1.483,1.4828,1.4825,1.4822,1.4819,1.4816,1.4813,1.481,&
+1.4807,1.4804,1.4801,1.4797,1.4794,1.4791,1.4788,1.4784,1.4781,1.4777,&
+1.4774,1.4771,1.4767,1.4764,1.476,1.4757,1.4753,1.475,1.4746,1.4743,&
+1.4739,1.4735,1.4732,1.4728,1.4725,1.4721,1.4717,1.4713,1.4709,1.4705,&
+1.4701,1.4697,1.4693,1.4689,1.4685,1.4681,1.4677,1.4673,1.467,1.4666,&
+1.4662,1.4658,1.4654,1.4651,1.4647,1.4643,1.4639,1.4635,1.4632,1.4628,&
+1.4624,1.462,1.4616,1.4613,1.4609,1.4605,1.4602,1.4598,1.4595,1.4591,&
+1.4588,1.4585,1.4582,1.4579,1.4576,1.4573,1.457,1.4567,1.4565,1.4562/
+ data (refractive(i),i=201,300)/&
+1.4559,1.4556,1.4553,1.4551,1.4548,1.4545,1.4543,1.454,1.4538,1.4535,&
+1.4533,1.4531,1.4528,1.4526,1.4523,1.4521,1.4519,1.4517,1.4514,1.4512,&
+1.451,1.4508,1.4506,1.4504,1.4502,1.45,1.4498,1.4497,1.4495,1.4494,&
+1.4492,1.4491,1.4489,1.4488,1.4486,1.4485,1.4484,1.4483,1.4482,1.4481,&
+1.448,1.4479,1.4478,1.4478,1.4477,1.4476,1.4475,1.4475,1.4474,1.4474,&
+1.4473,1.4473,1.4472,1.4472,1.4471,1.4471,1.447,1.447,1.4469,1.4469,&
+1.4468,1.4468,1.4468,1.4467,1.4467,1.4467,1.4466,1.4466,1.4465,1.4465,&
+1.4464,1.4464,1.4463,1.4463,1.4462,1.4462,1.4461,1.446,1.446,1.4459,&
+1.4458,1.4457,1.4457,1.4456,1.4456,1.4455,1.4454,1.4453,1.4453,1.4452,&
+1.4451,1.445,1.445,1.4449,1.4449,1.4448,1.4447,1.4446,1.4446,1.4445/
+ data (refractive(i),i=301,400)/&
+1.4444,1.4443,1.4442,1.4441,1.444,1.4439,1.4438,1.4437,1.4435,1.4434,&
+1.4433,1.4431,1.443,1.4428,1.4427,1.4425,1.4423,1.4422,1.442,1.4419,&
+1.4417,1.4415,1.4413,1.4411,1.4409,1.4407,1.4405,1.4403,1.4402,1.44,&
+1.4398,1.4396,1.4394,1.4393,1.4391,1.4389,1.4387,1.4385,1.4384,1.4382,&
+1.438,1.4378,1.4377,1.4375,1.4374,1.4372,1.4371,1.437,1.4368,1.4367,&
+1.4366,1.4364,1.4363,1.4361,1.436,1.4358,1.4357,1.4356,1.4354,1.4353,&
+1.4352,1.4351,1.435,1.4349,1.4348,1.4347,1.4346,1.4345,1.4345,1.4344,&
+1.4343,1.4343,1.4342,1.4342,1.4341,1.4341,1.4341,1.4341,1.434,1.434,&
+1.434,1.434,1.434,1.434,1.434,1.434,1.434,1.4341,1.4341,1.4342,&
+1.4342,1.4342,1.4342,1.4343,1.4343,1.4343,1.4343,1.4344,1.4344,1.4345/
+ data (refractive(i),i=401,500)/&
+1.4345,1.4345,1.4346,1.4346,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,&
+1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,&
+1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4348,1.4348,&
+1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,&
+1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4348,1.4347,1.4347,&
+1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4347,1.4346,1.4346,&
+1.4346,1.4346,1.4346,1.4345,1.4345,1.4345,1.4345,1.4345,1.4345,1.4345,&
+1.4345,1.4345,1.4345,1.4344,1.4344,1.4344,1.4344,1.4343,1.4343,1.4342,&
+1.4342,1.4342,1.4342,1.4341,1.4341,1.4341,1.4341,1.4341,1.434,1.434,&
+1.434,1.434,1.4339,1.4339,1.4338,1.4338,1.4338,1.4338,1.4337,1.4337/
+ data (refractive(i),i=501,600)/&
+1.4337,1.4337,1.4336,1.4336,1.4335,1.4335,1.4335,1.4335,1.4334,1.4334,&
+1.4334,1.4334,1.4333,1.4333,1.4332,1.4332,1.4332,1.4332,1.4331,1.4331,&
+1.4331,1.4331,1.433,1.433,1.4329,1.4329,1.4329,1.4328,1.4328,1.4327,&
+1.4327,1.4326,1.4326,1.4325,1.4325,1.4324,1.4324,1.4323,1.4323,1.4322,&
+1.4322,1.4322,1.4321,1.4321,1.432,1.432,1.432,1.4319,1.4319,1.4318,&
+1.4318,1.4318,1.4317,1.4317,1.4316,1.4316,1.4316,1.4315,1.4315,1.4314,&
+1.4314,1.4313,1.4313,1.4312,1.4312,1.4311,1.431,1.431,1.4309,1.4309,&
+1.4308,1.4307,1.4307,1.4306,1.4306,1.4305,1.4304,1.4304,1.4303,1.4303,&
+1.4302,1.4301,1.43,1.43,1.4299,1.4298,1.4297,1.4297,1.4296,1.4296,&
+1.4295,1.4294,1.4293,1.4293,1.4292,1.4291,1.429,1.4289,1.4289,1.4288/
+ data (refractive(i),i=601,700)/&
+1.4287,1.4286,1.4285,1.4285,1.4284,1.4283,1.4282,1.4281,1.4281,1.428,&
+1.4279,1.4278,1.4277,1.4276,1.4275,1.4274,1.4273,1.4272,1.4272,1.4271,&
+1.427,1.4269,1.4268,1.4267,1.4266,1.4265,1.4264,1.4263,1.4263,1.4262,&
+1.4261,1.426,1.4259,1.4258,1.4257,1.4256,1.4255,1.4254,1.4253,1.4252,&
+1.4251,1.425,1.4249,1.4248,1.4247,1.4246,1.4245,1.4244,1.4242,1.4241,&
+1.424,1.4239,1.4238,1.4237,1.4236,1.4235,1.4234,1.4233,1.4232,1.4231,&
+1.423,1.4229,1.4228,1.4226,1.4225,1.4224,1.4223,1.4222,1.422,1.4219,&
+1.4218,1.4217,1.4216,1.4215,1.4214,1.4213,1.4212,1.4211,1.4209,1.4208,&
+1.4207,1.4206,1.4205,1.4203,1.4202,1.4201,1.42,1.4199,1.4197,1.4196,&
+1.4195,1.4194,1.4193,1.4191,1.419,1.4189,1.4188,1.4187,1.4185,1.4184/
+ data (refractive(i),i=701,800)/&
+1.4183,1.4182,1.4181,1.4179,1.4178,1.4177,1.4176,1.4175,1.4173,1.4172,&
+1.4171,1.417,1.4169,1.4167,1.4166,1.4165,1.4164,1.4163,1.4161,1.416,&
+1.4159,1.4158,1.4157,1.4156,1.4155,1.4154,1.4153,1.4152,1.415,1.4149,&
+1.4148,1.4147,1.4146,1.4145,1.4144,1.4143,1.4142,1.4141,1.4139,1.4138,&
+1.4137,1.4136,1.4135,1.4133,1.4132,1.4131,1.413,1.4129,1.4128,1.4127,&
+1.4126,1.4125,1.4124,1.4122,1.4121,1.412,1.4119,1.4118,1.4117,1.4116,&
+1.4115,1.4114,1.4113,1.4111,1.411,1.4109,1.4108,1.4107,1.4106,1.4105,&
+1.4104,1.4103,1.4102,1.4101,1.41,1.4099,1.4098,1.4097,1.4096,1.4095,&
+1.4094,1.4093,1.4092,1.409,1.4089,1.4088,1.4087,1.4086,1.4085,1.4084,&
+1.4083,1.4082,1.4081,1.408,1.4079,1.4078,1.4077,1.4076,1.4075,1.4074/
+ data (refractive(i),i=801,900)/&
+1.4073,1.4072,1.4071,1.407,1.4069,1.4068,1.4067,1.4066,1.4065,1.4064,&
+1.4063,1.4062,1.4061,1.406,1.4059,1.4058,1.4057,1.4056,1.4054,1.4053,&
+1.4052,1.4051,1.405,1.4049,1.4048,1.4047,1.4046,1.4045,1.4044,1.4043,&
+1.4042,1.4041,1.404,1.4038,1.4037,1.4036,1.4035,1.4034,1.4033,1.4032,&
+1.4031,1.403,1.4029,1.4028,1.4027,1.4026,1.4025,1.4024,1.4023,1.4022,&
+1.4021,1.402,1.4019,1.4017,1.4016,1.4015,1.4014,1.4013,1.4012,1.4011,&
+1.401,1.4009,1.4008,1.4007,1.4006,1.4005,1.4004,1.4003,1.4001,1.4,&
+1.3999,1.3998,1.3997,1.3996,1.3995,1.3994,1.3993,1.3992,1.3991,1.399,&
+1.3989,1.3988,1.3987,1.3985,1.3984,1.3983,1.3982,1.3981,1.398,1.3979,&
+1.3978,1.3977,1.3976,1.3975,1.3974,1.3973,1.3972,1.3971,1.397,1.3969/
+ data (refractive(i),i=901,1000)/&
+1.3968,1.3967,1.3966,1.3965,1.3964,1.3963,1.3962,1.3961,1.396,1.3959,&
+1.3958,1.3957,1.3956,1.3955,1.3954,1.3953,1.3952,1.3951,1.3949,1.3948,&
+1.3947,1.3946,1.3945,1.3944,1.3943,1.3942,1.3941,1.394,1.3939,1.3938,&
+1.3937,1.3936,1.3935,1.3934,1.3933,1.3932,1.3931,1.393,1.3929,1.3928,&
+1.3927,1.3926,1.3925,1.3924,1.3923,1.3922,1.3921,1.392,1.3919,1.3918,&
+1.3917,1.3916,1.3915,1.3914,1.3913,1.3912,1.3911,1.391,1.3909,1.3908,&
+1.3907,1.3906,1.3905,1.3904,1.3903,1.3902,1.3901,1.39,1.3899,1.3898,&
+1.3897,1.3896,1.3895,1.3893,1.3892,1.3891,1.389,1.3889,1.3888,1.3887,&
+1.3886,1.3885,1.3884,1.3883,1.3882,1.3881,1.388,1.3879,1.3877,1.3876,&
+1.3875,1.3874,1.3873,1.3872,1.3871,1.387,1.3869,1.3868,1.3867,1.3866/
+ data (refractive(i),i=1001,1100)/&
+1.3865,1.3864,1.3863,1.3861,1.386,1.3859,1.3858,1.3857,1.3855,1.3854,&
+1.3853,1.3852,1.3851,1.3849,1.3848,1.3847,1.3846,1.3845,1.3843,1.3842,&
+1.3841,1.384,1.3839,1.3837,1.3836,1.3835,1.3834,1.3833,1.3831,1.383,&
+1.3829,1.3828,1.3826,1.3825,1.3823,1.3822,1.3821,1.382,1.3818,1.3817,&
+1.3816,1.3815,1.3813,1.3812,1.381,1.3809,1.3808,1.3807,1.3805,1.3804,&
+1.3803,1.3802,1.38,1.3799,1.3797,1.3796,1.3794,1.3793,1.3791,1.379,&
+1.3788,1.3787,1.3785,1.3784,1.3782,1.3781,1.3779,1.3778,1.3776,1.3775,&
+1.3773,1.3772,1.377,1.3769,1.3767,1.3766,1.3764,1.3763,1.3761,1.376,&
+1.3758,1.3756,1.3755,1.3753,1.3752,1.375,1.3748,1.3747,1.3745,1.3744,&
+1.3742,1.374,1.3739,1.3737,1.3736,1.3734,1.3732,1.3731,1.3729,1.3728/
+ data (refractive(i),i=1101,1200)/&
+1.3726,1.3724,1.3723,1.3721,1.372,1.3718,1.3716,1.3715,1.3713,1.3712,&
+1.371,1.3708,1.3706,1.3705,1.3703,1.3701,1.3699,1.3698,1.3696,1.3695,&
+1.3693,1.3692,1.369,1.3689,1.3687,1.3686,1.3684,1.3683,1.3681,1.368,&
+1.3678,1.3676,1.3675,1.3673,1.3672,1.367,1.3668,1.3666,1.3665,1.3663,&
+1.3661,1.3659,1.3658,1.3656,1.3655,1.3653,1.3651,1.365,1.3648,1.3647,&
+1.3645,1.3643,1.3641,1.364,1.3638,1.3636,1.3634,1.3633,1.3631,1.363,&
+1.3628,1.3626,1.3625,1.3623,1.3622,1.362,1.3618,1.3617,1.3615,1.3614,&
+1.3612,1.361,1.3608,1.3607,1.3605,1.3603,1.3601,1.36,1.3598,1.3597,&
+1.3595,1.3593,1.3592,1.359,1.3589,1.3587,1.3585,1.3584,1.3582,1.3581,&
+1.3579,1.3577,1.3576,1.3574,1.3573,1.3571,1.3569,1.3568,1.3566,1.3565/
+ data (refractive(i),i=1201,1300)/&
+1.3563,1.3561,1.356,1.3558,1.3557,1.3555,1.3553,1.3552,1.355,1.3549,&
+1.3547,1.3545,1.3544,1.3542,1.3541,1.3539,1.3537,1.3536,1.3534,1.3533,&
+1.3531,1.3529,1.3528,1.3526,1.3525,1.3523,1.3521,1.352,1.3518,1.3517,&
+1.3515,1.3513,1.3512,1.351,1.3509,1.3507,1.3505,1.3504,1.3502,1.3501,&
+1.3499,1.3498,1.3496,1.3495,1.3493,1.3492,1.349,1.3489,1.3487,1.3486,&
+1.3484,1.3482,1.3481,1.3479,1.3478,1.3476,1.3475,1.3473,1.3472,1.347,&
+1.3469,1.3467,1.3466,1.3464,1.3463,1.3461,1.3459,1.3458,1.3456,1.3455,&
+1.3453,1.3452,1.345,1.3449,1.3447,1.3446,1.3445,1.3443,1.3442,1.344,&
+1.3439,1.3438,1.3436,1.3435,1.3433,1.3432,1.3431,1.3429,1.3428,1.3426,&
+1.3425,1.3424,1.3422,1.3421,1.3419,1.3418,1.3417,1.3415,1.3414,1.3412/
+ data (refractive(i),i=1301,1400)/&
+1.3411,1.341,1.3409,1.3407,1.3406,1.3405,1.3404,1.3402,1.3401,1.3399,&
+1.3398,1.3397,1.3396,1.3394,1.3393,1.3392,1.3391,1.339,1.3388,1.3387,&
+1.3386,1.3385,1.3383,1.3382,1.338,1.3379,1.3378,1.3377,1.3376,1.3375,&
+1.3374,1.3373,1.3372,1.337,1.3369,1.3368,1.3367,1.3366,1.3365,1.3364,&
+1.3363,1.3362,1.3361,1.3359,1.3358,1.3357,1.3356,1.3355,1.3354,1.3353,&
+1.3352,1.3351,1.335,1.3349,1.3348,1.3347,1.3346,1.3345,1.3344,1.3343,&
+1.3342,1.3341,1.334,1.3339,1.3338,1.3337,1.3336,1.3335,1.3334,1.3333,&
+1.3332,1.3331,1.333,1.3329,1.3328,1.3327,1.3326,1.3325,1.3324,1.3323,&
+1.3322,1.3321,1.332,1.332,1.3319,1.3318,1.3317,1.3316,1.3316,1.3315,&
+1.3314,1.3313,1.3312,1.3311,1.331,1.3309,1.3308,1.3307,1.3307,1.3306/
+ data (refractive(i),i=1401,1500)/&
+1.3305,1.3304,1.3303,1.3303,1.3302,1.3301,1.33,1.3299,1.3299,1.3298,&
+1.3297,1.3296,1.3295,1.3295,1.3294,1.3293,1.3292,1.3291,1.3291,1.329,&
+1.3289,1.3288,1.3287,1.3287,1.3286,1.3285,1.3284,1.3283,1.3283,1.3282,&
+1.3281,1.328,1.3279,1.3279,1.3278,1.3277,1.3276,1.3275,1.3275,1.3274,&
+1.3273,1.3272,1.3271,1.3271,1.327,1.3269,1.3268,1.3268,1.3267,1.3267,&
+1.3266,1.3265,1.3264,1.3264,1.3263,1.3262,1.3261,1.3261,1.326,1.326,&
+1.3259,1.3258,1.3257,1.3257,1.3256,1.3255,1.3254,1.3254,1.3253,1.3253,&
+1.3252,1.3251,1.325,1.325,1.3249,1.3248,1.3247,1.3247,1.3246,1.3246,&
+1.3245,1.3244,1.3243,1.3243,1.3242,1.3241,1.324,1.324,1.3239,1.3239,&
+1.3238,1.3237,1.3236,1.3236,1.3235,1.3234,1.3233,1.3233,1.3232,1.3232/
+ data (refractive(i),i=1501,1600)/&
+1.3231,1.323,1.323,1.3229,1.3229,1.3228,1.3227,1.3227,1.3226,1.3226,&
+1.3225,1.3224,1.3224,1.3223,1.3223,1.3222,1.3221,1.322,1.322,1.3219,&
+1.3218,1.3217,1.3217,1.3216,1.3216,1.3215,1.3214,1.3213,1.3213,1.3212,&
+1.3211,1.321,1.321,1.3209,1.3209,1.3208,1.3207,1.3206,1.3206,1.3205,&
+1.3204,1.3203,1.3203,1.3202,1.3202,1.3201,1.32,1.32,1.3199,1.3199,&
+1.3198,1.3197,1.3197,1.3196,1.3196,1.3195,1.3194,1.3193,1.3193,1.3192,&
+1.3191,1.319,1.319,1.3189,1.3189,1.3188,1.3187,1.3186,1.3186,1.3185,&
+1.3184,1.3183,1.3183,1.3182,1.3182,1.3181,1.318,1.3179,1.3179,1.3178,&
+1.3177,1.3176,1.3175,1.3175,1.3174,1.3173,1.3172,1.3171,1.3171,1.317,&
+1.3169,1.3168,1.3167,1.3167,1.3166,1.3165,1.3164,1.3163,1.3163,1.3162/
+ data (refractive(i),i=1601,1700)/&
+1.3161,1.316,1.3159,1.3159,1.3158,1.3157,1.3156,1.3155,1.3154,1.3153,&
+1.3152,1.3151,1.315,1.315,1.3149,1.3148,1.3147,1.3146,1.3146,1.3145,&
+1.3144,1.3143,1.3142,1.3141,1.314,1.3139,1.3138,1.3137,1.3136,1.3135,&
+1.3134,1.3133,1.3132,1.3131,1.313,1.3129,1.3128,1.3127,1.3126,1.3125,&
+1.3124,1.3123,1.3122,1.3121,1.312,1.3119,1.3118,1.3117,1.3116,1.3115,&
+1.3114,1.3113,1.3112,1.311,1.3109,1.3108,1.3107,1.3106,1.3105,1.3104,&
+1.3103,1.3102,1.3101,1.3099,1.3098,1.3097,1.3096,1.3095,1.3094,1.3093,&
+1.3092,1.3091,1.309,1.3088,1.3087,1.3086,1.3085,1.3084,1.3082,1.3081,&
+1.308,1.3079,1.3078,1.3076,1.3075,1.3074,1.3073,1.3072,1.307,1.3069,&
+1.3068,1.3067,1.3066,1.3064,1.3063,1.3062,1.3061,1.306,1.3059,1.3058/
+ data (refractive(i),i=1701,1800)/&
+1.3057,1.3056,1.3055,1.3053,1.3052,1.3051,1.305,1.3049,1.3047,1.3046,&
+1.3045,1.3044,1.3043,1.3041,1.304,1.3039,1.3038,1.3037,1.3035,1.3034,&
+1.3033,1.3032,1.3031,1.3029,1.3028,1.3027,1.3026,1.3025,1.3023,1.3022,&
+1.3021,1.302,1.3019,1.3017,1.3016,1.3015,1.3014,1.3013,1.3011,1.301,&
+1.3009,1.3008,1.3007,1.3005,1.3004,1.3003,1.3002,1.3001,1.2999,1.2998,&
+1.2997,1.2996,1.2995,1.2993,1.2992,1.2991,1.299,1.2989,1.2987,1.2986,&
+1.2985,1.2984,1.2983,1.2981,1.298,1.2979,1.2978,1.2977,1.2975,1.2974,&
+1.2973,1.2972,1.297,1.2969,1.2967,1.2966,1.2965,1.2964,1.2962,1.2961,&
+1.296,1.2959,1.2958,1.2957,1.2956,1.2955,1.2954,1.2953,1.2951,1.295,&
+1.2949,1.2948,1.2947,1.2945,1.2944,1.2943,1.2942,1.2941,1.2939,1.2938/
+ data (refractive(i),i=1801,1900)/&
+1.2937,1.2936,1.2935,1.2933,1.2932,1.2931,1.293,1.2928,1.2927,1.2925,&
+1.2924,1.2923,1.2922,1.292,1.2919,1.2918,1.2917,1.2916,1.2914,1.2913,&
+1.2912,1.2911,1.291,1.2908,1.2907,1.2906,1.2905,1.2904,1.2902,1.2901,&
+1.29,1.2899,1.2898,1.2896,1.2895,1.2894,1.2893,1.2892,1.289,1.2889,&
+1.2888,1.2887,1.2886,1.2884,1.2883,1.2882,1.2881,1.288,1.2878,1.2877,&
+1.2876,1.2875,1.2874,1.2873,1.2872,1.2871,1.287,1.2869,1.2867,1.2866,&
+1.2865,1.2864,1.2863,1.2862,1.2861,1.286,1.2859,1.2858,1.2856,1.2855,&
+1.2854,1.2853,1.2852,1.285,1.2849,1.2848,1.2847,1.2846,1.2845,1.2844,&
+1.2843,1.2842,1.2841,1.284,1.2839,1.2838,1.2837,1.2836,1.2834,1.2833,&
+1.2832,1.2831,1.283,1.2829,1.2828,1.2827,1.2826,1.2825,1.2824,1.2823/
+ data (refractive(i),i=1901,2000)/&
+1.2822,1.2821,1.282,1.2818,1.2817,1.2816,1.2815,1.2814,1.2813,1.2812,&
+1.2811,1.281,1.2809,1.2808,1.2807,1.2806,1.2805,1.2804,1.2803,1.2802,&
+1.2801,1.28,1.2799,1.2799,1.2798,1.2797,1.2796,1.2795,1.2795,1.2794,&
+1.2793,1.2792,1.2791,1.2791,1.279,1.2789,1.2788,1.2788,1.2787,1.2787,&
+1.2786,1.2785,1.2785,1.2784,1.2784,1.2783,1.2782,1.2781,1.278,1.2779,&
+1.2778,1.2777,1.2776,1.2776,1.2775,1.2774,1.2773,1.2772,1.2771,1.277,&
+1.2769,1.2768,1.2767,1.2766,1.2765,1.2764,1.2763,1.2762,1.2761,1.276,&
+1.2759,1.2758,1.2757,1.2757,1.2756,1.2755,1.2754,1.2753,1.2753,1.2752,&
+1.2751,1.275,1.2749,1.2749,1.2748,1.2747,1.2746,1.2745,1.2745,1.2744,&
+1.2743,1.2742,1.2742,1.2741,1.2741,1.274,1.2739,1.2739,1.2738,1.2738/
+ data (refractive(i),i=2001,2101)/&
+1.2737,1.2736,1.2736,1.2735,1.2735,1.2734,1.2733,1.2733,1.2732,1.2732,&
+1.2731,1.273,1.273,1.2729,1.2729,1.2728,1.2727,1.2727,1.2726,1.2726,&
+1.2725,1.2725,1.2724,1.2724,1.2723,1.2723,1.2722,1.2722,1.2721,1.2721,&
+1.272,1.272,1.2719,1.2719,1.2718,1.2718,1.2717,1.2717,1.2716,1.2716,&
+1.2715,1.2715,1.2714,1.2714,1.2713,1.2713,1.2713,1.2713,1.2712,1.2712,&
+1.2712,1.2712,1.2711,1.2711,1.271,1.271,1.271,1.271,1.2709,1.2709,&
+1.2709,1.2709,1.2709,1.2708,1.2708,1.2708,1.2708,1.2708,1.2708,1.2708,&
+1.2708,1.2708,1.2708,1.2708,1.2708,1.2708,1.2708,1.2709,1.2709,1.271,&
+1.271,1.2711,1.2712,1.2712,1.2713,1.2714,1.2715,1.2716,1.2717,1.2718,&
+1.2719,1.272,1.2722,1.2723,1.2725,1.2726,1.2728,1.273,1.2732,1.2734,&
+1.2736/
+
+! ********************************************************************************
+! Specific absorption coefficient of chlorophyll
+! ********************************************************************************
+
+ data (k_Cab(i),i=1,100)/&
+0.064881,0.066732,0.068551,0.069982,0.0709,0.071333,0.07132,0.07126,0.071223,0.071228,&
+0.071491,0.071888,0.072018,0.071827,0.071493,0.071132,0.070763,0.070437,0.070094,0.06984,&
+0.069819,0.070054,0.070281,0.070503,0.070473,0.070528,0.070809,0.071312,0.071622,0.071905,&
+0.072449,0.073091,0.073652,0.074047,0.074335,0.074542,0.074691,0.074653,0.07457,0.074285,&
+0.073794,0.072818,0.071622,0.070459,0.069105,0.067568,0.066026,0.064492,0.062668,0.060755,&
+0.058775,0.056778,0.054732,0.052844,0.051125,0.049573,0.048139,0.046801,0.045645,0.044691,&
+0.043873,0.043162,0.042653,0.042206,0.041774,0.041297,0.040911,0.040571,0.040302,0.040009,&
+0.039727,0.039521,0.039292,0.039035,0.038773,0.038523,0.03826,0.037881,0.03751,0.037149,&
+0.036776,0.0363,0.035761,0.03521,0.034583,0.033909,0.033184,0.032377,0.031519,0.030584,&
+0.029662,0.028699,0.027692,0.02664,0.02559,0.024517,0.023428,0.022328,0.021224,0.020137/
+ data (k_Cab(i),i=101,200)/&
+0.019048,0.01798,0.016943,0.015923,0.014934,0.013979,0.01305,0.012154,0.011296,0.01048,&
+0.0097008,0.008954,0.0082461,0.00758,0.0069574,0.0063867,0.005868,0.0054015,0.0049913,0.0046349,&
+0.0043338,0.004085,0.0038874,0.0037421,0.0036525,0.0036118,0.0036193,0.0036728,0.0037697,0.0039032,&
+0.004069,0.0042637,0.0044843,0.00473,0.0049935,0.0052728,0.0055645,0.0058662,0.0061706,0.0064792,&
+0.0067864,0.00709,0.007388,0.0076742,0.0079483,0.0082083,0.0084536,0.008685,0.0089037,0.0091119,&
+0.0093094,0.0095001,0.0096821,0.0098639,0.01004,0.010214,0.010386,0.010556,0.010724,0.010889,&
+0.011048,0.011217,0.011402,0.011605,0.011827,0.012075,0.01234,0.012628,0.012933,0.01326,&
+0.013598,0.013947,0.014301,0.014658,0.01501,0.015357,0.015693,0.016023,0.01634,0.016648,&
+0.016945,0.017241,0.017527,0.017801,0.018066,0.018325,0.018568,0.0188,0.019019,0.019228,&
+0.019419,0.019599,0.019766,0.019922,0.020066,0.020199,0.020327,0.020458,0.020585,0.020715/
+ data (k_Cab(i),i=201,300)/&
+0.020854,0.021007,0.021172,0.021348,0.021546,0.021764,0.022003,0.022268,0.022553,0.022859,&
+0.023177,0.023502,0.023842,0.024199,0.024561,0.024917,0.025269,0.025617,0.02595,0.026255,&
+0.02653,0.026786,0.02701,0.027207,0.027379,0.027523,0.027645,0.027739,0.027821,0.027895,&
+0.027978,0.028072,0.028194,0.02836,0.028573,0.028846,0.029181,0.029599,0.030077,0.030634,&
+0.031248,0.031927,0.032659,0.033441,0.034255,0.035101,0.035949,0.036779,0.037588,0.038323,&
+0.039014,0.039631,0.040222,0.040804,0.041418,0.042107,0.04288,0.043808,0.044861,0.046107,&
+0.047495,0.049113,0.050849,0.05273,0.0547,0.056761,0.058868,0.06083,0.06275,0.064472,&
+0.066112,0.067471,0.068675,0.069635,0.070465,0.070995,0.071402,0.071358,0.071127,0.070185,&
+0.068921,0.066576,0.063948,0.060482,0.056858,0.052747,0.048726,0.044707,0.040858,0.037141,&
+0.033671,0.030459,0.027502,0.024787,0.02233,0.020144,0.018173,0.016421,0.014852,0.013471/
+ data (k_Cab(i),i=301,400)/&
+0.012241,0.011155,0.010193,0.009343,0.0085869,0.007915,0.0073126,0.0067711,0.0062803,0.0058322,&
+0.0054214,0.0050449,0.0046965,0.0043735,0.004072,0.0037922,0.0035302,0.0032856,0.0030575,0.0028435,&
+0.0026434,0.0024563,0.0022809,0.0021168,0.0019636,0.0018206,0.0016869,0.0015628,0.0014468,0.0013388,&
+0.0012386,0.0011459,0.0010591,0.00097828,0.00090409,0.00083609,0.00077289,0.00071503,0.00066162,0.00061235,&
+0.00056764,0.00052722,0.00048994,0.00045636,0.00042566,0.00039812,0.00037316,0.00035104,0.00033141,0.00031371,&
+0.00029841,0.00028315,0.00026796,0.00025289,0.00023795,0.00022319,0.00020864,0.00019431,0.00018026,0.00016649,&
+0.00015306,0.00013998,0.00012729,0.00011501,0.00010319,9.1841e-05,8.1005e-05,7.0709e-05,6.0985e-05,5.1862e-05,&
+4.3372e-05,3.5545e-05,2.8412e-05,2.2003e-05,1.6349e-05,1.1481e-05,7.4298e-06,4.2252e-06,1.8983e-06,4.7969e-07,&
+1.0525e-13,0,0,0,0,0,0,0,0,0,&
+0,0,0,0,0,0,0,0,0,0/
+ data (k_Cab(i),i=401,2101)/1701*0./
+
+! ********************************************************************************
+! Specific absorption coefficient of carotenoids
+! ********************************************************************************
+
+ data (k_Car(i),i=1,100)/&
+0.16734,0.16761,0.16718,0.16721,0.16761,0.1676,0.16751,0.16743,0.16724,0.16668,&
+0.16588,0.16552,0.16545,0.16569,0.16609,0.16619,0.16629,0.16646,0.16662,0.16687,&
+0.16716,0.16754,0.16798,0.16844,0.1686,0.16847,0.16814,0.168,0.16773,0.16741,&
+0.16755,0.16774,0.16791,0.16797,0.16794,0.16797,0.16818,0.16832,0.1687,0.16916,&
+0.16957,0.16968,0.16963,0.1699,0.16991,0.16981,0.16977,0.16973,0.16935,0.16857,&
+0.16744,0.16602,0.16446,0.1629,0.16136,0.15978,0.15822,0.15656,0.15497,0.1533,&
+0.15167,0.14997,0.14832,0.14677,0.14508,0.14349,0.142,0.14055,0.13919,0.13802,&
+0.13701,0.13614,0.13548,0.135,0.13464,0.13437,0.13417,0.13394,0.13375,0.13356,&
+0.13327,0.13279,0.13217,0.13141,0.13042,0.12922,0.12782,0.12631,0.12457,0.12269,&
+0.12066,0.1186,0.11652,0.11441,0.11227,0.11011,0.10793,0.10573,0.1035,0.10126/
+ data (k_Car(i),i=101,200)/&
+0.099004,0.096734,0.09445,0.092156,0.089854,0.087544,0.085228,0.082909,0.080588,0.078267,&
+0.075947,0.073631,0.071319,0.069014,0.066717,0.064431,0.062156,0.059895,0.057649,0.055421,&
+0.053211,0.051021,0.048854,0.04671,0.044592,0.042502,0.040441,0.03841,0.036412,0.034449,&
+0.032521,0.030631,0.028781,0.026971,0.025205,0.023483,0.021808,0.020181,0.018603,0.017077,&
+0.015605,0.014187,0.012826,0.011524,0.010282,0.0091015,0.0079848,0.0069335,0.0059492,0.0050338,&
+0.004189,0.0034164,0.0027178,0.0020949,0.0015495,0.0010832,0.00069786,0.00039514,0.00017677,4.448e-05,&
+2.1316e-13,0,0,0,0,0,0,0,0,0,&
+0,0,0,0,0,0,0,0,0,0,&
+0,0,0,0,0,0,0,0,0,0,&
+0,0,0,0,0,0,0,0,0,0/
+ data (k_Car(i),i=201,2101)/1901*0./
+
+! ********************************************************************************
+! Specific absorption coefficient of anthocyanins
+! ********************************************************************************
+
+ data (k_Anth(i),i=1,100)/&
+0.066675,0.064056,0.061933,0.059922,0.058277,0.056699,0.055366,0.054163,0.053116,0.05198,&
+0.050951,0.050117,0.049387,0.048604,0.047876,0.047379,0.046899,0.046532,0.046157,0.045792,&
+0.045429,0.045144,0.044845,0.044536,0.044249,0.044116,0.043958,0.043874,0.043805,0.043858,&
+0.043861,0.043912,0.043959,0.044037,0.04411,0.044203,0.044277,0.044399,0.04451,0.044647,&
+0.044787,0.044919,0.045061,0.045227,0.045415,0.045589,0.045753,0.045857,0.045994,0.046195,&
+0.046414,0.04668,0.046953,0.047162,0.04736,0.047593,0.047814,0.048082,0.048335,0.048595,&
+0.048839,0.049123,0.04937,0.049608,0.049841,0.050136,0.05042,0.050784,0.05115,0.051557,&
+0.051941,0.052387,0.05282,0.053409,0.05399,0.054462,0.05494,0.055543,0.056155,0.056638,&
+0.057152,0.057689,0.058265,0.058847,0.059478,0.060054,0.06067,0.061221,0.061809,0.062358,&
+0.062922,0.063434,0.06397,0.064462,0.064964,0.065431,0.06591,0.066378,0.066852,0.067309/
+ data (k_Anth(i),i=101,200)/&
+0.067771,0.068133,0.068479,0.068815,0.06914,0.069362,0.069563,0.069828,0.070073,0.070279,&
+0.070472,0.070679,0.070872,0.071025,0.071165,0.071285,0.07139,0.071486,0.071573,0.07163,&
+0.071682,0.071739,0.071775,0.071815,0.071864,0.071959,0.07206,0.072153,0.07224,0.072295,&
+0.072349,0.072414,0.072476,0.07251,0.072528,0.072529,0.072506,0.072433,0.07234,0.07221,&
+0.072063,0.071837,0.071602,0.071343,0.071067,0.070707,0.070307,0.06984,0.069355,0.068756,&
+0.06814,0.06744,0.066733,0.065904,0.065061,0.06421,0.063357,0.062437,0.061518,0.060579,&
+0.059652,0.058611,0.057591,0.056554,0.055543,0.054379,0.053243,0.052056,0.0509,0.049671,&
+0.048481,0.047309,0.046174,0.045,0.043871,0.042781,0.041734,0.040618,0.039543,0.038457,&
+0.037412,0.0362,0.035043,0.033919,0.032846,0.031701,0.030606,0.029616,0.028665,0.027715,&
+0.026803,0.025951,0.025134,0.024293,0.023487,0.022687,0.021918,0.021085,0.020284,0.019497/
+ data (k_Anth(i),i=201,300)/&
+0.01874,0.017977,0.017242,0.016604,0.015987,0.01541,0.014845,0.014317,0.0138,0.013295,&
+0.012801,0.012336,0.011884,0.011394,0.010918,0.010464,0.010022,0.0095808,0.0091553,0.0087766,&
+0.008411,0.0080523,0.0077073,0.0073755,0.0070567,0.0067504,0.0064566,0.0061747,0.0059044,0.0056455,&
+0.0053977,0.0051604,0.0049336,0.0047168,0.0045097,0.004312,0.0041234,0.0039435,0.003772,0.0036087,&
+0.003453,0.0033048,0.0031638,0.0030295,0.0029017,0.00278,0.0026642,0.0025538,0.0024487,0.0023483,&
+0.0022525,0.0021608,0.0020731,0.0019889,0.0019079,0.0018298,0.0017542,0.0016809,0.0016096,0.0015398,&
+0.0014713,0.0014037,0.0013368,0.0012702,0.0012035,0.0011365,0.0010688,0.0010001,0.00093008,0.00085841,&
+0.00078476,0.00071002,0.00063884,0.00057124,0.00050727,0.00044695,0.0003903,0.00033737,0.00028817,0.00024273,&
+0.0002011,0.00016329,0.00012933,9.9259e-05,7.3102e-05,5.0888e-05,3.2647e-05,1.8408e-05,8.2009e-06,2.0551e-06,&
+0,0,0,0,0,0,0,0,0,0/
+ data (k_Anth(i),i=301,2101)/1801*0./
+
+! ********************************************************************************
+! Specific absorption coefficient of brown pigments
+! ********************************************************************************
+
+ data (k_Brown(i),i=1,100)/&
+5.272e-01,5.262e-01,5.252e-01,5.242e-01,5.232e-01,5.222e-01,5.212e-01,5.202e-01,5.192e-01,5.182e-01,&
+5.172e-01,5.162e-01,5.152e-01,5.142e-01,5.132e-01,5.122e-01,5.112e-01,5.102e-01,5.092e-01,5.082e-01,&
+5.072e-01,5.062e-01,5.052e-01,5.042e-01,5.032e-01,5.022e-01,5.012e-01,5.002e-01,4.992e-01,4.982e-01,&
+4.972e-01,4.960e-01,4.948e-01,4.936e-01,4.924e-01,4.912e-01,4.900e-01,4.888e-01,4.876e-01,4.864e-01,&
+4.852e-01,4.840e-01,4.829e-01,4.817e-01,4.805e-01,4.793e-01,4.781e-01,4.769e-01,4.757e-01,4.745e-01,&
+4.733e-01,4.720e-01,4.708e-01,4.695e-01,4.683e-01,4.670e-01,4.658e-01,4.645e-01,4.633e-01,4.620e-01,&
+4.608e-01,4.597e-01,4.587e-01,4.577e-01,4.566e-01,4.556e-01,4.546e-01,4.535e-01,4.525e-01,4.515e-01,&
+4.504e-01,4.494e-01,4.484e-01,4.473e-01,4.463e-01,4.453e-01,4.442e-01,4.432e-01,4.422e-01,4.411e-01,&
+4.401e-01,4.388e-01,4.375e-01,4.362e-01,4.350e-01,4.337e-01,4.324e-01,4.311e-01,4.298e-01,4.285e-01,&
+4.272e-01,4.260e-01,4.247e-01,4.234e-01,4.221e-01,4.208e-01,4.195e-01,4.183e-01,4.170e-01,4.157e-01/
+ data (k_Brown(i),i=101,200)/&
+4.144e-01,4.135e-01,4.127e-01,4.118e-01,4.109e-01,4.100e-01,4.092e-01,4.083e-01,4.074e-01,4.065e-01,&
+4.057e-01,4.047e-01,4.038e-01,4.028e-01,4.019e-01,4.009e-01,4.000e-01,3.990e-01,3.981e-01,3.971e-01,&
+3.962e-01,3.952e-01,3.943e-01,3.933e-01,3.924e-01,3.914e-01,3.905e-01,3.895e-01,3.886e-01,3.876e-01,&
+3.867e-01,3.846e-01,3.824e-01,3.803e-01,3.782e-01,3.760e-01,3.739e-01,3.718e-01,3.696e-01,3.675e-01,&
+3.654e-01,3.639e-01,3.625e-01,3.611e-01,3.597e-01,3.582e-01,3.568e-01,3.554e-01,3.540e-01,3.525e-01,&
+3.511e-01,3.500e-01,3.489e-01,3.478e-01,3.467e-01,3.456e-01,3.445e-01,3.434e-01,3.423e-01,3.412e-01,&
+3.401e-01,3.383e-01,3.366e-01,3.348e-01,3.330e-01,3.312e-01,3.294e-01,3.276e-01,3.258e-01,3.241e-01,&
+3.223e-01,3.202e-01,3.182e-01,3.162e-01,3.141e-01,3.121e-01,3.100e-01,3.080e-01,3.059e-01,3.039e-01,&
+3.019e-01,2.999e-01,2.979e-01,2.959e-01,2.940e-01,2.920e-01,2.900e-01,2.881e-01,2.861e-01,2.841e-01,&
+2.821e-01,2.803e-01,2.784e-01,2.766e-01,2.747e-01,2.728e-01,2.710e-01,2.691e-01,2.673e-01,2.654e-01/
+ data (k_Brown(i),i=201,300)/&
+2.636e-01,2.618e-01,2.601e-01,2.584e-01,2.566e-01,2.549e-01,2.532e-01,2.515e-01,2.497e-01,2.480e-01,&
+2.463e-01,2.447e-01,2.431e-01,2.414e-01,2.398e-01,2.382e-01,2.366e-01,2.350e-01,2.334e-01,2.318e-01,&
+2.302e-01,2.288e-01,2.273e-01,2.258e-01,2.244e-01,2.229e-01,2.215e-01,2.200e-01,2.185e-01,2.171e-01,&
+2.156e-01,2.143e-01,2.129e-01,2.115e-01,2.102e-01,2.088e-01,2.074e-01,2.061e-01,2.047e-01,2.033e-01,&
+2.020e-01,2.007e-01,1.994e-01,1.981e-01,1.968e-01,1.955e-01,1.942e-01,1.929e-01,1.916e-01,1.903e-01,&
+1.890e-01,1.878e-01,1.865e-01,1.853e-01,1.841e-01,1.829e-01,1.816e-01,1.804e-01,1.792e-01,1.780e-01,&
+1.768e-01,1.755e-01,1.742e-01,1.729e-01,1.717e-01,1.704e-01,1.691e-01,1.679e-01,1.666e-01,1.653e-01,&
+1.641e-01,1.627e-01,1.613e-01,1.600e-01,1.586e-01,1.572e-01,1.559e-01,1.545e-01,1.532e-01,1.518e-01,&
+1.504e-01,1.491e-01,1.478e-01,1.464e-01,1.451e-01,1.437e-01,1.424e-01,1.411e-01,1.397e-01,1.384e-01,&
+1.370e-01,1.358e-01,1.345e-01,1.333e-01,1.320e-01,1.308e-01,1.295e-01,1.283e-01,1.270e-01,1.258e-01/
+ data (k_Brown(i),i=301,400)/&
+1.245e-01,1.234e-01,1.223e-01,1.212e-01,1.200e-01,1.189e-01,1.178e-01,1.167e-01,1.156e-01,1.144e-01,&
+1.133e-01,1.122e-01,1.111e-01,1.100e-01,1.089e-01,1.078e-01,1.067e-01,1.056e-01,1.046e-01,1.035e-01,&
+1.024e-01,1.013e-01,1.003e-01,9.931e-02,9.829e-02,9.727e-02,9.625e-02,9.524e-02,9.422e-02,9.320e-02,&
+9.218e-02,9.120e-02,9.022e-02,8.924e-02,8.827e-02,8.729e-02,8.631e-02,8.533e-02,8.435e-02,8.337e-02,&
+8.239e-02,8.155e-02,8.070e-02,7.985e-02,7.901e-02,7.816e-02,7.732e-02,7.647e-02,7.562e-02,7.478e-02,&
+7.393e-02,7.319e-02,7.245e-02,7.171e-02,7.097e-02,7.023e-02,6.949e-02,6.875e-02,6.801e-02,6.727e-02,&
+6.653e-02,6.586e-02,6.519e-02,6.452e-02,6.385e-02,6.318e-02,6.251e-02,6.184e-02,6.117e-02,6.050e-02,&
+5.983e-02,5.913e-02,5.843e-02,5.773e-02,5.704e-02,5.634e-02,5.564e-02,5.494e-02,5.424e-02,5.354e-02,&
+5.284e-02,5.226e-02,5.167e-02,5.109e-02,5.050e-02,4.992e-02,4.933e-02,4.874e-02,4.816e-02,4.757e-02,&
+4.699e-02,4.646e-02,4.594e-02,4.542e-02,4.490e-02,4.437e-02,4.385e-02,4.333e-02,4.281e-02,4.228e-02/
+ data (k_Brown(i),i=401,500)/&
+4.176e-02,4.128e-02,4.081e-02,4.033e-02,3.985e-02,3.937e-02,3.889e-02,3.841e-02,3.793e-02,3.746e-02,&
+3.698e-02,3.657e-02,3.615e-02,3.574e-02,3.533e-02,3.492e-02,3.451e-02,3.409e-02,3.368e-02,3.327e-02,&
+3.286e-02,3.249e-02,3.212e-02,3.175e-02,3.139e-02,3.102e-02,3.065e-02,3.028e-02,2.991e-02,2.954e-02,&
+2.918e-02,2.885e-02,2.852e-02,2.819e-02,2.786e-02,2.753e-02,2.720e-02,2.688e-02,2.655e-02,2.622e-02,&
+2.589e-02,2.559e-02,2.529e-02,2.499e-02,2.469e-02,2.440e-02,2.410e-02,2.380e-02,2.350e-02,2.320e-02,&
+2.290e-02,2.264e-02,2.238e-02,2.212e-02,2.186e-02,2.159e-02,2.133e-02,2.107e-02,2.081e-02,2.055e-02,&
+2.029e-02,2.006e-02,1.983e-02,1.961e-02,1.938e-02,1.915e-02,1.893e-02,1.870e-02,1.847e-02,1.825e-02,&
+1.802e-02,1.782e-02,1.762e-02,1.742e-02,1.723e-02,1.703e-02,1.683e-02,1.663e-02,1.643e-02,1.623e-02,&
+1.604e-02,1.586e-02,1.568e-02,1.551e-02,1.533e-02,1.516e-02,1.498e-02,1.481e-02,1.463e-02,1.446e-02,&
+1.428e-02,1.414e-02,1.400e-02,1.385e-02,1.371e-02,1.357e-02,1.343e-02,1.328e-02,1.314e-02,1.300e-02/
+ data (k_Brown(i),i=501,600)/&
+1.286e-02,1.275e-02,1.265e-02,1.255e-02,1.245e-02,1.235e-02,1.225e-02,1.215e-02,1.205e-02,1.195e-02,&
+1.185e-02,1.175e-02,1.165e-02,1.155e-02,1.145e-02,1.135e-02,1.125e-02,1.115e-02,1.105e-02,1.096e-02,&
+1.086e-02,1.076e-02,1.066e-02,1.056e-02,1.047e-02,1.037e-02,1.027e-02,1.017e-02,1.008e-02,9.980e-03,&
+9.884e-03,9.787e-03,9.691e-03,9.595e-03,9.500e-03,9.404e-03,9.309e-03,9.214e-03,9.120e-03,9.025e-03,&
+8.931e-03,8.837e-03,8.743e-03,8.650e-03,8.557e-03,8.464e-03,8.371e-03,8.279e-03,8.187e-03,8.095e-03,&
+8.004e-03,7.913e-03,7.822e-03,7.732e-03,7.641e-03,7.552e-03,7.462e-03,7.373e-03,7.284e-03,7.195e-03,&
+7.107e-03,7.019e-03,6.932e-03,6.844e-03,6.758e-03,6.671e-03,6.585e-03,6.499e-03,6.414e-03,6.329e-03,&
+6.244e-03,6.160e-03,6.076e-03,5.993e-03,5.910e-03,5.827e-03,5.745e-03,5.663e-03,5.581e-03,5.500e-03,&
+5.419e-03,5.339e-03,5.259e-03,5.180e-03,5.101e-03,5.023e-03,4.945e-03,4.867e-03,4.790e-03,4.713e-03,&
+4.637e-03,4.561e-03,4.486e-03,4.411e-03,4.337e-03,4.263e-03,4.190e-03,4.117e-03,4.044e-03,3.972e-03/
+ data (k_Brown(i),i=601,700)/&
+3.901e-03,3.830e-03,3.760e-03,3.690e-03,3.620e-03,3.552e-03,3.483e-03,3.416e-03,3.348e-03,3.282e-03,&
+3.215e-03,3.150e-03,3.085e-03,3.020e-03,2.956e-03,2.893e-03,2.830e-03,2.768e-03,2.706e-03,2.645e-03,&
+2.585e-03,2.525e-03,2.465e-03,2.407e-03,2.348e-03,2.291e-03,2.234e-03,2.178e-03,2.122e-03,2.067e-03,&
+2.012e-03,1.959e-03,1.905e-03,1.853e-03,1.801e-03,1.750e-03,1.699e-03,1.649e-03,1.600e-03,1.551e-03,&
+1.503e-03,1.456e-03,1.409e-03,1.363e-03,1.318e-03,1.274e-03,1.230e-03,1.187e-03,1.144e-03,1.102e-03,&
+1.061e-03,1.021e-03,9.811e-04,9.422e-04,9.040e-04,8.665e-04,8.297e-04,7.937e-04,7.584e-04,7.239e-04,&
+6.901e-04,6.571e-04,6.248e-04,5.933e-04,5.626e-04,5.326e-04,5.034e-04,4.750e-04,4.473e-04,4.205e-04,&
+3.944e-04,3.691e-04,3.446e-04,3.210e-04,2.981e-04,2.760e-04,2.548e-04,2.344e-04,2.148e-04,1.960e-04,&
+1.780e-04,1.609e-04,1.446e-04,1.292e-04,1.146e-04,1.009e-04,8.804e-05,7.603e-05,6.488e-05,5.460e-05,&
+4.519e-05,3.666e-05,2.901e-05,2.225e-05,1.637e-05,1.138e-05,7.297e-06,4.111e-06,1.830e-06,4.581e-07/
+ data (k_Brown(i),i=701,2101)/1401*0./
+
+! ********************************************************************************
+! Specific absorption coefficient of water
+! ********************************************************************************
+
+ data (k_Cw(i),i=1,100)/&
+5.800E-05,5.852E-05,5.900E-05,5.989E-05,6.100E-05,6.203E-05,6.300E-05,6.399E-05,6.500E-05,6.603E-05,&
+6.700E-05,6.790E-05,6.900E-05,7.050E-05,7.200E-05,7.312E-05,7.400E-05,7.490E-05,7.600E-05,7.740E-05,&
+7.900E-05,8.063E-05,8.200E-05,8.297E-05,8.400E-05,8.551E-05,8.700E-05,8.800E-05,8.900E-05,9.050E-05,&
+9.200E-05,9.300E-05,9.400E-05,9.550E-05,9.700E-05,9.801E-05,9.900E-05,1.005E-04,1.020E-04,1.031E-04,&
+1.040E-04,1.050E-04,1.060E-04,1.070E-04,1.080E-04,1.090E-04,1.100E-04,1.110E-04,1.120E-04,1.130E-04,&
+1.140E-04,1.150E-04,1.160E-04,1.170E-04,1.180E-04,1.190E-04,1.200E-04,1.210E-04,1.220E-04,1.230E-04,&
+1.240E-04,1.250E-04,1.260E-04,1.270E-04,1.280E-04,1.289E-04,1.300E-04,1.315E-04,1.330E-04,1.340E-04,&
+1.350E-04,1.364E-04,1.380E-04,1.396E-04,1.410E-04,1.424E-04,1.440E-04,1.459E-04,1.480E-04,1.499E-04,&
+1.520E-04,1.544E-04,1.570E-04,1.596E-04,1.620E-04,1.643E-04,1.670E-04,1.704E-04,1.740E-04,1.775E-04,&
+1.810E-04,1.849E-04,1.890E-04,1.934E-04,1.980E-04,2.031E-04,2.090E-04,2.158E-04,2.230E-04,2.303E-04/
+ data (k_Cw(i),i=101,200)/&
+2.380E-04,2.463E-04,2.550E-04,2.640E-04,2.730E-04,2.819E-04,2.910E-04,3.004E-04,3.100E-04,3.194E-04,&
+3.290E-04,3.390E-04,3.490E-04,3.588E-04,3.680E-04,3.767E-04,3.860E-04,3.962E-04,4.040E-04,4.069E-04,&
+4.090E-04,4.138E-04,4.160E-04,4.112E-04,4.090E-04,4.176E-04,4.270E-04,4.268E-04,4.230E-04,4.237E-04,&
+4.290E-04,4.371E-04,4.450E-04,4.506E-04,4.560E-04,4.631E-04,4.700E-04,4.748E-04,4.800E-04,4.879E-04,&
+4.950E-04,4.983E-04,5.030E-04,5.141E-04,5.270E-04,5.363E-04,5.440E-04,5.532E-04,5.640E-04,5.759E-04,&
+5.880E-04,5.998E-04,6.110E-04,6.215E-04,6.310E-04,6.391E-04,6.460E-04,6.520E-04,6.580E-04,6.647E-04,&
+6.720E-04,6.793E-04,6.860E-04,6.920E-04,6.990E-04,7.084E-04,7.180E-04,7.257E-04,7.340E-04,7.455E-04,&
+7.590E-04,7.729E-04,7.870E-04,8.020E-04,8.190E-04,8.386E-04,8.580E-04,8.754E-04,8.960E-04,9.238E-04,&
+9.520E-04,9.745E-04,1.000E-03,1.037E-03,1.079E-03,1.119E-03,1.159E-03,1.204E-03,1.253E-03,1.304E-03,&
+1.356E-03,1.408E-03,1.459E-03,1.510E-03,1.567E-03,1.635E-03,1.700E-03,1.758E-03,1.860E-03,2.042E-03/
+ data (k_Cw(i),i=201,300)/&
+2.224E-03,2.323E-03,2.366E-03,2.400E-03,2.448E-03,2.519E-03,2.587E-03,2.629E-03,2.653E-03,2.674E-03,&
+2.691E-03,2.704E-03,2.715E-03,2.727E-03,2.740E-03,2.753E-03,2.764E-03,2.775E-03,2.785E-03,2.797E-03,&
+2.810E-03,2.824E-03,2.839E-03,2.854E-03,2.868E-03,2.881E-03,2.893E-03,2.907E-03,2.922E-03,2.938E-03,&
+2.955E-03,2.972E-03,2.988E-03,3.000E-03,3.011E-03,3.023E-03,3.038E-03,3.057E-03,3.076E-03,3.094E-03,&
+3.111E-03,3.127E-03,3.144E-03,3.162E-03,3.181E-03,3.202E-03,3.223E-03,3.242E-03,3.263E-03,3.289E-03,&
+3.315E-03,3.338E-03,3.362E-03,3.390E-03,3.423E-03,3.461E-03,3.508E-03,3.567E-03,3.636E-03,3.712E-03,&
+3.791E-03,3.866E-03,3.931E-03,3.981E-03,4.019E-03,4.049E-03,4.072E-03,4.087E-03,4.098E-03,4.109E-03,&
+4.122E-03,4.137E-03,4.150E-03,4.160E-03,4.173E-03,4.196E-03,4.223E-03,4.248E-03,4.270E-03,4.293E-03,&
+4.318E-03,4.347E-03,4.381E-03,4.418E-03,4.458E-03,4.500E-03,4.545E-03,4.594E-03,4.646E-03,4.701E-03,&
+4.760E-03,4.827E-03,4.903E-03,4.986E-03,5.071E-03,5.154E-03,5.244E-03,5.351E-03,5.470E-03,5.594E-03/
+ data (k_Cw(i),i=301,400)/&
+5.722E-03,5.855E-03,5.995E-03,6.146E-03,6.303E-03,6.463E-03,6.628E-03,6.804E-03,6.993E-03,7.197E-03,&
+7.415E-03,7.647E-03,7.893E-03,8.157E-03,8.445E-03,8.763E-03,9.109E-03,9.479E-03,9.871E-03,1.029E-02,&
+1.072E-02,1.119E-02,1.168E-02,1.218E-02,1.268E-02,1.319E-02,1.372E-02,1.428E-02,1.487E-02,1.551E-02,&
+1.621E-02,1.699E-02,1.787E-02,1.886E-02,1.992E-02,2.101E-02,2.207E-02,2.306E-02,2.394E-02,2.469E-02,&
+2.532E-02,2.583E-02,2.623E-02,2.652E-02,2.672E-02,2.689E-02,2.702E-02,2.713E-02,2.722E-02,2.728E-02,&
+2.733E-02,2.738E-02,2.741E-02,2.745E-02,2.748E-02,2.751E-02,2.754E-02,2.758E-02,2.763E-02,2.767E-02,&
+2.771E-02,2.773E-02,2.773E-02,2.774E-02,2.774E-02,2.773E-02,2.770E-02,2.766E-02,2.761E-02,2.757E-02,&
+2.754E-02,2.752E-02,2.748E-02,2.741E-02,2.731E-02,2.720E-02,2.710E-02,2.701E-02,2.690E-02,2.675E-02,&
+2.659E-02,2.645E-02,2.633E-02,2.624E-02,2.613E-02,2.593E-02,2.558E-02,2.523E-02,2.513E-02,2.501E-02,&
+2.466E-02,2.447E-02,2.412E-02,2.389E-02,2.374E-02,2.355E-02,2.337E-02,2.318E-02,2.304E-02,2.281E-02/
+ data (k_Cw(i),i=401,500)/&
+2.246E-02,2.243E-02,2.238E-02,2.222E-02,2.204E-02,2.201E-02,2.204E-02,2.196E-02,2.177E-02,2.190E-02,&
+2.188E-02,2.188E-02,2.198E-02,2.210E-02,2.223E-02,2.233E-02,2.248E-02,2.276E-02,2.304E-02,2.311E-02,&
+2.329E-02,2.388E-02,2.446E-02,2.475E-02,2.516E-02,2.620E-02,2.769E-02,2.830E-02,2.914E-02,3.108E-02,&
+3.214E-02,3.297E-02,3.459E-02,3.606E-02,3.662E-02,3.702E-02,3.788E-02,3.829E-02,3.854E-02,3.909E-02,&
+3.949E-02,3.972E-02,4.000E-02,4.040E-02,4.057E-02,4.075E-02,4.115E-02,4.127E-02,4.149E-02,4.204E-02,&
+4.199E-02,4.223E-02,4.254E-02,4.272E-02,4.280E-02,4.306E-02,4.360E-02,4.369E-02,4.379E-02,4.433E-02,&
+4.454E-02,4.466E-02,4.505E-02,4.527E-02,4.552E-02,4.605E-02,4.658E-02,4.691E-02,4.705E-02,4.713E-02,&
+4.752E-02,4.833E-02,4.867E-02,4.894E-02,4.960E-02,5.006E-02,5.050E-02,5.115E-02,5.153E-02,5.204E-02,&
+5.298E-02,5.346E-02,5.386E-02,5.465E-02,5.528E-02,5.566E-02,5.596E-02,5.653E-02,5.745E-02,5.789E-02,&
+5.831E-02,5.924E-02,5.982E-02,6.009E-02,6.035E-02,6.094E-02,6.185E-02,6.226E-02,6.269E-02,6.360E-02/
+ data (k_Cw(i),i=501,600)/&
+6.407E-02,6.458E-02,6.562E-02,6.636E-02,6.672E-02,6.699E-02,6.769E-02,6.900E-02,6.989E-02,7.037E-02,&
+7.085E-02,7.187E-02,7.358E-02,7.486E-02,7.562E-02,7.630E-02,7.792E-02,8.085E-02,8.292E-02,8.410E-02,&
+8.528E-02,8.801E-02,9.268E-02,9.584E-02,9.819E-02,1.012E-01,1.042E-01,1.066E-01,1.113E-01,1.194E-01,&
+1.246E-01,1.281E-01,1.327E-01,1.374E-01,1.410E-01,1.465E-01,1.557E-01,1.635E-01,1.688E-01,1.732E-01,&
+1.818E-01,1.963E-01,2.050E-01,2.106E-01,2.187E-01,2.287E-01,2.386E-01,2.468E-01,2.542E-01,2.701E-01,&
+2.976E-01,3.153E-01,3.274E-01,3.438E-01,3.622E-01,3.785E-01,3.930E-01,4.068E-01,4.184E-01,4.273E-01,&
+4.385E-01,4.538E-01,4.611E-01,4.633E-01,4.663E-01,4.701E-01,4.733E-01,4.756E-01,4.772E-01,4.785E-01,&
+4.800E-01,4.814E-01,4.827E-01,4.843E-01,4.864E-01,4.870E-01,4.867E-01,4.864E-01,4.857E-01,4.841E-01,&
+4.821E-01,4.804E-01,4.786E-01,4.764E-01,4.738E-01,4.710E-01,4.677E-01,4.641E-01,4.604E-01,4.570E-01,&
+4.532E-01,4.482E-01,4.434E-01,4.397E-01,4.362E-01,4.316E-01,4.265E-01,4.215E-01,4.168E-01,4.121E-01/
+ data (k_Cw(i),i=601,700)/&
+4.072E-01,4.017E-01,3.963E-01,3.915E-01,3.868E-01,3.816E-01,3.760E-01,3.701E-01,3.640E-01,3.581E-01,&
+3.521E-01,3.461E-01,3.402E-01,3.349E-01,3.297E-01,3.243E-01,3.191E-01,3.141E-01,3.086E-01,3.022E-01,&
+2.957E-01,2.897E-01,2.840E-01,2.782E-01,2.724E-01,2.672E-01,2.621E-01,2.566E-01,2.506E-01,2.444E-01,&
+2.391E-01,2.357E-01,2.331E-01,2.299E-01,2.251E-01,2.198E-01,2.151E-01,2.109E-01,2.064E-01,2.020E-01,&
+1.981E-01,1.944E-01,1.904E-01,1.868E-01,1.841E-01,1.818E-01,1.790E-01,1.752E-01,1.715E-01,1.687E-01,&
+1.664E-01,1.639E-01,1.613E-01,1.586E-01,1.562E-01,1.545E-01,1.532E-01,1.522E-01,1.510E-01,1.495E-01,&
+1.475E-01,1.457E-01,1.447E-01,1.442E-01,1.438E-01,1.433E-01,1.426E-01,1.418E-01,1.412E-01,1.410E-01,&
+1.409E-01,1.408E-01,1.406E-01,1.405E-01,1.408E-01,1.414E-01,1.426E-01,1.435E-01,1.438E-01,1.439E-01,&
+1.443E-01,1.456E-01,1.475E-01,1.498E-01,1.519E-01,1.534E-01,1.547E-01,1.561E-01,1.580E-01,1.604E-01,&
+1.632E-01,1.659E-01,1.677E-01,1.693E-01,1.712E-01,1.739E-01,1.777E-01,1.824E-01,1.866E-01,1.890E-01/
+ data (k_Cw(i),i=701,800)/&
+1.906E-01,1.929E-01,1.967E-01,2.005E-01,2.031E-01,2.051E-01,2.079E-01,2.123E-01,2.166E-01,2.196E-01,&
+2.219E-01,2.251E-01,2.298E-01,2.337E-01,2.346E-01,2.342E-01,2.353E-01,2.397E-01,2.450E-01,2.491E-01,&
+2.528E-01,2.578E-01,2.650E-01,2.719E-01,2.765E-01,2.811E-01,2.891E-01,3.023E-01,3.164E-01,3.271E-01,&
+3.378E-01,3.533E-01,3.770E-01,4.037E-01,4.281E-01,4.502E-01,4.712E-01,4.932E-01,5.202E-01,5.572E-01,&
+6.052E-01,6.520E-01,6.863E-01,7.159E-01,7.535E-01,8.064E-01,8.597E-01,8.981E-01,9.253E-01,9.493E-01,&
+9.769E-01,1.008E+00,1.041E+00,1.073E+00,1.100E+00,1.119E+00,1.131E+00,1.140E+00,1.150E+00,1.160E+00,&
+1.170E+00,1.181E+00,1.190E+00,1.194E+00,1.196E+00,1.197E+00,1.200E+00,1.203E+00,1.205E+00,1.206E+00,&
+1.207E+00,1.213E+00,1.223E+00,1.232E+00,1.234E+00,1.232E+00,1.229E+00,1.230E+00,1.233E+00,1.236E+00,&
+1.239E+00,1.241E+00,1.244E+00,1.248E+00,1.252E+00,1.256E+00,1.258E+00,1.260E+00,1.262E+00,1.265E+00,&
+1.267E+00,1.270E+00,1.272E+00,1.275E+00,1.277E+00,1.280E+00,1.282E+00,1.283E+00,1.283E+00,1.279E+00/
+ data (k_Cw(i),i=801,900)/&
+1.272E+00,1.266E+00,1.267E+00,1.271E+00,1.273E+00,1.271E+00,1.265E+00,1.260E+00,1.258E+00,1.258E+00,&
+1.257E+00,1.252E+00,1.247E+00,1.243E+00,1.243E+00,1.243E+00,1.240E+00,1.233E+00,1.224E+00,1.216E+00,&
+1.214E+00,1.214E+00,1.213E+00,1.210E+00,1.205E+00,1.200E+00,1.199E+00,1.198E+00,1.197E+00,1.194E+00,&
+1.189E+00,1.184E+00,1.180E+00,1.176E+00,1.171E+00,1.166E+00,1.161E+00,1.158E+00,1.157E+00,1.157E+00,&
+1.155E+00,1.152E+00,1.148E+00,1.142E+00,1.138E+00,1.133E+00,1.130E+00,1.126E+00,1.123E+00,1.120E+00,&
+1.116E+00,1.111E+00,1.107E+00,1.103E+00,1.101E+00,1.101E+00,1.101E+00,1.101E+00,1.100E+00,1.098E+00,&
+1.094E+00,1.089E+00,1.085E+00,1.084E+00,1.083E+00,1.083E+00,1.082E+00,1.081E+00,1.080E+00,1.079E+00,&
+1.080E+00,1.083E+00,1.087E+00,1.093E+00,1.099E+00,1.104E+00,1.107E+00,1.109E+00,1.111E+00,1.115E+00,&
+1.121E+00,1.129E+00,1.137E+00,1.147E+00,1.156E+00,1.164E+00,1.170E+00,1.175E+00,1.181E+00,1.188E+00,&
+1.196E+00,1.206E+00,1.216E+00,1.227E+00,1.239E+00,1.252E+00,1.267E+00,1.283E+00,1.297E+00,1.310E+00/
+ data (k_Cw(i),i=901,1000)/&
+1.323E+00,1.336E+00,1.351E+00,1.370E+00,1.392E+00,1.416E+00,1.440E+00,1.465E+00,1.489E+00,1.511E+00,&
+1.532E+00,1.555E+00,1.580E+00,1.610E+00,1.642E+00,1.672E+00,1.701E+00,1.728E+00,1.758E+00,1.791E+00,&
+1.831E+00,1.872E+00,1.911E+00,1.943E+00,1.974E+00,2.007E+00,2.047E+00,2.098E+00,2.153E+00,2.203E+00,&
+2.243E+00,2.277E+00,2.312E+00,2.357E+00,2.415E+00,2.479E+00,2.540E+00,2.590E+00,2.631E+00,2.666E+00,&
+2.701E+00,2.738E+00,2.780E+00,2.829E+00,2.889E+00,2.960E+00,3.033E+00,3.097E+00,3.146E+00,3.181E+00,&
+3.226E+00,3.267E+00,3.319E+00,3.363E+00,3.412E+00,3.449E+00,3.504E+00,3.544E+00,3.600E+00,3.648E+00,&
+3.701E+00,3.752E+00,3.802E+00,3.871E+00,3.927E+00,3.985E+00,4.064E+00,4.125E+00,4.216E+00,4.302E+00,&
+4.389E+00,4.504E+00,4.630E+00,4.737E+00,4.904E+00,5.092E+00,5.260E+00,5.479E+00,5.720E+00,6.006E+00,&
+6.242E+00,6.580E+00,6.927E+00,7.313E+00,7.633E+00,8.089E+00,8.545E+00,9.030E+00,9.591E+00,1.002E+01,&
+1.063E+01,1.122E+01,1.184E+01,1.245E+01,1.316E+01,1.369E+01,1.434E+01,1.509E+01,1.578E+01,1.646E+01/
+ data (k_Cw(i),i=1001,1100)/&
+1.714E+01,1.781E+01,1.854E+01,1.919E+01,1.980E+01,2.029E+01,2.089E+01,2.146E+01,2.202E+01,2.260E+01,&
+2.313E+01,2.360E+01,2.407E+01,2.450E+01,2.493E+01,2.533E+01,2.571E+01,2.606E+01,2.641E+01,2.673E+01,&
+2.701E+01,2.729E+01,2.756E+01,2.782E+01,2.806E+01,2.835E+01,2.856E+01,2.875E+01,2.892E+01,2.908E+01,&
+2.926E+01,2.940E+01,2.956E+01,2.966E+01,2.982E+01,2.993E+01,3.003E+01,3.014E+01,3.023E+01,3.029E+01,&
+3.036E+01,3.042E+01,3.046E+01,3.049E+01,3.052E+01,3.053E+01,3.055E+01,3.056E+01,3.056E+01,3.055E+01,&
+3.054E+01,3.051E+01,3.049E+01,3.045E+01,3.041E+01,3.035E+01,3.029E+01,3.023E+01,3.014E+01,3.006E+01,&
+2.998E+01,2.983E+01,2.971E+01,2.957E+01,2.936E+01,2.917E+01,2.899E+01,2.872E+01,2.851E+01,2.829E+01,&
+2.800E+01,2.777E+01,2.754E+01,2.722E+01,2.699E+01,2.664E+01,2.638E+01,2.611E+01,2.581E+01,2.555E+01,&
+2.522E+01,2.497E+01,2.468E+01,2.443E+01,2.413E+01,2.388E+01,2.364E+01,2.332E+01,2.307E+01,2.274E+01,&
+2.250E+01,2.218E+01,2.193E+01,2.163E+01,2.139E+01,2.107E+01,2.082E+01,2.052E+01,2.025E+01,2.001E+01/
+ data (k_Cw(i),i=1101,1200)/&
+1.972E+01,1.951E+01,1.924E+01,1.900E+01,1.874E+01,1.847E+01,1.827E+01,1.802E+01,1.784E+01,1.758E+01,&
+1.734E+01,1.712E+01,1.688E+01,1.671E+01,1.647E+01,1.623E+01,1.606E+01,1.583E+01,1.562E+01,1.545E+01,&
+1.525E+01,1.504E+01,1.489E+01,1.468E+01,1.447E+01,1.432E+01,1.413E+01,1.395E+01,1.381E+01,1.364E+01,&
+1.348E+01,1.329E+01,1.316E+01,1.298E+01,1.282E+01,1.265E+01,1.254E+01,1.238E+01,1.223E+01,1.206E+01,&
+1.193E+01,1.181E+01,1.166E+01,1.152E+01,1.137E+01,1.126E+01,1.114E+01,1.100E+01,1.088E+01,1.075E+01,&
+1.064E+01,1.054E+01,1.044E+01,1.032E+01,1.022E+01,1.011E+01,1.001E+01,9.912E+00,9.839E+00,9.754E+00,&
+9.660E+00,9.563E+00,9.477E+00,9.383E+00,9.305E+00,9.202E+00,9.133E+00,9.047E+00,8.977E+00,8.898E+00,&
+8.820E+00,8.742E+00,8.665E+00,8.588E+00,8.509E+00,8.448E+00,8.364E+00,8.295E+00,8.234E+00,8.157E+00,&
+8.104E+00,8.036E+00,7.959E+00,7.890E+00,7.834E+00,7.773E+00,7.712E+00,7.654E+00,7.609E+00,7.548E+00,&
+7.495E+00,7.432E+00,7.374E+00,7.315E+00,7.252E+00,7.203E+00,7.164E+00,7.124E+00,7.084E+00,7.041E+00/
+ data (k_Cw(i),i=1201,1300)/&
+6.987E+00,6.943E+00,6.910E+00,6.865E+00,6.828E+00,6.776E+00,6.742E+00,6.714E+00,6.695E+00,6.654E+00,&
+6.630E+00,6.599E+00,6.567E+00,6.526E+00,6.501E+00,6.474E+00,6.449E+00,6.420E+00,6.401E+00,6.363E+00,&
+6.345E+00,6.309E+00,6.282E+00,6.250E+00,6.214E+00,6.186E+00,6.163E+00,6.130E+00,6.121E+00,6.091E+00,&
+6.076E+00,6.053E+00,6.048E+00,6.016E+00,6.005E+00,5.982E+00,5.973E+00,5.947E+00,5.940E+00,5.919E+00,&
+5.911E+00,5.887E+00,5.875E+00,5.846E+00,5.826E+00,5.798E+00,5.787E+00,5.751E+00,5.746E+00,5.718E+00,&
+5.705E+00,5.685E+00,5.684E+00,5.657E+00,5.658E+00,5.644E+00,5.648E+00,5.626E+00,5.626E+00,5.619E+00,&
+5.618E+00,5.603E+00,5.614E+00,5.597E+00,5.603E+00,5.582E+00,5.584E+00,5.564E+00,5.563E+00,5.547E+00,&
+5.545E+00,5.536E+00,5.542E+00,5.529E+00,5.532E+00,5.525E+00,5.533E+00,5.528E+00,5.529E+00,5.516E+00,&
+5.524E+00,5.516E+00,5.526E+00,5.520E+00,5.520E+00,5.516E+00,5.522E+00,5.511E+00,5.527E+00,5.511E+00,&
+5.519E+00,5.515E+00,5.520E+00,5.510E+00,5.518E+00,5.523E+00,5.538E+00,5.535E+00,5.544E+00,5.557E+00/
+ data (k_Cw(i),i=1301,1400)/&
+5.571E+00,5.583E+00,5.606E+00,5.607E+00,5.629E+00,5.636E+00,5.664E+00,5.670E+00,5.693E+00,5.702E+00,&
+5.733E+00,5.752E+00,5.766E+00,5.776E+00,5.797E+00,5.811E+00,5.829E+00,5.842E+00,5.877E+00,5.891E+00,&
+5.930E+00,5.945E+00,5.972E+00,5.999E+00,6.025E+00,6.051E+00,6.087E+00,6.096E+00,6.136E+00,6.166E+00,&
+6.198E+00,6.219E+00,6.256E+00,6.284E+00,6.335E+00,6.369E+00,6.392E+00,6.445E+00,6.493E+00,6.517E+00,&
+6.571E+00,6.617E+00,6.658E+00,6.689E+00,6.748E+00,6.796E+00,6.842E+00,6.897E+00,6.955E+00,7.003E+00,&
+7.054E+00,7.111E+00,7.179E+00,7.235E+00,7.274E+00,7.339E+00,7.414E+00,7.481E+00,7.536E+00,7.594E+00,&
+7.669E+00,7.734E+00,7.776E+00,7.833E+00,7.893E+00,7.952E+00,8.000E+00,8.045E+00,8.103E+00,8.155E+00,&
+8.205E+00,8.241E+00,8.264E+00,8.321E+00,8.352E+00,8.394E+00,8.430E+00,8.448E+00,8.477E+00,8.512E+00,&
+8.535E+00,8.562E+00,8.593E+00,8.618E+00,8.640E+00,8.670E+00,8.689E+00,8.720E+00,8.738E+00,8.755E+00,&
+8.777E+00,8.778E+00,8.778E+00,8.794E+00,8.805E+00,8.807E+00,8.809E+00,8.811E+00,8.799E+00,8.795E+00/
+ data (k_Cw(i),i=1401,1500)/&
+8.789E+00,8.779E+00,8.767E+00,8.754E+00,8.750E+00,8.738E+00,8.739E+00,8.735E+00,8.744E+00,8.753E+00,&
+8.755E+00,8.780E+00,8.787E+00,8.790E+00,8.798E+00,8.794E+00,8.811E+00,8.820E+00,8.836E+00,8.845E+00,&
+8.854E+00,8.858E+00,8.868E+00,8.869E+00,8.884E+00,8.888E+00,8.900E+00,8.922E+00,8.951E+00,8.973E+00,&
+9.010E+00,9.034E+00,9.110E+00,9.146E+00,9.195E+00,9.259E+00,9.315E+00,9.380E+00,9.457E+00,9.535E+00,&
+9.633E+00,9.723E+00,9.824E+00,9.935E+00,1.005E+01,1.018E+01,1.031E+01,1.042E+01,1.059E+01,1.075E+01,&
+1.094E+01,1.110E+01,1.139E+01,1.160E+01,1.184E+01,1.208E+01,1.235E+01,1.266E+01,1.301E+01,1.334E+01,&
+1.375E+01,1.412E+01,1.478E+01,1.529E+01,1.586E+01,1.641E+01,1.709E+01,1.774E+01,1.853E+01,1.925E+01,&
+2.051E+01,2.148E+01,2.250E+01,2.367E+01,2.483E+01,2.622E+01,2.751E+01,2.972E+01,3.144E+01,3.317E+01,&
+3.504E+01,3.725E+01,3.927E+01,4.269E+01,4.530E+01,4.789E+01,5.060E+01,5.360E+01,5.761E+01,6.088E+01,&
+6.401E+01,6.720E+01,7.059E+01,7.497E+01,7.841E+01,8.157E+01,8.469E+01,8.752E+01,9.189E+01,9.456E+01/
+ data (k_Cw(i),i=1501,1600)/&
+9.722E+01,9.995E+01,1.033E+02,1.057E+02,1.078E+02,1.097E+02,1.123E+02,1.140E+02,1.157E+02,1.171E+02,&
+1.190E+02,1.203E+02,1.215E+02,1.226E+02,1.240E+02,1.248E+02,1.257E+02,1.265E+02,1.275E+02,1.281E+02,&
+1.286E+02,1.292E+02,1.296E+02,1.299E+02,1.303E+02,1.304E+02,1.306E+02,1.306E+02,1.306E+02,1.305E+02,&
+1.304E+02,1.301E+02,1.299E+02,1.296E+02,1.291E+02,1.287E+02,1.282E+02,1.275E+02,1.270E+02,1.264E+02,&
+1.256E+02,1.249E+02,1.242E+02,1.232E+02,1.224E+02,1.216E+02,1.206E+02,1.197E+02,1.190E+02,1.178E+02,&
+1.170E+02,1.157E+02,1.149E+02,1.140E+02,1.128E+02,1.118E+02,1.110E+02,1.097E+02,1.088E+02,1.076E+02,&
+1.066E+02,1.058E+02,1.044E+02,1.036E+02,1.023E+02,1.014E+02,1.005E+02,9.928E+01,9.831E+01,9.711E+01,&
+9.631E+01,9.488E+01,9.412E+01,9.341E+01,9.206E+01,9.121E+01,9.009E+01,8.929E+01,8.804E+01,8.725E+01,&
+8.611E+01,8.532E+01,8.460E+01,8.336E+01,8.262E+01,8.151E+01,8.076E+01,7.973E+01,7.904E+01,7.800E+01,&
+7.723E+01,7.628E+01,7.557E+01,7.463E+01,7.392E+01,7.298E+01,7.234E+01,7.141E+01,7.082E+01,6.986E+01/
+ data (k_Cw(i),i=1601,1700)/&
+6.924E+01,6.865E+01,6.779E+01,6.688E+01,6.634E+01,6.548E+01,6.490E+01,6.412E+01,6.358E+01,6.281E+01,&
+6.232E+01,6.156E+01,6.105E+01,6.029E+01,5.980E+01,5.907E+01,5.857E+01,5.788E+01,5.746E+01,5.680E+01,&
+5.632E+01,5.566E+01,5.503E+01,5.463E+01,5.398E+01,5.356E+01,5.294E+01,5.256E+01,5.197E+01,5.138E+01,&
+5.098E+01,5.047E+01,5.006E+01,4.951E+01,4.915E+01,4.860E+01,4.806E+01,4.773E+01,4.718E+01,4.685E+01,&
+4.635E+01,4.584E+01,4.553E+01,4.503E+01,4.473E+01,4.426E+01,4.379E+01,4.348E+01,4.302E+01,4.273E+01,&
+4.228E+01,4.186E+01,4.155E+01,4.115E+01,4.072E+01,4.046E+01,4.002E+01,3.975E+01,3.934E+01,3.894E+01,&
+3.868E+01,3.827E+01,3.790E+01,3.762E+01,3.726E+01,3.687E+01,3.664E+01,3.628E+01,3.592E+01,3.568E+01,&
+3.536E+01,3.499E+01,3.479E+01,3.447E+01,3.413E+01,3.392E+01,3.363E+01,3.329E+01,3.309E+01,3.280E+01,&
+3.251E+01,3.231E+01,3.200E+01,3.172E+01,3.154E+01,3.127E+01,3.097E+01,3.071E+01,3.052E+01,3.025E+01,&
+2.999E+01,2.980E+01,2.958E+01,2.929E+01,2.906E+01,2.888E+01,2.865E+01,2.840E+01,2.822E+01,2.799E+01/
+ data (k_Cw(i),i=1701,1800)/&
+2.776E+01,2.751E+01,2.737E+01,2.713E+01,2.692E+01,2.671E+01,2.657E+01,2.637E+01,2.617E+01,2.597E+01,&
+2.584E+01,2.565E+01,2.547E+01,2.528E+01,2.518E+01,2.501E+01,2.485E+01,2.466E+01,2.455E+01,2.438E+01,&
+2.420E+01,2.401E+01,2.386E+01,2.374E+01,2.358E+01,2.342E+01,2.328E+01,2.318E+01,2.304E+01,2.289E+01,&
+2.275E+01,2.262E+01,2.252E+01,2.239E+01,2.227E+01,2.214E+01,2.202E+01,2.194E+01,2.183E+01,2.172E+01,&
+2.162E+01,2.150E+01,2.140E+01,2.133E+01,2.123E+01,2.112E+01,2.102E+01,2.091E+01,2.085E+01,2.077E+01,&
+2.067E+01,2.058E+01,2.049E+01,2.040E+01,2.033E+01,2.027E+01,2.018E+01,2.010E+01,2.002E+01,1.995E+01,&
+1.987E+01,1.983E+01,1.976E+01,1.969E+01,1.963E+01,1.958E+01,1.952E+01,1.946E+01,1.942E+01,1.938E+01,&
+1.933E+01,1.928E+01,1.923E+01,1.918E+01,1.913E+01,1.909E+01,1.904E+01,1.900E+01,1.896E+01,1.889E+01,&
+1.884E+01,1.880E+01,1.874E+01,1.870E+01,1.866E+01,1.860E+01,1.856E+01,1.852E+01,1.849E+01,1.845E+01,&
+1.843E+01,1.839E+01,1.837E+01,1.837E+01,1.838E+01,1.837E+01,1.836E+01,1.835E+01,1.835E+01,1.835E+01/
+ data (k_Cw(i),i=1801,1900)/&
+1.834E+01,1.833E+01,1.833E+01,1.833E+01,1.834E+01,1.833E+01,1.834E+01,1.834E+01,1.832E+01,1.831E+01,&
+1.829E+01,1.828E+01,1.828E+01,1.829E+01,1.829E+01,1.830E+01,1.832E+01,1.835E+01,1.836E+01,1.837E+01,&
+1.837E+01,1.838E+01,1.837E+01,1.840E+01,1.842E+01,1.843E+01,1.846E+01,1.849E+01,1.851E+01,1.854E+01,&
+1.857E+01,1.858E+01,1.860E+01,1.864E+01,1.865E+01,1.867E+01,1.870E+01,1.875E+01,1.879E+01,1.883E+01,&
+1.888E+01,1.893E+01,1.897E+01,1.903E+01,1.908E+01,1.913E+01,1.919E+01,1.924E+01,1.929E+01,1.934E+01,&
+1.940E+01,1.946E+01,1.951E+01,1.961E+01,1.966E+01,1.973E+01,1.980E+01,1.985E+01,1.991E+01,1.997E+01,&
+2.004E+01,2.013E+01,2.020E+01,2.027E+01,2.038E+01,2.046E+01,2.054E+01,2.062E+01,2.071E+01,2.079E+01,&
+2.087E+01,2.094E+01,2.103E+01,2.111E+01,2.126E+01,2.135E+01,2.145E+01,2.153E+01,2.164E+01,2.174E+01,&
+2.183E+01,2.192E+01,2.202E+01,2.212E+01,2.223E+01,2.234E+01,2.245E+01,2.264E+01,2.276E+01,2.287E+01,&
+2.301E+01,2.313E+01,2.327E+01,2.338E+01,2.351E+01,2.363E+01,2.377E+01,2.385E+01,2.409E+01,2.418E+01/
+ data (k_Cw(i),i=1901,2000)/&
+2.433E+01,2.444E+01,2.459E+01,2.470E+01,2.485E+01,2.495E+01,2.523E+01,2.534E+01,2.549E+01,2.564E+01,&
+2.579E+01,2.592E+01,2.611E+01,2.623E+01,2.653E+01,2.664E+01,2.681E+01,2.695E+01,2.712E+01,2.727E+01,&
+2.744E+01,2.756E+01,2.789E+01,2.802E+01,2.819E+01,2.838E+01,2.855E+01,2.869E+01,2.903E+01,2.916E+01,&
+2.934E+01,2.951E+01,2.969E+01,2.988E+01,3.002E+01,3.038E+01,3.054E+01,3.073E+01,3.092E+01,3.107E+01,&
+3.145E+01,3.160E+01,3.180E+01,3.199E+01,3.219E+01,3.238E+01,3.272E+01,3.290E+01,3.311E+01,3.331E+01,&
+3.348E+01,3.388E+01,3.404E+01,3.426E+01,3.447E+01,3.468E+01,3.486E+01,3.528E+01,3.547E+01,3.570E+01,&
+3.592E+01,3.610E+01,3.656E+01,3.675E+01,3.697E+01,3.716E+01,3.761E+01,3.777E+01,3.801E+01,3.827E+01,&
+3.848E+01,3.892E+01,3.913E+01,3.938E+01,3.957E+01,4.007E+01,4.024E+01,4.050E+01,4.078E+01,4.096E+01,&
+4.147E+01,4.167E+01,4.196E+01,4.220E+01,4.268E+01,4.293E+01,4.319E+01,4.342E+01,4.388E+01,4.413E+01,&
+4.439E+01,4.464E+01,4.513E+01,4.538E+01,4.565E+01,4.590E+01,4.638E+01,4.663E+01,4.690E+01,4.714E+01/
+ data (k_Cw(i),i=2001,2101)/&
+4.764E+01,4.787E+01,4.817E+01,4.836E+01,4.894E+01,4.917E+01,4.940E+01,4.997E+01,5.021E+01,5.050E+01,&
+5.078E+01,5.131E+01,5.159E+01,5.191E+01,5.246E+01,5.275E+01,5.310E+01,5.339E+01,5.401E+01,5.429E+01,&
+5.462E+01,5.523E+01,5.555E+01,5.588E+01,5.618E+01,5.686E+01,5.713E+01,5.746E+01,5.808E+01,5.841E+01,&
+5.878E+01,5.946E+01,5.976E+01,6.009E+01,6.039E+01,6.107E+01,6.146E+01,6.180E+01,6.250E+01,6.286E+01,&
+6.316E+01,6.392E+01,6.427E+01,6.462E+01,6.539E+01,6.574E+01,6.609E+01,6.685E+01,6.725E+01,6.759E+01,&
+6.842E+01,6.881E+01,6.918E+01,7.009E+01,7.046E+01,7.084E+01,7.174E+01,7.212E+01,7.249E+01,7.340E+01,&
+7.381E+01,7.423E+01,7.514E+01,7.554E+01,7.591E+01,7.675E+01,7.718E+01,7.801E+01,7.839E+01,7.880E+01,&
+7.970E+01,8.005E+01,8.046E+01,8.136E+01,8.173E+01,8.215E+01,8.295E+01,8.338E+01,8.423E+01,8.474E+01,&
+8.510E+01,8.584E+01,8.617E+01,8.637E+01,8.708E+01,8.762E+01,8.884E+01,8.904E+01,8.945E+01,9.055E+01,&
+9.089E+01,9.134E+01,9.204E+01,9.244E+01,9.308E+01,9.333E+01,9.358E+01,9.416E+01,9.448E+01,9.499E+01,&
+9.530E+01/
+
+
+! ********************************************************************************
+! Specific absorption coefficient of dry matter
+! ********************************************************************************
+
+ data (k_Cm(i),i=1,100)/&
+1.097E+02,1.037E+02,9.798E+01,9.244E+01,8.713E+01,8.231E+01,7.806E+01,7.404E+01,7.013E+01,6.654E+01,&
+6.300E+01,5.954E+01,5.616E+01,5.301E+01,5.001E+01,4.723E+01,4.463E+01,4.220E+01,3.996E+01,3.780E+01,&
+3.567E+01,3.362E+01,3.170E+01,2.993E+01,2.832E+01,2.679E+01,2.535E+01,2.402E+01,2.276E+01,2.150E+01,&
+2.024E+01,1.901E+01,1.785E+01,1.676E+01,1.575E+01,1.481E+01,1.392E+01,1.312E+01,1.233E+01,1.161E+01,&
+1.096E+01,1.041E+01,9.924E+00,9.410E+00,8.947E+00,8.508E+00,8.087E+00,7.640E+00,7.269E+00,6.939E+00,&
+6.660E+00,6.422E+00,6.222E+00,6.010E+00,5.782E+00,5.573E+00,5.370E+00,5.173E+00,4.946E+00,4.761E+00,&
+4.575E+00,4.419E+00,4.259E+00,4.117E+00,4.006E+00,3.945E+00,3.853E+00,3.784E+00,3.671E+00,3.554E+00,&
+3.462E+00,3.364E+00,3.282E+00,3.184E+00,3.102E+00,3.051E+00,2.983E+00,2.947E+00,2.913E+00,2.869E+00,&
+2.803E+00,2.777E+00,2.751E+00,2.726E+00,2.702E+00,2.679E+00,2.656E+00,2.634E+00,2.613E+00,2.593E+00,&
+2.573E+00,2.554E+00,2.536E+00,2.519E+00,2.502E+00,2.486E+00,2.471E+00,2.457E+00,2.443E+00,2.430E+00/
+ data (k_Cm(i),i=101,200)/&
+2.417E+00,2.405E+00,2.394E+00,2.384E+00,2.374E+00,2.365E+00,2.356E+00,2.348E+00,2.341E+00,2.334E+00,&
+2.328E+00,2.323E+00,2.318E+00,2.314E+00,2.310E+00,2.307E+00,2.304E+00,2.303E+00,2.301E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=201,300)/&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=301,400)/&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=401,500)/&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=501,600)/&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=601,700)/&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=701,800)/&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,&
+2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00,2.300E+00/
+ data (k_Cm(i),i=801,900)/&
+2.300E+00,2.300E+00,2.301E+00,2.301E+00,2.302E+00,2.303E+00,2.305E+00,2.306E+00,2.308E+00,2.310E+00,&
+2.312E+00,2.315E+00,2.318E+00,2.320E+00,2.323E+00,2.327E+00,2.330E+00,2.334E+00,2.338E+00,2.342E+00,&
+2.346E+00,2.350E+00,2.354E+00,2.359E+00,2.364E+00,2.369E+00,2.374E+00,2.379E+00,2.384E+00,2.389E+00,&
+2.395E+00,2.400E+00,2.406E+00,2.412E+00,2.418E+00,2.424E+00,2.430E+00,2.436E+00,2.442E+00,2.448E+00,&
+2.454E+00,2.461E+00,2.467E+00,2.473E+00,2.480E+00,2.486E+00,2.493E+00,2.499E+00,2.506E+00,2.512E+00,&
+2.519E+00,2.525E+00,2.532E+00,2.538E+00,2.545E+00,2.551E+00,2.558E+00,2.564E+00,2.570E+00,2.577E+00,&
+2.583E+00,2.589E+00,2.595E+00,2.601E+00,2.607E+00,2.613E+00,2.619E+00,2.625E+00,2.631E+00,2.636E+00,&
+2.642E+00,2.647E+00,2.652E+00,2.657E+00,2.662E+00,2.667E+00,2.672E+00,2.677E+00,2.681E+00,2.685E+00,&
+2.689E+00,2.693E+00,2.697E+00,2.701E+00,2.704E+00,2.708E+00,2.711E+00,2.714E+00,2.716E+00,2.719E+00,&
+2.721E+00,2.723E+00,2.725E+00,2.726E+00,2.728E+00,2.729E+00,2.730E+00,2.730E+00,2.731E+00,2.731E+00/
+ data (k_Cm(i),i=901,1000)/&
+2.721E+00,2.736E+00,2.728E+00,2.719E+00,2.712E+00,2.698E+00,2.702E+00,2.691E+00,2.688E+00,2.686E+00,&
+2.682E+00,2.676E+00,2.675E+00,2.677E+00,2.670E+00,2.671E+00,2.668E+00,2.670E+00,2.674E+00,2.674E+00,&
+2.683E+00,2.674E+00,2.675E+00,2.682E+00,2.683E+00,2.665E+00,2.661E+00,2.668E+00,2.670E+00,2.674E+00,&
+2.664E+00,2.661E+00,2.665E+00,2.668E+00,2.681E+00,2.686E+00,2.684E+00,2.697E+00,2.712E+00,2.720E+00,&
+2.717E+00,2.726E+00,2.744E+00,2.743E+00,2.751E+00,2.763E+00,2.778E+00,2.793E+00,2.818E+00,2.835E+00,&
+2.865E+00,2.879E+00,2.899E+00,2.918E+00,2.936E+00,2.953E+00,2.966E+00,2.977E+00,2.981E+00,2.942E+00,&
+2.888E+00,2.864E+00,2.877E+00,2.886E+00,2.888E+00,2.891E+00,2.899E+00,2.887E+00,2.884E+00,2.900E+00,&
+2.929E+00,2.969E+00,3.014E+00,3.053E+00,3.075E+00,3.111E+00,3.128E+00,3.130E+00,3.103E+00,3.051E+00,&
+2.980E+00,2.941E+00,2.920E+00,2.931E+00,2.950E+00,2.979E+00,3.025E+00,3.048E+00,3.066E+00,3.087E+00,&
+3.099E+00,3.090E+00,3.088E+00,3.081E+00,3.086E+00,3.071E+00,3.065E+00,3.069E+00,3.067E+00,3.085E+00/
+ data (k_Cm(i),i=1001,1100)/&
+3.094E+00,3.110E+00,3.136E+00,3.149E+00,3.158E+00,3.191E+00,3.230E+00,3.266E+00,3.298E+00,3.356E+00,&
+3.419E+00,3.476E+00,3.534E+00,3.584E+00,3.632E+00,3.708E+00,3.775E+00,3.847E+00,3.931E+00,3.987E+00,&
+4.071E+00,4.156E+00,4.242E+00,4.320E+00,4.395E+00,4.480E+00,4.561E+00,4.638E+00,4.708E+00,4.782E+00,&
+4.846E+00,4.906E+00,4.974E+00,5.026E+00,5.071E+00,5.131E+00,5.179E+00,5.220E+00,5.271E+00,5.322E+00,&
+5.358E+00,5.403E+00,5.441E+00,5.460E+00,5.481E+00,5.500E+00,5.523E+00,5.548E+00,5.560E+00,5.575E+00,&
+5.582E+00,5.597E+00,5.611E+00,5.639E+00,5.653E+00,5.675E+00,5.682E+00,5.685E+00,5.680E+00,5.689E+00,&
+5.711E+00,5.723E+00,5.715E+00,5.716E+00,5.732E+00,5.741E+00,5.743E+00,5.752E+00,5.745E+00,5.744E+00,&
+5.757E+00,5.766E+00,5.781E+00,5.787E+00,5.798E+00,5.810E+00,5.808E+00,5.815E+00,5.825E+00,5.824E+00,&
+5.827E+00,5.854E+00,5.878E+00,5.900E+00,5.908E+00,5.922E+00,5.940E+00,5.962E+00,5.963E+00,5.966E+00,&
+5.982E+00,5.990E+00,5.994E+00,6.016E+00,6.014E+00,6.025E+00,6.008E+00,6.022E+00,6.021E+00,6.027E+00/
+ data (k_Cm(i),i=1101,1200)/&
+6.027E+00,6.035E+00,6.025E+00,6.009E+00,5.990E+00,5.987E+00,5.984E+00,5.971E+00,5.971E+00,5.973E+00,&
+5.951E+00,5.952E+00,5.939E+00,5.933E+00,5.931E+00,5.925E+00,5.909E+00,5.897E+00,5.884E+00,5.881E+00,&
+5.876E+00,5.856E+00,5.843E+00,5.830E+00,5.818E+00,5.807E+00,5.799E+00,5.792E+00,5.776E+00,5.783E+00,&
+5.776E+00,5.767E+00,5.762E+00,5.769E+00,5.756E+00,5.762E+00,5.737E+00,5.740E+00,5.757E+00,5.756E+00,&
+5.751E+00,5.754E+00,5.751E+00,5.750E+00,5.744E+00,5.744E+00,5.754E+00,5.744E+00,5.735E+00,5.740E+00,&
+5.732E+00,5.728E+00,5.731E+00,5.724E+00,5.724E+00,5.715E+00,5.697E+00,5.693E+00,5.703E+00,5.700E+00,&
+5.713E+00,5.728E+00,5.731E+00,5.735E+00,5.743E+00,5.754E+00,5.753E+00,5.744E+00,5.746E+00,5.746E+00,&
+5.746E+00,5.750E+00,5.749E+00,5.743E+00,5.740E+00,5.747E+00,5.739E+00,5.755E+00,5.749E+00,5.753E+00,&
+5.745E+00,5.732E+00,5.735E+00,5.724E+00,5.725E+00,5.712E+00,5.702E+00,5.700E+00,5.700E+00,5.686E+00,&
+5.685E+00,5.672E+00,5.659E+00,5.627E+00,5.613E+00,5.590E+00,5.591E+00,5.563E+00,5.552E+00,5.525E+00/
+ data (k_Cm(i),i=1201,1300)/&
+5.517E+00,5.506E+00,5.494E+00,5.459E+00,5.450E+00,5.438E+00,5.428E+00,5.407E+00,5.391E+00,5.382E+00,&
+5.376E+00,5.358E+00,5.347E+00,5.333E+00,5.319E+00,5.301E+00,5.292E+00,5.284E+00,5.274E+00,5.258E+00,&
+5.253E+00,5.249E+00,5.233E+00,5.222E+00,5.211E+00,5.204E+00,5.210E+00,5.200E+00,5.193E+00,5.186E+00,&
+5.177E+00,5.175E+00,5.178E+00,5.173E+00,5.152E+00,5.135E+00,5.139E+00,5.128E+00,5.121E+00,5.114E+00,&
+5.126E+00,5.107E+00,5.104E+00,5.100E+00,5.109E+00,5.114E+00,5.112E+00,5.128E+00,5.137E+00,5.131E+00,&
+5.152E+00,5.175E+00,5.194E+00,5.200E+00,5.244E+00,5.257E+00,5.273E+00,5.289E+00,5.335E+00,5.366E+00,&
+5.389E+00,5.427E+00,5.453E+00,5.490E+00,5.522E+00,5.562E+00,5.605E+00,5.652E+00,5.698E+00,5.744E+00,&
+5.743E+00,5.642E+00,5.689E+00,5.722E+00,5.755E+00,5.798E+00,5.848E+00,5.875E+00,5.918E+00,5.971E+00,&
+6.022E+00,6.061E+00,6.116E+00,6.173E+00,6.214E+00,6.266E+00,6.319E+00,6.382E+00,6.426E+00,6.486E+00,&
+6.542E+00,6.579E+00,6.616E+00,6.666E+00,6.728E+00,6.771E+00,6.807E+00,6.858E+00,6.908E+00,6.959E+00/
+ data (k_Cm(i),i=1301,1400)/&
+7.006E+00,7.052E+00,7.093E+00,7.136E+00,7.164E+00,7.199E+00,7.232E+00,7.266E+00,7.315E+00,7.340E+00,&
+7.361E+00,7.399E+00,7.440E+00,7.473E+00,7.505E+00,7.525E+00,7.557E+00,7.579E+00,7.604E+00,7.633E+00,&
+7.653E+00,7.674E+00,7.691E+00,7.699E+00,7.708E+00,7.721E+00,7.730E+00,7.729E+00,7.712E+00,7.702E+00,&
+7.695E+00,7.670E+00,7.644E+00,7.618E+00,7.585E+00,7.555E+00,7.517E+00,7.479E+00,7.451E+00,7.435E+00,&
+7.408E+00,7.379E+00,7.363E+00,7.347E+00,7.332E+00,7.332E+00,7.332E+00,7.304E+00,7.295E+00,7.296E+00,&
+7.291E+00,7.292E+00,7.292E+00,7.281E+00,7.283E+00,7.264E+00,7.250E+00,7.240E+00,7.228E+00,7.210E+00,&
+7.186E+00,7.164E+00,7.143E+00,7.114E+00,7.101E+00,7.069E+00,7.038E+00,7.003E+00,6.974E+00,6.928E+00,&
+6.889E+00,6.839E+00,6.793E+00,6.764E+00,6.729E+00,6.694E+00,6.662E+00,6.613E+00,6.572E+00,6.546E+00,&
+6.522E+00,6.507E+00,6.482E+00,6.484E+00,6.479E+00,6.494E+00,6.496E+00,6.491E+00,6.461E+00,6.440E+00,&
+6.430E+00,6.413E+00,6.421E+00,6.399E+00,6.379E+00,6.365E+00,6.372E+00,6.346E+00,6.321E+00,6.310E+00/
+ data (k_Cm(i),i=1401,1500)/&
+6.314E+00,6.282E+00,6.277E+00,6.270E+00,6.258E+00,6.242E+00,6.234E+00,6.221E+00,6.231E+00,6.221E+00,&
+6.205E+00,6.193E+00,6.192E+00,6.179E+00,6.159E+00,6.143E+00,6.143E+00,6.120E+00,6.098E+00,6.087E+00,&
+6.063E+00,6.056E+00,6.053E+00,6.040E+00,6.044E+00,6.007E+00,5.996E+00,5.994E+00,5.997E+00,5.975E+00,&
+5.954E+00,5.946E+00,5.927E+00,5.914E+00,5.890E+00,5.873E+00,5.832E+00,5.794E+00,5.768E+00,5.728E+00,&
+5.681E+00,5.680E+00,5.655E+00,5.648E+00,5.620E+00,5.594E+00,5.567E+00,5.557E+00,5.552E+00,5.553E+00,&
+5.539E+00,5.524E+00,5.507E+00,5.505E+00,5.487E+00,5.474E+00,5.462E+00,5.450E+00,5.448E+00,5.441E+00,&
+5.440E+00,5.442E+00,5.450E+00,5.466E+00,5.461E+00,5.452E+00,5.445E+00,5.412E+00,5.379E+00,5.280E+00,&
+5.228E+00,5.199E+00,5.171E+00,5.139E+00,5.124E+00,5.112E+00,5.129E+00,5.145E+00,5.173E+00,5.176E+00,&
+5.185E+00,5.183E+00,5.200E+00,5.202E+00,5.204E+00,5.224E+00,5.244E+00,5.297E+00,5.318E+00,5.376E+00,&
+5.441E+00,5.491E+00,5.561E+00,5.629E+00,5.687E+00,5.757E+00,5.830E+00,5.911E+00,5.998E+00,6.090E+00/
+ data (k_Cm(i),i=1501,1600)/&
+6.193E+00,6.330E+00,6.449E+00,6.581E+00,6.710E+00,6.838E+00,6.970E+00,7.107E+00,7.238E+00,7.388E+00,&
+7.506E+00,7.635E+00,7.767E+00,7.874E+00,7.977E+00,8.071E+00,8.150E+00,8.220E+00,8.292E+00,8.350E+00,&
+8.449E+00,8.521E+00,8.583E+00,8.666E+00,8.723E+00,8.759E+00,8.821E+00,8.864E+00,8.909E+00,8.941E+00,&
+8.949E+00,8.955E+00,8.983E+00,9.022E+00,9.043E+00,9.044E+00,9.028E+00,9.034E+00,9.052E+00,9.048E+00,&
+9.041E+00,9.037E+00,9.036E+00,9.035E+00,9.021E+00,9.016E+00,9.008E+00,8.970E+00,8.974E+00,8.953E+00,&
+8.957E+00,8.937E+00,8.923E+00,8.912E+00,8.895E+00,8.891E+00,8.880E+00,8.867E+00,8.855E+00,8.852E+00,&
+8.861E+00,8.864E+00,8.876E+00,8.869E+00,8.873E+00,8.855E+00,8.828E+00,8.839E+00,8.855E+00,8.856E+00,&
+8.833E+00,8.842E+00,8.844E+00,8.830E+00,8.808E+00,8.818E+00,8.807E+00,8.797E+00,8.794E+00,8.791E+00,&
+8.795E+00,8.772E+00,8.754E+00,8.759E+00,8.760E+00,8.746E+00,8.762E+00,8.778E+00,8.790E+00,8.795E+00,&
+8.811E+00,8.848E+00,8.874E+00,8.885E+00,8.913E+00,8.944E+00,8.981E+00,8.988E+00,9.001E+00,9.034E+00/
+ data (k_Cm(i),i=1601,1700)/&
+9.076E+00,9.111E+00,9.141E+00,9.171E+00,9.214E+00,9.255E+00,9.304E+00,9.356E+00,9.406E+00,9.448E+00,&
+9.516E+00,9.578E+00,9.638E+00,9.692E+00,9.763E+00,9.845E+00,9.953E+00,1.004E+01,1.015E+01,1.027E+01,&
+1.039E+01,1.052E+01,1.063E+01,1.077E+01,1.091E+01,1.103E+01,1.119E+01,1.135E+01,1.150E+01,1.166E+01,&
+1.181E+01,1.201E+01,1.217E+01,1.235E+01,1.251E+01,1.269E+01,1.287E+01,1.307E+01,1.325E+01,1.346E+01,&
+1.364E+01,1.384E+01,1.404E+01,1.423E+01,1.441E+01,1.461E+01,1.481E+01,1.499E+01,1.518E+01,1.534E+01,&
+1.554E+01,1.571E+01,1.591E+01,1.607E+01,1.622E+01,1.637E+01,1.653E+01,1.667E+01,1.678E+01,1.690E+01,&
+1.698E+01,1.709E+01,1.718E+01,1.725E+01,1.734E+01,1.739E+01,1.748E+01,1.755E+01,1.761E+01,1.767E+01,&
+1.771E+01,1.777E+01,1.783E+01,1.787E+01,1.794E+01,1.795E+01,1.799E+01,1.805E+01,1.809E+01,1.813E+01,&
+1.820E+01,1.827E+01,1.830E+01,1.835E+01,1.841E+01,1.846E+01,1.852E+01,1.856E+01,1.861E+01,1.866E+01,&
+1.871E+01,1.876E+01,1.881E+01,1.885E+01,1.890E+01,1.896E+01,1.903E+01,1.907E+01,1.911E+01,1.916E+01/
+ data (k_Cm(i),i=1701,1800)/&
+1.921E+01,1.927E+01,1.929E+01,1.932E+01,1.935E+01,1.936E+01,1.940E+01,1.943E+01,1.947E+01,1.951E+01,&
+1.953E+01,1.956E+01,1.960E+01,1.961E+01,1.962E+01,1.966E+01,1.966E+01,1.969E+01,1.970E+01,1.972E+01,&
+1.974E+01,1.974E+01,1.976E+01,1.978E+01,1.979E+01,1.982E+01,1.982E+01,1.983E+01,1.986E+01,1.988E+01,&
+1.989E+01,1.989E+01,1.993E+01,1.993E+01,1.997E+01,2.001E+01,2.001E+01,2.004E+01,2.007E+01,2.011E+01,&
+2.014E+01,2.015E+01,2.017E+01,2.019E+01,2.022E+01,2.023E+01,2.023E+01,2.026E+01,2.027E+01,2.029E+01,&
+2.028E+01,2.027E+01,2.029E+01,2.029E+01,2.031E+01,2.029E+01,2.026E+01,2.030E+01,2.031E+01,2.030E+01,&
+2.030E+01,2.031E+01,2.029E+01,2.029E+01,2.026E+01,2.025E+01,2.023E+01,2.020E+01,2.016E+01,2.015E+01,&
+2.012E+01,2.009E+01,2.007E+01,2.003E+01,1.998E+01,1.996E+01,1.991E+01,1.986E+01,1.980E+01,1.975E+01,&
+1.969E+01,1.964E+01,1.959E+01,1.953E+01,1.947E+01,1.941E+01,1.936E+01,1.931E+01,1.922E+01,1.918E+01,&
+1.912E+01,1.906E+01,1.899E+01,1.890E+01,1.885E+01,1.881E+01,1.875E+01,1.867E+01,1.861E+01,1.858E+01/
+ data (k_Cm(i),i=1801,1900)/&
+1.852E+01,1.846E+01,1.840E+01,1.834E+01,1.829E+01,1.824E+01,1.819E+01,1.813E+01,1.807E+01,1.803E+01,&
+1.798E+01,1.792E+01,1.788E+01,1.782E+01,1.780E+01,1.775E+01,1.773E+01,1.768E+01,1.768E+01,1.766E+01,&
+1.763E+01,1.762E+01,1.763E+01,1.764E+01,1.764E+01,1.766E+01,1.770E+01,1.774E+01,1.779E+01,1.786E+01,&
+1.795E+01,1.803E+01,1.814E+01,1.825E+01,1.836E+01,1.851E+01,1.866E+01,1.881E+01,1.895E+01,1.913E+01,&
+1.932E+01,1.951E+01,1.972E+01,1.994E+01,2.017E+01,2.040E+01,2.065E+01,2.089E+01,2.114E+01,2.140E+01,&
+2.163E+01,2.186E+01,2.210E+01,2.237E+01,2.262E+01,2.290E+01,2.313E+01,2.339E+01,2.361E+01,2.387E+01,&
+2.410E+01,2.435E+01,2.455E+01,2.479E+01,2.499E+01,2.521E+01,2.541E+01,2.562E+01,2.583E+01,2.605E+01,&
+2.626E+01,2.643E+01,2.657E+01,2.674E+01,2.689E+01,2.701E+01,2.718E+01,2.732E+01,2.742E+01,2.754E+01,&
+2.763E+01,2.777E+01,2.794E+01,2.804E+01,2.821E+01,2.836E+01,2.850E+01,2.863E+01,2.878E+01,2.896E+01,&
+2.913E+01,2.922E+01,2.937E+01,2.947E+01,2.960E+01,2.970E+01,2.982E+01,2.997E+01,3.007E+01,3.018E+01/
+ data (k_Cm(i),i=1901,2000)/&
+3.028E+01,3.040E+01,3.053E+01,3.060E+01,3.066E+01,3.070E+01,3.076E+01,3.078E+01,3.075E+01,3.074E+01,&
+3.072E+01,3.065E+01,3.058E+01,3.051E+01,3.045E+01,3.034E+01,3.029E+01,3.023E+01,3.015E+01,3.004E+01,&
+3.000E+01,2.998E+01,2.991E+01,2.986E+01,2.984E+01,2.981E+01,2.976E+01,2.973E+01,2.976E+01,2.977E+01,&
+2.979E+01,2.981E+01,2.985E+01,2.989E+01,2.999E+01,3.000E+01,3.005E+01,3.007E+01,3.011E+01,3.017E+01,&
+3.022E+01,3.023E+01,3.029E+01,3.028E+01,3.029E+01,3.027E+01,3.027E+01,3.024E+01,3.019E+01,3.010E+01,&
+3.010E+01,3.003E+01,2.993E+01,2.983E+01,2.984E+01,2.975E+01,2.966E+01,2.958E+01,2.948E+01,2.930E+01,&
+2.926E+01,2.920E+01,2.913E+01,2.902E+01,2.890E+01,2.882E+01,2.873E+01,2.873E+01,2.870E+01,2.865E+01,&
+2.858E+01,2.854E+01,2.851E+01,2.846E+01,2.838E+01,2.834E+01,2.823E+01,2.820E+01,2.817E+01,2.809E+01,&
+2.803E+01,2.803E+01,2.801E+01,2.794E+01,2.791E+01,2.790E+01,2.784E+01,2.779E+01,2.781E+01,2.782E+01,&
+2.781E+01,2.781E+01,2.783E+01,2.785E+01,2.785E+01,2.782E+01,2.782E+01,2.780E+01,2.780E+01,2.778E+01/
+ data (k_Cm(i),i=2001,2101)/&
+2.783E+01,2.784E+01,2.788E+01,2.791E+01,2.799E+01,2.804E+01,2.812E+01,2.811E+01,2.819E+01,2.819E+01,&
+2.817E+01,2.817E+01,2.831E+01,2.837E+01,2.848E+01,2.853E+01,2.859E+01,2.870E+01,2.874E+01,2.887E+01,&
+2.898E+01,2.910E+01,2.923E+01,2.934E+01,2.944E+01,2.959E+01,2.973E+01,2.987E+01,3.002E+01,3.016E+01,&
+3.035E+01,3.043E+01,3.064E+01,3.084E+01,3.098E+01,3.122E+01,3.132E+01,3.152E+01,3.165E+01,3.184E+01,&
+3.204E+01,3.221E+01,3.233E+01,3.255E+01,3.282E+01,3.315E+01,3.339E+01,3.360E+01,3.384E+01,3.410E+01,&
+3.426E+01,3.452E+01,3.473E+01,3.497E+01,3.519E+01,3.539E+01,3.561E+01,3.579E+01,3.604E+01,3.618E+01,&
+3.636E+01,3.660E+01,3.675E+01,3.682E+01,3.699E+01,3.711E+01,3.735E+01,3.758E+01,3.792E+01,3.796E+01,&
+3.812E+01,3.822E+01,3.833E+01,3.856E+01,3.874E+01,3.877E+01,3.884E+01,3.883E+01,3.879E+01,3.886E+01,&
+3.900E+01,3.900E+01,3.906E+01,3.905E+01,3.916E+01,3.928E+01,3.948E+01,3.943E+01,3.951E+01,3.964E+01,&
+3.953E+01,3.960E+01,3.958E+01,3.954E+01,3.940E+01,3.936E+01,3.917E+01,3.926E+01,3.893E+01,3.921E+01,&
+3.871E+01/
+
+end
\ No newline at end of file
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_prospect_DB.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_prospect_DB.F90
new file mode 100644
index 0000000000..876f672c79
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_prospect_DB.F90
@@ -0,0 +1,204 @@
+#include
+
+! ********************************************************************************
+! prospect_DB.f90
+! a.k.a. PROSPECT-Dynamic
+! version 6.0 (January, 16th 2017)
+! subroutines required: tav.f90, dataSpec_PDB.f90
+! _______________________________________________________________________
+! for any question or request, please contact:
+!
+! Jean-Baptiste FERET
+! UMR-TETIS, IRSTEA Montpellier
+! Maison de la T�l�d�tection
+! 500 rue Jean-Fracois Breton
+! 34093 Montpellier cedex 5
+! E-mail: jb.feret@teledetection.fr
+!
+! St�phane JACQUEMOUD
+! Universit� Paris Diderot / Institut de Physique du Globe de Paris
+! 35 rue H�l�ne Brion
+! 75013 Paris, France
+! E-mail: jacquemoud@ipgp.fr
+!
+! http://teledetection.ipgp.fr/prosail/
+!______________________________________________________________________
+! Plant leaf reflectance and transmittance are calculated from 400 nm to
+! 2500 nm (1 nm step) with the following parameters:
+!
+! - N = leaf structure parameter
+! - Cab = chlorophyll a+b content in �g/cm�
+! - Car = carotenoids content in �g/cm�
+! - Anth = Anthocyanin content in �g/cm�
+! - Cbrown= brown pigments content in arbitrary units
+! - Cw = equivalent water thickness in g/cm� or cm
+! - Cm = dry matter content in g/cm�
+!
+!Here are some examples observed during the LOPEX'93 experiment on
+!fresh (F) and dry (D) leaves :
+!
+!---------------------------------------------
+! N Cab Cw Cm
+!---------------------------------------------
+!min 1.000 0.0 0.004000 0.001900
+! max 3.000 100.0 0.040000 0.016500
+! corn (F) 1.518 58.0 0.013100 0.003662
+! rice (F) 2.275 23.7 0.007500 0.005811
+! clover (F) 1.875 46.7 0.010000 0.003014
+! laurel (F) 2.660 74.1 0.019900 0.013520
+! ---------------------------------------------
+! min 1.500 0.0 0.000063 0.0019
+! max 3.600 100.0 0.000900 0.0165
+! bamboo (D) 2.698 70.8 0.000117 0.009327
+! lettuce (D) 2.107 35.2 0.000244 0.002250
+! walnut (D) 2.656 62.8 0.000263 0.006573
+! chestnut (D) 1.826 47.7 0.000307 0.004305
+! ---------------------------------------------
+! _______________________________________________________________________!
+! if no information about Anth or Cbrown and work on green / mature leaves
+! set it to 0 !
+! if no information about Car and work on green / mature leaves !
+! set the Chl / Car ratio between 4 and 5. this is not appropriate for !
+! senescent leaves !
+! _______________________________________________________________________!
+! this code includes numerical optimizations proposed in the FLUSPECT code
+! Authors: Wout Verhoef, Christiaan van der Tol (c.vandertol@utwente.nl) &
+! Joris Timmermans
+! Date: 2007
+! Update from PROSPECT to FLUSPECT: January 2011 (CvdT)
+! for more info about FLUSPECT, see publication:
+! Vilfan, N., van der Tol, C., Muller, O., Rascher, U., Verhoef, W., 2016.
+! Fluspect-B: A model for leaf fluorescence, reflectance and transmittance
+! spectra. Remote Sens. Environ. 186, 596�615. doi:10.1016/j.rse.2016.09.017
+
+MODULE MOD_prospect_DB
+USE MOD_Precision
+IMPLICIT NONE
+SAVE
+
+PUBLIC :: prospect_DB
+
+CONTAINS
+subroutine prospect_DB(N,Cab,Car,Anth,Cbrown,Cw,Cm,RT)
+! ********************************************************************************
+! F�ret, Gitelson, Noble & Jacqumoud (2017). PROSPECT-D: Towards modeling
+! leaf optical properties through a complete lifecycle
+! Remote Sensing of Environment, 193:204�215
+! DOI: http://doi.org/10.1016/j.rse.2017.03.004
+! Jacquemoud S., Baret F. (1990), PROSPECT: a model of leaf optical properties
+! spectra, Remote Sensing of Environment, 34:75-91.
+! ********************************************************************************
+
+use MOD_dataSpec_PDB
+use MOD_tav_abs
+implicit none
+
+real(r8), intent(in) :: N,Cab,Car,Anth,Cbrown,Cw,Cm
+real(r8), intent(out) :: RT(nw,2)
+
+real(r8) :: k(nw), tau(nw), xx(nw), yy(nw)
+real(r8) :: ralf(nw),talf(nw),r12(nw),t12(nw),r21(nw),t21(nw)
+real(r8) :: theta1, theta2, denom(nw),Ra(nw),Ta(nw),r(nw),t(nw)
+real(r8) :: d(nw),rq(nw),tq(nw),a(nw),b(nw)
+real(r8) :: bNm1(nw),bN2(nw),a2(nw),Rsub(nw),Tsub(nw)
+
+k = (Cab*k_Cab+Car*k_Car+Anth*k_Anth+Cbrown*k_Brown+Cw*k_Cw+Cm*k_Cm)/N
+
+! ********************************************************************************
+! reflectance and transmittance of one layer
+! ********************************************************************************
+! Allen W.A., Gausman H.W., Richardson A.J., Thomas J.R. (1969), Interaction of
+! isotropic ligth with a compact plant leaf, Journal of the Optical Society of
+! American, 59:1376-1379.
+! ********************************************************************************
+
+! exponential integral: S13AAF routine from the NAG library
+
+where (k.le.0.0)
+ tau = 1
+end where
+where (k.gt.0.0.and.k.le.4.0)
+ xx = 0.5*k-1.0
+ yy = (((((((((((((((-3.60311230482612224d-13 &
+ *xx+3.46348526554087424d-12)*xx-2.99627399604128973d-11) &
+ *xx+2.57747807106988589d-10)*xx-2.09330568435488303d-9) &
+ *xx+1.59501329936987818d-8)*xx-1.13717900285428895d-7) &
+ *xx+7.55292885309152956d-7)*xx-4.64980751480619431d-6) &
+ *xx+2.63830365675408129d-5)*xx-1.37089870978830576d-4) &
+ *xx+6.47686503728103400d-4)*xx-2.76060141343627983d-3) &
+ *xx+1.05306034687449505d-2)*xx-3.57191348753631956d-2) &
+ *xx+1.07774527938978692d-1)*xx-2.96997075145080963d-1
+ yy = (yy*xx+8.64664716763387311d-1)*xx+7.42047691268006429d-1
+ yy = yy-log(k)
+ tau = (1.0-k)*exp(-k)+k**2*yy
+end where
+where (k.gt.4.0.and.k.le.85.0)
+ xx = 14.5/(k+3.25)-1.0
+ yy = (((((((((((((((-1.62806570868460749d-12 &
+ *xx-8.95400579318284288d-13)*xx-4.08352702838151578d-12) &
+ *xx-1.45132988248537498d-11)*xx-8.35086918940757852d-11) &
+ *xx-2.13638678953766289d-10)*xx-1.10302431467069770d-9) &
+ *xx-3.67128915633455484d-9)*xx-1.66980544304104726d-8) &
+ *xx-6.11774386401295125d-8)*xx-2.70306163610271497d-7) &
+ *xx-1.05565006992891261d-6)*xx-4.72090467203711484d-6) &
+ *xx-1.95076375089955937d-5)*xx-9.16450482931221453d-5) &
+ *xx-4.05892130452128677d-4)*xx-2.14213055000334718d-3
+ yy = ((yy*xx-1.06374875116569657d-2)*xx-8.50699154984571871d-2)*xx+9.23755307807784058d-1
+ yy = exp(-k)*yy/k
+ tau = (1.0-k)*exp(-k)+k**2*yy
+end where
+where (k.gt.85.0)
+ tau = 0
+end where
+
+! transmissivity of the layer
+
+theta1 = 90.
+call tav_abs(theta1,refractive,t12)
+theta2 = 40.
+call tav_abs(theta2,refractive,talf)
+ralf = 1.-talf
+r12 = 1.-t12
+t21 = t12/(refractive**2)
+r21 = 1-t21
+! top surface side
+denom = 1-r21*r21*tau**2
+Ta = talf*tau*t21/denom
+Ra = ralf+r21*tau*Ta
+! bottom surface side
+t = t12*tau*t21/denom
+r = r12+r21*tau*t
+
+! ********************************************************************************
+! reflectance and transmittance of N layers
+! ********************************************************************************
+! Stokes G.G. (1862), On the intensity of the light reflected from or transmitted
+! through a pile of plates, Proceedings of the Royal Society of London, 11:545-556.
+! ********************************************************************************
+D = sqrt((1.+r+t)*(1.+r-t)*(1.-r+t)*(1.-r-t))
+rq = r**2
+tq = t**2
+a = (1.+rq-tq+D)/(2*r)
+b = (1.-rq+tq+D)/(2*t)
+
+bNm1 = b**(N-1)
+bN2 = bNm1**2
+a2 = a**2
+denom = a2*bN2-1.
+Rsub = a*(bN2-1.)/denom
+Tsub = bNm1*(a2-1.)/denom
+
+! Case of zero absorption
+where (r+t.ge.1.0)
+ Tsub = t/(t+(1.-t)*(N-1))
+ Rsub = 1-Tsub
+end where
+
+! Reflectance and transmittance of the leaf: combine top layer with next N-1 layers
+denom = 1-Rsub*r
+RT(:,2) = Ta*Tsub/denom
+RT(:,1) = Ra+Ta*Rsub*t/denom
+
+end subroutine
+
+END MODULE
\ No newline at end of file
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/MOD_tav_abs.F90 b/src/core_atmosphere/physics/physics_colm2024/main/MOD_tav_abs.F90
new file mode 100644
index 0000000000..f738a7cb57
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/MOD_tav_abs.F90
@@ -0,0 +1,67 @@
+#include
+
+! ********************************************************************************
+! tav_abs.f90
+! ********************************************************************************
+! computation of the average transmittivity at the leaf surface within a given
+! solid angle. teta is the incidence solid angle (in radian). The average angle
+! that works in most cases is 40deg*pi/180. ref is the refaction index.
+! ********************************************************************************
+! Stern F. (1964), Transmission of isotropic radiation across an interface between
+! two dielectrics, Applied Optics, 3:111-113.
+! Allen W.A. (1973), Transmission of isotropic light across a dielectric surface in
+! two and three dimensions, Journal of the Optical Society of America, 63:664-666.
+! ********************************************************************************
+! version 5.02 (25 July 2011)
+! ********************************************************************************
+MODULE MOD_tav_abs
+IMPLICIT NONE
+PUBLIC :: tav_abs
+
+CONTAINS
+subroutine tav_abs(theta,nr,tav)
+USE MOD_Precision
+use MOD_dataSpec_PDB
+implicit none
+
+real(r8), intent(in) :: theta, nr(nw)
+real(r8), intent(out) :: tav(nw)
+
+real(r8) pi,rd
+real(r8) n2(nw),np(nw),nm(nw)
+real(r8) a(nw),k(nw),sa(nw),b1(nw),b2(nw),b3(nw),b(nw),a3(nw)
+real(r8) ts(nw),tp(nw),tp1(nw),tp2(nw),tp3(nw),tp4(nw),tp5(nw)
+
+
+pi = atan(1.)*4.
+rd = pi/180.
+n2 = nr**2.
+np = n2+1.
+nm = n2-1.
+a = (nr+1)*(nr+1.)/2.
+k = -(n2-1)*(n2-1.)/4.
+sa = sin(theta*rd)
+
+if (theta.eq.90.) then
+ b1=0.
+else
+ b1 = sqrt((sa**2-np/2._r8)*(sa**2-np/2._r8)+k)
+endif
+
+b2 = sa**2-np/2._r8
+b = b1-b2
+b3 = b**3
+a3 = a**3
+ts = (k**2./(6._r8*b3)+k/b-b/2._r8)-(k**2./(6._r8*a3)+k/a-a/2._r8)
+
+tp1 = -2._r8*n2*(b-a)/(np**2)
+tp2 = -2._r8*n2*np*log(b/a)/(nm**2)
+tp3 = n2*(1._r8/b-1._r8/a)/2._r8
+tp4 = 16._r8*n2**2._r8*(n2**2._r8+1._r8)*log((2._r8*np*b-nm**2)/(2._r8*np*a-nm**2))/(np**3._r8*nm**2)
+tp5 = 16._r8*n2**3._r8*(1._r8/(2._r8*np*b-nm**2)-1._r8/(2._r8*np*a-nm**2))/(np**3._r8)
+tp = tp1+tp2+tp3+tp4+tp5
+tav = (ts+tp)/(2._r8*sa**2)
+
+return
+end
+END MODULE MOD_tav_abs
\ No newline at end of file
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/ParaOpt/MOD_Opt_Baseflow.F90 b/src/core_atmosphere/physics/physics_colm2024/main/ParaOpt/MOD_Opt_Baseflow.F90
new file mode 100644
index 0000000000..a1d8c4b3d4
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/ParaOpt/MOD_Opt_Baseflow.F90
@@ -0,0 +1,212 @@
+#include
+
+MODULE MOD_Opt_Baseflow
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ real(r8), allocatable :: scale_baseflow (:)
+
+ real(r8), allocatable :: zwt_init (:)
+ real(r8), allocatable :: rchg_year (:)
+ real(r8), allocatable :: rsub_year (:)
+
+ integer :: iter_bf_opt
+
+CONTAINS
+
+ ! -----
+ SUBROUTINE Opt_Baseflow_init ()
+
+ USE MOD_NetCDFVector
+ USE MOD_Vars_TimeVariables, only: zwt
+ USE MOD_LandPatch, only: numpatch, landpatch
+ IMPLICIT NONE
+
+ ! Local Variables
+ character(len=256) :: file_restart
+
+
+ file_restart = trim(DEF_dir_restart) // '/ParaOpt/' // trim(DEF_CASE_NAME) //'_baseflow.nc'
+ CALL ncio_read_vector (file_restart, 'scale_baseflow', landpatch, scale_baseflow, defval = 1.)
+
+ IF (p_is_root) THEN
+ CALL system('mkdir -p ' // trim(DEF_dir_restart)//'/ParaOpt')
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (DEF_Optimize_Baseflow) THEN
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ allocate (zwt_init (numpatch)); zwt_init (:) = zwt
+ allocate (rchg_year (numpatch)); rchg_year (:) = spval
+ allocate (rsub_year (numpatch)); rsub_year (:) = spval
+ ENDIF
+ ENDIF
+
+ iter_bf_opt = 0
+
+ ENDIF
+
+ END SUBROUTINE Opt_Baseflow_init
+
+ ! -----
+ SUBROUTINE BaseFlow_Optimize (idate, deltim, is_spinup)
+
+ USE MOD_TimeManager
+ USE MOD_NetCDFVector
+ USE MOD_Vars_TimeInvariants, only: patchtype
+ USE MOD_Vars_TimeVariables, only: wice_soisno, zwt
+ USE MOD_Vars_1DForcing, only: forc_prc, forc_prl
+ USE MOD_Vars_1DFluxes, only: fevpa, rsur, rsub
+ USE MOD_LandPatch, only: numpatch, landpatch
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ logical, intent(in) :: is_spinup
+
+ ! Local Variables
+ real(r8), allocatable :: recharge(:)
+ integer :: ipatch
+ character(len=256) :: file_restart
+ character(len=5) :: strcyc
+
+ IF (DEF_Optimize_Baseflow .and. is_spinup) THEN
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+
+ allocate (recharge(numpatch)); recharge(:) = spval
+ WHERE ((forc_prc /= spval) .and. (forc_prl /= spval) .and. (fevpa /= spval) .and. (rsur /= spval))
+ recharge = forc_prc + forc_prl - fevpa - rsur
+ END WHERE
+
+ CALL add_spv (recharge, rchg_year, deltim)
+
+ deallocate (recharge)
+
+ CALL add_spv (rsub, rsub_year, deltim)
+
+ ENDIF
+ ENDIF
+
+ IF (isendofyear(idate,deltim)) THEN
+
+ iter_bf_opt = iter_bf_opt + 1
+
+ write(strcyc,'(A1,I4.4)') 'c', iter_bf_opt
+ IF (p_is_root) THEN
+ CALL system('mkdir -p ' // trim(DEF_dir_restart)//'/ParaOpt/'//strcyc)
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ file_restart = trim(DEF_dir_restart)//'/ParaOpt/'//strcyc//'/'//trim(DEF_CASE_NAME)//'_baseflow.nc'
+ CALL ncio_create_file_vector (file_restart, landpatch)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+ CALL ncio_write_vector (file_restart, 'zwt', 'patch', landpatch, zwt, 1)
+ CALL ncio_write_vector (file_restart, 'zwt_init', 'patch', landpatch, zwt_init, 1)
+ CALL ncio_write_vector (file_restart, 'scale_baseflow', 'patch', landpatch, scale_baseflow, 1)
+ CALL ncio_write_vector (file_restart, 'total_recharge', 'patch', landpatch, rchg_year, 1)
+ CALL ncio_write_vector (file_restart, 'total_subsurface_runoff', 'patch', landpatch, rsub_year, 1)
+
+ IF (p_is_compute) THEN
+ DO ipatch = 1, numpatch
+ IF (patchtype(ipatch) <= 1) THEN
+
+ IF ((rchg_year(ipatch) > 0) .and. (rsub_year(ipatch) > 0)) THEN
+
+ IF ((zwt(ipatch) > zwt_init(ipatch)) .and. (rchg_year(ipatch) < rsub_year(ipatch))) THEN
+
+ scale_baseflow(ipatch) = rchg_year(ipatch)/rsub_year(ipatch) * scale_baseflow(ipatch)
+
+ ENDIF
+
+ IF ((zwt(ipatch) < zwt_init(ipatch)) .and. (rchg_year(ipatch) > rsub_year(ipatch))) THEN
+
+ scale_baseflow(ipatch) = rchg_year(ipatch)/rsub_year(ipatch) * scale_baseflow(ipatch)
+
+ ENDIF
+
+ ENDIF
+
+ scale_baseflow(ipatch) = max(1.e-8, scale_baseflow(ipatch))
+
+ ENDIF
+ ENDDO
+ ENDIF
+
+ file_restart = trim(DEF_dir_restart) // '/ParaOpt/' // trim(DEF_CASE_NAME) //'_baseflow.nc'
+ CALL ncio_create_file_vector (file_restart, landpatch)
+ CALL ncio_define_dimension_vector (file_restart, landpatch, 'patch')
+ CALL ncio_write_vector (file_restart, 'scale_baseflow', 'patch', landpatch, scale_baseflow, 1)
+
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ rchg_year(:) = spval
+ rsub_year(:) = spval
+ ENDIF
+ ENDIF
+
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE BaseFlow_Optimize
+
+ ! -----
+ SUBROUTINE Opt_Baseflow_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(scale_baseflow)) deallocate(scale_baseflow)
+ IF (allocated(zwt_init )) deallocate(zwt_init )
+ IF (allocated(rchg_year )) deallocate(rchg_year )
+ IF (allocated(rsub_year )) deallocate(rsub_year )
+
+ END SUBROUTINE Opt_Baseflow_final
+
+ !-----------------------------------------------------------------------
+ SUBROUTINE add_spv (var, s, dt)
+
+ USE MOD_Precision
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: var(:)
+ real(r8), intent(inout) :: s (:)
+ real(r8), intent(in), optional :: dt
+ ! Local variables
+ integer :: i
+
+ IF (present(dt)) THEN
+ DO i = lbound(var,1), ubound(var,1)
+ IF (var(i) /= spval) THEN
+ IF (s(i) /= spval) THEN
+ s(i) = s(i) + var(i)*dt
+ ELSE
+ s(i) = var(i)*dt
+ ENDIF
+ ENDIF
+ ENDDO
+ ELSE
+ DO i = lbound(var,1), ubound(var,1)
+ IF (var(i) /= spval) THEN
+ IF (s(i) /= spval) THEN
+ s(i) = s(i) + var(i)
+ ELSE
+ s(i) = var(i)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE add_spv
+END MODULE MOD_Opt_Baseflow
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/ParaOpt/MOD_ParameterOptimization.F90 b/src/core_atmosphere/physics/physics_colm2024/main/ParaOpt/MOD_ParameterOptimization.F90
new file mode 100644
index 0000000000..a9a9f61eb8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/ParaOpt/MOD_ParameterOptimization.F90
@@ -0,0 +1,44 @@
+#include
+
+MODULE MOD_ParameterOptimization
+
+ USE MOD_Precision
+ USE MOD_Opt_Baseflow
+ IMPLICIT NONE
+ SAVE
+
+CONTAINS
+
+ ! -----
+ SUBROUTINE ParaOpt_init (ref_date_in, ref_lc_year_in)
+
+ IMPLICIT NONE
+ integer :: ref_date_in(3), ref_lc_year_in
+
+ CALL Opt_Baseflow_init ()
+
+ END SUBROUTINE ParaOpt_init
+
+ ! -----
+ SUBROUTINE ParameterOptimization (idate, deltim, is_spinup)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: idate(3)
+ real(r8), intent(in) :: deltim
+ logical, intent(in) :: is_spinup
+
+ CALL BaseFlow_Optimize (idate, deltim, is_spinup)
+
+ END SUBROUTINE ParameterOptimization
+
+ ! -----
+ SUBROUTINE ParaOpt_final ()
+
+ IMPLICIT NONE
+
+ CALL Opt_Baseflow_final ()
+
+ END SUBROUTINE ParaOpt_final
+
+END MODULE MOD_ParameterOptimization
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/CoLMMAIN_Urban.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/CoLMMAIN_Urban.F90
new file mode 100644
index 0000000000..b3aad898d2
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/CoLMMAIN_Urban.F90
@@ -0,0 +1,1351 @@
+#include
+
+!-----------------------------------------------------------------------
+!
+! --- CoLM 3D Building Community Urban Model ---
+!
+! Sun
+! \\\
+! \\\
+! ______
+! |++++++| roof
+! |++++++|_ AC ______
+! |++++++|_| ___ |++++++|
+! ______+++++| ||||| |++++++|
+! |++++++|++++| ||||||| |++++++|
+! sunlit |[]++[]|++++| ||||| |++++++| shaded
+! wall |++++++| | tree |++++++| wall
+! |[]++[]| | |++++++|
+! |++++++| impervious/pervious ground
+! __________|++++++|____________________________________
+!
+! !DESCRIPTION:
+!
+! Unlike the traditional urban canyon models, the CoLM urban model is
+! based on the assumption of a three-dimensional urban building
+! community, including trees and water bodies. We have developed a new
+! approach for shortwave and longwave radiation transfer, as well as
+! turbulent exchange within the three-dimensional urban buildings. In
+! the process of calculating radiation transfer and turbulent exchange,
+! we have integrated simulations of vegetation and water bodies.
+!
+! The CoLM urban model utilizes comprehensive high-resolution data on
+! urban cover, geometric structure, vegetation, water bodies, etc.
+! Furthermore, it has developed a relatively complete simulation of
+! anthropogenic heat processes, including building energy consumption,
+! traffic heat, and metabolic heat.
+!
+! Created by Hua Yuan, 09/2021
+!
+!
+! !REVISIONS (major):
+!
+! 03/2022, Hua Yuan: complete the model with full coupling, and make
+! it possible to run multiple scenario assumptions through
+! macro definitions.
+!
+! 07/2022, Wenzong Dong: add LUCY model initial version.
+!
+! 05/2023, Hua Yuan: Initial urban physical codes in MPI version. Add
+! some interface or modifications for Urban model coupling.
+!
+! 05/2023, Wenzong Dong, Hua Yuan, Shupeng Zhang: porting urban making
+! surface data codes to MPI parallel version.
+!
+! 05/2023, Hua Yuan: Rename files and modules align with current
+! version.
+!
+!-----------------------------------------------------------------------
+
+ SUBROUTINE CoLMMAIN_Urban ( &
+
+ ! model running information
+ ipatch ,idate ,coszen ,deltim ,&
+ patchlonr ,patchlatr ,patchclass ,patchtype ,&
+
+ ! urban and lake depth
+ froof ,flake ,hroof ,hlr ,&
+ fgper ,em_roof ,em_wall ,em_gimp ,&
+ em_gper ,cv_roof ,cv_wall ,cv_gimp ,&
+ tk_roof ,tk_wall ,tk_gimp ,z_roof ,&
+ z_wall ,dz_roof ,dz_wall ,lakedepth ,&
+ dz_lake ,elvstd ,BVIC ,&
+
+ ! LUCY model input parameters
+ fix_holiday ,week_holiday ,hum_prof ,pop_den ,&
+ vehicle ,weh_prof ,wdh_prof ,&
+
+ ! soil ground and wall information
+ vf_quartz ,vf_gravels ,vf_om ,vf_sand ,&
+ wf_gravels ,wf_sand ,porsl ,psi0 ,&
+ bsw ,theta_r ,fsatmax ,fsatdcf ,&
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm ,n_vgm ,L_vgm ,&
+ sc_vgm ,fc_vgm ,&
+#endif
+ hksati ,csol ,k_solids ,dksatu ,&
+ dksatf ,dkdry ,BA_alpha ,BA_beta ,&
+ alb_roof ,alb_wall ,alb_gimp ,alb_gper ,&
+
+ ! vegetation information
+ htop ,hbot ,sqrtdi ,chil ,&
+ effcon ,vmax25 ,c3c4 ,slti ,hlti,&
+ shti ,hhti ,trda ,trdm ,&
+ trop ,g1 ,g0 ,gradm ,&
+ binter ,extkn ,rho ,tau ,&
+ rootfr ,lambda ,&
+
+ ! atmospheric forcing
+ forc_pco2m ,forc_po2m ,forc_us ,forc_vs ,&
+ forc_t ,forc_q ,forc_prc ,forc_prl ,&
+ forc_rain ,forc_snow ,forc_psrf ,forc_pbot ,&
+ forc_sols ,forc_soll ,forc_solsd ,forc_solld ,&
+ forc_frl ,forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,&
+ forc_rhoair ,Fhac ,Fwst ,Fach ,&
+ Fahe ,Fhah ,vehc ,meta ,&
+
+ ! land surface variables required for restart
+ z_sno_roof ,z_sno_gimp ,z_sno_gper ,z_sno_lake ,&
+ dz_sno_roof ,dz_sno_gimp ,dz_sno_gper ,dz_sno_lake ,&
+ t_roofsno ,t_gimpsno ,t_gpersno ,t_lakesno ,&
+ wliq_roofsno ,wliq_gimpsno ,wliq_gpersno ,wliq_lakesno ,&
+ wice_roofsno ,wice_gimpsno ,wice_gpersno ,wice_lakesno ,&
+ z_sno ,dz_sno ,wliq_soisno ,wice_soisno ,&
+ t_soisno ,smp ,hk ,t_wallsun ,&
+ t_wallsha ,&
+
+ lai ,sai ,fveg ,sigf ,&
+ green ,tleaf ,ldew ,ldew_rain ,&
+ ldew_snow ,fwet_snow ,t_grnd ,&
+
+ sag_roof ,sag_gimp ,sag_gper ,sag_lake ,&
+ scv_roof ,scv_gimp ,scv_gper ,scv_lake ,&
+ snowdp_roof ,snowdp_gimp ,snowdp_gper ,snowdp_lake ,&
+ fsno_roof ,fsno_gimp ,fsno_gper ,fsno_lake ,&
+ sag ,scv ,snowdp ,fsno ,&
+ extkd ,alb ,ssun ,ssha ,&
+ sroof ,swsun ,swsha ,sgimp ,&
+ sgper ,slake ,lwsun ,lwsha ,&
+ lgimp ,lgper ,lveg ,fwsun ,&
+ dfwsun ,t_room ,troof_inner ,twsun_inner ,&
+ twsha_inner ,t_roommax ,t_roommin ,tafu ,&
+
+ zwt ,wdsrf ,wa ,&
+ t_lake ,lake_icefrac ,savedtke1 ,&
+
+ ! SNICAR snow model related
+ snw_rds ,ssno ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+
+ ! additional diagnostic variables for output
+ laisun ,laisha ,rss ,&
+ rstfac ,h2osoi ,wat ,&
+
+ ! FLUXES
+ taux ,tauy ,fsena ,fevpa ,&
+ lfevpa ,fsenl ,fevpl ,etr ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ fsen_roof ,fsen_wsun ,fsen_wsha ,fsen_gimp ,&
+ fsen_gper ,fsen_urbl ,troof ,twall ,&
+ lfevp_roof ,lfevp_gimp ,lfevp_gper ,lfevp_urbl ,&
+ trad ,tref ,&!tmax ,tmin ,&
+ qref ,rsur ,rnof ,qintr ,&
+ qinfl ,qdrip ,rst ,assim ,&
+ respc ,sabvsun ,sabvsha ,sabg ,&
+ sr ,solvd ,solvi ,solnd ,&
+ solni ,srvd ,srvi ,srnd ,&
+ srni ,solvdln ,solviln ,solndln ,&
+ solniln ,srvdln ,srviln ,srndln ,&
+ srniln ,qcharge ,xerr ,zerr ,&
+
+ ! TUNABLE model constants
+ zlnd ,zsno ,csoilc ,dewmx ,&
+ capr ,cnfac ,ssi ,wimp ,&
+ pondmx ,smpmax ,smpmin ,trsmx0 ,&
+ tcrit ,&
+
+ ! additional variables required by coupling with WRF model
+ emis ,z0m ,zol ,rib ,&
+ ustar ,qstar ,tstar ,fm ,&
+ fh ,fq ,hpbl )
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: tfrz, denh2o, denice
+ USE MOD_Vars_TimeVariables, only: tlai, tsai
+ USE MOD_SnowLayersCombineDivide
+ USE MOD_LeafInterception
+ USE MOD_Urban_Albedo
+ USE MOD_Urban_NetSolar
+ USE MOD_Urban_Thermal
+ USE MOD_Urban_Hydrology
+ USE MOD_Lake
+ USE MOD_TimeManager
+ USE MOD_RainSnowTemp, only: rain_snow_temp
+ USE MOD_NewSnow, only: newsnow
+ USE MOD_OrbCoszen, only: orb_coszen
+ USE MOD_SnowFraction, only: snowfraction
+ USE MOD_ALBEDO, only: snowage
+ USE MOD_Qsadv, only: qsadv
+#ifdef USE_LUCY
+ USE MOD_Urban_LUCY
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch ,&! maximum number of snow layers
+ idate(3) ,&! next time-step /year/julian day/second in a day/
+ patchclass ,&! land cover type of USGS classification or others
+ patchtype ! land patch type (0=soil, 1=urban and built-up,
+ ! 2=wetland, 3=land ice, 4=land water bodies, 99 = ocean)
+
+ real(r8),intent(in) :: &
+ deltim ,&! seconds in a time step [second]
+ patchlonr ,&! longitude in radians
+ patchlatr ! latitude in radians
+
+ real(r8),intent(inout) :: &
+ coszen ! cosine of solar zenith angle
+
+ ! Parameters
+ ! ----------------------
+ real(r8), intent(in) :: &
+ fix_holiday(365) ,&! Fixed public holidays, holiday(0) or workday(1)
+ week_holiday(7) ,&! week holidays
+ hum_prof(24) ,&! Diurnal metabolic heat profile
+ weh_prof(24) ,&! Diurnal traffic flow profile of weekend
+ wdh_prof(24) ,&! Diurnal traffic flow profile of weekday
+ pop_den ,&! population density
+ vehicle(3) ! vehicle numbers per thousand people
+
+ real(r8), intent(in) :: &
+ froof ,&! roof fractional cover [-]
+ fgper ,&! impervious fraction to ground area [-]
+ flake ,&! lake fraction to ground area [-]
+ hroof ,&! average building height [m]
+ hlr ,&! average building height to their side length [-]
+ em_roof ,&! emissivity of roof [-]
+ em_wall ,&! emissivity of walls [-]
+ em_gimp ,&! emissivity of impervious [-]
+ em_gper ! emissivity of pervious [-]
+
+ real(r8), intent(in) :: &
+ cv_roof (1:nl_roof) ,&! heat capacity of roof [J/(m2 K)]
+ cv_wall (1:nl_wall) ,&! heat capacity of wall [J/(m2 K)]
+ cv_gimp (1:nl_soil) ,&! heat capacity of impervious [J/(m2 K)]
+ tk_roof (1:nl_roof) ,&! thermal conductivity of roof [W/m-K]
+ tk_wall (1:nl_wall) ,&! thermal conductivity of wall [W/m-K]
+ tk_gimp (1:nl_soil) ! thermal conductivity of impervious [W/m-K]
+
+ real(r8), intent(in) :: &
+ ! soil physical parameters and lake info
+ vf_quartz (nl_soil) ,&! volumetric fraction of quartz within mineral soil
+ vf_gravels (nl_soil) ,&! volumetric fraction of gravels
+ vf_om (nl_soil) ,&! volumetric fraction of organic matter
+ vf_sand (nl_soil) ,&! volumetric fraction of sand
+ wf_gravels (nl_soil) ,&! gravimetric fraction of gravels
+ wf_sand (nl_soil) ,&! gravimetric fraction of sand
+ porsl (nl_soil) ,&! fraction of soil that is voids [-]
+ psi0 (nl_soil) ,&! minimum soil suction [mm]
+ bsw (nl_soil) ,&! clapp and hornberger "b" parameter [-]
+ theta_r (nl_soil) ,&! residual water content (cm3/cm3)
+ fsatmax ,&! maximum saturated area fraction [-]
+ fsatdcf ,&! decay factor in calculation of saturated area fraction [1/m]
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ alpha_vgm (1:nl_soil) ,&! parameter correspond approximately to inverse of air-entry value
+ n_vgm (1:nl_soil) ,&! a shape parameter
+ L_vgm (1:nl_soil) ,&! pore-connectivity parameter
+ sc_vgm (1:nl_soil) ,&! saturation at air entry value in classical vanGenuchten model [-]
+ fc_vgm (1:nl_soil) ,&! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+ hksati (nl_soil) ,&! hydraulic conductivity at saturation [mm h2o/s]
+ csol (nl_soil) ,&! heat capacity of soil solids [J/(m3 K)]
+ k_solids (nl_soil) ,&! thermal conductivity of minerals soil [W/m-K]
+ dksatu (nl_soil) ,&! thermal conductivity of saturated unfrozen soil [W/m-K]
+ dksatf (nl_soil) ,&! thermal conductivity of saturated frozen soil [W/m-K]
+ dkdry (nl_soil) ,&! thermal conductivity for dry soil [J/(K s m)]
+
+ BA_alpha (nl_soil) ,&! alpha in Balland and Arp(2005) thermal conductivity scheme
+ BA_beta (nl_soil) ,&! beta in Balland and Arp(2005) thermal conductivity scheme
+ alb_roof(2,2) ,&! albedo of roof [-]
+ alb_wall(2,2) ,&! albedo of walls [-]
+ alb_gimp(2,2) ,&! albedo of impervious [-]
+ alb_gper(2,2) ,&! albedo of pervious [-]
+
+ ! vegetation static, dynamic, derived parameters
+ sqrtdi ,&! inverse sqrt of leaf dimension [m**-0.5]
+ chil ,&! leaf angle distribution factor
+ effcon ,&! quantum efficiency of RuBP regeneration (mol CO2/mol quanta)
+ vmax25 ,&! maximum carboxylation rate at 25 C at canopy top
+ slti ,&! slope of low temperature inhibition function [s3]
+ hlti ,&! 1/2 point of low temperature inhibition function [s4]
+ shti ,&! slope of high temperature inhibition function [s1]
+ hhti ,&! 1/2 point of high temperature inhibition function [s2]
+ trda ,&! temperature coefficient in gs-a model [s5]
+ trdm ,&! temperature coefficient in gs-a model [s6]
+ trop ,&! temperature coefficient in gs-a model
+ g1 ,&! conductance-photosynthesis slope parameter for medlyn model
+ g0 ,&! conductance-photosynthesis intercept for medlyn model
+ gradm ,&! conductance-photosynthesis slope parameter
+ binter ,&! conductance-photosynthesis intercep
+ extkn ,&! coefficient of leaf nitrogen allocation
+ rho(2,2) ,&! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2) ,&! leaf transmittance (iw=iband, il=life and dead)
+
+ rootfr (nl_soil) ,&! fraction of roots in each soil layer
+ lambda ,&! marginal water cost of carbon gain
+
+ ! tunable parameters
+ zlnd ,&! roughness length for soil [m]
+ zsno ,&! roughness length for snow [m]
+ csoilc ,&! drag coefficient for soil under canopy [-]
+ dewmx ,&! maximum dew
+ ! wtfact ,&! fraction of model area with high water table
+ ! (updated to gridded 'fsatmax')
+ capr ,&! tuning factor to turn first layer T into surface T
+ cnfac ,&! Crank Nicholson factor between 0 and 1
+ ssi ,&! irreducible water saturation of snow
+ wimp ,&! water impermeable IF porosity less than wimp
+ pondmx ,&! ponding depth (mm)
+ smpmax ,&! wilting point potential in mm
+ smpmin ,&! restriction for min of soil poten. (mm)
+ trsmx0 ,&! max transpiration for moist soil+100% veg. [mm/s]
+ tcrit ! critical temp. to determine rain or snow
+
+ integer, intent(in) :: c3c4 ! 1 for C3, 0 for C4
+
+ real(r8), intent(in) :: hpbl ! atmospheric boundary layer height [m]
+
+ ! Forcing
+ ! ----------------------
+ real(r8), intent(in) :: &
+ forc_pco2m ,&! partial pressure of CO2 at observational height [pa]
+ forc_po2m ,&! partial pressure of O2 at observational height [pa]
+ forc_us ,&! wind speed in eastward direction [m/s]
+ forc_vs ,&! wind speed in northward direction [m/s]
+ forc_t ,&! temperature at agcm reference height [kelvin]
+ forc_q ,&! specific humidity at agcm reference height [kg/kg]
+ forc_prc ,&! convective precipitation [mm/s]
+ forc_prl ,&! large scale precipitation [mm/s]
+ forc_psrf ,&! atmosphere pressure at the surface [pa]
+ forc_pbot ,&! atmosphere pressure at the bottom of the atmos. model level [pa]
+ forc_sols ,&! atm vis direct beam solar rad onto srf [W/m2]
+ forc_soll ,&! atm nir direct beam solar rad onto srf [W/m2]
+ forc_solsd ,&! atm vis diffuse solar rad onto srf [W/m2]
+ forc_solld ,&! atm nir diffuse solar rad onto srf [W/m2]
+ forc_frl ,&! atmospheric infrared (longwave) radiation [W/m2]
+ forc_hgt_u ,&! observational height of wind [m]
+ forc_hgt_t ,&! observational height of temperature [m]
+ forc_hgt_q ,&! observational height of humidity [m]
+ forc_rhoair ! density air [kg/m3]
+
+! Variables required for restart run
+! ----------------------------------------------------------------------
+ real(r8), intent(inout) :: &
+ t_wallsun ( 1:nl_wall) ,&! sunlit wall layer temperature [K]
+ t_wallsha ( 1:nl_wall) ,&! shaded wall layer temperature [K]
+ t_soisno (maxsnl+1:nl_soil) ,&! soil + snow layer temperature [K]
+ t_roofsno (maxsnl+1:nl_roof) ,&! soil + snow layer temperature [K]
+ t_gimpsno (maxsnl+1:nl_soil) ,&! soil + snow layer temperature [K]
+ t_gpersno (maxsnl+1:nl_soil) ,&! soil + snow layer temperature [K]
+ t_lakesno (maxsnl+1:nl_soil) ,&! soil + snow layer temperature [K]
+ wliq_soisno (maxsnl+1:nl_soil) ,&! liquid water (kg/m2)
+ wliq_roofsno (maxsnl+1:nl_roof) ,&! liquid water (kg/m2)
+ wliq_gimpsno (maxsnl+1:nl_soil) ,&! liquid water (kg/m2)
+ wliq_gpersno (maxsnl+1:nl_soil) ,&! liquid water (kg/m2)
+ wliq_lakesno (maxsnl+1:nl_soil) ,&! liquid water (kg/m2)
+ wice_soisno (maxsnl+1:nl_soil) ,&! ice lens (kg/m2)
+ wice_roofsno (maxsnl+1:nl_roof) ,&! ice lens (kg/m2)
+ wice_gimpsno (maxsnl+1:nl_soil) ,&! ice lens (kg/m2)
+ wice_gpersno (maxsnl+1:nl_soil) ,&! ice lens (kg/m2)
+ wice_lakesno (maxsnl+1:nl_soil) ,&! ice lens (kg/m2)
+ smp ( 1:nl_soil) ,&! soil matrix potential [mm]
+ hk ( 1:nl_soil) ,&! hydraulic conductivity [mm h2o/s]
+
+ z_sno (maxsnl+1:0) ,&! node depth [m]
+ dz_sno (maxsnl+1:0) ,&! interface depth [m]
+ z_sno_roof (maxsnl+1:0) ,&! node depth of roof [m]
+ z_sno_gimp (maxsnl+1:0) ,&! node depth of impervious [m]
+ z_sno_gper (maxsnl+1:0) ,&! node depth pervious [m]
+ z_sno_lake (maxsnl+1:0) ,&! node depth lake [m]
+ dz_sno_roof (maxsnl+1:0) ,&! interface depth of roof [m]
+ dz_sno_gimp (maxsnl+1:0) ,&! interface depth of impervious [m]
+ dz_sno_gper (maxsnl+1:0) ,&! interface depth pervious [m]
+ dz_sno_lake (maxsnl+1:0) ,&! interface depth lake [m]
+
+ lakedepth ,&! lake depth (m)
+ z_roof (nl_roof) ,&! thickness of roof [m]
+ z_wall (nl_wall) ,&! thickness of wall [m]
+ dz_roof (nl_roof) ,&! thickness of each layer [m]
+ dz_wall (nl_wall) ,&! thickness of each layer [m]
+ dz_lake (nl_lake) ,&! lake layer thickness (m)
+ t_lake (nl_lake) ,&! lake temperature (kelvin)
+ lake_icefrac (nl_lake) ,&! lake mass fraction of lake layer that is frozen
+ savedtke1 ,&! top level eddy conductivity (W/m K)
+
+ elvstd ,&! standard deviation of elevation [m]
+ BVIC ,&! b parameter in Fraction of saturated soil calculated by VIC
+
+ t_grnd ,&! ground surface temperature [k]
+ tleaf ,&! sunlit leaf temperature [K]
+ !tmax ,&! Diurnal Max 2 m height air temperature [kelvin]
+ !tmin ,&! Diurnal Min 2 m height air temperature [kelvin]
+ ldew ,&! depth of water on foliage [kg/m2/s]
+ ldew_rain ,&! depth of rain on foliage[kg/m2/s]
+ ldew_snow ,&! depth of snow on foliage[kg/m2/s]
+ fwet_snow ,&! vegetation canopy snow fractional cover [-]
+ sag ,&! non dimensional snow age [-]
+ sag_roof ,&! non dimensional snow age [-]
+ sag_gimp ,&! non dimensional snow age [-]
+ sag_gper ,&! non dimensional snow age [-]
+ sag_lake ,&! non dimensional snow age [-]
+ scv ,&! snow mass (kg/m2)
+ scv_roof ,&! snow mass (kg/m2)
+ scv_gimp ,&! snow mass (kg/m2)
+ scv_gper ,&! snow mass (kg/m2)
+ scv_lake ,&! snow mass (kg/m2)
+ snowdp ,&! snow depth (m)
+ snowdp_roof ,&! snow depth (m)
+ snowdp_gimp ,&! snow depth (m)
+ snowdp_gper ,&! snow depth (m)
+ snowdp_lake ,&! snow depth (m)
+ zwt ,&! the depth to water table [m]
+ wdsrf ,&! depth of surface water [mm]
+ wa ,&! water storage in aquifer [mm]
+
+ snw_rds ( maxsnl+1:0 ) ,&! effective grain radius (col,lyr) [microns, m-6]
+ mss_bcpho ( maxsnl+1:0 ) ,&! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi ( maxsnl+1:0 ) ,&! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho ( maxsnl+1:0 ) ,&! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi ( maxsnl+1:0 ) ,&! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 ( maxsnl+1:0 ) ,&! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 ( maxsnl+1:0 ) ,&! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 ( maxsnl+1:0 ) ,&! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 ( maxsnl+1:0 ) ,&! mass of dust species 4 in snow (col,lyr) [kg]
+ ssno (2,2,maxsnl+1:1 ) ,&! snow layer absorption [-]
+
+ fveg ,&! fraction of vegetation cover
+ fsno ,&! fractional snow cover
+ fsno_roof ,&! fractional snow cover
+ fsno_gimp ,&! fractional snow cover
+ fsno_gper ,&! fractional snow cover
+ fsno_lake ,&! fractional snow cover
+ sigf ,&! fraction of veg cover, excluding snow-covered veg [-]
+ green ,&! greenness
+ lai ,&! leaf area index
+ sai ,&! stem area index
+ htop ,&! canopy crown top
+ hbot ,&! canopy crown bottom
+
+ lwsun ,&! net longwave of sunlit wall [W/m2]
+ lwsha ,&! net longwave of shaded wall [W/m2]
+ lgimp ,&! net longwave of impervious [W/m2]
+ lgper ,&! net longwave of pervious [W/m2]
+ lveg ,&! net longwave of vegetation [W/m2]
+ fwsun ,&! sunlit fraction of walls [-]
+ dfwsun ,&! change of sunlit fraction of walls [-]
+ t_room ,&! temperature of inner building [K]
+ troof_inner ,&! temperature of inner roof [K]
+ twsun_inner ,&! temperature of inner sunlit wall [K]
+ twsha_inner ,&! temperature of inner shaded wall [K]
+ t_roommax ,&! maximum temperature of inner room [K]
+ t_roommin ,&! minimum temperature of inner room [K]
+ tafu ,&! temperature of outer building [K]
+ Fhac ,&! sensible flux from heat or cool AC [W/m2]
+ Fwst ,&! waste heat flux from heat or cool AC [W/m2]
+ Fach ,&! flux from inner and outer air exchange [W/m2]
+ Fahe ,&! flux from metabolism and vehicle [W/m2]
+ Fhah ,&! sensible heat flux from heating [W/m2]
+ vehc ,&! flux from vehicle [W/m2]
+ meta ,&! flux from metabolism [W/m2]
+
+ extkd ,&! diffuse and scattered diffuse PAR extinction coefficient
+ alb (2,2) ,&! averaged albedo [-]
+ ssun (2,2) ,&! sunlit canopy absorption for solar radiation
+ ssha (2,2) ,&! shaded canopy absorption for solar radiation
+ sroof(2,2) ,&! shaded canopy absorption for solar radiation
+ swsun(2,2) ,&! shaded canopy absorption for solar radiation
+ swsha(2,2) ,&! shaded canopy absorption for solar radiation
+ sgimp(2,2) ,&! shaded canopy absorption for solar radiation
+ sgper(2,2) ,&! shaded canopy absorption for solar radiation
+ slake(2,2) ! shaded canopy absorption for solar radiation
+
+! additional diagnostic variables for output
+ real(r8), intent(out) :: &
+ laisun ,&! sunlit leaf area index
+ laisha ,&! shaded leaf area index
+ rstfac ,&! factor of soil water stress
+ rss ,&! soil surface resistance
+ wat ,&! total water storage
+ h2osoi(nl_soil) ! volumetric soil water in layers [m3/m3]
+
+! Fluxes
+! ----------------------------------------------------------------------
+ real(r8), intent(out) :: &
+ taux ,&! wind stress: E-W [kg/m/s**2]
+ tauy ,&! wind stress: N-S [kg/m/s**2]
+ fsena ,&! sensible heat from canopy height to atmosphere [W/m2]
+ fevpa ,&! evapotranspiration from canopy height to atmosphere [mm/s]
+ lfevpa ,&! latent heat flux from canopy height to atmosphere [W/2]
+ fsenl ,&! sensible heat from leaves [W/m2]
+ fevpl ,&! evaporation+transpiration from leaves [mm/s]
+ etr ,&! transpiration rate [mm/s]
+ fseng ,&! sensible heat flux from ground [W/m2]
+ fevpg ,&! evaporation heat flux from ground [mm/s]
+ olrg ,&! outgoing long-wave radiation from ground+canopy
+ fgrnd ,&! ground heat flux [W/m2]
+ xerr ,&! water balance error at current time-step [mm/s]
+ zerr ,&! energy balance error at current time-step [W/m2]
+
+ tref ,&! 2 m height air temperature [K]
+ qref ,&! 2 m height air specific humidity
+ trad ,&! radiative temperature [K]
+ rsur ,&! surface runoff (mm h2o/s)
+ rnof ,&! total runoff (mm h2o/s)
+ qintr ,&! interception (mm h2o/s)
+ qinfl ,&! infiltration (mm h2o/s)
+ qdrip ,&! throughfall (mm h2o/s)
+ qcharge ,&! groundwater recharge [mm/s]
+
+ rst ,&! canopy stomatal resistance
+ assim ,&! canopy assimilation
+ respc ,&! canopy respiration
+
+ fsen_roof ,&! sensible heat flux from roof [W/m2]
+ fsen_wsun ,&! sensible heat flux from sunlit wall [W/m2]
+ fsen_wsha ,&! sensible heat flux from shaded wall [W/m2]
+ fsen_gimp ,&! sensible heat flux from impervious road [W/m2]
+ fsen_gper ,&! sensible heat flux from pervious road [W/m2]
+ fsen_urbl ,&! sensible heat flux from urban vegetation [W/m2]
+
+ lfevp_roof ,&! latent heat flux from roof [W/m2]
+ lfevp_gimp ,&! latent heat flux from impervious road [W/m2]
+ lfevp_gper ,&! latent heat flux from pervious road [W/m2]
+ lfevp_urbl ,&! latent heat flux from urban vegetation [W/m2]
+
+ troof ,&! temperature of roof [K]
+ twall ,&! temperature of wall [K]
+
+ sabvsun ,&! solar absorbed by sunlit vegetation [W/m2]
+ sabvsha ,&! solar absorbed by shaded vegetation [W/m2]
+ sabg ,&! solar absorbed by ground [W/m2]
+ sr ,&! total reflected solar radiation (W/m2)
+ solvd ,&! incident direct beam vis solar radiation (W/m2)
+ solvi ,&! incident diffuse beam vis solar radiation (W/m2)
+ solnd ,&! incident direct beam nir solar radiation (W/m2)
+ solni ,&! incident diffuse beam nir solar radiation (W/m2)
+ srvd ,&! reflected direct beam vis solar radiation (W/m2)
+ srvi ,&! reflected diffuse beam vis solar radiation (W/m2)
+ srnd ,&! reflected direct beam nir solar radiation (W/m2)
+ srni ,&! reflected diffuse beam nir solar radiation (W/m2)
+ solvdln ,&! incident direct beam vis solar radiation at local noon(W/m2)
+ solviln ,&! incident diffuse beam vis solar radiation at local noon(W/m2)
+ solndln ,&! incident direct beam nir solar radiation at local noon(W/m2)
+ solniln ,&! incident diffuse beam nir solar radiation at local noon(W/m2)
+ srvdln ,&! reflected direct beam vis solar radiation at local noon(W/m2)
+ srviln ,&! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ srndln ,&! reflected direct beam nir solar radiation at local noon(W/m2)
+ srniln ,&! reflected diffuse beam nir solar radiation at local noon(W/m2)
+
+ forc_rain ,&! rain [mm/s]
+ forc_snow ,&! snow [mm/s]
+
+ emis ,&! averaged bulk surface emissivity
+ z0m ,&! effective roughness [m]
+ zol ,&! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib ,&! bulk Richardson number in surface layer
+ ustar ,&! u* in similarity theory [m/s]
+ qstar ,&! q* in similarity theory [kg/kg]
+ tstar ,&! t* in similarity theory [K]
+ fm ,&! integral of profile function for momentum
+ fh ,&! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ calday ,&! Julian cal day (1.xx to 365.xx)
+ endwb ,&! water mass at the end of time step
+ errore ,&! energy balance error (Wm-2)
+ errorw ,&! water balance error (mm)
+ fioldr (maxsnl+1:nl_roof), &! fraction of ice relative to the total water
+ fioldi (maxsnl+1:nl_soil), &! fraction of ice relative to the total water
+ fioldp (maxsnl+1:nl_soil), &! fraction of ice relative to the total water
+ fioldl (maxsnl+1:nl_soil), &! fraction of ice relative to the total water
+ w_old ,&! liquid water mass of the column at the previous time step (mm)
+ theta ,&! sun zenith angle
+ sabv ,&! solar absorbed by vegetation [W/m2]
+ sabroof ,&! solar absorbed by vegetation [W/m2]
+ sabwsun ,&! solar absorbed by vegetation [W/m2]
+ sabwsha ,&! solar absorbed by vegetation [W/m2]
+ sabgimp ,&! solar absorbed by vegetation [W/m2]
+ sabgper ,&! solar absorbed by vegetation [W/m2]
+ sablake ,&! solar absorbed by vegetation [W/m2]
+ par ,&! PAR by leaves [W/m2]
+ tgimp ,&! temperature of impervious surface [K]
+ tgper ,&! temperature of pervious surface [K]
+ tlake ,&! temperature of lake surface [K]
+ qdrip_gper ,&! throughfall of pervious (mm h2o/s)
+ qseva_roof ,&! ground surface evaporation rate (mm h2o/s)
+ qseva_gimp ,&! ground surface evaporation rate (mm h2o/s)
+ qseva_gper ,&! ground surface evaporation rate (mm h2o/s)
+ qseva_lake ,&! ground surface evaporation rate (mm h2o/s)
+ qsdew_roof ,&! ground surface dew formation (mm h2o /s) [+]
+ qsdew_gimp ,&! ground surface dew formation (mm h2o /s) [+]
+ qsdew_gper ,&! ground surface dew formation (mm h2o /s) [+]
+ qsdew_lake ,&! ground surface dew formation (mm h2o /s) [+]
+ qsubl_roof ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qsubl_gimp ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qsubl_gper ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qsubl_lake ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros_roof ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_gimp ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_gper ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_lake ,&! surface dew added to snow pack (mm h2o /s) [+]
+ scvold_roof ,&! snow mass on roof for previous time step [kg/m2]
+ scvold_gimp ,&! snow mass on impervious surfaces for previous time step [kg/m2]
+ scvold_gper ,&! snow mass on pervious surfaces for previous time step [kg/m2]
+ scvold_lake ,&! snow mass on lake for previous time step [kg/m2]
+ sm_roof ,&! rate of snowmelt [kg/(m2 s)]
+ sm_gimp ,&! rate of snowmelt [kg/(m2 s)]
+ sm_gper ,&! rate of snowmelt [kg/(m2 s)]
+ sm_lake ,&! rate of snowmelt [kg/(m2 s)]
+ totwb ,&! water mass at the begining of time step
+ totwb_roof ,&! water mass at the begining of time step
+ totwb_gimp ,&! water mass at the begining of time step
+ totwb_gper ,&! water mass at the begining of time step
+ wt ,&! fraction of vegetation buried (covered) by snow [-]
+ rootr (1:nl_soil) ,&! root resistance of a layer, all layers add to 1.0
+ rootflux (1:nl_soil) ,&! root resistance of a layer, all layers add to 1.0
+ etr_deficit ,&! urban tree etr deficit [mm/s]
+ urb_irrig ,&! named urban tree irrigation [mm/s]
+
+ zi_wall ( 0:nl_wall) ,&! interface level below a "z" level [m]
+ z_roofsno (maxsnl+1:nl_roof) ,&! layer depth [m]
+ z_gimpsno (maxsnl+1:nl_soil) ,&! layer depth [m]
+ z_gpersno (maxsnl+1:nl_soil) ,&! layer depth [m]
+ z_lakesno (maxsnl+1:nl_soil) ,&! layer depth [m]
+ dz_roofsno (maxsnl+1:nl_roof) ,&! layer thickness [m]
+ dz_gimpsno (maxsnl+1:nl_soil) ,&! layer thickness [m]
+ dz_gpersno (maxsnl+1:nl_soil) ,&! layer thickness [m]
+ dz_lakesno (maxsnl+1:nl_soil) ,&! layer thickness [m]
+ zi_roofsno (maxsnl :nl_roof) ,&! interface level below a "z" level [m]
+ zi_gimpsno (maxsnl :nl_soil) ,&! interface level below a "z" level [m]
+ zi_gpersno (maxsnl :nl_soil) ,&! interface level below a "z" level [m]
+ zi_lakesno (maxsnl :nl_soil) ! interface level below a "z" level [m]
+
+ real(r8) :: &
+ prc_rain ,&! convective rainfall [kg/(m2 s)]
+ prc_snow ,&! convective snowfall [kg/(m2 s)]
+ prl_rain ,&! large scale rainfall [kg/(m2 s)]
+ prl_snow ,&! large scale snowfall [kg/(m2 s)]
+ t_precip ,&! snowfall/rainfall temperature [kelvin]
+ bifall ,&! bulk density of newly fallen dry snow [kg/m3]
+ pg_rain ,&! rainfall onto ground including canopy runoff [kg/(m2 s)]
+ pg_snow ,&! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ pgper_rain ,&! rainfall onto ground including canopy runoff [kg/(m2 s)]
+ pgper_snow ,&! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ pgimp_rain ,&! rainfall onto ground including canopy runoff [kg/(m2 s)]
+ pgimp_snow ,&! snowfall onto ground including canopy runoff [kg/(m2 s)]
+ pg_rain_lake ,&! rainfall onto lake [kg/(m2 s)]
+ pg_snow_lake ,&! snowfall onto lake [kg/(m2 s)]
+ qintr_rain ,&! rainfall interception (mm h2o/s)
+ qintr_snow ,&! snowfall interception (mm h2o/s)
+ etrgper ,&! etr for pervious ground
+ fveg_gper ,&! fraction of fveg/fgper
+ fveg_gimp ! fraction of fveg/fgimp
+
+ real(r8) :: &
+ ei ,&! vapor pressure on leaf surface [pa]
+ deidT ,&! derivative of "ei" on "tl" [pa/K]
+ qsatl ,&! leaf specific humidity [kg/kg]
+ qsatldT ! derivative of "qsatl" on "tlef"
+
+ integer :: &
+ snlr ,&! number of snow layers
+ snli ,&! number of snow layers
+ snlp ,&! number of snow layers
+ snll ,&! number of snow layers
+ imeltr (maxsnl+1:nl_roof), &! flag for: melting=1, freezing=2, Nothing happened=0
+ imelti (maxsnl+1:nl_soil), &! flag for: melting=1, freezing=2, Nothing happened=0
+ imeltp (maxsnl+1:nl_soil), &! flag for: melting=1, freezing=2, Nothing happened=0
+ imeltl (maxsnl+1:nl_soil), &! flag for: melting=1, freezing=2, Nothing happened=0
+ lbr ,&! lower bound of arrays
+ lbi ,&! lower bound of arrays
+ lbp ,&! lower bound of arrays
+ lbl ,&! lower bound of arrays
+ lbsn ,&! lower bound of arrays
+ j ! DO looping index
+
+ ! For SNICAR snow model
+ !----------------------------------------------------------------------
+ real(r8) forc_aer ( 14 ) !aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+ real(r8) snofrz (maxsnl+1:0) !snow freezing rate (col,lyr) [kg m-2 s-1]
+ real(r8) sabg_lyr (maxsnl+1:1) !snow layer absorption [W/m-2]
+
+ !irrigation
+ real(r8) :: &
+ qflx_irrig_drip ,&! drip irrigation rate [mm/s]
+ qflx_irrig_sprinkler ,&! sprinkler irrigation rate [mm/s]
+ qflx_irrig_flood ,&! flood irrigation rate [mm/s]
+ qflx_irrig_paddy ! paddy irrigation rate [mm/s]
+
+ ! A simple urban irrigation scheme accounts for soil water stress of trees
+ ! a factor represents irrigation efficiency, '1' represents a 50% direct irrigation efficiency.
+ real(r8), parameter :: wst_irrig = 1.0
+
+!-----------------------------------------------------------------------
+
+ theta = acos(max(coszen,0.01))
+ forc_aer(:) = 0. !aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+
+!======================================================================
+! [1] Solar absorbed by vegetation and ground
+! and precipitation information (rain/snow fall and precip temperature
+!======================================================================
+
+ CALL netsolar_urban (ipatch,idate,patchlonr,deltim,&
+ forc_sols,forc_soll,forc_solsd,forc_solld,lai,sai,rho,tau,&
+ alb(:,:),ssun(:,:),ssha(:,:),sroof(:,:),swsun(:,:),&
+ swsha(:,:),sgimp(:,:),sgper(:,:),slake(:,:),&
+ sr,sabv,par,sabroof,sabwsun,sabwsha,sabgimp,sabgper,sablake,&
+ solvd,solvi,solnd,solni,srvd,srvi,srnd,srni,&
+ solvdln,solviln,solndln,solniln,srvdln,srviln,srndln,srniln)
+
+ CALL rain_snow_temp (patchtype,forc_t,forc_q,forc_psrf,forc_prc,forc_prl,forc_us,forc_vs,&
+ tcrit,prc_rain,prc_snow,prl_rain,prl_snow,t_precip,bifall)
+
+#ifdef MPAS_EMBEDDED_COLM
+ ! MPAS already provides hydrometeor phase; keep it while using CoLM for precipitation temperature.
+ prc_rain = max(0._r8, min(forc_prc, forc_rain))
+ prc_snow = max(0._r8, forc_prc - prc_rain)
+ prl_rain = max(0._r8, forc_rain - prc_rain)
+ prl_snow = max(0._r8, forc_snow - prc_snow)
+#else
+ forc_rain = prc_rain + prl_rain
+ forc_snow = prc_snow + prl_snow
+#endif
+
+ sabvsun = sabv * fveg * (1-flake)
+ sabvsha = 0.
+
+!======================================================================
+
+ z_roofsno (maxsnl+1:0) = z_sno_roof (maxsnl+1:0)
+ z_roofsno (1:nl_roof ) = z_roof (1:nl_roof)
+ dz_roofsno(maxsnl+1:0) = dz_sno_roof(maxsnl+1:0)
+ dz_roofsno(1:nl_roof ) = dz_roof(1:nl_roof)
+
+ z_gimpsno (maxsnl+1:0) = z_sno_gimp (maxsnl+1:0)
+ z_gimpsno (1:nl_soil ) = z_soi (1:nl_soil)
+ dz_gimpsno(maxsnl+1:0) = dz_sno_gimp(maxsnl+1:0)
+ dz_gimpsno(1:nl_soil ) = dz_soi(1:nl_soil)
+
+ z_gpersno (maxsnl+1:0) = z_sno_gper (maxsnl+1:0)
+ z_gpersno (1:nl_soil ) = z_soi (1:nl_soil)
+ dz_gpersno(maxsnl+1:0) = dz_sno_gper(maxsnl+1:0)
+ dz_gpersno(1:nl_soil ) = dz_soi(1:nl_soil)
+
+ z_lakesno (maxsnl+1:0) = z_sno_lake (maxsnl+1:0)
+ z_lakesno (1:nl_soil ) = z_soi (1:nl_soil)
+ dz_lakesno(maxsnl+1:0) = dz_sno_lake(maxsnl+1:0)
+ dz_lakesno(1:nl_soil ) = dz_soi(1:nl_soil)
+
+ !============================================================
+ zi_wall(0) = 0.
+ DO j = 1, nl_wall
+ zi_wall(j) = zi_wall(j-1) + dz_wall(j)
+ ENDDO
+
+ !============================================================
+ scvold_roof = scv_roof !snow mass at previous time step
+
+ snlr = 0
+ DO j = maxsnl+1, 0
+ IF (wliq_roofsno(j)+wice_roofsno(j) > 0.) snlr = snlr - 1
+ ENDDO
+
+ zi_roofsno(0) = 0.
+ IF (snlr < 0) THEN
+ DO j = -1, snlr, -1
+ zi_roofsno(j) = zi_roofsno(j+1) - dz_roofsno(j+1)
+ ENDDO
+ ENDIF
+ DO j = 1, nl_roof
+ zi_roofsno(j) = zi_roofsno(j-1) + dz_roofsno(j)
+ ENDDO
+
+ totwb_roof = scv_roof + wice_roofsno(1) + wliq_roofsno(1)
+ fioldr(:) = 0.0
+ IF (snlr < 0) THEN
+ fioldr(snlr+1:0) = wice_roofsno(snlr+1:0) / &
+ (wliq_roofsno(snlr+1:0) + wice_roofsno(snlr+1:0))
+ ENDIF
+
+ !============================================================
+ scvold_gimp = scv_gimp !snow mass at previous time step
+
+ snli = 0
+ DO j = maxsnl+1, 0
+ IF (wliq_gimpsno(j)+wice_gimpsno(j) > 0.) snli = snli - 1
+ ENDDO
+
+ zi_gimpsno(0) = 0.
+ IF (snli < 0) THEN
+ DO j = -1, snli, -1
+ zi_gimpsno(j) = zi_gimpsno(j+1) - dz_gimpsno(j+1)
+ ENDDO
+ ENDIF
+
+ zi_gimpsno(1:nl_soil) = zi_soi(1:nl_soil)
+
+ totwb_gimp = scv_gimp + wice_gimpsno(1) + wliq_gimpsno(1)
+ fioldi(:) = 0.0
+ IF (snli < 0) THEN
+ fioldi(snli+1:0) = wice_gimpsno(snli+1:0) / &
+ (wliq_gimpsno(snli+1:0) + wice_gimpsno(snli+1:0))
+ ENDIF
+
+ !============================================================
+ scvold_gper = scv_gper !snow mass at previous time step
+
+ snlp = 0
+ DO j = maxsnl+1, 0
+ IF(wliq_gpersno(j)+wice_gpersno(j) > 0.) snlp = snlp - 1
+ ENDDO
+
+ zi_gpersno(0) = 0.
+ IF (snlp < 0) THEN
+ DO j = -1, snlp, -1
+ zi_gpersno(j) = zi_gpersno(j+1) - dz_gpersno(j+1)
+ ENDDO
+ ENDIF
+
+ zi_gpersno(1:nl_soil) = zi_soi(1:nl_soil)
+
+ totwb_gper = ldew + scv_gper + sum(wice_gpersno(1:) + wliq_gpersno(1:)) + wa
+ fioldp(:) = 0.0
+ IF (snlp < 0) THEN
+ fioldp(snlp+1:0) = wice_gpersno(snlp+1:0) / &
+ (wliq_gpersno(snlp+1:0) + wice_gpersno(snlp+1:0))
+ ENDIF
+
+ !============================================================
+ scvold_lake = scv_lake !snow mass at previous time step
+
+ snll = 0
+ DO j = maxsnl+1, 0
+ IF (wliq_lakesno(j) + wice_lakesno(j) > 0.) snll = snll - 1
+ ENDDO
+
+ zi_lakesno(0) = 0.
+ IF (snll < 0) THEN
+ DO j = -1, snll, -1
+ zi_lakesno(j) = zi_lakesno(j+1) - dz_lakesno(j+1)
+ ENDDO
+ ENDIF
+
+ zi_lakesno(1:nl_soil) = zi_soi(1:nl_soil)
+
+ w_old = sum(wliq_lakesno(snll+1:))
+ fioldl(:) = 0.0
+ IF (snll <0 ) THEN
+ fioldl(snll+1:0) = wice_lakesno(snll+1:0) / &
+ (wliq_lakesno(snll+1:0) + wice_lakesno(snll+1:0))
+ ENDIF
+
+ !============================================================
+ totwb = sum(wice_soisno(1:) + wliq_soisno(1:))
+ totwb = totwb + scv + ldew*fveg + wa*(1-froof)*fgper
+
+ etr_deficit = 0.
+ urb_irrig = 0.
+
+!----------------------------------------------------------------------
+! [2] Canopy interception and precipitation onto ground surface
+!----------------------------------------------------------------------
+ qflx_irrig_drip = 0._r8
+ qflx_irrig_sprinkler = 0._r8
+ qflx_irrig_flood = 0._r8
+ qflx_irrig_paddy = 0._r8
+
+ ! with vegetation canopy
+ CALL LEAF_interception_CoLM2014 (deltim,dewmx,forc_us,forc_vs,chil,sigf,lai,sai,tref,tleaf,&
+ prc_rain,prc_snow,prl_rain,prl_snow,qflx_irrig_sprinkler,bifall,&
+ ldew,ldew_rain,ldew_snow,z0m,forc_hgt_u,pgper_rain,pgper_snow,&
+ qintr,qintr_rain,qintr_snow)
+
+ ! for output, patch scale
+ qintr = qintr * fveg * (1-flake)
+ qdrip_gper = pgper_rain + pgper_snow
+ qdrip = forc_rain + forc_snow
+ qdrip = qdrip*(1-fveg*(1-flake)) + qdrip_gper*fveg*(1-flake)
+
+ ! without vegetation canopy
+ pg_rain = prc_rain + prl_rain
+ pg_snow = prc_snow + prl_snow
+ pg_rain_lake = prc_rain + prl_rain
+ pg_snow_lake = prc_snow + prl_snow
+
+ ! for urban hydrology input, only for pervious ground
+ IF (fgper > 0) THEN
+ fveg_gper = fveg/((1-froof)*fgper)
+ ELSE
+ fveg_gper = 0.
+ ENDIF
+
+ IF (fgper < 1) THEN
+ fveg_gimp = (fveg-(1-froof)*fgper)/((1-froof)*(1-fgper))
+ ELSE
+ fveg_gimp = 0.
+ ENDIF
+
+ IF (fveg_gper .le. 1) THEN
+ pgper_rain = pgper_rain*fveg_gper + pg_rain*(1-fveg_gper)
+ pgper_snow = pgper_snow*fveg_gper + pg_snow*(1-fveg_gper)
+ pgimp_rain = pg_rain
+ pgimp_snow = pg_snow
+ ELSE
+ pgimp_rain = pgper_rain*fveg_gimp + pg_rain*(1-fveg_gimp)
+ pgimp_snow = pgper_snow*fveg_gimp + pg_snow*(1-fveg_gimp)
+ ENDIF
+
+!----------------------------------------------------------------------
+! [3] Initialize new snow nodes for snowfall / sleet
+!----------------------------------------------------------------------
+
+ lbr = snlr + 1 !lower bound of array
+ lbi = snli + 1 !lower bound of array
+ lbp = snlp + 1 !lower bound of array
+ troof = t_roofsno(lbr)
+ tgimp = t_gimpsno(lbi)
+ tgper = t_gpersno(lbp)
+
+ CALL newsnow (patchtype,maxsnl,deltim,troof,pg_rain,pg_snow,bifall,&
+ t_precip,zi_roofsno(:0),z_roofsno(:0),dz_roofsno(:0),t_roofsno(:0),&
+ wliq_roofsno(:0),wice_roofsno(:0),fioldr(:0),&
+ snlr,sag_roof,scv_roof,snowdp_roof,fsno_roof)
+
+ CALL newsnow (patchtype,maxsnl,deltim,tgimp,pgimp_rain,pgimp_snow,bifall,&
+ t_precip,zi_gimpsno(:0),z_gimpsno(:0),dz_gimpsno(:0),t_gimpsno(:0),&
+ wliq_gimpsno(:0),wice_gimpsno(:0),fioldi(:0),&
+ snli,sag_gimp,scv_gimp,snowdp_gimp,fsno_gimp)
+
+ CALL newsnow (patchtype,maxsnl,deltim,tgper,pgper_rain,pgper_snow,bifall,&
+ t_precip,zi_gpersno(:0),z_gpersno(:0),dz_gpersno(:0),t_gpersno(:0),&
+ wliq_gpersno(:0),wice_gpersno(:0),fioldp(:0),&
+ snlp,sag_gper,scv_gper,snowdp_gper,fsno_gper)
+
+ CALL newsnow_lake ( DEF_USE_Dynamic_Lake, &
+ ! "in" arguments
+ ! ---------------
+ maxsnl ,nl_lake ,deltim ,dz_lake ,&
+ pg_rain_lake ,pg_snow_lake ,t_precip ,bifall ,&
+
+ ! "inout" arguments
+ ! ------------------
+ t_lake ,zi_lakesno(:0),z_lakesno(:0) ,&
+ dz_lakesno(:0),t_lakesno(:0) ,wliq_lakesno(:0),wice_lakesno(:0),&
+ fioldl(:0) ,snll ,sag_lake ,scv_lake ,&
+ snowdp_lake ,lake_icefrac )
+
+!----------------------------------------------------------------------
+! [4] Energy and Water balance
+!----------------------------------------------------------------------
+
+ lbr = snlr + 1 !lower bound of array
+ lbi = snli + 1 !lower bound of array
+ lbp = snlp + 1 !lower bound of array
+ lbl = snll + 1 !lower bound of array
+ lbsn= min(lbp,0)
+
+ ! Thermal process
+ CALL UrbanTHERMAL ( &
+ ! model running information
+ ipatch ,patchtype ,lbr ,lbi ,&
+ lbp ,lbl ,deltim ,patchlatr ,&
+ ! forcing
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_psrf ,&
+ forc_rhoair ,forc_frl ,forc_po2m ,forc_pco2m ,&
+ forc_sols ,forc_soll ,forc_solsd ,forc_solld ,&
+ theta ,sabroof ,sabwsun ,sabwsha ,&
+ sabgimp ,sabgper ,sablake ,sabv ,&
+ par ,Fhac ,Fwst ,Fach ,&
+ Fahe ,Fhah ,vehc ,meta ,&
+ ! LUCY INPUT PARAMETERS
+ fix_holiday ,week_holiday ,hum_prof ,pop_den ,&
+ vehicle ,weh_prof ,wdh_prof ,idate ,&
+ patchlonr ,&
+ ! GROUND PARAMETERS
+ froof ,flake ,hroof ,hlr ,&
+ fgper ,pondmx ,em_roof ,em_wall ,&
+ em_gimp ,em_gper ,trsmx0 ,zlnd ,&
+ zsno ,capr ,cnfac ,vf_quartz ,&
+ vf_gravels ,vf_om ,vf_sand ,wf_gravels ,&
+ wf_sand ,csol ,porsl ,psi0 ,&
+#ifdef Campbell_SOIL_MODEL
+ bsw ,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r ,alpha_vgm ,n_vgm ,L_vgm ,&
+ sc_vgm ,fc_vgm ,&
+#endif
+ k_solids ,dksatu ,dksatf ,dkdry ,&
+ BA_alpha ,BA_beta ,&
+ cv_roof ,cv_wall ,cv_gimp ,&
+ tk_roof ,tk_wall ,tk_gimp ,dz_roofsno(lbr:) ,&
+ dz_gimpsno(lbi:) ,dz_gpersno(lbp:) ,dz_lakesno(:) ,dz_wall(:) ,&
+ z_roofsno(lbr:) ,z_gimpsno(lbi:) ,z_gpersno(lbp:) ,z_lakesno(:) ,&
+ z_wall(:) ,zi_roofsno(lbr-1:) ,zi_gimpsno(lbi-1:) ,zi_gpersno(lbp-1:) ,&
+ zi_lakesno(:) ,zi_wall(0:) ,dz_lake(1:) ,lakedepth ,&
+ dewmx ,sqrtdi ,rootfr(:) ,effcon ,&
+ vmax25 ,c3c4 ,slti ,hlti ,shti,&
+ hhti ,trda ,trdm ,trop ,&
+ g1 ,g0 ,gradm ,binter ,&
+ extkn ,lambda ,&
+ ! surface status
+ fsno_roof ,fsno_gimp ,fsno_gper ,scv_roof ,&
+ scv_gimp ,scv_gper ,scv_lake ,snowdp_roof ,&
+ snowdp_gimp ,snowdp_gper ,snowdp_lake ,fwsun ,&
+ dfwsun ,lai ,sai ,htop ,&
+ hbot ,fveg ,sigf ,extkd ,&
+ lwsun ,lwsha ,lgimp ,lgper ,&
+ t_grnd ,t_roofsno(lbr:) ,t_wallsun(:) ,t_wallsha(:) ,&
+ t_gimpsno(lbi:) ,t_gpersno(lbp:) ,t_lakesno(:) ,wliq_roofsno(lbr:) ,&
+ wliq_gimpsno(lbi:) ,wliq_gpersno(lbp:) ,wliq_lakesno(:) ,wice_roofsno(lbr:) ,&
+ wice_gimpsno(lbi:) ,wice_gpersno(lbp:) ,wice_lakesno(:) ,t_lake(:) ,&
+ lake_icefrac(:) ,savedtke1 ,lveg ,tleaf ,&
+ ldew ,ldew_rain ,ldew_snow ,fwet_snow ,&
+ t_room ,troof_inner ,twsun_inner ,twsha_inner ,&
+ t_roommax ,t_roommin ,tafu ,&
+
+! SNICAR model variables
+ snofrz(lbsn:0) ,sabg_lyr(lbp:1) ,&
+! END SNICAR model variables
+
+ ! output
+ taux ,tauy ,fsena ,fevpa ,&
+ lfevpa ,fsenl ,fevpl ,etr ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ fsen_roof ,fsen_wsun ,fsen_wsha ,fsen_gimp ,&
+ fsen_gper ,fsen_urbl ,troof ,twall ,&
+ lfevp_roof ,lfevp_gimp ,lfevp_gper ,lfevp_urbl ,&
+ qseva_roof ,qseva_gimp ,qseva_gper ,qseva_lake ,&
+ qsdew_roof ,qsdew_gimp ,qsdew_gper ,qsdew_lake ,&
+ qsubl_roof ,qsubl_gimp ,qsubl_gper ,qsubl_lake ,&
+ qfros_roof ,qfros_gimp ,qfros_gper ,qfros_lake ,&
+ imeltr(lbr:) ,imelti(lbi:) ,imeltp(lbp:) ,imeltl(:) ,&
+ sm_roof ,sm_gimp ,sm_gper ,sm_lake ,&
+ sabg ,rstfac ,rootr(:) ,etr_deficit ,&
+ tref ,qref ,trad ,rst ,&
+ assim ,respc ,errore ,emis ,&
+ z0m ,zol ,rib ,ustar ,&
+ qstar ,tstar ,fm ,fh ,&
+ fq ,hpbl )
+
+!----------------------------------------------------------------------
+! [5] Urban hydrology
+!----------------------------------------------------------------------
+ IF (fveg > 0) THEN
+ ! convert to unit area
+ etrgper = (etr-etr_deficit)/(1-froof)/fgper
+ ELSE
+ etrgper = 0.
+ ENDIF
+
+ pgper_rain = pgper_rain + wst_irrig*etr_deficit/(1-froof)/fgper
+ urb_irrig = etr_deficit + wst_irrig*etr_deficit
+
+ CALL UrbanHydrology ( &
+ ! model running information
+ ipatch ,patchtype ,lbr ,lbi ,&
+ lbp ,lbl ,snll ,deltim ,&
+ ! forcing
+ pg_rain ,pgper_rain ,pgimp_rain ,pg_snow ,&
+ pg_rain_lake ,pg_snow_lake ,&
+ froof ,fgper ,flake ,bsw ,&
+ porsl ,psi0 ,hksati ,pondmx ,&
+ ssi ,wimp ,smpmin ,theta_r ,&
+ fsatmax ,fsatdcf ,elvstd ,BVIC ,&
+ rootr,rootflux ,etrgper ,fseng ,fgrnd ,&
+ t_gpersno(lbp:) ,t_lakesno(:) ,t_lake ,dz_lake ,&
+ z_gpersno(lbp:) ,z_lakesno(:) ,zi_gpersno(lbp-1:) ,zi_lakesno(:) ,&
+ dz_roofsno(lbr:) ,dz_gimpsno(lbi:) ,dz_gpersno(lbp:) ,dz_lakesno(:) ,&
+ wliq_roofsno(lbr:) ,wliq_gimpsno(lbi:) ,wliq_gpersno(lbp:) ,wliq_lakesno(:) ,&
+ wice_roofsno(lbr:) ,wice_gimpsno(lbi:) ,wice_gpersno(lbp:) ,wice_lakesno(:) ,&
+ qseva_roof ,qseva_gimp ,qseva_gper ,qseva_lake ,&
+ qsdew_roof ,qsdew_gimp ,qsdew_gper ,qsdew_lake ,&
+ qsubl_roof ,qsubl_gimp ,qsubl_gper ,qsubl_lake ,&
+ qfros_roof ,qfros_gimp ,qfros_gper ,qfros_lake ,&
+ sm_roof ,sm_gimp ,sm_gper ,sm_lake ,&
+ lake_icefrac ,scv_lake ,snowdp_lake ,imeltl ,&
+ fioldl ,w_old ,&
+ forc_us ,forc_vs ,&
+
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho(lbsn:0) ,mss_bcphi(lbsn:0) ,mss_ocpho(lbsn:0) ,mss_ocphi(lbsn:0) ,&
+ mss_dst1 (lbsn:0) ,mss_dst2 (lbsn:0) ,mss_dst3 (lbsn:0) ,mss_dst4 (lbsn:0) ,&
+! END SNICAR model variables
+! irrigaiton
+ qflx_irrig_drip ,qflx_irrig_flood ,qflx_irrig_paddy ,&
+! end irrigation
+ ! output
+ rsur ,rnof ,qinfl ,zwt ,&
+ wdsrf ,wa ,qcharge ,smp ,hk )
+
+ ! roof
+ !============================================================
+ IF (snlr < 0) THEN
+ ! Compaction rate for snow
+ ! Natural compaction and metamorphosis. The compaction rate
+ ! is recalculated for every new timestep
+ lbr = snlr + 1 ! lower bound of array
+ CALL snowcompaction (lbr,deltim,&
+ imeltr(lbr:0),fioldr(lbr:0),t_roofsno(lbr:0),&
+ wliq_roofsno(lbr:0),wice_roofsno(lbr:0),forc_us,forc_vs,dz_roofsno(lbr:0))
+
+ ! Combine thin snow elements
+ lbr = maxsnl + 1
+ CALL snowlayerscombine (lbr,snlr,&
+ z_roofsno(lbr:1),dz_roofsno(lbr:1),zi_roofsno(lbr-1:1),&
+ wliq_roofsno(lbr:1),wice_roofsno(lbr:1),t_roofsno(lbr:1),&
+ scv_roof,snowdp_roof)
+
+ ! Divide thick snow elements
+ IF (snlr < 0) &
+ CALL snowlayersdivide (lbr,snlr,&
+ z_roofsno(lbr:0),dz_roofsno(lbr:0),zi_roofsno(lbr-1:0),&
+ wliq_roofsno(lbr:0),wice_roofsno(lbr:0),t_roofsno(lbr:0))
+ ENDIF
+
+ ! Set zero to the empty node
+ IF (snlr > maxsnl) THEN
+ wice_roofsno(maxsnl+1:snlr) = 0.
+ wliq_roofsno(maxsnl+1:snlr) = 0.
+ t_roofsno (maxsnl+1:snlr) = 0.
+ z_roofsno (maxsnl+1:snlr) = 0.
+ dz_roofsno (maxsnl+1:snlr) = 0.
+ ENDIF
+
+ lbr = snlr + 1
+ troof = t_roofsno(lbr)
+
+ ! impervious ground
+ !============================================================
+ IF (snli < 0) THEN
+ ! Compaction rate for snow
+ ! Natural compaction and metamorphosis. The compaction rate
+ ! is recalculated for every new timestep
+ lbi = snli + 1 ! lower bound of array
+ CALL snowcompaction (lbi,deltim,&
+ imelti(lbi:0),fioldi(lbi:0),t_gimpsno(lbi:0),&
+ wliq_gimpsno(lbi:0),wice_gimpsno(lbi:0),forc_us,forc_vs,dz_gimpsno(lbi:0))
+
+ ! Combine thin snow elements
+ lbi = maxsnl + 1
+ CALL snowlayerscombine (lbi,snli,&
+ z_gimpsno(lbi:1),dz_gimpsno(lbi:1),zi_gimpsno(lbi-1:1),&
+ wliq_gimpsno(lbi:1),wice_gimpsno(lbi:1),t_gimpsno(lbi:1),&
+ scv_gimp,snowdp_gimp)
+
+ ! Divide thick snow elements
+ IF (snli < 0) &
+ CALL snowlayersdivide (lbi,snli,&
+ z_gimpsno(lbi:0),dz_gimpsno(lbi:0),zi_gimpsno(lbi-1:0),&
+ wliq_gimpsno(lbi:0),wice_gimpsno(lbi:0),t_gimpsno(lbi:0))
+ ENDIF
+
+ ! Set zero to the empty node
+ IF (snli > maxsnl) THEN
+ wice_gimpsno(maxsnl+1:snli) = 0.
+ wliq_gimpsno(maxsnl+1:snli) = 0.
+ t_gimpsno (maxsnl+1:snli) = 0.
+ z_gimpsno (maxsnl+1:snli) = 0.
+ dz_gimpsno (maxsnl+1:snli) = 0.
+ ENDIF
+
+ lbi = snli + 1
+ tgimp = t_gimpsno(lbi)
+
+ ! pervious ground
+ !============================================================
+ IF (snlp < 0) THEN
+ ! Compaction rate for snow
+ ! Natural compaction and metamorphosis. The compaction rate
+ ! is recalculated for every new timestep
+ lbp = snlp + 1 ! lower bound of array
+ CALL snowcompaction (lbp,deltim,&
+ imeltp(lbp:0),fioldp(lbp:0),t_gpersno(lbp:0),&
+ wliq_gpersno(lbp:0),wice_gpersno(lbp:0),forc_us,forc_vs,dz_gpersno(lbp:0))
+
+ ! Combine thin snow elements
+ lbp = maxsnl + 1
+ CALL snowlayerscombine (lbp,snlp,&
+ z_gpersno(lbp:1),dz_gpersno(lbp:1),zi_gpersno(lbp-1:1),&
+ wliq_gpersno(lbp:1),wice_gpersno(lbp:1),t_gpersno(lbp:1),&
+ scv_gper,snowdp_gper)
+
+ ! Divide thick snow elements
+ IF (snlp < 0) &
+ CALL snowlayersdivide (lbp,snlp,&
+ z_gpersno(lbp:0),dz_gpersno(lbp:0),zi_gpersno(lbp-1:0),&
+ wliq_gpersno(lbp:0),wice_gpersno(lbp:0),t_gpersno(lbp:0))
+ ENDIF
+
+ ! Set zero to the empty node
+ IF (snlp > maxsnl) THEN
+ wice_gpersno(maxsnl+1:snlp) = 0.
+ wliq_gpersno(maxsnl+1:snlp) = 0.
+ t_gpersno (maxsnl+1:snlp) = 0.
+ z_gpersno (maxsnl+1:snlp) = 0.
+ dz_gpersno (maxsnl+1:snlp) = 0.
+ ENDIF
+
+ lbp = snlp + 1
+ tgper = t_gpersno(lbp)
+
+ !TODO: temporal, set to t_soisno
+ t_soisno(:) = t_gpersno(:)
+
+ !TODO: how to set tlake
+ lbl = snll + 1
+ IF (lbl < 1) THEN
+ tlake = t_lakesno(lbl)
+ ELSE
+ tlake = t_lake(1)
+ ENDIF
+
+ ! ----------------------------------------
+ ! energy balance check
+ ! ----------------------------------------
+ zerr=errore
+#if (defined CoLMDEBUG)
+ IF(abs(errore)>.5)THEN
+ write(6,*) 'Warning: energy balance violation ',errore,patchclass
+ ENDIF
+#endif
+
+ ! ----------------------------------------
+ ! water balance check
+ ! ----------------------------------------
+
+ wliq_soisno(: ) = 0.
+ wliq_soisno(:1) = wliq_roofsno(:1)*froof
+ wliq_soisno(: ) = wliq_soisno(: ) + wliq_gpersno(: )*(1-froof)*fgper
+ wliq_soisno(:1) = wliq_soisno(:1) + wliq_gimpsno(:1)*(1-froof)*(1-fgper)
+ !wliq_soisno(:) = wliq_soisno(:)*(1-flake) + wliq_lakesno(:)*flake
+
+ wice_soisno(: ) = 0.
+ wice_soisno(:1) = wice_roofsno(:1)*froof
+ wice_soisno(: ) = wice_soisno(: ) + wice_gpersno(: )*(1-froof)*fgper
+ wice_soisno(:1) = wice_soisno(:1) + wice_gimpsno(:1)*(1-froof)*(1-fgper)
+ !wice_soisno(:) = wice_soisno(:)*(1-flake) + wice_lakesno(:)*flake
+
+ scv = scv_roof*froof + scv_gper*(1-froof)*fgper + scv_gimp*(1-froof)*(1-fgper)
+ !scv = scv*(1-flake) + scv_lake*flake
+
+ endwb = sum(wice_soisno(1:) + wliq_soisno(1:))
+ endwb = endwb + scv + ldew*fveg + wa*(1-froof)*fgper
+ errorw = (endwb - totwb) - (forc_prc + forc_prl + urb_irrig - fevpa - rnof)*deltim
+ xerr = errorw/deltim
+
+#if (defined CoLMDEBUG)
+ IF(abs(errorw)>1.e-3) THEN
+ write(6,*) 'Warning: water balance violation', errorw, ipatch, patchclass
+ !STOP
+ ENDIF
+#endif
+
+!======================================================================
+! Preparation for the next time step
+! 1) time-varying parameters for vegetation
+! 2) fraction of snow cover
+! 3) solar zenith angle and
+! 4) albedos
+!======================================================================
+
+ ! cosine of solar zenith angle
+ calday = calendarday(idate)
+ coszen = orb_coszen(calday,patchlonr,patchlatr)
+
+ ! fraction of snow cover.
+ CALL snowfraction ( 0., 0.,z0m,zlnd,scv_lake,snowdp_lake,wt,sigf,fsno_lake)
+ CALL snowfraction ( 0., 0.,z0m,zlnd,scv_roof,snowdp_roof,wt,sigf,fsno_roof)
+ CALL snowfraction ( 0., 0.,z0m,zlnd,scv_gimp,snowdp_gimp,wt,sigf,fsno_gimp)
+ CALL snowfraction (lai,sai,z0m,zlnd,scv_gper,snowdp_gper,wt,sigf,fsno_gper)
+ lai = tlai(ipatch)
+ sai = tsai(ipatch) * sigf
+
+ ! update the snow age
+ !TODO: can be moved to UrbanALBEDO.F90
+ IF (snlr == 0) sag_roof = 0.
+ CALL snowage (deltim,troof,scv_roof,scvold_roof,sag_roof)
+ IF (snli == 0) sag_gimp = 0.
+ CALL snowage (deltim,tgimp,scv_gimp,scvold_gimp,sag_gimp)
+ IF (snlp == 0) sag_gper = 0.
+ CALL snowage (deltim,tgper,scv_gper,scvold_gper,sag_gper)
+ IF (snll == 0) sag_lake = 0.
+ CALL snowage (deltim,tlake,scv_lake,scvold_lake,sag_lake)
+
+ ! update snow depth, snow cover and snow age
+ snowdp = snowdp_roof*froof + snowdp_gper*(1-froof)*fgper + snowdp_gimp*(1-froof)*(1-fgper)
+ fsno = fsno_roof*froof + fsno_gper*(1-froof)*fgper + fsno_gimp*(1-froof)*(1-fgper)
+ sag = sag_roof*froof + sag_gper*(1-froof)*fgper + sag_gimp*(1-froof)*(1-fgper)
+
+ ! albedos
+ ! we supposed call it every time-step, because
+ ! other vegetation related parameters are needed to create
+
+ CALL alburban (ipatch,froof,fgper,flake,hlr,hroof,&
+ alb_roof,alb_wall,alb_gimp,alb_gper,&
+ rho,tau,fveg,(htop+hbot)/2.,lai,sai,fwet_snow,coszen,fwsun,tlake,&
+ fsno_roof,fsno_gimp,fsno_gper,fsno_lake,&
+ scv_roof,scv_gimp,scv_gper,scv_lake,&
+ sag_roof,sag_gimp,sag_gper,sag_lake,&
+ dfwsun,extkd,alb,ssun,ssha,sroof,swsun,swsha,sgimp,sgper,slake)
+
+ ! zero-filling set for glacier/ice-sheet/land water bodies/ocean components
+ laisun = lai
+ laisha = 0.0
+ green = 1.
+
+ h2osoi = wliq_soisno(1:)/(dz_soi(1:)*denh2o) + wice_soisno(1:)/(dz_soi(1:)*denice)
+ wat = sum(wice_soisno(1:)+wliq_soisno(1:))
+ wat = wat + scv + ldew*fveg + wa*(1-froof)*fgper
+
+ z_sno_roof (maxsnl+1:0) = z_roofsno (maxsnl+1:0)
+ z_sno_gimp (maxsnl+1:0) = z_gimpsno (maxsnl+1:0)
+ z_sno_gper (maxsnl+1:0) = z_gpersno (maxsnl+1:0)
+ z_sno_lake (maxsnl+1:0) = z_lakesno (maxsnl+1:0)
+
+ dz_sno_roof(maxsnl+1:0) = dz_roofsno(maxsnl+1:0)
+ dz_sno_gimp(maxsnl+1:0) = dz_gimpsno(maxsnl+1:0)
+ dz_sno_gper(maxsnl+1:0) = dz_gpersno(maxsnl+1:0)
+ dz_sno_lake(maxsnl+1:0) = dz_lakesno(maxsnl+1:0)
+
+ z_sno(:) = z_sno_roof(:)*froof
+ z_sno(:) = z_sno(:) + z_sno_gper(:)*(1-froof)*fgper
+ z_sno(:) = z_sno(:) + z_sno_gimp(:)*(1-froof)*(1-fgper)
+ z_sno(:) = z_sno(:)*(1-flake) + z_sno_lake(:)*flake
+
+ dz_sno(:) = dz_sno_roof(:)*froof
+ dz_sno(:) = dz_sno(:) + dz_sno_gper(:)*(1-froof)*fgper
+ dz_sno(:) = dz_sno(:) + dz_sno_gimp(:)*(1-froof)*(1-fgper)
+ dz_sno(:) = dz_sno(:)*(1-flake) + dz_sno_lake(:)*flake
+
+! diagnostic diurnal temperature
+ !IF (tref > tmax) tmax = tref
+ !IF (tref < tmin) tmin = tref
+
+! 06/05/2022, yuan: RH for output to compare
+ CALL qsadv(tref,forc_psrf,ei,deiDT,qsatl,qsatlDT)
+ qref = qref/qsatl
+
+END SUBROUTINE CoLMMAIN_Urban
+! ----------------------------------------------------------------------
+! EOP
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Albedo.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Albedo.F90
new file mode 100644
index 0000000000..07d568478e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Albedo.F90
@@ -0,0 +1,371 @@
+#include
+
+MODULE MOD_Urban_Albedo
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Calculate the total urban albedo. Prepare albedo values over water,
+! roof, ground with snow cover. Then CALL 3D urban radiation transfer
+! model. Finally calculate the total albedo weighted by the urban and
+! water fractional cover.
+!
+! Created by Hua Yuan, 09/2021
+!
+!
+! !REVISIONS:
+!
+! 07/2023, Hua Yuan: Fix low zenith angle problem for urban radiation
+! calculation and urban display height problem when
+! considering vegetations. modify limitation for conzen value
+! (0.001->0.01) for urban.
+!
+! 05/2024, Hua Yuan: Account for vegetation snow optical properties.
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: alburban
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE alburban (ipatch,froof,fgper,flake,hlr,hroof,&
+ alb_roof,alb_wall,alb_gimp,alb_gper,&
+ rho,tau,fveg,hveg,lai,sai,fwet_snow,coszen,fwsun,tlake,&
+ fsno_roof,fsno_gimp,fsno_gper,fsno_lake,&
+ scv_roof,scv_gimp,scv_gper,scv_lake,&
+ sag_roof,sag_gimp,sag_gper,sag_lake,&
+ dfwsun,extkd,alb,ssun,ssha,sroof,swsun,swsha,sgimp,sgper,slake)
+
+!=======================================================================
+! Calculates fragmented albedos (direct and diffuse) for urban area in
+! wavelength regions split at 0.7um.
+!
+! (1) snow albedos: as in BATS formulations, which are inferred from
+! the calculations of Wiscombe and Warren (1980) and the snow model
+! and data of Anderson(1976), and the function of snow age, grain
+! size, solar zenith angle, pollution, the amount of the fresh snow
+! (2) lake and wetland albedos: as in BATS, which depend on cosine solar
+! zenith angle, based on data in Henderson-Sellers (1986). The
+! frozen lake and wetland albedos are set to constants (0.6 for
+! visible beam, 0.4 for near-infrared)
+! (3) over the snow covered surface, the surface albedo is estimated by
+! a linear combination of albedos for snow, roof, impervious and
+! pervious ground
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: tfrz
+ USE MOD_Namelist, only: DEF_VEG_SNOW
+ USE MOD_Urban_Shortwave
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+! ground cover index
+ integer, intent(in) :: &
+ ipatch ! patch index
+
+ real(r8), intent(in) :: &
+ froof, &! roof fraction
+ fgper, &! impervious ground weight fraction
+ flake, &! lake fraction
+ hlr, &! average building height to their side length
+ hroof ! average building height
+
+ real(r8), intent(in) :: &
+ alb_roof(2,2), &! roof albedo (iband,direct/diffuse)
+ alb_wall(2,2), &! wall albedo (iband,direct/diffuse)
+ alb_gimp(2,2), &! impervious albedo (iband,direct/diffuse)
+ alb_gper(2,2) ! pervious albedo (iband,direct/diffuse)
+
+ real(r8), intent(in) :: &
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2), &! leaf transmittance (iw=iband, il=life and dead)
+ fveg, &! fractional vegetation cover [-]
+ hveg, &! vegetation central crown height [m]
+ lai, &! leaf area index (LAI+SAI) [m2/m2]
+ sai, &! stem area index (LAI+SAI) [m2/m2]
+ fwet_snow, &! vegetation snow fractional cover [-]
+
+ ! variables
+ coszen, &! cosine of solar zenith angle [-]
+ fwsun, &! sunlit wall fraction [-]
+ tlake, &! lake surface temperature [K]
+ fsno_roof, &! fraction of soil covered by snow [-]
+ fsno_gimp, &! fraction of soil covered by snow [-]
+ fsno_gper, &! fraction of soil covered by snow [-]
+ fsno_lake, &! fraction of soil covered by snow [-]
+ scv_roof, &! snow cover, water equivalent [mm]
+ scv_gimp, &! snow cover, water equivalent [mm]
+ scv_gper, &! snow cover, water equivalent [mm]
+ scv_lake, &! snow cover, water equivalent [mm]
+ sag_roof, &! non dimensional snow age [-]
+ sag_gimp, &! non dimensional snow age [-]
+ sag_gper, &! non dimensional snow age [-]
+ sag_lake ! non dimensional snow age [-]
+
+ real(r8), intent(out) :: &
+ dfwsun, &! change of fwsun
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ alb (2,2), &! averaged albedo [-]
+ ssun (2,2), &! sunlit canopy absorption for solar radiation
+ ssha (2,2), &! shaded canopy absorption for solar radiation,
+ sroof(2,2), &! roof absorption for solar radiation,
+ swsun(2,2), &! sunlit wall absorption for solar radiation,
+ swsha(2,2), &! shaded wall absorption for solar radiation,
+ sgimp(2,2), &! impervious ground absorption for solar radiation,
+ sgper(2,2), &! pervious ground absorption for solar radiation,
+ slake(2,2) ! lake absorption for solar radiation,
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ age, &! factor to reduce visible snow alb due to snow age [-]
+ albg0, &! temporary varaiable [-]
+ alb_s_inc, &! decrease in soil albedo due to wetness [-]
+ beta0, &! upscattering parameter for direct beam [-]
+ cff, &! snow alb correction factor for zenith angle > 60 [-]
+ conn, &! constant (=0.5) for visible snow alb calculation [-]
+ cons, &! constant (=0.2) for nir snow albedo calculation [-]
+ czen, &! cosine of solar zenith angle > 0 [-]
+ theta, &! solar zenith angle
+ fwsun_, &! sunlit wall fraction
+ czf, &! solar zenith correction for new snow albedo [-]
+ dfalbl, &! snow albedo for diffuse nir radiation [-]
+ dfalbs, &! snow albedo for diffuse visible solar radiation [-]
+ dralbl, &! snow albedo for visible radiation [-]
+ dralbs, &! snow albedo for near infrared radiation [-]
+ sl, &! factor that helps control alb zenith dependence [-]
+ snal0, &! alb for visible,incident on new snow (zen ang<60) [-]
+ snal1 ! alb for NIR, incident on new snow (zen angle<60) [-]
+
+ real(r8) :: &
+ erho(2), &! effective reflection of leaf+stem
+ etau(2), &! effective transmittance of leaf+stem
+ albsno (2,2), &! snow albedo [-]
+ albroof(2,2), &! albedo, ground
+ albgimp(2,2), &! albedo, ground
+ albgper(2,2), &! albedo, ground
+ alblake(2,2) ! albedo, ground
+
+ ! vegetation snow optical properties, 1:vis, 2:nir
+ real(r8) :: rho_sno(2), tau_sno(2)
+ data rho_sno(1), rho_sno(2) /0.5, 0.2/
+ data tau_sno(1), tau_sno(2) /0.3, 0.2/
+
+! ----------------------------------------------------------------------
+! 1. Initial set
+! ----------------------------------------------------------------------
+
+! short and long wave albedo for new snow
+ snal0 = 0.85 ! shortwave
+ snal1 = 0.65 ! long wave
+
+! ----------------------------------------------------------------------
+! set default soil and vegetation albedos and solar absorption
+ alb (:,:) = 1. ! averaged
+ ssun (:,:) = 0.
+ ssha (:,:) = 0.
+ sroof (:,:) = 0.
+ swsun (:,:) = 0.
+ swsha (:,:) = 0.
+ sgimp (:,:) = 0.
+ sgper (:,:) = 0.
+ alblake (:,:) = 1.
+ slake (:,:) = 0.
+
+ dfwsun = 0.
+ extkd = 0.718
+
+ IF(coszen <= -0.3) THEN
+ !print *, "coszen < 0, ipatch and coszen: ", ipatch, coszen
+ RETURN !only do albedo when coszen > -0.3
+ ENDIF
+
+ czen = max(coszen, 0.01)
+ albsno(:,:) = 0. !set initial snow albedo
+ cons = 0.2 !parameter for snow albedo
+ conn = 0.5 !parameter for snow albedo
+ sl = 2.0 !sl helps control albedo zenith dependence
+
+ ! effective leaf optical properties: rho and tau.
+ IF (lai+sai>1.e-6 .and. fveg>0.) THEN
+ erho(:) = rho(:,1)*lai/(lai+sai) + rho(:,2)*sai/(lai+sai)
+ etau(:) = tau(:,1)*lai/(lai+sai) + tau(:,2)*sai/(lai+sai)
+ ENDIF
+
+ ! correct for snow on leaf
+ IF ( DEF_VEG_SNOW ) THEN
+ ! modify rho, tau, USE: fwet_snow
+ erho(:) = (1-fwet_snow)*erho(:) + fwet_snow*rho_sno(:)
+ etau(:) = (1-fwet_snow)*etau(:) + fwet_snow*tau_sno(:)
+ ENDIF
+
+! ----------------------------------------------------------------------
+! 2. get albedo over water, roof, ground
+! ----------------------------------------------------------------------
+
+! 2.1 albedo for inland water (NOTE: wetland is removed)
+ albg0 = 0.05/(czen+0.15)
+ alblake(:,1) = albg0
+ alblake(:,2) = 0.1 !Subin (2012)
+
+ IF (tlake < tfrz) THEN !frozen lake and wetland
+ alblake(1,:) = 0.6
+ alblake(2,:) = 0.4
+ ENDIF
+
+ IF (scv_lake > 0.) THEN
+
+ ! correction for snow age
+ age = 1.-1./(1.+sag_lake) !correction for snow age
+ dfalbs = snal0*(1.-cons*age)
+
+ ! czf corrects albedo of new snow for solar zenith
+ cff = ((1.+1./sl)/(1.+czen*2.*sl )- 1./sl)
+ cff = max(cff,0.)
+ czf = 0.4*cff*(1.-dfalbs)
+ dralbs = dfalbs+czf
+ dfalbl = snal1*(1.-conn*age)
+ czf = 0.4*cff*(1.-dfalbl)
+ dralbl = dfalbl+czf
+
+ albsno(1,1) = dralbs
+ albsno(2,1) = dralbl
+ albsno(1,2) = dfalbs
+ albsno(2,2) = dfalbl
+
+ ENDIF
+
+ alblake(:,:) = (1.-fsno_lake)*alblake(:,:) + fsno_lake*albsno(:,:)
+ slake(:,:) = 1. - alblake(:,:)
+
+! 2.2 roof albedo with snow
+ IF (scv_roof > 0.) THEN
+
+ ! correction for snow age
+ age = 1.-1./(1.+sag_roof) !correction for snow age
+ dfalbs = snal0*(1.-cons*age)
+
+ ! czf corrects albedo of new snow for solar zenith
+ cff = ((1.+1./sl)/(1.+czen*2.*sl )- 1./sl)
+ cff = max(cff,0.)
+ czf = 0.4*cff*(1.-dfalbs)
+ dralbs = dfalbs+czf
+ dfalbl = snal1*(1.-conn*age)
+ czf = 0.4*cff*(1.-dfalbl)
+ dralbl = dfalbl+czf
+
+ albsno(1,1) = dralbs
+ albsno(2,1) = dralbl
+ albsno(1,2) = dfalbs
+ albsno(2,2) = dfalbl
+
+ ENDIF
+
+ albroof(:,:) = (1.-fsno_roof)*alb_roof(:,:) + fsno_roof*albsno(:,:)
+
+! 2.3 impervious ground albedo with snow
+ IF (scv_gimp > 0.) THEN
+
+ ! correction for snow age
+ age = 1.-1./(1.+sag_gimp) !correction for snow age
+ dfalbs = snal0*(1.-cons*age)
+
+ ! czf corrects albedo of new snow for solar zenith
+ cff = ((1.+1./sl)/(1.+czen*2.*sl )- 1./sl)
+ cff = max(cff,0.)
+ czf = 0.4*cff*(1.-dfalbs)
+ dralbs = dfalbs+czf
+ dfalbl = snal1*(1.-conn*age)
+ czf = 0.4*cff*(1.-dfalbl)
+ dralbl = dfalbl+czf
+
+ albsno(1,1) = dralbs
+ albsno(2,1) = dralbl
+ albsno(1,2) = dfalbs
+ albsno(2,2) = dfalbl
+
+ ENDIF
+
+ albgimp(:,:) = (1.-fsno_gimp)*alb_gimp(:,:) + fsno_gimp*albsno(:,:)
+
+! 2.4 pervious ground albedo with snow
+ IF (scv_gper > 0.) THEN
+
+ ! correction for snow age
+ age = 1.-1./(1.+sag_gper) !correction for snow age
+ dfalbs = snal0*(1.-cons*age)
+
+ ! czf corrects albedo of new snow for solar zenith
+ cff = ((1.+1./sl)/(1.+czen*2.*sl )- 1./sl)
+ cff = max(cff,0.)
+ czf = 0.4*cff*(1.-dfalbs)
+ dralbs = dfalbs+czf
+ dfalbl = snal1*(1.-conn*age)
+ czf = 0.4*cff*(1.-dfalbl)
+ dralbl = dfalbl+czf
+
+ albsno(1,1) = dralbs
+ albsno(2,1) = dralbl
+ albsno(1,2) = dfalbs
+ albsno(2,2) = dfalbl
+
+ ENDIF
+
+ albgper(:,:) = (1.-fsno_gper)*alb_gper(:,:) + fsno_gper*albsno(:,:)
+
+! ----------------------------------------------------------------------
+! 3. Urban albedo
+! ----------------------------------------------------------------------
+
+ theta = acos(czen)
+
+ ! Distinguish between no-vegetation and vegetation-included cases
+ IF (lai+sai>1.e-6 .and. fveg>0.) THEN
+
+ CALL UrbanVegShortwave ( &
+ theta, hlr, froof, fgper, hroof, &
+ albroof(1,1), alb_wall(1,1), albgimp(1,1), albgper(1,1), &
+ lai, sai, fveg, hveg, erho(1), etau(1), &
+ fwsun_, sroof(1,:), swsun(1,:), swsha(1,:), sgimp(1,:), &
+ sgper(1,:), ssun(1,:), alb(1,:))
+
+ CALL UrbanVegShortwave ( &
+ theta, hlr, froof, fgper, hroof, &
+ albroof(2,1), alb_wall(2,1), albgimp(2,1), albgper(2,1), &
+ lai, sai, fveg, hveg, erho(2), etau(2), &
+ fwsun_, sroof(2,:), swsun(2,:), swsha(2,:), sgimp(2,:), &
+ sgper(2,:), ssun(2,:), alb(2,:))
+ ELSE
+
+ CALL UrbanOnlyShortwave ( &
+ theta, hlr, froof, fgper, hroof, &
+ albroof(1,1), alb_wall(1,1), albgimp(1,1), albgper(1,1), &
+ fwsun_, sroof(1,:), swsun(1,:), swsha(1,:), sgimp(1,:), &
+ sgper(1,:), alb(1,:))
+
+ CALL UrbanOnlyShortwave ( &
+ theta, hlr, froof, fgper, hroof, &
+ albroof(2,1), alb_wall(2,1), albgimp(2,1), albgper(2,1), &
+ fwsun_, sroof(2,:), swsun(2,:), swsha(2,:), sgimp(2,:), &
+ sgper(2,:), alb(2,:))
+
+ ssun(:,:) = 0.
+ ENDIF
+
+ dfwsun = fwsun_ - fwsun
+
+ alb(:,:) = (1.-flake)*alb(:,:) + flake*alblake(:,:)
+
+ END SUBROUTINE alburban
+
+END MODULE MOD_Urban_Albedo
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_BEM.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_BEM.F90
new file mode 100644
index 0000000000..7b817c1bfa
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_BEM.F90
@@ -0,0 +1,256 @@
+#include
+
+MODULE MOD_Urban_BEM
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical
+ USE MOD_Urban_Shortwave, only: MatrixInverse
+
+ IMPLICIT NONE
+ SAVE
+ PRIVATE
+
+ ! A simple building energy model to calculate room temperature
+ PUBLIC :: SimpleBEM
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+ SUBROUTINE SimpleBEM (deltim, rhoair, fcover, H, troom_max, troom_min, &
+ troof_nl_bef, twsun_nl_bef, twsha_nl_bef, &
+ troof_nl, twsun_nl, twsha_nl, &
+ tkdz_roof, tkdz_wsun, tkdz_wsha, taf, &
+ troom, troof_inner, twsun_inner, twsha_inner, &
+ Fhac, Fwst, Fach, Fhah)
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! A simple building energy model to calculate room temperature
+!
+! The basic approach is as follows:
+!
+! 1. Predict indoor temperature using the indoor energy balance
+! equations (see below) without turning on the air conditioning.
+!
+! 2. If the indoor temperature falls within the predefined comfort
+! range, further energy consumption calculations are not necessary,
+! only indoor and outdoor heat exchange is considered.
+!
+! 3. If the indoor temperature falls outside the predefined comfort
+! range, calculate the minimum/maximum heating/cooling capacity
+! based on the air conditioning usage strategy.
+!
+! 4. Calculate the indoor and outdoor heat exchange and waste heat
+! discharge (taking into account energy utilization efficiency)
+! based on the calculated heating/cooling capacity in step 3.
+!
+! Finally, energy consumption can be calculated based on the total
+! heat flux.
+!
+! o Solve the following energy balance equations
+! o Variables: troom, troof_inner, twsun_inner, twsha_innter
+!
+! Hc_roof = Fn_roof .................................(1)
+! Hc_wsun = Fn_wsun .................................(2)
+! Hc_wsha = Fn_wsha .................................(3)
+!
+! Troom' - Troom
+! H*rhoair*cpair*-------------- =
+! dt
+! ACH
+! ------*H*rhoair*cpair*(Taf-Troom') + Hc_roof + Hc_wsun + Hc_wsha
+! 3600
+! .................................(4)
+!
+! Created by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+!
+! 11/2022, Hua Yuan: Add option for constant AC.
+!
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ deltim, &! seconds in a time step [second]
+ rhoair, &! density air [kg/m3]
+ fcover(0:2), &! fractional cover of roof, wall
+ H, &! average building height [m]
+ troom_max, &! maximum temperature of inner building
+ troom_min, &! minimum temperature of inner building
+ troof_nl_bef, &! roof temperature at layer nl_roof
+ twsun_nl_bef, &! sunlit wall temperature at layer nl_wall
+ twsha_nl_bef, &! shaded wall temperature at layer nl_wall
+ troof_nl, &! roof temperature at layer nl_roof
+ twsun_nl, &! sunlit wall temperature at layer nl_wall
+ twsha_nl, &! shaded wall temperature at layer nl_wall
+ tkdz_roof, &! temporal var for heat transfer of roof
+ tkdz_wsun, &! temporal var for heat transfer of sunlit wall
+ tkdz_wsha, &! temporal var for heat transfer of shaded wall
+ taf ! temperature of urban air
+
+ real(r8), intent(inout) :: &
+ troom, &! temperature of inner building
+ troof_inner, &! temperature of inner roof
+ twsun_inner, &! temperature of inner sunlit wall
+ twsha_inner ! temperature of inner shaded wall
+
+ real(r8), intent(out) :: &
+ Fhah, &! flux from heating
+ Fhac, &! flux from heat or cool AC
+ Fwst, &! waste heat from cool or heat
+ Fach ! flux from air exchange
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ ACH, &! air exchange coefficient
+ hcv_roof, &! convective exchange coefficient for roof<->room
+ hcv_wall, &! convective exchange coefficient for wall<->room
+ waste_coef, &! waste coefficient
+ waste_cool, &! waste heat for AC cooling
+ waste_heat ! waste heat for AC heating
+
+ real(r8) :: &
+ f_wsun, &! weight factor for sunlit wall
+ f_wsha ! weight factor for shaded wall
+
+ real(r8) :: &
+ A(4,4), &! Heat transfer matrix
+ Ainv(4,4), &! Inverse of Heat transfer matrix
+ B(4), &! B for Ax=B
+ X(4) ! x for Ax=B
+
+ real(r8) :: &
+ troom_pro, &! projected room temperature
+ troom_bef, &! temperature of inner building
+ troof_inner_bef, &! temperature of inner roof
+ twsun_inner_bef, &! temperature of inner sunlit wall
+ twsha_inner_bef ! temperature of inner shaded wall
+
+ logical :: cooling, heating
+
+ ! Option for continuous AC
+ logical, parameter :: Constant_AC = .true.
+
+!-----------------------------------------------------------------------
+
+ ACH = 0.3 !air exchange coefficient
+ hcv_roof = 4.040 !convective exchange coefficient for roof<->room (W m-2 K-1)
+ hcv_wall = 3.076 !convective exchange coefficient for wall<->room (W m-2 K-1)
+ waste_cool = 0.6 !waste heat for AC cooling
+ waste_heat = 0.2 !waste heat for AC heating
+ cooling = .false. !cooling case
+ heating = .false. !heating case
+
+ f_wsun = fcover(1)/fcover(0) !weight factor for sunlit wall
+ f_wsha = fcover(2)/fcover(0) !weight factor for shaded wall
+
+ ! initialization
+ Fhac = 0.; Fwst = 0.; Fach = 0.; Fhah = 0.;
+
+ ! Ax = B
+ ! set values for heat transfer matrix
+ ! 1: roof, 2: sunlit wall, 3: shaded wall, 4: room
+ A(:,:) = 0.
+ A(1,:) = (/0.5*hcv_roof+0.5*tkdz_roof, 0., 0., -0.5*hcv_roof/)
+ A(2,:) = (/0., 0.5*hcv_wall+0.5*tkdz_wsun, 0., -0.5*hcv_wall/)
+ A(3,:) = (/0., 0., 0.5*hcv_wall+0.5*tkdz_wsha, -0.5*hcv_wall/)
+
+ A(4,:) = (/-0.5*hcv_roof, -0.5*hcv_wall*f_wsun, -0.5*hcv_wall*f_wsha, &
+ 0.5*hcv_roof + 0.5*hcv_wall*f_wsun + 0.5*hcv_wall*f_wsha +&
+ H*rhoair*cpair/deltim + (ACH/3600.)*H*rhoair*cpair /)
+
+ B(1) = -0.5*hcv_roof*(troof_inner-troom) + 0.5*tkdz_roof*(troof_nl_bef-troof_inner) &
+ + 0.5*tkdz_roof*troof_nl
+ B(2) = -0.5*hcv_wall*(twsun_inner-troom) + 0.5*tkdz_wsun*(twsun_nl_bef-twsun_inner) &
+ + 0.5*tkdz_wsun*twsun_nl
+ B(3) = -0.5*hcv_wall*(twsha_inner-troom) + 0.5*tkdz_wsha*(twsha_nl_bef-twsha_inner) &
+ + 0.5*tkdz_wsha*twsha_nl
+
+ B(4) = H*rhoair*cpair*troom/deltim + (ACH/3600.)*H*rhoair*cpair*taf &
+ + 0.5*hcv_roof*(troof_inner-troom) &
+ + 0.5*hcv_wall*(twsun_inner-troom)*f_wsun &
+ + 0.5*hcv_wall*(twsha_inner-troom)*f_wsha
+
+ ! Inverse of matrix A
+ Ainv = MatrixInverse(A)
+
+ ! Matrix computing to resolve multiple reflections
+ X = matmul(Ainv, B)
+
+ troof_inner_bef = troof_inner
+ twsun_inner_bef = twsun_inner
+ twsha_inner_bef = twsha_inner
+ troom_bef = troom
+
+ troof_inner = X(1)
+ twsun_inner = X(2)
+ twsha_inner = X(3)
+ troom = X(4)
+ troom_pro = X(4)
+
+ Fach = (ACH/3600.)*H*rhoair*cpair*(troom - taf)
+
+ IF (troom > troom_max) THEN !cooling case
+ Fhac = H*rhoair*cpair*(troom-troom_max)/deltim
+ troom = troom_max
+ Fwst = Fhac*waste_cool
+ ENDIF
+
+ IF (troom < troom_min) THEN !heating case
+ Fhac = H*rhoair*cpair*(troom-troom_min)/deltim
+ troom = troom_min
+ Fwst = abs(Fhac)*waste_heat
+ ! negative value, set it to 0.
+ Fhac = 0.
+ ENDIF
+
+ ! for constant cooling or heating
+ IF ((troom_pro>troom_max .or. troom_pro troom_max) THEN !cooling case
+ troom = troom_max
+ waste_coef = waste_cool
+ cooling = .true.
+ ENDIF
+
+ IF (troom_pro < troom_min) THEN !heating case
+ troom = troom_min
+ waste_coef = waste_heat
+ heating = .true.
+ ENDIF
+
+ Fach = (ACH/3600.)*H*rhoair*cpair*(troom - taf)
+
+ troof_inner = (B(1)-A(1,4)*troom)/A(1,1)
+ twsun_inner = (B(2)-A(2,4)*troom)/A(2,2)
+ twsha_inner = (B(3)-A(3,4)*troom)/A(3,3)
+
+ Fhac = 0.5*hcv_roof*(troof_inner_bef-troom_bef) &
+ + 0.5*hcv_roof*(troof_inner-troom)
+ Fhac = 0.5*hcv_wall*(twsun_inner_bef-troom_bef)*f_wsun &
+ + 0.5*hcv_wall*(twsun_inner-troom)*f_wsun + Fhac
+ Fhac = 0.5*hcv_wall*(twsha_inner_bef-troom_bef)*f_wsha &
+ + 0.5*hcv_wall*(twsha_inner-troom)*f_wsha + Fhac
+
+ IF ( heating ) Fhah = abs(Fhac)
+ Fhac = abs(Fhac) + abs(Fach)
+ Fwst = Fhac*waste_coef
+ IF ( heating ) Fhac = 0.
+
+ ENDIF
+
+ Fhah = Fhah*fcover(0)
+ Fach = Fach*fcover(0)
+ Fwst = Fwst*fcover(0)
+ Fhac = Fhac*fcover(0)
+
+ END SUBROUTINE SimpleBEM
+
+END MODULE MOD_Urban_BEM
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Const_LCZ.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Const_LCZ.F90
new file mode 100644
index 0000000000..0504664be4
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Const_LCZ.F90
@@ -0,0 +1,125 @@
+#include
+MODULE MOD_Urban_Const_LCZ
+
+! -----------------------------------------------------------------------
+! !DESCRIPTION:
+! look-up-table for LCZ morphology and thermal parameters
+! - NOTE -
+! Each city may have different values for the parameters in this table.
+! The default values may not suit any specific city.
+! Users could adjust these values based on the city they are working with.
+!
+! Created by Wenzong Dong, Jun, 2022
+!
+! !REFERENCES:
+! 1) Stewart, I. D., Oke, T. R., & Krayenhoff, E. S. (2014). Evaluation of
+! the 'local climate zone' scheme using temperature observations and model
+! simulations. International Journal of Climatology, 34(4), 1062-1080.
+! https://doi.org/10.1002/joc.3746
+!
+! 2) The URBPARM_LCZ.TBL of WRF, https://github.com/wrf-model/WRF/
+!
+! -----------------------------------------------------------------------
+! !USE
+ USE MOD_Precision
+
+ IMPLICIT NONE
+ SAVE
+
+ ! roof fraction [-]
+ real(r8), parameter, dimension(10) :: wtroof_lcz &
+ = (/0.5 , 0.5 , 0.55, 0.3 , 0.3, 0.3, 0.8 , 0.4 , 0.15, 0.25/)
+
+ ! pervious fraction [-]
+ real(r8), parameter, dimension(10) :: fgper_lcz &
+ = (/0.05, 0.1 , 0.15, 0.35, 0.3, 0.4, 0.15, 0.15, 0.7 , 0.45/)
+
+ ! height of roof [m]
+ real(r8), parameter, dimension(10) :: htroof_lcz &
+ = (/45., 15. , 5. , 40., 15., 5. , 3. , 7. , 5. , 8.5 /)
+
+ ! H/W [-]
+ real(r8), parameter, dimension(10) :: hwrbld_lcz &
+ = (/2.5, 1.25, 1.25, 1. , 0.5, 0.5, 1.5, 0.2, 0.15, 0.35/)
+
+ ! thickness of roof [m]
+ real(r8), parameter, dimension(10) :: thkroof_lcz &
+ = (/0.3 , 0.3 , 0.2 , 0.3 , 0.25, 0.15, 0.05, 0.12, 0.15, 0.05/)
+
+ ! thickness of wall [m]
+ real(r8), parameter, dimension(10) :: thkwall_lcz &
+ = (/0.3 , 0.25, 0.2 , 0.2 , 0.2 , 0.2 , 0.1 , 0.2 , 0.2 , 0.05/)
+
+ ! thickness of impervious road [m]
+ real(r8), parameter, dimension(10) :: thkgimp_lcz &
+ = (/0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25/)
+
+ ! albedo of roof [-]
+ real(r8), parameter, dimension(10) :: albroof_lcz &
+ = (/0.13, 0.18, 0.15, 0.13, 0.13, 0.13, 0.15, 0.18, 0.13, 0.1 /)
+
+ ! albedo of wall [-]
+ real(r8), parameter, dimension(10) :: albwall_lcz &
+ = (/0.25, 0.2 , 0.2 , 0.25, 0.25, 0.25, 0.2 , 0.25, 0.25, 0.2 /)
+
+ ! albedo of impervious road [-]
+ real(r8), parameter, dimension(10) :: albgimp_lcz &
+ = (/0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.18, 0.14, 0.14, 0.14/)
+
+ ! albedo of pervious road [-]
+ real(r8), parameter, dimension(10) :: albgper_lcz &
+ = (/0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15, 0.15/)
+
+ ! emissivity of roof [-]
+ real(r8), parameter, dimension(10) :: emroof_lcz &
+ = (/0.91, 0.91, 0.91, 0.91, 0.91, 0.91, 0.28, 0.91, 0.91, 0.91/)
+
+ ! emissivity of wall [-]
+ real(r8), parameter, dimension(10) :: emwall_lcz &
+ = (/0.90, 0.90, 0.90, 0.90, 0.90, 0.90, 0.90, 0.90, 0.90, 0.90/)
+
+ ! emissivity of road [-]
+ real(r8), parameter, dimension(10) :: emgimp_lcz &
+ = (/0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.92, 0.95, 0.95, 0.95/)
+
+ ! emissivity of impervious road [-]
+ real(r8), parameter, dimension(10) :: emgper_lcz &
+ = (/0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95, 0.95/)
+
+
+ ! volumetric heat capacity of roof [J/m3*K]
+ real(r8), parameter, dimension(10) :: cvroof_lcz &
+ = (/1.8E6 , 1.8E6 , 1.44E6, 1.8E6 , 1.8E6 , 1.44E6, 2.0E6 , 1.8E6 , 1.44E6, 2.0E6 /)
+
+ ! volumetric heat capacity of wall [J/m3*K]
+ real(r8), parameter, dimension(10) :: cvwall_lcz &
+ = (/1.8E6 , 2.67E6, 2.05E6, 2.0E6 , 2.0E6 , 2.05E6, 0.72E6, 1.8E6 , 2.56E6, 1.69E6/)
+
+ ! volumetric heat capacity of impervious road [J/m3*K]
+ real(r8), parameter, dimension(10) :: cvgimp_lcz &
+ = (/1.75E6, 1.68E6, 1.63E6, 1.54E6, 1.50E6, 1.47E6, 1.67E6, 1.38E6, 1.37E6, 1.49E6/)
+
+
+ ! thermal conductivity of roof [W/m*K]
+ real(r8), parameter, dimension(10) :: tkroof_lcz &
+ = (/1.25, 1.25, 1.00, 1.25, 1.25, 1.00, 2.0 , 1.25, 1.00, 2.00/)
+
+ ! thermal conductivity of wall [W/m*K]
+ real(r8), parameter, dimension(10) :: tkwall_lcz &
+ = (/1.09, 1.5 , 1.25, 1.45, 1.45, 1.25, 0.5 , 1.25, 1.00, 1.33/)
+
+ ! thermal conductivity of impervious road [W/m*K]
+ real(r8), parameter, dimension(10) :: tkgimp_lcz &
+ = (/0.77, 0.73, 0.69, 0.64, 0.62, 0.60, 0.72, 0.51, 0.55, 0.61/)
+
+ !TODO:AHE coding
+ ! maximum temperature of inner room [K]
+ real(r8), parameter, dimension(10) :: tbldmax_lcz &
+ = (/297.65, 297.65, 297.65, 297.65, 297.65, 297.65, 297.65, 297.65, 297.65, 297.65/)
+
+ ! minimum temperature of inner room [K]
+ real(r8), parameter, dimension(10) :: tbldmin_lcz &
+ = (/290.65, 290.65, 290.65, 290.65, 290.65, 290.65, 290.65, 290.65, 290.65, 290.65/)
+
+END MODULE MOD_Urban_Const_LCZ
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Flux.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Flux.F90
new file mode 100644
index 0000000000..c8e307d36d
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Flux.F90
@@ -0,0 +1,2644 @@
+#include
+
+MODULE MOD_Urban_Flux
+
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! The process of urban turbulence exchange is similar to the plant
+! community (3D canopy) turbulence exchange. The sensible and latent
+! heat exchange of roofs, walls (shaded and sunny sides), ground, and
+! vegetation is calculated based on the M-O similarity theory
+! similarity. However, the differences lie in the roughness, frontal
+! area index, zero-plane displacement height, wind speed/turbulence
+! exchange coefficient decay rate, and calculation of boundary layer
+! resistance for building surfaces and vegetation. Each layer
+! (equivalent height) conservation equation for flux is established and
+! solved simultaneously.
+!
+! The process of solving includes two situations:
+!
+! 1. not considering vegetation - Subroutine UrbanOnlyFlux()
+!
+! 2. considering vegetation - Subroutine UrbanVegFlux()
+!
+! Created by Hua Yuan, 09/2021
+!
+!
+! !REVISIONS:
+!
+! 10/2022, Hua Yuan: Add three options of decay coefficient for u and k.
+! Add wet fraction for roof and impervious ground, set max
+! ponding for roof and impervious from 10mm -> 1mm.
+!
+! 12/2022, Wenzong Dong: Traffic and metabolism heat flux are considered
+! in turbulent flux exchange.
+!
+! 05/2024, Wenzong Dong: re-write the two- and three-layer flux exchange
+! code in resistance style and make it consistant with the
+! technical report. [better for incorporating rss and further
+! developments]
+!
+! 05/2024, Hua Yuan: add option to account for vegetation snow process.
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist, only: DEF_RSS_SCHEME, DEF_VEG_SNOW
+ USE MOD_Vars_Global
+ USE MOD_Qsadv, only: qsadv
+ IMPLICIT NONE
+ SAVE
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: UrbanOnlyFlux
+ PUBLIC :: UrbanVegFlux
+ PUBLIC :: dewfraction
+
+ ! Exponential extinction factor (alpha) options:
+ ! 1. Masson, 2000; Oleson et al., 2008
+ ! 2. Swaid, 1993; Kusaka, 2001; Lee and Park, 2008
+ ! 3. Macdonald, 2000
+ integer, parameter :: alpha_opt = 3
+
+ ! Layer number setting, default is false, i.e., 2 layers
+ logical, parameter :: run_three_layer = .false.
+
+ ! Percent of sensible/latent to AHE (only for Fhac, Fwst, vehc now),
+ ! 92% heat release as SH, 8% heat release as LH, Pigeon et al., 2007
+ real(r8), parameter :: fsh = 0.92
+ real(r8), parameter :: flh = 0.08
+
+ ! A simple urban irrigation scheme accounts for soil water stress of trees
+ logical, parameter :: DEF_URBAN_Irrigation = .true.
+ real(r8), parameter :: rstfac_irrig = 1.
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE UrbanOnlyFlux ( &
+ ! Model running information
+ ipatch ,deltim ,lbr ,lbi ,&
+ ! Forcing
+ hu ,ht ,hq ,us ,&
+ vs ,thm ,th ,thv ,&
+ qm ,psrf ,rhoair ,Fhac ,&
+ Fwst ,Fach ,vehc ,meta ,&
+ ! Urban parameters
+ hroof ,hlr ,nurb ,fcover ,&
+ ! Status of surface
+ z0h_g ,obug ,ustarg ,zlnd ,&
+ zsno ,fsno_roof ,fsno_gimp ,fsno_gper ,&
+ wliq_roofsno ,wliq_gimpsno ,wice_roofsno ,wice_gimpsno ,&
+ htvp_roof ,htvp_gimp ,htvp_gper ,troof ,&
+ twsun ,twsha ,tgimp ,tgper ,&
+ qroof ,qgimp ,qgper ,dqroofdT ,&
+ dqgimpdT ,dqgperdT ,rss ,&
+ ! Output
+ taux ,tauy ,fsenroof ,fsenwsun ,&
+ fsenwsha ,fsengimp ,fsengper ,fevproof ,&
+ fevpgimp ,fevpgper ,croofs ,cwsuns ,&
+ cwshas ,cgrnds ,croofl ,cgimpl ,&
+ cgperl ,croof ,cgimp ,cgper ,&
+ tref ,qref ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,tafu )
+
+!=======================================================================
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpair,vonkar,grav,hvap
+ USE MOD_FrictionVelocity
+ USE MOD_CanopyLayerProfile
+ USE MOD_UserSpecifiedForcing, only: HEIGHT_mode
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch, &! patch index [-]
+ lbr, &! lower bound of array
+ lbi ! lower bound of array
+
+ real(r8), intent(in) :: &
+ deltim ! seconds in a time step [second]
+
+ ! atmospherical variables and observational height
+ real(r8), intent(in) :: &
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht) [K]
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ qm, &! specific humidity at agcm reference height [kg/kg]
+ psrf, &! atmosphere pressure at the surface [pa] [not used]
+ rhoair ! density air [kg/m3]
+
+ real(r8), intent(in) :: &
+ vehc, &! flux from vehicle [W/m2]
+ meta, &! flux from metabolic [W/m2]
+ Fhac, &! flux from heat or cool AC [W/m2]
+ Fwst, &! waste heat from cool or heat [W/m2]
+ Fach ! flux from air exchange [W/m2]
+
+ integer, intent(in) :: &
+ nurb ! number of aboveground urban components [-]
+
+ real(r8), intent(in) :: &
+ hroof, &! average building height [m]
+ hlr, &! average building height to their side length [-]
+ fcover(0:4) ! coverage of aboveground urban components [-]
+
+ real(r8), intent(in) :: &
+ rss, &! bare soil resistance for evaporation [s/m]
+ z0h_g, &! roughness length for bare ground, sensible heat [m]
+ obug, &! monin-obukhov length for bare ground (m)
+ ustarg, &! friction velocity for bare ground [m/s]
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+ fsno_roof, &! fraction of ground covered by snow [-]
+ fsno_gimp, &! fraction of ground covered by snow [-]
+ fsno_gper, &! fraction of ground covered by snow [-]
+ wliq_roofsno, &! liqui water [kg/m2]
+ wliq_gimpsno, &! liqui water [kg/m2]
+ wice_roofsno, &! ice lens [kg/m2]
+ wice_gimpsno, &! ice lens [kg/m2]
+ htvp_roof, &! latent heat of vapor of water (or sublimation) [j/kg]
+ htvp_gimp, &! latent heat of vapor of water (or sublimation) [j/kg]
+ htvp_gper, &! latent heat of vapor of water (or sublimation) [j/kg]
+
+ troof, &! temperature of roof [K]
+ twsun, &! temperature of sunlit wall [K]
+ twsha, &! temperature of shaded wall [K]
+ tgimp, &! temperature of impervious road [K]
+ tgper, &! pervious ground temperature [K]
+
+ qroof, &! roof specific humidity [kg/kg]
+ qgimp, &! imperivous road specific humidity [kg/kg]
+ qgper, &! pervious ground specific humidity [kg/kg]
+ dqroofdT, &! d(qroof)/dT
+ dqgimpdT, &! d(qgimp)/dT
+ dqgperdT ! d(qgper)/dT
+
+ ! Output
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fsenroof, &! sensible heat flux from roof [W/m2]
+ fsenwsun, &! sensible heat flux from sunlit wall [W/m2]
+ fsenwsha, &! sensible heat flux from shaded wall [W/m2]
+ fsengimp, &! sensible heat flux from impervious road [W/m2]
+ fsengper, &! sensible heat flux from pervious ground [W/m2]
+ fevproof, &! evaporation heat flux from roof [W/m2]
+ fevpgimp, &! evaporation heat flux from impervious road [W/m2]
+ fevpgper, &! evaporation heat flux from pervious ground [mm/s]
+
+ croofs, &! deriv of roof sensible heat flux wrt soil temp [w/m**2/k]
+ cwsuns, &! deriv of sunlit wall sensible heat flux wrt soil temp [w/m**2/k]
+ cwshas, &! deriv of shaded wall sensible heat flux wrt soil temp [w/m**2/k]
+ cgrnds, &! deriv of soil sensible heat flux wrt soil temp [w/m**2/k]
+ croofl, &! deriv of roof latent heat flux wrt soil temp [w/m**2/k]
+ cgimpl, &! deriv of gimp latent heat flux wrt soil temp [w/m**2/k]
+ cgperl, &! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+ croof, &! deriv of roof total heat flux wrt soil temp [w/m**2/k]
+ cgimp, &! deriv of gimp total heat flux wrt soil temp [w/m**2/k]
+ cgper, &! deriv of soil total heat flux wrt soil temp [w/m**2/k]
+
+ tref, &! 2 m height air temperature [kelvin]
+ qref, &! 2 m height air humidity [kg/kg]
+
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq, &! integral of profile function for moisture
+ tafu ! effective urban air temperature (2nd layer, walls)
+
+!-------------------------- Local Variables ----------------------------
+ integer :: &
+ niters, &! maximum number of iterations for surface temperature
+ iter, &! iteration index
+ nmozsgn ! number of times moz changes sign
+
+ real(r8) :: &
+ beta, &! coefficient of convective velocity [-]
+ dth, &! diff of virtual temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ obuold, &! monin-obukhov length from previous iteration
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile function for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ um, &! wind speed including the stability effect [m/s]
+ ur, &! wind speed at reference height [m/s]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ zii, &! convective boundary height [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ z0mg, &! roughness length over ground, momentum [m]
+ z0hg, &! roughness length over ground, sensible heat [m]
+ z0qg ! roughness length over ground, latent heat [m]
+
+ real(r8) evplwet, evplwet_dtl, elwmax, elwdif
+
+!----------------------- definition for 3d run -------------------------
+
+ integer, parameter :: nlay = 3 ! potential layer number
+
+ integer :: &
+ clev, &! current layer index
+ numlay ! available layer number
+
+ real(r8) :: &
+ hu_, &! adjusted observational height of wind [m]
+ ht_, &! adjusted observational height of temperature [m]
+ hq_, &! adjusted observational height of humidity [m]
+ ktop, &! K value at a specific height
+ utop, &! u value at a specific height
+ fht, &! integral of profile function for heat at the top layer
+ fqt, &! integral of profile function for moisture at the top layer
+ fmtop, &! fm value at a specific height
+ phih, &! phi(h), similarity function for sensible heat
+ displa, &! displacement height for urban
+ displau, &! displacement height for urban building
+ z0mu, &! roughness length for urban building only
+ z0h, &! roughness length for sensible heat
+ z0q, &! roughness length for latent heat
+ tg, &! ground temperature
+ qg ! ground specific humidity
+
+ real(r8) :: &
+ fg, &! ground fractional cover
+ fgimp, &! weight of impervious ground
+ fgper, &! weight of pervious ground
+ hwr, &! average building height to their distance [-]
+ sqrtdragc, &! sqrt(drag coefficient)
+ lm, &! mix length within canopy
+ fai, &! frontal area index
+ fwet, &! fractional wet area
+ delta, &! 0 or 1
+ alpha ! exponential extinction factor for u/k decline within urban
+
+ real(r8), dimension(0:nurb) :: &
+ tu, &! temperature array
+ fc, &! fractional cover array
+ canlev, &! urban canopy layer lookup table
+ rb, &! leaf boundary layer resistance [s/m]
+ cfh, &! heat conductance for leaf [m/s]
+ cfw, &! latent heat conductance for leaf [m/s]
+ wtl0, &! normalized heat conductance for air and leaf [-]
+ wtlq0, &! normalized latent heat cond. for air and leaf [-]
+
+ ei, &! vapor pressure on leaf surface [pa]
+ deidT, &! derivative of "ei" on "tl" [pa/K]
+ qsatl, &! leaf specific humidity [kg/kg]
+ qsatldT ! derivative of "qsatl" on "tlef"
+
+ real(r8), dimension(nlay) :: &
+ fah, &! weight for thermal resistance to upper layer
+ faw, &! weight for moisture resistance to upper layer
+ fgh, &! weight for thermal resistance to lower layer
+ fgw, &! weight for moisture resistance to lower layer
+ ueff_lay, &! effective wind speed within canopy layer [m/s]
+ ueff_lay_, &! effective wind speed within canopy layer [m/s]
+ taf, &! air temperature within canopy space [K]
+ qaf, &! humidity of canopy air [kg/kg]
+ rd, &! aerodynamic resistance between layers [s/m]
+ rd_, &! aerodynamic resistance between layers [s/m]
+ cah, &! heat conductance for air [m/s]
+ cgh, &! heat conductance for ground [m/s]
+ caw, &! latent heat conductance for air [m/s]
+ cgw, &! latent heat conductance for ground [m/s]
+ wtshi, &! sensible heat resistance for air, grd and leaf [-]
+ wtsqi, &! latent heat resistance for air, grd and leaf [-]
+ wta0, &! normalized heat conductance for air [-]
+ wtg0, &! normalized heat conductance for ground [-]
+ wtaq0, &! normalized latent heat conductance for air [-]
+ wtgq0, &! normalized heat conductance for ground [-]
+ wtll, &! sum of normalized heat conductance for air and leaf
+ wtlql ! sum of normalized heat conductance for air and leaf
+
+ real(r8), dimension(nlay) :: &
+ Hahe ! anthropogenic heat emission (AHE)
+
+ real(r8) :: &
+ ra2m, &! aerodynamic resistance between 2m and bottom layer [s/m]
+ rd2m ! aerodynamic resistance between bottom layer and ground [s/m]
+
+ ! temporal
+ integer i
+ real(r8) tmpw3, cgw_per, cgw_imp
+ real(r8) bee, tmpw1, tmpw2, fact, facq
+ real(r8) aT, bT, cT
+ real(r8) aQ, bQ, cQ, Lahe
+ real(r8) fwet_roof, fwet_roof_, fwet_gimp, fwet_gimp_, rss_
+ real(r8) fwetfac
+
+!-----------------------------------------------------------------------
+
+! initialization
+ tu(0) = troof; tu(1) = twsun; tu(2) = twsha
+
+ fc(:) = fcover(0:nurb)
+ fg = 1 - fcover(0)
+ fgimp = fcover(3)/fg
+ fgper = fcover(4)/fg
+ !hlr = hwr*(1-sqrt(fcover(0)))/sqrt(fcover(0))
+ hwr = hlr*sqrt(fcover(0))/(1-sqrt(fcover(0)))
+ canlev = (/3, 2, 2/)
+ numlay = 2
+
+!-----------------------------------------------------------------------
+! initial roughness length for z0mg, z0hg, z0qg
+! Roughness of the city ground only (excluding buildings and vegetation)
+!-----------------------------------------------------------------------
+
+ !NOTE: change to original
+ !z0mg = (1.-fsno)*zlnd + fsno*zsno
+ IF (fsno_gper > 0) THEN
+ z0mg = zsno
+ ELSE
+ z0mg = zlnd
+ ENDIF
+ z0hg = z0mg
+ z0qg = z0mg
+
+!-----------------------------------------------------------------------
+! initial saturated vapor pressure and humidity and their derivation
+! 0: roof, 1: sunlit wall, 2: shaded wall
+!-----------------------------------------------------------------------
+
+ qsatl(0) = qroof
+ qsatldT(0) = dqroofdT
+ DO i = 1, nurb
+ CALL qsadv(tu(i),psrf,ei(i),deiDT(i),qsatl(i),qsatldT(i))
+ ENDDO
+
+!-----------------------------------------------------------------------
+! tg, qg and wet fraction calculation
+!-----------------------------------------------------------------------
+
+ ! weighted tg
+ tg = tgimp*fgimp + tgper*fgper
+
+ ! wet fraction for roof and impervious ground
+ !-------------------------------------------
+ ! roof
+ IF (lbr < 1) THEN
+ fwet_roof_ = fsno_roof !for snow layer exist
+ ELSE
+ ! surface wet fraction. assuming max ponding = 1 kg/m2
+ fwet_roof_ = (max(0., wliq_roofsno+wice_roofsno))**(2/3.)
+ fwet_roof_ = min(1., fwet_roof_)
+ ENDIF
+
+ ! impervious ground
+ IF (lbi < 1) THEN
+ fwet_gimp_ = fsno_gimp !for snow layer exist
+ ELSE
+ ! surface wet fraction. assuming max ponding = 1 kg/m2
+ fwet_gimp_ = (max(0., wliq_gimpsno+wice_gimpsno))**(2/3.)
+ fwet_gimp_ = min(1., fwet_gimp_)
+ ENDIF
+
+ ! dew case
+ IF (qm > qroof) THEN
+ fwet_roof = 1.
+ ELSE
+ fwet_roof = fwet_roof_
+ ENDIF
+
+ ! dew case
+ IF (qm > qgimp) THEN
+ fwet_gimp = 1.
+ ELSE
+ fwet_gimp = fwet_gimp_
+ ENDIF
+
+ ! weighted qg
+ ! NOTE: IF fwet_gimp=1, same as pervious ground
+ fwetfac = fgimp*fwet_gimp + fgper
+ qg = (qgimp*fgimp*fwet_gimp + qgper*fgper) / fwetfac
+
+
+!-----------------------------------------------------------------------
+! initial for fluxes profile
+!-----------------------------------------------------------------------
+
+ nmozsgn = 0 !number of times moz changes sign
+ obuold = 0. !monin-obukhov length from previous iteration
+ zii = 1000. !m (pbl height)
+ beta = 1. !- (in computing W_*)
+
+!-----------------------------------------------------------------------
+! scaling factor bee
+!-----------------------------------------------------------------------
+!NOTE: bee value, the default is 1
+ bee = 1.
+
+!-----------------------------------------------------------------------
+! calculate z0m and displa
+!-----------------------------------------------------------------------
+
+ ! Macdonald et al., 1998, Eq. (23), A=4.43
+ displau = hroof * (1 + 4.43**(-fcover(0))*(fcover(0) - 1))
+ fai = 4/PI*hlr*fcover(0)
+ z0mu = (hroof - displau) * &
+ exp( -(0.5*1.2/vonkar/vonkar*(1-displau/hroof)*fai)**(-0.5) )
+
+ ! to compare z0 of urban and only the surface
+ ! maximum assumption
+ IF (z0mu < z0mg) z0mu = z0mg
+
+ ! roughness length and displacement height for sensible
+ ! and latent heat transfer
+ z0m = z0mu
+
+ displa = displau
+ displau = max(hroof/2., displau)
+
+!-----------------------------------------------------------------------
+! calculate layer decay coefficient
+!-----------------------------------------------------------------------
+
+ !NOTE: the below is for vegetation, may not be suitable for urban
+ ! Raupach, 1992
+ !sqrtdragc = min( (0.003+0.3*fai)**0.5, 0.3 )
+
+ ! Kondo, 1971
+ !alpha = hroof/(hroof-displa)/(vonkar/sqrtdragc)
+
+ ! Masson, 2000; Oleson et al., 2008
+ IF (alpha_opt == 1) alpha = 0.5*hwr
+
+ ! Swaid, 1993; Kusaka, 2001; Lee and Park, 2008
+ IF (alpha_opt == 2) alpha = 0.772*hwr
+
+ ! Macdonald, 2000
+ IF (alpha_opt == 3) alpha = 9.6*fai
+
+!-----------------------------------------------------------------------
+! first guess for taf and qaf for each layer
+! a large difference from previous schemes
+!-----------------------------------------------------------------------
+
+ IF (numlay .eq. 2) THEN
+ taf(3) = (tg + 2.*thm)/3.
+ qaf(3) = (qg + 2.*qm )/3.
+ taf(2) = (2.*tg + thm)/3.
+ qaf(2) = (2.*qg + qm )/3.
+ ENDIF
+
+! initialization and input values for Monin-Obukhov
+ ! have been set before
+ z0h = z0m; z0q = z0m
+ ur = max(0.1, sqrt(us*us+vs*vs)) !limit set to 0.1
+ dth = thm - taf(2)
+ dqh = qm - qaf(2)
+ dthv = dth*(1.+0.61*qm) + 0.61*th*dqh
+
+ hu_ = hu; ht_ = ht; hq_ = hq;
+
+ IF (trim(HEIGHT_mode) == 'absolute') THEN
+
+ IF (hu <= hroof+1) THEN
+ hu_ = hroof + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of u less than hroof+1, set it to hroof+1.'
+ ENDIF
+
+ IF (ht <= hroof+1) THEN
+ ht_ = hroof + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of t less than hroof+1, set it to hroof+1.'
+ ENDIF
+
+ IF (hq <= hroof+1) THEN
+ hq_ = hroof + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of q less than hroof+1, set it to hroof+1.'
+ ENDIF
+
+ ELSE ! relative height
+ hu_ = hroof + hu
+ ht_ = hroof + ht
+ hq_ = hroof + hq
+ ENDIF
+
+ zldis = hu_ - displa
+
+ IF (zldis <= 0.0) THEN
+ write(6,*) 'the obs height of u less than the zero displacement heght'
+ CALL abort
+ ENDIF
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0m,um,obu)
+
+ niters=6
+
+! ======================================================================
+! BEGIN stability iteration
+! ======================================================================
+
+ ITERATION : DO iter = 1, niters !begin stability iteration
+
+!-----------------------------------------------------------------------
+! Aerodynamical resistances
+!-----------------------------------------------------------------------
+! Evaluate stability-dependent variables using moz from prior iteration
+
+ !NOTE: displat=hroof, z0mt=0, are set for roof
+ ! fmtop is calculated at the same height of fht, fqt
+ CALL moninobukm(hu_,ht_,hq_,displa,z0m,z0h,z0q,obu,um, &
+ hroof,0.,ustar,fh2m,fq2m,hroof,fmtop,fm,fh,fq,fht,fqt,phih)
+
+! Aerodynamic resistance
+ ! 09/16/2017:
+ ! NOTE that for ram, it is the resistance from Href to z0mv+displa
+ ! however, for rah and raw is only from Href to canopy effective
+ ! exchange height.
+ ! For Urban: from Href to roof height
+ ! so rah/raw is not comparable with that of 1D case
+ ram = 1./(ustar*ustar/um)
+
+ ! 05/02/2016: calculate resistance from the top layer (effective exchange
+ ! height) to reference height
+ ! For Urban: from roof height to reference height
+ rah = 1./(vonkar/(fh-fht)*ustar)
+ raw = 1./(vonkar/(fq-fqt)*ustar)
+
+ ! update roughness length for sensible/latent heat
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ z0h = max(z0hg, z0h)
+ z0q = max(z0qg, z0q)
+
+!-----------------------------------------------------------------------
+! new method to calculate rd and ueffect
+! the kernel part of 3d model
+!-----------------------------------------------------------------------
+
+ ! initialization
+ rd(:) = 0.
+ rd_(:) = 0.
+ ueff_lay(:) = 0.
+ ueff_lay_(:) = 0.
+
+ ! calculate canopy top wind speed (utop) and exchange coefficient (ktop)
+ ! need to update each time as obu changed after each iteration
+ utop = ustar/vonkar * fmtop
+ ktop = vonkar * (hroof-displa) * ustar / phih
+
+ ueff_lay(3) = utop
+
+ ! NOTE: another calculation method for double-check
+ ! real(r8) FUNCTION kintegral(ktop, fc, bee, alpha, z0mg, displah, &
+ ! htop, hbot, obu, ustar, ztop, zbot)
+ ! rd(3) = kintegral(ktop, 1., bee, alpha, z0mg, displa/hroof, &
+ ! hroof, 0., obug, ustarg, hroof, displa+z0m)
+
+ ! real(r8) FUNCTION frd(ktop, htop, hbot, ztop, zbot, displah, z0h, &
+ ! obu, ustar, z0mg, alpha, bee, fc)
+ rd(3) = frd(ktop, hroof, 0., hroof, displau+z0mu, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! real(r8) FUNCTION uintegralz(utop, fc, bee, alpha, z0mg, htop, hbot, ztop, zbot)
+ ! ueff_lay(2) = uintegralz(utop, 1., bee, alpha, z0mg, hroof, 0., hroof, z0mg)
+
+ ! real(r8) FUNCTION ueffectz(utop, htop, hbot, ztop, zbot, z0mg, alpha, bee, fc)
+ ueff_lay(2) = ueffectz(utop, hroof, 0., hroof, z0mg, z0mg, alpha, bee, 1.)
+
+ ! rd(2) = kintegral(ktop, 1., bee, alpha, z0mg, displa/hroof, &
+ ! hroof, 0., obug, ustarg, displau+z0mu, z0qg)
+ rd(2) = frd(ktop, hroof, 0., displau+z0mu, z0qg, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! calculate ra2m, rd2m. NOTE: not used now.
+ ra2m = frd(ktop, hroof, 0., displau+z0mu, 2., displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ rd2m = frd(ktop, hroof, 0., 2., z0qg, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! Masson, 2000: Account for different canyon orientations
+ ! 2/PI is a factor derived from 0-360deg integration
+ IF (alpha_opt == 1) THEN
+ ueff_lay(2) = 2/PI*ueff_lay(2)
+ rd(:) = PI/2*rd(:)
+ ENDIF
+
+!-----------------------------------------------------------------------
+! Bulk boundary layer resistance of leaves
+!-----------------------------------------------------------------------
+
+ rb(:) = 0.
+
+ DO i = 0, nurb
+ clev = canlev(i)
+ rb(i) = rhoair * cpair / ( 11.8 + 4.2*ueff_lay(clev) )
+ ENDDO
+
+!-----------------------------------------------------------------------
+! Solve taf(:) and qaf(:)
+!-----------------------------------------------------------------------
+
+ IF (numlay .eq. 2) THEN
+
+ ! - Equations:
+ ! taf(3) = (1/rah*thm + 1/rd(3)*taf(2) + 1/rb(0)*troof*fc(0) &
+ ! + AHE/(rho*cp))/(1/rah + 1/rd(3) + 1/rb(0)*fc(0))
+ ! taf(2) = (1/rd(3)*taf(3) + 1/rd(2)*tg*fg + 1/rb(1)*twsun*fc(1) + 1/rb(2)*twsha*fc(2) &
+ ! + AHE/(rho*cp))/ (1/rd(3) + 1/rd(2)*fg + 1/rb(1)*fc(1) + 1/rb(2)*fc(2))
+ ! Also written as:
+ ! taf(3) = (cah(3)*thm + cah(2)*taf(2) &
+ ! + cfh(0)*troof*fc(0))/(cah(3) + cah(2) + cfh(0)*fc(0))
+ ! taf(2) = (cah(2)*taf(3) + cgh(2)*tg*fg + cfh(1)*twsun*fc(1) + cfh(2)*twsha*fc(2) &
+ ! + AHE/(rho*cp))/(cah(2) + cgh(2)*fg + cfh(1)*fc(1) + cfh(2)*fc(2))
+ !
+ ! - Equations:
+ ! qaf(3) = (1/raw*qm + 1/rd(3)*qaf(2) + 1/rb(0)*qroof*fc(0)) &
+ ! / (1/raw + 1/rd(3) + 1/rb(0)*fc(0))
+ ! qaf(2) = (1/rd(3)*qaf(3) + 1/(rd(2)+rss)*qper*fgper*fg + fwetimp/rd(2)*qimp*fgimp*fg &
+ ! + AHE/rho)/(1/rd(3) + 1/(rd(2)+rss)*fgper*fg + fwetimp/rd(2)*fgimp*fg)
+ ! Also written as:
+ ! qaf(3) = (caw(3)*qm + caw(2)*qaf(2) &
+ ! + cfw(0)*qroof*fc(0))/(caw(3) + caw(2) + cfw(0)*fc(0))
+ ! qaf(2) = (caw(2)*qaf(3) + cgwper*qper*fgper*fg + cgwimp*qimp*fgimp*fg + AHE/rho)/ &
+ ! (caw(2) + cgwper*fgper*fg + cgwimp*fgimp*fg)
+
+ ! 06/20/2021, yuan: account for Anthropogenic heat
+ ! 92% heat release as SH, Pigeon et al., 2007
+
+ Hahe(2) = 4*hlr/(4*hlr+1)*(Fhac+Fwst)*fsh + Fach + vehc*fsh + meta
+ Hahe(3) = 1/(4*hlr+1)*(Fhac+Fwst)*fsh
+
+ bT = 1/(rd(3) * (1/rah+1/rd(3)+fc(0)/rb(0)))
+ cT = 1/rd(3) + fg/rd(2) + fc(1)/rb(1) + fc(2)/rb(2)
+ aT = (tu(0)*fc(0)/rb(0) + Hahe(3)/(rhoair*cpair) + thm/rah)*bT
+
+ taf(2) = (tg*fg/rd(2) + Hahe(2)/(rhoair*cpair) &
+ + tu(1)*fc(1)/rb(1) + tu(2)*fc(2)/rb(2) + aT) &
+ / (cT * (1- bT/(cT*rd(3))))
+
+ taf(3) = (taf(2)/rd(3) + tu(0)*fc(0)/rb(0) + Hahe(3)/(rhoair*cpair) + thm/rah) &
+ / (1/rah + 1/rd(3) + fc(0)/rb(0))
+
+ IF (qgper < qaf(2)) THEN
+ ! dew case. no soil resistance
+ rss_ = 0
+ ELSE
+ rss_ = rss
+ ENDIF
+
+ Lahe = (Fhac + Fwst + vehc)*flh
+ cQ = 1/rd(3) + fg*fgper/(rd(2)+rss_) + fwet_gimp*fg*fgimp/rd(2)
+ bQ = 1/(rd(3) * (1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+ aQ = (qsatl(0)*fwet_roof*fc(0)/rb(0) + qm/raw)*bQ
+
+ qaf(2) = (qgper*fgper*fg/(rd(2)+rss_) + qgimp*fwet_gimp*fgimp*fg/rd(2) &
+ + aQ + Lahe/rhoair/hvap) / (cQ * (1-bQ/(cQ*rd(3))))
+
+ qaf(3) = (qaf(2)/rd(3) + qsatl(0)*fwet_roof*fc(0)/rb(0) + qm/raw) &
+ / (1/raw + 1/rd(3) + fwet_roof*fc(0)/rb(0))
+
+ ENDIF
+
+ !------------------------------------------------
+ ! update fwet for roof and impervious ground
+ ! to check whether dew happens
+ IF (qaf(3) > qroof) THEN
+ fwet_roof = 1. !dew case
+ ELSE
+ fwet_roof = fwet_roof_
+ ENDIF
+
+ ! to check whether dew happens
+ IF (qaf(2) > qgimp) THEN
+ fwet_gimp = 1. !dew case
+ ELSE
+ fwet_gimp = fwet_gimp_
+ ENDIF
+
+ ! weighted qg
+ ! NOTE: IF fwet_gimp=1, same as previous
+ fwetfac = fgimp*fwet_gimp + fgper
+ qg = (qgimp*fgimp*fwet_gimp + qgper*fgper) / fwetfac
+
+ fgw(2) = fg*fwetfac
+
+!-----------------------------------------------------------------------
+! Update monin-obukhov length and wind speed including the stability effect
+!-----------------------------------------------------------------------
+
+ ! USE the top layer taf and qaf
+ dth = thm - taf(2)
+ dqh = qm - qaf(2)
+
+ tstar = vonkar/(fh)*dth
+ qstar = vonkar/(fq)*dqh
+
+ thvstar = tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta = zldis*vonkar*grav*thvstar / (ustar**2*thv)
+ IF (zeta .ge. 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF (zeta .ge. 0.) THEN
+ um = max(ur,.1)
+ ELSE
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu .lt. 0.) nmozsgn = nmozsgn+1
+ IF (nmozsgn >= 4) EXIT
+
+ obuold = obu
+
+ ENDDO ITERATION !end stability iteration
+
+! ======================================================================
+! END stability iteration
+! ======================================================================
+
+ zol = zeta
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+ ! sensible heat fluxes
+ fsenroof = rhoair*cpair/rb(0)*(troof-taf(3))
+ fsenwsun = rhoair*cpair/rb(1)*(twsun-taf(2))
+ fsenwsha = rhoair*cpair/rb(2)*(twsha-taf(2))
+
+ ! latent heat fluxes
+ fevproof = rhoair/rb(0)*(qsatl(0)-qaf(3))
+ fevproof = fevproof*fwet_roof
+
+ bT = 1/(rd(3) * (1/rah+1/rd(3)+fc(0)/rb(0)))
+ cT = 1/rd(3) + fg/rd(2) + fc(1)/rb(1) + fc(2)/rb(2)
+
+ cQ = 1/rd(3) + fg*fgper/(rd(2)+rss_) + fwet_gimp*fg*fgimp/rd(2)
+ bQ = 1/(rd(3) * (1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+
+ cwsuns = rhoair*cpair/rb(1) &
+ * ( 1. - fc(1) / (cT*rb(1)*(1-bT/(cT*rd(3)))) )
+ cwshas = rhoair*cpair/rb(2) &
+ * ( 1. - fc(2) / (cT*rb(2)*(1-bT/(cT*rd(3)))) )
+ croofs = rhoair*cpair/rb(0) &
+ * ( 1. - fc(0)*bT*bT / (cT*rb(0)*(1-bT/(cT*rd(3)))) &
+ - fc(0) / (rb(0)*(1/rah+1/rd(3)+fc(0)/rb(0))) )
+
+ croofl = rhoair*fwet_roof/rb(0)*qsatldT(0) &
+ * ( 1. - fwet_roof*fc(0)*bQ*bQ / (cQ*rb(0)*(1-bQ/(cQ*rd(3)))) &
+ - fwet_roof*fc(0) / (rb(0)*(1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0))) )
+
+ croof = croofs + croofl*htvp_roof
+
+
+#if (defined CoLMDEBUG)
+#endif
+
+ tafu = taf(2)
+
+!-----------------------------------------------------------------------
+! wind stresses
+!-----------------------------------------------------------------------
+
+ taux = - rhoair*us/ram
+ tauy = - rhoair*vs/ram
+
+!-----------------------------------------------------------------------
+! fluxes from urban ground to canopy space
+!-----------------------------------------------------------------------
+
+ fsengper = cpair*rhoair/rd(2)*(tgper-taf(2))
+ fsengimp = cpair*rhoair/rd(2)*(tgimp-taf(2))
+
+ fevpgper = rhoair/(rd(2)+rss_)*(qgper-qaf(2))
+ fevpgimp = rhoair/rd(2) *(qgimp-qaf(2))
+ fevpgimp = fevpgimp*fwet_gimp
+
+!-----------------------------------------------------------------------
+! Derivative of soil energy flux with respect to soil temperature (cgrnd)
+!-----------------------------------------------------------------------
+
+ cgrnds = cpair*rhoair/rd(2)*( 1. - fg/(cT*rd(2)*(1-bT/(cT*rd(3)))) )
+
+ cgperl = rhoair/(rd(2)+rss_) &
+ * dqgperdT*( 1 - fg*fgper/(cQ*(rd(2)+rss_)*(1-bQ/(cQ*rd(3)))) )
+ cgimpl = rhoair*fwet_gimp/rd(2)&
+ * dqgimpdT*( 1 - fwet_gimp*fg*fgimp/(cQ*rd(2)*(1-bQ/(cQ*rd(3)))) )
+
+ cgimp = cgrnds + cgimpl*htvp_gimp
+ cgper = cgrnds + cgperl*htvp_gper
+
+!-----------------------------------------------------------------------
+! 2 m height air temperature above apparent sink height
+!-----------------------------------------------------------------------
+
+ !tref = thm + vonkar/(fh-fht)*dth * (fh2m/vonkar - fh/vonkar)
+ !qref = qm + vonkar/(fq-fqt)*dqh * (fq2m/vonkar - fq/vonkar)
+
+ ! assumption: (tg-t2m):(tg-taf) = 2:(displa+z0m)
+ tref = ( (displau+z0mu-2.)*tg + 2.*taf(2) ) / (displau+z0mu)
+ qref = ( (displau+z0mu-2.)*qg + 2.*qaf(2) ) / (displau+z0mu)
+
+ END SUBROUTINE UrbanOnlyFlux
+
+
+ SUBROUTINE UrbanVegFlux ( &
+ ! Model running information
+ ipatch ,deltim ,lbr ,lbi ,&
+ ! Forcing
+ hu ,ht ,hq ,us ,&
+ vs ,thm ,th ,thv ,&
+ qm ,psrf ,rhoair ,frl ,&
+ po2m ,pco2m ,par ,sabv ,&
+ rstfac ,Fhac ,Fwst ,Fach ,&
+ vehc ,meta ,&
+ ! Urban and vegetation parameters
+ hroof ,hlr ,nurb ,fcover ,&
+ ewall ,egimp ,egper ,ev ,&
+ htop ,hbot ,lai ,sai ,&
+ sqrtdi ,effcon ,vmax25 ,c3c4 ,slti,&
+ hlti ,shti ,hhti ,trda ,&
+ trdm ,trop ,g1 ,g0 ,&
+ gradm ,binter ,extkn ,extkd ,&
+ dewmx ,etrc ,trsmx0 ,lambda_wue ,&
+ ! Status of surface
+ z0h_g ,obug ,ustarg ,zlnd ,&
+ zsno ,fsno_roof ,fsno_gimp ,fsno_gper ,&
+ wliq_roofsno ,wliq_gimpsno ,wice_roofsno ,wice_gimpsno ,&
+ htvp_roof ,htvp_gimp ,htvp_gper ,troof ,&
+ twsun ,twsha ,tgimp ,tgper ,&
+ qroof ,qgimp ,qgper ,dqroofdT ,&
+ dqgimpdT ,dqgperdT ,sigf ,tl ,&
+ ldew ,ldew_rain ,ldew_snow ,fwet_snow ,&
+ dheatl ,rss ,etr_deficit ,&
+ ! Longwave information
+ Ainv ,B ,B1 ,dBdT ,&
+ SkyVF ,VegVF ,&
+ ! Output
+ taux ,tauy ,fsenroof ,fsenwsun ,&
+ fsenwsha ,fsengimp ,fsengper ,fevproof ,&
+ fevpgimp ,fevpgper ,croofs ,cwsuns ,&
+ cwshas ,cgrnds ,croofl ,cgimpl ,&
+ cgperl ,croof ,cgimp ,cgper ,&
+ fsenl ,fevpl ,etr ,rst ,&
+ assim ,respc ,lwsun ,lwsha ,&
+ lgimp ,lgper ,lveg ,lout ,&
+ tref ,qref ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,tafu )
+
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: vonkar,grav,hvap,cpair,stefnc,cpliq, cpice, &
+ hfus, tfrz, denice, denh2o
+ USE MOD_FrictionVelocity
+ USE MOD_CanopyLayerProfile
+ USE MOD_AssimStomataConductance
+ USE MOD_UserSpecifiedForcing, only: HEIGHT_mode
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch, &! patch index [-]
+ lbr, &! lower bound of array
+ lbi ! lower bound of array
+
+ real(r8), intent(in) :: &
+ deltim ! seconds in a time step [second]
+
+ ! Forcing
+ real(r8), intent(in) :: &
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+ qm, &! specific humidity at reference height [kg/kg]
+ psrf, &! pressure at reference height [pa]
+ rhoair, &! density air [kg/m**3]
+
+ frl, &! atmospheric infrared (longwave) radiation [W/m2]
+ par, &! par absorbed per unit sunlit lai [w/m**2]
+ sabv, &! solar radiation absorbed by vegetation [W/m2]
+ rstfac, &! factor of soil water stress to plant physiological processes
+
+ po2m, &! atmospheric partial pressure o2 (pa)
+ pco2m, &! atmospheric partial pressure co2 (pa)
+
+ vehc, &! flux from vehicle [W/m2]
+ meta, &! flux from metabolic [W/m2]
+ Fhac, &! flux from heat or cool AC [W/m2]
+ Fwst, &! waste heat from cool or heat [W/m2]
+ Fach ! flux from air exchange [W/m2]
+
+ ! Urban and vegetation parameters
+ integer, intent(in) :: &
+ nurb ! number of aboveground urban components [-]
+
+ real(r8), intent(in) :: &
+ hroof, &! average building height [m]
+ hlr, &! average building height to their side length [-]
+ fcover(0:5) ! coverage of aboveground urban components [-]
+
+ real(r8), intent(in) :: &
+ ewall, &! emissivity of walls
+ egimp, &! emissivity of impervious road
+ egper, &! emissivity of pervious road
+ ev ! emissivity of vegetation
+
+ real(r8), intent(in) :: &
+ htop, &! PFT crown top height [m]
+ hbot, &! PFT crown bottom height [m]
+ lai, &! adjusted leaf area index for seasonal variation [-]
+ sai, &! stem area index [-]
+ sqrtdi, &! inverse sqrt of leaf dimension [m**-0.5]
+
+ effcon, &! quantum efficiency of RuBP regeneration (mol CO2 / mol quanta)
+ vmax25, &! maximum carboxylation rate at 25 C at canopy top
+ ! the range : 30.e-6 <-> 100.e-6 (mol co2 m-2 s-1)
+ shti, &! slope of high temperature inhibition function (s1)
+ hhti, &! 1/2 point of high temperature inhibition function (s2)
+ slti, &! slope of low temperature inhibition function (s3)
+ hlti, &! 1/2 point of low temperature inhibition function (s4)
+ trda, &! temperature coefficient in gs-a model (s5)
+ trdm, &! temperature coefficient in gs-a model (s6)
+ trop, &! temperature coefficient in gs-a model (273+25)
+ g1, &! conductance-photosynthesis slope parameter for medlyn model
+ g0, &! conductance-photosynthesis intercept for medlyn model
+ gradm, &! conductance-photosynthesis slope parameter
+ binter, &! conductance-photosynthesis intercept
+ lambda_wue, &! marginal water cost of carbon gain
+
+ extkn, &! coefficient of leaf nitrogen allocation
+ extkd, &! diffuse and scattered diffuse PAR extinction coefficient
+ dewmx, &! maximum dew
+ trsmx0, &! max transpiration for moist soil+100% veg. [mm/s]
+ etrc ! maximum possible transpiration rate (mm/s)
+
+ integer, intent(in) :: &
+ c3c4 ! 1: C3, 0: C4
+
+ ! Status of surface
+ real(r8), intent(in) :: &
+ rss, &! bare soil resistance for evaporation [s/m]
+ z0h_g, &! roughness length for bare ground, sensible heat [m]
+ obug, &! monin-obukhov length for bare ground (m)
+ ustarg, &! friction velocity for bare ground [m/s]
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+ fsno_roof, &! fraction of ground covered by snow
+ fsno_gimp, &! fraction of ground covered by snow
+ fsno_gper, &! fraction of ground covered by snow
+ wliq_roofsno, &! liqui water [kg/m2]
+ wliq_gimpsno, &! liqui water [kg/m2]
+ wice_roofsno, &! ice lens [kg/m2]
+ wice_gimpsno, &! ice lens [kg/m2]
+ htvp_roof, &! latent heat of vapor of water (or sublimation) [j/kg]
+ htvp_gimp, &! latent heat of vapor of water (or sublimation) [j/kg]
+ htvp_gper, &! latent heat of vapor of water (or sublimation) [j/kg]
+
+ troof, &! temperature of roof [K]
+ twsun, &! temperature of sunlit wall [K]
+ twsha, &! temperature of shaded wall [K]
+ tgimp, &! temperature of impervious road [K]
+ tgper, &! pervious ground temperature [K]
+
+ qroof, &! roof specific humidity [kg/kg]
+ qgimp, &! imperivous road specific humidity [kg/kg]
+ qgper, &! pervious ground specific humidity [kg/kg]
+ dqroofdT, &! d(qroof)/dT
+ dqgimpdT, &! d(qgimp)/dT
+ dqgperdT, &! d(qgper)/dT
+ sigf !
+
+ real(r8), intent(inout) :: &
+ tl, &! leaf temperature [K]
+ ldew, &! depth of water on foliage [mm]
+ ldew_rain, &! depth of rain on foliage [mm]
+ ldew_snow ! depth of snow on foliage [mm]
+
+ real(r8), intent(out) :: &
+ fwet_snow, &! vegetation snow fractional cover [-]
+ dheatl ! vegetation heat change [W/m2]
+
+ real(r8), intent(in) :: Ainv(5,5) !Inverse of Radiation transfer matrix
+ real(r8), intent(in) :: SkyVF (5) !View factor to sky
+ real(r8), intent(in) :: VegVF (5) !View factor to veg
+ real(r8), intent(inout) :: B (5) !Vectors of incident radiation on each surface
+ real(r8), intent(inout) :: B1 (5) !Vectors of incident radiation on each surface
+ real(r8), intent(inout) :: dBdT (5) !Vectors of incident radiation on each surface
+
+ real(r8), intent(out) :: &
+ taux, &! wind stress: E-W [kg/m/s**2]
+ tauy, &! wind stress: N-S [kg/m/s**2]
+ fsenroof, &! sensible heat flux from roof [W/m2]
+ fsenwsun, &! sensible heat flux from sunlit wall [W/m2]
+ fsenwsha, &! sensible heat flux from shaded wall [W/m2]
+ fsengimp, &! sensible heat flux from impervious road [W/m2]
+ fsengper, &! sensible heat flux from pervious ground [W/m2]
+ fevproof, &! evaporation heat flux from roof [mm/s]
+ fevpgimp, &! evaporation heat flux from impervious road [mm/s]
+ fevpgper, &! evaporation heat flux from pervious ground [mm/s]
+
+ croofs, &! deriv of roof sensible heat flux wrt soil temp [w/m**2/k]
+ cwsuns, &! deriv of sunlit wall sensible heat flux wrt soil temp [w/m**2/k]
+ cwshas, &! deriv of shaded wall sensible heat flux wrt soil temp [w/m**2/k]
+ cgrnds, &! deriv of ground latent heat flux wrt soil temp [w/m**2/k]
+ croofl, &! deriv of roof latent heat flux wrt soil temp [w/m**2/k]
+ cgimpl, &! deriv of impervious latent heat flux wrt soil temp [w/m**2/k]
+ cgperl, &! deriv of soil latent heat flux wrt soil temp [w/m**2/k]
+ croof, &! deriv of roof total flux wrt soil temp [w/m**2/k]
+ cgimp, &! deriv of impervious total heat flux wrt soil temp [w/m**2/k]
+ cgper, &! deriv of soil total heat flux wrt soil temp [w/m**2/k]
+
+ tref, &! 2 m height air temperature [kelvin]
+ qref ! 2 m height air humidity
+
+ real(r8), intent(out) :: &
+ fsenl, &! sensible heat from leaves [W/m2]
+ fevpl, &! evaporation+transpiration from leaves [mm/s]
+ etr, &! transpiration rate [mm/s]
+ rst, &! stomatal resistance
+ assim, &! rate of assimilation
+ respc ! rate of respiration
+
+ real(r8), intent(inout) :: &
+ etr_deficit ! urban irrigation [mm/s]
+
+ real(r8), intent(inout) :: &
+ lwsun, &! net longwave radiation of sunlit wall [W/m2]
+ lwsha, &! net longwave radiation of shaded wall [W/m2]
+ lgimp, &! net longwave radiation of impervious road [W/m2]
+ lgper, &! net longwave radiation of pervious road [W/m2]
+ lveg, &! net longwave radiation of vegetation [W/m2]
+ lout ! out-going longwave radiation [W/m2]
+
+ real(r8), intent(inout) :: &
+ z0m, &! effective roughness [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib, &! bulk Richardson number in surface layer
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq, &! integral of profile function for moisture
+ tafu ! effective urban air temperature (2nd layer, walls)
+
+!-----------------------Local Variables---------------------------------
+! assign iteration parameters
+ integer, parameter :: itmax = 40 !maximum number of iteration
+ integer, parameter :: itmin = 6 !minimum number of iteration
+ real(r8),parameter :: delmax = 3.0 !maximum change in leaf temperature [K]
+ real(r8),parameter :: dtmin = 0.01 !max limit for temperature convergence [K]
+ real(r8),parameter :: dlemin = 0.1 !max limit for energy flux convergence [w/m2]
+
+ real(r8) dtl(0:itmax+1) !difference of tl between two iterative step
+
+ real(r8) :: &
+ zldis, &! reference height "minus" zero displacement height [m]
+ zii, &! convective boundary layer height [m]
+ z0mv, &! roughness length of vegetation only, momentum [m]
+ z0mu, &! roughness length of building only, momentum [m]
+ z0h, &! roughness length, sensible heat [m]
+ z0q, &! roughness length, latent heat [m]
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ beta, &! coefficient of convective velocity [-]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ dth, &! diff of virtual temp. between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ um, &! wind speed including the stability effect [m/s]
+ ur, &! wind speed at reference height [m/s]
+ uaf, &! velocity of air within foliage [m/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile function for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ eah, &! canopy air vapor pressure (pa)
+ pco2g, &! co2 pressure (pa) at ground surface (pa)
+ pco2a, &! canopy air co2 pressure (pa)
+
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ clai, &! canopy heat capacity [Jm-2K-1]
+ del, &! absolute change in leaf temp in current iteration [K]
+ del2, &! change in leaf temperature in previous iteration [K]
+ dele, &! change in heat fluxes from leaf [K]
+ dele2, &! change in heat fluxes from leaf [K]
+ det, &! maximum leaf temp. change in two consecutive iter [K]
+ dee, &! maximum leaf temp. change in two consecutive iter [K]
+
+ obuold, &! monin-obukhov length from previous iteration
+ tlbef, &! leaf temperature from previous iteration [K]
+ err, &! balance error
+
+ rs, &! sunlit leaf stomatal resistance [s/m]
+ rsoil, &! soil respiration
+ gah2o, &! conductance between canopy and atmosphere
+ gdh2o, &! conductance between canopy and ground
+ tprcor ! tf*psur*100./1.013e5
+
+ integer it, nmozsgn
+
+ real(r8) evplwet, evplwet_dtl, etr_dtl, elwmax, elwdif
+ real(r8) irab, dirab_dtl, fsenl_dtl, fevpl_dtl
+ real(r8) z0mg, z0hg, z0qg, cint(3)
+ real(r8) fevpl_bef, fevpl_noadj, dtl_noadj, erre
+ real(r8) qevpl, qdewl, qsubl, qfrol, qmelt, qfrz
+
+!----------------------- definition for 3d run ------------------------
+ integer, parameter :: nlay = 3
+ integer, parameter :: uvec(5) = (/0,0,0,0,1/) !unit vector
+
+ integer :: &
+ clev, &! current layer index
+ botlay, &! bottom layer index
+ numlay ! available layer number
+
+ real(r8) :: &
+ hu_, &! adjusted observational height of wind [m]
+ ht_, &! adjusted observational height of temperature [m]
+ hq_, &! adjusted observational height of humidity [m]
+ ktop, &! K value at a specific height
+ utop, &! u value at a specific height
+ fht, &! integral of profile function for heat at the top layer
+ fqt, &! integral of profile function for moisture at the top layer
+ fmtop, &! fm value at a specific height
+ phih, &! phi(h), similarity function for sensible heat
+ displa, &! displacement height for urban
+ displau, &! displacement height for urban building
+ displav, &! displacement height for urban vegetation
+ displav_lay, &! displacement height for urban vegetation layer
+ z0mv_lay, &! roughness length for vegetation
+ ueff_veg, &! effective wind speed within canopy layer [m/s]
+ tg, &! ground temperature
+ qg ! ground specific humidity
+
+ real(r8) :: &
+ fg, &! ground fractional cover
+ fgimp, &! weight of impervious ground
+ fgper, &! weight of pervious ground
+ hwr, &! average building height to their distance [-]
+ sqrtdragc, &! sqrt(drag coefficient)
+ lm, &! mix length within canopy
+ fai, &! frontal area index for urban
+ faiv, &! frontal area index for trees
+ lsai, &! lai+sai
+ fwet, &! fractional wet area of foliage [-]
+ fdry, &! fraction of foliage that is green and dry [-]
+ delta, &! 0 or 1
+ alpha, &! exponential extinction factor for u/k decline within urban
+ alphav ! exponential extinction factor for u/k decline within trees
+
+ real(r8) :: &
+ dlwsun, &! change of lw for the last time
+ dlwsha, &! change of lw for the last time
+ dlgimp, &! change of lw for the last time
+ dlgper, &! change of lw for the last time
+ dlveg ! change of lw for the last time
+
+ real(r8), dimension(0:nurb) :: &
+ tu, &! temperature array
+ fc, &! fractional cover array
+ canlev, &! urban canopy layer lookup table
+ rb, &! leaf boundary layer resistance [s/m]
+ cfh, &! heat conductance for leaf [m/s]
+ cfw, &! latent heat conductance for leaf [m/s]
+ wtl0, &! normalized heat conductance for air and leaf [-]
+ wtlq0, &! normalized latent heat cond. for air and leaf [-]
+
+ ei, &! vapor pressure on leaf surface [pa]
+ deidT, &! derivative of "ei" on "tl" [pa/K]
+ qsatl, &! leaf specific humidity [kg/kg]
+ qsatldT ! derivative of "qsatl" on "tlef"
+
+ real(r8), dimension(nlay) :: &
+ fah, &! weight for thermal resistance to upper layer
+ faw, &! weight for moisture resistance to upper layer
+ fgh, &! weight for thermal resistance to lower layer
+ fgw, &! weight for moisture resistance to lower layer
+ ueff_lay, &! effective wind speed within canopy layer [m/s]
+ ueff_lay_, &! effective wind speed within canopy layer [m/s]
+ taf, &! air temperature within canopy space [K]
+ qaf, &! humidity of canopy air [kg/kg]
+ rd, &! aerodynamic resistance between layers [s/m]
+ rd_, &! aerodynamic resistance between layers [s/m]
+ cah, &! heat conductance for air [m/s]
+ cgh, &! heat conductance for ground [m/s]
+ caw, &! latent heat conductance for air [m/s]
+ cgw, &! latent heat conductance for ground [m/s]
+ wtshi, &! sensible heat resistance for air, grd and leaf [-]
+ wtsqi, &! latent heat resistance for air, grd and leaf [-]
+ wta0, &! normalized heat conductance for air [-]
+ wtg0, &! normalized heat conductance for ground [-]
+ wtaq0, &! normalized latent heat conductance for air [-]
+ wtgq0, &! normalized heat conductance for ground [-]
+ wtll, &! sum of normalized heat conductance for air and leaf
+ wtlql ! sum of normalized heat conductance for air and leaf
+
+ real(r8), dimension(nlay) :: &
+ Hahe ! anthropogenic heat emission (AHE)
+
+ real(r8) :: &
+ rv, &! aerodynamic resistance between layers [s/m]
+ ra2m, &! aerodynamic resistance between 2m and bottom layer [s/m]
+ rd2m ! aerodynamic resistance between bottom layer and ground [s/m]
+
+ ! temporal
+ integer i
+ real(r8) aT, bT, cT, aQ, bQ, cQ, Lahe
+ real(r8) bee, cf, tmpw1, tmpw2, tmpw3, tmpw4, fact, facq, taftmp
+ real(r8) B_5, B1_5, dBdT_5, X(5), dX(5)
+ real(r8) fwet_roof, fwet_roof_, fwet_gimp, fwet_gimp_, rss_, rs_, etr_
+ real(r8) fwetfac, lambda
+ real(r8) cgw_imp, cgw_per
+
+ ! for interface
+ real(r8) o3coefv, o3coefg, assim_RuBP, assim_Rubisco, ci, vpd, gammas
+
+!-----------------------------------------------------------------------
+
+! initialization of errors and iteration parameters
+ it = 1 !counter for leaf temperature iteration
+ del = 0.0 !change in leaf temperature from previous iteration
+ dele = 0.0 !latent head flux from leaf for previous iteration
+
+ dtl = 0.
+ fevpl_bef = 0.
+
+! initial values for z0hg, z0qg
+
+ !TODO: change to original
+ !z0mg = (1.-fsno)*zlnd + fsno*zsno
+ IF (fsno_gper > 0) THEN
+ z0mg = zsno
+ ELSE
+ z0mg = zlnd
+ ENDIF
+ z0hg = z0mg
+ z0qg = z0mg
+
+!-----------------------------------------------------------------------
+! scaling-up coefficients from leaf to canopy
+!-----------------------------------------------------------------------
+
+ cint(1) = (1.-exp(-0.110*lai))/0.110
+ cint(2) = (1.-exp(-extkd*lai))/extkd
+ cint(3) = lai
+
+!-----------------------------------------------------------------------
+! initial saturated vapor pressure and humidity and their derivation
+!-----------------------------------------------------------------------
+
+ clai = 0.0
+ lsai = lai + sai
+
+ ! 0.2mm*LSAI, account for leaf (plus dew) heat capacity
+ IF ( DEF_VEG_SNOW ) THEN
+ clai = 0.2*(lai+sai)*cpliq + ldew_rain*cpliq + ldew_snow*cpice
+ ENDIF
+
+ ! index 0:roof, 1:sunlit wall, 2:shaded wall, 3: vegetation
+ tu(0) = troof; tu(1) = twsun; tu(2) = twsha; tu(3) = tl
+
+ fg = 1 - fcover(0)
+ fc(:) = fcover(0:nurb)
+ fc(3) = fcover(5)
+ fgimp = fcover(3)/fg
+ fgper = fcover(4)/fg
+ !hlr = hwr*(1-sqrt(fcover(0)))/sqrt(fcover(0))
+ hwr = hlr*sqrt(fcover(0))/(1-sqrt(fcover(0)))
+ canlev = (/3, 2, 2, 1/)
+
+ B_5 = B(5)
+ B1_5 = B1(5)
+ dBdT_5 = dBdT(5)
+
+ CALL dewfraction (sigf,lai,sai,dewmx,ldew,ldew_rain,ldew_snow,fwet,fdry)
+
+ qsatl(0) = qroof
+ qsatldT(0) = dqroofDT
+ DO i = 1, nurb
+ CALL qsadv(tu(i),psrf,ei(i),deiDT(i),qsatl(i),qsatldT(i))
+ ENDDO
+
+ ! Save the longwave for the last time
+ dlwsun = lwsun
+ dlwsha = lwsha
+ dlgimp = lgimp
+ dlgper = lgper
+ dlveg = lveg
+
+!-----------------------------------------------------------------------
+! Calculate the weighted qg, tg, and wet fraction
+!-----------------------------------------------------------------------
+
+ ! weighted tg and qg
+ tg = tgimp*fgimp + tgper*fgper
+
+ ! wet fraction for roof and impervious ground
+ !-------------------------------------------
+ ! roof
+ IF (lbr < 1) THEN
+ fwet_roof_ = fsno_roof !for snow layer exist
+ ELSE
+ ! surface wet fraction. assuming max ponding = 1 kg/m2
+ fwet_roof_ = (max(0., wliq_roofsno+wice_roofsno))**(2/3.)
+ fwet_roof_ = min(1., fwet_roof_)
+ ENDIF
+
+ ! impervious ground
+ IF (lbi < 1) THEN
+ fwet_gimp_ = fsno_gimp !for snow layer exist
+ ELSE
+ ! surface wet fraction. assuming max ponding = 1 kg/m2
+ fwet_gimp_ = (max(0., wliq_gimpsno+wice_gimpsno))**(2/3.)
+ fwet_gimp_ = min(1., fwet_gimp_)
+ ENDIF
+
+ ! dew case
+ IF (qm > qroof) THEN
+ fwet_roof = 1.
+ ELSE
+ fwet_roof = fwet_roof_
+ ENDIF
+
+ ! dew case
+ IF (qm > qgimp) THEN
+ fwet_gimp = 1.
+ ELSE
+ fwet_gimp = fwet_gimp_
+ ENDIF
+
+ ! weighted qg
+ ! NOTE: IF fwet_gimp=1, same as previous
+ fwetfac = fgimp*fwet_gimp + fgper
+ qg = (qgimp*fgimp*fwet_gimp + qgper*fgper) / fwetfac
+
+
+!-----------------------------------------------------------------------
+! initial for fluxes profile
+!-----------------------------------------------------------------------
+
+ nmozsgn = 0 !number of times moz changes sign
+ obuold = 0. !monin-obukhov length from previous iteration
+ zii = 1000. !m (pbl height)
+ beta = 1. !- (in computing W_*)
+
+!-----------------------------------------------------------------------
+! scaling factor bee
+!-----------------------------------------------------------------------
+!NOTE: bee value, the default is 1
+ bee = 1.
+
+!-----------------------------------------------------------------------
+! calculate z0m and displa for layers
+!-----------------------------------------------------------------------
+
+ ! Calculate z0 and displa for vegetation only and the whole area
+ CALL cal_z0_displa(lsai, htop, 1., z0mv, displav)
+ CALL cal_z0_displa(lsai, htop, fc(3), z0mv_lay, displav_lay)
+
+ ! For building only below
+ ! Macdonald et al., 1998, Eq. (23), A=4.43
+ lambda = fcover(0)
+ displau = hroof * (1 + 4.43**(-lambda)*(lambda - 1))
+ fai = 4/PI*hlr*fcover(0)
+ z0mu = (hroof - displau) * &
+ exp( -(0.5*1.2/vonkar/vonkar*(1-displau/hroof)*fai)**(-0.5) )
+
+ ! account for vegetation
+ faiv = fc(3)*(1. - exp(-0.5*lsai))
+ lambda = fcover(0) + faiv*htop/hroof
+ displa = hroof * (1 + 4.43**(-lambda)*(lambda - 1))
+ displa = min(0.95*hroof, displa)
+ z0m = (hroof - displa) * &
+ exp( -(0.5*1.2/vonkar/vonkar*(1-displa/hroof)*(fai+faiv*htop/hroof))**(-0.5) )
+
+ ! to compare z0 of urban and only the surface
+ ! maximum assumption
+ IF (z0m < z0mg) z0m = z0mg
+ IF (displa >= hroof-z0mg) displa = hroof-z0mg
+
+ ! minimum building displa limit
+ displau = max(hroof/2., displau)
+
+ ! Layer setting
+ IF ( (.not.run_three_layer) .or. z0mv+displav > 0.5*(z0mu+displau) ) THEN
+ numlay = 2; botlay = 2; canlev(3) = 2
+ ELSE
+ numlay = 3; botlay = 1
+ ENDIF
+
+!-----------------------------------------------------------------------
+! calculate layer decay coefficient
+!-----------------------------------------------------------------------
+
+ ! Raupach, 1992
+ sqrtdragc = min( (0.003+0.3*faiv)**0.5, 0.3 )
+
+ ! Kondo, 1971
+ alphav = htop/(htop-displav_lay)/(vonkar/sqrtdragc)
+ alphav = alphav*htop/hroof
+
+ ! Masson, 2000; Oleson et al., 2008 plus tree (+)
+ IF (alpha_opt == 1) alpha = 0.5*hwr + alphav
+
+ ! Swaid, 1993; Kusaka, 2001; Lee and Park, 2008. plus tree (+)
+ IF (alpha_opt == 2) alpha = 0.772*hwr + alphav
+
+ ! Macdonald, 2000 plus tree (+)
+ IF (alpha_opt == 3) alpha = 9.6*fai + alphav
+
+!-----------------------------------------------------------------------
+! first guess for taf and qaf for each layer
+! a large differece from previous schemes
+!-----------------------------------------------------------------------
+ taf(:) = 0.
+ qaf(:) = 0.
+
+ IF (numlay .eq. 2) THEN
+ taf(3) = (tg + 2.*thm)/3.
+ qaf(3) = (qg + 2.*qm )/3.
+ taf(2) = (2.*tg + thm)/3.
+ qaf(2) = (2.*qg + qm )/3.
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+ taf(3) = (tg + 3.*thm)/4.
+ qaf(3) = (qg + 3.*qm )/4.
+ taf(2) = (tg + thm )/2.
+ qaf(2) = (qg + qm )/2.
+ taf(1) = (3.*tg + thm)/4.
+ qaf(1) = (3.*qg + qm )/4.
+ ENDIF
+
+!-----------------------------------------------------------------------
+! some environment variables
+! how to calculate rsoil and what is its usage?
+!-----------------------------------------------------------------------
+ pco2a = pco2m
+ tprcor = 44.6*273.16*psrf/1.013e5
+ rsoil = 0. !respiration (mol m-2 s-1)
+ !rsoil = 1.22e-6*exp(308.56*(1./56.02-1./(tg-227.13)))
+ !rsoil = rstfac * 0.23 * 15. * 2.**((tg-273.16-10.)/10.) * 1.e-6
+ !rsoil = 5.22 * 1.e-6
+ rsoil = 0.22 * 1.e-6
+
+! initialization and input values for Monin-Obukhov
+ ! have been set before
+ z0h = z0m; z0q = z0m
+ ur = max(0.1, sqrt(us*us+vs*vs)) !limit set to 0.1
+ dth = thm - taf(2)
+ dqh = qm - qaf(2)
+ dthv = dth*(1.+0.61*qm) + 0.61*th*dqh
+
+ hu_ = hu; ht_ = ht; hq_ = hq;
+
+ IF (trim(HEIGHT_mode) == 'absolute') THEN
+
+ IF (hu <= hroof+1) THEN
+ hu_ = hroof + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of u less than hroof+1, set it to hroof+1.'
+ ENDIF
+
+ IF (ht <= hroof+1) THEN
+ ht_ = hroof + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of t less than hroof+1, set it to hroof+1.'
+ ENDIF
+
+ IF (hq <= hroof+1) THEN
+ hq_ = hroof + 1.
+ IF (taux == spval) & ! only print warning for the first time-step
+ write(6,*) 'Warning: the obs height of q less than hroof+1, set it to hroof+1.'
+ ENDIF
+
+ ELSE ! relative height
+ hu_ = hroof + hu
+ ht_ = hroof + ht
+ hq_ = hroof + hq
+ ENDIF
+
+ zldis = hu_ - displa
+
+ IF (zldis <= 0.0) THEN
+ write(6,*) 'the obs height of u less than the zero displacement heght'
+ CALL abort
+ ENDIF
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0m,um,obu)
+
+! ======================================================================
+! BEGIN stability iteration
+! ======================================================================
+
+ DO WHILE (it .le. itmax)
+
+ tlbef = tl
+
+ del2 = del
+ dele2 = dele
+
+!-----------------------------------------------------------------------
+! Aerodynamical resistances
+!-----------------------------------------------------------------------
+! Evaluate stability-dependent variables using moz from prior iteration
+
+ CALL moninobukm(hu_,ht_,hq_,displa,z0m,z0h,z0q,obu,um, &
+ hroof,0.,ustar,fh2m,fq2m,hroof,fmtop,fm,fh,fq,fht,fqt,phih)
+
+! Aerodynamic resistance
+ ! 09/16/2017:
+ ! NOTE that for ram, it is the resistance from Href to z0m+displa
+ ! however, for rah and raw is only from Href to canopy effective
+ ! exchange height.
+ ! So rah/raw is not comparable with that of 1D case
+ ram = 1./(ustar*ustar/um)
+
+ ! 05/02/2016: calculate resistance from the top layer (effective
+ ! exchange height) to reference height.
+ ! For urban, from roof height to reference height
+ rah = 1./(vonkar/(fh-fht)*ustar)
+ raw = 1./(vonkar/(fq-fqt)*ustar)
+
+! update roughness length for sensible/latent heat
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ z0h = max(z0hg, z0h)
+ z0q = max(z0qg, z0q)
+
+!-----------------------------------------------------------------------
+! new method to calculate rd and ueffect
+! the kernel part of 3d model
+!-----------------------------------------------------------------------
+
+ ! initialization
+ rd(:) = 0.
+ rd_(:) = 0.
+ ueff_lay(:) = 0.
+ ueff_lay_(:) = 0.
+
+ ! calculate canopy top wind speed (utop) and exchange coefficient (ktop)
+ ! need to update each time as obu changed after each iteration
+ utop = ustar/vonkar * fmtop
+ ktop = vonkar * (hroof-displa) * ustar / phih
+
+ ueff_lay(3) = utop
+ ueff_lay_(3) = utop
+
+ ! NOTE: another calculation method for double-check
+ ! real(r8) FUNCTION kintegral(ktop, fc, bee, alpha, z0mg, displah, &
+ ! htop, hbot, obu, ustar, ztop, zbot)
+ ! rd_(3) = kintegral(ktop, 1., bee, alpha, z0mg, displa/hroof, &
+ ! hroof, 0., obug, ustarg, hroof, displau+z0mu)
+
+ ! real(r8) FUNCTION frd(ktop, htop, hbot, ztop, zbot, displah, z0h, &
+ ! obu, ustar, z0mg, alpha, bee, fc)
+ rd(3) = frd(ktop, hroof, 0., hroof, displau+z0mu, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! real(r8) FUNCTION uintegralz(utop, fc, bee, alpha, z0mg, htop, hbot, ztop, zbot)
+ ! ueff_lay(2) = uintegralz(utop, 1., bee, alpha, z0mg, hroof, 0., hroof, z0mg)
+
+ ! real(r8) FUNCTION ueffectz(utop, htop, hbot, ztop, zbot, z0mg, alpha, bee, fc)
+ ueff_lay(2) = ueffectz(utop, hroof, 0., hroof, z0mg, z0mg, alpha, bee, 1.)
+
+ IF (numlay == 3) THEN
+ ! real(r8) FUNCTION kintegral(ktop, fc, bee, alpha, z0mg, displah, &
+ ! htop, hbot, obu, ustar, ztop, zbot)
+ ! rd(2) = kintegral(ktop, 1., bee, alpha, z0mg, displa/hroof, &
+ ! hroof, 0., obug, ustarg, displau+z0mu, displav+z0mv)
+ rd(2) = frd(ktop, hroof, 0., displau+z0mu, displav+z0mv, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! rd(1) = kintegral(ktop, 1., bee, alpha, z0mg, displa/hroof, &
+ ! hroof, 0., obug, ustarg, displav+z0mv, z0qg)
+ rd(1) = frd(ktop, hroof, 0., displav+z0mv, z0qg, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! calculate ra2m, rd2m
+ ra2m = frd(ktop, hroof, 0., displav+z0mv, 2., displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ rd2m = frd(ktop, hroof, 0., 2., z0qg, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+ ELSE
+ ! rd_(2) = kintegral(ktop, 1., bee, alpha, z0mg, displa/hroof, &
+ ! hroof, 0., obug, ustarg, displau+z0mu, z0qg)
+ rd(2) = frd(ktop, hroof, 0., displau+z0mu, z0qg, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ ! calculate ra2m, rd2m
+ ra2m = frd(ktop, hroof, 0., displau+z0mu, 2., displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+
+ rd2m = frd(ktop, hroof, 0., 2., z0qg, displa/hroof, z0h_g, &
+ obug, ustarg, z0mg, alpha, bee, 1.)
+ ENDIF
+
+ ! ueff_lay(2) = uintegralz(utop, 1., bee, alpha, z0mg, hroof, 0., hroof, z0mg)
+ ! ueff_veg = uintegralz(utop, 1., bee, alpha, z0mg, hroof, 0., htop, hbot)
+
+ ! ueff_lay_(2) = ueffectz(utop, hroof, 0., hroof, z0mg, z0mg, alpha, bee, 1.)
+ ueff_veg = ueffectz(utop, hroof, 0., htop, hbot, z0mg, alpha, bee, 1.)
+
+ ! Masson, 2000: Account for different canyon orientations
+ ! 2/PI is a factor derived from 0-360deg integration
+ IF (alpha_opt == 1) THEN
+ ueff_lay(2) = 2/PI*ueff_lay(2)
+ ueff_veg = 2/PI*ueff_veg
+ rd(:) = PI/2*rd(:)
+ ENDIF
+
+!-----------------------------------------------------------------------
+! Bulk boundary layer resistance of leaves
+!-----------------------------------------------------------------------
+
+ rb(:) = 0.
+
+ DO i = 0, nurb
+
+ IF (i == 3) THEN
+ cf = 0.01*sqrtdi*sqrt(ueff_veg)
+ rb(i) = 1./cf
+ CYCLE
+ ENDIF
+
+ clev = canlev(i)
+ rb(i) = rhoair * cpair / ( 11.8 + 4.2*ueff_lay(clev) )
+
+ ! Cole & Sturrock (1977) Building and Environment, 12, 207-214.
+ ! rb(i) = rhoair * cpair / ( 5.8 + 4.1*ueff_lay(clev) )
+ ! IF (ueff_lay(clev) > 5.) THEN
+ ! rb(i) = rhoair * cpair / (7.51*ueff_lay(clev)**0.78)
+ ! ELSE
+ ! rb(i) = rhoair * cpair / (5.8 + 4.1*ueff_lay(clev))
+ ! ENDIF
+ ! rb(i) = rhoair * cpair &
+ ! / ( cpair*vonkar*vonkar*ueff_lay(clev)&
+ ! / (log(0.1*hroof/)*(2.3+log(0.1*hroof/))) )
+ ENDDO
+
+!-----------------------------------------------------------------------
+! stomatal resistances
+!-----------------------------------------------------------------------
+
+ IF (lai > 0.) THEN
+
+ clev = canlev(3)
+ eah = qaf(clev) * psrf / ( 0.622 + 0.378 * qaf(clev) ) !pa
+
+!-----------------------------------------------------------------------
+! note: calculate resistance for leaves
+!-----------------------------------------------------------------------
+
+ CALL stomata (vmax25,effcon ,c3c4 ,slti ,hlti ,&
+ shti ,hhti ,trda ,trdm ,trop ,&
+ g1 ,g0 ,gradm ,binter ,thm ,&
+ psrf ,po2m ,pco2m ,pco2a ,eah ,&
+ ei(3) ,tu(3) ,par ,&
+ o3coefv ,o3coefg ,lambda_wue ,&
+ rb(3)/lai,raw ,rstfac ,cint(:),&
+ assim ,respc ,rs &
+ )
+
+ rs_ = rs
+
+IF ( DEF_URBAN_Irrigation .and. rstfac < rstfac_irrig ) THEN
+ CALL stomata (vmax25,effcon ,c3c4 ,slti ,hlti ,&
+ shti ,hhti ,trda ,trdm ,trop ,&
+ g1 ,g0 ,gradm ,binter ,thm ,&
+ psrf ,po2m ,pco2m ,pco2a ,eah ,&
+ ei(3) ,tu(3) ,par ,&
+ o3coefv ,o3coefg ,lambda_wue ,&
+ rb(3)/lai,raw ,rstfac_irrig ,cint(:),&
+ assim ,respc ,rs &
+ )
+ENDIF
+ ELSE
+ rs = 2.e4; assim = 0.; respc = 0.
+ ENDIF
+
+! above stomatal resistances are for the canopy, the stomatal rsistances
+! and the "rb" in the following calculations are the average for single leaf. thus,
+ rs = rs * lai
+ rs_= rs_* lai
+
+! calculate latent heat resistances
+ clev = canlev(3)
+ delta = 0.0
+ IF (qsatl(3)-qaf(clev) .gt. 0.) delta = 1.0
+
+ rv = 1/( (1.-delta*(1.-fwet))*lsai/rb(3) &
+ + (1.-fwet)*delta*(lai/(rb(3)+rs)) )
+
+!-----------------------------------------------------------------------
+! Solve taf(:) and qaf(:)
+!-----------------------------------------------------------------------
+
+ IF (numlay .eq. 2) THEN
+
+ ! - Equations:
+ ! taf(3) = (1/rah*thm + 1/rd(3)*taf(2) + 1/rb(0)*troof*fc(0) &
+ ! + AHE/(rho*cp))/(1/rah + 1/rd(3) + 1/rb(0)*fc(0))
+ ! taf(2) = (1/rd(3)*taf(3) + 1/rd(2)*tg*fg + 1/rb(1)*twsun*fc(1) + 1/rb(2)*twsha*fc(2) &
+ ! + lsai/rb(3)*tl*fc(3) + AHE/(rho*cp)) &
+ ! / (1/rd(3) + 1/rd(2)*fg + 1/rb(1)*fc(1) + 1/rb(2)*fc(2) + lsai/rb(3)*fc(3))
+ !
+ ! Also written as:
+ ! taf(3) = (cah(3)*thm + cah(2)*taf(2) &
+ ! + cfh(0)*troof*fc(0))/(cah(3) + cah(2) + cfh(0)*fc(0))
+ ! taf(2) = (cah(2)*taf(3) + cgh(2)*tg*fg + cfh(1)*twsun*fc(1) + cfh(2)*twsha*fc(2) &
+ ! + cfh(3)*tl*fc(3) + AHE/(rho*cp)) &
+ ! / (cah(2) + cgh(2)*fg + cfh(1)*fc(1) + cfh(2)*fc(2) + cfh(3)*fc(3))
+ !
+ ! - Equations:
+ ! qaf(3) = (1/raw*qm + 1/rd(3)*qaf(2) &
+ ! + 1/rb(0)*qroof*fc(0))/(1/raw + 1/rd(3) + 1/rb(0)*fc(0))
+ ! qaf(2) = (1/rd(3)*qaf(3) + 1/(rd(2)+rss)*qper*fgper*fg + fwetimp/rd(2)*qimp*fgimp*fg &
+ ! + lsai/(rb(3)+rs)*ql*fc(3) + AHE/rho) &
+ ! / (1/rd(3) + 1/(rd(2)+rss)*fgper*fg &
+ ! + fwetimp/rd(2)*fgimp*fg + lsai/(rb(3)+rs)*fc(3))
+ !
+ ! Also written as:
+ ! qaf(3) = (caw(3)*qm + caw(2)*qaf(2) + cfw(0)*qroof*fc(0)) &
+ ! / (caw(3) + caw(2) + cfw(0)*fc(0))
+ ! qaf(2) = (caw(2)*qaf(3) + cgwper*qper*fgper*fg + cgwimp*qimp*fgimp*fg &
+ ! + cfw(3)*ql*fc(3) + AHE/rho) &
+ ! / (caw(2) + cgwper*fgper*fg + cgwimp*fgimp*fg + cfw(3)*fc(3))
+
+ ! 06/20/2021, yuan: account for Anthropogenic heat
+ ! 92% heat release as SH, Pigeon et al., 2007
+
+ Hahe(2) = 4*hlr/(4*hlr+1)*(Fhac+Fwst)*fsh + Fach + vehc*fsh + meta
+ Hahe(3) = 1/(4*hlr+1)*(Fhac+Fwst)*fsh
+
+ bT = 1/(rd(3) * (1/rah+1/rd(3)+fc(0)/rb(0)))
+ cT = 1/rd(3) + fg/rd(2) + fc(1)/rb(1) + fc(2)/rb(2) + fc(3)*lsai/rb(3)
+ aT = (tu(0)*fc(0)/rb(0) + Hahe(3)/(rhoair*cpair) + thm/rah)*bT
+
+ taf(2) = (tg*fg/rd(2) + Hahe(2)/(rhoair*cpair) + tu(1)*fc(1)/rb(1) + tu(2)*fc(2)/rb(2) &
+ + tu(3)*fc(3)*lsai/rb(3) + aT) / (cT * (1- bT/(cT*rd(3))))
+
+ taf(3) = (taf(2)/rd(3) + tu(0)*fc(0)/rb(0) + Hahe(3)/(rhoair*cpair) + thm/rah) &
+ / (1/rah + 1/rd(3) + fc(0)/rb(0))
+
+ IF (qgper < qaf(2)) THEN
+ ! dew case. no soil resistance
+ rss_ = 0
+ ELSE
+ rss_ = rss
+ ENDIF
+
+ Lahe = (Fhac + Fwst + vehc)*flh
+ cQ = 1/rd(3) + fg*fgper/(rd(2)+rss_) + fwet_gimp*fg*fgimp/rd(2) + fc(3)/rv
+ bQ = 1/(rd(3) * (1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+ aQ = (qsatl(0)*fwet_roof*fc(0)/rb(0) + qm/raw)*bQ
+
+ qaf(2) = (qgper*fgper*fg/(rd(2)+rss_) + qgimp*fwet_gimp*fgimp*fg/rd(2) &
+ + qsatl(3)*fc(3)/rv + aQ + Lahe/rhoair/hvap) &
+ / (cQ * (1-bQ/(cQ*rd(3))))
+
+ qaf(3) = (qaf(2)/rd(3) + qsatl(0)*fwet_roof*fc(0)/rb(0) + qm/raw) &
+ / (1/raw + 1/rd(3) + fwet_roof*fc(0)/rb(0))
+
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+
+ ! - Equations:
+ ! taf(3) = (thm/rah+1/rd(3)*taf(2)+AHE2/rho/cpair+1/rb(0)*troof*fc(0))/&
+ ! (1/rah+1/rd(3)+1/rb(0)*fc(0))
+ ! taf(2) = (1/rd(3)*taf(3)+1/rd(2)*taf1+1/rb(1)*twsun*fc(1)+1/rb(2)*twsha*fc(2)+&
+ ! AHE1/rho/cpair)/(1/rd(3)+1/rd(2)+1/rb(1)*fc(1)+1/rb(2)*fc(2))
+ ! taf(1) = (1/rd(2)*taf(2)+1/rd(1)*tg*fg+1/rb(3)*tl*fc(3)+Hveh/rhoair/cpair)/&
+ ! (1/rd(2)+1/rd(1)*fg+1/rb(3)*fc(3))
+ !
+ ! - Equations:
+ ! qaf(3) = (1/raw*qm+1/rd(3)*qaf(2)+1/rb(0)*qroof*fc(0))/&
+ ! (1/raw+1/rd(3)+1/rb(0)*fc(0))
+ ! qaf(2) = (1/rd(3)*qaf(3)+1/rd(2)*qaf(1))/&
+ ! (1/rd(3) + 1/rd(2))
+ ! qaf(1) = (1/rd(2)*qaf(2)+1/(rd(1)+rss)*qgper*fgper*fg+&
+ ! 1/rd(1)*qimp*fgimp*fg+1/(rb(3)+rs)*ql*fc(3)+h_veh/rho)/&
+ ! (1/rd(2)+1/(rd(1)+rss)*fgper*fg+1/rd(1)*fgimp*fg+1/(rb(3)+rs)*fc(3))
+
+ Hahe(1) = vehc*fsh + meta
+ Hahe(2) = 4*hlr/(4*hlr+1)*(Fhac+Fwst)*fsh + Fach
+ Hahe(3) = 1/(4*hlr+1)*(Fhac+Fwst)*fsh
+
+ cT = 1/rd(3) + 1/rd(2) + fc(1)/rb(1) + fc(2)/rb(2)
+ at = 1/(rd(2)*(1/rd(2)+fg/rd(1)+fc(3)*lsai/rb(3)))
+ bT = 1/(rd(3)*(1/rah+1/rd(3)+fc(0)/rb(0)))
+
+ taf(2) = (tu(1)*fc(1)/rb(1) + tu(2)*fc(2)/rb(2) &
+ + (tu(3)*fc(3)*lsai/rb(3)+tg*fg/rd(1)+Hahe(1)/(rhoair*cpair))*aT &
+ + (tu(0)*fc(0)/rb(0)+thm/rah+Hahe(3)/(rhoair*cpair))*bT &
+ + Hahe(2)/(rhoair*cpair)) &
+ / (cT*(1-aT/(rd(2)*cT)-bT/(rd(3)*cT)))
+
+ taf(1) = (tu(3)*fc(3)*lsai/rb(3) + tg*fg/rd(1) + taf(2)/rd(2) &
+ + Hahe(1)/(rhoair*cpair)) / (1/rd(2)+fg/rd(1)+fc(3)*lsai/rb(3))
+
+ taf(3) = (tu(0)*fc(0)/rb(0) + taf(2)/rd(3) + thm/rah + Hahe(3)/(rhoair*cpair)) &
+ / (1/rah+1/rd(3)+fc(0)/rb(0))
+
+ IF (qgper < qaf(1)) THEN
+ ! dew case. no soil resistance
+ rss_ = 0
+ ELSE
+ rss_ = rss
+ ENDIF
+
+ Lahe = (Fhac + Fwst + vehc)*flh
+ cQ = 1/rd(3) + 1/rd(2)
+ bQ = 1/(rd(3)*(1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+ aQ = 1/(rd(2)*(1/rd(2)+fg*fgimp*fwet_gimp/rd(1)+fg*fgper/(rd(1)+rss_)+fc(3)/rv))
+
+ qaf(2) = ( (fg*fgimp*fwet_gimp*qgimp/rd(1) + fg*fgper*qgper/(rd(1)+rss_) &
+ + fc(3)*qsatl(3)/rv + Lahe/rhoair/hvap)*aQ &
+ + (qm/raw+fc(0)*fwet_roof*qsatl(0)/rb(0))*bQ ) &
+ / ( cQ*(1-bQ/(cQ*rd(3))-aQ/(cQ*rd(2))) )
+
+ qaf(1) = ( fg*fgimp*fwet_gimp*qgimp/rd(1) + fg*fgper*qgper/(rd(1)+rss_) &
+ + fc(3)*qsatl(3)/rv + qaf(2)/rd(2) + Lahe/rhoair/hvap ) &
+ / ( 1/rd(2) + fg*fgimp*fwet_gimp/rd(1) + fg*fgper/(rd(1)+rss_) + fc(3)/rv )
+
+ qaf(3) = ( fc(0)*fwet_roof*qsatl(0)/rb(0) + qaf(2)/rd(3) + qm/raw ) &
+ / ( 1/raw + 1/rd(3)+ fwet_roof*fc(0)/rb(0) )
+ ENDIF
+
+!-----------------------------------------------------------------------
+! IR radiation, sensible and latent heat fluxes and their derivatives
+!-----------------------------------------------------------------------
+! the partial derivatives of areodynamical resistance are ignored
+! which cannot be determined analytically
+
+ !NOTE: ONLY for vegetation
+ i = 3
+
+! sensible heat fluxes and their derivatives
+ fsenl = rhoair * cpair * lsai/rb(3) * (tl - taf(botlay))
+
+ IF (botlay == 2) THEN
+ fsenl_dtl = rhoair * cpair * lsai/rb(3) &
+ * ( 1. - fc(3)*lsai/(rb(3)*cT*(1-bT/(cT*rd(3)))) )
+ ELSE
+ fsenl_dtl = rhoair * cpair * lsai/rb(3) &
+ * ( 1. - fc(3)*lsai/(rb(3)*(1/rd(2)+fg/rd(1)+fc(3)*lsai/rb(3))) &
+ - fc(3)*lsai*aT*aT/(rb(3)*cT*(1-aT/(cT*rd(2))-bT/(cT*rd(3)))) )
+ ENDIF
+
+
+! latent heat fluxes and their derivatives
+ etr = rhoair * (1.-fwet) * delta * lai/(rb(i)+rs) &
+ * (qsatl(i) - qaf(botlay))
+
+ IF (botlay == 2) THEN
+ etr_dtl = rhoair * (1.-fwet) * delta * lai/(rb(3)+rs) &
+ * (1.-fc(3)/(cQ*rv*(1-bQ/(cQ*rd(3))))) &
+ * qsatldT(3)
+ ELSE
+ etr_dtl = rhoair * (1.-fwet) * delta * lai/(rb(i)+rs) &
+ * ( 1. - fc(3)/(rv*(1/rd(2) + fg*fgimp*fwet_gimp/rd(1) + &
+ fg*fgper/(rss_+rd(1)) + fc(3)/rv)) &
+ - fc(3)*aQ*aQ/(rv*cQ*(1-aQ/(cQ*rd(2))-bQ/(cQ*rd(3)))) )
+ ENDIF
+
+IF ( DEF_URBAN_Irrigation ) THEN
+ IF (etr.ge.trsmx0*rstfac_irrig) THEN
+ etr = trsmx0*rstfac_irrig
+ etr_dtl = 0.
+ ENDIF
+ELSE
+ IF (etr.ge.etrc) THEN
+ etr = etrc
+ etr_dtl = 0.
+ ENDIF
+ENDIF
+
+ evplwet = rhoair * (1.-delta*(1.-fwet)) * lsai/rb(i) &
+ * (qsatl(i) - qaf(botlay))
+
+ IF (botlay == 2) THEN
+ evplwet_dtl = rhoair * (1.-delta*(1.-fwet)) * lsai/rb(3) &
+ * (1.-fc(3)/(cQ*rv*(1-bQ/(cQ*rd(3))))) &
+ * qsatldT(3)
+ ELSE
+ evplwet_dtl = rhoair * (1.-delta*(1.-fwet)) * lsai/rb(i) &
+ * ( 1. - fc(3)/(rv*(1/rd(2) + fg*fgimp*fwet_gimp/rd(1) + &
+ fg*fgper/(rss_+rd(1)) + fc(3)/rv)) &
+ - fc(3)*aQ*aQ/(rv*CQ*(1-aQ/(cQ*rd(2))-bQ/(cQ*rd(3)))) )
+ ENDIF
+
+ IF (evplwet.ge.ldew/deltim) THEN
+ evplwet = ldew/deltim
+ evplwet_dtl = 0.
+ ENDIF
+
+ fevpl = etr + evplwet
+ fevpl_dtl = etr_dtl + evplwet_dtl
+
+ erre = 0.
+ fevpl_noadj = fevpl
+ IF ( fevpl*fevpl_bef < 0. ) THEN
+ erre = -0.9*fevpl
+ fevpl = 0.1*fevpl
+ ENDIF
+
+IF ( DEF_URBAN_Irrigation ) THEN
+ etr_= rhoair * (1.-fwet) * delta * lai/(rb(i)+rs_) &
+ * (qsatl(i) - qaf(botlay))
+
+ IF (etr_.ge.etrc) THEN
+ etr_ = etrc
+ ENDIF
+ENDIF
+
+
+!-----------------------------------------------------------------------
+! difference of temperatures by quasi-newton-raphson method for the non-linear system equations
+!-----------------------------------------------------------------------
+
+ ! calculate irab, dirab_dtl
+ B(5) = B_5*tl**4
+ B1(5) = B1_5*tl**4
+ dBdT(5) = dBdT_5*tl**3
+ X = matmul(Ainv, B)
+ ! first 5 items of dBdT is 0, dBdT*(0,0,0,0,0,1)
+ dX = matmul(Ainv, dBdT*uvec)
+
+ ! calculate longwave for vegetation
+ irab = ( (sum(X(1:4)*VegVF(1:4)) + frl*VegVF(5))*ev - B1(5) ) / fcover(5)*fg
+ irab = irab + dlveg ! plus the previous step dlveg
+ dirab_dtl = ( sum(dX(1:4)*VegVF(1:4))*ev - dBdT(5) ) / fcover(5)*fg
+
+ ! solve for leaf temperature
+ dtl(it) = (sabv + irab - fsenl - hvap*fevpl) &
+ / (clai/deltim - dirab_dtl + fsenl_dtl + hvap*fevpl_dtl)
+ dtl_noadj = dtl(it)
+
+ ! check magnitude of change in leaf temperature limit to maximum allowed value
+
+ IF (it .le. itmax) THEN
+
+ ! put brakes on large temperature excursions
+ IF (abs(dtl(it)).gt.delmax) THEN
+ dtl(it) = delmax*dtl(it)/abs(dtl(it))
+ ENDIF
+
+ IF ((it.ge.2) .and. (dtl(it-1)*dtl(it).le.0.)) THEN
+ dtl(it) = 0.5*(dtl(it-1) + dtl(it))
+ ENDIF
+
+ ENDIF
+
+ tl = tlbef + dtl(it)
+ tu(3) = tl
+
+!-----------------------------------------------------------------------
+! square roots differences of temperatures and fluxes for use as the condition of convergences
+!-----------------------------------------------------------------------
+
+ del = sqrt( dtl(it)*dtl(it) )
+ dele = dtl(it) * dtl(it) * &
+ ( dirab_dtl**2 + fsenl_dtl**2 + (hvap*fevpl_dtl)**2 )
+ dele = sqrt(dele)
+
+!-----------------------------------------------------------------------
+! saturated vapor pressures and canopy air temperature, canopy air humidity
+!-----------------------------------------------------------------------
+! Recalculate leaf saturated vapor pressure (ei_)for updated leaf temperature
+! and adjust specific humidity (qsatl_) proportionately
+ CALL qsadv(tu(i),psrf,ei(i),deiDT(i),qsatl(i),qsatldT(i))
+
+! update vegetation/ground surface temperature, canopy air temperature,
+! canopy air humidity
+
+ IF (numlay .eq. 2) THEN
+
+ ! - Equations:
+ ! taf(3) = (1/rah*thm + 1/rd(3)*taf(2) + 1/rb(0)*troof*fc(0) &
+ ! + AHE/(rho*cp))/(1/rah + 1/rd(3) + 1/rb(0)*fc(0))
+ ! taf(2) = (1/rd(3)*taf(3) + 1/rd(2)*tg*fg + 1/rb(1)*twsun*fc(1) + 1/rb(2)*twsha*fc(2) &
+ ! + lsai/rb(3)*tl*fc(3) + AHE/(rho*cp)) &
+ ! / (1/rd(3) + 1/rd(2)*fg + 1/rb(1)*fc(1) + 1/rb(2)*fc(2) + lsai/rb(3)*fc(3))
+ !
+ ! Also written as:
+ ! taf(3) = (cah(3)*thm + cah(2)*taf(2) &
+ ! + cfh(0)*troof*fc(0))/(cah(3) + cah(2) + cfh(0)*fc(0))
+ ! taf(2) = (cah(2)*taf(3) + cgh(2)*tg*fg + cfh(1)*twsun*fc(1) &
+ ! + cfh(2)*twsha*fc(2) + cfh(3)*tl*fc(3) + AHE/(rho*cp)) &
+ ! / (cah(2) + cgh(2)*fg + cfh(1)*fc(1) + cfh(2)*fc(2) + cfh(3)*fc(3))
+ !
+ ! - Equations:
+ ! qaf(3) = (1/raw*qm + 1/rd(3)*qaf(2) &
+ ! + 1/rb(0)*qroof*fc(0))/(1/raw + 1/rd(3) + 1/rb(0)*fc(0))
+ ! qaf(2) = (1/rd(3)*qaf(3) + 1/(rd(2)+rss)*qper*fgper*fg &
+ ! + fwetimp/rd(2)*qimp*fgimp*fg + lsai/(rb(3)+rs)*ql*fc(3) + AHE/rho) &
+ ! / (1/rd(3) + 1/(rd(2)+rss)*fgper*fg &
+ ! + fwetimp/rd(2)*fgimp*fg + lsai/(rb(3)+rs)*fc(3))
+ !
+ ! Also written as:
+ ! qaf(3) = (caw(3)*qm + caw(2)*qaf(2) &
+ ! + cfw(0)*qroof*fc(0))/(caw(3) + caw(2) + cfw(0)*fc(0))
+ ! qaf(2) = (caw(2)*qaf(3) + cgwper*qper*fgper*fg + cgwimp*qimp*fgimp*fg &
+ ! + cfw(3)*ql*fc(3) + AHE/rho) &
+ ! / (caw(2) + cgwper*fgper*fg + cgwimp*fgimp*fg + cfw(3)*fc(3))
+
+ ! 06/20/2021, yuan: account for AH
+ ! 92% heat release as SH, Pigeon et al., 2007
+
+ Hahe(2) = 4*hlr/(4*hlr+1)*(Fhac+Fwst)*fsh + Fach + vehc*fsh + meta
+ Hahe(3) = 1/(4*hlr+1)*(Fhac+Fwst)*fsh
+
+ bT = 1/(rd(3) * (1/rah+1/rd(3)+fc(0)/rb(0)))
+ cT = 1/rd(3) + fg/rd(2) + fc(1)/rb(1) + fc(2)/rb(2) + fc(3)*lsai/rb(3)
+ aT = (tu(0)*fc(0)/rb(0) + Hahe(3)/(rhoair*cpair) + thm/rah)*bT
+
+ taf(2) = (tg*fg/rd(2) + Hahe(2)/(rhoair*cpair) + tu(1)*fc(1)/rb(1) + tu(2)*fc(2)/rb(2) &
+ + tu(3)*fc(3)*lsai/rb(3) + aT) / (cT * (1- bT/(cT*rd(3))))
+
+ taf(3) = (taf(2)/rd(3) + tu(0)*fc(0)/rb(0) + Hahe(3)/(rhoair*cpair) + thm/rah) &
+ / (1/rah + 1/rd(3) + fc(0)/rb(0))
+
+ IF (qgper < qaf(2)) THEN
+ ! dew case. no soil resistance
+ rss_ = 0
+ ELSE
+ rss_ = rss
+ ENDIF
+
+ Lahe = (Fhac + Fwst + vehc)*flh
+ cQ = 1/rd(3) + fg*fgper/(rd(2)+rss_) + fwet_gimp*fg*fgimp/rd(2) + fc(3)/rv
+ bQ = 1/(rd(3) * (1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+ aQ = (qsatl(0)*fwet_roof*fc(0)/rb(0) + qm/raw)*bQ
+
+ qaf(2) = (qgper*fgper*fg/(rd(2)+rss_) + qgimp*fwet_gimp*fgimp*fg/rd(2) &
+ + qsatl(3)*fc(3)/rv + aQ + Lahe/rhoair/hvap) / (cQ * (1-bQ/(cQ*rd(3))))
+
+ qaf(3) = (qaf(2)/rd(3) + qsatl(0)*fwet_roof*fc(0)/rb(0) + qm/raw) &
+ / (1/raw + 1/rd(3) + fwet_roof*fc(0)/rb(0))
+
+ ENDIF
+
+ IF (numlay .eq. 3) THEN
+
+ ! - Equations:
+ ! taf(3) = (thm/rah+1/rd(3)*taf(2)+AHE2/rho/cpair+1/rb(0)*troof*fc(0))/&
+ ! (1/rah+1/rd(3)+1/rb(0)*fc(0))
+ ! taf(2) = (1/rd(3)*taf(3)+1/rd(2)*taf1+1/rb(1)*twsun*fc(1)+1/rb(2)*twsha*fc(2)+&
+ ! AHE1/rho/cpair)/(1/rd(3)+1/rd(2)+1/rb(1)*fc(1)+1/rb(2)*fc(2))
+ ! taf(1) = (1/rd(2)*taf(2)+1/rd(1)*tg*fg+1/rb(3)*tl*fc(3)+Hveh/rhoair/cpair)/&
+ ! (1/rd(2)+1/rd(1)*fg+1/rb(3)*fc(3))
+ !
+ ! - Equations:
+ ! qaf(3) = (1/raw*qm+1/rd(3)*qaf(2)+1/rb(0)*qroof*fc(0))/&
+ ! (1/raw+1/rd(3)+1/rb(0)*fc(0))
+ ! qaf(2) = (1/rd(3)*qaf(3)+1/rd(2)*qaf(1))/&
+ ! (1/rd(3) + 1/rd(2))
+ ! qaf(1) = (1/rd(2)*qaf(2)+1/(rd(1)+rss)*qgper*fgper*fg+&
+ ! 1/rd(1)*qimp*fgimp*fg+1/(rb(3)+rs)*ql*fc(3)+h_veh/rho))/&
+ ! (1/rd(2)+1/(rd(1)+rss)*fgper*fg+1/rd(1)*fgimp*fg+1/(rb(3)+rs)*fc(3))
+
+ Hahe(1) = vehc*fsh + meta
+ Hahe(2) = 4*hlr/(4*hlr+1)*(Fhac+Fwst)*fsh + Fach
+ Hahe(3) = 1/(4*hlr+1)*(Fhac+Fwst)*fsh
+
+ cT = 1/rd(3) + 1/rd(2) + fc(1)/rb(1) + fc(2)/rb(2)
+ at = 1/(rd(2)*(1/rd(2)+fg/rd(1)+fc(3)*lsai/rb(3)))
+ bT = 1/(rd(3)*(1/rah+1/rd(3)+fc(0)/rb(0)))
+
+ taf(2) = (tu(1)*fc(1)/rb(1) + tu(2)*fc(2)/rb(2) &
+ + (tu(3)*fc(3)*lsai/rb(3)+tg*fg/rd(1)+Hahe(1)/(rhoair*cpair))*aT &
+ + (tu(0)*fc(0)/rb(0)+thm/rah+Hahe(3)/(rhoair*cpair))*bT &
+ + Hahe(2)/(rhoair*cpair)) / (cT*(1-aT/(rd(2)*cT)-bT/(rd(3)*cT)))
+
+ taf(1) = (tu(3)*fc(3)*lsai/rb(3) + tg*fg/rd(1) + taf(2)/rd(2) &
+ + Hahe(1)/(rhoair*cpair)) / (1/rd(2)+fg/rd(1)+fc(3)*lsai/rb(3))
+
+ taf(3) = (tu(0)*fc(0)/rb(0) + taf(2)/rd(3) + thm/rah + Hahe(3)/(rhoair*cpair)) &
+ / (1/rah+1/rd(3)+fc(0)/rb(0))
+
+ IF (qgper < qaf(1)) THEN
+ ! dew case. no soil resistance
+ rss_ = 0
+ ELSE
+ rss_ = rss
+ ENDIF
+
+ Lahe = (Fhac + Fwst + vehc)*flh
+ cQ = 1/rd(3) + 1/rd(2)
+ bQ = 1/(rd(3)*(1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+ aQ = 1/(rd(2)*(1/rd(2)+fg*fgimp*fwet_gimp/rd(1)+fg*fgper/(rd(1)+rss_)+fc(3)/rv))
+
+ qaf(2) = ((fg*fgimp*fwet_gimp*qgimp/rd(1)+fg*fgper*qgper/(rd(1)+rss_) &
+ + fc(3)*qsatl(3)/rv+Lahe/rhoair/hvap)*aQ &
+ + (qm/raw+fc(0)*fwet_roof*qsatl(0)/rb(0))*bQ) &
+ / (cQ*(1-bQ/(cQ*rd(3))-aQ/(cQ*rd(2))))
+
+ qaf(1) = (fg*fgimp*fwet_gimp*qgimp/rd(1)+fg*fgper*qgper/(rd(1)+rss_) &
+ + fc(3)*qsatl(3)/rv+qaf(2)/rd(2)+Lahe/rhoair/hvap) &
+ /(1/rd(2)+fg*fgimp*fwet_gimp/rd(1)+fg*fgper/(rd(1)+rss_)+fc(3)/rv)
+
+ qaf(3) = (fc(0)*fwet_roof*qsatl(0)/rb(0)+qaf(2)/rd(3)+qm/raw) &
+ /(1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0))
+
+ ENDIF
+
+ !------------------------------------------------
+ ! account for fwet for roof and impervious ground
+ IF (qaf(3) > qroof) THEN
+ fwet_roof = 1. !dew case
+ ELSE
+ fwet_roof = fwet_roof_
+ ENDIF
+
+ IF (qaf(botlay) > qgimp) THEN
+ fwet_gimp = 1. !dew case
+ ELSE
+ fwet_gimp = fwet_gimp_
+ ENDIF
+
+ ! weighted qg
+ ! NOTE: IF fwet_gimp=1, same as previous
+ fwetfac = fgimp*fwet_gimp + fgper
+ qg = (qgimp*fgimp*fwet_gimp + qgper*fgper) / fwetfac
+
+ fgw(2) = fg*fwetfac
+
+! update co2 partial pressure within canopy air
+ ! 05/02/2016: may have some problem with gdh2o, however,
+ ! this variable seems never used here. Different height
+ ! level vegetation should have different gdh2o, i.e.,
+ ! different rd(layer) values.
+ gah2o = 1.0/raw * tprcor/thm !mol m-2 s-1
+ gdh2o = 1.0/rd(botlay) * tprcor/thm !mol m-2 s-1
+
+ pco2a = pco2m - 1.37*psrf/max(0.446,gah2o) * &
+ (assim - respc - rsoil)
+
+!-----------------------------------------------------------------------
+! Update monin-obukhov length and wind speed including the stability effect
+!-----------------------------------------------------------------------
+
+ ! USE the top layer taf and qaf
+ dth = thm - taf(2)
+ dqh = qm - qaf(2)
+
+ tstar = vonkar/(fh)*dth
+ qstar = vonkar/(fq)*dqh
+
+ thvstar = tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta = zldis*vonkar*grav*thvstar / (ustar**2*thv)
+ IF (zeta .ge. 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF (zeta .ge. 0.) THEN
+ um = max(ur,.1)
+ ELSE
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu .lt. 0.) nmozsgn = nmozsgn+1
+ IF (nmozsgn .ge. 4) obu = zldis/(-0.01)
+ obuold = obu
+
+!-----------------------------------------------------------------------
+! Test for convergence
+!-----------------------------------------------------------------------
+
+ it = it+1
+
+ IF (it .gt. itmin) THEN
+ fevpl_bef = fevpl
+ det = max(del,del2)
+ dee = max(dele,dele2)
+ IF (det .lt. dtmin .and. dee .lt. dlemin) EXIT
+ ENDIF
+
+ ENDDO
+
+! ======================================================================
+! END stability iteration
+! ======================================================================
+
+ zol = zeta
+ rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+! canopy fluxes and total assimilation amd respiration
+
+ IF (lai .gt. 0.001) THEN
+ rst = rs/lai
+ ELSE
+ rs = 2.0e4
+ assim = 0.
+ respc = 0.
+ rst = 2.0e4
+ ENDIF
+ respc = respc + rsoil
+
+IF ( DEF_URBAN_Irrigation ) THEN
+ etr_deficit = max(0., etr - etr_)
+ENDIF
+
+! canopy fluxes and total assimilation and respiration
+
+ fsenl = fsenl + fsenl_dtl*dtl(it-1) &
+ ! add the imbalanced energy below due to T adjustment to sensible heat
+ + (dtl_noadj-dtl(it-1)) * (clai/deltim - dirab_dtl &
+ + fsenl_dtl + hvap*fevpl_dtl) &
+ ! add the imbalanced energy below due to q adjustment to sensible heat
+ + hvap*erre
+
+ etr = etr + etr_dtl*dtl(it-1)
+ evplwet = evplwet + evplwet_dtl*dtl(it-1)
+ fevpl = fevpl_noadj
+ fevpl = fevpl + fevpl_dtl*dtl(it-1)
+
+ elwmax = ldew/deltim
+
+ elwdif = max(0., evplwet-elwmax)
+ evplwet = min(evplwet, elwmax)
+
+ fevpl = fevpl - elwdif
+ fsenl = fsenl + hvap*elwdif
+
+
+!-----------------------------------------------------------------------
+! Update dew accumulation (kg/m2)
+!-----------------------------------------------------------------------
+
+ ldew = max(0., ldew-evplwet*deltim)
+
+ ! account for vegetation snow and update ldew_rain, ldew_snow, ldew
+ IF ( DEF_VEG_SNOW ) THEN
+ IF (tl > tfrz) THEN
+ qevpl = max (evplwet, 0.)
+ qdewl = abs (min (evplwet, 0.) )
+ qsubl = 0.
+ qfrol = 0.
+
+ IF (qevpl > ldew_rain/deltim) THEN
+ qsubl = qevpl - ldew_rain/deltim
+ qevpl = ldew_rain/deltim
+ ENDIF
+ ELSE
+ qevpl = 0.
+ qdewl = 0.
+ qsubl = max (evplwet, 0.)
+ qfrol = abs (min (evplwet, 0.) )
+
+ IF (qsubl > ldew_snow/deltim) THEN
+ qevpl = qsubl - ldew_snow/deltim
+ qsubl = ldew_snow/deltim
+ ENDIF
+ ENDIF
+
+ ldew_rain = ldew_rain + (qdewl-qevpl)*deltim
+ ldew_snow = ldew_snow + (qfrol-qsubl)*deltim
+
+ ldew = ldew_rain + ldew_snow
+ ENDIF
+
+ IF ( DEF_VEG_SNOW ) THEN
+ ! update fwet_snow
+ fwet_snow = 0
+ IF(ldew_snow > 0.) THEN
+ fwet_snow = ((10./(48.*(lai+sai)))*ldew_snow)**.666666666666
+ ! Check for maximum limit of fwet_snow
+ fwet_snow = min(fwet_snow,1.0)
+ ENDIF
+
+ ! phase change
+
+ qmelt = 0.
+ qfrz = 0.
+
+ IF (ldew_snow.gt.1.e-6 .and. tl.gt.tfrz) THEN
+ qmelt = min(ldew_snow/deltim,(tl-tfrz)*cpice*ldew_snow/(deltim*hfus))
+ ldew_snow = max(0.,ldew_snow - qmelt*deltim)
+ ldew_rain = max(0.,ldew_rain + qmelt*deltim)
+ !NOTE: There may be some problem, energy imbalance
+ ! However, detailed treatment could be somewhat trivial
+ tl = fwet_snow*tfrz + (1.-fwet_snow)*tl !Niu et al., 2004
+ ENDIF
+
+ IF (ldew_rain.gt.1.e-6 .and. tl.lt.tfrz) THEN
+ qfrz = min(ldew_rain/deltim,(tfrz-tl)*cpliq*ldew_rain/(deltim*hfus))
+ ldew_rain = max(0.,ldew_rain - qfrz*deltim)
+ ldew_snow = max(0.,ldew_snow + qfrz*deltim)
+ !NOTE: There may be some problem, energy imbalance
+ ! However, detailed treatment could be somewhat trivial
+ tl = fwet_snow*tfrz + (1.-fwet_snow)*tl !Niu et al., 2004
+ ENDIF
+ ENDIF
+
+ ! vegetation heat change
+ dheatl = clai/deltim*dtl(it-1)
+
+!-----------------------------------------------------------------------
+! balance check
+!-----------------------------------------------------------------------
+
+ err = sabv + irab + dirab_dtl*dtl(it-1) &
+ - fsenl - hvap*fevpl - dheatl
+
+#if (defined CoLMDEBUG)
+ IF (abs(err) .gt. .2) THEN
+ write(6,*) 'energy imbalance in UrbanVegFlux.F90', &
+ i,it-1,err,sabv,irab,fsenl,hvap*fevpl,dheatl
+ CALL CoLM_stop()
+ ENDIF
+#endif
+
+
+ ! calculate longwave absorption
+ lwsun = ( ewall*X(1) - B1(1) ) / (1-ewall)
+ lwsha = ( ewall*X(2) - B1(2) ) / (1-ewall)
+ lgimp = ( egimp*X(3) - B1(3) ) / (1-egimp)
+ lgper = ( egper*X(4) - B1(4) ) / (1-egper)
+ lveg = ( (sum(X(1:4)*VegVF(1:4)) + frl*VegVF(5))*ev - B1(5) )
+ lout = sum( X * SkyVF )
+
+ ! longwave absorption due to leaf temperature change
+ lwsun = lwsun + ( ewall*dX(1) ) / (1-ewall) * dtl(it-1)
+ lwsha = lwsha + ( ewall*dX(2) ) / (1-ewall) * dtl(it-1)
+ lgimp = lgimp + ( egimp*dX(3) ) / (1-egimp) * dtl(it-1)
+ lgper = lgper + ( egper*dX(4) ) / (1-egper) * dtl(it-1)
+ lveg = lveg + ( sum(dX(1:4)*VegVF(1:4))*ev - dBdT(5) ) * dtl(it-1)
+ lout = lout + sum( dX * SkyVF * dtl(it-1) )
+
+ ! Energy balance check
+ err = lwsun + lwsha + lgimp + lgper + lveg + lout
+
+ IF (abs(err-frl) > 1e-6) THEN
+ print *, "Longwave - Energy Balance Check error!", err-frl
+ ENDIF
+
+ ! convert to per unit area
+ IF (fcover(1) > 0.) lwsun = lwsun / fcover(1) * fg !/ (4*fwsun*HL*fb/fg)
+ IF (fcover(2) > 0.) lwsha = lwsha / fcover(2) * fg !/ (4*fwsha*HL*fb/fg)
+ IF (fcover(3) > 0.) lgimp = lgimp / fcover(3) * fg !/ fgimp
+ IF (fcover(4) > 0.) lgper = lgper / fcover(4) * fg !/ fgper
+ IF (fcover(5) > 0.) lveg = lveg / fcover(5) * fg !/ fv/fg
+
+ ! add previous longwave
+ lwsun = lwsun + dlwsun
+ lwsha = lwsha + dlwsha
+ lgimp = lgimp + dlgimp
+ lgper = lgper + dlgper
+ lveg = lveg + dlveg
+
+ tafu = taf(2)
+
+!-----------------------------------------------------------------------
+! wind stresses
+!-----------------------------------------------------------------------
+
+ taux = - rhoair*us/ram
+ tauy = - rhoair*vs/ram
+
+!-----------------------------------------------------------------------
+! fluxes from roof, walls to canopy space
+!-----------------------------------------------------------------------
+
+ ! sensible heat fluxes
+ fsenroof = rhoair*cpair/rb(0)*(troof-taf(3))
+ fsenwsun = rhoair*cpair/rb(1)*(twsun-taf(2))
+ fsenwsha = rhoair*cpair/rb(2)*(twsha-taf(2))
+
+ ! latent heat fluxes
+ fevproof = rhoair/rb(0)*(qsatl(0)-qaf(3))
+ fevproof = fevproof*fwet_roof
+
+ IF (botlay == 2) THEN
+
+ bT = 1/(rd(3) * (1/rah+1/rd(3)+fc(0)/rb(0)))
+ cT = 1/rd(3) + fg/rd(2) + fc(1)/rb(1) + fc(2)/rb(2) + fc(3)*lsai/rb(3)
+
+ cQ = 1/rd(3) + fg*fgper/(rd(2)+rss_) + fwet_gimp*fg*fgimp/rd(2) + fc(3)/rv
+ bQ = 1/(rd(3) * (1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+
+ cwsuns = rhoair*cpair/rb(1) &
+ *( 1. - fc(1)/(cT*rb(1)*(1-bT/(cT*rd(3)))) )
+
+ cwshas = rhoair*cpair/rb(2) &
+ *( 1. - fc(2)/(cT*rb(2)*(1-bT/(cT*rd(3)))) )
+
+ croofs = rhoair*cpair/rb(0) &
+ *( 1. - fc(0)*bT*bT / (cT*rb(0)*(1-bT/(cT*rd(3)))) &
+ - fc(0) / (rb(0)*(1/rah+1/rd(3)+fc(0)/rb(0))) )
+
+ croofl = rhoair*fwet_roof/rb(0)*qsatldT(0) &
+ * ( 1. - fwet_roof*fc(0)*bQ*bQ / (cQ*rb(0)*(1-bQ/(cQ*rd(3)))) &
+ - fwet_roof*fc(0) / (rb(0)*(1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0))) )
+
+ croof = croofs + croofl*htvp_roof
+ ELSE
+
+ cT = 1/rd(3) + 1/rd(2) + fc(1)/rb(1) + fc(2)/rb(2)
+ bT = 1/(rd(3)*(1/rah+1/rd(3)+fc(0)/rb(0)))
+
+ cQ = 1/rd(3) + 1/rd(2)
+ bQ = 1/(rd(3) * (1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0)))
+
+ cwsuns = rhoair*cpair/rb(1) &
+ *( 1. - fc(1)/(cT*rb(1)*(1-aT/(rd(2)*cT)-bT/(rd(3)*cT))) )
+
+ cwshas = rhoair*cpair/rb(2) &
+ *( 1. - fc(2)/(cT*rb(2)*(1-aT/(rd(2)*cT)-bT/(rd(3)*cT))) )
+
+ croofs = rhoair*cpair/rb(0) &
+ *( 1. - fc(0)*bT*bT/(cT*rb(0)*(1-aT/(rd(2)*cT)-bT/(rd(3)*cT))) &
+ - fc(0)/(rb(0)*(1/rah+1/rd(3)+fc(0)/rb(0))) )
+
+ croofl = rhoair*fwet_roof/rb(0)*qsatldT(0) &
+ *( 1. - fwet_roof*fc(0)/(rb(0)*(1/raw+1/rd(3)+fwet_roof*fc(0)/rb(0))) &
+ - fwet_roof*fc(0)*bQ*bQ/(rb(0)*cQ*(1-aQ/(cQ*rd(2))-bQ/(cQ*rd(3)))) )
+
+ croof = croofs + croofl*htvp_roof
+ ENDIF
+
+!-----------------------------------------------------------------------
+! fluxes from urban ground to canopy space
+!-----------------------------------------------------------------------
+
+ fsengimp = cpair*rhoair/rd(botlay)*(tgimp-taf(botlay))
+ fsengper = cpair*rhoair/rd(botlay)*(tgper-taf(botlay))
+
+ fevpgper = rhoair/(rd(botlay)+rss_)*(qgper-qaf(botlay))
+ fevpgimp = rhoair/rd(botlay) *(qgimp-qaf(botlay))
+
+ fevpgimp = fevpgimp*fwet_gimp
+
+!-----------------------------------------------------------------------
+! Derivative of soil energy flux with respect to soil temperature
+!-----------------------------------------------------------------------
+
+ IF (botlay == 2) THEN
+ cgrnds = cpair*rhoair/rd(2)*( 1. - fg/(cT*rd(2)*(1-bT/(cT*rd(3)))) )
+
+ cgperl = rhoair/(rd(2)+rss_)*dqgperdT*(1-fg*fgper/(cQ*(rd(2)+rss_)*(1-bQ/(cQ*rd(3)))) )
+ cgimpl = rhoair/rd(2) *dqgimpdT*(1-fwet_gimp*fg*fgimp/(cQ*rd(2)*(1-bQ/(cQ*rd(3)))) )
+ cgimpl = cgimpl*fwet_gimp
+
+ ELSE !botlay == 1
+ cgrnds = cpair*rhoair/rd(1)* &
+ ( 1. - fg/(rd(1)*(1/rd(2)+fg/rd(1)+fc(3)*lsai/rb(3))) &
+ - fg*aT*aT/(rd(1)*cT*(1-aT/(cT*rd(2))-bT/(cT*rd(3)))) )
+
+ cgperl = rhoair/(rd(1)+rss_)*dqgperdT &
+ *( 1. - fg*fgper/((rss_+rd(1))*(1/rd(2)+fg*fgper/(rss_+rd(1)) &
+ +fg*fgimp*fwet_gimp/rd(1)+fc(3)/rv)) &
+ - fg*fgper*aQ*aQ/((rss_+rd(1))*cQ*(1-aQ/(cQ*rd(2))-bQ/(cQ*rd(3)))) )
+
+ cgimpl = rhoair/rd(1)*dqgimpdT &
+ *( 1. - fg*fgimp*fwet_gimp/(rd(1)*(1/rd(2)+fg*fgper/(rss_+rd(1)) &
+ +fg*fgimp*fwet_gimp/rd(1)+fc(3)/rv)) &
+ - fg*fgimp*fwet_gimp*aQ*aQ/(rd(1)*cQ*(1-aQ/(cQ*rd(2))-bQ/(cQ*rd(3)))) )
+ cgimpl = cgimpl*fwet_gimp
+ ENDIF
+
+ cgimp = cgrnds + cgimpl*htvp_gimp
+ cgper = cgrnds + cgperl*htvp_gper
+
+!-----------------------------------------------------------------------
+! 2 m height air temperature above apparent sink height
+!-----------------------------------------------------------------------
+
+ !tref = thm + vonkar/(fh)*dth * (fh2m/vonkar - fh/vonkar)
+ !qref = qm + vonkar/(fq)*dqh * (fq2m/vonkar - fq/vonkar)
+
+ ! assumption: (tg-t2m):(tg-taf) = 2:(displa+z0m)
+ IF (numlay == 2) THEN
+ tref = ( (displau+z0mu-2.)*tg + 2.*taf(2) ) / (displau+z0mu)
+ qref = ( (displau+z0mu-2.)*qg + 2.*qaf(2) ) / (displau+z0mu)
+ ELSE
+ tref = (((displau+z0mu+displav+z0mv)*0.5-2.)*tg + taf(1) + taf(2) ) &
+ / ( (displau+z0mu+displav+z0mv)*0.5 )
+ qref = (((displau+z0mu+displav+z0mv)*0.5-2.)*qg + qaf(1) + qaf(2) ) &
+ / ( (displau+z0mu+displav+z0mv)*0.5 )
+ ENDIF
+
+ END SUBROUTINE UrbanVegFlux
+!----------------------------------------------------------------------
+
+
+ SUBROUTINE dewfraction (sigf,lai,sai,dewmx,ldew,ldew_rain,ldew_snow,fwet,fdry)
+!=======================================================================
+! Original author: Yongjiu Dai, September 15, 1999
+!
+! determine fraction of foliage covered by water and
+! fraction of foliage that is dry and transpiring
+!
+! !REVISIONS:
+!
+! 2024.04.16, Hua Yuan: add option to account for vegetation snow process
+! 2018.06 , Hua Yuan: remove sigf, to compatible with PFT
+!=======================================================================
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: sigf !fraction of veg cover, excluding snow-covered veg [-]
+ real(r8), intent(in) :: lai !leaf area index [-]
+ real(r8), intent(in) :: sai !stem area index [-]
+ real(r8), intent(in) :: dewmx !maximum allowed dew [0.1 mm]
+ real(r8), intent(in) :: ldew !depth of water on foliage [kg/m2/s]
+ real(r8), intent(in) :: ldew_rain !depth of rain on foliage [kg/m2/s]
+ real(r8), intent(in) :: ldew_snow !depth of snow on foliage [kg/m2/s]
+ real(r8), intent(out) :: fwet !fraction of foliage covered by water&snow [-]
+ real(r8), intent(out) :: fdry !fraction of foliage that is green and dry [-]
+
+ real(r8) :: lsai !lai + sai
+ real(r8) :: dewmxi !inverse of maximum allowed dew [1/mm]
+ real(r8) :: vegt !sigf*lsai, NOTE: remove sigf
+ real(r8) :: fwet_rain !fraction of foliage covered by water [-]
+ real(r8) :: fwet_snow !fraction of foliage covered by snow [-]
+!
+!-----------------------------------------------------------------------
+! Fwet is the fraction of all vegetation surfaces which are wet
+! including stem area which contribute to evaporation
+ lsai = lai + sai
+ dewmxi = 1.0/dewmx
+ ! 06/2018, yuan: remove sigf, to compatible with PFT
+ vegt = lsai
+
+ fwet = 0
+ IF (ldew > 0.) THEN
+ fwet = ((dewmxi/vegt)*ldew)**.666666666666
+ ! Check for maximum limit of fwet
+ fwet = min(fwet,1.0)
+ ENDIF
+
+ ! account for vegetation snow
+ ! calculate fwet_rain, fwet_snow, fwet
+ IF ( DEF_VEG_SNOW ) THEN
+
+ fwet_rain = 0
+ IF(ldew_rain > 0.) THEN
+ fwet_rain = ((dewmxi/vegt)*ldew_rain)**.666666666666
+ ! Check for maximum limit of fwet_rain
+ fwet_rain = min(fwet_rain,1.0)
+ ENDIF
+
+ fwet_snow = 0
+ IF(ldew_snow > 0.) THEN
+ fwet_snow = ((dewmxi/(48.*vegt))*ldew_snow)**.666666666666
+ ! Check for maximum limit of fwet_snow
+ fwet_snow = min(fwet_snow,1.0)
+ ENDIF
+
+ fwet = fwet_rain + fwet_snow - fwet_rain*fwet_snow
+ fwet = min(fwet,1.0)
+ ENDIF
+
+ ! fdry is the fraction of lai which is dry because only leaves can
+ ! transpire. Adjusted for stem area which does not transpire
+ fdry = (1.-fwet)*lai/lsai
+
+ END SUBROUTINE dewfraction
+
+END MODULE MOD_Urban_Flux
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_GroundFlux.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_GroundFlux.F90
new file mode 100644
index 0000000000..53a5cba0e9
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_GroundFlux.F90
@@ -0,0 +1,229 @@
+#include
+
+MODULE MOD_Urban_GroundFlux
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanGroundFlux
+
+CONTAINS
+
+ SUBROUTINE UrbanGroundFlux (hu, ht, hq, us, vs, tm, qm, rhoair, psrf, &
+ ur, thm, th, thv, zlnd, zsno, fsno_gimp, &
+ lbi, wliq_gimpsno,wice_gimpsno, &
+ fcover, tgimp, tgper, qgimp, qgper, tref, qref, &
+ z0m, z0hg, zol, ustar, qstar, tstar, fm, fh, fq)
+
+!=======================================================================
+!
+! !DESCRIPTION:
+! This is the main subroutine to execute the calculation
+! of bare ground fluxes
+!
+! Created by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+! 07/2022, Hua Yuan: Urban 2m T/q -> above bare ground 2m.
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpair,vonkar,grav
+ USE MOD_FrictionVelocity
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer , intent(in) :: &
+ lbi
+ real(r8), intent(in) :: &
+ ! atmospherical variables and observational height
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ tm, &! temperature at agcm reference height [kelvin] [not used]
+ qm, &! specific humidity at agcm reference height [kg/kg]
+ rhoair, &! density air [kg/m3]
+ psrf, &! atmosphere pressure at the surface [pa] [not used]
+
+ ur, &! wind speed at reference height [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+
+ zlnd, &! roughness length for soil [m]
+ zsno, &! roughness length for snow [m]
+ fsno_gimp, &! fraction of impervious ground covered by snow
+ fcover(0:5), &! coverage of aboveground urban components [-]
+
+ wliq_gimpsno, &! liqui water [kg/m2]
+ wice_gimpsno, &! ice lens [kg/m2]
+
+ tgimp, &! ground impervious temperature [K]
+ tgper, &! ground pervious temperature [K]
+ qgimp, &! ground impervious specific humidity [kg/kg]
+ qgper ! ground pervious specific humidity [kg/kg]
+
+ real(r8), intent(out) :: &
+ tref, &! 2 m height air temperature [kelvin]
+ qref ! 2 m height air humidity
+
+ real(r8), intent(out) :: &
+ z0m, &! effective roughness [m]
+ z0hg, &! roughness length over ground, sensible heat [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+!-------------------------- Local Variables ----------------------------
+ integer niters, &! maximum number of iterations for surface temperature
+ iter, &! iteration index
+ nmozsgn ! number of times moz changes sign
+
+ real(r8) :: &
+ beta, &! coefficient of convective velocity [-]
+ displax, &! zero-displacement height [m]
+ tg, &! ground surface temperature [K]
+ qg, &! ground specific humidity [kg/kg]
+ fg, &! ground fractional cover [-]
+ fgimp, &! weight of impervious ground
+ fgper, &! weight of pervious ground
+ dth, &! diff of virtual temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ obuold, &! monin-obukhov length from previous iteration
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile function for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ um, &! wind speed including the stability effect [m/s]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ zii, &! convective boundary height [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ z0mg, &! roughness length over ground, momentum [m]
+ z0qg ! roughness length over ground, latent heat [m]
+
+ real(r8) fwet_gimp, fwetfac
+
+!-----------------------------------------------------------------------
+
+! initial roughness length
+ !NOTE: change to original
+ !z0mg = (1.-fsno)*zlnd + fsno*zsno
+ IF (fsno_gimp > 0) THEN
+ z0mg = zsno
+ ELSE
+ z0mg = zlnd
+ ENDIF
+ z0hg = z0mg
+ z0qg = z0mg
+
+! potential temperature at the reference height
+ beta = 1. !- (in computing W_*)
+ zii = 1000. !m (pbl height)
+ z0m = z0mg
+
+ fg = 1 - fcover(0)
+ fgimp = fcover(3)/fg
+ fgper = fcover(4)/fg
+
+ ! weighted tg
+ tg = tgimp*fgimp + tgper*fgper
+
+ ! wet fraction impervious ground
+ !-------------------------------------------
+ IF (lbi < 1) THEN
+ fwet_gimp = fsno_gimp !for snow layer exist
+ ELSE
+ ! surface wet fraction. assuming max ponding = 1 kg/m2
+ fwet_gimp = (max(0., wliq_gimpsno+wice_gimpsno))**(2/3.)
+ fwet_gimp = min(1., fwet_gimp)
+ ENDIF
+
+ ! dew case
+ IF (qm > qgimp) THEN
+ fwet_gimp = 1.
+ ENDIF
+
+ ! weighted qg
+ fwetfac = fgimp*fwet_gimp + fgper
+ qg = (qgimp*fgimp*fwet_gimp + qgper*fgper)/fwetfac
+
+!-----------------------------------------------------------------------
+! Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+!-----------------------------------------------------------------------
+! Initialization variables
+ nmozsgn = 0
+ obuold = 0.
+
+ dth = thm-tg
+ dqh = qm-qg
+ dthv = dth*(1.+0.61*qm)+0.61*th*dqh
+ zldis = hu-0.
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mg,um,obu)
+
+! Evaluated stability-dependent variables using moz from prior iteration
+ niters=6
+
+ !----------------------------------------------------------------
+ ITERATION : DO iter = 1, niters !begin stability iteration
+ !----------------------------------------------------------------
+ displax = 0.
+ CALL moninobuk(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+
+ tstar = vonkar/fh*dth
+ qstar = vonkar/fq*dqh
+
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ thvstar=tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta=zldis*vonkar*grav*thvstar/(ustar**2*thv)
+ IF (zeta >= 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF (zeta >= 0.) THEN
+ um = max(ur,0.1)
+ ELSE
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu < 0.) nmozsgn = nmozsgn+1
+ IF (nmozsgn >= 4) EXIT
+
+ obuold = obu
+
+ !----------------------------------------------------------------
+ ENDDO ITERATION !end stability iteration
+ !----------------------------------------------------------------
+
+ zol = zeta
+ !rib = min(5.,zol*ustar**2/(vonkar**2/fh*um**2))
+
+! 2 m height air temperature
+ tref = thm + vonkar/fh*dth * (fh2m/vonkar - fh/vonkar)
+ qref = qm + vonkar/fq*dqh * (fq2m/vonkar - fq/vonkar)
+
+ END SUBROUTINE UrbanGroundFlux
+
+END MODULE MOD_Urban_GroundFlux
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Hydrology.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Hydrology.F90
new file mode 100644
index 0000000000..29b0d5ce6b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Hydrology.F90
@@ -0,0 +1,407 @@
+#include
+
+MODULE MOD_Urban_Hydrology
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! The urban hydrological processes mainly falls into three categories:
+! 1) previous surfaces; 2) roofs and imperious surfaces; 3) urban water
+! bodies (lakes).
+!
+! For pervious surfaces, the process is similar to soil water
+! processes, involving the calculation of runoff and soil water
+! transport. For urban water bodies, a lake model is used for
+! simulation. For roofs and impermeable surfaces, snow accumulation and
+! ponding processes are considered. The snow accumulation process is
+! consistent with soil snow processes. The ponding process considers
+! the surface as an impermeable area, with the maximum capacity of
+! liquid water not exceeding a predetermined value (max ponding = 1 kg
+! m−2). Any excess water is treated as runoff. The coverage ratio of
+! ponded areas is calculated using a similar leaf wetness index
+! calculation scheme.
+!
+! Create by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+!
+! 10/2022, Hua Yuan: Add wet fraction for roof and impervious ground;
+! set max ponding for roof and impervious from 10mm -> 1mm.
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanHydrology
+
+CONTAINS
+
+ SUBROUTINE UrbanHydrology ( &
+ ! model running information
+ ipatch ,patchtype ,lbr ,lbi ,&
+ lbp ,lbl ,snll ,deltim ,&
+ ! forcing
+ pg_rain ,pgper_rain ,pgimp_rain ,pg_snow ,&
+ pg_rain_lake ,pg_snow_lake ,&
+ ! surface parameters or status
+ froof ,fgper ,flake ,bsw ,&
+ porsl ,psi0 ,hksati ,pondmx ,&
+ ssi ,wimp ,smpmin ,theta_r ,&
+ fsatmax ,fsatdcf ,elvstd ,BVIC ,&
+ rootr,rootflux ,etr ,fseng ,fgrnd ,&
+ t_gpersno ,t_lakesno ,t_lake ,dz_lake ,&
+ z_gpersno ,z_lakesno ,zi_gpersno ,zi_lakesno ,&
+ dz_roofsno ,dz_gimpsno ,dz_gpersno ,dz_lakesno ,&
+ wliq_roofsno ,wliq_gimpsno ,wliq_gpersno ,wliq_lakesno ,&
+ wice_roofsno ,wice_gimpsno ,wice_gpersno ,wice_lakesno ,&
+ qseva_roof ,qseva_gimp ,qseva_gper ,qseva_lake ,&
+ qsdew_roof ,qsdew_gimp ,qsdew_gper ,qsdew_lake ,&
+ qsubl_roof ,qsubl_gimp ,qsubl_gper ,qsubl_lake ,&
+ qfros_roof ,qfros_gimp ,qfros_gper ,qfros_lake ,&
+ sm_roof ,sm_gimp ,sm_gper ,sm_lake ,&
+ lake_icefrac ,scv_lake ,snowdp_lake ,imelt_lake ,&
+ fioldl ,w_old ,&
+ forc_us ,forc_vs ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+! END SNICAR model variables
+! irrigaiton
+ qflx_irrig_drip,qflx_irrig_flood,qflx_irrig_paddy ,&
+ ! output
+ rsur ,rnof ,qinfl ,zwt ,&
+ wdsrf ,wa ,qcharge ,smp ,hk)
+
+!=======================================================================
+! this is the main SUBROUTINE to execute the calculation of URBAN
+! hydrological processes
+!
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: denice, denh2o, tfrz
+ USE MOD_SoilSnowHydrology
+ USE MOD_Lake
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ ipatch ,&! patch index
+ patchtype ,&! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=land ice, 4=land water bodies, 99=ocean
+ lbr ,&! lower bound of array
+ lbi ,&! lower bound of array
+ lbp ,&! lower bound of array
+ lbl ! lower bound of array
+
+ integer, intent(inout) :: &
+ snll ! number of snow layers
+
+ real(r8), intent(in) :: &
+ deltim ,&! time step (s)
+ pg_rain ,&! rainfall after removal of interception (mm h2o/s)
+ pg_snow ,&! snowfall after removal of interception (mm h2o/s)
+ pgper_rain ,&! rainfall after removal of interception (mm h2o/s)
+ pgimp_rain ,&! rainfall after removal of interception (mm h2o/s)
+ pg_rain_lake ,&! rainfall onto lake (mm h2o/s)
+ pg_snow_lake ,&! snowfall onto lake (mm h2o/s)
+ froof ,&! roof fractional cover [-]
+ fgper ,&! weight of impervious ground [-]
+ flake ,&! lake fractional cover [-]
+ ! wtfact ,&! fraction of model area with high water table
+ ! (updated to gridded 'fsatmax' data)
+ pondmx ,&! ponding depth (mm)
+ ssi ,&! irreducible water saturation of snow
+ wimp ,&! water impermeable IF porosity less than wimp
+ smpmin ,&! restriction for min of soil poten. (mm)
+
+ elvstd ,&! standard deviation of elevation [m]
+ BVIC ,&! b parameter in Fraction of saturated soil in a grid calculated by VIC
+
+ bsw (1:nl_soil) ,&! Clapp-Hornberger "B"
+ porsl (1:nl_soil) ,&! saturated volumetric soil water content(porosity)
+ psi0 (1:nl_soil) ,&! saturated soil suction (mm) (NEGATIVE)
+ hksati(1:nl_soil) ,&! hydraulic conductivity at saturation (mm h2o/s)
+ theta_r(1:nl_soil) ,&! residual moisture content [-]
+ fsatmax ,&! maximum saturated area fraction [-]
+ fsatdcf ,&! decay factor in calculation of saturated area fraction [1/m]
+ rootr (1:nl_soil) ,&! root resistance of a layer, all layers add to 1.0
+
+ etr ,&! vegetation transpiration
+ qseva_roof ,&! ground surface evaporation rate (mm h2o/s)
+ qseva_gimp ,&! ground surface evaporation rate (mm h2o/s)
+ qseva_gper ,&! ground surface evaporation rate (mm h2o/s)
+ qseva_lake ,&! ground surface evaporation rate (mm h2o/s)
+ qsdew_roof ,&! ground surface dew formation (mm h2o /s) [+]
+ qsdew_gimp ,&! ground surface dew formation (mm h2o /s) [+]
+ qsdew_gper ,&! ground surface dew formation (mm h2o /s) [+]
+ qsdew_lake ,&! ground surface dew formation (mm h2o /s) [+]
+ qsubl_roof ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qsubl_gimp ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qsubl_gper ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qsubl_lake ,&! sublimation rate from snow pack (mm h2o /s) [+]
+ qfros_roof ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_gimp ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_gper ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_lake ,&! surface dew added to snow pack (mm h2o /s) [+]
+ sm_roof ,&! snow melt (mm h2o/s)
+ sm_gimp ,&! snow melt (mm h2o/s)
+ sm_gper ,&! snow melt (mm h2o/s)
+ w_old ! liquid water mass of the column at the previous time step (mm)
+
+ real(r8), intent(inout) :: rootflux(1:nl_soil)
+
+ real(r8), intent(in) :: forc_us
+ real(r8), intent(in) :: forc_vs
+
+! SNICAR model variables
+! Aerosol Fluxes (Jan. 07, 2023)
+ ! aerosol deposition from atmosphere model (grd,aer) [kg m-1 s-1]
+ real(r8), intent(in) :: forc_aer (14)
+
+ real(r8), intent(inout) :: &
+ mss_bcpho (lbp:0) ,&! mass of hydrophobic BC in snow (col,lyr) [kg]
+ mss_bcphi (lbp:0) ,&! mass of hydrophillic BC in snow (col,lyr) [kg]
+ mss_ocpho (lbp:0) ,&! mass of hydrophobic OC in snow (col,lyr) [kg]
+ mss_ocphi (lbp:0) ,&! mass of hydrophillic OC in snow (col,lyr) [kg]
+ mss_dst1 (lbp:0) ,&! mass of dust species 1 in snow (col,lyr) [kg]
+ mss_dst2 (lbp:0) ,&! mass of dust species 2 in snow (col,lyr) [kg]
+ mss_dst3 (lbp:0) ,&! mass of dust species 3 in snow (col,lyr) [kg]
+ mss_dst4 (lbp:0) ! mass of dust species 4 in snow (col,lyr) [kg]
+! Aerosol Fluxes (Jan. 07, 2023)
+! END SNICAR model variables
+
+! For irrigation
+ real(r8), intent(in) :: &
+ qflx_irrig_drip ,&! drip irrigation rate [mm/s]
+ qflx_irrig_flood ,&! flood irrigation rate [mm/s]
+ qflx_irrig_paddy ! paddy irrigation rate [mm/s]
+! END irrigation
+
+ integer, intent(in) :: &
+ imelt_lake(maxsnl+1:nl_soil) ! lake flag for melting or freezing snow and soil layer [-]
+
+ real(r8), intent(inout) :: &
+ lake_icefrac( 1:nl_lake) ,&! lake ice fraction
+ fioldl (maxsnl+1:nl_soil) ,&! fraction of ice relative to the total water content [-]
+ dz_lake ( 1:nl_lake) ,&! lake layer depth [m]
+ z_gpersno (lbp:nl_soil) ,&! layer depth (m)
+ dz_roofsno (lbr:nl_roof) ,&! layer thickness (m)
+ dz_gimpsno (lbi:nl_soil) ,&! layer thickness (m)
+ dz_gpersno (lbp:nl_soil) ,&! layer thickness (m)
+ zi_gpersno(lbp-1:nl_soil) ,&! interface level below a "z" level (m)
+ t_lake ( 1:nl_lake) ,&! lake temperature [K]
+ t_gpersno (lbp:nl_soil) ,&! soil/snow skin temperature (K)
+ wliq_roofsno(lbr:nl_roof) ,&! liquid water (kg/m2)
+ wliq_gimpsno(lbi:nl_soil) ,&! liquid water (kg/m2)
+ wliq_gpersno(lbp:nl_soil) ,&! liquid water (kg/m2)
+ wice_roofsno(lbr:nl_roof) ,&! ice lens (kg/m2)
+ wice_gimpsno(lbi:nl_soil) ,&! ice lens (kg/m2)
+ wice_gpersno(lbp:nl_soil) ,&! ice lens (kg/m2)
+
+ zi_lakesno (maxsnl :nl_soil),&! interface level below a "z" level (m)
+ t_lakesno (maxsnl+1:nl_soil),&! soil/snow skin temperature (K)
+ z_lakesno (maxsnl+1:nl_soil),&! layer depth (m)
+ dz_lakesno (maxsnl+1:nl_soil),&! layer thickness (m)
+ wliq_lakesno(maxsnl+1:nl_soil),&! liquid water (kg/m2)
+ wice_lakesno(maxsnl+1:nl_soil),&! ice lens (kg/m2)
+
+ sm_lake ,&! snow melt (mm h2o/s)
+ scv_lake ,&! lake snow mass (kg/m2)
+ snowdp_lake ,&! lake snow depth
+ fseng ,&! sensible heat from ground
+ fgrnd ,&! ground heat flux
+ zwt ,&! the depth from ground (soil) surface to water table [m]
+ wdsrf ,&! depth of surface water [mm]
+ wa ! water storage in aquifer [mm]
+
+ real(r8), intent(out) :: &
+ rsur ,&! surface runoff (mm h2o/s)
+ rnof ,&! total runoff (mm h2o/s)
+ qinfl ,&! infiltration rate (mm h2o/s)
+ qcharge ! groundwater recharge (positive to aquifer) [mm/s]
+
+ real(r8), intent(out) :: &
+ smp(1:nl_soil) ,&! soil matrix potential [mm]
+ hk (1:nl_soil) ! hydraulic conductivity [mm h2o/m]
+
+!-------------------------- Local Variables ----------------------------
+
+ real(r8) :: &
+ fg ,&! ground fractional cover [-]
+ gwat ,&! net water input from top (mm/s)
+ rnof_roof ,&! total runoff (mm h2o/s)
+ rnof_gimp ,&! total runoff (mm h2o/s)
+ rnof_gper ,&! total runoff (mm h2o/s)
+ rnof_lake ,&! total runoff (mm h2o/s)
+ rsur_roof ,&! surface runoff (mm h2o/s)
+ rsur_gimp ,&! surface runoff (mm h2o/s)
+ rsur_gper ,&! surface runoff (mm h2o/s)
+ rsur_lake ,&! surface runoff (mm h2o/s)
+ dfseng ,&! change of lake sensible heat [W/m2]
+ dfgrnd ! change of lake ground heat flux [W/m2]
+
+ real(r8) :: a, aa, xs1
+
+!-----------------------------------------------------------------------
+
+ fg = 1 - froof
+ dfseng = 0.
+ dfgrnd = 0.
+
+!=======================================================================
+! [1] for pervious road, the same as soil
+!=======================================================================
+
+ rootflux(:) = rootr(:)*etr
+
+ CALL WATER_2014 (ipatch,patchtype,lbp ,nl_soil ,deltim ,&
+ z_gpersno ,dz_gpersno ,zi_gpersno ,bsw ,porsl ,&
+ psi0 ,hksati ,theta_r ,fsatmax ,fsatdcf ,&
+ elvstd ,BVIC ,rootr ,rootflux ,t_gpersno ,&
+ wliq_gpersno,wice_gpersno,smp ,hk ,pgper_rain ,&
+ sm_gper ,etr ,qseva_gper ,qsdew_gper ,qsubl_gper ,&
+ qfros_gper ,&
+ !NOTE: temporal input, as urban mode doesn't support split soil&snow
+ ! set all the same for soil and snow surface,
+ ! and fsno=0. (no physical meaning here)
+ qseva_gper ,qsdew_gper ,qsubl_gper ,qfros_gper ,&
+ qseva_gper ,qsdew_gper ,qsubl_gper ,qfros_gper ,&
+ 0. ,& ! fsno, not active
+ rsur_gper ,rnof_gper ,qinfl ,pondmx ,ssi ,&
+ wimp ,smpmin ,zwt ,wdsrf ,wa ,qcharge ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+! irrigation variables
+ qflx_irrig_drip ,qflx_irrig_flood ,qflx_irrig_paddy )
+
+!=======================================================================
+! [2] for roof and impervious road
+!=======================================================================
+
+ IF (lbr >= 1) THEN
+ gwat = pg_rain + sm_roof - qseva_roof
+ ELSE
+ CALL snowwater (lbr,deltim,ssi,wimp,&
+ pg_rain,qseva_roof,qsdew_roof,qsubl_roof,qfros_roof,&
+ dz_roofsno(lbr:0),wice_roofsno(lbr:0),wliq_roofsno(lbr:0),gwat)
+ ENDIF
+
+ wliq_roofsno(1) = wliq_roofsno(1) + gwat*deltim
+
+ ! Renew the ice and liquid mass due to condensation
+ IF (lbr >= 1) THEN
+ ! make consistent with how evap_grnd removed in infiltration
+ wliq_roofsno(1) = max(0., wliq_roofsno(1) + qsdew_roof * deltim)
+ wice_roofsno(1) = max(0., wice_roofsno(1) + (qfros_roof-qsubl_roof) * deltim)
+ ENDIF
+
+ ! only consider ponding and surface runoff
+ ! NOTE: set max ponding depth = 1mm (liq+ice)
+ xs1 = wliq_roofsno(1) - 1.
+ IF (xs1 > 0.) THEN
+ wliq_roofsno(1) = 1.
+ ELSE
+ xs1 = 0.
+ ENDIF
+
+ rsur_roof = xs1 / deltim
+ rnof_roof = rsur_roof
+
+ ! ================================================
+
+ IF (lbi >= 1) THEN
+ gwat = pgimp_rain + sm_gimp - qseva_gimp
+ ELSE
+ CALL snowwater (lbi,deltim,ssi,wimp,&
+ pgimp_rain,qseva_gimp,qsdew_gimp,qsubl_gimp,qfros_gimp,&
+ dz_gimpsno(lbi:0),wice_gimpsno(lbi:0),wliq_gimpsno(lbi:0),gwat)
+ ENDIF
+
+ wliq_gimpsno(1) = wliq_gimpsno(1) + gwat*deltim
+
+ ! Renew the ice and liquid mass due to condensation
+ IF (lbi >= 1) THEN
+ ! make consistent with how evap_grnd removed in infiltration
+ wliq_gimpsno(1) = max(0., wliq_gimpsno(1) + qsdew_gimp * deltim)
+ wice_gimpsno(1) = max(0., wice_gimpsno(1) + (qfros_gimp-qsubl_gimp) * deltim)
+ ENDIF
+
+ ! only consider ponding and surface runoff
+ ! NOTE: set max ponding depth = 1mm
+ xs1 = wliq_gimpsno(1) - 1.
+ IF (xs1 > 0.) THEN
+ wliq_gimpsno(1) = 1.
+ ELSE
+ xs1 = 0.
+ ENDIF
+
+ rsur_gimp = xs1 / deltim
+ rnof_gimp = rsur_gimp
+
+!=======================================================================
+! [3] lake hydrology
+!=======================================================================
+
+ CALL snowwater_lake ( DEF_USE_Dynamic_Lake, &
+ ! "in" snowater_lake arguments
+ ! ---------------------------
+ maxsnl ,nl_soil ,nl_lake ,deltim ,&
+ ssi ,wimp ,porsl ,pg_rain_lake ,&
+ pg_snow_lake ,dz_lake ,imelt_lake(:0) ,fioldl(:0) ,&
+ qseva_lake ,qsubl_lake ,qsdew_lake ,qfros_lake ,&
+
+ ! "inout" snowater_lake arguments
+ ! ---------------------------
+ z_lakesno ,dz_lakesno ,zi_lakesno ,t_lakesno ,&
+ wice_lakesno ,wliq_lakesno ,t_lake ,lake_icefrac ,&
+ gwat ,&
+ dfseng ,dfgrnd ,snll ,scv_lake ,&
+ snowdp_lake ,sm_lake ,forc_us ,forc_vs ,&
+! SNICAR model variables
+ forc_aer ,&
+ mss_bcpho ,mss_bcphi ,mss_ocpho ,mss_ocphi ,&
+ mss_dst1 ,mss_dst2 ,mss_dst3 ,mss_dst4 ,&
+! END SNICAR model variables
+ urban_call=.true.)
+
+ ! We assume the land water bodies have zero extra liquid water capacity
+ ! (i.e.,constant capacity), all excess liquid water are put into the runoff,
+ ! this unreasonable assumption should be updated in the future version
+ a = (sum(wliq_lakesno(snll+1:))-w_old)/deltim
+ aa = qseva_lake-(qsubl_lake-qsdew_lake)
+ rsur_lake = max(0., pg_rain_lake - aa - a)
+ rnof_lake = rsur_lake
+
+ ! Set zero to the empty node
+ IF (snll > maxsnl) THEN
+ wice_lakesno(maxsnl+1:snll) = 0.
+ wliq_lakesno(maxsnl+1:snll) = 0.
+ t_lakesno (maxsnl+1:snll) = 0.
+ z_lakesno (maxsnl+1:snll) = 0.
+ dz_lakesno (maxsnl+1:snll) = 0.
+ ENDIF
+
+ fseng = fseng + dfseng*flake
+ fgrnd = fgrnd + dfgrnd*flake
+
+!=======================================================================
+! [4] surface and total runoff weighted by fractional coverages
+!=======================================================================
+
+ ! 10/01/2021, yuan: exclude lake part
+ rsur = rsur_roof*froof + rsur_gimp*fg*(1-fgper) + rsur_gper*fg*fgper
+ !rsur = rsur*(1.-flake) + rsur_lake*flake
+ rnof = rnof_roof*froof + rnof_gimp*fg*(1-fgper) + rnof_gper*fg*fgper
+ !rnof = rnof*(1.-flake) + rnof_lake*flake
+
+ END SUBROUTINE UrbanHydrology
+
+END MODULE MOD_Urban_Hydrology
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_ImperviousTemperature.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_ImperviousTemperature.F90
new file mode 100644
index 0000000000..b6fdf67f96
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_ImperviousTemperature.F90
@@ -0,0 +1,304 @@
+#include
+
+MODULE MOD_Urban_ImperviousTemperature
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! The main difference between calculating the temperature conduction
+! for an impervious ground and a pervious surface lies in the need to
+! USE the thermal properties (thermal conductivity and heat capacity)
+! of the imperious surface layer instead of the soil thermal
+! properties. Additionally, when snow, ice, and water are present, the
+! heat capacity of the first impervious surface layer needs to be
+! adjusted. The impervious surface does not consider the transmission
+! of water below the surface, and the phase change process only
+! considers the first impervious surface layer (surface water/ice) and
+! the overlying snow cover layer.
+!
+! Created by Yongjiu Dai and Hua Yuan, 05/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanImperviousTem
+
+CONTAINS
+
+ SUBROUTINE UrbanImperviousTem (patchtype,lb,deltim, &
+ capr,cnfac,csol,k_solids,porsl,psi0,dkdry,dksatu,dksatf,&
+ vf_quartz,vf_gravels,vf_om,vf_sand,wf_gravels,wf_sand,&
+ BA_alpha, BA_beta,&
+ cv_gimp,tk_gimp,dz_gimpsno,z_gimpsno,zi_gimpsno,&
+ t_gimpsno,wice_gimpsno,wliq_gimpsno,scv_gimp,snowdp_gimp,&
+ lgimp,clgimp,sabgimp,fsengimp,fevpgimp,cgimp,htvp,&
+ imelt,sm,xmf,fact)
+
+!=======================================================================
+! Snow and impervious road temperatures
+! o The volumetric heat capacity is calculated as a linear combination
+! in terms of the volumetric fraction of the constituent phases.
+! o The thermal conductivity of road soil is computed from
+! the algorithm of Johansen (as reported by Farouki 1981), impervious
+! and pervious from LOOK-UP table and of snow is from the formulation
+! used in SNTHERM (Jordan 1991).
+! o Boundary conditions:
+! F = Rnet - Hg - LEg (top), F = 0 (base of the soil column).
+! o Soil / snow temperature is predicted from heat conduction
+! in 10 soil layers and up to 5 snow layers. The thermal
+! conductivities at the interfaces between two neighbor layers (j,j+1)
+! are derived from an assumption that the flux across the interface is
+! equal to that from the node j to the interface and the flux from the
+! interface to the node j+1. The equation is solved using the
+! Crank-Nicholson method and resulted in a tridiagonal system
+! equation.
+!
+! Phase change (see MOD_PhaseChange.F90)
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002; 05/2020
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical
+ USE MOD_SoilThermalParameters
+ USE MOD_PhaseChange, only: meltf_urban
+ USE MOD_Utils, only: tridia
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: lb !lower bound of array
+ integer, intent(in) :: patchtype !land patch type
+ !(0=soil,1=urban or built-up,2=wetland,
+ !3=land ice, 4=deep lake, 5=shallow lake)
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: capr !tuning factor: turn 1st layer T to surface T
+ real(r8), intent(in) :: cnfac !Crank Nicholson factor between 0 and 1
+
+ real(r8), intent(in) :: csol (1:nl_soil) !heat capacity of soil solids [J/(m3 K)]
+ real(r8), intent(in) :: k_solids (1:nl_soil) !thermal conductivity of minerals [W/m-K]
+ real(r8), intent(in) :: porsl (1:nl_soil) !soil porosity [-]
+ real(r8), intent(in) :: psi0 (1:nl_soil) !soil water suction, negative potential [mm]
+
+ real(r8), intent(in) :: dkdry (1:nl_soil) !thermal conductivity of dry soil [W/m-K]
+ real(r8), intent(in) :: dksatu (1:nl_soil) !thermal conductivity of sat soil [W/m-K]
+ real(r8), intent(in) :: dksatf (1:nl_soil) !thermal cond. of sat frozen soil [W/m-K]
+
+ real(r8), intent(in) :: vf_quartz (1:nl_soil) !volumetric frac of quartz in mineral soil
+ real(r8), intent(in) :: vf_gravels(1:nl_soil) !volumetric frac of gravels
+ real(r8), intent(in) :: vf_om (1:nl_soil) !volumetric frac of organic matter
+ real(r8), intent(in) :: vf_sand (1:nl_soil) !volumetric frac of sand
+ real(r8), intent(in) :: wf_gravels(1:nl_soil) !gravimetric frac of gravels
+ real(r8), intent(in) :: wf_sand (1:nl_soil) !gravimetric frac of sand
+
+ real(r8), intent(in) :: BA_alpha (1:nl_soil) !alpha in Balland and Arp(2005) thermal cond.
+ real(r8), intent(in) :: BA_beta (1:nl_soil) !beta in Balland and Arp(2005) thermal cond.
+
+ real(r8), intent(in) :: cv_gimp (1:nl_soil) !heat capacity of urban impervious [J/m3/K]
+ real(r8), intent(in) :: tk_gimp (1:nl_soil) !thermal cond. of urban impervious [W/m/K]
+
+ real(r8), intent(in) :: dz_gimpsno(lb :nl_soil) !layer thickness [m]
+ real(r8), intent(in) :: z_gimpsno (lb :nl_soil) !node depth [m]
+ real(r8), intent(in) :: zi_gimpsno(lb-1:nl_soil) !interface depth [m]
+
+ real(r8), intent(in) :: sabgimp !solar radiation absorbed by ground [W/m2]
+ real(r8), intent(in) :: lgimp !atmospheric longwave radiation [W/m2]
+ real(r8), intent(in) :: clgimp !deriv. of longwave wrt to soil temp [w/m2/k]
+ real(r8), intent(in) :: fsengimp !sensible heat flux from ground [W/m2]
+ real(r8), intent(in) :: fevpgimp !evaporation heat flux from ground [mm/s]
+ real(r8), intent(in) :: cgimp !deriv. of gimp energy flux to T [w/m2/k]
+ real(r8), intent(in) :: htvp !latent heat of vapor (or sublimation) [j/kg]
+
+ real(r8), intent(inout) :: t_gimpsno (lb:nl_soil) !soil temperature [K]
+ real(r8), intent(inout) :: wice_gimpsno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_gimpsno(lb:nl_soil) !liqui water [kg/m2]
+ real(r8), intent(inout) :: scv_gimp !snow cover, water equivalent [mm, kg/m2]
+ real(r8), intent(inout) :: snowdp_gimp !snow depth [m]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change in soil
+ real(r8), intent(out) :: fact (lb:nl_soil) !used in computing tridiagonal matrix
+ integer, intent(out) :: imelt(lb:nl_soil) !flag for melting or freezing [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) cv (lb:nl_soil) !heat capacity [J/(m2 K)]
+ real(r8) tk (lb:nl_soil) !thermal conductivity [W/(m K)]
+
+ real(r8) hcap(1:nl_soil) !J/(m3 K)
+ real(r8) thk(lb:nl_soil) !W/(m K)
+ real(r8) rhosnow !partial density of water (ice + liquid)
+
+ real(r8) at (lb:nl_soil) !"a" vector for tridiagonal matrix
+ real(r8) bt (lb:nl_soil) !"b" vector for tridiagonal matrix
+ real(r8) ct (lb:nl_soil) !"c" vector for tridiagonal matrix
+ real(r8) rt (lb:nl_soil) !"r" vector for tridiagonal solution
+
+ real(r8) fn (lb:nl_soil) !heat diffusion through the layer interface [W/m2]
+ real(r8) fn1(lb:nl_soil) !heat diffusion through the layer interface [W/m2]
+ real(r8) dzm !used in computing tridiagonal matrix
+ real(r8) dzp !used in computing tridiagonal matrix
+
+ real(r8) t_gimpsno_bef(lb:nl_soil) !soil/snow temperature before update
+ real(r8) hs !net energy flux into the surface (w/m2)
+ real(r8) dhsdt !d(hs)/dT
+ real(r8) brr(lb:nl_soil) !temporary set
+
+ real(r8) vf_water(1:nl_soil) !volumetric fraction liquid water within soil
+ real(r8) vf_ice (1:nl_soil) !volumetric fraction ice len within soil
+
+ integer i,j
+
+!-----------------------------------------------------------------------
+
+ wice_gimpsno(2:) = 0.0 !ice lens [kg/m2]
+ wliq_gimpsno(2:) = 0.0 !liquid water [kg/m2]
+
+!=======================================================================
+! soil ground and wetland heat capacity
+ DO i = 1, nl_soil
+ vf_water(i) = wliq_gimpsno(i)/(dz_gimpsno(i)*denh2o)
+ vf_ice(i) = wice_gimpsno(i)/(dz_gimpsno(i)*denice)
+ CALL soil_hcap_cond(vf_gravels(i),vf_om(i),vf_sand(i),porsl(i),&
+ wf_gravels(i),wf_sand(i),k_solids(i),&
+ csol(i),dkdry(i),dksatu(i),dksatf(i),&
+ BA_alpha(i),BA_beta(i),&
+ t_gimpsno(i),vf_water(i),vf_ice(i),hcap(i),thk(i))
+ cv(i) = hcap(i)*dz_gimpsno(i)
+ ENDDO
+ IF(lb==1 .and. scv_gimp>0.) cv(1) = cv(1) + cpice*scv_gimp
+
+! Snow heat capacity
+ IF(lb <= 0)THEN
+ cv(:0) = cpliq*wliq_gimpsno(:0) + cpice*wice_gimpsno(:0)
+ ENDIF
+
+! Snow thermal conductivity
+ IF(lb <= 0)THEN
+ DO i = lb, 0
+ rhosnow = (wice_gimpsno(i)+wliq_gimpsno(i))/dz_gimpsno(i)
+
+ ! presently option [1] is the default option
+ ! [1] Jordan (1991) pp. 18
+ thk(i) = tkair+(7.75e-5*rhosnow+1.105e-6*rhosnow*rhosnow)*(tkice-tkair)
+
+ ! [2] Sturm et al (1997)
+ ! thk(i) = 0.0138 + 1.01e-3*rhosnow + 3.233e-6*rhosnow**2
+ ! [3] Ostin and Andersson presented in Sturm et al., (1997)
+ ! thk(i) = -0.871e-2 + 0.439e-3*rhosnow + 1.05e-6*rhosnow**2
+ ! [4] Jansson(1901) presented in Sturm et al. (1997)
+ ! thk(i) = 0.0293 + 0.7953e-3*rhosnow + 1.512e-12*rhosnow**2
+ ! [5] Douville et al., (1995)
+ ! thk(i) = 2.2*(rhosnow/denice)**1.88
+ ! [6] van Dusen (1992) presented in Sturm et al. (1997)
+ ! thk(i) = 0.021 + 0.42e-3*rhosnow + 0.22e-6*rhosnow**2
+
+ ENDDO
+ ENDIF
+
+! Thermal conductivity at the layer interface
+ DO i = lb, nl_soil-1
+
+! the following consideration is try to avoid the snow conductivity
+! to be dominant in the thermal conductivity of the interface.
+! Because when the distance of bottom snow node to the interface
+! is larger than that of interface to top soil node,
+! the snow thermal conductivity will be dominant, and the result is that
+! lees heat transfer between snow and soil
+ IF((i==0) .and. (z_gimpsno(i+1)-zi_gimpsno(i) 0.) tk(1:) = tk_gimp(1:)
+ WHERE (cv_gimp > 0.) cv(1:) = cv_gimp(1:)*dz_gimpsno(1:)
+
+ ! snow exist when there is no snow layer
+ IF (lb == 1 .and. scv_gimp > 0.0) THEN
+ cv(1) = cv(1) + cpice*scv_gimp
+ ENDIF
+
+ ! ponding water or ice exist
+ cv(1) = cv(1) + cpliq*wliq_gimpsno(1) + cpice*wice_gimpsno(1)
+
+! net ground heat flux into the surface and its temperature derivative
+ hs = sabgimp + lgimp - (fsengimp+fevpgimp*htvp)
+ dhsdT = - cgimp + clgimp
+
+ t_gimpsno_bef(lb:) = t_gimpsno(lb:)
+
+ j = lb
+ fact(j) = deltim / cv(j) * dz_gimpsno(j) &
+ / (0.5*(z_gimpsno(j)-zi_gimpsno(j-1)+capr*(z_gimpsno(j+1)-zi_gimpsno(j-1))))
+
+ DO j = lb + 1, nl_soil
+ fact(j) = deltim/cv(j)
+ ENDDO
+
+ DO j = lb, nl_soil - 1
+ fn(j) = tk(j)*(t_gimpsno(j+1)-t_gimpsno(j))/(z_gimpsno(j+1)-z_gimpsno(j))
+ ENDDO
+ fn(nl_soil) = 0.
+
+! set up vector r and vectors a, b, c that define tridiagonal matrix
+ j = lb
+ dzp = z_gimpsno(j+1)-z_gimpsno(j)
+ at(j) = 0.
+ bt(j) = 1+(1.-cnfac)*fact(j)*tk(j)/dzp-fact(j)*dhsdT
+ ct(j) = -(1.-cnfac)*fact(j)*tk(j)/dzp
+ rt(j) = t_gimpsno(j) + fact(j)*( hs - dhsdT*t_gimpsno(j) + cnfac*fn(j) )
+
+
+ DO j = lb + 1, nl_soil - 1
+ dzm = (z_gimpsno(j)-z_gimpsno(j-1))
+ dzp = (z_gimpsno(j+1)-z_gimpsno(j))
+ at(j) = - (1.-cnfac)*fact(j)* tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm)
+ ct(j) = - (1.-cnfac)*fact(j)* tk(j)/dzp
+ rt(j) = t_gimpsno(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ENDDO
+
+ j = nl_soil
+ dzm = (z_gimpsno(j)-z_gimpsno(j-1))
+ at(j) = - (1.-cnfac)*fact(j)*tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*tk(j-1)/dzm
+ ct(j) = 0.
+ rt(j) = t_gimpsno(j) - cnfac*fact(j)*fn(j-1)
+
+! solve for t_gimpsno
+ i = size(at)
+ CALL tridia (i ,at ,bt ,ct ,rt ,t_gimpsno)
+
+!=======================================================================
+! melting or freezing
+!=======================================================================
+
+ DO j = lb, nl_soil - 1
+ fn1(j) = tk(j)*(t_gimpsno(j+1)-t_gimpsno(j))/(z_gimpsno(j+1)-z_gimpsno(j))
+ ENDDO
+ fn1(nl_soil) = 0.
+
+ j = lb
+ brr(j) = cnfac*fn(j) + (1.-cnfac)*fn1(j)
+
+ DO j = lb + 1, nl_soil
+ brr(j) = cnfac*(fn(j)-fn(j-1)) + (1.-cnfac)*(fn1(j)-fn1(j-1))
+ ENDDO
+
+ CALL meltf_urban (lb,1,deltim, &
+ fact(lb:1),brr(lb:1),hs,dhsdT, &
+ t_gimpsno_bef(lb:1),t_gimpsno(lb:1), &
+ wliq_gimpsno(lb:1),wice_gimpsno(lb:1),imelt(lb:1), &
+ scv_gimp,snowdp_gimp,sm,xmf)
+
+ END SUBROUTINE UrbanImperviousTem
+
+END MODULE MOD_Urban_ImperviousTemperature
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_LAIReadin.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_LAIReadin.F90
new file mode 100644
index 0000000000..3b1de1a0b7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_LAIReadin.F90
@@ -0,0 +1,83 @@
+#include
+
+#ifdef URBAN_MODEL
+MODULE MOD_Urban_LAIReadin
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanLAI_readin
+
+CONTAINS
+
+ SUBROUTINE UrbanLAI_readin (year, time, dir_landdata)
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Read in urban LAI, SAI and urban tree cover data.
+!
+! Create by Hua Yuan, 11/2021
+!
+!
+! !REVISIONS:
+! 08/2023, Wenzong Dong: add codes to read urban tree LAI.
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+ USE MOD_Vars_Global
+ USE MOD_Const_LC
+ USE MOD_Vars_TimeVariables
+ USE MOD_Vars_TimeInvariants
+ USE MOD_Urban_Vars_TimeInvariants
+ USE MOD_NetCDFVector
+ USE MOD_UserDefFun
+#ifdef SinglePoint
+ USE MOD_SingleSrfdata
+#endif
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: year
+ integer, intent(in) :: time
+ character(len=256), intent(in) :: dir_landdata
+
+ character(len=256) :: lndname
+ character(len=256) :: cyear, ctime
+ integer :: u, npatch, iyear
+
+ ! READ in Leaf area index and stem area index
+ write(ctime,'(i2.2)') time
+ write(cyear,'(i4.4)') min(DEF_LAI_END_YEAR, max(DEF_LAI_START_YEAR,year) )
+
+#ifdef SinglePoint
+ iyear = findloc_ud(SITE_LAI_year == min(DEF_LAI_END_YEAR, max(DEF_LAI_START_YEAR,year)) )
+ urb_lai(:) = SITE_LAI_monthly(time,iyear)
+ urb_sai(:) = SITE_SAI_monthly(time,iyear)
+#else
+ lndname = trim(dir_landdata)//'/urban/'//trim(cyear)//'/LAI/urban_LAI_'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'TREE_LAI', landurban, urb_lai)
+
+ lndname = trim(dir_landdata)//'/urban/'//trim(cyear)//'/LAI/urban_SAI_'//trim(ctime)//'.nc'
+ CALL ncio_read_vector (lndname, 'TREE_SAI', landurban, urb_sai)
+#endif
+ ! loop for urban patch to assign fraction of green leaf
+ IF (p_is_compute) THEN
+ DO u = 1, numurban
+ npatch = urban2patch(u)
+ tlai(npatch) = urb_lai(u)
+ tsai(npatch) = urb_sai(u)
+ urb_green(u) = 1. !TODO: usage? fraction of green leaf
+ green(npatch)= 1. !fraction of green leaf
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE UrbanLAI_readin
+
+END MODULE MOD_Urban_LAIReadin
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_LUCY.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_LUCY.F90
new file mode 100644
index 0000000000..a07505998b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_LUCY.F90
@@ -0,0 +1,181 @@
+#include
+
+MODULE MOD_Urban_LUCY
+! -----------------------------------------------------------------------
+! !DESCRIPTION:
+! Anthropogenic model to calculate anthropogenic heat flux for the rest
+!
+! Original: Wenzong Dong, May, 2022
+!
+! -----------------------------------------------------------------------
+! !USE
+ USE MOD_Precision
+ USE MOD_TimeManager
+ USE MOD_Namelist
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical
+ USE MOD_TimeManager
+ IMPLICIT NONE
+ SAVE
+ PUBLIC :: LUCY
+
+CONTAINS
+
+ SUBROUTINE LUCY( idate , deltim , patchlonr, fix_holiday, &
+ week_holiday, hum_prof, wdh_prof , weh_prof , pop_den, &
+ vehicle , Fahe , vehc , meta )
+
+! -----------------------------------------------------------------------
+! !DESCRIPTION:
+! Anthropogenic heat fluxes other than building heat were calculated
+!
+! !REFERENCES:
+! 1) Grimmond, C. S. B. (1992). The suburban energy balance:
+! Methodological considerations and results for a mid-latitude west
+! coast city under winter and spring conditions. International Journal
+! of Climatology, 12(5), 481-497. https://doi.org/10.1002/joc.3370120506
+!
+! 2) Allen, L., Lindberg, F., & Grimmond, C. S. B. (2011). Global to
+! city scale urban anthropogenic heat flux: Model and variability.
+! International Journal of Climatology, 31(13), 1990-2005.
+! https://doi.org/10.1002/joc.2210
+!
+! -----------------------------------------------------------------------
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer , intent(in) :: &
+ idate(3) ! calendar (year, julian day, seconds)
+
+ real(r8), intent(in) :: &
+ fix_holiday(365) ,&! Fixed public holidays, holiday(0) or workday(1)
+ week_holiday(7) ! week holidays
+
+ real(r8), intent(in) :: &
+ deltim ,&! seconds in a time step [second]
+ patchlonr ,&! longitude of patch [radian]
+ hum_prof(24) ,&! Diurnal metabolic heat profile [W/person]
+ wdh_prof(24) ,&! Diurnal traffic flow profile of weekday
+ weh_prof(24) ,&! Diurnal traffic flow profile of weekend
+ pop_den ,&! population density [person per square kilometer]
+ vehicle(3) ! vehicle numbers per thousand people
+
+ real(r8) :: &
+ vehc_prof(24,2) ,&!
+ carscell ,&! cars numbers per thousand people
+ frescell ,&! freights numbers per thousand people
+ mbkscell ! motobikes numbers per thousand people
+
+ real(r8), intent(out) :: &
+ Fahe ,&! flux from metabolic and vehicle
+ vehc ,&! flux from vehicle
+ meta ! flux from metabolic
+
+ real(r8) :: &
+ londeg ,&! longitude of path [degree]
+ car_sp ,&! distance traveled [km]
+ traf_frac ,&! vehicle heat profile of hour [-]
+ meta_prof ,&! metabolic heat profile of hour [-]
+ carflx ,&! flux from car [W/m2]
+ motflx ,&! flux from motorbike [W/m2]
+ freflx ! flux from freight [W/m2]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8):: ldate(3) ! local time (year, julian day, seconds)
+ integer :: &
+ iweek ,&! day of week
+ ihour ,&! hour of day
+ day ,&! day of month
+ month ,&! month of year
+ day_inx ,&! holiday index, day=1(workday), day=1(holiday)
+ EC ,&! emission factor of car [J/m]
+ EF ,&! emission factor of freight [J/m]
+ EM ! emission factor of motorbike [J/m]
+
+!-----------------------------------------------------------------------
+
+ ! initialization
+ meta = 0.
+ vehc = 0.
+ Fahe = 0.
+
+ ! set vehicle distance traveled
+ car_sp = 50
+
+ ! emission factor Sailor and Lu (2004),
+ ! all vehicle are set to same value
+ EC = 3975
+ EM = 3975
+ EF = 3975
+
+ IF (DEF_simulation_time%greenwich) THEN
+ ! convert GMT time to local time
+ londeg = patchlonr*180/PI
+ CALL gmt2local(idate, londeg, ldate)
+ ENDIF
+
+ vehc_prof(:,1) = wdh_prof
+ vehc_prof(:,2) = weh_prof
+
+ CALL julian2monthday(int(ldate(1)), int(ldate(2)), month, day)
+ CALL timeweek(int(ldate(1)), month, day, iweek)
+
+ ihour = CEILING(ldate(3)*1./3600)
+
+ IF (day==366) day=365
+ IF (fix_holiday(day)==0 .or. week_holiday(iweek)==0) THEN
+ day_inx = 1
+ ELSE
+ day_inx = 2
+ ENDIF
+
+ ! set traffic flow to be used of this time step
+ traf_frac = vehc_prof(ihour,day_inx)
+ ! set heat release per people of this time step
+ meta_prof = hum_prof (ihour)
+
+ carscell = vehicle(1)
+ mbkscell = vehicle(2)
+ frescell = vehicle(3)
+
+ ! heat release of metabolism [W/m2]
+ meta = pop_den*meta_prof/1e6
+ ! heat release of cars [W/m2]
+ IF (carscell > 0) THEN
+ carflx = carscell*pop_den/1000
+ carflx = carflx*traf_frac &
+ *EC*(car_sp*1000)/1e6
+ carflx = carflx/3600
+ ELSE
+ carflx = 0.
+ ENDIF
+
+ ! heat release of motorbikes [W/m2]
+ IF (mbkscell > 0) THEN
+ motflx = mbkscell*pop_den/1000
+ motflx = motflx*traf_frac &
+ *EM*(car_sp*1000)/1e6
+ motflx = motflx/3600
+ ELSE
+ motflx = 0.
+ ENDIF
+
+ ! heat release of freight [W/m2]
+ IF (frescell > 0)THEN
+ freflx = frescell*pop_den/1000
+ freflx = freflx*traf_frac &
+ *EF*(car_sp*1000)/1e6
+ freflx = freflx/3600
+ ELSE
+ freflx = 0.
+ ENDIF
+
+ ! total vehicle heat flux
+ vehc = carflx + motflx + freflx
+ ! total anthropogenic heat flux exclude building part
+ Fahe = meta + vehc
+
+ END Subroutine LUCY
+
+END MODULE MOD_Urban_LUCY
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Longwave.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Longwave.F90
new file mode 100644
index 0000000000..760774abef
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Longwave.F90
@@ -0,0 +1,678 @@
+#include
+
+MODULE MOD_Urban_Longwave
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: stefnc
+ USE MOD_Urban_Shortwave, only: MatrixInverse
+ USE MOD_Urban_Shortwave, only: ShadowWall_dir
+ USE MOD_Urban_Shortwave, only: ShadowWall_dif
+ USE MOD_Urban_Shortwave, only: ShadowTree
+ USE MOD_3DCanopyRadiation, only: tee, phi
+
+ IMPLICIT NONE
+ SAVE
+ PRIVATE
+
+ PUBLIC :: UrbanOnlyLongwave !Urban Longwave radiation transfer
+ PUBLIC :: UrbanVegLongwave !Urban Longwave radiation transfer with trees
+
+CONTAINS
+
+ SUBROUTINE UrbanOnlyLongwave (theta, HL, fb, fgper, H, LW, &
+ twsun, twsha, tgimp, tgper, ewall, egimp, egper, &
+ Ainv, B, B1, dBdT, SkyVF, fcover)
+
+!-----------------------------------------------------------------------
+! Sun
+! \\\
+! \\\
+! ______
+! |++++++| roof
+! |++++++| ______
+! |++++++| |++++++|
+! ______+++++| |++++++|
+! |++++++|++++| |++++++|
+! sunlit |[]++[]|++++| |++++++| shaded
+! wall |++++++| |++++++| wall
+! |[]++[]| |++++++|
+! |++++++| impervious/pervious ground
+! __________|++++++|____________________________________
+!
+!
+! !DESCRIPTION:
+!
+! The process of long-wave radiation transmission in the absence of
+! vegetation is similar to the incident diffuse case of short-wave
+! radiation transmission in the absence of vegetation (where long-wave
+! radiation is approximated as a diffuse source). The long-wave
+! radiation flux reaching each component surface is calculated, as well
+! as the long-wave radiation emitted outward from each component
+! surface. Multiple scattering and absorption between components are
+! considered, and a long-wave radiation transmission equilibrium
+! equation is established for solving.
+!
+! Created by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ theta, &! Sun zenith angle [radian]
+ HL, &! Ratio of building height to ground width [-]
+ fb, &! Fraction of building area [-]
+ fgper, &! Fraction of impervious ground [-]
+ H, &! Building average height [m]
+ LW, &! Downward longwave radiation [W/m2]
+
+ twsun, &! Temperature of sunlit wall [K]
+ twsha, &! Temperature of shaded wall [K]
+ tgimp, &! Temperature of impervious road [K]
+ tgper, &! Temperature of pervious road [K]
+
+ ewall, &! Emissivity of walls [-]
+ egimp, &! Emissivity of ground [-]
+ egper ! Emissivity of ground [-]
+
+ real(r8), intent(out) :: &
+ Ainv(4,4), &! Inverse of Radiation transfer matrix
+ B(4), &! Vectors of incident radiation on each surface
+ B1(4), &! Vectors of incident radiation on each surface
+ dBdT(4), &! Vectors of incident radiation on each surface
+ SkyVF(4), &! View factor to sky
+ fcover(0:4) ! View factor to sky
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ W, &! Urban ground average width [m]
+ L, &! Urban building average length [m]
+ HW, &! Ratio of H to W, H/W [-]
+ fg, &! Fraction of ground [-]
+ fgimp, &! Fraction of snow ground [-]
+
+ Fsw, &! View factor from sky to wall [-]
+ Fsg, &! View factor from sky to ground [-]
+ Fgw, &! View factor from ground to wall [-]
+ Fgs, &! View factor from ground to sky [-]
+ Fww, &! View factor from wall to wall [-]
+ Fwg, &! View factor from wall to ground [-]
+ Fws, &! View factor from wall to sky [-]
+
+ Sw, &! Shadow of wall [-]
+ fwsun, &! Fraction of sunlit wall [-]
+ fwsha, &! Fraction of shaded wall [-]
+ Iwsun, &! Incident radiation on sunlit wall [W/m2]
+ Iwsha, &! Incident radiation on shaded wall [W/m2]
+ Ig, &! Incident radiation on ground [W/m2]
+ Igimp, &! Incident radiation on impervious ground [W/m2]
+ Igper ! Incident radiation on pervious ground [W/m2]
+
+ real(r8) :: A(4,4) !Radiation transfer matrix
+
+ ! Temporal
+ real(r8) :: tmp, eb
+!-----------------------------------------------------------------------
+
+ ! Calculate urban structure parameters
+ !-------------------------------------------------
+ !W = H/HW
+ !L = W*sqrt(fb)/(1-sqrt(fb))
+ !HL = H/L !NOTE: Same as HL = HW*(1-sqrt(fb))/sqrt(fb)
+ fg = 1. - fb
+ fgimp = 1. - fgper
+
+ ! Calculate view factors
+ !-------------------------------------------------
+
+ ! View factor from sky to wall(sunlit+shaded) and ground
+ Fsw = ShadowWall_dif(fb/fg, HL)
+ Fsg = 1 - Fsw
+
+ ! View factor from ground to walls and sky
+ Fgw = Fsw
+ Fgs = Fsg
+
+ ! View factor from wall to wall, sky and ground
+ ! Fws*4*H*L/L/L = Fws*4H/L*fb = Fsw*fg
+ ! Fws*4HL*fb = Fsw*fg
+ ! Fws = Fsw*fg/(4HL*fb)
+ ! Adjusted as below:
+ Fws = Fsw*fg/fb/(4*HL)
+ Fwg = Fsw*fg/fb/(4*HL)
+ Fww = 1 - Fws - Fwg
+
+ ! Calculate sunlit wall fraction
+ !-------------------------------------------------
+
+ ! Building shadow on the ground
+ Sw = ShadowWall_dir(fb/fg, HL, theta)
+
+ ! Sunlit/shaded wall fraction
+ fwsun = 0.5 * (Sw*fg + fb) / (4/PI*fb*HL*tan(theta) + fb)
+ fwsha = 1. - fwsun
+
+ ! Calculate radiation transfer matrix
+ ! AX = B
+ ! o A: radiation transfer matrix
+ ! o B: incident radiation on each surface
+ ! o X: radiation emit from each surface
+ !-------------------------------------------------
+ A(1,:) = (/1-Fww*fwsun*(1-ewall), -Fww*fwsun*(1-ewall), &
+ -Fgw*fwsun*(1-ewall), -Fgw*fwsun*(1-ewall) /)
+
+ A(2,:) = (/ -Fww*fwsha*(1-ewall), 1-Fww*fwsha*(1-ewall), &
+ -Fgw*fwsha*(1-ewall), -Fgw*fwsha*(1-ewall) /)
+
+ A(3,:) = (/ -Fwg*fgimp*(1-egimp), -Fwg*fgimp*(1-egimp), &
+ 1._r8, 0._r8 /)
+
+ A(4,:) = (/ -Fwg*fgper*(1-egper), -Fwg*fgper*(1-egper), &
+ 0._r8, 1._r8 /)
+
+ ! Inverse of matrix A
+ Ainv = MatrixInverse(A)
+
+ ! Incident LW radiation on sunlit/shaded wall and
+ ! impervious/pervious ground
+ Iwsun = LW*Fsw*fwsun
+ Iwsha = LW*Fsw*fwsha
+ Ig = LW*Fsg
+ Igimp = Ig*fgimp
+ Igper = Ig*fgper
+
+ ! Vector of initial LW radiation on each surface
+ !NOTE: for 3D, absorption per unit area: 4*HL*fb/fg
+ ! for canyon: absorption per unit area: 2*HW
+ B(1) = Iwsun*(1.-ewall) + 4*fwsun*HL*fb/fg*stefnc*ewall*twsun**4
+ B(2) = Iwsha*(1.-ewall) + 4*fwsha*HL*fb/fg*stefnc*ewall*twsha**4
+ !B(1) = Iwsun*(1.-ewall) + 2*fwsun*HW*stefnc*ewall*twsun**4
+ !B(2) = Iwsha*(1.-ewall) + 2*fwsha*HW*stefnc*ewall*twsha**4
+ B(3) = Igimp*(1.-egimp) + fgimp*stefnc*egimp*tgimp**4
+ B(4) = Igper*(1.-egper) + fgper*stefnc*egper*tgper**4
+
+ B1(1) = 4*fwsun*HL*fb/fg*stefnc*ewall*twsun**4
+ B1(2) = 4*fwsha*HL*fb/fg*stefnc*ewall*twsha**4
+ !B1(1) = 2*fwsun*HW*stefnc*ewall*twsun**4
+ !B1(2) = 2*fwsha*HW*stefnc*ewall*twsha**4
+ B1(3) = fgimp*stefnc*egimp*tgimp**4
+ B1(4) = fgper*stefnc*egper*tgper**4
+
+ dBdT(1) = 16*fwsun*HL*fb/fg*stefnc*ewall*twsun**3
+ dBdT(2) = 16*fwsha*HL*fb/fg*stefnc*ewall*twsha**3
+ !dBdT(1) = 2*fwsun*HW*stefnc*ewall*twsun**3
+ !dBdT(2) = 2*fwsha*HW*stefnc*ewall*twsha**3
+ dBdT(3) = 4*fgimp*stefnc*egimp*tgimp**3
+ dBdT(4) = 4*fgper*stefnc*egper*tgper**3
+
+ SkyVF(1:2) = Fws
+ SkyVF(3:4) = Fgs
+
+ fcover(0) = fb
+ fcover(1) = 4*fwsun*HL*fb
+ fcover(2) = 4*fwsha*HL*fb
+ fcover(3) = fg*fgimp
+ fcover(4) = fg*fgper
+
+ !NOTE: the below codes put into the THERMAL.F90
+ ! Equation solve
+ ! X = matmul(Ainv, B)
+
+ ! LW radiation absorption by each surface (per m^2)
+ !lwsun = ( ewall*X(1) - B1(1) ) / (1-ewall) !/ (4*fwsun*HL*fb/fg)
+ !lwsha = ( ewall*X(2) - B1(2) ) / (1-ewall) !/ (4*fwsha*HL*fb/fg)
+ !lgimp = ( egimp*X(3) - B1(3) ) / (1-egimp) !/ fgimp
+ !lgper = ( egper*X(4) - B1(4) ) / (1-egper) !/ fgper
+
+ ! Out-going LW of urban canopy
+ !lout = X(1)*Fws + X(2)*Fws + X(3)*Fgs + X(4)*Fgs
+ !lout = sum( X * SkyVF )
+
+ ! Energy balance check
+ !eb = lwsun + lwsha + lgimp + lgper + lout
+
+ !IF (abs(eb-LW) > 1e-6) THEN
+ ! print *, "Longwave - Energy Balance Check error!", eb-LW
+ !ENDIF
+
+ !NOTE: put it outside, after temperature change of roof, wall and ground
+ ! absorption change due to temperature change, as restart variables.
+ !dX = matmul(Ainv, dBdT*dT)
+ !lwsun = ( ewall*dX(1) - dBdT(1)*dT(1) ) / (1-ewall) !/ (4*fwsun*HL*fb/fg)
+ !lwsha = ( ewall*dX(2) - dBdT(2)*dT(2) ) / (1-ewall) !/ (4*fwsha*HL*fb/fg)
+ !lgimp = ( egimp*dX(3) - dBdT(3)*dT(3) ) / (1-egimp) !/ fgimp
+ !lgper = ( egper*dX(4) - dBdT(4)*dT(4) ) / (1-egper) !/ fgper
+
+ !lout = lout + sum( dX * SkyVF )
+
+ END SUBROUTINE UrbanOnlyLongwave
+
+
+ SUBROUTINE UrbanVegLongwave (theta, HL, fb, fgper, H, LW, &
+ twsun, twsha, tgimp, tgper, ewall, egimp, egper, lai, sai, fv, hv, &
+ ev, Ainv, B, B1, dBdT, SkyVF, VegVF, fcover)
+
+!-----------------------------------------------------------------------
+! Sun
+! \\\
+! \\\
+! ______
+! |++++++| roof
+! |++++++| ______
+! |++++++| ___ |++++++|
+! ______+++++| ||||| |++++++|
+! |++++++|++++| ||||||| |++++++|
+! sunlit |[]++[]|++++| ||||| |++++++| shaded
+! wall |++++++| | tree |++++++| wall
+! |[]++[]| | |++++++|
+! |++++++| impervious/pervious ground
+! __________|++++++|___________________________________
+!
+! !DESCRIPTION:
+!
+! The calculation of longwave radiation when considering vegetation
+! (trees only) is similar to the shortwave radiation transmission with
+! vegetation. On the basis of the longwave radiation transmission
+! balance equation without vegetation, a balanced equation with
+! vegetation is constructed, and the solution process is similar.
+!
+! Created by Hua Yuan, 09/2021
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ theta, &! Sun zenith angle [radian]
+ HL, &! Ratio of building height to ground width [-]
+ fb, &! Fraction of building area [-]
+ fgper, &! Fraction of impervious ground [-]
+ H, &! Building average height [m]
+ LW, &! Downward longwave radiation [W/m2]
+
+ twsun, &! Temperature of sunlit wall [K]
+ twsha, &! Temperature of shaded wall [K]
+ tgimp, &! Temperature of impervious road [K]
+ tgper, &! Temperature of pervious road [K]
+
+ ewall, &! Emissivity of walls [-]
+ egimp, &! Emissivity of ground [-]
+ egper, &! Emissivity of ground [-]
+ lai, &! leaf area index [m2/m2]
+ sai, &! stem area index [m2/m2]
+ fv, &! Fraction of tree cover [-]
+ hv ! Crown central height [m]
+
+ real(r8), intent(out) :: &
+ ev, &! emissivity of vegetation
+ Ainv(5,5), &! Inverse of Radiation transfer matrix
+ B(5), &! Vectors of incident radiation on each surface
+ B1(5), &! Vectors of incident radiation on each surface
+ dBdT(5), &! Vectors of incident radiation on each surface
+ SkyVF(5), &! View factor to sky
+ VegVF(5), &! View factor to sky
+ fcover(0:5) ! View factor to sky
+
+!-------------------------- Local Variables ----------------------------
+ real(r16),parameter :: DD1=1.0_r16 !quad accuracy real number
+
+ real(r8) :: &
+ W, &! Urban ground average width [m]
+ L, &! Urban building average length [m]
+ HW, &! Ratio of H to W, H/W [-]
+ fg, &! Fraction of ground [-]
+ fgimp, &! Fraction of pervious ground [-]
+
+ Fsw, &! View factor from sky to wall [-]
+ Fsg, &! View factor from sky to ground [-]
+ Fgw, &! View factor from ground to wall [-]
+ Fgs, &! View factor from ground to sky [-]
+ Fww, &! View factor from wall to wall [-]
+ Fwg, &! View factor from wall to ground [-]
+ Fws, &! View factor from wall to sky [-]
+
+ Fvg, &! View factor from tree to ground [-]
+ Fvs, &! View factor from tree to sky [-]
+ Fvw, &! View factor from tree to walls (sunlit+shaded) [-]
+ Fwv, &! View factor from wall to tree [-]
+ Fgv, &! View factor from ground to tree [-]
+ Fsv, &! View factor from sky to tree [-]
+
+ Fgvs, &! View factor from ground->|tree|-> to sky [-]
+ Fgvw, &! View factor from ground->|tree|-> to walls [-]
+ Fsvg, &! View factor from sky->|tree|-> to ground [-]
+ Fsvw, &! View factor from sky->|tree|-> to walls [-]
+ Fwvw, &! View factor from walls->|tree|-> to walls [-]
+ Fwvs, &! View factor from walls->|tree|-> to sky [-]
+ Fwvg, &! View factor from walls->|tree|-> to ground [-]
+
+ Fsw_, &! Fsw - Fsvw + Fsvw*Td [-]
+ Fsg_, &! Fsg - Fsvg + Fsvg*Td [-]
+ Fgw_, &! Fgw - Fgvw + Fgvw*Td [-]
+ Fgs_, &! Fgs - Fgvs + Fgvs*Td [-]
+ Fwg_, &! Fwg - Fwvg + Fwvg*Td [-]
+ Fww_, &! Fww - Fwvw + Fwvw*Td [-]
+ Fws_, &! Fws - Fwvs + Fwvs*Td [-]
+
+ Sw, &! Shadow of wall [-]
+ Sw_, &! Shadow of wall [-]
+ Sv, &! Shadow of trees [-]
+ Swv, &! Overlapped shadow between wall and trees [-]
+ fv_, &! Fraction of trees [-]
+ Td, &! Transmission of tree [-]
+ fwsun, &! Fraction of sunlit wall [-]
+ fwsha, &! Fraction of shaded wall [-]
+ Iwsun, &! Incident radiation on sunlit wall [W/m2]
+ Iwsha, &! Incident radiation on shaded wall [W/m2]
+ Ig, &! Incident radiation on ground [W/m2]
+ Igimp, &! Incident radiation on impervious ground [W/m2]
+ Igper, &! Incident radiation on pervious ground [W/m2]
+ Iv ! Incident radiation on trees [W/m2]
+
+ ! Radiation transfer matrix and vectors
+ !-------------------------------------------------
+ real(r8) :: A(5,5) !Radiation transfer matrix
+
+ ! Temporal
+ real(r8) :: tmp, eb, fac1, fac2, lsai
+!-----------------------------------------------------------------------
+
+ ! Calculate urban structure parameters
+ !-------------------------------------------------
+ !W = H/HW
+ !L = W*sqrt(fb)/(1-sqrt(fb))
+ !HL = H/L !NOTE: Same as HL = HW*(1-sqrt(fb))/sqrt(fb)
+ L = H/HL
+ fg = 1. - fb
+
+ fgimp = 1. - fgper
+
+ ! Calculate transmission and albedo of tree
+ !-------------------------------------------------
+ lsai = (lai+sai)*fv/cos(PI/3)/ShadowTree(fv, PI/3)
+ Td = tee(DD1*3/8.*lsai)
+ ev = 1 - Td
+
+ ! Calculate view factors
+ !-------------------------------------------------
+
+ ! View factor from sky to wall(sunlit+shaded) and ground
+ Fsw = ShadowWall_dif(fb/fg, HL)
+ Fsg = 1 - Fsw
+
+ ! View factor from ground to walls and sky
+ Fgw = Fsw
+ Fgs = Fsg
+
+ ! View factor from wall to wall, sky and ground
+ ! Fws*4*H*L*L/L = Fws*4H/L*fb = Fsw*fg
+ ! Fws*4HL*fb = Fsw*fg
+ ! Fws = Fsw*fg/(4HL*fb)
+ Fws = Fsw*fg/fb/(4*HL)
+ Fwg = Fsw*fg/fb/(4*HL)
+ Fww = 1 - Fws - Fwg
+
+ ! View factor from tree to walls, ground and sky
+ !-------------------------------------------------
+
+ Sw = ShadowWall_dif(fb/fg, HL)
+ Sw_ = ShadowWall_dif(fb/fg, (H-hv)/L)
+
+ !NOTE: fg*(fv/fg - fv/fg * Sw_)
+ fv_ = fv - fv*Sw_
+ Sv = ShadowTree(fv_, PI/3)
+
+ ! Overlapped shadow between tree and building
+ ! (to ground only)
+ Swv = (Sw-Sw_) * Sv
+
+ ! convert Sv to ground ratio
+ Sv = min(1., Sv/fg)
+
+ ! robust check
+ IF (Sw+Sv-Swv > 1) THEN
+ Swv = Sw+Sv-1
+ ENDIF
+
+ ! Calibrated building ground shadow
+ Fsv = Sv
+ Fsvw = Swv
+ Fsvg = Fsv - Fsvw
+
+ ! View factor from veg to sky and walls above canopy
+ Fvs = 0.5*(1-Sw_)
+ Fvw = 0.5*Sw_
+
+ Sw_ = ShadowWall_dif(fb/fg, hv/L)
+ fv_ = fv - fv*Sw_
+ Sv = ShadowTree(fv_, PI/3)
+
+ ! Overlapped shadow between tree and building
+ ! (to ground only)
+ Swv = (Sw-Sw_) * Sv
+
+ ! convert Sv to ground ratio
+ Sv = min(1., Sv/fg)
+
+ ! robust check
+ IF (Sw+Sv-Swv > 1) THEN
+ Swv = Sw+Sv-1
+ ENDIF
+
+ ! Calibrated building ground shadow
+ Fgv = Sv
+ Fgvw = Swv
+ Fgvs = Fgv - Fgvw
+
+ ! View factor from veg to sky and walls below+above canopy
+ Fvg = 0.5*(1-Sw_)
+ Fvw = 0.5*Sw_ + Fvw
+
+ Fvw = 1 - Fvs - Fvg
+
+ !Fvs = Fsv*fg/min(4*fv,2*fg)
+ !Fvg = Fgv*fg/min(4*fv,2*fg)
+ !Fvw = 1 - Fvs - Fvg
+
+ ! Canopy mode:
+ Fwv = max(fv,0.5*(Fsv+Fgv))*2*fg*Fvw/(4*HL*fb)
+ Fwv = min(0.8, Fwv)
+
+ fac1 = 1.*hv/H
+ fac2 = 1.*(H-hv)/H
+ Fwvw = Fwv/(1 + Fws*fac1/Fww + Fwg*fac2/Fww)
+ Fwvs = Fws*fac1/Fww*Fwvw
+ Fwvg = Fwg*fac2/Fww*Fwvw
+
+ ! set upper limit
+ Fwvw = min(Fww, Fwvw)
+ Fwvs = min(Fws, Fwvs)
+ Fwvg = min(Fwg, Fwvg)
+
+ Fwv = Fwvw + Fwvs + Fwvg
+
+ ! View factors with trees
+ !---------------------------------------------------------
+ Fsw_ = Fsw - Fsvw + Fsvw*Td
+ Fsg_ = Fsg - Fsvg + Fsvg*Td
+ Fgw_ = Fgw - Fgvw + Fgvw*Td
+ Fgs_ = Fgs - Fgvs + Fgvs*Td
+ Fwg_ = Fwg - Fwvg + Fwvg*Td
+ Fww_ = Fww - Fwvw + Fwvw*Td
+ Fws_ = Fws - Fwvs + Fwvs*Td
+
+ ! Calculate wall sunlit fraction
+ !-------------------------------------------------
+
+ ! Building wall shadow
+ Sw = ShadowWall_dir(fb/fg, HL, theta)
+
+ Sw_ = Sw; fv_ = fv;
+
+ Sw_ = ShadowWall_dir(fb/fg, (H-hv)/L, theta)
+ fv_ = fv - fv*Sw_
+
+ ! Tree shadow (to all area)
+ Sv = ShadowTree(fv_, theta)
+
+ ! Overlapped shadow between tree and building
+ ! (to ground only)
+ Swv = (Sw-Sw_) * Sv
+
+ ! convert Sv to ground ratio
+ Sv = min(1., Sv/fg)
+
+ ! robust check
+ IF (Sw+Sv-Swv > 1) THEN
+ Swv = Sw+Sv-1
+ ENDIF
+
+ ! Calibrated building ground shadow
+ Sw = Sw - Swv
+
+ ! Sunlit/shaded wall fraction
+ fwsun = 0.5 * (Sw*fg+fb) / (4/PI*fb*HL*tan(theta) + fb)
+ fwsha = 1. - fwsun
+
+ ! Calculate radiation transfer matrix
+ ! AX = B
+ !-------------------------------------------------
+ A(1,:) = (/1-Fww_*fwsun*(1-ewall), -Fww_*fwsun*(1-ewall), -Fgw_*fwsun*(1-ewall), &
+ -Fgw_*fwsun*(1-ewall), -Fvw *fwsun*(1-ewall) /)
+
+ A(2,:) = (/ -Fww_*fwsha*(1-ewall), 1-Fww_*fwsha*(1-ewall), -Fgw_*fwsha*(1-ewall), &
+ -Fgw_*fwsha*(1-ewall), -Fvw *fwsha*(1-ewall) /)
+
+ A(3,:) = (/ -Fwg_*fgimp*(1-egimp), -Fwg_*fgimp*(1-egimp), 1._r8, &
+ 0._r8, -Fvg *fgimp*(1-egimp) /)
+
+ A(4,:) = (/ -Fwg_*fgper*(1-egper), -Fwg_*fgper*(1-egper), 0._r8, &
+ 1._r8, -Fvg *fgper*(1-egper) /)
+
+ A(5,:) = (/ 0._r8, 0._r8, 0._r8, &
+ 0._r8, 1._r8 /)
+
+ ! Inverse of matrix A
+ Ainv = MatrixInverse(A)
+
+ ! Incident LW radiation on sunlit/shaded wall and
+ ! impervious/pervious ground
+ Iwsun = LW*Fsw_*fwsun
+ Iwsha = LW*Fsw_*fwsha
+ Ig = LW*Fsg_
+ Igimp = Ig*fgimp
+ Igper = Ig*fgper
+ Iv = LW*Fsv
+
+ ! Vector of initial LW radiation on each surface
+ !NOTE: for 3D, absorption per unit area: 4*HL*fb/fg
+ ! for canyon: absorption per unit area: 2*HW
+ B(1) = Iwsun*(1.-ewall) + 4*fwsun*HL*fb/fg*stefnc*ewall*twsun**4
+ B(2) = Iwsha*(1.-ewall) + 4*fwsha*HL*fb/fg*stefnc*ewall*twsha**4
+ B(3) = Igimp*(1.-egimp) + fgimp*stefnc*egimp*tgimp**4
+ B(4) = Igper*(1.-egper) + fgper*stefnc*egper*tgper**4
+ ! leaf temperature iteration in urban flux calculation
+ ! see MOD_Urban_Flux.F90
+ ! B(5) = 4*fv/fg*stefnc*ev*tl**4 !NOTE: 4*fv/fg or 2*fv/fg
+ !4*fv/fg. equivalent to 2fc
+ B(5) = max(2*fv/fg,Fsv+Fgv)*stefnc*ev
+
+ B1(1) = 4*fwsun*HL*fb/fg*stefnc*ewall*twsun**4
+ B1(2) = 4*fwsha*HL*fb/fg*stefnc*ewall*twsha**4
+ B1(3) = fgimp*stefnc*egimp*tgimp**4
+ B1(4) = fgper*stefnc*egper*tgper**4
+ ! leaf temperature iteration in urban flux calculation
+ ! B1(5) = 4*fv/fg*stefnc*ev*tl**4
+ B1(5) = max(2*fv/fg,Fsv+Fgv)*stefnc*ev
+
+ dBdT(1) = 16*fwsun*HL*fb/fg*stefnc*ewall*twsun**3
+ dBdT(2) = 16*fwsha*HL*fb/fg*stefnc*ewall*twsha**3
+ dBdT(3) = 4*fgimp*stefnc*egimp*tgimp**3
+ dBdT(4) = 4*fgper*stefnc*egper*tgper**3
+ ! leaf temperature iteration in urban flux calculation
+ ! dBdT(5) = 16*fv/fg*stefnc*ev*tl**3
+ dBdT(5) = 4*max(2*fv/fg,Fsv+Fgv)*stefnc*ev
+
+ SkyVF(1:2) = Fws_
+ SkyVF(3:4) = Fgs_
+ SkyVF(5) = Fvs
+
+ VegVF(1:2) = Fwv
+ VegVF(3:4) = Fgv
+ VegVF(5) = Fsv
+
+ fcover(0) = fb
+ fcover(1) = 4*fwsun*HL*fb
+ fcover(2) = 4*fwsha*HL*fb
+ fcover(3) = fg*fgimp
+ fcover(4) = fg*fgper
+ fcover(5) = fv
+
+ !NOTE: the below codes are put in the leaf temperature iteration process
+ ! after each iteration, update the below iterms
+ !B(5) = 4*fv/fg*stefnc*ev*tl**4
+ !B1(5) = 4*fv/fg*stefnc*ev*tl**4
+ !dBdT(5) = 16*fv/fg*stefnc*ev*tl**3
+ ! Equation solve
+ !X = matmul(Ainv, B)
+
+ ! LW radiation absorption by each surface (per m^2)
+ !lwsun = ( ewall*X(1) - B1(1) ) / (1-ewall) !/ (4*fwsun*HL*fb/fg)
+ !lwsha = ( ewall*X(2) - B1(2) ) / (1-ewall) !/ (4*fwsha*HL*fb/fg)
+ !lgimp = ( egimp*X(3) - B1(3) ) / (1-egimp) !/ fgimp
+ !lgper = ( egper*X(4) - B1(4) ) / (1-egper) !/ fgper
+
+ !NOTE: before leaf temperature iteration
+ !lv = ((X(1)*Fwv + X(2)*Fwv + X(3)*Fgv + X(4)*Fgv + LW*Fsv)*ev - B1(5))!/(fv/fg)
+
+ ! Out-going LW of urban canopy
+ !SkyVF(1:2) = Fws_; SkyVF(3:4) = Fgs_; SkyVF(5) = Fvs
+ !lout = X(1)*Fws_ + X(2)*Fws_ + X(3)*Fgs_ + X(4)*Fgs_ + X(5)*Fvs
+ !lout = sum( X * SkyVF )
+
+ ! Energy balance check
+ !eb = lwsun + lwsha + lgimp + lgper + lv + lout
+
+ !IF (abs(eb-LW) > 1e-6) THEN
+ ! print *, "Longwave tree - Energy Balance Check error!", eb-LW
+ !ENDIF
+
+ ! Radiation difference due to the last temperature change of the leaf
+ ! dBdT: the first 4 iterms is 0
+ !dX = matmul(Ainv, dBdT)
+ ! Finally solve the first 4 items, the leaf has been solved
+ !lwsun = lwsun + ( ewall*dX(1) ) / (1-ewall) * dtl!/ (4*fwsun*HL*fb/fg)
+ !lwsha = lwsha + ( ewall*dX(2) ) / (1-ewall) * dtl!/ (4*fwsha*HL*fb/fg)
+ !lgimp = lwimp + ( egimp*dX(3) ) / (1-egimp) * dtl!/ fgimp
+ !lgper = lgper + ( egper*dX(4) ) / (1-egper) * dtl!/ fgper
+
+ ! update after each temperature iteration
+ !lv = lv + ((dX(1)*Fwv + dX(2)*Fwv + dX(3)*Fgv + dX(4)*Fgv)*ev - dBdT(5))*dtl!/(fv/fg)
+ !dlvdt = (dX(1)*Fwv + dX(2)*Fwv + dX(3)*Fgv + dX(4)*Fgv)*ev - dBdT(5)
+
+ !SkyVF(1:2) = Fws_; SkyVF(3:4) = Fgs_; SkyVF(5) = Fvs
+ !lout = lout + sum( dX * SkyVF * dtl )
+
+ ! put it outside
+ ! absorption change due to temperature change, as restart variables.
+ ! now the leaf temperature does not change, the last iterm of dBdT is 0.
+ !dX = matmul(Ainv, dBdT*dT)
+
+ !lwsun = ( ewall*dX(1) - dBdT(1)*dT(1) ) / (1-ewall) !/ (4*fwsun*HL*fb/fg)
+ !lwsha = ( ewall*dX(2) - dBdT(2)*dT(2) ) / (1-ewall) !/ (4*fwsha*HL*fb/fg)
+ !lgimp = ( egimp*dX(3) - dBdT(3)*dT(3) ) / (1-egimp) !/ fgimp
+ !lgper = ( esnow*dX(4) - dBdT(4)*dT(4) ) / (1-esnow) !/ fgper
+ !lv = ((dX(1)*Fwv + dX(2)*Fwv + dX(3)*Fgv + dX(4)*Fgv + dX(5)*Fgv)*ev)!/(fv/fg)
+
+ !lout = X(1)*Fws_ + X(2)*Fws_ + X(3)*Fgs_ + X(4)*Fgs_ + X(5)*Fvs
+ !SkyVF(1:2) = Fws_; SkyVF(3:4) = Fgs_; SkyVF(5) = Fvs
+ !lout = lout + sum( dX * SkyVF )
+
+ END SUBROUTINE UrbanVegLongwave
+
+END MODULE MOD_Urban_Longwave
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_NetSolar.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_NetSolar.F90
new file mode 100644
index 0000000000..2992510f3a
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_NetSolar.F90
@@ -0,0 +1,184 @@
+#include
+
+MODULE MOD_Urban_NetSolar
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: netsolar_urban
+
+CONTAINS
+
+ SUBROUTINE netsolar_urban (ipatch,idate,dlon,deltim,&
+ forc_sols,forc_soll,forc_solsd,forc_solld,lai,sai,rho,tau,&
+ alb,ssun,ssha,sroof,swsun,swsha,sgimp,sgper,slake,&
+ sr,sabv,par,sabroof,sabwsun,sabwsha,sabgimp,sabgper,sablake,&
+ solvd,solvi,solnd,solni,srvd,srvi,srnd,srni,&
+ solvdln,solviln,solndln,solniln,srvdln,srviln,srndln,srniln)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Net solar absorbed by urban surface.
+!
+! Created by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_TimeManager, only: isgreenwich
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: ipatch ! patch index
+ integer, intent(in) :: idate(3) ! model time
+
+ real(r8), intent(in) :: dlon ! longitude in radians
+ real(r8), intent(in) :: deltim ! seconds in a time step [second]
+
+ real(r8), intent(in) :: &
+ forc_sols, &! atm vis direct beam solar rad onto srf [W/m2]
+ forc_soll, &! atm nir direct beam solar rad onto srf [W/m2]
+ forc_solsd, &! atm vis diffuse solar rad onto srf [W/m2]
+ forc_solld ! atm nir diffuse solar rad onto srf [W/m2]
+
+ real(r8), intent(in) :: &
+ lai, &! leaf area index
+ sai, &! stem area index
+ rho(2,2), &! leaf reflectance (iw=iband, il=life and dead)
+ tau(2,2) ! leaf transmittance (iw=iband, il=life and dead)
+
+ real(r8), dimension(1:2,1:2), intent(in) :: &
+ alb, &! averaged albedo [-]
+ ssun, &! sunlit canopy absorption for solar radiation
+ ssha, &! shaded canopy absorption for solar radiation
+ sroof, &! roof absorption for solar radiation
+ swsun, &! sunlit wall absorption for solar radiation
+ swsha, &! shaded wall absorption for solar radiation
+ sgimp, &! impervious ground absorption for solar radiation
+ sgper, &! pervious ground absorption for solar radiation
+ slake ! lake absorption for solar radiation
+
+
+ real(r8), intent(out) :: &
+ sr, &! total reflected solar radiation (W/m2)
+ par, &! PAR absorbed by sunlit vegetation [W/m2]
+ sabv, &! solar absorbed by sunlit vegetation [W/m2]
+ sabroof, &! roof absorbed solar radiation (W/m2)
+ sabwsun, &! sunlit wall absorbed solar radiation (W/m2)
+ sabwsha, &! shaded wall absorbed solar radiation (W/m2)
+ sabgimp, &! impervious ground absorbed solar radiation (W/m2)
+ sabgper, &! pervious ground absorbed solar radiation (W/m2)
+ sablake, &! solar absorbed by ground [W/m2]
+ solvd, &! incident direct beam vis solar radiation (W/m2)
+ solvi, &! incident diffuse beam vis solar radiation (W/m2)
+ solnd, &! incident direct beam nir solar radiation (W/m2)
+ solni, &! incident diffuse beam nir solar radiation (W/m2)
+ srvd, &! reflected direct beam vis solar radiation (W/m2)
+ srvi, &! reflected diffuse beam vis solar radiation (W/m2)
+ srnd, &! reflected direct beam nir solar radiation (W/m2)
+ srni, &! reflected diffuse beam nir solar radiation (W/m2)
+ solvdln, &! incident direct beam vis solar radiation at local noon(W/m2)
+ solviln, &! incident diffuse beam vis solar radiation at local noon(W/m2)
+ solndln, &! incident direct beam nir solar radiation at local noon(W/m2)
+ solniln, &! incident diffuse beam nir solar radiation at local noon(W/m2)
+ srvdln, &! reflected direct beam vis solar radiation at local noon(W/m2)
+ srviln, &! reflected diffuse beam vis solar radiation at local noon(W/m2)
+ srndln, &! reflected direct beam nir solar radiation at local noon(W/m2)
+ srniln ! reflected diffuse beam nir solar radiation at local noon(W/m2)
+
+!-------------------------- Local Variables ----------------------------
+ integer :: local_secs
+ real(r8) :: radpsec
+
+!-----------------------------------------------------------------------
+
+ sabroof = 0.
+ sabwsun = 0.
+ sabwsha = 0.
+ sabgimp = 0.
+ sabgper = 0.
+ sablake = 0.
+ sabv = 0.
+ par = 0.
+
+ IF (forc_sols+forc_soll+forc_solsd+forc_solld > 0.) THEN
+
+ sabroof = forc_sols *sroof(1,1) + forc_soll *sroof(2,1) &
+ + forc_solsd*sroof(1,2) + forc_solld*sroof(2,2)
+
+ sabwsun = forc_sols *swsun(1,1) + forc_soll *swsun(2,1) &
+ + forc_solsd*swsun(1,2) + forc_solld*swsun(2,2)
+
+ sabwsha = forc_sols *swsha(1,1) + forc_soll *swsha(2,1) &
+ + forc_solsd*swsha(1,2) + forc_solld*swsha(2,2)
+
+ sabgimp = forc_sols *sgimp(1,1) + forc_soll *sgimp(2,1) &
+ + forc_solsd*sgimp(1,2) + forc_solld*sgimp(2,2)
+
+ sabgper = forc_sols *sgper(1,1) + forc_soll *sgper(2,1) &
+ + forc_solsd*sgper(1,2) + forc_solld*sgper(2,2)
+
+ sabv = forc_sols *ssun (1,1) + forc_soll *ssun (2,1) &
+ + forc_solsd*ssun (1,2) + forc_solld*ssun (2,2)
+
+ par = forc_sols *ssun (1,1) + forc_solsd*ssun (1,2)
+
+ ! LAI PAR
+ !TODO: to distinguish lai and sai
+ !par = par * lai*(1.-rho(1,1)-tau(1,1)) / &
+ ! ( lai*(1.-rho(1,1)-tau(1,1)) + &
+ ! sai*(1.-rho(1,2)-tau(1,2)) )
+
+ ! for lake
+ sablake = forc_sols *slake(1,1) + forc_soll *slake(2,1) &
+ + forc_solsd*slake(1,2) + forc_solld*slake(2,2)
+
+ ENDIF
+
+ solvd = forc_sols
+ solvi = forc_solsd
+ solnd = forc_soll
+ solni = forc_solld
+ srvd = solvd*alb(1,1)
+ srvi = solvi*alb(1,2)
+ srnd = solnd*alb(2,1)
+ srni = solni*alb(2,2)
+ sr = srvd + srvi + srnd + srni
+
+ ! calculate the local secs
+ radpsec = pi/12./3600.
+ IF ( isgreenwich ) THEN
+ local_secs = idate(3) + nint((dlon/radpsec)/deltim)*deltim
+ local_secs = mod(local_secs,86400)
+ ELSE
+ local_secs = idate(3)
+ ENDIF
+
+ IF (local_secs == 86400/2) THEN
+ solvdln = forc_sols
+ solviln = forc_solsd
+ solndln = forc_soll
+ solniln = forc_solld
+ srvdln = solvdln*alb(1,1)
+ srviln = solviln*alb(1,2)
+ srndln = solndln*alb(2,1)
+ srniln = solniln*alb(2,2)
+ ELSE
+ solvdln = spval
+ solviln = spval
+ solndln = spval
+ solniln = spval
+ srvdln = spval
+ srviln = spval
+ srndln = spval
+ srniln = spval
+ ENDIF
+
+ END SUBROUTINE netsolar_urban
+
+END MODULE MOD_Urban_NetSolar
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_PerviousTemperature.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_PerviousTemperature.F90
new file mode 100644
index 0000000000..6943f651fe
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_PerviousTemperature.F90
@@ -0,0 +1,314 @@
+#include
+
+MODULE MOD_Urban_PerviousTemperature
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! The urban's pervious ground is equivalent to soil, and the heat
+! transfer process of the surface soil is calculated consistently. This
+! includes considering 10 layers of soil and up to 5 layers of snow,
+! with a layering scheme consistent with the soil (snow). The phase
+! change process is considered, and soil thermal parameters are
+! obtained from global data. The difference lies in the fact that the
+! shortwave and longwave radiation received at the surface, as well as
+! the turbulent exchange flux (sensible heat, latent heat), are solved
+! by the corresponding MODULE for the urban model.
+!
+! Created by Yongjiu Dai and Hua Yuan, 05/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanPerviousTem
+
+CONTAINS
+
+ SUBROUTINE UrbanPerviousTem (patchtype,lb,deltim, &
+ capr,cnfac,csol,k_solids,porsl,psi0,dkdry,dksatu,dksatf,&
+ vf_quartz,vf_gravels,vf_om,vf_sand,wf_gravels,wf_sand,&
+ BA_alpha, BA_beta,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r,alpha_vgm,n_vgm,L_vgm,&
+ sc_vgm,fc_vgm,&
+#endif
+ dz_gpersno,z_gpersno,zi_gpersno,&
+ t_gpersno,wice_gpersno,wliq_gpersno,scv_gper,snowdp_gper,&
+ lgper,clgper,sabgper,fsengper,fevpgper,cgper,htvp,&
+ imelt,sm,xmf,fact)
+
+!=======================================================================
+! Snow and pervious road temperatures
+! o The volumetric heat capacity is calculated as a linear combination
+! in terms of the volumetric fraction of the constituent phases.
+! o The thermal conductivity of road soil is computed from
+! the algorithm of Johansen (as reported by Farouki 1981), impervious
+! and perivious from LOOK-UP table and of snow is from the formulation
+! used in SNTHERM (Jordan 1991).
+! o Boundary conditions:
+! F = Rnet - Hg - LEg (top), F = 0 (base of the soil column).
+! o Soil / snow temperature is predicted from heat conduction
+! in 10 soil layers and up to 5 snow layers. The thermal
+! conductivities at the interfaces between two neighbor layers
+! (j,j+1) are derived from an assumption that the flux across the
+! interface is equal to that from the node j to the interface and the
+! flux from the interface to the node j+1. The equation is solved
+! using the Crank-Nicholson method and resulted in a tridiagonal
+! system equation.
+!
+! Phase change (see MOD_PhaseChange.F90)
+!
+! Original author: Yongjiu Dai, 09/15/1999; 08/30/2002; 05/2020
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical
+ USE MOD_SoilThermalParameters
+ USE MOD_Utils, only: tridia
+ USE MOD_PhaseChange, only: meltf
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: lb !lower bound of array
+ integer, intent(in) :: patchtype !land patch type
+ !(0=soil,1=urban or built-up,2=wetland,
+ !3=land ice, 4=deep lake, 5=shallow lake)
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: capr !tuning factor: turn 1st layer T to surface T
+ real(r8), intent(in) :: cnfac !Crank Nicholson factor between 0 and 1
+
+ real(r8), intent(in) :: csol (1:nl_soil) !heat capacity of soil solids [J/(m3 K)]
+ real(r8), intent(in) :: k_solids (1:nl_soil) !thermal cond. of minerals soil [W/m-K]
+ real(r8), intent(in) :: porsl (1:nl_soil) !soil porosity [-]
+ real(r8), intent(in) :: psi0 (1:nl_soil) !soil water suction, negative potential [mm]
+
+ real(r8), intent(in) :: dkdry (1:nl_soil) !thermal cond. of dry soil [W/m-K]
+ real(r8), intent(in) :: dksatu (1:nl_soil) !thermal cond. of sat soil [W/m-K]
+ real(r8), intent(in) :: dksatf (1:nl_soil) !thermal cond. of sat frozen soil [W/m-K]
+
+ real(r8), intent(in) :: vf_quartz (1:nl_soil) !volumetric frac of quartz in mineral soil
+ real(r8), intent(in) :: vf_gravels(1:nl_soil) !volumetric frac of gravels
+ real(r8), intent(in) :: vf_om (1:nl_soil) !volumetric frac of organic matter
+ real(r8), intent(in) :: vf_sand (1:nl_soil) !volumetric frac of sand
+ real(r8), intent(in) :: wf_gravels(1:nl_soil) !gravimetric frac of gravels
+ real(r8), intent(in) :: wf_sand (1:nl_soil) !gravimetric frac of sand
+
+ real(r8), intent(in) :: BA_alpha (1:nl_soil) !alpha in Balland and Arp(2005) thermal cond.
+ real(r8), intent(in) :: BA_beta (1:nl_soil) !beta in Balland and Arp(2005) thermal cond.
+
+#ifdef Campbell_SOIL_MODEL
+ real(r8), intent(in) :: bsw (1:nl_soil) !clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), intent(in) :: theta_r (1:nl_soil),& !soil parameter for vanGenuchten scheme
+ alpha_vgm (1:nl_soil),& !soil parameter for vanGenuchten scheme
+ n_vgm (1:nl_soil),& !soil parameter for vanGenuchten scheme
+ L_vgm (1:nl_soil),& !soil parameter for vanGenuchten scheme
+ sc_vgm (1:nl_soil),& !soil parameter for vanGenuchten scheme
+ fc_vgm (1:nl_soil) !soil parameter for vanGenuchten scheme
+#endif
+
+ real(r8), intent(in) :: dz_gpersno(lb :nl_soil) !layer thickness [m]
+ real(r8), intent(in) :: z_gpersno (lb :nl_soil) !node depth [m]
+ real(r8), intent(in) :: zi_gpersno(lb-1:nl_soil) !interface depth [m]
+
+ real(r8), intent(in) :: sabgper !solar radiation absorbed by ground [W/m2]
+ real(r8), intent(in) :: lgper !atmospheric longwave radiation [W/m2]
+ real(r8), intent(in) :: clgper !deriv. of longwave wrt to soil temp [w/m2/k]
+ real(r8), intent(in) :: fsengper !sensible heat flux from ground [W/m2]
+ real(r8), intent(in) :: fevpgper !evaporation heat flux from ground [mm/s]
+ real(r8), intent(in) :: cgper !deriv. of soil energy flux to T [w/m2/k]
+ real(r8), intent(in) :: htvp !latent heat of vapor (or sublimation) [j/kg]
+
+ real(r8), intent(inout) :: t_gpersno (lb:nl_soil) !soil temperature [K]
+ real(r8), intent(inout) :: wice_gpersno(lb:nl_soil) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_gpersno(lb:nl_soil) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv_gper !snow cover, water equivalent [mm, kg/m2]
+ real(r8), intent(inout) :: snowdp_gper !snow depth [m]
+
+ real(r8), intent(out) :: sm !rate of snowmelt [kg/(m2 s)]
+ real(r8), intent(out) :: xmf !total latent heat of phase change in soil
+ real(r8), intent(out) :: fact (lb:nl_soil) !used in computing tridiagonal matrix
+ integer, intent(out) :: imelt(lb:nl_soil) !flag for melting or freezing [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) cv(lb:nl_soil) !heat capacity [J/(m2 K)]
+ real(r8) tk(lb:nl_soil) !thermal conductivity [W/(m K)]
+
+ real(r8) hcap(1:nl_soil) !J/(m3 K)
+ real(r8) thk(lb:nl_soil) !W/(m K)
+ real(r8) rhosnow !partial density of water (ice + liquid)
+
+ real(r8) at(lb:nl_soil) !"a" vector for tridiagonal matrix
+ real(r8) bt(lb:nl_soil) !"b" vector for tridiagonal matrix
+ real(r8) ct(lb:nl_soil) !"c" vector for tridiagonal matrix
+ real(r8) rt(lb:nl_soil) !"r" vector for tridiagonal solution
+
+ real(r8) fn (lb:nl_soil) !heat diffusion through the layer interface [W/m2]
+ real(r8) fn1(lb:nl_soil) !heat diffusion through the layer interface [W/m2]
+ real(r8) dzm !used in computing tridiagonal matrix
+ real(r8) dzp !used in computing tridiagonal matrix
+
+ real(r8) t_gpersno_bef(lb:nl_soil) !soil/snow temperature before update
+ real(r8) hs !net energy flux into the surface (w/m2)
+ real(r8) dhsdt !d(hs)/dT
+ real(r8) brr(lb:nl_soil) !temporary set
+
+ real(r8) vf_water(1:nl_soil) !volumetric fraction liquid water within soil
+ real(r8) vf_ice(1:nl_soil) !volumetric fraction ice len within soil
+
+ integer i,j
+
+!=======================================================================
+! soil ground and wetland heat capacity
+ DO i = 1, nl_soil
+ vf_water(i) = wliq_gpersno(i)/(dz_gpersno(i)*denh2o)
+ vf_ice(i) = wice_gpersno(i)/(dz_gpersno(i)*denice)
+ CALL soil_hcap_cond(vf_gravels(i),vf_om(i),vf_sand(i),porsl(i),&
+ wf_gravels(i),wf_sand(i),k_solids(i),&
+ csol(i),dkdry(i),dksatu(i),dksatf(i),&
+ BA_alpha(i),BA_beta(i),&
+ t_gpersno(i),vf_water(i),vf_ice(i),hcap(i),thk(i))
+ cv(i) = hcap(i)*dz_gpersno(i)
+ ENDDO
+ IF(lb==1 .and. scv_gper>0.) cv(1) = cv(1) + cpice*scv_gper
+
+! Snow heat capacity
+ IF(lb <= 0)THEN
+ cv(:0) = cpliq*wliq_gpersno(:0) + cpice*wice_gpersno(:0)
+ ENDIF
+
+! Snow thermal conductivity
+ IF(lb <= 0)THEN
+ DO i = lb, 0
+ rhosnow = (wice_gpersno(i)+wliq_gpersno(i))/dz_gpersno(i)
+
+ ! presently option [1] is the default option
+ ! [1] Jordan (1991) pp. 18
+ thk(i) = tkair+(7.75e-5*rhosnow+1.105e-6*rhosnow*rhosnow)*(tkice-tkair)
+
+ ! [2] Sturm et al (1997)
+ ! thk(i) = 0.0138 + 1.01e-3*rhosnow + 3.233e-6*rhosnow**2
+ ! [3] Ostin and Andersson presented in Sturm et al., (1997)
+ ! thk(i) = -0.871e-2 + 0.439e-3*rhosnow + 1.05e-6*rhosnow**2
+ ! [4] Jansson(1901) presented in Sturm et al. (1997)
+ ! thk(i) = 0.0293 + 0.7953e-3*rhosnow + 1.512e-12*rhosnow**2
+ ! [5] Douville et al., (1995)
+ ! thk(i) = 2.2*(rhosnow/denice)**1.88
+ ! [6] van Dusen (1992) presented in Sturm et al. (1997)
+ ! thk(i) = 0.021 + 0.42e-3*rhosnow + 0.22e-6*rhosnow**2
+
+ ENDDO
+ ENDIF
+
+! Thermal conductivity at the layer interface
+ DO i = lb, nl_soil-1
+
+! the following consideration is try to avoid the snow conductivity
+! to be dominant in the thermal conductivity of the interface.
+! Because when the distance of bottom snow node to the interface
+! is larger than that of interface to top soil node,
+! the snow thermal conductivity will be dominant, and the result is that
+! lees heat transfer between snow and soil
+ IF((i==0) .and. (z_gpersno(i+1)-zi_gpersno(i)
+
+MODULE MOD_Urban_RoofFlux
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanRoofFlux
+
+CONTAINS
+
+
+ SUBROUTINE UrbanRoofFlux (hu, ht, hq, us, vs, tm, qm, rhoair, psrf, &
+ ur, thm, th, thv, zsno, fsno_roof, hroof, htvp_roof, &
+ lbr, wliq_roofsno, wice_roofsno, troof, qroof, dqroofdT, &
+ croofs, croofl, croof, fsenroof, fevproof, &
+ z0m, z0hg, zol, ustar, qstar, tstar, fm, fh, fq)
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This is the main subroutine to execute the calculation
+! of roof fluxes - not used now.
+!
+! Created by Hua Yuan, 11/2022
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Const_Physical, only: cpair,vonkar,grav
+ USE MOD_FrictionVelocity
+ IMPLICIT NONE
+
+!----------------------- Dummy argument --------------------------------
+ integer, intent(in) :: &
+ lbr ! lower bound of array
+
+ real(r8), intent(in) :: &
+ ! atmospherical variables and observational height
+ hu, &! observational height of wind [m]
+ ht, &! observational height of temperature [m]
+ hq, &! observational height of humidity [m]
+ us, &! wind component in eastward direction [m/s]
+ vs, &! wind component in northward direction [m/s]
+ tm, &! temperature at agcm reference height [kelvin] [not used]
+ qm, &! specific humidity at agcm reference height [kg/kg]
+ rhoair, &! density air [kg/m3]
+ psrf, &! atmosphere pressure at the surface [pa] [not used]
+
+ ur, &! wind speed at reference height [m/s]
+ thm, &! intermediate variable (tm+0.0098*ht)
+ th, &! potential temperature (kelvin)
+ thv, &! virtual potential temperature (kelvin)
+
+ zsno, &! roughness length for snow [m]
+ fsno_roof,&! fraction of impervious ground covered by snow
+ hroof, &! average building height [m]
+
+ wliq_roofsno,&! liquid water [kg/m2]
+ wice_roofsno,&! ice lens [kg/m2]
+
+ troof, &! ground impervious temperature [K]
+ qroof, &! ground impervious specific humidity [kg/kg]
+ dqroofdT, &! d(qroof)/dT
+ htvp_roof ! latent heat of vapor of water (or sublimation) [j/kg]
+
+ real(r8), intent(out) :: &
+ croofs, &! deriv of roof sensible heat flux wrt soil temp [w/m**2/k]
+ croofl, &! deriv of roof latent heat flux wrt soil temp [w/m**2/k]
+ croof ! deriv of roof total heat flux wrt soil temp [w/m**2/k]
+
+ real(r8), intent(out) :: &
+ fsenroof, &! sensible heat flux from roof [W/m2]
+ fevproof ! evaporation heat flux from roof [W/m2]
+
+ real(r8), intent(out) :: &
+ z0m, &! effective roughness [m]
+ z0hg, &! roughness length over ground, sensible heat [m]
+ zol, &! dimensionless height (z/L) used in Monin-Obukhov theory
+ ustar, &! friction velocity [m/s]
+ tstar, &! temperature scaling parameter
+ qstar, &! moisture scaling parameter
+ fm, &! integral of profile function for momentum
+ fh, &! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+!-------------------------- Local Variables ----------------------------
+ integer niters,&! maximum number of iterations for surface temperature
+ iter, &! iteration index
+ nmozsgn ! number of times moz changes sign
+
+ real(r8) :: &
+ beta, &! coefficient of convective velocity [-]
+ displax, &! zero-displacement height [m]
+ tg, &! ground surface temperature [K]
+ qg, &! ground specific humidity [kg/kg]
+ fg, &! ground fractional cover [-]
+ froof, &! weight of impervious ground
+ dth, &! diff of virtual temp. between ref. height and surface
+ dqh, &! diff of humidity between ref. height and surface
+ dthv, &! diff of vir. poten. temp. between ref. height and surface
+ obu, &! monin-obukhov length (m)
+ obuold, &! monin-obukhov length from previous iteration
+ ram, &! aerodynamical resistance [s/m]
+ rah, &! thermal resistance [s/m]
+ raw, &! moisture resistance [s/m]
+ raih, &! temporary variable [kg/m2/s]
+ raiw, &! temporary variable [kg/m2/s]
+ fh2m, &! relation for temperature at 2m
+ fq2m, &! relation for specific humidity at 2m
+ fm10m, &! integral of profile function for momentum at 10m
+ thvstar, &! virtual potential temperature scaling parameter
+ um, &! wind speed including the stability effect [m/s]
+ wc, &! convective velocity [m/s]
+ wc2, &! wc**2
+ zeta, &! dimensionless height used in Monin-Obukhov theory
+ zii, &! convective boundary height [m]
+ zldis, &! reference height "minus" zero displacement height [m]
+ z0mg, &! roughness length over ground, momentum [m]
+ z0qg ! roughness length over ground, latent heat [m]
+
+ real(r8) fwet_roof
+
+!-----------------------------------------------------------------------
+! initial roughness length
+ !TODO: change to original
+ !z0mg = (1.-fsno)*zlnd + fsno*zsno
+ IF (fsno_roof > 0) THEN
+ z0mg = zsno
+ ELSE
+ z0mg = 0.01
+ ENDIF
+ z0hg = z0mg
+ z0qg = z0mg
+
+! potential temperature at the reference height
+ beta = 1. !- (in computing W_*)
+ zii = 1000. !m (pbl height)
+ z0m = z0mg
+
+ ! wet fraction for roof and impervious ground
+ !-------------------------------------------
+ ! roof
+ IF (lbr < 1) THEN
+ fwet_roof = fsno_roof !for snow layer exist
+ ELSE
+ ! surface wet fraction. assuming max ponding = 1 kg/m2
+ fwet_roof = (max(0., wliq_roofsno+wice_roofsno))**(2/3.)
+ fwet_roof = min(1., fwet_roof)
+ ENDIF
+
+ ! dew case
+ IF (qm > qroof) THEN
+ fwet_roof = 1.
+ ENDIF
+
+!-----------------------------------------------------------------------
+! Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+!-----------------------------------------------------------------------
+! Initialization variables
+ nmozsgn = 0
+ obuold = 0.
+
+ dth = thm-troof
+ dqh = qm-qroof
+ dthv = dth*(1.+0.61*qm)+0.61*th*dqh
+ zldis = hu-hroof-0.
+
+ CALL moninobukini(ur,th,thm,thv,dth,dqh,dthv,zldis,z0mg,um,obu)
+
+! Evaluated stability-dependent variables using moz from prior iteration
+ niters=6
+
+ !----------------------------------------------------------------
+ ITERATION : DO iter = 1, niters !begin stability iteration
+ !----------------------------------------------------------------
+ displax = hroof
+ CALL moninobuk(hu,ht,hq,displax,z0mg,z0hg,z0qg,obu,um,&
+ ustar,fh2m,fq2m,fm10m,fm,fh,fq)
+
+ tstar = vonkar/fh*dth
+ qstar = vonkar/fq*dqh
+
+ z0hg = z0mg/exp(0.13 * (ustar*z0mg/1.5e-5)**0.45)
+ z0qg = z0hg
+
+ thvstar=tstar*(1.+0.61*qm)+0.61*th*qstar
+ zeta=zldis*vonkar*grav*thvstar/(ustar**2*thv)
+ IF (zeta >= 0.) THEN !stable
+ zeta = min(2.,max(zeta,1.e-6))
+ ELSE !unstable
+ zeta = max(-100.,min(zeta,-1.e-6))
+ ENDIF
+ obu = zldis/zeta
+
+ IF (zeta >= 0.) THEN
+ um = max(ur,0.1)
+ ELSE
+ wc = (-grav*ustar*thvstar*zii/thv)**(1./3.)
+ wc2 = beta*beta*(wc*wc)
+ um = sqrt(ur*ur+wc2)
+ ENDIF
+
+ IF (obuold*obu < 0.) nmozsgn = nmozsgn+1
+ IF (nmozsgn >= 4) EXIT
+
+ obuold = obu
+
+ !----------------------------------------------------------------
+ ENDDO ITERATION !end stability iteration
+ !----------------------------------------------------------------
+
+! Get derivative of fluxes with respect to ground temperature
+ ram = 1./(ustar*ustar/um)
+ rah = 1./(vonkar/fh*ustar)
+ raw = 1./(vonkar/fq*ustar)
+
+ raih = rhoair*cpair/rah
+ raiw = rhoair/raw
+ croofs = raih
+ croofl = raiw*dqroofdT*fwet_roof
+ croof = croofs + htvp_roof*croofl
+
+ zol = zeta
+
+! surface fluxes of momentum, sensible and latent
+! using ground temperatures from previous time step
+ !taux = -rhoair*us/ram
+ !tauy = -rhoair*vs/ram
+ fsenroof = -raih*dth
+ fevproof = -raiw*dqh*fwet_roof
+
+ END SUBROUTINE UrbanRoofFlux
+
+END MODULE MOD_Urban_RoofFlux
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_RoofTemperature.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_RoofTemperature.F90
new file mode 100644
index 0000000000..25d72a226a
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_RoofTemperature.F90
@@ -0,0 +1,252 @@
+#include
+
+MODULE MOD_Urban_RoofTemperature
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! The layer division scheme of the roof is the same as the wall (equal
+! depth), and the thickness is read from external data. The temperature
+! transfer is similar to the wall, but considering the influence of
+! snow and water accumulation on the thermal properties of the first
+! layer of the roof, as well as impervious surfaces. At the same time,
+! the heat exchange between the innermost layer of the roof and the
+! indoor roof surface air is considered, and the phase change process
+! is only considered for the first layer of the roof and the snow cover
+! layer.
+!
+! Created by Yongjiu Dai and Hua Yuan, 05/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanRoofTem
+
+CONTAINS
+
+
+ SUBROUTINE UrbanRoofTem (lb,deltim,capr,cnfac,&
+ cv_roof,tk_roof,dz_roofsno,z_roofsno,zi_roofsno,&
+ t_roofsno,wice_roofsno,wliq_roofsno,scv_roof,snowdp_roof,&
+ troof_inner,lroof,clroof,sabroof,fsenroof,fevproof,croof,htvp,&
+ imelt_roof,sm_roof,xmf_roof,fact,tkdz_roof)
+
+!=======================================================================
+! Snow and roof temperatures
+! o The volumetric heat capacity is calculated as a linear combination
+! in terms of the volumetric fraction of the constituent phases.
+! o The thermal conductivity of roof is given by LOOK-UP table, and of
+! snow is from the formulation used in SNTHERM (Jordan 1991).
+! o Boundary conditions:
+! F = Rnet - Hg - LEg (top),
+! For urban sunwall, shadewall, and roof columns, there is a non-zero
+! heat flux across the bottom "building inner surface" layer and the
+! equations are derived assuming a prescribed or adjusted internal
+! building temperature. T = T_roof_inner (at the roof inner surface).
+! o Roof / snow temperature is predicted from heat conduction
+! in N roof layers and up to 5 snow layers. The thermal
+! conductivities at the interfaces between two neighbor layers (j,
+! j+1) are derived from an assumption that the flux across the
+! interface is equal to that from the node j to the interface and the
+! flux from the interface to the node j+1. The equation is solved
+! using the Crank-Nicholson method and resulted in a tridiagonal
+! system equation.
+!
+! Phase change (see MOD_PhaseChange.F90)
+!
+! Original author: Yongjiu Dai, 05/2020
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical
+ USE MOD_Utils, only: tridia
+ USE MOD_PhaseChange, only: meltf_urban
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer , intent(in) :: lb !lower bound of array
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: capr !tuning factor: turn 1st layer T to surface T
+ real(r8), intent(in) :: cnfac !Crank Nicholson factor between 0 and 1
+
+ real(r8), intent(in) :: cv_roof(1:nl_roof) !heat capacity of urban roof [J/m3/K]
+ real(r8), intent(in) :: tk_roof(1:nl_roof) !thermal conductivity of urban roof [W/m/K]
+
+ real(r8), intent(in) :: dz_roofsno(lb:nl_roof) !layer thickness [m]
+ real(r8), intent(in) :: z_roofsno (lb:nl_roof) !node depth [m]
+ real(r8), intent(in) :: zi_roofsno(lb-1:nl_roof) !interface depth [m]
+
+ real(r8), intent(in) :: troof_inner !temperature at the roof inner surface [K]
+ real(r8), intent(in) :: lroof !atmospheric longwave radiation [W/m2]
+ real(r8), intent(in) :: clroof !atmospheric longwave radiation [W/m2]
+ real(r8), intent(in) :: sabroof !solar radiation absorbed by roof [W/m2]
+ real(r8), intent(in) :: fsenroof !sensible heat flux from roof [W/m2]
+ real(r8), intent(in) :: fevproof !evaporation heat flux from roof [mm/s]
+ real(r8), intent(in) :: croof !deriv. of roof energy flux to T [w/m2/k]
+ real(r8), intent(in) :: htvp !latent heat of vapor (or sublimation) [j/kg]
+
+ real(r8), intent(inout) :: t_roofsno (lb:nl_roof) !roof layers' temperature [K]
+ real(r8), intent(inout) :: wice_roofsno(lb:nl_roof) !ice lens [kg/m2]
+ real(r8), intent(inout) :: wliq_roofsno(lb:nl_roof) !liquid water [kg/m2]
+ real(r8), intent(inout) :: scv_roof !snow cover, water equivalent [mm, kg/m2]
+ real(r8), intent(inout) :: snowdp_roof !snow depth [m]
+
+ real(r8), intent(out) :: sm_roof !rate of snowmelt [kg/(m2 s)]
+ real(r8), intent(out) :: xmf_roof !total latent heat of phase change of roof
+ real(r8), intent(out) :: fact(lb:nl_roof) !used in computing tridiagonal matrix
+ real(r8), intent(out) :: tkdz_roof !heat diffusion with inner room space
+ integer , intent(out) :: imelt_roof(lb:nl_roof) !flag for melting or freezing [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) cv (lb:nl_roof) !heat capacity [J/(m2 K)]
+ real(r8) thk(lb:nl_roof) !thermal conductivity of layer
+ real(r8) tk (lb:nl_roof) !thermal conductivity [W/(m K)]
+
+ real(r8) at (lb:nl_roof) !"a" vector for tridiagonal matrix
+ real(r8) bt (lb:nl_roof) !"b" vector for tridiagonal matrix
+ real(r8) ct (lb:nl_roof) !"c" vector for tridiagonal matrix
+ real(r8) rt (lb:nl_roof) !"r" vector for tridiagonal solution
+
+ real(r8) fn (lb:nl_roof) !heat diffusion through the layer interface [W/m2]
+ real(r8) fn1(lb:nl_roof) !heat diffusion through the layer interface [W/m2]
+ real(r8) dzm !used in computing tridiagonal matrix
+ real(r8) dzp !used in computing tridiagonal matrix
+
+ real(r8) t_roofsno_bef(lb:nl_roof) !roof/snow temperature before update
+ real(r8) hs !net energy flux into the surface (w/m2)
+ real(r8) dhsdt !d(hs)/dT
+ real(r8) brr(lb:nl_roof) !temporary set
+ real(r8) bw !snow density [kg/m3]
+
+ integer i,j
+
+!-----------------------------------------------------------------------
+
+ wice_roofsno(2:) = 0.0 !ice lens [kg/m2]
+ wliq_roofsno(2:) = 0.0 !liquid water [kg/m2]
+
+! heat capacity
+ IF (lb <= 0) THEN
+ DO j = lb, 0
+ cv(j) = max(1.0e-6_r8,(cpliq*wliq_roofsno(j) + cpice*wice_roofsno(j)))
+ ENDDO
+ ENDIF
+
+ cv(1:) = cv_roof(1:)*dz_roofsno(1:)
+
+ ! snow exist when there is no snow layer
+ IF (lb == 1 .and. scv_roof > 0.0) THEN
+ cv(1) = cv(1) + cpice*scv_roof
+ ENDIF
+
+ ! ponding water or ice exist
+ cv(1) = cv(1) + cpliq*wliq_roofsno(1) + cpice*wice_roofsno(1)
+
+! thermal conductivity
+ ! Thermal conductivity of snow, which from Yen (1980)
+ IF (lb <= 0) THEN
+ DO j = lb, 0
+ bw = (wice_roofsno(j)+wliq_roofsno(j))/(dz_roofsno(j))
+ thk(j) = tkair + (7.75e-5_r8 *bw + 1.105e-6_r8*bw*bw)*(tkice-tkair) ! Yen, 1980
+ !thk(j) = 0.024 - 1.23e-4_r8*bw + 2.5e-6_r8*bw*bw ! Calonne et al., 2011
+ ENDDO
+ ENDIF
+
+! thermal conductivity at the layer interface
+ thk(1:) = tk_roof(1:)
+ IF (lb <= 0) THEN
+ DO j = lb, 0
+ tk(j) = thk(j)*thk(j+1)*(z_roofsno(j+1)-z_roofsno(j)) &
+ /(thk(j)*(z_roofsno(j+1)-zi_roofsno(j))+thk(j+1)*(zi_roofsno(j)-z_roofsno(j)))
+ ENDDO
+ ENDIF
+
+ DO j = 1, nl_roof-1
+ tk(j) = thk(j)*thk(j+1)*(z_roofsno(j+1)-z_roofsno(j)) &
+ /(thk(j)*(z_roofsno(j+1)-zi_roofsno(j))+thk(j+1)*(zi_roofsno(j)-z_roofsno(j)))
+ ENDDO
+ tk(nl_roof) = thk(nl_roof)
+
+! net ground heat flux into the roof surface and its temperature derivative
+ hs = sabroof + lroof - (fsenroof+fevproof*htvp)
+ dhsdT = - croof + clroof
+
+ t_roofsno_bef(lb:) = t_roofsno(lb:)
+
+ j = lb
+ fact(j) = deltim / cv(j) * dz_roofsno(j) &
+ / (0.5*(z_roofsno(j)-zi_roofsno(j-1)+capr*(z_roofsno(j+1)-zi_roofsno(j-1))))
+
+ DO j = lb + 1, nl_roof
+ fact(j) = deltim/cv(j)
+ ENDDO
+
+ DO j = lb, nl_roof - 1
+ fn(j) = tk(j)*(t_roofsno(j+1)-t_roofsno(j))/(z_roofsno(j+1)-z_roofsno(j))
+ ENDDO
+
+ j = nl_roof
+ fn(j) = tk(j)*(troof_inner - cnfac*t_roofsno(j))/(zi_roofsno(j)-z_roofsno(j))
+ tkdz_roof = tk(j)/(zi_roofsno(j)-z_roofsno(j))
+
+! set up vector r and vectors a, b, c that define tridiagonal matrix
+ j = lb
+ dzp = z_roofsno(j+1)-z_roofsno(j)
+ at(j) = 0.
+ bt(j) = 1+(1.-cnfac)*fact(j)*tk(j)/dzp-fact(j)*dhsdT
+ ct(j) = -(1.-cnfac)*fact(j)*tk(j)/dzp
+ rt(j) = t_roofsno(j) + fact(j)*( hs - dhsdT*t_roofsno(j) + cnfac*fn(j) )
+
+ DO j = lb + 1, nl_roof - 1
+ dzm = (z_roofsno(j)-z_roofsno(j-1))
+ dzp = (z_roofsno(j+1)-z_roofsno(j))
+ at(j) = - (1.-cnfac)*fact(j)* tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm)
+ ct(j) = - (1.-cnfac)*fact(j)* tk(j)/dzp
+ rt(j) = t_roofsno(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ENDDO
+
+ j = nl_roof
+ dzm = (z_roofsno(j)-z_roofsno(j-1))
+ dzp = (zi_roofsno(j)-z_roofsno(j))
+ at(j) = - (1.-cnfac)*fact(j)*tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j-1)/dzm+tk(j)/dzp)
+ ct(j) = 0.
+ rt(j) = t_roofsno(j) + fact(j)*(fn(j) - cnfac*fn(j-1))
+
+! solve for t_roofsno
+ i = size(at)
+ CALL tridia (i ,at ,bt ,ct ,rt ,t_roofsno)
+
+!=======================================================================
+! melting or freezing
+!=======================================================================
+
+ DO j = lb, nl_roof - 1
+ fn1(j) = tk(j)*(t_roofsno(j+1)-t_roofsno(j))/(z_roofsno(j+1)-z_roofsno(j))
+ ENDDO
+
+ j = nl_roof
+ fn1(j) = tk(j)*(troof_inner - cnfac*t_roofsno(j))/(zi_roofsno(j)-z_roofsno(j))
+
+ j = lb
+ brr(j) = cnfac*fn(j) + (1.-cnfac)*fn1(j)
+
+ DO j = lb + 1, nl_roof
+ brr(j) = cnfac*(fn(j)-fn(j-1)) + (1.-cnfac)*(fn1(j)-fn1(j-1))
+ ENDDO
+
+ CALL meltf_urban (lb,1,deltim, &
+ fact(lb:1),brr(lb:1),hs,dhsdT, &
+ t_roofsno_bef(lb:1),t_roofsno(lb:1), &
+ wliq_roofsno(lb:1),wice_roofsno(lb:1),imelt_roof(lb:1), &
+ scv_roof,snowdp_roof,sm_roof,xmf_roof)
+
+ END SUBROUTINE UrbanRoofTem
+
+END MODULE MOD_Urban_RoofTemperature
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Shortwave.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Shortwave.F90
new file mode 100644
index 0000000000..1a8628a5bf
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Shortwave.F90
@@ -0,0 +1,777 @@
+#include
+
+MODULE MOD_Urban_Shortwave
+
+ USE MOD_Precision
+ USE MOD_LandUrban
+ USE MOD_Vars_Global
+ USE MOD_3DCanopyRadiation, only: tee, phi
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+ SAVE
+ PRIVATE
+
+ PUBLIC :: UrbanOnlyShortwave !Radiation transfer for shortwave radiation without trees
+ PUBLIC :: UrbanVegShortwave !Radiation transfer for shortwave radiation with trees
+
+ PUBLIC :: MatrixInverse !Inverse of radiation transfer matrix for multiple reflections
+ PUBLIC :: ShadowWall_dir !Shadow of wall for direct radiation
+ PUBLIC :: ShadowWall_dif !Shadow of wall for diffuse radiation
+ PUBLIC :: ShadowTree !Shadow of trees
+
+CONTAINS
+
+
+ SUBROUTINE UrbanOnlyShortwave ( theta, HL, fb, fgper, H, &
+ aroof, awall, agimp, agper, fwsun, sroof, swsun, swsha, sgimp, sgper, albu)
+
+!-----------------------------------------------------------------------
+! Sun
+! \\\
+! \\\
+! ______
+! |++++++| roof
+! |++++++| ______
+! |++++++| |++++++|
+! ______+++++| |++++++|
+! |++++++|++++| |++++++|
+! sunlit |[]++[]|++++| |++++++| shaded
+! wall |++++++| |++++++| wall
+! |[]++[]| |++++++|
+! |++++++| impervious/pervious ground
+! __________|++++++|____________________________________
+!
+!
+! !DESCRIPTION:
+!
+! Calculate the ground shadow area, the area of the sunny and shady
+! walls taking into account mutual shading between buildings;
+! calculate the visibility factor F between the sky, walls, and
+! ground; calculate the initial radiation reaching each component
+! surface, considering multiple scattering processes, and establish
+! the radiation transfer balance equation for both incident direct
+! and diffuse radiation cases for solving.
+!
+! Created by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ theta, &! Sun zenith angle [radian]
+ HL, &! Ratio of building height to their side length [-]
+ fb, &! Fraction of building area [-]
+ fgper, &! Fraction of impervious ground [-]
+ H ! Building average height [m]
+
+ real(r8), intent(in) :: &
+ aroof, &! albedo of roof [-]
+ awall, &! albedo of walls [-]
+ agimp, &! albedo of impervious road [-]
+ agper ! albedo of pervious road [-]
+
+ real(r8), intent(out) :: &
+ fwsun, &! Fraction of sunlit wall [-]
+ sroof(2), &! Urban building roof absorption [-]
+ swsun(2), &! Urban sunlit wall absorption [-]
+ swsha(2), &! Urban shaded wall absorption [-]
+ sgimp(2), &! Urban impervious ground absorption [-]
+ sgper(2), &! Urban pervious ground absorption [-]
+ albu(2) ! Urban overall albedo [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) :: &
+ W, &! Urban ground average width [m]
+ L, &! Urban building average length [m]
+ HW, &! Ratio of H to W, H/W [-]
+ fg, &! Fraction of ground [-]
+ fgimp, &! Weight of pervious ground [-]
+
+ Fsw, &! View factor from sky to wall [-]
+ Fsg, &! View factor from sky to ground [-]
+ Fgw, &! View factor from ground to wall [-]
+ Fgs, &! View factor from ground to sky [-]
+ Fww, &! View factor from wall to wall [-]
+ Fwg, &! View factor from wall to ground [-]
+ Fws, &! View factor from wall to sky [-]
+
+ Sw, &! Shadow of wall [-]
+ fwsha, &! Fraction of shaded wall [-]
+ Ewsun, &! Incident radiation on sunlit wall [-]
+ Ewsha, &! Incident radiation on shaded wall [-]
+ Eg, &! Incident radiation on ground [-]
+ Egimp, &! Incident radiation on impervious ground [-]
+ Egper, &! Incident radiation on pervious ground [-]
+
+ A(4,4), &! Radiation transfer matrix
+ Ainv(4,4), &! Inverse of Radiation transfer matrix
+ B(4), &! Vectors of incident radiation on each surface
+ X(4) ! Radiation emit from each surface in balance condition
+
+ ! Temporal
+ real(r8) :: fac1, fac2, eb
+
+!-----------------------------------------------------------------------
+
+ ! Calculate urban structure parameters
+ !-------------------------------------------------
+ !W = H/HW
+ !L = W*sqrt(fb)/(1-sqrt(fb))
+ !HL = H/L !NOTE: Same as: HL = HW*(1-sqrt(fb))/sqrt(fb)
+ fg = 1. - fb
+
+ fgimp = 1. - fgper
+
+ ! Calculate view factors
+ !-------------------------------------------------
+
+ ! View factor from sky to wall(sunlit+shaded) and ground
+ Fsw = ShadowWall_dif(fb/fg, HL)
+ Fsg = 1 - Fsw
+
+ ! View factor from ground to walls and sky
+ Fgw = Fsw
+ Fgs = Fsg
+
+ ! View factor from wall to wall, sky and ground
+ ! Fws*4*H*L/L/L = Fws*4H/L*fb = Fsw*fg
+ ! Fws*4HL*fb = Fsw*fg
+ ! Fws = Fsw*fg/(4HL*fb)
+ ! Adjusted as below:
+ Fws = Fsw*fg/fb/(2*HL)*0.75
+ Fwg = Fsw*fg/fb/(2*HL)*0.25
+ Fww = 1 - Fws - Fwg
+
+ ! Calculate sunlit wall fraction
+ !-------------------------------------------------
+
+ ! Building wall shadow on the ground
+ Sw = ShadowWall_dir(fb/fg, HL, theta)
+
+ ! Sunlit/shaded wall fraction
+ fwsun = 0.5 * (Sw*fg + fb) / (4/PI*fb*HL*tan(theta) + fb)
+ fwsha = 1. - fwsun
+
+ ! Calculate radiation transfer matrix
+ ! AX = B
+ ! o A: radiation transfer matrix
+ ! o B: incident radiation on each surface
+ ! o X: radiation emit from each surface
+ !-------------------------------------------------
+ A(1,:) = (/1-Fww*fwsun*awall, -Fww*fwsun*awall, -Fgw*fwsun*awall, -Fgw*fwsun*awall/)
+ A(2,:) = (/ -Fww*fwsha*awall, 1-Fww*fwsha*awall, -Fgw*fwsha*awall, -Fgw*fwsha*awall/)
+ A(3,:) = (/ -Fwg*fgimp*agimp, -Fwg*fgimp*agimp, 1._r8, 0._r8/)
+ A(4,:) = (/ -Fwg*fgper*agper, -Fwg*fgper*agper, 0._r8, 1._r8/)
+
+ ! Inverse of matrix A
+ Ainv = MatrixInverse(A)
+
+ ! Radiation transfer for incident direct case
+ !-------------------------------------------------
+
+ ! Incident radiation on sunlit/shaded wall and
+ ! impervious/pervious ground
+ Ewsun = Sw
+ Ewsha = 0.
+ Eg = 1.-Ewsun
+ Egimp = Eg*fgimp
+ Egper = Eg*fgper
+
+ ! Vector of first scattering radiation on each surface
+ B(:) = (/Ewsun*awall, Ewsha*awall, Egimp*agimp, Egper*agper/)
+
+ ! Matrix computing to resolve multiple reflections
+ X = matmul(Ainv, B)
+
+ !-------------------------------------------------
+ ! SAVE results for output
+ !-------------------------------------------------
+
+ ! Radiation absorption by each surface
+ !NOTE: for 3D, absorption per unit area: 4*HL*fb/fg
+ ! for canyon: absorption per unit area: 2*HW
+ swsun(1) = X(1)/awall*(1-awall)!/(4*fwsun*HL*fb/fg)
+ swsha(1) = X(2)/awall*(1-awall)!/(4*fwsha*HL*fb/fg)
+ sgimp(1) = X(3)/agimp*(1-agimp)!/fgimp
+ sgper(1) = X(4)/agper*(1-agper)!/fgper
+
+ ! albedo of urban canopy
+ albu(1) = X(1)*Fws + X(2)*Fws + X(3)*Fgs + X(4)*Fgs
+
+ ! Energy balance check
+ eb = swsun(1) + swsha(1) + sgimp(1) + sgper(1) + albu(1)
+ IF (abs(eb-1) > 1e-6) THEN
+ print *, "Direct - Energy Balance Check error!", eb-1
+ ENDIF
+
+ ! Radiation transfer for incident diffuse case
+ !-------------------------------------------------
+
+ ! Incident radiation on sunlit/shaded wall and
+ ! impervious/pervious ground
+ Ewsun = Fsw*fwsun
+ Ewsha = Fsw*fwsha
+ Eg = Fsg
+ Egimp = Eg*fgimp
+ Egper = Eg*fgper
+
+ ! Vector of first scattering radiation on each surface
+ B(:) = (/Ewsun*awall, Ewsha*awall, Egimp*agimp, Egper*agper/)
+
+ ! Equation solve
+ X = matmul(Ainv, B)
+
+ ! Radiation absorption by each surface
+ !NOTE: for 3D, absorption per unit area: 4*HL*fb/fg
+ ! for canyon: absorption per unit area: 2*HW
+ swsun(2) = X(1)/awall*(1-awall)!/(4*fwsun*HL*fb/fg)
+ swsha(2) = X(2)/awall*(1-awall)!/(4*fwsha*HL*fb/fg)
+ sgimp(2) = X(3)/agimp*(1-agimp)!/fgimp
+ sgper(2) = X(4)/agper*(1-agper)!/fgper
+
+ !albedo of urban canopy
+ albu(2) = X(1)*Fws + X(2)*Fws + X(3)*Fgs + X(4)*Fgs
+
+ ! energy balance check
+ eb = swsun(2) + swsha(2) + sgimp(2) + sgper(2) + albu(2)
+ IF (abs(eb-1) > 1e-6) THEN
+ print *, "Diffuse - Energy Balance Check error!", eb-1
+ ENDIF
+
+ ! convert to per unit area absorption
+ IF (fb > 0.) THEN
+ swsun = swsun/(4*fwsun*HL*fb)*fg
+ swsha = swsha/(4*fwsha*HL*fb)*fg
+ ENDIF
+ IF (fgimp > 0.) sgimp = sgimp/fgimp
+ IF (fgper > 0.) sgper = sgper/fgper
+
+ ! roof absorption
+ sroof = 1. - aroof
+
+ ! albedo account for both roof and urban's wall and ground
+ albu = aroof*fb + albu*fg
+
+ END SUBROUTINE UrbanOnlyShortwave
+
+
+ SUBROUTINE UrbanVegShortwave ( theta, HL, fb, fgper, H, &
+ aroof, awall, agimp, agper, lai, sai, fv, hv, rho, tau, &
+ fwsun, sroof, swsun, swsha, sgimp, sgper, sveg, albu )
+
+!-----------------------------------------------------------------------
+! Sun
+! \\\
+! \\\
+! ______
+! |++++++| roof
+! |++++++| ______
+! |++++++| ___ |++++++|
+! ______+++++| ||||| |++++++|
+! |++++++|++++| ||||||| |++++++|
+! sunlit |[]++[]|++++| ||||| |++++++| shaded
+! wall |++++++| | tree |++++++| wall
+! |[]++[]| | |++++++|
+! |++++++| impervious/pervious ground
+! __________|++++++|____________________________________
+!
+!
+! !DESCRIPTION:
+!
+! The process of shortwave radiation transfer in a city considering
+! vegetation (trees only) is based on the radiation transfer without
+! vegetation (UrbanOnlyShortwave), taking into account the visibility
+! factors F between the various components including the vegetation, in
+! order to calculate the radiation transfer matrix during radiation
+! balance. A similar method is used to solve the radiation absorption
+! of walls, ground, and vegetation. The additional part compared to
+! urban radiation transfer without vegetation (UrbanOnlyShortwave) is
+! the consideration of the visibility factors and shadow area
+! calculation including the vegetation.
+!
+! Created by Hua Yuan, 09/2021
+!
+! !REVISIONS:
+!
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: &
+ theta, &! Sun zenith angle [radian]
+ HL, &! Ratio of building height to their side length [-]
+ fb, &! Fraction of building area [-]
+ fgper, &! Fraction of impervious ground [-]
+ H ! Building average height [m]
+
+ real(r8), intent(in) :: &
+ aroof, &! albedo of roof [-]
+ awall, &! albedo of walls [-]
+ agimp, &! albedo of impervious road [-]
+ agper ! albedo of pervious road [-]
+
+ real(r8), intent(in) :: &
+ lai, &! leaf area index
+ sai, &! stem area index
+ fv, &! Fraction of tree cover [-]
+ hv, &! Central height of vegetation crown
+ rho, &! effective rho (lai + sai)
+ tau ! effective tau (lai + sai)
+
+ real(r8), intent(out) :: &
+ fwsun, &! Fraction of sunlit wall [-]
+ sroof(2), &! Urban building roof absorption [-]
+ swsun(2), &! Urban sunlit wall absorption [-]
+ swsha(2), &! Urban shaded wall absorption [-]
+ sgimp(2), &! Urban impervious ground absorption [-]
+ sgper(2), &! Urban pervious ground absorption [-]
+ sveg(2), &! Urban building tree absorption [-]
+ albu(2) ! Urban overall albedo [-]
+
+!-------------------------- Local Variables ----------------------------
+ real(r16),parameter :: DD1=1.0_r16 !quad accuracy real number
+
+ real(r8) :: &
+ W, &! Urban ground average width
+ L, &! Urban building average length
+ HW, &! Ratio of H to W, H/W [-]
+ fg, &! Fraction of ground [-]
+ fgimp, &! Weight of pervious ground [-]
+
+ Fsw, &! View factor from sky to wall [-]
+ Fsg, &! View factor from sky to ground [-]
+ Fgw, &! View factor from ground to wall [-]
+ Fgs, &! View factor from ground to sky [-]
+ Fww, &! View factor from wall to wall [-]
+ Fwg, &! View factor from wall to ground [-]
+ Fws, &! View factor from wall to sky [-]
+
+ Fvg, &! View factor from tree to ground [-]
+ Fvs, &! View factor from tree to sky [-]
+ Fvw, &! View factor from tree to walls (sunlit+shaded) [-]
+ Fwv, &! View factor from wall to tree [-]
+ Fgv, &! View factor from ground to tree [-]
+ Fsv, &! View factor from sky to tree [-]
+
+ Fgvs, &! View factor from ground->|tree|-> to sky [-]
+ Fgvw, &! View factor from ground->|tree|-> to walls [-]
+ Fsvg, &! View factor from sky->|tree|-> to ground [-]
+ Fsvw, &! View factor from sky->|tree|-> to walls [-]
+ Fwvw, &! View factor from walls->|tree|-> to walls [-]
+ Fwvs, &! View factor from walls->|tree|-> to sky [-]
+ Fwvg, &! View factor from walls->|tree|-> to ground [-]
+
+ Fsw_, &! Fsw - Fsvw + Fsvw*Td [-]
+ Fsg_, &! Fsg - Fsvg + Fsvg*Td [-]
+ Fgw_, &! Fgw - Fgvw + Fgvw*Td [-]
+ Fgs_, &! Fgs - Fgvs + Fgvs*Td [-]
+ Fwg_, &! Fwg - Fwvg + Fwvg*Td [-]
+ Fww_, &! Fww - Fwvw + Fwvw*Td [-]
+ Fws_, &! Fws - Fwvs + Fwvs*Td [-]
+
+ Sw, &! Shadow of wall [-]
+ Sw_, &! Shadow of wall [-]
+ Sv, &! Shadow of trees [-]
+ Svw, &! Overlapped shadow between wall and trees [-]
+ fv_, &! Fraction of trees [-]
+ Td, &! Transmission of tree [-]
+ av, &! albedo of tree [-]
+ fwsha, &! Fraction of shaded wall [-]
+ Ewsun, &! Incident radiation on sunlit wall [-]
+ Ewsha, &! Incident radiation on shaded wall [-]
+ Eg, &! Incident radiation on ground [-]
+ Egimp, &! Incident radiation on impervious ground [-]
+ Egper, &! Incident radiation on pervious ground [-]
+ Ev ! Incident radiation on trees [-]
+
+ ! Radiation transfer matrix and vectors
+ !-------------------------------------------------
+ real(r8) :: A(5,5) !Radiation transfer matrix
+ real(r8) :: Ainv(5,5) !Inverse of Radiation transfer matrix
+ real(r8) :: B(5) !Vectors of incident radiation on each surface
+ real(r8) :: X(5) !Radiation emit from each surface in balance condition
+
+ ! Temporal
+ real(r8) :: fac1, fac2, eb, sumw, ws, wg, ww
+
+ real(r8) :: phi_tot !albedo of a single tree
+ real(r8) :: phi_dif !Temporal
+ real(r8) :: pa2 !Temporal
+ real(r8) :: lsai !lai+sai
+!-----------------------------------------------------------------------
+
+ ! Calculate urban structure parameters
+ !-------------------------------------------------
+ !W = H/HW
+ !L = W*sqrt(fb)/(1-sqrt(fb))
+ !HL = H/L !NOTE: Same as: HL = HW*(1-sqrt(fb))/sqrt(fb)
+ L = H/HL
+ fg = 1. - fb
+
+ fgimp = 1. - fgper
+
+ ! Calculate transmission and albedo of tree
+ !-------------------------------------------------
+ lsai = (lai+sai)*fv/cos(PI/3)/ShadowTree(fv, PI/3)
+ Td = tee(DD1*3/8.*lsai)
+ CALL phi(.true., 3/8.*lsai, tau+rho, tau, rho, phi_tot, phi_dif, pa2)
+ av = phi_tot
+
+ ! Calculate view factors
+ !-------------------------------------------------
+
+ ! View factor from sky to wall(sunlit+shaded) and ground
+ Fsw = ShadowWall_dif(fb/fg, HL)
+ Fsg = 1 - Fsw
+
+ ! View factor from ground to walls and sky
+ Fgw = Fsw
+ Fgs = Fsg
+
+ ! View factor from wall to wall, sky and ground
+ ! Fws*4*H*L*L/L = Fws*4H/L*fb = Fsw*fg
+ ! Fws*4HL*fb = Fsw*fg
+ ! Fws = Fsw*fg/(4HL*fb)
+ ! adjusted as below:
+ Fws = Fsw*fg/fb/(2*HL)*0.75
+ Fwg = Fsw*fg/fb/(2*HL)*0.25
+ Fww = 1 - Fws - Fwg
+
+ ! View factor from tree to walls, ground and sky
+ !-------------------------------------------------
+
+ Sw = ShadowWall_dif(fb/fg, HL)
+ Sw_ = ShadowWall_dif(fb/fg, (H-hv)/L)
+
+ !NOTE: fg*(fv/fg - fv/fg * Sw_)
+ fv_ = fv - fv*Sw_
+ Sv = ShadowTree(fv_, PI/3)
+
+ ! Overlapped shadow between tree and building
+ ! (to ground only)
+ Svw = Sv * (Sw-Sw_)
+
+ ! convert Sv to ground ratio
+ Sv = min(1., Sv/fg)
+
+ ! robust check
+ IF (Sv+Sw-Svw > 1) THEN
+ Svw = Sv+Sw-1
+ ENDIF
+
+ ! Calibrated building ground shadow
+ Fsv = Sv
+ Fsvw = Svw
+ Fsvg = Fsv - Fsvw
+
+ ! View factor from veg to sky and walls above canopy
+ Fvs = 0.5*(1-Sw_)
+ Fvw = 0.5*Sw_
+
+ Sw_ = ShadowWall_dif(fb/fg, hv/L)
+ fv_ = fv - fv*Sw_
+ Sv = ShadowTree(fv_, PI/3)
+
+ ! Overlapped shadow between tree and building
+ ! (to ground only)
+ Svw = Sv * (Sw-Sw_)
+
+ ! convert Sv to ground ratio
+ Sv = min(1., Sv/fg)
+
+ ! robust check
+ IF (Sv+Sw-Svw > 1) THEN
+ Svw = Sv+Sw-1
+ ENDIF
+
+ ! Calibrated building ground shadow
+ Fgv = Sv
+ Fgvw = Svw
+ Fgvs = Fgv - Fgvw
+
+ ! View factor from veg to sky and walls below+above canopy
+ Fvg = 0.5*(1-Sw_)
+ Fvw = 0.5*Sw_ + Fvw
+
+ Fvw = 1 - Fvs - Fvg
+
+ !Fvs = Fsv*fg/min(4*fv,2*fg)
+ !Fvg = Fgv*fg/min(4*fv,2*fg)
+ !Fvw = 1 - Fvs - Fvg
+
+ !ws = (phi_tot - phi_dif)/2
+ !wg = (phi_tot + phi_dif)/2
+ !ww = (phi_tot + phi_dif)/2
+ !sumw = Fvs*ws + Fvg*wg + Fvw*ww
+ !Fvs = Fvs*ws/sumw
+ !Fvg = Fvg*wg/sumw
+ !Fvw = Fvw*ww/sumw
+
+ ! Canopy mode:
+ Fwv = max(fv,0.5*(Fsv+Fgv))*2*fg*Fvw/(4*HL*fb)
+ Fwv = min(0.8, Fwv)
+
+ fac1 = 1.*hv/H
+ fac2 = 1.*(H-hv)/H
+ Fwvw = Fwv/(1 + Fws*fac1/Fww + Fwg*fac2/Fww)
+ Fwvs = Fws*fac1/Fww*Fwvw
+ Fwvg = Fwg*fac2/Fww*Fwvw
+
+ ! set upper limit
+ Fwvw = min(Fww, Fwvw)
+ Fwvs = min(Fws, Fwvs)
+ Fwvg = min(Fwg, Fwvg)
+
+ Fwv = Fwvw + Fwvs + Fwvg
+
+ ! View factors with trees
+ !---------------------------------------------------------
+ Fsw_ = Fsw - Fsvw + Fsvw*Td
+ Fsg_ = Fsg - Fsvg + Fsvg*Td
+ Fgw_ = Fgw - Fgvw + Fgvw*Td
+ Fgs_ = Fgs - Fgvs + Fgvs*Td
+ Fwg_ = Fwg - Fwvg + Fwvg*Td
+ Fww_ = Fww - Fwvw + Fwvw*Td
+ Fws_ = Fws - Fwvs + Fwvs*Td
+
+ ! Calculate sunlit wall fraction
+ !-------------------------------------------------
+
+ ! Building wall shadow
+ Sw = ShadowWall_dir(fb/fg, HL, theta)
+
+ Sw_ = Sw; fv_ = fv;
+
+ Sw_ = ShadowWall_dir(fb/fg, (H-hv)/L, theta)
+ fv_ = fv - fv*Sw_
+
+ ! Tree shadow (to all area)
+ Sv = ShadowTree(fv_, theta)
+
+ ! Overlapped shadow between tree and building
+ ! (to ground only)
+ Svw = (Sw-Sw_) * Sv
+
+ ! convert Sv to ground ratio
+ Sv = min(1., Sv/fg)
+
+ ! robust check
+ IF (Sv+Sw-Svw > 1) THEN
+ Svw = Sv+Sw-1
+ ENDIF
+
+ ! Calibrated building ground shadow
+ Sw = Sw - Svw
+
+ ! Sunlit/shaded wall fraction
+ fwsun = 0.5 * (Sw*fg + fb) / (4/PI*fb*HL*tan(theta) + fb)
+ fwsha = 1. - fwsun
+
+ ! Calculate radiation transfer matrix
+ ! AX = B
+ !-------------------------------------------------
+ A(1,:) = (/1-Fww_*fwsun*awall, -Fww_*fwsun*awall, &
+ -Fgw_*fwsun*awall, -Fgw_*fwsun*awall, -Fvw*fwsun*awall/)
+
+ A(2,:) = (/ -Fww_*fwsha*awall, 1-Fww_*fwsha*awall, &
+ -Fgw_*fwsha*awall, -Fgw_*fwsha*awall, -Fvw*fwsha*awall/)
+
+ A(3,:) = (/ -Fwg_*fgimp*agimp, -Fwg_*fgimp*agimp, &
+ 1._r8, 0._r8, -Fvg*fgimp*agimp/)
+
+ A(4,:) = (/ -Fwg_*fgper*agper, -Fwg_*fgper*agper, &
+ 0._r8, 1._r8, -Fvg*fgper*agper/)
+
+ A(5,:) = (/ -Fwv*av , -Fwv*av , &
+ -Fgv*av , -Fgv*av , 1._r8/)
+
+ ! Inverse of matrix A
+ Ainv = MatrixInverse(A)
+
+ ! Radiation transfer for incident direct case
+ !-------------------------------------------------
+
+ ! Incident radiation on sunlit/shaded wall and
+ ! impervious/pervious ground
+ Ewsun = Sw
+ Ewsha = Svw*Td
+ Eg = 1-Sw-Sv+(Sv-Svw)*Td
+ Egimp = Eg*fgimp
+ Egper = Eg*fgper
+ Ev = Sv
+
+ ! Vector of first scattering radiation on each surface
+ B(:) = (/Ewsun*awall, Ewsha*awall, Egimp*agimp, Egper*agper, Ev*av/)
+
+ ! Matrix computing to resolve multiple reflections
+ X = matmul(Ainv, B)
+
+ !-------------------------------------------------
+ ! SAVE results for output
+ !-------------------------------------------------
+
+ ! Radiation absorption by each surface
+ !NOTE: for 3D, absorption per unit area: 4*HL*fb/fg
+ ! for canyon: absorption per unit area: 2*HW
+ swsun(1) = X(1)/awall*(1-awall)!/(4*fwsun*HL*fb/fg)
+ swsha(1) = X(2)/awall*(1-awall)!/(4*fwsha*HL*fb/fg)
+ sgimp(1) = X(3)/agimp*(1-agimp)!/fgimp
+ sgper(1) = X(4)/agper*(1-agper)!/fgper
+ sveg (1) = X(5)/av *(1-av-Td)!/(fv/fg)
+
+ ! albedo of urban canopy
+ albu(1) = X(1)*Fws_ + X(2)*Fws_ + X(3)*Fgs_ + X(4)*Fgs_ + X(5)*Fvs
+
+ ! Energy balance check
+ eb = swsun(1) + swsha(1) + sgimp(1) + sgper(1) + sveg(1) + albu(1)
+ IF (abs(eb-1) > 1e-6) THEN
+ print *, "Direct tree - Energy Balance Check error!", eb-1
+ ENDIF
+
+ ! Radiation transfer for incident diffuse case
+ !-------------------------------------------------
+
+ ! Incident radiation on sunlit/shaded wall and
+ ! impervious/pervious ground
+ Ewsun = Fsw_*fwsun
+ Ewsha = Fsw_*fwsha
+ Eg = Fsg_
+ Egimp = Eg*fgimp
+ Egper = Eg*fgper
+ Ev = Fsv
+
+ ! Vector of first scattering radiation on each surface
+ B(:) = (/Ewsun*awall, Ewsha*awall, Egimp*agimp, Egper*agper, Ev*av/)
+
+ ! Equation solve
+ X = matmul(Ainv, B)
+
+ ! Radiation absorption by each surface
+ !NOTE: for 3D, absorption per unit area: 4*HL*fb/fg
+ ! for canyon: absorption per unit area: 2*HW
+ swsun(2) = X(1)/awall*(1-awall)!/(4*fwsun*HL*fb/fg)
+ swsha(2) = X(2)/awall*(1-awall)!/(4*fwsha*HL*fb/fg)
+ sgimp(2) = X(3)/agimp*(1-agimp)!/fgimp
+ sgper(2) = X(4)/agper*(1-agper)!/fgper
+ sveg (2) = X(5)/ av*(1-av-Td)!/(fv/fg)
+
+ ! albedo of urban canopy
+ albu(2) = X(1)*Fws_ + X(2)*Fws_ + X(3)*Fgs_ + X(4)*Fgs_ + X(5)*Fvs
+
+ ! Energy balance check
+ eb = swsun(2) + swsha(2) + sgimp(2) + sgper(2) + sveg(2) + albu(2)
+ IF (abs(eb-1) > 1e-6) THEN
+ print *, "Diffuse tree - Energy Balance Check error!", eb-1
+ ENDIF
+
+ ! convert to per unit area absorption
+ IF (fb > 0.) THEN
+ swsun = swsun/(4*fwsun*HL*fb)*fg
+ swsha = swsha/(4*fwsha*HL*fb)*fg
+ ENDIF
+ IF (fgimp > 0.) sgimp = sgimp/fgimp
+ IF (fgper > 0.) sgper = sgper/fgper
+ IF ( fv > 0.) sveg = sveg/fv*fg
+
+ ! roof absorption
+ sroof = 1. - aroof
+
+ ! albedo account for both roof and urban's wall and ground
+ albu = aroof*fb + albu*fg
+
+ END SUBROUTINE UrbanVegShortwave
+
+ !-------------------------------------------------
+ ! calculate shadow of wall for incident direct radiation
+ FUNCTION ShadowWall_dir(f, HL, theta) result(Sw)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: f
+ real(r8), intent(in) :: HL
+ real(r8), intent(in) :: theta
+
+ real(r8) :: Sw
+
+ Sw = 1 - exp( -4/PI*f*HL*tan(theta) )
+
+ END FUNCTION ShadowWall_dir
+
+ !-------------------------------------------------
+ ! calculate shadow of wall for incident diffuse radiation
+ FUNCTION ShadowWall_dif(f, HL) result(Sw)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: f
+ real(r8), intent(in) :: HL
+
+ real(r8) :: Sw
+
+ Sw = 1 - exp( -4/PI*f*HL*tan( (53-sqrt(f*HL*100))/180*PI ) )
+
+ END FUNCTION ShadowWall_dif
+
+ !-------------------------------------------------
+ ! calculate shadow of tree
+ FUNCTION ShadowTree(f, theta) result(Sv)
+
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: f
+ real(r8), intent(in) :: theta
+
+ real(r8) :: mu
+ real(r8) :: Sv
+
+ mu = cos(theta)
+ Sv = max( f, (1.-exp(-f/mu))/(1.-f*exp(-1./mu)) )
+
+ END FUNCTION ShadowTree
+
+
+ !-------------------------------------------------
+ ! Returns the inverse of a matrix calculated by finding the LU
+ ! decomposition. Depends on LAPACK.
+ FUNCTION MatrixInverse(A) result(Ainv)
+
+ IMPLICIT NONE
+
+ real(r8), dimension(:,:), intent(in) :: A
+ real(r8), dimension(size(A,1),size(A,2)) :: Ainv
+ real(r8), dimension(size(A,1)) :: work !work array for LAPACK
+ integer, dimension(size(A,1)) :: ipiv !pivot indices
+ integer :: n, info
+
+ ! External procedures defined in LAPACK
+ external DGETRF
+ external DGETRI
+
+ ! Store A in Ainv to prevent it from being overwritten by LAPACK
+ Ainv = A
+ n = size(A,1)
+
+ ! DGETRF computes an LU factorization of a general M-by-N matrix A
+ ! using partial pivoting with row interchanges.
+ CALL DGETRF(n, n, Ainv, n, ipiv, info)
+ IF (info /= 0) THEN
+ CALL CoLM_stop('Matrix is numerically singular!')
+ ENDIF
+
+ ! DGETRI computes the inverse of a matrix using the LU factorization
+ ! computed by DGETRF.
+ CALL DGETRI(n, Ainv, n, ipiv, work, n, info)
+ IF (info /= 0) THEN
+ CALL CoLM_stop('Matrix inversion failed!')
+ ENDIF
+
+ END FUNCTION MatrixInverse
+
+END MODULE MOD_Urban_Shortwave
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Thermal.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Thermal.F90
new file mode 100644
index 0000000000..cfd72215e4
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Thermal.F90
@@ -0,0 +1,1402 @@
+#include
+
+MODULE MOD_Urban_Thermal
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! This is the main subroutine to execute the calculation of urban
+! thermal processes and surface fluxes
+!
+! Created by Hua Yuan, 09/2021
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+ PRIVATE
+
+ PUBLIC :: UrbanTHERMAL
+
+CONTAINS
+
+
+ SUBROUTINE UrbanTHERMAL ( &
+
+ ! model running information
+ ipatch ,patchtype ,lbr ,lbi ,&
+ lbp ,lbl ,deltim ,patchlatr ,&
+ ! forcing
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,forc_t ,forc_q ,forc_psrf ,&
+ forc_rhoair ,forc_frl ,forc_po2m ,forc_pco2m ,&
+ forc_sols ,forc_soll ,forc_solsd ,forc_solld ,&
+ theta ,sabroof ,sabwsun ,sabwsha ,&
+ sabgimp ,sabgper ,sablake ,sabv ,&
+ par ,Fhac ,Fwst ,Fach ,&
+ Fahe ,Fhah ,vehc ,meta ,&
+ ! LUCY model input parameters
+ fix_holiday ,week_holiday ,hum_prof ,pop_den ,&
+ vehicle ,weh_prof ,wdh_prof ,idate ,&
+ patchlonr ,&
+ ! surface parameters
+ froof ,flake ,hroof ,hlr ,&
+ fgper ,pondmx ,eroof ,ewall ,&
+ egimp ,egper ,trsmx0 ,zlnd ,&
+ zsno ,capr ,cnfac ,vf_quartz ,&
+ vf_gravels ,vf_om ,vf_sand ,wf_gravels ,&
+ wf_sand ,csol ,porsl ,psi0 ,&
+#ifdef Campbell_SOIL_MODEL
+ bsw ,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r ,alpha_vgm ,n_vgm ,L_vgm ,&
+ sc_vgm ,fc_vgm ,&
+#endif
+ k_solids ,dksatu ,dksatf ,dkdry ,&
+ BA_alpha ,BA_beta ,&
+ cv_roof ,cv_wall ,cv_gimp ,&
+ tk_roof ,tk_wall ,tk_gimp ,dz_roofsno ,&
+ dz_gimpsno ,dz_gpersno ,dz_lakesno ,dz_wall ,&
+ z_roofsno ,z_gimpsno ,z_gpersno ,z_lakesno ,&
+ z_wall ,zi_roofsno ,zi_gimpsno ,zi_gpersno ,&
+ zi_lakesno ,zi_wall ,dz_lake ,lakedepth ,&
+ dewmx ,sqrtdi ,rootfr ,effcon ,&
+ vmax25 ,c3c4 ,slti ,hlti ,shti,&
+ hhti ,trda ,trdm ,trop ,&
+ g1 ,g0 ,gradm ,binter ,&
+ extkn ,lambda ,&
+
+ ! surface status
+ fsno_roof ,fsno_gimp ,fsno_gper ,scv_roof ,&
+ scv_gimp ,scv_gper ,scv_lake ,snowdp_roof ,&
+ snowdp_gimp ,snowdp_gper ,snowdp_lake ,fwsun ,&
+ dfwsun ,lai ,sai ,htop ,&
+ hbot ,fveg ,sigf ,extkd ,&
+ lwsun ,lwsha ,lgimp ,lgper ,&
+ t_grnd ,t_roofsno ,t_wallsun ,t_wallsha ,&
+ t_gimpsno ,t_gpersno ,t_lakesno ,wliq_roofsno ,&
+ wliq_gimpsno ,wliq_gpersno ,wliq_lakesno ,wice_roofsno ,&
+ wice_gimpsno ,wice_gpersno ,wice_lakesno ,t_lake ,&
+ lake_icefrac ,savedtke1 ,lveg ,tleaf ,&
+ ldew ,ldew_rain ,ldew_snow ,fwet_snow ,&
+ troom ,troof_inner ,twsun_inner ,twsha_inner ,&
+ troommax ,troommin ,tafu ,&
+
+! SNICAR model variables
+ snofrz ,sabg_lyr ,&
+! END SNICAR model variables
+
+ ! output
+ taux ,tauy ,fsena ,fevpa ,&
+ lfevpa ,fsenl ,fevpl ,etr ,&
+ fseng ,fevpg ,olrg ,fgrnd ,&
+ fsen_roof ,fsen_wsun ,fsen_wsha ,fsen_gimp ,&
+ fsen_gper ,fsen_urbl ,troof ,twall ,&
+ lfevp_roof ,lfevp_gimp ,lfevp_gper ,lfevp_urbl ,&
+ qseva_roof ,qseva_gimp ,qseva_gper ,qseva_lake ,&
+ qsdew_roof ,qsdew_gimp ,qsdew_gper ,qsdew_lake ,&
+ qsubl_roof ,qsubl_gimp ,qsubl_gper ,qsubl_lake ,&
+ qfros_roof ,qfros_gimp ,qfros_gper ,qfros_lake ,&
+ imelt_roof ,imelt_gimp ,imelt_gper ,imelt_lake ,&
+ sm_roof ,sm_gimp ,sm_gper ,sm_lake ,&
+ sabg ,rstfac ,rootr ,etr_deficit ,&
+ tref ,qref ,trad ,rst ,&
+ assim ,respc ,errore ,emis ,&
+ z0m ,zol ,rib ,ustar ,&
+ qstar ,tstar ,fm ,fh ,&
+ fq ,hpbl )
+
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical, only: denh2o,roverg,hvap,hsub,rgas,cpair,&
+ stefnc,denice,tfrz,vonkar,grav
+ USE MOD_Urban_Shortwave
+ USE MOD_Urban_Longwave
+ USE MOD_Urban_GroundFlux
+ USE MOD_Urban_Flux
+ USE MOD_Urban_RoofTemperature
+ USE MOD_Urban_WallTemperature
+ USE MOD_Urban_PerviousTemperature
+ USE MOD_Urban_ImperviousTemperature
+ USE MOD_Lake
+ USE MOD_Urban_BEM
+ USE MOD_Urban_LUCY, only: LUCY
+ USE MOD_Eroot, only: eroot
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ USE MOD_Hydro_SoilFunction, only: soil_psi_from_vliq
+#endif
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ integer, intent(in) :: &
+ idate(3) ,&
+ ipatch ,&! patch index
+ patchtype ,&! land patch type (0=soil, 1=urban or built-up, 2=wetland,
+ ! 3=glacier/ice sheet, 4=land water bodies)
+ lbr ,&! lower bound of array
+ lbi ,&! lower bound of array
+ lbp ,&! lower bound of array
+ lbl ! lower bound of array
+
+ real(r8), intent(in) :: &
+ deltim ,&! seconds in a time step [second]
+ patchlatr ! latitude in radians
+
+ real(r8), intent(in) :: &
+ patchlonr ,&! longitude of patch [radian]
+ fix_holiday(365) ,&! Fixed public holidays, holiday(0) or workday(1)
+ week_holiday(7) ,&! week holidays
+ hum_prof(24) ,&! Diurnal metabolic heat profile
+ weh_prof(24) ,&! Diurnal traffic flow profile of weekend
+ wdh_prof(24) ,&! Diurnal traffic flow profile of weekday
+ pop_den ,&! population density
+ vehicle(3) ! vehicle numbers per thousand people
+
+ real(r8), intent(in) :: &
+ ! atmospherical variables and observational height
+ forc_hgt_u ,&! observational height of wind [m]
+ forc_hgt_t ,&! observational height of temperature [m]
+ forc_hgt_q ,&! observational height of humidity [m]
+ forc_us ,&! wind component in eastward direction [m/s]
+ forc_vs ,&! wind component in northward direction [m/s]
+ forc_t ,&! temperature at agcm reference height [kelvin]
+ forc_q ,&! specific humidity at agcm reference height [kg/kg]
+ forc_psrf ,&! atmosphere pressure at the surface [pa]
+ forc_rhoair ,&! density air [kg/m3]
+ forc_frl ,&! atmospheric infrared (longwave) radiation [W/m2]
+ forc_po2m ,&! O2 concentration in atmos. (pascals)
+ forc_pco2m ,&! CO2 concentration in atmos. (pascals)
+ forc_sols ,&! atm vis direct beam solar rad onto srf [W/m2]
+ forc_soll ,&! atm nir direct beam solar rad onto srf [W/m2]
+ forc_solsd ,&! atm vis diffuse solar rad onto srf [W/m2]
+ forc_solld ,&! atm nir diffuse solar rad onto srf [W/m2]
+ theta ,&! sun zenith angle
+ par ,&! vegetation PAR
+ sabv ,&! absorbed shortwave radiation by vegetation [W/m2]
+ sabroof ,&! absorbed shortwave radiation by roof [W/m2]
+ sabwsun ,&! absorbed shortwave radiation by sunlit wall [W/m2]
+ sabwsha ,&! absorbed shortwave radiation by shaded wall [W/m2]
+ sabgimp ,&! absorbed shortwave radiation by impervious road [W/m2]
+ sabgper ,&! absorbed shortwave radiation by ground snow [W/m2]
+ sablake ! absorbed shortwave radiation by lake [W/m2]
+
+ real(r8), intent(in) :: &
+ froof ,&! roof fractional cover [-]
+ flake ,&! urban lake fractional cover [-]
+ hroof ,&! average building height [m]
+ hlr ,&! average building height to their side length [-]
+ fgper ,&! impervious road fractional cover [-]
+ pondmx ,&! maximum ponding for soil [mm]
+ eroof ,&! emissivity of roof
+ ewall ,&! emissivity of walls
+ egimp ,&! emissivity of impervious road
+ egper ,&! emissivity of soil
+
+ trsmx0 ,&! max transpiration for moist soil+100% veg. [mm/s]
+ zlnd ,&! roughness length for soil [m]
+ zsno ,&! roughness length for snow [m]
+ capr ,&! tuning factor to turn first layer T into surface T
+ cnfac ,&! Crank Nicholson factor between 0 and 1
+
+ ! soil physical parameters
+ vf_quartz (1:nl_soil) ,&! volumetric fraction of quartz within mineral soil
+ vf_gravels(1:nl_soil) ,&! volumetric fraction of gravels
+ vf_om (1:nl_soil) ,&! volumetric fraction of organic matter
+ vf_sand (1:nl_soil) ,&! volumetric fraction of sand
+ wf_gravels(1:nl_soil) ,&! gravimetric fraction of gravels
+ wf_sand (1:nl_soil) ,&! gravimetric fraction of sand
+ csol (1:nl_soil) ,&! heat capacity of soil solids [J/(m3 K)]
+ porsl (1:nl_soil) ,&! soil porosity [-]
+ psi0 (1:nl_soil) ,&! soil water suction, negative potential [mm]
+#ifdef Campbell_SOIL_MODEL
+ bsw (1:nl_soil) ,&! clapp and hornberger "b" parameter [-]
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r (1:nl_soil) ,&! residual water content (cm3/cm3)
+
+ alpha_vgm (1:nl_soil) ,&! parameter correspond approximately to inverse of air-entry value
+ n_vgm (1:nl_soil) ,&! a shape parameter
+ L_vgm (1:nl_soil) ,&! pore-connectivity parameter
+ sc_vgm (1:nl_soil) ,&! saturation at air entry value in classical vanGenuchten model [-]
+ fc_vgm (1:nl_soil) ,&! a scaling factor by using air entry value in the Mualem model [-]
+#endif
+ k_solids (1:nl_soil) ,&! thermal conductivity of minerals soil [W/m-K]
+ dkdry (1:nl_soil) ,&! thermal conductivity of dry soil [W/m-K]
+ dksatu (1:nl_soil) ,&! thermal conductivity of saturated unfrozen soil [W/m-K]
+ dksatf (1:nl_soil) ,&! thermal conductivity of saturated frozen soil [W/m-K]
+
+ BA_alpha (1:nl_soil) ,&! alpha in Balland and Arp(2005) thermal cond. scheme
+ BA_beta (1:nl_soil) ,&! beta in Balland and Arp(2005) thermal cond. scheme
+ cv_roof (1:nl_roof) ,&! heat capacity of roof [J/(m2 K)]
+ cv_wall (1:nl_wall) ,&! heat capacity of wall [J/(m2 K)]
+ cv_gimp (1:nl_soil) ,&! heat capacity of impervious [J/(m2 K)]
+ tk_roof (1:nl_roof) ,&! thermal conductivity of roof [W/m-K]
+ tk_wall (1:nl_wall) ,&! thermal conductivity of wall [W/m-K]
+ tk_gimp (1:nl_soil) ,&! thermal conductivity of impervious [W/m-K]
+
+ dz_roofsno(lbr :nl_roof) ,&! layer thickness [m]
+ dz_gimpsno(lbi :nl_soil) ,&! layer thickness [m]
+ dz_gpersno(lbp :nl_soil) ,&! layer thickness [m]
+ dz_wall ( 1:nl_wall) ,&! layer thickness [m]
+ z_roofsno (lbr :nl_roof) ,&! node depth [m]
+ z_gimpsno (lbi :nl_soil) ,&! node depth [m]
+ z_gpersno (lbp :nl_soil) ,&! node depth [m]
+ z_wall ( 1:nl_wall) ,&! node depth [m]
+ zi_roofsno(lbr-1:nl_roof) ,&! interface depth [m]
+ zi_gimpsno(lbi-1:nl_soil) ,&! interface depth [m]
+ zi_gpersno(lbp-1:nl_soil) ,&! interface depth [m]
+ zi_wall ( 0:nl_wall) ,&! interface depth [m]
+ dz_lake ( 1:nl_lake) ,&! lake layer thickness (m)
+ lakedepth ,&! lake depth (m)
+
+ z_lakesno (maxsnl+1:nl_soil) ,&! node depth [m]
+ dz_lakesno(maxsnl+1:nl_soil) ,&! layer thickness [m]
+ zi_lakesno(maxsnl :nl_soil) ,&! interface depth [m]
+
+ ! vegetation parameters
+ dewmx ,&! maximum dew
+ sqrtdi ,&! inverse sqrt of leaf dimension [m**-0.5]
+ rootfr (1:nl_soil) ,&! root fraction
+
+ effcon ,&! quantum efficiency of RuBP regeneration (mol CO2/mol quanta)
+ vmax25 ,&! maximum carboxylation rate at 25 C at canopy top
+ slti ,&! slope of low temperature inhibition function [s3]
+ hlti ,&! 1/2 point of low temperature inhibition function [s4]
+ shti ,&! slope of high temperature inhibition function [s1]
+ hhti ,&! 1/2 point of high temperature inhibition function [s2]
+ trda ,&! temperature coefficient in gs-a model [s5]
+ trdm ,&! temperature coefficient in gs-a model [s6]
+ trop ,&! temperature coefficient in gs-a model
+ g1 ,&! conductance-photosynthesis slope parameter for medlyn model
+ g0 ,&! conductance-photosynthesis intercept for medlyn model
+ gradm ,&! conductance-photosynthesis slope parameter
+ binter ,&! conductance-photosynthesis intercept
+ lambda ,&! marginal water cost of carbon gain
+ extkn ! coefficient of leaf nitrogen allocation
+
+ integer , intent(in) :: &
+ c3c4 ! 1 for C3, 0 for C4
+
+ real(r8), intent(in) :: &
+ fsno_roof ,&! fraction of ground covered by snow
+ fsno_gimp ,&! fraction of ground covered by snow
+ fsno_gper ,&! fraction of ground covered by snow
+ dfwsun ,&! change of fwsun [%]
+ lai ,&! adjusted leaf area index for seasonal variation [-]
+ sai ,&! stem area index [-]
+ htop ,&! canopy crown top height [m]
+ hbot ,&! canopy crown bottom height [m]
+ fveg ,&! fraction of veg cover
+ sigf ,&! fraction of veg cover, excluding snow-covered veg [-]
+ extkd ! diffuse and scattered diffuse PAR extinction coefficient
+
+ real(r8), intent(in) :: hpbl ! atmospheric boundary layer height [m]
+
+ real(r8), intent(inout) :: &
+ fwsun ,&! fraction of sunlit wall [-]
+ lwsun ,&! net longwave radiation of sunlit wall
+ lwsha ,&! net longwave radiation of shaded wall
+ lgimp ,&! net longwave radiation of impervious road
+ lgper ,&! net longwave radiation of pervious road
+ t_grnd ,&! ground temperature
+ t_roofsno ( lbr:nl_wall) ,&! temperatures of roof layers
+ t_wallsun ( nl_wall) ,&! temperatures of roof layers
+ t_wallsha ( nl_wall) ,&! temperatures of roof layers
+ t_gimpsno ( lbi:nl_soil) ,&! temperatures of roof layers
+ t_gpersno ( lbp:nl_soil) ,&! temperatures of roof layers
+ wliq_roofsno( lbr:nl_roof) ,&! liquid water [kg/m2]
+ wliq_gimpsno( lbi:nl_soil) ,&! liquid water [kg/m2]
+ wliq_gpersno( lbp:nl_soil) ,&! liquid water [kg/m2]
+ wice_roofsno( lbr:nl_roof) ,&! ice lens [kg/m2]
+ wice_gimpsno( lbi:nl_soil) ,&! ice lens [kg/m2]
+ wice_gpersno( lbp:nl_soil) ,&! ice lens [kg/m2]
+ t_lake ( nl_lake) ,&! lake temperature [K]
+ lake_icefrac( nl_lake) ,&! lake mass fraction of lake layer that is frozen
+ t_lakesno (maxsnl+1:nl_soil) ,&! temperatures of roof layers
+ wliq_lakesno(maxsnl+1:nl_soil) ,&! liquid water [kg/m2]
+ wice_lakesno(maxsnl+1:nl_soil) ,&! ice lens [kg/m2]
+ savedtke1 ,&! top level eddy conductivity (W/m K)
+ scv_roof ,&! snow cover, water equivalent [mm, kg/m2]
+ scv_gimp ,&! snow cover, water equivalent [mm, kg/m2]
+ scv_gper ,&! snow cover, water equivalent [mm, kg/m2]
+ scv_lake ,&! snow cover, water equivalent [mm, kg/m2]
+ snowdp_roof ,&! snow depth [m]
+ snowdp_gimp ,&! snow depth [m]
+ snowdp_gper ,&! snow depth [m]
+ snowdp_lake ,&! snow depth [m]
+ lveg ,&! net longwave radiation of vegetation [W/m2]
+ tleaf ,&! leaf temperature [K]
+ ldew ,&! depth of water on foliage [kg/(m2 s)]
+ ldew_rain ,&! depth of rain on foliage [kg/(m2 s)]
+ ldew_snow ,&! depth of rain on foliage [kg/(m2 s)]
+ fwet_snow ,&! vegetation canopy snow fractional cover [-]
+ troom ,&! temperature of inner building
+ troof_inner ,&! temperature of inner roof
+ twsun_inner ,&! temperature of inner sunlit wall
+ twsha_inner ,&! temperature of inner shaded wall
+ troommax ,&! maximum temperature of inner building
+ troommin ,&! minimum temperature of inner building
+ tafu ,&! temperature of outer building
+ Fahe ,&! flux from metabolic and vehicle
+ Fhah ,&! flux from heating
+ Fhac ,&! flux from heat or cool AC
+ Fwst ,&! waste heat from cool or heat
+ Fach ,&! flux from air exchange
+ vehc ,&! flux from vehicle
+ meta ! flux from metabolic
+
+ real(r8), intent(out) :: &
+ taux ,&! wind stress: E-W [kg/m/s**2]
+ tauy ,&! wind stress: N-S [kg/m/s**2]
+ fsena ,&! sensible heat from canopy height to atm [W/m2]
+ fevpa ,&! evapotranspiration from canopy height to atm [mm/s]
+ lfevpa ,&! latent heat flux from canopy height to atm [W/m2]
+ fsenl ,&! sensible heat from leaves [W/m2]
+ fevpl ,&! evaporation+transpiration from leaves [mm/s]
+ etr ,&! transpiration rate [mm/s]
+ fseng ,&! sensible heat flux from ground [W/m2]
+ fevpg ,&! evaporation heat flux from ground [mm/s]
+ olrg ,&! outgoing long-wave radiation from ground+canopy
+ fgrnd ,&! ground heat flux [W/m2]
+
+ fsen_roof ,&! sensible heat from roof [W/m2]
+ fsen_wsun ,&! sensible heat from sunlit wall [W/m2]
+ fsen_wsha ,&! sensible heat from shaded wall [W/m2]
+ fsen_gimp ,&! sensible heat from impervious road [W/m2]
+ fsen_gper ,&! sensible heat from pervious road [W/m2]
+ fsen_urbl ,&! sensible heat from urban vegetation [W/m2]
+
+ lfevp_roof ,&! latent heat flux from roof [W/m2]
+ lfevp_gimp ,&! latent heat flux from impervious road [W/m2]
+ lfevp_gper ,&! latent heat flux from pervious road [W/m2]
+ lfevp_urbl ,&! latent heat flux from urban vegetation [W/m2]
+
+ troof ,&! temperature of roof [K]
+ twall ,&! temperature of wall [K]
+
+ qseva_roof ,&! ground soil surface evaporation rate (mm h2o/s)
+ qseva_gimp ,&! ground soil surface evaporation rate (mm h2o/s)
+ qseva_gper ,&! ground soil surface evaporation rate (mm h2o/s)
+ qseva_lake ,&! ground soil surface evaporation rate (mm h2o/s)
+ qsdew_roof ,&! ground soil surface dew formation (mm h2o /s) [+]
+ qsdew_gimp ,&! ground soil surface dew formation (mm h2o /s) [+]
+ qsdew_gper ,&! ground soil surface dew formation (mm h2o /s) [+]
+ qsdew_lake ,&! ground soil surface dew formation (mm h2o /s) [+]
+ qsubl_roof ,&! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qsubl_gimp ,&! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qsubl_gper ,&! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qsubl_lake ,&! sublimation rate from soil ice pack (mm h2o /s) [+]
+ qfros_roof ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_gimp ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_gper ,&! surface dew added to snow pack (mm h2o /s) [+]
+ qfros_lake ! surface dew added to snow pack (mm h2o /s) [+]
+
+ integer, intent(out) :: &
+ imelt_roof(lbr:nl_roof) ,&! flag for melting or freezing [-]
+ imelt_gimp(lbi:nl_soil) ,&! flag for melting or freezing [-]
+ imelt_gper(lbp:nl_soil) ,&! flag for melting or freezing [-]
+ imelt_lake(maxsnl+1:nl_soil) ! flag for melting or freezing [-]
+
+ real(r8), intent(out) :: &
+ sm_roof ,&! rate of snowmelt [kg/(m2 s)]
+ sm_gimp ,&! rate of snowmelt [kg/(m2 s)]
+ sm_gper ,&! rate of snowmelt [kg/(m2 s)]
+ sm_lake ,&! rate of snowmelt [kg/(m2 s)]
+ sabg ,&! overall ground solar radiation absorption (+wall)
+ rstfac ,&! factor of soil water stress
+ rootr(1:nl_soil) ,&! root resistance of a layer, all layers add to 1
+ etr_deficit ,&! urban irrigation [mm/s]
+ tref ,&! 2 m height air temperature [kelvin]
+ qref ,&! 2 m height air specific humidity
+ trad ,&! radiative temperature [K]
+ rst ,&! stomatal resistance (s m-1)
+ assim ,&! assimilation
+ respc ,&! respiration
+ errore ,&! energy balance error [w/m2]
+
+ ! additional variables required by coupling with WRF or RSM model
+ emis ,&! averaged bulk surface emissivity
+ z0m ,&! effective roughness [m]
+ zol ,&! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib ,&! bulk Richardson number in surface layer
+ ustar ,&! u* in similarity theory [m/s]
+ qstar ,&! q* in similarity theory [kg/kg]
+ tstar ,&! t* in similarity theory [K]
+ fm ,&! integral of profile function for momentum
+ fh ,&! integral of profile function for heat
+ fq ! integral of profile function for moisture
+
+! SNICAR model variables
+ real(r8), intent(in) :: sabg_lyr(lbp:1) !snow layer absorption
+ real(r8), intent(out) :: snofrz (lbp:0) !snow freezing rate (col,lyr) [kg m-2 s-1]
+! END SNICAR model variables
+
+!-------------------------- Local Variables ----------------------------
+
+ integer :: nurb ! number of aboveground urban components [-]
+
+ logical :: doveg ! run model with vegetation
+
+ real(r8) :: &
+ fg ,&! ground fraction ( impervious + soil + snow )
+ fsenroof ,&! sensible heat flux from roof [W/m2]
+ fsenwsun ,&! sensible heat flux from sunlit wall [W/m2]
+ fsenwsha ,&! sensible heat flux from shaded wall [W/m2]
+ fsengimp ,&! sensible heat flux from impervious road [W/m2]
+ fsengper ,&! sensible heat flux from ground soil [W/m2]
+ fevproof ,&! evaporation heat flux from roof [mm/s]
+ fevpgimp ,&! evaporation heat flux from impervious road [mm/s]
+ fevpgper ,&! evaporation heat flux from ground soil [mm/s]
+
+ croofs ,&! deriv of roof sensible heat flux wrt soil temp [w/m**2/k]
+ cwsuns ,&! deriv of sunlit wall sensible heat flux wrt soil temp [w/m**2/k]
+ cwshas ,&! deriv of shaded wall sensible heat flux wrt soil temp [w/m**2/k]
+ cgrnds ,&! deriv of ground latent heat flux wrt soil temp [w/m**2/k]
+ croofl ,&! deriv of roof latent heat flux wrt soil temp [w/m**2/k]
+ cgimpl ,&! deriv of impervious latent heat flux wrt soil temp [w/m**2/k]
+ cgperl ,&! deriv of pervious latent heat flux wrt soil temp [w/m**2/k]
+ croof ,&! deriv of roof total flux wrt soil temp [w/m**2/k]
+ cgimp ,&! deriv of impervious total heat flux wrt soil temp [w/m**2/k]
+ cgper ,&! deriv of pervious total heat flux wrt soil temp [w/m**2/k]
+
+ dqroofdT ,&! d(qroof)/dT
+ dqgimpdT ,&! d(qgimp)/dT
+ dqgperdT ,&! d(qgper)/dT
+
+ degdT ,&! d(eg)/dT
+ eg ,&! water vapor pressure at temperature T [pa]
+ egsmax ,&! max. evaporation which soil can provide at one time step
+ egidif ,&! the excess of evaporation over "egsmax"
+ emg ,&! ground emissivity (0.97 for snow,
+ ! glaciers and water surface; 0.96 for soil and wetland)
+ etrc ,&! maximum possible transpiration rate [mm/s]
+ fac ,&! soil wetness of surface layer
+ factr(lbr:nl_roof) ,&! used in computing tridiagonal matrix
+ facti(lbi:nl_soil) ,&! used in computing tridiagonal matrix
+ factp(lbp:nl_soil) ,&! used in computing tridiagonal matrix
+ hr ,&! relative humidity
+ htvp_roof ,&! latent heat of vapor of water (or sublimation) [J/Kg]
+ htvp_gimp ,&! latent heat of vapor of water (or sublimation) [J/Kg]
+ htvp_gper ,&! latent heat of vapor of water (or sublimation) [J/Kg]
+ olru ,&! olrg excluding downwelling reflection [W/m2]
+ olrb ,&! olrg assuming black body emission [W/m2]
+ psit ,&! negative potential of soil
+
+ rss ,&! soil resistance
+ qroof ,&! roof specific humidity [kg/kg]
+ qgimp ,&! ground impervious road specific humidity [kg/kg]
+ qgper ,&! ground pervious specific humidity [kg/kg]
+ qsatg ,&! saturated humidity [kg/kg]
+ qsatgdT ,&! d(qsatg)/dT
+ qred ,&! soil surface relative humidity
+ thm ,&! intermediate variable (forc_t+0.0098*forc_hgt_t)
+ th ,&! potential temperature (kelvin)
+ thv ,&! virtual potential temperature (kelvin)
+
+ twsun ,&! temperature of sunlit wall
+ twsha ,&! temperature of shaded wall
+ tgimp ,&! temperature of impervious road
+ tgper ,&! ground soil temperature
+ tlake ,&! lake surface temperature
+ troof_bef ,&! temperature of roof
+ twsun_bef ,&! temperature of sunlit wall
+ twsha_bef ,&! temperature of shaded wall
+ tgimp_bef ,&! temperature of impervious road
+ tgper_bef ,&! ground soil temperature
+ troof_nl_bef ,&! temperature of roof
+ twsun_nl_bef ,&! temperature of sunlit wall
+ twsha_nl_bef ,&! temperature of shaded wall
+ tkdz_roof ,&! heat flux from room to roof
+ tkdz_wsun ,&! heat flux from room to sunlit wall
+ tkdz_wsha ,&! heat flux from room to shaded wall
+ tinc ,&! temperature difference of two time step
+ ev ,&! emissivity of vegetation [-]
+ lroof ,&! net longwave radiation of roof
+ rout ,&! out-going longwave radiation from roof
+ lout ,&! out-going longwave radiation
+ lnet ,&! overall net longwave radiation
+ dlw ,&! change of net longwave radiation
+ dlwbef ,&! change of net longwave radiation
+ dlwsun ,&! change of net longwave radiation of sunlit wall
+ dlwsha ,&! change of net longwave radiation of shaded wall
+ dlgimp ,&! change of net longwave radiation of impervious road
+ dlgper ,&! change of net longwave radiation of pervious road
+ dlveg ,&! change of net longwave radiation of vegetation [W/m2]
+ dlout ,&! change of out-going radiation due to temp change
+ clroof ,&! deriv of lroof wrt roof temp [w/m**2/k]
+ clwsun ,&! deriv of lwsun wrt wsun temp [w/m**2/k]
+ clwsha ,&! deriv of lwsha wrt wsha temp [w/m**2/k]
+ clgimp ,&! deriv of lgimp wrt gimp temp [w/m**2/k]
+ clgper ,&! deriv of lgper wrt soil temp [w/m**2/k]
+ fwsha ,&! fraction of shaded wall [-]
+ ur ,&! wind speed at reference height [m/s]
+ wx ,&! partial volume of ice and water of surface layer
+ xmf ! total latent heat of phase change of ground water
+
+ real(r8) :: &
+ taux_lake ,&! wind stress: E-W [kg/m/s**2]
+ tauy_lake ,&! wind stress: N-S [kg/m/s**2]
+ fsena_lake ,&! sensible heat from canopy height to atmosphere [W/m2]
+ fevpa_lake ,&! evapotranspiration from canopy height to atmosphere [mm/s]
+ lfevpa_lake ,&! latent heat flux from canopy height to atmosphere [W/m2]
+ fseng_lake ,&! sensible heat flux from ground [W/m2]
+ fevpg_lake ,&! evaporation heat flux from ground [mm/s]
+ olrg_lake ,&! outgoing long-wave radiation from ground+canopy
+ fgrnd_lake ,&! ground heat flux [W/m2]
+ tref_lake ,&! 2 m height air temperature [kelvin]
+ qref_lake ,&! 2 m height air specific humidity
+ trad_lake ,&! radiative temperature [K]
+ lnet_lake ,&! net longwave radiation
+ emis_lake ,&! averaged bulk surface emissivity
+ z0m_lake ,&! effective roughness [m]
+ zol_lake ,&! dimensionless height (z/L) used in Monin-Obukhov theory
+ rib_lake ,&! bulk Richardson number in surface layer
+ ustar_lake ,&! u* in similarity theory [m/s]
+ qstar_lake ,&! q* in similarity theory [kg/kg]
+ tstar_lake ,&! t* in similarity theory [K]
+ fm_lake ,&! integral of profile function for momentum
+ fh_lake ,&! integral of profile function for heat
+ fq_lake ,&! integral of profile function for moisture
+ dheatl ! vegetation heat change [W/m2]
+
+ real(r8) :: z0m_g,z0h_g,zol_g,obu_g,ustar_g,qstar_g,tstar_g
+ real(r8) :: fm10m,fm_g,fh_g,fq_g,fh2m,fq2m,um,obu,eb
+
+ ! definition for urban related
+ real(r8), allocatable :: Ainv(:,:) ! Inverse of Radiation transfer matrix
+ real(r8), allocatable :: X(:) ! solution
+ real(r8), allocatable :: dX(:) ! solution
+ real(r8), allocatable :: B(:) ! Vectors of incident radiation on each surface
+ real(r8), allocatable :: B1(:) ! Vectors of incident radiation on each surface
+ real(r8), allocatable :: dBdT(:) ! Vectors of incident radiation on each surface
+ real(r8), allocatable :: dT(:) ! Vectors of incident radiation on each surface
+ real(r8), allocatable :: SkyVF(:) ! View factor to sky
+ real(r8), allocatable :: VegVF(:) ! View factor to vegetation
+ real(r8), allocatable :: fcover(:) ! fractional cover of roof, wall, ground and veg
+
+
+!=======================================================================
+! [1] Initial set and propositional variables
+!=======================================================================
+
+ ! fluxes
+ fsenl = 0.; fevpl = 0.
+ etr = 0.; rst = 2.0e4
+ assim = 0.; respc = 0.
+
+ emis = 0.; z0m = 0.
+ zol = 0.; rib = 0.
+ ustar = 0.; qstar = 0.
+ tstar = 0.; rootr = 0.
+
+ dheatl = 0.
+
+ ! latent heat, assumed that the sublimation occurred only as wliq_gpersno=0
+ htvp_roof = hvap
+ htvp_gimp = hvap
+ htvp_gper = hvap
+ IF (wliq_roofsno(lbr)<=0. .and. wice_roofsno(lbr)>0.) htvp_roof = hsub
+ IF (wliq_gimpsno(lbi)<=0. .and. wice_gimpsno(lbi)>0.) htvp_gimp = hsub
+ IF (wliq_gpersno(lbp)<=0. .and. wice_gpersno(lbp)>0.) htvp_gper = hsub
+
+ ! potential temperature at the reference height
+ thm = forc_t + 0.0098*forc_hgt_t !intermediate variable equivalent to
+ !forc_t*(pgcm/forc_psrf)**(rgas/cpair)
+ th = forc_t*(100000./forc_psrf)**(rgas/cpair) !potential T
+ thv = th*(1.+0.61*forc_q) !virtual potential T
+ ur = max(0.1,sqrt(forc_us*forc_us+forc_vs*forc_vs)) !limit set to 0.1
+
+ ! Adjust wall temperature, weighted average according to fwsun, dfwsun
+ !-------------------------------------------
+ fwsha = 1. - fwsun
+
+ IF (dfwsun > 0) THEN
+ t_wallsun = (fwsun*t_wallsun + dfwsun*t_wallsha) / (fwsun+dfwsun)
+ twsun_inner = (fwsun*twsun_inner + dfwsun*twsun_inner) / (fwsun+dfwsun)
+ lwsun = (fwsun*lwsun + dfwsun*lwsha ) / (fwsun+dfwsun)
+ ENDIF
+
+ IF (dfwsun < 0) THEN
+ t_wallsha = (fwsha*t_wallsha - dfwsun*t_wallsun) / (fwsha-dfwsun)
+ twsha_inner = (fwsha*twsha_inner - dfwsun*twsun_inner) / (fwsha-dfwsun)
+ lwsha = (fwsha*lwsha - dfwsun*lwsun ) / (fwsha-dfwsun)
+ ENDIF
+
+ ! update fwsun
+ fwsun = fwsun + dfwsun
+
+ ! temperature and water mass from previous time step
+ twsun = t_wallsun( 1 )
+ twsha = t_wallsha( 1 )
+ troof = t_roofsno(lbr)
+ tgimp = t_gimpsno(lbi)
+ tgper = t_gpersno(lbp)
+
+ troof_nl_bef = t_roofsno(nl_roof)
+ twsun_nl_bef = t_wallsun(nl_wall)
+ twsha_nl_bef = t_wallsha(nl_wall)
+
+ !TODO: ???how to calculate tlake
+ IF (lbl < 1) THEN
+ tlake = t_lakesno(lbl)
+ ELSE
+ tlake = t_lake(1)
+ ENDIF
+
+ ! SAVE temperature
+ troof_bef = troof
+ twsun_bef = twsun
+ twsha_bef = twsha
+ tgimp_bef = tgimp
+ tgper_bef = tgper
+
+ ! SAVE longwave for the last time
+ dlwsun = lwsun
+ dlwsha = lwsha
+ dlgimp = lgimp
+ dlgper = lgper
+ dlveg = lveg
+
+ fg = 1. - froof
+
+ IF (lai+sai>1.e-6 .and. fveg>0.) THEN
+ doveg = .true.
+ ELSE
+ doveg = .false.
+ ENDIF
+
+ ! convert AHE to urban area, i.e. (1-flake)
+ IF ( 1-flake > 0. ) THEN
+ Fhac = Fhac / (1-flake)
+ Fwst = Fwst / (1-flake)
+ Fach = Fach / (1-flake)
+ vehc = vehc / (1-flake)
+ meta = meta / (1-flake)
+ ENDIF
+
+
+!=======================================================================
+! [2] specific humidity and its derivative at ground surface
+!=======================================================================
+
+ qred = 1.
+ CALL qsadv(tgper,forc_psrf,eg,degdT,qsatg,qsatgdT)
+
+ ! initialization for rss
+ rss = 0.
+
+ IF (patchtype <=1 ) THEN !soil ground
+ wx = (wliq_gpersno(1)/denh2o + wice_gpersno(1)/denice)/dz_gpersno(1)
+ IF (porsl(1) < 1.e-6) THEN !bed rock
+ fac = 0.001
+ ELSE
+ fac = min(1.,wx/porsl(1))
+ fac = max( fac, 0.001 )
+ ENDIF
+
+#ifdef Campbell_SOIL_MODEL
+ psit = psi0(1) * fac ** (- bsw(1) ) !psit = max(smpmin, psit)
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ psit = soil_psi_from_vliq ( fac*(porsl(1)-theta_r(1)) + theta_r(1), &
+ porsl(1), theta_r(1), psi0(1), &
+ 5, (/alpha_vgm(1), n_vgm(1), L_vgm(1), sc_vgm(1), fc_vgm(1)/))
+#endif
+ psit = max( -1.e8, psit )
+ hr = exp(psit/roverg/tgper)
+ qred = (1.-fsno_gper)*hr + fsno_gper
+
+ IF (lbp == 1) THEN !no snow layer exist
+
+ ! calculate soil resistance for evaporation
+ wx = (sum(wliq_gpersno(1:2))/denh2o+sum(wice_gpersno(1:2))/denice)/sum(dz_gpersno(1:2))
+ IF (sum(porsl(1:2)) < 1.e-6) THEN !bed rock
+ fac = 0.001
+ ELSE
+ fac = min(1.,sum(dz_gpersno(1:2))*wx/(dz_gpersno(1)*porsl(1)+dz_gpersno(2)*porsl(2)))
+ fac = max( fac, 0.001 )
+ ENDIF
+
+ ! Sellers et al., 1992
+ rss = (1-fsno_gper)*exp(8.206-4.255*fac)
+ ENDIF
+ ENDIF
+
+ qgper = qred*qsatg
+ dqgperdT = qred*qsatgdT
+
+ IF (qsatg>forc_q .and. forc_q>qred*qsatg) THEN
+ qgper = forc_q; dqgperdT = 0.
+ ENDIF
+
+ CALL qsadv(tgimp,forc_psrf,eg,degdT,qsatg,qsatgdT)
+ qgimp = qsatg
+ dqgimpdT = qsatgdT
+
+ CALL qsadv(troof,forc_psrf,eg,degdT,qsatg,qsatgdT)
+ qroof = qsatg
+ dqroofdT = qsatgdT
+
+
+!=======================================================================
+! [3] calculate longwave radiation
+!=======================================================================
+
+ IF ( doveg ) THEN
+
+ allocate ( Ainv(5,5) )
+ allocate ( X(5) )
+ allocate ( dX(5) )
+ allocate ( B(5) )
+ allocate ( B1(5) )
+ allocate ( dBdT(5) )
+ allocate ( SkyVF(5) )
+ allocate ( VegVF(5) )
+ allocate ( fcover(0:5) )
+ allocate ( dT(0:5) )
+
+ ! call longwave function (vegetation)
+ CALL UrbanVegLongwave ( &
+ theta, hlr, froof, fgper, hroof, forc_frl, &
+ twsun, twsha, tgimp, tgper, ewall, egimp, &
+ egper, lai, sai, fveg, (htop+hbot)/2., &
+ ev, Ainv, B, B1, dBdT, SkyVF, VegVF, fcover)
+ ELSE
+
+ allocate ( Ainv(4,4) )
+ allocate ( X(4) )
+ allocate ( dX(4) )
+ allocate ( B(4) )
+ allocate ( B1(4) )
+ allocate ( dBdT(4) )
+ allocate ( SkyVF(4) )
+ allocate ( fcover(0:4) )
+ allocate ( dT(0:4) )
+
+ ! call longwave function, calculate Ainv, B, B1, dBdT
+ CALL UrbanOnlyLongwave ( &
+ theta, hlr, froof, fgper, hroof, forc_frl, &
+ twsun, twsha, tgimp, tgper, ewall, egimp, egper, &
+ Ainv, B, B1, dBdT, SkyVF, fcover)
+
+ ! calculate longwave radiation abs, for UrbanOnlyLongwave
+ !-------------------------------------------
+ X = matmul(Ainv, B)
+
+ ! using the longwave radiation transfer matrix to calculate
+ ! LW radiation absorption by each surface and total absorption.
+ lwsun = ( ewall*X(1) - B1(1) ) / (1-ewall)
+ lwsha = ( ewall*X(2) - B1(2) ) / (1-ewall)
+ lgimp = ( egimp*X(3) - B1(3) ) / (1-egimp)
+ lgper = ( egper*X(4) - B1(4) ) / (1-egper)
+
+ ! Out-going LW of urban canopy
+ lout = sum( X * SkyVF )
+
+ ! Energy balance check
+ eb = lwsun + lwsha + lgimp + lgper + lout
+
+ IF (abs(eb-forc_frl) > 1e-6) THEN
+ print *, "Urban Only Longwave - Energy Balance Check error!", eb-forc_frl
+ ENDIF
+
+ ! fur per unit surface
+ IF (fcover(1) >0.) lwsun = lwsun / fcover(1) * fg !/ (4*fwsun*HL*fb/fg)
+ IF (fcover(2) >0.) lwsha = lwsha / fcover(2) * fg !/ (4*fwsha*HL*fb/fg)
+ IF (fcover(3) >0.) lgimp = lgimp / fcover(3) * fg !/ fgimp
+ IF (fcover(4) >0.) lgper = lgper / fcover(4) * fg !/ fsoil
+
+ ! added last time value
+ lwsun = lwsun + dlwsun
+ lwsha = lwsha + dlwsha
+ lgimp = lgimp + dlgimp
+ lgper = lgper + dlgper
+ ENDIF
+
+ dlwbef = dlwsun*fcover(1) + dlwsha*fcover(2) + dlgimp*fcover(3) + dlgper*fcover(4)
+ IF ( doveg ) dlwbef = dlwbef + dlveg*fcover(5)
+ dlwbef = dlwbef*(1-flake)
+
+ ! roof net longwave
+ lroof = eroof*forc_frl - eroof*stefnc*troof**4
+
+
+!=======================================================================
+! [4] Compute sensible and latent fluxes and their derivatives with respect
+! to ground temperature using ground temperatures from previous time step.
+!=======================================================================
+
+ ! bare ground case
+ CALL UrbanGroundFlux (forc_hgt_u,forc_hgt_t,forc_hgt_q,forc_us, &
+ forc_vs,forc_t,forc_q,forc_rhoair,forc_psrf, &
+ ur,thm,th,thv,zlnd,zsno,fsno_gimp, &
+ lbi,wliq_gimpsno(1),wice_gimpsno(1), &
+ fcover,tgimp,tgper,qgimp,qgper,tref,qref, &
+ z0m_g,z0h_g,zol_g,ustar_g,qstar_g,tstar_g,fm_g,fh_g,fq_g)
+
+ ! SAVE variables for bare ground case
+ obu_g = forc_hgt_u / zol_g
+
+
+!=======================================================================
+! [5] Canopy temperature, fluxes from roof/wall/ground
+!=======================================================================
+
+ IF ( doveg ) THEN
+
+ ! soil water stress factor on stomatal resistance
+ CALL eroot (nl_soil,trsmx0,porsl,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r, alpha_vgm, n_vgm, L_vgm, sc_vgm, fc_vgm, &
+#endif
+ psi0,rootfr,dz_gpersno,t_gpersno,wliq_gpersno,rootr,etrc,rstfac)
+
+ nurb = 3
+
+ CALL UrbanVegFlux ( &
+
+ ! model running information
+ ipatch ,deltim ,lbr ,lbi ,&
+ ! forcing
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,thm ,th ,thv ,&
+ forc_q ,forc_psrf ,forc_rhoair ,forc_frl ,&
+ forc_po2m ,forc_pco2m ,par ,sabv ,&
+ rstfac ,Fhac ,Fwst ,Fach ,&
+ vehc ,meta ,&
+ ! urban and vegetation parameters
+ hroof ,hlr ,nurb ,fcover ,&
+ ewall ,egimp ,egper ,ev ,&
+ htop ,hbot ,lai ,sai ,&
+ sqrtdi ,effcon ,vmax25 ,c3c4 ,slti,&
+ hlti ,shti ,hhti ,trda ,&
+ trdm ,trop ,g1 ,g0 ,&
+ gradm ,binter ,extkn ,extkd ,&
+ dewmx ,etrc ,trsmx0 ,lambda ,&
+ ! surface status
+ z0h_g ,obu_g ,ustar_g ,zlnd ,&
+ zsno ,fsno_roof ,fsno_gimp ,fsno_gper ,&
+ wliq_roofsno(1),wliq_gimpsno(1),wice_roofsno(1),wice_gimpsno(1),&
+ htvp_roof ,htvp_gimp ,htvp_gper ,troof ,&
+ twsun ,twsha ,tgimp ,tgper ,&
+ qroof ,qgimp ,qgper ,dqroofdT ,&
+ dqgimpdT ,dqgperdT ,sigf ,tleaf ,&
+ ldew ,ldew_rain ,ldew_snow ,fwet_snow ,&
+ dheatl ,rss ,etr_deficit ,&
+ ! longwave related
+ Ainv ,B ,B1 ,dBdT ,&
+ SkyVF ,VegVF ,&
+ ! output
+ taux ,tauy ,fsenroof ,fsenwsun ,&
+ fsenwsha ,fsengimp ,fsengper ,fevproof ,&
+ fevpgimp ,fevpgper ,croofs ,cwsuns ,&
+ cwshas ,cgrnds ,croofl ,cgimpl ,&
+ cgperl ,croof ,cgimp ,cgper ,&
+ fsenl ,fevpl ,etr ,rst ,&
+ assim ,respc ,lwsun ,lwsha ,&
+ lgimp ,lgper ,lveg ,lout ,&
+ tref ,qref ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,tafu )
+ ELSE
+
+ nurb = 2
+
+ ! CALL urban flux
+ CALL UrbanOnlyFlux ( &
+ ! model running information
+ ipatch ,deltim ,lbr ,lbi ,&
+ ! forcing
+ forc_hgt_u ,forc_hgt_t ,forc_hgt_q ,forc_us ,&
+ forc_vs ,thm ,th ,thv ,&
+ forc_q ,forc_psrf ,forc_rhoair ,Fhac ,&
+ Fwst ,Fach ,vehc ,meta ,&
+ ! surface parameters
+ hroof ,hlr ,nurb ,fcover ,&
+ ! surface status
+ z0h_g ,obu_g ,ustar_g ,zlnd ,&
+ zsno ,fsno_roof ,fsno_gimp ,fsno_gper ,&
+ wliq_roofsno(1),wliq_gimpsno(1),wice_roofsno(1),wice_gimpsno(1),&
+ htvp_roof ,htvp_gimp ,htvp_gper ,troof ,&
+ twsun ,twsha ,tgimp ,tgper ,&
+ qroof ,qgimp ,qgper ,dqroofdT ,&
+ dqgimpdT ,dqgperdT ,rss ,&
+ ! output
+ taux ,tauy ,fsenroof ,fsenwsun ,&
+ fsenwsha ,fsengimp ,fsengper ,fevproof ,&
+ fevpgimp ,fevpgper ,croofs ,cwsuns ,&
+ cwshas ,cgrnds ,croofl ,cgimpl ,&
+ cgperl ,croof ,cgimp ,cgper ,&
+ tref ,qref ,z0m ,zol ,&
+ rib ,ustar ,qstar ,tstar ,&
+ fm ,fh ,fq ,tafu )
+
+ !TODO: check
+ tleaf = forc_t
+ ldew = 0.
+ ldew_rain = 0.
+ ldew_snow = 0.
+ fwet_snow = 0.
+ rstfac = 0.
+ fsenl = 0.0
+ fevpl = 0.0
+ etr = 0.0
+ assim = 0.0
+ respc = 0.0
+
+ ENDIF
+
+!=======================================================================
+! [6] roof/wall/ground temperature
+!=======================================================================
+
+ ! Calculate the change rate of long-wave radiation
+ ! caused by temperature change
+ clroof = - 4.*eroof*stefnc*troof**3
+ clwsun = ( ewall*Ainv(1,1) - 1. ) / (1-ewall) * dBdT(1)
+ clwsha = ( ewall*Ainv(2,2) - 1. ) / (1-ewall) * dBdT(2)
+ clgimp = ( egimp*Ainv(3,3) - 1. ) / (1-egimp) * dBdT(3)
+ clgper = ( egper*Ainv(4,4) - 1. ) / (1-egper) * dBdT(4)
+
+ IF (fcover(1) >0. ) clwsun = clwsun / fcover(1) * fg !/ (4*fwsun*HL*fb/fg)
+ IF (fcover(2) >0. ) clwsha = clwsha / fcover(2) * fg !/ (4*fwsha*HL*fb/fg)
+ IF (fcover(3) >0. ) clgimp = clgimp / fcover(3) * fg !/ fgimp
+ IF (fcover(4) >0. ) clgper = clgper / fcover(4) * fg !/ fsoil
+
+ ! Calculate the temperature of each component: roof, wall, floor
+ CALL UrbanRoofTem (lbr,deltim,capr,cnfac,&
+ cv_roof,tk_roof,dz_roofsno,z_roofsno,zi_roofsno,&
+ t_roofsno,wice_roofsno,wliq_roofsno,scv_roof,snowdp_roof,&
+ troof_inner,lroof,clroof,sabroof,fsenroof,fevproof,croof,htvp_roof,&
+ imelt_roof,sm_roof,xmf,factr,tkdz_roof)
+
+ CALL UrbanWallTem (deltim,capr,cnfac,&
+ cv_wall,tk_wall,t_wallsun,dz_wall,z_wall,zi_wall,&
+ twsun_inner,lwsun,clwsun,sabwsun,fsenwsun,cwsuns,tkdz_wsun)
+
+ CALL UrbanWallTem (deltim,capr,cnfac,&
+ cv_wall,tk_wall,t_wallsha,dz_wall,z_wall,zi_wall,&
+ twsha_inner,lwsha,clwsha,sabwsha,fsenwsha,cwshas,tkdz_wsha)
+
+ CALL UrbanImperviousTem (patchtype,lbi,deltim,&
+ capr,cnfac,csol,k_solids,porsl,psi0,dkdry,dksatu,dksatf,&
+ vf_quartz,vf_gravels,vf_om,vf_sand,wf_gravels,wf_sand,&
+ BA_alpha, BA_beta,&
+ cv_gimp,tk_gimp,dz_gimpsno,z_gimpsno,zi_gimpsno,&
+ t_gimpsno,wice_gimpsno,wliq_gimpsno,scv_gimp,snowdp_gimp,&
+ lgimp,clgimp,sabgimp,fsengimp,fevpgimp,cgimp,htvp_gimp,&
+ imelt_gimp,sm_gimp,xmf,facti)
+
+ CALL UrbanPerviousTem (patchtype,lbp,deltim,&
+ capr,cnfac,csol,k_solids,porsl,psi0,dkdry,dksatu,dksatf,&
+ vf_quartz,vf_gravels,vf_om,vf_sand,wf_gravels,wf_sand,&
+ BA_alpha, BA_beta,&
+#ifdef Campbell_SOIL_MODEL
+ bsw,&
+#endif
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ theta_r,alpha_vgm,n_vgm,L_vgm,&
+ sc_vgm,fc_vgm,&
+#endif
+ dz_gpersno,z_gpersno,zi_gpersno,&
+ t_gpersno,wice_gpersno,wliq_gpersno,scv_gper,snowdp_gper,&
+ lgper,clgper,sabgper,fsengper,fevpgper,cgper,htvp_gper,&
+ imelt_gper,sm_gper,xmf,factp)
+
+ ! update temperature
+ twsun = t_wallsun( 1 )
+ twsha = t_wallsha( 1 )
+ troof = t_roofsno(lbr)
+ tgimp = t_gimpsno(lbi)
+ tgper = t_gpersno(lbp)
+ twall = (twsun*fwsun + twsha*fwsha)/(fwsun + fwsha)
+
+ ! calculate lake temperature and sensible/latent heat fluxes
+ CALL laketem ( &
+ ! "in" laketem arguments
+ ! ---------------------------
+ patchtype ,maxsnl ,nl_soil ,nl_lake ,&
+ patchlatr ,deltim ,forc_hgt_u ,forc_hgt_t ,&
+ forc_hgt_q ,forc_us ,forc_vs ,forc_t ,&
+ forc_q ,forc_rhoair ,forc_psrf ,forc_sols ,&
+ forc_soll ,forc_solsd ,forc_solld ,sablake ,&
+ forc_frl ,dz_lakesno ,z_lakesno ,zi_lakesno ,&
+ dz_lake ,lakedepth ,vf_quartz ,vf_gravels ,&
+ vf_om ,vf_sand ,wf_gravels ,wf_sand ,&
+ porsl ,csol ,k_solids ,&
+ dksatu ,dksatf ,dkdry ,&
+ BA_alpha ,BA_beta ,hpbl ,&
+
+ ! "inout" laketem arguments
+ ! ---------------------------
+ tlake ,scv_lake ,snowdp_lake ,t_lakesno ,&
+ wliq_lakesno ,wice_lakesno ,imelt_lake ,t_lake ,&
+ lake_icefrac ,savedtke1 ,&
+
+! SNICAR model variables
+ snofrz ,sabg_lyr ,&
+! END SNICAR model variables
+
+ ! "out" laketem arguments
+ ! ---------------------------
+ taux_lake ,tauy_lake ,fsena_lake ,&
+ fevpa_lake ,lfevpa_lake ,fseng_lake ,fevpg_lake ,&
+ qseva_lake ,qsubl_lake ,qsdew_lake ,qfros_lake ,&
+ olrg_lake ,fgrnd_lake ,tref_lake ,qref_lake ,&
+ trad_lake ,emis_lake ,z0m_lake ,zol_lake ,&
+ rib_lake ,ustar_lake ,qstar_lake ,tstar_lake ,&
+ fm_lake ,fh_lake ,fq_lake ,sm_lake ,&
+ urban_call=.true. )
+
+ lnet_lake = forc_frl - olrg_lake
+
+!=======================================================================
+! [7] Correct fluxes for temperature change
+!=======================================================================
+
+ ! calculate temperature change
+ dT(0) = troof - troof_bef
+ dT(1) = twsun - twsun_bef
+ dT(2) = twsha - twsha_bef
+ dT(3) = tgimp - tgimp_bef
+ dT(4) = tgper - tgper_bef
+ IF ( doveg ) dT(5) = 0.
+
+ ! flux change due to temperature change
+ fsenroof = fsenroof + dT(0)*croofs
+ fsenwsun = fsenwsun + dT(1)*cwsuns
+ fsenwsha = fsenwsha + dT(2)*cwshas
+ fsengimp = fsengimp + dT(3)*cgrnds
+ fsengper = fsengper + dT(4)*cgrnds
+
+ fevproof = fevproof + dT(0)*croofl
+ fevpgimp = fevpgimp + dT(3)*cgimpl
+ fevpgper = fevpgper + dT(4)*cgperl
+
+! calculation of evaporative potential; flux in kg m-2 s-1.
+! egidif holds the excess energy IF all water is evaporated
+! during the timestep. this energy is later added to the sensible heat flux.
+
+ ! --- for pervious ground ---
+ egsmax = (wice_gpersno(lbp)+wliq_gpersno(lbp)) / deltim
+ egidif = max( 0., fevpgper - egsmax )
+ fevpgper = min ( fevpgper, egsmax )
+ fsengper = fsengper + htvp_gper*egidif
+
+ ! --- for impervious ground ---
+ egsmax = (wice_gimpsno(lbi)+wliq_gimpsno(lbi)) / deltim
+ egidif = max( 0., fevpgimp - egsmax )
+ fevpgimp = min ( fevpgimp, egsmax )
+ fsengimp = fsengimp + htvp_gimp*egidif
+
+ ! --- for roof ---
+ egsmax = (wice_roofsno(lbr)+wliq_roofsno(lbr)) / deltim
+ egidif = max( 0., fevproof - egsmax )
+ fevproof = min ( fevproof, egsmax )
+ fsenroof = fsenroof + htvp_roof*egidif
+
+!=======================================================================
+! [8] total fluxes to atmosphere
+!=======================================================================
+
+ lnet = lroof *fcover(0) + lwsun *fcover(1) + lwsha *fcover(2) + &
+ lgimp *fcover(3) + lgper *fcover(4)
+
+ ! 03/30/2022, Wenzong Dong: bug find, sabgwsha->sabgwsun
+ sabg = sabroof *fcover(0) + sabwsun *fcover(1) + sabwsha *fcover(2) + &
+ sabgimp *fcover(3) + sabgper *fcover(4)
+
+ ! 03/30/2022, Wenzong Dong: bug find, fsenwsha->fsenwsun
+ fseng = fsenroof*fcover(0) + fsenwsun*fcover(1) + fsenwsha*fcover(2) + &
+ fsengimp*fcover(3) + fsengper*fcover(4)
+
+ fsen_roof = fsenroof*fcover(0)
+ fsen_wsun = fsenwsun*fcover(1)
+ fsen_wsha = fsenwsha*fcover(2)
+ fsen_gimp = fsengimp*fcover(3)
+ fsen_gper = fsengper*fcover(4)
+
+ fevpg = fevproof*fcover(0) + fevpgimp*fcover(3) + fevpgper*fcover(4)
+
+ lfevpa = htvp_roof*fevproof*fcover(0) + &
+ htvp_gimp*fevpgimp*fcover(3) + &
+ htvp_gper*fevpgper*fcover(4)
+
+ lfevp_roof = htvp_roof*fevproof*fcover(0)
+ lfevp_gimp = htvp_gimp*fevpgimp*fcover(3)
+ lfevp_gper = htvp_gper*fevpgper*fcover(4)
+
+ IF ( doveg ) THEN
+ assim = assim * fveg
+ respc = respc * fveg
+ fsenl = fsenl * fveg
+ fevpl = fevpl * fveg
+ etr = etr * fveg
+ fsena = fsenl + fseng
+ fevpa = fevpl + fevpg
+ lfevpa = lfevpa + hvap*fevpl
+
+ fsen_urbl = fsenl
+ lfevp_urbl = hvap*fevpl
+ etr_deficit = etr_deficit*fveg
+ ELSE
+ fsena = fseng
+ fevpa = fevpg
+ ENDIF
+
+ fsena = fsena + (Fhac + Fwst + vehc)*fsh + Fach + meta
+ lfevpa = lfevpa + (Fhac + Fwst + vehc)*flh
+
+ ! flux/variable average weighted by fractional cover
+ taux = taux *(1-flake) + taux_lake *flake
+ tauy = tauy *(1-flake) + tauy_lake *flake
+ sabg = sabg *(1-flake) + sablake *flake
+ lnet = lnet *(1-flake) + lnet_lake *flake
+ fseng = fseng *(1-flake) + fseng_lake *flake
+ fsena = fsena *(1-flake) + fsena_lake *flake
+ fevpg = fevpg *(1-flake) + fevpg_lake *flake
+ lfevpa = lfevpa *(1-flake) + lfevpa_lake *flake
+ tref = tref *(1-flake) + tref_lake *flake
+ qref = qref *(1-flake) + qref_lake *flake
+ z0m = z0m *(1-flake) + z0m_lake *flake
+ zol = zol *(1-flake) + zol_lake *flake
+ rib = rib *(1-flake) + rib_lake *flake
+ ustar = ustar *(1-flake) + ustar_lake *flake
+ qstar = qstar *(1-flake) + qstar_lake *flake
+ tstar = tstar *(1-flake) + tstar_lake *flake
+ fm = fm *(1-flake) + fm_lake *flake
+ fh = fh *(1-flake) + fh_lake *flake
+ fq = fq *(1-flake) + fq_lake *flake
+
+ ! 10/01/2021, yuan: exclude lake fevpa.
+ ! because we don't consider water balance for lake currently.
+ !fevpa = fevpa *(1-flake) + fevpa_lake *flake
+
+ ! 07/11/2023, yuan: don't not consider lake fraction cover
+ !fsenl = fsenl *(1-flake)
+ !fevpl = fevpl *(1-flake)
+ !etr = etr *(1-flake)
+ !assim = assim *(1-flake)
+ !respc = respc *(1-flake)
+
+ ! effective ground temperature, simple average
+ ! 12/01/2021, yuan: !TODO Bugs. temperature cannot be weighted like below.
+ !t_grnd = troof*fcover(0) + twsun*fcover(1) + twsha*fcover(2) + &
+ t_grnd = tgper*fgper + tgimp*(1-fgper)
+
+ !==============================================
+ qseva_roof = 0.
+ qsubl_roof = 0.
+ qfros_roof = 0.
+ qsdew_roof = 0.
+
+ IF (fevproof >= 0.)THEN
+! not allow for sublimation in melting (melting ==> evap. ==> sublimation)
+ qseva_roof = min(wliq_roofsno(lbr)/deltim, fevproof)
+ qsubl_roof = fevproof - qseva_roof
+ ELSE
+ IF (troof < tfrz)THEN
+ qfros_roof = abs(fevproof)
+ ELSE
+ qsdew_roof = abs(fevproof)
+ ENDIF
+ ENDIF
+
+ !==============================================
+ qseva_gimp = 0.
+ qsubl_gimp = 0.
+ qfros_gimp = 0.
+ qsdew_gimp = 0.
+
+ IF (fevpgimp >= 0.)THEN
+! not allow for sublimation in melting (melting ==> evap. ==> sublimation)
+ qseva_gimp = min(wliq_gimpsno(lbi)/deltim, fevpgimp)
+ qsubl_gimp = fevpgimp - qseva_gimp
+ ELSE
+ IF (tgimp < tfrz)THEN
+ qfros_gimp = abs(fevpgimp)
+ ELSE
+ qsdew_gimp = abs(fevpgimp)
+ ENDIF
+ ENDIF
+
+ !==============================================
+ qseva_gper = 0.
+ qsubl_gper = 0.
+ qfros_gper = 0.
+ qsdew_gper = 0.
+
+ IF (fevpgper >= 0.)THEN
+! not allow for sublimation in melting (melting ==> evap. ==> sublimation)
+ qseva_gper = min(wliq_gpersno(lbp)/deltim, fevpgper)
+ qsubl_gper = fevpgper - qseva_gper
+ ELSE
+ IF (tgper < tfrz)THEN
+ qfros_gper = abs(fevpgper)
+ ELSE
+ qsdew_gper = abs(fevpgper)
+ ENDIF
+ ENDIF
+
+!=======================================================================
+! [9] Calculate the change of long-wave radiation caused by temperature change
+!=======================================================================
+
+ dX = matmul(Ainv, dBdT*dT(1:))
+ dlwsun = ( ewall*dX(1) - dBdT(1)*dT(1) ) / (1-ewall)
+ dlwsha = ( ewall*dX(2) - dBdT(2)*dT(2) ) / (1-ewall)
+ dlgimp = ( egimp*dX(3) - dBdT(3)*dT(3) ) / (1-egimp)
+ dlgper = ( egper*dX(4) - dBdT(4)*dT(4) ) / (1-egper)
+
+ IF ( doveg ) THEN
+ dlveg = ( sum(dX(1:5)*VegVF(1:5))*ev )
+ ELSE
+ dlveg = 0.
+ ENDIF
+
+ dlout = sum( dX * SkyVF )
+
+ ! Energy balance check
+ eb = dlwsun + dlwsha + dlgimp + dlgper + dlveg + dlout
+
+ IF (abs(eb) > 1e-6) THEN
+ print *, "Urban Vegetation Longwave - Energy Balance Check error!", eb
+ ENDIF
+
+ ! for per unit surface
+ IF (fcover(1) > 0.) dlwsun = dlwsun / fcover(1) * fg !/ (4*fwsun*HL*fb/fg)
+ IF (fcover(2) > 0.) dlwsha = dlwsha / fcover(2) * fg !/ (4*fwsha*HL*fb/fg)
+ IF (fcover(3) > 0.) dlgimp = dlgimp / fcover(3) * fg !/ fgimp
+ IF (fcover(4) > 0.) dlgper = dlgper / fcover(4) * fg !/ fgper
+ IF ( doveg ) dlveg = dlveg / fcover(5) * fg !/ fv/fg
+
+ dlw = dlwsun*fcover(1) + dlwsha*fcover(2) + dlgimp*fcover(3) + dlgper*fcover(4)
+ IF ( doveg) dlw = dlw + dlveg*fcover(5)
+ dlw = dlw*(1-flake)
+
+ ! calculate out going longwave by added the before value
+ ! of lout and considered troof change
+ lout = lout + dlout
+ rout = (1-eroof)*forc_frl + eroof*stefnc*troof_bef**4 &
+ + 4.*eroof*stefnc*troof_bef**3*dT(0)
+
+ olrg = lout*fg + rout*froof
+ olrg = olrg*(1-flake) + olrg_lake*flake
+
+ IF (olrg < 0) THEN
+ write(6,*) 'Urban_THERMAL.F90: Urban out-going longwave radiation < 0!'
+ write(6,*) ipatch,olrg,lout,dlout,rout,olrg_lake,fg,froof,flake
+ CALL CoLM_stop()
+ ENDIF
+
+ ! radiative temperature
+ trad = (olrg/stefnc)**0.25
+
+! averaged bulk surface emissivity
+!TODO: how to calculate for urban case?
+! 03/10/2020, yuan: removed below.
+ !olrb = stefnc*t_soisno_bef(lb)**3*(4.*tinc)
+ !olrb = stefnc*t_grnd_bef**3*(4.*tinc)
+ !olru = ulrad + emg*olrb
+ !olrb = ulrad + olrb
+ !emis = olru / olrb
+
+
+!=======================================================================
+! [10] ground heat flux and energy balance error
+!=======================================================================
+
+ ! ground heat flux
+ fgrnd = sabg + lnet - dlwbef - dlout*fg*(1-flake) &
+ - 4.*eroof*stefnc*troof_bef**3*dT(0)*froof*(1-flake)&
+ - fseng - (lfevp_roof + lfevp_gimp + lfevp_gper)*(1-flake) &
+ - lfevpa_lake*flake
+
+ ! energy balance check
+ errore = sabg + sabv*fveg*(1-flake) &
+ + forc_frl - olrg &
+ + (Fhac + Fwst + Fach + vehc + meta)*(1-flake) &
+ - fsena - lfevpa - fgrnd &
+ - dheatl*fveg*(1-flake)
+
+ fgrnd = fgrnd - (Fhac + Fwst + Fach + vehc + meta)*(1-flake)
+
+#if (defined CoLMDEBUG)
+ IF (abs(errore)>.5) THEN
+ write(6,*) 'Urban_THERMAL.F90: Urban energy balance violation'
+ write(6,*) ipatch,errore,sabg,sabv*fveg*(1-flake)
+ write(6,*) forc_frl,dlwbef,dlw,olrg
+ write(6,*) Fhac,Fwst,Fach,vehc,meta,(1-flake)
+ write(6,*) fsena,lfevpa,fgrnd
+ write(6,*) dheatl*fveg*(1-flake)
+ CALL CoLM_stop()
+ ENDIF
+100 format(10(f15.3))
+#endif
+
+ ! diagnostic sabg only for pervious and impervious ground
+ !sabg = sabgper*fgper + sabgimp*(1-fgper)
+
+ ! SAVE for next time run
+ lwsun = dlwsun
+ lwsha = dlwsha
+ lgimp = dlgimp
+ lgper = dlgper
+ lveg = dlveg
+
+ ! deallocate memory
+ deallocate ( Ainv )
+ deallocate ( X )
+ deallocate ( dX )
+ deallocate ( B )
+ deallocate ( B1 )
+ deallocate ( dBdT )
+ deallocate ( SkyVF )
+ deallocate ( dT )
+
+ IF ( doveg ) THEN
+ deallocate ( VegVF )
+ ENDIF
+
+
+!=======================================================================
+! [11] Anthropogenic heat
+!=======================================================================
+
+ ! A simple Building energy model
+ CALL SimpleBEM ( deltim, forc_rhoair, fcover(0:2), hroof, troommax, troommin, &
+ troof_nl_bef, twsun_nl_bef, twsha_nl_bef, &
+ t_roofsno(nl_roof), t_wallsun(nl_wall), t_wallsha(nl_wall), &
+ tkdz_roof, tkdz_wsun, tkdz_wsha, tafu, troom, &
+ troof_inner, twsun_inner, twsha_inner, &
+ Fhac, Fwst, Fach, Fhah )
+
+ ! Anthropogenic heat flux for the rest (vehicle heat flux and metabolic heat flux)
+ CALL LUCY ( idate , deltim , patchlonr, fix_holiday, &
+ week_holiday, hum_prof, wdh_prof , weh_prof ,pop_den, &
+ vehicle , Fahe , vehc , meta )
+
+ fgrnd = fgrnd + (Fhac + Fwst + Fach)*(1-flake) + vehc + meta
+
+
+ ! convert BEM AHE to grid area values
+ ! NOTE: BEM AHE are assumed only affecting the urban area,
+ ! but vehc and meta area for the whole grid.
+ Fhac = Fhac * (1-flake)
+ Fwst = Fwst * (1-flake)
+ Fach = Fach * (1-flake)
+ Fhah = Fhah * (1-flake)
+
+
+ deallocate ( fcover )
+
+ END SUBROUTINE UrbanTHERMAL
+
+END MODULE MOD_Urban_Thermal
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_1DFluxes.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_1DFluxes.F90
new file mode 100644
index 0000000000..3e20a7c3c4
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_1DFluxes.F90
@@ -0,0 +1,155 @@
+#include
+
+#if (defined URBAN_MODEL)
+MODULE MOD_Urban_Vars_1DFluxes
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Define urban model 1D flux variables.
+!
+! Created by Hua Yuan, 12/2020
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+!-----------------------------------------------------------------------
+! Fluxes
+!-----------------------------------------------------------------------
+ !real(r8), allocatable :: sabroof (:) !solar absorption of roof [W/m2]
+ !real(r8), allocatable :: sabwsun (:) !solar absorption of sunlit wall [W/m2]
+ !real(r8), allocatable :: sabwsha (:) !solar absorption of shaded wall [W/m2]
+ !real(r8), allocatable :: sabgimp (:) !solar absorption of impervious [W/m2]
+ !real(r8), allocatable :: sabgper (:) !solar absorption of pervious [W/m2]
+
+ real(r8), allocatable :: fsen_roof (:) !sensible heat flux from roof [W/m2]
+ real(r8), allocatable :: fsen_wsun (:) !sensible heat flux from sunlit wall [W/m2]
+ real(r8), allocatable :: fsen_wsha (:) !sensible heat flux from shaded wall [W/m2]
+ real(r8), allocatable :: fsen_gimp (:) !sensible heat flux from impervious road [W/m2]
+ real(r8), allocatable :: fsen_gper (:) !sensible heat flux from pervious road [W/m2]
+ real(r8), allocatable :: fsen_urbl (:) !sensible heat flux from urban vegetation [W/m2]
+
+ real(r8), allocatable :: lfevp_roof (:) !latent heat flux from roof [W/m2]
+ real(r8), allocatable :: lfevp_gimp (:) !latent heat flux from impervious road [W/m2]
+ real(r8), allocatable :: lfevp_gper (:) !latent heat flux from pervious road [W/m2]
+ real(r8), allocatable :: lfevp_urbl (:) !latent heat flux from urban vegetation [W/m2]
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_1D_UrbanFluxes
+ PUBLIC :: deallocate_1D_UrbanFluxes
+ PUBLIC :: set_1D_UrbanFluxes
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_1D_UrbanFluxes
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CLM 1d [numurban] variables
+ ! --------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+ !allocate (sabroof (numurban))
+ !allocate (sabwsun (numurban))
+ !allocate (sabwsha (numurban))
+ !allocate (sabgimp (numurban))
+ !allocate (sabgper (numurban))
+ allocate (fsen_roof (numurban)) ; fsen_roof (:) = spval
+ allocate (fsen_wsun (numurban)) ; fsen_wsun (:) = spval
+ allocate (fsen_wsha (numurban)) ; fsen_wsha (:) = spval
+ allocate (fsen_gimp (numurban)) ; fsen_gimp (:) = spval
+ allocate (fsen_gper (numurban)) ; fsen_gper (:) = spval
+ allocate (fsen_urbl (numurban)) ; fsen_urbl (:) = spval
+
+ allocate (lfevp_roof (numurban)) ; lfevp_roof (:) = spval
+ allocate (lfevp_gimp (numurban)) ; lfevp_gimp (:) = spval
+ allocate (lfevp_gper (numurban)) ; lfevp_gper (:) = spval
+ allocate (lfevp_urbl (numurban)) ; lfevp_urbl (:) = spval
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE allocate_1D_UrbanFluxes
+
+ SUBROUTINE deallocate_1D_UrbanFluxes
+ ! --------------------------------------------------------------------
+ ! deallocates memory for CLM 1d [numurban] variables
+ ! --------------------------------------------------------------------
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+
+ !deallocate (sabroof )
+ !deallocate (sabwsun )
+ !deallocate (sabwsha )
+ !deallocate (sabgimp )
+ !deallocate (sabgper )
+ deallocate (fsen_roof )
+ deallocate (fsen_wsun )
+ deallocate (fsen_wsha )
+ deallocate (fsen_gimp )
+ deallocate (fsen_gper )
+ deallocate (fsen_urbl )
+
+ deallocate (lfevp_roof )
+ deallocate (lfevp_gimp )
+ deallocate (lfevp_gper )
+ deallocate (lfevp_urbl )
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_1D_UrbanFluxes
+
+ SUBROUTINE set_1D_UrbanFluxes(Values, Nan)
+ ! --------------------------------------------------------------------
+ ! Allocates memory for CLM 1d [numurban] variables
+ ! --------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+ IMPLICIT NONE
+ real(r8),intent(in) :: Values
+ real(r8),intent(in) :: Nan
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+ !sabroof (:) = Values
+ !sabwsun (:) = Values
+ !sabwsha (:) = Values
+ !sabgimp (:) = Values
+ !sabgper (:) = Values
+ fsen_roof (:) = Values
+ fsen_wsun (:) = Values
+ fsen_wsha (:) = Values
+ fsen_gimp (:) = Values
+ fsen_gper (:) = Values
+ fsen_urbl (:) = Values
+
+ lfevp_roof (:) = Values
+ lfevp_gimp (:) = Values
+ lfevp_gper (:) = Values
+ lfevp_urbl (:) = Values
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE set_1D_UrbanFluxes
+
+END MODULE MOD_Urban_Vars_1DFluxes
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_TimeInvariants.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_TimeInvariants.F90
new file mode 100644
index 0000000000..bded9f3f79
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_TimeInvariants.F90
@@ -0,0 +1,340 @@
+#include
+
+#ifdef URBAN_MODEL
+MODULE MOD_Urban_Vars_TimeInvariants
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Define urban model time invariant variables.
+!
+! Created by Hua Yuan, 12/2020
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ !integer , allocatable :: urbclass (:) !urban type
+ !integer , allocatable :: patch2urb (:) !projection from patch to Urban
+ !integer , allocatable :: urb2patch (:) !projection from Urban to patch
+
+ real(r8), allocatable :: pop_den (:) !pop density
+ real(r8), allocatable :: vehicle (:,:) !vehicle numbers per thousand people
+ real(r8), allocatable :: week_holiday(:,:) !week holidays
+ real(r8), allocatable :: weh_prof (:,:) !Diurnal traffic flow profile of weekend
+ real(r8), allocatable :: wdh_prof (:,:) !Diurnal traffic flow profile of weekday
+ real(r8), allocatable :: hum_prof (:,:) !Diurnal metabolic heat profile
+ real(r8), allocatable :: fix_holiday (:,:) !Fixed public holidays, holiday (0) or workday(1)
+
+ ! Vegetations
+ real(r8), allocatable :: fveg_urb (:) !tree coverage of urban patch [-]
+ real(r8), allocatable :: htop_urb (:) !tree crown top height of urban patch [m]
+ real(r8), allocatable :: hbot_urb (:) !tree crown bottom height of urban patch [m]
+
+ ! Urban morphology
+ real(r8), allocatable :: froof (:) !roof fractional cover [-]
+ real(r8), allocatable :: fgper (:) !impervious fraction to ground area [-]
+ real(r8), allocatable :: flake (:) !lake fraction to ground area [-]
+ real(r8), allocatable :: hroof (:) !average building height [m]
+ real(r8), allocatable :: hlr (:) !average building height to their side length [-]
+
+ real(r8), allocatable :: z_roof (:,:) !depth of each roof layer [m]
+ real(r8), allocatable :: z_wall (:,:) !depth of each wall layer [m]
+ real(r8), allocatable :: dz_roof (:,:) !thickness of each roof layer [m]
+ real(r8), allocatable :: dz_wall (:,:) !thickness of each wall layer [m]
+
+ ! albedo
+ real(r8), allocatable :: alb_roof (:,:,:) !albedo of roof [-]
+ real(r8), allocatable :: alb_wall (:,:,:) !albedo of walls [-]
+ real(r8), allocatable :: alb_gimp (:,:,:) !albedo of impervious [-]
+ real(r8), allocatable :: alb_gper (:,:,:) !albedo of pervious [-]
+
+ ! emissivity
+ real(r8), allocatable :: em_roof (:) !emissivity of roof [-]
+ real(r8), allocatable :: em_wall (:) !emissivity of walls [-]
+ real(r8), allocatable :: em_gimp (:) !emissivity of impervious [-]
+ real(r8), allocatable :: em_gper (:) !emissivity of pervious [-]
+
+ ! thermal pars of roof, wall, impervious
+ real(r8), allocatable :: cv_roof (:,:) !heat capacity of roof [J/(m2 K)]
+ real(r8), allocatable :: cv_wall (:,:) !heat capacity of wall [J/(m2 K)]
+ real(r8), allocatable :: cv_gimp (:,:) !heat capacity of impervious [J/(m2 K)]
+
+ real(r8), allocatable :: tk_roof (:,:) !thermal conductivity of roof [W/m-K]
+ real(r8), allocatable :: tk_wall (:,:) !thermal conductivity of wall [W/m-K]
+ real(r8), allocatable :: tk_gimp (:,:) !thermal conductivity of impervious [W/m-K]
+
+ ! room maximum and minimum temperature
+ real(r8), allocatable :: t_roommax (:) !maximum temperature of inner room [K]
+ real(r8), allocatable :: t_roommin (:) !minimum temperature of inner room [K]
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_UrbanTimeInvariants
+ PUBLIC :: deallocate_UrbanTimeInvariants
+ PUBLIC :: READ_UrbanTimeInvariants
+ PUBLIC :: WRITE_UrbanTimeInvariants
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_UrbanTimeInvariants ()
+! ------------------------------------------------------
+! Allocates memory for CLM 1d [numurban] variants
+! ------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+ allocate (fveg_urb (numurban))
+ allocate (htop_urb (numurban))
+ allocate (hbot_urb (numurban))
+ allocate (froof (numurban))
+ allocate (fgper (numurban))
+ allocate (flake (numurban))
+ allocate (hroof (numurban))
+ allocate (hlr (numurban))
+
+ allocate (alb_roof (2,2,numurban))
+ allocate (alb_wall (2,2,numurban))
+ allocate (alb_gimp (2,2,numurban))
+ allocate (alb_gper (2,2,numurban))
+
+ allocate (em_roof (numurban))
+ allocate (em_wall (numurban))
+ allocate (em_gimp (numurban))
+ allocate (em_gper (numurban))
+
+ allocate (z_roof (1:nl_roof,numurban))
+ allocate (z_wall (1:nl_wall,numurban))
+ allocate (dz_roof (1:nl_roof,numurban))
+ allocate (dz_wall (1:nl_wall,numurban))
+
+ allocate (cv_roof (1:nl_roof,numurban))
+ allocate (cv_wall (1:nl_wall,numurban))
+ allocate (cv_gimp (1:nl_soil,numurban))
+ allocate (tk_roof (1:nl_roof,numurban))
+ allocate (tk_wall (1:nl_wall,numurban))
+ allocate (tk_gimp (1:nl_soil,numurban))
+
+ allocate (t_roommax (numurban))
+ allocate (t_roommin (numurban))
+ allocate (pop_den (numurban))
+
+ allocate (vehicle (3 ,numurban))
+ allocate (week_holiday (7 ,numurban))
+ allocate (weh_prof (24 ,numurban))
+ allocate (wdh_prof (24 ,numurban))
+ allocate (hum_prof (24 ,numurban))
+ allocate (fix_holiday (365,numurban))
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE allocate_UrbanTimeInvariants
+
+ SUBROUTINE READ_UrbanTimeInvariants (file_restart)
+
+ USE MOD_NetCDFVector
+ USE MOD_LandUrban
+
+ IMPLICIT NONE
+
+ integer, parameter :: ns = 2
+ integer, parameter :: nr = 2
+ integer, parameter :: ulev = 10
+ character(len=*), intent(in) :: file_restart
+
+ ! vegetation
+ CALL ncio_read_vector (file_restart, 'PCT_Tree' , landurban, fveg_urb )
+ CALL ncio_read_vector (file_restart, 'URBAN_TREE_TOP', landurban, htop_urb )
+ CALL ncio_read_vector (file_restart, 'URBAN_TREE_BOT', landurban, hbot_urb )
+ CALL ncio_read_vector (file_restart, 'PCT_Water' , landurban, flake )
+
+ ! LUCY paras !TODO: variable name can be optimized
+ CALL ncio_read_vector (file_restart, 'POP_DEN' , landurban, pop_den )
+ CALL ncio_read_vector (file_restart, 'VEHC_NUM' , 3 , landurban, vehicle )
+ CALL ncio_read_vector (file_restart, 'week_holiday', 7 , landurban, week_holiday )
+ CALL ncio_read_vector (file_restart, 'weekendhour' , 24 , landurban, weh_prof )
+ CALL ncio_read_vector (file_restart, 'weekdayhour' , 24 , landurban, wdh_prof )
+ CALL ncio_read_vector (file_restart, 'metabolism' , 24 , landurban, hum_prof )
+ CALL ncio_read_vector (file_restart, 'holiday' , 365, landurban, fix_holiday )
+
+ ! morphological paras
+ CALL ncio_read_vector (file_restart, 'WT_ROOF' , landurban, froof )
+ CALL ncio_read_vector (file_restart, 'HT_ROOF' , landurban, hroof )
+ CALL ncio_read_vector (file_restart, 'BUILDING_HLR' , landurban, hlr )
+ CALL ncio_read_vector (file_restart, 'WTROAD_PERV' , landurban, fgper )
+ CALL ncio_read_vector (file_restart, 'EM_ROOF' , landurban, em_roof )
+ CALL ncio_read_vector (file_restart, 'EM_WALL' , landurban, em_wall )
+ CALL ncio_read_vector (file_restart, 'EM_IMPROAD' , landurban, em_gimp )
+ CALL ncio_read_vector (file_restart, 'EM_PERROAD' , landurban, em_gper )
+ CALL ncio_read_vector (file_restart, 'T_BUILDING_MIN', landurban, t_roommin )
+ CALL ncio_read_vector (file_restart, 'T_BUILDING_MAX', landurban, t_roommax )
+
+ CALL ncio_read_vector (file_restart, 'ROOF_DEPTH_L' , ulev, landurban, z_roof )
+ CALL ncio_read_vector (file_restart, 'ROOF_THICK_L' , ulev, landurban, dz_roof )
+ CALL ncio_read_vector (file_restart, 'WALL_DEPTH_L' , ulev, landurban, z_wall )
+ CALL ncio_read_vector (file_restart, 'WALL_THICK_L' , ulev, landurban, dz_wall )
+
+ ! thermal paras
+ CALL ncio_read_vector (file_restart, 'CV_ROOF' , ulev, landurban, cv_roof )
+ CALL ncio_read_vector (file_restart, 'CV_WALL' , ulev, landurban, cv_wall )
+ CALL ncio_read_vector (file_restart, 'TK_ROOF' , ulev, landurban, tk_roof )
+ CALL ncio_read_vector (file_restart, 'TK_WALL' , ulev, landurban, tk_wall )
+ CALL ncio_read_vector (file_restart, 'TK_IMPROAD', ulev, landurban, tk_gimp )
+ CALL ncio_read_vector (file_restart, 'CV_IMPROAD', ulev, landurban, cv_gimp )
+
+ CALL ncio_read_vector (file_restart, 'ALB_ROOF' , ns, nr, landurban, alb_roof )
+ CALL ncio_read_vector (file_restart, 'ALB_WALL' , ns, nr, landurban, alb_wall )
+ CALL ncio_read_vector (file_restart, 'ALB_IMPROAD', ns, nr, landurban, alb_gimp )
+ CALL ncio_read_vector (file_restart, 'ALB_PERROAD', ns, nr, landurban, alb_gper )
+
+ END SUBROUTINE READ_UrbanTimeInvariants
+
+ SUBROUTINE WRITE_UrbanTimeInvariants (file_restart)
+
+ USE MOD_NetCDFVector
+ USE MOD_LandUrban
+ USE MOD_Namelist
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ integer, parameter :: ns = 2
+ integer, parameter :: nr = 2
+ integer, parameter :: ulev = 10
+ integer, parameter :: ityp = 3
+ integer, parameter :: ihour = 24
+ integer, parameter :: iweek = 7
+ integer, parameter :: iday = 365
+ ! Local variables
+ character(len=*), intent(in) :: file_restart
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ CALL ncio_create_file_vector (file_restart, landurban)
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'urban')
+
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'urban')
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'numsolar', nr )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'numrad' , ns )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'ulev' , ulev)
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'ityp' , 3 )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'iweek' , 7 )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'ihour' , 24 )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'iday' , 365 )
+
+ ! vegetation
+ CALL ncio_write_vector (file_restart, 'PCT_Tree' , 'urban', landurban, fveg_urb, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'URBAN_TREE_TOP', 'urban', landurban, htop_urb, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'URBAN_TREE_BOT', 'urban', landurban, hbot_urb, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'PCT_Water' , 'urban', landurban, flake , DEF_REST_CompressLevel)
+
+ ! LUCY paras
+ CALL ncio_write_vector (file_restart, 'POP_DEN' , 'urban', landurban, pop_den , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'VEHC_NUM' , 'ityp' , ityp , 'urban', landurban, vehicle , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'week_holiday', 'iweek', iweek, 'urban', landurban, week_holiday, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'weekendhour' , 'ihour', ihour, 'urban', landurban, weh_prof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'weekdayhour' , 'ihour', ihour, 'urban', landurban, wdh_prof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'metabolism' , 'ihour', ihour, 'urban', landurban, hum_prof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'holiday' , 'iday' , iday , 'urban', landurban, fix_holiday , DEF_REST_CompressLevel)
+
+ ! morphological paras
+ CALL ncio_write_vector (file_restart, 'WT_ROOF' , 'urban', landurban, froof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'HT_ROOF' , 'urban', landurban, hroof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'BUILDING_HLR' , 'urban', landurban, hlr , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'WTROAD_PERV' , 'urban', landurban, fgper , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'EM_ROOF' , 'urban', landurban, em_roof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'EM_WALL' , 'urban', landurban, em_wall , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'EM_IMPROAD' , 'urban', landurban, em_gimp , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'EM_PERROAD' , 'urban', landurban, em_gper , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'T_BUILDING_MIN', 'urban', landurban, t_roommin, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'T_BUILDING_MAX', 'urban', landurban, t_roommax, DEF_REST_CompressLevel)
+
+ CALL ncio_write_vector (file_restart, 'ROOF_DEPTH_L', 'ulev', ulev, 'urban', landurban, z_roof , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'ROOF_THICK_L', 'ulev', ulev, 'urban', landurban, dz_roof, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'WALL_DEPTH_L', 'ulev', ulev, 'urban', landurban, z_wall , DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'WALL_THICK_L', 'ulev', ulev, 'urban', landurban, dz_wall, DEF_REST_CompressLevel)
+
+ ! thermal paras
+ CALL ncio_write_vector (file_restart, 'CV_ROOF' , 'ulev', ulev, 'urban', landurban, cv_roof, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'CV_WALL' , 'ulev', ulev, 'urban', landurban, cv_wall, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'TK_ROOF' , 'ulev', ulev, 'urban', landurban, tk_roof, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'TK_WALL' , 'ulev', ulev, 'urban', landurban, tk_wall, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'TK_IMPROAD', 'ulev', ulev, 'urban', landurban, tk_gimp, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'CV_IMPROAD', 'ulev', ulev, 'urban', landurban, cv_gimp, DEF_REST_CompressLevel)
+
+ CALL ncio_write_vector (file_restart, 'ALB_ROOF' , 'numsolar', ns, 'numrad', nr, 'urban', landurban, alb_roof, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'ALB_WALL' , 'numsolar', ns, 'numrad', nr, 'urban', landurban, alb_wall, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'ALB_IMPROAD', 'numsolar', ns, 'numrad', nr, 'urban', landurban, alb_gimp, DEF_REST_CompressLevel)
+ CALL ncio_write_vector (file_restart, 'ALB_PERROAD', 'numsolar', ns, 'numrad', nr, 'urban', landurban, alb_gper, DEF_REST_CompressLevel)
+
+ END SUBROUTINE WRITE_UrbanTimeInvariants
+
+ SUBROUTINE deallocate_UrbanTimeInvariants
+
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+
+ ! deallocate (urbclass )
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+ deallocate (fveg_urb )
+ deallocate (htop_urb )
+ deallocate (hbot_urb )
+ deallocate (froof )
+ deallocate (fgper )
+ deallocate (flake )
+ deallocate (hroof )
+ deallocate (hlr )
+
+ deallocate (alb_roof )
+ deallocate (alb_wall )
+ deallocate (alb_gimp )
+ deallocate (alb_gper )
+
+ deallocate (em_roof )
+ deallocate (em_wall )
+ deallocate (em_gimp )
+ deallocate (em_gper )
+
+ deallocate (z_roof )
+ deallocate (z_wall )
+ deallocate (dz_roof )
+ deallocate (dz_wall )
+
+ deallocate (cv_roof )
+ deallocate (cv_wall )
+ deallocate (cv_gimp )
+ deallocate (tk_roof )
+ deallocate (tk_wall )
+ deallocate (tk_gimp )
+
+ deallocate (t_roommax )
+ deallocate (t_roommin )
+
+ deallocate (pop_den )
+ deallocate (vehicle )
+ deallocate (week_holiday )
+ deallocate (weh_prof )
+ deallocate (wdh_prof )
+ deallocate (hum_prof )
+ deallocate (fix_holiday )
+ ENDIF
+ ENDIF
+ END SUBROUTINE deallocate_UrbanTimeInvariants
+
+END MODULE MOD_Urban_Vars_TimeInvariants
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_TimeVariables.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_TimeVariables.F90
new file mode 100644
index 0000000000..31234bb8c5
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_Vars_TimeVariables.F90
@@ -0,0 +1,506 @@
+#include
+
+#if (defined URBAN_MODEL)
+MODULE MOD_Urban_Vars_TimeVariables
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Define urban model time variant variables.
+!
+! Created by Hua Yuan, 12/2020
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+! -----------------------------------------------------------------
+! Time-varying state variables which required by restart run
+
+ real(r8), allocatable :: fwsun (:) !sunlit fraction of walls [-]
+ real(r8), allocatable :: dfwsun (:) !change of sunlit fraction of walls [-]
+
+ ! shortwave absorption
+ real(r8), allocatable :: sroof (:,:,:) !roof absorption [-]
+ real(r8), allocatable :: swsun (:,:,:) !sunlit wall absorption [-]
+ real(r8), allocatable :: swsha (:,:,:) !shaded wall absorption [-]
+ real(r8), allocatable :: sgimp (:,:,:) !impervious absorption [-]
+ real(r8), allocatable :: sgper (:,:,:) !pervious absorption [-]
+ real(r8), allocatable :: slake (:,:,:) !urban lake absorption [-]
+
+ ! net longwave radiation for last time temperature change
+ real(r8), allocatable :: lwsun (:) !net longwave of sunlit wall [W/m2]
+ real(r8), allocatable :: lwsha (:) !net longwave of shaded wall [W/m2]
+ real(r8), allocatable :: lgimp (:) !net longwave of impervious [W/m2]
+ real(r8), allocatable :: lgper (:) !net longwave of pervious [W/m2]
+ real(r8), allocatable :: lveg (:) !net longwave of vegetation [W/m2]
+
+ real(r8), allocatable :: z_sno_roof (:,:) !node depth of roof [m]
+ real(r8), allocatable :: z_sno_gimp (:,:) !node depth of impervious [m]
+ real(r8), allocatable :: z_sno_gper (:,:) !node depth pervious [m]
+ real(r8), allocatable :: z_sno_lake (:,:) !node depth lake [m]
+
+ real(r8), allocatable :: dz_sno_roof (:,:) !interface depth of roof [m]
+ real(r8), allocatable :: dz_sno_gimp (:,:) !interface depth of impervious [m]
+ real(r8), allocatable :: dz_sno_gper (:,:) !interface depth pervious [m]
+ real(r8), allocatable :: dz_sno_lake (:,:) !interface depth lake [m]
+
+ real(r8), allocatable :: troof_inner (:) !temperature of roof [K]
+ real(r8), allocatable :: twsun_inner (:) !temperature of sunlit wall [K]
+ real(r8), allocatable :: twsha_inner (:) !temperature of shaded wall [K]
+
+ real(r8), allocatable :: t_roofsno (:,:) !temperature of roof [K]
+ real(r8), allocatable :: t_wallsun (:,:) !temperature of sunlit wall [K]
+ real(r8), allocatable :: t_wallsha (:,:) !temperature of shaded wall [K]
+ real(r8), allocatable :: t_gimpsno (:,:) !temperature of impervious [K]
+ real(r8), allocatable :: t_gpersno (:,:) !temperature of pervious [K]
+ real(r8), allocatable :: t_lakesno (:,:) !temperature of pervious [K]
+
+ real(r8), allocatable :: wliq_roofsno (:,:) !liquid water in layers [kg/m2]
+ real(r8), allocatable :: wliq_gimpsno (:,:) !liquid water in layers [kg/m2]
+ real(r8), allocatable :: wliq_gpersno (:,:) !liquid water in layers [kg/m2]
+ real(r8), allocatable :: wliq_lakesno (:,:) !liquid water in layers [kg/m2]
+ real(r8), allocatable :: wice_roofsno (:,:) !ice lens in layers [kg/m2]
+ real(r8), allocatable :: wice_gimpsno (:,:) !ice lens in layers [kg/m2]
+ real(r8), allocatable :: wice_gpersno (:,:) !ice lens in layers [kg/m2]
+ real(r8), allocatable :: wice_lakesno (:,:) !ice lens in layers [kg/m2]
+
+ real(r8), allocatable :: sag_roof (:) !roof snow age [-]
+ real(r8), allocatable :: sag_gimp (:) !impervious ground snow age [-]
+ real(r8), allocatable :: sag_gper (:) !pervious ground snow age [-]
+ real(r8), allocatable :: sag_lake (:) !urban lake snow age [-]
+
+ real(r8), allocatable :: scv_roof (:) !roof snow mass [kg/m2]
+ real(r8), allocatable :: scv_gimp (:) !impervious ground snow mass [kg/m2]
+ real(r8), allocatable :: scv_gper (:) !pervious ground snow mass [kg/m2]
+ real(r8), allocatable :: scv_lake (:) !urban lake snow mass [kg/m2]
+
+ real(r8), allocatable :: fsno_roof (:) !roof snow fraction [-]
+ real(r8), allocatable :: fsno_gimp (:) !impervious ground snow fraction [-]
+ real(r8), allocatable :: fsno_gper (:) !pervious ground snow fraction [-]
+ real(r8), allocatable :: fsno_lake (:) !urban lake snow fraction [-]
+
+ real(r8), allocatable :: snowdp_roof (:) !roof snow depth [m]
+ real(r8), allocatable :: snowdp_gimp (:) !impervious ground snow depth [m]
+ real(r8), allocatable :: snowdp_gper (:) !pervious ground snow depth [m]
+ real(r8), allocatable :: snowdp_lake (:) !urban lake snow depth [m]
+
+ !TODO: rename the below variables
+ real(r8), allocatable :: Fhac (:) !sensible flux from heat or cool AC [W/m2]
+ real(r8), allocatable :: Fwst (:) !waste heat flux from heat or cool AC [W/m2]
+ real(r8), allocatable :: Fach (:) !flux from inner and outer air exchange [W/m2]
+ real(r8), allocatable :: Fahe (:) !flux from metabolism and vehicle [W/m2]
+ real(r8), allocatable :: Fhah (:) !sensible heat flux from heating [W/m2]
+ real(r8), allocatable :: vehc (:) !flux from vehicle [W/m2]
+ real(r8), allocatable :: meta (:) !flux from metabolism [W/m2]
+
+ real(r8), allocatable :: t_room (:) !temperature of inner building [K]
+ real(r8), allocatable :: t_roof (:) !temperature of roof [K]
+ real(r8), allocatable :: t_wall (:) !temperature of wall [K]
+ real(r8), allocatable :: tafu (:) !temperature of outer building [K]
+
+ real(r8), allocatable :: urb_green (:) !fractional of green leaf in urban patch [-]
+ real(r8), allocatable :: urb_lai (:) !urban tree LAI [m2/m2]
+ real(r8), allocatable :: urb_sai (:) !urban tree SAI [m2/m2]
+
+
+! PUBLIC MEMBER FUNCTIONS:
+ PUBLIC :: allocate_UrbanTimeVariables
+ PUBLIC :: deallocate_UrbanTimeVariables
+ PUBLIC :: READ_UrbanTimeVariables
+ PUBLIC :: WRITE_UrbanTimeVariables
+
+! PRIVATE MEMBER FUNCTIONS:
+
+!-----------------------------------------------------------------------
+
+CONTAINS
+
+!-----------------------------------------------------------------------
+
+ SUBROUTINE allocate_UrbanTimeVariables ()
+! ------------------------------------------------------
+! Allocates memory for CLM 1d [numurban] variables
+! ------------------------------------------------------
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+ allocate (fwsun (numurban))
+ allocate (dfwsun (numurban))
+
+ allocate (sroof (2,2,numurban))
+ allocate (swsun (2,2,numurban))
+ allocate (swsha (2,2,numurban))
+ allocate (sgimp (2,2,numurban))
+ allocate (sgper (2,2,numurban))
+ allocate (slake (2,2,numurban))
+
+ allocate (lwsun (numurban))
+ allocate (lwsha (numurban))
+ allocate (lgimp (numurban))
+ allocate (lgper (numurban))
+ allocate (lveg (numurban))
+
+ allocate (z_sno_roof (maxsnl+1:0,numurban))
+ allocate (z_sno_gimp (maxsnl+1:0,numurban))
+ allocate (z_sno_gper (maxsnl+1:0,numurban))
+ allocate (z_sno_lake (maxsnl+1:0,numurban))
+
+ allocate (dz_sno_roof (maxsnl+1:0,numurban))
+ allocate (dz_sno_gimp (maxsnl+1:0,numurban))
+ allocate (dz_sno_gper (maxsnl+1:0,numurban))
+ allocate (dz_sno_lake (maxsnl+1:0,numurban))
+
+ allocate (troof_inner (numurban))
+ allocate (twsun_inner (numurban))
+ allocate (twsha_inner (numurban))
+
+ allocate (t_roofsno (maxsnl+1:nl_roof,numurban))
+ allocate (t_wallsun (maxsnl+1:nl_wall,numurban))
+ allocate (t_wallsha (maxsnl+1:nl_wall,numurban))
+ allocate (t_gimpsno (maxsnl+1:nl_soil,numurban))
+ allocate (t_gpersno (maxsnl+1:nl_soil,numurban))
+ allocate (t_lakesno (maxsnl+1:nl_soil,numurban))
+
+ allocate (wliq_roofsno (maxsnl+1:nl_roof,numurban))
+ allocate (wice_roofsno (maxsnl+1:nl_roof,numurban))
+ allocate (wliq_gimpsno (maxsnl+1:nl_soil,numurban))
+ allocate (wice_gimpsno (maxsnl+1:nl_soil,numurban))
+ allocate (wliq_gpersno (maxsnl+1:nl_soil,numurban))
+ allocate (wice_gpersno (maxsnl+1:nl_soil,numurban))
+ allocate (wliq_lakesno (maxsnl+1:nl_soil,numurban))
+ allocate (wice_lakesno (maxsnl+1:nl_soil,numurban))
+
+ allocate (sag_roof (numurban))
+ allocate (sag_gimp (numurban))
+ allocate (sag_gper (numurban))
+ allocate (sag_lake (numurban))
+ allocate (scv_roof (numurban))
+ allocate (scv_gimp (numurban))
+ allocate (scv_gper (numurban))
+ allocate (scv_lake (numurban))
+ allocate (fsno_roof (numurban))
+ allocate (fsno_gimp (numurban))
+ allocate (fsno_gper (numurban))
+ allocate (fsno_lake (numurban))
+ allocate (snowdp_roof (numurban))
+ allocate (snowdp_gimp (numurban))
+ allocate (snowdp_gper (numurban))
+ allocate (snowdp_lake (numurban))
+
+ allocate (Fhac (numurban))
+ allocate (Fwst (numurban))
+ allocate (Fach (numurban))
+ allocate (Fahe (numurban))
+ allocate (Fhah (numurban))
+ allocate (vehc (numurban))
+ allocate (meta (numurban))
+
+ allocate (t_room (numurban))
+ allocate (t_roof (numurban))
+ allocate (t_wall (numurban))
+ allocate (tafu (numurban))
+
+ allocate (urb_green (numurban))
+ allocate (urb_lai (numurban))
+ allocate (urb_sai (numurban))
+ ENDIF
+ ENDIF
+ END SUBROUTINE allocate_UrbanTimeVariables
+
+ SUBROUTINE READ_UrbanTimeVariables (file_restart)
+
+ USE MOD_NetCDFVector
+ USE MOD_LandUrban
+ USE MOD_Vars_Global
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ CALL ncio_read_vector (file_restart, 'fwsun' , landurban, fwsun )
+ CALL ncio_read_vector (file_restart, 'dfwsun', landurban, dfwsun)
+
+ CALL ncio_read_vector (file_restart, 'sroof', 2, 2, landurban, sroof)
+ CALL ncio_read_vector (file_restart, 'swsun', 2, 2, landurban, swsun)
+ CALL ncio_read_vector (file_restart, 'swsha', 2, 2, landurban, swsha)
+ CALL ncio_read_vector (file_restart, 'sgimp', 2, 2, landurban, sgimp)
+ CALL ncio_read_vector (file_restart, 'sgper', 2, 2, landurban, sgper)
+ CALL ncio_read_vector (file_restart, 'slake', 2, 2, landurban, slake)
+
+ CALL ncio_read_vector (file_restart, 'lwsun', landurban, lwsun)
+ CALL ncio_read_vector (file_restart, 'lwsha', landurban, lwsha)
+ CALL ncio_read_vector (file_restart, 'lgimp', landurban, lgimp)
+ CALL ncio_read_vector (file_restart, 'lgper', landurban, lgper)
+ CALL ncio_read_vector (file_restart, 'lveg' , landurban, lveg )
+
+ CALL ncio_read_vector (file_restart, 'z_sno_roof' , -maxsnl, landurban, z_sno_roof )
+ CALL ncio_read_vector (file_restart, 'z_sno_gimp' , -maxsnl, landurban, z_sno_gimp )
+ CALL ncio_read_vector (file_restart, 'z_sno_gper' , -maxsnl, landurban, z_sno_gper )
+ CALL ncio_read_vector (file_restart, 'z_sno_lake' , -maxsnl, landurban, z_sno_lake )
+
+ CALL ncio_read_vector (file_restart, 'dz_sno_roof', -maxsnl, landurban, dz_sno_roof)
+ CALL ncio_read_vector (file_restart, 'dz_sno_gimp', -maxsnl, landurban, dz_sno_gimp)
+ CALL ncio_read_vector (file_restart, 'dz_sno_gper', -maxsnl, landurban, dz_sno_gper)
+ CALL ncio_read_vector (file_restart, 'dz_sno_lake', -maxsnl, landurban, dz_sno_lake)
+
+ CALL ncio_read_vector (file_restart, 'troof_inner', landurban, troof_inner)
+ CALL ncio_read_vector (file_restart, 'twsun_inner', landurban, twsun_inner)
+ CALL ncio_read_vector (file_restart, 'twsha_inner', landurban, twsha_inner)
+
+ CALL ncio_read_vector (file_restart, 't_roofsno', nl_roof-maxsnl, landurban, t_roofsno)
+ CALL ncio_read_vector (file_restart, 't_wallsun', nl_wall-maxsnl, landurban, t_wallsun)
+ CALL ncio_read_vector (file_restart, 't_wallsha', nl_wall-maxsnl, landurban, t_wallsha)
+ CALL ncio_read_vector (file_restart, 't_gimpsno', nl_soil-maxsnl, landurban, t_gimpsno)
+ CALL ncio_read_vector (file_restart, 't_gpersno', nl_soil-maxsnl, landurban, t_gpersno)
+ CALL ncio_read_vector (file_restart, 't_lakesno', nl_soil-maxsnl, landurban, t_lakesno)
+
+ CALL ncio_read_vector (file_restart, 'wliq_roofsno', nl_roof-maxsnl, landurban, wliq_roofsno)
+ CALL ncio_read_vector (file_restart, 'wliq_gimpsno', nl_soil-maxsnl, landurban, wliq_gimpsno)
+ CALL ncio_read_vector (file_restart, 'wliq_gpersno', nl_soil-maxsnl, landurban, wliq_gpersno)
+ CALL ncio_read_vector (file_restart, 'wliq_lakesno', nl_soil-maxsnl, landurban, wliq_lakesno)
+ CALL ncio_read_vector (file_restart, 'wice_roofsno', nl_roof-maxsnl, landurban, wice_roofsno)
+ CALL ncio_read_vector (file_restart, 'wice_gimpsno', nl_soil-maxsnl, landurban, wice_gimpsno)
+ CALL ncio_read_vector (file_restart, 'wice_gpersno', nl_soil-maxsnl, landurban, wice_gpersno)
+ CALL ncio_read_vector (file_restart, 'wice_lakesno', nl_soil-maxsnl, landurban, wice_lakesno)
+
+ CALL ncio_read_vector (file_restart, 'sag_roof' , landurban, sag_roof )
+ CALL ncio_read_vector (file_restart, 'sag_gimp' , landurban, sag_gimp )
+ CALL ncio_read_vector (file_restart, 'sag_gper' , landurban, sag_gper )
+ CALL ncio_read_vector (file_restart, 'sag_lake' , landurban, sag_lake )
+ CALL ncio_read_vector (file_restart, 'scv_roof' , landurban, scv_roof )
+ CALL ncio_read_vector (file_restart, 'scv_gimp' , landurban, scv_gimp )
+ CALL ncio_read_vector (file_restart, 'scv_gper' , landurban, scv_gper )
+ CALL ncio_read_vector (file_restart, 'scv_lake' , landurban, scv_lake )
+ CALL ncio_read_vector (file_restart, 'fsno_roof' , landurban, fsno_roof )
+ CALL ncio_read_vector (file_restart, 'fsno_gimp' , landurban, fsno_gimp )
+ CALL ncio_read_vector (file_restart, 'fsno_gper' , landurban, fsno_gper )
+ CALL ncio_read_vector (file_restart, 'fsno_lake' , landurban, fsno_lake )
+ CALL ncio_read_vector (file_restart, 'snowdp_roof', landurban, snowdp_roof)
+ CALL ncio_read_vector (file_restart, 'snowdp_gimp', landurban, snowdp_gimp)
+ CALL ncio_read_vector (file_restart, 'snowdp_gper', landurban, snowdp_gper)
+ CALL ncio_read_vector (file_restart, 'snowdp_lake', landurban, snowdp_lake)
+ CALL ncio_read_vector (file_restart, 'Fhac' , landurban, Fhac )
+ CALL ncio_read_vector (file_restart, 'Fwst' , landurban, Fwst )
+ CALL ncio_read_vector (file_restart, 'Fach' , landurban, Fach )
+ CALL ncio_read_vector (file_restart, 'Fahe' , landurban, Fahe )
+ CALL ncio_read_vector (file_restart, 'Fhah' , landurban, Fhah )
+ CALL ncio_read_vector (file_restart, 'vehc' , landurban, vehc )
+ CALL ncio_read_vector (file_restart, 'meta' , landurban, meta )
+ CALL ncio_read_vector (file_restart, 't_room ' , landurban, t_room )
+ CALL ncio_read_vector (file_restart, 't_roof' , landurban, t_roof )
+ CALL ncio_read_vector (file_restart, 't_wall' , landurban, t_wall )
+ CALL ncio_read_vector (file_restart, 'tafu' , landurban, tafu )
+ CALL ncio_read_vector (file_restart, 'urb_green' , landurban, urb_green )
+ CALL ncio_read_vector (file_restart, 'tree_lai' , landurban, urb_lai )
+ CALL ncio_read_vector (file_restart, 'tree_sai' , landurban, urb_sai )
+
+ END SUBROUTINE READ_UrbanTimeVariables
+
+ SUBROUTINE WRITE_UrbanTimeVariables (file_restart)
+
+ USE MOD_Namelist, only: DEF_REST_CompressLevel
+ USE MOD_LandUrban
+ USE MOD_NetCDFVector
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: file_restart
+
+ ! Local variables
+ integer :: compress
+
+ compress = DEF_REST_CompressLevel
+
+ CALL ncio_create_file_vector (file_restart, landurban)
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'urban')
+
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'snow' , -maxsnl )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'soil' , nl_soil )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'roof' , nl_roof )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'wall' , nl_wall )
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'soilsnow', nl_soil-maxsnl)
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'roofsnow', nl_roof-maxsnl)
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'wallsnow', nl_wall-maxsnl)
+
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'band', 2)
+ CALL ncio_define_dimension_vector (file_restart, landurban, 'rtyp', 2)
+
+ CALL ncio_write_vector (file_restart, 'fwsun' , 'urban', landurban, fwsun , compress)
+ CALL ncio_write_vector (file_restart, 'dfwsun', 'urban', landurban, dfwsun, compress)
+
+ CALL ncio_write_vector (file_restart, 'sroof', 'band', 2, 'rtyp', 2, 'urban', landurban, sroof, compress)
+ CALL ncio_write_vector (file_restart, 'swsun', 'band', 2, 'rtyp', 2, 'urban', landurban, swsun, compress)
+ CALL ncio_write_vector (file_restart, 'swsha', 'band', 2, 'rtyp', 2, 'urban', landurban, swsha, compress)
+ CALL ncio_write_vector (file_restart, 'sgimp', 'band', 2, 'rtyp', 2, 'urban', landurban, sgimp, compress)
+ CALL ncio_write_vector (file_restart, 'sgper', 'band', 2, 'rtyp', 2, 'urban', landurban, sgper, compress)
+ CALL ncio_write_vector (file_restart, 'slake', 'band', 2, 'rtyp', 2, 'urban', landurban, slake, compress)
+
+ CALL ncio_write_vector (file_restart, 'lwsun', 'urban', landurban, lwsun, compress)
+ CALL ncio_write_vector (file_restart, 'lwsha', 'urban', landurban, lwsha, compress)
+ CALL ncio_write_vector (file_restart, 'lgimp', 'urban', landurban, lgimp, compress)
+ CALL ncio_write_vector (file_restart, 'lgper', 'urban', landurban, lgper, compress)
+ CALL ncio_write_vector (file_restart, 'lveg' , 'urban', landurban, lveg , compress)
+
+ CALL ncio_write_vector (file_restart, 'z_sno_roof' , 'snow', -maxsnl, 'urban', landurban, z_sno_roof , compress)
+ CALL ncio_write_vector (file_restart, 'z_sno_gimp' , 'snow', -maxsnl, 'urban', landurban, z_sno_gimp , compress)
+ CALL ncio_write_vector (file_restart, 'z_sno_gper' , 'snow', -maxsnl, 'urban', landurban, z_sno_gper , compress)
+ CALL ncio_write_vector (file_restart, 'z_sno_lake' , 'snow', -maxsnl, 'urban', landurban, z_sno_lake , compress)
+
+ CALL ncio_write_vector (file_restart, 'dz_sno_roof', 'snow', -maxsnl, 'urban', landurban, dz_sno_roof, compress)
+ CALL ncio_write_vector (file_restart, 'dz_sno_gimp', 'snow', -maxsnl, 'urban', landurban, dz_sno_gimp, compress)
+ CALL ncio_write_vector (file_restart, 'dz_sno_gper', 'snow', -maxsnl, 'urban', landurban, dz_sno_gper, compress)
+ CALL ncio_write_vector (file_restart, 'dz_sno_lake', 'snow', -maxsnl, 'urban', landurban, dz_sno_lake, compress)
+
+ CALL ncio_write_vector (file_restart, 'troof_inner', 'urban', landurban, troof_inner, compress)
+ CALL ncio_write_vector (file_restart, 'twsun_inner', 'urban', landurban, twsun_inner, compress)
+ CALL ncio_write_vector (file_restart, 'twsha_inner', 'urban', landurban, twsha_inner, compress)
+
+ CALL ncio_write_vector (file_restart, 't_roofsno', 'roofsnow', nl_roof-maxsnl, 'urban', landurban, t_roofsno, compress)
+ CALL ncio_write_vector (file_restart, 't_wallsun', 'wallsnow', nl_wall-maxsnl, 'urban', landurban, t_wallsun, compress)
+ CALL ncio_write_vector (file_restart, 't_wallsha', 'wallsnow', nl_wall-maxsnl, 'urban', landurban, t_wallsha, compress)
+ CALL ncio_write_vector (file_restart, 't_gimpsno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, t_gimpsno, compress)
+ CALL ncio_write_vector (file_restart, 't_gpersno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, t_gpersno, compress)
+ CALL ncio_write_vector (file_restart, 't_lakesno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, t_lakesno, compress)
+
+ CALL ncio_write_vector (file_restart, 'wliq_roofsno', 'roofsnow', nl_roof-maxsnl, 'urban', landurban, wliq_roofsno, compress)
+ CALL ncio_write_vector (file_restart, 'wliq_gimpsno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, wliq_gimpsno, compress)
+ CALL ncio_write_vector (file_restart, 'wliq_gpersno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, wliq_gpersno, compress)
+ CALL ncio_write_vector (file_restart, 'wliq_lakesno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, wliq_lakesno, compress)
+ CALL ncio_write_vector (file_restart, 'wice_roofsno', 'roofsnow', nl_roof-maxsnl, 'urban', landurban, wice_roofsno, compress)
+ CALL ncio_write_vector (file_restart, 'wice_gimpsno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, wice_gimpsno, compress)
+ CALL ncio_write_vector (file_restart, 'wice_gpersno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, wice_gpersno, compress)
+ CALL ncio_write_vector (file_restart, 'wice_lakesno', 'soilsnow', nl_soil-maxsnl, 'urban', landurban, wice_lakesno, compress)
+
+ CALL ncio_write_vector (file_restart, 'sag_roof' , 'urban', landurban, sag_roof , compress)
+ CALL ncio_write_vector (file_restart, 'sag_gimp' , 'urban', landurban, sag_gimp , compress)
+ CALL ncio_write_vector (file_restart, 'sag_gper' , 'urban', landurban, sag_gper , compress)
+ CALL ncio_write_vector (file_restart, 'sag_lake' , 'urban', landurban, sag_lake , compress)
+ CALL ncio_write_vector (file_restart, 'scv_roof' , 'urban', landurban, scv_roof , compress)
+ CALL ncio_write_vector (file_restart, 'scv_gimp' , 'urban', landurban, scv_gimp , compress)
+ CALL ncio_write_vector (file_restart, 'scv_gper' , 'urban', landurban, scv_gper , compress)
+ CALL ncio_write_vector (file_restart, 'scv_lake' , 'urban', landurban, scv_lake , compress)
+ CALL ncio_write_vector (file_restart, 'fsno_roof' , 'urban', landurban, fsno_roof , compress)
+ CALL ncio_write_vector (file_restart, 'fsno_gimp' , 'urban', landurban, fsno_gimp , compress)
+ CALL ncio_write_vector (file_restart, 'fsno_gper' , 'urban', landurban, fsno_gper , compress)
+ CALL ncio_write_vector (file_restart, 'fsno_lake' , 'urban', landurban, fsno_lake , compress)
+ CALL ncio_write_vector (file_restart, 'snowdp_roof', 'urban', landurban, snowdp_roof, compress)
+ CALL ncio_write_vector (file_restart, 'snowdp_gimp', 'urban', landurban, snowdp_gimp, compress)
+ CALL ncio_write_vector (file_restart, 'snowdp_gper', 'urban', landurban, snowdp_gper, compress)
+ CALL ncio_write_vector (file_restart, 'snowdp_lake', 'urban', landurban, snowdp_lake, compress)
+ CALL ncio_write_vector (file_restart, 't_room' , 'urban', landurban, t_room , compress)
+ CALL ncio_write_vector (file_restart, 't_roof' , 'urban', landurban, t_roof , compress)
+ CALL ncio_write_vector (file_restart, 't_wall' , 'urban', landurban, t_wall , compress)
+ CALL ncio_write_vector (file_restart, 'tafu' , 'urban', landurban, tafu , compress)
+ CALL ncio_write_vector (file_restart, 'Fhac' , 'urban', landurban, Fhac , compress)
+ CALL ncio_write_vector (file_restart, 'Fwst' , 'urban', landurban, Fwst , compress)
+ CALL ncio_write_vector (file_restart, 'Fach' , 'urban', landurban, Fach , compress)
+ CALL ncio_write_vector (file_restart, 'Fahe' , 'urban', landurban, Fahe , compress)
+ CALL ncio_write_vector (file_restart, 'Fhah' , 'urban', landurban, Fhah , compress)
+ CALL ncio_write_vector (file_restart, 'vehc' , 'urban', landurban, vehc , compress)
+ CALL ncio_write_vector (file_restart, 'meta' , 'urban', landurban, meta , compress)
+ CALL ncio_write_vector (file_restart, 'tree_lai' , 'urban', landurban, urb_lai , compress)
+ CALL ncio_write_vector (file_restart, 'tree_sai' , 'urban', landurban, urb_sai , compress)
+ CALL ncio_write_vector (file_restart, 'urb_green' , 'urban', landurban, urb_green , compress)
+
+ END SUBROUTINE WRITE_UrbanTimeVariables
+
+ SUBROUTINE deallocate_UrbanTimeVariables
+
+ USE MOD_SPMD_Task
+ USE MOD_LandUrban
+
+ IF (p_is_compute) THEN
+ IF (numurban > 0) THEN
+ deallocate (fwsun )
+ deallocate (dfwsun )
+
+ deallocate (sroof )
+ deallocate (swsun )
+ deallocate (swsha )
+ deallocate (sgimp )
+ deallocate (sgper )
+ deallocate (slake )
+
+ deallocate (lwsun )
+ deallocate (lwsha )
+ deallocate (lgimp )
+ deallocate (lgper )
+ deallocate (lveg )
+
+ deallocate (z_sno_roof )
+ deallocate (z_sno_gimp )
+ deallocate (z_sno_gper )
+ deallocate (z_sno_lake )
+
+ deallocate (dz_sno_roof )
+ deallocate (dz_sno_gimp )
+ deallocate (dz_sno_gper )
+ deallocate (dz_sno_lake )
+
+ deallocate (t_roofsno )
+ deallocate (t_wallsun )
+ deallocate (t_wallsha )
+ deallocate (t_gimpsno )
+ deallocate (t_gpersno )
+ deallocate (t_lakesno )
+
+ deallocate (troof_inner )
+ deallocate (twsun_inner )
+ deallocate (twsha_inner )
+
+ deallocate (wliq_roofsno )
+ deallocate (wice_roofsno )
+ deallocate (wliq_gimpsno )
+ deallocate (wice_gimpsno )
+ deallocate (wliq_gpersno )
+ deallocate (wice_gpersno )
+ deallocate (wliq_lakesno )
+ deallocate (wice_lakesno )
+
+ deallocate (sag_roof )
+ deallocate (sag_gimp )
+ deallocate (sag_gper )
+ deallocate (sag_lake )
+ deallocate (scv_roof )
+ deallocate (scv_gimp )
+ deallocate (scv_gper )
+ deallocate (scv_lake )
+ deallocate (fsno_roof )
+ deallocate (fsno_gimp )
+ deallocate (fsno_gper )
+ deallocate (fsno_lake )
+ deallocate (snowdp_roof )
+ deallocate (snowdp_gimp )
+ deallocate (snowdp_gper )
+ deallocate (snowdp_lake )
+
+ deallocate (Fhac )
+ deallocate (Fwst )
+ deallocate (Fach )
+ deallocate (Fahe )
+ deallocate (Fhah )
+ deallocate (vehc )
+ deallocate (meta )
+
+ deallocate (t_room )
+ deallocate (t_roof )
+ deallocate (t_wall )
+ deallocate (tafu )
+
+ deallocate (urb_green )
+ deallocate (urb_lai )
+ deallocate (urb_sai )
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE deallocate_UrbanTimeVariables
+
+END MODULE MOD_Urban_Vars_TimeVariables
+#endif
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_WallTemperature.F90 b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_WallTemperature.F90
new file mode 100644
index 0000000000..1821feb6c8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/main/URBAN/MOD_Urban_WallTemperature.F90
@@ -0,0 +1,190 @@
+#include
+
+MODULE MOD_Urban_WallTemperature
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+!
+! The thickness of the wall (including the shady wall and the sunny
+! wall) is read from external data. Just like the soil, it is also
+! divided into 10 layers, with the same thickness set for each layer,
+! and its thermal parameters are also read from external data. Unlike
+! pervious/impervious surfaces, the wall does not consider water
+! accumulation or snow cover, so its thermal properties are completely
+! determined by its own materials. At the same time, it does not
+! consider water transfer, phase change processes, and latent heat
+! exchange.
+!
+! Another difference is in the setting of heat exchange for the
+! innermost (bottom) layer. For soil and impervious surfaces, the lack
+! of heat exchange in the bottom layer is considered. However, for
+! walls, the heat exchange between the indoor wall surface air and the
+! innermost layer of the wall is considered. Apart from this, the other
+! aspects and the solution process are similar to the temperature
+! solution for the soil.
+!
+! Created by Yongjiu Dai and Hua Yuan, 05/2020
+!
+!-----------------------------------------------------------------------
+ USE MOD_Precision
+ IMPLICIT NONE
+ SAVE
+
+ PUBLIC :: UrbanWallTem
+
+CONTAINS
+
+
+ SUBROUTINE UrbanWallTem (deltim,capr,cnfac,&
+ cv_wall,tk_wall,t_wall,dz_wall,z_wall,zi_wall,&
+ twall_inner,lwall,clwall,sabwall,fsenwall,cwalls,tkdz_wall)
+
+!=======================================================================
+! Wall temperatures
+! o Boundary conditions:
+! F = Rnet - Hg - LEg (top),
+! For urban sunwall, shadewall, and wall columns, there is a non-zero
+! heat flux across the bottom "building inner surface" layer and the
+! equations are derived assuming a prescribed or adjusted internal
+! building temperature. T = T_wall_inner (at the wall inner surface).
+!
+! o Wall temperature is predicted from heat conduction in N wall layers
+! and up to 5 snow layers. The thermal conductivities at the
+! interfaces between two neighbor layers (j, j+1) are derived from an
+! assumption that the flux across the interface is equal to that from
+! the node j to the interface and the flux from the interface to the
+! node j+1. The equation is solved using the Crank-Nicholson method
+! and resulted in a tridiagonal system equation.
+!
+! o no Phase change
+!
+! Original author: Yongjiu Dai, 05/2020
+!=======================================================================
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_Const_Physical
+ USE MOD_Utils, only: tridia
+
+ IMPLICIT NONE
+
+!-------------------------- Dummy Arguments ----------------------------
+ real(r8), intent(in) :: deltim !seconds in a time step [second]
+ real(r8), intent(in) :: capr !tuning factor to turn first layer T into surface T
+ real(r8), intent(in) :: cnfac !Crank Nicholson factor between 0 and 1
+
+ real(r8), intent(in) :: cv_wall(1:nl_wall) !heat capacity of urban wall [J/m3/K]
+ real(r8), intent(in) :: tk_wall(1:nl_wall) !thermal conductivity of urban wall [W/m/K]
+
+ real(r8), intent(in) :: dz_wall(1:nl_wall) !layer thickness [m]
+ real(r8), intent(in) :: z_wall (1:nl_wall) !node depth [m]
+ real(r8), intent(in) :: zi_wall(0:nl_wall) !interface depth [m]
+
+ real(r8), intent(in) :: twall_inner !temperature at the wall inner surface [K]
+ real(r8), intent(in) :: lwall !atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), intent(in) :: clwall !atmospheric infrared (longwave) radiation [W/m2]
+ real(r8), intent(in) :: sabwall !solar radiation absorbed by wall [W/m2]
+ real(r8), intent(in) :: fsenwall !sensible heat flux from wall [W/m2]
+ real(r8), intent(in) :: cwalls !deriv. of wall energy flux to wall temp [w/m2/k]
+
+ real(r8), intent(inout) :: t_wall(1:nl_wall) !wall layers' temperature [K]
+ real(r8), intent(inout) :: tkdz_wall !inner wall heat flux [w/m2/k]
+
+!-------------------------- Local Variables ----------------------------
+ real(r8) wice_wall(1:nl_wall) !ice lens [kg/m2]
+ real(r8) wliq_wall(1:nl_wall) !liquid water [kg/m2]
+
+ real(r8) cv (1:nl_wall) !heat capacity [J/(m2 K)]
+ real(r8) thk(1:nl_wall) !thermal conductivity of layer
+ real(r8) tk (1:nl_wall) !thermal conductivity [W/(m K)]
+
+ real(r8) at (1:nl_wall) !"a" vector for tridiagonal matrix
+ real(r8) bt (1:nl_wall) !"b" vector for tridiagonal matrix
+ real(r8) ct (1:nl_wall) !"c" vector for tridiagonal matrix
+ real(r8) rt (1:nl_wall) !"r" vector for tridiagonal solution
+
+ real(r8) fn (1:nl_wall) !heat diffusion through the layer interface [W/m2]
+ real(r8) fn1(1:nl_wall) !heat diffusion through the layer interface [W/m2]
+ real(r8) fact(1:nl_wall) !used in computing tridiagonal matrix
+ real(r8) dzm !used in computing tridiagonal matrix
+ real(r8) dzp !used in computing tridiagonal matrix
+
+ real(r8) t_wall_bef(1:nl_wall) !wall/snow temperature before update
+ real(r8) hs !net energy flux into the surface (w/m2)
+ real(r8) dhsdt !d(hs)/dT
+
+ integer i,j
+
+!-----------------------------------------------------------------------
+
+ wice_wall(1:) = 0.0 !ice lens [kg/m2]
+ wliq_wall(1:) = 0.0 !liquid water [kg/m2]
+
+ cv(1:) = cv_wall(1:)*dz_wall(1:)
+
+ thk(1:) = tk_wall(1:)
+
+ DO j = 1, nl_wall-1
+ tk(j) = thk(j)*thk(j+1)*(z_wall(j+1)-z_wall(j)) &
+ /(thk(j)*(z_wall(j+1)-zi_wall(j))+thk(j+1)*(zi_wall(j)-z_wall(j)))
+ ENDDO
+ tk(nl_wall) = thk(nl_wall)
+
+! net ground heat flux into the wall surface and its temperature derivative
+ hs = sabwall + lwall - fsenwall
+ dhsdT = - cwalls + clwall
+
+ t_wall_bef(1:) = t_wall(1:)
+
+ j = 1
+ fact(j) = deltim / cv(j) * dz_wall(j) &
+ / (0.5*(z_wall(j)-zi_wall(j-1)+capr*(z_wall(j+1)-zi_wall(j-1))))
+
+ DO j = 1, nl_wall
+ fact(j) = deltim/cv(j)
+ ENDDO
+
+ DO j = 1, nl_wall - 1
+ fn(j) = tk(j)*(t_wall(j+1)-t_wall(j))/(z_wall(j+1)-z_wall(j))
+ ENDDO
+
+ j = nl_wall
+ fn(j) = tk(j)*(twall_inner - cnfac*t_wall(j))/(zi_wall(j)-z_wall(j))
+ tkdz_wall= tk(j)/(zi_wall(j)-z_wall(j))
+
+! set up vector r and vectors a, b, c that define tridiagonal matrix
+ j = 1
+ dzp = z_wall(j+1)-z_wall(j)
+ at(j) = 0.
+ bt(j) = 1+(1.-cnfac)*fact(j)*tk(j)/dzp-fact(j)*dhsdT
+ ct(j) = -(1.-cnfac)*fact(j)*tk(j)/dzp
+ rt(j) = t_wall(j) + fact(j)*( hs - dhsdT*t_wall(j) + cnfac*fn(j) )
+
+ DO j = 2, nl_wall - 1
+ dzm = (z_wall(j)-z_wall(j-1))
+ dzp = (z_wall(j+1)-z_wall(j))
+ at(j) = - (1.-cnfac)*fact(j)* tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j)/dzp + tk(j-1)/dzm)
+ ct(j) = - (1.-cnfac)*fact(j)* tk(j)/dzp
+ rt(j) = t_wall(j) + cnfac*fact(j)*( fn(j) - fn(j-1) )
+ ENDDO
+
+ j = nl_wall
+ dzm = (z_wall(j)-z_wall(j-1))
+ dzp = (zi_wall(j)-z_wall(j))
+ at(j) = - (1.-cnfac)*fact(j)*tk(j-1)/dzm
+ bt(j) = 1.+ (1.-cnfac)*fact(j)*(tk(j-1)/dzm+tk(j)/dzp)
+ ct(j) = 0.
+ rt(j) = t_wall(j) + fact(j)*(fn(j) - cnfac*fn(j-1))
+
+! solve for t_wall
+ i = size(at)
+ CALL tridia (i ,at ,bt ,ct ,rt ,t_wall)
+
+ j = nl_wall
+ fn1(j) = tk(j)*(twall_inner - cnfac*t_wall(j))/(zi_wall(j)-z_wall(j))
+
+ END SUBROUTINE UrbanWallTem
+
+END MODULE MOD_Urban_WallTemperature
+! ---------- EOP ------------
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_5x5DataReadin.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_5x5DataReadin.F90
new file mode 100644
index 0000000000..4a120a37e1
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_5x5DataReadin.F90
@@ -0,0 +1,554 @@
+#include
+
+MODULE MOD_5x5DataReadin
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Reading data in netCDF files by 5 degree blocks.
+!
+! The file name gives the boundaries of the block.
+! For example, file "RG_65_75_60_80.URB2010.nc" stores data in region
+! from 65N to 60N and 75E to 80E.
+!
+! Notice that:
+! 1. Subroutines loop over all 5 degree blocks in simulation region.
+! 2. Latitude in files is from north to south.
+! 3. "read_5x5_data_pft" reads data with dimension "pft" and permute
+! dimension (lon,lat,pft) in files to (pft,lon,lat) in variables.
+! 4. "read_5x5_data_time" reads data with dimension "time"
+! at given time.
+! 5. "read_5x5_data_pft_time" reads data with dimension "pft" and "time"
+! at given time and permute dimension (lon,lat,pft) in files
+! to (pft,lon,lat) in variables.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_NetCDFSerial, only: nccheck
+ IMPLICIT NONE
+
+ integer, parameter :: N_PFT_modis = 16
+
+ INTERFACE read_5x5_data
+ MODULE procedure read_5x5_data_int32
+ MODULE procedure read_5x5_data_real8
+ END INTERFACE read_5x5_data
+
+ PUBLIC :: read_5x5_data_pft
+ PUBLIC :: read_5x5_data_time
+ PUBLIC :: read_5x5_data_pft_time
+
+CONTAINS
+
+ ! -----
+ SUBROUTINE this_block_and_move_to_next ( &
+ dir_5x5, sfx, nxbox, nybox, nxglb, isouth, inorth, iwest, ieast, &
+ ibox, jbox, ibox0, i0, i1, j0, j1, il0, il1, jl0, jl1, &
+ file_5x5)
+
+ USE MOD_Grid
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+
+ integer, intent(in) :: nxbox, nybox, nxglb
+ integer, intent(in) :: isouth, inorth, iwest, ieast
+ integer, intent(inout) :: ibox, jbox, ibox0
+ integer, intent(out) :: i0, i1, j0, j1
+ integer, intent(out) :: il0, il1, jl0, jl1
+
+ character (len=*), intent(out) :: file_5x5
+
+ ! Local variables
+ integer :: xdsp, ydsp
+ character(len=4) :: str
+
+ xdsp = (ibox-1) * nxbox
+ ydsp = (jbox-1) * nybox
+
+ j0 = max(inorth-ydsp, 1)
+ j1 = min(isouth-ydsp, nybox)
+ jl0 = j0 + ydsp - inorth + 1
+ jl1 = j1 + ydsp - inorth + 1
+
+ IF (ieast >= iwest) THEN
+ i0 = max(iwest-xdsp, 1)
+ i1 = min(ieast-xdsp, nxbox)
+ il0 = i0 + xdsp - iwest + 1
+ il1 = i1 + xdsp - iwest + 1
+ ELSE
+ IF (iwest <= xdsp+nxbox) THEN
+ i0 = max(iwest-xdsp, 1)
+ i1 = nxbox
+ il0 = i0 + xdsp - iwest + 1
+ il1 = i1 + xdsp - iwest + 1
+ ELSE
+ i0 = 1
+ i1 = min(ieast-xdsp, nxbox)
+ il0 = i0 + xdsp + nxglb - iwest + 1
+ il1 = i1 + xdsp + nxglb - iwest + 1
+ ENDIF
+ ENDIF
+
+ file_5x5 = trim(dir_5x5) // '/RG'
+ write(str, '(I4)') (19-jbox)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ write(str, '(I4)') (ibox-37)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ write(str, '(I4)') (18-jbox)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ write(str, '(I4)') (ibox-36)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ file_5x5 = trim(file_5x5) // '.' // trim(sfx) // '.nc'
+
+ IF ((ieast >= xdsp + 1) .and. (ieast <= xdsp + nxbox)) THEN
+ IF (isouth <= ydsp + nybox) THEN
+ jbox = -1
+ ELSE
+ ibox = ibox0
+ jbox = jbox + 1
+ ENDIF
+ ELSE
+ ibox = mod(ibox, nxglb/nxbox) + 1
+ ENDIF
+
+ END SUBROUTINE this_block_and_move_to_next
+
+ ! -----
+ SUBROUTINE read_5x5_data_int32 (dir_5x5, sfx, grid, dataname, rdata)
+
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE netcdf
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ type (grid_type), intent(in) :: grid
+
+ character (len=*), intent(in) :: dataname
+ type (block_data_int32_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: nxbox, nybox, nxglb, nyglb
+ integer :: iblkme, iblk, jblk, isouth, inorth, iwest, ieast, ibox, jbox, ibox0
+ integer :: i0, i1, j0, j1, il0, il1, jl0, jl1
+ character(len=256) :: file_5x5
+ integer :: ncid, varid
+ integer, allocatable :: dcache(:,:)
+ logical :: fexists
+
+ nxglb = grid%nlon
+ nyglb = grid%nlat
+
+ nxbox = nxglb / 360 * 5
+ nybox = nyglb / 180 * 5
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (grid%xcnt(iblk) == 0) CYCLE
+ IF (grid%ycnt(jblk) == 0) CYCLE
+
+ rdata%blk(iblk,jblk)%val(:,:) = 0
+
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (ieast > nxglb) ieast = ieast - nxglb
+
+ ibox = grid%xdsp(iblk)/nxbox + 1
+ jbox = grid%ydsp(jblk)/nybox + 1
+ ibox0 = ibox
+
+ DO WHILE (.true.)
+
+ CALL this_block_and_move_to_next ( &
+ dir_5x5, sfx, nxbox, nybox, nxglb, isouth, inorth, iwest, ieast, &
+ ibox, jbox, ibox0, i0, i1, j0, j1, il0, il1, jl0, jl1, &
+ file_5x5)
+
+ inquire(file=file_5x5, exist=fexists)
+ IF (fexists) THEN
+ allocate (dcache (i1-i0+1,j1-j0+1))
+
+ CALL nccheck( nf90_open(trim(file_5x5), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid) )
+ CALL nccheck( nf90_get_var(ncid, varid, dcache, (/i0,j0/), (/i1-i0+1,j1-j0+1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ rdata%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache
+
+ deallocate (dcache)
+ ENDIF
+
+ IF (jbox == -1) EXIT
+
+ ENDDO
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE read_5x5_data_int32
+
+ ! -----
+ SUBROUTINE read_5x5_data_real8 (dir_5x5, sfx, grid, dataname, rdata)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE netcdf
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ type (grid_type), intent(in) :: grid
+
+ character (len=*), intent(in) :: dataname
+ type (block_data_real8_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: nxbox, nybox, nxglb, nyglb
+ integer :: iblkme, iblk, jblk, isouth, inorth, iwest, ieast, ibox, jbox, ibox0
+ integer :: i0, i1, j0, j1, il0, il1, jl0, jl1
+ character(len=256) :: file_5x5
+ integer :: ncid, varid
+ real(r8), allocatable :: dcache(:,:)
+ logical :: fexists
+
+ nxglb = grid%nlon
+ nyglb = grid%nlat
+
+ nxbox = nxglb / 360 * 5
+ nybox = nyglb / 180 * 5
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (grid%xcnt(iblk) == 0) CYCLE
+ IF (grid%ycnt(jblk) == 0) CYCLE
+
+ rdata%blk(iblk,jblk)%val(:,:) = 0
+
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (ieast > nxglb) ieast = ieast - nxglb
+
+ ibox = grid%xdsp(iblk)/nxbox + 1
+ jbox = grid%ydsp(jblk)/nybox + 1
+ ibox0 = ibox
+
+ DO WHILE (.true.)
+
+ CALL this_block_and_move_to_next ( &
+ dir_5x5, sfx, nxbox, nybox, nxglb, isouth, inorth, iwest, ieast, &
+ ibox, jbox, ibox0, i0, i1, j0, j1, il0, il1, jl0, jl1, &
+ file_5x5)
+
+ inquire(file=file_5x5, exist=fexists)
+ IF (fexists) THEN
+ allocate (dcache (i1-i0+1,j1-j0+1))
+
+ CALL nccheck( nf90_open(trim(file_5x5), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid) )
+ CALL nccheck( nf90_get_var(ncid, varid, dcache, (/i0,j0/), (/i1-i0+1,j1-j0+1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ rdata%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache
+
+ deallocate(dcache)
+ ENDIF
+
+ IF (jbox == -1) EXIT
+
+ ENDDO
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE read_5x5_data_real8
+
+ ! -----
+ SUBROUTINE read_5x5_data_pft (dir_5x5, sfx, grid, dataname, rdata)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE netcdf
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ type (grid_type), intent(in) :: grid
+
+ character (len=*), intent(in) :: dataname
+ type (block_data_real8_3d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: nxbox, nybox, nxglb, nyglb
+ integer :: iblkme, iblk, jblk, isouth, inorth, iwest, ieast, ibox, jbox, ibox0
+ integer :: i0, i1, j0, j1, il0, il1, jl0, jl1
+ character(len=256) :: file_5x5
+ integer :: ncid, varid
+ real(r8), allocatable :: dcache(:,:,:)
+ logical :: fexists
+ integer :: ipft
+
+ nxglb = grid%nlon
+ nyglb = grid%nlat
+
+ nxbox = nxglb / 360 * 5
+ nybox = nyglb / 180 * 5
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (grid%xcnt(iblk) == 0) CYCLE
+ IF (grid%ycnt(jblk) == 0) CYCLE
+
+ rdata%blk(iblk,jblk)%val(:,:,:) = 0
+
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (ieast > nxglb) ieast = ieast - nxglb
+
+ ibox = grid%xdsp(iblk)/nxbox + 1
+ jbox = grid%ydsp(jblk)/nybox + 1
+ ibox0 = ibox
+
+ DO WHILE (.true.)
+
+ CALL this_block_and_move_to_next ( &
+ dir_5x5, sfx, nxbox, nybox, nxglb, isouth, inorth, iwest, ieast, &
+ ibox, jbox, ibox0, i0, i1, j0, j1, il0, il1, jl0, jl1, &
+ file_5x5)
+
+ inquire(file=file_5x5, exist=fexists)
+ IF (fexists) THEN
+ allocate (dcache (i1-i0+1,j1-j0+1,0:N_PFT_modis-1))
+
+ CALL nccheck( nf90_open(trim(file_5x5), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid) )
+ CALL nccheck( nf90_get_var(ncid, varid, dcache, &
+ (/i0,j0,1/), (/i1-i0+1,j1-j0+1,N_PFT_modis/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ DO ipft = 0, N_PFT_modis-1
+ rdata%blk(iblk,jblk)%val(ipft,il0:il1,jl0:jl1) = dcache(:,:,ipft)
+ ENDDO
+
+ deallocate (dcache)
+ ENDIF
+
+ IF (jbox == -1) EXIT
+
+ ENDDO
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE read_5x5_data_pft
+
+ ! -----
+ SUBROUTINE read_5x5_data_time (dir_5x5, sfx, grid, dataname, time, rdata)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE netcdf
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ type (grid_type), intent(in) :: grid
+
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: time
+ type (block_data_real8_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: nxbox, nybox, nxglb, nyglb
+ integer :: iblkme, iblk, jblk, isouth, inorth, iwest, ieast, ibox, jbox, ibox0
+ integer :: i0, i1, j0, j1, il0, il1, jl0, jl1
+ character(len=256) :: file_5x5
+ integer :: ncid, varid
+ real(r8), allocatable :: dcache(:,:)
+ logical :: fexists
+
+ nxglb = grid%nlon
+ nyglb = grid%nlat
+
+ nxbox = nxglb / 360 * 5
+ nybox = nyglb / 180 * 5
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (grid%xcnt(iblk) == 0) CYCLE
+ IF (grid%ycnt(jblk) == 0) CYCLE
+
+ rdata%blk(iblk,jblk)%val(:,:) = 0
+
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (ieast > nxglb) ieast = ieast - nxglb
+
+ ibox = grid%xdsp(iblk)/nxbox + 1
+ jbox = grid%ydsp(jblk)/nybox + 1
+ ibox0 = ibox
+
+ DO WHILE (.true.)
+
+ CALL this_block_and_move_to_next ( &
+ dir_5x5, sfx, nxbox, nybox, nxglb, isouth, inorth, iwest, ieast, &
+ ibox, jbox, ibox0, i0, i1, j0, j1, il0, il1, jl0, jl1, &
+ file_5x5)
+
+ inquire(file=file_5x5, exist=fexists)
+ IF (fexists) THEN
+ allocate (dcache (i1-i0+1,j1-j0+1))
+
+ CALL nccheck( nf90_open(trim(file_5x5), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid) )
+ CALL nccheck( nf90_get_var(ncid, varid, dcache, &
+ (/i0,j0,time/), (/i1-i0+1,j1-j0+1,1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ rdata%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache
+
+ deallocate (dcache)
+ ENDIF
+
+ IF (jbox == -1) EXIT
+
+ ENDDO
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE read_5x5_data_time
+
+ ! -----
+ SUBROUTINE read_5x5_data_pft_time (dir_5x5, sfx, grid, dataname, time, rdata)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE netcdf
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ type (grid_type), intent(in) :: grid
+
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: time
+ type (block_data_real8_3d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: nxbox, nybox, nxglb, nyglb
+ integer :: iblkme, iblk, jblk, isouth, inorth, iwest, ieast, ibox, jbox, ibox0
+ integer :: i0, i1, j0, j1, il0, il1, jl0, jl1
+ character(len=256) :: file_5x5
+ integer :: ncid, varid
+ real(r8), allocatable :: dcache(:,:,:)
+ logical :: fexists
+ integer :: ipft
+
+ nxglb = grid%nlon
+ nyglb = grid%nlat
+
+ nxbox = nxglb / 360 * 5
+ nybox = nyglb / 180 * 5
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (grid%xcnt(iblk) == 0) CYCLE
+ IF (grid%ycnt(jblk) == 0) CYCLE
+
+ rdata%blk(iblk,jblk)%val(:,:,:) = 0
+
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (ieast > nxglb) ieast = ieast - nxglb
+
+ ibox = grid%xdsp(iblk)/nxbox + 1
+ jbox = grid%ydsp(jblk)/nybox + 1
+ ibox0 = ibox
+
+ DO WHILE (.true.)
+
+ CALL this_block_and_move_to_next ( &
+ dir_5x5, sfx, nxbox, nybox, nxglb, isouth, inorth, iwest, ieast, &
+ ibox, jbox, ibox0, i0, i1, j0, j1, il0, il1, jl0, jl1, &
+ file_5x5)
+
+ inquire(file=file_5x5, exist=fexists)
+ IF (fexists) THEN
+ allocate (dcache (i1-i0+1,j1-j0+1,0:N_PFT_modis-1))
+
+ CALL nccheck( nf90_open(trim(file_5x5), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid) )
+ CALL nccheck( nf90_get_var(ncid, varid, dcache, &
+ (/i0,j0,1,time/), (/i1-i0+1,j1-j0+1,N_PFT_modis,1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ DO ipft = 0, N_PFT_modis-1
+ rdata%blk(iblk,jblk)%val(ipft,il0:il1,jl0:jl1) = dcache(:,:,ipft)
+ ENDDO
+
+ deallocate (dcache)
+ ENDIF
+
+ IF (jbox == -1) EXIT
+
+ ENDDO
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE read_5x5_data_pft_time
+
+END MODULE MOD_5x5DataReadin
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_AggregationRequestData.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_AggregationRequestData.F90
new file mode 100644
index 0000000000..c4517c21cc
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_AggregationRequestData.F90
@@ -0,0 +1,709 @@
+#include
+
+MODULE MOD_AggregationRequestData
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Aggregation Utilities.
+!
+! On IO ranks, a data daemon is running to provide data
+! at fine resolutions for rank processes.
+! On rank processes, request is sent to IO ranks and
+! data is returned from IO ranks.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ PUBLIC :: aggregation_request_data
+
+#ifdef USEMPI
+ PUBLIC :: aggregation_data_daemon
+ PUBLIC :: aggregation_compute_done
+#endif
+
+! ---- subroutines ----
+CONTAINS
+
+#ifdef USEMPI
+ SUBROUTINE aggregation_data_daemon (grid_in, &
+ data_r8_2d_in1, data_r8_2d_in2, data_r8_2d_in3, data_r8_2d_in4, &
+ data_r8_2d_in5, data_r8_2d_in6, &
+ data_r8_3d_in1, n1_r8_3d_in1 , data_r8_3d_in2, n1_r8_3d_in2, &
+ data_i4_2d_in1, data_i4_2d_in2)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Grid
+ USE MOD_DataType
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid_in
+
+ ! 2D REAL data
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in1
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in2
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in3
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in4
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in5
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in6
+
+ ! 3D REAL data
+ integer, intent(in), optional :: n1_r8_3d_in1
+ type (block_data_real8_3d), intent(in), optional :: data_r8_3d_in1
+
+ integer, intent(in), optional :: n1_r8_3d_in2
+ type (block_data_real8_3d), intent(in), optional :: data_r8_3d_in2
+
+ ! 2D INTEGER data
+ type (block_data_int32_2d), intent(in), optional :: data_i4_2d_in1
+ type (block_data_int32_2d), intent(in), optional :: data_i4_2d_in2
+
+ ! Local Variables
+ integer :: nreq, ireq, rmesg(2), isrc, idest
+ integer :: xblk, yblk, xloc, yloc
+ integer, allocatable :: ylist(:), xlist(:)
+
+ real(r8), allocatable :: sbuf_r8_1d(:), sbuf_r8_2d(:,:)
+ integer , allocatable :: sbuf_i4_1d(:)
+
+ logical, allocatable :: compute_done (:)
+
+#ifdef MPAS_EMBEDDED_COLM
+ RETURN
+#endif
+
+ IF (p_is_active) THEN
+
+ allocate (compute_done (0:p_np_compute-1))
+
+ compute_done(:) = .false.
+ DO WHILE (any(.not. compute_done))
+
+ CALL mpi_recv (rmesg, 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ nreq = rmesg(2)
+
+ IF (nreq > 0) THEN
+
+ allocate (xlist (nreq))
+ allocate (ylist (nreq))
+
+ CALL mpi_recv (xlist, nreq, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (ylist, nreq, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ idest = isrc
+
+ allocate (sbuf_r8_1d (nreq))
+
+ IF (present(data_r8_2d_in1)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_1d(ireq) = data_r8_2d_in1%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_1d, nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ IF (present(data_r8_2d_in2)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_1d(ireq) = data_r8_2d_in2%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_1d, nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ IF (present(data_r8_2d_in3)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_1d(ireq) = data_r8_2d_in3%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_1d, nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ IF (present(data_r8_2d_in4)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_1d(ireq) = data_r8_2d_in4%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_1d, nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ IF (present(data_r8_2d_in5)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_1d(ireq) = data_r8_2d_in5%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_1d, nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ IF (present(data_r8_2d_in6)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_1d(ireq) = data_r8_2d_in6%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_1d, nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+
+ deallocate (sbuf_r8_1d)
+
+ IF (present(data_r8_3d_in1) .and. present(n1_r8_3d_in1)) THEN
+
+ allocate (sbuf_r8_2d (n1_r8_3d_in1,nreq))
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_2d(:,ireq) = data_r8_3d_in1%blk(xblk,yblk)%val(:,xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_2d, n1_r8_3d_in1*nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (sbuf_r8_2d)
+ ENDIF
+
+ IF (present(data_r8_3d_in2) .and. present(n1_r8_3d_in2)) THEN
+
+ allocate (sbuf_r8_2d (n1_r8_3d_in2,nreq))
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_r8_2d(:,ireq) = data_r8_3d_in2%blk(xblk,yblk)%val(:,xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_r8_2d, n1_r8_3d_in2*nreq, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (sbuf_r8_2d)
+ ENDIF
+
+ allocate (sbuf_i4_1d (nreq))
+
+ IF (present(data_i4_2d_in1)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_i4_1d(ireq) = data_i4_2d_in1%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_i4_1d, nreq, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ IF (present(data_i4_2d_in2)) THEN
+ DO ireq = 1, nreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ sbuf_i4_1d(ireq) = data_i4_2d_in2%blk(xblk,yblk)%val(xloc,yloc)
+ ENDDO
+
+ CALL mpi_send (sbuf_i4_1d, nreq, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+
+ deallocate (sbuf_i4_1d)
+
+ deallocate (ylist)
+ deallocate (xlist)
+
+ ELSE
+ compute_done(p_itis_compute(isrc)) = .true.
+ ENDIF
+
+ ENDDO
+
+ deallocate (compute_done)
+
+ ENDIF
+
+ END SUBROUTINE aggregation_data_daemon
+
+#endif
+
+ !----------------------------------------------------
+ SUBROUTINE aggregation_request_data ( &
+ pixelset, iset, grid_in, zip, area, &
+ data_r8_2d_in1, data_r8_2d_out1, &
+ data_r8_2d_in2, data_r8_2d_out2, &
+ data_r8_2d_in3, data_r8_2d_out3, &
+ data_r8_2d_in4, data_r8_2d_out4, &
+ data_r8_2d_in5, data_r8_2d_out5, &
+ data_r8_2d_in6, data_r8_2d_out6, &
+ data_r8_3d_in1, data_r8_3d_out1, n1_r8_3d_in1, lb1_r8_3d_in1, &
+ data_r8_3d_in2, data_r8_3d_out2, n1_r8_3d_in2, lb1_r8_3d_in2, &
+ data_i4_2d_in1, data_i4_2d_out1, &
+ data_i4_2d_in2, data_i4_2d_out2, &
+ filledvalue_i4)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixel
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_Pixelset
+ USE MOD_Utils
+
+ IMPLICIT NONE
+
+ type (pixelset_type), intent(in) :: pixelset
+ integer, intent(in) :: iset
+
+ type (grid_type), intent(in) :: grid_in
+ logical, intent(in) :: zip
+
+ real(r8), allocatable, intent(out), optional :: area(:)
+
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in1
+ real(r8), allocatable, intent(out), optional :: data_r8_2d_out1 (:)
+
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in2
+ real(r8), allocatable, intent(out), optional :: data_r8_2d_out2 (:)
+
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in3
+ real(r8), allocatable, intent(out), optional :: data_r8_2d_out3 (:)
+
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in4
+ real(r8), allocatable, intent(out), optional :: data_r8_2d_out4 (:)
+
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in5
+ real(r8), allocatable, intent(out), optional :: data_r8_2d_out5 (:)
+
+ type (block_data_real8_2d), intent(in), optional :: data_r8_2d_in6
+ real(r8), allocatable, intent(out), optional :: data_r8_2d_out6 (:)
+
+ integer, intent(in), optional :: n1_r8_3d_in1, lb1_r8_3d_in1
+ type (block_data_real8_3d), intent(in), optional :: data_r8_3d_in1
+ real(r8), allocatable, intent(out), optional :: data_r8_3d_out1 (:,:)
+
+ integer, intent(in), optional :: n1_r8_3d_in2, lb1_r8_3d_in2
+ type (block_data_real8_3d), intent(in), optional :: data_r8_3d_in2
+ real(r8), allocatable, intent(out), optional :: data_r8_3d_out2 (:,:)
+
+ type (block_data_int32_2d), intent(in), optional :: data_i4_2d_in1
+ integer, allocatable, intent(out), optional :: data_i4_2d_out1 (:)
+
+ type (block_data_int32_2d), intent(in), optional :: data_i4_2d_in2
+ integer, allocatable, intent(out), optional :: data_i4_2d_out2 (:)
+
+ integer, intent(in), optional :: filledvalue_i4
+
+ ! Local Variables
+ integer :: totalreq, ireq, nreq, smesg(2), isrc, idest, iproc
+ integer :: ilon, ilat, xblk, yblk, xloc, yloc, iloc, nx, ny, ix, iy, ig
+ integer :: ie, ipxstt, ipxend, npxl, ipxl, lb1, xgrdthis, ygrdthis
+ integer, allocatable :: ylist(:), xlist(:), ipt(:), ibuf(:), rbuf_i4_1d(:)
+ integer, allocatable :: xsorted(:), ysorted(:), xy2d(:,:)
+ real(r8), allocatable :: area2d(:,:), rbuf_r8_1d(:), rbuf_r8_2d(:,:)
+ logical, allocatable :: msk(:)
+
+
+ ie = pixelset%ielm (iset)
+ ipxstt = pixelset%ipxstt(iset)
+ ipxend = pixelset%ipxend(iset)
+ npxl = ipxend - ipxstt + 1
+
+ IF (zip) THEN
+
+ allocate (xsorted(npxl))
+ allocate (ysorted(npxl))
+
+ nx = 0; ny = 0
+ DO ipxl = ipxstt, ipxend
+ xgrdthis = grid_in%xgrd(mesh(ie)%ilon(ipxl))
+ ygrdthis = grid_in%ygrd(mesh(ie)%ilat(ipxl))
+ CALL insert_into_sorted_list1 (xgrdthis, nx, xsorted, iloc)
+ CALL insert_into_sorted_list1 (ygrdthis, ny, ysorted, iloc)
+ ENDDO
+
+ allocate (xy2d (nx,ny)); xy2d(:,:) = 0
+
+ IF (present(area)) THEN
+ allocate(area2d(nx,ny)); area2d(:,:) = 0.
+ ENDIF
+
+ DO ipxl = ipxstt, ipxend
+ xgrdthis = grid_in%xgrd(mesh(ie)%ilon(ipxl))
+ ygrdthis = grid_in%ygrd(mesh(ie)%ilat(ipxl))
+
+ ix = find_in_sorted_list1(xgrdthis, nx, xsorted)
+ iy = find_in_sorted_list1(ygrdthis, ny, ysorted)
+
+ xy2d(ix,iy) = xy2d(ix,iy) + 1
+
+ IF (present(area)) THEN
+ area2d(ix,iy) = area2d(ix,iy) + areaquad (&
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDIF
+ ENDDO
+
+ totalreq = count(xy2d > 0)
+
+ allocate (xlist (totalreq))
+ allocate (ylist (totalreq))
+
+ IF (present(area)) allocate(area(totalreq))
+
+ ig = 0
+ DO ix = 1, nx
+ DO iy = 1, ny
+ IF (xy2d(ix,iy) > 0) THEN
+ ig = ig + 1
+ xlist(ig) = xsorted(ix)
+ ylist(ig) = ysorted(iy)
+ IF (present(area)) area (ig) = area2d(ix,iy)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (xsorted, ysorted, xy2d)
+ IF (present(area)) deallocate (area2d)
+
+ ELSE
+
+ allocate(xlist (npxl))
+ allocate(ylist (npxl))
+
+ IF (present(area)) allocate (area (npxl))
+
+ totalreq = npxl
+ DO ipxl = ipxstt, ipxend
+ xlist(ipxl-ipxstt+1) = grid_in%xgrd(mesh(ie)%ilon(ipxl))
+ ylist(ipxl-ipxstt+1) = grid_in%ygrd(mesh(ie)%ilat(ipxl))
+ IF (present(area)) THEN
+ area(ipxl-ipxstt+1) = areaquad (&
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (present(data_r8_2d_in1) .and. present(data_r8_2d_out1)) allocate (data_r8_2d_out1 (totalreq))
+ IF (present(data_r8_2d_in2) .and. present(data_r8_2d_out2)) allocate (data_r8_2d_out2 (totalreq))
+ IF (present(data_r8_2d_in3) .and. present(data_r8_2d_out3)) allocate (data_r8_2d_out3 (totalreq))
+ IF (present(data_r8_2d_in4) .and. present(data_r8_2d_out4)) allocate (data_r8_2d_out4 (totalreq))
+ IF (present(data_r8_2d_in5) .and. present(data_r8_2d_out5)) allocate (data_r8_2d_out5 (totalreq))
+ IF (present(data_r8_2d_in6) .and. present(data_r8_2d_out6)) allocate (data_r8_2d_out6 (totalreq))
+
+ IF (present(data_r8_3d_in1) .and. present(data_r8_3d_out1) .and. present(n1_r8_3d_in1)) THEN
+ IF (present(lb1_r8_3d_in1)) THEN
+ lb1 = lb1_r8_3d_in1
+ ELSE
+ lb1 = 1
+ ENDIF
+ allocate (data_r8_3d_out1 (lb1:lb1-1+n1_r8_3d_in1,totalreq))
+ ENDIF
+
+ IF (present(data_r8_3d_in2) .and. present(data_r8_3d_out2) .and. present(n1_r8_3d_in2)) THEN
+ IF (present(lb1_r8_3d_in2)) THEN
+ lb1 = lb1_r8_3d_in2
+ ELSE
+ lb1 = 1
+ ENDIF
+ allocate (data_r8_3d_out2 (lb1:lb1-1+n1_r8_3d_in2,totalreq))
+ ENDIF
+
+ IF (present(data_i4_2d_in1) .and. present(data_i4_2d_out1)) THEN
+ allocate (data_i4_2d_out1 (totalreq))
+ IF (present(filledvalue_i4)) THEN
+ data_i4_2d_out1 = filledvalue_i4
+ ENDIF
+ ENDIF
+
+ IF (present(data_i4_2d_in2) .and. present(data_i4_2d_out2)) THEN
+ allocate (data_i4_2d_out2 (totalreq))
+ IF (present(filledvalue_i4)) THEN
+ data_i4_2d_out2 = filledvalue_i4
+ ENDIF
+ ENDIF
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+
+ allocate (ipt (totalreq))
+ allocate (msk (totalreq))
+
+ ipt(:) = -1
+
+ DO ireq = 1, totalreq
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ ipt(ireq) = gblock%pio(xblk,yblk)
+ ENDDO
+
+ DO iproc = 0, p_np_active-1
+ msk = (ipt == p_address_active(iproc))
+ nreq = count(msk)
+
+ IF (nreq > 0) THEN
+
+ smesg = (/p_iam_glb, nreq/)
+ idest = p_address_active(iproc)
+ CALL mpi_send (smesg, 2, MPI_INTEGER, idest, mpi_tag_mesg, p_comm_glb, p_err)
+
+ allocate (ibuf (nreq))
+
+ ibuf = pack(xlist(1:totalreq), msk)
+ CALL mpi_send (ibuf, nreq, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ ibuf = pack(ylist(1:totalreq), msk)
+ CALL mpi_send (ibuf, nreq, MPI_INTEGER, idest, mpi_tag_data, p_comm_glb, p_err)
+
+ isrc = idest
+
+ allocate (rbuf_r8_1d (nreq))
+
+ IF (present(data_r8_2d_in1) .and. present(data_r8_2d_out1)) THEN
+ CALL mpi_recv (rbuf_r8_1d, nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_1d, msk, data_r8_2d_out1)
+ ENDIF
+
+ IF (present(data_r8_2d_in2) .and. present(data_r8_2d_out2)) THEN
+ CALL mpi_recv (rbuf_r8_1d, nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_1d, msk, data_r8_2d_out2)
+ ENDIF
+
+ IF (present(data_r8_2d_in3) .and. present(data_r8_2d_out3)) THEN
+ CALL mpi_recv (rbuf_r8_1d, nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_1d, msk, data_r8_2d_out3)
+ ENDIF
+
+ IF (present(data_r8_2d_in4) .and. present(data_r8_2d_out4)) THEN
+ CALL mpi_recv (rbuf_r8_1d, nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_1d, msk, data_r8_2d_out4)
+ ENDIF
+
+ IF (present(data_r8_2d_in5) .and. present(data_r8_2d_out5)) THEN
+ CALL mpi_recv (rbuf_r8_1d, nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_1d, msk, data_r8_2d_out5)
+ ENDIF
+
+ IF (present(data_r8_2d_in6) .and. present(data_r8_2d_out6)) THEN
+ CALL mpi_recv (rbuf_r8_1d, nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_1d, msk, data_r8_2d_out6)
+ ENDIF
+
+ deallocate (rbuf_r8_1d)
+
+ IF (present(data_r8_3d_in1) .and. present(data_r8_3d_out1) .and. present(n1_r8_3d_in1)) THEN
+ allocate (rbuf_r8_2d (n1_r8_3d_in1,nreq))
+ CALL mpi_recv (rbuf_r8_2d, n1_r8_3d_in1*nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_2d, msk, data_r8_3d_out1)
+ deallocate (rbuf_r8_2d)
+ ENDIF
+
+ IF (present(data_r8_3d_in2) .and. present(data_r8_3d_out2) .and. present(n1_r8_3d_in2)) THEN
+ allocate (rbuf_r8_2d (n1_r8_3d_in2,nreq))
+ CALL mpi_recv (rbuf_r8_2d, n1_r8_3d_in2*nreq, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_r8_2d, msk, data_r8_3d_out2)
+ deallocate (rbuf_r8_2d)
+ ENDIF
+
+ allocate (rbuf_i4_1d (nreq))
+ IF (present(data_i4_2d_in1) .and. present(data_i4_2d_out1)) THEN
+ CALL mpi_recv (rbuf_i4_1d, nreq, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_i4_1d, msk, data_i4_2d_out1)
+ ENDIF
+
+ IF (present(data_i4_2d_in2) .and. present(data_i4_2d_out2)) THEN
+ CALL mpi_recv (rbuf_i4_1d, nreq, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL unpack_inplace (rbuf_i4_1d, msk, data_i4_2d_out2)
+ ENDIF
+
+ deallocate (rbuf_i4_1d)
+
+ deallocate (ibuf)
+ ENDIF
+ ENDDO
+
+ deallocate (xlist)
+ deallocate (ylist)
+ deallocate (ipt )
+ deallocate (msk )
+
+#else
+
+ DO ireq = 1, totalreq
+
+ xblk = grid_in%xblk(xlist(ireq))
+ yblk = grid_in%yblk(ylist(ireq))
+ xloc = grid_in%xloc(xlist(ireq))
+ yloc = grid_in%yloc(ylist(ireq))
+
+ IF (present(data_r8_2d_in1) .and. present(data_r8_2d_out1)) THEN
+ data_r8_2d_out1(ireq) = data_r8_2d_in1%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_2d_in2) .and. present(data_r8_2d_out2)) THEN
+ data_r8_2d_out2(ireq) = data_r8_2d_in2%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_2d_in3) .and. present(data_r8_2d_out3)) THEN
+ data_r8_2d_out3(ireq) = data_r8_2d_in3%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_2d_in4) .and. present(data_r8_2d_out4)) THEN
+ data_r8_2d_out4(ireq) = data_r8_2d_in4%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_2d_in5) .and. present(data_r8_2d_out5)) THEN
+ data_r8_2d_out5(ireq) = data_r8_2d_in5%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_2d_in6) .and. present(data_r8_2d_out6)) THEN
+ data_r8_2d_out6(ireq) = data_r8_2d_in6%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_3d_in1) .and. present(data_r8_3d_out1) .and. present(n1_r8_3d_in1)) THEN
+ data_r8_3d_out1(:,ireq) = data_r8_3d_in1%blk(xblk,yblk)%val(:,xloc,yloc)
+ ENDIF
+
+ IF (present(data_r8_3d_in2) .and. present(data_r8_3d_out2) .and. present(n1_r8_3d_in2)) THEN
+ data_r8_3d_out2(:,ireq) = data_r8_3d_in2%blk(xblk,yblk)%val(:,xloc,yloc)
+ ENDIF
+
+ IF (present(data_i4_2d_in1) .and. present(data_i4_2d_out1)) THEN
+ data_i4_2d_out1(ireq) = data_i4_2d_in1%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ IF (present(data_i4_2d_in2) .and. present(data_i4_2d_out2)) THEN
+ data_i4_2d_out2(ireq) = data_i4_2d_in2%blk(xblk,yblk)%val(xloc,yloc)
+ ENDIF
+
+ ENDDO
+
+#endif
+
+ END SUBROUTINE aggregation_request_data
+
+#ifdef USEMPI
+
+ SUBROUTINE aggregation_compute_done ()
+
+ USE MOD_SPMD_Task
+
+ IMPLICIT NONE
+
+ integer :: smesg(2), iproc, idest
+
+#ifdef MPAS_EMBEDDED_COLM
+ RETURN
+#endif
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ smesg = (/p_iam_glb, -1/)
+ idest = p_address_active(iproc)
+ CALL mpi_send (smesg, 2, MPI_INTEGER, idest, mpi_tag_mesg, p_comm_glb, p_err)
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE aggregation_compute_done
+
+#endif
+
+
+ SUBROUTINE fillnan (vec, fill, defval)
+
+ USE MOD_Precision
+ USE MOD_UserDefFun, only: isnan_ud
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: vec(:)
+ logical, intent(in) :: fill
+ real(r8), intent(in) :: defval
+
+ ! local variables
+ integer :: i, n
+ real(r8) :: s
+
+ n = 0
+ s = 0.
+ DO i = lbound(vec,1), ubound(vec,1)
+ IF (.not. isnan_ud(vec(i))) THEN
+ n = n + 1
+ s = s + vec(i)
+ ENDIF
+ ENDDO
+
+ IF ((n > 0) .and. (n < size(vec))) THEN
+ s = s/n
+ DO i = lbound(vec,1), ubound(vec,1)
+ IF (isnan_ud(vec(i))) vec(i) = s
+ ENDDO
+ ENDIF
+
+ IF ((n == 0) .and. fill) THEN
+ vec(:) = defval
+ ENDIF
+
+ END SUBROUTINE fillnan
+
+END MODULE MOD_AggregationRequestData
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Block.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Block.F90
new file mode 100644
index 0000000000..e46580e731
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Block.F90
@@ -0,0 +1,642 @@
+#include
+
+MODULE MOD_Block
+
+!-------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! To deal with high-resolution data, the globe is divided into blocks.
+!
+! (180W,90N) (180E,90N)
+! .-----------------------------------.
+! | | | | |
+! | | | | |
+! | | | | |
+! .-----------------------------------.
+! | | | | |
+! | | | | |
+! | | | | |
+! .-----------------------------------.
+! | | | | |
+! | | | | |
+! | | | | |
+! .-----------------------------------.
+! (180W,90S) (180E,90S)
+!
+! 1.
+! Boundaries for block (i,j) is saved in
+! "gblock%lat_s(j), gblock%lat_n(j), gblock%lon_w(i), gblock%lon_e(i)"
+! for south, north, west and east boundaries respectively.
+!
+! 2.
+! The (i,j) element of 2D array gblock%pio saves the global communication
+! number of process which is in charge of Input/Output of block (i,j).
+!
+! 3.
+! For Input/Output processes, "gblock%nblkme, gblock%xblkme(:), gblock%yblkme(:)"
+! SAVE the locations of blocks which are handled by themselves.
+!
+! 4.
+! Division of blocks can be generated by number of blocks globally (by set_by_size),
+! or set by predefined boundaries in files (by set_by_file).
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! ---- data types ----
+ type :: block_type
+
+ ! Coordinates.
+ integer :: nxblk, nyblk
+ real(r8), allocatable :: lat_s (:)
+ real(r8), allocatable :: lat_n (:)
+ real(r8), allocatable :: lon_w (:)
+ real(r8), allocatable :: lon_e (:)
+
+ ! IO.
+ integer, allocatable :: pio(:,:)
+
+ integer :: nblkme
+ integer, allocatable :: xblkme(:), yblkme(:)
+
+ CONTAINS
+
+ procedure, PUBLIC :: set => block_set
+
+ procedure, PUBLIC :: save_to_file => block_save_to_file
+ procedure, PUBLIC :: load_from_file => block_load_from_file
+
+ procedure, PRIVATE :: clip => block_clip
+ procedure, PRIVATE :: init_pio => block_init_pio
+ procedure, PRIVATE :: read_pio => block_read_pio
+
+ final :: block_free_mem
+
+ END type block_type
+
+ ! ---- Instance ----
+ type (block_type) :: gblock
+
+
+ ! ---- PUBLIC SUBROUTINE ----
+ PUBLIC :: get_filename_block
+
+CONTAINS
+
+ ! --------------------------------
+ SUBROUTINE block_set (this)
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_Utils
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+
+ class (block_type) :: this
+
+ ! Local Variables
+ logical :: fexists
+ integer :: iblk, jblk
+
+ inquire(file=trim(DEF_BlockInfoFile), exist=fexists)
+
+ IF (fexists) THEN
+
+ CALL ncio_read_bcast_serial (DEF_BlockInfoFile, 'lat_s', this%lat_s)
+ CALL ncio_read_bcast_serial (DEF_BlockInfoFile, 'lat_n', this%lat_n)
+ CALL ncio_read_bcast_serial (DEF_BlockInfoFile, 'lon_w', this%lon_w)
+ CALL ncio_read_bcast_serial (DEF_BlockInfoFile, 'lon_e', this%lon_e)
+
+ this%nyblk = size(this%lat_s)
+ this%nxblk = size(this%lon_w)
+
+ ! blocks should be from south to north
+ IF (this%lat_s(1) > this%lat_s(this%nyblk)) THEN
+ this%lat_s = this%lat_s(this%nyblk:1:-1)
+ this%lat_n = this%lat_n(this%nyblk:1:-1)
+ ENDIF
+
+ ELSE
+
+ IF (DEF_AverageElementSize > 0) THEN
+
+ this%nxblk = floor(360./(DEF_AverageElementSize/120.*50))
+ this%nxblk = min(this%nxblk,360)
+ DO WHILE ((this%nxblk < 360) .and. (mod(360,this%nxblk) /= 0))
+ this%nxblk = this%nxblk + 1
+ ENDDO
+
+ this%nyblk = floor(180./(DEF_AverageElementSize/120.*50))
+ this%nyblk = min(this%nyblk,180)
+ DO WHILE ((this%nyblk < 180) .and. (mod(180,this%nyblk) /= 0))
+ this%nyblk = this%nyblk + 1
+ ENDDO
+
+ ELSE
+
+ this%nxblk = DEF_nx_blocks
+ this%nyblk = DEf_ny_blocks
+
+ ENDIF
+
+ IF ((mod(360,this%nxblk) /= 0) .or. (mod(180,this%nyblk) /= 0)) THEN
+ IF (p_is_root) THEN
+ write(*,*) 'Number of blocks in longitude should be a factor of 360 '
+ write(*,*) ' and Number of blocks in latitude should be a factor of 180.'
+ CALL CoLM_stop ()
+ ENDIF
+ ENDIF
+
+ allocate (this%lon_w (this%nxblk))
+ allocate (this%lon_e (this%nxblk))
+
+ DO iblk = 1, this%nxblk
+ this%lon_w(iblk) = -180.0 + 360.0/this%nxblk * (iblk-1)
+ this%lon_e(iblk) = -180.0 + 360.0/this%nxblk * iblk
+
+ CALL normalize_longitude (this%lon_w(iblk))
+ CALL normalize_longitude (this%lon_e(iblk))
+ ENDDO
+
+ allocate (this%lat_s (this%nyblk))
+ allocate (this%lat_n (this%nyblk))
+
+ DO jblk = 1, this%nyblk
+ this%lat_s(jblk) = -90.0 + 180.0/this%nyblk * (jblk-1)
+ this%lat_n(jblk) = -90.0 + 180.0/this%nyblk * jblk
+ ENDDO
+
+ ENDIF
+
+#ifndef SinglePoint
+ IF (p_is_root) THEN
+ write (*,*)
+ write (*,'(A)') '----- Block information -----'
+ write (*,'(I4,A,I4,A)') this%nxblk, ' blocks in longitude,', &
+ this%nyblk, ' blocks in latitude.'
+ write (*,*)
+ ENDIF
+#else
+ write(*,'(A)') 'Blocks : Set (360 longitude x 180 latitude) blocks for Single Point.'
+#endif
+
+#ifndef SinglePoint
+ CALL this%init_pio ()
+#endif
+
+ END SUBROUTINE block_set
+
+ ! --------------------------------
+ SUBROUTINE block_save_to_file (this, dir_landdata)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (block_type) :: this
+
+ character(len=*), intent(in) :: dir_landdata
+
+ ! Local variables
+ character(len=256) :: filename
+
+ IF (p_is_root) THEN
+
+ filename = trim(dir_landdata) // '/block.nc'
+
+ CALL ncio_create_file (filename)
+
+ CALL ncio_define_dimension (filename, 'longitude', this%nxblk)
+ CALL ncio_define_dimension (filename, 'latitude', this%nyblk)
+
+ CALL ncio_write_serial (filename, 'lat_s', this%lat_s, 'latitude' )
+ CALL ncio_write_serial (filename, 'lat_n', this%lat_n, 'latitude' )
+ CALL ncio_write_serial (filename, 'lon_w', this%lon_w, 'longitude')
+ CALL ncio_write_serial (filename, 'lon_e', this%lon_e, 'longitude')
+
+ ENDIF
+
+ END SUBROUTINE block_save_to_file
+
+ ! --------------------------------
+ SUBROUTINE block_load_from_file (this, dir_landdata)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (block_type) :: this
+ character(len=*), intent(in) :: dir_landdata
+
+ ! Local variables
+ character(len=256) :: filename
+
+ filename = trim(dir_landdata) // '/block.nc'
+
+ CALL ncio_read_bcast_serial (filename, 'lat_s', this%lat_s)
+ CALL ncio_read_bcast_serial (filename, 'lat_n', this%lat_n)
+ CALL ncio_read_bcast_serial (filename, 'lon_w', this%lon_w)
+ CALL ncio_read_bcast_serial (filename, 'lon_e', this%lon_e)
+
+ this%nyblk = size(this%lat_s)
+ this%nxblk = size(this%lon_w)
+
+ IF (p_is_root) THEN
+ write (*,*) 'Block information:'
+ write (*,'(I3,A,I3,A)') this%nxblk, ' blocks in longitude,', &
+ this%nyblk, ' blocks in latitude.'
+ write (*,*)
+ ENDIF
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (allocated(this%pio)) deallocate(this%pio)
+ allocate (this%pio (this%nxblk,this%nyblk))
+ this%pio(:,:) = -1
+ this%nblkme = 0
+#else
+ CALL this%read_pio (dir_landdata)
+#endif
+
+ END SUBROUTINE block_load_from_file
+
+ ! --------------------------------
+ SUBROUTINE block_clip (this, &
+ iblk_south, iblk_north, iblk_west, iblk_east, numblocks)
+
+ USE MOD_Namelist
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ class (block_type) :: this
+ integer, intent(out) :: iblk_south, iblk_north, iblk_west, iblk_east
+ integer, intent(out), optional :: numblocks
+
+ ! Local Variables
+ real(r8) :: edges, edgen, edgew, edgee
+ integer :: numblocks_x, numblocks_y
+
+ edges = DEF_domain%edges
+ edgen = DEF_domain%edgen
+ edgew = DEF_domain%edgew
+ edgee = DEF_domain%edgee
+
+ iblk_south = find_nearest_south (edges, this%nyblk, this%lat_s)
+ iblk_north = find_nearest_north (edgen, this%nyblk, this%lat_n)
+
+ CALL normalize_longitude (edgew)
+ CALL normalize_longitude (edgee)
+
+ IF (edgew == edgee) THEN
+ iblk_west = 1
+ iblk_east = this%nxblk
+ ELSE
+ iblk_west = find_nearest_west (edgew, this%nxblk, this%lon_w)
+ iblk_east = find_nearest_east (edgee, this%nxblk, this%lon_e)
+
+ IF (iblk_west == iblk_east) THEN
+ IF ((lon_between_floor(edgee,this%lon_w(iblk_west),edgew)) &
+ .and. (this%lon_w(iblk_west) /= edgew)) THEN
+ iblk_west = 1
+ iblk_east = this%nxblk
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (present(numblocks)) THEN
+
+ numblocks_y = iblk_north - iblk_south + 1
+
+ IF (iblk_east >= iblk_west) THEN
+ numblocks_x = iblk_east - iblk_west + 1
+ ELSE
+ numblocks_x = this%nxblk - iblk_west + 1 + iblk_east
+ ENDIF
+
+ numblocks = numblocks_x * numblocks_y
+
+ ENDIF
+
+ END SUBROUTINE block_clip
+
+ ! --------------------------------
+ SUBROUTINE block_init_pio (this)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ class (block_type) :: this
+
+ integer :: iblk, jblk, iproc
+ integer :: iblk_south, iblk_north, iblk_west, iblk_east
+ integer :: numblocks, ngrp
+ integer :: iblkme
+
+ IF (p_is_root) THEN
+ CALL this%clip (iblk_south, iblk_north, iblk_west, iblk_east, numblocks)
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (numblocks, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+
+ IF ((mod(p_np_glb,DEF_PIO_groupsize) == 0) .and. (DEF_PIO_groupsize > 2)) THEN
+ ngrp = p_np_glb / DEF_PIO_groupsize
+ ELSE
+ ngrp = (p_np_glb-1) / DEF_PIO_groupsize
+ ENDIF
+ ngrp = min(max(ngrp, 1), numblocks)
+
+ CALL divide_processes_into_groups (ngrp)
+#endif
+
+ allocate (this%pio (this%nxblk,this%nyblk))
+ this%pio(:,:) = -1
+
+ IF (p_is_root) THEN
+
+ iproc = -1
+ DO jblk = iblk_south, iblk_north
+
+ iblk = iblk_west
+ DO WHILE (.true.)
+#ifdef USEMPI
+ iproc = mod(iproc+1, p_np_active)
+ this%pio(iblk,jblk) = p_address_active(iproc)
+#else
+ this%pio(iblk,jblk) = p_root
+#endif
+
+ IF (iblk /= iblk_east) THEN
+ iblk = mod(iblk,this%nxblk) + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDDO
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (this%pio, this%nxblk * this%nyblk, MPI_INTEGER, &
+ p_address_root, p_comm_glb, p_err)
+#endif
+
+ this%nblkme = 0
+ IF (p_is_active) THEN
+ this%nblkme = count(this%pio == p_iam_glb)
+ IF (this%nblkme > 0) THEN
+ iblkme = 0
+ allocate (this%xblkme(this%nblkme))
+ allocate (this%yblkme(this%nblkme))
+ DO iblk = 1, this%nxblk
+ DO jblk = 1, this%nyblk
+ IF (p_iam_glb == this%pio(iblk,jblk)) THEN
+ iblkme = iblkme + 1
+ this%xblkme(iblkme) = iblk
+ this%yblkme(iblkme) = jblk
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE block_init_pio
+
+ ! --------------------------------
+ SUBROUTINE block_read_pio (this, dir_landdata)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ class (block_type) :: this
+ character(len=*), intent(in) :: dir_landdata
+
+ ! Local Variables
+ character(len=256) :: filename, cyear
+ integer, allocatable :: nelm_io(:), nelmblk(:,:)
+ integer :: iblk_south, iblk_north, iblk_west, iblk_east
+ integer :: numblocks, ngrp, iblk, jblk, iproc, jproc
+ integer :: iblkme
+
+ IF (p_is_root) THEN
+ ! Whether it varies by year???
+ write(cyear,'(i4.4)') DEF_LC_YEAR
+ filename = trim(dir_landdata) // '/mesh/' // trim(cyear) // '/mesh.nc'
+ CALL ncio_read_serial (filename, 'nelm_blk', nelmblk)
+ numblocks = count(nelmblk > 0)
+
+ CALL this%clip (iblk_south, iblk_north, iblk_west, iblk_east)
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+
+ IF ((mod(p_np_glb,DEF_PIO_groupsize) == 0) .and. (DEF_PIO_groupsize > 2)) THEN
+ ngrp = p_np_glb / DEF_PIO_groupsize
+ ELSE
+ ngrp = (p_np_glb-1) / DEF_PIO_groupsize
+ ENDIF
+ ngrp = min(max(ngrp, 1), numblocks)
+
+ DO WHILE (.true.)
+
+ allocate (nelm_io (ngrp))
+ nelm_io(:) = 0
+
+ DO jblk = iblk_south, iblk_north
+ iblk = iblk_west
+ DO WHILE (.true.)
+
+ IF (nelmblk(iblk,jblk) > 0) THEN
+ iproc = minloc(nelm_io, dim=1)
+ nelm_io(iproc) = nelm_io(iproc) + nelmblk(iblk,jblk)
+ ENDIF
+
+ IF (iblk /= iblk_east) THEN
+ iblk = mod(iblk,this%nxblk) + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDDO
+
+ IF (maxval(nelm_io) < 2 * minval(nelm_io)) THEN
+ deallocate (nelm_io)
+ EXIT
+ ELSE
+ ngrp = ngrp - 1
+ deallocate (nelm_io)
+ ENDIF
+ ENDDO
+
+ IF (DEF_nIO_eq_nBlock) THEN
+ ngrp = numblocks
+ ENDIF
+
+ IF ((p_np_glb-1)/ngrp < 2) THEN
+ CALL CoLM_stop ('CoLM called STOP: Too many groups or Too few processors for this case.')
+ ENDIF
+ ENDIF
+
+
+ CALL mpi_bcast (numblocks, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ CALL mpi_bcast (ngrp, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ CALL divide_processes_into_groups (ngrp)
+#endif
+
+ allocate (this%pio (this%nxblk,this%nyblk))
+ this%pio(:,:) = -1
+
+ IF (p_is_root) THEN
+
+#ifdef USEMPI
+ allocate (nelm_io (0:p_np_active-1))
+ nelm_io(:) = 0
+ jproc = -1
+#endif
+
+ DO jblk = iblk_south, iblk_north
+ iblk = iblk_west
+ DO WHILE (.true.)
+#ifdef USEMPI
+ IF (nelmblk(iblk,jblk) > 0) THEN
+ iproc = minloc(nelm_io, dim=1) - 1
+ this%pio(iblk,jblk) = p_address_active(iproc)
+ nelm_io(iproc) = nelm_io(iproc) + nelmblk(iblk,jblk)
+ ELSEIF (nelmblk(iblk,jblk) == 0) THEN
+ jproc = mod(jproc+1, p_np_active)
+ this%pio(iblk,jblk) = p_address_active(jproc)
+ ENDIF
+#else
+ this%pio(iblk,jblk) = p_root
+#endif
+
+ IF (iblk /= iblk_east) THEN
+ iblk = mod(iblk,this%nxblk) + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ deallocate (nelm_io)
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (this%pio, this%nxblk * this%nyblk, MPI_INTEGER, &
+ p_address_root, p_comm_glb, p_err)
+#endif
+
+ this%nblkme = 0
+ IF (p_is_active) THEN
+ this%nblkme = count(this%pio == p_iam_glb)
+ IF (this%nblkme > 0) THEN
+ iblkme = 0
+ allocate (this%xblkme(this%nblkme))
+ allocate (this%yblkme(this%nblkme))
+ DO iblk = 1, this%nxblk
+ DO jblk = 1, this%nyblk
+ IF (p_iam_glb == this%pio(iblk,jblk)) THEN
+ iblkme = iblkme + 1
+ this%xblkme(iblkme) = iblk
+ this%yblkme(iblkme) = jblk
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (allocated(nelmblk)) deallocate (nelmblk)
+
+ END SUBROUTINE block_read_pio
+
+ ! --------------------------------
+ SUBROUTINE block_free_mem (this)
+
+ IMPLICIT NONE
+ type (block_type) :: this
+
+ IF (allocated (this%lat_s)) deallocate (this%lat_s)
+ IF (allocated (this%lat_n)) deallocate (this%lat_n)
+ IF (allocated (this%lon_w)) deallocate (this%lon_w)
+ IF (allocated (this%lon_e)) deallocate (this%lon_e)
+
+ IF (allocated (this%pio) ) deallocate (this%pio )
+
+ IF (allocated (this%xblkme)) deallocate (this%xblkme)
+ IF (allocated (this%yblkme)) deallocate (this%yblkme)
+
+ END SUBROUTINE block_free_mem
+
+ ! -----
+ SUBROUTINE get_blockname (iblk, jblk, blockname)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: iblk, jblk
+
+ character(len=*), intent(out) :: blockname
+
+ ! Local variables
+ character(len=4) :: cx
+ character(len=3) :: cy
+ integer :: i
+
+ IF (gblock%lat_s(jblk) < 0) THEN
+ write (cy, '(A1,I2.2)') 's', - floor(gblock%lat_s(jblk))
+ ELSE
+ write (cy, '(A1,I2.2)') 'n', floor(gblock%lat_s(jblk))
+ ENDIF
+
+ IF (gblock%lon_w(iblk) < 0) THEN
+ write (cx, '(A1,I3.3)') 'w', - floor(gblock%lon_w(iblk))
+ ELSE
+ write (cx, '(A1,I3.3)') 'e', floor(gblock%lon_w(iblk))
+ ENDIF
+
+ blockname = trim(cx) // '_' // trim(cy)
+
+ END SUBROUTINE get_blockname
+
+ ! --------------------------------
+ SUBROUTINE get_filename_block (filename, iblk, jblk, fileblock)
+
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ integer, intent(in) :: iblk, jblk
+
+ character(len=*), intent(out) :: fileblock
+
+ ! Local variables
+ character(len=8) :: blockname
+ integer :: i
+
+ CALL get_blockname (iblk, jblk, blockname)
+
+ i = len_trim (filename)
+ DO WHILE (i > 0)
+ IF (filename(i:i) == '.') EXIT
+ i = i - 1
+ ENDDO
+
+ IF (i > 0) THEN
+ fileblock = filename(1:i-1) // '_' // blockname // '.nc'
+ ELSE
+ fileblock = filename // '_' // blockname // '.nc'
+ ENDIF
+
+ END SUBROUTINE get_filename_block
+
+END MODULE MOD_Block
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_CatchmentDataReadin.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_CatchmentDataReadin.F90
new file mode 100644
index 0000000000..dcb444bc80
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_CatchmentDataReadin.F90
@@ -0,0 +1,375 @@
+#include
+
+MODULE MOD_CatchmentDataReadin
+
+!--------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Reading preprocessed MERIT Hydro data and generated catchment data in netcdf files.
+!
+! 1. If "in_one_file" is false, then the data is orgnized by 5 degree blocks.
+! The file name gives the southwest corner of the block.
+! For example, file "n60e075.nc" stores data in region from 65N to 60N and 75E to 80E,
+! Subroutines loop over all 5 degree blocks in simulation region.
+!
+! 2. Data is saved in variables with types of "block_data_xxxxx_xd".
+!
+! 3. Latitude in files is from north to south.
+!
+! Created by Shupeng Zhang, May 2023
+!--------------------------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ integer, parameter :: nxhbox = 6000
+ integer, parameter :: nyhbox = 6000
+ integer, parameter :: nxhglb = 432000
+ integer, parameter :: nyhglb = 216000
+
+ INTERFACE catchment_data_read
+ MODULE procedure catchment_data_read_int32
+ MODULE procedure catchment_data_read_real8
+ END INTERFACE catchment_data_read
+
+CONTAINS
+
+ ! -----
+ SUBROUTINE catchment_data_read_int32 (file_meshdata_in, dataname, grid, rdata_int32, spv)
+
+ USE MOD_Grid
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: file_meshdata_in
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+
+ type (block_data_int32_2d), intent(inout) :: rdata_int32
+ integer, intent(in), optional :: spv
+
+ IF (present(spv)) THEN
+ CALL catchment_data_read_general (file_meshdata_in, dataname, grid, &
+ rdata_int32 = rdata_int32, spv_i4 = spv)
+ ELSE
+ CALL catchment_data_read_general (file_meshdata_in, dataname, grid, &
+ rdata_int32 = rdata_int32)
+ ENDIF
+
+ END SUBROUTINE catchment_data_read_int32
+
+ ! -----
+ SUBROUTINE catchment_data_read_real8 (file_meshdata_in, dataname, grid, rdata_real8, spv)
+
+ USE MOD_Grid
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: file_meshdata_in
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+
+ type (block_data_real8_2d), intent(inout) :: rdata_real8
+ real(r8), intent(in), optional :: spv
+
+ IF (present(spv)) THEN
+ CALL catchment_data_read_general (file_meshdata_in, dataname, grid, &
+ rdata_real8 = rdata_real8, spv_r8 = spv)
+ ELSE
+ CALL catchment_data_read_general (file_meshdata_in, dataname, grid, &
+ rdata_real8 = rdata_real8)
+ ENDIF
+
+ END SUBROUTINE catchment_data_read_real8
+
+ ! -----
+ SUBROUTINE catchment_data_read_general (file_meshdata_in, dataname, grid, &
+ rdata_int32, spv_i4, rdata_real8, spv_r8)
+
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Utils
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: file_meshdata_in
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+
+ type (block_data_int32_2d), intent(inout), optional :: rdata_int32
+ integer, intent(in), optional :: spv_i4
+
+ type (block_data_real8_2d), intent(inout), optional :: rdata_real8
+ real(r8), intent(in), optional :: spv_r8
+
+
+ ! Local Variables
+ logical :: in_one_file
+ integer :: nlat, nlon, ilon
+ integer :: iblkme, iblk, jblk, isouth, inorth, iwest, ieast, ibox, jbox
+ integer :: xdsp, ydsp, i0, i1, j0, j1, il0, il1, jl0, jl1
+ integer :: i0min, i1max, if0, if1, jf0, jf1, i0next, i1next
+ character(len=256) :: file_mesh, path_mesh
+ character(len=3) :: pre1
+ character(len=4) :: pre2
+ integer, allocatable :: dcache_i4(:,:)
+ real(r8), allocatable :: dcache_r8(:,:)
+ real(r8), allocatable :: latitude(:), longitude(:)
+ logical :: fexists
+
+ IF (p_is_active) THEN
+
+ IF (p_iam_active == p_root) THEN
+ IF (grid%yinc == 1) THEN
+ write(*,*) 'Warning: latitude in catchment data should be from north to south.'
+ ENDIF
+ ENDIF
+
+ IF (p_iam_active == p_root) THEN
+ in_one_file = ncio_var_exist (file_meshdata_in, dataname)
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_bcast (in_one_file, 1, mpi_logical, p_root, p_comm_active, p_err)
+#endif
+
+ IF (in_one_file) THEN
+
+ file_mesh = file_meshdata_in
+
+ CALL ncio_read_serial (file_mesh, 'lat', latitude)
+ CALL ncio_read_serial (file_mesh, 'lon', longitude)
+
+ nlat = size(latitude )
+ nlon = size(longitude)
+
+ isouth = find_nearest_south (latitude(nlat), grid%nlat, grid%lat_s)
+ inorth = find_nearest_north (latitude(1), grid%nlat, grid%lat_n)
+
+ DO ilon = 1, nlon
+ CALL normalize_longitude (longitude(ilon))
+ ENDDO
+
+ iwest = find_nearest_west (longitude(1), grid%nlon, grid%lon_w)
+ ieast = find_nearest_east (longitude(nlon), grid%nlon, grid%lon_e)
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ IF (present(rdata_int32)) THEN
+ IF (present(spv_i4)) THEN
+ rdata_int32%blk(iblk,jblk)%val(:,:) = spv_i4
+ ELSE
+ rdata_int32%blk(iblk,jblk)%val(:,:) = 0
+ ENDIF
+ ENDIF
+
+ IF (present(rdata_real8)) THEN
+ IF (present(spv_r8)) THEN
+ rdata_real8%blk(iblk,jblk)%val(:,:) = spv_r8
+ ELSE
+ rdata_real8%blk(iblk,jblk)%val(:,:) = -1.e36_r8
+ ENDIF
+ ENDIF
+
+ IF ((inorth > grid%ydsp(jblk)+nyhbox) .or. (isouth < grid%ydsp(jblk)+1)) THEN
+ CYCLE
+ ENDIF
+
+ j0 = max(inorth, grid%ydsp(jblk)+1)
+ j1 = min(isouth, grid%ydsp(jblk)+grid%ycnt(jblk))
+
+ jl0 = j0 - grid%ydsp(jblk)
+ jl1 = j1 - grid%ydsp(jblk)
+ jf0 = j0 - inorth + 1
+ jf1 = j1 - inorth + 1
+
+ i0min = grid%xdsp(iblk) + 1
+ i1max = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (i1max > grid%nlon) i1max = i1max - grid%nlon
+
+ DO WHILE ((i0min /= i1max) .and. (.not. (lon_between_floor(grid%lon_w(i0min), &
+ grid%lon_w(iwest), grid%lon_e(ieast)))))
+ i0min = i0min + 1; IF (i0min > grid%nlon) i0min = 1
+ ENDDO
+
+ IF (lon_between_floor(grid%lon_w(i0min), grid%lon_w(iwest), grid%lon_e(ieast))) THEN
+ i0 = i0min
+ i1 = i0
+ i1next = i1 + 1; IF (i1next > grid%nlon) i1next = 1
+ DO WHILE ((i1 /= i1max) .and. &
+ lon_between_floor(grid%lon_w(i1next), grid%lon_w(iwest), grid%lon_e(ieast)))
+ i1 = i1next
+ i1next = i1 + 1; IF (i1next > grid%nlon) i1next = 1
+ ENDDO
+
+ if0 = i0 - iwest + 1; IF (if0 <= 0) if0 = if0 + grid%nlon
+ if1 = i1 - iwest + 1; IF (if1 <= 0) if1 = if1 + grid%nlon
+ il0 = i0 - grid%xdsp(iblk); IF (il0 <= 0) il0 = il0 + grid%nlon
+ il1 = i1 - grid%xdsp(iblk); IF (il1 <= 0) il1 = il1 + grid%nlon
+
+ IF (present(rdata_int32)) THEN
+ CALL ncio_read_part_serial (file_mesh, dataname, (/jf0,if0/), (/jf1,if1/), dcache_i4)
+ dcache_i4 = transpose(dcache_i4)
+
+ rdata_int32%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache_i4
+ ENDIF
+
+ IF (present(rdata_real8)) THEN
+ CALL ncio_read_part_serial (file_mesh, dataname, (/jf0,if0/), (/jf1,if1/), dcache_r8)
+ dcache_r8 = transpose(dcache_r8)
+
+ rdata_real8%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache_r8
+ ENDIF
+
+ ENDIF
+
+ IF (lon_between_ceil(grid%lon_e(i1max), grid%lon_w(iwest), grid%lon_e(ieast))) THEN
+ i1 = i1max
+ i0 = i1
+ i0next = i0 - 1; IF (i0next == 0) i0next = grid%nlon
+ DO WHILE ((i0 /= i0min) .and. &
+ lon_between_ceil(grid%lon_e(i0next), grid%lon_w(iwest), grid%lon_e(ieast)))
+ i0 = i0next
+ i0next = i0 - 1; IF (i0next == 0) i0next = grid%nlon
+ ENDDO
+
+ IF (i0 /= i0min) THEN
+ if0 = i0 - iwest + 1; IF (if0 <= 0) if0 = if0 + grid%nlon
+ if1 = i1 - iwest + 1; IF (if1 <= 0) if1 = if1 + grid%nlon
+ il0 = i0 - grid%xdsp(iblk); IF (il0 <= 0) il0 = il0 + grid%nlon
+ il1 = i1 - grid%xdsp(iblk); IF (il1 <= 0) il1 = il1 + grid%nlon
+
+ IF (present(rdata_int32)) THEN
+ CALL ncio_read_part_serial (file_mesh, dataname, (/jf0,if0/), (/jf1,if1/), dcache_i4)
+ dcache_i4 = transpose(dcache_i4)
+
+ rdata_int32%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache_i4
+ ENDIF
+
+ IF (present(rdata_real8)) THEN
+ CALL ncio_read_part_serial (file_mesh, dataname, (/jf0,if0/), (/jf1,if1/), dcache_r8)
+ dcache_r8 = transpose(dcache_r8)
+
+ rdata_real8%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache_r8
+ ENDIF
+ ENDIF
+ ENDIF
+
+ ENDDO
+
+ ELSE
+
+ ! remove suffix ".nc"
+ path_mesh = file_meshdata_in(1:len_trim(file_meshdata_in)-3)
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ IF (present(rdata_int32)) THEN
+ IF (present(spv_i4)) THEN
+ rdata_int32%blk(iblk,jblk)%val(:,:) = spv_i4
+ ELSE
+ rdata_int32%blk(iblk,jblk)%val(:,:) = 0
+ ENDIF
+ ENDIF
+
+ IF (present(rdata_real8)) THEN
+ IF (present(spv_r8)) THEN
+ rdata_real8%blk(iblk,jblk)%val(:,:) = spv_r8
+ ELSE
+ rdata_real8%blk(iblk,jblk)%val(:,:) = -1.e36_r8
+ ENDIF
+ ENDIF
+
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+ IF (ieast > nxhglb) ieast = ieast - nxhglb
+
+ ibox = grid%xdsp(iblk)/nxhbox + 1
+ jbox = grid%ydsp(jblk)/nyhbox + 1
+
+ DO WHILE (.true.)
+
+ xdsp = (ibox-1) * nxhbox
+ ydsp = (jbox-1) * nyhbox
+
+ j0 = max(inorth-ydsp, 1)
+ j1 = min(isouth-ydsp, nyhbox)
+ jl0 = j0 + ydsp - inorth + 1
+ jl1 = j1 + ydsp - inorth + 1
+
+ IF (ieast >= iwest) THEN
+ i0 = max(iwest-xdsp, 1)
+ i1 = min(ieast-xdsp, nxhbox)
+ il0 = i0 + xdsp - iwest + 1
+ il1 = i1 + xdsp - iwest + 1
+ ELSE
+ IF (iwest <= xdsp+nxhbox) THEN
+ i0 = max(iwest-xdsp, 1)
+ i1 = nxhbox
+ il0 = i0 + xdsp - iwest + 1
+ il1 = i1 + xdsp - iwest + 1
+ ELSE
+ i0 = 1
+ i1 = min(ieast-xdsp, nxhbox)
+ il0 = i0 + xdsp + nxhglb - iwest + 1
+ il1 = i1 + xdsp + nxhglb - iwest + 1
+ ENDIF
+ ENDIF
+
+ IF (jbox <= 18) THEN
+ write (pre1,'(A1,I2.2)') 'n', (18-jbox)*5
+ ELSE
+ write (pre1,'(A1,I2.2)') 's', (jbox-18)*5
+ ENDIF
+
+ IF (ibox <= 36) THEN
+ write (pre2,'(A1,I3.3)') 'w', (37-ibox)*5
+ ELSE
+ write (pre2,'(A1,I3.3)') 'e', (ibox-37)*5
+ ENDIF
+
+ file_mesh = trim(path_mesh) // '/' // trim(pre1) // trim(pre2) // '.nc'
+
+ inquire(file=file_mesh, exist=fexists)
+ IF (fexists) THEN
+ IF (present(rdata_int32)) THEN
+ CALL ncio_read_part_serial (file_mesh, dataname, (/j0,i0/), (/j1,i1/), dcache_i4)
+ dcache_i4 = transpose(dcache_i4)
+
+ rdata_int32%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache_i4
+ ENDIF
+
+ IF (present(rdata_real8)) THEN
+ CALL ncio_read_part_serial (file_mesh, dataname, (/j0,i0/), (/j1,i1/), dcache_r8)
+ dcache_r8 = transpose(dcache_r8)
+
+ rdata_real8%blk(iblk,jblk)%val(il0:il1,jl0:jl1) = dcache_r8
+ ENDIF
+ ENDIF
+
+ IF ((ieast >= xdsp + 1) .and. (ieast <= xdsp + nxhbox)) THEN
+ IF (isouth <= ydsp + nyhbox) THEN
+ EXIT
+ ELSE
+ ibox = grid%xdsp(iblk)/nxhbox + 1
+ jbox = jbox + 1
+ ENDIF
+ ELSE
+ ibox = mod(ibox, nxhglb/nxhbox) + 1
+ ENDIF
+
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE catchment_data_read_general
+
+END MODULE MOD_CatchmentDataReadin
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_ComputePushData.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_ComputePushData.F90
new file mode 100644
index 0000000000..d810f957f0
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_ComputePushData.F90
@@ -0,0 +1,1136 @@
+#include
+
+MODULE MOD_ComputePushData
+!--------------------------------------------------------------------------------
+! DESCRIPTION:
+!--------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ ! -- Data Type : push data between ranks --
+ type :: compute_pushdata_type
+
+ integer :: num_req_uniq
+
+ integer, allocatable :: addr_single (:)
+
+ integer, allocatable :: addr_multi (:,:)
+ real(r8), allocatable :: area_multi (:,:)
+ real(r8), allocatable :: sum_area (:)
+
+ ! data is on the same processor
+ integer :: nself
+ integer, allocatable :: self_from (:)
+ integer, allocatable :: self_to (:)
+#ifdef COLM_PARALLEL
+ ! data is on other processors
+ integer, allocatable :: n_to_other (:)
+ integer, allocatable :: n_from_other (:)
+ type(pointer_int32_1d), allocatable :: to_other (:)
+ type(pointer_int32_1d), allocatable :: other_to (:)
+#endif
+ CONTAINS
+ final :: compute_pushdata_free_mem
+ END type compute_pushdata_type
+
+
+ ! -- Data Type : remap data on ranks --
+ type :: compute_remapdata_type
+
+ integer :: num_grid
+ integer, allocatable :: ilon_me (:)
+ integer, allocatable :: ilat_me (:)
+ integer, allocatable :: ids_me (:)
+
+ integer :: npset
+ real(r8), allocatable :: sum_area (:)
+ integer, allocatable :: npart (:)
+ type(pointer_int32_1d), allocatable :: part_to (:) !
+ type(pointer_real8_1d), allocatable :: areapart (:) ! intersection area
+
+ CONTAINS
+ final :: compute_remapdata_free_mem
+ END type compute_remapdata_type
+
+ ! -- public subroutines --
+ INTERFACE build_compute_pushdata
+ MODULE procedure build_compute_pushdata_single
+ MODULE procedure build_compute_pushdata_multi
+ END INTERFACE build_compute_pushdata
+
+ PUBLIC :: build_compute_pushdata_subset
+
+ PUBLIC :: build_compute_remapdata
+
+ INTERFACE compute_push_data
+ MODULE procedure compute_push_data_single_real8
+ MODULE procedure compute_push_data_single_int32
+ MODULE procedure compute_push_data_multi_real8
+ END INTERFACE compute_push_data
+
+ INTERFACE compute_remap_data_pset2grid
+ MODULE procedure compute_remap_data_pset2grid_real8
+ END INTERFACE compute_remap_data_pset2grid
+
+ INTERFACE compute_remap_data_grid2pset
+ MODULE procedure compute_remap_data_grid2pset_real8
+ END INTERFACE compute_remap_data_grid2pset
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE build_compute_pushdata_uniq (num_me, ids_me, n_req_uniq, ids_req_uniq, pushdata)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: num_me, ids_me (:)
+ integer, intent(in) :: n_req_uniq, ids_req_uniq (:)
+ type(compute_pushdata_type), intent(inout) :: pushdata
+
+ ! Local Variables
+ integer, allocatable :: ids_me_sorted(:), order_ids(:), self_from(:)
+#ifdef COLM_PARALLEL
+ integer, allocatable :: ids(:), loc_from_me(:), loc_from_other(:)
+ integer :: request(3)
+#endif
+ integer :: i, iloc, irank, jrank, n_req_other
+
+
+ IF (p_is_compute) THEN
+
+ allocate (ids_me_sorted (num_me))
+ allocate (order_ids (num_me))
+ IF (num_me > 0) THEN
+ ids_me_sorted = ids_me
+ order_ids = (/(i, i = 1, num_me)/)
+ CALL quicksort (num_me, ids_me_sorted, order_ids)
+ ENDIF
+
+ pushdata%nself = 0
+
+ IF (n_req_uniq > 0) THEN
+ allocate (self_from (n_req_uniq))
+ self_from(:) = -1
+
+ DO i = 1, n_req_uniq
+ iloc = find_in_sorted_list1 (ids_req_uniq(i), num_me, ids_me_sorted)
+ IF (iloc > 0) THEN
+ self_from(i) = order_ids(iloc)
+ ENDIF
+ ENDDO
+
+ pushdata%nself = count(self_from > 0)
+ IF (pushdata%nself > 0) THEN
+ allocate (pushdata%self_from (pushdata%nself))
+ allocate (pushdata%self_to (pushdata%nself))
+ pushdata%self_from = pack(self_from, self_from > 0)
+ pushdata%self_to = pack((/(i,i=1,n_req_uniq)/), self_from > 0)
+ ENDIF
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ CALL mpi_barrier (p_comm_compute, p_err)
+
+ allocate (pushdata%n_to_other (0:p_np_compute-1))
+ allocate (pushdata%to_other (0:p_np_compute-1))
+
+ allocate (pushdata%n_from_other (0:p_np_compute-1))
+ allocate (pushdata%other_to (0:p_np_compute-1))
+
+ pushdata%n_to_other (:) = 0
+ pushdata%n_from_other(:) = 0
+
+ IF (n_req_uniq > 0) allocate (loc_from_other (n_req_uniq))
+
+ irank = modulo(p_iam_compute+1, p_np_compute)
+ jrank = modulo(p_iam_compute-1, p_np_compute)
+ DO WHILE (irank /= p_iam_compute)
+
+ CALL mpi_isend (n_req_uniq, 1, MPI_INTEGER, jrank, 10, &
+ p_comm_compute, request(1), p_err)
+
+ IF (n_req_uniq > 0) THEN
+ CALL mpi_isend(ids_req_uniq, n_req_uniq, MPI_INTEGER, jrank, 11, &
+ p_comm_compute, request(2), p_err)
+ ENDIF
+
+ CALL mpi_recv (n_req_other, 1, MPI_INTEGER, irank, 10, &
+ p_comm_compute, p_stat, p_err)
+
+ IF (n_req_other > 0) THEN
+
+ allocate (ids (n_req_other))
+ CALL mpi_recv (ids, n_req_other, MPI_INTEGER, irank, 11, &
+ p_comm_compute, p_stat, p_err)
+
+ allocate (loc_from_me (n_req_other))
+ loc_from_me(:) = -1
+
+ IF (num_me > 0) THEN
+ DO i = 1, n_req_other
+ iloc = find_in_sorted_list1 (ids(i), num_me, ids_me_sorted)
+ IF (iloc > 0) THEN
+ loc_from_me(i) = order_ids(iloc)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ pushdata%n_to_other(irank) = count(loc_from_me > 0)
+ IF (pushdata%n_to_other(irank) > 0) THEN
+ allocate (pushdata%to_other(irank)%val (pushdata%n_to_other(irank)))
+ pushdata%to_other(irank)%val = pack(loc_from_me, loc_from_me > 0)
+ ENDIF
+
+ CALL mpi_isend (loc_from_me, n_req_other, MPI_INTEGER, irank, 12, &
+ p_comm_compute, request(3), p_err)
+
+ ENDIF
+
+ IF (n_req_uniq > 0) THEN
+
+ CALL mpi_recv (loc_from_other, n_req_uniq, MPI_INTEGER, &
+ jrank, 12, p_comm_compute, p_stat, p_err)
+
+ pushdata%n_from_other(jrank) = count(loc_from_other > 0)
+ IF (pushdata%n_from_other(jrank) > 0) THEN
+ allocate (pushdata%other_to(jrank)%val (pushdata%n_from_other(jrank)))
+ pushdata%other_to(jrank)%val = pack((/(i,i=1,n_req_uniq)/), loc_from_other > 0)
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_wait(request(1), MPI_STATUS_IGNORE, p_err)
+ IF (n_req_uniq > 0) CALL mpi_wait(request(2), MPI_STATUSES_IGNORE, p_err)
+ IF (n_req_other > 0) CALL mpi_wait(request(3), MPI_STATUSES_IGNORE, p_err)
+
+ IF (allocated(ids )) deallocate(ids )
+ IF (allocated(loc_from_me)) deallocate(loc_from_me)
+
+ irank = modulo(irank+1, p_np_compute)
+ jrank = modulo(jrank-1, p_np_compute)
+ ENDDO
+
+ IF (allocated (loc_from_other)) deallocate (loc_from_other)
+
+ CALL mpi_barrier (p_comm_compute, p_err)
+#endif
+
+ IF (allocated(ids_me_sorted)) deallocate(ids_me_sorted)
+ IF (allocated(order_ids )) deallocate(order_ids )
+ IF (allocated(self_from )) deallocate(self_from )
+
+ ENDIF
+
+ END SUBROUTINE build_compute_pushdata_uniq
+
+ ! ----------
+ SUBROUTINE build_compute_pushdata_single (num_me, ids_me, num_req, ids_req, pushdata)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: num_me, ids_me (:)
+ integer, intent(in) :: num_req, ids_req (:)
+ type(compute_pushdata_type), intent(inout) :: pushdata
+
+ ! Local Variables
+ integer :: n_req_uniq, iloc, i
+ integer, allocatable :: ids_req_uniq (:)
+
+ IF (p_is_compute) THEN
+
+ n_req_uniq = 0
+
+ allocate (ids_req_uniq (num_req))
+ IF (num_req > 0) THEN
+ DO i = 1, size(ids_req)
+ CALL insert_into_sorted_list1 (ids_req(i), n_req_uniq, ids_req_uniq, iloc)
+ ENDDO
+
+ allocate (pushdata%addr_single (num_req))
+ DO i = 1, size(ids_req)
+ pushdata%addr_single(i) = &
+ find_in_sorted_list1 (ids_req(i), n_req_uniq, ids_req_uniq(1:n_req_uniq))
+ ENDDO
+ ENDIF
+
+ pushdata%num_req_uniq = n_req_uniq
+
+ CALL build_compute_pushdata_uniq ( &
+ num_me, ids_me, n_req_uniq, ids_req_uniq(1:n_req_uniq), pushdata)
+
+ IF (allocated (ids_req_uniq)) deallocate(ids_req_uniq)
+
+ ENDIF
+
+ END SUBROUTINE build_compute_pushdata_single
+
+ ! ----------
+ SUBROUTINE build_compute_pushdata_multi ( &
+ num_me, ids_me, num_req, ids_req, area_req, pushdata)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: num_me, ids_me (:)
+ integer, intent(in) :: num_req, ids_req (:,:)
+ real(r8), intent(in) :: area_req(:,:)
+ type(compute_pushdata_type), intent(inout) :: pushdata
+
+ ! Local Variables
+ integer :: ndim1, n_req_uniq, iloc, i, j, irank
+ integer, allocatable :: ids_req_uniq (:)
+ logical, allocatable :: id_found (:)
+
+ IF (p_is_compute) THEN
+
+ n_req_uniq = 0
+
+ ndim1 = size(ids_req,1)
+ allocate (ids_req_uniq (ndim1*num_req))
+
+ IF (num_req > 0) THEN
+
+ DO j = 1, num_req
+ DO i = 1, ndim1
+ CALL insert_into_sorted_list1 (ids_req(i,j), n_req_uniq, ids_req_uniq, iloc)
+ ENDDO
+ ENDDO
+
+ allocate (pushdata%addr_multi (ndim1,num_req))
+
+ DO j = 1, num_req
+ DO i = 1, ndim1
+ pushdata%addr_multi(i,j) = &
+ find_in_sorted_list1 (ids_req(i,j), n_req_uniq, ids_req_uniq(1:n_req_uniq))
+ ENDDO
+ ENDDO
+ ENDIF
+
+ pushdata%num_req_uniq = n_req_uniq
+
+ CALL build_compute_pushdata_uniq ( &
+ num_me, ids_me, n_req_uniq, ids_req_uniq(1:n_req_uniq), pushdata)
+
+ IF (num_req > 0) THEN
+ allocate (pushdata%area_multi (ndim1,num_req))
+ allocate (pushdata%sum_area (num_req))
+
+ pushdata%area_multi = area_req
+
+ WHERE ((area_req <= 0.) .or. (ids_req <= 0))
+ pushdata%area_multi = 0.
+ END WHERE
+
+ allocate (id_found (n_req_uniq))
+ id_found(:) = .false.
+
+ IF (pushdata%nself > 0) id_found(pushdata%self_to) = .true.
+#ifdef COLM_PARALLEL
+ DO irank = 0, p_np_compute-1
+ IF (pushdata%n_from_other(irank) > 0) THEN
+ id_found(pushdata%other_to(irank)%val) = .true.
+ ENDIF
+ ENDDO
+#endif
+
+ DO j = 1, num_req
+ DO i = 1, ndim1
+ IF (.not. id_found(pushdata%addr_multi(i,j))) then
+ pushdata%area_multi(i,j) = 0.
+ ENDIF
+ ENDDO
+ ENDDO
+
+ pushdata%sum_area = sum(pushdata%area_multi, dim = 1)
+
+ deallocate (id_found)
+ ENDIF
+
+ IF (allocated (ids_req_uniq)) deallocate(ids_req_uniq)
+
+ ENDIF
+
+ END SUBROUTINE build_compute_pushdata_multi
+
+ ! ----------
+ SUBROUTINE build_compute_pushdata_subset ( &
+ num_me, num_req, pushdata_in, subset_in, pushdata_out, subset_out, numsubset)
+
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ integer, intent(in) :: num_me
+ integer, intent(in) :: num_req
+
+ type(compute_pushdata_type), intent(in) :: pushdata_in
+ type(subset_type), intent(in) :: subset_in
+
+ type(compute_pushdata_type), intent(inout) :: pushdata_out
+ type(subset_type), optional, intent(inout) :: subset_out
+ integer, optional, intent(inout) :: numsubset
+
+ ! Local Variables
+ integer :: i, j, ii, jj, idsp, jdsp, kdsp, nsub, irank
+ integer, allocatable :: nsub_me (:), nsub_req(:), nsub_req_uniq(:)
+ integer, allocatable :: subdsp_me(:), subdsp_req_uniq(:)
+
+ IF (p_is_compute) THEN
+
+ IF (num_me > 0) THEN
+ allocate (nsub_me (num_me))
+ nsub_me = subset_in%subend - subset_in%substt + 1
+ ENDIF
+
+ IF (num_req > 0) THEN
+ allocate (nsub_req (num_req))
+ ENDIF
+
+ CALL compute_push_data (pushdata_in, nsub_me, nsub_req, 0)
+
+ IF (present(subset_out) .and. present(numsubset)) THEN
+ IF (num_req > 0) THEN
+ allocate (subset_out%substt (num_req))
+ allocate (subset_out%subend (num_req))
+
+ idsp = 0
+ DO i = 1, num_req
+ IF (nsub_req(i) == 0) THEN
+ subset_out%substt(i) = 0
+ subset_out%subend(i) = -1
+ ELSE
+ subset_out%substt(i) = idsp + 1
+ subset_out%subend(i) = idsp + nsub_req(i)
+ ENDIF
+ idsp = idsp + nsub_req(i)
+ ENDDO
+
+ numsubset = idsp
+ ELSE
+ numsubset = 0
+ ENDIF
+ ENDIF
+
+ IF (num_me > 0) THEN
+ allocate (subdsp_me (num_me))
+ idsp = 0
+ DO i = 1, num_me
+ IF (nsub_me(i) > 0) THEN
+ subdsp_me(i) = idsp
+ idsp = idsp + nsub_me(i)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ pushdata_out%num_req_uniq = 0
+ IF (pushdata_in%num_req_uniq > 0) THEN
+
+ allocate (nsub_req_uniq (pushdata_in%num_req_uniq))
+ allocate (subdsp_req_uniq (pushdata_in%num_req_uniq))
+
+ nsub_req_uniq(:) = 0
+ DO i = 1, size(pushdata_in%addr_single)
+ nsub_req_uniq(pushdata_in%addr_single(i)) = nsub_req(i)
+ ENDDO
+
+ idsp = 0
+ DO i = 1, pushdata_in%num_req_uniq
+ IF (nsub_req_uniq(i) > 0) THEN
+ subdsp_req_uniq(i) = idsp
+ idsp = idsp + nsub_req_uniq(i)
+ ENDIF
+ ENDDO
+
+ pushdata_out%num_req_uniq = sum(nsub_req_uniq)
+ ENDIF
+
+
+ IF (pushdata_out%num_req_uniq > 0) THEN
+ allocate (pushdata_out%addr_single (sum(nsub_req)))
+
+ idsp = 0
+ DO i = 1, num_req
+ IF (nsub_req(i) > 0) THEN
+ jdsp = subdsp_req_uniq(pushdata_in%addr_single(i))
+ pushdata_out%addr_single(idsp+1:idsp+nsub_req(i)) = &
+ (/(jj, jj=jdsp+1,jdsp+nsub_req(i))/)
+ idsp = idsp + nsub_req(i)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ pushdata_out%nself = 0
+ DO i = 1, pushdata_in%nself
+ pushdata_out%nself = pushdata_out%nself + nsub_me(pushdata_in%self_from(i))
+ ENDDO
+
+ IF (pushdata_out%nself > 0) THEN
+ allocate (pushdata_out%self_from (pushdata_out%nself))
+ allocate (pushdata_out%self_to (pushdata_out%nself))
+
+ kdsp = 0
+ DO i = 1, pushdata_in%nself
+ IF (nsub_me(pushdata_in%self_from(i)) > 0) THEN
+ nsub = nsub_me(pushdata_in%self_from(i))
+ idsp = subdsp_me (pushdata_in%self_from(i))
+ jdsp = subdsp_req_uniq(pushdata_in%self_to (i))
+ pushdata_out%self_from(kdsp+1:kdsp+nsub) = (/(ii, ii=idsp+1,idsp+nsub)/)
+ pushdata_out%self_to (kdsp+1:kdsp+nsub) = (/(jj, jj=jdsp+1,jdsp+nsub)/)
+ kdsp = kdsp + nsub
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ allocate (pushdata_out%n_to_other (0:p_np_compute-1))
+ allocate (pushdata_out%to_other (0:p_np_compute-1))
+
+ DO irank = 0, p_np_compute-1
+
+ pushdata_out%n_to_other(irank) = 0
+ DO i = 1, pushdata_in%n_to_other(irank)
+ pushdata_out%n_to_other(irank) = pushdata_out%n_to_other(irank) &
+ + nsub_me(pushdata_in%to_other(irank)%val(i))
+ ENDDO
+
+ IF (pushdata_out%n_to_other(irank) > 0) THEN
+ allocate (pushdata_out%to_other(irank)%val (pushdata_out%n_to_other(irank)))
+ kdsp = 0
+ DO i = 1, pushdata_in%n_to_other(irank)
+ IF (nsub_me(pushdata_in%to_other(irank)%val(i)) > 0) THEN
+ nsub = nsub_me (pushdata_in%to_other(irank)%val(i))
+ idsp = subdsp_me(pushdata_in%to_other(irank)%val(i))
+ pushdata_out%to_other(irank)%val(kdsp+1:kdsp+nsub) = (/(ii, ii=idsp+1,idsp+nsub)/)
+ kdsp = kdsp + nsub
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ENDDO
+
+ allocate (pushdata_out%n_from_other (0:p_np_compute-1))
+ allocate (pushdata_out%other_to (0:p_np_compute-1))
+
+ DO irank = 0, p_np_compute-1
+ pushdata_out%n_from_other(irank) = 0
+ DO i = 1, pushdata_in%n_from_other(irank)
+ pushdata_out%n_from_other(irank) = pushdata_out%n_from_other(irank) &
+ + nsub_req_uniq(pushdata_in%other_to(irank)%val(i))
+ ENDDO
+
+ IF (pushdata_out%n_from_other(irank) > 0) THEN
+ allocate (pushdata_out%other_to(irank)%val (pushdata_out%n_from_other(irank)))
+ kdsp = 0
+ DO i = 1, pushdata_in%n_from_other(irank)
+ IF (nsub_req_uniq(pushdata_in%other_to(irank)%val(i)) > 0) THEN
+ nsub = nsub_req_uniq (pushdata_in%other_to(irank)%val(i))
+ idsp = subdsp_req_uniq(pushdata_in%other_to(irank)%val(i))
+ pushdata_out%other_to(irank)%val(kdsp+1:kdsp+nsub) = (/(ii, ii=idsp+1,idsp+nsub)/)
+ kdsp = kdsp + nsub
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+#endif
+
+ IF (allocated (nsub_me )) deallocate (nsub_me )
+ IF (allocated (nsub_req )) deallocate (nsub_req )
+ IF (allocated (nsub_req_uniq )) deallocate (nsub_req_uniq )
+ IF (allocated (subdsp_me )) deallocate (subdsp_me )
+ IF (allocated (subdsp_req_uniq)) deallocate (subdsp_req_uniq)
+
+ ENDIF
+
+ END SUBROUTINE build_compute_pushdata_subset
+
+ ! ----------
+ SUBROUTINE build_compute_remapdata (pixelset, grid, remapdata)
+
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_SpatialMapping
+ IMPLICIT NONE
+
+ type(pixelset_type), intent(in) :: pixelset
+ type(grid_type), intent(in) :: grid
+
+ type(compute_remapdata_type), intent(inout) :: remapdata
+
+ ! Local Variables
+ type(spatial_mapping_type) :: mapping
+ integer, allocatable :: ilon_me(:), ilat_me(:)
+ integer :: ngrid, iproc, ig, iloc, iset, ipart
+
+
+ CALL mapping%build_arealweighted (grid, pixelset)
+
+ IF (p_is_compute) THEN
+
+ ngrid = 0
+ DO iproc = 0, p_np_active-1
+ ngrid = ngrid + mapping%glist(iproc)%ng
+ ENDDO
+
+ IF (ngrid > 0) THEN
+ allocate (ilon_me (ngrid))
+ allocate (ilat_me (ngrid))
+ ENDIF
+
+ ngrid = 0
+ DO iproc = 0, p_np_active-1
+ DO ig = 1, mapping%glist(iproc)%ng
+ CALL insert_into_sorted_list2 ( &
+ mapping%glist(iproc)%ilon(ig), mapping%glist(iproc)%ilat(ig), &
+ ngrid, ilon_me, ilat_me, iloc)
+ ENDDO
+ ENDDO
+
+ remapdata%num_grid = ngrid
+
+ IF (ngrid > 0) THEN
+ allocate (remapdata%ilon_me (ngrid))
+ allocate (remapdata%ilat_me (ngrid))
+ allocate (remapdata%ids_me (ngrid))
+ remapdata%ilon_me = ilon_me(1:ngrid)
+ remapdata%ilat_me = ilat_me(1:ngrid)
+ remapdata%ids_me = (ilat_me(1:ngrid)-1) * grid%nlon + ilon_me(1:ngrid)
+ ENDIF
+
+ remapdata%npset = mapping%npset
+
+ IF (remapdata%npset > 0) THEN
+
+ allocate (remapdata%sum_area (remapdata%npset))
+ allocate (remapdata%npart (remapdata%npset))
+ allocate (remapdata%part_to (remapdata%npset))
+ allocate (remapdata%areapart (remapdata%npset))
+
+ remapdata%npart = mapping%npart
+
+ DO iset = 1, remapdata%npset
+ IF (remapdata%npart(iset) > 0) THEN
+ allocate (remapdata%part_to(iset)%val (remapdata%npart(iset)))
+ allocate (remapdata%areapart(iset)%val (remapdata%npart(iset)))
+ ENDIF
+
+ DO ipart = 1, remapdata%npart(iset)
+ iproc = mapping%address(iset)%val(1,ipart)
+ iloc = mapping%address(iset)%val(2,ipart)
+ remapdata%part_to(iset)%val(ipart) = find_in_sorted_list2 ( &
+ mapping%glist(iproc)%ilon(iloc), mapping%glist(iproc)%ilat(iloc), ngrid, ilon_me, ilat_me)
+ ! from km^2 to m^2
+ remapdata%areapart(iset)%val(ipart) = mapping%areapart(iset)%val(ipart) * 1.e6
+ ENDDO
+
+ IF (remapdata%npart(iset) > 0) THEN
+ remapdata%sum_area(iset) = sum(remapdata%areapart(iset)%val)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (allocated(ilon_me)) deallocate(ilon_me)
+ IF (allocated(ilat_me)) deallocate(ilat_me)
+
+ ENDIF
+
+ END SUBROUTINE build_compute_remapdata
+
+ ! ----------
+ SUBROUTINE compute_push_data_uniq_real8 ( &
+ pushdata, vec_send, vec_recv, fillvalue)
+
+ IMPLICIT NONE
+
+ type(compute_pushdata_type), intent(in) :: pushdata
+
+ real(r8), intent(in) , optional :: vec_send (:)
+ real(r8), intent(inout), optional :: vec_recv (:)
+ real(r8), intent(in) , optional :: fillvalue
+
+ ! Local Variables
+ integer :: ndatasend
+ integer, allocatable :: req_send (:)
+ real(r8), allocatable :: sendcache (:)
+
+ integer :: ndatarecv
+ integer, allocatable :: req_recv (:)
+ real(r8), allocatable :: recvcache (:)
+
+ integer :: irank, iproc, idsp, istt, iend, i, i_to
+
+
+ IF (p_is_compute) THEN
+
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv = fillvalue
+ ENDIF
+
+ IF (pushdata%nself > 0) THEN
+ vec_recv(pushdata%self_to) = vec_send(pushdata%self_from)
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ ndatasend = sum(pushdata%n_to_other)
+ IF (ndatasend > 0) THEN
+
+ allocate (sendcache(ndatasend))
+ allocate (req_send (count(pushdata%n_to_other > 0)))
+
+ iproc = 0
+ idsp = 0
+ DO irank = 0, p_np_compute-1
+ IF (pushdata%n_to_other(irank) > 0) THEN
+ iproc = iproc + 1
+ istt = idsp + 1
+ iend = idsp + pushdata%n_to_other(irank)
+
+ sendcache(istt:iend) = vec_send(pushdata%to_other(irank)%val)
+ CALL mpi_isend(sendcache(istt:iend), pushdata%n_to_other(irank), MPI_REAL8, &
+ irank, 101, p_comm_compute, req_send(iproc), p_err)
+
+ idsp = iend
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ndatarecv = sum(pushdata%n_from_other)
+ IF (ndatarecv > 0) THEN
+
+ allocate (recvcache(ndatarecv))
+ allocate (req_recv (count(pushdata%n_from_other > 0)))
+
+ iproc = 0
+ idsp = 0
+ DO irank = 0, p_np_compute-1
+ IF (pushdata%n_from_other(irank) > 0) THEN
+ iproc = iproc + 1
+ istt = idsp + 1
+ iend = idsp + pushdata%n_from_other(irank)
+
+ CALL mpi_irecv(recvcache(istt:iend), pushdata%n_from_other(irank), MPI_REAL8, &
+ irank, 101, p_comm_compute, req_recv(iproc), p_err)
+
+ idsp = iend
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (ndatarecv > 0) THEN
+
+ CALL mpi_waitall(size(req_recv), req_recv, MPI_STATUSES_IGNORE, p_err)
+
+ idsp = 0
+ DO irank = 0, p_np_compute-1
+ DO i = 1, pushdata%n_from_other(irank)
+
+ IF (recvcache(idsp+i) /= fillvalue) THEN
+ i_to = pushdata%other_to(irank)%val(i)
+ IF (vec_recv(i_to) == fillvalue) THEN
+ vec_recv(i_to) = recvcache(idsp+i)
+ ELSE
+ vec_recv(i_to) = vec_recv(i_to) + recvcache(idsp+i)
+ ENDIF
+ ENDIF
+
+ ENDDO
+ idsp = idsp + pushdata%n_from_other(irank)
+ ENDDO
+
+ ENDIF
+
+ IF (ndatasend > 0) THEN
+ CALL mpi_waitall(size(req_send), req_send, MPI_STATUSES_IGNORE, p_err)
+ ENDIF
+
+ IF (allocated(req_send )) deallocate(req_send )
+ IF (allocated(sendcache)) deallocate(sendcache)
+ IF (allocated(req_recv )) deallocate(req_recv )
+ IF (allocated(recvcache)) deallocate(recvcache)
+#endif
+
+ ENDIF
+
+ END SUBROUTINE compute_push_data_uniq_real8
+
+ ! ----------
+ SUBROUTINE compute_push_data_uniq_int32 ( &
+ pushdata, vec_send, vec_recv, fillvalue)
+
+ IMPLICIT NONE
+
+ type(compute_pushdata_type), intent(in) :: pushdata
+
+ integer, intent(in) , optional :: vec_send (:)
+ integer, intent(inout), optional :: vec_recv (:)
+ integer, intent(in) , optional :: fillvalue
+
+ ! Local Variables
+ integer :: ndatasend
+ integer, allocatable :: req_send (:)
+ integer, allocatable :: sendcache (:)
+
+ integer :: ndatarecv
+ integer, allocatable :: req_recv (:)
+ integer, allocatable :: recvcache (:)
+
+ integer :: irank, iproc, idsp, istt, iend, i, i_to
+
+
+ IF (p_is_compute) THEN
+
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv = fillvalue
+ ENDIF
+
+ IF (pushdata%nself > 0) THEN
+ vec_recv(pushdata%self_to) = vec_send(pushdata%self_from)
+ ENDIF
+
+#ifdef COLM_PARALLEL
+ ndatasend = sum(pushdata%n_to_other)
+ IF (ndatasend > 0) THEN
+
+ allocate (sendcache(ndatasend))
+ allocate (req_send (count(pushdata%n_to_other > 0)))
+
+ iproc = 0
+ idsp = 0
+ DO irank = 0, p_np_compute-1
+ IF (pushdata%n_to_other(irank) > 0) THEN
+ iproc = iproc + 1
+ istt = idsp + 1
+ iend = idsp + pushdata%n_to_other(irank)
+
+ sendcache(istt:iend) = vec_send(pushdata%to_other(irank)%val)
+ CALL mpi_isend(sendcache(istt:iend), pushdata%n_to_other(irank), MPI_INTEGER, &
+ irank, 101, p_comm_compute, req_send(iproc), p_err)
+
+ idsp = iend
+ ENDIF
+ ENDDO
+ ENDIF
+
+ ndatarecv = sum(pushdata%n_from_other)
+ IF (ndatarecv > 0) THEN
+
+ allocate (recvcache(ndatarecv))
+ allocate (req_recv (count(pushdata%n_from_other > 0)))
+
+ iproc = 0
+ idsp = 0
+ DO irank = 0, p_np_compute-1
+ IF (pushdata%n_from_other(irank) > 0) THEN
+ iproc = iproc + 1
+ istt = idsp + 1
+ iend = idsp + pushdata%n_from_other(irank)
+
+ CALL mpi_irecv(recvcache(istt:iend), pushdata%n_from_other(irank), MPI_INTEGER, &
+ irank, 101, p_comm_compute, req_recv(iproc), p_err)
+
+ idsp = iend
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (ndatarecv > 0) THEN
+
+ CALL mpi_waitall(size(req_recv), req_recv, MPI_STATUSES_IGNORE, p_err)
+
+ idsp = 0
+ DO irank = 0, p_np_compute-1
+ DO i = 1, pushdata%n_from_other(irank)
+
+ IF (recvcache(idsp+i) /= fillvalue) THEN
+ i_to = pushdata%other_to(irank)%val(i)
+ IF (vec_recv(i_to) == fillvalue) THEN
+ vec_recv(i_to) = recvcache(idsp+i)
+ ELSE
+ vec_recv(i_to) = vec_recv(i_to) + recvcache(idsp+i)
+ ENDIF
+ ENDIF
+
+ ENDDO
+ idsp = idsp + pushdata%n_from_other(irank)
+ ENDDO
+
+ ENDIF
+
+ IF (ndatasend > 0) THEN
+ CALL mpi_waitall(size(req_send), req_send, MPI_STATUSES_IGNORE, p_err)
+ ENDIF
+
+ IF (allocated(req_send )) deallocate(req_send )
+ IF (allocated(sendcache)) deallocate(sendcache)
+ IF (allocated(req_recv )) deallocate(req_recv )
+ IF (allocated(recvcache)) deallocate(recvcache)
+#endif
+
+ ENDIF
+
+ END SUBROUTINE compute_push_data_uniq_int32
+
+ ! ----------
+ SUBROUTINE compute_push_data_single_real8 (pushdata, vec_send, vec_recv, fillvalue)
+
+ IMPLICIT NONE
+
+ type(compute_pushdata_type) :: pushdata
+
+ real(r8), intent(in) :: vec_send (:)
+ real(r8), intent(inout) :: vec_recv (:)
+ real(r8), intent(in) :: fillvalue
+
+ ! Local Variables
+ real(r8), allocatable :: vec_recv_uniq (:)
+
+ IF (p_is_compute) THEN
+
+ ! Always allocate (zero-length if no requests) to avoid passing
+ ! unallocated array to compute_push_data_uniq_real8.
+ allocate (vec_recv_uniq (pushdata%num_req_uniq))
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv_uniq(:) = fillvalue
+ ENDIF
+
+ CALL compute_push_data_uniq_real8 (pushdata, vec_send, vec_recv_uniq, fillvalue)
+
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv = vec_recv_uniq(pushdata%addr_single)
+ ENDIF
+ deallocate (vec_recv_uniq)
+
+ ENDIF
+
+ END SUBROUTINE compute_push_data_single_real8
+
+ ! ----------
+ SUBROUTINE compute_push_data_multi_real8 (pushdata, vec_send, vec_recv, fillvalue, mode)
+
+ IMPLICIT NONE
+
+ type(compute_pushdata_type) :: pushdata
+
+ real(r8), intent(in) :: vec_send (:)
+ real(r8), intent(inout) :: vec_recv (:)
+ real(r8), intent(in) :: fillvalue
+
+ character(len=*), intent(in) :: mode
+
+ ! Local Variables
+ real(r8), allocatable :: vec_recv_uniq (:)
+ integer :: i, j
+ real(r8) :: val, sumarea
+
+ IF (p_is_compute) THEN
+
+ ! Always allocate (zero-length if no requests) to avoid passing
+ ! unallocated array to compute_push_data_uniq_real8.
+ allocate (vec_recv_uniq (pushdata%num_req_uniq))
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv_uniq(:) = fillvalue
+ ENDIF
+
+ CALL compute_push_data_uniq_real8 (pushdata, vec_send, vec_recv_uniq, fillvalue)
+
+ IF (pushdata%num_req_uniq > 0) THEN
+
+ vec_recv(:) = fillvalue
+
+ DO j = 1, size(pushdata%addr_multi,2)
+
+ sumarea = 0.
+
+ DO i = 1, size(pushdata%addr_multi,1)
+ val = vec_recv_uniq(pushdata%addr_multi(i,j))
+ IF (val /= fillvalue) THEN
+ IF (vec_recv(j) == fillvalue) THEN
+ vec_recv(j) = val * pushdata%area_multi(i,j)
+ ELSE
+ vec_recv(j) = vec_recv(j) + val * pushdata%area_multi(i,j)
+ ENDIF
+ sumarea = sumarea + pushdata%area_multi(i,j)
+ ENDIF
+ ENDDO
+
+ IF (trim(mode) == 'average') THEN
+ IF (vec_recv(j) /= fillvalue) THEN
+ vec_recv(j) = vec_recv(j) / sumarea
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+ deallocate (vec_recv_uniq)
+
+ ENDIF
+
+ END SUBROUTINE compute_push_data_multi_real8
+
+ ! ----------
+ SUBROUTINE compute_push_data_single_int32 (pushdata, vec_send, vec_recv, fillvalue)
+
+ IMPLICIT NONE
+
+ type(compute_pushdata_type) :: pushdata
+
+ integer, intent(in) :: vec_send (:)
+ integer, intent(inout) :: vec_recv (:)
+ integer, intent(in) :: fillvalue
+
+ ! Local Variables
+ integer, allocatable :: vec_recv_uniq (:)
+
+ IF (p_is_compute) THEN
+
+ allocate (vec_recv_uniq (pushdata%num_req_uniq))
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv_uniq(:) = fillvalue
+ ENDIF
+
+ CALL compute_push_data_uniq_int32 (pushdata, vec_send, vec_recv_uniq, fillvalue)
+
+ IF (pushdata%num_req_uniq > 0) THEN
+ vec_recv = vec_recv_uniq(pushdata%addr_single)
+ ENDIF
+ deallocate (vec_recv_uniq)
+
+ ENDIF
+
+ END SUBROUTINE compute_push_data_single_int32
+
+ ! ---------
+ SUBROUTINE compute_remap_data_pset2grid_real8 (remapdata, vec_in, vec_out, fillvalue, filter)
+
+ IMPLICIT NONE
+
+ type(compute_remapdata_type), intent(in) :: remapdata
+
+ real(r8), intent(in) :: vec_in (:)
+ real(r8), intent(inout) :: vec_out(:)
+ real(r8), intent(in) :: fillvalue
+ logical, intent(in) :: filter (:)
+
+ ! Local Variables
+ integer :: iset, ipart, iloc
+ real(r8) :: area
+
+
+ IF (p_is_compute) THEN
+ IF (remapdata%num_grid > 0) THEN
+
+ vec_out(:) = fillvalue
+
+ DO iset = 1, remapdata%npset
+ IF (filter(iset) .and. (vec_in(iset) /= fillvalue)) THEN
+ DO ipart = 1, remapdata%npart(iset)
+
+ iloc = remapdata%part_to(iset)%val(ipart)
+ area = remapdata%areapart(iset)%val(ipart)
+
+ IF (vec_out(iloc) == fillvalue) THEN
+ vec_out(iloc) = vec_in(iset) * area
+ ELSE
+ vec_out(iloc) = vec_out(iloc) + vec_in(iset) * area
+ ENDIF
+
+ ENDDO
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE compute_remap_data_pset2grid_real8
+
+ ! ---------
+ SUBROUTINE compute_remap_data_grid2pset_real8 (remapdata, vec_in, vec_out, fillvalue, mode)
+
+ IMPLICIT NONE
+
+ type(compute_remapdata_type), intent(in) :: remapdata
+
+ real(r8), intent(in) :: vec_in (:)
+ real(r8), intent(inout) :: vec_out(:)
+ real(r8), intent(in) :: fillvalue
+
+ character(len=*), intent(in) :: mode
+
+ ! Local Variables
+ integer :: iset, ipart, iloc
+ real(r8) :: area, sumarea
+
+ IF (p_is_compute) THEN
+ IF (remapdata%npset > 0) THEN
+
+ vec_out(:) = fillvalue
+
+ DO iset = 1, remapdata%npset
+
+ sumarea = 0.
+
+ DO ipart = 1, remapdata%npart(iset)
+ iloc = remapdata%part_to(iset)%val(ipart)
+ area = remapdata%areapart(iset)%val(ipart)
+
+ IF (vec_in(iloc) /= fillvalue) THEN
+ IF (vec_out(iset) == fillvalue) THEN
+ vec_out(iset) = vec_in(iloc) * area
+ ELSE
+ vec_out(iset) = vec_out(iset) + vec_in(iloc) * area
+ ENDIF
+ sumarea = sumarea + area
+ ENDIF
+ ENDDO
+
+ IF (trim(mode) == 'average') THEN
+ IF (vec_out(iset) /= fillvalue) THEN
+ vec_out(iset) = vec_out(iset) / sumarea
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE compute_remap_data_grid2pset_real8
+
+ ! ---------
+ SUBROUTINE compute_pushdata_free_mem (this)
+
+ IMPLICIT NONE
+ type(compute_pushdata_type) :: this
+
+ IF (allocated(this%addr_single )) deallocate(this%addr_single )
+ IF (allocated(this%addr_multi )) deallocate(this%addr_multi )
+ IF (allocated(this%area_multi )) deallocate(this%area_multi )
+ IF (allocated(this%sum_area )) deallocate(this%sum_area )
+ IF (allocated(this%self_from )) deallocate(this%self_from )
+ IF (allocated(this%self_to )) deallocate(this%self_to )
+#ifdef COLM_PARALLEL
+ IF (allocated(this%n_to_other )) deallocate(this%n_to_other )
+ IF (allocated(this%n_from_other)) deallocate(this%n_from_other)
+ IF (allocated(this%to_other )) deallocate(this%to_other )
+ IF (allocated(this%other_to )) deallocate(this%other_to )
+#endif
+
+ END SUBROUTINE compute_pushdata_free_mem
+
+ ! ---------
+ SUBROUTINE compute_remapdata_free_mem (this)
+
+ IMPLICIT NONE
+ type(compute_remapdata_type) :: this
+
+ IF (allocated(this%ilon_me )) deallocate(this%ilon_me )
+ IF (allocated(this%ilat_me )) deallocate(this%ilat_me )
+ IF (allocated(this%ids_me )) deallocate(this%ids_me )
+ IF (allocated(this%npart )) deallocate(this%npart )
+ IF (allocated(this%sum_area)) deallocate(this%sum_area)
+ IF (allocated(this%part_to )) deallocate(this%part_to )
+ IF (allocated(this%areapart)) deallocate(this%areapart)
+
+ END SUBROUTINE compute_remapdata_free_mem
+
+END MODULE MOD_ComputePushData
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_DataType.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_DataType.F90
new file mode 100644
index 0000000000..54d355350e
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_DataType.F90
@@ -0,0 +1,709 @@
+#include
+
+MODULE MOD_DataType
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Definitions of data types used in CoLM.
+!
+! Most frequently used data types in CoLM are "blocked" data types
+! including,
+! 1. Blocked 2D data of 4-byte integer type;
+! 2. Blocked 2D data of 8-byte float type;
+! 3. Blocked 3D data of 8-byte float type;
+! 4. Blocked 4D data of 8-byte float type;
+!
+! Subroutines are used to
+! 1. allocate memory;
+! 2. flush data values;
+! 3. copy data;
+! 4. do linear transformation and interpolations.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+
+ ! ---- data types ----
+ !-------
+ type :: pointer_real8_1d
+ real(r8), allocatable :: val(:)
+ CONTAINS
+ final :: pointer_real8_1d_free_mem
+ END type pointer_real8_1d
+
+ !-------
+ type :: pointer_int8_1d
+ integer(1), allocatable :: val(:)
+ CONTAINS
+ final :: pointer_int8_1d_free_mem
+ END type pointer_int8_1d
+
+ !-------
+ type :: pointer_int32_1d
+ integer, allocatable :: val(:)
+ CONTAINS
+ final :: pointer_int32_1d_free_mem
+ END type pointer_int32_1d
+
+ !-------
+ type :: pointer_int64_1d
+ integer*8, allocatable :: val(:)
+ CONTAINS
+ final :: pointer_int64_1d_free_mem
+ END type pointer_int64_1d
+
+ !-------
+ type :: pointer_logic_1d
+ logical, allocatable :: val(:)
+ CONTAINS
+ final :: pointer_logic_1d_free_mem
+ END type pointer_logic_1d
+
+ !-------
+ type :: pointer_int32_2d
+ integer, allocatable :: val (:,:)
+ CONTAINS
+ final :: pointer_int32_2d_free_mem
+ END type pointer_int32_2d
+
+ type :: block_data_int32_2d
+ type(pointer_int32_2d), allocatable :: blk (:,:)
+ CONTAINS
+ final :: block_data_int32_2d_free_mem
+ END type block_data_int32_2d
+
+ !-------
+ type :: pointer_real8_2d
+ real(r8), allocatable :: val (:,:)
+ CONTAINS
+ final :: pointer_real8_2d_free_mem
+ END type pointer_real8_2d
+
+ type :: block_data_real8_2d
+ type(pointer_real8_2d), allocatable :: blk (:,:)
+ CONTAINS
+ final :: block_data_real8_2d_free_mem
+ END type block_data_real8_2d
+
+ !-------
+ type :: pointer_real8_3d
+ real(r8), allocatable :: val (:,:,:)
+ CONTAINS
+ final :: pointer_real8_3d_free_mem
+ END type pointer_real8_3d
+
+ type :: block_data_real8_3d
+ integer :: lb1, ub1
+ type(pointer_real8_3d), allocatable :: blk (:,:)
+ CONTAINS
+ final :: block_data_real8_3d_free_mem
+ END type block_data_real8_3d
+
+ !-------
+ type :: pointer_real8_4d
+ real(r8), allocatable :: val (:,:,:,:)
+ CONTAINS
+ final :: pointer_real8_4d_free_mem
+ END type pointer_real8_4d
+
+ type :: block_data_real8_4d
+ integer :: lb1, ub1, lb2, ub2
+ type(pointer_real8_4d), allocatable :: blk (:,:)
+ CONTAINS
+ final :: block_data_real8_4d_free_mem
+ END type block_data_real8_4d
+
+ ! ---- PUBLIC subroutines ----
+ !------
+ INTERFACE allocate_block_data
+ MODULE procedure allocate_block_data_int32_2d
+ MODULE procedure allocate_block_data_real8_2d
+ MODULE procedure allocate_block_data_real8_3d
+ MODULE procedure allocate_block_data_real8_4d
+ END INTERFACE allocate_block_data
+
+ !------
+ INTERFACE flush_block_data
+ MODULE procedure flush_block_data_int32_2d
+ MODULE procedure flush_block_data_real8_2d
+ MODULE procedure flush_block_data_real8_3d
+ MODULE procedure flush_block_data_real8_4d
+ END INTERFACE flush_block_data
+
+ !-----
+ PUBLIC :: block_data_linear_transform
+ PUBLIC :: block_data_copy
+ PUBLIC :: block_data_linear_interp
+ PUBLIC :: block_data_division
+
+CONTAINS
+
+ !------------------
+ SUBROUTINE pointer_real8_1d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_real8_1d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_real8_1d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_int8_1d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_int8_1d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_int8_1d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_int32_1d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_int32_1d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_int32_1d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_int64_1d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_int64_1d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_int64_1d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_logic_1d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_logic_1d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_logic_1d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_int32_2d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_int32_2d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_int32_2d_free_mem
+
+ !------------------
+ SUBROUTINE allocate_block_data_int32_2d (grid, gdata)
+
+ USE MOD_Grid
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ type(block_data_int32_2d), intent(out) :: gdata
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ allocate (gdata%blk (gblock%nxblk,gblock%nyblk))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ allocate (gdata%blk(iblk,jblk)%val (grid%xcnt(iblk), grid%ycnt(jblk)))
+ ENDDO
+
+ END SUBROUTINE allocate_block_data_int32_2d
+
+ !------------------
+ SUBROUTINE block_data_int32_2d_free_mem (this)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ type(block_data_int32_2d) :: this
+
+ ! Local variables
+ integer :: iblk, jblk
+
+ IF (allocated (this%blk)) THEN
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (allocated (this%blk(iblk,jblk)%val)) THEN
+ deallocate (this%blk(iblk,jblk)%val)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (this%blk)
+ ENDIF
+
+ END SUBROUTINE block_data_int32_2d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_real8_2d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_real8_2d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_real8_2d_free_mem
+
+ !------------------
+ SUBROUTINE allocate_block_data_real8_2d (grid, gdata)
+
+ USE MOD_Grid
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ type(block_data_real8_2d), intent(out) :: gdata
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ allocate (gdata%blk (gblock%nxblk,gblock%nyblk))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ allocate (gdata%blk(iblk,jblk)%val (grid%xcnt(iblk), grid%ycnt(jblk)))
+ ENDDO
+
+ END SUBROUTINE allocate_block_data_real8_2d
+
+ !------------------
+ SUBROUTINE block_data_real8_2d_free_mem (this)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ type(block_data_real8_2d) :: this
+
+ ! Local variables
+ integer :: iblk, jblk
+
+ IF (allocated (this%blk)) THEN
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (allocated (this%blk(iblk,jblk)%val)) THEN
+ deallocate (this%blk(iblk,jblk)%val)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (this%blk)
+ ENDIF
+
+ END SUBROUTINE block_data_real8_2d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_real8_3d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_real8_3d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_real8_3d_free_mem
+
+ !------------------
+ SUBROUTINE allocate_block_data_real8_3d (grid, gdata, ndim1, lb1)
+
+ USE MOD_Grid
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ type(block_data_real8_3d), intent(out) :: gdata
+ integer, intent(in) :: ndim1
+ integer, intent(in), optional :: lb1
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ allocate (gdata%blk (gblock%nxblk,gblock%nyblk))
+
+ IF (present(lb1)) THEN
+ gdata%lb1 = lb1
+ ELSE
+ gdata%lb1 = 1
+ ENDIF
+
+ gdata%ub1 = gdata%lb1-1+ndim1
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ allocate (gdata%blk(iblk,jblk)%val (gdata%lb1:gdata%ub1, grid%xcnt(iblk), grid%ycnt(jblk)))
+ ENDDO
+
+ END SUBROUTINE allocate_block_data_real8_3d
+
+ !------------------
+ SUBROUTINE block_data_real8_3d_free_mem (this)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ type(block_data_real8_3d) :: this
+
+ ! Local variables
+ integer :: iblk, jblk
+
+ IF (allocated (this%blk)) THEN
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (allocated (this%blk(iblk,jblk)%val)) THEN
+ deallocate (this%blk(iblk,jblk)%val)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (this%blk)
+ ENDIF
+
+ END SUBROUTINE block_data_real8_3d_free_mem
+
+ !------------------
+ SUBROUTINE pointer_real8_4d_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(pointer_real8_4d) :: this
+
+ IF (allocated(this%val)) THEN
+ deallocate(this%val)
+ ENDIF
+
+ END SUBROUTINE pointer_real8_4d_free_mem
+
+ !------------------
+ SUBROUTINE allocate_block_data_real8_4d (grid, gdata, ndim1, ndim2, lb1, lb2)
+
+ USE MOD_Grid
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ type(block_data_real8_4d), intent(out) :: gdata
+ integer, intent(in) :: ndim1, ndim2
+ integer, intent(in), optional :: lb1, lb2
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ allocate (gdata%blk (gblock%nxblk,gblock%nyblk))
+
+ IF (present(lb1)) THEN
+ gdata%lb1 = lb1
+ ELSE
+ gdata%lb1 = 1
+ ENDIF
+
+ gdata%ub1 = gdata%lb1-1+ndim1
+
+ IF (present(lb2)) THEN
+ gdata%lb2 = lb2
+ ELSE
+ gdata%lb2 = 1
+ ENDIF
+
+ gdata%ub2 = gdata%lb2-1+ndim2
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ allocate (gdata%blk(iblk,jblk)%val ( &
+ gdata%lb1:gdata%ub1, gdata%lb2:gdata%ub2, grid%xcnt(iblk), grid%ycnt(jblk)))
+ ENDDO
+
+ END SUBROUTINE allocate_block_data_real8_4d
+
+ !------------------
+ SUBROUTINE block_data_real8_4d_free_mem (this)
+
+ USE MOD_Block
+ IMPLICIT NONE
+
+ type(block_data_real8_4d) :: this
+
+ ! Local variables
+ integer :: iblk, jblk
+
+ IF (allocated (this%blk)) THEN
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (allocated (this%blk(iblk,jblk)%val)) THEN
+ deallocate (this%blk(iblk,jblk)%val)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (this%blk)
+ ENDIF
+
+ END SUBROUTINE block_data_real8_4d_free_mem
+
+ !------------------
+ SUBROUTINE flush_block_data_real8_2d (gdata, spval)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_real8_2d), intent(inout) :: gdata
+ real(r8), intent(in) :: spval
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata%blk(iblk,jblk)%val = spval
+ ENDDO
+
+ END SUBROUTINE flush_block_data_real8_2d
+
+ !------------------
+ SUBROUTINE flush_block_data_int32_2d (gdata, spval)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_int32_2d), intent(inout) :: gdata
+ integer, intent(in) :: spval
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata%blk(iblk,jblk)%val = spval
+ ENDDO
+
+ END SUBROUTINE flush_block_data_int32_2d
+
+ !------------------
+ SUBROUTINE flush_block_data_real8_3d (gdata, spval)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_real8_3d), intent(inout) :: gdata
+ real(r8), intent(in) :: spval
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata%blk(iblk,jblk)%val = spval
+ ENDDO
+
+ END SUBROUTINE flush_block_data_real8_3d
+
+ !------------------
+ SUBROUTINE flush_block_data_real8_4d (gdata, spval)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_real8_4d), intent(inout) :: gdata
+ real(r8), intent(in) :: spval
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata%blk(iblk,jblk)%val = spval
+ ENDDO
+
+ END SUBROUTINE flush_block_data_real8_4d
+
+ !------------------
+ SUBROUTINE block_data_linear_transform (gdata, scl, dsp)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_real8_2d), intent(inout) :: gdata
+ real(r8), intent(in), optional :: scl
+ real(r8), intent(in), optional :: dsp
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ IF (present(scl)) THEN
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata%blk(iblk,jblk)%val = gdata%blk(iblk,jblk)%val * scl
+ ENDDO
+ ENDIF
+
+ IF (present(dsp)) THEN
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata%blk(iblk,jblk)%val = gdata%blk(iblk,jblk)%val + dsp
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE block_data_linear_transform
+
+ !------------------
+ SUBROUTINE block_data_copy (gdata_from, gdata_to, sca)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_real8_2d), intent(in) :: gdata_from
+ type(block_data_real8_2d), intent(inout) :: gdata_to
+ real(r8), intent(in), optional :: sca
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (present(sca)) THEN
+ gdata_to%blk(iblk,jblk)%val = gdata_from%blk(iblk,jblk)%val * sca
+ ELSE
+ gdata_to%blk(iblk,jblk)%val = gdata_from%blk(iblk,jblk)%val
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE block_data_copy
+
+ !------------------
+ SUBROUTINE block_data_linear_interp ( &
+ gdata_from1, alp1, gdata_from2, alp2, gdata_to)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type(block_data_real8_2d), intent(in) :: gdata_from1, gdata_from2
+ real(r8), intent(in) :: alp1, alp2
+ type(block_data_real8_2d), intent(inout) :: gdata_to
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ gdata_to%blk(iblk,jblk)%val = &
+ gdata_from1%blk(iblk,jblk)%val * alp1 &
+ + gdata_from2%blk(iblk,jblk)%val * alp2
+ ENDDO
+
+ END SUBROUTINE block_data_linear_interp
+
+ !-----------------
+ SUBROUTINE block_data_division (gdata, sumdata, spv)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ type(block_data_real8_2d), intent(inout) :: gdata
+ type(block_data_real8_2d), intent(inout) :: sumdata
+ real(r8), intent(in), optional :: spv
+
+ ! Local variables
+ integer :: iblkme, iblk, jblk
+
+ IF (p_is_active) THEN
+
+ IF (.not. present(spv)) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ WHERE (sumdata%blk(iblk,jblk)%val > 0.)
+ gdata%blk(iblk,jblk)%val = &
+ gdata%blk(iblk,jblk)%val / sumdata%blk(iblk,jblk)%val
+ ELSEWHERE
+ gdata%blk(iblk,jblk)%val = spval
+ ENDWHERE
+ ENDDO
+
+ ELSE
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ WHERE ((sumdata%blk(iblk,jblk)%val > 0.) .and. (gdata%blk(iblk,jblk)%val /= spv))
+ gdata%blk(iblk,jblk)%val = &
+ gdata%blk(iblk,jblk)%val / sumdata%blk(iblk,jblk)%val
+ ELSEWHERE
+ gdata%blk(iblk,jblk)%val = spv
+ ENDWHERE
+ ENDDO
+
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE block_data_division
+
+END MODULE MOD_DataType
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_ElmVector.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_ElmVector.F90
new file mode 100644
index 0000000000..4f14eaf2af
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_ElmVector.F90
@@ -0,0 +1,188 @@
+#include
+
+#if (defined UNSTRUCTURED || defined CATCHMENT)
+MODULE MOD_ElmVector
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Address of Data associated with land element.
+!
+! To output a vector, Data is gathered from compute ranks directly to
+! root rank. "elm_data_address" stores information on how to reorganize data
+! gathered. The output data in vector is sorted by global element index.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ integer :: totalnumelm
+ type(pointer_int32_1d), allocatable :: elm_data_address (:)
+
+ integer*8, allocatable :: eindex_glb (:)
+
+CONTAINS
+
+ ! --------
+ SUBROUTINE elm_vector_init
+
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ USE MOD_Pixelset
+ USE MOD_Utils
+ USE MOD_UserDefFun
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_LandPatch
+#ifdef CROP
+ USE MOD_LandCrop
+#endif
+ IMPLICIT NONE
+
+ ! Local Variables
+ integer :: mesg(2), iwork, isrc, ndata
+ integer, allocatable :: numelm_rank (:)
+
+ integer :: i, idsp
+ integer, allocatable :: vec_rank_dsp (:)
+
+ integer*8, allocatable :: indexelm (:)
+ integer, allocatable :: order (:)
+
+ IF (p_is_compute) THEN
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+ ENDIF
+
+ IF (p_is_compute) THEN
+#ifdef USEMPI
+ IF (numelm > 0) THEN
+ allocate (indexelm (numelm))
+ indexelm = landelm%eindex
+ ENDIF
+
+ IF (p_iam_compute == p_root) allocate (numelm_rank (0:p_np_compute-1))
+ CALL mpi_gather (numelm, 1, MPI_INTEGER, &
+ numelm_rank, 1, MPI_INTEGER, p_root, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+#ifndef MPAS_EMBEDDED_COLM
+ CALL mpi_send (numelm_rank, p_np_compute, MPI_INTEGER, &
+ p_address_root, mpi_tag_size, p_comm_glb, p_err)
+#endif
+ ENDIF
+
+ mesg = (/p_iam_glb, numelm/)
+#ifdef MPAS_EMBEDDED_COLM
+ IF (.not. (p_is_root .and. p_iam_compute == p_root)) THEN
+#endif
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numelm > 0) THEN
+ CALL mpi_send (indexelm, numelm, MPI_INTEGER8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#ifdef MPAS_EMBEDDED_COLM
+ ENDIF
+#endif
+#else
+ IF (numelm > 0) THEN
+ allocate (eindex_glb (numelm))
+ eindex_glb = landelm%eindex
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+#ifdef USEMPI
+#ifndef MPAS_EMBEDDED_COLM
+ allocate (numelm_rank (0:p_np_compute-1))
+ CALL mpi_recv (numelm_rank, p_np_compute, MPI_INTEGER, p_address_compute(p_root), &
+ mpi_tag_size, p_comm_glb, p_stat, p_err)
+#endif
+
+ allocate (vec_rank_dsp (0:p_np_compute-1))
+ vec_rank_dsp(0) = 0
+ DO iwork = 1, p_np_compute-1
+ vec_rank_dsp(iwork) = vec_rank_dsp(iwork-1) + numelm_rank(iwork-1)
+ ENDDO
+
+ totalnumelm = sum(numelm_rank)
+
+ allocate (eindex_glb (totalnumelm))
+
+ allocate (elm_data_address(0:p_np_compute-1))
+ DO iwork = 0, p_np_compute-1
+ IF (numelm_rank(iwork) > 0) THEN
+ allocate (elm_data_address(iwork)%val (numelm_rank(iwork)))
+ ENDIF
+ ENDDO
+
+ DO iwork = 0, p_np_compute-1
+#ifdef MPAS_EMBEDDED_COLM
+ IF (iwork == p_root) THEN
+ ndata = numelm_rank(iwork)
+ IF (ndata > 0) THEN
+ idsp = vec_rank_dsp(iwork)
+ eindex_glb(idsp+1:idsp+ndata) = indexelm(1:ndata)
+ ENDIF
+ CYCLE
+ ENDIF
+#endif
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ idsp = vec_rank_dsp(p_itis_compute(isrc))
+ CALL mpi_recv (eindex_glb(idsp+1:idsp+ndata), ndata, MPI_INTEGER8, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDDO
+#else
+ totalnumelm = numelm
+ allocate (elm_data_address(0:0))
+ allocate (elm_data_address(0)%val (totalnumelm))
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (totalnumelm, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ allocate (order (totalnumelm))
+ order = (/(i, i=1,totalnumelm)/)
+
+ CALL quicksort (totalnumelm, eindex_glb, order)
+
+#ifdef USEMPI
+ DO i = 1, totalnumelm
+ iwork = findloc_ud(order(i) > vec_rank_dsp, back=.true.) - 1
+ elm_data_address(iwork)%val(order(i)-vec_rank_dsp(iwork)) = i
+ ENDDO
+#else
+ elm_data_address(0)%val (order) = (/(i, i=1,totalnumelm)/)
+#endif
+ ENDIF
+
+ IF (allocated(numelm_rank)) deallocate(numelm_rank)
+ IF (allocated(vec_rank_dsp)) deallocate(vec_rank_dsp)
+ IF (allocated(indexelm)) deallocate(indexelm)
+ IF (allocated(order)) deallocate(order)
+
+ END SUBROUTINE elm_vector_init
+
+ ! ----------
+ SUBROUTINE elm_vector_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(elm_data_address)) deallocate (elm_data_address)
+ IF (allocated(eindex_glb)) deallocate (eindex_glb)
+
+ END SUBROUTINE elm_vector_final
+
+END MODULE MOD_ElmVector
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Grid.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Grid.F90
new file mode 100644
index 0000000000..1b61638bfb
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Grid.F90
@@ -0,0 +1,1004 @@
+#include
+
+MODULE MOD_Grid
+
+!-------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Definition of latitude-longitude grids and data types related to grids.
+!
+! Latitude-longitude grid can be defined by
+! 1. "name" : frequently used grids is predefined in this MODULE;
+! 2. "ndims" : how many longitude and latitude grids are used globally;
+! 3. "res" : longitude and latitude resolutions in radian
+! 4. "center" : longitude and latitude grid centers, and the border lines
+! are defined by center lines of grid centers; the region
+! boundaries is optional.
+! 5. "file" : read grid informations from a file, the variables are
+! 'lat_s', 'lat_n', 'lon_w', 'lon_e'
+! 6. "copy" : copy grid informations from an existing grid
+!
+! Grid centers in radian can be calculated by using "set_rlon" and "set_rlat"
+!
+! Two additional data types are defined:
+! 1. "grid_list_type" : list of grid boxes;
+! 2. "grid_concat_type" : used to concatenate grids distributed in blocks.
+!
+! Created by Shupeng Zhang, May 2023
+!-------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_UserDefFun
+ IMPLICIT NONE
+
+ ! ---- data types ----
+ type :: grid_type
+
+ integer :: nlat
+ integer :: nlon
+
+ ! Latitude direction. (yinc = 1) means south to north.
+ integer :: yinc
+
+ ! Coordinates.
+ real(r8), allocatable :: lat_s (:)
+ real(r8), allocatable :: lat_n (:)
+ real(r8), allocatable :: lon_w (:)
+ real(r8), allocatable :: lon_e (:)
+
+ ! Blocks.
+ integer, allocatable :: xdsp(:), ydsp(:)
+ integer, allocatable :: xcnt(:), ycnt(:)
+ integer, allocatable :: xblk(:), yblk(:)
+ integer, allocatable :: xloc(:), yloc(:)
+
+ ! Mapping to pixels.
+ integer, allocatable :: xgrd(:), ygrd(:)
+
+ ! Grid info.
+ real(r8), allocatable :: rlon(:)
+ real(r8), allocatable :: rlat(:)
+
+ CONTAINS
+ procedure, PUBLIC :: define_by_name => grid_define_by_name
+ procedure, PUBLIC :: define_by_ndims => grid_define_by_ndims
+ procedure, PUBLIC :: define_by_res => grid_define_by_res
+ procedure, PUBLIC :: define_by_center => grid_define_by_center
+ procedure, PUBLIC :: define_from_file => grid_define_from_file
+ procedure, PUBLIC :: define_by_copy => grid_define_by_copy
+
+ procedure, PUBLIC :: set_rlon => grid_set_rlon
+ procedure, PUBLIC :: set_rlat => grid_set_rlat
+
+ procedure, PRIVATE :: init => grid_init
+ procedure, PRIVATE :: normalize => grid_normalize
+ procedure, PRIVATE :: set_blocks => grid_set_blocks
+
+ final :: grid_free_mem
+
+ END type grid_type
+
+ ! ---- data types ----
+ type :: grid_list_type
+ integer :: ng
+ integer, allocatable :: ilat(:)
+ integer, allocatable :: ilon(:)
+ END type grid_list_type
+
+ type :: segment_type
+ integer :: blk
+ integer :: cnt
+ integer :: bdsp
+ integer :: gdsp
+ END type segment_type
+
+ type :: grid_info_type
+ integer :: nlat, nlon
+ real(r8), allocatable :: lat_s(:)
+ real(r8), allocatable :: lat_n(:)
+ real(r8), allocatable :: lon_w(:)
+ real(r8), allocatable :: lon_e(:)
+ real(r8), allocatable :: lon_c(:) !grid center
+ real(r8), allocatable :: lat_c(:) !grid center
+ END type grid_info_type
+
+ type :: grid_concat_type
+ integer :: ndatablk
+ integer :: nxseg, nyseg
+ type(segment_type), allocatable :: xsegs(:), ysegs(:)
+ type(grid_info_type) :: ginfo
+ CONTAINS
+ procedure, PUBLIC :: set => set_grid_concat
+ final :: grid_concat_free_mem
+ END type grid_concat_type
+
+
+ ! -- PUBLIC SUBROUTINEs --
+ PUBLIC :: get_region_by_this_IO
+
+CONTAINS
+
+ ! --------------------------------
+ SUBROUTINE grid_init (this, nlon, nlat)
+
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ integer, intent(in) :: nlon
+ integer, intent(in) :: nlat
+
+ this%nlat = nlat
+ this%nlon = nlon
+
+ IF (allocated(this%lat_s)) deallocate(this%lat_s)
+ IF (allocated(this%lat_n)) deallocate(this%lat_n)
+ IF (allocated(this%lon_w)) deallocate(this%lon_w)
+ IF (allocated(this%lon_e)) deallocate(this%lon_e)
+ allocate (this%lat_s (nlat))
+ allocate (this%lat_n (nlat))
+ allocate (this%lon_w (nlon))
+ allocate (this%lon_e (nlon))
+
+ END SUBROUTINE grid_init
+
+ ! --------------------------------
+ SUBROUTINE grid_define_by_name (this, gridname)
+
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ character(len=*), intent(in) :: gridname
+
+ ! Local variables
+ integer :: nlat, nlon, ilat, ilon
+ real(r8) :: del_lat, del_lon
+
+ IF (trim(gridname) == 'merit_90m') THEN
+
+ nlat = 180*60*20
+ nlon = 360*60*20
+
+ this%nlat = nlat
+ this%nlon = nlon
+
+ CALL this%init (this%nlon, this%nlat)
+
+ del_lat = 180.0 / nlat
+ DO ilat = 1, this%nlat
+ this%lat_s(ilat) = 90.0 - del_lat * ilat - del_lat/2.0
+ this%lat_n(ilat) = 90.0 - del_lat * (ilat-1) - del_lat/2.0
+ ENDDO
+
+ del_lon = 360.0 / nlon
+ DO ilon = 1, this%nlon
+ this%lon_w(ilon) = -180.0 + del_lon * (ilon-1) - del_lon/2.0
+ this%lon_e(ilon) = -180.0 + del_lon * ilon - del_lon/2.0
+ ENDDO
+
+ CALL this%normalize ()
+ CALL this%set_blocks ()
+
+ ENDIF
+
+ IF (trim(gridname) == 'colm_5km') THEN
+
+ CALL this%define_by_ndims (8640,4320)
+
+ ENDIF
+
+ IF (trim(gridname) == 'colm_1km') THEN
+
+ CALL this%define_by_ndims (43200,21600)
+
+ ENDIF
+
+
+ IF (trim(gridname) == 'colm_500m') THEN
+
+ CALL this%define_by_ndims (86400,43200)
+
+ ENDIF
+
+ IF (trim(gridname) == 'colm_100m') THEN
+
+ CALL this%define_by_ndims (432000,216000)
+
+ ENDIF
+
+ IF (trim(gridname) == 'nitrif_2deg') THEN
+
+ CALL this%define_by_ndims (144,96)
+
+ ENDIF
+
+ END SUBROUTINE grid_define_by_name
+
+ !-----------------------------------------------------
+ SUBROUTINE grid_define_by_ndims (this, lon_points, lat_points)
+
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ integer, intent(in) :: lon_points
+ integer, intent(in) :: lat_points
+
+ ! Local variables
+ integer :: ilat, ilon
+ real(r8) :: del_lat, del_lon
+
+ this%nlat = lat_points
+ this%nlon = lon_points
+
+ CALL this%init (this%nlon, this%nlat)
+
+ del_lat = 180.0 / lat_points
+ DO ilat = 1, this%nlat
+ this%lat_s(ilat) = 90.0 - del_lat * ilat
+ this%lat_n(ilat) = 90.0 - del_lat * (ilat-1)
+ ENDDO
+
+ del_lon = 360.0 / lon_points
+ DO ilon = 1, this%nlon
+ this%lon_w(ilon) = -180.0 + del_lon * (ilon-1)
+ this%lon_e(ilon) = -180.0 + del_lon * ilon
+ ENDDO
+
+ this%lon_e(this%nlon) = -180.0
+
+ CALL this%normalize ()
+ CALL this%set_blocks ()
+
+ END SUBROUTINE grid_define_by_ndims
+
+ !-----------------------------------------------------
+ SUBROUTINE grid_define_by_res (this, lon_res, lat_res)
+
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ real(r8), intent(in) :: lon_res, lat_res
+
+ ! Local variables
+ integer :: lon_points, lat_points
+
+ lon_points = nint(360.0/lon_res)
+ lat_points = nint(180.0/lat_res)
+
+ CALL this%define_by_ndims (lon_points, lat_points)
+
+ END SUBROUTINE grid_define_by_res
+
+ !---------------------------------------------
+ SUBROUTINE grid_define_by_center (this, lat_in, lon_in, &
+ south, north, west, east)
+
+ USE MOD_Precision
+ USE MOD_Utils
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ real(r8), intent(in) :: lat_in(:), lon_in(:)
+ real(r8), intent(in), optional :: south, north, west, east
+
+ ! Local variables
+ integer :: ilat, ilon, ilone, ilonw
+ real(r8), allocatable :: lon_in_n(:)
+
+ this%nlat = size(lat_in)
+ this%nlon = size(lon_in)
+
+ CALL this%init (this%nlon, this%nlat)
+
+ IF (lat_in(1) > lat_in(this%nlat)) THEN
+ this%yinc = -1
+ ELSE
+ this%yinc = 1
+ ENDIF
+
+ DO ilat = 1, this%nlat
+ IF (this%yinc == 1) THEN
+ IF (ilat < this%nlat) THEN
+ this%lat_n(ilat) = (lat_in(ilat) + lat_in(ilat+1)) * 0.5
+ ELSE
+ IF (present(north)) THEN
+ this%lat_n(ilat) = north
+ ELSE
+ this%lat_n(ilat) = 90.0
+ ENDIF
+ ENDIF
+
+ IF (ilat > 1) THEN
+ this%lat_s(ilat) = (lat_in(ilat-1) + lat_in(ilat)) * 0.5
+ ELSE
+ IF (present(south)) THEN
+ this%lat_s(ilat) = south
+ ELSE
+ this%lat_s(ilat) = -90.0
+ ENDIF
+ ENDIF
+ ELSEIF (this%yinc == -1) THEN
+ IF (ilat > 1) THEN
+ this%lat_n(ilat) = (lat_in(ilat-1) + lat_in(ilat)) * 0.5
+ ELSE
+ IF (present(north)) THEN
+ this%lat_n(ilat) = north
+ ELSE
+ this%lat_n(ilat) = 90.0
+ ENDIF
+ ENDIF
+
+ IF (ilat < this%nlat) THEN
+ this%lat_s(ilat) = (lat_in(ilat) + lat_in(ilat+1)) * 0.5
+ ELSE
+ IF (present(south)) THEN
+ this%lat_s(ilat) = south
+ ELSE
+ this%lat_s(ilat) = -90.0
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+
+ allocate (lon_in_n (size(lon_in)))
+
+ lon_in_n = lon_in
+ DO ilon = 1, size(lon_in_n)
+ CALL normalize_longitude (lon_in_n(ilon))
+ ENDDO
+
+ DO ilon = 1, this%nlon
+ ilone = mod(ilon,this%nlon) + 1
+ IF (lon_in_n(ilon) > lon_in_n(ilone)) THEN
+ this%lon_e(ilon) = (lon_in_n(ilon) + lon_in_n(ilone) + 360.0) * 0.5
+ ELSE
+ this%lon_e(ilon) = (lon_in_n(ilon) + lon_in_n(ilone)) * 0.5
+ ENDIF
+
+ IF ((ilon == this%nlon) .and. (present(east))) THEN
+ this%lon_e(this%nlon) = east
+ ENDIF
+
+ ilonw = ilon - 1
+ IF (ilonw == 0) ilonw = this%nlon
+ IF (lon_in_n(ilonw) > lon_in_n(ilon)) THEN
+ this%lon_w(ilon) = (lon_in_n(ilonw) + lon_in_n(ilon) + 360.0) * 0.5
+ ELSE
+ this%lon_w(ilon) = (lon_in_n(ilonw) + lon_in_n(ilon)) * 0.5
+ ENDIF
+
+ IF ((ilon == 1) .and. (present(west))) THEN
+ this%lon_w(1) = west
+ ENDIF
+ ENDDO
+
+ deallocate (lon_in_n)
+
+ CALL this%normalize ()
+ CALL this%set_blocks ()
+
+ END SUBROUTINE grid_define_by_center
+
+ !-----------------------------------------------------
+ SUBROUTINE grid_define_from_file (this, filename, latname, lonname)
+
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in), optional :: latname, lonname
+
+ ! Local Variables
+ real(r8), allocatable :: lon_in(:)
+ real(r8), allocatable :: lat_in(:)
+
+ IF (.not. (present(latname) .and. present(lonname))) THEN
+
+ CALL ncio_read_bcast_serial (filename, 'lat_s', this%lat_s)
+ CALL ncio_read_bcast_serial (filename, 'lat_n', this%lat_n)
+ CALL ncio_read_bcast_serial (filename, 'lon_w', this%lon_w)
+ CALL ncio_read_bcast_serial (filename, 'lon_e', this%lon_e)
+
+ this%nlat = size(this%lat_s)
+ this%nlon = size(this%lon_w)
+
+ CALL this%normalize ()
+ CALL this%set_blocks ()
+
+ ELSE
+
+ CALL ncio_read_bcast_serial (filename, latname, lat_in)
+ CALL ncio_read_bcast_serial (filename, lonname, lon_in)
+ CALL this%define_by_center (lat_in, lon_in)
+
+ deallocate (lat_in, lon_in)
+ ENDIF
+
+ END SUBROUTINE grid_define_from_file
+
+ !-----------------------------------------------------
+ SUBROUTINE grid_define_by_copy (this, grid_in)
+
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+ class (grid_type) :: this
+
+ type(grid_type) :: grid_in
+
+ CALL this%init (grid_in%nlon, grid_in%nlat)
+
+ this%lat_s = grid_in%lat_s
+ this%lat_n = grid_in%lat_n
+ this%lon_w = grid_in%lon_w
+ this%lon_e = grid_in%lon_e
+
+ CALL this%normalize ()
+ CALL this%set_blocks ()
+
+ END SUBROUTINE grid_define_by_copy
+
+ !-----------------------------------------------------
+ SUBROUTINE grid_normalize (this)
+
+ USE MOD_Utils
+ IMPLICIT NONE
+ class(grid_type) :: this
+
+ ! Local variable
+ integer :: ilon, ilat
+
+ DO ilon = 1, this%nlon
+ CALL normalize_longitude (this%lon_w(ilon))
+ CALL normalize_longitude (this%lon_e(ilon))
+ ENDDO
+
+ DO ilat = 1, this%nlat
+ this%lat_s(ilat) = max(-90.0, min(90.0, this%lat_s(ilat)))
+ this%lat_n(ilat) = max(-90.0, min(90.0, this%lat_n(ilat)))
+ ENDDO
+
+ IF (this%lat_s(1) <= this%lat_s(this%nlat)) THEN
+ this%yinc = 1
+ ELSE
+ this%yinc = -1
+ ENDIF
+
+ ! align grid
+ DO ilon = 1, this%nlon-1
+ IF (lon_between_ceil(this%lon_e(ilon), this%lon_w(ilon+1), this%lon_e(ilon+1))) THEN
+ this%lon_e(ilon) = this%lon_w(ilon+1)
+ ELSE
+ this%lon_w(ilon+1) = this%lon_e(ilon)
+ ENDIF
+ ENDDO
+
+ IF (this%nlon > 1) THEN
+ ilon = this%nlon
+ IF (lon_between_ceil(this%lon_e(ilon), this%lon_w(1), this%lon_e(1))) THEN
+ this%lon_e(ilon) = this%lon_w(1)
+ ENDIF
+ ENDIF
+
+ DO ilat = 1, this%nlat-1
+ IF (this%yinc == 1) THEN
+ this%lat_n(ilat) = max(this%lat_n(ilat),this%lat_s(ilat+1))
+ this%lat_s(ilat+1) = this%lat_n(ilat)
+ ELSEIF (this%yinc == -1) THEN
+ this%lat_s(ilat) = min(this%lat_s(ilat),this%lat_n(ilat+1))
+ this%lat_n(ilat+1) = this%lat_s(ilat)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE grid_normalize
+
+ !-----------------------------------------------------
+ SUBROUTINE grid_set_blocks (this)
+
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ class (grid_type) :: this
+
+ ! Local variables
+ integer :: ilat, ilon, iblk, jblk, ilon_e
+ real(r8) :: edges, edgen, edgew, edgee
+
+ IF (allocated(this%xcnt)) deallocate(this%xcnt)
+ IF (allocated(this%xdsp)) deallocate(this%xdsp)
+ IF (allocated(this%ycnt)) deallocate(this%ycnt)
+ IF (allocated(this%ydsp)) deallocate(this%ydsp)
+ allocate (this%xcnt (gblock%nxblk))
+ allocate (this%xdsp (gblock%nxblk))
+ allocate (this%ycnt (gblock%nyblk))
+ allocate (this%ydsp (gblock%nyblk))
+
+ IF (allocated(this%xblk)) deallocate(this%xblk)
+ IF (allocated(this%yblk)) deallocate(this%yblk)
+ allocate (this%xblk (this%nlon))
+ allocate (this%yblk (this%nlat))
+
+ IF (allocated(this%xloc)) deallocate(this%xloc)
+ IF (allocated(this%yloc)) deallocate(this%yloc)
+ allocate (this%xloc (this%nlon))
+ allocate (this%yloc (this%nlat))
+
+ edges = DEF_domain%edges
+ edgen = DEF_domain%edgen
+ edgew = DEF_domain%edgew
+ edgee = DEF_domain%edgee
+
+ CALL normalize_longitude (edgew)
+ CALL normalize_longitude (edgee)
+
+ IF (this%yinc == 1) THEN
+
+ this%ycnt(:) = 0
+ this%yblk(:) = 0
+
+ IF (edges < this%lat_s(1)) THEN
+ jblk = find_nearest_south (this%lat_s(1), gblock%nyblk, gblock%lat_s)
+ ilat = 1
+ ELSE
+ jblk = find_nearest_south (edges, gblock%nyblk, gblock%lat_s)
+ ilat = find_nearest_south (edges, this%nlat, this%lat_s)
+ ENDIF
+
+ this%ydsp(jblk) = ilat - 1
+
+ DO WHILE (ilat <= this%nlat)
+ IF (this%lat_s(ilat) < edgen) THEN
+ IF (this%lat_s(ilat) < gblock%lat_n(jblk)) THEN
+
+ this%ycnt(jblk) = this%ycnt(jblk) + 1
+
+ this%yblk(ilat) = jblk
+ this%yloc(ilat) = this%ycnt(jblk)
+
+ ilat = ilat + 1
+ ELSE
+ jblk = jblk + 1
+ IF (jblk <= gblock%nyblk) THEN
+ this%ydsp(jblk) = ilat - 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDIF
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ ELSE
+
+ this%ycnt(:) = 0
+ this%yblk(:) = 0
+
+ IF (edgen > this%lat_n(1)) THEN
+ jblk = find_nearest_north (this%lat_n(1), gblock%nyblk, gblock%lat_n)
+ ilat = 1
+ ELSE
+ jblk = find_nearest_north (edgen, gblock%nyblk, gblock%lat_n)
+ ilat = find_nearest_north (edgen, this%nlat, this%lat_n)
+ ENDIF
+
+ this%ydsp(jblk) = ilat - 1
+
+ DO WHILE (ilat <= this%nlat)
+ IF (this%lat_n(ilat) > edges) THEN
+ IF (this%lat_n(ilat) > gblock%lat_s(jblk)) THEN
+
+ this%ycnt(jblk) = this%ycnt(jblk) + 1
+
+ this%yblk(ilat) = jblk
+ this%yloc(ilat) = this%ycnt(jblk)
+
+ ilat = ilat + 1
+ ELSE
+ jblk = jblk - 1
+ IF (jblk >= 1) THEN
+ this%ydsp(jblk) = ilat - 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDIF
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+
+ this%xcnt(:) = 0
+ this%xblk(:) = 0
+
+ IF ((this%lon_w(1) /= this%lon_e(this%nlon)) &
+ .and. (lon_between_floor(edgew, this%lon_e(this%nlon), this%lon_w(1)))) THEN
+ iblk = find_nearest_west (this%lon_w(1), gblock%nxblk, gblock%lon_w)
+ ilon = 1
+ ELSE
+ iblk = find_nearest_west (edgew, gblock%nxblk, gblock%lon_w)
+ ilon = find_nearest_west (edgew, this%nlon, this%lon_w)
+ ENDIF
+
+ this%xdsp(iblk) = ilon - 1
+ this%xcnt(iblk) = 1
+ this%xblk(ilon) = iblk
+ this%xloc(ilon) = 1
+
+ ilon_e = ilon - 1
+ IF (ilon_e == 0) ilon_e = this%nlon
+ ilon = mod(ilon,this%nlon) + 1
+ DO WHILE (.true.)
+ IF (lon_between_floor(this%lon_w(ilon), edgew, edgee)) THEN
+ IF (lon_between_floor(this%lon_w(ilon), gblock%lon_w(iblk), gblock%lon_e(iblk))) THEN
+
+ this%xcnt(iblk) = this%xcnt(iblk) + 1
+
+ this%xblk(ilon) = iblk
+ this%xloc(ilon) = this%xcnt(iblk)
+
+ IF (ilon /= ilon_e) THEN
+ ilon = mod(ilon,this%nlon) + 1
+ ELSE
+ EXIT
+ ENDIF
+ ELSE
+ iblk = mod(iblk,gblock%nxblk) + 1
+ IF (this%xcnt(iblk) == 0) THEN
+ this%xdsp(iblk) = ilon - 1
+ ELSE
+ ilon_e = this%xdsp(iblk) + this%xcnt(iblk)
+ IF (ilon_e > this%nlon) ilon_e = ilon_e - this%nlon
+
+ this%xdsp(iblk) = ilon - 1
+ this%xcnt(iblk) = 0
+ DO WHILE (.true.)
+ this%xcnt(iblk) = this%xcnt(iblk) + 1
+ this%xblk(ilon) = iblk
+ this%xloc(ilon) = this%xcnt(iblk)
+
+ IF (ilon /= ilon_e) THEN
+ ilon = mod(ilon,this%nlon) + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ EXIT
+ ENDIF
+ ENDIF
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE grid_set_blocks
+
+ !-----------
+ SUBROUTINE grid_set_rlon (this)
+
+ USE MOD_Precision
+ USE MOD_Utils
+ USE MOD_Vars_Global, only: pi
+ IMPLICIT NONE
+
+ class (grid_type) :: this
+
+ ! Local variables
+ integer :: ix
+ real(r8) :: lon
+
+ IF (.not. allocated(this%rlon)) THEN
+ allocate (this%rlon(this%nlon))
+ ENDIF
+
+ DO ix = 1, this%nlon
+ IF (this%lon_w(ix) <= this%lon_e(ix)) THEN
+ lon = (this%lon_w(ix) + this%lon_e(ix)) * 0.5
+ ELSE
+ lon = (this%lon_w(ix) + this%lon_e(ix)) * 0.5 + 180.0
+ ENDIF
+
+ CALL normalize_longitude (lon)
+
+ this%rlon(ix) = lon / 180.0_r8 * pi
+ ENDDO
+
+ END SUBROUTINE grid_set_rlon
+
+ !-----------
+ SUBROUTINE grid_set_rlat (this)
+
+ USE MOD_Precision
+ USE MOD_Utils
+ USE MOD_Vars_Global, only: pi
+ IMPLICIT NONE
+
+ class (grid_type) :: this
+
+ ! Local variables
+ integer :: iy
+
+ IF (.not. allocated(this%rlat)) THEN
+ allocate (this%rlat(this%nlat))
+ ENDIF
+
+ DO iy = 1, this%nlat
+ this%rlat(iy) = &
+ (this%lat_s(iy) + this%lat_n(iy)) * 0.5 / 180.0_r8 * pi
+ ENDDO
+
+ END SUBROUTINE grid_set_rlat
+
+ !---------
+ SUBROUTINE grid_free_mem (this)
+
+ IMPLICIT NONE
+ type (grid_type) :: this
+
+ IF (allocated (this%lat_s)) deallocate (this%lat_s)
+ IF (allocated (this%lat_n)) deallocate (this%lat_n)
+ IF (allocated (this%lon_w)) deallocate (this%lon_w)
+ IF (allocated (this%lon_e)) deallocate (this%lon_e)
+
+ IF (allocated (this%xdsp)) deallocate (this%xdsp)
+ IF (allocated (this%ydsp)) deallocate (this%ydsp)
+
+ IF (allocated (this%xcnt)) deallocate (this%xcnt)
+ IF (allocated (this%ycnt)) deallocate (this%ycnt)
+
+ IF (allocated (this%xblk)) deallocate (this%xblk)
+ IF (allocated (this%yblk)) deallocate (this%yblk)
+
+ IF (allocated (this%xloc)) deallocate (this%xloc)
+ IF (allocated (this%yloc)) deallocate (this%yloc)
+
+ IF (allocated (this%xgrd)) deallocate (this%xgrd)
+ IF (allocated (this%ygrd)) deallocate (this%ygrd)
+
+ IF (allocated (this%rlon)) deallocate (this%rlon)
+ IF (allocated (this%rlat)) deallocate (this%rlat)
+
+ END SUBROUTINE grid_free_mem
+
+ !----------
+ SUBROUTINE set_grid_concat (this, grid)
+
+ USE MOD_Block
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ class(grid_concat_type) :: this
+ type(grid_type), intent(in) :: grid
+
+ ! Local variables
+ integer :: ilat_l, ilat_u, ilat, ilatloc, jblk, iyseg
+ integer :: ilon_w, ilon_e, ilon, ilonloc, iblk, ixseg
+
+ ilat_l = findloc_ud(grid%yblk /= 0)
+ ilat_u = findloc_ud(grid%yblk /= 0, back=.true.)
+
+ this%ginfo%nlat = ilat_u - ilat_l + 1
+ IF (allocated(this%ginfo%lat_s)) deallocate(this%ginfo%lat_s)
+ IF (allocated(this%ginfo%lat_n)) deallocate(this%ginfo%lat_n)
+ IF (allocated(this%ginfo%lat_c)) deallocate(this%ginfo%lat_c)
+ allocate (this%ginfo%lat_s (this%ginfo%nlat))
+ allocate (this%ginfo%lat_n (this%ginfo%nlat))
+ allocate (this%ginfo%lat_c (this%ginfo%nlat))
+
+ this%nyseg = 0
+ jblk = 0
+ ilatloc = 0
+ DO ilat = ilat_l, ilat_u
+ IF (grid%yblk(ilat) /= jblk) THEN
+ this%nyseg = this%nyseg + 1
+ jblk = grid%yblk(ilat)
+ ENDIF
+
+ ilatloc = ilatloc + 1
+ this%ginfo%lat_s(ilatloc) = grid%lat_s(ilat)
+ this%ginfo%lat_n(ilatloc) = grid%lat_n(ilat)
+ this%ginfo%lat_c(ilatloc) = (grid%lat_s(ilat)+grid%lat_n(ilat)) * 0.5
+ ENDDO
+
+ IF (allocated(this%ysegs)) deallocate(this%ysegs)
+ allocate (this%ysegs (this%nyseg))
+
+ iyseg = 0
+ jblk = 0
+ DO ilat = ilat_l, ilat_u
+ IF (grid%yblk(ilat) /= jblk) THEN
+ iyseg = iyseg + 1
+ jblk = grid%yblk(ilat)
+ this%ysegs(iyseg)%blk = jblk
+ this%ysegs(iyseg)%bdsp = grid%yloc(ilat) - 1
+ this%ysegs(iyseg)%gdsp = ilat - ilat_l
+ this%ysegs(iyseg)%cnt = 1
+ ELSE
+ this%ysegs(iyseg)%cnt = this%ysegs(iyseg)%cnt + 1
+ ENDIF
+ ENDDO
+
+ IF (all(grid%xblk > 0)) THEN
+ ilon_w = 1
+ ilon_e = grid%nlon
+ ELSE
+ ilon_w = findloc_ud(grid%xblk /= 0)
+ DO WHILE (.true.)
+ ilon = ilon_w - 1
+ IF (ilon == 0) ilon = grid%nlon
+
+ IF (grid%xblk(ilon) /= 0) THEN
+ ilon_w = ilon
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ ilon_e = ilon_w
+ DO WHILE (.true.)
+ ilon = mod(ilon_e,grid%nlon) + 1
+
+ IF (grid%xblk(ilon) /= 0) THEN
+ ilon_e = ilon
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ this%ginfo%nlon = ilon_e - ilon_w + 1
+ IF (this%ginfo%nlon <= 0) THEN
+ this%ginfo%nlon = this%ginfo%nlon + grid%nlon
+ ENDIF
+
+ IF (allocated(this%ginfo%lon_w)) deallocate(this%ginfo%lon_w)
+ IF (allocated(this%ginfo%lon_e)) deallocate(this%ginfo%lon_e)
+ IF (allocated(this%ginfo%lon_c)) deallocate(this%ginfo%lon_c)
+ allocate (this%ginfo%lon_w (this%ginfo%nlon))
+ allocate (this%ginfo%lon_e (this%ginfo%nlon))
+ allocate (this%ginfo%lon_c (this%ginfo%nlon))
+
+ this%nxseg = 0
+ ilon = ilon_w - 1
+ iblk = 0
+ ilonloc = 0
+ DO WHILE (.true.)
+ ilon = mod(ilon,grid%nlon) + 1
+ IF ((grid%xblk(ilon) /= iblk) .or. (grid%xloc(ilon) == 1)) THEN
+ this%nxseg = this%nxseg + 1
+ iblk = grid%xblk(ilon)
+ ENDIF
+
+ ilonloc = ilonloc + 1
+ this%ginfo%lon_w(ilonloc) = grid%lon_w(ilon)
+ this%ginfo%lon_e(ilonloc) = grid%lon_e(ilon)
+
+ this%ginfo%lon_c(ilonloc) = (grid%lon_w(ilon) + grid%lon_e(ilon)) * 0.5
+ IF (grid%lon_w(ilon) > grid%lon_e(ilon)) THEN
+ this%ginfo%lon_c(ilonloc) = this%ginfo%lon_c(ilonloc) + 180.0
+ CALL normalize_longitude (this%ginfo%lon_c(ilonloc))
+ ENDIF
+
+ IF (ilon == ilon_e) EXIT
+ ENDDO
+
+ DO ilon = 2, this%ginfo%nlon
+ IF ((this%ginfo%lon_c(ilon) < this%ginfo%lon_c(ilon-1)) &
+ .and. (this%ginfo%lon_c(ilon) < 0)) THEN
+ this%ginfo%lon_c(ilon) = this%ginfo%lon_c(ilon) + 360.0
+ ENDIF
+ ENDDO
+
+ IF (allocated(this%xsegs)) deallocate(this%xsegs)
+ allocate (this%xsegs (this%nxseg))
+
+ ixseg = 0
+ iblk = 0
+ ilon = ilon_w - 1
+ ilonloc = 0
+ DO WHILE (.true.)
+ ilon = mod(ilon,grid%nlon) + 1
+ ilonloc = ilonloc + 1
+ IF ((grid%xblk(ilon) /= iblk) .or. (grid%xloc(ilon) == 1)) THEN
+ ixseg = ixseg + 1
+ iblk = grid%xblk(ilon)
+ this%xsegs(ixseg)%blk = iblk
+ this%xsegs(ixseg)%bdsp = grid%xloc(ilon) - 1
+ this%xsegs(ixseg)%gdsp = ilonloc - 1
+ this%xsegs(ixseg)%cnt = 1
+ ELSE
+ this%xsegs(ixseg)%cnt = this%xsegs(ixseg)%cnt + 1
+ ENDIF
+
+ IF (ilon == ilon_e) EXIT
+ ENDDO
+
+ this%ndatablk = 0
+
+ DO iyseg = 1, this%nyseg
+ DO ixseg = 1, this%nxseg
+ iblk = this%xsegs(ixseg)%blk
+ jblk = this%ysegs(iyseg)%blk
+ IF (gblock%pio(iblk,jblk) >= 0) THEN
+ this%ndatablk = this%ndatablk + 1
+ ENDIF
+ ENDDO
+ ENDDO
+
+ END SUBROUTINE set_grid_concat
+
+ !-------
+ SUBROUTINE grid_concat_free_mem (this)
+
+ IMPLICIT NONE
+
+ type(grid_concat_type) :: this
+
+ IF (allocated(this%xsegs)) deallocate(this%xsegs)
+ IF (allocated(this%ysegs)) deallocate(this%ysegs)
+
+ IF (allocated(this%ginfo%lat_s)) deallocate(this%ginfo%lat_s)
+ IF (allocated(this%ginfo%lat_n)) deallocate(this%ginfo%lat_n)
+ IF (allocated(this%ginfo%lat_c)) deallocate(this%ginfo%lat_c)
+ IF (allocated(this%ginfo%lon_w)) deallocate(this%ginfo%lon_w)
+ IF (allocated(this%ginfo%lon_e)) deallocate(this%ginfo%lon_e)
+ IF (allocated(this%ginfo%lon_c)) deallocate(this%ginfo%lon_c)
+
+ END SUBROUTINE grid_concat_free_mem
+
+ ! -------
+ SUBROUTINE get_region_by_this_IO ( grid, &
+ west, east, north, south, iwest, ieast, isouth, inorth)
+
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+
+ real(r8), intent(out) :: west, east, north, south
+ integer, intent(out) :: iwest, ieast, inorth, isouth
+
+ ! Local Variables
+ integer :: iblk, jblk
+
+ IF (p_is_active) THEN
+
+ IF (gblock%nblkme /= 1) THEN
+ write(*,*) 'Warning: more than one block is on IO processor: ', p_iam_glb
+ west = spval; iwest = -1
+ east = spval; ieast = -1
+ north = spval; inorth = -1
+ south = spval; isouth = -1
+ RETURN
+ ENDIF
+
+ iblk = gblock%xblkme(1)
+ jblk = gblock%yblkme(1)
+
+ iwest = grid%xdsp(iblk) + 1
+ ieast = grid%xdsp(iblk) + grid%xcnt(iblk)
+
+ IF (grid%yinc == 1) THEN
+ inorth = grid%ydsp(jblk) + grid%ycnt(jblk)
+ isouth = grid%ydsp(jblk) + 1
+ ELSE
+ inorth = grid%ydsp(jblk) + 1
+ isouth = grid%ydsp(jblk) + grid%ycnt(jblk)
+ ENDIF
+
+ west = grid%lon_w(iwest )
+ east = grid%lon_e(ieast )
+ north = grid%lat_n(inorth)
+ south = grid%lat_s(isouth)
+
+ ENDIF
+
+ END SUBROUTINE get_region_by_this_IO
+
+END MODULE MOD_Grid
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_HRUVector.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_HRUVector.F90
new file mode 100644
index 0000000000..8115d9cab3
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_HRUVector.F90
@@ -0,0 +1,215 @@
+#include
+
+#if (defined CATCHMENT)
+MODULE MOD_HRUVector
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Address of Data associated with HRU.
+!
+! To output a vector, Data is gathered from compute ranks directly to
+! root rank. "hru_data_address" stores information on how to reorganize data
+! gathered. The output data in vector is sorted by global element index
+! (i.e. catchment index)
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ integer :: totalnumhru
+ type(pointer_int32_1d), allocatable :: hru_data_address (:)
+
+ integer*8, allocatable :: eindx_hru (:)
+ integer, allocatable :: htype_hru (:)
+
+CONTAINS
+
+ ! --------
+ SUBROUTINE hru_vector_init
+
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_LandHRU
+ USE MOD_LandPatch
+ USE MOD_ElmVector
+#ifdef CROP
+ USE MOD_LandCrop
+#endif
+ IMPLICIT NONE
+
+ ! Local Variables
+ integer :: mesg(2), iwork, isrc, ndata
+
+ integer, allocatable :: nhru_bsn (:)
+ integer, allocatable :: nhru_bsn_glb (:)
+ integer, allocatable :: rbuff (:)
+
+ integer, allocatable :: hru_dsp_glb (:)
+ integer :: ielm, i, ielm_glb
+
+ integer :: nhru, nelm, hru_dsp_loc
+
+ IF (p_is_compute) THEN
+
+ CALL elm_hru%build (landelm, landhru, use_frac = .true.)
+
+ CALL hru_patch%build (landhru, landpatch, use_frac = .true.)
+
+ IF (numelm > 0) THEN
+ allocate (nhru_bsn (numelm))
+ nhru_bsn = elm_hru%subend - elm_hru%substt + 1
+ ENDIF
+
+#ifdef USEMPI
+ mesg = (/p_iam_glb, numelm/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numelm > 0) THEN
+ CALL mpi_send (nhru_bsn, numelm, MPI_INTEGER, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+#endif
+ ENDIF
+
+ IF (p_is_root) THEN
+
+ allocate (hru_data_address (0:p_np_compute-1))
+
+ allocate (nhru_bsn_glb (totalnumelm))
+
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate (rbuff (ndata))
+
+ CALL mpi_recv (rbuff, ndata, MPI_INTEGER, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+
+ nhru_bsn_glb(elm_data_address(p_itis_compute(isrc))%val) = rbuff
+
+ IF (sum(rbuff) > 0) THEN
+ allocate(hru_data_address(p_itis_compute(isrc))%val (sum(rbuff)))
+ ENDIF
+
+ deallocate(rbuff)
+ ENDIF
+ ENDDO
+#else
+ nhru_bsn_glb(elm_data_address(0)%val) = nhru_bsn
+ IF (sum(nhru_bsn) > 0) THEN
+ allocate(hru_data_address(0)%val (sum(nhru_bsn)))
+ ENDIF
+#endif
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+
+ totalnumhru = sum(nhru_bsn_glb)
+
+ allocate (hru_dsp_glb (totalnumelm))
+ hru_dsp_glb(1) = 0
+ DO ielm = 2, totalnumelm
+ hru_dsp_glb(ielm) = hru_dsp_glb(ielm-1) + nhru_bsn_glb(ielm-1)
+ ENDDO
+
+ DO iwork = 0, p_np_compute-1
+ IF (allocated(elm_data_address(iwork)%val)) THEN
+ nelm = size(elm_data_address(iwork)%val)
+ hru_dsp_loc = 0
+ DO ielm = 1, nelm
+ ielm_glb = elm_data_address(iwork)%val(ielm)
+ nhru = nhru_bsn_glb(ielm_glb)
+ IF (nhru > 0) THEN
+ hru_data_address(iwork)%val (hru_dsp_loc+1:hru_dsp_loc+nhru) = &
+ (/ (i, i = hru_dsp_glb(ielm_glb)+1, hru_dsp_glb(ielm_glb)+nhru) /)
+ hru_dsp_loc = hru_dsp_loc + nhru
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_bcast (totalnumhru, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#endif
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ mesg = (/p_iam_glb, numhru/)
+ CALL mpi_send (mesg, 2, MPI_INTEGER, p_address_root, mpi_tag_mesg, p_comm_glb, p_err)
+ IF (numhru > 0) THEN
+ CALL mpi_send (landhru%settyp, numhru, MPI_INTEGER, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDIF
+#endif
+
+ IF (p_is_root) THEN
+
+ allocate (eindx_hru (totalnumhru))
+
+ DO ielm = 1, totalnumelm
+ eindx_hru(hru_dsp_glb(ielm)+1:hru_dsp_glb(ielm)+nhru_bsn_glb(ielm)) = &
+ eindex_glb(ielm)
+ ENDDO
+
+ allocate (htype_hru (totalnumhru))
+
+#ifdef USEMPI
+ DO iwork = 0, p_np_compute-1
+ CALL mpi_recv (mesg, 2, MPI_INTEGER, MPI_ANY_SOURCE, &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = mesg(1)
+ ndata = mesg(2)
+ IF (ndata > 0) THEN
+ allocate (rbuff (ndata))
+
+ CALL mpi_recv (rbuff, ndata, MPI_INTEGER, isrc, &
+ mpi_tag_data, p_comm_glb, p_stat, p_err)
+ htype_hru(hru_data_address(p_itis_compute(isrc))%val) = rbuff
+
+ deallocate(rbuff)
+ ENDIF
+ ENDDO
+#else
+ htype_hru(hru_data_address(0)%val) = landhru%settyp
+#endif
+
+ ! To distinguish between lake HRUs and hillslopes, the program sets the
+ ! type of lake HRUs as a negative number.
+ ! Set it as a positive number for output.
+ htype_hru = abs(htype_hru)
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (totalnumhru, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE hru_vector_init
+
+ ! ----------
+ SUBROUTINE hru_vector_final ()
+
+ IMPLICIT NONE
+
+ IF (allocated(hru_data_address)) deallocate (hru_data_address)
+ IF (allocated(eindx_hru)) deallocate (eindx_hru)
+ IF (allocated(htype_hru)) deallocate (htype_hru)
+
+ END SUBROUTINE hru_vector_final
+
+END MODULE MOD_HRUVector
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_IncompleteGamma.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_IncompleteGamma.F90
new file mode 100644
index 0000000000..2d8a195d55
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_IncompleteGamma.F90
@@ -0,0 +1,946 @@
+MODULE MOD_IncompleteGamma
+
+ USE MOD_Precision, ONLY: r8
+ IMPLICIT REAL(KIND=r8) (A-H,O-Z)
+
+! ALGORITHM 654, COLLECTED ALGORITHMS FROM ACM.
+! THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE,
+! VOL. 13, NO. 3, P. 318.
+
+CONTAINS
+
+ SUBROUTINE GRATIO (A, X, ANS, QANS, IND)
+! ----------------------------------------------------------------------
+! EVALUATION OF THE INCOMPLETE GAMMA RATIO FUNCTIONS
+! P(A,X) AND Q(A,X)
+!
+! ----------
+!
+! IT IS ASSUMED THAT A AND X ARE NONNEGATIVE, WHERE A AND X
+! ARE NOT BOTH 0.
+!
+! ANS AND QANS ARE VARIABLES. GRATIO ASSIGNS ANS THE VALUE
+! P(A,X) AND QANS THE VALUE Q(A,X). IND MAY BE ANY INTEGER.
+! IF IND = 0 THEN THE USER IS REQUESTING AS MUCH ACCURACY AS
+! POSSIBLE (UP TO 14 SIGNIFICANT DIGITS). OTHERWISE, IF
+! IND = 1 THEN ACCURACY IS REQUESTED TO WITHIN 1 UNIT OF THE
+! 6-TH SIGNIFICANT DIGIT, AND IF IND .NE. 0,1 THEN ACCURACY
+! IS REQUESTED TO WITHIN 1 UNIT OF THE 3RD SIGNIFICANT DIGIT.
+!
+! ERROR RETURN ...
+! ANS IS ASSIGNED THE VALUE 2 WHEN A OR X IS NEGATIVE,
+! WHEN A*X = 0, OR WHEN P(A,X) AND Q(A,X) ARE INDETERMINANT.
+! P(A,X) AND Q(A,X) ARE COMPUTATIONALLY INDETERMINANT WHEN
+! X IS EXCEEDINGLY CLOSE TO A AND A IS EXTREMELY LARGE.
+! ----------------------------------------------------------------------
+! WRITTEN BY ALFRED H. MORRIS, JR.
+! NAVAL SURFACE WEAPONS CENTER
+! DAHLGREN, VIRGINIA
+! --------------------
+ REAL(r8) J, L, ACC0(3), BIG(3), E00(3), X00(3), WK(20)
+ REAL(r8) D0(13), D1(12), D2(10), D3(8), D4(6), D5(4), D6(2)
+! --------------------
+ DATA ACC0(1)/5.E-15/, ACC0(2)/5.E-7/, ACC0(3)/5.E-4/
+ DATA BIG(1)/20.0/, BIG(2)/14.0/, BIG(3)/10.0/
+ DATA E00(1)/.25E-3/, E00(2)/.25E-1/, E00(3)/.14/
+ DATA X00(1)/31.0/, X00(2)/17.0/, X00(3)/9.7/
+! --------------------
+! ALOG10 = LN(10)
+! RT2PIN = 1/SQRT(2*PI)
+! RTPI = SQRT(PI)
+! --------------------
+ DATA ALOG10/2.30258509299405/
+ DATA RT2PIN/.398942280401433/
+ DATA RTPI /1.77245385090552/
+ DATA THIRD /.333333333333333/
+! --------------------
+ DATA D0(1) / .833333333333333E-01/, D0(2) /-.148148148148148E-01/, &
+ D0(3) / .115740740740741E-02/, D0(4) / .352733686067019E-03/, &
+ D0(5) /-.178755144032922E-03/, D0(6) / .391926317852244E-04/, &
+ D0(7) /-.218544851067999E-05/, D0(8) /-.185406221071516E-05/, &
+ D0(9) / .829671134095309E-06/, D0(10)/-.176659527368261E-06/, &
+ D0(11)/ .670785354340150E-08/, D0(12)/ .102618097842403E-07/, &
+ D0(13)/-.438203601845335E-08/
+! --------------------
+ DATA D10 /-.185185185185185E-02/, D1(1) /-.347222222222222E-02/, &
+ D1(2) / .264550264550265E-02/, D1(3) /-.990226337448560E-03/, &
+ D1(4) / .205761316872428E-03/, D1(5) /-.401877572016461E-06/, &
+ D1(6) /-.180985503344900E-04/, D1(7) / .764916091608111E-05/, &
+ D1(8) /-.161209008945634E-05/, D1(9) / .464712780280743E-08/, &
+ D1(10)/ .137863344691572E-06/, D1(11)/-.575254560351770E-07/, &
+ D1(12)/ .119516285997781E-07/
+! --------------------
+ DATA D20 / .413359788359788E-02/, D2(1) /-.268132716049383E-02/, &
+ D2(2) / .771604938271605E-03/, D2(3) / .200938786008230E-05/, &
+ D2(4) /-.107366532263652E-03/, D2(5) / .529234488291201E-04/, &
+ D2(6) /-.127606351886187E-04/, D2(7) / .342357873409614E-07/, &
+ D2(8) / .137219573090629E-05/, D2(9) /-.629899213838006E-06/, &
+ D2(10)/ .142806142060642E-06/
+! --------------------
+ DATA D30 / .649434156378601E-03/, D3(1) / .229472093621399E-03/, &
+ D3(2) /-.469189494395256E-03/, D3(3) / .267720632062839E-03/, &
+ D3(4) /-.756180167188398E-04/, D3(5) /-.239650511386730E-06/, &
+ D3(6) / .110826541153473E-04/, D3(7) /-.567495282699160E-05/, &
+ D3(8) / .142309007324359E-05/
+! --------------------
+ DATA D40 /-.861888290916712E-03/, D4(1) / .784039221720067E-03/, &
+ D4(2) /-.299072480303190E-03/, D4(3) /-.146384525788434E-05/, &
+ D4(4) / .664149821546512E-04/, D4(5) /-.396836504717943E-04/, &
+ D4(6) / .113757269706784E-04/
+! --------------------
+ DATA D50 /-.336798553366358E-03/, D5(1) /-.697281375836586E-04/, &
+ D5(2) / .277275324495939E-03/, D5(3) /-.199325705161888E-03/, &
+ D5(4) / .679778047793721E-04/
+! --------------------
+ DATA D60 / .531307936463992E-03/, D6(1) /-.592166437353694E-03/, &
+ D6(2) / .270878209671804E-03/
+! --------------------
+ DATA D70 / .344367606892378E-03/
+! --------------------
+! ****** E IS A MACHINE DEPENDENT CONSTANT. E IS THE SMALLEST
+! FLOATING POINT NUMBER FOR WHICH 1.0 + E .GT. 1.0 .
+!
+! E = SPMPAR(1)
+ E = epsilon(1._r8)
+!
+! --------------------
+ IF (A .LT. 0.0 .OR. X .LT. 0.0) GO TO 400
+ IF (A .EQ. 0.0 .AND. X .EQ. 0.0) GO TO 400
+ IF (A*X .EQ. 0.0) GO TO 331
+!
+ IOP = IND + 1
+ IF (IOP .NE. 1 .AND. IOP .NE. 2) IOP = 3
+ ACC = DMAX1(ACC0(IOP),E)
+ E0 = E00(IOP)
+ X0 = X00(IOP)
+!
+! SELECT THE APPROPRIATE ALGORITHM
+!
+ IF (A .GE. 1.0) GO TO 10
+ IF (A .EQ. 0.5) GO TO 320
+ IF (X .LT. 1.1) GO TO 110
+ T1 = A*LOG(X) - X
+ U = A*EXP(T1)
+ IF (U .EQ. 0.0) GO TO 310
+ R = U*(1.0 + GAM1(A))
+ GO TO 170
+!
+ 10 IF (A .GE. BIG(IOP)) GO TO 20
+ IF (A .GT. X .OR. X .GE. X0) GO TO 11
+ TWOA = A + A
+ M = INT(TWOA)
+ IF (TWOA .NE. REAL(M, r8)) GO TO 11
+ I = M/2
+ IF (A .EQ. REAL(I, r8)) GO TO 140
+ GO TO 150
+ 11 T1 = A*LOG(X) - X
+ R = EXP(T1)/GAMMA(A)
+ GO TO 30
+!
+ 20 L = X/A
+ IF (L .EQ. 0.0) GO TO 300
+ S = 0.5 + (0.5 - L)
+ Z = RLOG(L)
+ IF (Z .GE. 700.0/A) GO TO 330
+ Y = A*Z
+ RTA = SQRT(A)
+ IF (ABS(S) .LE. E0/RTA) GO TO 250
+ IF (ABS(S) .LE. 0.4) GO TO 200
+!
+ T = (1.0/A)**2
+ T1 = (((0.75*T - 1.0)*T + 3.5)*T - 105.0)/(A*1260.0)
+ T1 = T1 - Y
+ R = RT2PIN*RTA*EXP(T1)
+!
+ 30 IF (R .EQ. 0.0) GO TO 331
+ IF (X .LE. DMAX1(A,ALOG10)) GO TO 50
+ IF (X .LT. X0) GO TO 170
+ GO TO 80
+!
+! TAYLOR SERIES FOR P/R
+!
+ 50 APN = A + 1.0
+ T = X/APN
+ WK(1) = T
+ DO N = 2,20
+ APN = APN + 1.0
+ T = T*(X/APN)
+ IF (T .LE. 1.E-3) GO TO 60
+ WK(N) = T
+ ENDDO
+ N = 20
+!
+ 60 SUM = T
+ TOL = 0.5*ACC
+ 61 APN = APN + 1.0
+ T = T*(X/APN)
+ SUM = SUM + T
+ IF (T .GT. TOL) GO TO 61
+!
+ MAX = N - 1
+ DO M = 1,MAX
+ N = N - 1
+ SUM = SUM + WK(N)
+ ENDDO
+ ANS = (R/A)*(1.0 + SUM)
+ QANS = 0.5 + (0.5 - ANS)
+ RETURN
+!
+! ASYMPTOTIC EXPANSION
+!
+ 80 AMN = A - 1.0
+ T = AMN/X
+ WK(1) = T
+ DO N = 2,20
+ AMN = AMN - 1.0
+ T = T*(AMN/X)
+ IF (ABS(T) .LE. 1.E-3) GO TO 90
+ WK(N) = T
+ ENDDO
+ N = 20
+!
+ 90 SUM = T
+ 91 IF (ABS(T) .LE. ACC) GO TO 100
+ AMN = AMN - 1.0
+ T = T*(AMN/X)
+ SUM = SUM + T
+ GO TO 91
+!
+ 100 MAX = N - 1
+ DO M = 1,MAX
+ N = N - 1
+ SUM = SUM + WK(N)
+ ENDDO
+ QANS = (R/X)*(1.0 + SUM)
+ ANS = 0.5 + (0.5 - QANS)
+ RETURN
+!
+! TAYLOR SERIES FOR P(A,X)/X**A
+!
+ 110 AN = 3.0
+ C = X
+ SUM = X/(A + 3.0)
+ TOL = 3.0*ACC/(A + 1.0)
+ 111 AN = AN + 1.0
+ C = -C*(X/AN)
+ T = C/(A + AN)
+ SUM = SUM + T
+ IF (ABS(T) .GT. TOL) GO TO 111
+ J = A*X*((SUM/6.0 - 0.5/(A + 2.0))*X + 1.0/(A + 1.0))
+!
+ Z = A*LOG(X)
+ H = GAM1(A)
+ G = 1.0 + H
+ IF (X .LT. 0.25) GO TO 120
+ IF (A .LT. X/2.59) GO TO 135
+ GO TO 130
+ 120 IF (Z .GT. -.13394) GO TO 135
+!
+ 130 W = EXP(Z)
+ ANS = W*G*(0.5 + (0.5 - J))
+ QANS = 0.5 + (0.5 - ANS)
+ RETURN
+!
+ 135 L = REXP(Z)
+ W = 0.5 + (0.5 + L)
+ QANS = (W*J - L)*G - H
+ IF (QANS .LT. 0.0) GO TO 310
+ ANS = 0.5 + (0.5 - QANS)
+ RETURN
+!
+! FINITE SUMS FOR Q WHEN A .GE. 1
+! AND 2*A IS AN INTEGER
+!
+ 140 SUM = EXP(-X)
+ T = SUM
+ N = 1
+ C = 0.0
+ GO TO 160
+!
+ 150 RTX = SQRT(X)
+ SUM = ERFC1(0,RTX)
+ T = EXP(-X)/(RTPI*RTX)
+ N = 0
+ C = -0.5
+!
+ 160 IF (N .EQ. I) GO TO 161
+ N = N + 1
+ C = C + 1.0
+ T = (X*T)/C
+ SUM = SUM + T
+ GO TO 160
+ 161 QANS = SUM
+ ANS = 0.5 + (0.5 - QANS)
+ RETURN
+!
+! CONTINUED FRACTION EXPANSION
+!
+ 170 TOL = DMAX1(5.0_r8*E,ACC)
+ A2NM1 = 1.0
+ A2N = 1.0
+ B2NM1 = X
+ B2N = X + (1.0 - A)
+ C = 1.0
+ 171 A2NM1 = X*A2N + C*A2NM1
+ B2NM1 = X*B2N + C*B2NM1
+ AM0 = A2NM1/B2NM1
+ C = C + 1.0
+ CMA = C - A
+ A2N = A2NM1 + CMA*A2N
+ B2N = B2NM1 + CMA*B2N
+ AN0 = A2N/B2N
+ IF (ABS(AN0 - AM0) .GE. TOL*AN0) GO TO 171
+!
+ QANS = R*AN0
+ ANS = 0.5 + (0.5 - QANS)
+ RETURN
+!
+! GENERAL TEMME EXPANSION
+!
+ 200 IF (ABS(S) .LE. 2.0*E .AND. A*E*E .GT. 3.28E-3) GO TO 400
+ C = EXP(-Y)
+ W = 0.5*ERFC1(1,SQRT(Y))
+ U = 1.0/A
+ Z = SQRT(Z + Z)
+ IF (L .LT. 1.0) Z = -Z
+ IF (IOP < 2) THEN
+ GO TO 210
+ ELSEIF (IOP == 2) THEN
+ GO TO 220
+ ELSE
+ GO TO 230
+ ENDIF
+!
+ 210 IF (ABS(S) .LE. 1.E-3) GO TO 260
+ C0 = ((((((((((((D0(13) * Z + D0(12)) * Z + D0(11)) * Z &
+ + D0(10)) * Z + D0(9)) * Z + D0(8)) * Z + D0(7)) * Z &
+ + D0(6)) * Z + D0(5)) * Z + D0(4)) * Z + D0(3)) * Z &
+ + D0(2)) * Z + D0(1)) * Z - THIRD
+ C1 = (((((((((((D1(12) * Z + D1(11)) * Z + D1(10)) * Z &
+ + D1(9)) * Z + D1(8)) * Z + D1(7)) * Z + D1(6)) * Z &
+ + D1(5)) * Z + D1(4)) * Z + D1(3)) * Z + D1(2)) * Z &
+ + D1(1)) * Z + D10
+ C2 = (((((((((D2(10) * Z + D2(9)) * Z + D2(8)) * Z &
+ + D2(7)) * Z + D2(6)) * Z + D2(5)) * Z + D2(4)) * Z &
+ + D2(3)) * Z + D2(2)) * Z + D2(1)) * Z + D20
+ C3 = (((((((D3(8) * Z + D3(7)) * Z + D3(6)) * Z &
+ + D3(5)) * Z + D3(4)) * Z + D3(3)) * Z + D3(2)) * Z &
+ + D3(1)) * Z + D30
+ C4 = (((((D4(6) * Z + D4(5)) * Z + D4(4)) * Z + D4(3)) * Z &
+ + D4(2)) * Z + D4(1)) * Z + D40
+ C5 = (((D5(4) * Z + D5(3)) * Z + D5(2)) * Z + D5(1)) * Z &
+ + D50
+ C6 = (D6(2) * Z + D6(1)) * Z + D60
+ T = ((((((D70*U + C6)*U + C5)*U + C4)*U + C3)*U + C2)*U &
+ + C1)*U + C0
+ GO TO 240
+!
+ 220 C0 = (((((D0(6) * Z + D0(5)) * Z + D0(4)) * Z + D0(3)) * Z &
+ + D0(2)) * Z + D0(1)) * Z - THIRD
+ C1 = (((D1(4) * Z + D1(3)) * Z + D1(2)) * Z + D1(1)) * Z &
+ + D10
+ C2 = D2(1) * Z + D20
+ T = (C2*U + C1)*U + C0
+ GO TO 240
+!
+ 230 T = ((D0(3) * Z + D0(2)) * Z + D0(1)) * Z - THIRD
+!
+ 240 IF (L .LT. 1.0) GO TO 241
+ QANS = C*(W + RT2PIN*T/RTA)
+ ANS = 0.5 + (0.5 - QANS)
+ RETURN
+ 241 ANS = C*(W - RT2PIN*T/RTA)
+ QANS = 0.5 + (0.5 - ANS)
+ RETURN
+!
+! TEMME EXPANSION FOR L = 1
+!
+ 250 IF (A*E*E .GT. 3.28E-3) GO TO 400
+ C = 0.5 + (0.5 - Y)
+ W = (0.5 - SQRT(Y)*(0.5 + (0.5 - Y/3.0))/RTPI)/C
+ U = 1.0/A
+ Z = SQRT(Z + Z)
+ IF (L .LT. 1.0) Z = -Z
+ IF (IOP < 2) THEN
+ GO TO 260
+ ELSEIF (IOP == 2) THEN
+ GO TO 270
+ ELSE
+ GO TO 280
+ ENDIF
+!
+ 260 C0 = ((((((D0(7) * Z + D0(6)) * Z + D0(5)) * Z + D0(4)) * Z &
+ + D0(3)) * Z + D0(2)) * Z + D0(1)) * Z - THIRD
+ C1 = (((((D1(6) * Z + D1(5)) * Z + D1(4)) * Z + D1(3)) * Z &
+ + D1(2)) * Z + D1(1)) * Z + D10
+ C2 = ((((D2(5) * Z + D2(4)) * Z + D2(3)) * Z + D2(2)) * Z &
+ + D2(1)) * Z + D20
+ C3 = (((D3(4) * Z + D3(3)) * Z + D3(2)) * Z + D3(1)) * Z &
+ + D30
+ C4 = (D4(2) * Z + D4(1)) * Z + D40
+ C5 = (D5(2) * Z + D5(1)) * Z + D50
+ C6 = D6(1) * Z + D60
+ T = ((((((D70*U + C6)*U + C5)*U + C4)*U + C3)*U + C2)*U &
+ + C1)*U + C0
+ GO TO 240
+!
+ 270 C0 = (D0(2) * Z + D0(1)) * Z - THIRD
+ C1 = D1(1) * Z + D10
+ T = (D20*U + C1)*U + C0
+ GO TO 240
+!
+ 280 T = D0(1) * Z - THIRD
+ GO TO 240
+!
+! SPECIAL CASES
+!
+ 300 ANS = 0.0
+ QANS = 1.0
+ RETURN
+!
+ 310 ANS = 1.0
+ QANS = 0.0
+ RETURN
+!
+ 320 IF (X .GE. 0.25) GO TO 321
+ ANS = ERF(SQRT(X))
+ QANS = 0.5 + (0.5 - ANS)
+ RETURN
+ 321 QANS = ERFC1(0,SQRT(X))
+ ANS = 0.5 + (0.5 - QANS)
+ RETURN
+!
+ 330 IF (ABS(S) .LE. 2.0*E) GO TO 400
+ 331 IF (X .LE. A) GO TO 300
+ GO TO 310
+!
+! ERROR RETURN
+!
+ 400 ANS = 2.0
+ RETURN
+
+ END SUBROUTINE
+
+
+
+ FUNCTION ERF(X)
+! ******************************************************************
+! EVALUATION OF THE REAL ERROR FUNCTION
+! ******************************************************************
+ DIMENSION A(4),B(4),P(8),Q(8),R(5),S(5)
+ DATA A(1)/-1.65581836870402E-4/, A(2)/3.25324098357738E-2/, &
+ A(3)/1.02201136918406E-1/, A(4)/1.12837916709552E00/
+ DATA B(1)/4.64988945913179E-3/, B(2)/7.01333417158511E-2/, &
+ B(3)/4.23906732683201E-1/, B(4)/1.00000000000000E00/
+ DATA P(1)/-1.36864857382717E-7/, P(2)/5.64195517478974E-1/, &
+ P(3)/7.21175825088309E00/, P(4)/4.31622272220567E01/, &
+ P(5)/1.52989285046940E02/, P(6)/3.39320816734344E02/, &
+ P(7)/4.51918953711873E02/, P(8)/3.00459261020162E02/
+ DATA Q(1)/1.00000000000000E00/, Q(2)/1.27827273196294E01/, &
+ Q(3)/7.70001529352295E01/, Q(4)/2.77585444743988E02/, &
+ Q(5)/6.38980264465631E02/, Q(6)/9.31354094850610E02/, &
+ Q(7)/7.90950925327898E02/, Q(8)/3.00459260956983E02/
+ DATA R(1)/2.10144126479064E00/, R(2)/2.62370141675169E01/, &
+ R(3)/2.13688200555087E01/, R(4)/4.65807828718470E00/, &
+ R(5)/2.82094791773523E-1/
+ DATA S(1)/9.41537750555460E01/, S(2)/1.87114811799590E02/, &
+ S(3)/9.90191814623914E01/, S(4)/1.80124575948747E01/, &
+ S(5)/1.00000000000000E00/
+ DATA C/5.64189583547756E-1/
+! -------------------
+ AX=ABS(X)
+ X2=AX*AX
+ IF (AX.GE.0.5) GO TO 10
+ TOP=((A(1)*X2+A(2))*X2+A(3))*X2+A(4)
+ BOT=((B(1)*X2+B(2))*X2+B(3))*X2+B(4)
+ ERF=X*TOP/BOT
+ RETURN
+!
+ 10 IF (AX.GT.4.0) GO TO 20
+ TOP=((((((P(1)*AX+P(2))*AX+P(3))*AX+P(4))*AX+P(5))*AX &
+ +P(6))*AX+P(7))*AX+P(8)
+ BOT=((((((Q(1)*AX+Q(2))*AX+Q(3))*AX+Q(4))*AX+Q(5))*AX &
+ +Q(6))*AX+Q(7))*AX+Q(8)
+ ERF=1.0-EXP(-X2)*TOP/BOT
+ IF (X.LT.0.0) ERF=-ERF
+ RETURN
+!
+ 20 ERF=1.0
+ IF (AX.GE.5.54) GO TO 21
+ T=1.0/X2
+ TOP=(((R(1)*T+R(2))*T+R(3))*T+R(4))*T+R(5)
+ BOT=(((S(1)*T+S(2))*T+S(3))*T+S(4))*T+S(5)
+ ERF=C-TOP/(X2*BOT)
+ ERF=1.0-EXP(-X2)*ERF/AX
+ 21 IF (X.LT.0.0) ERF=-ERF
+ RETURN
+
+ END FUNCTION
+
+
+
+ REAL(r8) FUNCTION ERFC1(IND,X)
+! ----------------------------------------------------------------------
+! EVALUATION OF THE REAL COMPLEMENTARY ERROR FUNCTION
+!
+! ERFC1(IND,X) = ERFC(X) IF IND = 0
+! ERFC1(IND,X) = EXP(X*X)*ERFC(X) OTHERWISE
+! ----------------------------------------------------------------------
+ DIMENSION A(4),B(4),P(8),Q(8),R(5),S(5)
+ DATA A(1)/-1.65581836870402E-4/, A(2)/3.25324098357738E-2/, &
+ A(3)/1.02201136918406E-1/, A(4)/1.12837916709552E00/
+ DATA B(1)/4.64988945913179E-3/, B(2)/7.01333417158511E-2/, &
+ B(3)/4.23906732683201E-1/, B(4)/1.00000000000000E00/
+ DATA P(1)/-1.36864857382717E-7/, P(2)/5.64195517478974E-1/, &
+ P(3)/7.21175825088309E00/, P(4)/4.31622272220567E01/, &
+ P(5)/1.52989285046940E02/, P(6)/3.39320816734344E02/, &
+ P(7)/4.51918953711873E02/, P(8)/3.00459261020162E02/
+ DATA Q(1)/1.00000000000000E00/, Q(2)/1.27827273196294E01/, &
+ Q(3)/7.70001529352295E01/, Q(4)/2.77585444743988E02/, &
+ Q(5)/6.38980264465631E02/, Q(6)/9.31354094850610E02/, &
+ Q(7)/7.90950925327898E02/, Q(8)/3.00459260956983E02/
+ DATA R(1)/2.10144126479064E00/, R(2)/2.62370141675169E01/, &
+ R(3)/2.13688200555087E01/, R(4)/4.65807828718470E00/, &
+ R(5)/2.82094791773523E-1/
+ DATA S(1)/9.41537750555460E01/, S(2)/1.87114811799590E02/, &
+ S(3)/9.90191814623914E01/, S(4)/1.80124575948747E01/, &
+ S(5)/1.00000000000000E00/
+ DATA C/5.64189583547756E-1/
+! -------------------
+ AX=ABS(X)
+ X2=AX*AX
+ IF (AX.GE.0.47) GO TO 10
+ TOP=((A(1)*X2+A(2))*X2+A(3))*X2+A(4)
+ BOT=((B(1)*X2+B(2))*X2+B(3))*X2+B(4)
+ ERFC1=1.0-X*TOP/BOT
+ IF (IND.NE.0) ERFC1=EXP(X2)*ERFC1
+ RETURN
+!
+ 10 IF (AX.GT.4.0) GO TO 20
+ TOP=((((((P(1)*AX+P(2))*AX+P(3))*AX+P(4))*AX+P(5))*AX &
+ +P(6))*AX+P(7))*AX+P(8)
+ BOT=((((((Q(1)*AX+Q(2))*AX+Q(3))*AX+Q(4))*AX+Q(5))*AX &
+ +Q(6))*AX+Q(7))*AX+Q(8)
+ ERFC1=TOP/BOT
+ IF (IND.EQ.0) GO TO 11
+ IF (X.LT.0.0) ERFC1=2.0*EXP(X2)-ERFC1
+ RETURN
+ 11 ERFC1=EXP(-X2)*ERFC1
+ IF (X.LT.0.0) ERFC1=2.0-ERFC1
+ RETURN
+!
+ 20 IF (X.LE.-5.33) GO TO 30
+ T=1.0/X2
+ TOP=(((R(1)*T+R(2))*T+R(3))*T+R(4))*T+R(5)
+ BOT=(((S(1)*T+S(2))*T+S(3))*T+S(4))*T+S(5)
+ ERFC1=(C-TOP/(X2*BOT))/AX
+ IF (IND.EQ.0) GO TO 11
+ IF (X.LT.0.0) ERFC1=2.0*EXP(X2)-ERFC1
+ RETURN
+!
+ 30 ERFC1=2.0
+ IF (IND.NE.0) ERFC1=EXP(X2)*ERFC1
+ RETURN
+
+ END FUNCTION
+
+
+
+ REAL(r8) FUNCTION REXP(X)
+! ------------------------------------------------------------------
+! COMPUTATION OF EXP(X) - 1
+! ------------------------------------------------------------------
+ DATA P1/ .914041914819518E-09/, P2/ .238082361044469E-01/, &
+ Q1/-.499999999085958E+00/, Q2/ .107141568980644E+00/, &
+ Q3/-.119041179760821E-01/, Q4/ .595130811860248E-03/
+! ------------------
+ IF (ABS(X) .GT. 0.15) GO TO 10
+ REXP = X*(((P2*X + P1)*X + 1.0)/((((Q4*X + Q3)*X + Q2)*X &
+ + Q1)*X + 1.0))
+ RETURN
+!
+ 10 W = EXP(X)
+ IF (X .GT. 0.0) GO TO 20
+ REXP = (W - 0.5) - 0.5
+ RETURN
+ 20 REXP = W*(0.5 + (0.5 - 1.0/W))
+ RETURN
+ END FUNCTION
+
+
+
+ REAL(r8) FUNCTION RLOG(X)
+! -------------------
+! COMPUTATION OF X - 1 - LN(X)
+! -------------------
+ DATA A/.566749439387324E-01/
+ DATA B/.456512608815524E-01/
+! -------------------
+ DATA P0/ .333333333333333E+00/, P1/-.224696413112536E+00/, &
+ P2/ .620886815375787E-02/
+ DATA Q1/-.127408923933623E+01/, Q2/ .354508718369557E+00/
+! -------------------
+ IF (X .LT. 0.61 .OR. X .GT. 1.57) GO TO 100
+ IF (X .LT. 0.82) GO TO 10
+ IF (X .GT. 1.18) GO TO 20
+!
+! ARGUMENT REDUCTION
+!
+ U = (X - 0.5) - 0.5
+ W1 = 0.0
+ GO TO 30
+!
+ 10 U = DBLE(X) - 0.7D0
+ U = U/0.7
+ W1 = A - U*0.3
+ GO TO 30
+!
+ 20 U = 0.75D0*DBLE(X) - 1.D0
+ W1 = B + U/3.0
+!
+! SERIES EXPANSION
+!
+ 30 R = U/(U + 2.0)
+ T = R*R
+ W = ((P2*T + P1)*T + P0)/((Q2*T + Q1)*T + 1.0)
+ RLOG = 2.0*T*(1.0/(1.0 - R) - R*W) + W1
+ RETURN
+!
+!
+ 100 R = (X - 0.5) - 0.5
+ RLOG = R - LOG(X)
+ RETURN
+
+ END FUNCTION
+
+
+
+ REAL(r8) FUNCTION GAMMA(A)
+!-----------------------------------------------------------------------
+!
+! EVALUATION OF THE GAMMA FUNCTION FOR REAL ARGUMENTS
+!
+! -----------
+!
+! GAMMA(A) IS ASSIGNED THE VALUE 0 WHEN THE GAMMA FUNCTION CANNOT
+! BE COMPUTED.
+!
+!-----------------------------------------------------------------------
+! WRITTEN BY ALFRED H. MORRIS, JR.
+! NAVAL SURFACE WEAPONS CENTER
+! DAHLGREN, VIRGINIA
+!-----------------------------------------------------------------------
+ REAL(r8) P(7), Q(7)
+ DOUBLE PRECISION D, G, Z, LNX
+!--------------------------
+! D = 0.5*(LN(2*PI) - 1)
+!--------------------------
+ DATA PI /3.1415926535898/
+ DATA D /.41893853320467274178D0/
+!--------------------------
+ DATA P(1)/ .539637273585445E-03/, P(2)/ .261939260042690E-02/, &
+ P(3)/ .204493667594920E-01/, P(4)/ .730981088720487E-01/, &
+ P(5)/ .279648642639792E+00/, P(6)/ .553413866010467E+00/, &
+ P(7)/ 1.0/
+ DATA Q(1)/-.832979206704073E-03/, Q(2)/ .470059485860584E-02/, &
+ Q(3)/ .225211131035340E-01/, Q(4)/-.170458969313360E+00/, &
+ Q(5)/-.567902761974940E-01/, Q(6)/ .113062953091122E+01/, &
+ Q(7)/ 1.0/
+!--------------------------
+ DATA R1/.820756370353826E-03/, R2/-.595156336428591E-03/, &
+ R3/.793650663183693E-03/, R4/-.277777777770481E-02/, &
+ R5/.833333333333333E-01/
+!--------------------------
+ GAMMA = 0.0
+ X = A
+ IF (ABS(A) .GE. 15.0) GO TO 60
+!-----------------------------------------------------------------------
+! EVALUATION OF GAMMA(A) FOR ABS(A) .LT. 15
+!-----------------------------------------------------------------------
+ T = 1.0
+ M = INT(A) - 1
+!
+! LET T BE THE PRODUCT OF A-J WHEN A .GE. 2
+!
+ IF (M < 0) THEN
+ GO TO 20
+ ELSEIF (M == 0) THEN
+ GO TO 12
+ ELSE
+ GO TO 10
+ ENDIF
+
+ 10 DO J = 1,M
+ X = X - 1.0
+ T = X*T
+ ENDDO
+ 12 X = X - 1.0
+ GO TO 40
+!
+! LET T BE THE PRODUCT OF A+J WHEN A .LT. 1
+!
+ 20 T = A
+ IF (A .GT. 0.0) GO TO 30
+ M = - M - 1
+ IF (M .EQ. 0) GO TO 22
+ DO J = 1,M
+ X = X + 1.0
+ T = X*T
+ ENDDO
+ 22 X = (X + 0.5) + 0.5
+ T = X*T
+ IF (T .EQ. 0.0) RETURN
+!
+ 30 CONTINUE
+!
+! THE FOLLOWING CODE CHECKS IF 1/T CAN OVERFLOW. THIS
+! CODE MAY BE OMITTED IF DESIRED.
+!
+ IF (ABS(T) .GE. 1.E-30) GO TO 40
+! IF (ABS(T)*SPMPAR(3) .LE. 1.0001) RETURN
+ IF (ABS(T)*HUGE(1._r8) .LE. 1.0001) RETURN
+ GAMMA = 1.0/T
+ RETURN
+!
+! COMPUTE GAMMA(1 + X) FOR 0 .LE. X .LT. 1
+!
+ 40 TOP = P(1)
+ BOT = Q(1)
+ DO I = 2,7
+ TOP = P(I) + X*TOP
+ BOT = Q(I) + X*BOT
+ ENDDO
+ GAMMA = TOP/BOT
+!
+! TERMINATION
+!
+ IF (A .LT. 1.0) GO TO 50
+ GAMMA = GAMMA*T
+ RETURN
+ 50 GAMMA = GAMMA/T
+ RETURN
+!-----------------------------------------------------------------------
+! EVALUATION OF GAMMA(A) FOR ABS(A) .GE. 15
+!-----------------------------------------------------------------------
+ 60 IF (ABS(A) .GE. 1.E3) RETURN
+ IF (A .GT. 0.0) GO TO 70
+ X = -A
+ N = X
+ T = X - N
+ IF (T .GT. 0.9) T = 1.0 - T
+ S = SIN(PI*T)/PI
+ IF (MOD(N,2) .EQ. 0) S = -S
+ IF (S .EQ. 0.0) RETURN
+!
+! COMPUTE THE MODIFIED ASYMPTOTIC SUM
+!
+ 70 T = 1.0/(X*X)
+ G = ((((R1*T + R2)*T + R3)*T + R4)*T + R5)/X
+!
+! ONE MAY REPLACE THE NEXT STATEMENT WITH LNX = ALOG(X)
+! BUT LESS ACCURACY WILL NORMALLY BE OBTAINED.
+!
+ LNX = GLOG(X)
+!
+! FINAL ASSEMBLY
+!
+ Z = X
+ G = (D + G) + (Z - 0.5D0)*(LNX - 1.D0)
+ W = G
+ T = G - DBLE(W)
+ IF (W .GT. 0.99999*EXPARG(0)) RETURN
+ GAMMA = EXP(W)*(1.0 + T)
+ IF (A .LT. 0.0) GAMMA = (1.0/(GAMMA*S))/X
+ RETURN
+
+ END FUNCTION
+
+
+
+ DOUBLE PRECISION FUNCTION GLOG(X)
+! -------------------
+! EVALUATION OF LN(X) FOR X .GE. 15
+! -------------------
+ REAL(r8) X
+ DOUBLE PRECISION Z, W(163)
+! -------------------
+ DATA C1/.286228750476730/, C2/.399999628131494/, &
+ C3/.666666666752663/
+! -------------------
+! W(J) = LN(J + 14) FOR EACH J
+! -------------------
+ DATA W(1) /.270805020110221007D+01/, &
+ W(2) /.277258872223978124D+01/, W(3) /.283321334405621608D+01/, &
+ W(4) /.289037175789616469D+01/, W(5) /.294443897916644046D+01/, &
+ W(6) /.299573227355399099D+01/, W(7) /.304452243772342300D+01/, &
+ W(8) /.309104245335831585D+01/, W(9) /.313549421592914969D+01/, &
+ W(10)/.317805383034794562D+01/, W(11)/.321887582486820075D+01/, &
+ W(12)/.325809653802148205D+01/, W(13)/.329583686600432907D+01/, &
+ W(14)/.333220451017520392D+01/, W(15)/.336729582998647403D+01/, &
+ W(16)/.340119738166215538D+01/, W(17)/.343398720448514625D+01/, &
+ W(18)/.346573590279972655D+01/, W(19)/.349650756146648024D+01/, &
+ W(20)/.352636052461616139D+01/, W(21)/.355534806148941368D+01/, &
+ W(22)/.358351893845611000D+01/, W(23)/.361091791264422444D+01/, &
+ W(24)/.363758615972638577D+01/, W(25)/.366356164612964643D+01/, &
+ W(26)/.368887945411393630D+01/, W(27)/.371357206670430780D+01/, &
+ W(28)/.373766961828336831D+01/, W(29)/.376120011569356242D+01/, &
+ W(30)/.378418963391826116D+01/
+ DATA W(31)/.380666248977031976D+01/, &
+ W(32)/.382864139648909500D+01/, W(33)/.385014760171005859D+01/, &
+ W(34)/.387120101090789093D+01/, W(35)/.389182029811062661D+01/, &
+ W(36)/.391202300542814606D+01/, W(37)/.393182563272432577D+01/, &
+ W(38)/.395124371858142735D+01/, W(39)/.397029191355212183D+01/, &
+ W(40)/.398898404656427438D+01/, W(41)/.400733318523247092D+01/, &
+ W(42)/.402535169073514923D+01/, W(43)/.404305126783455015D+01/, &
+ W(44)/.406044301054641934D+01/, W(45)/.407753744390571945D+01/, &
+ W(46)/.409434456222210068D+01/, W(47)/.411087386417331125D+01/, &
+ W(48)/.412713438504509156D+01/, W(49)/.414313472639153269D+01/, &
+ W(50)/.415888308335967186D+01/, W(51)/.417438726989563711D+01/, &
+ W(52)/.418965474202642554D+01/, W(53)/.420469261939096606D+01/, &
+ W(54)/.421950770517610670D+01/, W(55)/.423410650459725938D+01/, &
+ W(56)/.424849524204935899D+01/, W(57)/.426267987704131542D+01/, &
+ W(58)/.427666611901605531D+01/, W(59)/.429045944114839113D+01/, &
+ W(60)/.430406509320416975D+01/
+ DATA W(61)/.431748811353631044D+01/, &
+ W(62)/.433073334028633108D+01/, W(63)/.434380542185368385D+01/, &
+ W(64)/.435670882668959174D+01/, W(65)/.436944785246702149D+01/, &
+ W(66)/.438202663467388161D+01/, W(67)/.439444915467243877D+01/, &
+ W(68)/.440671924726425311D+01/, W(69)/.441884060779659792D+01/, &
+ W(70)/.443081679884331362D+01/, W(71)/.444265125649031645D+01/, &
+ W(72)/.445434729625350773D+01/, W(73)/.446590811865458372D+01/, &
+ W(74)/.447733681447820647D+01/, W(75)/.448863636973213984D+01/, &
+ W(76)/.449980967033026507D+01/, W(77)/.451085950651685004D+01/, &
+ W(78)/.452178857704904031D+01/, W(79)/.453259949315325594D+01/, &
+ W(80)/.454329478227000390D+01/, W(81)/.455387689160054083D+01/, &
+ W(82)/.456434819146783624D+01/, W(83)/.457471097850338282D+01/, &
+ W(84)/.458496747867057192D+01/, W(85)/.459511985013458993D+01/, &
+ W(86)/.460517018598809137D+01/, W(87)/.461512051684125945D+01/, &
+ W(88)/.462497281328427108D+01/, W(89)/.463472898822963577D+01/, &
+ W(90)/.464439089914137266D+01/
+ DATA W(91) /.465396035015752337D+01/, &
+ W(92) /.466343909411206714D+01/, W(93) /.467282883446190617D+01/, &
+ W(94) /.468213122712421969D+01/, W(95) /.469134788222914370D+01/, &
+ W(96) /.470048036579241623D+01/, W(97) /.470953020131233414D+01/, &
+ W(98) /.471849887129509454D+01/, W(99) /.472738781871234057D+01/, &
+ W(100)/.473619844839449546D+01/, W(101)/.474493212836325007D+01/, &
+ W(102)/.475359019110636465D+01/, W(103)/.476217393479775612D+01/, &
+ W(104)/.477068462446566476D+01/, W(105)/.477912349311152939D+01/, &
+ W(106)/.478749174278204599D+01/, W(107)/.479579054559674109D+01/, &
+ W(108)/.480402104473325656D+01/, W(109)/.481218435537241750D+01/, &
+ W(110)/.482028156560503686D+01/, W(111)/.482831373730230112D+01/, &
+ W(112)/.483628190695147800D+01/, W(113)/.484418708645859127D+01/, &
+ W(114)/.485203026391961717D+01/, W(115)/.485981240436167211D+01/, &
+ W(116)/.486753445045558242D+01/, W(117)/.487519732320115154D+01/, &
+ W(118)/.488280192258637085D+01/, W(119)/.489034912822175377D+01/, &
+ W(120)/.489783979995091137D+01/
+ DATA W(121)/.490527477843842945D+01/, &
+ W(122)/.491265488573605201D+01/, W(123)/.491998092582812492D+01/, &
+ W(124)/.492725368515720469D+01/, W(125)/.493447393313069176D+01/, &
+ W(126)/.494164242260930430D+01/, W(127)/.494875989037816828D+01/, &
+ W(128)/.495582705760126073D+01/, W(129)/.496284463025990728D+01/, &
+ W(130)/.496981329957600062D+01/, W(131)/.497673374242057440D+01/, &
+ W(132)/.498360662170833644D+01/, W(133)/.499043258677873630D+01/, &
+ W(134)/.499721227376411506D+01/, W(135)/.500394630594545914D+01/, &
+ W(136)/.501063529409625575D+01/, W(137)/.501727983681492433D+01/, &
+ W(138)/.502388052084627639D+01/, W(139)/.503043792139243546D+01/, &
+ W(140)/.503695260241362916D+01/, W(141)/.504342511691924662D+01/, &
+ W(142)/.504985600724953705D+01/, W(143)/.505624580534830806D+01/, &
+ W(144)/.506259503302696680D+01/, W(145)/.506890420222023153D+01/, &
+ W(146)/.507517381523382692D+01/, W(147)/.508140436498446300D+01/, &
+ W(148)/.508759633523238407D+01/, W(149)/.509375020080676233D+01/, &
+ W(150)/.509986642782419842D+01/
+ DATA W(151)/.510594547390058061D+01/, &
+ W(152)/.511198778835654323D+01/, W(153)/.511799381241675511D+01/, &
+ W(154)/.512396397940325892D+01/, W(155)/.512989871492307347D+01/, &
+ W(156)/.513579843705026176D+01/, W(157)/.514166355650265984D+01/, &
+ W(158)/.514749447681345304D+01/, W(159)/.515329159449777895D+01/, &
+ W(160)/.515905529921452903D+01/, W(161)/.516478597392351405D+01/, &
+ W(162)/.517048399503815178D+01/, W(163)/.517614973257382914D+01/
+!
+ IF (X .GE. 178.0) GO TO 10
+ N = X
+ T = (X - N)/(X + N)
+ T2 = T*T
+ Z = (((C1*T2 + C2)*T2 + C3)*T2 + 2.0)*T
+ GLOG = W(N - 14) + Z
+ RETURN
+!
+ 10 GLOG = LOG(X)
+ RETURN
+
+ END FUNCTION
+
+
+
+ REAL(r8) FUNCTION EXPARG (IDUMMY)
+!--------------------------------------------------------------------
+! COMPUTATION OF THE LARGEST ARGUMENT W FOR WHICH EXP(W)
+! MAY BE COMPUTED. (ONLY AN APPROXIMATE VALUE IS NEEDED.)
+!--------------------------------------------------------------------
+! EXPARG = 0.99999*ALOG(SPMPAR(3))
+ EXPARG = 0.99999*LOG(HUGE(1._r8))
+ RETURN
+ END
+
+
+
+ REAL(r8) FUNCTION GAM1(A)
+! ------------------------------------------------------------------
+! COMPUTATION OF 1/GAMMA(A+1) - 1 FOR -0.5 .LE. A .LE. 1.5
+! ------------------------------------------------------------------
+ REAL(r8) P(7), Q(5), R(9)
+! -------------------
+ DATA P(1)/ .577215664901533E+00/, P(2)/-.409078193005776E+00/, &
+ P(3)/-.230975380857675E+00/, P(4)/ .597275330452234E-01/, &
+ P(5)/ .766968181649490E-02/, P(6)/-.514889771323592E-02/, &
+ P(7)/ .589597428611429E-03/
+! -------------------
+ DATA Q(1)/ .100000000000000E+01/, Q(2)/ .427569613095214E+00/, &
+ Q(3)/ .158451672430138E+00/, Q(4)/ .261132021441447E-01/, &
+ Q(5)/ .423244297896961E-02/
+! -------------------
+ DATA R(1)/-.422784335098468E+00/, R(2)/-.771330383816272E+00/, &
+ R(3)/-.244757765222226E+00/, R(4)/ .118378989872749E+00/, &
+ R(5)/ .930357293360349E-03/, R(6)/-.118290993445146E-01/, &
+ R(7)/ .223047661158249E-02/, R(8)/ .266505979058923E-03/, &
+ R(9)/-.132674909766242E-03/
+! -------------------
+ DATA S1 / .273076135303957E+00/, S2 / .559398236957378E-01/
+! -------------------
+ T = A
+ D = A - 0.5
+ IF (D .GT. 0.0) T = D - 0.5
+ IF (T < 0) THEN
+ GO TO 30
+ ELSEIF (T == 0) THEN
+ GO TO 10
+ ELSE
+ GO TO 20
+ ENDIF
+!
+ 10 GAM1 = 0.0
+ RETURN
+!
+ 20 TOP = (((((P(7)*T + P(6))*T + P(5))*T + P(4))*T + P(3))*T &
+ + P(2))*T + P(1)
+ BOT = (((Q(5)*T + Q(4))*T + Q(3))*T + Q(2))*T + 1.0
+ W = TOP/BOT
+ IF (D .GT. 0.0) GO TO 21
+ GAM1 = A*W
+ RETURN
+ 21 GAM1 = (T/A)*((W - 0.5) - 0.5)
+ RETURN
+!
+ 30 TOP = (((((((R(9)*T + R(8))*T + R(7))*T + R(6))*T + R(5))*T &
+ + R(4))*T + R(3))*T + R(2))*T + R(1)
+ BOT = (S2*T + S1)*T + 1.0
+ W = TOP/BOT
+ IF (D .GT. 0.0) GO TO 31
+ GAM1 = A*((W + 0.5) + 0.5)
+ RETURN
+ 31 GAM1 = T*W/A
+ RETURN
+
+ END FUNCTION
+
+END MODULE MOD_IncompleteGamma
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Land2mWMO.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Land2mWMO.F90
new file mode 100644
index 0000000000..e646025a2b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Land2mWMO.F90
@@ -0,0 +1,249 @@
+#include
+
+MODULE MOD_Land2mWMO
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+! Build a virtual patch "land2mWMO" for output 2 m WMO temperature.
+!
+! Created by Wenzong Dong and Hua Yuan, 2025/08
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_LandPatch
+ USE MOD_LandElm
+ USE MOD_Vars_Global
+ USE MOD_Const_LC
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ integer, allocatable :: wmo_patch (:) !2m wmo patch index
+ integer, allocatable :: wmo_source (:) !source patch of a wmo patch
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE land2mwmo_build (lc_year)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ USE MOD_UserDefFun
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_Namelist
+ USE MOD_NetCDFBlock
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year
+ character(len=255) :: cyear
+
+ integer :: numpatch_
+ integer :: numset
+ integer :: iset
+ integer :: spatch, epatch, ipatch, jpatch
+ integer :: ipth, numpxl, numpth
+ integer :: src_pth, pthtype, maxpxl
+ integer*8, allocatable :: eindex_(:)
+ integer, allocatable :: settyp_(:), ipxstt_(:), ipxend_(:), ielm_(:)
+ integer, allocatable :: locpth(:)
+
+ integer :: npatch_glb
+ integer :: numwmo
+
+ write(cyear,'(i4.4)') lc_year
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making land 2 m wmo patches:'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_compute) THEN
+
+ numset = numelm
+
+ numwmo = 0
+ numpatch_ = 0
+ jpatch = 0
+
+ ! Count for 2 m WMO patches need to be set virtually
+ DO iset = 1, numset
+
+ numpth = count(landpatch%eindex==landelm%eindex(iset))
+ IF (allocated(locpth)) deallocate(locpth)
+ allocate(locpth(numpth))
+ locpth = pack([(ipth, ipth=1, numpatch)], &
+ landpatch%eindex==landelm%eindex(iset))
+
+ spatch = minval(locpth) ! elm_patch%substt(iset)
+ epatch = maxval(locpth) ! elm_patch%subend(iset)
+
+ maxpxl = 0
+ src_pth = -1
+
+ DO ipatch = spatch, epatch
+
+ pthtype = patchtypes(landpatch%settyp(ipatch))
+ numpxl = landpatch%ipxend(ipatch) - landpatch%ipxstt(ipatch) + 1
+
+ IF (numpxl>maxpxl .and. pthtype==0) THEN
+ maxpxl = numpxl
+ src_pth = ipatch
+ ENDIF
+ ENDDO
+
+ ! a new 2m WMO patch
+ IF (src_pth /= -1) THEN
+ wmo_source (iset) = src_pth
+ numwmo = numwmo + 1
+ landelm%settyp(iset) = 1
+ ELSE
+ wmo_source (iset) = -1
+ ENDIF
+
+ ENDDO
+
+ ! allocate new temporal patches memory
+ IF (numpatch > 0) THEN
+ ! a numpatch with WMO patch number
+ numpatch_ = numpatch + numwmo
+
+ allocate (eindex_ (numpatch_ ))
+ allocate (ipxstt_ (numpatch_ ))
+ allocate (ipxend_ (numpatch_ ))
+ allocate (settyp_ (numpatch_ ))
+ allocate (ielm_ (numpatch_ ))
+
+ ENDIF
+
+ numwmo = 0
+
+ ! set for new 2 m WMO patch
+ DO iset = 1, numset
+ numpth = count(landpatch%eindex==landelm%eindex(iset))
+
+ IF (allocated(locpth)) deallocate(locpth)
+ allocate(locpth(numpth))
+
+ locpth = pack([(ipth, ipth=1, numpatch)], &
+ landpatch%eindex==landelm%eindex(iset))
+
+ spatch = minval(locpth) ! elm_patch%substt(iset)
+ epatch = maxval(locpth) ! elm_patch%subend(iset)
+
+ DO ipatch = spatch, epatch
+ jpatch = jpatch + 1
+ eindex_(jpatch) = landpatch%eindex(ipatch)
+ settyp_(jpatch) = landpatch%settyp(ipatch)
+ ipxstt_(jpatch) = landpatch%ipxstt(ipatch)
+ ipxend_(jpatch) = landpatch%ipxend(ipatch)
+ ielm_ (jpatch) = landpatch%ielm (ipatch)
+ ENDDO
+
+ IF (wmo_source(iset) > 0) THEN
+ jpatch = jpatch + 1
+ eindex_(jpatch) = landpatch%eindex(epatch)
+ settyp_(jpatch) = landpatch%settyp(wmo_source(iset))
+ ipxstt_(jpatch) = -1
+ ipxend_(jpatch) = -1
+ ielm_ (jpatch) = landpatch%ielm (epatch)
+
+ ! update the newly 2m WMO source/patch index
+ wmo_patch (iset) = jpatch
+ wmo_source(iset) = wmo_source(iset) + numwmo
+ numwmo = numwmo + 1
+ ENDIF
+ ENDDO
+
+ ! 2m WMO patch number check
+ IF (jpatch .ne. numpatch_) THEN
+ write(*,'(A)') 'Count land 2 m WMO patches error! See MOD_Land2mWMO.F90.'
+ ENDIF
+
+ ! set the new patch number
+ numpatch = numpatch_
+
+ ! allocate and save the new patches info
+ IF (numpatch > 0) THEN
+ ! update landpath with new patch number
+ IF (allocated (landpatch%eindex)) deallocate (landpatch%eindex)
+ IF (allocated (landpatch%ipxstt)) deallocate (landpatch%ipxstt)
+ IF (allocated (landpatch%ipxend)) deallocate (landpatch%ipxend)
+ IF (allocated (landpatch%settyp)) deallocate (landpatch%settyp)
+ IF (allocated (landpatch%ielm )) deallocate (landpatch%ielm )
+
+ allocate (landpatch%eindex (numpatch))
+ allocate (landpatch%ipxstt (numpatch))
+ allocate (landpatch%ipxend (numpatch))
+ allocate (landpatch%settyp (numpatch))
+ allocate (landpatch%ielm (numpatch))
+
+ ! update all information of landpatch
+ landpatch%eindex = eindex_(1:numpatch)
+ landpatch%ipxstt = ipxstt_(1:numpatch)
+ landpatch%ipxend = ipxend_(1:numpatch)
+ landpatch%settyp = settyp_(1:numpatch)
+ landpatch%ielm = ielm_ (1:numpatch)
+
+ ENDIF
+ ENDIF
+
+ landpatch%nset = numpatch
+
+ CALL landpatch%set_vecgs
+
+ IF (allocated (eindex_ )) deallocate (eindex_ )
+ IF (allocated (settyp_ )) deallocate (settyp_ )
+ IF (allocated (ipxstt_ )) deallocate (ipxstt_ )
+ IF (allocated (ipxend_ )) deallocate (ipxend_ )
+ IF (allocated (ielm_ )) deallocate (ielm_ )
+ IF (allocated (locpth )) deallocate (locpth )
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numpatch, npatch_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', npatch_glb, ' patches.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numpatch, ' patches.'
+#endif
+
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+
+ CALL write_patchfrac (DEF_dir_landdata, lc_year)
+
+ END SUBROUTINE land2mwmo_build
+
+ SUBROUTINE land2mwmo_init
+ USE MOD_Mesh
+ IMPLICIT NONE
+
+ allocate (wmo_patch (numelm))
+ allocate (wmo_source (numelm))
+
+ wmo_patch = -1
+ wmo_source = -1
+
+ END SUBROUTINE land2mwmo_init
+
+ SUBROUTINE land2mwmo_final
+ IMPLICIT NONE
+
+ IF (allocated (wmo_patch )) deallocate (wmo_patch )
+ IF (allocated (wmo_source)) deallocate (wmo_source)
+
+ END SUBROUTINE land2mwmo_final
+
+END MODULE MOD_Land2mWMO
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandCrop.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandCrop.F90
new file mode 100644
index 0000000000..85ed62521c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandCrop.F90
@@ -0,0 +1,152 @@
+#include
+
+#ifdef CROP
+MODULE MOD_LandCrop
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Build crop patches.
+!
+! Created by Shupeng Zhang, Sep 2023
+! porting codes from Hua Yuan's OpenMP version to MPI parallel version.
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Grid
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ type(grid_type) :: grid_crop
+ integer, allocatable :: cropclass (:)
+ real(r8), allocatable :: cropfrac (:)
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE landcrop_build (lc_year)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_DataType
+ USE MOD_LandElm
+#ifdef CATCHMENT
+ USE MOD_LandHRU
+#endif
+ USE MOD_LandPatch
+ USE MOD_NetCDFBlock
+ USE MOD_PixelsetShared
+ USE MOD_5x5DataReadin
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year
+
+ ! Local Variables
+ character(len=255) :: cyear, file_patch, dir_5x5, suffix
+ integer :: npatch_glb
+ type(block_data_real8_2d) :: pctcrop_xy
+ type(block_data_real8_3d) :: pctshared_xy
+ type(block_data_real8_3d) :: cropdata
+ integer :: sharedfilter(1), cropfilter(1)
+ integer :: iblkme, ib, jb
+ real(r8), allocatable :: pctshared (:)
+ integer , allocatable :: classshared(:)
+
+ write(cyear,'(i4.4)') lc_year
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making patches (crop shared):'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_active) THEN
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ suffix = 'MOD'//trim(cyear)
+
+ CALL allocate_block_data (grid_patch, pctcrop_xy)
+ CALL read_5x5_data (dir_5x5, suffix, grid_patch, 'PCT_CROP', pctcrop_xy)
+
+ CALL allocate_block_data (grid_patch, pctshared_xy, 2)
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+ pctshared_xy%blk(ib,jb)%val(1,:,:) = 1. - pctcrop_xy%blk(ib,jb)%val/100.
+ pctshared_xy%blk(ib,jb)%val(2,:,:) = pctcrop_xy%blk(ib,jb)%val/100.
+ ENDDO
+ ENDIF
+
+ sharedfilter = (/ 1 /)
+
+ IF (landpatch%has_shared) then
+ CALL pixelsetshared_build (landpatch, grid_patch, pctshared_xy, 2, sharedfilter, &
+ pctshared, classshared, fracin = landpatch%pctshared)
+ ELSE
+ CALL pixelsetshared_build (landpatch, grid_patch, pctshared_xy, 2, sharedfilter, &
+ pctshared, classshared)
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (landpatch%nset > 0) THEN
+ WHERE (classshared == 2) landpatch%settyp = CROPLAND
+ ENDIF
+ ENDIF
+
+ IF (p_is_active) THEN
+ file_patch = trim(DEF_dir_rawdata) // '/global_CFT_surface_data.nc'
+ CALL allocate_block_data (grid_crop, cropdata, N_CFT)
+ CALL ncio_read_block (file_patch, 'PCT_CFT', grid_crop, N_CFT, cropdata)
+ ENDIF
+
+ cropfilter = (/ CROPLAND /)
+
+ CALL pixelsetshared_build (landpatch, grid_crop, cropdata, N_CFT, cropfilter, &
+ cropfrac, cropclass, fracin = pctshared)
+
+ numpatch = landpatch%nset
+
+ landpatch%has_shared = .true.
+ IF (p_is_compute) THEN
+ IF (numpatch > 0) THEN
+ IF (allocated(landpatch%pctshared)) THEN
+ deallocate(landpatch%pctshared)
+ ENDIF
+
+ allocate(landpatch%pctshared(numpatch))
+ landpatch%pctshared = cropfrac
+ ENDIF
+ ENDIF
+
+ IF (allocated(pctshared )) deallocate(pctshared )
+ IF (allocated(classshared)) deallocate(classshared)
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numpatch, npatch_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', npatch_glb, ' patches (with crop).'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numpatch, ' patches.'
+#endif
+
+IF ( .not. DEF_Output_2mWMO ) THEN
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+#ifdef CATCHMENT
+ CALL hru_patch%build (landhru, landpatch, use_frac = .true.)
+#endif
+
+ CALL write_patchfrac (DEF_dir_landdata, lc_year)
+ENDIF
+
+ END SUBROUTINE landcrop_build
+
+END MODULE MOD_LandCrop
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandElm.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandElm.F90
new file mode 100644
index 0000000000..69d75a4878
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandElm.F90
@@ -0,0 +1,84 @@
+#include
+
+MODULE MOD_LandElm
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Build pixelset "landelm".
+!
+! In CoLM, the global/regional area is divided into a hierarchical structure:
+! 1. If GRIDBASED or UNSTRUCTURED is defined, it is
+! ELEMENT >>> PATCH
+! 2. If CATCHMENT is defined, it is
+! ELEMENT >>> HRU >>> PATCH
+! If Plant Function Type classification is used, PATCH is further divided into PFT.
+! If Plant Community classification is used, PATCH is further divided into PC.
+!
+! "landelm" refers to pixelset ELEMENT.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ type(pixelset_type) :: landelm
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE landelm_build
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Mesh
+ IMPLICIT NONE
+
+ ! Local Variables
+ integer :: ielm, nelm_glb
+
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making land elements:'
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (landelm%eindex (numelm))
+ allocate (landelm%ipxstt (numelm))
+ allocate (landelm%ipxend (numelm))
+ allocate (landelm%settyp (numelm))
+ allocate (landelm%ielm (numelm))
+
+ DO ielm = 1, numelm
+ landelm%eindex(ielm) = mesh(ielm)%indx
+ landelm%ipxstt(ielm) = 1
+ landelm%ipxend(ielm) = mesh(ielm)%npxl
+ landelm%settyp(ielm) = 0
+ landelm%ielm (ielm) = ielm
+ ENDDO
+
+ ENDIF
+
+ landelm%nset = numelm
+ CALL landelm%set_vecgs
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numelm, nelm_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', nelm_glb, ' elements.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numelm, ' elements.'
+#endif
+
+ END SUBROUTINE landelm_build
+
+END MODULE MOD_LandElm
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandHRU.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandHRU.F90
new file mode 100644
index 0000000000..7e490ebf47
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandHRU.F90
@@ -0,0 +1,252 @@
+#include
+
+#ifdef CATCHMENT
+
+MODULE MOD_LandHRU
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Build pixelset "landhru".
+!
+! In CoLM, the global/regional area is divided into a hierarchical structure:
+! 1. If GRIDBASED or UNSTRUCTURED is defined, it is
+! ELEMENT >>> PATCH
+! 2. If CATCHMENT is defined, it is
+! ELEMENT >>> HRU >>> PATCH
+! If Plant Function Type classification is used, PATCH is further divided into PFT.
+! If Plant Community classification is used, PATCH is further divided into PC.
+!
+! "landhru" refers to pixelset HRU.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Pixelset
+ USE MOD_Grid
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ integer :: numhru
+ type(grid_type) :: grid_hru
+ type(pixelset_type) :: landhru
+
+ type(subset_type) :: elm_hru
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE landhru_build ()
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_NetcdfSerial
+ USE MOD_Utils
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_LandElm
+ USE MOD_CatchmentDataReadin
+ USE MOD_Namelist
+ USE MOD_AggregationRequestData
+
+ IMPLICIT NONE
+
+ ! Local Variables
+ type (block_data_int32_2d) :: hrudata
+ integer :: iwork, ncat, nhru, ie, typsgn, npxl, ipxl
+ integer*8, allocatable :: catnum(:)
+ integer, allocatable :: numhru_all_g(:), lakeid(:)
+ integer, allocatable :: types(:), order(:), ibuff(:)
+ integer :: nhru_glb
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making land hydro units:'
+ ENDIF
+
+ IF (p_is_root) THEN
+ CALL ncio_read_serial (DEF_CatchmentMesh_data, 'basin_numhru', numhru_all_g)
+ CALL ncio_read_serial (DEF_CatchmentMesh_data, 'lake_id', lakeid)
+ ENDIF
+
+#ifdef USEMPI
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_root) THEN
+ ncat = size(numhru_all_g)
+ ELSE
+ ncat = 0
+ ENDIF
+ CALL mpi_bcast (ncat, 1, MPI_INTEGER, p_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) THEN
+ allocate (numhru_all_g(ncat))
+ allocate (lakeid(ncat))
+ ENDIF
+ CALL mpi_bcast (numhru_all_g, ncat, MPI_INTEGER, p_root, p_comm_glb, p_err)
+ CALL mpi_bcast (lakeid, ncat, MPI_INTEGER, p_root, p_comm_glb, p_err)
+
+ IF (p_is_compute) THEN
+ IF (numelm > 0) THEN
+ allocate (catnum(numelm))
+ allocate (ibuff(numelm))
+ catnum = landelm%eindex
+ numhru = sum(numhru_all_g(catnum))
+ ibuff = lakeid(catnum)
+ deallocate (lakeid)
+ allocate (lakeid(numelm))
+ lakeid = ibuff
+ deallocate (catnum)
+ deallocate (ibuff)
+ ELSE
+ numhru = 0
+ ENDIF
+ ENDIF
+#else
+ IF (p_is_root) THEN
+ DO iwork = 0, p_np_compute-1
+
+ CALL mpi_recv (ncat, 1, MPI_INTEGER, p_address_compute(iwork), mpi_tag_size, &
+ p_comm_glb, p_stat, p_err)
+
+ IF (ncat > 0) THEN
+ allocate (catnum(ncat))
+ allocate (ibuff (ncat))
+
+ CALL mpi_recv (catnum, ncat, MPI_INTEGER8, p_address_compute(iwork), mpi_tag_data, &
+ p_comm_glb, p_stat, p_err)
+
+ nhru = sum(numhru_all_g(catnum))
+ CALL mpi_send (nhru, 1, MPI_INTEGER, &
+ p_address_compute(iwork), mpi_tag_size, p_comm_glb, p_err)
+
+ ibuff = lakeid(catnum)
+ CALL mpi_send (ibuff, ncat, MPI_INTEGER, &
+ p_address_compute(iwork), mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate(catnum)
+ deallocate(ibuff )
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_compute) THEN
+ CALL mpi_send (numelm, 1, MPI_INTEGER, p_address_root, mpi_tag_size, p_comm_glb, p_err)
+ IF (numelm > 0) THEN
+ allocate (lakeid (numelm))
+ CALL mpi_send (landelm%eindex, numelm, MPI_INTEGER8, p_address_root, mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_recv (numhru, 1, MPI_INTEGER, p_address_root, mpi_tag_size, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (lakeid, numelm, MPI_INTEGER, p_address_root, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ELSE
+ numhru = 0
+ ENDIF
+ ENDIF
+#endif
+#else
+ numhru = sum(numhru_all_g)
+#endif
+
+ IF (allocated(numhru_all_g)) deallocate(numhru_all_g)
+
+ IF (p_is_active) CALL allocate_block_data (grid_hru, hrudata)
+ CALL catchment_data_read (DEF_CatchmentMesh_data, 'ihydrounit2d', grid_hru, hrudata)
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+ CALL aggregation_data_daemon (grid_hru, data_i4_2d_in1 = hrudata)
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+
+ IF (numhru > 0) THEN
+ allocate (landhru%eindex (numhru))
+ allocate (landhru%settyp (numhru))
+ allocate (landhru%ipxstt (numhru))
+ allocate (landhru%ipxend (numhru))
+ allocate (landhru%ielm (numhru))
+ ENDIF
+
+ numhru = 0
+
+ DO ie = 1, numelm
+
+ IF (lakeid(ie) > 0) THEN
+ typsgn = -1
+ ELSE
+ typsgn = 1
+ ENDIF
+
+ npxl = mesh(ie)%npxl
+
+ allocate (types (1:npxl))
+
+ CALL aggregation_request_data (landelm, ie, grid_hru, zip = .false., &
+ data_i4_2d_in1 = hrudata, data_i4_2d_out1 = ibuff)
+
+ types = ibuff
+
+ allocate (order (1:npxl))
+ order = (/ (ipxl, ipxl = 1, npxl) /)
+
+ CALL quicksort (npxl, types, order)
+
+ mesh(ie)%ilon(1:npxl) = mesh(ie)%ilon(order)
+ mesh(ie)%ilat(1:npxl) = mesh(ie)%ilat(order)
+
+ DO ipxl = 1, npxl
+ IF (ipxl == 1) THEN
+ numhru = numhru + 1
+ landhru%eindex (numhru) = mesh(ie)%indx
+ landhru%settyp (numhru) = types(ipxl) * typsgn
+ landhru%ipxstt (numhru) = ipxl
+ landhru%ielm (numhru) = ie
+ ELSEIF (types(ipxl) /= types(ipxl-1)) THEN
+ landhru%ipxend(numhru) = ipxl - 1
+
+ numhru = numhru + 1
+ landhru%eindex (numhru) = mesh(ie)%indx
+ landhru%settyp (numhru) = types(ipxl) * typsgn
+ landhru%ipxstt (numhru) = ipxl
+ landhru%ielm (numhru) = ie
+ ENDIF
+ ENDDO
+ landhru%ipxend(numhru) = npxl
+
+ deallocate (ibuff)
+ deallocate (types)
+ deallocate (order)
+
+ ENDDO
+
+#ifdef USEMPI
+ CALL aggregation_compute_done ()
+#endif
+ ENDIF
+
+ landhru%nset = numhru
+ CALL landhru%set_vecgs
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numhru, nhru_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', nhru_glb, ' hydro units.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numhru, ' hydro units.'
+#endif
+
+ IF (allocated(lakeid)) deallocate(lakeid)
+
+ END SUBROUTINE landhru_build
+
+END MODULE MOD_LandHRU
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandPFT.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandPFT.F90
new file mode 100644
index 0000000000..4c8d17e875
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandPFT.F90
@@ -0,0 +1,325 @@
+#include
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+MODULE MOD_LandPFT
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Build pixelset "landpft" (Plant Function Type).
+!
+! In CoLM, the global/regional area is divided into a hierarchical structure:
+! 1. If GRIDBASED or UNSTRUCTURED is defined, it is
+! ELEMENT >>> PATCH
+! 2. If CATCHMENT is defined, it is
+! ELEMENT >>> HRU >>> PATCH
+! If Plant Function Type classification is used, PATCH is further divided into PFT.
+! If Plant Community classification is used, PATCH is further divided into PC.
+!
+! "landpft" refers to pixelset PFT.
+!
+! Created by Shupeng Zhang, May 2023
+! porting codes from Hua Yuan's OpenMP version to MPI parallel version.
+!-----------------------------------------------------------------------
+
+ USE MOD_Namelist
+ USE MOD_Pixelset
+ USE MOD_Const_LC
+ USE MOD_Vars_Global
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ integer :: numpft
+ type(pixelset_type) :: landpft
+
+ integer , allocatable :: pft2patch (:) !patch index of a PFT
+ integer , allocatable :: patch_pft_s (:) !start PFT index of a patch
+ integer , allocatable :: patch_pft_e (:) !end PFT index of a patch
+
+ ! ---- PUBLIC routines ----
+ PUBLIC :: landpft_build
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE landpft_build (lc_year)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Namelist
+ USE MOD_5x5DataReadin
+ USE MOD_LandPatch
+ USE MOD_Land2mWMO
+ USE MOD_AggregationRequestData
+ USE MOD_Const_LC
+#ifdef CROP
+ USE MOD_LandCrop
+#endif
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year
+ ! Local Variables
+ character(len=256) :: dir_5x5, suffix, cyear
+ type (block_data_real8_3d) :: pctpft
+ real(r8), allocatable :: pctpft_patch(:,:), pctpft_one(:,:)
+ real(r8), allocatable :: area_one (:)
+ logical, allocatable :: patchmask (:)
+ integer :: ipatch, ipft, npatch, npft, npft_glb
+ integer :: wmo_src, ipft_grass
+ real(r8) :: sumarea, maxgrass
+
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making land plant function type tiles:'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ landpft%has_shared = .true.
+
+ IF (p_is_active) THEN
+
+ CALL allocate_block_data (grid_patch, pctpft, N_PFT_modis, lb1 = 0)
+ CALL flush_block_data (pctpft, 1.0)
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ ! add parameter input for time year
+ write(cyear,'(i4.4)') lc_year
+ suffix = 'MOD'//trim(cyear)
+ CALL read_5x5_data_pft (dir_5x5, suffix, grid_patch, 'PCT_PFT', pctpft)
+
+#ifdef USEMPI
+ CALL aggregation_data_daemon (grid_patch, data_r8_3d_in1 = pctpft, n1_r8_3d_in1 = N_PFT_modis)
+#endif
+ ENDIF
+
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+ allocate (pctpft_patch (0:N_PFT-1,numpatch))
+ allocate (patchmask (numpatch))
+
+ pctpft_patch(:,:) = 0
+ patchmask (:) = .true.
+ ENDIF
+
+ DO ipatch = 1, numpatch
+
+ IF (ipatch == wmo_patch(landpatch%ielm(ipatch))) THEN
+
+ wmo_src = wmo_source(landpatch%ielm(ipatch))
+ maxgrass = maxval(pctpft_patch(12:14,wmo_src))
+
+ IF (maxgrass > 0) THEN
+ ipft_grass = maxloc(pctpft_patch(12:14,wmo_src), dim=1) + 11
+ pctpft_patch(:,ipatch) = 0
+ pctpft_patch(ipft_grass,ipatch) = 1.
+ ELSE
+ pctpft_patch(0,ipatch) = 1.
+ ENDIF
+
+ CYCLE
+ ENDIF
+#ifndef CROP
+ IF (patchtypes(landpatch%settyp(ipatch)) == 0) THEN
+#else
+ IF (patchtypes(landpatch%settyp(ipatch)) == 0 .and. landpatch%settyp(ipatch)/=CROPLAND) THEN
+#endif
+ CALL aggregation_request_data (landpatch, ipatch, grid_patch, zip = .false., area = area_one, &
+ data_r8_3d_in1 = pctpft, data_r8_3d_out1 = pctpft_one, n1_r8_3d_in1 = N_PFT_modis, lb1_r8_3d_in1 = 0)
+
+ sumarea = sum(area_one * sum(pctpft_one(0:N_PFT-1,:),dim=1))
+
+ ! In case of no PFT data, set patchtype=0 to 100% bare.
+ IF (sumarea <= 0.0) THEN
+ pctpft_patch(0,ipatch) = 1.
+ ELSE
+ DO ipft = 0, N_PFT-1
+ pctpft_patch(ipft,ipatch) = sum(pctpft_one(ipft,:) * area_one) / sumarea
+ ENDDO
+ ENDIF
+
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ CALL aggregation_compute_done ()
+#endif
+
+ IF (numpatch > 0) THEN
+ npatch = count(patchmask)
+ numpft = count(pctpft_patch > 0.)
+#ifdef CROP
+ numpft = numpft + count(landpatch%settyp == CROPLAND)
+#endif
+ IF (npatch > 0) THEN
+ allocate (patch_pft_s (npatch))
+ allocate (patch_pft_e (npatch))
+ ENDIF
+ ELSE
+ numpft = 0
+ ENDIF
+
+ IF (numpft > 0) THEN
+
+ allocate (pft2patch (numpft))
+
+ allocate (landpft%eindex (numpft))
+ allocate (landpft%settyp (numpft))
+ allocate (landpft%ipxstt (numpft))
+ allocate (landpft%ipxend (numpft))
+ allocate (landpft%ielm (numpft))
+
+ allocate (landpft%pctshared (numpft))
+ landpft%pctshared(:) = 1.
+
+ npft = 0
+ npatch = 0
+ DO ipatch = 1, numpatch
+ IF (patchmask(ipatch)) THEN
+ npatch = npatch + 1
+
+#ifndef CROP
+ IF (patchtypes(landpatch%settyp(ipatch)) == 0) THEN
+#else
+ IF (patchtypes(landpatch%settyp(ipatch)) == 0 .and. landpatch%settyp(ipatch)/=CROPLAND) THEN
+#endif
+ patch_pft_s(npatch) = npft + 1
+ patch_pft_e(npatch) = npft + count(pctpft_patch(:,ipatch) > 0)
+
+ DO ipft = 0, N_PFT-1
+ IF (pctpft_patch(ipft,ipatch) > 0) THEN
+ npft = npft + 1
+
+ landpft%ielm (npft) = landpatch%ielm (ipatch)
+ landpft%eindex(npft) = landpatch%eindex(ipatch)
+ landpft%ipxstt(npft) = landpatch%ipxstt(ipatch)
+ landpft%ipxend(npft) = landpatch%ipxend(ipatch)
+ landpft%settyp(npft) = ipft
+
+ landpft%pctshared(npft) = pctpft_patch(ipft,ipatch)
+
+ pft2patch(npft) = npatch
+ ENDIF
+ ENDDO
+#ifdef CROP
+ ELSEIF (landpatch%settyp(ipatch) == CROPLAND) THEN
+ npft = npft + 1
+ patch_pft_s(npatch) = npft
+ patch_pft_e(npatch) = npft
+
+ landpft%ielm (npft) = landpatch%ielm (ipatch)
+ landpft%eindex(npft) = landpatch%eindex(ipatch)
+ landpft%ipxstt(npft) = landpatch%ipxstt(ipatch)
+ landpft%ipxend(npft) = landpatch%ipxend(ipatch)
+ landpft%settyp(npft) = cropclass(ipatch) + N_PFT - 1
+
+ landpft%pctshared(npft) = landpatch%pctshared(ipatch)
+
+ pft2patch(npft) = npatch
+#endif
+ ELSE
+ patch_pft_s(npatch) = -1
+ patch_pft_e(npatch) = -1
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ ENDIF
+
+ CALL landpatch%pset_pack(patchmask, numpatch)
+
+ landpft%nset = numpft
+ CALL landpft%set_vecgs
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numpft, npft_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', npft_glb, ' plant function type tiles.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numpft, ' plant function type tiles.'
+#endif
+
+ IF (allocated(pctpft_patch)) deallocate (pctpft_patch)
+ IF (allocated(pctpft_one )) deallocate (pctpft_one )
+ IF (allocated(area_one )) deallocate (area_one )
+ IF (allocated(patchmask )) deallocate (patchmask )
+
+ END SUBROUTINE landpft_build
+
+ ! ----------------------
+ SUBROUTINE map_patch_to_pft
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ USE MOD_Const_LC
+ IMPLICIT NONE
+
+ integer :: ipatch, ipft
+
+ IF (p_is_compute) THEN
+
+ IF ((numpatch <= 0) .or. (numpft <= 0)) RETURN
+
+ IF (allocated(patch_pft_s)) deallocate(patch_pft_s)
+ IF (allocated(patch_pft_e)) deallocate(patch_pft_e)
+ IF (allocated(pft2patch )) deallocate(pft2patch )
+
+ allocate (patch_pft_s (numpatch))
+ allocate (patch_pft_e (numpatch))
+ allocate (pft2patch (numpft ))
+
+ ipft = 1
+ DO ipatch = 1, numpatch
+#ifndef CROP
+ IF (patchtypes(landpatch%settyp(ipatch)) == 0) THEN
+#else
+ IF (patchtypes(landpatch%settyp(ipatch)) == 0 .and. landpatch%settyp(ipatch)/=CROPLAND) THEN
+#endif
+
+ patch_pft_s(ipatch) = ipft
+
+ DO WHILE (ipft <= numpft)
+ IF ((landpft%eindex(ipft) == landpatch%eindex(ipatch)) &
+ .and. (landpft%ipxstt(ipft) == landpatch%ipxstt(ipatch)) &
+ .and. (landpft%settyp(ipft) < N_PFT)) THEN
+ pft2patch (ipft ) = ipatch
+ patch_pft_e(ipatch) = ipft
+ ipft = ipft + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+#ifdef CROP
+ ELSEIF (landpatch%settyp(ipatch) == CROPLAND) THEN
+ patch_pft_s(ipatch) = ipft
+ patch_pft_e(ipatch) = ipft
+ pft2patch (ipft ) = ipatch
+ ipft = ipft + 1
+#endif
+ ELSE
+ patch_pft_s(ipatch) = -1
+ patch_pft_e(ipatch) = -1
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE map_patch_to_pft
+
+END MODULE MOD_LandPFT
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandPatch.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandPatch.F90
new file mode 100644
index 0000000000..04c76fe18b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandPatch.F90
@@ -0,0 +1,319 @@
+#include
+
+MODULE MOD_LandPatch
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Build pixelset "landpatch".
+!
+! In CoLM, the global/regional area is divided into a hierarchical structure:
+! 1. If GRIDBASED or UNSTRUCTURED is defined, it is
+! ELEMENT >>> PATCH
+! 2. If CATCHMENT is defined, it is
+! ELEMENT >>> HRU >>> PATCH
+! If Plant Function Type classification is used, PATCH is further divided into PFT.
+! If Plant Community classification is used, PATCH is further divided into PC.
+!
+! "landpatch" refers to pixelset PATCH.
+!
+! Created by Shupeng Zhang, May 2023
+! porting codes from Hua Yuan's OpenMP version to MPI parallel version.
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_Vars_Global
+ USE MOD_Const_LC
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ integer :: numpatch
+ type(grid_type) :: grid_patch
+ type(pixelset_type) :: landpatch
+
+ type(subset_type) :: elm_patch
+ type(superset_type) :: patch2elm
+
+#ifdef CATCHMENT
+ type(subset_type) :: hru_patch
+ type(superset_type) :: patch2hru
+#endif
+
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE landpatch_build (lc_year)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ USE MOD_UserDefFun
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_LandElm
+#ifdef CATCHMENT
+ USE MOD_LandHRU
+#endif
+ USE MOD_Namelist
+ USE MOD_NetCDFBlock
+ USE MOD_AggregationRequestData
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year
+ ! Local Variables
+ character(len=256) :: file_patch
+ character(len=255) :: cyear
+ type (block_data_int32_2d) :: patchdata
+ integer :: iloc, npxl, ipxl, numset
+ integer :: ie, iset, ipxstt, ipxend
+ integer, allocatable :: types(:), order(:), ibuff(:)
+ integer*8, allocatable :: eindex_tmp(:)
+ integer, allocatable :: settyp_tmp(:), ipxstt_tmp(:), ipxend_tmp(:), ielm_tmp(:)
+ logical, allocatable :: msk(:)
+ integer :: npatch_glb
+ integer :: dominant_type
+ integer, allocatable :: npxl_types (:)
+
+ write(cyear,'(i4.4)') lc_year
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making land patches:'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_active) THEN
+
+ CALL allocate_block_data (grid_patch, patchdata)
+
+#ifndef LULC_USGS
+ ! add parameter input for time year
+ file_patch = trim(DEF_dir_rawdata)//'landtypes/landtype-igbp-modis-'//trim(cyear)//'.nc'
+#else
+ !TODO: need usgs land cover type data
+ file_patch = trim(DEF_dir_rawdata) //'/landtypes/landtype-usgs-update.nc'
+#endif
+ CALL ncio_read_block (file_patch, 'landtype', grid_patch, patchdata)
+
+#ifdef USEMPI
+ CALL aggregation_data_daemon (grid_patch, data_i4_2d_in1 = patchdata)
+#endif
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+#ifdef CATCHMENT
+ numset = numhru
+#else
+ numset = numelm
+#endif
+
+ IF (numset > 0) THEN
+ allocate (eindex_tmp (numset*N_land_classification))
+ allocate (settyp_tmp (numset*N_land_classification))
+ allocate (ipxstt_tmp (numset*N_land_classification))
+ allocate (ipxend_tmp (numset*N_land_classification))
+ allocate (ielm_tmp (numset*N_land_classification))
+ ENDIF
+
+ numpatch = 0
+
+ DO iset = 1, numset
+#ifdef CATCHMENT
+ ie = landhru%ielm (iset)
+ ipxstt = landhru%ipxstt(iset)
+ ipxend = landhru%ipxend(iset)
+#else
+ ie = landelm%ielm (iset)
+ ipxstt = landelm%ipxstt(iset)
+ ipxend = landelm%ipxend(iset)
+#endif
+
+ npxl = ipxend - ipxstt + 1
+
+ allocate (types (ipxstt:ipxend))
+
+#ifdef CATCHMENT
+ CALL aggregation_request_data (landhru, iset, grid_patch, zip = .false., &
+#else
+ CALL aggregation_request_data (landelm, iset, grid_patch, zip = .false., &
+#endif
+ data_i4_2d_in1 = patchdata, data_i4_2d_out1 = ibuff)
+
+
+ types(:) = ibuff
+ deallocate (ibuff)
+
+#ifdef CATCHMENT
+ IF (landhru%settyp(iset) <= 0) THEN
+ types(ipxstt:ipxend) = WATERBODY
+ ENDIF
+ WHERE (types == 0)
+ ! set land in MERITHydro while ocean in landtype data as water body
+ types = WATERBODY
+ END WHERE
+ WHERE (types == 11)
+ types = 10
+ END WHERE
+#endif
+
+ IF ((DEF_USE_PFT .and. (.not. DEF_SOLO_PFT)) .or. DEF_FAST_PC) THEN
+ ! For classification of plant function types or fast PC,
+ ! merge all land types with soil ground
+ DO ipxl = ipxstt, ipxend
+ IF (types(ipxl) > 0) THEN
+ IF (patchtypes(types(ipxl)) == 0) THEN
+ ! Deal with cropland separately for fast PC
+ IF (DEF_FAST_PC .and. &
+ (types(ipxl)==CROPLAND .or. types(ipxl)==14)) THEN
+ types(ipxl) = CROPLAND
+ ELSE
+ types(ipxl) = 1
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDIF
+
+ allocate (order (ipxstt:ipxend))
+ order = (/ (ipxl, ipxl = ipxstt, ipxend) /)
+
+ CALL quicksort (npxl, types, order)
+
+ mesh(ie)%ilon(ipxstt:ipxend) = mesh(ie)%ilon(order)
+ mesh(ie)%ilat(ipxstt:ipxend) = mesh(ie)%ilat(order)
+
+ IF (DEF_USE_DOMINANT_PATCHTYPE) THEN
+ allocate (npxl_types (0:maxval(types)))
+ npxl_types(:) = 0
+ DO ipxl = ipxstt, ipxend
+ npxl_types(types(ipxl)) = npxl_types(types(ipxl)) + 1
+ ENDDO
+
+ IF (any(types > 0)) THEN
+ iloc = findloc_ud(types > 0) + ipxstt - 1
+ dominant_type = maxloc(npxl_types(1:), dim=1)
+ types(iloc:ipxend) = dominant_type
+ ENDIF
+
+ deallocate(npxl_types)
+ ENDIF
+
+ DO ipxl = ipxstt, ipxend
+ IF (ipxl == ipxstt) THEN
+ numpatch = numpatch + 1
+ eindex_tmp(numpatch) = mesh(ie)%indx
+ settyp_tmp(numpatch) = types(ipxl)
+ ipxstt_tmp(numpatch) = ipxl
+ ielm_tmp (numpatch) = ie
+ ELSEIF (types(ipxl) /= types(ipxl-1)) THEN
+ ipxend_tmp(numpatch) = ipxl - 1
+
+ numpatch = numpatch + 1
+ eindex_tmp(numpatch) = mesh(ie)%indx
+ settyp_tmp(numpatch) = types(ipxl)
+ ipxstt_tmp(numpatch) = ipxl
+ ielm_tmp (numpatch) = ie
+ ENDIF
+ ENDDO
+ ipxend_tmp(numpatch) = ipxend
+
+ deallocate (types)
+ deallocate (order)
+
+ ENDDO
+
+ IF (numpatch > 0) THEN
+ allocate (landpatch%eindex (numpatch))
+ allocate (landpatch%settyp (numpatch))
+ allocate (landpatch%ipxstt (numpatch))
+ allocate (landpatch%ipxend (numpatch))
+ allocate (landpatch%ielm (numpatch))
+
+ landpatch%eindex = eindex_tmp(1:numpatch)
+ landpatch%ipxstt = ipxstt_tmp(1:numpatch)
+ landpatch%ipxend = ipxend_tmp(1:numpatch)
+ landpatch%settyp = settyp_tmp(1:numpatch)
+ landpatch%ielm = ielm_tmp (1:numpatch)
+ ENDIF
+
+ IF (numset > 0) THEN
+ deallocate (eindex_tmp)
+ deallocate (ipxstt_tmp)
+ deallocate (ipxend_tmp)
+ deallocate (settyp_tmp)
+ deallocate (ielm_tmp )
+ ENDIF
+
+#ifdef USEMPI
+ CALL aggregation_compute_done ()
+#endif
+
+ ENDIF
+
+ landpatch%nset = numpatch
+
+ CALL landpatch%set_vecgs
+
+
+#if (!defined(URBAN_MODEL) && !defined(CROP))
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numpatch, npatch_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', npatch_glb, ' patches.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numpatch, ' patches.'
+#endif
+
+IF ( .not. DEF_Output_2mWMO ) THEN
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+#ifdef CATCHMENT
+ CALL hru_patch%build (landhru, landpatch, use_frac = .true.)
+#endif
+
+ CALL write_patchfrac (DEF_dir_landdata, lc_year)
+ENDIF
+#endif
+
+ END SUBROUTINE landpatch_build
+
+ ! -----
+ SUBROUTINE write_patchfrac (dir_landdata, lc_year)
+
+ USE MOD_Namelist
+ USE MOD_NetCDFVector
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year
+ character(len=*), intent(in) :: dir_landdata
+ character(len=256) :: lndname, cyear
+
+ write(cyear,'(i4.4)') lc_year
+ CALL system('mkdir -p ' // trim(dir_landdata) // '/landpatch/' // trim(cyear))
+
+ lndname = trim(dir_landdata)//'/landpatch/'//trim(cyear)//'/patchfrac_elm.nc'
+ CALL ncio_create_file_vector (lndname, landpatch)
+ CALL ncio_define_dimension_vector (lndname, landpatch, 'patch')
+ CALL ncio_write_vector (lndname, 'patchfrac_elm', 'patch', landpatch, elm_patch%subfrc, DEF_Srfdata_CompressLevel)
+
+#ifdef CATCHMENT
+ lndname = trim(dir_landdata)//'/landpatch/'//trim(cyear)//'/patchfrac_hru.nc'
+ CALL ncio_create_file_vector (lndname, landpatch)
+ CALL ncio_define_dimension_vector (lndname, landpatch, 'patch')
+ CALL ncio_write_vector (lndname, 'patchfrac_hru', 'patch', landpatch, hru_patch%subfrc, DEF_Srfdata_CompressLevel)
+#endif
+
+ END SUBROUTINE write_patchfrac
+
+END MODULE MOD_LandPatch
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandUrban.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandUrban.F90
new file mode 100644
index 0000000000..76fd7e77fe
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_LandUrban.F90
@@ -0,0 +1,409 @@
+#include
+
+MODULE MOD_LandUrban
+!-----------------------------------------------------------------------
+!
+! !DESCRIPTION:
+! Build pixelset "landurban".
+!
+! Original authors: Hua Yuan and Wenzong Dong, 2021, OpenMP version.
+!
+!
+! !REVISIONS:
+! 05/2023, Wenzong Dong, Hua Yuan, Shupeng Zhang: porting codes to MPI
+! parallel version.
+!
+!-----------------------------------------------------------------------
+
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_Vars_Global, only: N_URB, URBAN
+
+ IMPLICIT NONE
+
+ ! ---- Instance ----
+ type(grid_type) :: grid_urban
+
+ integer :: numurban
+ type(pixelset_type) :: landurban
+
+ integer , allocatable :: urban_reg (:) !region index of a urban
+ integer , allocatable :: urban2patch (:) !patch index of a urban
+ integer , allocatable :: patch2urban (:) !urban index of a patch
+
+ ! ---- PUBLIC routines ----
+ PUBLIC :: landurban_build
+ PUBLIC :: map_patch_to_urban
+
+CONTAINS
+
+ ! -------------------------------
+ SUBROUTINE landurban_build (lc_year)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFBlock
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Namelist
+ USE MOD_5x5DataReadin
+ USE MOD_Mesh
+ USE MOD_LandPatch
+ USE MOD_LandElm
+#ifdef CATCHMENT
+ USE MOD_LandHRU
+#endif
+ USE MOD_AggregationRequestData
+ USE MOD_Utils
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: lc_year
+ ! Local Variables
+ character(len=256) :: dir_urban
+ type (block_data_int32_2d) :: data_urb_class ! urban type index
+
+ ! local vars
+ integer, allocatable :: ibuff(:), types(:), order(:)
+
+ ! index
+ integer :: ipatch, jpatch, iurban
+ integer :: ie, ipxstt, ipxend, npxl, ipxl
+ integer :: nurb_glb, npatch_glb
+
+ ! local vars for landpath and landurban
+ integer :: numpatch_
+ integer*8, allocatable :: eindex_(:)
+ integer, allocatable :: ipxstt_(:)
+ integer, allocatable :: ipxend_(:)
+ integer, allocatable :: settyp_(:)
+ integer, allocatable :: ielm_ (:)
+
+ integer :: numurban_
+ integer :: iurb, ib, imiss
+ integer :: buff_count(N_URB)
+ real(r8) :: buff_p(N_URB)
+
+ integer , allocatable :: urbclass (:)
+ real(r8), allocatable :: area_one (:)
+
+ character(len=256) :: suffix, cyear
+
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making urban type tiles:'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ ! allocate and read the grided LCZ/NCAR urban type
+ IF (p_is_active) THEN
+
+ dir_urban = trim(DEF_dir_rawdata) // '/urban_type'
+
+ CALL allocate_block_data (grid_urban, data_urb_class)
+ CALL flush_block_data (data_urb_class, 0)
+
+ ! read urban type data
+ suffix = 'URBTYP'
+IF (DEF_URBAN_type_scheme == 1) THEN
+ CALL read_5x5_data (dir_urban, suffix, grid_urban, 'URBAN_DENSITY_CLASS', data_urb_class)
+ELSE IF (DEF_URBAN_type_scheme == 2) THEN
+ CALL read_5x5_data (dir_urban, suffix, grid_urban, 'LCZ_DOM', data_urb_class)
+ENDIF
+
+#ifdef USEMPI
+ CALL aggregation_data_daemon (grid_urban, data_i4_2d_in1 = data_urb_class)
+#endif
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (numpatch > 0) THEN
+ ! a temporary numpatch with max urban patch number
+ numpatch_ = numpatch + count(landpatch%settyp == URBAN) * (N_URB-1)
+
+ allocate (eindex_ (numpatch_ ))
+ allocate (ipxstt_ (numpatch_ ))
+ allocate (ipxend_ (numpatch_ ))
+ allocate (settyp_ (numpatch_ ))
+ allocate (ielm_ (numpatch_ ))
+
+ ! max urban patch number (temporary)
+ numurban_ = count(landpatch%settyp == URBAN) * N_URB
+ IF (numurban_ > 0) THEN
+ allocate (urbclass(numurban_))
+ ENDIF
+ ENDIF
+
+ jpatch = 0
+ iurban = 0
+
+ ! loop for temporary numpatch to filter duplicate urban patch
+ DO ipatch = 1, numpatch
+ IF (landpatch%settyp(ipatch) == URBAN) THEN
+
+ ie = landpatch%ielm (ipatch)
+ ipxstt = landpatch%ipxstt(ipatch)
+ ipxend = landpatch%ipxend(ipatch)
+
+ CALL aggregation_request_data (landpatch, ipatch, grid_urban, zip = .false., area = area_one, &
+ data_i4_2d_in1 = data_urb_class, data_i4_2d_out1 = ibuff)
+
+ ! when there is missing urban types
+ !NOTE@tungwz: need double check below and add appropriate annotations
+ ! check if there is urban pixel without URBAN ID
+ imiss = count(ibuff<1 .or. ibuff>N_URB)
+ IF (imiss > 0) THEN
+ ! Calculate the relative ratio of each urban types by excluding urban pixels without URBAN ID
+ WHERE (ibuff<1 .or. ibuff>N_URB)
+ area_one = 0
+ END WHERE
+
+ buff_p = 0
+ IF (sum(area_one) > 0) THEN
+ DO ib = 1, size(area_one)
+ IF (ibuff(ib)>1 .and. ibuff(ib)N_URB) THEN
+ type_loop: DO iurb = 1, N_URB
+ IF (buff_count(iurb) > 0) THEN
+ ibuff(ib) = iurb
+ buff_count(iurb) = buff_count(iurb) - 1
+ EXIT type_loop
+ ENDIF
+ ENDDO type_loop
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+
+ npxl = ipxend - ipxstt + 1
+
+ allocate (types (ipxstt:ipxend))
+
+ types(:) = ibuff
+
+ deallocate (ibuff)
+
+ allocate (order (ipxstt:ipxend))
+ order = (/ (ipxl, ipxl = ipxstt, ipxend) /)
+
+ ! change order vars, types->regid ? still types below
+ ! add region information, because urban type may be same,
+ ! but from different region in this urban patch
+ ! relative code is changed
+ CALL quicksort (npxl, types, order)
+
+ mesh(ie)%ilon(ipxstt:ipxend) = mesh(ie)%ilon(order)
+ mesh(ie)%ilat(ipxstt:ipxend) = mesh(ie)%ilat(order)
+
+ DO ipxl = ipxstt, ipxend
+ IF (ipxl /= ipxstt) THEN
+ IF (types(ipxl) /= types(ipxl-1)) THEN
+ ipxend_(jpatch) = ipxl - 1
+ ELSE
+ CYCLE
+ ENDIF
+ ENDIF
+
+ jpatch = jpatch + 1
+ eindex_(jpatch) = mesh(ie)%indx
+ settyp_(jpatch) = URBAN
+ ipxstt_(jpatch) = ipxl
+ ielm_ (jpatch) = ie
+
+ iurban = iurban + 1
+ urbclass(iurban) = types(ipxl)
+ ENDDO
+
+ ipxend_(jpatch) = ipxend
+
+ deallocate (types)
+ deallocate (order)
+
+ ELSE
+ jpatch = jpatch + 1
+ eindex_(jpatch) = landpatch%eindex(ipatch)
+ ipxstt_(jpatch) = landpatch%ipxstt(ipatch)
+ ipxend_(jpatch) = landpatch%ipxend(ipatch)
+ settyp_(jpatch) = landpatch%settyp(ipatch)
+ ielm_ (jpatch) = landpatch%ielm (ipatch)
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ CALL aggregation_compute_done ()
+#endif
+
+ numpatch = jpatch
+
+ IF (numpatch > 0) THEN
+ ! update landpath with new patch number
+ ! all urban type patch are included
+ IF (allocated (landpatch%eindex)) deallocate (landpatch%eindex)
+ IF (allocated (landpatch%ipxstt)) deallocate (landpatch%ipxstt)
+ IF (allocated (landpatch%ipxend)) deallocate (landpatch%ipxend)
+ IF (allocated (landpatch%settyp)) deallocate (landpatch%settyp)
+ IF (allocated (landpatch%ielm )) deallocate (landpatch%ielm )
+
+ allocate (landpatch%eindex (numpatch))
+ allocate (landpatch%ipxstt (numpatch))
+ allocate (landpatch%ipxend (numpatch))
+ allocate (landpatch%settyp (numpatch))
+ allocate (landpatch%ielm (numpatch))
+
+ ! update all information of landpatch
+ landpatch%eindex = eindex_(1:jpatch)
+ landpatch%ipxstt = ipxstt_(1:jpatch)
+ landpatch%ipxend = ipxend_(1:jpatch)
+ landpatch%settyp = settyp_(1:jpatch)
+ landpatch%ielm = ielm_ (1:jpatch)
+ ENDIF
+
+ ! update urban patch number
+ IF (numpatch > 0) THEN
+ numurban = count(landpatch%settyp == URBAN)
+ ELSE
+ numurban = 0
+ ENDIF
+
+ IF (numurban > 0) THEN
+ allocate (landurban%eindex (numurban))
+ allocate (landurban%settyp (numurban))
+ allocate (landurban%ipxstt (numurban))
+ allocate (landurban%ipxend (numurban))
+ allocate (landurban%ielm (numurban))
+
+ ! copy urban path information from landpatch for landurban
+ landurban%eindex = pack(landpatch%eindex, landpatch%settyp == URBAN)
+ landurban%ipxstt = pack(landpatch%ipxstt, landpatch%settyp == URBAN)
+ landurban%ipxend = pack(landpatch%ipxend, landpatch%settyp == URBAN)
+ landurban%ielm = pack(landpatch%ielm , landpatch%settyp == URBAN)
+
+ ! assign urban region id and type for each urban patch
+ landurban%settyp = urbclass(1:numurban)
+ ENDIF
+
+ ! update land patch with urban type patch
+ ! set numurban
+ landurban%nset = numurban
+ landpatch%nset = numpatch
+ ENDIF
+
+ CALL landpatch%set_vecgs
+ CALL landurban%set_vecgs
+
+ CALL map_patch_to_urban
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numurban, nurb_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', nurb_glb, ' urban tiles.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numurban, ' urban tiles.'
+#endif
+
+#ifndef CROP
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numpatch, npatch_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', npatch_glb, ' patches.'
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numpatch, ' patches.'
+#endif
+
+IF ( .not. DEF_Output_2mWMO ) THEN
+ CALL elm_patch%build (landelm, landpatch, use_frac = .true.)
+#ifdef CATCHMENT
+ CALL hru_patch%build (landhru, landpatch, use_frac = .true.)
+#endif
+ CALL write_patchfrac (DEF_dir_landdata, lc_year)
+ENDIF
+#endif
+
+ IF (allocated (ibuff )) deallocate (ibuff )
+ IF (allocated (types )) deallocate (types )
+ IF (allocated (order )) deallocate (order )
+
+ IF (allocated (eindex_ )) deallocate (eindex_ )
+ IF (allocated (ipxstt_ )) deallocate (ipxstt_ )
+ IF (allocated (ipxend_ )) deallocate (ipxend_ )
+ IF (allocated (settyp_ )) deallocate (settyp_ )
+ IF (allocated (ielm_ )) deallocate (ielm_ )
+
+ IF (allocated (urbclass)) deallocate (urbclass )
+ IF (allocated (area_one)) deallocate (area_one )
+
+ END SUBROUTINE landurban_build
+
+ ! ----------------------
+ SUBROUTINE map_patch_to_urban
+
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ IMPLICIT NONE
+
+ integer :: ipatch, iurban
+
+ IF (p_is_compute) THEN
+
+ IF ((numpatch <= 0) .or. (numurban <= 0)) RETURN
+
+ IF (allocated(patch2urban)) deallocate(patch2urban)
+ IF (allocated(urban2patch)) deallocate(urban2patch)
+ allocate (patch2urban (numpatch))
+ allocate (urban2patch (numurban))
+
+ iurban = 0
+ DO ipatch = 1, numpatch
+ IF (landpatch%settyp(ipatch) == URBAN) THEN
+ iurban = iurban + 1
+ patch2urban(ipatch) = iurban
+ urban2patch(iurban) = ipatch
+ ELSE
+ patch2urban(ipatch) = -1
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE map_patch_to_urban
+
+END MODULE MOD_LandUrban
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Mesh.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Mesh.F90
new file mode 100644
index 0000000000..24bfc019c8
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Mesh.F90
@@ -0,0 +1,1051 @@
+#include
+
+MODULE MOD_Mesh
+
+!------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! MESH refers to the set of largest elements in CoLM.
+!
+! In CoLM, the global/regional area is divided into a hierarchical structure:
+! 1. If GRIDBASED or UNSTRUCTURED is defined, it is
+! ELEMENT >>> PATCH
+! 2. If CATCHMENT is defined, it is
+! ELEMENT >>> HRU >>> PATCH
+! If Plant Function Type classification is used, PATCH is further divided into PFT.
+! If Plant Community classification is used, PATCH is further divided into PC.
+!
+! To represent ELEMENT in CoLM, the land surface is first divided into pixels,
+! which are rasterized points defined by fine-resolution data.
+!
+! ELEMENT in MESH is set of pixels:
+! 1. If GRIDBASED, ELEMENT is set of pixels in a longitude-latitude rectangle.
+! 2. If UNSTRUCTURED, ELEMENT is set of pixels in an irregular area (usually polygon).
+! 3. If CATCHMENT, ELEMENT is set of pixels in a catchment whose area is less than
+! a predefined value.
+!
+! If GRIDBASED is defined, MESH is built by using input files containing mask of
+! land area or by defining the resolution of longitude-latitude grid.
+! If CATCHMENT or UNSTRUCTURED is defined, MESH is built by using input files
+! containing index of elements.
+!
+! Created by Shupeng Zhang, May 2023
+!------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Grid
+ IMPLICIT NONE
+
+ ! ---- data types ----
+ type :: irregular_elm_type
+
+ integer*8 :: indx
+ integer :: xblk, yblk
+
+ integer :: npxl
+ integer, allocatable :: ilon(:)
+ integer, allocatable :: ilat(:)
+
+ END type irregular_elm_type
+
+ ! ---- Instance ----
+ type (grid_type) :: gridmesh
+
+ integer :: numelm
+ type (irregular_elm_type), allocatable :: mesh (:)
+
+ integer, allocatable :: nelm_blk(:,:)
+
+#ifdef GRIDBASED
+ logical :: read_mesh_from_file = .true.
+#endif
+
+CONTAINS
+
+ ! ------
+#ifdef GRIDBASED
+ SUBROUTINE init_gridbased_mesh_grid ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ IF (p_is_root) THEN
+ inquire (file=trim(DEF_file_mesh), exist=read_mesh_from_file)
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_bcast (read_mesh_from_file, 1, MPI_LOGICAL, p_address_root, p_comm_glb, p_err)
+#endif
+ IF (read_mesh_from_file) THEN
+ CALL gridmesh%define_from_file (DEF_file_mesh)
+ ELSE
+ CALL gridmesh%define_by_res (DEF_GRIDBASED_lon_res, DEF_GRIDBASED_lat_res)
+ ENDIF
+
+ END SUBROUTINE init_gridbased_mesh_grid
+#endif
+
+ ! -------
+ SUBROUTINE copy_elm (elm_from, elm_to)
+
+ IMPLICIT NONE
+ type (irregular_elm_type), intent(in) :: elm_from
+ type (irregular_elm_type), intent(out) :: elm_to
+
+ elm_to%indx = elm_from%indx
+ elm_to%npxl = elm_from%npxl
+ elm_to%xblk = elm_from%xblk
+ elm_to%yblk = elm_from%yblk
+
+ IF (allocated(elm_to%ilat)) deallocate(elm_to%ilat)
+ IF (allocated(elm_to%ilon)) deallocate(elm_to%ilon)
+
+ allocate (elm_to%ilat (elm_to%npxl))
+ allocate (elm_to%ilon (elm_to%npxl))
+ elm_to%ilon = elm_from%ilon
+ elm_to%ilat = elm_from%ilat
+
+ END SUBROUTINE copy_elm
+
+ ! --------------------------------
+ SUBROUTINE mesh_build ()
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFBlock
+ USE MOD_Block
+ USE MOD_Pixel
+ USE MOD_Grid
+ USE MOD_Utils
+ USE MOD_DataType
+ USE MOD_CatchmentDataReadin
+
+ IMPLICIT NONE
+
+ ! Local Variables
+ type(block_data_int32_2d) :: datamesh
+
+ integer :: nelm, ie, je, dsp
+ integer :: iblkme, iblk, jblk, xloc, yloc, xg, yg, ixloc, iyloc
+ integer :: xp, yp, xblk, yblk, npxl, ipxl, ix, iy
+ integer :: irank, iproc, idest, isrc, iloc, iloc_max(2)
+ integer :: ylg, yug, ysp, ynp, nyp
+ integer :: xlg, xug, xwp, xep, nxp
+ real(r8) :: dlatp, dlonp
+ logical :: is_new
+ integer :: smesg(6), rmesg(6), blktag, nsend, nrecv, irecv
+ integer :: iblk_p, jblk_p, nelm_max_blk, nelm_glb
+
+ integer, allocatable :: nelm_rank(:)
+ type(pointer_int64_1d), allocatable :: elist_rank(:)
+
+ integer*8 :: elmid
+ integer*8, allocatable :: elist(:), elist2(:,:), sbuf64(:), elist_recv(:)
+
+ integer, allocatable :: iaddr(:), elmindx (:), order(:)
+ integer, allocatable :: xlist(:), ylist (:), npxl_(:), xlist_recv(:), ylist_recv(:), sbuf(:)
+ logical, allocatable :: msk (:), work_done(:)
+
+ integer, allocatable :: xlist2(:,:), ylist2(:,:), ipt2(:,:), npxl_blk(:,:), blkdsp(:,:), blkcnt(:,:)
+ logical, allocatable :: msk2 (:,:)
+
+ type(irregular_elm_type), allocatable :: meshtmp (:)
+
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (gridmesh, datamesh)
+ ENDIF
+
+#ifdef GRIDBASED
+ IF (read_mesh_from_file) THEN
+ CALL ncio_read_block (DEF_file_mesh, 'landmask', gridmesh, datamesh)
+ ELSE
+ CALL flush_block_data (datamesh, 1)
+ ENDIF
+#endif
+
+#ifdef CATCHMENT
+ CALL catchment_data_read (DEF_CatchmentMesh_data, 'icatchment2d', gridmesh, datamesh, spv = -1)
+#endif
+
+#ifdef UNSTRUCTURED
+ CALL ncio_read_block (DEF_file_mesh, 'elmindex', gridmesh, datamesh)
+#endif
+
+ ! Step 1: How many elms in each block?
+ IF (p_is_active) THEN
+
+ nelm = 0
+
+ allocate (nelm_rank (0:p_np_compute-1))
+ nelm_rank(:) = 0
+
+ allocate (elist_rank (0:p_np_compute-1))
+ DO irank = 0, p_np_compute-1
+ allocate (elist_rank(irank)%val (1000))
+ ENDDO
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ DO yloc = 1, gridmesh%ycnt(jblk)
+ DO xloc = 1, gridmesh%xcnt(iblk)
+
+#ifdef GRIDBASED
+ IF (datamesh%blk(iblk,jblk)%val(xloc,yloc) > 0) THEN
+ xg = gridmesh%xdsp(iblk) + xloc
+ IF (xg > gridmesh%nlon) xg = xg - gridmesh%nlon
+
+ yg = gridmesh%ydsp(jblk) + yloc
+
+ elmid = int(gridmesh%nlon,8) * (yg-1) + xg
+ ELSE
+ elmid = 0
+ ENDIF
+#endif
+#ifdef CATCHMENT
+ elmid = datamesh%blk(iblk,jblk)%val(xloc,yloc)
+#endif
+#ifdef UNSTRUCTURED
+ elmid = datamesh%blk(iblk,jblk)%val(xloc,yloc)
+#endif
+
+ IF (elmid > 0) THEN
+
+ irank = mod(elmid, p_np_compute)
+ CALL insert_into_sorted_list1 ( &
+ elmid, nelm_rank(irank), elist_rank(irank)%val, iloc)
+
+ IF (nelm_rank(irank) == size(elist_rank(irank)%val)) THEN
+ CALL expand_list (elist_rank(irank)%val, 0.2_r8)
+ ENDIF
+
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO irank = 0, p_np_compute-1
+ IF (nelm_rank(irank) > 0) THEN
+ idest = p_address_compute(irank)
+ smesg(1:2) = (/p_iam_glb, nelm_rank(irank)/)
+ ! send(01)
+ CALL mpi_send (smesg(1:2), 2, MPI_INTEGER, &
+ idest, mpi_tag_size, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ nelm = nelm + sum(nelm_rank)
+ nelm_rank(:) = 0
+ ENDDO
+
+#ifdef USEMPI
+ DO irank = 0, p_np_compute-1
+ idest = p_address_compute(irank)
+ ! send(02)
+ smesg(1:2) = (/p_iam_glb, 0/)
+ CALL mpi_send (smesg(1:2), 2, MPI_INTEGER, &
+ idest, mpi_tag_size, p_comm_glb, p_err)
+ ENDDO
+#endif
+
+ deallocate (nelm_rank)
+ DO irank = 0, p_np_compute-1
+ deallocate (elist_rank(irank)%val)
+ ENDDO
+ deallocate (elist_rank)
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ nelm = 0
+ allocate(work_done(0:p_np_active-1))
+ work_done(:) = .false.
+ DO WHILE (.not. all(work_done))
+ ! recv(01,02)
+ CALL mpi_recv (rmesg(1:2), 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_size, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ nrecv = rmesg(2)
+
+ IF (nrecv > 0) THEN
+ nelm = nelm + nrecv
+ ELSE
+ work_done(p_itis_active(isrc)) = .true.
+ ENDIF
+ ENDDO
+
+ deallocate(work_done)
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ ! Step 2: Build pixel list for each elm.
+ IF (p_is_compute) THEN
+ IF (nelm > 0) THEN
+ allocate (meshtmp (nelm))
+ allocate (elist (nelm))
+ allocate (iaddr (nelm))
+ ENDIF
+ nelm = 0
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+ IF (gridmesh%xcnt(iblk) <= 0) CYCLE
+ IF (gridmesh%ycnt(jblk) <= 0) CYCLE
+
+ ylg = gridmesh%ydsp(jblk) + 1
+ yug = gridmesh%ydsp(jblk) + gridmesh%ycnt(jblk)
+ IF (gridmesh%yinc == 1) THEN
+ ysp = find_nearest_south (gridmesh%lat_s(ylg), pixel%nlat, pixel%lat_s)
+ ynp = find_nearest_north (gridmesh%lat_n(yug), pixel%nlat, pixel%lat_n)
+ ELSE
+ ysp = find_nearest_south (gridmesh%lat_s(yug), pixel%nlat, pixel%lat_s)
+ ynp = find_nearest_north (gridmesh%lat_n(ylg), pixel%nlat, pixel%lat_n)
+ ENDIF
+
+ nyp = ynp - ysp + 1
+
+ xlg = gridmesh%xdsp(iblk) + 1
+ xug = gridmesh%xdsp(iblk) + gridmesh%xcnt(iblk)
+ IF (xug > gridmesh%nlon) xug = xug - gridmesh%nlon
+
+ xwp = find_nearest_west (gridmesh%lon_w(xlg), pixel%nlon, pixel%lon_w)
+ IF (.not. lon_between_floor(pixel%lon_w(xwp), gridmesh%lon_w(xlg), gridmesh%lon_e(xlg))) THEN
+ xwp = mod(xwp,pixel%nlon) + 1
+ ENDIF
+
+ xep = find_nearest_east (gridmesh%lon_e(xug), pixel%nlon, pixel%lon_e)
+ IF (.not. lon_between_ceil(pixel%lon_e(xep), gridmesh%lon_w(xug), gridmesh%lon_e(xug))) THEN
+ xep = xep - 1
+ IF (xep == 0) xep = pixel%nlon
+ ENDIF
+
+ nxp = xep - xwp + 1
+ IF (nxp <= 0) nxp = nxp + pixel%nlon
+
+ allocate (elist2 (nxp,nyp))
+ allocate (xlist2 (nxp,nyp))
+ allocate (ylist2 (nxp,nyp))
+ allocate (msk2 (nxp,nyp))
+
+ DO iy = ysp, ynp
+ yg = gridmesh%ygrd(iy)
+ yloc = gridmesh%yloc(yg)
+
+ iyloc = iy - ysp + 1
+ dlatp = pixel%lat_n(iy) - pixel%lat_s(iy)
+ IF (dlatp < 1.0e-6_r8) THEN
+ elist2(:,iyloc) = 0
+ CYCLE
+ ENDIF
+
+ ix = xwp
+ ixloc = 0
+ DO WHILE (.true.)
+ ixloc = ixloc + 1
+ dlonp = pixel%lon_e(ix) - pixel%lon_w(ix)
+ IF (dlonp < 0) dlonp = dlonp + 360.0_r8
+
+ xg = gridmesh%xgrd(ix)
+ xloc = gridmesh%xloc(xg)
+
+#ifdef GRIDBASED
+ IF (datamesh%blk(iblk,jblk)%val(xloc,yloc) > 0) THEN
+ elmid = int(gridmesh%nlon,8) * (yg-1) + xg
+ ELSE
+ elmid = 0
+ ENDIF
+#endif
+#ifdef CATCHMENT
+ elmid = datamesh%blk(iblk,jblk)%val(xloc,yloc)
+#endif
+#ifdef UNSTRUCTURED
+ elmid = datamesh%blk(iblk,jblk)%val(xloc,yloc)
+#endif
+
+ xlist2(ixloc,iyloc) = ix
+ ylist2(ixloc,iyloc) = iy
+ elist2(ixloc,iyloc) = elmid
+
+ IF (dlonp < 1.0e-6_r8) THEN
+ elist2(ixloc,iyloc) = 0
+ ENDIF
+
+ IF (ix == xep) EXIT
+ ix = mod(ix,pixel%nlon) + 1
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ allocate (sbuf (nxp*nyp))
+ allocate (ipt2 (nxp,nyp))
+
+ allocate (sbuf64 (nxp*nyp))
+
+ blktag = iblkme
+ ipt2 = mod(elist2, p_np_compute)
+ DO iproc = 0, p_np_compute-1
+ msk2 = (ipt2 == iproc) .and. (elist2 > 0)
+ nsend = count(msk2)
+ IF (nsend > 0) THEN
+
+ idest = p_address_compute(iproc)
+
+ smesg(1:3) = (/p_iam_glb, nsend, blktag/)
+ ! send(03)
+ CALL mpi_send (smesg(1:3), 3, MPI_INTEGER, &
+ idest, mpi_tag_mesg, p_comm_glb, p_err)
+
+ sbuf64(1:nsend) = pack(elist2, msk2)
+ ! send(04)
+ CALL mpi_send (sbuf64(1:nsend), nsend, MPI_INTEGER8, &
+ idest, blktag, p_comm_glb, p_err)
+
+ sbuf(1:nsend) = pack(xlist2, msk2)
+ ! send(05)
+ CALL mpi_send (sbuf(1:nsend), nsend, MPI_INTEGER, &
+ idest, blktag, p_comm_glb, p_err)
+
+ sbuf(1:nsend) = pack(ylist2, msk2)
+ ! send(06)
+ CALL mpi_send (sbuf(1:nsend), nsend, MPI_INTEGER, &
+ idest, blktag, p_comm_glb, p_err)
+
+ ENDIF
+ ENDDO
+
+ deallocate (sbuf )
+ deallocate (ipt2 )
+ deallocate (sbuf64)
+#else
+
+ DO iy = 1, nyp
+ DO ix = 1, nxp
+
+ elmid = elist2(ix,iy)
+ IF (elmid > 0) THEN
+
+ CALL insert_into_sorted_list1 (elmid, nelm, elist, iloc, is_new)
+
+ msk2 = (elist2 == elmid)
+ npxl = count(msk2)
+
+ IF (is_new) THEN
+ IF (iloc < nelm) THEN
+ iaddr(iloc+1:nelm) = iaddr(iloc:nelm-1)
+ ENDIF
+ iaddr(iloc) = nelm
+
+ meshtmp(iaddr(iloc))%indx = elmid
+ meshtmp(iaddr(iloc))%npxl = npxl
+ ELSE
+ meshtmp(iaddr(iloc))%npxl = meshtmp(iaddr(iloc))%npxl + npxl
+ ENDIF
+
+ allocate (xlist(npxl))
+ allocate (ylist(npxl))
+ xlist = pack(xlist2, msk2)
+ ylist = pack(ylist2, msk2)
+
+ CALL append_to_list (meshtmp(iaddr(iloc))%ilon, xlist)
+ CALL append_to_list (meshtmp(iaddr(iloc))%ilat, ylist)
+
+ WHERE(msk2) elist2 = -1
+
+ deallocate (xlist)
+ deallocate (ylist)
+ ENDIF
+
+ ENDDO
+ ENDDO
+#endif
+
+ deallocate (elist2)
+ deallocate (xlist2)
+ deallocate (ylist2)
+ deallocate (msk2 )
+
+ ENDDO
+
+#ifdef USEMPI
+ DO irank = 0, p_np_compute-1
+ idest = p_address_compute(irank)
+ ! send(07)
+ smesg(1:3) = (/p_iam_glb, 0, 0/)
+ CALL mpi_send (smesg(1:3), 3, MPI_INTEGER, &
+ idest, mpi_tag_mesg, p_comm_glb, p_err)
+ ENDDO
+#endif
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+
+ allocate(work_done(0:p_np_active-1))
+ work_done(:) = .false.
+ DO WHILE (.not. all(work_done))
+ ! recv(03,07)
+ CALL mpi_recv (rmesg(1:3), 3, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ nrecv = rmesg(2)
+ blktag = rmesg(3)
+ IF (nrecv > 0) THEN
+
+ allocate (elist_recv (nrecv))
+ ! recv(04)
+ CALL mpi_recv (elist_recv, nrecv, MPI_INTEGER8, &
+ isrc, blktag, p_comm_glb, p_stat, p_err)
+
+ allocate (xlist_recv (nrecv))
+ ! recv(05)
+ CALL mpi_recv (xlist_recv, nrecv, MPI_INTEGER, &
+ isrc, blktag, p_comm_glb, p_stat, p_err)
+
+ allocate (ylist_recv (nrecv))
+ ! recv(06)
+ CALL mpi_recv (ylist_recv, nrecv, MPI_INTEGER, &
+ isrc, blktag, p_comm_glb, p_stat, p_err)
+
+ allocate (msk(nrecv))
+
+ DO irecv = 1, nrecv
+
+ elmid = elist_recv(irecv)
+
+ IF (elmid > 0) THEN
+
+ CALL insert_into_sorted_list1 (elmid, nelm, elist, iloc, is_new)
+
+ msk = (elist_recv == elmid)
+ npxl = count(msk)
+
+ IF (is_new) THEN
+ IF (iloc < nelm) THEN
+ iaddr(iloc+1:nelm) = iaddr(iloc:nelm-1)
+ ENDIF
+ iaddr(iloc) = nelm
+
+ meshtmp(iaddr(iloc))%indx = elmid
+ meshtmp(iaddr(iloc))%npxl = npxl
+ ELSE
+ meshtmp(iaddr(iloc))%npxl = meshtmp(iaddr(iloc))%npxl + npxl
+ ENDIF
+
+ allocate (xlist(npxl))
+ allocate (ylist(npxl))
+ xlist = pack(xlist_recv, msk)
+ ylist = pack(ylist_recv, msk)
+
+ CALL append_to_list (meshtmp(iaddr(iloc))%ilon, xlist)
+ CALL append_to_list (meshtmp(iaddr(iloc))%ilat, ylist)
+
+ WHERE(msk) elist_recv = -1
+ deallocate (xlist)
+ deallocate (ylist)
+ ENDIF
+
+ ENDDO
+
+ deallocate (msk)
+ deallocate (elist_recv)
+ deallocate (xlist_recv)
+ deallocate (ylist_recv)
+ ELSE
+ work_done(p_itis_active(isrc)) = .true.
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (allocated(elist)) deallocate (elist)
+ IF (allocated(iaddr)) deallocate (iaddr)
+
+ ! Step 3: Which block each elm locates at.
+ IF (p_is_compute) THEN
+
+ allocate (npxl_blk (gblock%nxblk,gblock%nyblk))
+ allocate (nelm_blk (gblock%nxblk,gblock%nyblk))
+
+ nelm_blk(:,:) = 0
+
+ DO ie = 1, nelm
+
+ npxl_blk (:,:) = 0
+
+ DO ipxl = 1, meshtmp(ie)%npxl
+ xp = meshtmp(ie)%ilon(ipxl)
+ yp = meshtmp(ie)%ilat(ipxl)
+
+ xg = gridmesh%xgrd(xp)
+ yg = gridmesh%ygrd(yp)
+
+ xblk = gridmesh%xblk(xg)
+ yblk = gridmesh%yblk(yg)
+
+ npxl_blk(xblk,yblk) = npxl_blk(xblk,yblk) + 1
+ ENDDO
+
+ iloc_max = maxloc(npxl_blk)
+ meshtmp(ie)%xblk = iloc_max(1)
+ meshtmp(ie)%yblk = iloc_max(2)
+
+ nelm_blk(iloc_max(1), iloc_max(2)) = &
+ nelm_blk(iloc_max(1), iloc_max(2)) + 1
+
+ ENDDO
+
+ deallocate (npxl_blk)
+ ENDIF
+
+#ifdef USEMPI
+ IF (.not. p_is_compute) THEN
+ allocate (nelm_blk (gblock%nxblk,gblock%nyblk))
+ nelm_blk(:,:) = 0
+ ENDIF
+
+ CALL mpi_allreduce (MPI_IN_PLACE, nelm_blk, gblock%nxblk*gblock%nyblk, &
+ MPI_INTEGER, MPI_SUM, p_comm_glb, p_err)
+#endif
+
+ ! Step 4: IF MPI is used, sending elms from rank to their IO processes.
+
+ IF (p_is_active) THEN
+
+ allocate (blkdsp (gblock%nxblk, gblock%nyblk))
+ blkdsp(1,1) = 0
+ DO iblk = 1, gblock%nxblk
+ DO jblk = 1, gblock%nyblk
+ IF ((iblk /= 1) .or. (jblk /= 1)) THEN
+ IF (jblk == 1) THEN
+ iblk_p = iblk - 1
+ jblk_p = gblock%nyblk
+ ELSE
+ iblk_p = iblk
+ jblk_p = jblk - 1
+ ENDIF
+
+ IF (gblock%pio(iblk_p,jblk_p) == p_iam_glb) THEN
+ blkdsp(iblk,jblk) = blkdsp(iblk_p,jblk_p) + nelm_blk(iblk_p,jblk_p)
+ ELSE
+ blkdsp(iblk,jblk) = blkdsp(iblk_p,jblk_p)
+ ENDIF
+ ENDIF
+ ENDDO
+ ENDDO
+
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ DO iblk = 1, gblock%nxblk
+ DO jblk = 1, gblock%nyblk
+
+ idest = gblock%pio(iblk,jblk)
+
+ nsend = 0
+ npxl = 0
+ DO ie = 1, nelm
+ IF ((meshtmp(ie)%xblk == iblk) .and. (meshtmp(ie)%yblk == jblk)) THEN
+ nsend = nsend + 1
+ npxl = npxl + meshtmp(ie)%npxl
+ ENDIF
+ ENDDO
+
+ IF (nsend > 0) THEN
+
+ allocate (elist (nsend))
+ allocate (npxl_ (nsend))
+ allocate (xlist (npxl ))
+ allocate (ylist (npxl ))
+
+ nsend = 0
+ npxl = 0
+ DO ie = 1, nelm
+ IF ((meshtmp(ie)%xblk == iblk) .and. (meshtmp(ie)%yblk == jblk)) THEN
+
+ nsend = nsend + 1
+
+ elist(nsend) = meshtmp(ie)%indx
+ npxl_(nsend) = meshtmp(ie)%npxl
+
+ xlist(npxl+1:npxl+meshtmp(ie)%npxl) = meshtmp(ie)%ilon
+ ylist(npxl+1:npxl+meshtmp(ie)%npxl) = meshtmp(ie)%ilat
+
+ npxl = npxl + meshtmp(ie)%npxl
+ ENDIF
+ ENDDO
+
+ blktag = p_iam_glb + 1000
+
+ ! send(09)
+ smesg(1:6) = (/p_iam_glb, blktag, iblk, jblk, nsend, npxl/)
+ CALL mpi_send (smesg(1:6), 6, MPI_INTEGER, idest, mpi_tag_mesg, p_comm_glb, p_err)
+
+ ! send(10)
+ CALL mpi_send (elist, nsend, MPI_INTEGER8, idest, blktag, p_comm_glb, p_err)
+ CALL mpi_send (npxl_, nsend, MPI_INTEGER, idest, blktag, p_comm_glb, p_err)
+
+ ! send(11)
+ CALL mpi_send (xlist, npxl, MPI_INTEGER, idest, blktag, p_comm_glb, p_err)
+ CALL mpi_send (ylist, npxl, MPI_INTEGER, idest, blktag, p_comm_glb, p_err)
+
+ deallocate (elist)
+ deallocate (npxl_)
+ deallocate (xlist)
+ deallocate (ylist)
+
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ numelm = sum(nelm_blk, mask = gblock%pio == p_iam_glb)
+
+ IF (numelm > 0) THEN
+
+ allocate (mesh (numelm))
+
+ allocate (blkcnt (gblock%nxblk, gblock%nyblk))
+ blkcnt(:,:) = 0
+
+ DO WHILE (sum(blkcnt) < numelm)
+
+ ! recv(09)
+ CALL mpi_recv (rmesg(1:6), 6, MPI_INTEGER, MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ isrc = rmesg(1)
+ blktag = rmesg(2)
+ xblk = rmesg(3)
+ yblk = rmesg(4)
+ nrecv = rmesg(5)
+ npxl = rmesg(6)
+
+ allocate (elist (nrecv))
+ allocate (npxl_ (nrecv))
+ allocate (xlist (npxl ))
+ allocate (ylist (npxl ))
+
+ ! recv(10)
+ CALL mpi_recv (elist, nrecv, MPI_INTEGER8, isrc, blktag, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (npxl_, nrecv, MPI_INTEGER, isrc, blktag, p_comm_glb, p_stat, p_err)
+
+ ! recv(11)
+ CALL mpi_recv (xlist, npxl, MPI_INTEGER, isrc, blktag, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (ylist, npxl, MPI_INTEGER, isrc, blktag, p_comm_glb, p_stat, p_err)
+
+ dsp = 0
+ DO ie = 1, nrecv
+
+ je = blkdsp(xblk,yblk) + blkcnt(xblk,yblk) + ie
+
+ mesh(je)%indx = elist(ie)
+ mesh(je)%xblk = xblk
+ mesh(je)%yblk = yblk
+ mesh(je)%npxl = npxl_(ie)
+
+ allocate (mesh(je)%ilon (npxl_(ie)))
+ allocate (mesh(je)%ilat (npxl_(ie)))
+
+ mesh(je)%ilon = xlist(dsp+1:dsp+npxl_(ie))
+ mesh(je)%ilat = ylist(dsp+1:dsp+npxl_(ie))
+
+ dsp = dsp + npxl_(ie)
+
+ ENDDO
+
+ blkcnt(xblk,yblk) = blkcnt(xblk,yblk) + nrecv
+
+ deallocate (elist)
+ deallocate (npxl_)
+ deallocate (xlist)
+ deallocate (ylist)
+
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+#else
+ numelm = nelm
+ IF (numelm > 0) THEN
+
+ allocate (mesh (numelm))
+
+ allocate (blkcnt (gblock%nxblk, gblock%nyblk))
+ blkcnt(:,:) = 0
+ DO ie = 1, numelm
+
+ xblk = meshtmp(ie)%xblk
+ yblk = meshtmp(ie)%yblk
+
+ blkcnt(xblk,yblk) = blkcnt(xblk,yblk) + 1
+ je = blkdsp(xblk,yblk) + blkcnt(xblk,yblk)
+
+ CALL copy_elm (meshtmp(ie), mesh(je))
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ ! Step 4-2: sort elms.
+ IF (p_is_active) THEN
+ IF (allocated (meshtmp)) THEN
+ DO ie = 1, size(meshtmp)
+ IF (allocated(meshtmp(ie)%ilon)) deallocate (meshtmp(ie)%ilon)
+ IF (allocated(meshtmp(ie)%ilat)) deallocate (meshtmp(ie)%ilat)
+ ENDDO
+ deallocate (meshtmp)
+ ENDIF
+
+ IF (numelm > 0) THEN
+ allocate (meshtmp (numelm))
+ DO ie = 1, numelm
+ CALL copy_elm(mesh(ie), meshtmp(ie))
+ ENDDO
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ IF (blkcnt(iblk,jblk) > 0) THEN
+ allocate (elmindx (blkcnt(iblk,jblk)))
+ allocate (order (blkcnt(iblk,jblk)))
+
+ DO ie = blkdsp(iblk,jblk)+1, blkdsp(iblk,jblk)+blkcnt(iblk,jblk)
+ elmindx(ie-blkdsp(iblk,jblk)) = mesh(ie)%indx
+ ENDDO
+
+ order = (/ (ie, ie = 1, blkcnt(iblk,jblk)) /)
+ CALL quicksort (blkcnt(iblk,jblk), elmindx, order)
+
+ DO ie = 1, blkcnt(iblk,jblk)
+ CALL copy_elm (meshtmp(blkdsp(iblk,jblk)+order(ie)), &
+ mesh(blkdsp(iblk,jblk)+ie))
+ ENDDO
+
+ deallocate (elmindx)
+ deallocate (order )
+ ENDIF
+
+ ENDDO
+ ENDIF
+ ENDIF
+
+ IF (allocated(blkdsp)) deallocate(blkdsp)
+ IF (allocated(blkcnt)) deallocate(blkcnt)
+
+ IF (allocated (meshtmp)) THEN
+ DO ie = 1, size(meshtmp)
+ IF (allocated(meshtmp(ie)%ilon)) deallocate (meshtmp(ie)%ilon)
+ IF (allocated(meshtmp(ie)%ilat)) deallocate (meshtmp(ie)%ilat)
+ ENDDO
+
+ deallocate (meshtmp )
+ ENDIF
+
+ ! Step 5: IF MPI is used, scatter elms from IO to ranks.
+#ifdef USEMPI
+#ifndef MPAS_EMBEDDED_COLM
+ CALL scatter_mesh_legacy_roles ()
+#endif
+#endif
+
+ IF (p_is_root) THEN
+ write(*,'(A)') 'Making mesh elements:'
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_active) THEN
+
+ CALL mpi_reduce (numelm, nelm_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_active, p_err)
+ IF (p_iam_active == p_root) THEN
+ write(*,'(A,I12,A)') 'Total : ', nelm_glb, ' elements.'
+ ENDIF
+
+ nelm_max_blk = maxval(nelm_blk, mask = gblock%pio == p_iam_glb)
+ CALL mpi_allreduce (MPI_IN_PLACE, nelm_max_blk, 1, MPI_INTEGER, MPI_MAX, p_comm_active, p_err)
+ IF (p_iam_active == p_root) THEN
+ write(*,'(A,I12,A)') 'Maximum : ', nelm_max_blk, &
+ ' elements in one block (More than 3600 is recommended).'
+ write(*,'(/,A)') ' -----------------------------------------------------------------'
+ write(*,'(A)') ' | Examples for setting of blocks and processor groupsize: |'
+ write(*,'(A)') ' | Resolution DEF_nx_blocks DEF_ny_blocks DEF_PIO_groupsize |'
+ write(*,'(A)') ' | 2x2 18 9 15 |'
+ write(*,'(A)') ' | 1x1 18 9 24 |'
+ write(*,'(A)') ' | 0.5x0.5 18 9 36 |'
+ write(*,'(A)') ' | 0.25x0.25 30 15 45 |'
+ write(*,'(A)') ' | 0.1x0.1 72 36 64 |'
+ write(*,'(A,/)') ' -----------------------------------------------------------------'
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#else
+ write(*,'(A,I12,A)') 'Total: ', numelm, ' elements.'
+#endif
+
+ END SUBROUTINE mesh_build
+
+
+#ifdef USEMPI
+#ifndef MPAS_EMBEDDED_COLM
+ ! --------------------------------
+ SUBROUTINE scatter_mesh_legacy_roles
+
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ IMPLICIT NONE
+
+ ! Local variables
+ integer :: iblk, jblk, nave, nres, iproc, ndsp, nsend, idest, ie
+ integer :: smesg(4), rmesg(4)
+ integer, allocatable :: nelm_rank(:)
+ integer :: iblkme
+ character(len=20) :: wfmt
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ IF (p_is_active) THEN
+
+ allocate (nelm_rank (1:p_np_group-1))
+ nelm_rank(:) = 0
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ nave = nelm_blk(iblk,jblk) / (p_np_group-1)
+ nres = mod(nelm_blk(iblk,jblk), p_np_group-1)
+ DO iproc = 1, p_np_group-1
+ nelm_rank(iproc) = nelm_rank(iproc) + nave
+ IF (iproc <= nres) nelm_rank(iproc) = nelm_rank(iproc) + 1
+ ENDDO
+ ENDDO
+
+ IF (any(nelm_rank == 0)) THEN
+ write(*,'(A,/,A)') 'Warning: there are idle ranks, please use less processors ' // &
+ 'OR larger working group ', ' (set by DEF_PIO_groupsize in CoLM namelist).'
+ write(wfmt,'(A,I0,A)') '(A,I6,A,', p_np_group-1, '(X,I0))'
+ write(*,wfmt) 'Numbers of elements by ranks in group ', p_iam_glb, ' are ', nelm_rank
+ ENDIF
+
+ DO iproc = 1, p_np_group-1
+ CALL mpi_send (nelm_rank(iproc), 1, MPI_INTEGER, &
+ iproc, mpi_tag_size, p_comm_group, p_err)
+ ENDDO
+ deallocate (nelm_rank)
+
+ ndsp = 0
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ nave = nelm_blk(iblk,jblk) / (p_np_group-1)
+ nres = mod(nelm_blk(iblk,jblk), p_np_group-1)
+ DO iproc = 1, p_np_group-1
+ nsend = nave
+ IF (iproc <= nres) nsend = nsend + 1
+
+ DO ie = ndsp+1, ndsp+nsend
+ idest = iproc
+ CALL mpi_send (mesh(ie)%indx, 1, MPI_INTEGER8, &
+ idest, mpi_tag_mesg, p_comm_group, p_err)
+ smesg(1:3) = (/mesh(ie)%xblk, mesh(ie)%yblk, mesh(ie)%npxl/)
+ CALL mpi_send (smesg(1:3), 3, MPI_INTEGER, &
+ idest, mpi_tag_mesg, p_comm_group, p_err)
+ CALL mpi_send (mesh(ie)%ilon, mesh(ie)%npxl, &
+ MPI_INTEGER, idest, mpi_tag_data, p_comm_group, p_err)
+ CALL mpi_send (mesh(ie)%ilat, mesh(ie)%npxl, &
+ MPI_INTEGER, idest, mpi_tag_data, p_comm_group, p_err)
+ ENDDO
+ ndsp = ndsp + nsend
+ ENDDO
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ CALL mpi_recv (numelm, 1, MPI_INTEGER, &
+ p_root, mpi_tag_size, p_comm_group, p_stat, p_err)
+
+ IF (numelm > 0) THEN
+ allocate (mesh (numelm))
+
+ DO ie = 1, numelm
+ CALL mpi_recv (mesh(ie)%indx, 1, MPI_INTEGER8, &
+ p_root, mpi_tag_mesg, p_comm_group, p_stat, p_err)
+ CALL mpi_recv (rmesg, 3, MPI_INTEGER, &
+ p_root, mpi_tag_mesg, p_comm_group, p_stat, p_err)
+
+ mesh(ie)%xblk = rmesg(1)
+ mesh(ie)%yblk = rmesg(2)
+ mesh(ie)%npxl = rmesg(3)
+
+ allocate (mesh(ie)%ilon (mesh(ie)%npxl))
+ allocate (mesh(ie)%ilat (mesh(ie)%npxl))
+
+ CALL mpi_recv (mesh(ie)%ilon, mesh(ie)%npxl, MPI_INTEGER, &
+ p_root, mpi_tag_data, p_comm_group, p_stat, p_err)
+ CALL mpi_recv (mesh(ie)%ilat, mesh(ie)%npxl, MPI_INTEGER, &
+ p_root, mpi_tag_data, p_comm_group, p_stat, p_err)
+ ENDDO
+
+ ENDIF
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+
+ END SUBROUTINE scatter_mesh_legacy_roles
+
+#endif
+#endif
+
+ ! --------------------------------
+ SUBROUTINE mesh_free_mem ()
+
+ IMPLICIT NONE
+
+ ! Local variables
+ integer :: ie
+
+ IF (allocated(mesh)) THEN
+ DO ie = 1, size(mesh)
+ IF (allocated(mesh(ie)%ilon)) deallocate (mesh(ie)%ilon)
+ IF (allocated(mesh(ie)%ilat)) deallocate (mesh(ie)%ilat)
+ ENDDO
+
+ deallocate (mesh)
+ ENDIF
+
+ numelm = 0
+
+ END SUBROUTINE mesh_free_mem
+
+END MODULE MOD_Mesh
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_MeshFilter.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_MeshFilter.F90
new file mode 100644
index 0000000000..d4796ff885
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_MeshFilter.F90
@@ -0,0 +1,181 @@
+#include
+
+MODULE MOD_MeshFilter
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Mesh filter.
+! Mesh filter can be used to mask part of region or globe as needed.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Grid
+ IMPLICIT NONE
+
+ logical :: has_mesh_filter
+ type(grid_type) :: grid_filter
+
+CONTAINS
+
+ logical FUNCTION inquire_mesh_filter ()
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ IMPLICIT NONE
+ logical :: fexists
+
+ IF (p_is_root) THEN
+
+ inquire (file=trim(DEF_file_mesh_filter), exist=fexists)
+
+ IF (.not. fexists) THEN
+ write(*,'(/, 2A)') 'Note: Mesh Filter not used: file ', trim(DEF_file_mesh_filter)
+ ELSE
+ write(*,'(/, 2A)') 'Note: Mesh Filter from file ', trim(DEF_file_mesh_filter)
+ ENDIF
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (fexists, 1, MPI_LOGICAL, p_address_root, p_comm_glb, p_err)
+#endif
+
+ inquire_mesh_filter = fexists
+
+ END FUNCTION inquire_mesh_filter
+
+ ! -------------
+ SUBROUTINE mesh_filter (gridf, ffilter, fvname)
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFBlock
+ USE MOD_DataType
+ USE MOD_LandElm
+ USE MOD_Mesh
+ USE MOD_AggregationRequestData
+ USE MOD_Block
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: gridf
+ character(len=*), intent(in) :: ffilter
+ character(len=*), intent(in) :: fvname
+
+ ! local variables:
+ ! ---------------------------------------------------------------
+ type (block_data_int32_2d) :: datafilter
+ integer, allocatable :: ifilter(:), xtemp(:), ytemp(:)
+ logical, allocatable :: filter(:)
+ integer :: ielm, jelm, npxl, nelm_glb
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ IF (p_is_root) THEN
+ write(*,'(/, A)') 'Filtering pixels ...'
+ ENDIF
+
+ IF (p_is_active) THEN
+ CALL allocate_block_data (gridf, datafilter)
+ CALL ncio_read_block (trim(ffilter), trim(fvname), gridf, datafilter)
+
+#ifdef USEMPI
+ CALL aggregation_data_daemon (gridf, data_i4_2d_in1 = datafilter)
+#endif
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ jelm = 0
+ DO ielm = 1, numelm
+ CALL aggregation_request_data (landelm, ielm, gridf, zip = .false., &
+ data_i4_2d_in1 = datafilter, data_i4_2d_out1 = ifilter, &
+ filledvalue_i4 = -1)
+
+ allocate (filter (mesh(ielm)%npxl))
+ filter = ifilter > 0
+
+ IF (any(filter)) THEN
+ jelm = jelm + 1
+ IF (.not. all(filter)) THEN
+
+ npxl = count(filter)
+
+ allocate (xtemp(npxl))
+ allocate (ytemp(npxl))
+ xtemp = pack(mesh(ielm)%ilon, filter)
+ ytemp = pack(mesh(ielm)%ilat, filter)
+
+ deallocate(mesh(ielm)%ilon)
+ deallocate(mesh(ielm)%ilat)
+
+ mesh(ielm)%npxl = npxl
+
+ allocate(mesh(ielm)%ilon(npxl))
+ allocate(mesh(ielm)%ilat(npxl))
+ mesh(ielm)%ilon = xtemp
+ mesh(ielm)%ilat = ytemp
+
+ deallocate (xtemp)
+ deallocate (ytemp)
+ ENDIF
+
+ IF (jelm /= ielm) THEN
+ CALL copy_elm (mesh(ielm), mesh(jelm))
+ ENDIF
+
+ ENDIF
+
+ deallocate (filter)
+ ENDDO
+
+ numelm = jelm
+
+#ifdef USEMPI
+ CALL aggregation_compute_done ()
+#endif
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (allocated(landelm%eindex)) deallocate (landelm%eindex)
+ IF (allocated(landelm%ipxstt)) deallocate (landelm%ipxstt)
+ IF (allocated(landelm%ipxend)) deallocate (landelm%ipxend)
+ IF (allocated(landelm%settyp)) deallocate (landelm%settyp)
+ IF (allocated(landelm%ielm )) deallocate (landelm%ielm )
+ ENDIF
+
+ CALL landelm_build ()
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ CALL mpi_reduce (numelm, nelm_glb, 1, MPI_INTEGER, MPI_SUM, p_root, p_comm_compute, p_err)
+ IF (p_iam_compute == 0) THEN
+ write(*,'(A,I12,A)') 'Total: ', nelm_glb, ' elements after mesh filtering.'
+ ENDIF
+ ENDIF
+#else
+ write(*,'(A,I12,A)') 'Total: ', numelm, ' elements after mesh filtering.'
+#endif
+
+ ! Update nelm_blk
+ nelm_blk(:,:) = 0
+ IF (p_is_compute) THEN
+ DO ielm = 1, numelm
+ nelm_blk(mesh(ielm)%xblk,mesh(ielm)%yblk) = &
+ nelm_blk(mesh(ielm)%xblk,mesh(ielm)%yblk) + 1
+ ENDDO
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, nelm_blk, gblock%nxblk*gblock%nyblk, &
+ MPI_INTEGER, MPI_SUM, p_comm_glb, p_err)
+#endif
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE mesh_filter
+
+END MODULE MOD_MeshFilter
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Namelist.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Namelist.F90
new file mode 100644
index 0000000000..d22cdf17ed
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Namelist.F90
@@ -0,0 +1,2508 @@
+#include
+
+MODULE MOD_Namelist
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Variables in namelist files and subroutines to read namelist files.
+!
+! Initial Authors: Shupeng Zhang, Zhongwang Wei, Xingjie Lu, Nan Wei,
+! Hua Yuan, Wenzong Dong et al., May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision, only: r8
+ IMPLICIT NONE
+ SAVE
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 0: CASE name -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ character(len=256) :: DEF_CASE_NAME = 'CASENAME'
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 1: domain -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ type nl_domain_type
+ real(r8) :: edges = -90.0
+ real(r8) :: edgen = 90.0
+ real(r8) :: edgew = -180.0
+ real(r8) :: edgee = 180.0
+ END type nl_domain_type
+
+ type (nl_domain_type) :: DEF_domain
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 2: blocks and MPI -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ ! "blocks" is used to deal with high resolution data.
+ ! It is defined by one of the following (in order of priority):
+ ! 1) "DEF_BlockInfoFile" : "lat_s","lat_n","lon_w","lon_e" in file ;
+ ! 2) "DEF_AverageElementSize" : diameter of element (in kilometer);
+ ! 3) "DEF_nx_blocks" and "DEF_ny_blocks" : number of blocks;
+ character(len=256) :: DEF_BlockInfoFile = 'null'
+ real(r8) :: DEF_AverageElementSize = -1.
+ integer :: DEF_nx_blocks = 72
+ integer :: DEF_ny_blocks = 36
+
+ ! Standalone CoLM used this to size its role-split groups.
+ ! MPAS-embedded CoLM maps all active ranks to MPAS compute ranks.
+ integer :: DEF_PIO_groupsize = 12
+ logical :: DEF_nIO_eq_nBlock = .false.
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 3: For Single Point -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ character(len=256) :: SITE_fsitedata = 'null'
+
+ real(r8) :: SITE_lon_location = -1.e36_r8
+ real(r8) :: SITE_lat_location = -1.e36_r8
+
+ integer :: SITE_landtype = -1
+
+ logical :: USE_SITE_landtype = .false.
+ logical :: USE_SITE_pctpfts = .true.
+ logical :: USE_SITE_pctcrop = .true.
+ logical :: USE_SITE_htop = .true.
+ logical :: USE_SITE_LAI = .true.
+ logical :: USE_SITE_lakedepth = .true.
+ logical :: USE_SITE_soilreflectance = .true.
+ logical :: USE_SITE_soilparameters = .true.
+ logical :: USE_SITE_dbedrock = .true.
+ logical :: USE_SITE_topography = .true.
+ logical :: USE_SITE_urban_geometry = .true.
+ logical :: USE_SITE_urban_ecology = .true.
+ logical :: USE_SITE_urban_radiation = .true.
+ logical :: USE_SITE_urban_thermal = .false.
+ logical :: USE_SITE_urban_human = .true.
+ logical :: USE_SITE_HistWriteBack = .true.
+ logical :: USE_SITE_ForcingReadAhead = .true.
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 4: simulation time type -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ type nl_simulation_time_type
+ logical :: greenwich = .TRUE.
+ integer :: start_year = 2000
+ integer :: start_month = 1
+ integer :: start_day = 1
+ integer :: start_sec = 0
+ integer :: end_year = 2003
+ integer :: end_month = 1
+ integer :: end_day = 1
+ integer :: end_sec = 0
+ integer :: spinup_year = 0
+ integer :: spinup_month = 1
+ integer :: spinup_day = 1
+ integer :: spinup_sec = 0
+ integer :: spinup_repeat = 1
+ real(r8) :: timestep = 1800.
+ END type nl_simulation_time_type
+
+ type (nl_simulation_time_type) :: DEF_simulation_time
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 5: directories and files -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ character(len=256) :: DEF_dir_rawdata = 'path/to/rawdata/'
+ character(len=256) :: DEF_dir_runtime = 'path/to/runtime/'
+ character(len=256) :: DEF_dir_output = 'path/to/output/data'
+
+ character(len=256) :: DEF_dir_landdata = 'path/to/landdata'
+ character(len=256) :: DEF_dir_restart = 'path/to/restart'
+ character(len=256) :: DEF_dir_history = 'path/to/history'
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 6: landdata and surface inputs -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ character(len=256) :: DEF_file_mesh = 'path/to/mesh/file'
+ real(r8) :: DEF_GRIDBASED_lon_res = 0.5
+ real(r8) :: DEF_GRIDBASED_lat_res = 0.5
+
+ character(len=256) :: DEF_CatchmentMesh_data = 'path/to/catchment/data'
+
+ character(len=256) :: DEF_file_mesh_filter = 'path/to/mesh/filter'
+
+ ! ----- Use surface data from existing dataset -----
+ ! case 1: from a larger region
+ logical :: USE_srfdata_from_larger_region = .false.
+ character(len=256) :: DEF_dir_existing_srfdata = 'path/to/landdata'
+ ! case 2: from gridded data with dimensions [patch,lon,lat] or [pft,lon,lat]
+ ! only available for USGS/IGBP/PFT CLASSIFICATION
+ logical :: USE_srfdata_from_3D_gridded_data = .false.
+
+ ! ----- land cover data year (for static land cover, i.e. non-LULCC) -----
+ ! NOTE: Please check the LC data year range available
+ integer :: DEF_LC_YEAR = 2005
+
+ ! ----- Subgrid scheme -----
+ logical :: DEF_USE_USGS = .false.
+ logical :: DEF_USE_IGBP = .false.
+ logical :: DEF_USE_LCT = .false.
+ logical :: DEF_USE_PFT = .false.
+ logical :: DEF_USE_PC = .false.
+ logical :: DEF_SOLO_PFT = .false.
+ logical :: DEF_FAST_PC = .true.
+ logical :: DEF_PC_CROP_SPLIT = .true.
+ character(len=256) :: DEF_SUBGRID_SCHEME = 'LCT'
+
+ logical :: DEF_LANDONLY = .true.
+ logical :: DEF_USE_DOMINANT_PATCHTYPE = .false.
+
+ ! soil hydraulic parameters are upscaled from rawdata (1km resolution)
+ ! to model patches through FIT algorithm (Montzka et al., 2017).
+ logical :: DEF_USE_SOILPAR_UPS_FIT = .true.
+
+ ! Options for soil reflectance setting schemes
+ ! 1: Guessed soil color type according to land cover classes
+ ! 2: Read a global soil color map from CLM
+ integer :: DEF_SOIL_REFL_SCHEME = 2
+
+ ! ----- merge data in aggregation when send data from IO to compute rank -----
+ logical :: USE_zip_for_aggregation = .true.
+
+ ! ----- compress level in writing aggregated surface data -----
+ integer :: DEF_Srfdata_CompressLevel = 1
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 7: Leaf Area Index -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ ! NOTE: Please check the LAI data year range available
+ integer :: DEF_LAI_START_YEAR = 2000
+ integer :: DEF_LAI_END_YEAR = 2020
+
+ ! add by zhongwang wei @ sysu 2021/12/23
+ ! To allow read satellite observed LAI
+ ! 06/2023, note by hua yuan: change DEF_LAI_CLIM to DEF_LAI_MONTHLY
+ logical :: DEF_LAI_MONTHLY = .true.
+
+ ! ------LAI change and Land cover year setting ----------
+ ! 06/2023, add by wenzong dong and hua yuan: use for updating LAI with simulation year
+ logical :: DEF_LAI_CHANGE_YEARLY = .true.
+
+ ! 05/2023, add by Xingjie Lu: use for updating LAI with leaf carbon
+ logical :: DEF_USE_LAIFEEDBACK = .false.
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 8: Initialization -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ logical :: DEF_USE_SoilInit = .false.
+ character(len=256) :: DEF_file_SoilInit = 'null'
+
+ logical :: DEF_USE_SnowInit = .false.
+ character(len=256) :: DEF_file_SnowInit = 'null'
+
+ logical :: DEF_USE_CN_INIT = .false.
+ character(len=256) :: DEF_file_cn_init = 'null'
+
+ logical :: DEF_USE_WaterTableInit = .false.
+ character(len=256) :: DEF_file_WaterTable = 'null'
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 9: LULCC related ------
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ ! Options for LULCC year-to-year transfer schemes
+ ! 1: Same Type Assignment scheme (STA), state variables assignment for the same type (LC, PFT or PC)
+ ! 2: Mass and Energy Conservation scheme (MEC), DO mass and energy conservation calculation
+ integer :: DEF_LULCC_SCHEME = 1
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 10: Urban model related ------
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ ! Options for urban type scheme
+ ! 1: NCAR Urban Classification, 3 urban type with Tall Building, High Density and Medium Density
+ ! 2: LCZ Classification, 10 urban type with LCZ 1-10
+ integer :: DEF_URBAN_type_scheme = 1
+ integer :: DEF_URBAN_geom_data = 1
+ logical :: DEF_URBAN_ONLY = .false.
+ logical :: DEF_URBAN_RUN = .false.
+ logical :: DEF_URBAN_BEM = .true.
+ logical :: DEF_URBAN_TREE = .true.
+ logical :: DEF_URBAN_WATER = .true.
+ logical :: DEF_URBAN_LUCY = .true.
+ logical :: DEF_USE_CANYON_HWR = .true.
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 11: parameterization schemes -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ integer :: DEF_Interception_scheme = 1 !1:CoLM;2:CLM4.5; 3:CLM5; 4:Noah-MP; 5:MATSIRO; 6:VIC; 7:JULES
+
+ ! ----- SOIL parameters and supercool water setting ------
+ integer :: DEF_THERMAL_CONDUCTIVITY_SCHEME = 4 ! Options for soil thermal conductivity schemes
+ ! 1: Farouki (1981)
+ ! 2: Johansen(1975)
+ ! 3: Cote and Konrad (2005)
+ ! 4: Balland and Arp (2005)
+ ! 5: Lu et al. (2007)
+ ! 6: Tarnawski and Leong (2012)
+ ! 7: De Vries (1963)
+ ! 8: Yan Hengnian, He Hailong et al.(2019)
+
+ logical :: DEF_USE_SUPERCOOL_WATER = .true. ! supercooled soil water scheme, Niu & Yang (2006)
+
+ ! ----- Options for soil surface resistance schemes -----
+ ! 0: NONE soil surface resistance
+ ! 1: SL14, Swenson and Lawrence (2014)
+ ! 2: SZ09, Sakaguchi and Zeng (2009)
+ ! 3: TR13, Tang and Riley (2013)
+ ! 4: LP92, Lee and Pielke (1992)
+ ! 5: S92, Sellers et al (1992)
+ integer :: DEF_RSS_SCHEME = 1
+
+ ! ----- Options for runoff parameterization schemes -----
+ ! 0: scheme from TOPMODEL, also used in CoLM2014
+ ! 1: scheme from VIC model
+ ! 2: scheme from XinAnJiang model, also used in ECMWF model
+ ! 3: scheme from Simple VIC, also used in NoahMP 5.0
+
+ integer :: DEF_Runoff_SCHEME = 3
+ character(len=256) :: DEF_file_VIC_para = 'null'
+ character(len=256) :: DEF_file_VIC_OPT = 'null'
+ logical :: DEF_VIC_OPT = .false.
+
+ integer :: DEF_TOPMOD_method = 0
+
+ ! ----- Treat exposed soil and snow surface separately -----
+ ! including solar absorption, sensible/latent heat, ground temperature,
+ ! ground heat flux and ground evp/dew/subl/fros. Corresponding vars are
+ ! named as ***_soil, ***_snow.
+ logical :: DEF_SPLIT_SOILSNOW = .false.
+
+ ! ----- Account for vegetation snow process -----
+ ! NOTE: This option will be activated in the new release, accompanied by
+ ! a new set of canopy structure data, include the snow-free LAI.
+ logical :: DEF_VEG_SNOW = .false.
+
+ ! ----- Variably Saturated Flow Soil Water -----
+ logical :: DEF_USE_VariablySaturatedFlow = .true.
+ logical :: DEF_USE_BEDROCK = .false.
+
+ ! ----- Ozone stress -----
+ logical :: DEF_USE_OZONESTRESS = .true.
+ logical :: DEF_USE_OZONEDATA = .true.
+
+ ! ----- SNICAR model related -----
+ logical :: DEF_USE_SNICAR = .false.
+ character(len=256) :: DEF_file_snowoptics = 'null'
+ character(len=256) :: DEF_file_snowaging = 'null'
+
+ ! ----- Hyperspectral related -----
+ logical :: DEF_HighResSoil = .true.
+ logical :: DEF_HighResVeg = .true.
+ logical :: DEF_PROSPECT = .false.
+
+ CHARACTER(LEN=256) :: DEF_HighResUrban_albedo = 'null'
+ ! logical :: DEF_Satellite_Params = .false.
+ ! character(len=256) :: DEF_file_soiloptics = 'null'
+ ! character(len=256) :: DEF_file_satellite_params = 'null'
+ ! character(len=256) :: DEF_sla_varname = 'null'
+
+ ! .true. read aerosol deposition data from file or .false. set in the code
+ logical :: DEF_Aerosol_Readin = .true.
+
+ ! .true. Read aerosol deposition climatology data or .false. yearly changed
+ logical :: DEF_Aerosol_Clim = .false.
+
+ ! ----- Atmospheric Nitrogen Deposition -----
+ !add by Fang Shang @ pku 2023/08
+ !1: To allow annuaul ndep data to be read in
+ !2: To allow monthly ndep data to be read in
+ integer :: DEF_NDEP_FREQUENCY = 1
+
+ ! ----- lateral flow related -----
+ character(len=256) :: DEF_ElementNeighbour_file = 'null'
+ character(len=256) :: DEF_UnitCatchment_file = 'null'
+ character(len=256) :: DEF_ReservoirPara_file = 'null'
+
+ logical :: DEF_USE_EstimatedRiverDepth = .true.
+ integer :: DEF_Reservoir_Method = 0
+ real(r8) :: DEF_GRIDBASED_ROUTING_MAX_DT = 3600.
+
+ ! ----- sediment module -----
+ logical :: DEF_USE_SEDIMENT = .false.
+ real(r8) :: DEF_SED_LAMBDA = 0.4
+ real(r8) :: DEF_SED_LYRDPH = 0.00005
+ real(r8) :: DEF_SED_DENSITY = 2.65
+ real(r8) :: DEF_SED_WATER_DENSITY = 1.0
+ real(r8) :: DEF_SED_VISKIN = 1.0e-6
+ real(r8) :: DEF_SED_VONKAR = 0.4
+ real(r8) :: DEF_SED_PSET = 1.0
+ integer :: DEF_SED_TOTLYRNUM = 5
+ real(r8) :: DEF_SED_CFL_ADV = 0.5
+ real(r8) :: DEF_SED_IGNORE_DPH = 0.05
+ real(r8) :: DEF_SED_DT_MAX = 3600.
+ character(len=256) :: DEF_SED_DIAMETER = "0.0002,0.002,0.02"
+ real(r8) :: DEF_SED_PYLD = 0.01
+ real(r8) :: DEF_SED_PYLDC = 2.0
+ real(r8) :: DEF_SED_PYLDPC = 2.0
+ real(r8) :: DEF_SED_DSYLUNIT = 1.0e-6
+
+ ! ----- others -----
+ character(len=5) :: DEF_precip_phase_discrimination_scheme = 'II'
+
+ character(len=256) :: DEF_SSP = '585' ! Co2 path for CMIP6 future scenario.
+
+ logical :: DEF_USE_IRRIGATION = .false. ! use irrigation
+ integer :: DEF_IRRIGATION_ALLOCATION = 1 ! irrigation allocated method
+
+ logical :: DEF_USE_NOSTRESSNITROGEN = .false. ! photosynthesis stress option
+ integer :: DEF_RSTFAC = 1 ! root resistance factors option
+ logical :: DEF_USE_PLANTHYDRAULICS = .true. ! Plant Hydraulics
+ logical :: DEF_USE_MEDLYNST = .false. ! Medlyn stomata model
+ logical :: DEF_USE_WUEST = .true. ! WUE stomata model
+
+ logical :: DEF_USE_SASU = .false. ! Semi-Analytic-Spin-Up
+ logical :: DEF_USE_DiagMatrix = .false.
+ logical :: DEF_USE_PN = .false. ! Punctuated nitrogen addition Spin up
+
+ logical :: DEF_USE_FERT = .true. ! Fertilisation on crop
+ integer :: DEF_FERT_SOURCE = 1 ! Fertilisation data source
+ logical :: DEF_USE_NITRIF = .true. ! Nitrification and denitrification switch
+ logical :: DEF_USE_CNSOYFIXN = .true. ! Soy nitrogen fixation
+
+ logical :: DEF_USE_FIRE = .false. ! Fire MODULE
+
+ logical :: DEF_USE_Dynamic_Lake = .false. ! Dynamic Lake model
+
+ logical :: DEF_USE_Dynamic_Wetland = .false. ! Dynamic wetland model
+
+ logical :: DEF_CheckEquilibrium = .false.
+
+ logical :: DEF_Output_2mWMO = .false. ! 2m WMO temperature
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 12: forcing -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ character(len=256) :: DEF_forcing_namelist = 'null'
+
+ character(len=256) :: DEF_dir_forcing = 'path/to/forcing/data'
+
+ type nl_forcing_type
+
+ character(len=256) :: dataset = 'CRUNCEP'
+ logical :: solarin_all_band = .true.
+ character(len=256) :: HEIGHT_mode = 'absolute'
+ real(r8) :: HEIGHT_V = 100.0
+ real(r8) :: HEIGHT_T = 50.
+ real(r8) :: HEIGHT_Q = 50.
+
+ logical :: regional = .false.
+ real(r8) :: regbnd(4) = (/-90.0, 90.0, -180.0, 180.0/)
+ logical :: has_missing_value = .false.
+ character(len=256) :: missing_value_name = 'missing_value'
+
+ integer :: NVAR = 8 ! variable number of forcing data
+ integer :: startyr = 2000 ! start year of forcing data
+ integer :: startmo = 1 ! start month of forcing data
+ integer :: endyr = 2003 ! end year of forcing data
+ integer :: endmo = 12 ! end month of forcing data
+ integer :: dtime(8) = (/21600,21600,21600,21600,0,21600,21600,21600/)
+ integer :: offset(8) = (/10800,10800,10800,10800,0,10800,0,10800/)
+ integer :: nlands = 1 ! land grid number in 1d
+
+ logical :: leapyear = .false. ! leapyear calendar
+ logical :: data2d = .true. ! data in 2 dimension (lon, lat)
+ logical :: hightdim = .false. ! have "z" dimension
+ logical :: dim2d = .true. ! lat/lon value in 2 dimension (lon, lat)
+
+ character(len=256) :: latname = 'LATIXY' ! dimension name of latitude
+ character(len=256) :: lonname = 'LONGXY' ! dimension name of longitude
+
+ character(len=256) :: groupby = 'month' ! file grouped by year/month
+
+ character(len=256) :: fprefix(8) = (/ &
+ 'TPHWL6Hrly/clmforc.cruncep.V4.c2011.0.5d.TPQWL.', &
+ 'TPHWL6Hrly/clmforc.cruncep.V4.c2011.0.5d.TPQWL.', &
+ 'TPHWL6Hrly/clmforc.cruncep.V4.c2011.0.5d.TPQWL.', &
+ 'Precip6Hrly/clmforc.cruncep.V4.c2011.0.5d.Prec.', &
+ 'NULL ', &
+ 'TPHWL6Hrly/clmforc.cruncep.V4.c2011.0.5d.TPQWL.', &
+ 'Solar6Hrly/clmforc.cruncep.V4.c2011.0.5d.Solr. ', &
+ 'TPHWL6Hrly/clmforc.cruncep.V4.c2011.0.5d.TPQWL.' /)
+ character(len=256) :: vname(8) = (/ &
+ 'TBOT ','QBOT ','PSRF ','PRECTmms', &
+ 'NULL ','WIND ','FSDS ','FLDS ' /)
+ character(len=256) :: timelog(8) = (/ &
+ 'instant ','instant ','instant ','forward ', &
+ 'NULL ','instant ','forward ','forward ' /)
+ character(len=256) :: tintalgo(8) = (/ &
+ 'linear ','linear ','linear ','nearest', &
+ 'NULL ','linear ','coszen ','linear ' /)
+
+ character(len=256) :: CBL_fprefix = 'TPHWL6Hrly/clmforc.cruncep.V4.c2011.0.5d.TPQWL.'
+ character(len=256) :: CBL_vname = 'blh'
+ character(len=256) :: CBL_tintalgo = 'linear'
+ integer :: CBL_dtime = 21600
+ integer :: CBL_offset = 10800
+ END type nl_forcing_type
+
+ type (nl_forcing_type) :: DEF_forcing
+
+ !CBL height
+ logical :: DEF_USE_CBL_HEIGHT = .false.
+
+ character(len=20) :: DEF_Forcing_Interp_Method = 'arealweight' ! 'arealweight' (default) or 'bilinear'
+
+ logical :: DEF_USE_Forcing_Downscaling = .false.
+ logical :: DEF_USE_Forcing_Downscaling_Simple = .false.
+ character(len=256):: DEF_DS_HiresTopographyDataDir = 'null'
+ character(len=5) :: DEF_DS_precipitation_adjust_scheme = 'I'
+ character(len=5) :: DEF_DS_longwave_adjust_scheme = 'II'
+
+ logical :: DEF_USE_ClimForcing_for_Spinup = .false.
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 13: data assimilation -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ character(len=256) :: DEF_DA_obsdir = 'null'
+ logical :: DEF_DA_TWS = .false.
+ logical :: DEF_DA_TWS_GRACE = .false.
+ logical :: DEF_DA_SM = .false.
+ integer :: DEF_DA_ENS_NUM = 20
+ logical :: DEF_DA_ENS_SM = .false.
+ logical :: DEF_DA_SM_SMAP = .false.
+ logical :: DEF_DA_SM_FY = .false.
+ logical :: DEF_DA_SM_SYNOP = .false.
+ integer :: DEF_DA_RTM_diel = 0
+ integer :: DEF_DA_RTM_rough = 0
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 14: parameter optimization -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ logical :: DEF_Optimize_Baseflow = .false.
+
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+! ----- Part 15: history and restart -----
+! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ logical :: DEF_HISTORY_IN_VECTOR = .false.
+
+ logical :: DEF_HIST_grid_as_forcing = .false.
+ real(r8) :: DEF_HIST_lon_res = 0.5
+ real(r8) :: DEF_HIST_lat_res = 0.5
+
+ character(len=256) :: DEF_WRST_FREQ = 'none' ! write restart file frequency: TIMESTEP/HOURLY/DAILY/MONTHLY/YEARLY
+ character(len=256) :: DEF_HIST_FREQ = 'none' ! write history file frequency: TIMESTEP/HOURLY/DAILY/MONTHLY/YEARLY
+ character(len=256) :: DEF_HIST_groupby = 'MONTH' ! history file in one file: DAY/MONTH/YEAR
+ character(len=256) :: DEF_HIST_mode = 'one'
+ logical :: DEF_HIST_WriteBack = .false.
+ integer :: DEF_REST_CompressLevel = 1
+ integer :: DEF_HIST_CompressLevel = 1
+
+ character(len=256) :: DEF_HIST_vars_namelist = 'null'
+ logical :: DEF_HIST_vars_out_default = .true.
+
+
+ ! ----- history variables -----
+ type history_var_type
+
+ logical :: xy_us = .true.
+ logical :: xy_vs = .true.
+ logical :: xy_t = .true.
+ logical :: xy_q = .true.
+ logical :: xy_prc = .true.
+ logical :: xy_prl = .true.
+ logical :: xy_pbot = .true.
+ logical :: xy_frl = .true.
+ logical :: xy_solarin = .true.
+ logical :: xy_rain = .true.
+ logical :: xy_snow = .true.
+ logical :: xy_ozone = .true.
+ logical :: xy_hpbl = .true.
+
+ logical :: taux = .true.
+ logical :: tauy = .true.
+ logical :: fsena = .true.
+ logical :: lfevpa = .true.
+ logical :: fevpa = .true.
+ logical :: fsenl = .true.
+ logical :: fevpl = .true.
+ logical :: etr = .true.
+ logical :: fseng = .true.
+ logical :: fevpg = .true.
+ logical :: fgrnd = .true.
+ logical :: sabvsun = .true.
+ logical :: sabvsha = .true.
+ logical :: sabg = .true.
+ logical :: olrg = .true.
+ logical :: rnet = .true.
+ logical :: xerr = .true.
+ logical :: zerr = .true.
+ logical :: rsur = .true.
+ logical :: rsur_se = .true.
+ logical :: rsur_ie = .true.
+ logical :: rsub = .true.
+ logical :: rnof = .true.
+ logical :: xwsur = .true.
+ logical :: xwsub = .true.
+ logical :: fldarea = .true.
+ logical :: qintr = .true.
+ logical :: qinfl = .true.
+ logical :: qdrip = .true.
+ logical :: wat = .true.
+ logical :: wat_inst = .true.
+ logical :: wetwat = .true.
+ logical :: wetwat_inst = .true.
+ logical :: wetzwt = .true.
+ logical :: assim = .true.
+ logical :: respc = .true.
+ logical :: qcharge = .true.
+ logical :: t_grnd = .true.
+ logical :: tleaf = .true.
+ logical :: ldew = .true.
+ logical :: scv = .true.
+ logical :: snowdp = .true.
+ logical :: fsno = .true.
+ logical :: frcsat = .true.
+ logical :: sigf = .true.
+ logical :: green = .true.
+ logical :: lai = .true.
+ logical :: laisun = .true.
+ logical :: laisha = .true.
+ logical :: sai = .true.
+ logical :: alb = .true.
+ logical :: alb_hires = .true.
+ logical :: reflectance_out = .true.
+ logical :: transmittance_out = .true.
+ logical :: emis = .true.
+ logical :: z0m = .true.
+ logical :: trad = .true.
+ logical :: rss = .true.
+ logical :: tref = .true.
+ logical :: t2m_wmo = .true.
+ logical :: qref = .true.
+
+ logical :: fsen_roof = .true.
+ logical :: fsen_wsun = .true.
+ logical :: fsen_wsha = .true.
+ logical :: fsen_gimp = .true.
+ logical :: fsen_gper = .true.
+ logical :: fsen_urbl = .true.
+ logical :: lfevp_roof = .true.
+ logical :: lfevp_gimp = .true.
+ logical :: lfevp_gper = .true.
+ logical :: lfevp_urbl = .true.
+ logical :: fhac = .true.
+ logical :: fwst = .true.
+ logical :: fach = .true.
+ logical :: fhah = .true.
+ logical :: meta = .true.
+ logical :: vehc = .true.
+ logical :: t_room = .true.
+ logical :: tafu = .true.
+ logical :: t_roof = .true.
+ logical :: t_wall = .true.
+
+ logical :: assimsun = .true.
+ logical :: assimsha = .true.
+ logical :: etrsun = .true.
+ logical :: etrsha = .true.
+
+ logical :: o3uptakesun = .true.
+ logical :: o3uptakesha = .true.
+
+ logical :: leafc = .true.
+ logical :: leafc_storage = .true.
+ logical :: leafc_xfer = .true.
+ logical :: frootc = .true.
+ logical :: frootc_storage = .true.
+ logical :: frootc_xfer = .true.
+ logical :: livestemc = .true.
+ logical :: livestemc_storage = .true.
+ logical :: livestemc_xfer = .true.
+ logical :: deadstemc = .true.
+ logical :: deadstemc_storage = .true.
+ logical :: deadstemc_xfer = .true.
+ logical :: livecrootc = .true.
+ logical :: livecrootc_storage = .true.
+ logical :: livecrootc_xfer = .true.
+ logical :: deadcrootc = .true.
+ logical :: deadcrootc_storage = .true.
+ logical :: deadcrootc_xfer = .true.
+ logical :: grainc = .true.
+ logical :: grainc_storage = .true.
+ logical :: grainc_xfer = .true.
+ logical :: leafn = .true.
+ logical :: leafn_storage = .true.
+ logical :: leafn_xfer = .true.
+ logical :: frootn = .true.
+ logical :: frootn_storage = .true.
+ logical :: frootn_xfer = .true.
+ logical :: livestemn = .true.
+ logical :: livestemn_storage = .true.
+ logical :: livestemn_xfer = .true.
+ logical :: deadstemn = .true.
+ logical :: deadstemn_storage = .true.
+ logical :: deadstemn_xfer = .true.
+ logical :: livecrootn = .true.
+ logical :: livecrootn_storage = .true.
+ logical :: livecrootn_xfer = .true.
+ logical :: deadcrootn = .true.
+ logical :: deadcrootn_storage = .true.
+ logical :: deadcrootn_xfer = .true.
+ logical :: grainn = .true.
+ logical :: grainn_storage = .true.
+ logical :: grainn_xfer = .true.
+ logical :: retrasn = .true.
+ logical :: gpp = .true.
+ logical :: downreg = .true.
+ logical :: ar = .true.
+ logical :: cwdprod = .true.
+ logical :: cwddecomp = .true.
+ logical :: hr = .true.
+ logical :: fpg = .true.
+ logical :: fpi = .true.
+ logical :: totvegc = .true.
+ logical :: totlitc = .true.
+ logical :: totcwdc = .true.
+ logical :: totsomc = .true.
+ logical :: totcolc = .true.
+ logical :: totvegn = .true.
+ logical :: totlitn = .true.
+ logical :: totcwdn = .true.
+ logical :: totsomn = .true.
+ logical :: totcoln = .true.
+ logical :: totsoiln_vr = .true.
+ logical :: gpp_enftemp = .false. !1
+ logical :: gpp_enfboreal = .false. !2
+ logical :: gpp_dnfboreal = .false. !3
+ logical :: gpp_ebftrop = .false. !4
+ logical :: gpp_ebftemp = .false. !5
+ logical :: gpp_dbftrop = .false. !6
+ logical :: gpp_dbftemp = .false. !7
+ logical :: gpp_dbfboreal = .false. !8
+ logical :: gpp_ebstemp = .false. !9
+ logical :: gpp_dbstemp = .false. !10
+ logical :: gpp_dbsboreal = .false. !11
+ logical :: gpp_c3arcgrass = .false. !12
+ logical :: gpp_c3grass = .false. !13
+ logical :: gpp_c4grass = .false. !14
+ logical :: leafc_enftemp = .false. !1
+ logical :: leafc_enfboreal = .false. !2
+ logical :: leafc_dnfboreal = .false. !3
+ logical :: leafc_ebftrop = .false. !4
+ logical :: leafc_ebftemp = .false. !5
+ logical :: leafc_dbftrop = .false. !6
+ logical :: leafc_dbftemp = .false. !7
+ logical :: leafc_dbfboreal = .false. !8
+ logical :: leafc_ebstemp = .false. !9
+ logical :: leafc_dbstemp = .false. !10
+ logical :: leafc_dbsboreal = .false. !11
+ logical :: leafc_c3arcgrass = .false. !12
+ logical :: leafc_c3grass = .false. !13
+ logical :: leafc_c4grass = .false. !14
+ logical :: lai_enftemp = .false. !1
+ logical :: lai_enfboreal = .false. !2
+ logical :: lai_dnfboreal = .false. !3
+ logical :: lai_ebftrop = .false. !4
+ logical :: lai_ebftemp = .false. !5
+ logical :: lai_dbftrop = .false. !6
+ logical :: lai_dbftemp = .false. !7
+ logical :: lai_dbfboreal = .false. !8
+ logical :: lai_ebstemp = .false. !9
+ logical :: lai_dbstemp = .false. !10
+ logical :: lai_dbsboreal = .false. !11
+ logical :: lai_c3arcgrass = .false. !12
+ logical :: lai_c3grass = .false. !13
+ logical :: lai_c4grass = .false. !14
+ logical :: npp_enftemp = .false. !1
+ logical :: npp_enfboreal = .false. !2
+ logical :: npp_dnfboreal = .false. !3
+ logical :: npp_ebftrop = .false. !4
+ logical :: npp_ebftemp = .false. !5
+ logical :: npp_dbftrop = .false. !6
+ logical :: npp_dbftemp = .false. !7
+ logical :: npp_dbfboreal = .false. !8
+ logical :: npp_ebstemp = .false. !9
+ logical :: npp_dbstemp = .false. !10
+ logical :: npp_dbsboreal = .false. !11
+ logical :: npp_c3arcgrass = .false. !12
+ logical :: npp_c3grass = .false. !13
+ logical :: npp_c4grass = .false. !14
+ logical :: npptoleafc_enftemp = .false. !1
+ logical :: npptoleafc_enfboreal = .false. !2
+ logical :: npptoleafc_dnfboreal = .false. !3
+ logical :: npptoleafc_ebftrop = .false. !4
+ logical :: npptoleafc_ebftemp = .false. !5
+ logical :: npptoleafc_dbftrop = .false. !6
+ logical :: npptoleafc_dbftemp = .false. !7
+ logical :: npptoleafc_dbfboreal = .false. !8
+ logical :: npptoleafc_ebstemp = .false. !9
+ logical :: npptoleafc_dbstemp = .false. !10
+ logical :: npptoleafc_dbsboreal = .false. !11
+ logical :: npptoleafc_c3arcgrass = .false. !12
+ logical :: npptoleafc_c3grass = .false. !13
+ logical :: npptoleafc_c4grass = .false. !14
+
+ logical :: cphase = .true.
+ logical :: gddmaturity = .true.
+ logical :: gddplant = .true.
+ logical :: vf = .true.
+ logical :: hui = .true.
+ logical :: cropprod1c = .true.
+ logical :: cropprod1c_loss = .true.
+ logical :: cropseedc_deficit = .true.
+ logical :: grainc_to_cropprodc = .true.
+ logical :: plantdate_rainfed_temp_corn = .true.
+ logical :: plantdate_irrigated_temp_corn = .true.
+ logical :: plantdate_rainfed_spwheat = .true.
+ logical :: plantdate_irrigated_spwheat = .true.
+ logical :: plantdate_rainfed_wtwheat = .true.
+ logical :: plantdate_irrigated_wtwheat = .true.
+ logical :: plantdate_rainfed_temp_soybean = .true.
+ logical :: plantdate_irrigated_temp_soybean = .true.
+ logical :: plantdate_rainfed_cotton = .true.
+ logical :: plantdate_irrigated_cotton = .true.
+ logical :: plantdate_rainfed_rice = .true.
+ logical :: plantdate_irrigated_rice = .true.
+ logical :: plantdate_rainfed_sugarcane = .true.
+ logical :: plantdate_irrigated_sugarcane = .true.
+ logical :: plantdate_rainfed_trop_corn = .true.
+ logical :: plantdate_irrigated_trop_corn = .true.
+ logical :: plantdate_rainfed_trop_soybean = .true.
+ logical :: plantdate_irrigated_trop_soybean = .true.
+ logical :: plantdate_unmanagedcrop = .true.
+ logical :: cropprodc_rainfed_temp_corn = .true.
+ logical :: cropprodc_irrigated_temp_corn = .true.
+ logical :: cropprodc_rainfed_spwheat = .true.
+ logical :: cropprodc_irrigated_spwheat = .true.
+ logical :: cropprodc_rainfed_wtwheat = .true.
+ logical :: cropprodc_irrigated_wtwheat = .true.
+ logical :: cropprodc_rainfed_temp_soybean = .true.
+ logical :: cropprodc_irrigated_temp_soybean = .true.
+ logical :: cropprodc_rainfed_cotton = .true.
+ logical :: cropprodc_irrigated_cotton = .true.
+ logical :: cropprodc_rainfed_rice = .true.
+ logical :: cropprodc_irrigated_rice = .true.
+ logical :: cropprodc_rainfed_sugarcane = .true.
+ logical :: cropprodc_irrigated_sugarcane = .true.
+ logical :: cropprodc_rainfed_trop_corn = .true.
+ logical :: cropprodc_irrigated_trop_corn = .true.
+ logical :: cropprodc_rainfed_trop_soybean = .true.
+ logical :: cropprodc_irrigated_trop_soybean = .true.
+ logical :: cropprodc_unmanagedcrop = .true.
+
+ logical :: grainc_to_seed = .true.
+ logical :: fert_to_sminn = .true.
+
+ logical :: huiswheat = .true.
+ logical :: pdcorn = .false.
+ logical :: pdswheat = .false.
+ logical :: pdwwheat = .false.
+ logical :: pdsoybean = .false.
+ logical :: pdcotton = .false.
+ logical :: pdrice1 = .false.
+ logical :: pdrice2 = .false.
+ logical :: pdsugarcane = .false.
+ logical :: manunitro = .false.
+ logical :: fertnitro_corn = .true.
+ logical :: fertnitro_swheat = .true.
+ logical :: fertnitro_wwheat = .true.
+ logical :: fertnitro_soybean = .true.
+ logical :: fertnitro_cotton = .true.
+ logical :: fertnitro_rice1 = .true.
+ logical :: fertnitro_rice2 = .true.
+ logical :: fertnitro_sugarcane = .true.
+ logical :: irrig_method_corn = .true.
+ logical :: irrig_method_swheat = .true.
+ logical :: irrig_method_wwheat = .true.
+ logical :: irrig_method_soybean = .true.
+ logical :: irrig_method_cotton = .true.
+ logical :: irrig_method_rice1 = .true.
+ logical :: irrig_method_rice2 = .true.
+ logical :: irrig_method_sugarcane = .true.
+
+ logical :: sum_irrig = .true.
+ logical :: sum_deficit_irrig = .true.
+ logical :: sum_irrig_count = .true.
+ logical :: waterstorage = .true.
+ logical :: groundwater_demand = .true.
+ logical :: groundwater_supply = .true.
+ logical :: reservoirriver_demand = .true.
+ logical :: reservoirriver_supply = .true.
+
+ logical :: ndep_to_sminn = .true.
+ logical :: CONC_O2_UNSAT = .false.
+ logical :: O2_DECOMP_DEPTH_UNSAT = .false.
+ logical :: abm = .false.
+ logical :: gdp = .false.
+ logical :: peatf = .false.
+ logical :: hdm = .false.
+ logical :: lnfm = .false.
+
+ logical :: leafcCap = .false.
+ logical :: leafc_storageCap = .false.
+ logical :: leafc_xferCap = .false.
+ logical :: frootcCap = .false.
+ logical :: frootc_storageCap = .false.
+ logical :: frootc_xferCap = .false.
+ logical :: livestemcCap = .false.
+ logical :: livestemc_storageCap = .false.
+ logical :: livestemc_xferCap = .false.
+ logical :: deadstemcCap = .false.
+ logical :: deadstemc_storageCap = .false.
+ logical :: deadstemc_xferCap = .false.
+ logical :: livecrootcCap = .false.
+ logical :: livecrootc_storageCap = .false.
+ logical :: livecrootc_xferCap = .false.
+ logical :: deadcrootcCap = .false.
+ logical :: deadcrootc_storageCap = .false.
+ logical :: deadcrootc_xferCap = .false.
+ logical :: leafnCap = .false.
+ logical :: leafn_storageCap = .false.
+ logical :: leafn_xferCap = .false.
+ logical :: frootnCap = .false.
+ logical :: frootn_storageCap = .false.
+ logical :: frootn_xferCap = .false.
+ logical :: livestemnCap = .false.
+ logical :: livestemn_storageCap = .false.
+ logical :: livestemn_xferCap = .false.
+ logical :: deadstemnCap = .false.
+ logical :: deadstemn_storageCap = .false.
+ logical :: deadstemn_xferCap = .false.
+ logical :: livecrootnCap = .false.
+ logical :: livecrootn_storageCap = .false.
+ logical :: livecrootn_xferCap = .false.
+ logical :: deadcrootnCap = .false.
+ logical :: deadcrootn_storageCap = .false.
+ logical :: deadcrootn_xferCap = .false.
+ logical :: t_scalar = .false.
+ logical :: w_scalar = .false.
+
+ logical :: t_soisno = .true.
+ logical :: wliq_soisno = .true.
+ logical :: wice_soisno = .true.
+
+ logical :: h2osoi = .true.
+ logical :: qlayer = .true.
+ logical :: lake_deficit = .true.
+ logical :: rstfacsun = .true.
+ logical :: rstfacsha = .true.
+ logical :: gssun = .true.
+ logical :: gssha = .true.
+ logical :: rootr = .true.
+ logical :: vegwp = .true.
+ logical :: BD_all = .true.
+ logical :: wfc = .true.
+ logical :: OM_density = .true.
+ logical :: wdsrf = .true.
+ logical :: wdsrf_inst = .true.
+ logical :: zwt = .true.
+ logical :: wa = .true.
+ logical :: wa_inst = .true.
+
+ logical :: dz_lake = .true.
+ logical :: t_lake = .true.
+ logical :: lake_icefrac = .true.
+
+ logical :: DA_wliq_h2osoi_5cm = .true.
+ logical :: DA_wliq_h2osoi_5cm_a = .true.
+ logical :: DA_t_soisno_5cm = .true.
+ logical :: DA_t_soisno_5cm_a = .true.
+ logical :: DA_wliq_soisno_ens = .true.
+ logical :: DA_t_soisno_ens = .true.
+ logical :: DA_wliq_soisno_5cm_ens_std = .true.
+ logical :: DA_t_soisno_5cm_ens_std = .true.
+ logical :: DA_t_brt_smap = .true.
+ logical :: DA_t_brt_smap_a = .true.
+ logical :: DA_t_brt_smap_ens = .true.
+ logical :: DA_t_brt_smap_ens_std = .true.
+ logical :: DA_t_brt_fy3d = .true.
+ logical :: DA_t_brt_fy3d_a = .true.
+ logical :: DA_t_brt_fy3d_ens = .true.
+ logical :: DA_t_brt_fy3d_ens_std = .true.
+
+ logical :: litr1c_vr = .true.
+ logical :: litr2c_vr = .true.
+ logical :: litr3c_vr = .true.
+ logical :: soil1c_vr = .true.
+ logical :: soil2c_vr = .true.
+ logical :: soil3c_vr = .true.
+ logical :: cwdc_vr = .true.
+ logical :: litr1n_vr = .true.
+ logical :: litr2n_vr = .true.
+ logical :: litr3n_vr = .true.
+ logical :: soil1n_vr = .true.
+ logical :: soil2n_vr = .true.
+ logical :: soil3n_vr = .true.
+ logical :: cwdn_vr = .true.
+
+ logical :: litr1cCap_vr = .false.
+ logical :: litr2cCap_vr = .false.
+ logical :: litr3cCap_vr = .false.
+ logical :: soil1cCap_vr = .false.
+ logical :: soil2cCap_vr = .false.
+ logical :: soil3cCap_vr = .false.
+ logical :: cwdcCap_vr = .false.
+ logical :: litr1nCap_vr = .false.
+ logical :: litr2nCap_vr = .false.
+ logical :: litr3nCap_vr = .false.
+ logical :: soil1nCap_vr = .false.
+ logical :: soil2nCap_vr = .false.
+ logical :: soil3nCap_vr = .false.
+ logical :: cwdnCap_vr = .false.
+
+ logical :: sminn_vr = .true.
+
+ logical :: ustar = .true.
+ logical :: ustar2 = .true.
+ logical :: tstar = .true.
+ logical :: qstar = .true.
+ logical :: zol = .true.
+ logical :: rib = .true.
+ logical :: fm = .true.
+ logical :: fh = .true.
+ logical :: fq = .true.
+ logical :: us10m = .true.
+ logical :: vs10m = .true.
+ logical :: fm10m = .true.
+ logical :: sr = .true.
+ logical :: solvd = .true.
+ logical :: solvi = .true.
+ logical :: solnd = .true.
+ logical :: solni = .true.
+ logical :: srvd = .true.
+ logical :: srvi = .true.
+ logical :: srnd = .true.
+ logical :: srni = .true.
+
+ logical :: solvdln = .true.
+ logical :: solviln = .true.
+ logical :: solndln = .true.
+ logical :: solniln = .true.
+ logical :: srvdln = .true.
+ logical :: srviln = .true.
+ logical :: srndln = .true.
+ logical :: srniln = .true.
+
+ logical :: sol_dir_ln_hires = .true.
+ logical :: sol_dif_ln_hires = .true.
+ logical :: sr_dir_ln_hires = .true.
+ logical :: sr_dif_ln_hires = .true.
+
+ logical :: xsubs_bsn = .true.
+ logical :: xsubs_hru = .true.
+ logical :: riv_height = .true.
+ logical :: riv_veloct = .true.
+ logical :: discharge = .true.
+ logical :: floodarea = .true.
+ logical :: floodfrc = .true.
+ logical :: wdsrf_hru = .true.
+ logical :: veloc_hru = .true.
+ logical :: volresv = .true.
+ logical :: qresv_in = .true.
+ logical :: qresv_out = .true.
+
+ logical :: sedcon = .true.
+ logical :: sedout = .true.
+ logical :: bedout = .true.
+ logical :: sedinp = .true.
+ logical :: netflw = .true.
+ logical :: sedlayer = .true.
+ logical :: shearvel = .false.
+
+ logical :: sensors = .true.
+
+ END type history_var_type
+
+ type (history_var_type) :: DEF_hist_vars
+
+CONTAINS
+
+ SUBROUTINE read_namelist (nlfile)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: nlfile
+
+ ! Local variables
+ logical :: fexists
+ integer :: ivar
+ integer :: ierr
+ character(len=256) :: iomesg
+
+ namelist /nl_colm/ &
+ DEF_CASE_NAME, &
+ DEF_domain, &
+
+ SITE_fsitedata, &
+ SITE_lon_location, &
+ SITE_lat_location, &
+ SITE_landtype, &
+ USE_SITE_landtype, &
+ USE_SITE_pctpfts, &
+ USE_SITE_pctcrop, &
+ USE_SITE_htop, &
+ USE_SITE_LAI, &
+ USE_SITE_lakedepth, &
+ USE_SITE_soilreflectance, &
+ USE_SITE_soilparameters, &
+ USE_SITE_dbedrock, &
+ USE_SITE_topography, &
+ USE_SITE_HistWriteBack, &
+ USE_SITE_ForcingReadAhead, &
+ USE_SITE_urban_geometry, &
+ USE_SITE_urban_ecology, &
+ USE_SITE_urban_radiation, &
+ USE_SITE_urban_thermal, &
+ USE_SITE_urban_human, &
+
+ DEF_BlockInfoFile, &
+ DEF_AverageElementSize, &
+ DEF_nx_blocks, &
+ DEF_ny_blocks, &
+ DEF_PIO_groupsize, &
+ DEF_nIO_eq_nBlock, &
+ DEF_simulation_time, &
+ DEF_dir_rawdata, &
+ DEF_dir_runtime, &
+ DEF_dir_output, &
+ DEF_file_mesh, &
+ DEF_GRIDBASED_lon_res, &
+ DEF_GRIDBASED_lat_res, &
+ DEF_CatchmentMesh_data, &
+ DEF_file_mesh_filter, &
+
+ DEF_USE_LCT, &
+ DEF_USE_PFT, &
+ DEF_USE_PC, &
+ DEF_FAST_PC, &
+ DEF_PC_CROP_SPLIT, &
+ DEF_SOLO_PFT, &
+ DEF_SUBGRID_SCHEME, &
+
+ DEF_LAI_MONTHLY, & !add by zhongwang wei @ sysu 2021/12/23
+ DEF_NDEP_FREQUENCY, & !add by Fang Shang @ pku 2023/08
+ DEF_Interception_scheme, & !add by zhongwang wei @ sysu 2022/05/23
+ DEF_SSP, & !add by zhongwang wei @ sysu 2023/02/07
+
+ DEF_LAI_START_YEAR, &
+ DEF_LAI_END_YEAR, &
+ DEF_LAI_CHANGE_YEARLY, &
+ DEF_USE_LAIFEEDBACK, & !add by Xingjie Lu, use for updating LAI with leaf carbon
+ DEF_USE_IRRIGATION, & !add by Hongbin Liang @ sysu
+ DEF_IRRIGATION_ALLOCATION, & !add by Hongbin Liang @ sysu
+ DEF_USE_NOSTRESSNITROGEN, & !add by Hongbin Liang @ sysu
+ DEF_RSTFAC, & !add by Hongbin Liang @ sysu
+ DEF_LC_YEAR, &
+ DEF_LULCC_SCHEME, &
+
+ DEF_URBAN_type_scheme, &
+ DEF_URBAN_geom_data, &
+ DEF_URBAN_ONLY, &
+ DEF_URBAN_RUN, & !add by hua yuan, open urban model or not
+ DEF_URBAN_BEM, & !add by hua yuan, open urban BEM model or not
+ DEF_URBAN_TREE, & !add by hua yuan, modeling urban tree or not
+ DEF_URBAN_WATER, & !add by hua yuan, modeling urban water or not
+ DEF_URBAN_LUCY, &
+ DEF_USE_CANYON_HWR, &
+
+ DEF_USE_SOILPAR_UPS_FIT, &
+ DEF_THERMAL_CONDUCTIVITY_SCHEME, &
+ DEF_USE_SUPERCOOL_WATER, &
+ DEF_SOIL_REFL_SCHEME, &
+ DEF_RSS_SCHEME, &
+ DEF_Runoff_SCHEME, &
+ DEF_TOPMOD_method, &
+ DEF_SPLIT_SOILSNOW, &
+ DEF_VEG_SNOW, &
+ DEF_file_VIC_para, &
+ DEF_file_VIC_OPT, &
+ DEF_VIC_OPT, & !add by Qijia Guo @ sysu
+
+ DEF_dir_existing_srfdata, &
+ USE_srfdata_from_larger_region, &
+ USE_srfdata_from_3D_gridded_data, &
+ USE_zip_for_aggregation, &
+ DEF_Srfdata_CompressLevel, &
+
+ DEF_USE_CBL_HEIGHT, & !add by zhongwang wei @ sysu 2022/12/31
+ DEF_USE_PLANTHYDRAULICS, & !add by xingjie lu @ sysu 2023/05/28
+ DEF_USE_MEDLYNST, & !add by xingjie lu @ sysu 2023/05/28
+ DEF_USE_WUEST, & !add by xingjie lu @ sysu 2024/05/28
+ DEF_USE_SASU, & !add by Xingjie Lu @ sysu 2023/06/27
+ DEF_USE_DiagMatrix, & !add by Xingjie Lu @ sysu 2023/06/27
+ DEF_USE_PN, & !add by Xingjie Lu @ sysu 2023/06/27
+ DEF_USE_FERT, & !add by Xingjie Lu @ sysu 2023/06/27
+ DEF_FERT_SOURCE, & !add by Hongbin Liang @ sysu
+ DEF_USE_NITRIF, & !add by Xingjie Lu @ sysu 2023/06/27
+ DEF_USE_CNSOYFIXN, & !add by Xingjie Lu @ sysu 2023/06/27
+ DEF_USE_FIRE, & !add by Xingjie Lu @ sysu 2023/06/27
+
+ DEF_USE_Dynamic_Lake, & !add by Shupeng Zhang @ sysu 2024/09/12
+ DEF_USE_Dynamic_Wetland, & !add by Shupeng Zhang @ sysu 2026/01/09
+
+ DEF_CheckEquilibrium, & !add by Shupeng Zhang @ sysu 2024/11/26
+ DEF_Output_2mWMO, &
+
+ DEF_LANDONLY, &
+ DEF_USE_DOMINANT_PATCHTYPE, &
+ DEF_USE_VariablySaturatedFlow, &
+ DEF_USE_BEDROCK, &
+ DEF_USE_OZONESTRESS, &
+ DEF_USE_OZONEDATA, &
+ DEF_USE_SNICAR, &
+ DEF_Aerosol_Readin, &
+ DEF_Aerosol_Clim, &
+ DEF_USE_EstimatedRiverDepth, &
+ DEF_Reservoir_Method, &
+ DEF_GRIDBASED_ROUTING_MAX_DT, &
+
+ DEF_USE_SEDIMENT, &
+ DEF_SED_LAMBDA, &
+ DEF_SED_LYRDPH, &
+ DEF_SED_DENSITY, &
+ DEF_SED_WATER_DENSITY, &
+ DEF_SED_VISKIN, &
+ DEF_SED_VONKAR, &
+ DEF_SED_PSET, &
+ DEF_SED_TOTLYRNUM, &
+ DEF_SED_CFL_ADV, &
+ DEF_SED_IGNORE_DPH, &
+ DEF_SED_DT_MAX, &
+ DEF_SED_DIAMETER, &
+ DEF_SED_PYLD, &
+ DEF_SED_PYLDC, &
+ DEF_SED_PYLDPC, &
+ DEF_SED_DSYLUNIT, &
+
+ DEF_precip_phase_discrimination_scheme, &
+
+ DEF_USE_SoilInit, &
+ DEF_file_SoilInit, &
+
+ DEF_HighResSoil, &
+ DEF_HighResVeg, &
+ DEF_PROSPECT, &
+ DEF_HighResUrban_albedo, &
+ ! DEF_Satellite_Params, &
+ ! DEF_file_soiloptics, &
+ ! DEF_file_satellite_params, &
+ ! DEF_sla_varname, &
+
+ DEF_USE_SnowInit, &
+ DEF_file_SnowInit, &
+
+ DEF_USE_CN_INIT, &
+ DEF_file_cn_init, &
+
+ DEF_USE_WaterTableInit, &
+ DEF_file_WaterTable, &
+
+ DEF_file_snowoptics, &
+ DEF_file_snowaging , &
+
+ DEF_ElementNeighbour_file, &
+ DEF_UnitCatchment_file, &
+ DEF_ReservoirPara_file, &
+
+ DEF_DA_obsdir, &
+ DEF_DA_TWS, &
+ DEF_DA_TWS_GRACE, &
+ DEF_DA_SM, &
+ DEF_DA_ENS_NUM, &
+ DEF_DA_ENS_SM, &
+ DEF_DA_SM_SMAP, &
+ DEF_DA_SM_FY, &
+ DEF_DA_SM_SYNOP, &
+ DEF_DA_RTM_diel, &
+ DEF_DA_RTM_rough, &
+
+ DEF_Optimize_Baseflow, &
+
+ DEF_forcing_namelist, &
+
+ DEF_Forcing_Interp_Method, &
+
+ DEF_USE_Forcing_Downscaling, &
+ DEF_USE_Forcing_Downscaling_Simple, &
+ DEF_DS_HiresTopographyDataDir, &
+ DEF_DS_precipitation_adjust_scheme, &
+ DEF_DS_longwave_adjust_scheme, &
+ DEF_USE_ClimForcing_for_Spinup, &
+
+ DEF_HISTORY_IN_VECTOR, &
+ DEF_HIST_lon_res, &
+ DEF_HIST_lat_res, &
+ DEF_HIST_grid_as_forcing, &
+ DEF_WRST_FREQ, &
+ DEF_HIST_FREQ, &
+ DEF_HIST_groupby, &
+ DEF_HIST_mode, &
+ DEF_HIST_WriteBack, &
+ DEF_REST_CompressLevel, &
+ DEF_HIST_CompressLevel, &
+ DEF_HIST_vars_namelist, &
+ DEF_HIST_vars_out_default
+
+ namelist /nl_colm_forcing/ DEF_dir_forcing, DEF_forcing
+ namelist /nl_colm_history/ DEF_hist_vars
+
+ ! ----- open the namelist file -----
+ IF (p_is_root) THEN
+
+ open(10, status='OLD', file=nlfile, form="FORMATTED")
+ read(10, nml=nl_colm, iostat=ierr, iomsg=iomesg)
+ IF (ierr /= 0) THEN
+ write(*,*) 'ERROR in ', trim(nlfile), ' : ', trim(iomesg)
+ CALL CoLM_Stop (' ***** ERROR: Problem reading namelist: '// trim(nlfile))
+ ENDIF
+ close(10)
+
+ open(10, status='OLD', file=trim(DEF_forcing_namelist), form="FORMATTED")
+ read(10, nml=nl_colm_forcing, iostat=ierr, iomsg=iomesg)
+ IF (ierr /= 0) THEN
+ write(*,*) 'ERROR in ', trim(DEF_forcing_namelist), ' : ', trim(iomesg)
+ CALL CoLM_Stop (' ***** ERROR: Problem reading namelist: '// trim(DEF_forcing_namelist))
+ ENDIF
+ close(10)
+
+ IF (trim(DEF_forcing%dataset) == 'POINT') THEN
+ DEF_forcing%has_missing_value = .false.
+ ENDIF
+
+ DEF_dir_landdata = trim(DEF_dir_output) // '/' // trim(adjustl(DEF_CASE_NAME)) // '/landdata'
+ DEF_dir_restart = trim(DEF_dir_output) // '/' // trim(adjustl(DEF_CASE_NAME)) // '/restart'
+ DEF_dir_history = trim(DEF_dir_output) // '/' // trim(adjustl(DEF_CASE_NAME)) // '/history'
+
+ CALL system('mkdir -p ' // trim(adjustl(DEF_dir_output )))
+ CALL system('mkdir -p ' // trim(adjustl(DEF_dir_landdata)))
+ CALL system('mkdir -p ' // trim(adjustl(DEF_dir_restart )))
+ CALL system('mkdir -p ' // trim(adjustl(DEF_dir_history )))
+
+#ifdef SinglePoint
+ DEF_nx_blocks = 360
+ DEF_ny_blocks = 180
+ DEF_HIST_mode = 'one'
+#endif
+
+ IF (DEF_simulation_time%timestep > 3600.) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: timestep should be less than or equal to 3600 seconds.'
+ CALL CoLM_Stop ()
+ ENDIF
+
+! ===============================================================
+! ----- Macros&Namelist conflicts and dependency management -----
+! ===============================================================
+
+
+! ----- SOIL model related ------ Macros&Namelist conflicts and dependency management
+#if (defined vanGenuchten_Mualem_SOIL_MODEL)
+ write(*,*) ' ***** '
+ write(*,*) 'Note: DEF_USE_VariablySaturatedFlow is automaticlly set to .true. '
+ write(*,*) 'when using vanGenuchten_Mualem_SOIL_MODEL. '
+ DEF_USE_VariablySaturatedFlow = .true.
+#endif
+#if (defined CatchLateralFlow)
+ write(*,*) ' ***** '
+ write(*,*) 'Note: DEF_USE_VariablySaturatedFlow is automaticlly set to .true. '
+ write(*,*) 'when defined CatchLateralFlow. '
+ DEF_USE_VariablySaturatedFlow = .true.
+#endif
+#ifdef SinglePoint
+ IF (DEF_Runoff_SCHEME == 0) THEN
+ write(*,*) 'Note: DEF_TOPMOD_method is set to 0 in SinglePoint.'
+ DEF_TOPMOD_method = 0
+ ENDIF
+#endif
+
+ IF (DEF_Runoff_SCHEME == 1) THEN
+ DEF_file_VIC_para = trim(DEF_dir_runtime)//'/vic/vic_para.txt'
+ IF (DEF_VIC_OPT) THEN
+ DEF_file_VIC_OPT = trim(DEF_dir_runtime)//'vic/vic_para.nc'
+ ENDIF
+ ENDIF
+
+! ----- subgrid type related ------ Macros&Namelist conflicts and dependency management
+
+#if (defined LULC_USGS || defined LULC_IGBP)
+ DEF_USE_LCT = .true.
+ DEF_USE_PFT = .false.
+ DEF_USE_PC = .false.
+ DEF_FAST_PC = .false.
+ DEF_SOLO_PFT = .false.
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ write(*,*) ' ***** '
+ write(*,*) 'Note: Soil resistance is automaticlly turned off for VG soil + USGS|IGBP scheme.'
+ DEF_RSS_SCHEME = 0
+#endif
+#endif
+
+#ifdef LULC_IGBP_PFT
+ DEF_USE_LCT = .false.
+ DEF_USE_PFT = .true.
+ DEF_USE_PC = .false.
+ DEF_FAST_PC = .false.
+#endif
+
+#ifdef LULC_IGBP_PC
+ DEF_USE_LCT = .false.
+ DEF_USE_PFT = .false.
+ DEF_USE_PC = .true.
+ DEF_SOLO_PFT = .false.
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (.not.DEF_LAI_MONTHLY) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: 8-day LAI data is not supported for '
+ write(*,*) 'LULC_IGBP_PFT and LULC_IGBP_PC.'
+ write(*,*) 'Changed to monthly data, set DEF_LAI_MONTHLY = .true.'
+ DEF_LAI_MONTHLY = .true.
+ ENDIF
+#endif
+
+
+! ----- BGC and CROP model related ------ Macros&Namelist conflicts and dependency management
+
+#ifndef BGC
+ IF(DEF_USE_LAIFEEDBACK)THEN
+ DEF_USE_LAIFEEDBACK = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: LAI feedback is not supported for BGC off.'
+ write(*,*) 'DEF_USE_LAIFEEDBACK is set to false automatically when BGC is turned off.'
+ ENDIF
+
+ IF(DEF_USE_SASU)THEN
+ DEF_USE_SASU = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Semi-Analytic Spin-up is on when BGC is off.'
+ write(*,*) 'DEF_USE_SASU is set to false automatically when BGC is turned off.'
+ ENDIF
+
+ IF(DEF_USE_DiagMatrix)THEN
+ DEF_USE_DiagMatrix = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: CN Matrix Diagnostic is on when BGC is off.'
+ write(*,*) 'DEF_USE_DiagMatrix is set to false automatically when BGC is turned off.'
+ ENDIF
+
+ IF(DEF_USE_PN)THEN
+ DEF_USE_PN = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Punctuated nitrogen addition spin up is on when BGC is off.'
+ write(*,*) 'DEF_USE_PN is set to false automatically when BGC is turned off.'
+ ENDIF
+
+ IF(DEF_USE_NITRIF)THEN
+ DEF_USE_NITRIF = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Nitrification-Denitrification is on when BGC is off.'
+ write(*,*) 'DEF_USE_NITRIF is set to false automatically when BGC is turned off.'
+ ENDIF
+
+ IF(DEF_USE_FIRE)THEN
+ DEF_USE_FIRE = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Fire model is on when BGC is off.'
+ write(*,*) 'DEF_USE_FIRE is set to false automatically when BGC is turned off.'
+ ENDIF
+#endif
+
+#ifndef CROP
+ IF(DEF_USE_FERT)THEN
+ DEF_USE_FERT = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Fertilization is on when CROP is off.'
+ write(*,*) 'DEF_USE_FERT is set to false automatically when CROP is turned off.'
+ ENDIF
+
+ IF(DEF_USE_CNSOYFIXN)THEN
+ DEF_USE_CNSOYFIXN = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Soy nitrogen fixation is on when CROP is off.'
+ write(*,*) 'DEF_USE_CNSOYFIXN is set to false automatically when CROP is turned off.'
+ ENDIF
+
+ IF(DEF_USE_IRRIGATION)THEN
+ DEF_USE_IRRIGATION = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: irrigation is on when CROP is off.'
+ write(*,*) 'DEF_USE_IRRIGATION is set to false automatically when CROP is turned off.'
+ ENDIF
+#endif
+
+ IF(.not.(DEF_FERT_SOURCE == 1 .or. DEF_FERT_SOURCE == 2))THEN
+ write(*,*) ' ***** '
+ write(*,'(A,I0,A)') 'ERROR: DEF_FERT_SOURCE is ',DEF_FERT_SOURCE,' , should only = 1 or 2'
+ CALL CoLM_stop ()
+ ENDIF
+
+ IF(.not. DEF_USE_OZONESTRESS)THEN
+ IF(DEF_USE_OZONEDATA)THEN
+ DEF_USE_OZONEDATA = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: DEF_USE_OZONEDATA is not supported for OZONESTRESS off.'
+ write(*,*) 'DEF_USE_OZONEDATA is set to false automatically.'
+ ENDIF
+ ENDIF
+
+ IF(DEF_USE_MEDLYNST)THEN
+ IF(DEF_USE_WUEST)THEN
+ DEF_USE_MEDLYNST = .false.
+ DEF_USE_WUEST = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: configure conflict, both DEF_USE_MEDLYNST and DEF_USE_WUEST were set true.'
+ write(*,*) 'set both DEF_USE_MEDLYNST and DEF_USE_WUEST to false.'
+ ENDIF
+ ENDIF
+
+! ----- SNICAR model ------ Macros&Namelist conflicts and dependency management
+
+ DEF_file_snowoptics = trim(DEF_dir_runtime)//'/snicar/snicar_optics_5bnd_mam_c211006.nc'
+ DEF_file_snowaging = trim(DEF_dir_runtime)//'/snicar/snicar_drdt_bst_fit_60_c070416.nc'
+
+ IF (.not. DEF_USE_SNICAR) THEN
+ IF (DEF_Aerosol_Readin) THEN
+ DEF_Aerosol_Readin = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: DEF_Aerosol_Readin is not needed for DEF_USE_SNICAR off. '
+ write(*,*) 'DEF_Aerosol_Readin is set to false automatically.'
+ ENDIF
+ ENDIF
+
+
+! ----- Urban model ----- Macros&Namelist conflicts and dependency management
+
+#ifdef URBAN_MODEL
+ DEF_URBAN_RUN = .true.
+
+ write(*,*) ' ***** '
+ write(*,*) 'When URBAN model is opened, WUEST/SUPERCOOL_WATER/PLANTHYDRAULICS/OZONESTRESS/SOILSNOW'
+ write(*,*) 'will be set to false automatically for simplicity.'
+ DEF_USE_WUEST = .false.
+ DEF_USE_SUPERCOOL_WATER = .false.
+ DEF_USE_PLANTHYDRAULICS = .false.
+ DEF_USE_OZONESTRESS = .false.
+ DEF_USE_OZONEDATA = .false.
+ DEF_SPLIT_SOILSNOW = .false.
+#else
+ IF (DEF_URBAN_RUN) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'Note: The Urban model is not opened. IF you want to run Urban model '
+ write(*,*) 'please #define URBAN_MODEL in define.h. otherwise DEF_URBAN_RUN will '
+ write(*,*) 'be set to false automatically.'
+ DEF_URBAN_RUN = .false.
+ ENDIF
+#endif
+
+
+! ----- LULCC ----- Macros&Namelist conflicts and dependency management
+
+#ifdef LULCC
+
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: The LULCC data is provided for years 2000 to 2020 right now! '
+ write(*,*) 'Please make sure the year range you set is suitable. '
+
+#if (defined LULC_USGS || defined BGC)
+ write(*,*) ' ***** '
+ write(*,*) 'Fatal ERROR: LULCC is not supported for LULC_USGS/BGC at present. STOP! '
+ CALL CoLM_stop ()
+#endif
+ IF (.not.DEF_LAI_MONTHLY) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'Note: When LULCC is opened, DEF_LAI_MONTHLY '
+ write(*,*) 'will be set to true automatically.'
+ DEF_LAI_MONTHLY = .true.
+ ENDIF
+
+ IF (.not.DEF_LAI_CHANGE_YEARLY) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'Note: When LULCC is opened, DEF_LAI_CHANGE_YEARLY '
+ write(*,*) 'will be set to true automatically.'
+ DEF_LAI_CHANGE_YEARLY = .true.
+ ENDIF
+
+#if (defined LULC_IGBP_PC || defined URBAN)
+ !write(*,*) ' ***** '
+ !write(*,*) 'Fatal ERROR: LULCC is not supported for LULC_IGBP_PC/URBAN at present. STOP! '
+ !write(*,*) 'It is coming soon. '
+ !CALL CoLM_stop ()
+ ![update] 24/10/2023: right now IGBP/PFT/PC and Urban are all supported.
+#endif
+
+#if (defined SinglePoint)
+ write(*,*) ' ***** '
+ write(*,*) 'Fatal ERROR: LULCC is not supported for Single Point run at present. STOP! '
+ write(*,*) 'It will come later. '
+ CALL CoLM_stop ()
+#endif
+
+#endif
+
+#if (defined DEF_LAI_CHANGE_YEARLY)
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: The LAI data is provided for years 2000 to 2020 right now! '
+ write(*,*) 'Any year before 2000 or after 2020 will be treated as 2000 or 2020. '
+#endif
+
+
+! ----- single point run ----- Macros&Namelist conflicts and dependency management
+
+#if (defined SinglePoint)
+#ifdef SrfdataDiag
+ write(*,*) ' ***** '
+ write(*,*) 'Surface data diagnose is closed in SinglePoint case.'
+#undef SrfdataDiag
+#endif
+ IF (trim(DEF_Forcing_Interp_Method) == 'bilinear') THEN
+ DEF_Forcing_Interp_Method = 'arealweight'
+ write(*,*) ' ***** '
+ write(*,*) 'Bilinear interpolation is not supported in SinglePoint case.'
+ ENDIF
+#endif
+
+! ----- Soil water and temperature Initialization ----- Namelist conflicts
+
+ IF (DEF_USE_SoilInit .and. DEF_USE_WaterTableInit) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'If both DEF_USE_SoilInit and DEF_USE_WaterTableInit are .TRUE., '
+ write(*,*) 'initial value of water table depth is read from DEF_file_SoilInit,'
+ write(*,*) 'instead of DEF_file_WaterTable (which is useless in this CASE). '
+ ENDIF
+
+! ----- dynamic lake run ----- Macros&Namelist conflicts and dependency management
+
+#ifndef CATCHMENT
+ IF ((.not. DEF_USE_VariablySaturatedFlow) .and. DEF_USE_Dynamic_Lake) THEN
+ DEF_USE_Dynamic_Lake = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Dynamic Lake is closed if variably saturated flow algorithm is not used.'
+ ENDIF
+ IF (DEF_USE_Dynamic_Lake) THEN
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Dynamic Lake is not well supported without lateral flow.'
+ ENDIF
+#else
+ DEF_USE_Dynamic_Lake = .true.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: Dynamic Lake is used if CATCHMENT-based lateral flow used.'
+#endif
+
+! ----- 2m WMO temperature ---- Macros&Namelist conflicts and dependency management
+
+#if !defined(GRIDBASED) || (defined LULC_IGBP || defined LULC_USGS)
+ IF (DEF_Output_2mWMO) THEN
+ DEF_Output_2mWMO = .false.
+ write(*,*) ' ***** '
+ write(*,*) 'Warning: 2m WMO temperature is not well supported for IGBP and USGS'
+ write(*,*) 'DEF_Output_2mWMO will be set to false automatically.'
+ ENDIF
+#endif
+
+! ----- [Complement IF needed] ----- Macros&Namelist conflicts and dependency management
+
+
+! -----END Macros&Namelist conflicts and dependency management -----
+! ===============================================================
+
+
+ ENDIF
+
+
+#ifdef USEMPI
+ CALL mpi_bcast (DEF_Output_2mWMO ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_CASE_NAME ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_domain%edges ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_domain%edgen ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_domain%edgew ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_domain%edgee ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_BlockInfoFile ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_AverageElementSize ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_nx_blocks ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_ny_blocks ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_PIO_groupsize ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_nIO_eq_nBlock ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_simulation_time%greenwich ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_simulation_time%start_year ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%start_month ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%start_day ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%start_sec ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_simulation_time%end_year ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%end_month ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%end_day ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%end_sec ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_simulation_time%spinup_year ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%spinup_month ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%spinup_day ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%spinup_sec ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_simulation_time%spinup_repeat ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_simulation_time%timestep ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_dir_rawdata ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_dir_runtime ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_dir_output ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_dir_forcing ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_dir_landdata ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_dir_restart ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_dir_history ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+#if (defined GRIDBASED || defined UNSTRUCTURED)
+ CALL mpi_bcast (DEF_file_mesh ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_GRIDBASED_lon_res ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_GRIDBASED_lat_res ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+#endif
+
+#ifdef CATCHMENT
+ CALL mpi_bcast (DEF_CatchmentMesh_data ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+#endif
+
+ CALL mpi_bcast (DEF_file_mesh_filter ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_dir_existing_srfdata ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (USE_srfdata_from_larger_region ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (USE_srfdata_from_3D_gridded_data ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (USE_zip_for_aggregation ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_Srfdata_CompressLevel ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ ! 07/2023, added by yuan: subgrid setting related
+ CALL mpi_bcast (DEF_USE_LCT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_PFT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_PC ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_FAST_PC ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_PC_CROP_SPLIT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SOLO_PFT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SUBGRID_SCHEME ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_LAI_START_YEAR ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_LAI_END_YEAR ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_LAI_CHANGE_YEARLY ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ ! 05/2023, added by Xingjie lu
+ CALL mpi_bcast (DEF_USE_LAIFEEDBACK ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_IRRIGATION ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_IRRIGATION_ALLOCATION ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_NOSTRESSNITROGEN ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_RSTFAC ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ ! LULC related
+ CALL mpi_bcast (DEF_LC_YEAR ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_LULCC_SCHEME ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_URBAN_type_scheme ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_URBAN_geom_data ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ ! 05/2023, added by yuan
+ CALL mpi_bcast (DEF_URBAN_ONLY ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_URBAN_RUN ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_URBAN_BEM ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_URBAN_TREE ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_URBAN_WATER ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_URBAN_LUCY ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_CANYON_HWR ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ ! 06/2023, added by weinan
+ CALL mpi_bcast (DEF_USE_SOILPAR_UPS_FIT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_THERMAL_CONDUCTIVITY_SCHEME ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_SUPERCOOL_WATER ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ ! 06/2023, added by hua yuan
+ CALL mpi_bcast (DEF_SOIL_REFL_SCHEME ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ ! 07/2023, added by zhuo liu
+ CALL mpi_bcast (DEF_RSS_SCHEME ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ ! 02/2024, added by Shupeng Zhang
+ CALL mpi_bcast (DEF_Runoff_SCHEME ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_VIC_OPT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_VIC_para ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_VIC_OPT ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_TOPMOD_method ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ ! 08/2023, added by hua yuan
+ CALL mpi_bcast (DEF_SPLIT_SOILSNOW ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_VEG_SNOW ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_LAI_MONTHLY ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_NDEP_FREQUENCY ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_Interception_scheme ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SSP ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_CBL_HEIGHT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_PLANTHYDRAULICS ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_MEDLYNST ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_WUEST ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_SASU ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_DiagMatrix ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_PN ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_FERT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_FERT_SOURCE ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_NITRIF ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_CNSOYFIXN ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_FIRE ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_Dynamic_Lake ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_Dynamic_Wetland ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_CheckEquilibrium ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_LANDONLY ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_DOMINANT_PATCHTYPE ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_VariablySaturatedFlow ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_BEDROCK ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_OZONESTRESS ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_OZONEDATA ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_precip_phase_discrimination_scheme ,5 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_SoilInit ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_SoilInit ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_HighResSoil ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HighResVeg ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_PROSPECT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HighResUrban_albedo ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_SnowInit ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_SnowInit ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_CN_INIT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_cn_init ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_WaterTableInit ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_WaterTable ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_SNICAR ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_snowoptics ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_file_snowaging ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_ElementNeighbour_file ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_UnitCatchment_file ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_ReservoirPara_file ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_DA_obsdir ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_TWS ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_TWS_GRACE ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_SM ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_ENS_NUM ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_ENS_SM ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_SM_SMAP ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_SM_FY ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_SM_SYNOP ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_RTM_diel ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DA_RTM_rough ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_Optimize_Baseflow ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_Aerosol_Readin ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_Aerosol_Clim ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_EstimatedRiverDepth ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_Reservoir_Method ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_GRIDBASED_ROUTING_MAX_DT ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_USE_SEDIMENT ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_LAMBDA ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_LYRDPH ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_DENSITY ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_WATER_DENSITY ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_VISKIN ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_VONKAR ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_PSET ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_TOTLYRNUM ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_CFL_ADV ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_IGNORE_DPH ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_DT_MAX ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_DIAMETER ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_PYLD ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_PYLDC ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_PYLDPC ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_SED_DSYLUNIT ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_HISTORY_IN_VECTOR ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_HIST_lon_res ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HIST_lat_res ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_HIST_grid_as_forcing ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_WRST_FREQ ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HIST_FREQ ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HIST_groupby ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HIST_mode ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HIST_WriteBack ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_REST_CompressLevel ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_HIST_CompressLevel ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_Forcing_Interp_Method ,20 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_Forcing_Downscaling ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_Forcing_Downscaling_Simple ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DS_HiresTopographyDataDir ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DS_precipitation_adjust_scheme ,5 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_DS_longwave_adjust_scheme ,5 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_USE_ClimForcing_for_Spinup ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+
+ CALL mpi_bcast (DEF_forcing%dataset ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%solarin_all_band ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%HEIGHT_mode ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%HEIGHT_V ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%HEIGHT_T ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%HEIGHT_Q ,1 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%regional ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%regbnd ,4 ,mpi_real8 ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%has_missing_value ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%missing_value_name ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%NVAR ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%startyr ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%startmo ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%endyr ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%endmo ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%dtime ,8 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%offset ,8 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%nlands ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%leapyear ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%data2d ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%hightdim ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%dim2d ,1 ,mpi_logical ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%latname ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%lonname ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%groupby ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+
+ DO ivar = 1, 8
+ CALL mpi_bcast (DEF_forcing%fprefix(ivar) ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%vname(ivar) ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%timelog(ivar) ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%tintalgo(ivar) ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ ENDDO
+ CALL mpi_bcast (DEF_forcing%CBL_fprefix ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%CBL_vname ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%CBL_tintalgo ,256 ,mpi_character ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%CBL_dtime ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+ CALL mpi_bcast (DEF_forcing%CBL_offset ,1 ,mpi_integer ,p_address_root ,p_comm_glb ,p_err)
+#endif
+
+ CALL sync_hist_vars (set_defaults = .true.)
+
+ IF (p_is_root) THEN
+
+ inquire (file=trim(DEF_HIST_vars_namelist), exist=fexists)
+ IF (.not. fexists) THEN
+ write(*,*) 'History namelist file: ', trim(DEF_HIST_vars_namelist), ' does not exist.'
+ ELSE
+ open(10, status='OLD', file=trim(DEF_HIST_vars_namelist), form="FORMATTED")
+ read(10, nml=nl_colm_history, iostat=ierr, iomsg=iomesg)
+ IF (ierr /= 0) THEN
+ write(*,*) 'ERROR in ', trim(DEF_HIST_vars_namelist), ' : ', trim(iomesg)
+ CALL CoLM_Stop (' ***** ERROR: Problem reading namelist: ' &
+ // trim(DEF_HIST_vars_namelist))
+ ENDIF
+ close(10)
+ ENDIF
+
+ IF(DEF_USE_DiagMatrix)THEN
+ DEF_hist_vars%leafcCap = .true.
+ DEF_hist_vars%leafc_storageCap = .true.
+ DEF_hist_vars%leafc_xferCap = .true.
+ DEF_hist_vars%frootcCap = .true.
+ DEF_hist_vars%frootc_storageCap = .true.
+ DEF_hist_vars%frootc_xferCap = .true.
+ DEF_hist_vars%livestemcCap = .true.
+ DEF_hist_vars%livestemc_storageCap = .true.
+ DEF_hist_vars%livestemc_xferCap = .true.
+ DEF_hist_vars%deadstemcCap = .true.
+ DEF_hist_vars%deadstemc_storageCap = .true.
+ DEF_hist_vars%deadstemc_xferCap = .true.
+ DEF_hist_vars%livecrootcCap = .true.
+ DEF_hist_vars%livecrootc_storageCap = .true.
+ DEF_hist_vars%livecrootc_xferCap = .true.
+ DEF_hist_vars%deadcrootcCap = .true.
+ DEF_hist_vars%deadcrootc_storageCap = .true.
+ DEF_hist_vars%deadcrootc_xferCap = .true.
+ DEF_hist_vars%leafnCap = .true.
+ DEF_hist_vars%leafn_storageCap = .true.
+ DEF_hist_vars%leafn_xferCap = .true.
+ DEF_hist_vars%frootnCap = .true.
+ DEF_hist_vars%frootn_storageCap = .true.
+ DEF_hist_vars%frootn_xferCap = .true.
+ DEF_hist_vars%livestemnCap = .true.
+ DEF_hist_vars%livestemn_storageCap = .true.
+ DEF_hist_vars%livestemn_xferCap = .true.
+ DEF_hist_vars%deadstemnCap = .true.
+ DEF_hist_vars%deadstemn_storageCap = .true.
+ DEF_hist_vars%deadstemn_xferCap = .true.
+ DEF_hist_vars%livecrootnCap = .true.
+ DEF_hist_vars%livecrootn_storageCap = .true.
+ DEF_hist_vars%livecrootn_xferCap = .true.
+ DEF_hist_vars%deadcrootnCap = .true.
+ DEF_hist_vars%deadcrootn_storageCap = .true.
+ DEF_hist_vars%deadcrootn_xferCap = .true.
+ DEF_hist_vars%t_scalar = .true.
+ DEF_hist_vars%w_scalar = .true.
+
+ DEF_hist_vars%litr1cCap_vr = .true.
+ DEF_hist_vars%litr2cCap_vr = .true.
+ DEF_hist_vars%litr3cCap_vr = .true.
+ DEF_hist_vars%soil1cCap_vr = .true.
+ DEF_hist_vars%soil2cCap_vr = .true.
+ DEF_hist_vars%soil3cCap_vr = .true.
+ DEF_hist_vars%cwdcCap_vr = .true.
+ DEF_hist_vars%litr1nCap_vr = .true.
+ DEF_hist_vars%litr2nCap_vr = .true.
+ DEF_hist_vars%litr3nCap_vr = .true.
+ DEF_hist_vars%soil1nCap_vr = .true.
+ DEF_hist_vars%soil2nCap_vr = .true.
+ DEF_hist_vars%soil3nCap_vr = .true.
+ DEF_hist_vars%cwdnCap_vr = .true.
+ ENDIF
+ ENDIF
+
+ CALL sync_hist_vars (set_defaults = .false.)
+
+ END SUBROUTINE read_namelist
+
+ ! ---------------
+ SUBROUTINE sync_hist_vars (set_defaults)
+
+ IMPLICIT NONE
+
+ logical, intent(in) :: set_defaults
+
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_us , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_vs , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_t , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_q , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_prc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_prl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_pbot , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_frl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_solarin , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_rain , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_snow , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%xy_hpbl , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%taux , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%tauy , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsena , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lfevpa , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fevpa , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsenl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fevpl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%etr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fseng , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fevpg , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fgrnd , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sabvsun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sabvsha , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sabg , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%olrg , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rnet , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xerr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%zerr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rsur , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rsur_se , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rsur_ie , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rsub , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rnof , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xwsur , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xwsub , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fldarea , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qintr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qinfl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qdrip , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wat_inst , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wetwat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wetwat_inst , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wetzwt , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%assim , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%respc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qcharge , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t_grnd , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%tleaf , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%ldew , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%scv , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%snowdp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsno , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frcsat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sigf , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%green , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%laisun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%laisha , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sai , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%alb , set_defaults)
+#ifdef HYPERSPECTRAL
+ CALL sync_hist_vars_one (DEF_hist_vars%alb_hires , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%reflectance_out , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%transmittance_out , set_defaults)
+#endif
+ CALL sync_hist_vars_one (DEF_hist_vars%emis , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%z0m , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%trad , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rss , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%tref , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t2m_wmo , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qref , set_defaults)
+#ifdef URBAN_MODEL
+ CALL sync_hist_vars_one (DEF_hist_vars%fsen_roof , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsen_wsun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsen_wsha , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsen_gimp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsen_gper , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fsen_urbl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lfevp_roof , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lfevp_gimp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lfevp_gper , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lfevp_urbl , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fhac , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fwst , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fach , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fhah , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%meta , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%vehc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t_room , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%tafu , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t_roof , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t_wall , set_defaults)
+#endif
+ CALL sync_hist_vars_one (DEF_hist_vars%assimsun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%assimsha , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%etrsun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%etrsha , set_defaults)
+#ifdef BGC
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainc_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainc_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainn_storage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainn_xfer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%retrasn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%downreg , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%ar , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cwdprod , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cwddecomp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%hr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fpg , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fpi , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totvegc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totlitc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totcwdc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totsomc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totcolc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totvegn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totlitn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totcwdn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totsomn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totcoln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%totsoiln_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_enftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_enfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_dnfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_ebftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_ebftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_dbftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_dbftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_dbfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_ebstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_dbstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_dbsboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_c3arcgrass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_c3grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gpp_c4grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_enftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_enfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_dnfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_ebftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_ebftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_dbftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_dbftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_dbfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_ebstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_dbstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_dbsboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_c3arcgrass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_c3grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_c4grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_enftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_enfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_dnfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_ebftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_ebftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_dbftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_dbftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_dbfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_ebstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_dbstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_dbsboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_c3arcgrass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_c3grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lai_c4grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_enftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_enfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_dnfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_ebftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_ebftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_dbftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_dbftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_dbfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_ebstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_dbstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_dbsboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_c3arcgrass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_c3grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npp_c4grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_enftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_enfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_dnfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_ebftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_ebftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_dbftrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_dbftemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_dbfboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_ebstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_dbstemp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_dbsboreal , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_c3arcgrass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_c3grass , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%npptoleafc_c4grass , set_defaults)
+#ifdef CROP
+ CALL sync_hist_vars_one (DEF_hist_vars%cphase , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gddmaturity , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gddplant , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%vf , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%hui , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprod1c , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprod1c_loss , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropseedc_deficit , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%grainc_to_cropprodc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_temp_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_temp_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_spwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_spwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_wtwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_wtwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_temp_soybean , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_temp_soybean, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_cotton , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_cotton , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_rice , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_rice , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_sugarcane , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_sugarcane , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_trop_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_trop_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_rainfed_trop_soybean , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_irrigated_trop_soybean, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%plantdate_unmanagedcrop , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_temp_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_temp_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_spwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_spwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_wtwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_wtwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_temp_soybean , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_temp_soybean, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_cotton , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_cotton , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_rice , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_rice , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_sugarcane , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_sugarcane , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_trop_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_trop_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_rainfed_trop_soybean , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_irrigated_trop_soybean, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cropprodc_unmanagedcrop , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%grainc_to_seed , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fert_to_sminn , set_defaults)
+
+ IF(DEF_USE_FERT)THEN
+ CALL sync_hist_vars_one (DEF_hist_vars%manunitro , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_corn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_swheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_wwheat , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_soybean , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_cotton , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_rice1 , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_rice2 , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fertnitro_sugarcane , set_defaults)
+ ENDIF
+
+ IF(DEF_USE_IRRIGATION)THEN
+ CALL sync_hist_vars_one (DEF_hist_vars%sum_irrig , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sum_deficit_irrig , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sum_irrig_count , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%waterstorage , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%groundwater_demand , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%groundwater_supply , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%reservoirriver_demand , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%reservoirriver_supply , set_defaults)
+ ENDIF
+#endif
+ CALL sync_hist_vars_one (DEF_hist_vars%ndep_to_sminn , set_defaults)
+ IF(DEF_USE_NITRIF)THEN
+ CALL sync_hist_vars_one (DEF_hist_vars%CONC_O2_UNSAT , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%O2_DECOMP_DEPTH_UNSAT , set_defaults)
+ ENDIF
+ IF(DEF_USE_FIRE)THEN
+ CALL sync_hist_vars_one (DEF_hist_vars%abm , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gdp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%peatf , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%hdm , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lnfm , set_defaults)
+ ENDIF
+ CALL sync_hist_vars_one (DEF_hist_vars%leafcCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafc_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootcCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootc_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootc_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemcCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemc_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemc_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemcCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemc_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemc_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootcCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootc_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootc_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootcCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootc_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootc_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafnCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafn_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%leafn_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootnCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootn_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%frootn_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemnCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemn_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livestemn_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemnCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemn_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadstemn_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootnCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootn_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%livecrootn_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootnCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootn_storageCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%deadcrootn_xferCap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t_scalar , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%w_scalar , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%litr1cCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr2cCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr3cCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil1cCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil2cCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil3cCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cwdcCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr1nCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr2nCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr3nCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil1nCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil2nCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil3nCap_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cwdnCap_vr , set_defaults)
+#endif
+ IF(DEF_USE_OZONESTRESS)THEN
+ CALL sync_hist_vars_one (DEF_hist_vars%o3uptakesun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%o3uptakesha , set_defaults)
+ ENDIF
+
+#ifdef DataAssimilation
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_wliq_h2osoi_5cm , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_wliq_h2osoi_5cm_a , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_soisno_5cm , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_soisno_5cm_a , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_wliq_soisno_ens , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_soisno_ens , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_wliq_soisno_5cm_ens_std, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_soisno_5cm_ens_std , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_smap , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_smap_a , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_smap_ens , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_smap_ens_std , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_fy3d , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_fy3d_a , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_fy3d_ens , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%DA_t_brt_fy3d_ens_std , set_defaults)
+#endif
+
+ CALL sync_hist_vars_one (DEF_hist_vars%t_soisno , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wliq_soisno , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wice_soisno , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%h2osoi , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qlayer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lake_deficit, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rstfacsun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rstfacsha , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gssun , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%gssha , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rootr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%vegwp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%BD_all , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wfc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%OM_density , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wdsrf , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wdsrf_inst , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%zwt , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wa , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wa_inst , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%dz_lake , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%t_lake , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%lake_icefrac, set_defaults)
+
+#ifdef BGC
+ CALL sync_hist_vars_one (DEF_hist_vars%litr1c_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr2c_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr3c_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil1c_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil2c_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil3c_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cwdc_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr1n_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr2n_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%litr3n_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil1n_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil2n_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%soil3n_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%cwdn_vr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sminn_vr , set_defaults)
+#endif
+
+ CALL sync_hist_vars_one (DEF_hist_vars%ustar , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%ustar2 , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%tstar , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qstar , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%zol , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%rib , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fm , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fh , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fq , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%us10m , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%vs10m , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%fm10m , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sr , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solvd , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solvi , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solnd , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solni , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srvd , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srvi , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srnd , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srni , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%solvdln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solviln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solndln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%solniln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srvdln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srviln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srndln , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%srniln , set_defaults)
+#ifdef HYPERSPECTRAL
+ CALL sync_hist_vars_one (DEF_hist_vars%sol_dir_ln_hires, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sol_dif_ln_hires, set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sr_dir_ln_hires , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sr_dif_ln_hires , set_defaults)
+#endif
+
+ CALL sync_hist_vars_one (DEF_hist_vars%xsubs_bsn , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%xsubs_hru , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%riv_height , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%riv_veloct , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%discharge , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%floodarea , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%floodfrc , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%wdsrf_hru , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%veloc_hru , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%volresv , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qresv_in , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%qresv_out , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%sedcon , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sedout , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%bedout , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sedinp , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%netflw , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%sedlayer , set_defaults)
+ CALL sync_hist_vars_one (DEF_hist_vars%shearvel , set_defaults)
+
+ CALL sync_hist_vars_one (DEF_hist_vars%sensors , set_defaults)
+
+ END SUBROUTINE sync_hist_vars
+
+ SUBROUTINE sync_hist_vars_one (onoff, set_defaults)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ logical, intent(inout) :: onoff
+ logical, intent(in) :: set_defaults
+
+ IF (p_is_root) THEN
+ IF (set_defaults) THEN
+ onoff = DEF_HIST_vars_out_default
+ ENDIF
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_bcast (onoff, 1, mpi_logical, p_address_root, p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE sync_hist_vars_one
+
+END MODULE MOD_Namelist
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFBlock.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFBlock.F90
new file mode 100644
index 0000000000..68f36f0231
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFBlock.F90
@@ -0,0 +1,461 @@
+#include
+
+MODULE MOD_NetCDFBlock
+
+!----------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! High-level Subroutines to read and write variables in files with netCDF format.
+!
+! CoLM read and write netCDF files mainly in three ways:
+! 1. Serial: read and write data by a single process;
+! 2. Vector: read/write data associated with CoLM pixelsets
+! Notice: each file contains vector data in one block.
+! 3. Block : read blocked data by IO
+! Notice: input file is a single file.
+!
+! This MODULE contains subroutines of "3. Block".
+!
+! Created by Shupeng Zhang, May 2023
+!----------------------------------------------------------------------------------
+
+ USE netcdf
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+
+ ! PUBLIC subroutines
+ INTERFACE ncio_read_block
+ MODULE procedure ncio_read_block_int32_2d
+ MODULE procedure ncio_read_block_real8_2d
+ MODULE procedure ncio_read_block_real8_3d
+ END INTERFACE ncio_read_block
+
+ INTERFACE ncio_read_block_time
+ MODULE procedure ncio_read_block_int32_2d_time
+ MODULE procedure ncio_read_block_real8_2d_time
+ MODULE procedure ncio_read_block_real8_3d_time
+ END INTERFACE ncio_read_block_time
+
+ PUBLIC :: ncio_read_site_time
+
+CONTAINS
+
+ ! ----
+ SUBROUTINE ncio_read_block_int32_2d (filename, dataname, grid, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+
+ type (block_data_int32_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: iblk, jblk, ndims(2), start2(2), count2(2), start_mem
+ integer :: ncid, varid
+ integer :: iblkme
+
+ IF (p_is_active) THEN
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid) ,trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ ndims = (/grid%xcnt(iblk), grid%ycnt(jblk)/)
+ IF (any(ndims == 0)) CYCLE
+
+ start2 = (/grid%xdsp(iblk)+1, grid%ydsp(jblk)+1/)
+ count2(1) = min(grid%xcnt(iblk), grid%nlon-grid%xdsp(iblk))
+ count2(2) = grid%ycnt(jblk)
+
+ IF (count2(1) == grid%xcnt(iblk)) THEN
+ CALL nccheck (nf90_get_var(ncid, varid, rdata%blk(iblk,jblk)%val, &
+ start2, count2) )
+ ELSE
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(1:count2(1),:), start2, count2) )
+
+ start2(1) = 1
+ start_mem = count2(1) + 1
+ count2(1) = grid%xdsp(iblk) + grid%xcnt(iblk) - grid%nlon
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(start_mem:ndims(1),:), start2, count2) )
+ ENDIF
+
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_block_int32_2d
+
+ ! ----
+ SUBROUTINE ncio_read_block_real8_2d (filename, dataname, grid, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+
+ type (block_data_real8_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: iblk, jblk, ndims(2), start2(2), count2(2), start_mem
+ integer :: ncid, varid
+ integer :: iblkme
+
+ IF (p_is_active) THEN
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid) ,trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ ndims = (/grid%xcnt(iblk), grid%ycnt(jblk)/)
+ IF (any(ndims == 0)) CYCLE
+
+ start2 = (/grid%xdsp(iblk)+1, grid%ydsp(jblk)+1/)
+ count2(1) = min(grid%xcnt(iblk), grid%nlon-grid%xdsp(iblk))
+ count2(2) = grid%ycnt(jblk)
+
+ IF (count2(1) == grid%xcnt(iblk)) THEN
+ CALL nccheck (nf90_get_var(ncid, varid, rdata%blk(iblk,jblk)%val, &
+ start2, count2) )
+ ELSE
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(1:count2(1),:), start2, count2) )
+
+ start2(1) = 1
+ start_mem = count2(1) + 1
+ count2(1) = grid%xdsp(iblk) + grid%xcnt(iblk) - grid%nlon
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(start_mem:ndims(1),:), start2, count2) )
+ ENDIF
+
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_block_real8_2d
+
+ ! ----
+ SUBROUTINE ncio_read_block_real8_3d (filename, dataname, grid, ndim1, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: ndim1
+
+ type (block_data_real8_3d), intent(inout) :: rdata
+ integer :: ncid, varid
+
+ ! Local variables
+ integer :: iblk, jblk, ndims(3), start3(3), count3(3), start_mem
+ integer :: iblkme
+
+ IF (p_is_active) THEN
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid) ,trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ ndims = (/ndim1, grid%xcnt(iblk), grid%ycnt(jblk)/)
+ IF (any(ndims == 0)) CYCLE
+
+ start3 = (/1, grid%xdsp(iblk)+1, grid%ydsp(jblk)+1/)
+ count3(1) = ndim1
+ count3(2) = min(grid%xcnt(iblk), grid%nlon-grid%xdsp(iblk))
+ count3(3) = grid%ycnt(jblk)
+
+ IF (count3(2) == grid%xcnt(iblk)) THEN
+ CALL nccheck (nf90_get_var(ncid, varid, rdata%blk(iblk,jblk)%val, &
+ start3, count3) )
+ ELSE
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(:,1:count3(2),:), start3, count3) )
+
+ start3(2) = 1
+ start_mem = count3(2) + 1
+ count3(2) = grid%xdsp(iblk) + grid%xcnt(iblk) - grid%nlon
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(:,start_mem:ndims(2),:), start3, count3) )
+ ENDIF
+
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_block_real8_3d
+
+ ! ----
+ SUBROUTINE ncio_read_block_int32_2d_time (filename, dataname, grid, itime, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: itime
+
+ type (block_data_int32_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: iblk, jblk, ndims(2), start3(3), count3(3), start_mem
+ integer :: ncid, varid
+ integer :: iblkme
+
+ IF (p_is_active) THEN
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid) ,trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ ndims = (/grid%xcnt(iblk), grid%ycnt(jblk)/)
+ IF (any(ndims == 0)) CYCLE
+
+ start3 = (/grid%xdsp(iblk)+1, grid%ydsp(jblk)+1, itime/)
+ count3(1) = min(grid%xcnt(iblk), grid%nlon-grid%xdsp(iblk))
+ count3(2) = grid%ycnt(jblk)
+ count3(3) = 1
+
+ IF (count3(1) == grid%xcnt(iblk)) THEN
+ CALL nccheck (nf90_get_var(ncid, varid, rdata%blk(iblk,jblk)%val, &
+ start3, count3) )
+ ELSE
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(1:count3(1),:), start3, count3) )
+
+ start3(1) = 1
+ start_mem = count3(1) + 1
+ count3(1) = grid%xdsp(iblk) + grid%xcnt(iblk) - grid%nlon
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(start_mem:ndims(1),:), start3, count3) )
+ ENDIF
+
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_block_int32_2d_time
+
+ ! ----
+ SUBROUTINE ncio_read_block_real8_2d_time (filename, dataname, grid, itime, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: itime
+
+ type (block_data_real8_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: iblk, jblk, ndims(2), start3(3), count3(3), start_mem
+ integer :: ncid, varid
+ integer :: iblkme
+
+ IF (p_is_active) THEN
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid) ,trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ ndims = (/grid%xcnt(iblk), grid%ycnt(jblk)/)
+ IF (any(ndims == 0)) CYCLE
+
+ start3 = (/grid%xdsp(iblk)+1, grid%ydsp(jblk)+1, itime/)
+ count3(1) = min(grid%xcnt(iblk), grid%nlon-grid%xdsp(iblk))
+ count3(2) = grid%ycnt(jblk)
+ count3(3) = 1
+ IF (count3(1) == grid%xcnt(iblk)) THEN
+ CALL nccheck (nf90_get_var(ncid, varid, rdata%blk(iblk,jblk)%val, &
+ start3, count3) ,trace=trim(filename))
+ ELSE
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(1:count3(1),:), start3, count3) )
+
+ start3(1) = 1
+ start_mem = count3(1) + 1
+ count3(1) = grid%xdsp(iblk) + grid%xcnt(iblk) - grid%nlon
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(start_mem:ndims(1),:), start3, count3) )
+ ENDIF
+
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_block_real8_2d_time
+
+ ! ----
+ SUBROUTINE ncio_read_block_real8_3d_time (filename, dataname, grid, ndim1, itime, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ type (grid_type), intent(in) :: grid
+ integer, intent(in) :: ndim1, itime
+
+ type (block_data_real8_3d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: iblk, jblk, ndims(3), start4(4), count4(4), start_mem
+ integer :: ncid, varid
+ integer :: iblkme
+
+ IF (p_is_active) THEN
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid) ,trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ ndims = (/ndim1, grid%xcnt(iblk), grid%ycnt(jblk)/)
+ IF (any(ndims == 0)) CYCLE
+
+ start4 = (/1, grid%xdsp(iblk)+1, grid%ydsp(jblk)+1, itime/)
+ count4(1) = ndim1
+ count4(2) = min(grid%xcnt(iblk), grid%nlon-grid%xdsp(iblk))
+ count4(3) = grid%ycnt(jblk)
+ count4(4) = 1
+ IF (count4(2) == grid%xcnt(iblk)) THEN
+ CALL nccheck (nf90_get_var(ncid, varid, rdata%blk(iblk,jblk)%val, &
+ start4, count4) ,trace=trim(filename))
+ ELSE
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(:,1:count4(2),:), start4, count4) )
+
+ start4(2) = 1
+ start_mem = count4(2) + 1
+ count4(2) = grid%xdsp(iblk) + grid%xcnt(iblk) - grid%nlon
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(iblk,jblk)%val(:,start_mem:ndims(2),:), start4, count4) )
+ ENDIF
+
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_block_real8_3d_time
+
+ ! ----
+ SUBROUTINE ncio_read_site_time (filename, dataname, itime, rdata)
+
+ USE netcdf
+ USE MOD_Block
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: itime
+
+ type (block_data_real8_2d), intent(inout) :: rdata
+
+ ! Local variables
+ integer :: start3(3), count3(3)
+ integer :: varid, dimid
+ character(len=256), SAVE :: fileopen = 'null'
+ integer, SAVE :: ncid, time_dim
+ logical, SAVE :: fid = .false.
+
+ IF (p_is_active) THEN
+ CALL check_ncfile_exist (filename)
+
+ IF ((.not. fid) .or. (trim(fileopen) /= trim(filename))) THEN
+ fid = .true.
+ fileopen = trim(filename)
+
+ CALL nccheck (nf90_open(trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+
+ CALL nccheck (nf90_inq_dimid(ncid, 'time', dimid), trace=trim(filename))
+ CALL nccheck (nf90_inquire_dimension(ncid, dimid, len=time_dim), trace=trim(filename))
+ ENDIF
+
+ CALL nccheck (nf90_inq_varid(ncid, trim(dataname), varid) ,trace=trim(dataname)//' in file '//trim(filename))
+
+ start3 = (/1, 1, itime/)
+ count3 = (/1, 1, 1/)
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata%blk(gblock%xblkme(1),gblock%yblkme(1))%val, start3, count3) )
+
+ IF ((itime==time_dim) .and. trim(dataname)==DEF_forcing%vname(DEF_forcing%NVAR)) THEN
+ CALL nccheck( nf90_close(ncid) )
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE ncio_read_site_time
+
+END MODULE MOD_NetCDFBlock
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFPoint.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFPoint.F90
new file mode 100644
index 0000000000..95e7615a95
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFPoint.F90
@@ -0,0 +1,425 @@
+#include
+
+MODULE MOD_NetCDFPoint
+
+!----------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! High-level Subroutines to read and write variables in files with netCDF format.
+! Read data for single point run.
+!
+! Created by Shupeng Zhang, March 2025
+!----------------------------------------------------------------------------------
+
+ USE netcdf
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Utils
+ USE MOD_NetCDFSerial, only : nccheck
+ IMPLICIT NONE
+
+ ! PUBLIC subroutines
+ PUBLIC :: read_point_var_2d_int32
+ PUBLIC :: read_point_var_2d_real8
+ PUBLIC :: read_point_var_3d_real8
+ PUBLIC :: read_point_var_3d_first_real8
+ PUBLIC :: read_point_var_2d_time_real8
+ PUBLIC :: read_point_var_3d_time_real8
+ PUBLIC :: read_point_5x5_var_2d_int32
+ PUBLIC :: read_point_5x5_var_2d_real8
+ PUBLIC :: read_point_5x5_var_3d_real8
+ PUBLIC :: read_point_5x5_var_2d_time_real8
+ PUBLIC :: read_point_5x5_var_3d_time_real8
+
+CONTAINS
+
+ ! ------
+ SUBROUTINE read_point_var_2d_int32 (grid, filename, varname, site_lon, site_lat, rdata)
+
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+
+ integer, intent(out) :: rdata
+
+ ! local variables
+ integer :: ilat, ilon
+ integer :: ncid, varid
+ integer :: rcache(1)
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rcache, (/ilon,ilat/), (/1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ rdata = rcache(1)
+
+ END SUBROUTINE read_point_var_2d_int32
+
+ ! ------
+ SUBROUTINE read_point_var_2d_real8 (grid, filename, varname, site_lon, site_lat, rdata)
+
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+
+ real(r8), intent(out) :: rdata
+
+ ! local variables
+ integer :: ilat, ilon
+ integer :: ncid, varid
+ real(r8) :: rcache(1)
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rcache, (/ilon,ilat/), (/1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ rdata = rcache(1)
+
+ END SUBROUTINE read_point_var_2d_real8
+
+ ! ------
+ SUBROUTINE read_point_var_3d_real8 (grid, filename, varname, site_lon, site_lat, nlastdim, rdata)
+
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: nlastdim
+
+ real(r8), allocatable, intent(out) :: rdata(:)
+
+ ! local variables
+ integer :: ilat, ilon
+ integer :: ncid, varid
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ allocate (rdata (nlastdim))
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rdata, (/ilon,ilat,1/), (/1,1,nlastdim/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ END SUBROUTINE read_point_var_3d_real8
+
+ ! ------
+ SUBROUTINE read_point_var_3d_first_real8 (grid, filename, varname, site_lon, site_lat, nfirstdim, rdata)
+
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: nfirstdim
+
+ real(r8), allocatable, intent(out) :: rdata(:)
+
+ ! local variables
+ integer :: ilat, ilon
+ integer :: ncid, varid
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ allocate (rdata (nfirstdim))
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rdata, (/1,ilon,ilat/), (/nfirstdim,1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ END SUBROUTINE read_point_var_3d_first_real8
+
+ ! ------
+ SUBROUTINE read_point_var_2d_time_real8 (grid, filename, varname, site_lon, site_lat, itime, rdata)
+
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: itime
+
+ real(r8), intent(out) :: rdata
+
+ ! local variables
+ integer :: ilat, ilon
+ integer :: ncid, varid
+ real(r8) :: rcache(1)
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rcache, (/ilon,ilat,itime/), (/1,1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ rdata = rcache(1)
+
+ END SUBROUTINE read_point_var_2d_time_real8
+
+ ! ------
+ SUBROUTINE read_point_var_3d_time_real8 (grid, filename, varname, site_lon, site_lat, nlastdim, itime, rdata)
+
+ IMPLICIT NONE
+
+ type(grid_type), intent(in) :: grid
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: nlastdim
+ integer, intent(in) :: itime
+
+ real(r8), allocatable, intent(out) :: rdata(:)
+
+ ! local variables
+ integer :: ilat, ilon
+ integer :: ncid, varid
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ allocate (rdata (nlastdim))
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rdata, (/ilon,ilat,1,itime/), (/1,1,nlastdim,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ END SUBROUTINE read_point_var_3d_time_real8
+
+ ! -----
+ SUBROUTINE get_5x5_filename (grid, dir_5x5, sfx, site_lon, site_lat, file_5x5, start2)
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+
+ character (len=*), intent(out) :: file_5x5
+ integer, intent(out) :: start2(2)
+
+ ! local variables
+ integer :: ilon, ilat, nxbox, nybox, ibox, jbox
+ character (len=4) :: str
+
+ ilon = find_nearest_west (site_lon, grid%nlon, grid%lon_w)
+ ilat = find_nearest_south (site_lat, grid%nlat, grid%lat_s)
+
+ nxbox = grid%nlon / 360 * 5
+ nybox = grid%nlat / 180 * 5
+
+ ibox = (ilon-1)/nxbox + 1
+ jbox = (ilat-1)/nybox + 1
+ start2(1) = ilon - (ibox-1)*nxbox
+ start2(2) = ilat - (jbox-1)*nybox
+
+ file_5x5 = trim(dir_5x5) // '/RG'
+ write(str, '(I4)') (19-jbox)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ write(str, '(I4)') (ibox-37)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ write(str, '(I4)') (18-jbox)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ write(str, '(I4)') (ibox-36)*5
+ file_5x5 = trim(file_5x5) // '_' // trim(adjustl(str))
+ file_5x5 = trim(file_5x5) // '.' // trim(sfx) // '.nc'
+
+ END SUBROUTINE get_5x5_filename
+
+ ! -----
+ SUBROUTINE read_point_5x5_var_2d_int32 (grid, dir_5x5, sfx, varname, site_lon, site_lat, rdata)
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ character (len=*), intent(in) :: varname
+
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+
+ integer, intent(out) :: rdata
+
+ ! Local variables
+ character(len=256) :: filename
+ integer :: ncid, varid, start2(2)
+ integer :: rcache(1)
+
+ CALL get_5x5_filename (grid, dir_5x5, sfx, site_lon, site_lat, filename, start2)
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rcache, start2, (/1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ rdata = rcache(1)
+
+ END SUBROUTINE read_point_5x5_var_2d_int32
+
+ ! -----
+ SUBROUTINE read_point_5x5_var_2d_real8 (grid, dir_5x5, sfx, varname, site_lon, site_lat, rdata)
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ character (len=*), intent(in) :: varname
+
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+
+ real(r8), intent(out) :: rdata
+
+ ! Local variables
+ character(len=256) :: filename
+ integer :: ncid, varid, start2(2)
+ real(r8) :: rcache(1)
+
+ CALL get_5x5_filename (grid, dir_5x5, sfx, site_lon, site_lat, filename, start2)
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rcache, start2, (/1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ rdata = rcache(1)
+
+ END SUBROUTINE read_point_5x5_var_2d_real8
+
+ ! -----
+ SUBROUTINE read_point_5x5_var_3d_real8 (grid, dir_5x5, sfx, varname, site_lon, site_lat, nlastdim, rdata)
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ character (len=*), intent(in) :: varname
+
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: nlastdim
+
+ real(r8), allocatable, intent(out) :: rdata(:)
+
+ ! Local variables
+ character(len=256) :: filename
+ integer :: ncid, varid, start3(3)
+
+ CALL get_5x5_filename (grid, dir_5x5, sfx, site_lon, site_lat, filename, start3(1:2))
+
+ allocate (rdata (nlastdim))
+
+ start3(3) = 1
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rdata, start3, (/1,1,nlastdim/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ END SUBROUTINE read_point_5x5_var_3d_real8
+
+ ! -----
+ SUBROUTINE read_point_5x5_var_2d_time_real8 (grid, dir_5x5, sfx, varname, site_lon, site_lat, itime, rdata)
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ character (len=*), intent(in) :: varname
+
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: itime
+
+ real(r8), intent(out) :: rdata
+
+ ! Local variables
+ character(len=256) :: filename
+ integer :: ncid, varid, start3(3)
+ real(r8) :: rcache(1)
+
+ CALL get_5x5_filename (grid, dir_5x5, sfx, site_lon, site_lat, filename, start3(1:2))
+
+ start3(3) = itime
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rcache, start3, (/1,1,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ rdata = rcache(1)
+
+ END SUBROUTINE read_point_5x5_var_2d_time_real8
+
+ ! -----
+ SUBROUTINE read_point_5x5_var_3d_time_real8 (grid, dir_5x5, sfx, varname, &
+ site_lon, site_lat, nlastdim, itime, rdata)
+
+ IMPLICIT NONE
+
+ type (grid_type), intent(in) :: grid
+ character (len=*), intent(in) :: dir_5x5
+ character (len=*), intent(in) :: sfx
+ character (len=*), intent(in) :: varname
+
+ real(r8), intent(in) :: site_lon
+ real(r8), intent(in) :: site_lat
+ integer, intent(in) :: nlastdim
+ integer, intent(in) :: itime
+
+ real(r8), allocatable, intent(out) :: rdata(:)
+
+ ! Local variables
+ character(len=256) :: filename
+ integer :: ncid, varid, start4(4)
+
+ CALL get_5x5_filename (grid, dir_5x5, sfx, site_lon, site_lat, filename, start4(1:2))
+
+ allocate (rdata (nlastdim))
+
+ start4(3) = 1
+ start4(4) = itime
+
+ CALL nccheck (nf90_open (trim(filename), NF90_NOWRITE, ncid), trace=trim(filename)//' cannot open')
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trace=trim(varname)//' in file '//trim(filename))
+ CALL nccheck (nf90_get_var (ncid, varid, rdata, start4, (/1,1,nlastdim,1/)) )
+ CALL nccheck (nf90_close (ncid) )
+
+ END SUBROUTINE read_point_5x5_var_3d_time_real8
+
+END MODULE MOD_NetCDFPoint
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFSerial.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFSerial.F90
new file mode 100644
index 0000000000..89c0b68b60
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFSerial.F90
@@ -0,0 +1,2615 @@
+#include
+
+MODULE MOD_NetCDFSerial
+
+!----------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! High-level Subroutines to read and write variables in files with netCDF format.
+!
+! CoLM read and write netCDF files mainly in three ways:
+! 1. Serial: read and write data by a single process;
+! 2. Vector: read/write data associated with CoLM pixelsets
+! Notice: each file CONTAINS vector data in one block.
+! 3. Block : read blocked data by IO
+! Notice: input file is a single file.
+!
+! This MODULE CONTAINS subroutines of "1. Serial".
+!
+! Created by Shupeng Zhang, May 2023
+!----------------------------------------------------------------------------------
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! PUBLIC subroutines
+
+ PUBLIC :: ncio_create_file
+ PUBLIC :: check_ncfile_exist
+
+ INTERFACE ncio_put_attr
+ MODULE procedure ncio_put_attr_str
+ MODULE procedure ncio_put_attr_real8
+ END INTERFACE ncio_put_attr
+
+ INTERFACE ncio_get_attr
+ MODULE procedure ncio_get_attr_str
+ MODULE procedure ncio_get_attr_real8
+ END INTERFACE ncio_get_attr
+
+ PUBLIC :: ncio_var_exist
+ PUBLIC :: ncio_inquire_varsize
+ PUBLIC :: ncio_inquire_length
+
+ INTERFACE ncio_read_serial
+ MODULE procedure ncio_read_serial_int32_0d
+ MODULE procedure ncio_read_serial_real8_0d
+ MODULE procedure ncio_read_serial_int8_1d
+ MODULE procedure ncio_read_serial_int32_1d
+ MODULE procedure ncio_read_serial_int64_1d
+ MODULE procedure ncio_read_serial_real8_1d
+ MODULE procedure ncio_read_serial_int8_2d
+ MODULE procedure ncio_read_serial_int16_2d
+ MODULE procedure ncio_read_serial_int32_2d
+ MODULE procedure ncio_read_serial_real4_2d
+ MODULE procedure ncio_read_serial_real8_2d
+ MODULE procedure ncio_read_serial_int32_3d
+ MODULE procedure ncio_read_serial_real8_3d
+ MODULE procedure ncio_read_serial_real8_4d
+ MODULE procedure ncio_read_serial_real8_5d
+ END INTERFACE ncio_read_serial
+
+ INTERFACE ncio_read_bcast_serial
+ MODULE procedure ncio_read_bcast_serial_int32_0d
+ MODULE procedure ncio_read_bcast_serial_real8_0d
+ MODULE procedure ncio_read_bcast_serial_int32_1d
+ MODULE procedure ncio_read_bcast_serial_int32_2d
+ MODULE procedure ncio_read_bcast_serial_real8_1d
+ MODULE procedure ncio_read_bcast_serial_real8_2d
+ MODULE procedure ncio_read_bcast_serial_real8_3d
+ MODULE procedure ncio_read_bcast_serial_real8_4d
+ MODULE procedure ncio_read_bcast_serial_real8_5d
+ MODULE procedure ncio_read_bcast_serial_logical_1d
+ END INTERFACE ncio_read_bcast_serial
+
+ INTERFACE ncio_read_part_serial
+ MODULE procedure ncio_read_part_serial_int32_1d
+ MODULE procedure ncio_read_part_serial_int32_2d
+ MODULE procedure ncio_read_part_serial_real8_2d
+ END INTERFACE ncio_read_part_serial
+
+ INTERFACE ncio_read_indexed_serial
+ MODULE procedure ncio_read_indexed_serial_int32_1d
+ MODULE procedure ncio_read_indexed_serial_real8_1d
+ MODULE procedure ncio_read_indexed_serial_int32_2d
+ MODULE procedure ncio_read_indexed_serial_real8_2d
+ END INTERFACE ncio_read_indexed_serial
+
+ PUBLIC :: ncio_read_indexed_serial
+
+ INTERFACE ncio_read_period_serial
+ MODULE procedure ncio_read_period_serial_real8_2d
+ END INTERFACE ncio_read_period_serial
+
+
+ INTERFACE ncio_define_dimension
+ MODULE procedure ncio_define_dimension_int32
+ MODULE procedure ncio_define_dimension_int64
+ END INTERFACE ncio_define_dimension
+
+ INTERFACE ncio_write_serial
+ MODULE procedure ncio_write_serial_int32_0d
+ MODULE procedure ncio_write_serial_real8_0d
+ MODULE procedure ncio_write_serial_int8_1d
+ MODULE procedure ncio_write_serial_int32_1d
+ MODULE procedure ncio_write_serial_int64_1d
+ MODULE procedure ncio_write_serial_real8_1d
+ MODULE procedure ncio_write_serial_logical_1d
+ MODULE procedure ncio_write_serial_int8_2d
+ MODULE procedure ncio_write_serial_int16_2d
+ MODULE procedure ncio_write_serial_int32_2d
+ MODULE procedure ncio_write_serial_int64_2d
+ MODULE procedure ncio_write_serial_real4_2d
+ MODULE procedure ncio_write_serial_real8_2d
+ MODULE procedure ncio_write_serial_int32_3d
+ MODULE procedure ncio_write_serial_real8_3d
+ MODULE procedure ncio_write_serial_real8_4d
+ MODULE procedure ncio_write_serial_real8_5d
+ END INTERFACE ncio_write_serial
+
+ PUBLIC :: ncio_write_serial
+ PUBLIC :: ncio_write_time
+ PUBLIC :: ncio_write_lastdim
+
+ INTERFACE ncio_write_serial_time
+ MODULE procedure ncio_write_serial_real8_0d_time
+ MODULE procedure ncio_write_serial_real8_1d_time
+ MODULE procedure ncio_write_serial_real8_2d_time
+ MODULE procedure ncio_write_serial_real8_3d_time
+ MODULE procedure ncio_write_serial_real8_4d_time
+ END INTERFACE ncio_write_serial_time
+
+ PUBLIC :: get_time_now
+
+ PUBLIC :: ncio_write_colm_dimension
+
+CONTAINS
+
+ ! ----
+ SUBROUTINE nccheck (status, trace)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ integer, intent(in) :: status
+ character(len=*), intent(in), optional :: trace
+
+ IF (status /= NF90_NOERR) THEN
+ IF (present(trace)) THEN
+ write(*,'(A)') 'Netcdf error: ' //trim(nf90_strerror(status))// ' ' //trim(trace)
+ ELSE
+ write(*,'(A)') 'Netcdf error: ' //trim(nf90_strerror(status))
+ ENDIF
+
+ CALL CoLM_stop ()
+ ENDIF
+
+ END SUBROUTINE nccheck
+
+ ! ----
+ SUBROUTINE check_ncfile_exist (filename)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ ! Local Variables
+ logical :: fexists
+
+ inquire (file=trim(filename), exist=fexists)
+ IF (.not. fexists) THEN
+ write(*,*) trim(filename), ' does not exist.'
+ CALL CoLM_stop ()
+ ENDIF
+
+ END SUBROUTINE check_ncfile_exist
+
+ ! ----
+ character(len=27) FUNCTION get_time_now ()
+
+ IMPLICIT NONE
+ character(len=8) :: date
+ character(len=10) :: time
+ character(len=5) :: zone
+
+ CALL date_and_time(date, time, zone)
+ get_time_now = date(1:8)//'-'//time(1:2)//':'//time(3:4)//':'//time(5:6) &
+ //' UTC'//zone(1:3)//':'//zone(4:5)
+
+ END FUNCTION get_time_now
+
+ ! ----
+ SUBROUTINE ncio_create_file (filename)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+
+ ! Local Variables
+ integer :: ncid
+
+ CALL nccheck( nf90_create(trim(filename), ior(NF90_CLOBBER,NF90_NETCDF4), ncid) )
+
+ CALL nccheck( nf90_put_att(ncid, NF90_GLOBAL, 'create_time', get_time_now()))
+ CALL nccheck (nf90_enddef (ncid))
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_create_file
+
+ ! ----
+ SUBROUTINE ncio_put_attr_str (filename, varname, attrname, attrval)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename, varname, attrname, attrval
+
+ ! Local Variables
+ integer :: ncid, varid
+
+ CALL nccheck( nf90_open (trim(filename), NF90_WRITE, ncid) )
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trim(varname))
+ CALL nccheck (nf90_redef (ncid))
+ CALL nccheck (nf90_put_att (ncid, varid, trim(attrname), trim(attrval)))
+ CALL nccheck (nf90_enddef (ncid))
+ CALL nccheck( nf90_close (ncid))
+
+ END SUBROUTINE ncio_put_attr_str
+
+ ! ----
+ SUBROUTINE ncio_get_attr_str (filename, varname, attrname, attrval)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename, varname, attrname
+ character(len=*), intent(out) :: attrval
+
+ ! Local Variables
+ integer :: ncid, varid
+
+ CALL nccheck( nf90_open (trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trim(varname))
+ CALL nccheck (nf90_get_att (ncid, varid, trim(attrname), attrval))
+ CALL nccheck( nf90_close (ncid))
+
+ END SUBROUTINE ncio_get_attr_str
+
+ ! ----
+ SUBROUTINE ncio_get_attr_real8 (filename, varname, attrname, attrval)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename, varname, attrname
+ real(r8), intent(out) :: attrval
+
+ ! Local Variables
+ integer :: ncid, varid
+
+ CALL nccheck( nf90_open (trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trim(varname))
+ CALL nccheck (nf90_get_att (ncid, varid, trim(attrname), attrval))
+ CALL nccheck (nf90_close (ncid))
+
+ END SUBROUTINE ncio_get_attr_real8
+
+ ! ----
+ SUBROUTINE ncio_put_attr_real8 (filename, varname, attrname, attrval)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename, varname, attrname
+ real(r8), intent(in) :: attrval
+
+ ! Local Variables
+ integer :: ncid, varid
+
+ CALL nccheck( nf90_open (trim(filename), NF90_WRITE, ncid) )
+ CALL nccheck (nf90_inq_varid (ncid, trim(varname), varid), trim(varname))
+ CALL nccheck (nf90_redef (ncid))
+ CALL nccheck (nf90_put_att (ncid, varid, trim(attrname), attrval))
+ CALL nccheck (nf90_enddef (ncid))
+ CALL nccheck( nf90_close (ncid))
+
+ END SUBROUTINE ncio_put_attr_real8
+
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_inquire_varsize (filename, dataname, varsize)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, allocatable, intent(out) :: varsize(:)
+
+ ! Local variables
+ integer :: ncid, varid, ndims, idm
+ integer, allocatable :: dimids(:)
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ CALL nccheck( nf90_inquire_variable(ncid, varid, ndims = ndims) )
+ allocate (dimids(ndims))
+ CALL nccheck( nf90_inquire_variable(ncid, varid, dimids = dimids) )
+
+ allocate (varsize(ndims))
+ DO idm = 1, ndims
+ CALL nccheck( nf90_inquire_dimension(ncid, dimids(idm), len = varsize(idm)) )
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+ deallocate (dimids)
+
+ END SUBROUTINE ncio_inquire_varsize
+
+ !---------------------------------------------------------
+ logical FUNCTION ncio_var_exist (filename, dataname, readflag)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ logical, optional,intent(in) :: readflag
+
+ ! Local variables
+ integer :: ncid, varid, status
+ logical :: readflag_
+
+ status = nf90_open(trim(filename), NF90_NOWRITE, ncid)
+ IF (status == nf90_noerr) THEN
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ ncio_var_exist = (status == nf90_noerr)
+ CALL nccheck( nf90_close(ncid) )
+ ELSE
+ ncio_var_exist = .false.
+ ENDIF
+
+ IF (present(readflag)) THEN
+ readflag_ = readflag
+ ELSE
+ readflag_ = .true.
+ ENDIF
+
+ IF ((.not. ncio_var_exist) .and. trim(filename) /= 'null' .and. readflag_) THEN
+ write(*,*) 'Warning: ', trim(dataname), ' not found in ', trim(filename)
+ ENDIF
+
+ END FUNCTION ncio_var_exist
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_inquire_length (filename, dataname, length)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(out) :: length
+
+ ! Local variables
+ integer :: ncid, varid, ndims
+ integer, allocatable :: dimids(:)
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ CALL nccheck( nf90_inquire_variable(ncid, varid, ndims = ndims) )
+ allocate (dimids(ndims))
+ CALL nccheck( nf90_inquire_variable(ncid, varid, dimids = dimids) )
+ CALL nccheck( nf90_inquire_dimension(ncid, dimids(ndims), len = length) )
+
+ CALL nccheck( nf90_close(ncid) )
+ deallocate (dimids)
+
+ END SUBROUTINE ncio_inquire_length
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int32_0d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(out) :: rdata
+
+ ! Local variables
+ integer :: ncid, varid
+
+ CALL check_ncfile_exist (filename)
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_serial_int32_0d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real8_0d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(out) :: rdata
+
+ ! Local variables
+ integer :: ncid, varid
+
+ CALL check_ncfile_exist (filename)
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_serial_real8_0d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int8_1d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer(1), allocatable, intent(out) :: rdata (:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int32_1d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, allocatable, intent(out) :: rdata (:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int64_1d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer*8, allocatable, intent(out) :: rdata (:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int64_1d
+
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real8_1d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_real8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int8_2d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer(1), allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int16_2d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer(2), allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int16_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int32_2d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+ integer :: dsp, nread
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ IF ((varsize(1) > 1000) .and. (varsize(2) > 100000)) THEN
+ dsp = 0
+ DO WHILE (dsp < varsize(2))
+ nread = min(100000,varsize(2)-dsp)
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata(1:varsize(1),dsp+1:dsp+nread), (/1,dsp+1/), (/varsize(1),nread/)))
+ dsp = dsp + nread
+ ENDDO
+ ELSE
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ ENDIF
+
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int32_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real4_2d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(4), allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_real4_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real8_2d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+ integer :: dsp, nread
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ IF ((varsize(1) > 1000) .and. (varsize(2) > 100000)) THEN
+ dsp = 0
+ DO WHILE (dsp < varsize(2))
+ nread = min(100000,varsize(2)-dsp)
+ CALL nccheck (nf90_get_var(ncid, varid, &
+ rdata(1:varsize(1),dsp+1:dsp+nread), (/1,dsp+1/), (/varsize(1),nread/)))
+ dsp = dsp + nread
+ ENDDO
+ ELSE
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ ENDIF
+
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_int32_3d (filename, dataname, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, allocatable, intent(out) :: rdata (:,:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2), varsize(3)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_int32_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real8_3d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2), varsize(3)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_real8_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real8_4d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:,:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2), varsize(3), varsize(4)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_real8_4d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_serial_real8_5d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:,:,:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ allocate (rdata (varsize(1), varsize(2), varsize(3), varsize(4), varsize(5)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_serial_real8_5d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_int32_0d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(out) :: rdata
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_int32_0d (filename, dataname, rdata)
+ ENDIF
+ CALL mpi_bcast (rdata, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_int32_0d (filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_int32_0d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_real8_0d (filename, dataname, rdata)
+
+ USE MOD_SPMD_Task
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(out) :: rdata
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_real8_0d (filename, dataname, rdata)
+ ENDIF
+ CALL mpi_bcast (rdata, 1, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_real8_0d (filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_real8_0d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_int32_1d (filename, dataname, rdata)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, allocatable, intent(out) :: rdata (:)
+ integer :: vlen
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_int32_1d(filename, dataname, rdata)
+ vlen = size(rdata)
+ ENDIF
+ CALL mpi_bcast (vlen, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vlen))
+ CALL mpi_bcast (rdata, vlen, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_int32_1d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_int32_2d (filename, dataname, rdata)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, allocatable, intent(out) :: rdata (:,:)
+ integer :: vsize(2)
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_int32_2d(filename, dataname, rdata)
+ vsize = shape(rdata)
+ ENDIF
+ CALL mpi_bcast (vsize, 2, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vsize(1), vsize(2)))
+ CALL mpi_bcast (rdata, vsize(1)*vsize(2), MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_int32_2d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_int32_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_real8_1d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_SPMD_Task
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:)
+ integer :: vlen
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_real8_1d(filename, dataname, rdata)
+ vlen = size(rdata)
+ ENDIF
+ CALL mpi_bcast (vlen, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vlen))
+ CALL mpi_bcast (rdata, vlen, MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_real8_1d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_real8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_real8_2d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_SPMD_Task
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:)
+ integer :: vsize(2)
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_real8_2d(filename, dataname, rdata)
+ vsize = shape(rdata)
+ ENDIF
+ CALL mpi_bcast (vsize, 2, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vsize(1),vsize(2)))
+ CALL mpi_bcast (rdata, vsize(1)*vsize(2), MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_real8_2d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_real8_3d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_SPMD_Task
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:,:)
+ integer :: vsize(3)
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_real8_3d(filename, dataname, rdata)
+ vsize = shape(rdata)
+ ENDIF
+ CALL mpi_bcast (vsize, 3, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vsize(1),vsize(2),vsize(3)))
+ CALL mpi_bcast (rdata, vsize(1)*vsize(2)*vsize(3), MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_real8_3d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_real8_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_real8_4d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_SPMD_Task
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:,:,:)
+ integer :: vsize(4)
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_real8_4d(filename, dataname, rdata)
+ vsize = shape(rdata)
+ ENDIF
+ CALL mpi_bcast (vsize, 4, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vsize(1),vsize(2),vsize(3),vsize(4)))
+ CALL mpi_bcast (rdata, vsize(1)*vsize(2)*vsize(3)*vsize(4), MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_real8_4d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_real8_4d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_bcast_serial_real8_5d (filename, dataname, rdata)
+
+ USE netcdf
+ USE MOD_SPMD_Task
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), allocatable, intent(out) :: rdata (:,:,:,:,:)
+ integer :: vsize(5)
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_real8_5d(filename, dataname, rdata)
+ vsize = shape(rdata)
+ ENDIF
+ CALL mpi_bcast (vsize, 5, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vsize(1),vsize(2),vsize(3),vsize(4),vsize(5)))
+ CALL mpi_bcast (rdata, vsize(1)*vsize(2)*vsize(3)*vsize(4)*vsize(5), MPI_REAL8, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_real8_5d(filename, dataname, rdata)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_real8_5d
+
+ ! -------------------------------
+ SUBROUTINE ncio_read_bcast_serial_logical_1d (filename, dataname, rdata)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ logical, allocatable, intent(out) :: rdata (:)
+ integer :: vlen
+ integer(1), allocatable :: rdata_byte(:)
+
+#ifdef USEMPI
+ IF (p_is_root) THEN
+ CALL ncio_read_serial_int8_1d(filename, dataname, rdata_byte)
+ vlen = size(rdata_byte)
+
+ allocate(rdata(vlen))
+ rdata = (rdata_byte == 1)
+
+ deallocate (rdata_byte)
+ ENDIF
+ CALL mpi_bcast (vlen, 1, MPI_INTEGER, p_address_root, p_comm_glb, p_err)
+ IF (.not. p_is_root) allocate (rdata (vlen))
+ CALL mpi_bcast (rdata, vlen, MPI_LOGICAL, p_address_root, p_comm_glb, p_err)
+#else
+ CALL ncio_read_serial_int8_1d(filename, dataname, rdata_byte)
+ vlen = size(rdata_byte)
+
+ allocate(rdata(vlen))
+ rdata = (rdata_byte == 1)
+
+ deallocate (rdata_byte)
+#endif
+
+ END SUBROUTINE ncio_read_bcast_serial_logical_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_part_serial_int32_1d (filename, dataname, datastt, dataend, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: datastt, dataend
+ integer, allocatable, intent(out) :: rdata (:)
+
+ ! Local variables
+ integer :: ncid, varid
+
+ CALL check_ncfile_exist (filename)
+
+ allocate (rdata (datastt:dataend) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata, &
+ (/datastt/), (/dataend-datastt+1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_part_serial_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_part_serial_int32_2d (filename, dataname, datastt, dataend, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: datastt(2), dataend(2)
+ integer, allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+
+ CALL check_ncfile_exist (filename)
+
+ allocate (rdata (datastt(1):dataend(1), datastt(2):dataend(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata, &
+ (/datastt(1),datastt(2)/), (/dataend(1)-datastt(1)+1, dataend(2)-datastt(2)+1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_part_serial_int32_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_part_serial_real8_2d (filename, dataname, datastt, dataend, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: datastt(2), dataend(2)
+ real(r8), allocatable, intent(out) :: rdata (:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+
+ CALL check_ncfile_exist (filename)
+
+ allocate (rdata (datastt(1):dataend(1), datastt(2):dataend(2)) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata, &
+ (/datastt(1),datastt(2)/), (/dataend(1)-datastt(1)+1, dataend(2)-datastt(2)+1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_part_serial_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_indexed_serial_int32_1d (filename, dataname, index, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: index(:)
+ integer, allocatable, intent(out) :: rdata(:)
+
+ integer :: ncid, varid
+ integer :: nidx, istart, iend, nread
+
+ nidx = size(index)
+ allocate (rdata(nidx))
+ IF (nidx == 0) RETURN
+ IF (any(index < 1)) CALL nccheck(NF90_EINVAL, trim(dataname)//' indexed read')
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ istart = 1
+ DO WHILE (istart <= nidx)
+ iend = istart
+ DO WHILE (iend < nidx .and. index(iend+1) == index(iend) + 1)
+ iend = iend + 1
+ ENDDO
+ nread = iend - istart + 1
+ CALL nccheck( nf90_get_var(ncid, varid, rdata(istart:iend), &
+ start=(/index(istart)/), count=(/nread/)) )
+ istart = iend + 1
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_indexed_serial_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_indexed_serial_real8_1d (filename, dataname, index, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: index(:)
+ real(r8), allocatable, intent(out) :: rdata(:)
+
+ integer :: ncid, varid
+ integer :: nidx, istart, iend, nread
+
+ nidx = size(index)
+ allocate (rdata(nidx))
+ IF (nidx == 0) RETURN
+ IF (any(index < 1)) CALL nccheck(NF90_EINVAL, trim(dataname)//' indexed read')
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ istart = 1
+ DO WHILE (istart <= nidx)
+ iend = istart
+ DO WHILE (iend < nidx .and. index(iend+1) == index(iend) + 1)
+ iend = iend + 1
+ ENDDO
+ nread = iend - istart + 1
+ CALL nccheck( nf90_get_var(ncid, varid, rdata(istart:iend), &
+ start=(/index(istart)/), count=(/nread/)) )
+ istart = iend + 1
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_read_indexed_serial_real8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_indexed_serial_int32_2d (filename, dataname, index, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: index(:)
+ integer, allocatable, intent(out) :: rdata(:,:)
+
+ integer :: ncid, varid
+ integer :: nidx, istart, iend, nread
+ integer, allocatable :: varsize(:)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ nidx = size(index)
+ IF (size(varsize) /= 2) CALL nccheck(NF90_EINVAL, trim(dataname)//' indexed read')
+ allocate (rdata(varsize(1), nidx))
+ IF (nidx == 0) THEN
+ deallocate (varsize)
+ RETURN
+ ENDIF
+ IF (any(index < 1)) CALL nccheck(NF90_EINVAL, trim(dataname)//' indexed read')
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ istart = 1
+ DO WHILE (istart <= nidx)
+ iend = istart
+ DO WHILE (iend < nidx .and. index(iend+1) == index(iend) + 1)
+ iend = iend + 1
+ ENDDO
+ nread = iend - istart + 1
+ CALL nccheck( nf90_get_var(ncid, varid, rdata(:,istart:iend), &
+ start=(/1,index(istart)/), count=(/varsize(1),nread/)) )
+ istart = iend + 1
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_indexed_serial_int32_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_indexed_serial_real8_2d (filename, dataname, index, rdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: index(:)
+ real(r8), allocatable, intent(out) :: rdata(:,:)
+
+ integer :: ncid, varid
+ integer :: nidx, istart, iend, nread
+ integer, allocatable :: varsize(:)
+
+ CALL ncio_inquire_varsize(filename, dataname, varsize)
+ nidx = size(index)
+ IF (size(varsize) /= 2) CALL nccheck(NF90_EINVAL, trim(dataname)//' indexed read')
+ allocate (rdata(varsize(1), nidx))
+ IF (nidx == 0) THEN
+ deallocate (varsize)
+ RETURN
+ ENDIF
+ IF (any(index < 1)) CALL nccheck(NF90_EINVAL, trim(dataname)//' indexed read')
+
+ CALL check_ncfile_exist (filename)
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+
+ istart = 1
+ DO WHILE (istart <= nidx)
+ iend = istart
+ DO WHILE (iend < nidx .and. index(iend+1) == index(iend) + 1)
+ iend = iend + 1
+ ENDDO
+ nread = iend - istart + 1
+ CALL nccheck( nf90_get_var(ncid, varid, rdata(:,istart:iend), &
+ start=(/1,index(istart)/), count=(/varsize(1),nread/)) )
+ istart = iend + 1
+ ENDDO
+
+ CALL nccheck( nf90_close(ncid) )
+ deallocate (varsize)
+
+ END SUBROUTINE ncio_read_indexed_serial_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_period_serial_real8_2d (filename, dataname, timestt, timeend, rdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: timestt, timeend
+
+ real(r8), allocatable, intent(out) :: rdata (:,:,:)
+
+ ! Local variables
+ integer :: ncid, varid
+ integer, allocatable :: varsize(:)
+
+ CALL check_ncfile_exist (filename)
+
+ CALL ncio_inquire_varsize (filename, dataname, varsize)
+
+ allocate (rdata (varsize(1), varsize(2), timestt:timeend) )
+
+ CALL nccheck( nf90_open(trim(filename), NF90_NOWRITE, ncid) )
+ CALL nccheck( nf90_inq_varid(ncid, trim(dataname), varid), trim(dataname) )
+ CALL nccheck( nf90_get_var(ncid, varid, rdata, &
+ (/1,1,timestt/), (/varsize(1),varsize(2), timeend-timestt+1/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ deallocate(varsize)
+
+ END SUBROUTINE ncio_read_period_serial_real8_2d
+
+ ! -------------------------------
+ SUBROUTINE ncio_define_dimension_int32 (filename, dimname, dimlen)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dimname
+ integer, intent(in) :: dimlen
+
+ ! Local variables
+ integer :: ncid, dimid, status
+ integer :: varid
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+
+ status = nf90_inq_dimid(ncid, trim(dimname), dimid)
+ IF (status /= NF90_NOERR) THEN
+ CALL nccheck (nf90_redef(ncid))
+ IF (dimlen == 0) THEN
+ CALL nccheck( nf90_def_dim(ncid, trim(dimname), NF90_UNLIMITED, dimid) )
+ ELSE
+ CALL nccheck( nf90_def_dim(ncid, trim(dimname), dimlen, dimid) )
+ ENDIF
+ IF (trim(dimname) .eq. 'lon') THEN
+ !print *, 'lon-def'
+ CALL nccheck( nf90_def_var(ncid, 'lon', nf90_float, (/dimid/), varid) )
+ CALL nccheck( nf90_put_att(ncid, varid, 'long_name','longitude') )
+ CALL nccheck( nf90_put_att(ncid, varid, 'units','degrees_east') )
+ ELSEIF (trim(dimname) .eq.'lat') THEN
+ !print *, 'lat-def'
+ CALL nccheck( nf90_def_var(ncid, 'lat', nf90_float, (/dimid/), varid) )
+ CALL nccheck( nf90_put_att(ncid, varid, 'long_name','latitude') )
+ CALL nccheck( nf90_put_att(ncid, varid, 'units','degrees_north') )
+ ENDIF
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_define_dimension_int32
+
+ ! -------------------------------
+ SUBROUTINE ncio_define_dimension_int64 (filename, dimname, dimlen)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dimname
+ integer*8, intent(in) :: dimlen
+
+ ! Local variables
+ integer :: ncid, dimid, status
+ integer :: varid
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+
+ status = nf90_inq_dimid(ncid, trim(dimname), dimid)
+ IF (status /= NF90_NOERR) THEN
+ CALL nccheck (nf90_redef(ncid))
+ IF (dimlen == 0) THEN
+ CALL nccheck( nf90_def_dim(ncid, trim(dimname), NF90_UNLIMITED, dimid) )
+ ELSE
+ CALL nccheck( nf90_def_dim(ncid, trim(dimname), int(dimlen), dimid) )
+ ENDIF
+ IF (trim(dimname) .eq. 'lon') THEN
+ !print *, 'lon-def'
+ CALL nccheck( nf90_def_var(ncid, 'lon', nf90_float, (/dimid/), varid) )
+ CALL nccheck( nf90_put_att(ncid, varid, 'long_name','longitude') )
+ CALL nccheck( nf90_put_att(ncid, varid, 'units','degrees_east') )
+ ELSEIF (trim(dimname) .eq.'lat') THEN
+ !print *, 'lat-def'
+ CALL nccheck( nf90_def_var(ncid, 'lat', nf90_float, (/dimid/), varid) )
+ CALL nccheck( nf90_put_att(ncid, varid, 'long_name','latitude') )
+ CALL nccheck( nf90_put_att(ncid, varid, 'units','degrees_north') )
+ ENDIF
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_define_dimension_int64
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int32_0d (filename, dataname, wdata)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: wdata
+
+ ! Local variables
+ integer :: ncid, varid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ CALL nccheck (nf90_redef(ncid))
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, varid = varid))
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int32_0d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_0d (filename, dataname, wdata)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(in) :: wdata
+
+ ! Local variables
+ integer :: ncid, varid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ CALL nccheck (nf90_redef(ncid))
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, varid = varid))
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_0d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int8_1d (filename, dataname, wdata, dimname, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer(1), intent(in) :: wdata (:)
+
+ character(len=*), intent(in), optional :: dimname
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. present(dimname)) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dimname), dimid))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_BYTE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_BYTE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int32_1d (filename, dataname, wdata, dimname, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: wdata (:)
+
+ character(len=*), intent(in), optional :: dimname
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. present(dimname)) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dimname), dimid))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int64_1d (filename, dataname, wdata, dimname, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer*8, intent(in) :: wdata (:)
+
+ character(len=*), intent(in), optional :: dimname
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. present(dimname)) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dimname), dimid))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT64, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT64, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int64_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_1d (filename, dataname, wdata, dimname, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(in) :: wdata (:)
+
+ character(len=*), intent(in), optional :: dimname
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. present(dimname)) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dimname), dimid))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_logical_1d (filename, dataname, wdata, dimname, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ logical, intent(in) :: wdata (:)
+
+ character(len=*), intent(in) :: dimname
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer(1), allocatable :: wdata_byte(:)
+
+ allocate(wdata_byte(size(wdata)))
+ WHERE(wdata)
+ wdata_byte = 1
+ ELSEWHERE
+ wdata_byte = 0
+ ENDWHERE
+
+ IF (present(compress)) THEN
+ CALL ncio_write_serial_int8_1d (filename, dataname, wdata_byte, dimname, compress)
+ ELSE
+ CALL ncio_write_serial_int8_1d (filename, dataname, wdata_byte, dimname)
+ ENDIF
+
+ deallocate(wdata_byte)
+
+ END SUBROUTINE ncio_write_serial_logical_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int8_2d (filename, dataname, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer(1), intent(in) :: wdata (:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_BYTE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_BYTE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int16_2d (filename, dataname, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer(2), intent(in) :: wdata (:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_SHORT, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_SHORT, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int16_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int32_2d (filename, dataname, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: wdata (:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int32_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int64_2d (filename, dataname, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer*8, intent(in) :: wdata (:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT64, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT64, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int64_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real4_2d (filename, dataname, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(4), intent(in) :: wdata (:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_FLOAT, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_FLOAT, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real4_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_2d (filename, dataname, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(in) :: wdata (:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_int32_3d (filename, dataname, wdata, &
+ dim1name, dim2name, dim3name, compress)
+
+ USE netcdf
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: wdata (:,:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(3), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) .and. present(dim3name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_INT, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_int32_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_3d (filename, dataname, wdata, &
+ dim1name, dim2name, dim3name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(in) :: wdata (:,:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(3), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) .and. present(dim3name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_4d (filename, dataname, wdata, &
+ dim1name, dim2name, dim3name, dim4name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(in) :: wdata (:,:,:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name, dim4name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(4), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) &
+ .and. present(dim3name) .and. present(dim4name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim4name), dimid(4)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_4d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_5d (filename, dataname, wdata, &
+ dim1name, dim2name, dim3name, dim4name, dim5name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ real(r8), intent(in) :: wdata (:,:,:,:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name
+ character(len=*), intent(in), optional :: dim4name, dim5name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(5), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) .and. present(dim3name) &
+ .and. present(dim4name) .and. present(dim5name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim4name), dimid(4)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim5name), dimid(5)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_5d
+
+ !------------------------------
+ SUBROUTINE ncio_write_time (filename, dataname, time_component, itime, adjust)
+
+ USE MOD_TimeManager
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: time_component(3)
+ integer, intent(out) :: itime
+
+ character(len=*), intent(in), optional :: adjust
+
+ ! Local variables
+ integer, allocatable :: time_file(:)
+ integer :: ncid, varid, time_id, status
+ integer :: timelen, minutes
+
+ minutes = minutes_since_1900 (time_component(1), time_component(2), time_component(3))
+
+ IF (present(adjust)) THEN
+ SELECTCASE (trim(adjustl(adjust)))
+ CASE ('HOURLY')
+ minutes = minutes - 30
+ CASE ('DAILY')
+ minutes = minutes - 720
+ CASE ('MONTHLY')
+ minutes = minutes - 21600
+ CASE ('YEARLY')
+ minutes = minutes - 262800
+ ENDSELECT
+ ENDIF
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status == NF90_NOERR) THEN
+ CALL nccheck( nf90_inq_dimid(ncid, 'time', time_id) )
+ CALL nccheck( nf90_inquire_dimension(ncid, time_id, len = timelen) )
+
+ itime = 1
+ IF (timelen > 0) THEN
+ allocate (time_file (timelen))
+ CALL nccheck( nf90_get_var(ncid, varid, time_file) )
+
+ DO WHILE (itime <= timelen)
+ IF (minutes == time_file(itime)) EXIT
+ itime = itime + 1
+ ENDDO
+
+ deallocate(time_file)
+ ENDIF
+
+ ELSE
+ status = nf90_inq_dimid(ncid, 'time', time_id)
+ IF (status /= NF90_NOERR) THEN
+ CALL nccheck( nf90_redef(ncid) )
+ CALL nccheck( nf90_def_dim(ncid, 'time', NF90_UNLIMITED, time_id) )
+ CALL nccheck( nf90_enddef(ncid) )
+ ENDIF
+
+ CALL nccheck( nf90_redef(ncid) )
+ CALL nccheck( nf90_def_var(ncid, trim(dataname), NF90_INT, (/time_id/), varid) )
+
+ CALL nccheck( nf90_put_att(ncid, varid, 'long_name', 'time') )
+ CALL nccheck( nf90_put_att(ncid, varid, 'units', 'minutes since 1900-1-1 0:0:0') )
+ CALL nccheck( nf90_enddef(ncid) )
+
+ itime = 1
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, minutes, (/itime/)) )
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_time
+
+ !------------------------------
+ SUBROUTINE ncio_write_lastdim (filename, lastname, lastvalue, ilast)
+
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: lastname
+ integer, intent(in) :: lastvalue
+ integer, intent(out) :: ilast
+
+ ! Local variables
+ integer :: ncid, varid, dimid, dimlen, status
+ integer, allocatable :: lastvalue_f(:)
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+
+ status = nf90_inq_varid(ncid, trim(lastname), varid)
+
+ IF (status == NF90_NOERR) THEN
+ CALL nccheck( nf90_inq_dimid(ncid, trim(lastname), dimid) )
+ CALL nccheck( nf90_inquire_dimension(ncid, dimid, len = dimlen) )
+
+ ilast = 1
+ IF (dimlen > 0) THEN
+ allocate (lastvalue_f (dimlen))
+ CALL nccheck( nf90_get_var(ncid, varid, lastvalue_f) )
+
+ DO WHILE (ilast <= dimlen)
+ IF (lastvalue == lastvalue_f(ilast)) EXIT
+ ilast = ilast + 1
+ ENDDO
+
+ deallocate(lastvalue_f)
+ ENDIF
+ ELSE
+ status = nf90_inq_dimid(ncid, trim(lastname), dimid)
+ IF (status /= NF90_NOERR) THEN
+ CALL nccheck( nf90_redef(ncid) )
+ CALL nccheck( nf90_def_dim(ncid, trim(lastname), NF90_UNLIMITED, dimid) )
+ CALL nccheck( nf90_enddef(ncid) )
+ ENDIF
+
+ CALL nccheck( nf90_redef(ncid) )
+ CALL nccheck( nf90_def_var(ncid, trim(lastname), NF90_INT, (/dimid/), varid) )
+ CALL nccheck( nf90_enddef(ncid) )
+
+ ilast = 1
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, lastvalue, (/ilast/)) )
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_lastdim
+
+ !----------------------------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_0d_time ( &
+ filename, dataname, itime, wdata, dim1name)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: itime
+ real(r8), intent(in) :: wdata
+
+ character(len=*), intent(in), optional :: dim1name
+
+ ! Local variables
+ integer :: ncid, varid, dimid, status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. present(dim1name)) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid))
+
+ CALL nccheck (nf90_redef(ncid))
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata, start = (/itime/)) )
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_0d_time
+
+ !----------------------------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_1d_time ( &
+ filename, dataname, itime, wdata, &
+ dim1name, dim2name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: itime
+ real(r8), intent(in) :: wdata(:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(2), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata, &
+ (/1,itime/), (/size(wdata,1),1/)) )
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_1d_time
+
+ !----------------------------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_2d_time ( &
+ filename, dataname, itime, wdata, &
+ dim1name, dim2name, dim3name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: itime
+ real(r8), intent(in) :: wdata(:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(3), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) .and. present(dim3name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata, &
+ (/1,1,itime/), (/size(wdata,1),size(wdata,2),1/)) )
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_2d_time
+
+ !----------------------------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_3d_time ( &
+ filename, dataname, itime, wdata, &
+ dim1name, dim2name, dim3name, dim4name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: itime
+ real(r8), intent(in) :: wdata(:,:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name, dim4name
+ integer, intent(in), optional :: compress
+ ! Local variables
+ integer :: ncid, varid, dimid(4), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) &
+ .and. present(dim3name) .and. present(dim4name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim4name), dimid(4)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata, &
+ (/1,1,1,itime/), (/size(wdata,1),size(wdata,2),size(wdata,3),1/)) )
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_3d_time
+
+ !----------------------------------------------------------------------------
+ SUBROUTINE ncio_write_serial_real8_4d_time ( &
+ filename, dataname, itime, wdata, &
+ dim1name, dim2name, dim3name, dim4name, dim5name, compress)
+
+ USE netcdf
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ character (len=*), intent(in) :: filename
+ character (len=*), intent(in) :: dataname
+ integer, intent(in) :: itime
+ real(r8), intent(in) :: wdata(:,:,:,:)
+
+ character(len=*), intent(in), optional :: dim1name, dim2name, dim3name
+ character(len=*), intent(in), optional :: dim4name, dim5name
+ integer, intent(in), optional :: compress
+
+ ! Local variables
+ integer :: ncid, varid, dimid(5), status
+
+ CALL nccheck( nf90_open(trim(filename), NF90_WRITE, ncid) )
+ status = nf90_inq_varid(ncid, trim(dataname), varid)
+ IF (status /= NF90_NOERR) THEN
+ IF (.not. (present(dim1name) .and. present(dim2name) &
+ .and. present(dim3name) .and. present(dim4name) .and. present(dim5name))) THEN
+ write(*,*) 'Warning: no dimension name for ', trim(dataname)
+ CALL nccheck( nf90_close(ncid) )
+ RETURN
+ ENDIF
+
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim1name), dimid(1)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim2name), dimid(2)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim3name), dimid(3)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim4name), dimid(4)))
+ CALL nccheck (nf90_inq_dimid(ncid, trim(dim5name), dimid(5)))
+
+ CALL nccheck (nf90_redef(ncid))
+ IF (present(compress)) THEN
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid, &
+ deflate_level = compress))
+ ELSE
+ CALL nccheck (nf90_def_var(ncid, trim(dataname), NF90_DOUBLE, dimid, varid))
+ ENDIF
+
+ CALL nccheck (nf90_enddef(ncid))
+ ENDIF
+
+ CALL nccheck( nf90_put_var(ncid, varid, wdata, &
+ (/1,1,1,1,itime/), (/size(wdata,1),size(wdata,2),size(wdata,3),size(wdata,4), 1/)) )
+
+ CALL nccheck( nf90_close(ncid) )
+
+ END SUBROUTINE ncio_write_serial_real8_4d_time
+
+ !----------------------
+ SUBROUTINE ncio_write_colm_dimension (filename)
+
+ USE MOD_Vars_Global, only: nl_soil, maxsnl, nl_lake, nvegwcs
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+
+ ! Local Variables
+ integer :: soillayers(1:nl_soil)
+ integer :: soilinterfaces(0:nl_soil)
+ integer :: soilsnowlayers(-maxsnl+nl_soil)
+ integer :: lakelayers(1:nl_lake)
+ integer :: vegnodes(1:nvegwcs)
+ integer :: i
+
+
+ soillayers = (/(i, i = 1,nl_soil)/)
+ CALL ncio_define_dimension (filename, 'soil', nl_soil)
+ CALL ncio_write_serial (filename, 'soil', soillayers, 'soil')
+ CALL ncio_put_attr_str (filename, 'soil', 'long_name', 'soil layers')
+
+ soilinterfaces = (/(i, i = 0,nl_soil)/)
+ CALL ncio_define_dimension (filename, 'soilinterface', nl_soil+1)
+ CALL ncio_write_serial (filename, 'soilinterface', soilinterfaces, 'soilinterface')
+ CALL ncio_put_attr_str (filename, 'soilinterface', 'long_name', 'soil layer interfaces')
+
+ soilsnowlayers = (/(i, i = maxsnl+1,nl_soil)/)
+ CALL ncio_define_dimension (filename, 'soilsnow', -maxsnl+nl_soil)
+ CALL ncio_write_serial (filename, 'soilsnow', soilsnowlayers, 'soilsnow')
+ CALL ncio_put_attr_str (filename, 'soilsnow', 'long_name', 'snow(<= 0) and soil(>0) layers')
+
+ lakelayers = (/(i, i = 1,nl_lake)/)
+ CALL ncio_define_dimension (filename, 'lake', nl_lake)
+ CALL ncio_write_serial (filename, 'lake', lakelayers, 'lake')
+ CALL ncio_put_attr_str (filename, 'lake', 'long_name', 'vertical lake layers')
+
+ vegnodes = (/(i, i = 1,nvegwcs)/)
+ CALL ncio_define_dimension (filename, 'vegnodes', nvegwcs)
+ CALL ncio_write_serial (filename, 'vegnodes', vegnodes, 'vegnodes')
+ CALL ncio_put_attr_str (filename, 'vegnodes', 'long_name', 'vegetation water potential nodes')
+
+ CALL ncio_define_dimension (filename, 'band', 2)
+ CALL ncio_write_serial (filename, 'band', (/1,2/), 'band')
+ CALL ncio_put_attr_str (filename, 'band', 'long_name', '1 = visible; 2 = near-infrared')
+
+ CALL ncio_define_dimension (filename, 'rtyp', 2)
+ CALL ncio_write_serial (filename, 'rtyp', (/1,2/), 'rtyp')
+ CALL ncio_put_attr_str (filename, 'rtyp', 'long_name', '1 = direct; 2 = diffuse')
+
+ END SUBROUTINE ncio_write_colm_dimension
+
+END MODULE MOD_NetCDFSerial
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFVector.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFVector.F90
new file mode 100644
index 0000000000..f803c3d468
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_NetCDFVector.F90
@@ -0,0 +1,2035 @@
+#include
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+#define COLM_VECTOR_MPI_IO
+#endif
+
+!----------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! High-level Subroutines to read and write variables in files with netCDF format.
+!
+! CoLM read and write netCDF files mainly in three ways:
+! 1. Serial: read and write data by a single process;
+! 2. Vector: read/write data associated with CoLM pixelsets
+! 3. Block : read blocked data by IO
+! Notice: input file is a single file.
+!
+! This MODULE CONTAINS subroutines of "2. Vector".
+!
+! Two implementations can be used,
+! 1) "MOD_NetCDFVectorBlk.F90":
+! A vector is saved in separated files, each associated with a block.
+! READ/WRITE are fast in this way and compression can be used.
+! However, there may be too many files, especially when blocks are small.
+! CHOOSE this implementation by "#undef VectorInOneFile" in include/define.h
+! 2) "MOD_NetCDFVectorOne.F90":
+! A vector is saved in one file.
+! READ/WRITE may be slow in this way.
+! CHOOSE this implementation by "#define VectorInOneFile" in include/define.h
+!
+! Created by Shupeng Zhang, May 2023
+!----------------------------------------------------------------------------------
+
+MODULE MOD_NetCDFVector
+
+
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ ! PUBLIC subroutines
+
+ INTERFACE ncio_read_vector
+ MODULE procedure ncio_read_vector_logical_1d
+ MODULE procedure ncio_read_vector_int32_1d
+ MODULE procedure ncio_read_vector_int64_1d
+ MODULE procedure ncio_read_vector_real8_1d
+ MODULE procedure ncio_read_vector_real8_2d
+ MODULE procedure ncio_read_vector_real8_3d
+ MODULE procedure ncio_read_vector_real8_4d
+ MODULE procedure ncio_read_vector_real8_5d
+ END INTERFACE ncio_read_vector
+
+ PUBLIC :: ncio_create_file_vector
+ PUBLIC :: ncio_define_dimension_vector
+
+ INTERFACE ncio_write_vector
+ MODULE procedure ncio_write_vector_logical_1d
+ MODULE procedure ncio_write_vector_int32_1d
+ MODULE procedure ncio_write_vector_int32_3d
+ MODULE procedure ncio_write_vector_int64_1d
+ MODULE procedure ncio_write_vector_real8_1d
+ MODULE procedure ncio_write_vector_real8_2d
+ MODULE procedure ncio_write_vector_real8_3d
+ MODULE procedure ncio_write_vector_real8_4d
+ MODULE procedure ncio_write_vector_real8_5d
+ END INTERFACE ncio_write_vector
+
+CONTAINS
+
+ !---------------------------------------------------------
+ SUBROUTINE get_filename_vector_block (filename, iblk, jblk, fileblock, for_write, use_srcpos)
+
+ USE MOD_Block, only: get_filename_block
+#ifdef MPAS_EMBEDDED_COLM
+ USE MOD_SPMD_Task, only: p_iam_glb
+#endif
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ integer, intent(in) :: iblk, jblk
+ character(len=*), intent(out) :: fileblock
+ logical, intent(in), optional :: for_write
+ logical, intent(inout), optional :: use_srcpos
+
+#ifdef MPAS_EMBEDDED_COLM
+ character(len=256) :: fileblock_rank
+ character(len=32) :: rank_suffix
+ integer :: idot
+ logical :: rank_local_file
+#endif
+
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+
+#ifdef MPAS_EMBEDDED_COLM
+ write(rank_suffix,'("_mpasr",I8.8)') p_iam_glb
+ idot = len_trim(fileblock)
+ DO WHILE (idot > 0)
+ IF (fileblock(idot:idot) == '.') EXIT
+ idot = idot - 1
+ ENDDO
+
+ IF (idot > 0) THEN
+ fileblock_rank = fileblock(1:idot-1) // trim(rank_suffix) // fileblock(idot:len_trim(fileblock))
+ ELSE
+ fileblock_rank = trim(fileblock) // trim(rank_suffix)
+ ENDIF
+
+ rank_local_file = .false.
+ IF (present(for_write)) rank_local_file = for_write
+ IF ((.not. rank_local_file) .and. present(use_srcpos)) THEN
+ inquire(file=trim(fileblock_rank), exist=rank_local_file)
+ ENDIF
+ IF (rank_local_file) THEN
+ fileblock = fileblock_rank
+ IF (present(use_srcpos)) use_srcpos = .false.
+ ENDIF
+#endif
+
+ END SUBROUTINE get_filename_vector_block
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_vector_stop_missing_block (filename, dataname, fileblock)
+
+ USE MOD_SPMD_Task, only: CoLM_stop
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: fileblock
+
+ write(*,*) 'Error : required vector data '//trim(dataname) &
+ //' in '//trim(filename)//' is missing from block file '//trim(fileblock)//'.'
+ CALL CoLM_stop ()
+
+ END SUBROUTINE ncio_vector_stop_missing_block
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_int32_1d ( &
+ filename, dataname, pixelset, rdata, defval)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ type(pixelset_type), intent(in) :: pixelset
+
+ integer, allocatable, intent(inout) :: rdata (:)
+ integer, intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ integer, allocatable :: sbuff(:), rbuff(:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER, &
+ MPI_IN_PLACE, 0, MPI_INTEGER, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(iset) = sbuff(pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER, & ! unused on non-root ranks
+ rbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_int64_1d ( &
+ filename, dataname, pixelset, rdata, defval)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ type(pixelset_type), intent(in) :: pixelset
+
+ integer*8, allocatable, intent(inout) :: rdata (:)
+ integer, intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ integer*8, allocatable :: sbuff(:), rbuff(:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER8, &
+ MPI_IN_PLACE, 0, MPI_INTEGER8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(iset) = sbuff(pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER8, & ! unused on non-root ranks
+ rbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER8, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_int64_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_logical_1d (filename, dataname, pixelset, rdata, &
+ defval)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ type(pixelset_type), intent(in) :: pixelset
+
+ logical, allocatable, intent(inout) :: rdata (:)
+ logical, intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ integer(1), allocatable :: sbuff(:), rbuff(:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ IF (defval) THEN
+ sbuff(:) = 1
+ ELSE
+ sbuff(:) = 0
+ ENDIF
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER1, &
+ MPI_IN_PLACE, 0, MPI_INTEGER1, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(iset) = (sbuff(pixelset%srcpos(iset)) == 1)
+ ENDDO
+ ELSE
+ rdata(istt:iend) = (sbuff == 1)
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER1, & ! unused on non-root ranks
+ rbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER1, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(istt:iend) = (rbuff == 1)
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_logical_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_real8_1d (filename, dataname, pixelset, rdata, &
+ defval)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ type(pixelset_type), intent(in) :: pixelset
+
+ real(r8), allocatable, intent(inout) :: rdata (:)
+ real(r8), intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:), rbuff(:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ MPI_IN_PLACE, 0, MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(iset) = sbuff(pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ rbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_real8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_real8_2d ( &
+ filename, dataname, ndim1, pixelset, rdata, defval)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: ndim1
+ type(pixelset_type), intent(in) :: pixelset
+
+ real(r8), allocatable, intent(inout) :: rdata (:,:)
+ real(r8), intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:), rbuff(:,:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (ndim1, pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (ndim1, pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:,:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, ndim1 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ MPI_IN_PLACE, 0, MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(:,iset) = sbuff(:,pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(:,istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (ndim1, pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1,1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ rbuff, ndim1 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(:,istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_real8_3d ( &
+ filename, dataname, ndim1, ndim2, pixelset, rdata, defval)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: ndim1, ndim2
+ type(pixelset_type), intent(in) :: pixelset
+
+ real(r8), allocatable, intent(inout) :: rdata (:,:,:)
+ real(r8), intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:,:), rbuff(:,:,:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (ndim1,ndim2, pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (ndim1,ndim2, pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:,:,:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, ndim1 * ndim2 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * ndim2 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ MPI_IN_PLACE, 0, MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(:,:,iset) = sbuff(:,:,pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(:,:,istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (ndim1,ndim2, pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1,1,1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ rbuff, ndim1 * ndim2 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(:,:,istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_real8_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_real8_4d ( &
+ filename, dataname, ndim1, ndim2, ndim3, pixelset, rdata, defval)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: ndim1, ndim2, ndim3
+ type(pixelset_type), intent(in) :: pixelset
+
+ real(r8), allocatable, intent(inout) :: rdata (:,:,:,:)
+ real(r8), intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:,:,:), rbuff(:,:,:,:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (ndim1,ndim2,ndim3, pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (ndim1,ndim2,ndim3, pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:,:,:,:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, ndim1 * ndim2 * ndim3 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * ndim2 * ndim3 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ MPI_IN_PLACE, 0, MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(:,:,:,iset) = sbuff(:,:,:,pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(:,:,:,istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (ndim1,ndim2,ndim3, pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1,1,1,1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ rbuff, ndim1 * ndim2 * ndim3 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(:,:,:,istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_real8_4d
+
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_read_vector_real8_5d ( &
+ filename, dataname, ndim1, ndim2, ndim3, ndim4, pixelset, rdata, defval)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ integer, intent(in) :: ndim1, ndim2, ndim3, ndim4
+ type(pixelset_type), intent(in) :: pixelset
+
+ real(r8), allocatable, intent(inout) :: rdata (:,:,:,:,:)
+ real(r8), intent(in), optional :: defval
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, iset
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:,:,:,:), rbuff(:,:,:,:,:)
+ logical :: any_data_exists, block_has_data, use_srcpos
+
+ IF (p_is_compute) THEN
+ IF ((pixelset%nset > 0) .and. (.not. allocated(rdata))) THEN
+ allocate (rdata (ndim1,ndim2,ndim3,ndim4, pixelset%nset))
+ ENDIF
+ ENDIF
+
+ any_data_exists = .false.
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (sbuff (ndim1,ndim2,ndim3,ndim4, pixelset%vecgs%vlen(iblk,jblk)))
+ use_srcpos = allocated(pixelset%srcpos)
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, use_srcpos = use_srcpos)
+
+ block_has_data = .false.
+ IF (ncio_var_exist(fileblock,dataname,readflag=.false.)) THEN
+ CALL ncio_read_serial (fileblock, dataname, sbuff)
+ any_data_exists = .true.
+ block_has_data = .true.
+ ELSEIF (present(defval)) THEN
+ sbuff(:,:,:,:,:) = defval
+ ELSEIF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ CALL ncio_vector_stop_missing_block (filename, dataname, fileblock)
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_scatterv ( &
+ sbuff, ndim1 * ndim2 * ndim3 * ndim4 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * ndim2 * ndim3 * ndim4 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ MPI_IN_PLACE, 0, MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ IF (use_srcpos .and. block_has_data) THEN
+ DO iset = istt, iend
+ rdata(:,:,:,:,iset) = sbuff(:,:,:,:,pixelset%srcpos(iset))
+ ENDDO
+ ELSE
+ rdata(:,:,:,:,istt:iend) = sbuff
+ ENDIF
+#endif
+
+ deallocate (sbuff)
+
+ ENDDO
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, any_data_exists, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (pixelset%nset > 0 .and. .not. any_data_exists) THEN
+ IF (ncio_vector_report_missing(.not. present(defval))) THEN
+ IF (.not. present(defval)) THEN
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found.'
+ CALL CoLM_stop ()
+ ELSE
+ write(*,*) 'Warning : restart data '//trim(dataname) &
+ //' in '//trim(filename)//' not found, default value is used.'
+ ENDIF
+ ENDIF
+ ENDIF
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (rbuff (ndim1,ndim2,ndim3,ndim4, pixelset%vecgs%vlen(iblk,jblk)))
+ ELSE
+ allocate (rbuff(1,1,1,1,1))
+ ENDIF
+
+ CALL mpi_scatterv ( &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ rbuff, ndim1 * ndim2 * ndim3 * ndim4 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rdata(:,:,:,:,istt:iend) = rbuff
+ ENDIF
+
+ IF (allocated(rbuff)) deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_read_vector_real8_5d
+
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_create_file_vector (filename, pixelset)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ type(pixelset_type), intent(in) :: pixelset
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk
+ character(len=256) :: fileblock
+
+ IF (p_is_active) THEN
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+ CALL ncio_create_file (fileblock)
+
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE ncio_create_file_vector
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_define_dimension_vector (filename, pixelset, dimname, dimlen)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ type(pixelset_type), intent(in) :: pixelset
+ character(len=*), intent(in) :: dimname
+ integer, intent(in), optional :: dimlen
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk
+ character(len=256) :: fileblock
+ logical :: fexists
+
+ IF (p_is_active) THEN
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+ inquire (file=trim(fileblock), exist=fexists)
+ IF (.not. fexists) THEN
+ CALL ncio_create_file (fileblock)
+ ENDIF
+
+ IF (present(dimlen)) THEN
+ CALL ncio_define_dimension (fileblock, trim(dimname), dimlen)
+ ELSE
+ CALL ncio_define_dimension (fileblock, trim(dimname), &
+ pixelset%vecgs%vlen(iblk,jblk))
+ ENDIF
+
+ ENDDO
+ ENDIF
+
+ END SUBROUTINE ncio_define_dimension_vector
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_int32_1d ( &
+ filename, dataname, dimname, pixelset, wdata, compress_level)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dimname
+ type(pixelset_type), intent(in) :: pixelset
+ integer, intent(in) :: wdata (:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ integer, allocatable :: sbuff(:), rbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_INTEGER, &
+ rbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname, &
+ compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(istt:iend)
+ ELSE
+ allocate (sbuff (1))
+ ENDIF
+
+ CALL mpi_gatherv ( &
+ sbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER, &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_int32_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_logical_1d ( &
+ filename, dataname, dimname, pixelset, wdata, compress_level)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dimname
+ type(pixelset_type), intent(in) :: pixelset
+ logical, intent(in) :: wdata (:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend, i
+ character(len=256) :: fileblock
+ integer(1), allocatable :: sbuff(:), rbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_INTEGER1, &
+ rbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER1, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ DO i = istt, iend
+ IF(wdata(i))THEN
+ rbuff(i-istt+1) = 1
+ ELSE
+ rbuff(i-istt+1) = 0
+ ENDIF
+ ENDDO
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname, &
+ compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ DO i = istt, iend
+ IF(wdata(i))THEN
+ sbuff(i-istt+1) = 1
+ ELSE
+ sbuff(i-istt+1) = 0
+ ENDIF
+ ENDDO
+ ELSE
+ allocate (sbuff (1))
+ ENDIF
+
+ CALL mpi_gatherv ( &
+ sbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER1, &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER1, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_logical_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_int32_3d ( &
+ filename, dataname, dim1name, ndim1, dim2name, ndim2, &
+ dim3name, pixelset, wdata, compress_level)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dim1name, dim2name, dim3name
+ type(pixelset_type), intent(in) :: pixelset
+ integer, intent(in) :: ndim1, ndim2
+ integer, intent(in) :: wdata (:,:,:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ integer, allocatable :: sbuff(:,:,:), rbuff(:,:,:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (ndim1,ndim2,pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_INTEGER, &
+ rbuff, ndim1*ndim2*pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1*ndim2*pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(:,:,istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name, compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (ndim1,ndim2, pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(:,:,istt:iend)
+ ELSE
+ allocate (sbuff (1,1,1))
+ ENDIF
+
+ CALL mpi_gatherv ( &
+ sbuff, ndim1*ndim2*pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER, &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_int32_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_int64_1d ( &
+ filename, dataname, dimname, pixelset, wdata, compress_level)
+
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dimname
+ type(pixelset_type), intent(in) :: pixelset
+ integer*8, intent(in) :: wdata (:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ integer*8, allocatable :: sbuff(:), rbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_INTEGER8, &
+ rbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_INTEGER8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname, &
+ compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(istt:iend)
+ ELSE
+ allocate (sbuff (1))
+ ENDIF
+
+ CALL mpi_gatherv ( &
+ sbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_INTEGER8, &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_int64_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_real8_1d ( &
+ filename, dataname, dimname, pixelset, wdata, compress_level)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dimname
+ type(pixelset_type), intent(in) :: pixelset
+ real(r8), intent(in) :: wdata (:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:), rbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv ( MPI_IN_PLACE, 0, MPI_REAL8, &
+ rbuff, pixelset%vecgs%vcnt(:,iblk,jblk), &
+ pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dimname, compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, dimname)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(istt:iend)
+ ELSE
+ allocate (sbuff (1))
+ ENDIF
+
+ CALL mpi_gatherv ( &
+ sbuff, pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_real8_1d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_real8_2d ( &
+ filename, dataname, dim1name, ndim1, &
+ dim2name, pixelset, wdata, compress_level)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dim1name, dim2name
+ integer, intent(in) :: ndim1
+ type(pixelset_type), intent(in) :: pixelset
+ real(r8), intent(in) :: wdata (:,:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:), rbuff(:,:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (ndim1, pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_REAL8, &
+ rbuff, ndim1 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(:,istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (ndim1,pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(:,istt:iend)
+ ELSE
+ allocate (sbuff (1,1))
+ ENDIF
+
+ CALL mpi_gatherv ( &
+ sbuff, ndim1 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_real8_2d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_real8_3d ( &
+ filename, dataname, dim1name, ndim1, dim2name, ndim2, &
+ dim3name, pixelset, wdata, compress_level)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dim1name, dim2name, dim3name
+ type(pixelset_type), intent(in) :: pixelset
+ integer, intent(in) :: ndim1, ndim2
+ real(r8), intent(in) :: wdata (:,:,:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:,:), rbuff(:,:,:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (ndim1, ndim2, pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_REAL8, &
+ rbuff, ndim1 * ndim2 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * ndim2 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(:,:,istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name, compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (ndim1,ndim2,pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(:,:,istt:iend)
+ ELSE
+ allocate (sbuff (1,1,1))
+ ENDIF
+
+ CALL mpi_gatherv ( sbuff, &
+ ndim1 * ndim2 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_real8_3d
+
+ !---------------------------------------------------------
+ SUBROUTINE ncio_write_vector_real8_4d ( &
+ filename, dataname, dim1name, ndim1, dim2name, ndim2, dim3name, ndim3, &
+ dim4name, pixelset, wdata, compress_level)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dim1name, dim2name, dim3name, dim4name
+ integer, intent(in) :: ndim1, ndim2, ndim3
+ type(pixelset_type), intent(in) :: pixelset
+ real(r8), intent(in) :: wdata (:,:,:,:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:,:,:), rbuff(:,:,:,:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (ndim1, ndim2, ndim3, pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_REAL8, &
+ rbuff, ndim1 * ndim2 * ndim3 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * ndim2 * ndim3 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(:,:,:,istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name, dim4name, compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name, dim4name)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (ndim1,ndim2,ndim3,pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(:,:,:,istt:iend)
+ ELSE
+ allocate (sbuff (1,1,1,1))
+ ENDIF
+
+ CALL mpi_gatherv ( sbuff, &
+ ndim1 * ndim2 * ndim3 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_real8_4d
+
+
+ !------------------------------------------------
+ SUBROUTINE ncio_write_vector_real8_5d ( &
+ filename, dataname, dim1name, ndim1, dim2name, ndim2, &
+ dim3name, ndim3, dim4name, ndim4, dim5name, pixelset, wdata, compress_level)
+
+ USE MOD_Precision
+ USE MOD_NetCDFSerial
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: filename
+ character(len=*), intent(in) :: dataname
+ character(len=*), intent(in) :: dim1name, dim2name, dim3name, dim4name, dim5name
+ type(pixelset_type), intent(in) :: pixelset
+ integer, intent(in) :: ndim1, ndim2, ndim3, ndim4
+ real(r8), intent(in) :: wdata (:,:,:,:,:)
+
+ integer, intent(in), optional :: compress_level
+
+ ! Local variables
+ integer :: iblkgrp, iblk, jblk, istt, iend
+ character(len=256) :: fileblock
+ real(r8), allocatable :: sbuff(:,:,:,:,:), rbuff(:,:,:,:,:)
+
+ IF (p_is_active) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ allocate (rbuff (ndim1, ndim2, ndim3, ndim4, pixelset%vecgs%vlen(iblk,jblk)))
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_REAL8, &
+ rbuff, ndim1 * ndim2 * ndim3 * ndim4 * pixelset%vecgs%vcnt(:,iblk,jblk), &
+ ndim1 * ndim2 * ndim3 * ndim4 * pixelset%vecgs%vdsp(:,iblk,jblk), MPI_REAL8, &
+ p_root, p_comm_group, p_err)
+#else
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ rbuff = wdata(:,:,:,:,istt:iend)
+#endif
+
+ CALL get_filename_vector_block (filename, iblk, jblk, fileblock, for_write = .true.)
+ IF (present(compress_level)) THEN
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name, dim4name, dim5name, compress = compress_level)
+ ELSE
+ CALL ncio_write_serial (fileblock, dataname, rbuff, &
+ dim1name, dim2name, dim3name, dim4name, dim5name)
+ ENDIF
+
+ deallocate (rbuff)
+
+ ENDDO
+
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_compute) THEN
+
+ DO iblkgrp = 1, pixelset%nblkgrp
+ iblk = pixelset%xblkgrp(iblkgrp)
+ jblk = pixelset%yblkgrp(iblkgrp)
+
+ IF (pixelset%vecgs%vlen(iblk,jblk) > 0) THEN
+ allocate (sbuff (ndim1,ndim2,ndim3,ndim4,pixelset%vecgs%vlen(iblk,jblk)))
+ istt = pixelset%vecgs%vstt(iblk,jblk)
+ iend = pixelset%vecgs%vend(iblk,jblk)
+ sbuff = wdata(:,:,:,:,istt:iend)
+ ELSE
+ allocate (sbuff (1,1,1,1,1))
+ ENDIF
+
+ CALL mpi_gatherv ( sbuff, &
+ ndim1 * ndim2 * ndim3 * ndim4 * pixelset%vecgs%vlen(iblk,jblk), MPI_REAL8, &
+ MPI_RNULL_P, MPI_INULL_P, MPI_INULL_P, MPI_REAL8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ IF (allocated(sbuff)) deallocate (sbuff)
+
+ ENDDO
+
+ ENDIF
+#endif
+
+ END SUBROUTINE ncio_write_vector_real8_5d
+ !------------------------------------------------
+
+ LOGICAL FUNCTION ncio_vector_report_missing(mandatory)
+
+ USE MOD_SPMD_Task, only: p_iam_active, p_root
+ IMPLICIT NONE
+
+ logical, intent(in) :: mandatory
+
+#ifdef MPAS_EMBEDDED_COLM
+ ncio_vector_report_missing = mandatory .or. (p_iam_active == p_root)
+#else
+ ncio_vector_report_missing = (p_iam_active == p_root)
+#endif
+
+ END FUNCTION ncio_vector_report_missing
+
+
+END MODULE MOD_NetCDFVector
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Pixel.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Pixel.F90
new file mode 100644
index 0000000000..69f6d2bf3c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Pixel.F90
@@ -0,0 +1,418 @@
+#include
+
+MODULE MOD_Pixel
+
+!------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Pixels are rasterized points defined by fine-resolution data.
+!
+! CoLM USE multiple grids to construct pixels. Grids are assimilated into pixel
+! coordinate one by one. One grid is assimilated by adding grid lines not present
+! in pixel coordinate. In other words, pixel coordinate is the union of all grids.
+!
+! Pixels are used to carry out land surface tessellation. The grids used to
+! construct pixels are associated with surface data such as land cover types, soil
+! parameters, plant function types, leaf area index and forest height.
+! By using pixels, these variables are downscaled to fine resolution.
+!
+! In pixel data type, region boundaries and each pixel boundaries are defined.
+! Subroutines to assimilate grid and map pixel to grid are defined as methods.
+!
+! Created by Shupeng Zhang, May 2023
+!------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ ! ---- data types ----
+ type :: pixel_type
+
+ real(r8) :: edges ! southern edge (degrees)
+ real(r8) :: edgen ! northern edge (degrees)
+ real(r8) :: edgew ! western edge (degrees)
+ real(r8) :: edgee ! eastern edge (degrees)
+
+ integer :: nlon, nlat
+ real(r8), allocatable :: lat_s (:)
+ real(r8), allocatable :: lat_n (:)
+ real(r8), allocatable :: lon_w (:)
+ real(r8), allocatable :: lon_e (:)
+
+ CONTAINS
+ procedure, PUBLIC :: set_edges => pixel_set_edges
+
+ procedure, PRIVATE :: assimilate_latlon => pixel_assimilate_latlon
+ procedure, PUBLIC :: assimilate_gblock => pixel_assimilate_gblock
+ procedure, PUBLIC :: assimilate_grid => pixel_assimilate_grid
+
+ procedure, PUBLIC :: map_to_grid => pixel_map_to_grid
+
+ procedure, PUBLIC :: save_to_file => pixel_save_to_file
+ procedure, PUBLIC :: load_from_file => pixel_load_from_file
+
+ final :: pixel_free_mem
+
+ END type pixel_type
+
+ ! ---- Instance ----
+ type(pixel_type) :: pixel
+
+CONTAINS
+
+ ! --------------------------------
+ SUBROUTINE pixel_set_edges (this, &
+ edges_in, edgen_in, edgew_in, edgee_in)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ class(pixel_type) :: this
+
+ real(r8), intent(in) :: edges_in, edgen_in
+ real(r8), intent(in) :: edgew_in, edgee_in
+
+ this%nlon = 1
+ this%nlat = 1
+
+ this%edges = edges_in
+ this%edgen = edgen_in
+ this%edgew = edgew_in
+ this%edgee = edgee_in
+
+ CALL normalize_longitude (this%edgew)
+ CALL normalize_longitude (this%edgee)
+
+ allocate (this%lat_s (1))
+ allocate (this%lat_n (1))
+ allocate (this%lon_w (1))
+ allocate (this%lon_e (1))
+
+ this%lat_s(1) = this%edges
+ this%lat_n(1) = this%edgen
+ this%lon_w(1) = this%edgew
+ this%lon_e(1) = this%edgee
+
+ IF (p_is_root) THEN
+ write(*,'(A)') '----- Region information -----'
+ write(*,'(A,F10.4,A,F10.4,A,F10.4,A,F10.4,A)') ' (south,north,west,east) = (', &
+ this%edges, ',', this%edgen, ',', this%edgew, ',', this%edgee, ')'
+ ENDIF
+
+ END SUBROUTINE pixel_set_edges
+
+ ! --------------------------------
+ SUBROUTINE pixel_assimilate_latlon (this, &
+ nlat, lat_s, lat_n, nlon, lon_w, lon_e)
+
+ USE MOD_Precision
+ USE MOD_Utils
+ IMPLICIT NONE
+ class(pixel_type) :: this
+
+ integer, intent(in) :: nlat
+ real(r8), intent(in) :: lat_s(nlat), lat_n(nlat)
+ integer, intent(in) :: nlon
+ real(r8), intent(in) :: lon_w(nlon), lon_e(nlon)
+
+ ! Local variables
+ real(r8) :: south, north, west, east
+
+ integer :: ny, yinc
+ integer :: iy1, iy2, ys2, yn2
+ real(r8), allocatable :: ytmp(:)
+
+ integer :: nx, nlonc
+ integer :: ix1, ix2, xw2
+ real(r8), allocatable :: xtmp(:), loncirc(:)
+
+ IF (lat_s(1) <= lat_s(nlat)) THEN
+ yinc = 1
+ south = lat_s(1)
+ north = lat_n(nlat)
+ ELSE
+ yinc = -1
+ south = lat_s(nlat)
+ north = lat_n(1)
+ ENDIF
+
+ allocate (ytmp (this%nlat+nlat+2))
+
+ ny = 0
+ DO iy1 = 1, this%nlat
+
+ ny = ny + 1
+ ytmp(ny) = this%lat_s(iy1)
+
+ IF ((this%lat_s(iy1) < north) .and. (this%lat_n(iy1) > south)) THEN
+ ys2 = find_nearest_south (this%lat_s(iy1), nlat, lat_s)
+ yn2 = find_nearest_north (this%lat_n(iy1), nlat, lat_n)
+ DO iy2 = ys2, yn2, yinc
+ IF (lat_s(iy2) > this%lat_s(iy1)) THEN
+ ny = ny + 1
+ ytmp(ny) = lat_s(iy2)
+ ENDIF
+ ENDDO
+ IF (lat_n(yn2) < this%lat_n(iy1)) THEN
+ ny = ny + 1
+ ytmp(ny) = lat_n(yn2)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ ny = ny + 1
+ ytmp(ny) = this%lat_n(this%nlat)
+
+ deallocate (this%lat_s)
+ deallocate (this%lat_n)
+
+ this%nlat = ny - 1
+ allocate (this%lat_s (this%nlat))
+ allocate (this%lat_n (this%nlat))
+
+ this%lat_s = ytmp(1:ny-1)
+ this%lat_n = ytmp(2:ny)
+
+ deallocate (ytmp)
+
+ west = lon_w(1)
+ east = lon_e(nlon)
+
+ IF (west == east) THEN
+ nlonc = nlon
+ allocate (loncirc (nlonc))
+ loncirc = lon_w
+ ELSE
+ nlonc = nlon + 1
+ allocate (loncirc (nlonc))
+ loncirc(1:nlon) = lon_w
+ loncirc(nlon+1) = east
+ ENDIF
+
+ allocate (xtmp (this%nlon+nlon+2))
+ nx = 0
+ DO ix1 = 1, this%nlon
+
+ nx = nx + 1
+ xtmp(nx) = this%lon_w(ix1)
+
+ xw2 = find_nearest_west (this%lon_w(ix1), nlonc, loncirc)
+ ix2 = mod(xw2,nlonc) + 1
+ DO WHILE (.true.)
+ IF (lon_between_floor(loncirc(ix2), this%lon_w(ix1), this%lon_e(ix1))) THEN
+ IF (loncirc(ix2) /= this%lon_w(ix1)) THEN
+ nx = nx + 1
+ xtmp(nx) = loncirc(ix2)
+ ENDIF
+
+ IF (ix2 /= xw2) THEN
+ ix2 = mod(ix2,nlonc) + 1
+ ELSE
+ EXIT
+ ENDIF
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ ENDDO
+
+ nx = nx + 1
+ xtmp(nx) = this%lon_e(this%nlon)
+
+ deallocate (this%lon_w)
+ deallocate (this%lon_e)
+
+ this%nlon = nx - 1
+ allocate (this%lon_w (this%nlon))
+ allocate (this%lon_e (this%nlon))
+
+ this%lon_w = xtmp(1:nx-1)
+ this%lon_e = xtmp(2:nx)
+
+ deallocate (xtmp)
+
+ END SUBROUTINE pixel_assimilate_latlon
+
+ ! --------------------------------
+ SUBROUTINE pixel_assimilate_gblock (this)
+
+ USE MOD_Block, only: gblock
+ IMPLICIT NONE
+ class(pixel_type) :: this
+
+ CALL this%assimilate_latlon ( &
+ gblock%nyblk, gblock%lat_s, gblock%lat_n, &
+ gblock%nxblk, gblock%lon_w, gblock%lon_e)
+
+ END SUBROUTINE pixel_assimilate_gblock
+
+ ! --------------------------------
+ SUBROUTINE pixel_assimilate_grid (this, grid)
+
+ USE MOD_Grid
+ IMPLICIT NONE
+ class(pixel_type) :: this
+
+ type(grid_type), intent(in) :: grid
+
+ CALL this%assimilate_latlon ( &
+ grid%nlat, grid%lat_s, grid%lat_n, &
+ grid%nlon, grid%lon_w, grid%lon_e)
+
+ END SUBROUTINE pixel_assimilate_grid
+
+ ! --------------------------------
+ SUBROUTINE pixel_map_to_grid (this, grd)
+
+ USE MOD_Grid
+ USE MOD_Utils
+ IMPLICIT NONE
+ class(pixel_type) :: this
+
+ type(grid_type), intent(inout) :: grd
+
+ ! Local variables
+ integer :: iy1, iy2, ix1, ix2
+ real(r8) :: south, north, west, east
+
+ IF (allocated (grd%xgrd)) deallocate (grd%xgrd)
+ IF (allocated (grd%ygrd)) deallocate (grd%ygrd)
+
+ allocate (grd%ygrd (this%nlat))
+
+ IF (grd%yinc == 1) THEN
+ south = grd%lat_s(1)
+ north = grd%lat_n(grd%nlat)
+ ELSE
+ south = grd%lat_s(grd%nlat)
+ north = grd%lat_n(1)
+ ENDIF
+
+ iy1 = 1
+ DO WHILE (.true.)
+ IF ((this%lat_s(iy1) < north) .and. (this%lat_n(iy1) > south)) THEN
+ iy2 = find_nearest_south (this%lat_s(iy1), grd%nlat, grd%lat_s)
+ DO WHILE (this%lat_n(iy1) <= grd%lat_n(iy2))
+ grd%ygrd(iy1) = iy2
+ iy1 = iy1 + 1
+ IF (iy1 > this%nlat) EXIT
+ ENDDO
+ ELSE
+ write(*,*) 'Warning: grid in latitude does not cover simulation region completely.', &
+ south, north, this%lat_s(iy1), this%lat_n(iy1)
+ grd%ygrd(iy1) = -1
+ iy1 = iy1 + 1
+ ENDIF
+ IF (iy1 > this%nlat) EXIT
+ ENDDO
+
+ allocate (grd%xgrd (this%nlon))
+
+ west = grd%lon_w(1)
+ east = grd%lon_e(grd%nlon)
+
+ ix1 = 1
+ DO WHILE (.true.)
+ IF ( lon_between_floor(this%lon_w(ix1), west, east) &
+ .or. lon_between_ceil (this%lon_e(ix1), west, east) ) THEN
+
+ ix2 = find_nearest_west (this%lon_w(ix1), grd%nlon, grd%lon_w)
+ DO WHILE (lon_between_ceil(this%lon_e(ix1), grd%lon_w(ix2), grd%lon_e(ix2)))
+ grd%xgrd(ix1) = ix2
+ ix1 = ix1 + 1
+ IF (ix1 > this%nlon) EXIT
+ ENDDO
+
+ ELSE
+ write(*,*) 'Warning: grid in longitude does not cover simulation region completely.', &
+ west, east, this%lon_w(ix1), this%lon_e(ix1)
+ grd%xgrd(ix1) = -1
+ ix1 = ix1 + 1
+ ENDIF
+ IF (ix1 > this%nlon) EXIT
+ ENDDO
+
+ END SUBROUTINE pixel_map_to_grid
+
+ ! --------------------------------
+ SUBROUTINE pixel_save_to_file (this, dir_landdata)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+ class(pixel_type) :: this
+
+ character(len=*), intent(in) :: dir_landdata
+
+ ! Local variables
+ character(len=256) :: filename
+
+ IF (p_is_root) THEN
+
+ filename = trim(dir_landdata) // '/pixel.nc'
+
+ CALL ncio_create_file (filename)
+
+ CALL ncio_write_serial (filename, 'edges', this%edges)
+ CALL ncio_write_serial (filename, 'edgen', this%edgen)
+ CALL ncio_write_serial (filename, 'edgew', this%edgew)
+ CALL ncio_write_serial (filename, 'edgee', this%edgee)
+
+ CALL ncio_define_dimension (filename, 'latitude', this%nlat)
+ CALL ncio_define_dimension (filename, 'longitude', this%nlon)
+
+ CALL ncio_write_serial (filename, 'lat_s', this%lat_s, 'latitude' )
+ CALL ncio_write_serial (filename, 'lat_n', this%lat_n, 'latitude' )
+ CALL ncio_write_serial (filename, 'lon_w', this%lon_w, 'longitude')
+ CALL ncio_write_serial (filename, 'lon_e', this%lon_e, 'longitude')
+
+ ENDIF
+
+ END SUBROUTINE pixel_save_to_file
+
+ ! --------------------------------
+ SUBROUTINE pixel_load_from_file (this, dir_landdata)
+
+ USE MOD_NetCDFSerial
+ IMPLICIT NONE
+
+ class(pixel_type) :: this
+
+ character(len=*), intent(in) :: dir_landdata
+ ! Local variables
+ character(len=256) :: filename
+
+ filename = trim(dir_landdata) // '/pixel.nc'
+
+ CALL ncio_read_bcast_serial (filename, 'edges', this%edges)
+ CALL ncio_read_bcast_serial (filename, 'edgen', this%edgen)
+ CALL ncio_read_bcast_serial (filename, 'edgew', this%edgew)
+ CALL ncio_read_bcast_serial (filename, 'edgee', this%edgee)
+
+ CALL ncio_read_bcast_serial (filename, 'lat_s', this%lat_s)
+ CALL ncio_read_bcast_serial (filename, 'lat_n', this%lat_n)
+ CALL ncio_read_bcast_serial (filename, 'lon_w', this%lon_w)
+ CALL ncio_read_bcast_serial (filename, 'lon_e', this%lon_e)
+
+ this%nlon = size(this%lon_w)
+ this%nlat = size(this%lat_s)
+
+ END SUBROUTINE pixel_load_from_file
+
+ ! --------------------------------
+ SUBROUTINE pixel_free_mem (this)
+
+ IMPLICIT NONE
+ type (pixel_type) :: this
+
+ IF (allocated(this%lat_s)) deallocate(this%lat_s)
+ IF (allocated(this%lat_n)) deallocate(this%lat_n)
+ IF (allocated(this%lon_w)) deallocate(this%lon_w)
+ IF (allocated(this%lon_e)) deallocate(this%lon_e)
+
+ END SUBROUTINE pixel_free_mem
+
+END MODULE MOD_Pixel
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Pixelset.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Pixelset.F90
new file mode 100644
index 0000000000..a5276283a4
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Pixelset.F90
@@ -0,0 +1,747 @@
+#include
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+#define COLM_VECTOR_MPI_IO
+#endif
+
+MODULE MOD_Pixelset
+
+!------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Pixelset refers to a set of pixels in CoLM.
+!
+! In CoLM, the global/regional area is divided into a hierarchical structure:
+! 1. If GRIDBASED or UNSTRUCTURED is defined, it is
+! ELEMENT >>> PATCH
+! 2. If CATCHMENT is defined, it is
+! ELEMENT >>> HRU >>> PATCH
+! If Plant FUNCTION Type classification is used, PATCH is further divided into PFT.
+! If Plant Community classification is used, PATCH is further divided into PC.
+!
+! In CoLM, the land surface is first divided into pixels, which are rasterized
+! points defined by fine-resolution data. Then ELEMENT, PATCH, HRU, PFT, PC
+! are all consists of pixels, and hence they are all pixelsets.
+!
+! The highest level pixelset in CoLM is ELEMENT, all other pixelsets are subsets
+! of ELEMENTs.
+! In a pixelset, pixels are sorted to make pixels in its subsets consecutive.
+! Thus a subset can be represented by starting pixel index and ending pixel index
+! in an ELEMENT.
+!
+! Example of hierarchical pixelsets
+! ************************************************ <-- pixels in an ELEMENT
+! |<------------------- ELEMENT ---------------->| <-- level 1
+! | subset 1 | subset 2 | subset 3 | <-- level 2
+! |s11| s12 | s21 | s22 | s23 | s31 | <-- level 3
+!
+! "Vector" is a collection of data when each pixelset in a given level is associated
+! with a value, representing its averaged physical, chemical or biological state.
+!
+! Legacy vector MPI I/O may redistribute vector data between ranks for IO.
+! MPAS-embedded CoLM keeps land vectors on MPAS-owned cell subsets.
+!
+! Created by Shupeng Zhang, May 2023
+!------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ ! ---- data types ----
+ type :: vec_gather_scatter_type
+
+ ! rank-local vector layout
+ integer, allocatable :: vlen(:,:)
+
+ ! local vector offsets
+ integer, allocatable :: vstt(:,:)
+ integer, allocatable :: vend(:,:)
+
+ ! gathered vector counts/displacements
+ integer, allocatable :: vcnt(:,:,:)
+ integer, allocatable :: vdsp(:,:,:)
+
+ CONTAINS
+ final :: vec_gather_scatter_free_mem
+
+ END type vec_gather_scatter_type
+
+ ! ---- data types ----
+ type :: pixelset_type
+
+ integer :: nset
+
+ integer*8, allocatable :: eindex(:) ! global index of element to which pixelset belongs
+
+ integer, allocatable :: ipxstt(:) ! start local index of pixel in the element
+ integer, allocatable :: ipxend(:) ! end local index of pixel in the element
+ integer, allocatable :: settyp(:) ! type of pixelset
+
+ integer, allocatable :: ielm(:) ! local index of element to which pixelset belongs
+ integer, allocatable :: srcpos(:) ! original block-vector position for packed subsets
+
+ integer :: nblkgrp ! number of blocks for this process's working group
+ integer, allocatable :: xblkgrp (:) ! block index in longitude for this process's group
+ integer, allocatable :: yblkgrp (:) ! block index in latitude for this process's group
+
+ type(vec_gather_scatter_type) :: vecgs ! for vector gathering and scattering
+
+ logical :: has_shared = .false.
+ real(r8), allocatable :: pctshared (:)
+
+ CONTAINS
+ procedure, PUBLIC :: set_vecgs => vec_gather_scatter_set
+ procedure, PUBLIC :: get_lonlat_radian => pixelset_get_lonlat_radian
+ procedure, PUBLIC :: pset_pack => pixelset_pack
+ procedure, PUBLIC :: forc_free_mem => pixelset_forc_free_mem
+ final :: pixelset_free_mem
+
+ END type pixelset_type
+
+ ! ---- data types ----
+ type :: subset_type
+
+ integer, allocatable :: substt(:)
+ integer, allocatable :: subend(:)
+ real(r8), allocatable :: subfrc(:)
+
+ CONTAINS
+ procedure, PUBLIC :: build => subset_build
+ final :: subset_free_mem
+
+ END type subset_type
+
+ ! ---- data types ----
+ type :: superset_type
+
+ integer, allocatable :: sup(:)
+
+ CONTAINS
+ procedure, PUBLIC :: build => superset_build
+ final :: superset_free_mem
+
+ END type superset_type
+
+CONTAINS
+
+ ! --------------------------------
+ SUBROUTINE pixelset_get_lonlat_radian (this, rlon, rlat)
+
+ USE MOD_Precision
+ USE MOD_Utils
+ USE MOD_Pixel
+ USE MOD_Mesh
+
+ IMPLICIT NONE
+ CLASS(pixelset_type) :: this
+
+ real(r8), intent(inout) :: rlon(:), rlat(:)
+
+ ! Local Variables
+ integer :: iset, ie, ipxstt, ipxend, npxl, ipxl
+ real(r8), allocatable :: area(:)
+
+ DO iset = 1, this%nset
+
+ ie = this%ielm(iset)
+
+ ipxstt = this%ipxstt (iset)
+ ipxend = this%ipxend (iset)
+
+ ! for 2m WMO patch, use all pixels
+ IF (ipxstt == -1) THEN
+ ipxstt = 1
+ ipxend = mesh(ie)%npxl
+ ENDIF
+
+ allocate (area (ipxstt:ipxend))
+ DO ipxl = ipxstt, ipxend
+ area(ipxl) = areaquad (&
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), &
+ pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), &
+ pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDDO
+
+ npxl = ipxend - ipxstt + 1
+ rlat(iset) = get_pixelset_rlat ( &
+ npxl, mesh(ie)%ilat(ipxstt:ipxend), area)
+ rlon(iset) = get_pixelset_rlon ( &
+ npxl, mesh(ie)%ilon(ipxstt:ipxend), area)
+
+ deallocate (area)
+
+ ENDDO
+
+ END SUBROUTINE pixelset_get_lonlat_radian
+
+ ! --------------------------------
+ FUNCTION get_pixelset_rlat (npxl, ilat, area) result(rlat)
+
+ USE MOD_Precision
+ USE MOD_Vars_Global, only: pi
+ USE MOD_Pixel
+ IMPLICIT NONE
+
+ real(r8) :: rlat
+
+ integer, intent(in) :: npxl
+ integer, intent(in) :: ilat(npxl)
+ real(r8), intent(in) :: area(npxl)
+
+ ! Local variables
+ integer :: ipxl
+
+ rlat = 0.0
+ DO ipxl = 1, npxl
+ rlat = rlat + (pixel%lat_s(ilat(ipxl)) + pixel%lat_n(ilat(ipxl))) * 0.5 * area(ipxl)
+ ENDDO
+ rlat = rlat / sum(area) * pi/180.0
+
+ END FUNCTION get_pixelset_rlat
+
+ ! --------------------------------
+ FUNCTION get_pixelset_rlon (npxl, ilon, area) result(rlon)
+
+ USE MOD_Precision
+ USE MOD_Utils
+ USE MOD_Vars_Global, only: pi
+ USE MOD_Pixel
+ IMPLICIT NONE
+
+ real(r8) :: rlon
+
+ integer, intent(in) :: npxl
+ integer, intent(in) :: ilon(npxl)
+ real(r8), intent(in) :: area(npxl)
+
+ ! Local variables
+ integer :: ipxl
+ real(r8) :: lon, lon0, area_done
+
+ lon = 0.0
+ area_done = 0.0
+ DO ipxl = 1, npxl
+
+ IF (pixel%lon_w(ilon(ipxl)) > pixel%lon_e(ilon(ipxl))) THEN
+ lon0 = (pixel%lon_w(ilon(ipxl)) + pixel%lon_e(ilon(ipxl)) + 360.0) * 0.5
+ ELSE
+ lon0 = (pixel%lon_w(ilon(ipxl)) + pixel%lon_e(ilon(ipxl))) * 0.5
+ ENDIF
+
+ CALL normalize_longitude (lon0)
+
+ IF (lon - lon0 > 180._r8) THEN
+ lon = lon * area_done + (lon0 + 360._r8) * area(ipxl)
+ ELSEIF (lon - lon0 < -180._r8) THEN
+ lon = lon * area_done + (lon0 - 360._r8) * area(ipxl)
+ ELSE
+ lon = lon * area_done + lon0 * area(ipxl)
+ ENDIF
+
+ area_done = area_done + area(ipxl)
+ lon = lon / area_done
+
+ CALL normalize_longitude(lon)
+
+ ENDDO
+
+ rlon = lon * pi/180.0
+
+ END FUNCTION get_pixelset_rlon
+
+ ! --------------------------------
+ SUBROUTINE pixelset_free_mem (this)
+
+ IMPLICIT NONE
+ type (pixelset_type) :: this
+
+ IF (allocated(this%eindex)) deallocate(this%eindex)
+ IF (allocated(this%ipxstt)) deallocate(this%ipxstt)
+ IF (allocated(this%ipxend)) deallocate(this%ipxend)
+ IF (allocated(this%settyp)) deallocate(this%settyp)
+
+ IF (allocated(this%ielm )) deallocate(this%ielm )
+ IF (allocated(this%srcpos)) deallocate(this%srcpos)
+
+ IF (allocated(this%xblkgrp)) deallocate(this%xblkgrp)
+ IF (allocated(this%yblkgrp)) deallocate(this%yblkgrp)
+
+ CALL vec_gather_scatter_free_mem(this%vecgs)
+
+ IF (allocated(this%pctshared)) deallocate(this%pctshared)
+
+ this%nset = 0
+ this%nblkgrp = 0
+ this%has_shared = .false.
+
+ END SUBROUTINE pixelset_free_mem
+
+ ! --------------------------------
+ SUBROUTINE pixelset_forc_free_mem (this)
+
+ IMPLICIT NONE
+
+ class(pixelset_type) :: this
+
+ IF (allocated(this%eindex )) deallocate(this%eindex )
+ IF (allocated(this%ipxstt )) deallocate(this%ipxstt )
+ IF (allocated(this%ipxend )) deallocate(this%ipxend )
+ IF (allocated(this%settyp )) deallocate(this%settyp )
+
+ IF (allocated(this%ielm )) deallocate(this%ielm )
+ IF (allocated(this%srcpos )) deallocate(this%srcpos )
+
+ IF (allocated(this%xblkgrp)) deallocate(this%xblkgrp)
+ IF (allocated(this%yblkgrp)) deallocate(this%yblkgrp)
+
+ CALL vec_gather_scatter_free_mem(this%vecgs)
+
+ IF (allocated(this%pctshared)) deallocate(this%pctshared)
+
+ this%nset = 0
+ this%nblkgrp = 0
+ this%has_shared = .false.
+
+ END SUBROUTINE pixelset_forc_free_mem
+
+ ! --------------------------------
+ SUBROUTINE copy_pixelset(pixel_from, pixel_to)
+
+ IMPLICIT NONE
+
+ type(pixelset_type), intent(in) :: pixel_from
+ type(pixelset_type), intent(out) :: pixel_to
+
+ pixel_to%nset = pixel_from%nset
+ pixel_to%eindex = pixel_from%eindex
+ pixel_to%ipxstt = pixel_from%ipxstt
+ pixel_to%ipxend = pixel_from%ipxend
+ pixel_to%settyp = pixel_from%settyp
+ pixel_to%ielm = pixel_from%ielm
+ IF (allocated(pixel_from%srcpos)) THEN
+ pixel_to%srcpos = pixel_from%srcpos
+ ENDIF
+
+ pixel_to%nblkgrp = pixel_from%nblkgrp
+ pixel_to%xblkgrp = pixel_from%xblkgrp
+ pixel_to%yblkgrp = pixel_from%yblkgrp
+
+ IF (pixel_from%has_shared) THEN
+ pixel_to%pctshared = pixel_from%pctshared
+ ENDIF
+
+ END SUBROUTINE
+
+ ! --------------------------------
+ SUBROUTINE vec_gather_scatter_set (this)
+
+ USE MOD_Block
+ USE MOD_SPMD_Task
+ USE MOD_Mesh
+ IMPLICIT NONE
+
+ class(pixelset_type) :: this
+
+ ! Local variables
+ integer :: iproc
+ integer :: iset, ie, xblk, yblk, iblk, jblk, scnt, iblkgrp, iblkall
+ logical, allocatable :: nonzero(:,:)
+
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (.not. allocated (this%vecgs%vlen)) THEN
+ allocate (this%vecgs%vlen (gblock%nxblk, gblock%nyblk))
+ this%vecgs%vlen(:,:) = 0
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (.not. allocated (this%vecgs%vstt)) THEN
+ allocate (this%vecgs%vstt (gblock%nxblk, gblock%nyblk))
+ allocate (this%vecgs%vend (gblock%nxblk, gblock%nyblk))
+ ENDIF
+
+ this%vecgs%vstt(:,:) = 0
+ this%vecgs%vend(:,:) = -1
+
+ ie = 1
+ xblk = 0
+ yblk = 0
+ DO iset = 1, this%nset
+ DO WHILE (this%eindex(iset) /= mesh(ie)%indx)
+ ie = ie + 1
+ ENDDO
+
+ IF ((mesh(ie)%xblk /= xblk) .or. (mesh(ie)%yblk /= yblk)) THEN
+ xblk = mesh(ie)%xblk
+ yblk = mesh(ie)%yblk
+ this%vecgs%vstt(xblk,yblk) = iset
+ ENDIF
+
+ this%vecgs%vend(xblk,yblk) = iset
+ ENDDO
+
+ this%vecgs%vlen = this%vecgs%vend - this%vecgs%vstt + 1
+
+#ifdef COLM_VECTOR_MPI_IO
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (gblock%pio(iblk,jblk) == p_address_active(p_my_group)) THEN
+
+ scnt = this%vecgs%vlen(iblk,jblk)
+ CALL mpi_gather (scnt, 1, MPI_INTEGER, &
+ MPI_INULL_P, 1, MPI_INTEGER, p_root, p_comm_group, p_err)
+
+ ENDIF
+ ENDDO
+ ENDDO
+#endif
+ ENDIF
+
+#ifdef COLM_VECTOR_MPI_IO
+ IF (p_is_active) THEN
+
+ IF (.not. allocated(this%vecgs%vcnt)) THEN
+ allocate (this%vecgs%vcnt (0:p_np_group-1,gblock%nxblk,gblock%nyblk))
+ allocate (this%vecgs%vdsp (0:p_np_group-1,gblock%nxblk,gblock%nyblk))
+ ENDIF
+
+ this%vecgs%vcnt(:,:,:) = 0
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+
+ scnt = 0
+ CALL mpi_gather (scnt, 1, MPI_INTEGER, &
+ this%vecgs%vcnt(:,iblk,jblk), 1, MPI_INTEGER, &
+ p_root, p_comm_group, p_err)
+
+ this%vecgs%vdsp(0,iblk,jblk) = 0
+ DO iproc = 1, p_np_group-1
+ this%vecgs%vdsp(iproc,iblk,jblk) = &
+ this%vecgs%vdsp(iproc-1,iblk,jblk) + this%vecgs%vcnt(iproc-1,iblk,jblk)
+ ENDDO
+
+ this%vecgs%vlen(iblk,jblk) = sum(this%vecgs%vcnt(:,iblk,jblk))
+
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDIF
+#endif
+
+ IF (p_is_active .or. p_is_compute) THEN
+ allocate (nonzero (gblock%nxblk,gblock%nyblk))
+
+ nonzero = this%vecgs%vlen > 0
+#ifdef COLM_VECTOR_MPI_IO
+ CALL mpi_allreduce (MPI_IN_PLACE, nonzero, gblock%nxblk * gblock%nyblk, &
+ MPI_LOGICAL, MPI_LOR, p_comm_group, p_err)
+#endif
+
+ this%nblkgrp = count(nonzero)
+ IF (allocated(this%xblkgrp)) deallocate(this%xblkgrp)
+ IF (allocated(this%yblkgrp)) deallocate(this%yblkgrp)
+ allocate (this%xblkgrp (this%nblkgrp))
+ allocate (this%yblkgrp (this%nblkgrp))
+
+ iblkgrp = 0
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+ IF (nonzero(iblk,jblk)) THEN
+ iblkgrp = iblkgrp + 1
+ this%xblkgrp(iblkgrp) = iblk
+ this%yblkgrp(iblkgrp) = jblk
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate(nonzero)
+ ENDIF
+
+ END SUBROUTINE vec_gather_scatter_set
+
+ ! --------------------------------
+ SUBROUTINE pixelset_pack (this, mask, nset_packed)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+ class(pixelset_type) :: this
+ logical, intent(in) :: mask(:)
+ integer, intent(out) :: nset_packed
+
+ integer*8, allocatable :: eindex_(:)
+ integer, allocatable :: ipxstt_(:)
+ integer, allocatable :: ipxend_(:)
+ integer, allocatable :: settyp_(:)
+ integer, allocatable :: ielm_ (:)
+ integer, allocatable :: srcpos_(:)
+
+ real(r8), allocatable :: pctshared_(:)
+ integer :: s, e
+
+ IF (p_is_compute) THEN
+
+ IF (this%nset > 0) THEN
+ IF (count(mask) < this%nset) THEN
+
+ allocate (eindex_(this%nset))
+ allocate (ipxstt_(this%nset))
+ allocate (ipxend_(this%nset))
+ allocate (settyp_(this%nset))
+ allocate (ielm_ (this%nset))
+ IF (allocated(this%srcpos)) allocate (srcpos_(this%nset))
+
+ eindex_ = this%eindex
+ ipxstt_ = this%ipxstt
+ ipxend_ = this%ipxend
+ settyp_ = this%settyp
+ ielm_ = this%ielm
+ IF (allocated(this%srcpos)) srcpos_ = this%srcpos
+
+ deallocate (this%eindex)
+ deallocate (this%ipxstt)
+ deallocate (this%ipxend)
+ deallocate (this%settyp)
+ deallocate (this%ielm )
+ IF (allocated(this%srcpos)) deallocate (this%srcpos)
+
+ IF (this%has_shared) THEN
+ allocate (pctshared_(this%nset))
+ pctshared_ = this%pctshared
+ deallocate (this%pctshared)
+ ENDIF
+
+ this%nset = count(mask)
+
+ IF (this%nset > 0) THEN
+
+ allocate (this%eindex(this%nset))
+ allocate (this%ipxstt(this%nset))
+ allocate (this%ipxend(this%nset))
+ allocate (this%settyp(this%nset))
+ allocate (this%ielm (this%nset))
+ IF (allocated(srcpos_)) allocate (this%srcpos(this%nset))
+
+ this%eindex = pack(eindex_, mask)
+ this%ipxstt = pack(ipxstt_, mask)
+ this%ipxend = pack(ipxend_, mask)
+ this%settyp = pack(settyp_, mask)
+ this%ielm = pack(ielm_ , mask)
+ IF (allocated(srcpos_)) this%srcpos = pack(srcpos_, mask)
+
+ IF (this%has_shared) THEN
+
+ this%pctshared = pack(pctshared_, mask)
+
+ s = 1
+ DO WHILE (s < this%nset)
+ e = s
+ DO WHILE (e < this%nset)
+ IF ((this%ielm(e+1) == this%ielm(s)) &
+ .and. (this%ipxstt(e+1) == this%ipxstt(s))) THEN
+ e = e + 1
+ ELSE
+ EXIT
+ ENDIF
+ ENDDO
+
+ IF (e > s) THEN
+ this%pctshared(s:e) = this%pctshared(s:e)/sum(this%pctshared(s:e))
+ ENDIF
+
+ s = e + 1
+ ENDDO
+
+ ENDIF
+
+ ENDIF
+
+ deallocate (eindex_)
+ deallocate (ipxstt_)
+ deallocate (ipxend_)
+ deallocate (settyp_)
+ deallocate (ielm_ )
+ IF (allocated(srcpos_)) deallocate (srcpos_)
+
+ IF (this%has_shared) THEN
+ deallocate (pctshared_)
+ ENDIF
+
+ ENDIF
+ ENDIF
+
+ ENDIF
+
+ CALL this%set_vecgs
+
+ nset_packed = this%nset
+
+ END SUBROUTINE pixelset_pack
+
+ ! --------------------------------
+ SUBROUTINE vec_gather_scatter_free_mem (this)
+
+ IMPLICIT NONE
+ type (vec_gather_scatter_type) :: this
+
+ IF (allocated(this%vlen)) deallocate (this%vlen)
+ IF (allocated(this%vstt)) deallocate (this%vstt)
+ IF (allocated(this%vend)) deallocate (this%vend)
+ IF (allocated(this%vcnt)) deallocate (this%vcnt)
+ IF (allocated(this%vdsp)) deallocate (this%vdsp)
+
+ END SUBROUTINE vec_gather_scatter_free_mem
+
+ ! --------------------------------
+ SUBROUTINE subset_build (this, superset, subset, use_frac)
+
+ USE MOD_Mesh
+ USE MOD_Pixel
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ CLASS(subset_type) :: this
+
+ type (pixelset_type), intent(in) :: superset
+ type (pixelset_type), intent(in) :: subset
+ logical, intent(in) :: use_frac
+
+ ! Local Variables
+ integer :: isuperset, isubset, ielm, ipxl, istt, iend
+
+ IF (superset%has_shared) THEN
+ write(*,*) 'Warning: superset has shared area.'
+ ENDIF
+
+ IF (allocated(this%substt)) deallocate(this%substt)
+ IF (allocated(this%subend)) deallocate(this%subend)
+
+ allocate (this%substt (superset%nset))
+ allocate (this%subend (superset%nset))
+
+ this%substt = 0
+ this%subend = -1
+
+ IF (use_frac) THEN
+ IF (allocated(this%subfrc)) deallocate(this%subfrc)
+ allocate (this%subfrc (subset%nset))
+ ENDIF
+
+ IF (superset%nset <= 0 .or. subset%nset <= 0) RETURN
+
+ isuperset = 1
+ isubset = 1
+ DO WHILE (isubset <= subset%nset)
+ IF ( (subset%eindex(isubset) == superset%eindex(isuperset)) &
+ .and. (subset%ipxstt(isubset) >= superset%ipxstt(isuperset) .or. &
+ subset%ipxstt(isubset) == -1 ) &
+ .and. (subset%ipxend(isubset) <= superset%ipxend(isuperset) .or. &
+ subset%ipxend(isubset) == -1 ) ) THEN
+
+ IF (this%substt(isuperset) == 0) THEN
+ this%substt(isuperset) = isubset
+ ENDIF
+
+ this%subend(isuperset) = isubset
+
+ isubset = isubset + 1
+ ELSE
+ isuperset = isuperset + 1
+ ENDIF
+ ENDDO
+
+ IF (use_frac) THEN
+
+ DO isubset = 1, subset%nset
+ ielm = subset%ielm(isubset)
+ this%subfrc(isubset) = 0
+ DO ipxl = subset%ipxstt(isubset), subset%ipxend(isubset)
+ IF (ipxl == -1) CYCLE
+ this%subfrc(isubset) = this%subfrc(isubset) &
+ + areaquad (&
+ pixel%lat_s(mesh(ielm)%ilat(ipxl)), &
+ pixel%lat_n(mesh(ielm)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ielm)%ilon(ipxl)), &
+ pixel%lon_e(mesh(ielm)%ilon(ipxl)) )
+ ENDDO
+ IF (subset%has_shared) THEN
+ this%subfrc(isubset) = this%subfrc(isubset) * subset%pctshared(isubset)
+ ENDIF
+ ENDDO
+
+ DO isuperset = 1, superset%nset
+ IF (this%substt(isuperset) /= 0) THEN
+ istt = this%substt(isuperset)
+ iend = this%subend(isuperset)
+ this%subfrc(istt:iend) = this%subfrc(istt:iend) / sum(this%subfrc(istt:iend))
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE subset_build
+
+ ! --------------------------------
+ SUBROUTINE subset_free_mem (this)
+
+ IMPLICIT NONE
+ type (subset_type) :: this
+
+ IF (allocated(this%substt)) deallocate (this%substt)
+ IF (allocated(this%subend)) deallocate (this%subend)
+ IF (allocated(this%subfrc)) deallocate (this%subfrc)
+
+ END SUBROUTINE subset_free_mem
+
+ ! --------------------------------
+ SUBROUTINE superset_build (this, superset, subset)
+
+ IMPLICIT NONE
+
+ CLASS(superset_type) :: this
+
+ type (pixelset_type), intent(in) :: superset
+ type (pixelset_type), intent(in) :: subset
+
+ ! Local Variables
+ integer :: isuperset, isubset
+
+ IF (subset%nset <= 0) RETURN
+
+ IF (allocated(this%sup)) deallocate(this%sup)
+
+ allocate (this%sup (subset%nset))
+
+ isuperset = 1
+ isubset = 1
+ DO WHILE (isubset <= subset%nset)
+ IF ( (subset%eindex(isubset) == superset%eindex(isuperset)) &
+ .and. (subset%ipxstt(isubset) >= superset%ipxstt(isuperset)) &
+ .and. (subset%ipxend(isubset) <= superset%ipxend(isuperset))) THEN
+
+ this%sup(isubset) = isuperset
+
+ isubset = isubset + 1
+ ELSE
+ isuperset = isuperset + 1
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE superset_build
+
+ ! --------------------------------
+ SUBROUTINE superset_free_mem (this)
+
+ IMPLICIT NONE
+ type (superset_type) :: this
+
+ IF (allocated(this%sup)) deallocate (this%sup)
+
+ END SUBROUTINE superset_free_mem
+
+END MODULE MOD_Pixelset
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_PixelsetShared.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_PixelsetShared.F90
new file mode 100644
index 0000000000..61f5ab7bdf
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_PixelsetShared.F90
@@ -0,0 +1,213 @@
+#include
+
+MODULE MOD_PixelsetShared
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Shared pixelset refer to two or more pixelsets sharing the same geographic area.
+!
+! For example, for patch of crops, multiple crops can be planted on a piece of land.
+! When planting these crops, different irrigation schemes may be used. Thus the water
+! and energy processes have difference in crops and should be modeled independently.
+! By using shared pixelset, crop patch is splitted to two or more shared patches.
+! Each shared patch is assigned with a percentage of area and has its own states.
+!
+! Example of shared pixelsets
+! |<------------------- ELEMENT ------------------>| <-- level 1
+! | subset 1 | subset 2 | subset 3 | <-- level 2
+! | subset 2 shared 1 50% |
+! | subset 2 shared 2 20% | <-- subset 2 shares
+! | subset 2 shared 3 30% |
+!
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+CONTAINS
+
+ SUBROUTINE pixelsetshared_build (pixelset, gshared, datashared, nmaxshared, typfilter, &
+ fracout, sharedclass, fracin)
+
+ USE MOD_SPMD_Task
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Pixel
+ USE MOD_Pixelset
+ USE MOD_Mesh
+ USE MOD_Utils
+ USE MOD_AggregationRequestData
+ IMPLICIT NONE
+
+ type(pixelset_type), intent(inout) :: pixelset
+ type(grid_type), intent(in) :: gshared
+ type(block_data_real8_3d), intent(in) :: datashared
+ integer, intent(in) :: nmaxshared
+ integer, intent(in) :: typfilter(:)
+
+ real(r8), intent(out), allocatable :: fracout(:)
+ integer, intent(out), allocatable :: sharedclass(:)
+ real(r8), intent(in), optional :: fracin (:)
+
+ ! Local Variables
+ real(r8), allocatable :: pctshared(:,:)
+ real(r8), allocatable :: datashared1d(:,:), areapixel(:), rbuff(:,:)
+ integer :: nsetshared, ipset, jpset
+ integer :: ipxl, ie, ipxstt, ipxend, ishared
+ integer*8,allocatable :: eindex1(:)
+ integer, allocatable :: ielm1(:), ipxstt1(:), ipxend1(:), settyp1(:)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+ CALL aggregation_data_daemon (gshared, data_r8_3d_in1 = datashared, n1_r8_3d_in1 = nmaxshared)
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+
+ nsetshared = 0
+
+ allocate (pctshared(nmaxshared,pixelset%nset))
+
+ DO ipset = 1, pixelset%nset
+ IF (any(typfilter(:) == pixelset%settyp(ipset))) THEN
+
+ ie = pixelset%ielm (ipset)
+ ipxstt = pixelset%ipxstt(ipset)
+ ipxend = pixelset%ipxend(ipset)
+
+ allocate (datashared1d (nmaxshared, ipxstt:ipxend))
+
+ CALL aggregation_request_data (pixelset, ipset, gshared, zip = .false., &
+ data_r8_3d_in1 = datashared, data_r8_3d_out1 = rbuff, n1_r8_3d_in1 = nmaxshared)
+
+ datashared1d = rbuff
+
+ allocate (areapixel(ipxstt:ipxend))
+ DO ipxl = ipxstt, ipxend
+ areapixel(ipxl) = areaquad (&
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDDO
+
+ DO ishared = 1, nmaxshared
+ pctshared(ishared,ipset) = sum(datashared1d(ishared,:) * areapixel)
+ ENDDO
+
+ IF (any(pctshared(:,ipset) > 0.)) THEN
+ nsetshared = nsetshared + count(pctshared(:,ipset) > 0.)
+ pctshared(:,ipset) = pctshared(:,ipset) / sum(pctshared(:,ipset))
+ ENDIF
+
+ deallocate (rbuff )
+ deallocate (areapixel )
+ deallocate (datashared1d)
+
+ ELSE
+ nsetshared = nsetshared + 1
+ ENDIF
+
+ ENDDO
+
+#ifdef USEMPI
+ CALL aggregation_compute_done ()
+#endif
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (pixelset%nset > 0) THEN
+
+ allocate (eindex1(pixelset%nset))
+ allocate (ipxstt1(pixelset%nset))
+ allocate (ipxend1(pixelset%nset))
+ allocate (settyp1(pixelset%nset))
+ allocate (ielm1 (pixelset%nset))
+
+ eindex1 = pixelset%eindex
+ ipxstt1 = pixelset%ipxstt
+ ipxend1 = pixelset%ipxend
+ settyp1 = pixelset%settyp
+ ielm1 = pixelset%ielm
+
+ deallocate (pixelset%eindex)
+ deallocate (pixelset%ipxstt)
+ deallocate (pixelset%ipxend)
+ deallocate (pixelset%settyp)
+ deallocate (pixelset%ielm )
+
+ allocate (pixelset%eindex(nsetshared))
+ allocate (pixelset%ipxstt(nsetshared))
+ allocate (pixelset%ipxend(nsetshared))
+ allocate (pixelset%settyp(nsetshared))
+ allocate (pixelset%ielm (nsetshared))
+
+ allocate (fracout (nsetshared))
+ allocate (sharedclass(nsetshared))
+
+ fracout(:) = 1.0
+
+ jpset = 0
+ DO ipset = 1, pixelset%nset
+ IF (any(typfilter(:) == settyp1(ipset))) THEN
+ IF (any(pctshared(:,ipset) > 0.)) THEN
+ DO ishared = 1, nmaxshared
+ IF (pctshared(ishared,ipset) > 0.) THEN
+ jpset = jpset + 1
+ pixelset%eindex(jpset) = eindex1(ipset)
+ pixelset%ipxstt(jpset) = ipxstt1(ipset)
+ pixelset%ipxend(jpset) = ipxend1(ipset)
+ pixelset%settyp(jpset) = settyp1(ipset)
+ pixelset%ielm (jpset) = ielm1 (ipset)
+
+ IF (present(fracin)) THEN
+ fracout(jpset) = fracin(ipset) * pctshared(ishared,ipset)
+ ELSE
+ fracout(jpset) = pctshared(ishared,ipset)
+ ENDIF
+
+ sharedclass(jpset) = ishared
+ ENDIF
+ ENDDO
+ ENDIF
+ ELSE
+ jpset = jpset + 1
+ pixelset%eindex(jpset) = eindex1(ipset)
+ pixelset%ipxstt(jpset) = ipxstt1(ipset)
+ pixelset%ipxend(jpset) = ipxend1(ipset)
+ pixelset%settyp(jpset) = settyp1(ipset)
+ pixelset%ielm (jpset) = ielm1 (ipset)
+
+ IF (present(fracin)) THEN
+ fracout(jpset) = fracin(ipset)
+ ELSE
+ fracout(jpset) = 1.
+ ENDIF
+
+ sharedclass(jpset) = 0 ! no meaning
+ ENDIF
+ ENDDO
+
+ pixelset%nset = nsetshared
+
+ deallocate (eindex1)
+ deallocate (ipxstt1)
+ deallocate (ipxend1)
+ deallocate (settyp1)
+ deallocate (ielm1 )
+ deallocate (pctshared)
+
+ ENDIF
+
+ ENDIF
+
+ CALL pixelset%set_vecgs
+
+ END SUBROUTINE pixelsetshared_build
+
+END MODULE MOD_PixelsetShared
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Precision.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Precision.F90
new file mode 100644
index 0000000000..d3c259200b
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Precision.F90
@@ -0,0 +1,12 @@
+MODULE MOD_Precision
+!-------------------------------------------------------------------------------
+! !Purpose:
+! Define the precision to use for floating point and integer operations
+! throughout the model.
+!-------------------------------------------------------------------------------
+ integer, parameter :: r4 = selected_real_kind(5)
+ integer, parameter :: r8 = selected_real_kind(12)
+ integer, parameter :: r16 = selected_real_kind(24) !16 byte REAL
+ integer, parameter :: i8 = selected_int_kind(13)
+
+END MODULE MOD_Precision
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_RangeCheck.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_RangeCheck.F90
new file mode 100644
index 0000000000..e66c2dc779
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_RangeCheck.F90
@@ -0,0 +1,886 @@
+#include
+
+MODULE MOD_RangeCheck
+
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Subroutines show the range of values in block data or vector data.
+!
+! Notice that:
+! 1. "check_block_data" can only be called by IO processes.
+! 2. "check_vector_data" can only be called by compute ranks.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+#ifdef RangeCheck
+ USE MOD_UserDefFun, only: isnan_ud
+ IMPLICIT NONE
+
+ INTERFACE check_block_data
+ MODULE procedure check_block_data_real8_2d
+ END INTERFACE check_block_data
+
+ INTERFACE check_vector_data
+ MODULE procedure check_vector_data_real8_1d
+ MODULE procedure check_vector_data_real8_2d
+ MODULE procedure check_vector_data_real8_3d
+ MODULE procedure check_vector_data_real8_4d
+ MODULE procedure check_vector_data_real8_5d
+ MODULE procedure check_vector_data_int32_1d
+ END INTERFACE check_vector_data
+
+CONTAINS
+
+ ! ----------
+ SUBROUTINE check_block_data_real8_2d (varname, gdata, spv_in, limits)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_DataType
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ type(block_data_real8_2d), intent(in) :: gdata
+ real(r8), intent(in), optional :: spv_in
+ real(r8), intent(in), optional :: limits(2)
+
+ ! Local variables
+ real(r8) :: gmin, gmax, spv
+ real(r8), allocatable :: gmin_all(:), gmax_all(:)
+ logical, allocatable :: msk2(:,:)
+ integer :: iblkme, ib, jb, ix, iy
+ logical :: has_nan
+ character(len=256) :: wfmt, exception, str_print
+
+ IF (p_is_active) THEN
+
+ IF (present(spv_in)) THEN
+ spv = spv_in
+ ELSE
+ spv = spval
+ ENDIF
+
+ gmin = spv
+ gmax = spv
+
+ has_nan = .false.
+ DO iblkme = 1, gblock%nblkme
+ ib = gblock%xblkme(iblkme)
+ jb = gblock%yblkme(iblkme)
+
+ IF (.not. allocated(gdata%blk(ib,jb)%val)) CYCLE
+
+ allocate(msk2 (size(gdata%blk(ib,jb)%val,1), size(gdata%blk(ib,jb)%val,2)))
+ msk2 = gdata%blk(ib,jb)%val /= spv
+
+ IF (any(msk2)) THEN
+ IF (gmin == spv) THEN
+ gmin = minval(gdata%blk(ib,jb)%val, mask = msk2)
+ ELSE
+ gmin = min(gmin, minval(gdata%blk(ib,jb)%val, mask = msk2))
+ ENDIF
+
+ IF (gmax == spv) THEN
+ gmax = maxval(gdata%blk(ib,jb)%val, mask = msk2)
+ ELSE
+ gmax = max(gmax, maxval(gdata%blk(ib,jb)%val, mask = msk2))
+ ENDIF
+ ENDIF
+
+ DO iy = 1, size(gdata%blk(ib,jb)%val,2)
+ DO ix = 1, size(gdata%blk(ib,jb)%val,1)
+ has_nan = has_nan .or. isnan_ud(gdata%blk(ib,jb)%val(ix,iy))
+ ENDDO
+ ENDDO
+
+ deallocate(msk2)
+
+ ENDDO
+
+#ifdef USEMPI
+ IF (p_iam_active == p_root) THEN
+ allocate (gmin_all (0:p_np_active-1))
+ allocate (gmax_all (0:p_np_active-1))
+ CALL mpi_gather (gmin, 1, MPI_REAL8, gmin_all, 1, MPI_REAL8, p_root, p_comm_active, p_err)
+ CALL mpi_gather (gmax, 1, MPI_REAL8, gmax_all, 1, MPI_REAL8, p_root, p_comm_active, p_err)
+ ELSE
+ CALL mpi_gather (gmin, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_active, p_err)
+ CALL mpi_gather (gmax, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_active, p_err)
+ ENDIF
+
+ CALL mpi_allreduce (MPI_IN_PLACE, has_nan, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+
+ IF (p_iam_active == p_root) THEN
+ IF (any(gmin_all /= spv)) THEN
+ gmin = minval(gmin_all, mask = (gmin_all /= spv))
+ ELSE
+ gmin = spv
+ ENDIF
+
+ IF (any(gmax_all /= spv)) THEN
+ gmax = maxval(gmax_all, mask = (gmax_all /= spv))
+ ELSE
+ gmax = spv
+ ENDIF
+
+ deallocate (gmin_all)
+ deallocate (gmax_all)
+ ENDIF
+#endif
+ IF (p_iam_active == p_root) THEN
+
+ exception = ''
+
+ IF (has_nan) THEN
+ exception = trim(exception) // ' with NAN'
+ ENDIF
+
+ IF (present(limits)) THEN
+ IF ((gmin < limits(1)) .or. (gmax > limits(2))) THEN
+ exception = trim(exception) // ' Out of Range!'
+ ENDIF
+ ENDIF
+
+ wfmt = "('Check block data:', A25, ' is in (', e20.10, ',', e20.10, ')', A)"
+ write(str_print,wfmt) varname, gmin, gmax, trim(exception)
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_send (exception, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (str_print, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_recv (exception, 256, MPI_CHARACTER, p_address_active(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (str_print, 256, MPI_CHARACTER, p_address_active(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+
+ write(*,'(A)') trim(str_print)
+
+#if (defined CoLMDEBUG)
+ IF (len_trim(exception) > 0) THEN
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE check_block_data_real8_2d
+
+
+ ! ----------
+ SUBROUTINE check_vector_data_real8_1d (varname, vdata, spv_in, limits)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ real(r8), allocatable, intent(in) :: vdata(:)
+
+ real(r8), intent(in), optional :: spv_in
+ real(r8), intent(in), optional :: limits(2)
+
+ ! Local variables
+ real(r8) :: vmin, vmax, spv
+ real(r8), allocatable :: vmin_all(:), vmax_all(:)
+ integer :: i
+ logical :: has_nan
+ character(len=256) :: wfmt, exception, str_print
+
+ IF (p_is_compute) THEN
+
+ IF (present(spv_in)) THEN
+ spv = spv_in
+ ELSE
+ spv = spval
+ ENDIF
+
+ IF (allocated(vdata)) THEN
+ IF (any(vdata /= spv)) THEN
+ vmin = minval(vdata, mask = vdata /= spv)
+ vmax = maxval(vdata, mask = vdata /= spv)
+ ELSE
+ vmin = spv
+ vmax = spv
+ ENDIF
+
+ has_nan = .false.
+ DO i = lbound(vdata,1), ubound(vdata,1)
+ has_nan = has_nan .or. isnan_ud(vdata(i))
+ ENDDO
+ ELSE
+ vmin = spv; vmax = spv
+ has_nan = .false.
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (vmin_all (0:p_np_compute-1))
+ allocate (vmax_all (0:p_np_compute-1))
+ CALL mpi_gather (vmin, 1, MPI_REAL8, vmin_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, vmax_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ELSE
+ CALL mpi_gather (vmin, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ENDIF
+
+ CALL mpi_allreduce (MPI_IN_PLACE, has_nan, 1, MPI_LOGICAL, MPI_LOR, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+ IF (any(vmin_all /= spv)) THEN
+ vmin = minval(vmin_all, mask = (vmin_all /= spv))
+ ELSE
+ vmin = spv
+ ENDIF
+
+ IF (any(vmax_all /= spv)) THEN
+ vmax = maxval(vmax_all, mask = (vmax_all /= spv))
+ ELSE
+ vmax = spv
+ ENDIF
+
+ deallocate (vmin_all)
+ deallocate (vmax_all)
+ ENDIF
+#endif
+
+ IF (p_iam_compute == p_root) THEN
+
+ exception = ''
+
+ IF (has_nan) THEN
+ exception = trim(exception) // ' with NAN'
+ ENDIF
+
+ IF (present(limits)) THEN
+ IF ((vmin < limits(1)) .or. (vmax > limits(2))) THEN
+ exception = trim(exception) // ' Out of Range!'
+ ENDIF
+ ENDIF
+
+ wfmt = "('Check vector data:', A25, ' is in (', e20.10, ',', e20.10, ')', A)"
+ write(str_print,wfmt) varname, vmin, vmax, trim(exception)
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_send (exception, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (str_print, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_recv (exception, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (str_print, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+
+ write(*,'(A)') trim(str_print)
+
+#if (defined CoLMDEBUG)
+ IF (len_trim(exception) > 0) THEN
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE check_vector_data_real8_1d
+
+ ! ----------
+ SUBROUTINE check_vector_data_real8_2d (varname, vdata, spv_in, limits)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ real(r8), allocatable, intent(in) :: vdata(:,:)
+
+ real(r8), intent(in), optional :: spv_in
+ real(r8), intent(in), optional :: limits(2)
+
+ ! Local variables
+ real(r8) :: vmin, vmax, spv
+ real(r8), allocatable :: vmin_all(:), vmax_all(:)
+ integer :: i, j
+ logical :: has_nan
+ character(len=256) :: wfmt, exception, str_print
+
+ IF (p_is_compute) THEN
+
+ IF (present(spv_in)) THEN
+ spv = spv_in
+ ELSE
+ spv = spval
+ ENDIF
+
+ IF (allocated(vdata)) THEN
+ IF (any(vdata /= spv)) THEN
+ vmin = minval(vdata, mask = vdata /= spv)
+ vmax = maxval(vdata, mask = vdata /= spv)
+ ELSE
+ vmin = spv
+ vmax = spv
+ ENDIF
+
+ has_nan = .false.
+ DO j = lbound(vdata,2), ubound(vdata,2)
+ DO i = lbound(vdata,1), ubound(vdata,1)
+ has_nan = has_nan .or. isnan_ud(vdata(i,j))
+ ENDDO
+ ENDDO
+ ELSE
+ vmin = spv; vmax = spv
+ has_nan = .false.
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (vmin_all (0:p_np_compute-1))
+ allocate (vmax_all (0:p_np_compute-1))
+ CALL mpi_gather (vmin, 1, MPI_REAL8, vmin_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, vmax_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ELSE
+ CALL mpi_gather (vmin, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ENDIF
+
+ CALL mpi_allreduce (MPI_IN_PLACE, has_nan, 1, MPI_LOGICAL, MPI_LOR, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+ IF (any(vmin_all /= spv)) THEN
+ vmin = minval(vmin_all, mask = (vmin_all /= spv))
+ ELSE
+ vmin = spv
+ ENDIF
+
+ IF (any(vmax_all /= spv)) THEN
+ vmax = maxval(vmax_all, mask = (vmax_all /= spv))
+ ELSE
+ vmax = spv
+ ENDIF
+
+ deallocate (vmin_all)
+ deallocate (vmax_all)
+ ENDIF
+#endif
+
+ IF (p_iam_compute == p_root) THEN
+
+ exception = ''
+
+ IF (has_nan) THEN
+ exception = trim(exception) // ' with NAN'
+ ENDIF
+
+ IF (present(limits)) THEN
+ IF ((vmin < limits(1)) .or. (vmax > limits(2))) THEN
+ exception = trim(exception) // ' Out of Range!'
+ ENDIF
+ ENDIF
+
+ wfmt = "('Check vector data:', A25, ' is in (', e20.10, ',', e20.10, ')', A)"
+ write(str_print,wfmt) varname, vmin, vmax, trim(exception)
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_send (exception, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (str_print, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_recv (exception, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (str_print, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+
+ write(*,'(A)') trim(str_print)
+
+#if (defined CoLMDEBUG)
+ IF (len_trim(exception) > 0) THEN
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE check_vector_data_real8_2d
+
+ ! ----------
+ SUBROUTINE check_vector_data_real8_3d (varname, vdata, spv_in, limits)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ real(r8), allocatable, intent(in) :: vdata(:,:,:)
+
+ real(r8), intent(in), optional :: spv_in
+ real(r8), intent(in), optional :: limits(2)
+
+ ! Local variables
+ real(r8) :: vmin, vmax, spv
+ real(r8), allocatable :: vmin_all(:), vmax_all(:)
+ integer :: i, j, k
+ logical :: has_nan
+ character(len=256) :: wfmt, exception, str_print
+
+ IF (p_is_compute) THEN
+
+ IF (present(spv_in)) THEN
+ spv = spv_in
+ ELSE
+ spv = spval
+ ENDIF
+
+ IF (allocated(vdata)) THEN
+ IF (any(vdata /= spv)) THEN
+ vmin = minval(vdata, mask = vdata /= spv)
+ vmax = maxval(vdata, mask = vdata /= spv)
+ ELSE
+ vmin = spv
+ vmax = spv
+ ENDIF
+
+ has_nan = .false.
+ DO k = lbound(vdata,3), ubound(vdata,3)
+ DO j = lbound(vdata,2), ubound(vdata,2)
+ DO i = lbound(vdata,1), ubound(vdata,1)
+ has_nan = has_nan .or. isnan_ud(vdata(i,j,k))
+ ENDDO
+ ENDDO
+ ENDDO
+ ELSE
+ vmin = spv; vmax = spv
+ has_nan = .false.
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (vmin_all (0:p_np_compute-1))
+ allocate (vmax_all (0:p_np_compute-1))
+ CALL mpi_gather (vmin, 1, MPI_REAL8, vmin_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, vmax_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ELSE
+ CALL mpi_gather (vmin, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ENDIF
+
+
+ CALL mpi_allreduce (MPI_IN_PLACE, has_nan, 1, MPI_LOGICAL, MPI_LOR, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+ IF (any(vmin_all /= spv)) THEN
+ vmin = minval(vmin_all, mask = (vmin_all /= spv))
+ ELSE
+ vmin = spv
+ ENDIF
+
+ IF (any(vmax_all /= spv)) THEN
+ vmax = maxval(vmax_all, mask = (vmax_all /= spv))
+ ELSE
+ vmax = spv
+ ENDIF
+
+ deallocate (vmin_all)
+ deallocate (vmax_all)
+ ENDIF
+#endif
+
+ IF (p_iam_compute == p_root) THEN
+
+ exception = ''
+
+ IF (has_nan) THEN
+ exception = trim(exception) // ' with NAN'
+ ENDIF
+
+ IF (present(limits)) THEN
+ IF ((vmin < limits(1)) .or. (vmax > limits(2))) THEN
+ exception = trim(exception) // ' Out of Range!'
+ ENDIF
+ ENDIF
+
+ wfmt = "('Check vector data:', A25, ' is in (', e20.10, ',', e20.10, ')', A)"
+ write(str_print,wfmt) varname, vmin, vmax, trim(exception)
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_send (exception, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (str_print, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_recv (exception, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (str_print, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+
+ write(*,'(A)') trim(str_print)
+
+#if (defined CoLMDEBUG)
+ IF (len_trim(exception) > 0) THEN
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE check_vector_data_real8_3d
+
+ ! ----------
+ SUBROUTINE check_vector_data_real8_4d (varname, vdata, spv_in, limits)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ real(r8), allocatable, intent(in) :: vdata(:,:,:,:)
+
+ real(r8), intent(in), optional :: spv_in
+ real(r8), intent(in), optional :: limits(2)
+
+ ! Local variables
+ real(r8) :: vmin, vmax, spv
+ real(r8), allocatable :: vmin_all(:), vmax_all(:)
+ integer :: i, j, k, l
+ logical :: has_nan
+ character(len=256) :: wfmt, exception, str_print
+
+ IF (p_is_compute) THEN
+
+ IF (present(spv_in)) THEN
+ spv = spv_in
+ ELSE
+ spv = spval
+ ENDIF
+
+ IF (allocated(vdata)) THEN
+ IF (any(vdata /= spv)) THEN
+ vmin = minval(vdata, mask = vdata /= spv)
+ vmax = maxval(vdata, mask = vdata /= spv)
+ ELSE
+ vmin = spv
+ vmax = spv
+ ENDIF
+
+ has_nan = .false.
+ DO l = lbound(vdata,4), ubound(vdata,4)
+ DO k = lbound(vdata,3), ubound(vdata,3)
+ DO j = lbound(vdata,2), ubound(vdata,2)
+ DO i = lbound(vdata,1), ubound(vdata,1)
+ has_nan = has_nan .or. isnan_ud(vdata(i,j,k,l))
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDDO
+ ELSE
+ vmin = spv; vmax = spv
+ has_nan = .false.
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (vmin_all (0:p_np_compute-1))
+ allocate (vmax_all (0:p_np_compute-1))
+ CALL mpi_gather (vmin, 1, MPI_REAL8, vmin_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, vmax_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ELSE
+ CALL mpi_gather (vmin, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ENDIF
+
+
+ CALL mpi_allreduce (MPI_IN_PLACE, has_nan, 1, MPI_LOGICAL, MPI_LOR, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+ IF (any(vmin_all /= spv)) THEN
+ vmin = minval(vmin_all, mask = (vmin_all /= spv))
+ ELSE
+ vmin = spv
+ ENDIF
+
+ IF (any(vmax_all /= spv)) THEN
+ vmax = maxval(vmax_all, mask = (vmax_all /= spv))
+ ELSE
+ vmax = spv
+ ENDIF
+
+ deallocate (vmin_all)
+ deallocate (vmax_all)
+ ENDIF
+#endif
+
+ IF (p_iam_compute == p_root) THEN
+
+ exception = ''
+
+ IF (has_nan) THEN
+ exception = trim(exception) // ' with NAN'
+ ENDIF
+
+ IF (present(limits)) THEN
+ IF ((vmin < limits(1)) .or. (vmax > limits(2))) THEN
+ exception = trim(exception) // ' Out of Range!'
+ ENDIF
+ ENDIF
+
+ wfmt = "('Check vector data:', A25, ' is in (', e20.10, ',', e20.10, ')', A)"
+ write(str_print,wfmt) varname, vmin, vmax, trim(exception)
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_send (exception, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+ CALL mpi_send (str_print, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_recv (exception, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (str_print, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+
+ write(*,'(A)') trim(str_print)
+
+#if (defined CoLMDEBUG)
+ IF (len_trim(exception) > 0) THEN
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+ ENDIF
+
+ END SUBROUTINE check_vector_data_real8_4d
+
+
+ ! ----------
+ SUBROUTINE check_vector_data_real8_5d (varname, vdata, spv_in, limits)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only : spval
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ real(r8), intent(in) :: vdata(:,:,:,:,:)
+ real(r8), intent(in), optional :: spv_in
+ real(r8), intent(in), optional :: limits(2)
+
+ ! Local variables
+ real(r8) :: vmin, vmax, spv
+ real(r8), allocatable :: vmin_all(:), vmax_all(:)
+ integer :: i, j, k, l, m
+ logical :: has_nan
+ character(len=256) :: wfmt, ss, info
+
+ IF (p_is_compute) THEN
+
+ IF (present(spv_in)) THEN
+ spv = spv_in
+ ELSE
+ spv = spval
+ ENDIF
+
+ IF (any(vdata /= spv)) THEN
+ vmin = minval(vdata, mask = vdata /= spv)
+ vmax = maxval(vdata, mask = vdata /= spv)
+ ELSE
+ vmin = spv
+ vmax = spv
+ ENDIF
+
+ has_nan = .false.
+ DO m = 1, size(vdata,5)
+ DO l = 1, size(vdata,4)
+ DO k = 1, size(vdata,3)
+ DO j = 1, size(vdata,2)
+ DO i = 1, size(vdata,1)
+ has_nan = has_nan .or. isnan_ud(vdata(i,j,k,l,m))
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (vmin_all (0:p_np_compute-1))
+ allocate (vmax_all (0:p_np_compute-1))
+ CALL mpi_gather (vmin, 1, MPI_REAL8, vmin_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, vmax_all, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ELSE
+ CALL mpi_gather (vmin, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_REAL8, MPI_RNULL_P, 1, MPI_REAL8, p_root, p_comm_compute, p_err)
+ ENDIF
+
+
+ CALL mpi_allreduce (MPI_IN_PLACE, has_nan, 1, MPI_LOGICAL, MPI_LOR, p_comm_compute, p_err)
+
+ IF (p_iam_compute == p_root) THEN
+ IF (any(vmin_all /= spv)) THEN
+ vmin = minval(vmin_all, mask = (vmin_all /= spv))
+ ELSE
+ vmin = spv
+ ENDIF
+
+ IF (any(vmax_all /= spv)) THEN
+ vmax = maxval(vmax_all, mask = (vmax_all /= spv))
+ ELSE
+ vmax = spv
+ ENDIF
+
+ deallocate (vmin_all)
+ deallocate (vmax_all)
+ ENDIF
+#endif
+
+ IF (p_iam_compute == p_root) THEN
+
+ info = ''
+
+ IF (has_nan) THEN
+ info = trim(info) // ' with NAN'
+ ENDIF
+
+ IF (present(limits)) THEN
+ IF ((vmin < limits(1)) .or. (vmax > limits(2))) THEN
+ info = trim(info) // ' Out of Range!'
+ ENDIF
+ ENDIF
+
+ wfmt = "('Check vector data:', A25, ' is in (', e20.10, ',', e20.10, ')', A)"
+ write(*,wfmt) varname, vmin, vmax, info
+
+#if(defined CoLMDEBUG)
+ IF (len_trim(info) > 0) THEN
+ CALL CoLM_stop ()
+ ENDIF
+#endif
+
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE check_vector_data_real8_5d
+
+
+ ! ----------
+ SUBROUTINE check_vector_data_int32_1d (varname, vdata, spv_in)
+
+ USE MOD_Precision
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: varname
+ integer, allocatable, intent(in) :: vdata(:)
+
+ integer, intent(in), optional :: spv_in
+
+ ! Local variables
+ integer :: vmin, vmax
+ logical :: isnull
+ logical, allocatable :: null_all(:)
+ integer, allocatable :: vmin_all(:), vmax_all(:)
+ character(len=256) :: wfmt, str_print
+
+ IF (p_is_compute) THEN
+
+ isnull = .not. allocated(vdata)
+
+ IF (.not. isnull) THEN
+ IF (present(spv_in)) THEN
+ IF (any(vdata /= spv_in)) THEN
+ vmin = minval(vdata, mask = vdata /= spv_in)
+ vmax = maxval(vdata, mask = vdata /= spv_in)
+ ELSE
+ vmin = spv_in
+ vmax = spv_in
+ ENDIF
+ ELSE
+ vmin = minval(vdata)
+ vmax = maxval(vdata)
+ ENDIF
+ ENDIF
+
+#ifdef USEMPI
+ IF (p_iam_compute == p_root) THEN
+ allocate (null_all (0:p_np_compute-1))
+ allocate (vmin_all (0:p_np_compute-1))
+ allocate (vmax_all (0:p_np_compute-1))
+ CALL mpi_gather (isnull, 1, MPI_LOGICAL, null_all, 1, MPI_LOGICAL, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmin, 1, MPI_INTEGER, vmin_all, 1, MPI_INTEGER, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_INTEGER, vmax_all, 1, MPI_INTEGER, p_root, p_comm_compute, p_err)
+ ELSE
+ CALL mpi_gather (isnull, 1, MPI_LOGICAL, MPI_LNULL_P, 1, MPI_LOGICAL, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmin, 1, MPI_INTEGER, MPI_INULL_P, 1, MPI_INTEGER, p_root, p_comm_compute, p_err)
+ CALL mpi_gather (vmax, 1, MPI_INTEGER, MPI_INULL_P, 1, MPI_INTEGER, p_root, p_comm_compute, p_err)
+ ENDIF
+
+ IF (p_iam_compute == p_root) THEN
+ IF (present(spv_in)) THEN
+ null_all = null_all .and. (vmin_all == spv_in)
+ ENDIF
+
+ vmin = minval(vmin_all, mask = .not. null_all)
+ vmax = maxval(vmax_all, mask = .not. null_all)
+
+ deallocate (null_all)
+ deallocate (vmin_all)
+ deallocate (vmax_all)
+ ENDIF
+#endif
+
+ IF (p_iam_compute == p_root) THEN
+ wfmt = "('Check vector data:', A25, ' is in (', I20, ',', I20, ')')"
+ write(str_print,wfmt) varname, vmin, vmax
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_send (str_print, 256, MPI_CHARACTER, p_address_root, &
+ mpi_tag_mesg, p_comm_glb, p_err)
+#endif
+ ENDIF
+ ENDIF
+
+ IF (p_is_root) THEN
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ CALL mpi_recv (str_print, 256, MPI_CHARACTER, p_address_compute(p_root), &
+ mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+#endif
+ write(*,'(A)') trim(str_print)
+ ENDIF
+
+ END SUBROUTINE check_vector_data_int32_1d
+
+#endif
+
+END MODULE MOD_RangeCheck
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_SPMD_Task.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SPMD_Task.F90
new file mode 100644
index 0000000000..f14cd1c143
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SPMD_Task.F90
@@ -0,0 +1,212 @@
+#include
+
+MODULE MOD_SPMD_Task
+
+!-----------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! SPMD refers to "Single PROGRAM/Multiple Data" parallelization.
+!
+! MPAS owns MPI initialization and decomposition. Every MPAS rank stays active
+! as a CoLM compute rank, with rank 0 used only for logging/error aggregation.
+!
+! CoLM element ownership is supplied by MPAS cell ownership. Patch/PFT state
+! remains internal to CoLM and is mapped back to the owning element/cell by CoLM.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ include 'mpif.h'
+
+ integer, parameter :: p_root = 0
+
+ logical :: p_is_root = .false.
+ logical :: p_is_active = .false.
+ logical :: p_is_compute = .false.
+ logical :: p_is_history_task = .false.
+
+ integer :: p_comm_glb_plus = MPI_COMM_NULL
+ integer :: p_iam_glb_plus = -1
+
+ ! MPAS-owned communicator aliases used by legacy CoLM helper APIs.
+ integer :: p_comm_glb = MPI_COMM_NULL
+ integer :: p_iam_glb = -1
+ integer :: p_np_glb = 0
+
+ integer :: p_comm_group = MPI_COMM_NULL
+ integer :: p_iam_group = -1
+ integer :: p_np_group = 0
+
+ integer :: p_my_group = 0
+ integer :: p_address_root = p_root
+
+ integer :: p_comm_active = MPI_COMM_NULL
+ integer :: p_iam_active = -1
+ integer :: p_np_active = 0
+
+ integer, allocatable :: p_itis_active (:)
+ integer, allocatable :: p_address_active (:)
+
+ integer :: p_comm_compute = MPI_COMM_NULL
+ integer :: p_iam_compute = -1
+ integer :: p_np_compute = 0
+
+ integer, allocatable :: p_itis_compute (:)
+ integer, allocatable :: p_address_compute (:)
+
+ integer :: p_address_history_task = -1
+
+ integer :: p_stat (MPI_STATUS_SIZE)
+ integer :: p_err = 0
+
+ integer, PUBLIC, parameter :: mpi_tag_size = 1
+ integer, PUBLIC, parameter :: mpi_tag_mesg = 2
+ integer, PUBLIC, parameter :: mpi_tag_data = 3
+
+ integer :: MPI_INULL_P(1)
+ logical :: MPI_LNULL_P(1)
+ real(r8) :: MPI_RNULL_P(1)
+
+ integer, parameter :: MesgMaxSize = 4194304 ! 4MB
+
+ PUBLIC :: spmd_init
+ PUBLIC :: spmd_exit
+ PUBLIC :: divide_processes_into_groups
+ PUBLIC :: spmd_assign_history_task
+
+CONTAINS
+
+ !-----------------------------------------
+ SUBROUTINE spmd_init (MyComm_r)
+
+ IMPLICIT NONE
+ integer, intent(in), optional :: MyComm_r
+ logical mpi_inited
+ integer :: iproc
+
+ CALL MPI_INITIALIZED (mpi_inited, p_err)
+
+ IF ( .not. mpi_inited ) THEN
+ CALL mpi_init (p_err)
+ ENDIF
+
+ IF (present(MyComm_r)) THEN
+ CALL MPI_Comm_dup (MyComm_r, p_comm_glb, p_err)
+ ELSE
+ CALL MPI_Comm_dup (MPI_COMM_WORLD, p_comm_glb, p_err)
+ ENDIF
+
+ CALL mpi_comm_rank (p_comm_glb, p_iam_glb, p_err)
+ CALL mpi_comm_size (p_comm_glb, p_np_glb, p_err)
+
+ p_address_root = p_root
+ p_is_root = (p_iam_glb == p_address_root)
+ p_is_active = .true.
+ p_is_compute = .true.
+ p_is_history_task = .false.
+
+ p_comm_group = p_comm_glb
+ p_iam_group = p_iam_glb
+ p_np_group = p_np_glb
+ p_my_group = 0
+
+ p_comm_active = p_comm_glb
+ p_iam_active = p_iam_glb
+ p_np_active = p_np_glb
+
+ p_comm_compute = p_comm_glb
+ p_iam_compute = p_iam_glb
+ p_np_compute = p_np_glb
+
+ p_comm_glb_plus = MPI_COMM_NULL
+ p_iam_glb_plus = -1
+ p_address_history_task = -1
+
+ IF (allocated(p_itis_active )) deallocate (p_itis_active )
+ IF (allocated(p_address_active )) deallocate (p_address_active )
+ IF (allocated(p_itis_compute )) deallocate (p_itis_compute )
+ IF (allocated(p_address_compute)) deallocate (p_address_compute)
+
+ allocate (p_itis_active (0:p_np_glb-1))
+ allocate (p_address_active (0:p_np_glb-1))
+ allocate (p_itis_compute (0:p_np_glb-1))
+ allocate (p_address_compute (0:p_np_glb-1))
+
+ DO iproc = 0, p_np_glb-1
+ p_itis_active(iproc) = iproc
+ p_address_active(iproc) = iproc
+ p_itis_compute(iproc) = iproc
+ p_address_compute(iproc) = iproc
+ ENDDO
+
+ END SUBROUTINE spmd_init
+
+ !-----------------------------------------
+ SUBROUTINE divide_processes_into_groups (ngrp)
+
+ IMPLICIT NONE
+ integer, intent(in) :: ngrp
+
+ IF (ngrp <= 0) THEN
+ CALL mpi_abort (p_comm_glb, 1, p_err)
+ ENDIF
+
+ ! MPAS owns the process decomposition. Keep every MPAS rank active.
+ p_comm_group = p_comm_glb
+ p_iam_group = p_iam_glb
+ p_np_group = p_np_glb
+ p_my_group = 0
+
+ END SUBROUTINE divide_processes_into_groups
+
+ !-----------------------------------------
+ SUBROUTINE spmd_exit
+
+ IF (allocated(p_itis_active )) deallocate (p_itis_active )
+ IF (allocated(p_address_active )) deallocate (p_address_active )
+ IF (allocated(p_itis_compute )) deallocate (p_itis_compute )
+ IF (allocated(p_address_compute)) deallocate (p_address_compute)
+
+ IF (p_comm_glb /= MPI_COMM_NULL) THEN
+ CALL mpi_barrier (p_comm_glb, p_err)
+ CALL MPI_Comm_free (p_comm_glb, p_err)
+ ENDIF
+
+ p_comm_glb = MPI_COMM_NULL
+ p_comm_group = MPI_COMM_NULL
+ p_comm_active = MPI_COMM_NULL
+ p_comm_compute = MPI_COMM_NULL
+
+ END SUBROUTINE spmd_exit
+
+ ! ----- -----
+ SUBROUTINE spmd_assign_history_task ()
+
+ IMPLICIT NONE
+
+ CALL CoLM_stop('MPAS embedded CoLM does not support a dedicated history MPI task.')
+
+ END SUBROUTINE spmd_assign_history_task
+
+ ! -- STOP all processes --
+ SUBROUTINE CoLM_stop (mesg)
+
+ IMPLICIT NONE
+ character(len=*), optional :: mesg
+ logical :: mpi_inited
+
+ IF (present(mesg)) write(*,*) trim(mesg)
+
+ CALL MPI_INITIALIZED (mpi_inited, p_err)
+ IF (mpi_inited .and. p_comm_glb /= MPI_COMM_NULL) THEN
+ CALL mpi_abort (p_comm_glb, 1, p_err)
+ ENDIF
+
+ STOP
+
+ END SUBROUTINE CoLM_stop
+
+END MODULE MOD_SPMD_Task
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_SingleSrfdata.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SingleSrfdata.F90
new file mode 100644
index 0000000000..80de18fdf7
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SingleSrfdata.F90
@@ -0,0 +1,3472 @@
+#include
+
+#ifdef SinglePoint
+MODULE MOD_SingleSrfdata
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! This module includes subroutines to read or write surface data for
+! "SinglePoint".
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ USE MOD_Precision, only: r8
+ USE MOD_Vars_Global
+ USE MOD_Const_LC
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+ SAVE
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ integer, allocatable :: SITE_pfttyp (:)
+ real(r8), allocatable :: SITE_pctpfts (:)
+#endif
+
+#ifdef CROP
+ integer, allocatable :: SITE_croptyp (:)
+ real(r8), allocatable :: SITE_pctcrop (:)
+#endif
+
+ real(r8) :: SITE_htop
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ real(r8), allocatable :: SITE_htop_pfts (:)
+#endif
+
+ real(r8), allocatable :: SITE_LAI_monthly (:,:)
+ real(r8), allocatable :: SITE_SAI_monthly (:,:)
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ real(r8), allocatable :: SITE_LAI_pfts_monthly (:,:,:)
+ real(r8), allocatable :: SITE_SAI_pfts_monthly (:,:,:)
+#endif
+
+ integer, allocatable :: SITE_LAI_year (:)
+ real(r8), allocatable :: SITE_LAI_8day (:,:)
+
+ real(r8) :: SITE_lakedepth = 1.
+
+ real(r8) :: SITE_soil_s_v_alb
+ real(r8) :: SITE_soil_d_v_alb
+ real(r8) :: SITE_soil_s_n_alb
+ real(r8) :: SITE_soil_d_n_alb
+
+ real(r8), allocatable :: SITE_soil_vf_quartz_mineral (:)
+ real(r8), allocatable :: SITE_soil_vf_gravels (:)
+ real(r8), allocatable :: SITE_soil_vf_sand (:)
+ real(r8), allocatable :: SITE_soil_vf_clay (:)
+ real(r8), allocatable :: SITE_soil_vf_om (:)
+ real(r8), allocatable :: SITE_soil_wf_gravels (:)
+ real(r8), allocatable :: SITE_soil_wf_sand (:)
+ real(r8), allocatable :: SITE_soil_wf_clay (:)
+ real(r8), allocatable :: SITE_soil_wf_om (:)
+ real(r8), allocatable :: SITE_soil_OM_density (:)
+ real(r8), allocatable :: SITE_soil_BD_all (:)
+ real(r8), allocatable :: SITE_soil_theta_s (:)
+ real(r8), allocatable :: SITE_soil_k_s (:)
+ real(r8), allocatable :: SITE_soil_csol (:)
+ real(r8), allocatable :: SITE_soil_tksatu (:)
+ real(r8), allocatable :: SITE_soil_tksatf (:)
+ real(r8), allocatable :: SITE_soil_tkdry (:)
+ real(r8), allocatable :: SITE_soil_k_solids (:)
+ real(r8), allocatable :: SITE_soil_psi_s (:)
+ real(r8), allocatable :: SITE_soil_lambda (:)
+ real(r8), allocatable :: SITE_soil_theta_r (:)
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ real(r8), allocatable :: SITE_soil_alpha_vgm (:)
+ real(r8), allocatable :: SITE_soil_L_vgm (:)
+ real(r8), allocatable :: SITE_soil_n_vgm (:)
+#endif
+ real(r8), allocatable :: SITE_soil_BA_alpha (:)
+ real(r8), allocatable :: SITE_soil_BA_beta (:)
+
+ integer :: SITE_soil_texture
+
+ real(r8) :: SITE_dbedrock = 0.
+
+ real(r8) :: SITE_elevation = 0.
+ real(r8) :: SITE_elvstd = 0.
+ real(r8) :: SITE_sloperatio = 0.
+
+ ! topography factors used for downscaling
+ real(r8) :: SITE_svf = 0.
+ real(r8) :: SITE_cur = 0.
+ real(r8), allocatable :: SITE_slp_type (:)
+ real(r8), allocatable :: SITE_asp_type (:)
+ real(r8), allocatable :: SITE_area_type(:)
+ real(r8), allocatable :: SITE_sf_lut (:,:)
+
+ logical :: u_site_landtype, u_site_crop, u_site_pfts, u_site_htop, &
+ u_site_lai, u_site_lakedepth, u_site_soil_bright, u_site_vf_quartz_mineral, &
+ u_site_vf_gravels, u_site_vf_sand, u_site_vf_clay, u_site_vf_om, &
+ u_site_wf_gravels, u_site_wf_sand, u_site_wf_clay, u_site_wf_om, &
+ u_site_OM_density, u_site_BD_all, u_site_theta_s, u_site_k_s, &
+ u_site_csol, u_site_tksatu, u_site_tksatf, u_site_tkdry, &
+ u_site_k_solids, u_site_psi_s, u_site_lambda, u_site_theta_r, &
+ u_site_alpha_vgm, u_site_L_vgm, u_site_n_vgm, u_site_BA_alpha, &
+ u_site_BA_beta, u_site_soil_texture, u_site_dbedrock, u_site_elevation, &
+ u_site_elvstd, u_site_svf, u_site_cur, u_site_slp_type, &
+ u_site_asp_type, u_site_area_type, u_site_sf_lut, u_site_sloperatio
+
+
+ integer :: SITE_ncar_rid
+ integer :: SITE_urbtyp
+
+ real(r8) :: SITE_lucyid
+
+ real(r8) :: SITE_fveg_urb
+ real(r8) :: SITE_htop_urb
+ real(r8) :: SITE_flake_urb
+ real(r8) :: SITE_froof
+ real(r8) :: SITE_hroof
+ real(r8) :: SITE_fgimp
+ real(r8) :: SITE_fgper
+ real(r8) :: SITE_hlr
+ real(r8) :: SITE_lambdaw
+ real(r8) :: SITE_popden
+
+ real(r8) :: SITE_em_roof
+ real(r8) :: SITE_em_wall
+ real(r8) :: SITE_em_gimp
+ real(r8) :: SITE_em_gper
+ real(r8) :: SITE_t_roommax
+ real(r8) :: SITE_t_roommin
+
+ real(r8) :: SITE_thickroof
+ real(r8) :: SITE_thickwall
+
+ real(r8), allocatable :: SITE_cv_roof (:)
+ real(r8), allocatable :: SITE_cv_wall (:)
+ real(r8), allocatable :: SITE_cv_gimp (:)
+ real(r8), allocatable :: SITE_tk_roof (:)
+ real(r8), allocatable :: SITE_tk_wall (:)
+ real(r8), allocatable :: SITE_tk_gimp (:)
+
+ real(r8), allocatable :: SITE_alb_roof (:,:)
+ real(r8), allocatable :: SITE_alb_wall (:,:)
+ real(r8), allocatable :: SITE_alb_gimp (:,:)
+ real(r8), allocatable :: SITE_alb_gper (:,:)
+
+ logical :: u_site_froof, u_site_hroof, u_site_fgper , u_site_hlr , &
+ u_site_fveg , u_site_htopu, u_site_urblai , u_site_urbsai , &
+ u_site_flake, u_site_utype, &
+ u_site_albr , u_site_albw , u_site_albgimp, u_site_albgper, &
+ u_site_emr , u_site_emw , u_site_emgimp , u_site_emgper , &
+ u_site_cvr , u_site_cvw , u_site_cvgimp , &
+ u_site_tkr , u_site_tkw , u_site_tkgimp , &
+ u_site_tbmax, u_site_tbmin, u_site_thickr , u_site_thickw , &
+ u_site_pop , u_site_lucy
+
+ ! -----------------------------------------------------------------------------------
+ ! The soil color and reflectance is from the work:
+ ! Peter J. Lawrence and Thomas N. Chase, 2007:
+ ! Representing a MODIS consistent land surface in the Community Land Model (CLM 3.0):
+ ! Part 1 generating MODIS consistent land surface parameters
+ ! -----------------------------------------------------------------------------------
+ real(r8), parameter :: soil_s_v_refl(20) = & ! Saturated visible soil reflectance
+ (/ 0.26, 0.24, 0.22, 0.20, 0.19, 0.18, 0.17, 0.16, 0.15, 0.14, &
+ 0.13, 0.12, 0.11, 0.10, 0.09, 0.08, 0.07, 0.06, 0.05, 0.04 /)
+ real(r8), parameter :: soil_d_v_refl(20) = & ! Dry visible soil reflectance
+ (/ 0.37, 0.35, 0.33, 0.31, 0.30, 0.29, 0.28, 0.27, 0.26, 0.25, &
+ 0.24, 0.23, 0.22, 0.21, 0.20, 0.19, 0.18, 0.17, 0.16, 0.15 /)
+ real(r8), parameter :: soil_s_n_refl(20) = & ! Saturated near infrared soil reflectance
+ (/ 0.52, 0.48, 0.44, 0.40, 0.38, 0.36, 0.34, 0.32, 0.30, 0.28, &
+ 0.26, 0.24, 0.22, 0.20, 0.18, 0.16, 0.14, 0.12, 0.10, 0.08 /)
+ real(r8), parameter :: soil_d_n_refl(20) = & ! Dry near infrared soil reflectance
+ (/ 0.63, 0.59, 0.55, 0.51, 0.49, 0.47, 0.45, 0.43, 0.41, 0.39, &
+ 0.37, 0.35, 0.33, 0.31, 0.29, 0.27, 0.25, 0.23, 0.21, 0.19 /)
+
+CONTAINS
+
+
+!-----------------------------------------------------------------------
+ SUBROUTINE read_surface_data_single (fsrfdata, for_surface_build)
+
+ USE MOD_TimeManager
+ USE MOD_Grid
+ USE MOD_Block
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFPoint
+ USE MOD_Namelist
+ USE MOD_Utils
+ USE MOD_Vars_Global, only: PI
+ USE MOD_Const_LC
+ USE MOD_Const_PFT
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ USE MOD_LandPFT
+#endif
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandElm
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: fsrfdata
+ logical, intent(in) :: for_surface_build
+
+ ! Local Variables
+ real(r8) :: lat_in, lon_in
+ real(r8) :: LAI, lakedepth, slp, asp, zenith_angle
+ integer :: i, isc, nsl, typ, a, z, arraysize
+ integer :: iyear, idate(3), simulation_lai_year_start, simulation_lai_year_end
+ integer :: start_year, end_year, ntime, itime
+
+ character(len=256) :: filename, dir_5x5, fmt_str
+ character(len=4) :: cyear, c
+
+ type(grid_type) :: gridpatch, gridcrop, gridpft, gridhtop, gridlai, gridlake, &
+ gridbright, gridsoil, gridrock, gridtopo, grid_topo_factor
+
+ integer, allocatable :: croptyp(:), pfttyp (:)
+ real(r8), allocatable :: pctcrop(:), pctpfts(:), pftLAI(:), pftSAI(:), tea_f(:), tea_b(:)
+
+ integer, parameter :: N_PFT_modis = 16
+ logical :: readflag
+
+ CALL Init_GlobalVars
+ CALL Init_LC_Const
+
+ IF (for_surface_build) THEN
+ write(*,*)
+ write(*,*) ' ---------------- Make Single Point Surface Data ---------------- '
+ ENDIF
+
+ IF (ncio_var_exist(fsrfdata, 'latitude')) THEN
+ CALL ncio_read_serial (fsrfdata, 'latitude', lat_in)
+ IF ((lat_in /= SITE_lat_location) .and. (SITE_lat_location /= -1.e36_r8)) THEN
+ write(*,*) 'Warning: Latitude mismatch: ', &
+ lat_in, ' in data file and ', SITE_lat_location, 'in namelist.'
+ ENDIF
+ SITE_lat_location = lat_in
+ ENDIF
+
+ IF (ncio_var_exist(fsrfdata, 'longitude')) THEN
+ CALL ncio_read_serial (fsrfdata, 'longitude', lon_in)
+ IF ((lon_in /= SITE_lon_location) .and. (SITE_lon_location /= -1.e36_r8)) THEN
+ write(*,*) 'Warning: Longitude mismatch: ', &
+ lon_in, ' in data file and ', SITE_lon_location, 'in namelist.'
+ ENDIF
+ SITE_lon_location = lon_in
+ ENDIF
+
+ CALL normalize_longitude (SITE_lon_location)
+
+ IF (.not. isgreenwich) THEN
+ LocalLongitude = SITE_lon_location
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,F8.2)') 'Latitude : ', SITE_lat_location
+ write(*,'(A,F8.2)') 'Longitude : ', SITE_lon_location
+ ENDIF
+
+
+ DEF_domain%edges = floor(SITE_lat_location)
+ DEF_domain%edgen = floor(SITE_lat_location) + 1.
+ DEF_domain%edgew = floor(SITE_lon_location)
+ DEF_domain%edgee = floor(SITE_lon_location) + 1.
+
+ CALL gblock%set ()
+ gblock%nblkme = 1
+ allocate(gblock%xblkme(1))
+ allocate(gblock%yblkme(1))
+ gblock%xblkme(1) = find_nearest_west (SITE_lon_location, gblock%nxblk, gblock%lon_w)
+ gblock%yblkme(1) = find_nearest_south (SITE_lat_location, gblock%nyblk, gblock%lat_s)
+
+
+ ! (1) build/read "land patch" by using land cover type data
+ numpatch = 1
+
+#ifdef LULC_USGS
+ u_site_landtype = (.not. for_surface_build) .or. (SITE_landtype >= 0) &
+ .or. (USE_SITE_landtype .and. ncio_var_exist(fsrfdata,'USGS_classification'))
+
+ IF (u_site_landtype) THEN
+ IF (SITE_landtype == -1) THEN
+ CALL ncio_read_serial (fsrfdata, 'USGS_classification', SITE_landtype)
+ ENDIF
+ ELSE
+ CALL gridpatch%define_by_name ('colm_1km')
+ filename = trim(DEF_dir_rawdata)//'/landtypes/landtype-usgs-update.nc'
+ CALL read_point_var_2d_int32 (gridpatch, filename, 'landtype', &
+ SITE_lon_location, SITE_lat_location, SITE_landtype)
+ ENDIF
+#else
+ u_site_landtype = (.not. for_surface_build) .or. (SITE_landtype >= 0) &
+ .or. (USE_SITE_landtype .and. ncio_var_exist(fsrfdata,'IGBP_classification'))
+
+ IF (u_site_landtype) THEN
+ IF (SITE_landtype == -1) THEN
+ CALL ncio_read_serial (fsrfdata, 'IGBP_classification', SITE_landtype)
+ ENDIF
+ ELSE
+ CALL gridpatch%define_by_name ('colm_500m')
+ write(cyear,'(i4.4)') DEF_LC_YEAR
+ filename = trim(DEF_dir_rawdata)//'landtypes/landtype-igbp-modis-'//trim(cyear)//'.nc'
+ CALL read_point_var_2d_int32 (gridpatch, filename, 'landtype', &
+ SITE_lon_location, SITE_lat_location, SITE_landtype)
+ ENDIF
+#endif
+
+ IF (SITE_landtype < 0) THEN
+ write(*,*) 'Error! Please set SITE_landtype in namelist file !'
+ CALL CoLM_stop()
+ ENDIF
+
+#ifdef URBAN_MODEL
+ IF (SITE_landtype /= URBAN) THEN
+ write(*,*) 'Error! Please set SITE_landtype to URBAN in namelist file !'
+ CALL CoLM_stop()
+ ENDIF
+#endif
+
+ IF (for_surface_build) THEN
+ write(*,'(A,A,3A)') 'Land cover type : ', trim(patchclassname(SITE_landtype)), &
+ ' (from ',trim(datasource(u_site_landtype)),')'
+ ENDIF
+
+ ! (2) build/read "land crop" by using crop data
+#ifdef CROP
+ IF (SITE_landtype == CROPLAND) THEN
+
+ readflag = ((.not. for_surface_build) .or. USE_SITE_pctcrop)
+ u_site_crop = readflag &
+ .and. ncio_var_exist(fsrfdata,'croptyp',readflag) .and. ncio_var_exist(fsrfdata,'pctcrop',readflag)
+
+ IF (u_site_crop) THEN
+ CALL ncio_read_serial (fsrfdata, 'croptyp', croptyp)
+ CALL ncio_read_serial (fsrfdata, 'pctcrop', pctcrop)
+ ELSE
+ allocate (croptyp (N_CFT))
+ croptyp = (/(i, i = 1, N_CFT)/)
+
+ filename = trim(DEF_dir_rawdata) // '/global_CFT_surface_data.nc'
+ CALL gridcrop%define_from_file (filename, 'lat', 'lon')
+ CALL read_point_var_3d_first_real8 (gridcrop, filename, 'PCT_CFT', &
+ SITE_lon_location, SITE_lat_location, N_CFT, pctcrop)
+ ENDIF
+
+ numpatch = count(pctcrop > 0.)
+
+ IF (numpatch == 0) THEN
+ write(*,*) 'There is no crop at this point!'
+ CALL CoLM_stop()
+ ENDIF
+
+ allocate (SITE_croptyp (numpatch))
+ allocate (SITE_pctcrop (numpatch))
+
+ SITE_croptyp = pack(croptyp, pctcrop > 0.)
+ SITE_pctcrop = pack(pctcrop, pctcrop > 0.) / sum(pctcrop)
+
+ IF (for_surface_build) THEN
+ write(c,'(I0)') numpatch
+ write(*,'(A,'//trim(c)//'I5,3A)') 'crop type : ', SITE_croptyp, ' (from ',trim(datasource(u_site_crop)),')'
+ write(*,'(A,'//trim(c)//'F5.2,3A)') 'crop frac : ', SITE_pctcrop, ' (from ',trim(datasource(u_site_crop)),')'
+ ENDIF
+
+ ENDIF
+#endif
+
+
+ ! (3) build/read "land pft" or "land pc" by using plant functional type data
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+#ifndef CROP
+ IF (patchtypes(SITE_landtype) == 0) THEN
+#else
+ IF (patchtypes(SITE_landtype) == 0 .and. SITE_landtype /= CROPLAND) THEN
+#endif
+ readflag = ((.not. for_surface_build) .or. USE_SITE_pctpfts)
+ u_site_pfts = readflag &
+ .and. ncio_var_exist(fsrfdata,'pfttyp',readflag) .and. ncio_var_exist(fsrfdata,'pctpfts',readflag)
+
+ IF (u_site_pfts) THEN
+ CALL ncio_read_serial (fsrfdata, 'pfttyp', pfttyp )
+ CALL ncio_read_serial (fsrfdata, 'pctpfts', pctpfts)
+ ELSE
+ allocate (pfttyp (N_PFT_modis))
+ pfttyp = (/(i, i = 0, N_PFT_modis-1)/)
+
+ CALL gridpft%define_by_name ('colm_500m')
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ write(cyear,'(i4.4)') DEF_LC_YEAR
+ CALL read_point_5x5_var_3d_real8 (gridpft, dir_5x5, 'MOD'//trim(cyear), 'PCT_PFT', &
+ SITE_lon_location, SITE_lat_location, N_PFT_modis, pctpfts)
+ ENDIF
+
+ numpft = count(pctpfts > 0.)
+
+ allocate (SITE_pfttyp (numpft))
+ allocate (SITE_pctpfts (numpft))
+
+ SITE_pfttyp = pack(pfttyp, pctpfts > 0.)
+ SITE_pctpfts = pack(pctpfts, pctpfts > 0.) / sum(pctpfts)
+
+#ifdef CROP
+ ELSEIF (SITE_landtype == CROPLAND) THEN
+ u_site_pfts = .false.
+ numpft = numpatch
+ allocate (SITE_pfttyp (numpft))
+ allocate (SITE_pctpfts (numpft))
+ SITE_pfttyp = SITE_croptyp + N_PFT - 1
+ SITE_pctpfts = 1.
+#endif
+ ELSE
+ numpft = 0
+ ENDIF
+
+ IF ((patchtypes(SITE_landtype) == 0) .and. (numpft == 0)) THEN
+ write(*,*) 'Warning : There is no plant functional type at this site ! '
+ CALL CoLM_stop()
+ ENDIF
+
+ IF (for_surface_build) THEN
+ IF (numpft > 0) THEN
+ write(*,'(4A)') 'PFT type and fraction : ', ' (from ',trim(datasource(u_site_pfts)),')'
+ DO i = 1, numpft
+ write(*,'(A,F5.2)') ' '//trim(pftclassname(SITE_pfttyp(i))), SITE_pctpfts(i)
+ ENDDO
+ ENDIF
+ ENDIF
+
+#endif
+
+
+ ! (4) forest height
+ readflag = (.not. for_surface_build) .or. USE_SITE_htop
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ u_site_htop = readflag .and. ncio_var_exist(fsrfdata,'canopy_height_pfts',readflag)
+ ELSE
+ u_site_htop = readflag .and. ncio_var_exist(fsrfdata,'canopy_height',readflag)
+ ENDIF
+#else
+ u_site_htop = readflag .and. ncio_var_exist(fsrfdata,'canopy_height',readflag)
+#endif
+
+ IF (u_site_htop) THEN
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ CALL ncio_read_serial (fsrfdata, 'canopy_height_pfts', SITE_htop_pfts)
+ ELSE
+ CALL ncio_read_serial (fsrfdata, 'canopy_height', SITE_htop)
+ ENDIF
+#else
+ CALL ncio_read_serial (fsrfdata, 'canopy_height', SITE_htop)
+#endif
+ ELSE
+#ifdef LULC_USGS
+ CALL gridhtop%define_by_name ('colm_1km')
+ filename = trim(DEF_dir_rawdata)//'/Forest_Height.nc'
+ CALL read_point_var_2d_real8 (gridhtop, filename, 'forest_height', &
+ SITE_lon_location, SITE_lat_location, SITE_htop)
+#else
+
+ CALL gridhtop%define_by_name ('colm_500m')
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ write(cyear,'(i4.4)') DEF_LC_YEAR
+ CALL read_point_5x5_var_2d_real8 (gridhtop, dir_5x5, 'MOD'//trim(cyear), 'HTOP', &
+ SITE_lon_location, SITE_lat_location, SITE_htop)
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (numpft > 0) THEN
+ allocate (SITE_htop_pfts (numpft))
+ SITE_htop_pfts(:) = SITE_htop
+ ENDIF
+#endif
+#endif
+ ENDIF
+
+ IF (for_surface_build) THEN
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ arraysize = size(SITE_htop_pfts)
+ write(fmt_str, '("(A,", I0, "F8.2,3A)")') arraysize
+ write(*,fmt_str) 'Forest height : ', SITE_htop_pfts, ' (from ',trim(datasource(u_site_htop)),')'
+ ELSE
+ write(*,'(A,F8.2,3A)') 'Forest height : ', SITE_htop, ' (from ',trim(datasource(u_site_htop)),')'
+ ENDIF
+#else
+ write(*,'(A,F8.2,3A)') 'Forest height : ', SITE_htop, ' (from ',trim(datasource(u_site_htop)),')'
+#endif
+ ENDIF
+
+
+ ! (5) LAI
+ readflag = ((.not. for_surface_build) .or. USE_SITE_LAI)
+ readflag = readflag .and. ncio_var_exist(fsrfdata,'LAI_year',readflag)
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ u_site_lai = readflag .and. ncio_var_exist(fsrfdata,'LAI_pfts_monthly',readflag) &
+ .and. ncio_var_exist(fsrfdata,'SAI_pfts_monthly',readflag)
+ ELSE
+ u_site_lai = readflag .and. ncio_var_exist(fsrfdata,'LAI_monthly',readflag) &
+ .and. ncio_var_exist(fsrfdata,'SAI_monthly',readflag)
+ ENDIF
+#else
+ IF (DEF_LAI_MONTHLY) THEN
+ u_site_lai = readflag .and. ncio_var_exist(fsrfdata,'LAI_monthly',readflag) &
+ .and. ncio_var_exist(fsrfdata,'SAI_monthly',readflag)
+ ELSE
+ u_site_lai = readflag .and. ncio_var_exist(fsrfdata,'LAI_8day',readflag)
+ ENDIF
+#endif
+
+ IF (u_site_lai) THEN
+ CALL ncio_read_serial (fsrfdata, 'LAI_year', SITE_LAI_year)
+ start_year = 1
+ end_year = size(SITE_LAI_year)
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ CALL ncio_read_serial (fsrfdata, 'LAI_pfts_monthly', SITE_LAI_pfts_monthly)
+ CALL ncio_read_serial (fsrfdata, 'SAI_pfts_monthly', SITE_SAI_pfts_monthly)
+ ntime = size(SITE_LAI_pfts_monthly,2)
+ ELSE
+ CALL ncio_read_serial (fsrfdata, 'LAI_monthly', SITE_LAI_monthly)
+ CALL ncio_read_serial (fsrfdata, 'SAI_monthly', SITE_SAI_monthly)
+ ntime = size(SITE_LAI_monthly,1)
+ ENDIF
+#else
+ IF (DEF_LAI_MONTHLY) THEN
+ CALL ncio_read_serial (fsrfdata, 'LAI_monthly', SITE_LAI_monthly)
+ CALL ncio_read_serial (fsrfdata, 'SAI_monthly', SITE_SAI_monthly)
+ ntime = size(SITE_LAI_monthly,1)
+ ELSE
+ CALL ncio_read_serial (fsrfdata, 'LAI_8day', SITE_LAI_8day)
+ ntime = size(SITE_LAI_8day,1)
+ ENDIF
+#endif
+ ELSE
+
+ idate(1) = DEF_simulation_time%start_year
+ IF (.not. isgreenwich) THEN
+ idate(3) = DEF_simulation_time%start_sec
+ CALL monthday2julian (idate(1), &
+ DEF_simulation_time%start_month, DEF_simulation_time%start_day, idate(2))
+ CALL localtime2gmt(idate)
+ ENDIF
+
+ simulation_lai_year_start = idate(1)
+
+ idate(1) = DEF_simulation_time%end_year
+ IF (.not. isgreenwich) THEN
+ idate(3) = DEF_simulation_time%end_sec
+ CALL monthday2julian (idate(1), &
+ DEF_simulation_time%end_month, DEF_simulation_time%end_day, idate(2))
+ CALL localtime2gmt(idate)
+ ENDIF
+
+ simulation_lai_year_end = idate(1)
+
+ IF (DEF_LAI_CHANGE_YEARLY) THEN
+ start_year = max(simulation_lai_year_start, DEF_LAI_START_YEAR )
+ start_year = min(start_year, DEF_LAI_END_YEAR )
+ end_year = min(simulation_lai_year_end, DEF_LAI_END_YEAR )
+ end_year = max(end_year, DEF_LAI_START_YEAR )
+ ELSE
+ start_year = DEF_LC_YEAR
+ end_year = DEF_LC_YEAR
+ ENDIF
+
+ allocate (SITE_LAI_year (start_year:end_year))
+ SITE_LAI_year = (/(iyear, iyear = start_year, end_year)/)
+
+ IF (DEF_LAI_MONTHLY) THEN
+ ntime = 12
+ allocate (SITE_LAI_monthly (12,start_year:end_year))
+ allocate (SITE_SAI_monthly (12,start_year:end_year))
+ ELSE
+ ntime = 46
+ allocate (SITE_LAI_8day (46,start_year:end_year))
+ ENDIF
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (numpft > 0) THEN
+ allocate (SITE_LAI_pfts_monthly (numpft,12,start_year:end_year))
+ allocate (SITE_SAI_pfts_monthly (numpft,12,start_year:end_year))
+ ENDIF
+#endif
+
+ CALL gridlai%define_by_name ('colm_500m')
+
+ DO iyear = start_year, end_year
+
+ write(cyear,'(i4.4)') iyear
+
+ DO itime = 1, ntime
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ CALL read_point_5x5_var_3d_time_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), 'MONTHLY_PFT_LAI', &
+ SITE_lon_location, SITE_lat_location, N_PFT_modis, itime, pftLAI)
+ CALL read_point_5x5_var_3d_time_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), 'MONTHLY_PFT_SAI', &
+ SITE_lon_location, SITE_lat_location, N_PFT_modis, itime, pftSAI)
+
+#ifndef CROP
+ IF (patchtypes(SITE_landtype) == 0) THEN
+#else
+ IF (patchtypes(SITE_landtype) == 0 .and. SITE_landtype /= CROPLAND) THEN
+#endif
+ IF (allocated(pctpfts)) deallocate (pctpfts)
+ allocate(pctpfts (0:N_PFT_modis-1)); pctpfts(:) = 0.
+ pctpfts(SITE_pfttyp) = SITE_pctpfts
+
+ SITE_LAI_pfts_monthly(:,itime,iyear) = pack(pftLAI, pctpfts > 0.)
+ SITE_SAI_pfts_monthly(:,itime,iyear) = pack(pftSAI, pctpfts > 0.)
+#ifdef CROP
+ ELSEIF (SITE_landtype == CROPLAND) THEN
+ CALL read_point_5x5_var_3d_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), 'PCT_PFT', &
+ SITE_lon_location, SITE_lat_location, N_PFT_modis, pctpfts)
+ SITE_LAI_pfts_monthly(:,itime,iyear) = sum(pftLAI * pctpfts) / sum(pctpfts)
+ SITE_SAI_pfts_monthly(:,itime,iyear) = sum(pftSAI * pctpfts) / sum(pctpfts)
+#endif
+ ELSE
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ CALL read_point_5x5_var_2d_time_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), &
+ 'MONTHLY_LC_LAI', SITE_lon_location, SITE_lat_location, itime, &
+ SITE_LAI_monthly(itime,iyear))
+ CALL read_point_5x5_var_2d_time_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), &
+ 'MONTHLY_LC_SAI', SITE_lon_location, SITE_lat_location, itime, &
+ SITE_SAI_monthly(itime,iyear))
+ ENDIF
+
+#else
+ IF (DEF_LAI_MONTHLY) THEN
+ dir_5x5 = trim(DEF_dir_rawdata) // '/plant_15s'
+ CALL read_point_5x5_var_2d_time_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), &
+ 'MONTHLY_LC_LAI', SITE_lon_location, SITE_lat_location, itime, &
+ SITE_LAI_monthly(itime,iyear))
+ CALL read_point_5x5_var_2d_time_real8 (gridlai, dir_5x5, 'MOD'//trim(cyear), &
+ 'MONTHLY_LC_SAI', SITE_lon_location, SITE_lat_location, itime, &
+ SITE_SAI_monthly(itime,iyear))
+ ELSE
+ filename = trim(DEF_dir_rawdata)//'/lai_15s_8day/lai_8-day_15s_'//trim(cyear)//'.nc'
+ CALL read_point_var_2d_time_real8 (gridlai, filename, 'lai', &
+ SITE_lon_location, SITE_lat_location, itime, LAI)
+ SITE_LAI_8day(itime,iyear) = LAI * 0.1
+ ENDIF
+#endif
+ ENDDO
+ ENDDO
+ ENDIF
+
+ IF (for_surface_build) THEN
+ DO iyear = start_year, end_year
+ write(c,'(i2)') ntime
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (patchtypes(SITE_landtype) == 0) THEN
+ DO i = 1, numpft
+ write(*,'(A,I4,A,I2,A,'//trim(c)//'F8.2,4A)') 'LAI (year ', SITE_LAI_year(iyear), &
+ ', pft ', SITE_pfttyp(i),') : ', SITE_LAI_pfts_monthly(i,:,iyear), &
+ ' (from ',trim(datasource(u_site_lai)),')'
+ write(*,'(A,I4,A,I2,A,'//trim(c)//'F8.2,4A)') 'SAI (year ', SITE_LAI_year(iyear), &
+ ', pft ', SITE_pfttyp(i),') : ', SITE_SAI_pfts_monthly(i,:,iyear), &
+ ' (from ',trim(datasource(u_site_lai)),')'
+ ENDDO
+ ELSE
+ write(*,'(A,I4,A,'//trim(c)//'F8.2,4A)') 'LAI (year ', SITE_LAI_year(iyear), ') : ', &
+ SITE_LAI_monthly(:,iyear), ' (from ',trim(datasource(u_site_lai)),')'
+ write(*,'(A,I4,A,'//trim(c)//'F8.2,4A)') 'SAI (year ', SITE_LAI_year(iyear), ') : ', &
+ SITE_SAI_monthly(:,iyear), ' (from ',trim(datasource(u_site_lai)),')'
+ ENDIF
+#else
+ IF (DEF_LAI_MONTHLY) THEN
+ write(*,'(A,I4,A,'//trim(c)//'F8.2,4A)') 'LAI (year ', SITE_LAI_year(iyear), ') : ', &
+ SITE_LAI_monthly(:,iyear), ' (from ',trim(datasource(u_site_lai)),')'
+ write(*,'(A,I4,A,'//trim(c)//'F8.2,4A)') 'SAI (year ', SITE_LAI_year(iyear), ') : ', &
+ SITE_SAI_monthly(:,iyear), ' (from ',trim(datasource(u_site_lai)),')'
+ ELSE
+ write(*,'(A,I4,A,'//trim(c)//'F8.2,4A)') 'LAI (year ', SITE_LAI_year(iyear), ') : ', &
+ SITE_LAI_8day(:,iyear), ' (from ',trim(datasource(u_site_lai)),')'
+ ENDIF
+#endif
+ ENDDO
+ ENDIF
+
+
+ ! (6) lake depth
+ readflag = ((.not. for_surface_build) .or. USE_SITE_lakedepth)
+ u_site_lakedepth = readflag .and. ncio_var_exist(fsrfdata,'lakedepth',readflag)
+
+ IF (u_site_lakedepth) THEN
+ CALL ncio_read_serial (fsrfdata, 'lakedepth', SITE_lakedepth)
+ ELSE
+ CALL gridlake%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/lake_depth.nc'
+ CALL read_point_var_2d_real8 (gridlake, filename, 'lake_depth', &
+ SITE_lon_location, SITE_lat_location, lakedepth)
+ SITE_lakedepth = lakedepth * 0.1
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,F8.2,3A)') 'Lake depth : ', SITE_lakedepth, ' (from ',trim(datasource(u_site_lakedepth)),')'
+ ENDIF
+
+
+ ! (7) soil brightness parameters
+ readflag = ((.not. for_surface_build) .or. USE_SITE_soilreflectance)
+ u_site_soil_bright = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_s_v_alb',readflag) &
+ .and. ncio_var_exist(fsrfdata,'soil_d_v_alb',readflag) &
+ .and. ncio_var_exist(fsrfdata,'soil_s_n_alb',readflag) &
+ .and. ncio_var_exist(fsrfdata,'soil_d_n_alb',readflag)
+
+ IF (u_site_soil_bright) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_s_v_alb', SITE_soil_s_v_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_d_v_alb', SITE_soil_d_v_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_s_n_alb', SITE_soil_s_n_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_d_n_alb', SITE_soil_d_n_alb)
+ ELSE
+ SITE_soil_s_v_alb = spval
+ SITE_soil_d_v_alb = spval
+ SITE_soil_s_n_alb = spval
+ SITE_soil_d_n_alb = spval
+
+ CALL gridbright%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/soil_brightness.nc'
+ CALL read_point_var_2d_int32 (gridbright, filename, 'soil_brightness', &
+ SITE_lon_location, SITE_lat_location, isc)
+
+#ifdef LULC_USGS
+ IF(SITE_landtype /= 16 .and. SITE_landtype /= 24)THEN ! NOT WATER BODIES(16)/GLACIER and ICESHEET(24)
+#else
+ IF(SITE_landtype /= 17 .and. SITE_landtype /= 15)THEN ! NOT WATER BODIES(17)/GLACIER and ICE SHEET(15)
+#endif
+ IF ((isc >= 1) .and. (isc <= 20)) THEN
+ SITE_soil_s_v_alb = soil_s_v_refl( isc )
+ SITE_soil_d_v_alb = soil_d_v_refl( isc )
+ SITE_soil_s_n_alb = soil_s_n_refl( isc )
+ SITE_soil_d_n_alb = soil_d_n_refl( isc )
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,F8.2,3A)') 'Soil brightness s_v : ', SITE_soil_s_v_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ write(*,'(A,F8.2,3A)') 'Soil brightness d_v : ', SITE_soil_d_v_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ write(*,'(A,F8.2,3A)') 'Soil brightness s_n : ', SITE_soil_s_n_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ write(*,'(A,F8.2,3A)') 'Soil brightness d_n : ', SITE_soil_d_n_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ ENDIF
+
+
+ ! (8) soil parameters
+
+ CALL gridsoil%define_by_name ('colm_500m')
+
+ readflag = ((.not. for_surface_build) .or. USE_SITE_soilparameters)
+ u_site_vf_quartz_mineral = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_vf_quartz_mineral',readflag)
+ IF (u_site_vf_quartz_mineral) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_quartz_mineral', SITE_soil_vf_quartz_mineral)
+ ELSE
+ allocate (SITE_soil_vf_quartz_mineral (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_quartz_mineral_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_quartz_mineral_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_quartz_mineral(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_gravels = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_vf_gravels',readflag)
+ IF (u_site_vf_gravels) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_gravels', SITE_soil_vf_gravels)
+ ELSE
+ allocate (SITE_soil_vf_gravels (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_gravels_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_gravels_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_gravels(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_sand = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_vf_sand',readflag)
+ IF (u_site_vf_sand) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_sand', SITE_soil_vf_sand)
+ ELSE
+ allocate (SITE_soil_vf_sand (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_sand_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_sand_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_sand(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_clay = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_vf_clay',readflag)
+ IF (u_site_vf_clay) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_clay', SITE_soil_vf_clay)
+ ELSE
+ allocate (SITE_soil_vf_clay (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_clay_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_clay_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_clay(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_om = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_vf_om',readflag)
+ IF (u_site_vf_om) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_om', SITE_soil_vf_om)
+ ELSE
+ allocate (SITE_soil_vf_om (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_om_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_om_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_om(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_gravels = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_wf_gravels',readflag)
+ IF (u_site_wf_gravels) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_gravels', SITE_soil_wf_gravels)
+ ELSE
+ allocate (SITE_soil_wf_gravels (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_gravels_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_gravels_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_gravels(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_sand = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_wf_sand',readflag)
+ IF (u_site_wf_sand) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_sand', SITE_soil_wf_sand)
+ ELSE
+ allocate (SITE_soil_wf_sand (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_sand_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_sand_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_sand(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_clay = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_wf_clay',readflag)
+ IF (u_site_wf_clay) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_clay', SITE_soil_wf_clay)
+ ELSE
+ allocate (SITE_soil_wf_clay (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_clay_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_clay_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_clay(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_om = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_wf_om',readflag)
+ IF (u_site_wf_om) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_om', SITE_soil_wf_om)
+ ELSE
+ allocate (SITE_soil_wf_om (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_om_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_om_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_om(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_OM_density = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_OM_density',readflag)
+ IF (u_site_OM_density) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_OM_density', SITE_soil_OM_density)
+ ELSE
+ allocate (SITE_soil_OM_density (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/OM_density_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'OM_density_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_OM_density(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_BD_all = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_BD_all',readflag)
+ IF (u_site_BD_all) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_BD_all', SITE_soil_BD_all)
+ ELSE
+ allocate (SITE_soil_BD_all (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/BD_all_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'BD_all_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_BD_all(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_theta_s = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_theta_s',readflag)
+ IF (u_site_theta_s) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_theta_s', SITE_soil_theta_s)
+ ELSE
+ allocate (SITE_soil_theta_s (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/theta_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'theta_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_theta_s(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_k_s = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_k_s',readflag)
+ IF (u_site_k_s) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_k_s', SITE_soil_k_s)
+ ELSE
+ allocate (SITE_soil_k_s (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/k_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'k_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_k_s(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_csol = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_csol',readflag)
+ IF (u_site_csol) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_csol', SITE_soil_csol)
+ ELSE
+ allocate (SITE_soil_csol (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/csol.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'csol_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_csol(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_tksatu = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_tksatu',readflag)
+ IF (u_site_tksatu) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_tksatu', SITE_soil_tksatu)
+ ELSE
+ allocate (SITE_soil_tksatu (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/tksatu.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'tksatu_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_tksatu(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_tksatf = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_tksatf',readflag)
+ IF (u_site_tksatf) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_tksatf', SITE_soil_tksatf)
+ ELSE
+ allocate (SITE_soil_tksatf (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/tksatf.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'tksatf_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_tksatf(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_tkdry = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_tkdry',readflag)
+ IF (u_site_tkdry) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_tkdry', SITE_soil_tkdry)
+ ELSE
+ allocate (SITE_soil_tkdry (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/tkdry.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'tkdry_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_tkdry(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_k_solids = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_k_solids',readflag)
+ IF (u_site_k_solids) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_k_solids', SITE_soil_k_solids)
+ ELSE
+ allocate (SITE_soil_k_solids (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/k_solids.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'k_solids_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_k_solids(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_psi_s = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_psi_s',readflag)
+ IF (u_site_psi_s) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_psi_s', SITE_soil_psi_s)
+ ELSE
+ allocate (SITE_soil_psi_s (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/psi_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'psi_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_psi_s(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_lambda = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_lambda',readflag)
+ IF (u_site_lambda) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_lambda', SITE_soil_lambda)
+ ELSE
+ allocate (SITE_soil_lambda (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/lambda.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'lambda_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_lambda(nsl))
+ ENDDO
+ ENDIF
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ u_site_theta_r = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_theta_r',readflag)
+ IF (u_site_theta_r) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_theta_r', SITE_soil_theta_r)
+ ELSE
+ allocate (SITE_soil_theta_r (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_theta_r.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_theta_r_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_theta_r(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_alpha_vgm = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_alpha_vgm',readflag)
+ IF (u_site_alpha_vgm) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_alpha_vgm', SITE_soil_alpha_vgm)
+ ELSE
+ allocate (SITE_soil_alpha_vgm (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_alpha.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_alpha_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_alpha_vgm(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_L_vgm = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_L_vgm',readflag)
+ IF (u_site_L_vgm) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_L_vgm', SITE_soil_L_vgm)
+ ELSE
+ allocate (SITE_soil_L_vgm (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_L.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_L_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_L_vgm(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_n_vgm = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_n_vgm',readflag)
+ IF (u_site_n_vgm) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_n_vgm', SITE_soil_n_vgm)
+ ELSE
+ allocate (SITE_soil_n_vgm (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_n.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_n_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_n_vgm(nsl))
+ ENDDO
+ ENDIF
+#endif
+
+ u_site_BA_alpha = u_site_vf_gravels .and. u_site_vf_sand
+ u_site_BA_beta = u_site_vf_gravels .and. u_site_vf_sand
+ allocate (SITE_soil_BA_alpha (8))
+ allocate (SITE_soil_BA_beta (8))
+ DO nsl = 1, 8
+ IF (SITE_soil_vf_gravels(nsl) + SITE_soil_vf_sand(nsl) > 0.4) THEN
+ SITE_soil_BA_alpha(nsl) = 0.38
+ SITE_soil_BA_beta (nsl) = 35.0
+ ELSEIF (SITE_soil_vf_gravels(nsl) + SITE_soil_vf_sand(nsl) > 0.25) THEN
+ SITE_soil_BA_alpha(nsl) = 0.24
+ SITE_soil_BA_beta (nsl) = 26.0
+ ELSE
+ SITE_soil_BA_alpha(nsl) = 0.20
+ SITE_soil_BA_beta (nsl) = 10.0
+ ENDIF
+ ENDDO
+
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ u_site_soil_texture = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_texture',readflag)
+ IF (u_site_soil_texture) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_texture', SITE_soil_texture)
+ ELSE
+ filename = trim(DEF_dir_rawdata)//'/soil/soiltexture_0cm-60cm_mean.nc'
+ CALL read_point_var_2d_int32 (gridsoil, filename, 'soiltexture', &
+ SITE_lon_location, SITE_lat_location, SITE_soil_texture)
+ ENDIF
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_quartz_mineral : ', SITE_soil_vf_quartz_mineral(1:8), ' (from ',trim(datasource(u_site_vf_quartz_mineral)),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_gravels : ', SITE_soil_vf_gravels (1:8), ' (from ',trim(datasource(u_site_vf_gravels )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_sand : ', SITE_soil_vf_sand (1:8), ' (from ',trim(datasource(u_site_vf_sand )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_clay : ', SITE_soil_vf_clay (1:8), ' (from ',trim(datasource(u_site_vf_clay )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_om : ', SITE_soil_vf_om (1:8), ' (from ',trim(datasource(u_site_vf_om )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_gravels : ', SITE_soil_wf_gravels (1:8), ' (from ',trim(datasource(u_site_wf_gravels )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_sand : ', SITE_soil_wf_sand (1:8), ' (from ',trim(datasource(u_site_wf_sand )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_clay : ', SITE_soil_wf_clay (1:8), ' (from ',trim(datasource(u_site_wf_clay )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_om : ', SITE_soil_wf_om (1:8), ' (from ',trim(datasource(u_site_wf_om )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_OM_density : ', SITE_soil_OM_density (1:8), ' (from ',trim(datasource(u_site_OM_density )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_BD_all : ', SITE_soil_BD_all (1:8), ' (from ',trim(datasource(u_site_BD_all )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_theta_s : ', SITE_soil_theta_s (1:8), ' (from ',trim(datasource(u_site_theta_s )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_k_s : ', SITE_soil_k_s (1:8), ' (from ',trim(datasource(u_site_k_s )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_csol : ', SITE_soil_csol (1:8), ' (from ',trim(datasource(u_site_csol )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_tksatu : ', SITE_soil_tksatu (1:8), ' (from ',trim(datasource(u_site_tksatu )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_tksatf : ', SITE_soil_tksatf (1:8), ' (from ',trim(datasource(u_site_tksatf )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_tkdry : ', SITE_soil_tkdry (1:8), ' (from ',trim(datasource(u_site_tkdry )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_k_solids : ', SITE_soil_k_solids (1:8), ' (from ',trim(datasource(u_site_k_solids )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_psi_s : ', SITE_soil_psi_s (1:8), ' (from ',trim(datasource(u_site_psi_s )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_lambda : ', SITE_soil_lambda (1:8), ' (from ',trim(datasource(u_site_lambda )),')'
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ write(*,'(A,8ES10.2,3A)') 'soil_theta_r : ', SITE_soil_theta_r (1:8), ' (from ',trim(datasource(u_site_theta_r )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_alpha_vgm : ', SITE_soil_alpha_vgm (1:8), ' (from ',trim(datasource(u_site_alpha_vgm )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_L_vgm : ', SITE_soil_L_vgm (1:8), ' (from ',trim(datasource(u_site_L_vgm )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_n_vgm : ', SITE_soil_n_vgm (1:8), ' (from ',trim(datasource(u_site_n_vgm )),')'
+#endif
+ write(*,'(A,8ES10.2,3A)') 'soil_BA_alpha : ', SITE_soil_BA_alpha (1:8), ' (from ',trim(datasource(u_site_BA_alpha )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_BA_beta : ', SITE_soil_BA_beta (1:8), ' (from ',trim(datasource(u_site_BA_beta )),')'
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ write(*,'(A,I3,3A)') 'soil texture : ', SITE_soil_texture, ' (from ',trim(datasource(u_site_soil_texture)),')'
+ ENDIF
+ ENDIF
+
+
+ ! (9) depth to bedrock
+ IF (DEF_USE_BEDROCK) THEN
+ readflag = ((.not. for_surface_build) .or. USE_SITE_dbedrock)
+ u_site_dbedrock = readflag &
+ .and. ncio_var_exist (fsrfdata, 'depth_to_bedrock',readflag)
+ IF (u_site_dbedrock) THEN
+ CALL ncio_read_serial (fsrfdata, 'depth_to_bedrock', SITE_dbedrock)
+ ELSE
+ CALL gridrock%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/bedrock.nc'
+ CALL read_point_var_2d_real8 (gridrock, filename, 'dbedrock', &
+ SITE_lon_location, SITE_lat_location, SITE_dbedrock)
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,F8.2,3A)') 'Depth to bedrock : ', SITE_dbedrock, ' (from ',trim(datasource(u_site_dbedrock)),')'
+ ENDIF
+
+ ENDIF
+
+ ! (10) topography
+ readflag = ((.not. for_surface_build) .or. USE_SITE_topography)
+
+ u_site_elevation = readflag &
+ .and. ncio_var_exist (fsrfdata, 'elevation',readflag)
+ IF (u_site_elevation) THEN
+ CALL ncio_read_serial (fsrfdata, 'elevation', SITE_elevation)
+ ELSE
+ CALL gridtopo%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/topography.nc'
+ CALL read_point_var_2d_real8 (gridtopo, filename, 'elevation', &
+ SITE_lon_location, SITE_lat_location, SITE_elevation)
+ ENDIF
+
+ u_site_elvstd = readflag &
+ .and. ncio_var_exist (fsrfdata, 'elvstd',readflag)
+ IF (u_site_elvstd) THEN
+ CALL ncio_read_serial (fsrfdata, 'elvstd', SITE_elvstd)
+ ELSE
+ CALL gridtopo%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/topography.nc'
+ CALL read_point_var_2d_real8 (gridtopo, filename, 'elvstd', &
+ SITE_lon_location, SITE_lat_location, SITE_elvstd)
+ ENDIF
+
+ u_site_sloperatio = readflag &
+ .and. ncio_var_exist (fsrfdata, 'sloperatio',readflag)
+ IF (u_site_sloperatio) THEN
+ CALL ncio_read_serial (fsrfdata, 'sloperatio', SITE_sloperatio)
+ ELSE
+ CALL gridtopo%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/topography.nc'
+ CALL read_point_var_2d_real8 (gridtopo, filename, 'slope', &
+ SITE_lon_location, SITE_lat_location, SITE_sloperatio)
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/slope.nc"
+ IF (ncio_var_exist(filename,'lat') .and. ncio_var_exist(filename,'lon')) THEN
+ CALL grid_topo_factor%define_from_file (filename, "lat", "lon")
+ ENDIF
+
+ u_site_svf = readflag &
+ .and. ncio_var_exist (fsrfdata, 'SITE_svf',readflag)
+ IF (u_site_svf) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_svf' , SITE_svf)
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/sky_view_factor.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'svf', &
+ SITE_lon_location, SITE_lat_location, SITE_svf)
+ ENDIF
+
+ u_site_cur = readflag &
+ .and. ncio_var_exist (fsrfdata, 'SITE_cur',readflag)
+ IF (u_site_cur) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_cur' , SITE_cur)
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/curvature.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'curvature', &
+ SITE_lon_location, SITE_lat_location, SITE_cur)
+ ENDIF
+
+ u_site_slp_type = readflag &
+ .and. ncio_var_exist (fsrfdata, 'SITE_slp_type', readflag) &
+ .and. ncio_var_exist (fsrfdata, 'SITE_asp_type', readflag) &
+ .and. ncio_var_exist (fsrfdata, 'SITE_area_type',readflag)
+ u_site_asp_type = u_site_slp_type
+ u_site_area_type = u_site_slp_type
+
+ IF (u_site_slp_type) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_slp_type' , SITE_slp_type )
+ CALL ncio_read_serial (fsrfdata, 'SITE_asp_type' , SITE_asp_type )
+ CALL ncio_read_serial (fsrfdata, 'SITE_area_type', SITE_area_type )
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/slope.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'slope', &
+ SITE_lon_location, SITE_lat_location, slp)
+
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/aspect.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'aspect', &
+ SITE_lon_location, SITE_lat_location, asp)
+
+ allocate (SITE_slp_type (num_slope_type)); SITE_slp_type (:) = 0.
+ allocate (SITE_asp_type (num_slope_type)); SITE_asp_type (:) = 0.
+ allocate (SITE_area_type (num_slope_type)); SITE_area_type(:) = 0.
+
+ IF ((asp.ge.0 .and. asp.le.90*pi/180) .or. (asp.ge.270*pi/180 .and. asp.le.360*pi/180)) THEN
+ IF ((slp.ge.15*pi/180)) THEN ! north abrupt slope
+ typ = 1
+ ELSE ! north gentle slope
+ typ = 2
+ ENDIF
+ ELSE
+ IF ((slp.ge.15*pi/180)) THEN ! south abrupt slope
+ typ = 3
+ ELSE ! south gentle slope
+ typ = 4
+ ENDIF
+ ENDIF
+
+ SITE_slp_type (typ) = slp
+ SITE_asp_type (typ) = asp
+ SITE_area_type(typ) = 1.
+
+ ENDIF
+
+ u_site_sf_lut = readflag &
+ .and. ncio_var_exist (fsrfdata, 'SITE_sf_lut',readflag)
+ IF (u_site_sf_lut) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_sf_lut', SITE_sf_lut)
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/terrain_elev_angle_front.nc"
+ CALL read_point_var_3d_first_real8 (grid_topo_factor, filename, 'tea_front', &
+ SITE_lon_location, SITE_lat_location, num_azimuth, tea_f)
+
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/terrain_elev_angle_back.nc"
+ CALL read_point_var_3d_first_real8 (grid_topo_factor, filename, 'tea_back', &
+ SITE_lon_location, SITE_lat_location, num_azimuth, tea_b)
+
+ allocate (SITE_sf_lut (num_azimuth, num_zenith))
+
+ DO a = 1, num_azimuth
+
+ tea_f(a) = asin(max(min(tea_f(a),1.),-1.))
+ tea_b(a) = asin(max(min(tea_b(a),1.),-1.))
+
+ IF (tea_f(a) <= tea_b(a)) tea_f(a) = tea_b(a) + 0.001
+
+ DO z = 1, num_zenith
+ zenith_angle = pi/(2*num_zenith)*(z-1)
+
+ IF (pi*0.5 - zenith_angle < tea_b(a)) THEN
+ SITE_sf_lut(a,z) = 0
+ ELSE IF (pi*0.5 - zenith_angle > tea_f(a)) THEN
+ SITE_sf_lut(a,z) = 1
+ ELSE
+ SITE_sf_lut(a,z) = (0.5*pi - zenith_angle - tea_b(a))/(tea_f(a) - tea_b(a))
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,F8.2,3A)') 'Elevation : ', SITE_elevation , ' (from ',trim(datasource(u_site_elevation)),')'
+ write(*,'(A,F8.2,3A)') 'Elv std : ', SITE_elvstd , ' (from ',trim(datasource(u_site_elvstd)),')'
+ write(*,'(A,F8.2,3A)') 'SlopeRatio: ', SITE_sloperatio, ' (from ',trim(datasource(u_site_sloperatio)),')'
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ write(*,'(A,F8.2,3A)') 'Sky view factor : ', SITE_svf, ' (from ',trim(datasource(u_site_svf)),')'
+ write(*,'(A,F8.2,3A)') 'Curvature : ', SITE_cur, ' (from ',trim(datasource(u_site_cur)),')'
+ write(c,'(I0)') num_slope_type
+ write(*,'(A,'//trim(c)//'F8.2,3A)') 'Slope type : ', SITE_slp_type, ' (from ',trim(datasource(u_site_slp_type)),')'
+ write(*,'(A,'//trim(c)//'F8.2,3A)') 'Aspect type : ', SITE_asp_type, ' (from ',trim(datasource(u_site_slp_type)),')'
+ write(*,'(A,'//trim(c)//'F8.2,3A)') 'Slope type area : ', SITE_area_type, ' (from ',trim(datasource(u_site_slp_type)),')'
+ write(c,'(I0)') num_azimuth*num_zenith
+ write(*,'(A,A,I3,A,I3,A,'//trim(c)//'F8.2,3A)') 'Shadow lookup table : ', &
+ '(', num_azimuth, ' in azimuth,', num_zenith, ' in zenith)', &
+ SITE_sf_lut , ' (from ',trim(datasource(u_site_sf_lut)),')'
+ ENDIF
+ ENDIF
+
+
+ IF (.not. for_surface_build) THEN
+
+ landpatch%nset = numpatch
+
+ allocate (landpatch%settyp (numpatch)); landpatch%settyp = SITE_landtype
+
+ landpatch%nblkgrp = 1
+ allocate (landpatch%xblkgrp(1)); landpatch%xblkgrp(1) = 1
+ allocate (landpatch%yblkgrp(1)); landpatch%yblkgrp(1) = 1
+
+ allocate (landpatch%vecgs%vlen(1,1)); landpatch%vecgs%vlen(1,1) = numpatch
+ allocate (landpatch%vecgs%vstt(1,1)); landpatch%vecgs%vstt(1,1) = 1
+ allocate (landpatch%vecgs%vend(1,1)); landpatch%vecgs%vend(1,1) = numpatch
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+
+ IF (numpft > 0) THEN
+
+ landpft%nset = numpft
+
+ allocate (landpft%settyp (numpft)); landpft%settyp = SITE_pfttyp
+
+ landpft%nblkgrp = 1
+ allocate (landpft%xblkgrp(1)); landpft%xblkgrp(1) = 1
+ allocate (landpft%yblkgrp(1)); landpft%yblkgrp(1) = 1
+
+ allocate (landpft%vecgs%vlen(1,1)); landpft%vecgs%vlen(1,1) = numpft
+ allocate (landpft%vecgs%vstt(1,1)); landpft%vecgs%vstt(1,1) = 1
+ allocate (landpft%vecgs%vend(1,1)); landpft%vecgs%vend(1,1) = numpft
+
+ allocate (patch_pft_s (numpatch))
+ allocate (patch_pft_e (numpatch))
+ allocate (pft2patch (numpft ))
+#ifdef CROP
+ IF (SITE_landtype == CROPLAND) THEN
+ patch_pft_s = (/(i, i = 1, numpatch)/)
+ patch_pft_e = (/(i, i = 1, numpatch)/)
+ pft2patch = (/(i, i = 1, numpatch)/)
+ ELSE
+ patch_pft_s = 1
+ patch_pft_e = numpft
+ pft2patch = 1
+ ENDIF
+#else
+ patch_pft_s = 1
+ patch_pft_e = numpft
+ pft2patch = 1
+#endif
+ ENDIF
+#endif
+
+ numelm = 1
+ allocate (landelm%settyp (1)); landelm%settyp (1) = 0
+ allocate (elm_patch%substt (1)); elm_patch%substt(1) = 1
+ allocate (elm_patch%subend (1)); elm_patch%subend(1) = numpatch
+
+ allocate (elm_patch%subfrc (numpatch)); elm_patch%subfrc = 1./numpatch
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+#ifdef CROP
+ elm_patch%subfrc = SITE_pctcrop
+#endif
+#endif
+
+ ENDIF
+
+ END SUBROUTINE read_surface_data_single
+
+!-----------------------------------------------------------------------
+ SUBROUTINE read_urban_surface_data_single (fsrfdata, for_surface_build, mkrun)
+
+ USE MOD_TimeManager
+ USE MOD_Grid
+ USE MOD_Block
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFPoint
+ USE MOD_Namelist
+ USE MOD_Utils
+ USE MOD_SPMD_Task
+ USE MOD_LandPatch
+ USE MOD_LandUrban
+ USE MOD_Urban_Const_LCZ
+ USE MOD_Vars_Global, only: PI, URBAN
+ USE MOD_Mesh, only: numelm
+ USE MOD_LandElm
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: fsrfdata
+ logical, intent(in) :: for_surface_build
+ logical, intent(in), optional :: mkrun
+
+ ! Local Variables
+ real(r8), allocatable, dimension(:,:) :: hwrbld_ncar , fgper_ncar , htroof_ncar , wtroof_ncar
+ real(r8), allocatable, dimension(:,:) :: emroof_ncar , emwall_ncar , emgimp_ncar , emgper_ncar
+ real(r8), allocatable, dimension(:,:) :: thkroof_ncar, thkwall_ncar, tbldmin_ncar, tbldmax_ncar
+ real(r8), allocatable, dimension(:,:,:) :: cvroof_ncar , cvwall_ncar , cvgimp_ncar , &
+ tkroof_ncar , tkwall_ncar , tkgimp_ncar
+ real(r8), allocatable, dimension(:,:,:,:) :: albroof_ncar, albwall_ncar, albgimp_ncar, albgper_ncar
+
+ real(r8) :: lat_in, lon_in
+ real(r8) :: LAI, lakedepth, slp, asp, zenith_angle
+ integer :: i, isc, nsl, typ, a, z, rid, utyp
+ integer :: iyear, idate(3), simulation_lai_year_start, simulation_lai_year_end
+ integer :: start_year, end_year, ntime, itime, pop_i
+ logical :: readflag
+
+ character(len=256) :: filename, dir_5x5
+ character(len=4) :: cyear, c, c5year
+
+ type(grid_type) :: gridupatch, gridhroof, gridfroof , gridhtopu, gridfvegu, gridflakeu, gridlaiu, &
+ gridpopu , gridlucy , gridbright, gridsoil , gridrock , gridtopo , gridlake, &
+ grid_topo_factor
+
+ real(r8), allocatable :: tea_f(:), tea_b(:)
+
+ u_site_froof = .false.; u_site_hroof = .false.; u_site_fgper = .false.; u_site_hlr = .false.;
+ u_site_fveg = .false.; u_site_htopu = .false.; u_site_urblai = .false.; u_site_urbsai = .false.;
+ u_site_flake = .false.;
+
+ u_site_albr = .false.; u_site_albw = .false.; u_site_albgimp = .false.; u_site_albgper = .false.;
+ u_site_emr = .false.; u_site_emw = .false.; u_site_emgimp = .false.; u_site_emgper = .false.;
+
+ u_site_cvr = .false.; u_site_cvw = .false.; u_site_cvgimp = .false.;
+ u_site_tkr = .false.; u_site_tkw = .false.; u_site_tkgimp = .false.;
+
+ u_site_tbmax = .false.; u_site_tbmin = .false.; u_site_thickr = .false.; u_site_thickw = .false.;
+ u_site_pop = .false.; u_site_lucy = .false.;
+
+ IF (for_surface_build) THEN
+ write(*,*)
+ write(*,*) ' ---------------- Make Single Point Surface Data ---------------- '
+ ENDIF
+
+ IF (ncio_var_exist(fsrfdata, 'latitude')) THEN
+ CALL ncio_read_serial (fsrfdata, 'latitude', lat_in)
+ IF (lat_in /= SITE_lat_location) THEN
+ write(*,*) 'Warning: Latitude mismatch: ', &
+ lat_in, ' in data file and ', SITE_lat_location, 'in namelist.'
+ ENDIF
+ SITE_lat_location = lat_in
+ ENDIF
+
+ IF (ncio_var_exist(fsrfdata, 'longitude')) THEN
+ CALL ncio_read_serial (fsrfdata, 'longitude', lon_in)
+ IF (lon_in /= SITE_lon_location) THEN
+ write(*,*) 'Warning: Longitude mismatch: ', &
+ lon_in, ' in data file and ', SITE_lon_location, 'in namelist.'
+ ENDIF
+ SITE_lon_location = lon_in
+ ENDIF
+
+ CALL normalize_longitude (SITE_lon_location)
+
+ IF (.not. isgreenwich) THEN
+ LocalLongitude = SITE_lon_location
+ ENDIF
+
+ IF (for_surface_build) THEN
+ write(*,'(A,F8.2)') 'Latitude : ', SITE_lat_location
+ write(*,'(A,F8.2)') 'Longitude : ', SITE_lon_location
+ ENDIF
+
+ DEF_domain%edges = floor(SITE_lat_location)
+ DEF_domain%edgen = floor(SITE_lat_location) + 1.
+ DEF_domain%edgew = floor(SITE_lon_location)
+ DEF_domain%edgee = floor(SITE_lon_location) + 1.
+
+ CALL gblock%set ()
+ gblock%nblkme = 1
+ allocate(gblock%xblkme(1))
+ allocate(gblock%yblkme(1))
+ gblock%xblkme(1) = find_nearest_west (SITE_lon_location, gblock%nxblk, gblock%lon_w)
+ gblock%yblkme(1) = find_nearest_south (SITE_lat_location, gblock%nyblk, gblock%lat_s)
+
+ ! (1) build/read "land patch" by using land cover type data
+ IF (trim(fsrfdata) /= 'null') THEN
+ SITE_landtype = URBAN
+ ELSEIF (SITE_landtype /= URBAN) THEN
+ write(*,*) 'Error! Please set SITE_landtype to URBAN in namelist file !'
+ CALL CoLM_stop()
+ ENDIF
+
+ numpatch = 1
+ numurban = 1
+ u_site_landtype = (SITE_landtype >= 0)
+ IF (for_surface_build) THEN
+ write(*,'(A,A,3A)') 'Land cover type : ', trim(patchclassname(SITE_landtype)), &
+ ' (from ',trim(datasource(u_site_landtype)),')'
+ ENDIF
+
+ IF (for_surface_build) THEN
+ ! (2) build/read "urban type" by using land cover type data
+IF (DEF_URBAN_type_scheme == 1) THEN
+ u_site_utype = ncio_var_exist(fsrfdata,'URBAN_DENSITY_CLASS')
+
+ IF ( u_site_utype ) THEN
+ CALL ncio_read_serial (fsrfdata, 'URBTYP' , SITE_ncar_rid)
+ CALL ncio_read_serial (fsrfdata, 'URBAN_DENSITY_CLASS', SITE_urbtyp )
+ ELSE
+ CALL gridupatch%define_by_name ('colm_500m')
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban_type/'
+ CALL read_point_5x5_var_2d_int32 (gridupatch, dir_5x5, 'URBTYP', 'REGION_ID', &
+ SITE_lon_location, SITE_lat_location, SITE_ncar_rid)
+
+ CALL read_point_5x5_var_2d_int32 (gridupatch, dir_5x5, 'URBTYP', 'URBAN_DENSITY_CLASS', &
+ SITE_lon_location, SITE_lat_location, SITE_urbtyp)
+
+ write(*,'(A,I0,A,I0,3A)') 'Urban type : NCAR ', SITE_urbtyp, ' of Region ', SITE_ncar_rid, &
+ ' (from ',trim(datasource(u_site_utype)),')'
+ ENDIF
+ELSE
+ u_site_utype = ncio_var_exist(fsrfdata,'LCZ_DOM')
+ IF ( u_site_utype ) THEN
+ CALL ncio_read_serial (fsrfdata, 'LCZ_DOM', SITE_urbtyp )
+ ELSE
+ CALL gridupatch%define_by_name ('colm_500m')
+
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban_type/'
+ CALL read_point_5x5_var_2d_int32 (gridupatch, dir_5x5, 'URBTYP', 'LCZ_DOM', &
+ SITE_lon_location, SITE_lat_location, SITE_urbtyp)
+ ENDIF
+ write(*,'(A,I0,3A)') 'Urban type : LCZ ', SITE_urbtyp, &
+ ' (from ',trim(datasource(u_site_utype)),')'
+ENDIF
+
+
+ ! (4) urban geometry
+ readflag = USE_SITE_urban_geometry
+ u_site_hroof = ncio_var_exist(fsrfdata,'building_mean_height',readflag)
+ IF ( u_site_hroof ) THEN
+ CALL ncio_read_serial (fsrfdata, 'building_mean_height', SITE_hroof )
+ ELSE
+ CALL gridhroof%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban/'
+ write(c5year, '(i4.4)') int(DEF_LC_YEAR/5)*5
+
+IF (DEF_Urban_geom_data == 1) THEN
+ CALL read_point_5x5_var_2d_real8 (gridhroof, dir_5x5, 'URBSRF'//trim(c5year), 'HT_ROOF_GHSL', &
+ SITE_lon_location, SITE_lat_location, SITE_hroof)
+ELSE
+ CALL read_point_5x5_var_2d_real8 (gridhroof, dir_5x5, 'URBSRF'//trim(c5year), 'HT_ROOF_Li', &
+ SITE_lon_location, SITE_lat_location, SITE_hroof)
+ENDIF
+ ENDIF
+
+ u_site_froof = readflag .and. ncio_var_exist(fsrfdata,'roof_area_fraction',readflag)
+ IF ( u_site_froof ) THEN
+ CALL ncio_read_serial (fsrfdata, 'roof_area_fraction', SITE_froof )
+ ELSE
+ CALL gridfroof%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban/'
+ write(c5year, '(i4.4)') int(DEF_LC_YEAR/5)*5
+IF (DEF_Urban_geom_data == 1) THEN
+ CALL read_point_5x5_var_2d_real8 (gridfroof, dir_5x5, 'URBSRF'//trim(c5year), 'PCT_ROOF_GHSL', &
+ SITE_lon_location, SITE_lat_location, SITE_froof)
+ELSE
+ CALL read_point_5x5_var_2d_real8 (gridfroof, dir_5x5, 'URBSRF'//trim(c5year), 'PCT_ROOF_Li', &
+ SITE_lon_location, SITE_lat_location, SITE_froof)
+ENDIF
+ ENDIF
+
+ u_site_fgper = readflag .and. ncio_var_exist(fsrfdata,'impervious_area_fraction',readflag)
+ IF ( u_site_fgper ) THEN
+ CALL ncio_read_serial (fsrfdata, 'impervious_area_fraction', SITE_fgimp )
+ ENDIF
+
+ u_site_thickr = readflag .and. ncio_var_exist(fsrfdata,'THICK_ROOF',readflag)
+ IF ( u_site_thickr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'THICK_ROOF', SITE_thickroof )
+ ENDIF
+
+ u_site_thickw = readflag .and. ncio_var_exist(fsrfdata,'THICK_WALL',readflag)
+ IF ( u_site_thickw ) THEN
+ CALL ncio_read_serial (fsrfdata, 'THICK_WALL', SITE_thickwall )
+ ENDIF
+
+IF (DEF_USE_CANYON_HWR) THEN
+ u_site_hlr = readflag .and. ncio_var_exist(fsrfdata,'canyon_height_width_ratio',readflag)
+ IF ( u_site_hlr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'canyon_height_width_ratio', SITE_hlr )
+ ENDIF
+ELSE
+ u_site_hlr = readflag .and. ncio_var_exist(fsrfdata,'wall_to_plan_area_ratio',readflag)
+ IF ( u_site_hlr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'wall_to_plan_area_ratio', SITE_lambdaw )
+ SITE_hlr = SITE_lambdaw/4/SITE_froof
+ ENDIF
+ENDIF
+ ! (5) urban ecology
+ readflag = USE_SITE_urban_ecology
+ u_site_htopu = readflag .and. ncio_var_exist(fsrfdata,'tree_mean_height',readflag)
+ IF ( u_site_htopu ) THEN
+ CALL ncio_read_serial (fsrfdata, 'tree_mean_height', SITE_htop_urb )
+ ELSE
+ CALL gridhtopu%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban/'
+ write(c5year, '(i4.4)') int(DEF_LC_YEAR/5)*5
+
+ CALL read_point_5x5_var_2d_real8 (gridhtopu, dir_5x5, 'URBSRF'//trim(c5year), 'HTOP', &
+ SITE_lon_location, SITE_lat_location, SITE_htop_urb)
+ ENDIF
+
+ u_site_flake = readflag .and. ncio_var_exist(fsrfdata,'water_area_fraction',readflag)
+ IF ( u_site_flake ) THEN
+ CALL ncio_read_serial (fsrfdata, 'water_area_fraction', SITE_flake_urb )
+ ELSE
+ CALL gridflakeu%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban/'
+ write(c5year, '(i4.4)') int(DEF_LC_YEAR/5)*5
+
+ CALL read_point_5x5_var_2d_real8 (gridflakeu, dir_5x5, 'URBSRF'//trim(c5year), 'PCT_Water', &
+ SITE_lon_location, SITE_lat_location, SITE_flake_urb)
+
+ SITE_flake_urb = SITE_flake_urb/100
+ ENDIF
+
+ u_site_fveg = readflag .and. ncio_var_exist(fsrfdata,'tree_area_fraction',readflag)
+ IF ( u_site_fveg ) THEN
+ CALL ncio_read_serial (fsrfdata, 'tree_area_fraction', SITE_fveg_urb )
+ ELSE
+ CALL gridfvegu%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban/'
+ write(c5year, '(i4.4)') int(DEF_LC_YEAR/5)*5
+
+ CALL read_point_5x5_var_2d_real8 (gridfvegu, dir_5x5, 'URBSRF'//trim(c5year), 'PCT_Tree', &
+ SITE_lon_location, SITE_lat_location, SITE_fveg_urb)
+
+ SITE_fveg_urb = SITE_fveg_urb/100
+ ENDIF
+
+ u_site_urblai = readflag .and. ncio_var_exist(fsrfdata,'TREE_LAI',readflag)
+ IF ( u_site_urblai) THEN
+ CALL ncio_read_serial (fsrfdata, 'TREE_LAI', SITE_LAI_monthly )
+ CALL ncio_read_serial (fsrfdata, 'TREE_SAI', SITE_SAI_monthly )
+ ELSE
+
+ idate(1) = DEF_simulation_time%start_year
+ IF (.not. isgreenwich) THEN
+ idate(3) = DEF_simulation_time%start_sec
+ CALL monthday2julian (idate(1), &
+ DEF_simulation_time%start_month, DEF_simulation_time%start_day, idate(2))
+ CALL localtime2gmt(idate)
+ ENDIF
+ simulation_lai_year_start = idate(1)
+
+ idate(1) = DEF_simulation_time%end_year
+ IF (.not. isgreenwich) THEN
+ idate(3) = DEF_simulation_time%end_sec
+ CALL monthday2julian (idate(1), &
+ DEF_simulation_time%end_month, DEF_simulation_time%end_day, idate(2))
+ CALL localtime2gmt(idate)
+ ENDIF
+ simulation_lai_year_end = idate(1)
+
+ IF (DEF_LAI_CHANGE_YEARLY) THEN
+ start_year = max(simulation_lai_year_start, DEF_LAI_START_YEAR )
+ start_year = min(start_year, DEF_LAI_END_YEAR )
+ end_year = min(simulation_lai_year_end, DEF_LAI_END_YEAR )
+ end_year = max(end_year, DEF_LAI_START_YEAR )
+ ELSE
+ start_year = DEF_LC_YEAR
+ end_year = DEF_LC_YEAR
+ ENDIF
+
+ allocate (SITE_LAI_year (start_year:end_year))
+ SITE_LAI_year = (/(iyear, iyear = start_year, end_year)/)
+
+ ntime = 12
+ allocate (SITE_LAI_monthly (12,start_year:end_year))
+ allocate (SITE_SAI_monthly (12,start_year:end_year))
+
+ CALL gridlaiu%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban_lai_500m/'
+
+ DO iyear = start_year, end_year
+ write(cyear,'(i4.4)') iyear
+ DO itime = 1, ntime
+ CALL read_point_5x5_var_2d_time_real8 (gridlaiu, dir_5x5, 'URBLAI_'//trim(cyear), &
+ 'URBAN_TREE_LAI', SITE_lon_location, SITE_lat_location, itime, &
+ SITE_LAI_monthly(itime,iyear))
+
+ CALL read_point_5x5_var_2d_time_real8 (gridlaiu, dir_5x5, 'URBLAI_'//trim(cyear), &
+ 'URBAN_TREE_SAI', SITE_lon_location, SITE_lat_location, itime, &
+ SITE_SAI_monthly(itime,iyear))
+ ENDDO
+ ENDDO
+ ENDIF
+
+ ! (6) urban radiation
+ readflag = USE_SITE_urban_radiation
+ u_site_albr = readflag .and. ncio_var_exist(fsrfdata,'ALB_ROOF',readflag)
+ IF ( u_site_albr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'ALB_ROOF', SITE_alb_roof )
+ ENDIF
+
+ u_site_albw = readflag .and. ncio_var_exist(fsrfdata,'ALB_WALL',readflag)
+ IF ( u_site_albw ) THEN
+ CALL ncio_read_serial (fsrfdata, 'ALB_WALL', SITE_alb_wall )
+ ENDIF
+
+ u_site_albgper = readflag .and. ncio_var_exist(fsrfdata,'ALB_GPER',readflag)
+ IF ( u_site_albgper ) THEN
+ CALL ncio_read_serial (fsrfdata, 'ALB_GPER', SITE_alb_gper )
+ ENDIF
+
+ u_site_albgimp = readflag .and. ncio_var_exist(fsrfdata,'ALB_GIMP',readflag)
+ IF ( u_site_albgimp ) THEN
+ CALL ncio_read_serial (fsrfdata, 'ALB_GIMP', SITE_alb_gimp )
+ ENDIF
+
+ u_site_emr = readflag .and. ncio_var_exist(fsrfdata,'EM_ROOF',readflag)
+ IF ( u_site_emr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'EM_ROOF', SITE_em_roof )
+ ENDIF
+
+ u_site_emw = readflag .and. ncio_var_exist(fsrfdata,'EM_WALL',readflag)
+ IF ( u_site_emw ) THEN
+ CALL ncio_read_serial (fsrfdata, 'EM_WALL', SITE_em_wall )
+ ENDIF
+
+ u_site_emgper = readflag .and. ncio_var_exist(fsrfdata,'EM_GPER',readflag)
+ IF ( u_site_emgper ) THEN
+ CALL ncio_read_serial (fsrfdata, 'EM_GPER', SITE_em_gper )
+ ENDIF
+
+ u_site_emgimp = readflag .and. ncio_var_exist(fsrfdata,'EM_GIMP',readflag)
+ IF ( u_site_emgimp ) THEN
+ CALL ncio_read_serial (fsrfdata, 'EM_GIMP', SITE_em_gimp )
+ ENDIF
+
+ ! (6) urban thermal
+ readflag = USE_SITE_urban_thermal
+ u_site_cvr = readflag .and. ncio_var_exist(fsrfdata,'CV_ROOF',readflag)
+ IF ( u_site_cvr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'CV_ROOF', SITE_cv_roof )
+ ENDIF
+
+ u_site_cvw = readflag .and. ncio_var_exist(fsrfdata,'CV_WALL',readflag)
+ IF ( u_site_cvw ) THEN
+ CALL ncio_read_serial (fsrfdata, 'CV_WALL', SITE_cv_wall )
+ ENDIF
+
+ u_site_cvgimp = readflag .and. ncio_var_exist(fsrfdata,'CV_GIMP',readflag)
+ IF ( u_site_cvgimp ) THEN
+ CALL ncio_read_serial (fsrfdata, 'CV_GIMP', SITE_cv_gimp )
+ ENDIF
+
+ u_site_tkr = readflag .and. ncio_var_exist(fsrfdata,'TK_ROOF',readflag)
+ IF ( u_site_tkr ) THEN
+ CALL ncio_read_serial (fsrfdata, 'TK_ROOF', SITE_tk_roof )
+ ENDIF
+
+ u_site_tkw = readflag .and. ncio_var_exist(fsrfdata,'TK_WALL',readflag)
+ IF ( u_site_tkw ) THEN
+ CALL ncio_read_serial (fsrfdata, 'TK_WALL', SITE_tk_wall )
+ ENDIF
+
+ u_site_tkgimp = readflag .and. ncio_var_exist(fsrfdata,'TK_GIMP',readflag)
+ IF ( u_site_tkgimp ) THEN
+ CALL ncio_read_serial (fsrfdata, 'TK_GIMP', SITE_tk_gimp )
+ ENDIF
+
+ ! (6) urban human
+ readflag = USE_SITE_urban_human
+ u_site_pop= readflag .and. ncio_var_exist(fsrfdata,'resident_population_density',readflag)
+ IF ( u_site_pop) THEN
+ CALL ncio_read_serial (fsrfdata, 'resident_population_density', SITE_popden )
+ ELSE
+ CALL gridpopu%define_by_name ('colm_500m')
+ dir_5x5 = trim(DEF_dir_rawdata) // '/urban/'
+ write(c5year, '(i4.4)') int(DEF_LC_YEAR/5)*5
+
+ IF (mod(DEF_LC_YEAR,5) == 0) THEN
+ pop_i = 1
+ ELSE
+ pop_i = 5 - (ceiling(DEF_LC_YEAR*1./5.)*5 - DEF_LC_YEAR) + 1
+ ENDIF
+
+ CALL read_point_5x5_var_2d_time_real8 (gridlaiu, dir_5x5, 'URBSRF'//trim(c5year), &
+ 'POP_DEN', SITE_lon_location, SITE_lat_location, pop_i, &
+ SITE_popden)
+ ENDIF
+
+ u_site_lucy= readflag .and. ncio_var_exist(fsrfdata,'LUCY_ID',readflag)
+ IF ( u_site_lucy) THEN
+ CALL ncio_read_serial (fsrfdata, 'LUCY_ID', SITE_lucyid )
+ ELSE
+ CALL gridlucy%define_by_name ('colm_5km')
+ filename = trim(DEF_dir_rawdata) // '/urban/LUCY_regionid.nc'
+
+ CALL read_point_var_2d_real8 (gridlucy, filename, 'LUCY_REGION_ID', &
+ SITE_lon_location, SITE_lat_location, SITE_lucyid)
+ ENDIF
+
+ u_site_tbmax= readflag .and. ncio_var_exist(fsrfdata,'T_BUILDING_MAX',readflag)
+ IF ( u_site_tbmax) THEN
+ CALL ncio_read_serial (fsrfdata, 'T_BUILDING_MAX', SITE_t_roommax )
+ ENDIF
+
+ u_site_tbmin= readflag .and. ncio_var_exist(fsrfdata,'T_BUILDING_MIN',readflag)
+ IF ( u_site_tbmin) THEN
+ CALL ncio_read_serial (fsrfdata, 'T_BUILDING_MIN', SITE_t_roommin )
+ ENDIF
+
+IF (DEF_URBAN_type_scheme == 1) THEN
+ filename = trim(DEF_dir_rawdata)//'urban/NCAR_urban_properties.nc'
+
+ CALL ncio_read_bcast_serial (filename, "WTLUNIT_ROOF" , wtroof_ncar )
+ CALL ncio_read_bcast_serial (filename, "HT_ROOF" , htroof_ncar )
+ CALL ncio_read_bcast_serial (filename, "CANYON_HWR" , hwrbld_ncar )
+ CALL ncio_read_bcast_serial (filename, "WTROAD_PERV" , fgper_ncar )
+ CALL ncio_read_bcast_serial (filename, "EM_ROOF" , emroof_ncar )
+ CALL ncio_read_bcast_serial (filename, "EM_WALL" , emwall_ncar )
+ CALL ncio_read_bcast_serial (filename, "EM_IMPROAD" , emgimp_ncar )
+ CALL ncio_read_bcast_serial (filename, "EM_PERROAD" , emgper_ncar )
+ CALL ncio_read_bcast_serial (filename, "ALB_ROOF" , albroof_ncar)
+ CALL ncio_read_bcast_serial (filename, "ALB_WALL" , albwall_ncar)
+ CALL ncio_read_bcast_serial (filename, "ALB_IMPROAD" , albgimp_ncar)
+ CALL ncio_read_bcast_serial (filename, "ALB_PERROAD" , albgper_ncar)
+ CALL ncio_read_bcast_serial (filename, "TK_ROOF" , tkroof_ncar )
+ CALL ncio_read_bcast_serial (filename, "TK_WALL" , tkwall_ncar )
+ CALL ncio_read_bcast_serial (filename, "TK_IMPROAD" , tkgimp_ncar )
+ CALL ncio_read_bcast_serial (filename, "CV_ROOF" , cvroof_ncar )
+ CALL ncio_read_bcast_serial (filename, "CV_WALL" , cvwall_ncar )
+ CALL ncio_read_bcast_serial (filename, "CV_IMPROAD" , cvgimp_ncar )
+ CALL ncio_read_bcast_serial (filename, "THICK_ROOF" , thkroof_ncar)
+ CALL ncio_read_bcast_serial (filename, "THICK_WALL" , thkwall_ncar)
+ CALL ncio_read_bcast_serial (filename, "T_BUILDING_MIN", tbldmin_ncar)
+ CALL ncio_read_bcast_serial (filename, "T_BUILDING_MAX", tbldmax_ncar)
+
+ rid = SITE_ncar_rid
+ utyp = SITE_urbtyp
+
+ IF (.not. u_site_emr ) SITE_em_roof = emroof_ncar(utyp, rid)
+ IF (.not. u_site_emw ) SITE_em_wall = emwall_ncar(utyp, rid)
+ IF (.not. u_site_emgimp ) SITE_em_gimp = emgimp_ncar(utyp, rid)
+ IF (.not. u_site_emgper ) SITE_em_gper = emgper_ncar(utyp, rid)
+
+ IF (.not. u_site_tbmax ) SITE_t_roommax = tbldmax_ncar (utyp, rid)
+ IF (.not. u_site_tbmin ) SITE_t_roommin = tbldmin_ncar (utyp, rid)
+
+ IF (.not. u_site_thickr ) SITE_thickroof = thkroof_ncar(utyp, rid)
+ IF (.not. u_site_thickw ) SITE_thickwall = thkwall_ncar(utyp, rid)
+
+ IF (.not. u_site_cvr ) THEN
+ allocate( SITE_cv_roof (nl_roof) )
+ SITE_cv_roof(:) = cvroof_ncar(utyp, rid, :)
+ ENDIF
+
+ IF (.not. u_site_cvw ) THEN
+ allocate( SITE_cv_wall (nl_wall) )
+ SITE_cv_wall(:) = cvwall_ncar(utyp, rid, :)
+ ENDIF
+
+ IF (.not. u_site_cvgimp) THEN
+ allocate( SITE_cv_gimp (nl_soil) )
+ SITE_cv_gimp(:) = cvgimp_ncar(utyp, rid, :)
+ ENDIF
+
+ IF (.not. u_site_tkr ) THEN
+ allocate( SITE_tk_roof (nl_roof) )
+ SITE_tk_roof(:) = tkroof_ncar(utyp, rid, :)
+ ENDIF
+
+ IF (.not. u_site_tkw ) THEN
+ allocate( SITE_tk_wall (nl_wall) )
+ SITE_tk_wall(:) = tkwall_ncar(utyp, rid, :)
+ ENDIF
+
+ IF (.not. u_site_tkgimp) THEN
+ allocate( SITE_tk_gimp (nl_soil) )
+ SITE_tk_gimp(:) = tkgimp_ncar(utyp, rid, :)
+ ENDIF
+
+ IF (.not. u_site_albr ) THEN
+ allocate( SITE_alb_roof (2, 2) )
+ SITE_alb_roof(:,:) = albroof_ncar(utyp, rid, :, :)
+ ENDIF
+
+ IF (.not. u_site_albw ) THEN
+ allocate( SITE_alb_wall (2, 2) )
+ SITE_alb_wall(:,:) = albwall_ncar(utyp, rid, :, :)
+ ENDIF
+
+ IF (.not. u_site_albgimp) THEN
+ allocate( SITE_alb_gimp (2, 2) )
+ SITE_alb_gimp(:,:) = albgimp_ncar(utyp, rid, :, :)
+ ENDIF
+
+ IF (.not. u_site_albgper) THEN
+ allocate( SITE_alb_gper (2, 2) )
+ SITE_alb_gper(:,:) = albgper_ncar(utyp, rid, :, :)
+ ENDIF
+
+ IF (.not. u_site_hlr ) SITE_hlr = hwrbld_ncar(utyp, rid)
+ IF (.not. u_site_fgper) SITE_fgimp = 1-fgper_ncar(utyp, rid)
+ELSE
+ utyp = SITE_urbtyp
+ IF (.not. u_site_emr ) SITE_em_roof = emroof_lcz(utyp)
+ IF (.not. u_site_emw ) SITE_em_wall = emwall_lcz(utyp)
+ IF (.not. u_site_emgimp) SITE_em_gimp = emgimp_lcz(utyp)
+ IF (.not. u_site_emgper) SITE_em_gper = emgper_lcz(utyp)
+
+ IF (.not. u_site_tbmax) SITE_t_roommax = tbldmax_lcz(utyp)
+ IF (.not. u_site_tbmin) SITE_t_roommin = tbldmin_lcz(utyp)
+
+ IF (.not. u_site_thickr) SITE_thickroof = thkroof_lcz(utyp)
+ IF (.not. u_site_thickw) SITE_thickwall = thkwall_lcz(utyp)
+
+ IF (.not. u_site_cvr ) THEN
+ allocate( SITE_cv_roof (nl_roof) )
+ SITE_cv_roof(:) = cvroof_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_cvw ) THEN
+ allocate( SITE_cv_wall (nl_wall) )
+ SITE_cv_wall(:) = cvwall_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_cvgimp) THEN
+ allocate( SITE_cv_gimp (nl_soil) )
+ SITE_cv_gimp(:) = cvgimp_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_tkr ) THEN
+ allocate( SITE_tk_roof (nl_roof) )
+ SITE_tk_roof(:) = tkroof_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_tkw ) THEN
+ allocate( SITE_tk_wall (nl_wall) )
+ SITE_tk_wall(:) = tkwall_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_tkgimp) THEN
+ allocate( SITE_tk_gimp (nl_soil) )
+ SITE_tk_gimp(:) = tkgimp_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_albr ) THEN
+ allocate( SITE_alb_roof (2, 2) )
+ SITE_alb_roof(:,:) = albroof_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_albw ) THEN
+ allocate( SITE_alb_wall (2, 2) )
+ SITE_alb_wall(:,:) = albwall_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_albgimp) THEN
+ allocate( SITE_alb_gimp (2, 2) )
+ SITE_alb_gimp(:,:) = albgimp_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_albgper) THEN
+ allocate( SITE_alb_gper (2, 2) )
+ SITE_alb_gper(:,:) = albgper_lcz(utyp)
+ ENDIF
+
+ IF (.not. u_site_hlr ) SITE_hlr = hwrbld_lcz(utyp)
+
+ IF (.not. u_site_fgper) SITE_fgimp = 1-fgper_lcz(utyp)/(1-SITE_froof)
+ENDIF
+
+IF (DEF_USE_CANYON_HWR) THEN
+ SITE_hlr =SITE_hlr*(1-sqrt(SITE_froof))/sqrt(SITE_froof)
+ENDIF
+
+ ! (6) lake depth
+ readflag = u_site_lakedepth
+ u_site_lakedepth = readflag .and. ncio_var_exist(fsrfdata,'lakedepth',readflag)
+ IF (u_site_lakedepth) THEN
+ CALL ncio_read_serial (fsrfdata, 'lakedepth', SITE_lakedepth)
+ ELSE
+ CALL gridlake%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/lake_depth.nc'
+ CALL read_point_var_2d_real8 (gridlake, filename, 'lake_depth', &
+ SITE_lon_location, SITE_lat_location, lakedepth)
+ SITE_lakedepth = lakedepth * 0.1
+ ENDIF
+
+ write(*,'(A,F8.2,3A)') 'Lake depth : ', SITE_lakedepth, ' (from ',datasource(u_site_lakedepth),')'
+
+ ! (7) soil brightness parameters
+ readflag = USE_SITE_soilreflectance
+ u_site_soil_bright = readflag &
+ .and. ncio_var_exist(fsrfdata,'soil_s_v_alb',readflag) &
+ .and. ncio_var_exist(fsrfdata,'soil_d_v_alb',readflag) &
+ .and. ncio_var_exist(fsrfdata,'soil_s_n_alb',readflag) &
+ .and. ncio_var_exist(fsrfdata,'soil_d_n_alb',readflag)
+
+ IF (u_site_soil_bright) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_s_v_alb', SITE_soil_s_v_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_d_v_alb', SITE_soil_d_v_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_s_n_alb', SITE_soil_s_n_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_d_n_alb', SITE_soil_d_n_alb)
+ ELSE
+ SITE_soil_s_v_alb = spval
+ SITE_soil_d_v_alb = spval
+ SITE_soil_s_n_alb = spval
+ SITE_soil_d_n_alb = spval
+
+ CALL gridbright%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/soil_brightness.nc'
+ CALL read_point_var_2d_int32 (gridbright, filename, 'soil_brightness', &
+ SITE_lon_location, SITE_lat_location, isc)
+
+#ifdef LULC_USGS
+ IF(SITE_landtype /= 16 .and. SITE_landtype /= 24)THEN ! NOT WATER BODIES(16)/GLACIER and ICESHEET(24)
+#else
+ IF(SITE_landtype /= 17 .and. SITE_landtype /= 15)THEN ! NOT WATER BODIES(17)/GLACIER and ICE SHEET(15)
+#endif
+ IF ((isc >= 1) .and. (isc <= 20)) THEN
+ SITE_soil_s_v_alb = soil_s_v_refl( isc )
+ SITE_soil_d_v_alb = soil_d_v_refl( isc )
+ SITE_soil_s_n_alb = soil_s_n_refl( isc )
+ SITE_soil_d_n_alb = soil_d_n_refl( isc )
+ ENDIF
+ ENDIF
+ ENDIF
+
+ write(*,'(A,F8.2,3A)') 'Soil brightness s_v : ', SITE_soil_s_v_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ write(*,'(A,F8.2,3A)') 'Soil brightness d_v : ', SITE_soil_d_v_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ write(*,'(A,F8.2,3A)') 'Soil brightness s_n : ', SITE_soil_s_n_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+ write(*,'(A,F8.2,3A)') 'Soil brightness d_n : ', SITE_soil_d_n_alb, ' (from ',trim(datasource(u_site_soil_bright)),')'
+
+ ! (8) soil parameters
+ CALL gridsoil%define_by_name ('colm_500m')
+
+ readflag = USE_SITE_soilparameters
+ u_site_vf_quartz_mineral = readflag .and. ncio_var_exist(fsrfdata,'soil_vf_quartz_mineral',readflag)
+ IF (u_site_vf_quartz_mineral) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_quartz_mineral', SITE_soil_vf_quartz_mineral)
+ ELSE
+ allocate (SITE_soil_vf_quartz_mineral (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_quartz_mineral_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_quartz_mineral_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_quartz_mineral(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_gravels = readflag .and. ncio_var_exist(fsrfdata,'soil_vf_gravels',readflag)
+ IF (u_site_vf_gravels) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_gravels', SITE_soil_vf_gravels)
+ ELSE
+ allocate (SITE_soil_vf_gravels (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_gravels_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_gravels_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_gravels(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_sand = readflag .and. ncio_var_exist(fsrfdata,'soil_vf_sand',readflag)
+ IF (u_site_vf_sand) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_sand', SITE_soil_vf_sand)
+ ELSE
+ allocate (SITE_soil_vf_sand (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_sand_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_sand_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_sand(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_clay = readflag .and. ncio_var_exist(fsrfdata,'soil_vf_clay',readflag)
+ IF (u_site_vf_clay) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_clay', SITE_soil_vf_clay)
+ ELSE
+ allocate (SITE_soil_vf_clay (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_clay_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_clay_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_clay(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_vf_om = readflag .and. ncio_var_exist(fsrfdata,'soil_vf_om',readflag)
+ IF (u_site_vf_om) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_om', SITE_soil_vf_om)
+ ELSE
+ allocate (SITE_soil_vf_om (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/vf_om_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'vf_om_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_vf_om(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_gravels = readflag .and. ncio_var_exist(fsrfdata,'soil_wf_gravels',readflag)
+ IF (u_site_wf_gravels) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_gravels', SITE_soil_wf_gravels)
+ ELSE
+ allocate (SITE_soil_wf_gravels (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_gravels_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_gravels_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_gravels(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_sand = readflag .and. ncio_var_exist(fsrfdata,'soil_wf_sand',readflag)
+ IF (u_site_wf_sand) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_sand', SITE_soil_wf_sand)
+ ELSE
+ allocate (SITE_soil_wf_sand (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_sand_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_sand_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_sand(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_clay = readflag .and. ncio_var_exist(fsrfdata,'soil_wf_clay',readflag)
+ IF (u_site_wf_clay) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_clay', SITE_soil_wf_clay)
+ ELSE
+ allocate (SITE_soil_wf_clay (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_clay_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_clay_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_clay(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_wf_om = readflag .and. ncio_var_exist(fsrfdata,'soil_wf_om',readflag)
+ IF (u_site_wf_om) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_om', SITE_soil_wf_om)
+ ELSE
+ allocate (SITE_soil_wf_om (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/wf_om_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'wf_om_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_wf_om(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_OM_density = readflag .and. ncio_var_exist(fsrfdata,'soil_OM_density',readflag)
+ IF (u_site_OM_density) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_OM_density', SITE_soil_OM_density)
+ ELSE
+ allocate (SITE_soil_OM_density (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/OM_density_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'OM_density_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_OM_density(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_BD_all = readflag .and. ncio_var_exist(fsrfdata,'soil_BD_all',readflag)
+ IF (u_site_BD_all) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_BD_all', SITE_soil_BD_all)
+ ELSE
+ allocate (SITE_soil_BD_all (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/BD_all_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'BD_all_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_BD_all(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_theta_s = readflag .and. ncio_var_exist(fsrfdata,'soil_theta_s',readflag)
+ IF (u_site_theta_s) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_theta_s', SITE_soil_theta_s)
+ ELSE
+ allocate (SITE_soil_theta_s (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/theta_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'theta_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_theta_s(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_k_s = readflag .and. ncio_var_exist(fsrfdata,'soil_k_s',readflag)
+ IF (u_site_k_s) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_k_s', SITE_soil_k_s)
+ ELSE
+ allocate (SITE_soil_k_s (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/k_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'k_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_k_s(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_csol = readflag .and. ncio_var_exist(fsrfdata,'soil_csol',readflag)
+ IF (u_site_csol) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_csol', SITE_soil_csol)
+ ELSE
+ allocate (SITE_soil_csol (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/csol.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'csol_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_csol(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_tksatu = readflag .and. ncio_var_exist(fsrfdata,'soil_tksatu',readflag)
+ IF (u_site_tksatu) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_tksatu', SITE_soil_tksatu)
+ ELSE
+ allocate (SITE_soil_tksatu (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/tksatu.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'tksatu_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_tksatu(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_tksatf = readflag .and. ncio_var_exist(fsrfdata,'soil_tksatf',readflag)
+ IF (u_site_tksatf) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_tksatf', SITE_soil_tksatf)
+ ELSE
+ allocate (SITE_soil_tksatf (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/tksatf.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'tksatf_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_tksatf(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_tkdry = readflag .and. ncio_var_exist(fsrfdata,'soil_tkdry',readflag)
+ IF (u_site_tkdry) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_tkdry', SITE_soil_tkdry)
+ ELSE
+ allocate (SITE_soil_tkdry (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/tkdry.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'tkdry_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_tkdry(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_k_solids = readflag .and. ncio_var_exist(fsrfdata,'soil_k_solids',readflag)
+ IF (u_site_k_solids) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_k_solids', SITE_soil_k_solids)
+ ELSE
+ allocate (SITE_soil_k_solids (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/k_solids.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'k_solids_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_k_solids(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_psi_s = readflag .and. ncio_var_exist(fsrfdata,'soil_psi_s',readflag)
+ IF (u_site_psi_s) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_psi_s', SITE_soil_psi_s)
+ ELSE
+ allocate (SITE_soil_psi_s (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/psi_s.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'psi_s_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_psi_s(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_lambda = readflag .and. ncio_var_exist(fsrfdata,'soil_lambda',readflag)
+ IF (u_site_lambda) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_lambda', SITE_soil_lambda)
+ ELSE
+ allocate (SITE_soil_lambda (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/lambda.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'lambda_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_lambda(nsl))
+ ENDDO
+ ENDIF
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ u_site_theta_r = readflag .and. ncio_var_exist(fsrfdata,'soil_theta_r',readflag)
+ IF (u_site_theta_r) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_theta_r', SITE_soil_theta_r)
+ ELSE
+ allocate (SITE_soil_theta_r (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_theta_r.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_theta_r_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_theta_r(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_alpha_vgm = readflag .and. ncio_var_exist(fsrfdata,'soil_alpha_vgm',readflag)
+ IF (u_site_alpha_vgm) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_alpha_vgm', SITE_soil_alpha_vgm)
+ ELSE
+ allocate (SITE_soil_alpha_vgm (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_alpha.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_alpha_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_alpha_vgm(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_L_vgm = readflag .and. ncio_var_exist(fsrfdata,'soil_L_vgm',readflag)
+ IF (u_site_L_vgm) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_L_vgm', SITE_soil_L_vgm)
+ ELSE
+ allocate (SITE_soil_L_vgm (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_L.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_L_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_L_vgm(nsl))
+ ENDDO
+ ENDIF
+
+ u_site_n_vgm = readflag .and. ncio_var_exist(fsrfdata,'soil_n_vgm',readflag)
+ IF (u_site_n_vgm) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_n_vgm', SITE_soil_n_vgm)
+ ELSE
+ allocate (SITE_soil_n_vgm (8))
+ DO nsl = 1, 8
+ write(c,'(i1)') nsl
+ filename = trim(DEF_dir_rawdata)//'/soil/VGM_n.nc'
+ CALL read_point_var_2d_real8 (gridsoil, filename, 'VGM_n_l'//trim(c), &
+ SITE_lon_location, SITE_lat_location, SITE_soil_n_vgm(nsl))
+ ENDDO
+ ENDIF
+#endif
+
+ u_site_BA_alpha = .false.
+ u_site_BA_beta = .false.
+ allocate (SITE_soil_BA_alpha (8))
+ allocate (SITE_soil_BA_beta (8))
+ DO nsl = 1, 8
+ IF (SITE_soil_vf_gravels(nsl) + SITE_soil_vf_sand(nsl) > 0.4) THEN
+ SITE_soil_BA_alpha(nsl) = 0.38
+ SITE_soil_BA_beta (nsl) = 35.0
+ ELSEIF (SITE_soil_vf_gravels(nsl) + SITE_soil_vf_sand(nsl) > 0.25) THEN
+ SITE_soil_BA_alpha(nsl) = 0.24
+ SITE_soil_BA_beta (nsl) = 26.0
+ ELSE
+ SITE_soil_BA_alpha(nsl) = 0.20
+ SITE_soil_BA_beta (nsl) = 10.0
+ ENDIF
+ ENDDO
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ u_site_soil_texture = readflag .and. ncio_var_exist(fsrfdata,'soil_texture',readflag)
+ IF (u_site_soil_texture) THEN
+ CALL ncio_read_serial (fsrfdata, 'soil_texture', SITE_soil_texture)
+ ELSE
+ filename = trim(DEF_dir_rawdata)//'/soil/soiltexture_0cm-60cm_mean.nc'
+ CALL read_point_var_2d_int32 (gridsoil, filename, 'soiltexture', &
+ SITE_lon_location, SITE_lat_location, SITE_soil_texture)
+ ENDIF
+ ENDIF
+
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_quartz_mineral : ', SITE_soil_vf_quartz_mineral(1:8), ' (from ',trim(datasource(u_site_vf_quartz_mineral)),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_gravels : ', SITE_soil_vf_gravels (1:8), ' (from ',trim(datasource(u_site_vf_gravels )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_sand : ', SITE_soil_vf_sand (1:8), ' (from ',trim(datasource(u_site_vf_sand )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_clay : ', SITE_soil_vf_clay (1:8), ' (from ',trim(datasource(u_site_vf_clay )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_vf_om : ', SITE_soil_vf_om (1:8), ' (from ',trim(datasource(u_site_vf_om )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_gravels : ', SITE_soil_wf_gravels (1:8), ' (from ',trim(datasource(u_site_wf_gravels )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_sand : ', SITE_soil_wf_sand (1:8), ' (from ',trim(datasource(u_site_wf_sand )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_clay : ', SITE_soil_wf_clay (1:8), ' (from ',trim(datasource(u_site_wf_clay )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_wf_om : ', SITE_soil_wf_om (1:8), ' (from ',trim(datasource(u_site_wf_om )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_OM_density : ', SITE_soil_OM_density (1:8), ' (from ',trim(datasource(u_site_OM_density )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_BD_all : ', SITE_soil_BD_all (1:8), ' (from ',trim(datasource(u_site_BD_all )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_theta_s : ', SITE_soil_theta_s (1:8), ' (from ',trim(datasource(u_site_theta_s )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_k_s : ', SITE_soil_k_s (1:8), ' (from ',trim(datasource(u_site_k_s )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_csol : ', SITE_soil_csol (1:8), ' (from ',trim(datasource(u_site_csol )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_tksatu : ', SITE_soil_tksatu (1:8), ' (from ',trim(datasource(u_site_tksatu )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_tksatf : ', SITE_soil_tksatf (1:8), ' (from ',trim(datasource(u_site_tksatf )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_tkdry : ', SITE_soil_tkdry (1:8), ' (from ',trim(datasource(u_site_tkdry )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_k_solids : ', SITE_soil_k_solids (1:8), ' (from ',trim(datasource(u_site_k_solids )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_psi_s : ', SITE_soil_psi_s (1:8), ' (from ',trim(datasource(u_site_psi_s )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_lambda : ', SITE_soil_lambda (1:8), ' (from ',trim(datasource(u_site_lambda )),')'
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ write(*,'(A,8ES10.2,3A)') 'soil_theta_r : ', SITE_soil_theta_r (1:8), ' (from ',trim(datasource(u_site_theta_r )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_alpha_vgm : ', SITE_soil_alpha_vgm (1:8), ' (from ',trim(datasource(u_site_alpha_vgm )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_L_vgm : ', SITE_soil_L_vgm (1:8), ' (from ',trim(datasource(u_site_L_vgm )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_n_vgm : ', SITE_soil_n_vgm (1:8), ' (from ',trim(datasource(u_site_n_vgm )),')'
+#endif
+ write(*,'(A,8ES10.2,3A)') 'soil_BA_alpha : ', SITE_soil_BA_alpha (1:8), ' (from ',trim(datasource(u_site_BA_alpha )),')'
+ write(*,'(A,8ES10.2,3A)') 'soil_BA_beta : ', SITE_soil_BA_beta (1:8), ' (from ',trim(datasource(u_site_BA_beta )),')'
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ write(*,'(A,I3,3A)') 'soil texture : ', SITE_soil_texture, ' (from ',trim(datasource(u_site_soil_texture)),')'
+ ENDIF
+
+ ! (9) depth to bedrock
+ IF (DEF_USE_BEDROCK) THEN
+ readflag = USE_SITE_dbedrock
+ u_site_dbedrock = readflag .and. ncio_var_exist (fsrfdata, 'depth_to_bedrock',readflag)
+ IF (u_site_dbedrock) THEN
+ CALL ncio_read_serial (fsrfdata, 'depth_to_bedrock', SITE_dbedrock)
+ ELSE
+ CALL gridrock%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/bedrock.nc'
+ CALL read_point_var_2d_real8 (gridrock, filename, 'dbedrock', &
+ SITE_lon_location, SITE_lat_location, SITE_dbedrock)
+ ENDIF
+
+ write(*,'(A,F8.2,3A)') 'Depth to bedrock : ', SITE_dbedrock, ' (from ',datasource(u_site_dbedrock),')'
+ ENDIF
+
+ ! (10) topography
+ readflag = USE_SITE_topography
+
+ u_site_elevation = readflag .and. ncio_var_exist (fsrfdata, 'elevation',readflag)
+ IF (u_site_elevation) THEN
+ CALL ncio_read_serial (fsrfdata, 'elevation', SITE_elevation)
+ ELSE
+ CALL gridtopo%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/elevation.nc'
+ CALL read_point_var_2d_real8 (gridtopo, filename, 'elevation', &
+ SITE_lon_location, SITE_lat_location, SITE_elevation)
+ ENDIF
+
+ u_site_elvstd = readflag &
+ .and. ncio_var_exist (fsrfdata, 'elvstd',readflag)
+ IF (u_site_elvstd) THEN
+ CALL ncio_read_serial (fsrfdata, 'elvstd', SITE_elvstd)
+ ELSE
+ CALL gridtopo%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/topography.nc'
+ CALL read_point_var_2d_real8 (gridtopo, filename, 'elvstd', &
+ SITE_lon_location, SITE_lat_location, SITE_elvstd)
+ ENDIF
+
+ u_site_sloperatio = readflag &
+ .and. ncio_var_exist (fsrfdata, 'sloperatio',readflag)
+ IF (u_site_sloperatio) THEN
+ CALL ncio_read_serial (fsrfdata, 'sloperatio', SITE_sloperatio)
+ ELSE
+ CALL gridtopo%define_by_name ('colm_500m')
+ filename = trim(DEF_dir_rawdata)//'/topography.nc'
+ CALL read_point_var_2d_real8 (gridtopo, filename, 'slope', &
+ SITE_lon_location, SITE_lat_location, SITE_sloperatio)
+ ENDIF
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/slope.nc"
+ IF (ncio_var_exist(filename,'lat') .and. ncio_var_exist(filename,'lon')) THEN
+ CALL grid_topo_factor%define_from_file (filename, "lat", "lon")
+ ENDIF
+
+ u_site_svf = readflag .and. ncio_var_exist (fsrfdata, 'SITE_svf',readflag)
+ IF (u_site_svf) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_svf' , SITE_svf)
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/sky_view_factor.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'svf', &
+ SITE_lon_location, SITE_lat_location, SITE_svf)
+ ENDIF
+
+ u_site_cur = readflag .and. ncio_var_exist (fsrfdata, 'SITE_cur',readflag)
+ IF (u_site_cur) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_cur' , SITE_cur)
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/curvature.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'curvature', &
+ SITE_lon_location, SITE_lat_location, SITE_cur)
+ ENDIF
+
+ u_site_slp_type = readflag &
+ .and. ncio_var_exist (fsrfdata, 'SITE_slp_type' ,readflag) &
+ .and. ncio_var_exist (fsrfdata, 'SITE_asp_type' ,readflag) &
+ .and. ncio_var_exist (fsrfdata, 'SITE_area_type',readflag)
+ u_site_asp_type = u_site_slp_type
+ u_site_area_type = u_site_slp_type
+
+ IF (u_site_slp_type) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_slp_type' , SITE_slp_type )
+ CALL ncio_read_serial (fsrfdata, 'SITE_asp_type' , SITE_asp_type )
+ CALL ncio_read_serial (fsrfdata, 'SITE_area_type', SITE_area_type )
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/slope.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'slope', &
+ SITE_lon_location, SITE_lat_location, slp)
+
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/aspect.nc"
+ CALL read_point_var_2d_real8 (grid_topo_factor, filename, 'aspect', &
+ SITE_lon_location, SITE_lat_location, asp)
+
+ allocate (SITE_slp_type (num_slope_type)); SITE_slp_type (:) = 0.
+ allocate (SITE_asp_type (num_slope_type)); SITE_asp_type (:) = 0.
+ allocate (SITE_area_type (num_slope_type)); SITE_area_type(:) = 0.
+
+ IF ((asp.ge.0 .and. asp.le.90*pi/180) .or. (asp.ge.270*pi/180 .and. asp.le.360*pi/180)) THEN
+ IF ((slp.ge.15*pi/180)) THEN ! north abrupt slope
+ typ = 1
+ ELSE ! north gentle slope
+ typ = 2
+ ENDIF
+ ELSE
+ IF ((slp.ge.15*pi/180)) THEN ! south abrupt slope
+ typ = 3
+ ELSE ! south gentle slope
+ typ = 4
+ ENDIF
+ ENDIF
+
+ SITE_slp_type (typ) = slp
+ SITE_asp_type (typ) = asp
+ SITE_area_type(typ) = 1.
+
+ ENDIF
+
+ u_site_sf_lut = readflag .and. ncio_var_exist (fsrfdata, 'SITE_sf_lut',readflag)
+ IF (u_site_sf_lut) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_sf_lut', SITE_sf_lut)
+ ELSE
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/terrain_elev_angle_front.nc"
+ CALL read_point_var_3d_first_real8 (grid_topo_factor, filename, 'tea_front', &
+ SITE_lon_location, SITE_lat_location, num_azimuth, tea_f)
+
+ filename = trim(DEF_DS_HiresTopographyDataDir)//"/terrain_elev_angle_back.nc"
+ CALL read_point_var_3d_first_real8 (grid_topo_factor, filename, 'tea_back', &
+ SITE_lon_location, SITE_lat_location, num_azimuth, tea_b)
+
+ allocate (SITE_sf_lut (num_azimuth, num_zenith))
+
+ DO a = 1, num_azimuth
+
+ tea_f(a) = asin(max(min(tea_f(a),1.),-1.))
+ tea_b(a) = asin(max(min(tea_b(a),1.),-1.))
+
+ IF (tea_f(a) <= tea_b(a)) tea_f(a) = tea_b(a) + 0.001
+
+ DO z = 1, num_zenith
+ zenith_angle = pi/(2*num_zenith)*(z-1)
+
+ IF (pi*0.5 - zenith_angle < tea_b(a)) THEN
+ SITE_sf_lut(a,z) = 0
+ ELSE IF (pi*0.5 - zenith_angle > tea_f(a)) THEN
+ SITE_sf_lut(a,z) = 1
+ ELSE
+ SITE_sf_lut(a,z) = (0.5*pi - zenith_angle - tea_b(a))/(tea_f(a) - tea_b(a))
+ ENDIF
+
+ ENDDO
+ ENDDO
+
+ ENDIF
+ ENDIF
+
+ write(*,'(A,F8.2,3A)') 'Elevation : ', SITE_elevation, ' (from ',datasource(u_site_elevation),')'
+ write(*,'(A,F8.2,3A)') 'Elv std : ', SITE_elvstd, ' (from ',datasource(u_site_elvstd),')'
+ write(*,'(A,F8.2,3A)') 'SlopeRatio: ', SITE_sloperatio,' (from ',datasource(u_site_sloperatio),')'
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ write(*,'(A,F8.2,3A)') 'Sky view factor : ', SITE_svf, ' (from ',datasource(u_site_svf),')'
+ write(*,'(A,F8.2,3A)') 'Curvature : ', SITE_cur, ' (from ',datasource(u_site_cur),')'
+ write(c,'(I0)') num_slope_type
+ write(*,'(A,'//trim(c)//'F8.2,3A)') 'Slope type : ', SITE_slp_type, ' (from ',datasource(u_site_slp_type),')'
+ write(*,'(A,'//trim(c)//'F8.2,3A)') 'Aspect type : ', SITE_asp_type, ' (from ',datasource(u_site_slp_type),')'
+ write(*,'(A,'//trim(c)//'F8.2,3A)') 'Slope type area : ', SITE_area_type, ' (from ',datasource(u_site_slp_type),')'
+ write(c,'(I0)') num_azimuth*num_zenith
+ write(*,'(A,A,I3,A,I3,A,'//trim(c)//'F8.2,3A)') 'Shadow lookup table : ', &
+ '(', num_azimuth, ' in azimuth,', num_zenith, ' in zenith)', &
+ SITE_sf_lut , ' (from ',datasource(u_site_sf_lut),')'
+ ENDIF
+
+ ELSE
+ CALL ncio_read_serial (fsrfdata, 'LAI_year' , SITE_LAI_year )
+ CALL ncio_read_serial (fsrfdata, 'TREE_LAI' , SITE_LAI_monthly)
+ CALL ncio_read_serial (fsrfdata, 'TREE_SAI' , SITE_SAI_monthly)
+
+ CALL ncio_read_serial (fsrfdata, 'URBAN_TYPE' , SITE_urbtyp )
+ CALL ncio_read_serial (fsrfdata, 'LUCY_id' , SITE_lucyid )
+ CALL ncio_read_serial (fsrfdata, 'PCT_Tree' , SITE_fveg_urb )
+ CALL ncio_read_serial (fsrfdata, 'URBAN_TREE_TOP', SITE_htop_urb )
+ CALL ncio_read_serial (fsrfdata, 'PCT_Water' , SITE_flake_urb )
+ CALL ncio_read_serial (fsrfdata, 'WT_ROOF' , SITE_froof )
+ CALL ncio_read_serial (fsrfdata, 'HT_ROOF' , SITE_hroof )
+ CALL ncio_read_serial (fsrfdata, 'WTROAD_PERV' , SITE_fgper )
+ CALL ncio_read_serial (fsrfdata, 'BUILDING_HLR' , SITE_hlr )
+ CALL ncio_read_serial (fsrfdata, 'POP_DEN' , SITE_popden )
+
+ CALL ncio_read_serial (fsrfdata, 'EM_ROOF' , SITE_em_roof )
+ CALL ncio_read_serial (fsrfdata, 'EM_WALL' , SITE_em_wall )
+ CALL ncio_read_serial (fsrfdata, 'EM_IMPROAD' , SITE_em_gimp )
+ CALL ncio_read_serial (fsrfdata, 'EM_PERROAD' , SITE_em_gper )
+ CALL ncio_read_serial (fsrfdata, 'T_BUILDING_MAX', SITE_t_roommax )
+ CALL ncio_read_serial (fsrfdata, 'T_BUILDING_MIN', SITE_t_roommin )
+ CALL ncio_read_serial (fsrfdata, 'THICK_ROOF' , SITE_thickroof )
+ CALL ncio_read_serial (fsrfdata, 'THICK_WALL' , SITE_thickwall )
+
+ CALL ncio_read_serial (fsrfdata, 'ALB_ROOF' , SITE_alb_roof )
+ CALL ncio_read_serial (fsrfdata, 'ALB_WALL' , SITE_alb_wall )
+ CALL ncio_read_serial (fsrfdata, 'ALB_IMPROAD' , SITE_alb_gimp )
+ CALL ncio_read_serial (fsrfdata, 'ALB_PERROAD' , SITE_alb_gper )
+
+ CALL ncio_read_serial (fsrfdata, 'CV_ROOF' , SITE_cv_roof )
+ CALL ncio_read_serial (fsrfdata, 'CV_WALL' , SITE_cv_wall )
+ CALL ncio_read_serial (fsrfdata, 'CV_IMPROAD' , SITE_cv_gimp )
+ CALL ncio_read_serial (fsrfdata, 'TK_ROOF' , SITE_tk_roof )
+ CALL ncio_read_serial (fsrfdata, 'TK_WALL' , SITE_tk_wall )
+ CALL ncio_read_serial (fsrfdata, 'TK_IMPROAD' , SITE_tk_gimp )
+
+ CALL ncio_read_serial (fsrfdata, 'lakedepth' , SITE_lakedepth )
+
+ CALL ncio_read_serial (fsrfdata, 'soil_s_v_alb' , SITE_soil_s_v_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_d_v_alb' , SITE_soil_d_v_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_s_n_alb' , SITE_soil_s_n_alb)
+ CALL ncio_read_serial (fsrfdata, 'soil_d_n_alb' , SITE_soil_d_n_alb)
+
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_quartz_mineral', SITE_soil_vf_quartz_mineral)
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_gravels' , SITE_soil_vf_gravels )
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_sand' , SITE_soil_vf_sand )
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_clay' , SITE_soil_vf_clay )
+ CALL ncio_read_serial (fsrfdata, 'soil_vf_om' , SITE_soil_vf_om )
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_gravels' , SITE_soil_wf_gravels )
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_sand' , SITE_soil_wf_sand )
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_clay' , SITE_soil_wf_clay )
+ CALL ncio_read_serial (fsrfdata, 'soil_wf_om' , SITE_soil_wf_om )
+
+ CALL ncio_read_serial (fsrfdata, 'soil_OM_density' , SITE_soil_OM_density)
+ CALL ncio_read_serial (fsrfdata, 'soil_BD_all' , SITE_soil_BD_all )
+ CALL ncio_read_serial (fsrfdata, 'soil_theta_s' , SITE_soil_theta_s )
+ CALL ncio_read_serial (fsrfdata, 'soil_k_s' , SITE_soil_k_s )
+ CALL ncio_read_serial (fsrfdata, 'soil_csol' , SITE_soil_csol )
+ CALL ncio_read_serial (fsrfdata, 'soil_tksatu' , SITE_soil_tksatu )
+ CALL ncio_read_serial (fsrfdata, 'soil_tksatf' , SITE_soil_tksatf )
+ CALL ncio_read_serial (fsrfdata, 'soil_tkdry' , SITE_soil_tkdry )
+ CALL ncio_read_serial (fsrfdata, 'soil_k_solids' , SITE_soil_k_solids )
+ CALL ncio_read_serial (fsrfdata, 'soil_lambda' , SITE_soil_lambda )
+ CALL ncio_read_serial (fsrfdata, 'soil_psi_s' , SITE_soil_psi_s )
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ CALL ncio_read_serial (fsrfdata, 'soil_theta_r' , SITE_soil_theta_r )
+ CALL ncio_read_serial (fsrfdata, 'soil_alpha_vgm', SITE_soil_alpha_vgm)
+ CALL ncio_read_serial (fsrfdata, 'soil_L_vgm' , SITE_soil_L_vgm )
+ CALL ncio_read_serial (fsrfdata, 'soil_n_vgm' , SITE_soil_n_vgm )
+#endif
+
+ CALL ncio_read_serial (fsrfdata, 'soil_BA_alpha', SITE_soil_BA_alpha)
+ CALL ncio_read_serial (fsrfdata, 'soil_BA_beta' , SITE_soil_BA_beta )
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ CALL ncio_read_serial (fsrfdata, 'soil_texture', SITE_soil_texture)
+ ENDIF
+
+ IF(DEF_USE_BEDROCK)THEN
+ CALL ncio_read_serial (fsrfdata, 'depth_to_bedrock', SITE_dbedrock)
+ ENDIF
+
+ CALL ncio_read_serial (fsrfdata, 'elevation' , SITE_elevation )
+ CALL ncio_read_serial (fsrfdata, 'elvstd' , SITE_elvstd )
+ CALL ncio_read_serial (fsrfdata, 'sloperatio', SITE_sloperatio)
+
+ ! used for downscaling
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL ncio_read_serial (fsrfdata, 'SITE_svf' , SITE_svf )
+ CALL ncio_read_serial (fsrfdata, 'SITE_cur' , SITE_cur )
+ CALL ncio_read_serial (fsrfdata, 'SITE_sf_lut' , SITE_sf_lut )
+ CALL ncio_read_serial (fsrfdata, 'SITE_slp_type' , SITE_slp_type )
+ CALL ncio_read_serial (fsrfdata, 'SITE_asp_type' , SITE_asp_type )
+ CALL ncio_read_serial (fsrfdata, 'SITE_area_type', SITE_area_type)
+ ENDIF
+ ENDIF
+
+ IF (.not. for_surface_build) THEN
+
+ landpatch%nset = numpatch
+
+ allocate (landpatch%settyp (numpatch)); landpatch%settyp = SITE_landtype
+
+ landpatch%nblkgrp = 1
+ allocate (landpatch%xblkgrp(1)); landpatch%xblkgrp(1) = 1
+ allocate (landpatch%yblkgrp(1)); landpatch%yblkgrp(1) = 1
+
+ allocate (landpatch%vecgs%vlen(1,1)); landpatch%vecgs%vlen(1,1) = numpatch
+ allocate (landpatch%vecgs%vstt(1,1)); landpatch%vecgs%vstt(1,1) = 1
+ allocate (landpatch%vecgs%vend(1,1)); landpatch%vecgs%vend(1,1) = numpatch
+
+ landurban%nset = numurban
+
+ allocate (landurban%settyp (numurban)); landurban%settyp = SITE_urbtyp
+
+ landurban%nblkgrp = 1
+ allocate (landurban%xblkgrp(1)); landurban%xblkgrp(1) = 1
+ allocate (landurban%yblkgrp(1)); landurban%yblkgrp(1) = 1
+
+ allocate (landurban%vecgs%vlen(1,1)); landurban%vecgs%vlen(1,1) = numurban
+ allocate (landurban%vecgs%vstt(1,1)); landurban%vecgs%vstt(1,1) = 1
+ allocate (landurban%vecgs%vend(1,1)); landurban%vecgs%vend(1,1) = numurban
+
+ allocate (patch2urban (numurban)); patch2urban(1) = 1
+ allocate (urban2patch (numurban)); urban2patch(1) = 1
+
+ numelm = 1
+ allocate (landelm%settyp (1)); landelm%settyp (1) = 0
+ allocate (elm_patch%substt (1)); elm_patch%substt(1) = 1
+ allocate (elm_patch%subend (1)); elm_patch%subend(1) = numpatch
+ allocate (elm_patch%subfrc (numpatch)); elm_patch%subfrc = 1./numpatch
+
+ ENDIF
+
+ END SUBROUTINE read_urban_surface_data_single
+
+
+!-----------------------------------------------------------------------
+ SUBROUTINE write_surface_data_single (numpatch, numpft)
+
+ USE MOD_NetCDFSerial
+ USE MOD_Namelist
+ USE MOD_Const_LC
+ IMPLICIT NONE
+
+ integer, intent(in) :: numpatch
+ integer, intent(in), optional :: numpft
+
+ ! Local Variables
+ character(len=256) :: fsrfdata
+ integer :: ipft, iyear, itime
+ character(len=18) :: source
+
+ fsrfdata = trim(DEF_dir_landdata) // '/srfdata.nc'
+
+ CALL ncio_create_file (fsrfdata)
+
+ CALL ncio_define_dimension (fsrfdata, 'patch', numpatch)
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (numpft > 0) THEN
+ CALL ncio_define_dimension (fsrfdata, 'pft', numpft)
+ ENDIF
+#endif
+
+ CALL ncio_define_dimension (fsrfdata, 'LAI_year', size(SITE_LAI_year))
+ IF (DEF_LAI_MONTHLY) THEN
+ CALL ncio_define_dimension (fsrfdata, 'month', 12)
+ ELSE
+ CALL ncio_define_dimension (fsrfdata, 'J8day', 46)
+ ENDIF
+
+ CALL ncio_define_dimension (fsrfdata, 'soil', 8)
+
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL ncio_define_dimension (fsrfdata, 'slope_type', num_slope_type)
+ CALL ncio_define_dimension (fsrfdata, 'azi', num_azimuth)
+ CALL ncio_define_dimension (fsrfdata, 'zen', num_zenith)
+ ENDIF
+
+
+ CALL ncio_write_serial (fsrfdata, 'latitude', SITE_lat_location)
+ CALL ncio_put_attr (fsrfdata, 'latitude', 'units', 'degrees_north')
+
+ CALL ncio_write_serial (fsrfdata, 'longitude', SITE_lon_location)
+ CALL ncio_put_attr (fsrfdata, 'longitude','units', 'degrees_east')
+
+#ifdef LULC_USGS
+ CALL ncio_write_serial (fsrfdata, 'USGS_classification', SITE_landtype)
+ CALL ncio_put_attr (fsrfdata, 'USGS_classification', 'source', trim(datasource(u_site_landtype)))
+ CALL ncio_put_attr (fsrfdata, 'USGS_classification', 'long_name', 'GLCC USGS Land Use/Land Cover')
+#else
+ CALL ncio_write_serial (fsrfdata, 'IGBP_classification', SITE_landtype)
+ CALL ncio_put_attr (fsrfdata, 'IGBP_classification', 'source', trim(datasource(u_site_landtype)))
+ CALL ncio_put_attr (fsrfdata, 'IGBP_classification', 'long_name', 'MODIS IGBP Land Use/Land Cover')
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (numpft > 0) THEN
+ CALL ncio_write_serial (fsrfdata, 'pfttyp', SITE_pfttyp, 'pft')
+ CALL ncio_put_attr (fsrfdata, 'pfttyp', 'source', trim(datasource(u_site_pfts)))
+ CALL ncio_put_attr (fsrfdata, 'pfttyp', 'long_name', 'plant functional type')
+
+ CALL ncio_write_serial (fsrfdata, 'pctpfts', SITE_pctpfts, 'pft')
+ CALL ncio_put_attr (fsrfdata, 'pctpfts', 'source', trim(datasource(u_site_pfts)))
+ CALL ncio_put_attr (fsrfdata, 'pctpfts', 'long_name', 'fraction of plant functional type')
+ ENDIF
+#endif
+#if (defined CROP)
+ IF (SITE_landtype == CROPLAND) THEN
+ CALL ncio_write_serial (fsrfdata, 'croptyp', SITE_croptyp, 'patch')
+ CALL ncio_put_attr (fsrfdata, 'croptyp', 'source', trim(datasource(u_site_crop)))
+ CALL ncio_put_attr (fsrfdata, 'croptyp', 'long_name', 'crop type')
+
+ CALL ncio_write_serial (fsrfdata, 'pctcrop', SITE_pctcrop, 'patch')
+ CALL ncio_put_attr (fsrfdata, 'pctcrop', 'source', trim(datasource(u_site_crop)))
+ CALL ncio_put_attr (fsrfdata, 'pctcrop', 'long_name', 'fraction of crop type')
+ ENDIF
+#endif
+
+ CALL ncio_write_serial (fsrfdata, 'canopy_height', SITE_htop)
+ CALL ncio_put_attr (fsrfdata, 'canopy_height', 'source', trim(datasource(u_site_htop)))
+ CALL ncio_put_attr (fsrfdata, 'canopy_height', 'long_name', 'canopy height')
+ CALL ncio_put_attr (fsrfdata, 'canopy_height', 'units', 'm')
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (numpft > 0) THEN
+ CALL ncio_write_serial (fsrfdata, 'canopy_height_pfts', SITE_htop_pfts, 'pft')
+ CALL ncio_put_attr (fsrfdata, 'canopy_height_pfts', 'source', trim(datasource(u_site_htop)))
+ CALL ncio_put_attr (fsrfdata, 'canopy_height_pfts', 'long_name', 'canopy height')
+ CALL ncio_put_attr (fsrfdata, 'canopy_height_pfts', 'units', 'm')
+ ENDIF
+#endif
+
+ source = trim(datasource(u_site_lai))
+ CALL ncio_write_serial (fsrfdata, 'LAI_year', SITE_LAI_year, 'LAI_year')
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (numpft > 0) THEN
+ CALL ncio_write_serial (fsrfdata, 'LAI_pfts_monthly', SITE_LAI_pfts_monthly, 'pft', 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'LAI_pfts_monthly', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'LAI_pfts_monthly', 'long_name', 'monthly leaf area index associated with PFT')
+
+ CALL ncio_write_serial (fsrfdata, 'SAI_pfts_monthly', SITE_SAI_pfts_monthly, 'pft', 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'SAI_pfts_monthly', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'SAI_pfts_monthly', 'long_name', 'monthly stem area index associated with PFT')
+ ELSE
+ CALL ncio_write_serial (fsrfdata, 'LAI_monthly', SITE_LAI_monthly, 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'LAI_monthly', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'LAI_monthly', 'long_name', 'monthly leaf area index')
+
+ CALL ncio_write_serial (fsrfdata, 'SAI_monthly', SITE_SAI_monthly, 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'SAI_monthly', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'SAI_monthly', 'long_name', 'monthly stem area index')
+ ENDIF
+#else
+ IF (DEF_LAI_MONTHLY) THEN
+ CALL ncio_write_serial (fsrfdata, 'LAI_monthly', SITE_LAI_monthly, 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'LAI_monthly', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'LAI_monthly', 'long_name', 'monthly leaf area index')
+
+ CALL ncio_write_serial (fsrfdata, 'SAI_monthly', SITE_SAI_monthly, 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'SAI_monthly', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'SAI_monthly', 'long_name', 'monthly stem area index')
+ ELSE
+ CALL ncio_write_serial (fsrfdata, 'LAI_8day', SITE_LAI_8day, 'J8day', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'LAI_8day', 'source', source)
+ CALL ncio_put_attr (fsrfdata, 'LAI_8day', 'long_name', '8-day leaf area index')
+ ENDIF
+#endif
+
+ CALL ncio_write_serial (fsrfdata, 'lakedepth', SITE_lakedepth)
+ CALL ncio_put_attr (fsrfdata, 'lakedepth', 'source', trim(datasource(u_site_lakedepth)))
+ CALL ncio_put_attr (fsrfdata, 'lakedepth', 'long_name', 'lake depth')
+ CALL ncio_put_attr (fsrfdata, 'lakedepth', 'units', 'm')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_s_v_alb', SITE_soil_s_v_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_s_v_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_s_v_alb', 'long_name', 'albedo of visible of the saturated soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_d_v_alb', SITE_soil_d_v_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_d_v_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_d_v_alb', 'long_name', 'albedo of visible of the dry soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_s_n_alb', SITE_soil_s_n_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_s_n_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_s_n_alb', 'long_name', 'albedo of near infrared of the saturated soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_d_n_alb', SITE_soil_d_n_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_d_n_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_d_n_alb', 'long_name', 'albedo of near infrared of the dry soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_quartz_mineral', SITE_soil_vf_quartz_mineral(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_quartz_mineral', 'source', trim(datasource(u_site_vf_quartz_mineral)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_quartz_mineral', 'long_name', 'volumetric fraction of quartz within mineral soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_gravels', SITE_soil_vf_gravels(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_gravels', 'source', trim(datasource(u_site_vf_gravels)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_gravels', 'long_name', 'volumetric fraction of gravels')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_sand', SITE_soil_vf_sand(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_sand', 'source', trim(datasource(u_site_vf_sand)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_sand', 'long_name', 'volumetric fraction of sand')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_clay', SITE_soil_vf_clay(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_clay', 'source', trim(datasource(u_site_vf_clay)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_clay', 'long_name', 'volumetric fraction of clay')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_om', SITE_soil_vf_om(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_om', 'source', trim(datasource(u_site_vf_om)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_om', 'long_name', 'volumetric fraction of organic matter')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_gravels', SITE_soil_wf_gravels(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_gravels', 'source', trim(datasource(u_site_wf_gravels)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_gravels', 'long_name', 'gravimetric fraction of gravels')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_sand', SITE_soil_wf_sand(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_sand', 'source', trim(datasource(u_site_wf_sand)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_sand', 'long_name', 'gravimetric fraction of sand')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_clay', SITE_soil_wf_clay(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_clay', 'source', trim(datasource(u_site_wf_clay)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_clay', 'long_name', 'gravimetric fraction of clay')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_om', SITE_soil_wf_om(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_om', 'source', trim(datasource(u_site_wf_om)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_om', 'long_name', 'gravimetric fraction of om')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_OM_density', SITE_soil_OM_density(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_OM_density', 'source', trim(datasource(u_site_OM_density)))
+ CALL ncio_put_attr (fsrfdata, 'soil_OM_density', 'long_name', 'OM density')
+ CALL ncio_put_attr (fsrfdata, 'soil_OM_density', 'units', 'kg/m3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_BD_all', SITE_soil_BD_all(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_BD_all', 'source', trim(datasource(u_site_BD_all)))
+ CALL ncio_put_attr (fsrfdata, 'soil_BD_all', 'long_name', 'bulk density of soil (GRAVELS + OM + mineral soils)')
+ CALL ncio_put_attr (fsrfdata, 'soil_BD_all', 'units', 'kg/m3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_theta_s', SITE_soil_theta_s(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_s', 'source', trim(datasource(u_site_theta_s)))
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_s', 'long_name', 'saturated water content')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_s', 'units', 'cm3/cm3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_k_s', SITE_soil_k_s(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_s', 'source', trim(datasource(u_site_k_s)))
+ CALL ncio_put_attr (fsrfdata, 'soil_k_s', 'long_name', 'saturated hydraulic conductivity')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_s', 'units', 'cm/day')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_csol', SITE_soil_csol(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_csol', 'source', trim(datasource(u_site_csol)))
+ CALL ncio_put_attr (fsrfdata, 'soil_csol', 'long_name', 'heat capacity of soil solids')
+ CALL ncio_put_attr (fsrfdata, 'soil_csol', 'units', 'J/(m3 K)')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_tksatu', SITE_soil_tksatu(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatu', 'source', trim(datasource(u_site_tksatu)))
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatu', 'long_name', 'thermal conductivity of saturated unfrozen soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatu', 'units', 'W/m-K')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_tksatf', SITE_soil_tksatf(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatf', 'source', trim(datasource(u_site_tksatf)))
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatf', 'long_name', 'thermal conductivity of saturated frozen soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatf', 'units', 'W/m-K')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_tkdry', SITE_soil_tkdry(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tkdry', 'source', trim(datasource(u_site_tkdry)))
+ CALL ncio_put_attr (fsrfdata, 'soil_tkdry', 'long_name', 'thermal conductivity for dry soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tkdry', 'units', 'W/(m-K)')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_k_solids', SITE_soil_k_solids(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_solids', 'source', trim(datasource(u_site_k_solids)))
+ CALL ncio_put_attr (fsrfdata, 'soil_k_solids', 'long_name', 'thermal conductivity of minerals soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_solids', 'units', 'W/m-K')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_lambda', SITE_soil_lambda(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_lambda', 'source', trim(datasource(u_site_lambda)))
+ CALL ncio_put_attr (fsrfdata, 'soil_lambda', 'long_name', 'pore size distribution index (dimensionless)')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_psi_s', SITE_soil_psi_s(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_psi_s ', 'source', trim(datasource(u_site_psi_s)))
+ CALL ncio_put_attr (fsrfdata, 'soil_psi_s ', 'long_name', 'matric potential at saturation')
+ CALL ncio_put_attr (fsrfdata, 'soil_psi_s ', 'units', 'cm')
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ CALL ncio_write_serial (fsrfdata, 'soil_theta_r', SITE_soil_theta_r(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_r', 'source', trim(datasource(u_site_theta_r)))
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_r', 'long_name', 'residual water content')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_r', 'units', 'cm3/cm3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_alpha_vgm', SITE_soil_alpha_vgm(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_alpha_vgm', 'source', trim(datasource(u_site_alpha_vgm)))
+ CALL ncio_put_attr (fsrfdata, 'soil_alpha_vgm', 'long_name', 'a parameter corresponding approximately to the inverse of the air-entry value')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_L_vgm', SITE_soil_L_vgm(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_L_vgm', 'source', trim(datasource(u_site_L_vgm)))
+ CALL ncio_put_attr (fsrfdata, 'soil_L_vgm', 'long_name', 'pore-connectivity parameter [dimensionless]')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_n_vgm', SITE_soil_n_vgm(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_n_vgm', 'source', trim(datasource(u_site_n_vgm)))
+ CALL ncio_put_attr (fsrfdata, 'soil_n_vgm', 'long_name', 'a shape parameter [dimensionless]')
+
+#endif
+
+ CALL ncio_write_serial (fsrfdata, 'soil_BA_alpha', SITE_soil_BA_alpha(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_alpha', 'source', trim(datasource(u_site_BA_alpha)))
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_alpha', 'long_name', 'alpha in Balland and Arp(2005) thermal conductivity scheme')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_BA_beta', SITE_soil_BA_beta(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_beta', 'source', trim(datasource(u_site_BA_beta)))
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_beta', 'long_name', 'beta in Balland and Arp(2005) thermal conductivity scheme')
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ CALL ncio_write_serial (fsrfdata, 'soil_texture ', SITE_soil_texture)
+ CALL ncio_put_attr (fsrfdata, 'soil_texture ', 'source', trim(datasource(u_site_soil_texture)))
+ CALL ncio_put_attr (fsrfdata, 'soil_texture ', 'long_name', 'USDA soil texture')
+ ENDIF
+
+ IF(DEF_USE_BEDROCK)THEN
+ CALL ncio_write_serial (fsrfdata, 'depth_to_bedrock', SITE_dbedrock)
+ CALL ncio_put_attr (fsrfdata, 'depth_to_bedrock', 'source', trim(datasource(u_site_dbedrock)))
+ ENDIF
+
+ CALL ncio_write_serial (fsrfdata, 'elevation', SITE_elevation)
+ CALL ncio_put_attr (fsrfdata, 'elevation', 'source', trim(datasource(u_site_elevation)))
+
+ CALL ncio_write_serial (fsrfdata, 'elvstd', SITE_elvstd)
+ CALL ncio_put_attr (fsrfdata, 'elvstd', 'source', trim(datasource(u_site_elvstd)))
+ CALL ncio_put_attr (fsrfdata, 'elvstd', 'long_name', 'standard deviation of elevation')
+
+ CALL ncio_write_serial (fsrfdata, 'sloperatio', SITE_sloperatio)
+ CALL ncio_put_attr (fsrfdata, 'sloperatio', 'source', trim(datasource(u_site_sloperatio)))
+ CALL ncio_put_attr (fsrfdata, 'sloperatio', 'long_name', 'slope ratio')
+
+ ! used for downscaling
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL ncio_write_serial (fsrfdata, 'SITE_svf', SITE_svf)
+ CALL ncio_put_attr (fsrfdata, 'SITE_svf','source', trim(datasource(u_site_svf)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_svf','long_name', 'sky view factor')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_cur', SITE_cur)
+ CALL ncio_put_attr (fsrfdata, 'SITE_cur','source', trim(datasource(u_site_cur)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_cur','long_name', 'curvature')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_sf_lut', SITE_sf_lut, 'azi', 'zen')
+ CALL ncio_put_attr (fsrfdata, 'SITE_sf_lut','source', trim(datasource(u_site_sf_lut)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_sf_lut','long_name', 'look up table of shadow factor')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_slp_type' , SITE_slp_type , 'type')
+ CALL ncio_put_attr (fsrfdata, 'SITE_slp_type','source', trim(datasource(u_site_slp_type)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_slp_type','long_name', 'topographic slope of each character')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_asp_type' , SITE_asp_type , 'type')
+ CALL ncio_put_attr (fsrfdata, 'SITE_asp_type','source', trim(datasource(u_site_asp_type)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_asp_type','long_name', 'topographic aspect of each character')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_area_type', SITE_area_type, 'type')
+ CALL ncio_put_attr (fsrfdata, 'SITE_area_type','source', trim(datasource(u_site_area_type)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_area_type','long_name', 'area percentage of each character')
+ ENDIF
+
+ END SUBROUTINE write_surface_data_single
+
+
+!-----------------------------------------------------------------------
+ SUBROUTINE write_urban_surface_data_single (numurban)
+
+ USE MOD_NetCDFSerial
+ USE MOD_Namelist
+ USE MOD_Const_LC
+ IMPLICIT NONE
+
+ integer, intent(in) :: numurban
+
+ ! Local Variables
+ character(len=256) :: fsrfdata
+ integer :: iyear, itime
+ character(len=8) :: source
+
+ fsrfdata = trim(DEF_dir_landdata) // '/srfdata.nc'
+
+ SITE_fgper = 1 - (SITE_fgimp-SITE_froof)/(1-SITE_froof-SITE_flake_urb)
+ SITE_froof = SITE_froof/(1-SITE_flake_urb)
+ SITE_fveg_urb = SITE_fveg_urb * 100
+ SITE_flake_urb = SITE_flake_urb * 100
+
+ CALL ncio_create_file (fsrfdata)
+
+ CALL ncio_define_dimension (fsrfdata, 'soil', 8)
+
+ CALL ncio_define_dimension (fsrfdata, 'azi', num_azimuth)
+ CALL ncio_define_dimension (fsrfdata, 'zen', num_zenith)
+ CALL ncio_define_dimension (fsrfdata, 'slope_type', num_slope_type)
+
+ CALL ncio_define_dimension (fsrfdata, 'patch', numurban)
+
+ CALL ncio_define_dimension (fsrfdata, 'LAI_year', size(SITE_LAI_year))
+ CALL ncio_define_dimension (fsrfdata, 'month', 12)
+
+ CALL ncio_define_dimension (fsrfdata, 'ulev' , 10)
+ CALL ncio_define_dimension (fsrfdata, 'numsolar', 2 )
+ CALL ncio_define_dimension (fsrfdata, 'numrad' , 2 )
+
+ CALL ncio_write_serial (fsrfdata, 'latitude' , SITE_lat_location)
+ CALL ncio_write_serial (fsrfdata, 'longitude', SITE_lon_location)
+
+ CALL ncio_write_serial (fsrfdata, 'LAI_year', SITE_LAI_year, 'LAI_year')
+ CALL ncio_write_serial (fsrfdata, 'TREE_LAI', SITE_LAI_monthly, 'month', 'LAI_year')
+ CALL ncio_write_serial (fsrfdata, 'TREE_SAI', SITE_SAI_monthly, 'month', 'LAI_year')
+ CALL ncio_put_attr (fsrfdata, 'TREE_LAI', 'source', trim(datasource(u_site_urblai)))
+ CALL ncio_put_attr (fsrfdata, 'TREE_SAI', 'source', trim(datasource(u_site_urbsai)))
+
+ CALL ncio_write_serial (fsrfdata, 'URBAN_TYPE' , SITE_urbtyp )
+ CALL ncio_write_serial (fsrfdata, 'LUCY_id' , SITE_lucyid )
+ CALL ncio_write_serial (fsrfdata, 'PCT_Tree' , SITE_fveg_urb )
+ CALL ncio_write_serial (fsrfdata, 'URBAN_TREE_TOP', SITE_htop_urb )
+ CALL ncio_write_serial (fsrfdata, 'PCT_Water' , SITE_flake_urb )
+ CALL ncio_write_serial (fsrfdata, 'WT_ROOF' , SITE_froof )
+ CALL ncio_write_serial (fsrfdata, 'HT_ROOF' , SITE_hroof )
+ CALL ncio_write_serial (fsrfdata, 'WTROAD_PERV' , SITE_fgper )
+ CALL ncio_write_serial (fsrfdata, 'BUILDING_HLR' , SITE_hlr )
+ CALL ncio_write_serial (fsrfdata, 'POP_DEN' , SITE_popden )
+
+ CALL ncio_put_attr (fsrfdata, 'PCT_Tree' , 'source', trim(datasource(u_site_fveg )))
+ CALL ncio_put_attr (fsrfdata, 'URBAN_TREE_TOP', 'source', trim(datasource(u_site_htopu)))
+ CALL ncio_put_attr (fsrfdata, 'PCT_Water' , 'source', trim(datasource(u_site_flake)))
+ CALL ncio_put_attr (fsrfdata, 'WT_ROOF' , 'source', trim(datasource(u_site_froof)))
+ CALL ncio_put_attr (fsrfdata, 'HT_ROOF' , 'source', trim(datasource(u_site_hroof)))
+ CALL ncio_put_attr (fsrfdata, 'WTROAD_PERV' , 'source', trim(datasource(u_site_fgper)))
+ CALL ncio_put_attr (fsrfdata, 'BUILDING_HLR' , 'source', trim(datasource(u_site_hlr )))
+ CALL ncio_put_attr (fsrfdata, 'POP_DEN' , 'source', trim(datasource(u_site_pop )))
+
+ CALL ncio_write_serial (fsrfdata, 'EM_ROOF' , SITE_em_roof )
+ CALL ncio_write_serial (fsrfdata, 'EM_WALL' , SITE_em_wall )
+ CALL ncio_write_serial (fsrfdata, 'EM_IMPROAD' , SITE_em_gimp )
+ CALL ncio_write_serial (fsrfdata, 'EM_PERROAD' , SITE_em_gper )
+ CALL ncio_write_serial (fsrfdata, 'T_BUILDING_MAX', SITE_t_roommax )
+ CALL ncio_write_serial (fsrfdata, 'T_BUILDING_MIN', SITE_t_roommin )
+ CALL ncio_write_serial (fsrfdata, 'THICK_ROOF' , SITE_thickroof )
+ CALL ncio_write_serial (fsrfdata, 'THICK_WALL' , SITE_thickwall )
+
+ CALL ncio_put_attr (fsrfdata, 'EM_ROOF' , 'source', trim(datasource(u_site_emr )))
+ CALL ncio_put_attr (fsrfdata, 'EM_WALL' , 'source', trim(datasource(u_site_emw )))
+ CALL ncio_put_attr (fsrfdata, 'EM_IMPROAD' , 'source', trim(datasource(u_site_emgimp)))
+ CALL ncio_put_attr (fsrfdata, 'EM_PERROAD' , 'source', trim(datasource(u_site_emgper)))
+ CALL ncio_put_attr (fsrfdata, 'T_BUILDING_MAX', 'source', trim(datasource(u_site_tbmax )))
+ CALL ncio_put_attr (fsrfdata, 'T_BUILDING_MIN', 'source', trim(datasource(u_site_tbmin )))
+ CALL ncio_put_attr (fsrfdata, 'THICK_ROOF' , 'source', trim(datasource(u_site_thickr)))
+ CALL ncio_put_attr (fsrfdata, 'THICK_WALL' , 'source', trim(datasource(u_site_thickw)))
+
+ CALL ncio_write_serial (fsrfdata, 'ALB_ROOF' , SITE_alb_roof , 'numrad', 'numsolar')
+ CALL ncio_write_serial (fsrfdata, 'ALB_WALL' , SITE_alb_wall , 'numrad', 'numsolar')
+ CALL ncio_write_serial (fsrfdata, 'ALB_IMPROAD' , SITE_alb_gimp , 'numrad', 'numsolar')
+ CALL ncio_write_serial (fsrfdata, 'ALB_PERROAD' , SITE_alb_gper , 'numrad', 'numsolar')
+
+ CALL ncio_put_attr (fsrfdata, 'ALB_ROOF' , 'source', trim(datasource(u_site_albr )))
+ CALL ncio_put_attr (fsrfdata, 'ALB_WALL' , 'source', trim(datasource(u_site_albw )))
+ CALL ncio_put_attr (fsrfdata, 'ALB_IMPROAD' , 'source', trim(datasource(u_site_albgimp)))
+ CALL ncio_put_attr (fsrfdata, 'ALB_PERROAD' , 'source', trim(datasource(u_site_albgper)))
+
+ CALL ncio_write_serial (fsrfdata, 'CV_ROOF' , SITE_cv_roof , 'ulev')
+ CALL ncio_write_serial (fsrfdata, 'CV_WALL' , SITE_cv_wall , 'ulev')
+ CALL ncio_write_serial (fsrfdata, 'CV_IMPROAD' , SITE_cv_gimp , 'ulev')
+ CALL ncio_write_serial (fsrfdata, 'TK_ROOF' , SITE_tk_roof , 'ulev')
+ CALL ncio_write_serial (fsrfdata, 'TK_WALL' , SITE_tk_wall , 'ulev')
+ CALL ncio_write_serial (fsrfdata, 'TK_IMPROAD' , SITE_tk_gimp , 'ulev')
+
+ CALL ncio_put_attr (fsrfdata, 'CV_ROOF' , 'source', trim(datasource(u_site_cvr )))
+ CALL ncio_put_attr (fsrfdata, 'CV_WALL' , 'source', trim(datasource(u_site_cvw )))
+ CALL ncio_put_attr (fsrfdata, 'CV_IMPROAD' , 'source', trim(datasource(u_site_cvgimp)))
+ CALL ncio_put_attr (fsrfdata, 'TK_ROOF' , 'source', trim(datasource(u_site_tkr )))
+ CALL ncio_put_attr (fsrfdata, 'TK_WALL' , 'source', trim(datasource(u_site_tkw )))
+ CALL ncio_put_attr (fsrfdata, 'TK_IMPROAD' , 'source', trim(datasource(u_site_tkgimp)))
+
+ CALL ncio_write_serial (fsrfdata, 'lakedepth', SITE_lakedepth)
+ CALL ncio_put_attr (fsrfdata, 'lakedepth', 'source', trim(datasource(u_site_lakedepth)))
+ CALL ncio_put_attr (fsrfdata, 'lakedepth', 'long_name', 'lake depth')
+ CALL ncio_put_attr (fsrfdata, 'lakedepth', 'units', 'm')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_s_v_alb', SITE_soil_s_v_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_s_v_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_s_v_alb', 'long_name', 'albedo of visible of the saturated soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_d_v_alb', SITE_soil_d_v_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_d_v_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_d_v_alb', 'long_name', 'albedo of visible of the dry soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_s_n_alb', SITE_soil_s_n_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_s_n_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_s_n_alb', 'long_name', 'albedo of near infrared of the saturated soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_d_n_alb', SITE_soil_d_n_alb)
+ CALL ncio_put_attr (fsrfdata, 'soil_d_n_alb', 'source', trim(datasource(u_site_soil_bright)))
+ CALL ncio_put_attr (fsrfdata, 'soil_d_n_alb', 'long_name', 'albedo of near infrared of the dry soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_quartz_mineral', SITE_soil_vf_quartz_mineral(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_quartz_mineral', 'source', trim(datasource(u_site_vf_quartz_mineral)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_quartz_mineral', 'long_name', 'volumetric fraction of quartz within mineral soil')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_gravels', SITE_soil_vf_gravels(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_gravels', 'source', trim(datasource(u_site_vf_gravels)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_gravels', 'long_name', 'volumetric fraction of gravels')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_sand', SITE_soil_vf_sand(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_sand', 'source', trim(datasource(u_site_vf_sand)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_sand', 'long_name', 'volumetric fraction of sand')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_clay', SITE_soil_vf_clay(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_clay', 'source', trim(datasource(u_site_vf_clay)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_clay', 'long_name', 'volumetric fraction of clay')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_vf_om', SITE_soil_vf_om(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_om', 'source', trim(datasource(u_site_vf_om)))
+ CALL ncio_put_attr (fsrfdata, 'soil_vf_om', 'long_name', 'volumetric fraction of organic matter')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_gravels', SITE_soil_wf_gravels(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_gravels', 'source', trim(datasource(u_site_wf_gravels)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_gravels', 'long_name', 'gravimetric fraction of gravels')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_sand', SITE_soil_wf_sand(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_sand', 'source', trim(datasource(u_site_wf_sand)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_sand', 'long_name', 'gravimetric fraction of sand')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_clay', SITE_soil_wf_clay(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_clay', 'source', trim(datasource(u_site_wf_clay)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_clay', 'long_name', 'gravimetric fraction of clay')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_wf_om', SITE_soil_wf_om(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_om', 'source', trim(datasource(u_site_wf_om)))
+ CALL ncio_put_attr (fsrfdata, 'soil_wf_om', 'long_name', 'gravimetric fraction of om')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_OM_density', SITE_soil_OM_density(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_OM_density', 'source', trim(datasource(u_site_OM_density)))
+ CALL ncio_put_attr (fsrfdata, 'soil_OM_density', 'long_name', 'OM density')
+ CALL ncio_put_attr (fsrfdata, 'soil_OM_density', 'units', 'kg/m3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_BD_all', SITE_soil_BD_all(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_BD_all', 'source', trim(datasource(u_site_BD_all)))
+ CALL ncio_put_attr (fsrfdata, 'soil_BD_all', 'long_name', 'bulk density of soil (GRAVELS + OM + mineral soils)')
+ CALL ncio_put_attr (fsrfdata, 'soil_BD_all', 'units', 'kg/m3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_theta_s', SITE_soil_theta_s(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_s', 'source', trim(datasource(u_site_theta_s)))
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_s', 'long_name', 'saturated water content')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_s', 'units', 'cm3/cm3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_k_s', SITE_soil_k_s(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_s', 'source', trim(datasource(u_site_k_s)))
+ CALL ncio_put_attr (fsrfdata, 'soil_k_s', 'long_name', 'saturated hydraulic conductivity')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_s', 'units', 'cm/day')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_csol', SITE_soil_csol(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_csol', 'source', trim(datasource(u_site_csol)))
+ CALL ncio_put_attr (fsrfdata, 'soil_csol', 'long_name', 'heat capacity of soil solids')
+ CALL ncio_put_attr (fsrfdata, 'soil_csol', 'units', 'J/(m3 K)')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_tksatu', SITE_soil_tksatu(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatu', 'source', trim(datasource(u_site_tksatu)))
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatu', 'long_name', 'thermal conductivity of saturated unfrozen soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatu', 'units', 'W/m-K')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_tksatf', SITE_soil_tksatf(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatf', 'source', trim(datasource(u_site_tksatf)))
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatf', 'long_name', 'thermal conductivity of saturated frozen soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tksatf', 'units', 'W/m-K')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_tkdry', SITE_soil_tkdry(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tkdry', 'source', trim(datasource(u_site_tkdry)))
+ CALL ncio_put_attr (fsrfdata, 'soil_tkdry', 'long_name', 'thermal conductivity for dry soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_tkdry', 'units', 'W/(m-K)')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_k_solids', SITE_soil_k_solids(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_solids', 'source', trim(datasource(u_site_k_solids)))
+ CALL ncio_put_attr (fsrfdata, 'soil_k_solids', 'long_name', 'thermal conductivity of minerals soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_k_solids', 'units', 'W/m-K')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_lambda', SITE_soil_lambda(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_lambda', 'source', trim(datasource(u_site_lambda)))
+ CALL ncio_put_attr (fsrfdata, 'soil_lambda', 'long_name', 'pore size distribution index (dimensionless)')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_psi_s', SITE_soil_psi_s(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_psi_s ', 'source', trim(datasource(u_site_psi_s)))
+ CALL ncio_put_attr (fsrfdata, 'soil_psi_s ', 'long_name', 'matric potential at saturation')
+ CALL ncio_put_attr (fsrfdata, 'soil_psi_s ', 'units', 'cm')
+
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ CALL ncio_write_serial (fsrfdata, 'soil_theta_r', SITE_soil_theta_r(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_r', 'source', trim(datasource(u_site_theta_r)))
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_r', 'long_name', 'residual water content')
+ CALL ncio_put_attr (fsrfdata, 'soil_theta_r', 'units', 'cm3/cm3')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_alpha_vgm', SITE_soil_alpha_vgm(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_alpha_vgm', 'source', trim(datasource(u_site_alpha_vgm)))
+ CALL ncio_put_attr (fsrfdata, 'soil_alpha_vgm', 'long_name', 'a parameter corresponding approximately to the inverse of the air-entry value')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_L_vgm', SITE_soil_L_vgm(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_L_vgm', 'source', trim(datasource(u_site_L_vgm)))
+ CALL ncio_put_attr (fsrfdata, 'soil_L_vgm', 'long_name', 'pore-connectivity parameter [dimensionless]')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_n_vgm', SITE_soil_n_vgm(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_n_vgm', 'source', trim(datasource(u_site_n_vgm)))
+ CALL ncio_put_attr (fsrfdata, 'soil_n_vgm', 'long_name', 'a shape parameter [dimensionless]')
+
+#endif
+
+ CALL ncio_write_serial (fsrfdata, 'soil_BA_alpha', SITE_soil_BA_alpha(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_alpha', 'source', trim(datasource(u_site_BA_alpha)))
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_alpha', 'long_name', 'alpha in Balland and Arp(2005) thermal conductivity scheme')
+
+ CALL ncio_write_serial (fsrfdata, 'soil_BA_beta', SITE_soil_BA_beta(1:8), 'soil')
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_beta', 'source', trim(datasource(u_site_BA_beta)))
+ CALL ncio_put_attr (fsrfdata, 'soil_BA_beta', 'long_name', 'beta in Balland and Arp(2005) thermal conductivity scheme')
+
+ IF (DEF_Runoff_SCHEME == 3) THEN ! for Simple VIC
+ CALL ncio_write_serial (fsrfdata, 'soil_texture ', SITE_soil_texture)
+ CALL ncio_put_attr (fsrfdata, 'soil_texture ', 'source', trim(datasource(u_site_soil_texture)))
+ CALL ncio_put_attr (fsrfdata, 'soil_texture ', 'long_name', 'USDA soil texture')
+ ENDIF
+
+ IF(DEF_USE_BEDROCK)THEN
+ CALL ncio_write_serial (fsrfdata, 'depth_to_bedrock', SITE_dbedrock)
+ CALL ncio_put_attr (fsrfdata, 'depth_to_bedrock', 'source', trim(datasource(u_site_dbedrock)))
+ ENDIF
+
+ CALL ncio_write_serial (fsrfdata, 'elevation', SITE_elevation)
+ CALL ncio_put_attr (fsrfdata, 'elevation', 'source', trim(datasource(u_site_elevation)))
+
+ CALL ncio_write_serial (fsrfdata, 'elvstd', SITE_elvstd)
+ CALL ncio_put_attr (fsrfdata, 'elvstd', 'source', trim(datasource(u_site_elvstd)))
+ CALL ncio_put_attr (fsrfdata, 'elvstd', 'long_name', 'standard deviation of elevation')
+
+ CALL ncio_write_serial (fsrfdata, 'sloperatio', SITE_sloperatio)
+ CALL ncio_put_attr (fsrfdata, 'sloperatio', 'source', trim(datasource(u_site_sloperatio)))
+ CALL ncio_put_attr (fsrfdata, 'sloperatio', 'long_name', 'slope ratio')
+
+ ! used for downscaling
+ IF (DEF_USE_Forcing_Downscaling) THEN
+ CALL ncio_write_serial (fsrfdata, 'SITE_svf', SITE_svf)
+ CALL ncio_put_attr (fsrfdata, 'SITE_svf','source', trim(datasource(u_site_svf)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_svf','long_name', 'sky view factor')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_cur', SITE_cur)
+ CALL ncio_put_attr (fsrfdata, 'SITE_cur','source', trim(datasource(u_site_cur)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_cur','long_name', 'curvature')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_sf_lut', SITE_sf_lut, 'azi', 'zen')
+ CALL ncio_put_attr (fsrfdata, 'SITE_sf_lut','source', trim(datasource(u_site_sf_lut)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_sf_lut','long_name', 'look up table of shadow factor')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_slp_type' , SITE_slp_type , 'type')
+ CALL ncio_put_attr (fsrfdata, 'SITE_slp_type','source', trim(datasource(u_site_slp_type)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_slp_type','long_name', 'topographic slope of each character')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_asp_type' , SITE_asp_type , 'type')
+ CALL ncio_put_attr (fsrfdata, 'SITE_asp_type','source', trim(datasource(u_site_asp_type)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_asp_type','long_name', 'topographic aspect of each character')
+
+ CALL ncio_write_serial (fsrfdata, 'SITE_area_type', SITE_area_type, 'type')
+ CALL ncio_put_attr (fsrfdata, 'SITE_area_type','source', trim(datasource(u_site_area_type)))
+ CALL ncio_put_attr (fsrfdata, 'SITE_area_type','long_name', 'area percentage of each character')
+ ENDIF
+
+ END SUBROUTINE write_urban_surface_data_single
+
+
+!-----------------------------------------------------------------------
+ character(len=18) FUNCTION datasource (is_site)
+
+ IMPLICIT NONE
+ logical, intent(in) :: is_site
+
+ IF (is_site) THEN
+ datasource = 'SITE'
+ ELSE
+ datasource = 'CoLM 2024 raw data'
+ ENDIF
+
+ END FUNCTION datasource
+
+
+!-----------------------------------------------------------------------
+ SUBROUTINE single_srfdata_final ()
+
+ IMPLICIT NONE
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (allocated(SITE_pfttyp )) deallocate(SITE_pfttyp )
+ IF (allocated(SITE_pctpfts)) deallocate(SITE_pctpfts)
+#endif
+
+#ifdef CROP
+ IF (allocated(SITE_croptyp)) deallocate(SITE_croptyp)
+ IF (allocated(SITE_pctcrop)) deallocate(SITE_pctcrop)
+#endif
+
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (allocated(SITE_htop_pfts)) deallocate(SITE_htop_pfts)
+#endif
+
+ IF (allocated(SITE_LAI_monthly)) deallocate(SITE_LAI_monthly)
+ IF (allocated(SITE_SAI_monthly)) deallocate(SITE_SAI_monthly)
+#if (defined LULC_IGBP_PFT || defined LULC_IGBP_PC)
+ IF (allocated(SITE_LAI_pfts_monthly)) deallocate(SITE_LAI_pfts_monthly)
+ IF (allocated(SITE_SAI_pfts_monthly)) deallocate(SITE_SAI_pfts_monthly)
+#endif
+
+ IF (allocated(SITE_LAI_year)) deallocate(SITE_LAI_year)
+ IF (allocated(SITE_LAI_8day)) deallocate(SITE_LAI_8day)
+
+ IF (allocated(SITE_soil_vf_quartz_mineral)) deallocate(SITE_soil_vf_quartz_mineral)
+ IF (allocated(SITE_soil_vf_gravels )) deallocate(SITE_soil_vf_gravels )
+ IF (allocated(SITE_soil_vf_sand )) deallocate(SITE_soil_vf_sand )
+ IF (allocated(SITE_soil_vf_clay )) deallocate(SITE_soil_vf_clay )
+ IF (allocated(SITE_soil_vf_om )) deallocate(SITE_soil_vf_om )
+ IF (allocated(SITE_soil_wf_gravels )) deallocate(SITE_soil_wf_gravels )
+ IF (allocated(SITE_soil_wf_sand )) deallocate(SITE_soil_wf_sand )
+ IF (allocated(SITE_soil_wf_clay )) deallocate(SITE_soil_wf_clay )
+ IF (allocated(SITE_soil_wf_om )) deallocate(SITE_soil_wf_om )
+ IF (allocated(SITE_soil_OM_density )) deallocate(SITE_soil_OM_density )
+ IF (allocated(SITE_soil_BD_all )) deallocate(SITE_soil_BD_all )
+ IF (allocated(SITE_soil_theta_s )) deallocate(SITE_soil_theta_s )
+ IF (allocated(SITE_soil_k_s )) deallocate(SITE_soil_k_s )
+ IF (allocated(SITE_soil_csol )) deallocate(SITE_soil_csol )
+ IF (allocated(SITE_soil_tksatu )) deallocate(SITE_soil_tksatu )
+ IF (allocated(SITE_soil_tksatf )) deallocate(SITE_soil_tksatf )
+ IF (allocated(SITE_soil_tkdry )) deallocate(SITE_soil_tkdry )
+ IF (allocated(SITE_soil_k_solids )) deallocate(SITE_soil_k_solids )
+ IF (allocated(SITE_soil_psi_s )) deallocate(SITE_soil_psi_s )
+ IF (allocated(SITE_soil_lambda )) deallocate(SITE_soil_lambda )
+ IF (allocated(SITE_soil_theta_r )) deallocate(SITE_soil_theta_r )
+#ifdef vanGenuchten_Mualem_SOIL_MODEL
+ IF (allocated(SITE_soil_alpha_vgm )) deallocate(SITE_soil_alpha_vgm )
+ IF (allocated(SITE_soil_L_vgm )) deallocate(SITE_soil_L_vgm )
+ IF (allocated(SITE_soil_n_vgm )) deallocate(SITE_soil_n_vgm )
+#endif
+ IF (allocated(SITE_soil_BA_alpha )) deallocate(SITE_soil_BA_alpha )
+ IF (allocated(SITE_soil_BA_beta )) deallocate(SITE_soil_BA_beta )
+
+ IF (allocated(SITE_sf_lut )) deallocate(SITE_sf_lut )
+ IF (allocated(SITE_slp_type )) deallocate(SITE_slp_type )
+ IF (allocated(SITE_asp_type )) deallocate(SITE_asp_type )
+ IF (allocated(SITE_area_type )) deallocate(SITE_area_type )
+
+ END SUBROUTINE single_srfdata_final
+
+END MODULE MOD_SingleSrfdata
+#endif
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_SpatialMapping.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SpatialMapping.F90
new file mode 100644
index 0000000000..a47fa6e21c
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SpatialMapping.F90
@@ -0,0 +1,2887 @@
+#include
+
+MODULE MOD_SpatialMapping
+
+!--------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! Spatial Mapping module.
+!
+! Created by Shupeng Zhang, May 2024
+!--------------------------------------------------------------------------------
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ ! ------
+ type :: spatial_mapping_type
+
+ type(grid_type) :: grid
+
+ type(grid_list_type), allocatable :: glist (:)
+
+ integer :: npset
+ integer, allocatable :: npart(:)
+ type(pointer_int32_2d), allocatable :: address (:)
+
+ logical :: has_missing_value = .false.
+ real(r8) :: missing_value = spval
+
+ type(pointer_real8_1d), allocatable :: areapart(:) ! intersection area
+ real(r8), allocatable :: areapset(:)
+ type(block_data_real8_2d) :: areagrid
+
+ CONTAINS
+
+ procedure, PUBLIC :: build_arealweighted => spatial_mapping_build_arealweighted
+ procedure, PUBLIC :: build_bilinear => spatial_mapping_build_bilinear
+
+ procedure, PUBLIC :: set_missing_value => spatial_mapping_set_missing_value
+
+ ! 1) from pixelset to grid
+ procedure, PRIVATE :: pset2grid_2d => spatial_mapping_pset2grid_2d
+ procedure, PRIVATE :: pset2grid_3d => spatial_mapping_pset2grid_3d
+ procedure, PRIVATE :: pset2grid_4d => spatial_mapping_pset2grid_4d
+ generic, PUBLIC :: pset2grid => pset2grid_2d, pset2grid_3d, pset2grid_4d
+
+ procedure, PUBLIC :: pset2grid_max => spatial_mapping_pset2grid_max
+ procedure, PUBLIC :: pset2grid_split => spatial_mapping_pset2grid_split
+
+ procedure, PUBLIC :: get_sumarea => spatial_mapping_get_sumarea
+
+ ! 2) from grid to pixelset
+ procedure, PRIVATE :: grid2pset_2d => spatial_mapping_grid2pset_2d
+ procedure, PRIVATE :: grid2pset_3d => spatial_mapping_grid2pset_3d
+ generic, PUBLIC :: grid2pset => grid2pset_2d, grid2pset_3d
+
+ procedure, PUBLIC :: grid2pset_dominant => spatial_mapping_dominant_2d
+ procedure, PUBLIC :: grid2pset_varvalue => spatial_mapping_varvalue_2d
+
+ ! 3) between grid and intersections
+ procedure, PUBLIC :: grid2part => spatial_mapping_grid2part
+ procedure, PUBLIC :: part2grid => spatial_mapping_part2grid
+ procedure, PUBLIC :: normalize => spatial_mapping_normalize
+
+ ! 4) intersections to pixelset
+ procedure, PUBLIC :: part2pset => spatial_mapping_part2pset
+
+ procedure, PUBLIC :: allocate_part => spatial_mapping_allocate_part
+ procedure, PUBLIC :: deallocate_part => spatial_mapping_deallocate_part
+ procedure, PUBLIC :: forc_free_mem => forc_free_mem_spatial_mapping
+
+ final :: spatial_mapping_free_mem
+
+ END type spatial_mapping_type
+
+!-----------------------
+CONTAINS
+
+ !------------------------------------------
+ SUBROUTINE spatial_mapping_build_arealweighted (this, fgrid, pixelset)
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_Pixel
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_Utils
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(grid_type), intent(in) :: fgrid
+ type(pixelset_type), intent(in) :: pixelset
+
+ ! Local variables
+ type(pointer_real8_1d), allocatable :: afrac(:)
+ type(grid_list_type), allocatable :: gfrom(:)
+ type(pointer_int32_1d), allocatable :: list_lat(:)
+ integer, allocatable :: ng_lat(:)
+ integer, allocatable :: ys(:), yn(:), xw(:), xe(:)
+ integer, allocatable :: xlist(:), ylist(:)
+ integer, allocatable :: ipt(:)
+ logical, allocatable :: msk(:)
+
+ integer :: ie, iset, iblkme
+ integer :: ng, ig, ng_all, iloc
+ integer :: npxl, ipxl, ilat, ilon
+ integer :: irank, iproc, idest, isrc, nrecv
+ integer :: rmesg(2), smesg(2)
+ integer :: iy, ix, xblk, yblk, xloc, yloc
+ integer :: ipxstt, ipxend
+ real(r8) :: lat_s, lat_n, lon_w, lon_e, area
+ logical :: skip, is_new
+
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+
+ write(*,"(A, I0, A, I0, A)") &
+ 'Making areal weighted mapping between pixel set and grid: ', &
+ fgrid%nlat, ' grids in latitude ', fgrid%nlon, ' grids in longitude.'
+
+#ifndef SinglePoint
+ IF (.not. (lon_between_floor(pixel%edgew, fgrid%lon_w(1), fgrid%lon_e(fgrid%nlon)) &
+ .and. lon_between_ceil(pixel%edgee, fgrid%lon_w(1), fgrid%lon_e(fgrid%nlon)))) THEN
+ write(*,'(A)') 'Warning: Grid does not cover longitude range of modeling region.'
+ ENDIF
+
+ IF (fgrid%yinc == 1) THEN
+ IF (.not. ((pixel%edges >= fgrid%lat_s(1)) &
+ .and. (pixel%edgen <= fgrid%lat_n(fgrid%nlat)))) THEN
+ write(*,'(A)') 'Warning: Grid does not cover latitude range of modeling region.'
+ ENDIF
+ ELSE
+ IF (.not. ((pixel%edges >= fgrid%lat_s(fgrid%nlat)) &
+ .and. (pixel%edgen <= fgrid%lat_n(1)))) THEN
+ write(*,'(A)') 'Warning: Grid does not cover latitude range of modeling region.'
+ ENDIF
+ ENDIF
+#endif
+
+ ENDIF
+
+ allocate (this%grid%xblk (size(fgrid%xblk))); this%grid%xblk = fgrid%xblk
+ allocate (this%grid%yblk (size(fgrid%yblk))); this%grid%yblk = fgrid%yblk
+ allocate (this%grid%xloc (size(fgrid%xloc))); this%grid%xloc = fgrid%xloc
+ allocate (this%grid%yloc (size(fgrid%yloc))); this%grid%yloc = fgrid%yloc
+ allocate (this%grid%xcnt (size(fgrid%xcnt))); this%grid%xcnt = fgrid%xcnt
+ allocate (this%grid%ycnt (size(fgrid%ycnt))); this%grid%ycnt = fgrid%ycnt
+
+#ifdef SinglePoint
+ allocate (this%glist (0:0))
+ allocate (this%glist(0)%ilat (1))
+ allocate (this%glist(0)%ilon (1))
+
+ allocate (this%npart (pixelset%nset))
+ allocate (this%address (pixelset%nset))
+ allocate (this%areapset(pixelset%nset))
+ allocate (this%areapart(pixelset%nset))
+ DO iset = 1, pixelset%nset
+ allocate (this%address(iset)%val (2,1))
+ allocate (this%areapart(iset)%val (1))
+ ENDDO
+
+ this%glist(0)%ng = 1
+ this%glist(0)%ilat(1) = find_nearest_south (SITE_lat_location, fgrid%nlat, fgrid%lat_s)
+ this%glist(0)%ilon(1) = find_nearest_west (SITE_lon_location, fgrid%nlon, fgrid%lon_w)
+
+ this%npset = pixelset%nset
+ this%npart (:) = 1
+ this%areapset(:) = 1.
+
+ DO iset = 1, pixelset%nset
+ this%address(iset)%val = reshape((/0,1/), (/2,1/))
+ this%areapart(iset)%val = 1.
+ ENDDO
+
+ CALL allocate_block_data (fgrid, this%areagrid)
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+ this%areagrid%blk(xblk,yblk)%val = 1.
+ ENDDO
+
+ RETURN
+#endif
+
+
+ IF (p_is_compute) THEN
+
+ this%npset = pixelset%nset
+
+ allocate (afrac (pixelset%nset))
+ allocate (gfrom (pixelset%nset))
+
+ allocate (ys (pixel%nlat))
+ allocate (yn (pixel%nlat))
+ allocate (xw (pixel%nlon))
+ allocate (xe (pixel%nlon))
+
+ DO ilat = 1, pixel%nlat
+ ys(ilat) = find_nearest_south (pixel%lat_s(ilat), fgrid%nlat, fgrid%lat_s)
+ yn(ilat) = find_nearest_north (pixel%lat_n(ilat), fgrid%nlat, fgrid%lat_n)
+ ENDDO
+
+ DO ilon = 1, pixel%nlon
+ xw(ilon) = find_nearest_west (pixel%lon_w(ilon), fgrid%nlon, fgrid%lon_w)
+ xe(ilon) = find_nearest_east (pixel%lon_e(ilon), fgrid%nlon, fgrid%lon_e)
+ ENDDO
+
+ allocate (list_lat (fgrid%nlat))
+ DO iy = 1, fgrid%nlat
+ allocate (list_lat(iy)%val (100))
+ ENDDO
+
+ allocate (ng_lat (fgrid%nlat)); ng_lat(:) = 0
+
+ DO iset = 1, pixelset%nset
+
+ ie = pixelset%ielm(iset)
+ npxl = pixelset%ipxend(iset) - pixelset%ipxstt(iset) + 1
+
+ ipxstt = pixelset%ipxstt(iset)
+ ipxend = pixelset%ipxend(iset)
+
+ ! deal with 2m WMO patch
+ IF (ipxstt==-1 .and. ipxend==-1) THEN
+ ipxstt = 1
+ ipxend = mesh(ie)%npxl
+ npxl = mesh(ie)%npxl
+ ENDIF
+
+ allocate (afrac(iset)%val (npxl))
+ allocate (gfrom(iset)%ilat(npxl))
+ allocate (gfrom(iset)%ilon(npxl))
+
+ gfrom(iset)%ng = 0
+
+ DO ipxl = ipxstt, ipxend
+
+ ilat = mesh(ie)%ilat(ipxl)
+ ilon = mesh(ie)%ilon(ipxl)
+
+ DO iy = ys(ilat), yn(ilat), fgrid%yinc
+
+ lat_s = max(fgrid%lat_s(iy), pixel%lat_s(ilat))
+ lat_n = min(fgrid%lat_n(iy), pixel%lat_n(ilat))
+
+ IF ((lat_n-lat_s) < 1.0e-6_r8) THEN
+ CYCLE
+ ENDIF
+
+ ix = xw(ilon)
+ DO WHILE (.true.)
+
+ IF (ix == xw(ilon)) THEN
+ lon_w = pixel%lon_w(ilon)
+ ELSE
+ lon_w = fgrid%lon_w(ix)
+ ENDIF
+
+ IF (ix == xe(ilon)) THEN
+ lon_e = pixel%lon_e(ilon)
+ ELSE
+ lon_e = fgrid%lon_e(ix)
+ ENDIF
+
+ skip = .false.
+ IF (.not. (lon_between_floor (lon_w, pixel%lon_w(ilon), lon_e) &
+ .and. lon_between_ceil (lon_e, lon_w, pixel%lon_e(ilon)))) THEN
+ skip = .true.
+ ELSE
+ IF (lon_e > lon_w) THEN
+ IF ((lon_e-lon_w) < 1.0e-6_r8) THEN
+ skip = .true.
+ ENDIF
+ ELSE
+ IF ((lon_e+360.0_r8-lon_w) < 1.0e-6_r8) THEN
+ skip = .true.
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (.not. skip) THEN
+
+ area = areaquad (lat_s, lat_n, lon_w, lon_e)
+
+ CALL insert_into_sorted_list2 ( ix, iy, &
+ gfrom(iset)%ng, gfrom(iset)%ilon, gfrom(iset)%ilat, &
+ iloc, is_new)
+
+ IF (is_new) THEN
+ IF (iloc < gfrom(iset)%ng) THEN
+ afrac(iset)%val(iloc+1:gfrom(iset)%ng) &
+ = afrac(iset)%val(iloc:gfrom(iset)%ng-1)
+ ENDIF
+
+ afrac(iset)%val(iloc) = area
+ ELSE
+ afrac(iset)%val(iloc) = afrac(iset)%val(iloc) + area
+ ENDIF
+
+ IF (gfrom(iset)%ng == size(gfrom(iset)%ilat)) THEN
+ CALL expand_list (gfrom(iset)%ilat, 0.2_r8)
+ CALL expand_list (gfrom(iset)%ilon, 0.2_r8)
+ CALL expand_list (afrac(iset)%val, 0.2_r8)
+ ENDIF
+
+ CALL insert_into_sorted_list1 ( &
+ ix, ng_lat(iy), list_lat(iy)%val, iloc)
+
+ IF (ng_lat(iy) == size(list_lat(iy)%val)) THEN
+ CALL expand_list (list_lat(iy)%val, 0.2_r8)
+ ENDIF
+
+ ENDIF
+
+ IF (ix == xe(ilon)) EXIT
+ ix = mod(ix,fgrid%nlon) + 1
+ ENDDO
+ ENDDO
+
+ ENDDO
+ ENDDO
+
+ deallocate (ys)
+ deallocate (yn)
+ deallocate (xw)
+ deallocate (xe)
+
+ ng_all = sum(ng_lat)
+ allocate (xlist(ng_all))
+ allocate (ylist(ng_all))
+
+ ig = 0
+ DO iy = 1, fgrid%nlat
+ DO ix = 1, ng_lat(iy)
+ ig = ig + 1
+ xlist(ig) = list_lat(iy)%val(ix)
+ ylist(ig) = iy
+ ENDDO
+ ENDDO
+
+ deallocate (ng_lat)
+ DO iy = 1, fgrid%nlat
+ deallocate (list_lat(iy)%val)
+ ENDDO
+ deallocate (list_lat)
+
+#ifdef USEMPI
+ allocate (ipt (ng_all))
+ allocate (msk (ng_all))
+ DO ig = 1, ng_all
+ xblk = fgrid%xblk(xlist(ig))
+ yblk = fgrid%yblk(ylist(ig))
+ ipt(ig) = gblock%pio(xblk,yblk)
+ ENDDO
+#endif
+
+ allocate (this%glist (0:p_np_active-1))
+ DO iproc = 0, p_np_active-1
+#ifdef USEMPI
+ msk = (ipt == p_address_active(iproc))
+ ng = count(msk)
+#else
+ ng = ng_all
+#endif
+
+ this%glist(iproc)%ng = ng
+
+ IF (ng > 0) THEN
+ allocate (this%glist(iproc)%ilat (ng))
+ allocate (this%glist(iproc)%ilon (ng))
+
+#ifdef USEMPI
+ this%glist(iproc)%ilon = pack(xlist, msk)
+ this%glist(iproc)%ilat = pack(ylist, msk)
+#else
+ this%glist(iproc)%ilon = xlist
+ this%glist(iproc)%ilat = ylist
+#endif
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ deallocate (ipt)
+ deallocate (msk)
+#endif
+
+ allocate (this%address (pixelset%nset))
+ allocate (this%areapart (pixelset%nset))
+
+ allocate (this%npart (pixelset%nset))
+
+ DO iset = 1, pixelset%nset
+
+ ng = gfrom(iset)%ng
+
+ this%npart(iset) = ng
+
+ allocate (this%address(iset)%val (2,ng))
+ allocate (this%areapart(iset)%val (ng))
+
+ this%areapart(iset)%val = afrac(iset)%val(1:ng)
+
+ IF (pixelset%has_shared) THEN
+ this%areapart(iset)%val = this%areapart(iset)%val * pixelset%pctshared(iset)
+ ENDIF
+
+ DO ig = 1, gfrom(iset)%ng
+ ilon = gfrom(iset)%ilon(ig)
+ ilat = gfrom(iset)%ilat(ig)
+ xblk = fgrid%xblk(ilon)
+ yblk = fgrid%yblk(ilat)
+
+#ifdef USEMPI
+ iproc = p_itis_active(gblock%pio(xblk,yblk))
+#else
+ iproc = 0
+#endif
+
+ this%address(iset)%val(1,ig) = iproc
+ this%address(iset)%val(2,ig) = find_in_sorted_list2 ( &
+ ilon, ilat, this%glist(iproc)%ng, this%glist(iproc)%ilon, this%glist(iproc)%ilat)
+ ENDDO
+ ENDDO
+
+ deallocate (xlist)
+ deallocate (ylist)
+
+ DO iset = 1, pixelset%nset
+ deallocate (afrac(iset)%val )
+ deallocate (gfrom(iset)%ilon)
+ deallocate (gfrom(iset)%ilat)
+ ENDDO
+
+ deallocate (afrac)
+ deallocate (gfrom)
+
+ ENDIF
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ IF (p_is_compute) THEN
+
+ DO iproc = 0, p_np_active-1
+ idest = p_address_active(iproc)
+ smesg = (/p_iam_glb, this%glist(iproc)%ng/)
+
+ CALL mpi_send (smesg, 2, MPI_INTEGER, &
+ idest, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (this%glist(iproc)%ng > 0) THEN
+ CALL mpi_send (this%glist(iproc)%ilon, this%glist(iproc)%ng, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send (this%glist(iproc)%ilat, this%glist(iproc)%ng, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ allocate (this%glist (0:p_np_compute-1))
+
+ DO irank = 0, p_np_compute-1
+
+ CALL mpi_recv (rmesg, 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ nrecv = rmesg(2)
+ iproc = p_itis_compute(isrc)
+
+ this%glist(iproc)%ng = nrecv
+
+ IF (nrecv > 0) THEN
+ allocate (this%glist(iproc)%ilon (nrecv))
+ allocate (this%glist(iproc)%ilat (nrecv))
+
+ CALL mpi_recv (this%glist(iproc)%ilon, nrecv, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (this%glist(iproc)%ilat, nrecv, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+ ENDDO
+
+ ENDIF
+#endif
+
+ IF (p_is_compute) THEN
+ IF (this%npset > 0) THEN
+ allocate (this%areapset (this%npset))
+ this%areapset(:) = 0.
+ ENDIF
+ DO iset = 1, this%npset
+ IF (this%npart(iset) > 0) THEN
+ this%areapset(iset) = sum(this%areapart(iset)%val)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_active) CALL allocate_block_data (fgrid, this%areagrid)
+ IF (p_is_compute) THEN
+ IF (this%npset > 0) THEN
+ allocate (msk (this%npset))
+ msk = pixelset%ipxstt > 0 .and. pixelset%ipxend > 0
+ ENDIF
+ ENDIF
+ CALL this%get_sumarea (this%areagrid, msk)
+
+ IF (allocated(msk)) deallocate(msk)
+
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE spatial_mapping_build_arealweighted
+
+ !------------------------------------------
+ SUBROUTINE spatial_mapping_build_bilinear (this, fgrid, pixelset)
+
+ USE MOD_Precision
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_Pixel
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_Mesh
+ USE MOD_Pixelset
+ USE MOD_Utils
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: pi
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(grid_type), intent(in) :: fgrid
+ type(pixelset_type), intent(in) :: pixelset
+
+ ! Local variables
+ integer, allocatable :: ys(:), yn(:), xw(:), xe(:)
+ integer, allocatable :: xlist(:), ylist(:), ipt(:)
+
+ real(r8), allocatable :: rlon_pset(:), rlat_pset(:)
+ real(r8), allocatable :: nwgt(:), swgt(:), wwgt(:), ewgt(:)
+
+ logical, allocatable :: msk(:)
+
+ integer :: iset, ilat, ilon, iwest, ieast, ie, ipxl
+ integer :: nglist, iloc, ng, ig
+ integer :: irank, iproc, iio, idest, isrc, nrecv
+ integer :: rmesg(2), smesg(2)
+ integer :: iy, ix, xblk, yblk, xloc, yloc
+ integer :: ipxstt, ipxend
+
+ real(r8) :: lon, lonw, lone, latn, lats
+ real(r8) :: distn, dists, distw, diste, diffw, diffe, areathis
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+
+ write(*,*)
+ write(*,"(A, I0, A, I0, A)") &
+ 'Building bilinear interpolation from grid to pixel set: ', &
+ fgrid%nlat, ' grids in latitude ', fgrid%nlon, ' grids in longitude.'
+ write(*,*)
+
+ IF (.not. (lon_between_floor(pixel%edgew, fgrid%lon_w(1), fgrid%lon_e(fgrid%nlon)) &
+ .and. lon_between_ceil(pixel%edgee, fgrid%lon_w(1), fgrid%lon_e(fgrid%nlon)))) THEN
+ write(*,'(A)') 'Warning: Grid does not cover longitude range of modeling region.'
+ ENDIF
+
+ IF (fgrid%yinc == 1) THEN
+ IF (.not. ((pixel%edges >= fgrid%lat_s(1)) &
+ .and. (pixel%edgen <= fgrid%lat_n(fgrid%nlat)))) THEN
+ write(*,'(A)') 'Warning: Grid does not cover latitude range of modeling region.'
+ ENDIF
+ ELSE
+ IF (.not. ((pixel%edges >= fgrid%lat_s(fgrid%nlat)) &
+ .and. (pixel%edgen <= fgrid%lat_n(1)))) THEN
+ write(*,'(A)') 'Warning: Grid does not cover latitude range of modeling region.'
+ ENDIF
+ ENDIF
+
+ ENDIF
+
+ this%grid%nlat = fgrid%nlat
+ this%grid%nlon = fgrid%nlon
+
+ allocate (this%grid%xblk (size(fgrid%xblk))); this%grid%xblk = fgrid%xblk
+ allocate (this%grid%yblk (size(fgrid%yblk))); this%grid%yblk = fgrid%yblk
+ allocate (this%grid%xloc (size(fgrid%xloc))); this%grid%xloc = fgrid%xloc
+ allocate (this%grid%yloc (size(fgrid%yloc))); this%grid%yloc = fgrid%yloc
+ allocate (this%grid%xcnt (size(fgrid%xcnt))); this%grid%xcnt = fgrid%xcnt
+ allocate (this%grid%ycnt (size(fgrid%ycnt))); this%grid%ycnt = fgrid%ycnt
+
+ IF (p_is_compute) THEN
+
+ allocate (this%grid%lat_s(this%grid%nlat)); this%grid%lat_s = fgrid%lat_s
+ allocate (this%grid%lat_n(this%grid%nlat)); this%grid%lat_n = fgrid%lat_n
+ allocate (this%grid%lon_w(this%grid%nlon)); this%grid%lon_w = fgrid%lon_w
+ allocate (this%grid%lon_e(this%grid%nlon)); this%grid%lon_e = fgrid%lon_e
+ allocate (this%grid%rlon (this%grid%nlon)); CALL this%grid%set_rlon ()
+ allocate (this%grid%rlat (this%grid%nlat)); CALL this%grid%set_rlat ()
+
+ this%npset = pixelset%nset
+
+ allocate (yn (this%npset))
+ allocate (ys (this%npset))
+ allocate (xw (this%npset))
+ allocate (xe (this%npset))
+ allocate (rlon_pset (this%npset))
+ allocate (rlat_pset (this%npset))
+
+ CALL pixelset%get_lonlat_radian (rlon_pset, rlat_pset)
+
+ allocate (xlist(4*this%npset))
+ allocate (ylist(4*this%npset))
+
+ allocate (nwgt (this%npset))
+ allocate (swgt (this%npset))
+ allocate (wwgt (this%npset))
+ allocate (ewgt (this%npset))
+
+ nglist = 0
+
+ DO iset = 1, this%npset
+
+ IF (this%grid%rlat(1) > this%grid%rlat(this%grid%nlat)) THEN
+ ! from north to south
+ ilat = 1
+ DO WHILE ((rlat_pset(iset) < this%grid%rlat(ilat)) .and. (ilat < this%grid%nlat))
+ ilat = ilat + 1
+ ENDDO
+
+ IF (rlat_pset(iset) >= this%grid%rlat(ilat)) THEN
+ yn(iset) = max(ilat-1,1)
+ ys(iset) = ilat
+ ELSE
+ yn(iset) = this%grid%nlat
+ ys(iset) = this%grid%nlat
+ ENDIF
+ ELSE
+ ! from south to north
+ ilat = this%grid%nlat
+ DO WHILE ((rlat_pset(iset) < this%grid%rlat(ilat)) .and. (ilat > 1))
+ ilat = ilat - 1
+ ENDDO
+
+ IF (rlat_pset(iset) >= this%grid%rlat(ilat)) THEN
+ yn(iset) = min(ilat+1,this%grid%nlat)
+ ys(iset) = ilat
+ ELSE
+ yn(iset) = 1
+ ys(iset) = 1
+ ENDIF
+ ENDIF
+
+ IF (yn(iset) /= ys(iset)) THEN
+ latn = this%grid%rlat(yn(iset))
+ lats = this%grid%rlat(ys(iset))
+ distn = arclen(rlat_pset(iset), rlon_pset(iset), latn, rlon_pset(iset))
+ dists = arclen(rlat_pset(iset), rlon_pset(iset), lats, rlon_pset(iset))
+ nwgt(iset) = dists/(dists+distn)
+ swgt(iset) = distn/(dists+distn)
+ ELSE
+ nwgt(iset) = 1.0
+ swgt(iset) = 0.0
+ ENDIF
+
+
+ lon = rlon_pset(iset)*180.0/pi
+ CALL normalize_longitude (lon)
+
+ DO iwest = 1, this%grid%nlon
+ lonw = this%grid%rlon(iwest) *180.0/pi
+ CALL normalize_longitude (lonw)
+
+ ieast = mod(iwest,this%grid%nlon) + 1
+ lone = this%grid%rlon(ieast)*180.0/pi
+ CALL normalize_longitude (lone)
+
+ IF (lon_between_floor(lon, lonw, lone)) EXIT
+ ENDDO
+
+ xw(iset) = iwest
+ xe(iset) = ieast
+
+ ! for the case grid does not cover [-180,180)
+ IF ((iwest == this%grid%nlon) .and. (this%grid%nlon > 1)) THEN
+ IF (lon_between_floor( &
+ this%grid%lon_e(this%grid%nlon), lonw, this%grid%lon_w(1))) THEN
+
+ diffw = lon - lonw; IF (diffw < 0) diffw = diffw + 360.0
+ diffe = lone - lon; IF (diffe < 0) diffe = diffe + 360.0
+
+ IF (diffw > diffe) THEN
+ xw(iset) = ieast
+ xe(iset) = ieast
+ ELSE
+ xw(iset) = iwest
+ xe(iset) = iwest
+ ENDIF
+
+ ENDIF
+ ENDIF
+
+ IF (xw(iset) /= xe(iset)) THEN
+ lonw = this%grid%rlon(xw(iset))
+ lone = this%grid%rlon(xe(iset))
+ distw = arclen(rlat_pset(iset), rlon_pset(iset), rlat_pset(iset), lonw)
+ diste = arclen(rlat_pset(iset), rlon_pset(iset), rlat_pset(iset), lone)
+ wwgt(iset) = diste/(distw+diste)
+ ewgt(iset) = distw/(distw+diste)
+ ELSE
+ wwgt(iset) = 1.0
+ ewgt(iset) = 0.0
+ ENDIF
+
+ CALL insert_into_sorted_list2 ( xw(iset), yn(iset), nglist, xlist, ylist, iloc)
+ CALL insert_into_sorted_list2 ( xe(iset), yn(iset), nglist, xlist, ylist, iloc)
+ CALL insert_into_sorted_list2 ( xw(iset), ys(iset), nglist, xlist, ylist, iloc)
+ CALL insert_into_sorted_list2 ( xe(iset), ys(iset), nglist, xlist, ylist, iloc)
+
+ ENDDO
+
+#ifdef USEMPI
+ allocate (ipt (nglist))
+ allocate (msk (nglist))
+ DO ig = 1, nglist
+ xblk = this%grid%xblk(xlist(ig))
+ yblk = this%grid%yblk(ylist(ig))
+ ipt(ig) = gblock%pio(xblk,yblk)
+ ENDDO
+#endif
+
+ allocate (this%glist (0:p_np_active-1))
+ DO iproc = 0, p_np_active-1
+#ifdef USEMPI
+ msk = (ipt == p_address_active(iproc))
+ ng = count(msk)
+#else
+ ng = nglist
+#endif
+
+ this%glist(iproc)%ng = ng
+
+ IF (ng > 0) THEN
+ allocate (this%glist(iproc)%ilat (ng))
+ allocate (this%glist(iproc)%ilon (ng))
+
+#ifdef USEMPI
+ this%glist(iproc)%ilon = pack(xlist(1:nglist), msk)
+ this%glist(iproc)%ilat = pack(ylist(1:nglist), msk)
+#else
+ this%glist(iproc)%ilon = xlist(1:nglist)
+ this%glist(iproc)%ilat = ylist(1:nglist)
+#endif
+ ENDIF
+
+ ENDDO
+
+ deallocate (xlist)
+ deallocate (ylist)
+
+#ifdef USEMPI
+ deallocate (ipt)
+ deallocate (msk)
+#endif
+ ENDIF
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ idest = p_address_active(iproc)
+ smesg = (/p_iam_glb, this%glist(iproc)%ng/)
+
+ CALL mpi_send (smesg, 2, MPI_INTEGER, &
+ idest, mpi_tag_mesg, p_comm_glb, p_err)
+
+ IF (this%glist(iproc)%ng > 0) THEN
+ CALL mpi_send (this%glist(iproc)%ilon, this%glist(iproc)%ng, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ CALL mpi_send (this%glist(iproc)%ilat, this%glist(iproc)%ng, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ allocate (this%glist (0:p_np_compute-1))
+
+ DO irank = 0, p_np_compute-1
+
+ CALL mpi_recv (rmesg, 2, MPI_INTEGER, &
+ MPI_ANY_SOURCE, mpi_tag_mesg, p_comm_glb, p_stat, p_err)
+
+ isrc = rmesg(1)
+ nrecv = rmesg(2)
+ iproc = p_itis_compute(isrc)
+
+ this%glist(iproc)%ng = nrecv
+
+ IF (nrecv > 0) THEN
+ allocate (this%glist(iproc)%ilon (nrecv))
+ allocate (this%glist(iproc)%ilat (nrecv))
+
+ CALL mpi_recv (this%glist(iproc)%ilon, nrecv, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ CALL mpi_recv (this%glist(iproc)%ilat, nrecv, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_compute) THEN
+
+ allocate (this%address (this%npset))
+ allocate (this%npart (this%npset))
+ allocate (this%areapart(this%npset))
+
+ DO iset = 1, pixelset%nset
+
+ this%npart(iset) = 4
+
+ allocate (this%address (iset)%val(2,4))
+ allocate (this%areapart(iset)%val(4))
+
+ areathis = 0.
+
+ ie = pixelset%ielm(iset)
+
+ ipxstt = pixelset%ipxstt(iset)
+ ipxend = pixelset%ipxend(iset)
+
+ ! deal with 2m WMO patch
+ IF (ipxstt==-1 .and. ipxend==-1) THEN
+ ipxstt = 1
+ ipxend = mesh(ie)%npxl
+ ENDIF
+
+ DO ipxl = ipxstt, ipxend
+ areathis = areathis + areaquad (&
+ pixel%lat_s(mesh(ie)%ilat(ipxl)), pixel%lat_n(mesh(ie)%ilat(ipxl)), &
+ pixel%lon_w(mesh(ie)%ilon(ipxl)), pixel%lon_e(mesh(ie)%ilon(ipxl)) )
+ ENDDO
+
+ IF (pixelset%has_shared) THEN
+ areathis = areathis * pixelset%pctshared(iset)
+ ENDIF
+
+ ! northwest grid
+ ix = xw(iset); iy = yn(iset);
+#ifdef USEMPI
+ xblk = this%grid%xblk(ix)
+ yblk = this%grid%yblk(iy)
+ iproc = p_itis_active(gblock%pio(xblk,yblk))
+#else
+ iproc = 0
+#endif
+ this%address(iset)%val(1,1) = iproc
+ this%address(iset)%val(2,1) = find_in_sorted_list2 ( ix, iy, &
+ this%glist(iproc)%ng, this%glist(iproc)%ilon, this%glist(iproc)%ilat)
+
+ this%areapart(iset)%val(1) = areathis * nwgt(iset) * wwgt(iset)
+
+ ! northeast grid
+ ix = xe(iset); iy = yn(iset);
+#ifdef USEMPI
+ xblk = this%grid%xblk(ix)
+ yblk = this%grid%yblk(iy)
+ iproc = p_itis_active(gblock%pio(xblk,yblk))
+#else
+ iproc = 0
+#endif
+ this%address(iset)%val(1,2) = iproc
+ this%address(iset)%val(2,2) = find_in_sorted_list2 ( ix, iy, &
+ this%glist(iproc)%ng, this%glist(iproc)%ilon, this%glist(iproc)%ilat)
+
+ this%areapart(iset)%val(2) = areathis * nwgt(iset) * ewgt(iset)
+
+ ! southwest
+ ix = xw(iset); iy = ys(iset);
+#ifdef USEMPI
+ xblk = this%grid%xblk(ix)
+ yblk = this%grid%yblk(iy)
+ iproc = p_itis_active(gblock%pio(xblk,yblk))
+#else
+ iproc = 0
+#endif
+ this%address(iset)%val(1,3) = iproc
+ this%address(iset)%val(2,3) = find_in_sorted_list2 ( ix, iy, &
+ this%glist(iproc)%ng, this%glist(iproc)%ilon, this%glist(iproc)%ilat)
+
+ this%areapart(iset)%val(3) = areathis * swgt(iset) * wwgt(iset)
+
+ ! southeast
+ ix = xe(iset); iy = ys(iset);
+#ifdef USEMPI
+ xblk = this%grid%xblk(ix)
+ yblk = this%grid%yblk(iy)
+ iproc = p_itis_active(gblock%pio(xblk,yblk))
+#else
+ iproc = 0
+#endif
+ this%address(iset)%val(1,4) = iproc
+ this%address(iset)%val(2,4) = find_in_sorted_list2 ( ix, iy, &
+ this%glist(iproc)%ng, this%glist(iproc)%ilon, this%glist(iproc)%ilat)
+
+ this%areapart(iset)%val(4) = areathis * swgt(iset) * ewgt(iset)
+
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ IF (this%npset > 0) THEN
+ allocate (this%areapset (this%npset))
+ ENDIF
+ DO iset = 1, this%npset
+ this%areapset(iset) = sum(this%areapart(iset)%val)
+ ENDDO
+ ENDIF
+
+ IF (p_is_active) CALL allocate_block_data (fgrid, this%areagrid)
+ IF (p_is_compute) THEN
+ IF (this%npset > 0) THEN
+ allocate (msk (this%npset))
+ msk = pixelset%ipxstt > 0 .and. pixelset%ipxend > 0
+ ENDIF
+ ENDIF
+ CALL this%get_sumarea (this%areagrid, msk)
+
+
+ IF (allocated(this%grid%lat_s)) deallocate(this%grid%lat_s)
+ IF (allocated(this%grid%lat_n)) deallocate(this%grid%lat_n)
+ IF (allocated(this%grid%lon_w)) deallocate(this%grid%lon_w)
+ IF (allocated(this%grid%lon_e)) deallocate(this%grid%lon_e)
+ IF (allocated(this%grid%rlon )) deallocate(this%grid%rlon )
+ IF (allocated(this%grid%rlat )) deallocate(this%grid%rlat )
+
+ IF (allocated(yn)) deallocate(yn)
+ IF (allocated(ys)) deallocate(ys)
+ IF (allocated(xw)) deallocate(xw)
+ IF (allocated(xe)) deallocate(xe)
+
+ IF (allocated(rlon_pset)) deallocate(rlon_pset)
+ IF (allocated(rlat_pset)) deallocate(rlat_pset)
+
+ IF (allocated(nwgt)) deallocate(nwgt)
+ IF (allocated(swgt)) deallocate(swgt)
+ IF (allocated(wwgt)) deallocate(wwgt)
+ IF (allocated(ewgt)) deallocate(ewgt)
+
+ IF (allocated(msk)) deallocate(msk)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ END SUBROUTINE spatial_mapping_build_bilinear
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_set_missing_value (this, gdata, missing_value, pmask)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_2d), intent(in) :: gdata
+ real(r8), intent(in) :: missing_value
+
+ logical, intent(inout), optional :: pmask(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart, iblkme
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+
+ this%has_missing_value = .true.
+ this%missing_value = missing_value
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gbuff(ig) = gdata%blk(xblk,yblk)%val(xloc,yloc)
+
+ ENDDO
+
+#ifdef USEMPI
+ idest = p_address_compute(iproc)
+ CALL mpi_send (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ WHERE (gdata%blk(xblk,yblk)%val == missing_value)
+ this%areagrid%blk(xblk,yblk)%val = 0.
+ ENDWHERE
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_active(iproc)
+ CALL mpi_recv (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ pbuff(0)%val = gbuff
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+
+ DO iset = 1, this%npset
+
+ this%areapset(iset) = 0.
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ IF (pbuff(iproc)%val(iloc) == missing_value) THEN
+ this%areapart(iset)%val(ipart) = 0.
+ ELSE
+ this%areapset(iset) = this%areapset(iset) + this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+
+ IF (present(pmask)) THEN
+ pmask(iset) = (this%areapset(iset) > 0.)
+ ENDIF
+
+ ENDDO
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_set_missing_value
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_pset2grid_2d (this, pdata, gdata, spv, msk, input_mode)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ real(r8), intent(in) :: pdata(:)
+ type(block_data_real8_2d), intent(inout) :: gdata
+
+ real(r8), intent(in), optional :: spv
+ logical, intent(in), optional :: msk(:)
+
+ character(len=*), intent(in), optional :: input_mode
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+ character(len=256) :: inmode
+ real(r8) :: sumwt
+
+ IF (p_is_compute) THEN
+
+ inmode = 'average'
+ IF (present(input_mode)) inmode = trim(input_mode)
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+
+ IF (present(spv)) THEN
+ pbuff(iproc)%val(:) = spv
+ ELSE
+ pbuff(iproc)%val(:) = 0.0
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+
+ IF (present(spv)) THEN
+ IF (pdata(iset) == spv) CYCLE
+ ENDIF
+
+ IF (present(msk)) THEN
+ IF (.not. msk(iset)) CYCLE
+ ENDIF
+
+ IF ((this%npart(iset) > 0) .and. (trim(inmode) == 'total')) THEN
+ sumwt = sum(this%areapart(iset)%val)
+ ELSE
+ sumwt = 1.
+ ENDIF
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ IF (present(spv)) THEN
+ IF (pbuff(iproc)%val(iloc) /= spv) THEN
+ pbuff(iproc)%val(iloc) = pbuff(iproc)%val(iloc) &
+ + pdata(iset)/sumwt * this%areapart(iset)%val(ipart)
+ ELSE
+ pbuff(iproc)%val(iloc) = &
+ pdata(iset)/sumwt * this%areapart(iset)%val(ipart)
+ ENDIF
+ ELSE
+ pbuff(iproc)%val(iloc) = pbuff(iproc)%val(iloc) &
+ + pdata(iset)/sumwt * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ IF (present(spv)) THEN
+ CALL flush_block_data (gdata, spv)
+ ELSE
+ CALL flush_block_data (gdata, 0.0_r8)
+ ENDIF
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ IF (present(spv)) THEN
+ IF (gbuff(ig) /= spv) THEN
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ IF (gdata%blk(xblk,yblk)%val(xloc,yloc) /= spv) THEN
+ gdata%blk(xblk,yblk)%val(xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(xloc,yloc) + gbuff(ig)
+ ELSE
+ gdata%blk(xblk,yblk)%val(xloc,yloc) = gbuff(ig)
+ ENDIF
+ ENDIF
+ ELSE
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gdata%blk(xblk,yblk)%val(xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(xloc,yloc) + gbuff(ig)
+ ENDIF
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+
+ END SUBROUTINE spatial_mapping_pset2grid_2d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_pset2grid_3d (this, pdata, gdata, spv, msk)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ real(r8), intent(in) :: pdata(:,:)
+ type(block_data_real8_3d), intent(inout) :: gdata
+
+ real(r8), intent(in), optional :: spv
+ logical, intent(in), optional :: msk(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, iloc, iset, ipart
+ integer :: xblk, yblk, xloc, yloc
+ integer :: lb1, ub1, i1
+
+ real(r8), allocatable :: gbuff(:,:)
+ type(pointer_real8_2d), allocatable :: pbuff(:)
+
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ lb1 = lbound(pdata,1)
+ ub1 = ubound(pdata,1)
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (lb1:ub1, this%glist(iproc)%ng))
+
+ IF (present(spv)) THEN
+ pbuff(iproc)%val(:,:) = spv
+ ELSE
+ pbuff(iproc)%val(:,:) = 0.0
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+ IF (present(msk)) THEN
+ IF (.not. msk(iset)) CYCLE
+ ENDIF
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ DO i1 = lb1, ub1
+ IF (present(spv)) THEN
+ IF (pdata(i1,iset) /= spv) THEN
+ IF (pbuff(iproc)%val(i1,iloc) /= spv) THEN
+ pbuff(iproc)%val(i1,iloc) = pbuff(iproc)%val(i1,iloc) &
+ + pdata(i1,iset) * this%areapart(iset)%val(ipart)
+ ELSE
+ pbuff(iproc)%val(i1,iloc) = &
+ pdata(i1,iset) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDIF
+ ELSE
+ pbuff(iproc)%val(i1,iloc) = pbuff(iproc)%val(i1,iloc) &
+ + pdata(i1,iset) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, &
+ (ub1-lb1+1) * this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ lb1 = gdata%lb1
+ ub1 = gdata%ub1
+
+ IF (present(spv)) THEN
+ CALL flush_block_data (gdata, spv)
+ ELSE
+ CALL flush_block_data (gdata, 0.0_r8)
+ ENDIF
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (lb1:ub1, this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, &
+ (ub1-lb1+1) * this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ DO i1 = lb1, ub1
+ IF (present(spv)) THEN
+ IF (gbuff(i1,ig) /= spv) THEN
+ IF (gdata%blk(xblk,yblk)%val(i1,xloc,yloc) /= spv) THEN
+ gdata%blk(xblk,yblk)%val(i1,xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(i1,xloc,yloc) + gbuff(i1,ig)
+ ELSE
+ gdata%blk(xblk,yblk)%val(i1,xloc,yloc) = gbuff(i1,ig)
+ ENDIF
+ ENDIF
+ ELSE
+ gdata%blk(xblk,yblk)%val(i1,xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(i1,xloc,yloc) + gbuff(i1,ig)
+ ENDIF
+ ENDDO
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_pset2grid_3d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_pset2grid_4d (this, pdata, gdata, spv, msk)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ real(r8), intent(in) :: pdata(:,:,:)
+ type(block_data_real8_4d), intent(inout) :: gdata
+
+ real(r8), intent(in), optional :: spv
+ logical, intent(in), optional :: msk(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, iloc, iset, ipart
+ integer :: xblk, yblk, xloc, yloc
+ integer :: lb1, ub1, i1, ndim1, lb2, ub2, i2, ndim2
+
+ real(r8), allocatable :: gbuff(:,:,:)
+ type(pointer_real8_3d), allocatable :: pbuff(:)
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ lb1 = lbound(pdata,1)
+ ub1 = ubound(pdata,1)
+ ndim1 = ub1 - lb1 + 1
+
+ lb2 = lbound(pdata,2)
+ ub2 = ubound(pdata,2)
+ ndim2 = ub2 - lb2 + 1
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (lb1:ub1, lb2:ub2, this%glist(iproc)%ng))
+
+ IF (present(spv)) THEN
+ pbuff(iproc)%val(:,:,:) = spv
+ ELSE
+ pbuff(iproc)%val(:,:,:) = 0.0
+ ENDIF
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+ IF (present(msk)) THEN
+ IF (.not. msk(iset)) CYCLE
+ ENDIF
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ DO i1 = lb1, ub1
+ DO i2 = lb2, ub2
+ IF (present(spv)) THEN
+ IF (pdata(i1,i2,iset) /= spv) THEN
+ IF (pbuff(iproc)%val(i1,i2,iloc) /= spv) THEN
+ pbuff(iproc)%val(i1,i2,iloc) = pbuff(iproc)%val(i1,i2,iloc) &
+ + pdata(i1,i2,iset) * this%areapart(iset)%val(ipart)
+ ELSE
+ pbuff(iproc)%val(i1,i2,iloc) = &
+ pdata(i1,i2,iset) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDIF
+ ELSE
+ pbuff(iproc)%val(i1,i2,iloc) = pbuff(iproc)%val(i1,i2,iloc) &
+ + pdata(i1,i2,iset) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, ndim1 * ndim2 * this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ lb1 = gdata%lb1
+ ub1 = gdata%ub1
+ ndim1 = ub1 - lb1 + 1
+
+ lb2 = gdata%lb2
+ ub2 = gdata%ub2
+ ndim2 = ub2 - lb2 + 1
+
+ IF (present(spv)) THEN
+ CALL flush_block_data (gdata, spv)
+ ELSE
+ CALL flush_block_data (gdata, 0.0_r8)
+ ENDIF
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (lb1:ub1, lb2:ub2, this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, ndim1 * ndim2 * this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ DO i1 = lb1, ub1
+ DO i2 = lb2, ub2
+ IF (present(spv)) THEN
+ IF (gbuff(i1,i2,ig) /= spv) THEN
+ IF (gdata%blk(xblk,yblk)%val(i1,i2,xloc,yloc) /= spv) THEN
+ gdata%blk(xblk,yblk)%val(i1,i2,xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(i1,i2,xloc,yloc) + gbuff(i1,i2,ig)
+ ELSE
+ gdata%blk(xblk,yblk)%val(i1,i2,xloc,yloc) = gbuff(i1,i2,ig)
+ ENDIF
+ ENDIF
+ ELSE
+ gdata%blk(xblk,yblk)%val(i1,i2,xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(i1,i2,xloc,yloc) + gbuff(i1,i2,ig)
+ ENDIF
+ ENDDO
+ ENDDO
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_pset2grid_4d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_pset2grid_max (this, pdata, gdata, spv, msk)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ real(r8), intent(in) :: pdata(:)
+ type(block_data_real8_2d), intent(inout) :: gdata
+
+ real(r8), intent(in), optional :: spv
+ logical, intent(in), optional :: msk(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+ pbuff(iproc)%val(:) = spval
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+
+ IF (present(spv)) THEN
+ IF (pdata(iset) == spv) CYCLE
+ ENDIF
+
+ IF (present(msk)) THEN
+ IF (.not. msk(iset)) CYCLE
+ ENDIF
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ IF (pbuff(iproc)%val(iloc) /= spval) THEN
+ pbuff(iproc)%val(iloc) = max(pdata(iset), pbuff(iproc)%val(iloc))
+ ELSE
+ pbuff(iproc)%val(iloc) = pdata(iset)
+ ENDIF
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ CALL flush_block_data (gdata, spval)
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ IF (gbuff(ig) /= spval) THEN
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ IF (gdata%blk(xblk,yblk)%val(xloc,yloc) /= spval) THEN
+ gdata%blk(xblk,yblk)%val(xloc,yloc) = &
+ max(gdata%blk(xblk,yblk)%val(xloc,yloc), gbuff(ig))
+ ELSE
+ gdata%blk(xblk,yblk)%val(xloc,yloc) = gbuff(ig)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_pset2grid_max
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_pset2grid_split (this, pdata, settyp, typidx, gdata, spv)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ real(r8), intent(in) :: pdata (:)
+ integer , intent(in) :: settyp(:)
+ integer , intent(in) :: typidx(:)
+ type(block_data_real8_3d), intent(inout) :: gdata
+
+ real(r8), intent(in) :: spv
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, iloc, iset, ipart, ityp, ntyps
+ integer :: xblk, yblk, xloc, yloc
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff (:)
+
+ IF (p_is_compute) THEN
+ allocate (pbuff (0:p_np_active-1))
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (p_is_active) THEN
+ CALL flush_block_data (gdata, spv)
+ ENDIF
+
+ ntyps = size(typidx)
+
+ DO ityp = 1, ntyps
+
+ IF (p_is_compute) THEN
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ pbuff(iproc)%val(:) = spv
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+ IF ((settyp(iset) == typidx(ityp)) .and. (pdata(iset) /= spv)) THEN
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ IF (pbuff(iproc)%val(iloc) /= spv) THEN
+ pbuff(iproc)%val(iloc) = pbuff(iproc)%val(iloc) &
+ + pdata(iset) * this%areapart(iset)%val(ipart)
+ ELSE
+ pbuff(iproc)%val(iloc) = &
+ pdata(iset) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ IF (gbuff(ig) /= spv) THEN
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ IF (gdata%blk(xblk,yblk)%val(ityp,xloc,yloc) /= spv) THEN
+ gdata%blk(xblk,yblk)%val(ityp,xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(ityp,xloc,yloc) + gbuff(ig)
+ ELSE
+ gdata%blk(xblk,yblk)%val(ityp,xloc,yloc) = gbuff(ig)
+ ENDIF
+ ENDIF
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ ENDDO
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_pset2grid_split
+
+ ! ------------------------------
+ SUBROUTINE spatial_mapping_get_sumarea (this, sumarea, filter)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_2d), intent(inout) :: sumarea
+ logical, intent(in), optional :: filter(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+
+#ifdef MPAS_EMBEDDED_COLM
+ IF (p_is_active) CALL flush_block_data (sumarea, 0.0_r8)
+
+ IF (p_is_compute) THEN
+ DO iset = 1, this%npset
+
+ IF (present(filter)) THEN
+ IF (.not. filter(iset)) CYCLE
+ ENDIF
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ IF (p_address_active(iproc) /= p_iam_glb) CYCLE
+
+ iloc = this%address(iset)%val(2,ipart)
+ ilon = this%glist(iproc)%ilon(iloc)
+ ilat = this%glist(iproc)%ilat(iloc)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ sumarea%blk(xblk,yblk)%val(xloc,yloc) = &
+ sumarea%blk(xblk,yblk)%val(xloc,yloc) + this%areapart(iset)%val(ipart)
+ ENDDO
+ ENDDO
+ ENDIF
+
+ RETURN
+#endif
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+ pbuff(iproc)%val(:) = 0.0
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+
+ IF (present(filter)) THEN
+ IF (.not. filter(iset)) CYCLE
+ ENDIF
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+ pbuff(iproc)%val(iloc) = pbuff(iproc)%val(iloc) + this%areapart(iset)%val(ipart)
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ CALL flush_block_data (sumarea, 0.0_r8)
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ sumarea%blk(xblk,yblk)%val(xloc,yloc) = &
+ sumarea%blk(xblk,yblk)%val(xloc,yloc) + gbuff(ig)
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_get_sumarea
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_grid2pset_2d (this, gdata, pdata)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_2d), intent(in) :: gdata
+ real(r8), intent(out) :: pdata(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gbuff(ig) = gdata%blk(xblk,yblk)%val(xloc,yloc)
+
+ ENDDO
+
+#ifdef USEMPI
+ idest = p_address_compute(iproc)
+ CALL mpi_send (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_active(iproc)
+ CALL mpi_recv (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ pbuff(0)%val = gbuff
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+
+ IF (this%areapset(iset) > 0.) THEN
+
+ pdata(iset) = 0.
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ IF (this%areapart(iset)%val(ipart) > 0) THEN
+ pdata(iset) = pdata(iset) &
+ + pbuff(iproc)%val(iloc) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+
+ pdata(iset) = pdata(iset) / this%areapset(iset)
+
+ ELSE
+ pdata(iset) = spval
+ ENDIF
+
+ ENDDO
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_grid2pset_2d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_grid2pset_3d (this, gdata, ndim1, pdata)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_3d), intent(in) :: gdata
+ integer, intent(in) :: ndim1
+ real(r8), intent(out) :: pdata(:,:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart, i
+
+ real(r8), allocatable :: gbuff(:,:)
+ type(pointer_real8_2d), allocatable :: pbuff(:)
+
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (ndim1, this%glist(iproc)%ng))
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gbuff(:,ig) = gdata%blk(xblk,yblk)%val(:,xloc,yloc)
+ ENDDO
+
+#ifdef USEMPI
+ idest = p_address_compute(iproc)
+ CALL mpi_send (gbuff, ndim1 * this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (pbuff(iproc)%val (ndim1, this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_active(iproc)
+ CALL mpi_recv (pbuff(iproc)%val, ndim1 * this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ pbuff(0)%val = gbuff
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+
+ DO iset = 1, this%npset
+
+ IF (this%areapset(iset) > 0.) THEN
+
+ pdata(:,iset) = 0.
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ IF (this%areapart(iset)%val(ipart) > 0) THEN
+ pdata(:,iset) = pdata(:,iset) &
+ + pbuff(iproc)%val(:,iloc) * this%areapart(iset)%val(ipart)
+ ENDIF
+ ENDDO
+
+ pdata(:,iset) = pdata(:,iset) / this%areapset(iset)
+
+ ELSE
+ pdata(:,iset) = spval
+ ENDIF
+
+ ENDDO
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_grid2pset_3d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_dominant_2d (this, gdata, pdata)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_int32_2d), intent(in) :: gdata
+ integer, intent(out) :: pdata(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ integer, allocatable :: gbuff(:)
+ type(pointer_int32_1d), allocatable :: pbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gbuff(ig) = gdata%blk(xblk,yblk)%val(xloc,yloc)
+
+ ENDDO
+
+#ifdef USEMPI
+ idest = p_address_compute(iproc)
+ CALL mpi_send (gbuff, this%glist(iproc)%ng, MPI_INTEGER, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_active(iproc)
+ CALL mpi_recv (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_INTEGER, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ pbuff(0)%val = gbuff
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+ IF (this%areapset(iset) > 0.) THEN
+ ipart = maxloc(this%areapart(iset)%val, dim=1)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+ pdata(iset) = pbuff(iproc)%val(iloc)
+ ELSE
+ pdata(iset) = -9999
+ ENDIF
+ ENDDO
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+
+ deallocate (pbuff)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_dominant_2d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_varvalue_2d (this, gdata, pdata)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_2d), intent(in) :: gdata
+ real(r8), intent(inout) :: pdata(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+ real(r8), allocatable :: pdata_tem(:)
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gbuff(ig) = gdata%blk(xblk,yblk)%val(xloc,yloc)
+
+ ENDDO
+
+#ifdef USEMPI
+ idest = p_address_compute(iproc)
+ CALL mpi_send (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+ allocate (pdata_tem (size(pdata)))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_active(iproc)
+ CALL mpi_recv (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ pbuff(0)%val = gbuff
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+
+ IF (this%areapset(iset) > 0.) THEN
+
+ pdata_tem(iset) = 0._r8
+
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ pdata_tem(iset) = pdata_tem(iset) &
+ + pdata(iset) * pbuff(iproc)%val(iloc) * this%areapart(iset)%val(ipart)
+ ENDDO
+
+ pdata_tem(iset) = pdata_tem(iset) / this%areapset(iset)
+
+ ELSE
+ pdata_tem(iset) = 0._r8
+ ENDIF
+
+ ENDDO
+
+ pdata = pdata_tem
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ deallocate (pdata_tem)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_varvalue_2d
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_grid2part (this, gdata, sdata)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_2d), intent(in) :: gdata
+ type(pointer_real8_1d), intent(inout) :: sdata(:)
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+
+ IF (p_is_active) THEN
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gbuff(ig) = gdata%blk(xblk,yblk)%val(xloc,yloc)
+
+ ENDDO
+
+#ifdef USEMPI
+ idest = p_address_compute(iproc)
+ CALL mpi_send (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_active(iproc)
+ CALL mpi_recv (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ pbuff(0)%val = gbuff
+ deallocate (gbuff)
+#endif
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ sdata(iset)%val(ipart) = pbuff(iproc)%val(iloc)
+ ENDDO
+ ENDDO
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_grid2part
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_part2grid (this, sdata, gdata)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(pointer_real8_1d), intent(in) :: sdata(:)
+ type(block_data_real8_2d), intent(inout) :: gdata
+
+ ! Local variables
+ integer :: iproc, idest, isrc
+ integer :: ig, ilon, ilat, xblk, yblk, xloc, yloc, iloc, iset, ipart
+ integer :: iblkme
+
+ real(r8), allocatable :: gbuff(:)
+ type(pointer_real8_1d), allocatable :: pbuff(:)
+
+ IF (p_is_compute) THEN
+
+ allocate (pbuff (0:p_np_active-1))
+
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ allocate (pbuff(iproc)%val (this%glist(iproc)%ng))
+ pbuff(iproc)%val(:) = 0.0
+ ENDIF
+ ENDDO
+
+ DO iset = 1, this%npset
+ DO ipart = 1, this%npart(iset)
+ iproc = this%address(iset)%val(1,ipart)
+ iloc = this%address(iset)%val(2,ipart)
+
+ pbuff(iproc)%val(iloc) = pbuff(iproc)%val(iloc) &
+ + sdata(iset)%val(ipart) * this%areapart(iset)%val(ipart)
+ ENDDO
+ ENDDO
+
+#ifdef USEMPI
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ idest = p_address_active(iproc)
+ CALL mpi_send (pbuff(iproc)%val, this%glist(iproc)%ng, MPI_REAL8, &
+ idest, mpi_tag_data, p_comm_glb, p_err)
+ ENDIF
+ ENDDO
+#endif
+
+ ENDIF
+
+ IF (p_is_active) THEN
+
+ CALL flush_block_data (gdata, 0.0_r8)
+
+ DO iproc = 0, p_np_compute-1
+ IF (this%glist(iproc)%ng > 0) THEN
+
+ allocate (gbuff (this%glist(iproc)%ng))
+
+#ifdef USEMPI
+ isrc = p_address_compute(iproc)
+ CALL mpi_recv (gbuff, this%glist(iproc)%ng, MPI_REAL8, &
+ isrc, mpi_tag_data, p_comm_glb, p_stat, p_err)
+#else
+ gbuff = pbuff(0)%val
+#endif
+
+ DO ig = 1, this%glist(iproc)%ng
+ ilon = this%glist(iproc)%ilon(ig)
+ ilat = this%glist(iproc)%ilat(ig)
+ xblk = this%grid%xblk (ilon)
+ yblk = this%grid%yblk (ilat)
+ xloc = this%grid%xloc (ilon)
+ yloc = this%grid%yloc (ilat)
+
+ gdata%blk(xblk,yblk)%val(xloc,yloc) = &
+ gdata%blk(xblk,yblk)%val(xloc,yloc) + gbuff(ig)
+ ENDDO
+
+ deallocate (gbuff)
+ ENDIF
+ ENDDO
+
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ WHERE (this%areagrid%blk(xblk,yblk)%val > 0)
+ gdata%blk(xblk,yblk)%val = &
+ gdata%blk(xblk,yblk)%val / this%areagrid%blk(xblk,yblk)%val
+ ELSEWHERE
+ gdata%blk(xblk,yblk)%val = this%missing_value
+ ENDWHERE
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+ DO iproc = 0, p_np_active-1
+ IF (this%glist(iproc)%ng > 0) THEN
+ deallocate (pbuff(iproc)%val)
+ ENDIF
+ ENDDO
+ deallocate (pbuff)
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_part2grid
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_normalize (this, gdata, sdata)
+
+ USE MOD_Precision
+ USE MOD_Block
+ USE MOD_Grid
+ USE MOD_Pixelset
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(block_data_real8_2d), intent(in) :: gdata
+ type(pointer_real8_1d), intent(inout) :: sdata(:)
+
+ ! Local variables
+ integer :: iblkme, xblk, yblk, iset, ipart
+
+ type(block_data_real8_2d) :: sumdata
+ type(pointer_real8_1d), allocatable :: scaldata(:)
+
+
+ IF (p_is_active) CALL allocate_block_data (this%grid, sumdata)
+ IF (p_is_compute) CALL this%allocate_part (scaldata)
+
+ CALL this%part2grid (sdata, sumdata)
+
+ IF (p_is_active) THEN
+
+ DO iblkme = 1, gblock%nblkme
+ xblk = gblock%xblkme(iblkme)
+ yblk = gblock%yblkme(iblkme)
+
+ WHERE (sumdata%blk(xblk,yblk)%val /= this%missing_value)
+ sumdata%blk(xblk,yblk)%val = gdata%blk(xblk,yblk)%val / sumdata%blk(xblk,yblk)%val
+ ENDWHERE
+ ENDDO
+
+ ENDIF
+
+ CALL this%grid2part (sumdata, scaldata)
+
+ IF (p_is_compute) THEN
+
+ DO iset = 1, this%npset
+ DO ipart = 1, this%npart(iset)
+ IF (this%areapart(iset)%val(ipart) > 0.) THEN
+ sdata(iset)%val(ipart) = sdata(iset)%val(ipart) * scaldata(iset)%val(ipart)
+ ELSE
+ sdata(iset)%val(ipart) = this%missing_value
+ ENDIF
+ ENDDO
+ ENDDO
+
+ ENDIF
+
+ IF (p_is_compute) deallocate(scaldata)
+
+ END SUBROUTINE spatial_mapping_normalize
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_part2pset (this, sdata, pdata)
+
+ USE MOD_Precision
+ USE MOD_Grid
+ USE MOD_DataType
+ USE MOD_SPMD_Task
+ USE MOD_Vars_Global, only: spval
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(pointer_real8_1d), intent(in) :: sdata(:)
+ real(r8), intent(out) :: pdata(:)
+
+ ! Local variables
+ integer :: iset
+
+ IF (p_is_compute) THEN
+
+ pdata(:) = spval
+
+ DO iset = 1, this%npset
+ IF (this%areapset(iset) > 0) THEN
+ pdata(iset) = sum(sdata(iset)%val * this%areapart(iset)%val) / this%areapset(iset)
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_part2pset
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_allocate_part (this, datapart)
+
+ USE MOD_SPMD_Task
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(pointer_real8_1d), allocatable :: datapart (:)
+
+ ! Local variables
+ integer :: iset
+
+ IF (p_is_compute) THEN
+
+ IF (this%npset > 0) THEN
+ allocate (datapart (this%npset))
+ ENDIF
+
+ DO iset = 1, this%npset
+ IF (this%npart(iset) > 0) THEN
+ allocate (datapart(iset)%val (this%npart(iset)))
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_allocate_part
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_deallocate_part (this, datapart)
+
+ USE MOD_SPMD_Task
+ USE MOD_DataType
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ type(pointer_real8_1d), allocatable :: datapart (:)
+
+ ! Local variables
+ integer :: iset
+
+ IF (p_is_compute) THEN
+
+ DO iset = 1, this%npset
+ IF (this%npart(iset) > 0) THEN
+ deallocate (datapart(iset)%val)
+ ENDIF
+ ENDDO
+
+ IF (this%npset > 0) THEN
+ deallocate (datapart)
+ ENDIF
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_deallocate_part
+
+ !-----------------------------------------------------
+ SUBROUTINE spatial_mapping_free_mem (this)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ type (spatial_mapping_type) :: this
+
+ ! Local variables
+ integer :: iproc, iset
+
+ IF (allocated (this%grid%xblk)) deallocate (this%grid%xblk)
+ IF (allocated (this%grid%yblk)) deallocate (this%grid%yblk)
+
+ IF (allocated (this%grid%xloc)) deallocate (this%grid%xloc)
+ IF (allocated (this%grid%yloc)) deallocate (this%grid%yloc)
+
+ IF (allocated (this%grid%xcnt)) deallocate (this%grid%xcnt)
+ IF (allocated (this%grid%ycnt)) deallocate (this%grid%ycnt)
+
+ IF (allocated(this%glist)) THEN
+ DO iproc = lbound(this%glist,1), ubound(this%glist,1)
+ IF (allocated(this%glist(iproc)%ilat)) deallocate (this%glist(iproc)%ilat)
+ IF (allocated(this%glist(iproc)%ilon)) deallocate (this%glist(iproc)%ilon)
+ ENDDO
+
+ deallocate (this%glist)
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (allocated(this%npart)) deallocate(this%npart)
+
+ IF (allocated(this%address)) THEN
+ DO iset = lbound(this%address,1), ubound(this%address,1)
+ IF (allocated(this%address(iset)%val)) THEN
+ deallocate (this%address(iset)%val)
+ ENDIF
+ ENDDO
+
+ deallocate (this%address)
+ ENDIF
+
+ IF (allocated(this%areapart)) THEN
+ DO iset = lbound(this%areapart,1), ubound(this%areapart,1)
+ IF (allocated(this%areapart(iset)%val)) THEN
+ deallocate (this%areapart(iset)%val)
+ ENDIF
+ ENDDO
+
+ deallocate (this%areapart)
+ ENDIF
+
+ IF (allocated(this%areapset)) deallocate(this%areapset)
+
+ ENDIF
+
+ END SUBROUTINE spatial_mapping_free_mem
+
+ SUBROUTINE forc_free_mem_spatial_mapping(this)
+
+ USE MOD_SPMD_Task
+ IMPLICIT NONE
+
+ class (spatial_mapping_type) :: this
+
+ ! Local variables
+ integer :: iproc, iset
+
+ IF (allocated (this%grid%xblk)) deallocate (this%grid%xblk)
+ IF (allocated (this%grid%yblk)) deallocate (this%grid%yblk)
+
+ IF (allocated (this%grid%xloc)) deallocate (this%grid%xloc)
+ IF (allocated (this%grid%yloc)) deallocate (this%grid%yloc)
+
+ IF (allocated (this%grid%xcnt)) deallocate (this%grid%xcnt)
+ IF (allocated (this%grid%ycnt)) deallocate (this%grid%ycnt)
+
+ IF (allocated(this%glist)) THEN
+ DO iproc = lbound(this%glist,1), ubound(this%glist,1)
+ IF (allocated(this%glist(iproc)%ilat)) deallocate (this%glist(iproc)%ilat)
+ IF (allocated(this%glist(iproc)%ilon)) deallocate (this%glist(iproc)%ilon)
+ ENDDO
+
+ deallocate (this%glist)
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ IF (allocated(this%npart)) deallocate(this%npart)
+
+ IF (allocated(this%address)) THEN
+ DO iset = lbound(this%address,1), ubound(this%address,1)
+ IF (allocated(this%address(iset)%val)) THEN
+ deallocate (this%address(iset)%val)
+ ENDIF
+ ENDDO
+
+ deallocate (this%address)
+ ENDIF
+
+ IF (allocated(this%areapart)) THEN
+ DO iset = lbound(this%areapart,1), ubound(this%areapart,1)
+ IF (allocated(this%areapart(iset)%val)) THEN
+ deallocate (this%areapart(iset)%val)
+ ENDIF
+ ENDDO
+
+ deallocate (this%areapart)
+ ENDIF
+
+ IF (allocated(this%areapset)) deallocate(this%areapset)
+
+ ENDIF
+
+ END SUBROUTINE forc_free_mem_spatial_mapping
+
+END MODULE MOD_SpatialMapping
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_SrfdataRestart.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SrfdataRestart.F90
new file mode 100644
index 0000000000..f56f51a1f0
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_SrfdataRestart.F90
@@ -0,0 +1,837 @@
+#include
+
+MODULE MOD_SrfdataRestart
+!-----------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! This module includes subroutines to read/write data of mesh and pixelsets.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ ! ----- subroutines -----
+ PUBLIC :: mesh_save_to_file
+ PUBLIC :: mesh_load_from_file
+
+ PUBLIC :: pixelset_save_to_file
+ PUBLIC :: pixelset_load_from_file
+
+CONTAINS
+
+ ! -----------------------
+ SUBROUTINE mesh_save_to_file (dir_landdata, lc_year)
+
+ USE MOD_SPMD_Task
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh
+ USE MOD_Block
+ USE MOD_Utils
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: dir_landdata
+ integer , intent(in) :: lc_year
+
+ ! Local variables
+ character(len=256) :: filename, fileblock, cyear
+ integer :: ie, je, nelm, totlen, tothis, iblk, jblk, owner_rank, i
+ integer, allocatable :: nelm_rank(:), ndsp_rank(:)
+ integer*8, allocatable :: elmindx(:)
+ integer, allocatable :: npxlall(:)
+ integer, allocatable :: elmpixels(:,:)
+ real(r8), allocatable :: lon(:), lat(:)
+
+ integer :: nsend, nrecv, ndone, ndsp
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL CoLM_stop('MPAS embedded CoLM does not support standalone mesh_save_to_file.')
+#endif
+
+ ! add parameter input for time year
+ write(cyear,'(i4.4)') lc_year
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ IF (p_is_root) THEN
+ write(*,*) 'Saving land elements ...'
+ CALL system('mkdir -p ' // trim(dir_landdata) // '/mesh/' // trim(cyear))
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ filename = trim(dir_landdata) // '/mesh/' //trim(cyear) // '/mesh.nc'
+
+ DO jblk = 1, gblock%nyblk
+ DO iblk = 1, gblock%nxblk
+
+#ifdef USEMPI
+ IF (p_is_compute) THEN
+ IF (gblock%pio(iblk,jblk) == p_address_active(p_my_group)) THEN
+#endif
+ nelm = 0
+ totlen = 0
+ DO ie = 1, numelm
+ IF ((mesh(ie)%xblk == iblk) .and. (mesh(ie)%yblk == jblk)) THEN
+ nelm = nelm + 1
+ totlen = totlen + mesh(ie)%npxl
+ ENDIF
+ ENDDO
+
+ IF (nelm > 0) THEN
+
+ allocate (elmindx (nelm))
+ allocate (npxlall (nelm))
+ allocate (elmpixels (2,totlen))
+
+ je = 0
+ ndsp = 0
+ DO ie = 1, numelm
+ IF ((mesh(ie)%xblk == iblk) .and. (mesh(ie)%yblk == jblk)) THEN
+ je = je + 1
+ elmindx(je) = mesh(ie)%indx
+ npxlall(je) = mesh(ie)%npxl
+
+ elmpixels(1,ndsp+1:ndsp+npxlall(je)) = mesh(ie)%ilon
+ elmpixels(2,ndsp+1:ndsp+npxlall(je)) = mesh(ie)%ilat
+
+ ndsp = ndsp + npxlall(je)
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_gather (nelm, 1, MPI_INTEGER, &
+ MPI_INULL_P, 1, MPI_INTEGER, p_root, p_comm_group, p_err)
+
+ CALL mpi_gatherv (elmindx, nelm, MPI_INTEGER8, &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER8, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ CALL mpi_gatherv (npxlall, nelm, MPI_INTEGER, &
+ MPI_INULL_P, MPI_INULL_P, MPI_INULL_P, MPI_INTEGER, & ! unused on non-root ranks
+ p_root, p_comm_group, p_err)
+
+ ndone = 0
+ DO WHILE (ndone < totlen)
+ nsend = max(min(totlen-ndone, MesgMaxSize/8), 1)
+ CALL mpi_send (nsend, 1, &
+ MPI_INTEGER, p_root, mpi_tag_size, p_comm_group, p_err)
+ CALL mpi_send (elmpixels(:,ndone+1:ndone+nsend), 2*nsend, &
+ MPI_INTEGER, p_root, mpi_tag_data, p_comm_group, p_err)
+ ndone = ndone + nsend
+ ENDDO
+ ENDIF
+ ENDIF
+#endif
+
+#ifdef USEMPI
+ IF (p_is_active) THEN
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+
+ allocate (nelm_rank (0:p_np_group-1))
+ nelm_rank(0) = 0
+ CALL mpi_gather (MPI_IN_PLACE, 0, MPI_INTEGER, &
+ nelm_rank, 1, MPI_INTEGER, p_root, p_comm_group, p_err)
+
+ nelm = sum(nelm_rank)
+
+ allocate (ndsp_rank(0:p_np_group-1))
+ ndsp_rank(0) = 0
+ DO owner_rank = 1, p_np_group-1
+ ndsp_rank(owner_rank) = ndsp_rank(owner_rank-1) + nelm_rank(owner_rank-1)
+ ENDDO
+
+ allocate (elmindx (nelm))
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_INTEGER8, &
+ elmindx, nelm_rank(0:), ndsp_rank(0:), MPI_INTEGER8, &
+ p_root, p_comm_group, p_err)
+
+ allocate (npxlall (nelm))
+ CALL mpi_gatherv (MPI_IN_PLACE, 0, MPI_INTEGER, &
+ npxlall, nelm_rank(0:), ndsp_rank(0:), MPI_INTEGER, &
+ p_root, p_comm_group, p_err)
+
+ totlen = sum(npxlall)
+ allocate (elmpixels (2, totlen))
+
+ ndone = 0
+ DO owner_rank = 1, p_np_group-1
+
+ ndsp = ndsp_rank(owner_rank)
+ tothis = ndone + sum(npxlall(ndsp+1:ndsp+nelm_rank(owner_rank)))
+
+ DO WHILE (ndone < tothis)
+
+ CALL mpi_recv (nrecv, 1, &
+ MPI_INTEGER, owner_rank, mpi_tag_size, p_comm_group, p_stat, p_err)
+ CALL mpi_recv (elmpixels(:,ndone+1:ndone+nrecv), 2*nrecv, &
+ MPI_INTEGER, owner_rank, mpi_tag_data, p_comm_group, p_stat, p_err)
+
+ ndone = ndone + nrecv
+ ENDDO
+ ENDDO
+ ENDIF
+ ENDIF
+#endif
+
+ IF (p_is_active) THEN
+ IF (gblock%pio(iblk,jblk) == p_iam_glb) THEN
+ IF (nelm > 0) THEN
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+ CALL ncio_create_file (fileblock)
+
+ CALL ncio_define_dimension (fileblock, 'element',nelm)
+ CALL ncio_define_dimension (fileblock, 'ncoor', 2 )
+ CALL ncio_define_dimension (fileblock, 'pixel', totlen)
+
+ CALL ncio_write_serial (fileblock, 'elmindex', elmindx, 'element')
+ CALL ncio_write_serial (fileblock, 'elmnpxl', npxlall, 'element')
+ CALL ncio_write_serial (fileblock, 'elmpixels', elmpixels, &
+ 'ncoor', 'pixel', compress = 1)
+ ENDIF
+ ENDIF
+ ENDIF
+
+ IF (allocated (elmindx)) deallocate(elmindx)
+ IF (allocated (npxlall)) deallocate(npxlall)
+ IF (allocated (elmpixels)) deallocate(elmpixels)
+
+ IF (allocated (nelm_rank)) deallocate(nelm_rank)
+ IF (allocated (ndsp_rank)) deallocate(ndsp_rank)
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_group, p_err)
+#endif
+ ENDDO
+ ENDDO
+
+ IF (p_is_root) THEN
+
+ CALL ncio_create_file (filename)
+
+ CALL ncio_define_dimension (filename, 'xblk', gblock%nxblk)
+ CALL ncio_define_dimension (filename, 'yblk', gblock%nyblk)
+ CALL ncio_write_serial (filename, 'nelm_blk', nelm_blk, 'xblk', 'yblk')
+
+ CALL ncio_define_dimension (filename, 'longitude', gridmesh%nlon)
+ CALL ncio_define_dimension (filename, 'latitude' , gridmesh%nlat)
+
+ allocate (lon (gridmesh%nlon))
+ allocate (lat (gridmesh%nlat))
+
+ DO i = 1, gridmesh%nlon
+ lon(i) = (gridmesh%lon_w(i) + gridmesh%lon_e(i)) * 0.5
+ IF (gridmesh%lon_w(i) > gridmesh%lon_e(i)) THEN
+ lon(i) = lon(i) + 180.0
+ CALL normalize_longitude (lon(i))
+ ENDIF
+ ENDDO
+ CALL ncio_write_serial (filename, 'longitude', lon, 'longitude')
+
+ DO i = 1, gridmesh%nlat
+ lat(i) = (gridmesh%lat_s(i) + gridmesh%lat_n(i)) * 0.5
+ ENDDO
+ CALL ncio_write_serial (filename, 'latitude', lat, 'latitude')
+
+#ifdef GRIDBASED
+ CALL ncio_write_serial (filename, 'lat_s', gridmesh%lat_s, 'latitude' )
+ CALL ncio_write_serial (filename, 'lat_n', gridmesh%lat_n, 'latitude' )
+ CALL ncio_write_serial (filename, 'lon_w', gridmesh%lon_w, 'longitude')
+ CALL ncio_write_serial (filename, 'lon_e', gridmesh%lon_e, 'longitude')
+#endif
+
+ deallocate (lon)
+ deallocate (lat)
+
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) write(*,*) 'SAVE land elements done.'
+
+ END SUBROUTINE mesh_save_to_file
+
+ !------------------------------------
+ SUBROUTINE prepare_subset_eindex(subset_eindex, sorted_subset)
+
+ USE MOD_Utils, only: quicksort
+ IMPLICIT NONE
+
+ integer*8, intent(in) :: subset_eindex(:)
+ integer*8, allocatable, intent(out) :: sorted_subset(:)
+
+ integer, allocatable :: order(:)
+ integer :: i
+
+ allocate(sorted_subset(size(subset_eindex)))
+ sorted_subset = subset_eindex
+
+ IF (size(sorted_subset) > 1) THEN
+ allocate(order(size(sorted_subset)))
+ order = (/ (i, i = 1, size(sorted_subset)) /)
+ CALL quicksort(size(sorted_subset), sorted_subset, order)
+ deallocate(order)
+ ENDIF
+
+ END SUBROUTINE prepare_subset_eindex
+
+ !------------------------------------
+ logical FUNCTION eindex_in_subset(eindex, sorted_subset) result(keep)
+
+ USE MOD_Utils, only: find_in_sorted_list1
+ IMPLICIT NONE
+
+ integer*8, intent(in) :: eindex
+ integer*8, allocatable, intent(in) :: sorted_subset(:)
+
+ IF (.not. allocated(sorted_subset)) THEN
+ keep = .true.
+ ELSEIF (size(sorted_subset) < 1) THEN
+ keep = .false.
+ ELSE
+ keep = find_in_sorted_list1(eindex, size(sorted_subset), sorted_subset) > 0
+ ENDIF
+
+ END FUNCTION eindex_in_subset
+
+ !------------------------------------
+ integer FUNCTION count_subset_eindex(eindex, sorted_subset) result(nkeep)
+
+ IMPLICIT NONE
+
+ integer*8, intent(in) :: eindex(:)
+ integer*8, allocatable, intent(in) :: sorted_subset(:)
+
+ integer :: i
+
+ nkeep = 0
+ DO i = 1, size(eindex)
+ IF (eindex_in_subset(eindex(i), sorted_subset)) nkeep = nkeep + 1
+ ENDDO
+
+ END FUNCTION count_subset_eindex
+
+ !------------------------------------
+ SUBROUTINE mesh_load_from_file (dir_landdata, lc_year, subset_eindex)
+
+ USE MOD_SPMD_Task
+ USE MOD_Namelist
+ USE MOD_Block
+ USE MOD_NetCDFSerial
+ USE MOD_Mesh
+ IMPLICIT NONE
+
+ integer , intent(in) :: lc_year
+ character(len=*), intent(in) :: dir_landdata
+ integer*8, optional, intent(in) :: subset_eindex(:)
+
+ ! Local variables
+ character(len=256) :: filename, fileblock, cyear
+ integer :: iblkme, iblk, jblk, ie, nelm, ndsp, pdsp
+ integer*8, allocatable :: elmindx(:)
+ integer*8, allocatable :: subset_sorted(:)
+ integer, allocatable :: datasize(:)
+ integer, allocatable :: npxl(:), pixels(:,:), pixels2d(:,:,:)
+ logical, allocatable :: keep_elm(:)
+ logical :: use_subset
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write(*,*) 'Loading land elements ...'
+ ENDIF
+
+ ! add parameter input for time year
+ write(cyear,'(i4.4)') lc_year
+ filename = trim(dir_landdata) // '/mesh/' // trim(cyear) // '/mesh.nc'
+ CALL ncio_read_bcast_serial (filename, 'nelm_blk', nelm_blk)
+ use_subset = present(subset_eindex)
+ IF (use_subset) CALL prepare_subset_eindex(subset_eindex, subset_sorted)
+
+ IF (p_is_active) THEN
+
+ CALL mesh_free_mem()
+ numelm = sum(nelm_blk, mask = gblock%pio == p_iam_glb)
+
+ IF (numelm > 0) THEN
+
+ IF (allocated(mesh)) deallocate(mesh)
+ allocate (mesh (numelm))
+
+ ndsp = 0
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+ nelm = nelm_blk(iblk,jblk)
+
+ IF (nelm > 0) THEN
+
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+ CALL ncio_read_serial (fileblock, 'elmindex', elmindx)
+ CALL ncio_read_serial (fileblock, 'elmnpxl', npxl )
+
+ IF (use_subset) THEN
+ allocate (keep_elm(nelm))
+ DO ie = 1, nelm
+ keep_elm(ie) = eindex_in_subset(elmindx(ie), subset_sorted)
+ ENDDO
+ IF (count(keep_elm) < 1) THEN
+ deallocate(keep_elm)
+ IF (allocated(elmindx)) deallocate(elmindx)
+ IF (allocated(npxl)) deallocate(npxl)
+ CYCLE
+ ENDIF
+ ENDIF
+
+ CALL ncio_inquire_varsize (fileblock, 'elmpixels', datasize)
+ IF (size(datasize) == 3) THEN
+ CALL ncio_read_serial (fileblock, 'elmpixels', pixels2d)
+ ELSE
+ CALL ncio_read_serial (fileblock, 'elmpixels', pixels)
+ ENDIF
+
+ pdsp = 0
+ DO ie = 1, nelm
+ IF (use_subset) THEN
+ IF (.not. keep_elm(ie)) THEN
+ IF (size(datasize) /= 3) pdsp = pdsp + npxl(ie)
+ CYCLE
+ ENDIF
+ ENDIF
+
+ ndsp = ndsp + 1
+ mesh(ndsp)%indx = elmindx(ie)
+ mesh(ndsp)%npxl = npxl(ie)
+ mesh(ndsp)%xblk = iblk
+ mesh(ndsp)%yblk = jblk
+
+ allocate (mesh(ndsp)%ilon (npxl(ie)))
+ allocate (mesh(ndsp)%ilat (npxl(ie)))
+
+ IF (size(datasize) == 3) THEN
+ mesh(ndsp)%ilon = pixels2d(1,1:npxl(ie),ie)
+ mesh(ndsp)%ilat = pixels2d(2,1:npxl(ie),ie)
+ ELSE
+ mesh(ndsp)%ilon = pixels(1,pdsp+1:pdsp+npxl(ie))
+ mesh(ndsp)%ilat = pixels(2,pdsp+1:pdsp+npxl(ie))
+ pdsp = pdsp + npxl(ie)
+ ENDIF
+ ENDDO
+
+ IF (allocated(keep_elm)) deallocate(keep_elm)
+ IF (allocated(elmindx)) deallocate(elmindx)
+ IF (allocated(npxl)) deallocate(npxl)
+ IF (allocated(datasize)) deallocate(datasize)
+ IF (allocated(pixels)) deallocate(pixels)
+ IF (allocated(pixels2d)) deallocate(pixels2d)
+ ENDIF
+ ENDDO
+
+ numelm = ndsp
+ IF (numelm == 0) CALL mesh_free_mem()
+ ENDIF
+
+ IF (use_subset .and. allocated(nelm_blk)) THEN
+ nelm_blk(:,:) = 0
+ DO ie = 1, numelm
+ nelm_blk(mesh(ie)%xblk, mesh(ie)%yblk) = &
+ nelm_blk(mesh(ie)%xblk, mesh(ie)%yblk) + 1
+ ENDDO
+ ENDIF
+
+ IF (allocated(elmindx )) deallocate(elmindx )
+ IF (allocated(npxl )) deallocate(npxl )
+ IF (allocated(datasize)) deallocate(datasize)
+ IF (allocated(pixels )) deallocate(pixels )
+ IF (allocated(pixels2d)) deallocate(pixels2d)
+ IF (allocated(subset_sorted)) deallocate(subset_sorted)
+
+ ENDIF
+
+#ifdef CoLMDEBUG
+ IF (p_is_active) write(*,'(I10,A,I4)') numelm, ' elements on group ', p_iam_active
+#endif
+
+#ifdef USEMPI
+#ifndef MPAS_EMBEDDED_COLM
+ CALL scatter_mesh_legacy_roles
+#endif
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) THEN
+ write(*,*) 'Loading land elements done.'
+ ENDIF
+
+ END SUBROUTINE mesh_load_from_file
+
+ !------------------------------------------------
+ SUBROUTINE pixelset_save_to_file (dir_landdata, psetname, pixelset, lc_year)
+
+ USE MOD_Namelist
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_NetCDFVector
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ character(len=*), intent(in) :: dir_landdata
+ character(len=*), intent(in) :: psetname
+ type(pixelset_type), intent(in) :: pixelset
+ integer , intent(in) :: lc_year
+
+ ! Local variables
+ character(len=256) :: filename, cyear
+
+#ifdef MPAS_EMBEDDED_COLM
+ CALL CoLM_stop('MPAS embedded CoLM does not support standalone pixelset_save_to_file.')
+#endif
+
+ write(cyear,'(i4.4)') lc_year
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+ IF (p_is_root) THEN
+ write(*,*) 'Saving Pixel Sets ' // trim(psetname) // ' ...'
+ CALL system('mkdir -p ' // trim(dir_landdata) // '/' // trim(psetname) // '/' // trim(cyear))
+ ENDIF
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ filename = trim(dir_landdata) // '/' // trim(psetname) // '/' // trim(cyear) // '/' // trim(psetname) // '.nc'
+
+ CALL ncio_create_file_vector (filename, pixelset)
+ CALL ncio_define_dimension_vector (filename, pixelset, trim(psetname))
+
+ CALL ncio_write_vector (filename, 'eindex', trim(psetname), pixelset, pixelset%eindex, DEF_Srfdata_CompressLevel)
+ CALL ncio_write_vector (filename, 'ipxstt', trim(psetname), pixelset, pixelset%ipxstt, DEF_Srfdata_CompressLevel)
+ CALL ncio_write_vector (filename, 'ipxend', trim(psetname), pixelset, pixelset%ipxend, DEF_Srfdata_CompressLevel)
+ CALL ncio_write_vector (filename, 'settyp', trim(psetname), pixelset, pixelset%settyp, DEF_Srfdata_CompressLevel)
+
+ IF (pixelset%has_shared) THEN
+ CALL ncio_write_vector (filename, 'pctshared', trim(psetname), pixelset, pixelset%pctshared, DEF_Srfdata_CompressLevel)
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ IF (p_is_root) write(*,*) 'SAVE Pixel Sets ' // trim(psetname) // ' done.'
+
+ END SUBROUTINE pixelset_save_to_file
+
+
+ !---------------------------
+ SUBROUTINE pixelset_load_from_file (dir_landdata, psetname, pixelset, numset, lc_year, subset_eindex)
+
+ USE MOD_SPMD_Task
+ USE MOD_Block
+ USE MOD_NetCDFSerial
+ USE MOD_NetCDFVector
+ USE MOD_Mesh
+ USE MOD_Pixelset
+ IMPLICIT NONE
+
+ integer , intent(in) :: lc_year
+ character(len=*), intent(in) :: dir_landdata
+ character(len=*), intent(in) :: psetname
+ type(pixelset_type), intent(inout) :: pixelset
+ integer, intent(out) :: numset
+ integer*8, optional, intent(in) :: subset_eindex(:)
+
+ ! Local variables
+ character(len=256) :: filename, fileblock, blockname, cyear
+ integer :: iset, nset, nset_file, ndsp, iblkme, iblk, jblk, ie, je, nave, nres, left, iproc, ipos
+ integer :: nsend, nrecv
+ integer*8, allocatable :: rbuff(:), sbuff(:)
+ integer*8, allocatable :: subset_sorted(:)
+ integer, allocatable :: owner_rank(:)
+ logical, allocatable :: msk(:)
+ logical, allocatable :: keep_set(:)
+ logical :: fexists, fexists_any
+ logical :: use_subset
+
+ write(cyear,'(i4.4)') lc_year
+#ifdef USEMPI
+ CALL mpi_barrier (p_comm_glb, p_err)
+#endif
+
+ use_subset = present(subset_eindex)
+ IF (use_subset) CALL prepare_subset_eindex(subset_eindex, subset_sorted)
+
+ IF (p_is_root) THEN
+ write(*,*) 'Loading Pixel Sets ' // trim(psetname) // ' ...'
+ ENDIF
+
+ filename = trim(dir_landdata) // '/' // trim(psetname) // '/' // trim(cyear) // '/' // trim(psetname) // '.nc'
+
+ CALL pixelset%forc_free_mem()
+
+ IF (p_is_active) THEN
+
+ pixelset%nset = 0
+
+ fexists_any = .false.
+
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+#if (defined VectorInOneFileS || defined VectorInOneFileP)
+ CALL get_blockname (iblk, jblk, blockname)
+ CALL ncio_inquire_length_grp (filename, 'eindex', &
+ trim(psetname)//'_'//trim(blockname), nset)
+ IF (use_subset .and. nset > 0) THEN
+ CALL ncio_read_serial_grp_int64_1d (filename, 'eindex', &
+ trim(psetname)//'_'//trim(blockname), rbuff)
+ nset = count_subset_eindex(rbuff, subset_sorted)
+ deallocate(rbuff)
+ ENDIF
+ pixelset%nset = pixelset%nset + nset
+#else
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+
+ inquire (file=trim(fileblock), exist=fexists)
+ IF (fexists) THEN
+ IF (use_subset) THEN
+ CALL ncio_read_serial (fileblock, 'eindex', rbuff)
+ nset = count_subset_eindex(rbuff, subset_sorted)
+ deallocate(rbuff)
+ ELSE
+ CALL ncio_inquire_length (fileblock, 'eindex', nset)
+ ENDIF
+ pixelset%nset = pixelset%nset + nset
+ ENDIF
+
+ fexists_any = fexists_any .or. fexists
+#endif
+ ENDDO
+
+#if (defined VectorInOneFileS || defined VectorInOneFileP)
+ inquire(file=trim(filename), exist=fexists_any)
+#endif
+
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, fexists_any, 1, MPI_LOGICAL, MPI_LOR, p_comm_active, p_err)
+#endif
+ IF (.not. fexists_any) THEN
+ write(*,*) 'Warning : restart file ' //trim(filename)// ' not found.'
+ CALL CoLM_stop ()
+ ENDIF
+
+ IF (pixelset%nset > 0) THEN
+
+ allocate (pixelset%eindex (pixelset%nset))
+ allocate (pixelset%srcpos (pixelset%nset))
+
+ ndsp = 0
+ DO iblkme = 1, gblock%nblkme
+ iblk = gblock%xblkme(iblkme)
+ jblk = gblock%yblkme(iblkme)
+
+#if (defined VectorInOneFileS || defined VectorInOneFileP)
+ CALL get_blockname (iblk, jblk, blockname)
+ CALL ncio_inquire_length_grp (filename, 'eindex', &
+ trim(psetname)//'_'//trim(blockname), nset)
+
+ IF (nset > 0) THEN
+
+ CALL ncio_read_serial_grp_int64_1d (filename, 'eindex', &
+ trim(psetname)//'_'//trim(blockname), rbuff)
+
+ nset_file = size(rbuff)
+ IF (use_subset) THEN
+ allocate(keep_set(nset_file))
+ DO iset = 1, nset_file
+ keep_set(iset) = eindex_in_subset(rbuff(iset), subset_sorted)
+ ENDDO
+ nset = count(keep_set)
+ ELSE
+ nset = nset_file
+ ENDIF
+
+ IF (nset > 0) THEN
+ IF (use_subset) THEN
+ pixelset%eindex(ndsp+1:ndsp+nset) = pack(rbuff, keep_set)
+ pixelset%srcpos(ndsp+1:ndsp+nset) = &
+ pack((/ (ipos, ipos = 1, nset_file) /), keep_set)
+ ELSE
+ pixelset%eindex(ndsp+1:ndsp+nset) = rbuff
+ pixelset%srcpos(ndsp+1:ndsp+nset) = (/ (ipos, ipos = 1, nset) /)
+ ENDIF
+
+ ndsp = ndsp + nset
+ ENDIF
+
+ IF (allocated(keep_set)) deallocate(keep_set)
+ deallocate(rbuff)
+ ENDIF
+#else
+ CALL get_filename_block (filename, iblk, jblk, fileblock)
+ inquire (file=trim(fileblock), exist=fexists)
+ IF (fexists) THEN
+
+ CALL ncio_read_serial (fileblock, 'eindex', rbuff)
+
+ nset_file = size(rbuff)
+ IF (use_subset) THEN
+ allocate(keep_set(nset_file))
+ DO iset = 1, nset_file
+ keep_set(iset) = eindex_in_subset(rbuff(iset), subset_sorted)
+ ENDDO
+ nset = count(keep_set)
+ ELSE
+ nset = nset_file
+ ENDIF
+
+ IF (nset > 0) THEN
+ IF (use_subset) THEN
+ pixelset%eindex(ndsp+1:ndsp+nset) = pack(rbuff, keep_set)
+ pixelset%srcpos(ndsp+1:ndsp+nset) = &
+ pack((/ (ipos, ipos = 1, nset_file) /), keep_set)
+ ELSE
+ pixelset%eindex(ndsp+1:ndsp+nset) = rbuff
+ pixelset%srcpos(ndsp+1:ndsp+nset) = (/ (ipos, ipos = 1, nset) /)
+ ENDIF
+
+ ndsp = ndsp + nset
+ ENDIF
+
+ IF (allocated(keep_set)) deallocate(keep_set)
+ deallocate(rbuff)
+ ENDIF
+#endif
+
+ ENDDO
+ ENDIF
+ ENDIF
+
+
+#if defined(USEMPI) && !defined(MPAS_EMBEDDED_COLM)
+ IF (p_is_active) THEN
+ IF (pixelset%nset > 0) THEN
+ allocate (owner_rank (pixelset%nset))
+ allocate (msk (pixelset%nset))
+
+ ie = 1
+ je = 1
+ iblk = mesh(ie)%xblk
+ jblk = mesh(ie)%yblk
+ DO iset = 1, pixelset%nset
+ DO WHILE (pixelset%eindex(iset) /= mesh(ie)%indx)
+ ie = ie + 1
+ je = je + 1
+ IF ((mesh(ie)%xblk /= iblk) .or. (mesh(ie)%yblk /= jblk)) THEN
+ je = 1
+ iblk = mesh(ie)%xblk
+ jblk = mesh(ie)%yblk
+ ENDIF
+ ENDDO
+
+ nave = nelm_blk(iblk,jblk) / (p_np_group-1)
+ nres = mod(nelm_blk(iblk,jblk), p_np_group-1)
+ left = (nave+1) * nres
+ IF (je <= left) THEN
+ owner_rank(iset) = (je-1) / (nave+1) + 1
+ ELSE
+ owner_rank(iset) = (je-left-1) / nave + 1 + nres
+ ENDIF
+ ENDDO
+
+ DO iproc = 1, p_np_group-1
+ msk = (owner_rank == iproc)
+ nsend = count(msk)
+ CALL mpi_send (nsend, 1, MPI_INTEGER, iproc, mpi_tag_size, p_comm_group, p_err)
+
+ IF (nsend > 0) THEN
+ allocate (sbuff(nsend))
+ sbuff = pack(pixelset%eindex, msk)
+ CALL mpi_send (sbuff, nsend, MPI_INTEGER8, iproc, mpi_tag_data, p_comm_group, p_err)
+ deallocate (sbuff)
+ ENDIF
+ ENDDO
+ ELSE
+ DO iproc = 1, p_np_group-1
+ nsend = 0
+ CALL mpi_send (nsend, 1, MPI_INTEGER, iproc, mpi_tag_size, p_comm_group, p_err)
+ ENDDO
+ ENDIF
+
+ ENDIF
+
+ IF (p_is_compute) THEN
+
+ CALL mpi_recv (nrecv, 1, MPI_INTEGER, p_root, mpi_tag_size, p_comm_group, p_stat, p_err)
+
+ pixelset%nset = nrecv
+ IF (nrecv > 0) THEN
+ allocate (pixelset%eindex (nrecv))
+ CALL mpi_recv (pixelset%eindex, nrecv, MPI_INTEGER8, &
+ p_root, mpi_tag_data, p_comm_group, p_stat, p_err)
+ ENDIF
+ ENDIF
+#endif
+
+
+ CALL pixelset%set_vecgs
+
+ CALL ncio_read_vector (filename, 'ipxstt', pixelset, pixelset%ipxstt)
+ CALL ncio_read_vector (filename, 'ipxend', pixelset, pixelset%ipxend)
+ CALL ncio_read_vector (filename, 'settyp', pixelset, pixelset%settyp)
+
+ IF (p_is_compute) THEN
+ IF (pixelset%nset > 0) THEN
+
+ allocate (pixelset%ielm (pixelset%nset))
+ ie = 1
+ DO iset = 1, pixelset%nset
+ DO WHILE (pixelset%eindex(iset) /= mesh(ie)%indx)
+ ie = ie + 1
+ ENDDO
+ pixelset%ielm(iset) = ie
+ ENDDO
+
+ ELSE
+ write(*,*) 'Warning: 0 ',trim(psetname), ' on rank :', p_iam_glb
+ ENDIF
+ ENDIF
+
+ numset = pixelset%nset
+
+ pixelset%has_shared = .false.
+ IF (p_is_compute) THEN
+ DO iset = 1, pixelset%nset-1
+ IF ((pixelset%ielm(iset) == pixelset%ielm(iset+1)) &
+ .and. (pixelset%ipxstt(iset) == pixelset%ipxstt(iset+1))) THEN
+ pixelset%has_shared = .true.
+ exit
+ ENDIF
+ ENDDO
+ ENDIF
+
+#ifdef USEMPI
+ CALL mpi_allreduce (MPI_IN_PLACE, pixelset%has_shared, 1, MPI_LOGICAL, &
+ MPI_LOR, p_comm_glb, p_err)
+#endif
+
+ IF (pixelset%has_shared) THEN
+ CALL ncio_read_vector (filename, 'pctshared', pixelset, pixelset%pctshared)
+ ENDIF
+
+#ifdef CoLMDEBUG
+ IF (p_is_active) write(*,*) numset, trim(psetname), ' on group', p_iam_active
+#endif
+
+ IF (allocated(subset_sorted)) deallocate(subset_sorted)
+
+ END SUBROUTINE pixelset_load_from_file
+
+END MODULE MOD_SrfdataRestart
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_TimeManager.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_TimeManager.F90
new file mode 100644
index 0000000000..0b1b63cf2d
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_TimeManager.F90
@@ -0,0 +1,711 @@
+#include
+
+MODULE MOD_TimeManager
+
+! --------------------------------------------------------
+!
+! !DESCRIPTION:
+! Time manager module: to provide some basic operations for time stamp
+!
+! Created by Hua Yuan, 04/2014
+!
+! !REVISIONS:
+! 06/28/2017, Hua Yuan: added issame() and monthday2julian()
+! TODO...
+! --------------------------------------------------------
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer, dimension(0:12), parameter :: &
+ daysofmonth_leap = (/0,31,29,31,30,31,30,31,31,30,31,30,31/) ,&
+ daysofmonth_noleap = (/0,31,28,31,30,31,30,31,31,30,31,30,31/) ,&
+ accdaysofmonth_leap = (/0,31,60,91,121,152,182,213,244,274,305,335,366/) ,&
+ accdaysofmonth_noleap = (/0,31,59,90,120,151,181,212,243,273,304,334,365/)
+
+ type :: timestamp
+ integer :: year, day, sec
+ END type timestamp
+
+ INTERFACE ASSIGNMENT (=)
+ MODULE procedure assignidate
+ MODULE procedure assigntstamp
+ END INTERFACE
+
+ INTERFACE OPERATOR (+)
+ MODULE procedure addsec
+ END INTERFACE
+
+ INTERFACE OPERATOR (-)
+ MODULE procedure subtstamp
+ END INTERFACE
+
+ INTERFACE OPERATOR (<=)
+ MODULE procedure lessequal
+ END INTERFACE
+
+ INTERFACE OPERATOR (<)
+ MODULE procedure lessthan
+ END INTERFACE
+
+ INTERFACE OPERATOR (==)
+ MODULE procedure isnull
+ MODULE procedure besame
+ END INTERFACE
+
+ INTERFACE calendarday
+ MODULE procedure calendarday_date
+ MODULE procedure calendarday_stamp
+ END INTERFACE
+
+ logical, SAVE :: isgreenwich
+ real(r8),SAVE :: LocalLongitude = 0.
+ PUBLIC get_calday
+
+CONTAINS
+
+ SUBROUTINE initimetype(greenwich)
+
+ IMPLICIT NONE
+ logical, intent(in) :: greenwich
+
+ isgreenwich = greenwich
+
+#ifndef SinglePoint
+ IF (.not. isgreenwich) THEN
+ write(*,*) 'Warning: Please USE Greenwich time for non-SinglePoint case.'
+ isgreenwich = .true.
+ ENDIF
+#endif
+
+ END SUBROUTINE initimetype
+
+ SUBROUTINE assignidate(tstamp, idate)
+
+ IMPLICIT NONE
+ type(timestamp), intent(inout) :: tstamp
+ integer, intent(in) :: idate(3)
+
+ tstamp%year = idate(1)
+ tstamp%day = idate(2)
+ tstamp%sec = idate(3)
+
+ END SUBROUTINE assignidate
+
+ SUBROUTINE assigntstamp(tstamp1, tstamp2)
+
+ IMPLICIT NONE
+ type(timestamp), intent(out) :: tstamp1
+ type(timestamp), intent(in) :: tstamp2
+
+ tstamp1%year = tstamp2%year
+ tstamp1%day = tstamp2%day
+ tstamp1%sec = tstamp2%sec
+
+ END SUBROUTINE assigntstamp
+
+ FUNCTION addsec(tstamp, sec)
+
+ IMPLICIT NONE
+ type(timestamp), intent(in) :: tstamp
+ integer, intent(in) :: sec
+ type(timestamp) :: addsec
+ integer :: maxday
+
+ addsec = tstamp
+ addsec%sec = addsec%sec + sec
+ DO WHILE (addsec%sec > 86400)
+ addsec%sec = addsec%sec - 86400
+ IF( isleapyear(addsec%year) ) THEN
+ maxday = 366
+ ELSE
+ maxday = 365
+ ENDIF
+ addsec%day = addsec%day + 1
+ IF(addsec%day > maxday) THEN
+ addsec%year = addsec%year + 1
+ addsec%day = 1
+ ENDIF
+ ENDDO
+ DO WHILE (addsec%sec <= 0)
+ addsec%sec = addsec%sec + 86400
+ IF( isleapyear(addsec%year-1) )THEN
+ maxday = 366
+ ELSE
+ maxday = 365
+ ENDIF
+ addsec%day = addsec%day - 1
+ IF(addsec%day <= 0) THEN
+ addsec%year = addsec%year - 1
+ addsec%day = maxday
+ ENDIF
+ ENDDO
+ RETURN
+
+ END FUNCTION addsec
+
+ FUNCTION subtstamp(tstamp1, tstamp2)
+
+ IMPLICIT NONE
+ type(timestamp), intent(in) :: tstamp1
+ type(timestamp), intent(in) :: tstamp2
+ integer :: subtstamp
+
+ subtstamp = tstamp1%sec - tstamp2%sec
+ IF (subtstamp < 0) THEN
+ subtstamp = subtstamp + 86400
+ ENDIF
+ RETURN
+
+ END FUNCTION subtstamp
+
+ logical FUNCTION lessequal(tstamp1, tstamp2)
+
+ IMPLICIT NONE
+ type(timestamp), intent(in) :: tstamp1
+ type(timestamp), intent(in) :: tstamp2
+
+ integer(kind=4) :: idate1(3), idate2(3)
+ integer(kind=4) :: ts1, ts2
+
+ idate1 = (/tstamp1%year, tstamp1%day, tstamp1%sec/)
+ idate2 = (/tstamp2%year, tstamp2%day, tstamp2%sec/)
+
+ CALL adj2end(idate1)
+ CALL adj2end(idate2)
+
+ ts1 = idate1(1)*1000 + idate1(2)
+ ts2 = idate2(1)*1000 + idate2(2)
+
+ lessequal = .false.
+
+ IF (ts1 < ts2) lessequal = .true.
+
+ IF (ts1==ts2 .and. idate1(3)<=idate2(3)) THEN
+ lessequal = .true.
+ ENDIF
+
+ RETURN
+
+ END FUNCTION lessequal
+
+ logical FUNCTION lessthan(tstamp1, tstamp2)
+
+ IMPLICIT NONE
+ type(timestamp), intent(in) :: tstamp1
+ type(timestamp), intent(in) :: tstamp2
+
+ integer(kind=4) :: idate1(3), idate2(3)
+ integer(kind=4) :: ts1, ts2
+
+ idate1 = (/tstamp1%year, tstamp1%day, tstamp1%sec/)
+ idate2 = (/tstamp2%year, tstamp2%day, tstamp2%sec/)
+
+ CALL adj2end(idate1)
+ CALL adj2end(idate2)
+
+ ts1 = idate1(1)*1000 + idate1(2)
+ ts2 = idate2(1)*1000 + idate2(2)
+
+ lessthan = .false.
+
+ IF (ts1 < ts2) lessthan = .true.
+
+ IF (ts1==ts2 .and. idate1(3) 86400) THEN
+
+ idate(3) = idate(3) - 86400
+ idate(2) = idate(2) + 1
+
+ IF ( isleapyear(idate(1)) ) THEN
+ maxday = 366
+ ELSE
+ maxday = 365
+ ENDIF
+
+ IF(idate(2) > maxday) THEN
+ idate(1) = idate(1) + 1
+ idate(2) = 1
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE localtime2gmt
+
+ SUBROUTINE ticktime(deltim, idate)
+
+ IMPLICIT NONE
+
+ real(r8),intent(in) :: deltim
+ integer, intent(inout) :: idate(3)
+ integer maxday
+
+ idate(3) = idate(3) + nint(deltim)
+ IF (idate(3) > 86400) THEN
+
+ idate(3) = idate(3) - 86400
+ idate(2) = idate(2) + 1
+
+ IF ( isleapyear(idate(1)) ) THEN
+ maxday = 366
+ ELSE
+ maxday = 365
+ ENDIF
+
+ IF(idate(2) > maxday) THEN
+ idate(1) = idate(1) + 1
+ idate(2) = 1
+ ENDIF
+ ENDIF
+
+ END SUBROUTINE ticktime
+
+ real(r8) FUNCTION calendarday_date(date)
+
+ IMPLICIT NONE
+ integer, intent(in) :: date(3)
+
+ integer idate(3)
+
+ idate(:) = date(:)
+
+ IF ( .not. isgreenwich ) THEN
+ CALL localtime2gmt(idate)
+ ENDIF
+
+ calendarday_date = float(idate(2)) + float(idate(3))/86400.
+ RETURN
+
+ END FUNCTION calendarday_date
+
+ real(r8) FUNCTION calendarday_stamp(stamp)
+
+ IMPLICIT NONE
+ type(timestamp), intent(in) :: stamp
+
+ integer idate(3)
+
+ idate(1) = stamp%year
+ idate(2) = stamp%day
+ idate(3) = stamp%sec
+
+ IF ( .not. isgreenwich ) THEN
+ CALL localtime2gmt(idate)
+ ENDIF
+
+ calendarday_stamp = float(idate(2)) + float(idate(3))/86400.
+ RETURN
+
+ END FUNCTION calendarday_stamp
+
+ integer FUNCTION get_calday(mmdd,isleap)
+
+ IMPLICIT NONE
+ integer, intent(in) :: mmdd
+ logical, intent(in) :: isleap
+
+ integer imonth, iday
+
+ imonth = mmdd / 100
+ iday = mod(mmdd,100)
+ IF(isleap)THEN
+ get_calday = sum(daysofmonth_leap(0:imonth-1)) + iday
+ ELSE
+ get_calday = sum(daysofmonth_noleap(0:imonth-1)) + iday
+ ENDIF
+ RETURN
+ END FUNCTION get_calday
+
+ integer FUNCTION minutes_since_1900 (year, julianday, second)
+
+ USE MOD_UserDefFun
+ IMPLICIT NONE
+ integer, intent(in) :: year, julianday, second
+
+ integer :: refyear(10) = (/1, 1900, 1950, 1980, 1990, 2000, 2005, 2010, 2015, 2020/)
+ integer :: refval (10) = (/-998776800,0,26297280,42075360,47335680,52594560,55225440,&
+ 57854880,60484320,63113760/)
+ integer :: iref, iyear
+
+ iref = findloc_ud(refyear <= year, back=.true.)
+ minutes_since_1900 = refval(iref)
+ DO iyear = refyear(iref), year-1
+ IF (isleapyear(iyear)) THEN
+ minutes_since_1900 = minutes_since_1900 + 527040
+ ELSE
+ minutes_since_1900 = minutes_since_1900 + 525600
+ ENDIF
+ ENDDO
+
+ minutes_since_1900 = minutes_since_1900 + (julianday-1) * 1440
+ minutes_since_1900 = minutes_since_1900 + second/60
+
+ END FUNCTION minutes_since_1900
+
+ ! -----------------------------------------------------------------------
+ SUBROUTINE gmt2local(idate, long, ldate)
+
+ ! !DESCRIPTION:
+ ! A SUBROUTINE to calculate local time
+ ! !PURPOSE
+ ! Convert GMT time to local time in global run
+ ! -----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ integer , intent(in ) :: idate(3)
+ real(r8), intent(in ) :: long
+ real(r8), intent(out) :: ldate(3)
+
+ integer :: maxday
+ real(r8) :: tdiff
+
+ tdiff = long/15.*3600
+
+ ldate(3) = idate(3) + tdiff
+ ldate(1) = idate(1)
+
+ IF (ldate(3) < 0) THEN
+
+ ldate(3) = 86400 + ldate(3)
+ ldate(2) = idate(2) - 1
+
+ IF (ldate(2) < 1) THEN
+ ldate(1) = idate(1) - 1
+ IF ( isleapyear(int(ldate(1))) ) THEN
+ ldate(2) = 366
+ ELSE
+ ldate(2) = 365
+ ENDIF
+ ENDIF
+
+ ELSEIF (ldate(3) > 86400) THEN
+
+ ldate(3) = ldate(3) - 86400
+ ldate(2) = idate(2) + 1
+
+ IF ( isleapyear(int(ldate(1))) ) THEN
+ maxday = 366
+ ELSE
+ maxday = 365
+ ENDIF
+
+ IF(ldate(2) > maxday) THEN
+ ldate(1) = idate(1) + 1
+ ldate(2) = 1
+ ENDIF
+ ELSE
+ ldate(2) = idate(2)
+ ldate(1) = idate(1)
+ ENDIF
+
+ END SUBROUTINE gmt2local
+
+ ! -----------------------------------------------------------------------
+ SUBROUTINE timeweek(year, month, day, iweek)
+
+ ! !DESCRIPTION:
+ ! A subroutine to calculate day of week
+ ! !PURPOSE
+ ! Calculate day of week to determine IF the day is week holiday
+ ! -----------------------------------------------------------------------
+
+ IMPLICIT NONE
+
+ integer, intent(in ) :: year, month
+ integer, intent(out) :: iweek, day
+
+ integer :: myear, mmonth
+ integer :: yy, mm, dd, y12, y34
+ integer :: A, B, C, D, i
+
+ integer :: monthday(0:12)
+
+ IF ( isleapyear(year) ) THEN
+ monthday(:) = daysofmonth_leap(:)
+ ELSE
+ monthday(:) = daysofmonth_noleap(:)
+ ENDIF
+
+ IF (month==1 .or. month==2) THEN
+ mmonth = month + 12
+ myear = year - 1
+ ELSE
+ mmonth = month
+ myear = year
+ ENDIF
+
+ y12 = myear/100
+ y34 = myear - y12*100
+
+ A = int(y34/4.)
+ B = int(y12/4.)
+ C = y12*2
+ D = int(26*(mmonth+1)/10.)
+
+ iweek = abs(mod((y34+A+B-C+D+day-1), 7))
+
+ DO i=1, month-1
+ day = day + monthday(i)
+ ENDDO
+
+ IF (iweek == 0) THEN
+ iweek = 7
+ ENDIF
+
+ END SUBROUTINE timeweek
+
+END MODULE MOD_TimeManager
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_UserDefFun.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_UserDefFun.F90
new file mode 100644
index 0000000000..cb44a3e2b2
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_UserDefFun.F90
@@ -0,0 +1,70 @@
+MODULE MOD_UserDefFun
+
+!-----------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! This MODULE contains user defined functions to replace non-standard functions.
+!
+! Created by Shupeng Zhang, April 2024
+!-----------------------------------------------------------------------------------------
+
+ ! ---- PUBLIC subroutines ----
+
+ INTERFACE isnan_ud
+ MODULE procedure isnan_ud_r8
+ END INTERFACE isnan_ud
+
+CONTAINS
+
+ ! ----------
+ elemental logical FUNCTION isnan_ud_r8 (a)
+
+ USE MOD_Precision, only: r8
+
+ IMPLICIT NONE
+ real(r8), intent(in) :: a
+
+ isnan_ud_r8 = (a /= a)
+
+ END FUNCTION isnan_ud_r8
+
+ ! ----------
+ integer FUNCTION findloc_ud (array, back)
+
+ IMPLICIT NONE
+ logical, intent(in) :: array(:)
+ logical, intent(in), optional :: back
+
+ ! Local Variables
+ logical :: bb
+ integer :: n, i, i0, i1, ii
+
+ n = size(array)
+ IF (n <= 0) THEN
+ findloc_ud = 0
+ ELSE
+
+ bb = .false.
+ IF (present(back)) THEN
+ bb = back
+ ENDIF
+
+ IF (.not. bb) THEN
+ i0 = 1; i1 = n; ii = 1
+ ELSE
+ i0 = n; i1 = 1; ii = -1
+ ENDIF
+
+ findloc_ud = 0
+ DO i = i0, i1, ii
+ IF (array(i)) THEN
+ findloc_ud = i
+ EXIT
+ ENDIF
+ ENDDO
+
+ ENDIF
+
+ END FUNCTION findloc_ud
+
+END MODULE MOD_UserDefFun
diff --git a/src/core_atmosphere/physics/physics_colm2024/share/MOD_Utils.F90 b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Utils.F90
new file mode 100644
index 0000000000..4f22b5b0b5
--- /dev/null
+++ b/src/core_atmosphere/physics/physics_colm2024/share/MOD_Utils.F90
@@ -0,0 +1,2615 @@
+MODULE MOD_Utils
+
+!-----------------------------------------------------------------------------------------
+! !DESCRIPTION:
+!
+! This MODULE CONTAINS utilities.
+!
+! !REVISIONS:
+! Subroutines lmder, enorm, tridia and polint are moved from other files.
+!
+! Created by Shupeng Zhang, May 2023
+!-----------------------------------------------------------------------------------------
+
+ ! ---- PUBLIC subroutines ----
+
+ PUBLIC :: normalize_longitude
+
+ INTERFACE expand_list
+ MODULE procedure expand_list_int32
+ MODULE procedure expand_list_int64
+ MODULE procedure expand_list_real8
+ END INTERFACE expand_list
+
+ PUBLIC :: append_to_list
+
+ INTERFACE insert_into_sorted_list1
+ MODULE procedure insert_into_sorted_list1_int32
+ MODULE procedure insert_into_sorted_list1_int64
+ END INTERFACE insert_into_sorted_list1
+
+ PUBLIC :: insert_into_sorted_list2
+
+ INTERFACE find_in_sorted_list1
+ MODULE procedure find_in_sorted_list1_int32
+ MODULE procedure find_in_sorted_list1_int64
+ END INTERFACE find_in_sorted_list1
+
+ PUBLIC :: find_in_sorted_list2
+
+ PUBLIC :: find_nearest_south
+ PUBLIC :: find_nearest_north
+ PUBLIC :: find_nearest_west
+ PUBLIC :: find_nearest_east
+
+ PUBLIC :: lon_between_floor
+ PUBLIC :: lon_between_ceil
+
+ INTERFACE quicksort
+ MODULE procedure quicksort_int32
+ MODULE procedure quicksort_int64
+ MODULE procedure quicksort_real8
+ END INTERFACE quicksort
+
+ PUBLIC :: quickselect
+ PUBLIC :: median
+
+ PUBLIC :: areaquad
+ PUBLIC :: arclen
+
+ INTERFACE unpack_inplace
+ MODULE procedure unpack_inplace_int32
+ MODULE procedure unpack_inplace_real8
+ MODULE procedure unpack_inplace_lastdim_real8
+ END INTERFACE unpack_inplace
+
+ PUBLIC :: num_max_frequency
+
+ PUBLIC :: lmder
+ PUBLIC :: lmpar
+ PUBLIC :: qrfac
+ PUBLIC :: qrsolv
+
+ PUBLIC :: enorm
+ PUBLIC :: tridia
+ PUBLIC :: polint
+
+CONTAINS
+
+ !---------------------------------
+ SUBROUTINE normalize_longitude (lon)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(inout) :: lon
+
+ DO WHILE (lon >= 180.0)
+ lon = lon - 360.0
+ ENDDO
+
+ DO WHILE (lon < -180.0)
+ lon = lon + 360.0
+ ENDDO
+
+ END SUBROUTINE normalize_longitude
+
+ !--------------------------------------------------
+ SUBROUTINE expand_list_int32 (list, percent)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer, allocatable, intent(inout) :: list (:)
+ real(r8), intent(in) :: percent
+
+ ! Local variables
+ integer :: n0, n1
+ integer, allocatable :: temp (:)
+
+ n0 = size(list)
+
+ allocate (temp(n0))
+ temp = list
+
+ n1 = ceiling(n0 * (1+percent))
+
+ deallocate(list)
+ allocate (list(n1))
+ list(1:n0) = temp
+
+ deallocate (temp)
+
+ END SUBROUTINE expand_list_int32
+
+ !--------------------------------------------------
+ SUBROUTINE expand_list_int64 (list, percent)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer*8, allocatable, intent(inout) :: list (:)
+ real(r8), intent(in) :: percent
+
+ ! Local variables
+ integer :: n0, n1
+ integer*8, allocatable :: temp (:)
+
+ n0 = size(list)
+
+ allocate (temp(n0))
+ temp = list
+
+ n1 = ceiling(n0 * (1+percent))
+
+ deallocate(list)
+ allocate (list(n1))
+ list(1:n0) = temp
+
+ deallocate (temp)
+
+ END SUBROUTINE expand_list_int64
+
+ !--------------------------------------------------
+ SUBROUTINE expand_list_real8 (list, percent)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), allocatable, intent(inout) :: list (:)
+ real(r8), intent(in) :: percent
+
+ ! Local variables
+ integer :: n0, n1
+ real(r8), allocatable :: temp (:)
+
+ n0 = size(list)
+
+ allocate (temp(n0))
+ temp = list
+
+ n1 = ceiling(n0 * (1+percent))
+
+ deallocate(list)
+ allocate (list(n1))
+ list(1:n0) = temp
+
+ deallocate (temp)
+
+ END SUBROUTINE expand_list_real8
+
+ !--------------------------------------------------
+ SUBROUTINE append_to_list (list1, list2)
+
+ IMPLICIT NONE
+
+ integer, allocatable, intent(inout) :: list1 (:)
+ integer, intent(in) :: list2 (:)
+
+ ! Local variables
+ integer :: n1, n2
+ integer, allocatable :: temp (:)
+
+ IF (.not. allocated(list1)) THEN
+ n1 = 0
+ ELSE
+ n1 = size(list1)
+ ENDIF
+
+ n2 = size(list2)
+
+ IF (n1 > 0) THEN
+ allocate (temp(n1))
+ temp = list1
+
+ deallocate(list1)
+ allocate (list1(n1+n2))
+ list1(1:n1) = temp
+
+ deallocate (temp)
+ ELSE
+ IF (n2 > 0) allocate (list1(n2))
+ ENDIF
+
+ IF (n1 + n2 > 0) THEN
+ list1(n1+1:n1+n2) = list2
+ ENDIF
+
+ END SUBROUTINE append_to_list
+
+ !--------------------------------------------------
+ SUBROUTINE insert_into_sorted_list1_int32 (x, n, list, iloc, is_new_out)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: x
+ integer, intent(inout) :: n
+ integer, intent(inout) :: list(:)
+ integer, intent(out) :: iloc
+ logical, intent(out), optional :: is_new_out
+
+ ! Local variables
+ logical :: is_new
+ integer :: ileft, iright
+
+ IF (n == 0) THEN
+ iloc = 1
+ is_new = .true.
+ ELSEIF (x <= list(1)) THEN
+ iloc = 1
+ is_new = (x /= list(1))
+ ELSEIF (x > list(n)) THEN
+ iloc = n + 1
+ is_new = .true.
+ ELSEIF (x == list(n)) THEN
+ iloc = n
+ is_new = .false.
+ ELSE
+ ileft = 1
+ iright = n
+
+ DO WHILE (.true.)
+ IF (iright - ileft > 1) THEN
+ iloc = (ileft + iright) / 2
+ IF (x > list(iloc)) THEN
+ ileft = iloc
+ ELSEIF (x < list(iloc)) THEN
+ iright = iloc
+ ELSE
+ is_new = .false.
+ EXIT
+ ENDIF
+ ELSE
+ iloc = iright
+ is_new = .true.
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (is_new) THEN
+ IF (iloc <= n) THEN
+ list(iloc+1:n+1) = list(iloc:n)
+ ENDIF
+
+ list(iloc) = x
+ n = n + 1
+ ENDIF
+
+ IF (present(is_new_out)) THEN
+ is_new_out = is_new
+ ENDIF
+
+ END SUBROUTINE insert_into_sorted_list1_int32
+
+ !--------------------------------------------------
+ SUBROUTINE insert_into_sorted_list1_int64 (x, n, list, iloc, is_new_out)
+
+ IMPLICIT NONE
+
+ integer*8, intent(in) :: x
+ integer, intent(inout) :: n
+ integer*8, intent(inout) :: list(:)
+ integer, intent(out) :: iloc
+ logical, intent(out), optional :: is_new_out
+
+ ! Local variables
+ logical :: is_new
+ integer :: ileft, iright
+
+ IF (n == 0) THEN
+ iloc = 1
+ is_new = .true.
+ ELSEIF (x <= list(1)) THEN
+ iloc = 1
+ is_new = (x /= list(1))
+ ELSEIF (x > list(n)) THEN
+ iloc = n + 1
+ is_new = .true.
+ ELSEIF (x == list(n)) THEN
+ iloc = n
+ is_new = .false.
+ ELSE
+ ileft = 1
+ iright = n
+
+ DO WHILE (.true.)
+ IF (iright - ileft > 1) THEN
+ iloc = (ileft + iright) / 2
+ IF (x > list(iloc)) THEN
+ ileft = iloc
+ ELSEIF (x < list(iloc)) THEN
+ iright = iloc
+ ELSE
+ is_new = .false.
+ EXIT
+ ENDIF
+ ELSE
+ iloc = iright
+ is_new = .true.
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (is_new) THEN
+ IF (iloc <= n) THEN
+ list(iloc+1:n+1) = list(iloc:n)
+ ENDIF
+
+ list(iloc) = x
+ n = n + 1
+ ENDIF
+
+ IF (present(is_new_out)) THEN
+ is_new_out = is_new
+ ENDIF
+
+ END SUBROUTINE insert_into_sorted_list1_int64
+
+ !--------------------------------------------------
+ SUBROUTINE insert_into_sorted_list2 (x, y, n, xlist, ylist, iloc, is_new_out)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: x, y
+ integer, intent(inout) :: n
+ integer, intent(inout) :: xlist(:), ylist(:)
+ integer, intent(out) :: iloc
+ logical, intent(out), optional :: is_new_out
+
+ ! Local variables
+ logical :: is_new
+ integer :: ileft, iright
+
+ IF (n == 0) THEN
+ iloc = 1
+ is_new = .true.
+ ELSEIF ((y < ylist(1)) .or. ((y == ylist(1)) .and. (x <= xlist(1)))) THEN
+ iloc = 1
+ is_new = (x /= xlist(1)) .or. (y /= ylist(1))
+ ELSEIF ((y > ylist(n)) .or. ((y == ylist(n)) .and. (x > xlist(n)))) THEN
+ iloc = n + 1
+ is_new = .true.
+ ELSEIF ((x == xlist(n)) .and. (y == ylist(n))) THEN
+ iloc = n
+ is_new = .false.
+ ELSE
+ ileft = 1
+ iright = n
+
+ DO WHILE (.true.)
+ IF (iright - ileft > 1) THEN
+ iloc = (ileft + iright) / 2
+ IF ((y > ylist(iloc)) .or. ((y == ylist(iloc)) .and. (x > xlist(iloc)))) THEN
+ ileft = iloc
+ ELSEIF ((y < ylist(iloc)) .or. ((y == ylist(iloc)) .and. (x < xlist(iloc)))) THEN
+ iright = iloc
+ ELSE
+ is_new = .false.
+ EXIT
+ ENDIF
+ ELSE
+ iloc = iright
+ is_new = .true.
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ IF (is_new) THEN
+ IF (iloc <= n) THEN
+ xlist(iloc+1:n+1) = xlist(iloc:n)
+ ylist(iloc+1:n+1) = ylist(iloc:n)
+ ENDIF
+
+ xlist(iloc) = x
+ ylist(iloc) = y
+ n = n + 1
+ ENDIF
+
+ IF (present(is_new_out)) THEN
+ is_new_out = is_new
+ ENDIF
+
+ END SUBROUTINE insert_into_sorted_list2
+
+ !--------------------------------------------------
+ FUNCTION find_in_sorted_list1_int32 (x, n, list) result(iloc)
+
+ IMPLICIT NONE
+
+ integer :: iloc
+
+ integer, intent(in) :: x
+ integer, intent(in) :: n
+ integer, intent(in) :: list (n)
+
+ ! Local variables
+ integer :: i, ileft, iright
+
+ iloc = 0
+ IF (n > 0) THEN
+ IF ((x >= list(1)) .and. (x <= list(n))) THEN
+ IF (x == list(1)) THEN
+ iloc = 1
+ ELSEIF (x == list(n)) THEN
+ iloc = n
+ ELSE
+ ileft = 1
+ iright = n
+
+ DO WHILE (iright - ileft > 1)
+ i = (ileft + iright) / 2
+ IF (x == list(i)) THEN
+ iloc = i
+ EXIT
+ ELSEIF (x > list(i)) THEN
+ ileft = i
+ ELSEIF (x < list(i)) THEN
+ iright = i
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDIF
+
+ END FUNCTION find_in_sorted_list1_int32
+
+ !--------------------------------------------------
+ FUNCTION find_in_sorted_list1_int64 (x, n, list) result(iloc)
+
+ IMPLICIT NONE
+
+ integer :: iloc
+
+ integer*8, intent(in) :: x
+ integer, intent(in) :: n
+ integer*8, intent(in) :: list (n)
+
+ ! Local variables
+ integer :: i, ileft, iright
+
+ iloc = 0
+ IF (n > 0) THEN
+ IF ((x >= list(1)) .and. (x <= list(n))) THEN
+ IF (x == list(1)) THEN
+ iloc = 1
+ ELSEIF (x == list(n)) THEN
+ iloc = n
+ ELSE
+ ileft = 1
+ iright = n
+
+ DO WHILE (iright - ileft > 1)
+ i = (ileft + iright) / 2
+ IF (x == list(i)) THEN
+ iloc = i
+ EXIT
+ ELSEIF (x > list(i)) THEN
+ ileft = i
+ ELSEIF (x < list(i)) THEN
+ iright = i
+ ENDIF
+ ENDDO
+ ENDIF
+ ENDIF
+ ENDIF
+
+ END FUNCTION find_in_sorted_list1_int64
+
+ !--------------------------------------------------
+ FUNCTION find_in_sorted_list2 (x, y, n, xlist, ylist) result(iloc)
+
+ IMPLICIT NONE
+
+ integer :: iloc
+
+ integer, intent(in) :: x, y
+ integer, intent(in) :: n
+ integer, intent(in) :: xlist(:), ylist(:)
+
+ ! Local variables
+ integer :: i, ileft, iright
+
+ iloc = 0
+ IF (n < 1) RETURN
+
+ IF ((y < ylist(1)) .or. ((y == ylist(1)) .and. (x < xlist(1)))) THEN
+ iloc = 0
+ ELSEIF ((y > ylist(n)) .or. ((y == ylist(n)) .and. (x > xlist(n)))) THEN
+ iloc = 0
+ ELSEIF ((x == xlist(1)) .and. (y == ylist(1))) THEN
+ iloc = 1
+ ELSEIF ((x == xlist(n)) .and. (y == ylist(n))) THEN
+ iloc = n
+ ELSE
+ ileft = 1
+ iright = n
+
+ DO WHILE (.true.)
+ IF (iright - ileft > 1) THEN
+ i = (ileft + iright) / 2
+ IF ((y == ylist(i)) .and. (x == xlist(i))) THEN
+ iloc = i
+ EXIT
+ ELSEIF ((y > ylist(i)) .or. ((y == ylist(i)) .and. (x > xlist(i)))) THEN
+ ileft = i
+ ELSEIF ((y < ylist(i)) .or. ((y == ylist(i)) .and. (x < xlist(i)))) THEN
+ iright = i
+ ENDIF
+ ELSE
+ iloc = 0
+ EXIT
+ ENDIF
+ ENDDO
+ ENDIF
+
+ END FUNCTION find_in_sorted_list2
+
+ !-----------------------------------------------------
+ FUNCTION find_nearest_south (y, n, lat) result(iloc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer :: iloc
+
+ real(r8), intent(in) :: y
+ integer, intent(in) :: n
+ real(r8), intent(in) :: lat (n)
+
+ ! Local variables
+ integer :: i, iright, ileft
+
+ IF (lat(1) < lat(n)) THEN
+ IF (y <= lat(1)) THEN
+ iloc = 1
+ ELSEIF (y >= lat(n)) THEN
+ iloc = n
+ ELSE
+ ileft = 1; iright = n
+
+ DO WHILE (iright - ileft > 1)
+ i = (iright + ileft) / 2
+ IF (y >= lat(i)) THEN
+ ileft = i
+ ELSE
+ iright = i
+ ENDIF
+ ENDDO
+
+ iloc = ileft
+ ENDIF
+ ELSE
+ IF (y >= lat(1)) THEN
+ iloc = 1
+ ELSEIF (y <= lat(n)) THEN
+ iloc = n
+ ELSE
+ ileft = 1; iright = n
+
+ DO WHILE (iright - ileft > 1)
+ i = (iright + ileft) / 2
+ IF (y >= lat(i)) THEN
+ iright = i
+ ELSE
+ ileft = i
+ ENDIF
+ ENDDO
+
+ iloc = iright
+ ENDIF
+ ENDIF
+
+ END FUNCTION find_nearest_south
+
+ !-----------------------------------------------------
+ FUNCTION find_nearest_north (y, n, lat) result(iloc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: y
+ integer, intent(in) :: n
+ real(r8), intent(in) :: lat (n)
+
+ integer :: iloc
+
+ ! Local variables
+ integer :: i, iright, ileft
+
+ IF (lat(1) < lat(n)) THEN
+ IF (y <= lat(1)) THEN
+ iloc = 1
+ ELSEIF (y >= lat(n)) THEN
+ iloc = n
+ ELSE
+ ileft = 1; iright = n
+
+ DO WHILE (iright - ileft > 1)
+ i = (iright + ileft) / 2
+ IF (y > lat(i)) THEN
+ ileft = i
+ ELSE
+ iright = i
+ ENDIF
+ ENDDO
+
+ iloc = iright
+ ENDIF
+ ELSE
+ IF (y >= lat(1)) THEN
+ iloc = 1
+ ELSEIF (y <= lat(n)) THEN
+ iloc = n
+ ELSE
+ ileft = 1; iright = n
+
+ DO WHILE (iright - ileft > 1)
+ i = (iright + ileft) / 2
+ IF (y > lat(i)) THEN
+ iright = i
+ ELSE
+ ileft = i
+ ENDIF
+ ENDDO
+
+ iloc = ileft
+ ENDIF
+ ENDIF
+
+ END FUNCTION find_nearest_north
+
+ !-----------------------------------------
+ logical FUNCTION lon_between_floor (lon, west, east)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: lon, west, east ! [-180, 180)
+
+ IF (west >= east) THEN
+ lon_between_floor = (lon >= west) .or. (lon < east)
+ ELSE
+ lon_between_floor = (lon >= west) .and. (lon < east)
+ ENDIF
+
+ END FUNCTION lon_between_floor
+
+ !-----------------------------------------
+ logical FUNCTION lon_between_ceil (lon, west, east)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: lon, west, east ! [-180, 180)
+
+ IF (west >= east) THEN
+ lon_between_ceil = (lon > west) .or. (lon <= east)
+ ELSE
+ lon_between_ceil = (lon > west) .and. (lon <= east)
+ ENDIF
+
+ END FUNCTION lon_between_ceil
+
+ !-----------------------------------------------------
+ FUNCTION find_nearest_west (x, n, lon) result(iloc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: x
+ integer, intent(in) :: n
+ real(r8), intent(in) :: lon (n)
+
+ integer :: iloc
+
+ ! Local variables
+ integer :: i, iright, ileft
+
+ IF (n == 1) THEN
+ iloc = 1
+ RETURN
+ ENDIF
+
+ IF (lon_between_floor (x, lon(n), lon(1))) THEN
+ iloc = n
+ RETURN
+ ENDIF
+
+ ileft = 1; iright = n
+ DO WHILE (iright - ileft > 1)
+ i = (iright + ileft)/2
+ IF (lon_between_floor(x,lon(i),lon(iright))) THEN
+ ileft = i
+ ELSE
+ iright = i
+ ENDIF
+ ENDDO
+
+ iloc = ileft
+
+ END FUNCTION find_nearest_west
+
+ !-----------------------------------------------------
+ FUNCTION find_nearest_east (x, n, lon) result(iloc)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: x
+ integer, intent(in) :: n
+ real(r8), intent(in) :: lon (n)
+
+ integer :: iloc
+
+ ! Local variables
+ integer :: i, iright, ileft
+
+ IF (n == 1) THEN
+ iloc = 1
+ RETURN
+ ENDIF
+
+ IF (lon_between_ceil (x, lon(n), lon(1))) THEN
+ iloc = 1
+ RETURN
+ ENDIF
+
+ ileft = 1; iright = n
+ DO WHILE (iright - ileft > 1)
+ i = (iright + ileft)/2
+ IF (lon_between_ceil(x,lon(i),lon(iright))) THEN
+ ileft = i
+ ELSE
+ iright = i
+ ENDIF
+ ENDDO
+
+ iloc = iright
+
+ END FUNCTION find_nearest_east
+
+
+ !-----------------------------------------------------
+ recursive SUBROUTINE quicksort_int32 (nA, A, order)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer, intent(in) :: nA
+ integer, intent(inout) :: A (nA)
+ integer, intent(inout) :: order (nA)
+
+ ! Local variables
+ integer :: left, right
+ integer :: pivot
+ integer :: marker
+ integer :: itemp
+
+ IF (nA > 1) THEN
+
+ pivot = A (nA/2)
+ left = 0
+ right = nA + 1
+
+ DO WHILE (left < right)
+ right = right - 1
+ DO WHILE (A(right) > pivot)
+ right = right - 1
+ ENDDO
+
+ left = left + 1
+ DO WHILE (A(left) < pivot)
+ left = left + 1
+ ENDDO
+
+ IF (left < right) THEN
+ itemp = A(left)
+ A(left) = A(right)
+ A(right) = itemp
+
+ itemp = order(left)
+ order(left) = order(right)
+ order(right) = itemp
+ ENDIF
+ ENDDO
+
+ marker = right
+
+ CALL quicksort_int32 (marker, A(1:marker), order(1:marker))
+ CALL quicksort_int32 (nA-marker, A(marker+1:nA), order(marker+1:nA))
+
+ ENDIF
+
+ END SUBROUTINE quicksort_int32
+
+ !-----------------------------------------------------
+ recursive SUBROUTINE quicksort_int64 (nA, A, order)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer, intent(in) :: nA
+ integer*8, intent(inout) :: A (nA)
+ integer, intent(inout) :: order (nA)
+
+ ! Local variables
+ integer*8 :: left, right, pivot, itemp
+ integer :: marker
+
+ IF (nA > 1) THEN
+
+ pivot = A (nA/2)
+ left = 0
+ right = nA + 1
+
+ DO WHILE (left < right)
+ right = right - 1
+ DO WHILE (A(right) > pivot)
+ right = right - 1
+ ENDDO
+
+ left = left + 1
+ DO WHILE (A(left) < pivot)
+ left = left + 1
+ ENDDO
+
+ IF (left < right) THEN
+ itemp = A(left)
+ A(left) = A(right)
+ A(right) = itemp
+
+ itemp = order(left)
+ order(left) = order(right)
+ order(right) = itemp
+ ENDIF
+ ENDDO
+
+ marker = right
+
+ CALL quicksort_int64 (marker, A(1:marker), order(1:marker))
+ CALL quicksort_int64 (nA-marker, A(marker+1:nA), order(marker+1:nA))
+
+ ENDIF
+
+ END SUBROUTINE quicksort_int64
+
+ !-----------------------------------------------------
+ recursive SUBROUTINE quicksort_real8 (nA, A, order)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ integer, intent(in) :: nA
+ real(r8), intent(inout) :: A (nA)
+ integer, intent(inout) :: order (nA)
+
+ ! Local variables
+ real(r8) :: pivot, temp
+ integer :: left, right, marker, itemp
+
+ IF (nA > 1) THEN
+
+ pivot = A (nA/2)
+ left = 0
+ right = nA + 1
+
+ DO WHILE (left < right)
+ right = right - 1
+ DO WHILE (A(right) > pivot)
+ right = right - 1
+ ENDDO
+
+ left = left + 1
+ DO WHILE (A(left) < pivot)
+ left = left + 1
+ ENDDO
+
+ IF (left < right) THEN
+ temp = A(left)
+ A(left) = A(right)
+ A(right) = temp
+
+ itemp = order(left)
+ order(left) = order(right)
+ order(right) = itemp
+ ENDIF
+ ENDDO
+
+ marker = right
+
+ CALL quicksort_real8 (marker, A(1:marker), order(1:marker))
+ CALL quicksort_real8 (nA-marker, A(marker+1:nA), order(marker+1:nA))
+
+ ENDIF
+
+ END SUBROUTINE quicksort_real8
+
+ !-----------------------------------------------------
+ recursive FUNCTION quickselect (nA, A, k) result(selected)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8) :: selected
+
+ integer , intent(in) :: nA
+ real(r8), intent(inout) :: A (nA)
+ integer, intent(in) :: k
+
+ ! Local variables
+ integer :: left, right
+ real(r8) :: pivot
+ integer :: marker
+ real(r8) :: rtemp
+
+ IF (nA > 1) THEN
+
+ pivot = A (nA/2)
+ left = 0
+ right = nA + 1
+
+ DO WHILE (left < right)
+ right = right - 1
+ DO WHILE (A(right) > pivot)
+ right = right - 1
+ ENDDO
+
+ left = left + 1
+ DO WHILE (A(left) < pivot)
+ left = left + 1
+ ENDDO
+
+ IF (left < right) THEN
+ rtemp = A(left)
+ A(left) = A(right)
+ A(right) = rtemp
+ ENDIF
+ ENDDO
+
+ marker = right
+
+ IF (k <= marker) THEN
+ selected = quickselect (marker, A(1:marker), k)
+ ELSE
+ selected = quickselect (nA-marker, A(marker+1:nA), k-marker)
+ ENDIF
+
+ ELSE
+ selected = A(1)
+ ENDIF
+
+ END FUNCTION quickselect
+
+
+ ! ------------------------
+ FUNCTION median(x, n, spval) result(mval)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8) :: mval
+
+ integer, intent(in) :: n
+ real(r8), intent(in) :: x(n)
+ real(r8), intent(in), optional :: spval
+
+ ! Local variables
+ integer :: nc
+ real(r8), allocatable :: xtemp(:)
+ logical, allocatable :: msk (:)
+ real(r8) :: right, left
+
+ IF (present(spval)) THEN
+ allocate (msk (n))
+ msk = (x /= spval)
+ nc = count(msk)
+ IF (nc /= 0) THEN
+
+ allocate (xtemp(nc))
+ xtemp = pack(x, msk)
+
+ deallocate (msk)
+ ELSE
+
+ mval = spval
+
+ deallocate(msk)
+ RETURN
+ ENDIF
+ ELSE
+ nc = n
+ allocate (xtemp(nc))
+ xtemp = x
+ ENDIF
+
+ IF (mod(nc,2) == 0) THEN
+ left = quickselect(nc,xtemp,nc/2)
+ right = quickselect(nc,xtemp,nc/2+1)
+ mval = (left + right) / 2.0_r8
+ ELSE
+ mval = quickselect(nc,xtemp,nc/2+1)
+ ENDIF
+
+ deallocate (xtemp)
+
+ END FUNCTION median
+
+
+ !-----------------------------------------------------
+ FUNCTION areaquad (lats, latn, lonw, lone) result(area)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8) :: area ! in km^2
+ real(r8), parameter :: re = 6.37122e3 ! kilometer
+ real(r8), parameter :: deg2rad = 1.745329251994330e-2_r8
+ real(r8), intent(in) :: lats, latn, lonw, lone
+
+ ! Local variables
+ real(r8) :: dx, dy
+
+ IF (lone < lonw) THEN
+ dx = (lone + 360 - lonw) * deg2rad
+ ELSE
+ dx = (lone - lonw) * deg2rad
+ ENDIF
+
+ dy = sin(latn * deg2rad) - sin(lats * deg2rad)
+
+ area = dx * dy * re * re
+
+ END FUNCTION areaquad
+
+ ! --- spherical distance ---
+ FUNCTION arclen (lat1, lon1, lat2, lon2)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8) :: arclen ! in km
+ real(r8), intent(in) :: lat1, lon1, lat2, lon2
+
+ real(r8), parameter :: re = 6.37122e3 ! kilometer
+ real(r8) :: tmp
+
+ tmp = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2) * cos(lon1-lon2)
+ tmp = min(max(tmp, -1.), 1.)
+ arclen = re * acos(tmp)
+
+ END FUNCTION arclen
+
+ !-----------------------------------------------------
+ SUBROUTINE unpack_inplace_int32 (din, msk, dout)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: din (:)
+ logical, intent(in) :: msk (:)
+ integer, intent(inout) :: dout (:)
+
+ ! Local variables
+ integer :: n, i
+
+ n = 0
+ DO i = 1, size(msk)
+ IF (msk(i)) THEN
+ n = n + 1
+ dout(i) = din(n)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE unpack_inplace_int32
+
+ !-----------------------------------------------------
+ SUBROUTINE unpack_inplace_real8 (din, msk, dout)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: din (:)
+ logical, intent(in) :: msk (:)
+ real(r8), intent(inout) :: dout (:)
+
+ ! Local variables
+ integer :: n, i
+
+ n = 0
+ DO i = 1, size(msk)
+ IF (msk(i)) THEN
+ n = n + 1
+ dout(i) = din(n)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE unpack_inplace_real8
+
+ !-----------------------------------------------------
+ SUBROUTINE unpack_inplace_lastdim_real8 (din, msk, dout)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+
+ real(r8), intent(in) :: din (:,:)
+ logical, intent(in) :: msk (:)
+ real(r8), intent(inout) :: dout (:,:)
+
+ ! Local variables
+ integer :: n, i
+
+ n = 0
+ DO i = 1, size(msk)
+ IF (msk(i)) THEN
+ n = n + 1
+ dout(:,i) = din(:,n)
+ ENDIF
+ ENDDO
+
+ END SUBROUTINE unpack_inplace_lastdim_real8
+
+ !---------------------------------------------------
+ integer FUNCTION num_max_frequency (data_in)
+
+ IMPLICIT NONE
+
+ integer, intent(in) :: data_in(:)
+
+ ! Local Variables
+ integer, allocatable :: data_(:), cnts(:)
+ integer :: ndata, i, n, iloc
+ logical :: is_new
+
+ ndata = size(data_in)
+ allocate (data_(ndata))
+ allocate (cnts (ndata))
+
+ n = 0
+ cnts(:) = 0
+ DO i = 1, ndata
+ CALL insert_into_sorted_list1 (data_in(i), n, data_, iloc, is_new)
+ IF (is_new) THEN
+ IF (iloc < n) cnts(iloc+1:ndata) = cnts(iloc:ndata-1)
+ cnts(iloc) = 1
+ ELSE
+ cnts(iloc) = cnts(iloc) + 1
+ ENDIF
+ ENDDO
+
+ num_max_frequency = data_(maxloc(cnts,dim=1))
+
+ deallocate(data_)
+ deallocate(cnts )
+
+ END FUNCTION num_max_frequency
+
+ !----------------------------------------------------
+ SUBROUTINE lmder ( fcn, m, n, x, fvec, fjac, ldfjac, ftol, xtol, gtol, maxfev, &
+ diag, mode, factor, nprint, info, nfev, njev, ipvt, qtf, xdat, npoint, ydat, &
+ ydatks, nptf, phi, k_s, isiter, L_vgm)
+
+ !*******************************************************************************
+ !
+ !! LMDER minimizes M functions in N variables by the Levenberg-Marquardt method
+ ! implemented for fitting the SW retention & hydraulic conductivity parameters
+ ! in the Campbell/van Genuchten models.
+ !
+ ! Discussion:
+ !
+ ! LMDER minimizes the sum of the squares of M nonlinear functions in
+ ! N variables by a modification of the Levenberg-Marquardt algorithm.
+ ! The user must provide a subroutine which calculates the functions
+ ! and the jacobian.
+ !
+ ! Licensing:
+ !
+ ! This code may freely be copied, modified, and used for any purpose.
+ !
+ ! Modified:
+ !
+ ! 06 April 2010
+ !
+ ! Author:
+ !
+ ! Original FORTRAN77 version by Jorge More, Burton Garbow, Kenneth Hillstrom.
+ ! FORTRAN90 version by John Burkardt.
+ ! Modified by Nan Wei, 2019/01
+ !
+ ! Reference:
+ !
+ ! Jorge More, Burton Garbow, Kenneth Hillstrom,
+ ! User Guide for MINPACK-1,
+ ! Technical Report ANL-80-74,
+ ! Argonne National Laboratory, 1980.
+ !
+ ! Parameters:
+ !
+ ! Input, external FCN, the name of the user-supplied subroutine which
+ ! calculates the functions and the jacobian. FCN should have the form:
+ ! subroutine fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter, L_vgm)
+ ! integer ( kind = 4 ) ldfjac
+ ! integer ( kind = 4 ) n
+ ! real ( kind = 8 ) fjac(ldfjac,n)
+ ! real ( kind = 8 ) fvec(m)
+ ! integer ( kind = 4 ) iflag
+ ! real ( kind = 8 ) x(n)
+ ! xdat, npoint, ydat, ydatks, nptf, phi, k_s and isiter are transfered as the inputs of the fitting functions.
+ ! L_vgm are only used for vanGenuchten_Mualem soil model input.
+ !
+ ! If IFLAG = 0 on input, then FCN is only being called to allow the user
+ ! to print out the current iterate.
+ ! If IFLAG = 1 on input, FCN should calculate the functions at X and
+ ! return this vector in FVEC.
+ ! If IFLAG = 2 on input, FCN should calculate the jacobian at X and
+ ! return this matrix in FJAC.
+ ! To terminate the algorithm, FCN may set IFLAG negative on return.
+ !
+ ! Input, integer ( kind = 4 ) M, is the number of functions.
+ !
+ ! Input, integer ( kind = 4 ) N, is the number of variables.
+ ! N must not exceed M.
+ !
+ ! Input/output, real ( kind = 8 ) X(N). On input, X must contain an initial
+ ! estimate of the solution vector. On output X contains the final
+ ! estimate of the solution vector.
+ !
+ ! Output, real ( kind = 8 ) FVEC(M), the functions evaluated at the output X.
+ !
+ ! Output, real ( kind = 8 ) FJAC(LDFJAC,N), an M by N array. The upper
+ ! N by N submatrix of FJAC contains an upper triangular matrix R with
+ ! diagonal elements of nonincreasing magnitude such that
+ ! P' * ( JAC' * JAC ) * P = R' * R,
+ ! where P is a permutation matrix and JAC is the final calculated jacobian.
+ ! Column J of P is column IPVT(J) of the identity matrix. The lower
+ ! trapezoidal part of FJAC contains information generated during
+ ! the computation of R.
+ !
+ ! Input, integer ( kind = 4 ) LDFJAC, the leading dimension of FJAC.
+ ! LDFJAC must be at least M.
+ !
+ ! Input, real ( kind = 8 ) FTOL. Termination occurs when both the actual
+ ! and predicted relative reductions in the sum of squares are at most FTOL.
+ ! Therefore, FTOL measures the relative error desired in the sum of
+ ! squares. FTOL should be nonnegative.
+ !
+ ! Input, real ( kind = 8 ) XTOL. Termination occurs when the relative error
+ ! between two consecutive iterates is at most XTOL. XTOL should be
+ ! nonnegative.
+ !
+ ! Input, real ( kind = 8 ) GTOL. Termination occurs when the cosine of the
+ ! angle between FVEC and any column of the jacobian is at most GTOL in
+ ! absolute value. Therefore, GTOL measures the orthogonality desired
+ ! between the function vector and the columns of the jacobian. GTOL should
+ ! be nonnegative.
+ !
+ ! Input, integer ( kind = 4 ) MAXFEV. Termination occurs when the number of
+ ! calls to FCN with IFLAG = 1 is at least MAXFEV by the end of an iteration.
+ !
+ ! Input/output, real ( kind = 8 ) DIAG(N). If MODE = 1, then DIAG is set
+ ! internally. If MODE = 2, then DIAG must contain positive entries that
+ ! serve as multiplicative scale factors for the variables.
+ !
+ ! Input, integer ( kind = 4 ) MODE, scaling option.
+ ! 1, variables will be scaled internally.
+ ! 2, scaling is specified by the input DIAG vector.
+ !
+ ! Input, real ( kind = 8 ) FACTOR, determines the initial step bound. This
+ ! bound is set to the product of FACTOR and the euclidean norm of DIAG*X if
+ ! nonzero, or else to FACTOR itself. In most cases, FACTOR should lie
+ ! in the interval (0.1, 100) with 100 the recommended value.
+ !
+ ! Input, integer ( kind = 4 ) NPRINT, enables controlled printing of iterates
+ ! if it is positive. In this case, FCN is called with IFLAG = 0 at the
+ ! beginning of the first iteration and every NPRINT iterations thereafter
+ ! and immediately prior to return, with X and FVEC available
+ ! for printing. If NPRINT is not positive, no special calls
+ ! of FCN with IFLAG = 0 are made.
+ !
+ ! Output, integer ( kind = 4 ) INFO, error flag. If the user has terminated
+ ! execution, INFO is set to the (negative) value of IFLAG. See description
+ ! of FCN. Otherwise, INFO is set as follows:
+ ! 0, improper input parameters.
+ ! 1, both actual and predicted relative reductions in the sum of
+ ! squares are at most FTOL.
+ ! 2, relative error between two consecutive iterates is at most XTOL.
+ ! 3, conditions for INFO = 1 and INFO = 2 both hold.
+ ! 4, the cosine of the angle between FVEC and any column of the jacobian
+ ! is at most GTOL in absolute value.
+ ! 5, number of calls to FCN with IFLAG = 1 has reached MAXFEV.
+ ! 6, FTOL is too small. No further reduction in the sum of squares
+ ! is possible.
+ ! 7, XTOL is too small. No further improvement in the approximate
+ ! solution X is possible.
+ ! 8, GTOL is too small. FVEC is orthogonal to the columns of the
+ ! jacobian to machine precision.
+ !
+ ! Output, integer ( kind = 4 ) NFEV, the number of calls to FCN with
+ ! IFLAG = 1.
+ !
+ ! Output, integer ( kind = 4 ) NJEV, the number of calls to FCN with
+ ! IFLAG = 2.
+ !
+ ! Output, integer ( kind = 4 ) IPVT(N), defines a permutation matrix P
+ ! such that JAC*P = Q*R, where JAC is the final calculated jacobian, Q is
+ ! orthogonal (not stored), and R is upper triangular with diagonal
+ ! elements of nonincreasing magnitude. Column J of P is column
+ ! IPVT(J) of the identity matrix.
+ !
+ ! Output, real ( kind = 8 ) QTF(N), contains the first N elements of Q'*FVEC.
+ !
+ IMPLICIT NONE
+
+ integer ( kind = 4 ) ldfjac
+ integer ( kind = 4 ) m
+ integer ( kind = 4 ) n
+
+ real ( kind = 8 ) actred
+ real ( kind = 8 ) delta
+ real ( kind = 8 ) diag(n)
+ real ( kind = 8 ) dirder
+ real ( kind = 8 ) epsmch
+ real ( kind = 8 ) factor
+ external fcn
+ real ( kind = 8 ) fjac(ldfjac,n)
+ real ( kind = 8 ) fnorm
+ real ( kind = 8 ) fnorm1
+ real ( kind = 8 ) ftol
+ real ( kind = 8 ) fvec(m)
+ real ( kind = 8 ) gnorm
+ real ( kind = 8 ) gtol
+ integer ( kind = 4 ) i
+ integer ( kind = 4 ) iflag
+ integer ( kind = 4 ) info
+ integer ( kind = 4 ) ipvt(n)
+ integer ( kind = 4 ) iter
+ integer ( kind = 4 ) j
+ integer ( kind = 4 ) l
+ integer ( kind = 4 ) maxfev
+ integer ( kind = 4 ) mode
+ integer ( kind = 4 ) nfev
+ integer ( kind = 4 ) njev
+ integer ( kind = 4 ) nprint
+ real ( kind = 8 ) par
+ logical pivot
+ real ( kind = 8 ) pnorm
+ real ( kind = 8 ) prered
+ real ( kind = 8 ) qtf(n)
+ real ( kind = 8 ) ratio
+ real ( kind = 8 ) sum2
+ real ( kind = 8 ) temp
+ real ( kind = 8 ) temp1
+ real ( kind = 8 ) temp2
+ real ( kind = 8 ) wa1(n)
+ real ( kind = 8 ) wa2(n)
+ real ( kind = 8 ) wa3(n)
+ real ( kind = 8 ) wa4(m)
+ real ( kind = 8 ) xnorm
+ real ( kind = 8 ) x(n)
+ real ( kind = 8 ) xtol
+ real ( kind = 8 ) phi,k_s
+ integer ( kind = 4 ) isiter
+ integer ( kind = 4 ) npoint
+ integer ( kind = 4 ) nptf
+ real ( kind = 8 ) xdat(npoint)
+ real ( kind = 8 ) ydat (nptf,npoint)
+ real ( kind = 8 ) ydatks(nptf,npoint)
+ real ( kind = 8 ), optional :: L_vgm
+
+ epsmch = epsilon ( epsmch )
+
+ info = 0
+ iflag = 0
+ nfev = 0
+ njev = 0
+ !
+ ! Check the input parameters for errors.
+ !
+ IF ( n <= 0 ) THEN
+ go to 300
+ ENDIF
+
+ IF ( m < n ) THEN
+ go to 300
+ ENDIF
+
+ IF ( ldfjac < m &
+ .or. ftol < 0.0D+00 .or. xtol < 0.0D+00 .or. gtol < 0.0D+00 &
+ .or. maxfev <= 0 .or. factor <= 0.0D+00 ) THEN
+ go to 300
+ ENDIF
+
+ IF ( mode == 2 ) THEN
+ DO j = 1, n
+ IF ( diag(j) <= 0.0D+00 ) THEN
+ go to 300
+ ENDIF
+ ENDDO
+ ENDIF
+ !
+ ! Evaluate the function at the starting point and calculate its norm.
+ !
+ iflag = 1
+ IF (present(L_vgm)) THEN
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter, L_vgm)
+ ELSE
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter )
+ ENDIF
+ nfev = 1
+ IF ( iflag < 0 ) THEN
+ go to 300
+ ENDIF
+
+ fnorm = enorm ( m, fvec )
+ !
+ ! Initialize Levenberg-Marquardt parameter and iteration counter.
+ !
+ par = 0.0D+00
+ iter = 1
+ !
+ ! Beginning of the outer loop.
+ !
+ DO
+ !
+ ! Calculate the jacobian matrix.
+ !
+ iflag = 2
+ IF (present(L_vgm)) THEN
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter, L_vgm)
+ ELSE
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter )
+ ENDIF
+
+ njev = njev + 1
+
+ IF ( iflag < 0 ) THEN
+ go to 300
+ ENDIF
+ !
+ ! IF requested, call FCN to enable printing of iterates.
+ !
+ IF ( 0 < nprint ) THEN
+ iflag = 0
+ IF ( mod ( iter - 1, nprint ) == 0 ) THEN
+ IF (present(L_vgm)) THEN
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter, L_vgm)
+ ELSE
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter )
+ ENDIF
+ ENDIF
+ IF ( iflag < 0 ) THEN
+ go to 300
+ ENDIF
+ ENDIF
+ !
+ ! Compute the QR factorization of the jacobian.
+ !
+ pivot = .true.
+ CALL qrfac ( m, n, fjac, ldfjac, pivot, ipvt, n, wa1, wa2 )
+
+ ! On the first iteration and if mode is 1, scale according
+ ! to the norms of the columns of the initial jacobian.
+ !
+ IF ( iter == 1 ) THEN
+
+ IF ( mode /= 2 ) THEN
+ diag(1:n) = wa2(1:n)
+ DO j = 1, n
+ IF ( wa2(j) == 0.0D+00 ) THEN
+ diag(j) = 1.0D+00
+ ENDIF
+ ENDDO
+ ENDIF
+ !
+ ! On the first iteration, calculate the norm of the scaled X
+ ! and initialize the step bound DELTA.
+ !
+ wa3(1:n) = diag(1:n) * x(1:n)
+
+ xnorm = enorm ( n, wa3 )
+
+ IF ( xnorm == 0.0D+00 ) THEN
+ delta = factor
+ ELSE
+ delta = factor * xnorm
+ ENDIF
+
+ ENDIF
+ !
+ ! Form Q'*FVEC and store the first N components in QTF.
+ !
+ wa4(1:m) = fvec(1:m)
+
+ DO j = 1, n
+
+ IF ( fjac(j,j) /= 0.0D+00 ) THEN
+ sum2 = dot_product ( wa4(j:m), fjac(j:m,j) )
+ temp = - sum2 / fjac(j,j)
+ wa4(j:m) = wa4(j:m) + fjac(j:m,j) * temp
+ ENDIF
+
+ fjac(j,j) = wa1(j)
+ qtf(j) = wa4(j)
+
+ ENDDO
+ !
+ ! Compute the norm of the scaled gradient.
+ !
+ gnorm = 0.0D+00
+
+ IF ( fnorm /= 0.0D+00 ) THEN
+
+ DO j = 1, n
+ l = ipvt(j)
+ IF ( wa2(l) /= 0.0D+00 ) THEN
+ sum2 = dot_product ( qtf(1:j), fjac(1:j,j) ) / fnorm
+ gnorm = max ( gnorm, abs ( sum2 / wa2(l) ) )
+ ENDIF
+ ENDDO
+
+ ENDIF
+ !
+ ! Test for convergence of the gradient norm.
+ !
+ IF ( gnorm <= gtol ) THEN
+ info = 4
+ go to 300
+ ENDIF
+ !
+ ! Rescale if necessary.
+ !
+ IF ( mode /= 2 ) THEN
+ DO j = 1, n
+ diag(j) = max ( diag(j), wa2(j) )
+ ENDDO
+ ENDIF
+ !
+ ! Beginning of the inner loop.
+ !
+ DO
+ !
+ ! Determine the Levenberg-Marquardt parameter.
+
+ CALL lmpar ( n, fjac, ldfjac, ipvt, diag, qtf, delta, par, wa1, wa2 )
+
+ ! Store the direction p and x + p. calculate the norm of p.
+ !
+ wa1(1:n) = - wa1(1:n)
+ wa2(1:n) = x(1:n) + wa1(1:n)
+ wa3(1:n) = diag(1:n) * wa1(1:n)
+
+ pnorm = enorm ( n, wa3 )
+ !
+ ! On the first iteration, adjust the initial step bound.
+ !
+ IF ( iter == 1 ) THEN
+ delta = min ( delta, pnorm )
+ ENDIF
+ !
+ ! Evaluate the function at x + p and calculate its norm.
+ !
+ iflag = 1
+ IF (present(L_vgm)) THEN
+ CALL fcn ( m, n, wa2, wa4, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter, L_vgm)
+ ELSE
+ CALL fcn ( m, n, wa2, wa4, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter )
+ ENDIF
+
+ nfev = nfev + 1
+
+ IF ( iflag < 0 ) THEN
+ go to 300
+ ENDIF
+
+ fnorm1 = enorm ( m, wa4 )
+ !
+ ! Compute the scaled actual reduction.
+ !
+ IF ( 0.1D+00 * fnorm1 < fnorm ) THEN
+ actred = 1.0D+00 - ( fnorm1 / fnorm ) ** 2
+ ELSE
+ actred = - 1.0D+00
+ ENDIF
+ !
+ ! Compute the scaled predicted reduction and
+ ! the scaled directional derivative.
+ !
+ DO j = 1, n
+ wa3(j) = 0.0D+00
+ l = ipvt(j)
+ temp = wa1(l)
+ wa3(1:j) = wa3(1:j) + fjac(1:j,j) * temp
+ ENDDO
+
+ temp1 = enorm ( n, wa3 ) / fnorm
+ temp2 = ( sqrt ( par ) * pnorm ) / fnorm
+ prered = temp1 ** 2 + temp2 ** 2 / 0.5D+00
+ dirder = - ( temp1 ** 2 + temp2 ** 2 )
+ !
+ ! Compute the ratio of the actual to the predicted reduction.
+ !
+ IF ( prered /= 0.0D+00 ) THEN
+ ratio = actred / prered
+ ELSE
+ ratio = 0.0D+00
+ ENDIF
+ !
+ ! Update the step bound.
+ !
+ IF ( ratio <= 0.25D+00 ) THEN
+
+ IF ( 0.0D+00 <= actred ) THEN
+ temp = 0.5D+00
+ ENDIF
+
+ IF ( actred < 0.0D+00 ) THEN
+ temp = 0.5D+00 * dirder / ( dirder + 0.5D+00 * actred )
+ ENDIF
+
+ IF ( 0.1D+00 * fnorm1 >= fnorm .or. temp < 0.1D+00 ) THEN
+ temp = 0.1D+00
+ ENDIF
+
+ delta = temp * min ( delta, pnorm / 0.1D+00 )
+ par = par / temp
+
+ ELSE
+
+ IF ( par == 0.0D+00 .or. ratio >= 0.75D+00 ) THEN
+ delta = 2.0D+00 * pnorm
+ par = 0.5D+00 * par
+ ENDIF
+
+ ENDIF
+ !
+ ! Successful iteration.
+ !
+ ! Update X, FVEC, and their norms.
+ !
+ IF ( 0.0001D+00 <= ratio ) THEN
+ x(1:n) = wa2(1:n)
+ wa2(1:n) = diag(1:n) * x(1:n)
+ fvec(1:m) = wa4(1:m)
+ xnorm = enorm ( n, wa2 )
+ fnorm = fnorm1
+ iter = iter + 1
+ ENDIF
+ !
+ ! Tests for convergence.
+ !
+ IF ( abs ( actred) <= ftol .and. &
+ prered <= ftol .and. &
+ 0.5D+00 * ratio <= 1.0D+00 ) THEN
+ info = 1
+ ENDIF
+
+ IF ( delta <= xtol * xnorm ) THEN
+ info = 2
+ ENDIF
+
+ IF ( abs ( actred) <= ftol .and. prered <= ftol &
+ .and. 0.5D+00 * ratio <= 1.0D+00 .and. info == 2 ) THEN
+ info = 3
+ ENDIF
+
+ IF ( info /= 0 ) THEN
+ go to 300
+ ENDIF
+ !
+ ! Tests for termination and stringent tolerances.
+ !
+ IF ( nfev >= maxfev ) THEN
+ info = 5
+ ENDIF
+
+ IF ( abs ( actred ) <= epsmch .and. prered <= epsmch &
+ .and. 0.5D+00 * ratio <= 1.0D+00 ) THEN
+ info = 6
+ ENDIF
+
+ IF ( delta <= epsmch * xnorm ) THEN
+ info = 7
+ ENDIF
+
+ IF ( gnorm <= epsmch ) THEN
+ info = 8
+ ENDIF
+
+ IF ( info /= 0 ) THEN
+ go to 300
+ ENDIF
+ !
+ ! End of the inner loop. repeat IF iteration unsuccessful.
+ !
+ IF ( 0.0001D+00 <= ratio ) THEN
+ EXIT
+ ENDIF
+
+ ENDDO
+ !
+ ! End of the outer loop.
+ !
+ ENDDO
+
+ 300 continue
+ !
+ ! Termination, either normal or user imposed.
+ !
+ IF ( iflag < 0 ) THEN
+ info = iflag
+ ENDIF
+
+ iflag = 0
+
+ IF ( 0 < nprint ) THEN
+ IF (present(L_vgm)) THEN
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter, L_vgm)
+ ELSE
+ CALL fcn ( m, n, x, fvec, fjac, ldfjac, iflag, xdat, npoint, ydat, ydatks, nptf, phi, k_s, isiter )
+ ENDIF
+ ENDIF
+
+ RETURN
+ END SUBROUTINE lmder
+
+ SUBROUTINE lmpar ( n, r, ldr, ipvt, diag, qtb, delta, par, x, sdiag )
+
+ !*****************************************************************************80
+ !
+ !! LMPAR computes a parameter for the Levenberg-Marquardt method.
+ !
+ ! Discussion:
+ !
+ ! Given an M by N matrix A, an N by N nonsingular diagonal
+ ! matrix D, an M-vector B, and a positive number DELTA,
+ ! the problem is to determine a value for the parameter
+ ! PAR such that IF X solves the system
+ !
+ ! A*X = B,
+ ! sqrt ( PAR ) * D * X = 0,
+ !
+ ! in the least squares sense, and DXNORM is the euclidean
+ ! norm of D*X, THEN either PAR is zero and
+ !
+ ! ( DXNORM - DELTA ) <= 0.1 * DELTA,
+ !
+ ! or PAR is positive and
+ !
+ ! abs ( DXNORM - DELTA) <= 0.1 * DELTA.
+ !
+ ! This FUNCTION completes the solution of the problem
+ ! IF it is provided with the necessary information from the
+ ! QR factorization, with column pivoting, of A. That is, IF
+ ! A*P = Q*R, WHERE P is a permutation matrix, Q has orthogonal
+ ! columns, and R is an upper triangular matrix with diagonal
+ ! elements of nonincreasing magnitude, THEN LMPAR expects
+ ! the full upper triangle of R, the permutation matrix P,
+ ! and the first N components of Q'*B. On output
+ ! LMPAR also provides an upper triangular matrix S such that
+ !
+ ! P' * ( A' * A + PAR * D * D ) * P = S'* S.
+ !
+ ! S is employed within LMPAR and may be of separate interest.
+ !
+ ! Only a few iterations are generally needed for convergence
+ ! of the algorithm.
+ !
+ ! IF, however, the limit of 10 iterations is reached, THEN the output
+ ! PAR will contain the best value obtained so far.
+ !
+ ! Licensing:
+ !
+ ! This code may freely be copied, modified, and used for any purpose.
+ !
+ ! Modified:
+ !
+ ! 24 January 2014
+ !
+ ! Author:
+ !
+ ! Original FORTRAN77 version by Jorge More, Burton Garbow, Kenneth Hillstrom.
+ ! FORTRAN90 version by John Burkardt.
+ !
+ ! Reference:
+ !
+ ! Jorge More, Burton Garbow, Kenneth Hillstrom,
+ ! User Guide for MINPACK-1,
+ ! Technical Report ANL-80-74,
+ ! Argonne National Laboratory, 1980.
+ !
+ ! Parameters:
+ !
+ ! Input, integer ( kind = 4 ) N, the order of R.
+ !
+ ! Input/output, real ( kind = 8 ) R(LDR,N),the N by N matrix. The full
+ ! upper triangle must contain the full upper triangle of the matrix R.
+ ! On output the full upper triangle is unaltered, and the strict lower
+ ! triangle CONTAINS the strict upper triangle (transposed) of the upper
+ ! triangular matrix S.
+ !
+ ! Input, integer ( kind = 4 ) LDR, the leading dimension of R. LDR must be
+ ! no less than N.
+ !
+ ! Input, integer ( kind = 4 ) IPVT(N), defines the permutation matrix P
+ ! such that A*P = Q*R. Column J of P is column IPVT(J) of the
+ ! identity matrix.
+ !
+ ! Input, real ( kind = 8 ) DIAG(N), the diagonal elements of the matrix D.
+ !
+ ! Input, real ( kind = 8 ) QTB(N), the first N elements of the vector Q'*B.
+ !
+ ! Input, real ( kind = 8 ) DELTA, an upper bound on the euclidean norm
+ ! of D*X. DELTA should be positive.
+ !
+ ! Input/output, real ( kind = 8 ) PAR. On input an initial estimate of the
+ ! Levenberg-Marquardt parameter. On output the final estimate.
+ ! PAR should be nonnegative.
+ !
+ ! Output, real ( kind = 8 ) X(N), the least squares solution of the system
+ ! A*X = B, sqrt(PAR)*D*X = 0, for the output value of PAR.
+ !
+ ! Output, real ( kind = 8 ) SDIAG(N), the diagonal elements of the upper
+ ! triangular matrix S.
+ !
+ IMPLICIT NONE
+
+ integer ( kind = 4 ) ldr
+ integer ( kind = 4 ) n
+
+ real ( kind = 8 ) delta
+ real ( kind = 8 ) diag(n)
+ real ( kind = 8 ) dwarf
+ real ( kind = 8 ) dxnorm
+ real ( kind = 8 ) gnorm
+ real ( kind = 8 ) fp
+ integer ( kind = 4 ) i
+ integer ( kind = 4 ) ipvt(n)
+ integer ( kind = 4 ) iter
+ integer ( kind = 4 ) j
+ integer ( kind = 4 ) k
+ integer ( kind = 4 ) l
+ integer ( kind = 4 ) nsing
+ real ( kind = 8 ) par
+ real ( kind = 8 ) parc
+ real ( kind = 8 ) parl
+ real ( kind = 8 ) paru
+ real ( kind = 8 ) qnorm
+ real ( kind = 8 ) qtb(n)
+ real ( kind = 8 ) r(ldr,n)
+ real ( kind = 8 ) sdiag(n)
+ real ( kind = 8 ) sum2
+ real ( kind = 8 ) temp
+ real ( kind = 8 ) wa1(n)
+ real ( kind = 8 ) wa2(n)
+ real ( kind = 8 ) x(n)
+
+ !
+ ! DWARF is the smallest positive magnitude.
+ !
+ dwarf = tiny ( dwarf )
+ !
+ ! Compute and store in X the Gauss-Newton direction.
+ !
+ ! IF the jacobian is rank-deficient, obtain a least squares solution.
+ !
+ nsing = n
+
+ DO j = 1, n
+ wa1(j) = qtb(j)
+ IF ( r(j,j) == 0.0D+00 .and. nsing == n ) THEN
+ nsing = j - 1
+ ENDIF
+ IF ( nsing < n ) THEN
+ wa1(j) = 0.0D+00
+ ENDIF
+ ENDDO
+
+ DO k = 1, nsing
+ j = nsing - k + 1
+ wa1(j) = wa1(j) / r(j,j)
+ temp = wa1(j)
+ wa1(1:j-1) = wa1(1:j-1) - r(1:j-1,j) * temp
+ ENDDO
+
+ DO j = 1, n
+ l = ipvt(j)
+ x(l) = wa1(j)
+ ENDDO
+ !
+ ! Initialize the iteration counter.
+ ! Evaluate the FUNCTION at the origin, and test
+ ! for acceptance of the Gauss-Newton direction.
+ !
+ iter = 0
+ wa2(1:n) = diag(1:n) * x(1:n)
+ dxnorm = enorm ( n, wa2 )
+ fp = dxnorm - delta
+
+ IF ( fp <= 0.1D+00 * delta ) THEN
+ IF ( iter == 0 ) THEN
+ par = 0.0D+00
+ ENDIF
+ RETURN
+ ENDIF
+ !
+ ! IF the jacobian is not rank deficient, the Newton
+ ! step provides a lower bound, PARL, for the zero of
+ ! the FUNCTION.
+ !
+ ! Otherwise set this bound to zero.
+ !
+ parl = 0.0D+00
+
+ IF ( n <= nsing ) THEN
+
+ DO j = 1, n
+ l = ipvt(j)
+ wa1(j) = diag(l) * ( wa2(l) / dxnorm )
+ ENDDO
+
+ DO j = 1, n
+ sum2 = dot_product ( wa1(1:j-1), r(1:j-1,j) )
+ wa1(j) = ( wa1(j) - sum2 ) / r(j,j)
+ ENDDO
+
+ temp = enorm ( n, wa1 )
+ parl = ( ( fp / delta ) / temp ) / temp
+
+ ENDIF
+ !
+ ! Calculate an upper bound, PARU, for the zero of the FUNCTION.
+ !
+ DO j = 1, n
+ sum2 = dot_product ( qtb(1:j), r(1:j,j) )
+ l = ipvt(j)
+ wa1(j) = sum2 / diag(l)
+ ENDDO
+
+ gnorm = enorm ( n, wa1 )
+ paru = gnorm / delta
+
+ IF ( paru == 0.0D+00 ) THEN
+ paru = dwarf / min ( delta, 0.1D+00 )
+ ENDIF
+ !
+ ! IF the input PAR lies outside of the interval (PARL, PARU),
+ ! set PAR to the closer endpoint.
+ !
+ par = max ( par, parl )
+ par = min ( par, paru )
+ IF ( par == 0.0D+00 ) THEN
+ par = gnorm / dxnorm
+ ENDIF
+ !
+ ! Beginning of an iteration.
+ !
+ DO
+
+ iter = iter + 1
+ !
+ ! Evaluate the FUNCTION at the current value of PAR.
+ !
+ IF ( par == 0.0D+00 ) THEN
+ par = max ( dwarf, 0.001D+00 * paru )
+ ENDIF
+
+ wa1(1:n) = sqrt ( par ) * diag(1:n)
+
+ CALL qrsolv ( n, r, ldr, ipvt, wa1, qtb, x, sdiag )
+
+ wa2(1:n) = diag(1:n) * x(1:n)
+ dxnorm = enorm ( n, wa2 )
+ temp = fp
+ fp = dxnorm - delta
+ !
+ ! IF the FUNCTION is small enough, accept the current value of PAR.
+ !
+ IF ( abs ( fp ) <= 0.1D+00 * delta ) THEN
+ EXIT
+ ENDIF
+ !
+ ! Test for the exceptional cases WHERE PARL
+ ! is zero or the number of iterations has reached 10.
+ !
+ IF ( parl == 0.0D+00 .and. fp <= temp .and. temp < 0.0D+00 ) THEN
+ EXIT
+ ELSEIF ( iter == 10 ) THEN
+ EXIT
+ ENDIF
+ !
+ ! Compute the Newton correction.
+ !
+ DO j = 1, n
+ l = ipvt(j)
+ wa1(j) = diag(l) * ( wa2(l) / dxnorm )
+ ENDDO
+
+ DO j = 1, n
+ wa1(j) = wa1(j) / sdiag(j)
+ temp = wa1(j)
+ wa1(j+1:n) = wa1(j+1:n) - r(j+1:n,j) * temp
+ ENDDO
+
+ temp = enorm ( n, wa1 )
+ parc = ( ( fp / delta ) / temp ) / temp
+ !
+ ! Depending on the sign of the FUNCTION, update PARL or PARU.
+ !
+ IF ( 0.0D+00 < fp ) THEN
+ parl = max ( parl, par )
+ ELSEIF ( fp < 0.0D+00 ) THEN
+ paru = min ( paru, par )
+ ENDIF
+ !
+ ! Compute an improved estimate for PAR.
+ !
+ par = max ( parl, par + parc )
+ !
+ ! END of an iteration.
+ !
+ ENDDO
+ !
+ ! Termination.
+ !
+ IF ( iter == 0 ) THEN
+ par = 0.0D+00
+ ENDIF
+
+ RETURN
+
+ END SUBROUTINE lmpar
+
+ SUBROUTINE qrfac ( m, n, a, lda, pivot, ipvt, lipvt, rdiag, acnorm )
+
+ !*****************************************************************************80
+ !
+ !! QRFAC computes a QR factorization using Householder transformations.
+ !
+ ! Discussion:
+ !
+ ! This FUNCTION uses Householder transformations with optional column
+ ! pivoting to compute a QR factorization of the
+ ! M by N matrix A. That is, QRFAC determines an orthogonal
+ ! matrix Q, a permutation matrix P, and an upper trapezoidal
+ ! matrix R with diagonal elements of nonincreasing magnitude,
+ ! such that A*P = Q*R.
+ !
+ ! The Householder transformation for column K, K = 1,2,...,min(M,N),
+ ! is of the form
+ !
+ ! I - ( 1 / U(K) ) * U * U'
+ !
+ ! WHERE U has zeros in the first K-1 positions.
+ !
+ ! The form of this transformation and the method of pivoting first
+ ! appeared in the corresponding LINPACK routine.
+ !
+ ! Licensing:
+ !
+ ! This code may freely be copied, modified, and used for any purpose.
+ !
+ ! Modified:
+ !
+ ! 06 April 2010
+ !
+ ! Author:
+ !
+ ! Original FORTRAN77 version by Jorge More, Burton Garbow, Kenneth Hillstrom.
+ ! FORTRAN90 version by John Burkardt.
+ !
+ ! Reference:
+ !
+ ! Jorge More, Burton Garbow, Kenneth Hillstrom,
+ ! User Guide for MINPACK-1,
+ ! Technical Report ANL-80-74,
+ ! Argonne National Laboratory, 1980.
+ !
+ ! Parameters:
+ !
+ ! Input, integer ( kind = 4 ) M, the number of rows of A.
+ !
+ ! Input, integer ( kind = 4 ) N, the number of columns of A.
+ !
+ ! Input/output, real ( kind = 8 ) A(LDA,N), the M by N array.
+ ! On input, A CONTAINS the matrix for which the QR factorization is to
+ ! be computed. On output, the strict upper trapezoidal part of A CONTAINS
+ ! the strict upper trapezoidal part of R, and the lower trapezoidal
+ ! part of A CONTAINS a factored form of Q, the non-trivial elements of
+ ! the U vectors described above.
+ !
+ ! Input, integer ( kind = 4 ) LDA, the leading dimension of A, which must
+ ! be no less than M.
+ !
+ ! Input, logical PIVOT, is TRUE IF column pivoting is to be carried out.
+ !
+ ! Output, integer ( kind = 4 ) IPVT(LIPVT), defines the permutation matrix P
+ ! such that A*P = Q*R. Column J of P is column IPVT(J) of the identity
+ ! matrix. IF PIVOT is false, IPVT is not referenced.
+ !
+ ! Input, integer ( kind = 4 ) LIPVT, the dimension of IPVT, which should
+ ! be N IF pivoting is used.
+ !
+ ! Output, real ( kind = 8 ) RDIAG(N), CONTAINS the diagonal elements of R.
+ !
+ ! Output, real ( kind = 8 ) ACNORM(N), the norms of the corresponding
+ ! columns of the input matrix A. IF this information is not needed,
+ ! THEN ACNORM can coincide with RDIAG.
+ !
+ IMPLICIT NONE
+
+ integer ( kind = 4 ) lda
+ integer ( kind = 4 ) lipvt
+ integer ( kind = 4 ) m
+ integer ( kind = 4 ) n
+
+ real ( kind = 8 ) a(lda,n)
+ real ( kind = 8 ) acnorm(n)
+ real ( kind = 8 ) ajnorm
+ real ( kind = 8 ) epsmch
+ integer ( kind = 4 ) i
+ integer ( kind = 4 ) i4_temp
+ integer ( kind = 4 ) ipvt(lipvt)
+ integer ( kind = 4 ) j
+ integer ( kind = 4 ) k
+ integer ( kind = 4 ) kmax
+ integer ( kind = 4 ) minmn
+ logical pivot
+ real ( kind = 8 ) r8_temp(m)
+ real ( kind = 8 ) rdiag(n)
+ real ( kind = 8 ) temp
+ real ( kind = 8 ) wa(n)
+
+ epsmch = epsilon ( epsmch )
+ !
+ ! Compute the initial column norms and initialize several arrays.
+ !
+ DO j = 1, n
+ acnorm(j) = enorm ( m, a(1:m,j) )
+ ENDDO
+
+ rdiag(1:n) = acnorm(1:n)
+ wa(1:n) = acnorm(1:n)
+
+ IF ( pivot ) THEN
+ DO j = 1, n
+ ipvt(j) = j
+ ENDDO
+ ENDIF
+ !
+ ! Reduce A to R with Householder transformations.
+ !
+ minmn = min ( m, n )
+
+ DO j = 1, minmn
+ !
+ ! Bring the column of largest norm into the pivot position.
+ !
+ IF ( pivot ) THEN
+
+ kmax = j
+
+ DO k = j, n
+ IF ( rdiag(kmax) < rdiag(k) ) THEN
+ kmax = k
+ ENDIF
+ ENDDO
+
+ IF ( kmax /= j ) THEN
+
+ r8_temp(1:m) = a(1:m,j)
+ a(1:m,j) = a(1:m,kmax)
+ a(1:m,kmax) = r8_temp(1:m)
+
+ rdiag(kmax) = rdiag(j)
+ wa(kmax) = wa(j)
+
+ i4_temp = ipvt(j)
+ ipvt(j) = ipvt(kmax)
+ ipvt(kmax) = i4_temp
+
+ ENDIF
+
+ ENDIF
+ !
+ ! Compute the Householder transformation to reduce the
+ ! J-th column of A to a multiple of the J-th unit vector.
+ !
+ ajnorm = enorm ( m-j+1, a(j,j) )
+
+ IF ( ajnorm /= 0.0D+00 ) THEN
+
+ IF ( a(j,j) < 0.0D+00 ) THEN
+ ajnorm = -ajnorm
+ ENDIF
+
+ a(j:m,j) = a(j:m,j) / ajnorm
+ a(j,j) = a(j,j) + 1.0D+00
+ !
+ ! Apply the transformation to the remaining columns and update the norms.
+ !
+ DO k = j + 1, n
+
+ temp = dot_product ( a(j:m,j), a(j:m,k) ) / a(j,j)
+
+ a(j:m,k) = a(j:m,k) - temp * a(j:m,j)
+
+ IF ( pivot .and. rdiag(k) /= 0.0D+00 ) THEN
+
+ temp = a(j,k) / rdiag(k)
+ rdiag(k) = rdiag(k) * sqrt ( max ( 0.0D+00, 1.0D+00-temp ** 2 ) )
+
+ IF ( 0.05D+00 * ( rdiag(k) / wa(k) ) ** 2 <= epsmch ) THEN
+ rdiag(k) = enorm ( m-j, a(j+1,k) )
+ wa(k) = rdiag(k)
+ ENDIF
+
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+
+ rdiag(j) = - ajnorm
+
+ ENDDO
+
+ RETURN
+
+ END SUBROUTINE qrfac
+
+ SUBROUTINE qrsolv ( n, r, ldr, ipvt, diag, qtb, x, sdiag )
+
+ !*****************************************************************************80
+ !
+ !! QRSOLV solves a rectangular linear system A*x=b in the least squares sense.
+ !
+ ! Discussion:
+ !
+ ! Given an M by N matrix A, an N by N diagonal matrix D,
+ ! and an M-vector B, the problem is to determine an X which
+ ! solves the system
+ !
+ ! A*X = B
+ ! D*X = 0
+ !
+ ! in the least squares sense.
+ !
+ ! This FUNCTION completes the solution of the problem
+ ! IF it is provided with the necessary information from the
+ ! QR factorization, with column pivoting, of A. That is, IF
+ ! A*P = Q*R, WHERE P is a permutation matrix, Q has orthogonal
+ ! columns, and R is an upper triangular matrix with diagonal
+ ! elements of nonincreasing magnitude, THEN QRSOLV expects
+ ! the full upper triangle of R, the permutation matrix p,
+ ! and the first N components of Q'*B.
+ !
+ ! The system is THEN equivalent to
+ !
+ ! R*Z = Q'*B
+ ! P'*D*P*Z = 0
+ !
+ ! WHERE X = P*Z. IF this system does not have full rank,
+ ! THEN a least squares solution is obtained. On output QRSOLV
+ ! also provides an upper triangular matrix S such that
+ !
+ ! P'*(A'*A + D*D)*P = S'*S.
+ !
+ ! S is computed within QRSOLV and may be of separate interest.
+ !
+ ! Licensing:
+ !
+ ! This code may freely be copied, modified, and used for any purpose.
+ !
+ ! Modified:
+ !
+ ! 06 April 2010
+ !
+ ! Author:
+ !
+ ! Original FORTRAN77 version by Jorge More, Burton Garbow, Kenneth Hillstrom.
+ ! FORTRAN90 version by John Burkardt.
+ !
+ ! Reference:
+ !
+ ! Jorge More, Burton Garbow, Kenneth Hillstrom,
+ ! User Guide for MINPACK-1,
+ ! Technical Report ANL-80-74,
+ ! Argonne National Laboratory, 1980.
+ !
+ ! Parameters:
+ !
+ ! Input, integer ( kind = 4 ) N, the order of R.
+ !
+ ! Input/output, real ( kind = 8 ) R(LDR,N), the N by N matrix.
+ ! On input the full upper triangle must contain the full upper triangle
+ ! of the matrix R. On output the full upper triangle is unaltered, and
+ ! the strict lower triangle CONTAINS the strict upper triangle
+ ! (transposed) of the upper triangular matrix S.
+ !
+ ! Input, integer ( kind = 4 ) LDR, the leading dimension of R, which must be
+ ! at least N.
+ !
+ ! Input, integer ( kind = 4 ) IPVT(N), defines the permutation matrix P such
+ ! that A*P = Q*R. Column J of P is column IPVT(J) of the identity matrix.
+ !
+ ! Input, real ( kind = 8 ) DIAG(N), the diagonal elements of the matrix D.
+ !
+ ! Input, real ( kind = 8 ) QTB(N), the first N elements of the vector Q'*B.
+ !
+ ! Output, real ( kind = 8 ) X(N), the least squares solution.
+ !
+ ! Output, real ( kind = 8 ) SDIAG(N), the diagonal elements of the upper
+ ! triangular matrix S.
+ !
+ IMPLICIT NONE
+
+ integer ( kind = 4 ) ldr
+ integer ( kind = 4 ) n
+
+ real ( kind = 8 ) c
+ real ( kind = 8 ) cotan
+ real ( kind = 8 ) diag(n)
+ integer ( kind = 4 ) i
+ integer ( kind = 4 ) ipvt(n)
+ integer ( kind = 4 ) j
+ integer ( kind = 4 ) k
+ integer ( kind = 4 ) l
+ integer ( kind = 4 ) nsing
+ real ( kind = 8 ) qtb(n)
+ real ( kind = 8 ) qtbpj
+ real ( kind = 8 ) r(ldr,n)
+ real ( kind = 8 ) s
+ real ( kind = 8 ) sdiag(n)
+ real ( kind = 8 ) sum2
+ real ( kind = 8 ) t
+ real ( kind = 8 ) temp
+ real ( kind = 8 ) wa(n)
+ real ( kind = 8 ) x(n)
+
+ !
+ ! Copy R and Q'*B to preserve input and initialize S.
+ !
+ ! In particular, SAVE the diagonal elements of R in X.
+ !
+ DO j = 1, n
+ r(j:n,j) = r(j,j:n)
+ x(j) = r(j,j)
+ ENDDO
+
+ wa(1:n) = qtb(1:n)
+ !
+ ! Eliminate the diagonal matrix D using a Givens rotation.
+ !
+ DO j = 1, n
+ !
+ ! Prepare the row of D to be eliminated, locating the
+ ! diagonal element using P from the QR factorization.
+ !
+ l = ipvt(j)
+
+ IF ( diag(l) /= 0.0D+00 ) THEN
+
+ sdiag(j:n) = 0.0D+00
+ sdiag(j) = diag(l)
+ !
+ ! The transformations to eliminate the row of D
+ ! modify only a single element of Q'*B
+ ! beyond the first N, which is initially zero.
+ !
+ qtbpj = 0.0D+00
+
+ DO k = j, n
+ !
+ ! Determine a Givens rotation which eliminates the
+ ! appropriate element in the current row of D.
+ !
+ IF ( sdiag(k) /= 0.0D+00 ) THEN
+
+ IF ( abs ( r(k,k) ) < abs ( sdiag(k) ) ) THEN
+ cotan = r(k,k) / sdiag(k)
+ s = 0.5D+00 / sqrt ( 0.25D+00 + 0.25D+00 * cotan ** 2 )
+ c = s * cotan
+ ELSE
+ t = sdiag(k) / r(k,k)
+ c = 0.5D+00 / sqrt ( 0.25D+00 + 0.25D+00 * t ** 2 )
+ s = c * t
+ ENDIF
+ !
+ ! Compute the modified diagonal element of R and
+ ! the modified element of (Q'*B,0).
+ !
+ r(k,k) = c * r(k,k) + s * sdiag(k)
+ temp = c * wa(k) + s * qtbpj
+ qtbpj = - s * wa(k) + c * qtbpj
+ wa(k) = temp
+ !
+ ! Accumulate the tranformation in the row of S.
+ !
+ DO i = k + 1, n
+ temp = c * r(i,k) + s * sdiag(i)
+ sdiag(i) = - s * r(i,k) + c * sdiag(i)
+ r(i,k) = temp
+ ENDDO
+
+ ENDIF
+
+ ENDDO
+
+ ENDIF
+ !
+ ! Store the diagonal element of S and restore
+ ! the corresponding diagonal element of R.
+ !
+ sdiag(j) = r(j,j)
+ r(j,j) = x(j)
+
+ ENDDO
+ !
+ ! Solve the triangular system for Z. IF the system is
+ ! singular, THEN obtain a least squares solution.
+ !
+ nsing = n
+
+ DO j = 1, n
+
+ IF ( sdiag(j) == 0.0D+00 .and. nsing == n ) THEN
+ nsing = j - 1
+ ENDIF
+
+ IF ( nsing < n ) THEN
+ wa(j) = 0.0D+00
+ ENDIF
+
+ ENDDO
+
+ DO j = nsing, 1, -1
+ sum2 = dot_product ( wa(j+1:nsing), r(j+1:nsing,j) )
+ wa(j) = ( wa(j) - sum2 ) / sdiag(j)
+ ENDDO
+ !
+ ! Permute the components of Z back to components of X.
+ !
+ DO j = 1, n
+ l = ipvt(j)
+ x(l) = wa(j)
+ ENDDO
+
+ RETURN
+
+ END SUBROUTINE qrsolv
+
+ FUNCTION enorm ( n, x )
+
+ !*****************************************************************************80
+ !
+ !! ENORM computes the Euclidean norm of a vector.
+ !
+ ! Discussion:
+ !
+ ! This is an extremely simplified version of the original ENORM
+ ! routine, which has been renamed to "ENORM2".
+ !
+ ! Licensing:
+ !
+ ! This code may freely be copied, modified, and used for any purpose.
+ !
+ ! Modified:
+ !
+ ! 06 April 2010
+ !
+ ! Author:
+ !
+ ! Original FORTRAN77 version by Jorge More, Burton Garbow, Kenneth Hillstrom.
+ ! FORTRAN90 version by John Burkardt.
+ !
+ ! Reference:
+ !
+ ! Jorge More, Burton Garbow, Kenneth Hillstrom,
+ ! User Guide for MINPACK-1,
+ ! Technical Report ANL-80-74,
+ ! Argonne National Laboratory, 1980.
+ !
+ ! Parameters:
+ !
+ ! Input, integer ( kind = 4 ) N, is the length of the vector.
+ !
+ ! Input, real ( kind = 8 ) X(N), the vector whose norm is desired.
+ !
+ ! Output, real ( kind = 8 ) ENORM, the Euclidean norm of the vector.
+ !
+ IMPLICIT NONE
+
+ integer ( kind = 4 ) n
+ real ( kind = 8 ) x(n)
+ real ( kind = 8 ) enorm
+
+ enorm = sqrt ( sum ( x(1:n) ** 2 ))
+
+ RETURN
+
+ END FUNCTION enorm
+
+ SUBROUTINE tridia (n, a, b, c, r, u)
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ integer, intent(in) :: n !length of diagonal element vector
+ real(r8), intent(in) :: a(1:n) !subdiagonal elements
+ real(r8), intent(in) :: b(1:n) !diagonal elements
+ real(r8), intent(in) :: c(1:n) !superdiagonal elements
+ real(r8), intent(in) :: r(1:n) !right hand side
+ real(r8), intent(out) :: u(1:n) !solution vector
+
+ integer j
+ real(r8) gam(1:n),bet
+
+ bet = b(1)
+ u(1) = r(1) / bet
+ DO j = 2, n
+ gam(j) = c(j-1) / bet
+ bet = b(j) - a(j) * gam(j)
+ u(j) = (r(j) - a(j)*u(j-1)) / bet
+ ENDDO
+ DO j = n-1, 1, -1
+ u(j) = u(j) - gam(j+1) * u(j+1)
+ ENDDO
+
+ END SUBROUTINE tridia
+
+ ! -----------------------------------------------------------------
+ SUBROUTINE polint(xa,ya,n,x,y)
+
+ ! Given arrays xa and ya, each of length n, and gi
+ ! value y, and an error estimate dy. IF P (x) is the p
+ ! P (xa(i)) = ya(i), i = 1, . . . , n, THEN the returned value
+ ! (from: "Numerical Recipes")
+
+ USE MOD_Precision
+ IMPLICIT NONE
+ integer n,NMAX
+ real(r8) dy,x,y,xa(n),ya(n)
+ parameter (NMAX=10) !Largest anticipated val
+ integer i,m,ns
+ real(r8) den,dif,dift,ho,hp,w,c(NMAX),d(NMAX)
+
+ ns=1
+ dif=abs(x-xa(1))
+
+ DO i=1,n !Here we find the index ns of the closest table entry,
+ dift=abs(x-xa(i))
+ IF(dift.lt.dif) THEN
+ ns=i
+ dif=dift
+ ENDIF
+ c(i)=ya(i) !and initialize the tableau of c's and d's.
+ d(i)=ya(i)
+ ENDDO
+
+ y=ya(ns) !This is the initial approximation to y.
+ ns=ns-1
+
+ DO m=1,n-1 !For each column of the tableau,
+ DO i=1,n-m !we loop over the current c's and d's and update them.
+ ho=xa(i)-x
+ hp=xa(i+m)-x
+ w=c(i+1)-d(i)
+ den=ho-hp
+ IF(den.eq.0.) print*, 'failure in polint' !two input xa's are identical.
+ den=w/den
+ d(i)=hp*den !here the c's and d's are updated.
+ c(i)=ho*den
+ ENDDO
+ IF(2*ns.lt.n-m)THEN !After each column in the tableau is completed, we decide
+ dy=c(ns+1) !which correction, c or d, we want to add to our accumulating
+ ELSE !value of y, i.e., which path to take through
+ dy=d(ns) !the tableau-forking up or down. We DO this in such a
+ ns=ns-1 !way as to take the most "straight line" route through the
+ ENDIF !tableau to its apex, updating ns accordingly to keep track
+ y=y+dy !of WHERE we are. This route keeps the partial approximations
+ ENDDO !centered (insofar as possible) on the target x. T he
+ !last dy added is thus the error indication.
+
+ END SUBROUTINE polint
+
+END MODULE MOD_Utils
diff --git a/src/core_atmosphere/physics/physics_wrf/module_ra_rrtmg_sw.F b/src/core_atmosphere/physics/physics_wrf/module_ra_rrtmg_sw.F
index faa5761c9a..8b679a7adb 100644
--- a/src/core_atmosphere/physics/physics_wrf/module_ra_rrtmg_sw.F
+++ b/src/core_atmosphere/physics/physics_wrf/module_ra_rrtmg_sw.F
@@ -10037,6 +10037,7 @@ subroutine rrtmg_swrad( &
swupb,swupbc,swdnb,swdnbc, &
swupflx, swupflxc, swdnflx, swdnflxc, &
swddir,swddni,swddif, &
+ swvisdir,swvisdif,swnirdir,swnirdif, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte &
@@ -10085,7 +10086,7 @@ subroutine rrtmg_swrad( &
!--- output arguments:
real,intent(out),dimension(ims:ime,jms:jme),optional:: &
- swddir,swddni,swddif
+ swddir,swddni,swddif,swvisdir,swvisdif,swnirdir,swnirdif
real,intent(out),dimension(ims:ime,kms:kme+2,jms:jme ),optional:: &
swupflx,swupflxc,swdnflx,swdnflxc
@@ -10625,6 +10626,14 @@ subroutine rrtmg_swrad( &
swddif(i,j) = swdkdif(1,1) ! jararias 2013/08/10
endif
+ if(present(swvisdir) .and. present(swvisdif) .and. &
+ present(swnirdir) .and. present(swnirdif)) then
+ swvisdir(i,j) = sibvisdir(1,1)
+ swvisdif(i,j) = sibvisdif(1,1)
+ swnirdir(i,j) = sibnirdir(1,1)
+ swnirdif(i,j) = sibnirdif(1,1)
+ endif
+
if(present (swupflx)) then
do k = kts, kte+2
swupflx(i,k,j) = swuflx(1,k)
@@ -10655,6 +10664,20 @@ subroutine rrtmg_swrad( &
swdnbc(i,j) = 0.
endif
+ if(present(swddir) .and. present(swddni) .and. present(swddif)) then
+ swddir(i,j) = 0.
+ swddni(i,j) = 0.
+ swddif(i,j) = 0.
+ endif
+
+ if(present(swvisdir) .and. present(swvisdif) .and. &
+ present(swnirdir) .and. present(swnirdif)) then
+ swvisdir(i,j) = 0.
+ swvisdif(i,j) = 0.
+ swnirdir(i,j) = 0.
+ swnirdif(i,j) = 0.
+ endif
+
endif
end do i_loop !end longitude loop.