// 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; }
// 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; }