Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_DeviceInstance.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_DeviceInstance.C,v $
27 //
28 // Purpose : Implementation of the base device instance class.
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 03/30/00
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.191 $
40 //
41 // Revision Date : $Date: 2014/05/19 20:00:59 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 #include <N_DEV_DeviceInstance.h>
49 
50 #include <N_DEV_Const.h>
51 #include <N_DEV_DeviceBlock.h>
52 #include <N_DEV_DeviceOptions.h>
53 #include <N_DEV_ExternData.h>
54 #include <N_DEV_ExternDevice.h>
55 #include <N_DEV_MatrixLoadData.h>
56 #include <N_DEV_Message.h>
58 #include <N_DEV_SolverState.h>
59 #include <N_ERH_ErrorMgr.h>
60 #include <N_LAS_Matrix.h>
61 #include <N_LAS_Vector.h>
62 
63 namespace Xyce {
64 namespace Device {
65 
66 //-----------------------------------------------------------------------------
67 // Function : DeviceInstance::DeviceInstance
68 // Purpose : instance block constructor
69 // Special Notes :
70 // Scope : public
71 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
72 // Creation Date : 3/30/00
73 //-----------------------------------------------------------------------------
75  const InstanceBlock & instance_block,
76  ParametricData<void> & parametric_data,
77  const FactoryBlock & factory_block)
78  : DeviceEntity(parametric_data, factory_block.solverState_, factory_block.deviceOptions_, instance_block.getNetlistLocation().getPath(), instance_block.getNetlistLocation().getLineNumber()),
79  name_(instance_block.getInstanceName()),
80  psLoaded(false),
81  ssLoaded(false),
82  rhsLoaded(false),
83  origFlag(true),
84  mlData(factory_block.matrixLoadData_),
85  cols(factory_block.matrixLoadData_.cols),
86  vals(factory_block.matrixLoadData_.vals),
87  numIntVars(0),
88  numExtVars(2),
89  numStateVars(0),
90  numStoreVars(0),
91  numLeadCurrentStoreVars(0),
92  configuredForLeadCurrent(false),
93  loadLeadCurrent(false),
94  mergeRowColChecked(false),
95  extData(factory_block.externData_),
96  numJacPtr(NULL)
97 {
98  devConMap.resize(2);
99  devConMap[0] = 1;
100  devConMap[1] = 1;
101  numJacPtr = new NumericalJacobian(factory_block.matrixLoadData_, factory_block.solverState_, factory_block.externData_, factory_block.deviceOptions_);
102 }
103 
104 //-----------------------------------------------------------------------------
105 // Function : DeviceInstance::~DeviceInstance
106 // Purpose : destructor
107 // Special Notes :
108 // Scope : public
109 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
110 // Creation Date : 3/30/00
111 //-----------------------------------------------------------------------------
113 {
114  delete numJacPtr;
115 }
116 
117 //-----------------------------------------------------------------------------
118 // Function : DeviceInstance::getDepSolnVars
119 //
120 // Purpose : This function configures a device to an auxiliary F & Q vector
121 // so that lead currents can be calculated for this device.c.
122 //
123 // Special Notes : This must be called soon after the constructor call
124 // before the store vector is allocated.
125 //
126 // Scope : public
127 // Creator : Richard Schiek, Electrical Systems Modeling
128 // Creation Date : 03/22/13
129 //-----------------------------------------------------------------------------
131 {
133  {
134  // indicated that this device is now configured for lead current calculation
135  // this avoids claiming too much space in the store vector if this function
136  // is called more than once for a device.
138 
139  // set device instance flag to indicate the need to load lead current
140  // data into store F & Q vectors
141  loadLeadCurrent = true;
142 
143  // request additional space in store vector for lead current vars
145  }
146  return;
147 }
148 
149 
150 //-----------------------------------------------------------------------------
151 // Function : N_DEV_DeviceInstance::getDepSolnVars
152 //
153 // Purpose : Topology uses this method to check for late dependencies
154 // due to such things as Expressions in the B-src.
155 //
156 // Special Notes : Returns empty list for devices that use this base method
157 //
158 // Scope : public
159 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
160 // Creation Date : 05/05/01
161 //-----------------------------------------------------------------------------
162 const std::vector<std::string> & DeviceInstance::getDepSolnVars()
163 {
164  return expVarNames;
165 }
166 
167 //-----------------------------------------------------------------------------
168 // Function : DeviceInstance::registerDepSolnLIDs
169 // Purpose : Allows registration of LIDs of nodes and instances that
170 // appear in expressions that occur in the device.
171 // Special Notes :
172 // Scope : public
173 // Creator : Dave Shirley, PSSI
174 // Creation Date : 03/15/05
175 //-----------------------------------------------------------------------------
177 (const std::vector< std::vector<int> > & depSolnLIDVecRef)
178 {
179  int size = expVarLIDs.size();
180  if (size != depSolnLIDVecRef.size())
181  {
182  DevelFatal0(*this).in("DeviceInstance::registerDepSolnLIDs")
183  << "Inconsistent number of LIDs returned from topology";
184  }
185  for (int i = 0; i < size; ++i)
186  {
187  if (depSolnLIDVecRef[i].size() != 1)
188  {
189  UserError0(*this) << "Problem with value for " << expVarNames[i]
190  << ". This may be an incorrect usage of a lead current in place of a current through a voltage source.";
191  }
192  expVarLIDs[i] = depSolnLIDVecRef[i][0];
193  }
194 
195  return;
196 }
197 
198 //-----------------------------------------------------------------------------
199 // Function : DeviceInstance::registerDepSolnGIDs
200 //
201 // Purpose : This function allows global ID's to be registered
202 // with a device. These global ID's refer to the global
203 // indices for the solution vector. Given these ID's, the
204 // device can then also determine the (row,col) ID's needed
205 // to load the jacobian matrix.
206 //
207 // Special Notes : The method is used for late resolution of variables
208 // of dependency such as for B-source. Does nothing for
209 // devices using this base class method.
210 //
211 // Scope : public
212 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
213 // Creation Date : 05/05/01
214 //-----------------------------------------------------------------------------
216  const std::vector< std::vector<int> > & varList )
217 {
218  int size = expVarGIDs.size();
219  for (int i = 0; i < size; ++i)
220  {
221  expVarGIDs[i] = varList[i][0];
222  }
223  return;
224 }
225 
226 //-----------------------------------------------------------------------------
227 // Function : DeviceInstance::registerJacLIDs
228 // Purpose :
229 // Special Notes :
230 // Scope : public
231 // Creator : Eric R. Keiter, SNL
232 // Creation Date :
233 //-----------------------------------------------------------------------------
234 void DeviceInstance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
235 {
236  if (getDeviceOptions().numericalJacobianFlag || getDeviceOptions().testJacobianFlag)
237  {
238  devJacLIDs = jacLIDVec;
239  }
240 }
241 
242 //-----------------------------------------------------------------------------
243 // Function : DeviceInstance::getDepSolnGIDVec
244 // Purpose :
245 // Special Notes :
246 // Scope : public
247 // Creator : Dave Shirley, PSSI
248 // Creation Date : 03/17/05
249 //-----------------------------------------------------------------------------
250 void DeviceInstance::getDepSolnGIDVec( std::vector<int> & depGIDVec )
251 {
252  depGIDVec = expVarGIDs;
253  return;
254 }
255 
256 //-----------------------------------------------------------------------------
257 // Function : DeviceInstance::getDepStateVars
258 //
259 // Purpose : Topology uses this method to check for late dependencies
260 // due to such things as Expressions in the B-src.
261 //
262 // Special Notes : Returns empty list for devices that use this base method
263 //
264 // Scope : public
265 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
266 // Creation Date : 05/05/01
267 //-----------------------------------------------------------------------------
268 const std::vector<std::string> & DeviceInstance::getDepStateVars()
269 {
270  static std::vector<std::string> emptyList;
271  emptyList.clear();
272  return emptyList;
273 }
274 
275 //-----------------------------------------------------------------------------
276 // Function : DeviceInstance::registerDepStateGIDs
277 //
278 // Purpose : This function allows global ID's to be registered
279 // with a device. These global ID's refer to the global
280 // indices for the solution vector. Given these ID's, the
281 // device can then also determine the (row,col) ID's needed
282 // to load the jacobian matrix.
283 //
284 // Special Notes : The method is used for late resolution of variables
285 // of dependency such as for B-source. Does nothing for
286 // devices using this base class method.
287 //
288 // Scope : public
289 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
290 // Creation Date : 05/05/01
291 //-----------------------------------------------------------------------------
293  const std::vector< std::vector<int> > & varList )
294 {
295  if( varList.size() != 0 )
296  {
297  std::string msg;
298  msg = "DeviceInstance::registerDepStateGIDs\n";
299  msg += "\tCall to registerDepStateGIDs for a device which doesn't use it.";
300  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
301  }
302 }
303 
304 //-----------------------------------------------------------------------------
305 // Function : DeviceInstance::getDepStoreVars
306 //
307 // Purpose : Topology uses this method to check for late dependencies
308 // due to such things as Expressions in the B-src.
309 //
310 // Special Notes : Returns empty list for devices that use this base method
311 //
312 // Scope : public
313 // Creator : Eric Keiter
314 // Creation Date :
315 //-----------------------------------------------------------------------------
316 const std::vector<std::string> & DeviceInstance::getDepStoreVars()
317 {
318  static std::vector<std::string> emptyList;
319  emptyList.clear();
320  return emptyList;
321 }
322 
323 //-----------------------------------------------------------------------------
324 // Function : DeviceInstance::registerDepStoreGIDs
325 //
326 // Purpose : This function allows global ID's to be registered
327 // with a device. These global ID's refer to the global
328 // indices for the solution vector. Given these ID's, the
329 // device can then also determine the (row,col) ID's needed
330 // to load the jacobian matrix.
331 //
332 // Special Notes : The method is used for late resolution of variables
333 // of dependency such as for B-source. Does nothing for
334 // devices using this base class method.
335 //
336 // Scope : public
337 // Creator : Eric Keiter
338 // Creation Date :
339 //-----------------------------------------------------------------------------
341  const std::vector< std::vector<int> > & varList )
342 {
343  if( varList.size() != 0 )
344  {
345  std::string msg;
346  msg = "DeviceInstance::registerDepStoreGIDs\n";
347  msg += "\tCall to registerDepStoreGIDs for a device which doesn't use it.";
348  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
349  }
350 }
351 
352 //-----------------------------------------------------------------------------
353 // Function : DeviceInstance::getIndexPairList
354 //
355 // Purpose : This function
356 //
357 // Special Notes :
358 //
359 // Scope : public
360 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
361 // Creation Date : 05/26/00
362 //-----------------------------------------------------------------------------
363 bool DeviceInstance::getIndexPairList(std::list<index_pair> & iplRef)
364 {
365  iplRef = indexPairList;
366 
367  return true;
368 }
369 
370 //-----------------------------------------------------------------------------
371 // Function : DeviceInstance::testDAEMatrices
372 // Purpose :
373 // Special Notes :
374 // Scope : public
375 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
376 // Creation Date : 12/15/06
377 //-----------------------------------------------------------------------------
378 bool DeviceInstance::testDAEMatrices (std::vector<std::string> & nameVec)
379 {
380  bool bsuccess = true;
381 
382  // if necessary, consolodate the LIDs vector.
383  if (devLIDs.empty())
384  {
385  devLIDs = extLIDVec;
386  devLIDs.insert(devLIDs.end(), intLIDVec.begin(), intLIDVec.end());
387  devLIDs.insert(devLIDs.end(), expVarLIDs.begin(), expVarLIDs.end());
388  }
389 
390  bsuccess = numJacPtr-> testDAEMatrices (*this, nameVec);
391 
392  return bsuccess;
393 }
394 
395 //-----------------------------------------------------------------------------
396 // Function : DeviceInstance::trivialStampLoader
397 // Purpose : This function contains most of the original
398 // loadTrivialMatrixStamp function. See comments above.
399 // Special Notes :
400 // Scope : public
401 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
402 // Creation Date : 05/25/05
403 //-----------------------------------------------------------------------------
404 bool DeviceInstance::trivialStampLoader (N_LAS_Matrix * matPtr)
405 {
406  int count = 0;
407  int i;
408  int row;
409 
410  std::vector<int>::const_iterator firstVar;
411  std::vector<int>::const_iterator lastVar;
412  std::vector<int>::const_iterator iterVar;
413  int localRows = matPtr->getLocalNumRows();
414 
415  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
416  {
417  Xyce::dout() << std::endl
418  << "Loading trivial stamp for " << getName() << std::endl;
419  }
420 
421  if (cols.size() < 1) cols.resize(1);
422  if (vals.size() < 1) vals.resize(1);
423 
424  for (i=0;i<2;++i)
425  {
426  // do external vars first.
427  if (i==0)
428  {
429  firstVar = extLIDVec.begin ();
430  lastVar = extLIDVec.end ();
431  }
432  // then do internal vars.
433  else
434  {
435  firstVar = intLIDVec.begin ();
436  lastVar = intLIDVec.end ();
437  }
438 
439  for (iterVar=firstVar; iterVar!=lastVar; ++iterVar)
440  {
441  row = *iterVar;
442 
443  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
444  Xyce::dout() << "matrix row = " << row << std::endl;
445  if (row < 0)
446  {
447  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
448  Xyce::dout() << "\tNOT loading this one - too small" << std::endl;
449  continue;
450  }
451 
452  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
453  Xyce::dout() << "\tloading this one" << std::endl;
454 
455  count = 1;
456  vals[0] = 1.0;
457  cols[0] = row;
458 
459  //matPtr->putLocalRow(row, count, &vals[0], &cols[0]);
460  matPtr->replaceLocalRow(row, count, &vals[0], &cols[0]);
461  }
462  }
463 
464  return true;
465 }
466 
467 //-----------------------------------------------------------------------------
468 // Function : DeviceInstance::loadTrivialDAE_FMatrixStamp
469 // Purpose : See loadTrivialMatrixStamp - this is the same thing, except
470 // for the new-DAE F-Matrix.
471 // Special Notes :
472 // Scope : public
473 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
474 // Creation Date : 05/25/05
475 //-----------------------------------------------------------------------------
477 {
479 }
480 
481 //-----------------------------------------------------------------------------
482 // Function : DeviceInstance::zeroMatrixDiagonal
483 // Purpose : puts zeros into on matrix diagonal, but just for this
484 // device.
485 // Special Notes :
486 // Scope : public
487 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
488 // Creation Date : 05/25/05
489 //-----------------------------------------------------------------------------
490 bool DeviceInstance::zeroMatrixDiagonal (N_LAS_Matrix * matPtr)
491 {
492  int count = 0;
493  int i;
494  int row;
495 
496  std::vector<int>::const_iterator firstVar;
497  std::vector<int>::const_iterator lastVar;
498  std::vector<int>::const_iterator iterVar;
499  int localRows = matPtr->getLocalNumRows();
500 
501  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
502  {
503  Xyce::dout() << std::endl
504  << "Zeroing the matrix diagonal for " << getName() << std::endl;
505  }
506 
507  if (cols.size() < 1) cols.resize(1);
508  if (vals.size() < 1) vals.resize(1);
509 
510  for (i=0;i<2;++i)
511  {
512  // do external vars first.
513  if (i==0)
514  {
515  firstVar = extLIDVec.begin ();
516  lastVar = extLIDVec.end ();
517  }
518  // then do internal vars.
519  else
520  {
521  firstVar = intLIDVec.begin ();
522  lastVar = intLIDVec.end ();
523  }
524 
525  for (iterVar=firstVar; iterVar!=lastVar; ++iterVar)
526  {
527  row = *iterVar;
528 
529  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
530  Xyce::dout() << "matrix row = " << row << std::endl;
531 
532  if (row < 0) continue;
533  if (row >= localRows) continue;
534 
535  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0)
536  Xyce::dout() << "\tloading this one" << std::endl;
537 
538  count = 1;
539  vals[0] = 0.0;
540  cols[0] = row;
541 
542  matPtr->putLocalRow(row, count, &vals[0], &cols[0]);
543  }
544  }
545 
546  return true;
547 }
548 
549 //-----------------------------------------------------------------------------
550 // Function : DeviceInstance::enablePDEContinuation
551 // Purpose :
552 // Special Notes :
553 // Scope : public
554 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
555 // Creation Date : 07/23/03
556 //-----------------------------------------------------------------------------
558 {
559  return true;
560 }
561 
562 //-----------------------------------------------------------------------------
563 // Function : DeviceInstance::disablePDEContinuation
564 // Purpose :
565 // Special Notes :
566 // Scope : public
567 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
568 // Creation Date : 07/23/03
569 //-----------------------------------------------------------------------------
571 {
572  return true;
573 }
574 
575 //-----------------------------------------------------------------------------
576 // Function : DeviceInstance::setPDEContinuationAlpha
577 // Purpose :
578 // Special Notes :
579 // Scope : public
580 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
581 // Creation Date : 07/23/03
582 //-----------------------------------------------------------------------------
584 {
585  return;
586 }
587 
588 //-----------------------------------------------------------------------------
589 // Function : DeviceInstance::setPDEContinuationBeta
590 // Purpose :
591 // Special Notes :
592 // Scope : public
593 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
594 // Creation Date : 02/28/04
595 //-----------------------------------------------------------------------------
597 {
598  return;
599 }
600 
601 //-----------------------------------------------------------------------------
602 // Function : DeviceInstance::setInitialGuess
603 // Purpose :
604 // Special Notes :
605 // Scope : public
606 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
607 // Creation Date : 07/23/03
608 //-----------------------------------------------------------------------------
610 {
611  return true;
612 }
613 
614 //-----------------------------------------------------------------------------
615 // Function : DeviceInstance::getMaxTimeStepSize
616 // Purpose :
617 // Special Notes :
618 // Scope : public
619 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
620 // Creation Date : 07/23/03
621 //-----------------------------------------------------------------------------
623 {
625 }
626 
627 
628 //-----------------------------------------------------------------------------
629 // Function : DeviceInstance::jacStampMap
630 // Purpose : Compute Jacobian Stamp and Map for devices that can have merged nodes
631 // Special Notes :
632 // Scope : public
633 // Creator : Dave Shirley, PSSI
634 // Creation Date : 2/13/04
635 //-----------------------------------------------------------------------------
637 (std::vector< std::vector<int> > & stamp_parent,
638  std::vector<int> & map_parent,
639  std::vector< std::vector<int> > & map2_parent,
640  std::vector< std::vector<int> > & stamp,
641  std::vector<int> & map,
642  std::vector< std::vector<int> > & map2,
643  int from, int to, int original_size)
644 {
645  int i, j, t_index, f_index, t_index2, f_index2, p_size, p_row, f_mod;
646  int map_2_from;
647  bool new_col;
648  std::vector< std::vector<int> > fill;
649  std::vector<int> dup;
650  std::vector< std::vector<int> > map2_tmp;
651 
652  if (from <= to)
653  {
654  std::string msg = "Internal Error 1 in DeviceInstance::jacStampMap. from <= to.";
655  //msg += " from index = " << from;
656  //msg += " to index = " << to;
657  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
658  }
659 
660  if (map_parent.size() == 0)
661  {
662  map_parent.resize(original_size);
663  map2_parent.resize(original_size);
664  for (i=0 ; i<original_size ; ++i)
665  {
666  map_parent[i] = i;
667  map2_parent[i].resize(stamp_parent[i].size());
668  for (j=0 ; j<stamp_parent[i].size() ; ++j)
669  {
670  map2_parent[i][j] = j;
671  }
672  }
673  }
674  map2.resize(original_size);
675 
676  // This is to merge the column that is being eliminated into the column it is merged.
677  // If extra elements are present then we must increment the map2 value for later
678  // elements. There are multiple cases depending what is populated.
679  for (i=0 ; i<original_size ; ++i)
680  {
681  f_index = -1;
682  t_index = -1;
683  p_row = map_parent[i];
684  for (j=0 ; j<stamp_parent[p_row].size() ; ++j)
685  {
686  if (stamp_parent[p_row][j] == from)
687  f_index = j;
688  if (stamp_parent[p_row][j] == to)
689  t_index = j;
690  }
691  map2[i].resize(map2_parent[i].size());
692  f_index2 = -1;
693  t_index2 = -1;
694  for (j=0 ; j<map2_parent[i].size() ; ++j)
695  {
696  map2[i][j] = map2_parent[i][j];
697  if (stamp_parent[p_row][map2[i][j]] == from)
698  f_index2 = j;
699  if (stamp_parent[p_row][map2[i][j]] == to)
700  t_index2 = j;
701  }
702  if (f_index >= 0)
703  {
704  if (t_index >= 0)
705  {
706  for (j=0 ; j<map2[i].size() ; ++j)
707  {
708  if (map2[i][j] > f_index)
709  map2[i][j]--;
710  }
711  if (f_index2 >= 0 && t_index2 >= 0)
712  map2[i][f_index2] = map2[i][t_index2];
713  }
714  else
715  {
716  for (j=0 ; j<map2[i].size() ; ++j)
717  {
718  if (stamp_parent[p_row][map2[i][j]] > to && stamp_parent[p_row][map2[i][j]] < from)
719  ++map2[i][j];
720  }
721  t_index = 0;
722  for (j=0 ; j<stamp_parent[p_row].size() ; ++j)
723  {
724  if (to > stamp_parent[p_row][j])
725  ++t_index;
726  else
727  break;
728  }
729  if (f_index2 >= 0)
730  map2[i][f_index2] = t_index;
731  }
732  }
733  }
734  map.resize(original_size);
735  p_size = stamp_parent.size();
736 
737  // This is to merge the row that is being eliminated into the row it is merged into
738  // if extra elements are present then we must increment the map2 value for later
739  // elements in the row
740  map2_tmp = map2;
741 
742  for (i=0 ; i<stamp_parent[from].size() && stamp_parent[from][i] < p_size-1 ; ++i)
743  {
744  new_col = false;
745  for (j=0 ; j<stamp_parent[to].size() ; ++j)
746  {
747  if (j == 0)
748  new_col = true;
749  if (stamp_parent[from][i] == stamp_parent[to][j])
750  {
751  new_col = false;
752  break;
753  }
754  }
755  if (new_col)
756  {
757  for (j=0 ; j<map2[to].size() ; ++j)
758  {
759  if (stamp_parent[to][map2_tmp[to][j]] > stamp_parent[from][i])
760  {
761  ++map2[to][j];
762  }
763  }
764  }
765  }
766 
767  stamp.resize(p_size-1);
768 
769  dup.resize(original_size);
770  f_mod = from;
771  for (i=1 ; i<original_size ; ++i)
772  {
773  dup[i] = -1;
774  for (j=0 ; j<i ; ++j)
775  {
776  if (map_parent[i] == map_parent[j])
777  {
778  dup[i] = j;
779  if (i<=f_mod)
780  ++f_mod;
781  break;
782  }
783  }
784  }
785 
786  for (i=0 ; i<f_mod ; ++i)
787  map[i] = map_parent[i];
788  map[f_mod] = map[to];
789  for (i=f_mod+1 ; i<original_size ; ++i)
790  map[i] = map_parent[i]-1;
791 
792  for (i=1 ; i<original_size ; ++i)
793  {
794  if (dup[i] >= 0)
795  map[i] = map[dup[i]];
796  }
797 
798 
799  // Now that we know where the row originally came from, we can do any renumbering
800  // needed in the map2 source row
801  map2_tmp = map2;
802  map_2_from = from;
803  if (map[from] != map[to]) {
804  for (i=from+1 ; i<original_size ; ++i) {
805  if (map[i] == map[to]) {
806  map_2_from = i;
807  break;
808  }
809  }
810  if (map_2_from == from) {
811  std::string msg = "Internal Error 2 in DeviceInstance::jacStampMap";
812  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
813  }
814  }
815 
816  for (i=0 ; i<stamp_parent[to].size() && stamp_parent[to][i] < p_size-1 ; ++i)
817  {
818  new_col = false;
819  for (j=0 ; j<stamp_parent[from].size() ; ++j)
820  {
821  if (j == 0)
822  new_col = true;
823  if (stamp_parent[to][i] == stamp_parent[from][j])
824  {
825  new_col = false;
826  break;
827  }
828  }
829  if (new_col)
830  {
831  for (j=0 ; j<map2[map_2_from].size() ; ++j)
832  {
833  if (stamp_parent[from][map2_tmp[map_2_from][j]] > stamp_parent[to][i])
834  {
835  ++map2[map_2_from][j];
836  }
837  }
838  }
839  }
840 
841  fill.resize(p_size);
842  for (i=0 ; i<p_size ; ++i)
843  {
844  fill[i].resize(p_size);
845  for (j=0 ; j<p_size ; ++j)
846  fill[i][j] = 0;
847  for (j=0 ; j<stamp_parent[i].size() ; ++j)
848  fill[i][stamp_parent[i][j]] = 1;
849  }
850  for (i=0 ; i<p_size ; ++i)
851  {
852  fill[to][i] += fill[from][i];
853  }
854  for (i=0 ; i<p_size ; ++i)
855  {
856  fill[i][to] += fill[i][from];
857  }
858  for (i=from ; i<p_size-1 ; ++i)
859  {
860  for (j=0 ; j<p_size ; ++j)
861  fill[i][j] = fill[i+1][j];
862  for (j=0 ; j<p_size ; ++j)
863  fill[j][i] = fill[j][i+1];
864  }
865  for (i=0 ; i<p_size-1 ; ++i)
866  {
867  stamp[i].clear();
868  for (j=0 ; j<p_size-1 ; ++j)
869  {
870  if (fill[i][j] > 0)
871  stamp[i].push_back(j);
872  }
873  }
874  return;
875 }
876 
877 //-----------------------------------------------------------------------------
878 // Function : DeviceInstance::jacStampMap_fixOrder
879 //
880 // Purpose : This function corrects the compressed row column array so
881 // that the column indices are in ascending order.
882 //
883 // Special Notes : The reason for this function is that the
884 // DeviceInstance::jacStampMap function
885 // implicitly requires an ordered jacStamp to work correctly.
886 // Some devices (particularly devices that have meshes),
887 // will start out with an non-ordered stamp, at least in the
888 // column entries.
889 //
890 // Note, this does require the "map" argument, because,
891 // unlike the function DeviceInstnace::jacStamMap,
892 // because this function doesn't change the row ordering,
893 // or remove or merge any rows.
894 //
895 // This function only changes the column ordering in the
896 // compressed row form of the jacStamp. It thus requires
897 // modifications to map2, which is essentially a column map.
898 //
899 // Scope : public
900 // Creator : Eric R. Keiter, SNL
901 // Creation Date : 2/01/08
902 //-----------------------------------------------------------------------------
904 (std::vector< std::vector<int> > & stamp_parent,
905  std::vector< std::vector<int> > & map2_parent,
906  std::vector< std::vector<int> > & stamp,
907  std::vector< std::vector<int> > & map2)
908 {
909  int i, j;
910  int current_size = stamp_parent.size();
911 
912  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 1 && getSolverState().debugTimeFlag)
913  {
914  Xyce::dout() << Xyce::section_divider << std::endl
915  << "Begin DeviceInstance::jacStampMap_fixOrder." << std::endl
916  << Xyce::section_divider << std::endl;
917  }
918 
919  // if this is the first time this function is called (for a particular device), then
920  // allocate the map and set up their trivial contents.
921  if (map2_parent.size() == 0)
922  {
923  map2_parent.resize(current_size);
924  for (i=0 ; i<current_size ; ++i)
925  {
926  map2_parent[i].resize(stamp_parent[i].size());
927  for (j=0 ; j<stamp_parent[i].size() ; ++j)
928  {
929  map2_parent[i][j] = j;
930  }
931  }
932  }
933 
934  stamp.clear();
935  map2.clear();
936 
937  // To make this simple, start out with a full, dense stamp.
938  std::vector< std::vector<int> > denseStamp(current_size);
939  for (i=0;i<current_size;++i)
940  {
941  denseStamp[i].resize(current_size,-1);
942 
943  for (j=0;j<stamp_parent[i].size();++j)
944  {
945  int denseCol = stamp_parent[i][j];
946  denseStamp[i][denseCol] = j;
947  }
948  }
949 
950  // At this point, the denseStamp has been set up. Now use it to re-create the
951  // compressed-row stamp. By simply looping over the dense stamp, the column order
952  // in the compressed row stamp will automatically be ascending.
953  // map2 is set up here as well, by pulling the values out that we previously put into
954  // dense stamp.
955  stamp.resize(current_size);
956  map2.resize(current_size);
957  for (i=0;i<current_size;++i)
958  {
959  for (j=0;j<current_size;++j)
960  {
961  int colMapIndex = denseStamp[i][j];
962  if (colMapIndex!=-1)
963  {
964  stamp[i].push_back(j);
965  }
966  }
967 
968  int stampRowLength=stamp[i].size();
969  map2[i].resize(stampRowLength, 0);
970 
971  int k=0;
972  for (j=0;j<current_size;++j)
973  {
974  int colMapIndex = denseStamp[i][j];
975  if (colMapIndex!=-1 && colMapIndex < stampRowLength)
976  {
977  map2[i][colMapIndex] = k;
978  ++k;
979  }
980  }
981  }
982 
983  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 1 && getSolverState().debugTimeFlag)
984  {
985  Xyce::dout() << "From inside of DeviceInstance::jacStampMap_fixOrder:" << std::endl
986  << "The original parent stamp is:" << std::endl;
987  outputJacStamp(stamp_parent);
988  Xyce::dout() << "The new reduced stamp is:" << std::endl;
989  outputJacStamp(stamp);
990  Xyce::dout() << "The dense stamp is:" << std::endl;
991  outputJacStamp(denseStamp);
992 
993  Xyce::dout() << "The new map is:" << std::endl;
994  outputJacStamp(map2);
995 
996  Xyce::dout() << Xyce::section_divider << std::endl
997  << "End DeviceInstance::jacStampMap_fixOrder."<<std::endl
998  << Xyce::section_divider << std::endl;
999  }
1000 
1001  return;
1002 }
1003 //-----------------------------------------------------------------------------
1004 // Function : DeviceInstance::outputJacStamp
1005 // Purpose : Output jacStamp (for debugging)
1006 // Special Notes :
1007 // Scope : public
1008 // Creator : Dave Shirley, PSSI
1009 // Creation Date : 01/19/06
1010 //-----------------------------------------------------------------------------
1011 void DeviceInstance::outputJacStamp(const std::vector<std::vector<int> > & jac)
1012 {
1013  int i,j;
1014  for (i=0 ; i<jac.size() ; ++i)
1015  {
1016  Xyce::dout() << "Row: " << i << " ::";
1017  for (j=0 ; j<jac[i].size() ; ++j)
1018  Xyce::dout() << " " << jac[i][j];
1019  Xyce::dout() << std::endl;
1020  }
1021  Xyce::dout() << std::endl;
1022 }
1023 
1024 //-----------------------------------------------------------------------------
1025 // Function : DeviceInstance::outputJacMaps
1026 // Purpose : Output jacMap and jacMap2 (for debugging)
1027 // Special Notes :
1028 // Scope : public
1029 // Creator : Keith Santarelli, Electrical & Microsystems Modeling
1030 // Creation Date : 02/20/08
1031 //-----------------------------------------------------------------------------
1032 void DeviceInstance::outputJacMaps(const std::vector<int> & jacMap,
1033  const std::vector<std::vector<int> > & jacMap2)
1034 {
1035  int i,j;
1036 
1037  for (i=0 ; i<jacMap.size() ; ++i)
1038  {
1039  Xyce::dout() << "Row " << i << ": ";
1040  for (j=0; j < jacMap2[i].size(); j++)
1041  {
1042  Xyce::dout() << jacMap[i]<< "," << jacMap2[i][j] << " ";
1043  }
1044  Xyce::dout() << std::endl;
1045  }
1046 
1047  Xyce::dout() << std::endl;
1048 }
1049 
1050 //-----------------------------------------------------------------------------
1051 // Function : DeviceInstance::registerGIDData
1052 // Purpose : Insert GID data into 'indexPairList' object
1053 //
1054 // Special Notes : This information is neccessary for the numerical Jacobian.
1055 // It is only called once.
1056 //
1057 // The numerical jacobian may get confused by duplicate
1058 // matrix entries, in that it might load them 2x. For that
1059 // reason, this function checks for duplicates.
1060 //
1061 // Scope : public
1062 // Creator : Rob Hoekstra
1063 // Creation Date : 12/13/04
1064 //-----------------------------------------------------------------------------
1066  const std::vector<int> & counts,
1067  const std::vector<int> & GIDs,
1068  const std::vector< std::vector<int> > & jacGIDs )
1069 {
1070 
1071  // the test for the PDE system flag only needs to be here until the
1072  // "diagonal" matrix load is fixed.
1073  //if (getDeviceOptions().numericalJacobianFlag || getSolverState().PDESystemFlag)
1074  if (getDeviceOptions().numericalJacobianFlag)
1075  {
1076  indexPairList.clear();
1077 
1078  int extSize = counts[0];
1079  int intSize = counts[1];
1080  int expSize = counts[2];
1081  int size = GIDs.size();
1082  int i;
1083 
1084  std::map<int,int> testIndexMap;
1085 
1086  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1087  {
1088  Xyce::dout() << "DeviceInstance::registerGIDData for " << getName() << std::endl
1089  << " extSize = " << extSize << std::endl
1090  << " intSize = " << intSize << std::endl
1091  << " expSize = " << expSize << std::endl
1092  << " GIDs.size = " << size << std::endl
1093  << " jacGIDs.size = " << jacGIDs.size () << std::endl
1094  << std::endl;
1095  }
1096 
1097  // Copy out external gids:
1098  extGIDList.clear ();
1099  for (i = 0; i < extSize; ++i )
1100  {
1101  if ( testIndexMap.find(GIDs[i]) == testIndexMap.end() )
1102  {
1103  extGIDList.push_back( index_pair( GIDs[i], 1 ) );
1104  testIndexMap[GIDs[i]] = 1;
1105  }
1106  }
1107 
1108  testIndexMap.clear ();
1109 
1110  // Copy out internal gids:
1111  intGIDList.clear ();
1112  for (; i<intSize+extSize;++i)
1113  {
1114  if ( testIndexMap.find(GIDs[i]) == testIndexMap.end() )
1115  {
1116  intGIDList.push_back( index_pair( GIDs[i], 1 ) );
1117  testIndexMap[GIDs[i]] = 1;
1118  }
1119  }
1120 
1121  testIndexMap.clear ();
1122 
1123  // Copy out the exp var gid's, if they exist. These will
1124  // only exist in devices which depend on expressions, like the Bsrc.
1125  expVarGIDs.clear ();
1126  for (; i<intSize+extSize+expSize;++i)
1127  {
1128  if ( testIndexMap.find(GIDs[i]) == testIndexMap.end() )
1129  {
1130  expVarGIDs.push_back( GIDs[i] );
1131  testIndexMap[GIDs[i]] = 1;
1132  }
1133  }
1134 
1135  // Now copy the exp var GIDs into the extVarGID's.
1136  // add the contents of expVarGIDs to the extGIDListRef.
1137  // This is done because the numerical jacobian treats expression
1138  // GIDs the same as external (nodal) GIDs.
1139  int expS = expVarGIDs.size();
1140  for (int itmp = 0; itmp < expS; ++itmp)
1141  {
1142  extGIDList.push_back( index_pair( expVarGIDs[itmp], 1 ) );
1143  }
1144 
1145  testIndexMap.clear ();
1146 
1147  // do the index pairs for the jacobian matrix
1148  indexPairList.clear ();
1149  for(i = 0; i < jacGIDs.size () ; ++i )
1150  {
1151 
1152  if ( testIndexMap.find(GIDs[i]) == testIndexMap.end() )
1153  {
1154  testIndexMap[GIDs[i]] = 1;
1155 
1156  std::map<int,int> testJMap;
1157  testJMap.clear ();
1158  int length = jacGIDs[i].size();
1159  for( int j = 0; j < length; ++j )
1160  {
1161  if ( testJMap.find(jacGIDs[i][j]) == testJMap.end () )
1162  {
1163  indexPairList.push_back( index_pair( GIDs[i], jacGIDs[i][j] ) );
1164  testJMap[jacGIDs[i][j]] = 1;
1165  }
1166  }
1167  }
1168  }
1169 
1170  if (DEBUG_DEVICE && getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1171  {
1172  std::vector<int>::const_iterator begin = GIDs.begin ();
1173  std::vector<int>::const_iterator end = GIDs.end ();
1174  std::vector<int>::const_iterator iterGID;
1175 
1176  Xyce::dout() << " Complete GIDs :" << std::endl;
1177  for (iterGID=begin;iterGID!=end ;++iterGID)
1178  {
1179  Xyce::dout() << "\tgid=" << *iterGID << std::endl;
1180  }
1181  Xyce::dout() << std::endl;
1182 
1183  std::list<index_pair>::iterator first;
1184  std::list<index_pair>::iterator last;
1185  std::list<index_pair>::iterator iter;
1186 
1187  Xyce::dout() << " intGIDList :" << std::endl;
1188  first = intGIDList.begin ();
1189  last = intGIDList.end ();
1190  for (iter=first;iter!=last;++iter)
1191  {
1192  Xyce::dout() << "\tgid=" << iter->row << std::endl;
1193  }
1194  Xyce::dout() << std::endl;
1195 
1196  Xyce::dout() << " extGIDList :" << std::endl;
1197  first = extGIDList.begin ();
1198  last = extGIDList.end ();
1199  for (iter=first;iter!=last;++iter)
1200  {
1201  Xyce::dout() << "\tgid=" << iter->row << std::endl;
1202  }
1203  Xyce::dout() << std::endl;
1204 
1205 
1206  Xyce::dout() << " indexPairList :" << std::endl;
1207  first = indexPairList.begin();
1208  last = indexPairList.end ();
1209  for (iter=first;iter!=last;++iter)
1210  {
1211  Xyce::dout() << " row=" << iter->row << " col=" << iter->col << std::endl;
1212  }
1213  Xyce::dout() << std::endl << std::endl;
1214  }
1215  }
1216 }
1217 
1218 //-----------------------------------------------------------------------------
1219 // Function : DeviceInstance::updateTemperature
1220 // Purpose :
1221 // Special Notes :
1222 // Scope : public
1223 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1224 // Creation Date : 11/30/00
1225 //-----------------------------------------------------------------------------
1226 bool DeviceInstance::updateTemperature(const double & temp_tmp)
1227 {
1228  return true;
1229 }
1230 
1231 //-----------------------------------------------------------------------------
1232 // Function : DeviceInstance::processParams
1233 // Purpose :
1234 // Special Notes :
1235 // Scope : public
1236 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1237 // Creation Date : 06/03/02
1238 //-----------------------------------------------------------------------------
1240 {
1241  Report::DevelFatal0().in("DeviceInstance::processParams")
1242  << "DeviceInstance::processParams() must be implemented for device " << getName();
1243 
1244  return true;
1245 }
1246 
1247 // //-----------------------------------------------------------------------------
1248 // // Function : DeviceInstance::updateIntermediateVars
1249 // // Purpose :
1250 // // Special Notes :
1251 // // Scope : public
1252 // // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1253 // // Creation Date : 11/30/00
1254 // //-----------------------------------------------------------------------------
1255 // bool DeviceInstance::updateIntermediateVars ()
1256 // {
1257 // std::string msg;
1258 // msg = "DeviceInstance::updateIntermediateVars does not exist";
1259 // msg += " for this device: " + getName() + "\n";
1260 // N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
1261 
1262 // return true;
1263 // }
1264 
1265 
1266 // //-----------------------------------------------------------------------------
1267 // // Function : DeviceInstance::updatePrimaryState
1268 // // Purpose :
1269 // // Special Notes :
1270 // // Scope : public
1271 // // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1272 // // Creation Date : 11/30/00
1273 // //-----------------------------------------------------------------------------
1274 // bool DeviceInstance::updatePrimaryState ()
1275 // {
1276 // std::string msg;
1277 // msg = "DeviceInstance::updatePrimaryState does not exist";
1278 // msg += " for this device: " + getName() + "\n";
1279 // N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
1280 
1281 // return true;
1282 // }
1283 
1284 //-----------------------------------------------------------------------------
1285 // Function : DeviceInstance::setInternalState
1286 // Purpose :
1287 // Special Notes :
1288 // Scope : public
1289 // Creator : Robert J Hoekstra, SNL, Parallel Computational Sciences
1290 // Creation Date : 09/02/01
1291 //-----------------------------------------------------------------------------
1293  const DeviceState & state )
1294 {
1295  Report::DevelFatal().in("DeviceInstance::setInternalState") << "does not exist for this device " << getName();
1296 
1297  return false;
1298 }
1299 
1300 std::ostream &
1301 DeviceInstance::printName(std::ostream &os) const
1302 {
1303  return os << "instance " << name_.getEncodedName();
1304 }
1305 
1306 } // namespace Device
1307 } // namespace Xyce