Add MosfetModel class with lambda (channel-length modulation)#313
Open
esaruoho wants to merge 4 commits intopfalstad:devfrom
Open
Add MosfetModel class with lambda (channel-length modulation)#313esaruoho wants to merge 4 commits intopfalstad:devfrom
esaruoho wants to merge 4 commits intopfalstad:devfrom
Conversation
Owner
|
If you load an existing circuit with a MOSFET (example: Circuits->MOSFETs->n-MOSFET) and right click the MOSFET you get an exception. If you check and then uncheck "Simulate Body Diode" you get the edit model dialog...? I assume you have another PR coming soon with Cgs/Cgd support so I'd probably wait for that... Otherwise remove Cgs/Cgd from the model details. |
Author
|
Fixed both bugs and added Cgs/Cgd companion model simulation in the latest push: Bug fixes:
Cgs/Cgd support:
The saturable inductor (dL/dt) is already up as PR #308. |
087c701 to
3aefa29
Compare
esaruoho
added a commit
to esaruoho/circuitjs1
that referenced
this pull request
Apr 15, 2026
…nstant model Replaces the draw-call-counter scope fade with a wall-clock-based exponential decay. The user setting now means a literal trail persistence in milliseconds, not an opaque alpha number. Per @pfalstad on PR pfalstad#240: - "vary alpha instead of the number of draw calls between fade outs" - "should look the same regardless of the simulation speed setting" - "It still seems too persistent even at the lowest setting" Implementation: alpha = 1 - exp(-elapsed_ms / trailPersistence) This is the analytic solution for an exponential decay with time constant `trailPersistence`. Same fade rate at 30fps or 144fps, because elapsed wall-clock time appears in the exponent. The user sees and sets the time constant directly (default 200 ms). Range 0..2000 ms. Setting trailPersistence = 0 maps to alpha = 1 (instant erase, no trail at all) so "lowest setting" really is no trail, addressing the "still too persistent" complaint. Persisted per-scope as XML attribute "tp"; omitted when at the default to keep file size small. The MOSFET lambda part of the original PR pfalstad#240 has been superseded by PR pfalstad#313 (MosfetModel class), so this PR is now scope-fade-only. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 tasks
esaruoho
added a commit
to esaruoho/circuitjs1
that referenced
this pull request
Apr 15, 2026
…nstant model Replaces the draw-call-counter scope fade with a wall-clock-based exponential decay. The user setting now means a literal trail persistence in milliseconds, not an opaque alpha number. Per @pfalstad on PR pfalstad#240: - "vary alpha instead of the number of draw calls between fade outs" - "should look the same regardless of the simulation speed setting" - "It still seems too persistent even at the lowest setting" Implementation: alpha = 1 - exp(-elapsed_ms / trailPersistence) This is the analytic solution for an exponential decay with time constant `trailPersistence`. Same fade rate at 30fps or 144fps, because elapsed wall-clock time appears in the exponent. The user sees and sets the time constant directly (default 200 ms). Range 0..2000 ms. Setting trailPersistence = 0 maps to alpha = 1 (instant erase, no trail at all) so "lowest setting" really is no trail, addressing the "still too persistent" complaint. Persisted per-scope as XML attribute "tp"; omitted when at the default to keep file size small. The MOSFET lambda part of the original PR pfalstad#240 has been superseded by PR pfalstad#313 (MosfetModel class), so this PR is now scope-fade-only. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduces named, reusable MOSFET models following the DiodeModel/ TransistorModel pattern. Models store threshold voltage (Vt), beta, lambda (channel-length modulation), and gate capacitance fields (Cgs/Cgd, for future use). Key changes: - MosfetModel.java: new model class with HashMap registry, text/XML serialization (type 36, tag "mm"), edit dialog support - EditMosfetModelDialog.java: model editor dialog - MosfetElm.java: model reference with FLAG_MODEL backward compat, model selector in edit dialog, lambda in saturation calculation (ids = 0.5*beta*(Vgs-Vt)^2*(1+lambda*Vds)) - JfetElm.java: needsModel() returns false (JFETs unaffected) - Registration in CircuitLoader, XMLDeserializer, CirSim, CommandManager, SimulationManager Old circuits without FLAG_MODEL load vt/beta inline as before. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bug fixes: - Old circuits without FLAG_MODEL now get default model assigned (matching TransistorElm pattern), preventing NPE on right-click - Body diode toggle no longer causes dialog issues with null model Gate capacitance (Cgs/Cgd) simulation: - Trapezoidal companion model stamps in doStep via calculate() - startIteration() computes geq/ceq from model capGS/capGD - stepFinished() saves cap voltage/current state - Gate node stamped as nonlinear when caps are present - getConnection() returns true when caps bridge gate to S/D - Info display shows Cgs/Cgd values when enabled Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The companion model stamps correct Cgs/Cgd values into the matrix, but getCurrentIntoNode() was returning 0 for the gate node and omitting cap currents from source/drain. This caused incorrect current display (same bug pattern as DiodeElm and TransistorElm). Gate current = -(Igs + Igd), source gets +Igs, drain gets +Igd, maintaining KCL compliance across all terminals. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ids, gm, and Gds in the linear region now include the (1+lambda*Vds) factor, matching the SPICE Level 1 MOSFET model. When lambda=0 (the default), all formulas collapse to the originals with no behavior change. Linear-region lambda was informed by independent work from Jonathan Klamroth (@jonnykl) in their fork. Our version additionally includes the lambda factor in linear-region gm, which their implementation omitted. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3aefa29 to
9a24bf8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MosfetModelclass following theDiodeModel/TransistorModelpattern — named, reusable MOSFET parameter sets stored in a staticHashMapIds = 0.5*β*(Vgs-Vt)²*(1+λ*Vds), with proper gm and Gds derivativesIds = β*((Vgs-Vt)*Vds - Vds²/2)*(1+λ*Vds), with full product-rule Gds derivativeMosfetElmedit dialog shows model selector with Create/Edit buttons; old circuits withoutFLAG_MODELload inline vt/beta as before (full backward compatibility)JfetElmis unaffected — overridesneedsModel()to return false (1-line change)Changes
MosfetModel.javaEditableinterfaceEditMosfetModelDialog.javaEditTransistorModelDialogpattern)MosfetElm.javamodelName/model),FLAG_MODEL(128) for backward compat,setup(),dump()/dumpXml()/undumpXml()with model support, lambda incalculate()(both linear and saturation regions), model selector in edit dialogJfetElm.javaneedsModel()returns false (1 line)CircuitLoader.javaMosfetModel.undumpModel()XMLDeserializer.javaMosfetModel.undumpModelXml()CirSim.javamosfetModelEditDialogstatic field,MosfetModel.clearDumpedFlags()CommandManager.javaMosfetModel.clearDumpedFlags()incopyOfSelectedElms()SimulationManager.javaMosfetModel.clearDumpedFlags()ingetCircuitAsComposite()Context
This addresses Paul's feedback on PR #266 and #240: "Between this and the lambda change, I think we need mosfet models." The approach follows the established model pattern exactly —
DiodeModelfor diodes,TransistorModelfor BJTs, nowMosfetModelfor MOSFETs.The linear-region lambda improvement was informed by independent work from Jonathan Klamroth (@jonnykl), who implemented channel-length modulation in their fork. Their approach applied
(1+λ*Vds)in the linear region as well, matching SPICE Level 1. We adopted this improvement with corrected linear-region gm (including the(1+λ*Vds)factor, which their version omitted) and the Gds convergence floor preserved.Based on
v3-devbranch.Test plan
🤖 Generated with Claude Code