Skip to content

Commit f16ffb2

Browse files
feat: add src/DataModel/ directory
1 parent fc3e1e0 commit f16ffb2

10 files changed

Lines changed: 3165 additions & 0 deletions

File tree

src/DataModel/cabledesign.jl

Lines changed: 382 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,382 @@
1+
"""
2+
$(TYPEDEF)
3+
4+
Stores the nominal electrical and geometric parameters for a cable design, with attributes:
5+
6+
$(TYPEDFIELDS)
7+
"""
8+
struct NominalData
9+
"Cable designation as per DIN VDE 0271/0276."
10+
designation_code::Union{Nothing,String}
11+
"Rated phase-to-earth voltage \\[kV\\]."
12+
U0::Union{Nothing,Number}
13+
"Rated phase-to-phase voltage \\[kV\\]."
14+
"Cross-sectional area of the conductor \\[mm²\\]."
15+
U::Union{Nothing,Number}
16+
conductor_cross_section::Union{Nothing,Number}
17+
"Cross-sectional area of the screen \\[mm²\\]."
18+
screen_cross_section::Union{Nothing,Number}
19+
"Cross-sectional area of the armor \\[mm²\\]."
20+
armor_cross_section::Union{Nothing,Number}
21+
"Base (DC) resistance of the cable core \\[Ω/km\\]."
22+
resistance::Union{Nothing,Number}
23+
"Capacitance of the main insulation \\[μF/km\\]."
24+
capacitance::Union{Nothing,Number}
25+
"Inductance of the cable (trifoil formation) \\[mH/km\\]."
26+
inductance::Union{Nothing,Number}
27+
28+
@doc """
29+
$(TYPEDSIGNATURES)
30+
31+
Initializes a [`NominalData`](@ref) object with optional default values.
32+
33+
# Arguments
34+
- `designation_code`: Cable designation (default: `nothing`).
35+
- `U0`: Phase-to-earth voltage rating \\[kV\\] (default: `nothing`).
36+
- `U`: Phase-to-phase voltage rating \\[kV\\] (default: `nothing`).
37+
- `conductor_cross_section`: Conductor cross-section \\[mm²\\] (default: `nothing`).
38+
- `screen_cross_section`: Screen cross-section \\[mm²\\] (default: `nothing`).
39+
- `armor_cross_section`: Armor cross-section \\[mm²\\] (default: `nothing`).
40+
- `resistance`: Cable resistance \\[Ω/km\\] (default: `nothing`).
41+
- `capacitance`: Cable capacitance \\[μF/km\\] (default: `nothing`).
42+
- `inductance`: Cable inductance (trifoil) \\[mH/km\\] (default: `nothing`).
43+
44+
# Returns
45+
An instance of [`NominalData`](@ref) with the specified nominal properties.
46+
47+
# Examples
48+
```julia
49+
nominal_data = $(FUNCTIONNAME)(
50+
conductor_cross_section=1000,
51+
resistance=0.0291,
52+
capacitance=0.39,
53+
)
54+
println(nominal_data.conductor_cross_section)
55+
println(nominal_data.resistance)
56+
println(nominal_data.capacitance)
57+
```
58+
"""
59+
function NominalData(;
60+
designation_code::Union{Nothing,String}=nothing,
61+
U0::Union{Nothing,Number}=nothing,
62+
U::Union{Nothing,Number}=nothing,
63+
conductor_cross_section::Union{Nothing,Number}=nothing,
64+
screen_cross_section::Union{Nothing,Number}=nothing,
65+
armor_cross_section::Union{Nothing,Number}=nothing,
66+
resistance::Union{Nothing,Number}=nothing,
67+
capacitance::Union{Nothing,Number}=nothing,
68+
inductance::Union{Nothing,Number}=nothing,
69+
)
70+
return new(
71+
designation_code,
72+
U0,
73+
U,
74+
conductor_cross_section,
75+
screen_cross_section,
76+
armor_cross_section,
77+
resistance,
78+
capacitance,
79+
inductance,
80+
)
81+
end
82+
end
83+
84+
"""
85+
$(TYPEDEF)
86+
87+
Represents a [`CableComponent`](@ref), i.e. a group of [`AbstractCablePart`](@ref) objects, with the equivalent geometric and material properties:
88+
89+
$(TYPEDFIELDS)
90+
91+
!!! info "Definition & application"
92+
Cable components operate as containers for multiple cable parts, allowing the calculation of effective electromagnetic (EM) properties (``\\sigma, \\varepsilon, \\mu``). This is performed by transforming the physical objects within the [`CableComponent`](@ref) into one equivalent coaxial homogeneous structure comprised of one conductor and one insulator, each one represented by effective [`Material`](@ref) types stored in `conductor_props` and `insulator_props` fields.
93+
94+
The effective properties approach is widely adopted in EMT-type simulations, and involves locking the internal and external radii of the conductor and insulator parts, respectively, and calculating the equivalent EM properties in order to match the previously determined values of R, L, C and G [916943](@cite) [1458878](@cite).
95+
96+
In applications, the [`CableComponent`](@ref) type is mapped to the main cable structures described in manufacturer datasheets, e.g., core, sheath, armor and jacket.
97+
"""
98+
mutable struct CableComponent
99+
"Cable component identification (e.g. core/sheath/armor)."
100+
id::String
101+
"The conductor group containing all conductive parts."
102+
conductor_group::ConductorGroup
103+
"Effective properties of the equivalent coaxial conductor."
104+
conductor_props::Material
105+
"The insulator group containing all insulating parts."
106+
insulator_group::InsulatorGroup
107+
"Effective properties of the equivalent coaxial insulator."
108+
insulator_props::Material
109+
110+
@doc """
111+
$(TYPEDSIGNATURES)
112+
113+
Initializes a [`CableComponent`](@ref) object based on its constituent conductor and insulator groups. The constructor performs the following sequence of steps:
114+
115+
1. Validate that the conductor and insulator groups have matching radii at their interface.
116+
2. Obtain the lumped-parameter values (R, L, C, G) from the conductor and insulator groups, which are computed within their respective constructors.
117+
3. Calculate the correction factors and equivalent electromagnetic properties of the conductor and insulator groups:
118+
119+
120+
| Quantity | Symbol | Function |
121+
|----------|--------|----------|
122+
| Resistivity (conductor) | ``\\rho_{con}`` | [`calc_equivalent_rho`](@ref) |
123+
| Permeability (conductor) | ``\\mu_{con}`` | [`calc_equivalent_mu`](@ref) |
124+
| Resistivity (insulator) | ``\\rho_{ins}`` | [`calc_sigma_lossfact`](@ref) |
125+
| Permittivity (insulation) | ``\\varepsilon_{ins}`` | [`calc_equivalent_eps`](@ref) |
126+
| Permeability (insulation) | ``\\mu_{ins}`` | [`calc_solenoid_correction`](@ref) |
127+
128+
# Arguments
129+
130+
- `id`: Cable component identification (e.g. core/sheath/armor).
131+
- `conductor_group`: The conductor group containing all conductive parts.
132+
- `insulator_group`: The insulator group containing all insulating parts.
133+
134+
# Returns
135+
136+
- A [`CableComponent`](@ref) instance with calculated equivalent properties.
137+
138+
# Examples
139+
140+
```julia
141+
conductor_group = ConductorGroup(...)
142+
insulator_group = InsulatorGroup(...)
143+
cable = $(FUNCTIONNAME)("component_id", conductor_group, insulator_group) # Create cable component with base parameters @ 50 Hz
144+
```
145+
146+
# See also
147+
148+
- [`calc_equivalent_rho`](@ref)
149+
- [`calc_equivalent_mu`](@ref)
150+
- [`calc_equivalent_eps`](@ref)
151+
- [`calc_sigma_lossfact`](@ref)
152+
- [`calc_solenoid_correction`](@ref)
153+
"""
154+
function CableComponent(
155+
id::String,
156+
conductor_group::ConductorGroup,
157+
insulator_group::InsulatorGroup)
158+
# Validate the geometry
159+
if conductor_group.radius_ext != insulator_group.radius_in
160+
error("Conductor outer radius must match insulator inner radius.")
161+
end
162+
163+
# Use pre-calculated values from the groups
164+
radius_in_con = conductor_group.radius_in
165+
radius_ext_con = conductor_group.radius_ext
166+
radius_ext_ins = insulator_group.radius_ext
167+
168+
# Equivalent conductor properties
169+
rho_con =
170+
calc_equivalent_rho(conductor_group.resistance, radius_ext_con, radius_in_con)
171+
mu_con = calc_equivalent_mu(conductor_group.gmr, radius_ext_con, radius_in_con)
172+
alpha_con = conductor_group.alpha
173+
conductor_props =
174+
Material(rho_con, 0.0, mu_con, conductor_group.layers[1].temperature, alpha_con)
175+
176+
# Insulator properties
177+
C_eq = insulator_group.shunt_capacitance
178+
G_eq = insulator_group.shunt_conductance
179+
eps_ins = calc_equivalent_eps(C_eq, radius_ext_ins, radius_ext_con)
180+
rho_ins = 1 / calc_sigma_lossfact(G_eq, radius_ext_con, radius_ext_ins)
181+
correction_mu_ins = calc_solenoid_correction(
182+
conductor_group.num_turns,
183+
radius_ext_con,
184+
radius_ext_ins,
185+
)
186+
mu_ins = correction_mu_ins
187+
insulator_props =
188+
Material(rho_ins, eps_ins, mu_ins, insulator_group.layers[1].temperature, 0.0)
189+
190+
# Initialize object
191+
return new(
192+
id,
193+
conductor_group,
194+
conductor_props,
195+
insulator_group,
196+
insulator_props,
197+
)
198+
end
199+
end
200+
201+
"""
202+
$(TYPEDEF)
203+
204+
Represents the design of a cable, including its unique identifier, nominal data, and components.
205+
206+
$(TYPEDFIELDS)
207+
"""
208+
mutable struct CableDesign
209+
"Unique identifier for the cable design."
210+
cable_id::String
211+
"Informative reference data."
212+
nominal_data::NominalData
213+
"Vector of cable components."
214+
components::Vector{CableComponent}
215+
216+
@doc """
217+
$(TYPEDSIGNATURES)
218+
219+
Constructs a [`CableDesign`](@ref) instance.
220+
221+
# Arguments
222+
223+
- `cable_id`: Unique identifier for the cable design.
224+
- `component`: Initial [`CableComponent`](@ref) for the design.
225+
- `nominal_data`: Reference data for the cable design. Default: `NominalData()`.
226+
227+
# Returns
228+
229+
- A [`CableDesign`](@ref) object with the specified properties.
230+
231+
# Examples
232+
233+
```julia
234+
conductor_group = ConductorGroup(central_conductor)
235+
insulator_group = InsulatorGroup(main_insulator)
236+
component = CableComponent(conductor_group, insulator_group)
237+
design = $(FUNCTIONNAME)("example", component)
238+
```
239+
240+
# See also
241+
242+
- [`CableComponent`](@ref)
243+
- [`ConductorGroup`](@ref)
244+
- [`InsulatorGroup`](@ref)
245+
"""
246+
function CableDesign(
247+
cable_id::String,
248+
component::CableComponent;
249+
nominal_data::NominalData=NominalData(),
250+
)
251+
return new(cable_id, nominal_data, [component])
252+
end
253+
end
254+
255+
"""
256+
$(TYPEDSIGNATURES)
257+
258+
Constructs a [`CableDesign`](@ref) instance from conductor and insulator groups.
259+
260+
# Arguments
261+
262+
- `cable_id`: Unique identifier for the cable design.
263+
- `conductor_group`: The [`ConductorGroup`](@ref) for the component.
264+
- `insulator_group`: The [`InsulatorGroup`](@ref) for the component.
265+
- `component_id`: ID for the cable component. Default: "core".
266+
- `nominal_data`: Reference data for the cable design. Default: `NominalData()`.
267+
268+
# Returns
269+
270+
- A [`CableDesign`](@ref) object with the specified properties.
271+
272+
# Examples
273+
274+
```julia
275+
conductor_group = ConductorGroup(central_conductor)
276+
insulator_group = InsulatorGroup(main_insulator)
277+
design = $(FUNCTIONNAME)("example", conductor_group, insulator_group)
278+
```
279+
"""
280+
function CableDesign(
281+
cable_id::String,
282+
conductor_group::ConductorGroup,
283+
insulator_group::InsulatorGroup;
284+
component_id::String="component1",
285+
nominal_data::NominalData=NominalData(),
286+
)
287+
component = CableComponent(component_id, conductor_group, insulator_group)
288+
return CableDesign(cable_id, nominal_data, [component])
289+
end
290+
291+
292+
"""
293+
$(TYPEDSIGNATURES)
294+
295+
Adds a cable component to an existing [`CableDesign`](@ref).
296+
297+
# Arguments
298+
299+
- `design`: A [`CableDesign`](@ref) object where the component will be added.
300+
- `component`: A [`CableComponent`](@ref) to add to the design.
301+
302+
# Returns
303+
304+
- The modified [`CableDesign`](@ref) object.
305+
306+
# Notes
307+
308+
If a component with the same ID already exists, it will be overwritten, and a warning will be logged.
309+
310+
# Examples
311+
312+
```julia
313+
conductor_group = ConductorGroup(wire_array)
314+
insulator_group = InsulatorGroup(insulation)
315+
component = CableComponent("sheath", conductor_group, insulator_group)
316+
$(FUNCTIONNAME)(design, component)
317+
```
318+
319+
# See also
320+
321+
- [`CableDesign`](@ref)
322+
- [`CableComponent`](@ref)
323+
"""
324+
function add!(
325+
design::CableDesign,
326+
component::CableComponent,
327+
)
328+
# Check for existing component with same ID
329+
existing_idx = findfirst(comp -> comp.id == component.id, design.components)
330+
331+
if !isnothing(existing_idx)
332+
@warn "Component with ID '$(component.id)' already exists in the CableDesign and will be overwritten."
333+
design.components[existing_idx] = component
334+
else
335+
# Add new component to the vector
336+
push!(design.components, component)
337+
end
338+
339+
return design
340+
end
341+
342+
"""
343+
$(TYPEDSIGNATURES)
344+
345+
Adds a cable component to an existing [`CableDesign`](@ref) using separate conductor and insulator groups. Performs as a convenience wrapper to construct the [`CableComponent`](@ref) object with reduced boilerplate.
346+
347+
# Arguments
348+
349+
- `design`: A [`CableDesign`](@ref) object where the component will be added.
350+
- `component_id`: ID for the new component.
351+
- `conductor_group`: A [`ConductorGroup`](@ref) for the component.
352+
- `insulator_group`: An [`InsulatorGroup`](@ref) for the component.
353+
354+
# Returns
355+
356+
- The modified [`CableDesign`](@ref) object.
357+
358+
# Examples
359+
360+
```julia
361+
conductor_group = ConductorGroup(wire_array)
362+
insulator_group = InsulatorGroup(insulation)
363+
$(FUNCTIONNAME)(design, "shield", conductor_group, insulator_group)
364+
```
365+
366+
# See also
367+
368+
- [`CableDesign`](@ref)
369+
- [`CableComponent`](@ref)
370+
"""
371+
function add!(
372+
design::CableDesign,
373+
component_id::String,
374+
conductor_group::ConductorGroup,
375+
insulator_group::InsulatorGroup,
376+
)
377+
# Create new component
378+
component = CableComponent(component_id, conductor_group, insulator_group)
379+
380+
# Call the main function
381+
return add!(design, component)
382+
end

0 commit comments

Comments
 (0)