def divergence_theorem_test(self): "Test that the total input equals the total flux through the boundary." grid = self.grid inputs = PISM.HydrologyInputs() inputs.no_model_mask = None inputs.geometry = self.geometry inputs.basal_melt_rate = self.zero inputs.ice_sliding_speed = self.zero inputs.surface_input_rate = self.surface_input_rate dt = self.model.max_timestep(0).value() self.model.update(0, dt, inputs) flux_magnitude = PISM.IceModelVec2S(grid, "flux_magnitude", PISM.WITHOUT_GHOSTS) flux_magnitude.set_to_magnitude(self.model.flux()) # Compute the total input. This approximates a double integral, hence # the "dx dy" factor. total_input = self.model.surface_input_rate().sum() * (grid.dx() * grid.dy()) # Compute the total flux through the grounding line. This is not # exactly what we want, but it's close. It would be better to use the # flux on the staggered grid as computed internally, but the flux # magnitude will do, especially in the dx=dy case. This approximates a # line integral over the grounding line, hence the dx factor below. total_flux = 0.0 cell_type = self.geometry.cell_type with PISM.vec.Access(nocomm=[cell_type, flux_magnitude]): for (i, j) in grid.points(): if cell_type.ice_free_ocean( i, j) and cell_type.next_to_grounded_ice(i, j): total_flux += flux_magnitude[i, j] * grid.dx() total_flux = PISM.GlobalSum(ctx.com, total_flux) # This is the relative error. Note that it is not sensitive to the # value of hydrology.steady.volume_ratio. relative_error = np.fabs(total_input - total_flux) / total_input assert relative_error < 1e-5 ctx.log.message(1, "relative error: {}\n".format(relative_error))
def report(self): """Compares computed and exact solution values and displays a summary report.""" grid = self.grid ssa_stdout = self.ssa.stdout_report() PISM.verbPrintf(3, grid.com, ssa_stdout) maxvecerr = 0.0 avvecerr = 0.0 avuerr = 0.0 avverr = 0.0 maxuerr = 0.0 maxverr = 0.0 if (self.config.get_boolean("basal_resistance.pseudo_plastic.enabled") and self.config.get_double("basal_resistance.pseudo_plastic.q") != 1.0): PISM.verbPrintf( 1, grid.com, "WARNING: numerical errors not valid for pseudo-plastic till\n" ) PISM.verbPrintf( 1, grid.com, "NUMERICAL ERRORS in velocity relative to exact solution:\n") vel_ssa = self.ssa.velocity() vel_ssa.begin_access() exactvelmax = 0 gexactvelmax = 0 for (i, j) in self.grid.points(): x = grid.x(i) y = grid.y(j) (uexact, vexact) = self.exactSolution(i, j, x, y) exactnormsq = math.sqrt(uexact * uexact + vexact * vexact) exactvelmax = max(exactnormsq, exactvelmax) solution = vel_ssa[i, j] uerr = abs(solution.u - uexact) verr = abs(solution.v - vexact) avuerr += uerr avverr += verr maxuerr = max(maxuerr, uerr) maxverr = max(maxverr, verr) vecerr = math.sqrt(uerr * uerr + verr * verr) maxvecerr = max(maxvecerr, vecerr) avvecerr = avvecerr + vecerr vel_ssa.end_access() N = grid.Mx() * grid.My() gexactvelmax = PISM.GlobalMax(grid.com, exactvelmax) gmaxuerr = PISM.GlobalMax(grid.com, maxuerr) gmaxverr = PISM.GlobalMax(grid.com, maxverr) gavuerr = PISM.GlobalSum(grid.com, avuerr) / N gavverr = PISM.GlobalSum(grid.com, avverr) / N gmaxvecerr = PISM.GlobalMax(grid.com, maxvecerr) gavvecerr = PISM.GlobalSum(grid.com, avvecerr) / N sys = grid.ctx().unit_system() m_year = PISM.UnitConverter(sys, "m / second", "m / year") if abs(gexactvelmax) > 0.0: relative_vel_error = (gavvecerr / gexactvelmax) * 100.0 else: relative_vel_error = 0.0 PISM.verbPrintf( 1, grid.com, "velocity : maxvector prcntavvec maxu maxv avu avv\n" ) PISM.verbPrintf(1, grid.com, " %11.4f%13.5f%10.4f%10.4f%10.4f%10.4f\n", m_year(gmaxvecerr), relative_vel_error, m_year(gmaxuerr), m_year(gmaxverr), m_year(gavuerr), m_year(gavverr)) PISM.verbPrintf(1, grid.com, "NUM ERRORS DONE\n")