Skip to content

Commit 54fc5bb

Browse files
Merge pull request #15245 from marcosvanella/FireX
Merge firemodels/FireX
2 parents 311c5f5 + 67e743f commit 54fc5bb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2191
-2057
lines changed

.github/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ pygments
1111
ipython
1212
cantera
1313
pyfdstools
14+
15+
# Local utility packages (imports fdsplotlib)
16+
-e ../Utilities/Python

.github/workflows/linux.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ jobs:
102102
with:
103103
python-version: '3.9'
104104
cache: 'pip' # caching pip dependencies
105-
- run: pip install -r .github/requirements.txt
105+
- run: |
106+
echo $GITHUB_WORKSPACE
107+
cd $GITHUB_WORKSPACE/.github
108+
pip install -r requirements.txt
106109
107110
- name: Python test
108111
run: |

Manuals/FDS_User_Guide/FDS_User_Guide.tex

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,18 +1274,7 @@ \subsection{Overlapping Obstructions}
12741274

12751275
When obstructions overlap, Smokeview renders both obstructions independently of each other, often leading to an unsightly cross-hatching of the two surface colors where there is an overlap. A simple remedy for this is to ``shrink'' the obstruction you do not wish to take precedence by slightly by adjusting its coordinates (\ct{XB}) accordingly. Then, in Smokeview, toggle the ``q'' key to show the obstructions as you specified them, rather than as FDS rendered them.
12761276

1277-
The simulation will be stopped with an error if all of the following occur: (1) surfaces of two obstructions overlap, (2) the surface properties are different, and (3) one or both of the obstructions can be removed or created during the simulation.
1278-
1279-
If you have two overlapping obstructions and one obstruction is to be added or removed during the simulation with a hole made in the region of overlap, then define a \ct{HOLE} for the obstruction being added or removed and set \ct{REMOVABLE=F} as discussed in the next two sections.
1280-
1281-
\subsection{Preventing Obstruction Removal}
1282-
1283-
Obstructions can be protected from the \ct{HOLE} punching feature. Sometimes creating create a door or window using a \ct{HOLE} is convenient. For example, suppose a \ct{HOLE} is punched in a wall to represent a door or window. An obstruction can be defined to fill this hole (presumably to be removed or colored differently or whatever) so long as the phrase \ct{PERMIT_HOLE=F} is included on the \ct{OBST} line. In general, any obstruction can be made impenetrable to a \ct{HOLE} using this phrase. By default, \ct{PERMIT_HOLE=T}, meaning that an obstruction is assumed to be penetrable unless otherwise directed. Note that if a penetrable obstruction and an impenetrable obstruction overlap, the obstruction with \ct{PERMIT_HOLE=F} should be listed first.
1284-
1285-
If the obstruction is not to be removed or rejected for any reason, set \ct{REMOVABLE=F} This is sometimes needed to stop
1286-
FDS from removing the obstruction if it is embedded within another, like a door within a wall.
1287-
1288-
In rare cases, you might not want to allow a \ct{VENT} to be attached to a particular obstruction, in which case set \ct{ALLOW_VENT=F}.
1277+
Two obstructions should not overlap; that is, they should not have a common grid cell, if one or both of the obstructions is to be removed or created during the simulation. This will prompt an error message and the simulation will be shut down. However, you can punch a \ct{HOLE} through one obstruction and then fill that \ct{HOLE} with another obstruction which has the attribute \ct{REMOVABLE=F} or \ct{PERMIT_HOLE=F} as discussed in Sec.~\ref{info:REMOVABLE}. In this way, the first obstruction shall be broken up into multiple obstructions, none of which overlap the second obstrction which will not be punched by the \ct{HOLE}.
12891278

12901279
\subsection{Transparent or Outlined Obstructions}
12911280

@@ -1343,6 +1332,17 @@ \subsection{Creating Holes in Obstructions}
13431332
It is a good idea to inspect the geometry by running either a setup job
13441333
(\ct{T_END=0} on the \ct{TIME} line) or a short-time job to test the operation of devices and control functions.
13451334

