Skip to content

Commit 9bad282

Browse files
Refactor and enhance the LineCableModels.jl package
- Introduced a mapping function `map_verbosity_to_getdp` to standardize verbosity levels for GetDP solver. - Updated `run_getdp` to utilize the new verbosity mapping and improved command construction for solving and plotting. - Modified `make_space_geometry` to correctly determine the number of earth layers and validate layer indices. - Renamed `CommonDeps.jl` to `common_deps.jl` for consistency across modules. - Added a new `Core.jl` module to encapsulate core functionalities, including problem definitions and formulation types. - Implemented `AbstractEHEMFormulation` and `EnforceLayer` for enhanced earth model handling. - Removed the obsolete `ProblemDefs.jl` file to streamline the codebase. - Updated tests to reflect changes in function names and ensure proper DataFrame generation. - Enhanced utility functions for better readability and consistency in handling measurements and uncertainties.
1 parent bb26e0f commit 9bad282

20 files changed

Lines changed: 947 additions & 815 deletions

examples/525kV_1600mm2_bipole_export.pscx

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

examples/tutorial2.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -343,13 +343,13 @@ In this section, the cable design is examined and the calculated parameters are
343343
=#
344344

345345
# Compare with datasheet information (R, L, C values):
346-
core_df = cabledesign_todf(cable_design, :baseparams)
346+
core_df = to_df(cable_design, :baseparams)
347347

348348
# Obtain the equivalent electromagnetic properties of the cable:
349-
components_df = cabledesign_todf(cable_design, :components)
349+
components_df = to_df(cable_design, :components)
350350

351351
# Get detailed description of all cable parts:
352-
detailed_df = cabledesign_todf(cable_design, :detailed)
352+
detailed_df = to_df(cable_design, :detailed)
353353

354354
#=
355355
## Saving the cable design
@@ -386,7 +386,7 @@ f = 10.0 .^ range(0, stop=6, length=10) # Frequency range
386386
earth_params = EarthModel(f, 100.0, 10.0, 1.0) # 100 Ω·m resistivity, εr=10, μr=1
387387

388388
# Earth model base (DC) properties:
389-
earthmodel_df = earthmodel_todf(earth_params)
389+
earthmodel_df = to_df(earth_params)
390390

391391
#=
392392
### Three-phase system in trifoil configuration
@@ -425,7 +425,7 @@ In this section the complete three-phase cable system is examined.
425425
=#
426426

427427
# Display system details:
428-
system_df = linecablesystem_todf(cable_system)
428+
system_df = to_df(cable_system)
429429

430430
# Visualize the cross-section of the three-phase system:
431431
plt4 = preview_linecablesystem(cable_system, zoom_factor=0.15)

examples/tutorial3.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,10 @@ In this section, the cable design is examined and the calculated parameters are
218218
=#
219219

220220
# Summarize DC lumped parameters (R, L, C):
221-
core_df = cabledesign_todf(cable_design, :baseparams)
221+
core_df = to_df(cable_design, :baseparams)
222222

223223
# Obtain the equivalent electromagnetic properties of the cable:
224-
components_df = cabledesign_todf(cable_design, :components)
224+
components_df = to_df(cable_design, :components)
225225

226226
#=
227227
## Saving the cable design
@@ -255,7 +255,7 @@ f = 10.0 .^ range(0, stop=6, length=10) # Frequency range
255255
earth_params = EarthModel(f, 100.0, 10.0, 1.0) # 100 Ω·m resistivity, εr=10, μr=1
256256

257257
# Earth model base (DC) properties:
258-
earthmodel_df = earthmodel_todf(earth_params)
258+
earthmodel_df = to_df(earth_params)
259259

260260
#=
261261
### Underground bipole configuration
@@ -282,7 +282,7 @@ In this section the complete bipole cable system is examined.
282282
=#
283283

284284
# Display system details:
285-
system_df = linecablesystem_todf(cable_system)
285+
system_df = to_df(cable_system)
286286

287287
# Visualize the cross-section of the three-phase system:
288288
plt4 = preview_linecablesystem(cable_system, zoom_factor=0.15)
@@ -337,16 +337,16 @@ mesh_transition2 = MeshTransition(
337337
n_regions=5);
338338

