├── Chapter01 └── script.txt ├── Chapter02 ├── 01_C_PI.c ├── 02_call-procs.c ├── 03_MPI_08_b.c ├── 04_Euler.c ├── 05_Gregory_Leibniz.c └── 06_Nilakantha.c ├── Chapter03 └── script.txt ├── Chapter04 └── script.txt ├── Chapter05 └── script.txt ├── Chapter06 └── script.txt ├── Chapter07 └── script.txt ├── Chapter08 └── script.txt ├── Chapter09 ├── 07_Serial_sine.c ├── 08_MPI_sine.c ├── 09_Serial_cosine.c ├── 10_MPI_cosine.c ├── 11_Serial_tan.c ├── 12_MPI_tan.c ├── 13_Serial_ln.c └── 14_MPI_ln.c ├── Chapter10 └── 15_BK_wave4.c ├── Chapter11 ├── 16_Serial_Sawtooth.c └── 17_MPI_Sawtooth.c ├── Chapter12Appendix ├── 01_Ramanujan.c ├── 02_Chudnovsky.c ├── 03_Unknown.c ├── 04_Simon_Pluff.c └── 05_Fabrice_Bellard.c ├── LICENSE └── README.md /Chapter01/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter02/01_C_PI.c: -------------------------------------------------------------------------------- 1 | /************************************* 2 | * *** Serial pi code. *** * 3 | * * 4 | * This program calculates pi using * 5 | * serial computing. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 7/14/2017 * 10 | *************************************/ 11 | 12 | #include 13 | #include 14 | 15 | 16 | int main(void) 17 | { 18 | long num_rects = 300000;//1000000000; 19 | long i; 20 | double x,height,width,area; 21 | double sum; 22 | 23 | width = 1.0/(double)num_rects; // width of a segment 24 | 25 | sum = 0; 26 | for(i = 0; i < num_rects; i++) 27 | { 28 | x = (i+0.5) * width; // x: distance to center of i(th) segment 29 | height = 4/(1.0 + x*x); 30 | sum += height; // sum of individual segment height 31 | } 32 | 33 | // approximate area of segments (Pi value) 34 | area = width * sum; 35 | 36 | printf("\n"); 37 | printf(" Calculated Pi = %.16f\n", area); 38 | printf(" M_PI = %.16f\n", M_PI); 39 | printf("Relative error = %.16f\n", fabs(area - M_PI)); 40 | printf("\n"); 41 | return 0; 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Chapter02/02_call-procs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) 5 | { 6 | /* MPI Variables */ 7 | int num_processes; 8 | int curr_rank; 9 | char proc_name[MPI_MAX_PROCESSOR_NAME]; 10 | int proc_name_len; 11 | 12 | /* Initialize MPI */ 13 | MPI_Init(&argc, &argv); 14 | 15 | /* acquire number of processes */ 16 | MPI_Comm_size(MPI_COMM_WORLD, &num_processes); 17 | 18 | /* acquire rank of the current process */ 19 | MPI_Comm_rank(MPI_COMM_WORLD, &curr_rank); 20 | 21 | /* acquire processor name for the current thread */ 22 | MPI_Get_processor_name(proc_name, &proc_name_len); 23 | 24 | /* output rank , no of processes, and process name */ 25 | printf("Calling process %d out of %d on %s\r\n", curr_rank, num_processes, proc_name); 26 | 27 | /* clean up, done with MPI */ 28 | MPI_Finalize(); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /Chapter02/03_MPI_08_b.c: -------------------------------------------------------------------------------- 1 | /******************************************** 2 | * *** MPI pi code. *** * 3 | * * 4 | * This numerical integration calculates * 5 | * pi using MPI. It converges very slowely, * 6 | * requiring 5 million iterations for * 7 | * 48 decimal place accuracy. * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | ********************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n, rank, length, numprocs, i; 22 | double mypi, pi, width, sum, x, rank_integral; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if (rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("Master node name: %s\n", hostname); 36 | printf("\n"); 37 | printf("Enter number of segments:\n"); 38 | printf("\n"); 39 | scanf("%d",&n); 40 | printf("\n"); 41 | } 42 | 43 | // broadcast the number of segments "n" to all processes. 44 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 45 | 46 | // this loop increments the maximum number of iterations, thus providing 47 | // additional work for testing computational speed of the processors 48 | for(total_iter = 1; total_iter < n; total_iter++) 49 | { 50 | sum=0.0; 51 | width = 1.0 / (double)total_iter; // width of a segment 52 | // width = 1.0 / (double)n; // width of a segment 53 | 54 | for(i = rank + 1; i <= total_iter; i += numprocs) 55 | // for(i = rank + 1; i <= n; i += numprocs) 56 | { 57 | x = width * ((double)i - 0.5); // x: distance to center of i(th) segment 58 | sum += 4.0/(1.0 + x*x); // sum of individual segment height for a given rank 59 | } 60 | 61 | // approximate area of segment (Pi value) for a given rank 62 | rank_integral = width * sum; 63 | 64 | // collect and add the partial area (Pi) values from all processes 65 | MPI_Reduce(&rank_integral, &pi, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 66 | 67 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 68 | 69 | // printf("Process %d on %s has the partial result of %.16f \n",rank,hostname, 70 | // rank_integral); 71 | 72 | if(rank == 0) 73 | { 74 | printf("\n\n"); 75 | printf("*** Number of processes: %d\n",numprocs); 76 | printf("\n\n"); 77 | printf(" Calculated pi = %.50f\n", pi); 78 | printf(" M_PI = %.50f\n", M_PI); 79 | printf(" Relative Error = %.50f\n", fabs(pi-M_PI)); 80 | printf("\n"); 81 | } 82 | 83 | // clean up, done with MPI 84 | MPI_Finalize(); 85 | return 0; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /Chapter02/04_Euler.c: -------------------------------------------------------------------------------- 1 | /***************************************** 2 | * *** Euler MPI pi code. *** * 3 | * * 4 | * This infinate series calculates pi * 5 | * using MPI. It converges very slowely, * 6 | * requiring 7.6 million iterations for * 7 | * eight decimal place accuracy. * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | *****************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n,rank,length,numprocs,i; 22 | double sum,sum0,rank_integral,A; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if (rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("Master node name: %s\n", hostname); 36 | printf("\n"); 37 | printf("Enter the number of intervals:\n"); 38 | printf("\n"); 39 | scanf("%d",&n); 40 | printf("\n"); 41 | } 42 | 43 | // broadcast the number of iterations "n" to all processes. 44 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 45 | 46 | // this loop increments the maximum number of iterations, thus providing 47 | // additional work for testing computational speed of the processors 48 | // for(total_iter = 1; total_iter < n; total_iter++) 49 | { 50 | sum0 = 0.0; 51 | // for(i = rank + 1; i < total_iter; i += numprocs) 52 | for(i = rank + 1; i <= n; i += numprocs) 53 | { 54 | A = 1.0/(double)pow(i,2); 55 | sum0 += A; 56 | } 57 | 58 | // Partial sum for a given rank 59 | rank_integral = sum0; 60 | 61 | // collect and add the partial sum0 values from all processes 62 | MPI_Reduce(&rank_integral, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 63 | 64 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 65 | 66 | if(rank == 0) 67 | { 68 | printf("\n\n"); 69 | printf("*** Number of processes: %d\n",numprocs); 70 | printf("\n\n"); 71 | printf(" Calculated pi = %.30f\n", sqrt(6*sum)); 72 | printf(" M_PI = %.30f\n", M_PI); 73 | printf(" Relative Error = %.30f\n", fabs(sqrt(6*sum)-M_PI)); 74 | printf("\n"); 75 | } 76 | 77 | // clean up, done with MPI 78 | MPI_Finalize(); 79 | 80 | return 0; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /Chapter02/05_Gregory_Leibniz.c: -------------------------------------------------------------------------------- 1 | /***************************************** 2 | * *** Gregory_Leibniz MPI pi code. *** * 3 | * * 4 | * This infinate series calculates pi * 5 | * using MPI. It converges very slowely, * 6 | * requiring 2.15 billion iterations for * 7 | * ten decimal place accuracy. * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | *****************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n, rank,length,numprocs; 22 | double rank_sum,pi,sum,A; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | unsigned long i,k; 26 | 27 | MPI_Init(&argc, &argv); // initiates MPI 28 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 29 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 30 | MPI_Get_processor_name(hostname, &length); // acquire hostname 31 | 32 | if (rank == 0) 33 | { 34 | printf("\n"); 35 | printf("#######################################################"); 36 | printf("\n\n"); 37 | printf("Master node name: %s\n", hostname); 38 | printf("\n"); 39 | printf("Enter the number of iterations:\n"); 40 | printf("\n"); 41 | scanf("%d",&n); 42 | printf("\n"); 43 | } 44 | 45 | // broadcast the number of iterations "n" to all processes. 46 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 47 | 48 | // this loop increments the maximum number of iterations, thus providing 49 | // additional work for testing computational speed of the processors 50 | // for(total_iter = 1; total_iter < n; total_iter++) 51 | { 52 | sum = 0.0; 53 | // for(i = rank + 1; i <= total_iter; i += numprocs) 54 | for(i = rank + 1; i <= n; i += numprocs) 55 | { 56 | k = i-1; 57 | A = (double)pow(-1,k)* 4.0/(double)(2*k+1); 58 | 59 | sum += A; 60 | } 61 | 62 | rank_sum = sum;// Partial sum for a given rank 63 | 64 | // collect and add the partial sum values from all processes 65 | MPI_Reduce(&rank_sum, &pi, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 66 | 67 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 68 | 69 | 70 | if(rank == 0) 71 | { 72 | printf("\n\n"); 73 | printf("*** Number of processes: %d\n",numprocs); 74 | printf("\n\n"); 75 | printf(" Calculated pi = %.30f\n", pi); 76 | printf(" M_PI = %.30f\n", M_PI); 77 | printf(" Relative Error = %.30f\n", fabs(pi-M_PI)); 78 | printf("\n"); 79 | } 80 | 81 | // clean up, done with MPI 82 | MPI_Finalize(); 83 | 84 | return 0; 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Chapter02/06_Nilakantha.c: -------------------------------------------------------------------------------- 1 | /****************************************** 2 | * *** Nilakantha MPI pi code. *** * 3 | * * 4 | * This infinate series calculates pi * 5 | * using MPI. It converges slowely, * 6 | * requiring 750 iterations for 9 decimal * 7 | * place accuracy. * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | ******************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n,rank,length,numprocs,i,j,k; 22 | double sum,sum0,rank_integral,A,B,C; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if (rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("Master node name: %s\n", hostname); 36 | printf("\n"); 37 | printf("Enter the number of intervals:\n"); 38 | printf("\n"); 39 | scanf("%d",&n); 40 | printf("\n"); 41 | } 42 | 43 | // broadcast the number of iterations "n" to all processes. 44 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 45 | 46 | // this loop increments the maximum number of iterations, thus providing 47 | // additional work for testing computational speed of the processors 48 | // for(total_iter = 1; total_iter < n; total_iter++) 49 | { 50 | sum0 = 0.0; 51 | // for(i = rank + 1; i <= total_iter; i += numprocs) 52 | for(i = rank + 1; i <= n; i += numprocs) 53 | { 54 | j = i-1; 55 | k = (2*j+1); 56 | 57 | A = (double)pow(-1,j+2); 58 | B = 4.0/(double)((k+1)*(k+2)*(k+3)); 59 | C = A * B; 60 | 61 | sum0 += C; 62 | } 63 | 64 | rank_integral = sum0;// Partial sum for a given rank 65 | 66 | // collect and add the partial sum0 values from all processes 67 | MPI_Reduce(&rank_integral, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 68 | 69 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 70 | // printf("Process %d on %s has the partial result of %.16f \n",rank,hostname, 71 | // rank_integral); 72 | 73 | if(rank == 0) 74 | { 75 | printf("\n\n"); 76 | printf("*** Number of processes: %d\n",numprocs); 77 | printf("\n\n"); 78 | printf(" Calculated pi = %.30f\n", (3+sum)); 79 | printf(" M_PI = %.30f\n", M_PI); 80 | printf(" Relative Error = %.30f\n", fabs((3+sum)-M_PI)); 81 | printf("\n"); 82 | } 83 | 84 | // clean up, done with MPI 85 | MPI_Finalize(); 86 | 87 | return 0; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /Chapter03/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter04/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter05/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter06/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter07/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter08/script.txt: -------------------------------------------------------------------------------- 1 | This chapter does not contain any code files. -------------------------------------------------------------------------------- /Chapter09/07_Serial_sine.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | * *** Serial sine(x) code *** * 3 | * * 4 | * Taylor series representation * 5 | * of the sine(x) functon. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 1/10/2017 * 10 | ********************************/ 11 | 12 | #include 13 | #include 14 | 15 | int main(void) 16 | { 17 | unsigned int j; 18 | unsigned long int k; 19 | long long int B,D; 20 | int num_loops = 17; 21 | float y; 22 | double x; 23 | double sum0=0,A,C,E; 24 | 25 | /******************************************************/ 26 | printf("\n"); 27 | printf("Enter angle(deg.):\n"); 28 | printf("\n"); 29 | scanf("%f",&y); 30 | if(y <= 180.0) 31 | { 32 | x = y*(M_PI/180.0); 33 | } 34 | else 35 | x = -(360.0-y)*(M_PI/180.0); 36 | /******************************************************/ 37 | 38 | sum0 = 0; 39 | for(k = 0; k < num_loops; k++) 40 | { 41 | A = (double)pow(-1,k);// (-1^k) 42 | B = 2*k+1; 43 | C = (double)pow(x,B); 44 | 45 | D = 1; 46 | for(j=1; j <= B; j++)// (2k+1)! 47 | { 48 | D *= j; 49 | } 50 | 51 | E = (A*C)/(double)D; 52 | 53 | sum0 += E; 54 | } 55 | 56 | printf("\n"); 57 | printf(" %.1f deg. = %.3f rads\n", y, x); 58 | printf("Sine(%.1f) = %.4f\n", y, sum0); 59 | 60 | return 0; 61 | } 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /Chapter09/08_MPI_sine.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | * *** MPI sine(x) code *** * 3 | * * 4 | * Taylor series representation * 5 | * of the sine(x) function. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 1/10/2017 * 10 | ********************************/ 11 | 12 | #include // (Open)MPI library 13 | #include // math library 14 | #include // Standard Input / Output library 15 | 16 | int main(int argc, char*argv[]) 17 | { 18 | long long int total_iter,B,D; 19 | int n = 17,rank,length,numprocs,i,j; 20 | unsigned long int k; 21 | double sum,sum0,rank_integral,A,C,E; 22 | float y,x; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if(rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("*** Number of processes: %d\n",numprocs); 36 | printf("*** processing capacity: %.1f GHz.\n",numprocs*1.2); 37 | printf("\n\n"); 38 | printf("Master node name: %s\n", hostname); 39 | printf("\n"); 40 | printf("Enter angle(deg.):\n"); 41 | printf("\n"); 42 | scanf("%f",&y); 43 | if(y <= 180.0) 44 | { 45 | x = y*(M_PI/180.0); 46 | } 47 | else 48 | x = -(360.0-y)*(M_PI/180.0); 49 | }// End of if(rank == 0) 50 | 51 | // broadcast input items "n" & "x" to all processes. 52 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 53 | MPI_Bcast(&x, 1, MPI_INT, 0, MPI_COMM_WORLD); 54 | 55 | // this loop increments the maximum number of iterations, thus providing 56 | // additional work for testing computational speed of the processors 57 | // for(total_iter = 1; total_iter < n; total_iter++) 58 | { 59 | sum0 = 0.0; 60 | // for(i = rank + 1; i <= total_iter; i += numprocs) 61 | for(i = rank + 1; i <= n; i += numprocs) 62 | { 63 | k = (i-1); 64 | 65 | A = (double)pow(-1,k); 66 | B = 2*k+1; 67 | C = (double)pow(x,B); 68 | 69 | D = 1; 70 | for(j=1; j <= B; j++) 71 | { 72 | D *= j; 73 | } 74 | E = (A*C)/(double)D; 75 | 76 | sum0 += E; 77 | } 78 | 79 | rank_integral = sum0;// Partial sum for a given rank 80 | 81 | // collect and add the partial sum0 values from all processes 82 | MPI_Reduce(&rank_integral, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 83 | 84 | }// End of for(total_iter = 1; total_iter < n; total_iter++) 85 | 86 | if(rank == 0) 87 | { 88 | printf("\n\n"); 89 | printf(" %.1f deg. = %.3f rads\n", y, x); 90 | printf("Sine(%.3f) = %.3f\n", x, sum); 91 | } 92 | 93 | //clean up, done with MPI 94 | MPI_Finalize(); 95 | 96 | return 0; 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 | -------------------------------------------------------------------------------- /Chapter09/09_Serial_cosine.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | **** Serial cosine(x) code *** * 3 | * * 4 | * Taylor series representation * 5 | * of the cosine(x) function. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 1/10/2017 * 10 | ********************************/ 11 | 12 | #include 13 | #include 14 | 15 | int main(void) 16 | { 17 | unsigned int j; 18 | unsigned long int k; 19 | long long int B,D; 20 | int num_loops = 17; 21 | float y; 22 | double x; 23 | double sum0=0,A,C,E; 24 | 25 | /******************************************************/ 26 | printf("\n"); 27 | printf("Enter angle(deg.):\n"); 28 | printf("\n"); 29 | scanf("%f",&y); 30 | if(y <= 180.0) 31 | { 32 | x = y*(M_PI/180.0); 33 | } 34 | else 35 | x = -(360.0-y)*(M_PI/180.0); 36 | /******************************************************/ 37 | 38 | sum0 = 0; 39 | for(k = 0; k < num_loops; k++) 40 | { 41 | A = (double)pow(-1,k);// (-1^k) 42 | B = 2*k; 43 | C = (double)pow(x,B); 44 | 45 | D = 1; 46 | for(j=1; j <= B; j++)// (2k!) 47 | { 48 | D *= j; 49 | } 50 | 51 | E = (A*C)/(double)D; 52 | 53 | sum0 += E; 54 | } 55 | 56 | printf("\n"); 57 | printf(" %.1f deg. = %.3f rads\n", y, x); 58 | printf("Cosine(%.1f) = %.4f\n", y, sum0); 59 | 60 | return 0; 61 | } 62 | 63 | 64 | -------------------------------------------------------------------------------- /Chapter09/10_MPI_cosine.c: -------------------------------------------------------------------------------- 1 | /********************************* 2 | * *** MPI cosine(x) code. *** * 3 | * * 4 | * Taylor series representation * 5 | * of the cosine(x) function. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 1/10/2017 * 10 | *********************************/ 11 | 12 | #include // (Open)MPI library 13 | #include // math library 14 | #include // Standard Input / Output library 15 | 16 | int main(int argc, char*argv[]) 17 | { 18 | long long int total_iter,B,D; 19 | int n = 17,rank,length,numprocs,i,j; 20 | unsigned long int k; 21 | double sum,sum0,rank_integral,A,C,E; 22 | float y,x; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if (rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("*** Number of processes: %d\n",numprocs); 36 | printf("*** processing capacity: %.1f GHz.\n",numprocs*1.2); 37 | printf("\n\n"); 38 | printf("Master node name: %s\n", hostname); 39 | printf("\n"); 40 | printf("Enter angle(deg.):\n"); 41 | printf("\n"); 42 | scanf("%f",&y); 43 | if(y <= 180.0) 44 | { 45 | x = y*(M_PI/180.0); 46 | } 47 | else 48 | x = -(360.0-y)*(M_PI/180.0); 49 | } 50 | 51 | // broadcast input items "n" & "x" to all processes. 52 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 53 | MPI_Bcast(&x, 1, MPI_INT, 0, MPI_COMM_WORLD); 54 | 55 | // this loop increments the maximum number of iterations, thus providing 56 | // additional work for testing computational speed of the processors 57 | // for(total_iter = 1; total_iter < n; total_iter++) 58 | { 59 | sum0 = 0.0; 60 | // for(i = rank + 1; i <= total_iter; i += numprocs) 61 | for(i = rank + 1; i <= n; i += numprocs) 62 | { 63 | k = (i-1); 64 | 65 | A = (double)pow(-1,k);// (-1^k) 66 | B = 2*k; 67 | C = (double)pow(x,B); 68 | 69 | D = 1; 70 | for(j=1; j <= B; j++)// (2k!) 71 | { 72 | D *= j; 73 | } 74 | E = (A*C)/(double)D; 75 | 76 | sum0 += E; 77 | } 78 | 79 | rank_integral = sum0;// Partial sum for a given rank 80 | 81 | // collect and add the partial sum0 values from all processes 82 | MPI_Reduce(&rank_integral, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 83 | 84 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 85 | 86 | if(rank == 0) 87 | { 88 | printf("\n\n"); 89 | printf(" %.1f deg. = %.3f rads\n", y, x); 90 | printf("Cosine(%.3f) = %.3f\n", x, sum); 91 | } 92 | 93 | // clean up, done with MPI 94 | MPI_Finalize(); 95 | 96 | return 0; 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 | -------------------------------------------------------------------------------- /Chapter09/11_Serial_tan.c: -------------------------------------------------------------------------------- 1 | /********************************** 2 | **** Serial tangent(x) code. *** * 3 | * * 4 | * Composite Taylor series * 5 | * representation of the tan(x) * 6 | * function. * 7 | * * 8 | * Author: Carlos R. Morrison * 9 | * * 10 | * Date: 1/10/2017 * 11 | **********************************/ 12 | 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | /************************************************/ 19 | unsigned int i,j,l; 20 | unsigned long int k; 21 | long long int B,D,G,I; 22 | int num_loops = 17; 23 | float y; 24 | double x; 25 | double sum=0,sum01=0,sum02=0; 26 | double A,C,E,F,H,J; 27 | /************************************************/ 28 | 29 | /************************************************/ 30 | printf("\n"); 31 | Z:printf("Enter angle(deg.):\n"); 32 | printf("\n"); 33 | scanf("%f",&y); 34 | if(y >= 0 && y < 90.0) 35 | { 36 | x = y*(M_PI/180.0); 37 | } 38 | else 39 | if(y > 90.0 && y <= 180.0) 40 | { 41 | x = -(180.0-y)*(M_PI/180.0); 42 | } 43 | else 44 | if(y >= 180.0 && y < 270) 45 | { 46 | x = -(180-y)*(M_PI/180.0); 47 | } 48 | else 49 | if(y > 270.0 && y <= 360) 50 | { 51 | x = -(360.0-y)*(M_PI/180.0); 52 | } 53 | else 54 | { 55 | printf("\n"); 56 | printf("Bad input !! Please try another angel\n"); 57 | printf("\n"); 58 | goto Z; 59 | } 60 | /*************************************************/ 61 | 62 | /************************************************* 63 | * ***** SINE BLOCK ***** * 64 | *************************************************/ 65 | sum01 = 0; 66 | for(i = 0; i < num_loops; i++) 67 | { 68 | A = (double)pow(-1,i); 69 | B = 2*i+1; 70 | C = (double)pow(x,B); 71 | 72 | D = 1; 73 | for(j = 1; j <= B; j++) 74 | { 75 | D *= j; 76 | } 77 | 78 | E = (A*C)/(double)D; 79 | 80 | sum01 += E; 81 | }// End of for(i = 0; i < num_loops; i++) 82 | 83 | /***************************************************** 84 | * ***** COSINE BLOCK ***** * 85 | *****************************************************/ 86 | sum02 = 0; 87 | for(k = 0; k < num_loops; k++) 88 | { 89 | F = (double)pow(-1,k); 90 | G = 2*k; 91 | H = (double)pow(x,G); 92 | 93 | I = 1; 94 | for(l = 1; l <= G; l++) 95 | { 96 | I *= l; 97 | } 98 | 99 | J = (F*H)/(double)I; 100 | 101 | sum02 += J; 102 | }// End of for(k = 0; k < num_loops; k++) 103 | 104 | /***************************************************** 105 | * ***** TANGENT BLOCK ***** * 106 | *****************************************************/ 107 | 108 | /*******************/ 109 | sum = sum01/sum02; // Tan(x) ==> Sine(x)/Cos(x) 110 | /*******************/ 111 | 112 | /*****************************************************/ 113 | printf("\n"); 114 | printf("%.1f deg. = %.3f rads\n", y, x); 115 | printf("Tan(%.1f) = %.3f\n", y, sum); 116 | 117 | return 0; 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /Chapter09/12_MPI_tan.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | * *** MPI tangent(x) code. *** * 3 | * * 4 | * Composite Taylor series * 5 | * representation of the tan(x) * 6 | * function. * 7 | * * 8 | * Author: Carlos R. Morrison * 9 | * * 10 | * Date: 1/10/2017 * 11 | ********************************/ 12 | 13 | #include // (Open)MPI library 14 | #include // math library 15 | #include // Standard Input / Output library 16 | 17 | int main(int argc, char*argv[]) 18 | { 19 | /******************************************************************************/ 20 | unsigned int i,j,l; 21 | unsigned long int k,m,n; 22 | long long int B,D,G,I; 23 | int Q = 17,rank,length,numprocs; 24 | float x,y; 25 | double sum,sum1,sum2,sum01=0,sum02=0,rank_sum,rank_sum1,rank_sum2; 26 | double A,C,E,F,H,J; 27 | char hostname[MPI_MAX_PROCESSOR_NAME]; 28 | 29 | MPI_Init(&argc, &argv); // initiates MPI 30 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 31 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 32 | MPI_Get_processor_name(hostname, &length); // acquire hostname 33 | /******************************************************************************/ 34 | 35 | if(rank == 0) 36 | { 37 | printf("\n"); 38 | printf("#######################################################"); 39 | printf("\n\n"); 40 | printf("*** Number of processes: %d\n",numprocs); 41 | printf("*** processing capacity: %.1f GHz.\n",numprocs*1.2); 42 | printf("\n\n"); 43 | printf("Master node name: %s\n", hostname); 44 | printf("\n"); 45 | printf("\n"); 46 | Z: printf("Enter angle(deg.):\n"); 47 | printf("\n"); 48 | scanf("%f",&y); 49 | 50 | if(y >= 0 && y < 90.0) 51 | { 52 | x = y*(M_PI/180.0); 53 | } 54 | else 55 | if(y > 90.0 && y <= 180.0) 56 | { 57 | x = -(180.0-y)*(M_PI/180.0); 58 | } 59 | else 60 | if(y >= 180.0 && y < 270) 61 | { 62 | x = -(180-y)*(M_PI/180.0); 63 | } 64 | else 65 | if(y > 270.0 && y <= 360) 66 | { 67 | x = -(360.0-y)*(M_PI/180.0); 68 | } 69 | else 70 | { 71 | printf("\n"); 72 | printf("Bad input !! Please try another angel\n"); 73 | printf("\n"); 74 | goto Z; 75 | } 76 | }// End of if(rank == 0) 77 | /******************************************************************************/ 78 | 79 | // broadcast input items "Q" & "x" to all processes. 80 | MPI_Bcast(&Q, 1, MPI_INT, 0, MPI_COMM_WORLD); 81 | MPI_Bcast(&x, 1, MPI_INT, 0, MPI_COMM_WORLD); 82 | 83 | // this loop increments the maximum number of iterations, thus providing 84 | // additional work for testing computational speed of the processors 85 | // for(total_iter = 1; total_iter < Q; total_iter++) 86 | { 87 | sum01 = 0; 88 | sum02 = 0; 89 | // for(total_iter = 1; i < total_iter; total_iter++) 90 | for(i = rank + 1; i <= Q; i += numprocs) 91 | { 92 | m = (i-1); 93 | /************************************************* 94 | * ***** SINE BLOCK ***** * 95 | *************************************************/ 96 | A = (double)pow(-1,m); 97 | B = 2*m+1; 98 | C = (double)pow(x,B); 99 | 100 | D = 1; 101 | for(j = 1; j <= B; j++) 102 | { 103 | D *= j; 104 | } 105 | 106 | E = (A*C)/(double)D; 107 | 108 | sum01 += E; 109 | 110 | /***************************************************** 111 | * ***** COSINE BLOCK ***** * 112 | *****************************************************/ 113 | F = (double)pow(-1,m); 114 | G = 2*m; 115 | H = (double)pow(x,G); 116 | 117 | I = 1; 118 | for(l = 1; l <= G; l++) 119 | { 120 | I *= l; 121 | } 122 | 123 | J = (F*H)/(double)I; 124 | 125 | sum02 += J; 126 | }// End of for(i = rank + 1; i <= Q; i += numprocs) 127 | 128 | rank_sum1 = sum01; 129 | rank_sum2 = sum02; 130 | 131 | // collect and add the partial sum0 values from all processes 132 | MPI_Reduce(&rank_sum1, &sum1, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 133 | MPI_Reduce(&rank_sum2, &sum2, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 134 | }//End of for(total_iter = 1; total_iter < n; total_iter++) 135 | 136 | if(rank == 0) 137 | { 138 | sum = sum1/sum2;// Tan(x) ==> Sine(x)/Cos(x) 139 | printf("\n"); 140 | printf("%.1f deg. = %.3f rads\n", y, x); 141 | printf("Tan(%.1f) = %.3f\n", y, sum); 142 | } 143 | 144 | // clean up, done with MPI 145 | MPI_Finalize(); 146 | 147 | return 0; 148 | }// End of int main(int argc, char*argv[]) 149 | 150 | 151 | -------------------------------------------------------------------------------- /Chapter09/13_Serial_ln.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | * *** Serial ln(x) code *** * 3 | * * 4 | * Taylor series representation * 5 | * of the trigonometric ln(x). * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 1/10/2017 * 10 | ********************************/ 11 | 12 | #include 13 | #include 14 | 15 | int main(void) 16 | { 17 | unsigned int n; 18 | unsigned long int k; 19 | double A,B,C; 20 | double sum=0; 21 | long int num_loops; 22 | float x,y; 23 | 24 | /******************************************************/ 25 | printf("\n"); 26 | printf("\n"); 27 | printf("Enter the number of iterations:\n"); 28 | printf("\n"); 29 | scanf("%d",&n); 30 | printf("\n"); 31 | Z:printf("Enter x value:\n"); 32 | printf("\n"); 33 | scanf("%f",&y); 34 | 35 | if(y > 0.0) 36 | { 37 | x = y; 38 | } 39 | else 40 | { 41 | printf("\n"); 42 | printf("Bad input !! Please try another value\n"); 43 | printf("\n"); 44 | goto Z; 45 | } 46 | /******************************************************/ 47 | 48 | sum = 0; 49 | for(k = 1; k < n; k++) 50 | { 51 | A = 1.0/(double)(2*k-1); 52 | B = pow(((x-1)/(x+1)),(2*k-1)); 53 | C = A*B; 54 | 55 | sum += C; 56 | } 57 | 58 | printf("\n"); 59 | printf("ln(%.1f) = %.16f\n", y, 2.0*sum); 60 | printf("\n"); 61 | 62 | return 0; 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /Chapter09/14_MPI_ln.c: -------------------------------------------------------------------------------- 1 | /******************************** 2 | * *** MPI ln(x) code. *** * 3 | * * 4 | * Taylor series representation * 5 | * of the trigonometric ln(x). * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 1/10/2017 * 10 | ********************************/ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char*argv[]) 17 | { 18 | /******************************************************/ 19 | long long int total_iter; 20 | unsigned int n; 21 | unsigned long int k; 22 | int rank,length,numprocs,i; 23 | float x,y; 24 | double sum,sum0,A,C,B,rank_sum; 25 | char hostname[MPI_MAX_PROCESSOR_NAME]; 26 | 27 | MPI_Init(&argc, &argv); // initiates MPI 28 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 29 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 30 | MPI_Get_processor_name(hostname, &length); // acquire hostname 31 | /******************************************************/ 32 | 33 | if(rank == 0) 34 | { 35 | printf("\n"); 36 | printf("#######################################################"); 37 | printf("\n\n"); 38 | printf("*** Number of processes: %d\n",numprocs); 39 | printf("*** processing capacity: %.1f GHz.\n",numprocs*1.2); 40 | printf("\n\n"); 41 | printf("Master node name: %s\n", hostname); 42 | printf("\n"); 43 | printf("\n"); 44 | printf("Enter the number of iterations:\n"); 45 | printf("\n"); 46 | scanf("%d",&n); 47 | printf("\n"); 48 | Z:printf("Enter x value:\n"); 49 | printf("\n"); 50 | scanf("%f",&y); 51 | 52 | if(y > 0.0) 53 | { 54 | x = y; 55 | } 56 | else 57 | { 58 | printf("\n"); 59 | printf("Bad input !! Please try another value\n"); 60 | printf("\n"); 61 | goto Z; 62 | } 63 | }// End of if(rank == 0) 64 | 65 | // broadcast input items "n" & "x" to all processes. 66 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 67 | MPI_Bcast(&x, 1, MPI_INT, 0, MPI_COMM_WORLD); 68 | 69 | //this loop increments the maximum number of iterations, thus providing 70 | //additional work for testing computational speed of the processors 71 | //for(total_iter = 1; total_iter < n; total_iter++) 72 | { 73 | sum0 = 0.0; 74 | // for(i = rank + 1; i <= total_iter; i += numprocs) 75 | for(i = rank + 1; i <= n; i += numprocs) 76 | { 77 | k = i; 78 | 79 | A = 1.0/(double)(2*k-1); 80 | B = pow(((x-1)/(x+1)),(2*k-1)); 81 | C = A*B; 82 | 83 | sum0 += C; 84 | } 85 | 86 | rank_sum = sum0;// Partial sum for a given rank 87 | 88 | // collect and add the partial sum0 values from all processes 89 | MPI_Reduce(&rank_sum, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 90 | }// End of for(total_iter = 1; total_iter < n; total_iter++) 91 | 92 | if(rank == 0) 93 | { 94 | printf("\n"); 95 | printf("ln(%.1f) = %.16f\n", y, 2.0*sum); 96 | printf("\n"); 97 | } 98 | 99 | //clean up, done with MPI 100 | MPI_Finalize(); 101 | 102 | return 0; 103 | }// End of int main(int argc, char*argv[]) 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /Chapter10/15_BK_wave4.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * FILE: mpi_wave.c * 3 | * OTHER FILES: draw_wave.c * 4 | * DESCRIPTION: * 5 | * MPI Concurrent Wave Equation - C Version * 6 | * Point-to-Point Communications Example * 7 | * This program implements the concurrent wave equation described * 8 | * in Chapter 5 of Fox et al., 1988, Solving Problems on Concurrent * 9 | * Processors, vol 1. * 10 | * A vibrating string is decomposed into points. Each processor is * 11 | * responsible for updating the amplitude of a number of points over * 12 | * time. At each iteration, each processor exchanges boundary points with * 13 | * nearest neighbors. This version uses low level sends and receives * 14 | * to exchange boundary points. * 15 | * AUTHOR: Blaise Barney. Adapted from Ros Leibensperger, Cornell Theory * 16 | * Center. Converted to MPI: George L. Gusciora, MHPCC (1/95) * 17 | * LAST REVISED: 07/05/05 * 18 | ****************************************************************************/ 19 | #include "mpi.h" 20 | #include 21 | #include 22 | #include 23 | 24 | #define MASTER 0 25 | #define TPOINTS 800 26 | #define MAXSTEPS 10000 27 | #define PI 3.14159265 28 | 29 | int RtoL = 10; 30 | int LtoR = 20; 31 | int OUT1 = 30; 32 | int OUT2 = 40; 33 | 34 | void init_master(void); 35 | void init_workers(void); 36 | void init_line(void); 37 | void update (int left, int right); 38 | void output_master(void); 39 | void output_workers(void); 40 | extern void draw_wave(double *); 41 | 42 | int taskid, /* task ID */ 43 | numtasks, /* number of processes */ 44 | nsteps, /* number of time steps */ 45 | npoints, /* number of points handled by this processor */ 46 | first; /* index of 1st point handled by this processor */ 47 | double etime, /* elapsed time in seconds */ 48 | values[TPOINTS+2], /* values at time t */ 49 | oldval[TPOINTS+2], /* values at time (t-dt) */ 50 | newval[TPOINTS+2]; /* values at time (t+dt) */ 51 | 52 | /* ------------------------------------------------------------------------ * 53 | * Master obtains timestep input value from user and broadcasts it * 54 | * ------------------------------------------------------------------------ */ 55 | void init_master(void) 56 | { 57 | char tchar[8]; 58 | /* Set number of number of time steps and then print and broadcast*/ 59 | nsteps = 0; 60 | while ((nsteps < 1) || (nsteps > MAXSTEPS)) 61 | { 62 | printf("\n"); 63 | printf("Enter number of time steps (1-%d): \n",MAXSTEPS); 64 | scanf("%s", tchar); 65 | nsteps = atoi(tchar); 66 | if((nsteps < 1) || (nsteps > MAXSTEPS)) 67 | { 68 | printf("Enter value between 1 and %d\n", MAXSTEPS); 69 | } 70 | } 71 | MPI_Bcast(&nsteps, 1, MPI_INT, MASTER, MPI_COMM_WORLD); 72 | }// End of void init_master(void) 73 | 74 | /* ------------------------------------------------------------------------- * 75 | * Workers receive timestep input value from master * 76 | * ------------------------------------------------------------------------- */ 77 | void init_workers(void) 78 | { 79 | MPI_Bcast(&nsteps, 1, MPI_INT, MASTER, MPI_COMM_WORLD); 80 | } 81 | 82 | /* ------------------------------------------------------------------------ * 83 | * All processes initialize points on line * 84 | * ------------------------------------------------------------------------ */ 85 | void init_line(void) 86 | { 87 | int nmin, nleft, npts, i, j, k; 88 | double x, fac; 89 | 90 | /* calculate initial values based on sine curve */ 91 | nmin = TPOINTS/numtasks; 92 | nleft = TPOINTS%numtasks; 93 | fac = 2.0 * PI; 94 | for (i = 0, k = 0; i < numtasks; i++) 95 | { 96 | npts = (i < nleft) ? nmin + 1 : nmin; 97 | if (taskid == i) 98 | { 99 | first = k + 1; 100 | npoints = npts; 101 | printf("task=%3d first point=%5d npoints=%4d\n", taskid, first, npts); 102 | for (j = 1; j <= npts; j++, k++) 103 | { 104 | x = (double)k/(double)(TPOINTS - 1); 105 | values[j] = sin (fac * x); 106 | } 107 | } 108 | else k += npts; 109 | } 110 | for(i = 1; i <= npoints; i++) 111 | { 112 | oldval[i] = values[i]; 113 | } 114 | }//End of void init_line(void) 115 | 116 | /* ------------------------------------------------------------------------- * 117 | * All processes update their points a specified number of times * 118 | * ------------------------------------------------------------------------- */ 119 | void update(int left, int right) 120 | { 121 | int i, j; 122 | double dtime, c, dx, tau, sqtau; 123 | MPI_Status status; 124 | 125 | dtime = 0.3; 126 | c = 1.0; 127 | dx = 1.0; 128 | tau = (c * dtime / dx); 129 | sqtau = tau * tau; 130 | 131 | /* Update values for each point along string */ 132 | for (i = 1; i <= nsteps; i++) 133 | { 134 | /* Exchange data with "left-hand" neighbor */ 135 | if(first != 1) 136 | { 137 | MPI_Send(&values[1], 1, MPI_DOUBLE, left, RtoL, MPI_COMM_WORLD); 138 | MPI_Recv(&values[0], 1, MPI_DOUBLE, left, LtoR, MPI_COMM_WORLD, &status); 139 | } 140 | /* Exchange data with "right-hand" neighbor */ 141 | if(first + npoints -1 != TPOINTS) 142 | { 143 | MPI_Send(&values[npoints], 1, MPI_DOUBLE, right, LtoR, MPI_COMM_WORLD); 144 | MPI_Recv(&values[npoints+1], 1, MPI_DOUBLE, right, RtoL, MPI_COMM_WORLD, &status); 145 | } 146 | /* Update points along line */ 147 | for(j = 1; j <= npoints; j++) 148 | { 149 | /* Global endpoints */ 150 | if((first + j - 1 == 1) || (first + j - 1 == TPOINTS)) 151 | newval[j] = 0.0; 152 | else 153 | /* Use wave equation to update points */ 154 | newval[j] = (2.0 * values[j]) - oldval[j] 155 | + (sqtau * (values[j-1] - (2.0 * values[j]) + values[j+1])); 156 | }// End of for(j = 1; j <= npoints; j++) 157 | for(j = 1; j <= npoints; j++) 158 | { 159 | oldval[j] = values[j]; 160 | values[j] = newval[j]; 161 | } 162 | }// End of for (i = 1; i <= nsteps; i++) 163 | }// End of void update(int left, int right) 164 | 165 | /* ------------------------------------------------------------------------ * 166 | * Master receives results from workers and prints * 167 | * ------------------------------------------------------------------------ */ 168 | void output_master(void) 169 | { 170 | int i, j, source, start, npts, buffer[2]; 171 | double results[TPOINTS]; 172 | MPI_Status status; 173 | 174 | /* Store worker's results in results array */ 175 | for(i = 1; i < numtasks; i++) 176 | { 177 | /* Receive first point, number of points and results */ 178 | MPI_Recv(buffer, 2, MPI_INT, i, OUT1, MPI_COMM_WORLD, &status); 179 | start = buffer[0]; 180 | npts = buffer[1]; 181 | MPI_Recv(&results[start-1], npts, MPI_DOUBLE, i, OUT2, MPI_COMM_WORLD, &status); 182 | } 183 | /* Store master's results in results array */ 184 | for(i = first; i < first + npoints; i++) 185 | { 186 | results[i-1] = values[i]; 187 | } 188 | j = 0; 189 | printf("***************************************************************\n"); 190 | printf("Final amplitude values for all points after %d steps:\n",nsteps); 191 | for(i = 0; i < TPOINTS; i++) 192 | { 193 | printf("%6.2f ", results[i]); 194 | j = j++; 195 | if (j == 10) 196 | { 197 | printf("\n"); 198 | j = 0; 199 | } 200 | } 201 | printf("***************************************************************\n"); 202 | printf("\nDrawing graph...\n"); 203 | printf("Click the EXIT button or use CTRL-C to quit\n"); 204 | 205 | /* display results with draw_wave routine */ 206 | // draw_wave(&results[0]); // <===================> 207 | }// End of void output_master(void) 208 | 209 | /* ------------------------------------------------------------------------- * 210 | * Workers send the updated values to the master * 211 | * ------------------------------------------------------------------------- */ 212 | 213 | void output_workers(void) 214 | { 215 | int buffer[2]; 216 | MPI_Status status; 217 | 218 | /* Send first point, number of points and results to master */ 219 | buffer[0] = first; 220 | buffer[1] = npoints; 221 | MPI_Send(&buffer, 2, MPI_INT, MASTER, OUT1, MPI_COMM_WORLD); 222 | MPI_Send(&values[1], npoints, MPI_DOUBLE, MASTER, OUT2, MPI_COMM_WORLD); 223 | }// End of void output_workers(void) 224 | 225 | /* ------------------------------------------------------------------------ * 226 | * Main program * 227 | * ------------------------------------------------------------------------ */ 228 | 229 | int main (int argc, char *argv[]) 230 | { 231 | int left, right, rc; 232 | 233 | /* Initialize MPI */ 234 | MPI_Init(&argc,&argv); 235 | MPI_Comm_rank(MPI_COMM_WORLD,&taskid); 236 | MPI_Comm_size(MPI_COMM_WORLD,&numtasks); 237 | if (numtasks < 2) 238 | { 239 | printf("ERROR: Number of MPI tasks set to %d\n",numtasks); 240 | printf("Need at least 2 tasks! Quitting...\n"); 241 | MPI_Abort(MPI_COMM_WORLD, rc); 242 | exit(0); 243 | } 244 | 245 | /* Determine left and right neighbors */ 246 | if(taskid == numtasks-1) 247 | { 248 | right = 0; 249 | } 250 | else 251 | { 252 | right = taskid + 1; 253 | } 254 | if(taskid == 0) 255 | { 256 | left = numtasks - 1; 257 | } 258 | else 259 | { 260 | left = taskid - 1; 261 | } 262 | /* Get program parameters and initialize wave values */ 263 | if(taskid == MASTER) 264 | { 265 | printf("\n"); 266 | printf ("Starting mpi_wave using %d tasks.\n", numtasks); 267 | printf ("Using %d points on the vibrating string.\n", TPOINTS); 268 | init_master(); 269 | } 270 | else 271 | { 272 | init_workers(); 273 | } 274 | init_line(); 275 | 276 | /* Update values along the line for nstep time steps */ 277 | update(left, right); 278 | 279 | /* Master collects results from workers and prints */ 280 | if(taskid == MASTER) 281 | { 282 | output_master(); 283 | } 284 | else 285 | { 286 | output_workers(); 287 | } 288 | MPI_Finalize(); 289 | return 0; 290 | }// End of int main (int argc, char *argv[]) -------------------------------------------------------------------------------- /Chapter11/16_Serial_Sawtooth.c: -------------------------------------------------------------------------------- 1 | /*********************************** 2 | * *** Serial sawtooth(x) code *** * 3 | * * 4 | * Fourier series representation * 5 | * of the sawtooth(x) function. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 2/12/2017 * 10 | ***********************************/ 11 | #include // math library 12 | #include // Standard Input / Output library 13 | 14 | int main(void) 15 | { 16 | int j; 17 | unsigned long int i; 18 | double sum0,sum1,A,B,C; 19 | double D[100]={0},x[100]={0},d,dd=10.00,o,oo=10.0*(M_PI/180); 20 | float Amp; 21 | float g; 22 | int m,n,p=36; 23 | 24 | printf("\n"); 25 | printf("#######################################################"); 26 | printf("\n\n"); 27 | 28 | printf("Enter number of iterations:\n"); 29 | scanf("%d",&n); 30 | printf("\n"); 31 | 32 | x[0] = 0; 33 | D[0] = 0; 34 | o = 0; 35 | d = 0; 36 | 37 | for(j = 0; j <= p; j += 1) 38 | { 39 | o += oo;// rads 40 | d += dd;// deg 41 | x[j+1] = o; 42 | D[j+1] = d; 43 | } 44 | 45 | printf("\n"); 46 | printf("Enter amplitude:\n"); 47 | scanf("%f",&Amp); 48 | printf("\n"); 49 | 50 | printf("Enter frequency(Hz.):\n"); 51 | scanf("%f",&g); 52 | printf("\n"); 53 | 54 | for(m = 0; m <= p; m++) 55 | { 56 | sum0 = 0.0; 57 | for(i = 1; i <= n; i++) 58 | { 59 | A = 1.0/(double)i; 60 | B = sin(i*g*x[m]); 61 | 62 | C = A*B; 63 | 64 | sum0 += C; 65 | }// End of for(i = 1; i <= n; i++) 66 | 67 | sum1 = Amp*(0.5-(1.0/M_PI)*sum0); 68 | printf(" x = %.3f rad, Amp. = %.3f, Deg. = %.1f\n",x[m],sum1,D[m]); 69 | }// End of for(m = 1; m <= p; m++) 70 | 71 | return 0; 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 | -------------------------------------------------------------------------------- /Chapter11/17_MPI_Sawtooth.c: -------------------------------------------------------------------------------- 1 | /********************************* 2 | * *** MPI sawtooth(x) code *** * 3 | * * 4 | * Fourier series representation * 5 | * of the sawtooth(x) function. * 6 | * * 7 | * Author: Carlos R. Morrison * 8 | * * 9 | * Date: 2/13/2017 * 10 | *********************************/ 11 | 12 | #include // (Open)MPI library 13 | #include // math library 14 | #include // Standard Input / Output library 15 | 16 | int main(int argc, char*argv[]) 17 | { 18 | long long int total_iter; 19 | int rank,length,numprocs,j; 20 | unsigned long int i; 21 | double sum,sum0,sum1,rank_integral,A,B,C; 22 | double D[100]={0},sm[100]={0},d,dd=10.00,x=0.0; 23 | float Amp,g; 24 | int m=0,n,p=36; 25 | char hostname[MPI_MAX_PROCESSOR_NAME]; 26 | 27 | MPI_Init(&argc, &argv); // initiates MPI 28 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 29 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 30 | MPI_Get_processor_name(hostname, &length); // acquire hostname 31 | 32 | if(rank == 0) 33 | { 34 | printf("\n"); 35 | printf("#######################################################"); 36 | printf("\n\n"); 37 | 38 | printf("*** Number of processes: %d\n",numprocs); 39 | printf("*** processing capacity: %.1f GHz.\n",numprocs*1.2); 40 | printf("\n\n"); 41 | printf("Master node name: %s\n", hostname); 42 | printf("\n"); 43 | 44 | printf("Enter number of iterations:\n"); 45 | scanf("%d",&n); 46 | printf("\n"); 47 | 48 | D[0] = 0; 49 | d = 0; 50 | for(j = 0; j <= p; j += 1) 51 | { 52 | d += dd;// deg 53 | D[j+1] = d; 54 | } 55 | 56 | printf("Enter amplitude:\n"); 57 | scanf("%f",&Amp); 58 | printf("\n"); 59 | 60 | printf("Enter frequency:\n"); 61 | scanf("%f",&g); 62 | printf("\n"); 63 | }// End of if(rank == 0) 64 | 65 | // broadcast g, n & x values to all processes. 66 | Z:MPI_Bcast(&g, 1, MPI_INT, 0, MPI_COMM_WORLD); 67 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 68 | MPI_Bcast(&x, 1, MPI_INT, 0, MPI_COMM_WORLD); 69 | 70 | // this loop increments the maximum number of iterations, thus providing 71 | // additional work for testing computational speed of the processors 72 | //for(total_iter = 1; total_iter < n; total_iter++) 73 | { 74 | sum0 = 0.0; 75 | // for(i = rank + 1; i <= total_iter; i += numprocs) 76 | for(i = rank + 1; i <= n; i += numprocs) 77 | { 78 | A = 1.0/(double)i; 79 | B = sin(i*g*x); 80 | C = A*B; 81 | 82 | sum0 += C;// ==> Summation element of the Fourier series 83 | }// End of for(i = rank + 1; i <= n; i += numprocs) 84 | 85 | rank_integral = sum0;// Partial sum for a given rank 86 | 87 | // collect and add the partial sum0 values from all processes 88 | MPI_Reduce(&rank_integral, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 89 | 90 | }// End of for(total_iter = 1; total_iter < n; total_iter++) 91 | 92 | m += 1;//counter for array angle D[] 93 | if(rank == 0) 94 | { 95 | sum1 = Amp*(0.5-(1.0/M_PI)*sum);// Sawtooth function 96 | printf(" x = %.3f rad, Amp. = %.3f, Deg. = %.1f\n",x,sum1,D[m-1]); 97 | }// End of if(rank == 0) 98 | 99 | if(m <= p) 100 | { 101 | x += dd*(M_PI/180);// Angle (radians) accumulator 102 | goto Z; 103 | } 104 | 105 | //clean up, done with MPI 106 | MPI_Finalize(); 107 | 108 | return 0; 109 | }// End of int main(int argc, char*argv[]) 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 | -------------------------------------------------------------------------------- /Chapter12Appendix/01_Ramanujan.c: -------------------------------------------------------------------------------- 1 | /******************************************* 2 | * *** Ramanujan MPI pi code. *** * 3 | * * 4 | * This infinite series concerges rapidly. * 5 | * Only two iterations for 15 decimal * 6 | * place accuracy. * 7 | * * 8 | * Author: Carlos R. Morrison * 9 | * * 10 | * Date: 1/11/2017 * 11 | *******************************************/ 12 | 13 | #include // (Open)MPI library 14 | #include // math library 15 | #include // Standard Input / Output library 16 | 17 | int main(int argc, char*argv[]) 18 | { 19 | int total_iter; 20 | int n,rank,length,numprocs; 21 | double pi,sum,sum0,x,rank_sum,A,B,C,D,E; 22 | char hostname[MPI_MAX_PROCESSOR_NAME]; 23 | 24 | unsigned long factorial(unsigned long number); 25 | unsigned long long i,j,k,l,m; 26 | double F = 2.0*sqrt(2.0)/9801.0; 27 | 28 | MPI_Init(&argc, &argv); // initiates MPI 29 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 30 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 31 | MPI_Get_processor_name(hostname, &length); // acquire hostname 32 | 33 | if (rank == 0) 34 | { 35 | printf("\n"); 36 | printf("#######################################################"); 37 | printf("\n\n\n"); 38 | printf("*** NUMBER OF PROCESSORS: %d\n",numprocs); 39 | printf("\n\n"); 40 | printf("MASTER NODE NAME: %s\n", hostname); 41 | printf("\n"); 42 | printf("Enter the number of iterations:\n"); 43 | printf("\n"); 44 | scanf("%d",&n); 45 | printf("\n"); 46 | } 47 | 48 | // broadcast the number of iteration "n" to all processes 49 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 50 | 51 | // this loop increments the maximum number of iterations, thus providing 52 | // additional work for testing computational speed of the processors 53 | // for(total_iter = 1; total_iter < n; total_iter++) 54 | { 55 | sum0 = 0.0; 56 | // for(i = rank + 1; i <= total_iter; i += numprocs) 57 | for(i = rank + 1; i <= n; i += numprocs) 58 | { 59 | k = i-1; 60 | 61 | A = 1; 62 | for(l=1; l <= 4*k; l++)// (4*k)! 63 | { 64 | A *= l; 65 | } 66 | 67 | B = (double)(1103+26390*k); 68 | 69 | C = 1; 70 | for(m=1; m <= k; m++)// k! 71 | { 72 | C *= m; 73 | } 74 | 75 | D = (double)pow(396,4*k); 76 | E = (double)A*B/(C*D); 77 | 78 | sum0 += E; 79 | 80 | }// End of for(i = rank + 1; i <= total_iter; i += numprocs) 81 | 82 | rank_sum = sum0;// Partial sum for a given rank 83 | 84 | // collect and add the partial sum0 values from all processes 85 | MPI_Reduce(&rank_sum, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 86 | 87 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 88 | 89 | if(rank == 0) 90 | { 91 | pi = 1.0/(F*sum); 92 | printf("\n\n"); 93 | printf(" Calculated pi = %.16f\n", pi); 94 | printf(" M_PI = %.16f\n", M_PI); 95 | printf(" Relative Error = %.16f\n", fabs(pi-M_PI)); 96 | printf("\n"); 97 | } 98 | 99 | // clean up, done with MPI 100 | MPI_Finalize(); 101 | 102 | return 0; 103 | }// End of int main(int argc, char*argv[]) 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Chapter12Appendix/02_Chudnovsky.c: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * Chudnovsky MPI pi code. * 3 | * * 4 | * This infinate series concerges * 5 | * rapidly. Only two iterations for * 6 | * 15 decimal place accuracy. * 7 | * * 8 | * Author: Carlos R. Morrison * 9 | * * 10 | * Date: 1/11/2017 * 11 | **************************************/ 12 | 13 | #include // (Open)MPI library 14 | #include // math library 15 | #include // Standard Input / Output library 16 | 17 | int main(int argc, char*argv[]) 18 | { 19 | int total_iter; 20 | int n,rank,length,numprocs; 21 | double pi; 22 | double sum0,x,rank_sum,A,B,C,D,E,G,H; 23 | double F = 12.0/pow(640320,1.5),sum; 24 | unsigned long long i,j,k,l,m; 25 | char hostname[MPI_MAX_PROCESSOR_NAME]; 26 | 27 | MPI_Init(&argc, &argv); // initiates MPI 28 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 29 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 30 | MPI_Get_processor_name(hostname, &length); // acquire hostname 31 | 32 | if (rank == 0) 33 | { 34 | printf("\n"); 35 | printf("#######################################################"); 36 | printf("\n\n\n"); 37 | printf("*** NUMBER OF PROCESSORS: %d\n",numprocs); 38 | printf("\n\n"); 39 | printf("MASTER NODE NAME: %s\n", hostname); 40 | printf("\n"); 41 | printf("Enter the number of iterations:\n"); 42 | printf("\n"); 43 | scanf("%d",&n); 44 | printf("\n"); 45 | } 46 | 47 | // broadcast to all processes, the number of segments you want 48 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 49 | 50 | // this loop increments the maximum number of iterations, thus providing 51 | // additional work for testing computational speed of the processors 52 | // for(total_iter = 1; total_iter < n; total_iter++) 53 | { 54 | sum0 = 0.0; 55 | // for(i = rank + 1; i <= total_iter; i += numprocs) 56 | for(i = rank + 1; i <= n; i += numprocs) 57 | { 58 | k = i-1; 59 | 60 | A = 1; 61 | for(j=1; j <= 6*k; j++)// (6*k)! 62 | { 63 | A *= j; 64 | } 65 | 66 | B = (double)(13591409+545140134*k); 67 | 68 | C = 1; 69 | for(l=1; l <= 3*k; l++)// k! 70 | { 71 | C *= l; 72 | } 73 | D = 1; 74 | for(m=1; m <= k; m++)// k! 75 | { 76 | D *= m; 77 | } 78 | 79 | E = pow(D,3);// (k!)^3 80 | G = (double)pow(-640320,3*k); 81 | H = (double)A*B/(C*E*G); 82 | 83 | sum0 += H; 84 | 85 | }// End of for(i = rank + 1; i <= total_iter; i += numprocs) 86 | 87 | rank_sum = sum0;// Partial sum for a given rank 88 | 89 | // collect and add the partial sum0 values from all processes 90 | MPI_Reduce(&rank_sum, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 91 | 92 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 93 | 94 | if(rank == 0) 95 | { 96 | printf("\n\n"); 97 | // printf("*** Number of processes: %d\n",numprocs); 98 | // printf("\n\n"); 99 | pi = 1.0/(F*sum); 100 | printf(" Calculated pi = %.16f\n", pi); 101 | printf(" M_PI = %.16f\n", M_PI); 102 | printf(" Relative Error = %.16f\n", fabs(pi-M_PI)); 103 | } 104 | 105 | // clean up, done with MPI 106 | MPI_Finalize(); 107 | 108 | return 0; 109 | }// End of int main(int argc, char*argv[]) 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /Chapter12Appendix/03_Unknown.c: -------------------------------------------------------------------------------- 1 | /***************************************** 2 | * *** Unknown MPI pi code. *** * 3 | * * 4 | * This infinate series calculates pi * 5 | * using MPI. It converges very slowely, * 6 | * requiring 1 billion iterations for * 7 | * eight decimal place accuracy. * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | *****************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n,rank,length,numprocs,i,k; 22 | double pi,sum,rank_integral,A,B; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if (rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("Master node name: %s\n", hostname); 36 | printf("\n"); 37 | printf("Enter the number of intervals:\n"); 38 | printf("\n"); 39 | scanf("%d",&n); 40 | printf("\n"); 41 | } 42 | 43 | // broadcast the number of iterations "n" to all processes. 44 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 45 | 46 | // this loop increments the maximum number of iterations, thus providing 47 | // additional work for testing computational speed of the processors 48 | // for(total_iter = 1; total_iter < n; total_iter++) 49 | { 50 | sum=0.0; 51 | // for(i = rank + 1; i <= total_iter; i += numprocs) 52 | for(i = rank + 1; i <= n; i += numprocs) 53 | { 54 | k = i - 1; 55 | A = 8.0/(double)(4*k+1); 56 | B = 1.0/(double)(4*k+3); 57 | 58 | sum += A*B; // sum of individual segment for a given rank 59 | } 60 | 61 | rank_integral = sum;// Partial sum for a given rank 62 | 63 | // collect and add the partial sum values from all processes 64 | MPI_Reduce(&rank_integral, &pi, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 65 | 66 | }// End of for(total_iter = 1; total_iter < n; total_iter++) 67 | 68 | if(rank == 0) 69 | { 70 | printf("\n\n"); 71 | printf("*** Number of processes: %d\n",numprocs); 72 | printf("\n\n"); 73 | printf(" Calculated pi = %.40f\n", pi); 74 | printf(" M_PI = %.40f\n", M_PI); 75 | printf(" Relative Error = %.40f\n", fabs(pi-M_PI)); 76 | printf("\n"); 77 | } 78 | 79 | // clean up, done with MPI 80 | MPI_Finalize(); 81 | return 0; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /Chapter12Appendix/04_Simon_Pluff.c: -------------------------------------------------------------------------------- 1 | /******************************************** 2 | * *** Simon_Pluff MPI pi code. **** * 3 | * * 4 | * This infinite series calculates pi using * 5 | * MPI. It converges rapidly, requiring * 6 | * only 12 iterations for 48 decimal place * 7 | * accuracy. * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | ********************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n,rank,length,numprocs,i,k; 22 | double pi,sum,rank_integral,A,B,C,D,E; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | MPI_Init(&argc, &argv); // initiates MPI 26 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 27 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 28 | MPI_Get_processor_name(hostname, &length); // acquire hostname 29 | 30 | if (rank == 0) 31 | { 32 | printf("\n"); 33 | printf("#######################################################"); 34 | printf("\n\n"); 35 | printf("Master node name: %s\n", hostname); 36 | printf("\n"); 37 | printf("Enter the number of intervals:\n"); 38 | printf("\n"); 39 | scanf("%d",&n); 40 | printf("\n"); 41 | } 42 | 43 | // broadcast to all processes, the number of segments you want 44 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 45 | 46 | // this loop increments the maximum number of iterations, thus providing 47 | // additional work for testing computational speed of the processors 48 | // for(total_iter = 1; total_iter < n; total_iter++) 49 | { 50 | sum=0.0; 51 | // for(i = rank + 1; i <= total_iter; i += numprocs) 52 | for(i = rank + 1; i <= n; i += numprocs) 53 | { 54 | k = i - 1; 55 | A = 4.0/(double)(8*k+1); 56 | B = -2.0/(double)(8*k+4); 57 | C = -1.0/(double)(8*k+5); 58 | D = -1.0/(double)(8*k+6); 59 | E = 1.0/(double)pow(16,k); 60 | 61 | sum += E*(A+B+C+D); // sum of individual segment height for a given rank 62 | } 63 | 64 | rank_integral = sum;// Partial sum for a given rank 65 | 66 | // collect and add the partial sum values from all processes 67 | MPI_Reduce(&rank_integral, &pi, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 68 | 69 | }// End of for(total_iter = 1; total_iter < n; total_iter++) 70 | 71 | if(rank == 0) 72 | { 73 | printf("\n\n"); 74 | printf("*** Number of processes: %d\n",numprocs); 75 | printf("\n\n"); 76 | printf(" Calculated pi = %.50f\n", pi); 77 | printf(" M_PI = %.50f\n", M_PI); 78 | printf(" Relative Error = %.50f\n", fabs(pi-M_PI)); 79 | printf("\n"); 80 | } 81 | 82 | // clean up, done with MPI 83 | MPI_Finalize(); 84 | return 0; 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Chapter12Appendix/05_Fabrice_Bellard.c: -------------------------------------------------------------------------------- 1 | /********************************************* 2 | * *** Fabrice_Bellard MPI pi code. **** * 3 | * * 4 | * This infinite series calculates pi using * 5 | * MPI. It converges rapidly, requiring Only * 6 | * six iterations for 15 decimal place * 7 | * accuracy * 8 | * * 9 | * Author: Carlos R. Morrison * 10 | * * 11 | * Date: 1/14/2017 * 12 | *********************************************/ 13 | 14 | #include // (Open)MPI library 15 | #include // math library 16 | #include // Standard Input / Output library 17 | 18 | int main(int argc, char*argv[]) 19 | { 20 | int total_iter; 21 | int n,rank,length,numprocs,i; 22 | double pi,sum,sum0,x,rank_sum,A,B,C,D,E,F,G,H,I; 23 | char hostname[MPI_MAX_PROCESSOR_NAME]; 24 | 25 | unsigned long factorial(unsigned long number); 26 | unsigned long k; 27 | double J = pow(2,-6); 28 | 29 | MPI_Init(&argc, &argv); // initiates MPI 30 | MPI_Comm_size(MPI_COMM_WORLD, &numprocs); // acquire number of processes 31 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); // acquire current process id 32 | MPI_Get_processor_name(hostname, &length); // acquire hostname 33 | 34 | if (rank == 0) 35 | { 36 | printf("\n"); 37 | printf("#######################################################"); 38 | printf("\n\n"); 39 | printf("Master node name: %s\n", hostname); 40 | printf("\n"); 41 | printf("Enter the number of iterations:\n"); 42 | printf("\n"); 43 | scanf("%d",&n); 44 | printf("\n"); 45 | } 46 | 47 | // broadcast to all processes, the number of segments you want 48 | MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 49 | 50 | // this loop increments the maximum number of iterations, thus providing 51 | // additional work for testing computational speed of the processors 52 | // for(total_iter = 1; total_iter < n; total_iter++) 53 | { 54 | sum0 = 0.0; 55 | // for(i = rank + 1; i <= total_iter; i += numprocs) 56 | for(i = rank + 1; i <= n; i += numprocs) 57 | { 58 | k = i-1; 59 | A = (double)pow(-1,k)/(double)pow(2,10*k); 60 | B = -(double)pow(2,5)/(double)(4*k+1); 61 | C = -1.0/(double)(4*k+3); 62 | D = (double)pow(2,8)/(double)(10*k+1); 63 | E = -(double)pow(2,6)/(double)(10*k+3); 64 | F = -(double)pow(2,2)/(double)(10*k+5); 65 | G = -(double)pow(2,2)/(double)(10*k+7); 66 | H = 1.0/(double)(10*k+9); 67 | I = A*(B+C+D+E+F+G+H); 68 | sum0 += I; 69 | }// End of for(i = rank + 1; i <= total_iter; i += numprocs) 70 | 71 | rank_sum = sum0;// Partial sum0 for a given rank 72 | 73 | // collect and add the partial sum0 values from all processes 74 | MPI_Reduce(&rank_sum, &sum, 1, MPI_DOUBLE,MPI_SUM, 0, MPI_COMM_WORLD); 75 | 76 | } // End of for(total_iter = 1; total_iter < n; total_iter++) 77 | 78 | if(rank == 0) 79 | { 80 | printf("\n\n"); 81 | printf("*** Number of processes: %d\n",numprocs); 82 | printf("\n\n"); 83 | pi = (J*sum); 84 | printf(" Calculated pi = %.16f\n", pi); 85 | printf(" M_PI = %.16f\n", M_PI); 86 | printf(" Relative Error = %.16f\n", fabs(pi-M_PI)); 87 | printf("\n"); 88 | } 89 | 90 | // clean up, done with MPI 91 | MPI_Finalize(); 92 | 93 | return 0; 94 | }// End of int main(int argc, char*argv[]) 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Build Supercomputers with Raspberry Pi 3 5 | This is the code repository for [Build Supercomputers with Raspberry Pi 3](https://www.packtpub.com/hardware-and-creative/build-supercomputers-raspberry-pi-3?utm_source=github&utm_medium=repository&utm_content=978-1-78728-258-2), published by Packt. It contains all the supporting project files necessary to work through the book from start to finish. 6 | 7 | ## About the Book 8 | This book's mission is to effectively instruct anyone, with basic computer hardware and software skills, on how to construct an affordable Pi3 supercomputer. If you are looking at performing high-level computation with microchips, then this book is for you. 9 | 10 | ## Instructions and Navigation 11 | All of the code is organized into folders. The commands and instructions will look like the following: 12 | 13 | #include // math library 14 | #include // Standard Input / Output library 15 | 16 | int main(void) 17 | { 18 | long num_rects = 300000;//1000000000; 19 | long i; 20 | double x,height,width,area; 21 | double sum; 22 | width = 1.0/(double)num_rects; // width of a segment 23 | 24 | sum = 0; 25 | for(i = 0; i < num_rects; i++) 26 | { 27 | x = (i+0.5) * width; // x: distance to center of i(th) segment 28 | height = 4/(1.0 + x*x); 29 | sum += height; // sum of individual segment heights 30 | } 31 | 32 | // approximate area of segment (Pi value) 33 | area = width * sum; 34 | 35 | printf("\n"); 36 | printf(" Calculated Pi = %.16f\n", area); 37 | printf(" M_PI = %.16f\n", M_PI); 38 | printf("Relative error = %.16f\n", fabs(area - M_PI)); 39 | 40 | return 0; 41 | } 42 | 43 | 44 | 45 | ## Related products: 46 | * [Building Smart Homes with Raspberry Pi Zero](https://www.packtpub.com/hardware-and-creative/building-smart-homes-raspberry-pi-zero?utm_source=github&utm_medium=repository&utm_content=9781786466952) 47 | * [Getting Started with Raspberry Pi Zero](https://www.packtpub.com/hardware-and-creative/getting-started-raspberry-pi-zero?utm_source=github&utm_medium=repository&utm_content=9781786469465) 48 | * [Raspberry Pi Home Automation with Arduino - Second Edition](https://www.packtpub.com/hardware-and-creative/raspberry-pi-home-automation-arduino-second-edition?utm_source=github&utm_medium=repository&utm_content=9781784399207) 49 | 50 | ### Suggestions and Feedback 51 | [Click here](https://docs.google.com/forms/d/e/1FAIpQLSe5qwunkGf6PUvzPirPDtuy1Du5Rlzew23UBp2S-P3wB-GcwQ/viewform) if you have any feedback or suggestions. 52 | ### Download a free PDF 53 | 54 | If you have already purchased a print or Kindle version of this book, you can get a DRM-free PDF version at no cost.
Simply click on the link to claim your free PDF.
55 |

https://packt.link/free-ebook/9781787282582

--------------------------------------------------------------------------------