1335+
\subsection{Preventing Obstruction Removal or Hole Punching}
1336+
\label{info:REMOVABLE}
1337+
1338+
Obstructions can be protected from the \ct{HOLE} punching feature. Sometimes creating create a door or window using a \ct{HOLE} is convenient. For example, suppose a \ct{HOLE} is punched in a wall to represent a door or window. An obstruction can be defined to fill this hole (presumably to be removed or colored differently or whatever) so long as the phrase \ct{PERMIT_HOLE=F} is included on the \ct{OBST} line. In general, any obstruction can be made impenetrable to a \ct{HOLE} using this phrase. By default, \ct{PERMIT_HOLE=T}, meaning that an obstruction is assumed to be penetrable unless otherwise directed. Note that if a penetrable obstruction and an impenetrable obstruction overlap, the obstruction with \ct{PERMIT_HOLE=F} should be listed first.
1339+
1340+
If the obstruction is not to be removed or rejected for any reason, set \ct{REMOVABLE=F} This is sometimes needed to stop
1341+
FDS from removing the obstruction if it is embedded within another, like a door within a wall.
1342+
1343+
In rare cases, you might not want to allow a \ct{VENT} to be attached to a particular obstruction, in which case set \ct{ALLOW_VENT=F}.
1344+
1345+
13461346
\ifcompgeom
13471347

13481348
\newpage
@@ -14424,8 +14424,9 @@ \chapter{Error Codes}
1442414424
610 \> \ct{HOLE ... Cannot overlap HOLEs with a DEVC or CTRL_ID.} \> Section~\ref{info:HOLE} \\
1442514425
611 \> \ct{OBST ... has a BULK_DENSITY but zero volume.} \> Section~\ref{info:BURN_AWAY} \\
1442614426
612 \> \ct{OBST ... must have a volume to be assigned HT3D.} \> Section~\ref{checkerboard} \\
14427-
613 \> \ct{OBST ... and OBST ... cannot overlap in Mesh ...} \> Section~\ref{info:OVERLAY} \\
14428-
614 \> \ct{OBST_ID ... cannot have a SURF with NODE_ID} \> Section~\ref{info:hvac_geom} \\ \> \> \\
14427+
614 \> \ct{OBST_ID ... cannot have a SURF with NODE_ID} \> Section~\ref{info:hvac_geom} \\
14428+
615 \> \ct{OBST ... cannot overlap OBST ...} \> Section~\ref{info:OVERLAY} \\
14429+
\> \> \\
1442914430
701 \> \ct{problem with GEOM, local SURF_ID index ... out of bounds.} \> Section~\ref{info:GEOM_Basics} \\
1443014431
702 \> \ct{problem with GEOM, SURF_IDS not defined properly.} \> Section~\ref{info:first_geom} \\
1443114432
703 \> \ct{missing SURF_ID in \&GEOM line ...} \> Section~\ref{subsec:readbin} \\
@@ -14614,6 +14615,7 @@ \chapter{Error Codes}
1461414615
1044 \> \ct{Cannot set EXTERNAL_FILE=T for a RAMP used for an output clock ...} \> Section~\ref{info:external_control} \\
1461514616
1045 \> \ct{QUANTITY ... requires a PART_ID for particles with mass.} \> Section~\ref{tab:particleoutputquantities} \\
1461614617
\\
14618+
1050 \> \ct{The file ... does not exist. Set RESTART=.FALSE.} \> Section~\ref{info:restart} \\
1461714619
1051 \> \ct{RESTART initial time equals T_END.} \> Section~\ref{info:restart} \\
1461814620
1052 \> \ct{On TIME, do not set both RAMP_TIME and RAMP_DT.} \> Section~\ref{info:simulation_time_ramp} \\
1461914621
1053 \> \ct{One TIME, if one of DT_EXTERNAL_HEARTBEAT or} \> Section~\ref{info:external_control} \\

Source/ccib.f90

Lines changed: 84 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -19720,22 +19720,17 @@ END SUBROUTINE GET_CUTCELL_FH
1972019720

1972119721
! ---------------------------- GET_H_MATRIX_CC ------------------------------------
1972219722

19723-
SUBROUTINE GET_H_MATRIX_CC(NM,NM1,IPZ,D_MAT_HP)
19723+
SUBROUTINE GET_H_MATRIX_CC(NM,NM1,IPZ)
1972419724

1972519725
! This routine assumes the calling subroutine has called POINT_TO_MESH for NM.
1972619726

1972719727
INTEGER, INTENT(IN) :: NM,NM1,IPZ
19728-
REAL(EB), POINTER, DIMENSION(:,:) :: D_MAT_HP
1972919728

1973019729
! Local Variables:
1973119730
INTEGER :: X1AXIS,IFACE,ICF,I,J,K,IND(LOW_IND:HIGH_IND),IND_LOC(LOW_IND:HIGH_IND)
1973219731
INTEGER :: LOCROW_1,LOCROW_2,ILOC,JLOC,JCOL,IROW
1973319732
REAL(EB) :: AF,IDX,BIJ,KFACE(2,2)
1973419733

19735-
IF (.NOT. ASSOCIATED(D_MAT_HP)) THEN
19736-
WRITE(LU_ERR,*) 'GET_H_MATRIX_CC in geom.f90: Pointer D_MAT_HP not associated.'
19737-
RETURN
19738-
ENDIF
1973919734

1974019735
! X direction bounds:
1974119736
ILO_FACE = 0 ! Low mesh boundary face index.
@@ -19792,8 +19787,7 @@ SUBROUTINE GET_H_MATRIX_CC(NM,NM1,IPZ,D_MAT_HP)
1979219787
DO JLOC=LOW_IND,HIGH_IND ! Local col number in Kface, JD
1979319788
IROW=IND_LOC(ILOC) ! Process Local Unknown number.
1979419789
JCOL=RCF%JDH(ILOC,JLOC) ! Local position of coef in D_MAT_H
19795-
! Add coefficient:
19796-
D_MAT_HP(JCOL,IROW) = D_MAT_HP(JCOL,IROW) + KFACE(ILOC,JLOC)
19790+
ZONE_SOLVE(IPZ)%ROW_H(IROW)%D(JCOL) = ZONE_SOLVE(IPZ)%ROW_H(IROW)%D(JCOL) + KFACE(ILOC,JLOC)
1979719791
ENDDO
1979819792
ENDDO
1979919793
ENDDO
@@ -19841,8 +19835,7 @@ SUBROUTINE GET_H_MATRIX_CC(NM,NM1,IPZ,D_MAT_HP)
1984119835
DO JLOC=LOW_IND,HIGH_IND ! Local col number in Kface, JD
1984219836
IROW=IND_LOC(ILOC)
1984319837
JCOL=CF%JDH(ILOC,JLOC,IFACE)
19844-
! Add coefficient:
19845-
D_MAT_HP(JCOL,IROW) = D_MAT_HP(JCOL,IROW) + KFACE(ILOC,JLOC)
19838+
ZONE_SOLVE(IPZ)%ROW_H(IROW)%D(JCOL) = ZONE_SOLVE(IPZ)%ROW_H(IROW)%D(JCOL) + KFACE(ILOC,JLOC)
1984619839
ENDDO
1984719840
ENDDO
1984819841
ENDDO
@@ -19972,9 +19965,9 @@ SUBROUTINE GET_CC_MATRIXGRAPH_H(NM,NM1,IPZ,LOOP_FLAG)
1997219965
! Add to global matrix arrays:
1997319966
DO LOCROW=LOCROW_1,LOCROW_2
1997419967
DO IIND=LOW_IND,HIGH_IND
19975-
NII = ZONE_SOLVE(IPZ)%NNZ_D_MAT_H(IND_LOC(LOCROW))
19968+
NII = ZONE_SOLVE(IPZ)%ROW_H(IND_LOC(LOCROW))%NNZ
1997619969
DO ILOC=1,NII
19977-
IF ( IND(IIND) == ZONE_SOLVE(IPZ)%JD_MAT_H(ILOC,IND_LOC(LOCROW)) ) THEN
19970+
IF ( IND(IIND) == ZONE_SOLVE(IPZ)%ROW_H(IND_LOC(LOCROW))%JD(ILOC) ) THEN
1997819971
RCF%JDH(LOCROW,IIND) = ILOC
1997919972
EXIT
1998019973
ENDIF
@@ -20016,9 +20009,9 @@ SUBROUTINE GET_CC_MATRIXGRAPH_H(NM,NM1,IPZ,LOOP_FLAG)
2001620009
! Add to global matrix arrays:
2001720010
DO LOCROW=LOCROW_1,LOCROW_2
2001820011
DO IIND=LOW_IND,HIGH_IND
20019-
NII = ZONE_SOLVE(IPZ)%NNZ_D_MAT_H(IND_LOC(LOCROW))
20012+
NII = ZONE_SOLVE(IPZ)%ROW_H(IND_LOC(LOCROW))%NNZ
2002020013
DO ILOC=1,NII
20021-
IF ( IND(IIND) == ZONE_SOLVE(IPZ)%JD_MAT_H(ILOC,IND_LOC(LOCROW)) ) THEN
20014+
IF ( IND(IIND) == ZONE_SOLVE(IPZ)%ROW_H(IND_LOC(LOCROW))%JD(ILOC) ) THEN
2002220015
CF%JDH(LOCROW,IIND,IFACE) = ILOC
2002320016
EXIT
2002420017
ENDIF
@@ -20039,38 +20032,94 @@ SUBROUTINE ADD_INPLACE_NNZ_H_WHLDOM(LOCROW_1,LOCROW_2,IND,IND_LOC,IPZ)
2003920032
INTEGER, INTENT(IN) :: LOCROW_1,LOCROW_2,IND(LOW_IND:HIGH_IND),IND_LOC(LOW_IND:HIGH_IND),IPZ
2004020033

