Xyce  6.1
N_DEV_PowerGridGenBus.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_PowerGridGenBus.C,v $
27 //
28 // Purpose : PowerGrid classes: provides a device that calculates the
29 // steady state power flow from an Ideal Generator Bus.
30 // This device has a fixed output power (P) and a fixed
31 // voltage magnitude (VM).
32 //
33 // Special Notes : Experimental new device for an LDRD.
34 //
35 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
36 //
37 // Creation Date : 12/9/14
38 //
39 // Revision Information:
40 // ---------------------
41 //
42 // Revision Number: $Revision: 1.9 $
43 //
44 // Revision Date : $Date: 2015/11/04 23:02:39 $
45 //
46 // Current Owner : $Author: peshola $
47 //----------------------------------------------------------------------------
48 
49 #include <Xyce_config.h>
50 
51 
52 // ---------- Standard Includes ----------
53 
54 // ---------- Xyce Includes ----------
55 #include <N_DEV_PowerGridGenBus.h>
56 #include <N_DEV_Const.h>
57 #include <N_DEV_DeviceOptions.h>
58 #include <N_DEV_DeviceMaster.h>
59 #include <N_DEV_ExternData.h>
60 #include <N_DEV_MatrixLoadData.h>
61 #include <N_DEV_Message.h>
62 #include <N_DEV_SolverState.h>
63 
64 #include <N_LAS_Matrix.h>
65 #include <N_LAS_Vector.h>
66 
67 #include <N_UTL_ExtendedString.h>
68 #include <N_UTL_FeatureTest.h>
69 #include <N_UTL_IndentStreamBuf.h>
70 
71 namespace Xyce {
72 namespace Device {
73 namespace PowerGridGenBus {
74 
75 // enables debug output for just this device
76 //static const int DEBUG_DEVICE = 1;
77 
79 {
80  p.addPar("AT", std::string("PQP"), &PowerGridGenBus::Instance::analysisTypeStr_)
81  .setUnit(U_NONE)
82  .setDescription("Analysis Type");
83 
85  .setExpressionAccess(ParameterType::TIME_DEP)
86  .setUnit(U_PERUNIT)
87  .setDescription("Generator Output Power");
88 
90  .setExpressionAccess(ParameterType::TIME_DEP)
91  .setUnit(U_PERUNIT)
92  .setDescription("Voltage Magnitude");
93 
95  .setExpressionAccess(ParameterType::TIME_DEP)
96  .setUnit(U_PERUNIT)
97  .setDescription("Reactive Power Max Limit");
98 
100  .setExpressionAccess(ParameterType::TIME_DEP)
101  .setUnit(U_PERUNIT)
102  .setDescription("Reactive Power Min Limit");
103 
105  .setExpressionAccess(ParameterType::TIME_DEP)
106  .setUnit(U_NONE)
107  .setDescription("Q-Limit Enforcement Delay");
108 }
109 
111 {}
112 
113 
114 
115 std::vector< std::vector<int> > Instance::jacStamp;
116 
117 // Class Instance
118 //-----------------------------------------------------------------------------
119 // Function : Instance::Instance
120 // Purpose : "instance block" constructor
121 // Special Notes :
122 // Scope : public
123 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
124 // Creation Date : 12/9/14
125 //-----------------------------------------------------------------------------
127  const Configuration & configuration,
128  const InstanceBlock & IB,
129  Model & Miter,
130  const FactoryBlock & factory_block)
131  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
132  model_(Miter),
133  analysisTypeStr_("PQP"),
134  analysisType_(PQP),
135  power_(1.0),
136  VMag_(1.0),
137  QMax_(1.0),
138  QMin_(0.0),
139  QMaxGiven_(false),
140  QMinGiven_(false),
141  QLimitEnforceDelay_(0),
142  holdQatLower_(false),
143  holdQatUpper_(false)
144 {
145  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
146  {
147  Xyce::dout() << std::endl << "In device constructor for " << getName() << std::endl;
148  }
149 
150  std::vector<Param>::const_iterator iter = IB.params.begin();
151  std::vector<Param>::const_iterator last = IB.params.end();
152 
153  for ( ; iter != last; ++iter)
154  {
155  const std::string & tmpname = iter->tag();
156  const bool & tmpgiven = iter->given();
157 
158  // copy instance parameter values into private variables
159  if (tmpname == "AT" && tmpgiven == true)
160  {
161  ExtendedString atStr(iter->stringValue());
162  atStr.toUpper();
163  if ( atStr == "IV" )
164  {
165  // temporary error message since only PQP format works for the Generator Bus
166  // model in Xyce 6.4
167  UserError0(*this) << "Only PQP Analysis Type is supported for PowerGridGenBus device: " << getName();
168  analysisType_ = IV;
169  analysisTypeStr_ = "IV";
170  }
171  else if ( atStr == "PQR" )
172  {
173  // temporary error message since only PQP format works for the Generator Bus
174  // model in Xyce 6.4
175  UserError0(*this) << "Only PQP Analysis Type is supported for PowerGridGenBus device: " << getName();
176  analysisType_ = PQR;
177  analysisTypeStr_ = "PQR";
178  }
179  else if ( atStr == "PQP" )
180  {
181  analysisType_ = PQP;
182  analysisTypeStr_ = "PQP";
183  }
184  // these are for test purposes for development, and were made "not reachable" for the
185  // Xyce 6.4 release code. The code for DVS, VCS, CCS and RCB is not commented out in
186  // subsequent functions since those "analysis types" will error-out in the constructor.
187  //else if ( iter->stringValue() == "DVS" )
188  //{
189  // analysisType_ = DVS;
190  // analysisTypeStr_ = "DVS";
191  //}
192  //else if ( iter->stringValue() == "VCS" )
193  //{
194  // analysisType_ = VCS;
195  // analysisTypeStr_ = "VCS";
196  // }
197  //else if ( iter->stringValue() == "CCS" )
198  //{
199  // analysisType_ = CCS;
200  // analysisTypeStr_ = "CCS";
201  //}
202  //else if ( iter->stringValue() == "RCB" )
203  //{
204  // analysisType_ = RCB;
205  // analysisTypeStr_ = "RCB";
206  //}
207  else
208  {
209  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
210  }
211  }
212  if (tmpname == "VM" && tmpgiven == true)
213  {
214  VMag_ = iter->getImmutableValue<double>();
215  }
216  if (tmpname == "P" && tmpgiven == true)
217  {
218  power_ = iter->getImmutableValue<double>();
219  }
220  if (tmpname == "QMAX" && tmpgiven == true)
221  {
222  QMax_ = iter->getImmutableValue<double>();
223  QMaxGiven_ = true;
224  }
225  if (tmpname == "QMIN" && tmpgiven == true)
226  {
227  QMin_ = iter->getImmutableValue<double>();
228  QMinGiven_ = true;
229  }
230  if (tmpname == "QLED" && tmpgiven == true)
231  {
232  QLimitEnforceDelay_ = iter->getImmutableValue<int>();
233  }
234  }
235 
236  if ( analysisType_ == DVS || analysisType_ == IV || analysisType_ == PQR ||
238  {
239  numIntVars = 2;
240  numExtVars = 4;
241  numStateVars = 0;
242  }
243  else if (analysisType_ == PQP || analysisType_ == CCS)
244  {
245  numIntVars = 1;
246  numExtVars = 4;
247  numStateVars = 0;
248  }
249  else
250  {
251  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
252  return;
253  }
254 
255  if( jacStamp.empty() )
256  {
257  if ( analysisType_ == DVS || analysisType_ == IV )
258  {
259  jacStamp.resize(6);
260  jacStamp[0].resize(1);
261  jacStamp[1].resize(1);
262  jacStamp[2].resize(1);
263  jacStamp[3].resize(1);
264  jacStamp[4].resize(2);
265  jacStamp[5].resize(2);
266 
267  jacStamp[0][0] = 4;
268  jacStamp[1][0] = 4;
269  jacStamp[2][0] = 5;
270  jacStamp[3][0] = 5;
271  jacStamp[4][0] = 0;
272  jacStamp[4][1] = 1;
273  jacStamp[5][0] = 2;
274  jacStamp[5][1] = 3;
275  }
276  else if (analysisType_ == VCS )
277  { // this is for test purposes. It is a voltage-current source, where the branch current
278  // is a solution variable. The VCS code is not reachable in the Xyce 6.4 release code.
279  jacStamp.resize(6);
280  jacStamp[0].resize(1);
281  jacStamp[1].resize(1);
282  jacStamp[2].resize(1);
283  jacStamp[3].resize(1);
284  jacStamp[4].resize(2);
285  jacStamp[5].resize(1);
286 
287  jacStamp[0][0] = 4;
288  jacStamp[1][0] = 4;
289  jacStamp[2][0] = 5;
290  jacStamp[3][0] = 5;
291  jacStamp[4][0] = 0;
292  jacStamp[4][1] = 1;
293  jacStamp[5][0] = 5;
294  }
295  else if (analysisType_ == PQR)
296  {
297  jacStamp.resize(6);
298  jacStamp[0].resize(1);
299  jacStamp[1].resize(1);
300  jacStamp[2].resize(3);
301  jacStamp[3].resize(3);
302  jacStamp[4].resize(2);
303  jacStamp[5].resize(2);
304 
305  jacStamp[0][0] = 4;
306  jacStamp[1][0] = 4;
307  jacStamp[2][0] = 0;
308  jacStamp[2][1] = 1;
309  jacStamp[2][2] = 5;
310  jacStamp[3][0] = 0;
311  jacStamp[3][1] = 1;
312  jacStamp[3][2] = 5;
313  jacStamp[4][0] = 0;
314  jacStamp[4][1] = 1;
315  jacStamp[5][0] = 2;
316  jacStamp[5][1] = 3;
317  }
318  else if (analysisType_ == PQP )
319  {
320  jacStamp.resize(5);
321  jacStamp[2].resize(1);
322  jacStamp[3].resize(1);
323  jacStamp[4].resize(3);
324 
325  jacStamp[2][0] = 4;
326  jacStamp[3][0] = 4;
327  jacStamp[4][0] = 2;
328  jacStamp[4][1] = 3;
329  jacStamp[4][2] = 4;
330  }
331  else if (analysisType_ == CCS )
332  { // This is for test purposes. It is a current-current source, where the branch current is a
333  // solution variable. The CCS code is not reachable in the Xyce 6.4 release code.
334  jacStamp.resize(5);
335  jacStamp[2].resize(1);
336  jacStamp[3].resize(1);
337  jacStamp[4].resize(1);
338 
339  jacStamp[2][0] = 4;
340  jacStamp[3][0] = 4;
341  jacStamp[4][0] = 4;
342  }
343  else if (analysisType_ == RCB )
344  {
345  //This is for test purposes. It is a prototype of a remote controlled bus. This device
346  // is not functional yet. The RCB code is not reachable in the Xyce 6.4 release code.
347  jacStamp.resize(6);
348  jacStamp[0].resize(1);
349  jacStamp[1].resize(1);
350  jacStamp[4].resize(2);
351  jacStamp[5].resize(2);
352 
353  jacStamp[0][0] = 4;
354  jacStamp[1][0] = 4;
355  jacStamp[4][0] = 0;
356  jacStamp[4][1] = 1;
357  jacStamp[5][0] = 2;
358  jacStamp[5][1] = 3;
359  }
360  }
361 
362  // Set params to constant default values:
363  setDefaultParams ();
364 
365  // Set params according to instance line and constant defaults from metadata:
366  setParams (IB.params);
367 
368  // Set any non-constant parameter defaults:
369 
370 }
371 
372 //-----------------------------------------------------------------------------
373 // Function : Instance::~Instance
374 // Purpose : destructor
375 // Special Notes :
376 // Scope : public
377 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
378 // Creation Date : 12/9/14
379 //-----------------------------------------------------------------------------
381 {
382 }
383 
384 //-----------------------------------------------------------------------------
385 // Function : Instance::registerLIDs
386 // Purpose :
387 // Special Notes :
388 // Scope : public
389 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
390 // Creation Date : 9/12/14
391 //-----------------------------------------------------------------------------
392 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
393  const std::vector<int> & extLIDVecRef )
394 {
395  AssertLIDs(intLIDVecRef.size() == numIntVars);
396  AssertLIDs(extLIDVecRef.size() == numExtVars);
397 
398  // copy over the global ID lists.
399  intLIDVec = intLIDVecRef;
400  extLIDVec = extLIDVecRef;
401 
402  // These if-else blocks may be made into separate classes,
403  // in the final version of this model.
404  if ( analysisType_ == DVS || analysisType_ == VCS || analysisType_ == IV)
405  {
406  li_VR1 = extLIDVec[0];
407  li_VR2 = extLIDVec[1];
408  li_VI1 = extLIDVec[2];
409  li_VI2 = extLIDVec[3];
410  li_BranCurrR = intLIDVec[0];
411  li_BranCurrI = intLIDVec[1];
412 
413  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
414  {
415  Xyce::dout() << getName() << " LIDs"
416  << Util::push << std::endl
417  << "li_VR1 = " << li_VR1 << std::endl
418  << "li_VI1 = " << li_VI1 << std::endl
419  << "li_VR2 = " << li_VR2 << std::endl
420  << "li_VI2 = " << li_VI2 << std::endl
421  << "li_BranCurrR = " << li_BranCurrR << std::endl
422  << "li_BranCurrI = " << li_BranCurrI << std::endl
423  << std::endl;
424  }
425  }
426  else if ( analysisType_ == PQR)
427  {
428  li_VR1 = extLIDVec[0];
429  li_VR2 = extLIDVec[1];
430  li_VI1 = extLIDVec[2];
431  li_VI2 = extLIDVec[3];
432  li_BranCurrP = intLIDVec[0];
433  li_BranCurrQ = intLIDVec[1];
434 
435  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
436  {
437  Xyce::dout() << getName() << " LIDs"
438  << Util::push << std::endl
439  << "li_VR1 = " << li_VR1 << std::endl
440  << "li_VI1 = " << li_VI1 << std::endl
441  << "li_VR2 = " << li_VR2 << std::endl
442  << "li_VI2 = " << li_VI2 << std::endl
443  << "li_BranCurrP = " << li_BranCurrP << std::endl
444  << "li_BranCurrQ = " << li_BranCurrQ << std::endl
445  << std::endl;
446  }
447  }
448  else if (analysisType_ == PQP || analysisType_ == CCS)
449  {
450  li_Theta1 = extLIDVec[0];
451  li_Theta2 = extLIDVec[1];
452  li_VM1 = extLIDVec[2];
453  li_VM2 = extLIDVec[3];
454  li_BranCurrQ = intLIDVec[0];
455 
456  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
457  {
458  Xyce::dout() << getName() << " LIDs"
459  << Util::push << std::endl
460  << "li_Theta1 = " << li_Theta1 << std::endl
461  << "li_VM1 = " << li_VM1 << std::endl
462  << "li_Theta2 = " << li_Theta2 << std::endl
463  << "li_VM2 = " << li_VM2 << std::endl
464  << "li_BranCurrQ = " << li_BranCurrQ << std::endl
465  << std::endl;
466  }
467  }
468  else if (analysisType_ == RCB)
469  {
470  li_Theta1 = extLIDVec[0];
471  li_Theta2 = extLIDVec[1];
472  li_VM1 = extLIDVec[2];
473  li_VM2 = extLIDVec[3];
474  li_BranCurrP = intLIDVec[0];
475  li_BranCurrQ = intLIDVec[1];
476  }
477  else
478  {
479  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
480  return;
481  }
482 }
483 
484 //-----------------------------------------------------------------------------
485 // Function : Instance::loadNodeSymbols
486 // Purpose :
487 // Special Notes :
488 // Scope : public
489 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
490 // Creation Date : 05/13/05
491 //-----------------------------------------------------------------------------
492 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
493 {
494  // These if-else blocks may be made into separate classes,
495  // in the final version of this model
496  if ( analysisType_ == DVS || analysisType_ == VCS || analysisType_ == IV )
497  {
498  addInternalNode(symbol_table, li_BranCurrR, getName(), "BranchCurrR");
499  addInternalNode(symbol_table, li_BranCurrI, getName(), "BranchCurrI");
500  }
501  else if ( analysisType_ == PQR || analysisType_ == RCB )
502  {
503  addInternalNode(symbol_table, li_BranCurrP, getName(), "BranchCurrP");
504  addInternalNode(symbol_table, li_BranCurrQ, getName(), "BranchCurrQ");
505  }
506  else if ( analysisType_ == PQP || analysisType_ == CCS)
507  {
508  addInternalNode(symbol_table, li_BranCurrQ, getName(), "BranchCurrQ");
509  }
510  else
511  {
512  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
513  return;
514  }
515 }
516 
517 //-----------------------------------------------------------------------------
518 // Function : Instance::registerStateLIDs
519 // Purpose : Set up offsets so we can store quantities that need to be
520 // differentiated.
521 // Special Notes :
522 // Scope : public
523 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
524 // Creation Date : 9/12/14
525 //-----------------------------------------------------------------------------
526 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef )
527 {
528  AssertLIDs(staLIDVecRef.size() == numStateVars);
529 }
530 
531 //-----------------------------------------------------------------------------
532 // Function : Instance::jacobianStamp
533 // Purpose :
534 // Special Notes :
535 // Scope : public
536 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
537 // Creation Date : 08/20/01
538 //-----------------------------------------------------------------------------
539 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
540 {
541  return jacStamp;
542 }
543 
544 //-----------------------------------------------------------------------------
545 // Function : Instance::registerJacLIDs
546 // Purpose :
547 // Special Notes :
548 // Scope : public
549 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
550 // Creation Date : 09/12/14
551 //-----------------------------------------------------------------------------
552 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
553 {
554  DeviceInstance::registerJacLIDs( jacLIDVec );
555 
556  // // These if-else blocks may be made into separate classes,
557  // in the final version of this model
558  if (analysisType_ == DVS || analysisType_ == IV )
559  {
560  VR1_IR_Offset = jacLIDVec[0][0];
561  VR2_IR_Offset = jacLIDVec[1][0];
562  VI1_II_Offset = jacLIDVec[2][0];
563  VI2_II_Offset = jacLIDVec[3][0];
564 
565  IR_VR1_Offset = jacLIDVec[4][0];
566  IR_VR2_Offset = jacLIDVec[4][1];
567  II_VI1_Offset = jacLIDVec[5][0];
568  II_VI2_Offset = jacLIDVec[5][1];
569 
570  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
571  {
572  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
573  << "VR offsets are (" << VR1_IR_Offset << " , " << VR2_IR_Offset << ")" << std::endl
574  << "VI offsets are (" << VI1_II_Offset << " , " << VI1_II_Offset << ")" << std::endl
575  << "IR offsets are (" << IR_VR1_Offset << " , " << IR_VR2_Offset << ")" << std::endl
576  << "II offsets are (" << II_VI1_Offset << " , " << II_VI2_Offset << ")" << std::endl
577  << std::endl;
578  }
579  }
580  else if (analysisType_ == VCS)
581  { // This is for test purposes. It is a voltage-current source, where the branch current is
582  // a solution variable for the current source.
583  VR1_IR_Offset = jacLIDVec[0][0];
584  VR2_IR_Offset = jacLIDVec[1][0];
585  VI1_II_Offset = jacLIDVec[2][0];
586  VI2_II_Offset = jacLIDVec[3][0];
587 
588  IR_VR1_Offset = jacLIDVec[4][0];
589  IR_VR2_Offset = jacLIDVec[4][1];
590  II_II_Offset = jacLIDVec[5][0];
591 
592  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
593  {
594  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
595  << "VR offsets are (" << VR1_IR_Offset << " , " << VR2_IR_Offset << ")" << std::endl
596  << "VI offsets are (" << VI1_II_Offset << " , " << VI1_II_Offset << ")" << std::endl
597  << "IR offsets are (" << IR_VR1_Offset << " , " << IR_VR2_Offset << ")" << std::endl
598  << "II offsets are (" << II_VI1_Offset << " , " << II_VI2_Offset << ")" << std::endl
599  << std::endl;
600  }
601  }
602  else if (analysisType_ == PQR)
603  {
604  VR1_P_Offset = jacLIDVec[0][0];
605  VR2_P_Offset = jacLIDVec[1][0];
606  VI1_VR1_Offset = jacLIDVec[2][0];
607  VI1_VR2_Offset = jacLIDVec[2][1];
608  VI1_Q_Offset = jacLIDVec[2][2];
609  VI2_VR1_Offset = jacLIDVec[3][0];
610  VI2_VR2_Offset = jacLIDVec[3][1];
611  VI2_Q_Offset = jacLIDVec[3][2];
612 
613  P_VR1_Offset = jacLIDVec[4][0];
614  P_VR2_Offset = jacLIDVec[4][1];
615  Q_VI1_Offset = jacLIDVec[5][0];
616  Q_VI2_Offset = jacLIDVec[5][1];
617 
618  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
619  {
620  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
621  << "VR offsets are (" << VR1_P_Offset << " , " << VR2_P_Offset << ")" << std::endl
622  << "VI offsets are (" << VI1_Q_Offset << " , " << VI1_Q_Offset << ")" << std::endl
623  << "IR offsets are (" << P_VR1_Offset << " , " << P_VR2_Offset << ")" << std::endl
624  << "II offsets are (" << Q_VI1_Offset << " , " << Q_VI2_Offset << ")" << std::endl
625  << std::endl;
626  }
627  }
628  else if (analysisType_ == PQP)
629  {
630  VM1_Q_Offset = jacLIDVec[2][0];
631  VM2_Q_Offset = jacLIDVec[3][0];
632 
633  Q_VM1_Offset = jacLIDVec[4][0];
634  Q_VM2_Offset = jacLIDVec[4][1];
635  Q_Q_Offset = jacLIDVec[4][2];
636 
637  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
638  {
639  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
640  << "VM offsets are (" << VM1_Q_Offset << " , " << VM2_Q_Offset << ")" << std::endl
641  << "Q offsets are (" << Q_VM1_Offset << " , " << Q_VM2_Offset
642  << " , " << Q_Q_Offset << ")" << std::endl << std::endl;
643  }
644  }
645  else if (analysisType_ == CCS)
646  { // This is for test purposes. It is a current-current source, where the branch current is
647  // a solution variable.
648  VM1_Q_Offset = jacLIDVec[2][0];
649  VM2_Q_Offset = jacLIDVec[3][0];
650 
651  Q_Q_Offset = jacLIDVec[4][0];
652 
653  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
654  {
655  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
656  << "VM offsets are (" << VM1_Q_Offset << " , " << VM2_Q_Offset << ")" << std::endl
657  << "Q offsets are (" << Q_Q_Offset << ")" << std::endl
658  << std::endl;
659  }
660  }
661  else if (analysisType_ == RCB)
662  {
663  Th1_P_Offset = jacLIDVec[0][0];
664  Th2_P_Offset = jacLIDVec[1][0];
665  P_Th1_Offset = jacLIDVec[4][0];
666  P_Th2_Offset = jacLIDVec[4][1];
667  Q_VM1_Offset = jacLIDVec[5][0];
668  Q_VM2_Offset = jacLIDVec[5][1];
669  }
670 }
671 
672 //-----------------------------------------------------------------------------
673 // Function : Instance::updateIntermediateVars
674 // Purpose : update intermediate variables for one diode instance
675 // Special Notes :
676 // Scope : public
677 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
678 // Creation Date : 9/12/14
679 //-----------------------------------------------------------------------------
681 {
682  double * solVec = extData.nextSolVectorRawPtr;
683 
684  // These if-else blocks may be made into separate classes,
685  // in the final version of this model
686  if (analysisType_ == DVS || analysisType_ == VCS || analysisType_ == IV)
687  {
688  VR1 = solVec[li_VR1];
689  VR2 = solVec[li_VR2];
690  VI1 = solVec[li_VI1];
691  VI2 = solVec[li_VI2];
692 
693  Bran_CurrR = solVec[li_BranCurrR];
694  Bran_CurrI = solVec[li_BranCurrI];
695 
696  srcDropR = VR1 - VR2;
697  srcBCR = VMag_;
699 
700  srcDropI = VI1 - VI2;
701  srcBCI = VMag_;
703  }
704  else if (analysisType_ == PQR)
705  {
706  // implement P as a current source, which means it has no state
707 
708  // VI will be implmented as voltage source that depends on VR
709  VR1 = solVec[li_VR1];
710  VR2 = solVec[li_VR2];
711  VI1 = solVec[li_VI1];
712  VI2 = solVec[li_VI2];
713 
714  Bran_CurrP = solVec[li_BranCurrR];
715  Bran_CurrQ = solVec[li_BranCurrI];
716 
717  srcDropR = VR1 - VR2;
718  srcDropI = VI1 - VI2;
719 
720  // enforce Voltage Magnitude constraint
721  if (srcDropR > VMag_)
722  {
723  srcBCR = VMag_;
724  srcBCI = 0;
725  }
726  else if (-srcDropR > VMag_)
727  {
728  srcBCR = -VMag_;
729  srcBCI = 0;
730  }
731  else
732  {
733  srcBCR = srcDropR;
734  double signVal = (srcBCI < 0) ? -1.0 : 1.0;
735  srcBCI = signVal * sqrt( VMag_*VMag_ - srcDropR * srcDropR);
736  }
737 
740 
741  /*if (Bran_CurrQ > QMax_)
742  {
743  reactPower_ = QMax_;
744  }
745  else if (Bran_CurrQ < QMin_)
746  {
747  reactPower_ = QMin_;
748  }
749  else
750  {
751  reactPower_ = Bran_CurrQ;
752  }*/
753 
754  /*Q1 = Bran_CurrQ;
755  if (Q1 < -QMax_)
756  {
757  Q1 = -QMax_;
758  }
759  else if (Q1 > -QMin_)
760  {
761  Q1 = -QMin_;
762  }
763  else
764  { // Q is within limits. So, enforce the voltage magnitude constraint
765 
766  }
767 
768  Q2 = -Q1;*/
769  }
770  else if (analysisType_ == PQP)
771  {
772  // implement P as a current source, which means it has no state
773 
774  // implement VM as a voltage source
775  VM1 = solVec[li_VM1];
776  VM2 = solVec[li_VM2];
777  Bran_CurrQ = solVec[li_BranCurrQ];
778  if ( getSolverState().newtonIter > QLimitEnforceDelay_ )
779  {
780  if ( (Bran_CurrQ > QMax_) && QMaxGiven_ )
781  {
782  holdQatUpper_ = true;
783  }
784  else if ( (Bran_CurrQ < QMin_) && QMinGiven_ )
785  {
786  holdQatLower_ = true;
787  }
788  }
789 
790  //Xyce::dout() << getName() << ": Bran_CurrQ and NewtIter in UpdateIntermediate State is: " << Bran_CurrQ
791  // << " and " << getSolverState().newtonIter << std::endl;
792 
793  srcDropVM = VM1 - VM2;
794  srcBCVM = VMag_;
796  }
797  else if (analysisType_ == CCS)
798  { // this is for test purposes. It is a current-current source.
799  // implement P as a current source, which means it has no state
800 
801  // implement a current source with the branch current as a solution variable.
802  Bran_CurrQ = solVec[li_BranCurrQ];
803  }
804  else if (analysisType_ == RCB)
805  {
806  // implement VM as a voltage source
807  Th1 = solVec[li_Theta1];
808  Th2 = solVec[li_Theta2];
809  VM1 = solVec[li_VM1];
810  VM2 = solVec[li_VM2];
811  Bran_CurrP = solVec[li_BranCurrP];
812 
813  srcDropTh = Th1 - Th1;
814  srcDropVM = VM1 - VM2;
815  srcBCVM = VMag_;
816  }
817  else
818  {
819  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
820  return false;
821  }
822 
823  return true;
824 }
825 
826 //-----------------------------------------------------------------------------
827 // Function : Instance::updatePrimaryState
828 // Purpose :
829 // Special Notes :
830 // Scope : public
831 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
832 // Creation Date : 9/12/14
833 //-----------------------------------------------------------------------------
835 {
836  return updateIntermediateVars ();
837 }
838 
839 //-----------------------------------------------------------------------------
840 // Function : Instance::loadDAEFVector
841 //
842 // Purpose : Loads the F-vector contributions
843 //
844 // Special Notes :
845 //
846 //
847 // Scope : public
848 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
849 // Creation Date : 9/12/14
850 //-----------------------------------------------------------------------------
852 {
853  double * fVec = extData.daeFVectorRawPtr;
854 
855  // These if-else blocks may be made into separate classes,
856  // in the final version of this model
857  if (analysisType_ == DVS || analysisType_ == IV)
858  {
859  fVec[li_VR1] += Bran_CurrR;
860  fVec[li_VR2] -= Bran_CurrR;
861  fVec[li_VI1] += Bran_CurrI;
862  fVec[li_VI2] -= Bran_CurrI;
863 
864  fVec[li_BranCurrR] += srcDropR;
865  fVec[li_BranCurrI] += srcDropI;
866  }
867  else if (analysisType_ == VCS )
868  {
869  fVec[li_VR1] += Bran_CurrR;
870  fVec[li_VR2] -= Bran_CurrR;
871  fVec[li_VI1] -= Bran_CurrI;
872  fVec[li_VI2] += Bran_CurrI;
873 
874  fVec[li_BranCurrR] += srcDropR;
875  fVec[li_BranCurrI] += Bran_CurrI;
876  }
877  else if (analysisType_ == PQR)
878  {
879  fVec[li_VR1] -= power_;
880  fVec[li_VR2] += power_;
881  fVec[li_VI1] -= Bran_CurrQ;
882  fVec[li_VI2] += Bran_CurrQ;
883 
884  fVec[li_BranCurrP] -= srcDropR;
885  fVec[li_BranCurrP] += srcBCR;
886 
887  fVec[li_BranCurrQ] -= srcDropI;
888  fVec[li_BranCurrQ] += srcBCI;
889 
890  Xyce::dout() << getName() << ": F Vector Load info is (P,Q): (" << power_ << ","
891  << Bran_CurrQ << ")" << std::endl
892  << " (srcDropR,srcBCR,srcDropI,srcBCI: ("
893  << srcDropR << "," << srcBCR << "," <<srcDropI << ","
894  << srcBCI << ")"<< std::endl << std::endl
895  << " Solution Vector Currents are (P,Q): (" << Bran_CurrP << ","
896  << Bran_CurrQ << ")" << std::endl
897  << " (VR1,VR2,VI1,VI2): ("
898  << VR1 << "," << VR2 << "," << VI1 << ","
899  << VI2 << ")"<< std::endl << std::endl;
900  //fVec[li_VR1] += P1;
901  //fVec[li_VR2] += P2;
902  //fVec[li_VI1] += Q1;
903  //fVec[li_VI2] += Q2;
904  }
905  else if (analysisType_ == PQP)
906  {
907  // initial version does not have reactive power limiting.
908 
909  // implement P as a current source, which means it has no F-Vector contribution.
910  // Note though that the P is a generator. So, the current polarity is reversed from
911  // a normal Xyce current source, as explained below. The polarity difference is
912  // accounted for in the loadDAEBVector() function.
913 
914 
915  // implement VM as a voltage source, when we're inside of the Q limits. Implement a current source
916  // for the VM terminals, otherwise. This device is a generator. So, the current polarities on the
917  // branch current contributions, fVec[li_VM1] and fVec[li_VM2], are reversed in both cases from a
918  // normal Xyce voltage source. Also note that the dFdx[li_VM1][VM1_Q_Offset] and
919  // dFdx[li_VM2][VM2_Q_Offset] terms in the dFdX equations in loadDAEdFdx () are also reversed
920  // from a normal Xyce voltage source. For a Xyce voltage source, "positive current" flows
921  // from the positive node through the source to the negative node. For a Power Grid generator
922  // (like this device), the convention is that positive reactive power (Q) flows into the power
923  // grid from the positive VM terminal. A similar convention holds for the real power (P) flow
924  // from the positive Theta terminal.
926  {
927  // Outside of the Q limits. So, implement a current source with the branch current as a
928  // solution variable, since the jacStamp has to remain the same size. Reverse the signs though
929  // on the voltage terms since it's a generator, and positive power flows out of the positive (VM1)
930  // terminal.
931  fVec[li_VM1] -= Bran_CurrQ;
932  fVec[li_VM2] += Bran_CurrQ;
933  fVec[li_BranCurrQ] += Bran_CurrQ;
934 
935  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
936  {
937  Xyce::dout() << getName() << ": F Vector Load info is (Q,QMax,Qmin): (" << Bran_CurrQ <<
938  "," << QMax_ << "," << QMin_ << ")" << std::endl << std::endl;
939  }
940  }
941  else
942  {
943  // implement as a voltage source, since we're were within the Q limits. Again, the signs on
944  // VM terms are reversed since positive power flows out of the positive (VM1) terminal.
945  fVec[li_VM1] -= Bran_CurrQ;
946  fVec[li_VM2] += Bran_CurrQ;
947  if (DEBUG_DEVICE && isActive(Diag::DEVICE_LOAD_VECTOR))
948  {
949  Xyce::dout() << "Bran_CurrQ = " << Bran_CurrQ << std::endl;
950  }
951 
952  fVec[li_BranCurrQ] += srcDropVM;
953 
954  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
955  {
956  Xyce::dout() << getName() << ": F Vector Load info is (P,Q,srcDropVM,srcBCVM): (" << power_ << " , "
957  << Bran_CurrQ << " , " << srcDropVM << " , " << srcBCVM << ")" << std::endl << std::endl;
958  }
959  }
960  }
961  else if (analysisType_ == CCS)
962  { // for test purposes
963  fVec[li_VM1] -= Bran_CurrQ;
964  fVec[li_VM2] += Bran_CurrQ;
965  fVec[li_BranCurrQ] += Bran_CurrQ;
966  }
967  else if (analysisType_ == RCB)
968  {
969  fVec[li_Theta1] -= Bran_CurrP;
970  fVec[li_Theta2] += Bran_CurrP;
971  fVec[li_BranCurrP] += srcDropTh;
972  fVec[li_BranCurrQ] += srcDropVM;
973  }
974  else
975  {
976  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
977  return false;
978  }
979 
980  if (getSolverState().dcopFlag)
981  {
982  // no op placeholder
983  }
984  else
985  {
986  // no op placeholder
987  }
988 
989  return true;
990 }
991 
992 //-----------------------------------------------------------------------------
993 // Function : Instance::loadDAEBVector
994 //
995 // Purpose : Loads the B-vector contributions for a single
996 // vsrc instance.
997 //
998 // Special Notes :
999 //
1000 // Scope : public
1001 // Creator : Eric Keiter, SNL
1002 // Creation Date :
1003 //-----------------------------------------------------------------------------
1005 {
1006  double * bVec = extData.daeBVectorRawPtr;
1007 
1008  // These if-else blocks may be made into separate classes,
1009  // in the final version of this model
1010  if (analysisType_ == DVS || analysisType_ == IV )
1011  {
1012  bVec[li_BranCurrR] += srcBCR;
1013  bVec[li_BranCurrI] += srcBCI;
1014  }
1015  else if (analysisType_ == VCS)
1016  { // for test purposes. A voltage-current source
1017  bVec[li_BranCurrR] += srcBCR;
1018  bVec[li_BranCurrI] += power_;
1019  }
1020  else if (analysisType_ == PQR)
1021  {
1022  bVec[li_BranCurrR] -= srcBCR;
1023  bVec[li_BranCurrI] -= srcBCI;
1024  }
1025  else if (analysisType_ == PQP)
1026  {
1027  // current source for P. Note the P is a generator. So, the current polarity for
1028  // the bVec[li_Theta1] and bVec[li_Theta2] contributions are reversed from a normal Xyce
1029  // current source. The comments for the loadDAEFVector() function provide more explanation.
1030  bVec[li_Theta1] += power_;
1031  bVec[li_Theta2] -= power_;
1032 
1033  // Implement a current source for Q, if we're outside of one of the Q limits.
1034  if (holdQatUpper_ )
1035  {
1036  bVec[li_BranCurrQ] += QMax_;
1037  }
1038  else if (holdQatLower_)
1039  {
1040  bVec[li_BranCurrQ] += QMin_;
1041  }
1042  else
1043  {
1044  // implement as a voltage source for VM since we're were within the Q limits
1045  bVec[li_BranCurrQ] += srcBCVM;
1046  }
1047  }
1048  else if (analysisType_ == CCS)
1049  { // for test purposes. A current-current source
1050  bVec[li_Theta1] += power_;
1051  bVec[li_Theta2] -= power_;
1052  bVec[li_BranCurrQ] += power_;
1053  }
1054  else if (analysisType_ == RCB)
1055  {
1056  bVec[li_BranCurrQ] += srcBCVM;
1057  }
1058  else
1059  {
1060  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
1061  return false;
1062  }
1063 
1064  return true;
1065 }
1066 
1067 //-----------------------------------------------------------------------------
1068 // Function : Instance::loadDAEdFdx ()
1069 //
1070 // Purpose : Loads the F-vector contributions
1071 //
1072 // Special Notes :
1073 //
1074 // Scope : public
1075 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
1076 // Creation Date : 9/12/14
1077 //-----------------------------------------------------------------------------
1079 {
1080  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
1081 
1082  // These if-else blocks may be made into separate classes,
1083  // in the final version of this model
1084  if (analysisType_ == DVS || analysisType_ == IV)
1085  {
1086  dFdx[li_VR1][VR1_IR_Offset] += 1.0;
1087  dFdx[li_VR2][VR2_IR_Offset] -= 1.0;
1088  dFdx[li_VI1][VI1_II_Offset] += 1.0;
1089  dFdx[li_VI2][VI2_II_Offset] -= 1.0;
1090 
1091  dFdx[li_BranCurrR][IR_VR1_Offset] += 1.0;
1092  dFdx[li_BranCurrR][IR_VR2_Offset] -= 1.0;
1093  dFdx[li_BranCurrI][II_VI1_Offset] += 1.0;
1094  dFdx[li_BranCurrI][II_VI2_Offset] -= 1.0;
1095  }
1096  else if (analysisType_ == VCS)
1097  { // for test purposes. A voltage-current source
1098  dFdx[li_VR1][VR1_IR_Offset] += 1.0;
1099  dFdx[li_VR2][VR2_IR_Offset] -= 1.0;
1100  dFdx[li_VI1][VI1_II_Offset] -= 1.0;
1101  dFdx[li_VI2][VI2_II_Offset] += 1.0;
1102 
1103  dFdx[li_BranCurrR][IR_VR1_Offset] += 1.0;
1104  dFdx[li_BranCurrR][IR_VR2_Offset] -= 1.0;
1105  dFdx[li_BranCurrI][II_II_Offset] += 1.0;
1106  }
1107  else if (analysisType_ == PQR)
1108  {
1109  dFdx[li_VR1][VR1_P_Offset] += 1.0;
1110  dFdx[li_VR2][VR2_P_Offset] -= 1.0;
1111  dFdx[li_VI1][VI1_Q_Offset] += 1.0;
1112  dFdx[li_VI2][VI2_Q_Offset] -= 1.0;
1113 
1114  // jacobiam term that come from the VMag constraint
1115  double jacTerm = (VMag_ - abs(VR1-VR2)) > 0
1116  ? (VR2 - VR1) / sqrt(VMag_*VMag_ - (VR1-VR2)*(VR1-VR2)) : 1e10*(VR2 - VR1);
1117  Xyce::dout() << "Jacobian term = " << jacTerm << std::endl;
1118  dFdx[li_VI1][VI1_VR1_Offset] += jacTerm;
1119  dFdx[li_VI1][VI1_VR2_Offset] -= jacTerm;
1120  dFdx[li_VI2][VI2_VR1_Offset] -= jacTerm;
1121  dFdx[li_VI2][VI2_VR2_Offset] += jacTerm;
1122 
1123  //Jacobian terms from the voltage drop constraints
1124  dFdx[li_BranCurrP][P_VR1_Offset] -= 1.0;
1125  dFdx[li_BranCurrP][P_VR2_Offset] += 1.0;
1126  dFdx[li_BranCurrQ][Q_VI1_Offset] -= 1.0;
1127  dFdx[li_BranCurrQ][Q_VI2_Offset] += 1.0;
1128  }
1129  else if (analysisType_ == PQP)
1130  {
1131  // P is implemented as a current source. So, there are no dFdX terms for it
1132 
1133  // VM is implemented as a voltage source. This device is a generator. So, the signs of the
1134  // dFdx[li_VM1][VM1_Q_Offset] and dFdx[li_VM2][VM2_Q_Offset] terms are reversed from that of
1135  // a normal Xyce voltage source. Also note that the signs of the branch current contributions,
1136  // fVec[li_VM1] and fVec[li_VM2], in loadDAEFVector () are also reversed from a normal Xyce
1137  // voltage source.
1139  {
1140  // Outside of the Q limits. So, this is a current-source with the branch current as a solution
1141  // variable.
1142  dFdx[li_VM1][VM1_Q_Offset] -= 1.0;
1143  dFdx[li_VM2][VM2_Q_Offset] += 1.0;
1144 
1145  dFdx[li_BranCurrQ][Q_Q_Offset] += 1.0;
1146  }
1147  else
1148  {
1149  // implement as a voltage source, since we're were within the Q limits
1150  dFdx[li_VM1][VM1_Q_Offset] -= 1.0;
1151  dFdx[li_VM2][VM2_Q_Offset] += 1.0;
1152 
1153  dFdx[li_BranCurrQ][Q_VM1_Offset] += 1.0;
1154  dFdx[li_BranCurrQ][Q_VM2_Offset] -= 1.0;
1155  }
1156  }
1157  else if (analysisType_ == CCS)
1158  { // for test purposes. A current-current souce
1159  dFdx[li_VM1][VM1_Q_Offset] -= 1.0;
1160  dFdx[li_VM2][VM2_Q_Offset] += 1.0;
1161 
1162  dFdx[li_BranCurrQ][Q_Q_Offset] += 1.0;
1163  }
1164  else if (analysisType_ == RCB)
1165  {
1166  dFdx[li_Theta1][Theta1_P_Offset] -= 1.0;
1167  dFdx[li_Theta2][Theta2_P_Offset] += 1.0;
1168 
1169  dFdx[li_BranCurrP][P_Theta1_Offset] += 1.0;
1170  dFdx[li_BranCurrP][P_Theta2_Offset] -= 1.0;
1171 
1172  dFdx[li_BranCurrQ][Q_VM1_Offset] += 1.0;
1173  dFdx[li_BranCurrQ][Q_VM2_Offset] -= 1.0;
1174  }
1175  else
1176  {
1177  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
1178  return false;
1179  }
1180 
1181  if (getSolverState().dcopFlag)
1182  {
1183  // no op placeholder code;
1184  }
1185  else
1186  {
1187  // no op placeholder code;
1188  }
1189 
1190  return true;
1191 }
1192 
1193 //-----------------------------------------------------------------------------
1194 // Function : Model::Model
1195 // Purpose : "Model block" constructor
1196 // Special Notes :
1197 // Scope : public
1198 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
1199 // Creation Date : 9/12/14
1200 //-----------------------------------------------------------------------------
1201 
1202 
1203 // These are all just placeholder functions, as there is nothing to the model
1204 // class.
1205 // Class Model
1206 
1207 //-----------------------------------------------------------------------------
1208 // Function : Model::Model
1209 // Purpose : "Model block" constructor
1210 // Special Notes :
1211 // Scope : public
1212 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
1213 // Creation Date : 9/12/14
1214 //-----------------------------------------------------------------------------
1216  const Configuration & configuration,
1217  const ModelBlock & MB,
1218  const FactoryBlock & factory_block)
1219  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
1220 {
1221 }
1222 
1223 //-----------------------------------------------------------------------------
1224 // Function : Model::~Model
1225 // Purpose : destructor
1226 // Special Notes :
1227 // Scope : public
1228 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
1229 // Creation Date : 9/12/14
1230 //-----------------------------------------------------------------------------
1232 {
1233  std::vector<Instance*>::iterator iter;
1234  std::vector<Instance*>::iterator first = instanceContainer.begin();
1235  std::vector<Instance*>::iterator last = instanceContainer.end();
1236 
1237  for (iter=first; iter!=last; ++iter)
1238  {
1239  delete (*iter);
1240  }
1241 }
1242 
1243 //-----------------------------------------------------------------------------
1244 // Function : Model::printOutInstances
1245 // Purpose : debugging tool.
1246 // Special Notes :
1247 // Scope : public
1248 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
1249 // Creation Date : 9/12/14
1250 //-----------------------------------------------------------------------------
1251 std::ostream &Model::printOutInstances(std::ostream &os) const
1252 {
1253  std::vector<Instance*>::const_iterator iter;
1254  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
1255  std::vector<Instance*>::const_iterator last = instanceContainer.end();
1256 
1257  int i;
1258  os << std::endl;
1259  os << " name model name Parameters" << std::endl;
1260  for (i=0, iter=first; iter!=last; ++iter, ++i)
1261  {
1262  os << " " << i << ": " << (*iter)->getName() << " ";
1263  os << getName();
1264  os << std::endl;
1265  }
1266 
1267  os << std::endl;
1268 
1269  return os;
1270 }
1271 
1272 //-----------------------------------------------------------------------------
1273 // Function : Model::forEachInstance
1274 // Purpose :
1275 // Special Notes :
1276 // Scope : public
1277 // Creator : David Baur
1278 // Creation Date : 2/4/2014
1279 //-----------------------------------------------------------------------------
1280 /// Apply a device instance "op" to all instances associated with this
1281 /// model
1282 ///
1283 /// @param[in] op Operator to apply to all instances.
1284 ///
1285 ///
1286 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
1287 {
1288  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
1289  op(*it);
1290 }
1291 
1292 
1293 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1294 {
1295 
1296  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1297 }
1298 
1300 {
1302  .registerDevice("PowerGridGenBus", 1)
1303  .registerDevice("PGGB", 1)
1304  .registerModelType("PowerGridGenBus", 1);
1305 }
1306 
1307 } // namespace PowerGridGenBus
1308 } // namespace Device
1309 } // namespace Xyce
const InstanceName & getName() const
const SolverState & solverState_
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
Pure virtual class to augment a linear system.
Parameter may be specified as time dependent expression from netlist.
Definition: N_DEV_Pars.h:67
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
std::vector< Instance * > instanceContainer
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
#define AssertLIDs(cmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
void setParams(const std::vector< Param > &params)
const std::string & getName() const
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
const DeviceOptions & deviceOptions_
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
static void loadModelParameters(ParametricData< Model > &model_parameters)
Linear::Matrix * dFdxMatrixPtr
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
static std::vector< std::vector< int > > jacStamp
Class Configuration contains device configuration data.
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
const SolverState & getSolverState() const
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Riter, const FactoryBlock &factory_block)
const std::vector< std::vector< int > > & jacobianStamp() const
ModelBlock represents a .MODEL line from the netlist.
virtual std::ostream & printOutInstances(std::ostream &os) const
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
std::vector< Param > params