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
2 changes: 1 addition & 1 deletion Manuals/FDS_User_Guide/FDS_User_Guide.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3542,7 +3542,7 @@ \subsection{Louvered Vents}
\begin{lstlisting}
&SURF ID='LOUVER', VEL=-2.0, VEL_T=3.0,0.0, TAU_V=5., COLOR='GREEN' /
\end{lstlisting}
is a boundary condition for a louvered vent that pushes air into the space with a normal velocity of 2~m/s and a tangential velocity of 3~m/s in the first of the two tangential directions. Note that the negative sign of the normal component of velocity indicates that the fluid is injected into the computational domain. The tangential velocity of 3~m/s indicates that the flow is in the positive $y$ direction. Both the normal and tangential velocity components are ramped up with either \ct{TAU_V} or \ct{RAMP_V}, as shown in Fig.~\ref{fig:tangential_velocity}.
is a boundary condition for a louvered vent that pushes air into the space with a normal velocity of 2~m/s and a tangential velocity of 3~m/s in the first of the two tangential directions. Note that the negative sign of the normal component of velocity indicates that the fluid is injected into the computational domain. The tangential velocity of 3~m/s indicates that the flow is in the positive $y$ direction. Both the normal and tangential velocity components are ramped up with either \ct{TAU_V} or \ct{RAMP_V}, as shown in Fig.~\ref{fig:tangential_velocity}. If the boundary condition is specified with \ct{MASS_FLUX}, then \ct{VEL_T} should be specified assuming a wall normal velocity of 1~m/s. FDS will then scale the input values for \ct{VEL_T} based on the current wall velocity given by the species mass fractions, mass flux, and wall temperature.

