Xyce  6.1
N_DEV_FermiIntegrals.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_FermiIntegrals.h,v $
27 //
28 // Purpose : This file contains the fermi integral functors
29 //
30 // Special Notes :
31 //
32 // Creator : Lawrence C Musson, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 06/05/2014
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.1.2.1 $
40 //
41 // Revision Date : $Date: 2015/04/02 18:20:12 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-----------------------------------------------------------------------------
45 
46 #ifndef Xyce_N_DEV_FermiIntegrals_h
47 #define Xyce_N_DEV_FermiIntegrals_h
48 
49 // ---------- Standard Includes ----------
50 
51 #include <N_UTL_Misc.h>
52 
53 #ifdef HAVE_CMATH
54 #include <cmath>
55 #else
56 #include <math.h>
57 #endif
58 #include <time.h>
59 
60 #include <Sacado.hpp>
61 #include <map>
62 
63 // ---------- Xyce Includes ----------
64 #include <N_DEV_fwd.h>
65 #include <N_DEV_DeviceInstance.h>
66 #include <N_DEV_MaterialSupport.h>
67 #include <N_DEV_BernouliSupport.h>
68 #include <N_DEV_Const.h>
69 #include <N_DEV_CompositeParam.h>
70 #include <N_DEV_DopeInfo.h>
71 #include <N_DEV_ScalingVars.h>
72 
73 // ---------- Forward Declarations ----------
74 
75 typedef Sacado::Fad::SFad<double,10> pdeFadType;
76 
77 namespace Xyce
78 {
79  namespace Device
80  {
81 
82 
83 //-----------------------------------------------------------------------------
84 // Class : inverse_fermi_one_half_N
85 // Purpose : inverse fermi-dirac integral. Implemented as a functor.
86 // Special Notes :
87 // Creator : Eric Keiter, SNL
88 // Creation Date : 07/01/11
89 //-----------------------------------------------------------------------------
91 {
92  private:
93  double d__1, d__2, d__3;
94  double a1, a2, a3, a4, a5, a6, a7, a8, x10, y10, yp10, x20, y20, yp20, c1, c2;
95  double pi, delx, dely;
96 
97  public:
98  inverse_fermi_one_half_N () // this stuff gets called 1x.
99  {
100  double c_b2 = 4.0/3.0;
101  pi = 2.0*asin(1.0);
102 
103  a1 = sqrt(2.0) / 4.0;
104  a2 = 0.1875 - sqrt(3.0) / 9.0;
105  a3 = sqrt(2.0) * 5.0 / 48.0 + 0.125 - sqrt(6.0) / 9.0;
106  a4 = sqrt(2.0) * 5.0 / 32.0 + 1585.0/6912.0 - sqrt(3.0) * 5.0/24.0 - sqrt(5.0) / 25.0;
107  d__1 = sqrt(pi) * 3.0/4.0;
108  a5 = pow(d__1, c_b2);
109  a6 = 4.0/3.0;
110  a7 = pi * pi / 6.0;
111  a8 = 1.0/3.0;
112  x10 = 7.5;
113  d__3 = x10*x10;
114  y10 = log(x10) + a1 * x10 + a2 * (x10*x10) + a3*(x10*x10*x10) + a4*(d__3 * d__3);
115  yp10 = 1.0/x10 + a1 + a2 * 2.0 * x10 + a3 * 3.0 * (x10 * x10) + a4 * 4.0 * (x10 * x10 * x10);
116  x20 = 8.5;
117  y20 = sqrt(a5 * pow(x20, a6) - a7);
118  yp20 = 0.5 / sqrt(a5 * pow(x20, a6) - a7) * a6 * a5 * pow(x20, a8);
119  delx = 0.5;
120  dely = y20 - y10;
121  c1 = dely * 0.5 / (delx * delx) - yp10 * 0.75 / delx - yp20 * 0.25 / delx;
122  c2 = dely * 0.5 / (delx * delx) - yp20 * 0.75 / delx - yp10 * 0.25 / delx;
123  }
124 
125  template <typename ScalarT>
126  ScalarT operator()(const ScalarT & ratio)
127  {
128  ScalarT ret_val = 0.0;
129  ScalarT tempVal = 0.0;
130 
131  // Joyce-Dixon expressions as used in Medici
132  if (ratio > 0.0 && ratio <= 7.5)
133  {
134  tempVal = ratio*ratio;
135  ret_val = log(ratio) + a1 * ratio + a2*(ratio*ratio) + a3*(ratio*ratio*ratio) + a4*(tempVal*tempVal);
136  }
137 
138  // These next two clauses from Sam Myers
139  if (ratio > 7.5 && ratio <= 8.0)
140  {
141  ScalarT diff = ratio - 7.5;
142  ret_val = y10 + yp10*diff + c1*(diff*diff);
143  }
144  if (ratio > 8. && ratio < 8.5)
145  {
146  ScalarT diff = 8.5-ratio;
147  ret_val = y20 - yp20*diff - c2*(diff*diff);
148  }
149  if (ratio >= 8.5)
150  {
151  ret_val = sqrt(a5 * pow(ratio, a6) - a7);
152  }
153  return ret_val;
154  }
155 };
156 
157 
158 //-----------------------------------------------------------------------------
159 // Class : fermi_one_half
160 // Purpose : fermi-dirac integral. Implemented as a functor.
161 // Special Notes :
162 // Creator : Lawrence C Musson
163 // Creation Date : 06/04/14
164 //-----------------------------------------------------------------------------
166 {
167  private:
168 
169  double pi;
170 
171  public:
173  {
174  pi = 4.0*atan(1.0);
175  }
176 
177  template <typename ScalarT>
178  ScalarT operator()(const ScalarT & arg)
179  {
180 
181  // Reference: "The Approximation of the Fermi-Dirac Integral F1/2(eta)"
182  // by D. Bednarczyk and J. Bednarczyk, Physics Letters, Vol. 64A, No. 4,
183  // 9 January 1978, pp. 409-410.
184  ScalarT nu_eta = pow(arg, 4.0) + 50.0 +
185  33.6*arg*(1.0 - 0.68*exp(-0.17*pow(arg+1.0,2)));
186 
187  ScalarT xi = 3.0*sqrt(pi)/(4.0*pow(nu_eta,0.375));
188 
189  ScalarT neta_uarg = 1.0/(exp(-arg)+xi);
190 
191  return neta_uarg;
192  }
193 
194 };
195 
196 //-----------------------------------------------------------------------------
197 // Class : fermi_minus_one_half
198 // Purpose : fermi-dirac integral. Implemented as a functor.
199 // Special Notes :
200 // Creator : Lawrence C Musson
201 // Creation Date : 06/04/14
202 //-----------------------------------------------------------------------------
203 //template <typename ScalarT>
205  {
206 
207  //Halen Pulfrey approximation
208  private:
209 
210  double a1[7],a2[9],a3[9],n1[7];
211 
212  public:
214  {
215  a1[0] = 1.12837;
216  a1[1] = -0.470698;
217  a1[2] = -0.453108;
218  a1[3] = -228.975;
219  a1[4] = 8303.5;
220  a1[5] = -118124.0;
221  a1[6] = 632895.0;
222 
223  a2[0] = 0.604856;
224  a2[1] = 0.380080;
225  a2[2] = 0.059320;
226  a2[3] = -0.014526;
227  a2[4] = -0.004222;
228  a2[5] = 0.001335;
229  a2[6] = 0.000291;
230  a2[7] = -0.000159;
231  a2[8] = 0.000018;
232 
233  a3[0] = 0.638086;
234  a3[1] = 0.292266;
235  a3[2] = 0.159486;
236  a3[3] = -0.077691;
237  a3[4] = 0.018650;
238  a3[5] = -0.002736;
239  a3[6] = 0.000249;
240  a3[7] = -0.000013;
241  a3[8] = 2.9814e-07;
242 
243  // For negative arguments
244  n1[0] = 0.999909;
245  n1[1] = 0.706781;
246  n1[2] = 0.572752;
247  n1[3] = 0.466318;
248  n1[4] = 0.324511;
249  n1[5] = 0.152889;
250  n1[6] = 0.033673;
251  }
252 
253  template <typename ScalarT>
254  ScalarT operator()(const ScalarT & arg)
255  {
256 
257  ScalarT ret_val = 0.0;
258 
259  if (arg <= 0.0)
260  {
261  double sign = 1.0;
262  double index;
263  for (int i=0; i < 7; ++i)
264  {
265  index = i;
266  ret_val += sign*n1[i]*std::exp((index+1.0)*arg);
267  sign *= -1.0;
268  }
269  }
270  else if (arg >= 5.0)
271  {
272  ScalarT mult = std::sqrt(arg);
273  for (int i=0; i < 7; ++i)
274  {
275  ret_val += a1[i] / std::pow(arg, 2.0*i);
276  }
277  ret_val = mult * ret_val;
278  }
279  else if (arg < 2.5)
280  {
281  for (int i=0; i < 9; ++i)
282  {
283  ret_val += a2[i] * std::pow(arg, i);
284  }
285  }
286  else // 2.5 <= arg < 5.0
287  {
288  for (int i=0; i < 9; ++i)
289  {
290  ret_val += a3[i] * std::pow(arg, i);
291  }
292  }
293 
294  return ret_val;
295  }
296 
297 };
298 
299 
300 
301 
302  } //Device namespace
303 } //Xyce namespace
304 
305 //typedef Xyce::Device::FermiIntegrals N_DEV_FermiIntegrals;
306 
307 #endif //Xyce_N_DEV_FermiIntegrals_h
308 
Pure virtual class to augment a linear system.
ScalarT operator()(const ScalarT &arg)
ScalarT operator()(const ScalarT &arg)
ScalarT operator()(const ScalarT &ratio)
Sacado::Fad::SFad< double, 10 > pdeFadType