From 70fceae824f057397509b8f6e6fa6cfc083c0bfa Mon Sep 17 00:00:00 2001 From: Abby Lewis Date: Wed, 24 Jun 2026 12:04:24 -0400 Subject: [PATCH 1/4] Updates to improve input demo documentation --- base/utils/data/standard_vars.csv | 243 ++++++++-------- models/peprmt/R/helpers.R | 43 +++ ...can_peprmt.qmd => 01_run_pecan_peprmt.qmd} | 91 +++--- .../{input_demo.qmd => 02_input_demo.qmd} | 259 +++++++++++------- .../{event_demo.qmd => 03_event_demo.qmd} | 0 models/peprmt/demo_run/settings_inputdemo.xml | 8 +- models/peprmt/inst/xml_build.R | 48 +--- 7 files changed, 390 insertions(+), 302 deletions(-) create mode 100644 models/peprmt/R/helpers.R rename models/peprmt/demo_run/{run_pecan_peprmt.qmd => 01_run_pecan_peprmt.qmd} (80%) rename models/peprmt/demo_run/{input_demo.qmd => 02_input_demo.qmd} (63%) rename models/peprmt/demo_run/{event_demo.qmd => 03_event_demo.qmd} (100%) diff --git a/base/utils/data/standard_vars.csv b/base/utils/data/standard_vars.csv index 7691a0ebf32..1f3336e3cb6 100755 --- a/base/utils/data/standard_vars.csv +++ b/base/utils/data/standard_vars.csv @@ -1,122 +1,123 @@ -Variable.Name,standard_name,Units,Long.name,Category,var_type,dim1,dim2,dim3,dim4,Description, -lon,longitude,degrees_east,Longitude,Dimension,real,NA,NA,NA,NA,longitude at center of each grid cell, -lat,latitude,degrees_north,Latitude,Dimension,real,NA,NA,NA,NA,latitude at center of each grid cell, -depth,depth,m,Depth,Dimension,real,NA,NA,NA,NA,depth to bottom of soil layer, -pft,pft,(-),Plant Functional Type,Dimension,character,NA,NA,NA,NA,Name of each plant function type or species included in the model, -time,time,days since [year]-01-01 00:00:00 UTC,Time middle averaging period,Dimension,double,NA,NA,NA,NA,julian days days since [year]-01-01 00:00:00 UTC for middle of time averaging period Proleptic_Gregorian calendar, -rtsize,rtsize,m,Root Size Class,Dimension,real,NA,NA,NA,NA,Minimum threshold of root size class, -wdsize,wdsize,m,Woody Debris Size Class,Dimension,real,NA,NA,NA,NA,Minimum threshold of woody debris size class, -lon_bnds,NA,degrees_east,Longitude west-east bounds,Deprecated,real,nbnds,lon,NA,NA,"(west boundary of grid cell, east boundary of grid cell)", -lat_bnds,NA,degrees_north,Latitude south-north bounds,Deprecated,real,nbnds,lat,NA,NA,"(south boundary of grid cell, north boundary of grid cell)", -time_bnds,NA,days since 1700-01-01 00:00:00 UTC,Time beginning-end bounds,Deprecated,double,nbnds,time,NA,NA,"(julian days days since 1700-01-01 beginning time ave period, julian days days since 1700-01-01 end time ave period)", -time_bounds,time_bounds,days since [year]-01-01 00:00:00 UTC,history time interval endpoints,Attribute,double,time,hist_interval,NA,NA,"Start and end fractional DOY for each model averaging period (i.e. timepoint), starting from the base ""time"" start date used in the output netCDF file (e.g. days since 2000-01-01 00:00:00). E.g. 1, 1.25; 1.25, 1.5 ", -dec_date,NA,yr,Decimal date middle averaging period,Deprecated,double,time,NA,NA,NA,decimal date in fractional years for middle of time averaging period, -dec_date_bnds,NA,yr,Decimal date beginning-end bounds,Deprecated,double,nbnds,time,NA,NA,"(decimal date beginning time ave period, decimal date end time ave period)", -cal_date_mid,NA,"yr, mon, day, hr, min, sec",Calender date middle averaging period,Deprecated,integer,ncal,time,NA,NA,"calender date middle of time ave period: year, month, day, hour, minute, second for UTC time zone", -cal_date_beg,NA,"yr, mon, day, hr, min, sec",Calender date beginning averaging period,Deprecated,integer,ncal,time,NA,NA,"calender date beginning of time ave period: year, month, day, hour, minute, second for UTC time zone", -cal_date_end,NA,"yr, mon, day, hr, min, sec",Calender date end averaging period,Deprecated,integer,ncal,time,NA,NA,"calender date end of time ave period: year, month, day, hour, minute, second for UTC time zone", -GPP,NA,kg C m-2 s-1,Gross Primary Productivity,Carbon Fluxes,real,lon,lat,time,NA,Rate of photosynthesis (always positive), -NEE,NA,kg C m-2 s-1,Net Ecosystem Exchange,Carbon Fluxes,real,lon,lat,time,NA,"Net Ecosystem Exchange (NEE=HeteroResp+AutoResp-GPP, positive into atmosphere)", -TotalResp,NA,kg C m-2 s-1,Total Respiration,Carbon Fluxes,real,lon,lat,time,NA,"Total respiration (TotalResp=AutoResp+heteroResp, always positive)", -AutoResp,plant_respiration_carbon_flux,kg C m-2 s-1,Autotrophic Respiration,Carbon Fluxes,real,lon,lat,time,NA,Autotrophic respiration rate (always positive), -HeteroResp,heterotrophic_respiration_carbon_flux,kg C m-2 s-1,Heterotrophic Respiration,Carbon Fluxes,real,lon,lat,time,NA,Heterotrophic respiration rate (always positive), -SoilResp,soil_respiration_carbon_flux,kg C m-2 s-1,Soil Respiration,Carbon Fluxes,real,lon,lat,time,NA,Sum of respiration in the soil by heterotrophs and by the roots of plants (autotrophs), -CH4_flux,surface_upward_mass_flux_of_methane_expressed_as_carbon,kg C m-2 s-1,Methane Flux,Carbon Fluxes,real,lon,lat,time,NA,Net methane flux between ecosystem and atmosphere (positive into atmosphere), -N2O_flux,surface_upward_mass_flux_of_nitrous_oxide_expressed_as_nitrogen,kg N m-2 s-1,Nitrous Oxide Flux,Nitrogen Fluxes,real,lon,lat,time,NA,Net nitrous oxide flux between ecosystem and atmosphere (positive into atmosphere), -DOC_flux,NA,kg C m-2 s-1,Dissolved Organic Carbon flux,Carbon Fluxes,real,lon,lat,time,NA,Loss of organic carbon dissolved in ground water or rivers (positive out of grid cell), -Fire_flux,NA,kg C m-2 s-1,Fire emissions,Carbon Fluxes,real,lon,lat,time,NA,Flux of carbon due to fires (always positive), -litter_carbon_flux,litter_carbon_flux,kg C m-2 s-1,Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,NA,"Total carbon flux of litter, excluding coarse woody debris", -surface_litter_carbon_flux,surface_litter_carbon_flux,kg C m-2 s-1,Surface Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,NA,Total carbon flux of surface litter, -subsurface_litter_carbon_flux,subsurface_litter_carbon_flux,kg C m-2 s-1,Subsurface Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,depth,Total carbon flux of subsurface litter, -leaf_litter_carbon_flux,leaf_litter_carbon_flux,kg C m-2 s-1,Leaf Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,NA,Carbon flux of leaf litter, -WoodyLitter,wood_litter_carbon_flux,kg C m-2 s-1,Wood Litter Carbon Flux,Deprecated,real,lon,lat,time,NA,DALEC output; haven't yet resolved standard woody litter flux, -wood_debris_carbon_flux,wood_debris_carbon_flux,kg C m-2 s-1,Wood Debris Carbon Flux,Carbon Fluxes,real,lon,lat,time,wdsize,"Total carbon flux of woody debris, including downed woody debris and standing deadwood; excludes litter; size class defined by wdsize dimension", -NPP,NA,kg C m-2 s-1,Net Primary Productivity,Carbon Fluxes,real,lon,lat,time,NA,"Net Primary Productivity (NPP=GPP-AutoResp, positive into plants)", -GWBI,NA,kg C m-2 month-1,Gross Woody Biomass Increment,Carbon Fluxes,real,lon,lat,time,NA,Variable most analogous to tree-ring-derived change in stem biomass (before mortality/CWD flux), -CWDI,NA,kg C m-2 month-1,Coarse Woody Debris Increment,Carbon Fluxes,real,lon,lat,time,NA,Variable most analogous to flux of woody material material to the detrital pool resulting from mortality, -CropYield,NA,kg m-2,CropYield,Carbon Fluxes,real,lon,lat,time,pft,Crop yield; ED2 output variable, -poolname,NA,(-),Name of each Carbon Pool,Deprecated,character,nchar,npool,NA,NA,"Name of each carbon pool (i.e., wood or Coarse Woody Debris)", -CarbPools,NA,kg C m-2,Size of each carbon pool,Deprecated,real,lon,lat,npool,time,Total size of each carbon pool vertically integrated over the entire soil column, -TotLivBiom,NA,kg C m-2,Total living biomass,Carbon Pools,real,lon,lat,time,NA,Total carbon content of the living biomass (leaves+roots+wood), -AGB,NA,kg C m-2,Total aboveground biomass,Carbon Pools,real,lon,lat,time,NA,aboveground biomass, -LAI,NA,m2 m-2,Leaf Area Index,Carbon Pools,real,lon,lat,time,NA,Area of leaves per area ground, -leaf_carbon_content,leaf_carbon_content,kg C m-2,Leaf Carbon Content,Carbon Pools,real,lon,lat,time,NA,Leaf carbon content, +Variable.Name,standard_name,Units,Long.name,Category,var_type,dim1,dim2,dim3,dim4,Description +lon,longitude,degrees_east,Longitude,Dimension,real,NA,NA,NA,NA,longitude at center of each grid cell +lat,latitude,degrees_north,Latitude,Dimension,real,NA,NA,NA,NA,latitude at center of each grid cell +depth,depth,m,Depth,Dimension,real,NA,NA,NA,NA,depth to bottom of soil layer +pft,pft,(-),Plant Functional Type,Dimension,character,NA,NA,NA,NA,Name of each plant function type or species included in the model +time,time,days since [year]-01-01 00:00:00 UTC,Time middle averaging period,Dimension,double,NA,NA,NA,NA,julian days days since [year]-01-01 00:00:00 UTC for middle of time averaging period Proleptic_Gregorian calendar +rtsize,rtsize,m,Root Size Class,Dimension,real,NA,NA,NA,NA,Minimum threshold of root size class +wdsize,wdsize,m,Woody Debris Size Class,Dimension,real,NA,NA,NA,NA,Minimum threshold of woody debris size class +lon_bnds,NA,degrees_east,Longitude west-east bounds,Deprecated,real,nbnds,lon,NA,NA,"(west boundary of grid cell, east boundary of grid cell)" +lat_bnds,NA,degrees_north,Latitude south-north bounds,Deprecated,real,nbnds,lat,NA,NA,"(south boundary of grid cell, north boundary of grid cell)" +time_bnds,NA,days since 1700-01-01 00:00:00 UTC,Time beginning-end bounds,Deprecated,double,nbnds,time,NA,NA,"(julian days days since 1700-01-01 beginning time ave period, julian days days since 1700-01-01 end time ave period)" +time_bounds,time_bounds,days since [year]-01-01 00:00:00 UTC,history time interval endpoints,Attribute,double,time,hist_interval,NA,NA,"Start and end fractional DOY for each model averaging period (i.e. timepoint), starting from the base ""time"" start date used in the output netCDF file (e.g. days since 2000-01-01 00:00:00). E.g. 1, 1.25; 1.25, 1.5 " +dec_date,NA,yr,Decimal date middle averaging period,Deprecated,double,time,NA,NA,NA,decimal date in fractional years for middle of time averaging period +dec_date_bnds,NA,yr,Decimal date beginning-end bounds,Deprecated,double,nbnds,time,NA,NA,"(decimal date beginning time ave period, decimal date end time ave period)" +cal_date_mid,NA,"yr, mon, day, hr, min, sec",Calender date middle averaging period,Deprecated,integer,ncal,time,NA,NA,"calender date middle of time ave period: year, month, day, hour, minute, second for UTC time zone" +cal_date_beg,NA,"yr, mon, day, hr, min, sec",Calender date beginning averaging period,Deprecated,integer,ncal,time,NA,NA,"calender date beginning of time ave period: year, month, day, hour, minute, second for UTC time zone" +cal_date_end,NA,"yr, mon, day, hr, min, sec",Calender date end averaging period,Deprecated,integer,ncal,time,NA,NA,"calender date end of time ave period: year, month, day, hour, minute, second for UTC time zone" +GPP,NA,kg C m-2 s-1,Gross Primary Productivity,Carbon Fluxes,real,lon,lat,time,NA,Rate of photosynthesis (always positive) +NEE,NA,kg C m-2 s-1,Net Ecosystem Exchange,Carbon Fluxes,real,lon,lat,time,NA,"Net Ecosystem Exchange (NEE=HeteroResp+AutoResp-GPP, positive into atmosphere)" +TotalResp,NA,kg C m-2 s-1,Total Respiration,Carbon Fluxes,real,lon,lat,time,NA,"Total respiration (TotalResp=AutoResp+heteroResp, always positive)" +AutoResp,plant_respiration_carbon_flux,kg C m-2 s-1,Autotrophic Respiration,Carbon Fluxes,real,lon,lat,time,NA,Autotrophic respiration rate (always positive) +HeteroResp,heterotrophic_respiration_carbon_flux,kg C m-2 s-1,Heterotrophic Respiration,Carbon Fluxes,real,lon,lat,time,NA,Heterotrophic respiration rate (always positive) +SoilResp,soil_respiration_carbon_flux,kg C m-2 s-1,Soil Respiration,Carbon Fluxes,real,lon,lat,time,NA,Sum of respiration in the soil by heterotrophs and by the roots of plants (autotrophs) +CH4_flux,surface_upward_mass_flux_of_methane_expressed_as_carbon,kg C m-2 s-1,Methane Flux,Carbon Fluxes,real,lon,lat,time,NA,Net methane flux between ecosystem and atmosphere (positive into atmosphere) +N2O_flux,surface_upward_mass_flux_of_nitrous_oxide_expressed_as_nitrogen,kg N m-2 s-1,Nitrous Oxide Flux,Nitrogen Fluxes,real,lon,lat,time,NA,Net nitrous oxide flux between ecosystem and atmosphere (positive into atmosphere) +DOC_flux,NA,kg C m-2 s-1,Dissolved Organic Carbon flux,Carbon Fluxes,real,lon,lat,time,NA,Loss of organic carbon dissolved in ground water or rivers (positive out of grid cell) +Fire_flux,NA,kg C m-2 s-1,Fire emissions,Carbon Fluxes,real,lon,lat,time,NA,Flux of carbon due to fires (always positive) +litter_carbon_flux,litter_carbon_flux,kg C m-2 s-1,Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,NA,"Total carbon flux of litter, excluding coarse woody debris" +surface_litter_carbon_flux,surface_litter_carbon_flux,kg C m-2 s-1,Surface Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,NA,Total carbon flux of surface litter +subsurface_litter_carbon_flux,subsurface_litter_carbon_flux,kg C m-2 s-1,Subsurface Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,depth,Total carbon flux of subsurface litter +leaf_litter_carbon_flux,leaf_litter_carbon_flux,kg C m-2 s-1,Leaf Litter Carbon Flux,Carbon Fluxes,real,lon,lat,time,NA,Carbon flux of leaf litter +WoodyLitter,wood_litter_carbon_flux,kg C m-2 s-1,Wood Litter Carbon Flux,Deprecated,real,lon,lat,time,NA,DALEC output; haven't yet resolved standard woody litter flux +wood_debris_carbon_flux,wood_debris_carbon_flux,kg C m-2 s-1,Wood Debris Carbon Flux,Carbon Fluxes,real,lon,lat,time,wdsize,"Total carbon flux of woody debris, including downed woody debris and standing deadwood; excludes litter; size class defined by wdsize dimension" +NPP,NA,kg C m-2 s-1,Net Primary Productivity,Carbon Fluxes,real,lon,lat,time,NA,"Net Primary Productivity (NPP=GPP-AutoResp, positive into plants)" +GWBI,NA,kg C m-2 month-1,Gross Woody Biomass Increment,Carbon Fluxes,real,lon,lat,time,NA,Variable most analogous to tree-ring-derived change in stem biomass (before mortality/CWD flux) +CWDI,NA,kg C m-2 month-1,Coarse Woody Debris Increment,Carbon Fluxes,real,lon,lat,time,NA,Variable most analogous to flux of woody material material to the detrital pool resulting from mortality +CropYield,NA,kg m-2,CropYield,Carbon Fluxes,real,lon,lat,time,pft,Crop yield; ED2 output variable +poolname,NA,(-),Name of each Carbon Pool,Deprecated,character,nchar,npool,NA,NA,"Name of each carbon pool (i.e., wood or Coarse Woody Debris)" +CarbPools,NA,kg C m-2,Size of each carbon pool,Deprecated,real,lon,lat,npool,time,Total size of each carbon pool vertically integrated over the entire soil column +TotLivBiom,NA,kg C m-2,Total living biomass,Carbon Pools,real,lon,lat,time,NA,Total carbon content of the living biomass (leaves+roots+wood) +AGB,NA,kg C m-2,Total aboveground biomass,Carbon Pools,real,lon,lat,time,NA,aboveground biomass +LAI,NA,m2 m-2,Leaf Area Index,Carbon Pools,real,lon,lat,time,NA,Area of leaves per area ground +leaf_carbon_content,leaf_carbon_content,kg C m-2,Leaf Carbon Content,Carbon Pools,real,lon,lat,time,NA,Leaf carbon content root_carbon_content,root_carbon_content_of_size_class,kg C m-2,Root Carbon Content,Carbon Pools,real,lon,lat,time,rtsize," -Root carbon content, optionally by size class; alternatively specify fine_ and coarse_root_carbon_content", -fine_root_carbon_content,fine_root_carbon_content,kg C m-2,Fine Root Carbon Content,Carbon Pools,real,lon,lat,time,depth,Carbon content of fine roots (2 mm and smaller); alternative to providing dimensions for root_carbon_content, -coarse_root_carbon_content,coarse_root_carbon_content,kg C m-2,Coarse Root Carbon Content,Carbon Pools,real,lon,lat,time,depth,Carbon content of coarse roots (larger than 2 mm); alternative to providing dimensions for root_carbon_content, -wood_carbon_content,wood_carbon_content,kg C m-2,Wood Carbon Content,Carbon Pools,real,lon,lat,time,NA,"Wood carbon content including above (AbvGrndWood) and below ground (coarse roots, shared with root_carbon_content)", -AbvGrndWood,NA,kg C m-2,Above ground woody biomass,Carbon Pools,real,lon,lat,time,NA,Total above ground wood biomass, -TotSoilCarb,NA,kg C m-2,Total Soil Carbon,Carbon Pools,real,lon,lat,time,NA,Total soil and litter carbon content vertically integrated over the enire soil column, -litter_carbon_content,litter_carbon_content,kg C m-2,Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,"Total carbon content of litter pool, excluding coarse woody debris", -surface_litter_carbon_content,surface_litter_carbon_content,kg C m-2,Surface Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,Carbon content of surface litter pool, -subsurface_litter_carbon_content,subsurface_litter_carbon_content,kg C m-2,Subsurface Litter Carbon Content,Carbon Pools,real,lon,lat,time,depth,Carbon content of subsurface litter pool; depth dimension optional, -leaf_litter_carbon_content,leaf_litter_carbon_content,kg C m-2,Leaf Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,Carbon content of leaf litter pool, -reproductive_litter_carbon_content,reproductive_litter_carbon_content,kg C m-2,Reproductive Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,"Carbon content of reproductive litter pool (e.g. seeds, flowers, cones, pollen)", -other_litter_carbon_content,other_litter_carbon_content,kg C m-2,Other Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,Carbon content of uncategorized litter pool (e.g. insect excreta), -wood_debris_carbon_content,wood_debris_carbon_content,kg C m-2,Wood Debris Carbon Content,Carbon Pools,real,lon,lat,time,wdsize,Carbon content of downed woody debris and standing deadwood; excludes litter; size classes defined by wdsize dimension, -soil_carbon_content,soil_carbon_content_of_soil_layer,kg C m-2,Soil Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,"Total carbon content of soil layer, excluding litter", -soil_inorganic_carbon_content,soil_inorganic_carbon_content_of_soil_layer,kg C m-2,Soil Inorganic Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Total inorganic carbon content of soil layer (mineralized carbon such as carbonate), -soil_organic_carbon_content,soil_organic_carbon_content_of_soil_layer,kg C m-2,Soil Organic Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,"Total organic carbon content of soil layer, excluding litter", -slow_soil_pool_carbon_content,slow_soil_pool_carbon_content_of_soil_layer,kg C m-2,Slow Soil Pool Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Slow soil pool carbon content of soil layer, -fast_soil_pool_carbon_content,fast_soil_pool_carbon_content_of_soil_layer,kg C m-2,Fast Soil Pool Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Fast soil pool carbon content of soil layer, -structural_soil_pool_carbon_content,structural_soil_pool_carbon_content_of_soil_layer,kg C m-2,Structural Soil Pool Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Structural soil pool carbon content of soil layer, -soil_nitrogen_content,soil_nitrogen_content_of_soil_layer,kg N m-2,Soil Nitrogen Content by Layer,Nitrogen Pools,real,lon,lat,time,depth,Total nitrogen content of soil layer, -soil_inorganic_nitrogen_content,soil_inorganic_nitrogen_content_of_soil_layer,kg N m-2,Soil Inorganic Nitrogen Content by Layer,Nitrogen Pools,real,lon,lat,time,depth,Total inorganic nitrogen content of soil layer (mineralized nitrogen), -soil_organic_nitrogen_content,soil_organic_nitrogen_content_of_soil_layer,kg N m-2,Soil Organic Nitrogen Content by Layer,Nitrogen Pools,real,lon,lat,time,depth,"Total organic nitrogen content of soil layer, excluding litter", -soil_phosphorus_content,soil_phosphorus_content_of_soil_layer,kg P m-2,Soil Phosphorus Content by Layer,Phosphorus Pools,real,lon,lat,time,depth,Total phosphorus content of soil layer, -Qh,NA,W m-2,Sensible heat,Energy Fluxes,real,lon,lat,time,NA,Sensible heat flux into the boundary layer (positive into atmosphere), -Qle,NA,W m-2,Latent heat,Energy Fluxes,real,lon,lat,time,NA,Latent heat flux into the boundary layer (positive into atmosphere), -Qg,NA,W m-2,Ground heat,Energy Fluxes,real,lon,lat,time,NA,Ground heat flux; ED2 output variable, -stomatal_conductance,NA,kg m-2 s-1,Stomatal Conductance,Energy Fluxes,real,lon,lat,time,NA,Rate of leaf conductance of water vapor from the leaf sub-stomatal cavities to the atmosphere, -Evap,NA,kg m-2 s-1,Total Evaporation,Energy Fluxes,real,lon,lat,time,NA,Sum of all evaporation sources (positive into atmosphere), -TVeg,NA,kg m-2 s-1,Transpiration,Deprecated,real,lon,lat,time,NA,"Deprecated, to be replaced by Transp. Total Plant transpiration (always positive)", -Transp,NA,kg m-2 s-1,Total transpiration,Energy Fluxes,real,lon,lat,time,pft,Total transpiration of each PFT within each grid cell, -LW_albedo,NA,(-),Longwave Albedo,Energy Fluxes,real,lon,lat,time,NA,Longwave Albedo, -SW_albedo,NA,(-),Shortwave Albedo,Energy Fluxes,real,lon,lat,time,NA,Shortwave albedo, -Lwnet,NA,W m-2,Net Longwave Radiation,Energy Fluxes,real,lon,lat,time,NA,Incident longwave radiation minus simulated outgoing longwave radiation (positive into grnd), -SWnet,NA,W m-2,Net shortwave radiation,Energy Fluxes,real,lon,lat,time,NA,Incident shortwave radiation minus simulated outgoing shortwave radiation (positive into grnd), -fPAR,NA,(-),Absorbed fraction incoming PAR,Energy Fluxes,real,lon,lat,time,NA,absorbed fraction incoming photosyntetically active radiation, -z_top,NA,m,Soil Layer Top Depth,Deprecated,real,depth,NA,NA,NA,Depth from soil surface to top of soil layer, -z_node,NA,m,Soil Layer Node Depth,Deprecated,real,depth,NA,NA,NA,"Depth from soil surface to layer prognostic variables, typically center of soil layer", -z_bottom,NA,m,Soil Layer Bottom Depth,Deprecated,real,depth,NA,NA,NA,Depth from soil surface to bottom of soil layer, -SoilMoist,NA,kg m-2,Average Layer Soil Moisture,Physical Variables,real,lon,lat,depth,time,"Soil water content in each soil layer, including liquid, vapor and ice", -SoilMoistFrac,volume_fraction_of_condensed_water_in_soil,1,Average Layer Fraction of Saturation,Physical Variables,real,lon,lat,depth,time,"Fraction of saturation of soil water in each soil layer, including liquid and ice", -SoilWet,NA,(-),Total Soil Wetness,Physical Variables,real,lon,lat,time,NA,Vertically integrated soil moisture divided by maximum allowable soil moisture above wilting point, -Qs,NA,kg m-2 s-1,Surface runoff,Physical Variables,real,lon,lat,time,NA,Runoff from the landsurface and/or subsurface stormflow, -Qsb,NA,kg m-2 s-1,Subsurface runoff,Physical Variables,real,lon,lat,time,NA,Gravity soil water drainage and/or soil water lateral flow, -SoilTemp,soil_temperature,K,Average Layer Soil Temperature,Physical Variables,real,lon,lat,depth,time,Average soil temperature in each soil layer, -Tdepth,NA,m,Active Layer Thickness,Physical Variables,real,lon,lat,time,NA,Thaw depth to zero centigrade isotherm in permafrost, -Fdepth,NA,m,Frozen Thickness,Physical Variables,real,lon,lat,time,NA,Freeze depth to zero centigrade isotherm in non-permafrost, -Tcan,NA,K,Canopy Temperature,Physical Variables,real,lon,lat,time,NA,Canopy or vegetation temperature (or temperature used in photosynthesis calculations), -SWE,NA,kg m-2,Snow Water Equivalent,Physical Variables,real,lon,lat,time,NA,"Total water mass of snow pack, including ice and liquid water", -SnowDen,NA,kg m-3,Bulk Snow Density,Physical Variables,real,lon,lat,time,NA,"Overall bulk density of the snow pack, including ice and liquid water", -SnowDepth,NA,m,Total snow depth,Physical Variables,real,lon,lat,time,NA,Total snow depth, -CO2CAS,NA,ppmv,CO2CAS,Physical Variables,real,lon,lat,time,NA,CO2 in canopy air space; ED2 output variable, -CO2air,NA,micromol mol-1,Near surface CO2 concentration,Driver,real,lon,lat,time,NA,Near surface dry air CO2 mole fraction expressed as ppmv (umol / mol), -CO2air_mf,mole_fraction_of_carbon_dioxide_in_air,1,Near-surface CO2 mole fraction (CF-compliant),Driver,real,lon,lat,time,NA,Mole fraction of CO2 in air near the surface; dimensionless (mol/mol)., -LWdown,surface_downwelling_longwave_flux_in_air,W m-2,Surface incident longwave radiation,Driver,real,lon,lat,time,NA,Surface incident longwave radiation, -Psurf,air_pressure,Pa,Surface pressure,Driver,real,lon,lat,time,NA,Surface pressure, -Qair,specific_humidity,kg kg-1,Near surface specific humidity,Driver,real,lon,lat,time,NA,Near surface specific humidity, -Rainf,precipitation_flux,kg m-2 s-1,Rainfall rate,Driver,real,lon,lat,time,NA,Rainfall rate, -SWdown,surface_downwelling_shortwave_flux_in_air,W m-2,Surface incident shortwave radiation,Driver,real,lon,lat,time,NA,Surface incident shortwave radiation, -Tair,air_temperature,K,Near surface air temperature,Driver,real,lon,lat,time,NA,Near surface air temperature, -Wind,wind_speed,m s-1,Near surface module of the wind,Driver,real,lon,lat,time,NA,Near surface wind magnitude, -Tmin,air_temperature_max,K,Daily Maximum Temperature,Driver,real,lon,lat,time,NA,Daily Maximum Temperature, -Tmax,air_temperature_min,K,Daily Minimum Temperature,Driver,real,lon,lat,time,NA,Daily Minimum Temperature, -Uwind,northward_wind,m s-1,Northward Component of Wind,Driver,real,lon,lat,time,NA,Northward Component of Wind, -Vwind,eastward_wind,m s-1,Eastward Component of Wind,Driver,real,lon,lat,time,NA,Eastward Component of Wind, -RH,relative_humidity,%,Relative Humidity,Driver,real,lon,lat,time,NA,Relative Humidity, -PAR,surface_downwelling_photosynthetic_photon_flux_in_air,mol m-2 s-1,Photosynthetically Active Radiation,Driver,real,lon,lat,time,NA,Photosynthetically Active Radiation, -precipf,NA,kg m-2 s-1,Precipitation,Driver,real,lon,lat,time,NA,"The per unit area and time precipitation representing the sum of convective rainfall, stratiform rainfall, and snowfall", -BA,NA,m2 ha-1,Basal area,Diversity,real,lon,lat,time,pft,Basal area by PFT, -Dens,NA,1 ha-1,Stem Density,Diversity,real,lon,lat,time,pft,Stem Density by PFT, -DBH,NA,cm,Diameter at Breast Height,Diversity,real,lon,lat,time,pft,DBH by PFT, -Fcomp,NA,kgC kgC-1,Aboveground Biomass Fractional Composition,Diversity,real,lon,lat,time,pft,Aboveground biomass Fractional composition of each PFT within each grid cell, -Estab,NA,1 ha-1,New Individuals,Diversity,real,lon,lat,time,pft,New Individuals, -Mort,NA,1 ha-1,Mortality,Diversity,real,lon,lat,time,pft,Individuals lost through death, -SoilDepth,NA,m,Soil Depth Layer,Deprecated,real,depth,NA,NA,NA,Depth to the bottom of each model-defined soil layer, -assimilation_rate,NA,kg C m-2 s-1,Leaf assimilation rate,Carbon Fluxes,real,lon,lat,time,NA,Rate of leaf photosynthesis / carbon assimilation, -date_of_budburst,NA,day of year,Date of Budburst,Phenology,real,lon,lat,time,NA,Date of Budburst, -date_of_senescence,NA,day of year,Date of Senescence,Phenology,real,lon,lat,time,NA,Date of Senescence, -litter_mass_content_of_water,NA,kg m-2,Average layer litter moisture,Physical Variables,real,lon,lat,depth,time,Litter water content in litter layer including liquid vapor and ice, +Root carbon content, optionally by size class; alternatively specify fine_ and coarse_root_carbon_content" +fine_root_carbon_content,fine_root_carbon_content,kg C m-2,Fine Root Carbon Content,Carbon Pools,real,lon,lat,time,depth,Carbon content of fine roots (2 mm and smaller); alternative to providing dimensions for root_carbon_content +coarse_root_carbon_content,coarse_root_carbon_content,kg C m-2,Coarse Root Carbon Content,Carbon Pools,real,lon,lat,time,depth,Carbon content of coarse roots (larger than 2 mm); alternative to providing dimensions for root_carbon_content +wood_carbon_content,wood_carbon_content,kg C m-2,Wood Carbon Content,Carbon Pools,real,lon,lat,time,NA,"Wood carbon content including above (AbvGrndWood) and below ground (coarse roots, shared with root_carbon_content)" +AbvGrndWood,NA,kg C m-2,Above ground woody biomass,Carbon Pools,real,lon,lat,time,NA,Total above ground wood biomass +TotSoilCarb,NA,kg C m-2,Total Soil Carbon,Carbon Pools,real,lon,lat,time,NA,Total soil and litter carbon content vertically integrated over the enire soil column +litter_carbon_content,litter_carbon_content,kg C m-2,Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,"Total carbon content of litter pool, excluding coarse woody debris" +surface_litter_carbon_content,surface_litter_carbon_content,kg C m-2,Surface Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,Carbon content of surface litter pool +subsurface_litter_carbon_content,subsurface_litter_carbon_content,kg C m-2,Subsurface Litter Carbon Content,Carbon Pools,real,lon,lat,time,depth,Carbon content of subsurface litter pool; depth dimension optional +leaf_litter_carbon_content,leaf_litter_carbon_content,kg C m-2,Leaf Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,Carbon content of leaf litter pool +reproductive_litter_carbon_content,reproductive_litter_carbon_content,kg C m-2,Reproductive Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,"Carbon content of reproductive litter pool (e.g. seeds, flowers, cones, pollen)" +other_litter_carbon_content,other_litter_carbon_content,kg C m-2,Other Litter Carbon Content,Carbon Pools,real,lon,lat,time,NA,Carbon content of uncategorized litter pool (e.g. insect excreta) +wood_debris_carbon_content,wood_debris_carbon_content,kg C m-2,Wood Debris Carbon Content,Carbon Pools,real,lon,lat,time,wdsize,Carbon content of downed woody debris and standing deadwood; excludes litter; size classes defined by wdsize dimension +soil_carbon_content,soil_carbon_content_of_soil_layer,kg C m-2,Soil Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,"Total carbon content of soil layer, excluding litter" +soil_inorganic_carbon_content,soil_inorganic_carbon_content_of_soil_layer,kg C m-2,Soil Inorganic Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Total inorganic carbon content of soil layer (mineralized carbon such as carbonate) +soil_organic_carbon_content,soil_organic_carbon_content_of_soil_layer,kg C m-2,Soil Organic Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,"Total organic carbon content of soil layer, excluding litter" +slow_soil_pool_carbon_content,slow_soil_pool_carbon_content_of_soil_layer,kg C m-2,Slow Soil Pool Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Slow soil pool carbon content of soil layer +fast_soil_pool_carbon_content,fast_soil_pool_carbon_content_of_soil_layer,kg C m-2,Fast Soil Pool Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Fast soil pool carbon content of soil layer +structural_soil_pool_carbon_content,structural_soil_pool_carbon_content_of_soil_layer,kg C m-2,Structural Soil Pool Carbon Content by Layer,Carbon Pools,real,lon,lat,time,depth,Structural soil pool carbon content of soil layer +soil_nitrogen_content,soil_nitrogen_content_of_soil_layer,kg N m-2,Soil Nitrogen Content by Layer,Nitrogen Pools,real,lon,lat,time,depth,Total nitrogen content of soil layer +soil_inorganic_nitrogen_content,soil_inorganic_nitrogen_content_of_soil_layer,kg N m-2,Soil Inorganic Nitrogen Content by Layer,Nitrogen Pools,real,lon,lat,time,depth,Total inorganic nitrogen content of soil layer (mineralized nitrogen) +soil_organic_nitrogen_content,soil_organic_nitrogen_content_of_soil_layer,kg N m-2,Soil Organic Nitrogen Content by Layer,Nitrogen Pools,real,lon,lat,time,depth,"Total organic nitrogen content of soil layer, excluding litter" +soil_phosphorus_content,soil_phosphorus_content_of_soil_layer,kg P m-2,Soil Phosphorus Content by Layer,Phosphorus Pools,real,lon,lat,time,depth,Total phosphorus content of soil layer +Qh,NA,W m-2,Sensible heat,Energy Fluxes,real,lon,lat,time,NA,Sensible heat flux into the boundary layer (positive into atmosphere) +Qle,NA,W m-2,Latent heat,Energy Fluxes,real,lon,lat,time,NA,Latent heat flux into the boundary layer (positive into atmosphere) +Qg,NA,W m-2,Ground heat,Energy Fluxes,real,lon,lat,time,NA,Ground heat flux; ED2 output variable +stomatal_conductance,NA,kg m-2 s-1,Stomatal Conductance,Energy Fluxes,real,lon,lat,time,NA,Rate of leaf conductance of water vapor from the leaf sub-stomatal cavities to the atmosphere +Evap,NA,kg m-2 s-1,Total Evaporation,Energy Fluxes,real,lon,lat,time,NA,Sum of all evaporation sources (positive into atmosphere) +TVeg,NA,kg m-2 s-1,Transpiration,Deprecated,real,lon,lat,time,NA,"Deprecated, to be replaced by Transp. Total Plant transpiration (always positive)" +Transp,NA,kg m-2 s-1,Total transpiration,Energy Fluxes,real,lon,lat,time,pft,Total transpiration of each PFT within each grid cell +LW_albedo,NA,(-),Longwave Albedo,Energy Fluxes,real,lon,lat,time,NA,Longwave Albedo +SW_albedo,NA,(-),Shortwave Albedo,Energy Fluxes,real,lon,lat,time,NA,Shortwave albedo +Lwnet,NA,W m-2,Net Longwave Radiation,Energy Fluxes,real,lon,lat,time,NA,Incident longwave radiation minus simulated outgoing longwave radiation (positive into grnd) +SWnet,NA,W m-2,Net shortwave radiation,Energy Fluxes,real,lon,lat,time,NA,Incident shortwave radiation minus simulated outgoing shortwave radiation (positive into grnd) +fPAR,NA,(-),Absorbed fraction incoming PAR,Energy Fluxes,real,lon,lat,time,NA,absorbed fraction incoming photosyntetically active radiation +z_top,NA,m,Soil Layer Top Depth,Deprecated,real,depth,NA,NA,NA,Depth from soil surface to top of soil layer +z_node,NA,m,Soil Layer Node Depth,Deprecated,real,depth,NA,NA,NA,"Depth from soil surface to layer prognostic variables, typically center of soil layer" +z_bottom,NA,m,Soil Layer Bottom Depth,Deprecated,real,depth,NA,NA,NA,Depth from soil surface to bottom of soil layer +SoilMoist,NA,kg m-2,Average Layer Soil Moisture,Physical Variables,real,lon,lat,depth,time,"Soil water content in each soil layer, including liquid, vapor and ice" +SoilMoistFrac,volume_fraction_of_condensed_water_in_soil,1,Average Layer Fraction of Saturation,Physical Variables,real,lon,lat,depth,time,"Fraction of saturation of soil water in each soil layer, including liquid and ice" +SoilWet,NA,(-),Total Soil Wetness,Physical Variables,real,lon,lat,time,NA,Vertically integrated soil moisture divided by maximum allowable soil moisture above wilting point +Qs,NA,kg m-2 s-1,Surface runoff,Physical Variables,real,lon,lat,time,NA,Runoff from the landsurface and/or subsurface stormflow +Qsb,NA,kg m-2 s-1,Subsurface runoff,Physical Variables,real,lon,lat,time,NA,Gravity soil water drainage and/or soil water lateral flow +SoilTemp,soil_temperature,K,Average Layer Soil Temperature,Physical Variables,real,lon,lat,depth,time,Average soil temperature in each soil layer +Tdepth,NA,m,Active Layer Thickness,Physical Variables,real,lon,lat,time,NA,Thaw depth to zero centigrade isotherm in permafrost +Fdepth,NA,m,Frozen Thickness,Physical Variables,real,lon,lat,time,NA,Freeze depth to zero centigrade isotherm in non-permafrost +Tcan,NA,K,Canopy Temperature,Physical Variables,real,lon,lat,time,NA,Canopy or vegetation temperature (or temperature used in photosynthesis calculations) +SWE,NA,kg m-2,Snow Water Equivalent,Physical Variables,real,lon,lat,time,NA,"Total water mass of snow pack, including ice and liquid water" +SnowDen,NA,kg m-3,Bulk Snow Density,Physical Variables,real,lon,lat,time,NA,"Overall bulk density of the snow pack, including ice and liquid water" +SnowDepth,NA,m,Total snow depth,Physical Variables,real,lon,lat,time,NA,Total snow depth +CO2CAS,NA,ppmv,CO2CAS,Physical Variables,real,lon,lat,time,NA,CO2 in canopy air space; ED2 output variable +CO2air,NA,micromol mol-1,Near surface CO2 concentration,Driver,real,lon,lat,time,NA,Near surface dry air CO2 mole fraction expressed as ppmv (umol / mol) +CO2air_mf,mole_fraction_of_carbon_dioxide_in_air,1,Near-surface CO2 mole fraction (CF-compliant),Driver,real,lon,lat,time,NA,Mole fraction of CO2 in air near the surface; dimensionless (mol/mol). +LWdown,surface_downwelling_longwave_flux_in_air,W m-2,Surface incident longwave radiation,Driver,real,lon,lat,time,NA,Surface incident longwave radiation +Psurf,air_pressure,Pa,Surface pressure,Driver,real,lon,lat,time,NA,Surface pressure +Qair,specific_humidity,kg kg-1,Near surface specific humidity,Driver,real,lon,lat,time,NA,Near surface specific humidity +Rainf,precipitation_flux,kg m-2 s-1,Rainfall rate,Driver,real,lon,lat,time,NA,Rainfall rate +SWdown,surface_downwelling_shortwave_flux_in_air,W m-2,Surface incident shortwave radiation,Driver,real,lon,lat,time,NA,Surface incident shortwave radiation +Tair,air_temperature,K,Near surface air temperature,Driver,real,lon,lat,time,NA,Near surface air temperature +Wind,wind_speed,m s-1,Near surface module of the wind,Driver,real,lon,lat,time,NA,Near surface wind magnitude +Tmin,air_temperature_max,K,Daily Maximum Temperature,Driver,real,lon,lat,time,NA,Daily Maximum Temperature +Tmax,air_temperature_min,K,Daily Minimum Temperature,Driver,real,lon,lat,time,NA,Daily Minimum Temperature +Uwind,northward_wind,m s-1,Northward Component of Wind,Driver,real,lon,lat,time,NA,Northward Component of Wind +Vwind,eastward_wind,m s-1,Eastward Component of Wind,Driver,real,lon,lat,time,NA,Eastward Component of Wind +RH,relative_humidity,%,Relative Humidity,Driver,real,lon,lat,time,NA,Relative Humidity +PAR,surface_downwelling_photosynthetic_photon_flux_in_air,mol m-2 s-1,Photosynthetically Active Radiation,Driver,real,lon,lat,time,NA,Photosynthetically Active Radiation +precipf,NA,kg m-2 s-1,Precipitation,Driver,real,lon,lat,time,NA,"The per unit area and time precipitation representing the sum of convective rainfall, stratiform rainfall, and snowfall" +BA,NA,m2 ha-1,Basal area,Diversity,real,lon,lat,time,pft,Basal area by PFT +Dens,NA,1 ha-1,Stem Density,Diversity,real,lon,lat,time,pft,Stem Density by PFT +DBH,NA,cm,Diameter at Breast Height,Diversity,real,lon,lat,time,pft,DBH by PFT +Fcomp,NA,kgC kgC-1,Aboveground Biomass Fractional Composition,Diversity,real,lon,lat,time,pft,Aboveground biomass Fractional composition of each PFT within each grid cell +Estab,NA,1 ha-1,New Individuals,Diversity,real,lon,lat,time,pft,New Individuals +Mort,NA,1 ha-1,Mortality,Diversity,real,lon,lat,time,pft,Individuals lost through death +SoilDepth,NA,m,Soil Depth Layer,Deprecated,real,depth,NA,NA,NA,Depth to the bottom of each model-defined soil layer +assimilation_rate,NA,kg C m-2 s-1,Leaf assimilation rate,Carbon Fluxes,real,lon,lat,time,NA,Rate of leaf photosynthesis / carbon assimilation +date_of_budburst,NA,day of year,Date of Budburst,Phenology,real,lon,lat,time,NA,Date of Budburst +date_of_senescence,NA,day of year,Date of Senescence,Phenology,real,lon,lat,time,NA,Date of Senescence +litter_mass_content_of_water,NA,kg m-2,Average layer litter moisture,Physical Variables,real,lon,lat,depth,time,Litter water content in litter layer including liquid vapor and ice +year,NA,year,Year,Dimension,real,NA,NA,NA,Na,Year number (CE) \ No newline at end of file diff --git a/models/peprmt/R/helpers.R b/models/peprmt/R/helpers.R new file mode 100644 index 00000000000..8f0c800f52c --- /dev/null +++ b/models/peprmt/R/helpers.R @@ -0,0 +1,43 @@ +# setEnsemblePaths leaves all path components other than siteid +# identical across sites. This is an issue for our dataset, because +# each site has a different location and date range. +# To use site-specific grid id, we need to string-replace each siteid + +#' Set grid cell names (not exported) +#' +#' @param s settings object +#' +#' @returns updated settings with met paths including grid cell +#' @export +#' +#' @examples +id2grid <- function(s) { + # replacing in place to preserve names + for (p in seq_along(s$run$inputs$met$path)) { + s$run$inputs$met$path[[p]] <- gsub( + pattern = s$run$site$id, + replacement = s$run$site$ERA5_grid_cell, + x = s$run$inputs$met$path[[p]] + ) + } + s +} + +#' Set start and end dates (not exported) +#' +#' @param s settings object +#' +#' @returns updated settings object with met path including correct years +#' +#' @examples +dates2grid <- function(s) { + for (p in seq_along(s$run$inputs$met$path)) { + s$run$inputs$met$path[[p]] <- gsub( + pattern = "DATES-HERE", + replacement = paste0(s$run$site$met.start, ".", + s$run$site$met.end), + x = s$run$inputs$met$path[[p]] + ) + } + s +} \ No newline at end of file diff --git a/models/peprmt/demo_run/run_pecan_peprmt.qmd b/models/peprmt/demo_run/01_run_pecan_peprmt.qmd similarity index 80% rename from models/peprmt/demo_run/run_pecan_peprmt.qmd rename to models/peprmt/demo_run/01_run_pecan_peprmt.qmd index ca11758c115..f64375d7313 100644 --- a/models/peprmt/demo_run/run_pecan_peprmt.qmd +++ b/models/peprmt/demo_run/01_run_pecan_peprmt.qmd @@ -1,9 +1,9 @@ --- title: "Running PEPRMT Using PEcAn" author: - - "Abby Lewis" - "Aritra Dey" - "David LeBauer" + - "Abby Lewis" format: html: default pdf: default @@ -14,7 +14,7 @@ fig-height: 6 fig-dpi: 300 --- -# Introduction {#introduction} +# Introduction Welcome to this PEcAn workflow notebook! This notebook will guide you through running the PEPRMT model using PEcAn's programmatic interface. @@ -22,10 +22,10 @@ Welcome to this PEcAn workflow notebook! This notebook will guide you through ru PEcAn (Predictive Ecosystem Analyzer) is a scientific workflow system designed to make ecosystem modeling more transparent, repeatable, and accessible. It helps researchers: -- Run ecosystem models with standardized inputs and outputs -- Perform uncertainty analysis on model parameters -- Compare model predictions with observations -- Share and reproduce scientific workflows +- Run ecosystem models with standardized inputs and outputs +- Perform uncertainty analysis on model parameters +- Compare model predictions with observations +- Share and reproduce scientific workflows ## What This Notebook Does @@ -37,17 +37,17 @@ This notebook demonstrates how to: ### The Scenario Being Modeled: -We are modeling greenhouse gas dynamics (gross primary productivity, ecosystem respiration, and methane emissions) at five sites. The model configuration uses the PEPRMT-Tidal process-based ecosystem model (Oikawa et al. 2024). +We are modeling greenhouse gas dynamics (gross primary productivity, ecosystem respiration, and methane emissions) at five sites. The model configuration uses the PEPRMT-Tidal process-based ecosystem model (Oikawa et al. 2024). The simulation is run for the duration of data at each site, which ranges from 2011 to 2021. -This scenario is designed to be a minimal, reproducible example to demonstrate how to run PEPRMT within the PEcAn workflow. In later steps, this same framework can be extended to include more ensemble members, longer time periods, or alternative meteorological inputs. +This scenario is designed to be a minimal, reproducible example to demonstrate how to run PEPRMT within the PEcAn workflow. In later steps, this same framework can be extended to include more ensemble members, longer time periods, or alternative meteorological inputs (e.g., see `pecan/models/peprmt/demo_run/input_demo.qmd` and `pecan/models/peprmt/demo_run/event_demo.qmd`). ## Prerequisites Before running this notebook, make sure you have: -- All the PEcAn packages installed. You can install all PEcAn packages and their dependencies by running the following command in the root of your PEcAn repository. This chunk does not run automatically since it will overwrite a version of PEcAn you installed by other methods. Run it by hand when needed. +- All the PEcAn packages installed. You can install all PEcAn packages and their dependencies by running the following command in the root of your PEcAn repository. This chunk does not run automatically since it will overwrite a version of PEcAn you installed by other methods. Run it by hand when needed. ```{r, eval = FALSE} @@ -57,31 +57,28 @@ options(repos = c( CRAN = 'https://cloud.r-project.org')) # Download and install PEcAn.all in R install.packages(c('PEcAn.all', 'PEcAn.PEPRMT')) -``` -- Alternatively, install from GitHub. - -```{r, eval = FALSE} +# Alternatively, install from GitHub remotes::install_github("pecanproject/pecan", subdir = "base/all", ref = "develop", force = T) remotes::install_github("pecanproject/pecan", subdir = "models/peprmt", ref = "develop") ``` - -```{r} -#Set working directory -here::i_am("models/peprmt/demo_run/run_pecan_peprmt.qmd") -``` - - A valid `pecan.xml` configuration file or use the example provided: `pecan/models/peprmt/demo_run/settings.xml` ## How to Use This Notebook -1. Each section is clearly marked with a heading +1. Each section is marked with a heading 2. Code chunks are provided with explanations 3. You can run the code chunks sequentially 4. Once you have successfully run the demo, you can modify parameters to configure new runs and analyses +5. By default, the demo runs within `pecan/models/peprmt/demo_run/`. + +```{r} +#Set working directory +here::i_am("models/peprmt/demo_run/01_run_pecan_peprmt.qmd") +``` **Objective:** @@ -103,8 +100,14 @@ First, we need to load the PEcAn R packages. These packages provide all the func # Load the PEcAn.all package, which includes all necessary PEcAn functionality library("PEcAn.all") library("PEcAn.PEPRMT") -set.seed(20260326) + +# Set "seed" to make outputs reproducible +set.seed(20260326) + +# prints logger messages into the notebook instead of to the terminal logger.setUseConsole(console = TRUE, stderr = FALSE) +# prints messages with levels INFO or higher (WARNING, ERROR, SEVERE) +# For even more detail, change to "DEBUG" logger.setLevel("INFO") ``` @@ -126,8 +129,8 @@ settings_path <- here::here("models/peprmt/demo_run/settings_inputdemo.xml") After specifying the path to the `pecan.xml` file, the next step involves reading and preparing these settings. PEcAn provides utilities to process and validate the configurations before execution begins. -- `PEcAn.settings::read.settings(settings_path)`: Reads the `pecan.xml` file and converts it to an R list object. -- `PEcAn.settings::prepare.settings(settings)`: Prepares and validates settings. It sets defaults for missing fields, changes file paths to absolute paths, and generally ensures consistency. +- `PEcAn.settings::read.settings(settings_path)`: Reads the `pecan.xml` file and converts it to an R list object. +- `PEcAn.settings::prepare.settings(settings)`: Prepares and validates settings. It sets defaults for missing fields, changes file paths to absolute paths, and generally ensures consistency. ```{r read-prepare-settings} # Read the settings from the pecan.xml file @@ -141,7 +144,7 @@ settings <- PEcAn.settings::prepare.settings(settings) Once the settings have been read and prepared, it is useful to inspect the structure of the `settings` object. This object is an R list containing all parameters and configurations for the PEcAn workflow. -- `str(settings)` displays the internal structure of the `settings` object. This shows how the settings are represented in R and is useful for debugging and verifying settings. +- `str(settings)` displays the internal structure of the `settings` object. This shows how the settings are represented in R and is useful for debugging and verifying settings. ```{r explore-settings} str(settings) @@ -165,22 +168,20 @@ Editing the more interesting settings to change the PFT (`settings$pfts`) or ext The directory structure created by PEcAn for this demo run will look like this: -``` +``` demo_outdir/ # Root output directory ├── run/ # Configuration & execution metadata │ ├── runs.txt # List of run IDs (one per model realization) -│ ├── / # Model-specific config copies (sometimes) -│ └── config.* # Generated model configs (e.g., SIPNET) +│ ├── / # Model-specific configs, including run job and driver data +│ └── config.* # Generated model configs (not used for PEPRMT) ├── out/ # Raw model outputs by run ID -│ └── / # E.g., daily PEPRMT output files +│ └── / # E.g., PEPRMT output files ``` The root output directory is defined here as `demo_outdir/` by `settings$outdir`. This directory contains log and record files from the PEcAn workflow. They provide a detailed record of how data was generated and are key components of the analysis metadata and provenance. These can be useful for debugging as well as for downstream analysis. Key subdirectories include `run/` and `out/` that contain files used to configure and run the model, files generated by the underlying ecosystem model, and PEcAn standard outputs used in downstream analyses. These are described in subsequent sections. -Additional outputs include logs, a `STATUS` file that records the steps of the workflow along with timestamps and whether each step was successful, and a copy of the `pecan.*.xml` file. - # Write Model Configuration Files This step generates the model-specific configuration files and scripts that will be used to run the ecosystem model. The process involves generating PEPRMT configuration files using the `runModule.run.write.configs()` function. @@ -193,27 +194,25 @@ settings <- PEcAn.workflow::runModule.run.write.configs(settings) This section executes the actual model simulations and retrieves the results. The process is managed by PEcAn's workflow system, which handles the execution of your chosen ecosystem model. -- `runModule_start_model_runs(settings)`: This function initiates the model runs based on your configuration. It manages the execution of your chosen ecosystem model, using the configuration files generated in the previous step. +- `runModule_start_model_runs(settings)`: This function initiates the model runs based on your configuration. It manages the execution of your chosen ecosystem model, using the configuration files generated in the previous step. ```{r run-model} PEcAn.workflow::runModule_start_model_runs(settings) ``` - This step generates raw model outputs in model-specific format (in this case, `out.csv`) as well as log files. # Extract Model Results and Prepare for Analysis After the model simulation completes, we need to extract the results and prepare them for analysis. This involves: -1. Reading the run ID -2. Setting up output paths -3. Defining time period -4. Loading model output -5. Convert to a standard format +1. Reading the run ID +2. Setting up output paths +3. Defining time period +4. Loading model output +5. Convert to a standard format -Here we read output one site at a time to account for differing simulation periods. -For runs where all sites have the same dates, it should also work to pass the entire runid vector to a single `read.output` call. +Here we read output one site at a time to account for differing simulation periods. For runs where all sites have the same dates, it should also work to pass the entire runid vector to a single `read.output` call. ```{r get-plot-vars} runid <- read.csv(file.path(settings$outdir, "runs_manifest.csv"))$run_id @@ -236,11 +235,11 @@ model_output <- purrr::map2_dfr( available_vars <- names(model_output)[!names(model_output) %in% c("posix", "time_bounds")] ``` -Running this code will convert model specific output files into a standardized netCDF ([year].nc) that can be downloaded for visualization and analysis (R, Matlab, ncview, panoply, etc). This is a key step, because this standardization enables PEcAn to apply downstream analyses to outputs from different ecosystem models. +Running this code will convert model specific output files into a standardized netCDF (\[year\].nc) that can be downloaded for visualization and analysis (R, Matlab, ncview, panoply, etc). This is a key step, because this standardization enables PEcAn to apply downstream analyses to outputs from different ecosystem models. # Display Available Model Variables -This section shows all the variables that are available in the model output. These variables represent different ecosystem processes and states that the model has simulated. +This section shows all the variables that are available in the model output. These variables represent different ecosystem processes and states that the model has simulated. Here we are referencing PEcAn standard variables for documentation. ```{r show-variables, echo=FALSE} vars_df <- PEcAn.utils::standard_vars |> @@ -248,14 +247,7 @@ vars_df <- PEcAn.utils::standard_vars |> Variable = Variable.Name, Description = Long.name ) |> - dplyr::filter(Variable %in% available_vars) |> - # TODO: add year to PEcAn.utils::standard vars - dplyr::bind_rows( - dplyr::tibble( - Variable = "year", - Description = "Year" - ) - ) + dplyr::filter(Variable %in% available_vars) vars_df$Description[is.na(vars_df$Description)] <- "(No description available)" knitr::kable(vars_df, caption = "Model Output Variables and Descriptions") @@ -328,6 +320,7 @@ If you want to remove all files and directories created by this workflow and sta ``` # Session Info + This section prints your R session information for reproducibility. ```{r session-info} diff --git a/models/peprmt/demo_run/input_demo.qmd b/models/peprmt/demo_run/02_input_demo.qmd similarity index 63% rename from models/peprmt/demo_run/input_demo.qmd rename to models/peprmt/demo_run/02_input_demo.qmd index 253cab12e23..b0631c0bb7f 100644 --- a/models/peprmt/demo_run/input_demo.qmd +++ b/models/peprmt/demo_run/02_input_demo.qmd @@ -3,93 +3,79 @@ title: "Setting up PEPRMT inputs in PEcAn" author: - "Chris Black" - "Abby Lewis" +format: + html: default + pdf: default +toc: true +number-sections: true +fig-width: 10 +fig-height: 6 +fig-dpi: 300 --- -# Purpose +# Introduction -Show the process of creating input and met files for a basic PEcAn run. -PEcAn provides helpers for some of these, while others are (so far) still manual. +Welcome to the second demo workbook for `PEcAn.PEPRMT`! +If you are new to using PEcAn, we recommend starting with `pecan/models/peprmt/demo_run/01_run_pecan_peprmt.qmd`, which includes more explanation about the fundamental structure of a PEcAn model run. This demo builds on that initial example by showing the process for creating input and meteorological files. PEcAn provides helpers for some of these, while others are (so far) still manual. # Setup -We assume here that you already have PEcAn and PEPRMT installed. -See run_pecan_peprmt.qmd for installation instructions if needed. +We assume here that you already have PEcAn and PEPRMT installed. See `01_run_pecan_peprmt.qmd` for installation instructions if needed. ```{r setup} -here::i_am("models/peprmt/demo_run/input_demo.qmd") +here::i_am("models/peprmt/demo_run/02_input_demo.qmd") +# Load packages library(tidyverse) library(PEcAn.all) library(PEcAn.PEPRMT) +# Also requires ggh4x for the final visualization PEcAn.all::pecan_version() -# prints logger messages into the notebook instead of to the terminal +# Set PEcAn loggers logger.setUseConsole(consol = TRUE, stderr = FALSE) -# prints messages with levels INFO or higher (WARNING, ERROR, SEVERE) -# For even more detail, change to "DEBUG" logger.setLevel("INFO") ``` - # Settings PEcAn settings files declare the configuration for the entire run, including (by the end of the setup stage) full paths to every file for every ensemble member at every site. Rather than try to hand-build such a complex XML document, we expand it from a simpler XML template plus a CSV file declaring the site-specific information. -TODO: This section is hard to interpret. Either add more exposition or simplify. +Within PEcAn.PEPRMT, this process of building a setting xml document is often handled by `inst/xml_build.R`. Here, we show all of the steps that are addressed in that script. + +- First, set specifications for the run (e.g., ensemble size) and load information about each site. ```{r} +# Set the number of ensemble members for this run ensemble_size <- 10 +# Read info about the sites for this run site_info <- read.csv("data/site_info.csv") +# Ensure each site has one row stopifnot( - length(unique(site_info$id)) == nrow(site_info), - all(site_info$lat > 0), # just to simplify grid naming below - all(site_info$lon < 0) + length(unique(site_info$id)) == nrow(site_info) ) + +# Parse lat lon site_info <- site_info |> dplyr::mutate( # match locations to half-degree ERA5 grid cell centers - # CAUTION: Calculation only correct when all lats are N and all lons are W! ERA5_grid_cell = paste0( - ((lat + 0.25) %/% 0.5) * 0.5, "N_", - ((abs(lon) + 0.25) %/% 0.5) * 0.5, "W" - ), - # Hack: prepare.settings wants every site to have a name as well as an ID. - # It's probably never used downstream, but add here to quiet the check. - # TODO remove the upstream rule - name = id + ((lat + 0.25) %/% 0.5) * 0.5, ifelse(lat > 0, "N_", "S_"), + ((abs(lon) + 0.25) %/% 0.5) * 0.5, ifelse(lon > 0, "E", "W") + ) ) +``` -# Hack: setEnsemblePaths leaves all path components other than siteid -# identical across sites. -# To use site-specific grid id, I'll string-replace each siteid -id2grid <- function(s) { - # replacing in place to preserve names (easier than thinking) - for (p in seq_along(s$run$inputs$met$path)) { - s$run$inputs$met$path[[p]] <- gsub( - pattern = s$run$site$id, - replacement = s$run$site$ERA5_grid_cell, - x = s$run$inputs$met$path[[p]] - ) - } - s -} -# Also replace start and end dates -dates2grid <- function(s) { - for (p in seq_along(s$run$inputs$met$path)) { - s$run$inputs$met$path[[p]] <- gsub( - pattern = "DATES-HERE", - replacement = paste0(s$run$site$met.start, ".", - s$run$site$met.end), - x = s$run$inputs$met$path[[p]] - ) - } - s -} +- Next, load the settings template (provided in `demo_run/raw-data`) and update this template with the specifications provided above +```{r} +# Load template settings_raw <- read.settings("raw-data/template.xml") + +# Add ensemble size (as specified above) settings_raw$ensemble$size <- ensemble_size settings <- settings_raw |> @@ -102,7 +88,6 @@ settings <- settings_raw |> # for ensemble we take a range that includes all. setDates(min(site_info$met.start), max(site_info$met.end)) |> - # Takes all sites listed in site_info.csv, # adds empty path templates to each `run$site.[siteid]` createMultiSiteSettings(site_info) |> @@ -131,20 +116,31 @@ settings <- settings_raw |> path = file.path("data", "PEPRMT_specific_inputs"), path_template = "{path}/{id}_formatted.csv" ) |> + # helper functions from peprmt/R/helpers.R to address having multiple grid + # cells and date ranges in the same site_info file papply(id2grid) |> papply(dates2grid) -head(settings) settings$info$notes <- paste("Compiled from template.xml at", Sys.time()) +``` + +- Now, visualize the completed settings object and export +```{r} +# Look at the settings object +head(settings) + +# Export settings write.settings( settings, outputfile = "settings_inputdemo.xml", outputdir = getwd() ) +# Prepare and validate the settings settings <- PEcAn.settings::prepare.settings(settings) +# Export the prepared settings write.settings( settings, outputfile = "settings_inputdemo_prepped.xml", @@ -154,13 +150,16 @@ write.settings( Note for future development: We are considering a change in `PEcAn.settings::setEnsemblePaths` that would allow using all fields of `settings$run$site` (which typically include lat, lon, site pft, etc) inside the format string for the file path, which should simplify construction of paths that vary by more than the siteid. +# Inputs + +Now that the settings are prepared, the next step is to add input data for each run. For PEPRMT, this includes meteorological driver data (air temperature and light) as well as variables such as water level and salinity that we are supplying manually. -# Meteorology +## Meteorology -Process met data for all sites using `met2model.PEPRMT()` +To provide meteorological input data for each run, we are using ERA5 data that is provided in `raw-data/met`. All ERA5 files are provide in PEcAn standard format, which we can process using `met2model.PEPRMT()` to provide these data in the format PEPRMT expects. ```{r} -# Set up folder +# Set up folder for formatted met data dir.create(here::here("models","peprmt","demo_run","data","met")) # Fill in processed files @@ -172,21 +171,22 @@ for(i in 1:nrow(site_info)){ start_date <- site_info$met.start[i] end_date <- site_info$met.end[i] outfolder <- paste0("data/met/ERA5_",site_info$ERA5_grid_cell[i]) + + # Format and save files result <- met2model.PEPRMT(in.path, in.prefix, outfolder, start_date, end_date) } } ``` -# Other inputs +## Other inputs -PEPRMT includes a variety of inputs that we are supplying manually +PEPRMT requires a variety of inputs that we are currently supplying manually. These input data are stored in `raw-data/site-data-formatted`, so all we need to do is copy then over to the `data` folder, which is used in our demo run. ```{r} # Set up folder dir.create(here::here("models","peprmt","demo_run","data","PEPRMT_specific_inputs")) # Fill in processed files - for(i in 1:nrow(site_info)){ in.path <- here::here("models","peprmt","demo_run","raw-data","site-data-formatted", paste0(site_info$id[i], "_formatted.csv")) @@ -200,7 +200,7 @@ for(i in 1:nrow(site_info)){ ## Background: PEcAn's PFT concept -Each time it sets up a model run, PEcAn parameterizes it by sampling each model parameter from distributions that we define beforehand. These definitions are encapsulated in posterior files containing sets of parameters that are expected to all be set together. We refer to these parameterizations as PFTs ("plant functional type"), a name that shows PEcAn's forest ecology background and also aligns with the granularity of parameter sets typically used by ecosystem modelers. But really a "PFT" is just a group of parameters that are stored and set together; the parameters need not even be plant-related. Many PEcAn model couplers support passing multiple PFT definitions into the same model run; for example SIPNET can only simulate one type of plant at once but accepts multiple PFT files so that we can set plant and soil parameters separately. +Each time PEcAn sets up a model run, it is parameterized by sampling model parameters from distributions that we define beforehand. These definitions are encapsulated in posterior files containing sets of parameters that are expected to all be set together. We refer to these parameterizations as PFTs ("plant functional type"), a name that shows PEcAn's forest ecology background and also aligns with the granularity of parameter sets typically used by ecosystem modelers. But really a "PFT" is just a group of parameters that are stored and set together; the parameters need not even be plant-related. Many PEcAn model couplers support passing multiple PFT definitions into the same model run; for example SIPNET can only simulate one type of plant at once but accepts multiple PFT files so that we can set plant and soil parameters separately. PEcAn provides tools to define PFTs via formal meta-analysis and calibration, and the format of the PFT files is taken from the output of these tools. See the [meta-analysis](https://pecanproject.github.io/pecan-documentation/develop/rendered-demo-notebooks/meta_analysis.html) (`documentation/tutorials/Demo_03_Meta_Analysis/meta_analysis.qmd`) and parameter data assimilation (`documentation/tutorials/ParameterAssimilation/PDA.Rmd`) demos for details. However, distributions can also be computed by any other means that are convenient (an external calibration process, expert elicitation, wild guessing...) and saved in the formats described next. @@ -210,18 +210,16 @@ PEPRMT's PFT support is new and can be changed if we do not like it. For today's Before we jump into defining PEPRMT's files, it's worth reiterating that although the parameter names and distribution shapes in a PFT file are model specific, the sampling mechanism is fully controlled by PEcAn. At runtime, `PEcAn.uncertainty::get.parameter.samples()` takes samples from the posterior file you provide and passes a single numeric value for each parameter into the function responsible for model-specific run setup (in this case `write.config.PEPRMT()`). - ## Marginal posterior First we'll write marginal distributions. The format is an R data file (conventionally named "post.distns.RData" and stored in a directory whose name is the PFT name), containing a single object named `post.distns` that is a data frame with row names set to the parameter names and with the following columns: -* `distn`, the shape of distribution to use. Must be a distribution that R knows how to sample from using two moment parameters, i.e. if distribution is "foo" then `rfoo(n, a, b)` must exist. -* `parama` and `paramb`, the first two moments of the distribution. For `norm` and friends these are mean and sd, for `unif` they are max and min, for `gamma` they are shape and rate, and so on. -* `n`, the number of datapoints used to estimate this point. Usually NA in a file not created by formal meta-analysis, and not used by the model-specific sampling processes. +- `distn`, the shape of distribution to use. Must be a distribution that R knows how to sample from using two moment parameters, i.e. if distribution is "foo" then `rfoo(n, a, b)` must exist. +- `parama` and `paramb`, the first two moments of the distribution. For `norm` and friends these are mean and sd, for `unif` they are max and min, for `gamma` they are shape and rate, and so on. +- `n`, the number of datapoints used to estimate this point. Usually NA in a file not created by formal meta-analysis, and not used by the model-specific sampling processes. The means shown here were retrieved 2026-03-03 from the default values used in `PEPRPMT::run_PEPRMT()`. These were calibrated in Oikawa et al 2024 but not all variances are reported there. For demonstration purposes I estimated variance parameters by visual comparison to the histograms in Oikawa 2024 (for the parameters that appear there) or by arbitrarily setting sd to 1 (for CH4 parameters). TODO: Update this. - ```{r pft-marginal} post.distns <- read.csv( text = r"( @@ -254,29 +252,29 @@ save( Let's run this! -TODO: Copying most of the demo run here. This will turn into a lot of repeated lines. +The code below is largely copied from `01_run_pecan_peprmt.qmd`, so this should look familiar. If any of this is confusing, that workbook is a good resource for more documentation. -```{r config-marginal} +```{r} +# Set parameters to default_marginal within the settings settings$pfts[purrr::map_lgl(settings$pfts, \(x)x$name == "default")]$pft$posterior.files <- file.path("data", "pfts", "default_marginal", "post.distns.RData") +# Write configs settings <- PEcAn.workflow::runModule.run.write.configs(settings) -``` - -```{r run-marginal} +# Execute model runs PEcAn.workflow::runModule_start_model_runs(settings) -``` -```{r read-marginal} +# Compile all of the outputs runid <- read.csv(file.path(settings$outdir, "runs_manifest.csv"))$run_id outdirs <- file.path(settings$outdir, "out", runid) -model_output <- purrr::map2_dfr( + +model_output_marginal <- purrr::map2_dfr( .x = runid |> setNames(nm = _), .y = outdirs, .f = function(id, dir) { PEcAn.utils::read.output( runid = id, outdir = dir, start.year = NA, end.year = NA, - variables = "GPP", + variables = "CH4_flux", dataframe = TRUE, verbose = FALSE, print_summary = FALSE @@ -284,18 +282,41 @@ model_output <- purrr::map2_dfr( }, .id = "run_id" ) -model_output |> +``` + +Summarize and visualize outputs + +```{r} +# Summarize +model_output_marginal |> mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> group_by(site_id, year) |> summarize( - mean_GPP = mean(GPP, na.rm = TRUE), - q5 = quantile(GPP, 0.05, na.rm = TRUE), - q95 = quantile(GPP, 0.95, na.rm = TRUE), + mean_CH4 = mean(CH4_flux, na.rm = TRUE), + q5 = quantile(CH4_flux, 0.05, na.rm = TRUE), + q95 = quantile(CH4_flux, 0.95, na.rm = TRUE), n = n(), - n_missing = sum(is.na(GPP)) + n_missing = sum(is.na(CH4_flux)) ) -``` +model_output_marginal |> + mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> + select("site_id", "run_id", "posix", "CH4_flux") |> + ggplot() + + aes(x = posix, + y = CH4_flux * 1E6 * 60 * 60 * 24, # Convert from kg/m2/s to mg/m2/d + group = run_id) + + facet_wrap(~site_id, nrow = 1, scales = "free", space = "free_x") + + geom_line(alpha = 0.5) + + ylab(expression("Methane Flux (mg C"~m^-2~d^-1*")")) + + ggtitle("Methane Fluxes Over Time") + + theme_bw()+ + scale_x_date(date_breaks = "1 year", + date_labels = "%Y")+ + theme(legend.position = "none", + axis.text.x = element_text(angle = 45, hjust = 1), + axis.title.x = element_blank()) +``` ## MCMC posterior @@ -305,9 +326,7 @@ The format is an R data file (conventionally named "trait.mcmc.RData" and stored In non-demo cases, you would of course create this file by actually running an MCMC sampler and would probably want to include all the parameters in the same sampling (and therefore only pass a single `trait.mcmc.RData` into the run). -Caution: If two or more PFTs define a parameter with the same name, `get.parameter.samples` will provide a draw from each of them and pass both as the `trait.values` argument to `write.config.PEPRMT`, which will then use whichever value appears first in `trait.values`, which is in turn determined by which PFT appears first in `settings$run$site$site.pft`. -TODO: PEcAn should probably have a cross-model policy on how to handle duplicate parameter definitions (but one that realizes there exist models that _do_ use both of them, e.g. models that explicitly represent more than one simultaneously grown PFT). - +Caution: If two or more PFTs define a parameter with the same name, `get.parameter.samples` will provide a draw from each of them and pass both as the `trait.values` argument to `write.config.PEPRMT`, which will then use whichever value appears first in `trait.values`, which is in turn determined by which PFT appears first in `settings$run$site$site.pft`. TODO: PEcAn should probably have a cross-model policy on how to handle duplicate parameter definitions (but one that realizes there exist models that *do* use both of them, e.g. models that explicitly represent more than one simultaneously grown PFT). ```{r pft-mcmc} n_mc <- 100 @@ -350,6 +369,8 @@ trait.mcmc <- list( dimnames = list(NULL, "beta.o")) ), class = "mcmc.list") ) + +# Visualize and export str(trait.mcmc) demo_pft_dir <- file.path("data", "pfts", "default_mcmc") dir.create(demo_pft_dir, recursive = TRUE) @@ -358,18 +379,25 @@ save( file = file.path(demo_pft_dir, "trait.mcmc.RData")) ``` +We now need to go back and configure the settings object to handle these MCMC draws. + ```{r config-mcmc} +# Set name and location settings$pfts <- settings$pfts |> append(list(pft = list( name = "default_mcmc", posterior.files = file.path("data", "pfts", "default_mcmc", "trait.mcmc.RData") ))) + +# Create helper function for adding pfts add_mcpft_to_site <- function(s) { # Note: The order of this list determines the order of trait.values, # so if a parameter is defined in multiple PFTs the first listed here wins s$run$site$site.pft <- list(default_mcmc = "default_mcmc", default = "default") s } + +# Add pfts and set output directory for this run settings <- settings |> papply(add_mcpft_to_site) |> setOutDir("input_demo_mcmc_out") |> @@ -379,6 +407,7 @@ settings <- settings |> # why does that show up here but not for marginal? PEcAn.settings::prepare.settings(force = TRUE) +# Export write.settings( settings, outputfile = "settings_inputdemo_mcmc.xml", @@ -386,25 +415,23 @@ write.settings( ) ``` -```{r run-write-configs-mcmc} -settings <- PEcAn.workflow::runModule.run.write.configs(settings) -``` +Let's run it! ```{r run-mcmc} +settings <- PEcAn.workflow::runModule.run.write.configs(settings) + PEcAn.workflow::runModule_start_model_runs(settings) -``` -```{r read-mcmc} runid <- read.csv(file.path(settings$outdir, "runs_manifest.csv"))$run_id outdirs <- file.path(settings$outdir, "out", runid) -model_output <- purrr::map2_dfr( +model_output_mcmc <- purrr::map2_dfr( .x = runid |> setNames(nm = _), .y = outdirs, .f = function(id, dir) { PEcAn.utils::read.output( runid = id, outdir = dir, start.year = NA, end.year = NA, - variables = "GPP", + variables = "CH4_flux", dataframe = TRUE, verbose = FALSE, print_summary = FALSE @@ -412,15 +439,63 @@ model_output <- purrr::map2_dfr( }, .id = "run_id" ) -model_output |> +``` + +Summarize and visualize outputs + +```{r} +model_output_mcmc |> mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> group_by(site_id, year) |> summarize( - mean_GPP = mean(GPP, na.rm = TRUE), - q5 = quantile(GPP, 0.05, na.rm = TRUE), - q95 = quantile(GPP, 0.95, na.rm = TRUE), + mean_CH4 = mean(CH4_flux, na.rm = TRUE), + q5 = quantile(CH4_flux, 0.05, na.rm = TRUE), + q95 = quantile(CH4_flux, 0.95, na.rm = TRUE), n = n(), - n_missing = sum(is.na(GPP)) + n_missing = sum(is.na(CH4_flux)) ) + +model_output_mcmc |> + mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> + select("site_id", "run_id", "posix", "CH4_flux") |> + ggplot() + + aes(x = posix, + y = CH4_flux * 1E6 * 60 * 60 * 24, # Convert from kg/m2/s to mg/m2/d + group = run_id) + + facet_wrap(~site_id, nrow = 1, scales = "free", space = "free_x") + + geom_line(alpha = 0.5) + + ylab(expression("Methane Flux (mg C"~m^-2~d^-1*")")) + + ggtitle("Methane Fluxes Over Time") + + theme_bw()+ + scale_x_date(date_breaks = "1 year", + date_labels = "%Y")+ + theme(legend.position = "none", + axis.text.x = element_text(angle = 45, hjust = 1), + axis.title.x = element_blank()) +``` + +And one last visualization comparing the two approaches + +```{r} +bind_rows(MCMC = model_output_mcmc, + Marginal = model_output_marginal, + .id = "Approach") |> + mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> + select("site_id", "run_id", "posix", "CH4_flux", "Approach") |> + ggplot() + + aes(x = posix, + y = CH4_flux * 1E6 * 60 * 60 * 24, # Convert from kg/m2/s to mg/m2/d + group = run_id) + + ggh4x::facet_grid2(site_id~Approach, scales = "free", space = "free_x", + independent = "x") + + geom_line(alpha = 0.5) + + ylab(expression("Methane Flux (mg C"~m^-2~d^-1*")")) + + ggtitle("Methane Fluxes Over Time") + + theme_bw()+ + scale_x_date(date_breaks = "1 year", + date_labels = "%Y")+ + theme(legend.position = "none", + axis.text.x = element_text(angle = 45, hjust = 1), + axis.title.x = element_blank()) ``` diff --git a/models/peprmt/demo_run/event_demo.qmd b/models/peprmt/demo_run/03_event_demo.qmd similarity index 100% rename from models/peprmt/demo_run/event_demo.qmd rename to models/peprmt/demo_run/03_event_demo.qmd diff --git a/models/peprmt/demo_run/settings_inputdemo.xml b/models/peprmt/demo_run/settings_inputdemo.xml index 424714592f3..85fe83a001e 100644 --- a/models/peprmt/demo_run/settings_inputdemo.xml +++ b/models/peprmt/demo_run/settings_inputdemo.xml @@ -1,7 +1,7 @@ - Compiled from template.xml at 2026-04-20 17:29:14.53096 + Compiled from template.xml at 2026-06-24 11:41:32.880971 -1 @@ -37,7 +37,7 @@ US_EDN - US_EDN + Eden Landing 37.615 -122.114 default @@ -72,7 +72,7 @@ US_SRR - US_SRR + Rush Ranch 38.2 -122.026 default @@ -107,7 +107,7 @@ US_DMG - US_DMG + Dutch Slough 38.0015 -121.6691 default diff --git a/models/peprmt/inst/xml_build.R b/models/peprmt/inst/xml_build.R index 463730532c4..51d9ec95183 100644 --- a/models/peprmt/inst/xml_build.R +++ b/models/peprmt/inst/xml_build.R @@ -83,21 +83,21 @@ args <- optparse::OptionParser(option_list = options) |> ## Whew, that was a lot of lines to define a few defaults! - +# Load site info site_info <- read.csv(args$site_file) +# Ensure each site has one row stopifnot( - length(unique(site_info$id)) == nrow(site_info), - all(site_info$lat > 0), # just to simplify grid naming below - all(site_info$lon < 0) + length(unique(site_info$id)) == nrow(site_info) ) + +# Parse lat lon site_info <- site_info |> dplyr::mutate( # match locations to half-degree ERA5 grid cell centers - # CAUTION: Calculation only correct when all lats are N and all lons are W! ERA5_grid_cell = paste0( - ((lat + 0.25) %/% 0.5) * 0.5, "N_", - ((abs(lon) + 0.25) %/% 0.5) * 0.5, "W" + ((lat + 0.25) %/% 0.5) * 0.5, ifelse(lat > 0, "N_", "S_"), + ((abs(lon) + 0.25) %/% 0.5) * 0.5, ifelse(lon > 0, "E", "W") ), # Hack: prepare.settings wants every site to have a name as well as an ID. # It's probably never used downstream, but add here to quiet the check. @@ -105,6 +105,7 @@ site_info <- site_info |> name = id ) +# Load settings and set specifications settings_init <- read.settings(args$template_file) |> setDates(args$start_date, args$end_date) @@ -113,33 +114,6 @@ settings_init$info$notes <- paste("Compiled from", args$template_file, settings_init$ensemble$size <- args$n_ens -# Hack: setEnsemblePaths leaves all path components other than siteid -# identical across sites. -# To use site-specific grid id, I'll string-replace each siteid -id2grid <- function(s) { - # replacing in place to preserve names (easier than thinking) - for (p in seq_along(s$run$inputs$met$path)) { - s$run$inputs$met$path[[p]] <- gsub( - pattern = s$run$site$id, - replacement = s$run$site$ERA5_grid_cell, - x = s$run$inputs$met$path[[p]] - ) - } - s -} -# Also replace start and end dates -dates2grid <- function(s) { - for (p in seq_along(s$run$inputs$met$path)) { - s$run$inputs$met$path[[p]] <- gsub( - pattern = "DATES-HERE", - replacement = paste0(s$run$site$met.start, ".", - s$run$site$met.end), - x = s$run$inputs$met$path[[p]] - ) - } - s -} - settings <- settings_init |> # Set where demo outputs go @@ -150,7 +124,6 @@ settings <- settings_init |> # for ensemble we take a range that includes all. setDates(min(site_info$met.start), max(site_info$met.end)) |> - # Takes all sites listed in site_info.csv, # adds empty path templates to each `run$site.[siteid]` createMultiSiteSettings(site_info) |> @@ -179,7 +152,9 @@ settings <- settings_init |> path = file.path("data", "PEPRMT_specific_inputs"), path_template = "{path}/{id}_formatted.csv" ) |> - papply(id2grid) |> |> + # helper functions from peprmt/R/helpers.R to address having multiple grid + # cells and date ranges in the same site_info file + papply(id2grid) |> papply(dates2grid) # Update just the first component of the output directory, @@ -199,6 +174,7 @@ settings$host$outdir <- sub("^output", args$output_dir_name, settings$host$rundir <- sub("^output", args$output_dir_name, settings$host$rundir) +# Export write.settings( settings, outputfile = basename(args$output_file), From b60890706d1d10080193a5877dbb1a98bef6d2af Mon Sep 17 00:00:00 2001 From: Abby Lewis Date: Wed, 24 Jun 2026 12:06:53 -0400 Subject: [PATCH 2/4] file names --- models/peprmt/demo_run/01_run_pecan_peprmt.qmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/peprmt/demo_run/01_run_pecan_peprmt.qmd b/models/peprmt/demo_run/01_run_pecan_peprmt.qmd index f64375d7313..77a428d9189 100644 --- a/models/peprmt/demo_run/01_run_pecan_peprmt.qmd +++ b/models/peprmt/demo_run/01_run_pecan_peprmt.qmd @@ -41,7 +41,7 @@ We are modeling greenhouse gas dynamics (gross primary productivity, ecosystem r The simulation is run for the duration of data at each site, which ranges from 2011 to 2021. -This scenario is designed to be a minimal, reproducible example to demonstrate how to run PEPRMT within the PEcAn workflow. In later steps, this same framework can be extended to include more ensemble members, longer time periods, or alternative meteorological inputs (e.g., see `pecan/models/peprmt/demo_run/input_demo.qmd` and `pecan/models/peprmt/demo_run/event_demo.qmd`). +This scenario is designed to be a minimal, reproducible example to demonstrate how to run PEPRMT within the PEcAn workflow. In later steps, this same framework can be extended to include more ensemble members, longer time periods, or alternative meteorological inputs (e.g., see `pecan/models/peprmt/demo_run/02_input_demo.qmd` and `pecan/models/peprmt/demo_run/03_event_demo.qmd`). ## Prerequisites From eb9d16614a1e63fcd7411431f3b5677d9645063e Mon Sep 17 00:00:00 2001 From: Abby Lewis Date: Wed, 24 Jun 2026 12:13:35 -0400 Subject: [PATCH 3/4] labels --- .../peprmt/demo_run/01_run_pecan_peprmt.qmd | 4 ++-- models/peprmt/demo_run/02_input_demo.qmd | 22 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/models/peprmt/demo_run/01_run_pecan_peprmt.qmd b/models/peprmt/demo_run/01_run_pecan_peprmt.qmd index 77a428d9189..ccdf398b2c4 100644 --- a/models/peprmt/demo_run/01_run_pecan_peprmt.qmd +++ b/models/peprmt/demo_run/01_run_pecan_peprmt.qmd @@ -49,7 +49,7 @@ Before running this notebook, make sure you have: - All the PEcAn packages installed. You can install all PEcAn packages and their dependencies by running the following command in the root of your PEcAn repository. This chunk does not run automatically since it will overwrite a version of PEcAn you installed by other methods. Run it by hand when needed. -```{r, eval = FALSE} +```{r packages, eval = FALSE} # Enable repository from pecanproject options(repos = c( @@ -75,7 +75,7 @@ remotes::install_github("pecanproject/pecan", subdir = "models/peprmt", 4. Once you have successfully run the demo, you can modify parameters to configure new runs and analyses 5. By default, the demo runs within `pecan/models/peprmt/demo_run/`. -```{r} +```{r wd} #Set working directory here::i_am("models/peprmt/demo_run/01_run_pecan_peprmt.qmd") ``` diff --git a/models/peprmt/demo_run/02_input_demo.qmd b/models/peprmt/demo_run/02_input_demo.qmd index b0631c0bb7f..c4e7a5aec0a 100644 --- a/models/peprmt/demo_run/02_input_demo.qmd +++ b/models/peprmt/demo_run/02_input_demo.qmd @@ -46,7 +46,7 @@ Within PEcAn.PEPRMT, this process of building a setting xml document is often ha - First, set specifications for the run (e.g., ensemble size) and load information about each site. -```{r} +```{r set-specs} # Set the number of ensemble members for this run ensemble_size <- 10 @@ -71,7 +71,7 @@ site_info <- site_info |> - Next, load the settings template (provided in `demo_run/raw-data`) and update this template with the specifications provided above -```{r} +```{r make-settings} # Load template settings_raw <- read.settings("raw-data/template.xml") @@ -126,7 +126,7 @@ settings$info$notes <- paste("Compiled from template.xml at", Sys.time()) - Now, visualize the completed settings object and export -```{r} +```{r export_settings} # Look at the settings object head(settings) @@ -158,7 +158,7 @@ Now that the settings are prepared, the next step is to add input data for each To provide meteorological input data for each run, we are using ERA5 data that is provided in `raw-data/met`. All ERA5 files are provide in PEcAn standard format, which we can process using `met2model.PEPRMT()` to provide these data in the format PEPRMT expects. -```{r} +```{r load-met} # Set up folder for formatted met data dir.create(here::here("models","peprmt","demo_run","data","met")) @@ -182,7 +182,7 @@ for(i in 1:nrow(site_info)){ PEPRMT requires a variety of inputs that we are currently supplying manually. These input data are stored in `raw-data/site-data-formatted`, so all we need to do is copy then over to the `data` folder, which is used in our demo run. -```{r} +```{r load-other-inputs} # Set up folder dir.create(here::here("models","peprmt","demo_run","data","PEPRMT_specific_inputs")) @@ -254,7 +254,7 @@ Let's run this! The code below is largely copied from `01_run_pecan_peprmt.qmd`, so this should look familiar. If any of this is confusing, that workbook is a good resource for more documentation. -```{r} +```{r run-marginal} # Set parameters to default_marginal within the settings settings$pfts[purrr::map_lgl(settings$pfts, \(x)x$name == "default")]$pft$posterior.files <- file.path("data", "pfts", "default_marginal", "post.distns.RData") @@ -286,7 +286,7 @@ model_output_marginal <- purrr::map2_dfr( Summarize and visualize outputs -```{r} +```{r vis-marginal} # Summarize model_output_marginal |> mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> @@ -443,7 +443,7 @@ model_output_mcmc <- purrr::map2_dfr( Summarize and visualize outputs -```{r} +```{r vis-mcmc} model_output_mcmc |> mutate(site_id = sub("ENS-\\d+-", "", run_id)) |> group_by(site_id, year) |> @@ -474,9 +474,11 @@ model_output_mcmc |> axis.title.x = element_blank()) ``` -And one last visualization comparing the two approaches +## Visualize -```{r} +One last visualization comparing the two approaches + +```{r vis-both} bind_rows(MCMC = model_output_mcmc, Marginal = model_output_marginal, .id = "Approach") |> From 1bd390d72a01e9865108b8b77180a08c548d0b3a Mon Sep 17 00:00:00 2001 From: Abby Lewis Date: Wed, 24 Jun 2026 12:26:40 -0400 Subject: [PATCH 4/4] Tiny documentation changes for demo3 --- models/peprmt/demo_run/02_input_demo.qmd | 7 +- models/peprmt/demo_run/03_event_demo.qmd | 139 +++++++++++++---------- 2 files changed, 80 insertions(+), 66 deletions(-) diff --git a/models/peprmt/demo_run/02_input_demo.qmd b/models/peprmt/demo_run/02_input_demo.qmd index c4e7a5aec0a..9f004be1a71 100644 --- a/models/peprmt/demo_run/02_input_demo.qmd +++ b/models/peprmt/demo_run/02_input_demo.qmd @@ -15,7 +15,7 @@ fig-dpi: 300 # Introduction -Welcome to the second demo workbook for `PEcAn.PEPRMT`! +Welcome to the second demo workbook for `PEcAn.PEPRMT`! If you are new to using PEcAn, we recommend starting with `pecan/models/peprmt/demo_run/01_run_pecan_peprmt.qmd`, which includes more explanation about the fundamental structure of a PEcAn model run. This demo builds on that initial example by showing the process for creating input and meteorological files. PEcAn provides helpers for some of these, while others are (so far) still manual. @@ -152,11 +152,11 @@ Note for future development: We are considering a change in `PEcAn.settings::set # Inputs -Now that the settings are prepared, the next step is to add input data for each run. For PEPRMT, this includes meteorological driver data (air temperature and light) as well as variables such as water level and salinity that we are supplying manually. +Now that the settings are prepared, the next step is to add input data for each run. For PEPRMT, this includes meteorological driver data (air temperature and light) as well as variables such as water level and salinity that we are supplying manually. ## Meteorology -To provide meteorological input data for each run, we are using ERA5 data that is provided in `raw-data/met`. All ERA5 files are provide in PEcAn standard format, which we can process using `met2model.PEPRMT()` to provide these data in the format PEPRMT expects. +To provide meteorological input data for each run, we are using ERA5 data that is provided in `raw-data/met`. All ERA5 files are provide in PEcAn standard format, which we can process using `met2model.PEPRMT()` to provide these data in the format PEPRMT expects. ```{r load-met} # Set up folder for formatted met data @@ -500,4 +500,3 @@ bind_rows(MCMC = model_output_mcmc, axis.text.x = element_text(angle = 45, hjust = 1), axis.title.x = element_blank()) ``` - diff --git a/models/peprmt/demo_run/03_event_demo.qmd b/models/peprmt/demo_run/03_event_demo.qmd index 0e29e742ec9..e3aa36b8f47 100644 --- a/models/peprmt/demo_run/03_event_demo.qmd +++ b/models/peprmt/demo_run/03_event_demo.qmd @@ -2,63 +2,79 @@ title: "Event handling in PEPRMT" author: - "Chris Black" +editor: + markdown: + wrap: 72 +format: + html: default + pdf: default +toc: true +number-sections: true +fig-width: 10 +fig-height: 6 +fig-dpi: 300 --- +# Introduction + +Welcome to the third demo workbook for `PEcAn.PEPRMT`! + ## Purpose -Adds management events to a basic PEPRMT run using PEcAn. -For demonstration we show a one-time step change in inundation depth and a -temporary fractional change in salinity. -The same approach could be extended to other event types that alter timeseries -inputs. +Through the previous demo workbooks, we have shown how to execute a +minimal PEcAn run (`01_run_pecan_peprmt.qmd`), as well as how to set the +parameters and input data for that run (`02_input_demo.qmd`). Here, we +build on the outputs from `02_input_demo.qmd` by showing how to add +management events to a PEPRMT run in PEcAn. -Future development will add support for events that alter model parameters, -e.g. changes in site vegetation type). -This will require new capabilities for "restarting" the model, -which exist for other PEcAn models but are not yet implemented for PEPRMT. +For demonstration, the events we illustrate here include a one-time step +change in inundation depth and a temporary fractional change in +salinity. The same approach could be extended to other event types that +alter timeseries inputs. +Future development will add support for events that alter model +parameters, e.g. changes in site vegetation type. This will require new +capabilities for "restarting" the model, which exist for other PEcAn +models but are not yet implemented for PEPRMT. ## Prerequisites -We assume here that you already have PEcAn and PEPRMT installed. -See run_pecan_peprmt.qmd for installation instructions if needed. - -We also assume you have already run `input_demo.qmd`, -and this demo uses these files created by it: +We assume here that you already have PEcAn and PEPRMT installed. See +`01_run_pecan_peprmt.qmd` for installation instructions if needed. -* `settings_inputdemo.xml` -* `data/met/` -* `data/PEPRMT_specific_inputs/` -* `data/pfts/default_marginal/` +We also assume you have already run `02_input_demo.qmd`. This demo uses +these files created by in the second demp: +- `settings_inputdemo.xml` +- `data/met/` +- `data/PEPRMT_specific_inputs/` +- `data/pfts/default_marginal/` ## Setup - ```{r} #| label: setup here::i_am("models/peprmt/demo_run/event_demo.qmd") +# Load packages library(tidyverse) library(PEcAn.all) library(PEcAn.PEPRMT) PEcAn.all::pecan_version() -# prints logger messages into the notebook instead of to the terminal +# Set PEcAn loggers logger.setUseConsole(console = TRUE, stderr = FALSE) -# prints messages with levels INFO or higher (WARNING, ERROR, SEVERE) -# For even more detail, change to "DEBUG" logger.setLevel("INFO") ``` ### Define outdirs -PEcAn accepts existing output directories and will attempt to overwrite them, -but this often does not work cleanly. -We advise always starting fresh. +PEcAn accepts existing output directories and will attempt to overwrite +them, but this often does not work cleanly. We advise always starting +fresh. -This check adds a step when trying to rerun the notebook quickly, -but complaining here is better than clobbering outputs you were counting on. +This check adds a step when trying to rerun the notebook quickly, but +complaining here is better than clobbering outputs you were counting on. ```{r} #| label: outdir-check @@ -71,17 +87,17 @@ if (any(have_outdirs)) { } ``` - ## Settings -For brevity let's modify the settings used for the input demo rather than -start from scratch. -We'll use only the first two sites (US_EDN and US_SRR) and add an event file. +For brevity let's modify the settings used for the input demo rather +than start from scratch. We'll use only the first two sites (US_EDN and +US_SRR) and add an event file. -To add an input to a PEcAn run, first declare it in the sampling space and then -provide (an ensemble of) paths to the input files in each site's input block. -Note that these files don't exist yet -- we'll create them next. -This step only constructs paths and does not check their contents. +To add an input to a PEcAn run, first declare it in the sampling space +and then provide (an ensemble of) paths to the input files in each +site's input block. Note that these files don't exist yet -- we'll +create them next. This step only constructs paths and does not check +their contents. ```{r} #| label: settings @@ -119,27 +135,25 @@ write.settings( ) ``` - ## Event files -For demo purposes let's imagine all sites experience a one-time permanent change -in inundation depth of approximately 30 cm and a temporary step change in -salinity of approximately 75 percent. -These are chosen more for simplicity than for biological realism; -suggestions for other simple event examples are very welcome. - -PEcAn will treat these as "management events", and stores them as nested lists -in JSON format. -Each site has a site id, a list of events, and optionally other site-level -metadata. -Each event has a date, an event type, and optionally other parameters needed to -specify the particulars of that event type. -Models are allowed to ignore event types they do not recognize and to disregard -event parameters not used in their representation of an event they do recognize. +For demo purposes let's imagine all sites experience a one-time +permanent change in inundation depth of approximately 30 cm and a +temporary step change in salinity of approximately 75 percent. These are +chosen more for simplicity than for biological realism; suggestions for +other simple event examples are very welcome. +PEcAn will treat these as "management events", and stores them as nested +lists in JSON format. Each site has a site id, a list of events, and +optionally other site-level metadata. Each event has a date, an event +type, and optionally other parameters needed to specify the particulars +of that event type. Models are allowed to ignore event types they do not +recognize and to disregard event parameters not used in their +representation of an event they do recognize. ```{r} #| label: write-event-json + dir.create(file.path("data", "events")) for (i in seq_len(settings$ensemble$size)) { dsal <- rnorm(n = 1, mean = 75, sd = 5) |> round(2) @@ -196,13 +210,13 @@ for (i in seq_len(settings$ensemble$size)) { ### Generate sample design -To get clean comparisons between treatments, -we'll pair simulations with and without events by using the same ensemble of -parameter and input values for both runs. - +To get clean comparisons between treatments, we'll pair simulations with +and without events by using the same ensemble of parameter and input +values for both runs. ```{r} #| label: design + evt_design <- generate_joint_ensemble_design( settings_evt[[1]], settings_evt$ensemble$size @@ -247,10 +261,10 @@ runModule_start_model_runs(settings_evt) ## Plot results -Most non-carbon outputs are not yet written into the PEcAn standard outputs, -so let's read read the raw PEPRMT output (`out.csv`) to verify the environment -changes. See the input demo for an example of reading from PEcAn netcdf output. - +Most non-carbon outputs are not yet written into the PEcAn standard +outputs, so let's read read the raw PEPRMT output (`out.csv`) to verify +the environment changes. See the input demo for an example of reading +from PEcAn netcdf output. ```{r} #| label: read @@ -297,6 +311,7 @@ model_output <- dplyr::bind_rows( ) ``` + Salinity and water table depth did change: ```{r} @@ -316,10 +331,10 @@ base_plot + aes(y = Salinity_daily_ave_ppt) base_plot + aes(y = WTD_cm) ``` -...And as expected, salinity reduction at the normally-salty EDN site produces -a visible increase in CH4 production, while salinity increase at the -mostly-fresh SRR site produces a net inhibition of CH4. -The change in water depth does not visibly affect CH4 in these simulations. +...And as expected, salinity reduction at the normally-salty EDN site +produces a visible increase in CH4 production, while salinity increase +at the mostly-fresh SRR site produces a net inhibition of CH4. The +change in water depth does not visibly affect CH4 in these simulations. ```{r} #| label: plot-ch4