Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_DevicePDEInstance.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-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_DevicePDEInstance.h,v $
27 //
28 // Purpose : This file contains the PDE device instance base class.
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 05/15/01
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.56.2.1 $
40 //
41 // Revision Date : $Date: 2014/02/26 20:16:31 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-----------------------------------------------------------------------------
45 
46 #ifndef Xyce_N_DEV_DevicePDEInstance_h
47 #define Xyce_N_DEV_DevicePDEInstance_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 
62 // ---------- Xyce Includes ----------
63 #include <N_DEV_fwd.h>
64 #include <N_DEV_DeviceInstance.h>
65 #include <N_DEV_MaterialSupport.h>
66 #include <N_DEV_BernouliSupport.h>
67 #include <N_DEV_Const.h>
68 #include <N_DEV_CompositeParam.h>
69 #include <N_DEV_DopeInfo.h>
70 #include <N_DEV_ScalingVars.h>
71 
72 // ---------- Forward Declarations ----------
73 
74 typedef Sacado::Fad::SFad<double,10> pdeFadType;
75 
76 namespace Xyce {
77 namespace Device {
78 
79 //-----------------------------------------------------------------------------
80 // Class : inverse_fermi_one_half_N
81 // Purpose : inverse fermi-dirac integral. Implemented as a functor.
82 // Special Notes :
83 // Creator : Eric Keiter, SNL
84 // Creation Date : 07/01/11
85 //-----------------------------------------------------------------------------
87 {
88 private:
89  double d__1, d__2, d__3;
90  double a1, a2, a3, a4, a5, a6, a7, a8, x10, y10, yp10, x20, y20, yp20, c1, c2;
91  double pi, delx, dely;
92 
93 public:
94  inverse_fermi_one_half_N () // this stuff gets called 1x.
95  {
96  double c_b2 = 4.0/3.0;
97  pi = 2.0*asin(1.0);
98 
99  a1 = sqrt(2.0) / 4.0;
100  a2 = 0.1875 - sqrt(3.0) / 9.0;
101  a3 = sqrt(2.0) * 5.0 / 48.0 + 0.125 - sqrt(6.0) / 9.0;
102  a4 = sqrt(2.0) * 5.0 / 32.0 + 1585.0/6912.0 - sqrt(3.0) * 5.0/24.0 - sqrt(5.0) / 25.0;
103  d__1 = sqrt(pi) * 3.0/4.0;
104  a5 = pow(d__1, c_b2);
105  a6 = 4.0/3.0;
106  a7 = pi * pi / 6.0;
107  a8 = 1.0/3.0;
108  x10 = 7.5;
109  d__3 = x10*x10;
110  y10 = log(x10) + a1 * x10 + a2 * (x10*x10) + a3*(x10*x10*x10) + a4*(d__3 * d__3);
111  yp10 = 1.0/x10 + a1 + a2 * 2.0 * x10 + a3 * 3.0 * (x10 * x10) + a4 * 4.0 * (x10 * x10 * x10);
112  x20 = 8.5;
113  y20 = sqrt(a5 * pow(x20, a6) - a7);
114  yp20 = 0.5 / sqrt(a5 * pow(x20, a6) - a7) * a6 * a5 * pow(x20, a8);
115  delx = 0.5;
116  dely = y20 - y10;
117  c1 = dely * 0.5 / (delx * delx) - yp10 * 0.75 / delx - yp20 * 0.25 / delx;
118  c2 = dely * 0.5 / (delx * delx) - yp20 * 0.75 / delx - yp10 * 0.25 / delx;
119  }
120 
121  template <typename ScalarT>
122  ScalarT operator()(const ScalarT & ratio)
123  {
124  ScalarT ret_val = 0.0;
125  ScalarT tempVal = 0.0;
126 
127  // Joyce-Dixon expressions as used in Medici
128  if (ratio > 0.0 && ratio <= 7.5)
129  {
130  tempVal = ratio*ratio;
131  ret_val = log(ratio) + a1 * ratio + a2*(ratio*ratio) + a3*(ratio*ratio*ratio) + a4*(tempVal*tempVal);
132  }
133 
134  // These next two clauses from Sam Myers
135  if (ratio > 7.5 && ratio <= 8.0)
136  {
137  ScalarT diff = ratio - 7.5;
138  ret_val = y10 + yp10*diff + c1*(diff*diff);
139  }
140  if (ratio > 8. && ratio < 8.5)
141  {
142  ScalarT diff = 8.5-ratio;
143  ret_val = y20 - yp20*diff - c2*(diff*diff);
144  }
145  if (ratio >= 8.5)
146  {
147  ret_val = sqrt(a5 * pow(ratio, a6) - a7);
148  }
149  return ret_val;
150  }
151 };
152 
153 //-----------------------------------------------------------------------------
154 // Class : DevicePDEInstance
155 // Purpose :
156 // Special Notes :
157 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
158 // Creation Date : 3/16/00
159 //-----------------------------------------------------------------------------
161 {
162 public:
164  const InstanceBlock & IB,
165  ParametricData<void> & parametric_data,
166  const FactoryBlock & factory_block);
167 
168  virtual ~DevicePDEInstance () {};
169 
170 private:
171  DevicePDEInstance(const DevicePDEInstance & right);
173 
174 public:
175  // Fermi-Dirac integral
176  double fermi_one_half_B(double arg)
177  {
178  double pi = 4.0*atan(1.0);
179 
180  double nu_eta = pow(arg, 4.0) + 50.0 +
181  33.6*arg*(1.0 - 0.68*exp(-0.17*pow(arg+1.0,2)));
182 
183  double xi = 3.0*sqrt(pi)/(4.0*pow(nu_eta,0.375));
184 
185  return 1.0/(exp(-arg)+xi);
186  }
187 
188  double getVoltDepHoleDens (double Vmin, double V, double Na)
189  {
190  return Na * exp ( Xycemin(CONSTMAX_EXP_ARG, ((Vmin-V)/Ut)) );
191  }
192 
193  double getVoltDepElecDens (double Vmax, double V, double Nd)
194  {
195  return Nd * exp ( Xycemin(CONSTMAX_EXP_ARG, ((V-Vmax)/Ut)) );
196  }
197 
198  double aux1 (double x);
199  double aux2 (double x);
200 
201 
202  double pd1aux1(double x);
203  double pd1aux2(double x);
204 
205  double Jn (double n1, double n2, double E, double u, double h);
206 
207  double dJndV1 (double n1, double n2, double E, double u, double h);
208  double dJndV2 (double n1, double n2, double E, double u, double h);
209  double dJndn1 (double n1, double n2, double E, double u, double h);
210  double dJndn2 (double n1, double n2, double E, double u, double h);
211 
212  double Jp (double p1, double p2, double E, double u, double h);
213 
214  double dJpdV1 (double p1, double p2, double E, double u, double h);
215  double dJpdV2 (double p1, double p2, double E, double u, double h);
216  double dJpdn1 (double p1, double p2, double E, double u, double h);
217  double dJpdn2 (double p1, double p2, double E, double u, double h);
218 
219  // charge dependent current density calculations
220  double J_qdep (double n1, double n2, double E, double u, double h, int z);
221 
223  {
224  pdeFadType retVal=0.0;
225  if (x < -bernSupport.bp0_MISC) x = -bernSupport.bp0_MISC;
226  else if (x > bernSupport.bp0_MISC) x = bernSupport.bp0_MISC;
227 
228  if (x <= bernSupport.bp0_AUX1) retVal=(x / sinh(x));
229  else if (x <= bernSupport.bp1_AUX1) retVal=(1 - x*x/6.0*(1.0 - 7.0*x*x/60.0));
230  else retVal=(x / sinh(x));
231 
232  return retVal;
233  }
234 
236  {
237  pdeFadType retVal=0.0;
238 
239  if (x <= bernSupport.bp0_AUX2) retVal=(1.0);
240  else if (x <= bernSupport.bp1_AUX2) retVal=(1.0 / (1.0 + exp(x)));
241  else if (x <= bernSupport.bp2_AUX2) retVal=(exp(-x));
242  else retVal=(0.0);
243 
244  return retVal;
245  }
246 
247 
248  pdeFadType nMidpoint(pdeFadType & n1, pdeFadType & n2, pdeFadType & E, double h, int z);
249 
250  double J_qdep (double n1, double n2, double E, pdeFadType & u, double h, int z)
251  { return J_qdep (n1, n2, E, u.val(), h, z); }
252 
253  double dJdV1_qdep (double n1, double n2, double E, double u, double h, int z);
254  double dJdV2_qdep (double n1, double n2, double E, double u, double h, int z);
255  double dJdn1_qdep (double n1, double n2, double E, double u, double h, int z);
256  double dJdn2_qdep (double n1, double n2, double E, double u, double h, int z);
257 
258  double dJdV1_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
259  double dJdV2_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
260  double dJdn1_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
261  double dJdn2_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
262  double dJdp1_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
263  double dJdp2_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
264  double dJdbm1_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
265  double dJdbm2_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
266  double dJdpp1_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
267  double dJdpp2_qdep (double n1, double n2, double E, const pdeFadType & u, double h, int z);
268  //
269 
270 #if 0
271  double nsdep(double x, double W, double Dt);
272 
273  double ngdep(double x, double y, double W, double ax, double ay);
274  double ngdep2(double x, double y, double ax, double ay);
275 #endif
276 
277  double erf(double x);
278  double pd1erf(double x);
279 
280  void setupOutputName ();
281 
282  const std::string timeDateStamp();
283  const std::string tecplotTimeDateStamp();
284 
285 public:
286  // physical constants:
287  double Temp; // operating temperature (K)
288  double charge; // electron charge (C)
289  double kb; // boltzmann's constant (J/K)
290  double Vt; // thermal voltage
291  double Ut; // thermal voltage, scaled.
292  double e0; // permittivity of vacuum (F/cm)
293  double eSi; // relative permittivity of Si
294  double eSiO2; // relative permittivity of SiO2
295  double eps; // permittivity of Si (F/cm)
296  double Ni; // intrinsic concentration of Si (cm^-3)
297  double h_planck; // planck's constant
298  double e_mass; // electron mass
299 
300  // scaling variables:
301  double x0_user; // distance scaling, as set by the user (cm)
302  double C0_user; // concentration scaling, as set by the user (cm^-3)
303  double t0_user; // time scaling, as set by the user (sec)
304 
306 
307  std::map<std::string, DopeInfo *> dopeInfoMap;
308 
309  // photogen, seu variables:
311  double xstart, ystart; // starting location.
312  double xend, yend; // ending location.
313  double intensity;
314  double photoA1;
315  double photoTstart;
316  double photoTstop;
317  double photoTd;
318  double photoTr;
319  double photoTf;
320  double photoPw;
321  double photoPer;
324  std::string photoString;
327 
328  double photoA1_old; // old A1 (at begin of cont. loop)
329  double photoA1_final; // final A1 (at end of cont. loop)
330  double photoA1_orig; // original A1 (at begin of cont. step)
331  double photoA1_ramp; // ramped value of A1 (A1 at current cont. step)
332  double photoA1_ramp_old; // ramped value of A1 (A1 at current cont. step)
333  double photoA1_Delta; // 2-level delta.(between ckt iterations)
334  double photoA1_DeltaC; // continuation delta.(between cont. solves)
335  double maxPhotoDelta; // maximum photogen delta.
337 
338  // continuation parameters:
339  double maxVoltDelta;
342 
343  bool sensOn;
348 
349  std::string mobModelName;
352  std::string bulkMaterial;
354 
357 
358  std::string outputName; // added to remove the Y%PDE% prefix.
359 
360  // inverse fermi integral function functor.
362 
363 protected:
364 
365 private:
366 
367  template <typename T> int sgn(T val)
368  {
369  return (val > T(0)) - (val < T(0));
370  }
371 
372 };
373 
374 //-----------------------------------------------------------------------------
375 // Function : DevicePDEInstance::timeDateStamp_
376 // Purpose : get current date and time and format for .PRINT output
377 // Special Notes : inline
378 // Scope : private
379 // Creator :
380 // Creation Date :
381 //-----------------------------------------------------------------------------
382 inline const std::string DevicePDEInstance::timeDateStamp()
383 {
384  const time_t now = time( NULL );
385  char timeDate[ 80 ];
386 
387  // format for output
388  strftime( timeDate, 80, "TIME='%I:%M:%S %p' DATE='%b %d, %Y' ",
389  localtime( &now ) );
390 
391  return std::string( timeDate );
392 }
393 
394 //-----------------------------------------------------------------------------
395 // Function : DevicePDEInstance::tecplotTimeDateStamp_
396 // Purpose : Get current date and time and format for .PRINT output
397 // Special Notes : tecplot version of timeDateStamp_.
398 // Scope : private
399 // Creator : Eric Keiter, SNL
400 // Creation Date : 9/6/04
401 //-----------------------------------------------------------------------------
402 inline const std::string DevicePDEInstance::tecplotTimeDateStamp()
403 {
404  const time_t now = time( NULL );
405  char timeDate[ 80 ];
406 
407  // format for output
408  strftime( timeDate, 80, "TIME= \" %I:%M:%S %p %b %d, %Y \" ",
409  localtime( &now ) );
410 
411  return std::string( timeDate );
412 }
413 
414 } // namespace Device
415 } // namespace Xyce
416 
418 
419 #endif // Xyce_N_DEV_DevicePDEInstance_h