-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdla_single_thread.c
More file actions
306 lines (264 loc) · 10 KB
/
dla_single_thread.c
File metadata and controls
306 lines (264 loc) · 10 KB
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
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "support_functions.c"
#include "timer.h"
void gen_particles(int *seed, int num_particles, particle *particles_list, int n, int m);
void start_DLA(int num_particles, particle *particles_list, int n, int m, int **matrix, int horizon, stuckedParticles sp);
void move(particle *p, int n, int m);
void get_args(int argc, char *argv[], int *num_particles, int *n, int *m, int *seed, int *horizon);
/*
* Recupera tutti gli argomenti passati in input al programma e li setta alle opportune variabili.
* Prende come parametri le variabili da settare:
* @param argc numero di argomenti passati in input
* @param argv array di argomenti passati in input
* @param num_particles numero di particelle
* @param n numero di righe della matrice
* @param m numero di colonne della matrice
* @param seed posizione iniziale della particella
* @param horizon numero di iterazioni massime
*/
void get_args(int argc, char *argv[], int *num_particles, int *n, int *m, int *seed, int *horizon)
{
// recupero le dimensioni della matrice
char *token = strtok(argv[1], ",");
*n = (int)atoi(token);
token = strtok(NULL, ",");
*m = (int)atoi(token);
// recupero il numero di particelle
*num_particles = (int)atoi(argv[2]);
// genero random il seed - DEFAULT
seed[0] = (int)rand_r(&gen_rand) % *m;
seed[1] = (int)rand_r(&gen_rand) % *n;
// setto il numero di iterazioni massime - DEFAULT
*horizon = HORIZON;
int opt;
while ((opt = getopt(argc, argv, "-t:-s:")) != -1)
{
switch (opt)
{
case 't':
// recupero il numero di iterazioni massime - OPTION
*horizon = atoi(optarg);
break;
case 's':
// recupero la posizione iniziale del seed - OPTION
token = strtok(optarg, ",");
seed[0] = (int)atoi(token);
token = strtok(NULL, ",");
seed[1] = (int)atoi(token);
break;
case '?':
printf("Usage: %s [-n num_threads] [-t horizon] [-s seed] n,m num_particles \n", argv[0]);
exit(2);
}
}
}
/*
* Genera una lista di particelle con posizione casuale.
* La funzione modifica la lista di particelle.
* @param seed: posizione del seme
* @param num_particles: numero di particelle da generare
* @param particles_list: lista di particelle
* @param n: numero di righe della matrice
* @param m: numero di colonne della matrice
*/
void gen_particles(int *seed, int num_particles, particle *particles_list, int n, int m)
{
if (num_particles >= n * m)
{
perror("Troppe particelle all'interno della matrice. \n");
exit(3);
}
for (int i = 0; i < num_particles; i++)
{
// allocate memory for particle position
particles_list[i].current_position = (position *)malloc(sizeof(position));
if (particles_list[i].current_position == NULL)
{
perror("Errore durante l'allocazione della lista di particelle. \n");
exit(1);
}
// setto la posizione della particella, se è uguale al seed la ricreo
do
{
particles_list[i].current_position->x = rand() % m;
particles_list[i].current_position->y = rand() % n;
} while (seed[0] == particles_list[i].current_position->x && seed[1] == particles_list[i].current_position->y);
particles_list[i].dire = 0;
particles_list[i].stuck = 0;
particles_list[i].isOut = 0;
}
}
/*
* Muove la particella in una direzione pseudocasuale.
* Se la particelle esce fuori dalla matrice viene settata la variabile isOut a 1.
* Se la particella non esce fuori dalla matrice viene settata la variabile isOut a 0.
* @param p puntatore alla particella da muovere
* @param n numero di righe della matrice
* @param m numero di colonne della matrice
*/
void move(particle *p, int n, int m)
{
// calcolo la nuova posoizione della particella
p->dire = rand() % 2 == 0 ? 1 : -1;
p->current_position->x += rand() % 2 * p->dire;
p->dire = rand() % 2 == 0 ? 1 : -1;
p->current_position->y += rand() % 2 * p->dire;
// controllo se la particella è uscita dalla matrice o no
if (!(p->current_position->x >= 0 && p->current_position->x < m && p->current_position->y >= 0 && p->current_position->y < n))
{
p->isOut = 1;
return;
}
else
{
p->isOut = 0;
}
}
/*
* La funzione inizia la simulazione DLA.
* La simulazione consiste in:
* - un ciclo che simula il tempo, ogni tick è un'iterazione della simulazione
* - per ogni particella viene chiamata la funzione check_position che controlla se la particella è in prossimità di un cristallo,
* in caso affermativo setta un flag. Altrimenti la particella si muove.
* - nel caso in cui la particella non sia rimasta bloccata, viene chiamata la funzione move che si occupa di muoverla.
* - se la particella è rimasta bloccata viene aggiornata la matrice al termine di ogni tick
* Al termine di ogni tick viene aggiornata la matrice.
* @param num_particles numero di particelle
* @param particles_list lista di particelle
* @param n numero di righe della matrice
* @param m numero di colonne della matrice
* @param matrix matrice di interi
* @param horizon numero di iterazioni massime
* @param sp lista di particelle bloccate
*/
void start_DLA(int num_particles,
particle *particles_list,
int n, int m,
int **matrix, int horizon, stuckedParticles sp)
{
printf("Starting DLA\n");
// tick della simulazione
for (int t = 0; t < horizon + 1; t++)
{
// itero su tutte le particelle
for (int i = 0; i < num_particles; i++)
{
particle *p = &particles_list[i];
if (p->stuck <= 0)
{
// controllo se la particella si aggrega o no
int isStuck = check_position(n, m, matrix, p, &sp);
if (isStuck == 0)
{
if (t < horizon)
// muovo la particella
move(p, n, m);
else if (p->isOut == 0)
// se sono all'ultima iterazione e la particella non è uscita dalla matrice la aggiungo alla matrice per il render finale
matrix[p->current_position->y][p->current_position->x] += 2;
}
}
}
// aggiorno la matrice
// per ogni particella stucked scrivo 1 sulla matrice nella posizione della particella
while (sp.size > 0)
{
particle p = sp_pop(&sp);
matrix[p.current_position->y][p.current_position->x] = 1;
}
}
printf("Finished DLA\n");
}
int main(int argc, char *argv[])
{
int n, m; // matrix dimensions
int seed[2]; // seed position
int num_particles; // numero di particelle
int horizon; // tempo di simulazione
int **matrix;
stuckedParticles sp; // lista di particelle bloccate
double start, end, elapsed;
get_args(argc, argv, &num_particles, &n, &m, seed, &horizon);
printf("Initial seed position: %d, %d\n", seed[0], seed[1]);
matrix = (int **)calloc(n, sizeof(int *)); // Alloca un array di puntatori e inizializza tutti gli elementi a 0
if (matrix == NULL)
{
perror("Errore nell'allocazione della matrice. \n");
exit(1);
}
for (int i = 0; i < n; i++)
{
matrix[i] = (int *)calloc(m, sizeof(int)); // Alloca un array di interi per ogni riga e inizializza tutti gli elementi a 0
if (matrix[i] == NULL)
{
perror("Errore nell'allocazione della matrice. \n");
exit(1);
}
}
matrix[seed[1]][seed[0]] = 1; // scrivo il seed sulla matrice
float perc = ((float)num_particles / (float)(n * m)) * 100;
int cap = (int)(((float)perc * (float)num_particles) / 100);
if (cap == 0)
cap = num_particles/3;
if (init_StuckedParticles(&sp, (int)cap) != 0)
{
perror("Errore nell'allocazione della lista di particelle bloccate. \n");
exit(1);
}
particle *particles_list = (particle *)malloc(sizeof(particle) * num_particles);
if (particles_list == NULL)
{
perror("Errore durante l'allocazione della lista di particelle. \n");
exit(1);
}
srand(seed_rand); // setto il seed per la random
// genero le particelle
gen_particles(seed, num_particles, particles_list, n, m);
GET_TIME(start);
// start DLA
start_DLA(num_particles, particles_list, n, m, matrix, horizon, sp);
GET_TIME(end);
elapsed = (double)(end - start);
printf("Elapsed time: %f seconds \n", elapsed);
// ----- TIME ----- //
FILE *elapsed_time = fopen("./times/time_dla_single_thread.txt", "a");
fprintf(elapsed_time, "%f\n", elapsed);
fclose(elapsed_time);
// ----- RENDER ----- //
gdImagePtr img = gdImageCreate(m, n);
int white = gdImageColorAllocate(img, 255, 255, 255);
gdImageFilledRectangle(img, 0, 0, m, n, white);
int colors[2];
colors[0] = gdImageColorAllocate(img, 0, 0, 0); // black
colors[1] = gdImageColorAllocate(img, 255, 0, 0); // red
createImage(img, m, n, matrix, colors, "single_thread_render.jpg");
// -----FINALIZE----- //
printf("freed memory: ");
for (int i = 0; i < n; i++)
{
if (matrix[i] != NULL)
free(matrix[i]); // Libera la memoria della riga i-esima
}
printf("matrix, ");
if (matrix != NULL)
free(matrix); // Libera la memoria dell'array di puntatori
printf("destroy image pointer, ");
gdImageDestroy(img);
if (sp_destroy(&sp) != 0)
{
perror("Error nella distruzione della stuckedParticles list. \n");
exit(1);
}
for (int i = 0; i < num_particles; i++)
{
if (particles_list[i].current_position != NULL)
free(particles_list[i].current_position);
}
printf("current_position, ");
if (particles_list != NULL)
free(particles_list);
printf("particles_list \n");
return 0;
}