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