Local PowerFlow Web UI

Cooperative abort and hard reset

Active runs expose their current phase, phase start, last progress, and abort-request time. Cancellation is cooperative. If abort is requested during linear_solve, the current sparse solve must return before the cancellation check can run.

After 60 seconds in aborting, the status page offers Hard reset Web UI. This does not inject an exception into numerical code: it marks the run aborted_unknown, records that the result is invalid, and requests a clean server shutdown. Restart with julia --project=. start_webui.jl. Cooperative cancellation logs powerflow_aborted; the fallback logs webui_hard_reset_requested and webui_shutdown_requested.

Sparlectra includes a small, local-first browser interface above the existing PowerFlow service. The Web UI contains presentation, form parsing, and route handling only; numerical execution continues through start_powerflow_run and run_sparlectra_api.

Feedback and error popups

One-off feedback (a rejected submission's validation error, the case-import result summary, a case-specific-settings-loaded notice) is combined into a single dismissible <dialog> popup that opens over the PowerFlow form instead of being pushed inline into the page flow. It closes via its own close button, by clicking the dimmed backdrop, or with the Escape key. Persistent in-page notices with an actionable link — for example the configuration notice pointing at the advanced configuration tools — stay inline instead, since a modal would hide the target they link to. A separate, permanent history of recent errors remains available on the Last errors page linked from the header, independent of the popup.

Start after package installation

using Sparlectra

server = Sparlectra.start_sparlectra_webui(open_browser = true)
wait(server.task)

The package installation directory does not need to be known. By default, results are written beneath %LOCALAPPDATA%\Sparlectra\WebUI\runs on Windows, $XDG_STATE_HOME/sparlectra/webui/runs (or ~/.local/state/sparlectra/webui/runs) on Linux, and ~/Library/Application Support/Sparlectra/WebUI/runs on macOS. Directories are created automatically. The operation log is in the sibling user Web UI logs directory, and downloaded/generated MATPOWER cases are cached in the sibling user Web UI data/mpower directory. On first start, warmup_case3.jl is copied there only for internal startup warm-up and is not shown in the normal user-selectable case list.

On first startup, the Web UI copies the package configuration template to its user-writable config/configuration.yaml. Pass output_root="my_sparlectra_runs" or config_file="my_configuration.yaml" to override these defaults; an explicit configuration file is never overwritten. The effective configuration, output root, MATPOWER cache, and operation log are displayed by the Web UI; the browser cannot change the output root.

Repository developer launcher

From a repository checkout, run:

julia --project=. start_webui.jl

start_webui.jl is the single maintained developer launcher and delegates startup and default-path behavior to start_sparlectra_webui.

For end users the repository root additionally ships platform scripts: start_webui.sh / start_webui.bat (start; point at the install script when Julia is missing) and install_webui.sh / install_webui.bat (install Julia via juliaup when missing, obtain Sparlectra at its latest tagged release, offer the update when an existing copy is older than the latest release, offer the optional fast-start sysimage build and a desktop shortcut/launcher for restarting the Web UI, then start it). Unattended installs answer the questions via SPARLECTRA_UPDATE=1/0, SPARLECTRA_BUILD_SYSIMAGE=1/0, and SPARLECTRA_CREATE_SHORTCUT=1/0. The install scripts also run as a one-liner without any GitHub checkout, see the README installation section.

The call returns a SparlectraWebUIServer handle immediately. Stop it with close(server), Ctrl+C, or the Stop Web UI button in the shared page header. The button sends POST /webui/shutdown, closes the listening socket, and allows wait(server.task) to return. Pass open_browser=true to open the Web UI in a standalone app-style window without normal browser tabs or controls:

server = start_sparlectra_webui(open_browser = true)

The app-window launcher supports Microsoft Edge, Google Chrome, Chromium, and Brave. If none is installed, Sparlectra logs the local URL instead of falling back to a regular tab; open http://127.0.0.1:8080/powerflow manually if needed.

For safety, the first prototype accepts loopback hosts only: 127.0.0.1, localhost, or ::1. It is not intended for public or multi-user deployment.

The shared page header uses the existing Sparlectra documentation logo from docs/src/assets/logo.png. The Web UI serves that single PNG through its local asset route, and no additional branding configuration is required. The shared header and footer display the running package version from Sparlectra.version(), for example Sparlectra.jl v0.8.4.

Startup warm-up

start_sparlectra_webui accepts warmup, warmup_casefile, and warmup_store_result. warmup defaults to nothing, which means the configuration decides: webui.warmup (default true) is editable as Warm up on start under the form's Advanced options and takes effect at the next Web UI start; an explicit warmup = true/false in the call always wins. Besides the power-flow path, the warm-up also compiles the short-circuit path (Z-bus solve, IEC c-factor table, result and coverage types) on a throwaway two-bus network, so the first Short circuit click no longer pays that compilation. Warm-up runs asynchronously and fails softly. With warmup_store_result=false, it uses a temporary directory and creates no normal run-history entry. The bundled data/webui/warmup_case3.jl file is an original Sparlectra-owned synthetic three-bus MATPOWER-compatible Julia case, not a derivative of an external MATPOWER case. Files whose names start with the reserved warmup_ prefix are internal-only and are hidden from the case selector; pass warmup_casefile when a different explicit warm-up case is needed.

Starting a PowerFlow run

Web UI submissions start in a background worker task and redirect immediately to a run-status page. Near the top, a highlighted clock card shows elapsed time in HH:MM:SS format beside the current status. The technical details table retains the raw elapsed_seconds value along with the requested and resolved case paths, start time, and a manual refresh link. Queued, running, and aborting pages also refresh every two seconds through an HTML refresh directive. The marked autorefresh=1 requests are not recorded as user actions. Terminal success, failure, and abort pages stop refreshing automatically. While a job is queued or running, it also shows an Abort run form that sends POST /powerflow/abort/<run-id>; JavaScript is not required.

The start form and run-history page also show a prominent active-run banner with Open status and POST-only Abort controls. This keeps abort discoverable even when the user navigates away from the status page. The controls disappear as soon as the run reaches a completed, failed, or aborted state.

Abort is cooperative and never kills a Julia task unsafely. The abort request changes the visible state to aborting immediately, and the Web UI PowerFlow path checks cancellation before and after major service phases and inside each rectangular Newton iteration. The rectangular path also checks immediately before and after Y-bus construction and start projection, after Q-limit active set work, and after each Newton step. A sparse factorization or other non-interruptible operation may still finish before the next check, so the status page shows the current phase and explains that the phase may need to finish before cancellation is observed. Repeated requests are idempotent. Once cancellation is observed, the terminal state becomes aborted, powerflow_aborted is written to the operation log, the active-run guard is released, and a new submission is accepted. Aborted runs retain a normal run directory, result.json, and run.log status marker, but are never reported as success.

Large MATPOWER cases can spend substantial time before Newton iterations begin, especially while reading .m files, evaluating large .jl literal cases, building the Sparlectra network, assembling Y-bus data, or preparing start values. The result page, operation log, run.log, result.json, and performance.log (when timing is enabled) now expose service phase timings so users can distinguish reader, converter/cache, network-builder, solver, and artifact costs. These diagnostics do not guarantee that very large cases finish quickly through the local Web UI; they identify where follow-up optimization should focus. The operation log intentionally records only high-level phase starts; detailed Y-bus, Newton-iteration, Q-limit, and linear-solve timings belong to each run's performance.log and are summarized there instead of being repeated in the Web UI support log.

Deletion of a queued, running, or aborting run is rejected with an explanation. After the run reaches terminal aborted status, normal deletion is available.

The start page accepts:

  • a typed MATPOWER case name or an existing local case path;
  • a Sparlectra configuration template file;
  • read-only information showing the server's configured output-root directory;
  • PowerFlow tolerance and maximum iterations;
  • autodamping and its minimum factor;
  • Q-limit handling;
  • a single Solver radio group with three mutually exclusive, peer options — AC (Newton-Raphson, rectangular), APSLF (AnalyticLoadFlow), and DC (linear screening model) — with conditional, indented sub-options for whichever solver is selected;
  • wrong-branch detection mode;
  • angle and voltage start modes;
  • current-iteration pre-solve fields in the collapsible Advanced start values section;
  • merit-function line-search fields in the collapsible Merit-function line search section;
  • a visible MATPOWER import conventions section with auto-profile mode (off, recommend, or apply) plus manual transformer-ratio, phase-shift, bus-shunt, PV-voltage-source, and comparison-reference overrides;
  • logfile result mode;
  • single-run performance timing detail;
  • optional post-run diagnostics; and
  • benchmark enablement, samples, and seconds.

Only keys in GUI_EDITABLE_CONFIG_KEYS are submitted. The output root is chosen only through start_sparlectra_webui(; output_root=...), is displayed as read-only information, and cannot be overridden by a submitted browser field. The page does not offer a generic YAML editor and never modifies the selected template. The service creates an effective_config.yaml artifact for each run. The header and webui_operations.jsonl include the Sparlectra version, package path, and local Git commit when available so users can confirm which checkout is serving the browser page.

The current-iteration controls in Advanced start values write the same power_flow.start_current_iteration.* overrides documented in powerflow_configuration.md. They configure a guarded start-value preconditioner that runs after the normal start modes and optional start projection, before Newton-Raphson. They do not add a new start-voltage/start-angle mode and do not replace the rectangular Newton-Raphson solver. When case-specific sidecar saving is enabled, these fields are saved and restored through the same profile mechanism as the other Web UI form options.

The Merit-function line search controls write the same power_flow.merit.enabled/power_flow.merit.armijo_c1/power_flow.merit.fallback_max_mismatch overrides documented in powerflow_configuration.md. This is an opt-in Armijo acceptance criterion inside the existing autodamp backtracking loop; it requires power_flow.autodamp = true and does not replace autodamp or the Newton-Raphson solver. The residual-scaling keys (scale_p/scale_q/scale_v) are YAML-only and are not exposed as form fields. When a diagnostic run directory is available, results include a merit_linesearch.log text artifact.

The Solver radio group is a single power_flow_solver form field with three peer, mutually exclusive values — rectangular, apslf, dc — and writes the same power_flow.solver/power_flow.apslf.*/ power_flow.apslf_start.*/power_flow.dc.* overrides documented in powerflow_configuration.md and powerflow_configuration.md. An earlier version of this page presented AC/DC and rectangular/APSLF as two separate, layered controls (a "Berechnungsmodell" AC/DC radio group above a Solver dropdown that only ever chose between rectangular and apslf, DC being forced onto the dropdown from outside it). That structure made APSLF look like a sub-choice of AC even though it is a fully independent solver, a power_flow_calc_mode field existed only to drive the same underlying power_flow.solver value the dropdown also wrote (so the two controls could show inconsistent state), and it caused a real bug: because the Solver dropdown was disabled whenever DC was chosen, and disabled <select> elements are dropped from a submitted HTML form entirely, choosing DC could silently submit no power_flow.solver override at all and the run fell back to the default rectangular solver — reported to the user as an ordinary AC/NR convergence failure with no mention of DC anywhere in the diagnostics. The current single three-way radio group removes both problems by construction: there is exactly one field, exactly one place to pick a solver, and radio buttons are never individually disabled (only the checked one is submitted), so there is no submission path that can drop the choice.

Choosing AC (Newton-Raphson, rectangular) reveals the Newton-Raphson start- value block (Use APSLF start values, indented order field) together with every other AC/NR-only option (tolerance, autodamping/merit/trust-region step control, Q-limit handling, maximum iterations, wrong-branch detection, start angle/voltage mode, the current-iteration pre-solve block, transformer tap-changer model). By default (power_flow.start_mode.angle_mode = dc) the Newton-Raphson solver already seeds its own start angles from a fast internal DC pre-solve before iterating — it is not a separate configuration step; the Start angle mode dropdown further down the form (still NR-only) controls this and documents the other available start strategies. This DC pre-solve is unrelated to, and does not require, choosing the standalone DC solver option below.

Choosing APSLF (AnalyticLoadFlow) reveals an indented APSLF solver options block (highest coefficient/order, Padé evaluation, NR polish) instead. The Use APSLF start values checkbox in the Newton-Raphson block is unrelated to and mutually exclusive with the APSLF solver selection (the underlying configuration rejects setting both at once) — it configures how the rectangular NR solver seeds itself, not APSLF. As with the Q-limit and current-iteration checkboxes, an unchecked APSLF checkbox explicitly submits false rather than omitting the key. The APSLF solver requires the optional AnalyticLoadFlow.jl dependency to be loaded in the server process; if it is not installed, the run fails immediately with a clear pre-solve error instead of a silent fallback to the rectangular solver.

Choosing DC (lineares Screening-Modell, ersetzt Newton-Raphson vollständig) selects the standalone linear DC power-flow model described below, replacing Newton-Raphson entirely rather than merely seeding its start values.

Result and status pages reuse the existing summary, timing-card, artifact, and history views unchanged; the run status header additionally shows a Solver entry (rectangular, apslf, or dc) identifying which solver actually produced the result.

Mutually exclusive fields are grayed out, not hidden

Fields that don't apply to the currently selected solver (or, within the Newton-Raphson autodamp/trust-region step control, to the currently enabled step-control strategy) stay in their place in the form and are disabled with reduced opacity instead of disappearing. Earlier versions of this page hid inapplicable fields outright (hidden), which could make the form feel like fields randomly appeared/vanished/reordered when switching solvers. Nothing about which keys get submitted changes: a grayed-out field's underlying input is still disabled and therefore still omitted from the submitted form exactly as before — only the visual treatment changed.

DC power flow mode

Selecting DC in the Solver radio group does not add a new configuration key: it is simply the dc value of the same power_flow.solver field the rectangular/apslf options also write, documented together with power_flow.solver in powerflow_configuration.md. Selecting DC grays out every AC-only option that has no DC meaning: tolerance, autodamping/merit/trust-region step control, Q-limit handling, maximum iterations, wrong-branch detection, start angle/voltage mode, the current-iteration pre-solve block, and the transformer tap-changer model — their inputs are disabled and therefore not part of the submitted form, the same client-side mechanism already used for Newton-Raphson-only fields when APSLF is selected.

A DC run reuses the existing asynchronous job, abort, status, history, and artifact machinery unchanged; only the request's power_flow.solver override differs. The result page marks a DC run with a DC solution badge next to the Solver summary entry, and the run history table's Solver column shows dc for these runs, so a DC run's implicit Vm = 1.0 pu and lossless branch flows are never mistaken for an AC result. iterations is reported as-is from the DC solve (always 1, a direct linear solve, not a Newton iteration count).

Case-specific settings profiles

Case-specific Web UI settings are optional. When a terminal result page shows a successful or converged run, the compact Case settings section offers Save settings for this case. This writes only the Web UI form options that were used for that completed run, plus traceability metadata, into a sanitized YAML profile below the Web UI output root. It does not save the run's full effective_config.yaml, solver internals, artifact paths, or transient convergence diagnostics.

If the run did not converge, the result page does not show the normal save action. It instead labels the action Save these settings anyway and records that the user explicitly overrode the non-successful-run warning. No profile is saved automatically.

When the same MATPOWER case is opened again with a saved profile, the form is prefilled with the profile values and displays a small notice. Precedence stays conservative: built-in defaults are loaded first, global configuration remains unchanged, the case-specific Web UI profile only prefills editable form fields, and any manual browser edit wins for the submitted run.

Between the configuration file and a saved case profile, the last edit wins: when the YAML file is newer than the saved profile, the keys the YAML sets take precedence on the next page load (the notice says so), while fields the YAML does not set keep their saved case values. Editing the configuration therefore shows up on a simple page refresh — no Web UI restart needed.

The existing-case selector is MATPOWER-oriented by default and lists user-selectable .m files plus runnable DTF .DAT candidates when they are supported by the current Web UI case-resolution logic. Generated .jl cache artifacts are hidden from the selector, and files with the reserved warmup_ prefix are internal-only. FOR002-like .DAT files are not primary cases; use the optional FOR002 reference field for those validation references. The FOR002 reference field is used only for legacy reference comparison diagnostics: enter an absolute path, a path copied from the same case cache directory, or select a FOR002.DAT candidate already present in the case cache when one is offered. The Case input format selector defaults to Auto, which recognises MATPOWER files, CGMES deliveries (folders and ZIPs) and — where the FOR001 markers are unambiguous — native DTF input. Selecting CGMES (ENTSO-E, folder or ZIP) forces the CGMES importer; the option is preselected automatically when the chosen case is a .zip or a directory. The native DTF path is experimental/internal and intended for diagnostics and validation, not the primary workflow. For the selected-outage-records mode, the Selected DTF outage labels/indices field accepts one parsed label or outage index at a time; the result page reports the compact outage summary while detailed rows stay in artifacts. First startup still provisions the small warmup_case3.jl case for warmup, but it is not user-selectable. A separate manual field accepts a bare case name such as case14.m, case118.m, or case9241pegase.m; a nonempty manual value overrides the selected cached case. Internal DTF support is intended for supported conversion and validation workflows and does not change the normal MATPOWER-first workflow.

The landing page includes a compact, collapsible MATPOWER acknowledgement beside the case inputs. It distinguishes Sparlectra from MATPOWER, provides links to the MATPOWER project, its citation guidance, and the standard 2011 paper DOI, and notes that ACTIVSg, PEGASE, RTE, and other case files may request additional case-specific citations in their file headers.

A missing bare .m case name is resolved in the user Web UI data/mpower cache through the standard MATPOWER download helper and remains the executed source. Web UI/service PowerFlow runs do not automatically replace selected .m files with generated .jl cache files. If a user manually submits a generated .jl file from the Web UI MATPOWER cache and a matching .m source exists, the service resolves back to the .m file and records that the generated cache was bypassed. If the matching .m source is missing, the request is rejected with a clear validation error. Large generated .jl MATPOWER cases can fail while Julia and SparseArrays load literal data, before Sparlectra network construction or Newton iterations begin, so .m remains the canonical Web UI execution source.

Existing absolute and relative .m or .jl paths remain supported. A missing input containing a path separator is rejected instead of downloaded, and URL input is not accepted. The browser cannot select runtime directories. The read-only configuration path is the provisioned user file or the explicit file passed at startup.

Run artifacts and output modes

The Logfile output mode is forwarded through the form, service request, API configuration override, and run.log writer. classic keeps the standard result report plus a compact API timing/status summary. full adds a marked Full run details section with the effective typed configuration, artifact choices, and available status diagnostics. The summary records solver_time, representative_time, iterations, final mismatch, and final outcome where available. Benchmark median and sample count appear when benchmark mode is enabled.

The Export case as CGMES delivery (EQ+TP+SSH+SV, ZIP) checkbox writes the case as one re-importable CGMES delivery zip into the run's artifact directory — for every case format, and also on non-converged runs. See CGMES Export for what the export covers and how object identity is handled.

MATPOWER .m imports additionally print "Original/Final effective MATPOWER import options" and a "MATPOWER auto-profile recommendations" table, because MATPOWER files leave branch-convention details (shift_sign, shift_unit, ratio, ...) ambiguous enough to warrant a residual-scan recommendation step. DTF/FOR001 .DAT imports do not carry this ambiguity and therefore never print these sections, at any logfile output mode — a shorter run.log for a DTF case is expected, not a sign that classic/full logging is broken for that format.

The Performance timing control accepts off, compact, or full and writes performance.log when enabled. It describes phases of one request, unlike benchmark.enabled, which measures repeated solves and median timing. Service runs can include request parsing and case resolution; API phases include configuration, case loading/network construction/solve, postprocessing when separately available, artifact writing, solver time, and total time. full also includes available internal profile entries.

A normal Start PowerFlow run never writes diagnose.log — use the Diagnose action below for that. When it is written (by Diagnose, or programmatically via run_diagnostics = true), it is a diagnostic report rather than a flat key/value dump on a run that did not converge: a "Diagnosis" section names the worst-mismatch bus/equation and classifies the mismatch-history trend (monotonic / oscillatory / stagnant / diverging to non-finite) and autodamp health, a "Branch anomalies at worst-mismatch bus" section scans the branches incident to that bus for zero impedance, off-nominal transformer tap ratios, large phase shifts, or a reactance far outside the range of the other branches at the same bus, and a "Recommendations" section closes with concrete next steps. It also reuses the existing Q-limit event, PV-limit, and final limit-validation printers. A diagnostic exception is contained and recorded in that file without changing a successful PowerFlow result. Older run directories can still contain diagnose.txt; the artifact viewer continues to list and download that legacy filename.

Diagnose action

The Diagnose button next to Start PowerFlow run runs the selected case through a fixed-reference self-check instead of a normal solve: it evaluates the mismatch at the case's own stored operating point — MATPOWER VM/VA columns, or the SvVoltage state of a CGMES delivery — with no corrective Newton step. Every start-value machine is forced off (flatstart = false, start_projection = false, dc_seed_unconditional = false, start_current_iteration.enabled = false, apslf_start.enabled = false, plus max_iter = 1 and qlimits.enabled = false), so the imported voltages reach the solver verbatim and the reported residual reflects the imported network model itself rather than the solver's start guess or step control. It runs through the same result pipeline as a normal run (same run history, artifact viewer, and enriched diagnose.log) and writes two additional artifacts: self_check.log (forced settings, the start-state residual, and for CGMES the count of buses without a usable SvVoltage, which start at the flat 1.0 pu / 0° fallback and weaken the SV comparison) and self_check_residuals.csv (full per-bus P/Q residuals at the start state, with per-bus SV coverage plus transformer-terminal and shunt counts for attribution). The merged self-check configuration is written alongside the other artifacts as diagnose_self_check_config.yaml for inspection. Programmatically, the same behavior is available as run_fixed_reference_self_check.

Short circuit action

The Short circuit button next to Diagnose evaluates the balanced three-phase short-circuit currents (IEC 60909-0, runShortCircuit!) for every bus of a CGMES delivery — maximum and minimum case in one run, without any power-flow solve. The button is only selectable when the selected case is a CGMES delivery that actually carries short-circuit source data (synchronous machines, feeder short-circuit currents, or equivalent impedances); the form checks the delivery contents server-side and disables the button with an explanatory tooltip otherwise. The run writes short_circuit_max.csv and short_circuit_min.csv (per-bus Ik'', Sk'', κ, i_p, plus the safety flag and its reasons), a run.log narrative including the harvested-data coverage report, and a result-page summary row — rows with defaulted/skipped data render as a warning badge because a flagged Ik''max is a lower bound. A delivery without usable sources fails with short_circuit_data_missing (coverage report in run.log) instead of producing empty tables; non-CGMES cases fail with short_circuit_requires_cgmes.

Import analysis on case upload

Import case files checks every uploaded CGMES delivery immediately. When the delivery is complete (or a matching boundary is found or supplied automatically), the import message says "ready to compute". When it stays incomplete, the upload runs the full import analysis: the message names the missing declared md:Model.DependentOn dependencies by model id (the boundary set, typically), and the complete report — supplied models, dependency matching, unresolved-reference histogram, verdict — is written next to the case as <case>.import_analysis.txt. The same analysis is appended to cgmes.log automatically whenever a regular run's CGMES import aborts. For API/scripted use the check is also available as a run mode (import_analysis_mode on start_powerflow_run; a non-importable delivery finishes as a failed run with reason import_analysis_not_importable) and programmatically via analyzeCGMES.

The Require boundary set checkbox (CGMES section, saved in the per-case settings) submits cgmes_import.require_boundary as a run override: unchecked, an incomplete delivery imports anyway where possible — buses without a resolvable BaseVoltage still abort, with the analysis explaining why.

The Non-convergence handling block under Advanced options exposes power_flow.rescue (retry ladder for failed AC solves) and power_flow.dc.fallback (standalone DC result when AC has no solution) — see Power-Flow Configuration.

The Export detailed result CSV files checkbox is off by default because large networks can produce large files. When enabled for a successful run, it writes Excel-friendly UTF-8 artifacts:

  • bus_voltages_complex.csv contains one row per bus, including vm_pu, va_deg, numeric rectangular components v_re and v_im, a readable v_complex value, nominal/actual voltage, generation, load, Q-limit, and control columns.
  • branch_flows.csv contains physical branch rows with active/reactive power at both ends, losses, rating, status, and overload information.

The CSV files reuse the structured ACPFlowReport node and branch rows and, like the log artifacts, are viewable and downloadable through the normal artifact list.

The indented CSV format selector is subordinate to the opt-in export:

  • technical (default) uses a comma delimiter, decimal point, and no thousands grouping.
  • excel_de uses a semicolon delimiter, decimal comma, and thousands dot.
  • excel_us uses a comma delimiter, decimal point, and thousands comma.

US-formatted numbers containing a thousands comma are quoted because comma is also the field delimiter. Empty values and fields containing delimiters, quotes, carriage returns, or line feeds follow the same CSV quoting rules in all formats. The Excel-oriented formats write numeric fields in decimal notation instead of exponent notation where practical. The readable v_complex column follows the selected decimal notation, while v_re and v_im remain separate numeric columns.

Excel may still warn about automatic conversions when opening CSV files directly, especially if textual identifiers resemble scientific notation such as 1E5. Use Excel's Data > From Text/CSV import flow and select text types for exact textual identifiers when that distinction matters. The technical format remains the clean machine-readable default and does not add Excel-specific text hints.

PowerFlow input paths

Help topicInputGuidance
webui.casefileMATPOWER case fileChoose an available .m, .jl, or supported runnable internal DTF .DAT candidate from the existing-case selector, or type a bare case name or existing local path in the separate manual field. A nonempty manual value takes precedence. Missing bare .m names may be downloaded into the server-owned data/mpower directory; MATPOWER .m remains the default-oriented workflow, while FOR002-like .DAT files belong in the optional FOR002 reference field rather than the primary case field. Missing path-like inputs and URLs are rejected.
webui.config_fileConfiguration template fileSelect a YAML configuration or *.yaml.example template discovered in examples. Form values create allowlisted per-run overrides, while the selected template remains unchanged.
webui.output_rootOutput root directoryConfigure this path when calling start_sparlectra_webui; the browser displays it read-only. The service creates its persistent run index and one subdirectory per run beneath this root.

Contextual help and documentation

Every editable PowerFlow form option includes a contextual help link. Help pages include a Back button that uses the browser history to return to the existing PowerFlow form, preserving the values entered before opening help. If no local history entry is available, the button falls back to /powerflow. Help pages load the matching section or option row from repository Markdown at request time. Solver options use powerflow_configuration.md, output and benchmark options use performance_profiling.md, and path fields use the table above. Explanatory option text is not copied into Julia views or HTML templates; repository Markdown remains the single source of truth.

The Documentation navigation link opens /docs, which lists selected allowlisted pages under docs/src. Each /docs/<page> request resolves only a registered page name, so arbitrary paths and traversal requests are rejected. Markdown links to another allowlisted page are rewritten to local /docs/... routes, including section fragments such as the start-mode options. External HTTP and HTTPS links remain external; unknown or unsafe local paths are made inert. This is a lightweight reader for local reference material, not a replacement for the Documenter.jl site.

Results and artifacts

Successful and failed runs both have a result page. It shows the run ID, schema version, status, convergence and solution flags, iteration count, final mismatch, reason/message fields, input paths, and output directory. Aborted runs are listed distinctly in history and are never rendered as successful. After an abort, the user can return to the form and submit new inputs without restarting the server.

Artifact lists come from list_powerflow_artifacts. Artifact requests are resolved by exact metadata name through resolve_powerflow_artifact; browser input is never joined directly to a filesystem path. JSON, YAML, logs, CSV, HTML, Markdown, and other text artifacts are displayed as escaped text in a large, scrollable panel that preserves long lines for horizontal scrolling. Help excerpts and full documentation pages also use wider content panels and readable line spacing. Other files are downloaded, and every artifact page also offers an explicit download response. The text-artifact viewer uses 75–85 percent of the viewport height and a wider page layout for practical inspection of long logs and configuration files.

Runs that attempt the guarded current-iteration start pre-solve may include current_iteration_start.log. The artifact is classified as a start-value/current-iteration diagnostic artifact and records whether the candidate was attempted, accepted, rejected by a guard, or rejected with the original start values restored before Newton-Raphson.

Persistent operation log

The Web UI appends support-oriented JSON Lines events to its user-writable logs/webui_operations.jsonl. This file is independent of individual run directories and survives Web UI restarts that reuse the same output root. It records key page opens, submissions and validation failures, asynchronous run lifecycle changes, artifact views/downloads, abort requests, history refreshes, deletions, shutdown requests, and enabled diagnostics or timing modes. Static CSS and image requests are not user-action events.

Use the shared Operation Log navigation link to open the escaped text viewer at /webui/operation-log, or download the JSONL file from that page for an error report. Entries contain concise route, method, status, run/case/artifact, message, and timing fields when available. Every event also records sparlectra_version and a millisecond-precision UTC timestamp using yyyy-mm-ddTHH:MM:SS.sssZ. They never include artifact contents, local file contents, or complete configuration bodies. Logging is best effort and cannot fail a normal Web UI request. After an append takes the file above 10,000 valid JSONL entries, compaction atomically keeps the newest 1,000 valid entries and drops empty or malformed lines encountered during compaction. When the current file reaches 10 MiB, it is replaced after being retained as webui_operations.jsonl.1; this byte-size guard remains independent of entry-count compaction. The viewer and download read the current file.

Development reports distinguish external Verification limitations, such as an unavailable browser executable or an HTTP 403/proxy failure while installing documentation dependencies, from genuinely unfinished implementation work.

Persistent run history and run management

start_sparlectra_webui refreshes powerflow_runs_index.json beneath the configured output root before it begins serving pages, so valid runs from an earlier Julia process appear immediately. The Refresh registry button remains available for a manual reload. Missing, corrupt, or unsafe entries are reported or skipped without preventing valid runs from loading.

History is ordered newest first and shows a readable local date/time, run ID, status text, status badge, solver summary fields, and actions. Green, yellow, red, gray, and blue badges distinguish successful, warning/partial, failed, unknown, and running states while retaining visible text for accessibility. Older indexes without timestamps use the result.json modification time.

Each registered run has a Delete action, and Delete all runs removes all safely registered runs for the current configured root. These actions update the in-memory registry and persistent index as well as deleting the matching run directories. Run IDs are validated, indexed paths must remain beneath the configured root, and browser-submitted output roots are ignored; unrelated files and directories are never deletion targets.

Browser and application shutdown

All normal pages send a small local heartbeat after they load. With auto_shutdown_on_browser_close=true, heartbeat expiry after browser_heartbeat_timeout_seconds triggers best-effort shutdown after at least one heartbeat has been received. A server started with open_browser=false therefore remains running until a browser actually connects, the Stop Web UI button is used, close(server) is called, or the terminal receives Ctrl+C.

Browser-close detection is necessarily best effort: browser crashes, forced process termination, or operating-system shutdown may prevent a final clean lifecycle. Ctrl+C remains the fallback. If a port is still occupied, stop the old Julia process or start the Web UI with a different port value.

Current limitations

This first prototype is intentionally synchronous and local. It has no State Estimation UI, authentication, public-server mode, background queue, live progress stream, WebSockets, database, topology view, or advanced plotting. It uses a compact Julia Sockets HTTP layer to avoid a heavy web-framework dependency.

Configuration check and refresh

The PowerFlow page includes explicit Check configuration and Refresh configuration actions for user YAML files. They exist because the package configuration template can gain new options over time while existing local files remain in place. A check performs a dry run only: it compares the selected configuration against src/configuration.yaml.example, reports missing keys, known deprecated aliases, duplicate YAML keys, and shows a refreshed YAML preview without writing.

Refresh is conservative and user-initiated. It preserves existing user values, adds missing keys with current template defaults, and may normalize known deprecated aliases in user files to canonical start-mode settings or legacy matpower_* Q-limit mode names. It never rewrites YAML during Web UI startup. When writing a server-local configuration file, Sparlectra first creates a timestamped backup next to the original file. If duplicate YAML keys are detected, refresh refuses to write so the file can be reviewed manually. Browser-uploaded or pasted YAML is not rewritten in place; the refreshed YAML is offered as a download instead.

Configuration precedence and artifact downloads

PowerFlow API and Web UI runs apply configuration in a deterministic order: built-in defaults from src/configuration.yaml.example, the selected user YAML file, saved case-sidecar settings when the Web UI loads them into the run form, enabled Web UI form/runtime values, explicit API config_overrides, and intentional post-processing such as matpower_import.auto_profile: apply. Each run writes the actual effective_config.yaml; the file includes _config_sources metadata for the diagnostic options most likely to affect MATPOWER DC-line and island-aware solves, including Q-limit handling, start-current iteration, island mode, tolerance, iteration limits, start modes, and MATPOWER DC-line mode.

Web UI runtime controls are applied by default, so checked/enabled options and values entered or selected on the PowerFlow form are intentional runtime overrides. Boolean values are distinct from override participation: an unchecked functional checkbox can intentionally override YAML to false. The advanced Ignore Web UI settings and use configuration defaults checkbox inverts that behavior for diagnostic runs: when checked, the run ignores the form controls and uses the selected YAML/default configuration values instead. matpower_import.auto_profile: apply may still adjust supported MATPOWER import conventions after GUI and API values are assembled, and effective_config.yaml records those auto-profile applications. Active MATPOWER DC lines are supported by default as fixed terminal injections; they do not add Ybus connections, so AC islands are detected and solved independently by default. This is a power-flow approximation, not a complete HVDC converter or DC-grid model. When the YAML editor saves successfully, the server reloads the saved file so the PowerFlow form reflects the new YAML values on the next page load.

The plain Configuration Editor link on the PowerFlow page opens the active YAML in a textarea, validates it with the same lightweight YAML parser and duplicate-key checks used by configuration refresh, writes only after validation succeeds, and creates a timestamped backup next to the edited file. If case-sidecar settings exist for a selected case, they can still override the global YAML via the prefilled form; the editor warns about that interaction so stale case-specific settings are not mistaken for global configuration changes.

Result pages and artifact lists include Download all artifacts as ZIP. The ZIP is named sparlectra_run_<run_id>_artifacts.zip and is assembled only from files already exposed as artifacts for that run directory. Missing optional artifacts are skipped, and unsafe names are ignored rather than allowing path traversal.

Island diagnostics are run artifacts. Files such as ac_islands.csv, ac_island_solver_summary.csv, ac_island_<id>_solver.log, matpower_dcline.csv, q_limit.log, performance.log, run.log, and effective_config.yaml belong in the run output directory or a test-owned temporary directory; they must not be committed from the repository root.

Importing case files through the Web UI

The PowerFlow page includes a separate Import case files control near the case selection area. It uses the browser's native file picker and accepts multiple files in one selection. The picker advertises MATPOWER .m/.M files, DTF .dat/.DAT files and CGMES .zip deliveries; the server validates the extension again because browser-side filters can be bypassed. A CGMES ZIP may contain the whole delivery, including nested ZIPs — the importer opens them in memory, so no unpacking step is required.

Importing is a copy-only operation. It does not submit the PowerFlow form, create a run ID, create a result directory, parse uploaded .m code, or invoke the solver. After the POST/Redirect/GET refresh, the normal case selector is rebuilt from disk. If at least one imported file is runnable in the normal selector, the first such file may be preselected; the user must still press Start PowerFlow run to calculate it.

Pressing Enter in the Or type case file path field resolves the typed value the same copy-only way instead of starting a run: a bare MATPOWER case name (for example case300.m) is downloaded through ensure_casefile into the case directory, an entry of the form cgmes:<alias> fetches an ENTSO-E CGMES test configuration (see below), while a full local path to an existing file is copied into the case directory with the same validation as file import (unsupported extensions, oversized files, and name collisions are rejected with an inline message). Either way the resolved file then appears in the Existing case file selector; it does not submit the PowerFlow form or invoke the solver.

Uploaded files are stored in the same effective Web UI case directory shown in the form and used by the selector. Development checkouts use the writable data/mpower directory when it is available; installed or immutable package contexts fall back to the user-writable Web UI application data directory, specifically the sibling data/mpower directory next to the configured Web UI output root. The directory is created as needed. Manual full paths remain available for advanced users and continue to override the selector when filled in.

Upload limits are centralized in the Web UI implementation: 100 MiB per file and 250 MiB per multipart request. Oversized files are rejected cleanly and reported in the import summary. Existing files are not overwritten; conflicting uploads are rejected as already exists, while other selected files can still be imported. Filenames are treated as untrusted: directory components, traversal attempts, empty names, control characters, and names that would resolve outside the case directory are rejected. Writes are staged through a temporary file in the destination directory and then renamed into place.

The normal case selector continues to use the existing Web UI filtering rules. Imported MATPOWER .m files and runnable DTF .DAT files appear after refresh. FOR002 reference .DAT files may be copied for validation workflows but remain hidden from the normal runnable-case selector and belong in the optional FOR002 reference field.

Fetching ENTSO-E CGMES test configurations

Typing cgmes:<alias> into the Or type case file path field downloads the official ENTSO-E test-configuration package once (~22 MB) into the local CGMES cache (data/CGMES, overridable with SPARLECTRA_CGMES_CACHE), extracts it, and packs the requested configuration — base case together with its boundary set — into a single cgmes_<alias>.zip in the case directory. The ZIP then behaves like any other imported case.

Available aliases: microgrid_be, microgrid_nl, microgrid_assembled, smallgrid, smallgrid_nb, fullgrid, fullgrid_nb, realgrid. Repeated requests reuse the packed ZIP instead of downloading again. If the download fails, the error message names the file path where the package can be placed manually. The test data is never committed to the repository.

PowerFlow tolerance spinner

The PowerFlow tolerance control is a text field that accepts ordinary decimal values and scientific notation (for example 1e-8). A dedicated exponent spinner — the up/down buttons next to the field, or the Up/Down arrow keys while the field is focused — steps the exponent by one while keeping the mantissa unchanged: stepping down from 1e-5 yields 1e-6, stepping up from 1e-5 yields 1e-4. Manual entry and submitted solver tolerance values are unchanged.