summaryrefslogtreecommitdiffstats
path: root/fiz/naloga/numerično.c
blob: c1ca08cbb8bba6dfbfad728833908eea3a14547e (plain) (blame)
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#include <stdlib.h>
#include <stdio.h>
#include <error.h>
#include <math.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#define UVOD "program za numerični izračun jakosti magnetnega polja okoli helmholtzove tuljave\n" \
	"sem spisal anton luka šijanec za projektno nalogo pri fiziki v tretjem letniku gimb.\n" \
	"uporaba: %s	in nujni argumenti po vrsti:\n" \
	"	1. radij enega navitja v metrih\n" \
	"	2. tok, ki teče po vodniku v amperih\n" \
	"	3. število navojev na enem navitju\n" \
	"	4. razmak med merilnimi točkami v metrih\n" \
	"	5. koliko meritev od središča v obe dimenziji naj napravimo\n" \
	"	6. koliko kotov naj ima navitje - računamo, kot da je mnogokotnik\n" \
	"nenujni argumenti: prazen niz argument nastavi na privzeto vrednost.\n" \
	"	7. tip izhodnih podatkov (pgm, ppm ali tsv). privzeto je to pgm.\n" \
	"	8. razmak med navitjima. privzeto je to r/2.\n" \
	"	9. zamik enega navitja v metrih. privzeto sta osi navitij ista premica.\n" \
	"	A. polmer druge tuljave. privzeto je enak polmeru prve tuljave.\n" \
	"	B. tok druge tuljave v metrih. privzeto je enak toku prve tuljave.\n" \
	"oblika izhodnih podatkov, če je 7. parameter pgm, so pgm slike z vrednostmi 0-255\n" \
	"	- slika je prerez tuljave. magnetno polje teče vodoravno.\n" \
	"	- vrednosti direktno korelirajo z izračunano jakostjo v decigaussih: 10e-5 tesla\n" \
	"	- slika je široka 1+2*koliko in visoka 1+2*koliko (5. argument) slikovnih točk\n" \
	"oblika izhodnih podatkov, če je 7. parameter ppm, so barvne slike z 8 biti na barvo\n" \
	"	- barvi rdeča in zelena predstavljata komponenti vektorjev polja i in j\n" \
	"oblika izhodnih podatkov, če je 7. parameter tsv, je tsv, z naslednjimi stolpci:\n" \
	"	1. komponenta i krajevnega vektorja točke meritve. 0,0 je v središču tuljave.\n" \
	"	2. komponenta j krajevnega vektorja točke meritve. 0,0 je v središču tuljave.\n" \
	"	3. komponenta i vektorja magnetnega polja v točki meritve.\n" \
	"	4. komponenta j vektorja magnetnega polja v točki meritve.\n" \
	"	5. jakost magnetnega polja v teslah - tokrat ni v decigaussih!\n" \
	"način izdelave animacije: podan naj bo samo en argument - animacija - TOLE NE DELA\n" \
	"	- delajo se datoteke animacija0000.ppm, animacija0001.ppm, ...\n" \
	"	- parametri se sinusoidno spreminjajo po vdelanih konstantah.\n" \
	"	- slike lahko recimo s ffmpeg(1) nato pretvorite v videoposnetek."
enum oblika {
	PGM,
	PPM,
	TSV,
	ANIMACIJA
};
struct vektor {
	long double i; // x - desno na sliki
	long double j; // y - gor na sliki
	long double k; // z - v monitor
};
struct vektor seštej (struct vektor a, struct vektor b) {
	struct vektor r = {
		.i = a.i + b.i,
		.j = a.j + b.j,
		.k = a.k + b.k,
	};
	return r;
}
struct vektor vektorski_produkt (struct vektor a, struct vektor b) {	// ne bom implementiral
	struct vektor r = {						// matrik
		.i = a.j*b.k - a.k*b.j,
		.j = a.k*b.i - a.i*b.k,
		.k = a.i*b.j - a.j*b.i
	};
	return r;
}
struct vektor množi (struct vektor a, long double d) {
	struct vektor r = {
		.i = a.i * d,
		.j = a.j * d,
		.k = a.k * d
	};
	return r;
}
long double absolutno (struct vektor a) {
	return sqrtl(a.i*a.i+a.j*a.j+a.k*a.k);
}
#define MU0 4e-6*M_PI
struct vektor tuljava (long double R,	unsigned kotov, struct vektor m /* meritev - krajevni */) {
	long double dl_abs = 2*M_PI*R/kotov;	// metri - dolžina vodnika
	long double dr = 2*M_PI/kotov;		// radiani - kot med dl in točko na (0,R - vrh zanke)
	struct vektor B = {
		.i = 0,
		.j = 0,
		.k = 0
	};
	for (unsigned i = 0; i < kotov; i++) {
		long double theta = dr*i;	// kot na krogu
		struct vektor dl;
		dl.j = cosl(theta)*dl_abs;
		dl.k = -sinl(theta)*dl_abs;	// minus po skici sodeč ://of.sijanec.eu/sfu/skic.jpg
		dl.i = 0;			// sicer je vseeno, m je na z = 0 in gledamo vse
		struct vektor r;
		r.i = 0;
		r.j = sinl(theta)*R;
		r.k = cosl(theta)*R;
		r = seštej(r, m);
		B =	seštej(B,
				množi(
					vektorski_produkt(dl, r),
					1/(absolutno(r)*absolutno(r)*absolutno(r))
				)
			);
	}
	B = množi(B, MU0/(4*M_PI));
	return B;
} // ena zanka ob toku 1 A. pomnoži s tokom in številom navitij. 0,0 je v sredini. B teče v desno.
struct vektor zavrti_okoli (struct vektor točka, struct vektor središče, long double kot) {
	točka = seštej(točka, množi(središče, -1));
	struct vektor r = {
		.i = cosl(kot)*točka.i + sin(kot)*točka.j,
		.j = cosl(kot)*točka.j - sin(kot)*točka.i
	};
	return seštej(r, središče);
} // TODO: implement
void natisni (FILE * f, struct vektor v, const char * i) {
	fprintf(f, "vektor %s {\n\t.i = %Lf,\n\t.j = %Lf,\n\t.k = %Lf\n}\n", i, v.i, v.j, v.k);
}
int nariši (long double R, long double I, unsigned n, long double razmak, int koliko,
		unsigned kotov, enum oblika oblika, long double med_tuljavama,
		struct vektor zamik_izven_osi, long double R2, long double I2, FILE * out) {
	struct vektor merilno_mesto = {	// krajevni vektor
		.k = 0
	};
	if (oblika == PGM)
		fprintf(out, "P5 %u %u 255\n", koliko*2+1, koliko*2+1);
	if (oblika == PPM)
		fprintf(out, "P6 %u %u 255\n", koliko*2+1, koliko*2+1);
	struct vektor Rpolovic = {
		.i = med_tuljavama,
		.j = 0,
		.k = 0
	};
	for (int i = -koliko; i <= koliko; i++) {
		merilno_mesto.i = i*razmak;
		for (int j = -koliko; j <= koliko; j++) {
			merilno_mesto.j = j*razmak;
			struct vektor merilno_mesto2 = seštej(
					merilno_mesto,
					zamik_izven_osi
				);
			struct vektor B =
				seštej(
					množi(
						množi(
							tuljava(
								R,
								kotov,
								seštej(
									merilno_mesto,
									Rpolovic
								)
							),
							n
						),
						I
					),
					množi(
						množi(
							tuljava(
								R2,
								kotov,
								seštej(
									merilno_mesto2,
									množi(
										Rpolovic,
										-1
									)
								)
							),
							n
						),
						I2
					)
				);
			switch (oblika) {
				case PGM:
					if (10000*absolutno(B) > 255)
						putc(255, out);
					else
						putc(10000*absolutno(B), out);
					break;
				case PPM:
#define NATISNI_KOMPONENTO(x)		if (10000*fabsl(B.x) > 255) \
						putc(255, out); \
					else \
						putc(10000*fabsl(B.x), out);
					NATISNI_KOMPONENTO(i);
					NATISNI_KOMPONENTO(j);
					NATISNI_KOMPONENTO(k);
					break;
				case TSV:
					fprintf(out, "%Lf\t%Lf\t%Lf\t%Lf\t%Lf\n",
							merilno_mesto.i, merilno_mesto.j,
							B.i, B.j, absolutno(B));
					break;
				case ANIMACIJA:
					abort(); // invalid
					break;
			}
		}
	}
	return 0;
}
int shouldexit = 0;
void handler (int s __attribute__((unused))) {
	shouldexit++;
}
int main (int argc, char ** argv) {
	if (argv[1] && !strcmp(argv[1], "animacija"))
		goto animacija;
	if (argc < 8)
		error(1, 0, UVOD, argv[0] ? argv[0] : "./numerično");
	long double R = strtold(argv[1], NULL);
	long double I = strtold(argv[2], NULL);
	unsigned n = strtol(argv[3], NULL, 10);
	long double razmak = strtold(argv[4], NULL);
	int koliko = strtold(argv[5], NULL);
	unsigned kotov = strtol(argv[6], NULL, 10);
	enum oblika oblika = PGM;
	long double med_tuljavama = R/2;
	struct vektor zamik_izven_osi = {0, 0, 0};
	long double R2 = R;
	long double I2 = I;
	if (argc > 7 && argv[7][0])
		switch (argv[7][1]) {
			case 'G':
			case 'g':
				oblika = PGM;
				break;
			case 'P':
			case 'p':
				oblika = PPM;
				break;
			case 'S':
			case 's':
				oblika = TSV;
				break;
			case 'N':
			case 'n':
				oblika = ANIMACIJA;
				break;
		}
	if (argc > 8 && argv[8][0])
		med_tuljavama = strtold(argv[8], NULL);
	if (argc > 9 && argv[9][0])
		zamik_izven_osi.j = strtold(argv[9], NULL);
	if (argc > 0xA && argv[0xA][0])
		R2 = strtold(argv[0xA], NULL);
	if (argc > 0xB && argv[0xB][0])
		I2 = strtold(argv[0xB], NULL);
	if (oblika != ANIMACIJA)
		return nariši(R, I, n, razmak, koliko, kotov, oblika, med_tuljavama,
			       	zamik_izven_osi, R2, I2, stdout);
animacija:
	signal(SIGTERM, handler);
	signal(SIGINT, handler);
	unsigned čas = 0;
	while (!shouldexit && čas < 21) {
		char fn[25] = "animacija";
		sprintf(fn+strlen(fn), "%04d.ppm", čas);
		fprintf(stderr, "%s\n", fn);
		FILE * f = fopen(fn, "w");
		if (!f)
			error(2, errno, "fopen");
		long double R = 0.06;
		long double I = 2;
		unsigned n = 320;
		long double razmak = 0.0007;
		unsigned koliko = 350;
		unsigned kotov = 30;
		enum oblika oblika = PPM;
		long double med_tuljavama = (R/2/10)*(čas);
		struct vektor zamik = {
			.i = 0,
			.j = 0, // zamik osi
			.k = 0
		};
		long double R2 = R;
		long double I2 = I;
		if (nariši(R, I, n, razmak, koliko, kotov, oblika, med_tuljavama, zamik, R2, I2, f))
			error(3, errno, "nariši");
		if (fclose(f))
			error(4, errno, "fclose");
		čas++;
	}
	return 0;
}