PdeFiniteDifferenceSolver

C++/CUDA implementation of the most popular hyperbolic and parabolic PDE solvers


Project maintained by pmontalb Hosted on GitHub Pages — Theme by mattgraham

PdeFiniteDifferenceSolver

C++ manager class for PdeFiniteDifferenceKernels API. The low level calls are managed in the namespace pde::detail DeviceManager, whereas the high level infrastructure is delegated to the particular solver type.

Only linear hyperbolic and parabolic PDEs are supported (up to 3D). The exposed implementation is through:

These solvers are implemented with the Curiously Recurring Template Pattern (CRTP), useful for delegating the members data type at compile time.

For convenience’s sake the following typedefs have been defined:

Sample usage - 1D

Advection-Diffusion

	cl::vec grid = cl::LinSpace(0.0f, 1.0f, 128);
	auto _grid = grid.Get();

	std::vector<float> _initialCondition(grid.size());
	for (unsigned i = 0; i < _initialCondition.size(); ++i)
		_initialCondition[i] = sin(_grid[i]);

	cl::vec initialCondition(_initialCondition);

	unsigned steps = 100;
	double dt = 1e-4;
	float velocity = .05f;
	float diffusion = 0.1f;
	
	BoundaryCondition leftBoundaryCondition(BoundaryConditionType::Neumann, 0.0);
	BoundaryCondition rightBoundaryCondition(BoundaryConditionType::Neumann, 0.0);
	BoundaryCondition1D boundaryConditions(leftBoundaryCondition, rightBoundaryCondition);

	pde::GpuSinglePdeInputData1D data(initialCondition, grid, velocity, diffusion, dt, solverType, SpaceDiscretizerType::Centered, boundaryConditions);
	pde::ad1D solver(data);

	solver.Advance(steps);
	const auto solution = solver.solution->columns[0]->Get();

Wave Equation

	cl::dvec grid = cl::LinSpace<MemorySpace::Device, MathDomain::Double>(0.0, 1.0, 128);
	auto _grid = grid.Get();

	std::vector<double> _initialCondition(grid.size());
	for (unsigned i = 0; i < _initialCondition.size(); ++i)
		_initialCondition[i] = sin(_grid[i]);

	cl::dvec initialCondition(_initialCondition);

	unsigned steps = 100;
	double dt = 1e-4;
	double velocity = .05;
	
	BoundaryCondition leftBoundaryCondition(BoundaryConditionType::Neumann, 0.0);
	BoundaryCondition rightBoundaryCondition(BoundaryConditionType::Neumann, 0.0);
	BoundaryCondition1D boundaryConditions(leftBoundaryCondition, rightBoundaryCondition);

	pde::GpuDoublePdeInputData1D data(initialCondition, grid, velocity, diffusion, dt, solverType, SpaceDiscretizerType::Centered, boundaryConditions);
	pde::dwave1D solver(data);

	solver.Advance(steps);
	const auto solution = solver.solution->columns[0]->Get();

Sample results - 1D

I wrote a simple python script for plotting the results:

Hyperbolic - first order: transport equation

Parabolic: heat equation, advection-diffusion equation

Hyperbolic - second order: wave equation

Sample usage - 2D

Advection-Diffusion

	cl::dvec xGrid = cl::LinSpace<MemorySpace::Device, MathDomain::Double>(0.0f, 1.0f, 32u);
	cl::dvec yGrid = cl::LinSpace<MemorySpace::Device, MathDomain::Double>(0.0f, 1.0f, 32u);
	double dt = 1e-5;
	double xVelocity = .02;
	double yVelocity = .05;
	double diffusion = 1.0;

	auto _xGrid = xGrid.Get();
	auto _yGrid = yGrid.Get();
	std::vector<double> _initialCondition(xGrid.size() * yGrid.size());
	for (unsigned j = 0; j < _yGrid.size(); ++j)
	    for (unsigned i = 0; i < _xGrid.size(); ++i)
		_initialCondition[i + _xGrid.size() * j] = exp(-_xGrid[i] * _xGrid[i] - _yGrid[i] * _yGrid[i]);

	cl::dmat initialCondition(_initialCondition, xGrid.size(), yGrid.size());

	pde::GpuDoublePdeInputData2D data(initialCondition, xGrid, yGrid, xVelocity, yVelocity, diffusion, dt, solverType, SpaceDiscretizerType::Centered, boundaryConditions);
	pde::dad2D solver(data);
	const auto solution = solver.solution->columns[0]->Get();

Wave Equation

	cl::dvec xGrid = cl::LinSpace<MemorySpace::Device, MathDomain::Double>(0.0f, 1.0f, 32u);
	cl::dvec yGrid = cl::LinSpace<MemorySpace::Device, MathDomain::Double>(0.0f, 1.0f, 32u);
	double dt = 1e-5;
	double xVelocity = .02;

	auto _xGrid = xGrid.Get();
	auto _yGrid = yGrid.Get();
	std::vector<double> _initialCondition(xGrid.size() * yGrid.size());
	for (unsigned j = 0; j < _yGrid.size(); ++j)
	    for (unsigned i = 0; i < _xGrid.size(); ++i)
		_initialCondition[i + _xGrid.size() * j] = exp(-_xGrid[i] * _xGrid[i] - _yGrid[i] * _yGrid[i]);

	cl::dmat initialCondition(_initialCondition, xGrid.size(), yGrid.size());

	pde::GpuDoublePdeInputData2D data(initialCondition, xGrid, yGrid, xVelocity, 0.0, 0.0, dt, solverType, SpaceDiscretizerType::Centered, boundaryConditions);
	pde::dwave2D solver(data);
	const auto solution = solver.solution->columns[0]->Get();

Sample results - 2D

Hyperbolic - first order: transport equation

Parabolic: heat equation, advection-diffusion equation

Hyperbolic - second order: wave equation