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

Consultation on unit pressure drop #97

Open
zasddsgg opened this issue Feb 1, 2024 · 4 comments
Open

Consultation on unit pressure drop #97

zasddsgg opened this issue Feb 1, 2024 · 4 comments

Comments

@zasddsgg
Copy link

zasddsgg commented Feb 1, 2024

Hello, may I ask you some questions about the unit pressure drop?

a) The units like heat exchanger, storage tank, filter presser, conveyor can not achieve the pressure drop of the flow, if I want to achieve achieve the pressure drop of the flow, may I ask if you have any suggestions?

b) For the above units, if the pressure drop is achieved by unit pump, it seems to consume power, besides, it seems unreasonable to achieve the pressure drop by pumping when transferring solids.

c) For case #96, could I trouble you spare some time to look at the issue published on December 5th? Since analytical specifications and numerical specifications are often used in the process, I wanted to make sure I was using them without problems.

Thank you very much for your help.

@yoelcortes
Copy link
Member

Hi @zasddsgg,

Certainly, I'll plan to answer your questions Monday of next week.

Thanks!

@zasddsgg
Copy link
Author

zasddsgg commented Feb 2, 2024

Thanks again for your help.

@yoelcortes
Copy link
Member

yoelcortes commented Feb 5, 2024

a) For setting pressure drops of units that do not yet have this feature:

unit.dP = 0.04
@unit.add_specification(run=False)
def set_dP():
    unit._run()
    P0 = min([i.P for i in unit.ins])    
    Pf = P0 - unit.dP
    for i in unit.outs: i.P = Pf

No need to add impacted units. Impacted units is only needed when upstream units or units in parallel are impacted.

b) Use valves (https://biosteam.readthedocs.io/en/latest/API/units/valve.html#biosteam.units.valve.IsenthalpicValve) if the outlet pressure is lower than the inlet. Pumps assume a given pressure gain if the inlet pressure is equal or higher than the outlet https://biosteam.readthedocs.io/en/latest/tutorial/Gotchas.html#Simplified-pressure-handling.

c) Systems converge iteratively by sequentially running each unit operation and their specification in each loop. The initial guess for the flow rates of recycle streams can be larger or lower than the solution (it does not mater). If you would like to gain more insight, try running each unit operation within the system iteratively to understand what is going on. For example

for i in range(10):
    for i in sys.unit_path:
        i.run()
    recycle.show()

Your system (#96; last post) has several problems:

  • You have ethanol leaving the system through the flash vapor, and no ethanol entering the system. This makes no sense. You need an inlet of ethanol.
  • In your analytical specification, you are changing an outlet stream flow rate (this only works if you have 100% recirculation). Instead, please change a fresh feed flow or a design parameter to achieve your desired outcome analytically.

Thanks!

@zasddsgg
Copy link
Author

Thank you for your answer. May I ask you the following questions.

a) Does setting the pressure drop in the way in your response “a) For setting pressure drops of units that do not yet have this feature:” affect the cost, heat required or heat released of the heat exchanger, storage tank, filter presser and conveyor? Because the cost and heat required or heat released of the unit seem to be calculated in the absence of pressure drop.

b) In your reply a), , why use run=False in @unit.add_specification(run=False) and unit._run()? Why not run=True? For adjusting the unit pressure drop, are both of the following codes right? What's the difference between the following codes?

unit.dP = 0.04
@unit.add_specification(run=False)
def set_dP():
    unit._run()
    P0 = min([i.P for i in unit.ins])    
    Pf = P0 - unit.dP
    for i in unit.outs: i.P = Pf
unit.dP = 0.04
@unit.add_specification(run=True)
def set_dP():
    P0 = min([i.P for i in unit.ins])    
    Pf = P0 - unit.dP
    for i in unit.outs: i.P = Pf

c) For setting the pressure drop of unit (heat exchanger, storage tank, filter presser and conveyor) in reply a), should I use the way in reply a) or valve in return b)?

d) For solid transfer, how is the pressure drop set? Is the pressure drop set in the conveyor belt in the way of your reply a)
For gas transfer, how is the pressure drop set? Is the pressure drop set in the compressor in the way of your reply a)
For liquid transfer, how is the pressure drop set? Is the pressure drop set in the flow units such as heat exchangers, storage tanks and filter presser in the way of your reply a)?

e) When using Analytical specifications and bounded Numerical specifications, how to ensure that after the implementation of Analytical specifications and bounded Numerical specifications, rerun the associated unit

f) In the Analytical specifications, how to choose the unit that is @ in @unit.add_specification()?

g) For the upstream unit and parallel unit in your reply a, are they units relative to the unit that is @ in @unit.add_specification()?

h) Is it the same to use unit.run() or unit.run_until(unit) in bounded Numerical specifications? What’s the difference between them?

i) In your reply a) and https://biosteam.readthedocs.io/en/latest/tutorial/Process_specifications.html#Numerical-specifications:~:text=def%20f(x)%3A%0A%20%20%20%20%23%20Objective%20function%20where%20f(x)%20%3D%200%20at%20a%0A%20%20%20%20%23%20vapor%20fraction%20of%2050%20wt.%20%25.%0A%20%20%20%20F1.T%20%3D%20x%0A%20%20%20%20F1.run(), why isn't unit.run() in Analytical specifications and bounded Numerical specifications at the end of code def()? Because it seems to guarantee that the unit will be rerun after the specification is executed.

j) What does it mean in https://biosteam.readthedocs.io/en/latest/API/Unit.html#:~:text=This%20method%20also%20runs%20specifications%20user%20defined%20specifications%20unless%20it%20is%20being%20run%20within%20a%20specification%20(to%20avoid%20infinite%20loops).?
Does it refer to that unit.run() will automatically run the user-defined specification, is unit.run() in the specification just used to avoid infinite loops, or does it have some other purpose?

k) For the example in https://biosteam.readthedocs.io/en/latest/tutorial/Process_specifications.html#Numerical-specifications:~:text=print(%27vapor%20mass%20fraction%3A%20%27%2C%20format(F1.outs%5B0%5D.F_mass%20/%20mixture.F_mass%2C%20%27.0%25%27)), I use the same code and the output is 0.32 instead of 0.5?

l) If there are multiple adjusted streams, so have multiple affected units, is there a sequence for unit a,b,c in impacted_units=[a, b, c], i.e. is impacted_units=[a, b, c] the same as impacted_units=[a, c, b], and impacted_units=[b, c, a]? Does the order of the unit a,b,c in impacted_units=[] correspond to the order in which the adjusted streams appear in the code in analytical specifications?

m) If there are more than two affected units in analytical specifications, is it written this way: @F101.add_specification(impacted_units=[P104, D101])?

n) Is it OK to use one unit as the impact_unit of the previous specification and also as the unit that is @ in the next specification?

o) If two specifications @ are the same unit, such as @p103, can impact_unit not be the same? For example, is the code @P103.add_specification(run=True, impacted_units=[M101]), def adjust_ethanol_flow():, @P103.add_specification(run=True, impacted_units=[S101]), def adjust_pump_pressure_P103() ok?

p) If there is more than one specification in a process, can the impact_unit not be the same? Such as M101 in @P103.add_specification(run=True, impacted_units=[M101]) and H101 in @P102.add_specification(run=True, impacted_units=[H101]), M101 and H101 is not the same unit, is it ok?

q) In the same specification, there are two affected streams connected to the same unit. Is it OK to write the impact_unit once? For example, in @P103.add_specification(run=True, impacted_units=[M101]), stream riboflavin and stream Water both affect M101, So in impacted_units=[M101] of @P103.add_specification(run=True, impacted_units=[M101]), M101 is only written once, not impacted_units=[M101, M101], is it ok?

r) How to choose which unit is @ in analytical specification? Sometimes unit which is @ is the unit to be adjusted, sometimes it is the mixer, and sometimes it is the pump for recycle stream.

