地震响应谱计算器 返回
Interactive Tool — Seismic Engineering

地震响应谱计算器

交互式计算设计用响应谱(参考日本建筑基准法及ASCE/SEI 7的简化模型)。通过调整阻尼比和场地类别,实时比较Sa、Sv、Sd谱。

地震动与场地条件
阻尼比 ζ
主要阻尼比
钢结构: 2%,RC: 5%,隔震: 20%
谱类型
结构固有周期
固有周期 T
s
低层RC: 0.1〜0.3s / 超高层: 3〜5s
Sa = — m/s²
计算结果
固有周期 T [s]
Sa [m/s²]
Sv [m/s]
Sd [m]
响应谱(多组阻尼比) 加速度谱 Sa [m/s²]
Spec
建筑摇晃动画 — 地震応答的可视化

理论说明 — 响应谱的读取方法

响应谱是将"具有不同固有周期的单自由度系统在同一地震动作用下各自的最大响应值"以周期为自变量绘制的曲线。设计人员从中读取与建筑固有周期 T 对应的谱值,计算等效静力荷载 $F = S_a \times m$。

$$S_a(T) \xrightarrow{\div \omega^2}S_d(T) = \frac{T^2}{4\pi^2}S_a(T), \quad S_v(T) = \frac{T}{2\pi}S_a(T)$$

阻尼越大,谱值越低。实务中钢结构阻尼比取2%,RC结构取5%。隔震结构设定等效阻尼比20〜30%,可大幅降低响应。

本工具的设计谱为参考日本标准加速度响应谱的简化模型(实际设计请使用规范谱或场地专用谱)。

什么是地震响应谱

🙋
“地震响应谱”是什么?听起来好复杂。
🎓
简单来说,它就像一张“地震菜单”。想象一下,地震会摇晃各种不同“口味”(周期)的建筑。响应谱这张菜单就告诉你,每种口味的建筑在地震时会吃到多大的“力”(加速度)。在实际工程中,我们用它来快速估算地震力,而不用每次都做复杂的时程分析。
🙋
诶,真的吗?那菜单上的“口味”和“力”是怎么算出来的?
🎓
核心是单自由度体系的运动方程。比如,我们给一个具有特定周期和阻尼的“虚拟小房子”输入真实的地震波,计算它产生的最大反应(加速度、速度、位移),然后把结果画成曲线。你在这个模拟器里试着拖动“阻尼比”滑块,比如从钢结构的2%拖到隔震结构的30%,马上就能看到整条谱曲线都变矮了,这就是阻尼“吃掉”地震能量的直观效果。
🙋
原来阻尼这么厉害!那工程师拿到这条谱曲线后,具体怎么用呢?
🎓
最直接的用法就是算等效静力。比如一栋办公楼,我们算出它的基本周期T是1秒,然后从谱曲线上找到对应1秒的谱AccelerationSa。那么这栋楼受到的总水平地震力,大致就是Sa乘以楼的总重量。你可以在工具里改变“固有周期”参数,看看Sa值怎么变化,就能理解为什么短周期和长周期的建筑设计重点不一样了。

物理模型与关键公式

整个响应谱理论的基础是单自由度(SDOF)体系的运动方程。它描述了一个具有质量、刚度和阻尼的简化模型在地面运动激励下的振动。

$$ m\ddot{u}(t) + c\dot{u}(t) + ku(t) = -m\ddot{u}_g(t) $$

其中,$m$是质量,$c$是阻尼系数,$k$是刚度,$u(t)$是相对位移,$\ddot{u}_g(t)$是地面加速度。解这个方程可以得到体系在地震过程中的最大反应。

工程中更常用的是加速度响应谱$S_a(T, \xi)$。一旦得到它,可以通过简单的数学关系推导出速度谱$S_v$和位移谱$S_d$,三者统称为三联谱。

$$ S_d(T) = \frac{T^2}{4\pi^2}S_a(T), \quad S_v(T) = \frac{T}{2\pi} S_a(T) $$

