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.12.2.4 $
41 //
42 // Revision Date : $Date: 2015/04/03 16:42:57 $
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 will be made into separate classes,
267  // once they work
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 : Robert Hoekstra, SNL, Parallel Computational Sciences
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 will be split out into separate classes once they both work
362  if (analysisType_ == IV || analysisType_ == PQR)
363  {
364  VR1_VR1_Offset = jacLIDVec[0][0];
365  VR1_VR2_Offset = jacLIDVec[0][1];
366  VR1_VI1_Offset = jacLIDVec[0][2];
367  VR1_VI2_Offset = jacLIDVec[0][3];
368 
369  VR2_VR1_Offset = jacLIDVec[1][0];
370  VR2_VR2_Offset = jacLIDVec[1][1];
371  VR2_VI1_Offset = jacLIDVec[1][2];
372  VR2_VI2_Offset = jacLIDVec[1][3];
373 
374  VI1_VR1_Offset = jacLIDVec[2][0];
375  VI1_VR2_Offset = jacLIDVec[2][1];
376  VI1_VI1_Offset = jacLIDVec[2][2];
377  VI1_VI2_Offset = jacLIDVec[2][3];
378 
379  VI2_VR1_Offset = jacLIDVec[3][0];
380  VI2_VR2_Offset = jacLIDVec[3][1];
381  VI2_VI1_Offset = jacLIDVec[3][2];
382  VI2_VI2_Offset = jacLIDVec[3][3];
383 
384  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
385  {
386  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
387  << "VR1 offsets are (" << VR1_VR1_Offset << " , " << VR1_VR2_Offset << " , "
388  << VR1_VI1_Offset << " , " << VR1_VI2_Offset << ")" << std::endl
389  << "VR2 offsets are (" << VR2_VR1_Offset << " , " << VR2_VR2_Offset << " , "
390  << VR2_VI1_Offset << " , " << VR2_VI2_Offset << ")" << std::endl
391  << "VI1 offsets are (" << VI1_VR1_Offset << " , " << VI1_VR2_Offset << " , "
392  << VI1_VI1_Offset << " , " << VI1_VI2_Offset << ")" << std::endl
393  << "VI2 offsets are (" << VI2_VR1_Offset << " , " << VI2_VR2_Offset << " , "
394  << VI2_VI1_Offset << " , " << VI2_VI2_Offset << ")" << std::endl << std::endl;
395  }
396  }
397  else if (analysisType_ == PQP)
398  {
399  Theta1_Theta1_Offset = jacLIDVec[0][0];
400  Theta1_Theta2_Offset = jacLIDVec[0][1];
401  Theta1_VM1_Offset = jacLIDVec[0][2];
402  Theta1_VM2_Offset = jacLIDVec[0][3];
403 
404  Theta2_Theta1_Offset = jacLIDVec[1][0];
405  Theta2_Theta2_Offset = jacLIDVec[1][1];
406  Theta2_VM1_Offset = jacLIDVec[1][2];
407  Theta2_VM2_Offset = jacLIDVec[1][3];
408 
409  VM1_Theta1_Offset = jacLIDVec[2][0];
410  VM1_Theta2_Offset = jacLIDVec[2][1];
411  VM1_VM1_Offset = jacLIDVec[2][2];
412  VM1_VM2_Offset = jacLIDVec[2][3];
413 
414  VM2_Theta1_Offset = jacLIDVec[3][0];
415  VM2_Theta2_Offset = jacLIDVec[3][1];
416  VM2_VM1_Offset = jacLIDVec[3][2];
417  VM2_VM2_Offset = jacLIDVec[3][3];
418 
419  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
420  {
421  Xyce::dout() << getName() << ": In registerJacLIDs, the offsets are:" << std::endl
422  << "Theta1 offsets are (" << Theta1_Theta1_Offset << " , " << Theta1_Theta2_Offset << " , "
423  << Theta1_VM1_Offset << " , " << Theta1_VM2_Offset << ")" << std::endl
424  << "Theta2 offsets are (" << Theta2_Theta1_Offset << " , " << Theta2_Theta2_Offset << " , "
425  << Theta2_VM1_Offset << " , " << Theta2_VM2_Offset << ")" << std::endl
426  << "VM1 offsets are (" << VM1_Theta1_Offset << " , " << VM1_Theta2_Offset << " , "
427  << VM1_VM1_Offset << " , " << VM1_VM2_Offset << ")" << std::endl
428  << "VM2 offsets are (" << VM2_Theta1_Offset << " , " << VM2_Theta2_Offset << " , "
429  << VM2_VM1_Offset << " , " << VM2_VM2_Offset << ")" << std::endl<< std::endl;
430  }
431  }
432 }
433 
434 //-----------------------------------------------------------------------------
435 // Function : Instance::updateIntermediateVars
436 // Purpose : update intermediate variables for one diode instance
437 // Special Notes :
438 // Scope : public
439 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
440 // Creation Date : 12/4/14
441 //-----------------------------------------------------------------------------
443 {
444  double * solVec = extData.nextSolVectorRawPtr;
445 
446  // These will be split out into separate classes once they work
447  if (analysisType_ == IV)
448  {
449  IR1 = g11*solVec[li_VR1] + g12*solVec[li_VR2] - b11*solVec[li_VI1] - b12*solVec[li_VI2];
450  IR2 = g21*solVec[li_VR1] + g22*solVec[li_VR2] - b21*solVec[li_VI1] - b22*solVec[li_VI2];
451  II1 = b11*solVec[li_VR1] + b12*solVec[li_VR2] + g11*solVec[li_VI1] + g12*solVec[li_VI2];
452  II2 = b21*solVec[li_VR1] + b22*solVec[li_VR2] + g21*solVec[li_VI1] + g22*solVec[li_VI2];
453  }
454  else if (analysisType_ == PQR)
455  {
456  P1 = g11*(solVec[li_VR1]*solVec[li_VR1] + solVec[li_VI1]*solVec[li_VI1]) +
457  solVec[li_VR1]*(g12*solVec[li_VR2] - b12*solVec[li_VI2]) +
458  solVec[li_VI1]*(b12*solVec[li_VR2] + g12*solVec[li_VI2]);
459 
460  P2 = g22*(solVec[li_VR2]*solVec[li_VR2] + solVec[li_VI2]*solVec[li_VI2]) +
461  solVec[li_VR2]*(g21*solVec[li_VR1] - b21*solVec[li_VI1]) +
462  solVec[li_VI2]*(b21*solVec[li_VR1] + g21*solVec[li_VI1]);
463 
464  Q1 = -1.0*b11*(solVec[li_VR1]*solVec[li_VR1] + solVec[li_VI1]*solVec[li_VI1]) +
465  solVec[li_VI1]*(g12*solVec[li_VR2] - b12*solVec[li_VI2]) -
466  solVec[li_VR1]*(b12*solVec[li_VR2] + g12*solVec[li_VI2]);
467 
468  Q2 = -1.0*b22*(solVec[li_VR2]*solVec[li_VR2] + solVec[li_VI2]*solVec[li_VI2]) +
469  solVec[li_VI2]*(g21*solVec[li_VR1] - b21*solVec[li_VI1]) -
470  solVec[li_VR2]*(b21*solVec[li_VR1] + g21*solVec[li_VI1]);
471  }
472  else if (analysisType_ == PQP)
473  {
474  double dSin12 = sin(solVec[li_Theta1]-solVec[li_Theta2]);
475  double dSin21 = sin(solVec[li_Theta2]-solVec[li_Theta1]);
476  double dCos12 = cos(solVec[li_Theta1]-solVec[li_Theta2]);
477  double dCos21 = cos(solVec[li_Theta2]-solVec[li_Theta1]);
478 
479  P1 = g11*solVec[li_VM1]*solVec[li_VM1] + solVec[li_VM1]*solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
480  P2 = g22*solVec[li_VM2]*solVec[li_VM2] + solVec[li_VM2]*solVec[li_VM1]*(g21*dCos21 + b21*dSin21);
481  Q1 = -1*b11*solVec[li_VM1]*solVec[li_VM1] + solVec[li_VM1]*solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
482  Q2 = -1*b22*solVec[li_VM2]*solVec[li_VM2] + solVec[li_VM2]*solVec[li_VM1]*(g21*dSin21 - b21*dCos21);
483  }
484  else
485  {
486  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
487  return false;
488  }
489 
490  return true;
491 }
492 
493 //-----------------------------------------------------------------------------
494 // Function : Instance::updatePrimaryState
495 // Purpose :
496 // Special Notes :
497 // Scope : public
498 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
499 // Creation Date : 12/4/14
500 //-----------------------------------------------------------------------------
502 {
503  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
504  {
505  Xyce::dout() << "Instance::updatePrimaryState" <<std::endl;
506  }
507 
508  return updateIntermediateVars ();
509 }
510 
511 //-----------------------------------------------------------------------------
512 // Function : Instance::loadDAEFVector
513 //
514 // Purpose : Loads the F-vector contributions
515 //
516 // Special Notes :
517 //
518 //
519 // Scope : public
520 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
521 // Creation Date : 12/4/14
522 //-----------------------------------------------------------------------------
524 {
525  double * fVec = extData.daeFVectorRawPtr;
526 
527  // this needs to be vectorized in the general case.
528  // These will be split out into separate classes once they work
529  if (analysisType_ == IV)
530  {
531  fVec[li_VR1] += IR1;
532  fVec[li_VR2] += IR2;
533  fVec[li_VI1] += II1;
534  fVec[li_VI2] += II2;
535  }
536  else if (analysisType_ == PQR)
537  {
538  fVec[li_VR1] += P1;
539  fVec[li_VR2] += P2;
540  fVec[li_VI1] += Q1;
541  fVec[li_VI2] += Q2;
542  }
543  else if (analysisType_ == PQP)
544  {
545  fVec[li_Theta1] += P1;
546  fVec[li_Theta2] += P2;
547  fVec[li_VM1] += Q1;
548  fVec[li_VM2] += Q2;
549 
550  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
551  {
552  Xyce::dout() << getName() << ": F Vector Load info is: (P1,P2,Q1,Q2) load is: (" << P1 << " , "
553  << P2 << " , " << Q1 << " , " << Q2 << ")" << std::endl << std::endl;
554  }
555  }
556  else
557  {
558  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
559  return false;
560  }
561 
562  if (getSolverState().dcopFlag)
563  {
564  // no op placeholder
565  }
566  else
567  {
568  // no op placeholder
569  }
570 
571  return true;
572 }
573 
574 //-----------------------------------------------------------------------------
575 // Function : Instance::loadDAEQVector
576 //
577 // Purpose : Loads the Q-vector contributions. This is a no-op for
578 // this model
579 //
580 // Special Notes :
581 //
582 //
583 // Scope : public
584 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
585 // Creation Date : 9/12/14
586 //-----------------------------------------------------------------------------
588 {
589  return true;
590 }
591 
592 //-----------------------------------------------------------------------------
593 // Function : Instance::loadDAEdFdx ()
594 //
595 // Purpose : Loads the F-vector contributions
596 //
597 // Special Notes :
598 //
599 // Scope : public
600 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
601 // Creation Date : 9/12/14
602 //-----------------------------------------------------------------------------
604 {
605  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
606 
607  if (analysisType_ == IV)
608  {
609  dFdx[li_VR1][VR1_VR1_Offset] += g11;
610  dFdx[li_VR1][VR1_VR2_Offset] += g12;
611  dFdx[li_VR1][VR1_VI1_Offset] -= b11;
612  dFdx[li_VR1][VR1_VI2_Offset] -= b12;
613 
614  dFdx[li_VR2][VR2_VR1_Offset] += g21;
615  dFdx[li_VR2][VR2_VR2_Offset] += g22;
616  dFdx[li_VR2][VR2_VI1_Offset] -= b21;
617  dFdx[li_VR2][VR2_VI2_Offset] -= b22;
618 
619  dFdx[li_VI1][VI1_VR1_Offset] += b11;
620  dFdx[li_VI1][VI1_VR2_Offset] += b12;
621  dFdx[li_VI1][VI1_VI1_Offset] += g11;
622  dFdx[li_VI1][VI1_VI2_Offset] += g12;
623 
624  dFdx[li_VI2][VI2_VR1_Offset] += b21;
625  dFdx[li_VI2][VI2_VR2_Offset] += b22;
626  dFdx[li_VI2][VI2_VI1_Offset] += g21;
627  dFdx[li_VI2][VI2_VI2_Offset] += g22;
628  }
629  else if (analysisType_ == PQR)
630  {
631  double * solVec = extData.nextSolVectorRawPtr;
632 
633  dFdx[li_VR1][VR1_VR1_Offset] += 2*g11*solVec[li_VR1] + g12*solVec[li_VR2] - b12*solVec[li_VI2];
634  dFdx[li_VR1][VR1_VR2_Offset] += g12*solVec[li_VR1] + b12*solVec[li_VI1];
635  dFdx[li_VR1][VR1_VI1_Offset] += 2*g11*solVec[li_VI1] + b12*solVec[li_VR2] + g12*solVec[li_VI2];
636  dFdx[li_VR1][VR1_VI2_Offset] += g12*solVec[li_VI1] - b12*solVec[li_VR1];
637 
638  dFdx[li_VR2][VR2_VR1_Offset] += g21*solVec[li_VR2] + b21*solVec[li_VI2];
639  dFdx[li_VR2][VR2_VR2_Offset] += 2*g22*solVec[li_VR2] + g21*solVec[li_VR1] - b21*solVec[li_VI1];
640  dFdx[li_VR2][VR2_VI1_Offset] += g21*solVec[li_VI2] - b21*solVec[li_VR2];
641  dFdx[li_VR2][VR2_VI2_Offset] += 2*g22*solVec[li_VI2] + b21*solVec[li_VR1] + g21*solVec[li_VI1];
642 
643  dFdx[li_VI1][VI1_VR1_Offset] += -2*b11*solVec[li_VR1] - b12*solVec[li_VR2] - g12*solVec[li_VI2];
644  dFdx[li_VI1][VI1_VR2_Offset] += g12*solVec[li_VI1] - b12*solVec[li_VR1];
645  dFdx[li_VI1][VI1_VI1_Offset] += -2*b11*solVec[li_VI1] + g12*solVec[li_VR2] - b12*solVec[li_VI2];
646  dFdx[li_VI1][VI1_VI2_Offset] -= g12*solVec[li_VR1] + b12*solVec[li_VI1];
647 
648  dFdx[li_VI2][VI2_VR1_Offset] += g21*solVec[li_VI2] - b21*solVec[li_VR2];
649  dFdx[li_VI2][VI2_VR2_Offset] += -2*b22*solVec[li_VR2] - b21*solVec[li_VR1] - g12*solVec[li_VI1];
650  dFdx[li_VI2][VI2_VI1_Offset] -= g21*solVec[li_VR2] + b21*solVec[li_VI2];
651  dFdx[li_VI2][VI2_VI2_Offset] += -2*b22*solVec[li_VI2] + g21*solVec[li_VR1] - b21*solVec[li_VI1];
652  }
653  else if (analysisType_ == PQP)
654  {
655  double * solVec = extData.nextSolVectorRawPtr;
656  double dSin12 = sin(solVec[li_Theta1]-solVec[li_Theta2]);
657  double dSin21 = sin(solVec[li_Theta2]-solVec[li_Theta1]);
658  double dCos12 = cos(solVec[li_Theta1]-solVec[li_Theta2]);
659  double dCos21 = cos(solVec[li_Theta2]-solVec[li_Theta1]);
660 
661  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
662  {
663  Xyce::dout() << getName() << ": dFdx info is: " << std::endl
664  << "(dSin12,dSin21,dCos12,dCos21 = (" << dSin12 << " , " << dSin21
665  << " , " << dCos12 << " , " << dCos21 << ")" << std::endl
666  << "(solVec[li_Theta1],solVec[li_Theta2]) = (" << solVec[li_Theta1]
667  << " , " << solVec[li_Theta2] << ")" << std::endl
668  << "(solVec[li_VM1],solVec[li_VM2]) = (" << solVec[li_VM1]
669  << " , " << solVec[li_VM2] << ")" << std::endl;
670  }
671 
672  // dP / dTheta terms
673  dFdx[li_Theta1][Theta1_Theta1_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
674  dFdx[li_Theta1][Theta1_Theta2_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
675  dFdx[li_Theta2][Theta2_Theta1_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g21*dSin21 - b21*dCos21);
676  dFdx[li_Theta2][Theta2_Theta2_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g21*dSin21 - b21*dCos21);
677 
678  // dP / dV terms
679  dFdx[li_Theta1][Theta1_VM1_Offset] += 2*solVec[li_VM1]*g11 + solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
680  dFdx[li_Theta1][Theta1_VM2_Offset] += solVec[li_VM1]*(g12*dCos12 + b12*dSin12);
681  dFdx[li_Theta2][Theta2_VM1_Offset] += solVec[li_VM2]*(g21*dCos21 + b21*dSin21);
682  dFdx[li_Theta2][Theta2_VM2_Offset] += 2*solVec[li_VM2]*g22 + solVec[li_VM1]*(g21*dCos21 + b21*dSin21);
683 
684  // dQ / dTheta terms
685  dFdx[li_VM1][VM1_Theta1_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
686  dFdx[li_VM1][VM1_Theta2_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g12*dCos12 + b12*dSin12);
687  dFdx[li_VM2][VM2_Theta1_Offset] -= solVec[li_VM1]*solVec[li_VM2]*(g21*dCos21 + b21*dSin21);
688  dFdx[li_VM2][VM2_Theta2_Offset] += solVec[li_VM1]*solVec[li_VM2]*(g21*dCos21 + b21*dSin21);
689 
690  // dQ / dV terms
691  dFdx[li_VM1][VM1_VM1_Offset] += -2*solVec[li_VM1]*b11 + solVec[li_VM2]*(g12*dSin12 - b12*dCos12);
692  dFdx[li_VM1][VM1_VM2_Offset] += solVec[li_VM1]*(g12*dSin12 - b12*dCos12);
693  dFdx[li_VM2][VM2_VM1_Offset] += solVec[li_VM2]*(g21*dSin21 - b21*dCos21);
694  dFdx[li_VM2][VM2_VM2_Offset] += -2*solVec[li_VM2]*b22 + solVec[li_VM1]*(g21*dSin21 - b21*dCos21);
695  }
696  else
697  {
698  UserError0(*this) << "Analysis Type must be IV, PQR or PQP in power grid device: " << getName();
699  return false;
700  }
701 
702  if (getSolverState().dcopFlag)
703  {
704  // no op placeholder code;
705  }
706  else
707  {
708  // no op placeholder code;
709  }
710 
711  return true;
712 }
713 
714 //-----------------------------------------------------------------------------
715 // Function : Instance::loadDAEdQdx ()
716 //
717 // Purpose : Loads the Q-vector contributions. This is no-op for this
718 // model.
719 //
720 // Special Notes :
721 //
722 // Scope : public
723 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
724 // Creation Date : 9/12/14
725 //-----------------------------------------------------------------------------
727 {
728  return true;
729 }
730 
731 //-----------------------------------------------------------------------------
732 // Function : Model::Model
733 // Purpose : "Model block" constructor
734 // Special Notes :
735 // Scope : public
736 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
737 // Creation Date : 9/12/14
738 //-----------------------------------------------------------------------------
739 
740 
741 // These are all just placeholder functions, as there is nothing to the model
742 // class.
743 // Class Model
744 
745 //-----------------------------------------------------------------------------
746 // Function : Model::Model
747 // Purpose : "Model block" constructor
748 // Special Notes :
749 // Scope : public
750 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
751 // Creation Date : 9/12/14
752 //-----------------------------------------------------------------------------
754  const Configuration & configuration,
755  const ModelBlock & MB,
756  const FactoryBlock & factory_block)
757  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
758 {
759 }
760 
761 //-----------------------------------------------------------------------------
762 // Function : Model::~Model
763 // Purpose : destructor
764 // Special Notes :
765 // Scope : public
766 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
767 // Creation Date : 9/12/14
768 //-----------------------------------------------------------------------------
770 {
771  std::vector<Instance*>::iterator iter;
772  std::vector<Instance*>::iterator first = instanceContainer.begin();
773  std::vector<Instance*>::iterator last = instanceContainer.end();
774 
775  for (iter=first; iter!=last; ++iter)
776  {
777  delete (*iter);
778  }
779 }
780 
781 //-----------------------------------------------------------------------------
782 // Function : Model::printOutInstances
783 // Purpose : debugging tool.
784 // Special Notes :
785 // Scope : public
786 // Creator : Pete Sholander, SNL, Electrical and Microsystems Modeling
787 // Creation Date : 9/12/14
788 //-----------------------------------------------------------------------------
789 std::ostream &Model::printOutInstances(std::ostream &os) const
790 {
791  std::vector<Instance*>::const_iterator iter;
792  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
793  std::vector<Instance*>::const_iterator last = instanceContainer.end();
794 
795  int i;
796  os << std::endl;
797  os << " name model name Parameters" << std::endl;
798  for (i=0, iter=first; iter!=last; ++iter, ++i)
799  {
800  os << " " << i << ": " << (*iter)->getName() << " ";
801  os << getName();
802  os << std::endl;
803  }
804 
805  os << std::endl;
806 
807  return os;
808 }
809 
810 //-----------------------------------------------------------------------------
811 // Function : Model::forEachInstance
812 // Purpose :
813 // Special Notes :
814 // Scope : public
815 // Creator : David Baur
816 // Creation Date : 2/4/2014
817 //-----------------------------------------------------------------------------
818 /// Apply a device instance "op" to all instances associated with this
819 /// model
820 ///
821 /// @param[in] op Operator to apply to all instances.
822 ///
823 ///
824 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
825 {
826  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
827  op(*it);
828 }
829 
830 
831 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
832 {
833 
834  return new DeviceMaster<Traits>(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
835 }
836 
838 {
840  .registerDevice("PowerGridBusShunt", 1)
841  .registerDevice("PGBS", 1)
842  .registerModelType("PowerGridBusShunt", 1);
843 }
844 
845 } // namespace PowerGridBusShunt
846 } // namespace Device
847 } // 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)