5 /* Adapted for MPE display */
13 #include <mpe_graphics.h>
16 /********************************/
18 /* The Mandelbrot Set */
22 /********************************/
24 /* Simplified main() via two functions */
25 /* iterate_map() and set_grid() */
27 /* Slice image - strips parallel to real C */
29 /* set_slices() and calculate_slice() */
31 /* Parallel version -- Master-Slave model */
33 /* master() running on node zero */
34 /* slave() running on all other nodes */
43 /* Michel Vallieres */
46 /* large distance; if |z| goes */
47 /* beyond it, point C is not a */
48 /* member of the set */
49 #define LARGE_RADIUS 2.0
50 /* Maximum number of iterations */
51 /* before declaring a point in */
52 /* the Mandelbrot set */
53 #define MAX_ITERATIONS 120
57 /* # of slices parallel to C real */
59 /* Maximum # processes */
60 #define MAX_PROCESSES 1000
61 /* # of colors in MPE palette */
66 /* Iterate the Mandelbrot map -- decide if the (input) point */
67 /* in complex C plane belongs or not to the set */
68 /* prints out the number of iterations pro-rated to */
70 double iterate_map( double c_real, double c_img, int *count )
72 double z_real, z_img, z_current_real, z_magnitude;
76 /* z starts a origin */
79 /* set counter to zero */
82 /* MAX_ITERATIONS times or ...*/
83 while ( counter < MAX_ITERATIONS )
85 z_current_real = z_real;
86 z_real = z_real*z_real - z_img*z_img + c_real;
87 z_img = 2.0*z_current_real*z_img + c_img;
88 counter = counter + 1;
89 /* ... until magnitude of z */
90 /* is larger than some */
92 z_magnitude = z_real*z_real+z_img*z_img;
93 if ( z_magnitude > LARGE_RADIUS ) break;
95 /* write C real and */
96 /* imaginary parts if */
97 /* C belongs to the set */
99 if ( z_magnitude < LARGE_RADIUS )
100 printf ( " %f %f \n ", c_real, c_img );
102 /* or iteration number */
103 /* for all scanned C values */
104 /* for color picture */
107 color = (double)(counter) / (double)MAX_ITERATIONS;
113 /* Set up the grid in complex C plane to generate image */
114 void set_grid( double *crmin, double *crmax, double *cimin,
115 double *cimax, double *dcr, double *dci )
117 /* define grid spanning */
118 /* the complex plane for */
124 /* C spacing on complex plane */
125 *dcr = (*crmax - *crmin)/(NX-1);
126 *dci = (*cimax - *cimin)/(NY-1);
130 /* Calculate the Mandelbrot set in slice */
131 void calculate_slice( int slice, int *begin_slice,
132 int *end_slice, int *count,
133 double crmin, double cimin, double dcr, double dci,
134 double *store_slice, MPE_Point store_points[] )
137 double c_real, c_img, color;
141 /* scan over slice */
142 for ( j=begin_slice[slice] ; j<=end_slice[slice] ; j++ )
144 for ( i=0 ; i<NX ; i++ )
146 c_real = crmin + i*dcr;
147 c_img = cimin + j*dci;
148 /* iterate Mandelbrot map */
149 color = iterate_map( c_real, c_img, count );
151 /* store iteration # for */
152 /* use in MPE display */
153 /* color is NC scaled by */
154 /* iterations/max_iterations */
155 store_points[k].x = i;
156 store_points[k].y = j;
157 color_pointer = NC*color;
158 store_points[k].c = color_pointer;
160 /* store resulting color */
161 store_slice[k] = color;
168 /* Setup the slices through which compute the Mandelbrot set */
169 int set_slices( int *begin_slice, int *end_slice, int *offset )
171 int slice, average, leftover, temp, temp_offset;
174 average = NY / N_slices;
175 leftover = NY % N_slices;
178 for ( slice=0 ; slice<N_slices ; slice++ )
180 begin_slice[slice] = temp + 1;
181 end_slice[slice] = begin_slice[slice] + average - 1;
187 temp = end_slice[slice];
188 offset[slice] = temp_offset;
189 temp_offset = temp_offset + NX *
190 ( end_slice[slice] - begin_slice[slice] + 1 );
196 /* terminates graph interactively */
197 int quit_by_touch( MPE_XGraph graph, int WINDOW_SIZE_X,
200 int x, y, button, xc, yc, w, h, xs, ys;
202 xc = 0.95*WINDOW_SIZE_X; /* draw filled rectangle */
203 yc = 0.95*WINDOW_SIZE_Y; /* lower left bottom */
204 w = 0.05*WINDOW_SIZE_X; /* corner of graphic window */
205 h = WINDOW_SIZE_Y - yc;
206 /* write Q in small rectangle */
207 MPE_Fill_rectangle( graph, xc, yc, w, h, MPE_BLACK );
210 MPE_Draw_string( graph, xs, ys, MPE_WHITE, "Q" );
213 /* wait for different touch */
216 /* wait for mouse to touch graph */
217 /* can only be done by master */
218 MPE_Get_mouse_press( graph, &x, &y, &button );
219 /* result is touch point */
220 fprintf( stderr, "\n Graph coordinates of the touch: %d %d %d \n",
222 if ( x < xc+w && y > yc )
225 "\n Last touch was in the -- quit -- rectangle \n\n" );
233 /* slave processes -- calculate a specific slice */
234 /* specified by "slice" as received from process 0 */
235 void slave( int my_rank, int *begin_slice, int *end_slice,
236 int average, double crmin, double cimin, double dcr,
237 double dci, double *store_slice , MPE_Point store_points[],
241 int number, store_n, slice;
244 /* signal -> slice is done */
249 /* a new slice to calculate */
250 MPI_Recv( &slice, 1, MPI_INT, 0, 325, MPI_COMM_WORLD, &status );
256 free( store_points );
257 MPE_Close_graphics( &graph );
261 /* calculate requested slice */
262 calculate_slice( slice, begin_slice, end_slice, &count,
263 crmin, cimin, dcr, dci, store_slice,
266 /* send results back to master */
267 // number = NX * (average+1) ;
268 // MPI_Ssend( store_slice, number, MPI_DOUBLE, 0, 327,
271 /* send signal to node 0 */
272 MPI_Ssend( &done, 1, MPI_INT, 0, 327, MPI_COMM_WORLD );
274 /* draw the slice in MPE graph */
275 store_n = NX * ( end_slice[slice]-begin_slice[slice]+1 );
276 MPE_Draw_points( graph, store_points, store_n);
278 /* update the graph */
281 fprintf( stderr, "slave %d -> slice %d calculated & drawn\n",
288 /* Master node -- control the calculation */
289 void master(int numprocs, int *begin_slice, int *end_slice,
290 int average, double crmin, double cimin, double dcr,
291 double dci, double *store_slice, int *offset,
294 int k, k_slice, slice, process;
298 static int list_slices[MAX_PROCESSES];
299 int kill, recv_slice;
300 double mandelbrot[NX*NY];
302 /* # points in set */
304 /* scan over slices */
306 /* send a slice to each slave */
307 for ( process=1 ; process<numprocs ; process++ )
309 /* generate Mandelbrot set */
310 /* in each process */
311 MPI_Ssend( &slice, 1, MPI_INT, process, 325,
313 list_slices[process] = slice;
317 /* scan over received slices */
318 for ( k_slice=0 ; k_slice<N_slices ; k_slice++ )
320 /* receive a slice */
321 // number = NX * ( average+1);
322 // MPI_Recv( store_slice, number, MPI_DOUBLE, MPI_ANY_SOURCE, 327,
323 // MPI_COMM_WORLD, &status );
325 /* watch for done signal */
326 MPI_Recv( &done, 1, MPI_INT, MPI_ANY_SOURCE, 327,
327 MPI_COMM_WORLD, &status );
329 /* source of slice */
330 source = status.MPI_SOURCE;
332 recv_slice = list_slices[source];
333 /* send a slice to this slave */
334 if ( slice < N_slices )
336 MPI_Ssend( &slice, 1, MPI_INT, source, 325,
338 list_slices[source] = slice;
342 // number = NX * ( end_slice[recv_slice]-begin_slice[recv_slice]+1 );
344 /* store set in matrix */
345 // for ( k=0 ; k<number ; k++ )
346 // mandelbrot[offset[recv_slice]+k] = store_slice[k];
350 /* ouput Mandelbrot set */
351 // fprintf( stderr, " The Mandelbrot Set will be written out \n" );
352 // for ( k=0; k<NX*NY ; k++ )
353 // printf( " %f \n", mandelbrot[k] );
355 // fprintf( stderr, " The Mandelbrot Set has been written out \n" );
357 /* calculation is done! */
358 /* all stripes done */
359 /* wait for a touch - quit */
361 quit_by_touch( graph, NX, NY );
363 /* end all slave processes */
365 for ( process=1 ; process<numprocs ; process++ )
367 MPI_Ssend( &kill, 1, MPI_INT, process, 325, MPI_COMM_WORLD );
371 MPE_Close_graphics( &graph );
378 int main( int argc, char *argv[] )
380 double crmin, crmax, cimin, cimax;
383 int begin_slice[1000], end_slice[1000], offset[1000];
384 int my_rank, numprocs;
386 MPE_Point *store_points;
387 MPE_Color colors[500];
391 char displayname[MPI_MAX_PROCESSOR_NAME+4] = "";
394 MPI_Init( &argc, &argv );
395 MPI_Comm_size( MPI_COMM_WORLD, &numprocs );
396 MPI_Comm_rank( MPI_COMM_WORLD, &my_rank );
399 strcpy( displayname, getenv( "DISPLAY" ) );
401 MPI_Bcast( displayname, MPI_MAX_PROCESSOR_NAME+4, MPI_CHAR,
403 fprintf( stdout, "%d : $DISPLAY at process 0 = %s\n",
404 my_rank, displayname );
407 ierr = MPE_Open_graphics( &graph, MPI_COMM_WORLD, displayname,
408 -1, -1, 700, 500, 0 );
410 if ( ierr != MPE_SUCCESS )
412 fprintf( stderr, "%d : MPE_Open_graphics() fails\n", my_rank );
413 ierr = MPI_Abort( MPI_COMM_WORLD, 1 );
417 fprintf( stderr, "After Open Graphics call \n" );
419 /* make a new color palette */
420 MPE_Make_color_array( graph, NC, colors );
423 average = set_slices( begin_slice, end_slice, offset );
426 set_grid( &crmin, &crmax, &cimin, &cimax, &dcr, &dci );
429 store_slice = (double *)malloc( NX*(average+1)*sizeof(double) );
431 /* color storage for MPE graph */
432 store_points = (MPE_Point *)malloc( NX*(average+1)*sizeof(MPE_Point) );
437 master( numprocs, begin_slice, end_slice, average,
438 crmin, cimin, dcr, dci, store_slice, offset, graph );
443 slave( my_rank, begin_slice, end_slice, average,
444 crmin, cimin, dcr, dci, store_slice, store_points, graph );