Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_Reaction.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_Reaction.C,v $
27 //
28 // Purpose : Provide a generic class for reactions using simple
29 // law-of-mass-action kinetics, i.e.:
30 // A+2B+C -> D + 3E + F
31 // implies that the reaction happens at a rate:
32 // reactionRate = k*[A][B]^2[C]
33 // where [X] means "concentration of species X"
34 //
35 //
36 // Special Notes :
37 //
38 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
39 //
40 // Creation Date : 03/20/06
41 //
42 // Revision Information:
43 // ---------------------
44 //
45 // Revision Number: $Revision: 1.10 $
46 //
47 // Revision Date : $Date: 2014/02/24 23:49:15 $
48 //
49 // Current Owner : $Author: tvrusso $
50 //-----------------------------------------------------------------------------
51 
52 #include <Xyce_config.h>
53 
54 
55 
56 // Standard includes
57 #include <N_UTL_Misc.h>
58 #include <N_UTL_fwd.h>
59 
60 #include <vector>
61 #include <cmath>
62 
63 #ifdef Xyce_DEBUG_DEVICE
64 #include <iostream>
65 
66 #endif
67 
68 // Xyce includes
69 #include <N_DEV_Reaction.h>
70 #include <N_ERH_ErrorMgr.h>
71 
72 namespace Xyce {
73 namespace Device {
74 
75 //-----------------------------------------------------------------------------
76 // Function : Reaction::Reaction
77 // Purpose : Default constructor
78 // Special Notes :
79 // Scope : public
80 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
81 // Creation Date : 3/20/06
82 //-----------------------------------------------------------------------------
84  : numconcs(0),
85  numconsts(0),
86  theRateConstant(0.0),
87  myRateCalc(0)
88 {
89  theReactants.resize(0);
90  theProducts.resize(0);
91  concDependency.resize(0);
92  constDependency.resize(0);
93 }
94 
95 //-----------------------------------------------------------------------------
96 // Function : Reaction::Reaction
97 // Purpose : constructor
98 // Special Notes : Used when vector of reactants, products, and rate constant
99 // are available at time of construction
100 // Scope : public
101 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
102 // Creation Date : 3/20/06
103 //-----------------------------------------------------------------------------
104 Reaction::Reaction(std::vector< std::pair<int,double> > & reactants,
105  std::vector< std::pair<int,double> > & products,
106  double rateConstant)
107  :
108  theReactants(reactants),
109  theProducts(products),
110  theRateConstant(rateConstant),
111  numconcs(0),
112  numconsts(0),
113  myRateCalc(0)
114 {
115  concDependency.resize(0);
116  constDependency.resize(0);
117 }
118 
119 //-----------------------------------------------------------------------------
120 // Function : Reaction::Reaction
121 // Purpose : copy constructor
122 // Special Notes : Needed because we keep STL vectors of these objects, and
123 // we keep a pointer to the rate constant calculator. Kills
124 // us during all the push_backs without this copy constructor,
125 // as soon as the push starts moving existing objects around.
126 // Scope : public
127 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
128 // Creation Date : 3/20/06
129 //-----------------------------------------------------------------------------
131  :theReactants(right.theReactants),
132  theProducts(right.theProducts),
133  concDependency(right.concDependency),
134  constDependency(right.constDependency),
135  theRateConstant(right.theRateConstant),
136  numconcs(right.numconcs),
137  numconsts(right.numconsts)
138 {
139 
140  if (right.myRateCalc) // Never, ever copy the pointer to the rate calculator!
141  {
142  myRateCalc = right.myRateCalc->Clone();
143  }
144  else
145  {
146  myRateCalc=0;
147  }
148 }
149 
150 
151 //-----------------------------------------------------------------------------
152 // Function : Reaction::operator=
153 // Purpose : assignment operator
154 // Special Notes : Needed because we keep STL vectors of these objects, and
155 // we keep a pointer to the rate constant calculator. Kills
156 // us during all the push_backs without this copy constructor,
157 // as soon as the push starts moving existing objects around.
158 // Scope : public
159 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
160 // Creation Date : 3/20/06
161 //-----------------------------------------------------------------------------
162 Reaction &
164 {
165 
166  if (this == &right) return *this; // assignment to self
167 
168 #ifdef Xyce_DEBUG_DEVICE
169  Xyce::dout() << "We're doing an assignment of reaction! " << std::endl;
170 #endif
171 
172  // otherwise:
173  theReactants = right.theReactants;
174  theProducts = right.theProducts;
178  numconcs = right.numconcs;
179  numconsts = right.numconsts;
180 
181  if (right.myRateCalc) // Never, ever copy the pointer to the rate calculator!
182  {
183 
184  if (myRateCalc) delete myRateCalc; // we already have one, kill it
185 
186  myRateCalc=right.myRateCalc->Clone();
187  }
188  else
189  {
190  myRateCalc=0;
191  }
192 
193  return *this;
194 
195 }
196 
197 //-----------------------------------------------------------------------------
198 // Function : Reaction::Reaction
199 // Purpose : constructor
200 // Special Notes : Used when vector of reactants, products, and rate constant
201 // are available at time of construction
202 // Scope : public
203 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
204 // Creation Date : 3/20/06
205 //-----------------------------------------------------------------------------
207 {
208  if (myRateCalc)
209  {
210  delete myRateCalc;
211  myRateCalc=0;
212  }
213 }
214 
215 //-----------------------------------------------------------------------------
216 // Function : Reaction::setReactants
217 // Purpose : copy reactant/stoichiometric coefficients into object
218 // Special Notes :
219 // Scope : public
220 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
221 // Creation Date : 3/20/06
222 //-----------------------------------------------------------------------------
223 void Reaction::setReactants(std::vector< std::pair<int,double> > & reactants)
224 {
225  theReactants=reactants;
226 }
227 
228 //-----------------------------------------------------------------------------
229 // Function : Reaction::addReactant
230 // Purpose : add reactant/stoichiometric coefficients to reactants vector
231 // Special Notes :
232 // Scope : public
233 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
234 // Creation Date : 3/20/06
235 //-----------------------------------------------------------------------------
236 void Reaction::addReactant(int species,double stoich)
237 {
238  std::vector<std::pair<int,double> >::iterator iter;
239  std::vector<std::pair<int,double> >::iterator iter_end=theReactants.end();
240  bool foundSpecies=false;
241 
242  // Make sure we only have each that appears on the LHS of a reaction
243  // listed only once. If the user has specified one twice, combine them
244  // into a single term with an augmented stoichiometric coefficient.
245  for (iter=theReactants.begin(); iter != iter_end; iter++)
246  {
247  if (iter->first == species)
248  {
249  iter->second += stoich;
250  foundSpecies=true;
251  break;
252  }
253  }
254  // Only if we didn't find the species in our existing list should we
255  // add a new entry to the vector.
256  if (!foundSpecies)
257  theReactants.push_back(std::pair<int,double>(species,stoich));
258 }
259 
260 
261 //-----------------------------------------------------------------------------
262 // Function : Reaction::addProduct
263 // Purpose : add reactant/stoichiometric coefficients to vector
264 // Special Notes :
265 // Scope : public
266 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
267 // Creation Date : 3/20/06
268 //-----------------------------------------------------------------------------
269 void Reaction::addProduct(int species,double stoich)
270 {
271  std::vector<std::pair<int,double> >::iterator iter;
272  std::vector<std::pair<int,double> >::iterator iter_end=theProducts.end();
273  bool foundSpecies=false;
274 
275  // Make sure we only have each that appears on the RHS of a reaction
276  // listed only once. If the user has specified one twice, combine them
277  // into a single term with an augmented stoichiometric coefficient.
278  for (iter=theProducts.begin(); iter != iter_end; iter++)
279  {
280  if (iter->first == species)
281  {
282  iter->second += stoich;
283  foundSpecies=true;
284  break;
285  }
286  }
287  // Only if we didn't find the species in our existing list should we
288  // add a new entry to the vector.
289  if (!foundSpecies)
290  theProducts.push_back(std::pair<int,double>(species,stoich));
291 }
292 
293 //-----------------------------------------------------------------------------
294 // Function : Reaction::setProducts
295 // Purpose : copy product/stoichiometric coefficients into object
296 // Special Notes :
297 // Scope : public
298 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
299 // Creation Date : 3/20/06
300 //-----------------------------------------------------------------------------
301 void Reaction::setProducts(std::vector< std::pair<int,double> > & products)
302 {
303  theProducts=products;
304 }
305 
306 //-----------------------------------------------------------------------------
307 // Function : Reaction::getRate
308 // Purpose : compute and return the reaction rate. This is normally the
309 // first step of getDdt, but we might need this for
310 // other purposes (e.g. a kludge for getting electron/hole
311 // recombination/regeneration rates even when electrons and
312 // holes are constant species)
313 // Special Notes : It is tacitly assumed that the concentrations and
314 // constants in the provided vector are in an order
315 // consistent with the labeling in the reactants and
316 // products vectors. The contributions to the species
317 // time derivatives are summed into the provided output
318 // vector because it is assumed that there will be a network
319 // of reactions, not just one.
320 // Scope : public
321 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
322 // Creation Date : 3/20/06
323 //-----------------------------------------------------------------------------
324 double Reaction::getRate(std::vector<double> &concentrations,
325  std::vector<double> &constants)
326 {
327  int rSize=theReactants.size();
328  int pSize=theProducts.size();
329  double reactionRate;
330  int i;
331  int species;
332  double stoich;
333  double c;
334 
335  // Reaction rate determined by law of mass action
336  reactionRate=theRateConstant;
337  // product of concentrations of reactants raised to the power of
338  // stoichiometric coefficient
339  for (i=0;i<rSize;++i)
340  {
341  species=theReactants[i].first;
342  stoich=theReactants[i].second;
343  if (species>=0)
344  {
345  c=concentrations[species];
346  }
347  else
348  {
349  c=constants[-(species+1)];
350  }
351 
352  if (stoich != 1.0)
353  {
354  reactionRate *= pow(c,stoich);
355  }
356  else
357  {
358  reactionRate *= c;
359  }
360  }
361  return reactionRate;
362 }
363 
364 //-----------------------------------------------------------------------------
365 // Function : Reaction::getDRateDC
366 // Purpose : return a vector of the derivatives of this reaction's
367 // rate with respect to each species
368 // Special Notes :
369 //
370 // Scope : public
371 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
372 // Creation Date : 9/13/06
373 //-----------------------------------------------------------------------------
374 void Reaction::getDRateDC(std::vector<double> &concentrations,
375  std::vector<double> &constants,
376  std::vector<double> &dratedc)
377 {
378  int cSize=concentrations.size();
379  int rSize=theReactants.size();
380  int species;
381  double stoich,c;
382  int i,j;
383 
384  if (numconcs != cSize)
385  {
386  setDependency(cSize);
387  }
388 
389  // dratedc is the vector of derivatives of the reaction rate w.r.t.
390  // concentrations. Since the reaction rate is just a product of factors
391  // involving individual concentrations, we will just be multiplying in
392  // terms, so we initialize only those that are necessary to theRateConstant.
393  // Only those elements of dratedc that represent concentrations that the
394  // rate depends on will be initialized to non-zero.
395  for (i=0;i<cSize;++i)
396  {
397  if (concDependency[i]==1) // the rxn rate depends on this species
398  {
399  dratedc[i]=theRateConstant;
400  }
401  }
402 
403 
404  // The reaction rate is K*(product as i=0,rSize){[Xi]^{stoich[i]}}
405  // compute dR/dXj
406  for (i=0;i<rSize;++i) // loop over all species on left side of reaction
407  {
408  species=theReactants[i].first;
409  stoich=theReactants[i].second;
410  if (species>=0)
411  {
412  c=concentrations[species];
413  }
414  else
415  {
416  c=constants[-(species+1)];
417  }
418 
419 
420  // for each species in the network, if we depend on that species,
421  // update the product in the dR/dXj
422  if (stoich != 1.0)
423  {
424  for (j=0;j<cSize;++j)
425  {
426  if (concDependency[j] != 0)
427  {
428  if (j==species)
429  {
430  dratedc[j] *= stoich*pow(c,stoich-1.0);
431  }
432  else
433  {
434  dratedc[j] *= pow(c,stoich);
435  }
436  }
437  }
438  }
439  else
440  {
441  for (j=0;j<cSize;++j)
442  {
443  // when j==species we'd just multiply by 1.0
444  if (j!=species && concDependency[j] != 0)
445  {
446  dratedc[j] *= c;
447  }
448  }
449  }
450  }
451 }
452 
453 //-----------------------------------------------------------------------------
454 // Function : Reaction::getDRateDConst
455 // Purpose : return a vector of the derivatives of this reaction's
456 // rate with respect to each constant species
457 //
458 // Special Notes : Very much similar to getDRateDC, but computes
459 // derivative w.r.t. constants. Like getDRateDC, this
460 // will ultimately be used to compute jacobian elements,
461 // but unlike that routine, it will be used to pick out
462 // specific constants for special treatment, and unlike
463 // getDRateDC, it only computes the derivative with respect
464 // to a single constant, not all constants..
465 //
466 // Scope : public
467 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
468 // Creation Date : 10/17/06
469 //-----------------------------------------------------------------------------
470 void Reaction::getDRateDConst(int constNum,
471  std::vector<double> &concentrations,
472  std::vector<double> &constants,
473  double &dratedc)
474 {
475  int cSize=constants.size();
476  int rSize=theReactants.size();
477  int species;
478  double stoich,c;
479  int i,j;
480 
481  if (numconsts != cSize)
482  {
483  setConstDependency(cSize);
484  }
485 
486  if (constDependency[constNum]==0) // the rxn rate does not depend on this
487  //species
488  {
489  dratedc=0.0;
490  }
491  else
492  {
493  dratedc=theRateConstant;
494 
495  // The reaction rate is K*(product as i=0,rSize){[Xi]^{stoich[i]}}
496  // compute dR/dXj
497  for (i=0;i<rSize;++i) // loop over all species on left side of reaction
498  {
499  species=theReactants[i].first;
500  stoich=theReactants[i].second;
501  if (species>=0)
502  {
503  c=concentrations[species];
504  }
505  else
506  {
507  c=constants[-(species+1)];
508  }
509 
510 
511  // for each species in the network, if we depend on that species,
512  // update the product in the dR/dXj
513  if (stoich != 1.0)
514  {
515  if (species < 0 && constNum ==-(species+1)) // this specie is the one
516  // we're differntiating wrt
517  {
518  dratedc *= stoich*pow(c,stoich-1.0);
519  }
520  else
521  {
522  dratedc *= pow(c,stoich);
523  }
524  }
525  else
526  {
527  // when constNum is the specie under consideration we'd multiply by 1.0
528  if (constNum !=-(species+1))
529  {
530  dratedc *= c;
531  }
532  }
533  }
534  }
535 }
536 
537 //-----------------------------------------------------------------------------
538 // Function : Reaction::getDdt
539 // Purpose : sum time derivatives of species into provided vector
540 // Special Notes : It is tacitly assumed that the concentrations and
541 // constants in the provided vector are in an order
542 // consistent with the labeling in the reactants and
543 // products vectors. The contributions to the species
544 // time derivatives are summed into the provided output
545 // vector because it is assumed that there will be a network
546 // of reactions, not just one.
547 // Scope : public
548 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
549 // Creation Date : 3/20/06
550 //-----------------------------------------------------------------------------
551 void Reaction::getDdt(std::vector<double> &concentrations,
552  std::vector<double> &constants,
553  std::vector<double> &ddt)
554 {
555  int rSize=theReactants.size();
556  int pSize=theProducts.size();
557  double reactionRate;
558  int i;
559  int species;
560  double stoich;
561 
562  // Reaction rate determined by law of mass action
563  reactionRate=getRate(concentrations,constants);
564 
565  // Now update time derivatives:
566 
567  for (i=0;i<rSize;++i)
568  {
569  species=theReactants[i].first;
570  stoich=theReactants[i].second;
571  if (species>=0)
572  {
573  ddt[species] -= stoich*reactionRate;
574  }
575  }
576 
577  for (i=0;i<pSize;++i)
578  {
579  species=theProducts[i].first;
580  stoich=theProducts[i].second;
581  if (species>=0)
582  {
583  ddt[species] += stoich*reactionRate;
584  }
585  }
586 }
587 
588 //-----------------------------------------------------------------------------
589 // Function : Reaction::getJac
590 // Purpose : sum derivatives of time derivatives of species with
591 // respect to concentration into provided matrix
592 // Special Notes : It is tacitly assumed that the concentrations and
593 // constants in the provided vector are in an order
594 // consistent with the labeling in the reactants and
595 // products vectors. The contributions to the species
596 // second derivatives are summed into the provided output
597 // vector because it is assumed that there will be a network
598 // of reactions, not just one.
599 //
600 // An implicit assumption here is that the species numbering
601 // does not change through the run --- that is, once we
602 // call this routine with a vector of concentrations, it
603 // is assumed from that point forward that element i of the
604 // vector always refers to the same species in subsequent
605 // calls. If it is necessary to change that over time, the
606 // reaction network will probably have to be reconstructed
607 // and re-initialized.
608 //
609 // Scope : public
610 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
611 // Creation Date : 3/20/06
612 //-----------------------------------------------------------------------------
613 void Reaction::getJac(std::vector<double> &concentrations,
614  std::vector<double> &constants,
615  std::vector<std::vector<double> > &jac)
616 {
617  int cSize=concentrations.size();
618  int rSize=theReactants.size();
619  int pSize=theProducts.size();
620  int species;
621  double stoich,c;
622  std::vector<double> dratedc(cSize,0.0);
623  int i,j;
624 
625  // here is where the assumption of static species numbering is coded.
626  // Should it be necessary to change that assumption, here's where the work
627  // would be needed.
628  getDRateDC(concentrations, constants, dratedc);
629 
630  // we now know how the reaction rate depends on the various concentrations.
631  // Now we can assemble the jacobian, which is d^2[Xi]/(dt d[Xj])
632 
633  // species on the left of the reaction
634  for (i=0;i<rSize;++i)
635  {
636  species=theReactants[i].first;
637  stoich=theReactants[i].second;
638  if (species>=0)
639  {
640  for (j=0;j<cSize;++j)
641  {
642  if (concDependency[j]!=0)
643  {
644  jac[species][j] -= stoich*dratedc[j];
645  }
646  }
647  }
648  }
649  // species on the right
650  for (i=0;i<pSize;++i)
651  {
652  species=theProducts[i].first;
653  stoich=theProducts[i].second;
654  if (species>=0)
655  {
656  for (j=0;j<cSize;++j)
657  {
658  if (concDependency[j]!=0)
659  {
660  jac[species][j] += stoich*dratedc[j];
661  }
662  }
663  }
664  }
665 
666 }
667 
668 //-----------------------------------------------------------------------------
669 // Function : Reaction::getDFdConst
670 // Purpose : sum derivatives of time derivatives of species with
671 // respect to concentration into provided vector
672 // Special Notes : It is tacitly assumed that the concentrations and
673 // constants in the provided vector are in an order
674 // consistent with the labeling in the reactants and
675 // products vectors. The contributions to the species
676 // second derivatives are summed into the provided output
677 // vector because it is assumed that there will be a network
678 // of reactions, not just one.
679 //
680 // An implicit assumption here is that the species numbering
681 // does not change through the run --- that is, once we
682 // call this routine with a vector of concentrations, it
683 // is assumed from that point forward that element i of the
684 // vector always refers to the same species in subsequent
685 // calls. If it is necessary to change that over time, the
686 // reaction network will probably have to be reconstructed
687 // and re-initialized.
688 //
689 // This method sums into a vector containing the derivatives
690 // of variable species with respect to the specified constant
691 // specie. It'll be used as a fragment of a larger jacobian.
692 //
693 // Scope : public
694 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
695 // Creation Date : 3/20/06
696 //-----------------------------------------------------------------------------
697 void Reaction::getDFdConst(int constantNumber,
698  std::vector<double> &concentrations,
699  std::vector<double> &constants,
700  std::vector<double> &dFdConst)
701 {
702  int constSize=constants.size();
703  int rSize=theReactants.size();
704  int pSize=theProducts.size();
705  int species;
706  double stoich,c;
707  double dratedc;
708  int i;
709 
710  // here is where the assumption of static species numbering is coded.
711  // Should it be necessary to change that assumption, here's where the work
712  // would be needed.
713  getDRateDConst(constantNumber,concentrations, constants, dratedc);
714 
715  // no point going through these loops if this reaction doesn't depend
716  // on this constant!
717  if (constDependency[constantNumber] != 0)
718  {
719  // we now know how the reaction rate depends on the various constants
720  // we can assemble the derivatives we need.
721 
722  // species on the left of the reaction
723  for (i=0;i<rSize;++i)
724  {
725  species=theReactants[i].first;
726  stoich=theReactants[i].second;
727  if (species>=0)
728  {
729  dFdConst[species] -= stoich*dratedc;
730  }
731  }
732  // species on the right
733  for (i=0;i<pSize;++i)
734  {
735  species=theProducts[i].first;
736  stoich=theProducts[i].second;
737  if (species>=0)
738  {
739  dFdConst[species] += stoich*dratedc;
740  }
741  }
742  }
743 }
744 
745 
746 //-----------------------------------------------------------------------------
747 // Function : Reaction::setSimpleRateCalculator
748 // Purpose : set the rate calculator for this reaction to a simple one
749 // Special Notes :
750 // Scope : public
751 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
752 // Creation Date : 8/01/06
753 //-----------------------------------------------------------------------------
754 void Reaction::setSimpleRateCalculator(double k_in, double C0, double t0,
755  double x0)
756 {
757  if (myRateCalc) // we already have a calculator set
758  {
759  delete myRateCalc; // kill it
760  myRateCalc=0;
761  }
762 
763  myRateCalc = dynamic_cast<RateCalculator *> (new SimpleRateCalculator(k_in, C0, t0, x0));
764 }
765 
766 //-----------------------------------------------------------------------------
767 // Function : Reaction::setCaptureRateCalculator
768 // Purpose : set the rate calculator for this reaction to the
769 // capture rate type (A0+E->AM, for example)
770 // Special Notes :
771 // Scope : public
772 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
773 // Creation Date : 8/01/06
774 //-----------------------------------------------------------------------------
775 void Reaction::setCaptureRateCalculator(double sigma, double v,
776  double C0, double t0, double x0)
777 {
778  if (myRateCalc) // we already have a calculator set
779  {
780  delete myRateCalc; // kill it
781  myRateCalc=0;
782  }
783 
784  myRateCalc = dynamic_cast<RateCalculator *> (
785  new CaptureRateCalculator(sigma, v, C0, t0, x0));
786 }
787 
788 //-----------------------------------------------------------------------------
789 // Function : Reaction::setEmissionRateCalculator
790 // Purpose : set the rate calculator for this reaction to the
791 // emission rate type (AM->A0+E, for example)
792 // Special Notes :
793 // Scope : public
794 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
795 // Creation Date : 8/01/06
796 //-----------------------------------------------------------------------------
797 void Reaction::setEmissionRateCalculator(double sigma, double v,
798  double N, double Energy,
799  double C0, double t0, double x0)
800 {
801  if (myRateCalc) // we already have a calculator set
802  {
803  delete myRateCalc; // kill it
804  myRateCalc=0;
805  }
806 
807  myRateCalc = dynamic_cast<RateCalculator *> (
808  new EmissionRateCalculator(sigma, v, N, Energy, C0, t0, x0));
809 }
810 
811 //-----------------------------------------------------------------------------
812 // Function : Reaction::setComplexRateCalculator
813 // Purpose : set the rate calculator for this reaction to the
814 // complex rate type (A+B->AB, for example)
815 // Special Notes :
816 // Scope : public
817 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
818 // Creation Date : 8/01/06
819 //-----------------------------------------------------------------------------
820 void Reaction::setComplexRateCalculator(std::vector<Specie> &V,
821  std::vector<Specie> &C,
822  double C0, double t0, double x0)
823 {
824  if (myRateCalc) // we already have a calculator set
825  {
826  delete myRateCalc; // kill it
827  myRateCalc=0;
828  }
829 
830  myRateCalc = dynamic_cast<RateCalculator *> (
831  new ComplexRateCalculator(V,C,theReactants,C0, t0, x0));
832 }
833 
834 //-----------------------------------------------------------------------------
835 // Function : Reaction::setDecomplexRateCalculator
836 // Purpose : set the rate calculator for this reaction to the
837 // decomplex rate type (AB->A+B, for example)
838 // Special Notes :
839 // Scope : public
840 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
841 // Creation Date : 8/01/06
842 //-----------------------------------------------------------------------------
843 void Reaction::setDecomplexRateCalculator(std::vector<Specie> &V,
844  std::vector<Specie> &C,
845  double bindingEnergy,
846  double gammaAB, double gammaA,
847  double gammaB, double concSi,
848  double C0, double t0, double x0)
849 {
850  if (myRateCalc) // we already have a calculator set
851  {
852  delete myRateCalc; // kill it
853  myRateCalc=0;
854  }
855 
856  myRateCalc = dynamic_cast<RateCalculator *> (
858  bindingEnergy, gammaAB,gammaA,
859  gammaB, concSi,
860  C0, t0, x0));
861 }
862 
863 //-----------------------------------------------------------------------------
864 // Function : Reaction::setRateConstantFromCalculator
865 // Purpose : set the rate constant from the temperature using our rate
866 // calculator
867 // Special Notes :
868 // Scope : public
869 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
870 // Creation Date : 8/01/06
871 //-----------------------------------------------------------------------------
873 {
874  if (myRateCalc) // if we *have* a rate calculator
875  {
877  }
878  // otherwise just leave it where it is (which might be 0)
879 }
880 
881 //-----------------------------------------------------------------------------
882 // Function : Reaction::scaleRateConstantFromCalculator()
883 // Purpose : scale the rate constant using values stored in our rate
884 // calculator
885 // Special Notes :
886 // Scope : public
887 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
888 // Creation Date : 8/01/06
889 //-----------------------------------------------------------------------------
891 {
892  if (myRateCalc) // if we *have* a rate calculator
893  {
895  }
896  // otherwise just leave it where it is
897 }
898 
899 //-----------------------------------------------------------------------------
900 // Function : Reaction::unscaleRateConstantFromCalculator()
901 // Purpose : unscale the rate constant using values stored in our rate
902 // calculator
903 // Special Notes :
904 // Scope : public
905 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
906 // Creation Date : 8/01/06
907 //-----------------------------------------------------------------------------
909 {
910  if (myRateCalc) // if we *have* a rate calculator
911  {
913  }
914  // otherwise just leave it where it is
915 }
916 
917 
918 //-----------------------------------------------------------------------------
919 // Function : Reaction::setDependency
920 // Purpose : Set the vector that denotes which of the cSize species
921 // that the network tracks are actually used in this one
922 // reaction as reactants, that is, the species that are
923 // used in computing the reaction rate.
924 // Special Notes :
925 // Scope : private
926 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
927 // Creation Date : 3/20/06
928 //-----------------------------------------------------------------------------
929 void Reaction::setDependency(int cSize)
930 {
931  int rSize=theReactants.size();
932  int i;
933  numconcs=cSize;
934  concDependency.resize(numconcs,0);
935 
936  for (i=0;i<rSize;++i)
937  {
938  if (theReactants[i].first >= 0)
939  {
940  concDependency[theReactants[i].first]=1;
941  }
942  }
943 
944 }
945 
946 //-----------------------------------------------------------------------------
947 // Function : Reaction::setConstDependency
948 // Purpose : Set the vector that denotes which of the cSize constant
949 // species that the network contains are actually used in this
950 // one reaction as reactants, that is, the species that are
951 // used in computing the reaction rate.
952 // Special Notes :
953 // Scope : private
954 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
955 // Creation Date : 10/17/06
956 //-----------------------------------------------------------------------------
958 {
959  int rSize=theReactants.size();
960  int i;
961  numconsts=cSize;
962  constDependency.resize(numconsts,0);
963 
964  for (i=0;i<rSize;++i)
965  {
966  if (theReactants[i].first < 0)
967  {
968  constDependency[-(theReactants[i].first+1)]=1;
969  }
970  }
971 }
972 
973 //-----------------------------------------------------------------------------
974 // Function : Reaction::output
975 // Purpose : Accessor function to set rate constant
976 // Special Notes :
977 // Scope : public
978 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
979 // Creation Date : 5/27/06
980 //-----------------------------------------------------------------------------
981 void Reaction::output
982  ( const std::vector<Specie> & species, std::ostream & os ) const
983 {
984  int i=0;
985  int isize = theReactants.size();
986  os << " Rxn: ";
987  bool firstPrintDone=false;
988  for (i=0;i<isize;++i)
989  {
990  int speciesIndex = theReactants[i].first;
991  if (speciesIndex >= 0)
992  {
993  if (firstPrintDone) os << " + ";
994  double tmp = theReactants[i].second;
995  if (tmp > 1.0)
996  os << " "<<tmp<< " * ";
997  os.setf(std::ios::right); os.width(3);
998  os << species[speciesIndex].getName();
999 
1000  firstPrintDone = true;
1001  }
1002  }
1003 
1004  os << " = ";
1005  isize = theProducts.size();
1006  firstPrintDone=false;
1007  for (i=0;i<isize;++i)
1008  {
1009  int speciesIndex = theProducts[i].first;
1010  if (speciesIndex >= 0)
1011  {
1012  if (firstPrintDone) os << " + ";
1013  double tmp = theProducts[i].second;
1014  if (tmp > 1.0)
1015  os << " " << tmp << " * ";
1016  os.setf(std::ios::right); os.width(3);
1017 
1018  os << species[speciesIndex].getName();
1019  firstPrintDone = true;
1020  }
1021  }
1022 
1023  os << " Rate Constant: ";
1024  os.precision(8); os.setf(std::ios::scientific);
1025  os << theRateConstant;
1026 
1027 #if 0
1028  os << "\n Dependencies:\n";
1029  for (int j=0;j<concDependency.size();++j)
1030  {
1031  os << " " << species[j].getName() << " = " << concDependency[j] << std::endl;
1032  }
1033 #endif
1034  os << std::endl;
1035 
1036 }
1037 
1038 } // namespace Device
1039 } // namespace Xyce