空气污染控制设计Skill air-pollution-control

这项技能提供全面的空气污染控制系统设计能力,包括技术选择、设备尺寸、效率计算和法规合规性展示(BACT/LAER/MACT)。

环境影响评价 0 次安装 5 次浏览 更新于 2/25/2026

空气污染控制设计技能

空气污染控制设备的选择和设计,包括湿式洗涤器、布袋除尘器、电除尘器、氧化器和BACT/LAER确定。

目的

这项技能提供了设计空气污染控制系统的全面能力,包括技术选择、设备尺寸、效率计算和法规合规性展示(BACT/LAER/MACT)。

能力

洗涤器设计

  • 湿式洗涤器技术选择
  • 填充塔设计和尺寸
  • 喷雾塔配置
  • 文氏洗涤器设计
  • 压降计算
  • 液气比优化
  • 化学剂量要求

布袋除尘器和织物过滤器尺寸

  • 过滤介质选择
  • 气布比确定
  • 分隔设计
  • 脉冲喷射与反吹风清洁
  • 压降估计
  • 布袋寿命预测
  • 灰斗尺寸

电除尘器设计

  • 收集效率计算
  • 特定收集面积(SCA)确定
  • 板间距和配置
  • 电场强度
  • 敲击系统设计
  • 电阻率考虑
  • 电源尺寸

热和催化氧化器规格

  • 破坏效率要求
  • 温度和停留时间
  • 热回收选项(再生、回收)
  • 催化氧化器催化剂选择
  • 辅助燃料需求
  • 转换能力

活性炭吸附系统设计

  • 活性炭选择
  • 吸附容量计算
  • 穿透时间估计
  • 床尺寸
  • 再生系统设计
  • 碳更换频率

控制效率计算

  • 出口排放率确定
  • 去除效率验证
  • 烟气测试相关性
  • 连续监测要求

压降和能量分析

  • 系统压降计算
  • 风机功率要求
  • 运营成本估计
  • 能源优化机会

BACT/LAER/MACT确定

  • 控制技术识别
  • 成本效益分析
  • 技术可行性评估
  • 法规数据库研究
  • 从上到下的BACT分析

先决条件

安装

pip install numpy scipy pandas matplotlib

可选依赖

# 用于化学属性查找
pip install chemicals thermo

# 用于可视化
pip install plotly

使用模式

布袋除尘器设计

import numpy as np
from dataclasses import dataclass
from typing import Dict, List, Optional

@dataclass
class GasStreamData:
    """气体流特性"""
    flow_rate_acfm: float
    temperature_f: float
    moisture_pct: float
    particulate_loading_gr_acf: float
    particle_size_micron: float
    gas_composition: Dict[str, float] = None

@dataclass
class BaghouseDesign:
    """布袋除尘器设计参数"""
    filter_media: str
    bag_diameter_in: float
    bag_length_ft: float
    air_to_cloth_ratio: float
    cleaning_type: str  # 'pulse_jet', 'reverse_air', 'shaker'

class BaghouseCalculator:
    """脉冲喷射布袋除尘器尺寸计算"""

    # 按应用推荐的气布比(acfm/ft2)
    AC_RATIOS = {
        'cement': {'gross': 4.0, 'net': 3.5},
        'coal': {'gross': 6.0, 'net': 5.0},
        'foundry': {'gross': 4.5, 'net': 3.5},
        'steel': {'gross': 5.0, 'net': 4.0},
        'chemical': {'gross': 5.5, 'net': 4.5},
        'pharmaceutical': {'gross': 3.5, 'net': 3.0},
        'general': {'gross': 5.0, 'net': 4.0}
    }

    # 过滤介质属性
    MEDIA_PROPERTIES = {
        'polyester': {'max_temp_f': 275, 'cost_factor': 1.0, 'acid_resist': 'good'},
        'polypropylene': {'max_temp_f': 200, 'cost_factor': 0.9, 'acid_resist': 'excellent'},
        'nomex': {'max_temp_f': 400, 'cost_factor': 3.0, 'acid_resist': 'good'},
        'fiberglass': {'max_temp_f': 500, 'cost_factor': 2.5, 'acid_resist': 'excellent'},
        'ptfe': {'max_temp_f': 500, 'cost_factor': 8.0, 'acid_resist': 'excellent'},
        'p84': {'max_temp_f': 500, 'cost_factor': 5.0, 'acid_resist': 'good'}
    }

    def select_filter_media(self, gas: GasStreamData) -> str:
        """根据气体条件选择合适的过滤介质"""
        temp = gas.temperature_f

        suitable = []
        for media, props in self.MEDIA_PROPERTIES.items():
            if props['max_temp_f'] >= temp:
                suitable.append((media, props))

        # 返回成本最低的合适介质
        suitable.sort(key=lambda x: x[1]['cost_factor'])
        return suitable[0][0] if suitable else 'ptfe'

    def calculate_filter_area(self, gas: GasStreamData,
                              application: str = 'general',
                              use_net_ratio: bool = True) -> Dict:
        """计算所需过滤面积"""
        ratios = self.AC_RATIOS.get(application, self.AC_RATIOS['general'])
        ac_ratio = ratios['net'] if use_net_ratio else ratios['gross']

        filter_area = gas.flow_rate_acfm / ac_ratio

        return {
            'gas_flow_acfm': gas.flow_rate_acfm,
            'air_to_cloth_ratio': ac_ratio,
            'filter_area_sqft': filter_area
        }

    def size_baghouse(self, gas: GasStreamData,
                      bag_diameter_in: float = 6.0,
                      bag_length_ft: float = 10.0,
                      application: str = 'general') -> Dict:
        """尺寸完整的布袋除尘器系统"""

        # 过滤介质选择
        media = self.select_filter_media(gas)

        # 计算过滤面积
        area_calc = self.calculate_filter_area(gas, application)
        required_area = area_calc['filter_area_sqft']

        # 布袋面积计算
        bag_area = np.pi * (bag_diameter_in / 12) * bag_length_ft  # 每袋平方英尺

        # 布袋数量
        num_bags = np.ceil(required_area / bag_area)

        # 分隔(通常每排8-16个布袋,每个分隔2-4排)
        bags_per_compartment = 32  # 典型
        num_compartments = np.ceil(num_bags / bags_per_compartment)

        # 压降估计(脉冲喷射的典型值)
        dp_filter = 2.5  # 英寸水柱,用于清洁过滤器
        dp_tubesheet = 0.5
        dp_inlet_outlet = 1.0
        total_dp = dp_filter + dp_tubesheet + dp_inlet_outlet

        # 灰斗尺寸(4:1转换,8小时存储)
        dust_rate_lb_hr = gas.particulate_loading_gr_acf * gas.flow_rate_acfm * 60 / 7000
        hopper_volume = dust_rate_lb_hr * 8 / 50  # 50 lb/cf 堆积密度

        return {
            'filter_media': media,
            'required_filter_area_sqft': required_area,
            'bag_diameter_in': bag_diameter_in,
            'bag_length_ft': bag_length_ft,
            'area_per_bag_sqft': bag_area,
            'total_bags': int(num_bags),
            'num_compartments': int(num_compartments),
            'air_to_cloth_gross': gas.flow_rate_acfm / (num_bags * bag_area),
            'pressure_drop_in_wc': total_dp,
            'dust_rate_lb_hr': dust_rate_lb_hr,
            'hopper_volume_cf': hopper_volume,
            'max_temp_f': self.MEDIA_PROPERTIES[media]['max_temp_f']
        }

# 示例用法
gas = GasStreamData(
    flow_rate_acfm=50000,
    temperature_f=350,
    moisture_pct=8,
    particulate_loading_gr_acf=2.0,
    particle_size_micron=5
)

calculator = BaghouseCalculator()
design = calculator.size_baghouse(gas, application='cement')

print(f"Filter media: {design['filter_media']}")
print(f"Total bags: {design['total_bags']}")
print(f"Compartments: {design['num_compartments']}")
print(f"A/C ratio: {design['air_to_cloth_gross']:.2f} acfm/sqft")
print(f"Pressure drop: {design['pressure_drop_in_wc']:.1f} in w.c.")

湿式洗涤器设计

