Public API
General
These are the functions used to run the simulation. Note that an object of type SimulationOptions
is needed to call them.
BoreholeNetworksSimulator.initialize
— Functioninitialize(options::SimulationOptions)
Precompute the objects of each TimeSuperpositionMethod
that can be computed ahead of time and return the SimulationContainers
of the required size.
BoreholeNetworksSimulator.simulate!
— Functionsimulate!(;options::SimulationOptions, operator, containers::SimulationContainers)
Run the simulation defined by options
. At the end of simulation, containers.X
will contain the results. containers
should be the output of initialize
.
operator
should be a function that returns a BoreholeOperation
and with signature operator(step, options, X)
:
step::Int
is the time step.options
is theSimulationOptions
object passed tosimulate!
.X
is the matrixcontainers.X
containingTin
,Tout
,Tb
, andq
for each borehole.
BoreholeNetworksSimulator.simulate_steps!
— Functionsimulate_steps!(;n, initial_step = nothing, options::SimulationOptions, operator, containers::SimulationContainers)
Similar to simulate!
, but only run n
steps, starting at the step initial_step
, of the simulation defined by options
. If initial_step
is not specified, the index of first zero column of containers.X
is taken as the initial step.
Note that an array of BoreholeNetwork
containing all the configurations allowed during the simulation must be specified in SimulationOptions
. On the other hand, BoreholeOperation
is an object that needs to be returned by an object subtype of [Operator](@ref)
at each time step , representing the dynamical changes in the operation. See Basic tutorial for more details.
BoreholeNetworksSimulator.BoreholeNetwork
— TypeBoreholeNetwork(
graph::SimpleDiGraph = SimpleDiGraph()
)
Represents the network of boreholes with a directed graph graph
, whose edges represent the flow of fluid. The graph
is expected to have number of vertices Nb+2
, where Nb
is the number of boreholes in the borefield. Vertexs number Nb+1
and Nb+2
represent the mass flow source and sink, respectively. All branches are expected to be connected to the source at the beggining and to the sink at the end.
Convenience constructors
BoreholeNetwork(n::Int)
Create a network of n
boreholes (and the source and sink) without any connections.
all_parallel_network(n::Int)
Create a network of n
boreholes connected in parallel.
all_series_network(n::Int)
Create a network of n
boreholes connected in series.
Some relevant network related functions:
BoreholeNetworksSimulator.boreholes_in_branch
— Functionboreholes_in_branch(n::BoreholeNetwork; first_bh::Int)
Return all the boreholes in the branch that starts by borehole first_bh
.
BoreholeNetworksSimulator.first_bhs_in_branch
— Functionfirst_bhs_in_branch(network::BoreholeNetwork)
Return the first borehole in each branch of the borefield.
BoreholeNetworksSimulator.source
— Functionsource(network::BoreholeNetwork)
Return the vertex index of the source.
BoreholeNetworksSimulator.sink
— Functionsink(network::BoreholeNetwork)
Return the vertex index of the sink.
BoreholeNetworksSimulator.connect!
— Functionconnect!(network::BoreholeNetwork, i::Int, j::Int)
Create a flow from borehole i
to borehole j
.
BoreholeNetworksSimulator.connect_to_source!
— Functionconnect_to_source!(network::BoreholeNetwork, i::Int)
Create a connection injecting mass flow to borehole i
.
connect_to_source!(network::BoreholeNetwork, I::Vector{Int})
Vector version of connecttosource!.
BoreholeNetworksSimulator.connect_to_sink!
— Functionconnect_to_sink!(network::BoreholeNetwork, i::Int)
Create a connection extracting mass flow from borehole i
.
connect_to_sink!(network::BoreholeNetwork, I::Vector{Int})
Vector version of connecttosink!.
BoreholeNetworksSimulator.connect_in_series!
— Functionconnect_in_series!(network::BoreholeNetwork, I::Vector{Int})
Connect all the boreholes in I
, in order.
BoreholeNetworksSimulator.connect_in_parallel!
— Functionconnect_in_parallel!(network::BoreholeNetwork, j::Int, I::Vector{Int})
Make a connection from borehole j
to each of the boreholes in I
.
BoreholeNetworksSimulator.BoreholeOperation
— TypeBoreholeOperation{T <: Number}(
valves::Dict{Int, Valve{T}}
source_mass_flow::T
network::BoreholeNetwork
)
Representation of the a state of operation of the borefield.
Arguments
valves
: A dicitonary specifying the divergences of the network. Each key is the borehole where the divergence occurs, and its corresponding value is aValve
object, describing the behaviour of the divergence.source_mass_flow
: The total amount of mass flow injected into all branches.network
: The representation of the pipe layout of the borefield, including direction of flow.
Convenience constructors
BoreholeOperation(;network::BoreholeNetwork, mass_flows::Vector{T})
Builds the operation corresponding to network
sending mass flow mass_flows[i]
in each branch identical
. This method takes care of the initial valve from the source to the start of each branch.
BoreholeNetworksSimulator.Valve
— TypeValve{T <: Number}(
split::Dict{Int, T}
)
Models the behaviour of the fluid at pipe divergences. split
is a dicitonary representing the divergence. Its keys represent the boreholes where the flow splits and its values are the proportion of flow going to each borehole.
Valve creation:
BoreholeNetworksSimulator.valve
— Functionvalve(nodes::Vector{Int}, weights::Vector{T})
Return a Valve
that splits the flow to each borehole nodes[i]
in the proportion weights[i]
.
BoreholeNetworksSimulator.equal_valve
— Functionequal_valve(nodes::Vector{Int})
Return a Valve
that splits the flow equally to all the boreholes nodes
in the divergence.
BoreholeNetworksSimulator.absolute_valve
— Functionabsolute_valve(nodes::Vector{Int}, mass_flows::Vector{T})
Return a Valve
that splits the flow such that each borehole nodes[i]
receives an absolute amount of mass flow equal to mass_flows[i]
.
BoreholeNetworksSimulator.Operator
— Typeabstract type Operator
Interface for operation strategies.
Required functions:
operate(::Operator, step, options, X)
The implementation of operate
must return an instance of BoreholeOperation
, specifying the network topology and the mass flows per branch for the current time step. step
is the current time step, options
contains the provided simulation options and X
contains the time series up to the time step step-1
of the inlet fluid temperature, the outlet fluid temperature, the wall temperature and the heat extraction rate, for each borehole in the borefield. To get Tfin
, Tfout
, Tb
, and q
from X
, use the functions extract_Tfin
, extract_Tfout
, extract_Tb
, extract_q
, or get them manually at the indices [1:2:2Nb, :], [2:2:2Nb, :], [2Nb+1:3Nb, :], [3Nb+1:end, :], respectively.
Prewritten operator strategies
BoreholeNetworksSimulator.ConstantOperator
— TypeConstantOperator{T <: Number} <: Operator (
valves::Dict{Int, Valve{T}} = Dict{Int, Valve{Float64}}()
mass_flow::T
)
Constant operation strategy. Its implementation of operate
is: operate(op::ConstantOperator, step, options, X) = BoreholeOperation(op.valves, op.mass_flow, options.configurations[1])
Convenience constructors
ConstantOperator(network::BoreholeNetwork; mass_flows)
Builds the initial valve and total source mass flow needed to have mass flow equal to mass_flows[i]
in branch i
, according to the network network
.
Simulation Options
The available options for the simulation are specified through a SimulationOptions
object. This needs to be passed to the initialize
and simulate!
functions. The options are modular: each particular option can be chosen independently of the others, allowing for a wide range of possible simulations. Note that in some particular cases there might be some incompatibilities between options or non-implemented interactions. In those cases, an error will appear explaining the reason.
BoreholeNetworksSimulator.SimulationOptions
— Typestruct SimulationOptions{
N <: Number,
Tol <: Number,
TSM <: TimeSuperpositionMethod,
C <: Constraint,
B <: Borefield,
M <: Medium,
BC <: BoundaryCondition,
A <: Approximation,
F <: Fluid
}(
method::TSM
constraint::C
borefield::B
medium::M
boundary_condition::BoundaryCondition = DirichletBoundaryCondition()
approximation::A = MeanApproximation()
fluid::Fluid{N} = Fluid(cpf=4182., name="INCOMP::MEA-20%")
configurations::Vector{BoreholeNetwork}
Δt
Nt::Int
atol::Tol = 0.
rtol::Tol = sqrt(eps())
)
Specifies all the options for the simulation.
method
: time superposition method used to compute the response. Available options:ConvolutionMethod
,NonHistoryMethod
.constraint
: constraint that the system must satisfy. Can be variable with time. Available options:HeatLoadConstraint
,InletTempConstraint
,TotalHeatLoadConstraint
.borefield
: describes the geometrical properties and the boreholes of the borefield on which the simulation will be performed. Available options:EqualBoreholesBorefield
.medium
: properties of the ground where theborefield
is places. Available options:GroundMedium
,FlowInPorousMedium
.boundary_condition
: boundary condition of the domain where the simulation is performed. Available options:NoBoundary
,DirichletBoundaryCondition
,NeumannBoundaryCondition
.approximation
: determines how the approximate value for each segment is computed. Available options:MeanApproximation
,MidPointApproximation
.fluid
: properties of the fluid flowing through the hydraulic system.configurations
: possible hydraulic topologies possible in the system, including reverse flow.Δt
: time step used in the simulation.Nt
: total amount of time steps of the simulation.atol
: absolute tolerance used for the adaptive integration methods.rtol
: relative tolerance used for the adaptive integration methods.
The several options are listed below:
Fluid
Models the fluid used in the hydraulic system.
BoreholeNetworksSimulator.Fluid
— Typeabstract type Fluid end
Interface for fluids.
Required functions:
cpf(::Fluid)
: Return the scpecific heat capacity of the fluid.thermophysical_properties(::Fluid, T)
: Return theμ
,ρ
,cp
, andk
of the fluid at temperatureT
.
Options
BoreholeNetworksSimulator.Water
— TypeWater <: Fluid (
stored_properties::ThermophysicalProperties{Float64}
)
Models water.
To initialize, use the convenience method: function Water() that will automatically compute stored_properties
.
BoreholeNetworksSimulator.EthanolMix
— TypeEthanolMix <: Fluid (
stored_properties::ThermophysicalProperties{Float64}
)
Models a 20% ethanol and water mix.
To initialize, use the convenience method: function EthanolMix() that will automatically compute stored_properties
.
Medium
Models the underground medium through which the heat will transfer between boreholes.
BoreholeNetworksSimulator.Medium
— Typeabstract type Medium
Interface for mediums.
Required functions:
get_λ(::Medium)
: Return the thermal conductivity of the medium.get_α(::Medium)
: Return the thermal diffusivity of the medium.get_T0(::Medium)
: Return the initial temperature of the medium.
Options
BoreholeNetworksSimulator.GroundMedium
— TypeGroundMedium{T <: Real} <: Medium @deftype T
Model pure conduction in the ground.
Arguments
λ = 3.
: ground conductivityα = 1e-6
: ground thermal diffusivityC = λ/α
: ground medium capacityT0 = 0.
: initial ground temperature
BoreholeNetworksSimulator.FlowInPorousMedium
— TypeFlowInPorousMedium{T <: Real} <: Medium @deftype T
Model a porous ground with a water flow.
Arguments
λw = 0.6
: water thermal conductivityλs = 2.
: ground thermal conductivityCw = 4.18*1e6
:water thermal capacityCs = 1.7*1e6
: ground thermal capacityθ = 0.
: angle of Darcy velocityΦ = 0.2
: porosityλ = λs * (1-Φ) + λw*Φ
: porous medium conductivityC = Cs * (1-Φ) + Cw*Φ
: porous medium capacityα = λ/C
: porous medium thermal diffusivityux_in_meterperday = 1e-2
: groundwater speed along the flow coordinateux = ux_in_meterperday/(3600*24)
: groundwater speed in m/svt = ux * Cw/C
: porous medium darcy velocityT0 = 0.
: initial ground temperature
Borefield
Models the geometry of the borefield.
BoreholeNetworksSimulator.Borefield
— Typeabstract type Borefield
Interface for borefields.
Required functions
n_boreholes(::Borefield)
: Return the amount of boreholes present in the borefield.get_H(::Borefield, i)
: Return the length of boreholei
.get_rb(::Borefield, i)
: Return the radius of boreholei
.segment_coordinates(::Borefield)
: Return a vector with the coordinates of each segment.internal_model_coeffs!(M, ::Borefield, medium, operation, fluid)
: Compute inplace inM
the coefficients corresponding to the internal model equations, given themedium
,fluid
andoperation
in use in the system. Note thatM
is only a slice ofNb
(number of boreholes) rows, provided as aview
.internal_model_b!(b, ::Borefield)
: Compute inplace inb
the independent terms corresponding to the internal model equations. Note thatb
is only a vector of lengthNb
(number of boreholes) rows, provided as aview
.
Options
BoreholeNetworksSimulator.EqualBoreholesBorefield
— TypeEqualBoreholesBorefield{T <: Borehole, S <: Number} <: Borefield
EqualBoreholesBorefield(borehole_prototype::T, positions::Vector{Point2{S}}))
Model a borefield with boreholes all identical to the prototype borehole_prototype
, placed at positions
. Note that the length of positions
determines the amount of boreholes in the field.
Borehole
Models the internal heat transfer in the borehole.
BoreholeNetworksSimulator.Borehole
— Typeabstract type Borehole
Interface for boreholes.
Required functions:
get_H(::Borehole)
: Return the length of the borehole.get_D(::Borehole)
: Return the burial depth of the borehole.get_rb(::Borehole)
: Return the radius of the borehole.uniform_Tb_coeffs(::Borehole, λ, mass_flow, Tref, fluid)
: Return the internal model coefficients for the resistance network between the pipes and the wall.
Options
BoreholeNetworksSimulator.SingleUPipeBorehole
— TypeSingleUPipeBorehole{T <: Real} <: Borehole @deftype T
SingleUPipeBorehole(H, D)
Model a borehole with a single U-pipe with burial depth D
and length H
.
Arguments
λg = 2.5
: grout conductivityCg = 2000. * 1550.
: grout capacityαg = λg/Cg
: grout thermal diffusivityrp = 0.02
: pipe radiusλp = 0.42
: pipe material conductivitydpw = 0.0023
: pipe thicknessrpo = rp + dpw
: equivalent pipe radiushp = 725.
: heat transfer coefficient fluid to pipepipe_position::NTuple{2, Tuple{T, T}} = [(0.03, 0.0), (-0.03, 0.0)]
: positions of the downward and upward branches of the pipe. (0, 0) represents the center of the borehole.rb = 0.115/2
: borehole radius
Constraint
Imposes the working conditions and demands of the whole system.
BoreholeNetworksSimulator.Constraint
— Typeabstract type Constraint
Interface for constraints.
Required functions:
constraints_coeffs!(M, ::Constraint, operation::BoreholeOperation)
: Compute inplace inM
the coefficients corresponding to the constraints equations, given the currentoperation.network
. Note thatM
is only a slice ofNbr
(number of branches) rows, provided as aview
.constraints_b!(b, ::Constraint, ::BoreholeOperation, step)
: Compute inplace inb
the independent term corresponding to the constraints equations, given the currentoperation.network
, at the time stepstep
. Note thatb
is only a vector of lengthNbr
(number of branches), provided as aview
.
Options
BoreholeNetworksSimulator.HeatLoadConstraint
— TypeHeatLoadConstraint(Q_tot::Matrix{T}){T <: Number} <: Constraint
Constrain the heat extracted per branch.
The heat constraint Q_tot
must be a Matrix
, whose column i
are the loads per branch at the time step i
. The amount of rows of Q_tot
must equal to the amount of branches specified in BoreholeNetwork
.
BoreholeNetworksSimulator.constant_HeatLoadConstraint
— Functionconstant_HeatLoadConstraint(Q_tot::Vector{T}, Nt) where {T <: Number}
Convenience initializer for HeatLoadConstraint
. It creates a constant heat load constraint through all the Nt
time steps, where Q_tot
are the heat load for each branch.
BoreholeNetworksSimulator.uniform_HeatLoadConstraint
— Functionuniform_HeatLoadConstraint(Q_tot::Vector{T}, Nbr) where {T <: Number}
Convenience initializer for HeatLoadConstraint
. It creates a uniform heat load constraint along all branches, where T_in
are the heat load for each time step.
BoreholeNetworksSimulator.InletTempConstraint
— TypeInletTempConstraint(T_in::Matrix{T}){T <: Number} <: Constraint
Constrain the inlet temperature of the first borehole in each branch.
The inlet temperature T_in
must be a $N_{br} imes N_t$ Matrix
, whose column i
are the inlet temperatures per branch at the time step i
. The amount of rows of T_in
must equal to the amount of branches specified in BoreholeNetwork
.
BoreholeNetworksSimulator.constant_InletTempConstraint
— Functionconstant_InletTempConstraint(T_in::Vector{N}, Nt) where {N <: Number}
Convenience initializer for InletTempConstraint
. It creates a constant inlet temperature constraint through all the Nt
time steps, where T_in
are the inlet temperatures for each branch.
BoreholeNetworksSimulator.uniform_InletTempConstraint
— Functionuniform_InletTempConstraint(T_in::Vector{N}, Nbr) where {N <: Number}
Convenience initializer for InletTempConstraint
. It creates a uniform inlet temperature constraint along all branches, where T_in
are the inlet temperatures for each time step.
Time Superposition Method
Applies methods for time superposition.
BoreholeNetworksSimulator.TimeSuperpositionMethod
— Typeabstract type TimeSuperpositionMethod
Interface for time superposition methods.
Required functions:
method_coeffs!(M, ::TimeSuperpositionMethod, options)
: Compute inplace inM
the coefficients corresponding to the heat transfer equations, givenoptions
. Note thatM
is only a slice ofNbr
(number of branches) rows, provided as aview
.method_b!(b, ::TimeSuperpositionMethod, borefield, medium, step)
: Compute inplace inb
the independent terms corresponding to the heat transfer equations, given themedium
, at the given time stepstep
. Note thatb
is only a vector of lengthNbr
(number of branches) rows, provided as aview
.precompute_auxiliaries!(method::TimeSuperpositionMethod; options)
: Compute inplace inmethod
the auxiliary quantities used in the simulation that can be performed ahead of time.update_auxiliaries!(::TimeSuperpositionMethod, X, borefield, step)
: Update inplace inmethod
the auxiliaries after each time stepstep
.
Options
BoreholeNetworksSimulator.ConvolutionMethod
— TypeConvolutionMethod{T} <: TimeSuperpositionMethod
ConvolutionMethod()
Use the naïve convolution to compute the thermal response between boreholes. It should be initialized without arguments, but it contains the variables:
g
stores the unit response between each pair of boreholes evaluated at each time of the simulation.
It should be precomputed with initialize
.
q
stores the heat extraction in each borehole at each time step. It is filled as the simulation runs.
BoreholeNetworksSimulator.NonHistoryMethod
— TypeNonHistoryMethod{T} <: TimeSuperpositionMethod
NonHistoryMethod()
Use the non-history method to compute the thermal response between boreholes. See A non-history dependent temporal superposition algorithm for the finite line source solution. It should be initialized without arguments, but it contains the variables:
F::Matrix{T}
: each column contains theF
function (encoding the load history) for each borehole. It is initially 0.ζ::Vector{T}
: discretization nodes of the integration interval. Shared for all boreholes. Precomputed ininitialize
.w::Matrix{T}
: weights of the ζ integration for each pair of boreholes. Precomputed ininitialize
.expΔt::Vector{T}
: exp(-ζ^2*Δt). Precomputed ininitialize
.
This feature is experimental and might not work as expected in some cases.
Boundary Condition
Models the ground surface.
BoreholeNetworksSimulator.BoundaryCondition
— Typeabstract type BoundaryCondition
Interface for boundary conditions.
Options
BoreholeNetworksSimulator.NoBoundary
— TypeNoBoundary <: BoundaryCondition
Option to solve the problem in an infinite domain
BoreholeNetworksSimulator.DirichletBoundaryCondition
— TypeDirichletBoundaryCondition <: BoundaryCondition
Option to enforce that the surface plane z=0
remains at temperature T=0
BoreholeNetworksSimulator.NeumannBoundaryCondition
— TypeNeumannBoundaryCondition <: BoundaryCondition
Option to enforce zero heat flow at the surface plane z=0
.