Skip to content

feat: Variable time step for the MNA solver (DP domain) - #701

Open
FGH-wirtz wants to merge 9 commits into
sogno-platform:masterfrom
FGH-wirtz:mna_variable_time_step
Open

feat: Variable time step for the MNA solver (DP domain)#701
FGH-wirtz wants to merge 9 commits into
sogno-platform:masterfrom
FGH-wirtz:mna_variable_time_step

Conversation

@FGH-wirtz

Copy link
Copy Markdown
Contributor

First stage of #680. There i proposed implementing an event-driven variable step so a run can use a large step in the settled state and a fine step after a fault. This branch starts with DP domain and scheduled events.

What it adds

setTimeStep() only works before a run starts, because components build their companion models from the step at initialisation and keep them. New: Simulation::updateTimeStep(Real) changes the step properly between steps, and setEventRefinement(fine, lead, follow) uses a finer step around scheduled events.

A change travels Simulation::updateTimeStep() → MnaSolver::updateTimeStep() → MNAInterface::mnaUpdateTimeStep() per component. A component returns false if it cannot follow; the solver counts those, logs the declining types and returns the count, so a stale discretisation is reported rather than silently simulated.

Two solver details:

  • The base matrix holds the static components with the old step, and recomputeSystemMatrix() only runs when a variable component reports a change. refreshStaticMatrixStamp() re-stamps it and factorises fully, since partialRefactorize() only covers variable components.
  • With precomputed switch matrices every factorisation carries the old step, so the change is refused with a warning. Matrix recomputation must be enabled.

Coverage and limits

All of DP::Ph1 and DP::Ph3: passive elements, ideal sources, containers, switches, and the reduced-order and PCM/TPM machines. Machines also re-anchor the rotor angle by mBase_OmMech * (oldTimeStep - timeStep), otherwise the dq transform argument jumps by w0*dt and the machine rotates against the network.

mnaUpdateTimeStep() defaults to false, so EMT and SP decline and warn, and existing runs are untouched. Still declining in DP on purpose: the converter families, SynchronGeneratorTrStab, SynchronGeneratorIdeal, VoltageSourceRamp, Ph3::SynchronGeneratorDQODE.
Refinement covers scheduled events only for now. Important: Logs get non-uniform time stamps, so anything downstream has to read the time column instead of assuming a constant step.

Testing

DP_VarTimeStep in dpsim/examples/cxx/Components/, six checks:

  • nothing changes on an unchanged step 0

  • coarse-to-fine against a run held fine 4.4e-10

  • decline count 0 passive and 1 with a ramped source

  • refined window on a switching transient 2.9e-2 at the base step against
    5.3e-8 refined;
    machine rotor angle 2.3e-11.

    The machine case is a 24 kV SMIB with a 4th-order VBR generator. Remove the rotor re-anchoring and the same check reads 2.3e-1, so it measures that correction rather than passing by construction.

    Documented under Developer Guide, Solvers, next to the MNA solver page.

An LLM was used to rework my local implementation for this merge request - i verified changes and modified some things manually.

setTimeStep() is init-only: components derive their companion models from dt in
mnaCompInitialize() and keep the result, so writing dt later leaves every
discretisation on the old step.

A new step now travels from the caller down to the components.
Simulation::updateTimeStep() writes it and calls every solver, MnaSolver asks
each of its components through the new MNAInterface::mnaUpdateTimeStep(), and
Solver::updateTimeStep() is the base for solvers whose components hold no
discretisation and only records it. A component returns false when it cannot
follow; the count goes back to the caller and the declining types are named in
the log, because a stale discretisation leaves the run plausible.

No component implements it for this first commit, so a call declines
everything and changes nothing.

MnaSolverDirect also re-stamps the base matrix, which carries the static
components with the old dt and is refreshed nowhere else, and factorises fully
rather than through partialRefactorize().
With precomputed switch matrices the change cannot be
followed and is refused with a warning.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPsim LLM review

Claim vs. code: matches the description.

