Tutorial 2 - Building a cable design

This tutorial demonstrates how to model a typical medium-voltage single-core power cable using the LineCableModels.jl package. The objective is to build a complete representation of a single-core 18/30 kV cable with a 1000 mm² aluminum conductor and 35 mm² copper screen.

Tutorial outline

Introduction

Single-core power cables have a complex structure consisting of multiple concentric layers, each with specific geometric and material properties – for example, a cable of type NA2XS(FL)2Y 18/30 is shown here. Prior to building actual transmission line models that incorporate cables as part of the transmission system, e.g. for EMT simulations, power flow, harmonics, protection studies etc., it is necessary to determine the base (or DC) electrical parameters of the cable itself.

This tutorial covers:

  1. Creating a detailed CableDesign with all its components.
  2. Examining the main electrical parameters (R, L, C) of the cable core ConductorGroup and main InsulatorGroup.
  3. Examining the equivalent electromagnetic properties of every CableComponent (core, sheath, jacket).
  4. Saving the cable design to a CablesLibrary for future use.
  5. Assigning CableDesign objects to a LineCableSystem and exporting the model to PSCAD for EMT analysis.

Getting started

Load the package and set up the environment:

using DataFrames
using LineCableModels

Initialize materials library with default values:

materials_db = MaterialsLibrary(add_defaults = true)
list_materialslibrary(materials_db)
9×6 DataFrame
Rownamerhoeps_rmu_rT0alpha
StringFloat64Float64Float64Float64Float64
1pe1.97e142.31.020.00.0
2polyacrylate5300.032.31.020.00.0
3semicon11000.01000.01.020.00.0
4copper1.7241e-81.00.99999420.00.00393
5xlpe1.97e142.51.020.00.0
6pec2.22045e-161.01.020.00.0
7airInf1.01.020.00.0
8semicon2500.01000.01.020.00.0
9aluminum2.8264e-81.01.0000220.00.00429
# Alternatively, it can be loaded from the example file built in the previous tutorial:
load_materialslibrary!(
	materials_db,
	file_name = "materials_library.json",
)

Cable dimensions

The cable under consideration is a medium-voltage, stranded aluminum conductor cable with XLPE insulation, copper wire concentric screens, water-blocking tape, and PE jacket that is rated for 18/30 kV systems. This information is typically found in the cable datasheet and is fully described in the code type under standards HD 620 10C [10] or DIN VDE 0276-620 [11]:

NA2XS(FL)2Y
-----------
│ │   │  │
│ │   │  └── 2Y: Outer sheath of polyethylene (PE)
│ │   └── (FL): Longitudinal watertight protection
│ │
│ └── 2XS: XLPE insulation with screen of copper wires
└── NA: Aluminum conductor

After some research, it is found that a typical cable of this type has the following configuration:

num_co_wires = 61  # number of core wires
num_sc_wires = 49  # number of screen wires
d_core = 38.1e-3   # nominal core overall diameter
d_w = 4.7e-3       # nominal strand diameter of the core
t_sc_in = 0.6e-3   # nominal internal semicon thickness
t_ins = 8e-3       # nominal main insulation thickness
t_sc_out = 0.3e-3  # nominal external semicon thickness
d_ws = .95e-3      # nominal wire screen diameter
t_cut = 0.1e-3     # nominal thickness of the copper tape (around wire screens)
w_cut = 10e-3      # nominal width of copper tape
t_wbt = .3e-3      # nominal thickness of the water blocking tape
t_sct = .3e-3      # nominal thickness of the semiconductive tape
t_alt = .15e-3     # nominal thickness of the aluminum tape
t_pet = .05e-3     # nominal thickness of the pe face in the aluminum tape
t_jac = 2.4e-3     # nominal PE jacket thickness

The cable structure is summarized in a table for better visualization, with dimensions in milimiters:

12×3 DataFrame
Rowlayerthicknessdiameter
StringAnyFloat64
1Conductor-38.1
2Inner semiconductive tape0.338.7
3Inner semiconductor0.639.9
4Main insulation8.055.9
5Outer semiconductor0.356.5
6Outer semiconductive tape0.357.1
7Wire screen0.9559.0
8Copper tape0.159.2
9Water-blocking tape0.359.8
10Aluminum tape0.1560.1
11PE with aluminum face0.0560.2
12PE jacket2.465.0

Using the cable constructors

Object hierarchy

The LineCableModels.DataModel module implements a carefully designed component hierarchy that mirrors the physical construction of power cables while maintaining the mathematical relationships required for accurate electrical modeling.