2004120034
! Local Variables:
20042-
INTEGER LOCROW, IIND, NII, ILOC, JLOC
20035+
INTEGER LOCROW, IIND, ILOC
2004320036
LOGICAL INLIST
2004420037

2004520038
LOCROW_LOOP : DO LOCROW=LOCROW_1,LOCROW_2
2004620039
DO IIND=LOW_IND,HIGH_IND
20047-
NII = ZONE_SOLVE(IPZ)%NNZ_D_MAT_H(IND_LOC(LOCROW))
20048-
! Check that column index hasn't been already counted:
20049-
INLIST = .FALSE.
20050-
DO ILOC=1,NII
20051-
IF ( IND(IIND) == ZONE_SOLVE(IPZ)%JD_MAT_H(ILOC,IND_LOC(LOCROW)) ) THEN
20052-
INLIST = .TRUE.
20053-
EXIT
20040+
! Populate variable per-row storage ROW_H only:
20041+
ILOC = IND_LOC(LOCROW)
20042+
IF (ILOC>=1 .AND. ILOC<=SIZE(ZONE_SOLVE(IPZ)%ROW_H)) THEN
20043+
IF (.NOT. ALLOCATED(ZONE_SOLVE(IPZ)%ROW_H(ILOC)%JD)) THEN
20044+
ALLOCATE(ZONE_SOLVE(IPZ)%ROW_H(ILOC)%JD(7))
20045+
ALLOCATE(ZONE_SOLVE(IPZ)%ROW_H(ILOC)%D(7))
20046+
ZONE_SOLVE(IPZ)%ROW_H(ILOC)%JD(1) = IND(IIND)
20047+
ZONE_SOLVE(IPZ)%ROW_H(ILOC)%D(1) = 0._EB
20048+
ZONE_SOLVE(IPZ)%ROW_H(ILOC)%NNZ = 1
20049+
ELSE
20050+
INLIST = ANY(ZONE_SOLVE(IPZ)%ROW_H(ILOC)%JD(1:ZONE_SOLVE(IPZ)%ROW_H(ILOC)%NNZ) == IND(IIND))
20051+
IF (.NOT. INLIST) THEN
20052+
CALL INSERT_SORTED_INT_REAL( &
20053+
ZONE_SOLVE(IPZ)%ROW_H(ILOC)%JD, &
20054+
ZONE_SOLVE(IPZ)%ROW_H(ILOC)%D, &
20055+
ZONE_SOLVE(IPZ)%ROW_H(ILOC)%NNZ, &
20056+
IND(IIND))
20057+
ENDIF
2005420058
ENDIF
20055-
ENDDO
20056-
IF ( INLIST ) CYCLE
20057-
20058-
! Now add in place:
20059-
NII = NII + 1
20060-
DO ILOC=1,NII
20061-
IF ( ZONE_SOLVE(IPZ)%JD_MAT_H(ILOC,IND_LOC(LOCROW)) > IND(IIND) ) EXIT
20062-
ENDDO
20063-
DO JLOC=NII,ILOC+1,-1
20064-
ZONE_SOLVE(IPZ)%JD_MAT_H(JLOC,IND_LOC(LOCROW)) = ZONE_SOLVE(IPZ)%JD_MAT_H(JLOC-1,IND_LOC(LOCROW))
20065-
ENDDO
20066-
ZONE_SOLVE(IPZ)%NNZ_D_MAT_H(IND_LOC(LOCROW)) = NII
20067-
ZONE_SOLVE(IPZ)%JD_MAT_H(ILOC,IND_LOC(LOCROW)) = IND(IIND)
20059+
ENDIF
2006820060
ENDDO
2006920061
ENDDO LOCROW_LOOP
2007020062

2007120063
RETURN
2007220064
END SUBROUTINE ADD_INPLACE_NNZ_H_WHLDOM
2007320065

