Tutorial 3 - Computing line parameters
This case file demonstrates how to model an armored high-voltage single-core power cable using the LineCableModels.jl package. The objective is to build a complete representation of a single-core 525 kV cable with a 1600 mm² copper conductor, 1.2 mm tubular lead sheath and 68 x 6 mm galvanized steel armor, based on the design described in [13].
Tutorial outline
- Introduction
- Getting started
- Cable dimensions
- Core and main insulation
- Examining the cable parameters (RLC)
- Saving the cable design
- Defining a cable system
- PSCAD & ATPDraw export
- FEM calculations
Introduction
HVDC cables are constructed around a central conductor enclosed by a triple-extruded insulation system (inner/outer semi-conductive layers and main insulation). A metallic screen and protective outer sheath are then applied for land cables. Subsea designs add galvanized steel wire armor over this structure to provide mechanical strength against water pressure. A reference design for a 525 kV HVDC cable is shown here.
Getting started
Load the package and set up the environment:
using LineCableModels
using LineCableModels.Engine.FEM
using LineCableModels.Engine.Transforms: Fortescue
using DataFrames
using PrintfInitialize library and the required materials for this design:
materials = MaterialsLibrary(add_defaults = true)MaterialsLibrary with 12 materials:
├─ pe
├─ copper
├─ pec
├─ polyacrylate
└─ semicon1
└─ ... and 7 moreInspect the contents of the materials library:
materials_df = DataFrame(materials)| Row | name | rho | eps_r | mu_r | T0 | alpha |
|---|---|---|---|---|---|---|
| String | Float64 | Float64 | Float64 | Float64 | Float64 | |
| 1 | pe | 1.97e14 | 2.3 | 1.0 | 20.0 | 0.0 |
| 2 | copper | 1.7241e-8 | 1.0 | 0.999994 | 20.0 | 0.00393 |
| 3 | pec | 2.22045e-16 | 1.0 | 1.0 | 20.0 | 0.0 |
| 4 | polyacrylate | 5300.0 | 32.3 | 1.0 | 20.0 | 0.0 |
| 5 | semicon1 | 1000.0 | 1000.0 | 1.0 | 20.0 | 0.0 |
| 6 | xlpe | 1.97e14 | 2.5 | 1.0 | 20.0 | 0.0 |
| 7 | semicon2 | 500.0 | 1000.0 | 1.0 | 20.0 | 0.0 |
| 8 | aluminum | 2.8264e-8 | 1.0 | 1.00002 | 20.0 | 0.00429 |
| 9 | lead | 2.14e-7 | 1.0 | 0.999983 | 20.0 | 0.004 |
| 10 | air | Inf | 1.0 | 1.0 | 20.0 | 0.0 |
| 11 | pp | 1.0e15 | 2.8 | 1.0 | 20.0 | 0.0 |
| 12 | steel | 1.38e-7 | 1.0 | 300.0 | 20.0 | 0.0045 |
Cable dimensions
The cable under consideration is a high-voltage, stranded copper conductor cable with XLPE insulation, water-blocking tape, lead tubular screens, PE inner sheath, PP bedding, steel armor and PP jacket, rated for 525 kV HVDC systems. This information is typically found in the cable datasheet and is based on the design studied in [13].
The cable is found to have the following configuration:
num_co_wires = 127 # number of core wires
num_ar_wires = 68 # number of armor wires
d_core = 0.0463 # nominal core overall diameter
d_w = 3.6649e-3 # nominal strand diameter of the core (minimum value to match datasheet)
t_sc_in = 2e-3 # nominal internal semicon thickness
t_ins = 26e-3 # nominal main insulation thickness
t_sc_out = 1.8e-3 # nominal external semicon thickness
t_wbt = .3e-3 # nominal thickness of the water blocking tape
t_sc = 3.3e-3 # nominal lead screen thickness
t_pe = 3e-3 # nominal PE inner sheath thickness
t_bed = 3e-3 # nominal thickness of the PP bedding
d_wa = 5.827e-3 # nominal armor wire diameter
t_jac = 10e-3 # nominal PP jacket thicknessThe cable structure is summarized in a table for better visualization, with dimensions in milimiters:
| Row | layer | thickness | diameter |
|---|---|---|---|
| String | Any | Float64 | |
| 1 | Conductor | - | 46.3 |
| 2 | Inner semiconductor | 2.0 | 50.3 |
| 3 | Main insulation | 26.0 | 102.3 |
| 4 | Outer semiconductor | 1.8 | 105.9 |
| 5 | Swellable tape | 0.3 | 106.5 |
| 6 | Lead screen | 3.3 | 113.1 |
| 7 | PE inner sheath | 3.0 | 119.1 |
| 8 | PP bedding | 3.0 | 125.1 |
| 9 | Stranded wire armor | 5.8 | 136.75 |
| 10 | PP jacket | 10.0 | 156.75 |
Core and main insulation
Initialize the conductor object and assign the central wire:
material = get(materials, "copper")
core = ConductorGroup(CircStrands(0.0, Diameter(d_w), 1, 0.0, material))Add the subsequent layers of wires and inspect the object:
n_strands = 6 # Strands per layer
n_layers = 6 # Layers of strands
for i in 1:n_layers
add!(core, CircStrands, Diameter(d_w), i * n_strands, 11.0, material)
end
coreInner semiconductor
Inner semiconductor (1000 Ω.m as per IEC 840):
material = get(materials, "semicon1")
main_insu = InsulatorGroup(Semicon(core, Thickness(t_sc_in), material))Main insulation
Add the insulation layer:
material = get(materials, "pe")
add!(main_insu, Insulator, Thickness(t_ins), material)Outer semiconductor
Outer semiconductor (500 Ω.m as per IEC 840):
material = get(materials, "semicon2")
add!(main_insu, Semicon, Thickness(t_sc_out), material)Water blocking (swellable) tape:
material = get(materials, "polyacrylate")
add!(main_insu, Semicon, Thickness(t_wbt), material)Group core-related components:
core_cc = CableComponent("core", core, main_insu)
cable_id = "525kV_1600mm2"
datasheet_info = NominalData(
designation_code = "(N)2XH(F)RK2Y",
U0 = 500.0, # Phase (pole)-to-ground voltage [kV]
U = 525.0, # Phase (pole)-to-phase (pole) voltage [kV]
conductor_cross_section = 1600.0, # [mm²]
screen_cross_section = 1000.0, # [mm²]
resistance = nothing, # DC resistance [Ω/km]
capacitance = nothing, # Capacitance [μF/km]
inductance = nothing, # Inductance in trifoil [mH/km]
)
cable_design = CableDesign(cable_id, core_cc, nominal_data = datasheet_info)Lead screen/sheath
Build the wire screens on top of the previous layer:
material = get(materials, "lead")
screen_con = ConductorGroup(Tubular(main_insu, Thickness(t_sc), material))PE inner sheath:
material = get(materials, "pe")
screen_insu = InsulatorGroup(Insulator(screen_con, Thickness(t_pe), material))PP bedding:
material = get(materials, "pp")
add!(screen_insu, Insulator, Thickness(t_bed), material)Group sheath components and assign to design:
sheath_cc = CableComponent("sheath", screen_con, screen_insu)
add!(cable_design, sheath_cc)Armor and outer jacket components
Add the armor wires on top of the previous layer:
lay_ratio = 10.0 # typical value for wire screens
material = get(materials, "steel")
armor_con = ConductorGroup(
CircStrands(screen_insu, Diameter(d_wa), num_ar_wires, lay_ratio, material))PP layer after armor:
material = get(materials, "pp")
armor_insu = InsulatorGroup(Insulator(armor_con, Thickness(t_jac), material))Assign the armor parts directly to the design:
add!(cable_design, "armor", armor_con, armor_insu)Inspect the finished cable design:
plt1, _ = preview(cable_design)
plt1 #hideExamining the cable parameters (RLC)
Summarize DC lumped parameters (R, L, C):
core_df = DataFrame(cable_design, :baseparams)Obtain the equivalent electromagnetic properties of the cable:
components_df = DataFrame(cable_design, :components)Saving the cable design
Load an existing CablesLibrary file or create a new one:
library = CablesLibrary()
library_file = fullfile("cables_library.json")
load!(library, file_name = library_file)
add!(library, cable_design)
library_df = DataFrame(library)Save to file for later use:
save(library, file_name = library_file);[ Info: Cables library saved to: cables_library.jsonDefining a cable system
Earth model
Define a constant frequency earth model:
f = [1e-3] # Near DC frequency for the analysis
earth_params = EarthModel(f, 100.0, 10.0, 1.0) # 100 Ω·m resistivity, εr=10, μr=1EarthModel with 1 horizontal earth layer (homogeneous) and 1 frequency sample
├─ Layer 1 (air): [rho_g=Inf, epsr_g=1.0, mur_g=1.0, t=Inf]
└─ Layer 2: [rho_g=100.0, epsr_g=10.0, mur_g=1.0, t=Inf]
Frequency-dependent model: Constant properties (CP)
Earth model base (DC) properties:
earthmodel_df = DataFrame(earth_params)| Row | rho_g | epsr_g | mur_g | thickness |
|---|---|---|---|---|
| Float64 | Float64 | Float64 | Float64 | |
| 1 | Inf | 1.0 | 1.0 | Inf |
| 2 | 100.0 | 10.0 | 1.0 | Inf |
Underground bipole configuration
Define the coordinates for both cables:
xp, xn, y0 = -0.5, 0.5, -1.0;Initialize the LineCableSystem with positive pole:
cablepos = CablePosition(cable_design, xp, y0,
Dict("core" => 1, "sheath" => 0, "armor" => 0))
cable_system = LineCableSystem("525kV_1600mm2_bipole", 1000.0, cablepos)Add the other pole (negative) to the system:
add!(cable_system, cable_design, xn, y0,
Dict("core" => 2, "sheath" => 0, "armor" => 0))Cable system preview
In this section the complete bipole cable system is examined.
Display system details:
system_df = DataFrame(cable_system)Visualize the cross-section of the three-phase system:
plt2, _ = preview(cable_system, earth_model = earth_params, zoom_factor = 2.0)
plt2 #hidePSCAD & ATPDraw export
Export to PSCAD input file:
output_file = fullfile("pscad_export.pscx")
export_file = export_data(:pscad, cable_system, earth_params, file_name = output_file);
nothing #hideExport to ATPDraw project file (XML):
output_file = fullfile("atp_export.xml")
export_file = export_data(:atp, cable_system, earth_params, file_name = output_file);
nothing #hideFEM calculations
Define a LineParametersProblem with the cable system and earth model
problem = LineParametersProblem(
cable_system,
temperature = 20.0, # Operating temperature
earth_props = earth_params,
frequencies = f, # Frequency for the analysis
);
nothing #hideEstimate domain size based on skin depth in the earth
domain_radius = 10.0; #calc_domain_size(earth_params, f);Define custom mesh transitions around each cable
mesh_transition1 = MeshTransition(
cable_system,
[1],
r_min = 0.08,
r_length = 0.25,
mesh_factor_min = 0.01 / (domain_radius / 5),
mesh_factor_max = 0.25 / (domain_radius / 5),
n_regions = 5)
mesh_transition2 = MeshTransition(
cable_system,
[2],
r_min = 0.08,
r_length = 0.25,
mesh_factor_min = 0.01 / (domain_radius / 5),
mesh_factor_max = 0.25 / (domain_radius / 5),
n_regions = 5);
nothing #hideDefine runtime options
opts = (
force_remesh = true, # Force remeshing
force_overwrite = true, # Overwrite existing files
plot_field_maps = false, # Do not compute/ plot field maps
mesh_only = true, # Preview the mesh
save_path = fullfile("fem_output"), # Results directory
keep_run_files = true, # Archive files after each run
verbosity = 1, # Verbosity
);Define the FEM formulation with the specified parameters
F = FormulationSet(:FEM,
impedance = Darwin(),
admittance = Electrodynamics(),
domain_radius = domain_radius,
domain_radius_inf = domain_radius * 1.25,
elements_per_length_conductor = 1,
elements_per_length_insulator = 2,
elements_per_length_semicon = 1,
elements_per_length_interfaces = 5,
points_per_circumference = 16,
mesh_size_min = 1e-6,
mesh_size_max = domain_radius / 5,meshtransitions = [meshtransition1, mesh_transition2],
mesh_size_default = domain_radius / 10,
mesh_algorithm = 5,
mesh_max_retries = 20,
materials = materials,
options = opts,
);Run the FEM solver
@time ws, p = compute!(problem, F);
nothing #hideDisplay computation results
per_km(p, 1; mode = :RLCG, tol = 1e-9)Export ZY matrices to ATPDraw
output_file = fullfile("ZY_export.xml")
export_file = export_data(:atp, p; file_name = output_file, cable_system = cable_system);
nothing #hideObtain the symmetrical components via Fortescue transformation
Tv, p012 = Fortescue(tol = 1e-5)(p);
nothing #hideInspect the transformed matrices
per_km(p012, 1; mode = :ZY, tol = 1e-9)Or the corresponding lumped circuit quantities
per_km(p012, 1; mode = :RLCG, tol = 1e-9)🏠 Back to Tutorials