Skip to content
Snippets Groups Projects
Unverified Commit bded803a authored by Jamie Temple's avatar Jamie Temple
Browse files

feat: integratoren mit unit test

parent 5db126d6
Branches
No related tags found
No related merge requests found
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
};
\ No newline at end of file
module.exports = {
testEnvironment: 'node',
testRegex: '/tests/.*\\.(test|spec)?\\.(ts|tsx)$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node']
};
\ No newline at end of file
Source diff could not be displayed: it is too large. Options to address this: view the blob.
{
"name": "computergrafik-03",
"type": "module",
"type": "commonjs",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview"
"preview": "vite preview",
"test": "jest",
"coverage": "jest --coverage"
},
"devDependencies": {
"@babel/core": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
"@types/dat.gui": "^0.7.7",
"@types/jest": "^28.1.3",
"@types/three": "^0.139.0",
"tailwindcss": "^3.0.24",
"typescript": "^4.5.4",
"babel-jest": "^28.1.1",
"jest": "^28.1.1",
"typescript": "^4.7.4",
"vite": "^2.9.5"
},
"dependencies": {
"dat.gui": "^0.7.9",
"mathjs": "^10.6.4",
"three": "^0.139.2"
}
}
export function Euler(x: Array<number>, h: number, f: (x: Array<number>) => Array<number>): Array<number> {
let y = f(x);
let x_new = x.map((_, i) => x[i] + h * y[i]);
return x_new;
}
export function Midpoint(x: Array<number>, h: number, f: (x: Array<number>) => Array<number>): Array<number> {
let euler_step = Euler(x, h / 2, f);
let y = f(euler_step);
let x_new = x.map((_, i) => x[i] + h * y[i]);
return x_new;
}
export function Runge_Kutta(x: Array<number>, h: number, f: (x: Array<number>) => Array<number>): Array<number> {
let k1 = f(x);
let k2 = f(x.map((_, i) => x[i] + h / 2 * k1[i]));
let k3 = f(x.map((_, i) => x[i] + h / 2 * k2[i]));
let k4 = f(x.map((_, i) => x[i] + h * k3[i]));
let x_new = x.map((_, i) => x[i] + h / 6 * (k1[i] + 2 * k2[i] + 2 * k3[i] + k4[i]));
return x_new;
}
import * as Integrator from "../src/simulation/Integrators";
import * as math from "mathjs";
import * as fs from "fs";
// select a differential equation with a known solution
// format numbers to a fixed number of decimal places
function format_number(number: number, decimal_places: number): string {
return number.toFixed(decimal_places);
}
// find minimum for decimal places
function decimal_places(n: number): number {
let decimal_places = 0;
while (n < 1) {
n = n * 10;
decimal_places++;
}
return decimal_places+1;
}
function min_elem(arrs: Array<Array<number>>): number {
let min = arrs[0][0];
for (let i = 0; i < arrs.length; i++) {
for (let j = 0; j < arrs[i].length; j++) {
if (arrs[i][j] < min) {
min = arrs[i][j];
}
}
}
return min;
}
function write_table(result: Array<number>, exact: Array<number>, error: Array<number>, title: string, bins: number, decimal_places: number): void {
let table = [["x", "exact", "result", "error"]];
for (let i = 0; i < result.length; i++) {
table.push([format_number(i / bins, decimal_places), format_number(exact[i], decimal_places), format_number(result[i], decimal_places), format_number(error[i], decimal_places)]);
}
let table_string = "";
for (let i = 0; i < table.length; i++) {
for (let j = 0; j < table[i].length; j++) {
table_string += table[i][j];
if (j < table[i].length - 1) table_string += " | ";
}
table_string += "\n";
}
fs.writeFileSync(`${title}.txt`, table_string);
}
function calculate_error(result: Array<number>, exact: Array<number>): Array<number> {
let error: Array<number> = [];
for (let i = 0; i < result.length; i++) {
error.push(Math.abs(result[i] - exact[i]));
}
return error;
}
describe("Integrators", () => {
let k = 0.5
let c = 2
let g = (x: number): number => c * math.exp(-k * x);
let init_value = g(0);
// find the next y value for function g(x)
let f = (x: Array<number>): Array<number> => [-k * x[0]];
// compare values betwenn [0, 1]
let bins = 100;
let h = 1 / bins;
// calculate the exact solution
let exact: Array<number> = [];
for(let i = 0; i <= bins; i++) {
let x = i / bins;
let y = g(x);
exact.push(y);
}
// evaluation loop
function eval_func(integrator: (x: Array<number>, h: number, f: (x: Array<number>) => Array<number>) => Array<number>, init: number): Array<number> {
let result: Array<number> = [init];
let x = [init]
for(let i = 0; i < bins; i++) {
x = integrator(x, h, f);
result.push(x[0]);
}
return result;
}
let max_error = 0.1;
// calculate the Euler solution
it("Euler", () => {
let result = eval_func(Integrator.Euler, init_value);
let error = calculate_error(result, exact);
error.forEach((e, i) => { expect(e).toBeLessThan(max_error); });
write_table(result, exact, error, "Euler", bins, 5);
});
it("Midpoint", () => {
let result = eval_func(Integrator.Midpoint, init_value);
let error = calculate_error(result, exact);
error.forEach((e, i) => { expect(e).toBeLessThan(max_error); });
write_table(result, exact, error, "Midpoint", bins, 10);
});
it("Runge-Kutta", () => {
let result = eval_func(Integrator.Runge_Kutta, init_value);
let error = calculate_error(result, exact);
error.forEach((e, i) => { expect(e).toBeLessThan(max_error); });
write_table(result, exact, error, "Runge-Kutta", bins, 20);
});
});
\ No newline at end of file
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true
},
"include": ["src"]
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment