ProjectPhysX / FluidX3D

The fastest and most memory efficient lattice Boltzmann CFD software, running on all GPUs via OpenCL. Free for non-commercial use.
https://youtube.com/@ProjectPhysX
Other
3.82k stars 303 forks source link

Dynamic extraction of gas elements from model not working as expected? :3 #221

Closed RandomInternetPreson closed 2 weeks ago

RandomInternetPreson commented 2 weeks ago

Hello, I have been pulling my hair out trying different things but I can't seem to be able to pull out all the xyz coordinates of the gas elements from my model here:

#include <vector>
#include <iostream>
#include <fstream>
#include <iomanip> // For std::setprecision
#include <mutex> // For std::mutex

void main_setup() {
    // Set up the simulation box
    const uint Nx = 200u; // 200mm width
    const uint Ny = 2000u; // 2000mm length
    const uint Nz = 200u; // 200mm height
    const float nu = 1.0f / 6.0f; // kinematic shear viscosity
    const float fy = 0.0005f; // buoyancy force in positive y-direction
    const float sigma = 0.01f; // surface tension coefficient (moderate value)
    LBM lbm(Nx, Ny, Nz, nu, 0.0f, fy, 0.0f, sigma);

    // Initialize the bubble
    const uint cx = Nx / 2u;
    const uint cy = 50u; // 50mm from the bottom
    const uint cz = Nz / 2u;
    const uint radius = 25u; // 25mm diameter bubble
    parallel_for(lbm.get_N(), [&](ulong n) {
        uint x, y, z;
        lbm.coordinates(n, x, y, z);
        if (sqrtf((x - cx) * (x - cx) + (y - cy) * (y - cy) + (z - cz) * (z - cz)) < radius) {
            lbm.flags[n] = TYPE_G; // gas cell (bubble)
        } else {
            lbm.flags[n] = TYPE_F; // fluid cell (water)
        }
    });

    // Initialization Debugging
    uint initial_gas_cells = 0u;
    parallel_for(lbm.get_N(), [&](ulong n) {
        if (lbm.flags[n] == TYPE_G) {
            initial_gas_cells++;
        }
    });
    println("Initial number of gas cells: " + to_string(initial_gas_cells));

    // Function to output the coordinates of every gas element
    auto output_gas_elements = [&](uint step) {
        std::ofstream outfile("gas_elements_" + std::to_string(step) + ".txt");
        outfile << std::fixed << std::setprecision(2); // Set precision to 2 decimal places
        std::mutex file_mutex; // Mutex to ensure thread-safe file writing

        const uint Nx = lbm.get_Nx(), Ny = lbm.get_Ny(), Nz = lbm.get_Nz();
        parallel_for(lbm.get_N(), [&](ulong n) {
            uint x = 0u, y = 0u, z = 0u;
            lbm.coordinates(n, x, y, z);
            if (lbm.flags[n] == TYPE_G) {
                std::lock_guard<std::mutex> lock(file_mutex); // Lock the mutex before writing
                outfile << x << " " << y << " " << z << "\\n";
            }
        });
        outfile.close();
    };

    // Output gas elements at t=0
    output_gas_elements(0);

    // Run the simulation and output gas elements at the last step
    const uint total_steps = 500u;
    for (uint step = 0; step < total_steps; step += 10) {
        lbm.run(10u);
        uint gas_cells = 0u;
        parallel_for(lbm.get_N(), [&](ulong n) {
            if (lbm.flags[n] == TYPE_G) {
                gas_cells++;
            }
        });
        println("Step: " + to_string(step) + ", Number of gas cells: " + to_string(gas_cells));
    }
    output_gas_elements(total_steps);

    // Final State Debugging
    uint final_gas_cells = 0u;
    parallel_for(lbm.get_N(), [&](ulong n) {
        if (lbm.flags[n] == TYPE_G) {
            final_gas_cells++;
        }
    });
    println("Final number of gas cells: " + to_string(final_gas_cells));
}

It is a model of a bubble of air rising in a column of water, I can get things to render (yay!) but when I try to capture the xyz coordinates of all the gas elements at different points in the model I am always left with the the initial spherical state. I've captured all the gas elements and plotted them in python and at every "state" in the model the gas elements always form a perfect sphere. I can see in the model the bubble distorting while it renders.

Any help or guidance would be greatly appreciated :3 I checked the examples and it seems like the lmb.coordinates should be updating but idk, is this not what I should expect?

Thanks for the great software regardless, this thing rocks!

ProjectPhysX commented 2 weeks ago

Hi @RandomInternetPreson,

you can use

lbm.flags.read_from_device();
float3 bubble_position = calculate_object_center_of_mass(TYPE_G);

to track th bubble position, with the FORCE_FIELD extension enabled.

But this setup won't work, for two reasons:

Kind regards, Moritz

RandomInternetPreson commented 2 weeks ago

Oh thank you for the informative response, much appreciated 😁