AUSM on OpenFOAM
Dear All,
I tried to implement the AUSM flux splitting method in the OF. I replaced the flux formulation of rhoCentralFoam with those of basic AUSM method(JCP 107, 2339, 1993). Running the code for forward step case, after some time steps (about 20), some problems occur in some of boundary cells near the outlet that results in negative temperature. I've compared the computed fluxes with those of a fully explicit version of rhoCentralFoam and there is a good agreement. could any one help me to find out the source of this problem? Thanks. Here is the source code. #include "fvCFD.H" #include "basicPsiThermo.H" #include "zeroGradientFvPatchFields.H" #include "fixedRhoFvPatchScalarField.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * int main(int argc, char *argv[]) { #include "setRootCase.H" #include "createTime.H" #include "createMesh.H" #include "createFields.H" #include "readThermophysicalProperties.H" #include "readTimeControls.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // #include "readFluxScheme.H" dimensionedScalar v_zero("v_zero",dimVolume/dimTime, 0.0); Info<< "\nStarting time loop\n" << endl; while (runTime.run()) { volScalarField c = sqrt(thermo.Cp()/(thermo.Cv()*psi)); volScalarField rhoa = rho*c; volVectorField rhoaU = rhoU*c; volScalarField rhoah = (rhoE+rho/psi)*c; volVectorField Mach=U/c; surfaceScalarField Mach_L=fvc::interpolate(Mach, pos, "reconstruct(M)") & (mesh.Sf()/mag(mesh.Sf())) ; surfaceScalarField Mach_R=fvc::interpolate(Mach, neg, "reconstruct(M)") & (mesh.Sf()/mag(mesh.Sf())) ; surfaceScalarField Mach_plus_L= ((sign(1.0mag(Mach_L))+mag(sign(1.0mag(Mach_L))))/2) *(0.25*(Mach_L+1.0)*(Mach_L+1.0)) +((sign(1.0+mag(Mach_L))+mag(sign(1.0+mag(Mach_L))))/2) *(0.5*(Mach_L+mag(Mach_L))); surfaceScalarField Mach_minus_R= ((sign(1.0mag(Mach_R))+mag(sign(1.0mag(Mach_R))))/2) *(0.25*(Mach_R1.0)*(Mach_R1.0)) +((sign(1.0+mag(Mach_R))+mag(sign(1.0+mag(Mach_R))))/2) *(0.5*(Mach_Rmag(Mach_R))); surfaceScalarField Mach_1_2=Mach_plus_L+Mach_minus_R; surfaceScalarField p_L=fvc::interpolate(p, pos, "reconstruct(p)"); surfaceScalarField p_R=fvc::interpolate(p, neg, "reconstruct(p)"); surfaceScalarField p_plus_L= ((sign(1.0mag(Mach_L))+mag(sign(1.0mag(Mach_L))))/2) // *(0.25*p_L*(Mach_L+1.0)*(Mach_L+1.0)*(2.0Mach_L)) *0.5*p_L*(Mach_L+1.0) +((sign(1.0+mag(Mach_L))+mag(sign(1.0+mag(Mach_L))))/2) *(0.5*p_L*(100*Mach_L+100*mag(Mach_L))/(100*mag(Mach_L)+VSMALL)); surfaceScalarField p_minus_R= ((sign(1.0mag(Mach_R))+mag(sign(1.0mag(Mach_R))))/2) // *(0.25*p_R*(Mach_R1.0)*(Mach_R1.0)*(2.0+Mach_R)) *0.5*p_R*(Mach_R1.0) +((sign(1.0+mag(Mach_R))+mag(sign(1.0+mag(Mach_R))))/2) *(0.5*p_R*(100*Mach_R+100*mag(Mach_R))/(100*mag(Mach_R)+VSMALL)); surfaceScalarField p_1_2=p_plus_L+p_minus_R; surfaceScalarField Direction=sign(Mach_1_2); surfaceScalarField rhoa_LR=fvc::interpolate(rhoa, Direction, "reconstruct(rho)"); surfaceVectorField rhoaU_LR=fvc::interpolate(rhoaU, Direction, "reconstruct(U)"); surfaceScalarField rhoah_LR=fvc::interpolate(rhoah, Direction, "reconstruct(T)"); surfaceScalarField c_L=fvc::interpolate(c, pos, "reconstruct(T)"); surfaceScalarField c_R=fvc::interpolate(c, neg, "reconstruct(T)"); surfaceScalarField amaxSf("amaxSf",max(max( mag(Mach_L+1.0)*c_L,mag(Mach_R+1.0)*c_R),max(mag(M ach_L1.0)*c_L,mag(Mach_R1.0)*c_R))*mag(mesh.Sf())); #include "compressibleCourantNo.H" #include "readTimeControls.H" #include "setDeltaT.H" runTime++; Info<< "Time = " << runTime.timeName() << nl << endl; surfaceScalarField phi("phi", Mach_1_2*rhoa_LR*mag(mesh.Sf())); surfaceVectorField phiUp = Mach_1_2*rhoaU_LR*mag(mesh.Sf())+p_1_2*mesh.Sf(); surfaceScalarField phiEp = (Mach_1_2*rhoah_LR)*mag(mesh.Sf()); // Info << phiEp; volTensorField tau("tau", mu*dev(fvc::grad(U)()+fvc::grad(U)().T())); //  Solve density solve(fvm::ddt(rho) + fvc::div(phi)); // Info << Mach_1_2; //  Solve momentum volScalarField rhoBydt(rho/runTime.deltaT()); solve(fvm::ddt(rhoU) + fvc::div(phiUp) fvc::div(tau)); U.dimensionedInternalField() = rhoU.dimensionedInternalField() /rho.dimensionedInternalField(); U.correctBoundaryConditions(); rhoU.boundaryField() = rho.boundaryField()*U.boundaryField(); //  Solve energy surfaceScalarField sigmaDotU = ( ( (mesh.Sf() & fvc::interpolate(tau)) ) & (fvc::interpolate(U)) ); volScalarField k("k", thermo.Cp()*mu/Pr); solve ( fvm::ddt(rhoE) + fvc::div(phiEp)  fvc::div(sigmaDotU)  fvc::laplacian(k, T) ); e = rhoE/rho  0.5*magSqr(U); e.correctBoundaryConditions(); thermo.correct(); rhoE.boundaryField() = rho.boundaryField()* ( e.boundaryField() + 0.5*magSqr(U.boundaryField()) ); p.dimensionedInternalField() = rho.dimensionedInternalField() /psi.dimensionedInternalField(); p.correctBoundaryConditions(); rho.boundaryField() = psi.boundaryField()*p.boundaryField(); // Info << p; runTime.write(); Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << " ClockTime = " << runTime.elapsedClockTime() << " s" << nl << endl; } Info<< "End\n" << endl; return 0; } 
Note that the interpolate operator is exactly not the same as the gradient reconstruction that is popularly used in density based codes. It is some sort of linear interpolation using neighboring cell values on to the face.
So I would not recommend using rhoCentralFoam for this purpose ... Maybe I am wrong do correct me ... And its not straight forward to implement Riemann solvers in rhoCentralFoam. Have a look at AeroFoam it looks like a better solver for such applications. 
Thanks.
I applied the AUSM+up scheme and the problem did not repeat. In fact I was using the upwind scheme to interpolate the cell properties to the faces. So I think that the interpolation scheme was not the source of problem. 
Although I am not using a Riemann solver, you may find the comments by luca_g intersting:
http://www.cfdonline.com/Forums/ope...amdetail.html 
Quote:
F. 
2 Attachment(s)
Hi,
I fact, Results are not so good. But It can capture the main features of the flow ( forward facing step test in M=3 ) Here are some results for t=4.0. 
Thanks for your reply. Your results look qualitatively good. Did you compare them with ones obtained with KurganovTadmor scheme and with the results by Woodward&Colella? What about performances, is your code faster than rhoCentralFoam?

