Special Case

Area:\frac{S\sub{2}}{S\sub{1}}

[ [0], [0.25], [0.75], [0.5], [1], [1.25], [1.5], [1.75], [2], [2.25], [2.5], [3,100] ]

Density:\frac{\rho\sub{2}}{\rho\sub{1}}

[ [0], [0.25], [0.75], [0.5], [1], [1.25], [1.5], [1.75], [2] ]

Wavespeed:\frac{c\sub{2}}{c\sub{1}}

[ [0], [0.25], [0.75], [0.5], [1], [1.25], [1.5], [1.75], [2] ]

Coefficients

R\sub{\reg{\xi}{eqR}} = \frac{\reg{\minus}{eqRsignFront} \ratio{Z\sub{1}}{Z\sub{2}} \reg{\minus}{eqRsign} 1}{\ratio{Z\sub{1}}{Z\sub{2}} + 1} = \reg{0}{Rvalue} T\sub{\reg{\xi}{eqT}} = \frac{2}{\ratio{Z\sub{1}}{Z\sub{2}} + 1} = \reg{1}{Tvalue} [ ["disp","Displacement"], ["vel","Velocity"], ["pres","Pressure"] ]

Acoustic

Impedance

Z = \frac{\rho c}{S} \frac{Z\sub{1}}{Z\sub{2}} = \frac{S\sub{2}}{S\sub{1}} \frac{\rho\sub{1}}{\rho\sub{2}} \frac{c\sub{1}}{S\sub{2}}

Exaggerate:

[ ["none","None"], ["disp","Displacement"], ["dens","Density"] ]

Displacement

Velocity

Pressure

