From f24556732581ae61b1372b9888600b7288f67592 Mon Sep 17 00:00:00 2001 From: mcgratta Date: Wed, 23 Oct 2024 15:50:06 -0400 Subject: [PATCH] FDS Source: Remove unnecessary FLUSH calls --- Manuals/FDS_User_Guide/FDS_User_Guide.tex | 25 ++-- Source/dump.f90 | 142 +++++++--------------- Source/main.f90 | 4 - 3 files changed, 56 insertions(+), 115 deletions(-) diff --git a/Manuals/FDS_User_Guide/FDS_User_Guide.tex b/Manuals/FDS_User_Guide/FDS_User_Guide.tex index 6d824a9942..56b5604a49 100644 --- a/Manuals/FDS_User_Guide/FDS_User_Guide.tex +++ b/Manuals/FDS_User_Guide/FDS_User_Guide.tex @@ -5533,7 +5533,7 @@ \subsection{Chemical Time Integration} MAX_EQUIV_RATIO=20.0, DO_CHEM_LOAD_BALANCE=T / \end{lstlisting} -However, the relative and absolute tolerances for ODEs can be specified at the species level using the {\ct ODE\_REL\_ERROR} and {\ct ODE\_ABS\_ERROR} parameters. Currently, CVODE only supports absolute tolerance at the species level. The parameters {\ct EQUIV\_RATIO\_CHECK}, {\ct MIN\_EQUIV\_RATIO}, and {\ct MAX\_EQUIV\_RATIO} are optional. The purpose of {\ct EQUIV\_RATIO\_CHECK} (when true) is to save computational time by calling the chemistry solver only for cells where the equivalence ratio is within the specified {\ct MIN\_EQUIV\_RATIO} and {\ct MAX\_EQUIV\_RATIO} limits. Additionally, setting the parameter {\ct DO\_CHEM\_LOAD\_BALANCE} to true can significantly accelerate chemistry calculations by evenly distributing the chemistry workload across all MPI processes. The minimum concentration limit of a species is determined by multiplying {\ct ODE\_REL\_ERROR} to {\ct ZZ\_MIN\_GLOBAL}. Concentrations below this threshold are considered to be zero. +However, the relative and absolute tolerances for ODEs can be specified at the species level using the {\ct ODE\_REL\_ERROR} and {\ct ODE\_ABS\_ERROR} parameters. Currently, CVODE only supports absolute tolerance at the species level. The parameters {\ct EQUIV\_RATIO\_CHECK}, {\ct MIN\_EQUIV\_RATIO}, and {\ct MAX\_EQUIV\_RATIO} are optional. The purpose of {\ct EQUIV\_RATIO\_CHECK} (when true) is to save computational time by calling the chemistry solver only for cells where the equivalence ratio is within the specified {\ct MIN\_EQUIV\_RATIO} and {\ct MAX\_EQUIV\_RATIO} limits. Additionally, setting the parameter {\ct DO\_CHEM\_LOAD\_BALANCE} to true can significantly accelerate chemistry calculations by evenly distributing the chemistry workload across all MPI processes. The minimum concentration limit of a species is determined by multiplying {\ct ODE\_REL\_ERROR} to {\ct ZZ\_MIN\_GLOBAL}. Concentrations below this threshold are considered to be zero. For CVODE, the default parameter values are as follows: {\ct FINITE\_RATE\_MIN\_TEMP}=300~$^\circ$C, {\ct ZZ\_MIN\_GLOBAL}=1E-10, {\ct ODE\_MIN\_ATOL}=1E-10, {\ct ODE\_REL\_ERROR}=1E-6, {\ct EQUIV\_RATIO\_CHECK}=F, {\ct MIN\_EQUIV\_RATIO}=0.0, {\ct MAX\_EQUIV\_RATIO}=20.0, and {\ct DO\_CHEM\_LOAD\_BALANCE}=T. To use these default values, simply add the following lines to the FDS input file: \begin{lstlisting} @@ -6417,7 +6417,7 @@ \subsubsection{Randomly Distributed Particles within a Specified Volume} \end{lstlisting} Note that the volume of the specified region is calculated according to the {\ct SHAPE} dimensions, regardless of whether there are solid obstructions within this region. Note also that in most applications, the number of particles, {\ct N\_PARTICLES}, is somewhat arbitrary but should be chosen to provide at least a few particles per grid cell. FDS will then automatically assign a weighting factor to each particle to ensure that the {\ct MASS\_PER\_VOLUME} is achieved. In some applications, on the other hand, it may be important to specify the number of particles. For example, if using particles to model the burning of electrical cables, you may want to specify how many cables are actually burning. The {\ct MASS\_PER\_VOLUME} can be ramped up and down in time using the ramp function {\ct RAMP\_PART} on the {\ct INIT} line. -If the volume specified by the sextuplet {\ct XB} crosses mesh boundaries, be aware that {\ct N\_PARTICLES} refers to the entire volume, not just the volume within a particular mesh. FDS will automatically compute the necessary number of particles to assign to each mesh. This is done by multiplying {\ct N\_PARTICLES} by the ratio of the volume of {\ct XB} in each mesh by the total volume of {\ct XB} as specified in the input file (i.e, if the input is larger than the domain, fewer than {\ct N\_PARTICLES} will be inserted) with the result rounded to the nearest integer (with at least one particle inserted for every mesh that contains {\ct XB}). +If the volume specified by the sextuplet {\ct XB} crosses mesh boundaries, be aware that {\ct N\_PARTICLES} refers to the entire volume, not just the volume within a particular mesh. FDS will automatically compute the necessary number of particles to assign to each mesh. This is done by multiplying {\ct N\_PARTICLES} by the ratio of the volume of {\ct XB} in each mesh by the total volume of {\ct XB} as specified in the input file (i.e, if the input is larger than the domain, fewer than {\ct N\_PARTICLES} will be inserted) with the result rounded to the nearest integer (with at least one particle inserted for every mesh that contains {\ct XB}). Alternatively, you can specify {\ct SHAPE='CONE'}, in which case the particles will be randomly distributed within a vertical cone. This is primarily used for representing trees. The dimensions of the cone are specified via the parameters {\ct RADIUS}, {\ct HEIGHT}, and base position {\ct XYZ}. The latter is a triplet of real numbers designating the point at the center of the base of the cone. Here is an example of how one might make a tree: \begin{lstlisting} @@ -10694,7 +10694,7 @@ \subsection{Detailed Spray Properties} The first function, $f_1(t)$, is used for the computation of various mean diameters, with associated properties defined using the following keywords on the {\ct PROP} line: \begin{description} \item[{\ct PDPA\_M}] is the exponent $m$ in the numerator. -\item[{\ct PDPA\_N}] is the exponent $n$ in denominator. +\item[{\ct PDPA\_N}] is the exponent $n$ in denominator. \end{description} If $m=n$, the exponent $1/(m-n)$ is removed from the formula. @@ -14543,21 +14543,24 @@ \section{Boundary Files ({\tt .bf})} WRITE(LUBF) QUANTITY WRITE(LUBF) SHORT_NAME WRITE(LUBF) UNITS -WRITE(LUBF) NPATCH -WRITE(LUBF) I1,I2,J1,J2,K1,K2,IOR,NB,NM -WRITE(LUBF) I1,I2,J1,J2,K1,K2,IOR,NB,NM +WRITE(LUBF) N_PATCH +WRITE(LUBF) I1,I2,J1,J2,K1,K2,IOR,OBST_INDEX,NM +WRITE(LUBF) I1,I2,J1,J2,K1,K2,IOR,OBST_INDEX,NM . - . WRITE(LUBF) TIME + . +WRITE(LUBF) TIME_1 WRITE(LUBF) (((QQ(I,J,K),I=11,I2),J=J1,J2),K=K1,K2) WRITE(LUBF) (((QQ(I,J,K),I=11,I2),J=J1,J2),K=K1,K2) . - . WRITE(LUBF) TIME + . +WRITE(LUBF) TIME_2 WRITE(LUBF) (((QQ(I,J,K),I=11,I2),J=J1,J2),K=K1,K2) -WRITE(LUBF) (((QQ(I,J,K),I=11,I2),J=J1,J2),K=K1,K2) . +WRITE(LUBF) (((QQ(I,J,K),I=11,I2),J=J1,J2),K=K1,K2) + . . \end{lstlisting} -{\ct QUANTITY}, {\ct SHORT\_NAME} and {\ct UNITS} are character strings of length 30. {\ct NPATCH} is the number of planes (or ``patches'') that make up the solid boundaries plus the external walls. The sextuplet ({\ct I1,I2,J1,J2,K1,K2}) defines the cell nodes of each patch. {\ct IOR} is an integer indicating the orientation of the patch ($\pm 1,\pm 2,\pm 3$). You do not prescribe these. {\ct NB} is the number of the boundary (zero for external walls) and {\ct NM} is the number of the mesh. Note that the data is planar, thus one pair of cell nodes is the same. Presently, Smokeview is the -only program available to view the boundary files. +{\ct QUANTITY}, {\ct SHORT\_NAME} and {\ct UNITS} are character strings of length 30. {\ct N\_PATCH} is the number of planes (or ``patches'') that correspond to solid surfaces. The sextuplet ({\ct I1,I2,J1,J2,K1,K2}) defines the cell indices of each patch. For example, a patch on the lower $x$ boundary of the domain that spans cells 2 through 5 in the $y$ direction and 7 through 10 in the $z$ direction would have patch indices (0,0,1,5,6,10). Note that the boundary patches are 2-D; thus, one pair of cell indices is the same. {\ct IOR} is an integer indicating the orientation of the patch ($\pm 1,\pm 2,\pm 3$). {\ct OBST\_INDEX} refers to the solid obstruction ({\ct OBST}) to which the patch is affixed. Its value is 0 if the patch is affixed to an external boundary. {\ct NM} is the number of the mesh within which the obstruction lies. It may be different than the mesh containing the boundary data; that is, {\ct NM} is not necessarily equal to the mesh index {\ct M} in the file name. {\ct TIME\_N} and {\ct QQ} are four-byte reals. + \section{Particle Data ({\tt .prt5})} \label{out:PART} diff --git a/Source/dump.f90 b/Source/dump.f90 index f78500b863..e194dde29c 100644 --- a/Source/dump.f90 +++ b/Source/dump.f90 @@ -49,7 +49,7 @@ MODULE DUMP TYPE (INITIALIZATION_TYPE), POINTER :: IN=>NULL() PUBLIC ASSIGN_FILE_NAMES,INITIALIZE_GLOBAL_DUMPS,INITIALIZE_MESH_DUMPS,WRITE_STATUS_FILES, & - TIMINGS,FLUSH_GLOBAL_BUFFERS,FLUSH_LOCAL_BUFFERS,READ_RESTART,WRITE_DIAGNOSTICS, & + TIMINGS,FLUSH_GLOBAL_BUFFERS,READ_RESTART,WRITE_DIAGNOSTICS, & WRITE_SMOKEVIEW_FILE,DUMP_MESH_OUTPUTS,UPDATE_GLOBAL_OUTPUTS,DUMP_DEVICES,DUMP_HRR,& DUMP_MASS,DUMP_CONTROLS,INITIALIZE_DIAGNOSTIC_FILE,DUMP_RESTART,DUMP_HVAC,& DUMP_GEOM,UPDATE_DEVICES_2,WRITE_DEVC_CTRL_LOG @@ -1025,42 +1025,42 @@ SUBROUTINE INITIALIZE_MESH_DUMPS(NM) ! Initialize isosurface file - DO N=1,N_ISOF - IS => ISOSURFACE_FILE(N) - IF (.NOT. APPEND) THEN - OPEN(ABS(LU_ISOF(N,NM)),FILE=FN_ISOF(N,NM),FORM='UNFORMATTED',STATUS='REPLACE') - IF (IS%INDEX2 /= -1 ) THEN - OPEN(ABS(LU_ISOF2(N,NM)),FILE=FN_ISOF2(N,NM),FORM='UNFORMATTED',STATUS='REPLACE') - ENDIF - IF (M%N_STRINGS+5>M%N_STRINGS_MAX) CALL RE_ALLOCATE_STRINGS(NM) - M%N_STRINGS = M%N_STRINGS + 1 - IF (IS%INDEX2 .EQ. -1 ) THEN - WRITE(M%STRING(M%N_STRINGS),'(A,I6,1X,I6,1X,E13.6)') 'ISOG',NM,IS%SKIP,IS%DELTA - ELSE - WRITE(M%STRING(M%N_STRINGS),'(A,I6,1X,I6,1X,E13.6)') 'TISOG',NM,IS%SKIP,IS%DELTA - ENDIF - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(FN_ISOF(N,NM)) ! geometry - IF (IS%INDEX2 /= -1 ) THEN - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(FN_ISOF2(N,NM)) ! data - ENDIF - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_LABEL) ! labels for geometry - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_BAR_LABEL) - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(OUTPUT_QUANTITY(IS%INDEX)%UNITS) - IF (IS%INDEX2 /= -1 ) THEN - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_LABEL2) ! labels for data - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_BAR_LABEL2) - M%N_STRINGS = M%N_STRINGS + 1 - WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(OUTPUT_QUANTITY(IS%INDEX2)%UNITS) - ENDIF +DO N=1,N_ISOF + IS => ISOSURFACE_FILE(N) + IF (.NOT. APPEND) THEN + OPEN(ABS(LU_ISOF(N,NM)),FILE=FN_ISOF(N,NM),FORM='UNFORMATTED',STATUS='REPLACE') + IF (IS%INDEX2 /= -1 ) OPEN(ABS(LU_ISOF2(N,NM)),FILE=FN_ISOF2(N,NM),FORM='UNFORMATTED',STATUS='REPLACE') + IF (M%N_STRINGS+5>M%N_STRINGS_MAX) CALL RE_ALLOCATE_STRINGS(NM) + M%N_STRINGS = M%N_STRINGS + 1 + IF (IS%INDEX2 .EQ. -1 ) THEN + WRITE(M%STRING(M%N_STRINGS),'(A,I6,1X,I6,1X,E13.6)') 'ISOG',NM,IS%SKIP,IS%DELTA + ELSE + WRITE(M%STRING(M%N_STRINGS),'(A,I6,1X,I6,1X,E13.6)') 'TISOG',NM,IS%SKIP,IS%DELTA ENDIF - ENDDO + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(FN_ISOF(N,NM)) ! geometry + IF (IS%INDEX2 /= -1 ) THEN + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(FN_ISOF2(N,NM)) ! data + ENDIF + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_LABEL) ! labels for geometry + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_BAR_LABEL) + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(OUTPUT_QUANTITY(IS%INDEX)%UNITS) + IF (IS%INDEX2 /= -1 ) THEN + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_LABEL2) ! labels for data + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(IS%SMOKEVIEW_BAR_LABEL2) + M%N_STRINGS = M%N_STRINGS + 1 + WRITE(M%STRING(M%N_STRINGS),'(1X,A)') TRIM(OUTPUT_QUANTITY(IS%INDEX2)%UNITS) + ENDIF + CLOSE(ABS(LU_ISOF(N,NM))) + IF (IS%INDEX2 /= -1 ) CLOSE(ABS(LU_ISOF2(N,NM))) + ENDIF +ENDDO ! Initialize Smoke3d file @@ -4240,6 +4240,9 @@ SUBROUTINE DUMP_ISOF(T,DT,NM) ENDIF INDEX2_IF + OPEN(ABS(LU_ISOF(N,NM)),FILE=FN_ISOF(N,NM),FORM='UNFORMATTED',STATUS='OLD',POSITION='APPEND') + IF (IS%INDEX2 /= -1 ) OPEN(ABS(LU_ISOF2(N,NM)),FILE=FN_ISOF2(N,NM),FORM='UNFORMATTED',STATUS='OLD',POSITION='APPEND') + IF (IS%DEBUG) THEN TIME_FACTOR = MAX(0.05_EB, (STIME - T_BEGIN)/(T_END - T_BEGIN)) ISO_LEVEL(1) = REAL(TIME_FACTOR*(ZF_MAX-ZS_MIN)/2.0_EB, FB) @@ -4251,6 +4254,9 @@ SUBROUTINE DUMP_ISOF(T,DT,NM) IS%VALUE(1:IS%N_VALUES), IS%N_VALUES, IBLK, IS%SKIP, IS%DELTA, XPLT, IBP1, YPLT, JBP1, ZPLT, KBP1) ENDIF + CLOSE(ABS(LU_ISOF(N,NM))) + IF (IS%INDEX2 /= -1 ) CLOSE(ABS(LU_ISOF2(N,NM))) + ENDDO ISOF_LOOP END SUBROUTINE DUMP_ISOF @@ -10540,70 +10546,6 @@ SUBROUTINE FLUSH_GLOBAL_BUFFERS END SUBROUTINE FLUSH_GLOBAL_BUFFERS -!> \brief Periodically purge output files associated with mesh NM -!> \param NM Mesh number - -SUBROUTINE FLUSH_LOCAL_BUFFERS(NM) - -USE COMP_FUNCTIONS, ONLY : CURRENT_TIME -INTEGER, INTENT(IN) :: NM -INTEGER :: N -REAL(EB) :: TNOW - -TNOW = CURRENT_TIME() - -IF (PARTICLE_FILE) THEN - INQUIRE(UNIT=LU_PART(NM),OPENED=OPN) - IF (OPN) FLUSH(LU_PART(NM)) - INQUIRE(UNIT=LU_PART(NM+NMESHES),OPENED=OPN) - IF (OPN) FLUSH(LU_PART(NM+NMESHES)) -ENDIF - -DO N=1,MESHES(NM)%N_SLCF - INQUIRE(UNIT=LU_SLCF(N,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_SLCF(N,NM)) - INQUIRE(UNIT=LU_SLCF(N+N_SLCF_MAX,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_SLCF(N+N_SLCF_MAX,NM)) - INQUIRE(UNIT=LU_SLCF(N+2*N_SLCF_MAX,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_SLCF(N+2*N_SLCF_MAX,NM)) -ENDDO - -DO N=1,N_ISOF - INQUIRE(UNIT=ABS(LU_ISOF(N,NM)),OPENED=OPN) - IF (OPN) FLUSH(ABS(LU_ISOF(N,NM))) - INQUIRE(UNIT=ABS(LU_ISOF2(N,NM)),OPENED=OPN) - IF (OPN) FLUSH(ABS(LU_ISOF2(N,NM))) -ENDDO - -DO N=1,N_SMOKE3D - INQUIRE(UNIT=LU_SMOKE3D(N,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_SMOKE3D(N,NM)) - INQUIRE(UNIT=LU_SMOKE3D(N+N_SMOKE3D,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_SMOKE3D(N+N_SMOKE3D,NM)) - IF (SMOKE3D_16) THEN - INQUIRE(UNIT=LU_SMOKE3D(N+2*N_SMOKE3D,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_SMOKE3D(N+2*N_SMOKE3D,NM)) - ENDIF -ENDDO - -DO N=1,N_BNDF - INQUIRE(UNIT=LU_BNDF(N,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_BNDF(N,NM)) - INQUIRE(UNIT=LU_BNDF(N+N_BNDF,NM),OPENED=OPN) - IF (OPN) FLUSH(LU_BNDF(N+N_BNDF,NM)) -ENDDO - -DO N=1,N_PROF - IF (PROFILE(N)%MESH==NM) THEN - INQUIRE(UNIT=LU_PROF(N),OPENED=OPN) - IF (OPN) FLUSH(LU_PROF(N)) - ENDIF -ENDDO - -T_USED(7) = T_USED(7) + CURRENT_TIME() - TNOW -END SUBROUTINE FLUSH_LOCAL_BUFFERS - - !> \brief Print out detector activation times and total elapsed time into .out file. SUBROUTINE TIMINGS diff --git a/Source/main.f90 b/Source/main.f90 index 74654cc95c..16d0e60fbb 100644 --- a/Source/main.f90 +++ b/Source/main.f90 @@ -985,10 +985,6 @@ PROGRAM FDS IF (FLUSH_FILE_BUFFERS) THEN IF (T>=FLSH_CLOCK(FLSH_COUNTER(1))) THEN IF (MY_RANK==0) CALL FLUSH_GLOBAL_BUFFERS - CALL MPI_BARRIER(MPI_COMM_WORLD,IERR) ! Force all processes to sync up before dumping buffers - DO NM=LOWER_MESH_INDEX,UPPER_MESH_INDEX - CALL FLUSH_LOCAL_BUFFERS(NM) - ENDDO FLSH_COUNTER(1) = FLSH_COUNTER(1) + 1 ENDIF ENDIF