Exemplo n.º 1
0
// Surface linear forms representing the solid part of the boundary.
// The flux in the local coordinates is (0, p_b, 0, 0) where p_b stands for pressure on the boundary.
// The first function does the calculation, the next ones are added to the weakform and they call the first function, asking for
// the correct element of the vector.
double bdy_flux_solid_wall_comp(int element, int n, double *wt, Func<scalar> *ue[], Func<double> *v, Geom<double> *e, ExtData<double> *ext)
{
  double result = 0;
  double w01, w11, w21, w31;
  for (int i = 0; i < n; i++) 
  {
    w01 = ext->fn[0]->val[i];
    
    w11 = ext->fn[1]->val[i];

    w21 = ext->fn[2]->val[i];

    w31 = ext->fn[3]->val[i];

    double p_b = calc_pressure(w01, w11, w21, w31);
    
    //Ondrej's code.
    double flux[4];
    double alpha = atan2(e->ny[i], e->nx[i]);
    double mat_rot_inv[4][4];
    double flux_local[4];
    flux_local[0] = 0;
    flux_local[1] = p_b;
    flux_local[2] = 0;
    flux_local[3] = 0;
    num_flux.T_rot(mat_rot_inv, -alpha);
    num_flux.dot_vector(flux, mat_rot_inv, flux_local);

    result -= wt[i] * v->val[i] * flux[element];
  }
  return result * TAU;
}
Exemplo n.º 2
0
// Experimental "vector valued" linear form. Calculates and caches all components, returns the first one.
double linear_form_interface_vector(int n, double *wt, Func<double> *ue[], Func<double> *v, Geom<double> *e, ExtData<double> *ext)
{
  double *result = new double[4];
  result[0] = result[1] = result[2] = result[3] = 0;
  double w_l[4], w_r[4];
  for (int i = 0; i < n; i++) 
  {
    w_l[0] = ue[0]->get_val_central(i);
    w_r[0] = ue[0]->get_val_neighbor(i);
    
    w_l[1] = ue[1]->get_val_central(i);
    w_r[1] = ue[1]->get_val_neighbor(i);

    w_l[2] = ue[2]->get_val_central(i);
    w_r[2] = ue[2]->get_val_neighbor(i);

    w_l[3] = ue[3]->get_val_central(i);
    w_r[3] = ue[3]->get_val_neighbor(i);

    double flux[4];
    num_flux.numerical_flux(flux,w_l,w_r,e->nx[i], e->ny[i]);

    result[0] -= wt[i] * v->val[i] * flux[0] * TAU;
    result[1] -= wt[i] * v->val[i] * flux[1] * TAU;
    result[2] -= wt[i] * v->val[i] * flux[2] * TAU;
    result[3] -= wt[i] * v->val[i] * flux[3] * TAU;
  }
  DiscreteProblem::surf_forms_cache[DiscreteProblem::surf_forms_key] = result;
  return -result[0];
}
Exemplo n.º 3
0
// Experimental "vector valued" linear form. Calculates and caches all components, returns the first one.
double bdy_flux_solid_wall_comp_vector(int n, double *wt, Func<scalar> *ue[], Func<double> *v, Geom<double> *e, ExtData<double> *ext)
{
  double *result = new double[4];
  result[0] = result[1] = result[2] = result[3] = 0;
  double w01, w11, w21, w31;
  for (int i = 0; i < n; i++) 
  {
    w01 = ue[0]->val[i];
    
    w11 = ue[1]->val[i];

    w21 = ue[2]->val[i];

    w31 = ue[3]->val[i];

    double p_b = calc_pressure(w01, w11, w21, w31);
    
    //Ondrej's code.
    double flux[4];
    double alpha = atan2(e->ny[i], e->nx[i]);
    double mat_rot_inv[4][4];
    double flux_local[4];
    flux_local[0] = 0;
    flux_local[1] = p_b;
    flux_local[2] = 0;
    flux_local[3] = 0;
    num_flux.T_rot(mat_rot_inv, -alpha);
    num_flux.dot_vector(flux, mat_rot_inv, flux_local);

    result[0] -= wt[i] * v->val[i] * flux[0] * TAU;
    result[1] -= wt[i] * v->val[i] * flux[1] * TAU;
    result[2] -= wt[i] * v->val[i] * flux[2] * TAU;
    result[3] -= wt[i] * v->val[i] * flux[3] * TAU;
  }
  
  DiscreteProblem::surf_forms_cache[DiscreteProblem::surf_forms_key] = result;
  return -result[0];
}
Exemplo n.º 4
0
// Experimental "vector valued" linear form. Calculates and caches all components, returns the first one.
double bdy_flux_inlet_outlet_comp_vector(int n, double *wt, Func<scalar> *ue[], Func<double> *v, Geom<double> *e, ExtData<double> *ext)
{
  double *result = new double[4];
  result[0] = result[1] = result[2] = result[3] = 0;
  // Left (inner) state.
  double w_l[4];
  // Right (boundary) state.
  double w_r[4];
  // Eulerian flux.
  double flux[4];

  for (int i = 0; i < n; i++) 
  {
    // Left (inner) state from the previous time level solution.
    w_l[0] = ue[0]->val[i];
    
    w_l[1] = ue[1]->val[i];

    w_l[2] = ue[2]->val[i];

    w_l[3] = ue[3]->val[i];

    w_r[0] = bc_density(e->y[i]);

    w_r[1] = bc_density_vel_x(e->y[i]);

    w_r[2] = bc_density_vel_y(e->y[i]);

    w_r[3] = bc_energy(e->y[i]);
    
    num_flux.numerical_flux(flux,w_l,w_r,e->nx[i], e->ny[i]);

    result[0] -= wt[i] * v->val[i] * flux[0] * TAU;
    result[1] -= wt[i] * v->val[i] * flux[1] * TAU;
    result[2] -= wt[i] * v->val[i] * flux[2] * TAU;
    result[3] -= wt[i] * v->val[i] * flux[3] * TAU;
  }
  DiscreteProblem::surf_forms_cache[DiscreteProblem::surf_forms_key] = result;
  return -result[0];
}
Exemplo n.º 5
0
// Linear forms coming from the DG formulation, evaluated on the inner edges of the triangulation. Linear with respect to the test function v.
// Forms use riemann solvers (where the supplied states are from the previous time level).
// The first function does the calculation, the next ones are added to the weakform and they call the first function, asking for
// the correct element of the vector.
double linear_form_interface(int element, int n, double *wt, Func<double> *ue[], Func<double> *v, Geom<double> *e, ExtData<double> *ext)
{
  double result = 0;
  double w_l[4], w_r[4];
  for (int i = 0; i < n; i++) 
  {
    w_l[0] = ext->fn[0]->get_val_central(i);
    w_r[0] = ext->fn[0]->get_val_neighbor(i);
    
    w_l[1] = ext->fn[1]->get_val_central(i);
    w_r[1] = ext->fn[1]->get_val_neighbor(i);

    w_l[2] = ext->fn[2]->get_val_central(i);
    w_r[2] = ext->fn[2]->get_val_neighbor(i);

    w_l[3] = ext->fn[3]->get_val_central(i);
    w_r[3] = ext->fn[3]->get_val_neighbor(i);


    result -= wt[i] * v->val[i] * num_flux.numerical_flux_i(element, w_l, w_r, e->nx[i], e->ny[i]);
  }
  return result * TAU;
}
Exemplo n.º 6
0
// Surface linear forms representing the inlet/outlet part of the boundary.
// For details, see comments in the following function.
// The first function does the calculation, the next ones are added to the weakform and they call the first function, asking for
// the correct element of the vector.
double bdy_flux_inlet_outlet_comp(int element, int n, double *wt, Func<scalar> *ue[], Func<double> *v, Geom<double> *e, ExtData<double> *ext)
{
  double result = 0;
  // Left (inner) state.
  double w_l[4];
  // Right (boundary) state.
  double w_r[4];
  // Eulerian flux.
  //double flux[4];

  for (int i = 0; i < n; i++) 
  {
    // Left (inner) state from the previous time level solution.
    w_l[0] = ext->fn[0]->val[i];
    
    w_l[1] = ext->fn[1]->val[i];

    w_l[2] = ext->fn[2]->val[i];

    w_l[3] = ext->fn[3]->val[i];

    w_r[0] = RHO_EXT;

    w_r[1] = RHO_EXT * V1_EXT;

    w_r[2] = RHO_EXT * V2_EXT;

    w_r[3] = ENERGY_EXT;
    
    /*

    // The inlet part (left part of the computational domain).
    if(e->nx[i] < 0)
    {
      // Boundary state calculation.
      double rho_b = bc_density(e->y[i]);
      double velocity_x_b = bc_density_vel_x(e->y[i]) / bc_density(e->y[i]);
      double velocity_y_b = bc_density_vel_y(e->y[i]) / bc_density(e->y[i]);

      // Sound speed on the left (inner) side of the boundary.
      double sound_speed_l = calc_sound_speed(w_l[0], w_l[1], w_l[2], w_l[3]);

      // Intersection state calculation (marked with an underscore1 (_1)).
      double sound_speed_1 = sound_speed_l + (num_flux.R/num_flux.c_v) * (w_l[1]/w_l[0] - velocity_x_b);
      double rho_1 = std::pow(sound_speed_1*sound_speed_1*w_l[0]/(num_flux.kappa*calc_pressure(w_l[0], w_l[1], w_l[2], w_l[3])), num_flux.c_v/num_flux.R) * w_l[0];
      double velocity_x_1 = velocity_x_b;
      double velocity_y_1 = w_l[2] / w_l[0];

      // Boundary pressure calculated from the intersection state.
      double p_b = rho_1 * sound_speed_1 * sound_speed_1 / num_flux.kappa;
      // Calculation of the energy component of the intersection state.
      double energy_1 = calc_energy<double>(rho_1, velocity_x_1* rho_1, velocity_y_1 * rho_1, p_b);

      // Calculation of the state for inflow/outlow velocities above the local speed of sound.
      double sound_speed_l_star = num_flux.R/(num_flux.c_v * (2+num_flux.R/num_flux.c_v)) * w_l[1] / w_l[0] + 2 * sound_speed_l / (2+num_flux.R/num_flux.c_v);
      double rho_l_star = std::pow(sound_speed_l_star/sound_speed_l, 2*num_flux.c_v / num_flux.R) * w_l[0];
      double velocity_x_l_star = sound_speed_l_star;
      double velocity_y_l_star = w_l[2] / w_l[0];
      double p_l_star = rho_l_star * sound_speed_l_star * sound_speed_l_star / num_flux.kappa;
      double energy_l_star = calc_energy<double>(rho_l_star, velocity_x_l_star * rho_l_star, velocity_y_l_star * rho_l_star, p_l_star);

      // Inflow velocity below the local speed of sound (of the intersection state).
      if(velocity_x_b < sound_speed_1)
      {
        //Ondrej's code.
        double alpha = atan2(e->ny[i], e->nx[i]);
        double mat_rot_inv[4][4];
        double flux_local[4];
        double flux_global[4];
        double mat_rot[4][4];
        num_flux.T_rot(mat_rot, alpha);
        flux_global[0] = rho_1;
        flux_global[1] = velocity_x_1 * rho_1;
        flux_global[2] = velocity_y_1 * rho_1;
        flux_global[3] = energy_1;
        num_flux.dot_vector(flux_local, mat_rot, flux_global);
        flux[0] = f_x(0, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[1] = f_x(1, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[2] = f_x(2, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[3] = f_x(3, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        num_flux.T_rot(mat_rot_inv, -alpha);
        num_flux.dot_vector(flux, mat_rot_inv, flux);
      }
      // Inflow velocity above the local speed of sound (of the intersection state).
      else
      {
        //Ondrej's code.
        double alpha = atan2(e->ny[i], e->nx[i]);
        double mat_rot_inv[4][4];
        double flux_local[4];
        double flux_global[4];
        double mat_rot[4][4];
        num_flux.T_rot(mat_rot, alpha);
        flux_global[0] = rho_l_star;
        flux_global[1] = velocity_x_l_star * rho_l_star;
        flux_global[2] = velocity_y_l_star * rho_l_star;
        flux_global[3] = energy_l_star;
        num_flux.dot_vector(flux_local, mat_rot, flux_global);
        flux[0] = f_x(0, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[1] = f_x(1, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[2] = f_x(2, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[3] = f_x(3, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        num_flux.T_rot(mat_rot_inv, -alpha);
        num_flux.dot_vector(flux, mat_rot_inv, flux);
      }
    }
    // The outlet part (the right part of the boundary).
    else
    {
      // These calculations are the same as above.
      double p_b = bc_pressure(e->y[i]);
      double rho_b = w_l[0] * std::pow(p_b/calc_pressure(w_l[0], w_l[1], w_l[2], w_l[3]), (1/num_flux.kappa));
      double velocity_x_b = (w_l[1] / w_l[0]) + 2*(num_flux.c_v/num_flux.R)*(calc_sound_speed<double>(w_l[0], w_l[1], w_l[2], w_l[3]) - std::sqrt(num_flux.kappa * p_b / rho_b));
      double velocity_y_b = w_l[2] / w_l[0];
      double energy_b = calc_energy<double>(rho_b, velocity_x_b*rho_b, velocity_y_b*rho_b, p_b);

      double sound_speed_l_star = num_flux.R/(num_flux.c_v * (2+num_flux.R/num_flux.c_v)) * w_l[1] / w_l[0] + 2 * calc_sound_speed<double>(w_l[0], w_l[1], w_l[2], w_l[3]) / (2+num_flux.R/num_flux.c_v);
      double rho_l_star = std::pow(sound_speed_l_star/calc_sound_speed<double>(w_l[0], w_l[1], w_l[2], w_l[3]), 2*num_flux.c_v / num_flux.R) * w_l[0];
      double velocity_x_l_star = sound_speed_l_star;
      double velocity_y_l_star = w_l[2] / w_l[0];
      double p_l_star = rho_l_star * sound_speed_l_star * sound_speed_l_star / num_flux.kappa;
      double energy_l_star = calc_energy<double>(rho_l_star, velocity_x_l_star * rho_l_star, velocity_y_l_star * rho_l_star, p_l_star);

      double sound_speed_b = calc_sound_speed(rho_b, velocity_x_b*rho_b, velocity_y_b*rho_b, energy_b);
      //  Inflow velocity below the local speed of sound (of the intersection state).
      if(velocity_x_b < sound_speed_b)
      {
        //Ondrej's code.
        double alpha = atan2(e->ny[i], e->nx[i]);
        double mat_rot_inv[4][4];
        double flux_local[4];
        double flux_global[4];
        double mat_rot[4][4];
        num_flux.T_rot(mat_rot, alpha);
        flux_global[0] = rho_b;
        flux_global[1] = velocity_x_b * rho_b;
        flux_global[2] = velocity_y_b * rho_b;
        flux_global[3] = energy_b;
        num_flux.dot_vector(flux_local, mat_rot, flux_global);
        flux[0] = f_x(0, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[1] = f_x(1, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[2] = f_x(2, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[3] = f_x(3, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        num_flux.T_rot(mat_rot_inv, -alpha);
        num_flux.dot_vector(flux, mat_rot_inv, flux);
      }
      //  Outflow velocity above the local speed of sound (of the intersection state).
      else
      {
        //Ondrej's code.
        double alpha = atan2(e->ny[i], e->nx[i]);
        double mat_rot_inv[4][4];
        double flux_local[4];
        double flux_global[4];
        double mat_rot[4][4];
        num_flux.T_rot(mat_rot, alpha);
        flux_global[0] = rho_l_star;
        flux_global[1] = velocity_x_l_star * rho_l_star;
        flux_global[2] = velocity_y_l_star * rho_l_star;
        flux_global[3] = energy_l_star;
        num_flux.dot_vector(flux_local, mat_rot, flux_global);
        flux[0] = f_x(0, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[1] = f_x(1, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[2] = f_x(2, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        flux[3] = f_x(3, flux_local[0], flux_local[1], flux_local[2], flux_local[3]);
        num_flux.T_rot(mat_rot_inv, -alpha);
        num_flux.dot_vector(flux, mat_rot_inv, flux);
      }
    }
    */
    
    result -= wt[i] * v->val[i] * num_flux.numerical_flux_i(element, w_l, w_r, e->nx[i], e->ny[i]);
  }
  return result * TAU;
}