Bridge PowerValencia shore power

Method & data · model v0.2.1 · data as of 2026-11-09

How the numbers are made.

The project's working documents, rendered as they stand: the register contract, how unregistered ships get a size, how every category model was reconciled against TNO 2025 R12590, the draft export format for Gridcog, and the pipeline's own cleaning and time-zone checks.

Registers: what was built

registers/README.md

Built by scripts/build_registers.py on 2026-11-09T09:48:46+00:00 from data/pcs_calls_valencia_2021_2026.parquet, data/vessel_master.csv (snapshot read once), data/cruise2026.txt, data/ealing.pdf (p.38) and data/reference/terminal_coords.json (OSM Nominatim, fetched once by scripts/fetch_terminal_coords.py). Contract: docs/registers_schema.md. Every file is parquet + csv.

Row counts

register rows
vessel_register 3,392
port_register 1
terminal_register 22
berth_register 3
connection_register 6
visit_register 36,689
port_baseline_load.csv 0 (header only)

vessel_register

Category counts: container 1890, bulk 505, tanker 496, cruise 190, roro_cargo 156, other 101, ropax_ferry 43, general_cargo 11

column non-null null %
imo 1,828 46.1
imo_candidate 200 94.1
mmsi 845 75.1
gt 1,793 47.1
dwt 161 95.3
loa_m 1,796 47.1
built_year 1,817 46.4
teu 940 72.3
pax_capacity 66 98.1
beam_m 0 100.0
flag 0 100.0
operator 0 100.0
gen_total_kw 0 100.0
ops_capacity_kva 0 100.0
  • Vessels with confirmed IMO: 1,828; UNK keys: 1,564.
  • PCS names merged into another name's IMO record: 20 (in 20 IMO groups); UNK slug collisions merged: 0.
  • Same-IMO names deliberately NOT merged (kept as UNK with imo_candidate):
  • VOLCÁN DE TIJARAFE (IMO 9398890) not merged with CIUDAD DE MAHON: calls overlap in time with another name holding the same IMO
  • VOLCAN DEL TEIDE (IMO 9506289) not merged with CIUDAD DE BARCELONA: LOA 175.6 vs 164.0 for same IMO
  • Ship-hours coverage of confirmed-IMO vessels: 65.8% of in-model ship-hours.

visit_register

column non-null null %
imo 26,869 26.8
terminal_id 36,689 0.0
arrival_actual 36,471 0.6
departure_actual 36,379 0.8
alongside_hours 36,689 0.0
regular_line 36,689 0.0
agent 36,688 0.0
  • include_in_model = true: 35,553 of 36,689.
  • Quality flag counts: no_terminal 1,036, service_craft 693, dwell_gt_240h 385, estimated_times 310, future_departure 257, dwell_lt_0_5h 69, duplicate 45

terminal_register

column non-null null %
operator 20 9.1
pcs_terminal_names 21 4.5
categories_served 22 0.0
lat 4 81.8
lon 4 81.8
quay_names 3 86.4
ops_planned_mva 2 90.9

Terminal mapping (also TERMINAL_MAP in scripts/common.py)

PCS terminal string terminal_id calls
CSP IBERIAN VALENCIA TMNAL SAU ESVLC-T-CSP 9,456
APM TERMINALS VALENCIA, S.A. ESVLC-T-APM 4,453
M.S.C. TERMINAL VALENCIA,S.A.U ESVLC-T-MSC 2,904
TRASMED GLE, S.L. ESVLC-T-TRASMED 2,351
CIA. TRASMEDITERRANEA, S.A. ESVLC-T-TRASMED 696
BALEARIA EUROLINEAS MTMAS. S.A ESVLC-T-BALEARIA 5,945
GRANDI NAVI VELOCI ESPAÑA S.L. ESVLC-T-GNV 1,720
VALENCIA TERMINAL EUROPA, S.A. ESVLC-T-VTE 5,313
TEPSA IBERIA S.L.U ESVLC-T-TEPSA 944
GALP ENERGIA ESPAÑA, S.A.U. ESVLC-T-GALP 121
PROAS ESVLC-T-PROAS 68
TEVA-TANK, S.L. ESVLC-T-TEVA 1
ERSHIP, S.A. ESVLC-T-ERSHIP 133
TEMAGRA S.L. ESVLC-T-TEMAGRA 435
CEMEX ESPAÑA OPERACIONES, SLU ESVLC-T-CEMEX 3
HOLCIM ESPAÑA, S.A.U. ESVLC-T-HOLCIM 3
E. ERHARDT Y CIA., S.A. ESVLC-T-ERHARDT 356
BERGE MARITIMA, S.L.U ESVLC-T-BERGE 9
UPHILL SHIPPING S.A ESVLC-T-UPHILL 6
VALENCIA PASSENGERS SERV. S.L. ESVLC-T-VPS 1
NOATUM T SAGUNTO S.L.U. ESVLC-T-OTHER 1
***** V A R I O S ***** ESVLC-T-OTHER 734
<None> ESVLC-T-UNK 1,036

ESVLC-T-PAX has no PCS strings: it holds the two EALING passenger/ferry quays because the PCS does not say which cruise/ferry handler (Trasmed, VTE, Baleària, GNV) uses which quay.

Assumptions

  • Vessel identity. imo is filled only for vessel_master matches with confidence high or medium. Low-confidence matches keep a synthetic UNK-<slug> key with the IMO in imo_candidate (extra column) and null particulars (gt, dwt, loa, built_year, mmsi): they are guesses, and the previous demand model also ignored them.
  • Merging. PCS names sharing a trusted IMO are merged (renames) unless LOA differs by >5 m or their calls overlap in time. name_current = name of the most recent call; other names in names_previous.
  • category = most frequent per-call class from scripts/classify_vessels.py (vessel master class if high/medium, else rules on line/terminal/agent/cruise list). subcategory = service_craft when most calls are service craft, else the official type from the identity source.
  • teu = round(gt / 10.5) for containers with GT; teu_is_estimate = true for all of them (no TEU source yet).
  • pax_capacity from "Suma de Pax Max" in data/cruise2026.txt, matched by IMO then name (cruise only).
  • n_calls_esvlc counts all PCS calls; ship_hours_esvlc sums alongside_hours of include_in_model calls; n_calls_in_model added.
  • Visits: pre-berth offset 1.3 h cruise / 1.0 h others, connect/disconnect delays 0.5 h each; see docs/visit_register_assumptions.md.
  • Berths/connections: EALING FEED values, status study, planned_year 2028. Transversal de Costa linked to MSC Terminal Valencia by inference (EALING says only "container").

