From 71d4cc0ab8fbc08d409e2d138558b0992758873d Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Mon, 14 Oct 2024 12:13:00 +0000 Subject: [PATCH] build based on 019abc7 --- dev/.documenter-siteinfo.json | 2 +- dev/BNSPlots/index.html | 2 +- dev/Braedstrup/index.html | 2 +- dev/api/index.html | 24 ++++++++++++++---------- dev/index.html | 2 +- dev/nonhistory/index.html | 10 ++++++---- dev/objects.inv | Bin 953 -> 962 bytes dev/python/index.html | 2 +- dev/search_index.js | 2 +- dev/tutorial/index.html | 8 +++++--- 10 files changed, 31 insertions(+), 23 deletions(-) diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 6c9adee..676d32b 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-04T12:18:29","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-14T12:12:55","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/BNSPlots/index.html b/dev/BNSPlots/index.html index e78581b..875e722 100644 --- a/dev/BNSPlots/index.html +++ b/dev/BNSPlots/index.html @@ -1,2 +1,2 @@ -Visualizing the result with BNSPlots · BoreholeNetworksSimulator.jl

Visualizing the result with BNSPlots

The repository contains a subpackage called BNSPlots that contains useful convenience functions to easily display the results obtained from BoreholeNetworksSimulator.

Reference

BNSPlots.plot_borefieldFunction
plot_borefield(network, positions; distinguished_branches = [], colors = [])

Makes a plot of the borefield, showing the boreholes numbered and their connections.

Arguments

  • network: Network specifying the connections between boreholes.
  • positions: The positions of each borehole.

Optional arguments

  • distinguished_branches: Vector of Int. If specified, the branches corresponding to the given values will be highlighted with the colors of colors.
  • colors: Vector of Tuples of Color. If specified, uses each pair of colors to define a color gradient to color each of the branches of distinguished_branches.
source
BNSPlots.monitorFunction
monitor(containers, branch, t; steps = 1:length(t), display = [:Tfin, :Tfout, :Tb, :q], Δt = :year, color_pair = (colorant"navajowhite2", colorant"darkgreen")

Creates a plot of the result of the simulation.

Arguments

  • containers: The containers (SimulationContainers) containing the result of the simulation through simulate!.
  • branch: A vector containing the IDs of the boreholes whose data will be displayed.
  • t: The times at which the data corresponds. It should normally be options.t.

Optional arguments

  • steps: Index of the steps to display in the plot.
  • display: A vector describing which plots that will be generated. If :Tfin, :Tfout or :Tb are specified, a temperature plot will be created showing the inlet fluid temperature, the outlet fluid temperature, and the borehole wall temperature, respectively. If :q is specified, a separate power plot will be created shwoing the heat extracted per meter.
  • Δt: The scale of the x-axis in the plot. Possible options: :year, :month, :hour.
  • color_pair: A pair of colors used as extrema to generate a range of colors for each borehole.
source
+Visualizing the result with BNSPlots · BoreholeNetworksSimulator.jl

Visualizing the result with BNSPlots

The repository contains a subpackage called BNSPlots that contains useful convenience functions to easily display the results obtained from BoreholeNetworksSimulator.

Reference

BNSPlots.plot_borefieldFunction
plot_borefield(network, positions; distinguished_branches = [], colors = [])

Makes a plot of the borefield, showing the boreholes numbered and their connections.

Arguments

  • network: Network specifying the connections between boreholes.
  • positions: The positions of each borehole.

Optional arguments

  • distinguished_branches: Vector of Int. If specified, the branches corresponding to the given values will be highlighted with the colors of colors.
  • colors: Vector of Tuples of Color. If specified, uses each pair of colors to define a color gradient to color each of the branches of distinguished_branches.
source
BNSPlots.monitorFunction
monitor(containers, branch, t; steps = 1:length(t), display = [:Tfin, :Tfout, :Tb, :q], Δt = :year, color_pair = (colorant"navajowhite2", colorant"darkgreen")

Creates a plot of the result of the simulation.

Arguments

  • containers: The containers (SimulationContainers) containing the result of the simulation through simulate!.
  • branch: A vector containing the IDs of the boreholes whose data will be displayed.
  • t: The times at which the data corresponds. It should normally be options.t.

Optional arguments

  • steps: Index of the steps to display in the plot.
  • display: A vector describing which plots that will be generated. If :Tfin, :Tfout or :Tb are specified, a temperature plot will be created showing the inlet fluid temperature, the outlet fluid temperature, and the borehole wall temperature, respectively. If :q is specified, a separate power plot will be created shwoing the heat extracted per meter.
  • Δt: The scale of the x-axis in the plot. Possible options: :year, :month, :hour.
  • color_pair: A pair of colors used as extrema to generate a range of colors for each borehole.
source
diff --git a/dev/Braedstrup/index.html b/dev/Braedstrup/index.html index 8efe8e5..b7b2e05 100644 --- a/dev/Braedstrup/index.html +++ b/dev/Braedstrup/index.html @@ -11,4 +11,4 @@ 153.897 118.897 93.5639 74.8265 60.7942 -27.2873 -20.0578 -14.7582 -10.8234 144.883 112.083 87.7717 69.5736 55.8771 -29.8091 -21.8784 -16.1027 -11.856 136.767 108.025 86.4461 69.9911 57.3688 … -28.6089 -20.7213 -15.0661 -10.9335 - 149.022 124.549 105.729 90.6145 78.3994 -22.1191 -15.7456 -11.0385 -7.4812

Plots

In order to visualize the results, we can use the subpackage BNSPlots. For more details, refer to [Visualizing the result with BNSPlots](@ref).

Inlet borehole temperatures and heat flows for boreholes along two branches in the borehole field. The time series are color coded according to the previous configuration plot above. In addition to the inlet temperature, the output temperature from the branch (grey dot), and the mean output temperature from the field (black dot) are displayed.

Finally we can display the heatmap of the temperature field in the borehole region during the 10th year of operation

Running the code in Python

The example is also avaiable from Python. For details of how this is done refer to Running BoreholeNetworksSimulator from Python. The Python version is in:

examples/Braedstrup/main.py
+ 149.022 124.549 105.729 90.6145 78.3994 -22.1191 -15.7456 -11.0385 -7.4812

Plots

In order to visualize the results, we can use the subpackage BNSPlots. For more details, refer to [Visualizing the result with BNSPlots](@ref).

Inlet borehole temperatures and heat flows for boreholes along two branches in the borehole field. The time series are color coded according to the previous configuration plot above. In addition to the inlet temperature, the output temperature from the branch (grey dot), and the mean output temperature from the field (black dot) are displayed.

Finally we can display the heatmap of the temperature field in the borehole region during the 10th year of operation

Running the code in Python

The example is also avaiable from Python. For details of how this is done refer to Running BoreholeNetworksSimulator from Python. The Python version is in:

examples/Braedstrup/main.py
diff --git a/dev/api/index.html b/dev/api/index.html index 926b413..7719155 100644 --- a/dev/api/index.html +++ b/dev/api/index.html @@ -1,10 +1,12 @@ -API · BoreholeNetworksSimulator.jl

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.initializeFunction
initialize(options::SimulationOptions)

Precompute the objects of each TimeSuperpositionMethod that can be computed ahead of time and return the SimulationContainers of the required size.

source
BoreholeNetworksSimulator.simulate!Function
simulate!(;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(i, Tin, Tout, Tb, q, configurations):

  • i::Int is the time step
  • Tin is a vector containing the inlet temperature of each borehole
  • Tout is a vector containing the outlet temperature of each borehole
  • Tb is a vector containing the borehole wall temperature of each borehole
  • q is a vector containing the heat exchanged by each borehole
  • configurations: is the list of possible hydraulic configurations of the borefield.
source

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.BoreholeNetworkType
BoreholeNetwork(branches::Vector{Vector{Int}})

Representation of the hydraulic connections of the boreholes in the network. Each element in branches should be a vector representing a branch of boreholes connected in series, specified by their identifiers. The first borehole of each branch is assumed to be connected in parallel.

source
BoreholeNetworksSimulator.BoreholeOperationType
BoreholeOperation{Arr <: AbstractArray}(
+API · BoreholeNetworksSimulator.jl

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.initializeFunction
initialize(options::SimulationOptions)

Precompute the objects of each TimeSuperpositionMethod that can be computed ahead of time and return the SimulationContainers of the required size.

source
BoreholeNetworksSimulator.simulate!Function
simulate!(;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(i, Tin, Tout, Tb, q, configurations):

  • i::Int is the time step
  • Tin is a vector containing the inlet temperature of each borehole
  • Tout is a vector containing the outlet temperature of each borehole
  • Tb is a vector containing the borehole wall temperature of each borehole
  • q is a vector containing the heat exchanged by each borehole
  • configurations: is the list of possible hydraulic configurations of the borefield.
source

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.BoreholeNetworkType
BoreholeNetwork(branches::Vector{Vector{Int}})

Representation of the hydraulic connections of the boreholes in the network. Each element in branches should be a vector representing a branch of boreholes connected in series, specified by their identifiers. The first borehole of each branch is assumed to be connected in parallel.

source
BoreholeNetworksSimulator.BoreholeOperationType
BoreholeOperation{Arr <: AbstractArray}(
     network::BoreholeNetwork         
     mass_flows::Arr
-)

Represents a operation state of the network, with network representing the hydraulic configuration and mass_flows a Vector containing the mass flow rate of each branch.

source
BoreholeNetworksSimulator.OperatorType
abstract type Operator

Interface for operation strategies.

Required functions:

  • operate(::Operator, i, options, Tfin, Tfout, Tb, q): Return a BoreholeOperation.
source

Prewritten operator strategies

BoreholeNetworksSimulator.SimpleOperatorType
SimpleOperator{T <: Number} <: Operator (
+)

Represents a operation state of the network, with network representing the hydraulic configuration and mass_flows a Vector containing the mass flow rate of each branch.

source
BoreholeNetworksSimulator.OperatorType
abstract type Operator

Interface for operation strategies.

Required functions:

  • operate(::Operator, i, options, Tfin, Tfout, Tb, q): Return a BoreholeOperation.
source

Prewritten operator strategies

BoreholeNetworksSimulator.SimpleOperatorType
SimpleOperator{T <: Number} <: Operator (
     mass_flows::Vector{T}
-)

Constant operation strategy, always returning BoreholeOperation(options.configurations[1], operator.mass_flows).

source

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.

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.SimulationOptionsType
struct SimulationOptions{
+                N <: Number,
+                Tol <: Number,
                 TSM <: TimeSuperpositionMethod,
                 C <: Constraint,
                 B <: Borefield, 
@@ -23,12 +25,14 @@
     configurations::Vector{BoreholeNetwork}
     Δt
     Nt::Int
-)

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.
  • 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 the borefield is places. Available options: GroundMedium, FlowInPorousMedium.
  • boundary_condition: boundary condition of the domain where the simulation is performed. Available options: NoBoundary, DirichletBoundaryCondition.
  • approximation: determines how the approximate value for each segment is computed.
  • 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.
source

The several options are listed below:

Fluid

Models the fluid used in the hydraulic system.

BoreholeNetworksSimulator.FluidType
abstract 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, and k of the fluid at temperature T.
source

Options

BoreholeNetworksSimulator.WaterType
Water <: Fluid (
+    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 the borefield is places. Available options: GroundMedium, FlowInPorousMedium.
  • boundary_condition: boundary condition of the domain where the simulation is performed. Available options: NoBoundary, DirichletBoundaryCondition, AdiabaticBoundaryCondition.
  • 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.
source

The several options are listed below:

Fluid

Models the fluid used in the hydraulic system.

BoreholeNetworksSimulator.FluidType
abstract 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, and k of the fluid at temperature T.
source

Options

BoreholeNetworksSimulator.WaterType
Water <: Fluid (
     stored_properties::ThermophysicalProperties{Float64}
-)

Models water.

To initialize, use the convenience method: function Water() that will automatically compute stored_properties.

source
BoreholeNetworksSimulator.EthanolMixType
EthanolMix <: 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.

source

Medium

Models the underground medium through which the heat will transfer between boreholes.

BoreholeNetworksSimulator.MediumType
abstract 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.
  • compute_response!(g, ::Medium, borefield::Borefield, boundary_condition::BoundaryCondition, t): Compute inplace in g the thermal responses between boreholes in borefield, imposing the boundary condition boundary_condition, for all times in t.
source

Options

BoreholeNetworksSimulator.GroundMediumType
GroundMedium{T <: Real} <: Medium @deftype T

Model pure conduction in the ground.

Arguments

  • λ = 3.: ground conductivity
  • α = 1e-6: ground thermal diffusivity
  • C = λ/α: ground medium capacity
  • T0 = 0.: initial ground temperature
source
BoreholeNetworksSimulator.FlowInPorousMediumType
FlowInPorousMedium{T <: Real} <: Medium @deftype T

Model a porous ground with a water flow.

Arguments

  • λw = 0.6: water thermal conductivity
  • λs = 2.: ground thermal conductivity
  • Cw = 4.18*1e6:water thermal capacity
  • Cs = 1.7*1e6: ground thermal capacity
  • θ = 0.: angle of Darcy velocity
  • Φ = 0.2: porosity
  • λ = λs * (1-Φ) + λw*Φ: porous medium conductivity
  • C = Cs * (1-Φ) + Cw*Φ: porous medium capacity
  • α = λ/C: porous medium thermal diffusivity
  • ux_in_meterperday = 1e-2: groundwater speed along the flow coordinate
  • ux = ux_in_meterperday/(3600*24): groundwater speed in m/s
  • vt = ux * Cw/C: porous medium darcy velocity
  • T0 = 0.: initial ground temperature
source

Borefield

Models the geometry of the borefield.

BoreholeNetworksSimulator.BorefieldType
abstract 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 borehole i.
  • get_rb(::Borefield, i): Return the radius of borehole i.
  • segment_coordinates(::Borefield): Return a vector with the coordinates of each segment.
  • internal_model_coeffs!(M, ::Borefield, medium, operation, fluid): Compute inplace in M the coefficients corresponding to the internal model equations, given the medium, fluid and operation in use in the system. Note that M is only a slice of Nb (number of boreholes) rows, provided as a view.
  • internal_model_b!(b, ::Borefield): Compute inplace in b the independent terms corresponding to the internal model equations. Note that b is only a vector of length Nb (number of boreholes) rows, provided as a view.
source

Options

BoreholeNetworksSimulator.EqualBoreholesBorefieldType
EqualBoreholesBorefield{T <: Borehole, R <: Medium, S <: Real} <: Borefield
-EqualBoreholesBorefield(borehole_prototype::T, positions::Vector{Point2{S}}), medium::R)

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. medium contains the properties of the ground.

source

Borehole

Models the internal heat transfer in the borehole.

BoreholeNetworksSimulator.BoreholeType
abstract 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.
source

Options

BoreholeNetworksSimulator.SingleUPipeBoreholeType
SingleUPipeBorehole{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 conductivity
  • Cg = 2000. * 1550.: grout capacity
  • αg = λg/Cg: grout thermal diffusivity
  • rp = 0.02: pipe radius
  • λp = 0.42: pipe material conductivity
  • dpw = 0.0023: pipe thickness
  • rpo = rp + dpw: equivalent pipe radius
  • hp = 725.: heat transfer coefficient fluid to pipe
  • pipe_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
source

Constraint

Imposes the working conditions and demands of the whole system.

BoreholeNetworksSimulator.ConstraintType
abstract type Constraint

Interface for constraints.

Required functions:

  • constraints_coeffs!(M, ::Constraint, operation::BoreholeOperation): Compute inplace in M the coefficients corresponding to the constraints equations, given the current operation.network. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.
  • constraints_b!(b, ::Constraint, ::BoreholeOperation, step): Compute inplace in b the independent term corresponding to the constraints equations, given the current operation.network, at the time step step. Note that b is only a vector of length Nbr (number of branches), provided as a view.
source

Options

BoreholeNetworksSimulator.HeatLoadConstraintType
HeatLoadConstraint(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.

source
BoreholeNetworksSimulator.constant_HeatLoadConstraintFunction
constant_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.

source
BoreholeNetworksSimulator.uniform_HeatLoadConstraintFunction
uniform_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.

source
BoreholeNetworksSimulator.InletTempConstraintType
InletTempConstraint(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 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.

source
BoreholeNetworksSimulator.constant_InletTempConstraintFunction
constant_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.

source
BoreholeNetworksSimulator.uniform_InletTempConstraintFunction
uniform_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.

source

Time Superposition Method

Applies methods for time superposition.

BoreholeNetworksSimulator.TimeSuperpositionMethodType
abstract type TimeSuperpositionMethod

Interface for time superposition methods.

Required functions:

  • method_coeffs!(M, ::TimeSuperpositionMethod, options): Compute inplace in M the coefficients corresponding to the heat transfer equations, given options. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.
  • method_b!(b, ::TimeSuperpositionMethod, borefield, medium, step): Compute inplace in b the independent terms corresponding to the heat transfer equations, given the medium, at the given time step step. Note that b is only a vector of length Nbr (number of branches) rows, provided as a view.
  • precompute_auxiliaries!(method::TimeSuperpositionMethod; options): Compute inplace in method the auxiliary quantities used in the simulation that can be performed ahead of time.
  • update_auxiliaries!(::TimeSuperpositionMethod, X, borefield, step): Update inplace in method the auxiliaries after each time step step.
source

Options

BoreholeNetworksSimulator.ConvolutionMethodType
ConvolutionMethod{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.
source
BoreholeNetworksSimulator.NonHistoryMethodType
NonHistoryMethod{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 the F 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 in initialize.
  • w::Matrix{T}: weights of the ζ integration for each pair of boreholes. Precomputed in initialize.
  • expΔt::Vector{T}: exp(-ζ^2*Δt). Precomputed in initialize.

This feature is experimental and might not work as expected in some cases.

source

Boundary Condition

Models the ground surface.

Options

+)

Models a 20% ethanol and water mix.

To initialize, use the convenience method: function EthanolMix() that will automatically compute stored_properties.

source

Medium

Models the underground medium through which the heat will transfer between boreholes.

BoreholeNetworksSimulator.MediumType
abstract 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.
source

Options

BoreholeNetworksSimulator.GroundMediumType
GroundMedium{T <: Real} <: Medium @deftype T

Model pure conduction in the ground.

Arguments

  • λ = 3.: ground conductivity
  • α = 1e-6: ground thermal diffusivity
  • C = λ/α: ground medium capacity
  • T0 = 0.: initial ground temperature
source
BoreholeNetworksSimulator.FlowInPorousMediumType
FlowInPorousMedium{T <: Real} <: Medium @deftype T

Model a porous ground with a water flow.

Arguments

  • λw = 0.6: water thermal conductivity
  • λs = 2.: ground thermal conductivity
  • Cw = 4.18*1e6:water thermal capacity
  • Cs = 1.7*1e6: ground thermal capacity
  • θ = 0.: angle of Darcy velocity
  • Φ = 0.2: porosity
  • λ = λs * (1-Φ) + λw*Φ: porous medium conductivity
  • C = Cs * (1-Φ) + Cw*Φ: porous medium capacity
  • α = λ/C: porous medium thermal diffusivity
  • ux_in_meterperday = 1e-2: groundwater speed along the flow coordinate
  • ux = ux_in_meterperday/(3600*24): groundwater speed in m/s
  • vt = ux * Cw/C: porous medium darcy velocity
  • T0 = 0.: initial ground temperature
source

Borefield

Models the geometry of the borefield.

BoreholeNetworksSimulator.BorefieldType
abstract 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 borehole i.
  • get_rb(::Borefield, i): Return the radius of borehole i.
  • segment_coordinates(::Borefield): Return a vector with the coordinates of each segment.
  • internal_model_coeffs!(M, ::Borefield, medium, operation, fluid): Compute inplace in M the coefficients corresponding to the internal model equations, given the medium, fluid and operation in use in the system. Note that M is only a slice of Nb (number of boreholes) rows, provided as a view.
  • internal_model_b!(b, ::Borefield): Compute inplace in b the independent terms corresponding to the internal model equations. Note that b is only a vector of length Nb (number of boreholes) rows, provided as a view.
source

Options

BoreholeNetworksSimulator.EqualBoreholesBorefieldType
EqualBoreholesBorefield{T <: Borehole, R <: Medium, S <: Real} <: Borefield
+EqualBoreholesBorefield(borehole_prototype::T, positions::Vector{Point2{S}}), medium::R)

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. medium contains the properties of the ground.

source

Borehole

Models the internal heat transfer in the borehole.

BoreholeNetworksSimulator.BoreholeType
abstract 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.
source

Options

BoreholeNetworksSimulator.SingleUPipeBoreholeType
SingleUPipeBorehole{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 conductivity
  • Cg = 2000. * 1550.: grout capacity
  • αg = λg/Cg: grout thermal diffusivity
  • rp = 0.02: pipe radius
  • λp = 0.42: pipe material conductivity
  • dpw = 0.0023: pipe thickness
  • rpo = rp + dpw: equivalent pipe radius
  • hp = 725.: heat transfer coefficient fluid to pipe
  • pipe_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
source

Constraint

Imposes the working conditions and demands of the whole system.

BoreholeNetworksSimulator.ConstraintType
abstract type Constraint

Interface for constraints.

Required functions:

  • constraints_coeffs!(M, ::Constraint, operation::BoreholeOperation): Compute inplace in M the coefficients corresponding to the constraints equations, given the current operation.network. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.
  • constraints_b!(b, ::Constraint, ::BoreholeOperation, step): Compute inplace in b the independent term corresponding to the constraints equations, given the current operation.network, at the time step step. Note that b is only a vector of length Nbr (number of branches), provided as a view.
source

Options

BoreholeNetworksSimulator.HeatLoadConstraintType
HeatLoadConstraint(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.

source
BoreholeNetworksSimulator.constant_HeatLoadConstraintFunction
constant_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.

source
BoreholeNetworksSimulator.uniform_HeatLoadConstraintFunction
uniform_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.

source
BoreholeNetworksSimulator.InletTempConstraintType
InletTempConstraint(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 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.

source
BoreholeNetworksSimulator.constant_InletTempConstraintFunction
constant_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.

source
BoreholeNetworksSimulator.uniform_InletTempConstraintFunction
uniform_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.

source

Time Superposition Method

Applies methods for time superposition.

BoreholeNetworksSimulator.TimeSuperpositionMethodType
abstract type TimeSuperpositionMethod

Interface for time superposition methods.

Required functions:

  • method_coeffs!(M, ::TimeSuperpositionMethod, options): Compute inplace in M the coefficients corresponding to the heat transfer equations, given options. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.
  • method_b!(b, ::TimeSuperpositionMethod, borefield, medium, step): Compute inplace in b the independent terms corresponding to the heat transfer equations, given the medium, at the given time step step. Note that b is only a vector of length Nbr (number of branches) rows, provided as a view.
  • precompute_auxiliaries!(method::TimeSuperpositionMethod; options): Compute inplace in method the auxiliary quantities used in the simulation that can be performed ahead of time.
  • update_auxiliaries!(::TimeSuperpositionMethod, X, borefield, step): Update inplace in method the auxiliaries after each time step step.
source

Options

BoreholeNetworksSimulator.ConvolutionMethodType
ConvolutionMethod{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.
source
BoreholeNetworksSimulator.NonHistoryMethodType
NonHistoryMethod{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 the F 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 in initialize.
  • w::Matrix{T}: weights of the ζ integration for each pair of boreholes. Precomputed in initialize.
  • expΔt::Vector{T}: exp(-ζ^2*Δt). Precomputed in initialize.

This feature is experimental and might not work as expected in some cases.

source

Boundary Condition

Models the ground surface.

Options

diff --git a/dev/index.html b/dev/index.html index 2545965..d3cafd5 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,2 +1,2 @@ -Introduction · BoreholeNetworksSimulator.jl

BoreholeNetworksSimulator.jl

BoreholeNetworksSimulator.jl is a pure Julia, performant, and modular framework for simulations of fields of interconnected borehole heat exchangers. Features:

  • Computes fluid temperatures, borehole wall temperatures and heat extracted.
  • Supports many different configurations and settings by being highly modular: boreholes, hydraulic configurations, ground properties, load demand or temperature constraints, ground boundary conditions can be seamlessly used with minimal effort.
  • Allows for design of operation strategies via an operator callback at each time step.
  • Implements the "non-history" time superposition method, reducing the computational complexity in the number of time steps to linear. This allows for simulations with fine time steps.
  • Python interoperability.

Getting started

BoreholeNetworksSimulator.jl is currently not in Julia's General registry (as well as some of its dependencies), however, it is easily available through the local registry geothermal_registry. In order to install it, start Julia and run the command:

using Pkg; pkg"registry add https://github.com/marcbasquensmunoz/geothermal_registry"; Pkg.add("BoreholeNetworksSimulator")

In order to learn how to use this package, please visit Basic tutorial first.

For users interested in running BoreholeNetworksSimulator.jl from Python, see also Running BoreholeNetworksSimulator from Python.

Design philosophy

The driving motivation when developing BoreholeNetworksSimulator.jl was to create an easy to use tool that is also highly flexible and performant.

This goal has been accomplished by leveraging Julia's Multiple Dispatch. Through a simple, common interface, the user can run a plethora of different simulations by modularly specifying options. Some options have physical meaning or interpretation, while others are purely algorithmic, yet they can all be seamlessly changed by changing a parameter. Please, refer to Public API for the full list of options offered by this package.

+Introduction · BoreholeNetworksSimulator.jl

BoreholeNetworksSimulator.jl

BoreholeNetworksSimulator.jl is a pure Julia, performant, and modular framework for simulations of fields of interconnected borehole heat exchangers. Features:

  • Computes fluid temperatures, borehole wall temperatures and heat extracted.
  • Supports many different configurations and settings by being highly modular: boreholes, hydraulic configurations, ground properties, load demand or temperature constraints, ground boundary conditions can be seamlessly used with minimal effort.
  • Allows for design of operation strategies via an operator callback at each time step.
  • Implements the "non-history" time superposition method, reducing the computational complexity in the number of time steps to linear. This allows for simulations with fine time steps.
  • Python interoperability.

Getting started

BoreholeNetworksSimulator.jl is currently not in Julia's General registry (as well as some of its dependencies), however, it is easily available through the local registry geothermal_registry. In order to install it, start Julia and run the command:

using Pkg; pkg"registry add https://github.com/marcbasquensmunoz/geothermal_registry"; Pkg.add("BoreholeNetworksSimulator")

In order to learn how to use this package, please visit Basic tutorial first.

For users interested in running BoreholeNetworksSimulator.jl from Python, see also Running BoreholeNetworksSimulator from Python.

Design philosophy

The driving motivation when developing BoreholeNetworksSimulator.jl was to create an easy to use tool that is also highly flexible and performant.

This goal has been accomplished by leveraging Julia's Multiple Dispatch. Through a simple, common interface, the user can run a plethora of different simulations by modularly specifying options. Some options have physical meaning or interpretation, while others are purely algorithmic, yet they can all be seamlessly changed by changing a parameter. Please, refer to Public API for the full list of options offered by this package.

diff --git a/dev/nonhistory/index.html b/dev/nonhistory/index.html index d6de860..9816036 100644 --- a/dev/nonhistory/index.html +++ b/dev/nonhistory/index.html @@ -30,7 +30,7 @@ Δt = Δt, Nt = Nt, configurations = configurations -)
SimulationOptions{Float64, NonHistoryMethod{Float64}, HeatLoadConstraint{Float64}, EqualBoreholesBorefield{SingleUPipeBorehole{Float64}, Float64}, GroundMedium{Float64}, DirichletBoundaryCondition, MeanApproximation, Water}
+)
SimulationOptions{Float64, Float64, NonHistoryMethod{Float64}, HeatLoadConstraint{Float64}, EqualBoreholesBorefield{SingleUPipeBorehole{Float64}, Float64}, GroundMedium{Float64}, DirichletBoundaryCondition, MeanApproximation, Water}
   method: NonHistoryMethod{Float64}
   constraint: HeatLoadConstraint{Float64}
   borefield: EqualBoreholesBorefield{SingleUPipeBorehole{Float64}, Float64}
@@ -46,9 +46,11 @@
   Tmax: Float64 3.1536e7
   t: StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}
   configurations: Array{BoreholeNetwork}((1,))
+  atol: Float64 0.0
+  rtol: Float64 1.4901161193847656e-8
 

Let us run the convolution

containers_convolution = @time initialize(options_convolution)
-@time simulate!(operator=operator, options=options_convolution, containers=containers_convolution)
  6.779180 seconds (4.36 M allocations: 1.251 GiB, 1.74% gc time, 23.09% compilation time)
-  4.955480 seconds (7.08 M allocations: 434.665 MiB, 2.43% gc time, 79.97% compilation time)

And now let us run the non-history

containers_nonhistory = @time initialize(options_nonhistory)
+@time simulate!(operator=operator, options=options_convolution, containers=containers_convolution)
  6.902249 seconds (4.47 M allocations: 1.252 GiB, 1.58% gc time, 23.06% compilation time)
+  4.864411 seconds (7.08 M allocations: 434.579 MiB, 1.75% gc time, 79.73% compilation time)

And now let us run the non-history

containers_nonhistory = @time initialize(options_nonhistory)
 @time simulate!(operator=operator, options=options_nonhistory, containers=containers_nonhistory)
 
 abs.(containers_convolution.X - containers_nonhistory.X)
8×8760 Matrix{Float64}:
@@ -59,4 +61,4 @@
  5.05143e-11  4.84537e-11  5.72768e-11     1.17982e-10  1.17982e-10
  5.05143e-11  4.84537e-11  5.72768e-11  …  1.17982e-10  1.17982e-10
  0.0          0.0          0.0             0.0          0.0
- 0.0          0.0          0.0             0.0          0.0

References

[1] Lazzarotto, Alberto; Basquens, Marc; Cimmino, Massimo; Non-history dependent temporal superposition algorithm for the point source solution, Research Conference Proceedings of the IGSHPA (2024).


This page was generated using Literate.jl.

+ 0.0 0.0 0.0 0.0 0.0

References

[1] Lazzarotto, Alberto; Basquens, Marc; Cimmino, Massimo; Non-history dependent temporal superposition algorithm for the point source solution, Research Conference Proceedings of the IGSHPA (2024).


This page was generated using Literate.jl.

diff --git a/dev/objects.inv b/dev/objects.inv index 091fc65d5201362caad168e5009ab00909b60ed3..58be33d3c7983647272ab24c297cffc66c908c23 100644 GIT binary patch delta 833 zcmV-H1HSyZ2f_!CRRJ`SRy}`nn=lZ)^DES8b5uNOZ@Ip<6i6OlhkltHXZ+9O?5yK17CO(a2MCb`23t^Ou^T?nSfys?j$aov!*JfnS zG)DDvAf!l8+lOr%-mK2ZtrXNlQZR{(gKTRrqD?4QX5>B>0>u+qE17>*i^2SM8FFcK z8}HX<RL5u+ zQCm6+FD%V=1!)zjd~s3b3L1p@iep4=QF>#S+eOU=Q$2p(k*dh4+O~SqyUbm5?+Y3j zsbIlHnc69BGN-G41=?q;Xh&bp`iVYlf2aDYIvFDw14YqW!aaXAg`XS8A}D;#nu#0W z(q;;FV16_UkZns#VJOT%@vp!bm$^1f8Ho2vQSFmzKPdc%c08(v*DmD-qw78(TWEN4FMeC){kCpw#zr&S3`mdL?gu$Xg;B!6cq?rTcT}7^FZd{y z75Tc1tx=PX9HvP~4d(;R+U3m)0Omt1ZZB9uzz`jynZlV0qPvv|{{`JfGU|-i-do1isq_ LMmXX>R(vq!AE%Y- delta 824 zcmV-81IPTr2e}83RRJ@RRy}`H+b|Hl`&X#baugZb8#hwEGE=}qXnSNFdxMwClBDx{GSI0=f_!U#c$-kJ%*egr9QhMjOObz7i^2SM88V?& z8}HX<xr`uDTAI8Qq+Xr1p2?dy!3 zg^S=G)*yk$Q0By<6|kLafBZyfa03aNtc!6$ip{w_CKU_@w+&AsxustPPtX;n7wBQ6 zh6Pu^L00A4k6S5B{qcXdpf^JPQcKJXi)`-HX-~tZM0Jd+NH&Zw(_oOYfMHcYFX(Ve z)RvCIOO)lig0zZM9$Zwpf(D^kF^s7#N^k6PyQtYjbeQWZH>+g49{m%AU;dq4vt z6)dKbL?dZ!{KhcNn?^It^Cu1xUpvZemxTk+6_jBV|1i7zSGjRi4 z+DyR?%#UUPvTbQ85pq3H{43DfWv+B2H6(kbsP;*<9~AyWJ04ZTYnO6^(e90RsKRaNO;4OE8;2$xG%3-wr5|U4 zqf7FcovsZpzCUEQg@z~h;z>;Y&5;if%LfTevosN7^e)hx6;ONN5#4Gf{$WZ zk*`aQD&?Kqa$ z!vm=D2|g_JHO1Ssqt7RAPVt0qg5N2fXSAMHj6Z^zsg3GQ

Note that this is equivalent to calling the same code from Julia:

operator = jl.SimpleOperator(mass_flow = 2., branches = 2)

Finally we can run the simulation

containers = jl.initialize(options)
-jl.simulate_b(operator=operator, options=options, containers=containers)

Note that the bang in simulate! is replaced by a _b in the juliacall version of the function.

containers.X

Now, one can compare this result with its Julia version. If everything went right, they should agree!

+jl.simulate_b(operator=operator, options=options, containers=containers)

Note that the bang in simulate! is replaced by a _b in the juliacall version of the function.

containers.X

Now, one can compare this result with its Julia version. If everything went right, they should agree!

diff --git a/dev/search_index.js b/dev/search_index.js index b5df353..ae45287 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"BNSPlots/#Visualizing-the-result-with-BNSPlots","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"","category":"section"},{"location":"BNSPlots/","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"The repository contains a subpackage called BNSPlots that contains useful convenience functions to easily display the results obtained from BoreholeNetworksSimulator.","category":"page"},{"location":"BNSPlots/#Reference","page":"Visualizing the result with BNSPlots","title":"Reference","text":"","category":"section"},{"location":"BNSPlots/","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"plot_borefield","category":"page"},{"location":"BNSPlots/#BNSPlots.plot_borefield","page":"Visualizing the result with BNSPlots","title":"BNSPlots.plot_borefield","text":"plot_borefield(network, positions; distinguished_branches = [], colors = [])\n\nMakes a plot of the borefield, showing the boreholes numbered and their connections.\n\nArguments\n\nnetwork: Network specifying the connections between boreholes.\npositions: The positions of each borehole.\n\nOptional arguments\n\ndistinguished_branches: Vector of Int. If specified, the branches corresponding to the given values will be highlighted with the colors of colors.\ncolors: Vector of Tuples of Color. If specified, uses each pair of colors to define a color gradient to color each of the branches of distinguished_branches.\n\n\n\n\n\n","category":"function"},{"location":"BNSPlots/","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"monitor","category":"page"},{"location":"BNSPlots/#BNSPlots.monitor","page":"Visualizing the result with BNSPlots","title":"BNSPlots.monitor","text":"monitor(containers, branch, t; steps = 1:length(t), display = [:Tfin, :Tfout, :Tb, :q], Δt = :year, color_pair = (colorant\"navajowhite2\", colorant\"darkgreen\")\n\nCreates a plot of the result of the simulation.\n\nArguments\n\ncontainers: The containers (SimulationContainers) containing the result of the simulation through simulate!.\nbranch: A vector containing the IDs of the boreholes whose data will be displayed. \nt: The times at which the data corresponds. It should normally be options.t.\n\nOptional arguments\n\nsteps: Index of the steps to display in the plot.\ndisplay: A vector describing which plots that will be generated. If :Tfin, :Tfout or :Tb are specified, a temperature plot will be created showing the inlet fluid temperature, the outlet fluid temperature, and the borehole wall temperature, respectively. If :q is specified, a separate power plot will be created shwoing the heat extracted per meter.\nΔt: The scale of the x-axis in the plot. Possible options: :year, :month, :hour.\ncolor_pair: A pair of colors used as extrema to generate a range of colors for each borehole. \n\n\n\n\n\n","category":"function"},{"location":"api/#Public-API","page":"API","title":"Public API","text":"","category":"section"},{"location":"api/#General","page":"API","title":"General","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"These are the functions used to run the simulation. Note that an object of type SimulationOptions is needed to call them.","category":"page"},{"location":"api/","page":"API","title":"API","text":"initialize","category":"page"},{"location":"api/#BoreholeNetworksSimulator.initialize","page":"API","title":"BoreholeNetworksSimulator.initialize","text":"initialize(options::SimulationOptions)\n\nPrecompute the objects of each TimeSuperpositionMethod that can be computed ahead of time and return the SimulationContainers of the required size.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"simulate!","category":"page"},{"location":"api/#BoreholeNetworksSimulator.simulate!","page":"API","title":"BoreholeNetworksSimulator.simulate!","text":"simulate!(;options::SimulationOptions, operator, containers::SimulationContainers)\n\nRun the simulation defined by options. At the end of simulation, containers.X will contain the results. containers should be the output of initialize.\n\noperator should be a function that returns a BoreholeOperation and with signature operator(i, Tin, Tout, Tb, q, configurations):\n\ni::Int is the time step\nTin is a vector containing the inlet temperature of each borehole\nTout is a vector containing the outlet temperature of each borehole\nTb is a vector containing the borehole wall temperature of each borehole\nq is a vector containing the heat exchanged by each borehole\nconfigurations: is the list of possible hydraulic configurations of the borefield.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"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.","category":"page"},{"location":"api/","page":"API","title":"API","text":"BoreholeNetwork","category":"page"},{"location":"api/#BoreholeNetworksSimulator.BoreholeNetwork","page":"API","title":"BoreholeNetworksSimulator.BoreholeNetwork","text":"BoreholeNetwork(branches::Vector{Vector{Int}})\n\nRepresentation of the hydraulic connections of the boreholes in the network. Each element in branches should be a vector representing a branch of boreholes connected in series, specified by their identifiers. The first borehole of each branch is assumed to be connected in parallel. \n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"BoreholeOperation","category":"page"},{"location":"api/#BoreholeNetworksSimulator.BoreholeOperation","page":"API","title":"BoreholeNetworksSimulator.BoreholeOperation","text":"BoreholeOperation{Arr <: AbstractArray}(\n network::BoreholeNetwork \n mass_flows::Arr\n)\n\nRepresents a operation state of the network, with network representing the hydraulic configuration and mass_flows a Vector containing the mass flow rate of each branch.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"Operator","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Operator","page":"API","title":"BoreholeNetworksSimulator.Operator","text":"abstract type Operator\n\nInterface for operation strategies.\n\nRequired functions:\n\noperate(::Operator, i, options, Tfin, Tfout, Tb, q): Return a BoreholeOperation.\n\n\n\n\n\n","category":"type"},{"location":"api/#Prewritten-operator-strategies","page":"API","title":"Prewritten operator strategies","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"SimpleOperator","category":"page"},{"location":"api/#BoreholeNetworksSimulator.SimpleOperator","page":"API","title":"BoreholeNetworksSimulator.SimpleOperator","text":"SimpleOperator{T <: Number} <: Operator (\n mass_flows::Vector{T}\n)\n\nConstant operation strategy, always returning BoreholeOperation(options.configurations[1], operator.mass_flows).\n\n\n\n\n\n","category":"type"},{"location":"api/#Simulation-Options","page":"API","title":"Simulation Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"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.","category":"page"},{"location":"api/","page":"API","title":"API","text":"SimulationOptions","category":"page"},{"location":"api/#BoreholeNetworksSimulator.SimulationOptions","page":"API","title":"BoreholeNetworksSimulator.SimulationOptions","text":"struct SimulationOptions{\n TSM <: TimeSuperpositionMethod,\n C <: Constraint,\n B <: Borefield, \n M <: Medium, \n BC <: BoundaryCondition,\n A <: Approximation,\n F <: Fluid\n }(\n method::TSM\n constraint::C\n borefield::B\n medium::M\n boundary_condition::BoundaryCondition = DirichletBoundaryCondition()\n approximation::A = MeanApproximation()\n fluid::Fluid{N} = Fluid(cpf=4182., name=\"INCOMP::MEA-20%\")\n configurations::Vector{BoreholeNetwork}\n Δt\n Nt::Int\n)\n\nSpecifies all the options for the simulation.\n\nmethod: time superposition method used to compute the response. Available options: ConvolutionMethod, NonHistoryMethod.\nconstraint: constraint that the system must satisfy. Can be variable with time. Available options: HeatLoadConstraint, InletTempConstraint.\nborefield: describes the geometrical properties and the boreholes of the borefield on which the simulation will be performed. Available options: EqualBoreholesBorefield.\nmedium: properties of the ground where the borefield is places. Available options: GroundMedium, FlowInPorousMedium.\nboundary_condition: boundary condition of the domain where the simulation is performed. Available options: NoBoundary, DirichletBoundaryCondition.\napproximation: determines how the approximate value for each segment is computed.\nfluid: properties of the fluid flowing through the hydraulic system.\nconfigurations: possible hydraulic topologies possible in the system, including reverse flow.\nΔt: time step used in the simulation.\nNt: total amount of time steps of the simulation.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"The several options are listed below:","category":"page"},{"location":"api/#Fluid","page":"API","title":"Fluid","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the fluid used in the hydraulic system.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Fluid","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Fluid","page":"API","title":"BoreholeNetworksSimulator.Fluid","text":"abstract type Fluid end\n\nInterface for fluids.\n\nRequired functions:\n\ncpf(::Fluid): Return the scpecific heat capacity of the fluid.\nthermophysical_properties(::Fluid, T): Return the μ, ρ, cp, and k of the fluid at temperature T.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Water","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Water","page":"API","title":"BoreholeNetworksSimulator.Water","text":"Water <: Fluid (\n stored_properties::ThermophysicalProperties{Float64}\n)\n\nModels water.\n\nTo initialize, use the convenience method: function Water() that will automatically compute stored_properties.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"EthanolMix","category":"page"},{"location":"api/#BoreholeNetworksSimulator.EthanolMix","page":"API","title":"BoreholeNetworksSimulator.EthanolMix","text":"EthanolMix <: Fluid (\n stored_properties::ThermophysicalProperties{Float64}\n)\n\nModels a 20% ethanol and water mix.\n\nTo initialize, use the convenience method: function EthanolMix() that will automatically compute stored_properties.\n\n\n\n\n\n","category":"type"},{"location":"api/#Medium","page":"API","title":"Medium","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the underground medium through which the heat will transfer between boreholes.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Medium","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Medium","page":"API","title":"BoreholeNetworksSimulator.Medium","text":"abstract type Medium\n\nInterface for mediums.\n\nRequired functions:\n\nget_λ(::Medium): Return the thermal conductivity of the medium.\nget_α(::Medium): Return the thermal diffusivity of the medium.\nget_T0(::Medium): Return the initial temperature of the medium.\ncompute_response!(g, ::Medium, borefield::Borefield, boundary_condition::BoundaryCondition, t): Compute inplace in g the thermal responses between boreholes in borefield, imposing the boundary condition boundary_condition, for all times in t.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-2","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"GroundMedium","category":"page"},{"location":"api/#BoreholeNetworksSimulator.GroundMedium","page":"API","title":"BoreholeNetworksSimulator.GroundMedium","text":"GroundMedium{T <: Real} <: Medium @deftype T\n\nModel pure conduction in the ground.\n\nArguments\n\nλ = 3.: ground conductivity\nα = 1e-6: ground thermal diffusivity\nC = λ/α: ground medium capacity\nT0 = 0.: initial ground temperature\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"FlowInPorousMedium","category":"page"},{"location":"api/#BoreholeNetworksSimulator.FlowInPorousMedium","page":"API","title":"BoreholeNetworksSimulator.FlowInPorousMedium","text":"FlowInPorousMedium{T <: Real} <: Medium @deftype T\n\nModel a porous ground with a water flow.\n\nArguments\n\nλw = 0.6: water thermal conductivity\nλs = 2.: ground thermal conductivity\nCw = 4.18*1e6:water thermal capacity\nCs = 1.7*1e6: ground thermal capacity\nθ = 0.: angle of Darcy velocity\nΦ = 0.2: porosity\nλ = λs * (1-Φ) + λw*Φ: porous medium conductivity\nC = Cs * (1-Φ) + Cw*Φ: porous medium capacity\nα = λ/C: porous medium thermal diffusivity\nux_in_meterperday = 1e-2: groundwater speed along the flow coordinate\nux = ux_in_meterperday/(3600*24): groundwater speed in m/s\nvt = ux * Cw/C: porous medium darcy velocity\nT0 = 0.: initial ground temperature\n\n\n\n\n\n","category":"type"},{"location":"api/#Borefield","page":"API","title":"Borefield","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the geometry of the borefield.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Borefield","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Borefield","page":"API","title":"BoreholeNetworksSimulator.Borefield","text":"abstract type Borefield\n\nInterface for borefields.\n\nRequired functions\n\nn_boreholes(::Borefield): Return the amount of boreholes present in the borefield.\nget_H(::Borefield, i): Return the length of borehole i.\nget_rb(::Borefield, i): Return the radius of borehole i.\nsegment_coordinates(::Borefield): Return a vector with the coordinates of each segment. \ninternal_model_coeffs!(M, ::Borefield, medium, operation, fluid): Compute inplace in M the coefficients corresponding to the internal model equations, given the medium, fluid and operation in use in the system. Note that M is only a slice of Nb (number of boreholes) rows, provided as a view.\ninternal_model_b!(b, ::Borefield): Compute inplace in b the independent terms corresponding to the internal model equations. Note that b is only a vector of length Nb (number of boreholes) rows, provided as a view.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-3","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"EqualBoreholesBorefield","category":"page"},{"location":"api/#BoreholeNetworksSimulator.EqualBoreholesBorefield","page":"API","title":"BoreholeNetworksSimulator.EqualBoreholesBorefield","text":"EqualBoreholesBorefield{T <: Borehole, R <: Medium, S <: Real} <: Borefield\nEqualBoreholesBorefield(borehole_prototype::T, positions::Vector{Point2{S}}), medium::R)\n\nModel 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. medium contains the properties of the ground.\n\n\n\n\n\n","category":"type"},{"location":"api/#Borehole","page":"API","title":"Borehole","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the internal heat transfer in the borehole.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Borehole","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Borehole","page":"API","title":"BoreholeNetworksSimulator.Borehole","text":"abstract type Borehole\n\nInterface for boreholes.\n\nRequired functions:\n\nget_H(::Borehole): Return the length of the borehole.\nget_D(::Borehole): Return the burial depth of the borehole.\nget_rb(::Borehole): Return the radius of the borehole.\nuniform_Tb_coeffs(::Borehole, λ, mass_flow, Tref, fluid): Return the internal model coefficients for the resistance network between the pipes and the wall.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-4","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"SingleUPipeBorehole","category":"page"},{"location":"api/#BoreholeNetworksSimulator.SingleUPipeBorehole","page":"API","title":"BoreholeNetworksSimulator.SingleUPipeBorehole","text":"SingleUPipeBorehole{T <: Real} <: Borehole @deftype T\nSingleUPipeBorehole(H, D)\n\nModel a borehole with a single U-pipe with burial depth D and length H.\n\nArguments\n\nλg = 2.5: grout conductivity\nCg = 2000. * 1550.: grout capacity\nαg = λg/Cg: grout thermal diffusivity\nrp = 0.02: pipe radius\nλp = 0.42: pipe material conductivity\ndpw = 0.0023: pipe thickness\nrpo = rp + dpw: equivalent pipe radius\nhp = 725.: heat transfer coefficient fluid to pipe\npipe_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.\nrb = 0.115/2: borehole radius\n\n\n\n\n\n","category":"type"},{"location":"api/#Constraint","page":"API","title":"Constraint","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Imposes the working conditions and demands of the whole system.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Constraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Constraint","page":"API","title":"BoreholeNetworksSimulator.Constraint","text":"abstract type Constraint\n\nInterface for constraints.\n\nRequired functions:\n\nconstraints_coeffs!(M, ::Constraint, operation::BoreholeOperation): Compute inplace in M the coefficients corresponding to the constraints equations, given the current operation.network. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.\nconstraints_b!(b, ::Constraint, ::BoreholeOperation, step): Compute inplace in b the independent term corresponding to the constraints equations, given the current operation.network, at the time step step. Note that b is only a vector of length Nbr (number of branches), provided as a view.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-5","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"HeatLoadConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.HeatLoadConstraint","page":"API","title":"BoreholeNetworksSimulator.HeatLoadConstraint","text":"HeatLoadConstraint(Q_tot::Matrix{T}){T <: Number} <: Constraint\n\nConstrain the heat extracted per branch.\n\nThe 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.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"constant_HeatLoadConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.constant_HeatLoadConstraint","page":"API","title":"BoreholeNetworksSimulator.constant_HeatLoadConstraint","text":"constant_HeatLoadConstraint(Q_tot::Vector{T}, Nt) where {T <: Number}\n\nConvenience 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.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"uniform_HeatLoadConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.uniform_HeatLoadConstraint","page":"API","title":"BoreholeNetworksSimulator.uniform_HeatLoadConstraint","text":"uniform_HeatLoadConstraint(Q_tot::Vector{T}, Nbr) where {T <: Number}\n\nConvenience initializer for HeatLoadConstraint. It creates a uniform heat load constraint along all branches, where T_in are the heat load for each time step.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"InletTempConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.InletTempConstraint","page":"API","title":"BoreholeNetworksSimulator.InletTempConstraint","text":"InletTempConstraint(T_in::Matrix{T}){T <: Number} <: Constraint\n\nConstrain the inlet temperature of the first borehole in each branch.\n\nThe inlet temperature T_in must be a 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.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"constant_InletTempConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.constant_InletTempConstraint","page":"API","title":"BoreholeNetworksSimulator.constant_InletTempConstraint","text":"constant_InletTempConstraint(T_in::Vector{N}, Nt) where {N <: Number}\n\nConvenience 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.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"uniform_InletTempConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.uniform_InletTempConstraint","page":"API","title":"BoreholeNetworksSimulator.uniform_InletTempConstraint","text":"uniform_InletTempConstraint(T_in::Vector{N}, Nbr) where {N <: Number}\n\nConvenience initializer for InletTempConstraint. It creates a uniform inlet temperature constraint along all branches, where T_in are the inlet temperatures for each time step.\n\n\n\n\n\n","category":"function"},{"location":"api/#Time-Superposition-Method","page":"API","title":"Time Superposition Method","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Applies methods for time superposition.","category":"page"},{"location":"api/","page":"API","title":"API","text":"TimeSuperpositionMethod","category":"page"},{"location":"api/#BoreholeNetworksSimulator.TimeSuperpositionMethod","page":"API","title":"BoreholeNetworksSimulator.TimeSuperpositionMethod","text":"abstract type TimeSuperpositionMethod\n\nInterface for time superposition methods.\n\nRequired functions:\n\nmethod_coeffs!(M, ::TimeSuperpositionMethod, options): Compute inplace in M the coefficients corresponding to the heat transfer equations, given options. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.\nmethod_b!(b, ::TimeSuperpositionMethod, borefield, medium, step): Compute inplace in b the independent terms corresponding to the heat transfer equations, given the medium, at the given time step step. Note that b is only a vector of length Nbr (number of branches) rows, provided as a view.\nprecompute_auxiliaries!(method::TimeSuperpositionMethod; options): Compute inplace in method the auxiliary quantities used in the simulation that can be performed ahead of time.\nupdate_auxiliaries!(::TimeSuperpositionMethod, X, borefield, step): Update inplace in method the auxiliaries after each time step step.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-6","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"ConvolutionMethod","category":"page"},{"location":"api/#BoreholeNetworksSimulator.ConvolutionMethod","page":"API","title":"BoreholeNetworksSimulator.ConvolutionMethod","text":"ConvolutionMethod{T} <: TimeSuperpositionMethod \nConvolutionMethod()\n\nUse the naïve convolution to compute the thermal response between boreholes. It should be initialized without arguments, but it contains the variables:\n\ng stores the unit response between each pair of boreholes evaluated at each time of the simulation. \n\nIt should be precomputed with initialize.\n\nq stores the heat extraction in each borehole at each time step. It is filled as the simulation runs. \n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"NonHistoryMethod","category":"page"},{"location":"api/#BoreholeNetworksSimulator.NonHistoryMethod","page":"API","title":"BoreholeNetworksSimulator.NonHistoryMethod","text":"NonHistoryMethod{T} <: TimeSuperpositionMethod \nNonHistoryMethod()\n\nUse 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:\n\nF::Matrix{T}: each column contains the F function (encoding the load history) for each borehole. It is initially 0.\nζ::Vector{T}: discretization nodes of the integration interval. Shared for all boreholes. Precomputed in initialize.\nw::Matrix{T}: weights of the ζ integration for each pair of boreholes. Precomputed in initialize.\nexpΔt::Vector{T}: exp(-ζ^2*Δt). Precomputed in initialize.\n\nThis feature is experimental and might not work as expected in some cases. \n\n\n\n\n\n","category":"type"},{"location":"api/#Boundary-Condition","page":"API","title":"Boundary Condition","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the ground surface.","category":"page"},{"location":"api/","page":"API","title":"API","text":"BoundaryCondition","category":"page"},{"location":"api/#BoreholeNetworksSimulator.BoundaryCondition","page":"API","title":"BoreholeNetworksSimulator.BoundaryCondition","text":"abstract type BoundaryCondition\n\nInterface for boundary conditions.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-7","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"NoBoundary","category":"page"},{"location":"api/#BoreholeNetworksSimulator.NoBoundary","page":"API","title":"BoreholeNetworksSimulator.NoBoundary","text":"NoBoundary <: BoundaryCondition\n\nOption to solve the problem in an infinite domain \n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"DirichletBoundaryCondition","category":"page"},{"location":"api/#BoreholeNetworksSimulator.DirichletBoundaryCondition","page":"API","title":"BoreholeNetworksSimulator.DirichletBoundaryCondition","text":"DirichletBoundaryCondition <: BoundaryCondition\n\nOption to enforce that the surface plane z=0 remains at temperature T=0\n\n\n\n\n\n","category":"type"},{"location":"Braedstrup/#Example:-Braedstrup-borefield","page":"Braedstrup borefield","title":"Example: Braedstrup borefield","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"The example considers a borehole field of 48 boreholes connected according to scheme utilized in the installation in Braedstrup, Denmark. The source code of this example can be found in examples/Braedstrup/main.jl. The field is in a porous medium with an underground water flow of 001 fracmtextday, which we assume to be in the x direction. The borefield consists of 8 branches, each branch in parallel, and within each branch there are 6boreholes in series. The positions and connections are represented in the following plot: ","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"(Image: )","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"During the summer, heat is injected in the field with a fluid at a constant temperature of 90C through all the branches from the center of the field. During the winter, heat is extracted by circulating the fluid at a temperature of 55C from the external end of each branch and collected at the center. The simulation is done with a monthly time step duting 10 years.","category":"page"},{"location":"Braedstrup/#Run-the-example","page":"Braedstrup borefield","title":"Run the example","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"include(\"examples/Braedstrup/main.jl\")","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"The elapsed times for the precomputation and computation phases are:","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"2.449359 seconds (570.20 k allocations: 109.171 MiB, 0.66% gc time)\n0.140535 seconds (255.75 k allocations: 49.735 MiB, 62.17% compilation time: 100% of which was recompilation)","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"We can extract the result of the simulation ","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"julia> containers.X\n192×120 Matrix{Float64}:\n 192×120 Matrix{Float64}:\n 90.0 90.0 90.0 90.0 90.0 … 54.1785 53.5253 53.0836 52.7797\n 85.7196 86.3321 86.6953 86.9358 87.1041 53.3354 52.6224 52.1367 51.7994\n 85.7196 86.3321 86.6953 86.9358 87.1041 54.8461 54.2727 53.8868 53.6232\n 81.7574 83.051 83.8273 84.3361 84.6863 54.1785 53.5253 53.0836 52.7797\n ⋮ ⋱ \n 153.897 118.897 93.5639 74.8265 60.7942 -27.2873 -20.0578 -14.7582 -10.8234\n 144.883 112.083 87.7717 69.5736 55.8771 -29.8091 -21.8784 -16.1027 -11.856\n 136.767 108.025 86.4461 69.9911 57.3688 … -28.6089 -20.7213 -15.0661 -10.9335\n 149.022 124.549 105.729 90.6145 78.3994 -22.1191 -15.7456 -11.0385 -7.4812","category":"page"},{"location":"Braedstrup/#Plots","page":"Braedstrup borefield","title":"Plots","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"In order to visualize the results, we can use the subpackage BNSPlots. For more details, refer to [Visualizing the result with BNSPlots](@ref).","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"Inlet borehole temperatures and heat flows for boreholes along two branches in the borehole field. The time series are color coded according to the previous configuration plot above. In addition to the inlet temperature, the output temperature from the branch (grey dot), and the mean output temperature from the field (black dot) are displayed.","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"(Image: ) (Image: )","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"Finally we can display the heatmap of the temperature field in the borehole region during the 10th year of operation","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"(Image: )","category":"page"},{"location":"Braedstrup/#Running-the-code-in-Python","page":"Braedstrup borefield","title":"Running the code in Python","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"The example is also avaiable from Python. For details of how this is done refer to Running BoreholeNetworksSimulator from Python. The Python version is in:","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"examples/Braedstrup/main.py","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"EditURL = \"nonhistory.jl\"","category":"page"},{"location":"nonhistory/#Non-history-method","page":"Non-history method","title":"Non-history method","text":"","category":"section"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"The non-history method is a time superposition method introduced in [1] whose computational complexity in the number of time steps N_t is mathcalOleft( N_t right). Recall that the standard way to do time superposition is via the convolution of the load with the response, which implemented via the Fast Fourier Transform, yields a computational complexity of mathcalOleft( N_t logN_t right). This means that using the non-history method in simulations allows for finer time steps.","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"To show this, let us run a simulation with hourly time steps, with a duration of 1 year (so 8760 time steps), with both the convolution and the non-history time superposition methods. Let us define an example, very similar to Basic tutorial","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"using BoreholeNetworksSimulator","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"Δt = 3600.\nNt = 8760\n\nmedium = GroundMedium(α=1e-6, λ=3., T0=10.)\nborehole = SingleUPipeBorehole(H=100., D=10.)\npositions = [(0., 0.), (0., 5.)]\nborefield = EqualBoreholesBorefield(borehole_prototype=borehole, positions=positions)\nconstraint = constant_HeatLoadConstraint(5 .* ones(BoreholeNetworksSimulator.n_boreholes(borefield)), Nt)\nfluid = Water()\n\nconfigurations = [BoreholeNetwork([[1], [2]])]\noperator = SimpleOperator(mass_flow = 2., branches = 2)","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"Now, we define two different options using different method parameters, one with ConvolutionMethod corresponding to the convolution, and the other with NonHistoryMethod, corresponding with the non-history method.","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"options_convolution = SimulationOptions(\n method = ConvolutionMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = fluid,\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)\n\noptions_nonhistory = SimulationOptions(\n method = NonHistoryMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = fluid,\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"Let us run the convolution","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"containers_convolution = @time initialize(options_convolution)\n@time simulate!(operator=operator, options=options_convolution, containers=containers_convolution)","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"And now let us run the non-history","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"containers_nonhistory = @time initialize(options_nonhistory)\n@time simulate!(operator=operator, options=options_nonhistory, containers=containers_nonhistory)\n\nabs.(containers_convolution.X - containers_nonhistory.X)","category":"page"},{"location":"nonhistory/#References","page":"Non-history method","title":"References","text":"","category":"section"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"[1] Lazzarotto, Alberto; Basquens, Marc; Cimmino, Massimo; Non-history dependent temporal superposition algorithm for the point source solution, Research Conference Proceedings of the IGSHPA (2024).","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"This page was generated using Literate.jl.","category":"page"},{"location":"python/#Running-BoreholeNetworksSimulator-from-Python","page":"Running from python","title":"Running BoreholeNetworksSimulator from Python","text":"","category":"section"},{"location":"python/","page":"Running from python","title":"Running from python","text":"It is also possible to run BoreholeNetworksSimulator from Python by using its Julia interoperability (achieved with the package PythonCall.jl and the module juliacall) while keeping roughly the same syntax. For a more detailed explanation of how this works, please visit the PythonCall.jl documentation. This requires to have installed in your python environment the modules juliacall and numpy.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"BoreholeNetworksSimulator.jl contains a second Julia module called BNSPythonAdapter whose purpose is to make the necessary conversions between Python and Julia. This module is not intended to be used from Julia, but from within Python. In this tutorial, we will repeat the example in Basic tutorial but run from Python to show how it works. The full example as a Python script in at BNSPythonAdapter/example.py.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"BNSPythonAdapter contains a python script src/adapter.py that executes the necessary bridging code. You should start your python program by importing this module. Assuming that the directory BNSPythonAdapter is added to the sys.path, this should work:","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"import src.adapter","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"The script takes care of activating the Julia package BNSPythonAdapter which has BoreholeNetworksSimulator as a dependency, and loads both namespaces for later use. It also defines conversions from Python objects to their Julia counterparts. Next, we need to import juliacall to be able to reference objects and funcions from BoreholeNetworksSimulator. It is useful to give it an alias for conciseness.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"from juliacall import Main as jl","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Now, the python variable jl represents the Main module in Julia, and it has as methods all the Julia functions available in it. Since we imported the namespace BoreholeNetworksSimulator, this also includes its objects and functions.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Then, we define the same variables as in Basic tutorial:","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Δt = 8760*3600/12.\nNt = 10*12\n\nα = 1e-6\nλ = 3.\nT0 = 10.\nmedium = jl.GroundMedium(α=α, λ=λ, T0=T0)\n\nD = 10.\nH = 100.\n\nborehole = jl.SingleUPipeBorehole(H=H, D=D)\n\nσ = 5.\npositions = jl.Array[jl.Tuple[jl.Float64, jl.Float64]]([(0., 0.), (0., σ)])\nborefield = jl.EqualBoreholesBorefield(borehole_prototype=borehole, positions=positions)\n\nconfigurations = [jl.BoreholeNetwork(jl.Vector[jl.Vector[jl.Int]]([[1], [2]]))]\n\nq1 = 5.\nq2 = 5.\nloads = jl.Array[jl.Float64]([q1, q2])\nconstraint = jl.constant_HeatLoadConstraint(loads, Nt)\n\noptions = jl.SimulationOptions(\n method = jl.ConvolutionMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = jl.Water(),\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Note that the code itself is not very different from its Julia version, but there are two remarks worth making. First, we need to call any object defined in Julia by typing jl. in front. This creates a python object with the same fields that PythonCall.jl knows how to convert back into a Julia object. Second, note that we have defined the arrays by explicitly declaring their generic type. If we don't do this, they will be converted into Vector{Any} in the Julia code, which is not desirable.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Another difference is the definition of our [Operator](@ref) object. Since we are writing python, it should now be a python object with a method operate that returns an object of type jl.BoreholeOperation, which PythonCall.jl knows how to convert to BoreholeOperation. For the ssake of the example, we will implement again the [SimpleOperator](@ref) operator that is already implemented in Julia. For further examples, check the python version of the code for [Example: Braedstrup borefield ](@ref).","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"class SimpleOperator():\n def __init__(self, mass_flow, branches):\n self.mass_flows = jl.Vector[jl.Float64](mass_flow * np.ones(branches))\n\n def operate(self, i, options, Tfin, Tfout, Tb, q):\n return jl.BoreholeOperation(options.configurations[0], operator.mass_flows)\n\n\noperator = SimpleOperator(2., 2)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Note that this is equivalent to calling the same code from Julia:","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"operator = jl.SimpleOperator(mass_flow = 2., branches = 2)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Finally we can run the simulation","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"containers = jl.initialize(options)\njl.simulate_b(operator=operator, options=options, containers=containers)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Note that the bang in simulate! is replaced by a _b in the juliacall version of the function. ","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"containers.X","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Now, one can compare this result with its Julia version. If everything went right, they should agree!","category":"page"},{"location":"#BoreholeNetworksSimulator.jl","page":"Introduction","title":"BoreholeNetworksSimulator.jl","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"BoreholeNetworksSimulator.jl is a pure Julia, performant, and modular framework for simulations of fields of interconnected borehole heat exchangers. Features:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"Computes fluid temperatures, borehole wall temperatures and heat extracted. \nSupports many different configurations and settings by being highly modular: boreholes, hydraulic configurations, ground properties, load demand or temperature constraints, ground boundary conditions can be seamlessly used with minimal effort. \nAllows for design of operation strategies via an operator callback at each time step.\nImplements the \"non-history\" time superposition method, reducing the computational complexity in the number of time steps to linear. This allows for simulations with fine time steps.\nPython interoperability.","category":"page"},{"location":"#Getting-started","page":"Introduction","title":"Getting started","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"BoreholeNetworksSimulator.jl is currently not in Julia's General registry (as well as some of its dependencies), however, it is easily available through the local registry geothermal_registry. In order to install it, start Julia and run the command:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"using Pkg; pkg\"registry add https://github.com/marcbasquensmunoz/geothermal_registry\"; Pkg.add(\"BoreholeNetworksSimulator\")","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"In order to learn how to use this package, please visit Basic tutorial first.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"For users interested in running BoreholeNetworksSimulator.jl from Python, see also Running BoreholeNetworksSimulator from Python.","category":"page"},{"location":"#Design-philosophy","page":"Introduction","title":"Design philosophy","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"The driving motivation when developing BoreholeNetworksSimulator.jl was to create an easy to use tool that is also highly flexible and performant.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"This goal has been accomplished by leveraging Julia's Multiple Dispatch. Through a simple, common interface, the user can run a plethora of different simulations by modularly specifying options. Some options have physical meaning or interpretation, while others are purely algorithmic, yet they can all be seamlessly changed by changing a parameter. Please, refer to Public API for the full list of options offered by this package.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"EditURL = \"tutorial.jl\"","category":"page"},{"location":"tutorial/#Basic-tutorial","page":"Basic tutorial","title":"Basic tutorial","text":"","category":"section"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"In this tutorial we will learn how to simulate the expected temperature and heat extraction in a borehole field.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"First, we need to specify the parameters and constraints of our system, as well as some options for the simulation. This is done through a SimulationOptions object. Its variables are modular components with which we can describe many scenarios by leveraging Julia's multiple dispatch. Let us see the components one by one with an example.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"We start by specifying the simulation time step and the simulation duration. For our example, we will take monthly time steps during 10 years:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"using BoreholeNetworksSimulator\n\nΔt = 8760*3600/12.\nNt = 10*12","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Suppose the ground we are interested in simulating is made of solid rock. This means the heat transfer will occur by pure conduction. Assume that the thermal diffusivity of the rock is α = 10^-6 fracm^2s and its thermal conductivity is λ = 3 fracWm K. The undisturbed temperature of the ground is T_0=10 ^circC. We model the ground with a subtype of Medium, in our case, as per our assumptions, we are particularly interested in GroundMedium:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"α = 1e-6\nλ = 3.\nT0 = 10.\nmedium = GroundMedium(α=α, λ=λ, T0=T0)\n\n\nD = 10.\nH = 100.\nborehole = SingleUPipeBorehole(H=H, D=D)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Next, we need to know how and where the boreholes in our system are. Suppose we are interested in simulating the evolution of two identical vertical boreholes of length H=100m and buried at depth D=10m, separated by a distance of σ=5m. The boreholes are of the U-type. We need to enconde this information in a subtype of Borefield. Since the boreholes in our example have the same properties, we can use EqualBoreholesBorefield, which instantiates several identical boreholes from a prototype. The prototype is specified by a subtype of Borehole. In our case, we can use SingleUPipeBorehole to model a borehole with a single U-pipe.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"D = 10.\nH = 100.\n\nborehole = SingleUPipeBorehole(H=H, D=D)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"There are more parameters that are also relevant, such as borehole radius, grout properties, pipe resistance, etc., but for the moment we will use their default values.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Next, we need to specify where the borehole are located.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"σ = 5.\npositions = [(0., 0.), (0., σ)]\nborefield = EqualBoreholesBorefield(borehole_prototype=borehole, positions=positions)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Note that we didn't specify yet how the boreholes are connected. This is because the simulation allows for dynamical changes in the network hydraulic configuration. Using different configurations, we can simulate the reverse flow, or even simulate valves opening and closing. The reason behind this design is to allow for decision making on the operation of the borefield during the simulation, based on the inputs that we are interested in.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"For now, let us state the possible hydraulic configurations that we will allows our borefield to be in. This is done with an vector of BoreholeNetwork. Borefields usually have several branches of boreholes. Each borehole in a branch is connected in series, while branches may o may not be connected in parallel between themselves. To create a BoreholeNetwork, we need to provide all of its branches in a vector. Each branch is, in turn, a vector containing the identifiers, in order, of the boreholes present in that branch. Each identifier i::Int refers to the borehole located at position positions[i].","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"In our example, we want to simulate two independent boreholes, so each of them must be in a separate branch. Also, for the moment, we are only interested in this configuration, so we define:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"configurations = [BoreholeNetwork([[1], [2]])]","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Even with all these specifications, the evolution of the system is still not fully determined. The missing conditions are referred to as constraints, and are modeled by subtypes of Constraint. For instance, if we would like the two boreholes to be connected in parallel, we would still need to impose that their inlet temperatures be equal. In our example, since we want out boreholes to be independent, we will impose the total amount of heat that we want to extract from each borehole. We will impose a constant load, equal for both boreholes. This is specified by","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"q1 = 5.\nq2 = 5.\nconstraint = constant_HeatLoadConstraint([q1, q2], Nt)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"We can finally create the object with all the options:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"options = SimulationOptions(\n method = ConvolutionMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = Water(),\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"As we have mentioned, the simulation is designed to allow for a controllable opeartion during its duration. We do this by creating a subtype of Operator containing the operation strategy. Then, we must implement a method of the function operate with our Operator subtype, that takes as an input the current state of the borefield and outputs a BoreholeOperation object. BoreholeOperation has two variables: the first specifies which configuration will be used for the next time step. In our case, we only want a static, simple configuration. The second specifies the mass flow rate through each branch of the selected configuration, provided as a vector. In our example, we will keep this constant through the simulation. For this purpose, there exists the type SimpleOperator, that implements precisely this strategy.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"operator = SimpleOperator(mass_flow = 2., branches = 2)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Before simulating, we first need to call initialize to run some precomputations that will be used throught the simulation and to instantiate containers where the result will be written.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"containers = initialize(options)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"And finally, we can start the simulation.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"@time simulate!(operator=operator, options=options, containers=containers)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"The simulation is over! Note that the bulk of the time is spent in the precoputation, while the simulation itself is quite fast. This is especially good if we want to test different operation strategies.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"The result is saved in","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"containers.X","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Each column in containers.X contains the results for a time step. In each column, the first 2 N_b correspond to the fluid temperatures. In particular, the odd entries containers.X[1:2:2Nb, :] are the inlet temperatures, while the even entries containers.X[2:2:2Nb, :] are the outlet temperatures of each borehole. The next Nb values containers.X[2Nb+1:3Nb, :] are the borehole wall temperatures. The last Nb values containers.X[3Nb+1:4Nb, :] are the heat extraction of each borehole.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"This page was generated using Literate.jl.","category":"page"}] +[{"location":"BNSPlots/#Visualizing-the-result-with-BNSPlots","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"","category":"section"},{"location":"BNSPlots/","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"The repository contains a subpackage called BNSPlots that contains useful convenience functions to easily display the results obtained from BoreholeNetworksSimulator.","category":"page"},{"location":"BNSPlots/#Reference","page":"Visualizing the result with BNSPlots","title":"Reference","text":"","category":"section"},{"location":"BNSPlots/","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"plot_borefield","category":"page"},{"location":"BNSPlots/#BNSPlots.plot_borefield","page":"Visualizing the result with BNSPlots","title":"BNSPlots.plot_borefield","text":"plot_borefield(network, positions; distinguished_branches = [], colors = [])\n\nMakes a plot of the borefield, showing the boreholes numbered and their connections.\n\nArguments\n\nnetwork: Network specifying the connections between boreholes.\npositions: The positions of each borehole.\n\nOptional arguments\n\ndistinguished_branches: Vector of Int. If specified, the branches corresponding to the given values will be highlighted with the colors of colors.\ncolors: Vector of Tuples of Color. If specified, uses each pair of colors to define a color gradient to color each of the branches of distinguished_branches.\n\n\n\n\n\n","category":"function"},{"location":"BNSPlots/","page":"Visualizing the result with BNSPlots","title":"Visualizing the result with BNSPlots","text":"monitor","category":"page"},{"location":"BNSPlots/#BNSPlots.monitor","page":"Visualizing the result with BNSPlots","title":"BNSPlots.monitor","text":"monitor(containers, branch, t; steps = 1:length(t), display = [:Tfin, :Tfout, :Tb, :q], Δt = :year, color_pair = (colorant\"navajowhite2\", colorant\"darkgreen\")\n\nCreates a plot of the result of the simulation.\n\nArguments\n\ncontainers: The containers (SimulationContainers) containing the result of the simulation through simulate!.\nbranch: A vector containing the IDs of the boreholes whose data will be displayed. \nt: The times at which the data corresponds. It should normally be options.t.\n\nOptional arguments\n\nsteps: Index of the steps to display in the plot.\ndisplay: A vector describing which plots that will be generated. If :Tfin, :Tfout or :Tb are specified, a temperature plot will be created showing the inlet fluid temperature, the outlet fluid temperature, and the borehole wall temperature, respectively. If :q is specified, a separate power plot will be created shwoing the heat extracted per meter.\nΔt: The scale of the x-axis in the plot. Possible options: :year, :month, :hour.\ncolor_pair: A pair of colors used as extrema to generate a range of colors for each borehole. \n\n\n\n\n\n","category":"function"},{"location":"api/#Public-API","page":"API","title":"Public API","text":"","category":"section"},{"location":"api/#General","page":"API","title":"General","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"These are the functions used to run the simulation. Note that an object of type SimulationOptions is needed to call them.","category":"page"},{"location":"api/","page":"API","title":"API","text":"initialize","category":"page"},{"location":"api/#BoreholeNetworksSimulator.initialize","page":"API","title":"BoreholeNetworksSimulator.initialize","text":"initialize(options::SimulationOptions)\n\nPrecompute the objects of each TimeSuperpositionMethod that can be computed ahead of time and return the SimulationContainers of the required size.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"simulate!","category":"page"},{"location":"api/#BoreholeNetworksSimulator.simulate!","page":"API","title":"BoreholeNetworksSimulator.simulate!","text":"simulate!(;options::SimulationOptions, operator, containers::SimulationContainers)\n\nRun the simulation defined by options. At the end of simulation, containers.X will contain the results. containers should be the output of initialize.\n\noperator should be a function that returns a BoreholeOperation and with signature operator(i, Tin, Tout, Tb, q, configurations):\n\ni::Int is the time step\nTin is a vector containing the inlet temperature of each borehole\nTout is a vector containing the outlet temperature of each borehole\nTb is a vector containing the borehole wall temperature of each borehole\nq is a vector containing the heat exchanged by each borehole\nconfigurations: is the list of possible hydraulic configurations of the borefield.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"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.","category":"page"},{"location":"api/","page":"API","title":"API","text":"BoreholeNetwork","category":"page"},{"location":"api/#BoreholeNetworksSimulator.BoreholeNetwork","page":"API","title":"BoreholeNetworksSimulator.BoreholeNetwork","text":"BoreholeNetwork(branches::Vector{Vector{Int}})\n\nRepresentation of the hydraulic connections of the boreholes in the network. Each element in branches should be a vector representing a branch of boreholes connected in series, specified by their identifiers. The first borehole of each branch is assumed to be connected in parallel. \n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"BoreholeOperation","category":"page"},{"location":"api/#BoreholeNetworksSimulator.BoreholeOperation","page":"API","title":"BoreholeNetworksSimulator.BoreholeOperation","text":"BoreholeOperation{Arr <: AbstractArray}(\n network::BoreholeNetwork \n mass_flows::Arr\n)\n\nRepresents a operation state of the network, with network representing the hydraulic configuration and mass_flows a Vector containing the mass flow rate of each branch.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"Operator","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Operator","page":"API","title":"BoreholeNetworksSimulator.Operator","text":"abstract type Operator\n\nInterface for operation strategies.\n\nRequired functions:\n\noperate(::Operator, i, options, Tfin, Tfout, Tb, q): Return a BoreholeOperation.\n\n\n\n\n\n","category":"type"},{"location":"api/#Prewritten-operator-strategies","page":"API","title":"Prewritten operator strategies","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"SimpleOperator","category":"page"},{"location":"api/#BoreholeNetworksSimulator.SimpleOperator","page":"API","title":"BoreholeNetworksSimulator.SimpleOperator","text":"SimpleOperator{T <: Number} <: Operator (\n mass_flows::Vector{T}\n)\n\nConstant operation strategy, always returning BoreholeOperation(options.configurations[1], operator.mass_flows).\n\n\n\n\n\n","category":"type"},{"location":"api/#Simulation-Options","page":"API","title":"Simulation Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"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.","category":"page"},{"location":"api/","page":"API","title":"API","text":"SimulationOptions","category":"page"},{"location":"api/#BoreholeNetworksSimulator.SimulationOptions","page":"API","title":"BoreholeNetworksSimulator.SimulationOptions","text":"struct SimulationOptions{\n N <: Number,\n Tol <: Number,\n TSM <: TimeSuperpositionMethod,\n C <: Constraint,\n B <: Borefield, \n M <: Medium, \n BC <: BoundaryCondition,\n A <: Approximation,\n F <: Fluid\n }(\n method::TSM\n constraint::C\n borefield::B\n medium::M\n boundary_condition::BoundaryCondition = DirichletBoundaryCondition()\n approximation::A = MeanApproximation()\n fluid::Fluid{N} = Fluid(cpf=4182., name=\"INCOMP::MEA-20%\")\n configurations::Vector{BoreholeNetwork}\n Δt\n Nt::Int\n atol::Tol = 0.\n rtol::Tol = sqrt(eps())\n)\n\nSpecifies all the options for the simulation.\n\nmethod: time superposition method used to compute the response. Available options: ConvolutionMethod, NonHistoryMethod.\nconstraint: constraint that the system must satisfy. Can be variable with time. Available options: HeatLoadConstraint, InletTempConstraint, TotalHeatLoadConstraint.\nborefield: describes the geometrical properties and the boreholes of the borefield on which the simulation will be performed. Available options: EqualBoreholesBorefield.\nmedium: properties of the ground where the borefield is places. Available options: GroundMedium, FlowInPorousMedium.\nboundary_condition: boundary condition of the domain where the simulation is performed. Available options: NoBoundary, DirichletBoundaryCondition, AdiabaticBoundaryCondition.\napproximation: determines how the approximate value for each segment is computed. Available options: MeanApproximation, MidPointApproximation.\nfluid: properties of the fluid flowing through the hydraulic system.\nconfigurations: possible hydraulic topologies possible in the system, including reverse flow.\nΔt: time step used in the simulation.\nNt: total amount of time steps of the simulation.\natol: absolute tolerance used for the adaptive integration methods.\nrtol: relative tolerance used for the adaptive integration methods.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"The several options are listed below:","category":"page"},{"location":"api/#Fluid","page":"API","title":"Fluid","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the fluid used in the hydraulic system.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Fluid","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Fluid","page":"API","title":"BoreholeNetworksSimulator.Fluid","text":"abstract type Fluid end\n\nInterface for fluids.\n\nRequired functions:\n\ncpf(::Fluid): Return the scpecific heat capacity of the fluid.\nthermophysical_properties(::Fluid, T): Return the μ, ρ, cp, and k of the fluid at temperature T.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Water","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Water","page":"API","title":"BoreholeNetworksSimulator.Water","text":"Water <: Fluid (\n stored_properties::ThermophysicalProperties{Float64}\n)\n\nModels water.\n\nTo initialize, use the convenience method: function Water() that will automatically compute stored_properties.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"EthanolMix","category":"page"},{"location":"api/#BoreholeNetworksSimulator.EthanolMix","page":"API","title":"BoreholeNetworksSimulator.EthanolMix","text":"EthanolMix <: Fluid (\n stored_properties::ThermophysicalProperties{Float64}\n)\n\nModels a 20% ethanol and water mix.\n\nTo initialize, use the convenience method: function EthanolMix() that will automatically compute stored_properties.\n\n\n\n\n\n","category":"type"},{"location":"api/#Medium","page":"API","title":"Medium","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the underground medium through which the heat will transfer between boreholes.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Medium","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Medium","page":"API","title":"BoreholeNetworksSimulator.Medium","text":"abstract type Medium\n\nInterface for mediums.\n\nRequired functions:\n\nget_λ(::Medium): Return the thermal conductivity of the medium.\nget_α(::Medium): Return the thermal diffusivity of the medium.\nget_T0(::Medium): Return the initial temperature of the medium.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-2","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"GroundMedium","category":"page"},{"location":"api/#BoreholeNetworksSimulator.GroundMedium","page":"API","title":"BoreholeNetworksSimulator.GroundMedium","text":"GroundMedium{T <: Real} <: Medium @deftype T\n\nModel pure conduction in the ground.\n\nArguments\n\nλ = 3.: ground conductivity\nα = 1e-6: ground thermal diffusivity\nC = λ/α: ground medium capacity\nT0 = 0.: initial ground temperature\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"FlowInPorousMedium","category":"page"},{"location":"api/#BoreholeNetworksSimulator.FlowInPorousMedium","page":"API","title":"BoreholeNetworksSimulator.FlowInPorousMedium","text":"FlowInPorousMedium{T <: Real} <: Medium @deftype T\n\nModel a porous ground with a water flow.\n\nArguments\n\nλw = 0.6: water thermal conductivity\nλs = 2.: ground thermal conductivity\nCw = 4.18*1e6:water thermal capacity\nCs = 1.7*1e6: ground thermal capacity\nθ = 0.: angle of Darcy velocity\nΦ = 0.2: porosity\nλ = λs * (1-Φ) + λw*Φ: porous medium conductivity\nC = Cs * (1-Φ) + Cw*Φ: porous medium capacity\nα = λ/C: porous medium thermal diffusivity\nux_in_meterperday = 1e-2: groundwater speed along the flow coordinate\nux = ux_in_meterperday/(3600*24): groundwater speed in m/s\nvt = ux * Cw/C: porous medium darcy velocity\nT0 = 0.: initial ground temperature\n\n\n\n\n\n","category":"type"},{"location":"api/#Borefield","page":"API","title":"Borefield","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the geometry of the borefield.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Borefield","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Borefield","page":"API","title":"BoreholeNetworksSimulator.Borefield","text":"abstract type Borefield\n\nInterface for borefields.\n\nRequired functions\n\nn_boreholes(::Borefield): Return the amount of boreholes present in the borefield.\nget_H(::Borefield, i): Return the length of borehole i.\nget_rb(::Borefield, i): Return the radius of borehole i.\nsegment_coordinates(::Borefield): Return a vector with the coordinates of each segment. \ninternal_model_coeffs!(M, ::Borefield, medium, operation, fluid): Compute inplace in M the coefficients corresponding to the internal model equations, given the medium, fluid and operation in use in the system. Note that M is only a slice of Nb (number of boreholes) rows, provided as a view.\ninternal_model_b!(b, ::Borefield): Compute inplace in b the independent terms corresponding to the internal model equations. Note that b is only a vector of length Nb (number of boreholes) rows, provided as a view.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-3","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"EqualBoreholesBorefield","category":"page"},{"location":"api/#BoreholeNetworksSimulator.EqualBoreholesBorefield","page":"API","title":"BoreholeNetworksSimulator.EqualBoreholesBorefield","text":"EqualBoreholesBorefield{T <: Borehole, R <: Medium, S <: Real} <: Borefield\nEqualBoreholesBorefield(borehole_prototype::T, positions::Vector{Point2{S}}), medium::R)\n\nModel 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. medium contains the properties of the ground.\n\n\n\n\n\n","category":"type"},{"location":"api/#Borehole","page":"API","title":"Borehole","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the internal heat transfer in the borehole.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Borehole","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Borehole","page":"API","title":"BoreholeNetworksSimulator.Borehole","text":"abstract type Borehole\n\nInterface for boreholes.\n\nRequired functions:\n\nget_H(::Borehole): Return the length of the borehole.\nget_D(::Borehole): Return the burial depth of the borehole.\nget_rb(::Borehole): Return the radius of the borehole.\nuniform_Tb_coeffs(::Borehole, λ, mass_flow, Tref, fluid): Return the internal model coefficients for the resistance network between the pipes and the wall.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-4","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"SingleUPipeBorehole","category":"page"},{"location":"api/#BoreholeNetworksSimulator.SingleUPipeBorehole","page":"API","title":"BoreholeNetworksSimulator.SingleUPipeBorehole","text":"SingleUPipeBorehole{T <: Real} <: Borehole @deftype T\nSingleUPipeBorehole(H, D)\n\nModel a borehole with a single U-pipe with burial depth D and length H.\n\nArguments\n\nλg = 2.5: grout conductivity\nCg = 2000. * 1550.: grout capacity\nαg = λg/Cg: grout thermal diffusivity\nrp = 0.02: pipe radius\nλp = 0.42: pipe material conductivity\ndpw = 0.0023: pipe thickness\nrpo = rp + dpw: equivalent pipe radius\nhp = 725.: heat transfer coefficient fluid to pipe\npipe_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.\nrb = 0.115/2: borehole radius\n\n\n\n\n\n","category":"type"},{"location":"api/#Constraint","page":"API","title":"Constraint","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Imposes the working conditions and demands of the whole system.","category":"page"},{"location":"api/","page":"API","title":"API","text":"Constraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.Constraint","page":"API","title":"BoreholeNetworksSimulator.Constraint","text":"abstract type Constraint\n\nInterface for constraints.\n\nRequired functions:\n\nconstraints_coeffs!(M, ::Constraint, operation::BoreholeOperation): Compute inplace in M the coefficients corresponding to the constraints equations, given the current operation.network. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.\nconstraints_b!(b, ::Constraint, ::BoreholeOperation, step): Compute inplace in b the independent term corresponding to the constraints equations, given the current operation.network, at the time step step. Note that b is only a vector of length Nbr (number of branches), provided as a view.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-5","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"HeatLoadConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.HeatLoadConstraint","page":"API","title":"BoreholeNetworksSimulator.HeatLoadConstraint","text":"HeatLoadConstraint(Q_tot::Matrix{T}){T <: Number} <: Constraint\n\nConstrain the heat extracted per branch.\n\nThe 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.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"constant_HeatLoadConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.constant_HeatLoadConstraint","page":"API","title":"BoreholeNetworksSimulator.constant_HeatLoadConstraint","text":"constant_HeatLoadConstraint(Q_tot::Vector{T}, Nt) where {T <: Number}\n\nConvenience 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.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"uniform_HeatLoadConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.uniform_HeatLoadConstraint","page":"API","title":"BoreholeNetworksSimulator.uniform_HeatLoadConstraint","text":"uniform_HeatLoadConstraint(Q_tot::Vector{T}, Nbr) where {T <: Number}\n\nConvenience initializer for HeatLoadConstraint. It creates a uniform heat load constraint along all branches, where T_in are the heat load for each time step.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"InletTempConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.InletTempConstraint","page":"API","title":"BoreholeNetworksSimulator.InletTempConstraint","text":"InletTempConstraint(T_in::Matrix{T}){T <: Number} <: Constraint\n\nConstrain the inlet temperature of the first borehole in each branch.\n\nThe inlet temperature T_in must be a 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.\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"constant_InletTempConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.constant_InletTempConstraint","page":"API","title":"BoreholeNetworksSimulator.constant_InletTempConstraint","text":"constant_InletTempConstraint(T_in::Vector{N}, Nt) where {N <: Number}\n\nConvenience 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.\n\n\n\n\n\n","category":"function"},{"location":"api/","page":"API","title":"API","text":"uniform_InletTempConstraint","category":"page"},{"location":"api/#BoreholeNetworksSimulator.uniform_InletTempConstraint","page":"API","title":"BoreholeNetworksSimulator.uniform_InletTempConstraint","text":"uniform_InletTempConstraint(T_in::Vector{N}, Nbr) where {N <: Number}\n\nConvenience initializer for InletTempConstraint. It creates a uniform inlet temperature constraint along all branches, where T_in are the inlet temperatures for each time step.\n\n\n\n\n\n","category":"function"},{"location":"api/#Time-Superposition-Method","page":"API","title":"Time Superposition Method","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Applies methods for time superposition.","category":"page"},{"location":"api/","page":"API","title":"API","text":"TimeSuperpositionMethod","category":"page"},{"location":"api/#BoreholeNetworksSimulator.TimeSuperpositionMethod","page":"API","title":"BoreholeNetworksSimulator.TimeSuperpositionMethod","text":"abstract type TimeSuperpositionMethod\n\nInterface for time superposition methods.\n\nRequired functions:\n\nmethod_coeffs!(M, ::TimeSuperpositionMethod, options): Compute inplace in M the coefficients corresponding to the heat transfer equations, given options. Note that M is only a slice of Nbr (number of branches) rows, provided as a view.\nmethod_b!(b, ::TimeSuperpositionMethod, borefield, medium, step): Compute inplace in b the independent terms corresponding to the heat transfer equations, given the medium, at the given time step step. Note that b is only a vector of length Nbr (number of branches) rows, provided as a view.\nprecompute_auxiliaries!(method::TimeSuperpositionMethod; options): Compute inplace in method the auxiliary quantities used in the simulation that can be performed ahead of time.\nupdate_auxiliaries!(::TimeSuperpositionMethod, X, borefield, step): Update inplace in method the auxiliaries after each time step step.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-6","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"ConvolutionMethod","category":"page"},{"location":"api/#BoreholeNetworksSimulator.ConvolutionMethod","page":"API","title":"BoreholeNetworksSimulator.ConvolutionMethod","text":"ConvolutionMethod{T} <: TimeSuperpositionMethod \nConvolutionMethod()\n\nUse the naïve convolution to compute the thermal response between boreholes. It should be initialized without arguments, but it contains the variables:\n\ng stores the unit response between each pair of boreholes evaluated at each time of the simulation. \n\nIt should be precomputed with initialize.\n\nq stores the heat extraction in each borehole at each time step. It is filled as the simulation runs. \n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"NonHistoryMethod","category":"page"},{"location":"api/#BoreholeNetworksSimulator.NonHistoryMethod","page":"API","title":"BoreholeNetworksSimulator.NonHistoryMethod","text":"NonHistoryMethod{T} <: TimeSuperpositionMethod \nNonHistoryMethod()\n\nUse 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:\n\nF::Matrix{T}: each column contains the F function (encoding the load history) for each borehole. It is initially 0.\nζ::Vector{T}: discretization nodes of the integration interval. Shared for all boreholes. Precomputed in initialize.\nw::Matrix{T}: weights of the ζ integration for each pair of boreholes. Precomputed in initialize.\nexpΔt::Vector{T}: exp(-ζ^2*Δt). Precomputed in initialize.\n\nThis feature is experimental and might not work as expected in some cases. \n\n\n\n\n\n","category":"type"},{"location":"api/#Boundary-Condition","page":"API","title":"Boundary Condition","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"Models the ground surface.","category":"page"},{"location":"api/","page":"API","title":"API","text":"BoundaryCondition","category":"page"},{"location":"api/#BoreholeNetworksSimulator.BoundaryCondition","page":"API","title":"BoreholeNetworksSimulator.BoundaryCondition","text":"abstract type BoundaryCondition\n\nInterface for boundary conditions.\n\n\n\n\n\n","category":"type"},{"location":"api/#Options-7","page":"API","title":"Options","text":"","category":"section"},{"location":"api/","page":"API","title":"API","text":"NoBoundary","category":"page"},{"location":"api/#BoreholeNetworksSimulator.NoBoundary","page":"API","title":"BoreholeNetworksSimulator.NoBoundary","text":"NoBoundary <: BoundaryCondition\n\nOption to solve the problem in an infinite domain \n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"DirichletBoundaryCondition","category":"page"},{"location":"api/#BoreholeNetworksSimulator.DirichletBoundaryCondition","page":"API","title":"BoreholeNetworksSimulator.DirichletBoundaryCondition","text":"DirichletBoundaryCondition <: BoundaryCondition\n\nOption to enforce that the surface plane z=0 remains at temperature T=0\n\n\n\n\n\n","category":"type"},{"location":"api/","page":"API","title":"API","text":"AdiabaticBoundaryCondition","category":"page"},{"location":"api/#BoreholeNetworksSimulator.AdiabaticBoundaryCondition","page":"API","title":"BoreholeNetworksSimulator.AdiabaticBoundaryCondition","text":"AdiabaticBoundaryCondition <: BoundaryCondition\n\nOption to enforce zero heat flow at the surface plane z=0.\n\n\n\n\n\n","category":"type"},{"location":"Braedstrup/#Example:-Braedstrup-borefield","page":"Braedstrup borefield","title":"Example: Braedstrup borefield","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"The example considers a borehole field of 48 boreholes connected according to scheme utilized in the installation in Braedstrup, Denmark. The source code of this example can be found in examples/Braedstrup/main.jl. The field is in a porous medium with an underground water flow of 001 fracmtextday, which we assume to be in the x direction. The borefield consists of 8 branches, each branch in parallel, and within each branch there are 6boreholes in series. The positions and connections are represented in the following plot: ","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"(Image: )","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"During the summer, heat is injected in the field with a fluid at a constant temperature of 90C through all the branches from the center of the field. During the winter, heat is extracted by circulating the fluid at a temperature of 55C from the external end of each branch and collected at the center. The simulation is done with a monthly time step duting 10 years.","category":"page"},{"location":"Braedstrup/#Run-the-example","page":"Braedstrup borefield","title":"Run the example","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"include(\"examples/Braedstrup/main.jl\")","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"The elapsed times for the precomputation and computation phases are:","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"2.449359 seconds (570.20 k allocations: 109.171 MiB, 0.66% gc time)\n0.140535 seconds (255.75 k allocations: 49.735 MiB, 62.17% compilation time: 100% of which was recompilation)","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"We can extract the result of the simulation ","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"julia> containers.X\n192×120 Matrix{Float64}:\n 192×120 Matrix{Float64}:\n 90.0 90.0 90.0 90.0 90.0 … 54.1785 53.5253 53.0836 52.7797\n 85.7196 86.3321 86.6953 86.9358 87.1041 53.3354 52.6224 52.1367 51.7994\n 85.7196 86.3321 86.6953 86.9358 87.1041 54.8461 54.2727 53.8868 53.6232\n 81.7574 83.051 83.8273 84.3361 84.6863 54.1785 53.5253 53.0836 52.7797\n ⋮ ⋱ \n 153.897 118.897 93.5639 74.8265 60.7942 -27.2873 -20.0578 -14.7582 -10.8234\n 144.883 112.083 87.7717 69.5736 55.8771 -29.8091 -21.8784 -16.1027 -11.856\n 136.767 108.025 86.4461 69.9911 57.3688 … -28.6089 -20.7213 -15.0661 -10.9335\n 149.022 124.549 105.729 90.6145 78.3994 -22.1191 -15.7456 -11.0385 -7.4812","category":"page"},{"location":"Braedstrup/#Plots","page":"Braedstrup borefield","title":"Plots","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"In order to visualize the results, we can use the subpackage BNSPlots. For more details, refer to [Visualizing the result with BNSPlots](@ref).","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"Inlet borehole temperatures and heat flows for boreholes along two branches in the borehole field. The time series are color coded according to the previous configuration plot above. In addition to the inlet temperature, the output temperature from the branch (grey dot), and the mean output temperature from the field (black dot) are displayed.","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"(Image: ) (Image: )","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"Finally we can display the heatmap of the temperature field in the borehole region during the 10th year of operation","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"(Image: )","category":"page"},{"location":"Braedstrup/#Running-the-code-in-Python","page":"Braedstrup borefield","title":"Running the code in Python","text":"","category":"section"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"The example is also avaiable from Python. For details of how this is done refer to Running BoreholeNetworksSimulator from Python. The Python version is in:","category":"page"},{"location":"Braedstrup/","page":"Braedstrup borefield","title":"Braedstrup borefield","text":"examples/Braedstrup/main.py","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"EditURL = \"nonhistory.jl\"","category":"page"},{"location":"nonhistory/#Non-history-method","page":"Non-history method","title":"Non-history method","text":"","category":"section"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"The non-history method is a time superposition method introduced in [1] whose computational complexity in the number of time steps N_t is mathcalOleft( N_t right). Recall that the standard way to do time superposition is via the convolution of the load with the response, which implemented via the Fast Fourier Transform, yields a computational complexity of mathcalOleft( N_t logN_t right). This means that using the non-history method in simulations allows for finer time steps.","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"To show this, let us run a simulation with hourly time steps, with a duration of 1 year (so 8760 time steps), with both the convolution and the non-history time superposition methods. Let us define an example, very similar to Basic tutorial","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"using BoreholeNetworksSimulator","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"Δt = 3600.\nNt = 8760\n\nmedium = GroundMedium(α=1e-6, λ=3., T0=10.)\nborehole = SingleUPipeBorehole(H=100., D=10.)\npositions = [(0., 0.), (0., 5.)]\nborefield = EqualBoreholesBorefield(borehole_prototype=borehole, positions=positions)\nconstraint = constant_HeatLoadConstraint(5 .* ones(BoreholeNetworksSimulator.n_boreholes(borefield)), Nt)\nfluid = Water()\n\nconfigurations = [BoreholeNetwork([[1], [2]])]\noperator = SimpleOperator(mass_flow = 2., branches = 2)","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"Now, we define two different options using different method parameters, one with ConvolutionMethod corresponding to the convolution, and the other with NonHistoryMethod, corresponding with the non-history method.","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"options_convolution = SimulationOptions(\n method = ConvolutionMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = fluid,\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)\n\noptions_nonhistory = SimulationOptions(\n method = NonHistoryMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = fluid,\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"Let us run the convolution","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"containers_convolution = @time initialize(options_convolution)\n@time simulate!(operator=operator, options=options_convolution, containers=containers_convolution)","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"And now let us run the non-history","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"containers_nonhistory = @time initialize(options_nonhistory)\n@time simulate!(operator=operator, options=options_nonhistory, containers=containers_nonhistory)\n\nabs.(containers_convolution.X - containers_nonhistory.X)","category":"page"},{"location":"nonhistory/#References","page":"Non-history method","title":"References","text":"","category":"section"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"[1] Lazzarotto, Alberto; Basquens, Marc; Cimmino, Massimo; Non-history dependent temporal superposition algorithm for the point source solution, Research Conference Proceedings of the IGSHPA (2024).","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"","category":"page"},{"location":"nonhistory/","page":"Non-history method","title":"Non-history method","text":"This page was generated using Literate.jl.","category":"page"},{"location":"python/#Running-BoreholeNetworksSimulator-from-Python","page":"Running from python","title":"Running BoreholeNetworksSimulator from Python","text":"","category":"section"},{"location":"python/","page":"Running from python","title":"Running from python","text":"It is also possible to run BoreholeNetworksSimulator from Python by using its Julia interoperability (achieved with the package PythonCall.jl and the module juliacall) while keeping roughly the same syntax. For a more detailed explanation of how this works, please visit the PythonCall.jl documentation. This requires to have installed in your python environment the modules juliacall and numpy.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"BoreholeNetworksSimulator.jl contains a second Julia module called BNSPythonAdapter whose purpose is to make the necessary conversions between Python and Julia. This module is not intended to be used from Julia, but from within Python. In this tutorial, we will repeat the example in Basic tutorial but run from Python to show how it works. The full example as a Python script in at BNSPythonAdapter/example.py.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"BNSPythonAdapter contains a python script src/adapter.py that executes the necessary bridging code. You should start your python program by importing this module. Assuming that the directory BNSPythonAdapter is added to the sys.path, this should work:","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"import src.adapter","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"The script takes care of activating the Julia package BNSPythonAdapter which has BoreholeNetworksSimulator as a dependency, and loads both namespaces for later use. It also defines conversions from Python objects to their Julia counterparts. Next, we need to import juliacall to be able to reference objects and funcions from BoreholeNetworksSimulator. It is useful to give it an alias for conciseness.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"from juliacall import Main as jl","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Now, the python variable jl represents the Main module in Julia, and it has as methods all the Julia functions available in it. Since we imported the namespace BoreholeNetworksSimulator, this also includes its objects and functions.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Then, we define the same variables as in Basic tutorial:","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Δt = 8760*3600/12.\nNt = 10*12\n\nα = 1e-6\nλ = 3.\nT0 = 10.\nmedium = jl.GroundMedium(α=α, λ=λ, T0=T0)\n\nD = 10.\nH = 100.\n\nborehole = jl.SingleUPipeBorehole(H=H, D=D)\n\nσ = 5.\npositions = jl.Array[jl.Tuple[jl.Float64, jl.Float64]]([(0., 0.), (0., σ)])\nborefield = jl.EqualBoreholesBorefield(borehole_prototype=borehole, positions=positions)\n\nconfigurations = [jl.BoreholeNetwork(jl.Vector[jl.Vector[jl.Int]]([[1], [2]]))]\n\nq1 = 5.\nq2 = 5.\nloads = jl.Array[jl.Float64]([q1, q2])\nconstraint = jl.constant_HeatLoadConstraint(loads, Nt)\n\noptions = jl.SimulationOptions(\n method = jl.ConvolutionMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = jl.Water(),\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Note that the code itself is not very different from its Julia version, but there are two remarks worth making. First, we need to call any object defined in Julia by typing jl. in front. This creates a python object with the same fields that PythonCall.jl knows how to convert back into a Julia object. Second, note that we have defined the arrays by explicitly declaring their generic type. If we don't do this, they will be converted into Vector{Any} in the Julia code, which is not desirable.","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Another difference is the definition of our [Operator](@ref) object. Since we are writing python, it should now be a python object with a method operate that returns an object of type jl.BoreholeOperation, which PythonCall.jl knows how to convert to BoreholeOperation. For the ssake of the example, we will implement again the [SimpleOperator](@ref) operator that is already implemented in Julia. For further examples, check the python version of the code for [Example: Braedstrup borefield ](@ref).","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"class SimpleOperator():\n def __init__(self, mass_flow, branches):\n self.mass_flows = jl.Vector[jl.Float64](mass_flow * np.ones(branches))\n\n def operate(self, i, options, Tfin, Tfout, Tb, q):\n return jl.BoreholeOperation(options.configurations[0], operator.mass_flows)\n\n\noperator = SimpleOperator(2., 2)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Note that this is equivalent to calling the same code from Julia:","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"operator = jl.SimpleOperator(mass_flow = 2., branches = 2)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Finally we can run the simulation","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"containers = jl.initialize(options)\njl.simulate_b(operator=operator, options=options, containers=containers)","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Note that the bang in simulate! is replaced by a _b in the juliacall version of the function. ","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"containers.X","category":"page"},{"location":"python/","page":"Running from python","title":"Running from python","text":"Now, one can compare this result with its Julia version. If everything went right, they should agree!","category":"page"},{"location":"#BoreholeNetworksSimulator.jl","page":"Introduction","title":"BoreholeNetworksSimulator.jl","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"BoreholeNetworksSimulator.jl is a pure Julia, performant, and modular framework for simulations of fields of interconnected borehole heat exchangers. Features:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"Computes fluid temperatures, borehole wall temperatures and heat extracted. \nSupports many different configurations and settings by being highly modular: boreholes, hydraulic configurations, ground properties, load demand or temperature constraints, ground boundary conditions can be seamlessly used with minimal effort. \nAllows for design of operation strategies via an operator callback at each time step.\nImplements the \"non-history\" time superposition method, reducing the computational complexity in the number of time steps to linear. This allows for simulations with fine time steps.\nPython interoperability.","category":"page"},{"location":"#Getting-started","page":"Introduction","title":"Getting started","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"BoreholeNetworksSimulator.jl is currently not in Julia's General registry (as well as some of its dependencies), however, it is easily available through the local registry geothermal_registry. In order to install it, start Julia and run the command:","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"using Pkg; pkg\"registry add https://github.com/marcbasquensmunoz/geothermal_registry\"; Pkg.add(\"BoreholeNetworksSimulator\")","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"In order to learn how to use this package, please visit Basic tutorial first.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"For users interested in running BoreholeNetworksSimulator.jl from Python, see also Running BoreholeNetworksSimulator from Python.","category":"page"},{"location":"#Design-philosophy","page":"Introduction","title":"Design philosophy","text":"","category":"section"},{"location":"","page":"Introduction","title":"Introduction","text":"The driving motivation when developing BoreholeNetworksSimulator.jl was to create an easy to use tool that is also highly flexible and performant.","category":"page"},{"location":"","page":"Introduction","title":"Introduction","text":"This goal has been accomplished by leveraging Julia's Multiple Dispatch. Through a simple, common interface, the user can run a plethora of different simulations by modularly specifying options. Some options have physical meaning or interpretation, while others are purely algorithmic, yet they can all be seamlessly changed by changing a parameter. Please, refer to Public API for the full list of options offered by this package.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"EditURL = \"tutorial.jl\"","category":"page"},{"location":"tutorial/#Basic-tutorial","page":"Basic tutorial","title":"Basic tutorial","text":"","category":"section"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"In this tutorial we will learn how to simulate the expected temperature and heat extraction in a borehole field.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"First, we need to specify the parameters and constraints of our system, as well as some options for the simulation. This is done through a SimulationOptions object. Its variables are modular components with which we can describe many scenarios by leveraging Julia's multiple dispatch. Let us see the components one by one with an example.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"We start by specifying the simulation time step and the simulation duration. For our example, we will take monthly time steps during 10 years:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"using BoreholeNetworksSimulator\n\nΔt = 8760*3600/12.\nNt = 10*12","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Suppose the ground we are interested in simulating is made of solid rock. This means the heat transfer will occur by pure conduction. Assume that the thermal diffusivity of the rock is α = 10^-6 fracm^2s and its thermal conductivity is λ = 3 fracWm K. The undisturbed temperature of the ground is T_0=10 ^circC. We model the ground with a subtype of Medium, in our case, as per our assumptions, we are particularly interested in GroundMedium:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"α = 1e-6\nλ = 3.\nT0 = 10.\nmedium = GroundMedium(α=α, λ=λ, T0=T0)\n\n\nD = 10.\nH = 100.\nborehole = SingleUPipeBorehole(H=H, D=D)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Next, we need to know how and where the boreholes in our system are. Suppose we are interested in simulating the evolution of two identical vertical boreholes of length H=100m and buried at depth D=10m, separated by a distance of σ=5m. The boreholes are of the U-type. We need to enconde this information in a subtype of Borefield. Since the boreholes in our example have the same properties, we can use EqualBoreholesBorefield, which instantiates several identical boreholes from a prototype. The prototype is specified by a subtype of Borehole. In our case, we can use SingleUPipeBorehole to model a borehole with a single U-pipe.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"D = 10.\nH = 100.\n\nborehole = SingleUPipeBorehole(H=H, D=D)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"There are more parameters that are also relevant, such as borehole radius, grout properties, pipe resistance, etc., but for the moment we will use their default values.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Next, we need to specify where the borehole are located.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"σ = 5.\npositions = [(0., 0.), (0., σ)]\nborefield = EqualBoreholesBorefield(borehole_prototype=borehole, positions=positions)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Note that we didn't specify yet how the boreholes are connected. This is because the simulation allows for dynamical changes in the network hydraulic configuration. Using different configurations, we can simulate the reverse flow, or even simulate valves opening and closing. The reason behind this design is to allow for decision making on the operation of the borefield during the simulation, based on the inputs that we are interested in.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"For now, let us state the possible hydraulic configurations that we will allows our borefield to be in. This is done with an vector of BoreholeNetwork. Borefields usually have several branches of boreholes. Each borehole in a branch is connected in series, while branches may o may not be connected in parallel between themselves. To create a BoreholeNetwork, we need to provide all of its branches in a vector. Each branch is, in turn, a vector containing the identifiers, in order, of the boreholes present in that branch. Each identifier i::Int refers to the borehole located at position positions[i].","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"In our example, we want to simulate two independent boreholes, so each of them must be in a separate branch. Also, for the moment, we are only interested in this configuration, so we define:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"configurations = [BoreholeNetwork([[1], [2]])]","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Even with all these specifications, the evolution of the system is still not fully determined. The missing conditions are referred to as constraints, and are modeled by subtypes of Constraint. For instance, if we would like the two boreholes to be connected in parallel, we would still need to impose that their inlet temperatures be equal. In our example, since we want out boreholes to be independent, we will impose the total amount of heat that we want to extract from each borehole. We will impose a constant load, equal for both boreholes. This is specified by","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"q1 = 5.\nq2 = 5.\nconstraint = constant_HeatLoadConstraint([q1, q2], Nt)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"We can finally create the object with all the options:","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"options = SimulationOptions(\n method = ConvolutionMethod(),\n constraint = constraint,\n borefield = borefield,\n medium = medium,\n fluid = Water(),\n Δt = Δt,\n Nt = Nt,\n configurations = configurations\n)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"As we have mentioned, the simulation is designed to allow for a controllable opeartion during its duration. We do this by creating a subtype of Operator containing the operation strategy. Then, we must implement a method of the function operate with our Operator subtype, that takes as an input the current state of the borefield and outputs a BoreholeOperation object. BoreholeOperation has two variables: the first specifies which configuration will be used for the next time step. In our case, we only want a static, simple configuration. The second specifies the mass flow rate through each branch of the selected configuration, provided as a vector. In our example, we will keep this constant through the simulation. For this purpose, there exists the type SimpleOperator, that implements precisely this strategy.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"operator = SimpleOperator(mass_flow = 2., branches = 2)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Before simulating, we first need to call initialize to run some precomputations that will be used throught the simulation and to instantiate containers where the result will be written.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"containers = initialize(options)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"And finally, we can start the simulation.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"@time simulate!(operator=operator, options=options, containers=containers)","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"The simulation is over! Note that the bulk of the time is spent in the precoputation, while the simulation itself is quite fast. This is especially good if we want to test different operation strategies.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"The result is saved in","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"containers.X","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"Each column in containers.X contains the results for a time step. In each column, the first 2 N_b correspond to the fluid temperatures. In particular, the odd entries containers.X[1:2:2Nb, :] are the inlet temperatures, while the even entries containers.X[2:2:2Nb, :] are the outlet temperatures of each borehole. The next Nb values containers.X[2Nb+1:3Nb, :] are the borehole wall temperatures. The last Nb values containers.X[3Nb+1:4Nb, :] are the heat extraction of each borehole.","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"","category":"page"},{"location":"tutorial/","page":"Basic tutorial","title":"Basic tutorial","text":"This page was generated using Literate.jl.","category":"page"}] } diff --git a/dev/tutorial/index.html b/dev/tutorial/index.html index 6a245e8..00ccc80 100644 --- a/dev/tutorial/index.html +++ b/dev/tutorial/index.html @@ -66,7 +66,7 @@ Δt = Δt, Nt = Nt, configurations = configurations -)
SimulationOptions{Float64, ConvolutionMethod{Float64}, HeatLoadConstraint{Float64}, EqualBoreholesBorefield{SingleUPipeBorehole{Float64}, Float64}, GroundMedium{Float64}, DirichletBoundaryCondition, MeanApproximation, Water}
+)
SimulationOptions{Float64, Float64, ConvolutionMethod{Float64}, HeatLoadConstraint{Float64}, EqualBoreholesBorefield{SingleUPipeBorehole{Float64}, Float64}, GroundMedium{Float64}, DirichletBoundaryCondition, MeanApproximation, Water}
   method: ConvolutionMethod{Float64}
   constraint: HeatLoadConstraint{Float64}
   borefield: EqualBoreholesBorefield{SingleUPipeBorehole{Float64}, Float64}
@@ -82,12 +82,14 @@
   Tmax: Float64 3.1536e8
   t: StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}
   configurations: Array{BoreholeNetwork}((1,))
+  atol: Float64 0.0
+  rtol: Float64 1.4901161193847656e-8
 

As we have mentioned, the simulation is designed to allow for a controllable opeartion during its duration. We do this by creating a subtype of Operator containing the operation strategy. Then, we must implement a method of the function operate with our Operator subtype, that takes as an input the current state of the borefield and outputs a BoreholeOperation object. BoreholeOperation has two variables: the first specifies which configuration will be used for the next time step. In our case, we only want a static, simple configuration. The second specifies the mass flow rate through each branch of the selected configuration, provided as a vector. In our example, we will keep this constant through the simulation. For this purpose, there exists the type SimpleOperator, that implements precisely this strategy.

operator = SimpleOperator(mass_flow = 2., branches = 2)
SimpleOperator{Float64}([2.0, 2.0])

Before simulating, we first need to call initialize to run some precomputations that will be used throught the simulation and to instantiate containers where the result will be written.

containers = initialize(options)
SimulationContainers{Float64, Matrix{Float64}}
   M: Array{Float64}((8, 8)) [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
   X: Array{Float64}((8, 120)) [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0; … ; 0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
   b: Array{Float64}((8,)) [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
   mf: Array{Float64}((2, 120)) [0.0 0.0 … 0.0 0.0; 0.0 0.0 … 0.0 0.0]
-

And finally, we can start the simulation.

@time simulate!(operator=operator, options=options, containers=containers)
  0.000762 seconds (607 allocations: 117.375 KiB)

The simulation is over! Note that the bulk of the time is spent in the precoputation, while the simulation itself is quite fast. This is especially good if we want to test different operation strategies.

The result is saved in

containers.X
8×120 Matrix{Float64}:
+

And finally, we can start the simulation.

@time simulate!(operator=operator, options=options, containers=containers)
  0.000833 seconds (607 allocations: 117.469 KiB)

The simulation is over! Note that the bulk of the time is spent in the precoputation, while the simulation itself is quite fast. This is especially good if we want to test different operation strategies.

The result is saved in

containers.X
8×120 Matrix{Float64}:
  10.0128  10.0139  10.0146  10.0152  …  10.0226  10.0226  10.0226  10.0226
  10.0122  10.0133  10.014   10.0146     10.022   10.022   10.022   10.022
  10.0128  10.0139  10.0146  10.0152     10.0226  10.0226  10.0226  10.0226
@@ -95,4 +97,4 @@
  10.0099  10.011   10.0117  10.0123     10.0197  10.0197  10.0197  10.0198
  10.0099  10.011   10.0117  10.0123  …  10.0197  10.0197  10.0197  10.0198
   0.05     0.05     0.05     0.05        0.05     0.05     0.05     0.05
-  0.05     0.05     0.05     0.05        0.05     0.05     0.05     0.05

Each column in containers.X contains the results for a time step. In each column, the first $2 N_b$ correspond to the fluid temperatures. In particular, the odd entries containers.X[1:2:2Nb, :] are the inlet temperatures, while the even entries containers.X[2:2:2Nb, :] are the outlet temperatures of each borehole. The next $Nb$ values containers.X[2Nb+1:3Nb, :] are the borehole wall temperatures. The last $Nb$ values containers.X[3Nb+1:4Nb, :] are the heat extraction of each borehole.


This page was generated using Literate.jl.

+ 0.05 0.05 0.05 0.05 0.05 0.05 0.05 0.05

Each column in containers.X contains the results for a time step. In each column, the first $2 N_b$ correspond to the fluid temperatures. In particular, the odd entries containers.X[1:2:2Nb, :] are the inlet temperatures, while the even entries containers.X[2:2:2Nb, :] are the outlet temperatures of each borehole. The next $Nb$ values containers.X[2Nb+1:3Nb, :] are the borehole wall temperatures. The last $Nb$ values containers.X[3Nb+1:4Nb, :] are the heat extraction of each borehole.


This page was generated using Literate.jl.