aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README.md34
-rw-r--r--examples/burning_ship.pngbin0 -> 5830856 bytes
-rw-r--r--examples/julia.pngbin0 -> 5672122 bytes
-rw-r--r--examples/mandelbrot.pngbin0 -> 1554396 bytes
-rw-r--r--examples/multibrot.pngbin0 -> 2304127 bytes
-rw-r--r--examples/multicorn.gifbin0 -> 155443 bytes
-rw-r--r--examples/multicorn_framelist4
-rw-r--r--examples/tricorn.pngbin0 -> 1448374 bytes
-rw-r--r--makefile20
-rw-r--r--presentation/presentation.html411
-rw-r--r--presentation/presentation.md15
-rw-r--r--src/fractal_render.c3
-rw-r--r--src/renderers.c5
14 files changed, 480 insertions, 13 deletions
diff --git a/.gitignore b/.gitignore
index c93d064..270e560 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ analysis/data/*
build/*
*.html
!analysis/analysis.html
+!presentation/presentation.html
# IDE stuff
.vscode
diff --git a/README.md b/README.md
index 17c312e..a962c12 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ Each version of the complex fractal generator has its own dependencies.
The serial version should compile on all systems that support complex arithmetic.
The shared version requires a compiler with [OpenMP](https://www.openmp.org/) support.
-The CUDA version requires the `nvcc` compiler and `thrust libraries`.
+The CUDA version requires the `nvcc` compiler and `thrust` libraries.
For better performance on your machine, change the flag `-arch=sm_86` in `NVCFLAGS` in the makefile to your gpu's compute capability.
### Building
@@ -68,6 +68,38 @@ Generates a 500x500 julia fractal grid which has a maximum of 30 iterations for
## Visualizations
+The program `fractal-render` renders `.grid` files into txt, png's, and animated gifs.
+
+```
+Usage: fractal-render -i input.grid [-r renderer] [-o output.ext]
+Options:
+ -i, --input <input grid> the grid to be rendered, if the file name is '-' reads from stdin
+ -r, --renderer <renderer> the renderer to use, defaults to the text renderer
+ renderers: txt, png, gif (TODO, with additional features)
+ -d, --delay <delay> the delay between animation frames in 1/100 s
+ -o, --output <output file> the file to output the result of rendering, if not given defaults to fractal.out.
+ -v, --verbose verbose output
+ -h, --help prints this help and exits
+```
+
+### Building
+
+To build simply run
+
+```bash
+make
+```
+
+### Examples
+
+Some example visualizations are provided in `examples`, they can be regenerated with
+
+```bash
+make examples/julia.png
+make examples/multicorn.gif
+```
+
+
## Presentation
Building the presentation requires a [pandoc](https://pandoc.org/) installation.
diff --git a/examples/burning_ship.png b/examples/burning_ship.png
new file mode 100644
index 0000000..98ce9f1
--- /dev/null
+++ b/examples/burning_ship.png
Binary files differ
diff --git a/examples/julia.png b/examples/julia.png
new file mode 100644
index 0000000..1b8440c
--- /dev/null
+++ b/examples/julia.png
Binary files differ
diff --git a/examples/mandelbrot.png b/examples/mandelbrot.png
new file mode 100644
index 0000000..4fbfb8a
--- /dev/null
+++ b/examples/mandelbrot.png
Binary files differ
diff --git a/examples/multibrot.png b/examples/multibrot.png
new file mode 100644
index 0000000..6aae55d
--- /dev/null
+++ b/examples/multibrot.png
Binary files differ
diff --git a/examples/multicorn.gif b/examples/multicorn.gif
new file mode 100644
index 0000000..115eb9b
--- /dev/null
+++ b/examples/multicorn.gif
Binary files differ
diff --git a/examples/multicorn_framelist b/examples/multicorn_framelist
new file mode 100644
index 0000000..243dfd2
--- /dev/null
+++ b/examples/multicorn_framelist
@@ -0,0 +1,4 @@
+examples/multicorn_2.grid
+examples/multicorn_3.grid
+examples/multicorn_4.grid
+examples/multicorn_5.grid
diff --git a/examples/tricorn.png b/examples/tricorn.png
new file mode 100644
index 0000000..8d02e24
--- /dev/null
+++ b/examples/tricorn.png
Binary files differ
diff --git a/makefile b/makefile
index 8fc8abd..8a73420 100644
--- a/makefile
+++ b/makefile
@@ -48,19 +48,31 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(OBJ_DIR):
mkdir -p $@
-###########
-# Tests #
-###########
+####################
+# Tests/Examples #
+###################
examples/julia.png: examples/julia.grid $(BUILD_DIR)/fractal-render
$(BUILD_DIR)/fractal-render -i $< -r png -o $@
+examples/multicorn.gif: examples/multicorn_framelist
+ $(BUILD_DIR)/fractal-render -i $< -d 80 -r gif -o $@
+
+examples/multicorn_framelist: examples/multicorn_2.grid examples/multicorn_3.grid examples/multicorn_4.grid examples/multicorn_5.grid
+ @echo $< > $@
+ @echo $(word 2, $^) >> $@
+ @echo $(word 3, $^) >> $@
+ @echo $(word 4, $^) >> $@
+
examples/julia.grid: $(BUILD_DIR)/shared-fractals
- $< -c 0.285+0.01i -i 255 -r 2 -x 8192 -y 8192 -o $@ -f julia
+ $< -c 0.285+0.01i -i 155 -r 2 -x 8192 -y 8192 -o $@ -f julia
examples/mandelbrot_%.grid: $(BUILD_DIR)/%-fractals
$< -x 100 -y 100 -o $@
+examples/multicorn_%.grid: $(BUILD_DIR)/shared-fractals
+ $< -x1000 -y1000 -i50 -d $* -o $@ -f multicorn
+
tests/mandelbrot: examples/mandelbrot_serial.grid examples/mandelbrot_shared.grid examples/mandelbrot_cuda.grid
cmp -l $< $(word 2, $^) > $@
cmp -l $(word 2, $^) $(word 3, $^) >> $@
diff --git a/presentation/presentation.html b/presentation/presentation.html
new file mode 100644
index 0000000..31c1443
--- /dev/null
+++ b/presentation/presentation.html
@@ -0,0 +1,411 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="generator" content="pandoc">
+ <meta name="author" content="JP Appel">
+ <meta name="author" content="David Marrero">
+ <title>HPC Complex Fractal Generation</title>
+ <meta name="apple-mobile-web-app-capable" content="yes">
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/reset.css">
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/reveal.css">
+ <style>
+ .reveal .sourceCode { /* see #7635 */
+ overflow: visible;
+ }
+ code{white-space: pre-wrap;}
+ span.smallcaps{font-variant: small-caps;}
+ span.underline{text-decoration: underline;}
+ div.column{display: inline-block; vertical-align: top; width: 50%;}
+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
+ ul.task-list{list-style: none;}
+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
+ </style>
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/theme/black.css" id="theme">
+</head>
+<body>
+ <div class="reveal">
+ <div class="slides">
+
+<section id="title-slide">
+ <h1 class="title">HPC Complex Fractal Generation</h1>
+ <p class="author">JP Appel</p>
+ <p class="author">David Marrero</p>
+</section>
+
+<section>
+<section id="prerequisite-knowledge" class="title-slide slide level1">
+<h1>Prerequisite Knowledge</h1>
+
+</section>
+<section id="complex-numbers" class="slide level2">
+<h2>Complex Numbers</h2>
+<p><span class="math display"><em>i</em><sup>2</sup> =  − 1</span> <span
+class="math display"><em>z</em> = <em>x</em> + <em>i</em><em>y</em></span></p>
+<aside class="notes">
+<ul>
+<li>complex numbers are an extension of real numbers, stemming from the
+square root of <span class="math inline"> − 1</span></li>
+<li>a complex number is just a pair of two real numbers (x,y) with
+different ways to add and multiply</li>
+<li>in computer science we model real numbers with a single float or
+double, so we will need 2 floats or doubles to model a complex
+number</li>
+</ul>
+</aside>
+<div class="fragment">
+<h3 id="addition">Addition</h3>
+<p><span
+class="math display"><em>z</em><sub>1</sub> + <em>z</em><sub>2</sub> = (<em>x</em><sub>1</sub>+<em>x</em><sub>2</sub>) + <em>i</em>(<em>y</em><sub>1</sub>+<em>y</em><sub>2</sub>)</span></p>
+<aside class="notes">
+<ul>
+<li>addition behaves as you expect</li>
+<li>multiplication involves multiplying then distributing, and using the
+fact that <span
+class="math inline"><em>i</em><sup>2</sup> =  − 1</span></li>
+<li>so adding two complex numbers is 2 float additions</li>
+<li>and multiplying them is 4 multiplications and 2 additions</li>
+</ul>
+</aside>
+<h3 id="multiplication">Multiplication</h3>
+<p><span
+class="math display"><em>z</em><sub>1</sub><em>z</em><sub>2</sub> = (<em>x</em><sub>1</sub><em>x</em><sub>2</sub>−<em>y</em><sub>1</sub><em>y</em><sub>2</sub>) + <em>i</em>(<em>x</em><sub>1</sub><em>y</em><sub>2</sub>+<em>x</em><sub>2</sub><em>y</em><sub>1</sub>)</span></p>
+</div>
+</section>
+<section id="what-is-the-mandelbrot-set" class="slide level2">
+<h2>What is the Mandelbrot Set</h2>
+<div class="fragment">
+<p><span
+class="math display"><em>z</em><sub><em>n</em></sub> = <em>z</em><sub><em>n</em> − 1</sub><sup>2</sup> + <em>z</em><sub>0</sub></span></p>
+<aside class="notes">
+<ul>
+<li>this sequence is used to generate the mandelbrot set</li>
+<li>if for some complex number <span
+class="math inline"><em>z</em><sub>0</sub></span> the sequence remains
+bounded as it <span class="math inline"><em>n</em></span> approaches
+infinity then <span class="math inline"><em>z</em><sub>0</sub></span>
+lies within the mandelbrot set</li>
+<li>there are many recursive sequences related to this, where you modify
+that happens with the recursive term</li>
+</ul>
+</aside>
+</div>
+</section>
+<section id="fractals" class="slide level2">
+<h2>Fractals</h2>
+<div class="columns">
+<div class="column" style="width:40%;">
+<ul>
+<li>infinite self-similar geometric shape</li>
+<li>have “fractional dimension”</li>
+</ul>
+</div><div class="column" style="width:60%;">
+<figure>
+<img
+data-src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Sierpinski_triangle.svg/1920px-Sierpinski_triangle.svg.png"
+style="width:80.0%" alt="Sripenski Triangle" />
+<figcaption aria-hidden="true">Sripenski Triangle</figcaption>
+</figure>
+</div>
+</div>
+<div class="fragment">
+<p>The Mandelbrot set is a fractal in the complex plane</p>
+<aside class="notes">
+<ul>
+<li>fractals are a infinite self-similar geometric shape</li>
+<li>so if you zoom in on any one part it will look like the entire
+object</li>
+<li>the Sripenski triangle is an example of a fractal</li>
+<li>the mandelbrot set forms a fractal in the complex plane</li>
+</ul>
+</aside>
+</div>
+</section>
+<section id="fractal-in-nature" class="slide level2">
+<h2>Fractal in Nature</h2>
+<figure>
+<img
+data-src="https://www.rocketgardens.co.uk/wp-content/uploads/2016/02/Cauliflower20Romanesco.jpg"
+style="width:50.0%" alt="Romanesco Cauliflower" />
+<figcaption aria-hidden="true">Romanesco Cauliflower</figcaption>
+</figure>
+<aside class="notes">
+<ul>
+<li>fractals often show up in nature</li>
+</ul>
+</aside>
+</section>
+<section id="escape-time-algorithm" class="slide level2">
+<h2>Escape Time Algorithm</h2>
+<div>
+<ul>
+<li class="fragment">Inputs
+<ul>
+<li class="fragment">Maximum Number of iterations</li>
+<li class="fragment">Upper bound</li>
+</ul></li>
+</ul>
+<ol type="1">
+<li class="fragment">Create a grid of points to sample</li>
+<li class="fragment">For each point in the sample space
+<ol type="1">
+<li class="fragment">Compute the next term in the sequence</li>
+<li class="fragment">if greater than the upper bound return the number
+of iterations</li>
+<li class="fragment">else repeat until the maximum number of iterations
+and return</li>
+</ol></li>
+</ol>
+</div>
+<aside class="notes">
+<ul>
+<li>to compute the complex sets we used an escape time algorithm</li>
+<li>in general it takes in a maximum number of iterations, an initial
+value, and an upper bound</li>
+<li>the escape time algorithm is as follows (read of the slides)</li>
+<li>note that each sampled point is completely independent of any other
+point
+<ul>
+<li>this hints to us that the problem will parallelize well</li>
+</ul></li>
+<li>for most of the sets we looked at, there is a proven bound
+<ul>
+<li>ie if the sequence is ever larger than a value we know it
+diverges</li>
+</ul></li>
+</ul>
+</aside>
+</section></section>
+<section>
+<section id="implementation" class="title-slide slide level1">
+<h1>Implementation</h1>
+
+</section>
+<section id="program-structure" class="slide level2">
+<h2>Program Structure</h2>
+<p><img data-src="diagram.png" /></p>
+<aside class="notes">
+<ul>
+<li>the translation units are roughly as pictured here</li>
+<li>black ellipses are for serial code, color is for parallel</li>
+<li>each version of the program fills in an array with the number of
+iterations it took the sequence to grow too large</li>
+<li>that array along with some extra data is a grid object, which can be
+serialized and deserialized</li>
+<li>the main fractals unit handles cli argument parsing for the sampling
+resolution, fractal type etc</li>
+<li>a separate renderer program handles creating images from the
+<code>.grid</code> file</li>
+<li>the <code>.grid</code> file format is really simple, it’s a magic
+number, the grid dimensions, the maximum number of iterations, the lower
+left and upper right most points of the region, and then the data</li>
+</ul>
+</aside>
+</section>
+<section id="mandelbrot" class="slide level2">
+<h2>Mandelbrot</h2>
+<p><a href="../examples/mandelbrot.png">Image</a></p>
+<aside class="notes">
+<ul>
+<li>when mandelbrot initially tried to have this printed, the printers
+kept removing the “dust” thinking it was an error in their printing
+process</li>
+</ul>
+</aside>
+</section>
+<section id="tricorn" class="slide level2">
+<h2>Tricorn</h2>
+<p><a href="../examples/tricorn.png">Image</a></p>
+</section>
+<section id="burning-ship" class="slide level2">
+<h2>Burning Ship</h2>
+<p><a href="../examples/burning_ship.png">Image</a></p>
+</section>
+<section id="multibrot" class="slide level2">
+<h2>Multibrot</h2>
+<p><a href="../examples/multibrot.png">Image</a></p>
+</section>
+<section id="multicorn" class="slide level2">
+<h2>Multicorn</h2>
+<p><a href="../examples/multicorn.gif">GIF</a></p>
+</section>
+<section id="julia" class="slide level2">
+<h2>Julia</h2>
+<p><a href="../examples/julia.png">Image</a></p>
+</section></section>
+<section>
+<section id="analysis" class="title-slide slide level1">
+<h1>Analysis</h1>
+
+</section>
+<section id="section" class="slide level2">
+<h2></h2>
+<p><a href="../analysis/analysis.html">Interactive Plots</a></p>
+</section></section>
+ </div>
+ </div>
+
+ <script src="https://unpkg.com/reveal.js@^4//dist/reveal.js"></script>
+
+ <!-- reveal.js plugins -->
+ <script src="https://unpkg.com/reveal.js@^4//plugin/notes/notes.js"></script>
+ <script src="https://unpkg.com/reveal.js@^4//plugin/search/search.js"></script>
+ <script src="https://unpkg.com/reveal.js@^4//plugin/zoom/zoom.js"></script>
+
+ <script>
+
+ // Full list of configuration options available at:
+ // https://revealjs.com/config/
+ Reveal.initialize({
+ // Display controls in the bottom right corner
+ controls: true,
+
+ // Help the user learn the controls by providing hints, for example by
+ // bouncing the down arrow when they first encounter a vertical slide
+ controlsTutorial: true,
+
+ // Determines where controls appear, "edges" or "bottom-right"
+ controlsLayout: 'bottom-right',
+
+ // Visibility rule for backwards navigation arrows; "faded", "hidden"
+ // or "visible"
+ controlsBackArrows: 'faded',
+
+ // Display a presentation progress bar
+ progress: true,
+
+ // Display the page number of the current slide
+ slideNumber: false,
+
+ // 'all', 'print', or 'speaker'
+ showSlideNumber: 'all',
+
+ // Add the current slide number to the URL hash so that reloading the
+ // page/copying the URL will return you to the same slide
+ hash: true,
+
+ // Start with 1 for the hash rather than 0
+ hashOneBasedIndex: false,
+
+ // Flags if we should monitor the hash and change slides accordingly
+ respondToHashChanges: true,
+
+ // Push each slide change to the browser history
+ history: false,
+
+ // Enable keyboard shortcuts for navigation
+ keyboard: true,
+
+ // Enable the slide overview mode
+ overview: true,
+
+ // Disables the default reveal.js slide layout (scaling and centering)
+ // so that you can use custom CSS layout
+ disableLayout: false,
+
+ // Vertical centering of slides
+ center: true,
+
+ // Enables touch navigation on devices with touch input
+ touch: true,
+
+ // Loop the presentation
+ loop: false,
+
+ // Change the presentation direction to be RTL
+ rtl: false,
+
+ // see https://revealjs.com/vertical-slides/#navigation-mode
+ navigationMode: 'default',
+
+ // Randomizes the order of slides each time the presentation loads
+ shuffle: false,
+
+ // Turns fragments on and off globally
+ fragments: true,
+
+ // Flags whether to include the current fragment in the URL,
+ // so that reloading brings you to the same fragment position
+ fragmentInURL: true,
+
+ // Flags if the presentation is running in an embedded mode,
+ // i.e. contained within a limited portion of the screen
+ embedded: false,
+
+ // Flags if we should show a help overlay when the questionmark
+ // key is pressed
+ help: true,
+
+ // Flags if it should be possible to pause the presentation (blackout)
+ pause: true,
+
+ // Flags if speaker notes should be visible to all viewers
+ showNotes: false,
+
+ // Global override for autoplaying embedded media (null/true/false)
+ autoPlayMedia: null,
+
+ // Global override for preloading lazy-loaded iframes (null/true/false)
+ preloadIframes: null,
+
+ // Number of milliseconds between automatically proceeding to the
+ // next slide, disabled when set to 0, this value can be overwritten
+ // by using a data-autoslide attribute on your slides
+ autoSlide: 0,
+
+ // Stop auto-sliding after user input
+ autoSlideStoppable: true,
+
+ // Use this method for navigation when auto-sliding
+ autoSlideMethod: null,
+
+ // Specify the average time in seconds that you think you will spend
+ // presenting each slide. This is used to show a pacing timer in the
+ // speaker view
+ defaultTiming: null,
+
+ // Enable slide navigation via mouse wheel
+ mouseWheel: false,
+
+ // The display mode that will be used to show slides
+ display: 'block',
+
+ // Hide cursor if inactive
+ hideInactiveCursor: true,
+
+ // Time before the cursor is hidden (in ms)
+ hideCursorTime: 5000,
+
+ // Opens links in an iframe preview overlay
+ previewLinks: false,
+
+ // Transition style (none/fade/slide/convex/concave/zoom)
+ transition: 'slide',
+
+ // Transition speed (default/fast/slow)
+ transitionSpeed: 'default',
+
+ // Transition style for full page slide backgrounds
+ // (none/fade/slide/convex/concave/zoom)
+ backgroundTransition: 'fade',
+
+ // Number of slides away from the current that are visible
+ viewDistance: 3,
+
+ // Number of slides away from the current that are visible on mobile
+ // devices. It is advisable to set this to a lower number than
+ // viewDistance in order to save resources.
+ mobileViewDistance: 2,
+
+ // reveal.js plugins
+ plugins: [
+ RevealNotes,
+ RevealSearch,
+ RevealZoom
+ ]
+ });
+ </script>
+ </body>
+</html>
diff --git a/presentation/presentation.md b/presentation/presentation.md
index b3297c3..a4a1f4f 100644
--- a/presentation/presentation.md
+++ b/presentation/presentation.md
@@ -139,6 +139,8 @@ The Mandelbrot set is a fractal in the complex plane
## Mandelbrot
+[Image](../examples/mandelbrot.png)
+
::: notes
* when mandelbrot initially tried to have this printed, the printers kept removing the "dust" thinking it was an error in their printing process
@@ -147,19 +149,24 @@ The Mandelbrot set is a fractal in the complex plane
## Tricorn
+[Image](../examples/tricorn.png)
+
## Burning Ship
+[Image](../examples/burning_ship.png)
+
## Multibrot
+[Image](../examples/multibrot.png)
+
## Multicorn
-## Julia
+[GIF](../examples/multicorn.gif)
-## Serial Animation
-## Shared Animation
+## Julia
-## CUDA Animation
+[Image](../examples/julia.png)
# Analysis
diff --git a/src/fractal_render.c b/src/fractal_render.c
index 721d3f2..fe25f12 100644
--- a/src/fractal_render.c
+++ b/src/fractal_render.c
@@ -21,8 +21,7 @@ void print_help(){
" -r, --renderer <renderer> the renderer to use, defaults to the text renderer\n"
" renderers: txt, png, gif (TODO, with additional features)\n"
" -d, --delay <delay> the delay between animation frames in 1/100 s\n"
- " -o, --output <output file> the file to output the result of rendering, if not given defaults to output.<EXT>\n"
- " where <EXT> is the renderer used\n"
+ " -o, --output <output file> the file to output the result of rendering, if not given defaults to fractal.out\n"
" -v, --verbose verbose output\n"
" -h, --help prints this help and exits\n"
);
diff --git a/src/renderers.c b/src/renderers.c
index 2955fb2..372d7a2 100644
--- a/src/renderers.c
+++ b/src/renderers.c
@@ -51,10 +51,11 @@ gdImagePtr converter(const grid_t* grid){
gdImagePtr img = gdImageCreate(width, height);
int colors[256];
for(size_t i = 0; i < 255; i++){
- colors[i] = gdImageColorAllocate(img, 0, i, i/2);
+ colors[i] = gdImageColorAllocate(img, 0, 255-i, (255-i)/2);
}
colors[255] = gdImageColorAllocate(img, 0, 0, 0);
+
for(size_t y = 0; y < height; y++){
for(size_t x = 0; x < width; x++){
byte iteration = data[y * width + x];
@@ -82,7 +83,7 @@ void render_gif(FILE* output, const renderer_params* params){
gdImagePtr imgs[size];
imgs[0] = converter(grids[0]);
- gdImageGifAnimBegin(imgs[0], output, 1, -1);
+ gdImageGifAnimBegin(imgs[0], output, 1, 0);
gdImageGifAnimAdd(imgs[0], output, 0, 0, 0, delay, 1, NULL);
for(size_t i = 1; i < size; i++){