int main ( void ) { # define NSUB 100 # define NL 1 //double adiag[NSUB+1]; double *adiag; adiag = (double *)malloc(sizeof(double)*(NSUB+1)); //double aleft[NSUB+1]; double *aleft; aleft = (double *)malloc(sizeof(double)*(NSUB+1)); //double arite[NSUB+1]; double *arite; arite = (double *)malloc(sizeof(double)*(NSUB+1)); double *f; f = (double *)malloc(sizeof(double)*(NSUB+1)); // double h[NSUB]; double *h; h = (double *)malloc(sizeof(double)*(NSUB)); int ibc; //int indx[NSUB+1]; int *indx; indx = (int *)malloc(sizeof(double)*(NSUB+1)); //int node[NL*NSUB]; int *node; node = (int*)malloc(sizeof(double)*(NL*NSUB)); int nquad; int nu; double ul; double ur; double xl; //double xn[NSUB+1]; double *xn; xn = (double *)malloc(sizeof(double)*(NSUB+1)); //double xquad[NSUB]; double *xquad; xquad = (double *)malloc(sizeof(double)*(NSUB)); double xr; timestamp ( ); FILE *fp, *fopen(); fp =fopen("originalout.txt","w+"); fprintf (fp, "\n" ); fprintf (fp, "FEM1D\n" ); fprintf (fp, " C version\n" ); fprintf (fp, "\n" ); fprintf (fp, " Solve the two-point boundary value problem\n" ); fprintf (fp, "\n" ); fprintf (fp, " - d/dX (P dU/dX) + Q U = F\n" ); fprintf (fp, "\n" ); fprintf (fp, " on the interval [XL,XR], specifying\n" ); fprintf (fp, " the value of U or U' at each end.\n" ); fprintf (fp, "\n" ); fprintf (fp, " The interval [XL,XR] is broken into NSUB = %d subintervals\n", NSUB ); fprintf (fp, " Number of basis functions per element is NL = %d\n", NL ); fclose(fp); /*********************************************** Start timing ************************************************/ struct timeval start, end; gettimeofday(&start, NULL); /*********************************************** ************************************************/ /* Initialize the data. */ init ( &ibc, &nquad, &ul, &ur, &xl, &xr ); /* Compute the geometric quantities. */ geometry ( h, ibc, indx, NL, node, NSUB, &nu, xl, xn, xquad, xr ); /* Assemble the linear system. */ assemble ( adiag, aleft, arite, f, h, indx, NL, node, nu, nquad, NSUB, ul, ur, xn, xquad ); /* Print out the linear system. */ prsys ( adiag, aleft, arite, f, nu ); /* Solve the linear system. */ solve ( adiag, aleft, arite, f, nu ); /* Print out the solution. */ output ( f, ibc, indx, NSUB, nu, ul, ur, xn ); /* Terminate. */ gettimeofday(&end, NULL); double delta = ((end.tv_sec - start.tv_sec) * 1000000u + end.tv_usec - start.tv_usec) / 1.e6; printf("time elapsed = %12.10f seconds\n",delta); FILE *dp, *fopen(); dp =fopen("originalout.txt","a"); fprintf (dp, "\n" ); fprintf (dp, "FEM1D:\n" ); fprintf (dp, " Normal end of execution.\n" ); timestamp ( ); fprintf(dp,"time elapsed = %12.10f seconds\n",delta); fclose(dp); printf ( "\n" ); return 0; # undef NL # undef NSUB }
/* Purpose: RUN is the main program for FEM1D. Discussion: FEM1D solves a one dimensional ODE using the finite element method. The differential equation solved is - d/dX (P dU/dX) + Q U = F The finite-element method uses piecewise linear basis functions. Here U is an unknown scalar function of X defined on the interval [XL,XR], and P, Q and F are given functions of X. The values of U or U' at XL and XR are also specified. The interval [XL,XR] is "meshed" with NSUB+1 points, XN(0) = XL, XN(1)=XL+H, XN(2)=XL+2*H, ..., XN(NSUB)=XR. This creates NSUB subintervals, with interval number 1 having endpoints XN(0) and XN(1), and so on up to interval NSUB, which has endpoints XN(NSUB-1) and XN(NSUB). Licensing: This code is distributed under the GNU LGPL license. Modified: 29 May 2009 Author: C version by John Burkardt Parameters: double ADIAG(NU), the "diagonal" coefficients. That is, ADIAG(I) is the coefficient of the I-th unknown in the I-th equation. double ALEFT(NU), the "left hand" coefficients. That is, ALEFT(I) is the coefficient of the (I-1)-th unknown in the I-th equation. There is no value in ALEFT(1), since the first equation does not refer to a "0-th" unknown. double ARITE(NU). ARITE(I) is the "right hand" coefficient of the I-th equation in the linear system. ARITE(I) is the coefficient of the (I+1)-th unknown in the I-th equation. There is no value in ARITE(NU) because the NU-th equation does not refer to an "NU+1"-th unknown. double F(NU). ASSEMBLE stores into F the right hand side of the linear equations. SOLVE replaces those values of F by the solution of the linear equations. double H(NSUB) H(I) is the length of subinterval I. This code uses equal spacing for all the subintervals. int IBC. IBC declares what the boundary conditions are. 1, at the left endpoint, U has the value UL, at the right endpoint, U' has the value UR. 2, at the left endpoint, U' has the value UL, at the right endpoint, U has the value UR. 3, at the left endpoint, U has the value UL, and at the right endpoint, U has the value UR. 4, at the left endpoint, U' has the value UL, at the right endpoint U' has the value UR. int INDX[NSUB+1]. For a node I, INDX(I) is the index of the unknown associated with node I. If INDX(I) is equal to -1, then no unknown is associated with the node, because a boundary condition fixing the value of U has been applied at the node instead. Unknowns are numbered beginning with 1. If IBC is 2 or 4, then there is an unknown value of U at node 0, which will be unknown number 1. Otherwise, unknown number 1 will be associated with node 1. If IBC is 1 or 4, then there is an unknown value of U at node NSUB, which will be unknown NSUB or NSUB+1, depending on whether there was an unknown at node 0. int NL. The number of basis functions used in a single subinterval. (NL-1) is the degree of the polynomials used. For this code, NL is fixed at 2, meaning that piecewise linear functions are used as the basis. int NODE[NL*NSUB]. For each subinterval I: NODE[0+I*2] is the number of the left node, and NODE[1+I*2] is the number of the right node. int NQUAD. The number of quadrature points used in a subinterval. This code uses NQUAD = 1. int NSUB. The number of subintervals into which the interval [XL,XR] is broken. int NU. NU is the number of unknowns in the linear system. Depending on the value of IBC, there will be NSUB-1, NSUB, or NSUB+1 unknown values, which are the coefficients of basis functions. double UL. If IBC is 1 or 3, UL is the value that U is required to have at X = XL. If IBC is 2 or 4, UL is the value that U' is required to have at X = XL. double UR. If IBC is 2 or 3, UR is the value that U is required to have at X = XR. If IBC is 1 or 4, UR is the value that U' is required to have at X = XR. double XL. XL is the left endpoint of the interval over which the differential equation is being solved. double XN(0:NSUB). XN(I) is the location of the I-th node. XN(0) is XL, and XN(NSUB) is XR. double XQUAD(NSUB) XQUAD(I) is the location of the single quadrature point in interval I. double XR. XR is the right endpoint of the interval over which the differential equation is being solved. */ double run(int version){ if(version == 0){ if((fp_out = fopen("old_out.txt", "w+")) == NULL || (fp_sol = fopen("old_sol.txt", "a")) == NULL){ printf("Old Version files not found.\n"); exit(EXIT_FAILURE); } } else if (version == 1){ if((fp_out = fopen("new_out.txt", "w+")) == NULL || (fp_sol = fopen("new_sol.txt", "a")) == NULL){ printf("New Version files not found.\n"); exit(EXIT_FAILURE); } } //Allocate array memory adiag = (double *)malloc(sizeof(double)*(double)(NSUB+1)); aleft = (double *)malloc(sizeof(double)*(double)(NSUB+1)); arite = (double *)malloc(sizeof(double)*(double)(NSUB+1)); f = (double *)malloc(sizeof(double)*(double)(NSUB+1)); h = (double *)malloc(sizeof(double)*(double)(NSUB)); indx = (int *)malloc(sizeof(int)*(int)(NSUB+1)); node = (int *)malloc(sizeof(int)*((int)NL*(int)NSUB)); xn = (double *)malloc(sizeof(double)*(double)(NSUB+1)); xquad = (double *)malloc(sizeof(double)*(double)(NSUB)); //START TIMER// double begin, end, time_spent; begin = omp_get_wtime(); timestamp (); fprintf (fp_out, "\n" ); fprintf (fp_out, "FEM1D\n" ); fprintf (fp_out, " C version\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out, " Solve the two-point boundary value problem\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out, " - d/dX (P dU/dX) + Q U = F\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out, " on the interval [XL,XR], specifying\n" ); fprintf (fp_out," the value of U or U' at each end.\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out," The interval [XL,XR] is broken into NSUB = %ld subintervals\n", NSUB ); fprintf (fp_out, " Number of basis functions per element is NL = %ld\n", NL ); /* Initialize the data. */ init (); /* Compute the geometric quantities. */ geometry (version); /* Assemble the linear system. */ assemble (version); /* Print out the linear system. */ prsys (); /* Solve the linear system. */ solve (); /* Print out the solution. */ output (version); /* Terminate. */ fprintf (fp_out, "\n" ); fprintf (fp_out,"FEM1D:\n" ); fprintf (fp_out, " Normal end of execution.\n" ); fprintf ( fp_out,"\n" ); //END TIMER// end = omp_get_wtime(); time_spent = end - begin; timestamp ( ); //CLOSE STREAMS fclose(fp_out); fclose(fp_sol); //FREE MEMORY free(adiag); free(aleft); free(arite); free(f); free(h); free(indx); free(node); free(xn); free(xquad); return time_spent; }
int main(int argc, char **argv){ bool error = false; //get NSUB, threads, tasks and trails from argument if(argc != 4){ error = true; } else if((NSUB = atoi(argv[1])) == 0) { printf("Invalid subdivison size.\n"); error = true; } else if ((NL = atoi(argv[2])) == 0){ printf("Invalid base function degree.\n"); error = true; } else if ((THREADS = atoi(argv[3])) == 0){ printf("Invalid number of threads.\n"); error = true; } if(error){ printf("Usage: mpirun -np [TASKS] new [SUB_SIZE] [NL] [NUM_THREADS]\n"); exit(EXIT_FAILURE); } if((fp_out = fopen("new_out.txt", "a")) == NULL || (fp_sol = fopen("new_sol.txt", "a")) == NULL){ printf("New Version files not found.\n"); exit(EXIT_FAILURE); } //Allocate array memory adiag = (double *)malloc(sizeof(double)*(double)(NSUB+1)); aleft = (double *)malloc(sizeof(double)*(double)(NSUB+1)); arite = (double *)malloc(sizeof(double)*(double)(NSUB+1)); f = (double *)malloc(sizeof(double)*(double)(NSUB+1)); h = (double *)malloc(sizeof(double)*(double)(NSUB)); indx = (int *)malloc(sizeof(int)*(int)(NSUB+1)); node = (int *)malloc(sizeof(int)*((int)NL*(int)NSUB)); xn = (double *)malloc(sizeof(double)*(double)(NSUB+1)); xquad = (double *)malloc(sizeof(double)*(double)(NSUB)); //START TIMER// double begin, end, time_spent; begin = omp_get_wtime(); //set number of threads omp_set_num_threads(THREADS); /****************** MPI Initialisations ***************/ MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided); if(provided != MPI_THREAD_FUNNELED){ return 1; } MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* set up block sizes for MPI work */ slaveSize1 = (NSUB+1) / numprocs; masterSize1 = slaveSize1 + ((NSUB+1) % numprocs); slaveSize2 = NSUB / numprocs; masterSize2 = slaveSize2 + (NSUB % numprocs); printf("MPI: Process %d of %d\n", rank, numprocs); /* If we are the master process Master coordinates the slaves */ if (rank == MASTER){ printf("MASTER: Number of processes is: %d\n",numprocs); timestamp (); fprintf (fp_out, "\n" ); fprintf (fp_out, "FEM1D\n" ); fprintf (fp_out, " C version\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out, " Solve the two-point boundary value problem\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out, " - d/dX (P dU/dX) + Q U = F\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out, " on the interval [XL,XR], specifying\n" ); fprintf (fp_out," the value of U or U' at each end.\n" ); fprintf (fp_out, "\n" ); fprintf (fp_out," The interval [XL,XR] is broken into NSUB = %ld subintervals\n", NSUB ); fprintf (fp_out, " Number of basis functions per element is NL = %ld\n", NL ); } //Initialize the data. init (); //Compute the geometric quantities. geometry (); //Assemble the linear system. assemble (); if(rank == MASTER){ //Print out the linear system. prsys (); //Solve the linear system. solve (); //Print out the solution. output (); } //Terminate. fprintf (fp_out, "\n" ); fprintf (fp_out,"FEM1D:\n" ); fprintf (fp_out, " Normal end of execution.\n" ); fprintf ( fp_out,"\n" ); //END TIMER// end = omp_get_wtime(); time_spent = end - begin; timestamp ( ); //CLOSE STREAMS fclose(fp_out); fclose(fp_sol); //FREE MEMORY free(adiag); free(aleft); free(arite); free(f); free(h); free(indx); free(node); free(xn); free(xquad); MPI_Finalize(); if(rank == MASTER){ FILE *fp_time = fopen("times.txt","a"); fprintf(fp_time, "%f\n", time_spent); } return 0; }
int main ( void ) /******************************************************************************/ /* Purpose: MAIN is the main program for FEM1D. Discussion: FEM1D solves a one dimensional ODE using the finite element method. The differential equation solved is - d/dX (P dU/dX) + Q U = F The finite-element method uses piecewise linear basis functions. Here U is an unknown scalar function of X defined on the interval [XL,XR], and P, Q and F are given functions of X. The values of U or U' at XL and XR are also specified. The interval [XL,XR] is "meshed" with NSUB+1 points, XN(0) = XL, XN(1)=XL+H, XN(2)=XL+2*H, ..., XN(NSUB)=XR. This creates NSUB subintervals, with interval number 1 having endpoints XN(0) and XN(1), and so on up to interval NSUB, which has endpoints XN(NSUB-1) and XN(NSUB). Licensing: This code is distributed under the GNU LGPL license. Modified: 29 May 2009 Author: C version by John Burkardt Parameters: double ADIAG(NU), the "diagonal" coefficients. That is, ADIAG(I) is the coefficient of the I-th unknown in the I-th equation. double ALEFT(NU), the "left hand" coefficients. That is, ALEFT(I) is the coefficient of the (I-1)-th unknown in the I-th equation. There is no value in ALEFT(1), since the first equation does not refer to a "0-th" unknown. double ARITE(NU). ARITE(I) is the "right hand" coefficient of the I-th equation in the linear system. ARITE(I) is the coefficient of the (I+1)-th unknown in the I-th equation. There is no value in ARITE(NU) because the NU-th equation does not refer to an "NU+1"-th unknown. double F(NU). ASSEMBLE stores into F the right hand side of the linear equations. SOLVE replaces those values of F by the solution of the linear equations. double H(NSUB) H(I) is the length of subinterval I. This code uses equal spacing for all the subintervals. int IBC. IBC declares what the boundary conditions are. 1, at the left endpoint, U has the value UL, at the right endpoint, U' has the value UR. 2, at the left endpoint, U' has the value UL, at the right endpoint, U has the value UR. 3, at the left endpoint, U has the value UL, and at the right endpoint, U has the value UR. 4, at the left endpoint, U' has the value UL, at the right endpoint U' has the value UR. int INDX[NSUB+1]. For a node I, INDX(I) is the index of the unknown associated with node I. If INDX(I) is equal to -1, then no unknown is associated with the node, because a boundary condition fixing the value of U has been applied at the node instead. Unknowns are numbered beginning with 1. If IBC is 2 or 4, then there is an unknown value of U at node 0, which will be unknown number 1. Otherwise, unknown number 1 will be associated with node 1. If IBC is 1 or 4, then there is an unknown value of U at node NSUB, which will be unknown NSUB or NSUB+1, depending on whether there was an unknown at node 0. int NL. The number of basis functions used in a single subinterval. (NL-1) is the degree of the polynomials used. For this code, NL is fixed at 2, meaning that piecewise linear functions are used as the basis. int NODE[NL*NSUB]. For each subinterval I: NODE[0+I*2] is the number of the left node, and NODE[1+I*2] is the number of the right node. int NQUAD. The number of quadrature points used in a subinterval. This code uses NQUAD = 1. int NSUB. The number of subintervals into which the interval [XL,XR] is broken. int NU. NU is the number of unknowns in the linear system. Depending on the value of IBC, there will be NSUB-1, NSUB, or NSUB+1 unknown values, which are the coefficients of basis functions. double UL. If IBC is 1 or 3, UL is the value that U is required to have at X = XL. If IBC is 2 or 4, UL is the value that U' is required to have at X = XL. double UR. If IBC is 2 or 3, UR is the value that U is required to have at X = XR. If IBC is 1 or 4, UR is the value that U' is required to have at X = XR. double XL. XL is the left endpoint of the interval over which the differential equation is being solved. double XN(0:NSUB). XN(I) is the location of the I-th node. XN(0) is XL, and XN(NSUB) is XR. double XQUAD(NSUB) XQUAD(I) is the location of the single quadrature point in interval I. double XR. XR is the right endpoint of the interval over which the differential equation is being solved. */ { # define NSUB 22 # define NL 20 double adiag[NSUB+1]; double aleft[NSUB+1]; double arite[NSUB+1]; double f[NSUB+1]; double h[NSUB]; int ibc; int indx[NSUB+1]; int node[NL*NSUB]; int nquad; int nu; double ul; double ur; double xl; double xn[NSUB+1]; double xquad[NSUB]; double xr; timestamp ( ); printf ( "\n" ); printf ( "FEM1D\n" ); printf ( " C version\n" ); printf ( "\n" ); printf ( " Solve the two-point boundary value problem\n" ); printf ( "\n" ); printf ( " - d/dX (P dU/dX) + Q U = F\n" ); printf ( "\n" ); printf ( " on the interval [XL,XR], specifying\n" ); printf ( " the value of U or U' at each end.\n" ); printf ( "\n" ); printf ( " The interval [XL,XR] is broken into NSUB = %d subintervals\n", NSUB ); printf ( " Number of basis functions per element is NL = %d\n", NL ); /* Initialize the data. */ init ( &ibc, &nquad, &ul, &ur, &xl, &xr ); /* Compute the geometric quantities. */ geometry ( h, ibc, indx, NL, node, NSUB, &nu, xl, xn, xquad, xr ); /* Assemble the linear system. */ assemble ( adiag, aleft, arite, f, h, indx, NL, node, nu, nquad, NSUB, ul, ur, xn, xquad ); /* Print out the linear system. */ prsys ( adiag, aleft, arite, f, nu ); /* Solve the linear system. */ solve ( adiag, aleft, arite, f, nu ); /* Print out the solution. */ output ( f, ibc, indx, NSUB, nu, ul, ur, xn ); /* Terminate. */ printf ( "\n" ); printf ( "FEM1D:\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; # undef NL # undef NSUB }