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