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.14 $
40 //
41 // Revision Date : $Date: 2014/02/24 23:49:15 $
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  std::string msg="ReactionNetwork::setReactionNetworkFromFile: Cannot open reaction specification file: "+fileName;
228  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
229  }
230 
231  XyceDevice::ReactionParser theParser(theLexer, theSpeciesIDs, *this);
232 
233 
234  if (theParser.parse())
235  {
236 #ifdef Xyce_DEBUG_DEVICE
237  Xyce::dout() << *this << std::endl;
238 #endif
239  std::string msg="ReactionNetwork::setReactionNetworkFromFile: Parsing reaction spec failed.";
240  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
241  }
242 
243  // we're done with this:
244  delete theLexer;
245  }
246 #endif
247 
248 }
249 
250 //-----------------------------------------------------------------------------
251 // Function : ReactionNetwork::setSpecies
252 // Purpose : register a list of species names used in reactions.
253 //
254 // Special Notes : Once registered this way, it is assumed that all vectors
255 // of species concentrations are ordered in the same way as
256 // the provided vector of species names.
257 //
258 // Scope : public
259 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
260 // Creation Date : 03/20/06
261 //-----------------------------------------------------------------------------
262 void ReactionNetwork::setSpecies(std::vector<Specie> &theSpeciesVect)
263 {
264 
265  int i;
266  int nspec=theSpeciesVect.size();
267 
268  speciesMap.clear();
269  species=theSpeciesVect;
270 
271  for (i=0;i<nspec;++i)
272  {
273  speciesMap[theSpeciesVect[i].getName()]=i;
274  }
275 
276 }
277 
278 //-----------------------------------------------------------------------------
279 // Function : ReactionNetwork::setConstants
280 // Purpose : register a list of constant species names used in reactions.
281 //
282 // Special Notes : Once registered this way, it is assumed that all
283 // vectors of constant species concentrations are ordered in
284 // the same way as the provided vector of species names.
285 //
286 // Constant species are those whose concentrations remain
287 // unaltered by the reaction network, e.g. those that are
288 // fed into the system at fixed rate as in a CSTR.
289 //
290 // Scope : public
291 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
292 // Creation Date : 03/20/06
293 //-----------------------------------------------------------------------------
294 void ReactionNetwork::setConstants(std::vector<Specie> &theConstantsVect)
295 {
296 
297  int i;
298  int nspec=theConstantsVect.size();
299 
300  constantsMap.clear();
301  constants = theConstantsVect;
302 
303  for (i=0;i<nspec;++i)
304  {
305  constantsMap[theConstantsVect[i].getName()]=i;
306  }
307 }
308 
309 
310 //-----------------------------------------------------------------------------
311 // Function : ReactionNetwork::addSpecie
312 // Purpose : add one to the list of species names used in reactions.
313 //
314 // Scope : public
315 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
316 // Creation Date : 03/20/06
317 //-----------------------------------------------------------------------------
318 void ReactionNetwork::addSpecie(const Specie &aSpecie)
319 {
320 
321  int i=species.size(); // get index of next one we add
322  species.push_back(aSpecie);
323  speciesMap[aSpecie.getName()]=i;
324 
325 }
326 
327 //-----------------------------------------------------------------------------
328 // Function : ReactionNetwork::addConstant
329 // Purpose : add one to the list of constant names used in reactions.
330 //
331 // Scope : public
332 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
333 // Creation Date : 03/20/06
334 //-----------------------------------------------------------------------------
335 void ReactionNetwork::addConstant(const Specie &aConstant)
336 {
337 
338  int i=constants.size(); // get index of next one we add
339  constants.push_back(aConstant);
340  constantsMap[aConstant.getName()]=i;
341 
342 }
343 
344 //-----------------------------------------------------------------------------
345 // Function : ReactionNetwork::addReaction
346 // Purpose : Create a new named reaction in the network
347 // Special Notes :
348 // Scope : public
349 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
350 // Creation Date : 03/20/06
351 //-----------------------------------------------------------------------------
352 void ReactionNetwork::addReaction(const std::string &name)
353 {
354  N_DEV_Reaction dummy;
355 
356  addReaction(name, dummy);
357 }
358 
359 //-----------------------------------------------------------------------------
360 // Function : ReactionNetwork::addReaction
361 // Purpose : Add a reaction object into the network and give it a name
362 // Special Notes :
363 // Scope : public
364 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
365 // Creation Date : 03/20/06
366 //-----------------------------------------------------------------------------
367 void ReactionNetwork::addReaction(const std::string &name, N_DEV_Reaction &reaction)
368 {
369  // first check if there is already a reaction of that name in the
370  // reactions map:
371 
372  if (reactionNamesMap.find(name) != reactionNamesMap.end())
373  {
374  std::ostringstream ost;
375  ost << " Attempt to add reaction duplicate name " << name << std::endl;
376  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
377  }
378 
379  //try to cut down on calls to copy constructor
380  if (theReactions.capacity()<=theReactions.size())
381  {
382  theReactions.reserve(theReactions.size()+10);
383  }
384  theReactions.push_back(reaction);
385  reactionNames.push_back(name);
386  reactionNamesMap[name]=theReactions.size()-1;
387 
388  // Now check if the reaction has "_ELECTRON_CAPTURE",
389  // "_ELECTRON_EMISSION", "_HOLE_CAPTURE" or "_HOLE_EMISSION" in it.
390  // If so, keep track of it in a separate vector for such things.
391  // we do this so we can later get at them quickly without doing name
392  // searches.
393  if (name.find("_ELECTRON_CAPTURE",0) != std::string::npos)
394  {
395  electronCaptureReactions.push_back(theReactions.size()-1);
396  }
397  else if (name.find("_HOLE_CAPTURE",0) != std::string::npos)
398  {
399  holeCaptureReactions.push_back(theReactions.size()-1);
400  }
401  else if (name.find("_ELECTRON_EMISSION",0) != std::string::npos)
402  {
403  electronEmissionReactions.push_back(theReactions.size()-1);
404  }
405  else if (name.find("_HOLE_EMISSION",0) != std::string::npos)
406  {
407  holeEmissionReactions.push_back(theReactions.size()-1);
408  }
409 }
410 
411 //-----------------------------------------------------------------------------
412 // Function : ReactionNetwork::addReactant
413 // Purpose : add a species/stoichiometric coefficient pair to the
414 // reactant list of a specified named reaction
415 // The species is specified using its name, and can be either
416 // one of those in the list provided by setSpecies or
417 // setConstants.
418 // Special Notes :
419 // Scope : public
420 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
421 // Creation Date : 03/20/06
422 //-----------------------------------------------------------------------------
423 void ReactionNetwork::addReactant(const std::string &name, const std::string &reactant, double stoich)
424 {
425 
426  std::map<std::string,int>::iterator n_i;
427  // check that name exists in map
428  int reactionNum;
429  reactionNum=getReactionNum(name);
430  if (reactionNum == -1)
431  {
432  std::ostringstream ost;
433  ost << " Attempt to add reactant " << reactant
434  << " to non-existant reaction " << name << std::endl;
435  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
436  }
437  else
438  {
439  int speciesNum;
440  // now check if we know this reactant
441 
442  n_i = speciesMap.find(reactant);
443  if (n_i == speciesMap.end())
444  {
445  // not a solution species --- is it a constant?
446  n_i = constantsMap.find(reactant);
447  if (n_i == constantsMap.end())
448  { // nope
449  std::ostringstream ost;
450  ost << "attempt to add unknown reactant " << reactant
451  << " to reaction number " << reactionNum
452  << "("<<name<<")"<<std::endl;
453  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
454  }
455  else
456  {
457  speciesNum = -(n_i->second+1);
458  }
459  }
460  else
461  {
462  speciesNum = n_i->second;
463  }
464 
465 
466  getReaction(reactionNum).addReactant(speciesNum,stoich);
467  }
468 }
469 
470 //-----------------------------------------------------------------------------
471 // Function : ReactionNetwork::addProduct
472 // Purpose : add a species/stoichiometric coefficient pair to the
473 // product list of a specified named reaction
474 // The species is specified using its name, and must be
475 // one of those in the list provided by setSpecies
476 // (must not be one from the Constants list).
477 // Special Notes :
478 // Scope : public
479 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
480 // Creation Date : 03/20/06
481 //-----------------------------------------------------------------------------
482 void ReactionNetwork::addProduct(const std::string &name, const std::string &product, double stoich)
483 {
484 
485  std::map<std::string,int>::iterator n_i;
486 
487  // check that reaction name exists in map
488  // check that name exists in map
489  int reactionNum;
490  reactionNum=getReactionNum(name);
491  if (reactionNum == -1)
492  {
493  std::ostringstream ost;
494  ost << " Attempt to add product " << product
495  << " to non-existant reaction " << name << std::endl;
496  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
497  }
498  else
499  {
500  int speciesNum;
501  // now check if we know this product
502 
503  n_i = speciesMap.find(product);
504  if (n_i == speciesMap.end())
505  {
506  // not a solution species --- is it a constant?
507  n_i = constantsMap.find(product);
508  if (n_i == constantsMap.end())
509  { // nope
510  std::ostringstream ost;
511  ost << "attempt to add unknown product " << product
512  << " to reaction number " << reactionNum
513  << "("<<name<<")"<<std::endl;
514  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
515  }
516  else
517  {
518  std::ostringstream ost;
519 
520 #ifdef Xyce_RXN_WARNINGS
521  Report::UserWarning() << " Specified constant species " << product
522  << " as product of reaction number " << reactionNum
523  << "(" << name << ")"<<std::endl
524  << " IGNORING that product";
525 #endif
526  }
527  }
528  else
529  {
530  speciesNum = n_i->second;
531  getReaction(reactionNum).addProduct(speciesNum,stoich);
532  }
533 
534 
535  }
536 }
537 
538 
539 //-----------------------------------------------------------------------------
540 // Function : ReactionNetwork::setRateConstant
541 // Purpose : set the rate constant for the named reaction
542 // Special Notes :
543 // Scope : public
544 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
545 // Creation Date : 03/20/06
546 //-----------------------------------------------------------------------------
547 void ReactionNetwork::setRateConstant(const std::string &name, double k)
548 {
549  int reactionNum;
550  // check that reaction name exists in map
551  reactionNum=getReactionNum(name);
552  if (reactionNum == -1)
553  {
554  std::ostringstream ost;
555  ost << " Attempt to set rate constant of non-existant reaction "
556  << name << std::endl;
557  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
558  }
559  else
560  {
561  getReaction(reactionNum).setRateConstant(k);
562  }
563 }
564 
565 //-----------------------------------------------------------------------------
566 // Function : ReactionNetwork::scaleRateConstant
567 // Purpose : set the rate constant for the named reaction
568 // Special Notes :
569 // Scope : public
570 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
571 // Creation Date : 06/01/06
572 //-----------------------------------------------------------------------------
573 void ReactionNetwork::scaleRateConstant(const std::string &name, double kscale)
574 {
575 
576  int reactionNum;
577  // check that reaction name exists in map
578  reactionNum = getReactionNum(name);
579  if (reactionNum == -1)
580  {
581  std::ostringstream ost;
582  ost << " Attempt to scale rate constant of non-existant reaction "
583  << name << std::endl;
584  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
585  }
586  else
587  {
588  getReaction(reactionNum).scaleRateConstant(kscale);
589  }
590 }
591 
592 //-----------------------------------------------------------------------------
593 // Function : ReactionNetwork::setRateConstantFromCalculator
594 // Purpose : set the rate constant for the named reaction according
595 // to its saved method
596 // Special Notes :
597 // Scope : public
598 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
599 // Creation Date : 08/01/06
600 //-----------------------------------------------------------------------------
601 void ReactionNetwork::setRateConstantFromCalculator (const std::string &name, double T)
602 {
603 
604  int reactionNum;
605  // check that reaction name exists in map
606  reactionNum = getReactionNum(name);
607  if (reactionNum == -1)
608  {
609  std::ostringstream ost;
610  ost << " Attempt to scale rate constant of non-existant reaction "
611  << name << std::endl;
612  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
613  }
614  else
615  {
617  }
618 }
619 
620 //-----------------------------------------------------------------------------
621 // Function : ReactionNetwork::scaleRateConstantFromCalculator
622 // Purpose : scale the rate constant for the named reaction according
623 // to its saved method
624 // Special Notes :
625 // Scope : public
626 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
627 // Creation Date : 08/01/06
628 //-----------------------------------------------------------------------------
630 {
631 
632  int reactionNum;
633  // check that reaction name exists in map
634  reactionNum = getReactionNum(name);
635  if (reactionNum == -1)
636  {
637  std::ostringstream ost;
638  ost << " Attempt to scale rate constant of non-existant reaction "
639  << name << std::endl;
640  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
641  }
642  else
643  {
645  }
646 }
647 
648 //-----------------------------------------------------------------------------
649 // Function : ReactionNetwork::unscaleRateConstantFromCalculator
650 // Purpose : unscale the rate constant for the named reaction according
651 // to its saved method
652 // Special Notes :
653 // Scope : public
654 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
655 // Creation Date : 08/01/06
656 //-----------------------------------------------------------------------------
658 {
659 
660  int reactionNum;
661  // check that reaction name exists in map
662  reactionNum = getReactionNum(name);
663  if (reactionNum == -1)
664  {
665  std::ostringstream ost;
666  ost << " Attempt to scale rate constant of non-existant reaction "
667  << name << std::endl;
668  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, ost.str());
669  }
670  else
671  {
673  }
674 }
675 
676 //-----------------------------------------------------------------------------
677 // Function : ReactionNetwork::setRateConstantsFromCalc
678 // Purpose : set the rate constant for the all reaction according
679 // to their saved methods
680 // Special Notes :
681 // Scope : public
682 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
683 // Creation Date : 08/02/06
684 //-----------------------------------------------------------------------------
686 {
687  int numReacts=theReactions.size();
688  int i;
689  for (i=0; i<numReacts; ++i)
690  {
691  theReactions[i].setRateConstantFromCalculator(T);
692  }
693 }
694 
695 //-----------------------------------------------------------------------------
696 // Function : ReactionNetwork::scaleRateConstantsFromCalc
697 // Purpose : scale the rate constant for the all reaction according
698 // to their saved methods
699 // Special Notes :
700 // Scope : public
701 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
702 // Creation Date : 08/02/06
703 //-----------------------------------------------------------------------------
705 {
706  int numReacts=theReactions.size();
707  int i;
708  for (i=0; i<numReacts; ++i)
709  {
710  theReactions[i].scaleRateConstantFromCalculator();
711  }
712 }
713 
714 //-----------------------------------------------------------------------------
715 // Function : ReactionNetwork::unscaleRateConstantsFromCalc
716 // Purpose : unscale the rate constant for the all reaction according
717 // to their saved methods
718 // Special Notes :
719 // Scope : public
720 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
721 // Creation Date : 08/02/06
722 //-----------------------------------------------------------------------------
724 {
725  int numReacts=theReactions.size();
726  int i;
727  for (i=0; i<numReacts; ++i)
728  {
729  theReactions[i].unscaleRateConstantFromCalculator();
730  }
731 }
732 
733 //-----------------------------------------------------------------------------
734 // Function : ReactionNetwork::setScaleParams
735 // Purpose : set the scale parameters and pass them down to any existing
736 // reactions. Done this way, we make sure that all reactions
737 // in the network are reset to the same set of scale
738 // parameters.
739 // Special Notes : If called before reactions defined, it's OK, because as
740 // each reaction's rate calculator is created, the stored
741 // C0, t0, and x0 are passed to it. This function does the
742 // calls down to existing reactions just in case they were
743 // previously defined.
744 // Scope : public
745 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
746 // Creation Date : 08/24/06
747 //-----------------------------------------------------------------------------
748 void ReactionNetwork::setScaleParams(double c,double t, double x)
749 {
750  std::vector<N_DEV_Reaction>::iterator reactionIter=theReactions.begin();
751  std::vector<N_DEV_Reaction>::iterator reactionIterEnd=theReactions.end();
752  C0=c;
753  t0=t;
754  x0=x;
755 
756  for (; reactionIter != reactionIterEnd; ++reactionIter)
757  {
758  reactionIter->setScaleFactors(C0,t0,x0);
759  }
760 }
761 
762 //-----------------------------------------------------------------------------
763 // Function : ReactionNetwork::addSourceTerm
764 // Purpose : add an expression for a source term
765 // Special Notes :
766 // Scope : public
767 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
768 // Creation Date : 08/04/06
769 //-----------------------------------------------------------------------------
770 void ReactionNetwork::addSourceTerm(const std::string &speciesName, const std::string &expressionStr)
771 {
772  if (applySources)
773  {
774  int speciesNum=getSpeciesNum(speciesName);
775  if (speciesNum >= 0) // the species exists
776  {
777  Util::Expression *foo= new Util::Expression(expressionStr);
778  theSourceTerms.push_back( std::pair<int,Util::Expression *>(speciesNum, foo));
779  }
780  }
781 }
782 
783 //-----------------------------------------------------------------------------
784 // Function : ReactionNetwork::addSourceTerm
785 // Purpose : add an expression for a source term given
786 // already-constructed expression object.
787 // Special Notes :
788 // Scope : public
789 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
790 // Creation Date : 08/04/06
791 //-----------------------------------------------------------------------------
792 void ReactionNetwork::addSourceTerm(const std::string &speciesName, Util::Expression *expression)
793 {
794  int speciesNum=getSpeciesNum(speciesName);
795  Util::Expression * ExpressionCopy=new Util::Expression(*expression);
796 
797  if (speciesNum >= 0) // the species exists
798  {
799  theSourceTerms.push_back(
800  std::pair<int,Util::Expression *>(speciesNum,ExpressionCopy));
801  }
802 }
803 
804 //-----------------------------------------------------------------------------
805 // Function : ReactionNetwork::addMasterSourceTerm
806 // Purpose : add an expression for a source term that depends on a
807 // "master" source value.
808 // Special Notes :
809 // Scope : public
810 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
811 // Creation Date : 08/04/06
812 //-----------------------------------------------------------------------------
813 void ReactionNetwork::addMasterSourceTerm(const std::string &speciesName)
814 {
815  int speciesNum=getSpeciesNum(speciesName);
816 
817  if (speciesNum >= 0) // the species exists
818  {
819  masterSourceSpecies.push_back(speciesNum);
820  }
821 }
822 
823 //-----------------------------------------------------------------------------
824 // Function : ReactionNetwork::setSimTime
825 // Purpose : set internal "time" variable for all source terms
826 // Special Notes :
827 // Scope : public
828 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
829 // Creation Date : 08/04/06
830 //-----------------------------------------------------------------------------
832 {
833  std::vector< std::pair<int,Util::Expression *> >::iterator iterSource=
834  theSourceTerms.begin();
835  std::vector< std::pair<int,Util::Expression *> >::iterator source_end=
836  theSourceTerms.end();
837 
838  for (;iterSource != source_end; ++iterSource)
839  {
840  (iterSource->second)->set_sim_time(time);
841  }
842 }
843 
844 //-----------------------------------------------------------------------------
845 // Function : ReactionNetwork::getBreakpointTime
846 // Purpose : return the next time at which any source will have a
847 // breakpoint
848 // Special Notes :
849 // Scope : public
850 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
851 // Creation Date : 03/20/06
852 //-----------------------------------------------------------------------------
854 {
855  double breaktime=0, btime;
856  std::vector< std::pair<int,Util::Expression *> >::iterator iterSource=
857  theSourceTerms.begin();
858  std::vector< std::pair<int,Util::Expression *> >::iterator source_end=
859  theSourceTerms.end();
860 
861  for (;iterSource != source_end; ++iterSource)
862  {
863  btime=(iterSource->second)->get_break_time();
864  // pick smallest break time of all sources.
865  if (breaktime>0)
866  {
867  if (btime<breaktime)
868  {
869  breaktime=btime;
870  }
871  }
872  else
873  {
874  breaktime=btime;
875  }
876  }
877 
878  return (breaktime);
879 }
880 
881 //-----------------------------------------------------------------------------
882 // Function : ReactionNetwork::getDdt
883 // Purpose : compute the time derivative of all species concentrations
884 // Special Notes :
885 // Scope : public
886 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
887 // Creation Date : 03/20/06
888 //-----------------------------------------------------------------------------
889 void ReactionNetwork::getDdt(std::vector<double> &concs,std::vector<double> &constant_vec,
890  std::vector<double> &ddt)
891 {
892  int rSize=theReactions.size();
893  int i;
894  for (i=0;i<rSize;++i)
895  {
896  theReactions[i].getDdt(concs,constant_vec,ddt);
897  }
898 
899  // add in the source terms
900  std::vector< std::pair<int,Util::Expression *> >::iterator iterSource=
901  theSourceTerms.begin();
902  std::vector< std::pair<int,Util::Expression *> >::iterator source_end=
903  theSourceTerms.end();
904 
905  for (;iterSource != source_end; ++iterSource)
906  {
907  double return_val;
908  (iterSource->second)->evaluateFunction(return_val); // ignore return val? That's
909  // what's done everywhere else
910  ddt[(iterSource->first)] += sourceScaleFac*return_val;
911  }
912 
913  // Add in the master source terms:
914  std::vector<int>::iterator iterMasterSource=masterSourceSpecies.begin();
915  std::vector<int>::iterator masterSource_end=masterSourceSpecies.end();
916  for (; iterMasterSource!= masterSource_end; ++iterMasterSource)
917  {
918  ddt[*iterMasterSource] += masterSourceValue*sourceScaleFac;
919  }
920 
921 }
922 
923 //-----------------------------------------------------------------------------
924 // Function : ReactionNetwork::getJac
925 // Purpose : compute the jacobian of the reaction network, the
926 // derivatives of the time derivatives with respect to species
927 // concentration.
928 // Special Notes :
929 // Scope : public
930 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
931 // Creation Date : 03/20/06
932 //-----------------------------------------------------------------------------
933 void ReactionNetwork::getJac(std::vector<double> &concs, std::vector<double> &constant_vec,
934  std::vector<std::vector<double> >&jac)
935 {
936  int rSize=theReactions.size();
937  int i;
938  for (i=0;i<rSize;++i)
939  {
940  theReactions[i].getJac(concs,constant_vec,jac);
941  }
942 }
943 
944 //-----------------------------------------------------------------------------
945 // Function : ReactionNetwork::getDFdConst
946 // Purpose : compute the derivatives of the RHS with respect to
947 // a specified constant concentration.
948 // Special Notes :
949 // Scope : public
950 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
951 // Creation Date : 10/17/06
952 //-----------------------------------------------------------------------------
953 void ReactionNetwork::getDFdConst( const std::string & constantName,
954  std::vector<double> &concs,
955  std::vector<double> &constant_vec,
956  std::vector<double> &dFdConst)
957 {
958  int rSize=theReactions.size();
959  int cSize=concs.size();
960  int i;
961  int constNum=getConstantNum(constantName);
962 
963  dFdConst.resize(cSize);
964  for (i=0;i<cSize;++i)
965  dFdConst[i]=0.0;
966 
967  for (i=0;i<rSize;++i)
968  {
969  theReactions[i].getDFdConst(constNum,concs,constant_vec,dFdConst);
970  }
971 }
972 
973 
974 //-----------------------------------------------------------------------------
975 // Function : ReactionNetwork::getRate
976 // Purpose : Compute the total rate at which species are "consumed" or
977 // "produced" by all the capture and emission reactions,
978 // if there are any. This can be used even if the species
979 // concentration is held fixed (it'll just be the sum of all
980 // reaction rates involving electrons).
981 // Special Notes : Assumes that all emission and capture reactions are
982 // of the form B=>A+E or A+E=>B and will be incorrect if
983 // the number of any reaction not of this form is listed in
984 // the capture or emission vectors.
985 //
986 // Generic version in which the list of capture and emission
987 // reactions are passed in
988 //
989 // Scope : public
990 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
991 // Creation Date : 09/13/06
992 //-----------------------------------------------------------------------------
993 double ReactionNetwork::getRate(std::vector<double> &concs,
994  std::vector<double> &constant_vec,
995  std::vector<int> &captureVect,
996  std::vector<int> &emissionVect)
997 {
998  int i;
999  double rate=0;
1000 
1001  for (i=0;i<captureVect.size();++i)
1002  {
1003  rate -= theReactions[captureVect[i]].getRate(concs, constant_vec);
1004  }
1005 
1006  for (i=0;i<emissionVect.size();++i)
1007  {
1008  rate += theReactions[emissionVect[i]].getRate(concs,constant_vec);
1009  }
1010 
1011  return rate;
1012 }
1013 
1014 //-----------------------------------------------------------------------------
1015 // Function : ReactionNetwork::getCaptureLifetime
1016 // Purpose : Given a list of capture reaction numbers and the
1017 // species number of the concentration consumed by those
1018 // reactions, return the lifetime.
1019 // Special Notes : Returns -1 if lifetime would be infinite (zero capture rate)
1020 // This is a kludge, but one that is easily tested by anyone
1021 // who uses this.
1022 //
1023 // Scope : public
1024 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1025 // Creation Date : 09/20/06
1026 //-----------------------------------------------------------------------------
1027 double ReactionNetwork::getCaptureLifetime(std::vector<double> &concs,
1028  std::vector<double> &constant_vec,
1029  std::vector<int> &captureVect,
1030  double & concentration)
1031 {
1032  int i;
1033  double rate=0;
1034 
1035  for (i=0;i<captureVect.size();++i)
1036  {
1037  rate += theReactions[captureVect[i]].getRate(concs, constant_vec);
1038  }
1039 
1040  // inverse of lifetime = rate/concentration, so...
1041  if (rate > 0) // don't try to compute infinite lifetime!
1042  return concentration/rate;
1043  else
1044  return (-1.0); // bollocks, but let's not quibble. This is just as
1045  // invalid a lifetime as infinity would be!
1046 
1047 }
1048 
1049 //-----------------------------------------------------------------------------
1050 // Function : ReactionNetwork::getCaptureLifetimes
1051 // Purpose : Given a list of capture reaction numbers and the
1052 // species number of the concentration consumed by those
1053 // reactions, return a vector of lifetimes due to each
1054 // reaction.
1055 // Special Notes : Returns -1 if lifetime would be infinite (zero capture rate)
1056 // This is a kludge, but one that is easily tested by anyone
1057 // who uses this.
1058 //
1059 // Scope : public
1060 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1061 // Creation Date : 09/20/06
1062 //-----------------------------------------------------------------------------
1063 void ReactionNetwork::getCaptureLifetimes(std::vector<double> &concs,
1064  std::vector<double> &constant_vec,
1065  std::vector<int> &captureVect,
1066  double & concentration,
1067  std::vector<double> &lifetimes)
1068 {
1069  int i;
1070  lifetimes.resize(captureVect.size());
1071 
1072  for (i=0;i<captureVect.size();++i)
1073  {
1074  lifetimes[i] = theReactions[captureVect[i]].getRate(concs, constant_vec);
1075  // inverse of lifetime = rate/concentration, so...
1076  if (lifetimes[i] > 0) // don't try to compute infinite lifetime!
1077  lifetimes[i] = concentration/lifetimes[i];
1078  else
1079  lifetimes[i]=-1.0; // bollocks, but let's not quibble. This is just as
1080  // invalid a lifetime as infinity would be!
1081  }
1082 
1083 }
1084 
1085 //-----------------------------------------------------------------------------
1086 // Function : ReactionNetwork::getDRateDC
1087 // Purpose : Compute the vector of derivatives of the Rate (as returned
1088 // by getRate) with respect to concentrations
1089 //
1090 // Special Notes : Assumes that all emission and capture reactions are
1091 // of the form B=>A+E or A+E=>B and will be incorrect if
1092 // the number of any reaction not of this form is listed in
1093 // the capture or emission vectors.
1094 //
1095 // Generic version in which the list of capture and emission
1096 // reactions are passed in
1097 //
1098 // Note that dRatedC is zeroed, so if you need to sum
1099 // terms from multiple species, you need to pass a temporary
1100 // to this routine and sum terms in to a different vector.
1101 //
1102 // Scope : public
1103 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1104 // Creation Date : 09/13/06
1105 //-----------------------------------------------------------------------------
1106 void ReactionNetwork::getDRateDC(std::vector<double> &concs,
1107  std::vector<double> &constant_vec,
1108  std::vector<int> &captureVect,
1109  std::vector<int> &emissionVect,
1110  std::vector<double> &dRatedC)
1111 {
1112  int i,j;
1113  int cSize=dRatedC.size();
1114  std::vector<double> tempdRdC(cSize);
1115 
1116  for (i=0;i<cSize;++i)
1117  {
1118  dRatedC[i]=0;
1119  }
1120 
1121  for (i=0;i<captureVect.size();++i)
1122  {
1123  tempdRdC.assign(cSize,0.0);
1124  theReactions[captureVect[i]].getDRateDC(concs, constant_vec, tempdRdC);
1125 
1126  for (j=0;j<cSize;++j)
1127  {
1128  dRatedC[j] -= tempdRdC[j];
1129 #ifdef Xyce_DEBUG_DEVICE
1130  //cout << "ReactionNetwork::getDRateDC: Reaction: "<<captureVect[i]<<" tempdRdC["<<j<<"] = " << tempdRdC[j]<<std::endl;
1131 #endif
1132  }
1133  }
1134 
1135  for (i=0;i<emissionVect.size();++i)
1136  {
1137  tempdRdC.assign(cSize,0.0);
1138  theReactions[emissionVect[i]].getDRateDC(concs, constant_vec, tempdRdC);
1139 
1140  for (j=0;j<cSize;++j)
1141  {
1142  dRatedC[j] += tempdRdC[j];
1143 #ifdef Xyce_DEBUG_DEVICE
1144  //cout << "ReactionNetwork::getDRateDC: Reaction: "<<emissionVect[i]<<" tempdRdC["<<j<<"] = " << tempdRdC[j]<<std::endl;
1145 #endif
1146  }
1147  }
1148 }
1149 
1150 
1151 //-----------------------------------------------------------------------------
1152 // Function : ReactionNetwork::getDRateDConst
1153 //
1154 // Purpose : Compute the vector of derivatives of the Rate (as returned
1155 // by getRate) with respect to constants, like E and H.
1156 //
1157 // Special Notes : Assumes that all emission and capture reactions are
1158 // of the form B=>A+E or A+E=>B and will be incorrect if
1159 // the number of any reaction not of this form is listed in
1160 // the capture or emission vectors.
1161 //
1162 // Generic version in which the list of capture and emission
1163 // reactions are passed in
1164 //
1165 // Note that dRatedConst is zeroed, so if you need to sum
1166 // terms from multiple species, you need to pass a temporary
1167 // to this routine and sum terms in to a different vector.
1168 //
1169 // Scope : public
1170 // Creator : Eric Keiter
1171 // Creation Date : 11/15/08
1172 //-----------------------------------------------------------------------------
1173 void ReactionNetwork::getDRateDConst(std::vector<double> &concs,
1174  std::vector<double> &constant_vec,
1175  std::vector<int> &captureVect,
1176  std::vector<int> &emissionVect,
1177  std::vector<double> &dRatedConst)
1178 {
1179  int i,j;
1180  int cSize=dRatedConst.size();
1181  std::vector<double> tempdRdConst(cSize);
1182 
1183  for (i=0;i<cSize;++i)
1184  {
1185  dRatedConst[i]=0;
1186  }
1187 
1188  for (i=0;i<captureVect.size();++i)
1189  {
1190  tempdRdConst.assign(cSize,0.0);
1191 
1192  for (j=0;j<cSize;++j)
1193  {
1194  theReactions[captureVect[i]].getDRateDConst(j, concs, constant_vec, tempdRdConst[j]);
1195  dRatedConst[j] -= tempdRdConst[j];
1196 #ifdef Xyce_DEBUG_DEVICE
1197  //cout << "ReactionNetwork::getDRateDConst: Reaction: "<<captureVect[i]<<" tempdRdConst["<<j<<"] = " << tempdRdConst[j]<<std::endl;
1198 #endif
1199  }
1200  }
1201 #ifdef Xyce_DEBUG_DEVICE
1202  //cout << "After capture reactions:"<<std::endl;
1203  //for (j=0;j<cSize;++j)
1204  //{
1205  //cout << "ReactionNetwork::getDRateDConst: dRatedConst["<<j<<"] =" << dRatedConst[j] << std::endl;
1206  //}
1207 #endif
1208 
1209  for (i=0;i<emissionVect.size();++i)
1210  {
1211  tempdRdConst.assign(cSize,0.0);
1212 
1213  for (j=0;j<cSize;++j)
1214  {
1215  theReactions[emissionVect[i]].getDRateDConst(j, concs, constant_vec, tempdRdConst[j]);
1216  dRatedConst[j] += tempdRdConst[j];
1217 #ifdef Xyce_DEBUG_DEVICE
1218  //cout << "ReactionNetwork::getDRateDConst: Reaction: "<<emissionVect[i]<<" tempdRdConst["<<j<<"] = " << tempdRdConst[j]<<std::endl;
1219 #endif
1220  }
1221  }
1222 #ifdef Xyce_DEBUG_DEVICE
1223  //cout << "After emission reactions:"<<std::endl;
1224  //for (j=0;j<cSize;++j)
1225  //{
1226  //cout << "ReactionNetwork::getDRateDConst: dRatedConst["<<j<<"] =" << dRatedConst[j] << std::endl;
1227  //}
1228 #endif
1229 
1230 }
1231 
1232 } // namespace Device
1233 } // namespace Xyce