Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Way to freeze flame spread similar to freezing time for ramp input? #13234

Open
mcgratta opened this issue Jul 26, 2024 Discussed in #13222 · 22 comments
Open

Way to freeze flame spread similar to freezing time for ramp input? #13234

mcgratta opened this issue Jul 26, 2024 Discussed in #13222 · 22 comments
Assignees

Comments

@mcgratta
Copy link
Contributor

Discussed in #13222

Originally posted by bwklein July 25, 2024
I'm looking for a way to freeze the 'spread' of a fire growth that is based on the SPREAD_RATE parameter.
Similar to how we can freeze the time value input to a ramp for HRRPUA, is there a way to do this with the input to the spreading function. Essentially, stopping the spread of the fire, but keeping the cells active that are within the spread radius.

@mcgratta mcgratta self-assigned this Jul 26, 2024
@mcgratta
Copy link
Contributor Author

Bryan -- we're going to implement a way to control spreading fires with more features than just freezing it. But if you look at the test case called Fires/circular_burner.fds, does this do what you want?

@mcgratta
Copy link
Contributor Author

mcgratta commented Aug 6, 2024

I looked into this issue some more. Anything can be done with spread rates, but it would be more costly than what we do now because if we make SPREAD_RATE a time-dependent function, then we have to evaluate all the WALL, CFACE and PARTICLE cells each time step and change the ignition time if the fire front has swept by. Is there a strong use case for this? If you just want to stop the spread, you can just limit the VENT on which the SPREAD_RATE is specified.

@drjfloyd
Copy link
Contributor

drjfloyd commented Aug 6, 2024

I think Bryan was looking for a solution to do this when you don't know a priori how far it will spread.

@obscureed
Copy link

Sorry to hijack the thread, but I have some features I would like to see in fires with SPREAD_RATE:
• I have tried to combine SPREAD_RATE to define growth with RAMP_Q to define a sudden shutdown of the fire later. This does not work; a slow spread currently causes a slow shutdown. The memory used to set up the spread interferes with the connection of each facet to the RAMP_Q times. I would like some way to have a spreading fire that later shuts down cleanly.
• SPREAD_RATE will achieve"t-squared" growth (where the total heat release rate is proportional to time^2), but only for a circular fire. It would be convenient to create t-squared growth with non-circular shapes, using a growing, connected collection of facets.
• The initial part of a spread-rate growth curve is usually zero heat output, unless the centre of the fire bed is exactly a facet centroid. To some extent, this is just a consequence of a coarsely resolved growth, but it would be nice to have an option for some heat output from the start.
• If the centre of the fire bed is somewhere symmetric in the grid, then the growth curve goes up in jumps of 4 or 8 facets, all at the same distance from the centre. It would be nice to have a more smoothly resolved growth curve.

You may have thought of all these already. Thanks for reading!
Ed

@mcgratta
Copy link
Contributor Author

Let me push back a bit here. Currently, the user specifies a constant SPREAD_RATE originating from a single point on a VENT. The fire spreading stops when it reaches the boundary of the VENT. One can even make the VENT itself circular, as in the example case Fires/circular_burner.fds. This feature is cheap and easy to implement because during the simulation set up, all the relevant surface cells are assigned an appropriate ignition time and a ramp of heat release rate to invoke at the time of ignition.

However, all of the suggestions put forth above will cost more because they require that surface cells be scanned at each time step to determine ignition and various other behaviors. Not a lot of cost, but more than before for a feature that may or may not be widely used. In my opinion, the idea of the "t-squared" fire has been extended far beyond its original intent because of regulatory requirements and general practice. But nevertheless, we implemented what I have described above as a convenience for end users who need to conform to these requirements. But now, much like the layer height concept, this concept is beginning to go beyond what is called for by basic practice or regulatory requirements. I worry that if we add all these new variations, we risk confusing real fire spread behavior with these ad hoc mathematical shapes. Sure, we can make the fire spread like an oval rather than a circle, but where does that end? I would prefer that if fire spread is to be modeled in a more realistic way that there be some rationale for it. For example, we use a more sophisticated spread model for wildland applications, the so-called level set method, but this is based on the actual physics of spread over complex terrain and different fuel types. We are very cautious about making the fire spread in a way that cannot be justified other than as some hypothetical construct.