CableDesign
├── CableComponent
│   ├── conductor_group::ConductorGroup <: AbstractConductorPart
│   │   ├── layers::Vector{AbstractConductorPart}
│   │   │   ├── WireArray
│   │   │   ├── Tubular
│   │   │   ├── Strip
│   │   │   └── …
│   ├── conductor_props::Material
│   ├── insulator_group::InsulatorGroup <: AbstractInsulatorPart
│   │   ├── layers::Vector{AbstractInsulatorPart}
│   │   │   ├── Insulator
│   │   │   ├── Semicon
│   │   │   └── …
│   └── insulator_props::Material
⋮
├── CableComponent
│   ├── …
⋮  ⋮

Cable designs

The CableDesign object is the main container for all cable components. It encapsulates the entire cable structure and provides methods for calculating global cable properties.

Cable components

Each CableComponent represents a functional group of the cable (core, sheath, armor, outer), organized into a conductor group and an insulator group with their respective effective material properties. This structure is designed to provide precise calculation of electromagnetic parameters.

Conductor groups

The ConductorGroup object serves as a specialized container for organizing AbstractConductorPart elements in layers. It calculates equivalent resistance (R) and inductance (L) values for all contained conductive elements, handling the complexity of different geometrical arrangements.

AbstractConductorPart implementations

  • The WireArray object models stranded cores and screens with helical patterns and circular cross-sections.
  • The Tubular object represents simple tubular conductors with straightforward parameter calculations.
  • The Strip object models conductor tapes following helical patterns with rectangular cross-sections.

Insulator groups

The InsulatorGroup object organizes AbstractInsulatorPart elements in concentric layers, calculating the equivalent capacitance (C) and conductance (G) parameters.

AbstractInsulatorPart implementations

  • The Insulator object represents dielectric layers with very high resistivity.
  • The Semicon object models semiconducting layers with intermediate resistivity and high permittivity.
Equivalent circuit parameters

The hierarchical structure enables accurate calculation of equivalent circuit parameters by:

  1. Computing geometry-specific parameters at the AbstractConductorPart and AbstractInsulatorPart levels.
  2. Aggregating these into equivalent parameters within ConductorGroup and InsulatorGroup.
  3. Converting the composite structure into an equivalent coaxial model by matching lumped circuit quantities (R, L, C, G) to effective electromagnetic properties (ρ, ε, µ) at the CableComponent level. The effective properties are stored in dedicated Material objects.

Core and main insulation

The core consists of a 4-layer AAAC stranded conductor with 61 wires arranged in (1/6/12/18/24) pattern, with respective lay ratios of (15/13.5/12.5/11) [12]. Stranded conductors are modeled using the WireArray object, which handles the helical pattern and twisting effects via the calc_helical_params method.

Initialize the conductor object and assign the central wire:

material = get_material(materials_db, "aluminum")
core = ConductorGroup(WireArray(0, Diameter(d_w), 1, 0, material))
1-element ConductorGroup: [radius_in=0.0, radius_ext=0.00235, cross_section=1.735e-5, resistance=0.001629, gmr=0.00183]
└─WireArray: [radius_in=0.0, radius_ext=0.00235, cross_section=1.735e-5, resistance=0.001629, gmr=0.00183]
Convenience methods

The addto_conductorgroup! method internally passes the radius_ext of the existing object to the radius_in argument of the new conductor. This enables easy stacking of multiple layers without redundancy. Moreover, the Diameter method is a convenience function that converts the diameter to radius at the constructor level. This maintains alignment with manufacturer specifications while enabling internal calculations to use radius values directly. This approach eliminates repetitive unit conversions and potential sources of implementation error.

Add the subsequent layers of wires and inspect the object:

addto_conductorgroup!(core, WireArray, Diameter(d_w), 6, 15, material)
addto_conductorgroup!(core, WireArray, Diameter(d_w), 12, 13.5, material)
addto_conductorgroup!(core, WireArray, Diameter(d_w), 18, 12.5, material)
addto_conductorgroup!(core, WireArray, Diameter(d_w), 24, 11, material)
5-element ConductorGroup: [radius_in=0.0, radius_ext=0.02115, cross_section=0.001058, resistance=2.757e-5, gmr=0.01633]
├─WireArray: [radius_in=0.0, radius_ext=0.00235, cross_section=1.735e-5, resistance=0.001629, gmr=0.00183]
├─WireArray: [radius_in=0.00235, radius_ext=0.00705, cross_section=0.0001041, resistance=0.0002774, gmr=0.005414]
├─WireArray: [radius_in=0.00705, radius_ext=0.01175, cross_section=0.0002082, resistance=0.0001394, gmr=0.01009]
├─WireArray: [radius_in=0.01175, radius_ext=0.01645, cross_section=0.0003123, resistance=9.332e-5, gmr=0.01478]
└─WireArray: [radius_in=0.01645, radius_ext=0.02115, cross_section=0.0004164, resistance=7.059e-5, gmr=0.01948]

