Basic heat and wave equation solver for node and the browser
A simple and surprisingly easy to use partial-differential equation solver of the heat/diffusion equation and wave equation. The goal of this project was for driving visualizations not for performing exacting scientific analysis. The forward Euler step is employed for simplicity and speed, as well as further simplifying the discrete equations with the convolution operator.
It solves the pde on an
mxn grid with
n being set by the
setResolution method. Each call to
update increases the solution by a time step given by
dt. Depending on what the spatial step
dx is set at is how fast the solution will converge - remember
v = x/t from highschool.
update outputs a single column vector that must be indexed by
f[i*n + j] where
0 < i < m and
0 < j < n. The reason
pde-engine outputs a 2D array strung out as a 1D vector is for computational speed.
Version 0.2.0 uses Typed Arrays for computational efficiency / speed.
var engine = require'pde-engine'aprint = require'printarray'field = enginedt: 0.1gamma: 0.02eqn: "wave" // put "diffusion" here to solve the heat eqn.var dims =x: 12y: 12/** This sets up the dimensions of the field.* Everytime setResolution is called the field* arrays are reset (new Typed Arrays of given size* are created.)*/fieldsetResolutiondimsx dimsyvar src =x: 3y: 5mag: 1/** You can add sources before you begin the timesteps (updates)* or during. Note if you begin updating field (progressing in time)* before adding a source the field will have no energy and will not* evolve (the 2D diffusion of zero is zero).*/fieldaddSourcesrcx srcy srcmag/** Run the wave eqn solver.* Do something cool with the* coefficients: plot with html5 canvas* or gnuplot or whatever, or turn it into* animations within a website or video game.*/var steps = 5var tic = setIntervalvar coeffs = fieldupdate//// Render coeffs//aprintcoeffs 5 dimsx dimsyconsole.logsteps--if steps === 0clearIntervaltic1000
addSource method specifies the location of the source at that particular timestep with magnitude
mag. Right now it emplaces a hard-coded Gaussian source centred at
(row, col), with boundary cases already implemented. Every time field.update
The following are possible configuration options. If configs are omitted defaults will be used. The defaults are given after the
dt = specdt || 0.1 // time stepdx = specdx || 1 // spatial stepgamma = specgamma || 0.02 // wave or diffusion paramater (controls decay)vel = specvel || 2 // wave velocityeqn = speceqn || 'wave' // or "diffusion"
Note that the forward Euler approach suffers from poor stability. It is a good idea to keep dt < dx , probably by a factor of 0.5. If your solutions are not converging (things go crazy) try modifying these variables.
npm install pde-engine
then write some code with
engine = require('pde-engine') in it. If you want it in the browser do a
browserify mycode.js -o bundle.js
to include it. See benpostlethwaite.ca for a working example.
This is an early but fully working physics engine. Future releases may optimize algorithms or add new methods/configs, but this basic API should remain stable.
Tests will be coming soon. For now this is primarily a tool for graphics.