knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) is_windows <- Sys.info()[1] == "Windows"
library(flextreat.hydrus1d) ### Compile Hydrus1D v4.08 for windows ### based on: https://github.com/phydrus/source_code/tree/main/source exe_path <- flextreat.hydrus1d::create_hydrus_exe() env <- "flextreat" kwb.python::conda_py_install(env_name = env, pkgs = list(conda=c("python=3.9", "openpyxl"), py = "https://github.com/phydrus/phydrus/zipball/dev/79823e797662b9838dda13888e3ead962c6699d0")) reticulate::use_miniconda(condaenv = env, required = TRUE) ps <- reticulate::import("phydrus", convert = FALSE) env_yml <- kwb.python::conda_export(condaenv = env, export_dir = ".") env_yml <- basename(env_yml)
For reproducing the Python environment used for the Hydrus1D
modelling you can
download the r env_yml
. Keep in mind that phydrus
was developed
for the last open-source release (hydrus v4.0.8
) and is not compatible with the
lastest hydrus v4.17
(see: https://github.com/phydrus/source_code/issues/1#issuecomment-1034675697).
############################################################################### # 0 General Model Settings ############################################################################### #reticulate::py_help(object = phydrus$model$Model) ml <- ps$model$Model(exe_name = exe_path, ws_name = "test", name = "Test", description = "Test for FlexTreat", length_unit = "cm", time_unit = "days", mass_units = "mmol") #reticulate::py_help(object = ml$add_time_info) times <- ml$add_time_info( # tinit: int, optional # Initial time of the simulation [T]. tinit = 90, # tmax: int, optional # Final time of the simulation [T]. tmax = 273, # dt: float, optional # Initial time increment [T]. dt = 0.01, # dtmin: float, optional # Minimum permitted time increment [T]. dtmin = 1e-05, # dtmax: float, optional # Maximum permitted time increment [T]. dtmax=5, # print_times: boolean, optional # Set to True. if information of pressure head, water contents, # temperatures, and concentrations in observation nodes, and # the water and solute fluxes is to be printed at a constant # time interval of 1 time unit. print_times = TRUE, # printinit: int, optional # First specified print-time [T]. printinit = NULL, # printmax:int, optional # Last specified print-time [T]. printmax = NULL, # dtprint: int, optional # Specified time increment for print times [T]. dtprint = NULL, # nsteps: str, optional # Number of required time steps between the first specified # print-time (printinit) and the final specified # print-time (printmax)". nsteps = NULL, # from_atmo: boolean, optional. # Set to True if time information is determined from the # atmospheric boundary condition input data. from_atmo = FALSE, # print_array: array of float, optional # Array of specified print-times. print_array = NULL ) ############################################################################### # 1 Add the process water transport ############################################################################### #reticulate::py_help(object = ml$add_waterflow) ml$add_waterflow( # model: int, optional # Soil hydraulic properties model: # 0 = van Genuchten"s [1980] model with 6 parameters. # 1 = modified van Genuchten"s model with 10 parameters [Vogel # and Císlerová, 1988]. # 2 = Brooks and Corey"s [1964] model with 6 parameters. # 3 = van Genuchten"s [1980] model with air-entry value of -2 cm # and with 6 parameters. # 4 = Kosugi’s [1996] model with 6 parameters. # 5 = dual-porosity model of Durner [1994] with 9 parameters. # 6 = dual-porosity system with transfer proportional to the # effective saturation (9 parameters). # 7 = dual-porosity system with transfer proportional to the # pressure head (11 parameters). # 9 = dual-permeability system with transfer proportional to the # pressure head (17 parameters) model = 0, # maxit: int, optional # Maximum number of iterations allowed during any time step. maxit = 10L, # tolth: float, optional # Absolute water content tolerance for nodes in the unsaturated part # of the flow region [-]. TolTh represents the maximum desired # absolute change in the value of the water content, θ, between # two successive iterations during a particular time step. tolth = 1E-3, # tolh: float, optional # Absolute pressure head tolerance for nodes in the saturated part of # the flow region [L] (its recommended value is 0.1 cm). TolH # represents the maximum desired absolute change in the value of the # pressure head, h, between two successive iterations during a # particular time step. tolh = 0.1, # ha: float, optional # Absolute value of the upper limit [L] of the pressure head interval # below which a table of hydraulic properties will be generated # internally for each material. ha = 1E-6, # hb: float, optional # Absolute value of the lower limit [L] of the pressure head interval # for which a table of hydraulic properties will be generated # internally for each material. hb = 1E4, # linitw: bool, optional # Set to True if the initial condition is given in terms of the # water content. Set to False if given in terms of pressure head. linitw = FALSE, # top_bc: int, optional # Upper Boundary Condition: # 0 = Constant Pressure Head. # 1 = Constant Flux. # 2 = Atmospheric Boundary Condition with Surface Layer. # 3 = Atmospheric Boundary Condition with Surface Run Off. # 4 = Variable Pressure Head. # 5 = Variable Pressure Head/Flux. top_bc=3, # bot_bc: int, optional # Lower Boundary Condition: # 0 = Constant Pressure Head. # 1 = Constant Flux. # 2 = Variable Pressure Head. # 3 = Variable Flux. # 4 = Free Drainage. # 5 = Deep Drainage. # 6 = Seepage Face. # 7 = Horizontal Drains. bot_bc = 4, # 4: free drainage # hseep: float, optional # Pressure head (i.e., 0) that initiates flow over the seepage face # bottom boundary. hseep = 0, # rtop: float, optional # Prescribed top flux [LT-1] (in case of a Dirichlet BC set this # variable equal to zero). rtop = NULL, # rbot: float, optional # Prescribed bottom flux [LT-1] (in case of a Dirichlet BC set this # variable equal to zero). rbot = NULL, # rroot: float, optional # Prescribed potential transpiration rate [LT-1] (if no transpiration # occurs or if transpiration is variable in time set this variable # equal to zero). rroot = NULL, # gw_level: float, optional # Reference position of the groundwater table (e.g., the # x-coordinate of the soil surface) gw_level = NULL, # aqh: float, optional # Value of the parameter Aqh [LT-1] in the q(GWL)-relationship. aqh = NULL, # bqh: float, optional # Value of the parameter Bqh [L-1] in the q(GWL)-relationship. bqh = NULL, # hysteresis: int, optional # Hysteresis in the soil hydraulic properties: # 0 = No hysteresis. # 1 = Hysteresis in the retention curve only. # 2 = Hysteresis in both the retention and hydraulic conductivity # functions. # 3 = Hysteresis using Robert Lenhard’s model [Lenhard et al., # 1991; Lenhard and Parker, 1992]. (Not available with major ion # chemistry module.) hysteresis = 0, # ikappa: int, optional # Set to -1 if the initial condition is to be calculated from the # main drying branch. Set to 1 if the initial condition is to be # calculated from the main wetting branch. ikappa = -1 ) ############################################################################### # 2 Add the process solute transport ############################################################################### #reticulate::py_help(object = ml$add_solute_transport) ml$add_solute_transport( # model: int, optional # Code describing type of nonequilibrium for solute transport: # 0 = equilibrium solute transport (Default) # 1 = one-site sorption model (chemical nonequilibrium) # 2 = two-site sorption model (chemical nonequilibrium) # 3 = two kinetic sorption sites model (attachment/detachment; # chemical nonequilibrium). This model is often used for particle # (viruses, colloids, bacteria) transport. # 4 = two kinetic sorption sites model (attachment/detachment) ( # chemical nonequilibrium). Attachment coefficients are calculated # using filtration theory. # 5 = dual-porosity model (mobile-immobile regions; physical # nonequilibrium). # 6 = dual-porosity model (mobile-immobile regions) with two-site # sorption in the mobile zone (physical and chemical nonequilibrium). # 7 = dual-permeability model (physical nonequilibrium). # 8 = dual-permeability model with either an immobile region in the # matrix domain (physical nonequilibrium) or with two-site # sorption in both domains (physical and chemical nonequilibrium). model = 0, # epsi: float, optional # Temporal weighing coefficient. 0.0 for an explicit scheme ( # Default). 0.5 for a Crank-Nicholson implicit scheme. =1.0 for # a fully implicit scheme. epsi = 0.5, # lupw: bool, optional # True if upstream weighing formulation is to be used. False if # the original Galerkin formulation is to be used. lupw = FALSE, # lartd: bool, optional # True if artificial dispersion is to be added in order to fulfill # the stability criterion PeCr (see Section 8.4.4), else False. lartd = FALSE, #ltdep: bool, optional # True if at least one transport or reaction coefficient (ChPar) is # temperature dependent, else False. If ltdep=True, then all # values of ChPar(i,M) should be specified at a reference # temperature Tr=20 degrees celsius. ltdep = FALSE, # ctola: float, optional # Absolute concentration tolerance [ML-3], the value is dependent # on the units used (set equal to zero if nonlinear adsorption is # not considered). ctola = 0, # ctolr: float, optional # Relative concentration tolerance [-] (set equal to zero if # nonlinear adsorption is not considered). ctolr = 0, # maxit: int, optional # Maximum number of iterations allowed during any time step for # solute transport - usually 20 (set equal to zero if nonlinear # adsorption is not considered). maxit = 0, # pecr: float optional # Stability criteria. Set to zero when lUpW = TRUE pecr = 2, # ltort: bool, optional # TRUE if the tortuosity factor [Millington and Quirk, 1961] is to be # used. FALSE if the tortuosity factor is assumed to be equal to one. ltort = TRUE, # lwatdep: bool, optional # TRUE if at least one degradation coefficient (ChPar) is water # content dependent. lwatdep = FALSE, # top_bc: int, optional # Code which specifies the type of upper boundary condition # 1 = Dirichlet boundary condition, # -1 = Cauchy boundary condition. # -2 = a special type of boundary condition for volatile solutes # as described by equation (3.46). top_bc = -1, # bot_bc: int, optional # Code which specifies the type of lower boundary condition: # 1 = Dirichlet boundary condition, # 0 = continuous concentration profile, # -1 = Cauchy boundary condition. bot_bc = 0, # dsurf: float, optional # Thickness of the stagnant boundary layer, d [L]. Only when # kTopCh=-2. dsurf = NULL, # catm: float, optional # Concentration above the stagnant boundary layer, g_atm [ML-3]. # Only when kTopCh=-2. catm = NULL, # tpulse: float, optional # Time duration of the concentration pulse [T]. tpulse = 1) ############################################################################### # 3 Add soil characteristics & profile ############################################################################### #reticulate::py_help(object = ml$get_empty_material_df) m <- ml$get_empty_material_df(n = 2) m m_r <- reticulate::py_to_r(m) print(m_r) m$to_excel(excel_writer = "material.xlsx") # m <- [(0.0, 0.34, 0.01, 1.47, 13, 0.5, 1.5, 30.0, 1, 0), # (0.0, 0.36, 0.02, 1.52, 50, 0.5, 1.5, 30.0, 1, 0)) # ) ml$add_material(material = m) bottom <- c(-30, -100) # Depth of the soil column ihead <- -500 # Determine initial pressure head #reticulate::py_help(object = ps$create_profile) profile <- ps$create_profile( # top: float, optional # Top of the soil column. top = 0, # bot: float or list of float, optional # Bottom of the soil column. If a list is provided, multiple layers are # created and other arguments need to be of the same length (e.g. mat). bot = bottom, # dx: float, optional # Size of each grid cell. Default 0.1 meter. dx = 1, # h: float, optional # Initial values of the pressure head. h = ihead, # lay: int or list of int, optional # Subregion number (for mass balance calculations). lay = c(1,2), # mat: int or list of int, optional # Material number (for heterogeneity). mat = c(1,2), # beta: float or list of float, optional # Value of the water uptake distribution, b(x) [L-1], in the soil root # zone at node n. Set Beta(n) equal to zero if node n lies outside the # root zone. beta = 0, # ah: float or list of float, optional # Scaling factor for the pressure head (Axz in profile.dat). ah = 1.0, # ak: float or list of float, optional # Scaling factor the hydraulic conductivity (Bxz in profile.dat). ak = 1.0, # ath: float or list of float, optional # Scaling factor the the water content (Dxz in profile.dat). ath = 1.0, # temp: float, optional # Initial value of the temperature at node n [oC] (do not specify if # both lTemp or lChem are equal to .false.; if lTemp=.false. and # lChem=.true. then set equal to 0 or any other initial value to be used # later for temperature dependent water flow and solute transport). temp = 20.0, # conc: float, optional conc = NULL, # sconc: float, optional sconc = NULL) profile ml$add_profile(profile) ############################################################################### # 4 Add observation nodes ############################################################################### ml$add_obs_nodes(depths = c(-30, -60)) ############################################################################### # 5 Add solute ############################################################################### #reticulate::py_help(object = ml$get_empty_solute_df) sol <- ml$get_empty_solute_df() sol #sol$beta <- 1.0 # Required when no equilibrium is chosen. #reticulate::py_help(object = ml$add_solute) ml$add_solute(data = sol, # difw: float, optional # Ionic or molecular diffusion coefficient in free water, Dw [L2T-1]. difw = 0, # difg: float, optional # Ionic or molecular diffusion coefficient in gas phase, Dg [L2T-1]. difg = 0, # top_conc: float, optional # Concentration of the upper boundary, or concentration of the # incoming fluid [ML-3]. top_conc = 5, # bot_conc: float, optional # Concentration of the lower boundary, or concentration of the # incoming fluid [ML-3]. bot_conc = 0 ) ml$solutes ############################################################################### # 5 Add atmospheric boundary condition ############################################################################### atmosphere$cBot <- 0.0 atmosphere$cTop <- 0.0 atmosphere$cTop[1] <- 1 head(atmosphere) #reticulate::py_help(object = ml$add_atmospheric_bc) ml$add_atmospheric_bc( # atmosphere: pandas.DataFrame # Pandas DataFrame with at least the following columns: tAtm, # Prec, rSoil, rRoot, hCritA, rB, hB, hT, tTop, tBot, and Ampl. atmosphere = atmosphere, # ldailyvar: bool, optional # True if HYDRUS-1D is to generate daily variations in evaporation # and transpiration. False otherwise. ldailyvar = FALSE, # lsinusvar: bool, optional # True if HYDRUS-1D is to generate sinusoidal variations in # precipitation. False otherwise. lsinusvar = FALSE, # llai: bool, optional # Boolean indicating that potential evapotranspiration is # to be divided into potential evaporation and potential # transpiration using eq. (2.75) of the manual. llai = FALSE, # rextinct: float, optional # A constant for the radiation extinction by the canopy # (rExtinct=0.463) [-]. only used when lLai is True. rextinct = 0.463, # hcrits: float, optional # Maximum allowed pressure head at the soil surface [L]. Default is # 1e+30. hcrits = 0, # tatm: float, optional # Time for which the i-th data record is provided [T]. tatm = 0, # prec: float, optional # Precipitation rate [LT-1] (in absolute value). prec = 0, # rsoil: float, optional # Potential evaporation rate [LT-1] (in absolute value). rSoil(i) is # interpreted as KodTop when a time variable Dirichlet or Neumann # boundary condition is specified. rsoil = 0, # rroot: float, optional # Potential transpiration rate [LT-1] (in absolute value). rroot = 0, # hcrita: float, optional # Absolute value of the minimum allowed pressure head at the soil # surface [L]. hcrita = 100000.0, # rb: float, optional # Bottom flux [LT-1] (set equal to 0 if KodBot is positive, or if # one of the logical variables qGWLF, FreeD or SeepF is .true.). rb = 0, # hb: float, optional # Groundwater level [L], or any other prescribed pressure head # boundary condition as indicated by a positive value of KodBot # (set equal to 0 if KodBot is negative, or if one of the logical # variables qGWLF, FreeD or SeepF is .true.). hb = 0, # ht: float, optional # Prescribed pressure head [L] at the surface (set equal to 0 if # KodBot is negative). ht=0, # ttop: float, optional # Soil surface temperature [oC] (omit if both lTemp and lChem are # equal to .false.). ttop=0, # tbot: float, optional # Soil temperature at the bottom of the soil profile [oC] (omit if # both lTemp and lChem are equal to .false., set equal to zero if # kBotT=0). tbot=0, # ampl: float, optional # Temperature amplitude at the soil surface [K] (omit if both lTemp # and lChem are equal to .false.). ampl=0 ) ml$atmosphere ml$write_input()
ml$simulate()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.