Inner semiconductor

The inner semiconductor layer ensures uniform electric field distribution between the conductor and insulation, eliminating air gaps and reducing field concentrations. An optional semiconductive tape is often used to ensure core uniformity and enhanced adherence.

Convenience methods

The Thickness type is a convenience wrapper that simplifies layer construction. When used in a constructor, it automatically calculates the outer radius by adding the thickness to the inner radius (which is inherited from the previous layer's outer radius).

Inner semiconductive tape:

material = get_material(materials_db, "polyacrylate")
main_insu = InsulatorGroup(Semicon(core, Thickness(t_sct), material))
1-element InsulatorGroup: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]
└─Semicon: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, resistance=1.32e8, gmr=0.02135, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]

Inner semiconductor (1000 Ω.m as per IEC 840):

material = get_material(materials_db, "semicon1")
addto_insulatorgroup!(main_insu, Semicon, Thickness(t_sc_in), material)
2-element InsulatorGroup: [radius_in=0.02115, radius_ext=0.02205, cross_section=0.0001221, shunt_capacitance=2.149e-7, shunt_conductance=0.06146]
├─Semicon: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, resistance=1.32e8, gmr=0.02135, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]
└─Semicon: [radius_in=0.02145, radius_ext=0.02205, cross_section=8.2e-5, resistance=1.22e7, gmr=0.02185, shunt_capacitance=2.017e-6, shunt_conductance=0.2278]

Main insulation

XLPE (cross-linked polyethylene) is the standard insulation material for modern medium and high voltage cables due to its excellent dielectric properties.

Add the insulation layer:

material = get_material(materials_db, "pe")
addto_insulatorgroup!(main_insu, Insulator, Thickness(t_ins), material)
3-element InsulatorGroup: [radius_in=0.02115, radius_ext=0.03005, cross_section=0.001432, shunt_capacitance=4.134e-10, shunt_conductance=3.774e-13]
├─Semicon: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, resistance=1.32e8, gmr=0.02135, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]
├─Semicon: [radius_in=0.02145, radius_ext=0.02205, cross_section=8.2e-5, resistance=1.22e7, gmr=0.02185, shunt_capacitance=2.017e-6, shunt_conductance=0.2278]
└─Insulator: [radius_in=0.02205, radius_ext=0.03005, cross_section=0.001309, resistance=1.504e17, gmr=0.02752, shunt_capacitance=4.134e-10, shunt_conductance=1.03e-13]

Outer semiconductor

Similar to the inner semiconductor, the outer semiconductor provides a uniform transition from insulation to the metallic screen.

Outer semiconductor (500 Ω.m as per IEC 840):

material = get_material(materials_db, "semicon2")
addto_insulatorgroup!(main_insu, Semicon, Thickness(t_sc_out), material)
4-element InsulatorGroup: [radius_in=0.02115, radius_ext=0.03035, cross_section=0.001488, shunt_capacitance=4.134e-10, shunt_conductance=3.908e-13]
├─Semicon: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, resistance=1.32e8, gmr=0.02135, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]
├─Semicon: [radius_in=0.02145, radius_ext=0.02205, cross_section=8.2e-5, resistance=1.22e7, gmr=0.02185, shunt_capacitance=2.017e-6, shunt_conductance=0.2278]
├─Insulator: [radius_in=0.02205, radius_ext=0.03005, cross_section=0.001309, resistance=1.504e17, gmr=0.02752, shunt_capacitance=4.134e-10, shunt_conductance=1.03e-13]
└─Semicon: [radius_in=0.03005, radius_ext=0.03035, cross_section=5.693e-5, resistance=8.783e6, gmr=0.03025, shunt_capacitance=5.6e-6, shunt_conductance=1.265]

Outer semiconductive tape:

