47 #include <Xyce_config.h>
64 #include <N_LAS_Vector.h>
65 #include <N_LAS_Matrix.h>
66 #include <N_LAS_System.h>
67 #include <N_LAS_Builder.h>
68 #include <N_UTL_Math.h>
75 typedef unsigned int UINT;
89 .setDescription(
"Location of base contact (necessary if running with three terminals).")
94 .setDescription(
"Cross sectional area of the device.")
100 .setDescription(
"Length scalar; adjust to mitigate convergence problems."
101 "The model will do all of its scaling automatically, so it is generally not "
102 "necessary to specify it manually.")
107 .setDescription(
"Density scalar; adjust to mitigate convergence problems."
108 "The model will do all of its scaling automatically, so it is generally not "
109 "necessary to specify it manually.")
114 .setDescription(
"Time scalar; adjust to mitigate convergence problems."
115 "The model will do all of its scaling automatically, so it is generally not "
116 "necessary to specify it manually.")
121 .setDescription(
"If set the density will be scaled by a fraction of the maximum doping."
122 "The model will do all of its scaling automatically, so it is generally not "
123 "necessary to specify it manually.")
128 .setDescription(
"Fraction of the maximum doping by which density will be scaled."
129 "The model will do all of its scaling automatically, so it is generally not "
130 "necessary to specify it manually.")
135 .setDescription(
"Acceptor doping level")
140 .setDescription(
"Donor doping level")
145 .setDescription(
"Junction width, if graded junction enabled.")
150 .setDescription(
"Temperature");
154 .setDescription(
"Anode area (used for two-terminal devices)")
159 .setDescription(
"Cathode area (used for two-terminal devices)")
164 .setDescription(
"Emitter area (used for three-terminal (BJT) devices)")
169 .setDescription(
"Base area (used for three-terminal (BJT) devices)")
174 .setDescription(
"Collector area (used for three-terminal (BJT) devices)")
180 .setDescription(
"Device width.")
186 .setDescription(
"Device width.")
192 .setDescription(
"Time interval for tecplot output (if tecplot is enabled).")
207 .setDescription(
"Flag for graded junction vs. abrupt junction. – (1/true=graded, 0/false=abrupt)")
211 .setDescription(
"Mobility model.");
216 .setDescription(
"If true, use field dependent mobility.");
219 .setDescription(
"Bulk semiconductor material");
223 .setDescription(
"This is an output parameter that determines the ``zero'' of the potential at output. If OFFSETOUTPUTVOLTAGE=true (default) it will adjust the voltages at output so that the minimum voltage is zero. If true and also FIRSTELECTRODEOFFSET=true, then the voltage of the first electrode is the zero point. If OFFSETOUTPUTVOLTAGE=false, the output voltage sets the intrisic Fermi level to zero. Depending on circumstances each of these may be more or less convenient for plotting.")
228 .setDescription(
"This is an output parameter. It is only used if OFFSETOUTPUTVOLTAGE=true. (see description of that paramaeter")
233 .setDescription(
"If true, displacement current is computed and output");
237 .setDescription(
"Flag to determine if the results of the nonlinear Poisson "
238 "calculation is included in the output files. Normally, this calculation"
239 " is used to initialize a drift-diffusion calculation and isn't of interest.")
244 .setDescription(
"Flag to turn on/off Auger recombination");
248 .setDescription(
"Flag to turn on/off Shockley-Read-Hall recombination.");
251 .setDescription(
"Flag for gnuplot output.\n"
252 "0 - no gnuplot files.\n"
253 "1 - gnuplot files.\n"
254 "gnuplot is an open source plotting program that is usually installed on Linux "
255 "systems. gnuplot files will have the *Gnu.dat suffix, and the prefix will be the"
256 "name of the device instance.")
260 .setDescription(
"Setting for Tecplot output:\n"
261 "0 - no Tecplot files\n"
262 "1 - Tecplot files, each output in a separate file. 2 - Tecplot file, each output"
263 "appended to a single file.\n"
264 "Tecplot files will have the .dat suffix, and the prefix will be the name of the device instance")
268 .setDescription(
"Flag for sgplot output.\n"
269 "0 - no sgplot files.\n"
270 "1 - sgplot files.\n"
271 "sgplot is a plotting program that comes as part of the SG Framework. sgplot "
272 "files will have the *.res suffix, and the prefix will be the name of the "
278 .setDescription(
"File containing doping profile.")
289 .setDescription(
"Number of mesh points");
299 .setDescription(
"Anode voltage boundary condition. Only used if device is uncoupled from circuit, and running in diode mode.\n")
304 .setDescription(
"Cathode voltage boundary condition. Only used if device is uncoupled from circuit, and running in diode mode.\n")
310 .setDescription(
"Emitter voltage boundary condition. Only used if device is uncoupled from circuit, and running in BJT mode.\n")
315 .setDescription(
"Collector voltage boundary condition. Only used if device is uncoupled from circuit, and running in BJT mode.\n")
320 .setDescription(
"Base voltage boundary condition. Only used if device is uncoupled from circuit, and running in BJT mode.\n")
325 .setDescription(
"If set to true, then some variables are excluded from the time integration error control calculation.");
332 .setDescription(
"Maximum voltage change used by two-level Newton algorithm.");
337 .setDescription(
"Flag for using old(inaccurate) intrinsic carrier calculation.");
341 .setDescription(
"Use Fermi-Dirac statistics.");
393 maxColsPerRow(MAX_COLS_PER_ROW),
396 indicesSetup_(false),
397 includeBaseNode_(false),
398 useElectrodeSpec_(false),
399 maskVarsTIAFlag_(false),
400 scaleDensityToMaxDoping_(true),
401 densityScalarFraction_(1.0e-1),
402 useVoltageOutputOffset_(true),
403 offsetWithFirstElectrode_(false),
405 useLayerCompositeDoping_(false),
421 useOldNiGiven(false),
423 dopingFileName(
"NOFILE"),
424 ndopeFileName(
"NOFILE"),
425 pdopeFileName(
"NOFILE"),
445 baseLocation(0.5e-3),
446 baseLocationGiven(false),
448 gradedJunctionFlag(false),
449 displCurrentFlag(false),
450 calledBeforeUIVB(false),
454 lastOutputTime(-10.0),
456 outputIntervalGiven(false),
458 outputNLPoisson(false),
462 includeAugerRecomb(true),
463 includeSRHRecomb(true),
464 fermiDiracFlag(false),
465 thermionicEmissionFlag(false),
466 tunnelingModelName(
"none"),
468 anodeIndex_userGiven(false),
469 cathodeIndex_user(0),
470 cathodeIndex_userGiven(false),
473 enableContinuationCalled(false),
474 columnReorderingFlag(false),
475 layerCompositeSpecified(false)
498 UserFatal(*
this) <<
"Too many external nodes are set! Set no more than 3.";
508 if (
given(
"PDOPE_FILE") && !
given(
"NDOPE_FILE") )
510 std::string msg =
"Ndope file specified with no Pdope file. Exiting.";
511 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
514 if ( !
given(
"PDOPE_FILE") &&
given(
"NDOPE_FILE") )
516 std::string msg =
"Pdope file specified with no Ndope file. Exiting.";
517 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
524 if (
given(
"MESHFILE"))
526 std::string msg =
"Instance constructor."
527 "mesh file was specified. The 1D device doesn't need a mesh file."
528 " Either add a model statement of level=2, or get rid of the mesh"
529 " file specification.";
530 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
538 if (
given(
"GNUPLOTLEVEL") && !
given(
"TECPLOTLEVEL"))
553 bool bsuccess =
true;
559 bs1 =
setupMesh (); bsuccess = bsuccess && bs1;
561 bs1 =
setupNodes (); bsuccess = bsuccess && bs1;
582 for (std::map<std::string, DopeInfo *>::iterator it =
dopeInfoMap.begin();
588 for (std::map<std::string, PDE_1DElectrode *>::iterator it =
electrodeMap.begin();
595 for (
int i=0;i<size;++i)
618 if (compositeName ==
"DOPINGPROFILES" || compositeName ==
"REGION")
624 else if (compositeName ==
"NODE" || compositeName ==
"ELECTRODE")
627 ExtendedString electrodeName = paramName;
628 electrodeName.toUpper ();
630 bc.
eName = electrodeName;
631 bc.
nName = paramName;
635 if (electrodeName ==
"ANODE")
653 else if (compositeName ==
"LAYER")
658 return (static_cast<CompositeParam *> (matPtr));
663 "Instance::constructComposite: unrecognized composite name: ";
664 msg += compositeName;
665 N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
801 int collectorIndex=0;
803 bcVec[collectorIndex].eName =
"collector";
805 bcVec[collectorIndex].VequGiven =
given(
"COLLECTOR.BC");
807 bcVec[collectorIndex].areaGiven =
given(
"COLLECTOR.AREA");
808 bcVec[collectorIndex].meshIndex =
LX;
809 bcVec[collectorIndex].neighborNode =
LX-1;
815 bcVec[baseIndex].eName =
"base";
819 for (
int i=0;i<
NX;++i)
822 if (deltaX < minDelta)
830 bcVec[baseIndex].VequGiven =
given(
"BASE.BC");
832 bcVec[baseIndex].areaGiven =
given(
"BASE.AREA");
834 bcVec[baseIndex].meshIndex = bIndex;
835 bcVec[baseIndex].neighborNode =
bcVec[baseIndex].meshIndex-1;
841 bcVec[emitterIndex].eName =
"emitter";
843 bcVec[emitterIndex].VequGiven =
given(
"EMITTER.BC");
845 bcVec[emitterIndex].areaGiven =
given(
"EMITTER.AREA");
846 bcVec[emitterIndex].meshIndex = 0;
847 bcVec[emitterIndex].neighborNode = 1;
855 bcVec[anodeIndex].eName =
"anode";
857 bcVec[anodeIndex].VequGiven =
given(
"ANODE.BC");
859 bcVec[anodeIndex].areaGiven =
given(
"ANODE.AREA");
860 bcVec[anodeIndex].meshIndex = 0;
861 bcVec[anodeIndex].neighborNode = 1;
867 bcVec[cathodeIndex].eName =
"cathode";
869 bcVec[cathodeIndex].VequGiven =
given(
"CATHODE.BC");
871 bcVec[cathodeIndex].areaGiven =
given(
"CATHODE.AREA");
872 bcVec[cathodeIndex].meshIndex =
LX;
873 bcVec[cathodeIndex].neighborNode =
LX-1;
881 std::vector<int> tmpMeshSten(
NX,0);
883 for (
int iBC=0;iBC<
bcVec.size();++iBC)
891 ExtendedString side = electrode.
side;
895 bcVec[iBC].meshIndex = 0;
896 bcVec[iBC].neighborNode = 1;
899 else if (side ==
"right")
901 bcVec[iBC].meshIndex =
LX;
902 bcVec[iBC].neighborNode =
LX-1;
905 else if (side ==
"middle" || side ==
"mid")
908 double location = electrode.
location;
912 for (
int imesh=0;imesh<
NX;++imesh)
914 double deltaX=fabs(location-
xVec[imesh]);
915 if (deltaX < minDelta)
922 bcVec[iBC].meshIndex = bIndex;
923 bcVec[iBC].neighborNode = bIndex-1;
927 if (tmpMeshSten[bIndex] == 1)
929 std::string msg =
"Instance::setupNodes. Failed to find mesh index for " + bcVec[iBC].eName;
930 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
935 std::string msg =
"Instance::setupNodes. unrecognized side specified.";
936 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
945 bcVec[iBC].areaGiven = electrode.
areaGiven;
948 bcVec[iBC].area = electrode.
area;
955 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
957 Xyce::dout() <<
" area = " <<
area << std::endl;
958 Xyce::dout() <<
" areaGiven = " <<
given(
"AREA") << std::endl;
959 int isize=
bcVec.size();
960 for (
int i=0;i<isize;++i)
962 Xyce::dout() <<
" bcVec["<<i<<
"].area = " <<
bcVec[i].area << std::endl;
963 Xyce::dout() <<
" bcVec["<<i<<
"].areaGiven = " <<
bcVec[i].areaGiven << std::endl;
964 Xyce::dout() <<
" bcVec["<<i<<
"].meshIndex = " <<
bcVec[i].meshIndex << std::endl;
969 int bcSize=
bcVec.size();
970 for (
int i=0;i<bcSize;++i)
972 bcVec[i].colArray.resize(colmax,-1);
973 bcVec[i].dIdXcols.resize(colmax,-1);
974 bcVec[i].dIdX.resize(colmax,-1);
975 bcVec[i].dFdVckt.resize(colmax,0.0);
984 condVec[iE].resize(numElectrodes,0.0);
992 for (
int i=0;i<bcSize;++i)
994 int meshIndex=
bcVec[i].meshIndex;
996 if (meshIndex==0 || meshIndex==
LX)
1024 bool compositeGiven=
true;
1030 for (
int i=0;i<matVecSize;++i)
1036 matLay.
LX = matLay.
NX-1;
1051 std::string msg =
"Instance constructor."
1052 " NX parameter was not specified.";
1053 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
1075 int baseIndex_m1 = 0;
1076 int baseIndex_p1 = 0;
1101 int bcSize=
bcVec.size();
1103 for (
int iBC=0;iBC<bcSize;++iBC)
1105 int meshIndex=
bcVec[iBC].meshIndex;
1110 for (
int i=0;i<
NX;++i)
1119 for (iBC=0;iBC<
bcVec.size();++iBC)
1121 iMeshNode =
bcVec[iBC].meshIndex;
1125 std::string msg =
"Instance::setupJacStamp:";
1126 msg +=
"Boundary point not in the stencil.";
1127 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
1130 int iNN =
bcVec[iBC].neighborNode;
1131 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1132 Vindex = baseIndex + Voffset;
1133 Nindex = baseIndex + Noffset;
1134 Pindex = baseIndex + Poffset;
1136 if (iMeshNode > iNN)
1138 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1140 Vindex_m1 = baseIndex_m1 + Voffset;
1141 Nindex_m1 = baseIndex_m1 + Noffset;
1142 Pindex_m1 = baseIndex_m1 + Poffset;
1156 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1158 Vindex_p1 = baseIndex_p1 + Voffset;
1159 Nindex_p1 = baseIndex_p1 + Noffset;
1160 Pindex_p1 = baseIndex_p1 + Poffset;
1178 for (iBC=0;iBC<
bcVec.size();++iBC)
1180 iMeshNode =
bcVec[iBC].meshIndex;
1181 int iNN =
bcVec[iBC].neighborNode;
1184 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1185 Vindex = baseIndex + Voffset;
1186 Nindex = baseIndex + Noffset;
1187 Pindex = baseIndex + Poffset;
1195 if (iMeshNode < iNN)
1197 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1198 Vindex_p1 = baseIndex_p1 + Voffset;
1199 Nindex_p1 = baseIndex_p1 + Noffset;
1200 Pindex_p1 = baseIndex_p1 + Poffset;
1203 jacStamp[Vindex][col++] = NodeIndex;
1205 jacStamp[Vindex][col++] = Vindex_p1;
1209 jacStamp[Nindex][col++] = Nindex_p1;
1211 jacStamp[Nindex][col++] = Pindex_p1;
1215 jacStamp[Pindex][col++] = Pindex_p1;
1217 jacStamp[Pindex][col++] = Nindex_p1;
1221 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1222 Vindex_m1 = baseIndex_m1 + Voffset;
1223 Nindex_m1 = baseIndex_m1 + Noffset;
1224 Pindex_m1 = baseIndex_m1 + Poffset;
1227 jacStamp[Vindex][col++] = Vindex_m1;
1229 jacStamp[Vindex][col++] = NodeIndex;
1232 jacStamp[Nindex][col++] = Nindex_m1;
1234 jacStamp[Nindex][col++] = Pindex_m1;
1238 jacStamp[Pindex][col++] = Pindex_m1;
1240 jacStamp[Pindex][col++] = Nindex_m1;
1251 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1252 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1253 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1255 Vindex_m1 = baseIndex_m1 + Voffset;
1256 Nindex_m1 = baseIndex_m1 + Noffset;
1257 Pindex_m1 = baseIndex_m1 + Poffset;
1258 Vindex = baseIndex + Voffset;
1259 Nindex = baseIndex + Noffset;
1260 Pindex = baseIndex + Poffset;
1261 Vindex_p1 = baseIndex_p1 + Voffset;
1262 Nindex_p1 = baseIndex_p1 + Noffset;
1263 Pindex_p1 = baseIndex_p1 + Poffset;
1268 jacStamp[Vindex][col++] = NodeIndex;
1269 jacStamp[Vindex][col++] = Vindex_m1;
1271 jacStamp[Vindex][col++] = Vindex_p1;
1278 jacStamp[Nindex][col++] = Nindex_m1;
1280 jacStamp[Nindex][col++] = Nindex_p1;
1281 jacStamp[Nindex][col++] = Vindex_m1;
1283 jacStamp[Nindex][col++] = Vindex_p1;
1284 jacStamp[Nindex][col++] = Pindex_m1;
1286 jacStamp[Nindex][col++] = Pindex_p1;
1291 jacStamp[Pindex][col++] = Pindex_m1;
1293 jacStamp[Pindex][col++] = Pindex_p1;
1294 jacStamp[Pindex][col++] = Vindex_m1;
1296 jacStamp[Pindex][col++] = Vindex_p1;
1297 jacStamp[Pindex][col++] = Nindex_m1;
1299 jacStamp[Pindex][col++] = Nindex_p1;
1304 std::string msg =
"Instance::setupJacStamp:";
1305 msg +=
"Boundary point not in the stencil.";
1306 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
1311 for (iMeshNode=0;iMeshNode<
NX;++iMeshNode)
1315 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1316 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1317 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1319 Vindex_m1 = baseIndex_m1 + Voffset;
1320 Nindex_m1 = baseIndex_m1 + Noffset;
1321 Pindex_m1 = baseIndex_m1 + Poffset;
1322 Vindex = baseIndex + Voffset;
1323 Nindex = baseIndex + Noffset;
1324 Pindex = baseIndex + Poffset;
1325 Vindex_p1 = baseIndex_p1 + Voffset;
1326 Nindex_p1 = baseIndex_p1 + Noffset;
1327 Pindex_p1 = baseIndex_p1 + Poffset;
1332 jacStamp[Vindex][col++] = Vindex_m1;
1334 jacStamp[Vindex][col++] = Vindex_p1;
1341 jacStamp[Nindex][col++] = Nindex_m1;
1343 jacStamp[Nindex][col++] = Nindex_p1;
1344 jacStamp[Nindex][col++] = Vindex_m1;
1346 jacStamp[Nindex][col++] = Vindex_p1;
1347 jacStamp[Nindex][col++] = Pindex_m1;
1349 jacStamp[Nindex][col++] = Pindex_p1;
1354 jacStamp[Pindex][col++] = Pindex_m1;
1356 jacStamp[Pindex][col++] = Pindex_p1;
1357 jacStamp[Pindex][col++] = Vindex_m1;
1359 jacStamp[Pindex][col++] = Vindex_p1;
1360 jacStamp[Pindex][col++] = Nindex_m1;
1362 jacStamp[Pindex][col++] = Nindex_p1;
1365 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1369 Xyce::dout() <<
"jacStamp size = " << jacSize << std::endl;
1371 for(
int i=0;i<jacSize;++i)
1374 for (
int j=0;j<colSize;++j)
1376 Xyce::dout() <<
" jacStamp["<<i<<
"]["<<j<<
"] = " <<
jacStamp[i][j] << std::endl;
1404 int mapSize =
jacMap.size();
1405 for (
int i=0;i<mapSize;++i)
1409 for (
int j=0;j<
jacStamp[i].size();++j)
1423 std::vector< std::vector<int> > tempStamp_eric;
1424 std::vector< std::vector<int> > tempMap2_eric;
1446 for (
int i = 0; i <
NX; ++i)
1450 std::ostringstream oss;
1457 std::ostringstream oss;
1464 std::ostringstream oss;
1480 const std::vector<int> & extLIDVecRef)
1485 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1487 Xyce::dout() << section_divider << std::endl;
1488 Xyce::dout() <<
"Instance::registerLIDs:\n";
1489 Xyce::dout() <<
" name = " <<
getName() << std::endl;
1490 Xyce::dout() <<
" numInt = " <<
numIntVars << std::endl;
1491 Xyce::dout() <<
" numEXt = " <<
numExtVars << std::endl;
1492 Xyce::dout() <<
" NX = " <<
NX << std::endl;
1499 for (
int iBC=0;iBC<
bcVec.size();++iBC)
1517 for (
int iBC=0;iBC<
bcVec.size();++iBC)
1519 meshIndex =
bcVec[iBC].meshIndex;
1528 for (meshIndex=0;meshIndex<
NX;++meshIndex)
1537 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
1539 Xyce::dout() <<
"\n solution indices:\n";
1541 for (
int i=0;i<
NX;++i)
1543 Xyce::dout() <<
" li_Vrowarray["<<i<<
"] = " <<
li_Vrowarray[i];
1544 Xyce::dout() <<
"\tli_Nrowarray["<<i<<
"] = " <<
li_Nrowarray[i];
1545 Xyce::dout() <<
"\tli_Prowarray["<<i<<
"] = " <<
li_Prowarray[i] << std::endl;
1547 Xyce::dout() << section_divider << std::endl;
1564 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1566 Xyce::dout() << std::endl;
1567 Xyce::dout() << section_divider << std::endl;
1568 Xyce::dout() <<
" In Instance::registerStateLIDs\n\n";
1569 Xyce::dout() <<
" name = " <<
getName() << std::endl;
1570 Xyce::dout() <<
" Number of State LIDs: " <<
numStateVars << std::endl;
1578 for (i=0;i<
bcVec.size();++i)
1583 for (i=0,j=2;i<
NX-1;++i,++j)
1588 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1590 Xyce::dout() <<
" State indices:" << std::endl;
1591 Xyce::dout() << std::endl;
1592 for (i=0;i<
bcVec.size();++i)
1594 Xyce::dout() <<
"bcVec["<<i<<
"].li_stateC = "<<
bcVec[i].li_stateC<< std::endl;
1596 Xyce::dout() << std::endl;
1598 Xyce::dout() <<
" Displacement current state variable local indices:" << std::endl;
1599 for (i=0;i<NX-1;++i)
1601 Xyce::dout() <<
" li_stateDispl["<<i<<
"] = " <<
li_stateDispl[i] << std::endl;
1603 Xyce::dout() << section_divider << std::endl;
1629 (
const std::vector< std::vector<int> > & jacLIDVec )
1644 int extVarOffset = numExtVars;
1646 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1648 Xyce::dout() << section_divider << std::endl;
1649 Xyce::dout() <<
"Instance::registerJacLIDs" << std::endl;
1651 int jacLIDSize = jacLIDVec.size();
1652 Xyce::dout() <<
"jacLIDSize = " << jacLIDSize << std::endl;
1653 for (i=0;i<jacLIDSize;++i)
1655 int jacLIDcolSize = jacLIDVec[i].size();
1656 Xyce::dout() << std::endl;
1657 Xyce::dout() <<
"jacLIDVec["<<i<<
"].size = " << jacLIDcolSize << std::endl;
1658 for (j=0;j<jacLIDcolSize;++j)
1660 Xyce::dout() <<
"jacLIDVec["<<i<<
"]["<<j<<
"] = ";
1661 Xyce::dout() << jacLIDVec[i][j] << std::endl;
1666 li_Vcolarray.resize(NX);
1667 li_Ncolarray.resize(NX);
1668 li_Pcolarray.resize(NX);
1671 for (
int iBC=0;iBC<bcVec.size();++iBC)
1674 int numCols = jacLIDVec[iBC].size();
1675 bcVec[iBC].li_colArray.resize(numCols,-1);
1677 for (i1=0;i1<numCols;++i1)
1679 bcVec[iBC].li_colArray[i1] = jacLIDVec[iBC][i1];
1682 int iMeshNode = bcVec[iBC].meshIndex;
1684 bcVec[iBC].lidOffset = jacLIDVec[iBC][0];
1686 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1688 Xyce::dout() << std::endl;
1689 for(i=0;i<bcVec[iBC].li_colArray.size();++i)
1691 Xyce::dout() << bcVec[iBC].eName <<
": li_colArray["<<i<<
"] = "<<bcVec[iBC].li_colArray[i]<< std::endl;
1693 Xyce::dout() << std::endl;
1698 for (iMeshNode=0;iMeshNode<NX;++iMeshNode)
1700 if (boundarySten[iMeshNode]==1)
continue;
1702 baseIndex = numVars*meshToLID[iMeshNode ] + extVarOffset;
1704 Vindex = baseIndex + Voffset;
1705 Nindex = baseIndex + Noffset;
1706 Pindex = baseIndex + Poffset;
1711 li_Vcolarray[iMeshNode].resize(5,-1);
1712 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1713 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1714 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1715 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1716 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1720 li_Ncolarray[iMeshNode].resize(9,-1);
1721 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1722 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1723 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1724 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1725 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1726 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1727 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1728 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1729 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1734 li_Pcolarray[iMeshNode].resize(9,-1);
1735 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1736 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1737 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1738 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1739 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1740 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1741 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1742 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1743 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1745 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1747 Xyce::dout() << std::endl;
1748 Xyce::dout() <<
"registerJacLIDs: iMeshNode = " << iMeshNode << std::endl;
1749 Xyce::dout() <<
"jacLIDVec[Vindex].size = " << jacLIDVec[Vindex].size()<<std::endl;
1750 Xyce::dout() <<
"jacLIDVec[Nindex].size = " << jacLIDVec[Nindex].size()<<std::endl;
1751 Xyce::dout() <<
"jacLIDVec[Pindex].size = " << jacLIDVec[Pindex].size()<<std::endl;
1755 Xyce::dout() <<
" li_Vcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1756 Xyce::dout() << li_Vcolarray[iMeshNode][i] << std::endl;
1758 Xyce::dout() << std::endl;
1761 Xyce::dout() <<
" li_Ncolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1762 Xyce::dout() << li_Ncolarray[iMeshNode][i] << std::endl;
1764 Xyce::dout() << std::endl;
1767 Xyce::dout() <<
" li_Pcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1768 Xyce::dout() << li_Pcolarray[iMeshNode][i] << std::endl;
1770 Xyce::dout() << std::endl;
1775 for (
int iBC=0;iBC<bcVec.size();++iBC)
1777 iMeshNode = bcVec[iBC].meshIndex;
1778 int iNN = bcVec[iBC].neighborNode;
1780 baseIndex = numVars*meshToLID[iMeshNode ] + extVarOffset;
1781 Vindex = baseIndex + Voffset;
1782 Nindex = baseIndex + Noffset;
1783 Pindex = baseIndex + Poffset;
1785 if (edgeBoundarySten[iMeshNode]==1)
1789 li_Vcolarray[iMeshNode].resize(3,-1);
1790 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1791 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1792 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1795 if (iMeshNode < iNN)
1798 li_Ncolarray[iMeshNode].resize(3,-1);
1799 li_Ncolarray[iMeshNode][i1++] = -1;
1800 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1801 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1804 li_Pcolarray[iMeshNode].resize(3,-1);
1805 li_Pcolarray[iMeshNode][i1++] = -1;
1806 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1807 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1812 li_Ncolarray[iMeshNode].resize(3,-1);
1813 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1814 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1817 li_Pcolarray[iMeshNode].resize(3,-1);
1818 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1819 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1822 else if (internalBoundarySten[iMeshNode]==1)
1827 li_Vcolarray[iMeshNode].resize(6,-1);
1828 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1829 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1830 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1831 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1832 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1833 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1837 li_Ncolarray[iMeshNode].resize(9,-1);
1838 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1839 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1840 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1841 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1842 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1843 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1844 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1845 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1846 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1850 li_Pcolarray[iMeshNode].resize(9,-1);
1851 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1852 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1853 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1854 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1855 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1856 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1857 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1858 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1859 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1863 std::string msg =
"Instance::registerJacLIDs:";
1864 msg +=
"Boundary point not in the stencil.";
1865 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
1868 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1870 Xyce::dout() << std::endl;
1871 Xyce::dout() <<
"registerJacLIDs: ("<<bcVec[iBC].eName<<
") iMeshNode = ";
1872 Xyce::dout() << iMeshNode << std::endl;
1875 Xyce::dout() <<
" li_Vcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1876 Xyce::dout() << li_Vcolarray[iMeshNode][i] << std::endl;
1878 Xyce::dout() << std::endl;
1881 Xyce::dout() <<
" li_Ncolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1882 Xyce::dout() << li_Ncolarray[iMeshNode][i] << std::endl;
1884 Xyce::dout() << std::endl;
1887 Xyce::dout() <<
" li_Pcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1888 Xyce::dout() << li_Pcolarray[iMeshNode][i] << std::endl;
1890 Xyce::dout() << std::endl;
1920 for (
int i=0;i<
NX;++i)
1929 for (
int j=0;j<vSize;++j)
1938 for (
int j=0;j<nSize;++j)
1947 for (
int j=0;j<pSize;++j)
1966 bool bsuccess =
true;
1969 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1971 Xyce::dout() << section_divider << std::endl;
1972 Xyce::dout() <<
"updateIntermediateVars. name = " <<
getName() << std::endl;
1976 bs1 =
calcEfield (); bsuccess = bsuccess && bs1;
1982 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1984 Xyce::dout() << section_divider << std::endl;
2006 bool bsuccess =
true;
2012 for (iBC=0;iBC<
bcVec.size();++iBC)
2014 int index =
bcVec[iBC].meshIndex;
2015 int iNN=
bcVec[iBC].neighborNode;
2017 double A0=J0*a0*
area;
2019 double sign = ((iNN > index)?1.0:-1.0);
2020 int edgeIndex= ((iNN > index)?index:iNN);
2022 bcVec[iBC].elecCurrent = sign*
JnxVec[edgeIndex]*A0;
2023 bcVec[iBC].holeCurrent = sign*
JpxVec[edgeIndex]*A0;
2027 bcVec[iBC].currentSum =
bcVec[iBC].elecCurrent +
bcVec[iBC].holeCurrent;
2031 std::string & type =
bcVec[iBC].type;
2036 bcVec[iBC].currentSum =
bcVec[iBC].elecCurrent;
2038 else if (type==
"ptype")
2040 bcVec[iBC].currentSum =
bcVec[iBC].holeCurrent;
2044 std::string msg =
"Instance::calcTerminalCurrents";
2045 msg +=
"Unrecognized type on boundary.";
2046 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2051 std::string msg =
"Instance::calcTerminalCurrents";
2052 msg +=
"Unrecognized boundary.";
2053 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2058 bcVec[iBC].currentSum +=
bcVec[iBC].displCurrent;
2062 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2064 Xyce::dout() << Xyce::subsection_divider << std::endl
2065 <<
"Calculated currents, etc., coming from the DD calculation:" << std::endl
2066 <<
" scalingVars.J0 = " << J0<<std::endl
2067 <<
" scalingVars.a0 = " << a0<<std::endl
2068 << Xyce::subsection_divider << std::endl;
2069 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2071 Xyce::dout() <<
bcVec[iBC];
2073 Xyce::dout() << Xyce::subsection_divider << std::endl;
2126 int bcSize =
bcVec.size();
2127 for (iBC=0; iBC < bcSize; ++iBC)
2129 bcVec[iBC].dIdVckt = 0.0;
2135 for (iBC=0;iBC<
bcVec.size();++iBC)
2137 int iN =
bcVec[iBC].meshIndex;
2138 int iNN =
bcVec[iBC].neighborNode;
2139 int dFdVcktIndex = 0;
2155 for (iBC=0;iBC<bcSize;++iBC)
2158 i=
bcVec[iBC].meshIndex;
2162 std::string msg =
"Instance::pdTerminalCurrents";
2163 msg +=
"Unrecognized boundary.";
2164 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2167 int iNN=
bcVec[iBC].neighborNode;
2169 double A0=J0*a0*
area;
2170 std::vector<int> & colA =
bcVec[iBC].li_colArray;
2172 double sign = ((iNN > i)?1.0:-1.0);
2178 double dJndV_nn = 0.0;
2179 double dJpdV_nn = 0.0;
2180 double dJndn_nn = 0.0;
2181 double dJpdp_nn = 0.0;
2214 double Vcoef = (sign* dJndV + sign* dJpdV)*A0;
2215 double Ncoef = (sign* dJndn)*A0;
2216 double Pcoef = (sign* dJpdp)*A0;
2219 double Vcoef_nn = (sign* dJndV_nn + sign* dJpdV_nn)*A0;
2220 double Ncoef_nn = (sign* dJndn_nn)*A0;
2221 double Pcoef_nn = (sign* dJpdp_nn)*A0;
2225 std::string & type =
bcVec[iBC].type;
2233 else if (type==
"ptype")
2240 std::string msg =
"Instance::pdTerminalCurrents";
2241 msg +=
"Unrecognized type on boundary.";
2242 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2252 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2254 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2255 bcVec[iBC].dIdX[count] = Vcoef;
2261 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2263 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2264 bcVec[iBC].dIdX[count] = Vcoef_nn;
2270 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2272 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2273 bcVec[iBC].dIdX[count] = Ncoef;
2279 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2281 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2282 bcVec[iBC].dIdX[count] = Ncoef_nn;
2288 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2290 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2291 bcVec[iBC].dIdX[count] = Pcoef;
2297 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2299 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2300 bcVec[iBC].dIdX[count] = Pcoef_nn;
2335 bool bsuccess =
true;
2337 Linear::Vector & dfdv = *(dfdvPtr);
2394 bool bsuccess =
true;
2395 const Linear::Vector & dxdv = *dxdvPtr;
2397 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2399 Xyce::dout() << section_divider <<
"\n";
2400 Xyce::dout() <<
"calcConductances name = " <<
getName() << std::endl;
2401 Xyce::dout() <<
"electrode = " <<
bcVec[iElectrode].eName;
2402 Xyce::dout() <<
" dIdVckt = " <<
bcVec[iElectrode].dIdVckt;
2403 Xyce::dout() << std::endl;
2404 Xyce::dout() << std::endl;
2407 if (!(
bcVec[iElectrode].dxdvAllocated))
2410 bcVec[iElectrode].dxdvAllocated =
true;
2416 *(
bcVec[iElectrode].dxdvPtr) = *(dxdvPtr);
2423 double dIidVj = 0.0;
2424 double dIidVj_chain = 0.0;
2440 if (iElectrode != iEqu) dIidVj = 0.0;
2441 else dIidVj =
bcVec[iEqu].dIdVckt;
2445 int DIDXSize =
bcVec[iEqu].dIdX.size();
2446 for (
int iDIDX=0;iDIDX<DIDXSize;++iDIDX)
2448 int index =
bcVec[iEqu].dIdXcols[iDIDX];
2449 double coef =
bcVec[iEqu].dIdX[iDIDX];
2451 if (index < 0)
continue;
2458 std::ostringstream oss;
2459 oss <<
"dIdX" << std::setw(2) << std::setfill(
'0') << iEqu <<
".txt";
2466 Gij = dIidVj_chain + dIidVj;
2468 condVec[iEqu][iElectrode] = Gij;
2470 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2472 char outstring[128];
2473 double Itmp =
bcVec[iEqu].currentSum;
2474 double Vtmp =
bcVec[iEqu].Vckt -
bcVec[iElectrode].Vckt;
2476 double GV = Gij*Vtmp;
2477 for(
int i=0;i<128;++i) outstring[i] = static_cast<char>(0);
2479 "(%2d,%2d): dotPr=%12.4e G=%12.4e",
2480 iEqu,iElectrode,dIidVj_chain,Gij);
2481 Xyce::dout() << std::string(outstring) << std::endl;
2484 "(%2d,%2d): G=%12.4e G*V=%12.4e I=%12.4e V=%12.4e",
2485 iEqu,iElectrode,Gij,GV,Itmp,Vtmp);
2486 Xyce::dout() << std::string(outstring) << std::endl;
2490 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2492 Xyce::dout() << section_divider << std::endl;
2509 bool bsuccess =
true;
2513 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2515 int li_state=
bcVec[iBC].li_stateC;
2516 staVector[li_state] =
bcVec[iBC].currentSum;
2522 for (i = 0; i<
NX-1; ++i)
2541 bool bsuccess =
true;
2546 for(
int i = 0; i<
NX-1; ++i)
2581 for (
int i=0;i<
NX;++i)
2584 (*maskVectorPtr)[Vrow] = 0.0;
2585 (*maskVectorPtr)[Vrow] = 0.0;
2601 bool bsuccess =
true;
2629 bool bsuccess =
true;
2631 int Vrow(-1), Nrow(-1), Prow(-1);
2643 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2645 int i =
bcVec[iBC].meshIndex;
2652 rhs[Vrow] +=
VVec[i] - (
bcVec[iBC].Vequ);
2659 for (
int ihet=0;ihet<hetSize;++ihet)
2698 coef2 = -(holeDens-elecDens+
CVec[i]);
2721 bool bsuccess =
true;
2723 int Vrow, Nrow, Prow;
2731 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2733 rhs[
bcVec[iBC].lid] += bcVec[iBC].currentSum;
2741 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2743 int i =
bcVec[iBC].meshIndex;
2757 std::string & type =
bcVec[iBC].type;
2765 else if (type==
"ptype")
2772 std::string msg =
"Instance::loadVecDDForm";
2773 msg +=
"Unrecognized type on boundary.";
2774 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2779 std::string msg =
"Instance::loadVecDDForm";
2780 msg +=
"Unrecognized stencil on boundary.";
2781 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2827 std::vector<Util::BreakPoint> &breakPointTimes)
2845 bool bsuccess =
true;
2846 int Vrow, Nrow, Prow;
2850 double rUt = 1.0/
Ut;
2852 double elecDens, holeDens;
2860 for (iBC=0;iBC<
bcVec.size();++iBC)
2862 mat[
bcVec[iBC].lid][
bcVec[iBC].lidOffset] = 1.0;
2866 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2868 int i =
bcVec[iBC].meshIndex;
2879 mat[Vrow][offset1] = 0.0;
2880 mat[Vrow][offset2] = 1.0;
2881 mat[Vrow][offset3] = 0.0;
2885 mat[Vrow][offset1] = 0.0;
2886 mat[Vrow][offset2] = 1.0;
2887 mat[Vrow][offset3] = 0.0;
2891 mat[Vrow][offset1] = 0.0;
2892 mat[Vrow][offset2] = 0.0;
2893 mat[Vrow][offset3] = 1.0;
2903 for (
int ihet=0;ihet<hetSize;++ihet)
2926 Xyce::dout() <<
"ihet="<<ihet<<
" perm1/dx1="<<perm1/dx1<<
" perm2/dx2="<<perm2/dx2;
2927 Xyce::dout() <<
" Vrow="<<Vrow<<
" Nrow="<<Nrow<<
" Prow="<<Prow<<std::endl;
2930 mat[Vrow][offset1] = perm1/dx1;
2931 mat[Vrow][offset2] = -perm1/dx1;
2932 mat[Vrow][offset3] = -perm2/dx2;
2943 mat[Nrow][li_Ncolarray[i2][1]] = 1.0;
2944 mat[Prow][li_Pcolarray[i2][1]] = 1.0;
2971 mat[Vrow][offset1] = -L0/(dx1*dx2);
2972 mat[Vrow][offset2] = 2.0*L0/(dx1*dx2) + rUt*holeDens + rUt*elecDens;
2973 mat[Vrow][offset3] = -L0/(dx1*dx2);
3005 for (iBC=0;iBC<
bcVec.size();++iBC)
3008 i=
bcVec[iBC].meshIndex;
3012 std::string msg =
"Instance::loadMatKCLForm";
3013 msg +=
"Unrecognized boundary.";
3014 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
3017 int iNN=
bcVec[iBC].neighborNode;
3018 li_row =
bcVec[iBC].lid;
3020 double A0=J0*a0*
area;
3021 std::vector<int> & colA =
bcVec[iBC].li_colArray;
3023 double sign = ((iNN > i)?1.0:-1.0);
3031 double dJndV_nn = 0.0;
3032 double dJpdV_nn = 0.0;
3033 double dJndn_nn = 0.0;
3034 double dJndp_nn = 0.0;
3035 double dJpdp_nn = 0.0;
3036 double dJpdn_nn = 0.0;
3077 double Vcoef = sign*(dJndV + dJpdV)*A0;
3078 double Ncoef = sign*(dJndn + dJpdn)*A0;
3079 double Pcoef = sign*(dJndp + dJpdp)*A0;
3082 double Vcoef_nn = sign*(dJndV_nn + dJpdV_nn)*A0;
3083 double Ncoef_nn = sign*(dJndn_nn + dJpdn_nn)*A0;
3084 double Pcoef_nn = sign*(dJndp_nn + dJpdp_nn)*A0;
3088 std::string & type =
bcVec[iBC].type;
3096 else if (type==
"ptype")
3103 std::string msg =
"Instance::loadMatKCLForm";
3104 msg +=
"Unrecognized type on boundary.";
3105 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
3111 mat[li_row][colA[liOffIndex++]] += Vcoef;
3114 mat[li_row][colA[liOffIndex++]] += Vcoef_nn;
3117 mat[li_row][colA[liOffIndex++]] += Ncoef;
3120 mat[li_row][colA[liOffIndex++]] += Ncoef_nn;
3123 mat[li_row][colA[liOffIndex++]] += Pcoef;
3126 mat[li_row][colA[liOffIndex++]] += Pcoef_nn;
3143 bool bsuccess =
true;
3148 for (iBC=0;iBC<
bcVec.size();++iBC)
3150 mat[
bcVec[iBC].lid][
bcVec[iBC].lidOffset] = 1.0;
3166 bool bsuccess =
true;
3169 int Vrow, Nrow, Prow;
3180 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
3182 for (
int i=1;i<
LX;++i)
3193 bsuccess = bsuccess && bs1;
3198 bsuccess = bsuccess && bs1;
3202 for (
int iBC=0;iBC<
bcVec.size();++iBC)
3204 int i =
bcVec[iBC].meshIndex;
3212 mat[Vrow][li_Vcolarray[i][1]] = 1.0;
3213 mat[Vrow][li_Vcolarray[i][2]] = 0.0;
3221 mat[Vrow][li_Vcolarray[i][1]] = 1.0;
3230 mat[Vrow][li_Vcolarray[i][2]] = 1.0;
3232 std::string & type =
bcVec[iBC].type;
3245 mat[Prow][li_Pcolarray[i][1]] =
3249 mat[Prow][li_Pcolarray[i][2]] = -
dJpdp2Vec[i]/aveDx;
3252 mat[Prow][li_Pcolarray[i][3]] = (
dJpdV1Vec[i-1]/aveDx);
3255 mat[Prow][li_Pcolarray[i][4]] =
3259 mat[Prow][li_Pcolarray[i][5]] = (-
dJpdV2Vec[i]/aveDx);
3265 mat[Prow][li_Pcolarray[i][6]] =
dJpdn1Vec[i-1]/aveDx;
3268 mat[Prow][li_Pcolarray[i][7]] =
3272 mat[Prow][li_Pcolarray[i][8]] = -
dJpdn2Vec[i]/aveDx;
3274 else if (type==
"ptype")
3284 mat[Nrow][li_Ncolarray[i][1]] =
3288 mat[Nrow][li_Ncolarray[i][2]] =
dJndn2Vec[i]/aveDx;
3291 mat[Nrow][li_Ncolarray[i][3]] = (-
dJndV1Vec[i-1]/aveDx);
3294 mat[Nrow][li_Ncolarray[i][4]] =
3298 mat[Nrow][li_Ncolarray[i][5]] = (
dJndV2Vec[i]/aveDx);
3301 mat[Nrow][li_Ncolarray[i][6]] =
dJndp1Vec[i-1]/aveDx;
3304 mat[Nrow][li_Ncolarray[i][7]] =
3308 mat[Nrow][li_Ncolarray[i][8]] = -
dJndp2Vec[i]/aveDx;
3312 std::string msg =
"Instance::loadMatDDForm";
3313 msg +=
"Unrecognized type on boundary.";
3314 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
3333 double dx1 =
dxVec[i-1];
3334 double dx2 =
dxVec[i];
3341 *(
fVmatPtr[i][1])=(2.0*L0/(dx1*dx2));
3432 for (
int i=0;i<
NX;++i)
3454 bool bsuccess =
true;
3467 mi.
N = (fabs(
CVec[i+1])+fabs(
CVec[i]))*0.5;
3476 if (mi.
N == 0.0) mi.
N = 1.0;
3510 Xyce::dout() <<
"\tunE["<<i<<
"]="<<
unE_Vec[i];
3511 Xyce::dout() <<
"\tupE["<<i<<
"]="<<
upE_Vec[i];
3512 Xyce::dout() << std::endl;
3545 bool bsuccess =
true;
3591 for (
int i=0;i<
NX;++i)
3609 bool bsuccess (
false);
3610 bool fromFile (
false);
3618 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
3620 Xyce::dout() << section_divider << std::endl;
3621 Xyce::dout() <<
"Instance::setupDopingProfile\n";
3661 double xtmp =
xVec[i];
3662 double ndopeDopeValue(0.0), pdopeDopeValue(0.0);
3667 CVec[i] = ndopeDopeValue-pdopeDopeValue;
3680 for (iBC=0;iBC<
bcVec.size();++iBC)
3682 int i =
bcVec[iBC].meshIndex;
3685 bcVec[iBC].type =
"ntype";
3689 bcVec[iBC].type =
"ptype";
3695 Xyce::dout() <<
"Na = " <<
Na << std::endl;
3696 Xyce::dout() <<
"Nd = " <<
Nd << std::endl;
3699 Xyce::dout() <<
"x[" << i <<
"] = " <<
xVec[i] <<
"\t";
3700 Xyce::dout() <<
"C[" << i <<
"] = " <<
CVec[i] << std::endl;
3703 Xyce::dout() << section_divider << std::endl;
3728 bool bsuccess =
true;
3744 midpoint =
width/2.0;
3745 XL = midpoint -
WJ/2.0;
3746 XR = midpoint +
WJ/2.0;
3775 std::map<std::string, DopeInfo *>::iterator iter;
3776 std::map<std::string, DopeInfo *>::iterator start =
dopeInfoMap.begin();
3777 std::map<std::string, DopeInfo *>::iterator end =
dopeInfoMap.end();
3779 for ( iter = start; iter != end; ++iter )
3797 if (
Na == 0.0 ||
Nd == 0.0)
3799 UserError(*
this) <<
"Mistake in doping. Na=" <<
Na <<
" Nd=" <<
Nd;
3822 matPtr->
name=
"FULLDOMAIN";
3858 int totalMeshIndex = 1;
3859 for (
int imat=0;imat<matVecSize;++imat)
3862 Xyce::dout() <<
"name="<<matLay.
name <<
" NX="<<matLay.
NX<<
" LX="<<matLay.
LX <<std::endl;
3864 matLay.
LX = matLay.
NX-1;
3865 matLay.
begin = totalMeshIndex-1;
3871 double dx = matLay.
width /(
static_cast<double>(matLay.
LX));
3877 Xyce::dout() <<
"Setting xVec["<<matLay.
begin<<
"] to "<<
xVec[matLay.
begin] <<
"."<<std::endl;
3879 std::pair<int,int> hetPair = std::make_pair (matLayPrev.
end, matLay.
begin);
3885 for (
int ix=matLay.
begin;ix<=matLay.
end;++ix,++totalMeshIndex,++iloc)
3887 double extra=
static_cast<double>(iloc)*dx;
3888 xVec[ix] = base + extra;
3891 for (
int ix=matLay.
begin;ix<matLay.
end;++ix)
3906 double dx_tmp =
width/(
static_cast<double>(
LX));
3908 for (
int i=0;i<
NX;++i)
3910 xVec[i] =
static_cast<double>(i)*dx_tmp;
3913 for (
int i=0;i<
LX;++i)
3920 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
3922 for (
int i=0;i<
NX;++i)
3924 Xyce::dout() <<
"x["<<i<<
"] = " <<
xVec[i];
3925 Xyce::dout() <<
"\tdx["<<i<<
"] = " <<
dxVec[i];
3926 Xyce::dout() << std::endl;
3929 Xyce::dout() <<
"heterojunction boundary points:" <<std::endl;
3976 dnbnd0 = 2.0*pow(dnbnd0,1.5)/1.0e6;
3977 double kbq = 8.6173324e-5;
3981 for (
int im=0;im<size; ++im)
3985 int begin = matLayer.
begin;
3986 int end = matLayer.
end;
3988 double Ec = matLayer.
Ec;
3989 double Ev = matLayer.
Ev;
3990 double bg = fabs(Ec - Ev);
3992 double Nc = dnbnd0*(matLayer.
dnco);
3993 double Nv = dnbnd0*(matLayer.
dnva);
3995 double EcEff = matLayer.
Ec-matLayer.
narco;
3996 double EvEff = matLayer.
Ev+matLayer.
narva;
3997 double bgEff = fabs(EcEff-EvEff);
4000 double Ni = sqrt( Nc * Nv ) * exp (-bg/(2.0*kbq*
Temp));
4001 double NiEff = sqrt( Nc * Nv ) * exp (-bgEff/(2.0*kbq*Temp));
4004 matLayer.
NiEff = NiEff;
4006 matLayer.
bgEff = bgEff;
4008 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
4010 Xyce::dout() <<
"layer="<<matLayer.
name<<
"\t"<<matLayer.
material;
4011 Xyce::dout() <<
"\tNc="<<Nc<<
"\tNv="<<Nv<<
"\tbg="<<bg<<
"\tNi="<<Ni<<std::endl;
4014 for (
int i=begin;i<=end;++i)
4035 EiVec[i] = 0.5*(Ec+Ev)+0.5*
kb*Temp*log(Nv/Nc);
4036 EiEffVec[i] = 0.5*(EcEff+EvEff)+0.5*
kb*Temp*log(Nv/Nc);
4048 for (
int i=0;i<
NX;++i)
4057 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
4059 for (
int im=0;im<size; ++im)
4063 int begin = matLayer.
begin;
4064 int end = matLayer.
end;
4066 Xyce::dout() << matLayer.
name <<
"\tbegin="<<begin<<
"\tend="<<end<<std::endl;
4069 for (
int i=0;i<
NiVec.size();++i)
4071 Xyce::dout() << i <<
"\t"
4078 <<
NiVec[i] <<
"\n";
4080 Xyce::dout() << std::endl;
4118 bool bsuccess =
true;
4200 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
4202 Xyce::dout() <<
"scalingVars.x0 = " <<
scalingVars.
x0 << std::endl;
4203 Xyce::dout() <<
"scalingVars.a0 = " <<
scalingVars.
a0 << std::endl;
4204 Xyce::dout() <<
"scalingVars.T0 = " <<
scalingVars.
T0 << std::endl;
4205 Xyce::dout() <<
"scalingVars.V0 = " <<
scalingVars.
V0 << std::endl;
4206 Xyce::dout() <<
"scalingVars.C0 = " <<
scalingVars.
C0 << std::endl;
4207 Xyce::dout() <<
"scalingVars.D0 = " <<
scalingVars.
D0 << std::endl;
4208 Xyce::dout() <<
"scalingVars.u0 = " <<
scalingVars.
u0 << std::endl;
4209 Xyce::dout() <<
"scalingVars.R0 = " <<
scalingVars.
R0 << std::endl;
4210 Xyce::dout() <<
"scalingVars.t0 = " <<
scalingVars.
t0 << std::endl;
4211 Xyce::dout() <<
"scalingVars.E0 = " <<
scalingVars.
E0 << std::endl;
4212 Xyce::dout() <<
"scalingVars.F0 = " <<
scalingVars.
F0 << std::endl;
4213 Xyce::dout() <<
"scalingVars.J0 = " <<
scalingVars.
J0 << std::endl;
4214 Xyce::dout() <<
"scalingVars.L0 = " <<
scalingVars.
L0 << std::endl;
4241 for (i=0;i<
bcVec.size();++i)
4298 for (i=0;i<
bcVec.size();++i)
4348 bool bsuccess =
true;
4359 for (
int i=0;i<
NX;++i)
4366 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4367 nnVec[i] = ((Ci>=0)?(tmp):(0.0)) + ((Ci<0)?(Nisq/tmp):(0.0));
4370 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4371 npVec[i] = ((Ci<=0)?(tmp):(0.0)) + ((Ci>0)?(Nisq/tmp):(0.0));
4376 for (
int i=0;i<
NX;++i)
4379 double kbq_ = 8.6173324e-5;
4380 double dope_us_ =
CVec[i];
4381 double temp_us_ =
Temp;
4383 double Nc =
NcVec[i];
4384 double Nv =
NvVec[i];
4386 double cond_band =
EcVec[i];
4387 double vale_band =
EvVec[i];
4388 double bandgap = cond_band-vale_band;
4391 if (dope_us_ >= 0.0)
4397 double ef_m_ec_ = kbq_*temp_us_*
fdinvObj (dope_us_/Nc);
4400 double bgn_ = 3.23e-8 * std::pow(dope_us_, 1.0/3.0);
4403 double ef_m_ev_ = ef_m_ec_ + bandgap-bgn_;
4406 npVec[i] = Nv*std::exp(-ef_m_ev_/(kbq_*temp_us_));
4411 dope_us_ = std::fabs(dope_us_);
4415 double ev_m_ef_ = kbq_*temp_us_*
fdinvObj (dope_us_/Nv);
4418 double bgn_ = 2.55e-8 * std::pow(dope_us_, 1.0/3.0);
4421 double ec_m_ef_ = ev_m_ef_ + (bandgap-bgn_);
4424 nnVec[i] = Nc*std::exp(-ec_m_ef_/(kbq_*temp_us_));
4430 double Vmax = -1.0e99;
4431 double Vmin = +1.0e99;
4432 for (
int i=0;i<
NX;++i)
4445 if (Vmax <
VVec[i]) Vmax =
VVec[i];
4446 if (Vmin >
VVec[i]) Vmin =
VVec[i];
4453 for (
int i=0;i<
NX;++i)
4459 for (
int i=0;i<
NX;++i)
4479 bool bsuccess =
true;
4482 double VminBC =+1.0e+99;
4483 double VmaxBC =-1.0e+99;
4485 int bcSize=
bcVec.size();
4486 for (
int i=0;i<bcSize;++i)
4488 int mIndex =
bcVec[i].meshIndex;
4489 double Ci =
CVec[mIndex];
4490 double Cisq = Ci*Ci;
4491 double Nisq =
Ni*
Ni;
4492 double tmp, nnTmp, npTmp;
4495 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4496 nnTmp = ((Ci>=0)?(tmp):(0.0)) + ((Ci<0)?(Nisq/tmp):(0.0));
4499 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4500 npTmp = ((Ci<=0)?(tmp):(0.0)) + ((Ci>0)?(Nisq/tmp):(0.0));
4505 ExtendedString mater =
bcVec[i].material;
4508 if (
bcVec[i].VequGiven != 1)
4510 if (mater==
"neutral")
4515 bcVec[i].Vequ = +
Vt * log(nnTmp/Ni);
4519 bcVec[i].Vequ = -
Vt * log(npTmp/Ni);
4530 + 2.0 *
Vt * log(nnTmp/Ni);
4537 - 2.0 *
Vt * log(npTmp/Ni);
4542 if (VminBC >
bcVec[i].Vequ) VminBC =
bcVec[i].Vequ;
4543 if (VmaxBC <
bcVec[i].Vequ) VmaxBC =
bcVec[i].Vequ;
4566 bool bsuccess =
true;
4578 for (iBC=0;iBC<
bcVec.size();++iBC)
4580 int i1 =
bcVec[iBC].meshIndex;
4609 bool bsuccess =
true;
4612 int bcSize=
bcVec.size();
4615 for (iBC=0;iBC<bcSize;++iBC)
4622 for (iBC=0;iBC<bcSize;++iBC)
4654 for (iBC=0;iBC<
bcVec.size();++iBC)
4656 bcVec[iBC].Vckt = (*solVectorPtr)[
bcVec[iBC].lid];
4679 for (
int iBC=0;iBC<
bcVec.size();++iBC)
4683 double delV1 = v1 - v1_old;
4685 if ( delV1 > 1.25 ) v1 = v1_old + 1.25;
4687 if ( delV1 < -0.75) v1 = v1_old - 0.75;
4707 bool bsuccess =
true;
4744 #ifdef Xyce_PDE_DENSITY_CONSTRAINT
4750 #ifdef Xyce_PDE_DENSITY_CONSTRAINT
4788 bool bsuccess =
true;
4790 bool skipOutput =
false;
4801 double outMult =
static_cast<double> (
outputIndex);
4816 if (skipOutput)
return bsuccess;
4860 char filename[32];
for(i=0;i<32;++i) filename[i] = static_cast<char>(0);
4868 sprintf(filename,
"%s.dat",
outputName.c_str());
4876 fp1 = fopen(filename,
"w");
4882 fp1 = fopen(filename,
"w");
4886 fp1 = fopen(filename,
"a");
4895 " TITLE = \"Spatially Dependent data for PDE diode: %s time = %20.12e seconds. equation set = nonlinear Poisson\",\n",
4901 " TITLE = \"Spatially Dependent data for PDE diode: %s time = %20.12e seconds. equation set = drift diffusion\",\n",
4910 " TITLE = \"Spatially Dependent data for PDE diode: %s time = %20.12e seconds.\",\n",
4920 fprintf(fp1,
"%s",
"\tVARIABLES = \"X \",\n");
4922 fprintf(fp1,
"%s",
"\t \"V \",\n");
4923 fprintf(fp1,
"%s",
"\t \"nn (electron dens.) \",\n");
4924 fprintf(fp1,
"%s",
"\t \"np (hole dens.) \",\n");
4925 fprintf(fp1,
"%s",
"\t \"nn*np (carrier product) \",\n");
4926 fprintf(fp1,
"%s",
"\t \"Dopant density \",\n");
4927 fprintf(fp1,
"%s",
"\t \"fabs(Dopant density)\",\n");
4928 fprintf(fp1,
"%s",
"\t \"electron lifetime \",\n");
4929 fprintf(fp1,
"%s",
"\t \"hole lifetime \",\n");
4932 fprintf(fp1,
"%s",
"\t \"Jn \",\n");
4933 fprintf(fp1,
"%s",
"\t \"Jp \",\n");
4934 fprintf(fp1,
"%s",
"\t \"R \",\n");
4935 fprintf(fp1,
"%s",
"\t \"Ex \",\n");
4936 fprintf(fp1,
"%s",
"\t \"Idispl \", \n");
4939 fprintf(fp1,
"%s",
"\t \"Conduction Band, uncorrected \", \n");
4940 fprintf(fp1,
"%s",
"\t \"Valance Band, uncorrected \", \n");
4942 fprintf(fp1,
"%s",
"\t \"Band-gap narrowing, Conduction Band \", \n");
4943 fprintf(fp1,
"%s",
"\t \"Band-gap narrowing, Valance Band \", \n");
4945 fprintf(fp1,
"%s",
"\t \"Conduction Band, corrected for BGN \", \n");
4946 fprintf(fp1,
"%s",
"\t \"Valance Band, corrected for BGN \", \n");
4947 fprintf(fp1,
"%s",
"\t \"Fermi Level\", \n");
4949 fprintf(fp1,
"%s",
"\t \"conduction band DOS\", \n");
4950 fprintf(fp1,
"%s",
"\t \"valance band DOS\", \n");
4952 fprintf(fp1,
"\t \"n0, Fermi-Dirac \",\n");
4953 fprintf(fp1,
"\t \"p0, Fermi-Dirac \",\n");
4954 fprintf(fp1,
"\t \"n0, Boltzmann\",\n");
4955 fprintf(fp1,
"\t \"p0, Boltzmann\",\n");
4956 fprintf(fp1,
"\t \"np0 Fermi-Dirac\",\n");
4957 fprintf(fp1,
"\t \"Ni^2 (Boltzmann np0)\",\n");
4958 fprintf(fp1,
"%s",
"\t \"Ni (intrinsic concentration) \", \n");
4962 fprintf(fp1,
"\tZONE F=POINT,I=%d",
NX);
4966 fprintf(fp1,
" T = \"DCOP step = %d\" \n",
callsOTEC);
4970 fprintf(fp1,
" T = \"time step = %d time = %20.12e\" AUXDATA time = \"%20.12e seconds\" \n",
callsOTEC , time, time);
4973 double vcorrection = 0.0;
4991 fprintf(fp1,
"%s",
"\n");
4996 fprintf(fp1,
"%s",
"\n");
4999 fprintf(fp1,
"%s",
"\n");
5002 fprintf(fp1,
"%s",
"\n");
5006 fprintf(fp1,
"%s",
"\n");
5009 fprintf(fp1,
" %20.12e",
EcVec[i]);
5010 fprintf(fp1,
" %20.12e",
EvVec[i]);
5011 fprintf(fp1,
" %20.12e",
bgnCVec[i]);
5012 fprintf(fp1,
" %20.12e",
bgnVVec[i]);
5016 fprintf(fp1,
" %20.12e", con);
5017 fprintf(fp1,
" %20.12e", val);
5019 fprintf(fp1,
"%s",
"\n");
5021 fprintf(fp1,
" %20.12e",
EfVec[i]);
5022 fprintf(fp1,
" %20.12e",
NcVec[i]);
5023 fprintf(fp1,
" %20.12e",
NvVec[i]);
5031 fprintf(fp1,
" %20.12e",n0);
5032 fprintf(fp1,
" %20.12e",p0);
5037 if (n0 != 0.0) { p0 = Ni*Ni/n0; }
5042 if (p0 != 0.0) { n0 = Ni*Ni/p0; }
5044 fprintf(fp1,
" %20.12e",n0);
5045 fprintf(fp1,
" %20.12e",p0);
5051 fprintf(fp1,
" %20.12e",np0);
5052 fprintf(fp1,
" %20.12e",Ni*Ni);
5053 fprintf(fp1,
" %20.12e",Ni);
5056 fprintf(fp1,
"%s",
"\n");
5084 static const int LEN_IDENT2 = 31;
5086 for (i = 0 ; i < 32; ++i)
5087 fileName[i] = static_cast<char>(0);
5092 FILE * handle1 = fopen(fileName,
"w");
5095 double timeVar = 0.0;
5100 sprintf(title,
"%s",
"Xyce diodePDE 1D output");
5102 fwrite(&inx ,
sizeof( UINT), 1, handle1);
5103 fwrite(&numArrays,
sizeof( UINT), 1, handle1);
5104 fwrite( title ,
sizeof(
char),64, handle1);
5105 fwrite(&timeVar ,
sizeof(
double), 1, handle1);
5107 char names[3][LEN_IDENT2];
5108 sprintf(names[0],
"%s",
"V");
5109 sprintf(names[1],
"%s",
"Ne");
5110 sprintf(names[2],
"%s",
"Np");
5113 for(i=0;i<numArrays;++i)
5115 fwrite(names[i],
sizeof(
char),(LEN_IDENT2), handle1);
5118 double vcorrection = 0.0;
5140 fwrite( &
xVec[0],
sizeof(
double),inx , handle1 );
5143 fwrite( &
VVec[0],
sizeof(
double),inx , handle1 );
5146 fwrite( &
nnVec[0],
sizeof(
double),inx , handle1 );
5149 fwrite( &
npVec[0],
sizeof(
double),inx , handle1 );
5175 for (
int i=0;i<
NX;++i)
5180 double n =
nnVec[i];
5181 double p =
npVec[i];
5182 double tn =
tnVec[i];
5183 double tp =
tpVec[i];
5195 RVec[i] = (Rsrh + Raug);
5229 double n =
nnVec[i];
5230 double p =
npVec[i];
5231 double tn =
tnVec[i];
5232 double tp =
tpVec[i];
5246 dRdnVec[i] = dRsrhdn + dRaugdn;
5247 dRdpVec[i] = dRsrhdp + dRaugdp;
5264 for (
int i=0;i<
LX;++i)
5294 for (
int i=0;i<
LX;++i)
5337 for (
int i=0;i<
LX;++i)
5368 for (
int i=0;i<
LX;++i)
5412 for (
int i=0;i<
LX;++i)
5423 absEx = fabs(
ExVec[i]);
5446 bool bnoChange =
true;
5448 int bcSize=
bcVec.size();
5454 for (iBC=0;iBC<bcSize;++iBC)
5462 for (iBC=0;iBC<bcSize;++iBC)
5474 for (iBC=0;iBC<bcSize;++iBC)
5476 double dV,tmp1V, tmp2V;
5477 tmp1V =
bcVec[iBC].Vckt_final;
5478 tmp2V =
bcVec[iBC].Vckt_old;
5481 bcVec[iBC].Vckt_delta = dV;
5483 bcVec[iBC].Vckt_deltaC = dV/
static_cast<double>(max_PDE_continuation_steps);
5489 if (fabs(
bcVec[iBC].Vckt_deltaC) > maxDelta)
5491 int tmp_steps =
static_cast<int>(fabs(dV)/maxDelta) + 1;
5492 max_PDE_continuation_steps = tmp_steps;
5494 bcVec[iBC].Vckt_deltaC = dV/
static_cast<double>(max_PDE_continuation_steps);
5497 if (fabs(dV) > 1.0e-3) bnoChange =
false;
5500 bcVec[iBC].Vckt_ramp_old =
bcVec[iBC].Vckt_old;
5505 bool bnoChangePhotogen;
5507 bnoChangePhotogen = enablePhotogenContinuation ();
5509 bnoChange = bnoChange && bnoChangePhotogen;
5516 return (!bnoChange);
5531 int bcSize=
bcVec.size();
5532 for (iBC=0;iBC<bcSize;++iBC)
5538 photoA1_old = photoA1_final;
5556 Xyce::dout() << section_divider << std::endl;
5557 Xyce::dout() <<
"Instance::setPDEContinuationAlpha" << std::endl;
5562 int bcSize=
bcVec.size();
5563 for (
int iBC=0;iBC<bcSize;++iBC)
5565 bcVec[iBC].Vckt_ramp =
bcVec[iBC].Vckt_old + (
bcVec[iBC].Vckt_delta)*alpha;
5568 if ((
bcVec[iBC].Vckt_delta > 0 &&
bcVec[iBC].Vckt_ramp >
bcVec[iBC].Vckt_final) ||
5569 (
bcVec[iBC].Vckt_delta <= 0 &&
bcVec[iBC].Vckt_ramp <=
bcVec[iBC].Vckt_final) )
5571 bcVec[iBC].Vckt_ramp =
bcVec[iBC].Vckt_final;
5576 Xyce::dout() <<
" " <<
bcVec[iBC].eName <<
" Vckt_ramp = " <<
bcVec[iBC].Vckt_ramp << std::endl;
5582 photoA1_ramp = photoA1_old + photoA1_Delta * alpha;
5585 if ((photoA1_Delta > 0 && photoA1_ramp > photoA1_final) ||
5586 (photoA1_Delta <= 0 && photoA1_ramp <= photoA1_final) )
5588 photoA1_ramp = photoA1_final;
5593 Xyce::dout() <<
" photoA1_ramp = " << photoA1_ramp << std::endl;
5594 Xyce::dout() << section_divider << std::endl;
5610 .registerDevice(
"pde", 1)
5611 .registerModelType(
"pde", 1)
5612 .registerModelType(
"zod", 1);
const InstanceName & getName() const
std::vector< double > RVec
std::vector< int > edgeBoundarySten
bool setupDopingProfile()
std::vector< pdeFadType > unE_Vec
std::vector< double > bgnCVec
bool loadVecDDForm(double *rhs)
bool updateDependentParameters()
double getNi_old(const std::string &material, double temp)
std::vector< int > li_Vrowarray
std::map< std::string, PDE_1DElectrode * > electrodeMap
bool pdTerminalCurrents()
static ParametricData< MaterialLayer > & getParametricData()
std::vector< double > xVec
const SolverState & solverState_
std::vector< int > heterojunctionSten
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
std::vector< double > xloc_ndope_vec
pdeFadType nMidpoint(pdeFadType &n1, pdeFadType &n2, pdeFadType &E, double h, int z)
void loadErrorWeightMask()
std::vector< std::vector< double * > > fPmatPtr
Linear::System * lasSysPtr
double densityScalarFraction_
static ParametricData< DopeInfo > & getParametricData()
bool cathodeIndex_userGiven
std::vector< std::string > bulkMaterialVec
std::vector< double > VVec
void n0_and_p0(ScalarT const &elec_dens, ScalarT const &hole_dens, ScalarT const &Ni, ScalarT const &cond_band, ScalarT const &vale_band, ScalarT const &eff_dens_cond, ScalarT const &eff_dens_vale, ScalarT const &temp, ScalarT &n0, ScalarT &p0)
static const int NUM_MESH_POINTS
std::vector< double > dJndn1Vec
Linear::Vector * nextSolVectorPtr
std::vector< double > dJpdp1Vec
std::vector< int > stateDispl
std::vector< std::vector< double * > > fNmatPtr
std::map< std::string, int > bcIndexMap
bool given(const std::string ¶meter_name) const
Pure virtual class to augment a linear system.
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
bool loadMatDDForm(Linear::Matrix &mat)
ScalarT np0_calculation(ScalarT const &elec_dens, ScalarT const &hole_dens, ScalarT const &Ni, ScalarT const &cond_band, ScalarT const &vale_band, ScalarT const &eff_dens_cond, ScalarT const &eff_dens_vale, ScalarT const &temp)
bool scaleDensityToMaxDoping_
std::vector< double > NcVec
std::vector< double > dJpdn2Vec
bool columnReorderingFlag
std::vector< int > meshToLID
std::vector< int > li_Prowarray
double dJdp2_qdep(double n1, double n2, double E, const pdeFadType &u, double h, int z)
std::vector< double > npVec
std::vector< double > relPermVec
double pdRaugN(const std::string &material, double ni, double n, double p)
static void readDopingFile(std::string &filename, std::vector< double > &xloc, std::vector< double > &nvec, std::vector< double > &y2, DeviceSupport &devSup)
std::string ndopeFileName
double calcLt(bool holeFlag, double conc)
void jacStampMap_fixOrder(const JacobianStamp &stamp_parent, JacobianStamp &map2_parent, JacobianStamp &stamp, JacobianStamp &map2)
std::vector< double > dxVec
std::vector< double > NiVec
bool updateTemperature(const double &temp_tmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
std::vector< std::vector< double * > > fVmatPtr
std::vector< MaterialLayer * > materialVec
std::vector< double > EiVec
bool fieldDependentMobility
bool fieldDependentMobilityGiven
bool calcBoundaryConditions()
std::vector< int > stateDispl_owned
std::vector< double > EfEffVec
std::vector< double > ExVec
std::vector< double > dJndn2Vec
std::vector< double > dJndp1Vec
std::vector< double > CVec
double calcRaug(const std::string &material, double ni, double n, double p)
std::vector< double > EcVec
Linear::Vector * tmpdIdXPtr
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
std::vector< std::vector< double * > > qPmatPtr
std::vector< double > dRdpVec
static ParametricData< PDE_1DElectrode > & getParametricData()
double getRelPerm(const std::string &material)
std::vector< double > dJpdp2Vec
double workfunc(std::string &metal)
bool loadMatNLPoisson(Linear::Matrix &mat)
std::vector< double > dJndV2Vec
double bandgap(const std::string &material, double temp)
Sacado::Fad::SFad< double, 10 > pdeFadType
std::vector< double > JnxVec
bool loadMatKCLDDForm(Linear::Matrix &mat)
double dJdV2_qdep(double n1, double n2, double E, double u, double h, int z)
std::vector< std::vector< double * > > qVmatPtr
const std::vector< std::vector< int > > & jacobianStamp() const
std::vector< double > EvEffVec
void setParams(const std::vector< Param > ¶ms)
inverse_fermi_one_half_N fdinvObj
void splint(std::vector< double > &xa, std::vector< double > &ya, std::vector< double > &y2a, double x_position, double &y_spline)
std::vector< double > EvVec
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
std::vector< double > tnVec
std::vector< std::vector< int > > li_Vcolarray
const DeviceOptions & getDeviceOptions() const
std::vector< double > EfVec
void addComposite(const char *comp_name, const ParametricData< U > &composite_pars, std::map< std::string, U * > V::*composite_map)
Adds a composite parameter to the parameter map.
bool enablePDEContinuation(int &max_PDE_continuation_steps)
std::vector< int > internalBoundarySten
std::string tunnelingModelName
std::vector< double > xloc_pdope_vec
std::vector< double > dJndV1Vec
std::vector< int > matIndex
static const int MAX_COLS_PER_ROW
bool loadDFDV(int ielectrode, Linear::Vector *dfdvPtr)
bool updateSecondaryState()
const DeviceOptions & deviceOptions_
std::string dopingFileName
bool applyVoltageLimiting()
std::vector< bcData > bcVec
std::vector< double > pdope_vec
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
void setupInfo(std::vector< double > &CVec, std::vector< double > &CdonorVec, std::vector< double > &CacceptorVec, std::vector< double > &xVec, DeviceSupport &devSup)
std::vector< std::pair< int, int > > heterojunctionBCs
double dJdn1_qdep(double n1, double n2, double E, double u, double h, int z)
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
std::vector< double > dJpdV2Vec
Linear::Vector * deviceErrorWeightMask_
Linear::Vector * nextStaVectorPtr
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
std::vector< pdeFadType > upE_Vec
bool obtainNodeVoltages()
Linear::Matrix * dFdxMatrixPtr
double getVoltDepElecDens(double Vmax, double V, double Nd)
bool useLayerCompositeDoping_
double calcRsrh(const std::string &material, double ni, double n, double p, double tn, double tp)
std::vector< int > li_stateDispl
std::vector< double > EiEffVec
bool thermionicEmissionFlag
The Device class is an interface for device implementations.
std::vector< int > jacMap
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
bool calcVoltDepDensities()
std::vector< double > SVec
std::vector< double > dRdnVec
std::vector< double > dJpdn1Vec
void processParams()
processParams post processes the parameters that have been set in the object of the derived class...
bool calcElectronCurrent()
std::vector< std::vector< int > > li_Pcolarray
std::vector< double > ndope_vec
CompositeParam * constructComposite(const std::string &ccompositeName, const std::string ¶mName)
Class Configuration contains device configuration data.
std::string pdopeFileName
void setPDEContinuationAlpha(double alpha)
double pdRsrhN(const std::string &material, double ni, double n, double p, double tn, double tp)
std::vector< double > nnVec
double pdRaugP(const std::string &material, double ni, double n, double p)
double dJdV1_qdep(double n1, double n2, double E, double u, double h, int z)
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
bool anodeIndex_userGiven
bool useVoltageOutputOffset_
bool layerCompositeSpecified
const SolverState & getSolverState() const
std::vector< double > dJpdV1Vec
std::map< std::string, DopeInfo * > dopeInfoMap
std::vector< double > CdonorVec
double affin(const std::string &material)
std::vector< int > boundarySten
std::vector< std::vector< double > > condVec
std::vector< double > bgnVVec
std::vector< double > CacceptorVec
bool disablePDEContinuation()
bool enableContinuationCalled
bool calcTerminalCurrents()
bool calcConductance(int iElectrode, const Linear::Vector *dxdvPtr)
std::vector< double > dJndp2Vec
ScalarT calcMob(MobInfo< ScalarT > &min)
std::vector< double > displCurrent
std::vector< std::vector< int > > jacStamp
std::vector< double > EcEffVec
double J_qdep(double n1, double n2, double E, double u, double h, int z)
double dJdn2_qdep(double n1, double n2, double E, double u, double h, int z)
bool setupMiscConstants()
double getVoltDepHoleDens(double Vmin, double V, double Na)
bool loadVecNLPoisson(double *rhs)
const ExternData & extData
std::vector< double > y2_ndope_vec
std::vector< std::vector< double * > > qNmatPtr
std::vector< double > NvVec
double getNi(const std::string &material, double temp)
Manages parameter binding for class C.
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &model, const FactoryBlock &factory_block)
InstanceBlock represent a device instance line from the netlist.
std::vector< double > y2_pdope_vec
std::vector< double > tpVec
std::vector< std::vector< int > > li_Ncolarray
std::vector< Param > params
Linear::Matrix * dQdxMatrixPtr
bool offsetWithFirstElectrode_
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
std::vector< double > JpxVec
bool updateIntermediateVars()
double pdRsrhP(const std::string &material, double ni, double n, double p, double tn, double tp)
bool loadMatCktTrivial(Linear::Matrix &mat)
std::vector< double > dFdVckt
bool getInstanceBreakPoints(std::vector< Util::BreakPoint > &breakPointTimes)
std::vector< int > li_Nrowarray
bool updatePrimaryState()
CompositeParam is the base class for classes that wish to only manage the processing of parameter dat...
std::vector< std::vector< int > > jacMap2
Linear::Vector * nextStaDerivVectorPtr
bool setupMaterialArrays()
double dJdp1_qdep(double n1, double n2, double E, const pdeFadType &u, double h, int z)
std::vector< double > NiEffVec