Xyce  6.1
N_DEV_SW.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_SW.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes : "Creator and Creation Date" are actually the dates
31 // this file was created. When it was created it was
32 // just a placeholder.
33 // Actual implementation of the Xyce voltage controlled
34 // switch occurred on 5/22/2001, and was done by Tom Russo,
35 // SNL, Component Information and Models.
36 //
37 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
38 //
39 // Creation Date : 02/28/00
40 //
41 // Revision Information:
42 // ---------------------
43 //
44 // Revision Number: $Revision: 1.170 $
45 //
46 // Revision Date : $Date: 2015/04/24 20:25:45 $
47 //
48 // Current Owner : $Author: dgbaur $
49 //----------------------------------------------------------------------------
50 
51 #include <Xyce_config.h>
52 
53 
54 // ---------- Standard Includes ----------
55 #include <N_UTL_Math.h>
56 
57 // ---------- Xyce Includes ----------
58 #include <N_DEV_DeviceOptions.h>
59 #include <N_DEV_ExternData.h>
60 #include <N_DEV_MatrixLoadData.h>
61 #include <N_DEV_SW.h>
62 #include <N_DEV_SolverState.h>
63 #include <N_DEV_Message.h>
64 #include <N_ERH_ErrorMgr.h>
65 
66 #include <N_LAS_Matrix.h>
67 #include <N_LAS_Vector.h>
68 
69 #include <N_UTL_Expression.h>
70 
71 namespace Xyce {
72 namespace Device {
73 
74 namespace SW {
75 
77 {
78 // Set up double precision variables:
79  p.addPar ("CONTROL",0.0,&SW::Instance::CONTROL)
80  .setExpressionAccess(ParameterType::SOLN_DEP)
81  .setUnit(U_NONE)
82  .setCategory(CAT_NONE)
83  .setDescription("");
84 
85  // Set up non-double precision variables:
86  p.addPar ("ON",false,&SW::Instance::ON);
87  p.addPar ("OFF",false,&SW::Instance::OFF);
88 }
89 
91 {
92  p.addPar ("RON",1.0,&SW::Model::RON)
93  .setUnit(U_OHM)
94  .setCategory(CAT_NONE)
95  .setDescription("On resistance");
96 
97  p.addPar ("ROFF",1.0e6,&SW::Model::ROFF)
98  .setUnit(U_OHM)
99  .setCategory(CAT_NONE)
100  .setDescription("Off resistance");
101 
102  p.addPar ("VON",1.0,&SW::Model::VON)
103  .setUnit(U_VOLT)
104  .setCategory(CAT_NONE)
105  .setDescription("On voltage");
106 
107  p.addPar ("VOFF",0.0,&SW::Model::VOFF)
108  .setUnit(U_VOLT)
109  .setCategory(CAT_NONE)
110  .setDescription("Off voltage");
111 
112  p.addPar ("ION",0.001,&SW::Model::ION)
113  .setUnit(U_AMP)
114  .setCategory(CAT_NONE)
115  .setDescription("On current");
116 
117  p.addPar ("IOFF",0.0,&SW::Model::IOFF)
118  .setUnit(U_AMP)
119  .setCategory(CAT_NONE)
120  .setDescription("Off current");
121 
122  p.addPar ("ON",1.0,&SW::Model::ON)
123  .setUnit(U_NONE)
124  .setCategory(CAT_NONE)
125  .setDescription("On control value");
126 
127  p.addPar ("OFF",0.0,&SW::Model::OFF)
128  .setUnit(U_NONE)
129  .setCategory(CAT_NONE)
130  .setDescription("Off control value");
131 }
132 
133 // Class Instance
134 //-----------------------------------------------------------------------------
135 // Function : Instance::processParams
136 // Purpose :
137 // Special Notes :
138 // Scope : public
139 // Creator : Dave Shirley, PSSI
140 // Creation Date : 03/16/05
141 //-----------------------------------------------------------------------------
143 {
144  return true;
145 }
146 
147 //-----------------------------------------------------------------------------
148 // Function : Instance::Instance
149 // Purpose : constructor
150 // Special Notes :
151 // Scope : public
152 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
153 // Creation Date : 3/16/00
154 //-----------------------------------------------------------------------------
156  const Configuration & configuration,
157  const InstanceBlock & IB,
158  Model & SWiter,
159  const FactoryBlock & factory_block)
160  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
161  model_(SWiter),
162  R(0.0),
163  ON(false),
164  G(0.0),
165  SW_STATE(0.0),
166  switch_state(0.0),
167  li_switch_state(-1),
168  li_Pos(-1),
169  li_Neg(-1),
170  li_store_dev_i(-1),
171  APosEquPosNodeOffset(-1),
172  APosEquNegNodeOffset(-1),
173  ANegEquPosNodeOffset(-1),
174  ANegEquNegNodeOffset(-1),
175  fPosEquPosNodePtr(0),
176  fPosEquNegNodePtr(0),
177  fNegEquPosNodePtr(0),
178  fNegEquNegNodePtr(0),
179  Exp_ptr(0)
180 {
181  numIntVars = 0;
182  numExtVars = 2;
183  numStateVars = 1;
184  numLeadCurrentStoreVars = 1; // for device lead current if needed.
185 
186  jacStamp.resize(2);
187  jacStamp[0].resize(2);
188  jacStamp[0][0]=0;
189  jacStamp[0][1]=1;
190  jacStamp[1].resize(2);
191  jacStamp[1][0]=0;
192  jacStamp[1][1]=1;
193 
194  // Set params to constant default values:
195  setDefaultParams ();
196 
197  // Set params according to instance line and constant defaults from metadata:
198  setParams (IB.params);
199 
200  // Set any non-constant parameter defaults:
201  if (given("OFF"))
202  {
203  if (given("ON"))
204  {
205  UserError0(*this) << "Cannot specify both 'on' and off' for switch";
206  }
207  ON = !OFF;
208  }
209  if (!given("CONTROL"))
210  {
211  UserError0(*this) << "Must specify 'control' for switch";
212  }
213 
214  std::vector<Depend>::const_iterator d;
215  std::vector<Depend>::const_iterator begin = getDependentParams().begin();
216  std::vector<Depend>::const_iterator end = getDependentParams().end();
217 
218  for (d = begin ; d != end ; ++d)
219  {
220  if (d->name == "CONTROL")
221  {
222  expNumVars = d->n_vars;
223  expBaseVar = d->lo_var;
224  Exp_ptr = d->expr;
225 
226  expNumDdt = Exp_ptr->getNumDdt();
227  ddtVals.resize(expNumDdt);
228  li_ddt.resize(expNumDdt);
230 
231  jacStamp[0].resize(2+expNumVars);
232  jacStamp[1].resize(2+expNumVars);
233  for( int i = 0; i < expNumVars; ++i )
234  {
235  jacStamp[0][2+i] = 2+i;
236  jacStamp[1][2+i] = 2+i;
237  }
238  expVarDerivs.resize(expNumVars);
239  myVarVals.resize(expNumVars);
240  }
241  }
242 
243  // Calculate any parameters specified as expressions:
245 
246  // calculate dependent (ie computed) params and check for errors:
247  processParams ();
248 }
249 
250 //-----------------------------------------------------------------------------
251 // Function : Instance::~Instance
252 // Purpose : destructor
253 // Special Notes :
254 // Scope : public
255 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
256 // Creation Date : 3/16/00
257 //-----------------------------------------------------------------------------
259 {
260 }
261 
262 //-----------------------------------------------------------------------------
263 // Function : Instance::registerLIDs
264 // Purpose :
265 // Special Notes :
266 // Scope : public
267 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
268 // Creation Date : 6/20/02
269 //-----------------------------------------------------------------------------
270 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
271  const std::vector<int> & extLIDVecRef)
272 {
273  AssertLIDs(intLIDVecRef.size() == numIntVars);
274  AssertLIDs(extLIDVecRef.size() == numExtVars);
275 
276  // copy over the global ID lists.
277  intLIDVec = intLIDVecRef;
278  extLIDVec = extLIDVecRef;
279 
280  // now use these lists to obtain the indices into the
281  // linear algebra entities. This assumes an order.
282  // For the matrix indices, first do the rows.
283 
284  li_Pos = extLIDVec[0];
285  li_Neg = extLIDVec[1];
286 
287 }
288 
289 //-----------------------------------------------------------------------------
290 // Function : Instance::registerStateLIDs
291 // Purpose : Note that the SW does not have any state vars.
292 // Special Notes :
293 // Scope : public
294 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
295 // Creation Date : 06/20/02
296 //-----------------------------------------------------------------------------
297 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
298 {
299  AssertLIDs(staLIDVecRef.size() == numStateVars);
300 
301  // copy over the global ID lists:
302  staLIDVec = staLIDVecRef;
303  li_switch_state = staLIDVec[0];
304  for (int i=0 ; i<expNumDdt ; ++i)
305  {
306  li_ddt[i] = staLIDVecRef[i+1];
307  }
308 }
309 
310 //-----------------------------------------------------------------------------
311 // Function : Instance::registerStoreLIDs
312 // Purpose : One store var for device current.
313 // Special Notes :
314 // Scope : public
315 // Creator : Richard Schiek, Electrical Systems Modeling
316 // Creation Date : 04/05/2013
317 //-----------------------------------------------------------------------------
318 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef )
319 {
320  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
321 
322  if( loadLeadCurrent )
323  {
324  li_store_dev_i = stoLIDVecRef[0];
325  }
326 }
327 
328 //-----------------------------------------------------------------------------
329 // Function : Instance::getDepSolnVars
330 // Purpose :
331 // Special Notes :
332 // Scope : public
333 // Creator : Rob Hoekstra, SNL, Parallel Computational Sciences
334 // Creation Date : 06/06/01
335 //-----------------------------------------------------------------------------
336 const std::vector<std::string> & Instance::getDepSolnVars()
337 {
339 }
340 
341 //-----------------------------------------------------------------------------
342 // Function : Instance::jacobianStamp
343 // Purpose :
344 // Special Notes :
345 // Scope : public
346 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
347 // Creation Date : 09/2/02
348 //-----------------------------------------------------------------------------
349 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
350 {
351  return jacStamp;
352 }
353 
354 //-----------------------------------------------------------------------------
355 // Function : Instance::registerJacLIDs
356 // Purpose :
357 // Special Notes :
358 // Scope : public
359 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
360 // Creation Date : 09/2/02
361 //-----------------------------------------------------------------------------
362 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
363 {
364  DeviceInstance::registerJacLIDs( jacLIDVec );
365 
366  APosEquPosNodeOffset = jacLIDVec[0][0];
367  APosEquNegNodeOffset = jacLIDVec[0][1];
368  ANegEquPosNodeOffset = jacLIDVec[1][0];
369  ANegEquNegNodeOffset = jacLIDVec[1][1];
370 
373  for( int i = 0; i < expNumVars; ++i )
374  {
375  APosEquControlNodeOffset[i] = jacLIDVec[0][2+i];
376  ANegEquControlNodeOffset[i] = jacLIDVec[1][2+i];
377  }
378 }
379 
380 //-----------------------------------------------------------------------------
381 // Function : Instance::setupPointers
382 // Purpose :
383 // Special Notes :
384 // Scope : public
385 // Creator : Eric Keiter, SNL
386 // Creation Date : 11/30/08
387 //-----------------------------------------------------------------------------
389 {
390 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
391  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
392  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
393 
398 
401  for( int i = 0; i < expNumVars; ++i )
402  {
405  }
406 #endif
407 }
408 
409 //-----------------------------------------------------------------------------
410 // Function : Instance::updatePrimaryState
411 // Purpose :
412 // Special Notes :
413 // Scope : public
414 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
415 // Creation Date : 01/29/01
416 //-----------------------------------------------------------------------------
418 {
419  double * staVec = extData.nextStaVectorRawPtr;
420  bool bsuccess = updateIntermediateVars ();
421 
422  // obtain the current value of the switch state
424 
425  staVec[li_switch_state] = switch_state;
426 
427  return bsuccess;
428 }
429 
430 //-----------------------------------------------------------------------------
431 // Function : Instance::updateSecondaryState
432 // Purpose :
433 // Special Notes :
434 // Scope : public
435 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
436 // Creation Date : 01/29/01
437 //-----------------------------------------------------------------------------
439 {
440  double current_state;
441  double control;
442  int i;
443 
444  double * solVec = extData.nextSolVectorRawPtr;
445 
446  // Get time derivatives from time integrator, and evaluate expression to get
447  // derivatives with respect to independent quantities
448 
449  if (expNumDdt > 0)
450  {
451  double * staDerivVec = extData.nextStaDerivVectorRawPtr;
452 
453  for (i=0 ; i<expNumDdt ; ++i)
454  {
455  ddtVals[i] = staDerivVec[li_ddt[i]];
456  }
457  Exp_ptr->setDdtDerivs(ddtVals);
458  }
459  // Evaluate Expression with corrected time derivative values
460 
461  Exp_ptr->evaluate( expVal, expVarDerivs );
462  control = expVal;
463 
464  // This is not really correct, an interim hack. This is supposed
465  // to be where we deal with the specification of ON or OFF from the
466  // netlist.
467  if (getSolverState().initJctFlag_)
468  {
469  if (ON)
470  current_state = 1;
471  else
472  current_state = 0;
473  }
474  else
475  {
476  current_state = (control-model_.OFF)*model_.dInv;
477  }
478 
479  v_pos = solVec[li_Pos];
480  v_neg = solVec[li_Neg];
481 
482  if (current_state >= 1.0)
483  {
484  R = model_.RON;
485  G = 1.0/R;
486  for (i=0 ; i<expNumVars ; ++i)
487  expVarDerivs[i] = 0;
488  }
489  else if ( current_state <= 0.0)
490  {
491  R = model_.ROFF;
492  G = 1.0/R;
493  for (i=0 ; i<expNumVars ; ++i)
494  expVarDerivs[i] = 0;
495  }
496  else
497  {
498  current_state = 2*current_state - 1;
499  G = exp(-model_.Lm - 0.75*model_.Lr*current_state +
500  0.25*model_.Lr*current_state*current_state*current_state);
501  R = 1.0/G;
502  for (i=0 ; i<expNumVars ; ++i)
503  {
504  expVarDerivs[i] = G * (1.5 * (current_state*current_state-1) * model_.Lr *
505  model_.dInv * expVarDerivs[i]);
506  }
507  }
508 
509  return true;
510 }
511 
512 //-----------------------------------------------------------------------------
513 // Function : Instance::loadNodeSymbols
514 // Purpose :
515 // Special Notes :
516 // Scope : public
517 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
518 // Creation Date : 05/13/05
519 //-----------------------------------------------------------------------------
520 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
521 {
522  if (loadLeadCurrent)
523  addStoreNode(symbol_table, li_store_dev_i, getName(), "DEV_I");
524 }
525 
526 //-----------------------------------------------------------------------------
527 // Function : Instance::updateIntermediateVars
528 // Purpose : update intermediate variables for one switch instance
529 // Special Notes :
530 // Scope : public
531 // Creator : Tom Russo, Component Information and Models
532 // Creation Date : 1/10/01
533 //-----------------------------------------------------------------------------
535 {
536  // Get values of the arguments for ddt() calls in expression so that the derivatives
537  // can be determined by the time integration class
538  if (expNumDdt > 0)
539  {
540  double * staVec = extData.nextStaVectorRawPtr;
541 
542  Exp_ptr->getDdtVals (ddtVals);
543  for (int i=0 ; i<expNumDdt ; ++i)
544  {
545  staVec[li_ddt[i]] = ddtVals[i];
546  }
547  }
548 
549  return true;
550 }
551 
552 //-----------------------------------------------------------------------------
553 // Function : Instance::loadDAEFVector
554 //
555 // Purpose : Loads the F-vector contributions for a single
556 // resistor instance.
557 //
558 // Special Notes :
559 //
560 // Scope : public
561 // Creator : Eric R. Keiter, SNL, Electrical and Microsystems Modeling
562 // Creation Date : 11/13/05
563 //-----------------------------------------------------------------------------
565 {
566  double * fVec = extData.daeFVectorRawPtr;
567 
568  // load RHS vector element for the positive circuit node KCL equ.
569  double coef = (v_pos-v_neg)*G;
570 
571  fVec[li_Pos] += coef;
572  fVec[li_Neg] += -coef;
573  if( loadLeadCurrent )
574  {
575  double * stoVec = extData.nextStoVectorRawPtr;
576  stoVec[li_store_dev_i] = coef;
577  }
578 
579  return true;
580 }
581 
582 //-----------------------------------------------------------------------------
583 // Function : Instance::loadDAEdFdx ()
584 //
585 // Purpose : Loads the F-vector contributions for a single
586 // resistor instance.
587 //
588 // Special Notes :
589 //
590 // Scope : public
591 // Creator : Eric R. Keiter, SNL, Electrical and Microsystems Modeling
592 // Creation Date : 11/13/05
593 //-----------------------------------------------------------------------------
595 {
596  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
597 
598  dFdx[li_Pos][APosEquPosNodeOffset] += G;
599  dFdx[li_Pos][APosEquNegNodeOffset] -= G;
600  dFdx[li_Neg][ANegEquPosNodeOffset] -= G;
601  dFdx[li_Neg][ANegEquNegNodeOffset] += G;
602 
603  if( expNumVars )
604  {
605  for( int i = 0; i < expNumVars; ++i )
606  {
609  }
610  }
611 
612  return true;
613 }
614 
615 //-----------------------------------------------------------------------------
616 // Function : Model::Model
617 // Purpose : constructor
618 // Special Notes :
619 // Scope : public
620 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
621 // Creation Date : 5/16/00
622 //-----------------------------------------------------------------------------
624  const Configuration & configuration,
625  const ModelBlock & MB,
626  const FactoryBlock & factory_block)
627  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
628  dtype(1),
629  RON(0.0),
630  ROFF(0.0),
631  ON(0.0),
632  OFF(0.0)
633 {
634  if (getType() != "")
635  {
636  if (getType() == "SWITCH" ) {
637  dtype = 1;
638  }
639  else if (getType() == "ISWITCH") {
640  dtype = 2;
641  }
642  else if (getType() == "VSWITCH") {
643  dtype = 3;
644  }
645  else
646  {
647  UserError0(*this) << "Unrecognized model type " << getType();
648  }
649  }
650 
651 
652  // Set params to constant default values:
653  setDefaultParams ();
654 
655  // Set params according to .model line and constant defaults from metadata:
656  setModParams (MB.params);
657 
658  // Set any non-constant parameter defaults:
659 
660  // Calculate any parameters specified as expressions:
662 
663  // calculate dependent (ie computed) params and check for errors:
664 
665  if (dtype == 2)
666  {
667  if (!given("ON"))
668  ON = ION;
669  if (!given("OFF"))
670  OFF = IOFF;
671  }
672  else if (dtype == 3)
673  {
674  if (!given("ON"))
675  ON = VON;
676  if (!given("OFF"))
677  OFF = VOFF;
678  }
679 
680  processParams();
681 }
682 
683 //-----------------------------------------------------------------------------
684 // Function : Model::processParams
685 // Purpose :
686 // Special Notes :
687 // Scope : public
688 // Creator : Dave Shirley, PSSI
689 // Creation Date : 03/16/05
690 //-----------------------------------------------------------------------------
692 {
693  double del;
694  Lm = log (sqrt(RON*ROFF));
695  Lr = log (RON/ROFF);
696 
697  del = ON-OFF;
698 
699  if (del < 0 && del > -1e-12)
700  del = -1e-12;
701  if (del >= 0 && del < 1e-12)
702  del = 1e-12;
703  dInv = 1.0/del;
704 
705  return true;
706 }
707 
708 //----------------------------------------------------------------------------
709 // Function : Model::processInstanceParams
710 // Purpose :
711 // Special Notes :
712 // Scope : public
713 // Creator : Dave Shirely, PSSI
714 // Creation Date : 03/23/06
715 //----------------------------------------------------------------------------
717 {
718 
719  std::vector<Instance*>::iterator iter;
720  std::vector<Instance*>::iterator first = instanceContainer.begin();
721  std::vector<Instance*>::iterator last = instanceContainer.end();
722 
723  for (iter=first; iter!=last; ++iter)
724  {
725  (*iter)->processParams();
726  }
727 
728  return true;
729 }
730 
731 //-----------------------------------------------------------------------------
732 // Function : Model::~Model
733 // Purpose : destructor
734 // Special Notes :
735 // Scope : public
736 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
737 // Creation Date : 3/16/00
738 //-----------------------------------------------------------------------------
740 {
741  std::vector<Instance*>::iterator iter;
742  std::vector<Instance*>::iterator first = instanceContainer.begin();
743  std::vector<Instance*>::iterator last = instanceContainer.end();
744 
745  for (iter=first; iter!=last; ++iter)
746  delete (*iter);
747 }
748 
749 //-----------------------------------------------------------------------------
750 // Function : Model::printOutInstances
751 // Purpose : debugging tool.
752 // Special Notes :
753 // Scope : public
754 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
755 // Creation Date : 4/03/00
756 //-----------------------------------------------------------------------------
757 std::ostream &Model::printOutInstances(std::ostream &os) const
758 {
759  std::vector<Instance*>::const_iterator iter;
760  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
761  std::vector<Instance*>::const_iterator last = instanceContainer.end();
762 
763  int i;
764  os << std::endl;
765  os << " name model name Parameters" << std::endl;
766  for (i=0, iter=first; iter!=last; ++iter, ++i)
767  {
768  os << " " << i << ": " << (*iter)->getName() << " ";
769  os << getName();
770  os << " R = " << (*iter)->R;
771  os << " G = " << (*iter)->G;
772  os << " State = " << (*iter)->SW_STATE;
773  os << std::endl;
774  }
775 
776  os << std::endl;
777 
778  return os;
779 }
780 
781 //-----------------------------------------------------------------------------
782 // Function : Model::forEachInstance
783 // Purpose :
784 // Special Notes :
785 // Scope : public
786 // Creator : David Baur
787 // Creation Date : 2/4/2014
788 //-----------------------------------------------------------------------------
789 /// Apply a device instance "op" to all instances associated with this
790 /// model
791 ///
792 /// @param[in] op Operator to apply to all instances.
793 ///
794 ///
795 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
796 {
797  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
798  op(*it);
799 }
800 
801 //-----------------------------------------------------------------------------
802 // SW Master functions:
803 //-----------------------------------------------------------------------------
804 
805 //-----------------------------------------------------------------------------
806 // Function : Master::updateState
807 // Purpose :
808 // Special Notes :
809 // Scope : public
810 // Creator : Eric Keiter, SNL
811 // Creation Date : 11/26/08
812 //-----------------------------------------------------------------------------
813 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
814 {
815  bool bsuccess = true;
816 
817  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
818  {
819  Instance & si = *(*it);
820 
821  bool btmp = si.updateIntermediateVars ();
822  bsuccess = bsuccess && btmp;
823 
824  // obtain the current value of the switch state
825  si.switch_state = si.SW_STATE;
826  staVec[si.li_switch_state] = si.switch_state;
827  }
828 
829  return bsuccess;
830 }
831 
832 //-----------------------------------------------------------------------------
833 // Function : Master::updateSecondaryState
834 // Purpose :
835 // Special Notes :
836 // Scope : public
837 // Creator : Eric Keiter, SNL
838 // Creation Date : 11/26/08
839 //-----------------------------------------------------------------------------
840 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
841 {
842  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
843  {
844  Instance & si = *(*it);
845 
846  double current_state;
847  double control;
848  double * solVec = si.extData.nextSolVectorRawPtr;
849 
850  // Get time derivatives from time integrator, and evaluate expression to get
851  // derivatives with respect to independent quantities
852 
853  if (si.expNumDdt > 0)
854  {
855  for (int i=0 ; i<si.expNumDdt ; ++i)
856  {
857  si.ddtVals[i] = staDerivVec[si.li_ddt[i]];
858  }
859  si.Exp_ptr->setDdtDerivs(si.ddtVals);
860  }
861  // Evaluate Expression with corrected time derivative values
862 
863  si.Exp_ptr->evaluate( si.expVal, si.expVarDerivs );
864  control = si.expVal;
865 
866  // This is not really correct, an interim hack. This is supposed
867  // to be where we deal with the specification of ON or OFF from the
868  // netlist.
869  if (getSolverState().initJctFlag_)
870  {
871  if (si.ON)
872  current_state = 1;
873  else
874  current_state = 0;
875  }
876  else
877  {
878  current_state = (control-si.getModel().OFF)*si.getModel().dInv;
879  }
880 
881  si.v_pos = solVec[si.li_Pos];
882  si.v_neg = solVec[si.li_Neg];
883 
884  if (current_state >= 1.0)
885  {
886  si.R = si.getModel().RON;
887  si.G = 1.0/si.R;
888  for (int i=0 ; i<si.expNumVars ; ++i)
889  si.expVarDerivs[i] = 0;
890  }
891  else if ( current_state <= 0.0)
892  {
893  si.R = si.getModel().ROFF;
894  si.G = 1.0/si.R;
895  for (int i=0 ; i<si.expNumVars ; ++i)
896  si.expVarDerivs[i] = 0;
897  }
898  else
899  {
900  current_state = 2*current_state - 1;
901  si.G = exp(-si.getModel().Lm - 0.75*si.getModel().Lr*current_state +
902  0.25*si.getModel().Lr*current_state*current_state*current_state);
903  si.R = 1.0/si.G;
904  for (int i=0 ; i<si.expNumVars ; ++i)
905  {
906  si.expVarDerivs[i] = si.G * (1.5 * (current_state*current_state-1) * si.getModel().Lr *
907  si.getModel().dInv * si.expVarDerivs[i]);
908  }
909  }
910  }
911 
912  return true;
913 }
914 
915 //-----------------------------------------------------------------------------
916 // Function : Master::loadDAEVectors
917 // Purpose :
918 // Special Notes :
919 // Scope : public
920 // Creator : Eric Keiter, SNL
921 // Creation Date : 11/26/08
922 //-----------------------------------------------------------------------------
923 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
924 {
925  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
926  {
927  Instance & si = *(*it);
928  // F-vector:
929  double coef = (si.v_pos-si.v_neg)*si.G;
930  fVec[si.li_Pos] += coef;
931  fVec[si.li_Neg] += -coef;
932  if( si.loadLeadCurrent )
933  {
934  storeLeadF[si.li_store_dev_i] = coef;
935  }
936  // Q-vector:
937  }
938  return true;
939 }
940 
941 //-----------------------------------------------------------------------------
942 // Function : Master::loadDAEMatrices
943 // Purpose :
944 // Special Notes :
945 // Scope : public
946 // Creator : Eric Keiter, SNL
947 // Creation Date : 11/26/08
948 //-----------------------------------------------------------------------------
949 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
950 {
951  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
952  {
953  Instance & si = *(*it);
954 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
955 
956  *si.fPosEquPosNodePtr += si.G;
957  *si.fPosEquNegNodePtr -= si.G;
958  *si.fNegEquPosNodePtr -= si.G;
959  *si.fNegEquNegNodePtr += si.G;
960 
961  if( si.expNumVars )
962  {
963  for( int j = 0; j < si.expNumVars; ++j )
964  {
965  *si.fPosEquControlNodePtr[j] += (si.v_pos-si.v_neg) * si.expVarDerivs[j];
966  *si.fNegEquControlNodePtr[j] -= (si.v_pos-si.v_neg) * si.expVarDerivs[j];
967  }
968  }
969 #else
970 
971  dFdx[si.li_Pos][si.APosEquPosNodeOffset] += si.G;
972  dFdx[si.li_Pos][si.APosEquNegNodeOffset] -= si.G;
973  dFdx[si.li_Neg][si.ANegEquPosNodeOffset] -= si.G;
974  dFdx[si.li_Neg][si.ANegEquNegNodeOffset] += si.G;
975 
976  if( si.expNumVars )
977  {
978  for( int i = 0; i < si.expNumVars; ++i )
979  {
980  dFdx[si.li_Pos][si.APosEquControlNodeOffset[i]] += (si.v_pos-si.v_neg) * si.expVarDerivs[i];
981  dFdx[si.li_Neg][si.ANegEquControlNodeOffset[i]] -= (si.v_pos-si.v_neg) * si.expVarDerivs[i];
982  }
983  }
984 #endif
985  }
986  return true;
987 }
988 
989 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
990 {
991 
992  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
993 }
994 
996 {
998  .registerDevice("s", 1)
999 
1000 #ifdef Xyce_OLD_SWITCH
1001  .registerModelType("sw", 1)
1002 #else
1003  .registerModelType("switch", 1)
1004  .registerModelType("iswitch", 1)
1005  .registerModelType("vswitch", 1)
1006 #endif
1007  ;
1008 }
1009 
1010 } // namespace SW
1011 } // namespace Device
1012 } // namespace Xyce
const InstanceName & getName() const
static void loadModelParameters(ParametricData< Model > &model_parameters)
Definition: N_DEV_SW.C:90
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Definition: N_DEV_SW.C:989
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_SW.C:76
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
Definition: N_DEV_SW.C:795
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
virtual bool updateSecondaryState(double *staDeriv, double *stoVec)
Updates the devices secondary state information.
Definition: N_DEV_SW.C:840
bool given(const std::string &parameter_name) const
void G(const ScalarT &V1, const ScalarT &V2, const ScalarT &Ap, const ScalarT &An, ScalarT &Vp, ScalarT &Vn, ScalarT &fval)
Pure virtual class to augment a linear system.
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_SW.C:923
InstanceVector::const_iterator getInstanceEnd() const
Returns an iterator to the ending of the vector of all instances created for this device...
std::vector< double > myVarVals
Definition: N_DEV_SW.h:153
const std::vector< Depend > & getDependentParams()
#define AssertLIDs(cmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
std::vector< int > APosEquControlNodeOffset
Definition: N_DEV_SW.h:197
std::vector< double * > fPosEquControlNodePtr
Definition: N_DEV_SW.h:207
InstanceVector::const_iterator getInstanceBegin() const
Returns an iterator to the beginning of the vector of all instances created for this device...
std::vector< Param > params
Parameters from the line.
void setParams(const std::vector< Param > &params)
const std::string & getName() const
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
Definition: N_DEV_SW.C:297
std::vector< double > ddtVals
Definition: N_DEV_SW.h:154
std::vector< std::vector< int > > jacStamp
Definition: N_DEV_SW.h:210
std::vector< Instance * > instanceContainer
Definition: N_DEV_SW.h:257
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
Definition: N_DEV_SW.C:813
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &SWiter, const FactoryBlock &factory_block)
Definition: N_DEV_SW.C:155
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
Linear::Matrix * dFdxMatrixPtr
std::vector< double > expVarDerivs
Definition: N_DEV_SW.h:152
std::vector< int > li_ddt
Definition: N_DEV_SW.h:179
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
void addStoreNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
virtual bool loadDAEMatrices(Linear::Matrix &dFdx, Linear::Matrix &dQdx)
Populates the device's Jacobian object with these pointers.
Definition: N_DEV_SW.C:949
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Definition: N_DEV_SW.C:362
const SolverState & solverState_
Class Configuration contains device configuration data.
Util::Expression * Exp_ptr
Definition: N_DEV_SW.h:146
std::vector< int > ANegEquControlNodeOffset
Definition: N_DEV_SW.h:198
const SolverState & getSolverState() const
void registerStoreLIDs(const std::vector< int > &stoLIDVecRef)
Definition: N_DEV_SW.C:318
virtual std::ostream & printOutInstances(std::ostream &os) const
Definition: N_DEV_SW.C:757
const std::vector< std::vector< int > > & jacobianStamp() const
Definition: N_DEV_SW.C:349
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
Definition: N_DEV_SW.C:270
const std::string & getType() const
void registerDevice()
Definition: N_DEV_SW.C:995
virtual void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Definition: N_DEV_SW.C:520
std::vector< double * > fNegEquControlNodePtr
Definition: N_DEV_SW.h:208
bool processParams()
processParams
Definition: N_DEV_SW.C:691
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.
std::vector< Param > params
Linear::Matrix * dQdxMatrixPtr
const std::vector< std::string > & getDepSolnVars()
Definition: N_DEV_SW.C:336
bool processInstanceParams()
processInstanceParams
Definition: N_DEV_SW.C:716
virtual const std::vector< std::string > & getDepSolnVars()
const SolverState & getSolverState() const
Returns the solver state given during device construction.
void setModParams(const std::vector< Param > &params)