virtual void compute_numerical_flux(PhysData& left, PhysData& right, const RealVectorNDIM& unit_normal,
                                      RealVectorNEQS& flux, Real& wave_speed)
  {
    set_meanflow_properties(left);

    // Compute left and right fluxes
    PHYS::compute_properties(left.coord, left.solution, dummy_grads, p);
    PHYS::flux(p , unit_normal, flux_left);

    PHYS::compute_properties(left.coord, right.solution, dummy_grads, p);
    PHYS::flux(p , unit_normal, flux_right);

    // Compute the averaged properties
    sol_avg.noalias() = 0.5*(left.solution+right.solution);
    PHYS::compute_properties(left.coord, sol_avg, dummy_grads, p);

    // Compute absolute jacobian using averaged properties
    PHYS::flux_jacobian_eigen_structure(p,unit_normal,right_eigenvectors,left_eigenvectors,eigenvalues);
    abs_jacobian.noalias() = right_eigenvectors * eigenvalues.cwiseAbs().asDiagonal() * left_eigenvectors;

    // flux = central flux - upwind flux
    flux.noalias() = 0.5*(flux_left + flux_right);
    flux.noalias() -= 0.5*abs_jacobian*(right.solution-left.solution);
    wave_speed = eigenvalues.cwiseAbs().maxCoeff();
  }
 virtual void compute_analytical_flux(PhysData& data, const RealVectorNDIM& unit_normal,
                                      RealVectorNEQS& flux, Real& wave_speed)
 {
   set_meanflow_properties(data);
   PHYS::compute_properties(data.coord, data.solution , dummy_grads, p);
   PHYS::flux(p, unit_normal, flux);
   PHYS::flux_jacobian_eigen_values(p, unit_normal, eigenvalues);
   wave_speed = eigenvalues.cwiseAbs().maxCoeff();
 }
  virtual void compute_solution(const PhysData &inner_cell_data, const RealVectorNDIM &boundary_face_normal, RealVectorNEQS &boundary_face_solution)
  {
    set_meanflow_properties(inner_cell_data);

    RealVectorNEQS char_cell_sol;
    RealVectorNEQS char_bdry_sol;

    outward_normal = flx_pt_plane_jacobian_normal->get().plane_unit_normal[cell_flx_pt] * flx_pt_plane_jacobian_normal->get().sf->flx_pt_sign(cell_flx_pt);



//  COMMENTED HERE IS A STANDARD FORM NOT BASED ON CHARACTERISTIC THEORY
// velocity on the inside of the face
//    rho0u[XX] = inner_cell_data.solution[1];
//    rho0u[YY] = inner_cell_data.solution[2];

//    // velocity in outward_normal direction
//    rho0u_normal = rho0u.transpose()*outward_normal;

//    // Modify velocity to become the outside velocity of the face,
//    // and being the mirror of the inside velocity
//    rho0u.noalias() -= 2.*rho0u_normal*outward_normal;

//    boundary_face_solution = inner_cell_data.solution;
//    boundary_face_solution[1] = rho0u[XX];
//    boundary_face_solution[2] = rho0u[YY];

    cons_to_char(inner_cell_data.solution,outward_normal,char_cell_sol);
    const Real& S     = char_cell_sol[0];
    const Real& Omega = char_cell_sol[1];
    const Real& Aplus = char_cell_sol[2];
    const Real& Amin  = char_cell_sol[3];

    char_bdry_sol[0] =  S;
    char_bdry_sol[1] =  Omega;
    char_bdry_sol[2] =  Aplus;
    char_bdry_sol[3] =  Aplus; // Amin = Aplus is the magic here

    char_to_cons(char_bdry_sol,outward_normal,boundary_face_solution);
  }