rparedis il y a 3 ans
Parent
commit
aeed224d9b

+ 3 - 2
README.md

@@ -27,8 +27,9 @@ pip install .
 python -m pip install .
 ```
 
-Note that these commands assume `python` and `pip` refer to either Python 2 or
-Python 3, depending on your system.
+Note that these commands assume `python` and `pip` refer to Python 3.
+
+**As of version 1.5, Python 2 is no longer supported.**
 
 _**Note:** Some editors allow you to "mark" a directory as a source root. Use
 this option in your favorite IDE to use the library in a project without the

+ 2 - 4
doc/CBD.converters.CBD2C.rst

@@ -1,7 +1,5 @@
 Generate C code from CBDs
 =========================
 
-.. automodule:: CBD.converters.CBD2C
-    :members:
-    :undoc-members:
-    :show-inheritance:
+This module has been extracted to the CBD2FMU generator project in order to minimize
+code duplication and dependency overhead.

+ 16 - 0
doc/changelog.rst

@@ -3,6 +3,22 @@ Changelog
 
 .. code-block:: text
 
+    Version 1.5
+        * Changed how ports work. Instead of using PortBlocks, a custom Port
+          (and Connection) class has been introduced.
+            - InputPortBlock, WireBlock and OutputPortBlock were removed.
+            * Flattening now ignores empty CBD blocks and in-between ports.
+        * Some functions have been renamed to have a more descriptive name.
+            * linkInput was changed to linkToInput
+            * getSignals was split to getOutputPortNames and getSignalHistory
+        * naivelog now uses the standard Python logging module.
+        * Changed realtime simulation to be used more efficiently.
+            * Pubsub structure now runs asynchronously.
+            * Tracing now happens asynchronously.
+        - Removed the CBD2C module to reduce code duplication w.r.t. the
+          CBD2FMU project.
+        + Plotting framework now works with Bokeh.
+
     Version 1.4
         + Added DeltaTBlock
         - Removed "delta_t" input port of IntegratorBlock and DerivatorBlock

+ 1 - 1
doc/conf.py

@@ -25,7 +25,7 @@ copyright = '2020, Randy Paredis'
 author = 'Randy Paredis'
 
 # The short X.Y version
-version = ''
+version = '1.5'
 # The full version, including alpha/beta/rc tags
 release = ''
 

+ 2 - 0
doc/index.rst

@@ -21,6 +21,8 @@ to model complex systems of equations.
 
 :Python Version: :code:`>= 3.4`
 
+.. versionchanged:: 1.5
+    Python 2 is no longer supported.
 
 .. note::
     This documentation is a mere description of the CBD modelling framework

+ 0 - 2
doc/install.rst

@@ -31,8 +31,6 @@ Next, there are some additional **optional** requirements:
     allow the creation of CBDs directly from a textual language.
   * `PythonPDEVS <http://msdl.cs.mcgill.ca/projects/DEVS/PythonPDEVS>`_ for the :mod:`CBD.converters.hybrid`
     module. This allows CBDs to be run inside of DEVS simulations.
-  * `Jinja2 <https://jinja.palletsprojects.com/en/3.0.x/>`_ for the :mod:`CBD.converters.CBD2C` module, allowing
-    conversion to C code.
 
 * **Documentation:**
 

+ 1 - 1
src/CBD/Core.py

@@ -533,7 +533,7 @@ class CBD(BaseBlock):
                             no blocks are ignored. Defaults to :code:`None`.
             psep (str):     The path separator to use. Defaults to :code:`"."`.
 
-        Note:
+        .. versionchanged:: 1.5
             When an empty CBD block is encountered during flattening, this block will be removed from
             the resulting flattened model. Add it to the :attr:`ignore` iterable to prevent such a
             removal.

+ 0 - 233
src/CBD/converters/CBD2C/__init__.py

