Xyce  6.1
N_DEV_Region.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_Region.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL
33 //
34 // Creation Date : 07/19/06
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.31 $
40 //
41 // Revision Date : $Date: 2015/04/22 15:00:52 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 // ---------- Standard Includes ----------
49 #include <iostream>
50 #include <N_UTL_Math.h>
51 #include <cstdio>
52 
53 // ---------- Xyce Includes ----------
54 #include <N_DEV_Const.h>
55 #include <N_DEV_ExternData.h>
56 #include <N_DEV_SolverState.h>
57 #include <N_DEV_DeviceOptions.h>
58 #include <N_DEV_MatrixLoadData.h>
59 #include <N_DEV_DeviceInstance.h>
60 #include <N_DEV_RegionData.h>
61 
62 #include <N_LAS_Matrix.h>
63 #include <N_LAS_MultiVector.h>
64 #include <N_LAS_Vector.h>
65 
66 #include <N_DEV_Region.h>
67 #include <N_DEV_Specie.h>
68 #include <N_DEV_ScalingVars.h>
69 #include <N_UTL_Expression.h>
70 #include <N_UTL_FeatureTest.h>
71 
72 namespace Xyce {
73 namespace Device {
74 
75 //-----------------------------------------------------------------------------
76 // Function : Region::Region
77 // Purpose : constructor 1
78 // Special Notes : creates reaction region with default reaction network
79 // Scope : public
80 // Creator :
81 // Creation Date : 8/24/06
82 //-----------------------------------------------------------------------------
84  const NetlistLocation & netlist_location,
85  RegionData & rd,
86  const DeviceOptions & devOp,
87  const SolverState & solst,
88  bool sourceOn)
89  : name(rd.name),
90  outputName(rd.outName),
91  devOptions(devOp),
92  solState(solst),
93  regData(rd),
94  useScaledVariablesFlag(false),
95  variablesScaledFlag(false),
96  rateConstantsScaledFlag(false),
97  callsOTEC(0),
98  baseReactionIndex(-1),
99  x0(0.0),
100  a0(0.0),
101  C0(0.0),
102  D0(0.0),
103  u0(0.0),
104  R0(0.0),
105  rR0(0.0),
106  t0(0.0),
107  k0(0.0),
108  rt0(0.0),
109  rk0(0.0),
110  outputBefore1(false),
111  outputBefore2(false)
112 {
113  theReactions.setApplySources(sourceOn);
114  createDefaultReactionNetwork(netlist_location, rd.reactionFile );
115 }
116 
117 //-----------------------------------------------------------------------------
118 // Function : Region::Region
119 // Purpose : constructor 2
120 // Special Notes : creates reaction region with copied reaction network
121 // for now does nothing but call initializers, but moved
122 // out of header file in case we want it to be more than a
123 // simple inlined deal.
124 // Scope : public
125 // Creator :
126 // Creation Date : 7/29/06
127 //-----------------------------------------------------------------------------
129  RegionData & rd,
130  const DeviceOptions & devOp,
131  const SolverState & solst,
132  ReactionNetwork & reactionNet)
133  : name(rd.name),
134  outputName(rd.outName),
135  devOptions(devOp),
136  solState(solst),
137  regData(rd),
138  useScaledVariablesFlag(false),
139  variablesScaledFlag(false),
140  rateConstantsScaledFlag(false),
141  callsOTEC(0),
142  baseReactionIndex(-1),
143  x0(0.0),
144  a0(0.0),
145  C0(0.0),
146  D0(0.0),
147  u0(0.0),
148  R0(0.0),
149  rR0(0.0),
150  t0(0.0),
151  k0(0.0),
152  rt0(0.0),
153  rk0(0.0),
154  outputBefore1(false),
155  outputBefore2(false),
156  theReactions(reactionNet)
157 {
158  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
159  {
160  Xyce::dout() << theReactions << std::endl;
161  }
162 }
163 
164 //-----------------------------------------------------------------------------
165 // Function : Region::~Region
166 // Purpose : destructor
167 // Special Notes :
168 // Scope : public
169 // Creator :
170 // Creation Date : 7/29/06
171 //-----------------------------------------------------------------------------
173 {
175 }
176 
177 //-----------------------------------------------------------------------------
178 // Function : Region::createDefaultRectionNetwork
179 // Purpose : like it says
180 // Special Notes :
181 // Scope : private
182 // Creator :
183 // Creation Date : 7/29/06
184 //-----------------------------------------------------------------------------
185 void
186 Region::createDefaultReactionNetwork(const NetlistLocation &netlist_location, const std::string &reactionSpecFile)
187 {
189 
190  theReactions.setReactionNetworkFromFile(netlist_location, reactionSpecFile);
191 
192  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
193  Xyce::dout() << theReactions << std::endl;
194 }
195 
196 //-----------------------------------------------------------------------------
197 // Function : Region::initializeReactionNetwork
198 // Purpose : Initialize the 0-d reaction network equations
199 // Special Notes : The reaction network itself has already been created when
200 // the region was set up, here we just initialize some
201 // properties of it.
202 // Scope : public
203 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
204 // Creation Date : 3/29/06
205 //-----------------------------------------------------------------------------
207 {
208 
209  int cSize=theReactions.getNumConstants();
210  int sSize=theReactions.getNumSpecies();
211 
212  setupScalingVars(sv);
213 
215  theReactions.setMaterial(material, Temp);
217 
218  // We will need to get the initial conditions in some other way, too.
219  // this presumes we have all these specific named species. We might have
220  // more, or fewer.
221  if (cSize > 0)
222  {
223  theConstantConcentrations.resize(cSize,0.0);
224  }
225 
226  // initial condition
227  // These are just this way for testing purposes.
228  if (sSize > 0)
229  {
230  initialConcentrations.resize(sSize,0.0);
231  }
232 
233  // Estimate the electron and hole concentrations based on the
234  // doping levels. For now we are just considering the exact center
235  // of the depletion region.
236 
237  if (sSize > 0 ) // don't initialize any concentrations at all if there
238  // are no variable species!
239  {
240  int icSize = theReactions.getNumInitialConditions();
241  int i;
242  for (i=0; i<icSize; ++i)
243  {
244  std::pair<std::string,double> theIC=theReactions.getInitialCondition(i);
245  int specIndex=theReactions.getReactantNum(theIC.first);
246  if (specIndex < 0)
247  theConstantConcentrations[-(specIndex+1)] = theIC.second;
248  else
249  initialConcentrations[specIndex] = theIC.second;
250  }
251  }
252 
253 }
254 
255 //-----------------------------------------------------------------------------
256 // Function : Region::setInitialCondition
257 // Purpose :
258 // Special Notes :
259 // Scope : public
260 // Creator :
261 // Creation Date : 3/29/06
262 //-----------------------------------------------------------------------------
263 void Region::setInitialCondition(const std::string & reactantname, const double val)
264 {
265  int specIndex=theReactions.getReactantNum(reactantname);
266  initialConcentrations[specIndex] = val;
267 }
268 
269 //-----------------------------------------------------------------------------
270 // Function : Region::addSource
271 // Purpose : add a source term to the reaction network
272 // Special Notes :
273 // Scope : public
274 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
275 // Creation Date : 8/4/06
276 //-----------------------------------------------------------------------------
277 void Region::addSource(std::string speciesName, Util::Expression *expr)
278 {
279  theReactions.addSourceTerm(speciesName, expr);
280 }
281 
282 //-----------------------------------------------------------------------------
283 // Function : Region::addMasterSource
284 // Purpose : add a master source term to the reaction network
285 // Special Notes : "master" source terms are those that depend on a single
286 // master source value that is set each time we evaluate
287 // the RHS.
288 // Scope : public
289 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
290 // Creation Date : 8/4/06
291 //-----------------------------------------------------------------------------
292 void Region::addMasterSource(std::string speciesName)
293 {
294  theReactions.addMasterSourceTerm(speciesName);
295 }
296 
297 //-----------------------------------------------------------------------------
298 // Function : Region::setRateConstants
299 // Purpose : Set rate constants for reactions defined in
300 // initializeReactionNetwork. This is meant to be called
301 // from updateTemperature.
302 // Special Notes : Cheesy hard-coded version for initial testing
303 // Scope : public
304 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
305 // Creation Date : 3/29/06
306 //-----------------------------------------------------------------------------
308 {
310 
311  if (DEBUG_DEVICE)
312  {
313  if (!outputBefore1)
314  {
315  if (isActive(Diag::DEVICE_PARAMETERS))
316  Xyce::dout() << theReactions << std::endl;
317  outputBefore1 = true;
318  }
319 
320  }
321 
322  // if the variables have been scaled, then the rate constants should be
323  // as well:
325  {
327  }
328 
329  if (DEBUG_DEVICE)
330  {
332  {
333  if (isActive(Diag::DEVICE_PARAMETERS))
334  {
335  Xyce::dout() << "Scaled Reactions: " << std::endl;
336  Xyce::dout() << theReactions << std::endl;
337  }
338  outputBefore2=true;
339  }
340  }
341 }
342 
343 //----------------------------------------------------------------------------
344 // Function : Region::setupScalingVars
345 // Purpose :
346 //
347 // Special Notes : Most of these aren't used. The important ones are
348 // T0 and C0.
349 //
350 // Scope : public
351 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
352 // Creation Date : 6/01/06
353 //----------------------------------------------------------------------------
355 {
356  t0 = sv.t0;
357  C0 = sv.C0;
358  x0 = sv.x0;
359  double rx0 = 1.0/x0;
360 
361  a0 = sv.a0;
362 
363  D0 = sv.D0;
364  R0 = sv.R0;
365 
366  rR0 = 1.0/R0;
367 
368  rk0 = C0*t0;
369  rt0 = 1.0/t0;
370  k0 = 1.0/rk0;
371 
372  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
373  {
374  Xyce::dout() << "Device::Region::setupScalingVars:" << std::endl;
375  Xyce::dout().width(20);
376  Xyce::dout().precision(12);
377  Xyce::dout() << " " << std::endl;
378  Xyce::dout() << "t0 = " << t0 << std::endl;
379  Xyce::dout() << "x0 = " << x0 << std::endl;
380  Xyce::dout() << "a0 = " << a0 << std::endl;
381  Xyce::dout() << "C0 = " << C0 << std::endl;
382  Xyce::dout() << "D0 = " << D0 << std::endl;
383  Xyce::dout() << "R0 = " << R0 << std::endl;
384  Xyce::dout() << "k0 = " << k0 << std::endl;
385  Xyce::dout() << "rk0 = " << rk0 << std::endl;
386  }
387 }
388 
389 //----------------------------------------------------------------------------
390 // Function : Region::scaleVariables
391 // Purpose : Applies the scaling variables.
392 // Special Notes :
393 // Scope : public
394 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
395 // Creation Date : 6/01/06
396 //----------------------------------------------------------------------------
398 {
399  int i=0;
400  int size=0;
401 
402  // vector of constant concentrations (species held fixed)
403  size = theConstantConcentrations.size();
404  for (i=0;i<size;++i)
405  {
407  }
408 
409  // working storage for communicating between updateIntermediateVars
410  // and updatePrimaryState
411  size = tempConcentrations.size();
412  for (i=0;i<size;++i)
413  {
414  tempConcentrations[i] /= C0;
415  }
416 
417  // initial conditions
418  size = initialConcentrations.size();
419  for (i=0;i<size;++i)
420  {
422  }
423 
424  variablesScaledFlag = true;
425 }
426 
427 //----------------------------------------------------------------------------
428 // Function : Region::unscaleVariables
429 // Purpose : Restores things to normal units.
430 // Special Notes :
431 // Scope : public
432 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
433 // Creation Date : 6/01/06
434 //----------------------------------------------------------------------------
436 {
437  int i=0;
438  int size=0;
439 
440  // vector of constant concentrations (species held fixed)
441  size = theConstantConcentrations.size();
442  for (i=0;i<size;++i)
443  {
445  }
446 
447  // working storage for communicating between updateIntermediateVars
448  // and updatePrimaryState
449  size = tempConcentrations.size();
450  for (i=0;i<size;++i)
451  {
452  tempConcentrations[i] *= C0;
453  }
454 
455  // initial conditions
456  size = initialConcentrations.size();
457  for (i=0;i<size;++i)
458  {
460  }
461 
462  variablesScaledFlag = false;
463 }
464 
465 //----------------------------------------------------------------------------
466 // Function : Region::scaleRateConstants
467 // Purpose :
468 // Special Notes : This function assumes that the rate constants are
469 // in units of cm^3/s, need to be multiplied by C0*t0.
470 //
471 // Some rate constants include e- or h+ densities in them.
472 // ie, are k*Ne or k*Nh, rather than just k. For these
473 // rate constants, the scalar multiple should just be t0.
474 //
475 // To understand this consider the expression:
476 //
477 // k * Na * Nb, where k is a rate and Na and Nb are
478 // the concentrations of reactants. If the variables have
479 // been scaled already, then Na and Nb are already scaled
480 // to dimensionless units. (ie Na /= C0).
481 //
482 // k, being in cm^3/s, needs to be multiplied by t0/C0. So,
483 // the total scaling multiplied by the expression is:
484 //
485 // (rate scaling) * (concentration scaling)^2
486 // (t0*C0) * 1/C0 * 1/C0 = t0/C0.
487 //
488 // This is (correctly) the same as the scaling applied
489 // to dNa/dt, which will also be multiplied by t0/C0.
490 //
491 // In the case of an implicit e- density, then k is actually
492 // k*Ne, in units of s^-1. Then the expression is:
493 //
494 // kNe * Nb. The scalar will be:
495 //
496 // t0 * 1/C0 = t0/C0, which is correct.
497 //
498 // So the punchline is:
499 //
500 // (1) rates including Ne or Nh, multiply by t0.
501 // (2) rates not including Ne or Nh, multiply by rk0=C0*t0.
502 //
503 // For now, just like the other reaction-specific functions, this function
504 // is hardwired to a specific reaction network. It will have to be
505 // generalized later.
506 //
507 // Scope : public
508 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
509 // Creation Date : 6/01/06
510 //----------------------------------------------------------------------------
512 {
514 
516 }
517 
518 //----------------------------------------------------------------------------
519 // Function : Region::unscaleRateConstants
520 // Purpose :
521 // Special Notes :
522 // Scope : public
523 // Creator :
524 // Creation Date : 6/01/06
525 //----------------------------------------------------------------------------
527 {
529 
530  rateConstantsScaledFlag = false;
531 }
532 
533 //-----------------------------------------------------------------------------
534 // Function : Region::outputTecplot
535 // Purpose :
536 // Special Notes :
537 // Scope : public
538 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
539 // Creation Date : 7/19/06
540 //-----------------------------------------------------------------------------
542 {
543  bool bsuccess = true;
544 
545  int i;
546  char filename[32]; for(i=0;i<32;++i) filename[i] = static_cast<char>(0);
547 
548  sprintf(filename,"%s.dat",outputName.c_str());
549 
550  double time = solState.currTime_;
551  double step = solState.currTimeStep_;
552 
553  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && solState.debugTimeFlag)
554  {
555  Xyce::dout() << std::endl;
556  Xyce::dout() << section_divider << std::endl;
557  Xyce::dout() << "In Device::DiodePDEInstance::outputTecplot. filename = ";
558  Xyce::dout() << std::string(filename);
559  Xyce::dout() << " time = " << time;
560  Xyce::dout() << " step = " << step;
561  Xyce::dout() << std::endl;
562  }
563 
564  FILE *fp1;
565 
566  if (callsOTEC <= 0)
567  {
568  fp1 = fopen(filename,"w");
569  }
570  else
571  {
572  fp1 = fopen(filename,"a");
573  }
574 
575  // If this is the first call, print the header.
576  int rSize=theReactions.getNumSpecies();
577  int cSize=theReactions.getNumConstants();
578  if (callsOTEC <= 0)
579  {
580  fprintf(fp1,
581  " TITLE = \"Data for reaction model: %s.\",\n", name.getEncodedName().c_str());
582  fprintf(fp1,"%s","\tVARIABLES = \"TIME \",\n");
583 
584  for (i=0;i<cSize;++i)
585  {
586  fprintf(fp1, "\t \"%s \",\n" , (theReactions.getConstantsName(i)).c_str());
587  }
588 
589  for (i=0;i<rSize;++i)
590  {
591  fprintf(fp1,"\t \"%s \",\n", (theReactions.getSpeciesName(i)).c_str());
592  }
593  fprintf(fp1,"%s","\tZONE F=POINT\n");
594  }
595 
596  // Now print the data:
597  fprintf(fp1," %20.12e", solState.currTime_);
598 
599 
600  for (i=0;i<cSize;++i)
601  {
602  double printVal =
604  fprintf(fp1," %20.12e", printVal);
605  }
606 
607  for (i=0;i<rSize;++i)
608  {
609  double printVal =
611  fprintf(fp1," %20.12e", printVal);
612  }
613 
614  fprintf(fp1,"%s","\n");
615 
616  ++callsOTEC;
617  fclose(fp1);
618 
619  return bsuccess;
620 }
621 
622 //-----------------------------------------------------------------------------
623 // Function : Region::setupJacStamp
624 //
625 // Purpose : adds reaction region's information to jac stamp.
626 //
627 // Special Notes : Modified to return the base index.
628 //
629 // Scope : public
630 // Creator : Eric R. Keiter
631 // Creation Date : 7/19/06
632 //-----------------------------------------------------------------------------
633 void Region::setupJacStamp ( std::vector< std::vector<int> > & jacStamp,
634  std::vector<int> &colDep,
635  int & firstReactant,
636  int & lastIndex )
637 {
638  int concentrationSize = theReactions.getNumSpecies();
639 
640  if (concentrationSize != 0 && !(regData.doNothing) ) // then we have jacStamp modifications to do
641  {
642  if (colDep.size() != 2)
643  {
644  Report::DevelFatal0().in("Region::setupJacStamp") << "colDep != 2";
645  }
646 
647  int stampSize=jacStamp.size();
648  baseReactionIndex=stampSize;
649  jacStamp.resize(stampSize+concentrationSize);
650 
651  // This simply sets a full square block, irresepective of how the
652  // network actually couples variables. First cut, possibly inefficient,
653  // probably not worth doing more specifically unless there's a huge
654  // reaction network with many species and very sparse matrix.
655  for (int i=0; i<concentrationSize; ++i)
656  {
657 #if 0
658  jacStamp[baseReactionIndex+i].resize(concentrationSize+2);
659 #else
660  jacStamp[baseReactionIndex+i].resize(concentrationSize);
661 #endif
662  for (int j=0;j<concentrationSize; ++j)
663  {
664  jacStamp[baseReactionIndex+i][j]=baseReactionIndex+j;
665  }
666 
667 #if 0
668  // This is why colDep must be of size 2. (one for e-, one for h+)
669  // add the colDep colummns:
670  jacStamp[baseReactionIndex+i][concentrationSize ]=colDep[0];
671  jacStamp[baseReactionIndex+i][concentrationSize+1]=colDep[1];
672 #endif
673  }
674  }
675  firstReactant = baseReactionIndex;
676  lastIndex = jacStamp.size()-1;
677 }
678 
679 //-----------------------------------------------------------------------------
680 // Function : Region::registerLIDs
681 // Purpose :
682 // Special Notes : updates the intIndex
683 // Scope : public
684 // Creator : Eric R. Keiter
685 // Creation Date : 7/19/06
686 //-----------------------------------------------------------------------------
687 void Region::registerLIDs( const std::vector<int> & intLIDVec,
688  const std::vector<int> & extLIDVec,
689  int & intIndex)
690 {
691 
692  if ( !(regData.doNothing) )
693  {
694  if (baseReactionIndex != -1)
695  {
696  int rSize = theReactions.getNumSpecies();
697  li_Concentrations.clear();
698  li_Concentrations.resize(rSize);
699  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
700  {
701  Xyce::dout() << " li_Concentrations: " << std::endl;
702  }
703  for (int i=0;i<rSize;++i)
704  {
705  li_Concentrations[i] = intLIDVec[intIndex++];
706 
707  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
708  {
709  Xyce::dout() << " li_Concentrations["<< i << "] = " << li_Concentrations[i] << std::endl;
710  }
711  }
712  }
713  }
714 }
715 
716 
717 //-----------------------------------------------------------------------------
718 // Function : RxnRegion::augmentNameMap
719 // Purpose :
720 // Special Notes :
721 // Scope : public
722 // Creator : Eric R. Keiter
723 // Creation Date : 7/20/06
724 //-----------------------------------------------------------------------------
725 void
727  Util::SymbolTable & symbol_table,
728  const DeviceInstance & device_instance)
729 {
730  if (!regData.doNothing)
731  {
732  if (baseReactionIndex != -1)
733  {
734  int rSize=theReactions.getNumSpecies();
735  for (int i = 0; i < rSize; ++i)
736  {
737  std::string speciesName = theReactions.getSpeciesName(i);
738  addInternalNode(symbol_table, li_Concentrations[i], getName(), "Conc_" + speciesName);
739  }
740  }
741  }
742 }
743 
744 //-----------------------------------------------------------------------------
745 // Function : Region::augmentNameMap
746 // Purpose :
747 // Special Notes :
748 // Scope : public
749 // Creator : Eric R. Keiter
750 // Creation Date : 7/20/06
751 //-----------------------------------------------------------------------------
753  std::map<int,std::string> & intNameMap,
754  DeviceInstance & di)
755 {
756  if ( !(regData.doNothing) )
757  {
758  if (baseReactionIndex != -1)
759  {
760  int rSize=theReactions.getNumSpecies();
761  for (int i=0;i<rSize;++i)
762  {
763  std::string speciesName=theReactions.getSpeciesName(i);
764  intNameMap[li_Concentrations[i]] = spiceInternalName(getName(), "Conc_" + speciesName);
765  }
766  }
767  }
768 }
769 
770 //-----------------------------------------------------------------------------
771 // Function : Region::registerStateLIDs
772 // Purpose :
773 // Special Notes :
774 // Scope : public
775 // Creator : Eric R. Keiter
776 // Creation Date : 7/20/06
777 //-----------------------------------------------------------------------------
779  (const std::vector<int> & staLIDVec, int & i)
780 {
781  if (baseReactionIndex != -1)
782  {
783  int rSize = theReactions.getNumSpecies();
784  li_state_Concentrations.resize(rSize);
785  for (int j=0;j<rSize;++j)
786  {
787  li_state_Concentrations[j]=staLIDVec[i++];
788  }
789  }
790 }
791 
792 //-----------------------------------------------------------------------------
793 // Function : Region::registerJacLIDs
794 // Purpose :
795 // Special Notes :
796 // Scope : public
797 // Creator : Eric R. Keiter
798 // Creation Date : 7/20/06
799 //-----------------------------------------------------------------------------
801  ( const std::vector< std::vector<int> > & jacLIDVec,
802  const std::vector<int> &map,
803  const std::vector< std::vector<int> > &map2
804  )
805 {
806  if ( !(regData.doNothing) )
807  {
808  if (baseReactionIndex != -1)
809  {
810  int rSize = theReactions.getNumSpecies();
811  AConcentrationEquConcentrationNodeOffsets.clear();
812  AConcentrationEquAuxNodeOffsets.clear();
813 
814  AConcentrationEquConcentrationNodeOffsets.resize(rSize);
815  AConcentrationEquAuxNodeOffsets.resize(rSize);
816 
817  for (int i=0;i<rSize;++i)
818  {
819  AConcentrationEquConcentrationNodeOffsets[i].resize(rSize);
820  for (int j=0;j<rSize;++j)
821  {
822  AConcentrationEquConcentrationNodeOffsets[i][j]=
823  jacLIDVec[map[baseReactionIndex+i]][map2[baseReactionIndex+i][j]];
824  }
825 
826 #if 0
827  int bRI = baseReactionIndex;
828  AConcentrationEquAuxNodeOffsets[i].resize(2);
829  for (int j=0; j<2; ++j)
830  {
831  AConcentrationEquAuxNodeOffsets[i][j]=
832  jacLIDVec[map[bRI+i]][map2[bRI+i][rSize+j]];
833  }
834 #endif
835  }
836  }
837  }
838 
839 }
840 
841 //-----------------------------------------------------------------------------
842 // Function : Region::setupPointers()
843 // Purpose :
844 // Special Notes :
845 // Scope : public
846 // Creator : Eric R. Keiter, SNL
847 // Creation Date : 5/19/10
848 //-----------------------------------------------------------------------------
849 void Region::setupPointers (Linear::Matrix & dfdx, Linear::Matrix & dqdx)
850 {
851  if ( !(regData.doNothing) )
852  {
853  int rSize = theReactions.getNumSpecies();
854 
855  dfdxConcEquConcVarPtrs.clear();
856  dfdxConcEquConcVarPtrs.resize(rSize);
857 
858  dqdxConcEquConcVarPtrs.clear();
859  dqdxConcEquConcVarPtrs.resize(rSize);
860 
861 #if 0
862  dfdxConcEquAuxVarPtrs.clear();
863  dfdxConcEquAuxVarPtrs.resize(rSize);
864 
865  dqdxConcEquAuxVarPtrs.clear();
866  dqdxConcEquAuxVarPtrs.resize(rSize);
867 #endif
868 
869  for (int i=0;i<rSize;++i)
870  {
871  dfdxConcEquConcVarPtrs[i].resize(rSize,0);
872  dqdxConcEquConcVarPtrs[i].resize(rSize,0);
873 
874  for (int j=0;j<rSize; ++j)
875  {
876  int lidRow = li_Concentrations[i];
877  int lidCol = li_Concentrations[j];
878 
879  double * dfdxPtr = dfdx.returnRawEntryPointer (lidRow, lidCol);
880  dfdxConcEquConcVarPtrs[i][j] = dfdxPtr;
881 
882  double * dqdxPtr = dqdx.returnRawEntryPointer (lidRow, lidCol);
883  dqdxConcEquConcVarPtrs[i][j] = dqdxPtr;
884  }
885 
886 #if 0
887  dfdxConcEquAuxVarPtrs[i].resize(2,0);
888  dqdxConcEquAuxVarPtrs[i].resize(2,0);
889  for (int j=0;j<2; ++j)
890  {
891  int lidRow = li_Concentrations[i];
892  int coloffset = AConcentrationEquAuxNodeOffsets[i][j];
893 
894  dfdxConcEquAuxVarPtrs[i][j] = &(dfdx[lidRow][coloffset]);
895  dqdxConcEquAuxVarPtrs[i][j] = &(dqdx[lidRow][coloffset]);
896  }
897 #endif
898  }
899  }
900 }
901 
902 //-----------------------------------------------------------------------------
903 // Function : Region::getDoNothingFlag
904 // Purpose :
905 // Special Notes :
906 // Scope : public
907 // Creator : Eric Keiter
908 // Creation Date : 5/25/10
909 //-----------------------------------------------------------------------------
911 {
912  return regData.doNothing;
913 }
914 
915 //-----------------------------------------------------------------------------
916 // Function : Region::getBreakTime
917 // Purpose : Return next breakpoint time from reaction network
918 // Special Notes :
919 //
920 //
921 // Scope : public
922 // Creator : Tom Russo
923 // Creation Date : 8/4/06
924 //-----------------------------------------------------------------------------
926 {
927  return (theReactions.getBreakpointTime());
928 }
929 
930 //-----------------------------------------------------------------------------
931 // Function : Region::updateIntermediateVars
932 // Purpose :
933 // Special Notes :
934 //
935 // For reaction kinetics, all we have to do here is copy the concentrations
936 // out of the solution vector and into the temp storage
937 //
938 // Scope : public
939 // Creator : Eric R. Keiter
940 // Creation Date : 7/19/06
941 //-----------------------------------------------------------------------------
943  ( double * solVector, double * oldSolVector, double time)
944 {
945  if (baseReactionIndex != -1)
946  {
947  int rSize = theReactions.getNumSpecies();
948  if (tempConcentrations.size() != rSize)
949  {
950  tempConcentrations.clear();
951  tempConcentrations.resize(rSize,0.0);
952  }
953 
954  for (int i=0;i<rSize;++i)
955  {
956  tempConcentrations[i] = solVector[li_Concentrations[i]];
957  }
958 
959  // Now update the imposed time-dependent generation rates:
960  double scalar= ((variablesScaledFlag)?(t0/C0):(1.0));
961  theReactions.setSimTime(time);
962  theReactions.setSourceScaleFac(scalar);
963 
964  // Now compute ddt and jac for later use in the various loads
965  if (ddt.size() != rSize)
966  {
967  ddt.clear();
968  ddt.resize(rSize,0.0);
969  }
970  else
971  {
972  for (int i=0;i<rSize;++i)
973  {
974  ddt[i]=0.0;
975  }
976  }
977  theReactions.getDdt( tempConcentrations, theConstantConcentrations, ddt);
978 
979  // Jacobian
980  if (tempJac.size() != rSize)
981  {
982  tempJac.clear();
983  tempJac.resize(rSize);
984  for (int i=0; i<rSize; ++i)
985  {
986  tempJac[i].resize(rSize,0.0);
987  }
988  }
989  else
990  {
991  for (int i=0;i<rSize;++i)
992  {
993  for (int j=0;j<rSize;++j)
994  {
995  tempJac[i][j]=0.0;
996  }
997  }
998  }
999 
1000  std::vector<double> tempVec;
1001  theReactions.getJacobianVC( tempConcentrations, theConstantConcentrations, tempJac,tempVec);
1002  }
1003 }
1004 
1005 //-----------------------------------------------------------------------------
1006 // Function : Region::loadDAEQVector
1007 // Purpose :
1008 // Special Notes :
1009 // Scope : public
1010 // Creator : Eric R. Keiter
1011 // Creation Date : 7/21/06
1012 //-----------------------------------------------------------------------------
1013 bool Region::loadDAEQVector (double * qVec)
1014 {
1015 
1016  // ERK: The Q-vector must be loaded! Not loading during DCOP is a mistake!
1017  //
1018  // The Q-vector does not get summed into the residual during the DCOP. However,
1019  // it has to be computed during the DCOP, or else dQ/dt will be enormous in the
1020  // first time step out of the DCOP. (it will be (Q_1 - 0.0)/dt rather than (Q_1-Q_0)/dt.
1021  //
1022  // dQdt matrix does get summed into the jacobian, however, and this is because the
1023  // for some devices (particularly the stand-alone capacitor), excluding dQdx will result
1024  // in a singular jacobian.
1025  //
1026  // Note that this term will appear to cause the numerical jacobian test to fail for dQdx
1027  // during the DCOP. This is not a meaningful failure. The dQdx jacobian test should be turned
1028  // off for the DCOP phase.
1029 
1030  //if (!solState.dcopFlag)
1031  {
1032  if (baseReactionIndex != -1)
1033  {
1034  int rSize=theReactions.getNumSpecies();
1035 
1036  for (int i=0;i<rSize;++i)
1037  {
1038  double val = tempConcentrations[i];
1039  if (variablesScaledFlag)
1040  {
1041  val *= t0; // need to double-check this.
1042  }
1043  qVec[li_Concentrations[i]] += val;
1044  }
1045  }
1046  }
1047 
1048  return true;
1049 }
1050 
1051 
1052 //-----------------------------------------------------------------------------
1053 // Function : Region::loadDAEFVector
1054 // Purpose :
1055 // Special Notes :
1056 // Scope : public
1057 // Creator : Eric R. Keiter
1058 // Creation Date : 7/21/06
1059 //-----------------------------------------------------------------------------
1060 bool Region::loadDAEFVector (double * fVec)
1061 {
1062  if (baseReactionIndex != -1)
1063  {
1064  int rSize=theReactions.getNumSpecies();
1065 
1067  {
1068  // satisfy initial condition at dcop
1069  for (int i=0;i<rSize;++i)
1070  {
1072  }
1073  }
1074  else
1075  {
1076  // ddt from reaction rate should be equal to ddt from time integrator
1077  for (int i=0;i<rSize;++i)
1078  {
1079  fVec[li_Concentrations[i]] += (-ddt[i]);
1080  }
1081  }
1082  }
1083 
1084  return true;
1085 }
1086 
1087 //-----------------------------------------------------------------------------
1088 // Function : Region::loadDAEdFdxdV
1089 // Purpose :
1090 // Special Notes :
1091 // Scope : public
1092 // Creator : Eric R. Keiter
1093 // Creation Date : 10/26/06
1094 //-----------------------------------------------------------------------------
1095 bool Region::loadDAEdFdxdV (double * dfdxdv,double vdiff)
1096 {
1097  return true;
1098 }
1099 
1100 //-----------------------------------------------------------------------------
1101 // Function : Region::loadDAEdQdx
1102 // Purpose :
1103 // Special Notes :
1104 // Scope : public
1105 // Creator : Eric R. Keiter
1106 // Creation Date : 7/21/06
1107 //-----------------------------------------------------------------------------
1108 bool Region::loadDAEdQdx (Linear::Matrix & dqdx)
1109 {
1110 
1111  if (baseReactionIndex != -1)
1112  {
1113  if ( !(solState.dcopFlag || regData.doNothing) )
1114  {
1115  double val = ((variablesScaledFlag)?(t0):(1.0));
1116  int rSize = theReactions.getNumSpecies();
1117  for (int i=0;i<rSize; ++i)
1118  {
1119  *(dqdxConcEquConcVarPtrs[i][i]) += val;
1120  }
1121  }
1122  }
1123 
1124  return true;
1125 }
1126 
1127 //-----------------------------------------------------------------------------
1128 // Function : Region::loadDAEdFdx
1129 // Purpose :
1130 // Special Notes :
1131 // Scope : public
1132 // Creator : Eric R. Keiter
1133 // Creation Date : 7/21/06
1134 //-----------------------------------------------------------------------------
1135 bool Region::loadDAEdFdx (Linear::Matrix & dfdx)
1136 {
1137  if (baseReactionIndex != -1)
1138  {
1139  int rSize = theReactions.getNumSpecies();
1141  {
1142  // jacobian for dcop is just ones on the diagonals, nothing else
1143  for (int i=0; i<rSize; ++i)
1144  {
1145  *(dfdxConcEquConcVarPtrs[i][i]) += 1.0;
1146  }
1147  }
1148  else
1149  {
1150  for (int i=0;i<rSize; ++i)
1151  {
1152  for (int j=0;j<rSize; ++j)
1153  {
1154  double val = (-tempJac[i][j]);
1155  *(dfdxConcEquConcVarPtrs[i][j]) += val;
1156  }
1157  }
1158  }
1159  }
1160 
1161  return true;
1162 }
1163 
1164 //-----------------------------------------------------------------------------
1165 // Function : Region::updateSecondaryState
1166 // Purpose : Obtains time derivatives of concentrations from
1167 // time integrator
1168 // Special Notes :
1169 // Scope : public
1170 // Creator : Eric R. Keiter
1171 // Creation Date : 7/21/06
1172 //-----------------------------------------------------------------------------
1173 bool Region::updateSecondaryState (double * staDeriv)
1174 {
1175  if (baseReactionIndex != -1)
1176  {
1177  int rSize = theReactions.getNumSpecies();
1178  if (tempConcentrationDerivs.size() != rSize)
1179  {
1180  tempConcentrationDerivs.clear();
1181  tempConcentrationDerivs.resize(rSize,0.0);
1182  }
1183 
1184  for (int i=0;i<rSize;++i)
1185  {
1187 
1188  // If the variablesScaledFlag is true, then the concentrations
1189  // are already scaled, but the time is not.
1190  if (variablesScaledFlag)
1191  {
1193  }
1194  }
1195  }
1196 
1197  return true;
1198 }
1199 
1200 //-----------------------------------------------------------------------------
1201 // Function : Region::haveAnyReactions()
1202 // Purpose :
1203 // Special Notes :
1204 //
1205 // TVR: This one is a legacy of how I was keeping track of when
1206 // the network was initialized and jacobian set up. All the places
1207 // where this baseReactionIndex != -1 occur were really only checking
1208 // that the thing had been initialized.
1209 //
1210 // ERK: updated to include a test for "do nothing" flag.
1211 //
1212 // Scope : public
1213 // Creator : Eric R. Keiter, SNL
1214 // Creation Date : 05/22/10
1215 //-----------------------------------------------------------------------------
1217 {
1218  bool retVal = (baseReactionIndex != -1);
1219 
1220  if (regData.doNothing)
1221  {
1222  retVal = false;
1223  }
1224 
1225  return retVal;
1226 }
1227 
1228 //-----------------------------------------------------------------------------
1229 // Function : Region::getNumIntVars
1230 //
1231 // Purpose : Return the number of internal variables (solution vars)
1232 // this region is adding to the system.
1233 //
1234 // Special Notes : The number of internal variables is comprised of the
1235 // number of species in the reaction network.
1236 //
1237 // Scope : public
1238 //
1239 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1240 // Creation Date : 10/24/06
1241 //-----------------------------------------------------------------------------
1243 {
1244  int hInt=0;
1245  int numSpeciesVars=0;
1246 
1247  if (!(regData.doNothing))
1248  {
1249  numSpeciesVars=getNumSpecies();
1250  }
1251 
1252  return (numSpeciesVars+hInt);
1253 }
1254 
1255 } // namespace Device
1256 } // namespace Xyce
std::vector< std::vector< double * > > dqdxConcEquAuxVarPtrs
Definition: N_DEV_Region.h:233
void updateIntermediateVars(double *solVector, double *oldSolVector, double time)
Definition: N_DEV_Region.C:943
const InstanceName & getName()
Definition: N_DEV_Region.h:114
void setupJacStamp(std::vector< std::vector< int > > &jacStamp, std::vector< int > &colDep, int &firstReactant, int &lastIndex)
Definition: N_DEV_Region.C:633
double currTimeStep_
Region, BJT, Digital, ThermalResistor, ROM, Charon, Others.
void setScaleParams(double c, double t, double x)
Pure virtual class to augment a linear system.
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
const std::string & getEncodedName() const
Return the instance name encoded as: [s:]*xname [s:]*Ytype!name [s:]*Utype!name!count.
void addSource(std::string speciesName, Util::Expression *expr)
Definition: N_DEV_Region.C:277
void createDefaultReactionNetwork(const NetlistLocation &netlist_location, const std::string &reactionSpecFile)
Definition: N_DEV_Region.C:186
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec, const std::vector< int > &map, const std::vector< std::vector< int > > &map2)
Definition: N_DEV_Region.C:801
bool loadDAEdQdx(Linear::Matrix &dqdx)
std::vector< int > li_Concentrations
Definition: N_DEV_Region.h:239
const std::string & getSpeciesName(int i)
void setupScalingVars(ScalingVars &sv)
Definition: N_DEV_Region.C:354
std::vector< double > ddt
Definition: N_DEV_Region.h:223
void setupPointers(Linear::Matrix &dfdx, Linear::Matrix &dqdx)
Definition: N_DEV_Region.C:849
RegionData & regData
Definition: N_DEV_Region.h:199
const std::string & getConstantsName(int i)
bool loadDAEdFdx(Linear::Matrix &dfdx)
void addMasterSourceTerm(const std::string &speciesName)
void setInitialCondition(const std::string &name, const double val)
Definition: N_DEV_Region.C:263
bool loadDAEQVector(double *qVec)
std::vector< double > theConstantConcentrations
Definition: N_DEV_Region.h:215
void addMasterSource(std::string speciesName)
Definition: N_DEV_Region.C:292
void augmentNameMap(std::map< int, std::string > &intNameMap, DeviceInstance &di)
Definition: N_DEV_Region.C:752
std::vector< std::vector< int > > AConcentrationEquAuxNodeOffsets
Definition: N_DEV_Region.h:236
bool updateSecondaryState(double *staDeriv)
const SolverState & solState
Definition: N_DEV_Region.h:262
bool loadDAEdFdxdV(double *dfdxdv, double vdiff)
void loadNodeSymbols(Util::SymbolTable &symbol_table, const DeviceInstance &device_instance)
Definition: N_DEV_Region.C:726
Region(const NetlistLocation &netlist_location, RegionData &rd, const DeviceOptions &devOp, const SolverState &solst, bool sourceOn=true)
Definition: N_DEV_Region.C:83
std::vector< double > tempConcentrations
Definition: N_DEV_Region.h:218
void setMaterial(MaterialLayer *material, double Temp)
std::vector< double > initialConcentrations
Definition: N_DEV_Region.h:222
std::vector< std::vector< double * > > dqdxConcEquConcVarPtrs
Definition: N_DEV_Region.h:230
std::string outputName
Definition: N_DEV_Region.h:204
std::vector< std::vector< double * > > dfdxConcEquAuxVarPtrs
Definition: N_DEV_Region.h:232
std::vector< std::vector< double * > > dfdxConcEquConcVarPtrs
Definition: N_DEV_Region.h:229
std::vector< std::vector< double > > tempJac
Definition: N_DEV_Region.h:224
bool loadDAEFVector(double *fVec)
void initializeReactionNetwork(ScalingVars &sv, MaterialLayer *material, double Temp)
Definition: N_DEV_Region.C:206
std::pair< std::string, double > getInitialCondition(int i)
std::string spiceInternalName(const InstanceName &instance_name, const std::string &lead)
ReactionNetwork theReactions
Definition: N_DEV_Region.h:213
void setRateConstants(double T)
Definition: N_DEV_Region.C:307
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
int getReactantNum(const std::string &name)
std::vector< int > li_state_Concentrations
Definition: N_DEV_Region.h:243
void registerStateLIDs(const std::vector< int > &staLIDVecRef, int &i)
Definition: N_DEV_Region.C:779
void setReactionNetworkFromFile(const NetlistLocation &netlist_location, const std::string &fileName)
std::vector< double > tempConcentrationDerivs
Definition: N_DEV_Region.h:220
void addSourceTerm(const std::string &speciesName, const std::string &expressionStr)
void registerLIDs(const std::vector< int > &intLIDVec, const std::vector< int > &extLIDVec, int &intIndex)
Definition: N_DEV_Region.C:687