material = get_material(materials_db, "polyacrylate")
addto_insulatorgroup!(main_insu, Semicon, Thickness(t_sct), material)
5-element InsulatorGroup: [radius_in=0.02115, radius_ext=0.03065, cross_section=0.001546, shunt_capacitance=4.134e-10, shunt_conductance=5.307e-13]
├─Semicon: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, resistance=1.32e8, gmr=0.02135, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]
├─Semicon: [radius_in=0.02145, radius_ext=0.02205, cross_section=8.2e-5, resistance=1.22e7, gmr=0.02185, shunt_capacitance=2.017e-6, shunt_conductance=0.2278]
├─Insulator: [radius_in=0.02205, radius_ext=0.03005, cross_section=0.001309, resistance=1.504e17, gmr=0.02752, shunt_capacitance=4.134e-10, shunt_conductance=1.03e-13]
├─Semicon: [radius_in=0.03005, radius_ext=0.03035, cross_section=5.693e-5, resistance=8.783e6, gmr=0.03025, shunt_capacitance=5.6e-6, shunt_conductance=1.265]
└─Semicon: [radius_in=0.03035, radius_ext=0.03065, cross_section=5.749e-5, resistance=9.219e7, gmr=0.03055, shunt_capacitance=1.827e-7, shunt_conductance=0.1205]

Group core-related components:

core_cc = CableComponent("core", core, main_insu)
10-element CableComponent "core":
├─ 5-element ConductorGroup: [radius_in=0.0, radius_ext=0.02115, cross_section=0.001058, resistance=2.757e-5, gmr=0.01633]
│  ├─ Effective properties: [rho=3.874e-8, eps_r=0.0, mu_r=1.035, alpha=0.00429]
│  ├─── WireArray: [radius_in=0.0, radius_ext=0.00235, cross_section=1.735e-5, resistance=0.001629, gmr=0.00183]
│  ├─── WireArray: [radius_in=0.00235, radius_ext=0.00705, cross_section=0.0001041, resistance=0.0002774, gmr=0.005414]
│  ├─── WireArray: [radius_in=0.00705, radius_ext=0.01175, cross_section=0.0002082, resistance=0.0001394, gmr=0.01009]
│  ├─── WireArray: [radius_in=0.01175, radius_ext=0.01645, cross_section=0.0003123, resistance=9.332e-5, gmr=0.01478]
│  └─── WireArray: [radius_in=0.01645, radius_ext=0.02115, cross_section=0.0004164, resistance=7.059e-5, gmr=0.01948]
└─ 5-element InsulatorGroup: [radius_in=0.02115, radius_ext=0.03065, cross_section=0.001546, shunt_capacitance=4.134e-10, shunt_conductance=5.307e-13]
   ├─ Effective properties: [rho=3.191e13, eps_r=2.757, mu_r=1.278, alpha=0.0]
   ├─── Semicon: [radius_in=0.02115, radius_ext=0.02145, cross_section=4.015e-5, shunt_capacitance=1.276e-7, shunt_conductance=0.08417]
   ├─── Semicon: [radius_in=0.02145, radius_ext=0.02205, cross_section=8.2e-5, shunt_capacitance=2.017e-6, shunt_conductance=0.2278]
   ├─── Insulator: [radius_in=0.02205, radius_ext=0.03005, cross_section=0.001309, shunt_capacitance=4.134e-10, shunt_conductance=1.03e-13]
   ├─── Semicon: [radius_in=0.03005, radius_ext=0.03035, cross_section=5.693e-5, shunt_capacitance=5.6e-6, shunt_conductance=1.265]
   └─── Semicon: [radius_in=0.03035, radius_ext=0.03065, cross_section=5.749e-5, shunt_capacitance=1.827e-7, shunt_conductance=0.1205]

With the core parts properly defined, the CableDesign object is initialized with nominal data from the datasheet. This includes voltage ratings and reference electrical parameters that will be used to benchmark the design.

Define the nominal values and instantiate the CableDesign with the core_cc component:

cable_id = "tutorial2"
datasheet_info = NominalData(
	designation_code = "NA2XS(FL)2Y",
	U0 = 18.0,                        # Phase-to-ground voltage [kV]
	U = 30.0,                         # Phase-to-phase voltage [kV]
	conductor_cross_section = 1000.0, # [mm²]
	screen_cross_section = 35.0,      # [mm²]
	resistance = 0.0291,              # DC resistance [Ω/km]
	capacitance = 0.39,               # Capacitance [μF/km]
	inductance = 0.3,                 # Inductance in trifoil [mH/km]
)
cable_design = CableDesign(cable_id, core_cc, nominal_data = datasheet_info)
1-element CableDesign "tutorial2", with nominal values: [resistance=0.0291, inductance=0.3, capacitance=0.39]
└─ Component "core":
   ├─ ConductorGroup: [radius_in=0.0, radius_ext=0.02115, rho=3.874e-8, eps_r=0.0, mu_r=1.035, alpha=0.00429]
   └─ InsulatorGroup: [radius_in=0.02115, radius_ext=0.03065, rho=3.191e13, eps_r=2.757, mu_r=1.278, alpha=0.0]

At this point, it becomes possible to preview the cable design:

plt1 = preview_cabledesign(cable_design)
Example block output

Wire screens

The metallic screen (typically copper) serves multiple purposes:

  • Provides a return path for fault currents.
  • Ensures radial symmetry of the electric field.
  • Acts as electrical shielding.
  • Provides mechanical protection.

Build the wire screens on top of the previous layer:

lay_ratio = 10 # typical value for wire screens
material = get_material(materials_db, "copper")
screen_con =
	ConductorGroup(WireArray(main_insu, Diameter(d_ws), num_sc_wires, lay_ratio, material))
1-element ConductorGroup: [radius_in=0.03065, radius_ext=0.0316, cross_section=3.473e-5, resistance=0.0005203, gmr=0.03078]
└─WireArray: [radius_in=0.03065, radius_ext=0.0316, cross_section=3.473e-5, resistance=0.0005203, gmr=0.03078]

Add the equalizing copper tape wrapping the wire screen:

addto_conductorgroup!(screen_con, Strip, Thickness(t_cut), w_cut, lay_ratio, material)
2-element ConductorGroup: [radius_in=0.03065, radius_ext=0.0317, cross_section=3.573e-5, resistance=0.0005058, gmr=0.0308]
├─WireArray: [radius_in=0.03065, radius_ext=0.0316, cross_section=3.473e-5, resistance=0.0005203, gmr=0.03078]
└─Strip: [radius_in=0.0316, radius_ext=0.0317, cross_section=1.0e-6, resistance=0.01807, gmr=0.03167]

Water blocking tape over screen:

material = get_material(materials_db, "polyacrylate")
screen_insu = InsulatorGroup(Semicon(screen_con, Thickness(t_wbt), material))
1-element InsulatorGroup: [radius_in=0.0317, radius_ext=0.032, cross_section=6.004e-5, shunt_capacitance=1.908e-7, shunt_conductance=0.1259]
└─Semicon: [radius_in=0.0317, radius_ext=0.032, cross_section=6.004e-5, resistance=8.828e7, gmr=0.0319, shunt_capacitance=1.908e-7, shunt_conductance=0.1259]

Group sheath components and assign to design:

sheath_cc = CableComponent("sheath", screen_con, screen_insu)
addto_cabledesign!(cable_design, sheath_cc)
2-element CableDesign "tutorial2", with nominal values: [resistance=0.0291, inductance=0.3, capacitance=0.39]
├─ Component "core":
│  ├─ ConductorGroup: [radius_in=0.0, radius_ext=0.02115, rho=3.874e-8, eps_r=0.0, mu_r=1.035, alpha=0.00429]
│  └─ InsulatorGroup: [radius_in=0.02115, radius_ext=0.03065, rho=3.191e13, eps_r=2.757, mu_r=1.278, alpha=0.0]
└─ Component "sheath":
   ├─ ConductorGroup: [radius_in=0.03065, radius_ext=0.0317, rho=1.04e-7, eps_r=0.0, mu_r=2.601, alpha=0.00393]
   └─ InsulatorGroup: [radius_in=0.0317, radius_ext=0.032, rho=5300.0, eps_r=32.3, mu_r=1.103, alpha=0.0]

Examine the newly added components:

plt2 = preview_cabledesign(cable_design)
Example block output

Outer jacket components

Modern cables often include an aluminum tape as moisture barrier and PE (polyethylene) outer jacket for mechanical protection.

Add the aluminum foil (moisture barrier):

material = get_material(materials_db, "aluminum")
jacket_con = ConductorGroup(Tubular(screen_insu, Thickness(t_alt), material))
1-element ConductorGroup: [radius_in=0.032, radius_ext=0.03215, cross_section=3.023e-5, resistance=0.000935, gmr=0.0321]
└─Tubular: [radius_in=0.032, radius_ext=0.03215, cross_section=3.023e-5, resistance=0.000935, gmr=0.0321]