Deviations from docs/registers_schema.md

  • Extra columns. vessel_register: vessel_key (primary key, = imo or UNK-...), imo_candidate, imo_candidate_note, teu_is_estimate, n_calls_in_model, model_version. visit_register: category, pcs_terminal, UTC timestamps (arrival_utc, departure_utc, alongside_start_utc, alongside_end_utc), model_version. terminal_register: n_visits, n_visits_in_model. berth_register: ops_total_mva. connection_register: group_limit_kva, serves_category, note. port_register: coord_source.
  • imo in vessel_register is null for UNK rows, so the unique key is vessel_key (visit_register joins on it).
  • voltage_kv and freq_hz in connection_register are strings ("6.6|11", "50|60") because EALING gives options.
  • include_in_model also excludes calls flagged duplicate (45 calls).
  • Visit times: arrival_actual/departure_actual hold only actual stamps; PCS estimates go to *_planned.
  • Terminal ids added beyond the schema list: GNV, TEMAGRA, PROAS, TEVA, CEMEX, HOLCIM, ERHARDT, BERGE, UPHILL, VPS, UNK (no terminal) and PAX (EALING passenger quays).

What is still empty and why

  • flag, operator, beam_m, reefer_plugs, gen_count, gen_total_kw, fuel_type: no source loaded yet (needs a ship-particulars source such as Equasis / class registers / owner data).
  • ops_*: no evidence of shore-power fittings; ops_status = unknown, ops_confidence = none for all. (The 2026 cruise forecast lists "AMBITION OPS" once, possibly an OPS marker; not used.)
  • retrofit_forecast_year, adoption_assumption: scenario inputs, owned by the demand model.
  • berth_id in visits: the PCS historic feed has no berth; all null.
  • Berth dimensions and berth coordinates: not in EALING; APV berth list needed (requested in the data letter).
  • Terminal coordinates failed for: ESVLC ('Port de València'), ESVLC-T-PAX ('Muelle de Poniente'), ESVLC-T-TRASMED ('Trasmed'), ESVLC-T-VTE ('Valencia Terminal Europa'), ESVLC-T-TEPSA ('TEPSA') (left null; nothing invented).
  • port_baseline_load.csv: no meter data; EALING figures are in docs/port_energy_context.md as notes.

Bridge Power data model, v0.1 (Valencia pilot)

docs/registers_schema.md

Shared contract for the three work packages. Follow the deck (../../context/Bridge_Power_Development_Brief_Draft_01.md, slides 4 to 10). All tables are written as parquet AND csv under registers/ unless stated. Times are ISO 8601 with offset; tz column names the IANA zone (Europe/Madrid). Run everything with uv run python ... from valencia/.

Keys and ids

  • imo (int, 7 digits) is THE vessel key. Where no IMO is known, use a synthetic key UNK-<slug-of-pcs-name> and set imo_confirmed = false.
  • visit_id = ESVLC-<pcs_port_call_id>.
  • port_id = UN/LOCODE (ESVLC). terminal_id = ESVLC-T-<short> (CSP, APM, MSC, TRASMED, BALEARIA, VTE, TEPSA, GALP, ERSHIP, OTHER...). berth_id = <terminal_id>-B<nn> or null (unknown for all PCS visits today). connection_id = <berth_id>-C<n>.

1. registers/vessel_register

One row per vessel. Columns: imo, imo_confirmed, name_current, names_previous (pipe), mmsi, flag, operator, category (container|ropax_ferry|roro_cargo|cruise|tanker|bulk|general_cargo|other|unknown), subcategory (free), gt, dwt, loa_m, beam_m, built_year, teu, reefer_plugs, pax_capacity, gen_count, gen_total_kw, fuel_type, ops_status (operational|installed_unconfirmed|prepared|absent|unknown), ops_commissioned (date), ops_voltage_kv, ops_freq_hz, ops_capacity_kva, ops_source, ops_confidence (high|medium|low|none), retrofit_forecast_year, adoption_assumption (free), identity_source, identity_confidence, n_calls_esvlc, ship_hours_esvlc, updated

Everything not known is null, never guessed; ops_status defaults to unknown.

2. registers/port_register, terminal_register, berth_register, connection_register

  • port_register: port_id, name, country, authority, lat, lon, tz.
  • terminal_register: terminal_id, port_id, name, operator, pcs_terminal_names (pipe; the raw PCS strings mapped here), categories_served (pipe), lat, lon, quay_names (pipe), ops_planned_mva, ops_notes, source.
  • berth_register: berth_id, terminal_id, name, length_m, max_loa_m, max_draught_m, categories, lat, lon, source (may be sparse / empty rows for now; EALING quays Transversal de Costa, Poniente, Perfecto Palacio should appear as berths with their MVA).
  • connection_register: connection_id, berth_id, status (operational|planned|study), rated_kva, voltage_kv, freq_hz, shared_limit_group, planned_year, source.
  • registers/port_baseline_load.csv: ts_local, kw hourly baseline (existing port load, non-OPS). Empty with header for now; EALING said average ~7 MW, 13 MW grid cap, put that in docs/ as a note not in the table.

3. registers/visit_register

One row per call (ALL PCS calls, including those later excluded, with flags). Columns: visit_id, imo, vessel_key (imo or UNK-...), pcs_vessel_name, port_id, terminal_id, berth_id (null), arrival_planned, arrival_actual, departure_planned, departure_actual, arrival_is_actual, departure_is_actual, alongside_start, alongside_end, alongside_hours, pre_berth_offset_h (assumed, default 1.3 for cruise, 1.0 others; documented), connect_delay_h (default 0.5), disconnect_delay_h (default 0.5), connected_hours, status_pcs, voyage, regular_line, agent, quality_flags (pipe: service_craft|dwell_gt_240h|dwell_lt_0_5h|estimated_times|no_terminal|future_departure|duplicate), include_in_model (bool), source (pcs_historic), source_month, tz, ingested

