feat: unified 0 and 90 degree PDF envelope and category descriptors

This commit is contained in:
2026-07-08 19:52:34 +00:00
commit 9fece3f174
170 changed files with 27177 additions and 0 deletions
+282
View File
@@ -0,0 +1,282 @@
/**
* Casos clássicos resolvidos do livro "O Vento na Engenharia Estrutural"
* (J. Blessmann, EDUFRGS, 2ª ed.) — M9.9
*
* Estes casos são usados como benchmark de validação cruzada para
* verificar que os cálculos do VentoApp batem com a referência
* bibliográfica padrão da Engenharia Estrutural Brasileira.
*
* Cada caso documenta:
* - Dados de entrada (geometria, vento, terreno)
* - Resultados esperados com a fonte (capítulo ou equação)
* - Tolerância admitida (Δ% ou Δ absoluto)
*
* ⚠️ Valores baseados na edição 2011 da NBR 6123; pequenas diferenças
* com a edição 2023 (M9.1) podem existir em casas raras — ver notas
* em cada caso.
*/
import type { TerrainCategory } from './wind-kernel';
/** Estrutura comum a todos os casos de validação. */
export interface BlessmannCase {
/** Identificador único (capítulo ou exemplo do livro) */
id: string;
/** Descrição sucinta do cenário */
description: string;
/** Fonte no livro (capítulo/exemplo) */
source: string;
/** Tolerância admitida (fração, ex. 0.01 = 1%) */
tolerance: number;
/** Notas sobre o caso (diferenças entre edições, arredondamentos) */
notes?: string;
}
// =============================================================================
// CASO 1: Exemplo clássico do Capítulo 5 (Blessmann)
// Galpão industrial — vento 0° e 90°
// =============================================================================
/**
* Galpão retangular 30 × 15 × 6 m (a × b × h), cobertura duas águas θ = 10°,
* vento V₀ = 40 m/s, Cat. II, S₁ = 1, S₃ = 1.
*
* Esperado:
* - S₂(10m, II, A) = 1,00 (classe A: maior dimensão ≤ 20 m)
* - Vₖ = 40 × 1 × 1 × 1 = 40 m/s
* - q = 0,613 × 40² / 1000 = 0,981 kN/m²
* - Para vento 0°: h/b = 0,4; a/b = 2,0
* Cpe A = -1,1 (vértice barlavento, sucção)
* Cpe B = -0,8 (zona central lateral)
* Cpe C = +0,7 (barlavento principal, pressão)
* Cpe D = -0,4 (sotavento)
* Cpe E = -1,0 (telhado zona E — barlavento alta sucção)
*/
export const CASE_GALPAO_30x15x6: BlessmannCase = {
id: 'galpao-30x15x6-0deg',
description: 'Galpão 30×15×6 m, telhado duas águas θ=10°, vento 0°',
source: 'Blessmann Cap. 5, Exemplo 5.1 (adaptação)',
tolerance: 0.05,
notes: 'Valores arredondados para 1 casa decimal conforme Tab. 6.',
};
// =============================================================================
// CASO 2: Exemplo de vento em edifício alto (Cap. 9)
// =============================================================================
/**
* Edifício 60 × 20 × 100 m (a × b × h), Cat. III, S₃ grupo 3 (S₃ = 1).
*
* Esperado:
* - Classe C (maior dimensão > 50 m)
* - S₂(100 m, III, C) ≈ 1,15
* - Vₖ = 40 × 1 × 1,15 × 1 = 46 m/s
* - q(100m) ≈ 1,30 kN/m²
*/
export const CASE_EDIFICIO_ALTO_60x20x100: BlessmannCase = {
id: 'edificio-60x20x100',
description: 'Edifício alto 60×20×100 m, Cat. III',
source: 'Blessmann Cap. 9 (efeitos dinâmicos)',
tolerance: 0.03,
};
// =============================================================================
// CASO 3: Reservatório cilíndrico (Tab. 13)
// =============================================================================
/**
* Silo cilíndrico vertical, d = 8 m, h = 24 m, superfície lisa, topo
* aberto, vento V₀ = 35 m/s, Cat. II.
*
* Esperado:
* - h/d = 24/8 = 3 → comportamento próximo a h/d ≥ 2,5 (Tabela 13 usa
* coluna "h/d ≥ 2,5")
* - Re = 70 000 × 35 × 8 = 19,6 × 10⁶ (supercrítico)
* - Para cilindro liso em θ = 0°: Cpe ≈ -1,0 (sotavento); ≈ +1,0 (barlavento)
* Nota: valores reais dependem da interpolação fina, aqui usamos a
* referência simplificada do Blessmann.
* - Cpi para topo aberto (h/d ≥ 0,3): Cpi = -0,8
*/
export const CASE_SILO_CILINDRICO: BlessmannCase = {
id: 'silo-cilindrico-d8-h24',
description: 'Silo cilíndrico d=8m, h=24m, liso, topo aberto',
source: 'Blessmann Cap. 6 (Tabela 13 e Fig. 16)',
tolerance: 0.15,
notes: 'Tolerância mais ampla por causa de interpolação fina entre chaves da Tabela 13.',
};
// =============================================================================
// CASO 4: S₂ em diferentes categorias e alturas (Tab. 3, Anexo A)
// =============================================================================
/**
* Variação de S₂ com altura e categoria — conferência dos valores tabelados.
*
* h=10 m, Cat. II, Classe A: S₂ = 1,00
* h=30 m, Cat. III, Classe B: S₂ ≈ 1,03
* h=100 m, Cat. V, Classe C: S₂ ≈ 1,01 (saturação)
*
* Fonte: NBR 6123:2023 Tab. 3
*/
export const CASE_S2_TAB3: BlessmannCase = {
id: 's2-tabela-3',
description: 'S₂ em diferentes (h, categoria, classe)',
source: 'NBR 6123:2023 Tab. 3',
tolerance: 0.02,
};
// =============================================================================
// CASO 5: S₃ analítico por Pₘ e vida útil (Anexo B)
// =============================================================================
/**
* Cálculo analítico de S₃ conforme fórmula do Anexo B:
* S₃ = 0,54 · (-ln(1 - Pₘ))^(-1/7) · m^(1/7)
*
* Casos:
* - Pₘ = 0,63, m = 50 anos: S₃ = 1,00 (referência)
* - Pₘ = 0,10, m = 50 anos: S₃ ≈ 1,42
* - Pₘ = 0,63, m = 2 anos: S₃ ≈ 0,60
*/
export const CASE_S3_ANALITICO: BlessmannCase = {
id: 's3-analitico-anexo-b',
description: 'S₃ via fórmula analítica do Anexo B',
source: 'NBR 6123:2023 Anexo B',
tolerance: 0.02,
};
// =============================================================================
// CASO 6: Vento em ponte — Pse (Cap. 11)
// =============================================================================
/**
* Ponte com vão Lₚ = 120 m, largura B = 14 m, altura do tabuleiro z = 15 m,
* Cat. II, S₁ = 1, V₀ = 40 m/s.
*
* Esperado:
* - Vₖ(15m, II, A) ≈ 40 m/s
* - V_it = 0,65 × 40 × 1 × 1 × (15/10)^0,10 ≈ 26,5 m/s
* - ρ = 1,226 kg/m³
* - f_v = 0,6 Hz, m = 18000 kg/m → Pse ≈ ρ·V_it² / (m·f_v²) ≈ 1,226 × 26,5² / (18000 × 0,36) ≈ 0,13
* - Classe 2 (efeitos dinâmicos devem ser avaliados)
*/
export const CASE_PONTE_120m: BlessmannCase = {
id: 'ponte-120m-pse',
description: 'Ponte 120m vão, tabuleiro 14m de largura',
source: 'NBR 6123:2023 sec. 11.2.2',
tolerance: 0.10,
};
// =============================================================================
// CASO 7: Cobertura isolada (Tab. 24)
// =============================================================================
/**
* Cobertura isolada a duas águas, θ = 15°, profundidade b = 6 m, altura
* livre h = 1,5 m. Vento V₀ = 35 m/s, Cat. II.
*
* Para 0,07 ≤ tg(15°) = 0,268 ≤ 0,4 → Carregamento 1 aplica.
* Para h ≤ tg(θ)·b/2 = 0,268 × 6 / 2 = 0,80 m: limite OK (h = 1,5 > 0,80).
* Portanto caso NÃO aplica (limite excedido).
*/
export const CASE_COBERTURA_ISOLADA: BlessmannCase = {
id: 'cob-isolada-limite',
description: 'Verificação de limites para cobertura isolada',
source: 'NBR 6123:2023 sec. 7.2.1 (Tabela 25)',
tolerance: 0.0,
};
// =============================================================================
// CASO 8: Reynolds e Cpe em cilindro (Blessmann Cap. 6, Tab. 13)
// =============================================================================
/**
* Cilindro de chaminé d = 1,5 m, h = 30 m, superfície lisa, vento V₀ = 40 m/s,
* Cat. II. Avaliar Cpe em θ = 0°, 90°, 180° com Re = 70 000 × 40 × 1,5 = 4,2×10⁶.
*
* Para h/d = 20 ≥ 2,5, liso: Cpe(0°) = +1,0; Cpe(90°) = -1,0; Cpe(180°) = -0,4
* (valores aproximados da Tab. 13 para liso, h/d ≥ 2,5).
*/
export const CASE_CHAMINE_CILINDRO: BlessmannCase = {
id: 'chamine-d1.5-h30',
description: 'Chaminé d=1.5m, h=30m, liso',
source: 'NBR 6123:2023 Tab. 13 (regime supercrítico)',
tolerance: 0.20,
notes: 'Tolerância ampla por interpolação bilinear entre chaves.',
};
// =============================================================================
// CASO 9: Vento em muro/placa (Cap. 7, Tab. 23)
// =============================================================================
/**
* Placa de publicidad: = 6 m, hₐ = 2 m, α = 90°, sem placas de extremidade.
*
* Esperado para /hₐ = 3 (entre 10 e 60):
* - Para α = 90°, sem placas: C_f ≈ 1,2 + 0,03·(/hₐ) ≈ 1,2
* (interpolação entre /hₐ = 1 (C_f=1,2) e /hₐ = 10 (C_f=1,2))
* - Cf ≈ 1,2 (regime 2D)
*/
export const CASE_PLACA_PUBLICIDADE: BlessmannCase = {
id: 'placa-publicidade-6x2',
description: 'Placa 6×2 m sem placas de extremidade',
source: 'NBR 6123:2023 Tab. 23 (muro/placa)',
tolerance: 0.15,
};
// =============================================================================
// CASO 10: S₂ via fórmula teórica vs tabela (M9.1 cross-check)
// =============================================================================
/**
* Comparação S₂(tabela) vs S₂(fórmula teórica):
* S₂ = b · Fᵣ · (z/10)^p
*
* Para z = 30 m, Cat. II, Classe A (maior dimensão ≤ 20):
* - b = 1,00, Fᵣ = 1,00, p = 0,085
* - S₂(fórmula) = 1,00 × 1,00 × (30/10)^0,085 = 3^0,085 ≈ 1,099
* - S₂(tabela) = 1,10 (lido da Tab. 3)
*/
export const CASE_S2_FORMULA_VS_TABELA: BlessmannCase = {
id: 's2-formula-vs-tabela',
description: 'S₂ fórmula teórica vs Tabela 3 (consistência)',
source: 'NBR 6123:2023 Tab. 1 + Tab. 3',
tolerance: 0.005,
notes: 'Diferença < 0,5% esperada (mesma fórmula).',
};
// =============================================================================
// Lista consolidada
// =============================================================================
export const BLESSMANN_CASES = {
CASE_GALPAO_30x15x6,
CASE_EDIFICIO_ALTO_60x20x100,
CASE_SILO_CILINDRICO,
CASE_S2_TAB3,
CASE_S3_ANALITICO,
CASE_PONTE_120m,
CASE_COBERTURA_ISOLADA,
CASE_CHAMINE_CILINDRO,
CASE_PLACA_PUBLICIDADE,
CASE_S2_FORMULA_VS_TABELA,
} as const;
// =============================================================================
// Helpers para os testes
// =============================================================================
/**
* Compara valor calculado com esperado dentro de tolerância.
*/
export function isWithinTolerance(calculated: number, expected: number, tolerance: number): boolean {
if (expected === 0) return Math.abs(calculated) <= tolerance;
return Math.abs((calculated - expected) / expected) <= tolerance;
}
/**
* Calcula S₂ via fórmula teórica e compara com valor tabelado.
* Usado no CASO 10.
*/
export function s2FormulaFromBFR(
b: number,
fr: number,
z: number,
p: number,
): number {
return Number((b * fr * Math.pow(z / 10, p)).toFixed(3));
}
/**
* Tipo exportado para reuso em testes.
*/
export type Category = TerrainCategory;