Xyce  6.1
N_DEV_Bsrc.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_Bsrc.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Robert J Hoekstra, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 06/05/01
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.208 $
40 //
41 // Revision Date : $Date: 2015/09/23 18:29:48 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 #include <N_UTL_Math.h>
49 
50 // ---------- Xyce Includes ----------
51 #include <N_DEV_Bsrc.h>
52 #include <N_DEV_DeviceOptions.h>
53 #include <N_DEV_ExternData.h>
54 #include <N_DEV_MatrixLoadData.h>
55 #include <N_DEV_SolverState.h>
56 #include <N_DEV_Message.h>
57 #include <N_ERH_ErrorMgr.h>
58 
59 #include <N_LAS_Vector.h>
60 #include <N_LAS_Matrix.h>
61 
62 #include <N_UTL_Expression.h>
63 #include <N_UTL_BreakPoint.h>
64 #include <N_UTL_FeatureTest.h>
65 
66 namespace Xyce {
67 namespace Device {
68 
69 
70 namespace Bsrc {
71 
72 
74 {
75  // Set up configuration constants:
76 // Set up double precision variables:
77  p.addPar("I", 0.0, &Bsrc::Instance::I)
78  .setExpressionAccess(ParameterType::SOLN_DEP)
79  .setUnit(U_AMP)
80  .setDescription("Current for current source");
81 
82  p.addPar("V", 0.0, &Bsrc::Instance::V)
83  .setExpressionAccess(ParameterType::SOLN_DEP)
84  .setUnit(U_VOLT)
85  .setDescription("Voltage for voltage source");
86 
87  p.addPar("TEMP", 0.0, &Bsrc::Instance::temp)
88  .setUnit(U_DEGC)
89  .setCategory(CAT_NONE)
90  .setDescription("Device temperature");
91 }
92 
94 {}
95 
96 
97 #define Xyce_NONPOINTER_MATRIX_LOAD 1
98 
99 // Class Instance
100 //-----------------------------------------------------------------------------
101 // Function : Instance::Instance
102 // Purpose : "instance block" constructor
103 // Special Notes :
104 // Scope : public
105 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
106 // Creation Date : 06/05/01
107 //-----------------------------------------------------------------------------
109  const Configuration & configuration,
110  const InstanceBlock & IB,
111  Model & BMiter,
112  const FactoryBlock & factory_block)
113  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
114  model_(BMiter),
115  IB(IB),
116  li_Pos(-1),
117  li_Neg(-1),
118  li_Bra(-1),
119  li_store_branch(-1),
120  li_branch_data(0),
121  ABraEquPosNodeOffset(-1),
122  ABraEquNegNodeOffset(-1),
123  APosEquBraVarOffset(-1),
124  ANegEquBraVarOffset(-1),
125  fBraEquPosNodePtr(0),
126  fBraEquNegNodePtr(0),
127  fPosEquBraVarPtr(0),
128  fNegEquBraVarPtr(0),
129  Exp_ptr(0),
130  isVSRC(false),
131  scale(1.0),
132  nlstep(-1),
133  expNumVars(0),
134  expBaseVar(0),
135  expNumDdt(0),
136  expVal(0)
137 {
138  numIntVars = 1;
139  numExtVars = 2;
140  numStateVars = 0;
141  setNumBranchDataVars(0); // by default don't allocate space in branch vectors
142  numBranchDataVarsIfAllocated = 1; // this is the space to allocate if lead current or power is needed.
143 
144  // Set params to constant default values:
145  setDefaultParams ();
146 
147  // Set params according to instance line and constant defaults from metadata:
148  setParams (IB.params);
149 
150  // Set any non-constant parameter defaults:
151  if (given("I") && !given("V"))
152  {
153  isVSRC = false;
154  // current source doesn't have current as part of the solution vector
155  // so store it in the store vector
156  setNumStoreVars(1);
157  }
158  else if (!given("I") && given("V"))
159  {
160  isVSRC = true;
161  }
162  else
163  {
164  UserError0(*this) << "Must supply one of V= or I=";
165  }
166 
167  if (isVSRC)
168  {
169  numIntVars = 1;
170  }
171  else
172  {
173  numIntVars = 0;
174  }
175 
176  std::vector<Depend>::const_iterator d;
177  std::vector<Depend>::const_iterator begin = getDependentParams().begin();
178  std::vector<Depend>::const_iterator end = getDependentParams().end();
179 
180  for (d = begin ; d != end ; ++d)
181  {
182  if (d->name == "I" || d->name == "V")
183  {
184  expNumVars = d->n_vars;
185  expBaseVar = d->lo_var;
186  Exp_ptr = d->expr;
187 
188  expNumDdt = Exp_ptr->getNumDdt();
189  ddtVals.resize(expNumDdt);
190  li_ddt.resize(expNumDdt);
192 
193  expVarDerivs.resize(expNumVars);
194  myVarVals.resize(expNumVars);
195  break;
196  }
197  }
198 
199  if( jacStamp.empty() )
200  {
201  if( isVSRC )
202  {
203  jacStamp.resize(3);
204  jacStamp[0].resize(1);
205  jacStamp[0][0]=2;
206  jacStamp[1].resize(1);
207  jacStamp[1][0]=2;
208  jacStamp[2].resize(2+expNumVars);
209  jacStamp[2][0]=0;
210  jacStamp[2][1]=1;
211  for( int i = 0; i < expNumVars; ++i )
212  jacStamp[2][i+2] = i+3;
213  }
214  else
215  {
216  jacStamp.resize( 2 );
217  jacStamp[0].resize(expNumVars);
218  jacStamp[1].resize(expNumVars);
219  for( int i = 0; i < expNumVars; ++i )
220  {
221  jacStamp[0][i] = i+2;
222  jacStamp[1][i] = i+2;
223  }
224  }
225  }
226 
227  // Calculate any parameters specified as expressions:
228 
230 
231  // calculate dependent (ie computed) params and check for errors:
232 
233  processParams();
234 
235 }
236 
237 //-----------------------------------------------------------------------------
238 // Function : Instance::processParams
239 // Purpose :
240 // Special Notes :
241 // Scope : public
242 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
243 // Creation Date : 07/30/03
244 //-----------------------------------------------------------------------------
246 {
248 
249  return true;
250 }
251 
252 //-----------------------------------------------------------------------------
253 // Function : Instance::updateTemperature
254 // Purpose :
255 // Special Notes :
256 // Scope : public
257 // Creator :
258 // Creation Date :
259 //-----------------------------------------------------------------------------
260 bool Instance::updateTemperature(const double & temp_tmp)
261 {
262  updateDependentParameters(temp_tmp);
263 
264  if (expNumVars == 0)
265  {
266  if (isVSRC)
267  {
268  expVal = V;
269  }
270  else
271  {
272  expVal = I;
273  }
274  }
275 
276  return true;
277 }
278 
279 //-----------------------------------------------------------------------------
280 // Function : Instance::~Instance
281 // Purpose : destructor
282 // Special Notes :
283 // Scope : public
284 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
285 // Creation Date : 06/05/01
286 //-----------------------------------------------------------------------------
288 {
289 }
290 
291 // Additional Declarations
292 //-----------------------------------------------------------------------------
293 // Function : Instance::registerLIDs
294 // Purpose :
295 // Special Notes :
296 // Scope : public
297 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
298 // Creation Date : 6/21/02
299 //-----------------------------------------------------------------------------
300 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
301  const std::vector<int> & extLIDVecRef )
302 {
303  AssertLIDs(intLIDVecRef.size() == numIntVars);
304  AssertLIDs(extLIDVecRef.size() == numExtVars);
305 
306  if (DEBUG_DEVICE)
307  {
308  Xyce::dout() << std::endl << section_divider << std::endl;
309  Xyce::dout() << " BsrcInstance::registerLIDs" << std::endl;
310  Xyce::dout() << " name = " << getName() << std::endl;
311  }
312 
313  // copy over the global ID lists.
314  intLIDVec = intLIDVecRef;
315  extLIDVec = extLIDVecRef;
316 
317  // Now use these lists to obtain the indices into the
318  // linear algebra entities. This assumes an order.
319  // For the matrix indices, first do the rows.
320 
321  li_Pos = extLIDVec[0];
322  li_Neg = extLIDVec[1];
323 
324  if (DEBUG_DEVICE)
325  {
326  Xyce::dout() << " li_Pos = " << li_Pos << std::endl;
327  Xyce::dout() << " li_Neg = " << li_Neg << std::endl;
328  }
329 
330  if( isVSRC )
331  {
332  li_Bra = intLIDVec[0];
333 
334  if (DEBUG_DEVICE)
335  {
336  Xyce::dout() << " li_Bra = " << li_Bra << std::endl;
337  }
338  }
339 
340  if (DEBUG_DEVICE)
341  {
342  Xyce::dout() << section_divider << std::endl;
343  }
344 }
345 
346 //-----------------------------------------------------------------------------
347 // Function : Instance::registerBranchDataLIDs
348 // Purpose :
349 // Special Notes :
350 // Scope : public
351 // Creator : Richard Schiek, Electrical Systems Modeling
352 // Creation Date : 12/18/2012
353 //-----------------------------------------------------------------------------
354 /// Register the local store IDs
355 ///
356 /// In addition to state vector, Xyce maintains a separate datastructure
357 /// called a "branch data" vector. As with other such vectors, the device
358 /// declares at construction time how many branch vector entries it needs,
359 /// and later Topology assigns locations for devices, returning LIDs.
360 ///
361 /// These LIDs are stored in this method for later use.
362 ///
363 /// The Resistor device uses exactly one "branch data vector" element, where
364 ///
365 /// @param stoLIDVecRef Store variable local IDs
366 ///
367 /// @author Richard Schiek, Electrical Systems Modeling
368 /// @date 12/18/2012
369 
370 void Instance::registerBranchDataLIDs(const std::vector<int> & branchLIDVecRef)
371 {
372  AssertLIDs(branchLIDVecRef.size() == getNumBranchDataVars());
373 
374  if (loadLeadCurrent)
375  {
376  li_branch_data= branchLIDVecRef[0];
377  }
378 }
379 
380 //-----------------------------------------------------------------------------
381 // Function : Instance::loadNodeSymbols
382 // Purpose :
383 // Special Notes :
384 // Scope : public
385 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
386 // Creation Date : 05/13/05
387 //-----------------------------------------------------------------------------
388 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
389 {
390  if (isVSRC)
391  addInternalNode(symbol_table, li_Bra, getName(), "branch");
392 
393  if (!isVSRC)
394  addStoreNode(symbol_table, li_store_branch, getName(), "DEV_I");
395 
396  if (loadLeadCurrent)
397  {
398  addBranchDataNode( symbol_table, li_branch_data, getName(), "BRANCH_D");
399  }
400 
401 }
402 
403 //-----------------------------------------------------------------------------
404 // Function : Instance::registerStoreLIDs
405 // Purpose : One store var for device current if this is a current source
406 // Special Notes :
407 // Scope : public
408 // Creator : Richard Schiek, Electrical Systems Modeling
409 // Creation Date : 01/17/2013
410 //-----------------------------------------------------------------------------
411 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef )
412 {
413  if (!isVSRC)
414  {
415  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
416 
417  li_store_branch = stoLIDVecRef[0];
418  }
419 }
420 
421 //-----------------------------------------------------------------------------
422 // Function : Instance::registerStateLIDs
423 // Purpose :
424 // Special Notes :
425 // Scope : public
426 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
427 // Creation Date : 06/21/02
428 //-----------------------------------------------------------------------------
429 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
430 {
431  AssertLIDs(staLIDVecRef.size() == numStateVars);
432  AssertLIDs(li_ddt.size() == expNumDdt);
434 
435  for (int i=0 ; i<expNumDdt ; ++i)
436  {
437  li_ddt[i] = staLIDVecRef[i];
438  }
439 }
440 
441 
442 //-----------------------------------------------------------------------------
443 // Function : Instance::getDepSolnVars
444 // Purpose :
445 // Special Notes :
446 // Scope : public
447 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
448 // Creation Date : 06/06/01
449 //-----------------------------------------------------------------------------
450 const std::vector<std::string> & Instance::getDepSolnVars()
451 {
453 }
454 
455 
456 //-----------------------------------------------------------------------------
457 // Function : Instance::jacobianStamp
458 // Purpose :
459 // Special Notes :
460 // Scope : public
461 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
462 // Creation Date : 9/2/02
463 //-----------------------------------------------------------------------------
464 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
465 {
466  return jacStamp;
467 }
468 
469 //-----------------------------------------------------------------------------
470 // Function : Instance::registerJacLIDs
471 // Purpose :
472 // Special Notes :
473 // Scope : public
474 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
475 // Creation Date : 9/2/02
476 //-----------------------------------------------------------------------------
478  const std::vector< std::vector<int> > & jacLIDVec)
479 {
480  DeviceInstance::registerJacLIDs( jacLIDVec );
481  if( isVSRC )
482  {
483  APosEquBraVarOffset = jacLIDVec[0][0];
484  ANegEquBraVarOffset = jacLIDVec[1][0];
485  ABraEquPosNodeOffset = jacLIDVec[2][0];
486  ABraEquNegNodeOffset = jacLIDVec[2][1];
488  for( int i = 0; i < expNumVars; ++i )
489  {
490  ABraEquExpVarOffsets[i] = jacLIDVec[2][i+2];
491  }
492  }
493  else
494  {
497  for( int i = 0; i < expNumVars; ++i )
498  {
499  APosEquExpVarOffsets[i] = jacLIDVec[0][i];
500  ANegEquExpVarOffsets[i] = jacLIDVec[1][i];
501  }
502 
503  }
504 }
505 
506 
507 //-----------------------------------------------------------------------------
508 // Function : Instance::setupPointers
509 // Purpose :
510 // Special Notes :
511 // Scope : public
512 // Creator : Eric Keiter, SNL
513 // Creation Date : 11/30/08
514 //-----------------------------------------------------------------------------
516 {
517 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
518  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
519 
520  if( isVSRC )
521  {
526 
527  fBraEquExpVarPtrs.resize( expNumVars );
528  for( int i = 0; i < expNumVars; ++i )
529  {
530  fBraEquExpVarPtrs[i] = &(dFdx[li_Bra][ ABraEquExpVarOffsets[i] ]);
531  }
532  }
533  else
534  {
535  fPosEquExpVarPtrs.resize( expNumVars );
536  fNegEquExpVarPtrs.resize( expNumVars );
537  for( int i = 0; i < expNumVars; ++i )
538  {
539  fPosEquExpVarPtrs[i] = &(dFdx[li_Pos][ APosEquExpVarOffsets[i] ]);
540  fNegEquExpVarPtrs[i] = &(dFdx[li_Neg][ ANegEquExpVarOffsets[i] ]);
541  }
542  }
543 
544 #endif
545 }
546 
547 //-----------------------------------------------------------------------------
548 // Function : Instance::updateIntermediateVars
549 //
550 // Purpose : Calls the expression handler to evaluate the expression
551 // and various derivatives. These quantities are needed
552 // for the vector and matrix loads.
553 //
554 // Special Notes :
555 //
556 // Scope : public
557 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
558 // Creation Date : 06/05/01
559 //-----------------------------------------------------------------------------
561 {
562  if (expNumVars == 0)
563  {
564  if (isVSRC)
565  {
566  expVal = V;
567  }
568  else
569  {
570  expVal = I;
571  }
572  }
573 
574  return true;
575 }
576 
577 //-----------------------------------------------------------------------------
578 // Function : Instance::updatePrimaryState
579 // Purpose :
580 // Special Notes :
581 // Scope : public
582 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
583 // Creation Date : 06/05/01
584 //-----------------------------------------------------------------------------
586 {
587  bool bsuccess=updateIntermediateVars ();
588 
589  // Get values of the arguments for ddt() calls in expression so that the derivatives
590  // can be determined by the time integration class
591  if (expNumDdt > 0)
592  {
593  double * staVec = extData.nextStaVectorRawPtr;
594 
595  Exp_ptr->getDdtVals (ddtVals);
596  for (int i=0 ; i<expNumDdt ; ++i)
597  {
598  staVec[li_ddt[i]] = ddtVals[i];
599  }
600  }
601 
602  return bsuccess;
603 }
604 
605 //-----------------------------------------------------------------------------
606 // Function : Instance::updateSecondaryState
607 // Purpose :
608 // Special Notes :
609 // Scope : public
610 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
611 // Creation Date : 06/05/01
612 //-----------------------------------------------------------------------------
614 {
615  // Get time derivatives from time integrator, and evaluate expression to get
616  // derivatives with respect to independent quantities
617 
618  if (expNumDdt > 0)
619  {
620  double * staDerivVec = extData.nextStaDerivVectorRawPtr;
621 
622  for (int i=0 ; i<expNumDdt ; ++i)
623  {
624  ddtVals[i] = staDerivVec[li_ddt[i]];
625  }
626  Exp_ptr->setDdtDerivs(ddtVals);
627  }
628  // Evaluate Expression with corrected time derivative values
629  if (expNumVars != 0)
630  {
631  Exp_ptr->evaluate( expVal, expVarDerivs);
632  }
633 
634  // Test derivatives, if too big, zero out
635  for (int i = 0; i < expNumVars; ++i)
636  {
637  double maxMag = 1.0e+10;
638  if (expVarDerivs[i] > maxMag || expVarDerivs[i] < -maxMag)
639  {
640  static Report::MessageCode id;
641 
642  Report::UserWarning(id) << "Expression derivative |" << expVarDerivs[i] << "| exceeds " << maxMag << ", value reduced";
643 
644  expVarDerivs[i] = (expVarDerivs[i] > 0) ? maxMag : -maxMag;
645  }
646  }
647 
648  return true;
649 }
650 
651 //-----------------------------------------------------------------------------
652 // Function : Instance::loadDAEFVector
653 //
654 // Purpose : Loads the F-vector contributions for a single
655 // vsrc instance.
656 //
657 // Special Notes : See the special notes for loadDAEFVector.
658 //
659 // Scope : public
660 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
661 // Creation Date : 04/27/04
662 //-----------------------------------------------------------------------------
664 {
665  double source(0.0), v_pos(0.0), v_neg(0.0), i_bra(0.0);
666  double * solVec = extData.nextSolVectorRawPtr;
667  double * fVec = extData.daeFVectorRawPtr;
668  double * stoVec = extData.nextStoVectorRawPtr;
669 
670  source = expVal;
671 
672  //VSRC or ISRC
673  if (isVSRC)
674  {
675  // get the value for v_pos, v_neg, i_bra
676  v_pos = solVec[li_Pos];
677  v_neg = solVec[li_Neg];
678  i_bra = solVec[li_Bra];
679 
680  double c_tmp = i_bra;
681  double v_tmp = (v_pos-v_neg-source);
682 
683  fVec[li_Pos] += c_tmp;
684  fVec[li_Neg] += -c_tmp;
685  fVec[li_Bra] += v_tmp;
686 
687  if( loadLeadCurrent )
688  {
689  double * leadF = extData.nextLeadCurrFCompRawPtr;
690  leadF[li_branch_data] = c_tmp;
691  double * junctionV = extData.nextJunctionVCompRawPtr;
692  junctionV[li_branch_data] = v_tmp;
693  }
694 
695  }
696  else
697  {
698  fVec[li_Pos] += source;
699  fVec[li_Neg] += -source;
700 
701  stoVec[li_store_branch] = source;
702  if( loadLeadCurrent )
703  {
704  double * leadF = extData.nextLeadCurrFCompRawPtr;
705  leadF[li_branch_data] = source;
706  double * junctionV = extData.nextJunctionVCompRawPtr;
707  junctionV[li_branch_data] = solVec[li_Pos] - solVec[li_Neg];
708  }
709  }
710 
711  return true;
712 }
713 
714 //-----------------------------------------------------------------------------
715 // Function : Instance::loadDAEdFdx ()
716 //
717 // Purpose : Loads the F-vector contributions for a single
718 // resistor instance.
719 //
720 // Special Notes :
721 //
722 // Scope : public
723 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
724 // Creation Date : 04/27/04
725 //-----------------------------------------------------------------------------
727 {
728  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
729 
730  double coef = 1.0;
731 
732  if( isVSRC )
733  {
734  if( getDeviceOptions().scale_src != 0.0 )
735  {
736  coef *= scale;
737  }
738 
739  dFdx[li_Pos][APosEquBraVarOffset] += coef;
740  dFdx[li_Neg][ANegEquBraVarOffset] -= coef;
741  dFdx[li_Bra][ABraEquPosNodeOffset] += coef;
742  dFdx[li_Bra][ABraEquNegNodeOffset] -= coef;
743 
744  for( int i = 0; i < expNumVars; ++i )
745  {
746  dFdx[li_Bra][ABraEquExpVarOffsets[i]] -= expVarDerivs[i];
747  }
748  }
749  else
750  {
751  if( expNumVars )
752  {
753  for( int i = 0; i < expNumVars; ++i )
754  {
755  dFdx[li_Pos][APosEquExpVarOffsets[i]] += expVarDerivs[i];
756  dFdx[li_Neg][ANegEquExpVarOffsets[i]] -= expVarDerivs[i];
757  }
758  }
759  }
760 
761  return true;
762 }
763 
764 //-----------------------------------------------------------------------------
765 // Function : Instance::varTypes
766 // Purpose :
767 // Special Notes :
768 // Scope : public
769 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
770 // Creation Date : 02/17/02
771 //-----------------------------------------------------------------------------
772 void Instance::varTypes( std::vector<char> & varTypeVec )
773 {
774  if( !isVSRC )
775  {
776  varTypeVec.resize(1);
777  varTypeVec[0] = 'I';
778  }
779 }
780 
781 // Class Model
782 
783 //-----------------------------------------------------------------------------
784 // Function : Model::Model
785 // Purpose : constructor
786 // Special Notes :
787 // Scope : public
788 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
789 // Creation Date : 06/05/01
790 //-----------------------------------------------------------------------------
792  const Configuration & configuration,
793  const ModelBlock & MB,
794  const FactoryBlock & factory_block)
795  : DeviceModel(MB, configuration.getModelParameters(), factory_block)
796 {
797 }
798 
799 //-----------------------------------------------------------------------------
800 // Function : Model::~Model
801 // Purpose : destructor
802 // Special Notes :
803 // Scope : public
804 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
805 // Creation Date : 06/05/01
806 //-----------------------------------------------------------------------------
808 {
809  std::vector<Instance*>::iterator iter;
810  std::vector<Instance*>::iterator first = instanceContainer.begin();
811  std::vector<Instance*>::iterator last = instanceContainer.end();
812 
813  for (iter=first; iter!=last; ++iter)
814  {
815  delete (*iter);
816  }
817 }
818 
819 //-----------------------------------------------------------------------------
820 // Function : DeviceModel::processParams
821 // Purpose :
822 // Special Notes :
823 // Scope : public
824 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
825 // Creation Date : 06/03/02
826 //-----------------------------------------------------------------------------
828 {
829  return true;
830 }
831 
832 //-----------------------------------------------------------------------------
833 // Function : DeviceModel::processInstanceParams
834 // Purpose :
835 // Special Notes :
836 // Scope : public
837 // Creator : Dave Shirley, PSSI
838 // Creation Date : 03/23/06
839 //-----------------------------------------------------------------------------
841 {
842  return true;
843 }
844 
845 // Additional Declarations
846 
847 //-----------------------------------------------------------------------------
848 // Function : Model::printOutInstances
849 // Purpose : debugging tool.
850 // Special Notes :
851 // Scope : public
852 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
853 // Creation Date : 6/05/01
854 //-----------------------------------------------------------------------------
855 std::ostream &Model::printOutInstances(std::ostream &os) const
856 {
857  std::vector<Instance*>::const_iterator iter;
858  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
859  std::vector<Instance*>::const_iterator last = instanceContainer.end();
860 
861  int i;
862  os << std::endl;
863  os << " name model name Parameters" << std::endl;
864  for (i=0, iter=first; iter!=last; ++iter, ++i)
865  {
866  os << " " << i << ": " << (*iter)->getName() << " ";
867  os << getName();
868  os << std::endl;
869  }
870 
871  os << std::endl;
872 
873  return os;
874 }
875 
876 //-----------------------------------------------------------------------------
877 // Function : Model::forEachInstance
878 // Purpose :
879 // Special Notes :
880 // Scope : public
881 // Creator : David Baur
882 // Creation Date : 2/4/2014
883 //-----------------------------------------------------------------------------
884 /// Apply a device instance "op" to all instances associated with this
885 /// model
886 ///
887 /// @param[in] op Operator to apply to all instances.
888 ///
889 ///
890 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
891 {
892  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
893  op(*it);
894 }
895 
896 // Bsrc Master functions:
897 
898 //-----------------------------------------------------------------------------
899 // Function : Master::updateState
900 // Purpose :
901 // Special Notes :
902 // Scope : public
903 // Creator : Eric Keiter, SNL
904 // Creation Date : 11/26/08
905 //-----------------------------------------------------------------------------
906 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
907 {
908  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
909  {
910  Instance & bi = *(*it);
911  if (bi.expNumVars == 0)
912  {
913  if (bi.isVSRC)
914  {
915  bi.expVal = bi.V;
916  }
917  else
918  {
919  bi.expVal = bi.I;
920  stoVec[bi.li_store_branch]=bi.I;
921  }
922  }
923  // Get values of the arguments for ddt() calls in expression so that the derivatives
924  // can be determined by the time integration class
925  if (bi.expNumDdt > 0)
926  {
927  bi.Exp_ptr->getDdtVals (bi.ddtVals);
928  for (int j=0 ; j<bi.expNumDdt ; ++j)
929  {
930  staVec[bi.li_ddt[j]] = bi.ddtVals[j];
931  }
932  }
933  }
934 
935  return true;
936 }
937 
938 //-----------------------------------------------------------------------------
939 // Function : Master::updateSecondaryState
940 // Purpose :
941 // Special Notes :
942 // Scope : public
943 // Creator : Eric Keiter, SNL
944 // Creation Date : 11/26/08
945 //-----------------------------------------------------------------------------
946 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
947 {
948  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
949  {
950  Instance & bi = *(*it);
951 
952  // Get time derivatives from time integrator, and evaluate expression to get
953  // derivatives with respect to independent quantities
954 
955  if (bi.expNumDdt > 0)
956  {
957  for (int j=0 ; j<bi.expNumDdt ; ++j)
958  {
959  bi.ddtVals[j] = staDerivVec[bi.li_ddt[j]];
960  }
961  bi.Exp_ptr->setDdtDerivs(bi.ddtVals);
962  }
963  // Evaluate Expression with corrected time derivative values
964  if (bi.expNumVars != 0)
965  {
966  bi.Exp_ptr->evaluate( bi.expVal, bi.expVarDerivs);
967  if (!bi.isVSRC)
968  {
969  stoVec[bi.li_store_branch]=bi.expVal;
970  }
971  }
972 
973  // Test derivatives, if too big, zero out
974  for (int k = 0; k < bi.expNumVars; ++k)
975  {
976  double maxMag = 1.0e+10;
977  if (bi.expVarDerivs[k] > maxMag || bi.expVarDerivs[k] < -maxMag)
978  {
979  static Report::MessageCode id;
980 
981  Report::UserWarning(id) << "Expression derivative |" << bi.expVarDerivs[k] << "| exceeds " << maxMag << ", value reduced";
982  bi.expVarDerivs[k] = (bi.expVarDerivs[k] > 0) ? maxMag : -maxMag;
983  }
984  }
985  }
986 
987  return true;
988 }
989 
990 //-----------------------------------------------------------------------------
991 // Function : Master::loadDAEVectors
992 // Purpose :
993 // Special Notes :
994 // Scope : public
995 // Creator : Eric Keiter, SNL
996 // Creation Date : 11/26/08
997 //-----------------------------------------------------------------------------
998 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
999 {
1000  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1001  {
1002  Instance & bi = *(*it);
1003  double v_pos(0.0), v_neg(0.0), i_bra(0.0);
1004  double source = bi.expVal;
1005 
1006  //VSRC or ISRC
1007  if (bi.isVSRC)
1008  {
1009  // get the value for v_pos, v_neg, i_bra
1010  v_pos = solVec[bi.li_Pos];
1011  v_neg = solVec[bi.li_Neg];
1012  i_bra = solVec[bi.li_Bra];
1013 
1014  double c_tmp = i_bra;
1015  double v_tmp = (v_pos-v_neg-source);
1016 
1017  fVec[bi.li_Pos] += c_tmp;
1018  fVec[bi.li_Neg] += -c_tmp;
1019  fVec[bi.li_Bra] += v_tmp;
1020  if( bi.loadLeadCurrent )
1021  {
1022  leadF[bi.li_branch_data] = c_tmp;
1023  junctionV[bi.li_branch_data] = v_pos-v_neg;
1024  }
1025 
1026  }
1027  else
1028  {
1029  fVec[bi.li_Pos] += source;
1030  fVec[bi.li_Neg] += -source;
1031  if( bi.loadLeadCurrent )
1032  {
1033  leadF[bi.li_branch_data] = source;
1034  junctionV[bi.li_branch_data] = solVec[bi.li_Pos] - solVec[bi.li_Neg];
1035  }
1036  }
1037  }
1038  return true;
1039 }
1040 
1041 //-----------------------------------------------------------------------------
1042 // Function : Master::loadDAEMatrices
1043 // Purpose :
1044 // Special Notes :
1045 // Scope : public
1046 // Creator : Eric Keiter, SNL
1047 // Creation Date : 11/26/08
1048 //-----------------------------------------------------------------------------
1049 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
1050 {
1051  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1052  {
1053  Instance & bi = *(*it);
1054  double coef = 1.0;
1055 
1056  if( bi.isVSRC )
1057  {
1058  if( getDeviceOptions().scale_src != 0.0 )
1059  {
1060  coef *= bi.scale;
1061  }
1062 
1063 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1064  *bi.fPosEquBraVarPtr += coef;
1065  *bi.fNegEquBraVarPtr -= coef;
1066  *bi.fBraEquPosNodePtr += coef;
1067  *bi.fBraEquNegNodePtr -= coef;
1068 
1069  for( int j = 0; j < bi.expNumVars; ++j )
1070  {
1071  *bi.fBraEquExpVarPtrs[j] -= bi.expVarDerivs[j];
1072  }
1073 #else
1074  dFdx[bi.li_Pos][bi.APosEquBraVarOffset] += coef;
1075  dFdx[bi.li_Neg][bi.ANegEquBraVarOffset] -= coef;
1076  dFdx[bi.li_Bra][bi.ABraEquPosNodeOffset] += coef;
1077  dFdx[bi.li_Bra][bi.ABraEquNegNodeOffset] -= coef;
1078 
1079  for( int j = 0; j < bi.expNumVars; ++j )
1080  {
1081  dFdx[bi.li_Bra][bi.ABraEquExpVarOffsets[j]] -= bi.expVarDerivs[j];
1082  }
1083 #endif
1084  }
1085  else
1086  {
1087  if( bi.expNumVars )
1088  {
1089 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1090  for( int k = 0; k < bi.expNumVars; ++k )
1091  {
1092  *bi.fPosEquExpVarPtrs[k] += bi.expVarDerivs[k];
1093  *bi.fNegEquExpVarPtrs[k] -= bi.expVarDerivs[k];
1094  }
1095 #else
1096  for( int j = 0; j < bi.expNumVars; ++j )
1097  {
1098  dFdx[bi.li_Pos][bi.APosEquExpVarOffsets[j]] += bi.expVarDerivs[j];
1099  dFdx[bi.li_Neg][bi.ANegEquExpVarOffsets[j]] -= bi.expVarDerivs[j];
1100  }
1101 #endif
1102  }
1103  }
1104  }
1105  return true;
1106 }
1107 
1108 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
1109 {
1110  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
1111 }
1112 
1114 {
1116  .registerDevice("b", 1)
1117  .registerDevice("f", 1)
1118  .registerDevice("h", 1);
1119 }
1120 
1121 } // namespace Bsrc
1122 } // namespace Device
1123 } // namespace Xyce
const InstanceName & getName() const
std::vector< int > APosEquExpVarOffsets
Definition: N_DEV_Bsrc.h:196
const DeviceOptions & deviceOptions_
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
Definition: N_DEV_Bsrc.C:300
std::vector< int > ABraEquExpVarOffsets
Definition: N_DEV_Bsrc.h:198
bool given(const std::string &parameter_name) const
Pure virtual class to augment a linear system.
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Definition: N_DEV_Bsrc.C:388
std::vector< Instance * > instanceContainer
Definition: N_DEV_Bsrc.h:254
void setNumStoreVars(int num_store_vars)
void addBranchDataNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
InstanceVector::const_iterator getInstanceEnd() const
Returns an iterator to the ending of the vector of all instances created for this device...
virtual bool updateSecondaryState(double *staDeriv, double *stoVec)
Updates the devices secondary state information.
Definition: N_DEV_Bsrc.C:946
const std::vector< Depend > & getDependentParams()
#define AssertLIDs(cmp)
std::vector< double > expVarDerivs
Definition: N_DEV_Bsrc.h:158
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
static void loadModelParameters(ParametricData< Model > &model_parameters)
Definition: N_DEV_Bsrc.C:93
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Definition: N_DEV_Bsrc.C:477
virtual bool processInstanceParams()
processInstanceParams
Definition: N_DEV_Bsrc.C:840
const std::vector< std::string > & getDepSolnVars()
Definition: N_DEV_Bsrc.C:450
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Definition: N_DEV_Bsrc.C:1108
std::vector< double > ddtVals
Definition: N_DEV_Bsrc.h:160
virtual bool loadDAEVectors(double *solVec, double *fVec, double *qVec, double *bVec, double *storeLeadF, double *storeLeadQ, double *leadF, double *leadQ, double *junctionV)
Populates the device's ExternData object with these pointers.
Definition: N_DEV_Bsrc.C:998
std::vector< int > ANegEquExpVarOffsets
Definition: N_DEV_Bsrc.h:197
InstanceVector::const_iterator getInstanceBegin() const
Returns an iterator to the beginning of the vector of all instances created for this device...
void registerBranchDataLIDs(const std::vector< int > &branchLIDVecRef)
Register the local store IDs.
Definition: N_DEV_Bsrc.C:370
void setParams(const std::vector< Param > &params)
const std::string & getName() const
std::vector< double * > fNegEquExpVarPtrs
Definition: N_DEV_Bsrc.h:207
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
Definition: N_DEV_Bsrc.C:906
const DeviceOptions & getDeviceOptions() const
bool updateTemperature(const double &temp)
Definition: N_DEV_Bsrc.C:260
std::vector< double > myVarVals
Definition: N_DEV_Bsrc.h:159
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
std::vector< int > li_ddt
Definition: N_DEV_Bsrc.h:179
Linear::Matrix * dFdxMatrixPtr
const DeviceOptions & getDeviceOptions() const
Returns the device options given during device construction.
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_Bsrc.C:73
int li_branch_data
Index for lead current and junction voltage (for power calculations)
Definition: N_DEV_Bsrc.h:187
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
const std::vector< std::vector< int > > & jacobianStamp() const
Definition: N_DEV_Bsrc.C:464
void addStoreNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
Definition: N_DEV_Bsrc.C:890
const SolverState & solverState_
void varTypes(std::vector< char > &varTypeVec)
Definition: N_DEV_Bsrc.C:772
Class Configuration contains device configuration data.
std::vector< double * > fPosEquExpVarPtrs
Definition: N_DEV_Bsrc.h:206
std::vector< std::vector< int > > jacStamp
Definition: N_DEV_Bsrc.h:210
virtual bool processParams()
processParams
Definition: N_DEV_Bsrc.C:827
void setNumBranchDataVars(int num_branch_data_vars)
void registerStoreLIDs(const std::vector< int > &stoLIDVecRef)
Definition: N_DEV_Bsrc.C:411
virtual bool loadDAEMatrices(Linear::Matrix &dFdx, Linear::Matrix &dQdx)
Populates the device's Jacobian object with these pointers.
Definition: N_DEV_Bsrc.C:1049
virtual std::ostream & printOutInstances(std::ostream &os) const
Definition: N_DEV_Bsrc.C:855
double scale_src
scaling for source loads
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
Definition: N_DEV_Bsrc.C:429
ModelBlock represents a .MODEL line from the netlist.
Parameter may be specified as a solution dependent expression from netlist.
Definition: N_DEV_Pars.h:68
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
Util::Expression * Exp_ptr
Definition: N_DEV_Bsrc.h:151
std::vector< double * > fBraEquExpVarPtrs
Definition: N_DEV_Bsrc.h:208
std::vector< Param > params
virtual const std::vector< std::string > & getDepSolnVars()
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &BMiter, const FactoryBlock &factory_block)
Definition: N_DEV_Bsrc.C:108