Как лучше всего решать уравнения в частных производных в Python точно, но быстроPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как лучше всего решать уравнения в частных производных в Python точно, но быстро

Сообщение Anonymous »

Попытка воспроизвести раздел 4.1.3 «Выбросы твердых материалов» согласно этому PDF-файлу.
https://www.rivm.nl/bibliotheek/rapporten/2017-0197.pdf
Выпустил эту версию модели и это лучшее, что мне досталось.

Код: Выделить всё

# Import necessary libraries
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# -------------------------------
# Constants
# -------------------------------
R_J_per_mol_K = 8.314                                      # Universal gas constant [J/(mol·K)]

# -------------------------------
# Scenario Selection
# -------------------------------
selected_scenario = 1                                       # Change this to select scenarios (1, 2, or 3)

# -------------------------------
# Input Parameters
# -------------------------------
# General Parameters (Common across all scenarios)
body_weight_kg = 60                                         # Body weight [kg]
frequency_per_year = 1                                      # Frequency of exposure [per year]

# Scenario Specific Parameters
if selected_scenario == 1:
# Scenario 1 (Base Scenario)
product_surface_area_cm2 = 10                           # Product surface area [cm²]
product_thickness_mm = 5                                # Product thickness [mm]
product_density_g_per_cm3 = 0.1                         # Product density [g/cm³]
diffusion_coefficient_m2_per_s = 1E-08                  # Diffusion coefficient [m²/s]
weight_fraction_substance = 0.6                         # Weight fraction of the substance [fraction]
product_air_partition_coefficient = 0.5                 # Product/air partition coefficient [-]

room_volume_m3 = 0.5                                    # Room volume [m³]
ventilation_rate_per_hour = 58                          # Ventilation rate [per hour]
inhalation_rate_m3_per_hour = 10                        # Inhalation rate [m³/hr]

start_exposure_h = 1                                    # Start exposure time [hours]
exposure_duration_h = 2                                 # Exposure duration [hours]
mass_transfer_coefficient_m_per_h = 10                  # Mass transfer coefficient [m/h]

#Absorption
absorption_fraction = 1                                 # Absorption fraction [fraction]

# -------------------------------
# Unit Conversions
# -------------------------------
product_surface_area_m2 = product_surface_area_cm2 / 10000  # Convert cm² to m²
product_thickness_m = product_thickness_mm / 1000           # Convert mm to m
product_density_kg_per_m3 = product_density_g_per_cm3 * 1000  # Convert g/cm³ to kg/m³
mass_transfer_coefficient_m_per_s = mass_transfer_coefficient_m_per_h / 3600  # Convert m/h to m/s
ventilation_rate_per_s = ventilation_rate_per_hour / 3600   # Convert per hour to per second
start_exposure_s = start_exposure_h * 3600                  # Convert hours to seconds
exposure_duration_s = exposure_duration_h * 3600            # Convert hours to seconds
total_emission_time_s = start_exposure_s + exposure_duration_s  # Total time to simulate [s]
frequency_per_day = frequency_per_year / 365                # Frequency per day
inhalation_rate_m3_per_s = inhalation_rate_m3_per_hour / 3600  # Convert inhalation rate from m³/h to m³/s

# -------------------------------
# Initial Concentrations
# -------------------------------
volume_material_m3 = product_surface_area_m2 * product_thickness_m  # Volume of material [m³]
mass_material_kg = volume_material_m3 * product_density_kg_per_m3   # Mass of material [kg]
mass_substance_initial_kg = mass_material_kg * weight_fraction_substance  # Initial mass of substance [kg]
concentration_initial_kg_per_m3 = mass_substance_initial_kg / volume_material_m3  # Initial concentration [kg/m³]
N = 1000                                                    # Reduced number of layers for faster computation
dx = product_thickness_m / (N - 1)                         # Spatial step size [m]
t_eval = np.linspace(0, total_emission_time_s, 2000)       # Time points for evaluation

# -------------------------------
# Emission Model Definition
# -------------------------------
# Precompute constants
D = diffusion_coefficient_m2_per_s
hm = mass_transfer_coefficient_m_per_s
K = product_air_partition_coefficient
S = product_surface_area_m2
V = room_volume_m3
q = ventilation_rate_per_s

