First KLU support of CIDER TWOD simulations

This commit is contained in:
Francesco Lannutti 2020-06-01 16:15:55 +02:00 committed by Holger Vogt
parent 30d09c62ae
commit 8a8adfe451
11 changed files with 3215 additions and 388 deletions

View File

@ -102,36 +102,61 @@ NUMD2admittance(TWOdevice *pDevice, double omega, SPcomplex *yd)
}
storeNewRhs(pDevice, pDevice->pLastContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
}
}
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -263,36 +288,61 @@ NBJT2admittance(TWOdevice *pDevice, double omega, SPcomplex *yIeVce,
TWOPjacLoad(pDevice);
}
storeNewRhs(pDevice, pColContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
}
}
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -317,7 +367,13 @@ NBJT2admittance(TWOdevice *pDevice, double omega, SPcomplex *yIeVce,
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -517,36 +573,62 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
} else if (OneCarrier == P_TYPE) {
TWOPjacLoad(pDevice);
}
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
} else if (OneCarrier == N_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fNN, 0.0, -dxdy * omega);
} else if (OneCarrier == P_TYPE) {
spADD_COMPLEX_ELEMENT(pNode->fPP, 0.0, dxdy * omega);
}
}
}
}
}
}
#ifdef KLU
}
#endif
pDevice->pStats->loadTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
spFactor(pDevice->matrix);
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
pDevice->pStats->factorTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -574,7 +656,13 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
/* MISC */
@ -602,7 +690,13 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
pDevice->pStats->solveTime[STAT_AC] += SPfrontEnd->IFseconds() - startTime;
}
/* MISC */
@ -687,7 +781,12 @@ TWOsorSolve(TWOdevice *pDevice, double *xReal, double *xImag,
}
/* compute xReal(k+1). solution stored in rhsImag */
spSolve(pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL) ;
#else
SMPsolve(pDevice->matrix, rhsSOR, rhsSOR);
#endif
/* modify solution when wRelax is not 1 */
if (wRelax != 1) {
for (index = 1; index <= numEqns; index++) {
@ -729,7 +828,12 @@ TWOsorSolve(TWOdevice *pDevice, double *xReal, double *xImag,
}
}
/* compute xImag(k+1) */
spSolve(pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsSOR, rhsSOR, NULL, NULL) ;
#else
SMPsolve(pDevice->matrix, rhsSOR, rhsSOR);
#endif
/* modify solution when wRelax is not 1 */
if (wRelax != 1) {
for (index = 1; index <= numEqns; index++) {
@ -1073,32 +1177,54 @@ NUMD2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIn)
}
storeNewRhs(pDevice, pDevice->pLastContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
}
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
}
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDevice->pFirstContact, deltaVContact,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc, y->real, y->imag);
@ -1147,31 +1273,54 @@ NBJT2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex *yIcVce,
TWOPjacLoad(pDevice);
}
storeNewRhs(pDevice, pColContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
}
#ifdef KLU
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pEmitContact, FALSE,
solnReal, solnImag, &cOmega);
@ -1184,7 +1333,13 @@ NBJT2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex *yIcVce,
}
storeNewRhs(pDevice, pBaseContact);
/* don't need to LU factor the jacobian since it exists */
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pEmitContact, FALSE,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(pIeVbe, y->real, y->imag);
@ -1240,33 +1395,54 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
TWOPjacLoad(pDevice);
}
storeNewRhs(pDevice, pDContact);
spSetComplex(pDevice->matrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - To be completed
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixComplex ;
} else {
#endif
spSetComplex(pDevice->matrix->SPmatrix);
for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) {
pElem = pDevice->elements[eIndex];
if (pElem->elemType == SEMICON) {
dxdy = 0.25 * pElem->dx * pElem->dy;
for (index = 0; index <= 3; index++) {
pNode = pElem->pNodes[index];
if (pNode->nodeType != CONTACT) {
if (!OneCarrier) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
} else if (OneCarrier == N_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fNN, -temp.real, -temp.imag);
} else if (OneCarrier == P_TYPE) {
CMPLX_MULT_SCALAR(temp, cOmega, dxdy);
spADD_COMPLEX_ELEMENT(pNode->fPP, temp.real, temp.imag);
}
}
}
}
}
}
}
spFactor(pDevice->matrix);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
}
#endif
#ifdef KLU
SMPluFacKLUforCIDER (pDevice->matrix) ;
#else
SMPcLUfac(pDevice->matrix, 0);
#endif
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDContact, TRUE,
solnReal, solnImag, &cOmega);
@ -1283,7 +1459,13 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
}
storeNewRhs(pDevice, pSContact);
/* don't need to LU factor the jacobian since it exists */
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDContact, FALSE,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc->yIdVsb, y->real, y->imag);
@ -1297,7 +1479,13 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
rhsImag[index] = 0.0;
}
storeNewRhs(pDevice, pGContact);
spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#else
SMPcSolveForCIDER (pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag) ;
#endif
y = contactAdmittance(pDevice, pDContact, FALSE,
solnReal, solnImag, &cOmega);
CMPLX_ASSIGN_VALUE(yAc->yIdVgb, y->real, y->imag);

View File

@ -30,8 +30,13 @@ void
*/
incVpn = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pDevice->pLastContact );
spSolve( pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVpn) ;
#endif
incVpn = pDevice->dcDeltaSolution;
*gd = contactConductance( pDevice, pContact, deltaVContact, incVpn,
tranAnalysis, intCoeff );
@ -58,9 +63,20 @@ void
incVce = pDevice->dcDeltaSolution;
incVbe = pDevice->copiedSolution;
storeNewRhs( pDevice, pColContact );
spSolve( pDevice->matrix, pDevice->rhs, incVce, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVce, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVce) ;
#endif
storeNewRhs( pDevice, pBaseContact );
spSolve( pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVbe) ;
#endif
*dIeDVce = contactConductance( pDevice, pEmitContact, FALSE, incVce,
tranAnalysis, intCoeff );
@ -96,11 +112,28 @@ void
incVsb = pDevice->copiedSolution;
incVgb = pDevice->rhsImag;
storeNewRhs( pDevice, pDContact );
spSolve( pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVdb) ;
#endif
storeNewRhs( pDevice, pSContact );
spSolve( pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVsb) ;
#endif
storeNewRhs( pDevice, pGContact );
spSolve( pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVgb) ;
#endif
dIdV->dIdDVdb = contactConductance( pDevice, pDContact, TRUE,
incVdb, tranAnalysis, intCoeff );

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,13 @@ TWOdestroy(TWOdevice *pDevice)
FREE( pDevice->copiedSolution );
FREE( pDevice->rhs );
FREE( pDevice->rhsImag );
spDestroy( pDevice->matrix );
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
break;
case SLV_EQUIL:
/* free up the vectors allocated in the equilibrium solution */
@ -41,7 +47,13 @@ TWOdestroy(TWOdevice *pDevice)
FREE( pDevice->dcDeltaSolution );
FREE( pDevice->copiedSolution );
FREE( pDevice->rhs );
spDestroy( pDevice->matrix );
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
break;
case SLV_NONE:
break;

View File

@ -166,4 +166,11 @@ extern BOOLEAN TWOpsiDeltaConverged(TWOdevice *);
extern double TWOnuNorm(TWOdevice *);
extern void TWOjacCheck(TWOdevice *, BOOLEAN, TWOtranInfo *);
#ifdef KLU
void TWObindCSC (TWOdevice *) ;
void TWONbindCSC (TWOdevice *) ;
void TWOPbindCSC (TWOdevice *) ;
void TWOQbindCSC (TWOdevice *) ;
#endif
#endif

View File

