Xyce  6.1
N_DEV_ROM.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_ROM.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 12/11/09
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.78 $
40 //
41 // Revision Date : $Date: 2015/04/24 20:25:45 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 // ---------- Standard Includes ----------
49 #include <algorithm>
50 #include <N_UTL_Math.h>
51 
52 // ---------- Xyce Includes ----------
53 #include <N_DEV_Const.h>
54 #include <N_DEV_DeviceOptions.h>
55 #include <N_DEV_DeviceMaster.h>
56 #include <N_DEV_ExternData.h>
57 #include <N_DEV_MatrixLoadData.h>
58 #include <N_DEV_ROM.h>
59 #include <N_DEV_SolverState.h>
60 #include <N_DEV_Message.h>
61 #include <N_ERH_ErrorMgr.h>
62 
63 #include <N_LAS_Vector.h>
64 #include <N_LAS_Matrix.h>
65 #include <N_LAS_Util.h>
66 
67 #include <N_UTL_Expression.h>
68 #include <N_UTL_FeatureTest.h>
69 #include <N_IO_mmio.h>
70 
71 #include <Teuchos_BLAS.hpp>
72 #include <Teuchos_Utils.hpp>
73 #include <Teuchos_LAPACK.hpp>
74 
75 // Keep redundant (assuming Trilinos and Xyce are configured in the same environment) definitions from whining
76 #undef HAVE_CMATH
77 #undef HAVE_CSTDIO
78 #undef HAVE_CSTDLIB
79 #undef HAVE_INTTYPES_H
80 #undef HAVE_IOSTREAM
81 #undef HAVE_STDINT_H
82 #include <Trilinos_Util.h>
83 
84 namespace Xyce {
85 namespace Device {
86 
87 
88 namespace ROM {
89 
90 
92 {
93 p.addPar("BASE_FILENAME", std::string("rom_input"), &ROM::Instance::baseFileName);
94  p.addPar("MASK_VARS", false, &ROM::Instance::maskROMVars);
95  p.addPar("USE_PORT_DESCRIPTION", 0, &ROM::Instance::usePortDesc);
96 }
97 
99 {}
100 
101 
102 // Class Instance
103 //-----------------------------------------------------------------------------
104 // Function : Instance::processParams
105 // Purpose :
106 // Special Notes :
107 // Scope : public
108 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
109 // Creation Date : 12/11/09
110 //-----------------------------------------------------------------------------
112 {
113  return true;
114 }
115 
116 //-----------------------------------------------------------------------------
117 // Function : Instance::updateTemperature
118 // Purpose :
119 // Special Notes :
120 // Scope : public
121 // Creator : Tom Russo, Component Information and Models
122 // Creation Date : 12/11/09
123 //-----------------------------------------------------------------------------
124 bool Instance::updateTemperature ( const double & temp_tmp)
125 {
126  return true;
127 }
128 
129 //-----------------------------------------------------------------------------
130 // Function : Instance::Instance
131 // Purpose : instance block constructor
132 // Special Notes :
133 // Scope : public
134 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
135 // Creation Date : 12/11/09
136 //-----------------------------------------------------------------------------
138  const Configuration & configuration,
139  const InstanceBlock & IB,
140  Model & ROMiter,
141  const FactoryBlock & factory_block)
142  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
143  model_(ROMiter),
144  isCSparse(false),
145  isGSparse(false),
146  maskROMVars(false),
147  numROMVars(0),
148  baseFileName(""),
149  dt(0),
150  dt_last(0),
151  alph(0),
152  alph_last(0),
153  coef(0),
154  coefLast(0),
155  currentOrder(0),
156  usedOrder(0),
157  lastTimeStepNumber(0)
158 {
159  numExtVars = IB.numExtVars; // we have as many as were specified on the
160  // instance line
161 
162  // Set params to constant default values:
163  setDefaultParams ();
164 
165  // Set params according to instance line and constant defaults from metadata:
166  setParams (IB.params);
167 
168  // Read in reduced-order model.
169  if (given("BASE_FILENAME"))
170  {
171  FILE *c_file, *g_file, *b_file, *l_file;
172  Xyce::IO::MMIO::MM_typecode mat_code;
173  int M=0, N=0, nz=0;
174  std::string cfile = Instance::baseFileName + ".Chat";
175  std::string gfile = Instance::baseFileName + ".Ghat";
176  std::string bfile = Instance::baseFileName + ".Bhat";
177  std::string lfile = Instance::baseFileName + ".Lhat";
178  c_file = fopen(cfile.c_str(), "r");
179  g_file = fopen(gfile.c_str(), "r");
180  b_file = fopen(bfile.c_str(), "r");
181  l_file = fopen(lfile.c_str(), "r");
182  if (c_file == NULL || g_file == NULL || b_file == NULL || l_file == NULL)
183  {
184  UserFatal0(*this) << "Cannot open one of the ROM files: " << cfile << "," << gfile << "," << bfile << "," << lfile;
185  }
186 
187  // Get the input-output numbers from the projected B matrix
188  Xyce::IO::MMIO::mm_read_banner( b_file, &mat_code );
189  Xyce::IO::MMIO::mm_read_mtx_array_size( b_file, &M, &N );
190 
191  // Set number of internal variables to dimension of reduced-order model
193  {
194  numIntVars= 0;
195  numROMVars = 0;
196  numStateVars = M+N;
197  }
198  else
199  {
200  numIntVars = M+N; // Number of ROM variables + current variables for ports
201  numROMVars = M;
202  numStateVars = 0;
203  }
204 
205  numExtVars = N;
206 
207  // Read in B and L matrices.
208  // NOTE: B and L are assumed to be dense arrays at this time, so read them in.
209  Bhat.resize( M*N );
210  Lhat.resize( M*N );
211 
212  // NOTE: The banners and array sizes need to be read in
213  // before the rest of the file can be read.
214  int tmpM=0, tmpN=0;
215  Xyce::IO::MMIO::mm_read_banner( l_file, &mat_code ); // Already read b_file banner
216  Xyce::IO::MMIO::mm_read_mtx_array_size( l_file, &tmpM, &tmpN ); // Already read b_file array size
217 
218  // Read in Bhat and Lhat multivectors
219  for (int i=0; i<M*N; i++)
220  {
221  fscanf(b_file, "%lg\n", &Bhat[i]);
222  fscanf(l_file, "%lg\n", &Lhat[i]);
223  }
224 
225  // Read in C matrix.
226  // NOTE: This matrix may have been sparsified or stored in a symmetric format
227  Xyce::IO::MMIO::mm_read_banner( c_file, &mat_code );
228  isCSparse = mm_is_sparse(mat_code);
229 
230  // If the input matrix C is dense, read in the dense data
231  if (!isCSparse)
232  {
233  // Read in array size.
234  Xyce::IO::MMIO::mm_read_mtx_array_size( c_file, &tmpM, &tmpN );
235  // TODO: Add check of tmpM and tmpN
236 
237  Chat.resize( M*M );
238  if (mm_is_general(mat_code))
239  {
240  // Read in Chat matrix, stored column-wise
241  for (int i=0; i<M*M; i++)
242  {
243  fscanf(c_file, "%lg\n", &Chat[i]);
244  }
245  }
246  else if (mm_is_symmetric(mat_code) || mm_is_skew(mat_code))
247  {
248  int arraySize = M*(M+1)/2; // Only one triangle is stored
249  std::vector<double> Chat_tmp( arraySize ); // Only one triangle is stored
250  // Read in Chat matrix, stored column-wise
251  for (int i=0; i<arraySize; i++)
252  {
253  fscanf(c_file, "%lg\n", &Chat_tmp[i]);
254  }
255  // Copy Chat matrix into full dense matrix
256  for (int j=0; j<M; j++)
257  {
258  for (int i=j; i<M; i++)
259  {
260  double val = Chat_tmp[j*M - j*(j-1)/2 + i - j];
261  Chat[j*M+i] = val;
262  if (i!=j)
263  {
264  if (mm_is_symmetric(mat_code))
265  Chat[i*M+j] = val; // Symmetric
266  else
267  Chat[i*M+j] = -val; // Skew-symmetric
268  }
269  }
270  }
271  }
272  else
273  {
274  UserFatal0(*this) << "Do not recognize the Matrix Market format for Chat (matrix is not general or symmetric)";
275  }
276  }
277  else
278  {
279  int nnz=0;
280  Xyce::IO::MMIO::mm_read_mtx_crd_size( c_file, &tmpM, &tmpN, &nnz );
281  if (nnz==0)
282  {
283  UserFatal0(*this) << "Chat has zero entries according to the Matrix Market file " << cfile;
284  }
285 
286  // Temporary storage for Chat, to read in coordinate format
287  std::vector<double> Chat_tmp( nnz );
288  std::vector<int> rowIdx( nnz ), colIdx( nnz );
289 
290  if (nnz > 0)
291  Xyce::IO::MMIO::mm_read_mtx_crd_data( c_file, tmpM, tmpN, nnz, &rowIdx[0], &colIdx[0], &Chat_tmp[0], mat_code );
292 
293  // Reduce the row and column indices to 0-based indexing and add entries if the matrix is (skew) symmetric.
294  for (int i=0; i<nnz; ++i)
295  {
296  rowIdx[i]--;
297  colIdx[i]--;
298 
299  // If matrices are symmetric or skew symmetric, add entries to the coordinate storage format.
300  if (mm_is_symmetric(mat_code) || mm_is_skew(mat_code))
301  {
302  if (rowIdx[i]!=colIdx[i])
303  {
304  if (mm_is_symmetric(mat_code))
305  {
306  rowIdx.push_back(colIdx[i]);
307  colIdx.push_back(rowIdx[i]);
308  Chat_tmp.push_back(Chat_tmp[i]); // Symmetric
309  }
310  else
311  {
312  rowIdx.push_back(colIdx[i]);
313  colIdx.push_back(rowIdx[i]);
314  Chat_tmp.push_back(-Chat_tmp[i]); // Skew-symmetric
315  }
316  }
317  }
318  }
319 
320  // Use nnz2, the number of nonzeros for the symmetrized matrix, to compute the new CSR format.
321  int nnz2 = rowIdx.size();
322 
323  // Allocate storage for Chat in CSR format
324  Chat.resize( nnz2 );
325  Chat_rowPtr.resize( tmpM+1 );
326  Chat_colIdx.resize( nnz2 );
327 
328  // Convert coordinate (Matrix Market) storage to CSR format
329  if (nnz2 > 0)
330  Trilinos_Util_coocsr( tmpM, nnz2, &Chat_tmp[0], &rowIdx[0], &colIdx[0], &Chat[0], &Chat_colIdx[0], &Chat_rowPtr[0] );
331  }
332 
333  // Read in G matrix.
334  // NOTE: This matrix may have been sparsified or stored in a symmetric format
335  Xyce::IO::MMIO::mm_read_banner( g_file, &mat_code );
336  isGSparse = mm_is_sparse(mat_code);
337 
338  // If the input matrix G is dense, read in the dense data
339  if (!isGSparse)
340  {
341  // Read in array size.
342  Xyce::IO::MMIO::mm_read_mtx_array_size( g_file, &tmpM, &tmpN );
343  // TODO: Add check of tmpM and tmpN
344 
345  Ghat.resize( M*M );
346  if (mm_is_general(mat_code))
347  {
348  // Read in Ghat matrix, stored column-wise
349  for (int i=0; i<M*M; i++)
350  {
351  fscanf(g_file, "%lg\n", &Ghat[i]);
352  }
353  }
354  else if (mm_is_symmetric(mat_code) || mm_is_skew(mat_code))
355  {
356  int arraySize = M*(M+1)/2;
357  std::vector<double> Ghat_tmp( arraySize ); // Only one triangle is stored
358  // Read in Ghat matrix, stored column-wise
359  for (int i=0; i<arraySize; i++)
360  {
361  fscanf(g_file, "%lg\n", &Ghat_tmp[i]);
362  }
363  // Copy Ghat matrix into full dense matrix
364  for (int j=0; j<M; j++)
365  {
366  for (int i=j; i<M; i++)
367  {
368  double val = Ghat_tmp[j*M - j*(j-1)/2 + i - j];
369  Ghat[j*M+i] = val;
370  if (i!=j)
371  {
372  if (mm_is_symmetric(mat_code))
373  Ghat[i*M+j] = val; // Symmetric
374  else
375  Ghat[i*M+j] = -val; // Skew-symmetric
376  }
377  }
378  }
379  }
380  else
381  {
382  UserFatal0(*this) << "Do not recognize the Matrix Market format for Ghat (matrix is not general or symmetric)";
383  }
384  }
385  else
386  {
387  int nnz=0;
388  Xyce::IO::MMIO::mm_read_mtx_crd_size( g_file, &tmpM, &tmpN, &nnz );
389  if (nnz==0)
390  {
391  UserFatal0(*this) << "Ghat has zero entries according to the Matrix Market file " << gfile;
392  }
393 
394  // Temporary storage for Ghat, to read in coordinate format
395  std::vector<double> Ghat_tmp( nnz );
396  std::vector<int> rowIdx( nnz ), colIdx( nnz );
397 
398  if (nnz > 0)
399  Xyce::IO::MMIO::mm_read_mtx_crd_data( g_file, tmpM, tmpN, nnz, &rowIdx[0], &colIdx[0], &Ghat_tmp[0], mat_code );
400 
401  // Reduce the row and column indices to 0-based indexing
402  for (int i=0; i<nnz; ++i)
403  {
404  rowIdx[i]--;
405  colIdx[i]--;
406 
407  // If matrices are symmetric or skew symmetric, add entries to the coordinate storage format.
408  if (mm_is_symmetric(mat_code) || mm_is_skew(mat_code))
409  {
410  if (rowIdx[i]!=colIdx[i])
411  {
412  if (mm_is_symmetric(mat_code))
413  {
414  rowIdx.push_back(colIdx[i]);
415  colIdx.push_back(rowIdx[i]);
416  Ghat_tmp.push_back(Ghat_tmp[i]); // Symmetric
417  }
418  else
419  {
420  rowIdx.push_back(colIdx[i]);
421  colIdx.push_back(rowIdx[i]);
422  Ghat_tmp.push_back(-Ghat_tmp[i]); // Skew-symmetric
423  }
424  }
425  }
426  }
427 
428  // Use nnz2, the number of nonzeros for the symmetrized matrix, to compute the new CSR format.
429  int nnz2 = rowIdx.size();
430 
431  // Allocate storage for Ghat in CSR format
432  Ghat.resize( nnz2 );
433  Ghat_rowPtr.resize( tmpM+1 );
434  Ghat_colIdx.resize( nnz2 );
435 
436  // Convert coordinate (Matrix Market) storage to CSR format
437  if (nnz2 > 0)
438  Trilinos_Util_coocsr( tmpM, nnz2, &Ghat_tmp[0], &rowIdx[0], &colIdx[0], &Ghat[0], &Ghat_colIdx[0], &Ghat_rowPtr[0] );
439  }
440 
441  // Create a union map for Chat and Ghat if both are sparse, otherwise the union is a dense block.
442  if (isCSparse && isGSparse)
443  {
444  CG_rowPtr.resize( M+1 );
445  CG_colIdx.resize( Chat_colIdx.size() + Ghat_colIdx.size() ); // Maximum number of nonzeros in the union
446 
447  std::vector<int>::iterator it;
448  std::vector<int>::iterator itCG = CG_colIdx.begin();
449  std::vector<int>::iterator itChat = Chat_colIdx.begin();
450  std::vector<int>::iterator itGhat = Ghat_colIdx.begin();
451  CG_rowPtr[0] = 0;
452  for (int i=0; i<M; ++i)
453  {
454  // Get the number of nonzero entries for this row
455  int numEntriesChat = Chat_rowPtr[i+1] - Chat_rowPtr[i];
456  int numEntriesGhat = Ghat_rowPtr[i+1] - Ghat_rowPtr[i];
457  // Compute the union of the entries
458  it = set_union( itChat, itChat + numEntriesChat, itGhat, itGhat + numEntriesGhat, itCG );
459  CG_rowPtr[i+1] = CG_rowPtr[i] + (int)(it - itCG);
460  // Check if we need to sort the entries HERE!!!!
461 
462  // Increment the iterators
463  itCG = it;
464  itChat += numEntriesChat;
465  itGhat += numEntriesGhat;
466  }
467  }
468 
469  // Allocate memory for projected matrices
470  Qhat.resize( M );
471  Fhat.resize( M+N );
472  i_ip.resize( N );
473 
475  {
476  Jstamp.resize(N*N);
477  Fstamp.resize(N);
478  G2.resize((M+N)*(M+N));
479  C2.resize((M+N)*(M+N));
480  A2.resize((M+N)*(M+N));
481  A2last.resize((M+N)*(M+N));
482  G2p.resize((M+N)*N);
483  Gp2.resize((M+N)*N);
484  A2sol.resize((M+N)*N);
485 
486  ipiv_A2.resize(M+N);
487  }
488 
489  fclose(c_file);
490  fclose(g_file);
491  fclose(b_file);
492  fclose(l_file);
493 
495  {
496  if (!isGSparse)
497  {
498  // Construct constant matrices for two-level stamp
499  // G2 = [eye(N),-Lhat'; zeros(M,N), Ghat];
500  for(int iy=0; iy<M; iy++) // add Ghat term
501  {
502  for(int ix=0; ix<M; ix++)
503  G2[((N+M+1)*N)+ix+(M+N)*iy] = Ghat[ix+iy*M];
504  }
505  }
506  else
507  {
508  for (int ix=0; ix<M; ix++)
509  {
510  for (int j=Ghat_rowPtr[ix]; j<Ghat_rowPtr[ix+1]; ++j)
511  G2[((N+M+1)*N)+ix+(M+N)*Ghat_colIdx[j]] = Ghat[j];
512  }
513  }
514 
515  for(int ix=0; ix<N; ix++) // add eye(N) term
516  G2[ix+(M+N)*ix] = 1;
517  for(int ix=0; ix<M; ix++) // add Lhat' term
518  {
519  for(int iy=0; iy<N; iy++)
520  G2[((M+N)*N)+iy+(M+N)*ix] = -Lhat[ix+iy*M]; // L is transposed
521  }
522  // C2 = [zeros(N),zeros(N,M); zeros(M,N), Chat];
523  if (!isCSparse)
524  {
525  for(int iy=0; iy<M; iy++) // add Chat term
526  {
527  for(int ix=0; ix<M; ix++)
528  C2[((N+M+1)*N)+ix+(M+N)*iy] = Chat[ix+iy*M];
529  }
530  }
531  else
532  {
533  for (int ix=0; ix<M; ix++)
534  {
535  for (int j=Chat_rowPtr[ix]; j<Chat_rowPtr[ix+1]; ++j)
536  C2[((N+M+1)*N)+ix+(M+N)*Chat_colIdx[j]] = Chat[j];
537  }
538  }
539 
540  // G2p = -[zeros(N); Bhat];
541  for(int iy=0; iy<N; iy++) // add Bhat term
542  {
543  for(int ix=0; ix<M; ix++)
544  G2p[N+ix+(M+N)*iy] = -Bhat[ix+iy*M];
545  }
546 
547  // Gp2 = [eye(N), zeros(M,N)];
548  for(int iy=0; iy<N; iy++) // add eye(N) term
549  {
550  Gp2[iy+(N)*iy] = 1;
551  }
552 
553  // Construct jacStamp
554  if( jacStamp.empty() )
555  {
556  jacStamp.resize(numExtVars);
557 
558  // Put in external variables (node voltages)
559  for (int i=0; i<numExtVars; i++)
560  {
561  jacStamp[i].resize(numExtVars);
562  for(int j=0; j<numExtVars; j++)
563  jacStamp[i][j] = j;
564  }
565  }
566  }
567  else
568  {
569  // Create Jacobian stamp for direct stamping of ROM into full system
570  //
571  // [ Stamps for 0 0 ] [ x_NL ] [ v_NL ]
572  // [ f(x_NL,u_p) I_N 0 ] [ u_p ] = [ v_p ] (a)
573  // [ 0 0 I_N -Lhat^T ] [ i_p ] [ 0 ] (b)
574  // [ 0 -Bhat 0 (Ghat + Chat d/dt) ] [xhat_q] [ 0 ] (c)
575  //
576  if( jacStamp.empty() )
577  {
578  // Resize Jacobian stamp to size of reduced system + 2 x #ports
580 
581  // Equations (a): Put in external variables (port voltages)
582  for (int i=0; i<numExtVars; i++)
583  {
584  jacStamp[i].resize(1);
585  jacStamp[i][0] = numExtVars+i;
586  }
587 
588  // Equations (b): Put in internal variables (size of reduced model + port currents)
589  for (int i=numExtVars; i<2*numExtVars; i++)
590  {
591  jacStamp[i].resize(numROMVars+1);
592  jacStamp[i][0] = i;
593  for (int j=0; j<numROMVars; j++)
594  jacStamp[i][j+1] = 2*numExtVars+j;
595  }
596 
597  // Equations (c): Put in projected system
598  for (int i=2*numExtVars; i<numIntVars+numExtVars; i++)
599  {
600  int numEntries = numIntVars;
601  if (isCSparse && isGSparse)
602  numEntries = numExtVars+(CG_rowPtr[i-2*numExtVars+1]-CG_rowPtr[i-2*numExtVars]);
603  jacStamp[i].resize( numEntries );
604 
605  for (int j=0; j<numExtVars; j++)
606  jacStamp[i][j] = j;
607 
608  // Insert entries for (Ghat + Chat d/dt)
609  if (isCSparse && isGSparse)
610  {
611  for (int j=numExtVars; j<numEntries; j++)
612  jacStamp[i][j] = 2*numExtVars + CG_colIdx[CG_rowPtr[i-2*numExtVars] + j - numExtVars];
613  }
614  else
615  {
616  for (int j=numExtVars; j<numEntries; j++)
617  jacStamp[i][j] = numExtVars + j;
618  }
619  }
620  }
621  }
622  }
623 
624  // Calculate any parameters specified as expressions:
625 
627 
628  // calculate dependent (ie computed) params:
629 
630  processParams ();
631 }
632 
633 //-----------------------------------------------------------------------------
634 // Function : Instance::~Instance
635 // Purpose : destructor
636 // Special Notes :
637 // Scope : public
638 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
639 // Creation Date : 3/16/00
640 //-----------------------------------------------------------------------------
642 {
643 }
644 
645 // Additional Declarations
646 
647 //-----------------------------------------------------------------------------
648 // Function : Instance::registerLIDs
649 // Purpose :
650 // Special Notes :
651 // Scope : public
652 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
653 // Creation Date : 6/20/02
654 //-----------------------------------------------------------------------------
655 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
656  const std::vector<int> & extLIDVecRef)
657 {
658  AssertLIDs(intLIDVecRef.size() == numIntVars);
659  AssertLIDs(extLIDVecRef.size() == numExtVars);
660 
661  // Copy over the local ID lists:
662  intLIDVec = intLIDVecRef;
663  extLIDVec = extLIDVecRef;
664 
665  // Now use these lists to obtain the indices into the linear algebra
666  // entities. This assumes an order. For the matrix indices, first do the
667  // rows.
668 
669  // Obtain indices for internal variables
670  li_ROM.resize(numROMVars);
671  if(usePortDesc==0)
672  {
673  for (int i=0; i<numROMVars; i++)
674  li_ROM[i] = intLIDVec[i+numExtVars];
675  }
676  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
677  {
678  Xyce::dout() << section_divider << std::endl;
679 
680  Xyce::dout() << "::registerLIDs:\n";
681  Xyce::dout() << " name = " << getName() << std::endl;
682 
683  Xyce::dout() << "\nsolution indices:\n";
684  for (int i=0; i<numExtVars; ++i)
685  Xyce::dout() << " li_up[" << i << "] = " << extLIDVec[i] << std::endl;
686  if (usePortDesc==0)
687  {
688  for (int i=0; i<numExtVars; ++i)
689  Xyce::dout() << " li_ip[" << i << "] = " << intLIDVec[i] << std::endl;
690  }
691  for (int i=0; i<numROMVars; i++)
692  Xyce::dout() << " li_ROM[" << i << "] = " << li_ROM[i] << std::endl;
693 
694  Xyce::dout() << section_divider << std::endl;
695  }
696 
697 }
698 
699 //-----------------------------------------------------------------------------
700 // Function : Instance::registerStateLIDs
701 // Purpose :
702 // Special Notes :
703 // Scope : public
704 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
705 // Creation Date : 6/20/02
706 //-----------------------------------------------------------------------------
707 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef)
708 {
709  AssertLIDs(staLIDVecRef.size() == numStateVars);
710 
711  // Copy over the global ID lists:
712  staLIDVec = staLIDVecRef;
713 
714  li_state.resize(numStateVars, 0);
715  for (int ix=0; ix<numStateVars; ix++) {
716  li_state[ix] = staLIDVec[ix];
717  }
718 }
719 
720 //-----------------------------------------------------------------------------
721 // Function : Instance::loadNodeSymbols
722 // Purpose :
723 // Special Notes :
724 // Scope : public
725 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
726 // Creation Date : 05/13/05
727 //-----------------------------------------------------------------------------
728 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
729 {
730  if (numIntVars > 0) // Then add the current variables at the ports
731  for (int i = 0; i < numExtVars; i++)
732  addInternalNode(symbol_table, intLIDVec[i], getName(), "ip_Node" + Teuchos::Utils::toString(i + 1));
733 
734  for (int i = 0; i < numROMVars; i++)
735  addInternalNode(symbol_table, li_ROM[i], getName(), "ROM_Node"+Teuchos::Utils::toString(i+1));
736 }
737 
738 //-----------------------------------------------------------------------------
739 // Function : Instance::jacobianStamp
740 // Purpose :
741 // Special Notes :
742 // Scope : public
743 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
744 // Creation Date : 08/27/02
745 //-----------------------------------------------------------------------------
746 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
747 {
748  return jacStamp;
749 }
750 
751 //-----------------------------------------------------------------------------
752 // Function : Instance::registerJacLIDs
753 // Purpose :
754 // Special Notes :
755 // Scope : public
756 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
757 // Creation Date : 08/27/02
758 //-----------------------------------------------------------------------------
759 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
760 {
761 
762  DeviceInstance::registerJacLIDs( jacLIDVec );
763 
764  if(usePortDesc>0)
765  {
766  AEqu_NodeOffset.resize(numExtVars);
767  for (int i=0; i<numExtVars; i++)
768  {
769  AEqu_NodeOffset[i].resize(numExtVars);
770  for (int j=0; j<numExtVars; j++)
771  {
772  AEqu_NodeOffset[i][j] = jacLIDVec[i][j];
773  }
774  }
775  }
776  else
777  {
780  for (int i=0; i<numExtVars; i++)
781  {
782  AEqu_up_NodeOffset[i] = jacLIDVec[i][0];
783  AEqu_ip_NodeOffset[i] = jacLIDVec[numExtVars+i][0];
784  }
785 
786  // Get the offsets for -L^T
788  for (int i=0; i<numROMVars; i++)
789  {
790  ROMEqu_Lt_NodeOffset[i] = jacLIDVec[numExtVars][i+1];
791  }
792 
793  // Get the offsets for -B
794  ROMEqu_B_NodeOffset.resize(numExtVars*numROMVars);
795  for (int i=0; i<numROMVars; i++)
796  {
797  for (int j=0; j<numExtVars; j++)
798  ROMEqu_B_NodeOffset[i*numExtVars+j] = jacLIDVec[2*numExtVars+i][j];
799  }
800 
801  // Get the offsets for C d/dt
802  // If the matrix is sparse, then an offset will be stored for each nonzero.
803  if (isCSparse)
804  {
805  ROMEqu_C_NodeOffset.resize(Chat_rowPtr[numROMVars]);
806  for (int i=0; i<numROMVars; i++)
807  {
808  int nnz = CG_rowPtr[i+1]-CG_rowPtr[i];
809  int CrowPtr = Chat_rowPtr[i], Cnnz = Chat_rowPtr[i+1]-Chat_rowPtr[i];
810  for (int j=0, Cidx=0; j<nnz && Cidx<Cnnz; j++)
811  {
812  int colIdx = CG_colIdx[CG_rowPtr[i]+j];
813  if (colIdx == Chat_colIdx[CrowPtr])
814  {
815  ROMEqu_C_NodeOffset[CrowPtr++] = jacLIDVec[2*numExtVars+i][numExtVars+j];
816  Cidx++;
817  }
818  }
819  }
820  }
821 
822  // Get the offsets for G
823  // If the matrix is sparse, then an offset will be stored for each nonzero.
824  if (isGSparse)
825  {
826  ROMEqu_G_NodeOffset.resize(Ghat_rowPtr[numROMVars]);
827  for (int i=0; i<numROMVars; i++)
828  {
829  int nnz = CG_rowPtr[i+1]-CG_rowPtr[i];
830  int GrowPtr = Ghat_rowPtr[i], Gnnz = Ghat_rowPtr[i+1]-Ghat_rowPtr[i];
831  for (int j=0, Gidx=0; j<nnz && Gidx<Gnnz; j++)
832  {
833  int colIdx = CG_colIdx[CG_rowPtr[i]+j];
834  if (colIdx == Ghat_colIdx[GrowPtr])
835  {
836  ROMEqu_G_NodeOffset[GrowPtr++] = jacLIDVec[2*numExtVars+i][numExtVars+j];
837  Gidx++;
838  }
839  }
840  }
841  }
842 
843  // If either C or G is dense, we need these node offsets, which assume the storage is contiguous.
844  if (!isCSparse || !isGSparse)
845  {
846  ROMEqu_GpC_NodeOffset.resize(numROMVars);
847  for (int i=0; i<numROMVars; i++)
848  {
849  ROMEqu_GpC_NodeOffset[i] = jacLIDVec[2*numExtVars][numExtVars+i];
850  }
851  }
852 
853  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
854  {
855  Xyce::dout() << Xyce::section_divider << std::endl;
856  Xyce::dout() << "Instance::registerJacLIDs\n";
857  if (usePortDesc==0)
858  {
859  Xyce::dout() << " AEqu_up_NodeOffset: ";
860  for (int i=0; i<numExtVars; i++)
861  Xyce::dout() << AEqu_up_NodeOffset[i] << " ";
862  Xyce::dout() << std::endl;
863  Xyce::dout() << " AEqu_ip_NodeOffset: ";
864  for (int i=0; i<numExtVars; i++)
865  Xyce::dout() << AEqu_ip_NodeOffset[i] << " ";
866  Xyce::dout() << std::endl;
867  Xyce::dout() << " AROMEqu_Lt_NodeOffset: ";
868  for (int i=0; i<numROMVars; i++)
869  Xyce::dout() << ROMEqu_Lt_NodeOffset[i] << " ";
870  Xyce::dout() << std::endl;
871  Xyce::dout() << " AROMEqu_B_NodeOffset: " << std::endl;
872  for (int i=0; i<numROMVars; i++)
873  {
874  for (int j=0; j<numExtVars; j++)
875  Xyce::dout() << ROMEqu_B_NodeOffset[i*numExtVars+j] << " ";
876  Xyce::dout() << std::endl;
877  }
878  Xyce::dout() << " AROMEqu_GpC_NodeOffset: ";
879  for (int i=0; i<numROMVars; i++)
880  Xyce::dout() << ROMEqu_GpC_NodeOffset[i] << " ";
881  Xyce::dout() << std::endl;
882  }
883  Xyce::dout() << Xyce::section_divider << std::endl;
884  }
885  }
886 }
887 
888 //-----------------------------------------------------------------------------
889 // Function : Instance::setupPointers
890 // Purpose :
891 // Special Notes :
892 // Scope : public
893 // Creator : Heidi Thornquist, SNL
894 // Creation Date : 11/30/08
895 //-----------------------------------------------------------------------------
897 {
898 
899 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
900  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
901  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
902 
903  // Get pointers for KCL equations and Ghat, Lhat, and Bhat
904  if(usePortDesc==0)
905  {
906  fEqu_up_NodePtr.resize(numExtVars);
907  for (int i=0; i<numExtVars; ++i)
908  {
909  fEqu_up_NodePtr[i] = &(dFdx[extLIDVec[i]][AEqu_up_NodeOffset[i]]);
910  }
911 
912  fEqu_ip_NodePtr.resize(numExtVars);
913  for (int i=0; i<numExtVars; ++i)
914  {
915  fEqu_ip_NodePtr[i] = &(dFdx[intLIDVec[i]][AEqu_ip_NodeOffset[i]]);
916  }
917 
918  // Get pointers for Ghat (assuming contiguous), only if Ghat is not sparse.
919  if (isGSparse)
920  {
922  for (int i=0; i<numROMVars; ++i)
923  {
924  for (int j=Ghat_rowPtr[i]; j<Ghat_rowPtr[i+1]; j++)
925  {
927  }
928  }
929  }
930  else
931  {
933  for (int i=0; i<numROMVars; ++i)
934  {
936  }
937  }
938 
939  // Lhat (assuming contiguous)
940  fROMEqu_Lhat_VarsPtrs.resize(numExtVars);
941  for (int i=0; i<numExtVars; ++i)
942  {
944  }
945 
946  // Bhat (these are not guaranteed to be contiguous)
947  fROMEqu_Bhat_VarsPtrs.resize(numExtVars*numROMVars);
948  for (int i=0; i<numROMVars; ++i)
949  {
950  for (int j=0; j<numExtVars; ++j)
951  {
952  fROMEqu_Bhat_VarsPtrs[numExtVars*i+j]=&(dFdx[li_ROM[i]][ROMEqu_B_NodeOffset[i*numExtVars+j]]);
953  }
954  }
955 
956  // Get pointers for Chat (assuming contiguous), only if Chat is not sparse.
957  if (isCSparse)
958  {
959  qROMEqu_Chat_VarsPtrs.resize(Chat_rowPtr[numROMVars]);
960  for (int i=0; i<numROMVars; ++i)
961  {
962  for (int j=Chat_rowPtr[i]; j<Chat_rowPtr[i+1]; j++)
963  {
965  }
966  }
967  }
968  else
969  {
970  qROMEqu_Chat_VarsPtrs.resize(numROMVars);
971  for (int i=0; i<numROMVars; ++i)
973  }
974  }
975 #endif
976 }
977 
978 //-----------------------------------------------------------------------------
979 // Function : Instance::updatePrimaryState
980 // Purpose :
981 // Special Notes :
982 // Scope : public
983 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
984 // Creation Date : 01/29/01
985 //-----------------------------------------------------------------------------
987 {
988  double * solVec = extData.nextSolVectorRawPtr;
989  double * staVec = extData.nextStaVectorRawPtr;
990  std::vector<double> v_up(numExtVars);
991  for (int i=0; i<numExtVars; ++i)
992  {
993  v_up[i] = solVec[extLIDVec[i]];
994  Fhat[i] = solVec[intLIDVec[i]];
995  i_ip[i] = solVec[intLIDVec[i]];
996  }
997  double * xhat = &solVec[li_ROM[0]];
998 
999  Teuchos::BLAS<int, double> blas;
1000 
1001  // Compute Fhat[0:numExtVars-1] = i_ip - Lhat'*xhat
1002  blas.GEMV( Teuchos::TRANS, numROMVars, numExtVars, -1.0, &Lhat[0], numROMVars, xhat, 1, 1.0, &Fhat[0], 1 );
1003 
1004  // Compute Fhat[numExtVars:numIntVars] = Ghat*xhat - Bhat*v_up
1005  if (isGSparse)
1006  Linear::crsAxpy( numROMVars, 1.0, &Ghat[0], &Ghat_rowPtr[0], &Ghat_colIdx[0], xhat, 0.0, &Fhat[numExtVars] );
1007  else
1008  blas.GEMV( Teuchos::NO_TRANS, numROMVars, numROMVars, 1.0, &Ghat[0], numROMVars, xhat, 1, 0.0, &Fhat[numExtVars], 1 );
1009  blas.GEMV( Teuchos::NO_TRANS, numROMVars, numExtVars, -1.0, &Bhat[0], numROMVars, &v_up[0], 1, 1.0, &Fhat[numExtVars], 1 );
1010 
1011  // Compute Qhat = Chat * xhat
1012  if (isCSparse)
1013  Linear::crsAxpy( numROMVars, 1.0, &Chat[0], &Chat_rowPtr[0], &Chat_colIdx[0], xhat, 0.0, &Qhat[0] );
1014  else
1015  blas.GEMV( Teuchos::NO_TRANS, numROMVars, numROMVars, 1.0, &Chat[0], numROMVars, xhat, 1, 0.0, &Qhat[0], 1 );
1016 
1017  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1018  {
1019  Xyce::dout() << " ----------------------------------" << std::endl;
1020  Xyce::dout() << "Instance::updatePrimaryState:" << std::endl;
1021  }
1022 
1023  return true;
1024 }
1025 
1026 //-----------------------------------------------------------------------------
1027 // Function : Instance::loadErrorWeightMask
1028 //
1029 // Purpose : Loads the zero elements of the device mask
1030 //
1031 // Special Notes : elements of the error vector associated with zero
1032 // elements of the mask will not be included in weighted
1033 // norms by the time integrator.
1034 //
1035 // Scope : public
1036 // Creator : Keith Santarelli, SNL, Electrical and Microsystems Modeling
1037 // Creation Date : 03/12/08
1038 //-----------------------------------------------------------------------------
1040 {
1041  if (maskROMVars)
1042  {
1043  Linear::Vector * maskVectorPtr = extData.deviceErrorWeightMask_;
1044 
1045  for (int i=0; i<numROMVars; i++)
1046  {
1047  (*maskVectorPtr)[li_ROM[i]] = 0.0;
1048  }
1049  }
1050 }
1051 
1052 //-----------------------------------------------------------------------------
1053 // Function : Instance::loadDAEQVector
1054 //
1055 // Purpose : Loads the Q-vector contributions for a single
1056 // ROM instance.
1057 //
1058 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1059 // which the system of equations is represented as:
1060 //
1061 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1062 //
1063 // Scope : public
1064 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1065 // Creation Date : 01/24/03
1066 //-----------------------------------------------------------------------------
1068 {
1069  double * qVec = extData.daeQVectorRawPtr;
1070  for (int i=0; i<numROMVars; i++)
1071  {
1072  qVec[li_ROM[i]] += Qhat[i];
1073  }
1074  return true;
1075 }
1076 
1077 //-----------------------------------------------------------------------------
1078 // Function : Instance::loadDAEFVector
1079 //
1080 // Purpose : Loads the F-vector contributions for a single
1081 // ROM instance.
1082 //
1083 // Special Notes :
1084 //
1085 // Scope : public
1086 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1087 // Creation Date : 01/24/03
1088 //-----------------------------------------------------------------------------
1090 {
1091  double * fVec = extData.daeFVectorRawPtr;
1092 
1093  // Load F vector
1094  for (int i=0; i<numExtVars; ++i)
1095  {
1096  fVec[extLIDVec[i]] += i_ip[i];
1097  fVec[intLIDVec[i]] += Fhat[i];
1098  }
1099  for (int i=0; i<numROMVars; i++)
1100  {
1101  fVec[li_ROM[i]] += Fhat[numExtVars+i];
1102  }
1103 
1104  return true;
1105 }
1106 
1107 //-----------------------------------------------------------------------------
1108 // Function : Instance::loadDAEdQdx
1109 //
1110 // Purpose : Loads the dQdx-matrix contributions for a single
1111 // ROM instance.
1112 //
1113 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1114 // which the system of equations is represented as:
1115 //
1116 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1117 //
1118 // Scope : public
1119 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1120 // Creation Date : 03/05/04
1121 //-----------------------------------------------------------------------------
1123 {
1124  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
1125 
1126  // Load Chat portion of dQ/dx
1127  for (int i=0; i<numROMVars; i++)
1128  {
1129  if (isCSparse)
1130  {
1131  for (int j=Chat_rowPtr[i]; j<Chat_rowPtr[i+1]; j++)
1132  {
1133 
1134  dQdx[li_ROM[i]][ROMEqu_C_NodeOffset[j]] += Chat[j];
1135  }
1136  }
1137  else
1138  {
1139  for (int j=0; j<numROMVars; j++)
1140  {
1141 
1142  dQdx[li_ROM[i]][ROMEqu_GpC_NodeOffset[j]] += Chat[j*numROMVars + i];
1143  }
1144  }
1145  }
1146  return true;
1147 }
1148 
1149 //-----------------------------------------------------------------------------
1150 // Function : Instance::loadDAEdFdx ()
1151 //
1152 // Purpose : Loads the F-vector contributions for a single
1153 // ROM instance.
1154 //
1155 // Special Notes :
1156 //
1157 // Scope : public
1158 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1159 // Creation Date : 03/05/04
1160 //-----------------------------------------------------------------------------
1162 {
1163  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
1164 
1165  for (int i=0; i<numExtVars; ++i)
1166  {
1167 
1168  dFdx[extLIDVec[i]][AEqu_up_NodeOffset[i]] += 1.0;
1169 
1170  dFdx[intLIDVec[i]][AEqu_ip_NodeOffset[i]] += 1.0;
1171  }
1172 
1173  // Load -Lhat portion of dF/dx
1174  for (int j=0; j<numROMVars; j++)
1175  {
1176  for (int i=0; i<numExtVars; i++)
1177  {
1178 
1179  dFdx[intLIDVec[i]][ROMEqu_Lt_NodeOffset[j]] -= Lhat[j];
1180  }
1181  }
1182 
1183  // Load -Bhat portion of dF/dx
1184  for (int i=0; i<numROMVars; i++)
1185  {
1186  for (int j=0; j<numExtVars; j++)
1187  {
1188 
1189  dFdx[li_ROM[i]][ROMEqu_B_NodeOffset[i*numExtVars+j]] -= Bhat[j*numROMVars + i];
1190  }
1191  }
1192 
1193  // Load Ghat portion of dF/dx
1194  for (int i=0; i<numROMVars; i++)
1195  {
1196  if (isGSparse)
1197  {
1198  for (int j=Ghat_rowPtr[i]; j<Ghat_rowPtr[i+1]; j++)
1199  {
1200 
1201  dFdx[li_ROM[i]][ROMEqu_G_NodeOffset[j]] += Ghat[j];
1202  }
1203  }
1204  else
1205  {
1206  for (int j=0; j<numROMVars; j++)
1207  {
1208 
1209  dFdx[li_ROM[i]][ROMEqu_GpC_NodeOffset[j]] += Ghat[j*numROMVars + i];
1210  }
1211  }
1212  }
1213  return true;
1214 }
1215 
1216 //-----------------------------------------------------------------------------
1217 // Function : Instance::setIC
1218 // Purpose :
1219 // Special Notes :
1220 // Scope : public
1221 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1222 // Creation Date : 01/10/02
1223 //-----------------------------------------------------------------------------
1225 {
1226  return true;
1227 }
1228 
1229 //-----------------------------------------------------------------------------
1230 // Function : Instance::varTypes
1231 // Purpose :
1232 // Special Notes :
1233 // Scope : public
1234 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
1235 // Creation Date : 02/17/04
1236 //-----------------------------------------------------------------------------
1237 void Instance::varTypes( std::vector<char> & varTypeVec )
1238 {
1239 }
1240 
1241 
1242 // Class Model
1243 
1244 //-----------------------------------------------------------------------------
1245 // Function : Model::processParams
1246 // Purpose :
1247 // Special Notes :
1248 // Scope : public
1249 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1250 // Creation Date : 6/03/02
1251 //-----------------------------------------------------------------------------
1253 {
1254  return true;
1255 }
1256 
1257 //----------------------------------------------------------------------------
1258 // Function : Model::processInstanceParams
1259 // Purpose :
1260 // Special Notes :
1261 // Scope : public
1262 // Creator : Dave Shirely, PSSI
1263 // Creation Date : 03/23/06
1264 //----------------------------------------------------------------------------
1266 {
1267  std::vector<Instance*>::iterator iter;
1268  std::vector<Instance*>::iterator first = instanceContainer.begin();
1269  std::vector<Instance*>::iterator last = instanceContainer.end();
1270 
1271  for (iter=first; iter!=last; ++iter)
1272  {
1273  (*iter)->processParams();
1274  }
1275 
1276  return true;
1277 }
1278 
1279 //-----------------------------------------------------------------------------
1280 // Function : Model::Model
1281 // Purpose : block constructor
1282 // Special Notes :
1283 // Scope : public
1284 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1285 // Creation Date : 5/17/00
1286 //-----------------------------------------------------------------------------
1287 
1289  const Configuration & configuration,
1290  const ModelBlock & MB,
1291  const FactoryBlock & factory_block)
1292  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
1293 {
1294 
1295  // Set params to constant default values:
1296  setDefaultParams ();
1297 
1298  // Set params according to .model line and constant defaults from metadata:
1299  setModParams (MB.params);
1300 
1301  // Calculate any parameters specified as expressions:
1303 
1304  // calculate dependent (ie computed) params and check for errors:
1305  processParams ();
1306 }
1307 
1308 //-----------------------------------------------------------------------------
1309 // Function : Model::Model
1310 // Purpose : destructor
1311 // Special Notes :
1312 // Scope : public
1313 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1314 // Creation Date : 3/16/00
1315 //-----------------------------------------------------------------------------
1316 
1318 {
1319  std::vector<Instance*>::iterator iter;
1320  std::vector<Instance*>::iterator first = instanceContainer.begin();
1321  std::vector<Instance*>::iterator last = instanceContainer.end();
1322 
1323  for (iter=first; iter!=last; ++iter)
1324  {
1325  delete (*iter);
1326  }
1327 
1328 }
1329 
1330 //-----------------------------------------------------------------------------
1331 // Function : Model::printOutInstances
1332 // Purpose : debugging tool.
1333 // Special Notes :
1334 // Scope : public
1335 // Creator : Heidi Thornquist, SNL, Parallel Computational Sciences
1336 // Creation Date : 4/03/00
1337 //-----------------------------------------------------------------------------
1338 
1339 std::ostream &Model::printOutInstances(std::ostream &os) const
1340 {
1341  std::vector<Instance*>::const_iterator iter;
1342  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
1343  std::vector<Instance*>::const_iterator last = instanceContainer.end();
1344 
1345  int i,isize;
1346 
1347  isize = instanceContainer.size();
1348  os << std::endl;
1349  os << "Number of ROM instances: " << isize << std::endl;
1350  os << " name\t\tmodelName\tParameters" << std::endl;
1351 
1352  for (i = 0, iter = first; iter != last; ++iter, ++i)
1353  {
1354  os << " " << i << ": " << (*iter)->getName() << "\t";
1355  os << getName();
1356  os << std::endl;
1357  }
1358 
1359  os << std::endl;
1360 
1361  return os;
1362 }
1363 
1364 //-----------------------------------------------------------------------------
1365 // Function : Model::forEachInstance
1366 // Purpose :
1367 // Special Notes :
1368 // Scope : public
1369 // Creator : David Baur
1370 // Creation Date : 2/4/2014
1371 //-----------------------------------------------------------------------------
1372 /// Apply a device instance "op" to all instances associated with this
1373 /// model
1374 ///
1375 /// @param[in] op Operator to apply to all instances.
1376 ///
1377 ///
1378 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1379 {
1380  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1381  op(*it);
1382 }
1383 
1384 
1385 // ROM Master functions:
1386 
1387 //-----------------------------------------------------------------------------
1388 // Function : Master::updateState
1389 // Purpose :
1390 // Special Notes :
1391 // Scope : public
1392 // Creator : Heidi Thornquist, SNL
1393 // Creation Date : 11/26/08
1394 //-----------------------------------------------------------------------------
1395 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
1396 {
1397  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1398  {
1399  Xyce::dout() << " ----------------------------------" << std::endl;
1400  Xyce::dout() << " Master::updateState: " << std::endl;
1401  }
1402 
1403  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1404  {
1405  Instance & ci = *(*it);
1406 
1407  Teuchos::BLAS<int, double> blas;
1408  if (ci.usePortDesc>0) // TWO-LEVEL DEVICE STAMPS
1409  {
1410  const char test = 'N';
1411  int MN = ci.numStateVars;
1412  int N = ci.numExtVars;
1413  int M = MN-N;
1414 
1415  // Check if this is the first device call after a successful timestep
1416  int sameTimeStep=0;
1418  if (ci.lastTimeStepNumber==ci.getSolverState().timeStepNumber_) {sameTimeStep=1;}
1419 
1420  //********************************************************************
1421  // Set up the coefficients for discretization for the INNER solve
1422  //********************************************************************
1423  if (ci.usePortDesc == 1) // DYNAMIC ORDER SELECTION
1424  {
1425  if (sameTimeStep == 0)
1426  ci.coefLast = ci.coef;
1427 
1428  if (ci.getSolverState().currentOrder_ == 0)
1429  ci.coef = 1.0; // Force BE
1430  else
1431  ci.coef = (1.0/ci.getSolverState().currentOrder_);
1432 
1433  if (ci.getSolverState().usedOrder_ == 0)
1434  ci.coefLast = 1.0; // Force BE
1435  }
1436  else if (ci.usePortDesc == 2) { // BACKWARD EULER
1437  ci.coef = 1.0;
1438  ci.coefLast = 1.0;
1439  }
1440  else if (ci.usePortDesc == 3) { // TRAP
1441  ci.coef=0.5;
1442  ci.coefLast = 0.5;
1443  }
1444  else
1445  Xyce::dout() << "Bad 'USE_PORT_DESCRIPTION' flag" << std::endl;
1446 
1447 
1448  // Get alph=1/dt for current and last time steps
1449  if (sameTimeStep==0) {ci.alph_last = ci.alph;}
1450  ci.alph=1/ci.getSolverState().currTimeStep_;
1451  if (ci.getSolverState().dcopFlag==1) { ci.alph=0.0; ci.alph_last=0.0; }
1452  if (ci.getSolverState().timeStepNumber_ == 0) { ci.alph_last=0.0; }
1453 
1454 
1455  //********************************************************************
1456  // Load port and internal state variables
1457  //********************************************************************
1458  std::vector<double> lastStaVec, currStaVec, nextStaVec; // Internal states
1459  lastStaVec.resize(M+N,0);
1460  currStaVec.resize(M+N,0);
1461  nextStaVec.resize(M+N,0);
1462  //for(int ix=0; ix<(M+N); ++ix) { lastStaVec[ix] = (*ci.extData.lastStaVectorPtr)[ix]; } // WRONG
1463  for(int ix=0; ix<(M+N); ++ix) { lastStaVec[ix] = (*ci.extData.lastStaVectorPtr)[ ci.li_state[ix] ]; }
1464  std::vector<double> lastPortVec, currPortVec, nextPortVec; // Port voltages
1465  lastPortVec.resize(N,0);
1466  currPortVec.resize(N,0);
1467  nextPortVec.resize(N,0);
1468  for(int ix=0; ix<N; ++ix)
1469  {
1470  lastPortVec[ix] = (*ci.extData.lastSolVectorPtr)[ci.extLIDVec[ix]];
1471  currPortVec[ix] = (*ci.extData.currSolVectorPtr)[ci.extLIDVec[ix]];
1472  nextPortVec[ix] = solVec[ci.extLIDVec[ix]];
1473  }
1474 
1475  /*
1476  std::vector<int> lidState = set this up in registerStateLIDs
1477  localState[ix] = ci.extradata.currState[ ci.lidState[ix] ];
1478  ci.extData.currState[ ci.lidState[ix] ] = localState[ix];
1479  */
1480 
1481  // Begin math stuff
1482  Teuchos::LAPACK<int,double> lapack;
1483  std::vector<int> ipiv_A2last (M+N, 0);
1484  int info_A2, info_A2last, info2_A2, info2_A2last;
1485 
1486 
1487  //****************************************************************
1488  // Compute, or load, old internal state (currStaVec) [INNER SOLVE]
1489  // x2[t] = A2\(-coef*G2p*xp[t] - (1-coef)*G2p*xp[t-1] - [(1-coef)*G2-C2/dt]*x2[t-1])
1490  //******************************************************
1491  int updateCurrStaVec=0;
1492  // if (ci.getSolverState().newtonIter==0) { updateCurrStaVec=1; }
1493  if (sameTimeStep==0) {updateCurrStaVec=1; }
1494  if (updateCurrStaVec==1) { // compute new `last' state
1495  blas.GEMV( Teuchos::NO_TRANS,N+M,N+M,-(1-ci.coefLast),&ci.G2[0],M+N,&lastStaVec[0],1,0.0,&currStaVec[0],1 ); // -(1-coefLast)*G2*lastStaVec
1496  blas.GEMV( Teuchos::NO_TRANS,N+M,N+M,ci.alph_last,&ci.C2[0],M+N,&lastStaVec[0],1,1.0,&currStaVec[0],1 ); // C2/dtlast*lastStaVec
1497  blas.GEMV( Teuchos::NO_TRANS,N+M,N,-ci.coefLast,&ci.G2p[0],N+M,&currPortVec[0],1, 1.0,&currStaVec[0],1 ); // -coefLast*G2p*currPortVec
1498  blas.GEMV( Teuchos::NO_TRANS,N+M,N,-(1-ci.coefLast),&ci.G2p[0],N+M,&lastPortVec[0],1,1.0,&currStaVec[0],1 ); // -(1-coefLast)*G2p*lastPortVec
1499  int useOldA2=1;
1500  if (ci.getSolverState().timeStepNumber_ < 2) { useOldA2=0; }
1501  if (ci.lastTimeStepNumber==ci.getSolverState().timeStepNumber_) { useOldA2=0; }
1502  if (useOldA2==1) // use [previously factored] A2 as A2last
1503  lapack.GETRS(test, M+N, 1, &ci.A2[0], M+N, &ci.ipiv_A2[0], &currStaVec[0], M+N, &info2_A2); // A2\(xtmp)
1504  else { // compute new A2last
1505  for(int ix=0; ix<(M+N)*(M+N); ix++) { ci.A2last[ix]= (ci.alph_last*ci.C2[ix]) + (ci.coefLast*ci.G2[ix]); } // A2 using previous dt
1506  lapack.GETRF( M+N, M+N, &ci.A2last[0], M+N, &ipiv_A2last[0], &info_A2last); // factor A2last
1507  lapack.GETRS(test, M+N, 1, &ci.A2last[0], M+N, &ipiv_A2last[0], &currStaVec[0], M+N, &info2_A2last); // A2last\(xtmp)
1508  }
1509  for(int ix=0; ix<(M+N); ++ix) { (*ci.extData.currStaVectorPtr)[ ci.li_state[ix] ] = currStaVec[ix]; } // Store answer
1510  }
1511  else
1512  { // Load currStaVec
1513  for(int ix=0; ix<(M+N); ++ix) { currStaVec[ix] = (*ci.extData.currStaVectorPtr)[ ci.li_state[ix] ]; }
1514  }
1515 
1516 
1517  //**************************************************
1518  // construct A2 and Jacobian (Jstamp), if necessary
1519  // Jstamp = -Gp2*(A2\(coef*G2p)) = -Gp2 * A2sol
1520  //**************************************************
1521  int updateA2 = 1;
1522  if (ci.getSolverState().timeStepNumber_ > 2){
1523  if (ci.getSolverState().newtonIter>0) { updateA2=0; }
1524  if (ci.alph==ci.alph_last) { if (ci.coef==ci.coefLast) { updateA2=0; }}}
1525  if (updateA2==1) {
1526  for(int ix=0; ix<(M+N)*(M+N); ix++) { ci.A2[ix]= (ci.alph*ci.C2[ix]) + (ci.coef*ci.G2[ix]); } // A2 = 1/dt*C2 + coef*G2;
1527  lapack.GETRF( M+N, M+N, &ci.A2[0], M+N, &ci.ipiv_A2[0], &info_A2); // Factor A2
1528  for(int ix=0; ix<(M+N)*N; ix++) { ci.A2sol[ix] = ci.coef * ci.G2p[ix]; } // copy to RHS vector
1529  lapack.GETRS(test, M+N, N, &ci.A2[0], M+N, &ci.ipiv_A2[0], &ci.A2sol[0], M+N, &info2_A2);
1530  blas.GEMM(Teuchos::NO_TRANS, Teuchos::NO_TRANS, N, N, M+N, -1.0,&ci.Gp2[0],N,&ci.A2sol[0],M+N,0.0,&ci.Jstamp[0], N);
1531  }
1532 
1533 
1534  //************************************************
1535  // Compute and save new internal state (nextStaVec)
1536  // x2[t] = A2\(-coef*G2p*xp[t] - (1-coef)*G2p*xp[t-1] - [(1-coef)*G2-C2/dt]*x2[t-1])
1537  //************************************************
1538  blas.GEMV( Teuchos::NO_TRANS,N+M,N+M,-(1-ci.coef),&ci.G2[0],M+N,&currStaVec[0],1,0.0,&nextStaVec[0],1 ); // -(1-coef)*G2*currStaVec
1539  blas.GEMV( Teuchos::NO_TRANS,N+M,N+M,ci.alph,&ci.C2[0],M+N,&currStaVec[0],1,1.0,&nextStaVec[0],1 ); // C2/dt*currStaVec
1540  blas.GEMV( Teuchos::NO_TRANS,N+M,N,-ci.coef,&ci.G2p[0],N+M,&nextPortVec[0],1, 1.0,&nextStaVec[0],1 ); // -coef*G2p*nextPortVec
1541  blas.GEMV( Teuchos::NO_TRANS,N+M,N,-(1-ci.coef),&ci.G2p[0],N+M,&currPortVec[0],1,1.0,&nextStaVec[0],1 ); // -(1-coef)*G2p*currPortVec
1542  lapack.GETRS(test, M+N, 1, &ci.A2[0], M+N, &ci.ipiv_A2[0], &nextStaVec[0], M+N, &info2_A2); // A2\(prev)
1543  // for(int ix=0; ix<(M+N); ++ix) { (*ci.extData.nextStaVectorPtr)[ix] = nextStaVec[ix]; } // save internal state
1544  for(int ix=0; ix<(M+N); ++ix) { (*ci.extData.nextStaVectorPtr)[ ci.li_state[ix] ] = nextStaVec[ix]; } // save internal state
1545 
1546 
1547  //********************************************************
1548  // Compute residual stamp (Fstamp) using new internal state
1549  // Fstamp = Gp2 * nextStaVec
1550  //********************************************************
1551  blas.GEMV( Teuchos::NO_TRANS,N,N+M,1.0,&ci.Gp2[0],N,&nextStaVec[0],1,0.0,&ci.Fstamp[0],1 ); // Gp2*nextStaVec
1552 
1553 
1554  } // END 2-LEVEL STAMP
1555 
1556  //-------------------------------------------------------------------------
1557  //-------------------------------------------------------------------------
1558  //-------------------------------------------------------------------------
1559 
1560  if(ci.usePortDesc==0) // REGULAR DEVICE STAMPS
1561  {
1562  int N = ci.numExtVars;
1563  std::vector<double> v_up(N);
1564  for (int i=0; i<N; ++i)
1565  {
1566  v_up[i] = solVec[ci.extLIDVec[i]];
1567  ci.i_ip[i] = solVec[ci.intLIDVec[i]];
1568  ci.Fhat[i] = solVec[ci.intLIDVec[i]];
1569  }
1570  double * xhat = &solVec[ci.li_ROM[0]];
1571 
1572  // Compute Fhat[0:numExtVars-1] = i_ip - Lhat'*xhat
1573  blas.GEMV( Teuchos::TRANS, ci.numROMVars, ci.numExtVars, -1.0, &ci.Lhat[0], ci.numROMVars, xhat, 1, 1.0, &ci.Fhat[0], 1 );
1574 
1575  // Xyce::dout() << "Fhat (should just change first two elements): " << std::endl;
1576  // for (int i=0; i<ci.numIntVars; i++)
1577  // Xyce::dout() << "Fhat [" << i << "] = " << ci.Fhat[i] << std::endl;
1578 
1579  // Compute Fhat[numExtVars:numIntVars] = Ghat*xhat - Bhat*v_up
1580  if (ci.isGSparse)
1581  Linear::crsAxpy( ci.numROMVars, 1.0, &ci.Ghat[0], &ci.Ghat_rowPtr[0], &ci.Ghat_colIdx[0], xhat, 0.0, &ci.Fhat[ci.numExtVars] );
1582  else
1583  blas.GEMV( Teuchos::NO_TRANS, ci.numROMVars, ci.numROMVars, 1.0, &ci.Ghat[0], ci.numROMVars, xhat, 1, 0.0, &ci.Fhat[ci.numExtVars], 1 );
1584  blas.GEMV( Teuchos::NO_TRANS, ci.numROMVars, ci.numExtVars, -1.0, &ci.Bhat[0], ci.numROMVars, &v_up[0], 1, 1.0, &ci.Fhat[ci.numExtVars], 1 );
1585 
1586  // Xyce::dout() << "Fhat (should just change last elements representing ROM): " << std::endl;
1587  // for (int i=0; i<ci.numIntVars; i++)
1588  // Xyce::dout() << "Fhat [" << i << "] = " << ci.Fhat[i] << std::endl;
1589 
1590  // Compute Qhat = Chat * xhat
1591  if (ci.isCSparse)
1592  Linear::crsAxpy( ci.numROMVars, 1.0, &ci.Chat[0], &ci.Chat_rowPtr[0], &ci.Chat_colIdx[0], xhat, 0.0, &ci.Qhat[0] );
1593  else
1594  blas.GEMV( Teuchos::NO_TRANS, ci.numROMVars, ci.numROMVars, 1.0, &ci.Chat[0], ci.numROMVars, xhat, 1, 0.0, &ci.Qhat[0], 1 );
1595 
1596  // Xyce::dout() << "Qhat (should change all elements): " << std::endl;
1597  // for (int i=0; i<ci.numROMVars; i++)
1598  // Xyce::dout() << "Qhat [" << i << "] = " << ci.Qhat[i] << std::endl;
1599  }
1600  }
1601 
1602  return true;
1603 }
1604 
1605 
1606 
1607 //-----------------------------------------------------------------------------
1608 // Function : Master::printMatrix
1609 // Purpose :
1610 // Special Notes : For debugging 2-level device stamp
1611 // Scope : public
1612 // Creator : Brad Bond, SNL
1613 // Creation Date : 2011-03-11
1614 //-----------------------------------------------------------------------------
1615 void Master::printMatrix ( std::string vname, double * Matrix, int Nrows, int Ncols )
1616 {
1617  Xyce::dout() << std::endl << vname << ": " << std::endl;
1618  for(int ix=0; ix < Nrows; ix++)
1619  {
1620  for(int iy=0; iy < Ncols; iy++)
1621  {
1622  Xyce::dout() << Matrix[iy*Nrows+ix] << " ";
1623  }
1624  Xyce::dout() << std::endl;
1625  }
1626 }
1627 
1628 //-----------------------------------------------------------------------------
1629 // Function : Master::loadDAEVectors
1630 // Purpose :
1631 // Special Notes :
1632 // Scope : public
1633 // Creator : Heidi Thornquist, SNL
1634 // Creation Date : 11/26/08
1635 //-----------------------------------------------------------------------------
1636 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
1637 {
1638  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1639  {
1640  Xyce::dout() << " ----------------------------------" << std::endl;
1641  Xyce::dout() << " Master::loadDAEVectors: " << std::endl;
1642  }
1643 
1644  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1645  {
1646  Instance & ci = *(*it);
1647  if(ci.usePortDesc==0)
1648  {
1649  // Load F vector
1650  for (int i=0; i<ci.numExtVars; ++i)
1651  {
1652  fVec[ci.extLIDVec[i]] += ci.i_ip[i];
1653  fVec[ci.intLIDVec[i]] += ci.Fhat[i];
1654  }
1655 
1656  // Load ROM part of F and Q vector
1657  for (int i=0; i<ci.numROMVars; i++)
1658  {
1659  // F vector
1660 
1661  fVec[ci.li_ROM[i]] += ci.Fhat[ci.numExtVars+i];
1662  // Q vector
1663 
1664  qVec[ci.li_ROM[i]] += ci.Qhat[i];
1665  }
1666  }
1667 
1668  // TWO-LEVEL STAMP
1669  else
1670  {
1671  for (int i=0; i<ci.numExtVars; ++i)
1672  {
1673  fVec[ci.extLIDVec[i]] += ci.Fstamp[i];
1674  }
1675  }
1676  }
1677  return true;
1678 }
1679 
1680 //-----------------------------------------------------------------------------
1681 // Function : Master::loadDAEMatrices
1682 // Purpose :
1683 // Special Notes :
1684 // Scope : public
1685 // Creator : Heidi Thornquist, SNL
1686 // Creation Date : 11/26/08
1687 //-----------------------------------------------------------------------------
1688 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
1689 {
1690  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1691  {
1692  Xyce::dout() << " ----------------------------------" << std::endl;
1693  Xyce::dout() << " Master::loadDAEMatrices: " << std::endl;
1694  }
1695 
1696  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1697  {
1698  Instance & ci = *(*it);
1699 
1700  if(ci.usePortDesc==0)
1701  {
1702 
1703  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1704  {
1705  Xyce::dout() << " loads for ROM " << ci.getName() << std::endl;
1706  }
1707 
1708 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1709  // Load dF/dx
1710  for (int i=0; i<ci.numExtVars; ++i)
1711  {
1712 
1713  *(ci.fEqu_up_NodePtr[i]) += 1.0;
1714 
1715  *(ci.fEqu_ip_NodePtr[i]) += 1.0;
1716  }
1717 
1718  // Load -Lhat portion of dF/dx
1719  for (int i=0; i<ci.numExtVars; i++)
1720  {
1721  double * LhatPtr = ci.fROMEqu_Lhat_VarsPtrs[i];
1722  for (int j=0; j<ci.numROMVars; j++)
1723  {
1724 
1725  LhatPtr[j] -= ci.Lhat[i*ci.numROMVars + j];
1726  }
1727  }
1728 
1729  // Load -Bhat portion of dF/dx
1730  for (int i=0; i<ci.numROMVars; i++)
1731  {
1732  for (int j=0; j<ci.numExtVars; j++)
1733  {
1734 
1735  *(ci.fROMEqu_Bhat_VarsPtrs[ci.numExtVars*i+j]) -= ci.Bhat[j*ci.numROMVars + i];
1736  }
1737  }
1738 
1739  // Load Ghat portion of dF/dx
1740  if (ci.isGSparse)
1741  {
1742  int nnz = ci.Ghat_rowPtr[ci.numROMVars];
1743  for (int i=0; i<nnz; ++i)
1744  *(ci.fROMEqu_Ghat_VarsPtrs[i]) += ci.Ghat[i];
1745  }
1746  else
1747  {
1748  for (int i=0; i<ci.numROMVars; i++)
1749  {
1750  double * GhatPtr = ci.fROMEqu_Ghat_VarsPtrs[i];
1751  for (int j=0; j<ci.numROMVars; j++)
1752  {
1753 
1754  GhatPtr[j] += ci.Ghat[j*ci.numROMVars + i];
1755  }
1756  }
1757  }
1758 
1759  // Load dQ/dx
1760  // Load Chat portion of dQ/dx
1761  if (ci.isCSparse)
1762  {
1763  int nnz=ci.Chat_rowPtr[ci.numROMVars];
1764  for(int i=0; i<nnz; i++)
1765  *(ci.qROMEqu_Chat_VarsPtrs[i]) += ci.Chat[i];
1766  }
1767  else
1768  {
1769  for (int i=0; i<ci.numROMVars; i++)
1770  {
1771  double * ChatPtr = ci.qROMEqu_Chat_VarsPtrs[i];
1772  for (int j=0; j<ci.numROMVars; j++)
1773  {
1774 
1775  ChatPtr[j] += ci.Chat[j*ci.numROMVars + i];
1776  }
1777  }
1778  }
1779 
1780 #else
1781 
1782  for (int i=0; i<ci.numExtVars; i++)
1783  {
1784 
1785  dFdx[ci.extLIDVec[i]][ci.AEqu_up_NodeOffset[i]] += 1.0;
1786 
1787  dFdx[ci.intLIDVec[i]][ci.AEqu_ip_NodeOffset[i]] += 1.0;
1788  }
1789 
1790  // Load -Lhat portion of dF/dx
1791  for (int j=0; j<ci.numROMVars; j++)
1792  {
1793  for (int i=0; i<ci.numExtVars; i++)
1794  {
1795 
1796  dFdx[ci.intLIDVec[i]][ci.ROMEqu_Lt_NodeOffset[j]] -= ci.Lhat[i*ci.numROMVars + j];
1797  }
1798  }
1799 
1800  // Load -Bhat portion of dF/dx
1801  for (int i=0; i<ci.numROMVars; i++)
1802  {
1803  for (int j=0; j<ci.numExtVars; j++)
1804  {
1805 
1806  dFdx[ci.li_ROM[i]][ci.ROMEqu_B_NodeOffset[i*ci.numExtVars+j]] -= ci.Bhat[j*ci.numROMVars + i];
1807  }
1808  }
1809 
1810  // Load Ghat portion of dF/dx
1811  if (ci.isGSparse)
1812  {
1813  for (int j=ci.Ghat_rowPtr[i]; j<ci.Ghat_rowPtr[i+1]; j++)
1814  {
1815 
1816  dFdx[ci.li_ROM[i]][ci.ROMEqu_G_NodeOffset[j]] += ci.Ghat[j];
1817  }
1818  }
1819  else
1820  {
1821  for (int i=0; i<ci.numROMVars; i++)
1822  {
1823  for (int j=0; j<ci.numROMVars; j++)
1824  {
1825 
1826  dFdx[ci.li_ROM[i]][ci.ROMEqu_GpC_NodeOffset[j]] += ci.Ghat[j*ci.numROMVars + i];
1827  }
1828  }
1829  }
1830 
1831  // Load Chat portion of dQ/dx
1832  if (ci.isCSparse)
1833  {
1834  for (int j=ci.Chat_rowPtr[i]; j<ci.Chat_rowPtr[i+1]; j++)
1835  {
1836 
1837  dQdx[ci.li_ROM[i]][ci.ROMEqu_C_NodeOffset[j]] += ci.Chat[j];
1838  }
1839  }
1840  else
1841  {
1842  for (int i=0; i<ci.numROMVars; i++)
1843  {
1844  for (int j=0; j<ci.numROMVars; j++)
1845  {
1846 
1847  dQdx[ci.li_ROM[i]][ci.ROMEqu_GpC_NodeOffset[j]] += ci.Chat[j*ci.numROMVars + i];
1848  }
1849  }
1850  }
1851 #endif
1852  }
1853  else
1854  {
1855  for (int i=0; i<ci.numExtVars; i++)
1856  {
1857  for (int j=0; j<ci.numExtVars; j++)
1858  {
1859  dFdx[ci.extLIDVec[i]][ci.AEqu_NodeOffset[i][j]] += ci.Jstamp[i*ci.numExtVars + j];
1860  }
1861  }
1862  }
1863  }
1864  return true;
1865 }
1866 
1867 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1868 {
1869 
1870  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1871 }
1872 
1874 {
1876  .registerDevice("rom", 1)
1877  .registerModelType("rom", 1);
1878 }
1879 
1880 } // namespace ROM
1881 } // namespace Device
1882 } // namespace Xyce
const InstanceName & getName() const
bool processInstanceParams()
processInstanceParams
Definition: N_DEV_ROM.C:1265
const std::vector< std::vector< int > > & jacobianStamp() const
Definition: N_DEV_ROM.C:746
std::vector< int > li_state
Definition: N_DEV_ROM.h:188
Linear::Vector * lastStaVectorPtr
std::vector< int > CG_rowPtr
Definition: N_DEV_ROM.h:164
std::vector< double > Ghat
Definition: N_DEV_ROM.h:162
const DeviceOptions & deviceOptions_
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
std::vector< std::vector< int > > AEqu_NodeOffset
Definition: N_DEV_ROM.h:193
std::vector< double > Qhat
Definition: N_DEV_ROM.h:167
std::vector< double > Fhat
Definition: N_DEV_ROM.h:168
std::vector< double > Gp2
Definition: N_DEV_ROM.h:179
std::vector< double * > fEqu_ip_NodePtr
Definition: N_DEV_ROM.h:203
std::vector< double > G2p
Definition: N_DEV_ROM.h:178
std::vector< Instance * > instanceContainer
Definition: N_DEV_ROM.h:256
Linear::Vector * currSolVectorPtr
double currTimeStep_
Region, BJT, Digital, ThermalResistor, ROM, Charon, Others.
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
Definition: N_DEV_ROM.C:655
bool given(const std::string &parameter_name) const
std::vector< double > A2last
Definition: N_DEV_ROM.h:177
Pure virtual class to augment a linear system.
std::vector< double > Fstamp
Definition: N_DEV_ROM.h:173
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
std::vector< double > Chat
Definition: N_DEV_ROM.h:160
std::vector< double * > fROMEqu_Bhat_VarsPtrs
Definition: N_DEV_ROM.h:209
InstanceVector::const_iterator getInstanceEnd() const
Returns an iterator to the ending of the vector of all instances created for this device...
std::vector< int > AEqu_up_NodeOffset
Definition: N_DEV_ROM.h:191
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Definition: N_DEV_ROM.C:728
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Definition: N_DEV_ROM.C:1867
std::vector< int > Chat_rowPtr
Definition: N_DEV_ROM.h:161
#define AssertLIDs(cmp)
std::vector< int > AEqu_ip_NodeOffset
Definition: N_DEV_ROM.h:192
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
std::vector< double * > fROMEqu_Ghat_VarsPtrs
Definition: N_DEV_ROM.h:207
std::vector< double * > qROMEqu_Chat_VarsPtrs
Definition: N_DEV_ROM.h:206
std::vector< int > Ghat_rowPtr
Definition: N_DEV_ROM.h:163
std::vector< int > CG_colIdx
Definition: N_DEV_ROM.h:164
std::vector< int > ROMEqu_C_NodeOffset
Definition: N_DEV_ROM.h:198
InstanceVector::const_iterator getInstanceBegin() const
Returns an iterator to the beginning of the vector of all instances created for this device...
std::vector< Param > params
Parameters from the line.
void varTypes(std::vector< char > &varTypeVec)
Definition: N_DEV_ROM.C:1237
Linear::Vector * lastSolVectorPtr
void setParams(const std::vector< Param > &params)
const std::string & getName() const
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
std::vector< double * > fEqu_up_NodePtr
Definition: N_DEV_ROM.h:202
std::vector< double > Lhat
Definition: N_DEV_ROM.h:166
std::vector< std::vector< int > > jacStamp
Definition: N_DEV_ROM.h:211
std::vector< int > Ghat_colIdx
Definition: N_DEV_ROM.h:163
std::vector< int > ipiv_A2
Definition: N_DEV_ROM.h:184
bool updateTemperature(const double &temp_tmp)
Definition: N_DEV_ROM.C:124
void registerDevice()
Definition: N_DEV_ROM.C:1873
std::vector< double > G2
Definition: N_DEV_ROM.h:174
Linear::Vector * deviceErrorWeightMask_
Linear::Vector * nextStaVectorPtr
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
std::vector< double * > fROMEqu_Lhat_VarsPtrs
Definition: N_DEV_ROM.h:208
Linear::Matrix * dFdxMatrixPtr
std::vector< int > ROMEqu_GpC_NodeOffset
Definition: N_DEV_ROM.h:196
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Definition: N_DEV_ROM.C:759
std::vector< int > ROMEqu_Lt_NodeOffset
Definition: N_DEV_ROM.h:194
static void loadModelParameters(ParametricData< Model > &model_parameters)
Definition: N_DEV_ROM.C:98
virtual std::ostream & printOutInstances(std::ostream &os) const
Definition: N_DEV_ROM.C:1339
int timeStepNumber_
Memristor, LTRA, TRA, testing if debug or jacobian for testing.
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
Definition: N_DEV_ROM.C:1378
const SolverState & solverState_
Class Configuration contains device configuration data.
bool processParams()
processParams
Definition: N_DEV_ROM.C:1252
#define M
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
Definition: N_DEV_ROM.C:707
const SolverState & getSolverState() const
std::vector< double > Jstamp
Definition: N_DEV_ROM.h:172
std::vector< double > A2sol
Definition: N_DEV_ROM.h:180
Linear::Vector * currStaVectorPtr
std::vector< int > Chat_colIdx
Definition: N_DEV_ROM.h:161
std::vector< double > C2
Definition: N_DEV_ROM.h:175
std::vector< double > i_ip
Definition: N_DEV_ROM.h:169
void printMatrix(std::string vname, double *Matrix, int Nrows, int Ncols)
Definition: N_DEV_ROM.C:1615
ModelBlock represents a .MODEL line from the netlist.
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
virtual bool loadDAEVectors(double *solVec, double *fVec, double *qVec, double *bVec, double *storeLeadF, double *storeLeadQ, double *leadF, double *leadQ, double *junctionV)
Populates the device's ExternData object with these pointers.
Definition: N_DEV_ROM.C:1636
virtual bool loadDAEMatrices(Linear::Matrix &dFdx, Linear::Matrix &dQdx)
Populates the device's Jacobian object with these pointers.
Definition: N_DEV_ROM.C:1688
std::vector< Param > params
Linear::Matrix * dQdxMatrixPtr
std::vector< int > ROMEqu_B_NodeOffset
Definition: N_DEV_ROM.h:195
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Citer, const FactoryBlock &factory_block)
Definition: N_DEV_ROM.C:137
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_ROM.C:91
const SolverState & getSolverState() const
Returns the solver state given during device construction.
void setModParams(const std::vector< Param > &params)
std::vector< int > li_ROM
Definition: N_DEV_ROM.h:187
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
Definition: N_DEV_ROM.C:1395
std::vector< int > ROMEqu_G_NodeOffset
Definition: N_DEV_ROM.h:199
std::vector< double > Bhat
Definition: N_DEV_ROM.h:165
std::vector< double > A2
Definition: N_DEV_ROM.h:176