func (fs *Solver) swapV() {
	tmp := fs.v
	fs.v = fs.vOld
	fs.vOld = tmp
}
swapU swaps velocity y reference.
package fluid
import (
	"math"
)
type cell []float64
type solver struct {
	nx          int
	ny          int
	dt          float64
	diffusion   float64
	viscosity   float64
	iterations  int
	doVorticity bool
	doBuoyancy  bool
	numOfCells  int
	u cell
	v cell
	d cell
	uOld cell
	vOld cell
	dOld cell
	curlData cell
}
type BoundaryType int
const (
	BoundaryNone BoundaryType = iota
	BoundaryLeftRight
	BoundaryTopBottom
)
type Solver solver
func NewSolver(n int) *Solver {
	fs := &Solver{
		nx:          n,
		ny:          n,
		dt:          0.2,
		diffusion:   0.0001,
		viscosity:   0.0,
		iterations:  10,
		doVorticity: true,
		doBuoyancy:  true,
	}
	fs.numOfCells = (n + 2) * (n + 2)
	fs.u = make(cell, fs.numOfCells)
	fs.v = make(cell, fs.numOfCells)
	fs.d = make(cell, fs.numOfCells)
	fs.uOld = make(cell, fs.numOfCells)
	fs.vOld = make(cell, fs.numOfCells)
	fs.dOld = make(cell, fs.numOfCells)
	fs.curlData = make(cell, fs.numOfCells)
	return fs
}
func (fs *Solver) SetCell(cellType interface{}, x, y int, val float64) {
	switch cellType {
	case "u":
		fs.u[fs.idx(x, y)] = val
	case "v":
		fs.v[fs.idx(x, y)] = val
	case "d":
		fs.d[fs.idx(x, y)] = val
	case "uOld":
		fs.uOld[fs.idx(x, y)] = val
	case "vOld":
		fs.vOld[fs.idx(x, y)] = val
	case "dOld":
		fs.dOld[fs.idx(x, y)] = val
	}
}
func (fs *Solver) GetCell(cellType interface{}, x, y int) (result float64) {
	switch cellType {
	case "u":
		result = fs.u[fs.idx(x, y)]
	case "v":
		result = fs.v[fs.idx(x, y)]
	case "d":
		result = fs.d[fs.idx(x, y)]
	case "uOld":
		result = fs.uOld[fs.idx(x, y)]
	case "vOld":
		result = fs.vOld[fs.idx(x, y)]
	case "dOld":
		result = fs.dOld[fs.idx(x, y)]
	}
	return
}
func (fs *Solver) DensityStep() {
	fs.addSource(fs.d, fs.dOld)
	fs.swapD()
	fs.diffuse(BoundaryNone, fs.d, fs.dOld, fs.diffusion)
	fs.swapD()
	fs.advect(BoundaryNone, fs.d, fs.dOld, fs.u, fs.v)
	for i := 0; i < fs.numOfCells; i++ {
		fs.dOld[i] = 0
	}
}
func (fs *Solver) VelocityStep() {
	fs.addSource(fs.u, fs.uOld)
	fs.addSource(fs.v, fs.vOld)
	if fs.doVorticity {
		fs.calcVorticityConfinement(fs.uOld, fs.vOld)
		fs.addSource(fs.u, fs.uOld)
		fs.addSource(fs.v, fs.vOld)
	}
	if fs.doBuoyancy {
		fs.buoyancy(fs.vOld)
		fs.addSource(fs.v, fs.vOld)
	}
	fs.swapU()
	fs.diffuse(BoundaryLeftRight, fs.u, fs.uOld, fs.viscosity)
	fs.swapV()
	fs.diffuse(BoundaryTopBottom, fs.v, fs.vOld, fs.viscosity)
	fs.project(fs.u, fs.v, fs.uOld, fs.vOld)
	fs.swapU()
	fs.swapV()
	fs.advect(BoundaryLeftRight, fs.u, fs.uOld, fs.uOld, fs.vOld)
	fs.advect(BoundaryTopBottom, fs.v, fs.vOld, fs.uOld, fs.vOld)
	fs.project(fs.u, fs.v, fs.uOld, fs.vOld)
	for i := 0; i < fs.numOfCells; i++ {
		fs.uOld[i] = 0
		fs.vOld[i] = 0
	}
}
func (fs *Solver) ResetDensity() {
	for i := 0; i < fs.numOfCells; i++ {
		fs.d[i] = 0
	}
}
func (fs *Solver) ResetVelocity() {
	for i := 0; i < fs.numOfCells; i++ {
		fs.v[i] = 0.001
		fs.u[i] = 0.001
	}
}
func (fs *Solver) swapU() {
	tmp := fs.u
	fs.u = fs.uOld
	fs.uOld = tmp
}