@ -16,6 +16,9 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "ngspice/cidersupt.h"
#include "../../maths/misc/bernoull.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/*
* Functions to setup and solve the continuity equations.
@ -54,16 +57,41 @@ void
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
pNode->fPsiPsi = spGetElement( matrix, psiEqn, psiEqn );
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, psiEqn, psiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, psiEqn, psiEqn);
#endif
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
nEqn = pNode->nEqn;
pNode->pEqn = 0; /* Throw pEqn number into garbage. */
/* pointers for additional terms */
pNode->fPsiN = spGetElement( matrix, psiEqn, nEqn );
pNode->fNPsi = spGetElement( matrix, nEqn, psiEqn );
pNode->fNN = spGetElement( matrix, nEqn, nEqn );
#ifdef KLU
pNode->fPsiN = SMPmakeEltKLUforCIDER (matrix, psiEqn, nEqn) ;
pNode->fPsiNBinding = NULL ;
#else
pNode->fPsiN = SMPmakeElt(matrix, psiEqn, nEqn);
#endif
#ifdef KLU
pNode->fNPsi = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqn) ;
pNode->fNPsiBinding = NULL ;
#else
pNode->fNPsi = SMPmakeElt(matrix, nEqn, psiEqn);
#endif
#ifdef KLU
pNode->fNN = SMPmakeEltKLUforCIDER (matrix, nEqn, nEqn) ;
pNode->fNNBinding = NULL ;
#else
pNode->fNN = SMPmakeElt(matrix, nEqn, nEqn);
#endif
} else {
nEqn = 0;
}
@ -92,66 +120,270 @@ void
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnTL, psiEqnTR );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTL, psiEqnBL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnTR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnBL) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnBL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiP1 = spGetElement( matrix, nEqnTL, psiEqnTR );
pNode->fNNiP1 = spGetElement( matrix, nEqnTL, nEqnTR );
pNode->fNPsijP1 = spGetElement( matrix, nEqnTL, psiEqnBL );
pNode->fNNjP1 = spGetElement( matrix, nEqnTL, nEqnBL );
#ifdef KLU
pNode->fNPsiiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, psiEqnTR) ;
pNode->fNPsiiP1Binding = NULL ;
#else
pNode->fNPsiiP1 = SMPmakeElt(matrix, nEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fNNiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, nEqnTR) ;
pNode->fNNiP1Binding = NULL ;
#else
pNode->fNNiP1 = SMPmakeElt(matrix, nEqnTL, nEqnTR);
#endif
#ifdef KLU
pNode->fNPsijP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, psiEqnBL) ;
pNode->fNPsijP1Binding = NULL ;
#else
pNode->fNPsijP1 = SMPmakeElt(matrix, nEqnTL, psiEqnBL);
#endif
#ifdef KLU
pNode->fNNjP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, nEqnBL) ;
pNode->fNNjP1Binding = NULL ;
#else
pNode->fNNjP1 = SMPmakeElt(matrix, nEqnTL, nEqnBL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiP1jP1 = spGetElement( matrix, nEqnTL, psiEqnBR );
pNode->fNNiP1jP1 = spGetElement( matrix, nEqnTL, nEqnBR );
#ifdef KLU
pNode->fNPsiiP1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, psiEqnBR) ;
pNode->fNPsiiP1jP1Binding = NULL ;
#else
pNode->fNPsiiP1jP1 = SMPmakeElt(matrix, nEqnTL, psiEqnBR);
#endif
#ifdef KLU
pNode->fNNiP1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTL, nEqnBR) ;
pNode->fNNiP1jP1Binding = NULL ;
#else
pNode->fNNiP1jP1 = SMPmakeElt(matrix, nEqnTL, nEqnBR);
#endif
}
}
pNode = pElem->pTRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnTR, psiEqnTL );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTR, psiEqnBR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnTL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnBR) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTR, psiEqnBR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiM1 = spGetElement( matrix, nEqnTR, psiEqnTL );
pNode->fNNiM1 = spGetElement( matrix, nEqnTR, nEqnTL );
pNode->fNPsijP1 = spGetElement( matrix, nEqnTR, psiEqnBR );
pNode->fNNjP1 = spGetElement( matrix, nEqnTR, nEqnBR );
#ifdef KLU
pNode->fNPsiiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, psiEqnTL) ;
pNode->fNPsiiM1Binding = NULL ;
#else
pNode->fNPsiiM1 = SMPmakeElt(matrix, nEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fNNiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, nEqnTL) ;
pNode->fNNiM1Binding = NULL ;
#else
pNode->fNNiM1 = SMPmakeElt(matrix, nEqnTR, nEqnTL);
#endif
#ifdef KLU
pNode->fNPsijP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, psiEqnBR) ;
pNode->fNPsijP1Binding = NULL ;
#else
pNode->fNPsijP1 = SMPmakeElt(matrix, nEqnTR, psiEqnBR);
#endif
#ifdef KLU
pNode->fNNjP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, nEqnBR) ;
pNode->fNNjP1Binding = NULL ;
#else
pNode->fNNjP1 = SMPmakeElt(matrix, nEqnTR, nEqnBR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiM1jP1 = spGetElement( matrix, nEqnTR, psiEqnBL );
pNode->fNNiM1jP1 = spGetElement( matrix, nEqnTR, nEqnBL );
#ifdef KLU
pNode->fNPsiiM1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, psiEqnBL) ;
pNode->fNPsiiM1jP1Binding = NULL ;
#else
pNode->fNPsiiM1jP1 = SMPmakeElt(matrix, nEqnTR, psiEqnBL);
#endif
#ifdef KLU
pNode->fNNiM1jP1 = SMPmakeEltKLUforCIDER (matrix, nEqnTR, nEqnBL) ;
pNode->fNNiM1jP1Binding = NULL ;
#else
pNode->fNNiM1jP1 = SMPmakeElt(matrix, nEqnTR, nEqnBL);
#endif
}
}
pNode = pElem->pBRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnBR, psiEqnBL );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBR, psiEqnTR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnBL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnTR) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnTR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiM1 = spGetElement( matrix, nEqnBR, psiEqnBL );
pNode->fNNiM1 = spGetElement( matrix, nEqnBR, nEqnBL );
pNode->fNPsijM1 = spGetElement( matrix, nEqnBR, psiEqnTR );
pNode->fNNjM1 = spGetElement( matrix, nEqnBR, nEqnTR );
#ifdef KLU
pNode->fNPsiiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, psiEqnBL) ;
pNode->fNPsiiM1Binding = NULL ;
#else
pNode->fNPsiiM1 = SMPmakeElt(matrix, nEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fNNiM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, nEqnBL) ;
pNode->fNNiM1Binding = NULL ;
#else
pNode->fNNiM1 = SMPmakeElt(matrix, nEqnBR, nEqnBL);
#endif
#ifdef KLU
pNode->fNPsijM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, psiEqnTR) ;
pNode->fNPsijM1Binding = NULL ;
#else
pNode->fNPsijM1 = SMPmakeElt(matrix, nEqnBR, psiEqnTR);
#endif
#ifdef KLU
pNode->fNNjM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, nEqnTR) ;
pNode->fNNjM1Binding = NULL ;
#else
pNode->fNNjM1 = SMPmakeElt(matrix, nEqnBR, nEqnTR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiM1jM1 = spGetElement( matrix, nEqnBR, psiEqnTL );
pNode->fNNiM1jM1 = spGetElement( matrix, nEqnBR, nEqnTL );
#ifdef KLU
pNode->fNPsiiM1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, psiEqnTL) ;
pNode->fNPsiiM1jM1Binding = NULL ;
#else
pNode->fNPsiiM1jM1 = SMPmakeElt(matrix, nEqnBR, psiEqnTL);
#endif
#ifdef KLU
pNode->fNNiM1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBR, nEqnTL) ;
pNode->fNNiM1jM1Binding = NULL ;
#else
pNode->fNNiM1jM1 = SMPmakeElt(matrix, nEqnBR, nEqnTL);
#endif
}
}
pNode = pElem->pBLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnBL, psiEqnBR );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBL, psiEqnTL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnBR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnTL) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBL, psiEqnTL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fNPsiiP1 = spGetElement( matrix, nEqnBL, psiEqnBR );
pNode->fNNiP1 = spGetElement( matrix, nEqnBL, nEqnBR );
pNode->fNPsijM1 = spGetElement( matrix, nEqnBL, psiEqnTL );
pNode->fNNjM1 = spGetElement( matrix, nEqnBL, nEqnTL );
#ifdef KLU
pNode->fNPsiiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, psiEqnBR) ;
pNode->fNPsiiP1Binding = NULL ;
#else
pNode->fNPsiiP1 = SMPmakeElt(matrix, nEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fNNiP1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, nEqnBR) ;
pNode->fNNiP1Binding = NULL ;
#else
pNode->fNNiP1 = SMPmakeElt(matrix, nEqnBL, nEqnBR);
#endif
#ifdef KLU
pNode->fNPsijM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, psiEqnTL) ;
pNode->fNPsijM1Binding = NULL ;
#else
pNode->fNPsijM1 = SMPmakeElt(matrix, nEqnBL, psiEqnTL);
#endif
#ifdef KLU
pNode->fNNjM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, nEqnTL) ;
pNode->fNNjM1Binding = NULL ;
#else
pNode->fNNjM1 = SMPmakeElt(matrix, nEqnBL, nEqnTL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fNPsiiP1jM1 = spGetElement( matrix, nEqnBL, psiEqnTR );
pNode->fNNiP1jM1 = spGetElement( matrix, nEqnBL, nEqnTR );
#ifdef KLU
pNode->fNPsiiP1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, psiEqnTR) ;
pNode->fNPsiiP1jM1Binding = NULL ;
#else
pNode->fNPsiiP1jM1 = SMPmakeElt(matrix, nEqnBL, psiEqnTR);
#endif
#ifdef KLU
pNode->fNNiP1jM1 = SMPmakeEltKLUforCIDER (matrix, nEqnBL, nEqnTR) ;
pNode->fNNiP1jM1Binding = NULL ;
#else
pNode->fNNiP1jM1 = SMPmakeElt(matrix, nEqnBL, nEqnTR);
#endif
}
}
}
@ -200,27 +432,135 @@ void
nEqn = pNode->nEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP );
#ifdef KLU
pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
pNode->fNPsiInBinding = NULL ;
#else
pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fNPsiInP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
pNode->fNPsiInP1Binding = NULL ;
#else
pNode->fNPsiInP1 = SMPmakeElt(matrix, nEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
pNode->fNPsiOxBinding = NULL ;
#else
pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fNPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
pNode->fNPsiOxP1Binding = NULL ;
#else
pNode->fNPsiOxP1 = SMPmakeElt(matrix, nEqn, psiEqnOxP);
#endif
} else { /* Right Side */
pNode->fNPsiInM1 = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOxM1 = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxP );
#ifdef KLU
pNode->fNPsiInM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
pNode->fNPsiInM1Binding = NULL ;
#else
pNode->fNPsiInM1 = SMPmakeElt(matrix, nEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
pNode->fNPsiInBinding = NULL ;
#else
pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fNPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
pNode->fNPsiOxM1Binding = NULL ;
#else
pNode->fNPsiOxM1 = SMPmakeElt(matrix, nEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
pNode->fNPsiOxBinding = NULL ;
#else
pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxP);
#endif
}
} else { /* Horizontal Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP );
// <<<<<<< HEAD
// if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
// pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM );
// pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP );
// pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM );
// pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP );
// =======
// if ( nIndex <= 1 ) { /* Top Side */
//
// #ifdef KLU
// pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
// pNode->fNPsiInBinding = NULL ;
// #else
// pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInM);
// #endif
//
// #ifdef KLU
// pNode->fNPsiInP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
// pNode->fNPsiInP1Binding = NULL ;
// #else
// pNode->fNPsiInP1 = SMPmakeElt(matrix, nEqn, psiEqnInP);
// #endif
//
// #ifdef KLU
// pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
// pNode->fNPsiOxBinding = NULL ;
// #else
// pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxM);
// #endif
//
// #ifdef KLU
// pNode->fNPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
// pNode->fNPsiOxP1Binding = NULL ;
// #else
// pNode->fNPsiOxP1 = SMPmakeElt(matrix, nEqn, psiEqnOxP);
// #endif
//
// >>>>>>> First KLU support of CIDER TWOD simulations
} else { /* Bottom Side */
pNode->fNPsiInM1 = spGetElement( matrix, nEqn, psiEqnInM );
pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInP );
pNode->fNPsiOxM1 = spGetElement( matrix, nEqn, psiEqnOxM );
pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxP );
#ifdef KLU
pNode->fNPsiInM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInM) ;
pNode->fNPsiInM1Binding = NULL ;
#else
pNode->fNPsiInM1 = SMPmakeElt(matrix, nEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fNPsiIn = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnInP) ;
pNode->fNPsiInBinding = NULL ;
#else
pNode->fNPsiIn = SMPmakeElt(matrix, nEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fNPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxM) ;
pNode->fNPsiOxM1Binding = NULL ;
#else
pNode->fNPsiOxM1 = SMPmakeElt(matrix, nEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fNPsiOx = SMPmakeEltKLUforCIDER (matrix, nEqn, psiEqnOxP) ;
pNode->fNPsiOxBinding = NULL ;
#else
pNode->fNPsiOx = SMPmakeElt(matrix, nEqn, psiEqnOxP);
#endif
}
}
} /* endfor nIndex */
@ -230,6 +570,256 @@ void
} /* endif SurfaceMobility */
}
#ifdef KLU
void
TWONbindCSC (TWOdevice *pDevice)
{
TWOelem *pElem;
TWOnode *pNode;
TWOchannel *pCh;
BindKluElementCOO i, *matched, *BindStruct, *BindStructCSC ;
int index ;
size_t nz ;
int eIndex, nIndex;
int nextIndex; /* index of node to find next element */
int psiEqn, nEqn; /* scratch for deref'd eqn numbers */
int psiEqnTL = 0, nEqnTL = 0;
int psiEqnTR = 0, nEqnTR = 0;
int psiEqnBR = 0, nEqnBR = 0;
int psiEqnBL = 0, nEqnBL = 0;
int psiEqnInM = 0, psiEqnInP = 0; /* scratch for deref'd surface eqns */
int psiEqnOxM = 0, psiEqnOxP = 0; /* M= more negative, P= more positive */
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructCOO ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindKluElementCOO *) malloc (nz * sizeof(BindKluElementCOO)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
/* first the self terms */
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, psiEqn, psiEqn) ;
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
nEqn = pNode->nEqn;
pNode->pEqn = 0; /* Throw pEqn number into garbage. */
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fPsiN, fPsiNBinding, psiEqn, nEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsi, fNPsiBinding, nEqn, psiEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNN, fNNBinding, nEqn, nEqn) ;
} else {
nEqn = 0;
}
/* save equation indices */
switch ( nIndex ) {
case 0: /* TL Node */
psiEqnTL = psiEqn;
nEqnTL = nEqn;
break;
case 1: /* TR Node */
psiEqnTR = psiEqn;
nEqnTR = nEqn;
break;
case 2: /* BR Node */
psiEqnBR = psiEqn;
nEqnBR = nEqn;
break;
case 3: /* BL Node */
psiEqnBL = psiEqn;
nEqnBL = nEqn;
break;
default:
break;
}
}
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTL, psiEqnBL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1, fNPsiiP1Binding, nEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1, fNNiP1Binding, nEqnTL, nEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijP1, fNPsijP1Binding, nEqnTL, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjP1, fNNjP1Binding, nEqnTL, nEqnBL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1jP1, fNPsiiP1jP1Binding, nEqnTL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1jP1, fNNiP1jP1Binding, nEqnTL, nEqnBR) ;
}
}
pNode = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTR, psiEqnBR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1, fNPsiiM1Binding, nEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1, fNNiM1Binding, nEqnTR, nEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijP1, fNPsijP1Binding, nEqnTR, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjP1, fNNjP1Binding, nEqnTR, nEqnBR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1jP1, fNPsiiM1jP1Binding, nEqnTR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1jP1, fNNiM1jP1Binding, nEqnTR, nEqnBL) ;
}
}
pNode = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBR, psiEqnTR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1, fNPsiiM1Binding, nEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1, fNNiM1Binding, nEqnBR, nEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijM1, fNPsijM1Binding, nEqnBR, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjM1, fNNjM1Binding, nEqnBR, nEqnTR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiM1jM1, fNPsiiM1jM1Binding, nEqnBR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1jM1, fNNiM1jM1Binding, nEqnBR, nEqnTL) ;
}
}
pNode = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBL, psiEqnTL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1, fNPsiiP1Binding, nEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1, fNNiP1Binding, nEqnBL, nEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsijM1, fNPsijM1Binding, nEqnBL, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNjM1, fNNjM1Binding, nEqnBL, nEqnTL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiiP1jM1, fNPsiiP1jM1Binding, nEqnBL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1jM1, fNNiP1jM1Binding, nEqnBL, nEqnTR) ;
}
}
}
/*
* Add terms for surface-field of inversion-layer mobility model.
* Elements MUST be made from silicon for this to work.
* No empty elements are allowed.
* Don't need these pointers if SurfaceMobility isn't set.
*/
if ( MobDeriv && SurfaceMobility ) {
for ( pCh = pDevice->pChannel; pCh != NULL;
pCh = pCh->next ) {
pElem = pCh->pNElem;
switch (pCh->type) {
case 0:
psiEqnInM = pElem->pBLNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pTRNode->psiEqn;
break;
case 1:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pBLNode->psiEqn;
psiEqnOxM = pElem->pTRNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 2:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pTRNode->psiEqn;
psiEqnOxM = pElem->pBLNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 3:
psiEqnInM = pElem->pTRNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pBLNode->psiEqn;
break;
}
pElem = pCh->pSeed;
nextIndex = (pCh->type + 2)%4;
while (pElem && pElem->channel == pCh->id) {
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
psiEqn = pNode->psiEqn;
nEqn = pNode->nEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxP1, fNPsiOxP1Binding, nEqn, psiEqnOxP) ;
} else { /* Right Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInM1, fNPsiInM1Binding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxM1, fNPsiOxM1Binding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxP) ;
}
} else { /* Horizontal Slice */
if ( nIndex <= 1 ) { /* Top Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxP1, fNPsiOxP1Binding, nEqn, psiEqnOxP) ;
} else { /* Bottom Side */
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInM1, fNPsiInM1Binding, nEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOxM1, fNPsiOxM1Binding, nEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiOx, fNPsiOxBinding, nEqn, psiEqnOxP) ;
}
}
} /* endfor nIndex */
pElem = pElem->pElems[ nextIndex ];
} /* endwhile pElem */
} /* endfor pCh */
} /* endif SurfaceMobility */
free (BindStructCSC) ;
}
#endif
/*
* The Jacobian and Rhs are loaded by the following function.
@ -269,7 +859,17 @@ void
}
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
@ -434,7 +1034,17 @@ void
TWONcommonTerms( pDevice, FALSE, FALSE, NULL );
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];

View File

@ -16,6 +16,10 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "ngspice/cidersupt.h"
#include "../../maths/misc/bernoull.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/*
* Functions to setup and solve the continuity equations.
* Both continuity equations are solved.
@ -53,16 +57,41 @@ void
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
pNode->fPsiPsi = spGetElement( matrix, psiEqn, psiEqn );
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, psiEqn, psiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, psiEqn, psiEqn);
#endif
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
pEqn = pNode->pEqn;
pNode->nEqn = 0;
/* pointers for additional terms */
pNode->fPsiP = spGetElement( matrix, psiEqn, pEqn );
pNode->fPPsi = spGetElement( matrix, pEqn, psiEqn );
pNode->fPP = spGetElement( matrix, pEqn, pEqn );
#ifdef KLU
pNode->fPsiP = SMPmakeEltKLUforCIDER (matrix, psiEqn, pEqn) ;
pNode->fPsiPBinding = NULL ;
#else
pNode->fPsiP = SMPmakeElt(matrix, psiEqn, pEqn);
#endif
#ifdef KLU
pNode->fPPsi = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqn) ;
pNode->fPPsiBinding = NULL ;
#else
pNode->fPPsi = SMPmakeElt(matrix, pEqn, psiEqn);
#endif
#ifdef KLU
pNode->fPP = SMPmakeEltKLUforCIDER (matrix, pEqn, pEqn) ;
pNode->fPPBinding = NULL ;
#else
pNode->fPP = SMPmakeElt(matrix, pEqn, pEqn);
#endif
} else {
pEqn = 0;
}
@ -91,66 +120,270 @@ void
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnTL, psiEqnTR );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTL, psiEqnBL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnTR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTL, psiEqnBL) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTL, psiEqnBL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiP1 = spGetElement( matrix, pEqnTL, psiEqnTR );
pNode->fPPiP1 = spGetElement( matrix, pEqnTL, pEqnTR );
pNode->fPPsijP1 = spGetElement( matrix, pEqnTL, psiEqnBL );
pNode->fPPjP1 = spGetElement( matrix, pEqnTL, pEqnBL );
#ifdef KLU
pNode->fPPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, psiEqnTR) ;
pNode->fPPsiiP1Binding = NULL ;
#else
pNode->fPPsiiP1 = SMPmakeElt(matrix, pEqnTL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPPiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, pEqnTR) ;
pNode->fPPiP1Binding = NULL ;
#else
pNode->fPPiP1 = SMPmakeElt(matrix, pEqnTL, pEqnTR);
#endif
#ifdef KLU
pNode->fPPsijP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, psiEqnBL) ;
pNode->fPPsijP1Binding = NULL ;
#else
pNode->fPPsijP1 = SMPmakeElt(matrix, pEqnTL, psiEqnBL);
#endif
#ifdef KLU
pNode->fPPjP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, pEqnBL) ;
pNode->fPPjP1Binding = NULL ;
#else
pNode->fPPjP1 = SMPmakeElt(matrix, pEqnTL, pEqnBL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiP1jP1 = spGetElement( matrix, pEqnTL, psiEqnBR );
pNode->fPPiP1jP1 = spGetElement( matrix, pEqnTL, pEqnBR );
#ifdef KLU
pNode->fPPsiiP1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, psiEqnBR) ;
pNode->fPPsiiP1jP1Binding = NULL ;
#else
pNode->fPPsiiP1jP1 = SMPmakeElt(matrix, pEqnTL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPPiP1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTL, pEqnBR) ;
pNode->fPPiP1jP1Binding = NULL ;
#else
pNode->fPPiP1jP1 = SMPmakeElt(matrix, pEqnTL, pEqnBR);
#endif
}
}
pNode = pElem->pTRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnTR, psiEqnTL );
pNode->fPsiPsijP1 = spGetElement(matrix, psiEqnTR, psiEqnBR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnTL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnTR, psiEqnBR) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, psiEqnTR, psiEqnBR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiM1 = spGetElement( matrix, pEqnTR, psiEqnTL );
pNode->fPPiM1 = spGetElement( matrix, pEqnTR, pEqnTL );
pNode->fPPsijP1 = spGetElement( matrix, pEqnTR, psiEqnBR );
pNode->fPPjP1 = spGetElement( matrix, pEqnTR, pEqnBR );
#ifdef KLU
pNode->fPPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, psiEqnTL) ;
pNode->fPPsiiM1Binding = NULL ;
#else
pNode->fPPsiiM1 = SMPmakeElt(matrix, pEqnTR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPPiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, pEqnTL) ;
pNode->fPPiM1Binding = NULL ;
#else
pNode->fPPiM1 = SMPmakeElt(matrix, pEqnTR, pEqnTL);
#endif
#ifdef KLU
pNode->fPPsijP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, psiEqnBR) ;
pNode->fPPsijP1Binding = NULL ;
#else
pNode->fPPsijP1 = SMPmakeElt(matrix, pEqnTR, psiEqnBR);
#endif
#ifdef KLU
pNode->fPPjP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, pEqnBR) ;
pNode->fPPjP1Binding = NULL ;
#else
pNode->fPPjP1 = SMPmakeElt(matrix, pEqnTR, pEqnBR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiM1jP1 = spGetElement( matrix, pEqnTR, psiEqnBL );
pNode->fPPiM1jP1 = spGetElement( matrix, pEqnTR, pEqnBL );
#ifdef KLU
pNode->fPPsiiM1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, psiEqnBL) ;
pNode->fPPsiiM1jP1Binding = NULL ;
#else
pNode->fPPsiiM1jP1 = SMPmakeElt(matrix, pEqnTR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPPiM1jP1 = SMPmakeEltKLUforCIDER (matrix, pEqnTR, pEqnBL) ;
pNode->fPPiM1jP1Binding = NULL ;
#else
pNode->fPPiM1jP1 = SMPmakeElt(matrix, pEqnTR, pEqnBL);
#endif
}
}
pNode = pElem->pBRNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, psiEqnBR, psiEqnBL );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBR, psiEqnTR );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnBL) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBR, psiEqnTR) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBR, psiEqnTR);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiM1 = spGetElement( matrix, pEqnBR, psiEqnBL );
pNode->fPPiM1 = spGetElement( matrix, pEqnBR, pEqnBL );
pNode->fPPsijM1 = spGetElement( matrix, pEqnBR, psiEqnTR );
pNode->fPPjM1 = spGetElement( matrix, pEqnBR, pEqnTR );
#ifdef KLU
pNode->fPPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, psiEqnBL) ;
pNode->fPPsiiM1Binding = NULL ;
#else
pNode->fPPsiiM1 = SMPmakeElt(matrix, pEqnBR, psiEqnBL);
#endif
#ifdef KLU
pNode->fPPiM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, pEqnBL) ;
pNode->fPPiM1Binding = NULL ;
#else
pNode->fPPiM1 = SMPmakeElt(matrix, pEqnBR, pEqnBL);
#endif
#ifdef KLU
pNode->fPPsijM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, psiEqnTR) ;
pNode->fPPsijM1Binding = NULL ;
#else
pNode->fPPsijM1 = SMPmakeElt(matrix, pEqnBR, psiEqnTR);
#endif
#ifdef KLU
pNode->fPPjM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, pEqnTR) ;
pNode->fPPjM1Binding = NULL ;
#else
pNode->fPPjM1 = SMPmakeElt(matrix, pEqnBR, pEqnTR);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiM1jM1 = spGetElement( matrix, pEqnBR, psiEqnTL );
pNode->fPPiM1jM1 = spGetElement( matrix, pEqnBR, pEqnTL );
#ifdef KLU
pNode->fPPsiiM1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, psiEqnTL) ;
pNode->fPPsiiM1jM1Binding = NULL ;
#else
pNode->fPPsiiM1jM1 = SMPmakeElt(matrix, pEqnBR, psiEqnTL);
#endif
#ifdef KLU
pNode->fPPiM1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBR, pEqnTL) ;
pNode->fPPiM1jM1Binding = NULL ;
#else
pNode->fPPiM1jM1 = SMPmakeElt(matrix, pEqnBR, pEqnTL);
#endif
}
}
pNode = pElem->pBLNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, psiEqnBL, psiEqnBR );
pNode->fPsiPsijM1 = spGetElement(matrix, psiEqnBL, psiEqnTL );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnBR) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, psiEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, psiEqnBL, psiEqnTL) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, psiEqnBL, psiEqnTL);
#endif
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
pNode->fPPsiiP1 = spGetElement( matrix, pEqnBL, psiEqnBR );
pNode->fPPiP1 = spGetElement( matrix, pEqnBL, pEqnBR );
pNode->fPPsijM1 = spGetElement( matrix, pEqnBL, psiEqnTL );
pNode->fPPjM1 = spGetElement( matrix, pEqnBL, pEqnTL );
#ifdef KLU
pNode->fPPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, psiEqnBR) ;
pNode->fPPsiiP1Binding = NULL ;
#else
pNode->fPPsiiP1 = SMPmakeElt(matrix, pEqnBL, psiEqnBR);
#endif
#ifdef KLU
pNode->fPPiP1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, pEqnBR) ;
pNode->fPPiP1Binding = NULL ;
#else
pNode->fPPiP1 = SMPmakeElt(matrix, pEqnBL, pEqnBR);
#endif
#ifdef KLU
pNode->fPPsijM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, psiEqnTL) ;
pNode->fPPsijM1Binding = NULL ;
#else
pNode->fPPsijM1 = SMPmakeElt(matrix, pEqnBL, psiEqnTL);
#endif
#ifdef KLU
pNode->fPPjM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, pEqnTL) ;
pNode->fPPjM1Binding = NULL ;
#else
pNode->fPPjM1 = SMPmakeElt(matrix, pEqnBL, pEqnTL);
#endif
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
pNode->fPPsiiP1jM1 = spGetElement( matrix, pEqnBL, psiEqnTR );
pNode->fPPiP1jM1 = spGetElement( matrix, pEqnBL, pEqnTR );
#ifdef KLU
pNode->fPPsiiP1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, psiEqnTR) ;
pNode->fPPsiiP1jM1Binding = NULL ;
#else
pNode->fPPsiiP1jM1 = SMPmakeElt(matrix, pEqnBL, psiEqnTR);
#endif
#ifdef KLU
pNode->fPPiP1jM1 = SMPmakeEltKLUforCIDER (matrix, pEqnBL, pEqnTR) ;
pNode->fPPiP1jM1Binding = NULL ;
#else
pNode->fPPiP1jM1 = SMPmakeElt(matrix, pEqnBL, pEqnTR);
#endif
}
}
}
@ -199,27 +432,135 @@ void
pEqn = pNode->pEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiInP1 = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOxP1 = spGetElement( matrix, pEqn, psiEqnOxP );
#ifdef KLU
pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
pNode->fPPsiInBinding = NULL ;
#else
pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fPPsiInP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
pNode->fPPsiInP1Binding = NULL ;
#else
pNode->fPPsiInP1 = SMPmakeElt(matrix, pEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
pNode->fPPsiOxBinding = NULL ;
#else
pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fPPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
pNode->fPPsiOxP1Binding = NULL ;
#else
pNode->fPPsiOxP1 = SMPmakeElt(matrix, pEqn, psiEqnOxP);
#endif
} else { /* Right Side */
pNode->fPPsiInM1 = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOxM1 = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxP );
#ifdef KLU
pNode->fPPsiInM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
pNode->fPPsiInM1Binding = NULL ;
#else
pNode->fPPsiInM1 = SMPmakeElt(matrix, pEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
pNode->fPPsiInBinding = NULL ;
#else
pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fPPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
pNode->fPPsiOxM1Binding = NULL ;
#else
pNode->fPPsiOxM1 = SMPmakeElt(matrix, pEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
pNode->fPPsiOxBinding = NULL ;
#else
pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxP);
#endif
}
} else { /* Horizontal Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiInP1 = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOxP1 = spGetElement( matrix, pEqn, psiEqnOxP );
// <<<<<<< HEAD
// if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
// pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInM );
// pNode->fPPsiInP1 = spGetElement( matrix, pEqn, psiEqnInP );
// pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxM );
// pNode->fPPsiOxP1 = spGetElement( matrix, pEqn, psiEqnOxP );
// =======
// if ( nIndex <= 1 ) { /* Top Side */
//
// #ifdef KLU
// pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
// pNode->fPPsiInBinding = NULL ;
// #else
// pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInM);
// #endif
//
// #ifdef KLU
// pNode->fPPsiInP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
// pNode->fPPsiInP1Binding = NULL ;
// #else
// pNode->fPPsiInP1 = SMPmakeElt(matrix, pEqn, psiEqnInP);
// #endif
//
// #ifdef KLU
// pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
// pNode->fPPsiOxBinding = NULL ;
// #else
// pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxM);
// #endif
//
// #ifdef KLU
// pNode->fPPsiOxP1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
// pNode->fPPsiOxP1Binding = NULL ;
// #else
// pNode->fPPsiOxP1 = SMPmakeElt(matrix, pEqn, psiEqnOxP);
// #endif
//
// >>>>>>> First KLU support of CIDER TWOD simulations
} else { /* Bottom Side */
pNode->fPPsiInM1 = spGetElement( matrix, pEqn, psiEqnInM );
pNode->fPPsiIn = spGetElement( matrix, pEqn, psiEqnInP );
pNode->fPPsiOxM1 = spGetElement( matrix, pEqn, psiEqnOxM );
pNode->fPPsiOx = spGetElement( matrix, pEqn, psiEqnOxP );
#ifdef KLU
pNode->fPPsiInM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInM) ;
pNode->fPPsiInM1Binding = NULL ;
#else
pNode->fPPsiInM1 = SMPmakeElt(matrix, pEqn, psiEqnInM);
#endif
#ifdef KLU
pNode->fPPsiIn = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnInP) ;
pNode->fPPsiInBinding = NULL ;
#else
pNode->fPPsiIn = SMPmakeElt(matrix, pEqn, psiEqnInP);
#endif
#ifdef KLU
pNode->fPPsiOxM1 = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxM) ;
pNode->fPPsiOxM1Binding = NULL ;
#else
pNode->fPPsiOxM1 = SMPmakeElt(matrix, pEqn, psiEqnOxM);
#endif
#ifdef KLU
pNode->fPPsiOx = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqnOxP) ;
pNode->fPPsiOxBinding = NULL ;
#else
pNode->fPPsiOx = SMPmakeElt(matrix, pEqn, psiEqnOxP);
#endif
}
}
} /* endfor nIndex */
@ -229,6 +570,256 @@ void
} /* endif SurfaceMobility */
}
#ifdef KLU
void
TWOPbindCSC (TWOdevice *pDevice)
{
TWOelem *pElem;
TWOnode *pNode;
TWOchannel *pCh;
BindKluElementCOO i, *matched, *BindStruct, *BindStructCSC ;
int index ;
size_t nz ;
int eIndex, nIndex;
int nextIndex; /* index of node to find next element */
int psiEqn, pEqn; /* scratch for deref'd eqn numbers */
int psiEqnTL = 0, pEqnTL = 0;
int psiEqnTR = 0, pEqnTR = 0;
int psiEqnBR = 0, pEqnBR = 0;
int psiEqnBL = 0, pEqnBL = 0;
int psiEqnInM = 0, psiEqnInP = 0; /* scratch for deref'd surface eqns */
int psiEqnOxM = 0, psiEqnOxP = 0; /* M= more negative, P= more positive */
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructCOO ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindKluElementCOO *) malloc (nz * sizeof(BindKluElementCOO)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
/* first the self terms */
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
/* get poisson-only pointer */
psiEqn = pNode->psiEqn;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, psiEqn, psiEqn) ;
if ( pElem->elemType == SEMICON ) {
/* get continuity-coupling terms */
pEqn = pNode->pEqn;
pNode->nEqn = 0;
/* pointers for additional terms */
CREATE_KLU_BINDING_TABLE_CIDER(fPsiP, fPsiPBinding, psiEqn, pEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsi, fPPsiBinding, pEqn, psiEqn) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPP, fPPBinding, pEqn, pEqn) ;
} else {
pEqn = 0;
}
/* save equation indices */
switch ( nIndex ) {
case 0: /* TL Node */
psiEqnTL = psiEqn;
pEqnTL = pEqn;
break;
case 1: /* TR Node */
psiEqnTR = psiEqn;
pEqnTR = pEqn;
break;
case 2: /* BR Node */
psiEqnBR = psiEqn;
pEqnBR = pEqn;
break;
case 3: /* BL Node */
psiEqnBL = psiEqn;
pEqnBL = pEqn;
break;
default:
break;
}
}
/* now terms to couple to adjacent nodes */
pNode = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTL, psiEqnBL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1, fPPsiiP1Binding, pEqnTL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1, fPPiP1Binding, pEqnTL, pEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijP1, fPPsijP1Binding, pEqnTL, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjP1, fPPjP1Binding, pEqnTL, pEqnBL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1jP1, fPPsiiP1jP1Binding, pEqnTL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1jP1, fPPiP1jP1Binding, pEqnTL, pEqnBR) ;
}
}
pNode = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, psiEqnTR, psiEqnBR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1, fPPsiiM1Binding, pEqnTR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1, fPPiM1Binding, pEqnTR, pEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijP1, fPPsijP1Binding, pEqnTR, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjP1, fPPjP1Binding, pEqnTR, pEqnBR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1jP1, fPPsiiM1jP1Binding, pEqnTR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1jP1, fPPiM1jP1Binding, pEqnTR, pEqnBL) ;
}
}
pNode = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, psiEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBR, psiEqnTR) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1, fPPsiiM1Binding, pEqnBR, psiEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1, fPPiM1Binding, pEqnBR, pEqnBL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijM1, fPPsijM1Binding, pEqnBR, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjM1, fPPjM1Binding, pEqnBR, pEqnTR) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiM1jM1, fPPsiiM1jM1Binding, pEqnBR, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiM1jM1, fPPiM1jM1Binding, pEqnBR, pEqnTL) ;
}
}
pNode = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, psiEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, psiEqnBL, psiEqnTL) ;
if ( pElem->elemType == SEMICON ) {
/* continuity equation pointers */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1, fPPsiiP1Binding, pEqnBL, psiEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1, fPPiP1Binding, pEqnBL, pEqnBR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsijM1, fPPsijM1Binding, pEqnBL, psiEqnTL) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPjM1, fPPjM1Binding, pEqnBL, pEqnTL) ;
/* Surface Mobility Model depends on diagonal node values */
if ( MobDeriv && SurfaceMobility && pElem->channel ) {
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiiP1jM1, fPPsiiP1jM1Binding, pEqnBL, psiEqnTR) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPiP1jM1, fPPiP1jM1Binding, pEqnBL, pEqnTR) ;
}
}
}
/*
* Add terms for surface-field of inversion-layer mobility model.
* Elements MUST be made from silicon for this to work.
* No empty elements are allowed.
* Don't need these pointers if SurfaceMobility isn't set.
*/
if ( MobDeriv && SurfaceMobility ) {
for ( pCh = pDevice->pChannel; pCh != NULL;
pCh = pCh->next ) {
pElem = pCh->pNElem;
switch (pCh->type) {
case 0:
psiEqnInM = pElem->pBLNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pTRNode->psiEqn;
break;
case 1:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pBLNode->psiEqn;
psiEqnOxM = pElem->pTRNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 2:
psiEqnInM = pElem->pTLNode->psiEqn;
psiEqnInP = pElem->pTRNode->psiEqn;
psiEqnOxM = pElem->pBLNode->psiEqn;
psiEqnOxP = pElem->pBRNode->psiEqn;
break;
case 3:
psiEqnInM = pElem->pTRNode->psiEqn;
psiEqnInP = pElem->pBRNode->psiEqn;
psiEqnOxM = pElem->pTLNode->psiEqn;
psiEqnOxP = pElem->pBLNode->psiEqn;
break;
}
pElem = pCh->pSeed;
nextIndex = (pCh->type + 2)%4;
while (pElem && pElem->channel == pCh->id) {
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
pNode = pElem->pNodes[ nIndex ];
psiEqn = pNode->psiEqn;
pEqn = pNode->pEqn;
if ( pCh->type % 2 == 0 ) { /* Vertical Slice */
if ( nIndex == 0 || nIndex == 3 ) { /* Left Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInP1, fPPsiInP1Binding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxP1, fPPsiOxP1Binding, pEqn, psiEqnOxP) ;
} else { /* Right Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInM1, fPPsiInM1Binding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxM1, fPPsiOxM1Binding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxP) ;
}
} else { /* Horizontal Slice */
if ( nIndex <= 1 ) { /* Top Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInP1, fPPsiInP1Binding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxP1, fPPsiOxP1Binding, pEqn, psiEqnOxP) ;
} else { /* Bottom Side */
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInM1, fPPsiInM1Binding, pEqn, psiEqnInM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInP) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOxM1, fPPsiOxM1Binding, pEqn, psiEqnOxM) ;
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiOx, fPPsiOxBinding, pEqn, psiEqnOxP) ;
}
}
} /* endfor nIndex */
pElem = pElem->pElems[ nextIndex ];
} /* endwhile pElem */
} /* endfor pCh */
} /* endif SurfaceMobility */
free (BindStructCSC) ;
}
#endif
/*
* The Jacobian and Rhs are loaded by the following function.
@ -268,7 +859,17 @@ void
}
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
@ -432,7 +1033,17 @@ void
TWOPcommonTerms( pDevice, FALSE, FALSE, NULL );
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];

View File

@ -13,6 +13,9 @@ Author: 1991 David A. Gates, U. C. Berkeley CAD Group
#include "twoddefs.h"
#include "twodext.h"
#ifdef KLU
#include "ngspice/klu-binding.h"
#endif
/* functions to setup and solve the 2D poisson equation */
@ -31,7 +34,14 @@ TWOQjacBuild(TWOdevice *pDevice)
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
if ( pElem->evalNodes[ nIndex ] ) {
pNode = pElem->pNodes[ nIndex ];
pNode->fPsiPsi = spGetElement( matrix, pNode->poiEqn, pNode->poiEqn );
#ifdef KLU
pNode->fPsiPsi = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode->poiEqn) ;
pNode->fPsiPsiBinding = NULL ;
#else
pNode->fPsiPsi = SMPmakeElt(matrix, pNode->poiEqn, pNode->poiEqn);
#endif
}
}
}
@ -40,24 +50,80 @@ TWOQjacBuild(TWOdevice *pDevice)
pNode = pElem->pTLNode;
pNode1 = pElem->pTRNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pBLNode;
pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pTRNode;
pNode1 = pElem->pTLNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pBRNode;
pNode->fPsiPsijP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijP1Binding = NULL ;
#else
pNode->fPsiPsijP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pBRNode;
pNode1 = pElem->pBLNode;
pNode->fPsiPsiiM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiM1Binding = NULL ;
#else
pNode->fPsiPsiiM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pTRNode;
pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode = pElem->pBLNode;
pNode1 = pElem->pBRNode;
pNode->fPsiPsiiP1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsiiP1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsiiP1Binding = NULL ;
#else
pNode->fPsiPsiiP1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
pNode1 = pElem->pTLNode;
pNode->fPsiPsijM1 = spGetElement(matrix, pNode->poiEqn, pNode1->poiEqn );
#ifdef KLU
pNode->fPsiPsijM1 = SMPmakeEltKLUforCIDER (matrix, pNode->poiEqn, pNode1->poiEqn) ;
pNode->fPsiPsijM1Binding = NULL ;
#else
pNode->fPsiPsijM1 = SMPmakeElt(matrix, pNode->poiEqn, pNode1->poiEqn);
#endif
}
/*
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
@ -91,6 +157,81 @@ TWOQjacBuild(TWOdevice *pDevice)
*/
}
#ifdef KLU
void
TWOQbindCSC (TWOdevice *pDevice)
{
TWOelem *pElem;
TWOnode *pNode, *pNode1;
int eIndex, nIndex;
int index ;
BindKluElementCOO i, *matched, *BindStruct, *BindStructCSC ;
size_t nz ;
BindStruct = pDevice->matrix->SMPkluMatrix->KLUmatrixBindStructCOO ;
nz = pDevice->matrix->SMPkluMatrix->KLUmatrixNZ ;
BindStructCSC = (BindKluElementCOO *) malloc (nz * sizeof(BindKluElementCOO)) ;
for (index = 0 ; index < (int)nz ; index++) {
BindStructCSC [index] = BindStruct [index] ;
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( nIndex = 0; nIndex <= 3; nIndex++ ) {
if ( pElem->evalNodes[ nIndex ] ) {
pNode = pElem->pNodes[ nIndex ];
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsi, fPsiPsiBinding, pNode->poiEqn, pNode->poiEqn) ;
}
}
}
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
pNode = pElem->pTLNode;
pNode1 = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pTRNode;
pNode1 = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijP1, fPsiPsijP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pBRNode;
pNode1 = pElem->pBLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiM1, fPsiPsiiM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pTRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode = pElem->pBLNode;
pNode1 = pElem->pBRNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsiiP1, fPsiPsiiP1Binding, pNode->poiEqn, pNode1->poiEqn) ;
pNode1 = pElem->pTLNode;
CREATE_KLU_BINDING_TABLE_CIDER(fPsiPsijM1, fPsiPsijM1Binding, pNode->poiEqn, pNode1->poiEqn) ;
}
free (BindStructCSC) ;
}
#endif
void
TWOQsysLoad(TWOdevice *pDevice)
{
@ -109,7 +250,17 @@ TWOQsysLoad(TWOdevice *pDevice)
}
/* zero the matrix */
spClear( pDevice->matrix );
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
SMPclearKLUforCIDER (pDevice->matrix) ;
} else {
#endif
SMPclear(pDevice->matrix);
#ifdef KLU
}
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];

View File

@ -52,8 +52,13 @@ void NUMD2project(TWOdevice *pDevice, double delV)
}
incVpn = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pContact );
spSolve( pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL );
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVpn, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVpn) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -131,8 +136,13 @@ void NBJT2project(TWOdevice *pDevice, double delVce, double delVbe)
if ( ABS( delVce ) > MIN_DELV ) {
incVce = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pColContact );
spSolve( pDevice->matrix, pDevice->rhs, incVce, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVce, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVce) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -175,8 +185,13 @@ void NBJT2project(TWOdevice *pDevice, double delVce, double delVbe)
if ( ABS( delVbe ) > MIN_DELV ) {
incVbe = pDevice->copiedSolution;
storeNewRhs( pDevice, pBaseContact );
spSolve( pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVbe, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVbe) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -265,8 +280,13 @@ void NUMOSproject(TWOdevice *pDevice, double delVdb, double delVsb,
incVdb = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pDContact );
spSolve( pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVdb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVdb) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -310,8 +330,13 @@ void NUMOSproject(TWOdevice *pDevice, double delVdb, double delVsb,
incVsb = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pSContact );
spSolve( pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVsb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVsb) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {
@ -354,8 +379,13 @@ void NUMOSproject(TWOdevice *pDevice, double delVdb, double delVsb,
incVgb = pDevice->dcDeltaSolution;
storeNewRhs( pDevice, pGContact );
spSolve( pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, incVgb, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, incVgb) ;
#endif
for ( eIndex = 1; eIndex <= pDevice->numElems; eIndex++ ) {
pElem = pDevice->elements[ eIndex ];
for ( index = 0; index <= 3; index++ ) {

View File

@ -92,7 +92,13 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
/* FACTOR */
startTime = SPfrontEnd->IFseconds();
error = spFactor(pDevice->matrix);
#ifdef KLU
error = SMPreorderKLUforCIDER (pDevice->matrix) ;
#else
error = SMPluFacForCIDER (pDevice->matrix) ;
#endif
factorTime += SPfrontEnd->IFseconds() - startTime;
if (newSolver) {
if (pDevice->iterationNumber == 1) {
@ -116,7 +122,7 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
if (foundError(error)) {
if (error == spSINGULAR) {
int badRow, badCol;
spWhereSingular(pDevice->matrix, &badRow, &badCol);
SMPgetError(pDevice->matrix, &badRow, &badCol);
printf("***** singular at (%d,%d)\n", badRow, badCol);
}
pDevice->converged = FALSE;
@ -126,7 +132,13 @@ TWOdcSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN newSolver,
/* SOLVE */
startTime = SPfrontEnd->IFseconds();
spSolve(pDevice->matrix, rhs, delta, NULL, NULL);
#ifdef KLU
SMPsolveKLUforCIDER (pDevice->matrix, rhs, delta, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, rhs, delta) ;
#endif
solveTime += SPfrontEnd->IFseconds() - startTime;
/* UPDATE */
@ -362,7 +374,13 @@ TWOresetJacobian(TWOdevice *pDevice)
printf("TWOresetJacobian: unknown carrier type\n");
exit(-1);
}
error = spFactor(pDevice->matrix);
#ifdef KLU
error = SMPreorderKLUforCIDER (pDevice->matrix) ;
#else
error = SMPluFacForCIDER (pDevice->matrix) ;
#endif
if (foundError(error)) {
exit(-1);
}
@ -464,7 +482,13 @@ int TWOequilSolve(TWOdevice *pDevice)
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
FREE(pDevice->rhsImag);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
/* FALLTHROUGH */
case SLV_NONE: {
/* Allocate memory needed for an equilibrium solution */
@ -476,15 +500,64 @@ int TWOequilSolve(TWOdevice *pDevice)
XCALLOC(pDevice->dcDeltaSolution, double, n_dim);
XCALLOC(pDevice->copiedSolution, double, n_dim);
XCALLOC(pDevice->rhs, double, n_dim);
pDevice->matrix = spCreate(n_eqn, 0, &error);
pDevice->matrix = TMALLOC (SMPmatrix, 1) ;
#ifdef KLU
pDevice->matrix->CKTkluMODE = CKTkluON ; /* Francesco Lannutti - To be sustitued with a value coming from the uplevel */
error = SMPnewMatrixKLUforCIDER (pDevice->matrix, pDevice->numEqns, CKTkluMatrixReal) ;
#else
error = SMPnewMatrixForCIDER (pDevice->matrix, pDevice->numEqns, 0) ;
#endif
if (error == spNO_MEMORY) {
(void) fprintf(cp_err, "TWOequilSolve: Out of Memory\n");
return E_NOMEM;
}
newSolver = TRUE;
spSetReal(pDevice->matrix); /* set to a real matrix */
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixReal ;
} else {
#endif
spSetReal (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
TWOQjacBuild(pDevice);
pDevice->numOrigEquil = spElementCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
/* Convert the COO Storage to CSC for KLU and Fill the Binding Table */
SMPconvertCOOtoCSCKLUforCIDER (pDevice->matrix) ;
/* Bind the KLU Pointers */
TWOQbindCSC (pDevice) ;
/* Perform KLU Matrix Analysis */
pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)pDevice->matrix->SMPkluMatrix->KLUmatrixN, pDevice->matrix->SMPkluMatrix->KLUmatrixAp,
pDevice->matrix->SMPkluMatrix->KLUmatrixAi, pDevice->matrix->SMPkluMatrix->KLUmatrixCommon) ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
printf ("CIDER: KLU Failed\n") ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
return ; // Francesco Lannutti - Fix KLU return values
}
}
printf ("CIDER: KLU to be fixed: spElementCount\n") ;
pDevice->numOrigEquil = 0 ; // Francesco Lannutti - Fix for KLU
} else {
pDevice->numOrigEquil = spElementCount (pDevice->matrix->SPmatrix) ;
}
#else
pDevice->numOrigEquil = spElementCount (pDevice->matrix->SPmatrix) ;
#endif
pDevice->numFillEquil = 0;
pDevice->solverType = SLV_EQUIL;
break;
@ -504,7 +577,21 @@ int TWOequilSolve(TWOdevice *pDevice)
/* MISCELLANEOUS */
startTime = SPfrontEnd->IFseconds();
if (newSolver) {
pDevice->numFillEquil = spFillinCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - Fix for KLU
printf ("CIDER: KLU to be fixed: spFillinCount\n") ;
pDevice->numFillEquil = 0 ;
} else {
#endif
pDevice->numFillEquil = spFillinCount(pDevice->matrix->SPmatrix);
#ifdef KLU
}
#endif
}
if (pDevice->converged) {
TWOQcommonTerms(pDevice);
@ -557,7 +644,13 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
FREE(pDevice->dcDeltaSolution);
FREE(pDevice->copiedSolution);
FREE(pDevice->rhs);
spDestroy(pDevice->matrix);
#ifdef KLU
SMPdestroyKLUforCIDER (pDevice->matrix) ;
#else
SMPdestroy (pDevice->matrix) ;
#endif
/* FALLTHROUGH */
case SLV_NONE:
/* Set up for bias */
@ -568,7 +661,16 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
XCALLOC(pDevice->copiedSolution, double, pDevice->dimBias);
XCALLOC(pDevice->rhs, double, pDevice->dimBias);
XCALLOC(pDevice->rhsImag, double, pDevice->dimBias);
pDevice->matrix = spCreate(pDevice->numEqns, 1, &error);
pDevice->matrix = TMALLOC (SMPmatrix, 1) ;
#ifdef KLU
pDevice->matrix->CKTkluMODE = CKTkluON ; /* Francesco Lannutti - To be sustitued with a value coming from the uplevel */
error = SMPnewMatrixKLUforCIDER (pDevice->matrix, pDevice->numEqns, CKTkluMatrixComplex) ;
#else
error = SMPnewMatrixForCIDER (pDevice->matrix, pDevice->numEqns, 1) ;
#endif
if (error == spNO_MEMORY) {
printf("TWObiasSolve: Out of Memory\n");
exit(-1);
@ -581,12 +683,56 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
} else if (OneCarrier == P_TYPE) {
TWOPjacBuild(pDevice);
}
pDevice->numOrigBias = spElementCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
/* Convert the COO Storage to CSC for KLU and Fill the Binding Table */
SMPconvertCOOtoCSCKLUforCIDER (pDevice->matrix) ;
/* Bind the KLU Pointers */
if (!OneCarrier) {
TWObindCSC (pDevice) ;
} else if (OneCarrier == N_TYPE) {
TWONbindCSC (pDevice) ;
} else if (OneCarrier == P_TYPE) {
TWOPbindCSC (pDevice) ;
}
/* Perform KLU Matrix Analysis */
pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic = klu_analyze ((int)pDevice->matrix->SMPkluMatrix->KLUmatrixN, pDevice->matrix->SMPkluMatrix->KLUmatrixAp,
pDevice->matrix->SMPkluMatrix->KLUmatrixAi, pDevice->matrix->SMPkluMatrix->KLUmatrixCommon) ;
if (pDevice->matrix->SMPkluMatrix->KLUmatrixSymbolic == NULL) {
if (pDevice->matrix->SMPkluMatrix->KLUmatrixCommon->status == KLU_EMPTY_MATRIX) {
printf ("CIDER: KLU failed\n") ;
return ; // Francesco Lannutti - Fix KLU return values
}
}
pDevice->numOrigBias = 0 ; // Francesco Lannutti - Fix for KLU
} else {
pDevice->numOrigBias = spElementCount(pDevice->matrix->SPmatrix);
}
#else
pDevice->numOrigBias = spElementCount (pDevice->matrix->SPmatrix) ;
#endif
pDevice->numFillBias = 0;
TWOstoreInitialGuess(pDevice);
/* FALLTHROUGH */
case SLV_SMSIG:
spSetReal(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = CKTkluMatrixReal ;
} else {
#endif
spSetReal (pDevice->matrix->SPmatrix) ;
#ifdef KLU
}
#endif
pDevice->solverType = SLV_BIAS;
break;
case SLV_BIAS:
@ -604,7 +750,21 @@ TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis,
/* MISCELLANEOUS */
startTime = SPfrontEnd->IFseconds();
if (newSolver) {
pDevice->numFillBias = spFillinCount(pDevice->matrix);
#ifdef KLU
if (pDevice->matrix->CKTkluMODE) {
// Francesco Lannutti - Fix for KLU
printf ("CIDER: KLU to be fixed: spFillinCount\n") ;
pDevice->numFillBias = 0 ;
} else {
#endif
pDevice->numFillBias = spFillinCount (pDevice->matrix->SPmatrix) ; // Francesco Lannutti - Fix for KLU
#ifdef KLU
}
#endif
}
if ((!pDevice->converged) && iterationLimit > 1) {
printf("TWObiasSolve: No Convergence\n");
@ -1142,9 +1302,12 @@ TWOnuNorm(TWOdevice *pDevice)
int index;
/* the LU Decomposed matrix is available. use it to calculate x */
spSolve(pDevice->matrix, pDevice->rhs, pDevice->rhsImag,
NULL, NULL);
#ifdef KLU
printf ("CIDER: KLU to be fixed TWOnuNorm\n") ;
SMPsolveKLUforCIDER (pDevice->matrix, pDevice->rhs, pDevice->rhsImag, NULL, NULL) ;
#else
SMPsolveForCIDER (pDevice->matrix, pDevice->rhs, pDevice->rhsImag) ;
#endif
/* the solution is in the rhsImag vector */
/* compute L2-norm of the rhsImag vector */
@ -1202,7 +1365,14 @@ TWOjacCheck(TWOdevice *pDevice, BOOLEAN tranAnalysis, TWOtranInfo *info)
pDevice->dcSolution[index] = pDevice->copiedSolution[index];
for (rIndex = 1; rIndex <= pDevice->numEqns; rIndex++) {
diff = (pDevice->rhsImag[rIndex] - pDevice->rhs[rIndex]) / del;
dptr = spFindElement(pDevice->matrix, rIndex, index);
#ifdef KLU
printf ("CIDER: KLU to be fixed: spFindElement") ;
dptr = NULL ;
#else
dptr = spFindElement(pDevice->matrix->SPmatrix, rIndex, index); // Francesco Lannutti - Fix for KLU
#endif
if (dptr != NULL) {
tol = (1e-4 * pDevice->abstol) + (1e-2 * MAX(ABS(diff), ABS(*dptr)));
if ((diff != 0.0) && (ABS(diff - *dptr) > tol)) {

View File

@ -16,6 +16,10 @@ Authors: 1987 Karti Mayaram, 1991 David Gates
#include "ngspice/material.h"
#ifdef KLU
#include "ngspice/klu.h"
#endif
typedef struct sTWOelem
{
struct sTWOelem *pElems[4]; /* array to store the element neighbors */
@ -44,6 +48,20 @@ typedef struct sTWOelem
int direction; /* direction of flow for channels */
int evalNodes[4]; /* nodes to be evaluated in elem */
int evalEdges[4]; /* edges to be evaluated in elem */
#ifdef KLU
double *KLUleftLeftNode ;
double *KLUleftRightNode ;
double *KLUrightLeftNode ;
double *KLUrightRightNode ;
BindKluElementCOO *KLUleftLeftNodeBinding ;
BindKluElementCOO *KLUleftRightNodeBinding ;
BindKluElementCOO *KLUrightLeftNodeBinding ;
BindKluElementCOO *KLUrightRightNodeBinding ;
#endif
} TWOelem;
#define pTopElem pElems[0]
@ -193,6 +211,67 @@ typedef struct sTWOnode {
double *fPPsiOxM1;
double *fPPsiOx;
double *fPPsiOxP1;
#ifdef KLU
BindKluElementCOO *fPsiPsiBinding ;
BindKluElementCOO *fPsiNBinding ;
BindKluElementCOO *fPsiPBinding ;
BindKluElementCOO *fNPsiBinding ;
BindKluElementCOO *fNNBinding ;
BindKluElementCOO *fNPBinding ;
BindKluElementCOO *fPPsiBinding ;
BindKluElementCOO *fPNBinding ;
BindKluElementCOO *fPPBinding ;
BindKluElementCOO *fPsiPsiiP1Binding ;
BindKluElementCOO *fPsiPsijP1Binding ;
BindKluElementCOO *fNPsiiP1Binding ;
BindKluElementCOO *fNNiP1Binding ;
BindKluElementCOO *fNPsijP1Binding ;
BindKluElementCOO *fNNjP1Binding ;
BindKluElementCOO *fPPsiiP1Binding ;
BindKluElementCOO *fPPiP1Binding ;
BindKluElementCOO *fPPsijP1Binding ;
BindKluElementCOO *fPPjP1Binding ;
BindKluElementCOO *fNPsiiP1jP1Binding ;
BindKluElementCOO *fNNiP1jP1Binding ;
BindKluElementCOO *fPPsiiP1jP1Binding ;
BindKluElementCOO *fPPiP1jP1Binding ;
BindKluElementCOO *fPsiPsiiM1Binding ;
BindKluElementCOO *fNPsiiM1Binding ;
BindKluElementCOO *fNNiM1Binding ;
BindKluElementCOO *fPPsiiM1Binding ;
BindKluElementCOO *fPPiM1Binding ;
BindKluElementCOO *fNPsiiM1jP1Binding ;
BindKluElementCOO *fNNiM1jP1Binding ;
BindKluElementCOO *fPPsiiM1jP1Binding ;
BindKluElementCOO *fPPiM1jP1Binding ;
BindKluElementCOO *fPsiPsijM1Binding ;
BindKluElementCOO *fNPsijM1Binding ;
BindKluElementCOO *fNNjM1Binding ;
BindKluElementCOO *fPPsijM1Binding ;
BindKluElementCOO *fPPjM1Binding ;
BindKluElementCOO *fNPsiiM1jM1Binding ;
BindKluElementCOO *fNNiM1jM1Binding ;
BindKluElementCOO *fPPsiiM1jM1Binding ;
BindKluElementCOO *fPPiM1jM1Binding ;
BindKluElementCOO *fNPsiiP1jM1Binding ;
BindKluElementCOO *fNNiP1jM1Binding ;
BindKluElementCOO *fPPsiiP1jM1Binding ;
BindKluElementCOO *fPPiP1jM1Binding ;
BindKluElementCOO *fNPsiInBinding ;
BindKluElementCOO *fNPsiInP1Binding ;
BindKluElementCOO *fNPsiOxBinding ;
BindKluElementCOO *fNPsiOxP1Binding ;
BindKluElementCOO *fPPsiInBinding ;
BindKluElementCOO *fPPsiInP1Binding ;
BindKluElementCOO *fPPsiOxBinding ;
BindKluElementCOO *fPPsiOxP1Binding ;
BindKluElementCOO *fNPsiInM1Binding ;
BindKluElementCOO *fNPsiOxM1Binding ;
BindKluElementCOO *fPPsiInM1Binding ;
BindKluElementCOO *fPPsiOxM1Binding ;
#endif
} TWOnode;
#define pTLElem pElems[0]