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. (Synonym with W parameter)")
186 .setDescription(
"Device width. (Synonym with L parameter)")
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")
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 (SRH) 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.")
283 .setDescription(
"File containing doping profile for P-type dopants.");
287 .setDescription(
"File containing doping profile for N-type dopants.");
291 .setDescription(
"Number of mesh points");
301 .setDescription(
"Anode voltage boundary condition. Only used if device is uncoupled from circuit, and running in diode mode.\n")
306 .setDescription(
"Cathode voltage boundary condition. Only used if device is uncoupled from circuit, and running in diode mode.\n")
312 .setDescription(
"Emitter voltage boundary condition. Only used if device is uncoupled from circuit, and running in BJT mode.\n")
317 .setDescription(
"Collector voltage boundary condition. Only used if device is uncoupled from circuit, and running in BJT mode.\n")
322 .setDescription(
"Base voltage boundary condition. Only used if device is uncoupled from circuit, and running in BJT mode.\n")
327 .setDescription(
"If set to true, then some variables are excluded from the time integration error control calculation.");
331 .setDescription(
"Flag to apply voltage limiting. This is only relevant for an experimental two-level Newton solver.");
335 .setDescription(
"Maximum voltage change used by two-level Newton algorithm.");
340 .setDescription(
"Flag for using old(inaccurate) intrinsic carrier calculation.");
344 .setDescription(
"Use Fermi-Dirac statistics.");
396 maxColsPerRow(MAX_COLS_PER_ROW),
399 indicesSetup_(false),
400 includeBaseNode_(false),
401 useElectrodeSpec_(false),
402 maskVarsTIAFlag_(false),
403 scaleDensityToMaxDoping_(true),
404 densityScalarFraction_(1.0e-1),
405 useVoltageOutputOffset_(true),
406 offsetWithFirstElectrode_(false),
408 useLayerCompositeDoping_(false),
424 useOldNiGiven(false),
426 dopingFileName(
"NOFILE"),
427 ndopeFileName(
"NOFILE"),
428 pdopeFileName(
"NOFILE"),
448 baseLocation(0.5e-3),
449 baseLocationGiven(false),
451 gradedJunctionFlag(false),
452 displCurrentFlag(false),
453 calledBeforeUIVB(false),
457 lastOutputTime(-10.0),
459 outputIntervalGiven(false),
461 outputNLPoisson(false),
465 includeAugerRecomb(true),
466 includeSRHRecomb(true),
467 fermiDiracFlag(false),
468 thermionicEmissionFlag(false),
469 tunnelingModelName(
"none"),
471 anodeIndex_userGiven(false),
472 cathodeIndex_user(0),
473 cathodeIndex_userGiven(false),
476 enableContinuationCalled(false),
477 columnReorderingFlag(false),
478 layerCompositeSpecified(false)
501 UserFatal(*
this) <<
"Too many external nodes are set! Set no more than 3.";
511 if (
given(
"PDOPE_FILE") && !
given(
"NDOPE_FILE") )
513 std::string msg =
"Ndope file specified with no Pdope file. Exiting.";
514 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
517 if ( !
given(
"PDOPE_FILE") &&
given(
"NDOPE_FILE") )
519 std::string msg =
"Pdope file specified with no Ndope file. Exiting.";
520 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
527 if (
given(
"MESHFILE"))
529 std::string msg =
"Instance constructor."
530 "mesh file was specified. The 1D device doesn't need a mesh file."
531 " Either add a model statement of level=2, or get rid of the mesh"
532 " file specification.";
533 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
541 if (
given(
"GNUPLOTLEVEL") && !
given(
"TECPLOTLEVEL"))
556 bool bsuccess =
true;
562 bs1 =
setupMesh (); bsuccess = bsuccess && bs1;
564 bs1 =
setupNodes (); bsuccess = bsuccess && bs1;
585 for (std::map<std::string, DopeInfo *>::iterator it =
dopeInfoMap.begin();
591 for (std::map<std::string, PDE_1DElectrode *>::iterator it =
electrodeMap.begin();
598 for (
int i=0;i<size;++i)
621 if (compositeName ==
"DOPINGPROFILES" || compositeName ==
"REGION")
627 else if (compositeName ==
"NODE" || compositeName ==
"ELECTRODE")
630 ExtendedString electrodeName = paramName;
631 electrodeName.toUpper ();
633 bc.
eName = electrodeName;
634 bc.
nName = paramName;
638 if (electrodeName ==
"ANODE")
656 else if (compositeName ==
"LAYER")
661 return (static_cast<CompositeParam *> (matPtr));
666 "Instance::constructComposite: unrecognized composite name: ";
667 msg += compositeName;
668 N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
804 int collectorIndex=0;
806 bcVec[collectorIndex].eName =
"collector";
808 bcVec[collectorIndex].VequGiven =
given(
"COLLECTOR.BC");
810 bcVec[collectorIndex].areaGiven =
given(
"COLLECTOR.AREA");
811 bcVec[collectorIndex].meshIndex =
LX;
812 bcVec[collectorIndex].neighborNode =
LX-1;
818 bcVec[baseIndex].eName =
"base";
822 for (
int i=0;i<
NX;++i)
825 if (deltaX < minDelta)
833 bcVec[baseIndex].VequGiven =
given(
"BASE.BC");
835 bcVec[baseIndex].areaGiven =
given(
"BASE.AREA");
837 bcVec[baseIndex].meshIndex = bIndex;
838 bcVec[baseIndex].neighborNode =
bcVec[baseIndex].meshIndex-1;
844 bcVec[emitterIndex].eName =
"emitter";
846 bcVec[emitterIndex].VequGiven =
given(
"EMITTER.BC");
848 bcVec[emitterIndex].areaGiven =
given(
"EMITTER.AREA");
849 bcVec[emitterIndex].meshIndex = 0;
850 bcVec[emitterIndex].neighborNode = 1;
858 bcVec[anodeIndex].eName =
"anode";
860 bcVec[anodeIndex].VequGiven =
given(
"ANODE.BC");
862 bcVec[anodeIndex].areaGiven =
given(
"ANODE.AREA");
863 bcVec[anodeIndex].meshIndex = 0;
864 bcVec[anodeIndex].neighborNode = 1;
870 bcVec[cathodeIndex].eName =
"cathode";
872 bcVec[cathodeIndex].VequGiven =
given(
"CATHODE.BC");
874 bcVec[cathodeIndex].areaGiven =
given(
"CATHODE.AREA");
875 bcVec[cathodeIndex].meshIndex =
LX;
876 bcVec[cathodeIndex].neighborNode =
LX-1;
884 std::vector<int> tmpMeshSten(
NX,0);
886 for (
int iBC=0;iBC<
bcVec.size();++iBC)
894 ExtendedString side = electrode.
side;
898 bcVec[iBC].meshIndex = 0;
899 bcVec[iBC].neighborNode = 1;
902 else if (side ==
"right")
904 bcVec[iBC].meshIndex =
LX;
905 bcVec[iBC].neighborNode =
LX-1;
908 else if (side ==
"middle" || side ==
"mid")
911 double location = electrode.
location;
915 for (
int imesh=0;imesh<
NX;++imesh)
917 double deltaX=fabs(location-
xVec[imesh]);
918 if (deltaX < minDelta)
925 bcVec[iBC].meshIndex = bIndex;
926 bcVec[iBC].neighborNode = bIndex-1;
930 if (tmpMeshSten[bIndex] == 1)
932 std::string msg =
"Instance::setupNodes. Failed to find mesh index for " + bcVec[iBC].eName;
933 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
938 std::string msg =
"Instance::setupNodes. unrecognized side specified.";
939 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
948 bcVec[iBC].areaGiven = electrode.
areaGiven;
951 bcVec[iBC].area = electrode.
area;
958 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
960 Xyce::dout() <<
" area = " <<
area << std::endl;
961 Xyce::dout() <<
" areaGiven = " <<
given(
"AREA") << std::endl;
962 int isize=
bcVec.size();
963 for (
int i=0;i<isize;++i)
965 Xyce::dout() <<
" bcVec["<<i<<
"].area = " <<
bcVec[i].area << std::endl;
966 Xyce::dout() <<
" bcVec["<<i<<
"].areaGiven = " <<
bcVec[i].areaGiven << std::endl;
967 Xyce::dout() <<
" bcVec["<<i<<
"].meshIndex = " <<
bcVec[i].meshIndex << std::endl;
972 int bcSize=
bcVec.size();
973 for (
int i=0;i<bcSize;++i)
975 bcVec[i].colArray.resize(colmax,-1);
976 bcVec[i].dIdXcols.resize(colmax,-1);
977 bcVec[i].dIdX.resize(colmax,-1);
978 bcVec[i].dFdVckt.resize(colmax,0.0);
987 condVec[iE].resize(numElectrodes,0.0);
995 for (
int i=0;i<bcSize;++i)
997 int meshIndex=
bcVec[i].meshIndex;
999 if (meshIndex==0 || meshIndex==
LX)
1027 bool compositeGiven=
true;
1033 for (
int i=0;i<matVecSize;++i)
1039 matLay.
LX = matLay.
NX-1;
1054 std::string msg =
"Instance constructor."
1055 " NX parameter was not specified.";
1056 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
1078 int baseIndex_m1 = 0;
1079 int baseIndex_p1 = 0;
1104 int bcSize=
bcVec.size();
1106 for (
int iBC=0;iBC<bcSize;++iBC)
1108 int meshIndex=
bcVec[iBC].meshIndex;
1113 for (
int i=0;i<
NX;++i)
1122 for (iBC=0;iBC<
bcVec.size();++iBC)
1124 iMeshNode =
bcVec[iBC].meshIndex;
1128 std::string msg =
"Instance::setupJacStamp:";
1129 msg +=
"Boundary point not in the stencil.";
1130 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
1133 int iNN =
bcVec[iBC].neighborNode;
1134 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1135 Vindex = baseIndex + Voffset;
1136 Nindex = baseIndex + Noffset;
1137 Pindex = baseIndex + Poffset;
1139 if (iMeshNode > iNN)
1141 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1143 Vindex_m1 = baseIndex_m1 + Voffset;
1144 Nindex_m1 = baseIndex_m1 + Noffset;
1145 Pindex_m1 = baseIndex_m1 + Poffset;
1159 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1161 Vindex_p1 = baseIndex_p1 + Voffset;
1162 Nindex_p1 = baseIndex_p1 + Noffset;
1163 Pindex_p1 = baseIndex_p1 + Poffset;
1181 for (iBC=0;iBC<
bcVec.size();++iBC)
1183 iMeshNode =
bcVec[iBC].meshIndex;
1184 int iNN =
bcVec[iBC].neighborNode;
1187 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1188 Vindex = baseIndex + Voffset;
1189 Nindex = baseIndex + Noffset;
1190 Pindex = baseIndex + Poffset;
1198 if (iMeshNode < iNN)
1200 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1201 Vindex_p1 = baseIndex_p1 + Voffset;
1202 Nindex_p1 = baseIndex_p1 + Noffset;
1203 Pindex_p1 = baseIndex_p1 + Poffset;
1206 jacStamp[Vindex][col++] = NodeIndex;
1208 jacStamp[Vindex][col++] = Vindex_p1;
1212 jacStamp[Nindex][col++] = Nindex_p1;
1214 jacStamp[Nindex][col++] = Pindex_p1;
1218 jacStamp[Pindex][col++] = Pindex_p1;
1220 jacStamp[Pindex][col++] = Nindex_p1;
1224 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1225 Vindex_m1 = baseIndex_m1 + Voffset;
1226 Nindex_m1 = baseIndex_m1 + Noffset;
1227 Pindex_m1 = baseIndex_m1 + Poffset;
1230 jacStamp[Vindex][col++] = Vindex_m1;
1232 jacStamp[Vindex][col++] = NodeIndex;
1235 jacStamp[Nindex][col++] = Nindex_m1;
1237 jacStamp[Nindex][col++] = Pindex_m1;
1241 jacStamp[Pindex][col++] = Pindex_m1;
1243 jacStamp[Pindex][col++] = Nindex_m1;
1254 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1255 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1256 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1258 Vindex_m1 = baseIndex_m1 + Voffset;
1259 Nindex_m1 = baseIndex_m1 + Noffset;
1260 Pindex_m1 = baseIndex_m1 + Poffset;
1261 Vindex = baseIndex + Voffset;
1262 Nindex = baseIndex + Noffset;
1263 Pindex = baseIndex + Poffset;
1264 Vindex_p1 = baseIndex_p1 + Voffset;
1265 Nindex_p1 = baseIndex_p1 + Noffset;
1266 Pindex_p1 = baseIndex_p1 + Poffset;
1271 jacStamp[Vindex][col++] = NodeIndex;
1272 jacStamp[Vindex][col++] = Vindex_m1;
1274 jacStamp[Vindex][col++] = Vindex_p1;
1281 jacStamp[Nindex][col++] = Nindex_m1;
1283 jacStamp[Nindex][col++] = Nindex_p1;
1284 jacStamp[Nindex][col++] = Vindex_m1;
1286 jacStamp[Nindex][col++] = Vindex_p1;
1287 jacStamp[Nindex][col++] = Pindex_m1;
1289 jacStamp[Nindex][col++] = Pindex_p1;
1294 jacStamp[Pindex][col++] = Pindex_m1;
1296 jacStamp[Pindex][col++] = Pindex_p1;
1297 jacStamp[Pindex][col++] = Vindex_m1;
1299 jacStamp[Pindex][col++] = Vindex_p1;
1300 jacStamp[Pindex][col++] = Nindex_m1;
1302 jacStamp[Pindex][col++] = Nindex_p1;
1307 std::string msg =
"Instance::setupJacStamp:";
1308 msg +=
"Boundary point not in the stencil.";
1309 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
1314 for (iMeshNode=0;iMeshNode<
NX;++iMeshNode)
1318 baseIndex_m1 = numVars*
meshToLID[iMeshNode-1] + extVarOffset;
1319 baseIndex = numVars*
meshToLID[iMeshNode ] + extVarOffset;
1320 baseIndex_p1 = numVars*
meshToLID[iMeshNode+1] + extVarOffset;
1322 Vindex_m1 = baseIndex_m1 + Voffset;
1323 Nindex_m1 = baseIndex_m1 + Noffset;
1324 Pindex_m1 = baseIndex_m1 + Poffset;
1325 Vindex = baseIndex + Voffset;
1326 Nindex = baseIndex + Noffset;
1327 Pindex = baseIndex + Poffset;
1328 Vindex_p1 = baseIndex_p1 + Voffset;
1329 Nindex_p1 = baseIndex_p1 + Noffset;
1330 Pindex_p1 = baseIndex_p1 + Poffset;
1335 jacStamp[Vindex][col++] = Vindex_m1;
1337 jacStamp[Vindex][col++] = Vindex_p1;
1344 jacStamp[Nindex][col++] = Nindex_m1;
1346 jacStamp[Nindex][col++] = Nindex_p1;
1347 jacStamp[Nindex][col++] = Vindex_m1;
1349 jacStamp[Nindex][col++] = Vindex_p1;
1350 jacStamp[Nindex][col++] = Pindex_m1;
1352 jacStamp[Nindex][col++] = Pindex_p1;
1357 jacStamp[Pindex][col++] = Pindex_m1;
1359 jacStamp[Pindex][col++] = Pindex_p1;
1360 jacStamp[Pindex][col++] = Vindex_m1;
1362 jacStamp[Pindex][col++] = Vindex_p1;
1363 jacStamp[Pindex][col++] = Nindex_m1;
1365 jacStamp[Pindex][col++] = Nindex_p1;
1368 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1372 Xyce::dout() <<
"jacStamp size = " << jacSize << std::endl;
1374 for(
int i=0;i<jacSize;++i)
1377 for (
int j=0;j<colSize;++j)
1379 Xyce::dout() <<
" jacStamp["<<i<<
"]["<<j<<
"] = " <<
jacStamp[i][j] << std::endl;
1407 int mapSize =
jacMap.size();
1408 for (
int i=0;i<mapSize;++i)
1412 for (
int j=0;j<
jacStamp[i].size();++j)
1426 std::vector< std::vector<int> > tempStamp_eric;
1427 std::vector< std::vector<int> > tempMap2_eric;
1449 for (
int i = 0; i <
NX; ++i)
1453 std::ostringstream oss;
1460 std::ostringstream oss;
1467 std::ostringstream oss;
1483 const std::vector<int> & extLIDVecRef)
1488 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1490 Xyce::dout() << section_divider << std::endl;
1491 Xyce::dout() <<
"Instance::registerLIDs:\n";
1492 Xyce::dout() <<
" name = " <<
getName() << std::endl;
1493 Xyce::dout() <<
" numInt = " <<
numIntVars << std::endl;
1494 Xyce::dout() <<
" numEXt = " <<
numExtVars << std::endl;
1495 Xyce::dout() <<
" NX = " <<
NX << std::endl;
1502 for (
int iBC=0;iBC<
bcVec.size();++iBC)
1520 for (
int iBC=0;iBC<
bcVec.size();++iBC)
1522 meshIndex =
bcVec[iBC].meshIndex;
1531 for (meshIndex=0;meshIndex<
NX;++meshIndex)
1540 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
1542 Xyce::dout() <<
"\n solution indices:\n";
1544 for (
int i=0;i<
NX;++i)
1546 Xyce::dout() <<
" li_Vrowarray["<<i<<
"] = " <<
li_Vrowarray[i];
1547 Xyce::dout() <<
"\tli_Nrowarray["<<i<<
"] = " <<
li_Nrowarray[i];
1548 Xyce::dout() <<
"\tli_Prowarray["<<i<<
"] = " <<
li_Prowarray[i] << std::endl;
1550 Xyce::dout() << section_divider << std::endl;
1567 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1569 Xyce::dout() << std::endl;
1570 Xyce::dout() << section_divider << std::endl;
1571 Xyce::dout() <<
" In Instance::registerStateLIDs\n\n";
1572 Xyce::dout() <<
" name = " <<
getName() << std::endl;
1573 Xyce::dout() <<
" Number of State LIDs: " <<
numStateVars << std::endl;
1581 for (i=0;i<
bcVec.size();++i)
1586 for (i=0,j=2;i<
NX-1;++i,++j)
1591 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1593 Xyce::dout() <<
" State indices:" << std::endl;
1594 Xyce::dout() << std::endl;
1595 for (i=0;i<
bcVec.size();++i)
1597 Xyce::dout() <<
"bcVec["<<i<<
"].li_stateC = "<<
bcVec[i].li_stateC<< std::endl;
1599 Xyce::dout() << std::endl;
1601 Xyce::dout() <<
" Displacement current state variable local indices:" << std::endl;
1602 for (i=0;i<NX-1;++i)
1604 Xyce::dout() <<
" li_stateDispl["<<i<<
"] = " <<
li_stateDispl[i] << std::endl;
1606 Xyce::dout() << section_divider << std::endl;
1632 (
const std::vector< std::vector<int> > & jacLIDVec )
1647 int extVarOffset = numExtVars;
1649 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1651 Xyce::dout() << section_divider << std::endl;
1652 Xyce::dout() <<
"Instance::registerJacLIDs" << std::endl;
1654 int jacLIDSize = jacLIDVec.size();
1655 Xyce::dout() <<
"jacLIDSize = " << jacLIDSize << std::endl;
1656 for (i=0;i<jacLIDSize;++i)
1658 int jacLIDcolSize = jacLIDVec[i].size();
1659 Xyce::dout() << std::endl;
1660 Xyce::dout() <<
"jacLIDVec["<<i<<
"].size = " << jacLIDcolSize << std::endl;
1661 for (j=0;j<jacLIDcolSize;++j)
1663 Xyce::dout() <<
"jacLIDVec["<<i<<
"]["<<j<<
"] = ";
1664 Xyce::dout() << jacLIDVec[i][j] << std::endl;
1669 li_Vcolarray.resize(NX);
1670 li_Ncolarray.resize(NX);
1671 li_Pcolarray.resize(NX);
1674 for (
int iBC=0;iBC<bcVec.size();++iBC)
1677 int numCols = jacLIDVec[iBC].size();
1678 bcVec[iBC].li_colArray.resize(numCols,-1);
1680 for (i1=0;i1<numCols;++i1)
1682 bcVec[iBC].li_colArray[i1] = jacLIDVec[iBC][i1];
1685 int iMeshNode = bcVec[iBC].meshIndex;
1687 bcVec[iBC].lidOffset = jacLIDVec[iBC][0];
1689 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1691 Xyce::dout() << std::endl;
1692 for(i=0;i<bcVec[iBC].li_colArray.size();++i)
1694 Xyce::dout() << bcVec[iBC].eName <<
": li_colArray["<<i<<
"] = "<<bcVec[iBC].li_colArray[i]<< std::endl;
1696 Xyce::dout() << std::endl;
1701 for (iMeshNode=0;iMeshNode<NX;++iMeshNode)
1703 if (boundarySten[iMeshNode]==1)
continue;
1705 baseIndex = numVars*meshToLID[iMeshNode ] + extVarOffset;
1707 Vindex = baseIndex + Voffset;
1708 Nindex = baseIndex + Noffset;
1709 Pindex = baseIndex + Poffset;
1714 li_Vcolarray[iMeshNode].resize(5,-1);
1715 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1716 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1717 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1718 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1719 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1723 li_Ncolarray[iMeshNode].resize(9,-1);
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++];
1730 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1731 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1732 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1737 li_Pcolarray[iMeshNode].resize(9,-1);
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++];
1744 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1745 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1746 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1748 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1750 Xyce::dout() << std::endl;
1751 Xyce::dout() <<
"registerJacLIDs: iMeshNode = " << iMeshNode << std::endl;
1752 Xyce::dout() <<
"jacLIDVec[Vindex].size = " << jacLIDVec[Vindex].size()<<std::endl;
1753 Xyce::dout() <<
"jacLIDVec[Nindex].size = " << jacLIDVec[Nindex].size()<<std::endl;
1754 Xyce::dout() <<
"jacLIDVec[Pindex].size = " << jacLIDVec[Pindex].size()<<std::endl;
1758 Xyce::dout() <<
" li_Vcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1759 Xyce::dout() << li_Vcolarray[iMeshNode][i] << std::endl;
1761 Xyce::dout() << std::endl;
1764 Xyce::dout() <<
" li_Ncolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1765 Xyce::dout() << li_Ncolarray[iMeshNode][i] << std::endl;
1767 Xyce::dout() << std::endl;
1770 Xyce::dout() <<
" li_Pcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1771 Xyce::dout() << li_Pcolarray[iMeshNode][i] << std::endl;
1773 Xyce::dout() << std::endl;
1778 for (
int iBC=0;iBC<bcVec.size();++iBC)
1780 iMeshNode = bcVec[iBC].meshIndex;
1781 int iNN = bcVec[iBC].neighborNode;
1783 baseIndex = numVars*meshToLID[iMeshNode ] + extVarOffset;
1784 Vindex = baseIndex + Voffset;
1785 Nindex = baseIndex + Noffset;
1786 Pindex = baseIndex + Poffset;
1788 if (edgeBoundarySten[iMeshNode]==1)
1792 li_Vcolarray[iMeshNode].resize(3,-1);
1793 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1794 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1795 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1798 if (iMeshNode < iNN)
1801 li_Ncolarray[iMeshNode].resize(3,-1);
1802 li_Ncolarray[iMeshNode][i1++] = -1;
1803 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1804 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1807 li_Pcolarray[iMeshNode].resize(3,-1);
1808 li_Pcolarray[iMeshNode][i1++] = -1;
1809 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1810 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1815 li_Ncolarray[iMeshNode].resize(3,-1);
1816 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1817 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1820 li_Pcolarray[iMeshNode].resize(3,-1);
1821 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1822 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1825 else if (internalBoundarySten[iMeshNode]==1)
1830 li_Vcolarray[iMeshNode].resize(6,-1);
1831 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1832 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1833 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1834 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1835 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1836 li_Vcolarray[iMeshNode][i1++] = jacLIDVec[Vindex][j1++];
1840 li_Ncolarray[iMeshNode].resize(9,-1);
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++];
1847 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1848 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1849 li_Ncolarray[iMeshNode][i1++] = jacLIDVec[Nindex][j1++];
1853 li_Pcolarray[iMeshNode].resize(9,-1);
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++];
1860 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1861 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1862 li_Pcolarray[iMeshNode][i1++] = jacLIDVec[Pindex][j1++];
1866 std::string msg =
"Instance::registerJacLIDs:";
1867 msg +=
"Boundary point not in the stencil.";
1868 N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL,msg);
1871 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
1873 Xyce::dout() << std::endl;
1874 Xyce::dout() <<
"registerJacLIDs: ("<<bcVec[iBC].eName<<
") iMeshNode = ";
1875 Xyce::dout() << iMeshNode << std::endl;
1878 Xyce::dout() <<
" li_Vcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1879 Xyce::dout() << li_Vcolarray[iMeshNode][i] << std::endl;
1881 Xyce::dout() << std::endl;
1884 Xyce::dout() <<
" li_Ncolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1885 Xyce::dout() << li_Ncolarray[iMeshNode][i] << std::endl;
1887 Xyce::dout() << std::endl;
1890 Xyce::dout() <<
" li_Pcolarray["<<iMeshNode<<
"]["<<i<<
"] = ";
1891 Xyce::dout() << li_Pcolarray[iMeshNode][i] << std::endl;
1893 Xyce::dout() << std::endl;
1923 for (
int i=0;i<
NX;++i)
1932 for (
int j=0;j<vSize;++j)
1941 for (
int j=0;j<nSize;++j)
1950 for (
int j=0;j<pSize;++j)
1969 bool bsuccess =
true;
1972 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1974 Xyce::dout() << section_divider << std::endl;
1975 Xyce::dout() <<
"updateIntermediateVars. name = " <<
getName() << std::endl;
1979 bs1 =
calcEfield (); bsuccess = bsuccess && bs1;
1985 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
1987 Xyce::dout() << section_divider << std::endl;
2009 bool bsuccess =
true;
2015 for (iBC=0;iBC<
bcVec.size();++iBC)
2017 int index =
bcVec[iBC].meshIndex;
2018 int iNN=
bcVec[iBC].neighborNode;
2020 double A0=J0*a0*
area;
2022 double sign = ((iNN > index)?1.0:-1.0);
2023 int edgeIndex= ((iNN > index)?index:iNN);
2025 bcVec[iBC].elecCurrent = sign*
JnxVec[edgeIndex]*A0;
2026 bcVec[iBC].holeCurrent = sign*
JpxVec[edgeIndex]*A0;
2030 bcVec[iBC].currentSum =
bcVec[iBC].elecCurrent +
bcVec[iBC].holeCurrent;
2034 std::string & type =
bcVec[iBC].type;
2039 bcVec[iBC].currentSum =
bcVec[iBC].elecCurrent;
2041 else if (type==
"ptype")
2043 bcVec[iBC].currentSum =
bcVec[iBC].holeCurrent;
2047 std::string msg =
"Instance::calcTerminalCurrents";
2048 msg +=
"Unrecognized type on boundary.";
2049 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2054 std::string msg =
"Instance::calcTerminalCurrents";
2055 msg +=
"Unrecognized boundary.";
2056 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2061 bcVec[iBC].currentSum +=
bcVec[iBC].displCurrent;
2065 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2067 Xyce::dout() << Xyce::subsection_divider << std::endl
2068 <<
"Calculated currents, etc., coming from the DD calculation:" << std::endl
2069 <<
" scalingVars.J0 = " << J0<<std::endl
2070 <<
" scalingVars.a0 = " << a0<<std::endl
2071 << Xyce::subsection_divider << std::endl;
2072 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2074 Xyce::dout() <<
bcVec[iBC];
2076 Xyce::dout() << Xyce::subsection_divider << std::endl;
2129 int bcSize =
bcVec.size();
2130 for (iBC=0; iBC < bcSize; ++iBC)
2132 bcVec[iBC].dIdVckt = 0.0;
2138 for (iBC=0;iBC<
bcVec.size();++iBC)
2140 int iN =
bcVec[iBC].meshIndex;
2141 int iNN =
bcVec[iBC].neighborNode;
2142 int dFdVcktIndex = 0;
2158 for (iBC=0;iBC<bcSize;++iBC)
2161 i=
bcVec[iBC].meshIndex;
2165 std::string msg =
"Instance::pdTerminalCurrents";
2166 msg +=
"Unrecognized boundary.";
2167 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2170 int iNN=
bcVec[iBC].neighborNode;
2172 double A0=J0*a0*
area;
2173 std::vector<int> & colA =
bcVec[iBC].li_colArray;
2175 double sign = ((iNN > i)?1.0:-1.0);
2181 double dJndV_nn = 0.0;
2182 double dJpdV_nn = 0.0;
2183 double dJndn_nn = 0.0;
2184 double dJpdp_nn = 0.0;
2217 double Vcoef = (sign* dJndV + sign* dJpdV)*A0;
2218 double Ncoef = (sign* dJndn)*A0;
2219 double Pcoef = (sign* dJpdp)*A0;
2222 double Vcoef_nn = (sign* dJndV_nn + sign* dJpdV_nn)*A0;
2223 double Ncoef_nn = (sign* dJndn_nn)*A0;
2224 double Pcoef_nn = (sign* dJpdp_nn)*A0;
2228 std::string & type =
bcVec[iBC].type;
2236 else if (type==
"ptype")
2243 std::string msg =
"Instance::pdTerminalCurrents";
2244 msg +=
"Unrecognized type on boundary.";
2245 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2255 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2257 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2258 bcVec[iBC].dIdX[count] = Vcoef;
2264 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2266 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2267 bcVec[iBC].dIdX[count] = Vcoef_nn;
2273 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2275 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2276 bcVec[iBC].dIdX[count] = Ncoef;
2282 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2284 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2285 bcVec[iBC].dIdX[count] = Ncoef_nn;
2291 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2293 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2294 bcVec[iBC].dIdX[count] = Pcoef;
2300 if (
bcVec[iBC].li_colArray[liOffIndex] != -1)
2302 bcVec[iBC].dIdXcols[count] =
bcVec[iBC].li_colArray[liOffIndex];
2303 bcVec[iBC].dIdX[count] = Pcoef_nn;
2338 bool bsuccess =
true;
2340 Linear::Vector & dfdv = *(dfdvPtr);
2397 bool bsuccess =
true;
2398 const Linear::Vector & dxdv = *dxdvPtr;
2400 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2402 Xyce::dout() << section_divider <<
"\n";
2403 Xyce::dout() <<
"calcConductances name = " <<
getName() << std::endl;
2404 Xyce::dout() <<
"electrode = " <<
bcVec[iElectrode].eName;
2405 Xyce::dout() <<
" dIdVckt = " <<
bcVec[iElectrode].dIdVckt;
2406 Xyce::dout() << std::endl;
2407 Xyce::dout() << std::endl;
2410 if (!(
bcVec[iElectrode].dxdvAllocated))
2413 bcVec[iElectrode].dxdvAllocated =
true;
2419 *(
bcVec[iElectrode].dxdvPtr) = *(dxdvPtr);
2426 double dIidVj = 0.0;
2427 double dIidVj_chain = 0.0;
2443 if (iElectrode != iEqu) dIidVj = 0.0;
2444 else dIidVj =
bcVec[iEqu].dIdVckt;
2448 int DIDXSize =
bcVec[iEqu].dIdX.size();
2449 for (
int iDIDX=0;iDIDX<DIDXSize;++iDIDX)
2451 int index =
bcVec[iEqu].dIdXcols[iDIDX];
2452 double coef =
bcVec[iEqu].dIdX[iDIDX];
2454 if (index < 0)
continue;
2461 std::ostringstream oss;
2462 oss <<
"dIdX" << std::setw(2) << std::setfill(
'0') << iEqu <<
".txt";
2469 Gij = dIidVj_chain + dIidVj;
2471 condVec[iEqu][iElectrode] = Gij;
2473 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2475 char outstring[128];
2476 double Itmp =
bcVec[iEqu].currentSum;
2477 double Vtmp =
bcVec[iEqu].Vckt -
bcVec[iElectrode].Vckt;
2479 double GV = Gij*Vtmp;
2480 for(
int i=0;i<128;++i) outstring[i] = static_cast<char>(0);
2482 "(%2d,%2d): dotPr=%12.4e G=%12.4e",
2483 iEqu,iElectrode,dIidVj_chain,Gij);
2484 Xyce::dout() << std::string(outstring) << std::endl;
2487 "(%2d,%2d): G=%12.4e G*V=%12.4e I=%12.4e V=%12.4e",
2488 iEqu,iElectrode,Gij,GV,Itmp,Vtmp);
2489 Xyce::dout() << std::string(outstring) << std::endl;
2493 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
2495 Xyce::dout() << section_divider << std::endl;
2512 bool bsuccess =
true;
2516 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2518 int li_state=
bcVec[iBC].li_stateC;
2519 staVector[li_state] =
bcVec[iBC].currentSum;
2525 for (i = 0; i<
NX-1; ++i)
2544 bool bsuccess =
true;
2549 for(
int i = 0; i<
NX-1; ++i)
2584 for (
int i=0;i<
NX;++i)
2587 (*maskVectorPtr)[Vrow] = 0.0;
2588 (*maskVectorPtr)[Vrow] = 0.0;
2604 bool bsuccess =
true;
2632 bool bsuccess =
true;
2634 int Vrow(-1), Nrow(-1), Prow(-1);
2646 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2648 int i =
bcVec[iBC].meshIndex;
2655 rhs[Vrow] +=
VVec[i] - (
bcVec[iBC].Vequ);
2662 for (
int ihet=0;ihet<hetSize;++ihet)
2701 coef2 = -(holeDens-elecDens+
CVec[i]);
2724 bool bsuccess =
true;
2726 int Vrow, Nrow, Prow;
2734 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2736 rhs[
bcVec[iBC].lid] += bcVec[iBC].currentSum;
2744 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2746 int i =
bcVec[iBC].meshIndex;
2760 std::string & type =
bcVec[iBC].type;
2768 else if (type==
"ptype")
2775 std::string msg =
"Instance::loadVecDDForm";
2776 msg +=
"Unrecognized type on boundary.";
2777 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2782 std::string msg =
"Instance::loadVecDDForm";
2783 msg +=
"Unrecognized stencil on boundary.";
2784 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
2830 std::vector<Util::BreakPoint> &breakPointTimes)
2848 bool bsuccess =
true;
2849 int Vrow, Nrow, Prow;
2853 double rUt = 1.0/
Ut;
2855 double elecDens, holeDens;
2863 for (iBC=0;iBC<
bcVec.size();++iBC)
2865 mat[
bcVec[iBC].lid][
bcVec[iBC].lidOffset] = 1.0;
2869 for (
int iBC=0;iBC<
bcVec.size();++iBC)
2871 int i =
bcVec[iBC].meshIndex;
2882 mat[Vrow][offset1] = 0.0;
2883 mat[Vrow][offset2] = 1.0;
2884 mat[Vrow][offset3] = 0.0;
2888 mat[Vrow][offset1] = 0.0;
2889 mat[Vrow][offset2] = 1.0;
2890 mat[Vrow][offset3] = 0.0;
2894 mat[Vrow][offset1] = 0.0;
2895 mat[Vrow][offset2] = 0.0;
2896 mat[Vrow][offset3] = 1.0;
2906 for (
int ihet=0;ihet<hetSize;++ihet)
2929 Xyce::dout() <<
"ihet="<<ihet<<
" perm1/dx1="<<perm1/dx1<<
" perm2/dx2="<<perm2/dx2;
2930 Xyce::dout() <<
" Vrow="<<Vrow<<
" Nrow="<<Nrow<<
" Prow="<<Prow<<std::endl;
2933 mat[Vrow][offset1] = perm1/dx1;
2934 mat[Vrow][offset2] = -perm1/dx1;
2935 mat[Vrow][offset3] = -perm2/dx2;
2946 mat[Nrow][li_Ncolarray[i2][1]] = 1.0;
2947 mat[Prow][li_Pcolarray[i2][1]] = 1.0;
2974 mat[Vrow][offset1] = -L0/(dx1*dx2);
2975 mat[Vrow][offset2] = 2.0*L0/(dx1*dx2) + rUt*holeDens + rUt*elecDens;
2976 mat[Vrow][offset3] = -L0/(dx1*dx2);
3008 for (iBC=0;iBC<
bcVec.size();++iBC)
3011 i=
bcVec[iBC].meshIndex;
3015 std::string msg =
"Instance::loadMatKCLForm";
3016 msg +=
"Unrecognized boundary.";
3017 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
3020 int iNN=
bcVec[iBC].neighborNode;
3021 li_row =
bcVec[iBC].lid;
3023 double A0=J0*a0*
area;
3024 std::vector<int> & colA =
bcVec[iBC].li_colArray;
3026 double sign = ((iNN > i)?1.0:-1.0);
3034 double dJndV_nn = 0.0;
3035 double dJpdV_nn = 0.0;
3036 double dJndn_nn = 0.0;
3037 double dJndp_nn = 0.0;
3038 double dJpdp_nn = 0.0;
3039 double dJpdn_nn = 0.0;
3080 double Vcoef = sign*(dJndV + dJpdV)*A0;
3081 double Ncoef = sign*(dJndn + dJpdn)*A0;
3082 double Pcoef = sign*(dJndp + dJpdp)*A0;
3085 double Vcoef_nn = sign*(dJndV_nn + dJpdV_nn)*A0;
3086 double Ncoef_nn = sign*(dJndn_nn + dJpdn_nn)*A0;
3087 double Pcoef_nn = sign*(dJndp_nn + dJpdp_nn)*A0;
3091 std::string & type =
bcVec[iBC].type;
3099 else if (type==
"ptype")
3106 std::string msg =
"Instance::loadMatKCLForm";
3107 msg +=
"Unrecognized type on boundary.";
3108 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
3114 mat[li_row][colA[liOffIndex++]] += Vcoef;
3117 mat[li_row][colA[liOffIndex++]] += Vcoef_nn;
3120 mat[li_row][colA[liOffIndex++]] += Ncoef;
3123 mat[li_row][colA[liOffIndex++]] += Ncoef_nn;
3126 mat[li_row][colA[liOffIndex++]] += Pcoef;
3129 mat[li_row][colA[liOffIndex++]] += Pcoef_nn;
3146 bool bsuccess =
true;
3151 for (iBC=0;iBC<
bcVec.size();++iBC)
3153 mat[
bcVec[iBC].lid][
bcVec[iBC].lidOffset] = 1.0;
3169 bool bsuccess =
true;
3172 int Vrow, Nrow, Prow;
3183 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
3185 for (
int i=1;i<
LX;++i)
3196 bsuccess = bsuccess && bs1;
3201 bsuccess = bsuccess && bs1;
3205 for (
int iBC=0;iBC<
bcVec.size();++iBC)
3207 int i =
bcVec[iBC].meshIndex;
3215 mat[Vrow][li_Vcolarray[i][1]] = 1.0;
3216 mat[Vrow][li_Vcolarray[i][2]] = 0.0;
3224 mat[Vrow][li_Vcolarray[i][1]] = 1.0;
3233 mat[Vrow][li_Vcolarray[i][2]] = 1.0;
3235 std::string & type =
bcVec[iBC].type;
3248 mat[Prow][li_Pcolarray[i][1]] =
3252 mat[Prow][li_Pcolarray[i][2]] = -
dJpdp2Vec[i]/aveDx;
3255 mat[Prow][li_Pcolarray[i][3]] = (
dJpdV1Vec[i-1]/aveDx);
3258 mat[Prow][li_Pcolarray[i][4]] =
3262 mat[Prow][li_Pcolarray[i][5]] = (-
dJpdV2Vec[i]/aveDx);
3268 mat[Prow][li_Pcolarray[i][6]] =
dJpdn1Vec[i-1]/aveDx;
3271 mat[Prow][li_Pcolarray[i][7]] =
3275 mat[Prow][li_Pcolarray[i][8]] = -
dJpdn2Vec[i]/aveDx;
3277 else if (type==
"ptype")
3287 mat[Nrow][li_Ncolarray[i][1]] =
3291 mat[Nrow][li_Ncolarray[i][2]] =
dJndn2Vec[i]/aveDx;
3294 mat[Nrow][li_Ncolarray[i][3]] = (-
dJndV1Vec[i-1]/aveDx);
3297 mat[Nrow][li_Ncolarray[i][4]] =
3301 mat[Nrow][li_Ncolarray[i][5]] = (
dJndV2Vec[i]/aveDx);
3304 mat[Nrow][li_Ncolarray[i][6]] =
dJndp1Vec[i-1]/aveDx;
3307 mat[Nrow][li_Ncolarray[i][7]] =
3311 mat[Nrow][li_Ncolarray[i][8]] = -
dJndp2Vec[i]/aveDx;
3315 std::string msg =
"Instance::loadMatDDForm";
3316 msg +=
"Unrecognized type on boundary.";
3317 N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
3336 double dx1 =
dxVec[i-1];
3337 double dx2 =
dxVec[i];
3344 *(
fVmatPtr[i][1])=(2.0*L0/(dx1*dx2));
3435 for (
int i=0;i<
NX;++i)
3457 bool bsuccess =
true;
3470 mi.
N = (fabs(
CVec[i+1])+fabs(
CVec[i]))*0.5;
3479 if (mi.
N == 0.0) mi.
N = 1.0;
3513 Xyce::dout() <<
"\tunE["<<i<<
"]="<<
unE_Vec[i];
3514 Xyce::dout() <<
"\tupE["<<i<<
"]="<<
upE_Vec[i];
3515 Xyce::dout() << std::endl;
3548 bool bsuccess =
true;
3594 for (
int i=0;i<
NX;++i)
3612 bool bsuccess (
false);
3613 bool fromFile (
false);
3621 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) &&
getSolverState().debugTimeFlag)
3623 Xyce::dout() << section_divider << std::endl;
3624 Xyce::dout() <<
"Instance::setupDopingProfile\n";
3664 double xtmp =
xVec[i];
3665 double ndopeDopeValue(0.0), pdopeDopeValue(0.0);
3670 CVec[i] = ndopeDopeValue-pdopeDopeValue;
3683 for (iBC=0;iBC<
bcVec.size();++iBC)
3685 int i =
bcVec[iBC].meshIndex;
3688 bcVec[iBC].type =
"ntype";
3692 bcVec[iBC].type =
"ptype";
3698 Xyce::dout() <<
"Na = " <<
Na << std::endl;
3699 Xyce::dout() <<
"Nd = " <<
Nd << std::endl;
3702 Xyce::dout() <<
"x[" << i <<
"] = " <<
xVec[i] <<
"\t";
3703 Xyce::dout() <<
"C[" << i <<
"] = " <<
CVec[i] << std::endl;
3706 Xyce::dout() << section_divider << std::endl;
3731 bool bsuccess =
true;
3747 midpoint =
width/2.0;
3748 XL = midpoint -
WJ/2.0;
3749 XR = midpoint +
WJ/2.0;
3778 std::map<std::string, DopeInfo *>::iterator iter;
3779 std::map<std::string, DopeInfo *>::iterator start =
dopeInfoMap.begin();
3780 std::map<std::string, DopeInfo *>::iterator end =
dopeInfoMap.end();
3782 for ( iter = start; iter != end; ++iter )
3800 if (
Na == 0.0 ||
Nd == 0.0)
3802 UserError(*
this) <<
"Mistake in doping. Na=" <<
Na <<
" Nd=" <<
Nd;
3825 matPtr->
name=
"FULLDOMAIN";
3861 int totalMeshIndex = 1;
3862 for (
int imat=0;imat<matVecSize;++imat)
3866 matLay.
LX = matLay.
NX-1;
3867 matLay.
begin = totalMeshIndex-1;
3873 double dx = matLay.
width /(
static_cast<double>(matLay.
LX));
3879 Xyce::dout() <<
"Setting xVec["<<matLay.
begin<<
"] to "<<
xVec[matLay.
begin] <<
"."<<std::endl;
3881 std::pair<int,int> hetPair = std::make_pair (matLayPrev.
end, matLay.
begin);
3887 for (
int ix=matLay.
begin;ix<=matLay.
end;++ix,++totalMeshIndex,++iloc)
3889 double extra=
static_cast<double>(iloc)*dx;
3890 xVec[ix] = base + extra;
3893 for (
int ix=matLay.
begin;ix<matLay.
end;++ix)
3908 double dx_tmp =
width/(
static_cast<double>(
LX));
3910 for (
int i=0;i<
NX;++i)
3912 xVec[i] =
static_cast<double>(i)*dx_tmp;
3915 for (
int i=0;i<
LX;++i)
3922 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
3924 for (
int i=0;i<
NX;++i)
3926 Xyce::dout() <<
"x["<<i<<
"] = " <<
xVec[i];
3927 Xyce::dout() <<
"\tdx["<<i<<
"] = " <<
dxVec[i];
3928 Xyce::dout() << std::endl;
3931 Xyce::dout() <<
"heterojunction boundary points:" <<std::endl;
3978 dnbnd0 = 2.0*pow(dnbnd0,1.5)/1.0e6;
3979 double kbq = 8.6173324e-5;
3983 for (
int im=0;im<size; ++im)
3987 int begin = matLayer.
begin;
3988 int end = matLayer.
end;
3990 double Ec = matLayer.
Ec;
3991 double Ev = matLayer.
Ev;
3992 double bg = fabs(Ec - Ev);
3994 double Nc = dnbnd0*(matLayer.
dnco);
3995 double Nv = dnbnd0*(matLayer.
dnva);
3997 double EcEff = matLayer.
Ec-matLayer.
narco;
3998 double EvEff = matLayer.
Ev+matLayer.
narva;
3999 double bgEff = fabs(EcEff-EvEff);
4002 double Ni = sqrt( Nc * Nv ) * exp (-bg/(2.0*kbq*
Temp));
4003 double NiEff = sqrt( Nc * Nv ) * exp (-bgEff/(2.0*kbq*Temp));
4006 matLayer.
NiEff = NiEff;
4008 matLayer.
bgEff = bgEff;
4010 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
4012 Xyce::dout() <<
"layer="<<matLayer.
name<<
"\t"<<matLayer.
material;
4013 Xyce::dout() <<
"\tNc="<<Nc<<
"\tNv="<<Nv<<
"\tbg="<<bg<<
"\tNi="<<Ni<<std::endl;
4016 for (
int i=begin;i<=end;++i)
4037 EiVec[i] = 0.5*(Ec+Ev)+0.5*
kb*Temp*log(Nv/Nc);
4038 EiEffVec[i] = 0.5*(EcEff+EvEff)+0.5*
kb*Temp*log(Nv/Nc);
4050 for (
int i=0;i<
NX;++i)
4059 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
4061 for (
int im=0;im<size; ++im)
4065 int begin = matLayer.
begin;
4066 int end = matLayer.
end;
4068 Xyce::dout() << matLayer.
name <<
"\tbegin="<<begin<<
"\tend="<<end<<std::endl;
4071 for (
int i=0;i<
NiVec.size();++i)
4073 Xyce::dout() << i <<
"\t"
4080 <<
NiVec[i] <<
"\n";
4082 Xyce::dout() << std::endl;
4120 bool bsuccess =
true;
4202 if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
4204 Xyce::dout() <<
"scalingVars.x0 = " <<
scalingVars.
x0 << std::endl;
4205 Xyce::dout() <<
"scalingVars.a0 = " <<
scalingVars.
a0 << std::endl;
4206 Xyce::dout() <<
"scalingVars.T0 = " <<
scalingVars.
T0 << std::endl;
4207 Xyce::dout() <<
"scalingVars.V0 = " <<
scalingVars.
V0 << std::endl;
4208 Xyce::dout() <<
"scalingVars.C0 = " <<
scalingVars.
C0 << std::endl;
4209 Xyce::dout() <<
"scalingVars.D0 = " <<
scalingVars.
D0 << std::endl;
4210 Xyce::dout() <<
"scalingVars.u0 = " <<
scalingVars.
u0 << std::endl;
4211 Xyce::dout() <<
"scalingVars.R0 = " <<
scalingVars.
R0 << std::endl;
4212 Xyce::dout() <<
"scalingVars.t0 = " <<
scalingVars.
t0 << std::endl;
4213 Xyce::dout() <<
"scalingVars.E0 = " <<
scalingVars.
E0 << std::endl;
4214 Xyce::dout() <<
"scalingVars.F0 = " <<
scalingVars.
F0 << std::endl;
4215 Xyce::dout() <<
"scalingVars.J0 = " <<
scalingVars.
J0 << std::endl;
4216 Xyce::dout() <<
"scalingVars.L0 = " <<
scalingVars.
L0 << std::endl;
4243 for (i=0;i<
bcVec.size();++i)
4300 for (i=0;i<
bcVec.size();++i)
4350 bool bsuccess =
true;
4361 for (
int i=0;i<
NX;++i)
4368 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4369 nnVec[i] = ((Ci>=0)?(tmp):(0.0)) + ((Ci<0)?(Nisq/tmp):(0.0));
4372 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4373 npVec[i] = ((Ci<=0)?(tmp):(0.0)) + ((Ci>0)?(Nisq/tmp):(0.0));
4378 for (
int i=0;i<
NX;++i)
4381 double kbq_ = 8.6173324e-5;
4382 double dope_us_ =
CVec[i];
4383 double temp_us_ =
Temp;
4385 double Nc =
NcVec[i];
4386 double Nv =
NvVec[i];
4388 double cond_band =
EcVec[i];
4389 double vale_band =
EvVec[i];
4390 double bandgap = cond_band-vale_band;
4393 if (dope_us_ >= 0.0)
4399 double ef_m_ec_ = kbq_*temp_us_*
fdinvObj (dope_us_/Nc);
4402 double bgn_ = 3.23e-8 * std::pow(dope_us_, 1.0/3.0);
4405 double ef_m_ev_ = ef_m_ec_ + bandgap-bgn_;
4408 npVec[i] = Nv*std::exp(-ef_m_ev_/(kbq_*temp_us_));
4413 dope_us_ = std::fabs(dope_us_);
4417 double ev_m_ef_ = kbq_*temp_us_*
fdinvObj (dope_us_/Nv);
4420 double bgn_ = 2.55e-8 * std::pow(dope_us_, 1.0/3.0);
4423 double ec_m_ef_ = ev_m_ef_ + (bandgap-bgn_);
4426 nnVec[i] = Nc*std::exp(-ec_m_ef_/(kbq_*temp_us_));
4432 double Vmax = -1.0e99;
4433 double Vmin = +1.0e99;
4434 for (
int i=0;i<
NX;++i)
4447 if (Vmax <
VVec[i]) Vmax =
VVec[i];
4448 if (Vmin >
VVec[i]) Vmin =
VVec[i];
4455 for (
int i=0;i<
NX;++i)
4461 for (
int i=0;i<
NX;++i)
4481 bool bsuccess =
true;
4484 double VminBC =+1.0e+99;
4485 double VmaxBC =-1.0e+99;
4487 int bcSize=
bcVec.size();
4488 for (
int i=0;i<bcSize;++i)
4490 int mIndex =
bcVec[i].meshIndex;
4491 double Ci =
CVec[mIndex];
4492 double Cisq = Ci*Ci;
4493 double Nisq =
Ni*
Ni;
4494 double tmp, nnTmp, npTmp;
4497 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4498 nnTmp = ((Ci>=0)?(tmp):(0.0)) + ((Ci<0)?(Nisq/tmp):(0.0));
4501 tmp = (fabs(Ci)+sqrt(Cisq+4*Nisq))/2.0;
4502 npTmp = ((Ci<=0)?(tmp):(0.0)) + ((Ci>0)?(Nisq/tmp):(0.0));
4507 ExtendedString mater =
bcVec[i].material;
4510 if (
bcVec[i].VequGiven != 1)
4512 if (mater==
"neutral")
4517 bcVec[i].Vequ = +
Vt * log(nnTmp/Ni);
4521 bcVec[i].Vequ = -
Vt * log(npTmp/Ni);
4532 + 2.0 *
Vt * log(nnTmp/Ni);
4539 - 2.0 *
Vt * log(npTmp/Ni);
4544 if (VminBC >
bcVec[i].Vequ) VminBC =
bcVec[i].Vequ;
4545 if (VmaxBC <
bcVec[i].Vequ) VmaxBC =
bcVec[i].Vequ;
4568 bool bsuccess =
true;
4580 for (iBC=0;iBC<
bcVec.size();++iBC)
4582 int i1 =
bcVec[iBC].meshIndex;
4611 bool bsuccess =
true;
4614 int bcSize=
bcVec.size();
4617 for (iBC=0;iBC<bcSize;++iBC)
4624 for (iBC=0;iBC<bcSize;++iBC)
4656 for (iBC=0;iBC<
bcVec.size();++iBC)
4658 bcVec[iBC].Vckt = (*solVectorPtr)[
bcVec[iBC].lid];
4681 for (
int iBC=0;iBC<
bcVec.size();++iBC)
4685 double delV1 = v1 - v1_old;
4687 if ( delV1 > 1.25 ) v1 = v1_old + 1.25;
4689 if ( delV1 < -0.75) v1 = v1_old - 0.75;
4709 bool bsuccess =
true;
4746 #ifdef Xyce_PDE_DENSITY_CONSTRAINT
4752 #ifdef Xyce_PDE_DENSITY_CONSTRAINT
4790 bool bsuccess =
true;
4792 bool skipOutput =
false;
4800 !(force_final_output) &&
4803 double outMult =
static_cast<double> (
outputIndex);
4815 if (force_final_output &&
4818 if (skipOutput)
return bsuccess;
4862 char filename[32];
for(i=0;i<32;++i) filename[i] = static_cast<char>(0);
4870 sprintf(filename,
"%s.dat",
outputName.c_str());
4878 fp1 = fopen(filename,
"w");
4884 fp1 = fopen(filename,
"w");
4888 fp1 = fopen(filename,
"a");
4897 " TITLE = \"Spatially Dependent data for PDE diode: %s time = %20.12e seconds. equation set = nonlinear Poisson\",\n",
4903 " TITLE = \"Spatially Dependent data for PDE diode: %s time = %20.12e seconds. equation set = drift diffusion\",\n",
4912 " TITLE = \"Spatially Dependent data for PDE diode: %s time = %20.12e seconds.\",\n",
4922 fprintf(fp1,
"%s",
"\tVARIABLES = \"X \",\n");
4924 fprintf(fp1,
"%s",
"\t \"V \",\n");
4925 fprintf(fp1,
"%s",
"\t \"nn (electron dens.) \",\n");
4926 fprintf(fp1,
"%s",
"\t \"np (hole dens.) \",\n");
4927 fprintf(fp1,
"%s",
"\t \"nn*np (carrier product) \",\n");
4928 fprintf(fp1,
"%s",
"\t \"Dopant density \",\n");
4929 fprintf(fp1,
"%s",
"\t \"fabs(Dopant density)\",\n");
4930 fprintf(fp1,
"%s",
"\t \"electron lifetime \",\n");
4931 fprintf(fp1,
"%s",
"\t \"hole lifetime \",\n");
4934 fprintf(fp1,
"%s",
"\t \"Jn \",\n");
4935 fprintf(fp1,
"%s",
"\t \"Jp \",\n");
4936 fprintf(fp1,
"%s",
"\t \"R \",\n");
4937 fprintf(fp1,
"%s",
"\t \"Ex \",\n");
4938 fprintf(fp1,
"%s",
"\t \"Idispl \", \n");
4941 fprintf(fp1,
"%s",
"\t \"Conduction Band, uncorrected \", \n");
4942 fprintf(fp1,
"%s",
"\t \"Valance Band, uncorrected \", \n");
4944 fprintf(fp1,
"%s",
"\t \"Band-gap narrowing, Conduction Band \", \n");
4945 fprintf(fp1,
"%s",
"\t \"Band-gap narrowing, Valance Band \", \n");
4947 fprintf(fp1,
"%s",
"\t \"Conduction Band, corrected for BGN \", \n");
4948 fprintf(fp1,
"%s",
"\t \"Valance Band, corrected for BGN \", \n");
4949 fprintf(fp1,
"%s",
"\t \"Fermi Level\", \n");
4951 fprintf(fp1,
"%s",
"\t \"conduction band DOS\", \n");
4952 fprintf(fp1,
"%s",
"\t \"valance band DOS\", \n");
4954 fprintf(fp1,
"\t \"n0, Fermi-Dirac \",\n");
4955 fprintf(fp1,
"\t \"p0, Fermi-Dirac \",\n");
4956 fprintf(fp1,
"\t \"n0, Boltzmann\",\n");
4957 fprintf(fp1,
"\t \"p0, Boltzmann\",\n");
4958 fprintf(fp1,
"\t \"np0 Fermi-Dirac\",\n");
4959 fprintf(fp1,
"\t \"Ni^2 (Boltzmann np0)\",\n");
4960 fprintf(fp1,
"%s",
"\t \"Ni (intrinsic concentration) \", \n");
4964 fprintf(fp1,
"\tZONE F=POINT,I=%d",
NX);
4968 fprintf(fp1,
" T = \"DCOP step = %d\" \n",
callsOTEC);
4972 fprintf(fp1,
" T = \"time step = %d time = %20.12e\" AUXDATA time = \"%20.12e seconds\" \n",
callsOTEC , time, time);
4975 double vcorrection = 0.0;
4993 fprintf(fp1,
"%s",
"\n");
4998 fprintf(fp1,
"%s",
"\n");
5001 fprintf(fp1,
"%s",
"\n");
5004 fprintf(fp1,
"%s",
"\n");
5008 fprintf(fp1,
"%s",
"\n");
5011 fprintf(fp1,
" %20.12e",
EcVec[i]);
5012 fprintf(fp1,
" %20.12e",
EvVec[i]);
5013 fprintf(fp1,
" %20.12e",
bgnCVec[i]);
5014 fprintf(fp1,
" %20.12e",
bgnVVec[i]);
5018 fprintf(fp1,
" %20.12e", con);
5019 fprintf(fp1,
" %20.12e", val);
5021 fprintf(fp1,
"%s",
"\n");
5023 fprintf(fp1,
" %20.12e",
EfVec[i]);
5024 fprintf(fp1,
" %20.12e",
NcVec[i]);
5025 fprintf(fp1,
" %20.12e",
NvVec[i]);
5033 fprintf(fp1,
" %20.12e",n0);
5034 fprintf(fp1,
" %20.12e",p0);
5039 if (n0 != 0.0) { p0 = Ni*Ni/n0; }
5044 if (p0 != 0.0) { n0 = Ni*Ni/p0; }
5046 fprintf(fp1,
" %20.12e",n0);
5047 fprintf(fp1,
" %20.12e",p0);
5053 fprintf(fp1,
" %20.12e",np0);
5054 fprintf(fp1,
" %20.12e",Ni*Ni);
5055 fprintf(fp1,
" %20.12e",Ni);
5058 fprintf(fp1,
"%s",
"\n");
5086 static const int LEN_IDENT2 = 31;
5088 for (i = 0 ; i < 32; ++i)
5089 fileName[i] = static_cast<char>(0);
5094 FILE * handle1 = fopen(fileName,
"w");
5097 double timeVar = 0.0;
5102 sprintf(title,
"%s",
"Xyce diodePDE 1D output");
5104 fwrite(&inx ,
sizeof( UINT), 1, handle1);
5105 fwrite(&numArrays,
sizeof( UINT), 1, handle1);
5106 fwrite( title ,
sizeof(
char),64, handle1);
5107 fwrite(&timeVar ,
sizeof(
double), 1, handle1);
5109 char names[3][LEN_IDENT2];
5110 sprintf(names[0],
"%s",
"V");
5111 sprintf(names[1],
"%s",
"Ne");
5112 sprintf(names[2],
"%s",
"Np");
5115 for(i=0;i<numArrays;++i)
5117 fwrite(names[i],
sizeof(
char),(LEN_IDENT2), handle1);
5120 double vcorrection = 0.0;
5142 fwrite( &
xVec[0],
sizeof(
double),inx , handle1 );
5145 fwrite( &
VVec[0],
sizeof(
double),inx , handle1 );
5148 fwrite( &
nnVec[0],
sizeof(
double),inx , handle1 );
5151 fwrite( &
npVec[0],
sizeof(
double),inx , handle1 );
5177 for (
int i=0;i<
NX;++i)
5182 double n =
nnVec[i];
5183 double p =
npVec[i];
5184 double tn =
tnVec[i];
5185 double tp =
tpVec[i];
5197 RVec[i] = (Rsrh + Raug);
5231 double n =
nnVec[i];
5232 double p =
npVec[i];
5233 double tn =
tnVec[i];
5234 double tp =
tpVec[i];
5248 dRdnVec[i] = dRsrhdn + dRaugdn;
5249 dRdpVec[i] = dRsrhdp + dRaugdp;
5266 for (
int i=0;i<
LX;++i)
5296 for (
int i=0;i<
LX;++i)
5339 for (
int i=0;i<
LX;++i)
5370 for (
int i=0;i<
LX;++i)
5414 for (
int i=0;i<
LX;++i)
5425 absEx = fabs(
ExVec[i]);
5448 bool bnoChange =
true;
5450 int bcSize=
bcVec.size();
5456 for (iBC=0;iBC<bcSize;++iBC)
5464 for (iBC=0;iBC<bcSize;++iBC)
5476 for (iBC=0;iBC<bcSize;++iBC)
5478 double dV,tmp1V, tmp2V;
5479 tmp1V =
bcVec[iBC].Vckt_final;
5480 tmp2V =
bcVec[iBC].Vckt_old;
5483 bcVec[iBC].Vckt_delta = dV;
5485 bcVec[iBC].Vckt_deltaC = dV/
static_cast<double>(max_PDE_continuation_steps);
5491 if (fabs(
bcVec[iBC].Vckt_deltaC) > maxDelta)
5493 int tmp_steps =
static_cast<int>(fabs(dV)/maxDelta) + 1;
5494 max_PDE_continuation_steps = tmp_steps;
5496 bcVec[iBC].Vckt_deltaC = dV/
static_cast<double>(max_PDE_continuation_steps);
5499 if (fabs(dV) > 1.0e-3) bnoChange =
false;
5502 bcVec[iBC].Vckt_ramp_old =
bcVec[iBC].Vckt_old;
5507 bool bnoChangePhotogen;
5509 bnoChangePhotogen = enablePhotogenContinuation ();
5511 bnoChange = bnoChange && bnoChangePhotogen;
5518 return (!bnoChange);
5533 int bcSize=
bcVec.size();
5534 for (iBC=0;iBC<bcSize;++iBC)
5540 photoA1_old = photoA1_final;
5558 Xyce::dout() << section_divider << std::endl;
5559 Xyce::dout() <<
"Instance::setPDEContinuationAlpha" << std::endl;
5564 int bcSize=
bcVec.size();
5565 for (
int iBC=0;iBC<bcSize;++iBC)
5567 bcVec[iBC].Vckt_ramp =
bcVec[iBC].Vckt_old + (
bcVec[iBC].Vckt_delta)*alpha;
5570 if ((
bcVec[iBC].Vckt_delta > 0 &&
bcVec[iBC].Vckt_ramp >
bcVec[iBC].Vckt_final) ||
5571 (
bcVec[iBC].Vckt_delta <= 0 &&
bcVec[iBC].Vckt_ramp <=
bcVec[iBC].Vckt_final) )
5573 bcVec[iBC].Vckt_ramp =
bcVec[iBC].Vckt_final;
5578 Xyce::dout() <<
" " <<
bcVec[iBC].eName <<
" Vckt_ramp = " <<
bcVec[iBC].Vckt_ramp << std::endl;
5584 photoA1_ramp = photoA1_old + photoA1_Delta * alpha;
5587 if ((photoA1_Delta > 0 && photoA1_ramp > photoA1_final) ||
5588 (photoA1_Delta <= 0 && photoA1_ramp <= photoA1_final) )
5590 photoA1_ramp = photoA1_final;
5595 Xyce::dout() <<
" photoA1_ramp = " << photoA1_ramp << std::endl;
5596 Xyce::dout() << section_divider << std::endl;
5612 .registerDevice(
"pde", 1)
5613 .registerModelType(
"pde", 1)
5614 .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
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
double calcLt(bool holeFlag, double conc, std::string material="si")
CompositeParam * constructComposite(const std::string &ccompositeName, const std::string ¶mName)
bool outputPlotFiles(bool force_final_output)
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
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
std::vector< std::vector< int > > li_Ncolarray
Util::Param temp
operating temperature of ckt.
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