This is what I am trying to model:
pipe_flow_sketch.pdf
basically we have a level (A) feeding into a pipe (actually this is a length of intestines in my larger model that is modeling uptake of a nutrient) that ends up at level (B) according to "delayed_Flow" rate. While it is in the pipe a portion of the nutrient is absorbed through the pipe wall to level C. This is "AC flow rate".
I dried to model the accumulation of material into the empty pipe using a Delay function, but I hit a problem in making sure that the level in "A" does not go negative. Models up to this point were fixed by checking for a negative value in the level using "If Then Else (A<0,0,flowRate)". This works with AC Flow rate, but the test does not seem to be working when it is nested inside the delay function. I tried moving the test outside the delay and putting it into a variable " AB_FlowthroughPipe" , but it still does not shut down flow when A reaches 0.
This simplified model is in the mdl file: TestDelayFunction_Simplified.mdl
It seems I am probably fundamentally misusing the Delay function, so is there a more elegant way of doing this in Vensim?
I think this type of model might have a lot of applications: plug flow reactors not at steady state, contaminants precipitating in a river, change in concentration in a reverse osmosis system, dialysis, renal function, traffic flow diversions off Highways onto side streets.
Delay Function cannot shut off flow using a test for negative stock level.
Delay Function cannot shut off flow using a test for negative stock level.
 Attachments

 TestDelayFunction_Simplified.mdl
 (3.69 KiB) Downloaded 43 times

 pipe_flow_sketch.pdf
 (238.93 KiB) Downloaded 40 times

 Super Administrator
 Posts: 3823
 Joined: Wed Mar 05, 2003 3:10 am
