diff options
Diffstat (limited to 'fiz/naloga/numerično.c')
-rw-r--r-- | fiz/naloga/numerično.c | 192 |
1 files changed, 160 insertions, 32 deletions
diff --git a/fiz/naloga/numerično.c b/fiz/naloga/numerično.c index e102899..c1ca08c 100644 --- a/fiz/naloga/numerično.c +++ b/fiz/naloga/numerično.c @@ -2,28 +2,45 @@ #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 argumenti po vrsti:\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" \ - " 7. tip izhodnih podatkov (pgm ali csv)\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 csv, je csv, z naslednjimi stolpci:\n" \ - " 1. vodoravna komponenta oddaljenosti od središča tuljave v metrih\n" \ - " 2. navpična komponenta oddaljenosti od središča tuljave v metrih\n" \ - " 3. jakost magnetnega polja v teslah - tokrat ni v decigaussih!\n" \ - " 4. smer vektorja magnetnega polja v radianih. 0 radianov je smer v desno" + "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, - CSV + PPM, + TSV, + ANIMACIJA }; struct vektor { long double i; // x - desno na sliki @@ -87,27 +104,29 @@ struct vektor tuljava (long double R, unsigned kotov, struct vektor m /* meritev 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 main (int argc, char ** argv) { - if (argc != 1 + 7) - 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 = argv[7][0] == 'p' || argv[7][0] == 'P' ? PGM : CSV; +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 == CSV) - error(2, 0, "CSV oblika še ni implementirana."); - printf("P5 %u %u 255\n", koliko*2+1, koliko*2+1); + 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 = R/2, + .i = med_tuljavama, .j = 0, .k = 0 }; @@ -115,8 +134,12 @@ int main (int argc, char ** argv) { merilno_mesto.i = i*razmak; for (int j = -koliko; j <= koliko; j++) { merilno_mesto.j = j*razmak; - unsigned long long int out = - 1000*absolutno(seštej( + struct vektor merilno_mesto2 = seštej( + merilno_mesto, + zamik_izven_osi + ); + struct vektor B = + seštej( množi( množi( tuljava( @@ -134,10 +157,10 @@ int main (int argc, char ** argv) { množi( množi( tuljava( - R, + R2, kotov, seštej( - merilno_mesto, + merilno_mesto2, množi( Rpolovic, -1 @@ -146,14 +169,119 @@ int main (int argc, char ** argv) { ), n ), - I + I2 ) - )); - if (out > 255) - putchar(255); - else - putchar(out); + ); + 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; } |