changeset 11745:a6f6a1deefbb octave-forge

cleanup mods
author cdf
date Wed, 05 Jun 2013 05:28:04 +0000
parents d995950329f1
children 94f687098b2e
files extra/secs1d/inst/demos/simple_diode_tran_noscale.m extra/secs1d/inst/demos/simple_diode_tran_noscale_res.m extra/secs1d/inst/demos/thyristor_tran_noscale.m extra/secs1d/inst/secs1d_impact_ionization_noscale.m extra/secs1d/inst/secs1d_newton_res.m
diffstat 5 files changed, 149 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extra/secs1d/inst/demos/simple_diode_tran_noscale.m	Wed Jun 05 05:28:04 2013 +0000
@@ -0,0 +1,91 @@
+% physical constants and parameters
+constants = secs1d_physical_constants_fun ();
+material  = secs1d_silicon_material_properties_fun (constants);
+
+% geometry
+Nelements = 1000;
+L  = 1e-6;          % [m] 
+xm = L/2;
+device.W = 1e-6 * 1e-6;
+device.x  = linspace (0, L, Nelements+1)';
+device.sinodes = [1:length(device.x)];
+
+% doping profile [m^{-3}]
+device.Na = 1e23 * (device.x <= xm);
+device.Nd = 1e23 * (device.x >  xm);
+device.R = [0; 0];
+
+% avoid zero doping
+device.D  = device.Nd - device.Na;  
+
+% time span for simulation
+tmin  = 0;
+tmax  = 100;
+tspan = [tmin, tmax];
+
+Fn = Fp = zeros (size (device.x));
+
+%% bandgap narrowing correction
+device.ni = (material.ni) * exp (secs1d_bandgap_narrowing_model
+                                 (device.Na, device.Nd) / constants.Vth); 
+
+%% carrier lifetime
+device.tp = secs1d_carrier_lifetime_noscale (device.Na, device.Nd, 'p');
+device.tn = secs1d_carrier_lifetime_noscale (device.Na, device.Nd, 'n');
+
+% initial guess for n, p, V, phin, phip
+p = ((abs(device.D) + sqrt (abs(device.D) .^ 2 + 4 * device.ni .^2)) .* ...
+     (device.D <= 0)) / 2 + 2 * device.ni.^2 ./ ...
+    (abs(device.D) + sqrt (abs(device.D) .^ 2 + 4 * device.ni .^2)) .* ...
+    (device.D > 0);
+
+n = ((abs(device.D) + sqrt (abs(device.D) .^ 2 + 4 * device.ni .^2)) .* ...
+     (device.D > 0)) / 2 + 2 * device.ni.^2 ./ ...
+    (abs(device.D) + sqrt (abs(device.D) .^ 2 + 4 * device.ni .^2)) .* ...
+    (device.D <= 0);
+
+V = Fn + constants.Vth * log (n ./ device.ni);
+
+function fn = vbcs_1 (t);
+  fn    = [0; 0];
+  fn(2) = -t;
+endfunction
+
+function fp = vbcs_2 (t);
+  fp    = [0; 0];
+  fp(2) = -t;
+endfunction
+
+vbcs = {@vbcs_1, @vbcs_2};
+
+% tolerances for convergence checks
+algorithm.toll       = 1e-5;
+algorithm.ltol       = 1e-10;
+algorithm.maxit      = 100;
+algorithm.lmaxit     = 100;
+algorithm.ptoll      = 1e-12;
+algorithm.pmaxit     = 1000;
+algorithm.colscaling = [10 1e21 1e21 1];
+algorithm.rowscaling = [1  1e20 1e20 1];
+algorithm.maxnpincr  = 1e-2;
+
+%% initial guess via stationary simulation
+[nin, pin, Vin, Fnin, Fpin, Jn, Jp, it, res] = secs1d_dd_gummel_map_noscale ...
+    (device, material, constants, algorithm, V, n, p, Fn, Fp);  
+
+close all; semilogy (device.x, nin .* pin, 'x-'); pause
+
+%% (pseudo)transient simulation
+[V, n, p, Fn, Fp, Jn, Jp, Itot, tout] = secs1d_newton (device, material, constants, algorithm,
+                                                       Vin, nin, pin, tspan, @vbcs_1);
+
+dV   = diff (V, [], 1);
+dx   = diff (device.x);
+E    = -dV ./ dx;
+   
+vvector  = Fn(end, :);
+ivector  = Itot (2, :);
+
+plotyy (tout, vvector, tout, ivector)
+drawnow
+   
--- a/extra/secs1d/inst/demos/simple_diode_tran_noscale_res.m	Wed Jun 05 05:23:23 2013 +0000
+++ b/extra/secs1d/inst/demos/simple_diode_tran_noscale_res.m	Wed Jun 05 05:28:04 2013 +0000
@@ -3,7 +3,7 @@
 material  = secs1d_silicon_material_properties_fun (constants);
 
 % geometry
