Spatial stability analysis for compressible jet flow

Hi all,

I am working on spatial stability analysis of 1D jet flow in a polar coordinate system.

I am trying to validate the growth rate plot from this Linear and nonlinear mechanisms of sound
radiation by instability waves in subsonic jets VICTORIA SUPONITSKY, research paper.

Link for paper: Linear and nonlinear mechanisms of sound radiation by instability waves in subsonic jets | Journal of Fluid Mechanics | Cambridge Core

I wasn’t able to match the result.

I have attached the code and the current result plot for reference.

Thanks in advance.

//x=z, r=y, z=theta
// Run with MPI: ff-mpirun -np 4 jetstab.edp

load "PETSc-complex"
load "msh3"
macro dimension()3L//
include "macro_ddm.idp"

func Pb2 = [P2, P2];
func Pc = [P2, P2, P2, P2, P2]; // [rho, Vr, Vtheta, Vz, Tt]



real rmin = 1e-6;  // avoid singularity at r=0
//real rmin = 0;
real rmax = 10;
border rline(t=rmin,rmax){x=0;  y=t;}
int np = 45000;

meshL thL=buildmeshL(rline(np));
meshL thLzero = thL;



// Define separate complex FE functions
fespace VhC(thL,Pc);
VhC<complex> [rho, vr, vtheta, vz, Tt], [X1, X2, X3, X4, X5];
fespace VhBzero(thLzero,Pb2);


fespace Vh(thL,P1);

Vh U,Ur,Urr;


// Define r as the coordinate variable
Vh r = y;


//*********   for the profile  ********

/*
U=1/(1+(r*r))^2;

ofstream fout("U_output.txt");  // open file for writing
fout << U[] << endl;

*/


real zpos = 0;                 // renamed from z
real vcoflow = 0.01;          // fixed incomplete line

real a = 0.59 + 0.09 * tanh(sqrt(zpos) - 2.9);
real delta = (39 + 24*zpos + 0.11*zpos^4) / (1000 + zpos^3);

func real Vz(real r) {
    return 0.5 * (tanh((r + a) / delta) - tanh((r - a) / delta));
}

real a0 = 0.59 + 0.09 * tanh(sqrt(0) - 2.9);
real delta0 = (39 + 24*0 + 0.11*0^4) / (1000 + 0^3);
func real Vzref(real r) {
    return 0.5 * (tanh((r + a0) / delta0) - tanh((r - a0) / delta0));
}

func real Vzsim(real r) {
    return (Vz(r) + vcoflow) / (Vzref(0) + vcoflow);
}

U = Vzsim(r);

ofstream fout("U_output.txt");  // open file for writing
fout << U[] << endl;




// Define dr as a macro for dx
macro dr(u) dy(u) // EOM


Ur=dr(U);
Urr=dr(Ur);


 
    int[int] n2othL2;
    macro thL2N2O()n2othL2//
    fespace Bh(thL,P2);

real Pr=0.72;
real ga=1.4;
real M=0.9;
real M2=M*M;

Vh T,Tr,Trr;


T=1+M2*(ga-1)*(U-U*U);
Tr=M2*(ga-1)*(dr(U)-2*U*dr(U));
Trr=M2*(ga-1)*(dr(Ur)-2*dr(U)*dr(U)-2*U*dr(Ur));

real C=0.5;
Vh Mu,Mut,K,Kt,Mutt,Ktt;

Mu=(T^1.5)*((1+C)/(T+C));
K=(T^1.5)*((1+C)/(T+C));

Mut= 1.5*sqrt(T)*(1+C)*(1/(T+C)) - (T^(1.5))*((1+C)/((T+C)^(2)));
Mutt=(3/4)*(1/sqrt(T))*((1+C)/(T+C)) -3*sqrt(T)*( (1+C)/((T+C)*(T+C)) ) +2*(T^1.5)*((1+C)/(T+C)^3);

Kt=1.5*sqrt(T)*(1+C)*(1/(T+C)) - (T^(1.5))*((1+C)/((T+C)^(2)));
Ktt=(3/4)*(1/sqrt(T))*((1+C)/(T+C)) -3*sqrt(T)*( (1+C)/((T+C)*(T+C)) ) +2*(T^1.5)*((1+C)/((T+C)^3));



