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()
})