Skip to content
Snippets Groups Projects
Commit ce84829e authored by Armin Co's avatar Armin Co
Browse files

Refactoring.

Added CMake subdir. CMake creates a lib now.
Removed empty top line of doxygen comments.
Default build type is now Release (-O3 )
parent c4ec9859
No related branches found
No related tags found
No related merge requests found
# CMake file for the Q-Pong game.
## CMake file for the Q-Pong game.
##
project(QuantumPong)
cmake_minimum_required(VERSION 3.2)
project(run VERSION 1.0 LANGUAGES CXX)
## Use modern C++!
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_BUILD_TYPE Release)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTKMM gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
include_directories(src)
add_definitions(${GTKMM_INCLUDE_DIRS})
find_package(PkgConfig REQUIRED)
add_executable(run src/main.cpp src/ParticleImage.cpp src/ArrayCanvas.cpp src/Particle.cpp src/QuantumMath.cpp )
message("Build type is ${CMAKE_BUILD_TYPE}")
find_package (Threads)
add_subdirectory(
src
)
target_link_libraries (run ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(run ${GTKMM_LIBRARIES})
target_link_libraries(run m)
target_link_libraries(run fftw3 fftw3_omp)
......@@ -12,7 +12,7 @@ bool ArrayCanvas::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
// Clear background.
cr->save();
cr->set_source_rgba(0.0, 0.0, 0.0, 0.0);
cr->set_source_rgba(0.0, 0.0, 0.0, 1.0);
cr->paint();
// Print arrays.
......@@ -20,22 +20,50 @@ bool ArrayCanvas::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
for (unsigned x = 0; x < k_drawingAreaWidth; x++)
{
// Print local
QColor c;
c = m_bufLocalRepresentation->getValue(x, y);
double xi = x * imageScaleFactor;
double yi = y * imageScaleFactor;
// Print obstacles
// c = m_obstacles->getValue(x, y);
// cr->set_source_rgba(c.r, c.g, c.b, c.a);
// cr->rectangle(xi, yi, imageScaleFactor, imageScaleFactor);
// cr->fill();
// Print position
c = m_bufPositionRepresentation->getValue(x, y);
cr->set_source_rgba(c.r, c.g, c.b, c.a);
cr->rectangle(x*imageScaleFactor, y*imageScaleFactor, imageScaleFactor, imageScaleFactor);
cr->rectangle(xi, yi, imageScaleFactor, imageScaleFactor);
cr->fill();
// Print impulse
c = m_bufImpulseRepresentation->getValue(x, y);
// Print momentum
c = m_bufMomentumRepresentation->getValue(x, y);
cr->set_source_rgba(c.r, c.g, c.b, c.a);
cr->rectangle((x * imageScaleFactor+ k_drawingAreaWidth*imageScaleFactor), y * imageScaleFactor, imageScaleFactor, imageScaleFactor);
cr->rectangle((xi+ k_drawingAreaWidth*imageScaleFactor), yi, imageScaleFactor, imageScaleFactor);
cr->fill();
}
}
constexpr int crossSize = 10;
QColor c = {1.0, 0.9, 0.9, 0.2};
cr->set_source_rgba(c.r, c.g, c.b, c.a);
// draw horizontal half of cross
cr->move_to((nx* imageScaleFactor + nx* imageScaleFactor/2 - crossSize* imageScaleFactor/2), (nx* imageScaleFactor/2));
cr->line_to(nx* imageScaleFactor + nx* imageScaleFactor/2 + crossSize* imageScaleFactor/2, (ny* imageScaleFactor/2));
cr->stroke();
// draw certical half of cross
cr->move_to((nx* imageScaleFactor + nx* imageScaleFactor/2), (nx* imageScaleFactor/2 - crossSize* imageScaleFactor/2));
cr->line_to((nx* imageScaleFactor + nx* imageScaleFactor/2), (nx* imageScaleFactor/2 + crossSize* imageScaleFactor/2));
cr->stroke();
// draw seperator between position and momentum image
cr->move_to(nx*imageScaleFactor, 0);
cr->line_to(nx*imageScaleFactor, ny * imageScaleFactor);
cr->stroke();
cr->restore();
return true;
}
\ No newline at end of file
......@@ -16,7 +16,6 @@
#include "ParticleImage.hpp"
///
/// @brief Class ArrayCanvas. Draws two ParticleImages when triggered.
///
class ArrayCanvas : public Gtk::DrawingArea
......@@ -24,16 +23,14 @@ class ArrayCanvas : public Gtk::DrawingArea
public:
///
/// @brief Class ArrayCanvas drawing area for two ParticleImages.
///
ArrayCanvas(ParticleImage *momentum, ParticleImage *position) : m_bufImpulseRepresentation{momentum}, m_bufLocalRepresentation{position}
ArrayCanvas(ParticleImage *momentum, ParticleImage *position, ParticleImage *obstacles) : m_bufMomentumRepresentation{momentum}, m_bufPositionRepresentation{position}, m_obstacles{obstacles}
{
// Connect dispatcher
m_dispatcher.connect(sigc::mem_fun(*this, &ArrayCanvas::queueDraw));
}
///
/// @brief Trigger the redraw of this Canvas for example from another thread.
///
void triggerRedraw()
......@@ -43,25 +40,23 @@ public:
protected:
///
/// @brief Define the behaviour when on_draw is called.
///
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
///
/// @brief Bridge between threads to trigger the redraw of the canvas.
///
Glib::Dispatcher m_dispatcher;
///
/// @brief ParitcleImage copys from the simulation, which will be drawn to the screen.
///
ParticleImage *m_bufLocalRepresentation;
ParticleImage *m_bufImpulseRepresentation;
ParticleImage *m_bufPositionRepresentation;
ParticleImage *m_bufMomentumRepresentation;
ParticleImage *m_obstacles;
///
/// @brief Wraps function to trigger redraw.
/// This function cannot be called from another thread.
/// Therefore the call of this function will be triggered by the dispatcher.
......
## library for the app
add_library(qpong
QuantumMath.cpp
Particle.cpp
ParticleImage.cpp
ArrayCanvas.cpp
)
## create the application
add_executable(qpong.app
main.cpp
)
# we do need some threads
find_package(Threads)
## get all GTKMM dependencies and configuration
pkg_check_modules(GTKMM gtkmm-3.0)
include_directories(${GTKMM_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS})
## link all necessary libs to the target
target_link_libraries(qpong.app
qpong
${CMAKE_THREAD_LIBS_INIT}
${GTKMM_LIBRARIES}
fftw3
fftw3_omp
m # math
)
......@@ -8,64 +8,52 @@
#ifndef QPONG_CONFIGURATION_HPP
#define QPONG_CONFIGURATION_HPP
///
/// @brief Width of the drawing area in pixels.
///
constexpr unsigned long k_drawingAreaWidth = 300; // crashes at 418
constexpr unsigned imageScaleFactor = 4;
constexpr unsigned long k_drawingAreaWidth = 256; // crashes at 418
constexpr unsigned imageScaleFactor = 3;
///
/// @brief Height of the drawing area in pixels.
///
constexpr unsigned long k_drawingAreaHeight = k_drawingAreaWidth;
///
/// @brief Size of one time step.
///
constexpr double dt = 0.1;
constexpr double dt = 0.15;
///
/// @brief Start position on the x-Axis.
///
constexpr double k_x0 = 0.0;
///
/// @brief Start position on the y-Axis.
///
constexpr double k_y0 = 0.0;
constexpr double k_y0 = -0.5;
///
/// @brief Acceleration of gravity.
///
constexpr double g = 9.81;
///
/// @brief Mass of the particle.
///
constexpr double m = 1.0;
///
/// @brief Planck constant.
///
constexpr double hbar = 0.0001;
///
/// @brief Initial impulse in x direction.
/// @brief Initial momentum in x direction.
///
constexpr double k_px0 = 0.02;
///
/// @brief Initial impuls in y direction.
///
constexpr double k_py0 = 0.009;
///
/// @brief This constants scales the size of the impulse on initialisation.
/// @brief This constants scales the size of the momentum on initialisation.
///
constexpr double lambda = 80.0;
///
/// @brief Scale the max value at initialisation of the impulse
/// @brief Scale the max value at initialisation of the momentum
///
constexpr double A0 = 1.0;
......
......@@ -15,7 +15,7 @@
const Complex Ci(0.0, 1.0);
void Particle::initImpulse()
void Particle::initMomentum()
{
std::cout << "Initialising particle" << std::endl;
......@@ -32,7 +32,7 @@ void Particle::initImpulse()
}
}
Particle::Particle(ArrayCanvas &ac, ParticleImage *momentum, ParticleImage *position) : m_arrayCanvas{ac},m_bufImpulseRepresentation{momentum}, m_bufLocalRepresentation{position}
Particle::Particle(ArrayCanvas &ac, ParticleImage *momentum, ParticleImage *position, ParticleImage *obstacles) : m_arrayCanvas{ac},m_bufMomentumRepresentation{momentum}, m_bufPositionRepresentation{position}, m_obstacleImage{obstacles}
{
std::cout << "Creating particle" << std::endl;
fftw_init_threads();
......@@ -40,12 +40,12 @@ Particle::Particle(ArrayCanvas &ac, ParticleImage *momentum, ParticleImage *posi
constexpr int k_numThreads = 4;
fftw_plan_with_nthreads(k_numThreads);
m_psi = (Complex *)fftw_malloc(sizeof(fftw_complex) * n);
m_psi = static_cast<Complex *>(fftw_malloc(sizeof(fftw_complex) * n));
m_planForward = fftw_plan_dft_1d(n, (fftw_complex *)m_psi, (fftw_complex *)m_psi, FFTW_FORWARD, FFTW_MEASURE);
m_planBackward = fftw_plan_dft_1d(n, (fftw_complex *)m_psi, (fftw_complex *)m_psi, FFTW_BACKWARD, FFTW_MEASURE);
m_planForward = fftw_plan_dft_2d(ny, nx, (fftw_complex *)m_psi, (fftw_complex *)m_psi, FFTW_FORWARD, FFTW_MEASURE);
m_planBackward = fftw_plan_dft_2d(ny, nx, (fftw_complex *)m_psi, (fftw_complex *)m_psi, FFTW_BACKWARD, FFTW_MEASURE);
initImpulse();
initMomentum();
}
Particle::~Particle()
......@@ -61,22 +61,31 @@ void Particle::propagate()
for (unsigned long iy = 0; iy < ny; iy++)
{
double y = yAt(iy);
#pragma omp parallel for
for (unsigned long ix = 0; ix < nx; ix++)
{
constexpr double l = 0.0003; //lambda
constexpr double l = 0.0007; //lambda
double x = xAt(ix);
// double E = obstaclePotential(x, y);
double E = (square(x) * square(x) + square(y/2)) * l;
// double E = (square(x) + square(y)) * l;
int index = nx * iy + ix;
m_psi[index] *= exp(-Ci * dt / hbar * E);
// Complex tmp = m_psi[index] * exp(-Ci * dt / hbar * E);
// m_psi[index] = tmp;
// m_bufPositionRepresentation->updateBuffer(index, tmp + E*600*Ci);
m_bufPositionRepresentation->updateBuffer(index, m_psi[index]);
}
}
fftw_execute (m_planForward); // transform into impulse repr.
fftw_execute (m_planForward); // transform into momentum repr.
#pragma omp parallel for
for (unsigned long iy = 0; iy < ny; iy++)
{
double py = pyAt(iy);
#pragma omp parallel for
for (unsigned long ix = 0; ix < nx; ix++)
{
double px = pxAt(ix);
......@@ -86,17 +95,17 @@ void Particle::propagate()
m_psi[index] *= exp(-Ci * dt / hbar * E) * N;
}
}
updateImpulseImage(); //momentum
fftw_execute(m_planBackward); // transform into local repr.
updateLocalImage(); //position
updateMomentumImage(); //momentum
fftw_execute(m_planBackward); // transform into position repr.
// updatePositionImage(); //position
}
void Particle::updateImpulseImage()
void Particle::updateMomentumImage()
{
unsigned px = 0;
unsigned py = 0;
unsigned long impulse_index = 0;
unsigned long momentum_index = 0;
unsigned long array_index = 0;
#pragma omp parallel for
......@@ -105,31 +114,31 @@ void Particle::updateImpulseImage()
for (unsigned x = 0; x < nx; x++)
{
// if (y >= ny / 2)
// {
// px = y - ny / 2;
// }
// else
// {
// px = y + ny / 2;
// }
// if (x >= nx / 2)
// {
// py = x - nx / 2;
// }
// else
// {
// py = x + nx / 2;
// }
impulse_index = x * nx + y;
if (y >= ny / 2)
{
py = y - ny / 2;
}
else
{
py = y + ny / 2;
}
if (x >= nx / 2)
{
px = x - nx / 2;
}
else
{
px = x + nx / 2;
}
momentum_index = py * nx + px;
array_index = y * nx + x;
// impulse_index = array_index;
m_bufImpulseRepresentation->updateBuffer(array_index, (m_psi[impulse_index] * 142.42));
m_bufMomentumRepresentation->updateBuffer(array_index, (m_psi[momentum_index] * 142.42));
}
}
}
void Particle::updateLocalImage()
void Particle::updatePositionImage()
{
#pragma omp parallel for
......@@ -138,7 +147,7 @@ void Particle::updateLocalImage()
for (unsigned x = 0; x < nx; x++)
{
unsigned index = y * nx + x;
m_bufLocalRepresentation->updateBuffer(index, m_psi[index]);
m_bufPositionRepresentation->updateBuffer(index, m_psi[index]);
}
}
}
......@@ -21,15 +21,14 @@ class Particle
{
public:
Particle() = delete;
Particle(ArrayCanvas &ac, ParticleImage *momentum, ParticleImage *position);
Particle(ArrayCanvas &ac, ParticleImage *momentum, ParticleImage *position, ParticleImage *obstacles);
~Particle();
void propagate();
/// @brief Init the array with initial momentum.
/// Representation is in position representation.
///
/// @brief Init the array with initial impulse.
/// Representation is in local representation.
///
void initImpulse();
void initMomentum();
private:
Complex *m_psi;
ArrayCanvas &m_arrayCanvas;
......@@ -37,14 +36,14 @@ private:
fftw_plan m_planBackward;
ParticleImage *m_bufLocalRepresentation;
ParticleImage *m_bufImpulseRepresentation;
ParticleImage *m_bufPositionRepresentation;
ParticleImage *m_bufMomentumRepresentation;
ParticleImage *m_obstacleImage;
///
/// @brief Update the array at the ArrayCanvas
///
void updateImpulseImage();
void updateLocalImage();
void updateMomentumImage();
void updatePositionImage();
};
#endif
\ No newline at end of file
......@@ -9,19 +9,22 @@ constexpr unsigned maxBufferCount = 2;
void ParticleImage::updateBuffer(unsigned index, Complex v)
{
m_buffer[index] = v;
}
const QColor ParticleImage::getValue(const unsigned x, const unsigned y)
{
unsigned long index = y * nx + x;
constexpr double scale_factor = 1.0;
Complex val = m_buffer[index] * scale_factor;
constexpr double scale_factor = 0.9;
Complex val = m_buffer[index];
QColor c;
val *= scale_factor;
double r = real(val);
double i = imag(val);
QColor c;
c.r = square(r);
c.g = square(r) + square(i);
c.b = square(i);
return c;
}
\ No newline at end of file
......@@ -14,7 +14,6 @@
#include "QuantumMath.hpp"
///
/// @brief Convinient conatiner to store a RGBA value.
///
struct QColor
......@@ -22,11 +21,10 @@ struct QColor
float r = 0;
float g = 0;
float b = 0;
float a = 0.95;
float a = 1.0;
};
///
/// @brief Wraps an one dimensional array.
/// Values can be accessed as in 2D.
///
......@@ -34,7 +32,6 @@ class ParticleImage
{
public:
///
/// @return Get Color value from particle at position (x,y).
///
const QColor getValue(const unsigned x, const unsigned y);
......@@ -42,7 +39,6 @@ public:
void updateBuffer(unsigned index, Complex v);
private:
///
/// @brief Buffer for array with complex values from simulation.
///
std::array<Complex, n> m_buffer;
......
......@@ -7,6 +7,20 @@
#include "QuantumMath.hpp"
const double obstaclePotential(double x, double y)
{
double xPos = 0;
double yPos = 0;
constexpr double maxV = 1;
constexpr double l = 0.0007; //lambda
double E = (square(x) * square(x) + square(y/2)) * l;
return E;
}
const double xAt(int i)
{
return (i - (nx / 2)) * dx;
......
......@@ -35,14 +35,16 @@ constexpr int n = nx * ny;
const double dx = 2.0 / nx;
const double dy = 2.0 / ny;
/// @brief Potential of the obstachle that is controlled by the player.
///
/// @brief Get index to access array in local representation.
const double obstaclePotential(double x, double y);
/// @brief Get index to access array in position representation.
///
const double xAt(int i);
const double yAt(int iy);
///
/// @brief Get index to access array in impulse representation.
/// @brief Get index to access array in momentum representation.
///
const double pxAt(int ix);
......
......@@ -8,27 +8,19 @@
#include <chrono>
#include <thread>
#include <gtkmm/application.h>
#include <gtkmm/button.h>
#include <gtkmm/window.h>
#include <gtkmm/box.h>
#include <gtkmm.h>
#include "ArrayCanvas.hpp"
#include "Particle.hpp"
#include "Configuration.hpp"
ParticleImage *momentum;
ParticleImage *position;
bool propagating = true;
///
/// @brief This functino has to run in its own thread and propagates the particle as fast as possible.
///
void simulation(Particle *p)
{
//Particle *p = new Particle(ac, momentum, position);
do
{
p->propagate();
......@@ -36,40 +28,56 @@ void simulation(Particle *p)
while (propagating);
}
///
/// @brief This function has to run in its own thread an will redraw the canvas every ~25ms.
///
void render(ArrayCanvas &ac)
void render(ArrayCanvas *ac)
{
do
{
using namespace std::chrono_literals;
std::this_thread::sleep_for(25ms);
ac.triggerRedraw();
std::this_thread::sleep_for(5ms);
ac->triggerRedraw();
} while (true);
}
class QWindow : public Gtk::Window
{
public:
QWindow(ArrayCanvas &ac) : m_button{"Initialise Particle"}, m_ac{ac}
QWindow() : m_button{"Initialise Particle"}
{
m_particle = new Particle(m_ac, momentum, position);
m_momentum = new ParticleImage;
m_position = new ParticleImage;
m_obstacles = new ParticleImage;
m_ac = new ArrayCanvas(m_momentum, m_position, m_obstacles);
m_particle = new Particle(*m_ac, m_momentum, m_position, m_obstacles);
set_border_width(10);
m_button.signal_clicked().connect(sigc::mem_fun(*this, &QWindow::on_button_clicked));
add(m_box);
m_box.pack_start(m_button, Gtk::PACK_SHRINK);
m_box.pack_start(m_ac);
ac.show();
m_box.pack_start(m_vBox);
m_vBox.pack_start(m_button, Gtk::PACK_SHRINK);
m_vBox.pack_start(m_label, Gtk::PACK_SHRINK);
m_vBox.pack_start(*m_ac);
m_label.set_margin_top(5);
m_label.set_margin_bottom(5);
m_ac->show();
m_button.show();
m_box.show();
m_vBox.show();
m_label.show();
m_label.set_text("Hi, you are playing QPong and this is a label!");
m_propagatingThread = std::thread(simulation, m_particle);
m_propagatingThread.detach();
std::cout << "Starting to draw images" << std::endl;
std::thread rendering(render,m_ac);
rendering.detach();
}
virtual ~QWindow(){}
......@@ -80,7 +88,7 @@ protected:
{
propagating = false;
std::this_thread::sleep_for((std::chrono::seconds)1);
m_particle->initImpulse();
m_particle->initMomentum();
m_propagatingThread = std::thread(simulation, m_particle);
propagating = true;
m_propagatingThread.detach();
......@@ -88,40 +96,30 @@ protected:
// Member widgets:
Gtk::Box m_box;
Gtk::VBox m_vBox;
Gtk::Label m_label;
Gtk::Button m_button;
ArrayCanvas &m_ac;
ArrayCanvas *m_ac;
// qpong
Particle *m_particle;
std::thread m_propagatingThread;
ParticleImage *m_momentum;
ParticleImage *m_position;
ParticleImage *m_obstacles;
};
///
/// @brief MAIN
///
int main(int argc, char* argv[])
{
std::cout << "Starting QPong" << std::endl;
// App and window
auto app = Gtk::Application::create(argc, argv, "de.armin-co.qpong");
// canvas
momentum = new ParticleImage;
position = new ParticleImage;
std::cout << "Creating canvas" << std::endl;
ArrayCanvas ac{momentum, position};
std::cout << "Creating window" << std::endl;
QWindow window(ac);
window.set_default_size(k_drawingAreaWidth*imageScaleFactor*2+100, k_drawingAreaWidth*imageScaleFactor);
std::cout << "Starting to draw images" << std::endl;
std::thread rendering(render, std::ref(ac));
rendering.detach();
QWindow window;
window.set_default_size(k_drawingAreaWidth*imageScaleFactor*2+130, k_drawingAreaWidth*imageScaleFactor+100);
// show and run
ac.show();
return app->run(window);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment