Xyce  6.1
N_DEV_Reaction.h
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_Reaction.h,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.15.2.1 $
46 //
47 // Revision Date : $Date: 2015/04/02 18:20:09 $
48 //
49 // Current Owner : $Author: tvrusso $
50 //-----------------------------------------------------------------------------
51 
52 #ifndef N_DEV_REACTION_H
53 #define N_DEV_REACTION_H
54 #include <iosfwd>
55 #include <vector>
56 
57 #include <N_DEV_Specie.h>
59 #include <N_DEV_FermiIntegrals.h>
60 #include <N_DEV_MaterialLayer.h>
61 
62 // ---------- Forward Declarations ----------
63 
64 typedef Sacado::ELRFad::DFad<double> FDFadType;
65 
66 namespace Xyce {
67 namespace Device {
68 
69 class Reaction
70 {
71 public:
72  Reaction();
73  Reaction(std::vector< std::pair<int,double> > & ,
74  std::vector< std::pair<int,double> > &,
75  double);
76  Reaction(const Reaction &right);
77  ~Reaction();
78  void setRateConstant(double);
79  void setRateConstantFromCalculator(double T);
80  void setRateConstantFromCalculator(double T,
81  std::vector<double> &concs,
82  std::vector<double> &constant_vec);
83  void scaleRateConstant(double);
86  void setReactants(std::vector< std::pair<int,double> > &products );
87  void addReactant(int species,double stoich);
88  void setProducts(std::vector< std::pair<int,double> > &products );
89  void addProduct(int species,double stoich);
90  double getRate(std::vector<double> &concentrations,
91  std::vector<double> &constants);
92  void getDdt(std::vector<double> &concentrations,
93  std::vector<double> &constants,
94  std::vector<double> &ddt);
95  void getDRateDC(std::vector<double> &concentrations,
96  std::vector<double> &constants,
97  std::vector<double> &dratedc);
98  void getDRateDConst(int constNum,
99  std::vector<double> &concentrations,
100  std::vector<double> &constants,
101  double &dratedc);
102  void getJac(std::vector<double> &concentrations,
103  std::vector<double> &constants,
104  std::vector<std::vector<double> > &jac);
105  void getDFdConst(int constantNumber,
106  std::vector<double> &concentrations,
107  std::vector<double> &constants,
108  std::vector<double> &dFdConst);
109 
110  void getJacobianVC(std::vector<double> &concentrations,
111  std::vector<double> &constants,
112  std::vector<std::vector<double> > &jac,
113  std::vector<double> &constVec);
114 
115  void output ( const std::vector<Specie> & species,
116  std::ostream & os ) const;
117 
118  void setSimpleRateCalculator(double k, double C0, double t0, double x0);
119  void setCaptureRateCalculator(double sigma, double v, double C0, double t0,
120  double x0);
121  void setEmissionRateCalculator(double sigma, double v, double N,
122  double Energy, double C0, double t0,
123  double x0);
124  void setFDEmissionRateCalculator(int carrierIndex, double sigma, double Energy,
125  double v, double C0, double t0, double x0);
126  void setComplexRateCalculator(std::vector<Specie> &VariableSpecies,
127  std::vector<Specie> &ConstantSpecies,
128  double C0, double t0, double x0);
129  void setComplexMultiplierRateCalculator(std::vector<Specie> &VariableSpecies,
130  std::vector<Specie> &ConstantSpecies,
131  double C0, double t0, double x0,
132  double multiplier);
133  void setDecomplexRateCalculator(std::vector<Specie> &VariableSpecies,
134  std::vector<Specie> &ConstantSpecies,
135  double bindingEnergy,
136  double gammaAB, double gammaA, double gammaB,
137  double concSi,
138  double C0, double t0, double x0);
139 
140  void setBourgoinCorbettHoleRateCalculator(std::vector<Specie> &VariableSpecies,
141  std::vector<Specie> &ConstantSpecies,
142  double sigma,double C0, double t0, double x0);
143 
145 
146  void setTemperature(double T);
147 
148  void setMaterial(MaterialLayer *material, double Temp);
149  void setCoefficient(double Temp);
150  void setRxnVariableCoeffs(bool variableCoeff){variableRateCoefficient = variableCoeff;}
151 
152  template <class ScalarT>
153  ScalarT getFDEmissionRate(std::vector<ScalarT> &concentrations,
154  std::vector<ScalarT> &constants);
155 
156  template <class ScalarT>
157  ScalarT getRateVC(std::vector<ScalarT> &concentrations,
158  std::vector<ScalarT> &constants);
159 
160  inline void setScaleFactors(double C0i, double t0, double x0)
161  {
162  C0 = C0i;
163  if (myRateCalc)
164  myRateCalc->setScaleFactors(C0i,t0,x0);
165  };
166 
167  Reaction & operator=(const Reaction & right);
168 
169 private:
170  void setDependency(int cSize);
171  void setConstDependency(int cSize);
172  std::vector< std::pair<int,double> > theReactants;
173  std::vector< std::pair<int,double> > theProducts;
175  int numconcs; // size of vector of concentrations
176  int numconsts; // size of vector of constants
178  std::vector<int> concDependency;
179  std::vector<int> constDependency;
181  double C0;
186  std::string myReactionName;
188  std::vector<FDFadType> defects;
189  std::vector<FDFadType> carriers;
191 
192  //Coefficient data
194  double tolerance;
195  double charge;
196  double peq;
197  double constCoeff;
200  template <class ScalarT>
201  ScalarT rxnCoefficient(std::vector<ScalarT> &concentrations,
202  std::vector<ScalarT> &constants);
203 
204  template <class ScalarT>
205  ScalarT complexCoefficient(std::vector<ScalarT> &concentrations,
206  std::vector<ScalarT> &constants);
207 
211  //The following is needed for bourgoin corbett
215 
218 
219 
220 };
221 
222 //-----------------------------------------------------------------------------
223 // Function : Reaction::setRateConstant
224 // Purpose : Accessor function to set rate constant
225 // Special Notes :
226 // Scope : public
227 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
228 // Creation Date : 3/20/06
229 //-----------------------------------------------------------------------------
230 inline void Reaction::setRateConstant(double rateConst)
231 {
232  theRateConstant=rateConst;
233 }
234 
235 //-----------------------------------------------------------------------------
236 // Function : Reaction::scaleRateConstant
237 // Purpose : Accessor function to scale rate constant
238 // Special Notes :
239 // Scope : public
240 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
241 // Creation Date : 3/20/06
242 //-----------------------------------------------------------------------------
243 inline void Reaction::scaleRateConstant(double scalar)
244 {
245  theRateConstant *= scalar;
246 }
247 
248 
249 //-----------------------------------------------------------------------------
250 // Function : Reaction::getEmissionCarrierIndex
251 // Purpose : Accessor function to emission carrier index
252 // Special Notes :
253 // Scope : public
254 // Creator : Lawrence C Musson
255 // Creation Date : 07/14/2014
256 //-----------------------------------------------------------------------------
258 {
259  return carrierEmissionIndex;
260 }
261 
262 
263 //-----------------------------------------------------------------------------
264 // Function : Reaction::setTemperature
265 // Purpose : Accessor function to set the temperature
266 // Special Notes :
267 // Scope : public
268 // Creator : Lawrence C Musson
269 // Creation Date : 07/14/2014
270 //-----------------------------------------------------------------------------
271  inline void Reaction::setTemperature(double T)
272 {
273  temperature = T;
274 }
275 
276 //-----------------------------------------------------------------------------
277 // Function : Reaction::getFDEmissionRate
278 // Purpose : compute and return the carrier emission rate with FD stats.
279 // Scope : public
280 // Creator : Lawrence C Musson, SNL
281 // Creation Date : 07/11/2014
282 //-----------------------------------------------------------------------------
283 
284 template <class ScalarT>
285  ScalarT Reaction::getFDEmissionRate(std::vector<ScalarT> &concentrations,
286  std::vector<ScalarT> &constants)
287  {
288 
289  ScalarT rRate=0.0;
290 
291  int rSize=theReactants.size();
292  int pSize=theProducts.size();
293 
294  int i;
295  int species;
296  double stoich;
297  ScalarT c;
298 
299  // Reaction rate determined by law of mass action
300 
301  ScalarT localCoeff = rxnCoefficient(concentrations, constants);
302 
303  rRate = theRateConstant*localCoeff;
304  // product of concentrations of reactants raised to the power of
305  // stoichiometric coefficient
306 
307  for (i=0;i<rSize;++i)
308  {
309  species=theReactants[i].first;
310  stoich=theReactants[i].second;
311 
312  if (species>=0)
313  {
314  c=concentrations[species];
315  }
316  else
317  {
318  c=constants[-(species+1)];
319  }
320 
321  if (stoich != 1.0)
322  {
323  rRate *= pow(c,stoich);
324  }
325  else
326  {
327  rRate *= c;
328  }
329  }
330 
331  double KbT=CONSTboltz*temperature/CONSTQ;
332 
333  double DOS;
334 
335  if(carrierEmissionIndex==0)
336  DOS = material->Nc;
337  else
338  DOS = material->Nv;
339 
340  if(C0*constants[carrierEmissionIndex] <1.e12)
341  {
342  ScalarT exponential = exp(-energy/KbT);
343  rRate *= DOS*exponential;
344  }
345  else
346  {
347  DOS /= C0;
348 
349  ScalarT ratio = constants[carrierEmissionIndex]/DOS;
350 
351  ScalarT iFI = KbT*fdinvObj(ratio);
352 
353  ScalarT exponential = exp(-(iFI + energy)/KbT);
354 
355  rRate*=C0*constants[carrierEmissionIndex]*exponential;
356  }
357 
358  return rRate;
359 
360  }
361 
362 
363 //-----------------------------------------------------------------------------
364 // Function : Reaction::getRateVC
365 // Purpose : compute and return the reaction rate. This is normally the
366 // first step of getDdt, but we might need this for
367 // other purposes (e.g. a kludge for getting electron/hole
368 // recombination/regeneration rates even when electrons and
369 // holes are constant species). In this version the rate coefficients
370 // are CONCENTRAION AND temperature dependent. Moreover, the method
371 // is templated so that it can be FADed cleanly.
372 // Special Notes : It is tacitly assumed that the concentrations and
373 // constants in the provided vector are in an order
374 // consistent with the labeling in the reactants and
375 // products vectors. The contributions to the species
376 // time derivatives are summed into the provided output
377 // vector because it is assumed that there will be a network
378 // of reactions, not just one.
379 // Scope : public
380 // Creator : Lawrence C Musson
381 // Creation Date : 08/26/2014
382 //-----------------------------------------------------------------------------
383 template <class ScalarT>
384  ScalarT Reaction::getRateVC(std::vector<ScalarT> &concentrations,
385  std::vector<ScalarT> &constants)
386 {
387  int rSize=theReactants.size();
388  int pSize=theProducts.size();
389  ScalarT reactionRate;
390  int i;
391  int species;
392  double stoich;
393  ScalarT c;
394 
395  // Reaction rate determined by law of mass action
396 
397  ScalarT localCoeff = rxnCoefficient(concentrations, constants);
398 
399  reactionRate=theRateConstant*localCoeff;
400 
401  // product of concentrations of reactants raised to the power of
402  // stoichiometric coefficient
403 
404  for (i=0;i<rSize;++i)
405  {
406  species=theReactants[i].first;
407  stoich=theReactants[i].second;
408 
409  if (species>=0)
410  {
411  c=concentrations[species];
412  }
413  else
414  {
415  c=constants[-(species+1)];
416  }
417 
418  if (stoich != 1.0)
419  {
420  reactionRate *= pow(c,stoich);
421  }
422  else
423  {
424  reactionRate *= c;
425  }
426 
427  }
428 
429  return reactionRate;
430 }
431 
432 
433 //---------------------------------------------------------
434 //
435 // What follows is a set of templated functions that provide
436 // concentration dependent pieces of the rate coefficients.
437 //
438 //---------------------------------------------------------
439 
440 template <class ScalarT>
441 ScalarT Reaction::rxnCoefficient(std::vector<ScalarT> &concentrations,
442  std::vector<ScalarT> &constants)
443 {
444 
445  ScalarT rxnCoeff;
446 
447  switch(coefficientType)
448  {
449  case 0 :
450  rxnCoeff = constCoeff;
451  break;
452 
453  case 1:
454 
455  rxnCoeff = complexCoefficient(concentrations, constants);
456  break;
457 
458  default :
459  //unrecognized reaction name
460  Report::UserError() << "Unrecognized reaction coefficient type in rection coefficient evaluator";
461  }
462 
463  return rxnCoeff;
464 };
465 
466 template <class ScalarT>
467  ScalarT Reaction::complexCoefficient(std::vector<ScalarT> &concentrations,
468  std::vector<ScalarT> &constants)
469  {
470 
471  //The following is done to jibe with Myers and Wampler for GaAs
472 
473  ScalarT localCoeff;
474 
475  ScalarT ADTEMP = temperature;
476 
477  if(chargeProduct == 0)
478  if(materialEnum == si)
479  localCoeff = latticeConstant;
480  else if(materialEnum == gaas)
481  {
482  ScalarT concsDensity=0.0;
483  for(int i=0 ; i<concentrations.size() ; ++i)
484  concsDensity += concentrations[i];
485 
486  ScalarT rdefTilde = pow(tolerance+C0*concsDensity,1.0/3.0);
487 
488  ScalarT rdef = 0.5/rdefTilde;
489 
490  localCoeff = 1.0/(1.0/rdef + 1.0/latticeConstant);
491  }
492  else
493  {
494  //unrecognized material in complexCoefficient in
495  Report::UserError() << "Unrecognized material in complex reaction coefficient evaluator";
496  }
497  else
498  {
499  //if(material->material=="si")
500  if(materialEnum == si)
501  localCoeff = -(ScalarT)chargeProduct*unshieldedLength;
502  //else if(material->material == "gaas")
503  else if(materialEnum == gaas)
504  {
505 
506  // Defect / Doping Concentration Dependence
507  ScalarT concsDensity=0.0;
508 
509  charge=1.6021918e-19; //C
510 
511  peq = charge/(13.1*8.854214871e-14); //From Myers & Wampler
512 
513  for(int i=0 ; i<concentrations.size() ; ++i)
514  concsDensity += concentrations[i];
515 
516  ScalarT rdefTilde = pow(tolerance+C0*concsDensity,1.0/3.0);
517 
518  ScalarT rdef = 0.5/rdefTilde;
519 
520  //Carrier Dependence
521 
522  ScalarT TeV = ADTEMP/11604.0; //temperature in eV
523 
524  ScalarT deby0 = sqrt(TeV/peq);
525 
526  ScalarT carrierConcentration = tolerance + C0*constants[0];
527 
528  if(tolerance + C0*constants[0] < 0.0) carrierConcentration = 1.e-16;
529 
530  ScalarT carrier1Debye=deby0/sqrt(carrierConcentration);
531 
532  carrierConcentration = tolerance + C0*constants[1];
533 
534  if(carrierConcentration < 0.0)carrierConcentration = 1.0;
535 
536  ScalarT carrier2Debye=deby0/sqrt(carrierConcentration);
537 
538  ScalarT debye= 1.0/(1.0/carrier1Debye+1.0/carrier2Debye);
539 
540  // scrt(z)= 0.65d0*log(1.0d0+z/0.65d0) ! approximates root of screened coulomb potential
541 
542  ScalarT arg = - (ScalarT)chargeProduct*unshieldedLength/debye;
543 
544  ScalarT reactionRadiusTilde = 0.65*log(1.0 + arg/0.65)*debye;
545 
546  //if carriers < 0, default to using rdef
547 
548  if(constants[0] < 0.0 || constants[1] < 0)
549  reactionRadiusTilde = 1.0e12;
550 
551  localCoeff = 1.0/(1.0/rdef + 1.0/reactionRadiusTilde);
552  }
553  else
554  {
555  //unrecognized material in complexCoefficient in
556  Report::UserError() << "Unrecognized material in complex reaction coefficient evaluator";
557  }
558  }
559 
560 
561  ScalarT diffusion = diffusionCoefficient1 + diffusionCoefficient2;
562 
563  if(carrierBCIndex >= 0)
564  diffusion += sigmaBC*thermalVelocity*C0*constants[carrierBCIndex]*hopLength*hopLength/6.0;
565 
566  return localCoeff*diffusion;
567 
568  }
569 
570 
571 } // namespace Device
572 } // namespace Xyce
573 
574 #endif
void setSimpleRateCalculator(double k, double C0, double t0, double x0)
void setComplexMultiplierRateCalculator(std::vector< Specie > &VariableSpecies, std::vector< Specie > &ConstantSpecies, double C0, double t0, double x0, double multiplier)
virtual void setScaleFactors(double C0, double t0, double x0)=0
set concentration, time, and space scale factors (space scale factor is currently unused by any calcu...
#define CONSTQ
Definition: N_DEV_Const.h:51
Sacado::ELRFad::DFad< double > FDFadType
Pure virtual class to augment a linear system.
void unscaleRateConstantFromCalculator()
double getRate(std::vector< double > &concentrations, std::vector< double > &constants)
std::vector< int > concDependency
std::vector< FDFadType > carriers
inverse_fermi_one_half_N fdinvObj
void setMaterial(MaterialLayer *material, double Temp)
void scaleRateConstant(double)
void getDdt(std::vector< double > &concentrations, std::vector< double > &constants, std::vector< double > &ddt)
void setEmissionRateCalculator(double sigma, double v, double N, double Energy, double C0, double t0, double x0)
void getDRateDConst(int constNum, std::vector< double > &concentrations, std::vector< double > &constants, double &dratedc)
void addReactant(int species, double stoich)
void output(const std::vector< Specie > &species, std::ostream &os) const
ScalarT getFDEmissionRate(std::vector< ScalarT > &concentrations, std::vector< ScalarT > &constants)
std::vector< int > constDependency
std::vector< FDFadType > defects
void addProduct(int species, double stoich)
void setRateConstantFromCalculator(double T)
void setScaleFactors(double C0i, double t0, double x0)
ScalarT complexCoefficient(std::vector< ScalarT > &concentrations, std::vector< ScalarT > &constants)
RateCalculator * myRateCalc
void getJac(std::vector< double > &concentrations, std::vector< double > &constants, std::vector< std::vector< double > > &jac)
void setDecomplexRateCalculator(std::vector< Specie > &VariableSpecies, std::vector< Specie > &ConstantSpecies, double bindingEnergy, double gammaAB, double gammaA, double gammaB, double concSi, double C0, double t0, double x0)
Reaction & operator=(const Reaction &right)
void setRxnVariableCoeffs(bool variableCoeff)
void setCoefficient(double Temp)
void getDRateDC(std::vector< double > &concentrations, std::vector< double > &constants, std::vector< double > &dratedc)
std::vector< std::pair< int, double > > theReactants
std::vector< std::pair< int, double > > theProducts
void setCaptureRateCalculator(double sigma, double v, double C0, double t0, double x0)
void setRateConstant(double)
void setConstDependency(int cSize)
void setDependency(int cSize)
ScalarT getRateVC(std::vector< ScalarT > &concentrations, std::vector< ScalarT > &constants)
Abstract interface class for "rate calculator" strategy pattern.
void setFDEmissionRateCalculator(int carrierIndex, double sigma, double Energy, double v, double C0, double t0, double x0)
void setReactants(std::vector< std::pair< int, double > > &products)
void setTemperature(double T)
MaterialLayer * material
void setBourgoinCorbettHoleRateCalculator(std::vector< Specie > &VariableSpecies, std::vector< Specie > &ConstantSpecies, double sigma, double C0, double t0, double x0)
void setProducts(std::vector< std::pair< int, double > > &products)
ScalarT rxnCoefficient(std::vector< ScalarT > &concentrations, std::vector< ScalarT > &constants)
void getDFdConst(int constantNumber, std::vector< double > &concentrations, std::vector< double > &constants, std::vector< double > &dFdConst)
void getJacobianVC(std::vector< double > &concentrations, std::vector< double > &constants, std::vector< std::vector< double > > &jac, std::vector< double > &constVec)
materialEnum_t materialEnum
void setComplexRateCalculator(std::vector< Specie > &VariableSpecies, std::vector< Specie > &ConstantSpecies, double C0, double t0, double x0)
#define CONSTboltz
Definition: N_DEV_Const.h:53