doyubkim / fluid-engine-dev

Fluid simulation engine for computer graphics applications
https://fluidenginedevelopment.org/
MIT License
1.9k stars 266 forks source link

[APIC Solver] The preferred direction of motion of particles #288

Open PavelBlend opened 4 years ago

PavelBlend commented 4 years ago

Hello, @doyubkim

Using the APIC solver, I noticed one thing. Particles fly apart in the + X and + Z directions to a greater extent than in the -X and -Z directions. What can this be connected with and is this a mistake? Unfortunately, I can not provide a py file for an example, since I use blender addon for testing. Here are the screenshots: 01 02

doyubkim commented 4 years ago

Thanks for reporting this, @PavelBlend! Looks like there are some unintended anisotropy-ness in the code. What happens if you simulate the same scene with FLIP?

PavelBlend commented 4 years ago

In the APIC solver, particles are clogged in a corner. 01 02

doyubkim commented 4 years ago

Hmm I'm seeing two different issues here.

First one is the spread of the particles are biased toward the upper right corner, regardless of the solver. Is the chunk of particles slightly thrown to that direction or are you dropping it directly to -y axis and still getting this results?

Second is the clogging which is sort of expected since there are no mechanism implemented to prevent that behavior. This issue might need some extra noise added to the boundary to prevent the clogging.

Anyway, let me take some time to come up with solutions for these.

PavelBlend commented 4 years ago

Is the chunk of particles slightly thrown to that direction or are you dropping it directly to -y axis and still getting this results?

Initial velocity is 0.0, 0.0, 0.0 and 2.0, 0.0, 0.0.

doyubkim commented 4 years ago

Thanks @PavelBlend! Yes, that explains why the particles were heading toward the walls. Let me think how I can address the clogging issue then.

PavelBlend commented 2 years ago

after testing, I noticed that this behavior only occurs when using the single phase pressure solver. But if you use a fractional single phase pressure solver, then this behavior will not be: 0000

doyubkim commented 2 years ago

Very interesting. Thanks for providing more info! Please use the fractional solver in the meantime. It is more accurate anyway.

kujukuju commented 1 year ago

@doyubkim I believe this has to do with the matrix building and pressure applying code.

I've been using the book just as a reference while working on a project, so I'm not sure I completely understand all intricacies and shortcuts in the code. (For example, I know a cell centered grid has an extra column and row to avoid issues when checking neighboring indices.)

However, it seems to me that the matrix building code, and the matrix application code isn't "symmetric". The code for my fluid grid is sized exactly at the requested dimensions (no extra padding), so my situation might be different, but I've been able to correct some of my artifacts by messing with this code. https://github.com/doyubkim/fluid-engine-dev/blob/main/src/jet/grid_single_phase_pressure_solver2.cpp#L42-L47

I feel like it's likely I'm misunderstanding this code, but it seems incorrect to only check:

  1. if the current cell is a fluid
  2. if the right cell is a boundary
  3. if the right cell is a fluid

Because the matrix is symmetric, it seems like it would be necessary to also check the same conditions for the left cell, and increment/decrement the row center/right values respectively. Is my understanding here incorrect? It seems that otherwise it's inevitable that you'd end up with skewed velocity values in whichever direction you're checking (in this case right to left.)

Similarly when applying the pressure to the velocity of the grid, the pressure is only resolved considering the current cell pressure, and the left cell pressure. And in doing this, the left most column of the grid is left completely unaffected. https://github.com/doyubkim/fluid-engine-dev/blob/main/src/jet/grid_single_phase_pressure_solver2.cpp#L368-L377

I understand it's common practice to have a 1 cell boundary around the edge of your grid to help with these types of things, but it seems like it was still adding some very slight velocity artifacts to my code.

I'm interested to hear if my understanding of this is wrong, and if the code linked is actually a logically correct shortcut to resolving all adjacent pressures.

kujukuju commented 1 year ago

Also, if this is true, I expect the fractional pressure solving code has a similar issue. But because this issue only occurs at the left and bottom boundaries, and the fractional pressure solver subdivides each cell, I think the issue is just significantly less pronounced.

doyubkim commented 1 year ago

Hello! Thanks for the question. About the matrix, it is actually building the upper triangle (+diagonal) part of the matrix only, since we know it is symmetric.