Xyce  6.1
N_DEV_DopeInfo.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-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_DopeInfo.C,v $
27 //
28 // Purpose : This file contains the details of the dope info class.
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 03/04/08
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.30 $
40 //
41 // Revision Date : $Date: 2015/04/08 19:18:25 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 #include <iostream>
49 
50 // ---------- Xyce Includes ----------
52 #include <N_UTL_Expression.h>
53 #include <N_DEV_DeviceSupport.h>
54 
55 namespace Xyce {
56 namespace Device {
57 
58 template<>
60 {
61  addPar("NMAX", 1.0e+15, &DopeInfo::Nmax);
62  addPar("NMIN", 0.0, &DopeInfo::Nmin);
63  addPar("NMAXCHOP", 1.0e+20, &DopeInfo::Nmax_chop)
64  .setGivenMember(&DopeInfo::Nmax_chopGiven);
65  addPar("XLOC", 0.0, &DopeInfo::xloc);
66  addPar("XMIN", 0.0, &DopeInfo::xmin)
67  .setGivenMember(&DopeInfo::xminGiven);
68  addPar("XMAX", 0.0, &DopeInfo::xmax)
69  .setGivenMember(&DopeInfo::xmaxGiven);
70  addPar("XWIDTH", 1.0e-3, &DopeInfo::xwidth);
71  addPar("YLOC", 0.0, &DopeInfo::yloc);
72  addPar("YMIN", 0.0, &DopeInfo::ymin)
73  .setGivenMember(&DopeInfo::yminGiven);
74  addPar("YMAX", 0.0, &DopeInfo::ymax)
75  .setGivenMember(&DopeInfo::ymaxGiven);
76  addPar("YWIDTH", 1.0e-3, &DopeInfo::ywidth);
77 
78  // Set up map for non-double precision variables:
79  addPar("NAME", std::string("none"), &DopeInfo::name);
80  addPar("FUNCTION", std::string("uniform"), &DopeInfo::funcType);
81  addPar("TYPE", std::string("ntype"), &DopeInfo::type);
82  addPar("FLATX", 0, &DopeInfo::flatX);
83  addPar("FLATY", 0, &DopeInfo::flatY);
84  addPar("SPECIES", std::string("none"), &DopeInfo::speciesName);
85  addPar("FILE", std::string("none"), &DopeInfo::fileName);
86  addPar("EXPRESSION", std::string("none"), &DopeInfo::exprString);
87  addPar("EL2", 0, &DopeInfo::EL2Present);
88 }
89 
91  static ParametricData<DopeInfo> parMap;
92 
93  return parMap;
94 }
95 
96 // ----------------------------------------------------------------------------
97 // Function : DopeInfo::DopeInfo
98 // Purpose : constructor
99 // Special Notes :
100 // Scope : public
101 // Creator : Eric Keiter, SNL
102 // Creation Date : 05/07/05
103 // ----------------------------------------------------------------------------
105  : CompositeParam (getParametricData()),
106  name("reg0"),
107  type("ntype"),
108  funcType("uniform"),
109  speciesName("none"),
110  fileName("none"),
111 
112  EL2Present(0),
113 
114  xmin(0.0),
115  xmax(0.0),
116  xloc(0.0),
117  xwidth(0.0),
118 
119  ymin(0.0),
120  ymax(0.0),
121  yloc(0.0),
122  ywidth(0.0),
123 
124  Nmax(1.0e+15),
125  Nmin(1.0e+11),
126  Nmax_chop(1.0e+99),
127  Nmax_chopGiven(false),
128  flatX(0),
129  flatY(0)
130 {}
131 
132 // ----------------------------------------------------------------------------
133 // Function : DopeInfo::processParam
134 // Purpose :
135 // Special Notes :
136 // Scope : public
137 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
138 // Creation Date : 03/31/03
139 // ----------------------------------------------------------------------------
140 bool DopeInfo::processParam(Param & ndParam, std::string & param, DevicePDEInstance & di)
141 {
142  bool bsuccess = true;
143 
144  return bsuccess;
145 }
146 
147 // ----------------------------------------------------------------------------
148 // Function : DopeInfo::processParams
149 // Purpose :
150 // Special Notes :
151 // Scope : public
152 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
153 // Creation Date : 03/31/03
154 // ----------------------------------------------------------------------------
156 {
157  {
158  ParameterMap::const_iterator p_i = getParameterMap().find(std::string("FUNCTION"));
159  const Descriptor &p = *(*p_i).second;
160 
161  ExtendedString tmp = getValue<std::string, DopeInfo>(*this, p);
162  setValue<std::string, DopeInfo>(*this, p, static_cast<std::string>(tmp.toLower()));
163  }
164 
165  {
166  ParameterMap::const_iterator p_i = getParameterMap().find(std::string("TYPE"));
167  const Descriptor &p = *(*p_i).second;
168 
169  ExtendedString tmp = getValue<std::string, DopeInfo>(*this, p);
170  setValue<std::string, DopeInfo>(*this, p, static_cast<std::string>(tmp.toLower()));
171  }
172 }
173 
174 // ----------------------------------------------------------------------------
175 // Function : DopeInfo::setupInfo
176 // Purpose :
177 // Special Notes :
178 // Scope : public
179 // Creator : Eric Keiter, SNL
180 // Creation Date : 11/20/08
181 // ----------------------------------------------------------------------------
183  std::vector<double> & CVec,
184  std::vector<double> & CdonorVec,
185  std::vector<double> & CacceptorVec,
186  std::vector<double> & xVec,
187  DeviceSupport & devSupport)
188 {
189  int i(0);
190  int NX (CVec.size());
191  splintDopeVec.resize(NX,0.0);
192 
193  double sign = 0.0;
194  if (type == "ptype" || type == "acceptor")
195  {
196  sign = -1.0;
197  }
198  else if (type == "ntype" || type == "donor")
199  {
200  sign = 1.0;
201  }
202 
203  if (funcType == "uniform")
204  {
205  for (i=0;i<NX;++i)
206  {
207  if (xmaxGiven && xminGiven)
208  {
209  if (xVec[i] > xmax || xVec[i] < xmin) // if outside the range, skip
210  {
211  continue;
212  }
213  }
214 
215  CVec[i] += sign*Nmax;
216  splintDopeVec[i] = Nmax;
217  if (type == "ptype" || type == "acceptor")
218  {
219  CacceptorVec[i] += Nmax;
220  }
221  else if (type == "ntype" || type == "donor")
222  {
223  CdonorVec[i] += Nmax;
224  }
225  }
226  }
227  else if (funcType == "gaussian")
228  {
229  double deltaX = fabs(xwidth);
230 
231  double ax = log(Nmax/Nmin)/(deltaX*deltaX);
232  for (i=0;i<NX;++i)
233  {
234  double scalarX = 1.0;
235  double abs_dx;
236 
237  if (given("XLOC") && given("XWIDTH") && deltaX != 0.0)
238  {
239  abs_dx = fabs(xVec[i]-xloc);
240 
241  // if true gaussian, x-section:
242  if (flatX==0)
243  {
244  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
245  }
246  else if (flatX>0) // half-gaussian, x-section:
247  {
248  bool flatReg = (xVec[i] > xloc);
249 
250  if (!flatReg)
251  {
252  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
253  }
254  }
255  else if (flatX<0) // half-gaussian, x-section:
256  {
257  bool flatReg = (xVec[i] < xloc);
258 
259  if (!flatReg)
260  {
261  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
262  }
263  }
264  }
265 
266  CVec[i] += sign*Nmax*scalarX;
267  splintDopeVec[i] = Nmax*scalarX;
268  if (type == "ptype" || type == "acceptor")
269  {
270  CacceptorVec[i] += Nmax*scalarX;
271  }
272  else if (type == "ntype" || type == "donor")
273  {
274  CdonorVec[i] += Nmax*scalarX;
275  }
276  }
277  }
278  else if (funcType == "step")
279  {
280  for (i=0;i<NX;++i)
281  {
282  double x = xVec[i];
283  bool regOn = true;
284 
285  if (given("XLOC"))
286  {
287  if (flatX == 0) regOn = true;
288 
289  if (flatX == -1)
290  {
291  if (x > xloc) regOn = false;
292  else regOn = true;
293  }
294 
295  if (flatX == +1)
296  {
297  if (x < xloc) regOn = false;
298  else regOn = true;
299  }
300  }
301 
302  CVec[i] += (regOn)?(sign*Nmax):(sign*Nmin);
303  splintDopeVec[i] = (regOn)?(Nmax):(Nmin);
304  if (type == "ptype" || type == "acceptor")
305  {
306  CacceptorVec[i] += (regOn)?(Nmax):(sign*Nmin);
307  }
308  else if (type == "ntype" || type == "donor")
309  {
310  CdonorVec[i] += (regOn)?(Nmax):(sign*Nmin);
311  }
312  }
313  }
314  else if (funcType == "expression")
315  {
316  if (exprString == "none")
317  {
318  std::string msg = "Dope Region : ";
319  msg += name;
320  msg += " has specified the expression specification, but not provided an expression.";
321  msg += "\n";
322  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
323  }
324  else
325  {
326  if (DEBUG_DEVICE)
327  {
328  Xyce::dout() << "DopeInfo::setupInfo: exprString = " << exprString << std::endl;
329  }
330  Util::Expression expr;
331  expr.set(exprString);
332 
333  for (i=0;i<NX;++i)
334  {
335  double dopeValue(0.0);
336 
337  expr.set_var(std::string("#X"), xVec[i]);
338  expr.evaluateFunction (dopeValue);
339  CVec[i] += sign*dopeValue;
340  splintDopeVec[i] = dopeValue;
341  if (type == "ptype" || type == "acceptor")
342  {
343  CacceptorVec[i] += dopeValue;
344  }
345  else if (type == "ntype" || type == "donor")
346  {
347  CdonorVec[i] += dopeValue;
348  }
349  }
350  }
351  }
352  else if (funcType == "file")
353  {
354  if (fileName == "none")
355  {
356  std::string msg = "Dope Region : ";
357  msg += name;
358  msg += " has specified the file specification, but not specified a file name.";
359  msg += "\n";
360  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
361  }
362  else
363  {
364  readDopingFile (fileName, xlocVec, dopeVec, y2Vec, devSupport);
365 
366  // if the user has requested that this be truncated to a max value,
367  // do it here:
368  if (Nmax_chopGiven)
369  {
370  int dopeSize=dopeVec.size();
371  for (int id=0;id<dopeSize;++id)
372  {
373  if (dopeVec[id] > Nmax_chop)
374  {
375  dopeVec[id] = Nmax_chop;
376  }
377  }
378  }
379 
380  for (i=0;i<NX;++i)
381  {
382  double xtmp = xVec[i];
383  double dopeValue(0.0);
384  devSupport.splint(xlocVec, dopeVec, y2Vec, xtmp, dopeValue);
385  CVec[i] += sign*dopeValue;
386  splintDopeVec[i] = dopeValue;
387  if (type == "ptype" || type == "acceptor")
388  {
389  CacceptorVec[i] += dopeValue;
390  }
391  else if (type == "ntype" || type == "donor")
392  {
393  CdonorVec[i] += dopeValue;
394  }
395  }
396  }
397  }
398  else
399  {
400  std::string msg = "Unrecognized Dope Region function type: ";
401  msg += funcType;
402  msg += " for region: ";
403  msg += name;
404  msg += "\n";
405  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
406  }
407 
408 }
409 
410 // ----------------------------------------------------------------------------
411 // Function : DopeInfo::setupInfo2d
412 // Purpose :
413 // Special Notes :
414 // Scope : public
415 // Creator : Eric Keiter, SNL
416 // Creation Date : 11/20/08
417 // ----------------------------------------------------------------------------
419  std::vector<double> & CVec,
420  std::vector<double> & CdonorVec,
421  std::vector<double> & CacceptorVec,
422  std::vector<double> & xVec,
423  std::vector<double> & yVec,
424  DeviceSupport & devSupport)
425 {
426  int i(0);
427  int numMeshPoints (CVec.size());
428 
429  double sign = 1.0;
430  if (type == "ptype" || type == "acceptor") sign = -1.0;
431 
432  if (funcType == "uniform")
433  {
434  for (i=0;i<numMeshPoints;++i)
435  {
436 
437  if (xmaxGiven && xminGiven)
438  {
439  if (xVec[i] > xmax || xVec[i] < xmin) // if outside the x-range, skip
440  {
441  continue;
442  }
443  }
444 
445  if (ymaxGiven && yminGiven)
446  {
447  if (yVec[i] > ymax || yVec[i] < ymin) // if outside the y-range, skip
448  {
449  continue;
450  }
451  }
452 
453  CVec[i] += sign*Nmax;
454  if (type == "ptype" || type == "acceptor")
455  {
456  CacceptorVec[i] += Nmax;
457  }
458  else
459  {
460  CdonorVec[i] += Nmax;
461  }
462  }
463  }
464  else if (funcType == "gaussian")
465  {
466  double deltaX = fabs(xwidth);
467  double deltaY = fabs(ywidth);
468 
469  double ax = 0.0;
470  double ay = 0.0;
471 
472  if (deltaX!=0.0)
473  {
474  ax = log(Nmax/Nmin)/(deltaX*deltaX);
475  }
476 
477  if (deltaY!=0.0)
478  {
479  ay = log(Nmax/Nmin)/(deltaY*deltaY);
480  }
481 
482  for (i=0;i<numMeshPoints;++i)
483  {
484  double scalarX = 1.0;
485  double scalarY = 1.0;
486  double abs_dx, abs_dy;
487 
488  if (given("XLOC") && given("XWIDTH") && deltaX != 0.0)
489  {
490  abs_dx = fabs(xVec[i]-xloc);
491 
492  // if true gaussian, x-section:
493  if (flatX==0)
494  {
495  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
496  }
497  else if (flatX>0) // half-guassian, x-section:
498  {
499  bool flatReg = (xVec[i] > xloc);
500 
501  if (!flatReg)
502  {
503  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
504  }
505  }
506  else if (flatX<0) // half-guassian, x-section:
507  {
508  bool flatReg = (xVec[i] < xloc);
509 
510  if (!flatReg)
511  {
512  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
513  }
514  }
515  }
516 
517  if (given("YLOC") && given("YWIDTH") && deltaY != 0.0)
518  {
519  abs_dy = fabs(yVec[i]-yloc);
520  // if true gaussian, y-section:
521  if (flatY==0)
522  {
523  scalarY *= ngdep2(0.0, abs_dy, 1.0, ay);
524  }
525  else if (flatY>0) // half-guassian, y-section:
526  {
527  bool flatReg = (yVec[i] > yloc);
528 
529  if (!flatReg)
530  {
531  scalarY *= ngdep2(0.0, abs_dy, 1.0, ay);
532  }
533  }
534  else if (flatY<0) // half-guassian, y-section:
535  {
536  bool flatReg = (yVec[i] < yloc);
537 
538  if (!flatReg)
539  {
540  scalarY *= ngdep2(0.0, abs_dy, 1.0, ay);
541  }
542  }
543  }
544 
545  CVec[i] += sign*Nmax*scalarX*scalarY;
546 
547  if (type == "ptype" || type == "acceptor")
548  {
549  CacceptorVec[i] += Nmax*scalarX*scalarY;
550  }
551  else
552  {
553  CdonorVec[i] += Nmax*scalarX*scalarY;
554  }
555  }
556  }
557  else if (funcType == "step")
558  {
559  for (i=0;i<numMeshPoints;++i)
560  {
561  double x = xVec[i];
562  double y = yVec[i];
563  bool regOnX = true;
564  bool regOnY = true;
565 
566  if (given("YLOC"))
567  {
568  if (flatY == 0) regOnY = true;
569 
570  if (flatY == -1)
571  {
572  if(y > yloc) regOnY = false;
573  else regOnY = true;
574  }
575 
576  if (flatY == +1)
577  {
578  if (y < yloc) regOnY = false;
579  else regOnY = true;
580  }
581  }
582 
583  if (given("XLOC"))
584  {
585  if (flatX == 0) regOnX = true;
586 
587  if (flatX == -1)
588  {
589  if(x > xloc) regOnX = false;
590  else regOnX = true;
591  }
592 
593  if (flatX == +1)
594  {
595  if (x < xloc) regOnX = false;
596  else regOnX = true;
597  }
598  }
599  bool regOn = (regOnX && regOnY);
600 
601  CVec[i] += (regOn)?(sign*Nmax):(sign*Nmin);
602  if (type == "ptype" || type == "acceptor")
603  {
604  CacceptorVec[i] += (regOn)?(Nmax):(sign*Nmin);
605  }
606  else
607  {
608  CdonorVec[i] += (regOn)?(Nmax):(sign*Nmin);
609  }
610  }
611  }
612  else
613  {
614  std::string msg = "Unrecognized Dope Region function type: ";
615  msg += funcType;
616  msg += " for region: ";
617  msg += name;
618  msg += "\n";
619  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
620  }
621 
622 }
623 
624 // ----------------------------------------------------------------------------
625 // Function : DopeInfo::nsdep
626 // Purpose : This function returns an approximate deposition profile
627 // of a step implant driven in an inert environment.
628 // Special Notes :
629 // 1 W/2 + x W/2 - x
630 // nsdep(x,W,Dt) = - (erf(---------) + erf(----------))
631 // 2 2*sqrt(Dt) 2*sqrt(Dt)
632 //
633 //
634 // Scope : public
635 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
636 // Creation Date : 4/25/02
637 // ----------------------------------------------------------------------------
638 double DopeInfo::nsdep(double x, double W, double Dt)
639 {
640  double D = 2.0 * sqrt(Dt);
641  double Wh = W / 2.0;
642  return 0.5 * (erf((Wh + x)/D) + erf((Wh - x)/D));
643 }
644 
645 // ----------------------------------------------------------------------------
646 // Function : DopeInfo::ngdep
647 //
648 // Purpose : This function returns an approximate Gaussian deposition.
649 //
650 // Adapted from a similar function in SGF.
651 //
652 // Special Notes : This function is a little flakey, in that it assumes
653 // that we're using a cylindrical geomtry
654 // (x = radius, y = height.) It also assumes that the (0,0)
655 // origin is in the upper-left-hand corner of the mesh.
656 //
657 // So, y=0.0 is the upper surface of the device, and the
658 // implant is coming from the top (above y=0.0). Hence,
659 // the (y>0) conditional.
660 //
661 // Also, the width parameter (W), is set up to be a
662 // diameter about x=0, which is the reason for the 0.5*W -
663 // half of this diameter will impact this radius.
664 //
665 // The implant is completely flat and constant in the
666 // x-direction, as long as fabs(x) is less than W/2.0.
667 // Beyond W/2.0, the gaussian profile kicks in.
668 //
669 // The parameters ax and ay are scaling parameters, and
670 // correspond to how much you want the doping to vary with
671 // space. A typical value for either can be set up as:
672 //
673 // Ax = ln (Nhi / Nlo)/(Rx*Rx)
674 //
675 // where:
676 //
677 // Nhi = the max. level of doping
678 // Nlo = the min. level of doping
679 // Rx = distance over which this doping should vary.
680 //
681 // Nhi/Nlo = 10^N, where N = # of orders of magnitude
682 // that should vary between x=0 and x=Rx.
683 //
684 // Scope : public
685 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
686 // Creation Date : 4/25/02
687 // ----------------------------------------------------------------------------
688 double DopeInfo::ngdep(double x, double y, double W, double ax, double ay)
689 {
690  double xprime = fabs(x) - (0.5 * W);
691  return ((xprime <= 0.0) ? 1.0 : exp(-ax*xprime*xprime))*
692  ((y > 0.0) ? 0.0 : exp(-ay*y*y));
693 }
694 
695 // ----------------------------------------------------------------------------
696 // Function : DopeInfo::ngdep2
697 //
698 // Purpose : This function returns an approximate Gaussian deposition.
699 //
700 // Special Notes : This function is a modification of the original ngdep
701 // (see above), and I designed it to address some of the
702 // peculiarities of ngdep.
703 //
704 // (1) I've gotten rid of the width, W. I'm just
705 // going to assume that whoever is calling this function
706 // can set that(the constant region) up on their own.
707 //
708 // (2) I've removed the conditionals cause things to
709 // be set to zero, or one, or whatever, if you are on one
710 // side or another of the suface. I'm assuming that
711 // whoever calls this function can do that themselves, if
712 // they need to.
713 //
714 // (3) I've removed the stuff that sets the retVal to zero
715 // for y>0. Again, this is the user's problem.
716 //
717 // ax and ay mean the same as they did for the original
718 // ngdep. (see above).
719 //
720 // It is possible to use this for the 1D case, pretty
721 // easily. Set the xflag to false, hold y fixed at zero,
722 // and have x correspond to the 1D mesh locations. (or, set
723 // xflag to true, hold x fixed at zero, and let y
724 // correspond to 1D mesh locations - either way).
725 //
726 // Scope : public
727 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
728 // Creation Date : 03/28/03
729 // ----------------------------------------------------------------------------
730 double DopeInfo::ngdep2(double x, double y, double ax, double ay)
731 {
732  double retVal = exp(-ax*x*x)* exp(-ay*y*y);
733  return retVal;
734 }
735 
736 // ----------------------------------------------------------------------------
737 // Function : DopeInfo::erf
738 // Purpose : This function returns the error function.
739 // Special Notes :
740 // Scope : public
741 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
742 // Creation Date : 4/25/02
743 // ----------------------------------------------------------------------------
744 double DopeInfo::erf(double x)
745 {
746  double t1 = 1.0 / (1.0 + 0.3275911 * fabs(x));
747  double t2 = t1 * t1;
748  double t3 = t2 * t1;
749  double t4 = t3 * t1;
750  double t5 = t4 * t1;
751  double result = 1.0 - (0.254829592*t1 - 0.284496736*t2 + 1.421413741*t3 -
752  1.453152027*t4 + 1.061405429*t5) * exp(-x*x);
753  return (x < 0.0) ? -result : result;
754 }
755 
756 //-----------------------------------------------------------------------------
757 // Function : DopeInfo::readDopingFile
758 // Purpose :
759 // Special Notes :
760 // Scope : public
761 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
762 // Creation Date : 11/10/07
763 //-----------------------------------------------------------------------------
765  std::string & filename,
766  std::vector<double> & xloc,
767  std::vector<double> & nvec,
768  std::vector<double> & y2,
769  DeviceSupport & devSupport)
770 {
771  std::ifstream input;
772  double x_loc(0.0);
773  double value(0.0);
774  xloc.clear();
775  nvec.clear();
776  y2.clear();
777 
778  input.open( filename.c_str(), std::ios::in );
779  if ( input.good() )
780  {
781  bool endOfFile = input.eof();
782  while (!endOfFile)
783  {
784  endOfFile = input.eof();
785  if (!endOfFile)
786  {
787  input >> x_loc;
788  }
789  else
790  {
791  break;
792  }
793 
794  endOfFile = input.eof();
795  if (!endOfFile)
796  {
797  input >> value;
798  }
799  else
800  {
801  break;
802  }
803  xloc.push_back(x_loc);
804  nvec.push_back(value);
805  }
806  input.close();
807  y2.resize(xloc.size(),0.0);
808  devSupport.spline (xloc, nvec, y2);
809  }
810  else
811  {
812  std::string msg = "Error: Cannot open doping file: " + filename;
813  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
814  }
815 }
816 
817 //-----------------------------------------------------------------------------
818 // Function : DopeInfo::readDopingFile
819 // Purpose :
820 // Special Notes : This version assumes 2 dopants are in the file, P and N.
821 // Scope : public
822 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
823 // Creation Date : 11/10/07
824 //-----------------------------------------------------------------------------
826  std::string & filename,
827  std::vector<double> & xloc,
828  std::vector<double> & nvec,
829  std::vector<double> & y2_n,
830  std::vector<double> & pvec,
831  std::vector<double> & y2_p,
832  DeviceSupport & devSupport)
833 {
834  std::ifstream input;
835  double x_loc(0.0);
836  double value1(0.0);
837  double value2(0.0);
838  xloc.clear();
839  nvec.clear();
840  pvec.clear();
841  y2_n.clear();
842  y2_p.clear();
843 
844  input.open( filename.c_str(), std::ios::in );
845  if ( input.good() )
846  {
847  bool endOfFile = input.eof();
848  while (!endOfFile)
849  {
850  endOfFile = input.eof();
851  if (!endOfFile)
852  {
853  input >> x_loc;
854  }
855  else
856  {
857  break;
858  }
859 
860  endOfFile = input.eof();
861  if (!endOfFile)
862  {
863  input >> value1;
864  }
865  else
866  {
867  break;
868  }
869  endOfFile = input.eof();
870  if (!endOfFile)
871  {
872  input >> value2;
873  }
874  else
875  {
876  break;
877  }
878 
879  xloc.push_back(x_loc);
880  nvec.push_back(value1);
881  pvec.push_back(value2);
882 
883  //Xyce::dout() << "x="<<x_loc<<" value1="<<value1<<" value2="<<value2<<std::endl;
884  }
885  input.close();
886  y2_n.resize(xloc.size(),0.0);
887  y2_p.resize(xloc.size(),0.0);
888  devSupport.spline (xloc, nvec, y2_n);
889  devSupport.spline (xloc, pvec, y2_p);
890  }
891  else
892  {
893  std::string msg = "Error: Cannot open doping file: " + filename;
894  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
895  }
896 }
897 
898 
899 
900 
901 
902 // ----------------------------------------------------------------------------
903 // Function : DopeInfo::setupInfo
904 // Purpose :
905 // Special Notes : Hack for support of EL2
906 // Scope : public
907 // Creator : Jason Verley, SNL
908 // Creation Date : 11/20/08
909 // ----------------------------------------------------------------------------
911  std::vector<double> & CVec,
912  std::vector<double> & CdonorVec,
913  std::vector<double> & CacceptorVec,
914  std::vector<double> & xVec,
915  std::vector<bool> & el2Vec,
916  DeviceSupport & devSupport)
917 {
918  int i(0);
919  int NX (CVec.size());
920  splintDopeVec.resize(NX,0.0);
921 
922  double sign = 0.0;
923  if (type == "ptype" || type == "acceptor")
924  {
925  sign = -1.0;
926  }
927  else if (type == "ntype" || type == "donor")
928  {
929  sign = 1.0;
930  }
931 
932  if (EL2Present > 0)
933  {
934  for (i=0;i<NX;++i)
935  {
936  if (xmaxGiven && xminGiven)
937  {
938  if (xVec[i] > xmax || xVec[i] < xmin) // if outside the range, skip
939  {
940  continue;
941  }
942  }
943  el2Vec[i] = true;
944  }
945  }
946 
947  if (funcType == "uniform")
948  {
949  for (i=0;i<NX;++i)
950  {
951  if (xmaxGiven && xminGiven)
952  {
953  if (xVec[i] > xmax || xVec[i] < xmin) // if outside the range, skip
954  {
955  continue;
956  }
957  }
958 
959  CVec[i] += sign*Nmax;
960  splintDopeVec[i] = Nmax;
961  if (type == "ptype" || type == "acceptor")
962  {
963  CacceptorVec[i] += Nmax;
964  }
965  else if (type == "ntype" || type == "donor")
966  {
967  CdonorVec[i] += Nmax;
968  }
969  }
970  }
971  else if (funcType == "gaussian")
972  {
973  double deltaX = fabs(xwidth);
974 
975  double ax = log(Nmax/Nmin)/(deltaX*deltaX);
976  for (i=0;i<NX;++i)
977  {
978  double scalarX = 1.0;
979  double abs_dx;
980 
981  if (given("XLOC") && given("XWIDTH") && deltaX != 0.0)
982  {
983  abs_dx = fabs(xVec[i]-xloc);
984 
985  // if true gaussian, x-section:
986  if (flatX==0)
987  {
988  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
989  }
990  else if (flatX>0) // half-gaussian, x-section:
991  {
992  bool flatReg = (xVec[i] > xloc);
993 
994  if (!flatReg)
995  {
996  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
997  }
998  }
999  else if (flatX<0) // half-gaussian, x-section:
1000  {
1001  bool flatReg = (xVec[i] < xloc);
1002 
1003  if (!flatReg)
1004  {
1005  scalarX *= ngdep2(abs_dx, 0.0, ax, 1.0);
1006  }
1007  }
1008  }
1009 
1010  CVec[i] += sign*Nmax*scalarX;
1011  splintDopeVec[i] = Nmax*scalarX;
1012  if (type == "ptype" || type == "acceptor")
1013  {
1014  CacceptorVec[i] += Nmax*scalarX;
1015  }
1016  else if (type == "ntype" || type == "donor")
1017  {
1018  CdonorVec[i] += Nmax*scalarX;
1019  }
1020  }
1021  }
1022  else if (funcType == "step")
1023  {
1024  for (i=0;i<NX;++i)
1025  {
1026  double x = xVec[i];
1027  bool regOn = true;
1028 
1029  if (given("XLOC"))
1030  {
1031  if (flatX == 0) regOn = true;
1032 
1033  if (flatX == -1)
1034  {
1035  if (x > xloc) regOn = false;
1036  else regOn = true;
1037  }
1038 
1039  if (flatX == +1)
1040  {
1041  if (x < xloc) regOn = false;
1042  else regOn = true;
1043  }
1044  }
1045 
1046  CVec[i] += (regOn)?(sign*Nmax):(sign*Nmin);
1047  splintDopeVec[i] = (regOn)?(Nmax):(Nmin);
1048  if (type == "ptype" || type == "acceptor")
1049  {
1050  CacceptorVec[i] += (regOn)?(Nmax):(sign*Nmin);
1051  }
1052  else if (type == "ntype" || type == "donor")
1053  {
1054  CdonorVec[i] += (regOn)?(Nmax):(sign*Nmin);
1055  }
1056  }
1057  }
1058  else if (funcType == "expression")
1059  {
1060  if (exprString == "none")
1061  {
1062  std::string msg = "Dope Region : ";
1063  msg += name;
1064  msg += " has specified the expression specification, but not provided an expression.";
1065  msg += "\n";
1066  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
1067  }
1068  else
1069  {
1070  if (DEBUG_DEVICE)
1071  {
1072  Xyce::dout() << "DopeInfo::setupInfo: exprString = " << exprString << std::endl;
1073  }
1074  Util::Expression expr;
1075  expr.set(exprString);
1076 
1077  for (i=0;i<NX;++i)
1078  {
1079  double dopeValue(0.0);
1080 
1081  expr.set_var(std::string("#X"), xVec[i]);
1082  expr.evaluateFunction (dopeValue);
1083  CVec[i] += sign*dopeValue;
1084  splintDopeVec[i] = dopeValue;
1085  if (type == "ptype" || type == "acceptor")
1086  {
1087  CacceptorVec[i] += dopeValue;
1088  }
1089  else if (type == "ntype" || type == "donor")
1090  {
1091  CdonorVec[i] += dopeValue;
1092  }
1093  }
1094  }
1095  }
1096  else if (funcType == "file")
1097  {
1098  if (fileName == "none")
1099  {
1100  std::string msg = "Dope Region : ";
1101  msg += name;
1102  msg += " has specified the file specification, but not specified a file name.";
1103  msg += "\n";
1104  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
1105  }
1106  else
1107  {
1108  readDopingFile (fileName, xlocVec, dopeVec, y2Vec, devSupport);
1109 
1110  // if the user has requested that this be truncated to a max value,
1111  // do it here:
1112  if (Nmax_chopGiven)
1113  {
1114  int dopeSize=dopeVec.size();
1115  for (int id=0;id<dopeSize;++id)
1116  {
1117  if (dopeVec[id] > Nmax_chop)
1118  {
1119  dopeVec[id] = Nmax_chop;
1120  }
1121  }
1122  }
1123 
1124  for (i=0;i<NX;++i)
1125  {
1126  double xtmp = xVec[i];
1127  double dopeValue(0.0);
1128  devSupport.splint(xlocVec, dopeVec, y2Vec, xtmp, dopeValue);
1129  CVec[i] += sign*dopeValue;
1130  splintDopeVec[i] = dopeValue;
1131  if (type == "ptype" || type == "acceptor")
1132  {
1133  CacceptorVec[i] += dopeValue;
1134  }
1135  else if (type == "ntype" || type == "donor")
1136  {
1137  CdonorVec[i] += dopeValue;
1138  }
1139  }
1140  }
1141  }
1142  else
1143  {
1144  std::string msg = "Unrecognized Dope Region function type: ";
1145  msg += funcType;
1146  msg += " for region: ";
1147  msg += name;
1148  msg += "\n";
1149  N_ERH_ErrorMgr::report ( N_ERH_ErrorMgr::DEV_FATAL,msg);
1150  }
1151 
1152 }
1153 
1154 } // namespace Device
1155 } // namespace Xyce
std::vector< double > dopeVec
static double ngdep(double x, double y, double W, double ax, double ay)
static ParametricData< DopeInfo > & getParametricData()
static double ngdep2(double x, double y, double ax, double ay)
static double nsdep(double x, double W, double Dt)
Pure virtual class to augment a linear system.
static void readDopingFile(std::string &filename, std::vector< double > &xloc, std::vector< double > &nvec, std::vector< double > &y2, DeviceSupport &devSup)
const T & value(const ParameterBase &entity, const Descriptor &descriptor)
Returns the value of the parameter for the entity.
Definition: N_DEV_Pars.h:1224
void splint(std::vector< double > &xa, std::vector< double > &ya, std::vector< double > &y2a, double x_position, double &y_spline)
void spline(std::vector< double > &x, std::vector< double > &y, std::vector< double > &y2)
bool given(const std::string &parameter_name) const
given returns true if the value was specified in the netlist (not defaulted).
std::vector< double > xlocVec
void setupInfo(std::vector< double > &CVec, std::vector< double > &CdonorVec, std::vector< double > &CacceptorVec, std::vector< double > &xVec, DeviceSupport &devSup)
std::vector< double > y2Vec
void setupInfo2d(std::vector< double > &CVec, std::vector< double > &CdonorVec, std::vector< double > &CacceptorVec, std::vector< double > &xVec, std::vector< double > &yVec, DeviceSupport &devSup)
Class Descriptor describes the parameters stored in the ParametricData parameter map.
Definition: N_DEV_Pars.h:546
static double erf(double x)
bool processParam(Param &ndParam, std::string &param, DevicePDEInstance &di)
ParametricData()
Constructs the parameter data map.
Definition: N_DEV_Pars.h:1392
std::vector< double > splintDopeVec
#define W
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
void processParams()
processParams post processes the parameters that have been set in the object of the derived class...
CompositeParam is the base class for classes that wish to only manage the processing of parameter dat...
const ParameterMap & getParameterMap() const
getParameterMap returns the parameter map which describes the parameters.