def test_load_grid(): gr = Grid() gr.load('test_create_grid.vtk') ncells = gr.getNumberOfCells() print(f'ncells = {ncells}') assert ncells == 2
def test_edge_arc_lengths(): gr = Grid() gr.setFlags(1, 1) filename = str(DATA_DIR / Path('cs_4.nc')) gr.loadFromUgrid2DFile(f'{filename}$physics') gr.computeEdgeArcLengths() ncells = gr.getNumberOfCells() for icell in range(ncells): for edgeIndex in range(4): arcLength = gr.getEdgeArcLength(icell, edgeIndex) print(f"""" cell {icell} edge {edgeIndex} edge arc length/radius: {arcLength}""")
def test_degenerate(): nx, ny, nxTarget, nyTarget = 1, 1, 12, 11 v0 = (0., 0., 0.) v1 = (1., 1., 0.) v2 = (1., 1., 0.) # degenerate point v3 = (0., 1., 0.) # create the grid gr = Grid() cellPoints = getCellByCellPoints( generateStructuredGridPoints(nx, ny, v0, v1, v2, v3)) gr.setPoints(cellPoints) numCells = cellPoints.shape[0] # create the interpolator vi = VectorInterp() vi.setGrid(gr) vi.buildLocator(numCellsPerBucket=1, periodX=0., enableFolding=False) # generate targets point for the above grid targetPoints = generateStructuredGridPoints(nxTarget, nyTarget, v0, v1, v2, v3).reshape((-1, 3)) numBad = vi.findPoints(targetPoints, tol2=1.e-10) # all points fall within the source grid so numBad == 0 assert (numBad == 0) with TemporaryDirectory() as d: # generate edge data data = numpy.zeros((numCells, 4), numpy.float64) for cellId in range(numCells): # iterate over the edges of the source grid cells for edgeIndex in range(4): # set one edge to 1, all other edges to zero data[cellId, edgeIndex] = 1.0 # get the edge interpolated vectors vectorData = vi.getEdgeVectors(data, placement=CELL_BY_CELL_DATA) fileName = f"{d}{sep}degenerate_cellId{cellId}edgeIndex{edgeIndex}Edge.vtk" saveVectorsVTKFile(targetPoints, vectorData, fileName) # get the face interpolated vectors vectorData = vi.getFaceVectors(data, placement=CELL_BY_CELL_DATA) fileName = f"{d}{sep}degenerate_cellId{cellId}edgeIndex{edgeIndex}Face.vtk" saveVectorsVTKFile(targetPoints, vectorData, fileName) # reset this edge's value back to its original data[cellId, edgeIndex] = 0.0
def test_rectilinear(): nx, ny, nxTarget, nyTarget = 1, 1, 2, 3 v0 = (0., 0., 0.) v1 = (1., 0., 0.) v2 = (1., 1., 0.) v3 = (0., 1., 0.) # create the grid gr = Grid() cellPoints = getCellByCellPoints( generateStructuredGridPoints(nx, ny, v0, v1, v2, v3)) gr.setPoints(cellPoints) numCells = cellPoints.shape[0] # create the interpolator vi = VectorInterp() vi.setGrid(gr) vi.buildLocator(numCellsPerBucket=1, periodX=0., enableFolding=False) # generate targets point for the above grid targetPoints = generateStructuredGridPoints(nxTarget, nyTarget, v0, v1, v2, v3).reshape((-1, 3)) numBad = vi.findPoints(targetPoints, tol2=1.e-10) # all points fall within the source grid so numBad == 0 assert (numBad == 0) # generate edge data data = numpy.zeros((numCells, 4), numpy.float64) for cellId in range(numCells): # iterate over the edges of the source grid cells for edgeIndex in range(4): # set one edge to 1, all other edges to zero data[cellId, edgeIndex] = 1.0 # get the edge interpolated vectors vectorData = vi.getEdgeVectors(data, placement=CELL_BY_CELL_DATA) assert (abs(vectorData.max() - 1.) < 1.e-12) assert (abs(vectorData.min() - 0.) < 1.e-12) # get the lateral flux interpolated vectors vectorData = vi.getFaceVectors(data, placement=CELL_BY_CELL_DATA) # face vectors take the sign of the area vector, # negative if pointing down assert (abs(numpy.fabs(vectorData).max() - 1.) < 1.e-12) assert (abs(numpy.fabs(vectorData).min() - 0.) < 1.e-12) # reset this edge's value back to its original data[cellId, edgeIndex] = 0.0
def test_rectilinear2(): nx, ny, nxTarget, nyTarget = 1, 2, 1, 2 v0 = numpy.array((0., 0., 0.)) v1 = numpy.array((nx, 0., 0.)) v2 = numpy.array((nx, ny, 0.)) v3 = numpy.array((0., ny, 0.)) # create the grid gr = Grid() cellPoints = getCellByCellPoints( generateStructuredGridPoints(nx, ny, v0, v1, v2, v3)) gr.setPoints(cellPoints) numCells = cellPoints.shape[0] # create the interpolator vi = VectorInterp() vi.setGrid(gr) vi.buildLocator(numCellsPerBucket=10, periodX=0., enableFolding=False) # generate targets point for the above grid dx = numpy.array((0.1, 0., 0.)) dy = numpy.array((0., 0.1, 0.)) targetPoints = generateStructuredGridPoints(nxTarget, nyTarget, v0 + dx + dy, v1 - dx + dy, v2 - dx - dy, v3 + dx - dy).reshape((-1, 3)) numBad = vi.findPoints(targetPoints, tol2=1.e-10) # all points fall within the source grid so numBad == 0 assert (numBad == 0) # generate edge data data = numpy.zeros((numCells, 4), numpy.float64) for cellId in range(numCells): # iterate over the edges of the source grid cells for edgeIndex in range(4): # set one edge to 1, all other edges to zero data[cellId, edgeIndex] = 1.0 # get the edge interpolated vectors vectorData = vi.getEdgeVectors(data, placement=CELL_BY_CELL_DATA) # get the lateral flux interpolated vectors vectorData = vi.getFaceVectors(data, placement=CELL_BY_CELL_DATA) # reset this edge's value back to its original data[cellId, edgeIndex] = 0.0
def test_load_from_ugrid_file2(): gr = Grid() gr.setFlags(1, 1) filename = str(DATA_DIR / Path('lfric_diag_wind.nc')) gr.loadFromUgrid2DFile(f'{filename}$Mesh2d') nedges = gr.getNumberOfEdges() print(f'nedges = {nedges}') assert (nedges == 3072)
def test_simple(nx, ny, potFunc, xyz): # create the grid and the edge data gr = Grid() points = numpy.zeros((nx * ny, 4, 3), numpy.float64) data = numpy.zeros((nx * ny, 4)) dx = 1.0 / float(nx) dy = 1.0 / float(ny) k = 0 for i in range(nx): x0 = i * dx x1 = x0 + dx for j in range(ny): y0 = j * dy y1 = y0 + dy # node indexing # 3-->--2 # | | # ^ ^ # | | # 0-->--1 points[k, 0, :] = x0, y0, 0. points[k, 1, :] = x1, y0, 0. points[k, 2, :] = x1, y1, 0. points[k, 3, :] = x0, y1, 0. # edge indexing # 2 # +-->--+ # | | # 3^ ^1 # | | # +-->--+ # 0 data[k, 0] = potFunc(points[k, 1, :]) - potFunc(points[k, 0, :]) data[k, 1] = potFunc(points[k, 2, :]) - potFunc(points[k, 1, :]) data[k, 2] = potFunc(points[k, 2, :]) - potFunc(points[k, 3, :]) data[k, 3] = potFunc(points[k, 3, :]) - potFunc(points[k, 0, :]) # increment the cell counter k += 1 gr.setPoints(points) gr.dump('test_polyline_integral.vtk') pli = PolylineIntegral() pli.setGrid(gr) # no periodicity in x pli.buildLocator(numCellsPerBucket=128, periodX=0.0, enableFolding=False) pli.computeWeights(xyz, counterclock=False) flux = pli.getIntegral(data=data, placement=CELL_BY_CELL_DATA) exactFlux = potFunc(xyz[-1, :]) - potFunc(xyz[0, :]) print(f'total flux: {flux:.3f} exact flux: {exactFlux:.3f}') assert abs(flux - exactFlux) < 1.e-10
def test_load_grid(): gr = Grid() filename = str(DATA_DIR / Path('test_create_grid.vtk')) gr.load(filename) ncells = gr.getNumberOfCells() print(f'ncells = {ncells}') assert (ncells == 2) num_bad_cells = gr.check() assert (num_bad_cells == 0) points = gr.getPoints() assert (points.shape[0] == ncells) assert (points.shape[1] == 4) assert (points.shape[2] == 3)
def test_create_grid(): # create the grid gr = Grid() # 2 cells points = numpy.array([(0., 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.), (1., 0., 0.), (2., 0., 0.), (2., 1., 0.), (1., 1., 0.)]).reshape(2, 4, 3) gr.setPoints(points) gr.dump('test_create_grid.vtk')
def test_create_grid(): # create the grid gr = Grid() # 2 cells points = numpy.array([(0., 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.), (1., 0., 0.), (2., 0., 0.), (2., 1., 0.), (1., 1., 0.)]).reshape((2, 4, 3)) gr.setPoints(points) # get a pointer to the points of the cell-by-cell mesh pts = gr.getPoints() print(pts) with TemporaryDirectory() as d: fname = str(Path(d) / Path('grid.vtk')) gr.dump(fname)
def test_attach_data(): # create the grid gr = Grid() # 2 cells points = numpy.array([(0., 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.), (1., 0., 0.), (2., 0., 0.), (2., 1., 0.), (1., 1., 0.)]).reshape((2, 4, 3)) gr.setPoints(points) # create cell data, 3 per cell nDataPerCell = 3 data = numpy.arange(0, 2 * nDataPerCell, dtype=numpy.float64).reshape( (2, nDataPerCell)) gr.attach('mydata', data) with TemporaryDirectory() as d: fname = str(Path(d) / Path('grid.vtk')) gr.dump(fname) # read the data back to check the layout of the data reader = vtk.vtkUnstructuredGridReader() reader.SetFileName(fname) reader.Update() ugrid = reader.GetOutput() arr = ugrid.GetCellData().GetArray('mydata') assert (arr.GetNumberOfTuples() == gr.getNumberOfCells()) assert (arr.GetNumberOfComponents() == nDataPerCell)
def test_identity(): grid = Grid() grid.setFlags(fixLonAcrossDateline=0, averageLonAtPole=0, degrees=True) # uniform lat-lon filename = str(DATA_DIR / Path('latlon4x2.nc')) meshname = 'latlon' grid.loadFromUgrid2DFile(f'{filename}${meshname}') num_edges = grid.getNumberOfEdges() data = numpy.array(range(0, num_edges), numpy.float64) pli = PolylineIntegral() pli.setGrid(grid) pli.buildLocator(numCellsPerBucket=100, periodX=0., enableFolding=False) xyz = numpy.array([ (0., 90., 0.), (360., 90., 0.), ]) pli.computeWeights(xyz, counterclock=False) flux = pli.getIntegral(data=data, placement=UNIQUE_EDGE_DATA) print(f'flux = {flux}') assert abs(flux - 38.) < 1.e-10
def grid(filename): gr = Grid() gr.setFlags(1, 1) gr.loadFromUgrid2DFile(f'{filename}$Mesh2d') return gr
def test_load_from_ugrid_file(): gr = Grid() gr.setFlags(1, 1) filename = str(DATA_DIR / Path('cs_4.nc')) gr.loadFromUgrid2DFile(f'{filename}$physics') nedges = gr.getNumberOfEdges() print(f'nedges = {nedges}') assert (nedges == 192) ncells = gr.getNumberOfCells() for icell in range(ncells): for iedge in range(4): edgeId, edgeSign = gr.getEdgeId(icell, iedge) nodeIds = gr.getNodeIds(icell, iedge) print(f"cell {icell} edge {iedge}: " + f"edgeId = {edgeId}, {edgeSign} nodeIds = {nodeIds}") # attaching a 3 components field to the grid data = numpy.array(range(ncells * 4 * 3), numpy.float64) gr.attach('myData', data) num_bad_cells = gr.check() assert (num_bad_cells == 0)
def test_load_from_ugrid_file(): data_dir = Path(__file__).absolute().parent / '../../data' gr = Grid() gr.setFlags(1, 1) filename = str(data_dir / Path('cs_4.nc')) gr.loadFrom2DUgrid(f'{filename}:physics') nedges = gr.getNumberOfEdges() print(f'nedges = {nedges}') assert nedges == 192 ncells = gr.getNumberOfCells() for icell in range(ncells): for iedge in range(4): edgeId, edgeSign = gr.getEdgeId(icell, iedge) nodeIds = gr.getNodeIds(icell, iedge) print( f'cell {icell} edge {iedge}: edgeId = {edgeId}, {edgeSign} nodeIds = {nodeIds}' ) # attaching a 3 components field to the grid data = numpy.array(range(ncells * 4 * 3), numpy.float64) gr.attach('myData', data)
def test_load_ugrid_data(): # a single cell # 3....>2....2 # : : # v ^ # 1 0 # : : # 0....<3....1 xyz = numpy.array([(0., 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.)], dtype=numpy.float64) face2nodes = numpy.array([ (0, 1, 2, 3), ], dtype=numpy.uintp) edge2nodes = numpy.array( [ (1, 2), # edge 0 (3, 0), # edge 1 (3, 2), # edge 2 (1, 0) ], # edge 3 dtype=numpy.uintp) gr = Grid() gr.setFlags(0, 0) gr.loadFromUgrid2DData(xyz, face2nodes, edge2nodes) n0, n1 = gr.getNodeIds(cellId=0, edgeIndex=0) assert (n0 == 0) assert (n1 == 1) n0, n1 = gr.getNodeIds(cellId=0, edgeIndex=1) assert (n0 == 1) assert (n1 == 2) n0, n1 = gr.getNodeIds(cellId=0, edgeIndex=2) assert (n0 == 3) assert (n1 == 2) n0, n1 = gr.getNodeIds(cellId=0, edgeIndex=3) assert (n0 == 0) assert (n1 == 3) gr.dump('singleCell.vtk')
def test_loadFromUgrid2DData(): # src grid sg = Grid() sg.setFlags(0, 0) # lon-lat filename = str(DATA_DIR / Path('lonlatzt_100x50x3x2.nc')) sg.loadFromUgrid2DFile(f'{filename}$mesh2d') # dst grid dg = Grid() dg.setFlags(0, 0) # 2 cells/faces # # 3..1<...2...>5..5 # : : : # v v ^ # 6 0 3 1 4 # : : : # 0..>2...1...>0..4 xyz = numpy.array([ (0., 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.), (2., 0., 0.), (2., 1., 0.), ]) face2nodes = numpy.array([(0, 1, 2, 3), (2, 1, 4, 5)], numpy.uint64) edge2nodes = numpy.array([(1, 4), (2, 3), (0, 1), (2, 1), (4, 5), (2, 5), (3, 0)], numpy.uint64) dg.loadFromUgrid2DData(xyz, face2nodes, edge2nodes) # create a regridder rg = RegridEdges() rg.setSrcGrid(sg) rg.setDstGrid(dg) rg.buildLocator(numCellsPerBucket=128, periodX=0., enableFolding=False) rg.computeWeights()
def test_set_grids(): # create and load src grid sg = Grid() sg.setFlags(0, 0) # lon-lat filename = str(DATA_DIR / Path('lonlatzt_100x50x3x2.nc')) sg.loadFromUgrid2DFile(f'{filename}$mesh2d') # create and load dst grid dg = Grid() dg.setFlags(1, 1) # cubed-sphere filename = str(DATA_DIR / Path('lfric_diag_wind.nc')) dg.loadFromUgrid2DFile(f'{filename}$Mesh2d') # create a regridder rg = RegridEdges() rg.setSrcGrid(sg) rg.setDstGrid(dg) rg.buildLocator(numCellsPerBucket=128, periodX=360., enableFolding=True) rg.computeWeights()
def test_identity(): srcGrid = Grid() srcGrid.setFlags(fixLonAcrossDateline=0, averageLonAtPole=0, degrees=True) # uniform lat-lon filename = str(DATA_DIR / Path('latlon4x2.nc')) meshname = 'latlon' srcGrid.loadFromUgrid2DFile(f'{filename}${meshname}') # destination and source grids are the same dstGrid = Grid() dstGrid.setFlags(fixLonAcrossDateline=0, averageLonAtPole=0, degrees=True) # uniform lat-lon filename = str(DATA_DIR / Path('latlon4x2.nc')) meshname = 'latlon' dstGrid.loadFromUgrid2DFile(f'{filename}${meshname}') regridder = RegridEdges() # even though the grids are the same, we still need to create two # grid instances regridder.setSrcGrid(srcGrid) regridder.setDstGrid(dstGrid) # compute the weights regridder.buildLocator(numCellsPerBucket=128, periodX=360., enableFolding=False) regridder.computeWeights(debug=2) # create a mock field num_edges = srcGrid.getNumberOfEdges() src_data = numpy.array(range(0, num_edges), numpy.float64) # allocate space to receive the interpolated data dst_data = numpy.empty((num_edges, ), numpy.float64) # apply the interpolation weights regridder.apply(src_data, dst_data, placement=UNIQUE_EDGE_DATA) diff = src_data - dst_data for i in range(num_edges): print(f'{i} {diff[i]}') print(f'src data = {src_data}') print(f'dst data = {dst_data}') # check that we recover the original field error = numpy.fabs(diff).sum() print(f'error = {error}') assert error < 1.e-6
def test_simple(): # create the grid and the edge data gr = Grid() nx, ny = 3, 2 points = numpy.zeros((nx * ny, 4, 3), numpy.float64) data = numpy.zeros((nx * ny, 4)) dx = 1.0 / float(nx) dy = 1.0 / float(ny) k = 0 for i in range(nx): x0 = i * dx x1 = x0 + dx for j in range(ny): y0 = j * dy y1 = y0 + dy # node indexing # 3-->--2 # | | # ^ ^ # | | # 0-->--1 points[k, 0, :] = x0, y0, 0. points[k, 1, :] = x1, y0, 0. points[k, 2, :] = x1, y1, 0. points[k, 3, :] = x0, y1, 0. # edge indexing # 2 # +-->--+ # | | # 3^ ^1 # | | # +-->--+ # 0 data[k, 0] = potentialFunc(points[k, 1, :]) - potentialFunc( points[k, 0, :]) data[k, 1] = potentialFunc(points[k, 2, :]) - potentialFunc( points[k, 1, :]) data[k, 2] = potentialFunc(points[k, 2, :]) - potentialFunc( points[k, 3, :]) data[k, 3] = potentialFunc(points[k, 3, :]) - potentialFunc( points[k, 0, :]) # increment the cell counter k += 1 gr.setPoints(points) gr.dump('test_polyline_integral.vtk') pli = PolylineIntegral() # create the polyline through which the flux will be integrated xyz = numpy.array([(0., 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.)]) # no periodicity in x pli.build(gr, xyz, counterclock=False, periodX=0.0) flux = pli.getIntegral(data) exactFlux = potentialFunc(xyz[-1, :]) - potentialFunc(xyz[0, :]) print(f'total flux: {flux:.3f} exact flux: {exactFlux:.3f}') assert abs(flux - exactFlux) < 1.e-10
def test_completely_outside(nx, ny, potFunc): print('target line is outside the domain, expect warnings!') # create the grid and the edge data gr = Grid() points = numpy.zeros((nx * ny, 4, 3), numpy.float64) data = numpy.zeros((nx * ny, 4)) dx = 1.0 / float(nx) dy = 1.0 / float(ny) k = 0 for i in range(nx): x0 = i * dx x1 = x0 + dx for j in range(ny): y0 = j * dy y1 = y0 + dy # node indexing # 3-->--2 # | | # ^ ^ # | | # 0-->--1 points[k, 0, :] = x0, y0, 0. points[k, 1, :] = x1, y0, 0. points[k, 2, :] = x1, y1, 0. points[k, 3, :] = x0, y1, 0. # edge indexing # 2 # +-->--+ # | | # 3^ ^1 # | | # +-->--+ # 0 data[k, 0] = potFunc(points[k, 1, :]) - potFunc(points[k, 0, :]) data[k, 1] = potFunc(points[k, 2, :]) - potFunc(points[k, 1, :]) data[k, 2] = potFunc(points[k, 2, :]) - potFunc(points[k, 3, :]) data[k, 3] = potFunc(points[k, 3, :]) - potFunc(points[k, 0, :]) # increment the cell counter k += 1 gr.setPoints(points) pli = PolylineIntegral() pli.setGrid(gr) # create the polyline through which the flux will be integrated xyz = numpy.array([(0., 0., 0.), (-1., 0., 0.), (-1., 1., 0.), (0., 1., 0.)]) # no periodicity in x pli.buildLocator(numCellsPerBucket=128, periodX=0.0, enableFolding=False) pli.computeWeights(xyz, counterclock=False) flux = pli.getIntegral(data=data, placement=CELL_BY_CELL_DATA) exactFlux = 0.0 print(f'total flux: {flux:.3f} exact flux: {exactFlux:.3f}') assert abs(flux - exactFlux) < 1.e-10
def test_partially_outside(nx, ny, potFunc): print('target line is partially outside the domain, expect a warning!') # create the grid and the edge data gr = Grid() points = numpy.zeros((nx * ny, 4, 3), numpy.float64) data = numpy.zeros((nx * ny, 4)) dx = 1.0 / float(nx) dy = 1.0 / float(ny) k = 0 for i in range(nx): x0 = i * dx x1 = x0 + dx for j in range(ny): y0 = j * dy y1 = y0 + dy # node indexing # 3-->--2 # | | # ^ ^ # | | # 0-->--1 points[k, 0, :] = x0, y0, 0. points[k, 1, :] = x1, y0, 0. points[k, 2, :] = x1, y1, 0. points[k, 3, :] = x0, y1, 0. # edge indexing # 2 # +-->--+ # | | # 3^ ^1 # | | # +-->--+ # 0 data[k, 0] = potFunc(points[k, 1, :]) - potFunc(points[k, 0, :]) data[k, 1] = potFunc(points[k, 2, :]) - potFunc(points[k, 1, :]) data[k, 2] = potFunc(points[k, 2, :]) - potFunc(points[k, 3, :]) data[k, 3] = potFunc(points[k, 3, :]) - potFunc(points[k, 0, :]) # increment the cell counter k += 1 gr.setPoints(points) pli = PolylineIntegral() # create the polyline through which the flux will be integrated xyz = numpy.array([(-0.5, 0., 0.), (1., 0., 0.), (1., 1., 0.), (0., 1., 0.)]) pli.setGrid(gr) # no periodicity in x pli.buildLocator(numCellsPerBucket=128, periodX=0.0, enableFolding=False) pli.computeWeights(xyz, counterclock=False) flux = pli.getIntegral(data=data, placement=CELL_BY_CELL_DATA) # because the first point is outside the domain, only the contribution # stemming from the path inside the domain will be computed. Let's # correct for this by moving the first point inwards xyz[0, 0] = 0. exactFlux = potentialFunc(xyz[-1, :]) - potentialFunc(xyz[0, :]) print(f'total flux: {flux:.3f} exact flux: {exactFlux:.3f}') assert abs(flux - exactFlux) < 1.e-10 # print all the log messages printLogMessages() # write the logs to file writeLogMessages("test_partially_outside_log.txt")