class WetScrubberDesign:
    """湿式洗涤器设计计算"""

    def packed_tower_sizing(self, gas_flow_acfm: float,
                           pollutant: str,
                           inlet_conc_ppm: float,
                           outlet_conc_ppm: float,
                           scrubbing_liquid: str = 'water') -> Dict:
        """尺寸填充塔进行气体吸收"""

        # 去除效率
        efficiency = (inlet_conc_ppm - outlet_conc_ppm) / inlet_conc_ppm

        # 气体速度(填充塔的典型范围3-6 ft/s)
        gas_velocity_fps = 4.5

        # 横截面积
        area_sqft = (gas_flow_acfm / 60) / gas_velocity_fps

        # 直径
        diameter_ft = np.sqrt(4 * area_sqft / np.pi)

        # 基于NTU的高度(简化)
        ntu = -np.log(1 - efficiency)  # 传递单元数
        htu = 2.5  # 传递单元高度(ft)- 2"填料典型
        packing_height = ntu * htu

        # L/G比率(液气比)
        lg_ratio = 10  # gpm每1000 acfm典型

        # 液体流量
        liquid_flow_gpm = gas_flow_acfm * lg_ratio / 1000

        # 压降(填料每英尺1-2英寸水柱典型)
        pressure_drop = packing_height * 1.5

        return {
            'diameter_ft': diameter_ft,
            'packing_height_ft': packing_height,
            'total_height_ft': packing_height * 1.5,  # 内部件增加
            'cross_section_sqft': area_sqft,
            'gas_velocity_fps': gas_velocity_fps,
            'liquid_flow_gpm': liquid_flow_gpm,
            'lg_ratio_gpm_per_kacfm': lg_ratio,
            'pressure_drop_in_wc': pressure_drop,
            'removal_efficiency_pct': efficiency * 100,
            'ntu': ntu
        }

    def venturi_scrubber_sizing(self, gas_flow_acfm: float,
                                particulate_loading_gr_acf: float,
                                target_efficiency_pct: float) -> Dict:
        """尺寸文氏洗涤器进行颗粒物去除"""

        # 压降与效率相关性(Johnstone方程)
        # 效率随压降增加而增加
        # 对于99%效率,通常需要30-50英寸水柱

        if target_efficiency_pct >= 99:
            pressure_drop = 50
        elif target_efficiency_pct >= 95:
            pressure_drop = 30
        elif target_efficiency_pct >= 90:
            pressure_drop = 20
        else:
            pressure_drop = 10

        # L/G比率(效率越高,比率越高)
        lg_ratio = 8 + (target_efficiency_pct - 90) * 0.2

        # 喉部速度(通常12,000-24,000 fpm)
        throat_velocity = 15000  # fpm

        # 喉部面积
        throat_area = gas_flow_acfm / throat_velocity

        # 液体流量
        liquid_flow = gas_flow_acfm * lg_ratio / 1000

        return {
            'throat_area_sqft': throat_area,
            'throat_velocity_fpm': throat_velocity,
            'pressure_drop_in_wc': pressure_drop,
            'liquid_flow_gpm': liquid_flow,
            'lg_ratio': lg_ratio,
            'expected_efficiency_pct': target_efficiency_pct
        }

# 示例用法
scrubber = WetScrubberDesign()

# SO2去除填充塔
packed = scrubber.packed_tower_sizing(
    gas_flow_acfm=30000,
    pollutant='SO2',
    inlet_conc_ppm=1000,
    outlet_conc_ppm=50
)
print(f"Packed tower diameter: {packed['diameter_ft']:.1f} ft")
print(f"Packing height: {packed['packing_height_ft']:.1f} ft")
print(f"Removal efficiency: {packed['removal_efficiency_pct']:.1f}%")

