diff --git a/src/spicelib/devices/hicum2/hicumL2.cpp b/src/spicelib/devices/hicum2/hicumL2.cpp index 010e53e20..09f440dc0 100644 --- a/src/spicelib/devices/hicum2/hicumL2.cpp +++ b/src/spicelib/devices/hicum2/hicumL2.cpp @@ -1762,20 +1762,20 @@ HICUMload(GENmodel *inModel, CKTcircuit *ckt) Vbiei = DEVpnjlim(Vbiei,*(ckt->CKTstate0 + here->HICUMvbiei),here->HICUMvt.rpart, here->HICUMtVcrit,&icheck); Vaval = 3 * here->HICUMvdci_t.rpart;//limit step around 3*vdci_t -> somehow this brings convergence - // if ((model->HICUMkavlGiven) && (Vbici < MIN(0, -Vaval))) { - // Vbici_temp = -(Vbici + Vaval); - // Vbici_temp = DEVpnjlim( - // Vbici_temp, - // -(*(ckt->CKTstate0 + here->HICUMvbici) + Vaval), - // here->HICUMvt.rpart, - // here->HICUMtVcrit, - // &ichk1 - // ); - // Vbici = -(Vbici_temp + Vaval); - // } else { + if ((model->HICUMkavlGiven) && (Vbici < MIN(0, -Vaval))) { + Vbici_temp = -(Vbici + Vaval); + Vbici_temp = DEVpnjlim( + Vbici_temp, + -(*(ckt->CKTstate0 + here->HICUMvbici) + Vaval), + here->HICUMvt.rpart, + here->HICUMtVcrit, + &ichk1 + ); + Vbici = -(Vbici_temp + Vaval); + } else { Vbici = DEVpnjlim(Vbici,*(ckt->CKTstate0 + here->HICUMvbici),here->HICUMvt.rpart, here->HICUMtVcrit,&ichk1); - //} + } Vbpei = DEVpnjlim(Vbpei,*(ckt->CKTstate0 + here->HICUMvbpei),here->HICUMvt.rpart, here->HICUMtVcrit,&ichk2); Vbpci = DEVpnjlim(Vbpci,*(ckt->CKTstate0 + here->HICUMvbpci),here->HICUMvt.rpart, @@ -1786,7 +1786,7 @@ HICUMload(GENmodel *inModel, CKTcircuit *ckt) here->HICUMtVcrit,&ichk5); if (selfheat) { Vrth = HICUMlimitlog(Vrth, - *(ckt->CKTstate0 + here->HICUMvrth),10,&ichk6); + *(ckt->CKTstate0 + here->HICUMvrth),1,&ichk6); } if ((ichk1 == 1) || (ichk2 == 1) || (ichk3 == 1) || (ichk4 == 1) || (ichk5 == 1) || (ichk6 == 1)) icheck=1; } diff --git a/src/spicelib/devices/hicum2/hicumL2temp.cpp b/src/spicelib/devices/hicum2/hicumL2temp.cpp index c5c2f93f9..d77b068db 100644 --- a/src/spicelib/devices/hicum2/hicumL2temp.cpp +++ b/src/spicelib/devices/hicum2/hicumL2temp.cpp @@ -38,6 +38,19 @@ using namespace duals::literals; #define TMIN -100.0 #define LN_EXP_LIMIT 11.0 +duals::duald clip_temperature(duals::duald T){ + // smooth clipping function for device temperature, if self heating increases temperature beyond + // T0+TMAX or below T0-TMIN + duals::duald Tdev; + Tdev = T; + if (T<(TMIN+CONSTCtoK+1.0)){ + Tdev = TMIN+CONSTCtoK+exp(T-TMIN-CONSTCtoK-1.0); + } else if (T>(TMAX+CONSTCtoK-1.0)) { + Tdev = TMAX+CONSTCtoK-exp(TMAX+CONSTCtoK-T-1.0); + }; + return Tdev; +}; + void TMPHICJ(double , double , double , double , double , double , double , double , double , double , double , double *, double *, double *); @@ -157,20 +170,29 @@ int hicum_thermal_update(HICUMmodel *inModel, HICUMinstance *inInstance, double zetabcxt= mg+1-model->HICUMzetacx; zetasct = mg-1.5; - // Limit temperature to avoid FPEs in equations - *(Tdev_Vrth) = 1.0; - if(*(HICUMTemp) < TMIN + CONSTCtoK) { - *(HICUMTemp) = TMIN + CONSTCtoK; - *(Tdev_Vrth) = 0.0; - } else { - if (*(HICUMTemp) > TMAX + CONSTCtoK) { - *(HICUMTemp) = TMAX + CONSTCtoK; - *(Tdev_Vrth) = 0.0; - } - } + + + // Smooth ngspice T clipping + temp = clip_temperature( *(HICUMTemp)+1_e ); + *(HICUMTemp) = temp.rpart(); + *(Tdev_Vrth) = temp.dpart(); + + // original HICUM clipping for Tdev => left here for reference + // *(Tdev_Vrth) = 1.0; + // if(*(HICUMTemp) < TMIN + CONSTCtoK) { + // *(HICUMTemp) = TMIN + CONSTCtoK; + // *(Tdev_Vrth) = 0.0; + // } else { + // if (*(HICUMTemp) > TMAX + CONSTCtoK) { + // *(HICUMTemp) = TMAX + CONSTCtoK; + // *(Tdev_Vrth) = 0.0; + // } + //} + //This routine calculate the derivative with respect to Vrth. Since at some point // Tdev becomes constant (see above), we need to account for this like below. - temp = *(HICUMTemp)+1_e* *(Tdev_Vrth); // dual number device temperature + //temp = *(HICUMTemp)+1_e* *(Tdev_Vrth); // dual number device temperature + vt = temp*CONSTKoverQ; // dual valued temperature voltage here->HICUMvt0 = Tnom * CONSTKoverQ;