Re: Delay Function cannot shut off flow using a test for negative stock level.
Doesn't this suggest the structure you have drawn is incorrect? I'd suggest having a flow out of A, put this into a level "in transit" (or give it a real world name rather than A/B/C), and remove a proportion from that level? The remainder will go into B.While it is in the pipe a portion of the nutrient is absorbed through the pipe wall to level C. This is "AC flow rate".
Advice to posters seeking help (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Units are important!
http://www.bbc.co.uk/news/magazine27509559
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Units are important!
http://www.bbc.co.uk/news/magazine27509559
Re: Delay Function cannot shut off flow using a test for negative stock level.
You might check this: https://metasd.com/2019/11/theimportanceoffonfoo/
/*
Advice to posters (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Blog: http://blog.metasd.com
Model library: http://models.metasd.com
Bookmarks: http://delicious.com/tomfid/SystemDynamics
*/
Advice to posters (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Blog: http://blog.metasd.com
Model library: http://models.metasd.com
Bookmarks: http://delicious.com/tomfid/SystemDynamics
*/
Re: Delay Function cannot shut off flow using a test for negative stock level.
Replying to Tomfid:
Oh I didnt know it was called FONFOO, but isnt that what I did by testing for zero at A?
Delayed flow = DELAY FIXED( AB flowThrougPipe , Delay , 0 )
where AB flowThrougPipe = IF THEN ELSE(A<0, 0 , AB flow rate*A )
then on the other flow, "AC Flow Rate" = IF THEN ELSE(A<0, 0 , 0.1 )
Oh I didnt know it was called FONFOO, but isnt that what I did by testing for zero at A?
Delayed flow = DELAY FIXED( AB flowThrougPipe , Delay , 0 )
where AB flowThrougPipe = IF THEN ELSE(A<0, 0 , AB flow rate*A )
then on the other flow, "AC Flow Rate" = IF THEN ELSE(A<0, 0 , 0.1 )
Re: Delay Function cannot shut off flow using a test for negative stock level.
ABflowthroughpipe does impose the constraint for A<0, however, DelayedFlow does not respect the constraint. The DELAY FIXED means that the flow now depends on the value of A in the past, not the value of A now.
Also, the test for A<0 is not sufficient. A might have a small positive value, or 0 value, so that the flow in one time step causes it to fall below 0.
Also, the test for A<0 is not sufficient. A might have a small positive value, or 0 value, so that the flow in one time step causes it to fall below 0.
/*
Advice to posters (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Blog: http://blog.metasd.com
Model library: http://models.metasd.com
Bookmarks: http://delicious.com/tomfid/SystemDynamics
*/
Advice to posters (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Blog: http://blog.metasd.com
Model library: http://models.metasd.com
Bookmarks: http://delicious.com/tomfid/SystemDynamics
*/
Re: Delay Function cannot shut off flow using a test for negative stock level.
Hello Folks,
Thanks for your help. Attached is the solution I have so far.
I have attached the model with more descriptive labels, rather than A, B C etc, as administrator said, it makes it a bit more understandable.
As tomfid said, using DELAY FIXED to control flow does not work as it cannot do a logical test on current variables, the only variables available to it are the values that were in existence at the time DELAY was called.
Administrator also suggested putting the outflow into a new level and control flows in and out of this "in transit level". In this example the in transit level is "intestines" then I replaced the DELAY function with a IF THEN ELSE test on a <Time> shadow variable to start flow out to "Egestion" once the 8h is up (my guess for residence time in intestines).
You can imagine this is something of a simplification of what really happens in the gut, but its just thinking of the "stomach" as a CSTR reactor followed by the "intestines" modeled as a plug flow tube reactor. Refinement can come later.
There is also a FONFOO performed at the stomachOutFlow (IF THEN ELSE( Stomach<=0 , 0 , Stomach*stomach flow constant ), and at IntestinalFlow Rate (IF THEN ELSE( Time<8 :OR: Intestines<=0 , 0 , gut flow). Note this is also checking time < 8 before starting up the flow out of intestines using :OR: in the logical test.
One thing i have noticed is that if you drag the IO object tool slider for gut flow over 2.8 g/h, the intestinal flow rate starts oscillating after 23h. This is because there is still material dribbling in from the stomach at a low rate at some time steps there is inadequate intestinal level to result in the intestinal flow to be positive. Eventually intestinal level goes positive and the intestinal flow rate switches on, but only enough for it to hit <0 and it shuts down. Not sure how to do this more elegantly. Tying intestinalFlowRate to the level of material in intestines (e.g. intestinalFlowRate = ki*intestines) would be mathematically incorrect as this would not be a first order type of situation (in this simple model, flow of nutrients down the intestines has a constant velocity or zero order in the intestines).
Not sure what to do about that. If you have any suggestions, that would be great.
Thanks for the help so far!
Thanks for your help. Attached is the solution I have so far.
I have attached the model with more descriptive labels, rather than A, B C etc, as administrator said, it makes it a bit more understandable.
As tomfid said, using DELAY FIXED to control flow does not work as it cannot do a logical test on current variables, the only variables available to it are the values that were in existence at the time DELAY was called.
Administrator also suggested putting the outflow into a new level and control flows in and out of this "in transit level". In this example the in transit level is "intestines" then I replaced the DELAY function with a IF THEN ELSE test on a <Time> shadow variable to start flow out to "Egestion" once the 8h is up (my guess for residence time in intestines).
You can imagine this is something of a simplification of what really happens in the gut, but its just thinking of the "stomach" as a CSTR reactor followed by the "intestines" modeled as a plug flow tube reactor. Refinement can come later.
There is also a FONFOO performed at the stomachOutFlow (IF THEN ELSE( Stomach<=0 , 0 , Stomach*stomach flow constant ), and at IntestinalFlow Rate (IF THEN ELSE( Time<8 :OR: Intestines<=0 , 0 , gut flow). Note this is also checking time < 8 before starting up the flow out of intestines using :OR: in the logical test.
One thing i have noticed is that if you drag the IO object tool slider for gut flow over 2.8 g/h, the intestinal flow rate starts oscillating after 23h. This is because there is still material dribbling in from the stomach at a low rate at some time steps there is inadequate intestinal level to result in the intestinal flow to be positive. Eventually intestinal level goes positive and the intestinal flow rate switches on, but only enough for it to hit <0 and it shuts down. Not sure how to do this more elegantly. Tying intestinalFlowRate to the level of material in intestines (e.g. intestinalFlowRate = ki*intestines) would be mathematically incorrect as this would not be a first order type of situation (in this simple model, flow of nutrients down the intestines has a constant velocity or zero order in the intestines).
Not sure what to do about that. If you have any suggestions, that would be great.
Thanks for the help so far!
 Attachments

 IntestinalModel_2.mdl
 (3.38 KiB) Downloaded 24 times
Re: Delay Function cannot shut off flow using a test for negative stock level.
I think the oscillation is due to the discrete logic in the outflow constraint. You have:
intestinal Flow Rate=
IF THEN ELSE( Time<8 :OR: Intestines<=0 , 0 , gut flow)
This enforces "nothing in intestines, no outflow" but it doesn't enforce "tiny amount in intestines, limited outflow".
A better construction might be:
IF THEN ELSE( Time<8, 0, MIN( gut flow, intestines/min intestinal flow time ) )
where min intestinal flow time could be replaced with (or set to) TIME STEP as a shortcut.
I would tend to rewrite as:
STEP(1,intestinal flow time)*MIN( gut flow, intestines/min intestinal flow time )
intestinal flow time = 8
intestinal Flow Rate=
IF THEN ELSE( Time<8 :OR: Intestines<=0 , 0 , gut flow)
This enforces "nothing in intestines, no outflow" but it doesn't enforce "tiny amount in intestines, limited outflow".
A better construction might be:
IF THEN ELSE( Time<8, 0, MIN( gut flow, intestines/min intestinal flow time ) )
where min intestinal flow time could be replaced with (or set to) TIME STEP as a shortcut.
I would tend to rewrite as:
STEP(1,intestinal flow time)*MIN( gut flow, intestines/min intestinal flow time )
intestinal flow time = 8
/*
Advice to posters (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Blog: http://blog.metasd.com
Model library: http://models.metasd.com
Bookmarks: http://delicious.com/tomfid/SystemDynamics
*/
Advice to posters (it really helps us to help you)
http://www.ventanasystems.co.uk/forum/v ... f=2&t=4391
Blog: http://blog.metasd.com
Model library: http://models.metasd.com
Bookmarks: http://delicious.com/tomfid/SystemDynamics
*/