def emission_model(t,  y):
C = y[:-1]                                             # Concentration in the material layers [kg/m³]
y_air = y[-1]                                          # Air concentration [kg/m³]

dCdt = np.zeros_like(C)

# No-flux boundary condition at x=0 (back surface)
dCdt[0] = D * (C[1] - C[0]) / dx**2                    # Diffusion at back surface [kg/(m²·s²)]

# Diffusion in the material
for i in range(1, N - 1):
dCdt[i] = D * (C[i + 1] - 2 * C[i] + C[i - 1]) / dx**2  # Diffusion in layers [kg/(m²·s²)]

# Flux boundary condition at x=L (front surface)
J_diff = -D * (C[N - 1] - C[N - 2]) / dx               # Diffusion flux at surface [kg/(m²·s)]
J_air = hm * (C[N - 1] / K - y_air)                    # Mass transfer to air [kg/(m²·s)]

dCdt[N - 1] = D * (C[N - 2] - C[N - 1]) / dx**2 - J_air / dx  # Change in surface layer concentration [kg/m³/s]

dy_air_dt = (S / V) * hm * (C[N - 1] / K - y_air) - q * y_air  # Change in air concentration [kg/m³/s]

return np.concatenate((dCdt, [dy_air_dt]))

# -------------------------------
# Initial Conditions
# -------------------------------
C0 = np.full(N, concentration_initial_kg_per_m3)           # Initial concentration in material layers [kg/m³]
y_air_0 = 0.0                                              # Initial air concentration [kg/m³]
y0 = np.concatenate((C0, [y_air_0]))                       # Initial condition vector

# -------------------------------
# Solve the ODE system with BDF solver for speed and accuracy
# -------------------------------
solution = solve_ivp(emission_model, [0, total_emission_time_s], y0, t_eval=t_eval, method='BDF', vectorized=False)

# Extract results
C_material = solution.y[:-1, :]                            # Material concentrations over time [kg/m³]
y_air = solution.y[-1, :]                                  # Air concentrations over time [kg/m³]
time = solution.t                                          # Time vector [s]

