Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions Manuals/FDS_Validation_Guide/Burning_Rate_Chapter.tex
Original file line number Diff line number Diff line change
Expand Up @@ -2988,14 +2988,17 @@ \subsection{USFS/Catchpole Experiments}
\label{USFS_Catchpole_parameter_summary}
\end{figure}

Additionally, neither Fig.~\ref{USFS_Catchpole_parameter_summary} nor the summary scatter plot in Fig.~\ref{RoS_Summary} include information on the cases for which FDS fails to reproduce a spreading fire. All cases tested have a reported spread rate from the experiments, so instances where FDS does not produce sustained fire spread are indicative of limitations in the current model representation. In order to guide future development efforts, Fig.~\ref{USFS_Catchpole_no_spread} attempts to summarize the model performance over the parameter space by showing lines that connect each set of parameters for a given test. Gray lines in the background correspond to successful spread predictions, while colored lines in the foreground are those for which FDS does not sustain fire spread. This highlights problematic areas of the test matrix, such as zero wind speed cases with low values of packing ratio.
Additionally, neither Fig.~\ref{USFS_Catchpole_parameter_summary} nor the summary scatter plot in Fig.~\ref{RoS_Summary} include information on the cases for which FDS fails to reproduce a spreading fire. All cases tested have a reported spread rate from the experiments, so instances where FDS does not produce sustained fire spread are indicative of limitations in the current model representation. In order to guide future development efforts, Fig.~\ref{USFS_Catchpole_no_spread} attempts to summarize the model performance over the full parameter space. Gray points in the background correspond to successful spread predictions, while colored points in the foreground are those for which FDS does not sustain fire spread. This highlights problematic areas of the test matrix, such as zero wind speed cases with low values of packing ratio.

\begin{figure}[ht]
\centering
\begin{tabular}{c}
\includegraphics[height=3.5in]{SCRIPT_FIGURES/USFS_Catchpole/Catchpole_no_spread}
\end{tabular}
\caption[USFS/Catchpole, conditions leading to failed spread predictions]{Parameter combinations for all USFS/Catchpole cases, each connected by a single line. Parameters of surface-to-volume ratio (s), packing ratio (beta), moisture content (M) and wind speed (U) are normalized between 0 (minimum value) and 1 (maximum value). Gray lines in the background are cases where FDS successfully predicts spread, and colored lines in the foreground represent failed (no spread) predictions. Failed prediction lines are colored according to the beta value for a given test in order to help distinguish trends.}
\begin{tabular*}{\textwidth}{l@{\extracolsep{\fill}}r}
\includegraphics[height=2.15in]{SCRIPT_FIGURES/USFS_Catchpole/Catchpole_no_spread_MF} &
\includegraphics[height=2.15in]{SCRIPT_FIGURES/USFS_Catchpole/Catchpole_no_spread_PPMC} \\
\includegraphics[height=2.15in]{SCRIPT_FIGURES/USFS_Catchpole/Catchpole_no_spread_EXSC} &
\includegraphics[height=2.15in]{SCRIPT_FIGURES/USFS_Catchpole/Catchpole_no_spread_EX} \\
\end{tabular*}
\caption[USFS/Catchpole, conditions leading to failed spread predictions]{Parameter combinations for all USFS/Catchpole cases. Gray points in the background are cases where FDS successfully predicts spread, and colored points in the foreground represent failed (no spread) predictions. Both the point size and color are scaled according to the packing ratio (beta) value for a given test.}
\label{USFS_Catchpole_no_spread}
\end{figure}

Expand Down
94 changes: 58 additions & 36 deletions Utilities/Python/scripts/catchpole_spread_rates.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,39 +91,61 @@

# plot no-spread conditions

fig_file = os.path.join(fig_path, "Catchpole_no_spread.pdf")
# Dummy call to establish figure
fig = fdsplotlib.plot_to_fig(x_data=[-1,-1], y_data=[-1,-1],
x_label='Parameter',y_label='Normalized value',
x_min=0,x_max=3,y_min=0,y_max=1,ynumticks=2,
revision_label=version_string)
ax = plt.gca()

