Special Case

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

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

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

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 incidentDash = "35 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.1)?100:reg.area.value const densRatio = reg.density.value const speedRatio = reg.speed.value const impedanceRatio = (areaRatio>0) ? areaRatio / densRatio / speedRatio : Infinity R = (impedanceRatio - 1) / (impedanceRatio + 1) if (isNaN(R)) R = areaRatio==0?-1: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 p1 = this.newPlot({ position:[ left, this.bottom + 3*height + 4*gap], size: [ width, height-10 ], rangeX:[-1,1], rangeY:[-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 p2 = this.newPlot({ position: [left,this.bottom + 2*height + 3*gap], size: [width, height], rangeX: [-1,1], rangeY: [-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, tickStepY: 1, }) const p3 = this.newPlot({ position: [ left, this.bottom + height + 2*gap ], size: [ width, height ], rangeX: [-1,1], rangeY: [-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, tickStepY: 1, }) const p4 = this.newPlot({ position: [left,this.bottom + gap], size: [width, height], rangeX: [-1,1], rangeY: [-2,2], labelX: "Position x [m]", labelY: "Pressure p", tickStepY: 1, tickArrayX: [{value:0,label:" "}], labelGapX: -5, tickLabelGapX: 0, tickLengthX: 5, labelFontSizeY: 30, }) 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.plotFn({ y: 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.plotFn({y:x=> GaussPos(t, x, c1, c2, s),stroke:color.incident,dash:incidentDash,strokeWidth:imageWeight}) const dispRe = p2.plotFn({y:x=>R * GaussNeg(t, x, c1, c2, s),stroke:color.reflected,dash:reflectedDash,strokeWidth:imageWeight}) const dispTr = p2.plotFn({y: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.plotFn({ y: 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.plotFn({y:x=> GaussDerPos(t, x, c1, c2, s),stroke:color.incident,dash:incidentDash,strokeWidth:imageWeight}) const velRe = p3.plotFn({y:x=>R * GaussDerNeg(t, x, c1, c2, s),stroke:color.reflected,dash:reflectedDash,strokeWidth:imageWeight}) const velTr = p3.plotFn({y: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.plotFn({ y: 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.plotFn({y: x=> GaussDerPos(t, x, c1, c2, s),stroke:color.incident,dash:incidentDash,strokeWidth:imageWeight}) const presRe = p4.plotFn({y: x=>-R * GaussDerNeg(t, x, c1, c2, s),stroke:color.reflected,dash:reflectedDash,strokeWidth:imageWeight}) const presTr = p4.plotFn({y: 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.particles({ filter: (x,y)=>{ if(x<=0 && abs(y)<=1) return true if(x>=0 && abs(y)<(sqrt((reg.area.value==3.1)?100:(reg.area.value)))) return true }, dx: 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) } }, dy: y=>0, dr: (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.line({ x: ()=>{ return reg.area.value==0 ? [-1,0,0,-1] : [-1,0,0,1.5,1.5,0,0,-1] }, y: ()=>{ const wallSize = sqrt((reg.area.value==3.1)?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:15 }) 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.area.handleText.textContent = v==3.1?100:Math.round(v*10)/10 }) 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() })