【问题标题】:Weird pattern of Heat Equation Simulation on 2D Canvas二维画布上热方程模拟的奇怪模式
【发布时间】:2023-01-10 10:20:15
【问题描述】:

我正在 2D Canvas 上玩热方程式,带有甜甜圈形式的额外热源。结果我在这个甜甜圈周围得到了一些“酸性”图案。

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();

尝试了不同的方法,比如玩 hsl 颜色、初始参数,但肯定缺少一些东西。

我还注意到,在调试过程中,某些值似乎爆炸了,我认为这是问题的根源,但找不到它的根源,我试图找到更多关于微分方程的这种行为及其原因的信息这可能会发生,但无法将其应用于源代码。

【问题讨论】:

    标签: javascript canvas differential-equations


    【解决方案1】:

    在计算过程中,网格中的值可以超过 100,从而使公式 ((100 - grid[i][j]) / 100) * 240; 产生负值

    最简单的修复方法是限制值:

    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();
    &lt;canvas width="500" height="500" id="canvas"&gt;&lt;/canvas&gt;

    【讨论】:

    • 有趣的是,我在试错期间实际上使用了 Math.min,但也许我漏掉了一些逗号或其他东西,并认为它仍然无法正常工作。十分感谢! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 2013-12-27
    • 2015-09-21
    • 1970-01-01
    • 2021-05-27
    相关资源
    最近更新 更多