20066+
! Helper: insert NEWCOL into sorted integer array JD and mirror REAL array D, grow allocs
20067+
SUBROUTINE INSERT_SORTED_INT_REAL(JD, D, NNZ, NEWCOL)
20068+
USE PRECISION_PARAMETERS
20069+
IMPLICIT NONE (TYPE,EXTERNAL)
20070+
INTEGER, ALLOCATABLE, INTENT(INOUT) :: JD(:)
20071+
REAL(EB), ALLOCATABLE, INTENT(INOUT) :: D(:)
20072+
INTEGER, INTENT(INOUT) :: NNZ
20073+
INTEGER, INTENT(IN) :: NEWCOL
20074+
20075+
INTEGER :: POS, CAP
20076+
INTEGER :: I
20077+
INTEGER, ALLOCATABLE :: JD_TMP(:)
20078+
REAL(EB), ALLOCATABLE :: D_TMP(:)
20079+
20080+
! Determine current capacity from allocated size
20081+
CAP = SIZE(JD)
20082+
20083+
! Grow capacity geometrically if needed
20084+
IF (NNZ+1 > CAP) THEN
20085+
CAP = MAX(2*MAX(CAP,1), NNZ+1)
20086+
ALLOCATE(JD_TMP(CAP))
20087+
ALLOCATE(D_TMP(CAP))
20088+
IF (NNZ > 0) THEN
20089+
JD_TMP(1:NNZ) = JD(1:NNZ)
20090+
D_TMP(1:NNZ) = D(1:NNZ)
20091+
ENDIF
20092+
IF (ALLOCATED(JD)) DEALLOCATE(JD)
20093+
IF (ALLOCATED(D)) DEALLOCATE(D)
20094+
CALL MOVE_ALLOC(JD_TMP, JD)
20095+
CALL MOVE_ALLOC(D_TMP, D)
20096+
ENDIF
20097+
20098+
! Find insertion position (ascending order)
20099+
POS = 1
20100+
DO WHILE (POS <= NNZ)
20101+
IF(JD(POS) < NEWCOL) THEN
20102+
POS = POS + 1
20103+
ELSE
20104+
EXIT
20105+
ENDIF
20106+
ENDDO
20107+
20108+
! Shift in-place to make room
20109+
IF (NNZ >= POS) THEN
20110+
DO I = NNZ, POS, -1
20111+
JD(I+1) = JD(I)
20112+
D(I+1) = D(I)
20113+
ENDDO
20114+
ENDIF
20115+
20116+
! Insert new entry
20117+
JD(POS) = NEWCOL
20118+
D(POS) = 0._EB
20119+
NNZ = NNZ + 1
20120+
20121+
END SUBROUTINE INSERT_SORTED_INT_REAL
20122+
2007420123

2007520124
! --------------------------- GET_MMATRIX_SCALAR_3D -------------------------------
2007620125

Source/chem.f90

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,11 @@ SUBROUTINE CALC_FALLOFF_DBIDC_AND_DBIDT(TMP, RNI, K0, KINF, P_RATIO, F, DBIDC, D
679679
RRTMP = 1._EB/(R0*TMP)
680680

681681
DO NS=1,N_TRACKED_SPECIES
682-
DPRDBI = -RN%THIRD_EFF(NS )*K0/KINF
682+
IF (RN%N_THIRD>0) THEN
683+
DPRDBI = -RN%THIRD_EFF(NS)*K0/KINF
684+
ELSE
685+
DPRDBI = -1.0_EB*K0/KINF
686+
ENDIF
683687
DFDBI = 0._EB
684688
IF (RN%REACTYPE==FALLOFF_TROE_TYPE) THEN
685689
DFDBI = DDC_TROE(P_RATIO, F, DPRDBI, TMP, RNI)

Source/dump.f90

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1803,12 +1803,10 @@ SUBROUTINE WRITE_SMOKEVIEW_FILE
18031803

18041804
! If this is a RESTART case but an old .smv file does not exist, shutdown with an ERROR.
18051805

1806-
IF( MY_RANK==0) THEN
1807-
INQUIRE(FILE=FN_SMV,EXIST=EX)
1808-
IF (.NOT.EX .AND. APPEND) THEN
1809-
WRITE(MESSAGE,'(A,A,A)') "ERROR: The file, ",TRIM(FN_SMV),", does not exist. Set RESTART=.FALSE."
1810-
CALL SHUTDOWN(MESSAGE) ; RETURN
1811-
ENDIF
1806+
INQUIRE(FILE=FN_SMV,EXIST=EX)
1807+
IF (.NOT.EX .AND. APPEND) THEN
1808+
WRITE(MESSAGE,'(A,A,A)') "ERROR(1050): The file, ",TRIM(FN_SMV),", does not exist. Set RESTART=.FALSE."
1809+
CALL SHUTDOWN(MESSAGE) ; RETURN
18121810
ENDIF
18131811

18141812
! If this is a RESTART case, there is no need to open the .smv file except for Process 0.

0 commit comments

Comments
 (0)