# Normalize by max and min
tests_normalized = tests
tests_normalized[list(dep_variables.keys())] = tests[list(dep_variables.keys())].apply(
lambda x: (x - x.min()) / (x.max() - x.min()))

go_mask = tests_normalized['category'] == 'spread'
nogo_mask = tests_normalized['category'] == 'no spread'

pd.plotting.parallel_coordinates(tests_normalized[go_mask], 'category',
cols=['s','beta','M','U'],
color=[(0.,0.,0.,.04)],
ax=ax,
ls='-')
ax.get_legend().remove() # Hide the parallel_coordinates legend

color_var = 'beta' # or 'beta', 'M', 'U'
cmap = plt.cm.plasma
norm = mpl.colors.Normalize(vmin=tests[color_var].min(),
vmax=tests[color_var].max())
colors = cmap(norm(tests[color_var]))

for idx, (i, row) in enumerate(tests_normalized[nogo_mask].iterrows()):
x_vals = ['s','beta','M','U']
y_vals = [row['s'], row['beta'], row['M'], row['U']]
ax.plot(x_vals, y_vals, color=colors[i], linestyle='-')

plt.savefig(fig_file)
plt.close()
go_mask = tests['category'] == 'spread'
nogo_mask = tests['category'] == 'no spread'

# Create scatter plot for each fuel type
for i, fuel in enumerate(fuel_labels):
fuel_name = fuel_names[i]
fig_file = os.path.join(fig_path, f"Catchpole_no_spread_{fuel}.pdf")

# Filter for this fuel type
if fuel == 'EX':
fuel_mask = tests['Test'].str.startswith(fuel) & (~tests['Test'].str.startswith('EXSC'))
else:
fuel_mask = tests['Test'].str.startswith(fuel)

# Get data for this fuel type
fuel_go_data = tests[go_mask & fuel_mask]
fuel_nogo_data = tests[nogo_mask & fuel_mask]

s_value = fuel_go_data['s'].iloc[0]
# Create figure
fig = fdsplotlib.plot_to_fig(x_data=[-1,1], y_data=[0,0],
marker_style='k--',
x_label='Moisture Content, M (-)',
y_label='Wind Speed, U (m/s)',
x_min=0,
x_max=0.3,
y_min=-0.2,
y_max=3.5,
revision_label=version_string,
plot_title=rf'{fuel_name}, {s_value:.0f} m$^{{-1}}$')
ax = plt.gca()

# Fixed scale for beta (0 to 0.1)
beta_min_fixed = 0.0
beta_max_fixed = 0.1

# Plot spread cases (background, gray, sized by beta)
if len(fuel_go_data) > 0:
sizes_go = (fuel_go_data['beta'] - beta_min_fixed) / (beta_max_fixed - beta_min_fixed) * 100 + 20
ax.scatter(fuel_go_data['M'], fuel_go_data['U'],
s=sizes_go, c='gray', alpha=0.3, edgecolors='none')

# Plot no-spread cases (foreground, colored by beta, sized by beta)
if len(fuel_nogo_data) > 0:
cmap = plt.cm.plasma
norm = mpl.colors.Normalize(vmin=beta_min_fixed, vmax=beta_max_fixed)
sizes_nogo = (fuel_nogo_data['beta'] - beta_min_fixed) / (beta_max_fixed - beta_min_fixed) * 100 + 20
scatter = ax.scatter(fuel_nogo_data['M'], fuel_nogo_data['U'],
s=sizes_nogo, c=fuel_nogo_data['beta'], cmap=cmap, norm=norm,
alpha=0.8, edgecolors='black', linewidths=0.5)

# Add colorbar
cbar = plt.colorbar(scatter, ax=ax)
cbar.set_label('Packing Ratio, beta (-)', rotation=90, labelpad=15, fontsize=plot_style['Label_Font_Size'])
cbar.ax.tick_params(labelsize=plot_style['Label_Font_Size'])

plt.savefig(fig_file)
plt.close()