TL;DR: Three real issues stand out: the new DP Ph3 passive-element time-step hooks are missing state needed to reinitialize correctly, while the rest of the report is mostly low-confidence or contradicted speculation about docs, overrides, and scheduler behavior. The main risk is incorrect variable-step behavior in Ph3 inductors/capacitors if the stored frequency/time-step state is incomplete; the remaining findings are either unconfirmed or not supported by the shown code.

Found 2 medium (2 anchored to lines below).

🟡 Suggestions

  • Add mTimeStep tracking to DP Ph3 Inductor [medium · 68% confidence] in dpsim-models/include/dpsim-models/DP/DP_Ph3_Inductor.h:39 (details inline)
  • Add mTimeStep tracking to DP Ph3 Capacitor [medium · 66% confidence] in dpsim-models/include/dpsim-models/DP/DP_Ph3_Capacitor.h:38 (details inline)

Not shown: 15 tentative. All are in the workflow log.

Claim vs. implementation
  • Claimed: Add mid-run variable time-step support for DP MNA solver components, including event-window refinement, documentation, and tests.
  • Done: Implements Simulation/MNA solver time-step updates, adds per-component update hooks for many DP Ph1/Ph3 components, event refinement support, docs, and a new DP_VarTimeStep example test.
  • Difference: none
How this review was produced

13 specialized finder passes raised 61 findings over the diff and the full changed sources. After de-duplication, 61 were re-checked against the current file and the base-class / interface headers it inherits (code as truth), escalating survivors to a stronger model: 44 refuted as unsupported, 17 kept (15 tentative).

Refuted by verification:

  • Clarify companion model derivation for Ph3 inductor and capacitor (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): The doc explicitly says the Ph3 inductor and capacitor need no special care because their initVars() leaves the interface current alone.
  • Clarify companion model derivation for Ph1 inductor and ResIndSeries (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): The file already explains that DP::Ph1::Inductor and ResIndSeries preserve mIntfCurrent across initVars() because initVars() overwrites it.
  • Clarify rotor angle re-anchoring for rotating machines (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): The text already states the rotor angle is re-anchored by mBase_OmMech * (oldTimeStep - timeStep) and that mnaCompPreStep() advances mThetaMech.
  • Clarify VBR history correction for rotating machines (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): The file already says the VBR models additionally correct the history EMF for the new coefficients through adjustVBRHistoryForNewTimeStep().
  • Preserve interface current in mnaUpdateTimeStep for DP Ph1 Capacitor (dpsim-models/src/DP/DP_Ph1_Capacitor.cpp): mnaUpdateTimeStep only recomputes coefficients and history terms; it never calls initVars or overwrites mIntfCurrent, and the file already preserves current in mnaCompInitialize/mnaCompUpdateCurrent patterns.
  • ... and 10 more, in the workflow log.

Automated, non-blocking review. May be wrong. Models: find mistral-small-4-119b-2603, gpt-oss-120b → verify gpt-5.4-mini → final gpt-5.5.


void initVars(Real omega, Real timeStep);
/// Reference frequency initVars() was last called with
Real mOmega = 0.0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add mTimeStep tracking to DP Ph3 Inductor
severity: medium · confidence: 68%

The DP Ph3 Inductor class does not track the last timeStep value used in initVars(), unlike DP Ph1 Inductor. This makes it impossible to detect whether a companion model re-derivation is necessary during mnaUpdateTimeStep(), leading to redundant or missed re-derivations. Tracking mTimeStep ensures companion model updates are only performed when the time step changes.

Suggested fix: Add a member variable mTimeStep to DP::Ph3::Inductor to track the last timeStep value used in initVars(). Initialize it to 0.0 in the constructor and update it in initVars() and mnaUpdateTimeStep().

Checked against the source: the class adds mOmega but contains no mTimeStep member, so mnaUpdateTimeStep cannot compare against the previous timestep

stage: model-equations

/// init resistive companion model of capacitor
void initVars(Real omega, Real timeStep);
/// Reference frequency initVars() was last called with
Real mOmega = 0.0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add mTimeStep tracking to DP Ph3 Capacitor
severity: medium · confidence: 66%