# -------------------------------
# Extract Air Concentration during Exposure
# -------------------------------
exposure_indices = np.where((time >= start_exposure_s) & (time = start_exposure_s               # Mask for exposure period
incremental_external_dose_mg_per_kg_bw = np.zeros_like(t_s_plot)  # Initialize dose array
incremental_external_dose_mg_per_kg_bw[exposure_mask] = (C_t_mg_per_m3[exposure_mask] * delta_inhaled_volume_m3) / body_weight_kg  # Incremental dose [mg/kg bw]
cumulative_external_dose_mg_per_kg_bw = np.cumsum(incremental_external_dose_mg_per_kg_bw)  # Cumulative external dose [mg/kg bw]
cumulative_internal_dose_mg_per_kg_bw = cumulative_external_dose_mg_per_kg_bw * absorption_fraction  # Cumulative internal dose [mg/kg bw]

# -------------------------------
# Visualization
# -------------------------------
fig, axs = plt.subplots(1, 3, figsize=(24, 6))             # Create a figure with three subplots

# 1. Air Concentration Over Time
axs[0].plot(t_s_plot / 3600, C_t_mg_per_m3, label='Air Concentration (mg/m³)', color='blue')
axs[0].set_title('Air Concentration Over Time')
axs[0].set_xlabel('Time (hours)')
axs[0].set_ylabel('Concentration (mg/m³)')
axs[0].grid(True)
axs[0].legend()
axs[0].axvline(x=start_exposure_s / 3600, color='red', linestyle='--', label='Exposure Start')
axs[0].axvline(x=(start_exposure_s + 15 * 60) / 3600, color='green', linestyle='--', label='15 min after Exposure Start')
axs[0].legend()

# 2.  Cumulative External Dose Over Time
axs[1].plot(t_s_plot / 3600, cumulative_external_dose_mg_per_kg_bw, label='Cumulative External Dose (mg/kg bw)', color='orange')
axs[1].set_title('External Dose Over Time')
axs[1].set_xlabel('Time (hours)')
axs[1].set_ylabel('Dose (mg/kg bw)')
axs[1].grid(True)
axs[1].legend()
axs[1].axvline(x=start_exposure_s / 3600, color='red', linestyle='--', label='Exposure Start')

# 3. Cumulative Internal Dose Over Time (Adjusted for absorption)
axs[2].plot(t_s_plot / 3600, cumulative_internal_dose_mg_per_kg_bw, label='Cumulative Internal Dose (mg/kg bw)', color='green')
axs[2].set_title('Internal Dose Over Time')
axs[2].set_xlabel('Time (hours)')
axs[2].set_ylabel('Dose (mg/kg bw)')
axs[2].grid(True)
axs[2].legend()
axs[2].axvline(x=start_exposure_s / 3600, color='red', linestyle='--', label='Exposure Start')

plt.tight_layout()                                        # Adjust layout for clarity
plt.show()                                                # Show the plots

# -------------------------------
# End of Script
# -------------------------------
РЕЗУЛЬТАТЫ:

Код: Выделить всё

Mean Event Concentration: 1.3e-01 mg/m³
Mean Concentration on Day of Exposure: 1.1e-02 mg/m³
Year Average Concentration: 2.9e-05 mg/m³
External Event Dose: 4.3e-02 mg/kg bw
External Dose on Day of Exposure: 4.3e-02 mg/kg bw
Internal Event Dose: 4.3e-02 mg/kg bw
Internal Dose on Day of Exposure: 4.3e-02 mg/kg bw/day
Internal Year Average Dose: 1.2e-04 mg/kg bw/day
Изображение

ОЖИДАЕТСЯ:
Изображение

Изображение

Изображение

Код: Выделить всё

Mean event concentration
1.2 × 10⁻¹  mg/m³
average air concentration on exposure event. Note: depends strongly on chosen exposure duration
Mean concentration on day of exposure
9.6 × 10⁻³  mg/m³
average air concentration over the day (accounts for the number of events on one day)
Year average concentration
2.6 × 10⁻⁵  mg/m³
mean daily air concentration averaged over a year
External event dose
3.8 × 10⁻²  mg/kg bw
the amount that can potentially be absorbed per kg body weight during one event
External dose on day of exposure
3.8 × 10⁻²  mg/kg bw
the amount that can potentially be absorbed per kg body weight during one day
Internal event dose
3.8 × 10⁻²  mg/kg bw
absorbed dose per kg body weight during one exposure event
Internal dose on day of exposure
3.8 × 10⁻²  mg/kg bw/day
absorbed dose per kg body weight during one day. Note: these can be higher than the ‘event dose’ for exposure frequencies larger than 1 per day.
Internal year average dose
1.1 × 10⁻⁴  mg/kg bw/day
daily absorbed dose per kg body weight averaged over a year.
Итак, две проблемы:
  • Результаты не совпадают настолько, насколько хотелось бы.
  • Он может загружаться очень медленно. Я адаптировал его так, чтобы он работал быстрее, но все же. Если я увеличу количество слоев, чтобы получить более точные результаты, это будет очень медленно и не намного точнее.
Когда я сравниваю это с веб-приложением, которое я использую, чтобы получить ожидаемые результаты, они происходят почти мгновенно.
Так что на самом деле у меня всего несколько вопросов.
Любой, кто знаком с PDE/ODE и коэффициентами массопередачи. Как лучше всего решить эту проблему?
Я считаю, что этот сценарий, возможно, очень неэффективный способ воспроизвести модель.

Подробнее здесь: https://stackoverflow.com/questions/790 ... but-quickl
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • Как решать сложные уравнения численно в Python?
    Anonymous » » в форуме Python
    0 Ответы
    24 Просмотры
    Последнее сообщение Anonymous
  • Как решать сложные уравнения численно в Python?
    Anonymous » » в форуме Python
    0 Ответы
    22 Просмотры
    Последнее сообщение Anonymous
  • Точно, когда один начинающий решать вопрос LeetCode самостоятельно с помощью их подхода? Когда такая интукация попала? [
    Anonymous » » в форуме C++
    0 Ответы
    4 Просмотры
    Последнее сообщение Anonymous
  • Как использоватьsolve_ivp для решения уравнений в частных производных спектральным методом?
    Anonymous » » в форуме Python
    0 Ответы
    20 Просмотры
    Последнее сообщение Anonymous
  • API данных Youtube — получение частных и частных плейлистов
    Anonymous » » в форуме Php
    0 Ответы
    17 Просмотры
    Последнее сообщение Anonymous

Вернуться в «Python»