@@ -1,233 +0,0 @@
-"""
-A module that allows the creation of a C file, in which the block's computations are inlined.
-Additional library files will be created to allow for linking:
-
-- lsolve.c
-- lsolve.h
-
-
-Requires `Jinja2 <https://jinja.palletsprojects.com/en/3.0.x/>`_.
-The :code:`template.c` file is the jinja template file.
-
-Note:
-	To compile the generated code, execute :code:`gcc <filename>.c lsolve.c -lm`.
-"""
-from CBD.scheduling import TopologicalScheduler
-from CBD.loopsolvers.linearsolver import LinearSolver
-from CBD.depGraph import createDepGraph
-from CBD.converters.latexify import CBD2Latex, Time
-import CBD.naivelog as naivelog
-from CBD.simulator import Simulator
-
-from jinja2 import Template
-from shutil import copyfile
-import os, re
-
-
-class CBD2C:
-	"""
-	Main conversion class. Generates the new C file.
-	The C model will be executed in fixed-time steps of size
-	:code:`delta`, for a total of :code:`itcnt` iterations.
-	In total, the simulation will thus execute until timestep
-	:code:`itcnt * delta`.
-
-	Note:
-		This class does **not** change the original model.
-
-	Warning:
-		This class only works if the dependency graph is fixed
-		after the first iteration. I.e., iteration 0 can be
-		different, but all others must be the same.
-
-	Args:
-		model (CBD):    CBD model that will be converted to C.
-		itcnt (int):    The amount of iterations to execute the
-						c model for.
-		delta (float):  The stepsize of the C code.
-	"""
-	def __init__(self, model, itcnt, delta=1.0):
-		self.itcnt = itcnt
-		self.delta = delta
-		self.model = model.clone()
-		self.model.flatten(psep='_')
-		for block in self.model.getBlocks():
-			block.setBlockName(block.getBlockName().replace("-", "_"))
-		self.scheduler = TopologicalScheduler()
-		self.solver = LinearSolver(naivelog.getLogger("CBD"))
-
-	def get_blocks(self):
-		"""
-		Gets all the blocks from the flattened model.
-		"""
-		return self.model.getBlocks()
-
-	def get_order(self, curIt):
-		"""
-		Gets the topological order of the blocks at a specific iteration.
-
-		Args:
-			curIt (int):
-		"""
-		depGraph = createDepGraph(self.model, curIt)
-		return self.scheduler.schedule(depGraph, curIt, 0.0)
-
-	def obtain_eqs_from_order(self, order, curIt):
-		"""
-		Given the order in which the blocks must be executed,
-		this function will use the :class:`CBD2Latex` class to
-		construct the C-representation for the functions.
-
-		Args:
-			order:          List of components, topologically ordered.
-			curIt (int):    The current iteration.
-
-		Returns:
-			A list of tuples like :code:`[([LHS, ...], RHS), ...]`;
-			where the :code:`LHS` identifies an ordered list of
-			left-hand sides (when there are multiple, it means an
-			algebraic loop); and :code:`RHS` the string-representation
-			of the results.
-		"""
-		conf = {
-			"path_sep": '_',
-			"ignore_path": False,
-			"escape_nonlatex": False,
-			"time_variable": "i",
-			"time_format": "[{time}]"
-		}
-		ltx = CBD2Latex(self.model, **conf)
-		eqs = [re.sub(r"-(?!\s*\d)", "_", x) for x in ltx.eq(Time(0, curIt == "i")).split("\n")]
-		if eqs[-1] == '':
-			eqs.pop()
-		res_order = []
-		# reverse the order to allow scheduling at end as well
-		for c in reversed(order):
-			c_order = []
-			if len(c) == 1:  # NO ALGEBRAIC LOOP
-				block = c[0]
-
-				# Assumes no special blocks that change the deps exist
-				deps = block.getDependencies(1 if curIt == "i" else curIt)
-				path = block.getPath("_")
-				for out in block.getSignals().keys():
-					p = path + "_" + out + "[%s]" % curIt
-					for e in eqs:
-						if e.startswith(p):
-							c_order.insert(0, e)
-							break
-				for inp in block.getInputPortNames():
-					p = path + "_" + inp + "[%s]" % curIt
-					in_deps = block.getBlockConnectedToInput(inp).block in deps
-					for e in eqs:
-						if e.startswith(p):
-							if in_deps:
-								c_order.insert(0, e)
-							else:
-								c_order.append(e)
-							break
-				if block.getBlockType() == "WireBlock":
-					for e in eqs:
-						if e.startswith(path + "[%s]" % curIt):
-							c_order.append(e)
-							break
-			else:  # ALGEBRAIC LOOP!
-				self.solver.checkValidity(self.model.getPath("."), c)
-				other = []
-				known = {}
-				for block in c:
-					path = block.getPath("_")
-					for inp, b in block.getLinksIn().items():
-						var = path + "_" + inp
-						p = var + "[%s]" % curIt
-						prev = block.getBlockConnectedToInput(inp).block
-						for e in eqs:
-							if e.startswith(p):
-								if prev not in c:
-									c_order.insert(0, e)
-									known[var] = p
-
-					for inp in block.getInputPortNames():
-						var = path + "_" + inp
-						if var in known: continue
-						p = var + "[%s]" % curIt
-						for e in eqs:
-							if e.startswith(p):
-								other.insert(0, e)
-								break
-
-				# Get matrix representation
-				m1, m2 = self.solver.get_matrix(c, '_', known)
-				mat = m1.concat(m2)
-
-				deps = {}
-				for b in c:
-					D = [b.getBlockConnectedToInput(x) for x in b.getInputPortNames()]
-					deps[b] = [b.block.getPath('_') + '_' + b.output_port for b in D if b.block in c]
-
-				if mat.rows == 1:
-					# TODO: fix this?
-					raise NotImplementedError("Suspected singular matrix. However, currently cannot find an example "
-					                          "that enters this branch. Please contact the repository owner with this "
-					                          "error and all associated files.")
-					# nc = ([deps[c[mat[0].index(1)]]], mat[0][-1])
-					# print("NC:", nc)
-				else:
-					dlist = []
-					for b in c:
-						for d in deps[b]:
-							if d not in dlist:
-								dlist.append(d)
-					sm = "{" + mat.format(', ', '{}', "%f", ', ').replace("{,", "{").replace(", }", " }") + "}"
-					nc = (dlist, sm)
-
-				c_order.append(nc)
-				c_order += other
-			res_order = c_order + res_order
-		return res_order
-
-	def generate(self, fname):
-		"""
-		Generates the C file and copies the sources for the
-		lsolve library in the same folder.
-
-		To compile the generated code, execute :code:`gcc <filename>.c lsolve.c -lm`.
-
-		Args:
-			fname (str):    The filename of the C-code.
-		"""
-		path = os.path.dirname(os.path.realpath(__file__))
-		tpath = os.path.dirname(os.path.realpath(fname))
-		filename = os.path.join(path, "template.c")
-		with open(filename, 'r') as file:
-			template = Template(file.read(), trim_blocks=True, lstrip_blocks=True)
-		if not os.path.exists(os.path.join(tpath, "lsolve.c")):
-			copyfile(os.path.join(path, "lsolve.c"), os.path.join(tpath, "lsolve.c"))
-		if not os.path.exists(os.path.join(tpath, "lsolve.h")):
-			copyfile(os.path.join(path, "lsolve.h"), os.path.join(tpath, "lsolve.h"))
-		variables = []
-		for block in self.get_blocks():
-			if block.getBlockType() == "WireBlock":
-				variables.append(block.getPath('_'))
-			for port in block.getSignals().keys():
-				variables.append(block.getPath('_') + '_' + port)
-			for port in block.getInputPortNames():
-				variables.append(block.getPath('_') + '_' + port)
-		variables = [v.replace("-", "_") for v in variables]
-
-		# Obtain the data
-		comp0 = self.get_order(0)
-		comp = self.get_order(1)
-
-		eqs0 = self.obtain_eqs_from_order(comp0, 0)
-		eqs = self.obtain_eqs_from_order(comp, "i")
-
-		contents = template.render(itcnt = self.itcnt,
-		                           filename = fname,
-		                           delta = self.delta,
-		                           variables = variables,
-		                           components0 = eqs0,
-		                           components = eqs )
-		with open(fname, 'w') as file:
-			file.write(contents)
-