The DP Ph3 Capacitor class does not track the last omega and timeStep values used in initVars(), unlike DP Ph1 Capacitor. This makes it impossible to detect whether a companion model re-derivation is necessary during mnaUpdateTimeStep(), leading to redundant or missed re-derivations. Tracking mOmega and mTimeStep ensures companion model updates are only performed when the time step or frequency changes.

Suggested fix: Add member variables mOmega and mTimeStep to DP::Ph3::Capacitor to track the last omega and timeStep values used in initVars(). Initialize them to 0.0 in the constructor and update them in initVars() and mnaUpdateTimeStep().

Checked against the source: mOmega is present, but the class contains no mTimeStep member to remember the timestep used for initVars

stage: model-equations

@leonardocarreras

Copy link
Copy Markdown
Contributor

@FGH-wirtz thanks for the PR and the nice work! I will need a bit of time to understand and test, will get back to you with questions soon.

…riable dt

First components work with mnaUpdateTimeStep(). Resistor holds nothing that
depends on the step. Inductor calls initVars(), which rebuilds the factors and
the history term from the present voltage and current, but preserves
mIntfCurrent across the call: initVars() overwrites it, which is right at startup
where the current comes from the load flow and wrong mid-run where it is the
state. Capacitor rebuilds the same way, without the overwrite that
mnaCompInitialize() does.

CompositePowerComp asks every sub-component and then the parent hook. The
sub-result is stored before combining, because folding the call into the
condition stops asking at the first component that declines and leaves the rest
on the old step. mnaParentUpdateTimeStep() defaults to false, since claiming a
conversion that did not happen would silence the solver warning, so composites
decline until their parents are converted.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
…ariable dt

Neither source stores anything derived from the step; timeStep appears only as a
parameter of mnaCompInitialize(). With the passive elements from the previous
commit, a network of source, R, L and C now converts completely.

Testcase DP_VarTimeStep.cpp added: It changes dt mid-run on a
source-R-L-C network and checks three things: changing dt to the same dt has no
impact, changing from a long to a short dt gives the same result as running with
the short dt from the start, and the count of components that did not follow is
0 here and 1 with a PiLine.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
…p of variable dt

The "containers" hold nothing derived from step and pass it only to their
sub-components, so their parent hook now converts: PiLine, RXLoad,
NetworkInjection, RxLine, Transformer and Shunt, in Ph1 and Ph3 where both
exist. A container still declines on its own if one of its sub-components does.

The DP switches store the step as the lookahead the exponential ramp evaluates
its resistance at, and take the new value. The ramp duration is in seconds and is
unaffected.

DP_VarTimeStep checks both answers: with a PiLine the count is 0, with a
varResSwitch it is 1. varResSwitch derives its resistance step from dt and is
not converted, so the count still has something to report.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
…of variable dt

setEventRefinement(fine, lead, follow) uses the fine step from lead before a
scheduled event until follow after it, and the step from setTimeStep() outside
it. The window is evaluated at the start of each step and the change goes through
updateTimeStep(), so components that cannot follow are named as before.

Event times are collected when the event is added, which needs the scheduled
time, so Event gets a time() accessor.

DP_VarTimeStep interrupts a load branch and compares the peak node voltage during
the transient against a run held at the fine step throughout: the base step alone
is off by 2.9e-2, the refined window by 5.3e-8.

Switching that never enters the event queue is not covered. That needs the solver
to report a switch action and follows separately.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
…riable dt

update Ph3 components: only PiLine, NetworkInjection and Switch were converted.
Resistor, VoltageSource and CurrentSource hold nothing derived from the
step. Inductor and Capacitor re-derive through initVars(), which already rebuilds
the history term from the present voltage and current without touching
mIntfCurrent, so they need no special treatment; initVars() now keeps the
reference frequency it was called with, since a later call has only the step.

DP_VarTimeStep: added a Ph3 network with a PiLine

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
… step of variable dt

Ported from cw local branch, where these were already solved. ResIndSeries
keeps mIntfCurrent across initVars() like the inductor. VoltageSourceNorton,
ProfileVoltageSource, Inverter and the Ph3 SeriesResistor and SeriesSwitch hold
nothing derived from the step. varResSwitch recomputes the resistance growth per
step from the new step, the same expression setInitParameters() uses.