\begin{figure}[ht!]
\begin{center}
Expand Down
2 changes: 1 addition & 1 deletion Source/data.f90
Original file line number Diff line number Diff line change
Expand Up @@ -2452,7 +2452,7 @@ SUBROUTINE THERMO_TABLE_LIQUID(I_TMP,CP,H_V,T_REF,T_MELT,T_BOIL,SPEC_INDEX,FUEL,
LOGICAL,INTENT(OUT) :: FUEL
TYPE (THERMO_DATA_TYPE), POINTER :: TD

!Default to water properteis
! Default to water properties

IF (SPEC_INDEX < 0) THEN
FUEL = .FALSE.
Expand Down
4 changes: 2 additions & 2 deletions Source/vege.f90
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,9 @@ SUBROUTINE LEVEL_SET_FIRESPREAD(T,DT,NM)
U_Z(2) = 0.5_EB*(U(IIG-1,JJG,KWIND)+U(IIG,JJG,KWIND))
V_Z(1) = 0.5_EB*(V(IIG,JJG-1,KWIND-1)+V(IIG,JJG,KWIND-1))
V_Z(2) = 0.5_EB*(V(IIG,JJG-1,KWIND)+V(IIG,JJG,KWIND))
! If wind comes from first grid cell assume zero wind at ground level
! If wind comes from first grid cell assume plug flow near ground level
IF (KWIND==1) THEN
U_Z(1) = 0._EB; V_Z(1) = 0._EB; ZWIND(1) = 0._EB
U_Z(1) = U_Z(2); V_Z(1) = V_Z(2); ZWIND(1) = Z_LS(IIG,JJG)
ENDIF
U_LS(IIG,JJG) = U_Z(1) + (REF_WIND_HEIGHT-ZWIND(1))/(ZWIND(2)-ZWIND(1))*(U_Z(2)-U_Z(1))
V_LS(IIG,JJG) = V_Z(1) + (REF_WIND_HEIGHT-ZWIND(1))/(ZWIND(2)-ZWIND(1))*(V_Z(2)-V_Z(1))
Expand Down
37 changes: 24 additions & 13 deletions Source/velo.f90
Original file line number Diff line number Diff line change
Expand Up @@ -1816,7 +1816,7 @@ SUBROUTINE VELOCITY_BC(T,NM,APPLY_TO_ESTIMATED_VARIABLES)
REAL(EB) :: MUA,TSI,WGT,T_NOW,RAMP_T,OMW,MU_WALL,RHO_WALL,SLIP_COEF,VEL_T, &
UUP(2),UUM(2),DXX(2),MU_DUIDXJ(-2:2),DUIDXJ(-2:2),PROFILE_FACTOR,VEL_GAS,VEL_GHOST, &
MU_DUIDXJ_USE(2),DUIDXJ_USE(2),VEL_EDDY,U_TAU,Y_PLUS,U_NORM,U_WIND_LOC,V_WIND_LOC,W_WIND_LOC,&
DRAG_FACTOR,HT_SCALE_FACTOR,VEG_HT
DRAG_FACTOR,HT_SCALE_FACTOR,VEG_HT,VEL_MF
INTEGER :: NOM(2),IIO(2),JJO(2),KKO(2),IE,II,JJ,KK,IEC,IOR,IWM,IWP,ICMM,ICMP,ICPM,ICPP,ICD,ICDO,IVL,I_SGN, &
VELOCITY_BC_INDEX,IIGM,JJGM,KKGM,IIGP,JJGP,KKGP,SURF_INDEXM,SURF_INDEXP,ITMP,ICD_SGN,ICDO_SGN, &
BOUNDARY_TYPE_M,BOUNDARY_TYPE_P,IS,IS2,IWPI,IWMI,VENT_INDEX
Expand Down Expand Up @@ -2293,20 +2293,31 @@ SUBROUTINE VELOCITY_BC(T,NM,APPLY_TO_ESTIMATED_VARIABLES)
END SELECT

ELSE

PROFILE_FACTOR = 1._EB
IF (ABS(SF%T_IGN-T_BEGIN)<=SPACING(SF%T_IGN) .AND. SF%RAMP(TIME_VELO)%INDEX>=1) THEN
TSI = T
ELSE
TSI=T-SF%T_IGN
IF (ABS(SF%VEL) > 0._EB) THEN
IF (ABS(SF%T_IGN-T_BEGIN)<=SPACING(SF%T_IGN) .AND. SF%RAMP(TIME_VELO)%INDEX>=1) THEN
TSI = T
ELSE
TSI=T-SF%T_IGN
ENDIF
RAMP_T = EVALUATE_RAMP(TSI,SF%RAMP(TIME_VELO)%INDEX,TAU=SF%RAMP(TIME_VELO)%TAU)
IF (SF%VEL < 0._EB) THEN
IF (SF%RAMP(VELO_PROF_Z)%INDEX>0) PROFILE_FACTOR = EVALUATE_RAMP(ZC(KK),SF%RAMP(VELO_PROF_Z)%INDEX)
IF (IEC==1 .OR. (IEC==2 .AND. ICD==2)) VEL_T = RAMP_T*(PROFILE_FACTOR*(SF%VEL_T(2) + VEL_EDDY))
IF (IEC==3 .OR. (IEC==2 .AND. ICD==1)) VEL_T = RAMP_T*(PROFILE_FACTOR*(SF%VEL_T(1) + VEL_EDDY))
ELSE
IF (SF%PROFILE/=0) PROFILE_FACTOR = ABS(0.5_EB*(WCM_B1%U_NORMAL_0+WCP_B1%U_NORMAL_0)/SF%VEL)
IF (SF%RAMP(VELO_PROF_Z)%INDEX>0) PROFILE_FACTOR = EVALUATE_RAMP(ZC(KK),SF%RAMP(VELO_PROF_Z)%INDEX)
IF (IEC==1 .OR. (IEC==2 .AND. ICD==2)) VEL_T = RAMP_T*PROFILE_FACTOR*VEL_EDDY
IF (IEC==3 .OR. (IEC==2 .AND. ICD==1)) VEL_T = RAMP_T*PROFILE_FACTOR*VEL_EDDY
ENDIF
ELSE ! Mass flux BC
VEL_MF = 0.5_EB*(WCM_B1%U_NORMAL_S+WCP_B1%U_NORMAL_S)
IF (VEL_MF < 0._EB) THEN
IF (IEC==1 .OR. (IEC==2 .AND. ICD==2)) VEL_T = -SF%VEL_T(2)*VEL_MF
IF (IEC==3 .OR. (IEC==2 .AND. ICD==1)) VEL_T = -SF%VEL_T(1)*VEL_MF
ENDIF
ENDIF
IF (SF%PROFILE/=0 .AND. SF%VEL>TWO_EPSILON_EB) &
PROFILE_FACTOR = ABS(0.5_EB*(WCM_B1%U_NORMAL_0+WCP_B1%U_NORMAL_0)/SF%VEL)
IF (SF%RAMP(VELO_PROF_Z)%INDEX>0) PROFILE_FACTOR = EVALUATE_RAMP(ZC(KK),SF%RAMP(VELO_PROF_Z)%INDEX)
RAMP_T = EVALUATE_RAMP(TSI,SF%RAMP(TIME_VELO)%INDEX,TAU=SF%RAMP(TIME_VELO)%TAU)
IF (IEC==1 .OR. (IEC==2 .AND. ICD==2)) VEL_T = RAMP_T*(PROFILE_FACTOR*(SF%VEL_T(2) + VEL_EDDY))
IF (IEC==3 .OR. (IEC==2 .AND. ICD==1)) VEL_T = RAMP_T*(PROFILE_FACTOR*(SF%VEL_T(1) + VEL_EDDY))

ENDIF

! Choose the appropriate boundary condition to apply
Expand Down
2 changes: 2 additions & 0 deletions Utilities/Python/FDS_verification_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
print("fan_curve..."); runpy.run_path("./scripts/fan_curve.py", run_name="__main__")
print("favre_test..."); runpy.run_path("./scripts/favre_test.py", run_name="__main__")
print("fds_moody_chart..."); runpy.run_path("./scripts/fds_moody_chart.py", run_name="__main__")
print("fds_timing_stats..."); runpy.run_path("./scripts/fds_timing_stats.py", run_name="__main__")
print("fluid_part..."); runpy.run_path("./scripts/fluid_part.py", run_name="__main__")
print("freecon_sphere..."); runpy.run_path("./scripts/freecon_sphere.py", run_name="__main__")
print("geom_channel_test..."); runpy.run_path("./scripts/geom_channel_test.py", run_name="__main__")
Expand All @@ -61,6 +62,7 @@
print("law_of_the_wall..."); runpy.run_path("./scripts/law_of_the_wall.py", run_name="__main__")
print("level_set_ellipse..."); runpy.run_path("./scripts/level_set_ellipse.py", run_name="__main__")
print("mesh_transformation..."); runpy.run_path("./scripts/mesh_transformation.py", run_name="__main__")
print("make_smv_images..."); runpy.run_path("./scripts/make_smv_images.py", run_name="__main__")
print("mass_balance..."); runpy.run_path("./scripts/mass_balance.py", run_name="__main__")
print("mass_balance_gas_volume..."); runpy.run_path("./scripts/mass_balance_gas_volume.py", run_name="__main__")
print("mass_balance_reac..."); runpy.run_path("./scripts/mass_balance_reac.py", run_name="__main__")
Expand Down
147 changes: 147 additions & 0 deletions Utilities/Python/scripts/fds_timing_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@

# Produce a table of verification case CPU times in Manuals/FDS_Verification_Guide/SCRIPT_FIGURES/Scatterplots

import os
import subprocess
import csv

curdir = os.getcwd()
verdir = '../../Verification/'
resdir = '../../Manuals/FDS_Verification_Guide/SCRIPT_FIGURES/Scatterplots/'
resfile = resdir + 'fds_timing_stats.csv'

with open(resfile, 'w') as f:
f.write('FDS Case,Wall Clock Time (s),CPU Time (s),Number of Cells,Number of Time Steps,Performance Metric (1e-6)\n')

with open(verdir + 'FDS_Cases.sh', 'r') as casefile:
for line in casefile:
if line.strip().startswith('$QFDS'):
parts = line.split()
if '-d' in parts:
d_index = parts.index('-d')
if d_index + 2 < len(parts):
subdir = parts[d_index + 1]
fdsfile = parts[d_index + 2]

# Extract base filename without extension
fdsbase = verdir + subdir + '/' + os.path.splitext(fdsfile)[0]
outfile = f"{fdsbase}.out"
cpufile = f"{fdsbase}_cpu.csv"

# Check if outfile exists, try alternate name if not
if not os.path.exists(outfile):
outfile = f"{fdsbase}_cat.out"
if not os.path.exists(outfile):
continue

# Check if cpufile exists, try alternate name if not
if not os.path.exists(cpufile):
cpufile = f"{fdsbase}_cat_cpu.csv"
if not os.path.exists(cpufile):
continue

# Grep for wall clock time
WALL_CLOCK_TIME_VALUE = ""
with open(outfile, 'r') as f:
for line in f:
if "Total Elapsed Wall Clock Time (s):" in line:
WALL_CLOCK_TIME_VALUE = line.strip().split()[-1]

# Grep for CPU time and units
TOTAL_CPU_TIME = 0.0
CPU_TIME_VALUES = []

with open(cpufile, 'r') as f:
lines = f.readlines()
# Skip first line (header), process rest
for line in lines[1:]:
if line.strip():
# Get last column (split by comma)
parts = line.strip().split(',')
if parts:
CPU_TIME_VALUES.append(parts[-1])

# Process each CPU time value
for j in CPU_TIME_VALUES:
TOTAL_CPU_TIME += eval(j)

CPU_TIME = TOTAL_CPU_TIME

# Grep for number of cells in each dimension
X_CELLS = []
Y_CELLS = []
Z_CELLS = []

with open(outfile, 'r') as f:
for line in f:
if "Cells in the X" in line:
X_CELLS.append(line.strip().split()[-1])
elif "Cells in the Y" in line:
Y_CELLS.append(line.strip().split()[-1])
elif "Cells in the Z" in line:
Z_CELLS.append(line.strip().split()[-1])

numx = len(X_CELLS)

# Sum over the number of cells (for multi-mesh cases)
NUM_TOTAL_CELLS = 0
for i in range(numx):
XI = int(X_CELLS[i])
YI = int(Y_CELLS[i])
ZI = int(Z_CELLS[i])
sumxyz = XI * YI * ZI
NUM_TOTAL_CELLS += sumxyz

# Grep for number of time steps
NUM_TIME_STEPS = 0
time_step_lines = []
with open(outfile, 'r') as f:
for line in f:
if "Time Step " in line:
time_step_lines.append(line)

if time_step_lines:
# Get the last occurrence
last_line = time_step_lines[-1]
parts = last_line.strip().split()
if len(parts) >= 5:
# Get the 5th element from the end (NF-4 in awk)
NUM_TIME_STEPS = int(parts[-5])

# Calculate nondimensional performance metric
# Skip over cases with no time steps
if NUM_TIME_STEPS == 0:
NUM_TIME_STEPS = 0
PERFORMANCE = 0
else:
# Calculate performance metric
PERFORMANCE = int(1000000 * TOTAL_CPU_TIME / (NUM_TOTAL_CELLS * NUM_TIME_STEPS))

# Write results to fds_timing_stats.csv file
with open(resfile, 'a', newline='') as f:
csv_writer = csv.writer(f)
csv_writer.writerow([fdsfile,WALL_CLOCK_TIME_VALUE,CPU_TIME,NUM_TOTAL_CELLS,NUM_TIME_STEPS,PERFORMANCE])


# Sum up the wall clock times in the second column

TOTAL_CPU_TIME = 0.0
with open(resfile, 'r') as f:
lines = f.readlines()
for line in lines[1:]:
if line.strip():
fields = line.split(',')
if len(fields) >= 3:
j = fields[1].strip()
TOTAL_CPU_TIME = TOTAL_CPU_TIME + eval(j)

# Get git short commit hash and append to tmpout

git_hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=curdir, universal_newlines=True).strip()