BIN
src/CBD/converters/CBD2C/a.out


+ 0 - 100
src/CBD/converters/CBD2C/example.c

@@ -1,100 +0,0 @@
-/**
- *  Generated from the Python CBD Simulator
- *  In order to compile:
- *      gcc example.c lsolve.c -lm
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <time.h>
-#include "lsolve.h"
-
-#define M 14    /* No of Blocks */
-#define N 100    /* No of Iterations */
-
-/* BLOCK VARIABLE NAMES */
-#define test_sum_OUT1 RESULT[0]
-#define test_sum_IN1 RESULT[1]
-#define test_sum_IN2 RESULT[2]
-#define test_three_OUT1 RESULT[3]
-#define test_seven_OUT1 RESULT[4]
-#define test_mult_OUT1 RESULT[5]
-#define test_mult_IN1 RESULT[6]
-#define test_mult_IN2 RESULT[7]
-#define test_x RESULT[8]
-#define test_x_OUT1 RESULT[9]
-#define test_x_IN1 RESULT[10]
-#define test_y RESULT[11]
-#define test_y_OUT1 RESULT[12]
-#define test_y_IN1 RESULT[13]
-
-double RESULT[M][N];
-
-/* EQUATIONS */
-void _eq_init(const double time, const double delta) {
-    test_three_OUT1[0] = 3.0;
-    test_seven_OUT1[0] = 7;
-    test_sum_IN1[0] = test_three_OUT1[0];
-    test_mult_IN1[0] = test_seven_OUT1[0];
-
-    /* Algebraic Loop */
-    double _C4[2][3] = {{ -1.000000, 1 * test_mult_IN1[0] + 0, 0.000000 }, { 1.000000, -1.000000, 0 - test_sum_IN1[0] }};
-    agloop(&_C4, 2, &test_sum_OUT1[0], &test_mult_OUT1[0]);
-
-    test_sum_IN2[0] = test_mult_OUT1[0];
-    test_mult_IN2[0] = test_sum_OUT1[0];
-    test_x_IN1[0] = test_sum_OUT1[0];
-    test_x_OUT1[0] = test_x_IN1[0];
-    test_x[0] = test_x_OUT1[0];
-    test_y_IN1[0] = test_mult_OUT1[0];
-    test_y_OUT1[0] = test_y_IN1[0];
-    test_y[0] = test_y_OUT1[0];
-}
-
-void _eq_iter(const unsigned int i, const double time, const double delta) {
-    test_three_OUT1[i] = 3.0;
-    test_seven_OUT1[i] = 7;
-    test_sum_IN1[i] = test_three_OUT1[i];
-    test_mult_IN1[i] = test_seven_OUT1[i];
-
-    /* Algebraic Loop */
-    double _C4[2][3] = {{ -1.000000, 1 * test_mult_IN1[i] + 0, 0.000000 }, { 1.000000, -1.000000, 0 - test_sum_IN1[i] }};
-    agloop(&_C4, 2, &test_sum_OUT1[i], &test_mult_OUT1[i]);
-
-    test_sum_IN2[i] = test_mult_OUT1[i];
-    test_mult_IN2[i] = test_sum_OUT1[i];
-    test_x_IN1[i] = test_sum_OUT1[i];
-    test_x_OUT1[i] = test_x_IN1[i];
-    test_x[i] = test_x_OUT1[i];
-    test_y_IN1[i] = test_mult_OUT1[i];
-    test_y_OUT1[i] = test_y_IN1[i];
-    test_y[i] = test_y_OUT1[i];
-}
-
-/* SIMULATOR */
-int main(int argc, char *args[]) {
-    double delta = 1.0;
-    double time = 0.0;
-
-    _eq_init(0.0, delta);
-    for(int i = 1; i < N; ++i) {
-        time += delta;
-        _eq_iter(i, time, delta);
-    }
-
-    printf("\t%-20s = %12.4f\n", "TIME", time);
-    printf("\t%-20s = %12.4f\n", "test_sum_OUT1", test_sum_OUT1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_sum_IN1", test_sum_IN1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_sum_IN2", test_sum_IN2[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_three_OUT1", test_three_OUT1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_seven_OUT1", test_seven_OUT1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_mult_OUT1", test_mult_OUT1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_mult_IN1", test_mult_IN1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_mult_IN2", test_mult_IN2[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_x", test_x[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_x_OUT1", test_x_OUT1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_x_IN1", test_x_IN1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_y", test_y[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_y_OUT1", test_y_OUT1[N - 1]);
-    printf("\t%-20s = %12.4f\n", "test_y_IN1", test_y_IN1[N - 1]);
-}

+ 0 - 146
src/CBD/converters/CBD2C/lsolve.c

@@ -1,146 +0,0 @@
-#include <math.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include "lsolve.h"
-
-double getelm(double* matrix, const unsigned int i, const unsigned int j, const unsigned int m) {
-    const unsigned n = m + 1;
-    return *((matrix + i * n) + j);
-}
-
-void setelm(double* matrix, const unsigned i, const unsigned int j, const unsigned int m, double val) {
-    const unsigned n = m + 1;
-    *((matrix + i * n) + j) = val;
-}
-
-unsigned int argmax_abs(const unsigned int low, const unsigned int high, const unsigned int column, double* A) {
-    unsigned int i_max = 0;
-    double max_value = -1.0;  // computes the abs argmax, so always larger than -1
-    for(unsigned int i = low; i < high; ++i) {
-        double a = fabs(getelm(A, i, column, high));
-        if(a > max_value) {
-            max_value = a;
-            i_max = i;
-        }
-    }
-    return i_max;
-}
-
-void swrows(double* matrix, const unsigned int r1, const unsigned int r2, const unsigned int cols) {
-    if(r1 == r2) { return; }
-    double tmp;
-    for(unsigned int i = 0; i < cols; ++i) {
-        tmp = getelm(matrix, r2, i, cols - 1);
-        setelm(matrix, r2, i, cols - 1, getelm(matrix, r1, i, cols - 1));
-        setelm(matrix, r1, i, cols - 1, tmp);
-    }
-}
-
-void lsolve(double* matrix, const unsigned int size) {
-    const double eps = 1e-4;
-    const unsigned int m = size;        // rows
-    const unsigned int n = size + 1;    // columns
-    unsigned int h = 0;                 // pivot row
-    unsigned int k = 0;                 // pivot column
-
-    unsigned int* swaps = malloc(2 * sizeof(unsigned int));
-    int swaps_done = 0;
-
-    while(h < m && k < n) {
-        unsigned int i_max = argmax_abs(h, m, k, matrix);
-        double elm = getelm(matrix, i_max, k, m);
-        if(fabs(elm) <= eps) {
-            // Go to the next column
-            k += 1;
-        } else {
-            swrows(matrix, h, i_max, n);
-            for(unsigned int i = k; i < n; ++i) {
-                setelm(matrix, h, i, m, getelm(matrix, h, i, m) / elm);
-            }
-
-            for(unsigned int i = 0; i < m; ++i) {
-                if(i == h) { continue; }
-                double f = getelm(matrix, i, k, m) / getelm(matrix, h, k, m);
-                setelm(matrix, i, k, m, 0.0);
-                for(unsigned int j = k + 1; j < n; ++j) {
-                    setelm(matrix, i, j, m, getelm(matrix, i, j, m) - getelm(matrix, h, j, m) * f);
-                }
-            }
-
-            ++swaps_done;
-            swaps = realloc(swaps, (2 * swaps_done) * sizeof(unsigned int));
-            swaps[2 * (swaps_done - 1)] = h;
-            swaps[2 * (swaps_done - 1) + 1] = i_max;
-
-            h += 1;
-            k += 1;
-        }
-    }
-
-    for(int i = swaps_done - 1; i >= 0; --i) {
-        swrows(matrix, swaps[i * 2], swaps[i * 2 + 1], n);
-    }
-}
-
-double det(double* matrix, const unsigned int size) {
-    unsigned int height = size - 1;
-
-    if(size == 2) {
-        double a00 = getelm(matrix, 0, 0, size);
-        double a01 = getelm(matrix, 0, 1, size);
-        double a10 = getelm(matrix, 1, 0, size);
-        double a11 = getelm(matrix, 1, 1, size);
-        return (a00 * a11) - (a01 * a10);
-    }
-
-    double total = 0.0;
-    for(unsigned int fc = 0; fc < size; ++fc) {
-        double As[height][height];
-        for(unsigned int r = 0; r < height; ++r) {
-            for(unsigned int c = 0; c < fc; ++c) {
-                As[r][c] = getelm(matrix, r + 1, c, height);
-            }
-            for(unsigned int c = fc; c < height; ++c) {
-                As[r][c] = getelm(matrix, r + 1, c + 1, height);
-            }
-        }
-        double sign = -1.0;
-        if(fc % 2 == 1) {
-            sign = 1.0;
-        }
-        double sub_det = det(&As, height);
-        total += sign * getelm(matrix, 0, fc, height) * sub_det;
-    }
-    return total;
-}
-
-void agloop(double* A, const unsigned int size, ...) {
-    double D = det(A, size);
-    if(fabs(D) < 1e-5) {
-        printf("ERROR: SINGULAR MATRIX!\n");
-        exit(1);
-    }
-    lsolve(A, size);
-
-    // Read the arguments
-    va_list list;
-    va_start(list, size);
-    for(unsigned int j = 0; j < size; ++j) {
-        *va_arg(list, double*) = getelm(A, j, size, size);
-    }
-    va_end(list);
-}
-
-//int main(int argc, char *args[]) {
-//    double A[2][3] = {{-1.0, 7.0, 0.0}, {1.0, -1.0, -3.0}};
-//    lsolve(&A, 2);
-//
-//    printf("END\n");
-//    for(unsigned int i = 0; i < 2; ++i) {
-//        for(unsigned int j = 0; j < 3; ++j) {
-//            printf("\t%7f", A[i][j]);
-//        }
-//        printf("\n");
-//    }
-//}

+ 0 - 76
src/CBD/converters/CBD2C/lsolve.h

@@ -1,76 +0,0 @@
-#ifndef LSOLVE
-#define LSOLVE
-
-/**
- *  Obtains an element from a 2D array matrix, using pointers.
- *  This is mainly a helper function.
- *
- *  @param  matrix  An address to an (NxN+1) matrix, which is
- *                  to be constructed as a 2D array.
- *  @param  i       The row index of the element to obtain.
- *  @param  j       The column index of the element to obtain.
- *  @param  m       The amount of rows for the input matrix.
- **/
-double getelm(double* matrix, const unsigned int i, const unsigned int j, const unsigned int m);
-
-/**
- *  Sets an element in a 2D array matrix, using pointers.
- *  This is mainly a helper function.
- *
- *  @param  matrix  An address to an (NxN+1) matrix, which is
- *                  to be constructed as a 2D array.
- *  @param  i       The row index of the element to set.
- *  @param  j       The column index of the element to set.
- *  @param  m       The amount of rows for the input matrix.
- *  @param  val     The new value for the element.
- **/
-void setelm(double* matrix, const unsigned int i, const unsigned int j, const unsigned int m, double val);
-
-/**
- *  Computes the row index that yields the highest absolute value.
- *  This is mainly a helper function.
- *
- *  @param  low     The minimal row index to return.
- *  @param  high    The maximal row index to return.
- *  @param  A       An address to an (NxN+1) matrix, which is
- *                  to be constructed as a 2D array.
- **/
-unsigned int argmax_abs(const unsigned int low, const unsigned int high, const unsigned int column, double* A);
-
-/**
- *  Solves a system of equations linearly, by using matrices
- *  and Gauss-Jordan Elimination. Only works for N equations
- *  and N unknowns.
- *
- *  @param  matrix  An address to an (NxN+1) matrix, which is
- *                  to be constructed as a 2D array.
- *  @param  size    The amount of rows for the input matrix N.
- **/
-void lsolve(double* matrix, const unsigned int size);
-
-/**
- *  Computes the determinant of the matrix.
- *
- *  @param  matrix  An address to an (NxN) matrix, which is
- *                  to be constructed as a 2D array.
- *  @param  size    The amount of rows for the input matrix N.
- **/
-double det(double* matrix, const unsigned int size);
-
-/**
- *  Helper function to linearly solve algebraic loops.
- *  This first checks if the block matrix is not singular,
- *  after which it solves the equations w.r.t. Gauss-Jordan.
- *  Finally, the resulting matrix is automatically stored in
- *  the corresponding variables.
- *
- *  @param  A       An address to an (NxN+1) matrix, which is
- *                  to be constructed as a 2D array.
- *  @param  size    The amount of rows for the input matrix N.
- *  @param  ...     An undefined amount of arguments that refer
- *                  to the variables in which the data must be
- *                  stored in the end.
- **/
-void agloop(double* A, const unsigned int size, ...);
-
-#endif

+ 0 - 66
src/CBD/converters/CBD2C/template.c

@@ -1,66 +0,0 @@
-/**
- *  Generated from the Python CBD Simulator
- *  In order to compile:
- *      gcc {{ filename }} lsolve.c -lm
- */
-
-#include <math.h>
-#include <stdio.h>
-#include <time.h>
-#include "lsolve.h"
-
-#define M {{ variables|length }}    /* No of Blocks */
-#define N {{ itcnt }}    /* No of Iterations */
-
-/* BLOCK VARIABLE NAMES */
-{% for var in variables %}
-#define {{ var }} RESULT[{{ loop.index0 }}]
-{% endfor %}
-
-double RESULT[M][N];
-
-/* EQUATIONS */
-void _eq_init(const double time, const double delta) {
-    {% for comp in components0 %}
-        {% if comp is string %}
-    {{comp}};
-        {% else %}
-
-    /* Algebraic Loop */
-    double _C{{ loop.index0 }}[{{comp[0]|length}}][{{comp[0]|length + 1}}] = {{ comp[1] }};
-    agloop(&_C{{ loop.index0 }}, {{comp|length}}{% for block in comp[0] %}, &{{ block }}[0]{% endfor %});
-
-        {% endif %}
-    {% endfor %}
-}
-
-void _eq_iter(const unsigned int i, const double time, const double delta) {
-    {% for comp in components %}
-        {% if comp is string %}
-    {{comp}};
-        {% else %}
-
-    /* Algebraic Loop */
-    double _C{{ loop.index0 }}[{{comp[0]|length}}][{{comp[0]|length + 1}}] = {{ comp[1] }};
-    agloop(&_C{{ loop.index0 }}, {{comp|length}}{% for block in comp[0] %}, &{{ block }}[i]{% endfor %});
-
-        {% endif %}
-    {% endfor %}
-}
-
-/* SIMULATOR */
-int main(int argc, char *args[]) {
-    double delta = {{ delta }};
-    double time = 0.0;
-
-    _eq_init(0.0, delta);
-    for(int i = 1; i < N; ++i) {
-        time += delta;
-        _eq_iter(i, time, delta);
-    }
-
-    printf("\t%-20s = %12.4f\n", "TIME", time);
-    {% for var in variables %}
-    printf("\t%-20s = %12.4f\n", "{{ var }}", {{ var }}[N - 1]);
-    {% endfor %}
-}

+ 0 - 60
src/CBD/converters/CBD2C/template_old.c

@@ -1,60 +0,0 @@
-#include <math.h>
-#include <stdio.h>
-#include <time.h>
-#include "lsolve.h"
-
-#define M {{ variables|length }}    /* No of Blocks */
-#define N {{ itcnt }}    /* No of Iterations */
-
-/* BLOCK VARIABLE NAMES */
-{% for var in variables %}
-#define {{ var }} RESULT[{{ loop.index0 }}]
-{% endfor %}
-
-double RESULT[M][N];
-
-/* EQUATIONS */
-void _eq_init(const double time, const double delta) {
-    {% for comp in components0 %}
-        {% if comp[0]|length == 1 %}
-    {{ comp[0][0] }}[0] = {{ comp[1] }};
-        {% else %}
-
-    /* Algebraic Loop */
-    double _C{{ loop.index0 }}[{{comp[0]|length}}][{{comp[0]|length + 1}}] = {{ comp[1] }};
-    agloop(&_C{{ loop.index0 }}, {{comp|length}}{% for block in comp[0] %}, &{{ block }}[0]{% endfor %});
-
-        {% endif %}
-    {% endfor %}
-}
-
-void _eq_iter(const unsigned int i, const double time, const double delta) {
-    {% for comp in components %}
-        {% if comp[0]|length == 1 %}
-    {{ comp[0][0] }}[i] = {{ comp[1] }};
-        {% else %}
-
-    /* Algebraic Loop */
-    double _C{{ loop.index0 }}[{{comp[0]|length}}][{{comp[0]|length + 1}}] = {{ comp[1] }};
-    agloop(&_C{{ loop.index0 }}, {{comp|length}}{% for block in comp[0] %}, &{{ block }}[i]{% endfor %});
-
-        {% endif %}
-    {% endfor %}
-}
-
-/* SIMULATOR */
-int main(int argc, char *args[]) {
-    double delta = {{ delta }};
-    double time = 0.0;
-
-    _eq_init(0.0, delta);
-    for(int i = 1; i < N; ++i) {
-        time += delta;
-        _eq_iter(i, time, delta);
-    }
-
-    printf("\t%-20s = %12.4f\n", "TIME", time);
-    {% for var in variables %}
-    printf("\t%-20s = %12.4f\n", "{{ var }}", {{ var }}[N - 1]);
-    {% endfor %}
-}

+ 3 - 3
src/CBD/simulator.py

@@ -787,9 +787,9 @@ class Simulator:
 		Sets the verbose tracer.
 
 		Args:
-			filename (str): The file to which the trace must be written.
-							When :code:`None`, the trace will be written to
-							the console.
+			filename (Union[str, None]):    The file to which the trace must be written.
+											When :code:`None`, the trace will be written to
+											the console.
 
 		Note:
 			Calling this function multiple times will continuously add new tracers. Thus output