Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_2DPDESetup.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_2DPDESetup.C,v $
27 //
28 // Purpose : This file mostly contains functions that are called
29 // once, during the initial setup phase of the 2D PDE
30 // device. There are a couple of exceptions - the mesh
31 // resize functions are called during "re-set-up" phases
32 // of a sensitivity calculation.
33 //
34 // One very important setup function - processParams - is
35 // *not* in this file. It gets its own file,
36 // N_DEV_2DPDEParam.C.
37 //
38 // All of the of the functions pertaining to the global
39 // and local ID setup are in this file.
40 //
41 // Special Notes :
42 //
43 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
44 //
45 // Creation Date : 07/05/03
46 //
47 // Revision Information:
48 // ---------------------
49 //
50 // Revision Number: $Revision: 1.57 $
51 //
52 // Revision Date : $Date: 2014/05/13 14:50:41 $
53 //
54 // Current Owner : $Author: dgbaur $
55 //-------------------------------------------------------------------------
56 
57 #include <Xyce_config.h>
58 
59 
60 // ---------- Standard Includes ----------
61 #ifdef Xyce_DEBUG_DEVICE
62 #include <iostream>
63 #endif
64 
65 // ---------- Xyce Includes ----------
66 #include <N_DEV_2DPDE.h>
67 #include <N_DEV_SolverState.h>
68 #include <N_DEV_Message.h>
69 
70 #include <N_DEV_DeviceOptions.h>
71 #include <N_DEV_MatrixLoadData.h>
72 
73 #include <N_DEV_PDE_2DMesh.h>
74 #include <N_DEV_PDE_Electrode.h>
75 
76 namespace Xyce {
77 namespace Device {
78 namespace TwoDPDE {
79 
80 //-----------------------------------------------------------------------------
81 // Function : Instance::doSensMeshResize
82 // Purpose :
83 // Special Notes : Generally, this will be called for a mesh that was
84 // already scaled, so the resized mesh should be considered
85 // scaled as well.
86 //
87 // As should be obvious from the name, this function is
88 // designed for perturbing the mesh as part of a
89 // sensitivity calculation. As such, a copy of the
90 // original mesh is saved, to be restored after the
91 // calculation is over.
92 //
93 // Scope : public
94 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
95 // Creation Date : 11/26/02
96 //-----------------------------------------------------------------------------
98 {
99  bool bsuccess = true;
100  bool bs1 = true;
101 
102 #ifdef Xyce_DEBUG_DEVICE
103  if (getDeviceOptions().debugLevel > 0)
104  {
105  Xyce::dout() << "In Instance::doSensMeshResize." << std::endl;
106  }
107 #endif
108 
109  // make a copy of the mesh. This will need to be restored later.
110  if (meshCopyContainerPtr == NULL)
111  {
113  }
114  else
115  {
117  }
118 
119  // scale the new size:
120  if (variablesScaled)
121  {
124  }
125 
126  // get the old size:
127  double old_length = meshContainerPtr->getXMax () -
129 
130  double old_width = meshContainerPtr->getYMax () -
132 
133 #ifdef Xyce_DEBUG_DEVICE
134  double lengthRatio = deviceLength/old_length;
135  double widthRatio = deviceWidth/old_width;
136 
137  if (getDeviceOptions().debugLevel > 0)
138  {
139  Xyce::dout() << " x0 = " << scalingVars.x0 << std::endl;
140  Xyce::dout() << " deviceWidth = " << deviceWidth << std::endl;
141  Xyce::dout() << " old_width = " << old_width << std::endl;
142  Xyce::dout() << " widthRatio = " << widthRatio << std::endl;
143  Xyce::dout() << " deviceLength = " << deviceLength << std::endl;
144  Xyce::dout() << " old_length = " << old_length << std::endl;
145  Xyce::dout() << " lengthRatio = " << lengthRatio << std::endl;
146  }
147 #endif
148 
149  // first resize the mesh in the mesh class:
151 
152  // Then update all the mesh sized stuff used in the Instance
153  // class.
156 #ifdef Xyce_DEBUG_DEVICE
157  if (getDeviceOptions().debugLevel > 1)
158  {
159  for (int i=0;i<numMeshPoints;++i)
160  {
161  Xyce::dout() << " x["<<i<<"] = " << xVec[i];
162  Xyce::dout() << " y["<<i<<"] = " << yVec[i];
163  Xyce::dout() << std::endl;
164  }
165  }
166 #endif
167 
168  // now update all the mesh stuff in the 2DPDE class:
169  bs1 = setupBCEdgeAreas (); bsuccess = bsuccess && bs1;
170  bs1 = setupMinDXVector (); bsuccess = bsuccess && bs1;
171 
172 #ifdef Xyce_DEBUG_DEVICE
173  if (getDeviceOptions().debugLevel > 0)
174  {
175  Xyce::dout() << "Done with Instance::doSensMeshResize." << std::endl;
176  }
177 #endif
178 
179  return bsuccess;
180 }
181 
182 //-----------------------------------------------------------------------------
183 // Function : Instance::undoSensMeshResize
184 //
185 // Purpose : This un-does the damage done by doSensMeshResize.
186 //
187 // Special Notes :
188 //
189 // Scope : public
190 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
191 // Creation Date : 11/26/02
192 //-----------------------------------------------------------------------------
194 {
195  bool bsuccess = true;
196  bool bs1 = true;
197  // switch the mesh copy back into the official ptr.:
198  PDE_2DMesh * tmpPtr;
199 
200  tmpPtr = meshContainerPtr;
202  meshCopyContainerPtr = tmpPtr;
203 
204  // Restore all the mesh sized stuff used in the Instance
205  // class.
208 
209  // now update all the mesh stuff in the 2DPDE class:
210  bs1 = setupBCEdgeAreas (); bsuccess = bsuccess && bs1;
211  bs1 = setupMinDXVector (); bsuccess = bsuccess && bs1;
212 
213  return bsuccess;
214 }
215 
216 //-----------------------------------------------------------------------------
217 // Function : Instance::setupMesh
218 //
219 // Purpose : This function should only be called once. It handles
220 // most of the stuff associated with initializing the
221 // mesh class, and all the stuff in Instance
222 // that depends on the mesh.
223 //
224 // Special Notes :
225 //
226 // Scope : public
227 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
228 // Creation Date : 11/26/02
229 //-----------------------------------------------------------------------------
231 {
232 
233  bool bsuccess = true;
234 
235  ///////////////////////////////////////////////////////////////////
236  // First straighten out the electrode map, if it exists.
237  // The electrode map is one of the arguments that need to be passed into
238  // the "internal" mesh setup, so it has to be corrected first.
239  std::vector<DeviceInterfaceNode>::iterator first = dIVec.begin ();
240  std::vector<DeviceInterfaceNode>::iterator last = dIVec.end ();
241  std::vector<DeviceInterfaceNode>::iterator iterV;
242 
243  if (!(electrodeMap.empty ()))
244  {
245  // First make the names in electrodeMap consistent with those in dIVec.
246  for (iterV=first;iterV!=last; ++iterV)
247  {
248  if (!(iterV->given)) continue;
249 
250  if ( electrodeMap.find(iterV->nName) != electrodeMap.end () )
251  {
252  electrodeMap[iterV->nName]->name = iterV->eName;
253  }
254  else
255  {
256  std::string msg = "Instance::doMeshBasedInitializations."
257  "can't find " + iterV->nName + " in the electrode Map\n";
258  N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
259  }
260  }
261 
262 #ifdef Xyce_DEBUG_DEVICE
263  if (getDeviceOptions().debugLevel > 0)
264  {
265  Xyce::dout() << "list of user-specified electrodes:" << std::endl;
266  std::map<std::string, PDE_2DElectrode*>::iterator mapIter;
267  std::map<std::string, PDE_2DElectrode*>::iterator mapStart = electrodeMap.begin();
268  std::map<std::string, PDE_2DElectrode*>::iterator mapEnd = electrodeMap.end();
269 
270  // for ( mapIter = mapStart; mapIter != mapEnd; ++mapIter )
271  // {
272  // Xyce::dout() << *(mapIter->second);
273  // }
274  }
275 #endif
276  }
277 
278  ///////////////////////////////////////////////////////////////////
279  // Allocate the mesh container.
281 
282  if (!given("MESHFILE"))
283  {
284  lout() << "No mesh file specified. Setting meshfile=internal.msh\n" << std::endl;
285  }
286 
287  ///////////////////////////////////////////////////////////////////
288  // Now initialize the mesh either as internal or external.
289  if (meshFileName != "internal" && meshFileName != "internal.msh")
290  {
291 #ifdef Xyce_DEBUG_DEVICE
292  if (getDeviceOptions().debugLevel > 0)
293  {
294  Xyce::dout() << std::endl;
295  Xyce::dout() << "Reading mesh file..." << std::endl;
296  }
297 #endif
298  usingInternalMesh = false;
301  }
302  else
303  {
304 #ifdef Xyce_DEBUG_DEVICE
305  if (getDeviceOptions().debugLevel > 0)
306  {
307  Xyce::dout() << std::endl;
308  Xyce::dout() << "Generating internal mesh..." << std::endl;
309  }
310 #endif
311  usingInternalMesh = true;
312 
313  std::string outputMeshFileName = outputName + ".msh";
317  deviceLength,
318  deviceWidth,
320  outputMeshFileName,
321  electrodeMap,
322  cylGeomFlag);
323  }
324 
325  ///////////////////////////////////////////////////////////////////
330 
331 #ifdef Xyce_DEBUG_DEVICE
332  if (getDeviceOptions().debugLevel > 0)
333  {
334  Xyce::dout() << "\n";
335  Xyce::dout() << "Done setting up the mesh." << std::endl;
336  Xyce::dout() << " numMeshPoints = " << numMeshPoints << "\n";
337  Xyce::dout() << " numMeshEdges = " << numMeshEdges << "\n";
338  Xyce::dout() << " numMeshCells = " << numMeshCells << "\n";
339  }
340 #endif
341 
342  return bsuccess;
343 }
344 
345 //-----------------------------------------------------------------------------
346 // Function : Instance::setupDINodes
347 // Purpose : This function does some miscellaneous setup of the
348 // device interface nodes (boundary condition class).
349 // Mostly this is does some final, misc. cleanup.
350 //
351 // Should be called after setupMesh. Should only be called once.
352 // Special Notes :
353 // Scope : public
354 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
355 // Creation Date : 07/15/03
356 //-----------------------------------------------------------------------------
358 {
359  bool bsuccess = true;
360 
361  std::vector<DeviceInterfaceNode>::iterator first = dIVec.begin ();
362  std::vector<DeviceInterfaceNode>::iterator last = dIVec.end ();
363  std::vector<DeviceInterfaceNode>::iterator iterV;
364 
365  // loop through the boundary condition name vector and
366  // check if it matches the boundary conditions given in the mesh file.
367 
368  for (iterV=first;iterV!=last; ++iterV)
369  {
370  ExtendedString tmpName = iterV->eName;
371  tmpName.toUpper ();
372 
373  bool edgeLabelExist = meshContainerPtr->labelNameExist(tmpName);
374 
375  // If the device interface was given by the user(netlist)
376  // (as a boundary condition), then if it doesn't exist,
377  // then the user has made a mistake in setting up the input file and
378  // the code should exit.
379  if ((iterV->given))
380  {
381  if ( !(edgeLabelExist) )
382  {
384  std::string msg = "Instance::setupDINodes: "
385  "The boundary condition label "+tmpName+
386  " doesn't exist in the mesh file.\n";
387  N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
388  }
389  }
390  else // If this wasn't given, and doesn't exist, that just means it
391  // is part of the default list of boundary condition names,
392  // and should just be removed from the device interface vector.
393  // This does NOT represent a mistake in the netlist.
394  {
395  if ( !(edgeLabelExist) )
396  {
397 #ifdef Xyce_DEBUG_DEVICE
398  if (getDeviceOptions().debugLevel > 0)
399  Xyce::dout() << "Erasing DI: " << iterV->eName << std::endl;
400 #endif
401  dIVec.erase (iterV);
402  }
403  }
404  } // end of iterV loop.
405 
406  // Copy over a few of the material related variables from the electrode
407  // class to the device interface node class.
408  if (!(electrodeMap.empty ()))
409  {
410  // First make the names in electrodeMap consistent with those in dIVec.
411  for (iterV=first;iterV!=last; ++iterV)
412  {
413  if (!(iterV->given)) continue;
414 
415  if ( electrodeMap.find(iterV->nName) != electrodeMap.end () )
416  {
417  // material stuff:
418  iterV->material = electrodeMap[iterV->nName]->material;
419  iterV->materialGiven = electrodeMap[iterV->nName]->materialGiven;
420  iterV->oxideBndryFlag = electrodeMap[iterV->nName]->oxideBndryFlag;
421  iterV->oxthick = electrodeMap[iterV->nName]->oxthick;
422  iterV->oxcharge = electrodeMap[iterV->nName]->oxcharge;
423  }
424  else
425  {
426  std::string msg = "Instance::doMeshBasedInitializations."
427  "can't find " + iterV->nName + " in the electrode Map\n";
428  N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
429  }
430 #ifdef Xyce_DEBUG_DEVICE
431  if (getDeviceOptions().debugLevel > 0)
432  {
433  Xyce::dout() << std::endl;
434  Xyce::dout() << "name = " << iterV->eName << std::endl;
435  Xyce::dout() << " material = " << iterV->material << std::endl;
436  Xyce::dout() << " mat. given = " << iterV->materialGiven << std::endl;
437  Xyce::dout() << " oxide boundary flag = " << iterV->oxideBndryFlag << std::endl;
438  Xyce::dout() << " oxide thickness = " << iterV->oxthick << std::endl;
439  Xyce::dout() << " oxide charge = " << iterV->oxcharge << std::endl;
440  }
441 #endif
442  }
443  }
444 
445  // Loop over the boundaries, and check if each one is a
446  // neumann, or mixed boundary condition for each variable.
447  first = dIVec.begin ();
448  last = dIVec.end ();
449  for (iterV=first;iterV!=last; ++iterV)
450  {
451  ExtendedString tmpName = iterV->nName;
452  tmpName.toLower ();
453 
454 #ifdef Xyce_DEBUG_DEVICE
455  if (getDeviceOptions().debugLevel > 0)
456  Xyce::dout() << "Testing the neumann stuff. Name = " << tmpName << std::endl;
457 #endif
458 
459  if ( tmpBCmap.find(tmpName) != tmpBCmap.end () )
460  {
461  if (tmpBCmap[tmpName] == "NEUMANN")
462  {
463  iterV->neumannBCFlagV = true;
464  iterV->neumannBCFlagN = true;
465  iterV->neumannBCFlagP = true;
466  }
467 
468  if (tmpBCmap[tmpName] == "MIXED")
469  {
470  iterV->neumannBCFlagV = false;
471  iterV->neumannBCFlagN = true;
472  iterV->neumannBCFlagP = true;
473  }
474 
475 #ifdef Xyce_DEBUG_DEVICE
476  if (getDeviceOptions().debugLevel > 0)
477  {
478  Xyce::dout() << "Setting the neumann flags of " << tmpName << ":\n";
479  Xyce::dout() << " Vflag = " << iterV->neumannBCFlagV << std::endl;
480  Xyce::dout() << " Nflag = " << iterV->neumannBCFlagN << std::endl;
481  Xyce::dout() << " Pflag = " << iterV->neumannBCFlagP << std::endl;
482  }
483 #endif
484  }
485  } // end of iterV loop.
486 
487 #ifdef Xyce_DEBUG_DEVICE
488  if (getDeviceOptions().debugLevel > 0)
489  {
490  first = dIVec.begin ();
491  last = dIVec.end ();
492  Xyce::dout() << "Final DI list: " << std::endl;
493  for (iterV=first;iterV!=last; ++iterV)
494  {
495  Xyce::dout() << "DI name:" << iterV->eName;
496  Xyce::dout() << " The neumann flags are:" << std::endl;
497  Xyce::dout() << " Vflag =";
498  if (iterV->neumannBCFlagV) Xyce::dout() <<" true." << std::endl;
499  else Xyce::dout() <<" false." << std::endl;
500  Xyce::dout() << " Nflag =";
501  if (iterV->neumannBCFlagN) Xyce::dout() <<" true." << std::endl;
502  else Xyce::dout() <<" false." << std::endl;
503  Xyce::dout() << " Pflag =";
504  if (iterV->neumannBCFlagP) Xyce::dout() <<" true." << std::endl;
505  else Xyce::dout() <<" false." << std::endl;
506  }
507  }
508 #endif
509 
510  return bsuccess;
511 }
512 
513 //-----------------------------------------------------------------------------
514 // Function : Instance::doAllocations
515 // Purpose : A whole bunch of resizes. Should be called after
516 // setupMesh. Should only be called once.
517 // Special Notes :
518 // Scope : public
519 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
520 // Creation Date : 07/15/03
521 //-----------------------------------------------------------------------------
523 {
524  bool bsuccess = true;
525 
526  // allocate conductance, capacitance array:
527  condVec.resize(numElectrodes);
528  capVec.resize(numElectrodes);
529  for (int iE=0;iE<numElectrodes;++iE)
530  {
531  condVec[iE].resize(numElectrodes,0.0);
532  capVec[iE].resize(numElectrodes,0.0);
533  }
534 
535  // Set up a bunch of mesh-based arrays:
536  // Local allocations:
539 #ifdef Xyce_DEBUG_DEVICE
540  if (getDeviceOptions().debugLevel > 1)
541  {
542  for (int i=0;i<numMeshPoints;++i)
543  {
544  Xyce::dout() << " x["<<i<<"] = " << xVec[i];
545  Xyce::dout() << " y["<<i<<"] = " << yVec[i];
546  Xyce::dout() << std::endl;
547  }
548  }
549 #endif
550 
551  minDXVec.resize (numMeshPoints);
552 
553  areaVec.resize (numMeshPoints);
554 
555  VVec.resize (numMeshPoints);
556  RVec.resize (numMeshPoints);
557  SVec.resize (numMeshPoints);
558  totSrcVec.resize (numMeshPoints);
559  nnVec.resize (numMeshPoints);
560  npVec.resize (numMeshPoints);
561  CVec.resize (numMeshPoints);
562  dRdpVec.resize (numMeshPoints);
563  dRdnVec.resize (numMeshPoints);
564 
565  elecPenalty.resize (numMeshPoints,0.0);
566  holePenalty.resize (numMeshPoints,0.0);
567  pdElecPenalty.resize (numMeshPoints,0.0);
568  pdHolePenalty.resize (numMeshPoints,0.0);
569 
570  unVec.resize (numMeshPoints, 0.0);
571  upVec.resize (numMeshPoints, 0.0);
572  unE_Vec.resize (numMeshEdges, 0.0);
573  upE_Vec.resize (numMeshEdges, 0.0);
574  tnVec.resize (numMeshPoints, 0.0);
575  tpVec.resize (numMeshPoints, 0.0);
576 
577  // assume every node is owned until told otherwise.
578  // These are only really used for boundary conditions.
579  // They may, in fact, not be needed... ERK, 11/09/02
580  vOwnVec.resize (numMeshPoints, 1);
581  nnOwnVec.resize (numMeshPoints, 1);
582  npOwnVec.resize (numMeshPoints, 1);
583 
585 
586  if (sgplotLevel > 0) outputVec.resize(numMeshPoints,0.0);
587 
588  stateDispl.resize(numMeshPoints);
589  stateDispl_owned.resize(numMeshPoints,-1);
590  li_stateDispl.resize(numMeshPoints,0);
591 
592  EfieldVec.resize (numMeshEdges);
593  JnVec.resize (numMeshEdges);
594  JpVec.resize (numMeshEdges);
595  displCurrent.resize(numMeshEdges);
596 
597  dJndn1Vec.resize (numMeshEdges);
598  dJndn2Vec.resize (numMeshEdges);
599  dJndV1Vec.resize (numMeshEdges);
600  dJndV2Vec.resize (numMeshEdges);
601 
602  dJpdn1Vec.resize (numMeshEdges);
603  dJpdn2Vec.resize (numMeshEdges);
604  dJpdV1Vec.resize (numMeshEdges);
605  dJpdV2Vec.resize (numMeshEdges);
606 
607  Vrowarray.resize (numMeshPoints,-1); Vcolarray.resize (numMeshPoints);
608  Nrowarray.resize (numMeshPoints,-1); Ncolarray.resize (numMeshPoints);
609  Prowarray.resize (numMeshPoints,-1); Pcolarray.resize (numMeshPoints);
610 
611  boundarySten.resize(numMeshPoints,0);
612  boundaryStenV.resize(numMeshPoints,0);
613  boundaryStenN.resize(numMeshPoints,0);
614  boundaryStenP.resize(numMeshPoints,0);
615  boundaryTest.resize(numMeshPoints,0);
616 
617  li_Vrowarray.resize (numMeshPoints,0);
618  li_Nrowarray.resize (numMeshPoints,0);
619  li_Prowarray.resize (numMeshPoints,0);
620 
621  labelIndex.resize (numMeshPoints,0);
623 
624  // allocate the boundary condition arrays:
625  std::vector<DeviceInterfaceNode>::iterator first = dIVec.begin ();
626  std::vector<DeviceInterfaceNode>::iterator last = dIVec.end ();
627  std::vector<DeviceInterfaceNode>::iterator iterV;
628 
629  for (iterV=first;iterV!=last; ++iterV)
630  {
631  mLabel * labelPtr = meshContainerPtr->getLabel(iterV->eName);
632  int numPoints = labelPtr->mNodeVector.size();
633  iterV->numBoundaryPoints = numPoints;
634  iterV->VequVec.resize (numPoints,0.0);
635  iterV->VbcVec.resize (numPoints,0.0);
636  iterV->nnbcVec.resize (numPoints,0.0);
637  iterV->npbcVec.resize (numPoints,0.0);
638 
639  for (int i=0;i<iterV->numBoundaryPoints;++i)
640  {
641  mLabel * labelPtr = meshContainerPtr->getLabel(iterV->eName);
642  int nodeIndex = labelPtr->mNodeVector[i];
643  iterV->meshGlobalToLocal[nodeIndex] = i;
644  }
645  }
646 
647  // setup the aiEdge vector for tecplot:
648  aiEdge.resize(numMeshEdges,0);
649  aiEdge_nf.resize(numMeshEdges,0);
650  //electrodeEdge.resize(numMeshEdges,0);
651 
652  // determine the label index for noflux.
653  int nofluxIndex = 0;
654  int numLabels = meshContainerPtr->getNumLabels();
655  for (int i1=0;i1<numLabels;++i1)
656  {
657  mLabel * lPtr = meshContainerPtr->getLabel(i1);
658  if (lPtr->name == "NOFLUX")
659  {
660  nofluxIndex = i1;
661  }
662  }
663 
664  // finish the aiEdge stuff.
665  UINT iE;
666  iNumPlotEdges = 0;
667  iNumPlotEdges_nf = 0;
668  for(iE = 0;iE<numMeshEdges;++iE)
669  {
670  mEdge * edgePtr = meshContainerPtr->getEdge(iE);
671  UINT uLabel = edgePtr->uLabel;
672 
673  mLabel * labelPtr = meshContainerPtr->getLabel(uLabel);
674 
675  if(uLabel != -1u)
676  {
677  if(uLabel != nofluxIndex)
678  {
679  if(labelPtr->uType == TYPE_EDGE)
680  {
681  aiEdge[iE] = 1;
682  ++iNumPlotEdges;
683  }
684  }
685  else
686  {
687  if(labelPtr->uType == TYPE_EDGE)
688  {
689  aiEdge_nf[iE] = 1;
691  }
692  }
693  } // uLabel != -1u
694  }
695 
696  return bsuccess;
697 }
698 
699 //-----------------------------------------------------------------------------
700 // Function : Instance::setupLabelIndex
701 // Purpose : This function sets up the vector, labelIndex
702 //
703 // Special Notes : labelIndex is a key, which maps a node index
704 // to a label index. This is needed information, so that the
705 // load routines can determine what form rhs and
706 // Jacobian entries they should sum for a given node. - Should
707 // they set it up as a interior point, or a boundary, for
708 // example.
709 //
710 // By default, all nodes are assumed to belong to region label.
711 // However, some nodes will also belong to
712 // edges, or other regions, or whatever. Sometimes a node
713 // will be on the node list of more than one region/edge.
714 //
715 // To resolve such descrepancies, this function assumes that
716 // an edge label will take priority over a region label.
717 //
718 //
719 // Scope : public
720 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
721 // Creation Date : 04/29/02
722 //-----------------------------------------------------------------------------
724 {
725 
726  // first, loop over the various non-edge(region) labels, and loop over their
727  // node lists. Set the labelIndex for each of these nodes to correspond
728  // the current region label.
729 
730  int i;
731  std::vector<int>::iterator firstL;
732  std::vector<int>::iterator lastL;
733  std::vector<int>::iterator iterL;
734 
735  for (i=0;i<numMeshLabels;++i)
736  {
737  mLabel * labelPtr = meshContainerPtr->getLabel(i);
738  if (labelPtr->uType == TYPE_EDGE) continue;
739 
740  firstL = labelPtr->mNodeVector.begin();
741  lastL = labelPtr->mNodeVector.end ();
742 
743  for (iterL=firstL; iterL!=lastL; ++iterL)
744  {
745  labelIndex[*iterL] = i;
746  }
747  }
748 
749  // next, loop through the edge labels, and their node lists, and update
750  // the various label indices. If there are conflicts, the edge index will
751  // just write over a previously established region index.
752 
753  for (i=0;i<numMeshLabels;++i)
754  {
755  mLabel * labelPtr = meshContainerPtr->getLabel(i);
756  if (labelPtr->uType != TYPE_EDGE) continue;
757 
758  firstL = labelPtr->mNodeVector.begin();
759  lastL = labelPtr->mNodeVector.end ();
760 
761  for (iterL=firstL; iterL!=lastL; ++iterL)
762  {
763  labelIndex[*iterL] = i;
764  }
765  }
766 
767  for (i=0;i<numMeshPoints;++i)
768  {
769  mLabel * labelPtr = meshContainerPtr->getLabel(labelIndex[i]);
770  labelNameVector.push_back(labelPtr->name);
771  }
772 
773  int size = dIVec.size();
774  for (i = 0;i < size; ++i)
775  {
776  labelDIMap[dIVec[i].eName] = i;
777  }
778 
779 #ifdef Xyce_DEBUG_DEVICE
780 
781  if (getDeviceOptions().debugLevel > 0)
782  {
783  Xyce::dout() << section_divider << std::endl;
784  Xyce::dout() << "In the Intance::setupLabelIndex ";
785  Xyce::dout() << " name = "<< getName() << std::endl;
786 
787 #if 0
788  std::vector<std::string>::iterator firstM = labelNameVector.begin();
789  std::vector<std::string>::iterator lastM = labelNameVector.end ();
790  std::vector<std::string>::iterator iterM;
791 
792  for (i=0, iterM=firstM;iterM!=lastM;++i,++iterM)
793  {
794  Xyce::dout() << " i = "<<i<<" name = " << *iterM << std::endl;
795  }
796 #endif
797  std::map<std::string,int>::iterator firstDIM = labelDIMap.begin ();
798  std::map<std::string,int>::iterator lastDIM = labelDIMap.end ();
799  std::map<std::string,int>::iterator iterDIM;
800  for(iterDIM=firstDIM;iterDIM!=lastDIM;++iterDIM)
801  {
802  Xyce::dout() << " DI index = "<< iterDIM->second;
803  Xyce::dout() << " name = " << iterDIM->first << std::endl;
804  }
805  }
806 
807  if (getDeviceOptions().debugLevel > 1)
808  {
809  for (i=0;i<numMeshPoints;++i)
810  {
811  mLabel * labelPtr = meshContainerPtr->getLabel(labelIndex[i]);
812  Xyce::dout() << " labelIndex["<<i<<"] = " << labelIndex[i];
813  Xyce::dout() << " name = " << labelPtr->name << std::endl;
814  }
815  }
816 
817  if (getDeviceOptions().debugLevel > 0)
818  {
819  Xyce::dout() << section_divider << std::endl;
820  }
821 
822 #endif
823 
824  return true;
825 }
826 
827 //-----------------------------------------------------------------------------
828 // Function : Instance::setupBoundaryStencil
829 // Purpose : This function sets up the stencil vector for boundary
830 // nodes. In this case, a "boundary node" is a node from
831 // the mesh which is part of one of the user-specified
832 // boundary conditions. So, this would include an
833 // electrode, like "COLLECTOR", but would not include
834 // "NOFLUX".
835 //
836 // If node i is a boundary node, then the value of
837 // boundarySten[i] = 1. Otherwise boundarySten[i] = 0.
838 //
839 // 7/15/03. Revised to handle mixed boundary conditions,
840 // and the 3 new boundary stencils (one for each variable:
841 // (V,N,P)).
842 //
843 // Note: this only has nonzeros in it if using the "NEW_BC"
844 // version of boundary conditions. At this point 7/17/03,
845 // the boundary stencils are only used for the new boundary
846 // conditions, not the old.
847 //
848 // Special Notes :
849 // Scope : public
850 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
851 // Creation Date : 11/07/02
852 //-----------------------------------------------------------------------------
854 {
855  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
856  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
857  std::vector<DeviceInterfaceNode>::iterator iterDI;
858 
859 #ifdef Xyce_DEBUG_DEVICE
860  if (getDeviceOptions().debugLevel > 0)
861  {
862  Xyce::dout() << "In Instance::setupBoundaryStencil." << std::endl;
863  }
864 #endif
865 
866 #ifdef Xyce_NEW_BC
867  for (iterDI = firstDI; iterDI!=lastDI; ++iterDI)
868  {
869  // loop over the nodes of this device interface node,
870  // If it is an edge label, not a region label, and it is associated
871  // with a boundary condition.
872 
873  if ( !( meshContainerPtr->labelEdgeType (iterDI->eName) ) ) continue;
874 
875  mLabel * labelPtr = meshContainerPtr->getLabel(iterDI->eName);
876 
877  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
878  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
879  std::vector<int>::iterator iterI;
880 
881  for(iterI=firstI;iterI!=lastI;++iterI)
882  {
883  int nodeIndex = *iterI;
884 
885  if (!(iterDI->neumannBCFlagV)) boundaryStenV[nodeIndex] = 1;
886  if (!(iterDI->neumannBCFlagN)) boundaryStenN[nodeIndex] = 1;
887  if (!(iterDI->neumannBCFlagP)) boundaryStenP[nodeIndex] = 1;
888 
889  // if this BC is dirichlet for all the variables, then set the
890  // stencil.
891  if (!(iterDI->neumannBCFlagV) &&
892  !(iterDI->neumannBCFlagN) && !(iterDI->neumannBCFlagP))
893  {
894  boundarySten[nodeIndex] = 1;
895  }
896  }
897  }
898 #endif // NEW_BC
899 
900  return true;
901 }
902 
903 
904 //-----------------------------------------------------------------------------
905 // Function : Instance::checkForElectrodeOverlap
906 // Purpose : The purpose of this function is to make sure that there
907 // are not any nodes associated with multiple electrodes.
908 //
909 // If there were, the boundary conditions wouldn't make sense.
910 //
911 // Special Notes :
912 //
913 // Scope : public
914 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
915 // Creation Date : 07/23/2004
916 //-----------------------------------------------------------------------------
918 {
919 #ifdef Xyce_DEBUG_DEVICE
920  if (getDeviceOptions().debugLevel > 0)
921  {
922  Xyce::dout() << "In Instance::checkForElectrodeOverlap." << std::endl;
923  }
924 #endif
925 
926  for (int iDI=0;iDI<dIVec.size();++iDI)
927  {
928  // loop over the nodes of this device interface node,
929  // If it is an edge label, not a region label, and it is associated
930  // with a boundary condition.
931 
932  if ( !( meshContainerPtr->labelEdgeType (dIVec[iDI].eName) ) ) continue;
933 
934  mLabel * labelPtr = meshContainerPtr->getLabel(dIVec[iDI].eName);
935 
936  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
937  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
938  std::vector<int>::iterator iterI;
939 
940  for(iterI=firstI;iterI!=lastI;++iterI)
941  {
942  int nodeIndex = *iterI;
943 
944  if (boundaryTest[nodeIndex] != 0)
945  {
946  std::string msg = "Electrodes " + dIVec[iDI].eName + " and " +
947  dIVec[boundaryTest[nodeIndex]-1].eName + " overlap";
948  N_ERH_ErrorMgr::report( N_ERH_ErrorMgr::DEV_FATAL_0,msg);
949  }
950 
951  boundaryTest[nodeIndex] = iDI+1;
952  }
953  }
954 
955  return true;
956 }
957 
958 //-----------------------------------------------------------------------------
959 // Function : Instance::setupNumVars
960 // Purpose : The purpose of this function is to set up a few
961 // integer variables, such as numIntVars and numExtVars.
962 // These numbers are used by the registerGID , etc.
963 // functions.
964 // Special Notes :
965 // Scope : public
966 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
967 // Creation Date : 07/15/03
968 //-----------------------------------------------------------------------------
970 {
971  bool bsuccess = true;
972 
973  numIntVars = 3*numMeshPoints; // check this also.
974 
975  numExtVars = numElectrodes; // This is the number of external nodes,
976  // so it could be just about anything.
977 
979  // numMeshPoints is part of numStateVars for displacement current.
980 
981  maxColsPerRow = 20; // check this out later... depends on
982  // the max. NN count. (*3)
983 
984  int totalDirchlet = 0;
985 
986 #ifdef Xyce_NEW_BC
987  // For the new boundary conditions, reduce the size of the problem by
988  // the number of mesh points along the boundary
989  // (If all BC are dirichlet, then *3, for each equation).
991 
992  std::vector<DeviceInterfaceNode>::iterator first = dIVec.begin ();
993  std::vector<DeviceInterfaceNode>::iterator last = dIVec.end ();
994  std::vector<DeviceInterfaceNode>::iterator iterV;
995  for (iterV=first;iterV!=last; ++iterV)
996  {
997  mLabel * labelPtr = meshContainerPtr->getLabel(iterV->eName);
998  numInterfaceMeshPoints += labelPtr->mNodeVector.size();
999 #ifdef Xyce_DEBUG_DEVICE
1000  if (getDeviceOptions().debugLevel > 0)
1001  {
1002  Xyce::dout() << iterV->eName;
1003  Xyce::dout() << ": numInterfaceMeshPoints = ";
1004  Xyce::dout() << labelPtr->mNodeVector.size ();
1005  Xyce::dout() << std::endl;
1006  }
1007 #endif
1008  }
1009 
1010  // revising, because of possibility of mixed BC.
1011  for (iterV=first;iterV!=last; ++iterV)
1012  {
1013  mLabel * labelPtr = meshContainerPtr->getLabel(iterV->eName);
1014  int numPoints = labelPtr->mNodeVector.size();
1015 
1016  int mult = 0;
1017 
1018  if (!(iterV->neumannBCFlagV)) mult += 1;
1019  if (!(iterV->neumannBCFlagN)) mult += 1;
1020  if (!(iterV->neumannBCFlagP)) mult += 1;
1021 
1022  totalDirchlet += (mult * numPoints);
1023  }
1024 
1025  numIntVars -= totalDirchlet;
1026 
1027 #endif // Xyce_NEW_BC
1028 
1029 #ifdef Xyce_DEBUG_DEVICE
1030  if (getDeviceOptions().debugLevel > 0)
1031  {
1032  Xyce::dout() << "\n";
1033  Xyce::dout() << " numInterfaceMeshPoints = " << numInterfaceMeshPoints<< std::endl;
1034  Xyce::dout() << " numMeshPoints = " << numMeshPoints<< std::endl;
1035  Xyce::dout() << " numElectrodes = " << numElectrodes<< std::endl;
1036  Xyce::dout() << " numIntVars = " << numIntVars<< std::endl;
1037  Xyce::dout() << " 3*numMeshPoints = " << 3*numMeshPoints<< std::endl;
1038  Xyce::dout() << " 3*numInterfaceMeshPoints = "<<3*numInterfaceMeshPoints<< std::endl;
1039  Xyce::dout() << " totalDirchlet = " << totalDirchlet<< std::endl;
1040  Xyce::dout() << std::endl;
1041  }
1042 #endif
1043 
1044  return bsuccess;
1045 }
1046 
1047 //-----------------------------------------------------------------------------
1048 // Function : Instance::allocatePDTerms.
1049 //
1050 // Purpose : This function sets up and allocates a number of arrays
1051 // that are needed by the function pdTerminalCurrents.
1052 //
1053 // Special Notes : Ordinarily, this function would have been called
1054 // earlier, as I prefer to get allocations out of the way
1055 // as early as possible. However, it was easier to set
1056 // this up using the colarrays, which are set up by
1057 // function registerGIDs.
1058 //
1059 // Scope : public
1060 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1061 // Creation Date : 12/10/02
1062 //-----------------------------------------------------------------------------
1064 {
1065  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
1066  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
1067  std::vector<DeviceInterfaceNode>::iterator iterDI;
1068  // now do dIdX.
1069  for(iterDI=firstDI;iterDI!=lastDI;++iterDI)
1070  {
1071  mLabel * labelPtr = meshContainerPtr->getLabel(iterDI->eName);
1072 
1073  // obtain the node indices for the current label, loop over them.
1074  // for each edge node, add an extra column entry to the colarray.
1075 
1076  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
1077  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
1078  std::vector<int>::iterator iterI;
1079 
1080  std::vector<EDGEINFO>::iterator firstEI;
1081  std::vector<EDGEINFO>::iterator lastEI;
1082  std::vector<EDGEINFO>::iterator iterEI;
1083 
1084  int cnt2 = 0;
1085  int nodeIndex;
1086  int col1;
1087  bool bmatch;
1088  int iVcol = 0;
1089  for(nodeIndex=0,iterI=firstI;iterI!=lastI;++iterI,++nodeIndex)
1090  {
1091  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1092  firstEI = nodePtr->edgeInfoVector.begin();
1093  lastEI = nodePtr->edgeInfoVector.end ();
1094 
1095  // voltage variables:
1096  // do the center point first.
1097  col1 = iterDI->Vcol[iVcol];
1098  if (col1 != -1)
1099  {
1100  // check if node == any previous nodes in the cols array
1101  bmatch = false;
1102  for (cnt2=0;cnt2<iterDI->dIdXcols.size();++cnt2)
1103  {
1104  if (iterDI->dIdXcols[cnt2] == col1)
1105  { bmatch = true; break; }
1106  }
1107  if (!bmatch)
1108  {
1109  iterDI->dIdXcols.push_back(col1);
1110  iterDI->dIdX.push_back(0.0);
1111  iterDI->dQdX.push_back(0.0);
1112  }
1113  }
1114  ++iVcol;
1115  // loop over the edges connected to the current node,
1116  // and do the neighbor point dependencies.
1117  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI,++iVcol)
1118  {
1119  col1 = iterDI->Vcol[iVcol];
1120  if (col1 !=-1)
1121  {
1122  // check if node == any previous nodes in the cols array
1123  bmatch = false;
1124  for (cnt2=0;cnt2<iterDI->dIdXcols.size();++cnt2)
1125  {
1126  if (iterDI->dIdXcols[cnt2] == col1)
1127  { bmatch = true; break; }
1128  }
1129  if (!bmatch)
1130  {
1131  iterDI->dIdXcols.push_back(col1);
1132  iterDI->dIdX.push_back(0.0);
1133  iterDI->dQdX.push_back(0.0);
1134  }
1135  }
1136  } // end of nn edge loop
1137  } // end of node loop
1138 
1139  int iNcol = 0;
1140  for(nodeIndex=0,iterI=firstI;iterI!=lastI;++iterI,++nodeIndex)
1141  {
1142  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1143  firstEI = nodePtr->edgeInfoVector.begin();
1144  lastEI = nodePtr->edgeInfoVector.end ();
1145 
1146  // electron variables:
1147  // do the center point first.
1148  col1 = iterDI->Ncol[iNcol];
1149  if (col1 != -1)
1150  {
1151  // check if node == any previous nodes in the cols array
1152  bmatch = false;
1153  for (cnt2=0;cnt2<iterDI->dIdXcols.size();++cnt2)
1154  {
1155  if (iterDI->dIdXcols[cnt2] == col1)
1156  { bmatch = true; break; }
1157  }
1158  if (!bmatch)
1159  {
1160  iterDI->dIdXcols.push_back(col1);
1161  iterDI->dIdX.push_back(0.0);
1162  iterDI->dQdX.push_back(0.0);
1163  }
1164  }
1165  ++iNcol;
1166  // loop over the edges connected to the current node,
1167  // and do the neighbor point dependencies.
1168  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI,++iNcol)
1169  {
1170  col1 = iterDI->Ncol[iNcol];
1171  if (col1 !=-1)
1172  {
1173  // check if node == any previous nodes in the cols array
1174  bmatch = false;
1175  for (cnt2=0;cnt2<iterDI->dIdXcols.size();++cnt2)
1176  {
1177  if (iterDI->dIdXcols[cnt2] == col1)
1178  { bmatch = true; break; }
1179  }
1180  if (!bmatch)
1181  {
1182  iterDI->dIdXcols.push_back(col1);
1183  iterDI->dIdX.push_back(0.0);
1184  iterDI->dQdX.push_back(0.0);
1185  }
1186  }
1187  } // end of nn edge loop
1188  } // end of node loop
1189 
1190  int iPcol = 0;
1191  for(nodeIndex=0,iterI=firstI;iterI!=lastI;++iterI,++nodeIndex)
1192  {
1193  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1194  firstEI = nodePtr->edgeInfoVector.begin();
1195  lastEI = nodePtr->edgeInfoVector.end ();
1196 
1197  // hole variables:
1198  // do the center point first.
1199  col1 = iterDI->Pcol[iPcol];
1200  if (col1 != -1)
1201  {
1202  // check if node == any previous nodes in the cols array
1203  bmatch = false;
1204  for (cnt2=0;cnt2<iterDI->dIdXcols.size();++cnt2)
1205  {
1206  if (iterDI->dIdXcols[cnt2] == col1)
1207  { bmatch = true; break; }
1208  }
1209  if (!bmatch)
1210  {
1211  iterDI->dIdXcols.push_back(col1);
1212  iterDI->dIdX.push_back(0.0);
1213  iterDI->dQdX.push_back(0.0);
1214  }
1215  }
1216  ++iPcol;
1217  // loop over the edges connected to the current node,
1218  // and do the neighbor point dependencies.
1219  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI,++iPcol)
1220  {
1221  col1 = iterDI->Pcol[iPcol];
1222  if (col1 !=-1)
1223  {
1224  // check if node == any previous nodes in the cols array
1225  bmatch = false;
1226  for (cnt2=0;cnt2<iterDI->dIdXcols.size();++cnt2)
1227  {
1228  if (iterDI->dIdXcols[cnt2] == col1)
1229  { bmatch = true; break; }
1230  }
1231  if (!bmatch)
1232  {
1233  iterDI->dIdXcols.push_back(col1);
1234  iterDI->dIdX.push_back(0.0);
1235  iterDI->dQdX.push_back(0.0);
1236  }
1237  }
1238  } // end of nn edge loop
1239  } // end of node loop
1240 
1241  // Now add to the neighbor node array. Assuming that any of the 3
1242  // columns iPcol, iNcol, iVcol will do for a validity check vs. -1,
1243  // so just checking the pcol.
1244  iPcol = 0;
1245  for(nodeIndex=0,iterI=firstI;iterI!=lastI;++iterI,++nodeIndex)
1246  {
1247  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1248  firstEI = nodePtr->edgeInfoVector.begin();
1249  lastEI = nodePtr->edgeInfoVector.end ();
1250 
1251  // center point first.
1252  col1 = iterDI->Pcol[iPcol];
1253  int meshNode = *iterI;
1254 
1255  if (col1 !=-1)
1256  {
1257  // check if node == any previous nodes in the cols array
1258  bmatch = false;
1259  for (cnt2=0;cnt2<iterDI->neighborNodes.size();++cnt2)
1260  {
1261  if (iterDI->neighborNodes[cnt2] == meshNode)
1262  { bmatch = true; break; }
1263  }
1264  if (!bmatch)
1265  {
1266  iterDI->neighborNodes.push_back(meshNode);
1267  }
1268  }
1269 
1270  ++iPcol;
1271 
1272  // loop over the edges connected to the current node,
1273  // and do the neighbor point dependencies.
1274  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI,++iPcol)
1275  {
1276  col1 = iterDI->Pcol[iPcol];
1277  int meshNode = iterEI->inode;
1278 
1279  if (col1 !=-1)
1280  {
1281  // check if node == any previous nodes in the cols array
1282  bmatch = false;
1283  for (cnt2=0;cnt2<iterDI->neighborNodes.size();++cnt2)
1284  {
1285  if (iterDI->neighborNodes[cnt2] == meshNode)
1286  { bmatch = true; break; }
1287  }
1288  if (!bmatch)
1289  {
1290  iterDI->neighborNodes.push_back(meshNode);
1291  }
1292  }
1293  } // end of nn edge loop
1294  } // end of node loop
1295 
1296  int size1 = iterDI->neighborNodes.size();
1297  int size3 = iterDI->dIdX.size();
1298 #ifdef Xyce_DEBUG_DEVICE
1299  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1300  {
1301  Xyce::dout() << std::endl;
1302  Xyce::dout() << "number of neighbor nodes for " << iterDI->eName;
1303  Xyce::dout() << " is " << size1 << std::endl;
1304  int i;
1305  for (i=0;i<size1;++i)
1306  {
1307  Xyce::dout() << "neighborNodes["<<i<<"] = " << iterDI->neighborNodes[i] << std::endl;
1308  }
1309  Xyce::dout() << std::endl;
1310  Xyce::dout() << "dIdX size for " << iterDI->eName << " is " << size3 << std::endl;
1311  for (i=0;i<size3;++i)
1312  {
1313  Xyce::dout() << "dIdX["<<i<<"] = " << iterDI->dIdXcols[i] << std::endl;
1314  }
1315  }
1316 #endif
1317 
1318 #ifdef Xyce_NEW_BC
1319  // to set up dFdVckt, need to take it through the same set of loops it
1320  // will be subject to in function pdTerminalCurrents.
1321  int numNeighbor = iterDI->neighborNodes.size();
1322  int iNeighbor;
1323  int dFdVindex = 0;
1324  for (iNeighbor=0;iNeighbor<numNeighbor;++iNeighbor)
1325  {
1326  int inode = iterDI->neighborNodes[iNeighbor];
1327  mNode * nodePtr = meshContainerPtr->getNode(inode);
1328 
1329  for (int iNN=0;iNN<nodePtr->cnode;++iNN)
1330  {
1331  int inodeB = nodePtr->edgeInfoVector[iNN].inode;
1332 
1333  // if nodeB is not a boundary node, never mind.
1334  if (boundaryStenV[inodeB]!=1) continue;
1335 
1336  // if it is a boundary node, but not part of the
1337  // current boundary, also never mind.
1338  if (labelNameVector[inodeB]!= iterDI->eName) continue;
1339 
1340  iterDI->dFdVckt.push_back(0.0); ++dFdVindex;
1341  iterDI->dFdVckt.push_back(0.0); ++dFdVindex;
1342  iterDI->dFdVckt.push_back(0.0); ++dFdVindex;
1343  }
1344  }
1345 
1346 #ifdef Xyce_DEBUG_DEVICE
1347  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1348  {
1349  Xyce::dout() << iterDI->eName << ": size of dFdVckt = " << dFdVindex << std::endl;
1350  }
1351 #endif
1352 
1353 #else
1354  UserWarning0(*this) << "NEW_BC must be turned on to use TWO_LEVEL_NEWTON";
1355 #endif // Xyce_NEW_BC
1356 
1357  } // end of DI loop
1358 
1359  return true;
1360 }
1361 
1362 //-----------------------------------------------------------------------------
1363 // Function : Instance::setupBCEdgeAreas
1364 //
1365 // Purpose : This function sets up the areas associated with each
1366 // mesh node along a boundary condition edge.
1367 //
1368 // Special Notes : This is potentially tricky. The mesh may be 2D
1369 // cartesian or 2D cylindrical.
1370 //
1371 // Fortunately, the function "lengthAdjust", from the mesh
1372 // class, is designed for getting areas - either
1373 // cylindrical or cartesian.
1374 //
1375 // This whole should be moved to the mesh class later.
1376 //
1377 // This function is called before scaling is turned on, but
1378 // should work either way.
1379 //
1380 // Scope : public
1381 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1382 // Creation Date : 05/09/02
1383 //-----------------------------------------------------------------------------
1385 {
1386 
1387 #ifdef Xyce_DEBUG_DEVICE
1388  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1389  {
1390  Xyce::dout() << section_divider << "\n";
1391  Xyce::dout() << "setupBCEdgeAreas. name = " << getName() << std::endl;
1392  Xyce::dout().setf(std::ios::scientific);
1393  }
1394 #endif
1395 
1396  // now set up the local areas for needed to interface device boundary
1397  // conditions to the circuit
1398 
1399  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
1400  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
1401  std::vector<DeviceInterfaceNode>::iterator iterDI;
1402 
1403  for (iterDI = firstDI; iterDI!=lastDI; ++iterDI)
1404  {
1405  // loop over the nodes of this device interface node:
1406 
1407  if ( !( meshContainerPtr->labelEdgeType (iterDI->eName) ) ) continue;
1408 
1409  mLabel * labelPtr = meshContainerPtr->getLabel(iterDI->eName);
1410 
1411  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
1412  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
1413  std::vector<int>::iterator iterI;
1414 
1415  iterDI->area = 0.0; // total area for the edge.
1416 
1417  for(iterI=firstI;iterI!=lastI;++iterI)
1418  {
1419  // loop over neighbor nodes/edges to get area sum for this node.
1420  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1421 
1422  std::vector<EDGEINFO>::iterator firstEI = nodePtr->edgeInfoVector.begin();
1423  std::vector<EDGEINFO>::iterator lastEI = nodePtr->edgeInfoVector.end ();
1424  std::vector<EDGEINFO>::iterator iterEI;
1425 
1426  double areaLocal = 0.0; // total "area" for the this node
1427  double areaTmp = 0.0; // partial area for the this node(from one edge)
1428 
1429 #ifdef Xyce_DEBUG_DEVICE
1430  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1431  {
1432  Xyce::dout() << " --------------- " << std::endl;
1433  Xyce::dout() << "name = " << iterDI->eName;
1434  Xyce::dout() << " node = " << *iterI << std::endl;
1435  }
1436 #endif
1437 
1438  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1439  {
1440  int neighbor = iterEI->inode;
1441 
1442  // if this edge is actually on the boundary, then sum the
1443  // edge length into the "area" associated with this
1444  // boundary node. Check this by checking the label index
1445  // of the neighbor.
1446 
1447  int ilabel = labelIndex[neighbor];
1448  mLabel * labelPtr = meshContainerPtr->getLabel(ilabel);
1449 
1450  areaTmp = 0.0;
1451  if (labelPtr->name == iterDI->eName)
1452  // if this is along the bounadry
1453  {
1455  {
1456  // get the midpoint location, x2:
1457  double x1 = xVec[*iterI];
1458  double y1 = yVec[*iterI];
1459 
1460  double x2 = xVec[neighbor];
1461  double y2 = yVec[neighbor];
1462 
1463  double dx = x2-x1; dx *= 0.5;
1464  double dy = y2-y1; dy *= 0.5;
1465 
1466  x2 = x1 + dx;
1467  y2 = y1 + dy;
1468 
1469  areaTmp = meshContainerPtr->lengthAdjust(x1,y1,x2,y2);
1470  areaLocal += areaTmp;
1471  }
1472  else // cartesian
1473  {
1474  areaTmp = 0.5 * iterEI->elen;
1475  areaLocal += 0.5 * iterEI->elen;
1476  }
1477  }
1478 #ifdef Xyce_DEBUG_DEVICE
1479  if (getDeviceOptions().debugLevel > 1 && getSolverState().debugTimeFlag)
1480  {
1481  Xyce::dout() << " neighbor node = " << neighbor << std::endl;
1482  Xyce::dout() << " areaTmp = " << areaTmp << std::endl;
1483  Xyce::dout() << " areaLocal = " << areaLocal << std::endl;
1484  Xyce::dout() << " elen = " << iterEI->elen << std::endl;
1485  Xyce::dout() << " label name = " << labelPtr->name << std::endl;
1486  Xyce::dout() << " DI eName = " << iterDI->eName << std::endl;
1487  Xyce::dout() << "---" << std::endl;
1488  }
1489 #endif
1490  }
1491 
1492 #ifdef Xyce_DEBUG_DEVICE
1493  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1494  {
1495  Xyce::dout() << " --------------- " << std::endl;
1496  }
1497 #endif
1498  iterDI->area += areaLocal;
1499  iterDI->areaVector.push_back(areaLocal);
1500 
1501  } // iterI loop.
1502 
1503 
1504 #ifdef Xyce_DEBUG_DEVICE
1505  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1506  {
1507  Xyce::dout().setf(std::ios::scientific);
1508  Xyce::dout() << " Total area for edge: " << iterDI->area << std::endl;
1509  }
1510 #endif
1511  } // iterDI loop.
1512 
1513 #ifdef Xyce_DEBUG_DEVICE
1514  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1515  {
1516  Xyce::dout() << section_divider << "\n";
1517  }
1518 #endif
1519  return true;
1520 }
1521 
1522 //-----------------------------------------------------------------------------
1523 // Function : Instance::setupMinDXVector
1524 // Purpose : This finds the minimum edge length. I'm not sure if
1525 // there's any reason to do this anymore.
1526 // Special Notes :
1527 // Scope : public
1528 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1529 // Creation Date : 09/26/02
1530 //-----------------------------------------------------------------------------
1532 {
1533 
1534  int i;
1535  for (i=0;i<numMeshPoints;++i)
1536  {
1537  // loop over neighbor nodes/edges to get area sum for this node.
1538  mNode * nodePtr = meshContainerPtr->getNode(i);
1539 
1540  std::vector<EDGEINFO>::iterator firstEI = nodePtr->edgeInfoVector.begin();
1541  std::vector<EDGEINFO>::iterator lastEI = nodePtr->edgeInfoVector.end ();
1542  std::vector<EDGEINFO>::iterator iterEI;
1543 
1544  double tmpDX = +1.0e99;
1545  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1546  {
1547  if (tmpDX > iterEI->elen) tmpDX = iterEI->elen;
1548  }
1549 #ifdef Xyce_DEBUG_DEVICE
1550  if (getDeviceOptions().debugLevel > 2)
1551  {
1552  Xyce::dout() << "i = " << i << " minDX = " << tmpDX; Xyce::dout() << std::endl;
1553  }
1554 #endif
1555  minDXVec[i] = tmpDX;
1556  }
1557 
1558  return true;
1559 }
1560 
1561 //-----------------------------------------------------------------------------
1562 // Function : Instance::setupJacStamp
1563 //
1564 // Purpose : This function sets up the jacobian stamp data structure,
1565 // which is a symbolic, local-ID (LID) representation of the
1566 // jacobian matrix structure of the device.
1567 //
1568 // The jacStamp is the structure that gets passed up to
1569 // topology.
1570 //
1571 // It is similar to some of what has to happen in the
1572 // registerGID's function, but it is not dependent upon
1573 // knowing the global ID's for the solution variables.
1574 //
1575 // Special Notes :
1576 // Scope : public
1577 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1578 // Creation Date : 02/23/03
1579 //-----------------------------------------------------------------------------
1581 {
1582  bool bsuccess = true;
1583  int i;
1584 
1585 #ifdef Xyce_DEBUG_DEVICE
1586  if (getDeviceOptions().debugLevel > 0)
1587  {
1588  Xyce::dout() << "In Instance::setupJacStamp" << std::endl;
1589  Xyce::dout() << "numIntVars = " << numIntVars << std::endl;
1590  Xyce::dout() << "numMeshPoints = " << numMeshPoints << std::endl;
1591  }
1592 #endif
1593 
1594  // The number of rows in the jacStamp has to include all the *possible*
1595  // electrodes (external variables). This is a little confusing.
1596  // The PDE devices are set up so that there are:
1597  // 2 required nodes
1598  // 2 not-required, but not-optional nodes (these are fill nodes)
1599  // 100 optional nodes.
1600  // For some reason (that I don't understand) this means that the
1601  // jacStamp always has to have at least 4 external nodes. Even
1602  // if the device only has 2 nodes attached to the circuit, the
1603  // jacStamp is required to have 4.
1604  int numPossibleElectrodes = (numExtVars>4)?numExtVars:4;
1605  jacStamp.resize(numIntVars + numPossibleElectrodes);
1606 
1607  MESHtoLID_V.resize(numMeshPoints,-1);
1608  MESHtoLID_N.resize(numMeshPoints,-1);
1609  MESHtoLID_P.resize(numMeshPoints,-1);
1610 
1611 #ifdef Xyce_DEBUG_DEVICE
1612  if (getDeviceOptions().debugLevel > 0)
1613  {
1614  Xyce::dout() << "size of jacStamp = " << jacStamp.size() << std::endl;
1615  }
1616 #endif
1617 
1618  // Set up the MESHtoLID converter for internal vars.
1619  int LIDcounter = numPossibleElectrodes;
1620 
1621  for (i=0;i<numMeshPoints;++i)
1622  {
1623 #ifdef Xyce_NEW_BC
1624  if (boundarySten[i]) continue;
1625 #endif // Xyce_NEW_BC
1626 
1627  if (!(boundaryStenV[i]))
1628  {
1629  MESHtoLID_V[i] = LIDcounter; ++LIDcounter;
1630  }
1631 
1632  if (!(boundaryStenN[i]))
1633  {
1634  MESHtoLID_N[i] = LIDcounter; ++LIDcounter;
1635  }
1636 
1637  if (!(boundaryStenP[i]))
1638  {
1639  MESHtoLID_P[i] = LIDcounter; ++LIDcounter;
1640  }
1641  }
1642 
1643  /////////////////////////////////////////////////////////////////////////
1644  // Do the external variables first:
1645  // Loop over the boundary condition "device interface" labels.
1646  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
1647  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
1648  std::vector<DeviceInterfaceNode>::iterator iterDI;
1649  int DIsize = dIVec.size ();
1650  firstDI = dIVec.begin();
1651  lastDI = dIVec.end ();
1652 
1653  // note that the index, in addition to being the index into the
1654  // array of "DeviceInterfaceNodes" will also be the LID.
1655  int index;
1656  for(index=0,iterDI=firstDI;iterDI!=lastDI;++iterDI,++index)
1657  {
1658  // check that this label exists, and is an edge label
1659  // (everything in the dIVec container should pass these tests
1660  // by this point - these two if-statements are just a failsafe.)
1661  if ( !( meshContainerPtr->labelNameExist(dIVec[index].eName) ) ) continue;
1662  if ( !( meshContainerPtr->labelEdgeType (dIVec[index].eName) ) ) continue;
1663 
1664 
1665  // first do the external node's (row=cktnode,col=cktnode) pair:
1666  jacStamp[index].push_back(index);
1667 
1668  dIVec[index].numCrossTerms = 0;
1669 
1670  // next do the (row,col) pairs for other ckt nodes. This is needed for
1671  // 2-level newton only.
1672  for (int ind2=0;ind2<DIsize;++ind2)
1673  {
1674  if (ind2==index) continue;
1675 
1676  jacStamp[index].push_back(ind2);
1677  ++(dIVec[index].numCrossTerms);
1678  }
1679 
1680  mLabel * labelPtr = meshContainerPtr->getLabel(dIVec[index].eName);
1681 
1682  // obtain the node indices for the current label, loop over them.
1683  // for each edge node, add an extra column entry to the colarray,
1684  // which corresponds to the global ID of the connected ckt node.
1685 
1686  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
1687  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
1688  std::vector<int>::iterator iterI;
1689 
1690  std::vector<EDGEINFO>::iterator firstEI;
1691  std::vector<EDGEINFO>::iterator lastEI;
1692  std::vector<EDGEINFO>::iterator iterEI;
1693 
1694  int imesh;
1695 
1696  for(iterI=firstI;iterI!=lastI;++iterI)
1697  {
1698  // now do the V edge and edge neighbor nodes.
1699  imesh = *iterI;
1700  if (!boundaryStenV[imesh])
1701  jacStamp[index].push_back(MESHtoLID_V[imesh]);
1702 
1703  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1704  firstEI = nodePtr->edgeInfoVector.begin();
1705  lastEI = nodePtr->edgeInfoVector.end ();
1706 
1707  // loop over the edges connected to the current node:
1708  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI)
1709  {
1710  imesh = iterEI->inode;
1711  if (!boundaryStenV[imesh])
1712  jacStamp[index].push_back(MESHtoLID_V[imesh]);
1713  }
1714  }
1715 
1716  for(iterI=firstI;iterI!=lastI;++iterI)
1717  {
1718  // now do the N nodes.
1719  imesh = *iterI;
1720 
1721  if (!boundaryStenN[imesh])
1722  jacStamp[index].push_back(MESHtoLID_N[imesh]);
1723 
1724  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1725  firstEI = nodePtr->edgeInfoVector.begin();
1726  lastEI = nodePtr->edgeInfoVector.end ();
1727  // loop over the edges connected to the current node:
1728  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI)
1729  {
1730  imesh = iterEI->inode;
1731  if (!boundaryStenN[imesh])
1732  jacStamp[index].push_back(MESHtoLID_N[imesh]);
1733  }
1734  }
1735 
1736  for(iterI=firstI;iterI!=lastI;++iterI)
1737  {
1738  // now do the P nodes.
1739  imesh = *iterI;
1740  if (!boundaryStenP[imesh])
1741  jacStamp[index].push_back(MESHtoLID_P[imesh]);
1742 
1743  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
1744  firstEI = nodePtr->edgeInfoVector.begin();
1745  lastEI = nodePtr->edgeInfoVector.end ();
1746  // loop over the edges connected to the current node:
1747  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI)
1748  {
1749  imesh = iterEI->inode;
1750  if (!boundaryStenP[imesh])
1751  jacStamp[index].push_back(MESHtoLID_P[imesh]);
1752  }
1753  }// iterI loop
1754  } // index (dIVec) loop.
1755 
1756  /////////////////////////////////////////////////////////////////////////
1757  // Now do the internal variables. (V,N,P on the mesh)
1758  for(i=0;i<numMeshPoints;++i)
1759  {
1760 #ifdef Xyce_NEW_BC
1761  if (boundarySten[i]) continue;
1762 #endif // Xyce_NEW_BC
1763 
1764 #ifdef Xyce_DEBUG_DEVICE
1765  if (getDeviceOptions().debugLevel > 0)
1766  {
1767  Xyce::dout() << " mesh point i = " << i << std::endl;
1768  }
1769 #endif
1770 
1771  mNode * nodePtr = meshContainerPtr->getNode(i);
1772  std::vector<EDGEINFO>::iterator firstEI = nodePtr->edgeInfoVector.begin ();
1773  std::vector<EDGEINFO>::iterator lastEI = nodePtr->edgeInfoVector.end ();
1774  std::vector<EDGEINFO>::iterator iterEI;
1775 
1776  // get the temporary LID row indices:
1777  int Vrow = MESHtoLID_V[i];
1778  int Nrow = MESHtoLID_N[i];
1779  int Prow = MESHtoLID_P[i];
1780 
1781 #ifdef Xyce_DEBUG_DEVICE
1782  if (getDeviceOptions().debugLevel > 0)
1783  {
1784  Xyce::dout() << " Vrow = " << Vrow << std::endl;
1785  Xyce::dout() << " Nrow = " << Nrow << std::endl;
1786  Xyce::dout() << " Prow = " << Prow << std::endl;
1787  }
1788 #endif
1789 
1790  // voltage row:
1791  if (Vrow != -1)
1792  {
1793  // First do the (row, row) pair.
1794  jacStamp[Vrow].push_back(Vrow);
1795 
1796  // loop over the neighbor nodes of node i.
1797  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1798  {
1799 #ifdef Xyce_NEW_BC
1800  // if the neighbor node is on a boundary, need to use the
1801  // GID of the connected ckt node, rather than the (nonexistant)
1802  // GID of the boundary mesh node.
1803  if (boundaryStenV[iterEI->inode])
1804  {
1805  // get the gid:
1806  int DIindex = labelDIMap[labelNameVector[iterEI->inode]];
1807  jacStamp[Vrow].push_back (DIindex);
1808  }
1809  else
1810  {
1811  int imesh = iterEI->inode;
1812  int lid = MESHtoLID_V[imesh];
1813  jacStamp[Vrow].push_back(lid);
1814  }
1815 #else // Xyce_NEW_BC
1816  int imesh = iterEI->inode;
1817  int lid = MESHtoLID_V[imesh];
1818  jacStamp[Vrow].push_back(lid);
1819 #endif // Xyce_NEW_BC
1820  }
1821 
1822  jacStamp[Vrow].push_back(Nrow);
1823  jacStamp[Vrow].push_back(Prow);
1824  }
1825 
1826  // electron row:
1827  if (Nrow != -1)
1828  {
1829  jacStamp[Nrow].push_back(Nrow);
1830 
1831  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1832  {
1833  int imesh = iterEI->inode;
1834  if (!boundaryStenN[imesh])
1835  {
1836  int lid = MESHtoLID_N[imesh];
1837  jacStamp[Nrow].push_back(lid);
1838  }
1839  }
1840 
1841  jacStamp[Nrow].push_back(Vrow);
1842 
1843  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1844  {
1845 #ifdef Xyce_NEW_BC
1846  // if the neighbor node is on a boundary, need to use the
1847  // GID of the connected ckt node, rather than the (nonexistant)
1848  // GID of the boundary mesh node.
1849  if (boundaryStenV[iterEI->inode])
1850  {
1851  // get the gid:
1852  int DIindex = labelDIMap[labelNameVector[iterEI->inode]];
1853  jacStamp[Nrow].push_back (DIindex);
1854  }
1855  else
1856  {
1857  int imesh = iterEI->inode;
1858  int lid = MESHtoLID_V[imesh];
1859  jacStamp[Nrow].push_back(lid);
1860  }
1861 #else // Xyce_NEW_BC
1862  int imesh = iterEI->inode;
1863  int lid = MESHtoLID_V[imesh];
1864  jacStamp[Nrow].push_back(lid);
1865 #endif // Xyce_NEW_BC
1866  }
1867  jacStamp[Nrow].push_back(Prow);
1868  }
1869 
1870  // hole row:
1871  if (Prow != -1)
1872  {
1873  jacStamp[Prow].push_back(Prow);
1874 
1875  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1876  {
1877  int imesh = iterEI->inode;
1878  if(!boundaryStenP[imesh])
1879  {
1880  int lid = MESHtoLID_P[imesh];
1881  jacStamp[Prow].push_back(lid);
1882  }
1883  }
1884  jacStamp[Prow].push_back(Vrow);
1885 
1886  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
1887  {
1888 #ifdef Xyce_NEW_BC
1889  // if the neighbor node is on a boundary, need to use the
1890  // GID of the connected ckt node, rather than the (nonexistant)
1891  // GID of the boundary mesh node.
1892  if (boundaryStenV[iterEI->inode])
1893  {
1894  // get the gid:
1895  int DIindex = labelDIMap[labelNameVector[iterEI->inode]];
1896  jacStamp[Prow].push_back (DIindex);
1897  }
1898  else
1899  {
1900  int imesh = iterEI->inode;
1901  int lid = MESHtoLID_V[imesh];
1902  jacStamp[Prow].push_back(lid);
1903  }
1904 #else // Xyce_NEW_BC
1905  int imesh = iterEI->inode;
1906  int lid = MESHtoLID_V[imesh];
1907  jacStamp[Prow].push_back(lid);
1908 #endif // Xyce_NEW_BC
1909  }
1910  jacStamp[Prow].push_back(Nrow);
1911  }
1912  } // mesh point loop.
1913 
1914 #ifndef Xyce_NEW_BC
1915  // go back to the nodes which are boundary condition nodes - ones
1916  // that are connected to the external nodes, and add a few
1917  // (row, col) pairs . These nodes will need some extra ones, at
1918  // least to handle boundary conditions on the voltage.
1919 
1920  // loop over the boundary condition "device interface" labels.
1921  firstDI = dIVec.begin();
1922  lastDI = dIVec.end ();
1923 
1924  for(index=0,iterDI=firstDI;iterDI!=lastDI;++iterDI,++index)
1925  {
1926  // check that this label exists, and is an edge label
1927  // (everything in the dIVec container should pass these tests
1928  // by this point)
1929  if ( !( meshContainerPtr->labelNameExist(dIVec[index].eName) ) ) continue;
1930  if ( !( meshContainerPtr->labelEdgeType (dIVec[index].eName) ) ) continue;
1931 
1932  mLabel * labelPtr = meshContainerPtr->getLabel(dIVec[index].eName);
1933 
1934  // obtain the node indices for the current label, loop over them.
1935  // for each edge node, add an extra column entry to the colarray,
1936  // which corresponds to the global ID of the connected ckt node.
1937 
1938  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
1939  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
1940  std::vector<int>::iterator iterI;
1941 
1942  // For the "new" boundary conditions, this step isn't neccessary,
1943  // as the boundary nodes no longer have any dependent variables.
1944  // However, it is neccessary for the col array associated with
1945  // the "boundary condition" equation.
1946  for(iterI=firstI;iterI!=lastI;++iterI)
1947  {
1948  int imesh = *iterI;
1949  int Vrow = MESHtoLID_V[imesh];
1950  jacStamp[Vrow].push_back(index);
1951  }
1952  } // end of index (dIVec) loop
1953 #endif // Xyce_NEW_BC
1954 
1955 #ifdef Xyce_DEBUG_DEVICE
1956  if (getDeviceOptions().debugLevel > 1)
1957  {
1958  int irow, icol;
1959  for(irow=0;irow<jacStamp.size();++irow)
1960  {
1961  Xyce::dout() << "irow = " << irow;
1962  if (irow < dIVec.size())
1963  Xyce::dout() << " " << dIVec[irow].eName << " KCL";
1964  Xyce::dout() << std::endl;
1965  for (icol=0;icol<jacStamp[irow].size();++icol)
1966  {
1967  int jsTmp = jacStamp[irow][icol];
1968  Xyce::dout() << " jacStamp["<<irow<<"]["<<icol<<"] = "<<jsTmp;
1969  Xyce::dout() << std::endl;
1970  }
1971  }
1972  }
1973 #endif
1974 
1975  return bsuccess;
1976 }
1977 
1978 //-----------------------------------------------------------------------------
1979 // Function : Instance::registerGIDs
1980 // Purpose :
1981 // Special Notes :
1982 // Scope : public
1983 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1984 // Creation Date : 11/14/01
1985 //-----------------------------------------------------------------------------
1987  const std::list<index_pair> & intGIDListRef,
1988  const std::list<index_pair> & extGIDListRef)
1989 {
1990  AssertLIDs(intGIDListRef.size() == numIntVars);
1991 // AssertLIDs(extGIDListRef.size() == numExtVars);
1992 
1993 #ifdef Xyce_DEBUG_DEVICE
1994  if (getDeviceOptions().debugLevel > 0)
1995  {
1996  Xyce::dout() << section_divider << std::endl;
1997  Xyce::dout() << "In the Instance::registerGIDs function. ";
1998  Xyce::dout() << " name = "<< getName() << std::endl;
1999  Xyce::dout() << "numInt = " << numIntVars <<"\n";
2000  Xyce::dout() << "numExt = " << numExtVars <<"\n";
2001  Xyce::dout() << "numMeshPoints = " << numMeshPoints << "\n";
2002  }
2003 #endif
2004 
2005  // copy over the global ID lists:
2006  intGIDList.assign(intGIDListRef.begin(), intGIDListRef.end());
2007  extGIDList.assign(extGIDListRef.begin(), extGIDListRef.end());
2008 
2009  // Set up the rows first, then do the colarrays.
2010 
2011  // First do the external variables:
2012  // These will all be voltage nodes connected to the devices.
2013  std::list<index_pair>::iterator it1 = extGIDList.begin();
2014 
2015  std::list<index_pair>::iterator first = extGIDList.begin();
2016  std::list<index_pair>::iterator last = extGIDList.end ();
2017  std::list<index_pair>::iterator iter;
2018  int index;
2019 
2020 #ifdef Xyce_DEBUG_DEVICE
2021  if (getDeviceOptions().debugLevel > 0)
2022  {
2023  Xyce::dout() << "Setting up the indices for the external circuit nodes:" << std::endl;
2024  Xyce::dout() << "External node list:" << std::endl;
2025  }
2026 #endif
2027 
2028  int numExtNodes = 0;
2029  for(iter=first;iter!=last;++iter)
2030  {
2031  if ( (iter->col) && (iter->row != -1) )
2032  {
2033  ++numExtNodes;
2034  }
2035 
2036 #ifdef Xyce_DEBUG_DEVICE
2037  if (getDeviceOptions().debugLevel > 0)
2038  {
2039  Xyce::dout() << "node = " << iter->row << " col = ";
2040  Xyce::dout() << iter->col << " numExtNodes = " << numExtNodes << std::endl;
2041  }
2042 #endif
2043  }
2044 
2045 #ifdef Xyce_DEBUG_DEVICE
2046  if (getDeviceOptions().debugLevel > 0)
2047  Xyce::dout() << " number of owned external nodes = " << numExtNodes << std::endl;
2048 #endif
2049 
2050  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
2051  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
2052  std::vector<DeviceInterfaceNode>::iterator iterDI;
2053  int numRealDIs = 0;
2054  for(iterDI=firstDI;iterDI!=lastDI;++iterDI)
2055  {
2056  if (iterDI->given) ++numRealDIs;
2057  }
2058 
2059 #ifdef Xyce_DEBUG_DEVICE
2060  if (getDeviceOptions().debugLevel > 0)
2061  {
2062  Xyce::dout() << " number of user specified boundary conditions = ";
2063  Xyce::dout() << numRealDIs << std::endl;
2064  }
2065 #endif
2066 
2067  if (numRealDIs < numExtNodes)
2068  {
2069  DevelFatal(*this).in("Instance::registerGIDs")
2070  << "Number of boundary conditions < number of external nodes";
2071  }
2072 
2073  int isizeDI = dIVec.size();
2074 
2075  for(index=0, iter=first; (iter!=last && index < isizeDI); ++iter, ++index)
2076  {
2077  dIVec[index].gid = iter->row;
2078  if ( !(iter->col) ) dIVec[index].gid = -1;
2079 
2080 #ifdef Xyce_DEBUG_DEVICE
2081  if (getDeviceOptions().debugLevel > 0)
2082  {
2083  Xyce::dout() << " name = "<<dIVec[index].eName<<" gid = ";
2084  Xyce::dout() << dIVec[index].gid;
2085  Xyce::dout() << std::endl;
2086  }
2087 #endif
2088 
2089  // Obtain the node index for the first node of the current label.
2090  // Note: This particular attribute may be obsolete...
2091  mLabel * labelPtr = meshContainerPtr->getLabel(dIVec[index].eName);
2092  std::vector<int>::iterator iterTmp = labelPtr->mNodeVector.begin();
2093 
2094  dIVec[index].firstMeshNodeIndex = *iterTmp;
2095  }
2096 
2097 
2098 #ifdef Xyce_DEBUG_DEVICE
2099  if (getDeviceOptions().debugLevel > 0)
2100  {
2101  Xyce::dout() << "doing internal vars, row arrays:"<< std::endl;
2102  }
2103 #endif
2104 
2105  // Do the internal variables. There should be a lot of these.
2106  std::list<index_pair>::iterator intEnd = intGIDList.end();
2107  std::list<index_pair>::iterator it2 = intGIDList.begin();
2108  int i=0;
2109 
2110  // The interior points will be blocked (V,N,P) together.
2111  while (it2 != intEnd && i < numMeshPoints)
2112  {
2113  int Vrow = -1;
2114  int Nrow = -1;
2115  int Prow = -1;
2116 
2117 #ifdef Xyce_NEW_BC
2118  // don't set up row, col arrays if this is a boundary node.
2119  if (boundarySten[i]) { ++i; continue; }
2120 
2121  if (!(boundaryStenV[i]))
2122  {
2123  Vrow = it2->row;
2124  if ( !(it2->col) ) Vrow = -1;
2125  Vrowarray[i] = Vrow; // should be Vrowarray[i]
2126  ++it2;
2127  }
2128 
2129  if (!(boundaryStenN[i]))
2130  {
2131  Nrow = it2->row;
2132  if ( !(it2->col) ) Nrow = -1;
2133  Nrowarray[i] = Nrow; // should be Nrowarray[i]
2134  ++it2;
2135  }
2136 
2137  if (!(boundaryStenP[i]))
2138  {
2139  Prow = it2->row;
2140  if ( !(it2->col) ) Prow = -1;
2141  Prowarray[i] = Prow; // should be Prowarray[i]
2142  ++it2;
2143  }
2144 
2145 #ifdef Xyce_DEBUG_DEVICE
2146  if (getDeviceOptions().debugLevel >1)
2147  {
2148  Xyce::dout() << "doing row arrays for mesh point " << i << std::endl;
2149  if (!(boundaryStenV[i]))
2150  Xyce::dout() << " Vrow = " << Vrow << std::endl;
2151 
2152  if (!(boundaryStenN[i]))
2153  Xyce::dout() << " Nrow = " << Nrow << std::endl;
2154 
2155  if (!(boundaryStenP[i]))
2156  Xyce::dout() << " Prow = " << Prow << std::endl;
2157  }
2158 #endif
2159 
2160 #else
2161 
2162  Vrow = it2->row;
2163  if ( !(it2->col) ) Vrow = -1;
2164  Vrowarray[i] = Vrow; // should be Vrowarray[i]
2165  ++it2;
2166 
2167  Nrow = it2->row;
2168  if ( !(it2->col) ) Nrow = -1;
2169  Nrowarray[i] = Nrow; // should be Nrowarray[i]
2170  ++it2;
2171 
2172  Prow = it2->row;
2173  if ( !(it2->col) ) Prow = -1;
2174  Prowarray[i] = Prow; // should be Prowarray[i]
2175  ++it2;
2176 
2177 #ifdef Xyce_DEBUG_DEVICE
2178  if (getDeviceOptions().debugLevel >1)
2179  {
2180  Xyce::dout() << "doing row arrays for mesh point " << i << std::endl;
2181  Xyce::dout() << " Vrow = " << Vrow << std::endl;
2182  Xyce::dout() << " Nrow = " << Nrow << std::endl;
2183  Xyce::dout() << " Prow = " << Prow << std::endl;
2184  }
2185 #endif
2186 #endif // Xyce_NEW_BC
2187 
2188  ++i;
2189  }
2190 
2191  setupRowColPairs ();
2192 
2193  // Make sure the cols and vals arrays are big enough,
2194  // based on maxColsPerRow. (the variable maxColsPerRow was
2195  // setup in function setupRowColPairs).
2197 
2198 #ifdef Xyce_DEBUG_DEVICE
2199  if (getDeviceOptions().debugLevel > 0)
2200  {
2201  Xyce::dout() << "maxColsPerRow = " << maxColsPerRow << std::endl;
2202  }
2203 #endif
2204 
2205 #ifdef Xyce_DEBUG_DEVICE
2206  Xyce::dout() << section_divider << std::endl;
2207 #endif
2208 }
2209 
2210 //-----------------------------------------------------------------------------
2211 // Function : Instance::setupIntNameMap
2212 // Purpose : Sets up the "internal names map".
2213 //
2214 // Special Notes : This is to help with debugging. It assigns a unique
2215 // std::string name to each internal variable of this device.
2216 //
2217 // This function was once part of registerGID's, but I
2218 // decided to break that function up to make it more
2219 // readable.
2220 //
2221 // Scope : public
2222 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2223 // Creation Date : 03/02/03
2224 //-----------------------------------------------------------------------------
2226 {
2227  int i;
2228  char tmpchar[128]; for (i=0;i<128;++i) tmpchar[i] = 0;
2229 
2230  // set up the intNameMap, if necessary.
2231  for (i=0;i<numMeshPoints;++i)
2232  {
2233 #ifdef Xyce_NEW_BC
2234  if (boundarySten[i]) continue;
2235 #endif // Xyce_NEW_BC
2236 
2237  int Vrow, Nrow, Prow;
2238  Vrow = Vrowarray[i];
2239  Nrow = Nrowarray[i];
2240  Prow = Prowarray[i];
2241 
2242  if (Vrow != -1)
2243  {
2244  std::ostringstream oss;
2245  oss << getName() << "_V_" << i << "_" << labelNameVector[i];
2246  intNameMap[Vrow] = oss.str();
2247  }
2248 
2249  if (Nrow != -1)
2250  {
2251  std::ostringstream oss;
2252  oss << getName() << "_N_" << i << "_" << labelNameVector[i];
2253  intNameMap[Nrow] = oss.str();
2254  }
2255 
2256  if (Prow != -1)
2257  {
2258  std::ostringstream oss;
2259  oss << getName() << "_P_" << i << "_" << labelNameVector[i];
2260  intNameMap[Prow] = oss.str();
2261  }
2262  }
2263 }
2264 //-----------------------------------------------------------------------------
2265 // Function : Instance::getIntNameMap
2266 // Purpose :
2267 // Special Notes :
2268 // Scope : public
2269 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2270 // Creation Date : 05/13/05
2271 //-----------------------------------------------------------------------------
2272 std::map<int,std::string> & Instance::getIntNameMap ()
2273 {
2274  // set up the internal name map, if it hasn't been already.
2275  if (intNameMap.empty ())
2276  {
2277  setupIntNameMap ();
2278  }
2279 
2280  return intNameMap;
2281 }
2282 
2283 //-----------------------------------------------------------------------------
2284 // Function : Instance::setupRowColPairs
2285 //
2286 // Purpose : This function performs part of the "registerGIDs"
2287 // functionality, in that it sets up the Jacobian
2288 // matrix (row,col) pairs.
2289 //
2290 // Special Notes : This function was once part of registerGIDs, but I
2291 // moved it out b/c that function was so big that it needed
2292 // to be broken up. This function is now called from
2293 // registerGIDs.
2294 //
2295 // Scope : public
2296 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2297 // Creation Date : 03/02/03
2298 //-----------------------------------------------------------------------------
2300 {
2301 
2302  int i, j;
2303  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
2304  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
2305  std::vector<DeviceInterfaceNode>::iterator iterDI;
2306 
2307 #ifdef Xyce_DEBUG_DEVICE
2308  if (getDeviceOptions().debugLevel > 0)
2309  {
2310  Xyce::dout() << "Instance::setupRowColPairs ()" << std::endl;
2311  Xyce::dout() << " doing internal vars, col arrays:"<< std::endl;
2312  }
2313 #endif
2314 
2315  /////////////////////////////////////////////////////////////////////////
2316  // now do the colarrays for each variable type:
2317  for(i=0;i<numMeshPoints;++i)
2318  {
2319 
2320 #ifdef Xyce_NEW_BC
2321  if (boundarySten[i]) continue;
2322 #endif // Xyce_NEW_BC
2323 
2324 #ifdef Xyce_DEBUG_DEVICE
2325  if (getDeviceOptions().debugLevel > 1)
2326  {
2327  Xyce::dout() << "doing col arrays for mesh point " << i<< std::endl;
2328  }
2329 #endif
2330 
2331  mNode * nodePtr = meshContainerPtr->getNode(i);
2332  std::vector<EDGEINFO>::iterator firstEI = nodePtr->edgeInfoVector.begin ();
2333  std::vector<EDGEINFO>::iterator lastEI = nodePtr->edgeInfoVector.end ();
2334  std::vector<EDGEINFO>::iterator iterEI;
2335 
2336  // voltage col arrays:
2337  Vcolarray[i].push_back(Vrowarray[i]);
2338 
2339  // loop over the neighbor nodes of node i.
2340  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
2341  {
2342 #ifdef Xyce_NEW_BC
2343  // if the neighbor node is on a boundary, need to use the
2344  // GID of the connected ckt node, rather than the (nonexistant)
2345  // GID of the boundary mesh node.
2346  if (boundaryStenV[iterEI->inode])
2347  {
2348  // get the gid:
2349  int DIindex = labelDIMap[labelNameVector[iterEI->inode]];
2350  Vcolarray[i].push_back (dIVec[DIindex].gid);
2351  }
2352  else
2353  {
2354  Vcolarray[i].push_back(Vrowarray[iterEI->inode]);
2355  }
2356 #else
2357  Vcolarray[i].push_back(Vrowarray[iterEI->inode]);
2358 #endif // Xyce_NEW_BC
2359  }
2360 
2361  Vcolarray[i].push_back(Nrowarray[i]);
2362  Vcolarray[i].push_back(Prowarray[i]);
2363 
2364 #ifdef Xyce_DEBUG_DEVICE
2365  if (getDeviceOptions().debugLevel > 2)
2366  {
2367  Xyce::dout() << "size of vcolarray["<<i<<"] = " << Vcolarray[i].size() << std::endl;
2368  for(int eric=0;eric<Vcolarray[i].size();++eric)
2369  Xyce::dout() << " col["<<eric<<"] = " << Vcolarray[i][eric] << std::endl;
2370  }
2371 #endif
2372 
2373  // electron col arrays:
2374  Ncolarray[i].push_back(Nrowarray[i]);
2375 
2376  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
2377  {
2378  Ncolarray[i].push_back(Nrowarray[iterEI->inode]);
2379  }
2380 
2381  Ncolarray[i].push_back(Vrowarray[i]);
2382  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
2383  {
2384 #ifdef Xyce_NEW_BC
2385  // if the neighbor node is on a boundary, need to use the
2386  // GID of the connected ckt node, rather than the (nonexistant)
2387  // GID of the boundary mesh node.
2388  if (boundaryStenV[iterEI->inode])
2389  {
2390  // get the gid:
2391  int DIindex = labelDIMap[labelNameVector[iterEI->inode]];
2392  Ncolarray[i].push_back (dIVec[DIindex].gid);
2393  }
2394  else
2395  {
2396  Ncolarray[i].push_back(Vrowarray[iterEI->inode]);
2397  }
2398 #else
2399  Ncolarray[i].push_back(Vrowarray[iterEI->inode]);
2400 #endif // Xyce_NEW_BC
2401  }
2402  Ncolarray[i].push_back(Prowarray[i]);
2403 
2404  // hole col arrays:
2405  Pcolarray[i].push_back(Prowarray[i]);
2406 
2407  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
2408  {
2409  Pcolarray[i].push_back(Prowarray[iterEI->inode]);
2410  }
2411  Pcolarray[i].push_back(Vrowarray[i]);
2412  for (iterEI=firstEI;iterEI!=lastEI;++iterEI)
2413  {
2414 #ifdef Xyce_NEW_BC
2415  // if the neighbor node is on a boundary, need to use the
2416  // GID of the connected ckt node, rather than the (nonexistant)
2417  // GID of the boundary mesh node.
2418  if (boundaryStenV[iterEI->inode])
2419  {
2420  // get the gid:
2421  int DIindex = labelDIMap[labelNameVector[iterEI->inode]];
2422  Pcolarray[i].push_back (dIVec[DIindex].gid);
2423  }
2424  else
2425  {
2426  Pcolarray[i].push_back(Vrowarray[iterEI->inode]);
2427  }
2428 #else
2429  Pcolarray[i].push_back(Vrowarray[iterEI->inode]);
2430 #endif // Xyce_NEW_BC
2431  }
2432  Pcolarray[i].push_back(Nrowarray[i]);
2433 
2434  } // mesh point loop.
2435 
2436 #ifdef Xyce_DEBUG_DEVICE
2437  if (getDeviceOptions().debugLevel > 0)
2438  {
2439  Xyce::dout() << "doing some boundary condition vars:"<< std::endl;
2440  }
2441 #endif
2442 
2443  // go back to the nodes which are boundary condition nodes - ones
2444  // that are connected to the external nodes, and add a few
2445  // (row, col) pairs . These nodes will need some extra ones, at
2446  // least to handle boundary conditions on the voltage.
2447 
2448  // loop over the boundary condition "device interface" labels.
2449  firstDI = dIVec.begin();
2450  lastDI = dIVec.end ();
2451 
2452  int index;
2453 
2454  for(index=0,iterDI=firstDI;iterDI!=lastDI;++iterDI,++index)
2455  {
2456  // check that this label exists, and is an edge label
2457  // (everything in the dIVec container should pass these tests
2458  // by this point)
2459  if ( !( meshContainerPtr->labelNameExist(dIVec[index].eName) ) ) continue;
2460  if ( !( meshContainerPtr->labelEdgeType (dIVec[index].eName) ) ) continue;
2461 
2462 #ifdef Xyce_DEBUG_DEVICE
2463  if (getDeviceOptions().debugLevel > 1)
2464  {
2465  Xyce::dout() << "Device Interface: " << dIVec[index].eName << std::endl;
2466  }
2467 #endif
2468 
2469  mLabel * labelPtr = meshContainerPtr->getLabel(dIVec[index].eName);
2470 
2471  // obtain the node indices for the current label, loop over them.
2472  // for each edge node, add an extra column entry to the colarray,
2473  // which corresponds to the global ID of the connected ckt node.
2474 
2475  std::vector<int>::iterator firstI = labelPtr->mNodeVector.begin();
2476  std::vector<int>::iterator lastI = labelPtr->mNodeVector.end ();
2477  std::vector<int>::iterator iterI;
2478 
2479  // For the "new" boundary conditions, this step isn't neccessary,
2480  // as the boundary nodes no longer have any dependent variables.
2481  // However, it is neccessary for the col array associated with
2482  // the "boundary condition" equation.
2483 #ifndef Xyce_NEW_BC
2484  for(iterI=firstI;iterI!=lastI;++iterI)
2485  {
2486  Vcolarray[*iterI].push_back(dIVec[index].gid);
2487  }
2488 #endif // Xyce_NEW_BC
2489 
2490  int itmp;
2491  // Add indices to the colarray of the external circuit nodes.
2492 
2493  // These are for satisfying the KCL of the node - it will depend on
2494  // all the currents of all the edge nodes. Unfortunately, this
2495  // results in a potentially(probably) dense matrix row.
2496  //
2497  // Note that if this is a dielectric boundary, then no current is
2498  // going to come out of device at this boundary (no conduction
2499  // current, anyway), and that a lot of these (row, col) pairs will
2500  // wind up being loaded with 0's in that case. However, it doesn't
2501  // hurt to have them, so I'm leaving them in.
2502 
2503  // first push back the (gid,gid) entry. Then do the entries related
2504  // to the nearest neighbors of edge nodes.
2505  //dIVec[index].col.push_back(dIVec[index].gid);
2506 
2507  std::vector<EDGEINFO>::iterator firstEI;
2508  std::vector<EDGEINFO>::iterator lastEI;
2509  std::vector<EDGEINFO>::iterator iterEI;
2510 
2511 #ifdef Xyce_DEBUG_DEVICE
2512  if (getDeviceOptions().debugLevel > 2)
2513  {
2514  Xyce::dout() << "V edge and edge neighbor gids:" << std::endl;
2515  }
2516 #endif
2517 
2518  // now do the V edge and edge neighbor nodes.
2519  for(iterI=firstI;iterI!=lastI;++iterI)
2520  {
2521  itmp = Vrowarray[*iterI];
2522  dIVec[index].Vcol.push_back(itmp);
2523 
2524 #ifdef Xyce_DEBUG_DEVICE
2525  if (getDeviceOptions().debugLevel > 2)
2526  {
2527  int ind1 = dIVec[index].Vcol.size()-1;
2528  Xyce::dout() << " 1Vcol["<<ind1<<"] = " << itmp << std::endl;
2529  }
2530 #endif
2531 
2532  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
2533  firstEI = nodePtr->edgeInfoVector.begin();
2534  lastEI = nodePtr->edgeInfoVector.end ();
2535 
2536  // loop over the edges connected to the current node:
2537  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI)
2538  {
2539  itmp = Vrowarray[iterEI->inode];
2540  dIVec[index].Vcol.push_back(itmp);
2541 
2542 #ifdef Xyce_DEBUG_DEVICE
2543  if (getDeviceOptions().debugLevel > 2)
2544  {
2545  int ind1 = dIVec[index].Vcol.size()-1;
2546  Xyce::dout() << " 2Vcol["<<ind1<<"] = " << itmp << std::endl;
2547  }
2548 #endif
2549  }
2550  } // iterI loop
2551 
2552 #ifdef Xyce_DEBUG_DEVICE
2553  if (getDeviceOptions().debugLevel > 2)
2554  {
2555  Xyce::dout() << "N edge and edge neighbor gids:" << std::endl;
2556  }
2557 #endif
2558 
2559  // now do the N nodes.
2560  for(iterI=firstI;iterI!=lastI;++iterI)
2561  {
2562  itmp = Nrowarray[*iterI];
2563  dIVec[index].Ncol.push_back(itmp);
2564 
2565 #ifdef Xyce_DEBUG_DEVICE
2566  if (getDeviceOptions().debugLevel > 2)
2567  {
2568  int ind1 = dIVec[index].Ncol.size()-1;
2569  Xyce::dout() << " 1Ncol["<<ind1<<"] = " << itmp << std::endl;
2570  }
2571 #endif
2572 
2573  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
2574  firstEI = nodePtr->edgeInfoVector.begin();
2575  lastEI = nodePtr->edgeInfoVector.end ();
2576 
2577  // loop over the edges connected to the current node:
2578  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI)
2579  {
2580  itmp = Nrowarray[iterEI->inode];
2581  dIVec[index].Ncol.push_back(itmp);
2582 
2583 #ifdef Xyce_DEBUG_DEVICE
2584  if (getDeviceOptions().debugLevel > 2)
2585  {
2586  int ind1 = dIVec[index].Ncol.size()-1;
2587  Xyce::dout() << " 2Ncol["<<ind1<<"] = " << itmp << std::endl;
2588  }
2589 #endif
2590  }
2591  } // iterI loop
2592 
2593 #ifdef Xyce_DEBUG_DEVICE
2594  if (getDeviceOptions().debugLevel > 2)
2595  {
2596  Xyce::dout() << "P edge and edge neighbor gids:" << std::endl;
2597  }
2598 #endif
2599  // now do the P nodes.
2600  for(iterI=firstI;iterI!=lastI;++iterI)
2601  {
2602  itmp = Prowarray[*iterI];
2603  dIVec[index].Pcol.push_back(itmp);
2604 
2605 #ifdef Xyce_DEBUG_DEVICE
2606  if (getDeviceOptions().debugLevel > 2)
2607  {
2608  int ind1 = dIVec[index].Pcol.size()-1;
2609  Xyce::dout() << " 1Pcol["<<ind1<<"] = " << itmp << std::endl;
2610  }
2611 #endif
2612 
2613  mNode * nodePtr = meshContainerPtr->getNode(*iterI);
2614  firstEI = nodePtr->edgeInfoVector.begin();
2615  lastEI = nodePtr->edgeInfoVector.end ();
2616 
2617  // loop over the edges connected to the current node:
2618  for (iterEI=firstEI; iterEI!=lastEI; ++iterEI)
2619  {
2620  itmp = Prowarray[iterEI->inode];
2621  dIVec[index].Pcol.push_back(itmp);
2622 
2623 #ifdef Xyce_DEBUG_DEVICE
2624  if (getDeviceOptions().debugLevel > 2)
2625  {
2626  int ind1 = dIVec[index].Pcol.size()-1;
2627  Xyce::dout() << " 2Pcol["<<ind1<<"] = " << itmp << std::endl;
2628  }
2629 #endif
2630  }
2631  }// iterI loop
2632 
2633  if (maxColsPerRow <
2634  (dIVec[index].Vcol.size() +
2635  dIVec[index].Ncol.size() +
2636  dIVec[index].Pcol.size() + 10)
2637  )
2638  {
2639  maxColsPerRow =
2640  (dIVec[index].Vcol.size() +
2641  dIVec[index].Ncol.size() +
2642  dIVec[index].Pcol.size() + 10); // extra 10 just in case.
2643  }
2644  } // end of index (dIVec) loop
2645 
2646 #ifdef Xyce_DEBUG_DEVICE
2647  if (getDeviceOptions().debugLevel > 0)
2648  {
2649  Xyce::dout() << "Setting up the index pairs."<< std::endl;
2650  }
2651 #endif
2652 
2653  // Now that all the row and col arrays are set up, do the
2654  // index pair list.
2655  index_pair IP(0,0);
2656 
2657  int nn;
2658 
2659  // external KCL points first:
2660  firstDI = dIVec.begin();
2661  lastDI = dIVec.end ();
2662  for(index=0,iterDI=firstDI;iterDI!=lastDI;++iterDI,++index)
2663  {
2664 #ifdef Xyce_DEBUG_DEVICE
2665  if (getDeviceOptions().debugLevel > 2)
2666  Xyce::dout() << "device interface name: " << iterDI->eName << std::endl;
2667 #endif
2668  // check that this label exists, and is an edge label
2669  // (everything in the dIVec container should pass these tests
2670  // by this point)
2671  if ( !( meshContainerPtr->labelNameExist(dIVec[index].eName) ) ) continue;
2672  if ( !( meshContainerPtr->labelEdgeType (dIVec[index].eName) ) ) continue;
2673  if ( dIVec[index].gid == -1) continue;
2674 
2675  mLabel * labelPtr = meshContainerPtr->getLabel(dIVec[index].eName);
2676 
2677 #ifdef Xyce_DEBUG_DEVICE
2678  if (getDeviceOptions().debugLevel > 2)
2679  Xyce::dout() << "index = " << index<< " gid = " << dIVec[index].gid << std::endl;
2680 #endif
2681 
2682  // Do the (gid, gid) node.
2683  IP.row = dIVec[index].gid;
2684  IP.col = dIVec[index].gid;
2685  indexPairList.push_back(IP);
2686 
2687  // do the other (gid_1, gid_2) elements. These are needed for 2-level
2688  // "ckt-only" matrix loads.
2689  int size2 = dIVec.size();
2690  for (int ind2=0;ind2<size2;++ind2)
2691  {
2692  if (index == ind2) continue;
2693  IP.row = dIVec[index].gid;
2694  IP.col = dIVec[ind2].gid;
2695  indexPairList.push_back(IP);
2696  }
2697 
2698  // Loop over the mesh nodes that affect this terminal current.
2699  // Add row, col pairs for each variable.
2700  nn = dIVec[index].Vcol.size();
2701  for (j=0;j<nn;++j)
2702  {
2703  // electrostatic potential (row, col) pairs.
2704  if (dIVec[index].Vcol[j] != -1)
2705  {
2706  IP.row = dIVec[index].gid;
2707  IP.col = dIVec[index].Vcol[j];
2708  indexPairList.push_back(IP);
2709 #ifdef Xyce_DEBUG_DEVICE
2710  if (getDeviceOptions().debugLevel > 2)
2711  {
2712  Xyce::dout() << "Vcol["<<j<<"] = " << dIVec[index].Vcol[j] << std::endl;
2713  }
2714 #endif
2715  }
2716  }
2717 
2718  for (j=0;j<nn;++j)
2719  {
2720  // electron (row, col) pairs.
2721  if (dIVec[index].Ncol[j] != -1)
2722  {
2723  IP.row = dIVec[index].gid;
2724  IP.col = dIVec[index].Ncol[j];
2725  indexPairList.push_back(IP);
2726 #ifdef Xyce_DEBUG_DEVICE
2727  if (getDeviceOptions().debugLevel > 2)
2728  {
2729  Xyce::dout() << "Ncol["<<j<<"] = " << dIVec[index].Ncol[j] << std::endl;
2730  }
2731 #endif
2732  }
2733  }
2734 
2735  for (j=0;j<nn;++j)
2736  {
2737  // hole (row, col) pairs.
2738  if (dIVec[index].Pcol[j] != -1)
2739  {
2740  IP.row = dIVec[index].gid;
2741  IP.col = dIVec[index].Pcol[j];
2742  indexPairList.push_back(IP);
2743 #ifdef Xyce_DEBUG_DEVICE
2744  if (getDeviceOptions().debugLevel > 2)
2745  {
2746  Xyce::dout() << "Pcol["<<j<<"] = " << dIVec[index].Pcol[j] << std::endl;
2747  }
2748 #endif
2749  }
2750  } // end of j loop.
2751  } // end of DI loop
2752 
2753  // interior points next:
2754  for (i=0;i<numMeshPoints;++i)
2755  {
2756 #ifdef Xyce_DEBUG_DEVICE
2757  if (getDeviceOptions().debugLevel > 2)
2758  {
2759  Xyce::dout() << "Mesh Index: i = " << i << " label = ";
2760  Xyce::dout() << labelNameVector[i] << std::endl;
2761  }
2762 #endif
2763  nn = Vcolarray[i].size();
2764 
2765  for (j=0;j<nn;++j)
2766  {
2767  if (Vrowarray[i] != -1 && Vcolarray[i][j] != -1)
2768  {
2769  IP.row = Vrowarray[i];
2770  IP.col = Vcolarray[i][j];
2771  indexPairList.push_back(IP);
2772 #ifdef Xyce_DEBUG_DEVICE
2773  if (getDeviceOptions().debugLevel > 2)
2774  {
2775  Xyce::dout() << " V row,col = " << Vrowarray[i] << ", ";
2776  Xyce::dout() << Vcolarray[i][j] << "\n";
2777  }
2778 #endif
2779  }
2780  }
2781 
2782  nn = Ncolarray[i].size();
2783  for (j=0;j<nn;++j)
2784  {
2785  if (Nrowarray[i] != -1 && Ncolarray[i][j] != -1)
2786  {
2787  IP.row = Nrowarray[i];
2788  IP.col = Ncolarray[i][j];
2789  indexPairList.push_back(IP);
2790 #ifdef Xyce_DEBUG_DEVICE
2791  if (getDeviceOptions().debugLevel > 2)
2792  {
2793  Xyce::dout() << " N row,col = " << Nrowarray[i] << ", ";
2794  Xyce::dout() << Ncolarray[i][j] << "\n";
2795  }
2796 #endif
2797  }
2798  }
2799 
2800  nn = Pcolarray[i].size();
2801  for (j=0;j<nn;++j)
2802  {
2803  if (Prowarray[i] != -1 && Pcolarray[i][j] != -1)
2804  {
2805  IP.row = Prowarray[i];
2806  IP.col = Pcolarray[i][j];
2807  indexPairList.push_back(IP);
2808 #ifdef Xyce_DEBUG_DEVICE
2809  if (getDeviceOptions().debugLevel > 2)
2810  {
2811  Xyce::dout() << " P row,col = " << Prowarray[i] << ", ";
2812  Xyce::dout() << Pcolarray[i][j] << "\n";
2813  }
2814 #endif
2815  }
2816  }
2817  }
2818 
2819 #ifdef Xyce_DEBUG_DEVICE
2820  if (getDeviceOptions().debugLevel > 2)
2821  {
2822  Xyce::dout() << std::endl;
2823  }
2824 #endif
2825 
2826  // now that the index pair list has been set up,
2827  // print it out to the screen.
2828 #ifdef Xyce_DEBUG_DEVICE
2829  if (getDeviceOptions().debugLevel > 2)
2830  {
2831  std::list<index_pair>::iterator ip_iter;
2832  for (i=0,
2833  ip_iter = indexPairList.begin();
2834  ip_iter != indexPairList.end();
2835  ++ip_iter,++i)
2836  {
2837  Xyce::dout() << "i="<<i<<": (";
2838  Xyce::dout().width(6);
2839  Xyce::dout() << ip_iter->row;
2840  Xyce::dout() << ", ";
2841  Xyce::dout().width(6);
2842  Xyce::dout() << ip_iter->col;
2843  Xyce::dout() << ")\n";
2844  }
2845  }
2846 #endif
2847 
2848 }
2849 
2850 //-----------------------------------------------------------------------------
2851 // Function : Instance::registerStateGIDs
2852 // Purpose :
2853 // Special Notes :
2854 //
2855 // Scope : public
2856 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2857 // Creation Date : 11/14/01
2858 //-----------------------------------------------------------------------------
2860  const std::list<index_pair> & staGIDListRef)
2861 {
2862  AssertLIDs(staGIDListRef.size() == numStateVars);
2863 
2864 #ifdef Xyce_DEBUG_DEVICE
2865  if (getDeviceOptions().debugLevel > 0)
2866  {
2867  Xyce::dout() << "\n";
2868  Xyce::dout() << section_divider << "\n";
2869  Xyce::dout() << " In Instance::registerStateGIDs\n\n";
2870  Xyce::dout() << " name = " << getName() << "\n";
2871  Xyce::dout() << " Number of State GIDs: " << numStateVars << "\n";
2872  }
2873 #endif
2874 
2875  // Copy over the global ID lists:
2876  staGIDList.assign(staGIDListRef.begin(), staGIDListRef.end());
2877 
2878  std::list<index_pair>::iterator it1 = staGIDList.begin();
2879  std::list<index_pair>::iterator last1 = staGIDList.end ();
2880 
2881  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
2882  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
2883  std::vector<DeviceInterfaceNode>::iterator iterDI = firstDI;
2884 
2885  int i=0;
2886  for (; (iterDI!=lastDI && it1!=last1);++iterDI,++it1,++i)
2887  {
2888  iterDI->stateC = (*it1).row;
2889  iterDI->stateC_owned = (it1->col == 1);
2890  }
2891 
2892  for (i=0;i<numMeshPoints;++i,++it1)
2893  {
2894  stateDispl[i] = (*it1).row;
2895  stateDispl_owned[i] = static_cast<int>((it1->col == 1));
2896  }
2897 
2898 
2899 #ifdef Xyce_DEBUG_DEVICE
2900  if (getDeviceOptions().debugLevel > 1)
2901  {
2902  Xyce::dout() << " State indices:" << "\n";
2903  Xyce::dout() << "\n";
2904  for (iterDI=firstDI; iterDI!=lastDI;++iterDI)
2905  {
2906  Xyce::dout() << " ";
2907  Xyce::dout().width(12);
2908  Xyce::dout().setf(std::ios::right);
2909  Xyce::dout() << iterDI->eName;
2910  Xyce::dout().setf(std::ios::left);
2911  Xyce::dout() << " stateC = " << iterDI->stateC;
2912  Xyce::dout() << " stateC_owned = " << iterDI->stateC_owned << "\n";
2913  }
2914 
2915  Xyce::dout() << section_divider << std::endl;
2916  }
2917 #endif
2918 
2919 }
2920 
2921 //-----------------------------------------------------------------------------
2922 // Function : DiodeDPEInstance::registerLIDs
2923 // Purpose :
2924 // Special Notes :
2925 // Scope : public
2926 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2927 // Creation Date : 09/18/02
2928 //-----------------------------------------------------------------------------
2929 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
2930  const std::vector<int> & extLIDVecRef)
2931 {
2932  AssertLIDs(intLIDVecRef.size() == numIntVars);
2933  // AssertLIDs(extLIDVecRef.size() == numExtVars);
2934 
2935 #ifdef Xyce_DEBUG_DEVICE
2936  if (getDeviceOptions().debugLevel > 0)
2937  {
2938  Xyce::dout() << section_divider << std::endl;
2939  Xyce::dout() << "In the Intance::registerLIDs function. ";
2940  Xyce::dout() << " name = "<< getName() << std::endl;
2941  Xyce::dout() << "numInt = " << numIntVars << std::endl;
2942  Xyce::dout() << "numExt = " << numExtVars << std::endl;
2943  Xyce::dout() << "numMeshPoints = " << numMeshPoints << std::endl;
2944  }
2945 #endif
2946 
2947  // copy over the global ID lists:
2948  intLIDVec = intLIDVecRef;
2949  extLIDVec = extLIDVecRef;
2950 
2951  // Set up the rows first, then do the colarrays.
2952 
2953  // First do the external variables:
2954  // These will all be voltage nodes connected to the devices.
2955 #ifdef Xyce_DEBUG_DEVICE
2956  if (getDeviceOptions().debugLevel > 0)
2957  {
2958  Xyce::dout() << "Setting up the indices for the external circuit nodes:" << std::endl;
2959  Xyce::dout() << "External node list:" << std::endl;
2960  }
2961 #endif
2962 
2963  int isizeDI = dIVec.size();
2964 
2965  int index;
2966  for(index=0; index < isizeDI; ++index)
2967  {
2968  dIVec[index].lid = extLIDVec[index];
2969 
2970 #ifdef Xyce_DEBUG_DEVICE
2971  if (getDeviceOptions().debugLevel > 1)
2972  {
2973  Xyce::dout() << " name = "<<dIVec[index].eName<<" lid = ";
2974  Xyce::dout() << dIVec[index].lid;
2975  Xyce::dout() << std::endl;
2976  }
2977 #endif
2978  }
2979 
2980 
2981 #ifdef Xyce_DEBUG_DEVICE
2982  if (getDeviceOptions().debugLevel > 0)
2983  {
2984  Xyce::dout() << "Doing internal vars, row arrays:"<< std::endl;
2985  }
2986 #endif
2987 
2988  // Do the internal variables. There should be a lot of these.
2989  int i=0;
2990  index = 0;
2991 
2992  // The interior points will be blocked (V,N,P) together.
2993  while (i < numMeshPoints)
2994  {
2995 #ifdef Xyce_NEW_BC
2996  if (boundarySten[i]) { ++i; continue; }
2997 
2998  if (!(boundaryStenV[i]))
2999  {
3000  li_Vrowarray[i] = intLIDVec[index]; // should be Vrowarray[i]
3001  ++index;
3002  }
3003 
3004  if (!(boundaryStenN[i]))
3005  {
3006  li_Nrowarray[i] = intLIDVec[index];
3007  ++index;
3008  }
3009 
3010  if (!(boundaryStenP[i]))
3011  {
3012  li_Prowarray[i] = intLIDVec[index];
3013  ++index;
3014  }
3015 
3016 #ifdef Xyce_DEBUG_DEVICE
3017  if (getDeviceOptions().debugLevel > 1)
3018  {
3019  Xyce::dout() << "doing lid row arrays for mesh point " << i << std::endl;
3020  if (!(boundaryStenV[i]))
3021  Xyce::dout() << " li_Vrow = " << li_Vrowarray[i] << std::endl;
3022 
3023  if (!(boundaryStenN[i]))
3024  Xyce::dout() << " li_Nrow = " << li_Nrowarray[i] << std::endl;
3025 
3026  if (!(boundaryStenP[i]))
3027  Xyce::dout() << " li_Prow = " << li_Prowarray[i] << std::endl;
3028  }
3029 #endif
3030 
3031 #else
3032  li_Vrowarray[i] = intLIDVec[index]; // should be Vrowarray[i]
3033  ++index;
3034 
3035  li_Nrowarray[i] = intLIDVec[index];
3036  ++index;
3037 
3038  li_Prowarray[i] = intLIDVec[index];
3039  ++index;
3040 
3041 #ifdef Xyce_DEBUG_DEVICE
3042  if (getDeviceOptions().debugLevel > 1)
3043  {
3044  Xyce::dout() << "doing lid row arrays for mesh point " << i << std::endl;
3045  Xyce::dout() << " li_Vrow = " << li_Vrowarray[i] << std::endl;
3046  Xyce::dout() << " li_Nrow = " << li_Nrowarray[i] << std::endl;
3047  Xyce::dout() << " li_Prow = " << li_Prowarray[i] << std::endl;
3048  }
3049 #endif
3050 #endif // Xyce_NEW_BC
3051  ++i;
3052  }
3053 
3054 #ifdef Xyce_DEBUG_DEVICE
3055  Xyce::dout() << section_divider << std::endl;
3056 #endif
3057 
3058 
3059 }
3060 
3061 //-----------------------------------------------------------------------------
3062 // Function : Instance::registerStateLIDs
3063 // Purpose :
3064 // Special Notes :
3065 // Scope : public
3066 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3067 // Creation Date : 09/18/02
3068 //-----------------------------------------------------------------------------
3069 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef)
3070 {
3071  AssertLIDs(staLIDVecRef.size() == numStateVars);
3072 
3073 #ifdef Xyce_DEBUG_DEVICE
3074  if (getDeviceOptions().debugLevel > 0)
3075  {
3076  Xyce::dout() << "\n";
3077  Xyce::dout() << section_divider << "\n";
3078  Xyce::dout() << " In Instance::registerStateLIDs\n\n";
3079  Xyce::dout() << " name = " << getName() << "\n";
3080  Xyce::dout() << " Number of State LIDs: " << numStateVars << "\n";
3081  }
3082 #endif
3083 
3084  // Copy over the local ID lists:
3085  staLIDVec = staLIDVecRef;
3086 
3087  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
3088  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
3089  std::vector<DeviceInterfaceNode>::iterator iterDI = firstDI;
3090 
3091  int i=0,j=0;
3092  for (; iterDI!=lastDI;++iterDI,++i)
3093  {
3094  iterDI->li_stateC = staLIDVec[i];
3095  }
3096 
3097  for (j=0;j<numMeshPoints;++j,++i)
3098  {
3099  li_stateDispl[j] = staLIDVec[i];
3100  }
3101 
3102 
3103 #ifdef Xyce_DEBUG_DEVICE
3104  if (getDeviceOptions().debugLevel > 1)
3105  {
3106  Xyce::dout() << " State indices:" << "\n";
3107  Xyce::dout() << "\n";
3108  for (iterDI=firstDI; iterDI!=lastDI;++iterDI)
3109  {
3110  Xyce::dout() << " ";
3111  Xyce::dout().width(12);
3112  Xyce::dout().setf(std::ios::right);
3113  Xyce::dout() << iterDI->eName;
3114  Xyce::dout().setf(std::ios::left);
3115  Xyce::dout() << " li_stateC = " << iterDI->li_stateC;
3116  Xyce::dout() << std::endl;
3117  }
3118 
3119  Xyce::dout() << " Displacement state indices:\n";
3120  for (j=0;j<numMeshPoints;++j,++i)
3121  {
3122  Xyce::dout() << " edge: " << j << " li_stateDispl = " << li_stateDispl[j];
3123  Xyce::dout() << std::endl;
3124  }
3125 
3126  Xyce::dout() << section_divider << std::endl;
3127  }
3128 #endif
3129 
3130 }
3131 
3132 //-----------------------------------------------------------------------------
3133 // Function : Instance::jacobianStamp
3134 // Purpose :
3135 // Special Notes :
3136 // Scope : public
3137 // Creator : Eric R. Keiter, Dept. 9233
3138 // Creation Date : 02/23/03
3139 //-----------------------------------------------------------------------------
3140 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
3141 {
3142  return jacStamp;
3143 }
3144 
3145 //-----------------------------------------------------------------------------
3146 // Function : Instance::registerJacLIDs
3147 //
3148 // Purpose : This function sets up the "local-ID" (LID) jacobian
3149 // stamp. This is neccessary for the DMA=on capability,
3150 // which is the default. This represents the stuff that
3151 // comes in from topology.
3152 //
3153 // Special Notes : This needs to be consistent with the function,
3154 // Instance::setupJacStamp.
3155 //
3156 //
3157 // Scope : public
3158 // Creator : Eric R. Keiter, Dept. 9233
3159 // Creation Date : 02/23/03
3160 //-----------------------------------------------------------------------------
3162  ( const std::vector< std::vector<int> > & jacLIDVec )
3163 {
3164  DeviceInstance::registerJacLIDs ( jacLIDVec );
3165 
3166  int i;
3167 
3168 #ifdef Xyce_DEBUG_DEVICE
3169  if (getDeviceOptions().debugLevel > 0)
3170  {
3171  Xyce::dout() << "In Instance::registerJacLIDs" << std::endl;
3172  }
3173 #endif
3174 
3175  /////////////////////////////////////////////////////////////////////////
3176  // Do the external variables first:
3177  // Loop over the boundary condition "device interface" labels.
3178  std::vector<DeviceInterfaceNode>::iterator firstDI = dIVec.begin();
3179  std::vector<DeviceInterfaceNode>::iterator lastDI = dIVec.end ();
3180  std::vector<DeviceInterfaceNode>::iterator iterDI;
3181  int DIsize = dIVec.size ();
3182  firstDI = dIVec.begin();
3183  lastDI = dIVec.end ();
3184 
3185  int index;
3186  for(index=0,iterDI=firstDI;iterDI!=lastDI;++iterDI,++index)
3187  {
3188  int jacRowSize = jacLIDVec[index].size();
3189  dIVec[index].dIdXoffset.resize(jacRowSize-dIVec[index].numCrossTerms-1);
3190  dIVec[index].lidOffset = jacLIDVec[index][0];
3191 
3192 #ifdef Xyce_DEBUG_DEVICE
3193  if (getDeviceOptions().debugLevel > 0)
3194  {
3195  Xyce::dout() << "index = " << index;
3196  Xyce::dout() << " jacRowSize = " << jacRowSize;
3197  Xyce::dout() << " name = " << dIVec[index].eName << std::endl;
3198  Xyce::dout() << " lidOffset = ";
3199  Xyce::dout() << dIVec[index].lidOffset << std::endl;
3200  }
3201 #endif
3202 
3203  int nCT = dIVec[index].numCrossTerms;
3204 
3205  dIVec[index].crossOffsets.resize(nCT);
3206 
3207  for(int itmp=0;itmp<nCT;++itmp)
3208  {
3209  dIVec[index].crossOffsets[itmp] = jacLIDVec[index][itmp+1];
3210 #ifdef Xyce_DEBUG_DEVICE
3211  if (getDeviceOptions().debugLevel > 0)
3212  {
3213  Xyce::dout() << " crossOffsets["<<itmp<<"] = ";
3214  Xyce::dout() << dIVec[index].crossOffsets[itmp] << std::endl;
3215  }
3216 #endif
3217  }
3218 
3219  for (int ioff=nCT+1;ioff<jacRowSize;++ioff)
3220  {
3221  int tmpIndex = ioff - (nCT+1);
3222  dIVec[index].dIdXoffset[tmpIndex] = jacLIDVec[index][ioff];
3223 
3224 #ifdef Xyce_DEBUG_DEVICE
3225  if (getDeviceOptions().debugLevel > 0)
3226  {
3227  Xyce::dout() << " dIdXoffset["<<tmpIndex<<"] = ";
3228  Xyce::dout() << dIVec[index].dIdXoffset[tmpIndex] << std::endl;
3229  }
3230 #endif
3231  }
3232  } // index (dIVec) loop.
3233 
3234  /////////////////////////////////////////////////////////////////////////
3235  // Now do the internal variables. (V,N,P on the mesh)
3236  li_VoffsetArray.resize(numMeshPoints);
3237  li_NoffsetArray.resize(numMeshPoints);
3238  li_PoffsetArray.resize(numMeshPoints);
3239  for(i=0;i<numMeshPoints;++i)
3240  {
3241 #ifdef Xyce_NEW_BC
3242  if (boundarySten[i]) continue;
3243 #endif // Xyce_NEW_BC
3244 
3245 #ifdef Xyce_DEBUG_DEVICE
3246  if (getDeviceOptions().debugLevel > 0)
3247  {
3248  Xyce::dout() << " mesh point i = " << i << std::endl;
3249  }
3250 #endif
3251 
3252  mNode * nodePtr = meshContainerPtr->getNode(i);
3253  std::vector<EDGEINFO>::iterator firstEI = nodePtr->edgeInfoVector.begin ();
3254  std::vector<EDGEINFO>::iterator lastEI = nodePtr->edgeInfoVector.end ();
3255 
3256  // get the temporary LID row indices:
3257  int Vrow = MESHtoLID_V[i];
3258  int Nrow = MESHtoLID_N[i];
3259  int Prow = MESHtoLID_P[i];
3260 
3261 #ifdef Xyce_DEBUG_DEVICE
3262  if (getDeviceOptions().debugLevel > 0)
3263  {
3264  Xyce::dout() << " Vrow = " << Vrow << std::endl;
3265  Xyce::dout() << " Nrow = " << Nrow << std::endl;
3266  Xyce::dout() << " Prow = " << Prow << std::endl;
3267  }
3268 #endif
3269 
3270  int ioff;
3271  // voltage row:
3272  if (Vrow != -1)
3273  {
3274  int VrowSize = jacLIDVec[Vrow].size();
3275  li_VoffsetArray[i].resize(VrowSize);
3276  for (ioff=0;ioff<VrowSize;++ioff)
3277  {
3278  li_VoffsetArray[i][ioff] = jacLIDVec[Vrow][ioff];
3279 #ifdef Xyce_DEBUG_DEVICE
3280  if (getDeviceOptions().debugLevel > 1)
3281  {
3282  Xyce::dout() << " li_Voffset["<<i<<"]["<<ioff<<"] = ";
3283  Xyce::dout() << li_VoffsetArray[i][ioff] << std::endl;
3284  }
3285 #endif
3286  }
3287  }
3288 
3289  // electron row:
3290  if (Nrow != -1)
3291  {
3292  int NrowSize = jacLIDVec[Nrow].size();
3293  li_NoffsetArray[i].resize(NrowSize);
3294  for (ioff=0;ioff<NrowSize;++ioff)
3295  {
3296  li_NoffsetArray[i][ioff] = jacLIDVec[Nrow][ioff];
3297 #ifdef Xyce_DEBUG_DEVICE
3298  if (getDeviceOptions().debugLevel > 1)
3299  {
3300  Xyce::dout() << " li_Noffset["<<i<<"]["<<ioff<<"] = ";
3301  Xyce::dout() << li_NoffsetArray[i][ioff] << std::endl;
3302  }
3303 #endif
3304  }
3305  }
3306 
3307  // hole row:
3308  if (Prow != -1)
3309  {
3310  int ProwSize = jacLIDVec[Prow].size();
3311  li_PoffsetArray[i].resize(ProwSize);
3312  for (ioff=0;ioff<ProwSize;++ioff)
3313  {
3314  li_PoffsetArray[i][ioff] = jacLIDVec[Prow][ioff];
3315 #ifdef Xyce_DEBUG_DEVICE
3316  if (getDeviceOptions().debugLevel > 1)
3317  {
3318  Xyce::dout() << " li_Poffset["<<i<<"]["<<ioff<<"] = ";
3319  Xyce::dout() << li_PoffsetArray[i][ioff] << std::endl;
3320  }
3321 #endif
3322  }
3323  }
3324 
3325  } // mesh point loop
3326 }
3327 
3328 } // namespace TwoDPDE
3329 } // namespace Device
3330 } // namespace Xyce