// calculates the inverted flux, for testing purposes // it should return the same thing as riemann_solver(), only with minus sign void NumericalFlux::riemann_solver_invert(double result[4], double w_l[4], double w_r[4]) { double m[4][4]; double _w_l[4]; double _w_r[4]; double _tmp[4]; T_rot(m, M_PI); dot_vector(_w_l, m, w_l); dot_vector(_w_r, m, w_r); riemann_solver(_tmp, _w_r, _w_l); T_rot(m, -M_PI); dot_vector(result, m, _tmp); }
// Calculates the numerical flux in the normal (nx, ny) by rotating into the // local system, solving the Riemann problem and rotating back. It returns the // state as a 4-component vector. void NumericalFlux::numerical_flux(double result[4], double w_l[4], double w_r[4], double nx, double ny) { double alpha = atan2(ny, nx); double mat_rot[4][4]; double mat_rot_inv[4][4]; double w_l_local[4]; double w_r_local[4]; double flux_local[4]; T_rot(mat_rot, alpha); T_rot(mat_rot_inv, -alpha); dot_vector(w_l_local, mat_rot, w_l); dot_vector(w_r_local, mat_rot, w_r); riemann_solver(flux_local, w_l_local, w_r_local); dot_vector(result, mat_rot_inv, flux_local); }
static void riemann_solver(m2vol *VL, m2vol *VR, int axis, double *F, int suppress_extrapolation) { int q; m2riemann_problem R = { .m2 = VL->m2 }; double *UL = R.Ul; double *UR = R.Ur; double *FL = R.Fl; double *FR = R.Fr; double *lamL = R.lamL; double *lamR = R.lamR; double yl[8], yr[8]; /* cell-centered left/right interpolation variables */ double yL[8], yR[8]; /* face-centered left/right interpolation variables */ double xL = m2vol_coordinate_centroid(VL, axis); double xR = m2vol_coordinate_centroid(VR, axis); double *n = R.nhat; m2prim *PL = &R.Pl; m2prim *PR = &R.Pr; m2aux *AL = &R.Al; m2aux *AR = &R.Ar; int err[6]; int E = 1; if (suppress_extrapolation) E = 0; if (VL->m2->suppress_extrapolation_at_unhealthy_zones) { if (VL->zone_health != 0) E = 0; if (VR->zone_health != 0) E = 0; } if (VL->zone_type == M2_ZONE_TYPE_SHELL || VR->zone_type == M2_ZONE_TYPE_SHELL) { return; } n[0] = 0.0; n[1] = 0.0; n[2] = 0.0; n[3] = 0.0; n[axis] = 1.0; m2vol_to_interpolated(VL, yl, 1); m2vol_to_interpolated(VR, yr, 1); switch (axis) { case 1: for (q=0; q<8; ++q) yL[q] = yl[q] + E*VL->grad1[q] * (VL->x1[1] - xL); for (q=0; q<8; ++q) yR[q] = yr[q] + E*VR->grad1[q] * (VR->x0[1] - xR); break; case 2: for (q=0; q<8; ++q) yL[q] = yl[q] + E*VL->grad2[q] * (VL->x1[2] - xL); for (q=0; q<8; ++q) yR[q] = yr[q] + E*VR->grad2[q] * (VR->x0[2] - xR); break; case 3: for (q=0; q<8; ++q) yL[q] = yl[q] + E*VL->grad3[q] * (VL->x1[3] - xL); for (q=0; q<8; ++q) yR[q] = yr[q] + E*VR->grad3[q] * (VR->x0[3] - xR); break; } m2sim_from_interpolated(VL->m2, yL, PL); m2sim_from_interpolated(VR->m2, yR, PR); UL[B11] = PL->B1; UL[B22] = PL->B2; UL[B33] = PL->B3; UR[B11] = PR->B1; UR[B22] = PR->B2; UR[B33] = PR->B3; switch (axis) { case 1: UL[B11] = UR[B11] = PL->B1 = PR->B1 = VL->Bflux1A / VL->area1; break; case 2: UL[B22] = UR[B22] = PL->B2 = PR->B2 = VL->Bflux2A / VL->area2; break; case 3: UL[B33] = UR[B33] = PL->B3 = PR->B3 = VL->Bflux3A / VL->area3; break; } err[0] = m2sim_from_primitive(VL->m2, PL, NULL, NULL, 1.0, UL, AL); err[1] = m2sim_from_primitive(VR->m2, PR, NULL, NULL, 1.0, UR, AR); err[2] = m2aux_eigenvalues(AL, n, lamL); err[3] = m2aux_eigenvalues(AR, n, lamR); err[4] = m2aux_fluxes(AL, n, FL); err[5] = m2aux_fluxes(AR, n, FR); if (err[2]) VL->zone_health |= (1<<M2_BIT_BAD_EIGENVALUES); if (err[3]) VR->zone_health |= (1<<M2_BIT_BAD_EIGENVALUES); if (err[2] || err[3]) { if (suppress_extrapolation) { MSGF(INFO, "eigenvalues for %d-interface [%d %d %d] could not be found", axis, VL->global_index[1], VL->global_index[2], VL->global_index[3]); lamL[0] = -1.0; lamL[7] = +1.0; lamR[0] = -1.0; lamR[7] = +1.0; } else { riemann_solver(VL, VR, axis, F, 1); return; } } R.Sl = M2_MIN3(lamL[0], lamR[0], 0.0); R.Sr = M2_MAX3(lamL[7], lamR[7], 0.0); switch (VL->m2->riemann_solver) { case M2_RIEMANN_HLLE: riemann_solver_hlle(&R); break; case M2_RIEMANN_HLLC: riemann_solver_hllc(&R); break; default: MSG(FATAL, "invalid riemann solver"); break; } memcpy(F, R.F_hat, 8 * sizeof(double)); } static double plm_gradient(double *xs, double *fs, double plm) { #define minval3(a,b,c) ((a<b) ? ((a<c) ? a : c) : ((b<c) ? b : c)) #define sign(x) ((x > 0.0) - (x < 0.0)) double xL = xs[0]; double x0 = xs[1]; double xR = xs[2]; double yL = fs[0]; double y0 = fs[1]; double yR = fs[2]; double a = (yL - y0) / (xL - x0) * plm; double b = (yL - yR) / (xL - xR); double c = (y0 - yR) / (x0 - xR) * plm; double sa = sign(a), sb = sign(b), sc = sign(c); double fa = fabs(a), fb = fabs(b), fc = fabs(c); double g = 0.25 * fabs(sa + sb) * (sa + sc) * minval3(fa, fb, fc); if (g != g) { MSGF(FATAL, "got NAN gradient: [%f %f %f] [%f %f %f]", xs[0], xs[1], xs[2], fs[0], fs[1], fs[2]); } return g; #undef minval3 #undef sign }
int m2sim_calculate_flux(m2sim *m2) { int i, j, k; int *L = m2->local_grid_size; int *G = m2->domain_resolution; m2vol *V0, *V1, *V2, *V3; double n1[4] = { 0.0, 1.0, 0.0, 0.0 }; double n2[4] = { 0.0, 0.0, 1.0, 0.0 }; double n3[4] = { 0.0, 0.0, 0.0, 1.0 }; #ifdef _OPENMP #pragma omp parallel for private(V0,V1,V2,V3,j,k) #endif for (i=0; i<L[1]; ++i) { for (j=0; j<L[2]; ++j) { for (k=0; k<L[3]; ++k) { V0 = M2_VOL(i+0, j+0, k+0); V1 = M2_VOL(i+1, j+0, k+0); V2 = M2_VOL(i+0, j+1, k+0); V3 = M2_VOL(i+0, j+0, k+1); if (V1 == NULL) m2aux_fluxes(&V0->aux, n1, V0->flux1); else riemann_solver(V0, V1, 1, V0->flux1, 0); if (V2 == NULL) m2aux_fluxes(&V0->aux, n2, V0->flux2); else riemann_solver(V0, V2, 2, V0->flux2, 0); if (V3 == NULL) m2aux_fluxes(&V0->aux, n3, V0->flux3); else riemann_solver(V0, V3, 3, V0->flux3, 0); } } } for (i=0; i<L[1]; ++i) { for (j=0; j<L[2]; ++j) { for (k=0; k<L[3]; ++k) { V0 = M2_VOL(i, j, k); if (m2->periodic_dimension[1] == 0 && (V0->global_index[1] == -1 || V0->global_index[1] == G[1] - 1)) { if (m2->boundary_conditions_flux1) { m2->boundary_conditions_flux1(V0); } } if (m2->periodic_dimension[2] == 0 && (V0->global_index[2] == -1 || V0->global_index[2] == G[2] - 1)) { if (m2->boundary_conditions_flux2) { m2->boundary_conditions_flux2(V0); } } if (m2->periodic_dimension[3] == 0 && (V0->global_index[3] == -1 || V0->global_index[3] == G[3] - 1)) { if (m2->boundary_conditions_flux3) { m2->boundary_conditions_flux3(V0); } } } } } return 0; }