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