@@ -10,7 +10,7 @@ namespace SpiceSharpParser.CustomComponents.IdealDiodes
1010 /// <remarks>
1111 /// This helper owns only the local current law for one ideal diode cell. The
1212 /// biasing behavior that calls it handles the external branch details such as
13- /// series resistance and the parallel/series diode multipliers.
13+ /// the parallel/series diode multipliers.
1414 ///
1515 /// The current law is built from straight-line regions in slope/intercept
1616 /// form: <c>I = g * V + b</c>. The off region uses <c>Roff</c> or simulator
@@ -33,14 +33,12 @@ internal static class IdealDiodeEquation
3333 /// <param name="parameters">The effective model and instance parameters.</param>
3434 /// <param name="biasingParameters">The simulation biasing parameters, used for the default off conductance.</param>
3535 /// <param name="voltage">The local voltage across one diode cell.</param>
36- /// <param name="area">The diode area multiplier applied after the local equation is evaluated.</param>
37- /// <param name="current">The resulting local diode current, scaled by <paramref name="area" />.</param>
38- /// <param name="conductance">The resulting small-signal conductance, scaled by <paramref name="area" />.</param>
36+ /// <param name="current">The resulting local diode current.</param>
37+ /// <param name="conductance">The resulting small-signal conductance.</param>
3938 public static void Evaluate (
4039 IdealDiodeParameters parameters ,
4140 BiasingParameters biasingParameters ,
4241 double voltage ,
43- double area ,
4442 out double current ,
4543 out double conductance )
4644 {
@@ -87,8 +85,8 @@ public static void Evaluate(
8785 - reverseVoltage ) ;
8886
8987 // Evaluate the reverse-to-off knee. With revepsilon omitted or
90- // zero this is a hard switch at the intersection; otherwise it is
91- // smoothed symmetrically around the boundary.
88+ // zero this is a hard switch at the intersection; otherwise the
89+ // smoothing window extends from the boundary into reverse breakdown .
9290 EvaluateTransition (
9391 voltage ,
9492 boundary ,
@@ -97,6 +95,7 @@ public static void Evaluate(
9795 reverseIntercept ,
9896 offConductance ,
9997 0.0 ,
98+ false ,
10099 out current ,
101100 out conductance ) ;
102101 }
@@ -115,12 +114,10 @@ public static void Evaluate(
115114 onIntercept ,
116115 forwardVoltage ) ;
117116
118- // Avoid a second transition evaluation in the normal off region. For
119- // smoothed knees, begin applying the blend at the start of the epsilon
120- // band so the partial-conduction region is not missed.
121- double forwardWidth = parameters . ForwardEpsilon . Given ? parameters . ForwardEpsilon . Value : 0.0 ;
122- double forwardStart = forwardBoundary - ( Math . Max ( forwardWidth , 0.0 ) / 2.0 ) ;
123- if ( voltage > forwardBoundary || ( forwardWidth > 0.0 && voltage >= forwardStart ) )
117+ // Avoid a second transition evaluation in the off or reverse regions.
118+ // LTspice-style forward epsilon starts at the boundary and extends
119+ // into forward conduction, so voltages below the boundary remain off.
120+ if ( voltage >= forwardBoundary )
124121 {
125122 // Evaluate the off-to-forward knee using the same generic transition
126123 // helper used for reverse breakdown.
@@ -132,6 +129,7 @@ public static void Evaluate(
132129 0.0 ,
133130 onConductance ,
134131 onIntercept ,
132+ true ,
135133 out current ,
136134 out conductance ) ;
137135 }
@@ -141,10 +139,6 @@ public static void Evaluate(
141139 // derivative by the tanh derivative.
142140 ApplyCurrentLimits ( parameters , ref current , ref conductance ) ;
143141
144- // Area behaves like parallel identical cells: both DC current and
145- // small-signal conductance scale linearly.
146- current *= area ;
147- conductance *= area ;
148142 }
149143
150144 /// <summary>
@@ -183,6 +177,11 @@ private static double FindIntersection(
183177 /// <param name="leftIntercept">The intercept used below the transition.</param>
184178 /// <param name="rightSlope">The slope used above the transition.</param>
185179 /// <param name="rightIntercept">The intercept used above the transition.</param>
180+ /// <param name="smoothTowardRight">
181+ /// If <c>true</c>, the smoothing window starts at <paramref name="boundary" /> and extends toward
182+ /// larger voltages. If <c>false</c>, the window ends at <paramref name="boundary" /> and extends
183+ /// toward smaller voltages.
184+ /// </param>
186185 /// <param name="current">The evaluated current.</param>
187186 /// <param name="conductance">The evaluated conductance.</param>
188187 private static void EvaluateTransition (
@@ -193,6 +192,7 @@ private static void EvaluateTransition(
193192 double leftIntercept ,
194193 double rightSlope ,
195194 double rightIntercept ,
195+ bool smoothTowardRight ,
196196 out double current ,
197197 out double conductance )
198198 {
@@ -215,21 +215,33 @@ private static void EvaluateTransition(
215215 return ;
216216 }
217217
218- // The epsilon value is the full width of the blend, centered on the
219- // natural intersection of the two lines.
220- double start = boundary - ( width / 2.0 ) ;
221- double end = boundary + ( width / 2.0 ) ;
218+ // LTspice uses epsilon as a one-sided width, not as a centered band.
219+ // Forward smoothing starts at Vfwd and moves right into the on-region;
220+ // reverse smoothing starts in the reverse region and ends at -Vrev.
221+ double start = smoothTowardRight ? boundary : boundary - width ;
222+ double end = smoothTowardRight ? boundary + width : boundary ;
223+ double slopeDelta = rightSlope - leftSlope ;
224+
225+ // A one-sided conductance ramp shifts the fully conducting side by
226+ // half the slope change times the epsilon width. This keeps current
227+ // continuous where the ramp meets the straight-line region.
228+ double lowVoltageIntercept = smoothTowardRight
229+ ? leftIntercept
230+ : leftIntercept - ( slopeDelta * width / 2.0 ) ;
231+ double highVoltageIntercept = smoothTowardRight
232+ ? rightIntercept - ( slopeDelta * width / 2.0 )
233+ : rightIntercept ;
222234
223235 if ( voltage <= start )
224236 {
225- current = ( leftSlope * voltage ) + leftIntercept ;
237+ current = ( leftSlope * voltage ) + lowVoltageIntercept ;
226238 conductance = leftSlope ;
227239 return ;
228240 }
229241
230242 if ( voltage >= end )
231243 {
232- current = ( rightSlope * voltage ) + rightIntercept ;
244+ current = ( rightSlope * voltage ) + highVoltageIntercept ;
233245 conductance = rightSlope ;
234246 return ;
235247 }
@@ -243,8 +255,7 @@ private static void EvaluateTransition(
243255 //
244256 // where x is the distance from the start of the smoothing band.
245257 double distance = voltage - start ;
246- double slopeDelta = rightSlope - leftSlope ;
247- current = ( leftSlope * start ) + leftIntercept
258+ current = ( leftSlope * start ) + lowVoltageIntercept
248259 + ( leftSlope * distance )
249260 + ( slopeDelta * distance * distance / ( 2.0 * width ) ) ;
250261 conductance = leftSlope + ( slopeDelta * distance / width ) ;
0 commit comments