Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_ReactionNetwork.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_ReactionNetwork.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
33 //
34 // Creation Date : 03/20/2006
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.15.2.2 $
40 //
41 // Revision Date : $Date: 2014/08/20 19:42:08 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-----------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 //Standard includes
50 
51 #include <N_UTL_Misc.h>
52 
53 #ifdef Xyce_DEBUG_DEVICE
54 #include <iostream>
55 #endif
56 
57 #include <sstream>
58 
59 // Xyce Includes
60 #include <N_ERH_ErrorMgr.h>
61 #include <N_UTL_Xyce.h>
62 #include <N_UTL_fwd.h>
63 #include <N_UTL_Expression.h>
64 #include <N_DEV_ReactionNetwork.h>
65 
66 #ifdef Xyce_REACTION_PARSER
67 // Grrrr. Stupid bison 2.4 stopped putting the pre-prologue into the header.
68 // need this forward declaration
69 namespace Xyce {
70 namespace Device {
71 class ReactionLexer;
72 }}
73 
74 #include "N_DEV_ReactionParser.hxx"
75 // BLEAH! This is here DUPLICATED from N_DEV_ReactionParser.yxx
76 // because of STUPID choice in Bison 2.3 to put the post-prologue into the
77 // .cxx file instead of the .hxx file that Bison 2.1 used to put it in.
78 #undef yyFlexLexer
79  /* CAREFUL watch continuations! */
80 #define YY_DECL \
81  int N_DEV_ReactionLexer::getToken(Xyce::Device::N_DEV_ReactionParser::semantic_value *lvalp, \
82  Xyce::Device::location *llocp, \
83  map<std::string,int> &theSpeciesIDs)
84 
85  // YECH! Work around very stupid way that multiple parsers/lexers are
86  // handled.
87  // Bison's "%name-prefix" is implemented as a #define yylex "prefix"lex
88  // which BREAKS flex's C++ lexer: it contains a method "yylex" in the
89  // yyFlexLexer class. Unless we do this kludge, that method gets renamed
90  // with the define as well, and the result is a broken set of classes
91 #undef yylex
92 #include <FlexLexer.h>
93 #include <N_DEV_ReactionLexer.h>
94  // undo that kludge. Note that because of this stupidity, if the
95  // "%name-prefix" is changed, this line needs to be changed, too.
96 #define yylex N_DEV_lex
97 
98 #endif
99 
100 namespace Xyce {
101 namespace Device {
102 
103 //-----------------------------------------------------------------------------
104 // Function : ReactionNetwork::ReactionNetwork
105 // Purpose : Constructor
106 // Special Notes :
107 // Scope : public
108 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
109 // Creation Date : 03/20/06
110 //-----------------------------------------------------------------------------
111 ReactionNetwork::ReactionNetwork(const std::string &name)
112  : myName(name),
113  sourceScaleFac(1.0),
114  C0(1.0),
115  t0(1.0),
116  x0(1.0),
117  applySources(true)
118 {
119  theReactions.reserve(10); // try to cut down on copies
120 }
121 
122 //-----------------------------------------------------------------------------
123 // Function : ReactionNetwork::ReactionNetwork
124 // Purpose : Copy constructor
125 // Special Notes :
126 // Scope : public
127 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
128 // Creation Date : 03/20/06
129 //-----------------------------------------------------------------------------
131  const ReactionNetwork &right)
132  : speciesMap(right.speciesMap),
133  species(right.species),
134  constantsMap(right.constantsMap),
135  constants(right.constants),
136  initialConditions(right.initialConditions),
137  theReactions(right.theReactions),
138  reactionNamesMap(right.reactionNamesMap),
139  reactionNames(right.reactionNames),
140  myName(right.myName),
141  electronCaptureReactions(right.electronCaptureReactions),
142  holeCaptureReactions(right.holeCaptureReactions),
143  electronEmissionReactions(right.electronEmissionReactions),
144  holeEmissionReactions(right.holeEmissionReactions),
145  sourceScaleFac(right.sourceScaleFac),
146  C0(right.C0),
147  t0(right.t0),
148  x0(right.x0),
149  applySources(right.applySources)
150 {
151 
152  // Can't just copy the vector of source terms, coz those are pointers.
153  // Need to do deep copy:
154  int i,sourceSize;
155  sourceSize=right.theSourceTerms.size();
156  theSourceTerms.reserve(sourceSize);
157  for (i=0;i<sourceSize;++i)
158  {
159  Util::Expression *newSource;
160  // make a new one as a copy of the right one
161  newSource = new Util::Expression(*((right.theSourceTerms[i]).second));
162  theSourceTerms.push_back(std::pair<int,Util::Expression *>(
163  (right.theSourceTerms[i]).first,
164  newSource) );
165  }
166 
167 }
168 
169 //-----------------------------------------------------------------------------
170 // Function : ReactionNetwork::~ReactionNetwork
171 // Purpose : Destructor
172 // Special Notes :
173 // Scope : public
174 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
175 // Creation Date : 03/20/06
176 //-----------------------------------------------------------------------------
178 {
179 
180  // It is no longer the case that we store only copies of expression
181  // pointers allocated from other classes. We now *must* destroy expressions
182  // we have created in parsing. Since it is difficult to keep track of
183  // which expression pointers were passed in to us and which we created
184  // ourselves, we no longer store those passed-in pointers, but rather
185  // pointers to copies of the pointed-to expression.
186 
187  // Walk backwards through the sourceTerms vector, deleting the expression
188  // and removing the pair from the vector.
189  while (!theSourceTerms.empty())
190  {
191  std::pair<int,Util::Expression *> tempPair = theSourceTerms.back();
192  theSourceTerms.pop_back();
193  delete tempPair.second;
194  }
195 }
196 
197 //-----------------------------------------------------------------------------
198 // Function : ReactionNetwork::setReactionNetworkFromFile
199 // Purpose : Parse a reaction network specification file and set the
200 // network up.
201 //
202 // Special Notes :
203 //
204 // Scope : public
205 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
206 // Creation Date : 08/24/06
207 //-----------------------------------------------------------------------------
208 void
210 {
211 #ifdef Xyce_REACTION_PARSER
212  if (fileName != "") // do nothing if no file specified
213  {
214  // Get the reaction set from a file
215  ReactionLexer *theLexer;
216  std::ifstream reactionFile;
217  std::map<std::string,int> theSpeciesIDs;
218 
219  // temporary hard-coded filename
220  reactionFile.open(fileName.c_str(),std::ios::in);
221  if (reactionFile.is_open())
222  {
223  theLexer=new ReactionLexer(&reactionFile);
224  }
225  else
226  {
227  Report::UserError() << "ReactionNetwork::setReactionNetworkFromFile: Cannot open reaction specification file: " << fileName;
228  }
229 
230  XyceDevice::ReactionParser theParser(theLexer, theSpeciesIDs, *this);
231 
232 
233  if (theParser.parse())
234  {
235 #ifdef Xyce_DEBUG_DEVICE
236  Xyce::dout() << *this << std::endl;
237 #endif
238  Report::UserError() << "ReactionNetwork::setReactionNetworkFromFile: Parsing reaction spec from file " << fileName << " failed.";
239  }
240 
241  // we're done with this:
242  delete theLexer;
243  }
244 #endif
245 
246 }
247 
248 //-----------------------------------------------------------------------------
249 // Function : ReactionNetwork::setSpecies
250 // Purpose : register a list of species names used in reactions.
251 //
252 // Special Notes : Once registered this way, it is assumed that all vectors
253 // of species concentrations are ordered in the same way as
254 // the provided vector of species names.
255 //
256 // Scope : public
257 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
258 // Creation Date : 03/20/06
259 //-----------------------------------------------------------------------------
260 void ReactionNetwork::setSpecies(std::vector<Specie> &theSpeciesVect)
261 {
262 
263  int i;
264  int nspec=theSpeciesVect.size();
265 
266  speciesMap.clear();
267  species=theSpeciesVect;
268 
269  for (i=0;i<nspec;++i)
270  {
271  speciesMap[theSpeciesVect[i].getName()]=i;
272  }
273 
274 }
275 
276 //-----------------------------------------------------------------------------
277 // Function : ReactionNetwork::setConstants
278 // Purpose : register a list of constant species names used in reactions.
279 //
280 // Special Notes : Once registered this way, it is assumed that all
281 // vectors of constant species concentrations are ordered in
282 // the same way as the provided vector of species names.
283 //
284 // Constant species are those whose concentrations remain
285 // unaltered by the reaction network, e.g. those that are
286 // fed into the system at fixed rate as in a CSTR.
287 //
288 // Scope : public
289 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
290 // Creation Date : 03/20/06
291 //-----------------------------------------------------------------------------
292 void ReactionNetwork::setConstants(std::vector<Specie> &theConstantsVect)
293 {
294 
295  int i;
296  int nspec=theConstantsVect.size();
297 
298  constantsMap.clear();
299  constants = theConstantsVect;
300 
301  for (i=0;i<nspec;++i)
302  {
303  constantsMap[theConstantsVect[i].getName()]=i;
304  }
305 }
306 
307 
308 //-----------------------------------------------------------------------------
309 // Function : ReactionNetwork::addSpecie
310 // Purpose : add one to the list of species names used in reactions.
311 //
312 // Scope : public
313 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
314 // Creation Date : 03/20/06
315 //-----------------------------------------------------------------------------
316 void ReactionNetwork::addSpecie(const Specie &aSpecie)
317 {
318 
319  int i=species.size(); // get index of next one we add
320  species.push_back(aSpecie);
321  speciesMap[aSpecie.getName()]=i;
322 
323 }
324 
325 //-----------------------------------------------------------------------------
326 // Function : ReactionNetwork::addConstant
327 // Purpose : add one to the list of constant names used in reactions.
328 //
329 // Scope : public
330 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
331 // Creation Date : 03/20/06
332 //-----------------------------------------------------------------------------
333 void ReactionNetwork::addConstant(const Specie &aConstant)
334 {
335 
336  int i=constants.size(); // get index of next one we add
337  constants.push_back(aConstant);
338  constantsMap[aConstant.getName()]=i;
339 
340 }
341 
342 //-----------------------------------------------------------------------------
343 // Function : ReactionNetwork::addReaction
344 // Purpose : Create a new named reaction in the network
345 // Special Notes :
346 // Scope : public
347 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
348 // Creation Date : 03/20/06
349 //-----------------------------------------------------------------------------
350 void ReactionNetwork::addReaction(const std::string &name)
351 {
352  N_DEV_Reaction dummy;
353 
354  addReaction(name, dummy);
355 }
356 
357 //-----------------------------------------------------------------------------
358 // Function : ReactionNetwork::addReaction
359 // Purpose : Add a reaction object into the network and give it a name
360 // Special Notes :
361 // Scope : public
362 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
363 // Creation Date : 03/20/06
364 //-----------------------------------------------------------------------------
365 void ReactionNetwork::addReaction(const std::string &name, N_DEV_Reaction &reaction)
366 {
367  // first check if there is already a reaction of that name in the
368  // reactions map:
369 
370  if (reactionNamesMap.find(name) != reactionNamesMap.end())
371  {
372  Report::DevelFatal() << " Attempt to add reaction duplicate name " << name;
373  }
374 
375  //try to cut down on calls to copy constructor
376  if (theReactions.capacity()<=theReactions.size())
377  {
378  theReactions.reserve(theReactions.size()+10);
379  }
380  theReactions.push_back(reaction);
381  reactionNames.push_back(name);
382  reactionNamesMap[name]=theReactions.size()-1;
383 
384  // Now check if the reaction has "_ELECTRON_CAPTURE",
385  // "_ELECTRON_EMISSION", "_HOLE_CAPTURE" or "_HOLE_EMISSION" in it.
386  // If so, keep track of it in a separate vector for such things.
387  // we do this so we can later get at them quickly without doing name
388  // searches.
389  if (name.find("_ELECTRON_CAPTURE",0) != std::string::npos)
390  {
391  electronCaptureReactions.push_back(theReactions.size()-1);
392  }
393  else if (name.find("_HOLE_CAPTURE",0) != std::string::npos)
394  {
395  holeCaptureReactions.push_back(theReactions.size()-1);
396  }
397  else if (name.find("_ELECTRON_EMISSION",0) != std::string::npos)
398  {
399  electronEmissionReactions.push_back(theReactions.size()-1);
400  }
401  else if (name.find("_HOLE_EMISSION",0) != std::string::npos)
402  {
403  holeEmissionReactions.push_back(theReactions.size()-1);
404  }
405 }
406 
407 //-----------------------------------------------------------------------------
408 // Function : ReactionNetwork::addReactant
409 // Purpose : add a species/stoichiometric coefficient pair to the
410 // reactant list of a specified named reaction
411 // The species is specified using its name, and can be either
412 // one of those in the list provided by setSpecies or
413 // setConstants.
414 // Special Notes :
415 // Scope : public
416 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
417 // Creation Date : 03/20/06
418 //-----------------------------------------------------------------------------
419 void ReactionNetwork::addReactant(const std::string &name, const std::string &reactant, double stoich)
420 {
421 
422  std::map<std::string,int>::iterator n_i;
423  // check that name exists in map
424  int reactionNum;
425  reactionNum=getReactionNum(name);
426  if (reactionNum == -1)
427  {
428  Report::DevelFatal() << " Attempt to add reactant " << reactant
429  << " to non-existant reaction " << name;
430  }
431  else
432  {
433  int speciesNum;
434  // now check if we know this reactant
435 
436  n_i = speciesMap.find(reactant);
437  if (n_i == speciesMap.end())
438  {
439  // not a solution species --- is it a constant?
440  n_i = constantsMap.find(reactant);
441  if (n_i == constantsMap.end())
442  { // nope
443  Report::DevelFatal() << "attempt to add unknown reactant " << reactant
444  << " to reaction number " << reactionNum
445  << "("<<name<<")";
446  }
447  else
448  {
449  speciesNum = -(n_i->second+1);
450  }
451  }
452  else
453  {
454  speciesNum = n_i->second;
455  }
456 
457 
458  getReaction(reactionNum).addReactant(speciesNum,stoich);
459  }
460 }
461 
462 //-----------------------------------------------------------------------------
463 // Function : ReactionNetwork::addProduct
464 // Purpose : add a species/stoichiometric coefficient pair to the
465 // product list of a specified named reaction
466 // The species is specified using its name, and must be
467 // one of those in the list provided by setSpecies
468 // (must not be one from the Constants list).
469 // Special Notes :
470 // Scope : public
471 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
472 // Creation Date : 03/20/06
473 //-----------------------------------------------------------------------------
474 void ReactionNetwork::addProduct(const std::string &name, const std::string &product, double stoich)
475 {
476 
477  std::map<std::string,int>::iterator n_i;
478 
479  // check that reaction name exists in map
480  // check that name exists in map
481  int reactionNum;
482  reactionNum=getReactionNum(name);
483  if (reactionNum == -1)
484  {
485  Report::DevelFatal() << " Attempt to add product " << product
486  << " to non-existant reaction " << name;
487  }
488  else
489  {
490  int speciesNum;
491  // now check if we know this product
492 
493  n_i = speciesMap.find(product);
494  if (n_i == speciesMap.end())
495  {
496  // not a solution species --- is it a constant?
497  n_i = constantsMap.find(product);
498  if (n_i == constantsMap.end())
499  { // nope
500  Report::DevelFatal() << "attempt to add unknown product " << product
501  << " to reaction number " << reactionNum
502  << "("<<name<<")";
503  }
504  else
505  {
506  std::ostringstream ost;
507 
508 #ifdef Xyce_RXN_WARNINGS
509  Report::UserWarning() << " Specified constant species " << product
510  << " as product of reaction number " << reactionNum
511  << "(" << name << ")"<<std::endl
512  << " IGNORING that product";
513 #endif
514  }
515  }
516  else
517  {
518  speciesNum = n_i->second;
519  getReaction(reactionNum).addProduct(speciesNum,stoich);
520  }
521 
522 
523  }
524 }
525 
526 
527 //-----------------------------------------------------------------------------
528 // Function : ReactionNetwork::setRateConstant
529 // Purpose : set the rate constant for the named reaction
530 // Special Notes :
531 // Scope : public
532 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
533 // Creation Date : 03/20/06
534 //-----------------------------------------------------------------------------
535 void ReactionNetwork::setRateConstant(const std::string &name, double k)
536 {
537  int reactionNum;
538  // check that reaction name exists in map
539  reactionNum=getReactionNum(name);
540  if (reactionNum == -1)
541  {
542  Report::DevelFatal() << " Attempt to set rate constant of non-existant reaction "
543  << name;
544  }
545  else
546  {
547  getReaction(reactionNum).setRateConstant(k);
548  }
549 }
550 
551 //-----------------------------------------------------------------------------
552 // Function : ReactionNetwork::scaleRateConstant
553 // Purpose : set the rate constant for the named reaction
554 // Special Notes :
555 // Scope : public
556 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
557 // Creation Date : 06/01/06
558 //-----------------------------------------------------------------------------
559 void ReactionNetwork::scaleRateConstant(const std::string &name, double kscale)
560 {
561 
562  int reactionNum;
563  // check that reaction name exists in map
564  reactionNum = getReactionNum(name);
565  if (reactionNum == -1)
566  {
567  Report::DevelFatal() << " Attempt to scale rate constant of non-existant reaction "
568  << name;
569  }
570  else
571  {
572  getReaction(reactionNum).scaleRateConstant(kscale);
573  }
574 }
575 
576 //-----------------------------------------------------------------------------
577 // Function : ReactionNetwork::setRateConstantFromCalculator
578 // Purpose : set the rate constant for the named reaction according
579 // to its saved method
580 // Special Notes :
581 // Scope : public
582 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
583 // Creation Date : 08/01/06
584 //-----------------------------------------------------------------------------
585 void ReactionNetwork::setRateConstantFromCalculator (const std::string &name, double T)
586 {
587 
588  int reactionNum;
589  // check that reaction name exists in map
590  reactionNum = getReactionNum(name);
591  if (reactionNum == -1)
592  {
593  Report::DevelFatal() << " Attempt to scale rate constant of non-existant reaction "
594  << name;
595  }
596  else
597  {
599  }
600 }
601 
602 
603 //-----------------------------------------------------------------------------
604 // Function : ReactionNetwork::setRateConstantFromCalculator
605 // Purpose : set the rate constant for the named reaction according
606 // to its saved method
607 // Special Notes :
608 // Scope : public
609 // Creator : Lawrence C Musson, SNL, Electrical and Microsystems Modeling
610 // Creation Date : 04/17/2014
611 //-----------------------------------------------------------------------------
612 void ReactionNetwork::setRateConstantFromCalculator (const std::string &name, double T,
613  std::vector<double> &concs,
614  std::vector<double> &constant_vec)
615 {
616 
617  int reactionNum;
618  // check that reaction name exists in map
619  reactionNum = getReactionNum(name);
620  if (reactionNum == -1)
621  {
622  Report::DevelFatal() << " Attempt to scale rate constant of non-existant reaction "
623  << name;
624  }
625  else
626  {
627  getReaction(reactionNum).setRateConstantFromCalculator(T,concs,constant_vec);
628  }
629 }
630 
631 //-----------------------------------------------------------------------------
632 // Function : ReactionNetwork::scaleRateConstantFromCalculator
633 // Purpose : scale the rate constant for the named reaction according
634 // to its saved method
635 // Special Notes :
636 // Scope : public
637 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
638 // Creation Date : 08/01/06
639 //-----------------------------------------------------------------------------
641 {
642 
643  int reactionNum;
644  // check that reaction name exists in map
645  reactionNum = getReactionNum(name);
646  if (reactionNum == -1)
647  {
648  Report::DevelFatal() << " Attempt to scale rate constant of non-existant reaction "
649  << name;
650  }
651  else
652  {
654  }
655 }
656 
657 //-----------------------------------------------------------------------------
658 // Function : ReactionNetwork::unscaleRateConstantFromCalculator
659 // Purpose : unscale the rate constant for the named reaction according
660 // to its saved method
661 // Special Notes :
662 // Scope : public
663 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
664 // Creation Date : 08/01/06
665 //-----------------------------------------------------------------------------
667 {
668 
669  int reactionNum;
670  // check that reaction name exists in map
671  reactionNum = getReactionNum(name);
672  if (reactionNum == -1)
673  {
674  Report::DevelFatal() << " Attempt to scale rate constant of non-existant reaction "
675  << name;
676  }
677  else
678  {
680  }
681 }
682 
683 //-----------------------------------------------------------------------------
684 // Function : ReactionNetwork::setRateConstantsFromCalc
685 // Purpose : set the rate constant for the all reaction according
686 // to their saved methods
687 // Special Notes :
688 // Scope : public
689 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
690 // Creation Date : 08/02/06
691 //-----------------------------------------------------------------------------
693 {
694  int numReacts=theReactions.size();
695  int i;
696  for (i=0; i<numReacts; ++i)
697  {
698  theReactions[i].setRateConstantFromCalculator(T);
699  }
700 }
701 
702 
703 //-----------------------------------------------------------------------------
704 // Function : ReactionNetwork::setRateConstantsFromCalc
705 // Purpose : set the rate constant for the all reaction according
706 // to their saved methods
707 // Special Notes :
708 // Scope : public
709 // Creator : Lawrence C Musson, SNL, Electrical and Microsystems Modeling
710 // Creation Date : 08/02/06
711 //-----------------------------------------------------------------------------
713  std::vector<double> &concs,
714  std::vector<double> &constant_vec)
715 {
716  int numReacts=theReactions.size();
717  int i;
718  for (i=0; i<numReacts; ++i)
719  {
720  theReactions[i].setRateConstantFromCalculator(T,concs,constant_vec);
721  }
722 }
723 
724 //-----------------------------------------------------------------------------
725 // Function : ReactionNetwork::scaleRateConstantsFromCalc
726 // Purpose : scale the rate constant for the all reaction according
727 // to their saved methods
728 // Special Notes :
729 // Scope : public
730 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
731 // Creation Date : 08/02/06
732 //-----------------------------------------------------------------------------
734 {
735  int numReacts=theReactions.size();
736  int i;
737  for (i=0; i<numReacts; ++i)
738  {
739  theReactions[i].scaleRateConstantFromCalculator();
740  }
741 }
742 
743 //-----------------------------------------------------------------------------
744 // Function : ReactionNetwork::unscaleRateConstantsFromCalc
745 // Purpose : unscale the rate constant for the all reaction according
746 // to their saved methods
747 // Special Notes :
748 // Scope : public
749 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
750 // Creation Date : 08/02/06
751 //-----------------------------------------------------------------------------
753 {
754  int numReacts=theReactions.size();
755  int i;
756  for (i=0; i<numReacts; ++i)
757  {
758  theReactions[i].unscaleRateConstantFromCalculator();
759  }
760 }
761 
762 //-----------------------------------------------------------------------------
763 // Function : ReactionNetwork::setScaleParams
764 // Purpose : set the scale parameters and pass them down to any existing
765 // reactions. Done this way, we make sure that all reactions
766 // in the network are reset to the same set of scale
767 // parameters.
768 // Special Notes : If called before reactions defined, it's OK, because as
769 // each reaction's rate calculator is created, the stored
770 // C0, t0, and x0 are passed to it. This function does the
771 // calls down to existing reactions just in case they were
772 // previously defined.
773 // Scope : public
774 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
775 // Creation Date : 08/24/06
776 //-----------------------------------------------------------------------------
777 void ReactionNetwork::setScaleParams(double c,double t, double x)
778 {
779  std::vector<N_DEV_Reaction>::iterator reactionIter=theReactions.begin();
780  std::vector<N_DEV_Reaction>::iterator reactionIterEnd=theReactions.end();
781  C0=c;
782  t0=t;
783  x0=x;
784 
785  for (; reactionIter != reactionIterEnd; ++reactionIter)
786  {
787  reactionIter->setScaleFactors(C0,t0,x0);
788  }
789 }
790 
791 //-----------------------------------------------------------------------------
792 // Function : ReactionNetwork::addSourceTerm
793 // Purpose : add an expression for a source term
794 // Special Notes :
795 // Scope : public
796 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
797 // Creation Date : 08/04/06
798 //-----------------------------------------------------------------------------
799 void ReactionNetwork::addSourceTerm(const std::string &speciesName, const std::string &expressionStr)
800 {
801  if (applySources)
802  {
803  int speciesNum=getSpeciesNum(speciesName);
804  if (speciesNum >= 0) // the species exists
805  {
806  Util::Expression *foo= new Util::Expression(expressionStr);
807  theSourceTerms.push_back( std::pair<int,Util::Expression *>(speciesNum, foo));
808  }
809  }
810 }
811 
812 //-----------------------------------------------------------------------------
813 // Function : ReactionNetwork::addSourceTerm
814 // Purpose : add an expression for a source term given
815 // already-constructed expression object.
816 // Special Notes :
817 // Scope : public
818 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
819 // Creation Date : 08/04/06
820 //-----------------------------------------------------------------------------
821 void ReactionNetwork::addSourceTerm(const std::string &speciesName, Util::Expression *expression)
822 {
823  int speciesNum=getSpeciesNum(speciesName);
824  Util::Expression * ExpressionCopy=new Util::Expression(*expression);
825 
826  if (speciesNum >= 0) // the species exists
827  {
828  theSourceTerms.push_back(
829  std::pair<int,Util::Expression *>(speciesNum,ExpressionCopy));
830  }
831 }
832 
833 //-----------------------------------------------------------------------------
834 // Function : ReactionNetwork::addMasterSourceTerm
835 // Purpose : add an expression for a source term that depends on a
836 // "master" source value.
837 // Special Notes :
838 // Scope : public
839 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
840 // Creation Date : 08/04/06
841 //-----------------------------------------------------------------------------
842 void ReactionNetwork::addMasterSourceTerm(const std::string &speciesName)
843 {
844  int speciesNum=getSpeciesNum(speciesName);
845 
846  if (speciesNum >= 0) // the species exists
847  {
848  masterSourceSpecies.push_back(speciesNum);
849  }
850 }
851 
852 //-----------------------------------------------------------------------------
853 // Function : ReactionNetwork::setSimTime
854 // Purpose : set internal "time" variable for all source terms
855 // Special Notes :
856 // Scope : public
857 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
858 // Creation Date : 08/04/06
859 //-----------------------------------------------------------------------------
861 {
862  std::vector< std::pair<int,Util::Expression *> >::iterator iterSource=
863  theSourceTerms.begin();
864  std::vector< std::pair<int,Util::Expression *> >::iterator source_end=
865  theSourceTerms.end();
866 
867  for (;iterSource != source_end; ++iterSource)
868  {
869  (iterSource->second)->set_sim_time(time);
870  }
871 }
872 
873 //-----------------------------------------------------------------------------
874 // Function : ReactionNetwork::getBreakpointTime
875 // Purpose : return the next time at which any source will have a
876 // breakpoint
877 // Special Notes :
878 // Scope : public
879 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
880 // Creation Date : 03/20/06
881 //-----------------------------------------------------------------------------
883 {
884  double breaktime=0, btime;
885  std::vector< std::pair<int,Util::Expression *> >::iterator iterSource=
886  theSourceTerms.begin();
887  std::vector< std::pair<int,Util::Expression *> >::iterator source_end=
888  theSourceTerms.end();
889 
890  for (;iterSource != source_end; ++iterSource)
891  {
892  btime=(iterSource->second)->get_break_time();
893  // pick smallest break time of all sources.
894  if (breaktime>0)
895  {
896  if (btime<breaktime)
897  {
898  breaktime=btime;
899  }
900  }
901  else
902  {
903  breaktime=btime;
904  }
905  }
906 
907  return (breaktime);
908 }
909 
910 //-----------------------------------------------------------------------------
911 // Function : ReactionNetwork::getDdt
912 // Purpose : compute the time derivative of all species concentrations
913 // Special Notes :
914 // Scope : public
915 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
916 // Creation Date : 03/20/06
917 //-----------------------------------------------------------------------------
918 void ReactionNetwork::getDdt(std::vector<double> &concs,std::vector<double> &constant_vec,
919  std::vector<double> &ddt)
920 {
921  int rSize=theReactions.size();
922  int i;
923  for (i=0;i<rSize;++i)
924  {
925  theReactions[i].getDdt(concs,constant_vec,ddt);
926  }
927 
928  // add in the source terms
929  std::vector< std::pair<int,Util::Expression *> >::iterator iterSource=
930  theSourceTerms.begin();
931  std::vector< std::pair<int,Util::Expression *> >::iterator source_end=
932  theSourceTerms.end();
933 
934  for (;iterSource != source_end; ++iterSource)
935  {
936  double return_val;
937  (iterSource->second)->evaluateFunction(return_val); // ignore return val? That's
938  // what's done everywhere else
939  ddt[(iterSource->first)] += sourceScaleFac*return_val;
940  }
941 
942  // Add in the master source terms:
943  std::vector<int>::iterator iterMasterSource=masterSourceSpecies.begin();
944  std::vector<int>::iterator masterSource_end=masterSourceSpecies.end();
945  for (; iterMasterSource!= masterSource_end; ++iterMasterSource)
946  {
947  ddt[*iterMasterSource] += masterSourceValue*sourceScaleFac;
948  }
949 
950 }
951 
952 //-----------------------------------------------------------------------------
953 // Function : ReactionNetwork::getJac
954 // Purpose : compute the jacobian of the reaction network, the
955 // derivatives of the time derivatives with respect to species
956 // concentration.
957 // Special Notes :
958 // Scope : public
959 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
960 // Creation Date : 03/20/06
961 //-----------------------------------------------------------------------------
962 void ReactionNetwork::getJac(std::vector<double> &concs, std::vector<double> &constant_vec,
963  std::vector<std::vector<double> >&jac)
964 {
965  int rSize=theReactions.size();
966  int i;
967  for (i=0;i<rSize;++i)
968  {
969  theReactions[i].getJac(concs,constant_vec,jac);
970  }
971 }
972 
973 //-----------------------------------------------------------------------------
974 // Function : ReactionNetwork::getDFdConst
975 // Purpose : compute the derivatives of the RHS with respect to
976 // a specified constant concentration.
977 // Special Notes :
978 // Scope : public
979 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
980 // Creation Date : 10/17/06
981 //-----------------------------------------------------------------------------
982 void ReactionNetwork::getDFdConst( const std::string & constantName,
983  std::vector<double> &concs,
984  std::vector<double> &constant_vec,
985  std::vector<double> &dFdConst)
986 {
987  int rSize=theReactions.size();
988  int cSize=concs.size();
989  int i;
990  int constNum=getConstantNum(constantName);
991 
992  dFdConst.resize(cSize);
993  for (i=0;i<cSize;++i)
994  dFdConst[i]=0.0;
995 
996  for (i=0;i<rSize;++i)
997  {
998  theReactions[i].getDFdConst(constNum,concs,constant_vec,dFdConst);
999  }
1000 }
1001 
1002 
1003 //-----------------------------------------------------------------------------
1004 // Function : ReactionNetwork::getRate
1005 // Purpose : Compute the total rate at which species are "consumed" or
1006 // "produced" by all the capture and emission reactions,
1007 // if there are any. This can be used even if the species
1008 // concentration is held fixed (it'll just be the sum of all
1009 // reaction rates involving electrons).
1010 // Special Notes : Assumes that all emission and capture reactions are
1011 // of the form B=>A+E or A+E=>B and will be incorrect if
1012 // the number of any reaction not of this form is listed in
1013 // the capture or emission vectors.
1014 //
1015 // Generic version in which the list of capture and emission
1016 // reactions are passed in
1017 //
1018 // Scope : public
1019 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1020 // Creation Date : 09/13/06
1021 //-----------------------------------------------------------------------------
1022 double ReactionNetwork::getRate(std::vector<double> &concs,
1023  std::vector<double> &constant_vec,
1024  std::vector<int> &captureVect,
1025  std::vector<int> &emissionVect)
1026 {
1027  int i;
1028  double rate=0;
1029 
1030  for (i=0;i<captureVect.size();++i)
1031  {
1032  rate -= theReactions[captureVect[i]].getRate(concs, constant_vec);
1033  }
1034 
1035  for (i=0;i<emissionVect.size();++i)
1036  {
1037  rate += theReactions[emissionVect[i]].getRate(concs,constant_vec);
1038  }
1039 
1040  return rate;
1041 }
1042 
1043 //-----------------------------------------------------------------------------
1044 // Function : ReactionNetwork::getCaptureLifetime
1045 // Purpose : Given a list of capture reaction numbers and the
1046 // species number of the concentration consumed by those
1047 // reactions, return the lifetime.
1048 // Special Notes : Returns -1 if lifetime would be infinite (zero capture rate)
1049 // This is a kludge, but one that is easily tested by anyone
1050 // who uses this.
1051 //
1052 // Scope : public
1053 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1054 // Creation Date : 09/20/06
1055 //-----------------------------------------------------------------------------
1056 double ReactionNetwork::getCaptureLifetime(std::vector<double> &concs,
1057  std::vector<double> &constant_vec,
1058  std::vector<int> &captureVect,
1059  double & concentration)
1060 {
1061  int i;
1062  double rate=0;
1063 
1064  for (i=0;i<captureVect.size();++i)
1065  {
1066  rate += theReactions[captureVect[i]].getRate(concs, constant_vec);
1067  }
1068 
1069  // inverse of lifetime = rate/concentration, so...
1070  if (rate > 0) // don't try to compute infinite lifetime!
1071  return concentration/rate;
1072  else
1073  return (-1.0); // bollocks, but let's not quibble. This is just as
1074  // invalid a lifetime as infinity would be!
1075 
1076 }
1077 
1078 //-----------------------------------------------------------------------------
1079 // Function : ReactionNetwork::getCaptureLifetimes
1080 // Purpose : Given a list of capture reaction numbers and the
1081 // species number of the concentration consumed by those
1082 // reactions, return a vector of lifetimes due to each
1083 // reaction.
1084 // Special Notes : Returns -1 if lifetime would be infinite (zero capture rate)
1085 // This is a kludge, but one that is easily tested by anyone
1086 // who uses this.
1087 //
1088 // Scope : public
1089 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1090 // Creation Date : 09/20/06
1091 //-----------------------------------------------------------------------------
1092 void ReactionNetwork::getCaptureLifetimes(std::vector<double> &concs,
1093  std::vector<double> &constant_vec,
1094  std::vector<int> &captureVect,
1095  double & concentration,
1096  std::vector<double> &lifetimes)
1097 {
1098  int i;
1099  lifetimes.resize(captureVect.size());
1100 
1101  for (i=0;i<captureVect.size();++i)
1102  {
1103  lifetimes[i] = theReactions[captureVect[i]].getRate(concs, constant_vec);
1104  // inverse of lifetime = rate/concentration, so...
1105  if (lifetimes[i] > 0) // don't try to compute infinite lifetime!
1106  lifetimes[i] = concentration/lifetimes[i];
1107  else
1108  lifetimes[i]=-1.0; // bollocks, but let's not quibble. This is just as
1109  // invalid a lifetime as infinity would be!
1110  }
1111 
1112 }
1113 
1114 //-----------------------------------------------------------------------------
1115 // Function : ReactionNetwork::getDRateDC
1116 // Purpose : Compute the vector of derivatives of the Rate (as returned
1117 // by getRate) with respect to concentrations
1118 //
1119 // Special Notes : Assumes that all emission and capture reactions are
1120 // of the form B=>A+E or A+E=>B and will be incorrect if
1121 // the number of any reaction not of this form is listed in
1122 // the capture or emission vectors.
1123 //
1124 // Generic version in which the list of capture and emission
1125 // reactions are passed in
1126 //
1127 // Note that dRatedC is zeroed, so if you need to sum
1128 // terms from multiple species, you need to pass a temporary
1129 // to this routine and sum terms in to a different vector.
1130 //
1131 // Scope : public
1132 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1133 // Creation Date : 09/13/06
1134 //-----------------------------------------------------------------------------
1135 void ReactionNetwork::getDRateDC(std::vector<double> &concs,
1136  std::vector<double> &constant_vec,
1137  std::vector<int> &captureVect,
1138  std::vector<int> &emissionVect,
1139  std::vector<double> &dRatedC)
1140 {
1141  int i,j;
1142  int cSize=dRatedC.size();
1143  std::vector<double> tempdRdC(cSize);
1144 
1145  for (i=0;i<cSize;++i)
1146  {
1147  dRatedC[i]=0;
1148  }
1149 
1150  for (i=0;i<captureVect.size();++i)
1151  {
1152  tempdRdC.assign(cSize,0.0);
1153  theReactions[captureVect[i]].getDRateDC(concs, constant_vec, tempdRdC);
1154 
1155  for (j=0;j<cSize;++j)
1156  {
1157  dRatedC[j] -= tempdRdC[j];
1158 #ifdef Xyce_DEBUG_DEVICE
1159  //cout << "ReactionNetwork::getDRateDC: Reaction: "<<captureVect[i]<<" tempdRdC["<<j<<"] = " << tempdRdC[j]<<std::endl;
1160 #endif
1161  }
1162  }
1163 
1164  for (i=0;i<emissionVect.size();++i)
1165  {
1166  tempdRdC.assign(cSize,0.0);
1167  theReactions[emissionVect[i]].getDRateDC(concs, constant_vec, tempdRdC);
1168 
1169  for (j=0;j<cSize;++j)
1170  {
1171  dRatedC[j] += tempdRdC[j];
1172 #ifdef Xyce_DEBUG_DEVICE
1173  //cout << "ReactionNetwork::getDRateDC: Reaction: "<<emissionVect[i]<<" tempdRdC["<<j<<"] = " << tempdRdC[j]<<std::endl;
1174 #endif
1175  }
1176  }
1177 }
1178 
1179 
1180 //-----------------------------------------------------------------------------
1181 // Function : ReactionNetwork::getDRateDConst
1182 //
1183 // Purpose : Compute the vector of derivatives of the Rate (as returned
1184 // by getRate) with respect to constants, like E and H.
1185 //
1186 // Special Notes : Assumes that all emission and capture reactions are
1187 // of the form B=>A+E or A+E=>B and will be incorrect if
1188 // the number of any reaction not of this form is listed in
1189 // the capture or emission vectors.
1190 //
1191 // Generic version in which the list of capture and emission
1192 // reactions are passed in
1193 //
1194 // Note that dRatedConst is zeroed, so if you need to sum
1195 // terms from multiple species, you need to pass a temporary
1196 // to this routine and sum terms in to a different vector.
1197 //
1198 // Scope : public
1199 // Creator : Eric Keiter
1200 // Creation Date : 11/15/08
1201 //-----------------------------------------------------------------------------
1202 void ReactionNetwork::getDRateDConst(std::vector<double> &concs,
1203  std::vector<double> &constant_vec,
1204  std::vector<int> &captureVect,
1205  std::vector<int> &emissionVect,
1206  std::vector<double> &dRatedConst)
1207 {
1208  int i,j;
1209  int cSize=dRatedConst.size();
1210  std::vector<double> tempdRdConst(cSize);
1211 
1212  for (i=0;i<cSize;++i)
1213  {
1214  dRatedConst[i]=0;
1215  }
1216 
1217  for (i=0;i<captureVect.size();++i)
1218  {
1219  tempdRdConst.assign(cSize,0.0);
1220 
1221  for (j=0;j<cSize;++j)
1222  {
1223  theReactions[captureVect[i]].getDRateDConst(j, concs, constant_vec, tempdRdConst[j]);
1224  dRatedConst[j] -= tempdRdConst[j];
1225 #ifdef Xyce_DEBUG_DEVICE
1226  //cout << "ReactionNetwork::getDRateDConst: Reaction: "<<captureVect[i]<<" tempdRdConst["<<j<<"] = " << tempdRdConst[j]<<std::endl;
1227 #endif
1228  }
1229  }
1230 #ifdef Xyce_DEBUG_DEVICE
1231  //cout << "After capture reactions:"<<std::endl;
1232  //for (j=0;j<cSize;++j)
1233  //{
1234  //cout << "ReactionNetwork::getDRateDConst: dRatedConst["<<j<<"] =" << dRatedConst[j] << std::endl;
1235  //}
1236 #endif
1237 
1238  for (i=0;i<emissionVect.size();++i)
1239  {
1240  tempdRdConst.assign(cSize,0.0);
1241 
1242  for (j=0;j<cSize;++j)
1243  {
1244  theReactions[emissionVect[i]].getDRateDConst(j, concs, constant_vec, tempdRdConst[j]);
1245  dRatedConst[j] += tempdRdConst[j];
1246 #ifdef Xyce_DEBUG_DEVICE
1247  //cout << "ReactionNetwork::getDRateDConst: Reaction: "<<emissionVect[i]<<" tempdRdConst["<<j<<"] = " << tempdRdConst[j]<<std::endl;
1248 #endif
1249  }
1250  }
1251 #ifdef Xyce_DEBUG_DEVICE
1252  //cout << "After emission reactions:"<<std::endl;
1253  //for (j=0;j<cSize;++j)
1254  //{
1255  //cout << "ReactionNetwork::getDRateDConst: dRatedConst["<<j<<"] =" << dRatedConst[j] << std::endl;
1256  //}
1257 #endif
1258 
1259 }
1260 
1261 
1262 
1263 //-----------------------------------------------------------------------------
1264 // Function : ReactionNetwork::setBourgoinCorbettCalc
1265 // Purpose : set the named Bourgoin Corbett parameters in the species objects
1266 // Corbett enhanced diffusion
1267 // Special Notes :
1268 // Scope : public
1269 // Creator : Lawrence C Musson, SNL
1270 // Creation Date : 03/25/14
1271 //-----------------------------------------------------------------------------
1272  void ReactionNetwork::setBourgoinCorbettCalc(const std::string &speciesName,const std::string &carrierName,
1273  double sigma, double hopDistance)
1274  {
1275 
1276 
1277 
1278  //int i=species.size(); // get index of next one we add
1279  //species.push_back(aSpecie);
1280  //speciesMap[aSpecie.getName()]=i;
1281 
1282  int speciesIndex = speciesMap[speciesName];
1283 
1284  int carrierIndex=-1;
1285 
1286  double thermalVelocity=0.0;
1287 
1288  if(carrierName == "E")
1289  {
1290  carrierIndex = 0;
1291  thermalVelocity = 2.3e7;
1292  //thermalVelocity = 20335462.541814957; //This was taken from Myers' code
1293  }
1294  else if(carrierName == "H")
1295  {
1296  carrierIndex = 1;
1297  thermalVelocity = 1.9e7;
1298  //thermalVelocity = 16805101.599178847; //This was taken from Myers' code
1299  }
1300  else
1301  {
1302  Report::DevelFatal() << "ReactionNetwork::setBourgoinCorbettCalc: Illegal carrier for BC enhancement: " << carrierName;
1303  }
1304 
1305  species[speciesIndex].setBCEnhancedDiffusion(carrierIndex,sigma,thermalVelocity,hopDistance);
1306 
1307  }
1308 
1309 } // namespace Device
1310 } // namespace Xyce