## IE, Opera, and Nested Switch statements

I've created a module that displays many methods for numerically solving 1D linear advection equations at:
http://cis.jhu.edu/~shanest/project/...dvection7.html

These all work fine in FF. In IE and Opera, however, it always displays the arrays for the "Upwind" method, and none of the other 4. My method of display is highly procedural and relies on many nested switch statements. Is there a major difference about the way that IE and Opera handle nested switch statements? Note that the switch statements call the same variables on more than one occasion.

The code for "linearadvection.js" is here:

Code:
```var svg;
\$(function() {
svg = \$('#svgcontainer').svg('get');
svg.configure({width: '400', height: '400', preserveAspectRatio: 'none'});
}});
});

var c, deltax, cfl, dt, xb, tb, numsteps;
//ta, xa are initial points
var ta = 0;
var xa = 0;
var xsteps;
var period;
var numperiods;
//the specific time step
var tstep = 1;
//this time value (step times delta t)
var t;
//vectors for lw method
var phinew = new Array();
var phiold = new Array();
//for leapfrog method
var phi = new Array();

function calculate(which) {
//retrieve user input values
c = \$('#c').val();
deltax = \$('#dx').val();
cfl = \$('#cfl').val();

//calculate and display delta t (time step)
dt = cfl*deltax / c;
\$('#dt').text(dt);

switch(which) {
case "finite":
//xb is max x value; set here, not by user
xb = 3;
//tb is max time value
tb = \$('#T').val();
//calculate and display number of time steps
numsteps = (tb - ta) / dt;
\$('#numsteps').text(numsteps);
break;
case "periodic":
//xb is max x value; set here, not by user
xb = 1;
//retrieve number of periods for later use
numperiods = \$('#H').val();
//wave period
period = (xb - xa) / c;
//calculate and display time steps per period
numsteps = period / dt;
\$('#numsteps').text(numsteps);
break;
}
}

//which is either 'finite' or 'periodic'; method is L-W, Upwind, etc.
function makePlot(method, which) {
//number of points / x values
xsteps = (xb - xa) / deltax;
//retrieve c again in case user changes in the middle
//all the other values are supposed to remain "constant" right now
c = \$('#c').val();

if(tstep == 1) {
//plot the initial condition function, only once
svg.plot.numPoints(xsteps).plot2D(0,3,0,1,initCondition, {stroke: 'blue', 'stroke-width': .01, fill: 'none'}).drawAxes({stroke: 'black', 'stroke-width': .01});
}

//display time and specific tstep, note tstep incremented later
\$('#steps').text(tstep);
t = tstep*dt;
\$('#time').text(t);

//generic counter used multiple times
var i;

if(tstep == 1) {
//fill phiold vector; first time, gets initial condition
for(i = 1; i < xsteps+2; i++) {
phiold[i] = initCondition(xt(i));
}
}

/*This control structure does the following for each of the methods:
-defines the proper phiNew function to generate the phinew vector
-sets the proper phinew[1] and phinew[xsteps +1] components
-uses another switch for finite vs. periodic of each method*/
switch(method) {
case "laxwendroff":
function phiNew(val) {
return phiold[val] - cfl*0.5*(phiold[val+1] - phiold[val - 1]) + Math.pow(cfl,2)*.5*(phiold[val+1] - 2*phiold[val] + phiold[val-1]);
}
switch(which) {
case "finite":
phinew[1] = 0;
phinew[xsteps + 1] = 0;
break;
case "periodic":
//first and last components of phinew are diff for periodic
phinew[1] = phiold[1] - cfl*.5*(phiold[2]-phiold[xsteps])+Math.pow(cfl,2)*.5*(phiold[2]-2*phiold[1]+phiold[xsteps]);
phinew[xsteps + 1] = phiold[xsteps] - cfl*.5*(phiold[2]-phiold[xsteps-1])+Math.pow(cfl,2)*.5*(phiold[2]-2*phiold[xsteps]+phiold[xsteps-1]);
break;
}
break;
case "upwind":
function phiNew(val) {
return phiold[val] - cfl*(phiold[val] - phiold[val - 1]);
}
switch(which) {
case "finite":
phinew[1] = 0;
phinew[xsteps +1] = 0;
break;
case "periodic":
phinew[1] = phiold[1] - cfl*(phiold[1] - phiold[xsteps]);
phinew[xsteps + 1] = phiold[xsteps + 1] - cfl*(phiold[xsteps + 1] - phiold[xsteps]);
break;
}
break;
/*NOTE FOR LEAPFROG:
vector phi acts as phiold does in other methods
vector phiold is to phi as phi is to phinew*/
case "leapfrog":
if(tstep == 1) {
//fill phiold vector; first time, gets initial condition
for(i = 1; i < xsteps+2; i++) {
phi[i] = initCondition(xt(i)-c*dt);
}
}
function phiNew(val) {
if(tstep == 1) {
return phi[val] - cfl*(phiold[val] - phiold[val - 1]);
}
return phi[val] - cfl*(phiold[val+1]-phiold[val -1]);
}
switch(which) {
case "finite":
phinew[1] = 0;
phinew[xsteps + 1] = 0;
break;
case "periodic":
phinew[1] = phi[1] - cfl*(phiold[2]-phiold[xsteps]);
phinew[xsteps + 1] = phi[xsteps] - cfl*(phiold[2]-phiold[xsteps]);
break;
}
break;
/*NOTE FOR SEMILAGRANGIAN:
phinew and phiold are not exactly appropriate names
they are used, however, for consistency and to reuse as much
code as possible*/
case "semilagrangian":
function phiNew(val) {
var p = locate(val,xsteps + 1);
var xihere = xi(val);
if(xihere < xa) {
xihere = xb - (xa - xihere);
}
if(xihere > xb) {
xihere = xa + (xb - xihere);
}
return ((xihere-xt(p))*phiold[p+1]/(xt(p+1)-xt(p)))+((xt(p+1)-xihere)*phiold[p]/(xt(p+1)-xt(p)));
}
switch(which) {
case "finite":
phinew[1] = 0;
phinew[xsteps+1] = 0;
break;
case "periodic":
phinew[1] = phiNew(1);
phinew[xsteps + 1] = phiNew(xsteps + 1);
break;
}
break;
}

//fill phinew vector (first and last elements set diff in each case
for(i = 2; i < xsteps + 1; i++) {
phinew[i] = phiNew(i);
}

var group = svg.getElementById("group");
//create path object to be rendered later
var computed;
switch(which) {
case "finite":
//if more steps than 10, only draw when mod(step,10) is 0
if(numsteps > 10) {
if(tstep &#37; 10 == 0) {
svg.plot.numPoints(100).plot2D(0,3,0,1,phiTrue,{stroke: 'green', 'stroke-width': .01, fill: 'none'});
}
//if less than 10 steps, draw at every step
} else {
svg.plot.numPoints(100).plot2D(0,3,0,1,phiTrue,{stroke: 'green', 'stroke-width': .01, fill: 'none'});
}
computed = svg.createPath();
i = 2;
//start point for LW path
computed.moveTo(xt(i-1),phinew[i-1]);
if(numsteps > 10) {
if(tstep % 10 == 0) {
i = 2;
do {
//draw line to each next point of phinew
computed.lineTo(xt(i),phinew[i]);
i++;
} while(i < xsteps + 2)
}
} else {
i = 2;
do {
computed.lineTo(xt(i),phinew[i]);
i++;
} while(i < xsteps + 2)
}
//set viewbox here so that negative values show for computed path
svg.configure({viewBox: '0 -.3 3 1.5'});
//stop but do not clear once max steps reached
if(tstep >= numsteps) {
stop('');
}
break;
case "periodic":
//numsteps is number per period
if(tstep % parseInt(Math.round(numsteps)) == 0) {
i = 2;
computed = svg.createPath();
computed.moveTo(xt(i-1),phinew[i-1]);
do {
computed.lineTo(xt(i),phinew[i]);
i++;
} while(i < xsteps + 2)
}
svg.configure({viewBox: '0 -.3 1 1.5'});
//stop but no clear when number of periods reached
if(tstep >= numsteps*numperiods) {
stop('');
}
break;
}

//render LW computed path object
if(computed) {
svg.path(group,computed,{stroke: 'red', 'stroke-width':.01, fill: 'none'});
}

//special case for Leapfrog Method
switch(method) {
case "leapfrog":
for(i = 1; i < xsteps + 2; i++) {
phi[i] = phiold[i];
}
break;
}
//"iterate" by replacing phiold w/ phinew, which will be recalculated next time this function is called
for(i = 1; i < xsteps + 2; i++) {
phiold[i] = phinew[i];
}

//iterate tstep
tstep++;
}

//called by pressing "Clear" button
function clearPlot() {
svg.clear();
t = 0;
tstep = 0;
\$('#time').text('');
\$('#steps').text('');
}

//initial condition function
initCondition = function(val) {
return Math.exp(-200*Math.pow(val-0.5,2));
}

//with time taken into account
phiTrue = function(val) {
return initCondition(val - c*t);
}

//"true" x value
xt = function(val) {
return xa + (val - 1)*deltax;
}

xi = function(val) {
return xt(val) - c*dt;
}

//Semi-Lagrangian "zeroing in" on next grid value
function locate(i,N) {
var jupper = N;
var jlower = 1;
var jcent;
while((jupper - jlower) > 1) {
jcent = Math.floor((jupper + jlower)/2);
if(xi(i) > xt(jcent)) {
jlower = jcent;
} else {
jupper = jcent;
}
}
return jlower;
}```