# Append git hash and total CPU time to fds_timing_stats.csv

with open(resfile, 'a') as f:
f.write(git_hash + '\n')
f.write(str(TOTAL_CPU_TIME) + '\n')

2 changes: 1 addition & 1 deletion Utilities/Python/scripts/make_smv_images.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
smokeview_path = shutil.which(shell_command)

for i in range(len(folder)):
print(case[i])
print('generating smokeview image ' + case[i])
os.chdir(outdir + folder[i])
if os_name == "Linux":
subprocess.run(['xvfb-run','-a',smokeview_path,'-runscript',case[i]], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
Expand Down
46 changes: 0 additions & 46 deletions Utilities/Scripts/fds_timing_stats.sh

This file was deleted.

46 changes: 46 additions & 0 deletions Utilities/Scripts/get_download_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

import json
import urllib.request

FDSURL = "https://api.github.com/repos/firemodels/fds/releases"
SMVURL = "https://api.github.com/repos/firemodels/smv/releases"
BUNDLE = "FDS-6.10.1_SMV-6.10.1"
SMV = "SMV-6.10.5"
LINUX = "_lnx.sh"
OSX = "_osx.sh"
WIN = "_win.exe"


def get_downloads(filename: str, releases_url: str) -> int:
"""
Retrieve the download count for a given asset filename from a GitHub releases feed.
Returns 0 if the asset cannot be found.
"""
request = urllib.request.Request(
releases_url,
headers={
"Accept": "application/vnd.github+json",
"User-Agent": "python-urllib"
},
)
with urllib.request.urlopen(request, timeout=30) as response:
releases = json.load(response)

for release in releases:
for asset in release.get("assets", []):
if asset.get("name") == filename:
return int(asset.get("download_count", 0))
return 0


print("bundle downloads")
print(f"FILE={BUNDLE}{LINUX} downloads={get_downloads(BUNDLE + LINUX, FDSURL)}")
print(f"FILE={BUNDLE}{OSX} downloads={get_downloads(BUNDLE + OSX, FDSURL)}")
print(f"FILE={BUNDLE}{WIN} downloads={get_downloads(BUNDLE + WIN, FDSURL)}")

print("")
print("smokeview downloads")
print(f"FILE={SMV}{LINUX} downloads={get_downloads(SMV + LINUX, SMVURL)}")
print(f"FILE={SMV}{OSX} downloads={get_downloads(SMV + OSX, SMVURL)}")
print(f"FILE={SMV}{WIN} downloads={get_downloads(SMV + WIN, SMVURL)}")

25 changes: 0 additions & 25 deletions Utilities/Scripts/get_download_count.sh

This file was deleted.

7 changes: 0 additions & 7 deletions Utilities/Scripts/killXservers.sh

This file was deleted.

Loading
Loading