-Nelements = 19;
+Nelements = 3000;
 L  = 1e-6;          % [m] 
 xm = L/2;
 device.W = 1e-6 * 1e-6;
@@ -11,15 +11,15 @@
 device.sinodes = [1:length(device.x)];
 
 % doping profile [m^{-3}]
-device.Na = 1e21 * (device.x <= xm);
-device.Nd = 1e21 * (device.x >  xm);
+device.Na = 1e23 * exp ( - .5 * device.x.^2 / xm^2);
+device.Nd = 1e23 * exp ( - .5 * (device.x - L) .^2 / xm^2);
 
 % avoid zero doping
 device.D  = device.Nd - device.Na;  
 
 % time span for simulation
 tmin  = 0;
-tmax  = 100;
+tmax  = 10;
 tspan = [tmin, tmax];
 
 Fn = Fp = zeros (size (device.x));
@@ -46,30 +46,30 @@
 V = Fn + constants.Vth * log (n ./ device.ni);
 
 function [g, j] = vbcs (t, dt);
-  g = -[1; 1];
-  j = [t 0];
+  g = -[10; 10];
+  j = [t*10 0];
 endfunction
 
 % tolerances for convergence checks
-algorithm.toll       = 1e-5;
+algorithm.toll       = 1e-7;
 algorithm.ltol       = 1e-10;
-algorithm.maxit      = 100;
+algorithm.maxit      = 5;
 algorithm.lmaxit     = 100;
 algorithm.ptoll      = 1e-12;
 algorithm.pmaxit     = 1000;
-algorithm.colscaling = [10 1e21 1e21 1];
-algorithm.rowscaling = [1  1e20 1e20 1];
-algorithm.maxnpincr  = 1e-2;
+algorithm.colscaling = [10 1e21 1e21 .1];
+algorithm.rowscaling = [1  1e-7 1e-7 .1];
+algorithm.maxnpincr  = 1e-3;
 
 %% initial guess via stationary simulation
 [nin, pin, Vin, Fnin, Fpin, Jn, Jp, it, res] = secs1d_dd_gummel_map_noscale ...
     (device, material, constants, algorithm, V, n, p, Fn, Fp);  
 
-close all; semilogy (device.x, nin .* pin, 'x-'); pause
+close all; secs1d_logplot (device.x, device.D, 'x-'); pause
 
 %% (pseudo)transient simulation
-[V, n, p, Fn, Fp, Jn, Jp, Itot, tout] = secs1d_newton (device, material, constants, algorithm,
-                                                       Vin, nin, pin, tspan, @vbcs);
+[V, n, p, Fn, Fp, Jn, Jp, Itot, tout] = secs1d_newton_res (device, material, constants, algorithm,
+                                                           Vin, nin, pin, tspan, @vbcs);
 
 dV   = diff (V, [], 1);
 dx   = diff (device.x);
--- a/extra/secs1d/inst/demos/thyristor_tran_noscale.m	Wed Jun 05 05:23:23 2013 +0000
+++ b/extra/secs1d/inst/demos/thyristor_tran_noscale.m	Wed Jun 05 05:28:04 2013 +0000
@@ -79,9 +79,9 @@
 algorithm.ptoll = 1e-12;
 algorithm.pmaxit = 100;
 algorithm.maxnpincr = constants.Vth;
-algorithm.colscaling = [10 1e23 1e23];
-algorithm.rowscaling = [1e6 1e23 1e23];
-algorithm.maxnpincr = constants.Vth;
+algorithm.colscaling = [1 1e23 1e23];
+algorithm.rowscaling = [1 1e7 1e7];
+algorithm.maxnpincr = constants.Vth / 10;
 
 logplot = @(x) asinh (x/2) / log(10);
 close all; plot (device.x, logplot (device.D)); 
@@ -105,7 +105,7 @@
 %% initial guess via (pseudo)transient simulation
 [n, p, V, Fn, Fp, Jn, Jp, t, it, res] = ...
     secs1d_tran_dd_newton_noscale (device, material, constants, algorithm,
-                               Vin, nin, pin, Fn, Fp, tspan, vbcs);
+                                       Vin, nin, pin, Fn, Fp, tspan, vbcs);
 
 Vin = V(:, end);
 nin = n(:, end);