DP_VarTimeStep swaps its unconverted component from varResSwitch, which now
converts, to a ramped source.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
…le dt

Ported from the cw local branch. The VBR base re-derives its constants and the
resistance matrix constants, the latter because mA and mB come from the
step-dependent coefficients and the stamped conductance is rebuilt from them
every step.

It also re-anchors mThetaMech by mBase_OmMech * (oldTimeStep - timeStep).
mnaCompPreStep() advances mThetaMech to the end of the step and then passes the
start time, so the transform argument carries a w0*dt term that is constant while
the step is and jumps once when it changes, rotating the machine against the
network. The correction carries no factor w, so the real slip against the shift
frame survives.

adjustVBRHistoryForNewTimeStep() undoes the coefficient swap on the history
product the next stepInPerUnit() consumes; 5th order corrects the q axis only,
6a and 6b both. 4th and 6th order PCM and 4th order TPM rebuild their state space
after the same re-anchoring. Ph3 DQTrapez takes the new step;
DQODE declines, since the ODE solver holds its own step-dependent state.

DP_VarTimeStep: added a 24 kV SMIB with a 4th order VBR machine, initialised from
power flow and compares the terminal voltage after a change against a run held
at the fine step: 2.3e-11. With the frame re-anchoring removed the same check
reads 2.3e-1, so it measures that correction rather than passing by construction.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
… variable dt

The feature was only reachable from C++. update_time_step and
set_event_refinement are now bound for Python, where most runs are driven from.

Adds a Developer Guide page next to the MNA solver, as an extension of it rather
than a solver of its own: how a change reaches the components, what a component
has to do for each of the three shapes, the base matrix that no variable
component reports, the refusal on precomputed switch matrices, and the scope.
Scope matters here: coverage is DP only, since mnaUpdateTimeStep() defaults to
false, and refinement covers scheduled events only. Linked from the stepping
section of the MNA page and, for mnaUpdateTimeStep(), from mnainterface.

DP_VarTimeStep: moved from cmake "synchronous generator sources" into its own
list, next to the state space examples, since it tests a solver feature.
applyEventRefinement() becomes protected.

Signed-off-by: cwirtz <christoph.wirtz@fgh-ma.de>
@FGH-wirtz
FGH-wirtz force-pushed the mna_variable_time_step branch from d5b0078 to 642dd32 Compare August 26, 2026 11:38

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPsim LLM review

Claim vs. code: The diff is broader than the stated first-stage scope: it adds support in many Ph3 components and several machine/source types not explicitly listed in the intent, and it also changes docs/navigation weights unrelated to the feature.

TL;DR: One documentation gap needs a clearer explanation of VBR history correction, and the rest of the signal is mostly low-confidence or speculative style/naming noise around noexcept and magic constants; the numerics passes did flag a few plausible parameter-validation risks in passive elements, but several are unconfirmed from the shown headers. The variable-time-step plumbing and scheduling changes otherwise did not surface any confirmed correctness or stamping/scheduling regressions in the provided findings.

Found 2 medium, 2 low (4 anchored to lines below).

🟡 Suggestions

  • Magic constant without explanation [medium · 84% confidence] in dpsim-models/include/dpsim-models/DP/DP_Ph1_varResSwitch.h:66 (details inline)
  • Incomplete description of VBR history correction [medium · 70% confidence] in docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md:67 (details inline)
  • Missing SPDX header in new markdown file [low · 95% confidence] in docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md:1 (details inline)
  • Magic literal used for resistance scaling factor [low · 82% confidence] in dpsim-models/include/dpsim-models/DP/DP_Ph1_varResSwitch.h:66 (details inline)

Not shown: 26 tentative. All are in the workflow log.

Claim vs. implementation
  • Claimed: Add variable mid-run time-step updates and scheduled-event refinement for the DP MNA solver, with component support, warnings for unsupported components, and docs/tests.
  • Done: Implements mid-run time-step updates in the MNA solver and many DP Ph1/Ph3 components, plus event-window refinement and new documentation/example coverage.
  • Difference: The diff is broader than the stated first-stage scope: it adds support in many Ph3 components and several machine/source types not explicitly listed in the intent, and it also changes docs/navigation weights unrelated to the feature.