4. registers/demand_evidence (the waterfall inputs)

  • registers/overrides.csv: scope_type (visit|vessel|category|terminal), scope_id, field (avg_kw|energy_kwh|peak_kw|profile), value, profile_ref, reason, author, date, valid_from, valid_to. Empty with header.
  • registers/measurements.csv: measurement_id, imo, port_id, connection_id, start, end, avg_kw, energy_kwh, peak_kw, interval_min, profile_ref, source, confidence. Empty with header.
  • registers/category_models.csv: model_id, category, size_param (gt|teu|dwt|loa), size_min, size_max, avg_kw_low, avg_kw_mid, avg_kw_high, peak_kw, peak_duration_h, profile_shape_id, inputs (e.g. reefer_kw_per_plug), source, scope_note, is_assumption (bool), version.
  • registers/profile_shapes.csv: profile_shape_id, hour_index (0..n or fraction 0..1), multiplier for within-call shape (e.g. container reefer: high on arrival, dip, rise).

5. Per-visit resolved demand: output/visit_demand.parquet

visit_id, vessel_key, category, scenario_power (low|mid|high), evidence_level (1_override|2_measured_same_port|3_measured_elsewhere|4_category_model|5_installed_capacity), evidence_ref, avg_kw, peak_kw, energy_kwh, connected_hours, profile_shape_id, model_version

6. Hourly results with components: output/hourly_components.parquet

Long format: ts_local, interval_min (60), visit_id, vessel_key, category, terminal_id, scenario_power, adoption_case, avg_kw, kwh. One row per visit per hour it is connected (about 1.05 M rows per scenario; keep mid only in components, low/high as totals). Plus output/hourly_totals.parquet: ts_local, scenario_power, adoption_case, kw_vessels, kw_baseline, kw_total, kwh_total, n_vessels_connected, peak_potential_kw (sum of peak_kw of connected vessels), kw_by_category_* , kw_by_terminal_*.

7. Adoption cases (scenario axis separate from power axis)

current_confirmed (only vessels with ops_status = operational AND a connection at that terminal with status operational), fueleu_2030 (container, ropax_ferry, cruise with gt > 5000, GT unknown treated as in scope), phased_<year> (linear ramp of the fueleu set from current to full between 2026 and 2030; parameter), full_adoption (every merchant visit connects). Berth compatibility applies when connection registers exist; today it is pass-through.

8. Export for Gridcog: output/export/

Excel (.xlsx) and CSV, one file per (scenario_power, adoption_case): sheet profile with timestamp_local, timestamp_utc, interval_min, avg_kw_vessels, avg_kw_baseline, avg_kw_total, kwh_total, peak_potential_kw, n_vessels; sheet meta with port, tz, period, interval definition (start-of-interval timestamp, average over interval), scenario definitions, model_version, data sources, generated-at; sheet by_category and by_terminal wide. Keep the first working version simple; the format is to be confirmed with Steven and Gridcog.

Pipeline order

bash scripts/run_pipeline.sh = build_registers -> impute_sizes (service-based GT for unsized container vessels, flagged gt_is_imputed, logged in registers/size_imputation.csv, tagged size_imputed_from_service:<confidence> in evidence_ref) -> build_category_models -> run_waterfall -> test_waterfall -> build_scenarios -> export_gridcog (full history to output/export, calendar 2025 to output/export_2025).

Model version

MODEL_VERSION = "0.2.1" (0.1.0 = ICCT-based coefficients; 0.2.0 = TNO 2025 R12590 reconciliation; 0.2.1 = + service-based size imputation) in scripts/common.py; bump when coefficients change. Every output carries it.

Category models: reconciliation of TNO 2025 R12590 with the previous ICCT-based table

docs/category_models_reconciliation.md

Generated by scripts/build_category_models.py (version 0.2.1). Previous table: data/reference/at_berth_power_assumptions.csv (used by scripts/build_demand_model.py, 2025 mid = 383 GWh). New table: registers/category_models.csv. TNO extract with page references: data/reference/tno_2025_r12590_extract.md.