// Viscosity derivatives with respect to r
Vh Mur = Mut * Tr;                        // ∂μ/∂r = (∂μ/∂T)(∂T/∂r)
Vh Murr = (Mutt * (Tr * Tr)) + (Mut * Trr);   // ∂²μ/∂r² = (∂²μ/∂T²)(∂T/∂r)² + (∂μ/∂T)(∂²T/∂r²)

Vh Kr = Kt * Tr;   // First derivative ∂κ/∂r
Vh Krr =( Ktt * (Tr * Tr)) + (Kt * Trr);       // Second derivative ∂²κ/∂r² 


// Temperature and density profiles
Vh Rho,Rhor,Rhorr;
Rho=1/T;
Rhor=dr(Rho);
Rhorr=dr(Rhor);


/* ################################################################################## */
/* ########################## Solution of the Eigenproblem ########################## */
/* ################################################################################## */

real Re = getARGV("-Re", 3600);
real om= getARGV("-om", 9);
real shiftr = getARGV("-shiftr", 15);
real shifti = getARGV("-shifti", -1.4);
complex shift = shiftr + 1i*shifti;
int nEV = getARGV("-nEV", 15);
int nKryl = getARGV("-nKryl", 200);

real m = getARGV("-m", 0); // Azimuthal wavenumber   // m = 0 - axisymmetric;m = 1-first helical mode; m = 2 - higher modes


// Define test functions
VhC<complex> [a1, a2, a3, a4, a5];

// Weak form definitions based on the PDF formulation

varf A0mat([rho, vr, vtheta, vz, Tt],[a1,a2,a3,a4,a5]) = 
    int1d(thL) ( 
        // Row 1: Continuity Equation (ν1)
        ( a1 * (( vr *r*r* Rhor) + (Rho *r*r* dr(vr)) + (Rho * r* vr)  + (1i * m *r * Rho * vtheta )) ) - (a1* 1i * om*r*r* rho)    // contribution from -i*omega*K 
        
        // Row 2: r-Momentum Equation (ν2)
	    +(a2 * ( ((1.0 / (ga * M * M)) *r*r * Tr * rho)
             	 			+ ((1.0 / (ga * M * M)) *r*r *T * dr(rho))
             	 			- (1.0 / Re) * ( (-(7.0/3.0) * (1i * m * Mu * vtheta))
                        					    - ((2.0/3.0) * (1i * m* r* Mur * vtheta))
                            					  + ((1.0/3.0) * (1i * m * r* Mu * dr(vtheta))) )
                 			+ ((1.0 / (ga * M * M)) *r*r * Rhor * Tt )
	               + ((1.0 / (ga * M * M)) *r*r* Rho * dr(Tt))
		 - (1.0 / Re) *( ((4.0/3.0) * (Mu* r * dr(vr)) )
                                				+ ((4.0/3.0) *r*r* Mur * dr(vr))
                            					- (m*m * Mu * vr)
                            					- ((4.0/3.0) * (Mu * vr))  
                            					- ((2.0/3.0) * Mur* r* vr ) )   )  )
        		   + (1.0 / Re) * (4.0/3.0) * ( (r*r* dr(a2) * Mu * dr(vr))+ ( r*r* a2 * Mur * dr(vr)) + (2* a2*r* Mu* dr(vr)) )
           		 - (a2* 1i * r* r*om * Rho * vr)
        

        // Row 3: θ-Momentum Equation (ν3)
      		 	+ (a3 * ( ((1i * m / (ga * M * M))*r * T * rho)
                    			+  ((1i * m / (ga * M * M ))*r *Rho * Tt)
                   			- (1.0 / Re) * ( ((7.0/3.0) * (1i * m * Mu * vr))
                            					+ (1i * m *r * Mur * vr)
                           					+ (1i * m* r*(1.0/3.0) * Mu * dr(vr)) )
                      			 - (1.0 / Re) *( (Mu *r * dr(vtheta))
                            					+ (r*r* Mur * dr(vtheta))
                            					- ((4.0/3.0) * (m*m * Mu * vtheta))
                            					- (Mu * vtheta)
                            					- (r* Mur * vtheta) )  )  )
          		 + (1.0 / Re) * ( dr(a3) *r*r* Mu * dr(vtheta) + a3 * r*r*Mur * dr(vtheta)  + 2*a3*Mu*r* dr(vtheta) )
           		-( a3* 1i *r* r* om * Rho * vtheta)
        

	// Row 4: z-Momentum Equation (ν4)
	        +  (a4* ( ( Rho * Ur *r*r* vr)
         	     			   - (1.0 / Re) * ( (Mu *r * dr(vz))
                           						+ (r*r * Mur * dr(vz))
                            	 					- (m*m * Mu * vz))
          	       			 - (1.0 / Re) * ((r*r* Urr * Mut * Tt)
                          					+ (r* Mut * Ur*Tt)
                          					+ (r*r* Mut*Ur * dr(Tt))  )    )  )
           			+ (1.0 / Re) * ( dr(a4) *r*r* Mu * dr(vz) + a4 *r*r* Mur * dr(vz)  + 2*a4*r* Mu* dr(vz))
         			  - (a4* 1i *r* r*om * Rho * vz)


  	// Row 5: Energy Equation (ν5)
      				  + (a5* (  (Rho * Tr *r*r* vr)
                				+ ((ga - 1.0) * r * Rho * T* vr)
              					  + ((ga - 1.0) * Rho * T *r*r* dr(vr))
              					  + ((ga - 1.0) * (1i * m *r * Rho * T * vtheta))
            					    - ( ((M*M * ga * (ga - 1.0)) / Re ) *r*r* ( 2.0 * Mu * Ur * dr(vz) ))
             					   - (((M*M * ga * (ga - 1.0)) / Re )*r*r* ((Ur * Ur) * Mut * Tt ))
            					    - ( ga / (Pr * Re) ) * (( r*r* Trr * Kt * Tt)
                               								     + (r * Kr * Tt)
                                   							   - (m*m* K * Tt)    
			                                    + (r*r*Kr * dr(Tt))
                                    								+ (r*r*Kt*Tr * dr(Tt))
                              								       + (K*r* dr(Tt)) ) )  )
       			     + ( ga / (Pr * Re) ) * ( dr(a5) *r*r* K * dr(Tt) + a5 *r*r* Kr * dr(Tt)  + 2* a5*r*K* dr(Tt) )
         		   - (a5* 1i * r* r*om * Rho * Tt)
          
)+ on((abs(m) == 0)*1, vr=0 ,   vtheta=0)       							// |m| = 0 case
+ on((abs(m) == 1)*1, rho=0,  vz=0,  Tt=0)		 					// |m| = 1 case
+ on((abs(m) >= 2)*1, rho=0,  vr=0,  vtheta=0,  vz=0,  Tt=0 ) 					// |m| ≥ 2
+ on(2,  rho=0,  vr=0,  vtheta=0,  vz=0,  Tt=0); 						// r = Rmax