# 颗粒物文氏
venturi = scrubber.venturi_scrubber_sizing(
    gas_flow_acfm=30000,
    particulate_loading_gr_acf=5.0,
    target_efficiency_pct=95
)
print(f"
Venturi pressure drop: {venturi['pressure_drop_in_wc']} in w.c.")
print(f"Liquid flow: {venturi['liquid_flow_gpm']:.0f} gpm")

BACT分析

class BACTAnalysis:
    """最佳可用控制技术分析"""

    # 控制技术数据库(简化)
    CONTROL_TECHNOLOGIES = {
        'PM': [
            {'name': 'Baghouse', 'efficiency': 99.9, 'cost_per_ton': 500},
            {'name': 'ESP', 'efficiency': 99.5, 'cost_per_ton': 400},
            {'name': 'Cyclone', 'efficiency': 90, 'cost_per_ton': 100},
            {'name': 'Wet Scrubber', 'efficiency': 95, 'cost_per_ton': 600}
        ],
        'SO2': [
            {'name': 'Wet FGD', 'efficiency': 98, 'cost_per_ton': 800},
            {'name': 'Dry FGD', 'efficiency': 95, 'cost_per_ton': 600},
            {'name': 'SDA', 'efficiency': 92, 'cost_per_ton': 500}
        ],
        'NOx': [
            {'name': 'SCR', 'efficiency': 90, 'cost_per_ton': 2000},
            {'name': 'SNCR', 'efficiency': 60, 'cost_per_ton': 500},
            {'name': 'Low-NOx Burner', 'efficiency': 50, 'cost_per_ton': 200}
        ],
        'VOC': [
            {'name': 'RTO', 'efficiency': 99, 'cost_per_ton': 3000},
            {'name': 'Catalytic Oxidizer', 'efficiency': 98, 'cost_per_ton': 2500},
            {'name': 'Carbon Adsorption', 'efficiency': 95, 'cost_per_ton': 1500},
            {'name': 'Condenser', 'efficiency': 85, 'cost_per_ton': 800}
        ]
    }

    def top_down_bact(self, pollutant: str, uncontrolled_tpy: float,
                      cost_threshold: float = 15000) -> List[Dict]:
        """执行自上而下的BACT分析

        参数:
            pollutant: 污染物类型(PM, SO2, NOx, VOC)
            uncontrolled_tpy: 未控制排放量(吨/年)
            cost_threshold: 最大可接受成本($/吨移除)
        """
        technologies = self.CONTROL_TECHNOLOGIES.get(pollutant, [])

        # 按效率排序(最高优先)- 自上而下的方法
        technologies = sorted(technologies, key=lambda x: x['efficiency'], reverse=True)

        results = []
        for tech in technologies:
            tons_removed = uncontrolled_tpy * tech['efficiency'] / 100
            controlled_emissions = uncontrolled_tpy - tons_removed
            annual_cost = tech['cost_per_ton'] * tons_removed
            cost_effectiveness = tech['cost_per_ton']

            is_feasible = cost_effectiveness <= cost_threshold

            results.append({
                'technology': tech['name'],
                'efficiency_pct': tech['efficiency'],
                'controlled_emissions_tpy': controlled_emissions,
                'tons_removed_tpy': tons_removed,
                'annual_cost': annual_cost,
                'cost_effectiveness': cost_effectiveness,
                'is_cost_effective': is_feasible,
                'bact_candidate': is_feasible
            })

            if is_feasible:
                break  # 第一个成本效益选项是BACT

        return results

    def generate_bact_report(self, pollutant: str,
                             uncontrolled_tpy: float) -> str:
        """生成BACT确定报告"""
        analysis = self.top_down_bact(pollutant, uncontrolled_tpy)

        report = f"""
BACT DETERMINATION - {pollutant}
================================
Uncontrolled Emissions: {uncontrolled_tpy:.1f} tpy

TOP-DOWN ANALYSIS:

"""
        for i, tech in enumerate(analysis, 1):
            status = "BACT SELECTED" if tech['bact_candidate'] else \
                     "Eliminated - Cost" if not tech['is_cost_effective'] else "Evaluated"

            report += f"""
Step {i}: {tech['technology']}
  Control Efficiency: {tech['efficiency_pct']}%
  Controlled Emissions: {tech['controlled_emissions_tpy']:.2f} tpy
  Cost Effectiveness: ${tech['cost_effectiveness']:,.0f}/ton
  Status: {status}
"""

        # 找到BACT
        bact = next((t for t in analysis if t['bact_candidate']), None)
        if bact:
            report += f"""
BACT DETERMINATION:
  Selected Technology: {bact['technology']}
  Emission Limit: {bact['controlled_emissions_tpy']:.2f} tpy
  Control Efficiency: {bact['efficiency_pct']}%
"""

        return report

# 示例用法
bact = BACTAnalysis()

report = bact.generate_bact_report('NOx', uncontrolled_tpy=100)
print(report)

# VOC BACT
voc_analysis = bact.top_down_bact('VOC', uncontrolled_tpy=50)
for tech in voc_analysis:
    print(f"{tech['technology']}: {tech['efficiency_pct']}% - "
          f"${tech['cost_effectiveness']}/ton - "
          f"{'BACT' if tech['bact_candidate'] else 'Eliminated'}")

使用指南

何时使用此技能

  • 空气污染控制系统设计
  • 许可证申请准备
  • BACT/LAER/MACT确定
  • 控制设备优化
  • 减排项目

最佳实践

  1. 在设计前彻底表征排放
  2. 考虑多个控制选项用于BACT
  3. 在尺寸中考虑变化的操作条件
  4. 在设计中包括维护通道
  5. 设计时考虑负载变化
  6. 计划监测以验证性能

流程集成

  • AQ-002: 空气污染控制系统设计(所有阶段)
  • AQ-001: 空气许可证申请开发(BACT确定)

依赖关系

  • numpy: 数值计算
  • scipy: 工程相关性

参考资料

  • EPA空气污染控制技术概况
  • OAQPS控制成本手册
  • EPA RACT/BACT/LAER信息中心