@@ -115,12 +115,12 @@
 
 function fn = vbcs_1 (t);
   fn = [0; 0];
-  fn(2) = -10*t;
+  fn(2) = -10*2*t/7;
 endfunction
 
 function fp = vbcs_2 (t);
   fp = [0; 0];
-  fp(2) = -10*t;
+  fp(2) = -10*2*t/7;
 endfunction
 
 vbcs = {@vbcs_1, @vbcs_2};
@@ -157,8 +157,8 @@
 
 [n, p, V, Fn, Fp, Jnpos, Jppos, t, it, res] = ...
     secs1d_tran_dd_newton_noscale (device, material, constants, algorithm,
-                                   Vin, nin, pin, 
-                                   Fnin, Fpin, tspan, vbcs);
+                                       Vin, nin, pin, 
+                                       Fnin, Fpin, tspan, vbcs);
 
 vvectorpos  = Fn(end, :);
 ivectorpos  = (Jnpos(end, :) + Jppos(end, :));
--- a/extra/secs1d/inst/secs1d_impact_ionization_noscale.m	Wed Jun 05 05:23:23 2013 +0000
+++ b/extra/secs1d/inst/secs1d_impact_ionization_noscale.m	Wed Jun 05 05:28:04 2013 +0000
@@ -16,7 +16,8 @@
 %% You should have received a copy of the GNU General Public License
 %% along with SECS1D; If not, see <http://www.gnu.org/licenses/>.
 
-%% II = secs1d_impact_ionization_noscale (E, Jn, Jp)
+%% II = secs1d_impact_ionization_noscale ...
+%%      (device, material, constants, algorithm, E, Jn, Jp, V, n, p, Fn, Fp)
 
 function    II = secs1d_impact_ionization_noscale ...
       (device, material, constants, algorithm, E, Jn, Jp, V, n, p, Fn, Fp)
--- a/extra/secs1d/inst/secs1d_newton_res.m	Wed Jun 05 05:23:23 2013 +0000
+++ b/extra/secs1d/inst/secs1d_newton_res.m	Wed Jun 05 05:28:04 2013 +0000
@@ -4,9 +4,11 @@
   Nnodes = numel (device.x);
   dt = (tspan(2) - tspan(1)) / 20;  
   t(tstep = 1) = tspan (1);
-  [V, n, p] = deal (Vin, nin, pin);
+  [V, n, p] = deal (Vin, nin, pin);  
+  F = V([1 end], 1) - constants.Vth * log (n([1 end], 1) ...
+                                           ./ device.ni([1 end], :));
   M = bim1a_reaction (device.x, 1, 1);
-
+  
   while (t < tspan(2))
 
     reject = false;        
@@ -15,8 +17,8 @@
 
     [gi, ji] = va (t, dt);
     [V0, n0, p0, F0] = predict (device, material, constants, ...
-                                algorithm, V, n, p, tstep, tout, gi, ji);
-
+                                algorithm, V, n, p, F, tstep, tout, gi, ji);
+    
     [V2, n2, p2, F2] = deal (V0, n0, p0, F0);
 
     for in = 1 : algorithm.maxit