Using "upwind scheme to interpolate " means you are simply using the left/right cell value which makes your scheme first order. You must use vanLeer, vanAlbada and the like to have a limited linear reconstruction using gradients to make your FVM discretization second order.
This would require you to specify the gradScheme in your fvSchemes in addition to interpolationScheme. 
Quote:
Thanks, I've used such schemes in obtaining the above results. I'm somewhat confused. while I'm using expressions like : Code:
surfaceScalarField rhoa_LR=fvc::interpolate(rhoa, Direction, "reconstruct(rho)"); Code:
interpolationSchemes does the gradScheme affect the cell to face interpolations? 
Quote:

Yes. The "gradScheme" will affect the interpolation. Have a look at the file
src/finiteVolume/interpolation/surfaceInterpolation/limitedSchemes/LimitedScheme/LimitedScheme.C : lines (38152) ...... 38 template<class Type, class Limiter, template<class> class LimitFunc> 39 tmp<surfaceScalarField> LimitedScheme<Type, Limiter, LimitFunc>::limiter 40 ( 41 const GeometricField<Type, fvPatchField, volMesh>& phi 42 ) const 43 { ..... 67 68 GeometricField<typename Limiter::gradPhiType, fvPatchField, volMesh> 69 gradc(fvc::grad(lPhi)); 70 ...... for limited interpolation OpenFOAM uses the gradient for reconstruction. I was wrong in my previous post about this ... So the gradScheme that you specify will affect your limited interpolation. If "rho" is the variable you interpolate then in gradScheme specify gradScheme { grad(rho) leastSquares; } to use leastSquares gradient reconstruction. Just figured this out reading the code last night. Hope this helps ... 
All times are GMT 4. The time now is 03:09. 