String * collecttext(void) { String *s = newstring(); int begline, i, c, delim; if(skipbl()=='\n'){ getch(); i = 0; do{ begline = i; while((c = getch())>0 && c!='\n') i++, Straddc(s, c); i++, Straddc(s, '\n'); if(c < 0) goto Return; }while(s->s[begline]!='.' || s->s[begline+1]!='\n'); Strdelete(s, s->n-2, s->n); }else{ okdelim(delim = getch()); getrhs(s, delim, 'a'); if(nextc()==delim) getch(); atnl(); } Return: Straddc(s, 0); /* JUST FOR CMDPRINT() */ return s; }
String * collecttext(void) { String *s; int begline, i, c, delim; s = newstring(0); if(cmdskipbl()=='\n'){ getch(); i = 0; do{ begline = i; while((c = getch())>0 && c!='\n') i++, Straddc(s, c); i++, Straddc(s, '\n'); if(c < 0) goto Return; }while(s->r[begline]!='.' || s->r[begline+1]!='\n'); s->r[s->n-2] = '\0'; s->n -= 2; }else{ okdelim(delim = getch()); getrhs(s, delim, 'a'); if(nextc()==delim) getch(); atnl(); } Return: return s; }
// 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); }
Cmd * parsecmd(int nest) { int i, c; Cmdtab *ct; Cmd *cp, *ncp; Cmd cmd; cmd.next = cmd.ccmd = 0; cmd.re = 0; cmd.flag = cmd.num = 0; cmd.addr = compoundaddr(); if(skipbl() == -1) return 0; if((c=getch())==-1) return 0; cmd.cmdc = c; if(cmd.cmdc=='c' && nextc()=='d'){ /* sleazy two-character case */ getch(); /* the 'd' */ cmd.cmdc='c'|0x100; } i = lookup(cmd.cmdc); if(i >= 0){ if(cmd.cmdc == '\n') goto Return; /* let nl_cmd work it all out */ ct = &cmdtab[i]; if(ct->defaddr==aNo && cmd.addr) error(Enoaddr); if(ct->count) cmd.num = getnum(ct->count); if(ct->regexp){ /* x without pattern -> .*\n, indicated by cmd.re==0 */ /* X without pattern is all files */ if((ct->cmdc!='x' && ct->cmdc!='X') || ((c = nextc())!=' ' && c!='\t' && c!='\n')){ skipbl(); if((c = getch())=='\n' || c<0) error(Enopattern); okdelim(c); cmd.re = getregexp(c); if(ct->cmdc == 's'){ cmd.ctext = newstring(); getrhs(cmd.ctext, c, 's'); if(nextc() == c){ getch(); if(nextc() == 'g') cmd.flag = getch(); } } } } if(ct->addr && (cmd.caddr=simpleaddr())==0) error(Eaddress); if(ct->defcmd){ if(skipbl() == '\n'){ getch(); cmd.ccmd = newcmd(); cmd.ccmd->cmdc = ct->defcmd; }else if((cmd.ccmd = parsecmd(nest))==0) panic("defcmd"); }else if(ct->text) cmd.ctext = collecttext(); else if(ct->token) cmd.ctext = collecttoken(ct->token); else atnl(); }else switch(cmd.cmdc){ case '{': cp = 0; do{ if(skipbl()=='\n') getch(); ncp = parsecmd(nest+1); if(cp) cp->next = ncp; else cmd.ccmd = ncp; }while(cp = ncp); break; case '}': atnl(); if(nest==0) error(Enolbrace); return 0; default: error_c(Eunk, cmd.cmdc); } Return: cp = newcmd(); *cp = cmd; return cp; }
// 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); } }
//Source term depending on cell void sources(struct CSRMat *Mat, struct RHS *Rhs) { int icell, ivar, idir; double *CelldblPnt, *phi, *dep, Src[nvar]; double tau[ndir][ndir], div, CmuOm; int i, j, k; double beta, Sij[ndir][ndir], Omij[ndir][ndir], xiw, fb; double SAa, SAb, SAc; for (icell=0;icell<ncell;icell++) { phi = setvar(icell); dep = setdep(icell); CelldblPnt = setdblcell(icell); memset(Src, 0.0, nvar * sizeof(double)); // Momentum Sources ---------------------------------------------------- if (eos != ICOUPLED) { for (idir=0;idir<ndir;idir++) Src[Uvar+idir] = - dep[PGrd+idir]; } // Turbulence production -------------- if (Kvar!=-1) { for (idir=0;idir<ndir;idir++) Src[Uvar+idir]-= 2.0 / 3.0 * dep[Rdep] * dep[KGrd+idir]; //Src[Uvar+idir]-= 2.0 / 3.0 * dep[MTdep] * divergence( dep); stress( phi, dep, tau); Src[Kvar] = prodk( dep, tau); } // turbulence Sources -------------------------------------------------- switch (turb) { // Spalart Allmaras ---------------- case SA: // NASA ################################# /*SAa = cb1 * ( 1.0 - ft2( phi, dep)) * Shat( phi, dep) * phi[MTvar]; SAb = ( cw1 * fw( phi, dep) - cb1 / (kappa * kappa) * ft2( phi, dep)) * \ ( phi[MTvar] * phi[MTvar]) / ( dep[Ddep] * dep[Ddep]); SAc = cb2 / sigma * scalarp( ndir, &dep[MTGrd], &dep[MTGrd]);*/ // Deck ################################# SAa = cb1 * Shat( phi, dep) * phi[MTvar]; SAb = cw1 * fw( phi, dep) * \ ( phi[MTvar] * phi[MTvar]) / ( dep[Ddep] * dep[Ddep]); SAc = 0.0; //cb2 / sigma * scalarp( ndir, &dep[MTGrd], &dep[MTGrd]); Src[MTvar] = dep[Rdep] * (SAa - SAb + SAc); break; // Kw Wilcox 2006 ------------------ case KW06: strain( dep, Sij); rotation( dep, Omij); div = divergence( dep); for (i=0;i<ndir;i++) Sij[i][i] -= 0.5 * div; xiw = 0.0; for (i=0;i<ndir;i++) { for (j=0;j<ndir;j++) { for (k=0;k<ndir;k++) xiw += Omij[i][j] * Omij[j][k] * Sij[k][i]; }} CmuOm = Cmu * phi[OMvar]; xiw = fabs( xiw / (CmuOm * CmuOm * CmuOm)); fb = ( 1.0 + 85.0*xiw) / ( 1.0 + 100.0*xiw); beta = beta0 * fb; Src[Kvar] -= Cmu * dep[Rdep] * phi[Kvar] * phi[OMvar]; Src[OMvar] = alpha * phi[OMvar] / phi[Kvar] * prodk( dep, tau); Src[OMvar]-= beta * dep[Rdep] * phi[OMvar] * phi[OMvar]; if ( scalarp( ndir, &dep[KGrd], &dep[OMGrd]) > 0.0) Src[OMvar]+= 0.125 * dep[Rdep] / phi[OMvar] * \ scalarp( ndir, &dep[KGrd], &dep[OMGrd]); break; // Menter KwSST -------------------- case KWSST: strain( dep, Sij); rotation( dep, Omij); alpha = blend( F1(phi,dep), gamma1, gamma2); beta = blend( F1(phi,dep), beta1, beta2); Src[Kvar] -= Cmu * dep[Rdep] * phi[Kvar] * phi[OMvar]; Src[OMvar] = alpha * dep[Rdep] / dep[MTdep] * prodk( dep, tau); Src[OMvar]-= beta * dep[Rdep] * phi[OMvar] * phi[OMvar]; Src[OMvar]+= 2.0 * (1.0-F1(phi,dep)) * sigw2 * dep[Rdep] / phi[OMvar] * \ scalarp( ndir, &dep[KGrd], &dep[OMGrd]); break; } getrhs( Rhs, icell, CelldblPnt[CellVol], Src); } }
// 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);*/ } }