这里,$T$是体系固有周期,$S_a$是伪加速度谱(对于一般建筑,可近似为绝对最大加速度)。这个关系意味着,只要知道其中一个谱,另外两个就确定了。在模拟器中切换Sa、Sv、Sd视图,你会看到曲线形状随周期发生有趣的变化。

现实世界中的应用

建筑结构抗震设计:这是最核心的应用。世界各国的建筑规范(如中国的《抗规》、日本的《建筑基准法》、美国的ASCE 7)都规定了标准的设计响应谱。工程师根据建筑物所在地、场地条件和用途,选择对应的谱曲线来计算地震作用,进行构件设计。

隔震与消能减震设计:隔震结构通过延长周期和增加阻尼来大幅降低地震力。设计时,需要对比普通结构(阻尼比~5%)和隔震结构(阻尼比可达20-30%)的响应谱差异。模拟器中调整高阻尼比,你会看到谱值显著下降,这就是隔震的原理可视化。

桥梁与特种结构评估:对于大跨度桥梁、电视塔、大型储罐等,其动力特性复杂,但初步评估时仍可使用响应谱法。通过估算结构的主要周期,从谱中读取反应值,可以快速判断地震力的大小和分布特点。

设备与管道抗震:核电站内的精密设备、化工厂的管道系统也必须考虑地震安全。这些非结构构件的自振周期往往很短,位于响应谱的高频(短周期)加速度平台区,因此它们会受到很大的惯性力,需要专门设计支撑。

常见误解与注意事项

开始使用此工具时,有几个需要注意的关键点。首先要理解“设计谱并非绝对答案”。工具生成的平滑曲线是经过大量地震记录统计处理得到的“代表值”。例如,在实际输入某条地震波进行计算时,响应峰值远超此设计曲线的情况并不少见。因此在实际工程中,通常会在设计值基础上叠加“保有水平承载力”等安全系数进行设计。

其次,需要理解“单自由度体系”模型的局限性。此工具将建筑物简化为单个质点和弹簧模型,但实际建筑是多自由度体系,二阶、三阶等高阶振型也会影响响应。例如对于细长塔状结构,不仅一阶振型(最缓慢的振动)需要考虑,二阶振型(呈反S形振动)的响应也不容忽视。工具结果应仅作为一阶振型的参考指标。

最后要注意参数设置的陷阱。其中“阻尼比”的参数敏感性较高。通常以钢筋混凝土结构常用的5%为基准,钢结构取2%,隔震结构则取10%~20%。若随意保持默认设置,可能导致与预期完全不同的响应评估结果。务必养成根据目标结构类型设定参数的习惯。