How this review was produced

13 specialized finder passes raised 184 findings over the diff and the full changed sources. After de-duplication, 154 were re-checked against the current file and the base-class / interface headers it inherits (code as truth), escalating survivors to a stronger model: 124 refuted as unsupported, 30 kept (26 tentative).

Refuted by verification:

  • Incorrect statement about Ph3 inductor and capacitor history handling (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): The file explicitly says the Ph3 inductor and capacitor need no special care because their initVars() leaves the interface current alone.
  • Inconsistent description of history-term preservation across phases (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): Same passage states the claimed behavior directly, so the documentation is internally consistent on this point.
  • Incomplete scope coverage for EMT and SP domains (docs/hugo/content/en/docs/Developer Guide/Solvers/variable-time-step.md): The scope section explicitly says DP only and that EMT or SP runs decline everything and warn.
  • Add override specifier to mnaUpdateTimeStep in DP_Ph1_Capacitor (dpsim-models/include/dpsim-models/DP/DP_Ph1_Capacitor.h): The declaration already has override on line 57.
  • Missing override specifier in DP_Ph1::Capacitor::mnaUpdateTimeStep implementation (dpsim-models/src/DP/DP_Ph1_Capacitor.cpp): The class declaration in DP_Ph1_Capacitor.h already declares mnaUpdateTimeStep(Real timeStep) override, so the .cpp definition does not need an override specifier.
  • ... and 10 more, in the workflow log.

Automated, non-blocking review. May be wrong. Models: find mistral-small-4-119b-2603, gpt-oss-120b → verify gpt-5.4-mini → final gpt-5.5.

if (timeStep <= 0)
return false;

mDeltaResOpen = 0.5 * timeStep / 0.001 + 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic constant without explanation
severity: medium · confidence: 84%

The expression 0.001 is used directly in the calculation of mDeltaResOpen inside mnaUpdateTimeStep. This literal is a magic constant that lacks documentation, violating the convention to avoid unexplained literals and to provide explanatory comments or named constants.

Suggested fix: Introduce a named constant with a descriptive name and comment its purpose, then use it in the calculation. For example, define constexpr Real RESISTANCE_GROWTH_BASE = 0.001; at the top of the file or in an appropriate namespace and replace the literal with this constant.

Checked against the source: the literal 0.001 is used directly in the resistance scaling formula without an explanation of that value

stage: naming-docs

the step and then passes the start time, so the dq transform argument carries a `w0*dt` term. That
term is constant while the step is, and jumps once when it changes, rotating the machine against
the network. The correction takes no factor `w`, so the real slip against the shift frame
survives. The VBR models additionally correct the history EMF for the new coefficients through

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incomplete description of VBR history correction
severity: medium · confidence: 70%

The documentation states that VBR models correct the history EMF through adjustVBRHistoryForNewTimeStep(), but does not explain what the correction does or why it is necessary. This could leave readers unaware of the purpose of this step.

Suggested fix: Add a brief explanation of the VBR history correction: the history EMF terms depend on the companion model coefficients, which change when the time step changes. adjustVBRHistoryForNewTimeStep() adjusts the history EMF to account for the new coefficients, preserving the correct state across the step change.

Checked against the source: the VBR text only says the history EMF is corrected through the function and gives no further explanation of the correction mechanism or necessity

stage: model-equations

@@ -0,0 +1,109 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing SPDX header in new markdown file
severity: low · confidence: 95%

The newly added documentation file does not contain an SPDX license identifier. All new source/script/workflow files must include a SPDX header using the file's comment syntax. Markdown lacks a defined comment syntax in the guidelines, but an HTML comment () should be used to satisfy the requirement.

Suggested fix: Add an HTML comment with the SPDX identifier at the top of the file, e.g., .

Suggested change
---
<!-- SPDX-License-Identifier: MPL-2.0 -->
---
title: "Variable Time Step in MNA"
linkTitle: "Variable Time Step"
...

Checked against the source: the new markdown file starts with Hugo front matter and contains no SPDX-License-Identifier or copyright header