@obscureed
Copy link

You are right that I am driven to t-squared growth by regulatory definitions. I do not have a problem with that: we need to distinguish between "slow" and "fast" growth situations, and t-squared growth factors are a shared language that defines growth. (It also has some basis in reality, for a constant spread rate over a circular fire bed.) It does not seem unreasonable to me to want to combine t-squared growth with a later rampdown (for example because the fire is extinguished). Currently I do this by using SPREAD_RATE to define the growth and by creating an OBST on a timer over the fire bed to kill it suddenly, effectively like dropping a drain cover onto a fire bed. This does the job.

One route to satisfy the features I mentioned would be a connection between RAMP_Q and facet-by-facet timing. (Currently there is a connection between t-squared growth rate and facet-by-facet timing, or between an arbitrary RAMP_Q and variable Heat Release Rate Per Unit Area. The current implementation of RAMP_Q by using variable HRRPUA is less realistic than anything I have suggested.)
• The way I envisage it, the RAMP_Q time variations of heat release rate could be discretised to changes in quanta matching the number of facets. The facets of the fire bed would be put into a fixed order -- for example, sorted by distance from some coordinate, with a tie-breaker based on angle. If the ramp function requires N of the facets to be active, then the first N on the sorted list are active. If necessary, all this can be pre-calculated as a time history for each facet. The number of on/off flips might be greater than currently for some ramps, but there is no scanning of distances or angles in mid simulation.
• If I want to, I can then program in t-squared growth, plateau and ramp-down into a RAMP_Q. With a bit of tweaking, I can define the RAMP_Q to approximate t-squared growth using at least one facet from the start.
• I cannot comment on how widely this would be used, but I know I would use it a lot.

@mcgratta
Copy link
Contributor Author

If you make 'RAMP_Q' a step function whose duration is dictated by the fuel load (mass per area), then you have a ring of fire that expands outwards until it reaches the boundary of the VENT and goes out. If you make the duration longer than the time to reach the boundary, you will get t-squared growth, steady burning, and then a ramp down of some sort. Why is this not adequate to the purpose?

@drjfloyd
Copy link
Contributor

Wtih DEVC and CTRL functions you should be able to script out any desired rate of growth over any arbitrary set of VENT or OBST including decay. For example, for oval spread you could define rings of VENTs each with a different SURF_ID and RAMP_Q.

@obscureed
Copy link

@mcgratta : I am not completely sure I understand what you're suggesting. If you're suggesting a combination of SPREAD_RATE=... to define growth and a RAMP_Q to define extinguishing, then the reason it is not adequate is that it does not work. The events defined in the RAMP_Q are smeared out by the growth timescale defined in the SPREAD_RATE. (My simplistic way of thinking about it is that FDS has reset the timers of all the facets of the fire bed, so they respond late to the RAMP_Q.) Maybe this is a bug -- it certainly surprised me the first time I saw it.

Here is an example -- I'll put the code at the end of this post. This is intended to give "fast" t-squared growth (as defined in UK regulations), which should reach 1000 kW in 146 seconds. Then a plateau, then sudden extinguishing, ramping down from 100% at t=300s to 0% at t=310s. This is what happens instead:
graphHRR

There are several aspects I would like to change about this HRR curve:
• The sudden extinguishing has been smeared out badly.
• There is zero HRR until after t=20s.
• The HRR growth goes up in leaps of 4 or 8 facets, which is the same as 4% or 8% of the eventual fire size.
— If the discretisation of the HRR curve used individual pixels, each 1% of the eventual fire size in this case, then the first facet might turn on after a few seconds, which would be an improvement. I would prefer at least one facet to be active from the start. I can (and I do) achieve this by adjusting the position of the fire bed so that the centroid exactly matches a facet centroid, but this is fiddly.
• The t-squared growth that I would like is initially achieved, but it slows down when the spread approaches the corners of the square fire bed. To reach the full HRR takes 168s instead of 146s. This is certainly not a bug -- spread rate is doing what was specified -- but I would like to have a way to specify t-squared, facet-by-facet growth for non-circular fire beds.
• The overshoot on the first leap at t=21s is a bit strange, but that's just numerical stuff and not a priority.