339339
# Define the FEM formulation with the specified parameters
340-
formulation = FEMFormulation(
340+
formulation = FormulationSet(
341+
impedance=FEMDarwin(),
342+
admittance=FEMElectrodynamics(),
341343
domain_radius=domain_radius,
342344
domain_radius_inf=domain_radius * 1.25,
343345
elements_per_length_conductor=1,
344346
elements_per_length_insulator=2,
345347
elements_per_length_semicon=1,
346348
elements_per_length_interfaces=5,
347349
points_per_circumference=16,
348-
analysis_type=(FEMDarwin(),
349-
FEMElectrodynamics()),
350350
mesh_size_min=1e-6,
351351
mesh_size_max=domain_radius / 5,
352352
mesh_transitions=[mesh_transition1,
@@ -373,7 +373,7 @@ opts = FEMOptions(
373373

374374
# Display primary core results
375375
if !opts.mesh_only
376-
println("\nR = $(round(real(line_params.Z[1,1,1])*1000, sigdigits=4)) Ω/km")
376+
println("R = $(round(real(line_params.Z[1,1,1])*1000, sigdigits=4)) Ω/km")
377377
println("L = $(round(imag(line_params.Z[1,1,1])/(2π*f)*1e6, sigdigits=4)) mH/km")
378378
println("C = $(round(imag(line_params.Y[1,1,1])/(2π*f)*1e9, sigdigits=4)) μF/km")
379379
end

src/BaseParams.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ $(EXPORTS)
2323
module BaseParams
2424

2525
# Load common dependencies
26-
include("CommonDeps.jl")
26+
include("common_deps.jl")
2727
using ...Utils
2828

2929
# Module-specific dependencies

src/Core.jl

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
"""
2+
LineCableModels.Core
3+
4+
The [`Core`](@ref) module provides the main functionalities of the [`LineCableModels.jl`](index.md) package. This module implements data structures, methods and functions for calculating frequency-dependent electrical parameters (Z/Y matrices) of line and cable systems with uncertainty quantification.
5+
6+
# Overview
7+
8+
- Calculation of frequency-dependent series impedance (Z) and shunt admittance (Y) matrices.
9+
- Uncertainty propagation for geometric and material parameters using `Measurements.jl`.
10+
- Internal impedance computation for solid, tubular and multi-layered coaxial conductors.
11+
- Earth return impedances/admittances for overhead lines and underground cables (valid up to 10 MHz).
12+
- Support for frequency-dependent soil properties.
13+
- Handling of arbitrary polyphase systems with multiple conductors per phase.
14+
- Phase and sequence domain calculations with uncertainty quantification.
15+
- Novel N-layer concentric cable formulation with semiconductor modeling.
16+
17+
# Dependencies
18+
19+
$(IMPORTS)
20+
21+
# Exports
22+
23+
$(EXPORTS)
24+
"""
25+
module Core
26+
27+
# Load common dependencies
28+
include("common_deps.jl")
29+
using ..Utils
30+
using ..Materials
31+
using ..EarthProps
32+
using ..DataModel
33+
import ..LineCableModels: FormulationSet, _get_description
34+
35+
# Module-specific dependencies
36+
using Measurements
37+
using LinearAlgebra
38+
using SpecialFunctions
39+
40+
# Export public API
41+
export LineParametersProblem, LineParameters
42+
export AbstractFormulationSet, AbstractImpedanceFormulation, AbstractAdmittanceFormulation,
43+
FormulationOptions
44+
45+
"""
46+
$(TYPEDEF)
47+
48+
Abstract base type for all problem definitions in the [`LineCableModels.jl`](index.md) computation framework.
49+
"""
50+
abstract type ProblemDefinition end
51+
52+
# Formulation abstract types
53+
abstract type AbstractFormulationSet end
54+
abstract type AbstractImpedanceFormulation <: AbstractFormulationSet end
55+
abstract type AbstractAdmittanceFormulation <: AbstractFormulationSet end
56+
abstract type InternalImpedanceFormulation <: AbstractImpedanceFormulation end
57+
abstract type EarthImpedanceFormulation <: AbstractImpedanceFormulation end
58+
abstract type InternalAdmittanceFormulation <: AbstractAdmittanceFormulation end
59+
abstract type EarthAdmittanceFormulation <: AbstractAdmittanceFormulation end
60+
61+
"""
62+
$(TYPEDEF)
63+
64+
Represents a line parameters computation problem for a given physical cable system.
65+
66+
$(TYPEDFIELDS)
67+
"""
68+
struct LineParametersProblem <: ProblemDefinition
69+
"The physical cable system to analyze."
70+
system::LineCableSystem
71+
"Operating temperature [°C]."
72+
temperature::Number
73+
"Earth properties model."
74+
earth_props::EarthModel
75+
"Frequencies at which to perform the analysis [Hz]."
76+
frequencies::Vector{Float64}
77+
78+
function LineParametersProblem(
79+
system::LineCableSystem;
80+
temperature::Number=T₀,
81+
earth_props::EarthModel,
82+
frequencies::Vector{Float64}=[f₀]
83+
)
84+
return new(system, temperature, earth_props, frequencies)
85+
end
86+
end
87+
88+
"""
89+
$(TYPEDEF)
90+
91+
Formulation base type for defining solver options in the computation framework.
92+
Solver options define execution-related parameters such as output options,
93+
solver command line arguments, and post-processing settings.
94+
95+
Concrete implementations should define how the solution process is controlled,
96+
including file handling, previewing options, and external tool integration.
97+
"""
98+
abstract type FormulationOptions end
99+
100+
struct LineParameters{T<:Union{Complex{Float64},Complex{Measurement{Float64}}}}
101+
"Series impedance matrices [Ω/m]"
102+
Z::Array{T,3}
103+
"Shunt admittance matrices [S/m]"
104+
Y::Array{T,3}
105+
106+
# Inner constructor with validation
107+
function LineParameters(Z::Array{T,3}, Y::Array{T,3}) where {T<:Union{Complex{Float64},Complex{Measurement{Float64}}}}
108+
# Validate dimensions
109+
size(Z, 1) == size(Z, 2) || throw(DimensionMismatch("Z matrix must be square"))
110+
size(Y, 1) == size(Y, 2) || throw(DimensionMismatch("Y matrix must be square"))
111+
size(Z) == size(Y) || throw(DimensionMismatch("Z and Y must have same dimensions"))
112+
113+
new{T}(Z, Y)
114+
end
115+
end
116+
117+
struct EMTFormulation <: AbstractFormulationSet
118+
internal_impedance::InternalImpedanceFormulation
119+
earth_impedance::EarthImpedanceFormulation
120+
internal_admittance::InternalAdmittanceFormulation
121+
earth_admittance::EarthAdmittanceFormulation
122+
123+
function EMTFormulation(;
124+
internal_impedance::InternalImpedanceFormulation=nothing,
125+
earth_impedance::EarthImpedanceFormulation=nothing,
126+
internal_admittance::InternalAdmittanceFormulation=nothing,
127+
earth_admittance::EarthAdmittanceFormulation=nothing
128+
)
129+
return new(
130+
internal_impedance, earth_impedance,
131+
internal_admittance, earth_admittance
132+
)
133+
end
134+
end
135+
136+
function FormulationSet(; internal_impedance::InternalImpedanceFormulation,
137+
earth_impedance::EarthImpedanceFormulation,
138+
internal_admittance::InternalAdmittanceFormulation,
139+
earth_admittance::EarthAdmittanceFormulation)
140+
return EMTFormulation(; internal_impedance, earth_impedance,
141+
internal_admittance, earth_admittance)
142+
end
143+
144+
# Pretty printing with uncertainty information if present
145+
function Base.show(io::IO, params::LineParameters{T}) where {T}
146+
n_cond, _, n_freq = size(params.Z)
147+
print(io, "LineParameters with $(n_cond) conductors at $(n_freq) frequencies")
148+
if T <: Complex{Measurement{Float64}}
149+
print(io, " (with uncertainties)")
150+
end
151+
end
152+
153+
end # module Core

src/Core/ehem.jl

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
"""
2+
$(TYPEDEF)
3+
4+
Abstract type representing different equivalent homogeneous earth models (EHEM). Used in the multi-dispatch implementation of [`_calc_ehem_properties!`](@ref).
5+
6+
# Currently available formulations
7+
8+
- [`EnforceLayer`](@ref): Effective parameters defined according to a specific earth layer.
9+
"""
10+
abstract type AbstractEHEMFormulation end
11+
12+
"""
13+
$(TYPEDEF)
14+
15+
Represents a homogeneous earth model defined using the properties of a specific earth layer, with atttribute:
16+
17+
$(TYPEDFIELDS)
18+
"""
19+
struct EnforceLayer <: AbstractEHEMFormulation
20+
"Index of the enforced earth layer."
21+
layer::Int
22+
23+
@doc """
24+
$(TYPEDSIGNATURES)
25+
26+
Constructs an [`EnforceLayer`](@ref) instance, meaning that the properties of the specified layer are extended to the entire semi-infinite earth.
27+
28+
# Arguments
29+
30+
- `layer`: Integer specifying the layer to be enforced as the equivalent homogeneous layer.
31+
- `-1` selects the bottommost layer.
32+
- `2` selects the topmost earth layer (excluding air).
33+
- Any integer `≥ 2` selects a specific layer.
34+
35+
# Returns
36+
37+
- An [`EnforceLayer`](@ref) instance with the specified layer index.
38+
39+
# Examples
40+
41+
```julia
42+
# Enforce the bottommost layer
43+
bottom_layer = $(FUNCTIONNAME)(-1)
44+
println(_get_description(bottom_layer)) # Output: "Bottom layer"
45+
46+
# Enforce the topmost earth layer
47+
first_layer = $(FUNCTIONNAME)(2)
48+
println(_get_description(first_layer)) # Output: "Top layer"
49+
50+
# Enforce a specific layer
51+
specific_layer = $(FUNCTIONNAME)(3)
52+
println(_get_description(specific_layer)) # Output: "Layer 3"
53+
```
54+
"""
55+
function EnforceLayer(layer::Int)
56+
@assert (layer == -1 || layer >= 2) "Invalid earth layer choice."
57+
return new(layer)
58+
end
59+
end
60+
61+
function _get_description(formulation::EnforceLayer)
62+
if formulation.layer == -1
63+
return "Bottom layer"
64+
elseif formulation.layer == 2
65+
return "Top layer"
66+
else
67+
return "Layer $(formulation.layer)"
68+
end
69+
end
70+
71+
"""
72+
$(TYPEDSIGNATURES)
73+
74+
Computes the effective homogeneous earth model (EHEM) properties for an [`EarthModel`](@ref), overriding the layered model with the properties of the layer defined in [`EnforceLayer`](@ref).
75+
76+
# Arguments
77+
78+
- `model`: Instance of [`EarthModel`](@ref) for which effective properties are computed.
79+
- `frequencies`: Vector of frequency values \\[Hz\\].
80+
- `formulation`: Instance of [`AbstractEHEMFormulation`](@ref) specifying how the effective properties should be determined.
81+
82+
# Returns
83+
84+
- Modifies `model` in place by updating `rho_eff`, `eps_eff`, and `mu_eff` with the corresponding values.
85+
86+
# Notes
87+
88+
- If `formulation` is an [`EnforceLayer`](@ref), the effective properties (`rho_eff`, `eps_eff`, `mu_eff`) are **directly assigned** from the specified layer.
89+
- If `layer_idx = -1`, the **last** layer in `model.layers` is used.
90+
- If `layer_idx < 2` or `layer_idx > length(model.layers)`, an error is raised.
91+
92+
# Examples
93+
94+
```julia
95+
frequencies = [1e3, 1e4, 1e5]
96+
earth_model = EarthModel(frequencies, 100, 10, 1, t=5)
97+
earth_model.AbstractEHEMFormulation = EnforceLayer(-1) # Enforce the last layer as the effective
98+
$(FUNCTIONNAME)(earth_model, frequencies, EnforceLayer(-1))
99+
100+
println(earth_model.rho_eff) # Should match the last layer rho_g = 100
101+
println(earth_model.eps_eff) # Should match the last layer eps_g = 10*ε₀
102+
println(earth_model.mu_eff) # Should match the last layer mu_g = 1*μ₀
103+
```
104+
105+
# See also
106+
107+
- [`EarthModel`](@ref)
108+
- [`AbstractEHEMFormulation`](@ref)
109+
"""
110+
function _calc_ehem_properties!(
111+
model::EarthModel,
112+
frequencies::Vector{<:Number},
113+
formulation::AbstractEHEMFormulation=EnforceLayer(-1),
114+
)
115+
layer_idx = formulation.layer
116+
117+
if layer_idx == -1
118+
layer_idx = length(model.layers) # Use last layer
119+
elseif layer_idx < 2 || layer_idx > length(model.layers)
120+
error(
121+
"Invalid layer index: $layer_idx. Must be between 2 and $(length(model.layers))",
122+
)
123+
end
124+
125+
layer = model.layers[layer_idx]
126+
127+
# Just reference the selected layer
128+
model.rho_eff = layer.rho_g
129+
model.eps_eff = layer.eps_g
130+
model.mu_eff = layer.mu_g
131+
end
132+
133+
# Compute effective parameters **only if we have at least 2 earth layers**
134+
# if model.num_layers > 2 && !isnothing(model.AbstractEHEMFormulation) &&
135+
# !(model.vertical_layers)
136+
# _calc_ehem_properties!(model, frequencies, model.AbstractEHEMFormulation)
137+
# end

0 commit comments

Comments
 (0)