Merge branch 'hannes-philipp' of git.gfz-potsdam.de:naaice/tug into hannes-philipp
32
.readthedocs.yaml
Normal file
@ -0,0 +1,32 @@
|
||||
# .readthedocs.yaml
|
||||
# Read the Docs configuration file
|
||||
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||
|
||||
# Required
|
||||
version: 2
|
||||
|
||||
# Set the OS, Python version and other tools you might need
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
tools:
|
||||
python: "3.11"
|
||||
# You can also specify other tool versions:
|
||||
# nodejs: "19"
|
||||
# rust: "1.64"
|
||||
# golang: "1.19"
|
||||
|
||||
# Build documentation in the "docs/" directory with Sphinx
|
||||
sphinx:
|
||||
configuration: docs_sphinx/conf.py
|
||||
|
||||
# Optionally build your docs in additional formats such as PDF and ePub
|
||||
formats:
|
||||
- pdf
|
||||
# - epub
|
||||
|
||||
# Optional but recommended, declare the Python requirements required
|
||||
# to build your documentation
|
||||
# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
|
||||
python:
|
||||
install:
|
||||
- requirements: docs_sphinx/requirements.txt
|
||||
4
docs_sphinx/Boundary.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Boundary
|
||||
========
|
||||
|
||||
.. doxygenclass:: Boundary
|
||||
2771
docs_sphinx/Doxyfile.in
Normal file
4
docs_sphinx/Grid.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Grid
|
||||
====
|
||||
|
||||
.. doxygenclass:: Grid
|
||||
20
docs_sphinx/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
4
docs_sphinx/Simulation.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Simulation
|
||||
==========
|
||||
|
||||
.. doxygenclass:: Simulation
|
||||
4
docs_sphinx/_build/html/_images/activity_diagram_run.svg
Normal file
|
After Width: | Height: | Size: 15 KiB |
4
docs_sphinx/_build/html/_images/class_diagram.svg
Normal file
|
After Width: | Height: | Size: 23 KiB |
224
docs_sphinx/_build/vis.html
Normal file
@ -0,0 +1,224 @@
|
||||
<!DOCTYPE html>
|
||||
<div id="container"></div>
|
||||
|
||||
|
||||
<form>
|
||||
<label for="c_file">Select an output file: </label>
|
||||
<input type="file" id="c_file" name="c_file" accept="text/csv" />
|
||||
</form>
|
||||
|
||||
|
||||
<script type="module">
|
||||
|
||||
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
|
||||
|
||||
// Declare the chart dimensions and margins.
|
||||
const width = 600;
|
||||
const height = 600;
|
||||
const svgMargin = { top: 50, right: 50, bottom: 50, left: 50 };
|
||||
|
||||
var gridWidth = width - svgMargin.left - svgMargin.right;
|
||||
var gridHeight = height - svgMargin.top - svgMargin.bottom;
|
||||
const gap = 1;
|
||||
var state = 0;
|
||||
var numIterations = 0;
|
||||
var cellXcount = 0;
|
||||
var cellYcount = 0;
|
||||
var concentrations = [];
|
||||
|
||||
// Create the outer SVG container.
|
||||
const svg = d3.create("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
svg.append("rect")
|
||||
.attr("x", 0)
|
||||
.attr("y", 0)
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.attr("fill-opacity", 0)
|
||||
.attr("stroke-width", 4)
|
||||
.attr("stroke", "black");
|
||||
|
||||
var grid = svg.append("g")
|
||||
.attr("class", "grid")
|
||||
.attr("transform", `translate(${svgMargin.left}, ${svgMargin.top})`);
|
||||
|
||||
// color scale
|
||||
var colorScale = d3.scaleLinear()
|
||||
.range(["#d0d0ec", "#7f0000"])
|
||||
.domain([1, 2000]);
|
||||
function getColor(c, max) {
|
||||
if (c == -1) {
|
||||
return "#000000";
|
||||
}
|
||||
|
||||
colorScale.domain([0, max]);
|
||||
return colorScale(c);
|
||||
}
|
||||
|
||||
function calcMaxConcentrationInIteration(state) {
|
||||
var maxRow = concentrations[state].map(function(row){ return Math.max.apply(Math, row); });
|
||||
var maxC = Math.max.apply(null, maxRow);
|
||||
return maxC;
|
||||
}
|
||||
|
||||
// Load data from file
|
||||
async function createVisualFromFile(csv_input) {
|
||||
// console.log(csv_input);
|
||||
// var data = await d3.text(csv_input).then(function(csv){
|
||||
// return d3.dsvFormat(" ").parseRows(csv);
|
||||
// })
|
||||
var data = d3.dsvFormat(" ").parseRows(csv_input);
|
||||
// console.log(data);
|
||||
var leftBoundary = data[0];
|
||||
var rightBoundary = data[1];
|
||||
var topBoundary = data[2];
|
||||
var bottomBoundary = data[3];
|
||||
cellXcount = topBoundary.length;
|
||||
cellYcount = leftBoundary.length;
|
||||
concentrations = []; // reset concentrations
|
||||
grid.selectAll("rect").remove();
|
||||
svg.selectAll("rect").remove();
|
||||
state = 0;
|
||||
console.log(topBoundary);
|
||||
|
||||
var cellWidth = gridWidth / cellXcount;
|
||||
var cellHeight = gridHeight / cellYcount;
|
||||
var iteration = [];
|
||||
numIterations = (data.length - 6) / (cellYcount + 2);
|
||||
console.log(numIterations);
|
||||
for (let i = 0; i < numIterations; i++) {
|
||||
iteration = [];
|
||||
for (let j = 0; j < cellYcount; j++) {
|
||||
iteration.push(data[i * (cellYcount + 2) + 6 + j])
|
||||
}
|
||||
concentrations.push(iteration);
|
||||
}
|
||||
console.log(concentrations);
|
||||
|
||||
var maxC = calcMaxConcentrationInIteration(state);
|
||||
// Create grid
|
||||
for (let i = 0; i < cellYcount; i++) {
|
||||
for (let j = 0; j < cellXcount; j++) {
|
||||
grid.append("rect")
|
||||
.attr("x", i * cellWidth + gap/2)
|
||||
.attr("y", j * cellHeight + gap/2)
|
||||
.attr("width", cellWidth - gap)
|
||||
.attr("height", cellHeight - gap)
|
||||
.attr("fill", getColor(concentrations[state][i][j], maxC));
|
||||
}
|
||||
}
|
||||
|
||||
// Create Boundaries
|
||||
// left and right
|
||||
for (let j = 0; j < cellYcount; j++) {
|
||||
svg.append("rect")
|
||||
.attr("x", svgMargin.left - 10)
|
||||
.attr("y", svgMargin.top + j * cellHeight + gap/2)
|
||||
.attr("width", 7)
|
||||
.attr("height", cellHeight - gap)
|
||||
.attr("fill", getColor(leftBoundary[j], maxC));
|
||||
svg.append("rect")
|
||||
.attr("x", width - svgMargin.right + 3)
|
||||
.attr("y", svgMargin.top + j * cellHeight + gap/2)
|
||||
.attr("width", 7)
|
||||
.attr("height", cellHeight - gap)
|
||||
.attr("fill", getColor(rightBoundary[j], maxC));
|
||||
}
|
||||
|
||||
// top and bottom
|
||||
for (let i = 0; i < cellXcount; i++) {
|
||||
svg.append("rect")
|
||||
.attr("x", svgMargin.left + i * cellWidth + gap/2)
|
||||
.attr("y", svgMargin.top - 10)
|
||||
.attr("width", cellWidth - gap)
|
||||
.attr("height", 7)
|
||||
.attr("fill", getColor(topBoundary[i], maxC));
|
||||
svg.append("rect")
|
||||
.attr("x", svgMargin.left + i * cellWidth + gap/2)
|
||||
.attr("y", height - svgMargin.bottom + 3)
|
||||
.attr("width", cellWidth - gap)
|
||||
.attr("height", 7)
|
||||
.attr("fill", getColor(bottomBoundary[i], maxC));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateGrid(new_state) {
|
||||
var maxC = calcMaxConcentrationInIteration(new_state);
|
||||
console.log(maxC);
|
||||
grid.selectAll("rect")
|
||||
.attr("fill", function (d,i) {
|
||||
var row = Math.floor(i/20);
|
||||
var col = i%20;
|
||||
return getColor(concentrations[new_state][row][col], maxC);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// key events for changing grid iteration state
|
||||
addEventListener("keydown", (event) => {
|
||||
if (event.isComposing || event.keyCode === 81) {
|
||||
if (state > 0) {
|
||||
state -= 1;
|
||||
updateGrid(state);
|
||||
}
|
||||
}
|
||||
if (event.isComposing || event.keyCode === 69) {
|
||||
if (state < numIterations-1) {
|
||||
state += 1;
|
||||
updateGrid(state);
|
||||
}
|
||||
}
|
||||
if (event.isComposing || event.keyCode === 65) {
|
||||
if (state > 9) {
|
||||
state -= 10;
|
||||
} else {
|
||||
state = 0;
|
||||
}
|
||||
updateGrid(state);
|
||||
}
|
||||
if (event.isComposing || event.keyCode === 68) {
|
||||
if (state < numIterations-10) {
|
||||
state += 10;
|
||||
} else {
|
||||
state = numIterations-1;
|
||||
}
|
||||
updateGrid(state);
|
||||
}
|
||||
});
|
||||
|
||||
async function logFile() {
|
||||
var file = document.getElementById("c_file").files[0];
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file);
|
||||
console.log(reader.result);
|
||||
}
|
||||
|
||||
function reader(file, callback) {
|
||||
const fr = new FileReader();
|
||||
fr.onload = () => callback(null, fr.result);
|
||||
fr.onerror = (err) => callback(err);
|
||||
fr.readAsText(file);
|
||||
}
|
||||
|
||||
|
||||
// document.getElementById("c_file").addEventListener("change", logFile);
|
||||
document.getElementById("c_file").addEventListener("change", (evt) => {
|
||||
// No files, do nothing.
|
||||
if (!evt.target.files) {
|
||||
return;
|
||||
}
|
||||
reader(evt.target.files[0], (err, res) => {
|
||||
console.log(res); // Base64 `data:image/...` String result.
|
||||
createVisualFromFile(res);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Append the SVG element.
|
||||
container.append(svg.node());
|
||||
|
||||
</script>
|
||||
97
docs_sphinx/conf.py
Normal file
@ -0,0 +1,97 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
import subprocess, os
|
||||
|
||||
# Doxygen
|
||||
subprocess.call('doxygen Doxyfile.in', shell=True)
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'TUG'
|
||||
copyright = 'MIT'
|
||||
author = 'Philipp Ungrund, Hannes Signer'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.autosectionlabel',
|
||||
'sphinx.ext.todo',
|
||||
'sphinx.ext.coverage',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.ifconfig',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.inheritance_diagram',
|
||||
'breathe'
|
||||
]
|
||||
|
||||
html_baseurl = "/index.html"
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
highlight_language = 'c++'
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_options = {
|
||||
'canonical_url': '',
|
||||
'analytics_id': '', # Provided by Google in your dashboard
|
||||
'display_version': True,
|
||||
'prev_next_buttons_location': 'bottom',
|
||||
'style_external_links': False,
|
||||
|
||||
'logo_only': False,
|
||||
|
||||
# Toc options
|
||||
'collapse_navigation': True,
|
||||
'sticky_navigation': True,
|
||||
'navigation_depth': 4,
|
||||
'includehidden': True,
|
||||
'titles_only': False
|
||||
}
|
||||
# html_logo = ''
|
||||
# github_url = ''
|
||||
# html_baseurl = ''
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_logo = "images/tug_logo.svg"
|
||||
|
||||
# -- Breathe configuration -------------------------------------------------
|
||||
|
||||
breathe_projects = {
|
||||
"Tug": "_build/xml/"
|
||||
}
|
||||
breathe_default_project = "Tug"
|
||||
breathe_default_members = ('members', 'undoc-members')
|
||||
38
docs_sphinx/developer.rst
Normal file
@ -0,0 +1,38 @@
|
||||
Developer Guide
|
||||
===============
|
||||
|
||||
=========================
|
||||
Class Diagram of user API
|
||||
=========================
|
||||
|
||||
The following graphic shows the class diagram of the user API. The FTCS and
|
||||
BTCS functionalities are externally outsourced and not visible to the user.
|
||||
|
||||
.. image:: images/class_diagram.svg
|
||||
:width: 2000
|
||||
:alt: Class diagram for the user API
|
||||
|
||||
====================================================
|
||||
Activity Diagram for run routine in simulation class
|
||||
====================================================
|
||||
|
||||
The following activity diagram represents the actions when the run method is called within the simulation class.
|
||||
For better distinction, the activities of the calculation methods FTCS and BTCS are shown in two separate activity diagrams.
|
||||
|
||||
.. image:: images/activity_diagram_run.svg
|
||||
:width: 2000
|
||||
:alt: Activity diagram for the run method in the simulation class
|
||||
|
||||
|
||||
**Activity Diagram for FTCS method**
|
||||
|
||||
.. image:: images/activity_diagram_FTCS.svg
|
||||
:width: 400
|
||||
:alt: Activity diagram for the FTCS method
|
||||
|
||||
|
||||
**Activity Diagram for BTCS method**
|
||||
|
||||
.. image:: images/activity_diagram_BTCS.svg
|
||||
:width: 400
|
||||
:alt: Activity diagram for the BTCS method
|
||||
2
docs_sphinx/developper.rst
Normal file
@ -0,0 +1,2 @@
|
||||
Developper API
|
||||
==============
|
||||
62
docs_sphinx/examples.rst
Normal file
@ -0,0 +1,62 @@
|
||||
Examples
|
||||
========
|
||||
|
||||
At this point, some typical commented examples are presented to illustrate how Tug works.
|
||||
In general, each simulation is divided into three blocks:
|
||||
- the initialization of the grid, which is to be simulated
|
||||
- the setting of the boundary conditions
|
||||
- the setting of the simulation parameters and the start of the simulation
|
||||
|
||||
Two dimensional grid with constant boundaries and FTCS method
|
||||
-------------------------------------------------------------
|
||||
**Initialization of the grid**
|
||||
|
||||
For example, the initalization of a grid with 20 by 20 cells and a domain size (physical extent of the grid) of
|
||||
also 20 by 20 length units can be done as follows. The setting of the domain is optional here and is set to the
|
||||
same size as the number of cells in the standard case. As seen in the code, the cells of the grid are set to an
|
||||
initial value of 0 and only in the upper left corner (0,0) the starting concentration is set to the value 20.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
int row = 20
|
||||
int col = 20;
|
||||
Grid grid = Grid(row,col);
|
||||
grid.setDomain(row, col);
|
||||
MatrixXd concentrations = MatrixXd::Constant(row,col,0);
|
||||
concentrations(0,0) = 20;
|
||||
grid.setConcentrations(concentrations);
|
||||
|
||||
**Setting of the boundary conditions**
|
||||
|
||||
First, a boundary class is created and then the corresponding boundary conditions are set. In this case, all four sides
|
||||
of the grid are set as constant edges with a concentration of 0.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Boundary bc = Boundary(grid);
|
||||
bc.setBoundarySideConstant(BC_SIDE_LEFT, 0);
|
||||
bc.setBoundarySideConstant(BC_SIDE_RIGHT, 0);
|
||||
bc.setBoundarySideConstant(BC_SIDE_TOP, 0);
|
||||
bc.setBoundarySideConstant(BC_SIDE_BOTTOM, 0);
|
||||
|
||||
**Setting of the simulation parameters and simulation start**
|
||||
In the last block, a simulation class is created and the objects of the grid and the boundary conditions are passed. The solution
|
||||
method is also specified (either FCTS or BTCS). Furthermore, the desired time step and the number of iterations are set. The penultimate
|
||||
parameter specifies the output of the simulated results in a CSV file. In the present case, the result of each iteration step is written
|
||||
one below the other into the corresponding CSV file.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Simulation simulation = Simulation(grid, bc, FTCS_APPROACH);
|
||||
simulation.setTimestep(0.1);
|
||||
simulation.setIterations(1000);
|
||||
simulation.setOutputCSV(CSV_OUTPUT_VERBOSE);
|
||||
simulation.run();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Setting special boundary conditions on individual cells
|
||||
-------------------------------------------------------
|
||||
4
docs_sphinx/images/activity_diagram_BTCS.svg
Normal file
|
After Width: | Height: | Size: 35 KiB |
4
docs_sphinx/images/activity_diagram_FTCS.svg
Normal file
|
After Width: | Height: | Size: 19 KiB |
4
docs_sphinx/images/activity_diagram_run.svg
Normal file
|
After Width: | Height: | Size: 15 KiB |
4
docs_sphinx/images/class_diagram.svg
Normal file
|
After Width: | Height: | Size: 23 KiB |
2629
docs_sphinx/images/tug_logo.svg
Normal file
|
After Width: | Height: | Size: 138 KiB |
37
docs_sphinx/index.rst
Normal file
@ -0,0 +1,37 @@
|
||||
.. Tug documentation master file, created by
|
||||
sphinx-quickstart on Mon Aug 14 11:30:23 2023.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to Tug's documentation!
|
||||
===============================
|
||||
Welcome to the documentation of the TUG project, a simulation program
|
||||
for solving one- and two-dimensional diffusion problems with heterogeneous diffusion coefficients, more
|
||||
generally, for solving the following differential equation
|
||||
|
||||
.. math::
|
||||
\frac{\partial C}{\partial t} = \alpha_x \frac{\partial^2 C}{\partial x^2} + \alpha_y \frac{\partial^2 C}{\partial y^2}.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
||||
Table of Contents
|
||||
^^^^^^^^^^^^^^^^^
|
||||
.. toctree::
|
||||
|
||||
:maxdepth: 2
|
||||
self
|
||||
installation
|
||||
theory
|
||||
user
|
||||
developer
|
||||
examples
|
||||
visualization
|
||||
3
docs_sphinx/installation.rst
Normal file
@ -0,0 +1,3 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
2
docs_sphinx/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
breathe
|
||||
sphinx-rtd-theme
|
||||
15
docs_sphinx/theory.rst
Normal file
@ -0,0 +1,15 @@
|
||||
Theoretical Foundations
|
||||
=======================
|
||||
|
||||
=====================
|
||||
The Diffusion Problem
|
||||
=====================
|
||||
|
||||
================
|
||||
Numerical Solver
|
||||
================
|
||||
|
||||
**Backward Time-Centered Space (BTCS) Method**
|
||||
|
||||
|
||||
**Forward Time-Centered Space (BTCS) Method**
|
||||
2629
docs_sphinx/tug_logo.svg
Normal file
|
After Width: | Height: | Size: 138 KiB |
9
docs_sphinx/user.rst
Normal file
@ -0,0 +1,9 @@
|
||||
User API
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
|
||||
:maxdepth: 2
|
||||
Grid
|
||||
Boundary
|
||||
Simulation
|
||||
3
docs_sphinx/visualization.rst
Normal file
@ -0,0 +1,3 @@
|
||||
Visualization
|
||||
=============
|
||||
|
||||
50
examples/profiling.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include <tug/Simulation.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
int n[4] = {10, 20, 50, 100};
|
||||
int iterations[1] = {100};
|
||||
int repetition = 10;
|
||||
|
||||
ofstream myfile;
|
||||
myfile.open("btcs_time_measurement_openmp_10.csv");
|
||||
|
||||
for (int i = 0; i < size(n); i++){
|
||||
cout << "Grid size: " << n[i] << " x " << n[i] << endl << endl;
|
||||
myfile << "Grid size: " << n[i] << " x " << n[i] << endl;
|
||||
for(int j = 0; j < size(iterations); j++){
|
||||
cout << "Iterations: " << iterations[j] << endl;
|
||||
for (int k = 0; k < repetition; k++){
|
||||
cout << "Wiederholung: " << k << endl;
|
||||
Grid grid = Grid(n[i], n[i]);
|
||||
grid.setDomain(n[i], n[i]);
|
||||
|
||||
MatrixXd concentrations = MatrixXd::Constant(n[i], n[i], 0);
|
||||
concentrations(5,5) = 1;
|
||||
grid.setConcentrations(concentrations);
|
||||
MatrixXd alpha = MatrixXd::Constant(n[i], n[i], 0.5);
|
||||
|
||||
Boundary bc = Boundary(grid);
|
||||
|
||||
Simulation sim = Simulation(grid, bc, BTCS_APPROACH);
|
||||
|
||||
|
||||
sim.setTimestep(0.001);
|
||||
sim.setIterations(iterations[j]);
|
||||
sim.setOutputCSV(CSV_OUTPUT_OFF);
|
||||
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
sim.run();
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
|
||||
myfile << milliseconds.count() << endl;
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
myfile << endl;
|
||||
|
||||
}
|
||||
myfile.close();
|
||||
}
|
||||
51
examples/profiling_openmp.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include <tug/Simulation.hpp>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
int n[4] = {10, 20, 50, 100};
|
||||
int iterations[1] = {100};
|
||||
int repetition = 10;
|
||||
|
||||
ofstream myfile;
|
||||
myfile.open("time_measure_experiment_openmp_thread_6.csv");
|
||||
|
||||
for (int i = 0; i < size(n); i++){
|
||||
cout << "Grid size: " << n[i] << " x " << n[i] << endl << endl;
|
||||
myfile << "Grid size: " << n[i] << " x " << n[i] << endl << endl;
|
||||
for(int j = 0; j < size(iterations); j++){
|
||||
cout << "Iterations: " << iterations[j] << endl;
|
||||
myfile << "Iterations: " << iterations[j] << endl;
|
||||
for (int k = 0; k < repetition; k++){
|
||||
cout << "Wiederholung: " << k << endl;
|
||||
Grid grid = Grid(n[i], n[i]);
|
||||
grid.setDomain(n[i], n[i]);
|
||||
|
||||
MatrixXd concentrations = MatrixXd::Constant(n[i], n[i], 0);
|
||||
concentrations(5,5) = 1;
|
||||
grid.setConcentrations(concentrations);
|
||||
MatrixXd alpha = MatrixXd::Constant(n[i], n[i], 0.5);
|
||||
|
||||
Boundary bc = Boundary(grid);
|
||||
|
||||
Simulation sim = Simulation(grid, bc, FTCS_APPROACH);
|
||||
|
||||
|
||||
sim.setTimestep(0.001);
|
||||
sim.setIterations(iterations[j]);
|
||||
sim.setOutputCSV(CSV_OUTPUT_OFF);
|
||||
|
||||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
sim.run();
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(end - begin);
|
||||
myfile << milliseconds.count() << endl;
|
||||
}
|
||||
}
|
||||
cout << endl;
|
||||
myfile << endl;
|
||||
|
||||
}
|
||||
myfile.close();
|
||||
}
|
||||
@ -7,6 +7,9 @@
|
||||
|
||||
#include "FTCS.cpp"
|
||||
#include <tug/Boundary.hpp>
|
||||
#include <omp.h>
|
||||
|
||||
#define NUM_THREADS_BTCS 1
|
||||
|
||||
using namespace Eigen;
|
||||
|
||||
@ -62,7 +65,7 @@ static tuple<double, double> calcRightBoundaryCoeffClosed(MatrixXd &alpha, int &
|
||||
|
||||
|
||||
// creates coefficient matrix for next time step from alphas in x-direction
|
||||
static SparseMatrix<double> createCoeffMatrix(MatrixXd &alpha, vector<BoundaryElement> bcLeft, vector<BoundaryElement> bcRight, int numCols, int rowIndex, double sx) {
|
||||
static SparseMatrix<double> createCoeffMatrix(MatrixXd &alpha, vector<BoundaryElement> &bcLeft, vector<BoundaryElement> &bcRight, int &numCols, int &rowIndex, double &sx) {
|
||||
|
||||
// square matrix of column^2 dimension for the coefficients
|
||||
SparseMatrix<double> cm(numCols, numCols);
|
||||
@ -84,6 +87,7 @@ static SparseMatrix<double> createCoeffMatrix(MatrixXd &alpha, vector<BoundaryEl
|
||||
|
||||
// inner columns
|
||||
int n = numCols-1;
|
||||
#pragma omp parallel for num_threads(NUM_THREADS_BTCS)
|
||||
for (int i = 1; i < n; i++) {
|
||||
cm.insert(i,i-1) = -sx * calcAlphaIntercell(alpha(rowIndex,i-1), alpha(rowIndex,i));
|
||||
cm.insert(i,i) = 1 + sx * (
|
||||
@ -190,7 +194,7 @@ static double calcExplicitConcentrationsBottomBoundaryClosed(MatrixXd &concentra
|
||||
static VectorXd createSolutionVector(MatrixXd &concentrations, MatrixXd &alphaX, MatrixXd &alphaY,
|
||||
vector<BoundaryElement> &bcLeft, vector<BoundaryElement> &bcRight,
|
||||
vector<BoundaryElement> &bcTop, vector<BoundaryElement> &bcBottom,
|
||||
int length, int rowIndex, double sx, double sy) {
|
||||
int &length, int &rowIndex, double &sx, double &sy) {
|
||||
|
||||
VectorXd sv(length);
|
||||
int numRows = concentrations.rows();
|
||||
@ -198,6 +202,7 @@ static VectorXd createSolutionVector(MatrixXd &concentrations, MatrixXd &alphaX,
|
||||
|
||||
// inner rows
|
||||
if (rowIndex > 0 && rowIndex < numRows-1) {
|
||||
#pragma omp parallel for num_threads(NUM_THREADS_BTCS)
|
||||
for (int i = 0; i < length; i++) {
|
||||
sv(i) = sy * calcAlphaIntercell(alphaY(rowIndex,i), alphaY(rowIndex+1,i))
|
||||
* concentrations(rowIndex+1,i)
|
||||
@ -215,6 +220,7 @@ static VectorXd createSolutionVector(MatrixXd &concentrations, MatrixXd &alphaX,
|
||||
|
||||
// first row
|
||||
if (rowIndex == 0) {
|
||||
#pragma omp parallel for num_threads(NUM_THREADS_BTCS)
|
||||
for (int i = 0; i < length; i++) {
|
||||
type = bcTop[i].getType();
|
||||
if (type == BC_TYPE_CONSTANT) {
|
||||
@ -229,6 +235,7 @@ static VectorXd createSolutionVector(MatrixXd &concentrations, MatrixXd &alphaX,
|
||||
|
||||
// last row
|
||||
if (rowIndex == numRows-1) {
|
||||
#pragma omp parallel for num_threads(NUM_THREADS_BTCS)
|
||||
for (int i = 0; i < length; i++) {
|
||||
type = bcBottom[i].getType();
|
||||
if (type == BC_TYPE_CONSTANT) {
|
||||
@ -258,6 +265,7 @@ static VectorXd createSolutionVector(MatrixXd &concentrations, MatrixXd &alphaX,
|
||||
// solver for linear equation system; A corresponds to coefficient matrix,
|
||||
// b to the solution vector
|
||||
static VectorXd solve(SparseMatrix<double> &A, VectorXd &b) {
|
||||
|
||||
SparseLU<SparseMatrix<double>> solver;
|
||||
solver.analyzePattern(A);
|
||||
solver.factorize(A);
|
||||
@ -281,7 +289,8 @@ static void BTCS_1D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
vector<BoundaryElement> bcRight = bc.getBoundarySide(BC_SIDE_RIGHT);
|
||||
|
||||
MatrixXd concentrations = grid.getConcentrations();
|
||||
A = createCoeffMatrix(alpha, bcLeft, bcRight, length, 0, sx); // this is exactly same as in 2D
|
||||
int rowIndex = 0;
|
||||
A = createCoeffMatrix(alpha, bcLeft, bcRight, length, rowIndex, sx); // this is exactly same as in 2D
|
||||
for (int i = 0; i < length; i++) {
|
||||
b(i) = concentrations(0,i);
|
||||
}
|
||||
@ -323,34 +332,39 @@ static void BTCS_2D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
vector<BoundaryElement> bcBottom = bc.getBoundarySide(BC_SIDE_BOTTOM);
|
||||
|
||||
MatrixXd concentrations = grid.getConcentrations();
|
||||
#pragma omp parallel for num_threads(NUM_THREADS_BTCS) private(A, b, row_t1)
|
||||
for (int i = 0; i < rowMax; i++) {
|
||||
|
||||
|
||||
A = createCoeffMatrix(alphaX, bcLeft, bcRight, colMax, i, sx);
|
||||
b = createSolutionVector(concentrations, alphaX, alphaY, bcLeft, bcRight,
|
||||
bcTop, bcBottom, colMax, i, sx, sy);
|
||||
|
||||
SparseLU<SparseMatrix<double>> solver;
|
||||
|
||||
row_t1 = solve(A, b);
|
||||
|
||||
for (int j = 0; j < colMax; j++) {
|
||||
concentrations_t1(i,j) = row_t1(j); // can potentially be improved by using Eigen method
|
||||
}
|
||||
|
||||
concentrations_t1.row(i) = row_t1;
|
||||
}
|
||||
|
||||
concentrations_t1.transposeInPlace();
|
||||
concentrations.transposeInPlace();
|
||||
alphaX.transposeInPlace();
|
||||
alphaY.transposeInPlace();
|
||||
|
||||
#pragma omp parallel for num_threads(NUM_THREADS_BTCS) private(A, b, row_t1)
|
||||
|
||||
for (int i = 0; i < colMax; i++) {
|
||||
|
||||
// swap alphas, boundary conditions and sx/sy for column-wise calculation
|
||||
A = createCoeffMatrix(alphaY, bcTop, bcBottom, rowMax, i, sy);
|
||||
b = createSolutionVector(concentrations_t1, alphaY, alphaX, bcTop, bcBottom,
|
||||
bcLeft, bcRight, rowMax, i, sy, sx);
|
||||
|
||||
row_t1 = solve(A, b);
|
||||
|
||||
for (int j = 0; j < rowMax; j++) {
|
||||
concentrations(i,j) = row_t1(j); // can potentially be improved by using Eigen method
|
||||
}
|
||||
concentrations.row(i) = row_t1;
|
||||
}
|
||||
|
||||
concentrations.transposeInPlace();
|
||||
|
||||
grid.setConcentrations(concentrations);
|
||||
|
||||
12
src/FTCS.cpp
@ -11,6 +11,8 @@
|
||||
#include <iostream>
|
||||
#include <omp.h>
|
||||
|
||||
#define NUM_THREADS 6
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
@ -269,7 +271,7 @@ static void FTCS_2D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
// inner cells
|
||||
// these are independent of the boundary condition type
|
||||
// omp_set_num_threads(10);
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for num_threads(NUM_THREADS)
|
||||
for (int row = 1; row < rowMax-1; row++) {
|
||||
for (int col = 1; col < colMax-1; col++) {
|
||||
concentrations_t1(row, col) = grid.getConcentrations()(row, col)
|
||||
@ -289,7 +291,7 @@ static void FTCS_2D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
// left without corners / looping over rows
|
||||
// hold column constant at index 0
|
||||
int col = 0;
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for num_threads(NUM_THREADS)
|
||||
for (int row = 1; row < rowMax-1; row++) {
|
||||
concentrations_t1(row, col) = grid.getConcentrations()(row,col)
|
||||
+ timestep / (deltaCol*deltaCol)
|
||||
@ -306,7 +308,7 @@ static void FTCS_2D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
// right without corners / looping over rows
|
||||
// hold column constant at max index
|
||||
col = colMax-1;
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for num_threads(NUM_THREADS)
|
||||
for (int row = 1; row < rowMax-1; row++) {
|
||||
concentrations_t1(row,col) = grid.getConcentrations()(row,col)
|
||||
+ timestep / (deltaCol*deltaCol)
|
||||
@ -324,7 +326,7 @@ static void FTCS_2D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
// top without corners / looping over columns
|
||||
// hold row constant at index 0
|
||||
int row = 0;
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for num_threads(NUM_THREADS)
|
||||
for (int col=1; col<colMax-1;col++){
|
||||
concentrations_t1(row, col) = grid.getConcentrations()(row, col)
|
||||
+ timestep / (deltaRow*deltaRow)
|
||||
@ -341,7 +343,7 @@ static void FTCS_2D(Grid &grid, Boundary &bc, double ×tep) {
|
||||
// bottom without corners / looping over columns
|
||||
// hold row constant at max index
|
||||
row = rowMax-1;
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for num_threads(NUM_THREADS)
|
||||
for(int col=1; col<colMax-1;col++){
|
||||
concentrations_t1(row, col) = grid.getConcentrations()(row, col)
|
||||
+ timestep / (deltaRow*deltaRow)
|
||||
|
||||