@drjfloyd -- Yes, I could define rings of VENTS to define ovals. I could even define a different RAMP_Q for every facet. However, I still think it is the kind of feature that the software could take care of productively.

Here's the example code. It runs in a few minutes:

&HEAD CHID= 'firegrowth_fast', TITLE= 'firegrowth_fast'  /

! A fire (1.0m*1.0m square, 1.0MW) in an open box.
! This combines SPREAD_RATE corresponding to "fast" growth (as in BS7974-1:2019, Table 2)
!           and RAMP_Q      intended to extinguish the fire suddenly (over 10s) at t= 300s [but SPREAD_RATE interferes]

&TIME T_END= 500., RESTRICT_TIME_STEP= .FALSE./
&DUMP NFRAMES= 250 /
&MATL ID= 'CONCRETE',  FYI= 'Typical Concrete', CONDUCTIVITY= 1.4, SPECIFIC_HEAT= 0.84, DENSITY= 2100.0 /
&SURF ID= 'WALL', RGB= 200,210,220, MATL_ID= 'CONCRETE',  THICKNESS= 0.25, DEFAULT= .TRUE.   /

&MESH XB =   -2.000,   2.000,  -2.000,   2.000,   0.000,   4.000, IJK= 20,20,20, MPI_PROCESS= 0, ID= 'mesh1' /

&REAC ID= 'FUEL', C= 1.0, H= 2.0, O= 0.5, SOOT_YIELD= 0.100, CO_YIELD= 0.040, HEAT_OF_COMBUSTION= 20000.000 /
&SPEC ID= 'SOOT' /

&SURF ID= 'fire',  HRRPUA= 250.000 COLOR= 'RED',  RAMP_Q= 'fire_ramp',  /
&VENT XB =   -1.000,   1.000,  -1.000,   1.000,   0.000,   0.000, SURF_ID= 'fire', SPREAD_RATE= 0.00773578 /

&RAMP ID= 'fire_ramp', T=    0.000, F=    0.000, /
&RAMP ID= 'fire_ramp', T=    1.000, F=    1.000, /
&RAMP ID= 'fire_ramp', T=  300.000, F=    1.000, /
&RAMP ID= 'fire_ramp', T=  310.000, F=    0.000, /

&VENT XB =   -2.000,  -2.000,  -2.000,   2.000,   0.000,   4.000, SURF_ID= 'OPEN' /
&VENT XB =    2.000,   2.000,  -2.000,   2.000,   0.000,   4.000, SURF_ID= 'OPEN' /
&VENT XB =   -2.000,   2.000,  -2.000,  -2.000,   0.000,   4.000, SURF_ID= 'OPEN' /
&VENT XB =   -2.000,   2.000,   2.000,   2.000,   0.000,   4.000, SURF_ID= 'OPEN' /
&VENT XB =   -2.000,   2.000,  -2.000,   2.000,   4.000,   4.000, SURF_ID= 'OPEN' /
&SLCF PBX=    0.000, QUANTITY= 'TEMPERATURE', ID= 'x0' /
&TAIL /

@mcgratta
Copy link
Contributor Author

What you are doing is what I suggested, even though it is not exactly what you want. To do what you want would require making this feature far more complicated and prone to error and CPU bloat. I am uncomfortable going to all this effort to replicate a fictitious and unnatural heat release rate curve. If you want to mimic exactly any HRR curve, do not use the spread feature and just ramp up the fire over a given area to exactly match the curve.

@obscureed
Copy link

"Not exactly what you want" is an understatement -- I specified the fire to die out by t=310s, but it is still at full power at t=320s and it does not die completely until after t=470s. I could argue with your other points as well, but for now I'll be quiet.

@drjfloyd
Copy link
Contributor

You specified a RAMP that stops 310 s after the wall cell ignites. The T in RAMP_Q is time since ignition not overall simulation time. My guess is the last wall cell is igniting at 160 s (160 + 310 = 470).

What you are asking for is to have multiple control function inputs governing just the t2 growth vent type plus a bunch of logic to deal with a list of facets and times. This is not as trivial as change as you might think. We implemented the detailed control function logic in part so that user's can implement more complex needs without us having to develop new code, make verificaiton test cases for new code, document new code, and maintain new code in perpetuity.

@rmcdermo
Copy link
Contributor

rmcdermo commented Aug 21, 2024

Discussed this a bit and we think we can make a fairly simple change to how ramps are processed that would move us in the right direction. The key issue is decoupling the "T" in the RAMP from the "TSI" or Time Since Ignition in the ramp that multiplies the mass flux at a wall cell. One thought is to have a logical on the RAMP line that tells FDS whether T is meant to be TIME or TSI. Another option would be to use different parameters (T for TIME and TSI for Time Since Ignition---this is my preference but might not be very backward compatible).

If I make this hack in the code with your simple ramp,

&RAMP ID='fire_ramp', T=  0.0, F=1.0/
&RAMP ID='fire_ramp', T=300.0, F=1.0/
&RAMP ID='fire_ramp', T=310.0, F=0.0/

then I get this for the result (with twice the resolution; getting rid of the initial spike is also resolution dependent, but as you said we can tackle that later).
Figure_1

In general, the ramp function can be set to handle different spread rates and vent areas as follows. Suppose we have a vent with area A_VENT and a spread rate S. The circular area of the spread is A_SPREAD = pi*(S*T)^2. If F is the ramp function we would use for a t^2 fire with A_VENT, then the new ramp function is simply,

F_NEW(T) = F(T) * A_VENT/MIN(A_VENT,A_SPREAD[T])

Until A_SPREAD>A_VENT, this is just a constant that depends on the spread rate (if S is used for F[T] the constant is just 1) and beyond that you get back the original F(T).

I'm not sure if this solves all problems, but it seems to me it would get us moving toward what you are asking for. Let us know if this is worth implementing.

@drjfloyd
Copy link
Contributor

drjfloyd commented Aug 21, 2024 via email

@obscureed
Copy link

A few comments:

• I do not understand the usefulness of a new parameter SPREAD_DISTANCE, or new limits on the spread area. If the user wants a circular fire bed, smaller than the XB patch, this can already be specified in &VENT RADIUS=....

• "The T in RAMP_Q is time since ignition not overall simulation time."
— Yes, that is how RAMP_Q currently behaves when combined with SPREAD_RATE, but it is not what I expected from the User Guide, and not what I wanted.
— On the other hand, I can believe that it is exactly what some users might want -- for example, if the fuel at each facet has a finite life and burns with a certain history regardless of its neighbors.
— So now there is a bit of untangling to do. I cannot see a completely clean solution: either you break backward compatibility (where previous input files that used T in RAMP_Q to mean TSI will behave differently) or you break consistency (where T in a ramp usually means simulation time, except when applied to a RAMP_Q of a fire-bed VENT with SPREAD_RATE). Either way is going to be a bit ugly, and the User Guide will have to be updated.

• I accept @drjfloyd 's point that this is combining two controls that affect fire size -- the facet-by-facet spread, and the ramp -- and this is potentially complicated.
— I do not see how the existing logic controls currently help here.
— I have not completely worked out what @rmcdermo 's suggestion does, but it certainly looks useful. Basically, I think this is assuming a fixed rule to combine the two controls, and the rule is multiplication? Or the spread rate defines which facets are active, and the ramp (as a function of simulation time) defines the HRRPUA that applies to active facets?

• One point I want to make is that all this is helping to reach more realistic fire models without massive user input.
— For a fire size that starts small and grows slowly to large, SPREAD_RATE just looks right. The simple alternative is to have the large fire bed struggling along with a small HRRPUA spread uniformly across it while the fire size is small -- and this does not resemble a real fire at all well. (The complicated alternative is for the user to build a patchwork of fire beds, each with different ramps and fire sizes -- this is really fiddly to set up. To check when the combined patchwork reaches a certain size, you would need a spreadsheet.)
— None of the current discussion helps the 4- and 8-facet jumps in HRR. I still think there is potential for facet-by-facet response to an arbitrary RAMP_Q, without needing geometric scanning in mid-simulation. This is a separate feature from SPREAD_RATE, so perhaps it can wait, though it would be a good fit for grow-plateau-extinguish timelines.

• One extra feature that would be convenient would be a freeze on spread rate, in the same way that a NO_UPDATE_DEVC_ID can be applied to a ramp. I think that's a feature request for another day, but I mention it now in case it needs to be factored in.

@rmcdermo
Copy link
Contributor

@drjfloyd It depends on what you mean by "correct". For the period when the A_S < A_V, the fire grows with t^2 simply by following F=1, with T in the ramp being TIME. If you want each newly activated cell to have its own ramp based on TSI, then my approach will not work. But I think that using TIME instead of TSI gives the tight control over the shutdown that Ed is after. So, it's a bit of a compromise: easy coding and controls shutdown, but it does not solve all problems.

@drjfloyd
Copy link
Contributor

@obscureed you can define mutiple vents each with their own set of ramps and if you wanted those ramps to experience decay based on some event in FDS, that can be also be done using control functions. I recognize that this is more work for the user, but it can be done and gives much greater flexibility.

@rmcdermo At the instant of spread to the next cells in the current approach, the effective diameter of the fire does not change. We get a smooth change in the effective physical size of the fire which with the heat release rate drives entrainment. With your proposed approach we will a see jump up in the size of the fire diameter and a jump down in the burning intensity when each new ring ignites. This is going to cause some kind of step change in the entrainement. I see this change as potentially taking us further from the concept of what a t2 fire is (which I recognize is in itself just a convenient way of looking at real fires on solid fuels). Is this change in behavior going to be a net good or net bad for the typical user of SPREAD_RATE?

@rmcdermo
Copy link
Contributor

"With your proposed approach we will a see jump up in the size of the fire diameter and a jump down in the burning intensity when each new ring ignites."

I don't think we are on the same page. Taking T to be TIME in the RAMP, yes, with each new ring we get an increase in size, that is just how a t^2 fire grows. But we will not get a reduction in mass flux of fuel at the new wall cell. In this case F is 1 and the HRRPUA is a constant.

@drjfloyd
Copy link
Contributor

I think we are not on the same page. Say I am using a RAMP plus SPREAD_RATE to give a t2 growing fire. At some time t I have 100 kW and 0.1 m2 at t and at t+dt jumps to the next ring of cells giving 0.2 m2 and grows slightly (we generally have small timesteps) so the new HRR is 101 kW. My HRRPUA has gone from 1000 kW/m2 to 505 kW/m2 and the effective fire diameter has jumped by a factor of 2 over a timestep. In the old method, the original 0.1 m2 would keep the 1000 kW/m2 and the new would start at 5 kW/m2. My effective fire diameter and burning intensity will hardly change.

@rmcdermo
Copy link
Contributor

rmcdermo commented Aug 22, 2024

With the idea I'm proposing T_IGN is used for activation of a wall cell, but not for the RAMP of Q. I probably should not have complicated the idea with a discussion of rescaling F, forget about that for now. All F does is go to zero at a specific time (when Ed wants to turn off the fire). While the A_S(T) = pi * (S * T)^2 is less than the XB area of the VENT (assume a huge VENT area for now), each active cell has an HRRPUA of whatever is on the SURF line. The fire grows in size only by an increase in the number of active wall cells (which increases the AREA by t^2).

@drjfloyd
Copy link
Contributor

drjfloyd commented Aug 22, 2024 via email

@rmcdermo
Copy link
Contributor

Yes, for now at least, in my approach the step changes are resolution dependent. As I said, my method does 2 things: it's easy to code and it tightly controls the shutdown of the fire.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants