I hope after reading this post you will be able to predict everything with fluids.

Every fluid-containing object can be described with the following values: max capacity, max pressure and zero-pressure.

Max capacity is maximum amount of liquid which can fit into container.

Max pressure and zero pressure is a pressure of a full and empty container respectively.

Using its water level we can calculate its current pressure = zero-pressure + (max pressure - zero-pressure) * water level / max capacity.

Entities

Atomic object of the entire fluid system is a pipe. Simple pipe with 100 capacity and 0..100 pressure (first number is a zero pressure, second number is a max pressure). Later you will understand the purpose of this small picture.

Next object is storage tank. Basically storage tank can be considered as a very long pipe because it has the same pressure 0..100 but bigger capacity 25000.

Everyone knows that pipe connected with storage tank balances its pressure level, this is clearly demonstrated on this picture:

Next entities are "heart" of energy production system: boiler, heat exchanger, steam engine and steam turbine - all these entities share the same values (200 capacity and -100..100 pressure). Wait, what? negative pressure? Yep, this value is negative because it is located below the ocean level (ocean = default pipe). And here comes first interesting picture:

Last object is pump, it is very particular entity because it accepts liquid using electrical "force", and output flow obeys regular rules. Pump has 200 capacity and 0..200 pressure. Picture with disabled pump:

Powered pump increases its input flow up to pumping speed.

Also, there are several other entities that can interact with liquids:

- mining drills with sulfuric acid (200 capacity, -100..100 pressure)

- assemblies, chemical plants, oil refineries (input/output - same mechanic as with pump (speed? - untested yet))

- underground pipes have the same parameters as a regular pipe, but they "teleports" liquid, so using underground pipes allows to reduce pressure recession.

- did I forget something?

Flow

Okay, now we know and understand basic concepts of every entity and it is time to figure out how they interacts between themselves.

Each pair of adjacent entities balances their pressure every tick, this happens in the following way: entity with bigger pressure (here I means current pressure, there was a formula in the beginning) transfer its liquid to the entity with smaller pressure. This direct transfer is equal to (Pressure_A - Pressure_B)*0.4 (this coefficient is unique for every type of liquid, but as far as I know it is always 0.4). Also there are exist an inertial transfer, it can be calculated as part of previous tick flow: Previous_Flow * 0.59 (also predefined coefficient). Inertial component is limited with 10% of the max capacity of the destination entity.

So, total formula is (Pressure_A - Pressure_B) * 0.4 + Limited[Previous_Flow * 0.59, Target_Capacity * 0.1].

- using entities with different zero-pressure level simultaneously

- pumping from entity with low capacity

Obviously, it is not possible to pump more than we have in adjacent entity.

- pumping into entity with high zero-pressure:

using natural pressure difference you can increase flow speed:

- pressure-ignoring pumping into low zero-pressure entity

Pressure-ignoring pumping should be targeted on higher zero-pressure entity, because later natural pressure difference may be used for free.

- filling tank from low zero-pressure entity

Application

Using previous information we can calculate some interesting formulas:

X axis - flow speed in units/tick (Steam engine = 0.5, Steam turbine = 1, Offshore pump = 20, Pump = 200)

Y axis (logarithmic scale) - max pipe distance which can maintain specified flow speed.

and table