varf A1mat([rho, vr, vtheta, vz, Tt], [a1, a2, a3, a4, a5]) = 
    int1d(thL)(
(
         	 a1*(1i*U*r*r*rho + 1i*Rho*r*r*vz)
       			  + (a2*1i*Rho*U*r*r*vr)
        		 + (a3* 1i*Rho*U*r*r*vtheta)
       			  + a4*(((1i* T)/(ga*M*M))*r*r*rho + 1i*Rho*U*r*r*vz + ((1i* Rho)/(ga*M*M)*r*r*Tt ))
       			  +a5* (((ga-1)*1i*r*r*Rho*T*vz)+ 1i*Rho*r*r*U*Tt)
   		      - (1/Re)*(
                  			  a2 * (((1.0 / 3.0)* 1i *Mu *r*r* dr(vz))
                    				     - ((2.0 / 3.0) * 1i *r*r *Mur * vz)
                      				   + (1i *r*r* Ur * Mut * Tt) )
                			 - a3 * ((1.0 / 3.0) *m *r*r * Mur * vz)
               				  + a4 * ( (1i * Mu*(1.0/3.0) *r*r * dr(vr))
                       				    + ((1.0 / 3.0)*1i* r* Mu*vr)
               					   + (1i * Mur*r*r* vr)
                        			   - ((m* Mu*r* (1.0/3.0) * dr(vtheta)))  )
              				  + a5*(2.0*M*M*ga*(ga-1.0)*1i*Mu*r*r*Ur*vr)
             )
	)
)+ on((abs(m) == 0)*1, vr=0 ,   vtheta=0)       							// |m| = 0 case
+ on((abs(m) == 1)*1, rho=0,  vz=0,  Tt=0)		 					// |m| = 1 case
+ on((abs(m) >= 2)*1, rho=0,  vr=0,  vtheta=0,  vz=0,  Tt=0 ) 					// |m| ≥ 2
+ on(2,  rho=0,  vr=0,  vtheta=0,  vz=0,  Tt=0); 						// r = Rmax