color.add("incident","blue","#6666ff") color.add("transmitted","oklch(0.78 0.4 305)","oklch(0.62 0.4 305)") color.add("reflected","orange","#cc8500") color.add("wall","var(--theme-dull-dark-8)","var(--theme-dull-dark-3)") const transmittedDash = "10 5" const reflectedDash = "25 5" const imageWeight = 2 const dispWeight = 6 const acousticPropertyMap = new Map([ ["disp",{name:"Displacement",symbol:symbol.xi,tex:"\\xi"}], ["vel",{name:"Velocity",symbol:"u",tex:"u"}], ["pres",{name:"Pressure",symbol:"p",tex:"p"}] ]) reg.coeffProperty.onUpdate(v=>{ const quant = acousticPropertyMap.get(v) reg.eqR.update(quant.tex) reg.eqRsignFront.update((v=="pres")?"\\minus":"") reg.eqRsign.update((v=="pres")?"+":"\\minus") reg.eqT.update(quant.tex) calcR() }) let R, T function calcR(){ const areaRatio = (reg.area.value==3)?100:reg.area.value const densRatio = reg.density.value const speedRatio = reg.speed.value const impedanceRatio = areaRatio / densRatio / speedRatio R = (impedanceRatio - 1) / (impedanceRatio + 1) if (isNaN(R)) R = 1 T = 2 / (impedanceRatio + 1) reg.Rvalue.update(format((reg.coeffProperty.value=="pres")?-R:R)) reg.Tvalue.update(format(T)) switch(R){ case 0: reg.special.text = "Continuous" break case 1: reg.special.text = "Pressure-Release" break case -1: reg.special.text = "Hard Boundary" break default: reg.special.text = "None" break } } calcR() const left = this.left + 125 const width = this.width - 150 const gap = 50 const height = this.height/4 - gap const plot1 = this.newPlot( [left,this.bottom + 3*height + 4*gap], width, height - 10, [-1,1], [-2,2], { labelX: "Position x [m]", labelY: "Position y [m]", labelFontSizeY: 30, gridY: false, tickEndsY: false, tickStepY:10, labelGapY:0, tickArrayX: [{value:0,label:" "}], labelGapX: -5, tickLabelGapX: 0, tickLengthX: 5, } ) const p1 = plot1.group const plot2 = this.newPlot( [left,this.bottom + 2*height + 3*gap], width, height, [-1,1], [-2,2], { labelX: "Equilibrium x\\sub{0} [m]", labelY: "Displacement \\reg{\\xi}{disp-label}", tickArrayX: [{value:0,label:" "}], labelGapX: -5, tickLabelGapX: 0, tickLengthX: 5, labelFontSizeY: 30, } ) const p2 = plot2.group const plot3 = this.newPlot( [left,this.bottom + height + 2*gap], width, height, [-1,1], [-2,2], { labelX: "Equilibrium x\\sub{0} [m]", labelY: "Velocity \\reg{u}{vel-label}", tickArrayX: [{value:0,label:" "}], labelGapX: -5, tickLabelGapX: 0, tickLengthX: 5, labelFontSizeY: 30, } ) const p3 = plot3.group const plot4 = this.newPlot( [left,this.bottom + gap], width, height, [-1,1], [-2,2], { labelX: "Position x [m]", labelY: "Pressure p", tickArrayX: [{value:0,label:" "}], labelGapX: -5, tickLabelGapX: 0, tickLengthX: 5, labelFontSizeY: 30, } ) const p4 = plot4.group let t = reg.time.start reg.time.onUpdate(tt=>t=tt) reg.time.time = -0.0015 const c1 = 343 let c2 = c1 * reg.speed.value const s = 5e-8 function GaussPos(t, x, c1, c2, s){ if (x<0) return exp(-1*( t - x / c1)**2 / s) return exp(-1*( t - x / c2)**2 / s) } function GaussDerPos(t, x, c1, c2, s){ if (x<0) return GaussPos(t, x, c1, c2, s) * (-2 * (t - x/c1) / s) / (exp(-0.5) * sqrt(2 / s)) return GaussPos(t, x, c1, c2, s) * (-2 * (t - x/c2) / s) / (exp(-0.5) * sqrt(2 / s)) } function GaussNeg(t, x, c1, c2, s){ if (x<0) return exp(-1*( t + x / c1 )**2 / s) return exp(-1*( t + x / c2 )**2 / s) } function GaussDerNeg(t, x, c1, c2, s){ if (x<0) return GaussNeg(t, x, c1, c2, s) * (-2 * (t + x/c1) / s) / (exp(-0.5) * sqrt(2 / s)) return GaussNeg(t, x, c1, c2, s) * (-2 * (t + x/c2) / s) / (exp(-0.5) * sqrt(2 / s)) } const disp = p2.curve(x=>{ if (x<0){ return GaussPos(t, x, c1, c2, s) + R * GaussNeg(t, x, c1, c2, s) } else { return (T==2?0:T) * GaussPos(t, x, c1, c2, s) * (reg.volumeDisplacement.value?reg.area.value:1) } },{strokeWidth:dispWeight}) const dispIn = p2.sample(x=> GaussPos(t, x, c1, c2, s),{fill:color.incident,r:imageWeight}) const dispRe = p2.curve(x=>R * GaussNeg(t, x, c1, c2, s),{stroke:color.reflected,dash:reflectedDash,strokeWidth:imageWeight}) const dispTr = p2.curve(x=>(T==2?0:T) * GaussPos(t, x, c1, c2, s) * (reg.volumeDisplacement.value?reg.area.value:1),{stroke:color.transmitted,dash:transmittedDash,strokeWidth:imageWeight}) reg.displacementImages.onUpdate(v=>{ dispIn.classList.toggle("hidden",!v) dispRe.classList.toggle("hidden",!v) dispTr.classList.toggle("hidden",!v) }) reg.displacementImages.value = false const vel = p3.curve(x=>{ if (x<0){ return GaussDerPos(t, x, c1, c2, s) + R * GaussDerNeg(t, x, c1, c2, s) } else { return (T==2?0:T) * GaussDerPos(t, x, c1, c2, s) * (reg.volumeVelocity.value?reg.area.value:1) } },{strokeWidth:dispWeight}) const velIn = p3.sample(x=> GaussDerPos(t, x, c1, c2, s),{fill:color.incident,r:imageWeight}) const velRe = p3.curve(x=>R * GaussDerNeg(t, x, c1, c2, s),{stroke:color.reflected,dash:reflectedDash,strokeWidth:imageWeight}) const velTr = p3.curve(x=>(T==2?0:T) * GaussDerPos(t, x, c1, c2, s) * (reg.volumeVelocity.value?reg.area.value:1),{stroke:color.transmitted,dash:transmittedDash,strokeWidth:imageWeight}) reg.velocityImages.onUpdate(v=>{ velIn.classList.toggle("hidden",!v) velRe.classList.toggle("hidden",!v) velTr.classList.toggle("hidden",!v) }) reg.velocityImages.value = false const pres = p4.curve(x=>{ if (x<0){ return GaussDerPos(t, x, c1, c2, s) - R * GaussDerNeg(t, x, c1, c2, s) } else { return (T==2?0:T) * GaussDerPos(t, x, c1, c2, s) } },{strokeWidth:dispWeight}) const presIn = p4.sample(x=> GaussDerPos(t, x, c1, c2, s),{fill:color.incident,r:imageWeight}) const presRe = p4.curve(x=>-R * GaussDerNeg(t, x, c1, c2, s),{stroke:color.reflected,dash:reflectedDash,strokeWidth:imageWeight}) const presTr = p4.curve(x=> (T==2?0:T) * GaussDerPos(t, x, c1, c2, s),{stroke:color.transmitted,dash:transmittedDash,strokeWidth:imageWeight}) reg.pressureImages.onUpdate(v=>{ presIn.classList.toggle("hidden",!v) presRe.classList.toggle("hidden",!v) presTr.classList.toggle("hidden",!v) }) reg.pressureImages.value = false const dots = p1.sample2d((x,y)=>{ if(x<=0 && abs(y)<=1) return true if(x>=0 && abs(y)<(sqrt((reg.area.value==3)?100:(reg.area.value)))) return true }, x=>{ const exag = reg.exag.value=="disp"?50:10 if (x<0){ return exag * (GaussPos(t, x, c1, c2, s) + R * GaussNeg(t, x, c1, c2, s)) } else { return exag * T * GaussPos(t, x, c1, c2, s) } }, y=>0, (x,y)=>{ const dr = (x<0) ? GaussDerPos(t, x, c1, c2, s) - R * GaussDerNeg(t, x, c1, c2, s) : T * GaussDerPos(t, x, c1, c2, s) const r = ((x<0)?5:5 * reg.density.value) + ((reg.exag.value=="dens")?3*dr:0) return (r<0)?0:r } ) const wall = p1.polyline( ()=>{ return reg.area.value==0 ? [-1,0,0,-1] : [-1,0,0,1.5,1.5,0,0,-1] }, ()=>{ const wallSize = sqrt((reg.area.value==3)?100:(reg.area.value)) return reg.area.value==0 ? [1,1,-1,-1] : [1,1,wallSize,wallSize,-wallSize,-wallSize,-1,-1] }, {stroke:color.wall,strokeWidth:10} ) function updateCurves(){ disp.update() dispIn.update() dispRe.update() dispTr.update() vel.update() velIn.update() velRe.update() velTr.update() pres.update() presIn.update() presRe.update() presTr.update() dots.update() wall.update() } reg.area.onUpdate(v=>{ calcR() dots.filter() updateCurves() }) reg.density.onUpdate(v=>{ calcR() updateCurves() }) reg.exag.onUpdate(v=>{ updateCurves() }) reg.time.onUpdate(t=>{ updateCurves() }) reg.speed.onUpdate(v=>{ calcR() c2 = c1 * ((v==0)?0.001:v) updateCurves() }) reg.volumeVelocity.onUpdate(v=>{ reg.velLabel.update(v?"Su":"u") updateCurves() }) reg.volumeDisplacement.onUpdate(v=>{ reg.dispLabel.update(v?"S\\xi":"\\xi") updateCurves() })