@@ -58,8 +60,8 @@
       ## else
 
       J = [([algorithm.colscaling(1)*jac{1,1}, ...
-             algorithm.colscaling(2)*jac{1,2}(2:end-1, 2:end-1), ...
-             algorithm.colscaling(3)*jac{1,3}(2:end-1, 2:end-1), ...
+             algorithm.colscaling(2)*jac{1,2}(:, 2:end-1), ...
+             algorithm.colscaling(3)*jac{1,3}(:, 2:end-1), ...
              algorithm.colscaling(4)*jac{1,4}]/algorithm.rowscaling(1)); ...                        
              ##                   
            ([algorithm.colscaling(1)*jac{2,1}(2:end-1, :), ...
@@ -85,10 +87,10 @@
 
       delta = - J \ f;
 
-      dV = delta                             * algorithm.colscaling(1);
+      dV = delta (1:Nnodes)                  * algorithm.colscaling(1);
       dn = delta (Nnodes+1:2*(Nnodes)-2)     * algorithm.colscaling(2);
       dp = delta (2*(Nnodes)-1:3*(Nnodes)-4) * algorithm.colscaling(3);
-      dF = delta (3*(Nnodes)-4:end)          * algorithm.colscaling(4);
+      dF = delta (3*(Nnodes)-3:end)          * algorithm.colscaling(4);
 
       ## endif
 
@@ -110,7 +112,7 @@
         tkp = .9 * min (p1(2:end-1) ./ abs (dp))
       endif
 
-      tk = min ([tkv, tkn, tkp])
+      tk = min ([tkv, tkn, tkp]);
       if (tk <= 0)
         error ("relaxation parameter too small")
       endif
@@ -173,8 +175,7 @@
 
       Fp(:, tstep) = V2 + constants.Vth * log (p2 ./ device.ni);
       Fn(:, tstep) = V2 - constants.Vth * log (n2 ./ device.ni);        
-      [V(:, tstep), n(:, tstep), p(:, tstep), F(:, tstep)] = ...
-      deal (V2, n2, p2, F);
+      [V(:, tstep), n(:, tstep), p(:, tstep), F(:, tstep)] = deal (V2, n2, p2, F2);
 
       [mobilityn, mobilityp] = compute_mobilities ...
           (device, material, constants, algorithm, V2, n2, p2);  
@@ -227,8 +228,8 @@
   
   A11 = bim1a_laplacian (device.x, epsilon, 1);
   res{1} = A11 * V + bim1a_rhs (device.x, 1, constants.q * (n - p - device.D));
-  res{1}(1) = A11(1,1) (V(1) + constants.Vth*log(p(1)./device.ni(1))-F(1));
-  res{1}(end) = A11(end,end) (V(end)+constants.Vth*log(p(end)./device.ni(end))-F(end));
+  res{1}(1) = A11(1,1) * (V(1) + constants.Vth*log(p(1)./device.ni(1))-F(1));
+  res{1}(end) = A11(end,end) * (V(end)+constants.Vth*log(p(end)./device.ni(end))-F(end));
 
   A22 = bim1a_advection_diffusion ...
       (device.x, mobilityn * constants.Vth, 1, 1, V / constants.Vth);
@@ -240,17 +241,20 @@
 
 
   I1  = - constants.q * A22(1,:) * n + constants.q * A33(1,:) * p;
-  I1 += constants.e0 * material.esir * ...
-        ((V(2, tstep) - V(1, tstep)) -
-         (V(2, tstep-1) - V(1, tstep-1))) / ...
-        (device.x(2) - device.x(1));
-  I1 *= device.W;
+  I2  = - constants.q * A22(end,:) * n + constants.q * A33(end,:) * p;
+  
+  if (columns (V) >= 2)
+    I1 += constants.e0 * material.esir * ...
+          ((V(2, end) - V(1, end)) -
+           (V(2, end-1) - V(1, end-1))) / ...
+          (device.x(2) - device.x(1));
+    I2 += constants.e0 * material.esir * ...
+          ((V(end, end) - V(end-1, end)) -
+           (V(end, end-1) - V(end-1, end-1))) / ...
+          (device.x(end) - device.x(end-1));
+  endif
 
-  I2  = - constants.q * A22(end,:) * n + constants.q * A33(end,:) * p;
-  I2 += constants.e0 * material.esir * ...
-        ((V(end, tstep) - V(end-1, tstep)) -
-         (V(end, tstep-1) - V(end-1, tstep-1))) / ...
-        (device.x(end) - device.x(end-1));
+  I1 *= device.W;
   I2 *= device.W;
 
   res{4} = [gi(1)*F(1)+ji(1)+I1;
@@ -377,9 +381,9 @@
 
 endfunction
 
-function [V0, n0, p0] = predict (device, material, constants, ...
-                                 algorithm, V, n, p, F, tstep, ...
-                                 tout, gi, ji)
+function [V0, n0, p0, F0] = predict (device, material, constants, ...
+                                     algorithm, V, n, p, F, tstep, ...
+                                     tout, gi, ji)
 
   if (tstep > 2)
 
@@ -391,12 +395,15 @@
     Fn(:, 2) = V(:, it(2)) - constants.Vth * log (n(:, it(2)) ./ device.ni);
 
     dFndt = diff (Fn, 1, 2) ./ diff (tout(it));
+    dFdt  = diff (F(:, it(1:2)), 1, 2) ./ diff (tout(it));
 
     Fn0 = Fn(:, 2) + dFndt * dt;
+    F0 = F(:, it(2)) + dFdt * dt;
 
   else
 
     Fn0 = V(:, tstep-1) - constants.Vth * log (n(:, tstep-1) ./ device.ni);
+    F0  = F(:, tstep-1);
 
   endif
 
@@ -406,5 +413,5 @@
   %Fn0([1 end]) = va (tout (tstep));
 
   V0 = Fn0 + constants.Vth * log (n0 ./ device.ni);
-
+  
 endfunction