aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
blob: 01e5ef7ff454e73d178c36dbae43081fd032cf87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <diffeq.h>
#include <equations.h>
#include <types.h>

#define neqs 4
eqf_t eqfs[] = {f1, f2, f3, f4};

void help(const char *program, int exit_code) {
	printf("Usage:\n%s --method euler|rk4 [--equations <integer>] [--files <f1 f2 ... fn>] [--dt <number>] [--interval <start> <end>] [--init <num1 num2 ... num_n>]\n", program);
	puts(	"\t--method, -m:\twhich method to use, euler's method or 4th order Runge-Kutta method. Default: euler\n"
		"\t--equations, -e:\tAmount of equations. Optional, default 4\n"
		"\t--files, -f:\tSpecifies output files for approximations. Default: f1.data, f2.data, ...\n"
		"\t--dt, -t:\tApproximation step. default 0.1\n"
		"\t--range, -r:\tInterval of an approximation. defaults to '0 40'\n"
		"\t--init, -i:\tInitial conditions for problem at the start of an interval. Default: '0.1 -0.1 0.1 -0.1' ...\n"
		"\t--help, -h:\tThis message\n\n"
		"Note: -e MUST come before -f and -i. If not done so, amount of files will be determined incorrectly"
	);
	if (exit_code < 0) return;
	else exit(exit_code);
}

int main(int argc, char *argv[]) {
	i32 i, j, numeq = 4;
	f64 dt = 0.1, start = 0, end = 40;
	f64 * init = NULL;
	const char **files = NULL;
	void (*solver)(eqf_t*, f64*, const char**, usz, f64, f64, f64) = difeq_solve_euler;

	for (i = 1; i < argc; ++i) {
		if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i]))
			help(*argv, 0);
		if (!strcmp("-e", argv[i]) || !strcmp("--equations", argv[i]))
			numeq = atoi(argv[++i]);
		if (!strcmp("-t", argv[i]) || !strcmp("--dt", argv[i]))
			dt = atof(argv[++i]);
		if (!strcmp("-r", argv[i]) || !strcmp("--range", argv[i])) {
			start = atof(argv[++i]);
			end = atof(argv[++i]);
		}
		if (!strcmp("-i", argv[i]) || !strcmp("--init", argv[i])) {
			init = calloc(numeq, sizeof(f64));
			for (j = 0; j < numeq; ++j) init[j] = atof(argv[++i]);
		}
		if (!strcmp("-f", argv[i]) || !strcmp("--files", argv[i])) {
			files = calloc(numeq, sizeof(char*));
			for (j = 0; j < numeq; ++j) files[j] = argv[++i];
		}
		if (!strcmp("-m", argv[i]) || !strcmp("--method", argv[i])) {
			++i;
			if (!strcmp(argv[i], "euler")) {
				solver = difeq_solve_euler;
				continue;
			} 
			if (!strcmp(argv[i], "rk4")) {
				solver = difeq_solve_RK;
				continue;
			}
			printf("\x1b[91mError:\x1b[0mNo such method \"%s\". Available methods: \"euler\"\"rk4\". see --help for details.\n", argv[i]);
			return EXIT_FAILURE;
		}
	}
	
	if (numeq != neqs) {
		printf("\x1b[91mError:\x1b[0mCan not solve more than 4 equations without changing source code of main.");
		return EXIT_FAILURE;
	}
	if (files == NULL) {
		files = calloc(4, sizeof(char*));
		files[0] = "f1.data", files[1] = "f2.data",
		files[2] = "f3.data", files[3] = "f4.data";
	}
	if (init == NULL) {
		init = calloc(4, sizeof (double));
		init[0] = init[2] = 0.1,
		init[1] = init[3] = -0.1;
	}

	solver(eqfs, init, files, neqs, start, end, dt);
	puts("Done");
	
	free(init);
	free(files);
	return EXIT_SUCCESS;
}