import numpy as np
from scipy import interpolate
from dorie.utilities.grid import BaseGrid
def _equal_grid_shapes(cells1,cells2):
shapes_equal = cells1.shape == cells2.shape
if not shapes_equal:
print("Grid shapes do not match: {}, {}".format(cells1.shape,cells2.shape))
return shapes_equal
def _equal_coordinates(cells1,cells2,abstol,reltol):
if cells1.shape != cells2.shape:
return False
coords_equal = np.allclose(cells1,cells2,atol=abstol,rtol=reltol)
if not coords_equal:
print("Grids do not match")
idiff = np.argmax(np.sqrt(np.sum((cells1-cells2)**2, axis=0)))
print("\tLargest difference: got {} and {}".format(cells1[:,idiff],cells2[:,idiff]))
return coords_equal
def _equal_variable_keys(grid1,grid2):
data1, data2 = [g.data() for g in (grid1,grid2)]
keys_equal = set(data1.keys()) == set(data2.keys())
if not keys_equal:
print("Variable keys do not match")
return keys_equal
def _sort_cells(grid):
cells = grid.cellCenters()
ix = np.lexsort(cells.T)
sorted_cells = cells[ix,...]
return sorted_cells
def _sort_grid(grid):
cells = grid.cellCenters()
ix = np.lexsort(cells.T)
sorted_cells = cells[ix,...]
sorted_data = {key: val[ix] for key,val in grid.data().items()}
return sorted_cells, sorted_data
def _equal_grids(grid1,grid2,abstol,reltol):
cells1 = _sort_cells(grid1)
cells2 = _sort_cells(grid2)
return _equal_grid_shapes(cells1,cells2) and _equal_coordinates(cells1,cells2,abstol,reltol)
def _calc_residuals(grid1,grid2,interpolate_grid):
cells1 = grid1.cellCenters()
cells2 = grid2.cellCenters()
data1 = grid1.data()
data2 = grid2.data()
if interpolate_grid:
residuals = {}
for key in data1.keys():
print("Interpolating variable {} ...".format(key))
interpolator = interpolate.NearestNDInterpolator(cells1,data1[key])
residuals[key] = interpolator(cells2) - data2[key]
else:
_, sorted_data1 = _sort_grid(grid1)
_, sorted_data2 = _sort_grid(grid2)
residuals = {var: v1 - v2 for var, v1, v2 in zip(data1.keys(),sorted_data1.values(),sorted_data2.values())}
return residuals, grid2
def _compare_max_norm(residuals, atol, rtol):
passed = True
for var, res in residuals.items():
if not np.allclose(res, 0., atol=atol, rtol=rtol):
print(var, res)
print("Data in variable {} does not match".format(var))
print("\tLargest difference: {}".format(np.max(np.abs(res))))
passed = False
return passed
def _compare_l2_norm(residuals, grid, abstol):
passed = True
for var, res in residuals.items():
l2 = np.sqrt(np.sum(grid.integrate(res**2) / grid.integrate(1)))
if np.all(l2 > abstol):
print("Data in variable {} does not match".format(var))
print("\tL2 error: {}".format(l2))
passed = False
return passed
[docs]def compare(grid1,grid2,abstol=1E-7,reltol=1E-7,strict=False):
if not isinstance(grid1,BaseGrid) or not isinstance(grid2,BaseGrid):
raise TypeError("Inputs must be of type BaseGrid (got: {} and {})"\
.format(type(grid1),type(grid2)))
interpolate_grid = False
if not _equal_grids(grid1,grid2,abstol,reltol):
if strict:
return False
else:
interpolate_grid = True
if not _equal_variable_keys(grid1,grid2):
return False
residuals, res_grid = _calc_residuals(grid1,grid2,interpolate_grid)
if strict:
return _compare_max_norm(residuals, abstol, reltol)
else:
return _compare_l2_norm(residuals, res_grid, abstol)