int main (int args, char* argv[]) { double length = LENGTH; //Axial length of vessel to simulate (in micrometers). double diameter= DIAMETER; double pi = 3.1415; //Steady state diameter of the simulated vessel (in micrometers). double hx_smc = HX_SMC; double hy_smc = HY_SMC; double hx_ec = HX_EC; double hy_ec = HY_EC; double new_length = (rint (length/hx_ec) ) * hx_ec; if (( (int)(new_length) % (int) (hx_smc) )!=0) hx_smc = new_length / (rint (new_length/hx_smc)) ; double new_circ= (rint (diameter * pi /hy_smc) ) * hy_smc; if (( (int)(new_circ) % (int) (hy_ec) )!=0) hy_ec = new_circ / (rint (new_circ/hy_ec)) ; grid.neq_smc = 26; grid.neq_ec = 4; grid.nodes_smc = (int) (length/hx_smc); grid.layers_smc = (int) (new_circ/hy_smc); grid.nodes_ec = (int) (length/hx_ec); grid.layers_ec = (int) (new_circ/hy_ec); grid.m = grid.nodes_smc*grid.layers_smc; grid.n = grid.nodes_ec *grid.layers_ec ; MPI_Init(&args, &argv); int tasks, myRank; MPI_Status status1,stat1,stat2,stat3,stat4; MPI_Request req1,req2,req3,req4; MPI_Comm_size(MPI_COMM_WORLD,&tasks); MPI_Comm_rank(MPI_COMM_WORLD,&myRank); FILE *errPT; char filename[10];int n; int kB=1024, MB= 1024*1024; sprintf(filename,"err.%d.txt",myRank); errPT = fopen(filename,"w+"); int n_smc,n_ec; if (myRank ==0) { printf("LENGTH = %2.5f\t\tDIAMETER(requested)= %2.5f\t\tDIAMETER(corrected)= %2.5f\t\tCIRCUMFERENCE = %2.5f\n\n",length,diameter,(new_circ/pi),new_circ); printf("SMC GRID INFO:\nNodes = %d\nLayers = %d\nHX = %f,HY = %f\nTotal cells = %d\n",grid.nodes_smc,grid.layers_smc,hx_smc,hy_smc,grid.m); printf("EC GRID INFO:\nNodes = %d\nLayers = %d\nHX = %f,HY = %f\nTotal cells = %d\n",grid.nodes_ec,grid.layers_ec,hx_ec,hy_ec,grid.n); //EC bit int r = grid.nodes_ec%tasks; if (r ==0) { n_ec = grid.nodes_ec/tasks; grid.n_ec= n_ec; for (int i=1;i<tasks;i++) MPI_Send(&n_ec,1,MPI_INT,i,000,MPI_COMM_WORLD); } else{ n_ec = (grid.nodes_ec - r )/tasks; grid.n_ec= n_ec; for (int i=1;i<tasks-1;i++) MPI_Send(&n_ec,1,MPI_INT,i,000,MPI_COMM_WORLD); n_ec=n_ec+r; MPI_Send(&n_ec,1,MPI_INT,(tasks-1),000,MPI_COMM_WORLD); } } else MPI_Recv(&grid.n_ec,1,MPI_INT,MASTER,000,MPI_COMM_WORLD,&status1); grid.n_smc = 13*grid.n_ec; //Each should perform this bit locally celltype1* smc_base; celltype2* ec_base; smc_base = (celltype1*) malloc((grid.layers_smc *grid.n_smc) * sizeof(celltype1)); if(smc_base==NULL){ fprintf(errPT,"Allocation failed for smc_base\n"); MPI_Abort(MPI_COMM_WORLD,100); } ec_base = (celltype2*) malloc((grid.layers_ec *grid.n_ec) * sizeof(celltype2)); if(ec_base==NULL){ fprintf(errPT,"Allocation failed for ec_base\n"); MPI_Abort(MPI_COMM_WORLD,100); } smc = (celltype1**) malloc(grid.layers_smc * sizeof(celltype1*)); if(smc==NULL){ fprintf(errPT,"Allocation failed for smc row dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } for (int i=0; i<grid.layers_smc; i++){ smc[i]= (celltype1*) malloc(grid.n_smc * sizeof(celltype1)); if(smc[i]==NULL){ fprintf(errPT,"Allocation failed for smc row # %d dimension\n",i); MPI_Abort(MPI_COMM_WORLD,100); } smc[i]= smc_base+(i*grid.n_smc); } ec = (celltype2**) malloc(grid.layers_ec * sizeof(celltype2*)); if(smc==NULL){ fprintf(errPT,"Allocation failed for smc row dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } for (int i=0; i<grid.layers_ec; i++){ ec[i]= (celltype2*) malloc(grid.n_ec * sizeof(celltype2)); if(ec[i]==NULL){ fprintf(errPT,"Allocation failed for ec row # %d dimension\n",i); MPI_Abort(MPI_COMM_WORLD,100); } ec[i]= ec_base+(i*grid.n_ec); } nn.sbuf_left = (double*)malloc( 3*(grid.layers_smc+grid.layers_ec) * sizeof(double)); if(nn.sbuf_left==NULL){ fprintf(errPT,"Allocation failed for nn.sbuf_left dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.sbuf_right = (double*)malloc( 3*(grid.layers_smc+grid.layers_ec) * sizeof(double)); if(nn.sbuf_right==NULL){ fprintf(errPT,"Allocation failed for nn.sbuf_right dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.rbuf_left = (double*)malloc( 3*(grid.layers_smc+grid.layers_ec) * sizeof(double)); if(nn.rbuf_left==NULL){ fprintf(errPT,"Allocation failed for nn.rbuf_left dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.rbuf_right = (double*)malloc( 3*(grid.layers_smc+grid.layers_ec) * sizeof(double)); if(nn.rbuf_right==NULL){ fprintf(errPT,"Allocation failed for nn.rbuf_right dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.left_smc_c = (double*)malloc( grid.layers_smc * sizeof(double)); if(nn.left_smc_c==NULL){ fprintf(errPT,"Allocation failed for nn.left_smc_c dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.right_smc_c = (double*)malloc( grid.layers_smc * sizeof(double)); if(nn.right_smc_c==NULL){ fprintf(errPT,"Allocation failed for nn.right_smc_c dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.left_ec_c = (double*)malloc( grid.layers_ec * sizeof(double)); if(nn.left_ec_c==NULL){ fprintf(errPT,"Allocation failed for nn.left_ec_c dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.right_ec_c = (double*)malloc( grid.layers_ec * sizeof(double)); if(nn.right_ec_c==NULL){ fprintf(errPT,"Allocation failed for nn.right_ec_c dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.left_smc_v = (double*)malloc( grid.layers_smc * sizeof(double)); if(nn.left_smc_v==NULL){ fprintf(errPT,"Allocation failed for nn.left_smc_v dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.right_smc_v = (double*)malloc( grid.layers_smc * sizeof(double)); if(nn.right_smc_v==NULL){ fprintf(errPT,"Allocation failed for nn.right_smc_v dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.left_ec_v = (double*)malloc( grid.layers_ec * sizeof(double)); if(nn.left_ec_v==NULL){ fprintf(errPT,"Allocation failed for nn.left_ec_v dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.right_ec_v = (double*)malloc( grid.layers_ec * sizeof(double)); if(nn.right_ec_v==NULL){ fprintf(errPT,"Allocation failed for nn.right_ec_v dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.left_smc_I = (double*)malloc( grid.layers_smc * sizeof(double)); if(nn.left_smc_I==NULL){ fprintf(errPT,"Allocation failed for nn.left_smc_I dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.right_smc_I = (double*)malloc( grid.layers_smc * sizeof(double)); if(nn.right_smc_I==NULL){ fprintf(errPT,"Allocation failed for nn.right_smc_I dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.left_ec_I = (double*)malloc( grid.layers_ec * sizeof(double)); if(nn.left_ec_I==NULL){ fprintf(errPT,"Allocation failed for nn.left_ec_I dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } nn.right_ec_I = (double*)malloc( grid.layers_ec * sizeof(double)); if(nn.right_ec_I==NULL){ fprintf(errPT,"Allocation failed for nn.right_ec_I dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } //Lodaing the information of rows and cols of each cell and allocating memory for various flux equations for(int i=0; i<grid.layers_smc; i++) { for (int j=0;j<grid.n_smc;j++) { smc[i][j].row = i; smc[i][j].col = j; /* smc[i][j].A = (double*) malloc(12*sizeof(double)); if(smc[i][j].A==NULL){ fprintf(errPT,"Allocation failed for smc[i][j].A dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } smc[i][j].B = (double*) malloc(3*sizeof(double)); if(smc[i][j].B==NULL){ fprintf(errPT,"Allocation failed for smc[i][j].B dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } smc[i][j].C = (double*) malloc(3*sizeof(double)); if(smc[i][j].C==NULL){ fprintf(errPT,"Allocation failed for smc[i][j].C dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); }*/ } } for(int i=0; i<grid.layers_ec; i++) { for (int j=0;j<grid.n_ec;j++) { ec[i][j].row = i; ec[i][j].col = j; /* ec[i][j].A = (double*) malloc(12*sizeof(double)); if(ec[i][j].A==NULL){ fprintf(errPT,"Allocation failed for ec[i][j].A dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } ec[i][j].B = (double*) malloc(3*sizeof(double)); if(ec[i][j].B==NULL){ fprintf(errPT,"Allocation failed for ec[i][j].B dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); } ec[i][j].C = (double*) malloc(3*sizeof(double)); if(ec[i][j].C==NULL){ fprintf(errPT,"Allocation failed for ec[i][j].C dimension\n"); MPI_Abort(MPI_COMM_WORLD,100); }*/ } } int total = (grid.neq_smc * grid.n_smc * grid.layers_smc) + (grid.neq_ec * grid.n_ec * grid.layers_ec); //Initialize and use the solver here RKSUITE rksuite; //Time variables double tfinal = TFINAL; double tnow = 0.0; double interval= INTERVAL; //File written every 1 second int file_write_per_unit_time=(int)(1/interval); //Error control variables double TOL = 1e-7; double thres[total]; for (int i= 0; i<total; i++) thres[i] = 1e-7; //Variables holding new and old values double* y = (double*) malloc (total * sizeof(double)); /***** INITIALIZATION SECTION ******/ int offset = 0; Initialize_tsoukias_smc(offset,y); offset = grid.n_smc*grid.layers_smc * grid.neq_smc; Initialize_koeingsberger_ec(offset, y); int i,j,k; for(i=0;i< grid.layers_smc; i++) { for (j=0;j<grid.n_smc;j++) { if (i>0) k=(i*grid.n_smc*grid.neq_smc); else if (i==0) k=0; smc[i][j].p = &y[k+(j*grid.neq_smc)+0]; } } offset = grid.n_smc*grid.layers_smc * grid.neq_smc; for(i=0;i< grid.layers_ec; i++) { for (j=0;j<grid.n_ec;j++) { if (i>0) k= offset+i*grid.n_ec*grid.neq_ec ; else if (i==0) k=offset+0; ec[i][j].q = &y[k+(j*grid.neq_ec)+0]; } } for(i=0;i< grid.layers_smc; i++) { for (j=0;j<grid.n_smc;j++) { smc[i][j].NE = 0.0; smc[i][j].NO = 0.0; smc[i][j].I_stim= 0.0; } } /***************************************************************/ double* yp= (double*) malloc (total * sizeof(double)); //Solver method int method = 2; //RK(4,5) //Statistics int totf,stpcst,acptstp; double waste,hnext; //Error Flag int cflag = 0, uflag =0; //Error extent monitor, to select best constant step of tolerances double* ymax = (double*) malloc(total * sizeof(double)); int state = couplingParms(CASE); if (myRank==0) printf("\n Step Size=%2.10lf\nUnit time in file write=%lf\n",interval,(double)file_write_per_unit_time*interval ); //Output file management FILE *time,*Task_info, *ci,*cj, *si,*sj, *vi,*vj, *Ii,*Ij, *cpv_i,*cpc_i,*cpi_i, *cpv_j,*cpc_j,*cpi_j; n=sprintf(filename,"t%d.txt",myRank); time = fopen(filename,"w+"); n=sprintf(filename,"Task_info%d.txt",myRank); Task_info= fopen(filename,"w+"); n=sprintf(filename,"smc_c%d.txt",myRank); ci = fopen(filename,"w+"); n=sprintf(filename,"ec_c%d.txt",myRank); cj = fopen(filename,"w+"); n=sprintf(filename,"ec_s%d.txt",myRank); sj = fopen(filename,"w+"); n=sprintf(filename,"smc_v%d.txt",myRank); vi = fopen(filename,"w+"); n=sprintf(filename,"ec_v%d.txt",myRank); vj = fopen(filename,"w+"); n=sprintf(filename,"smc_I%d.txt",myRank); Ii = fopen(filename,"w+"); n=sprintf(filename,"ec_I%d.txt",myRank); Ij = fopen(filename,"w+"); n=sprintf(filename,"cpv_i%d.txt",myRank); cpv_i = fopen(filename,"w+"); n=sprintf(filename,"cpc_i%d.txt",myRank); cpc_i = fopen(filename,"w+"); n=sprintf(filename,"cpi_i%d.txt",myRank); cpi_i = fopen(filename,"w+"); n=sprintf(filename,"cpc_j%d.txt",myRank); cpc_j = fopen(filename,"w+"); n=sprintf(filename,"cpv_j%d.txt",myRank); cpv_j = fopen(filename,"w+"); n=sprintf(filename,"cpi_j%d.txt",myRank); cpi_j = fopen(filename,"w+"); int count = 3*(grid.layers_smc+grid.layers_ec), buf_offset = 3*grid.layers_smc; int iteration=0; double Per_MPI_time_t1,Per_MPI_time_t2, Per_step_compute_time_t1,Per_step_compute_time_t2; double t1 = MPI_Wtime(); /********************************************************************/ for(int i=0; i<grid.layers_smc;i++) update_send_buffers_smc(myRank,tasks,i); for(int i=0; i<grid.layers_ec;i++) update_send_buffers_ec(myRank,tasks,i); my_boundary(myRank); update_async(myRank,tasks); retrive_recv_buffers_smc(myRank,tasks); retrive_recv_buffers_ec(myRank,tasks); /************************************************************************/ /*********************SOLVER SECTION*************************/ /************************************************************************/ tend = interval; rksuite.setup(total, tnow, y, tend, TOL, thres, method, "CT", false, 1e-5, false ); while (tnow <=10.00) { // the ct() function does not guarantee to advance all the // way to the stop time. Keep stepping until it does. do { computeDerivatives( tnow, y, yp ); rksuite.ct(computeDerivatives, tnow, y, yp, cflag ); if (cflag >= 5) { printf("RKSUITE error %d\n", cflag ); MPI_Abort(MPI_COMM_WORLD,1000); return false; break; } } while (tnow < tend); iteration++; /************************************************/ /* Communication Block */ /************************************************/ update_async(myRank,tasks); MPI_Barrier(MPI_COMM_WORLD); if (iteration==5){ fprintf(Task_info,"COUPLING COEFFICIENTS\n\n"); fprintf(Task_info,"g_hm_smc=\t%6.2lf\ng_hm_ec=\t%6.2lf\np_hm_smc=\t%6.2lf\np_hm_ec=\t%6.2lf\npIP_hm_smc=\t%6.2lf\npIP_hm_ec=\t%6.2lf\ng_ht_smc=\t%6.2lf\tg_ht_ec=\t%6.2lf\np_ht_smc=\t%6.2lf\tp_ht_ec=\t%6.2lf\npIP_ht_smc=\t%6.2lf\tpIP_ht_ec=\t%6.2lf\n", cpl_cef.g_hm_smc,cpl_cef.g_hm_ec,cpl_cef.p_hm_smc,cpl_cef.p_hm_ec,cpl_cef.pIP_hm_smc,cpl_cef.pIP_hm_ec,cpl_cef.g_ht_smc,cpl_cef.g_ht_ec,cpl_cef.p_ht_smc,cpl_cef.p_ht_ec, cpl_cef.pIP_ht_smc,cpl_cef.pIP_ht_ec); fprintf(Task_info,"\nSpatial Gradient info:\nMinimum JPLC\t=\t=%lf\nMaximum JPLC\t=\t=%lf\nGradient\t=\t=%lf\n" ,grid.min_jplc,grid.max_jplc,grid.gradient); fprintf(Task_info,"\nTotal Tasks=%d\tMyRank=%d\n\n",tasks,myRank); fprintf(Task_info,"LENGTH = %2.5f\nREQUESTED DIAMETER = %2.5f\nCORRECTED CIRCUMFERENCE = %2.5f\nTotal layers=%d\nTotal nodes=%d\n\n",length,diameter,new_circ,grid.layers_smc,grid.nodes_smc); fprintf(Task_info,"SMC GRID INFO:\nNodes = %d\nLayers = %d\nHX = %lf,HY = %lf\nTotal cells = %d\n\n",grid.n_smc,grid.layers_smc,hx_smc,hy_smc,grid.m); fprintf(Task_info,"EC GRID INFO:\nNodes = %d\nLayers = %d\nHX = %lf,HY = %lf\nTotal cells = %d\n\n",grid.n_ec,grid.layers_ec,hx_ec,hy_ec,grid.n); fprintf(Task_info,"JPLC (at t<100 seconds) in axial direction per EC\n"); for (int p=0; p<grid.n_ec; p++) fprintf(Task_info,"[%d]\t%lf\n",p,ec[0][p].JPLC); } if ((iteration==1)||(iteration % file_write_per_unit_time==0)) { fprintf(time,"%lf\n",tnow); for (int row=0; row<grid.layers_smc;row++) { for (int col=0; col<grid.n_smc; col++) { fprintf(ci,"%2.10lf",smc[row][col].p[smc_Ca_i]); fprintf(vi,"%2.10lf",smc[row][col].p[smc_V_m]); fprintf(Ii,"%2.10lf",smc[row][col].p[smc_IP3]); if (col<(grid.n_smc-1)){ fprintf(ci,"\t"); fprintf(vi,"\t"); fprintf(Ii,"\t"); } } if (row<(grid.layers_smc-1)){ fprintf(ci,"\t"); fprintf(vi,"\t"); fprintf(Ii,"\t"); } else if (row==(grid.layers_smc-1)){ fprintf(ci,"\n"); fprintf(vi,"\n"); fprintf(Ii,"\n"); } } for (int row=0; row<grid.layers_ec;row++) { for (int col=0; col<grid.n_ec; col++) { fprintf(cj,"%2.10lf\t",ec[row][col].q[ec_Ca]); fprintf(sj,"%2.10lf\t",ec[row][col].q[ec_SR]); fprintf(vj,"%2.10lf\t",ec[row][col].q[ec_Vm]); fprintf(Ij,"%2.10lf\t",ec[row][col].q[ec_IP3]); } if (row<(grid.layers_ec-1)){ fprintf(cj,"\t"); fprintf(sj,"\t"); fprintf(vj,"\t"); fprintf(Ij,"\t"); } else if (row==(grid.layers_ec-1)){ fprintf(cj,"\n"); fprintf(sj,"\n"); fprintf(vj,"\n"); fprintf(Ij,"\n"); } } fflush(time);fflush(Task_info);fflush(errPT); //fflush(MPI_stat); fflush(ci);fflush(cj); fflush(sj); fflush(vi);fflush(vj); fflush(Ii);fflush(Ij); fflush(cpv_i); fflush(cpc_i);fflush(cpi_i); fflush(cpv_j);fflush(cpc_j); fflush(cpi_j); } tend += interval; rksuite.reset(tend); } //end while() /****////////*******////////**************** /************************************************************************/ /*********************AFTER 10.00 seconds*************************/ /************************************************************************/ tend = tnow + interval; rksuite.setup(total, tnow, y, tend, TOL, thres, method, "CT", false, 1e-5, false ); while (tnow <=100.00) { // the ct() function does not guarantee to advance all the // way to the stop time. Keep stepping until it does. do { computeDerivatives( tnow, y, yp ); rksuite.ct(computeDerivatives, tnow, y, yp, cflag ); if (cflag >= 5) { printf("RKSUITE error %d\n", cflag ); MPI_Abort(MPI_COMM_WORLD,1000); return false; break; } } while (tnow < tend); iteration++; /************************************************/ /* Communication Block */ /************************************************/ update_async(myRank,tasks); MPI_Barrier(MPI_COMM_WORLD); if (iteration==5e3){ fprintf(Task_info,"JPLC (at 10<t<100 seconds) in axial direction per EC\n"); for (int p=0; p<grid.n_ec; p++) fprintf(Task_info,"[%d]\t%lf\n",p,ec[0][p].JPLC); } if (iteration % file_write_per_unit_time==0) { fprintf(time,"%lf\n",tnow); for (int row=0; row<grid.layers_smc;row++) { for (int col=0; col<grid.n_smc; col++) { fprintf(ci,"%2.10lf",smc[row][col].p[smc_Ca_i]); fprintf(vi,"%2.10lf",smc[row][col].p[smc_V_m]); fprintf(Ii,"%2.10lf",smc[row][col].p[smc_IP3]); if (col<(grid.n_smc-1)){ fprintf(ci,"\t"); fprintf(vi,"\t"); fprintf(Ii,"\t"); } } if (row<(grid.layers_smc-1)){ fprintf(ci,"\t"); fprintf(vi,"\t"); fprintf(Ii,"\t"); } else if (row==(grid.layers_smc-1)){ fprintf(ci,"\n"); fprintf(vi,"\n"); fprintf(Ii,"\n"); } } for (int row=0; row<grid.layers_ec;row++) { for (int col=0; col<grid.n_ec; col++) { fprintf(cj,"%2.10lf\t",ec[row][col].q[ec_Ca]); fprintf(sj,"%2.10lf\t",ec[row][col].q[ec_SR]); fprintf(vj,"%2.10lf\t",ec[row][col].q[ec_Vm]); fprintf(Ij,"%2.10lf\t",ec[row][col].q[ec_IP3]); } if (row<(grid.layers_ec-1)){ fprintf(cj,"\t"); fprintf(sj,"\t"); fprintf(vj,"\t"); fprintf(Ij,"\t"); } else if (row==(grid.layers_ec-1)){ fprintf(cj,"\n"); fprintf(sj,"\n"); fprintf(vj,"\n"); fprintf(Ij,"\n"); } } fflush(time);fflush(Task_info);fflush(errPT); //fflush(MPI_stat); fflush(ci);fflush(cj); fflush(sj); fflush(vi);fflush(vj); fflush(Ii);fflush(Ij); fflush(cpv_i); fflush(cpc_i);fflush(cpi_i); fflush(cpv_j);fflush(cpc_j); fflush(cpi_j); } tend += interval; rksuite.reset(tend); } //end while() /****////////*******////////**************** /************************************************************************/ /*** After 100 seconds ****/ /************************************************************************/ tend = tnow+interval; rksuite.setup(total, tnow, y, tend, TOL, thres, method, "CT", false, 1e-6, false ); while (tnow <=tfinal) { // the ct() function does not guarantee to advance all the // way to the stop time. Keep stepping until it does. do { computeDerivatives( tnow, y, yp ); rksuite.ct(computeDerivatives, tnow, y, yp, cflag ); if (cflag >= 5) { printf("RKSUITE error %d\n", cflag ); MPI_Abort(MPI_COMM_WORLD,1000); return false; break; } } while (tnow < tend); iteration++; /************************************************/ /* Communication Block */ /************************************************/ update_async(myRank,tasks); MPI_Barrier(MPI_COMM_WORLD); if (iteration==1e5) { fprintf(Task_info,"JPLC (at t>100 seconds) in axial direction per EC\n"); for (int p=0; p<grid.n_ec; p++) fprintf(Task_info,"[%d]\t%lf\n",p,ec[0][p].JPLC); } if (iteration % file_write_per_unit_time==0) { fprintf(time,"%lf\n",tnow); for (int row=0; row<grid.layers_smc;row++) { for (int col=0; col<grid.n_smc; col++) { fprintf(ci,"%2.10lf",smc[row][col].p[smc_Ca_i]); fprintf(vi,"%2.10lf",smc[row][col].p[smc_V_m]); fprintf(Ii,"%2.10lf",smc[row][col].p[smc_IP3]); if (col<(grid.n_smc-1)){ fprintf(ci,"\t"); fprintf(vi,"\t"); fprintf(Ii,"\t"); } } if (row<(grid.layers_smc-1)){ fprintf(ci,"\t"); fprintf(vi,"\t"); fprintf(Ii,"\t"); } else if (row==(grid.layers_smc-1)){ fprintf(ci,"\n"); fprintf(vi,"\n"); fprintf(Ii,"\n"); } } for (int row=0; row<grid.layers_ec;row++) { for (int col=0; col<grid.n_ec; col++) { fprintf(cj,"%2.10lf\t",ec[row][col].q[ec_Ca]); fprintf(sj,"%2.10lf\t",ec[row][col].q[ec_SR]); fprintf(vj,"%2.10lf\t",ec[row][col].q[ec_Vm]); fprintf(Ij,"%2.10lf\t",ec[row][col].q[ec_IP3]); } if (row<(grid.layers_ec-1)){ fprintf(cj,"\t"); fprintf(sj,"\t"); fprintf(vj,"\t"); fprintf(Ij,"\t"); } else if (row==(grid.layers_ec-1)){ fprintf(cj,"\n"); fprintf(sj,"\n"); fprintf(vj,"\n"); fprintf(Ij,"\n"); } } fflush(time);fflush(Task_info);fflush(errPT); //fflush(MPI_stat); fflush(ci);fflush(cj); fflush(sj); fflush(vi);fflush(vj); fflush(Ii);fflush(Ij); fflush(cpv_i); fflush(cpc_i);fflush(cpi_i); fflush(cpv_j);fflush(cpc_j); fflush(cpi_j); } tend += interval; rksuite.reset(tend); } //end while() /****////////*******////////**************** /************************************************************************/ double t2 = MPI_Wtime(); //printf("[%d] : Elapsed time = %lf\nMPI size=%d\ttfinal=%lf\tStep size=%lf\tcount=%d\n",myRank,(t2-t1),tasks,tfinal,interval,cnt2); fprintf(Task_info,"Elapsed time = %lf\ntfinal=%lf\nStep size=%lf\n",(t2-t1),tasks,tfinal,interval); MPI_Barrier(MPI_COMM_WORLD); if (myRank==0) printf("\nEND OF PROGRAM\n"); free(smc);free(smc_base); free(ec);free(ec_base); free(nn.sbuf_left); free(nn.sbuf_right); free(nn.rbuf_left); free(nn.rbuf_right); free(nn.left_smc_c); free(nn.right_smc_c); free(nn.left_ec_c); free(nn.right_ec_c); free(nn.left_smc_v); free(nn.right_smc_v); free(nn.left_ec_v); free(nn.right_ec_v); free(nn.left_smc_I); free(nn.right_smc_I); free(nn.left_ec_I); free(nn.right_ec_I); free(y); free(yp); free(ymax); fclose(time);fclose(Task_info); fclose(errPT); fclose(ci);fclose(cj); fclose(sj); fclose(vi);fclose(vj); fclose(Ii);fclose(Ij); fclose(cpv_i); fclose(cpc_i);fclose(cpi_i); fclose(cpv_j);fclose(cpc_j); fclose(cpi_j); MPI_Finalize(); }
int main (int argc, char* argv[]) { //// These are input parameters for the simulation int m=16, ///number of grid points in axial direction n=4, ///number of grid points in circumferential direction e=2, ///number of ECs per node s=3; ///number of SMCs per node ///Time variables double tfinal = 100.00; double interval = 1e-2; //File written every 1 second int file_write_per_unit_time=int(1/interval); ///Global variables that are to be read by each processor int nbrs[4], dims[2], periods[2], reorder, coords[2]; ///Global declaration of request and status update place holders. ///Request and Status handles for nonblocking Send and Receive operations, for communicating with each of the four neighbours. MPI_Request reqs[8]; MPI_Status stats[8]; ///Initialize MPI MPI_Init(&argc, &argv); int rank,numtasks; int outbuf, inbuf[4]={MPI_PROC_NULL,MPI_PROC_NULL,MPI_PROC_NULL,MPI_PROC_NULL}, source,dest; int tag=1; ///tag for messaging information for nearset neighbour. //Open an instance of a log file on each processor //Reveal information of myself and size of MPI_COMM_WORLD MPI_Comm_size(MPI_COMM_WORLD,&numtasks); MPI_Comm_rank(MPI_COMM_WORLD,&rank); dims[0] =m; dims[1] =n; periods[0] =0; periods[1] =1; reorder =0; int err; char filename[20]; //open an output stream for logfile ofstream logptr; err=sprintf(filename,"logfile%d.txt",rank); logptr.open(filename); if (!logptr.good()){logptr.open(filename,fstream::trunc);} bool a = logptr.is_open(); err=MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, reorder, &grid.comm); if(err!=MPI_SUCCESS){logptr<<rank<<": "<<"failed at cart create"<<endl;} err=MPI_Comm_rank(grid.comm, &grid.rank); if(err!=MPI_SUCCESS){logptr<<rank<<": "<<"failed at comm rank"<<endl;} err=MPI_Cart_coords(grid.comm, grid.rank, 2, coords); if(err!=MPI_SUCCESS){logptr<<rank<<": "<<"failed at cart coords"<<endl;} err=MPI_Cart_shift(grid.comm, 0, 1, &nbrs[UP], &nbrs[DOWN]); if(err!=MPI_SUCCESS){logptr<<rank<<": "<<"failed at cart shift up down"<<endl;} err=MPI_Cart_shift(grid.comm, 1, 1, &nbrs[LEFT], &nbrs[RIGHT]); if(err!=MPI_SUCCESS){logptr<<rank<<": "<<"failed at cart left right"<<endl;} //outbuf now contains the rank of a processor from cartcomm communicator outbuf = grid.rank; for (int i=0; i<4; i++) { dest = nbrs[i]; source = nbrs[i]; MPI_Isend(&outbuf, 1, MPI_INT, dest, tag, grid.comm, &reqs[i]); MPI_Irecv(&inbuf[i], 1, MPI_INT, source, tag, grid.comm, &reqs[i+4]); } MPI_Waitall(8, reqs, stats); logptr<<"rank="<<grid.rank<<"\t"<<"coords= "<<coords[0]<<","<<coords[1]<<"\t"<<"nbrs(u,d,l,r)="<<nbrs[UP]<<","<<nbrs[DOWN]<<","<<nbrs[LEFT]<<","<<nbrs[RIGHT]<<endl; ///Each tasks now calculates the number of ECs per node. if (m!=(numtasks/n)) e = m/numtasks; grid.nbrs[UP] = nbrs[UP]; grid.nbrs[DOWN] = nbrs[DOWN]; grid.nbrs[LEFT] = nbrs[LEFT]; grid.nbrs[RIGHT]= nbrs[RIGHT]; ///Each tasks now calculates the number of ECs per node. grid.num_fluxes_smc = 12; ///number of SMC Ioinic currents to be evaluated for eval of LHS of the d/dt terms of the ODEs. grid.num_fluxes_ec = 12; ///number of EC Ioinic currents to be evaluated for eval of LHS of the d/dt terms of the ODEs. grid.num_coupling_species_smc = 3; ///number of SMC coupling species homogenic /heterogenic grid.num_coupling_species_ec = 3; ///number of SMC coupling species homogenic /heterogenic if (m!=(numtasks/n)) e = m/numtasks; grid.neq_smc = 5; /// number of SMC ODEs for a single cell grid.neq_ec = 4; /// number of EC ODEs for a single cell grid.num_ec_axially = e; grid.num_smc_axially = e*13; grid.num_ec_circumferentially = s*5; grid.num_smc_circumferentially = s; grid.neq_ec_axially = grid.num_ec_axially * grid.neq_ec; grid.neq_smc_axially = grid.num_smc_axially * grid.neq_smc; grid.m = m; grid.n = n; ///Local and global MPI information. grid.numtasks = numtasks; //this is my rank in MPI_COMM_WORLD err = MPI_Comm_rank(MPI_COMM_WORLD,&grid.universal_rank); grid.universal_rank = rank; ///Now allocate memory space for the structures representing the cells and the various members of those structures. //Each of the two cell grids have two additional rows and two additional columns as ghost cells. //Follwing is an example of a 5x7 grid with added ghost cells on all four sides. the 0s are the actual //members of the grid whereas the + are the ghost cells. // + + + + + + + + + // + 0 0 0 0 0 0 0 + // + 0 0 0 0 0 0 0 + // + 0 0 0 0 0 0 0 + // + 0 0 0 0 0 0 0 + // + 0 0 0 0 0 0 0 + // + + + + + + + + + smc = (celltype1**) checked_malloc((grid.num_smc_circumferentially+2)* sizeof(celltype1*), stdout, "smc"); for (int i=0; i<=(grid.num_smc_circumferentially+2); i++){ smc[i] = (celltype1*) checked_malloc((grid.num_smc_axially+2)* sizeof(celltype1), stdout, "smc column dimension"); } ec = (celltype2**) checked_malloc((grid.num_ec_circumferentially+2)* sizeof(celltype2*), stdout, "ec"); for (int i=0; i<=(grid.num_ec_circumferentially+2); i++){ ec[i] = (celltype2*) checked_malloc((grid.num_ec_axially+2)* sizeof(celltype2), stdout, "ec column dimension"); } ///Memory allocation for state vector, the single cell evaluation placeholders (The RHS of the ODEs for each cell) and coupling fluxes is implemented in this section. ///In ghost cells, only the state vector array for each type of cells exists including all other cells. ///The memory is allocated for all the cells except the ghost cells, hence the ranges 1 to grid.num_ec_circumferentially(inclusive). ///SMC domain /*for (int i = 0; i <= grid.num_smc_circumferentially + 1; i++) { ///commented as this is probably not required for (int j = 0; j <= grid.num_smc_axially + 1; j++) { smc[i][j].p = (double*) checked_malloc( grid.num_neq_smc * sizeof(double*), stdout, "state vector in smc"); } }*/ for (int i = 1; i <= grid.num_smc_circumferentially; i++) { for (int j = 1; j <= grid.num_smc_axially; j++) { smc[i][j].A = (double*) checked_malloc( grid.num_fluxes_smc * sizeof(double), stdout, "matrix A in smc"); smc[i][j].B = (double*) checked_malloc( grid.num_coupling_species_smc * sizeof(double), stdout, "matrix B in smc"); smc[i][j].C = (double*) checked_malloc( grid.num_coupling_species_smc * sizeof(double), stdout, "matrix C in smc"); } } ///EC domain /* for (int i = 0; i <= grid.num_ec_circumferentially + 1; i++) { ///commented as this is probably not required for (int j = 0; j <= grid.num_ec_axially + 1; j++) { ec[i][j].q = (double*) checked_malloc( grid.num_neq_ec * sizeof(double*), stdout, "state vector in ec"); } }*/ for (int i = 1; i <= grid.num_ec_circumferentially; i++) { for (int j = 1; j <= grid.num_ec_axially; j++) { ec[i][j].A = (double*) checked_malloc( grid.num_fluxes_ec * sizeof(double), stdout, "matrix A in ec"); ec[i][j].B = (double*) checked_malloc( grid.num_coupling_species_ec * sizeof(double), stdout, "matrix B in ec"); ec[i][j].C = (double*) checked_malloc( grid.num_coupling_species_ec * sizeof(double), stdout, "matrix C in ec"); } } ///Allocating memory space for coupling data to be sent and received by MPI communication routines. ///sendbuf and recvbuf are 2D arrays having up,down,left and right directions as their first dimension. ///Each dimension is broken down into two segments, e.g. up1,up2,down1 & down2,etc.. ///The length of the second dimension is equal to half the number of cells for which the information is to be sent and received. ///Thus each communicating pair will exchange data twice to get the full lenght. sendbuf = (double**) checked_malloc(8 * sizeof(double*), stdout, "sendbuf dimension 1"); recvbuf = (double**) checked_malloc(8 * sizeof(double*), stdout, "recvbuf dimension 1"); ///Each processor now allocates the memory for send and recv buffers those will hold the coupling information. ///Since sendbuf must contain the information of number of SMCs and ECs being sent in the directions, ///the first two elements contain the total count of SMCs located on the rank in the relevant dimension (circumferential or axial) and the count of SMCs for which ///information is being sent, respectively. ///The next two elements contain the same information for ECs. int extent_s, extent_e; ///Variables to calculate the length of the prospective buffer based on number of cell in either orientations (circumferential or axial). grid.added_info_in_send_buf = 4; ///Number of elements containing additional information at the beginning of the send buffer. /// data to send to the neighbour in UP1 direction extent_s = (int) (ceil((double) (grid.num_smc_circumferentially) / 2)); extent_e = (int) (ceil((double) (grid.num_ec_circumferentially) / 2)); sendbuf[UP1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[UP1] dimension 2"); sendbuf[UP1][0] = (double) (1); //Start of the 1st segment of SMC array in in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP1][1] = (double) (extent_s); //End of the 1st segment of SMC array in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP1][2] = (double) (1); //Start of the 1st segment of EC array in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP1][3] = (double) (extent_e); ///End of the 1st segment of EC array in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[UP2] dimension 2"); sendbuf[UP2][0] = (double) (extent_s -1); //Start of the 2nd segment of SMC array in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP2][1] = (double) (grid.num_smc_circumferentially); //End of the 2nd segment of SMC array in in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP2][2] = (double) (extent_e -1); //Start of the 2nd segment of EC array in in UP direction (circumferential direction) to be sent to neighbouring processor sendbuf[UP2][3] = (double) (grid.num_ec_circumferentially); //End of the 2nd segment of EC array in in UP direction (circumferential direction) to be sent to neighbouring processor /// data to receive from the neighbour in UP direction recvbuf[UP1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[UP1] dimension 2"); recvbuf[UP2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[UP2] dimension 2"); /// data to send to the neighbour in DOWN direction sendbuf[DOWN1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[DOWN1] dimension 2"); sendbuf[DOWN1][0] = (double) (1); //Start of the 1st segment of SMC array in in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN1][1] = (double) (extent_s); //End of the 1st segment of SMC array in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN1][2] = (double) (1); //Start of the 1st segment of EC array in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN1][3] = (double) (extent_e); ///End of the 1st segment of EC array in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[DOWN2] dimension 2"); sendbuf[DOWN2][0] = (double) (extent_s -1); //Start of the 2nd segment of SMC array in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN2][1] = (double) (grid.num_smc_circumferentially); //End of the 2nd segment of SMC array in in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN2][2] = (double) (extent_e -1); //Start of the 2nd segment of EC array in in DOWN direction (circumferential direction) to be sent to neighbouring processor sendbuf[DOWN2][3] = (double) (grid.num_ec_circumferentially); //End of the 2nd segment of EC array in in DOWN direction (circumferential direction) to be sent to neighbouring processor /// data to recv from the neighbour in DOWN direction recvbuf[DOWN1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[DOWN1] dimension 2"); recvbuf[DOWN2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[DOWN2] dimension 2"); /// data to send to the neighbour in LEFT direction extent_s = (int) (ceil((double) (grid.num_smc_axially) / 2)); extent_e = (int) (ceil((double) (grid.num_ec_axially) / 2)); sendbuf[LEFT1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[LEFT1] dimension 2"); sendbuf[LEFT1][0] = (double) (1); //Start of the 1st segment of SMC array in in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT1][1] = (double) (extent_s); //END of the 1st segment of SMC array in in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT1][2] = (double) (1); //Start of the 1st segment of EC array in in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT1][3] = (double) (extent_e); //END of the 1st segment of EC array in in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[LEFT2] dimension 2"); sendbuf[LEFT2][0] = (double) (extent_s -1); //Start of the 2nd segment of SMC array in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT2][1] = (double) (grid.num_smc_axially);//END of the 2nd segment of SMC array in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT2][2] = (double) (extent_e-1); //Start of the 2nd segment of EC array in LEFT direction (circumferential direction) to be sent to neighbouring processor sendbuf[LEFT2][3] = (double) (grid.num_ec_axially); //END of the 2nd segment of EC array in LEFT direction (circumferential direction) to be sent to neighbouring processor /// data to receive from the neighbour in LEFT direction recvbuf[LEFT1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[LEFT1] dimension 2"); recvbuf[LEFT2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[LEFT2] dimension 2"); /// data to send to the neighbour in RIGHT direction extent_s = (int) (ceil((double) (grid.num_smc_axially) / 2)); extent_e = (int) (ceil((double) (grid.num_ec_axially) / 2)); sendbuf[RIGHT1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[RIGHT1] dimension 2"); sendbuf[RIGHT1][0] = (double) (1); //Start of the 1st segment of SMC array in in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT1][1] = (double) (extent_s); //END of the 1st segment of SMC array in in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT1][2] = (double) (1); //Start of the 1st segment of EC array in in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT1][3] = (double) (extent_e); //END of the 1st segment of EC array in in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "sendbuf[RIGHT2] dimension 2"); sendbuf[RIGHT2][0] = (double) (extent_s -1); //Start of the 2nd segment of SMC array in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT2][1] = (double) (grid.num_smc_axially);//END of the 2nd segment of SMC array in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT2][2] = (double) (extent_e-1); //Start of the 2nd segment of EC array in RIGHT direction (circumferential direction) to be sent to neighbouring processor sendbuf[RIGHT2][3] = (double) (grid.num_ec_axially); //END of the 2nd segment of EC array in RIGHT direction (circumferential direction) to be sent to neighbouring processor /// data to receive from the neighbour in RIGHT direction recvbuf[RIGHT1] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[RIGHT1] dimension 2"); recvbuf[RIGHT2] = (double*) checked_malloc( grid.added_info_in_send_buf + (grid.num_coupling_species_smc * extent_s + grid.num_coupling_species_ec * extent_e) * sizeof(double), stdout, "recvbuf[RIGHT2] dimension 2"); int NEQ = grid.neq_smc*(grid.num_smc_axially*grid.num_smc_circumferentially) + grid.neq_ec*(grid.num_ec_axially*grid.num_ec_circumferentially); ///Setup output streams to write data in files. Each node opens an independent set of files and write various state variables into it. checkpoint_handle *check = initialise_checkpoint(myRank); ofstream Time, ci,si,vi,wi,Ii,cpCi,cpVi,cpIi, cj,sj,vj,Ij,cpCj,cpVj,cpIj; err = sprintf(filename, "time%d.txt", grid.universal_rank); Time.open(filename); if (!Time.good()){ Time.open(filename, fstream::trunc);} err = sprintf(filename, "smc_c%d.txt", grid.universal_rank); ci.open(filename); if (!ci.good()){ci.open(filename, fstream::trunc);} err = sprintf(filename, "smc_s%d.txt", grid.universal_rank); si.open(filename); if (!si.good()){si.open(filename, fstream::trunc);} err = sprintf(filename, "smc_v%d.txt", grid.universal_rank); vi.open(filename); if (!vi.good()){vi.open(filename, fstream::trunc);} err = sprintf(filename, "smc_w%d.txt", grid.universal_rank); wi.open(filename); if (!wi.good()){wi.open(filename, fstream::trunc);} err = sprintf(filename, "smc_I%d.txt", grid.universal_rank); Ii.open(filename); if (!Ii.good()){Ii.open(filename, fstream::trunc);} err = sprintf(filename, "ec_c%d.txt", grid.universal_rank); cj.open(filename); if (!cj.good()){cj.open(filename, fstream::trunc);} err = sprintf(filename, "ec_s%d.txt", grid.universal_rank); sj.open(filename); if (!sj.good()){sj.open(filename, fstream::trunc);} err = sprintf(filename, "ec_v%d.txt", grid.universal_rank); vj.open(filename); if (!vj.good()){vj.open(filename, fstream::trunc);} err = sprintf(filename, "ec_I%d.txt", grid.universal_rank); Ij.open(filename); if (!Ij.good()){Ij.open(filename, fstream::trunc);} err = sprintf(filename, "smc_cpC%d.txt", grid.universal_rank); cpCi.open(filename); if (!cpCi.good()){cpCi.open(filename, fstream::trunc);} err = sprintf(filename, "ec_cpC%d.txt", grid.universal_rank); cpCj.open(filename); if (!cpCj.good()){cpCj.open(filename, fstream::trunc);} err = sprintf(filename, "smc_cpV%d.txt", grid.universal_rank); cpVi.open(filename); if (!cpVi.good()){cpVi.open(filename, fstream::trunc);} err = sprintf(filename, "ec_cpV%d.txt", grid.universal_rank); cpVj.open(filename); if (!cpVj.good()){cpVj.open(filename, fstream::trunc);} err = sprintf(filename, "smc_cpI%d.txt", grid.universal_rank); cpIi.open(filename); if (!cpIi.good()){cpIi.open(filename, fstream::trunc);} err = sprintf(filename, "ec_cpI%d.txt", grid.universal_rank); cpIj.open(filename); if (!cpIj.good()){cpIj.open(filename, fstream::trunc);} ///Setting up the solver RKSUITE rksuite; double tnow = 0.0; //Error control variables double TOL = 1e-6; double * thres = (double*)checked_malloc(NEQ*sizeof(double),stdout,"Threshod array for RKSUITE"); for (int i=1; i<=NEQ; i++) thres[i] = 1e-6; //Variables holding new and old values double* y = (double*)checked_malloc(NEQ*sizeof(double),stdout,"Solver array y for RKSUITE"); double* yp= (double*)checked_malloc(NEQ*sizeof(double),stdout,"Solver array yp for RKSUITE"); double* ymax= (double*)checked_malloc(NEQ*sizeof(double),stdout,"Solver array ymax for RKSUITE"); double* derivative= (double*)checked_malloc(NEQ*sizeof(double),stdout,"Solver array derivative for RKSUITE"); ///Mapping state vectors of each cell (all except the ghost cells) to the corresponding locations on the solver's solution array y[]. int k=0,offset; for(i=1;i<=grid.num_smc_circumferentially; i++){ for (j=1;j<=grid.num_smc_axially;j++){ if (i>1) k=((i-1)*grid.neq_smc_axially); else if (i==1) k=0; smc[i][j].p[smc_Ca] = &y[k+((j-1)*grid.neq_smc)+0]; smc[i][j].p[smc_Vm] = &y[k+((j-1)*grid.neq_smc)+1]; smc[i][j].p[smc_SR] = &y[k+((j-1)*grid.neq_smc)+2]; smc[i][j].p[smc_w] = &y[k+((j-1)*grid.neq_smc)+3]; smc[i][j].p[smc_IP3]= &y[k+((j-1)*grid.neq_smc)+4]; } } offset = (grid.neq_smc*grid.num_smc_circumferentially*grid.num_smc_axially); for(i=1; i<= grid.num_ec_circumferentially; i++){ for (j=1;j<= grid.num_ec_axially; j++){ if (i>1) k= offset+((i-1)*grid.neq_ec_axially); else if (i==1) k=offset+0; ec[i][j].q[ec_Ca] = &y[k+((j-1)*grid.neq_ec)+0]; ec[i][j].q[ec_Vm] = &y[k+((j-1)*grid.neq_ec)+1]; ec[i][j].q[ec_SR] = &y[k+((j-1)*grid.neq_ec)+2]; ec[i][j].q[ec_IP3] = &y[k+((j-1)*grid.neq_ec)+3]; } } ///Initialize different state variables and coupling data values. void Initialize_koeingsberger_smc(grid); void Initialize_koeingsberger_ec(grid); //Solver method int method = 2; //RK(4,5) //Error Flag int uflag = 0; int state = couplingParms(CASE); int itteration=0; double tend; ///Write my local information in my rank's logfile logptr<<"COUPLING COEFFICIENTS"<<endl <<"g_hm_smc=\t"<<cpl_cef.g_hm_smc<<endl <<"g_hm_ec=\t"<<cpl_cef.g_hm_ec<<endl <<"p_hm_smc=\t"<<cpl_cef.p_hm_smc<<endl <<"p_hm_ec=\t"<<cpl_cef.p_hm_ec<<endl <<"pIP_hm_smc=\t"<<cpl_cef.pIP_hm_smc<<endl <<"pIP_hm_ec=\t"<<cpl_cef.pIP_hm_ec<<endl <<"g_ht_smc=\t"<<cpl_cef.g_ht_smc<<endl <<"g_ht_ec=\t"<<cpl_cef.g_ht_ec<<endl <<"p_ht_smc=\t"<<cpl_cef.p_ht_smc<<endl <<"p_ht_ec=\t"<<cpl_cef.p_ht_ec<<endl <<"pIP_ht_smc=\t"<<cpl_cef.pIP_ht_smc<<endl <<"pIP_ht_ec=\t"<<cpl_cef.pIP_ht_ec<<endl; logptr<<"Spatial Gradient info:"<<endl; //logptr<<"Minimum JPLC\t="<<min_jplc<<endl; //logptr<<"Maximum JPLC\t"<<max_jplc<<endl; //logptr<<"Gradient\t"<<gradient<<endl; logptr<<"Total Tasks="<<numtasks<<endl; logptr<<"Number of grid points in axial direction = "<<m<<endl; logptr<<"Number of grid points in circumferential direction = "<<n<<endl; logptr<<"Number of ECs per node (axially) = "<<grid.num_ec_axially<<endl; logptr<<"Number of SMCs per node (circumferentially) = "<<grid.num_smc_circumferentially<<endl; logptr<<"Total ECs on this node = "<< (grid.num_ec_axially * grid.num_ec_circumferentially)<<endl; logptr<<"Total SMCs on this node = "<< (grid.num_smc_axially * grid.num_smc_circumferentially)<<endl<<endl; logptr<<"Total number of cells on this node ="<<(grid.num_ec_axially * grid.num_ec_circumferentially)+(grid.num_smc_axially * grid.num_smc_circumferentially)<<endl; logptr<<"Total number of cells in the full computational domain = "<<((grid.num_ec_axially * grid.num_ec_circumferentially)+(grid.num_smc_axially * grid.num_smc_circumferentially))*numtasks<<endl; logptr<<"Total number of equations in the full computational domain = "<<NEQ*numtasks<<endl; ///Solver section rksuite.setup(NEQ, tnow, y, tfinal, TOL, thres, method, "UT", false, 0.00, false ); MPI_Barrier(MPI_COMM_WORLD); communication_async_send_recv(logptr); ///Iterative calls to the solver start here. for (tend = interval; tend < tfinal; tend+=interval) { /// RKSUITE UT Call /// prototype (f,twant,tgot,ygot,ypgot,ymax,work,uflag) rksuite.ut( computeDerivatives,tend,tnow, y, yp,ymax,uflag); if (uflag >= 5) { logptr<<rank<<"RKSUITE error "<<uflag<<" occured at t = "<<tnow<<endl; MPI_Abort(MPI_COMM_WORLD,grid.universal_rank); } ///Increament the itteration as rksuite has finished solving between bounds tnow<= t <= tend. itteration++; /// Call for interprocessor communication MPI_Barrier(MPI_COMM_WORLD); communication_async_send_recv(logptr); if (itteration==5){ logptr<<"At t= "<<tend; for (int j =1; j<=e; j++) logptr<<"JPLC["<<j<<"]= "<<ec[0][j-1].JPLC<<"\t"; logptr<<endl; } if (itteration==1e5){ logptr<<"At t= "<<tend; for (int j =1; j<=e; j++) logptr<<"JPLC["<<j<<"]= "<<ec[0][j-1].JPLC<<"\t"; logptr<<endl; } if ((itteration % file_write_per_unit_time)==0){ Time<<tend<<endl; for (int i =1; i<=grid.num_smc_circumferentially; i++){ for(int j=1; j<=grid.num_smc_axially; j++){ ci<<smc[i-1][j-1].c<<"\t"; si<<smc[i-1][j-1].s<<"\t"; vi<<smc[i-1][j-1].v<<"\t"; wi<<smc[i-1][j-1].w<<"\t"; Ii<<smc[i-1][j-1].I<<"\t"; cpCi<<smc[i-1][j-1].B[0]<<"\t"; cpVi<<smc[i-1][j-1].B[1]<<"\t"; cpIi<<smc[i-1][j-1].B[2]<<"\t"; }//end j }//end i ci<<endl;si<<endl;vi<<endl;wi<<endl;Ii<<endl; cpCi<<endl;cpVi<<endl;cpIi<<endl; for (int i =1; i<=grid.num_ec_circumferentially; i++){ for(int j=1; j<=grid.num_ec_axially; j++){ cj<<ec[i-1][j-1].c<<"\t"; sj<<ec[i-1][j-1].s<<"\t"; vj<<ec[i-1][j-1].v<<"\t"; Ij<<ec[i-1][j-1].I<<"\t"; cpCj<<ec[i-1][j-1].B[0]<<"\t"; cpVj<<ec[i-1][j-1].B[1]<<"\t"; cpIj<<ec[i-1][j-1].B[2]<<"\t"; }//end j }//end i cj<<endl;sj<<endl;vj<<endl;Ij<<endl; cpCj<<endl;cpVj<<endl;cpIj<<endl; }//end itteration }//end of for loop on TEND cout<<"["<<grid.rank<<"]"<<"End of run at time "<<tend<<endl; logptr.close(); Time.close(); ci.close();si.close();vi.close();wi.close();Ii.close(); cj.close();sj.close();vj.close();Ij.close(); cpCi.close();cpCj.close();cpVi.close();cpVj.close();cpIi.close();cpIj.close(); delete[] y; MPI_Finalize(); }// end main()