Grid-Tie Inverter (US / India)¶
EXAMPLE · REFERENCE MODEL · model_gti/
A three-phase, 10 kW, transformerless grid-tie inverter with a multi-string, high-voltage (1000 V) solar input and one MPPT tracker per string pair, sold into two grid-code regions (United States, India) from one hardware platform, with a mandatory STM32 controller. It is the first model built to exercise the executable parts of syscribe together with the product-line and safety features.
syscribe -m model_gti/ validate --all-configs
syscribe -m model_gti/ simulate TC-GTI-PROT-US-001 --coverage
syscribe -m model_gti/ mutate TC-GTI-PROT-IN-001
syscribe -m model_gti/ inject TC-GTI-PROT-US-001 --ft FT-GTI-001 --max-order 3 --report-only --config CONF-GTI-US-M3-001
syscribe -m model_gti/ validate --config CONF-GTI-US-M3-001 --deny W940 # every defeated set has a decision
syscribe -m model_gti/ matrix
What it contains¶
| Area | Content |
|---|---|
Analysis/ | Domain analysis, stakeholder concerns, US/India comparison, regulatory matrix with a verification status for every limit |
Features/, Configurations/ | Product line: region (US/IN), 2 or 3 trackers, global scan, string monitoring, arc-fault, rapid shutdown, communications, grid-support functions; four stored products and a feature-gated 150 % model (896 valid configurations) |
Requirements/ | 8 stakeholder needs, system requirements with regional variants, hardware and software leaves, each traced to a satisfying element and a test |
System/, Allocations/ | Hardware (power stage, DC input, AC output, sensing, STM32G474 control board) and firmware components; firmware allocated to the STM32 |
Decisions/ | Requirement-breakdown ADR, the STM32G474 selection ADR, four recorded assumptions (open until confirmed), and the fault-campaign-driven sensing ADR |
Safety/, Security/ | HARA (4 goals), architecture FMEA, an FMEA and fault tree with injectable faults, residual-risk decisions on the defeated fault sets, a TARA |
Behavior/ | Executable state machines: grid monitor, perturbation-response check, supervisor, hardware trip, relays, power stage, MPPT tracker; the grid impedance plant (Plants/); the protection chain as a composite with a US and an India variant |
Verification/, TestPlans/ | Gherkin test cases (executable and descriptive) and one verification plan per product |
Assumptions the model makes on the user's behalf¶
The request said "hybrid solar mode … multi string high voltage solar strings with moot". The model reads hybrid as multi-string high-voltage PV (no battery) and moot as MPPT. Power class (10 kW), phase configuration (three-phase), DC voltage class (1000 V) and the exact STM32 part are assumptions; all are recorded as proposed ADRs (ADR-GTI-ASM-*, ADR-GTI-MCU-001).
Regulatory values are not facts. Primary standards were not accessible when the model was written. Every limit is a review input carrying a verification status in the regulatory matrix; tests and requirements that quote one are tagged reg-unverified (syscribe -m model_gti/ list Requirement --tag reg-unverified).
What the executable model found¶
- A real design flaw. The first version of the protection chain fed the software monitor and the hardware trip from one voltage-sensing chain.
injectreported a single-fault defeat of the invariant "after a grid loss the grid is never energised for longer than 2 s". The fix (an independent sensing chain,REQ-GTI-HW-008,ADR-GTI-SAFE-001) came from the campaign, and the fault tree's minimal cut sets (order ≤ 3) are all defeated, as the tree predicts, in both regional variants. - Test gaps found by mutation. The first scenario set killed 33 % of the mutants of the grid monitor; boundary scenarios for every limit, recovery edge and insulation threshold bring the chain to 91 % (the rest are mostly equivalent mutants).
- Three more flaws found by an independent review and fixed with new scenarios: a dead grid at power-up was never reported (the monitor only reports changes), so the inverter connected to it after the reconnect delay; the hardware trip latched forever after its first operation; and a latched hardware trip did not keep relay B and the gate drive from being commanded closed afterwards. The reconnection window was also wider than the trip window; it is now the narrower window of RM-08. Three
@invariantscenarios (first loss, second loss after a full cycle, dead grid at power-up) now run under every fault set. - A genuine timing defect in the tool: see finding 1 below.
Tool findings from building the model¶
Building this model exposed a run of tool problems. Each row below became an issue (#310–#344) and was fixed in the tool, and the model was then changed to use the fixes:
| Finding | Issue | Fix, and what the model now does |
|---|---|---|
Virtual time in binary floating point: 99 ms + 1 ms at 300 s missed a 100 ms timer | #310 | Time is kept on a 1 ns grid; the scenarios use the exact split again |
| State machines could not read feature parameters, so the US and India machines were two hand-synced copies | #311 | {{Features::GridProfile.…}} in guards, assignments and durations, run with --config; one monitor, one supervisor, one chain |
A platform element satisfying a region-specific requirement raised W019 in the other region | #312 | A satisfies: of a requirement the product lacks is not an escape; the 13 per-feature "realisation" elements are gone |
| FMEA rows could not be variant-gated; fault values could not follow the region | #313 | appliesWhen: on a row; placeholders in injection: |
Test plans leaked into other products' projections, and selection: swept in inactive test cases | #314, #324 | A plan follows its bound configurations; the hand-written plan appliesWhen: is gone |
| Mutation reported equivalent mutants (swapping transitions with disjoint guards) as survivors | #315 (a) | Not generated; case (b), literal shifts on a stepped variable, stays open |
inject --max-order printed "too many cut sets" when it only pruned by order | #316 | Says higher-order cut sets were left out |
Configuration ids had to end in a number (CONF-GTI-US-M3 was E200) | #327 | CONF-* needs no numeric suffix, like FEAT-* |
Behaviour parts and architecture parts had no declared link, so a TestCase listed REQ-GTI-SYS-037 and REQ-GTI-HW-002 as verified although the executable chain models neither | #330 | Every Behavior::Parts::* part declares models: with portMap: and abstracts: (the two sensor instances map the two sensing chains); the power stage and relay parts name those two requirements in abstracts:, so listing them again is W992 |
| Architecture ports and machine ports were declared twice with no shared definition of the events they carry | #331 | Interfaces/ holds the events (GridSample, GridGood, GridLost, Close, Shutdown, Enable, Trip, Rearm) as items of five PortDefs typing both sides; a machine sending an event its port does not carry is E932, and only the two ambiguous portMap: entries remain |
| The protection chain mixed the test set-up with the product, and the supervisor existed twice (an architecture element and a behaviour part modelling it one-to-one) | #332 | The grid source is role: environment, so it is no evidence and has no architecture counterpart; System::Software::Supervisor carries the supervisor machine itself and is used directly in ProtectionChain, and SupervisorPart is gone. The relays, power stage, sensors, monitor and hardware trip keep models:, because their granularity or fidelity differs (two relays inside AcOutput, no 10 µs overcurrent trip, two sensing chains in one Sensing) |
| The traceability matrix ticked a requirement whether a scenario ran or a bench test was described, and every protection scenario counted for every requirement its TestCase listed | #333, #344 | requirement-coverage grades each requirement by what runs (13 of the 63 applicable requirements (20.6%) of the US M3 product are executable, REQ-GTI-SYS-037 descriptive-only) and exec-coverage shows which of the 23 software and hardware elements are modelled (7); each protection scenario carries @verifies for the requirements it is evidence for |
| The internal block diagram drew the DC and AC power path, the gate commands, the hardware trips and the sensing lines all alike, with ports placed by direction only, so the power path zig-zagged | #335 | Every connection of System::GridTieInverter carries a flowKind: (power, command, protection, signal); the [diagram.portSides] rule puts sensing ports on the south side, so DC input, power stage and AC output line up, and GtiInternalBlockView now shows the render of GtiIbd instead of a hand drawing |
| The derived IBD stopped at the first level: the firmware floated beside the control board, optional and safety-rated parts looked like any other | #336 | GtiIbd sets depth: 2; the firmware, allocated to the STM32, is drawn inside it inside the control board with its components; SIL-rated parts are outlined with their level, the arc-fault, rapid-shutdown and string-monitor parts badged optional and dashed, the comms hardware drawn beside the MCU although the board also has a comms port, and --config CONF-GTI-IN-M2-001 drops the arc-fault and rapid-shutdown parts |
| The model had no system context: nothing said who was on the other side of the inverter's terminals, and the inverter itself had no boundary ports | #337 | Context::GtiContext holds the inverter beside five actors (role: external): the PV array, the utility grid, the owner's head-end, the installer tool and the rapid-shutdown initiator, which applies only with rapid shutdown; the inverter gains pvIn, gridOut, comms and rsdIn, bound to the parts that serve them; GtiContextBdd and GtiContextIbd are derived from it, and a boundary port left unconnected would be W996 |
| Every diagram showed the whole inverter: a reviewer of the power path or of the protection chain had to find it among the sensing and command lines, and the US and India products could only be compared side by side | #338 | GtiPowerView (include: {kinds: [power]}, laid out left to right with the power parts in the first band), GtiProtectionView (kinds: [protection], style safety widening the trip lines) and GtiSoftwareView (domains: [software], style isolate leaving the hardware out) fade or hide what they are not about. diagram export Diagrams::GtiIbd --config CONF-GTI-US-M3-001 --config CONF-GTI-IN-M2-001 draws both products in one diagram, marking the arc-fault and rapid-shutdown parts as only the US one's |
| A diagram exported from the model was committed once and then drifted: nothing noticed when an edit changed what it should draw, and two machines with different fonts exported different sizes | #339 | generated/Diagrams/ holds the SVG render of every derived diagram, written by syscribe -m model_gti diagram export --all; CI runs it with --check, which fails naming the file. Text is measured with metrics compiled into syscribe, so the files are the same on every machine. GtiInternalBlockView points at generated/Diagrams/GtiIbd.svg instead of keeping its own copy |
| A state machine could not model how the grid answers a perturbation, so the anti-islanding check was only text and the sensing common cause FTE-GTI-009 stayed a single cut set; the invariants never saw an island whose voltage stays in the window | #340 | Behavior::Plants::GridImpedance is an in-process PlantDef (the line voltage's first-order answer to an injected current, connected, weak or islanded) and perturb runs the check of REQ-GTI-SW-008 against it through the software sensing chain. In the tree FTE-GTI-009 is no longer a cut set alone; with the check's failure (FTE-GTI-010) it is a cut set of order 2 (the campaign still defeats it alone since #342, see Open decisions), and every minimal cut set up to order 3 is defeated in both regions. TC-GTI-SAF-009 runs: a balanced island, both chains blind, a weak grid, and the monitor and hardware trip both dead |
| A campaign's result lived only in the terminal: nothing recorded which fault sets defeated an invariant, nothing said what was decided about them, and a new defeat looked like an old one | #341 | model_gti/.syscribe/campaigns.json holds the US and India campaigns (inject … --record --config CONF-GTI-US-M3-001, and CONF-GTI-IN-M3-001); Safety/ResidualRisk/ holds one proposed ResidualRisk per defeated set (RISK-GTI-001 … RISK-GTI-010: four of order 2, six of order 3, every one a multiple-point fault beyond SG-GTI-001's single-fault tolerance), each naming the requirements that address it. validate --config CONF-GTI-US-M3-001 is clean; remove a decision and it is W940. safety-case --config … hangs the campaign and its decisions under SG-GTI-001. A change to the protection chain makes the records stale (W944): re-run the two --record commands |
| The invariants stated the hazard ("not pwm on and both relays closed") instead of the safe state, because a welded relay makes "pwm off and both relays open" impossible, and checked it once, at the end of the scenario | #342 | TC-GTI-PROT-US-001/-IN-001 name the safe state of SG-GTI-001 once with Where, give its degraded form for each fault that makes part of it impossible (a welded relay, the gate drive stuck on, and a software fault, after which the hardware trip leaves gates off and relay B open) and for their combinations in the cut sets, and check it with within 2 s (reached and kept for 10 s) and always. Of the 30 sets, 5 survive with the full safe state, 14 only degraded, and 11 are defeated: the ten cut sets of #341 and, newly, FTE-GTI-009 alone. Checked at every instant, a dead grid at power-up is energised for 1.1 s under that common cause, from the end of the reconnect delay until the perturbation check, which needs the bridge switching, trips; the end-of-scenario check had missed it. RISK-GTI-011 records it as a proposed decision |
metrics said nothing about SG-GTI-001 (no event declares diagnostic coverage), the fault tree's 1.4e-1 over 15 years was never questioned, and nothing compared the tree with the campaign | #343 | metrics now judges SG-GTI-001 on a rate-only PFH of 1.09e-6 /h against the SIL 2 default of 1e-6 and reports it not credible: FTE-GTI-004, -005 and -010 fail with probability 0.48 over the mission, so the figure is no longer a rate; its largest contributor is FTE-GTI-005 (Fussell-Vesely 0.57), while FTE-GTI-009 has the highest Birnbaum importance (0.59) but contributes little. Every rate of FT-GTI-001 now says rateStatus: unverified with its source. inject TC-GTI-PROT-US-001 --ft FT-GTI-001 --max-order 3 --config CONF-GTI-US-M3-001 --consistency confirms all ten cut sets up to order 3, lists the tree's two order-4 cut sets as not run (above the campaign's order), and finds 19 defeating sets the tree does not have; 88 combinations cannot be judged for want of an Except under clause (see Open decisions) |
Not changed in the tool:
- Waveforms are not modelled: the grid impedance plant gives the voltage's answer to the inverter's current, nothing more. The invariant scenarios still model grid loss as a sample with zero voltage; the balanced island with the voltage in the window is exercised by
TC-GTI-SAF-009.
Open decisions¶
- Residual risk. The eleven decisions in
Safety/ResidualRisk/are proposed, not accepted: accepting one needsapprovedBy:from the compliance engineer, who weighs it with the fault tree's failure rates (illustrative and unverified). - Fault tree versus the invariants. The consistency search (#343) finds defeating sets that contain no minimal cut set of FT-GTI-001: FTE-GTI-009 alone, and pairs such as FTE-GTI-006 + FTE-GTI-007 or FTE-GTI-007 + FTE-GTI-008. They defeat the dead-grid-at-power-up invariant, which is stricter than the tree's top event (energised beyond the 2 s island-clearing time): the perturbation check needs the bridge switching, so a blinded monitor lets the inverter run for 1.1 s first. Either the tree gains that top event or the invariant is relaxed to the tree's; the safety engineer decides. The software FMEA rows (FM-GTI-001 … FM-GTI-011) carry no
ftaRef, so the search counts their defeating pairs as outside the tree too; mapping them to events would close that gap. 88 combinations cannot be judged because noExcept underclause covers them. - Failure rates. Every rate of FT-GTI-001 is an unverified proposal, and several fail with probability 0.48 over 15 years, so the verdict of SG-GTI-001 is not credible rather than pass or fail. Real rates (with
rateSourceandrateStatus: verified) are needed before the figure means anything. - Sensing common cause. The perturbation-response check (
REQ-GTI-SW-008, run against the grid impedance plant since #340) turns FTE-GTI-009 into a cut set of order 2 with the check's own failure (FTE-GTI-010). Its thresholds (0.1 Ω and 5 Ω around a nominal 0.4 Ω, a 0.2 A injection) and the plant's values are illustrative and unverified; the choice of measure is for the safety engineer to confirm. The current sensing it needs (REQ-GTI-HW-010) is not modelled and is verified on the bench (TC-GTI-SAF-010). - DC arc hazard in India. With arc-fault protection optional there, safety goal
SG-GTI-002has no requirement in an Indian product without it (W805). The model gates the goal with the feature; the safety engineer must decide how such a product covers the hazard (installation rules, conductor and connector selection).