Mercurial > forge
changeset 11547:201b0a716429 octave-forge
adaptive time_step
author | cdf |
---|---|
date | Thu, 14 Mar 2013 16:21:08 +0000 |
parents | 2acb4bbe57fd |
children | 2be420b66478 |
files | extra/secs1d/inst/demos/diode_refine_mesh.m extra/secs1d/inst/demos/diode_tran_noscale.m extra/secs1d/inst/demos/thyristor_refine_mesh.m extra/secs1d/inst/secs1d_logplot.m extra/secs1d/inst/secs1d_tran_dd_gummel_map_noscale.m |
diffstat | 5 files changed, 160 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/secs1d/inst/demos/diode_refine_mesh.m Thu Mar 14 16:21:08 2013 +0000 @@ -0,0 +1,85 @@ +% physical constants and parameters +constants = secs1d_physical_constants_fun (); +material = secs1d_silicon_material_properties_fun (constants); + +% geometry +Nelements = 100; +L = 50e-6; % [m] +xm = L/2; +device.W = 150e-6 * 50e-6; + +device.x = linspace (0, L, Nelements+1)'; +device.sinodes = [1:length(device.x)]; + +converged = false; +iters = 1; +maxiters = 10; +while (! converged) + + %% doping profile [m^{-3}] + device.Na = 1e23 * exp (- (device.x / 2e-6) .^ 2); + device.Nd = 1e25 * exp (- ((device.x-L) / 2.4e-6) .^ 2) + 1e19; + + %% avoid zero doping + device.D = device.Nd - device.Na; + + Fn = Fp = zeros (size (device.x)); + + %% carrier lifetime + device.tp = secs1d_carrier_lifetime_noscale (device.Na, device.Nd, 'p'); + device.tn = secs1d_carrier_lifetime_noscale (device.Na, device.Nd, 'n'); + + %% bandgap narrowing correction + device.ni = (material.ni) * exp (secs1d_bandgap_narrowing_model + (device.Na, device.Nd) / constants.Vth); + + %% 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); + + + %% tolerances for convergence checks + algorithm.toll = 1e-6; + algorithm.maxit = 100; + algorithm.ptoll = 1e-12; + algorithm.pmaxit = 100; + algorithm.maxnpincr = constants.Vth; + + secs1d_logplot (device.x, device.D); + drawnow + + %% initial guess via stationary simulation + [Vin, nin, pin, res, niter] = ... + secs1d_nlpoisson_newton_noscale (device, material, + constants, algorithm, + V, n, p, Fn, Fp); + + els_to_refine = find ((abs (diff (log10 (nin))) > .02) + | (abs (diff (log10 (pin))) > .02) + | (abs (diff (log10 (abs (device.D)))) > .05)); + + if isempty (els_to_refine) + converged = true; + endif + + if (converged || (++iters > maxiters)) + break + endif + + x = device.x; + newx = (x(els_to_refine) + x(els_to_refine+1)) / 2; + device.x = sort (vertcat (x, newx)); + device.sinodes = [1:length(device.x)]; + +endwhile + +save diode_mesh x L xm \ No newline at end of file
--- a/extra/secs1d/inst/demos/diode_tran_noscale.m Thu Mar 14 13:04:01 2013 +0000 +++ b/extra/secs1d/inst/demos/diode_tran_noscale.m Thu Mar 14 16:21:08 2013 +0000 @@ -1,14 +1,16 @@ + % physical constants and parameters constants = secs1d_physical_constants_fun (); material = secs1d_silicon_material_properties_fun (constants); % geometry -L = 50e-6; % [m] -xm = L/2; +diode_refine_mesh +load diode_mesh L xm x +# Nelements = 1000; +# L = 50e-6; % [m] +# xm = L/2; device.W = 150e-6 * 50e-6; - -Nelements = 1000; -device.x = linspace (0, L, Nelements+1)'; +# device.x = linspace (0, L, Nelements+1)'; device.sinodes = [1:length(device.x)]; % doping profile [m^{-3}] @@ -20,7 +22,7 @@ % time span for simulation tmin = 0; -tmax = 769; +tmax = 3/500; tspan = [tmin, tmax]; Fn = Fp = zeros (size (device.x)); @@ -48,22 +50,22 @@ function fn = vbcs_1 (t); fn = [0; 0]; - fn(2) = t; + fn(2) = 1 * sin (500 * pi * t); endfunction function fp = vbcs_2 (t); fp = [0; 0]; - fp(2) = t; + fp(2) = 1 * sin (500 * pi * t); endfunction vbcs = {@vbcs_1, @vbcs_2}; % tolerances for convergence checks -algorithm.toll = 1e-10; -algorithm.maxit = 10; +algorithm.toll = 1e-6; +algorithm.maxit = 300; algorithm.ptoll = 1e-12; algorithm.pmaxit = 1000; -algorithm.maxnpincr = constants.Vth; +algorithm.maxnpincr = constants.Vth / 10; %% initial guess via stationary simulation [nin, pin, Vin, Fnin, Fpin, Jn, Jp, it, res] = ...
--- a/extra/secs1d/inst/demos/thyristor_refine_mesh.m Thu Mar 14 13:04:01 2013 +0000 +++ b/extra/secs1d/inst/demos/thyristor_refine_mesh.m Thu Mar 14 16:21:08 2013 +0000 @@ -7,10 +7,10 @@ material = secs1d_silicon_material_properties_fun (constants); % geometry -L = 400e-6; % [m] +L = 80e-6; % [m] xm = L/2; -Nelements = 1000; +Nelements = 10; device.x = linspace (0, L, Nelements+1)'; device.sinodes = [1:length(device.x)]; @@ -54,11 +54,7 @@ algorithm.pmaxit = 100; algorithm.maxnpincr = constants.Vth; - logplot = @(x) asinh (x/2) / log(10); - close all; plot (device.x, logplot (device.D)); - set (gca, "yticklabel", - arrayfun (@(x) sprintf ("%s10^{%g}", ifelse (x >=0, "+", "-"), abs(x)), - get (gca, "ytick"), "uniformoutput", false)); + secs1d_logplot (device.x, device.D); drawnow %% initial guess via stationary simulation @@ -67,7 +63,10 @@ constants, algorithm, V, n, p, Fn, Fp); - els_to_refine = find ((abs (diff (log10 (nin))) > .1) | (abs (diff (log10 (pin))) > .1) | (abs (diff (log10 (abs (device.D)))) > .1)); + els_to_refine = find ((abs (diff (log10 (nin))) > .05) + | (abs (diff (log10 (pin))) > .05) + | (abs (diff (log10 (abs (device.D)))) > .1)); + if isempty (els_to_refine) converged = true; endif @@ -80,4 +79,6 @@ newx = (x(els_to_refine) + x(els_to_refine+1)) / 2; device.x = sort (vertcat (x, newx)); device.sinodes = [1:length(device.x)]; -endwhile \ No newline at end of file +endwhile + +save thyristor_mesh x L \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/secs1d/inst/secs1d_logplot.m Thu Mar 14 16:21:08 2013 +0000 @@ -0,0 +1,29 @@ +%% Copyright (C) 2013 Carlo de Falco +%% +%% This file is part of +%% SECS1D - A 1-D Drift--Diffusion Semiconductor Device Simulator +%% +%% SECS1D is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 3 of the License, or +%% (at your option) any later version. +%% +%% SECS1D is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with SECS1D; If not, see <http://www.gnu.org/licenses/>. + +function secs1d_logplot (x, y) + + plot (x, __logplot__ (y)); + set (gca, "yticklabel", + arrayfun (@(x) sprintf ("%s10^{%g}", ifelse (x >=0, "+", "-"), abs(x)), + get (gca, "ytick"), "uniformoutput", false)); +endfunction + +function logplot = __logplot__ (x) + logplot = asinh (x/2) / log(10); +endfunction \ No newline at end of file
--- a/extra/secs1d/inst/secs1d_tran_dd_gummel_map_noscale.m Thu Mar 14 13:04:01 2013 +0000 +++ b/extra/secs1d/inst/secs1d_tran_dd_gummel_map_noscale.m Thu Mar 14 16:21:08 2013 +0000 @@ -61,6 +61,8 @@ secs1d_tran_dd_gummel_map_noscale (device, material, constants, algorithm, Vin, nin, pin, Fnin, Fpin, tspan, vbcs) + rejected = 0; + V = Vin; n = nin; p = pin; @@ -120,12 +122,13 @@ V0 = Fn0 + constants.Vth * log (n0 ./ device.ni); + nrfnp = 4 * algorithm.maxnpincr; %% initialize so it is not undefined in case of exception [V(:,tstep), n(:,tstep), p(:,tstep), Fn(:,tstep), ... - Fp(:,tstep), Jn(:,tstep), Jp(:,tstep), res_, it] =... + Fp(:,tstep), Jn(:,tstep), Jp(:,tstep), res_, it, nrfnp] =... __one_step__ (device, material, constants, algorithm, V0, n0, p0, Fn0, Fp0, Jn(:,tstep), Jp(:,tstep), - n(:, tstep - 1), p(:, tstep - 1), dt); - + n(:, tstep - 1), p(:, tstep - 1), dt); + assert (nrfnp <= algorithm.maxnpincr) figure (1) plot (tout, (mean (Jn(:, 1:tstep) + Jp(:, 1:tstep), 1))) drawnow @@ -134,29 +137,34 @@ %if (tstep > 2) % dt *= (algorithm.maxnpincr - res(tstep, 1)) / (res(tstep, 1) - res(tstep-1, 1)); %endif - dt *= 2; + printf ("dt incremented by %g\n", .5 * sqrt (algorithm.maxnpincr / nrfnp)) + dt *= .5 * sqrt (algorithm.maxnpincr / nrfnp); numit(tstep) = it; catch warning (lasterr) - dt /= 2; + warning ("algorithm.maxnpincr = %17.17g, nrfnp = %17.17g, dt reduced by %17.17g", + algorithm.maxnpincr, nrfnp, .5 * sqrt (algorithm.maxnpincr / nrfnp)) + dt *= .5 * sqrt (algorithm.maxnpincr / nrfnp); t = tout(--tstep); if (dt < 100*eps) warning ("secs1d_tran_dd_gummel_map_noscale: minimum time step reached.") return endif + rejected ++ ; end_try_catch endwhile - + rejected endfunction function [Jn, Jp] = compute_currents (device, material, constants, algorithm, mobilityn, mobilityp, V, n, p, Fn, Fp) - dV = diff (V); + dV = diff (V); dx = diff (device.x); + [Bp, Bm] = bimu_bernoulli (dV ./ constants.Vth); Jn = constants.q * constants.Vth * mobilityn .* ... @@ -212,7 +220,7 @@ endfunction -function [V, n, p, Fn, Fp, Jn, Jp, res, it] = __one_step__ ... +function [V, n, p, Fn, Fp, Jn, Jp, res, it, nrfnp] = __one_step__ ... (device, material, constants, algorithm, V0, n0, p0, Fn0, Fp0, Jn0, Jp0, n_old, p_old, dt); @@ -229,14 +237,14 @@ Nelements = Nnodes -1; for it = 1 : algorithm.maxit - + [V, n, p] = secs1d_nlpoisson_newton_noscale ... (device, material, constants, algorithm, V, n, p, Fn, Fp); dV = diff (V); E = - dV ./ dx; - [Bp, Bm] = bimu_bernoulli (dV); + %% [Bp, Bm] = bimu_bernoulli (dV); [Rn, Rp, Gn, Gp, II] = generation_recombination_model ... (device, material, constants, algorithm, E, Jn, Jp, @@ -271,16 +279,16 @@ V, n, p, Fn, Fp); nrfn = norm (Fn - Fn0, inf); - assert (norm (Fn - Fnref, inf) <= algorithm.maxnpincr); - nrfp = norm (Fp - Fp0, inf); - assert (norm (Fp - Fpref, inf) <= algorithm.maxnpincr); + + nrfnp = max (norm (Fn - Fnref, inf), norm (Fp - Fpref, inf)); nrv = norm (V - V0, inf); res(it) = max ([nrfn; nrfp; nrv]); - if (res(it) < algorithm.toll) - break + if (res(it) < algorithm.toll + || (nrfnp > algorithm.maxnpincr)) + break; endif V0 = V;