s) If two streams are changed in a specification, are both unit a (upstream or parallel) and unit b (upstream or parallel) that use two streams as inlet streams respectively taken as impact_unit?

t) For “You need to specify all the units being directly impacted (which can be 0, 1, or more)”, what does it mean that the impact_unit is 0? If there are no units after P104, is this the case where impact_unit is 0? Do I still need to add impact_unit when the impact_unit is 0?

u) It seems that unit that is @ and impact_unit cannot be the same unit? Is it right? Do I still need to add impact_unit if the unit that is @ and impact_unit are the same unit?

v) In bounded numerical_specification, Does the unit that is @ and unit in unit.run_until in bounded_numerical_specification refer to the unit that the adjusted argument (such as V in F301.V = V in https://biosteam.readthedocs.io/en/latest/tutorial/Building_a_biorefinery.html#:~:text=(V)%3A-,F301.V%20%3D%20V,-F301.run_until) is located in? For (unit) in run_until(unit) in bounded_numerical_specification, which unit should I use in parentheses?

w) If like in the tutorial (https://biosteam.readthedocs.io/en/latest/tutorial/Building_a_biorefinery.html#:~:text=%40F301.add_bounded_numerical_specification(x0%3D0%2C%20x1%3D1%2C%20xtol%3D1e%2D5%2C%20ytol%3D1e%2D2)), I want to control the output of another unit by adjusting the input of one unit, I must add unit.run_until, is it right? That is, when should I add unit.run until?

x) As in the tutorial (https://biosteam.readthedocs.io/en/latest/tutorial/Process_specifications.html#:~:text=def%20f(x)%3A%0A%20%20%20%20%23%20Objective%20function%20where%20f(x)%20%3D%200%20at%20a%0A%20%20%20%20%23%20vapor%20fraction%20of%2050%20wt.%20%25.%0A%20%20%20%20F1.T%20%3D%20x%0A%20%20%20%20F1.run()), if I want to adjust the input of a unit so that the outlet gas fraction of the unit is 0.5, do I need to add unit.run_until (there are other units in the process)? If not, do I need to add unit.run (such as F1.run in the tutorial)? In bounded Numerical specification,does either unit.run_until or unit.run must be added? When should I use unit.run_until and when should I use unit.run?

y) Is it better to set inclusive=True than inclusive=False when using unit.run_until in bounded_numerical_specification? What is the difference between inclusive=True and inclusive=False?

z) In the calculator, should code @unit.add_specification follow the unit that is @ (such as code M1 = units.Mixer('M1', ins=(dehydrated_ethanol, denaturant), outs='denatured_ethanol')) (i.e. there should be no other codes between them)? Should the code def() follow the code @unit.add_specification (i.e. there should be no other codes between them)?
In bounded_numerical_specification, should the code def() follow code @unit.add_bounded_numerical_specification () (i.e. there should be no other codes between them)?

Z1) If one unit (such as the following unit P103) has two analytical specification, can I combine two codes def() ? If impact_unit is different, can I only write two def() separately? If I write them separately, can I have two def() for the same unit that is @? Are there some orders for two def()?
For example, the code is as follows:

P103=units.Pump('P103', H102-0, recycle, P=101325)
@P103.add_specification(run=True, impacted_units=[M101])
def adjust_ethanol_flow():                       
    F_mass_Ethanol = recycle.imass['Ethanol']
    F_mass_Water = recycle.imass['Water']
    riboflavin.imass['Ethanol'] = max(350 - F_mass_Ethanol, 0)
    Water.imass['Water'] = 350 - F_mass_Water
@P103.add_specification(run=True) 
def adjust_pump_pressure_P103():
    a = H102-0
    P103.P = a.P + 10132.5

Z2) For “In your analytical specification, you are changing an outlet stream flow rate (this only works if you have 100% recirculation). Instead, please change a fresh feed flow or a design parameter to achieve your desired outcome analytically”, but what I changed itself is the input stream riboflavin and stream Water. So may I ask you if there is any problem with this?

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

2 participants