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