// Seismic building animation (function() { const el = document.getElementById('seismicAnimCanvas'); const ctx = el.getContext('2d'); let simT = 0; const NFLOORS = 5; function getParams() { const T = parseFloat(document.getElementById('sl-T').value) || 0.5; const z = (parseFloat(document.getElementById('sl-z').value) || 5) / 100; const omega = 2 * Math.PI / T; return { T, z, omega }; } // Generate pseudo-random ground motion signal function groundAccel(t) { // Superposition of several frequency components to mimic earthquake return ( 0.5 * Math.sin(2 * Math.PI * 1.2 * t) + 0.3 * Math.sin(2 * Math.PI * 2.5 * t + 1.1) + 0.4 * Math.sin(2 * Math.PI * 0.7 * t + 2.3) + 0.2 * Math.sin(2 * Math.PI * 3.1 * t + 0.5) + 0.15 * Math.sin(2 * Math.PI * 4.5 * t + 1.8) ) * 0.5; } // Simple Duhamel response state (velocity, displacement) let respV = 0, respD = 0; let prevAccel = 0; const dt = 1/60; function resize() { const dpr = window.devicePixelRatio || 1; const w = el.parentElement.clientWidth - 48; const H = Math.round(Math.min(w * 0.5, 320)); if (Math.abs(el.width - w * dpr) > 2 || el.height !== H * dpr) { el.width = w * dpr; el.height = H * dpr; el.style.height = H + 'px'; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); } return { W: w, H }; } function frame() { const { W, H } = resize(); const { T, z, omega } = getParams(); simT += dt; // Compute ground acceleration const ag = groundAccel(simT); // Newmark-beta integration (beta=0.25, gamma=0.5 — avg. accel.) const c = 2 * z * omega; const k = omega * omega; const force = -ag - c * respV - k * respD; const newA = force; respD = respD + dt * respV + dt * dt * (0.25 * newA + 0.25 * prevAccel); respV = respV + dt * (0.5 * newA + 0.5 * prevAccel); prevAccel = newA; ctx.clearRect(0, 0, W, H); ctx.fillStyle = '#f8f9fa'; ctx.fillRect(0, 0, W, H); const groundY = H - 30; const bldW = Math.min(W * 0.25, 100); const floorH = Math.min((groundY - 40) / NFLOORS, 45); const bldH = floorH * NFLOORS; const bldX = W / 2 - bldW / 2; // Ground strip const groundShake = ag * 18; ctx.fillStyle = '#001F3F'; ctx.fillRect(0, groundY, W, H - groundY); // Ground motion indicator ctx.strokeStyle = '#e17055'; ctx.lineWidth = 1.5; ctx.beginPath(); ctx.moveTo(W - 100, groundY - 4); ctx.lineTo(W - 100 + groundShake * 8, groundY - 4); ctx.stroke(); ctx.fillStyle = '#6c757d'; ctx.font = '9px Roboto Mono'; ctx.textAlign = 'right'; ctx.fillText(`地面加速度: ${(ag * 9.8).toFixed(2)} m/s²`, W - 10, groundY - 8); // Cap visual displacement const maxVisDisp = bldH * 0.15; const disp0 = Math.max(-maxVisDisp, Math.min(maxVisDisp, respD * 80)); // Draw building floors with linear drift (larger sway at top) for (let f = 0; f < NFLOORS; f++) { const frac = (f + 1) / NFLOORS; // 0 at base, 1 at top const floorDisp = disp0 * frac + groundShake; const fy = groundY - (f + 1) * floorH; const fx = bldX + floorDisp; // Floor slab const g = Math.round(60 + (1 - frac) * 60); ctx.fillStyle = `rgb(0,${g},127)`; ctx.fillRect(fx, fy, bldW, 6); // Column (connecting to next floor) if (f < NFLOORS - 1) { const nextFrac = (f + 2) / NFLOORS; const nextDisp = disp0 * nextFrac + groundShake; const nextFy = groundY - (f + 2) * floorH; ctx.strokeStyle = `rgba(0,123,255,0.7)`; ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(fx + 8, fy + 6); ctx.lineTo(bldX + nextDisp + 8, nextFy + 6); ctx.moveTo(fx + bldW - 8, fy + 6); ctx.lineTo(bldX + nextDisp + bldW - 8, nextFy + 6); ctx.stroke(); } // Floor label ctx.fillStyle = 'rgba(255,255,255,0.7)'; ctx.font = '9px Roboto Mono'; ctx.textAlign = 'left'; ctx.fillText(`F${f+1}`, fx + bldW + 4, fy + 10); } // Base (ground floor connection) ctx.fillStyle = '#007BFF'; ctx.fillRect(bldX + groundShake - 2, groundY - floorH, bldW + 4, 6); // Roof marker and displacement label const roofDisp = disp0 + groundShake; const roofY = groundY - bldH; ctx.fillStyle = '#e17055'; ctx.beginPath(); ctx.arc(bldX + bldW/2 + roofDisp, roofY - 8, 4, 0, Math.PI * 2); ctx.fill(); // Response labels ctx.fillStyle = '#001F3F'; ctx.font = 'bold 11px Roboto Mono, monospace'; ctx.textAlign = 'left'; ctx.fillText(`T = ${T.toFixed(2)} s`, 10, 22); ctx.fillText(`ζ = ${(z*100).toFixed(0)}%`, 10, 36); ctx.fillStyle = Math.abs(respD) > 0.2 ? '#d63031' : '#007BFF'; ctx.fillText(`u = ${(respD * 100).toFixed(1)} cm`, 10, 50); requestAnimationFrame(frame); } frame(); })();