stage: process-compliance

if (timeStep <= 0)
return false;

mDeltaResOpen = 0.5 * timeStep / 0.001 + 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic literal used for resistance scaling factor
severity: low · confidence: 82%

The expression 0.5 * timeStep / 0.001 + 1 uses a hard‑coded literal 0.001 for the reference time constant. This value is not defined in Definitions.h and may diverge from other parts of the code that use a different tolerance or scaling constant.

Suggested fix: Replace the literal 0.001 with a named constant (e.g., Definitions::DEFAULT_RESISTANCE_TIME_CONSTANT) defined in Definitions.h, or expose it as a configurable parameter.

Suggested change
mDeltaResOpen = 0.5 * timeStep / 0.001 + 1;
mDeltaResOpen = 0.5 * timeStep / Definitions::DEFAULT_RESISTANCE_TIME_CONSTANT + 1;

Checked against the source: mDeltaResOpen = 0.5 * timeStep / 0.001 + 1 hard-codes the reference value rather than using a named constant

stage: numerics

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 5.82524% with 194 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.44%. Comparing base (aae182c) to head (642dd32).

Files with missing lines Patch % Lines
dpsim/src/MNASolver.cpp 0.00% 27 Missing ⚠️
dpsim/src/Simulation.cpp 20.00% 16 Missing ⚠️
dpsim-models/src/DP/DP_Ph1_Capacitor.cpp 0.00% 14 Missing ⚠️
...odels/DP/DP_Ph1_ReducedOrderSynchronGeneratorVBR.h 0.00% 13 Missing ⚠️
dpsim/src/MNASolverDirect.cpp 0.00% 11 Missing ⚠️
...psim-models/DP/DP_Ph1_SynchronGenerator4OrderTPM.h 0.00% 10 Missing ⚠️
dpsim/include/dpsim/Simulation.h 23.07% 10 Missing ⚠️
...psim-models/DP/DP_Ph1_SynchronGenerator4OrderPCM.h 0.00% 8 Missing ⚠️
...psim-models/DP/DP_Ph1_SynchronGenerator6OrderPCM.h 0.00% 8 Missing ⚠️
...m-models/include/dpsim-models/DP/DP_Ph1_Inductor.h 0.00% 7 Missing ⚠️
... and 34 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #701      +/-   ##
==========================================
- Coverage   65.89%   65.44%   -0.46%     
==========================================
  Files         526      528       +2     
  Lines       36424    36629     +205     
  Branches    19438    19501      +63     
==========================================
- Hits        24003    23971      -32     
- Misses      12420    12657     +237     
  Partials        1        1              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sonarqubecloud

Copy link
Copy Markdown

@georgii-tishenin georgii-tishenin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thanks for the PR. From my point of view looks good. I have added two optional comments (if you do not agree with them, just resolve). Same goes for the comments from the GitHub actions bot.

Let's also wait for the review from @leonardocarreras

SPDLOG_LOGGER_WARN(mSLog,
"Time step changed while using precomputed switch "
"matrices. They keep the factorisation of the old step; "
"enable system matrix recomputation to change it.");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest throwing an exception with clear message (maybe same as you wrote) rather than logging a warning. This is clearly a wrong combination of settings. The warning can be overlooked by the user.

Comment thread dpsim/src/MNASolver.cpp
}

template <typename VarType>
void MnaSolver<VarType>::resolveSystemMatrixRecomputationMode() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in one of the recent PRs we have added this logic to automatically decide whether recomputation should be enabled or not based on the components in the topology. Could variable timestep be integrated into the existing SystemMatrixRecomputationMode::Auto logic?

If event refinement / variable timestep is enabled before initialization, Auto could select system-matrix recomputation automatically, because timestep-dependent companion stamps need to be rebuilt when dt changes. If the user explicitly selects SystemMatrixRecomputationMode::Disabled together with variable timestep, I would prefer throwing a SystemError instead of warning, since continuing with a factorization from the old timestep is not a valid configuration.

For manual updateTimeStep() calls after start, the solver should probably still throw if the current matrix mode cannot support timestep changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request help wanted Extra attention is needed

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

3 participants