Home > Software engineering >  Weird pattern of Heat Equation Simulation on 2D Canvas
Weird pattern of Heat Equation Simulation on 2D Canvas

Time:01-10

I'm playing with a Heat Equation on 2D Canvas with additional heat source in a form of a donut. The result I got some "acidic" pattern around this donut.

const width = 200; // width of the grid
const height = 200; // height of the grid
const dt = 0.25; // time step
const dx = 1; // space step in the x-direction
const dy = 1; // space step in the y-direction
const alpha = 0.25; // thermal diffusivity


const Q = [];
// Heat of the heat source
const Q0 = 80;

const r1 = 8;
const r2 = 12;

for (let i = 0; i < width - 1; i  ) {
    Q[i] = [];
    for (let j = 0; j < height - 1; j  ) {
        // Calculate the distance from the center of the region
        const r = Math.sqrt((i - width / 2) ** 2   (j - height / 2) ** 2);

        Q[i][j] = (r1 < r && r < r2) ? Q0 : 0;
    }
}

let grid = []; // array to store the grid

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// Initialize the grid with random temperatures
for (let i = 0; i < width; i  ) {
    grid[i] = [];
    for (let j = 0; j < height; j  ) {
        grid[i][j] = 50
    }
}

function updateGrid() {
// Update the temperature of each cell based on the heat equation
    for (let i = 1; i < width - 1; i  ) {
            for (let j = 1; j < height - 1; j  ) {
                const d2Tdx2 = (grid[i   1][j] - 2 * grid[i][j]   grid[i - 1][j]) / (dx ** 2);
                const d2Tdy2 = (grid[i][j   1] - 2 * grid[i][j]   grid[i][j - 1]) / (dy ** 2);

                grid[i][j] = grid[i][j]   alpha * dt * (d2Tdx2   d2Tdy2)   (Q[i][j] * dt);
            }
    }
}

// This function is called repeatedly to update the grid and render it
function main() {
    updateGrid();
    renderGrid();
    requestAnimationFrame(main);
}

// This function render the grid
function renderGrid() {

    // Clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Iterate over the grid and draw each cell
    for (let i = 0; i < width; i  ) {
        for (let j = 0; j < height; j  ) {
            let hue = ((100 - grid[i][j]) / 100) * 240;
            //ctx.fillStyle = `rgb(${temp}, ${temp}, ${temp})`;
            ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
            ctx.fillRect(i * dx, j * dy, dx, dy);
        }
    }
}

// Start the simulation
main();

Tried different approaches, like playing with hsl colors, initial parameters but something definitely missing there.

What I aslo noticed is that during debuging, some values seems to be blowing up and I think that's the root of the problem but can't find the source of it, I have tried to found more information about this behaviour of differential equiations and why this can happen but couldn't apply it to the source code.

CodePudding user response:

during calculation values in grid can go over 100, thus making formula ((100 - grid[i][j]) / 100) * 240; produce negative values

the simples way to fix is to limit values:

grid[i][j] = Math.min(100, grid[i][j]   alpha * dt * (d2Tdx2   d2Tdy2)   (Q[i][j] * dt));

       

const width = 200; // width of the grid
const height = 200; // height of the grid
const dt = 0.25; // time step
const dx = 1; // space step in the x-direction
const dy = 1; // space step in the y-direction
const alpha = 0.25; // thermal diffusivity


const Q = [];
// Heat of the heat source
const Q0 = 80;

const r1 = 8;
const r2 = 12;

for (let i = 0; i < width - 1; i  ) {
    Q[i] = [];
    for (let j = 0; j < height - 1; j  ) {
        // Calculate the distance from the center of the region
        const r = Math.sqrt((i - width / 2) ** 2   (j - height / 2) ** 2);

        Q[i][j] = (r1 < r && r < r2) ? Q0 : 0;
    }
}

let grid = []; // array to store the grid

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// Initialize the grid with random temperatures
for (let i = 0; i < width; i  ) {
    grid[i] = [];
    for (let j = 0; j < height; j  ) {
        grid[i][j] = 50
    }
}

function updateGrid() {
// Update the temperature of each cell based on the heat equation
        for (let i = 1; i < width - 1; i  ) {
    for (let j = 1; j < height - 1; j  ) {
                const d2Tdx2 = (grid[i   1][j] - 2 * grid[i][j]   grid[i - 1][j]) / (dx ** 2);
                const d2Tdy2 = (grid[i][j   1] - 2 * grid[i][j]   grid[i][j - 1]) / (dy ** 2);

                grid[i][j] = Math.min(100, grid[i][j]   alpha * dt * (d2Tdx2   d2Tdy2)   (Q[i][j] * dt));
            }
    }
}

// This function is called repeatedly to update the grid and render it
function main() {
    updateGrid();
    renderGrid();
    requestAnimationFrame(main);
}

// This function render the grid
function renderGrid() {

    // Clear the canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Iterate over the grid and draw each cell
        for (let i = 0; i < width; i  ) {
    for (let j = 0; j < height; j  ) {
            let hue = (100 - grid[i][j]) / 100 * 240;
            //ctx.fillStyle = `rgb(${temp}, ${temp}, ${temp})`;
            ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
            ctx.fillRect(i * dx, j * dy, dx, dy);
        }
    }
}

// Start the simulation
main();
<canvas width="500" height="500" id="canvas"></canvas>

  • Related