void SpParMat<IT,NT,DER>::PrintInfo() const { IT mm = getnrow(); IT nn = getncol(); IT nznz = getnnz(); if (commGrid->myrank == 0) cout << "As a whole: " << mm << " rows and "<< nn <<" columns and "<< nznz << " nonzeros" << endl; #ifdef DEBUG if ((commGrid->grrows * commGrid->grcols) == 1) spSeq->PrintInfo(); #endif }
// Continuity equation is used to find out the pressure corrections void simple_peqn( void) { double c_a, c_c; int iface, acell, bcell, *FaceintPnt, idir, nniterp; double *FacedblPnt, *AA, *CellAdblPnt, *CellBdblPnt, A_a, A_b; double F_i[1], Fp_i[1][1], u_f[ndir], u_a[ndir], u_b[ndir]; double *phi_a, *dep_a, *phi_b, *dep_b, rho_i, *dd_a, *dd_b, p_sum[ndir]; double F_pa, F_pb, dx[ndir], dxi, e_xi[ndir], alfa, u_fp, ttollp, ttmmpp; struct CSRMat Mat_p; struct RHS Rhs_p; p_sol = (double *) calloc( ntot, sizeof(double)); c_a = 1.0; c_c = 1.0; matini(ncell, 1, &Mat_p); matalc(&Mat_p, dnnz); rhsini(ncell, 1, &Rhs_p); // Rileggersi: Versteeg pagg. 338 e seguenti ... // geometrical issues on Collocated grids // // Face interpolation has three different contributions here reported // u_f = f(U_a,U_b) + f(P_a, P_b) + f(grad(P_a), grad(P_b)) // 1 2 3 // The first therm is straight forward to compute and is implicit // The second and the third are explicit at a given time step for (iface=0;iface<nface;iface++) { FaceintPnt = setintface( iface); FacedblPnt = setdblface( iface); //A-B cells acell = FaceintPnt[FaceAcl]; bcell = FaceintPnt[FaceBcl]; alfa = FacedblPnt[FaceAlfa]; AA = &FacedblPnt[FaceSrf]; //Variables of the two cells phi_a = setvar( acell); dep_a = setdep( acell); phi_b = setvar( bcell); dep_b = setdep( bcell); //Cell dbl Pnt CellAdblPnt = setdblcell( acell); CellBdblPnt = setdblcell( bcell); rho_i = facevar( alfa, dep_a[Rdep], dep_b[Rdep]); // These are the coefficients averaged in all the directions // For ghosts cells the correspondent coefficient // of the fluid cell is considered if (acell<ncell) { dd_a = setsol( acell, ndir, dd); A_a = fabs( scalarp( ndir, dd_a, AA) / sqrt( scalarp( ndir, AA, AA))); } if (bcell<ncell) { dd_b = setsol( bcell, ndir, dd); A_b = fabs( scalarp( ndir, dd_b, AA) / sqrt( scalarp( ndir, AA, AA))); } if (acell>=ncell) A_a = A_b; if (bcell>=ncell) A_b = A_a; // u* contribution to continuity equation ------------------- // 1st term // we use u* to obtain the pressure correction for (idir=0;idir<ndir;idir++) { u_a[idir] = phi_a[Uvar+idir] + scalarp( ndir, &dep_a[UGrd+ndir*idir], &FacedblPnt[FaceDxA]); u_b[idir] = phi_b[Uvar+idir] + scalarp( ndir, &dep_b[UGrd+ndir*idir], &FacedblPnt[FaceDxB]); } for (idir=0;idir<ndir;idir++) u_f[idir] = facevar( alfa, u_a[idir], u_b[idir]); F_i[0] = rho_i * scalarp( ndir, AA, u_f); // 2nd and 3rd therms: face normal velocities from RhieChow F_pa = CellAdblPnt[CellVol] / A_a; F_pb = CellBdblPnt[CellVol] / A_b; pntsdist( &CellBdblPnt[CellXc], &CellAdblPnt[CellXc], dx); dxi = sqrt( scalarp( ndir, dx, dx) ); for (idir=0;idir<ndir;idir++) e_xi[idir] = dx[idir] / dxi; double dxn = scalarp( ndir, dx, AA) / sqrt( scalarp( ndir, AA, AA)); double p_a = phi_a[Pvar] + scalarp( ndir, &dep_a[PGrd], &FacedblPnt[FaceDxA]); double p_b = phi_b[Pvar] + scalarp( ndir, &dep_b[PGrd], &FacedblPnt[FaceDxB]); /////////////////////////////////////////// VERSTEEG u_fp = facevar( alfa, F_pa, F_pb) * (p_b - p_a) / dxn; for (idir=0;idir<ndir;idir++) p_sum[idir] = facevar( alfa, F_pa * dep_a[PGrd+idir], F_pb * dep_b[PGrd+idir]); //p_sum[idir] = facevar( alfa, F_pa, F_pb) * facevar( 0.5, dep_a[PGrd+idir], dep_b[PGrd+idir]); u_fp -= scalarp( ndir, p_sum, e_xi); /////////////////////////////////////////// DARWISH /*for (idir=0;idir<ndir;idir++) p_sum[idir] = -1.0 * facevar( 0.5, dep_a[PGrd+idir], dep_b[PGrd+idir]); for (idir=0;idir<ndir;idir++) p_sum[idir]+= ( p_b - p_a) / dxn * e_xi[idir]; u_fp = facevar( alfa, F_pa, F_pb) * scalarp( ndir, p_sum, AA) / sqrt( scalarp( ndir, AA, AA));*/ /////////////////////////////////////////// // There is a sign inconsistency between: // MATHUR AND MURTHY's "Pressure based method for unstructured mesh" // VERSTEEG's "An Introduction to C.F.D." F_i[0] -= rho_i * u_fp * sqrt( scalarp( ndir, AA, AA)); // A CELL fluxes ---------- getrhs( &Rhs_p, acell, c_a, F_i); // B CELL fluxes ---------- getrhs( &Rhs_p, bcell, -c_a, F_i); // p' contribution to continuity equation ------------------- // We need to know the sum of all the convective/diffusion // terms for the velocity double Cnst = rho_i * facevar( alfa, F_pa, F_pb); Fp_i[0][0] = Cnst * scalarp( ndir, AA, AA) / scalarp( ndir, dx, AA); // A CELL fluxes ---------- //LE BC qui sono DIFFERENTI!!! getnnz( &Mat_p, acell, acell, -c_c, Fp_i); if (bcell<ncell) getnnz( &Mat_p, acell, bcell, c_c, Fp_i); else getnnz( &Mat_p, acell, acell, c_c * ghst2fld( gbl2ghst( bcell), Pvar), Fp_i); // B CELL fluxes ---------- if (acell<ncell) getnnz( &Mat_p, bcell, acell, c_c, Fp_i); else getnnz( &Mat_p, bcell, bcell, c_c * ghst2fld( gbl2ghst( acell), Pvar), Fp_i); getnnz( &Mat_p, bcell, bcell, -c_c, Fp_i); } #if _DBG == 10 int icell; double *dep, *dd_i; for (icell=0;icell<ncell;icell++) { dep = setdep( icell); dep[DivSdep] = extrhs( icell, 0, &Rhs_p); dd_i = setsol( icell, ndir, dd); for (idir=0;idir<ndir;idir++) dep[DDdep+idir] = dd_i[idir]; } #endif // Solution ------------- nniterp = niterp; ttollp = tollp; // BiCGS seems to be the best method among the ones implemented ... // Cases in future may confirm this assumption ... // SORmethd( &Mat_p, &Rhs_p, p_sol, 1.0, &ttollp, &nniterp); // pcjacb( &Mat_p); // ConjGrad( &Mat_p, &Rhs_p, p_sol, &ttollp, &nniterp); BiCGStab( &Mat_p, &Rhs_p, p_sol, &ttollp, &nniterp); fprintf(logfile, " Press iter = %4d, Res = %f\n", nniterp, ttollp); matdel( &Mat_p); rhsdel( &Rhs_p); }
int main(int argc, char *argv[]) { int ncpus, mypid, nrem, ierr; MPI_Status mpistatus; MPI_Comm comm = MPI_COMM_WORLD; // Variables needed for the Cartesian topology. int ROW = 0, COL = 1; int dims[2], periods[2], keep_dims[2]; int my2dpid, mycoords[2], srcoords[2], otherpid; MPI_Comm comm_2d, comm_row, comm_col; // Initialize MPI. MPI_Init(&argc, &argv); MPI_Comm_size(comm, &ncpus); MPI_Comm_rank(comm, &mypid); if ( argc < 3 ) { printf ("ERROR: %s requires Cartesian dimensions input\n", argv[0]); return -1; } // Set up a Cartesian virtual topology and get the rank and coordinates of the processes in the topology. dims[ROW] = atoi(argv[1]); // Row dimension of the topology dims[COL] = atoi(argv[2]); // Column dimension of the topology if (dims[ROW]*dims[COL] != ncpus){ printf("ERROR: Row dim and col dim not equal to ncpus\n"); return -1; } periods[ROW] = periods[COL] = 1; // Set the periods for wrap-around MPI_Cart_create(comm, 2, dims, periods, 1, &comm_2d); MPI_Comm_rank(comm_2d, &my2dpid); //Get my pid in the new 2D topology MPI_Cart_coords(comm_2d, my2dpid, 2, mycoords); // Get my coordinates /* Create the row-based sub-topology */ keep_dims[ROW] = 0; keep_dims[COL] = 1; MPI_Cart_sub(comm_2d, keep_dims, &comm_row); /* Create the column-based sub-topology */ keep_dims[ROW] = 1; keep_dims[COL] = 0; MPI_Cart_sub(comm_2d, keep_dims, &comm_col); // STEP 1: Have processor (0,0) read in the entire set of 2D images, divide up the images, and send corresponding images to processors in processor group: g_c_0 Do the same for the angles. if (mycoords[ROW] == 0 && mycoords[COL] == 0){ //I'm processor (0,0) FILE *fp, *fpa; char imagefname[80]="tf2d84.raw", anglesfname[80]="angles.dat"; fp = fopen(imagefname,"r"); fread(&nangs, sizeof(int), 1, fp); fread(&nx, sizeof(int), 1, fp); fread(&ny, sizeof(int), 1, fp); images = new float[nx*ny*nangs]; fread(images, sizeof(float), nx*ny*nangs, fp); fclose(fp); fpa = fopen(anglesfname,"r"); angles = new float[3*nangs]; for (int i = 0; i< 3*nangs; i++) fscanf(fpa, "%f",&angles[i]); fclose(fpa); printf("There are %d 2D images of size %d x %d\n", nangs, nx, ny); } // Broadcast variables nangs, nx, ny to all processors srcoords[ROW] = srcoords[COL] = 0; MPI_Cart_rank(comm_2d, srcoords, &otherpid); MPI_Bcast (&nangs, 1, MPI_INT, otherpid, comm_2d); MPI_Bcast (&nx, 1, MPI_INT, otherpid, comm_2d); MPI_Bcast (&ny, 1, MPI_INT, otherpid, comm_2d); // Send images and angles from Processor (0,0) to processors in group g_c_0 int *psize = new int[dims[ROW]]; int *nbase = new int[dims[ROW]]; nangsloc = setpart_gc1(comm_2d, nangs, psize, nbase); imagesloc = new float[psize[mycoords[ROW]]*nx*ny]; reprojloc = new float[psize[mycoords[ROW]]*nx*ny]; anglesloc = new float[psize[mycoords[ROW]]*3]; // printf("My coords are (%d,%d) and nangsloc = %d\n", mycoords[ROW], mycoords[COL], nangsloc); if (mycoords[COL] == 0 && mycoords[ROW] == 0) { //I'm Proc. (0,0) for(int ip = 0; ip < dims[ROW]; ++ip){ int begidx = nbase[ip]*nx*ny; if (ip !=0){ // Proc (0,0) sends images and angle data to other processors srcoords[COL] = 0; srcoords[ROW] = ip; MPI_Cart_rank(comm_2d, srcoords, &otherpid); MPI_Send(&images[begidx],psize[ip]*nx*ny, MPI_FLOAT, otherpid, otherpid, comm_2d); MPI_Send(&angles[nbase[ip]*3],psize[ip]*3, MPI_FLOAT, otherpid, otherpid, comm_2d); } else{ // ip = 0: Proc (0,0) needs to copy images and angles into its imagesloc and anglesloc for (int i = 0; i < psize[ip]*nx*ny; i++){ imagesloc[i] = images[begidx+i]; } for (int i = 0; i < psize[ip]*3; i++){ anglesloc[i] = angles[nbase[ip]*3 + i]; } //printf("Finished copying to Proc (0,0) local"); } } //End for loop } //End if if (mycoords[COL] == 0 && mycoords[ROW] != 0) { //I'm in g_c_0 and I'm not Processor (0,0) so I should receive data. MPI_Recv(imagesloc, psize[mycoords[ROW]]*nx*ny, MPI_FLOAT, 0, mypid, comm_2d, &mpistatus); MPI_Recv(anglesloc, psize[mycoords[ROW]]*3, MPI_FLOAT, 0, mypid, comm_2d, &mpistatus); } // Now have all the processors in group g_c_0 broadcast the images and angles along the row communicator srcoords[ROW] = 0; MPI_Cart_rank(comm_row, srcoords, &otherpid); MPI_Bcast(imagesloc, nangsloc*nx*ny, MPI_FLOAT, otherpid , comm_row); MPI_Bcast(anglesloc, nangsloc*3, MPI_FLOAT, otherpid , comm_row); // Now distribute the volume (in spherical format) among columns of processors and use nnz to determine the splitting. Note: ptrs and coord are on all processors int radius; int volsize[3], origin[3]; volsize[0] = nx; volsize[1] = nx; volsize[2] = nx; origin[0] = nx/2+1; origin[1] = nx/2+1; origin[2] = nx/2+1; radius = nx/2-1; ierr = getnnz( volsize, radius, origin, &nrays, &nnz); int * ptrs = new int[nrays+1]; int * cord = new int[3*nrays]; ierr = getcb2sph(volsize, radius, origin, nnz, ptrs, cord); int *nnzpart = new int[dims[COL]]; int *nnzbase = new int[dims[COL]+1]; nnzloc = setpart_gr1(comm_2d, nnz, nnzpart, nnzbase); int *ptrstart = new int[dims[COL]+1]; nraysloc = sphpart(comm_2d, nrays, ptrs, nnzbase, ptrstart); myptrstart = ptrstart[mycoords[COL]]; int nnzall[dims[COL]]; for (int i = 0; i<dims[COL]; i++) nnzall[i] = ptrs[ptrstart[i+1]] - ptrs[ptrstart[i]]; nnzloc = nnzall[mycoords[COL]]; // Print some stuff. printf("My coords are (%d,%d) and nangsloc = %d, nraysloc = %d, myptrstart = %d, nnzloc = %d\n", mycoords[ROW], mycoords[COL], nangsloc, nraysloc, myptrstart, nnzloc); float *bvol_loc = new float[nnzloc]; float *vol_sphloc = new float[nnzloc]; for (int i=0; i< nnzloc; i++) bvol_loc[i] = 0.0; // STEP 2: Have everyone perform the backprojection operation for their assigned images and portions of the volume. Then perform an Allreduce along the columns. float phi, theta, psi; float dm[8]; for (int i=0; i<nangsloc; i++){ phi = anglesloc[3*i+0]; theta = anglesloc[3*i+1]; psi = anglesloc[3*i+2]; dm[6] = 0; dm[7] = 0; make_proj_mat(phi, theta, psi, dm); ierr = bckpj3_Cart(volsize, nraysloc, nnzloc, dm, origin, radius, ptrs, cord, myptrstart, &imagesloc[nx*ny*i], bvol_loc); } // Now an all reduce along the columns MPI_Allreduce (bvol_loc, vol_sphloc, nnzloc, MPI_FLOAT, MPI_SUM, comm_col); // For testing purposes, we bring all the portions of the volume back together onto Proc (0,0). Note: we only need to deal with the first row of processors. if (mycoords[COL] != 0 && mycoords[ROW] == 0) { //Send data to Processor (0,0) srcoords[COL] = srcoords[ROW] = 0; MPI_Cart_rank(comm_2d, srcoords, &otherpid); MPI_Send(vol_sphloc, nnzloc, MPI_FLOAT, otherpid, otherpid, comm_2d); } float *onevol_sph = new float[nnz]; if (mycoords[COL] == 0 && mycoords[ROW] ==0){ //Copy data and recieve data float *vol_sph = new float[nnz]; for (int i=0; i<nnzloc; i++) vol_sph[i] = vol_sphloc[i]; for (int i=1; i<dims[COL]; i++){ srcoords[ROW] = 0; srcoords[COL] = i; MPI_Cart_rank(comm_2d, srcoords, &otherpid); MPI_Recv(&vol_sph[ptrs[ptrstart[i]]-1], nnzall[i], MPI_FLOAT, otherpid, mypid, comm_2d, &mpistatus); } //printf("Finished combining all volume parts\n"); //Now compute the back projection serially on one processor (0,0) for (int i=0; i< nnz; i++) onevol_sph[i] = 0.0; for (int i=0; i<nangs; i++){ phi = angles[3*i+0]; theta = angles[3*i+1]; psi = angles[3*i+2]; dm[6] = 0; dm[7] = 0; make_proj_mat(phi, theta, psi, dm); ierr = bckpj3(volsize, nrays, nnz, dm, origin, radius, ptrs, cord, &images[nx*ny*i], onevol_sph); } float err=0; for (int i=0; i< nnz; i++){ err = err+(onevol_sph[i]-vol_sph[i])*(onevol_sph[i]-vol_sph[i]); } err = sqrt(err); printf("Cumulative error for backprojection is %f\n", err); delete [] vol_sph; } // STEP 3: Now perform a forward projection operation for the assigned images and portions of the volume. Then perform an all_reduce along the rows. float * newimagesloc = new float[nangsloc*nx*ny]; for (int i=0; i<nangsloc*nx*ny; i++) newimagesloc[i] = 0.0; for (int i=0; i<nangsloc; i++){ phi = anglesloc[3*i+0]; theta = anglesloc[3*i+1]; psi = anglesloc[3*i+2]; dm[6] = 0; dm[7] = 0; make_proj_mat(phi, theta, psi, dm); ierr = fwdpj3_Cart(volsize, nraysloc, nnzloc, dm, origin, radius, ptrs, cord, myptrstart, vol_sphloc, &newimagesloc[nx*ny*i]); } // Now an all reduce along the rows MPI_Allreduce (newimagesloc, reprojloc, nangsloc*nx*ny, MPI_FLOAT, MPI_SUM, comm_row); delete [] newimagesloc; // For testing purposes, we bring all the 2D images together onto Proc (0,0). Note: we only need to deal with the first column of processors. if (mycoords[ROW] != 0 && mycoords[COL] == 0) { //Send data to Processor (0,0) srcoords[COL] = srcoords[ROW] = 0; MPI_Cart_rank(comm_2d, srcoords, &otherpid); MPI_Send(reprojloc, nangsloc*nx*ny, MPI_FLOAT, otherpid, otherpid, comm_2d); } if (mycoords[COL] == 0 && mycoords[ROW] ==0){ //Copy data and recieve data float *reproj = new float[nangs*nx*ny]; for (int i=0; i<nangsloc*nx*ny; i++) reproj[i] = reprojloc[i]; for (int i=1; i<dims[ROW]; i++){ srcoords[COL] = 0; srcoords[ROW] = i; MPI_Cart_rank(comm_2d, srcoords, &otherpid); MPI_Recv(&reproj[nbase[i]*nx*ny], psize[i]*nx*ny, MPI_FLOAT, otherpid, mypid, comm_2d, &mpistatus); } delete [] reprojloc; // Now compute the forward projection serially on one processor (0,0) float *allimages = new float[nangs*nx*ny]; for (int i=0; i< nangs*nx*ny; i++) allimages[i] = 0.0; for (int i=0; i<nangs; i++){ phi = angles[3*i+0]; theta = angles[3*i+1]; psi = angles[3*i+2]; dm[6] = 0; dm[7] = 0; make_proj_mat(phi, theta, psi, dm); ierr = fwdpj3(volsize, nrays, nnz, dm, origin, radius, ptrs, cord, onevol_sph, &allimages[nx*ny*i]); } // Now compute the overall error. int idx; float err=0, max =0; for (int i=0; i< nangs*nx*ny; i++){ //if (allimages[i]!=reproj[i] && i < 256) // printf("i= %d\n",i); err = err+(allimages[i]-reproj[i])*(allimages[i]-reproj[i]); if (fabs(allimages[i]-reproj[i]) > max){ max = fabs(allimages[i]-reproj[i]); idx = i; } } err = sqrt(err); printf("Cumulative error for forward projection is %f with max error of %f occuring at %d\n", err, max, idx); printf("Max error: compare %f and %f\n",allimages[idx], reproj[idx]); delete [] reproj; delete [] allimages; delete [] angles; delete [] images; } delete [] onevol_sph; delete [] vol_sphloc; delete [] bvol_loc; delete [] ptrs; delete [] cord; delete [] nnzpart; delete [] nnzbase; delete [] ptrstart; delete [] anglesloc; delete [] imagesloc; delete [] nbase; delete [] psize; MPI_Comm_free(&comm_2d); MPI_Comm_free(&comm_row); MPI_Comm_free(&comm_col); MPI_Finalize(); }
// Convective fluxes void convflx(struct CSRMat *Mat, struct RHS *Rhs ) { int iface, acell, bcell, *FaceintPnt, idir, ivar; double *AA, u_i[ndir], rho_a, rho_b, rho_i, *FacedblPnt, *varPnt, *dep_a; double phi_a[nvar], phi_b[nvar], F_a[nvar][nvar], F_b[nvar][nvar], *dep_b; double Flux_a[nvar], Flux_b[nvar], Flux[nvar], alfa, mssflw; for (iface=0;iface<nface;iface++) { //Setting Pointers FaceintPnt = setintface( iface); FacedblPnt = setdblface( iface); //A-B cells acell = FaceintPnt[FaceAcl]; bcell = FaceintPnt[FaceBcl]; //Initialization of F_a and F_b memset(F_a, 0.0, nvar*nvar* sizeof(double)); memset(F_b, 0.0, nvar*nvar* sizeof(double)); /*Variables to convect*/ varPnt = setvar( acell); dep_a = setdep( acell); memcpy( phi_a, varPnt, nvar * sizeof(double)); rho_a = dep_a[Rdep]; varPnt = setvar( bcell); dep_b = setdep( bcell); memcpy( phi_b, varPnt, nvar * sizeof(double)); rho_b = dep_b[Rdep]; //Convective fluxes calculation: // Coeff * Phi_a + Coeff * Phi_b // Coeff = max(F_i, ..., 0) depends on the convective scheme //Convective fluxes: Rho * u * A * Phi --------------------------- alfa = FacedblPnt[FaceAlfa]; rho_i = facevar( alfa, rho_a, rho_b); AA = &FacedblPnt[FaceSrf]; for (idir=0;idir<ndir;idir++) u_i[idir] = facevar( alfa, \ phi_a[Uvar+idir] + scalarp( ndir, &dep_a[UGrd+ndir*idir], &FacedblPnt[FaceDxA]), \ phi_b[Uvar+idir] + scalarp( ndir, &dep_b[UGrd+ndir*idir], &FacedblPnt[FaceDxB])); mssflw = rho_i * scalarp( ndir, u_i, AA); //conv returns the convective scheme convscheme( iconv, nvar, 1.0, mssflw, F_a); convscheme( iconv, nvar,-1.0,-1.0 * mssflw, F_b); //////------------------------ PRESS-VEL COUPLING presflx(phi_a, F_a); presflx(phi_b, F_b); /////-------------------------------------------- // Flux calculation matvecdstd(nvar, F_a, phi_a, Flux_a); matvecdstd(nvar, F_b, phi_b, Flux_b); summvec(nvar, Flux_a, Flux_b, Flux); // Function to add 2 RHS (it is the explicit part!!) getrhs( Rhs, acell, -1.0 * (1.0 - theta), Flux); getrhs( Rhs, bcell, 1.0 * (1.0 - theta), Flux); // A CELL fluxes ------------------------------------------------ getnnz( Mat, acell, acell, 1.0 * theta, F_a); if (bcell<ncell) getnnz( Mat, acell, bcell, 1.0 * theta, F_b); else getrhs( Rhs, acell, -1.0 * theta, Flux_b); // B CELL fluxes ------------------------------------------------ if (acell<ncell) getnnz( Mat, bcell, acell, -1.0 * theta, F_a); else getrhs( Rhs, bcell, 1.0 * theta, Flux_a); getnnz( Mat, bcell, bcell, -1.0 * theta, F_b); // Non-orthogonality -------------------------------------------- // It is like an explicit flux where (Var * Dx) replaces phi for (ivar=0;ivar<nvar;ivar++) { phi_a[ivar] = scalarp( ndir, &dep_a[PGrd+(ivar*ndir)], &FacedblPnt[FaceDxA]); phi_b[ivar] = scalarp( ndir, &dep_b[PGrd+(ivar*ndir)], &FacedblPnt[FaceDxB]); } presflx( phi_a, F_a); presflx( phi_b, F_b); matvecdstd(nvar, F_a, phi_a, Flux_a); matvecdstd(nvar, F_b, phi_b, Flux_b); summvec(nvar, Flux_a, Flux_b, Flux); getrhs( Rhs, acell, -1.0, Flux); getrhs( Rhs, bcell, 1.0, Flux); } }
// Viscous fluxes void viscflx(struct CSRMat *Mat, struct RHS *Rhs ) { int iface, ivar, acell, bcell, *FaceintPnt, idir; double *AA, *FacedblPnt, *varPnt, *dep_a, *dep_b; double phi_a[nvar], phi_b[nvar], F_i[nvar][nvar]; double Flux_a[nvar], Flux_b[nvar], Flux[nvar], alfa; double *CellAdblPnt, *CellBdblPnt, dx[ndir]; double mu_i[nvar]; if (MUdep == -1) return; for (iface=0;iface<nface;iface++) { //Setting Pointers FaceintPnt = setintface( iface); FacedblPnt = setdblface( iface); //A-B cells acell = FaceintPnt[FaceAcl]; bcell = FaceintPnt[FaceBcl]; //Cell pointers CellAdblPnt = setdblcell( acell); CellBdblPnt = setdblcell( bcell); //Initialization of F_i and mu_i memset(F_i , 0.0, nvar * nvar * sizeof(double)); /*Variables*/ varPnt = setvar( acell); dep_a = setdep( acell); memcpy( phi_a, varPnt, nvar * sizeof(double)); varPnt = setvar( bcell); dep_b = setdep( bcell); memcpy( phi_b, varPnt, nvar * sizeof(double)); alfa = FacedblPnt[FaceAlfa]; // To better understand the ViscousFlux check the formula 11.22 // of the Versteeg book (page 332) //Cell centres distance pntsdist( &CellBdblPnt[CellXc], &CellAdblPnt[CellXc], dx); AA = &FacedblPnt[FaceSrf]; // Flux Matrix ----------- setmuvar( mu_i, alfa, dep_a, dep_b, phi_a, phi_b); viscscheme( nvar, mu_i, AA, dx, F_i); // Note: in continuity equation there is no diffusion phi_a[Pvar] = 0.0; phi_b[Pvar] = 0.0; for (ivar=0;ivar<nvar;ivar++) phi_a[ivar] *= -1.0; // Flux calculation matvecdstd(nvar, F_i, phi_a, Flux_a); matvecdstd(nvar, F_i, phi_b, Flux_b); summvec(nvar, Flux_a, Flux_b, Flux); // Function to add 2 RHS (it is the explicit part!!) getrhs( Rhs, acell, -1.0 * (1.0 - theta), Flux); getrhs( Rhs, bcell, 1.0 * (1.0 - theta), Flux); // A CELL fluxes ------------------------------------------------ getnnz( Mat, acell, acell, -1.0 * theta, F_i); if (bcell<ncell) getnnz( Mat, acell, bcell, 1.0 * theta, F_i); else getrhs( Rhs, acell, -1.0 * theta, Flux_b); // B CELL fluxes ------------------------------------------------ if (acell<ncell) getnnz( Mat, bcell, acell, 1.0 * theta, F_i); else getrhs( Rhs, bcell, 1.0 * theta, Flux_a); // NB: this should be negative, but Flux_a has already been // multiplied by a negative value!! getnnz( Mat, bcell, bcell, -1.0 * theta, F_i); // Non-orthogonality -------------------------------------------- // STANDARD MODE ################################################ for (ivar=0;ivar<nvar;ivar++) { phi_a[ivar] = scalarp( ndir, &dep_a[PGrd+(ivar*ndir)], &FacedblPnt[FaceDxA]); phi_b[ivar] = scalarp( ndir, &dep_b[PGrd+(ivar*ndir)], &FacedblPnt[FaceDxB]); } for (ivar=0;ivar<nvar;ivar++) phi_a[ivar] *= -1.0; phi_a[Pvar] = 0.0; phi_b[Pvar] = 0.0; matvecdstd(nvar, F_i, phi_a, Flux_a); matvecdstd(nvar, F_i, phi_b, Flux_b); summvec(nvar, Flux_a, Flux_b, Flux); getrhs( Rhs, acell, -1.0, Flux); getrhs( Rhs, bcell, 1.0, Flux); // MATHUR & MURTHY ############################################## /*double grdavg[ndir]; for (ivar=0;ivar<nvar;ivar++) { for (idir=0;idir<ndir;idir++) grdavg[idir] = facevar( alfa, dep_a[PGrd+(ivar*ndir)+idir], dep_b[PGrd+(ivar*ndir)+idir]); Flux[ivar] = scalarp( ndir, grdavg, AA); Flux[ivar]-= scalarp( ndir, grdavg, dx) * scalarp( ndir, AA, AA) / scalarp( ndir, AA, dx); Flux[ivar]*= mu_i[ivar]; } getrhs( Rhs, acell, 1.0, Flux); getrhs( Rhs, bcell, -1.0, Flux);*/ } }