Rules applied

  1. Mid = TNO. Where TNO Chapter 3 has a measurement in or next to the bin and it differs from the IMO benchmark by more than about 25 %, mid is the TNO measured value (cruise 60-100k GT, RoRo, chemical tanker 40k+ dwt, general cargo). Where TNO measurements roughly agree with IMO (container, RoPax 65k GT), or TNO has no measurement (bulk, small tankers, small ferries), mid is the IMO 4th GHG at-berth auxiliary power reproduced by TNO in Appendix A Table A.1 (p.40). Bins outside TNO's measured range in a category where TNO contradicts IMO (cruise <60k and >=100k GT, RoRo >=50k GT) use TNO's own kW-per-GT fit (App. D, Table D.1) and are is_assumption.
  2. ICCT value recorded, not used for mid. The previous low was "ICCT 2017 AE + boiler". Boiler output is heat/steam from oil-fired boilers, not electricity, so it is not shore-power demand. IMO/TNO numbers are generator (electrical) output only. The previous mid was a further own uplift above ICCT (container >14,500 TEU: 3,500 vs ICCT 1,320 + 700). Each row's scope_note carries the previous low/mid/high and the ICCT basis.
  3. High kept from the previous table (EALING 2024 connection ratings, EMSA ranges, or previous own value), because high is meant to cover reefer-heavy calls, hot-weather hotel load and connection ratings. Exception: RoPax bins below 20k GT, where the EALING 4 MVA ferry rating does not apply, use 2 x mid (assumption).
  4. Low = a documented fraction of mid read from the TNO spread (container 0.65 from Fig 3.4; cruise 0.85 from Fig 3.7; RoPax 0.60 from Fig 3.9; RoRo 0.75 from Fig 3.16), or an explicit TNO number (RoPax 20-40k: TNO ferry fit 900 kW; RoPax 40k+: Fig 3.9 tail 1,200; cruise 60-100k: 3,700). Bulk/tanker/other 0.70 or 0.67 are assumptions.
  5. Peak (interval maximum, independent of the average): TNO measured maxima where available (cruise 60-100k 5,000; RoPax 40k+ 2,750; RoRo <50k 830; chemical tanker 40-60k 1,300; general cargo 120 / 800). Otherwise mid x ratio: container 1.35 (Fig 3.5), cruise 1.15 (Fig 3.7), RoPax 1.15 (Fig 3.8), RoRo 1.2 (Fig 3.16), tanker 2.0 (Fig 3.13), general cargo 2.5 (Fig 3.10/3.11): inferred from figures, so is_assumption = true. Bulk and other 1.5 (no TNO data, deck example range 1.5-2.0).
  6. Reefers: inputs keeps reefer_kw_per_plug=4.4 (the previous ICCT-style planning figure) and adds TNO's implied 1.2-2.5 kW per connected reefer at berth (Fig 3.5: ~1,450 kW / 576 reefers; ~230 / 189; ~250 / 154). The category mid already includes a typical reefer load; the inputs are exposed for a consultant override, not added on top.
  7. Size proxies (in inputs, used by the waterfall when the size value is null): container TEU = GT / 10.5 (previous model's rule), tanker dwt = GT x 1.6, bulk dwt = GT x 1.8, general cargo dwt = GT x 1.5. Without size and GT the waterfall uses the row flagged default_bin=1.
  8. is_assumption = false only when both mid and peak are taken directly from a TNO measurement or the IMO table.

Row-by-row comparison (kW)

model_id bin prior_low prior_mid prior_high new_low new_mid new_high peak_kw mid_change_pct mid_basis prior_basis
CM-CONT-01 teu 0-999 460 700 1,000 240 370 1,000 500 -47 IMO 4th GHG via TNO App. A Table A.1 p.40 (370) ICCT 2017 App C+D: AE 340 + boiler 120
CM-CONT-02 teu 1,000-1,999 890 1,300 1,800 530 820 1,800 1,110 -37 IMO 4th GHG via TNO App. A Table A.1 p.40 (820) ICCT 2017: AE 600 + boiler 290
CM-CONT-03 teu 2,000-2,999 1,050 1,500 2,200 400 610 2,200 820 -59 IMO 4th GHG via TNO App. A Table A.1 p.40 (610) ICCT 2017: AE 700 + boiler 350
CM-CONT-04 teu 3,000-4,999 1,390 2,000 3,000 720 1,100 3,000 1,480 -45 IMO 4th GHG via TNO App. A Table A.1 p.40 (1100) ICCT 2017: AE 940 + boiler 450
CM-CONT-05 teu 5,000-7,999 1,420 2,200 3,500 750 1,150 3,500 1,550 -48 IMO 4th GHG via TNO App. A Table A.1 p.40 (1150); TNO Fig 3.4 4-10k TEU median ~1050 corroborates ICCT 2017: AE 970 + boiler 450
CM-CONT-06 teu 8,000-11,999 1,520 2,500 4,000 750 1,150 4,000 1,550 -54 IMO 4th GHG via TNO App. A Table A.1 p.40 (1150); TNO Fig 3.4 corroborates ICCT 2017: AE 1000 + boiler 520
CM-CONT-07 teu 12,000-14,499 1,830 3,000 5,000 840 1,300 5,000 1,760 -57 IMO 4th GHG via TNO App. A Table A.1 p.40 (1300); TNO Fig 3.4 >10k TEU median ~1300-1400 ICCT 2017: AE 1200 + boiler 630
CM-CONT-08 teu 14,500-19,999 2,020 3,500 6,000 910 1,400 6,000 1,890 -60 IMO 4th GHG via TNO App. A Table A.1 p.40 (1400); TNO 2025 R12590 Fig 3.5 18-20k TEU visits ~780/960/1900 kW ICCT 2017 >14500: AE 1320 + boiler 700
CM-CONT-09 teu 20,000- 2,020 3,500 6,000 910 1,400 6,000 1,890 -60 IMO 4th GHG via TNO App. A Table A.1 p.40 (1400) ICCT 2017 >14500: AE 1320 + boiler 700
CM-CRUI-01 gt 0-9,999 600 1,000 1,500 380 450 1,500 520 -55 IMO 4th GHG via TNO App. A Table A.1 p.40 (450) own assumption (prior model)
CM-CRUI-02 gt 10,000-59,999 4,500 6,000 8,000 1,530 1,800 8,000 2,070 -70 TNO 2025 R12590 App. D Table D.1 cruise fit 10.13 kg/1000GT.h = 50.7 kW/kGT x 35k GT ICCT 2017: AE 3500 + boiler 1000
CM-CRUI-03 gt 60,000-99,999 7,500 9,000 12,000 3,700 4,400 12,000 5,000 -51 TNO 2025 R12590 p.19 Fig 3.7 measured: A 4300, B 4200 (~80k GT), C ~4700 (~100k GT) ICCT 2017: AE 11480 incl hotel (prior mid 'use 7.5-9 MW typical')
CM-CRUI-04 gt 100,000-149,999 9,000 11,980 16,000 5,360 6,300 16,000 7,240 -47 TNO 2025 R12590 App. D cruise fit 50.7 kW/kGT x 125k GT ICCT 2017: AE 11480 + boiler 500
CM-CRUI-05 gt 150,000- 9,000 11,980 16,000 7,740 9,100 16,000 10,460 -24 TNO 2025 R12590 App. D cruise fit 50.7 kW/kGT x 180k GT ICCT 2017: AE 11480 + boiler 500
CM-ROPX-01 gt 0-1,999 200 300 500 60 105 500 120 -65 IMO 4th GHG via TNO App. A Table A.1 p.40 (105) prior used 'other' row for <2000 GT
CM-ROPX-02 gt 2,000-4,999 710 1,500 4,000 200 330 660 380 -78 IMO 4th GHG via TNO App. A Table A.1 p.40 (330) ICCT 2017 Ferry-ro-pax >2000 GT: AE 710 (no boiler)
CM-ROPX-03 gt 5,000-9,999 710 1,500 4,000 400 670 1,340 770 -55 IMO 4th GHG via TNO App. A Table A.1 p.40 (670) ICCT 2017 Ferry-ro-pax >2000 GT: AE 710
CM-ROPX-04 gt 10,000-19,999 710 1,500 4,000 660 1,100 2,200 1,260 -27 IMO 4th GHG via TNO App. A Table A.1 p.40 (1100) ICCT 2017 Ferry-ro-pax >2000 GT: AE 710
CM-ROPX-05 gt 20,000-39,999 710 1,500 4,000 900 1,950 4,000 2,240 30 IMO 4th GHG via TNO App. A Table A.1 p.40 (1950) ICCT 2017 Ferry-ro-pax >2000 GT: AE 710
CM-ROPX-06 gt 40,000- 710 1,500 4,000 1,200 2,050 4,000 2,750 37 TNO 2025 R12590 p.20 Fig 3.8/3.9 measured 65k GT sisters: per-visit means ~2200 / ~1900 ICCT 2017 Ferry-ro-pax >2000 GT: AE 710
CM-RORO-01 gt 0-49,999 1,500 1,800 2,500 520 700 2,500 830 -61 TNO 2025 R12590 p.29 Fig 3.16 measured: ~10k dwt / 33.7k GT Ro-Ro, mode ~690 kW ICCT 2017 RoRo: AE 1200 + boiler 300
CM-RORO-02 gt 50,000- 1,500 1,800 2,500 980 1,300 2,500 1,560 -28 TNO 2025 R12590 App. D RoRo fit 3.98 kg/1000GT.h = 19.9 kW/kGT x 65k GT ICCT 2017 RoRo: AE 1200 + boiler 300
CM-TANK-01 dwt 0-4,999 740 900 1,200 90 130 1,200 260 -86 IMO 4th GHG via TNO App. A Table A.1 p.40 chemical tanker (130) ICCT 2017 chem 10-20k: AE 490 + boiler 250 (prior applied to all <20k dwt)
CM-TANK-02 dwt 5,000-9,999 740 900 1,200 230 330 1,200 660 -63 IMO 4th GHG via TNO App. A Table A.1 p.40 chemical tanker (330) ICCT 2017 chem 10-20k: AE 490 + boiler 250
CM-TANK-03 dwt 10,000-19,999 740 900 1,200 340 490 1,200 980 -46 IMO 4th GHG via TNO App. A Table A.1 p.40 chemical tanker (490) ICCT 2017 chem 10-20k: AE 490 + boiler 250
CM-TANK-04 dwt 20,000-39,999 1,420 1,500 2,000 550 790 2,000 1,580 -47 IMO 4th GHG via TNO App. A Table A.1 p.40 chemical tanker (790) ICCT 2017 chem >20k: AE 1170 + boiler 250
CM-TANK-05 dwt 40,000-59,999 1,420 1,500 2,000 410 590 2,000 1,300 -61 TNO 2025 R12590 p.26 Fig 3.14 measured 45k dwt chemical tanker, 25 visits: loading ~560, unloading ~620 ICCT 2017 chem >20k: AE 1170 + boiler 250
CM-TANK-06 dwt 60,000- 2,250 2,250 3,000 620 880 3,000 1,760 -61 IMO 4th GHG via TNO App. A Table A.1 p.40 oil tanker 80-120k dwt (880) ICCT 2017 oil 20-60k: AE 750 + boiler 1500
CM-BULK-01 dwt 0-34,999 330 400 600 80 110 600 160 -72 IMO 4th GHG via TNO App. A Table A.1 p.40 (110) ICCT 2017: AE 280 + boiler 50
CM-BULK-02 dwt 35,000-59,999 470 550 800 100 150 800 220 -73 IMO 4th GHG via TNO App. A Table A.1 p.40 (150) ICCT 2017: AE 370 + boiler 100
CM-BULK-03 dwt 60,000- 470 550 800 170 240 800 360 -56 IMO 4th GHG via TNO App. A Table A.1 p.40 (240) no prior row (used 35-60k)
CM-GENC-01 dwt 0-9,999 405 450 600 30 50 600 120 -89 TNO 2025 R12590 p.21 Fig 3.10 measured ~6-7k dwt: modes 35-40 kW, peaks >100 kW ICCT 2017: AE 330 + boiler 75
CM-GENC-02 dwt 10,000- 1,070 1,100 1,400 210 350 1,400 800 -68 TNO 2025 R12590 p.23 Fig 3.11 measured 10-20k dwt: modes 200-500 kW ICCT 2017: AE 970 + boiler 100
CM-OTHR-01 gt 0- 200 300 500 200 300 500 450 0 prior own assumption (tugs/service/unknown small) ICCT 2017 misc (prior)

Main changes, with numbers

  • Container (76 % of previous energy): mid falls 37-60 % in every bin, e.g. 8,000-11,999 TEU 2,500 -> 1,150 and

    14,500 TEU 3,500 -> 1,400. Reason: IMO at-berth AE (TNO App. A) is 1,150-1,400 kW for large ships, and TNO's measured per-visit averages for one owner at one port (Fig 3.4) centre on ~1,050 (4-10k TEU) and ~1,300-1,400 (>10k TEU), confirming IMO; the measured 18-20k TEU visits ran at ~780, ~960 and ~1,900 kW. The previous mid stacked boiler heat (450-700 kW) and an own uplift on top. The unknown-size default moves from 2,000 kW to the 3,000-4,999 TEU bin (1,100 kW). High (1,000-6,000) unchanged; it still covers reefer-heavy calls (TNO Fig 3.4 max ~2,900).

  • Cruise: 60-100k GT mid 9,000 -> 4,400 kW (TNO measured 4,200-4,700 for three ~80-100k GT ships; IMO 11,500). Other bins scale with TNO's 50.7 kW per 1,000 GT fit: 10-60k 6,000 -> 1,800; 100-150k 11,980 -> 6,300; 150k+ 11,980 -> 9,100. Strong caveat: one owner, ambient temperature not controlled; Valencia summer HVAC load could push towards IMO. High stays at 12-16 MW (EALING Poniente / Perfecto Palacio ratings).
  • RoPax: mid 1,500 -> 1,950 kW for 20-40k GT (IMO; Valencia median ~27k GT) and 2,050 for 40k+ (TNO measured 65k GT sisters ~1,900-2,200, matches IMO 1,950). Previous mid 1,500 was below IMO. Small ferries follow IMO (105-1,100 kW).
  • RoRo: <50k GT mid 1,800 -> 700 (TNO measured ~690 kW at 33.7k GT, EMS-consistent, IMO 1,100); >=50k GT 1,800 -> 1,300 (TNO fit 19.9 kW/kGT x 65k GT). Size parameter changed from a single GT bin to two GT bins.
  • Tanker: most Valencia tanker calls are small (median ~2.7k GT, bunker/product tankers): mid 900 -> 130 kW (IMO chemical tanker 0-5k dwt; ICCT AE 160). 40-60k dwt 1,500 -> 590 (TNO measured, 25 visits). High kept (1,200-3,000) for cargo-pump peaks.
  • Bulk: 400/550 -> 110/150 kW (IMO; ICCT AE 280/370, boiler removed). No TNO measurement, marked assumption.
  • General cargo: 450/1,100 -> 50/350 kW (TNO measured; IMO 240/720). Negligible in Valencia (51 calls in 6 years).
  • Other: unchanged 200/300/500 (own assumption).

What remains unverified

  • All TNO Chapter 3 numbers apart from those quoted in the text were read from plots (about +/-5 % of full scale).
  • TNO samples are few, anonymised and mostly Dutch owners; no Spanish/Mediterranean data. The container per-visit distribution is one owner at one port.
  • The kW-per-GT fits (cruise, RoRo, ferry) are TNO's own "indicative" linear fits through the origin; TNO itself warns a linear GT relation "may not be the most accurate".
  • Peak durations are assumptions (TNO gives no peak-duration statistics).
  • EALING/EMSA highs are connection ratings or published ranges, not measured averages.

Size imputation from liner service (model 0.2.1)

docs/size_imputation.md

Rules: category = container; a line qualifies with >= 3 distinct sized vessels; vessel takes the median GT of its main qualifying line; confidence high if p75/p25 < 1.5.

  • Qualifying lines: 104
  • Vessels imputed: 887 (high confidence 435, low 452)
  • Container vessels still unsized: 63 (no qualifying line)
  • Container visits now with a size: imputed 6,590 of 16,811; still unsized 313
  • Share of container alongside-hours covered by imputation: 38.5%

Imputed GT distribution (vessels)

count mean std min 25% 50% 75% max
line_gt_median 887 64428 52717 7786 17272 44854 94700 210890

Largest imputations by berth time

name regular_line line_n_vessels line_gt_median spread confidence
TINA HOLLAND MASS-IBERICA EXPRESS LINE (IBEX) 7 9962 1.198 high
AVRA MITERAS MAGHREB SERVICE 29 9981 1.688 low
WEC JAN STEEN HOLLAND MASS-IBERICA EXPRESS LINE (IBEX) 7 9962 1.198 high
CONTSHIP PAX CMA NEW South Europe-Algerian Service 42 10742 1.736 low
NEOKASTRO CMA CGM - BLACK SEA 23 38332 1.229 high
WEC MAJORELLE X-PRESS - SPX 20 9832 1.547 low
ALEXANDRA A EMES - NORTE DE AFRICA (ARKAS) 14 10742 1.349 high
CONTSHIP MAX MAGHREB SERVICE 29 9981 1.688 low
DANIEL A EMES - NORTE DE AFRICA (ARKAS) 14 10742 1.349 high
MSC AZURIT F MAGHREB SERVICE 29 9981 1.688 low
CTM ISTMO MEDSER 3 7852 1.853 low
ANTIBES EXPRESS MAERSK E07 5 35595 2.083 low
MEDKON NLS CMA NEW South Europe-Algerian Service 42 10742 1.736 low
CMA CGM ISKENDERUN CMA CGM - BLACK SEA 23 38332 1.229 high
CARLA NAS (COSCO) 6 10636 2.255 low
MSC LEVANTE F MAGHREB SERVICE 29 9981 1.688 low
MSC DYMPHNA TURKEY - WEST MED - WAF SERVICE 49 43575 2.858 low
SPRING C CMA CGM - BLACK SEA 23 38332 1.229 high
JSP BORA MAGHREB SERVICE 29 9981 1.688 low
CMA CGM AMBARLI CMA CGM - BLACK SEA 23 38332 1.229 high

Caveats

  • Assigns the fleet-typical size of the service; occasional relief or feeder substitutions are mis-sized by the line's spread (median p75/p25 about 1.1-1.2).
  • Low-confidence rows (spread >= 1.5) are services that mix ship sizes; treat their kW as +-50%.
  • The waterfall tags these visits with size_imputed_from_service in evidence_ref so they can be filtered or audited.
  • Still-unsized vessels fall back to the category default bin as before.

Export format proposal: demand profile for Gridcog (draft v0.1)

docs/export_format_proposal.md

To confirm with Steven and Gridcog. Produced by scripts/export_gridcog.py; example files in output/export/.

Files and scenario naming

One file per combination of the two scenario axes: valencia_<scenario_power>_<adoption_case>.xlsx (and .csv).

  • scenario_power = how much a connected vessel draws: low, mid, high (per-visit kW from the evidence waterfall).
  • adoption_case = which visits connect: current_confirmed (vessels with confirmed OPS at a berth with an operational connection; empty today), fueleu_2030 (container, RoPax, cruise > 5,000 GT), phased_<year> (linear ramp of the FuelEU set, 0% in 2026 to 100% in 2030; e.g. phased_2028 = 50%), full_adoption (every merchant visit, upper bound).
  • Non-hourly files get a suffix: valencia_mid_fueleu_2030_15min.xlsx.

Sheets (xlsx); the csv is the profile sheet with the category and terminal columns appended

Sheet Column Unit Definition
profile timestamp_local ISO 8601 + offset Start of interval, Europe/Madrid, e.g. 2025-07-15T14:00:00+02:00
timestamp_utc ISO 8601 Z Start of interval in UTC. Unique key (local repeats one hour in October)
interval_min min Interval length (60 now; 15 supported)
avg_kw_vessels kW Average shore-power demand of connected vessels over the interval
avg_kw_baseline kW Existing non-OPS port load (0 until the port supplies it)
avg_kw_total kW vessels + baseline
kwh_total kWh Energy in the interval = avg_kw_total * interval_min / 60
peak_potential_kw kW Sum of the rated/peak demand of every vessel connected during the interval (see below)
n_vessels count Visits connected at any time during the interval
meta key, value Port, tz, period, interval definition, scenario definitions, model_version, data sources, generated-at, input notes
by_category avg_kw_<category> kW avg_kw_vessels split by container, ropax_ferry, roro_cargo, cruise, tanker, bulk, general_cargo, other, unknown
by_terminal avg_kw_<terminal_id> kW avg_kw_vessels split by terminal (e.g. ESVLC-T-CSP)

Conventions

  • Interval: timestamp = start of the interval; values are interval averages (period-ending conventions would shift by one row). A vessel connected for 20 minutes of an hour contributes 1/3 of its kW to that hour.
  • Time zone: both local (with offset) and UTC on every row. The local calendar has 23 rows on the last Sunday of March and 25 on the last Sunday of October; UTC has none of these gaps.
  • Average vs peak: avg_kw_* is what a meter would record as the interval mean and is what energy cost and battery sizing should use. peak_potential_kw is not a forecast of the metered peak: it assumes every vessel connected in that interval draws its peak at the same moment, so it is an upper bound for the connection/transformer rating. The real sub-interval peak sits between avg_kw_total and peak_potential_kw.
  • Confidence levels: P50/P80/P95/P99 of hourly avg_kw_total per scenario and year are in output/capacity_percentiles.csv (not in the export file).
  • Period: currently 2021-01-01 to 2026-10-31 (51,120 hourly rows); any sub-period can be exported (--start/--end).

Questions for Gridcog

  1. Which interval do you need (60, 30 or 15 min), and do you prefer start-of-interval or end-of-interval timestamps? Local time, UTC, or both?
  2. Do you ingest power (average kW) or energy (kWh per interval), or both? Should the baseline already be included in the total, or kept as a separate load?
  3. What are your limits on file size and rows (one year at 15 min = 35,040 rows; six years hourly = 51,120 rows; current xlsx about 9 MB)? Is CSV preferred over xlsx for upload?
  4. Do you want only the total profile per scenario, or components (by category, terminal or per berth/connection) as separate loads, and should multiple scenarios go in one file or one file each?

Demand model: cleaning, time zone, method, limitations

output/demand_model_report.md

Sections 1 to 3 and 12 of the pipeline's run report, kept for the data cleaning and time-zone evidence. That run predates the v0.2 category models: any energy figure or power coefficient quoted in it is superseded by the category model reconciliation above and the current headline numbers on the home page.

1. Data cleaning

Sequential filters (each row: what that filter removed from what was left):

filter calls_removed ship-hours removed calls_left
raw 0 0 36689
status != FIN 259 71623 36430
ATA or ATD not actual 51 264676 36379
harbour/service craft (name pattern, or no terminal + 'sin operación comercial') 641 511909 35738
dwell < 0.5 h 3 1 35735
dwell > 240 h 165 94937 35570

Kept 35,570 calls, 1,051,383 ship-hours. Service craft = name pattern (V.B./VB tugs, AMARRE mooring boats, DAMA DE VALENCIA, SERVIPORT, ABISUB, SAR/SALVAMAR, DN-numbered dredgers/pontoons, FT PORTORIA, etc.) or no terminal combined with regular line 'BUQUES SIN OPERACIÓN COMERCIAL' (tugs, pilot, rescue, lay-up, yachts). Calls with no terminal but on a liner service are kept and classified from the line. Dwell > 240 h (lay-ups, repairs) is dropped: these are not representative OPS connections and would inflate the base load.

2. Timezone check

Matched 219 2026 cruise calls (forecast name + date) with same-day departure. Scheduled local departure minus stored ATD: median +1.00 h in CET months vs +1.93 h in CEST months (jump +0.93 h at the DST change). Stored values follow the UTC offset of Europe/Madrid, so they are UTC. MSC ORCHESTRA (scheduled 07:00-21:00 / 07:00-18:00 local): stored median times {'Apr-Oct (CEST, UTC+2)': {'h_arr': 3.68, 'h_dep': 16.08}, 'Nov-Mar (CET, UTC+1)': {'h_arr': 4.58, 'h_dep': 20.0}}.

season n arr_median_h dep_median_h dep_p25 dep_p75
Apr-Oct (CEST, UTC+2) 176 3.33 1.93 1.80 2.12
Nov-Mar (CET, UTC+1) 43 2.27 1.00 0.72 1.13

Interpretation: the gap between scheduled local departure and stored ATD is ~1 h in winter and ~2 h in summer, i.e. it moves with the CET/CEST offset; if the values were local wall-clock it would be ~0 h all year. The stored epoch millis are therefore true UTC and all outputs were converted with tz Europe/Madrid (DST-aware; ts_local carries its UTC offset). Even after conversion, the PCS ATA is on median ~1.3 h (winter) / 1.3 h (summer) earlier than the scheduled local arrival (e.g. MSC ORCHESTRA ATA ~05:35 local for a 07:00 call): PCS ATA appears to be arrival at the port/pilot station rather than all-fast at berth, so dwell (and energy) includes some pre-berth time.

3. Method and assumptions

  • Classification (scripts/classify_vessels.py): Yes - data/vessel_master.csv used: 27,097 calls took ship_class from it and 26,200 calls took GT (match_confidence high/medium); rule-vs-master class agreement on those calls 99.9%. Rules (priority order): service craft -> other; regular line CRUCEROS -> cruise; Balearia / Trasmed / GNV / Algeria / Mostaganem lines -> ropax_ferry; granel líquido -> tanker; granel sólido -> bulk; name in 2026 cruise forecast -> cruise; CSP/APM/MSC terminals -> container; Balearia/Trasmed/GNV terminals -> ropax_ferry; VTE -> roro_cargo (Grimaldi/Neptune short-sea; Trasmed ferries and cruise at VTE are caught by the line rules first); TEPSA/GALP/PROAS -> tanker; ERSHIP/TEMAGRA/CEMEX/HOLCIM -> bulk; Erhardt/Berge/'VARIOS' -> general_cargo; no-terminal liner calls -> majority class of their regular line.
  • Power per call from data/reference/at_berth_power_assumptions.csv (low = ICCT 2017 / 4th IMO GHG basis, high = EALING Valencia FEED / EMSA). Size bins used when GT/TEU known (TEU estimated as GT/10.5); otherwise class defaults (mid kW): container 2,000; ropax 1,500; roro 1,800; cruise 9,000; tanker 1,500; bulk 450; general cargo 600; other 300. Tanker/bulk/general-cargo DWT is proxied from GT (x1.6 / x1.8 / x1.5) when only GT is known. Cruise ships < 10k GT (LOA < 150 m): 600/1,000/1,500 kW (own assumption, not in the CSV).
  • Connection: 100% of calls connect for (dwell - 1 h); 30 min at each end unpowered. This is an upper bound.
  • FuelEU 2030 scope: container, ropax_ferry and cruise with GT > 5,000 (GT unknown -> in scope), mid power.
  • Hourly values are time-weighted means within each local hour (fractional occupancy), so ships_* are average ships at berth in that hour and MW x 1 h = MWh.
  • Per-terminal columns use the PCS terminal field: CSP, APM, MSC, Trasmed (TRASMED GLE + CIA TRASMEDITERRANEA), Balearia, VTE, other (GNV, Erhardt, liquid/dry bulk, no terminal...).

Calls per terminal group and class (cleaned):

term_group bulk container cruise general_cargo ropax_ferry roro_cargo tanker
CSP 0 9327 3 0 0 0 0
APM 0 4386 0 0 0 0 0
MSC 0 2877 0 0 0 0 1
Trasmed 0 1 752 0 2261 9 0
Balearia 0 0 0 0 5924 0 0
VTE 0 5 701 1 1533 3045 1
other 547 227 17 50 2091 21 1790

Sensitivity - using GT/DWT also from low-confidence master matches (sizes 26,722 calls vs 25,989 in the base): 2025 call-based mid energy 379 GWh vs 382 GWh base (-0.9%); containers 288 vs 292 GWh. Container class default (2,000 kW) vs size-binned mean mid kW for sized container calls: 1,762 kW.

Power rule usage (cleaned calls):

ship_class power_rule calls
bulk bulk_<35k 186
bulk bulk_>35k 97
bulk class_default 264
container class_default 6910
container container_teu_1000-2000 1444
container container_teu_12000-14500 395
container container_teu_2000-3000 889
container container_teu_3000-5000 1437
container container_teu_5000-8000 965
container container_teu_8000-12000 2019
container container_teu_<1000 2315
container container_teu_>14500 449
cruise class_default 22
cruise cruise_10-60k_gt 252
cruise cruise_60-100k_gt 484
cruise cruise_<10k_gt 168
cruise cruise_>100k_gt 547
general_cargo class_default 45
general_cargo gc_>10k 6
ropax_ferry class_default 11809
roro_cargo class_default 3075
tanker class_default 450
tanker tanker_20-60k_dwt 182
tanker tanker_<20k_dwt 1158
tanker tanker_>60k_dwt 2

12. Limitations

  • No berth-level data: PCS gives terminal operator, not berth, so per-berth peaks/connection points cannot be derived; per-terminal values are terminal-operator aggregates.
  • Power values are literature values (ICCT 2017 / IMO GHG / EALING / EMSA), not measured at Valencia; real at-berth loads vary with reefers, hotel load, season and cargo operations.
  • PCS ATA appears to precede all-fast at berth by ~1-1.5 h for cruise ships (see timezone check), and ATD may lag cast-off; dwell and energy are somewhat overstated even after the 1 h connect/disconnect deduction. For container ships the PCS stay may also include anchorage waiting: container median dwell by year was 2021 30 h, 2022 33 h, 2023 26 h, 2024 31 h, 2025 43 h, 2026 38 h (CSP: 2021 30 h, 2022 33 h, 2023 26 h, 2024 35 h, 2025 54 h, 2026 45 h). The 2025 jump, with fewer calls, drives most of the 2025 energy increase and looks more like congestion/waiting (which may or may not happen at berth) than structural change. Treat the 2025 container load as an upper bound.
  • GT/TEU unknown for ships not resolved in the vessel master -> class default power; cruise GT proxied from LOA.
  • 100% connection is an upper bound; FuelEU/AFIR only mandate OPS for containers, passenger ships and cruise above 5,000 GT, and many ships will be exempt, use alternatives, or not be OPS-equipped.
  • Calls with dwell > 240 h and service craft are excluded; long-stay ships that would connect are therefore not counted.
  • Classification is rule-based where the vessel master is missing; misclassification between roro/ropax at VTE and general cargo under 'VARIOS' is possible.
  • 2026 is partial (Jan-Oct); the model ends 2026-10-31 23:00 local.

Export files

output/export_2025/ · output/export/

Draft Gridcog files, one per power level and adoption case, for calendar 2025 (below) and for the full 2021 to 2026 history. They are produced by scripts/export_gridcog.py and live in the project folder; any scenario, including your own settings, can also be downloaded as CSV from the workspace Export tab.

File (calendar 2025)Size
valencia_high_current_confirmed.csv1.68 MB
valencia_high_current_confirmed.xlsx0.97 MB
valencia_high_fueleu_2030.csv2.17 MB
valencia_high_fueleu_2030.xlsx1.51 MB
valencia_high_full_adoption.csv2.30 MB
valencia_high_full_adoption.xlsx1.60 MB
valencia_high_phased_2028.csv2.11 MB
valencia_high_phased_2028.xlsx1.44 MB
valencia_low_current_confirmed.csv1.68 MB
valencia_low_current_confirmed.xlsx0.97 MB
valencia_low_fueleu_2030.csv2.11 MB
valencia_low_fueleu_2030.xlsx1.50 MB
valencia_low_full_adoption.csv2.21 MB
valencia_low_full_adoption.xlsx1.59 MB
valencia_low_phased_2028.csv2.04 MB
valencia_low_phased_2028.xlsx1.43 MB
valencia_mid_current_confirmed.csv1.68 MB
valencia_mid_current_confirmed.xlsx0.97 MB
valencia_mid_fueleu_2030.csv2.14 MB
valencia_mid_fueleu_2030.xlsx1.51 MB
valencia_mid_full_adoption.csv2.25 MB
valencia_mid_full_adoption.xlsx1.60 MB
valencia_mid_phased_2028.csv2.07 MB
valencia_mid_phased_2028.xlsx1.44 MB