new-ospgl icon indicating copy to clipboard operation
new-ospgl copied to clipboard

Fluid Simulation

Open tatjam opened this issue 4 years ago • 8 comments

We should simulate the fluids inside of the tanks and its motions through the vehicle on a more or less accurate way. The system should avoid being "rocket-centric" as airplanes and other vehicles will also benefit from fluid simulation.

PhysicalMaterials define the physical properties of any material thing, such as what parts or planets are made of and the fuel inside tanks.

FluidTanks should offer a simple liquid-vapor equilibrium simulation, and should also implement some kind of "sloshing" dynamic and simulate ullage distribution.

Pipes are connections between fluid ports, they have physical significance and are connected between points of the vehicle so that they have a length and a radius. We can then use the Hagen-Poiseuille equation to approximate volumetric flow and then mass flow, assuming fully laminar flow, but simulating viscosity (*).

Temperature could be simulated only in tanks, or could also be included in all pipes. We should be able to simulate systems such as heat exchangers.

Conservation of Energy: We should try to conserve energy as best as we can while fluids are moving. KSP has a bunch of issues with this where you can use the fluid pumping mechanic to gain velocity.

(*) As a mixture of fluids may be flowing through the pipe, we should think what to do on this case. Simulating each fluid independently doesn't make much sense. For example, on a H2 feeding pipe to a combustion chamber, H2O backflow would be massive as the partial pressure of H2O in the tank is 0. On reality, the incoming fluid prevents any backflow: The fluid flow should more or less be equal to that of the most viscous fluid, assuming that there is enough of it as to "block" the pipe.

tatjam avatar Mar 22 '21 09:03 tatjam

I have decide to use a simple Bernoulli solved for velocity (and then volumetric flow = velocity * area) as Hagen-Poiseuille requires either extremely long pipes or very thin ones. This means that we will ignore viscosity, but density will still matter

tatjam avatar Mar 23 '21 19:03 tatjam

Junction method

We impose a simple requirement on junctions, the sum of all flows through it must be zero. As flows are proportional to the square root of the pressure difference, we can solve the system for the "pressure" at the junction. It turns out that the function is piecewise, so we first find which piece is the solution (there may only be one) by checking the signs at both ends, and then we use the Newton-Rhapson method to find the solution. 1 or 2 iterations are pretty much perfect.

There is a closed form solution, but it's quite long and probably more expensive than the approximation as it requires calculating quite a lot of powers and square roots, while the approximation is simply nx2xiterations square roots. (Maybe implement it and profile it if it matters?)

tatjam avatar Mar 29 '21 12:03 tatjam

As of this commit (https://github.com/TheOpenSpaceProgram/new-ospgl/commit/6efe199864b9fb00fa93bcfbdd6594663891f221) the plumbing editor is working but still has a bunch of bugs

tatjam avatar Aug 18 '21 13:08 tatjam

https://github.com/TheOpenSpaceProgram/new-ospgl/commit/8f71960a75d4828825946709070413d576dce260 started to implement the fluid tanks in lua

tatjam avatar Aug 22 '21 11:08 tatjam

Here's a new fluid flow algorithm I have been thinking about. It may contain some errors, but it's a written down version of the thinking I've been doing lately. Hopefully its implementation doesn't reveal a fatal flaw like the previous design had, as this one seems fairly promising, but also way more tricky to implement!

  • Flow machines: Machines which store so little fluid their pressure is not accounted for (as it depends on boundary conditions) and act as points through which fluid moves. They may also be elements which modify flow pressure greatly. Pipes, pumps, junctions...
  • True machines: Machines which "store" enough fluid, and thus, become inlets and outlets from the system. They are fluid tanks, engines, etc... They may not actually store fluid, such as engines, but their pressure will not be greatly dependent of the flows in the system.

The algorithm consists of two parts:

Flow direction determination algorithm:

  • First, every true machine will find paths to every other reachable true machine, accounting for every flow machine in the path which may change pressure (pumps for example). This path must always go away from the starting machine!
  • The pressure of the propagated path is compared to the target machine pressure, if it's lower, the flow path is early discarded
    • Paths which survived this selection are stored
    • One-way valves can be implemented by having them drop pressure to 0 in the no-flow direction, etc...
  • Once all possible paths are in the array, we build a compatibility map (nxn symmetric matrix) - If two flow paths have atleast a single point in which they are opposite, they are incompatible - At the end of the process, only compatible paths remain - Every true machine with only one possible path is marked as "forced", and all paths incompatible with the forced path are discarded
    • This is repeated until every machine only has a single possible path
    • The remaining paths must be compatible and unique for each machine
    • Flows are calculated using the pressure difference of the flow path

Flow algorithm:

  • Every true machine will lose a small ammount of fluid onto the chosen path. The first flow machine in the path will accept this fluid and discard enough from its internal tank into the next flow machine (thus creating a chain of fluids allowing systems such as pre-loading pipes). If the internal tank is too small or non-existant, then we simply move part (or all) of the accepted fluid. - Eventually the algorithm will reach the target machine and be done

Considerations of the graph:

  • From the design of the algorithm, it's not allowed to have cycles built from flow machines:
    • For example, a pipe going back to itself would break
    • A more realistic example is a junction connected to itself through a pump. This behaviour is not simulated, although it's physically possible
  • It's perfectly possible to have cycles built from real machines, or even from a single real machine
    • For example, a fuel tank connected to itself through a pump

The new thinking removes the uniqueness from pipes and junctions, and now the concept of plumbing connection is even more abstract. This is inline with the conception of the plumbing system as freely modifiable in lua, users could implement realistic pipes and junctions in lua, something which was not possible in the previous design.

tatjam avatar Dec 08 '21 13:12 tatjam

The concept of true machines and flow machines can be generalized further to true ports and flow ports. This allows machines to combine both, for example, for a self-powered turbopump which consumes liquid fuel.

tatjam avatar Dec 29 '21 16:12 tatjam

This also requires changing the logic a bit as now we are finding paths between ports. This is also cleaner and easier to understand as machines may have many ports!

tatjam avatar Dec 29 '21 16:12 tatjam

I've changed the algorithm a bit, as the matrix step was unnecessary. You can simply run the algorithm to find forced paths, then remove every path incompatible with it and repeat in a loop, which is what is currently done in the code (although it doesn't compile yet so it may not work at all)

tatjam avatar Dec 30 '21 16:12 tatjam

This is kind of done, although will (may be is more appropriate) be "rewritten" in the change to generic physical systems.

tatjam avatar Aug 26 '23 16:08 tatjam