/*ARGSUSED*/ int SMPluFac(SMPmatrix *Matrix, double PivTol, double Gmin) { spSetReal( (void *)Matrix ); LoadGmin( (void *)Matrix, Gmin ); return spFactor( (void *)Matrix ); }
/* * SMPreorder() */ int SMPreorder(SMPmatrix *Matrix, double PivTol, double PivRel, double Gmin) { spSetReal( (void *)Matrix ); LoadGmin( (void *)Matrix, Gmin ); return spOrderAndFactor( (void *)Matrix, (spREAL*)NULL, (spREAL)PivRel, (spREAL)PivTol, YES ); }
/* * SMPcombine() */ void SMPcombine(SMPmatrix *Matrix, double RHS[], double Spare[]) { spSetReal( (void *)Matrix ); spCombine( (void *)Matrix, RHS, Spare, (spREAL*)NULL, (spREAL*)NULL ); }
/* the equilibrium solution is taken as an initial guess */ void TWObiasSolve(TWOdevice *pDevice, int iterationLimit, BOOLEAN tranAnalysis, TWOtranInfo *info) { BOOLEAN newSolver = FALSE; int error; int index, eIndex; TWOelem *pElem; TWOnode *pNode; double refPsi; double startTime, setupTime, miscTime; setupTime = miscTime = 0.0; /* SETUP */ startTime = SPfrontEnd->IFseconds(); switch (pDevice->solverType) { case SLV_EQUIL: /* free up the vectors allocated in the equilibrium solution */ FREE(pDevice->dcSolution); FREE(pDevice->dcDeltaSolution); FREE(pDevice->copiedSolution); FREE(pDevice->rhs); spDestroy(pDevice->matrix); case SLV_NONE: pDevice->poissonOnly = FALSE; pDevice->numEqns = pDevice->dimBias - 1; XCALLOC(pDevice->dcSolution, double, pDevice->dimBias); XCALLOC(pDevice->dcDeltaSolution, double, pDevice->dimBias); 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); if (error == spNO_MEMORY) { printf("TWObiasSolve: Out of Memory\n"); exit(-1); } newSolver = TRUE; if (!OneCarrier) { TWO_jacBuild(pDevice); } else if (OneCarrier == N_TYPE) { TWONjacBuild(pDevice); } else if (OneCarrier == P_TYPE) { TWOPjacBuild(pDevice); } pDevice->numOrigBias = spElementCount(pDevice->matrix); pDevice->numFillBias = 0; TWOstoreInitialGuess(pDevice); case SLV_SMSIG: spSetReal(pDevice->matrix); case SLV_BIAS: pDevice->solverType = SLV_BIAS; break; default: fprintf(stderr, "Panic: Unknown solver type in bias solution.\n"); exit(-1); break; } setupTime += SPfrontEnd->IFseconds() - startTime; /* SOLVE */ TWOdcSolve(pDevice, iterationLimit, newSolver, tranAnalysis, info); /* MISCELLANEOUS */ startTime = SPfrontEnd->IFseconds(); if (newSolver) { pDevice->numFillBias = spFillinCount(pDevice->matrix); } if ((!pDevice->converged) && iterationLimit > 1) { printf("TWObiasSolve: No Convergence\n"); } else if (pDevice->converged) { /* update the nodal quantities */ for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) { pElem = pDevice->elements[eIndex]; refPsi = pElem->matlInfo->refPsi; for (index = 0; index <= 3; index++) { if (pElem->evalNodes[index]) { pNode = pElem->pNodes[index]; if (pNode->nodeType != CONTACT) { pNode->psi = pDevice->dcSolution[pNode->psiEqn]; if (pElem->elemType == SEMICON) { if (!OneCarrier) { pNode->nConc = pDevice->dcSolution[pNode->nEqn]; pNode->pConc = pDevice->dcSolution[pNode->pEqn]; } else if (OneCarrier == N_TYPE) { pNode->nConc = pDevice->dcSolution[pNode->nEqn]; pNode->pConc = pNode->nie * exp(-pNode->psi + refPsi); } else if (OneCarrier == P_TYPE) { pNode->pConc = pDevice->dcSolution[pNode->pEqn]; pNode->nConc = pNode->nie * exp(pNode->psi - refPsi); } } } } } } /* update the current terms */ if (!OneCarrier) { TWO_commonTerms(pDevice, FALSE, tranAnalysis, info); } else if (OneCarrier == N_TYPE) { TWONcommonTerms(pDevice, FALSE, tranAnalysis, info); } else if (OneCarrier == P_TYPE) { TWOPcommonTerms(pDevice, FALSE, tranAnalysis, info); } } else if (iterationLimit <= 1) { for (eIndex = 1; eIndex <= pDevice->numElems; eIndex++) { pElem = pDevice->elements[eIndex]; refPsi = pElem->matlInfo->refPsi; for (index = 0; index <= 3; index++) { if (pElem->evalNodes[index]) { pNode = pElem->pNodes[index]; if (pNode->nodeType != CONTACT) { pNode->psi = pDevice->dcSolution[pNode->psiEqn]; pDevice->devState0 [pNode->nodePsi] = pNode->psi; if (pElem->elemType == SEMICON) { if (!OneCarrier) { pNode->nConc = pDevice->dcSolution[pNode->nEqn]; pNode->pConc = pDevice->dcSolution[pNode->pEqn]; } else if (OneCarrier == N_TYPE) { pNode->nConc = pDevice->dcSolution[pNode->nEqn]; pNode->pConc = pNode->nie * exp(-pNode->psi + refPsi); } else if (OneCarrier == P_TYPE) { pNode->pConc = pDevice->dcSolution[pNode->pEqn]; pNode->nConc = pNode->nie * exp(pNode->psi - refPsi); } pDevice->devState0 [pNode->nodeN] = pNode->nConc; pDevice->devState0 [pNode->nodeP] = pNode->pConc; } } } } } } miscTime += SPfrontEnd->IFseconds() - startTime; if (tranAnalysis) { pDevice->pStats->setupTime[STAT_TRAN] += setupTime; pDevice->pStats->miscTime[STAT_TRAN] += miscTime; } else { pDevice->pStats->setupTime[STAT_DC] += setupTime; pDevice->pStats->miscTime[STAT_DC] += miscTime; } }
void TWOequilSolve(TWOdevice *pDevice) { BOOLEAN newSolver = FALSE; int error; int nIndex, eIndex; TWOelem *pElem; TWOnode *pNode; double startTime, setupTime, miscTime; setupTime = miscTime = 0.0; /* SETUP */ startTime = SPfrontEnd->IFseconds(); switch (pDevice->solverType) { case SLV_SMSIG: case SLV_BIAS: /* free up memory allocated for the bias solution */ FREE(pDevice->dcSolution); FREE(pDevice->dcDeltaSolution); FREE(pDevice->copiedSolution); FREE(pDevice->rhs); FREE(pDevice->rhsImag); spDestroy(pDevice->matrix); case SLV_NONE: pDevice->poissonOnly = TRUE; pDevice->numEqns = pDevice->dimEquil - 1; XCALLOC(pDevice->dcSolution, double, pDevice->dimEquil); XCALLOC(pDevice->dcDeltaSolution, double, pDevice->dimEquil); XCALLOC(pDevice->copiedSolution, double, pDevice->dimEquil); XCALLOC(pDevice->rhs, double, pDevice->dimEquil); pDevice->matrix = spCreate(pDevice->numEqns, 0, &error); if (error == spNO_MEMORY) { printf("TWOequilSolve: Out of Memory\n"); exit(-1); } newSolver = TRUE; spSetReal(pDevice->matrix); TWOQjacBuild(pDevice); pDevice->numOrigEquil = spElementCount(pDevice->matrix); pDevice->numFillEquil = 0; case SLV_EQUIL: pDevice->solverType = SLV_EQUIL; break; default: fprintf(stderr, "Panic: Unknown solver type in equil solution.\n"); exit(-1); break; } TWOstoreNeutralGuess(pDevice); setupTime += SPfrontEnd->IFseconds() - startTime; /* SOLVE */ TWOdcSolve(pDevice, MaxIterations, newSolver, FALSE, NULL); /* MISCELLANEOUS */ startTime = SPfrontEnd->IFseconds(); if (newSolver) { pDevice->numFillEquil = spFillinCount(pDevice->matrix); } if (pDevice->converged) { TWOQcommonTerms(pDevice); /* save equilibrium potential */ 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]; pNode->psi0 = pNode->psi; } } } } else { printf("TWOequilSolve: No Convergence\n"); } miscTime += SPfrontEnd->IFseconds() - startTime; pDevice->pStats->setupTime[STAT_SETUP] += setupTime; pDevice->pStats->miscTime[STAT_SETUP] += miscTime; }
int StanfordSolveSparseMatrix(Kentry* Kentries, double b[], int numUniqueEntries, int size, double soln[]) { int i; int row; int col; double value; spMatrix A; spError err, Error; spREAL AbsThreshold,RelThreshold; spREAL *pElement; #ifdef REALLY_OUTPUT_A_WHOLE_BUNCH FILE *fp; fp = NULL; fp = fopen("nonzero-inside-solver-call","w"); fprintf(fp,"title goes here (%i nonzero)\n",numUniqueEntries); fprintf(fp,"%i real\n",size); for (i = 0; i < numUniqueEntries; i++) { /* we add 1 to row and col numbers for sparse */ fprintf(fp,"%i %i %lf\n",Kentries[i].row+SPARSE_OFFSET,Kentries[i].col+SPARSE_OFFSET, Kentries[i].value); } fprintf(fp,"0 0 0.0\n"); for (i = 0; i < size; i++) { fprintf(fp,"%lf\n",b[i+SPARSE_OFFSET]); } fclose(fp); #endif /* create the matrix */ debugprint(stddbg," allocate A matrix.\n"); fflush(stdout); A = spCreate(size, 0, &err); if( err >= spFATAL || A == NULL) { fprintf(stderr,"error allocating matrix.\n"); exit(-1); } for (i = 0; i < numUniqueEntries; i++) { if (!(i % (int)(numUniqueEntries/50.0))) { debugprint(stddbg,"inserting into A: %i of %i\n",i,numUniqueEntries); } row = Kentries[i].row+SPARSE_OFFSET; col = Kentries[i].col+SPARSE_OFFSET; value = Kentries[i].value; pElement = spGetElement(A,row,col); if (pElement == NULL) { fprintf(stderr, "error: insufficient memory available.\n"); exit(-1); } *pElement = value; } debugprint(stddbg," free memory for Kentries\n"); deleteKentries(Kentries); spSetReal( A ); #if MODIFIED_NODAL spMNA_Preorder( A ); #endif RelThreshold = 0; AbsThreshold = 0; debugprint(stddbg," order and factor matrix.\n"); Error = spOrderAndFactor( A, b, RelThreshold, AbsThreshold, 1 ); if ( Error >= spFATAL ) { fprintf(stdout,"Fatal error (%i)\n",Error); exit(-1); } /* spPrint( A,1,1,1); */ for (i = 0; i <= size; i++) { soln[0] = 0; } debugprint(stddbg," call spSolve.\n"); spSolve( A, b, soln); debugprint(stddbg," destroy A.\n"); spDestroy(A); return 0; }
int main(int argc, char* argv[]) { int i; char title[1024]; char line[1024]; int size; int row; int col; double value; spMatrix A; spREAL x[4096]; spREAL b[4096]; spError err, Error; spREAL AbsThreshold,RelThreshold; spREAL *pElement; FILE *fp = NULL; if (argc != 2) { fprintf(stderr,"usage: sptest <matrix_filename>\n"); exit(-1); } fprintf(stdout,"Reading file [%s]\n",argv[1]); if ((fp = fopen(argv[1],"r")) == NULL) { fprintf(stderr,"Error opening file [%s]\n",argv[1]); exit(-1); } title[0]='\0'; fgets(title,1024,fp); fgets(line,1024,fp); if (sscanf(line,"%i real",&size) != 1) { fprintf(stderr,"Error reading size.\n"); exit(-1); } // create the matrix A = spCreate(size, 0, &err); if( err >= spFATAL || A == NULL) { fprintf(stderr,"error allocating matrix.\n"); exit(-1); } while (0 == 0) { line[0]='\0'; fgets(line,1024,fp); if (sscanf(line,"%i %i %lf",&row,&col,&value) != 3) { fprintf(stderr,"Error reading matrix.\n"); exit(-1); } if (row == 0 && col == 0) break; //spElement *pElement; pElement = spGetElement(A,row,col); if (pElement == NULL) { fprintf(stderr, "error: insufficient memory available.\n"); exit(-1); } *pElement = value; pElement = spGetElement(A,row,col); } b[0] = 0; for (i = 1; i <= size; i++) { line[0]='\0'; fgets(line,1024,fp); if (sscanf(line,"%lf",&value) != 1) { fprintf(stderr,"Error reading RHS.\n"); exit(-1); } b[i] = value; } spSetReal( A ); /*spPrint( A,1,1,1);*/ #if MODIFIED_NODAL spMNA_Preorder( A ); #endif RelThreshold = 0; AbsThreshold = 0; Error = spOrderAndFactor( A, b, RelThreshold, AbsThreshold, 1 ); if ( Error >= spFATAL ) { fprintf(stdout,"Fatal error (%i)\n",Error); exit(-1); } /*spPrint( A,1,1,1);*/ for (i = 0; i <= size; i++) { x[0] = 0; } spSolve( A, b, x); /* Print the Solution. */ for (i = 1; i <= size; i++) { fprintf(stdout,"diplacement[%i] = %lg\n",i,x[i]); } spDestroy(A); return 0; }