From 8a8adfe451500dead320d0607a3594dc57691142 Mon Sep 17 00:00:00 2001 From: Francesco Lannutti Date: Mon, 1 Jun 2020 16:15:55 +0200 Subject: [PATCH] First KLU support of CIDER TWOD simulations --- src/ciderlib/twod/twoadmit.c | 438 +++++++++---- src/ciderlib/twod/twocond.c | 47 +- src/ciderlib/twod/twocont.c | 1138 ++++++++++++++++++++++++++++++--- src/ciderlib/twod/twodest.c | 16 +- src/ciderlib/twod/twodext.h | 7 + src/ciderlib/twod/twoncont.c | 722 +++++++++++++++++++-- src/ciderlib/twod/twopcont.c | 721 +++++++++++++++++++-- src/ciderlib/twod/twopoiss.c | 171 ++++- src/ciderlib/twod/twoproj.c | 54 +- src/ciderlib/twod/twosolve.c | 206 +++++- src/include/ngspice/twomesh.h | 79 +++ 11 files changed, 3213 insertions(+), 386 deletions(-) diff --git a/src/ciderlib/twod/twoadmit.c b/src/ciderlib/twod/twoadmit.c index bf877639c..058e93976 100644 --- a/src/ciderlib/twod/twoadmit.c +++ b/src/ciderlib/twod/twoadmit.c @@ -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); + } } - } + } } } + +#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 - spFactor(pDevice->matrix); - spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag); 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); + } } - } + } } } + +#ifdef KLU } +#endif - spFactor(pDevice->matrix); - spSolve(pDevice->matrix, rhsReal, solnReal, rhsImag, solnImag); +#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); diff --git a/src/ciderlib/twod/twocond.c b/src/ciderlib/twod/twocond.c index cd717b535..a9c763d31 100644 --- a/src/ciderlib/twod/twocond.c +++ b/src/ciderlib/twod/twocond.c @@ -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 ); diff --git a/src/ciderlib/twod/twocont.c b/src/ciderlib/twod/twocont.c index 590dffe27..087fd8c06 100644 --- a/src/ciderlib/twod/twocont.c +++ b/src/ciderlib/twod/twocont.c @@ -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,21 +57,76 @@ 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; pEqn = pNode->pEqn; /* pointers for additional terms */ - pNode->fPsiN = spGetElement( matrix, psiEqn, nEqn ); - pNode->fPsiP = spGetElement( matrix, psiEqn, pEqn ); - pNode->fNPsi = spGetElement( matrix, nEqn, psiEqn ); - pNode->fNN = spGetElement( matrix, nEqn, nEqn ); - pNode->fNP = spGetElement( matrix, nEqn, pEqn ); - pNode->fPPsi = spGetElement( matrix, pEqn, psiEqn ); - pNode->fPN = spGetElement( matrix, pEqn, nEqn ); - pNode->fPP = spGetElement( matrix, pEqn, pEqn ); + +#ifdef KLU + pNode->fPsiN = SMPmakeEltKLUforCIDER (matrix, psiEqn, nEqn) ; + pNode->fPsiNBinding = NULL ; +#else + pNode->fPsiN = SMPmakeElt(matrix, psiEqn, nEqn); +#endif + +#ifdef KLU + pNode->fPsiP = SMPmakeEltKLUforCIDER (matrix, psiEqn, pEqn) ; + pNode->fPsiPBinding = NULL ; +#else + pNode->fPsiP = SMPmakeElt(matrix, psiEqn, pEqn); +#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 + +#ifdef KLU + pNode->fNP = SMPmakeEltKLUforCIDER (matrix, nEqn, pEqn) ; + pNode->fNPBinding = NULL ; +#else + pNode->fNP = SMPmakeElt(matrix, nEqn, pEqn); +#endif + +#ifdef KLU + pNode->fPPsi = SMPmakeEltKLUforCIDER (matrix, pEqn, psiEqn) ; + pNode->fPPsiBinding = NULL ; +#else + pNode->fPPsi = SMPmakeElt(matrix, pEqn, psiEqn); +#endif + +#ifdef KLU + pNode->fPN = SMPmakeEltKLUforCIDER (matrix, pEqn, nEqn) ; + pNode->fPNBinding = NULL ; +#else + pNode->fPN = SMPmakeElt(matrix, pEqn, nEqn); +#endif + +#ifdef KLU + pNode->fPP = SMPmakeEltKLUforCIDER (matrix, pEqn, pEqn) ; + pNode->fPPBinding = NULL ; +#else + pNode->fPP = SMPmakeElt(matrix, pEqn, pEqn); +#endif + } else { nEqn = 0; pEqn = 0; @@ -101,90 +160,438 @@ 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 ); - 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->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 + +#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->fNPsiiP1jP1 = spGetElement( matrix, nEqnTL, psiEqnBR ); - pNode->fNNiP1jP1 = spGetElement( matrix, nEqnTL, nEqnBR ); - pNode->fPPsiiP1jP1 = spGetElement( matrix, pEqnTL, psiEqnBR ); - pNode->fPPiP1jP1 = spGetElement( matrix, pEqnTL, pEqnBR ); + +#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 + +#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->fNPsiiM1 = spGetElement( matrix, nEqnTR, psiEqnTL ); - pNode->fNNiM1 = spGetElement( matrix, nEqnTR, nEqnTL ); - pNode->fNPsijP1 = spGetElement( matrix, nEqnTR, psiEqnBR ); - pNode->fNNjP1 = spGetElement( matrix, nEqnTR, nEqnBR ); - 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->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 + +#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->fNPsiiM1jP1 = spGetElement( matrix, nEqnTR, psiEqnBL ); - pNode->fNNiM1jP1 = spGetElement( matrix, nEqnTR, nEqnBL ); - pNode->fPPsiiM1jP1 = spGetElement( matrix, pEqnTR, psiEqnBL ); - pNode->fPPiM1jP1 = spGetElement( matrix, pEqnTR, pEqnBL ); + +#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 + +#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->fNPsiiM1 = spGetElement( matrix, nEqnBR, psiEqnBL ); - pNode->fNNiM1 = spGetElement( matrix, nEqnBR, nEqnBL ); - pNode->fNPsijM1 = spGetElement( matrix, nEqnBR, psiEqnTR ); - pNode->fNNjM1 = spGetElement( matrix, nEqnBR, nEqnTR ); - 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->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 + +#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->fNPsiiM1jM1 = spGetElement( matrix, nEqnBR, psiEqnTL ); - pNode->fNNiM1jM1 = spGetElement( matrix, nEqnBR, nEqnTL ); - pNode->fPPsiiM1jM1 = spGetElement( matrix, pEqnBR, psiEqnTL ); - pNode->fPPiM1jM1 = spGetElement( matrix, pEqnBR, pEqnTL ); + +#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 + +#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->fNPsiiP1 = spGetElement( matrix, nEqnBL, psiEqnBR ); - pNode->fNNiP1 = spGetElement( matrix, nEqnBL, nEqnBR ); - pNode->fNPsijM1 = spGetElement( matrix, nEqnBL, psiEqnTL ); - pNode->fNNjM1 = spGetElement( matrix, nEqnBL, nEqnTL ); - 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->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 + +#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->fNPsiiP1jM1 = spGetElement( matrix, nEqnBL, psiEqnTR ); - pNode->fNNiP1jM1 = spGetElement( matrix, nEqnBL, nEqnTR ); - pNode->fPPsiiP1jM1 = spGetElement( matrix, pEqnBL, psiEqnTR ); - pNode->fPPiP1jM1 = spGetElement( matrix, pEqnBL, pEqnTR ); + +#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 + +#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 + } } } @@ -234,43 +641,251 @@ void pEqn = pNode->pEqn; 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 ); - 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->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 + +#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->fNPsiInM1 = spGetElement( matrix, nEqn, psiEqnInM ); - pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInP ); - pNode->fNPsiOxM1 = spGetElement( matrix, nEqn, psiEqnOxM ); - pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxP ); - 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->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 + +#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->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM ); - pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP ); - pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM ); - pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP ); - 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->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInM ); +// pNode->fNPsiInP1 = spGetElement( matrix, nEqn, psiEqnInP ); +// pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxM ); +// pNode->fNPsiOxP1 = spGetElement( matrix, nEqn, psiEqnOxP ); +// 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->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 +// +// #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->fNPsiInM1 = spGetElement( matrix, nEqn, psiEqnInM ); - pNode->fNPsiIn = spGetElement( matrix, nEqn, psiEqnInP ); - pNode->fNPsiOxM1 = spGetElement( matrix, nEqn, psiEqnOxM ); - pNode->fNPsiOx = spGetElement( matrix, nEqn, psiEqnOxP ); - 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->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 + +#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 */ @@ -280,6 +895,307 @@ void } /* endif SurfaceMobility */ } +#ifdef KLU +void +TWObindCSC (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, pEqn; /* scratch for deref'd eqn numbers */ + int psiEqnTL = 0, nEqnTL = 0, pEqnTL = 0; + int psiEqnTR = 0, nEqnTR = 0, pEqnTR = 0; + int psiEqnBR = 0, nEqnBR = 0, pEqnBR = 0; + int psiEqnBL = 0, nEqnBL = 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 */ + nEqn = pNode->nEqn; + pEqn = pNode->pEqn; + /* pointers for additional terms */ + + CREATE_KLU_BINDING_TABLE_CIDER(fPsiN, fPsiNBinding, psiEqn, nEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fPsiP, fPsiPBinding, psiEqn, pEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNPsi, fNPsiBinding, nEqn, psiEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNN, fNNBinding, nEqn, nEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNP, fNPBinding, nEqn, pEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fPPsi, fPPsiBinding, pEqn, psiEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fPN, fPNBinding, pEqn, nEqn) ; + CREATE_KLU_BINDING_TABLE_CIDER(fPP, fPPBinding, pEqn, pEqn) ; + + } else { + nEqn = 0; + pEqn = 0; + } + /* save equation indices */ + switch ( nIndex ) { + case 0: /* TL Node */ + psiEqnTL = psiEqn; + nEqnTL = nEqn; + pEqnTL = pEqn; + break; + case 1: /* TR Node */ + psiEqnTR = psiEqn; + nEqnTR = nEqn; + pEqnTR = pEqn; + break; + case 2: /* BR Node */ + psiEqnBR = psiEqn; + nEqnBR = nEqn; + pEqnBR = pEqn; + break; + case 3: /* BL Node */ + psiEqnBL = psiEqn; + nEqnBL = nEqn; + 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(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) ; + 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(fNPsiiP1jP1, fNPsiiP1jP1Binding, nEqnTL, psiEqnBR) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1jP1, fNNiP1jP1Binding, nEqnTL, nEqnBR) ; + 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(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) ; + 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(fNPsiiM1jP1, fNPsiiM1jP1Binding, nEqnTR, psiEqnBL) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1jP1, fNNiM1jP1Binding, nEqnTR, nEqnBL) ; + 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(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) ; + 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(fNPsiiM1jM1, fNPsiiM1jM1Binding, nEqnBR, psiEqnTL) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNNiM1jM1, fNNiM1jM1Binding, nEqnBR, nEqnTL) ; + 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(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) ; + 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(fNPsiiP1jM1, fNPsiiP1jM1Binding, nEqnBL, psiEqnTR) ; + CREATE_KLU_BINDING_TABLE_CIDER(fNNiP1jM1, fNNiP1jM1Binding, nEqnBL, nEqnTR) ; + 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; + nEqn = pNode->nEqn; + pEqn = pNode->pEqn; + 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) ; + 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(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) ; + 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(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) ; + 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(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) ; + 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. @@ -320,7 +1236,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 ]; @@ -521,7 +1447,17 @@ void TWO_commonTerms( 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 ]; diff --git a/src/ciderlib/twod/twodest.c b/src/ciderlib/twod/twodest.c index e8e066469..537adc51d 100644 --- a/src/ciderlib/twod/twodest.c +++ b/src/ciderlib/twod/twodest.c @@ -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; diff --git a/src/ciderlib/twod/twodext.h b/src/ciderlib/twod/twodext.h index e4a3c2924..2af9e97d7 100644 --- a/src/ciderlib/twod/twodext.h +++ b/src/ciderlib/twod/twodext.h @@ -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 diff --git a/src/ciderlib/twod/twoncont.c b/src/ciderlib/twod/twoncont.c index d491e99cc..4884a3944 100644 --- a/src/ciderlib/twod/twoncont.c +++ b/src/ciderlib/twod/twoncont.c @@ -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 ]; diff --git a/src/ciderlib/twod/twopcont.c b/src/ciderlib/twod/twopcont.c index 6b2b81feb..f1166f088 100644 --- a/src/ciderlib/twod/twopcont.c +++ b/src/ciderlib/twod/twopcont.c @@ -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 ]; diff --git a/src/ciderlib/twod/twopoiss.c b/src/ciderlib/twod/twopoiss.c index 55c3d3c9b..fd39d53ea 100644 --- a/src/ciderlib/twod/twopoiss.c +++ b/src/ciderlib/twod/twopoiss.c @@ -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 ]; diff --git a/src/ciderlib/twod/twoproj.c b/src/ciderlib/twod/twoproj.c index 1905a1bd3..19c45a4a5 100644 --- a/src/ciderlib/twod/twoproj.c +++ b/src/ciderlib/twod/twoproj.c @@ -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++ ) { diff --git a/src/ciderlib/twod/twosolve.c b/src/ciderlib/twod/twosolve.c index 7be06a1fe..53dfe6c43 100644 --- a/src/ciderlib/twod/twosolve.c +++ b/src/ciderlib/twod/twosolve.c @@ -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)) { diff --git a/src/include/ngspice/twomesh.h b/src/include/ngspice/twomesh.h index c6f6cf662..6c07a777e 100644 --- a/src/include/ngspice/twomesh.h +++ b/src/include/ngspice/twomesh.h @@ -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]