Xyce  6.1
N_DEV_PowerGridBusShunt.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_PowerGridBusShunt.C,v $
27 //
28 // Purpose : PowerGrid classes: provides a device that calculates the
29 // steady state power flow in a transmission grid bus shunt
30 //
31 // Special Notes : Experimental new device for an LDRD.
32 //
33 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
34 //
35 // Creation Date : 12/4/14
36 //
37 // Revision Information:
38 // ---------------------
39 //
40 // Revision Number: $Revision: 1.15 $
41 //
42 // Revision Date : $Date: 2015/10/21 17:14:21 $
43 //
44 // Current Owner : $Author: peshola $
45 //----------------------------------------------------------------------------
46 
47 #include <Xyce_config.h>
48 
49 
50 // ---------- Standard Includes ----------
51 
52 // ---------- Xyce Includes ----------
54 #include <N_DEV_Const.h>
55 #include <N_DEV_DeviceOptions.h>
56 #include <N_DEV_DeviceMaster.h>
57 #include <N_DEV_ExternData.h>
58 #include <N_DEV_MatrixLoadData.h>
59 #include <N_DEV_Message.h>
60 #include <N_DEV_SolverState.h>
61 
62 #include <N_LAS_Matrix.h>
63 #include <N_LAS_Vector.h>
64 
65 #include <N_UTL_ExtendedString.h>
66 #include <N_UTL_FeatureTest.h>
67 #include <N_UTL_IndentStreamBuf.h>
68 
69 namespace Xyce {
70 namespace Device {
71 namespace PowerGridBusShunt {
72 
73 // enables debug output for just this device
74 //static const int DEBUG_DEVICE = 1;
75 
77 {
78  p.addPar("AT", std::string("PQP"), &PowerGridBusShunt::Instance::analysisTypeStr_)
79  .setUnit(U_NONE)
80  .setDescription("Analysis Type");
81 
83  .setExpressionAccess(ParameterType::TIME_DEP)
84  .setUnit(U_PERUNIT)
85  .setDescription("Shunt Conductance");
86 
88  .setExpressionAccess(ParameterType::TIME_DEP)
89  .setUnit(U_PERUNIT)
90  .setDescription("Shunt Susceptance");
91 }
92 
94 {}
95 
96 
97 
98 std::vector< std::vector<int> > Instance::jacStamp;
99 
100 // Class Instance
101 //-----------------------------------------------------------------------------
102 // Function : Instance::Instance
103 // Purpose : "instance block" constructor
104 // Special Notes :
105 // Scope : public
106 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
107 // Creation Date : 12/4/14
108 //-----------------------------------------------------------------------------
110  const Configuration & configuration,
111  const InstanceBlock & IB,
112  Model & Miter,
113  const FactoryBlock & factory_block)
114  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
115  model_(Miter),
116  analysisTypeStr_("PQP"),
117  analysisType_(PQP),
118  shuntConductance_(1),
119  shuntSusceptance_(1)
120 {
121  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
122  {
123  Xyce::dout() << std::endl << "In device constructor for " << getName() << std::endl;
124  }
125 
126  std::vector<Param>::const_iterator iter = IB.params.begin();
127  std::vector<Param>::const_iterator last = IB.params.end();
128 
129  for ( ; iter != last; ++iter)
130  {
131  const std::string & tmpname = iter->tag();
132  const bool & tmpgiven = iter->given();
133 
134  // copy instance parameter values into private variables
135  if (tmpname == "AT" && tmpgiven == true)
136  {
137  ExtendedString atStr(iter->stringValue());
138  atStr.toUpper();
139  if ( atStr == "IV" )
140  {
141  analysisType_ = IV;
142  analysisTypeStr_ = "IV";
143  }
144  else if ( atStr == "PQR" )
145  {
146  analysisType_ = PQR;
147  analysisTypeStr_ = "PQR";
148  }
149  else if ( atStr == "PQP" )
150  {
151  analysisType_ = PQP;
152  analysisTypeStr_ = "PQP";
153  }
154  else
155  {
156  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
157  }
158  }
159  if (tmpname == "G" && tmpgiven == true)
160  {
161  shuntConductance_ = iter->getImmutableValue<double>();
162  }
163  if (tmpname == "B" && tmpgiven == true)
164  {
165  shuntSusceptance_ = iter->getImmutableValue<double>();
166  }
167  }
168 
169  numIntVars = 0;
170  numExtVars = 4;
171  numStateVars = 0;
172 
173  // Calculate the Y parameters from the branch data
174  //calculateYParameters();
175  std::complex<double> yVal = std::complex<double>(shuntConductance_,shuntSusceptance_);
176 
177  // get the real and imaginary parts. It makes the rest of the code (in the F and dF/dX
178  // functions) more readable
181  g12 = -1.0*shuntConductance_;
182  b12 = -1.0*shuntSusceptance_;
183  g21 = g12;
184  b21 = b12;
185  g22 = g11;
186  b22 = b11;
187 
188  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
189  {
190  Xyce::dout() << getName() << " G's and B's are:"
191  << Util::push << std::endl
192  << "(g11,b11) = (" << g11 << " , " << b11 << ")" << std::endl
193  << "(g12,b12) = (" << g12 << " , " << b12 << ")" << std::endl
194  << "(g21,b21) = (" << g21 << " , " << b21 << ")" << std::endl
195  << "(g22,b22) = (" << g22 << " , " << b22 << ")" << std::endl
196  << std::endl;
197  }
198 
199  if( jacStamp.empty() )
200  {
201  jacStamp.resize(4);
202  jacStamp[0].resize(4);
203  jacStamp[1].resize(4);
204  jacStamp[2].resize(4);
205  jacStamp[3].resize(4);
206 
207  jacStamp[0][0] = 0;
208  jacStamp[0][1] = 1;
209  jacStamp[0][2] = 2;
210  jacStamp[0][3] = 3;
211  jacStamp[1][0] = 0;
212  jacStamp[1][1] = 1;
213  jacStamp[1][2] = 2;
214  jacStamp[1][3] = 3;
215  jacStamp[2][0] = 0;
216  jacStamp[2][1] = 1;
217  jacStamp[2][2] = 2;
218  jacStamp[2][3] = 3;
219  jacStamp[3][0] = 0;
220  jacStamp[3][1] = 1;
221  jacStamp[3][2] = 2;
222  jacStamp[3][3] = 3;
223  }
224 
225  // Set params to constant default values:
226  setDefaultParams ();
227 
228  // Set params according to instance line and constant defaults from metadata:
229  setParams (IB.params);
230 
231  // Set any non-constant parameter defaults:
232 
233 }
234 
235 //-----------------------------------------------------------------------------
236 // Function : Instance::~Instance
237 // Purpose : destructor
238 // Special Notes :
239 // Scope : public
240 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
241 // Creation Date : 12/4/14
242 //-----------------------------------------------------------------------------
244 {
245 }
246 
247 //-----------------------------------------------------------------------------
248 // Function : Instance::registerLIDs
249 // Purpose :
250 // Special Notes :
251 // Scope : public
252 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
253 // Creation Date : 12/4/14
254 //-----------------------------------------------------------------------------
255 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
256  const std::vector<int> & extLIDVecRef )
257 {
258  AssertLIDs(intLIDVecRef.size() == numIntVars);
259  AssertLIDs(extLIDVecRef.size() == numExtVars);
260 
261  // copy over the global ID lists.
262  intLIDVec = intLIDVecRef;
263  extLIDVec = extLIDVecRef;
264 
265  // in general, there will be 4 I/0 nodes for each shunt.
266  // these if-else blocks may be made into separate classes,
267  // in the final version of this model.
268  if ( analysisType_ == IV || analysisType_ == PQR)
269  {
270  li_VR1 = extLIDVec[0];
271  li_VR2 = extLIDVec[1];
272  li_VI1 = extLIDVec[2];
273  li_VI2 = extLIDVec[3];
274 
275  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
276  {
277  Xyce::dout() << getName() << " LIDs"
278  << Util::push << std::endl
279  << "li_VR1 = " << li_VR1 << std::endl
280  << "li_VI1 = " << li_VI1 << std::endl
281  << "li_VR2 = " << li_VR2 << std::endl
282  << "li_VI2 = " << li_VI2 << std::endl
283  << std::endl;
284  }
285  }
286  else if (analysisType_ == PQP )
287  {
288  li_Theta1 = extLIDVec[0];
289  li_Theta2 = extLIDVec[1];
290  li_VM1 = extLIDVec[2];
291  li_VM2 = extLIDVec[3];
292 
293  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
294  {
295  Xyce::dout() << getName() << " LIDs"
296  << Util::push << std::endl
297  << "li_Theta1 = " << li_Theta1 << std::endl
298  << "li_VM1 = " << li_VM1 << std::endl
299  << "li_Theta2 = " << li_Theta2 << std::endl
300  << "li_VM2 = " << li_VM2 << std::endl
301  << std::endl;
302  }
303  }
304  else
305  {
306  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
307  return;
308  }
309 }
310 
311 //-----------------------------------------------------------------------------
312 // Function : Instance::loadNodeSymbols
313 // Purpose :
314 // Special Notes :
315 // Scope : public
316 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
317 // Creation Date : 05/13/05
318 //-----------------------------------------------------------------------------
319 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
320 {}
321 
322 //-----------------------------------------------------------------------------
323 // Function : Instance::registerStateLIDs
324 // Purpose : Set up offsets so we can store quantities that need to be
325 // differentiated.
326 // Special Notes :
327 // Scope : public
328 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
329 // Creation Date : 12/4/14
330 //-----------------------------------------------------------------------------
331 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef )
332 {
333  AssertLIDs(staLIDVecRef.size() == numStateVars);
334 }
335 
336 //-----------------------------------------------------------------------------
337 // Function : Instance::jacobianStamp
338 // Purpose :
339 // Special Notes :
340 // Scope : public
341 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
342 // Creation Date : 08/20/01
343 //-----------------------------------------------------------------------------
344 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
345 {
346  return jacStamp;
347 }
348 
349 //-----------------------------------------------------------------------------
350 // Function : Instance::registerJacLIDs
351 // Purpose :
352 // Special Notes :
353 // Scope : public
354 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
355 // Creation Date : 12/4/14
356 //-----------------------------------------------------------------------------
357 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
358 {
359  DeviceInstance::registerJacLIDs( jacLIDVec );
360 
361  // These if-else blocks may be made into separate classes,
362  // in the final version of this model
363  if (analysisType_ == IV || analysisType_ == PQR)
364  {
365  VR1_VR1_Offset = jacLIDVec[0][0];
366  VR1_VR2_Offset = jacLIDVec[0][1];
367  VR1_VI1_Offset = jacLIDVec[0][2];
368  VR1_VI2_Offset = jacLIDVec[0][3];
369 
370  VR2_VR1_Offset = jacLIDVec[1][0];
371  VR2_VR2_Offset = jacLIDVec[1][1];
372  VR2_VI1_Offset = jacLIDVec[1][2];
373  VR2_VI2_Offset = jacLIDVec[1][3];
374 
375  VI1_VR1_Offset = jacLIDVec[2][0];
376  VI1_VR2_Offset = jacLIDVec[2][1];
377  VI1_VI1_Offset = jacLIDVec[2][2];
378  VI1_VI2_Offset = jacLIDVec[2][3];
379 
380  VI2_VR1_Offset = jacLIDVec[3][0];
381  VI2_VR2_Offset = jacLIDVec[3][1];
382  VI2_VI1_Offset = jacLIDVec[3][2];
383  VI2_VI2_Offset = jacLIDVec[3][3];
384 
385  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
386  {
387  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
388  << "VR1 offsets are (" << VR1_VR1_Offset << " , " << VR1_VR2_Offset << " , "
389  << VR1_VI1_Offset << " , " << VR1_VI2_Offset << ")" << std::endl
390  << "VR2 offsets are (" << VR2_VR1_Offset << " , " << VR2_VR2_Offset << " , "
391  << VR2_VI1_Offset << " , " << VR2_VI2_Offset << ")" << std::endl
392  << "VI1 offsets are (" << VI1_VR1_Offset << " , " << VI1_VR2_Offset << " , "
393  << VI1_VI1_Offset << " , " << VI1_VI2_Offset << ")" << std::endl
394  << "VI2 offsets are (" << VI2_VR1_Offset << " , " << VI2_VR2_Offset << " , "
395  << VI2_VI1_Offset << " , " << VI2_VI2_Offset << ")" << std::endl << std::endl;
396  }
397  }
398  else if (analysisType_ == PQP)
399  {
400  Theta1_Theta1_Offset = jacLIDVec[0][0];
401  Theta1_Theta2_Offset = jacLIDVec[0][1];
402  Theta1_VM1_Offset = jacLIDVec[0][2];
403  Theta1_VM2_Offset = jacLIDVec[0][3];
404 
405  Theta2_Theta1_Offset = jacLIDVec[1][0];
406  Theta2_Theta2_Offset = jacLIDVec[1][1];
407  Theta2_VM1_Offset = jacLIDVec[1][2];
408  Theta2_VM2_Offset = jacLIDVec[1][3];
409 
410  VM1_Theta1_Offset = jacLIDVec[2][0];
411  VM1_Theta2_Offset = jacLIDVec[2][1];
412  VM1_VM1_Offset = jacLIDVec[2][2];
413  VM1_VM2_Offset = jacLIDVec[2][3];
414 
415  VM2_Theta1_Offset = jacLIDVec[3][0];
416  VM2_Theta2_Offset = jacLIDVec[3][1];
417  VM2_VM1_Offset = jacLIDVec[3][2];
418  VM2_VM2_Offset = jacLIDVec[3][3];
419 
420  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
421  {
422  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
423  << "Theta1 offsets are (" << Theta1_Theta1_Offset << " , " << Theta1_Theta2_Offset << " , "
424  << Theta1_VM1_Offset << " , " << Theta1_VM2_Offset << ")" << std::endl
425  << "Theta2 offsets are (" << Theta2_Theta1_Offset << " , " << Theta2_Theta2_Offset << " , "
426  << Theta2_VM1_Offset << " , " << Theta2_VM2_Offset << ")" << std::endl
427  << "VM1 offsets are (" << VM1_Theta1_Offset << " , " << VM1_Theta2_Offset << " , "
428  << VM1_VM1_Offset << " , " << VM1_VM2_Offset << ")" << std::endl
429  << "VM2 offsets are (" << VM2_Theta1_Offset << " , " << VM2_Theta2_Offset << " , "
430  << VM2_VM1_Offset << " , " << VM2_VM2_Offset << ")" << std::endl<< std::endl;
431  }
432  }
433 }
434 
435 //-----------------------------------------------------------------------------
436 // Function : Instance::updateIntermediateVars
437 // Purpose : update intermediate variables for one diode instance
438 // Special Notes :
439 // Scope : public
440 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
441 // Creation Date : 12/4/14
442 //-----------------------------------------------------------------------------
444 {
445  double * solVec = extData.nextSolVectorRawPtr;
446 
447  // These if-else blocks may be made into separate classes,
448  // in the final version of this model
449  if (analysisType_ == IV)
450  {
451  IR1 = g11*solVec[li_VR1] + g12*solVec[li_VR2] - b11*solVec[li_VI1] - b12*solVec[li_VI2];
452  IR2 = g21*solVec[li_VR1] + g22*solVec[li_VR2] - b21*solVec[li_VI1] - b22*solVec[li_VI2];
453  II1 = b11*solVec[li_VR1] + b12*solVec[li_VR2] + g11*solVec[li_VI1] + g12*solVec[li_VI2];
454  II2 = b21*solVec[li_VR1] + b22*solVec[li_VR2] + g21*solVec[li_VI1] + g22*solVec[li_VI2];
455  }
456  else if (analysisType_ == PQR)
457  {
458  P1 = g11*(solVec[li_VR1]*solVec[li_VR1] + solVec[li_VI1]*solVec[li_VI1]) +
459  solVec[li_VR1]*(g12*solVec[li_VR2] - b12*solVec[li_VI2]) +
460  solVec[li_VI1]*(b12*solVec[li_VR2] + g12*solVec[li_VI2]);
461 
462  P2 = g22*(solVec[li_VR2]*solVec[li_VR2] + solVec[li_VI2]*solVec[li_VI2]) +
463  solVec[li_VR2]*(g21*solVec[li_VR1] - b21*solVec[li_VI1]) +
464  solVec[li_VI2]*(b21*solVec[li_VR1] + g21*solVec[li_VI1]);
465 
466  Q1 = -1.0*b11*(solVec[li_VR1]*solVec[li_VR1] + solVec[li_VI1]*solVec[li_VI1]) +
467  solVec[li_VI1]*(g12*solVec[li_VR2] - b12*solVec[li_VI2]) -
468  solVec[li_VR1]*(b12*solVec[li_VR2] + g12*solVec[li_VI2]);
469 
470  Q2 = -1.0*b22*(solVec[li_VR2]*solVec[li_VR2] + solVec[li_VI2]*solVec[li_VI2]) +
471  solVec[li_VI2]*(g21*solVec[li_VR1] - b21*solVec[li_VI1]) -
472  solVec[li_VR2]*(b21*solVec[li_VR1] + g21*solVec[li_VI1]);
473  }
474  else if (analysisType_ == PQP)
475  {
476  double dSin12 = sin(solVec[li_Theta1]-solVec[li_Theta2]);
477  double dSin21 = sin(solVec[li_Theta2]-solVec[li_Theta1]);
478  double dCos12 = cos(solVec[li_Theta1]-solVec[li_Theta2]);
479  double dCos21 = cos(solVec[li_Theta2]-solVec[li_Theta1]);
480 
481  P1 = g11*solVec[li_VM1]*solVec[li_VM1] + solVec[li_VM1]*solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
482  P2 = g22*solVec[li_VM2]*solVec[li_VM2] + solVec[li_VM2]*solVec[li_VM1]*(g21*dCos21 + b21*dSin21);
483  Q1 = -1*b11*solVec[li_VM1]*solVec[li_VM1] + solVec[li_VM1]*solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
484  Q2 = -1*b22*solVec[li_VM2]*solVec[li_VM2] + solVec[li_VM2]*solVec[li_VM1]*(g21*dSin21 - b21*dCos21);
485  }
486  else
487  {
488  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
489  return false;
490  }
491 
492  return true;
493 }
494 
495 //-----------------------------------------------------------------------------
496 // Function : Instance::updatePrimaryState
497 // Purpose :
498 // Special Notes :
499 // Scope : public
500 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
501 // Creation Date : 12/4/14
502 //-----------------------------------------------------------------------------
504 {
505  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
506  {
507  Xyce::dout() << "Instance::updatePrimaryState" <<std::endl;
508  }
509 
510  return updateIntermediateVars ();
511 }
512 
513 //-----------------------------------------------------------------------------
514 // Function : Instance::loadDAEFVector
515 //
516 // Purpose : Loads the F-vector contributions
517 //
518 // Special Notes :
519 //
520 //
521 // Scope : public
522 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
523 // Creation Date : 12/4/14
524 //-----------------------------------------------------------------------------
526 {
527  double * fVec = extData.daeFVectorRawPtr;
528 
529  // These if-else blocks may be made into separate classes,
530  // in the final version of this model
531  if (analysisType_ == IV)
532  {
533  fVec[li_VR1] += IR1;
534  fVec[li_VR2] += IR2;
535  fVec[li_VI1] += II1;
536  fVec[li_VI2] += II2;
537  }
538  else if (analysisType_ == PQR)
539  {
540  fVec[li_VR1] += P1;
541  fVec[li_VR2] += P2;
542  fVec[li_VI1] += Q1;
543  fVec[li_VI2] += Q2;
544  }
545  else if (analysisType_ == PQP)
546  {
547  fVec[li_Theta1] += P1;
548  fVec[li_Theta2] += P2;
549  fVec[li_VM1] += Q1;
550  fVec[li_VM2] += Q2;
551 
552  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
553  {
554  Xyce::dout() << getName() << ": F Vector Load info is: (P1,P2,Q1,Q2) load is: (" << P1 << " , "
555  << P2 << " , " << Q1 << " , " << Q2 << ")" << std::endl << std::endl;
556  }
557  }
558  else
559  {
560  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
561  return false;
562  }
563 
564  if (getSolverState().dcopFlag)
565  {
566  // no op placeholder
567  }
568  else
569  {
570  // no op placeholder
571  }
572 
573  return true;
574 }
575 
576 //-----------------------------------------------------------------------------
577 // Function : Instance::loadDAEQVector
578 //
579 // Purpose : Loads the Q-vector contributions. This is a no-op for
580 // this model
581 //
582 // Special Notes :
583 //
584 //
585 // Scope : public
586 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
587 // Creation Date : 9/12/14
588 //-----------------------------------------------------------------------------
590 {
591  return true;
592 }
593 
594 //-----------------------------------------------------------------------------
595 // Function : Instance::loadDAEdFdx ()
596 //
597 // Purpose : Loads the F-vector contributions
598 //
599 // Special Notes :
600 //
601 // Scope : public
602 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
603 // Creation Date : 9/12/14
604 //-----------------------------------------------------------------------------
606 {
607  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
608 
609  // These if-else blocks may be made into separate classes,
610  // in the final version of this model
611  if (analysisType_ == IV)
612  {
613  dFdx[li_VR1][VR1_VR1_Offset] += g11;
614  dFdx[li_VR1][VR1_VR2_Offset] += g12;
615  dFdx[li_VR1][VR1_VI1_Offset] -= b11;
616  dFdx[li_VR1][VR1_VI2_Offset] -= b12;
617 
618  dFdx[li_VR2][VR2_VR1_Offset] += g21;
619  dFdx[li_VR2][VR2_VR2_Offset] += g22;
620  dFdx[li_VR2][VR2_VI1_Offset] -= b21;
621  dFdx[li_VR2][VR2_VI2_Offset] -= b22;
622 
623  dFdx[li_VI1][VI1_VR1_Offset] += b11;
624  dFdx[li_VI1][VI1_VR2_Offset] += b12;
625  dFdx[li_VI1][VI1_VI1_Offset] += g11;
626  dFdx[li_VI1][VI1_VI2_Offset] += g12;
627 
628  dFdx[li_VI2][VI2_VR1_Offset] += b21;
629  dFdx[li_VI2][VI2_VR2_Offset] += b22;
630  dFdx[li_VI2][VI2_VI1_Offset] += g21;
631  dFdx[li_VI2][VI2_VI2_Offset] += g22;
632  }
633  else if (analysisType_ == PQR)
634  {
635  double * solVec = extData.nextSolVectorRawPtr;
636 
637  dFdx[li_VR1][VR1_VR1_Offset] += 2*g11*solVec[li_VR1] + g12*solVec[li_VR2] - b12*solVec[li_VI2];
638  dFdx[li_VR1][VR1_VR2_Offset] += g12*solVec[li_VR1] + b12*solVec[li_VI1];
639  dFdx[li_VR1][VR1_VI1_Offset] += 2*g11*solVec[li_VI1] + b12*solVec[li_VR2] + g12*solVec[li_VI2];
640  dFdx[li_VR1][VR1_VI2_Offset] += g12*solVec[li_VI1] - b12*solVec[li_VR1];
641 
642  dFdx[li_VR2][VR2_VR1_Offset] += g21*solVec[li_VR2] + b21*solVec[li_VI2];
643  dFdx[li_VR2][VR2_VR2_Offset] += 2*g22*solVec[li_VR2] + g21*solVec[li_VR1] - b21*solVec[li_VI1];
644  dFdx[li_VR2][VR2_VI1_Offset] += g21*solVec[li_VI2] - b21*solVec[li_VR2];
645  dFdx[li_VR2][VR2_VI2_Offset] += 2*g22*solVec[li_VI2] + b21*solVec[li_VR1] + g21*solVec[li_VI1];
646 
647  dFdx[li_VI1][VI1_VR1_Offset] += -2*b11*solVec[li_VR1] - b12*solVec[li_VR2] - g12*solVec[li_VI2];
648  dFdx[li_VI1][VI1_VR2_Offset] += g12*solVec[li_VI1] - b12*solVec[li_VR1];
649  dFdx[li_VI1][VI1_VI1_Offset] += -2*b11*solVec[li_VI1] + g12*solVec[li_VR2] - b12*solVec[li_VI2];
650  dFdx[li_VI1][VI1_VI2_Offset] -= g12*solVec[li_VR1] + b12*solVec[li_VI1];
651 
652  dFdx[li_VI2][VI2_VR1_Offset] += g21*solVec[li_VI2] - b21*solVec[li_VR2];
653  dFdx[li_VI2][VI2_VR2_Offset] += -2*b22*solVec[li_VR2] - b21*solVec[li_VR1] - g12*solVec[li_VI1];
654  dFdx[li_VI2][VI2_VI1_Offset] -= g21*solVec[li_VR2] + b21*solVec[li_VI2];
655  dFdx[li_VI2][VI2_VI2_Offset] += -2*b22*solVec[li_VI2] + g21*solVec[li_VR1] - b21*solVec[li_VI1];
656  }
657  else if (analysisType_ == PQP)
658  {
659  double * solVec = extData.nextSolVectorRawPtr;
660  double dSin12 = sin(solVec[li_Theta1]-solVec[li_Theta2]);
661  double dSin21 = sin(solVec[li_Theta2]-solVec[li_Theta1]);
662  double dCos12 = cos(solVec[li_Theta1]-solVec[li_Theta2]);
663  double dCos21 = cos(solVec[li_Theta2]-solVec[li_Theta1]);
664 
665  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
666  {
667  Xyce::dout() << getName() << ": dFdx info is: " << std::endl
668  << "(dSin12,dSin21,dCos12,dCos21 = (" << dSin12 << " , " << dSin21
669  << " , " << dCos12 << " , " << dCos21 << ")" << std::endl
670  << "(solVec[li_Theta1],solVec[li_Theta2]) = (" << solVec[li_Theta1]
671  << " , " << solVec[li_Theta2] << ")" << std::endl
672  << "(solVec[li_VM1],solVec[li_VM2]) = (" << solVec[li_VM1]
673  << " , " << solVec[li_VM2] << ")" << std::endl;
674  }
675 
676  // dP / dTheta terms
677  dFdx[li_Theta1][Theta1_Theta1_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
678  dFdx[li_Theta1][Theta1_Theta2_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
679  dFdx[li_Theta2][Theta2_Theta1_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g21*dSin21 - b21*dCos21);
680  dFdx[li_Theta2][Theta2_Theta2_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g21*dSin21 - b21*dCos21);
681 
682  // dP / dV terms
683  dFdx[li_Theta1][Theta1_VM1_Offset] += 2*solVec[li_VM1]*g11 + solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
684  dFdx[li_Theta1][Theta1_VM2_Offset] += solVec[li_VM1]*(g12*dCos12 + b12*dSin12);
685  dFdx[li_Theta2][Theta2_VM1_Offset] += solVec[li_VM2]*(g21*dCos21 + b21*dSin21);
686  dFdx[li_Theta2][Theta2_VM2_Offset] += 2*solVec[li_VM2]*g22 + solVec[li_VM1]*(g21*dCos21 + b21*dSin21);
687 
688  // dQ / dTheta terms
689  dFdx[li_VM1][VM1_Theta1_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
690  dFdx[li_VM1][VM1_Theta2_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
691  dFdx[li_VM2][VM2_Theta1_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g21*dCos21 + b21*dSin21);
692  dFdx[li_VM2][VM2_Theta2_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g21*dCos21 + b21*dSin21);
693 
694  // dQ / dV terms
695  dFdx[li_VM1][VM1_VM1_Offset] += -2*solVec[li_VM1]*b11 + solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
696  dFdx[li_VM1][VM1_VM2_Offset] += solVec[li_VM1]*(g12*dSin12 - b12*dCos12);
697  dFdx[li_VM2][VM2_VM1_Offset] += solVec[li_VM2]*(g21*dSin21 - b21*dCos21);
698  dFdx[li_VM2][VM2_VM2_Offset] += -2*solVec[li_VM2]*b22 + solVec[li_VM1]*(g21*dSin21 - b21*dCos21);
699  }
700  else
701  {
702  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
703  return false;
704  }
705 
706  if (getSolverState().dcopFlag)
707  {
708  // no op placeholder code;
709  }
710  else
711  {
712  // no op placeholder code;
713  }
714 
715  return true;
716 }
717 
718 //-----------------------------------------------------------------------------
719 // Function : Instance::loadDAEdQdx ()
720 //
721 // Purpose : Loads the Q-vector contributions. This is no-op for this
722 // model.
723 //
724 // Special Notes :
725 //
726 // Scope : public
727 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
728 // Creation Date : 9/12/14
729 //-----------------------------------------------------------------------------
731 {
732  return true;
733 }
734 
735 //-----------------------------------------------------------------------------
736 // Function : Model::Model
737 // Purpose : "Model block" constructor
738 // Special Notes :
739 // Scope : public
740 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
741 // Creation Date : 9/12/14
742 //-----------------------------------------------------------------------------
743 
744 
745 // These are all just placeholder functions, as there is nothing to the model
746 // class.
747 // Class Model
748 
749 //-----------------------------------------------------------------------------
750 // Function : Model::Model
751 // Purpose : "Model block" constructor
752 // Special Notes :
753 // Scope : public
754 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
755 // Creation Date : 9/12/14
756 //-----------------------------------------------------------------------------
758  const Configuration & configuration,
759  const ModelBlock & MB,
760  const FactoryBlock & factory_block)
761  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
762 {
763 }
764 
765 //-----------------------------------------------------------------------------
766 // Function : Model::~Model
767 // Purpose : destructor
768 // Special Notes :
769 // Scope : public
770 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
771 // Creation Date : 9/12/14
772 //-----------------------------------------------------------------------------
774 {
775  std::vector<Instance*>::iterator iter;
776  std::vector<Instance*>::iterator first = instanceContainer.begin();
777  std::vector<Instance*>::iterator last = instanceContainer.end();
778 
779  for (iter=first; iter!=last; ++iter)
780  {
781  delete (*iter);
782  }
783 }
784 
785 //-----------------------------------------------------------------------------
786 // Function : Model::printOutInstances
787 // Purpose : debugging tool.
788 // Special Notes :
789 // Scope : public
790 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
791 // Creation Date : 9/12/14
792 //-----------------------------------------------------------------------------
793 std::ostream &Model::printOutInstances(std::ostream &os) const
794 {
795  std::vector<Instance*>::const_iterator iter;
796  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
797  std::vector<Instance*>::const_iterator last = instanceContainer.end();
798 
799  int i;
800  os << std::endl;
801  os << " name model name Parameters" << std::endl;
802  for (i=0, iter=first; iter!=last; ++iter, ++i)
803  {
804  os << " " << i << ": " << (*iter)->getName() << " ";
805  os << getName();
806  os << std::endl;
807  }
808 
809  os << std::endl;
810 
811  return os;
812 }
813 
814 //-----------------------------------------------------------------------------
815 // Function : Model::forEachInstance
816 // Purpose :
817 // Special Notes :
818 // Scope : public
819 // Creator : David Baur
820 // Creation Date : 2/4/2014
821 //-----------------------------------------------------------------------------
822 /// Apply a device instance "op" to all instances associated with this
823 /// model
824 ///
825 /// @param[in] op Operator to apply to all instances.
826 ///
827 ///
828 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
829 {
830  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
831  op(*it);
832 }
833 
834 
835 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
836 {
837 
838  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
839 }
840 
842 {
844  .registerDevice("PowerGridBusShunt", 1)
845  .registerDevice("PGBS", 1)
846  .registerModelType("PowerGridBusShunt", 1);
847 }
848 
849 } // namespace PowerGridBusShunt
850 } // namespace Device
851 } // namespace Xyce
const InstanceName & getName() const
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
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
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Pure virtual class to augment a linear system.
Parameter may be specified as time dependent expression from netlist.
Definition: N_DEV_Pars.h:67
#define AssertLIDs(cmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
virtual std::ostream & printOutInstances(std::ostream &os) const
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...
const DeviceOptions & deviceOptions_
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
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.
const SolverState & getSolverState() const
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
const std::vector< std::vector< int > > & jacobianStamp() const
ModelBlock represents a .MODEL line from the netlist.
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Riter, const FactoryBlock &factory_block)
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
static void loadModelParameters(ParametricData< Model > &model_parameters)