varf A2mat([rho, vr, vtheta, vz, Tt],[a1,a2,a3,a4,a5]) = 
    int1d(thL) ( 
(
         -(1.0/Re)*( ( Mu*a2*vr*r*r)
                    + (Mu*a3*vtheta*r*r)
                    + ((4.0/3.0)*Mu*a4*vz*r*r)
                    + ((ga/(Re*Pr))*a5*r*r*K*Tt)   )
)
    ) + on((abs(m) == 0)*1, vr=0 ,   vtheta=0)       						// |m| = 0 case
+ on((abs(m) == 1)*1, rho=0,  vz=0,  Tt=0)		 					// |m| = 1 case
+ on((abs(m) >= 2)*1, rho=0,  vr=0,  vtheta=0,  vz=0,  Tt=0) 					// |m| ≥ 2
+ on(2,  rho=0,  vr=0,  vtheta=0,  vz=0,  Tt=0); 						// r = Rmax


Mat<complex>[int] Apep(3);
macro def(u)[u, u#B, u#C,u#D,u#E]//EOM
macro init(i)[i, i, i,i,i]//EOM
{
    MatCreate(thL, Apep[0], Pc);   // Create the matrices array first
    MatCreate(thL, Apep[1], Pc);
    MatCreate(thL, Apep[2], Pc);
}


Apep[2] = A2mat(VhC,VhC,tgv=-1);
Apep[1] = A1mat(VhC,VhC,tgv=-1);
Apep[0] = A0mat(VhC,VhC,tgv=-1);


VhC<complex>[int] def(eigenvecVec)(nEV);
complex[int] eigvalVec(nEV);
real[int] errestVec(nEV);

string PEPParamsbase =
  " -pep_basis monomial " +
  " -pep_general " +
  " -st_type sinvert " +
  " -st_pc_type lu " +
  " -pep_tol 1e-8 ";

string PEPspar = PEPParamsbase + " -pep_target " + shift +
  " -pep_nev " + nEV +
  " -pep_ncv " + nKryl + " ";

int nEvalConv = PEPSolve(Apep, vectors = eigenvecVec, values = eigvalVec, sparams = PEPspar, errorestimate = errestVec);


if(mpirank == 0) {
    cout << "Same output manually" << endl;
    cout << "    PEP nconv=" << nEvalConv << " Values (Errors)";
    for(int i = 0; i < nEvalConv; i++) {
        cout << " " << real(eigvalVec[i]) << "+" << imag(eigvalVec[i]) << "i (" << errestVec[i] << ")";
    }
    cout << endl;
}

if(mpirank == 0) {
    ofstream ofile("Blasius_EV.dat");
    ofile.precision(16);
    ofile << eigvalVec << endl;
        }


/*---------------------------------------------------------------------
   Extract the components of the first eigenvector
   from the 5-component FE space: [ρ, v_r, v_θ, v_z, T_t]
---------------------------------------------------------------------*/

// Define complex finite element functions for each component
Bh<complex> Rh, Vr, Vtheta,Vzz ,Tth;

    Rh=eigenvecVec[0];    // density perturbation (rho) component of the first eigenmode
    Vr=eigenvecVecB[0];   //x-velocity perturbation component
    Vtheta=eigenvecVecC[0];   // y-velocity perturbation component
              Vzz=eigenvecVecD[0];		// z-velocity perturbation component
    Tth=eigenvecVecE[0]; 	//temperature/energy perturbation component


//---------------------------------------------
// Write results to files for visualization
//---------------------------------------------
ofstream fileRho("rho_eig.txt");
fileRho.precision(12);
fileRho << Rh[] << endl;

ofstream fileVr("vr_eig.txt");
fileVr.precision(12);
fileVr << Vr[] << endl;

ofstream fileVtheta("vtheta_eig.txt");
fileVtheta.precision(12);
fileVtheta << Vtheta[] << endl;

ofstream fileVzz("vzz_eig.txt");
fileVzz.precision(12);
fileVzz << Vzz[] << endl;


ofstream fileTt("Tt_eig.txt");
fileTt.precision(12);
fileTt << Tth[] << endl;