PE layer after aluminum foil:

material = get_material(materials_db, "pe")
jacket_insu = InsulatorGroup(Insulator(jacket_con, Thickness(t_pet), material))
1-element InsulatorGroup: [radius_in=0.03215, radius_ext=0.0322, cross_section=1.011e-5, shunt_capacitance=8.234e-8, shunt_conductance=2.052e-11]
└─Insulator: [radius_in=0.03215, radius_ext=0.0322, cross_section=1.011e-5, resistance=1.949e19, gmr=0.03218, shunt_capacitance=8.234e-8, shunt_conductance=2.052e-11]

PE jacket (outer mechanical protection):

material = get_material(materials_db, "pe")
addto_insulatorgroup!(jacket_insu, Insulator, Thickness(t_jac), material)
2-element InsulatorGroup: [radius_in=0.03215, radius_ext=0.0346, cross_section=0.0005138, shunt_capacitance=1.742e-9, shunt_conductance=4.343e-13]
├─Insulator: [radius_in=0.03215, radius_ext=0.0322, cross_section=1.011e-5, resistance=1.949e19, gmr=0.03218, shunt_capacitance=8.234e-8, shunt_conductance=2.052e-11]
└─Insulator: [radius_in=0.0322, radius_ext=0.0346, cross_section=0.0005037, resistance=3.911e17, gmr=0.03381, shunt_capacitance=1.78e-9, shunt_conductance=4.437e-13]
Convenience methods

To facilitate data entry, it is possible to call the addto_cabledesign! method directly on the ConductorGroup and InsulatorGroup constituents of the component to include, without instantiating the CableComponent first.

Assign the jacket parts directly to the design:

addto_cabledesign!(cable_design, "jacket", jacket_con, jacket_insu)
3-element CableDesign "tutorial2", with nominal values: [resistance=0.0291, inductance=0.3, capacitance=0.39]
├─ Component "core":
│  ├─ ConductorGroup: [radius_in=0.0, radius_ext=0.02115, rho=3.874e-8, eps_r=0.0, mu_r=1.035, alpha=0.00429]
│  └─ InsulatorGroup: [radius_in=0.02115, radius_ext=0.03065, rho=3.191e13, eps_r=2.757, mu_r=1.278, alpha=0.0]
├─ Component "sheath":
│  ├─ ConductorGroup: [radius_in=0.03065, radius_ext=0.0317, rho=1.04e-7, eps_r=0.0, mu_r=2.601, alpha=0.00393]
│  └─ InsulatorGroup: [radius_in=0.0317, radius_ext=0.032, rho=5300.0, eps_r=32.3, mu_r=1.103, alpha=0.0]
└─ Component "jacket":
   ├─ ConductorGroup: [radius_in=0.032, radius_ext=0.03215, rho=2.826e-8, eps_r=0.0, mu_r=1.0, alpha=0.00429]
   └─ InsulatorGroup: [radius_in=0.03215, radius_ext=0.0346, rho=1.97e14, eps_r=2.3, mu_r=1.0, alpha=0.0]

Inspect the finished cable design:

plt3 = preview_cabledesign(cable_design)
Example block output

Examining the cable parameters (RLC)

In this section, the cable design is examined and the calculated parameters are compared with datasheet values. LineCableModels.jl provides methods to analyze the design in different levels of detail.

Compare with datasheet information (R, L, C values):

core_df = cabledesign_todf(cable_design, :core)
3×4 DataFrame
Rowparametercomputednominalpercent_diff
StringFloat64Float64Float64
1R [Ω/km]0.02756770.02915.2658
2L [mH/km]0.2871840.34.27206
3C [μF/km]0.4133570.395.98903

Obtain the equivalent electromagnetic properties of the cable:

components_df = cabledesign_todf(cable_design, :components)
9×4 DataFrame
Rowpropertycoresheathjacket
SymbolFloat64Float64Float64
1radius_in_con0.00.030650.032
2radius_ext_con0.021150.03170.03215
3rho_con3.8741e-81.0402e-72.8264e-8
4alpha_con0.004290.003930.00429
5mu_con1.034642.601161.00002
6radius_ext_ins0.030650.0320.0346
7eps_ins2.7565332.32.3
8mu_ins1.278441.103281.0
9loss_factor_ins4.08655e-62100.027.93428e-7

Get detailed description of all cable parts:

detailed_df = cabledesign_todf(cable_design, :detailed)
14×17 DataFrame
Rowpropertycore, cond. layer 1core, cond. layer 2core, cond. layer 3core, cond. layer 4core, cond. layer 5core, ins. layer 1core, ins. layer 2core, ins. layer 3core, ins. layer 4core, ins. layer 5sheath, cond. layer 1sheath, cond. layer 2sheath, ins. layer 1jacket, cond. layer 1jacket, ins. layer 1jacket, ins. layer 2
StringAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAnyAny
1typewirearraywirearraywirearraywirearraywirearraysemiconsemiconinsulatorsemiconsemiconwirearraystripsemicontubularinsulatorinsulator
2radius_in00.002350.007050.011750.016450.021150.021450.022050.030050.030350.030650.03160.03170.0320.032150.0322
3radius_ext0.002350.007050.011750.016450.021150.021450.022050.030050.030350.030650.03160.03170.0320.032150.03220.0346
4diam_in00.00470.01410.02350.03290.04230.04290.04410.06010.06070.06130.06320.06340.0640.06430.0644
5diam_ext0.00470.01410.02350.03290.04230.04290.04410.06010.06070.06130.06320.06340.0640.06430.06440.0692
6thickness0.002350.00470.00470.00470.00470.00030.00060.0080.00030.00030.000950.00010.00030.000155.0e-50.0024
7cross_section1.73494e-50.0001040970.0002081930.000312290.0004163874.01496e-58.19956e-50.001309425.69257e-55.74911e-53.47323e-51.0e-66.00358e-53.023e-51.01081e-50.00050366
8num_wires16121824missingmissingmissingmissingmissing49missingmissingmissingmissingmissing
9resistance0.00162910.0002774080.0001393869.33203e-57.05933e-51.32006e81.21958e71.50449e178.78339e69.21881e70.0005203170.01807188.82806e70.0009349661.94894e193.91137e17
10alpha0.004290.004290.004290.004290.004290.00.00.00.00.00.003930.003930.00.004290.00.0
11gmr0.001830170.005414050.01008880.01478070.01947660.02135020.02185090.02751960.03025020.03055020.03078350.03166670.03190020.03210.03218330.0338096
12gmr/radius0.7787960.767950.8586220.898520.9208810.9953490.9909710.9157930.9967110.9967430.9741610.9989490.996880.9984460.9994830.977155
13shunt_capacitancemissingmissingmissingmissingmissing1.2758e-72.01655e-64.13357e-105.60029e-61.82686e-7missingmissing1.90773e-7missing8.23389e-81.77994e-9
14shunt_conductancemissingmissingmissingmissingmissing0.08416960.2277511.03035e-131.2650.120526missingmissing0.12586missing2.0524e-114.43672e-13

Saving the cable design

Cables library

Designs can be saved to a library for future use. The CablesLibrary is a container for storing multiple cable designs, allowing for easy access and reuse in different projects. Lirabry management is performed using the list_cableslibrary, store_cableslibrary!, and save_cableslibrary functions.

Store the cable design and inspect the library contents:

library = CablesLibrary()
store_cableslibrary!(library, cable_design)
list_cableslibrary(library)
1×3 DataFrame
Rowcable_idnominal_datacomponents
StringStringString
1tutorial2NominalData("NA2XS(FL)2Y", 18.0, 30.0, 1000.0, 35.0, nothing, 0.0291, 0.39, 0.3)core, sheath, jacket

Save to file for later use:

output_file = joinpath(@__DIR__, "cables_library.json")
save_cableslibrary(library, file_name = output_file);
Cables library saved to: cables_library.json

Defining a cable system

Cable systems

A cable system is a collection of cables with defined positions, length and environmental characteristics. The LineCableSystem object is the main container for all cable systems, and it allows the definition of multiple cables in different configurations (e.g., trifoil, flat etc.). This object is the entry point for all system-related calculations and analyses.

Earth model

The earth return path significantly affects cable impedance calculations and needs to be properly modeled. In this tutorial, only a basic model with typical soil properties is defined. This will be further elaborated in the subsequent tutorials.

Define a frequency-dependent earth model (1 Hz to 1 MHz):

f = 10.0 .^ range(0, stop = 6, length = 10)  # Frequency range
earth_params = EarthModel(f, 100.0, 10.0, 1.0)  # 100 Ω·m resistivity, εr=10, μr=1
EarthModel with 1 horizontal earth layer (homogeneous) and 10 frequency samples
├─ Layer 1 (air): [rho_g=Inf, epsr_g=1.0, mur_g=1.0, t=∞]
└─ Layer 2: [rho_g=100.0, epsr_g=10.0, mur_g=1.0, t=∞]
   Frequency-dependent model: CP model
   No equivalent homogeneous model

