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