184ff8c8bSHong Zhang /* 284ff8c8bSHong Zhang Note: 36aad120cSJose E. Roman -hratio is the ratio between mesh size of coarse grids and fine grids 484ff8c8bSHong Zhang */ 584ff8c8bSHong Zhang 684ff8c8bSHong Zhang static const char help[] = "1D periodic Finite Volume solver in slope-limiter form with semidiscrete time stepping.\n" 784ff8c8bSHong Zhang " advect - Constant coefficient scalar advection\n" 884ff8c8bSHong Zhang " u_t + (a*u)_x = 0\n" 984ff8c8bSHong Zhang " shallow - 1D Shallow water equations (Saint Venant System)\n" 1084ff8c8bSHong Zhang " h_t + (q)_x = 0 \n" 1184ff8c8bSHong Zhang " q_t + (\frac{q^2}{h} + g/2*h^2)_x = 0 \n" 1284ff8c8bSHong Zhang " where, h(x,t) denotes the height of the water and q(x,t) the momentum.\n" 1384ff8c8bSHong Zhang " for this toy problem, we choose different meshsizes for different sub-domains (slow-fast-slow), say\n" 1484ff8c8bSHong Zhang " hxs = hratio*hxf \n" 1584ff8c8bSHong Zhang " where hxs and hxf are the grid spacings for coarse and fine grids respectively.\n" 1684ff8c8bSHong Zhang " exact - Exact Riemann solver which usually needs to perform a Newton iteration to connect\n" 1784ff8c8bSHong Zhang " the states across shocks and rarefactions\n" 1884ff8c8bSHong Zhang " simulation - use reference solution which is generated by smaller time step size to be true solution,\n" 1984ff8c8bSHong Zhang " also the reference solution should be generated by user and stored in a binary file.\n" 2084ff8c8bSHong Zhang " characteristic - Limit the characteristic variables, this is usually preferred (default)\n" 2184ff8c8bSHong Zhang " bc_type - Boundary condition for the problem, options are: periodic, outflow, inflow " 2284ff8c8bSHong Zhang "Several problem descriptions (initial data, physics specific features, boundary data) can be chosen with -initial N\n\n" 2384ff8c8bSHong Zhang "The problem size should be set with -da_grid_x M\n\n"; 2484ff8c8bSHong Zhang 2584ff8c8bSHong Zhang /* 2684ff8c8bSHong Zhang Example: 2784ff8c8bSHong Zhang ./ex4 -da_grid_x 40 -initial 1 -hratio 1 -limit mc -ts_dt 0.01 -ts_max_time 7.0 -ts_type mprk -ts_mprk_type 2a22 -ts_monitor_draw_solution -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 0 2884ff8c8bSHong Zhang ./ex4 -da_grid_x 40 -initial 2 -hratio 1 -limit mc -ts_dt 0.01 -ts_max_time 2.5 -ts_type mprk -ts_mprk_type 2a22 -ts_monitor_draw_solution -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 0 2984ff8c8bSHong Zhang ./ex4 -da_grid_x 40 -initial 3 -hratio 1 -limit mc -ts_dt 0.01 -ts_max_time 4.0 -ts_type mprk -ts_mprk_type 2a22 -ts_monitor_draw_solution -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 0 3084ff8c8bSHong Zhang ./ex4 -da_grid_x 40 -initial 4 -hratio 1 -limit koren3 -ts_dt 0.01 -ts_max_time 4.0 -ts_type mprk -ts_mprk_type 2a22 -ts_monitor_draw_solution -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 0 3184ff8c8bSHong Zhang ./ex4 -da_grid_x 40 -initial 5 -hratio 1 -limit mc -ts_dt 0.01 -ts_max_time 5.0 -ts_type mprk -ts_mprk_type 2a22 -ts_monitor_draw_solution -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 0 3284ff8c8bSHong Zhang 3384ff8c8bSHong Zhang Contributed by: Aidan Hamilton <aidan@udel.edu> 3484ff8c8bSHong Zhang */ 3584ff8c8bSHong Zhang 3684ff8c8bSHong Zhang #include <petscts.h> 3784ff8c8bSHong Zhang #include <petscdm.h> 3884ff8c8bSHong Zhang #include <petscdmda.h> 3984ff8c8bSHong Zhang #include <petscdraw.h> 4084ff8c8bSHong Zhang #include "finitevolume1d.h" 4184ff8c8bSHong Zhang #include <petsc/private/kernels/blockinvert.h> 4284ff8c8bSHong Zhang 439371c9d4SSatish Balay static inline PetscReal RangeMod(PetscReal a, PetscReal xmin, PetscReal xmax) { 449371c9d4SSatish Balay PetscReal range = xmax - xmin; 459371c9d4SSatish Balay return xmin + PetscFmodReal(range + PetscFmodReal(a, range), range); 469371c9d4SSatish Balay } 479371c9d4SSatish Balay static inline PetscReal MaxAbs(PetscReal a, PetscReal b) { 489371c9d4SSatish Balay return (PetscAbs(a) > PetscAbs(b)) ? a : b; 499371c9d4SSatish Balay } 5084ff8c8bSHong Zhang /* --------------------------------- Advection ----------------------------------- */ 5184ff8c8bSHong Zhang typedef struct { 5284ff8c8bSHong Zhang PetscReal a; /* advective velocity */ 5384ff8c8bSHong Zhang } AdvectCtx; 5484ff8c8bSHong Zhang 559371c9d4SSatish Balay static PetscErrorCode PhysicsRiemann_Advect(void *vctx, PetscInt m, const PetscScalar *uL, const PetscScalar *uR, PetscScalar *flux, PetscReal *maxspeed) { 5684ff8c8bSHong Zhang AdvectCtx *ctx = (AdvectCtx *)vctx; 5784ff8c8bSHong Zhang PetscReal speed; 5884ff8c8bSHong Zhang 5984ff8c8bSHong Zhang PetscFunctionBeginUser; 6084ff8c8bSHong Zhang speed = ctx->a; 6184ff8c8bSHong Zhang flux[0] = PetscMax(0, speed) * uL[0] + PetscMin(0, speed) * uR[0]; 6284ff8c8bSHong Zhang *maxspeed = speed; 6384ff8c8bSHong Zhang PetscFunctionReturn(0); 6484ff8c8bSHong Zhang } 6584ff8c8bSHong Zhang 669371c9d4SSatish Balay static PetscErrorCode PhysicsCharacteristic_Advect(void *vctx, PetscInt m, const PetscScalar *u, PetscScalar *X, PetscScalar *Xi, PetscReal *speeds) { 6784ff8c8bSHong Zhang AdvectCtx *ctx = (AdvectCtx *)vctx; 6884ff8c8bSHong Zhang 6984ff8c8bSHong Zhang PetscFunctionBeginUser; 7084ff8c8bSHong Zhang X[0] = 1.; 7184ff8c8bSHong Zhang Xi[0] = 1.; 7284ff8c8bSHong Zhang speeds[0] = ctx->a; 7384ff8c8bSHong Zhang PetscFunctionReturn(0); 7484ff8c8bSHong Zhang } 7584ff8c8bSHong Zhang 769371c9d4SSatish Balay static PetscErrorCode PhysicsSample_Advect(void *vctx, PetscInt initial, FVBCType bctype, PetscReal xmin, PetscReal xmax, PetscReal t, PetscReal x, PetscReal *u) { 7784ff8c8bSHong Zhang AdvectCtx *ctx = (AdvectCtx *)vctx; 7884ff8c8bSHong Zhang PetscReal a = ctx->a, x0; 7984ff8c8bSHong Zhang 8084ff8c8bSHong Zhang PetscFunctionBeginUser; 8184ff8c8bSHong Zhang switch (bctype) { 8284ff8c8bSHong Zhang case FVBC_OUTFLOW: x0 = x - a * t; break; 8384ff8c8bSHong Zhang case FVBC_PERIODIC: x0 = RangeMod(x - a * t, xmin, xmax); break; 8484ff8c8bSHong Zhang default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "unknown BCType"); 8584ff8c8bSHong Zhang } 8684ff8c8bSHong Zhang switch (initial) { 8784ff8c8bSHong Zhang case 0: u[0] = (x0 < 0) ? 1 : -1; break; 8884ff8c8bSHong Zhang case 1: u[0] = (x0 < 0) ? -1 : 1; break; 8984ff8c8bSHong Zhang case 2: u[0] = (0 < x0 && x0 < 1) ? 1 : 0; break; 9084ff8c8bSHong Zhang case 3: u[0] = PetscSinReal(2 * PETSC_PI * x0); break; 9184ff8c8bSHong Zhang case 4: u[0] = PetscAbs(x0); break; 9284ff8c8bSHong Zhang case 5: u[0] = (x0 < 0 || x0 > 0.5) ? 0 : PetscSqr(PetscSinReal(2 * PETSC_PI * x0)); break; 9384ff8c8bSHong Zhang case 6: u[0] = (x0 < 0) ? 0 : ((x0 < 1) ? x0 : ((x0 < 2) ? 2 - x0 : 0)); break; 9484ff8c8bSHong Zhang case 7: u[0] = PetscPowReal(PetscSinReal(PETSC_PI * x0), 10.0); break; 9584ff8c8bSHong Zhang default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "unknown initial condition"); 9684ff8c8bSHong Zhang } 9784ff8c8bSHong Zhang PetscFunctionReturn(0); 9884ff8c8bSHong Zhang } 9984ff8c8bSHong Zhang 1009371c9d4SSatish Balay static PetscErrorCode PhysicsCreate_Advect(FVCtx *ctx) { 10184ff8c8bSHong Zhang AdvectCtx *user; 10284ff8c8bSHong Zhang 10384ff8c8bSHong Zhang PetscFunctionBeginUser; 1049566063dSJacob Faibussowitsch PetscCall(PetscNew(&user)); 10584ff8c8bSHong Zhang ctx->physics2.sample2 = PhysicsSample_Advect; 10684ff8c8bSHong Zhang ctx->physics2.riemann2 = PhysicsRiemann_Advect; 10784ff8c8bSHong Zhang ctx->physics2.characteristic2 = PhysicsCharacteristic_Advect; 10884ff8c8bSHong Zhang ctx->physics2.destroy = PhysicsDestroy_SimpleFree; 10984ff8c8bSHong Zhang ctx->physics2.user = user; 11084ff8c8bSHong Zhang ctx->physics2.dof = 1; 11184ff8c8bSHong Zhang 1129566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("u", &ctx->physics2.fieldname[0])); 11384ff8c8bSHong Zhang user->a = 1; 114d0609cedSBarry Smith PetscOptionsBegin(ctx->comm, ctx->prefix, "Options for advection", ""); 1159566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-physics_advect_a", "Speed", "", user->a, &user->a, NULL)); 116d0609cedSBarry Smith PetscOptionsEnd(); 11784ff8c8bSHong Zhang PetscFunctionReturn(0); 11884ff8c8bSHong Zhang } 11984ff8c8bSHong Zhang /* --------------------------------- Shallow Water ----------------------------------- */ 12084ff8c8bSHong Zhang 12184ff8c8bSHong Zhang typedef struct { 12284ff8c8bSHong Zhang PetscReal gravity; 12384ff8c8bSHong Zhang } ShallowCtx; 12484ff8c8bSHong Zhang 1259371c9d4SSatish Balay static inline void ShallowFlux(ShallowCtx *phys, const PetscScalar *u, PetscScalar *f) { 12684ff8c8bSHong Zhang f[0] = u[1]; 12784ff8c8bSHong Zhang f[1] = PetscSqr(u[1]) / u[0] + 0.5 * phys->gravity * PetscSqr(u[0]); 12884ff8c8bSHong Zhang } 12984ff8c8bSHong Zhang 1309371c9d4SSatish Balay static PetscErrorCode PhysicsRiemann_Shallow_Exact(void *vctx, PetscInt m, const PetscScalar *uL, const PetscScalar *uR, PetscScalar *flux, PetscReal *maxspeed) { 13184ff8c8bSHong Zhang ShallowCtx *phys = (ShallowCtx *)vctx; 13284ff8c8bSHong Zhang PetscScalar g = phys->gravity, ustar[2], cL, cR, c, cstar; 1339371c9d4SSatish Balay struct { 1349371c9d4SSatish Balay PetscScalar h, u; 1359371c9d4SSatish Balay } L = {uL[0], uL[1] / uL[0]}, R = {uR[0], uR[1] / uR[0]}, star; 13684ff8c8bSHong Zhang PetscInt i; 13784ff8c8bSHong Zhang 13884ff8c8bSHong Zhang PetscFunctionBeginUser; 1393c633725SBarry Smith PetscCheck((L.h > 0 && R.h > 0), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Reconstructed thickness is negative"); 14084ff8c8bSHong Zhang cL = PetscSqrtScalar(g * L.h); 14184ff8c8bSHong Zhang cR = PetscSqrtScalar(g * R.h); 14284ff8c8bSHong Zhang c = PetscMax(cL, cR); 14384ff8c8bSHong Zhang { 14484ff8c8bSHong Zhang /* Solve for star state */ 14584ff8c8bSHong Zhang const PetscInt maxits = 50; 14684ff8c8bSHong Zhang PetscScalar tmp, res, res0 = 0, h0, h = 0.5 * (L.h + R.h); /* initial guess */ 14784ff8c8bSHong Zhang h0 = h; 14884ff8c8bSHong Zhang for (i = 0; i < maxits; i++) { 14984ff8c8bSHong Zhang PetscScalar fr, fl, dfr, dfl; 1509371c9d4SSatish Balay fl = (L.h < h) ? PetscSqrtScalar(0.5 * g * (h * h - L.h * L.h) * (1 / L.h - 1 / h)) /* shock */ 15184ff8c8bSHong Zhang : 2 * PetscSqrtScalar(g * h) - 2 * PetscSqrtScalar(g * L.h); /* rarefaction */ 1529371c9d4SSatish Balay fr = (R.h < h) ? PetscSqrtScalar(0.5 * g * (h * h - R.h * R.h) * (1 / R.h - 1 / h)) /* shock */ 15384ff8c8bSHong Zhang : 2 * PetscSqrtScalar(g * h) - 2 * PetscSqrtScalar(g * R.h); /* rarefaction */ 15484ff8c8bSHong Zhang res = R.u - L.u + fr + fl; 155cad9d221SBarry Smith PetscCheck(!PetscIsInfOrNanScalar(res), PETSC_COMM_SELF, PETSC_ERR_FP, "Infinity or Not-a-Number generated in computation"); 15684ff8c8bSHong Zhang if (PetscAbsScalar(res) < PETSC_SQRT_MACHINE_EPSILON || (i > 0 && PetscAbsScalar(h - h0) < PETSC_SQRT_MACHINE_EPSILON)) { 15784ff8c8bSHong Zhang star.h = h; 15884ff8c8bSHong Zhang star.u = L.u - fl; 15984ff8c8bSHong Zhang goto converged; 16084ff8c8bSHong Zhang } else if (i > 0 && PetscAbsScalar(res) >= PetscAbsScalar(res0)) { /* Line search */ 16184ff8c8bSHong Zhang h = 0.8 * h0 + 0.2 * h; 16284ff8c8bSHong Zhang continue; 16384ff8c8bSHong Zhang } 16484ff8c8bSHong Zhang /* Accept the last step and take another */ 16584ff8c8bSHong Zhang res0 = res; 16684ff8c8bSHong Zhang h0 = h; 16784ff8c8bSHong Zhang dfl = (L.h < h) ? 0.5 / fl * 0.5 * g * (-L.h * L.h / (h * h) - 1 + 2 * h / L.h) : PetscSqrtScalar(g / h); 16884ff8c8bSHong Zhang dfr = (R.h < h) ? 0.5 / fr * 0.5 * g * (-R.h * R.h / (h * h) - 1 + 2 * h / R.h) : PetscSqrtScalar(g / h); 16984ff8c8bSHong Zhang tmp = h - res / (dfr + dfl); 17084ff8c8bSHong Zhang if (tmp <= 0) h /= 2; /* Guard against Newton shooting off to a negative thickness */ 17184ff8c8bSHong Zhang else h = tmp; 1723c633725SBarry Smith PetscCheck(((h > 0) && PetscIsNormalScalar(h)), PETSC_COMM_SELF, PETSC_ERR_FP, "non-normal iterate h=%g", (double)h); 17384ff8c8bSHong Zhang } 17463a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, 1, "Newton iteration for star.h diverged after %" PetscInt_FMT " iterations", i); 17584ff8c8bSHong Zhang } 17684ff8c8bSHong Zhang converged: 17784ff8c8bSHong Zhang cstar = PetscSqrtScalar(g * star.h); 17884ff8c8bSHong Zhang if (L.u - cL < 0 && 0 < star.u - cstar) { /* 1-wave is sonic rarefaction */ 17984ff8c8bSHong Zhang PetscScalar ufan[2]; 18084ff8c8bSHong Zhang ufan[0] = 1 / g * PetscSqr(L.u / 3 + 2. / 3 * cL); 18184ff8c8bSHong Zhang ufan[1] = PetscSqrtScalar(g * ufan[0]) * ufan[0]; 18284ff8c8bSHong Zhang ShallowFlux(phys, ufan, flux); 18384ff8c8bSHong Zhang } else if (star.u + cstar < 0 && 0 < R.u + cR) { /* 2-wave is sonic rarefaction */ 18484ff8c8bSHong Zhang PetscScalar ufan[2]; 18584ff8c8bSHong Zhang ufan[0] = 1 / g * PetscSqr(R.u / 3 - 2. / 3 * cR); 18684ff8c8bSHong Zhang ufan[1] = -PetscSqrtScalar(g * ufan[0]) * ufan[0]; 18784ff8c8bSHong Zhang ShallowFlux(phys, ufan, flux); 18884ff8c8bSHong Zhang } else if ((L.h >= star.h && L.u - c >= 0) || (L.h < star.h && (star.h * star.u - L.h * L.u) / (star.h - L.h) > 0)) { 18984ff8c8bSHong Zhang /* 1-wave is right-travelling shock (supersonic) */ 19084ff8c8bSHong Zhang ShallowFlux(phys, uL, flux); 19184ff8c8bSHong Zhang } else if ((star.h <= R.h && R.u + c <= 0) || (star.h > R.h && (R.h * R.u - star.h * star.h) / (R.h - star.h) < 0)) { 19284ff8c8bSHong Zhang /* 2-wave is left-travelling shock (supersonic) */ 19384ff8c8bSHong Zhang ShallowFlux(phys, uR, flux); 19484ff8c8bSHong Zhang } else { 19584ff8c8bSHong Zhang ustar[0] = star.h; 19684ff8c8bSHong Zhang ustar[1] = star.h * star.u; 19784ff8c8bSHong Zhang ShallowFlux(phys, ustar, flux); 19884ff8c8bSHong Zhang } 19984ff8c8bSHong Zhang *maxspeed = MaxAbs(MaxAbs(star.u - cstar, star.u + cstar), MaxAbs(L.u - cL, R.u + cR)); 20084ff8c8bSHong Zhang PetscFunctionReturn(0); 20184ff8c8bSHong Zhang } 20284ff8c8bSHong Zhang 2039371c9d4SSatish Balay static PetscErrorCode PhysicsRiemann_Shallow_Rusanov(void *vctx, PetscInt m, const PetscScalar *uL, const PetscScalar *uR, PetscScalar *flux, PetscReal *maxspeed) { 20484ff8c8bSHong Zhang ShallowCtx *phys = (ShallowCtx *)vctx; 20584ff8c8bSHong Zhang PetscScalar g = phys->gravity, fL[2], fR[2], s; 2069371c9d4SSatish Balay struct { 2079371c9d4SSatish Balay PetscScalar h, u; 2089371c9d4SSatish Balay } L = {uL[0], uL[1] / uL[0]}, R = {uR[0], uR[1] / uR[0]}; 20984ff8c8bSHong Zhang PetscReal tol = 1e-6; 21084ff8c8bSHong Zhang 21184ff8c8bSHong Zhang PetscFunctionBeginUser; 21284ff8c8bSHong Zhang /* Positivity preserving modification*/ 21384ff8c8bSHong Zhang if (L.h < tol) L.u = 0.0; 21484ff8c8bSHong Zhang if (R.h < tol) R.u = 0.0; 21584ff8c8bSHong Zhang 21684ff8c8bSHong Zhang /*simple pos preserve limiter*/ 21784ff8c8bSHong Zhang if (L.h < 0) L.h = 0; 21884ff8c8bSHong Zhang if (R.h < 0) R.h = 0; 21984ff8c8bSHong Zhang 22084ff8c8bSHong Zhang ShallowFlux(phys, uL, fL); 22184ff8c8bSHong Zhang ShallowFlux(phys, uR, fR); 22284ff8c8bSHong Zhang 22384ff8c8bSHong Zhang s = PetscMax(PetscAbs(L.u) + PetscSqrtScalar(g * L.h), PetscAbs(R.u) + PetscSqrtScalar(g * R.h)); 22484ff8c8bSHong Zhang flux[0] = 0.5 * (fL[0] + fR[0]) + 0.5 * s * (L.h - R.h); 22584ff8c8bSHong Zhang flux[1] = 0.5 * (fL[1] + fR[1]) + 0.5 * s * (uL[1] - uR[1]); 22684ff8c8bSHong Zhang *maxspeed = s; 22784ff8c8bSHong Zhang PetscFunctionReturn(0); 22884ff8c8bSHong Zhang } 22984ff8c8bSHong Zhang 2309371c9d4SSatish Balay static PetscErrorCode PhysicsCharacteristic_Conservative(void *vctx, PetscInt m, const PetscScalar *u, PetscScalar *X, PetscScalar *Xi, PetscReal *speeds) { 23184ff8c8bSHong Zhang PetscInt i, j; 23284ff8c8bSHong Zhang 23384ff8c8bSHong Zhang PetscFunctionBeginUser; 23484ff8c8bSHong Zhang for (i = 0; i < m; i++) { 23584ff8c8bSHong Zhang for (j = 0; j < m; j++) Xi[i * m + j] = X[i * m + j] = (PetscScalar)(i == j); 23684ff8c8bSHong Zhang speeds[i] = PETSC_MAX_REAL; /* Indicates invalid */ 23784ff8c8bSHong Zhang } 23884ff8c8bSHong Zhang PetscFunctionReturn(0); 23984ff8c8bSHong Zhang } 24084ff8c8bSHong Zhang 2419371c9d4SSatish Balay static PetscErrorCode PhysicsCharacteristic_Shallow(void *vctx, PetscInt m, const PetscScalar *u, PetscScalar *X, PetscScalar *Xi, PetscReal *speeds) { 24284ff8c8bSHong Zhang ShallowCtx *phys = (ShallowCtx *)vctx; 24384ff8c8bSHong Zhang PetscReal c; 24484ff8c8bSHong Zhang PetscReal tol = 1e-6; 24584ff8c8bSHong Zhang 24684ff8c8bSHong Zhang PetscFunctionBeginUser; 24784ff8c8bSHong Zhang c = PetscSqrtScalar(u[0] * phys->gravity); 24884ff8c8bSHong Zhang 24984ff8c8bSHong Zhang if (u[0] < tol) { /*Use conservative variables*/ 25084ff8c8bSHong Zhang X[0 * 2 + 0] = 1; 25184ff8c8bSHong Zhang X[0 * 2 + 1] = 0; 25284ff8c8bSHong Zhang X[1 * 2 + 0] = 0; 25384ff8c8bSHong Zhang X[1 * 2 + 1] = 1; 25484ff8c8bSHong Zhang } else { 25584ff8c8bSHong Zhang speeds[0] = u[1] / u[0] - c; 25684ff8c8bSHong Zhang speeds[1] = u[1] / u[0] + c; 25784ff8c8bSHong Zhang X[0 * 2 + 0] = 1; 25884ff8c8bSHong Zhang X[0 * 2 + 1] = speeds[0]; 25984ff8c8bSHong Zhang X[1 * 2 + 0] = 1; 26084ff8c8bSHong Zhang X[1 * 2 + 1] = speeds[1]; 26184ff8c8bSHong Zhang } 26284ff8c8bSHong Zhang 2639566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(Xi, X, 4)); 2649566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_2(Xi, 0, PETSC_FALSE, NULL)); 26584ff8c8bSHong Zhang PetscFunctionReturn(0); 26684ff8c8bSHong Zhang } 26784ff8c8bSHong Zhang 2689371c9d4SSatish Balay static PetscErrorCode PhysicsSample_Shallow(void *vctx, PetscInt initial, FVBCType bctype, PetscReal xmin, PetscReal xmax, PetscReal t, PetscReal x, PetscReal *u) { 26984ff8c8bSHong Zhang PetscFunctionBeginUser; 27008401ef6SPierre Jolivet PetscCheck(t <= 0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Exact solutions not implemented for t > 0"); 27184ff8c8bSHong Zhang switch (initial) { 27284ff8c8bSHong Zhang case 0: 27384ff8c8bSHong Zhang u[0] = (x < 0) ? 2 : 1; /* Standard Dam Break Problem */ 27484ff8c8bSHong Zhang u[1] = (x < 0) ? 0 : 0; 27584ff8c8bSHong Zhang break; 27684ff8c8bSHong Zhang case 1: 27784ff8c8bSHong Zhang u[0] = (x < 10) ? 1 : 0.1; /*The Next 5 problems are standard Riemann problem tests */ 27884ff8c8bSHong Zhang u[1] = (x < 10) ? 2.5 : 0; 27984ff8c8bSHong Zhang break; 28084ff8c8bSHong Zhang case 2: 28184ff8c8bSHong Zhang u[0] = (x < 25) ? 1 : 1; 28284ff8c8bSHong Zhang u[1] = (x < 25) ? -5 : 5; 28384ff8c8bSHong Zhang break; 28484ff8c8bSHong Zhang case 3: 28584ff8c8bSHong Zhang u[0] = (x < 20) ? 1 : 1e-12; 28684ff8c8bSHong Zhang u[1] = (x < 20) ? 0 : 0; 28784ff8c8bSHong Zhang break; 28884ff8c8bSHong Zhang case 4: 28984ff8c8bSHong Zhang u[0] = (x < 30) ? 1e-12 : 1; 29084ff8c8bSHong Zhang u[1] = (x < 30) ? 0 : 0; 29184ff8c8bSHong Zhang break; 29284ff8c8bSHong Zhang case 5: 29384ff8c8bSHong Zhang u[0] = (x < 25) ? 0.1 : 0.1; 29484ff8c8bSHong Zhang u[1] = (x < 25) ? -0.3 : 0.3; 29584ff8c8bSHong Zhang break; 29684ff8c8bSHong Zhang case 6: 29784ff8c8bSHong Zhang u[0] = 1 + 0.5 * PetscSinReal(2 * PETSC_PI * x); 29884ff8c8bSHong Zhang u[1] = 1 * u[0]; 29984ff8c8bSHong Zhang break; 30084ff8c8bSHong Zhang case 7: 30184ff8c8bSHong Zhang if (x < -0.1) { 30284ff8c8bSHong Zhang u[0] = 1e-9; 30384ff8c8bSHong Zhang u[1] = 0.0; 30484ff8c8bSHong Zhang } else if (x < 0.1) { 30584ff8c8bSHong Zhang u[0] = 1.0; 30684ff8c8bSHong Zhang u[1] = 0.0; 30784ff8c8bSHong Zhang } else { 30884ff8c8bSHong Zhang u[0] = 1e-9; 30984ff8c8bSHong Zhang u[1] = 0.0; 31084ff8c8bSHong Zhang } 31184ff8c8bSHong Zhang break; 31284ff8c8bSHong Zhang case 8: 31384ff8c8bSHong Zhang if (x < -0.1) { 31484ff8c8bSHong Zhang u[0] = 2; 31584ff8c8bSHong Zhang u[1] = 0.0; 31684ff8c8bSHong Zhang } else if (x < 0.1) { 31784ff8c8bSHong Zhang u[0] = 3.0; 31884ff8c8bSHong Zhang u[1] = 0.0; 31984ff8c8bSHong Zhang } else { 32084ff8c8bSHong Zhang u[0] = 2; 32184ff8c8bSHong Zhang u[1] = 0.0; 32284ff8c8bSHong Zhang } 32384ff8c8bSHong Zhang break; 32484ff8c8bSHong Zhang default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "unknown initial condition"); 32584ff8c8bSHong Zhang } 32684ff8c8bSHong Zhang PetscFunctionReturn(0); 32784ff8c8bSHong Zhang } 32884ff8c8bSHong Zhang 32984ff8c8bSHong Zhang /* Implements inflow conditions for the given initial conditions. Which conditions are actually enforced depends on 33084ff8c8bSHong Zhang on the results of PhysicsSetInflowType_Shallow. */ 3319371c9d4SSatish Balay static PetscErrorCode PhysicsInflow_Shallow(void *vctx, PetscReal t, PetscReal x, PetscReal *u) { 33284ff8c8bSHong Zhang FVCtx *ctx = (FVCtx *)vctx; 33384ff8c8bSHong Zhang 33484ff8c8bSHong Zhang PetscFunctionBeginUser; 33584ff8c8bSHong Zhang if (ctx->bctype == FVBC_INFLOW) { 33684ff8c8bSHong Zhang switch (ctx->initial) { 33784ff8c8bSHong Zhang case 0: 33884ff8c8bSHong Zhang case 1: 33984ff8c8bSHong Zhang case 2: 34084ff8c8bSHong Zhang case 3: 34184ff8c8bSHong Zhang case 4: 34284ff8c8bSHong Zhang case 5: 3439371c9d4SSatish Balay u[0] = 0; 3449371c9d4SSatish Balay u[1] = 0.0; /* Left boundary conditions */ 3459371c9d4SSatish Balay u[2] = 0; 3469371c9d4SSatish Balay u[3] = 0.0; /* Right boundary conditions */ 34784ff8c8bSHong Zhang break; 34884ff8c8bSHong Zhang case 6: 3499371c9d4SSatish Balay u[0] = 0; 3509371c9d4SSatish Balay u[1] = 0.0; /* Left boundary conditions */ 3519371c9d4SSatish Balay u[2] = 0; 3529371c9d4SSatish Balay u[3] = 0.0; /* Right boundary conditions */ 35384ff8c8bSHong Zhang break; 35484ff8c8bSHong Zhang case 7: 3559371c9d4SSatish Balay u[0] = 0; 3569371c9d4SSatish Balay u[1] = 0.0; /* Left boundary conditions */ 3579371c9d4SSatish Balay u[2] = 0; 3589371c9d4SSatish Balay u[3] = 0.0; /* Right boundary conditions */ 35984ff8c8bSHong Zhang break; 36084ff8c8bSHong Zhang case 8: 3619371c9d4SSatish Balay u[0] = 0; 3629371c9d4SSatish Balay u[1] = 1.0; /* Left boundary conditions */ 3639371c9d4SSatish Balay u[2] = 0; 3649371c9d4SSatish Balay u[3] = -1.0; /* Right boundary conditions */ 36584ff8c8bSHong Zhang break; 36684ff8c8bSHong Zhang default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "unknown initial condition"); 36784ff8c8bSHong Zhang } 36884ff8c8bSHong Zhang } 36984ff8c8bSHong Zhang PetscFunctionReturn(0); 37084ff8c8bSHong Zhang } 37184ff8c8bSHong Zhang 37284ff8c8bSHong Zhang /* Selects which boundary conditions are marked as inflow and which as outflow when FVBC_INFLOW is selected. */ 3739371c9d4SSatish Balay static PetscErrorCode PhysicsSetInflowType_Shallow(FVCtx *ctx) { 37484ff8c8bSHong Zhang PetscFunctionBeginUser; 37584ff8c8bSHong Zhang switch (ctx->initial) { 37684ff8c8bSHong Zhang case 0: 37784ff8c8bSHong Zhang case 1: 37884ff8c8bSHong Zhang case 2: 37984ff8c8bSHong Zhang case 3: 38084ff8c8bSHong Zhang case 4: 38184ff8c8bSHong Zhang case 5: 38284ff8c8bSHong Zhang case 6: 38384ff8c8bSHong Zhang case 7: 38484ff8c8bSHong Zhang case 8: /* Fix left and right momentum, height is outflow */ 38584ff8c8bSHong Zhang ctx->physics2.bcinflowindex[0] = PETSC_FALSE; 38684ff8c8bSHong Zhang ctx->physics2.bcinflowindex[1] = PETSC_TRUE; 38784ff8c8bSHong Zhang ctx->physics2.bcinflowindex[2] = PETSC_FALSE; 38884ff8c8bSHong Zhang ctx->physics2.bcinflowindex[3] = PETSC_TRUE; 38984ff8c8bSHong Zhang break; 39084ff8c8bSHong Zhang default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "unknown initial condition"); 39184ff8c8bSHong Zhang } 39284ff8c8bSHong Zhang PetscFunctionReturn(0); 39384ff8c8bSHong Zhang } 39484ff8c8bSHong Zhang 3959371c9d4SSatish Balay static PetscErrorCode PhysicsCreate_Shallow(FVCtx *ctx) { 39684ff8c8bSHong Zhang ShallowCtx *user; 39784ff8c8bSHong Zhang PetscFunctionList rlist = 0, rclist = 0; 39884ff8c8bSHong Zhang char rname[256] = "rusanov", rcname[256] = "characteristic"; 39984ff8c8bSHong Zhang 40084ff8c8bSHong Zhang PetscFunctionBeginUser; 4019566063dSJacob Faibussowitsch PetscCall(PetscNew(&user)); 40284ff8c8bSHong Zhang ctx->physics2.sample2 = PhysicsSample_Shallow; 40384ff8c8bSHong Zhang ctx->physics2.inflow = PhysicsInflow_Shallow; 40484ff8c8bSHong Zhang ctx->physics2.destroy = PhysicsDestroy_SimpleFree; 40584ff8c8bSHong Zhang ctx->physics2.riemann2 = PhysicsRiemann_Shallow_Rusanov; 40684ff8c8bSHong Zhang ctx->physics2.characteristic2 = PhysicsCharacteristic_Shallow; 40784ff8c8bSHong Zhang ctx->physics2.user = user; 40884ff8c8bSHong Zhang ctx->physics2.dof = 2; 40984ff8c8bSHong Zhang 41084ff8c8bSHong Zhang PetscMalloc1(2 * (ctx->physics2.dof), &ctx->physics2.bcinflowindex); 41184ff8c8bSHong Zhang PhysicsSetInflowType_Shallow(ctx); 41284ff8c8bSHong Zhang 4139566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("height", &ctx->physics2.fieldname[0])); 4149566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("momentum", &ctx->physics2.fieldname[1])); 41584ff8c8bSHong Zhang 41684ff8c8bSHong Zhang user->gravity = 9.81; 41784ff8c8bSHong Zhang 4189566063dSJacob Faibussowitsch PetscCall(RiemannListAdd_2WaySplit(&rlist, "exact", PhysicsRiemann_Shallow_Exact)); 4199566063dSJacob Faibussowitsch PetscCall(RiemannListAdd_2WaySplit(&rlist, "rusanov", PhysicsRiemann_Shallow_Rusanov)); 4209566063dSJacob Faibussowitsch PetscCall(ReconstructListAdd_2WaySplit(&rclist, "characteristic", PhysicsCharacteristic_Shallow)); 4219566063dSJacob Faibussowitsch PetscCall(ReconstructListAdd_2WaySplit(&rclist, "conservative", PhysicsCharacteristic_Conservative)); 422d0609cedSBarry Smith PetscOptionsBegin(ctx->comm, ctx->prefix, "Options for Shallow", ""); 4239566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-physics_shallow_gravity", "Gravity", "", user->gravity, &user->gravity, NULL)); 4249566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-physics_shallow_riemann", "Riemann solver", "", rlist, rname, rname, sizeof(rname), NULL)); 4259566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-physics_shallow_reconstruct", "Reconstruction", "", rclist, rcname, rcname, sizeof(rcname), NULL)); 426d0609cedSBarry Smith PetscOptionsEnd(); 4279566063dSJacob Faibussowitsch PetscCall(RiemannListFind_2WaySplit(rlist, rname, &ctx->physics2.riemann2)); 4289566063dSJacob Faibussowitsch PetscCall(ReconstructListFind_2WaySplit(rclist, rcname, &ctx->physics2.characteristic2)); 4299566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&rlist)); 4309566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&rclist)); 43184ff8c8bSHong Zhang PetscFunctionReturn(0); 43284ff8c8bSHong Zhang } 43384ff8c8bSHong Zhang 4349371c9d4SSatish Balay PetscErrorCode FVSample_2WaySplit(FVCtx *ctx, DM da, PetscReal time, Vec U) { 43584ff8c8bSHong Zhang PetscScalar *u, *uj, xj, xi; 43684ff8c8bSHong Zhang PetscInt i, j, k, dof, xs, xm, Mx; 43784ff8c8bSHong Zhang const PetscInt N = 200; 43884ff8c8bSHong Zhang PetscReal hs, hf; 43984ff8c8bSHong Zhang 44084ff8c8bSHong Zhang PetscFunctionBeginUser; 4413c633725SBarry Smith PetscCheck(ctx->physics2.sample2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Physics has not provided a sampling function"); 4429566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); 4439566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0)); 4449566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, U, &u)); 4459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dof, &uj)); 44684ff8c8bSHong Zhang hs = (ctx->xmax - ctx->xmin) * 3.0 / 8.0 / ctx->sf; 44784ff8c8bSHong Zhang hf = (ctx->xmax - ctx->xmin) / 4.0 / (ctx->fs - ctx->sf); 44884ff8c8bSHong Zhang for (i = xs; i < xs + xm; i++) { 44984ff8c8bSHong Zhang if (i < ctx->sf) { 45084ff8c8bSHong Zhang xi = ctx->xmin + 0.5 * hs + i * hs; 45184ff8c8bSHong Zhang /* Integrate over cell i using trapezoid rule with N points. */ 45284ff8c8bSHong Zhang for (k = 0; k < dof; k++) u[i * dof + k] = 0; 45384ff8c8bSHong Zhang for (j = 0; j < N + 1; j++) { 45484ff8c8bSHong Zhang xj = xi + hs * (j - N / 2) / (PetscReal)N; 4559566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.sample2)(ctx->physics2.user, ctx->initial, ctx->bctype, ctx->xmin, ctx->xmax, time, xj, uj)); 45684ff8c8bSHong Zhang for (k = 0; k < dof; k++) u[i * dof + k] += ((j == 0 || j == N) ? 0.5 : 1.0) * uj[k] / N; 45784ff8c8bSHong Zhang } 45884ff8c8bSHong Zhang } else if (i < ctx->fs) { 45984ff8c8bSHong Zhang xi = ctx->xmin + ctx->sf * hs + 0.5 * hf + (i - ctx->sf) * hf; 46084ff8c8bSHong Zhang /* Integrate over cell i using trapezoid rule with N points. */ 46184ff8c8bSHong Zhang for (k = 0; k < dof; k++) u[i * dof + k] = 0; 46284ff8c8bSHong Zhang for (j = 0; j < N + 1; j++) { 46384ff8c8bSHong Zhang xj = xi + hf * (j - N / 2) / (PetscReal)N; 4649566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.sample2)(ctx->physics2.user, ctx->initial, ctx->bctype, ctx->xmin, ctx->xmax, time, xj, uj)); 46584ff8c8bSHong Zhang for (k = 0; k < dof; k++) u[i * dof + k] += ((j == 0 || j == N) ? 0.5 : 1.0) * uj[k] / N; 46684ff8c8bSHong Zhang } 46784ff8c8bSHong Zhang } else { 46884ff8c8bSHong Zhang xi = ctx->xmin + ctx->sf * hs + (ctx->fs - ctx->sf) * hf + 0.5 * hs + (i - ctx->fs) * hs; 46984ff8c8bSHong Zhang /* Integrate over cell i using trapezoid rule with N points. */ 47084ff8c8bSHong Zhang for (k = 0; k < dof; k++) u[i * dof + k] = 0; 47184ff8c8bSHong Zhang for (j = 0; j < N + 1; j++) { 47284ff8c8bSHong Zhang xj = xi + hs * (j - N / 2) / (PetscReal)N; 4739566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.sample2)(ctx->physics2.user, ctx->initial, ctx->bctype, ctx->xmin, ctx->xmax, time, xj, uj)); 47484ff8c8bSHong Zhang for (k = 0; k < dof; k++) u[i * dof + k] += ((j == 0 || j == N) ? 0.5 : 1.0) * uj[k] / N; 47584ff8c8bSHong Zhang } 47684ff8c8bSHong Zhang } 47784ff8c8bSHong Zhang } 4789566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, U, &u)); 4799566063dSJacob Faibussowitsch PetscCall(PetscFree(uj)); 48084ff8c8bSHong Zhang PetscFunctionReturn(0); 48184ff8c8bSHong Zhang } 48284ff8c8bSHong Zhang 4839371c9d4SSatish Balay static PetscErrorCode SolutionErrorNorms_2WaySplit(FVCtx *ctx, DM da, PetscReal t, Vec X, PetscReal *nrm1) { 48484ff8c8bSHong Zhang Vec Y; 48584ff8c8bSHong Zhang PetscInt i, Mx; 48684ff8c8bSHong Zhang const PetscScalar *ptr_X, *ptr_Y; 48784ff8c8bSHong Zhang PetscReal hs, hf; 48884ff8c8bSHong Zhang 48984ff8c8bSHong Zhang PetscFunctionBeginUser; 4909566063dSJacob Faibussowitsch PetscCall(VecGetSize(X, &Mx)); 4919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &Y)); 4929566063dSJacob Faibussowitsch PetscCall(FVSample_2WaySplit(ctx, da, t, Y)); 49384ff8c8bSHong Zhang hs = (ctx->xmax - ctx->xmin) * 3.0 / 8.0 / ctx->sf; 49484ff8c8bSHong Zhang hf = (ctx->xmax - ctx->xmin) / 4.0 / (ctx->fs - ctx->sf); 4959566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, &ptr_X)); 4969566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Y, &ptr_Y)); 49784ff8c8bSHong Zhang for (i = 0; i < Mx; i++) { 49884ff8c8bSHong Zhang if (i < ctx->sf || i > ctx->fs - 1) *nrm1 += hs * PetscAbs(ptr_X[i] - ptr_Y[i]); 49984ff8c8bSHong Zhang else *nrm1 += hf * PetscAbs(ptr_X[i] - ptr_Y[i]); 50084ff8c8bSHong Zhang } 5019566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, &ptr_X)); 5029566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Y, &ptr_Y)); 5039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Y)); 50484ff8c8bSHong Zhang PetscFunctionReturn(0); 50584ff8c8bSHong Zhang } 50684ff8c8bSHong Zhang 5079371c9d4SSatish Balay PetscErrorCode FVRHSFunction_2WaySplit(TS ts, PetscReal time, Vec X, Vec F, void *vctx) { 50884ff8c8bSHong Zhang FVCtx *ctx = (FVCtx *)vctx; 50984ff8c8bSHong Zhang PetscInt i, j, k, Mx, dof, xs, xm, sf = ctx->sf, fs = ctx->fs; 51084ff8c8bSHong Zhang PetscReal hxf, hxs, cfl_idt = 0; 51184ff8c8bSHong Zhang PetscScalar *x, *f, *slope; 51284ff8c8bSHong Zhang Vec Xloc; 51384ff8c8bSHong Zhang DM da; 51484ff8c8bSHong Zhang 51584ff8c8bSHong Zhang PetscFunctionBeginUser; 5169566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da)); 5179566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da, &Xloc)); /* Xloc contains ghost points */ 5189566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); /* Mx is the number of center points */ 51984ff8c8bSHong Zhang hxs = (ctx->xmax - ctx->xmin) * 3.0 / 8.0 / ctx->sf; 52084ff8c8bSHong Zhang hxf = (ctx->xmax - ctx->xmin) / 4.0 / (ctx->fs - ctx->sf); 5219566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc)); /* X is solution vector which does not contain ghost points */ 5229566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc)); 52384ff8c8bSHong Zhang 5249566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(F)); /* F is the right hand side function corresponds to center points */ 52584ff8c8bSHong Zhang 5269566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, Xloc, &x)); 5279566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, F, &f)); 5289566063dSJacob Faibussowitsch PetscCall(DMDAGetArray(da, PETSC_TRUE, &slope)); /* contains ghost points */ 5299566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0)); 53084ff8c8bSHong Zhang 53184ff8c8bSHong Zhang if (ctx->bctype == FVBC_OUTFLOW) { 53284ff8c8bSHong Zhang for (i = xs - 2; i < 0; i++) { 53384ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[j]; 53484ff8c8bSHong Zhang } 53584ff8c8bSHong Zhang for (i = Mx; i < xs + xm + 2; i++) { 53684ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[(xs + xm - 1) * dof + j]; 53784ff8c8bSHong Zhang } 53884ff8c8bSHong Zhang } 53984ff8c8bSHong Zhang 54084ff8c8bSHong Zhang if (ctx->bctype == FVBC_INFLOW) { 54184ff8c8bSHong Zhang /* See LeVeque, R. (2002). Finite Volume Methods for Hyperbolic Problems. doi:10.1017/CBO9780511791253 54284ff8c8bSHong Zhang pages 137-138 for the scheme. */ 54384ff8c8bSHong Zhang if (xs == 0) { /* Left Boundary */ 54484ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmin, ctx->ub); 54584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 54684ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[j]) { 54784ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = 2.0 * ctx->ub[j] - x[-(i + 1) * dof + j]; 54884ff8c8bSHong Zhang } else { 54984ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = x[j]; /* Outflow */ 55084ff8c8bSHong Zhang } 55184ff8c8bSHong Zhang } 55284ff8c8bSHong Zhang } 55384ff8c8bSHong Zhang if (xs + xm == Mx) { /* Right Boundary */ 55484ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmax, ctx->ub); 55584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 55684ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[dof + j]) { 55784ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = 2.0 * ctx->ub[dof + j] - x[(2 * Mx - (i + 1)) * dof + j]; 55884ff8c8bSHong Zhang } else { 55984ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = x[(Mx - 1) * dof + j]; /* Outflow */ 56084ff8c8bSHong Zhang } 56184ff8c8bSHong Zhang } 56284ff8c8bSHong Zhang } 56384ff8c8bSHong Zhang } 56484ff8c8bSHong Zhang 56584ff8c8bSHong Zhang for (i = xs - 1; i < xs + xm + 1; i++) { 56684ff8c8bSHong Zhang struct _LimitInfo info; 56784ff8c8bSHong Zhang PetscScalar *cjmpL, *cjmpR; 56884ff8c8bSHong Zhang /* Determine the right eigenvectors R, where A = R \Lambda R^{-1} */ 5699566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.characteristic2)(ctx->physics2.user, dof, &x[i * dof], ctx->R, ctx->Rinv, ctx->speeds)); 57084ff8c8bSHong Zhang /* Evaluate jumps across interfaces (i-1, i) and (i, i+1), put in characteristic basis */ 5719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ctx->cjmpLR, 2 * dof)); 57284ff8c8bSHong Zhang cjmpL = &ctx->cjmpLR[0]; 57384ff8c8bSHong Zhang cjmpR = &ctx->cjmpLR[dof]; 57484ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 57584ff8c8bSHong Zhang PetscScalar jmpL, jmpR; 57684ff8c8bSHong Zhang jmpL = x[(i + 0) * dof + j] - x[(i - 1) * dof + j]; 57784ff8c8bSHong Zhang jmpR = x[(i + 1) * dof + j] - x[(i + 0) * dof + j]; 57884ff8c8bSHong Zhang for (k = 0; k < dof; k++) { 57984ff8c8bSHong Zhang cjmpL[k] += ctx->Rinv[k + j * dof] * jmpL; 58084ff8c8bSHong Zhang cjmpR[k] += ctx->Rinv[k + j * dof] * jmpR; 58184ff8c8bSHong Zhang } 58284ff8c8bSHong Zhang } 58384ff8c8bSHong Zhang /* Apply limiter to the left and right characteristic jumps */ 58484ff8c8bSHong Zhang info.m = dof; 58584ff8c8bSHong Zhang info.hxs = hxs; 58684ff8c8bSHong Zhang info.hxf = hxf; 58784ff8c8bSHong Zhang (*ctx->limit2)(&info, cjmpL, cjmpR, ctx->sf, ctx->fs, i, ctx->cslope); 58884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 58984ff8c8bSHong Zhang PetscScalar tmp = 0; 59084ff8c8bSHong Zhang for (k = 0; k < dof; k++) tmp += ctx->R[j + k * dof] * ctx->cslope[k]; 59184ff8c8bSHong Zhang slope[i * dof + j] = tmp; 59284ff8c8bSHong Zhang } 59384ff8c8bSHong Zhang } 59484ff8c8bSHong Zhang 59584ff8c8bSHong Zhang for (i = xs; i < xs + xm + 1; i++) { 59684ff8c8bSHong Zhang PetscReal maxspeed; 59784ff8c8bSHong Zhang PetscScalar *uL, *uR; 59884ff8c8bSHong Zhang uL = &ctx->uLR[0]; 59984ff8c8bSHong Zhang uR = &ctx->uLR[dof]; 60084ff8c8bSHong Zhang if (i < sf) { /* slow region */ 60184ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 60284ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 60384ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 60484ff8c8bSHong Zhang } 6059566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 60684ff8c8bSHong Zhang if (i > xs) { 60784ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(i - 1) * dof + j] -= ctx->flux[j] / hxs; 60884ff8c8bSHong Zhang } 60984ff8c8bSHong Zhang if (i < xs + xm) { 61084ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[i * dof + j] += ctx->flux[j] / hxs; 61184ff8c8bSHong Zhang } 61284ff8c8bSHong Zhang } else if (i == sf) { /* interface between the slow region and the fast region */ 61384ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 61484ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 61584ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxf / 2; 61684ff8c8bSHong Zhang } 6179566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 61884ff8c8bSHong Zhang if (i > xs) { 61984ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(i - 1) * dof + j] -= ctx->flux[j] / hxs; 62084ff8c8bSHong Zhang } 62184ff8c8bSHong Zhang if (i < xs + xm) { 62284ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[i * dof + j] += ctx->flux[j] / hxf; 62384ff8c8bSHong Zhang } 62484ff8c8bSHong Zhang } else if (i > sf && i < fs) { /* fast region */ 62584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 62684ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxf / 2; 62784ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxf / 2; 62884ff8c8bSHong Zhang } 6299566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 63084ff8c8bSHong Zhang if (i > xs) { 63184ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(i - 1) * dof + j] -= ctx->flux[j] / hxf; 63284ff8c8bSHong Zhang } 63384ff8c8bSHong Zhang if (i < xs + xm) { 63484ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[i * dof + j] += ctx->flux[j] / hxf; 63584ff8c8bSHong Zhang } 63684ff8c8bSHong Zhang } else if (i == fs) { /* interface between the fast region and the slow region */ 63784ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 63884ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxf / 2; 63984ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 64084ff8c8bSHong Zhang } 6419566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 64284ff8c8bSHong Zhang if (i > xs) { 64384ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(i - 1) * dof + j] -= ctx->flux[j] / hxf; 64484ff8c8bSHong Zhang } 64584ff8c8bSHong Zhang if (i < xs + xm) { 64684ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[i * dof + j] += ctx->flux[j] / hxs; 64784ff8c8bSHong Zhang } 64884ff8c8bSHong Zhang } else { /* slow region */ 64984ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 65084ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 65184ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 65284ff8c8bSHong Zhang } 6539566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 65484ff8c8bSHong Zhang cfl_idt = PetscMax(cfl_idt, PetscAbsScalar(maxspeed / hxs)); /* Max allowable value of 1/Delta t */ 65584ff8c8bSHong Zhang if (i > xs) { 65684ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(i - 1) * dof + j] -= ctx->flux[j] / hxs; 65784ff8c8bSHong Zhang } 65884ff8c8bSHong Zhang if (i < xs + xm) { 65984ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[i * dof + j] += ctx->flux[j] / hxs; 66084ff8c8bSHong Zhang } 66184ff8c8bSHong Zhang } 66284ff8c8bSHong Zhang } 6639566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, Xloc, &x)); 6649566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, F, &f)); 6659566063dSJacob Faibussowitsch PetscCall(DMDARestoreArray(da, PETSC_TRUE, &slope)); 6669566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da, &Xloc)); 6679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&cfl_idt, &ctx->cfl_idt, 1, MPIU_SCALAR, MPIU_MAX, PetscObjectComm((PetscObject)da))); 66884ff8c8bSHong Zhang if (0) { 66984ff8c8bSHong Zhang /* We need to a way to inform the TS of a CFL constraint, this is a debugging fragment */ 67084ff8c8bSHong Zhang PetscReal dt, tnow; 6719566063dSJacob Faibussowitsch PetscCall(TSGetTimeStep(ts, &dt)); 6729566063dSJacob Faibussowitsch PetscCall(TSGetTime(ts, &tnow)); 67384ff8c8bSHong Zhang if (dt > 0.5 / ctx->cfl_idt) { 67484ff8c8bSHong Zhang if (1) { 6759566063dSJacob Faibussowitsch PetscCall(PetscPrintf(ctx->comm, "Stability constraint exceeded at t=%g, dt %g > %g\n", (double)tnow, (double)dt, (double)(0.5 / ctx->cfl_idt))); 67698921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, 1, "Stability constraint exceeded, %g > %g", (double)dt, (double)(ctx->cfl / ctx->cfl_idt)); 67784ff8c8bSHong Zhang } 67884ff8c8bSHong Zhang } 67984ff8c8bSHong Zhang PetscFunctionReturn(0); 68084ff8c8bSHong Zhang } 68184ff8c8bSHong Zhang 68284ff8c8bSHong Zhang /* --------------------------------- Finite Volume Solver for slow components ----------------------------------- */ 6839371c9d4SSatish Balay PetscErrorCode FVRHSFunctionslow_2WaySplit(TS ts, PetscReal time, Vec X, Vec F, void *vctx) { 68484ff8c8bSHong Zhang FVCtx *ctx = (FVCtx *)vctx; 68584ff8c8bSHong Zhang PetscInt i, j, k, Mx, dof, xs, xm, islow = 0, sf = ctx->sf, fs = ctx->fs, lsbwidth = ctx->lsbwidth, rsbwidth = ctx->rsbwidth; 68684ff8c8bSHong Zhang PetscReal hxs, hxf, cfl_idt = 0; 68784ff8c8bSHong Zhang PetscScalar *x, *f, *slope; 68884ff8c8bSHong Zhang Vec Xloc; 68984ff8c8bSHong Zhang DM da; 69084ff8c8bSHong Zhang 69184ff8c8bSHong Zhang PetscFunctionBeginUser; 6929566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da)); 6939566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da, &Xloc)); 6949566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); 69584ff8c8bSHong Zhang hxs = (ctx->xmax - ctx->xmin) * 3.0 / 8.0 / ctx->sf; 69684ff8c8bSHong Zhang hxf = (ctx->xmax - ctx->xmin) / 4.0 / (ctx->fs - ctx->sf); 6979566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc)); 6989566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc)); 6999566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(F)); 7009566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, Xloc, &x)); 7019566063dSJacob Faibussowitsch PetscCall(VecGetArray(F, &f)); 7029566063dSJacob Faibussowitsch PetscCall(DMDAGetArray(da, PETSC_TRUE, &slope)); 7039566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0)); 70484ff8c8bSHong Zhang 70584ff8c8bSHong Zhang if (ctx->bctype == FVBC_OUTFLOW) { 70684ff8c8bSHong Zhang for (i = xs - 2; i < 0; i++) { 70784ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[j]; 70884ff8c8bSHong Zhang } 70984ff8c8bSHong Zhang for (i = Mx; i < xs + xm + 2; i++) { 71084ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[(xs + xm - 1) * dof + j]; 71184ff8c8bSHong Zhang } 71284ff8c8bSHong Zhang } 71384ff8c8bSHong Zhang if (ctx->bctype == FVBC_INFLOW) { 71484ff8c8bSHong Zhang /* See LeVeque, R. (2002). Finite Volume Methods for Hyperbolic Problems. doi:10.1017/CBO9780511791253 71584ff8c8bSHong Zhang pages 137-138 for the scheme. */ 71684ff8c8bSHong Zhang if (xs == 0) { /* Left Boundary */ 71784ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmin, ctx->ub); 71884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 71984ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[j] == PETSC_TRUE) { 72084ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = 2.0 * ctx->ub[j] - x[-(i + 1) * dof + j]; 72184ff8c8bSHong Zhang } else { 72284ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = x[j]; /* Outflow */ 72384ff8c8bSHong Zhang } 72484ff8c8bSHong Zhang } 72584ff8c8bSHong Zhang } 72684ff8c8bSHong Zhang if (xs + xm == Mx) { /* Right Boundary */ 72784ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmax, ctx->ub); 72884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 72984ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[dof + j] == PETSC_TRUE) { 73084ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = 2.0 * ctx->ub[dof + j] - x[(2 * Mx - (i + 1)) * dof + j]; 73184ff8c8bSHong Zhang } else { 73284ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = x[(Mx - 1) * dof + j]; /* Outflow */ 73384ff8c8bSHong Zhang } 73484ff8c8bSHong Zhang } 73584ff8c8bSHong Zhang } 73684ff8c8bSHong Zhang } 73784ff8c8bSHong Zhang for (i = xs - 1; i < xs + xm + 1; i++) { 73884ff8c8bSHong Zhang struct _LimitInfo info; 73984ff8c8bSHong Zhang PetscScalar *cjmpL, *cjmpR; 74084ff8c8bSHong Zhang if (i < sf - lsbwidth + 1 || i > fs + rsbwidth - 2) { /* slow components and the first and last fast components */ 74184ff8c8bSHong Zhang /* Determine the right eigenvectors R, where A = R \Lambda R^{-1} */ 7429566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.characteristic2)(ctx->physics2.user, dof, &x[i * dof], ctx->R, ctx->Rinv, ctx->speeds)); 74384ff8c8bSHong Zhang /* Evaluate jumps across interfaces (i-1, i) and (i, i+1), put in characteristic basis */ 7449566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ctx->cjmpLR, 2 * dof)); 74584ff8c8bSHong Zhang cjmpL = &ctx->cjmpLR[0]; 74684ff8c8bSHong Zhang cjmpR = &ctx->cjmpLR[dof]; 74784ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 74884ff8c8bSHong Zhang PetscScalar jmpL, jmpR; 74984ff8c8bSHong Zhang jmpL = x[(i + 0) * dof + j] - x[(i - 1) * dof + j]; 75084ff8c8bSHong Zhang jmpR = x[(i + 1) * dof + j] - x[(i + 0) * dof + j]; 75184ff8c8bSHong Zhang for (k = 0; k < dof; k++) { 75284ff8c8bSHong Zhang cjmpL[k] += ctx->Rinv[k + j * dof] * jmpL; 75384ff8c8bSHong Zhang cjmpR[k] += ctx->Rinv[k + j * dof] * jmpR; 75484ff8c8bSHong Zhang } 75584ff8c8bSHong Zhang } 75684ff8c8bSHong Zhang /* Apply limiter to the left and right characteristic jumps */ 75784ff8c8bSHong Zhang info.m = dof; 75884ff8c8bSHong Zhang info.hxs = hxs; 75984ff8c8bSHong Zhang info.hxf = hxf; 76084ff8c8bSHong Zhang (*ctx->limit2)(&info, cjmpL, cjmpR, ctx->sf, ctx->fs, i, ctx->cslope); 76184ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 76284ff8c8bSHong Zhang PetscScalar tmp = 0; 76384ff8c8bSHong Zhang for (k = 0; k < dof; k++) tmp += ctx->R[j + k * dof] * ctx->cslope[k]; 76484ff8c8bSHong Zhang slope[i * dof + j] = tmp; 76584ff8c8bSHong Zhang } 76684ff8c8bSHong Zhang } 76784ff8c8bSHong Zhang } 76884ff8c8bSHong Zhang 76984ff8c8bSHong Zhang for (i = xs; i < xs + xm + 1; i++) { 77084ff8c8bSHong Zhang PetscReal maxspeed; 77184ff8c8bSHong Zhang PetscScalar *uL, *uR; 77284ff8c8bSHong Zhang uL = &ctx->uLR[0]; 77384ff8c8bSHong Zhang uR = &ctx->uLR[dof]; 77484ff8c8bSHong Zhang if (i < sf - lsbwidth) { /* slow region */ 77584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 77684ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 77784ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 77884ff8c8bSHong Zhang } 7799566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 78084ff8c8bSHong Zhang cfl_idt = PetscMax(cfl_idt, PetscAbsScalar(maxspeed / hxs)); /* Max allowable value of 1/Delta t */ 78184ff8c8bSHong Zhang if (i > xs) { 78284ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 78384ff8c8bSHong Zhang } 78484ff8c8bSHong Zhang if (i < xs + xm) { 78584ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 78684ff8c8bSHong Zhang islow++; 78784ff8c8bSHong Zhang } 78884ff8c8bSHong Zhang } 78984ff8c8bSHong Zhang if (i == sf - lsbwidth) { /* interface between the slow region and the fast region */ 79084ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 79184ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 79284ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 79384ff8c8bSHong Zhang } 7949566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 79584ff8c8bSHong Zhang if (i > xs) { 79684ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 79784ff8c8bSHong Zhang } 79884ff8c8bSHong Zhang } 79984ff8c8bSHong Zhang if (i == fs + rsbwidth) { /* slow region */ 80084ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 80184ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 80284ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 80384ff8c8bSHong Zhang } 8049566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 80584ff8c8bSHong Zhang if (i < xs + xm) { 80684ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 80784ff8c8bSHong Zhang islow++; 80884ff8c8bSHong Zhang } 80984ff8c8bSHong Zhang } 81084ff8c8bSHong Zhang if (i > fs + rsbwidth) { /* slow region */ 81184ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 81284ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 81384ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 81484ff8c8bSHong Zhang } 8159566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 81684ff8c8bSHong Zhang if (i > xs) { 81784ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 81884ff8c8bSHong Zhang } 81984ff8c8bSHong Zhang if (i < xs + xm) { 82084ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 82184ff8c8bSHong Zhang islow++; 82284ff8c8bSHong Zhang } 82384ff8c8bSHong Zhang } 82484ff8c8bSHong Zhang } 8259566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, Xloc, &x)); 8269566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(F, &f)); 8279566063dSJacob Faibussowitsch PetscCall(DMDARestoreArray(da, PETSC_TRUE, &slope)); 8289566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da, &Xloc)); 8299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&cfl_idt, &ctx->cfl_idt, 1, MPIU_SCALAR, MPIU_MAX, PetscObjectComm((PetscObject)da))); 83084ff8c8bSHong Zhang PetscFunctionReturn(0); 83184ff8c8bSHong Zhang } 83284ff8c8bSHong Zhang 8339371c9d4SSatish Balay PetscErrorCode FVRHSFunctionslowbuffer_2WaySplit(TS ts, PetscReal time, Vec X, Vec F, void *vctx) { 83484ff8c8bSHong Zhang FVCtx *ctx = (FVCtx *)vctx; 83584ff8c8bSHong Zhang PetscInt i, j, k, Mx, dof, xs, xm, islow = 0, sf = ctx->sf, fs = ctx->fs, lsbwidth = ctx->lsbwidth, rsbwidth = ctx->rsbwidth; 83684ff8c8bSHong Zhang PetscReal hxs, hxf; 83784ff8c8bSHong Zhang PetscScalar *x, *f, *slope; 83884ff8c8bSHong Zhang Vec Xloc; 83984ff8c8bSHong Zhang DM da; 84084ff8c8bSHong Zhang 84184ff8c8bSHong Zhang PetscFunctionBeginUser; 8429566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da)); 8439566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da, &Xloc)); 8449566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); 84584ff8c8bSHong Zhang hxs = (ctx->xmax - ctx->xmin) * 3.0 / 8.0 / ctx->sf; 84684ff8c8bSHong Zhang hxf = (ctx->xmax - ctx->xmin) / 4.0 / (ctx->fs - ctx->sf); 8479566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc)); 8489566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc)); 8499566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(F)); 8509566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, Xloc, &x)); 8519566063dSJacob Faibussowitsch PetscCall(VecGetArray(F, &f)); 8529566063dSJacob Faibussowitsch PetscCall(DMDAGetArray(da, PETSC_TRUE, &slope)); 8539566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0)); 85484ff8c8bSHong Zhang 85584ff8c8bSHong Zhang if (ctx->bctype == FVBC_OUTFLOW) { 85684ff8c8bSHong Zhang for (i = xs - 2; i < 0; i++) { 85784ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[j]; 85884ff8c8bSHong Zhang } 85984ff8c8bSHong Zhang for (i = Mx; i < xs + xm + 2; i++) { 86084ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[(xs + xm - 1) * dof + j]; 86184ff8c8bSHong Zhang } 86284ff8c8bSHong Zhang } 86384ff8c8bSHong Zhang if (ctx->bctype == FVBC_INFLOW) { 86484ff8c8bSHong Zhang /* See LeVeque, R. (2002). Finite Volume Methods for Hyperbolic Problems. doi:10.1017/CBO9780511791253 86584ff8c8bSHong Zhang pages 137-138 for the scheme. */ 86684ff8c8bSHong Zhang if (xs == 0) { /* Left Boundary */ 86784ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmin, ctx->ub); 86884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 86984ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[j] == PETSC_TRUE) { 87084ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = 2.0 * ctx->ub[j] - x[-(i + 1) * dof + j]; 87184ff8c8bSHong Zhang } else { 87284ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = x[j]; /* Outflow */ 87384ff8c8bSHong Zhang } 87484ff8c8bSHong Zhang } 87584ff8c8bSHong Zhang } 87684ff8c8bSHong Zhang if (xs + xm == Mx) { /* Right Boundary */ 87784ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmax, ctx->ub); 87884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 87984ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[dof + j] == PETSC_TRUE) { 88084ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = 2.0 * ctx->ub[dof + j] - x[(2 * Mx - (i + 1)) * dof + j]; 88184ff8c8bSHong Zhang } else { 88284ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = x[(Mx - 1) * dof + j]; /* Outflow */ 88384ff8c8bSHong Zhang } 88484ff8c8bSHong Zhang } 88584ff8c8bSHong Zhang } 88684ff8c8bSHong Zhang } 88784ff8c8bSHong Zhang for (i = xs - 1; i < xs + xm + 1; i++) { 88884ff8c8bSHong Zhang struct _LimitInfo info; 88984ff8c8bSHong Zhang PetscScalar *cjmpL, *cjmpR; 89084ff8c8bSHong Zhang if ((i > sf - lsbwidth - 2 && i < sf + 1) || (i > fs - 2 && i < fs + rsbwidth + 1)) { 89184ff8c8bSHong Zhang /* Determine the right eigenvectors R, where A = R \Lambda R^{-1} */ 8929566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.characteristic2)(ctx->physics2.user, dof, &x[i * dof], ctx->R, ctx->Rinv, ctx->speeds)); 89384ff8c8bSHong Zhang /* Evaluate jumps across interfaces (i-1, i) and (i, i+1), put in characteristic basis */ 8949566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ctx->cjmpLR, 2 * dof)); 89584ff8c8bSHong Zhang cjmpL = &ctx->cjmpLR[0]; 89684ff8c8bSHong Zhang cjmpR = &ctx->cjmpLR[dof]; 89784ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 89884ff8c8bSHong Zhang PetscScalar jmpL, jmpR; 89984ff8c8bSHong Zhang jmpL = x[(i + 0) * dof + j] - x[(i - 1) * dof + j]; 90084ff8c8bSHong Zhang jmpR = x[(i + 1) * dof + j] - x[(i + 0) * dof + j]; 90184ff8c8bSHong Zhang for (k = 0; k < dof; k++) { 90284ff8c8bSHong Zhang cjmpL[k] += ctx->Rinv[k + j * dof] * jmpL; 90384ff8c8bSHong Zhang cjmpR[k] += ctx->Rinv[k + j * dof] * jmpR; 90484ff8c8bSHong Zhang } 90584ff8c8bSHong Zhang } 90684ff8c8bSHong Zhang /* Apply limiter to the left and right characteristic jumps */ 90784ff8c8bSHong Zhang info.m = dof; 90884ff8c8bSHong Zhang info.hxs = hxs; 90984ff8c8bSHong Zhang info.hxf = hxf; 91084ff8c8bSHong Zhang (*ctx->limit2)(&info, cjmpL, cjmpR, ctx->sf, ctx->fs, i, ctx->cslope); 91184ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 91284ff8c8bSHong Zhang PetscScalar tmp = 0; 91384ff8c8bSHong Zhang for (k = 0; k < dof; k++) tmp += ctx->R[j + k * dof] * ctx->cslope[k]; 91484ff8c8bSHong Zhang slope[i * dof + j] = tmp; 91584ff8c8bSHong Zhang } 91684ff8c8bSHong Zhang } 91784ff8c8bSHong Zhang } 91884ff8c8bSHong Zhang 91984ff8c8bSHong Zhang for (i = xs; i < xs + xm + 1; i++) { 92084ff8c8bSHong Zhang PetscReal maxspeed; 92184ff8c8bSHong Zhang PetscScalar *uL, *uR; 92284ff8c8bSHong Zhang uL = &ctx->uLR[0]; 92384ff8c8bSHong Zhang uR = &ctx->uLR[dof]; 92484ff8c8bSHong Zhang if (i == sf - lsbwidth) { 92584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 92684ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 92784ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 92884ff8c8bSHong Zhang } 9299566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 93084ff8c8bSHong Zhang if (i < xs + xm) { 93184ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 93284ff8c8bSHong Zhang islow++; 93384ff8c8bSHong Zhang } 93484ff8c8bSHong Zhang } 93584ff8c8bSHong Zhang if (i > sf - lsbwidth && i < sf) { 93684ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 93784ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 93884ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 93984ff8c8bSHong Zhang } 9409566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 94184ff8c8bSHong Zhang if (i > xs) { 94284ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 94384ff8c8bSHong Zhang } 94484ff8c8bSHong Zhang if (i < xs + xm) { 94584ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 94684ff8c8bSHong Zhang islow++; 94784ff8c8bSHong Zhang } 94884ff8c8bSHong Zhang } 94984ff8c8bSHong Zhang if (i == sf) { /* interface between the slow region and the fast region */ 95084ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 95184ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 95284ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxf / 2; 95384ff8c8bSHong Zhang } 9549566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 95584ff8c8bSHong Zhang if (i > xs) { 95684ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 95784ff8c8bSHong Zhang } 95884ff8c8bSHong Zhang } 95984ff8c8bSHong Zhang if (i == fs) { /* interface between the fast region and the slow region */ 96084ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 96184ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxf / 2; 96284ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 96384ff8c8bSHong Zhang } 9649566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 96584ff8c8bSHong Zhang if (i < xs + xm) { 96684ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 96784ff8c8bSHong Zhang islow++; 96884ff8c8bSHong Zhang } 96984ff8c8bSHong Zhang } 97084ff8c8bSHong Zhang if (i > fs && i < fs + rsbwidth) { 97184ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 97284ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 97384ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 97484ff8c8bSHong Zhang } 9759566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 97684ff8c8bSHong Zhang if (i > xs) { 97784ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 97884ff8c8bSHong Zhang } 97984ff8c8bSHong Zhang if (i < xs + xm) { 98084ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[islow * dof + j] += ctx->flux[j] / hxs; 98184ff8c8bSHong Zhang islow++; 98284ff8c8bSHong Zhang } 98384ff8c8bSHong Zhang } 98484ff8c8bSHong Zhang if (i == fs + rsbwidth) { 98584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 98684ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 98784ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 98884ff8c8bSHong Zhang } 9899566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 99084ff8c8bSHong Zhang if (i > xs) { 99184ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(islow - 1) * dof + j] -= ctx->flux[j] / hxs; 99284ff8c8bSHong Zhang } 99384ff8c8bSHong Zhang } 99484ff8c8bSHong Zhang } 9959566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, Xloc, &x)); 9969566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(F, &f)); 9979566063dSJacob Faibussowitsch PetscCall(DMDARestoreArray(da, PETSC_TRUE, &slope)); 9989566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da, &Xloc)); 99984ff8c8bSHong Zhang PetscFunctionReturn(0); 100084ff8c8bSHong Zhang } 100184ff8c8bSHong Zhang 100284ff8c8bSHong Zhang /* --------------------------------- Finite Volume Solver for fast parts ----------------------------------- */ 10039371c9d4SSatish Balay PetscErrorCode FVRHSFunctionfast_2WaySplit(TS ts, PetscReal time, Vec X, Vec F, void *vctx) { 100484ff8c8bSHong Zhang FVCtx *ctx = (FVCtx *)vctx; 100584ff8c8bSHong Zhang PetscInt i, j, k, Mx, dof, xs, xm, ifast = 0, sf = ctx->sf, fs = ctx->fs; 100684ff8c8bSHong Zhang PetscReal hxs, hxf; 100784ff8c8bSHong Zhang PetscScalar *x, *f, *slope; 100884ff8c8bSHong Zhang Vec Xloc; 100984ff8c8bSHong Zhang DM da; 101084ff8c8bSHong Zhang 101184ff8c8bSHong Zhang PetscFunctionBeginUser; 10129566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &da)); 10139566063dSJacob Faibussowitsch PetscCall(DMGetLocalVector(da, &Xloc)); 10149566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); 101584ff8c8bSHong Zhang hxs = (ctx->xmax - ctx->xmin) * 3.0 / 8.0 / ctx->sf; 101684ff8c8bSHong Zhang hxf = (ctx->xmax - ctx->xmin) / 4.0 / (ctx->fs - ctx->sf); 10179566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, Xloc)); 10189566063dSJacob Faibussowitsch PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, Xloc)); 10199566063dSJacob Faibussowitsch PetscCall(VecZeroEntries(F)); 10209566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArray(da, Xloc, &x)); 10219566063dSJacob Faibussowitsch PetscCall(VecGetArray(F, &f)); 10229566063dSJacob Faibussowitsch PetscCall(DMDAGetArray(da, PETSC_TRUE, &slope)); 10239566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0)); 102484ff8c8bSHong Zhang 102584ff8c8bSHong Zhang if (ctx->bctype == FVBC_OUTFLOW) { 102684ff8c8bSHong Zhang for (i = xs - 2; i < 0; i++) { 102784ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[j]; 102884ff8c8bSHong Zhang } 102984ff8c8bSHong Zhang for (i = Mx; i < xs + xm + 2; i++) { 103084ff8c8bSHong Zhang for (j = 0; j < dof; j++) x[i * dof + j] = x[(xs + xm - 1) * dof + j]; 103184ff8c8bSHong Zhang } 103284ff8c8bSHong Zhang } 103384ff8c8bSHong Zhang if (ctx->bctype == FVBC_INFLOW) { 103484ff8c8bSHong Zhang /* See LeVeque, R. (2002). Finite Volume Methods for Hyperbolic Problems. doi:10.1017/CBO9780511791253 103584ff8c8bSHong Zhang pages 137-138 for the scheme. */ 103684ff8c8bSHong Zhang if (xs == 0) { /* Left Boundary */ 103784ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmin, ctx->ub); 103884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 103984ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[j] == PETSC_TRUE) { 104084ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = 2.0 * ctx->ub[j] - x[-(i + 1) * dof + j]; 104184ff8c8bSHong Zhang } else { 104284ff8c8bSHong Zhang for (i = -2; i < 0; i++) x[i * dof + j] = x[j]; /* Outflow */ 104384ff8c8bSHong Zhang } 104484ff8c8bSHong Zhang } 104584ff8c8bSHong Zhang } 104684ff8c8bSHong Zhang if (xs + xm == Mx) { /* Right Boundary */ 104784ff8c8bSHong Zhang ctx->physics2.inflow(ctx, time, ctx->xmax, ctx->ub); 104884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 104984ff8c8bSHong Zhang if (ctx->physics2.bcinflowindex[dof + j] == PETSC_TRUE) { 105084ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = 2.0 * ctx->ub[dof + j] - x[(2 * Mx - (i + 1)) * dof + j]; 105184ff8c8bSHong Zhang } else { 105284ff8c8bSHong Zhang for (i = Mx; i < Mx + 2; i++) x[i * dof + j] = x[(Mx - 1) * dof + j]; /* Outflow */ 105384ff8c8bSHong Zhang } 105484ff8c8bSHong Zhang } 105584ff8c8bSHong Zhang } 105684ff8c8bSHong Zhang } 105784ff8c8bSHong Zhang for (i = xs - 1; i < xs + xm + 1; i++) { 105884ff8c8bSHong Zhang struct _LimitInfo info; 105984ff8c8bSHong Zhang PetscScalar *cjmpL, *cjmpR; 106084ff8c8bSHong Zhang if (i > sf - 2 && i < fs + 1) { 10619566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.characteristic2)(ctx->physics2.user, dof, &x[i * dof], ctx->R, ctx->Rinv, ctx->speeds)); 10629566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(ctx->cjmpLR, 2 * dof)); 106384ff8c8bSHong Zhang cjmpL = &ctx->cjmpLR[0]; 106484ff8c8bSHong Zhang cjmpR = &ctx->cjmpLR[dof]; 106584ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 106684ff8c8bSHong Zhang PetscScalar jmpL, jmpR; 106784ff8c8bSHong Zhang jmpL = x[(i + 0) * dof + j] - x[(i - 1) * dof + j]; 106884ff8c8bSHong Zhang jmpR = x[(i + 1) * dof + j] - x[(i + 0) * dof + j]; 106984ff8c8bSHong Zhang for (k = 0; k < dof; k++) { 107084ff8c8bSHong Zhang cjmpL[k] += ctx->Rinv[k + j * dof] * jmpL; 107184ff8c8bSHong Zhang cjmpR[k] += ctx->Rinv[k + j * dof] * jmpR; 107284ff8c8bSHong Zhang } 107384ff8c8bSHong Zhang } 107484ff8c8bSHong Zhang /* Apply limiter to the left and right characteristic jumps */ 107584ff8c8bSHong Zhang info.m = dof; 107684ff8c8bSHong Zhang info.hxs = hxs; 107784ff8c8bSHong Zhang info.hxf = hxf; 107884ff8c8bSHong Zhang (*ctx->limit2)(&info, cjmpL, cjmpR, ctx->sf, ctx->fs, i, ctx->cslope); 107984ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 108084ff8c8bSHong Zhang PetscScalar tmp = 0; 108184ff8c8bSHong Zhang for (k = 0; k < dof; k++) tmp += ctx->R[j + k * dof] * ctx->cslope[k]; 108284ff8c8bSHong Zhang slope[i * dof + j] = tmp; 108384ff8c8bSHong Zhang } 108484ff8c8bSHong Zhang } 108584ff8c8bSHong Zhang } 108684ff8c8bSHong Zhang 108784ff8c8bSHong Zhang for (i = xs; i < xs + xm + 1; i++) { 108884ff8c8bSHong Zhang PetscReal maxspeed; 108984ff8c8bSHong Zhang PetscScalar *uL, *uR; 109084ff8c8bSHong Zhang uL = &ctx->uLR[0]; 109184ff8c8bSHong Zhang uR = &ctx->uLR[dof]; 109284ff8c8bSHong Zhang if (i == sf) { /* interface between the slow region and the fast region */ 109384ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 109484ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxs / 2; 109584ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxf / 2; 109684ff8c8bSHong Zhang } 10979566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 109884ff8c8bSHong Zhang if (i < xs + xm) { 109984ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[ifast * dof + j] += ctx->flux[j] / hxf; 110084ff8c8bSHong Zhang ifast++; 110184ff8c8bSHong Zhang } 110284ff8c8bSHong Zhang } 110384ff8c8bSHong Zhang if (i > sf && i < fs) { /* fast region */ 110484ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 110584ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxf / 2; 110684ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxf / 2; 110784ff8c8bSHong Zhang } 11089566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 110984ff8c8bSHong Zhang if (i > xs) { 111084ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(ifast - 1) * dof + j] -= ctx->flux[j] / hxf; 111184ff8c8bSHong Zhang } 111284ff8c8bSHong Zhang if (i < xs + xm) { 111384ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[ifast * dof + j] += ctx->flux[j] / hxf; 111484ff8c8bSHong Zhang ifast++; 111584ff8c8bSHong Zhang } 111684ff8c8bSHong Zhang } 111784ff8c8bSHong Zhang if (i == fs) { /* interface between the fast region and the slow region */ 111884ff8c8bSHong Zhang for (j = 0; j < dof; j++) { 111984ff8c8bSHong Zhang uL[j] = x[(i - 1) * dof + j] + slope[(i - 1) * dof + j] * hxf / 2; 112084ff8c8bSHong Zhang uR[j] = x[(i - 0) * dof + j] - slope[(i - 0) * dof + j] * hxs / 2; 112184ff8c8bSHong Zhang } 11229566063dSJacob Faibussowitsch PetscCall((*ctx->physics2.riemann2)(ctx->physics2.user, dof, uL, uR, ctx->flux, &maxspeed)); 112384ff8c8bSHong Zhang if (i > xs) { 112484ff8c8bSHong Zhang for (j = 0; j < dof; j++) f[(ifast - 1) * dof + j] -= ctx->flux[j] / hxf; 112584ff8c8bSHong Zhang } 112684ff8c8bSHong Zhang } 112784ff8c8bSHong Zhang } 11289566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArray(da, Xloc, &x)); 11299566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(F, &f)); 11309566063dSJacob Faibussowitsch PetscCall(DMDARestoreArray(da, PETSC_TRUE, &slope)); 11319566063dSJacob Faibussowitsch PetscCall(DMRestoreLocalVector(da, &Xloc)); 113284ff8c8bSHong Zhang PetscFunctionReturn(0); 113384ff8c8bSHong Zhang } 113484ff8c8bSHong Zhang 11359371c9d4SSatish Balay int main(int argc, char *argv[]) { 113684ff8c8bSHong Zhang char lname[256] = "mc", physname[256] = "advect", final_fname[256] = "solution.m"; 113784ff8c8bSHong Zhang PetscFunctionList limiters = 0, physics = 0; 113884ff8c8bSHong Zhang MPI_Comm comm; 113984ff8c8bSHong Zhang TS ts; 114084ff8c8bSHong Zhang DM da; 114184ff8c8bSHong Zhang Vec X, X0, R; 114284ff8c8bSHong Zhang FVCtx ctx; 114384ff8c8bSHong Zhang PetscInt i, k, dof, xs, xm, Mx, draw = 0, count_slow, count_fast, islow = 0, ifast = 0, islowbuffer = 0, *index_slow, *index_fast, *index_slowbuffer; 114484ff8c8bSHong Zhang PetscBool view_final = PETSC_FALSE; 114584ff8c8bSHong Zhang PetscReal ptime, maxtime; 114684ff8c8bSHong Zhang 1147327415f7SBarry Smith PetscFunctionBeginUser; 11489566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, 0, help)); 114984ff8c8bSHong Zhang comm = PETSC_COMM_WORLD; 11509566063dSJacob Faibussowitsch PetscCall(PetscMemzero(&ctx, sizeof(ctx))); 115184ff8c8bSHong Zhang 115284ff8c8bSHong Zhang /* Register limiters to be available on the command line */ 11539566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "upwind", Limit2_Upwind)); 11549566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "lax-wendroff", Limit2_LaxWendroff)); 11559566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "beam-warming", Limit2_BeamWarming)); 11569566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "fromm", Limit2_Fromm)); 11579566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "minmod", Limit2_Minmod)); 11589566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "superbee", Limit2_Superbee)); 11599566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "mc", Limit2_MC)); 11609566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&limiters, "koren3", Limit2_Koren3)); 116184ff8c8bSHong Zhang 116284ff8c8bSHong Zhang /* Register physical models to be available on the command line */ 11639566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&physics, "shallow", PhysicsCreate_Shallow)); 11649566063dSJacob Faibussowitsch PetscCall(PetscFunctionListAdd(&physics, "advect", PhysicsCreate_Advect)); 116584ff8c8bSHong Zhang 116684ff8c8bSHong Zhang ctx.comm = comm; 116784ff8c8bSHong Zhang ctx.cfl = 0.9; 116884ff8c8bSHong Zhang ctx.bctype = FVBC_PERIODIC; 116984ff8c8bSHong Zhang ctx.xmin = -1.0; 117084ff8c8bSHong Zhang ctx.xmax = 1.0; 117184ff8c8bSHong Zhang ctx.initial = 1; 117284ff8c8bSHong Zhang ctx.hratio = 2; 117384ff8c8bSHong Zhang maxtime = 10.0; 117484ff8c8bSHong Zhang ctx.simulation = PETSC_FALSE; 1175d0609cedSBarry Smith PetscOptionsBegin(comm, NULL, "Finite Volume solver options", ""); 11769566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-xmin", "X min", "", ctx.xmin, &ctx.xmin, NULL)); 11779566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-xmax", "X max", "", ctx.xmax, &ctx.xmax, NULL)); 11789566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-limit", "Name of flux imiter to use", "", limiters, lname, lname, sizeof(lname), NULL)); 11799566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-physics", "Name of physics model to use", "", physics, physname, physname, sizeof(physname), NULL)); 11809566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-draw", "Draw solution vector, bitwise OR of (1=initial,2=final,4=final error)", "", draw, &draw, NULL)); 11819566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-view_final", "Write final solution in ASCII MATLAB format to given file name", "", final_fname, final_fname, sizeof(final_fname), &view_final)); 11829566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-initial", "Initial condition (depends on the physics)", "", ctx.initial, &ctx.initial, NULL)); 11839566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-exact", "Compare errors with exact solution", "", ctx.exact, &ctx.exact, NULL)); 11849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-simulation", "Compare errors with reference solution", "", ctx.simulation, &ctx.simulation, NULL)); 11859566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-cfl", "CFL number to time step at", "", ctx.cfl, &ctx.cfl, NULL)); 11869566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-bc_type", "Boundary condition", "", FVBCTypes, (PetscEnum)ctx.bctype, (PetscEnum *)&ctx.bctype, NULL)); 11879566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-hratio", "Spacing ratio", "", ctx.hratio, &ctx.hratio, NULL)); 1188d0609cedSBarry Smith PetscOptionsEnd(); 118984ff8c8bSHong Zhang 119084ff8c8bSHong Zhang /* Choose the limiter from the list of registered limiters */ 11919566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(limiters, lname, &ctx.limit2)); 11923c633725SBarry Smith PetscCheck(ctx.limit2, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Limiter '%s' not found", lname); 119384ff8c8bSHong Zhang 119484ff8c8bSHong Zhang /* Choose the physics from the list of registered models */ 119584ff8c8bSHong Zhang { 119684ff8c8bSHong Zhang PetscErrorCode (*r)(FVCtx *); 11979566063dSJacob Faibussowitsch PetscCall(PetscFunctionListFind(physics, physname, &r)); 11983c633725SBarry Smith PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Physics '%s' not found", physname); 119984ff8c8bSHong Zhang /* Create the physics, will set the number of fields and their names */ 12009566063dSJacob Faibussowitsch PetscCall((*r)(&ctx)); 120184ff8c8bSHong Zhang } 120284ff8c8bSHong Zhang 120384ff8c8bSHong Zhang /* Create a DMDA to manage the parallel grid */ 12049566063dSJacob Faibussowitsch PetscCall(DMDACreate1d(comm, DM_BOUNDARY_PERIODIC, 50, ctx.physics2.dof, 2, NULL, &da)); 12059566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(da)); 12069566063dSJacob Faibussowitsch PetscCall(DMSetUp(da)); 120784ff8c8bSHong Zhang /* Inform the DMDA of the field names provided by the physics. */ 120884ff8c8bSHong Zhang /* The names will be shown in the title bars when run with -ts_monitor_draw_solution */ 1209*48a46eb9SPierre Jolivet for (i = 0; i < ctx.physics2.dof; i++) PetscCall(DMDASetFieldName(da, i, ctx.physics2.fieldname[i])); 12109566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(da, 0, &Mx, 0, 0, 0, 0, 0, &dof, 0, 0, 0, 0, 0)); 12119566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, &xs, 0, 0, &xm, 0, 0)); 121284ff8c8bSHong Zhang 121384ff8c8bSHong Zhang /* Set coordinates of cell centers */ 12149566063dSJacob Faibussowitsch PetscCall(DMDASetUniformCoordinates(da, ctx.xmin + 0.5 * (ctx.xmax - ctx.xmin) / Mx, ctx.xmax + 0.5 * (ctx.xmax - ctx.xmin) / Mx, 0, 0, 0, 0)); 121584ff8c8bSHong Zhang 121684ff8c8bSHong Zhang /* Allocate work space for the Finite Volume solver (so it doesn't have to be reallocated on each function evaluation) */ 12179566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(dof * dof, &ctx.R, dof * dof, &ctx.Rinv, 2 * dof, &ctx.cjmpLR, 1 * dof, &ctx.cslope)); 12189566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(2 * dof, &ctx.uLR, dof, &ctx.flux, dof, &ctx.speeds)); 12199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * dof, &ctx.ub)); 122084ff8c8bSHong Zhang 122184ff8c8bSHong Zhang /* Create a vector to store the solution and to save the initial state */ 12229566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(da, &X)); 12239566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &X0)); 12249566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &R)); 122584ff8c8bSHong Zhang 122684ff8c8bSHong Zhang /* create index for slow parts and fast parts, 122784ff8c8bSHong Zhang count_slow + count_fast = Mx, counts_slow*hs = 0.5, counts_fast*hf = 0.5 */ 122884ff8c8bSHong Zhang count_slow = Mx / (1.0 + ctx.hratio / 3.0); 122908401ef6SPierre Jolivet PetscCheck(count_slow % 2 == 0, PETSC_COMM_WORLD, PETSC_ERR_USER, "Please adjust grid size Mx (-da_grid_x) and hratio (-hratio) so that Mx/(1+hratio/3) is even"); 123084ff8c8bSHong Zhang count_fast = Mx - count_slow; 123184ff8c8bSHong Zhang ctx.sf = count_slow / 2; 123284ff8c8bSHong Zhang ctx.fs = ctx.sf + count_fast; 12339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xm * dof, &index_slow)); 12349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(xm * dof, &index_fast)); 12359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(8 * dof, &index_slowbuffer)); 123684ff8c8bSHong Zhang ctx.lsbwidth = 4; 123784ff8c8bSHong Zhang ctx.rsbwidth = 4; 123884ff8c8bSHong Zhang 123984ff8c8bSHong Zhang for (i = xs; i < xs + xm; i++) { 124084ff8c8bSHong Zhang if (i < ctx.sf - ctx.lsbwidth || i > ctx.fs + ctx.rsbwidth - 1) 124184ff8c8bSHong Zhang for (k = 0; k < dof; k++) index_slow[islow++] = i * dof + k; 124284ff8c8bSHong Zhang else if ((i >= ctx.sf - ctx.lsbwidth && i < ctx.sf) || (i > ctx.fs - 1 && i <= ctx.fs + ctx.rsbwidth - 1)) 124384ff8c8bSHong Zhang for (k = 0; k < dof; k++) index_slowbuffer[islowbuffer++] = i * dof + k; 124484ff8c8bSHong Zhang else 124584ff8c8bSHong Zhang for (k = 0; k < dof; k++) index_fast[ifast++] = i * dof + k; 124684ff8c8bSHong Zhang } 12479566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, islow, index_slow, PETSC_COPY_VALUES, &ctx.iss)); 12489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, ifast, index_fast, PETSC_COPY_VALUES, &ctx.isf)); 12499566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_WORLD, islowbuffer, index_slowbuffer, PETSC_COPY_VALUES, &ctx.issb)); 125084ff8c8bSHong Zhang 125184ff8c8bSHong Zhang /* Create a time-stepping object */ 12529566063dSJacob Faibussowitsch PetscCall(TSCreate(comm, &ts)); 12539566063dSJacob Faibussowitsch PetscCall(TSSetDM(ts, da)); 12549566063dSJacob Faibussowitsch PetscCall(TSSetRHSFunction(ts, R, FVRHSFunction_2WaySplit, &ctx)); 12559566063dSJacob Faibussowitsch PetscCall(TSRHSSplitSetIS(ts, "slow", ctx.iss)); 12569566063dSJacob Faibussowitsch PetscCall(TSRHSSplitSetIS(ts, "slowbuffer", ctx.issb)); 12579566063dSJacob Faibussowitsch PetscCall(TSRHSSplitSetIS(ts, "fast", ctx.isf)); 12589566063dSJacob Faibussowitsch PetscCall(TSRHSSplitSetRHSFunction(ts, "slow", NULL, FVRHSFunctionslow_2WaySplit, &ctx)); 12599566063dSJacob Faibussowitsch PetscCall(TSRHSSplitSetRHSFunction(ts, "fast", NULL, FVRHSFunctionfast_2WaySplit, &ctx)); 12609566063dSJacob Faibussowitsch PetscCall(TSRHSSplitSetRHSFunction(ts, "slowbuffer", NULL, FVRHSFunctionslowbuffer_2WaySplit, &ctx)); 126184ff8c8bSHong Zhang 12629566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSMPRK)); 12639566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts, maxtime)); 12649566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER)); 126584ff8c8bSHong Zhang 126684ff8c8bSHong Zhang /* Compute initial conditions and starting time step */ 12679566063dSJacob Faibussowitsch PetscCall(FVSample_2WaySplit(&ctx, da, 0, X0)); 12689566063dSJacob Faibussowitsch PetscCall(FVRHSFunction_2WaySplit(ts, 0, X0, X, (void *)&ctx)); /* Initial function evaluation, only used to determine max speed */ 12699566063dSJacob Faibussowitsch PetscCall(VecCopy(X0, X)); /* The function value was not used so we set X=X0 again */ 12709566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, ctx.cfl / ctx.cfl_idt)); 12719566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts)); /* Take runtime options */ 12729566063dSJacob Faibussowitsch PetscCall(SolutionStatsView(da, X, PETSC_VIEWER_STDOUT_WORLD)); 127384ff8c8bSHong Zhang { 127484ff8c8bSHong Zhang PetscInt steps; 127584ff8c8bSHong Zhang PetscScalar mass_initial, mass_final, mass_difference, mass_differenceg; 127684ff8c8bSHong Zhang const PetscScalar *ptr_X, *ptr_X0; 127784ff8c8bSHong Zhang const PetscReal hs = (ctx.xmax - ctx.xmin) * 3.0 / 4.0 / count_slow; 127884ff8c8bSHong Zhang const PetscReal hf = (ctx.xmax - ctx.xmin) / 4.0 / count_fast; 127984ff8c8bSHong Zhang 12809566063dSJacob Faibussowitsch PetscCall(TSSolve(ts, X)); 12819566063dSJacob Faibussowitsch PetscCall(TSGetSolveTime(ts, &ptime)); 12829566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts, &steps)); 128384ff8c8bSHong Zhang /* calculate the total mass at initial time and final time */ 128484ff8c8bSHong Zhang mass_initial = 0.0; 128584ff8c8bSHong Zhang mass_final = 0.0; 12869566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, X0, (void *)&ptr_X0)); 12879566063dSJacob Faibussowitsch PetscCall(DMDAVecGetArrayRead(da, X, (void *)&ptr_X)); 128884ff8c8bSHong Zhang for (i = xs; i < xs + xm; i++) { 128984ff8c8bSHong Zhang if (i < ctx.sf || i > ctx.fs - 1) { 129084ff8c8bSHong Zhang for (k = 0; k < dof; k++) { 129184ff8c8bSHong Zhang mass_initial = mass_initial + hs * ptr_X0[i * dof + k]; 129284ff8c8bSHong Zhang mass_final = mass_final + hs * ptr_X[i * dof + k]; 129384ff8c8bSHong Zhang } 129484ff8c8bSHong Zhang } else { 129584ff8c8bSHong Zhang for (k = 0; k < dof; k++) { 129684ff8c8bSHong Zhang mass_initial = mass_initial + hf * ptr_X0[i * dof + k]; 129784ff8c8bSHong Zhang mass_final = mass_final + hf * ptr_X[i * dof + k]; 129884ff8c8bSHong Zhang } 129984ff8c8bSHong Zhang } 130084ff8c8bSHong Zhang } 13019566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, X0, (void *)&ptr_X0)); 13029566063dSJacob Faibussowitsch PetscCall(DMDAVecRestoreArrayRead(da, X, (void *)&ptr_X)); 130384ff8c8bSHong Zhang mass_difference = mass_final - mass_initial; 13049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&mass_difference, &mass_differenceg, 1, MPIU_SCALAR, MPIU_SUM, comm)); 13059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Mass difference %g\n", (double)mass_differenceg)); 130663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Final time %g, steps %" PetscInt_FMT "\n", (double)ptime, steps)); 13079566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Maximum allowable stepsize according to CFL %g\n", (double)(1.0 / ctx.cfl_idt))); 130884ff8c8bSHong Zhang if (ctx.exact) { 130984ff8c8bSHong Zhang PetscReal nrm1 = 0; 13109566063dSJacob Faibussowitsch PetscCall(SolutionErrorNorms_2WaySplit(&ctx, da, ptime, X, &nrm1)); 13119566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Error ||x-x_e||_1 %g\n", (double)nrm1)); 131284ff8c8bSHong Zhang } 131384ff8c8bSHong Zhang if (ctx.simulation) { 131484ff8c8bSHong Zhang PetscReal nrm1 = 0; 131584ff8c8bSHong Zhang PetscViewer fd; 131684ff8c8bSHong Zhang char filename[PETSC_MAX_PATH_LEN] = "binaryoutput"; 131784ff8c8bSHong Zhang Vec XR; 131884ff8c8bSHong Zhang PetscBool flg; 131984ff8c8bSHong Zhang const PetscScalar *ptr_XR; 13209566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(NULL, NULL, "-f", filename, sizeof(filename), &flg)); 13213c633725SBarry Smith PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_USER, "Must indicate binary file with the -f option"); 13229566063dSJacob Faibussowitsch PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, filename, FILE_MODE_READ, &fd)); 13239566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X0, &XR)); 13249566063dSJacob Faibussowitsch PetscCall(VecLoad(XR, fd)); 13259566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&fd)); 13269566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(X, &ptr_X)); 13279566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(XR, &ptr_XR)); 132884ff8c8bSHong Zhang for (i = xs; i < xs + xm; i++) { 132984ff8c8bSHong Zhang if (i < ctx.sf || i > ctx.fs - 1) 133084ff8c8bSHong Zhang for (k = 0; k < dof; k++) nrm1 = nrm1 + hs * PetscAbs(ptr_X[i * dof + k] - ptr_XR[i * dof + k]); 133184ff8c8bSHong Zhang else 133284ff8c8bSHong Zhang for (k = 0; k < dof; k++) nrm1 = nrm1 + hf * PetscAbs(ptr_X[i * dof + k] - ptr_XR[i * dof + k]); 133384ff8c8bSHong Zhang } 13349566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(X, &ptr_X)); 13359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(XR, &ptr_XR)); 13369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(comm, "Error ||x-x_e||_1 %g\n", (double)nrm1)); 13379566063dSJacob Faibussowitsch PetscCall(VecDestroy(&XR)); 133884ff8c8bSHong Zhang } 133984ff8c8bSHong Zhang } 134084ff8c8bSHong Zhang 13419566063dSJacob Faibussowitsch PetscCall(SolutionStatsView(da, X, PETSC_VIEWER_STDOUT_WORLD)); 13429566063dSJacob Faibussowitsch if (draw & 0x1) PetscCall(VecView(X0, PETSC_VIEWER_DRAW_WORLD)); 13439566063dSJacob Faibussowitsch if (draw & 0x2) PetscCall(VecView(X, PETSC_VIEWER_DRAW_WORLD)); 134484ff8c8bSHong Zhang if (draw & 0x4) { 134584ff8c8bSHong Zhang Vec Y; 13469566063dSJacob Faibussowitsch PetscCall(VecDuplicate(X, &Y)); 13479566063dSJacob Faibussowitsch PetscCall(FVSample_2WaySplit(&ctx, da, ptime, Y)); 13489566063dSJacob Faibussowitsch PetscCall(VecAYPX(Y, -1, X)); 13499566063dSJacob Faibussowitsch PetscCall(VecView(Y, PETSC_VIEWER_DRAW_WORLD)); 13509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&Y)); 135184ff8c8bSHong Zhang } 135284ff8c8bSHong Zhang 135384ff8c8bSHong Zhang if (view_final) { 135484ff8c8bSHong Zhang PetscViewer viewer; 13559566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_WORLD, final_fname, &viewer)); 13569566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_MATLAB)); 13579566063dSJacob Faibussowitsch PetscCall(VecView(X, viewer)); 13589566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(viewer)); 13599566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 136084ff8c8bSHong Zhang } 136184ff8c8bSHong Zhang 136284ff8c8bSHong Zhang /* Clean up */ 13639566063dSJacob Faibussowitsch PetscCall((*ctx.physics2.destroy)(ctx.physics2.user)); 13649566063dSJacob Faibussowitsch for (i = 0; i < ctx.physics2.dof; i++) PetscCall(PetscFree(ctx.physics2.fieldname[i])); 13659566063dSJacob Faibussowitsch PetscCall(PetscFree(ctx.physics2.bcinflowindex)); 1366d0609cedSBarry Smith PetscCall(PetscFree(ctx.ub)); 13679566063dSJacob Faibussowitsch PetscCall(PetscFree4(ctx.R, ctx.Rinv, ctx.cjmpLR, ctx.cslope)); 13689566063dSJacob Faibussowitsch PetscCall(PetscFree3(ctx.uLR, ctx.flux, ctx.speeds)); 13699566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X)); 13709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&X0)); 13719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&R)); 13729566063dSJacob Faibussowitsch PetscCall(DMDestroy(&da)); 13739566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts)); 13749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ctx.iss)); 13759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ctx.isf)); 13769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ctx.issb)); 13779566063dSJacob Faibussowitsch PetscCall(PetscFree(index_slow)); 13789566063dSJacob Faibussowitsch PetscCall(PetscFree(index_fast)); 13799566063dSJacob Faibussowitsch PetscCall(PetscFree(index_slowbuffer)); 13809566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&limiters)); 13819566063dSJacob Faibussowitsch PetscCall(PetscFunctionListDestroy(&physics)); 13829566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 1383b122ec5aSJacob Faibussowitsch return 0; 138484ff8c8bSHong Zhang } 138584ff8c8bSHong Zhang 138684ff8c8bSHong Zhang /*TEST 138784ff8c8bSHong Zhang 138884ff8c8bSHong Zhang build: 138984ff8c8bSHong Zhang requires: !complex !single 139084ff8c8bSHong Zhang depends: finitevolume1d.c 139184ff8c8bSHong Zhang 139284ff8c8bSHong Zhang test: 139384ff8c8bSHong Zhang suffix: 1 139484ff8c8bSHong Zhang args: -da_grid_x 60 -initial 7 -xmin -1 -xmax 1 -hratio 2 -limit mc -ts_dt 0.025 -ts_max_steps 24 -ts_type mprk -ts_mprk_type 2a22 139584ff8c8bSHong Zhang output_file: output/ex4_1.out 139684ff8c8bSHong Zhang 139784ff8c8bSHong Zhang test: 139884ff8c8bSHong Zhang suffix: 2 139984ff8c8bSHong Zhang args: -da_grid_x 60 -initial 7 -xmin -1 -xmax 1 -hratio 2 -limit mc -ts_dt 0.025 -ts_max_steps 24 -ts_type mprk -ts_mprk_type 2a22 -ts_use_splitrhsfunction 1 140084ff8c8bSHong Zhang output_file: output/ex4_1.out 140184ff8c8bSHong Zhang 140284ff8c8bSHong Zhang test: 140384ff8c8bSHong Zhang suffix: 3 140484ff8c8bSHong Zhang args: -da_grid_x 40 -initial 1 -hratio 2 -limit mc -ts_dt 0.1 -ts_max_steps 24 -ts_max_time 7.0 -ts_type mprk -ts_mprk_type 2a22 -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 0 140584ff8c8bSHong Zhang output_file: output/ex4_3.out 140684ff8c8bSHong Zhang 140784ff8c8bSHong Zhang test: 140884ff8c8bSHong Zhang suffix: 4 140984ff8c8bSHong Zhang nsize: 2 141084ff8c8bSHong Zhang args: -da_grid_x 40 -initial 1 -hratio 2 -limit mc -ts_dt 0.1 -ts_max_steps 24 -ts_max_time 7.0 -ts_type mprk -ts_mprk_type 2a22 -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 1 141184ff8c8bSHong Zhang output_file: output/ex4_3.out 141284ff8c8bSHong Zhang 141384ff8c8bSHong Zhang test: 141484ff8c8bSHong Zhang suffix: 5 141584ff8c8bSHong Zhang nsize: 4 1416660278c0SBarry Smith args: -da_grid_x 40 -initial 1 -hratio 2 -limit mc -ts_dt 0.1 -ts_max_steps 24 -ts_max_time 7.0 -ts_type mprk -ts_mprk_type 2a22 -physics shallow -bc_type outflow -xmin 0 -xmax 50 -ts_use_splitrhsfunction 1 141784ff8c8bSHong Zhang output_file: output/ex4_3.out 141884ff8c8bSHong Zhang TEST*/ 1419