Earth model base (DC) properties:

earthmodel_todf_df = earthmodel_todf(earth_params)
2×4 DataFrame
Rowrho_gepsr_gmur_gthickness
Float64Float64Float64Float64
1Inf1.01.0Inf
2100.010.01.0Inf

Three-phase system in trifoil configuration

This section ilustrates the construction of a cable system with three identical cables arranged in a trifoil formation.

Define system center point (underground at 1 m depth) and the trifoil positions

x0 = 0
y0 = -1
xa, ya, xb, yb, xc, yc = trifoil_formation(x0, y0, 0.035)
(0, -0.9696891108675446, -0.035, -1.0303108891324553, 0.035, -1.0303108891324553)

Initialize the LineCableSystem with the first cable (phase A):

cabledef = CableDef(cable_design, xa, ya, Dict("core" => 1, "sheath" => 0, "jacket" => 0))
cable_system = LineCableSystem("tutorial2", 20.0, earth_params, 1000.0, cabledef)
LineCableSystem "tutorial2": [T=20.0, line_length=1000.0, num_cables=1, num_phases=1]
├─ EarthModel: 1 horizontal homogeneous layer, CP model
└─ 1-element CableDef:
   └─ CableDesign "tutorial2": [horz=0.0, vert=-0.9697, conn=(core→1, sheath→0, jacket→0)]

Add remaining cables (phases B and C):

addto_linecablesystem!(cable_system, cable_design, xb, yb,
	Dict("core" => 2, "sheath" => 0, "jacket" => 0),
)
addto_linecablesystem!(
	cable_system, cable_design, xc, yc,
	Dict("core" => 3, "sheath" => 0, "jacket" => 0),
)
LineCableSystem "tutorial2": [T=20.0, line_length=1000.0, num_cables=3, num_phases=3]
├─ EarthModel: 1 horizontal homogeneous layer, CP model
└─ 3-element CableDef:
   ├─ CableDesign "tutorial2": [horz=0.0, vert=-0.9697, conn=(core→1, sheath→0, jacket→0)]
   ├─ CableDesign "tutorial2": [horz=-0.035, vert=-1.03, conn=(core→2, sheath→0, jacket→0)]
   └─ CableDesign "tutorial2": [horz=0.035, vert=-1.03, conn=(core→3, sheath→0, jacket→0)]
Phase mapping

The addto_linecablesystem! function allows the specification of phase mapping for each cable. The Dict argument maps the cable components to their respective phases, where core is the conductor, sheath is the screen, and jacket is the outer jacket. The values (1, 2, 3) represent the phase numbers (A, B, C) in this case. Components mapped to phase 0 will be Kron-eliminated (grounded). Components set to the same phase will be bundled into an equivalent phase.

Cable system preview

In this section the complete three-phase cable system is examined.

Display system details:

system_df = linecablesystem_todf(cable_system)
3×4 DataFrame
Rowcable_idhorzvertphase_mapping
StringNumberNumberString
1tutorial20-0.969689core: 1, sheath: 0, jacket: 0
2tutorial2-0.035-1.03031core: 2, sheath: 0, jacket: 0
3tutorial20.035-1.03031core: 3, sheath: 0, jacket: 0

Visualize the cross-section of the three-phase system:

plt4 = preview_linecablesystem(cable_system, zoom_factor = 0.15)
Example block output

PSCAD Export

The final step showcases how to export the model for electromagnetic transient simulations in PSCAD.

Export to PSCAD input file:

output_file = joinpath(@__DIR__, "tutorial2_export.pscx")
export_file = export_pscad_lcp(cable_system, file_name = output_file);
PSCAD file saved to: tutorial2_export.pscx

Conclusion

This tutorial has demonstrated how to:

  1. Create a detailed model of a complex power cable with multiple concentric layers.
  2. Calculate and analyze the cable base parameters (R, L, C).
  3. Design a three-phase cable system in trifoil arrangement.
  4. Export the model for further analysis in specialized software.

LineCableModels.jl provides a powerful framework for accurate power cable modeling with a physically meaningful representation of all cable components. This approach ensures that electromagnetic parameters are calculated with high precision. Now you can go ahead and run these cable simulations like a boss!


🏠 Back to Tutorials