Started Parallel Programming Self Assessment
authorSam Moore <[email protected]>
Thu, 2 Aug 2012 12:44:08 +0000 (20:44 +0800)
committerSam Moore <[email protected]>
Thu, 2 Aug 2012 12:44:08 +0000 (20:44 +0800)
It is an N-Body simulator. Fun!
Hopefully I don't fail my research project because of this module...

course/semester2/pprog/assignment0/Makefile [new file with mode: 0644]
course/semester2/pprog/assignment0/graphics.c [new file with mode: 0644]
course/semester2/pprog/assignment0/graphics.h [new file with mode: 0644]
course/semester2/pprog/assignment0/main.c [new file with mode: 0644]
course/semester2/pprog/assignment0/nbody.c [new file with mode: 0644]
course/semester2/pprog/assignment0/nbody.h [new file with mode: 0644]

diff --git a/course/semester2/pprog/assignment0/Makefile b/course/semester2/pprog/assignment0/Makefile
new file mode 100644 (file)
index 0000000..538a0fa
--- /dev/null
@@ -0,0 +1,22 @@
+#Makefile for nbody program
+
+CXX = gcc --std=c99 -Wall -pedantic  -g -lm -lSDL -lGL
+OBJ = main.o nbody.o graphics.o
+
+BIN = nbody
+
+
+
+$(BIN) : $(OBJ) 
+       $(CXX) -o $(BIN) $(OBJ)
+
+%.o : %.c %.h
+       $(CXX) -c $<
+
+clean :
+       $(RM) $(BIN) $(OBJ) $(LINKOBJ)
+
+clean_full: #cleans up all backup files
+       $(RM) $(BIN) $(OBJ) $(LINKOBJ)
+       $(RM) *.*~
+       $(RM) *~
diff --git a/course/semester2/pprog/assignment0/graphics.c b/course/semester2/pprog/assignment0/graphics.c
new file mode 100644 (file)
index 0000000..747e399
--- /dev/null
@@ -0,0 +1,170 @@
+/**
+ * @file graphics.c
+ * @purpose Wrapper for SDL and OpenGL graphics libraries. Used for N-Body simulator. Implementations. Mostly copied from internet tutorials.
+ * @author Sam Moore
+ * @date August 2012
+ */
+
+
+
+#include "graphics.h"
+
+#include <math.h> //For trig functions
+
+/**
+ * @function Graphics_Init
+ * @purpose Initialise the SDL/OpenGL graphics system
+ * @param caption - The caption to give the view window
+ * @param w - The width of the view window
+ * @param h - The height of the view window
+ */ 
+void Graphics_Init(const char * caption, int w, int h)
+{
+       if (SDL_Init(SDL_INIT_VIDEO) != 0)
+       {
+               fprintf(stderr, "Graphics_Init - Couldn't initialise SDL! SDL_GetError() = %s\n",SDL_GetError());
+               exit(EXIT_FAILURE);
+       }
+
+       SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 
+
+       SDL_Surface * screen = SDL_SetVideoMode(w,h, 32, SDL_OPENGL);
+       if ( screen == NULL )
+       {
+               fprintf(stderr, "Graphics_Init - Couldn't set SDL VideoMode (%d x %d x 32). SDL_GetError() = %s\n", w, h, SDL_GetError());
+               exit(EXIT_FAILURE);
+       } 
+
+       glEnable(GL_TEXTURE_2D);
+       glClearColor(0,0,0,0);
+       glViewport(0,0,w,h);    //DOES matter
+       glClear(GL_COLOR_BUFFER_BIT);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glOrtho(0,w,h,0,-1,1);
+       glMatrixMode(GL_MODELVIEW);
+       glLoadIdentity();
+       glDisable(GL_DEPTH_TEST);
+       SDL_WM_SetCaption(caption, NULL);
+
+       atexit(Graphics_Destroy);
+}
+
+/**
+ * @function Graphics_Destroy
+ * @purpose Destroy the Graphics system
+ *             Note: Just wrap to SDL_Quit for now
+ */
+void Graphics_Destroy()
+{
+       SDL_Quit();
+}
+
+/**
+ * @function Graphics_DrawPixel
+ * @purpose Draw a pixel 
+ * @param x[...] Position of pixel
+ * @param r - Red component (0-1)
+ * @param g - Green component (0-1)
+ * @param b - Blue component (0-1)
+ */
+void Graphics_Pixel(int x[DIMENSIONS], float r, float g, float b)
+{
+       glBegin(GL_POINTS);
+       glColor3f(r, g, b);
+       if (DIMENSIONS == 2)
+               glVertex2f(x[0], x[1]); 
+       else if (DIMENSIONS == 3)
+               glVertex3f(x[0], x[1], x[2]);
+       else
+       {
+               fprintf(stderr, "Graphics_DrawPixel - DIMENSIONS = %d, expected 2 or 3\n", DIMENSIONS);
+               exit(EXIT_FAILURE);
+       }
+
+       glColor3f(1,1,1);
+       glEnd();
+}
+
+/**
+ * @function Graphics_DrawLine
+ * @purpose Draw a straight line between two points
+ * @param x1[...] - First coordinate
+ * @param x2[...] - Second coordinate
+ * @param r - Red component (0-1)
+ * @param g - Green component (0-1)
+ * @param b - Blue component (0-1)
+ */
+void Graphics_Line(int x1[DIMENSIONS], int x2[DIMENSIONS], float r, float g, float b)
+{              
+
+       glColor3f(r, g, b);
+       glBegin(GL_LINES);
+       if (DIMENSIONS == 2)
+       {
+               glVertex2f(x1[0], x1[1]); // origin of the line
+               glVertex2f(x2[0], x2[1]); // ending point of the line
+       }
+       else if (DIMENSIONS == 3)
+       {
+               glVertex3f(x1[0], x1[1], x1[2]); // origin of the line
+               glVertex3f(x2[0], x2[1], x2[2]); // ending point of the line
+       }
+       else
+       {
+               fprintf(stderr, "Graphics_DrawLine - DIMENSIONS = %d, expected 2 or 3\n", DIMENSIONS);
+               exit(EXIT_FAILURE);             
+       }
+       glColor3f(1,1,1);
+       glEnd();
+
+       
+}
+
+/**
+ * @function Graphics_Circle
+ * @purpose Draw a 2D Circle (filled)
+ * @param x[...] Position to draw at
+ * @param radius - Radius of circle
+ * @param r - Red component (0-1)
+ * @param g - Green component (0-1)
+ * @param b - Blue component (0-1)
+ */
+
+void Graphics_Circle(int x[2], float radius, float r, float g, float b)
+{
+       glColor3f(r, g, b);
+
+       glBegin(GL_TRIANGLE_FAN);
+       glVertex2f(x[0], x[1]);
+       for (float angle = 0; angle < 360; angle+=1)
+       {
+               glVertex2f(x[0] + sin(angle) * radius, x[1] + cos(angle) * radius);
+       }
+       glColor3f(1, 1, 1);
+       glEnd();
+}
+/**
+ * @function Graphics_Clear
+ * @purpose Clear the screen
+ * @param r - Red component of clear colour
+ * @param g - Green component
+ * @param b - Blue component
+ */
+void Graphics_Clear(float r, float g, float b)
+{
+       glClearColor(r,g,b,1);
+       glClear(GL_COLOR_BUFFER_BIT);
+}
+
+/**
+ * @function Graphics_Update
+ * @purpose Update the screen
+ */
+void Graphics_Update()
+{
+       SDL_GL_SwapBuffers();
+       //SDL_Flip(screen);
+}
+
diff --git a/course/semester2/pprog/assignment0/graphics.h b/course/semester2/pprog/assignment0/graphics.h
new file mode 100644 (file)
index 0000000..f977bd9
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * @file graphics.h
+ * @purpose Wrapper to the SDL and OpenGL libraries, used for N-Body simulator. Declarations.
+ * @author Sam Moore
+ * @date August 2012
+ */
+
+#ifndef _GRAPHICS_H
+#define _GRAPHICS_H
+
+#include <stdlib.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_opengl.h>
+
+#ifndef DIMENSIONS //Check so that DIMENSIONS can be defined elsewhere (ie in "nbody.h")
+       #define DIMENSIONS 2 
+#endif //DIMENSIONS
+
+
+void Graphics_Init(const char * caption, int w, int h); //Initialise graphics
+void Graphics_Destroy(); //Destroy graphics
+void Graphics_Update(); //Update view
+void Graphics_Clear(float r, float g, float b); //Clear screen
+void Graphics_Pixel(int x[DIMENSIONS], float r, float g, float b); //Draw single pixel
+void Graphics_Line(int x1[DIMENSIONS], int x2[DIMENSIONS], float r, float g, float b); //Draw straight line
+void Graphics_Circle(int x[2], float radius, float r, float g, float b); //Draw circle
+
+
+
+void Graphics_DrawPixel(int x[DIMENSIONS], float r, float g, float b);
+
+
+#endif //_GRAPHICS_H
+
+//EOF
diff --git a/course/semester2/pprog/assignment0/main.c b/course/semester2/pprog/assignment0/main.c
new file mode 100644 (file)
index 0000000..c335790
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * @file main.c
+ * @purpose Main program for N-Body simulator (single threaded)
+ * @author Sam Moore
+ * @date August 2012
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include "nbody.h"
+
+int main(int argc, char ** argv)
+{
+
+       System system;
+       System_Init(&system, (float[3]){320,240,0}, 0.1, 10, 1);
+       #ifdef _GRAPHICS_H
+               Graphics_Init("N-Body", 640, 480);
+       #endif //_GRAPHICS_H
+
+       assert(System_AddBody(&system, 1, (float[2]){0.0f,0.0f}, (float[2]){0.0f,0.0f})->exists);
+       assert(System_AddBody(&system, 0.01, (float[2]){120.0f, -120.0f}, (float[2]){-1.1f, 1.0f})->exists);
+       while (true)
+       {
+
+               System_Step(&system);
+               //System_WriteData(&system, stdout);
+               #ifdef _GRAPHICS_H
+                       Graphics_Clear(1, 1, 1); //Clear screen
+                       System_Draw(&system); //Draw system
+                       Graphics_Update(); //Update screen
+                       Process_Events(); //Process SDL events
+               #endif //_GRAPHICS_H
+
+       }
+       System_Destroy(&system);
+       return 0;
+}
+
diff --git a/course/semester2/pprog/assignment0/nbody.c b/course/semester2/pprog/assignment0/nbody.c
new file mode 100644 (file)
index 0000000..6f3ce50
--- /dev/null
@@ -0,0 +1,343 @@
+/**
+ * @file nbody.c
+ * @purpose Implementations for N-Body simulator
+ * @author Sam Moore
+ * @date August 2012
+ */
+
+#include <assert.h> // To make sure I don't do anything stupid.
+#include <math.h> //For maths and stuff
+#include <stdio.h> //For writing data to files
+#include "nbody.h" //Declarations of functions and structures in this file
+
+// --- Body functions --- //
+
+/**
+ * @function Body_Init
+ * @purpose Initialise a Body object with mass, position and velocity
+ * @param body - Target Body
+ * @param m - The mass of the Body
+ * @param x[...] - The position vector of the body
+ * @param v[...] - The velocity vector of the body
+ */
+void Body_Init(Body * body, float m, float x[DIMENSIONS], float v[DIMENSIONS])
+{
+       assert(body != NULL);
+       body->m = m;
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+       {
+               body->x[i] = x[i];
+               body->v[i] = v[i];
+               body->F[i] = 0.00;
+       }
+       body->exists = true;
+}
+
+/**
+ * @function Body_Destroy
+ * @purpose Destroy a Body
+ * @param body - Target Body
+ */
+void Body_Destroy(Body * body)
+{
+       assert(body != NULL);
+       body->exists = false;
+}
+
+/**
+ * @function Body_Step
+ * @purpose Perform a single step, updating target Body
+ * @param body - Target Body
+ * @param system - System that the Body is part of (used for universal constants, etc)
+ */
+void Body_Step(Body * body, System * system)
+{
+       assert(body != NULL && system != NULL && body->exists);
+
+       //fprintf(stderr, "DEBUG - Body %p\t%d\n", (void*)(body), body->exists);
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+       {
+               body->x[i] += body->v[i] * system->dt; //Update the position vector
+               body->v[i] += (body->F[i] / body->m) * system->dt; //Update the velocity vector
+               body->F[i] = 0.00; //Reset the net force vector
+       }
+
+       //Do collision checking
+       
+}
+
+/**
+ * @function Body_Force
+ * @purpose Update the net force on Body A due to Body B
+ * @param A - Body to update; subject of force from B
+ * @param B - Body causing force on A; NOT CHANGED BY THIS FUNCTION
+ * @param system - System which Body A is a part of (used for universal constants, etc)
+ */
+void Body_Force(Body * A, Body * B, System * system)
+{
+       
+       assert(A != NULL && B != NULL && system != NULL && A->exists && B->exists);
+       if (A == B)
+               return;
+       
+       float r2 = 0.00;
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               r2 += powf((B->x[i] - A->x[i]), 2);
+
+       float k = system->G * (A->m * B->m) / powf(r2, 1.50);
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               A->F[i] += k * (B->x[i] - A->x[i]);
+       
+}      
+
+/**
+ * @function Body_Radius
+ * @purpose Calculate the radius of a body
+ * @param body - Target Body
+ * @returns The radius of body
+ */
+float Body_Radius(Body * body)
+{
+       assert(body != NULL && body->exists);
+       float radius = 5.0;
+       return radius;
+}
+
+/**
+ * @function Body_WriteData
+ * @purpose Write data about the Body to a file
+ * @param body - The target Body
+ * @param system - System to which the Body belongs
+ * @param file - File to write data to
+ */
+void Body_WriteData(Body * body, System * system, FILE * file)
+{
+       assert(body != NULL && system != NULL && file != NULL && body->exists);
+       fprintf(file,"%d\t%p\t%f", system->step, (void*)(body), body->m);
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               fprintf(file,"\t%f", body->x[i]);
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               fprintf(file,"\t%f", body->v[i]);
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               fprintf(file,"\t%f", body->F[i]);
+
+       fprintf(file,"\n");
+
+}
+
+// --- System functions --- //
+
+/**
+ * @function System_Init
+ * @purpose Initialise a System object
+ * @param system - Target System
+ * @param x - The origin of the System (currently used for offset of graphics)
+ * @param dt - Time step
+ * @param G - Universal Gravitational Constant
+ * @param nMax - Number of Body objects this System will contain (DEFAULT = 10)
+ */
+void System_Init(System * system, float x[DIMENSIONS], float dt, float G, unsigned nMax)
+{
+       assert(system != NULL);
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               system->x[i] = x[i];
+
+       
+       system->dt = dt;
+       system->G = G;
+       system->nMax = nMax;
+       system->n = 0;
+       
+       system->bodies = (Body*)(calloc(sizeof(Body), nMax)); //Allocate space for nMax bodies
+       for (unsigned a = 0; a < nMax; ++a)
+               (system->bodies+a)->exists = false;
+}
+
+/**
+ * @function System_Destroy
+ * @purpose Destroy all Bodies in a system
+ * @param system - Target system
+ */
+
+void System_Destroy(System * system)
+{
+       assert(system != NULL);
+       if (system->bodies != NULL)
+               free(system->bodies);
+       system->nMax = 0;
+}
+
+/**
+ * @function System_Step
+ * @purpose Compute single step for all Bodies in System
+ * @param system - Target system
+ */
+void System_Step(System * system)
+{
+       assert(system != NULL);
+
+       // Update forces
+       for (unsigned a = 0; a < system->nMax; ++a)
+       {
+               if (system->bodies[a].exists)
+               {
+                       for (unsigned b = 0; b < system->nMax; ++b)
+                       {
+                               //fprintf(stderr, "DEBUG1 - %p\t%p\t%d\t%d\n", (void*)(system->bodies+a), (void*)(system->bodies+b), system->bodies[a].exists, system->bodies[b].exists);
+                               if (system->bodies[b].exists)
+                               {
+                                       //fprintf(stderr, "DEBUG2 - %p\t%p\t%d\t%d\n", (void*)(system->bodies+a), (void*)(system->bodies+b), system->bodies[a].exists, system->bodies[b].exists);
+                                       Body_Force(&(system->bodies[a]), &(system->bodies[b]), system); //Update force on bodies[a] due to bodies[b]
+                                       //fprintf(stderr, "DEBUG3 - %p\t%p\t%d\t%d\n", (void*)(system->bodies+a), (void*)(system->bodies+b), system->bodies[a].exists, system->bodies[b].exists);
+                               }
+                       }
+               }
+       }
+
+       // Perform steps
+       for (unsigned a = 0; a < system->nMax; ++a)
+       {
+               if ((system->bodies+a)->exists)
+                       Body_Step(system->bodies+a, system);
+       }
+}
+
+/**
+ * @function System_AddBody
+ * @purpose Add a Body to a System. Resizes the System's bodies array if necessary.
+ * @param system - Target System
+ * @param m - Mass of the new Body
+ * @param x[...] - position vector for the new Body
+ * @param v[...] - velocity vector for the new Body
+ * @returns Pointer to new Body
+ */
+
+Body * System_AddBody(System * system, float m, float x[DIMENSIONS], float v[DIMENSIONS])
+{
+       assert(system != NULL);
+
+       unsigned a = 0;
+       for (a = 0; a < system->nMax; ++a)
+       {
+               if (!(system->bodies+a)->exists)
+                       break;
+       }
+       
+       if (a >= system->nMax)
+       {
+               system->nMax = (system->nMax+1) * 2;
+               system->bodies = (Body*)(realloc(system->bodies, sizeof(Body) * system->nMax));
+               for (unsigned b = a; b < system->nMax; ++b)
+                       (system->bodies+b)->exists = false;
+       }
+
+       Body_Init(system->bodies+a, m, x, v);
+       system->n += 1;
+
+       return (system->bodies+a);
+       
+}
+
+/**
+ * @function System_WriteData
+ * @purpose Write all information about System to a file
+ * @param system - Target System
+ * @param file - Target FILE (must be opened for writing)
+ */
+void System_WriteData(System * system, FILE * file)
+{
+       assert(system != NULL && file != NULL);
+       for (unsigned a = 0; a < system->nMax; ++a)
+       {
+               if ((system->bodies+a)->exists)
+                       Body_WriteData(system->bodies+a, system, file);
+       }
+       fprintf(file, "\n");
+
+}
+
+// --- Graphical functions --- //
+
+#ifdef _GRAPHICS_H
+
+/**
+ * @function Body_Draw
+ * @purpose Draw an individual Body
+ * @param body - Target Body
+ * @param system - System to which the Body belongs
+ */
+
+void Body_Draw(Body * body, System * system)
+{
+       assert(body != NULL && system != NULL && body->exists);
+       int pixel_pos[DIMENSIONS];
+       for (unsigned i = 0; i < DIMENSIONS; ++i)
+               pixel_pos[i] = (int)(system->x[i] - body->x[i]);
+
+       float rgb[3] = {0.0f, 0.0f, 0.0f};
+       if (body->m >= 100.0)
+       {
+               rgb[0] = 0.0f; rgb[1] = 0.0f; rgb[2] = 1.0f;
+       }
+       if (body->m >= 10.0)
+       {
+               rgb[0] = 0.5f; rgb[1] = 0.5f; rgb[2] = 1.0f;
+       }
+       else if (body->m >= 1.0)
+       {
+               rgb[0] = 0.8f; rgb[1] = 0.2f; rgb[2] = 0.1f;
+       }
+       else if (body->m >= 0.1)
+       {
+               rgb[0] = 0.0f; rgb[1] = 0.5f; rgb[2] = 0.0f;            
+       }
+       else if (body->m >= 0.01)
+       {
+               rgb[0] = 0.5f; rgb[1] = 0.5f; rgb[2] = 0.5f;
+       }
+
+
+       Graphics_Circle(pixel_pos,Body_Radius(body), rgb[0], rgb[1], rgb[2]);
+
+       //fprintf(stdout, "DEBUG - Body_Draw - Called\n");
+}
+
+/**
+ * @function System_Draw
+ * @purpose Draw a System of Bodies
+ * @param system - Target System to draw
+ */
+void System_Draw(System * system)
+{
+       assert(system != NULL);
+       for (unsigned a = 0; a < system->nMax; ++a)
+       {
+               if ((system->bodies+a)->exists)
+                       Body_Draw(system->bodies+a, system);
+       }
+}
+
+/**
+ * @function Process_Events
+ * @purpose Handle any SDL events recieved.
+ */
+void Process_Events()
+{
+       SDL_Event event;
+       while (SDL_PollEvent(&event)) 
+       {
+               switch(event.type)
+               {
+                       case SDL_QUIT:
+                               exit(EXIT_SUCCESS);
+                               break;
+               }
+       }
+       //SDL_Delay(1);
+}
+
+#endif //_GRAPHICS_H
+
+//EOF
+
+
diff --git a/course/semester2/pprog/assignment0/nbody.h b/course/semester2/pprog/assignment0/nbody.h
new file mode 100644 (file)
index 0000000..775699f
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ * @file nbody.h
+ * @purpose Declarations for N-Body simulator
+ * @author Sam Moore
+ * @date August 2012
+ */
+
+#ifndef _NBODY_H
+#define _NBODY_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include "graphics.h" //TODO: Comment out this line to build the program without any graphics at all
+
+#define DIMENSIONS 2 //Number of dimensions to use in the simulation (2 or 3)
+
+/** 
+ * Structure to represent a single Body
+ */
+
+typedef struct
+{
+       float m; //Mass
+       float x[DIMENSIONS]; //Position vector
+       float v[DIMENSIONS]; //Velocity vector
+       float F[DIMENSIONS]; //Net force due to all other bodies in the System
+
+       bool exists; //Used by memory management
+} Body;
+
+/**
+ * Structure to represent a system of N Bodies
+ */
+typedef struct
+{
+       Body * bodies; //Array of Bodies
+       unsigned nMax; //Size of array; maximum number of Bodies before Array needs to be resized
+       unsigned n; //Number of bodies currently in the system
+       float G; //Universal Gravitational Constant; used to calculate forces between Bodies
+
+       float dt; //Time interval
+       unsigned step; //Number of steps executed by the System
+
+       float x[DIMENSIONS]; //The origin of the system
+
+} System;
+
+/**
+ * Functions for operating with Body objects
+ */
+extern void Body_Init(Body * body, float m, float x[DIMENSIONS], float v[DIMENSIONS]); //Initialise Body
+extern void Body_Destroy(Body * body); //Destroy Body
+extern void Body_Step(Body * body, System * system); //Step Body
+extern void Body_Force(Body * A, Body * B, System * system); //Calculate Force between Bodies
+
+
+/**
+ * Functions for operating with System object
+ */
+extern void System_Init(System * system, float x[DIMENSIONS], float dt, float G, unsigned nMax); //Initialise System
+extern void System_Destroy(System * system); //Destroy System
+extern void System_Step(System * system); //Step all Bodies in System
+extern Body * System_AddBody(System * system, float m, float x[DIMENSIONS], float v[DIMENSIONS]); //Add Body to System
+extern void System_RemoveBody(System * system, Body * body); //
+extern void System_MergeBodies(System * system, Body * A, Body * B);
+extern void System_WriteData(System * system, FILE * file); //Write System info to a file
+
+
+/**
+ * Functions to be used when "graphics.h" is included
+ */
+
+#ifdef _GRAPHICS_H
+       extern void System_Draw(System * system); //Draw a System of Bodies
+       extern void Body_Draw(Body * body, System * system); //Draw an individual Body
+
+       extern void Process_Events(); //Handle any events from the SDL system
+#endif //_GRAPHICS_H
+
+
+
+#endif //_NBODY_H
+
+//EOF

UCC git Repository :: git.ucc.asn.au