Nothing
#
# Copyright 2013, 2014, 2020, 2021 Guy Munhoven
#
# This file is part of SolveSAPHE v. 2
# SolveSAPHE is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# SolveSAPHE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with SolveSAPHE. If not, see <http://www.gnu.org/licenses/>.
#
# General option
SAFEGEOMEAN_INIT = FALSE
# General parameters
# Threshold relative difference between successive iterates
# (convergence criterion)
pp_rdel_ah_target = 1.E-08
# NaN for [H^+] results
pp_hnan = -1.
#===============================================================================
HINFSUPINI <- function (p_alktot, p_dicvar, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
p_dicsel, api, p_hini)
#===============================================================================
{
#--------------------#
# Argument variables #
#--------------------#
# p_alktot : Alkalinity total
# p_dicvar : Carbonate value
# p_bortot : Dissolved bore total
# p_po4tot : Dissolved Phosphate total
# p_siltot : Dissolved Silicium total
# p_nh4tot : Dissolved Ammonium total
# p_h2stot : Dissolved Hydrogene sulfide total
# p_so4tot : Dissolved Sulfate total
# p_flutot : Dissolved Fluor total
# p_dicsel : Carbonate variable selector (default = DIC)
# p_dicsel = "DIC": p_dicvar = DIC
# p_dicsel = "CO2": p_dicvar = [CO2*]
# p_dicsel = "HCO3": p_dicvar = [HCO3-]
# p_dicsel = "CO3": p_dicvar = [CO3--]
# api : Pi factors of dissociation constants
# p_hini : Initial value of pH (optionnal), 1 or 2 element long array
#-------------------------------------------------------------------------------
result = NULL
if (p_dicsel == "DIC")
{
result = HINFSUPINI_DIC(p_alktot, p_dicvar, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
}
else if (p_dicsel == "CO2")
{
result = HINFSUPINI_CO2(p_alktot, p_dicvar, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
}
else if (p_dicsel == "HCO3")
{
result = HINFSUPINI_HCO3(p_alktot, p_dicvar, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
}
else if (p_dicsel == "CO3")
{
result = HINFSUPINI_CO3(p_alktot, p_dicvar, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
}
if (is.null(result))
{
k_nroots = 0
p_hinf = pp_hnan
p_hsup = pp_hnan
p_hini = pp_hnan
result = list(p_hinf=p_hinf, p_hsup=p_hsup, p_hini=p_hini, k_nroots=k_nroots)
}
return (result)
}
#===============================================================================
HINFSUPINI_DIC <- function (p_alktot, p_dictot, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
#===============================================================================
# Subroutine provides
# - the infimum and the supremum of Alk_{nW}, obtained from ANW_INFSUP
# - a valid initial value for any solver, already brought within brackets.
# If the given p_hini is not equal to pp_hnan, the calculation of h_ini from
# the ACB approximation is skipped and the provided value is only brought into
# [p_hinf, p_hsup] if necessary.
{
#--------------------#
# Argument variables #
#--------------------#
# p_alktot : Alkalinity total
# p_dictot : DIC total
# p_bortot : Dissolved bore total
# p_po4tot : Dissolved Phosphate total
# p_siltot : Dissolved Silicium total
# p_nh4tot : Dissolved Ammonium total
# p_h2stot : Dissolved Hydrogene sulfide total
# p_so4tot : Dissolved Sulfate total
# p_flutot : Dissolved Fluor total
# api : Pi factors of dissociation constants
# p_hini : Initial value of pH (optionnal)
#-------------------------------------------------------------------------------
k_nroots = 1
result = anw_infsup(p_dictot, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot)
zalknw_inf = result[1]
zalknw_sup = result[2]
za1 = p_alktot - zalknw_inf
zd = za1^2 + 4.*api$api1_wat/api$aphscale
if (za1 > 0) {
z_hinf = 2.*api$api1_wat / ( za1 + sqrt(zd) )
} else {
z_hinf = api$aphscale*(-za1 + sqrt(zd) ) / 2.
}
za1 = p_alktot - zalknw_sup
zd = za1^2 + 4.*api$api1_wat/api$aphscale
if (za1 > 0) {
z_hsup = 2.*api$api1_wat / ( za1 + sqrt(zd) )
} else {
z_hsup = api$aphscale * (-za1 + sqrt(zd) ) / 2.
}
if (SAFEGEOMEAN_INIT)
{
if ( (p_hini[1] == pp_hnan) # request to calculate H_ini
|| (p_hini[1] < z_hinf) # the given H_ini is too low
|| (p_hini[1] > z_hsup) ) # the given H_ini too high
{
p_hini[1] = sqrt(z_hsup*z_hinf)
}
}
else
{
if (p_hini[1] == pp_hnan) { # request to calculate H_ini
if (DEBUG_PHSOLVERS)
{
print ('[HINFSUPINI] using hini_ACB_DIC to set H_ini')
}
p_hini[1] = hini_ACB_DIC(p_alktot, p_dictot, p_bortot, z_hinf, z_hsup, api)
}
else
{
# H_ini given: only bring it into [z_hinf, z_hsup]
p_hini[1] = max(min(z_hsup, p_hini[1]), z_hinf)
}
}
p_hinf = c(z_hinf, pp_hnan)
p_hsup = c(z_hsup, pp_hnan)
p_hini[2] = pp_hnan
return ( list(p_hinf=p_hinf, p_hsup=p_hsup, p_hini=p_hini, k_nroots=k_nroots))
}
#===============================================================================
HINFSUPINI_CO2 <- function (p_alktot, p_co2, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
#===============================================================================
# Subroutine provides
# - the infimum and the supremum of Alk_{nW}, obtained from ANW_INFSUP
# - a valid initial value for any solver, already brought within brackets.
# If the given p_hini is not equal to pp_hnan, the calculation of h_ini from
# the ACB approximation is skipped and the provided value is only brought into
# [p_hinf, p_hsup] if necessary.
{
#--------------------#
# Argument variables #
#--------------------#
# p_alktot : Alkalinity total
# p_co2 : [CO2*] concentration
# p_bortot : Dissolved bore total
# p_po4tot : Dissolved Phosphate total
# p_siltot : Dissolved Silicium total
# p_nh4tot : Dissolved Ammonium total
# p_h2stot : Dissolved Hydrogene sulfide total
# p_so4tot : Dissolved Sulfate total
# p_flutot : Dissolved Fluor total
# api : Pi factors of dissociation constants
# p_hini : Initial value of pH (optionnal)
#-------------------------------------------------------------------------------
k_nroots = 1
# Get Alk_nWCinf and Alk_nWCsup:
z_dictot = 0. # set C_T to 0 an call ANW_INFSUP
result = anw_infsup(z_dictot, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot)
zalknwc_inf = result[1]
zalknwc_sup = result[2]
# Lower root bracket
# would normally require the solution of a cubic equation. It is
# nevertheless sufficient to chose the location of the minimum of the
# cubic (written such that a_3 > 0).
# Coefficients of cubic polynomial
za3 = 1./api$aphscale
za2 = (p_alktot - zalknwc_inf)
za1 = -(api$api1_dic * p_co2 + api$api1_wat)
# za0 = -2. * api$api2_dic * p_dicvar
# The derivative has as constant term za1 < 0
# => one positive and one negative root.
# Determine the positive one,
# i.e., the greater one of the two
zd = za2^2 - 3.*za1*za3
if (za2 > 0) {
z_hinf = -za1 / ( za2 + sqrt(zd) )
} else {
z_hinf = (-za2 + sqrt(zd) ) / (3.*za3)
}
# Upper root bracket:
# would normally require the solution of a cubic equation.
# It is nevertheless sufficient to chose the greater of the roots of
# the quadratic expansion around the minimum of the cubic (written
# such that a_3 > 0)
# Coefficients of cubic polynomial
za3 = 1./api$aphscale
za2 = (p_alktot - zalknwc_sup)
za1 = -(api$api1_dic*p_co2 + api$api1_wat)
za0 = -2. * api$api2_dic * p_co2
# The derivative has as constant term za1 < 0
# => one positive and one negative root.
# Determine the positive one,
# i.e., the greater one of the two
zd = za2^2 - 3.*za1*za3
zsqrtd = sqrt(zd)
if (za2 > 0) {
z_hcmin = -za1 / ( za2 + zsqrtd )
} else {
z_hcmin = (-za2 + zsqrtd ) / (3.*za3)
}
z_hsup = z_hcmin + sqrt(-(za0 + z_hcmin*(za1 + z_hcmin*(za2 + z_hcmin*za3)))/zsqrtd)
if (SAFEGEOMEAN_INIT)
{
if ( (p_hini[1] == pp_hnan) # request to calculate H_ini
|| (p_hini[1] < z_hinf) # the given H_ini is too low
|| (p_hini[1] > z_hsup) ) # the given H_ini too high
{
p_hini[1] = sqrt(z_hsup*z_hinf)
}
}
else
{
if (p_hini[1] == pp_hnan) { # request to calculate H_ini
if (DEBUG_PHSOLVERS)
{
print ('[HINFSUPINI] using hini_ACB_CO2 to set H_ini')
}
p_hini[1] = hini_ACB_CO2(p_alktot, p_co2, p_bortot, z_hinf, z_hsup, api)
}
else
{
# H_ini given: only bring it into [z_hinf, z_hsup]
p_hini[1] = max(min(z_hsup, p_hini[1]), z_hinf)
}
}
p_hinf = c(z_hinf, pp_hnan)
p_hsup = c(z_hsup, pp_hnan)
p_hini[2] = pp_hnan
return ( list(p_hinf=p_hinf, p_hsup=p_hsup, p_hini=p_hini, k_nroots=k_nroots))
}
#===============================================================================
HINFSUPINI_HCO3 <- function (p_alktot, p_hco3, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
#===============================================================================
# Subroutine provides
# - the infimum and the supremum of Alk_{nW}, obtained from ANW_INFSUP
# - a valid initial value for any solver, already brought within brackets.
# If the given p_hini is not equal to pp_hnan, the calculation of h_ini from
# the ACB approximation is skipped and the provided value is only brought into
# [p_hinf, p_hsup] if necessary.
{
#--------------------#
# Argument variables #
#--------------------#
# p_alktot : Alkalinity total
# p_hco3 : [HCO3-] concentration
# p_bortot : Dissolved bore total
# p_po4tot : Dissolved Phosphate total
# p_siltot : Dissolved Silicium total
# p_nh4tot : Dissolved Ammonium total
# p_h2stot : Dissolved Hydrogene sulfide total
# p_so4tot : Dissolved Sulfate total
# p_flutot : Dissolved Fluor total
# api : Pi factors of dissociation constants
# p_hini : Initial value of pH (optionnal)
#-------------------------------------------------------------------------------
k_nroots = 1
# Get Alk_nWCinf and Alk_nWCsup:
z_dictot = 0. # set C_T to 0 an call ANW_INFSUP
result = anw_infsup(z_dictot, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot)
zalknwc_inf = result[1]
zalknwc_sup = result[2]
# za2 = 1./api$aphscale
za1 = p_alktot - zalknwc_inf - p_hco3
za0 = -(2.*(api$api2_dic/api$api1_dic)*p_hco3 + api$api1_wat)
zd = za1^2 - 4. * za0 / api$aphscale
if (za1 > 0) {
z_hinf = -2. * za0 / ( za1 + sqrt(zd) )
} else {
z_hinf = api$aphscale*(-za1 + sqrt(zd) ) / 2.
}
# za2 = 1./api$aphscale
za1 = p_alktot - zalknwc_sup - p_hco3
# za0 = -(2.*(api$api2_dic/api$api1_dic)*p_hco3 + api$api1_wat)
zd = za1^2 - 4. * za0 / api$aphscale
if (za1 > 0) {
z_hsup = -2. * za0 / ( za1 + sqrt(zd) )
} else {
z_hsup = api$aphscale * (-za1 + sqrt(zd) ) / 2.
}
if (SAFEGEOMEAN_INIT)
{
if ( (p_hini[1] == pp_hnan) # request to calculate H_ini
|| (p_hini[1] < z_hinf) # the given H_ini is too low
|| (p_hini[1] > z_hsup) ) # the given H_ini too high
{
p_hini[1] = sqrt(z_hsup*z_hinf)
}
}
else
{
if (p_hini[1] == pp_hnan) { # request to calculate H_ini
if (DEBUG_PHSOLVERS)
{
print ('[HINFSUPINI] using hini_ACBW_HCO3 to set H_ini')
}
p_hini[1] = hini_ACBW_HCO3(p_alktot, p_hco3, p_bortot, z_hinf, z_hsup, api)
}
else
{
# H_ini given: only bring it into [z_hinf, z_hsup]
p_hini[1] = max(min(z_hsup, p_hini[1]), z_hinf)
}
}
p_hinf = c(z_hinf, pp_hnan)
p_hsup = c(z_hsup, pp_hnan)
p_hini[2] = pp_hnan
return ( list(p_hinf=p_hinf, p_hsup=p_hsup, p_hini=p_hini, k_nroots=k_nroots))
}
#===============================================================================
HINFSUPINI_CO3 <- function (p_alktot, p_co3, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot,
api, p_hini)
#===============================================================================
# Subroutine provides
# - the infimum and the supremum of Alk_{nW}, obtained from ANW_INFSUP
# - a valid initial value for any solver, already brought within brackets.
# If the given p_hini is not equal to pp_hnan, the calculation of h_ini from
# the ACB approximation is skipped and the provided value is only brought into
# [infimum, supremum] if necessary.
{
#--------------------#
# Argument variables #
#--------------------#
# p_alktot : Alkalinity total
# p_co3 : [CO3--] concentration
# p_bortot : Dissolved bore total
# p_po4tot : Dissolved Phosphate total
# p_siltot : Dissolved Silicium total
# p_nh4tot : Dissolved Ammonium total
# p_h2stot : Dissolved Hydrogene sulfide total
# p_so4tot : Dissolved Sulfate total
# p_flutot : Dissolved Fluor total
# api : Pi factors of dissociation constants
# p_hini : Initial value of pH (optionnal), 2 element long array
#-------------------------------------------------------------------------------
z_dictot = 0.
result = anw_infsup(z_dictot, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot, api)
zalknwc_inf = result[1]
zalknwc_sup = result[2]
zalknwc_asympt_coeff = result[3]
z_gamma = p_co3 * (api$api1_dic/api$api2_dic)- 1./api$aphscale
if (z_gamma < 0.) { #-----------------------------------------------------
#-----------------------------------------------------
#-----------------------------------------------------
k_nroots = 1
# H_inf[1] = abscissa of P_UL,
# which is the positive root of
# the following quadratic
za2 = z_gamma
za1 = - (p_alktot - (p_co3 + p_co3) - zalknwc_inf)
za0 = api$api1_wat
zd = za1^2 - 4. * api$api1_wat * z_gamma
if (za1 > 0) {
z_hinf1 = -( za1 + sqrt(zd) ) / (za2 + za2)
} else {
z_hinf1 = -(za0 + za0) / ( za1 - sqrt(zd) )
}
# H_sup[1] = abscissa of P_LL,
# which is the positive root of
# the following quadratic
za2 = z_gamma
za1 = - (p_alktot - (p_co3 + p_co3) - zalknwc_sup)
za0 = api$api1_wat
zd = za1^2 - 4. * za0 * za2
if (za1 > 0.) {
z_hsup1 = -(za0 + za0) / ( za1 - sqrt(zd) )
} else {
z_hsup1 = -( za1 + sqrt(zd) ) / (za2 + za2)
}
z_hinf2 = pp_hnan
z_hsup2 = pp_hnan
}
else if (z_gamma > 0.) { #-------------------------------------------------
#-------------------------------------------------
#-------------------------------------------------
# 0, 1, or 2 roots ?
z_hmin = sqrt(api$api1_wat/z_gamma)
z_lmin = 2. * sqrt(z_gamma * api$api1_wat) + (p_co3 + p_co3)
zalknwc_hmin = ANW (z_hmin,
p_co3, p_bortot,
p_po4tot, p_siltot,
p_nh4tot, p_h2stot,
p_so4tot, p_flutot, "CO3", api)
if (p_alktot >= (z_lmin + zalknwc_hmin))
{
k_nroots = 2
# H_inf[1] = abscissa of P_UL,
# which is the lower (positive)
# root of the following quadratic;
# H_sup[2] = abscissa of P_UR,
# which is the greater (positive)
# root of the following quadratic;
za2 = z_gamma
za1 = -(p_alktot - (p_co3 + p_co3) - zalknwc_inf)
za0 = api$api1_wat
zd = za1^2 - 4. * za0 * za2
if (za1 > 0) {
z_hinf1 = -( za1 + sqrt(zd) ) / (za2 + za2)
} else {
z_hinf1 = -(za0 + za0) / ( za1 - sqrt(zd) )
}
if (za1 > 0) {
z_hsup2 = -(za0 + za0) / ( za1 + sqrt(zd) )
} else {
z_hsup2 = (-za1 + sqrt(zd) ) / (za2 + za2)
}
if (p_alktot > (z_lmin + zalknwc_sup)) {
# H_sup[1] = abscissa of P_LL,
# which is the lower (positive)
# root of the following quadratic;
# H_inf[2] = abscissa of P_LR,
# which is the greater (positive)
# root of the following quadratic;
za2 = z_gamma
za1 = -(p_alktot - (p_co3 + p_co3) - zalknwc_sup)
za0 = api$api1_wat
zd = za1^2 - 4. * za0 * za2
if (za1 > 0) {
z_hsup1 = -( za1 + sqrt(zd) ) / (za2 + za2)
} else {
z_hsup1 = -(za0 + za0) / ( za1 - sqrt(zd) )
}
if (za1 > 0) {
z_hinf2 = -(za0 + za0) / ( za1 + sqrt(zd) )
} else {
z_hinf2 = (-za1 + sqrt(zd) ) / (za2 + za2)
}
} else {
z_hsup1 = z_hmin
z_hinf2 = z_hmin
}
}
else if (p_alktot <= (z_lmin + zalknwc_inf))
{
k_nroots = 0
z_hinf1 = pp_hnan
z_hsup1 = pp_hnan
z_hinf2 = pp_hnan
z_hsup2 = pp_hnan
}
else
{
# Alk_T is in the intermediate region
# where we need to determine H_tan and Alk_tan
# Brackets of the H_tan:
# (H_min, A_min) and (H_UR, A_UR)
# H_UR = abscissa of P_UR,
# which is the greater (positive)
# root of the following quadratic:
# If Alk_T > Alk_tan, H_UR will also be
# H_sup[2]
za2 = z_gamma
za1 = -(p_alktot - (p_co3 + p_co3) - zalknwc_inf)
za0 = api$api1_wat
zd = za1^2 - 4. * za0 * za2
if (za1 > 0) {
z_hsup2 = -(za0 + za0) / ( za1 + sqrt(zd) )
} else {
z_hsup2 = (-za1 + sqrt(zd) ) / (za2 + za2)
}
z_tol = z_hmin * pp_rdel_ah_target # We assume that H_min is
# of the same order of magnitude
# as H_tan for fixing the absolute
# tolerance on H_tan
# z_atan = ALK_TAN(z_hmin, z_hsup2, z_tol, z_htan)
f <- function (z_h) equation_at (0., z_h, p_co3, p_bortot,
p_po4tot, p_siltot, p_nh4tot, p_h2stot, p_so4tot, p_flutot, "CO3", api)
# Use Brent algorithm to find the minimum of f(z_h)
xmin <- stats::optimize(f, c(z_hmin, z_hsup2), tol = z_tol)
z_htan = xmin$minimum
z_atan = xmin$objective
if (p_alktot < z_atan) {
k_nroots = 0
z_hinf1 = pp_hnan
z_hsup1 = pp_hnan
z_hinf2 = pp_hnan
z_hsup2 = pp_hnan
}
else if (p_alktot > z_atan)
{
k_nroots = 2
# H_inf[1] = abscissa of P_UL,
# which is the lower (positive)
# root of the following quadratic;
# H_sup[2] = abscissa of P_UR, which
# has already served as a bracket for H_tan
za2 = z_gamma
za1 = -(p_alktot - (p_co3 + p_co3) - zalknwc_inf)
za0 = api$api1_wat
zd = za1*za1 - 4. * za2 * za0
if (za1 > 0) {
z_hinf1 = -(za0 + za0) / ( za1 - sqrt(zd) )
} else {
z_hinf1 = -( za1 + sqrt(zd) ) / (za2 + za2)
}
z_hsup1 = z_htan
z_hinf2 = z_htan
}
else
{
k_nroots = 1
z_hinf1 = z_htan
z_hsup1 = z_htan
z_hinf2 = pp_hnan
z_hsup2 = pp_hnan
}
}
}
else { # z_gamma = 0 -----------------------------------------------------
# -----------------------------------------------------
# -----------------------------------------------------
zdiff = p_alktot - (p_co3 + p_co3) - zalknwc_inf
if (zdiff > 0) {
k_nroots = 1
z_hinf1 = api$api1_wat / zdiff
z_hsup1 = (api$api1_wat + zalknwc_asympt_coeff) / zdiff
z_hinf2 = pp_hnan
z_hsup2 = pp_hnan
} else {
k_nroots = 0
z_hinf1 = pp_hnan
z_hsup1 = pp_hnan
z_hinf2 = pp_hnan
z_hsup2 = pp_hnan
}
} #-----------------------------------------------------------------
#-----------------------------------------------------------------
#-----------------------------------------------------------------
z_hinf = c(z_hinf1, z_hinf2)
z_hsup = c(z_hsup1, z_hsup2)
if (SAFEGEOMEAN_INIT)
{
if ( (p_hini[1] == pp_hnan) # request to calculate H_ini
|| (p_hini[1] < z_hinf1) # the given H_ini is too low
|| (p_hini[1] > z_hsup1) ) # the given H_ini too high
{
p_hini[1] = sqrt(z_hsup1*z_hinf1)
}
if ( (p_hini[2] == pp_hnan) # request to calculate H_ini
|| (p_hini[2] < z_hinf1) # the given H_ini is too low
|| (p_hini[2] > z_hsup1) ) # the given H_ini too high
{
p_hini[2] = sqrt(z_hsup2*z_hinf2)
}
}
else
{
z_hini = hini_ACBW_CO3(p_alktot, p_co3, p_bortot, z_hinf, z_hsup, k_nroots, api)
if (p_hini[1] == pp_hnan) # request to calculate H_ini[1]
{
p_hini[1] = z_hini[1]
}
else
{
# H_ini[1] given: only bring it into [z_hinf1, z_hsup1]
p_hini[1] = max(min(z_hsup1, p_hini[1]), z_hinf1)
}
if (p_hini[2] == pp_hnan) # request to calculate H_ini[1]
{
p_hini[2] = z_hini[2]
}
else
{
# H_ini[2] given: only bring it into [z_hinf2, z_hsup2]
p_hini[2] = max(min(z_hsup2, p_hini[2]), z_hinf2)
}
}
p_hinf = z_hinf
p_hsup = z_hsup
return ( list(p_hinf=p_hinf, p_hsup=p_hsup, p_hini=p_hini, k_nroots=k_nroots))
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.