|
| 1 | +#!/usr/bin/env python3 |
| 2 | +import vtk |
| 3 | +from vtk.util import numpy_support |
| 4 | +import numpy as np |
| 5 | +from netCDF4 import Dataset |
| 6 | +import seissolxdmf |
| 7 | +import time |
| 8 | +import argparse |
| 9 | +from writeNetcdf import writeNetcdf |
| 10 | + |
| 11 | + |
| 12 | +def compute_lIdt(ndt: int, args_idt: list) -> list: |
| 13 | + """Compute list of time steps to process""" |
| 14 | + if args_idt[0] == -1: |
| 15 | + return list(range(0, ndt)) |
| 16 | + else: |
| 17 | + return args_idt |
| 18 | + |
| 19 | + |
| 20 | +class SeisSolXdmfExtended(seissolxdmf.seissolxdmf): |
| 21 | + def generate_vtk_ugrid(self) -> vtk.vtkUnstructuredGrid: |
| 22 | + """Generate VTK object from SeisSol XDMF file""" |
| 23 | + connect = self.ReadConnect() |
| 24 | + nElements, ndim2 = connect.shape |
| 25 | + |
| 26 | + grid_type = {3: vtk.vtkPolyData, 4: vtk.vtkUnstructuredGrid}[ndim2] |
| 27 | + grid = grid_type() |
| 28 | + |
| 29 | + xyz = self.ReadGeometry() |
| 30 | + points = vtk.vtkPoints() |
| 31 | + if ndim2 == 3: |
| 32 | + print("Surface output, assuming the grid is at z=0") |
| 33 | + xyz[:, 2] = 0.0 |
| 34 | + points.SetData(numpy_support.numpy_to_vtk(xyz)) |
| 35 | + grid.SetPoints(points) |
| 36 | + |
| 37 | + vtkCells = vtk.vtkCellArray() |
| 38 | + connect2 = np.zeros((nElements, ndim2 + 1), dtype=np.int64) |
| 39 | + connect2[:, 0] = ndim2 |
| 40 | + connect2[:, 1:] = connect |
| 41 | + vtkCells.SetCells(nElements, numpy_support.numpy_to_vtkIdTypeArray(connect2)) |
| 42 | + |
| 43 | + if ndim2 == 4: |
| 44 | + grid.SetCells(vtk.VTK_TETRA, vtkCells) |
| 45 | + elif ndim2 == 3: |
| 46 | + grid.SetPolys(vtkCells) |
| 47 | + else: |
| 48 | + raise NotImplementedError |
| 49 | + return grid |
| 50 | + |
| 51 | + |
| 52 | +def main(): |
| 53 | + parser = argparse.ArgumentParser( |
| 54 | + description="Read paraview output, and project on structured grid, generating a netcdf file" |
| 55 | + ) |
| 56 | + parser.add_argument("filename", help="SeisSol output filename (xdmf)") |
| 57 | + parser.add_argument( |
| 58 | + "--add2filename", |
| 59 | + help="string to append to filename of the new file", |
| 60 | + type=str, |
| 61 | + default="", |
| 62 | + ) |
| 63 | + parser.add_argument( |
| 64 | + "--box", |
| 65 | + nargs=1, |
| 66 | + metavar=("box_arguments"), |
| 67 | + help=( |
| 68 | + "structured grid, " |
| 69 | + "dx x0 x1 y0 y1 z0 z1 for 3D grid, " |
| 70 | + "dx x0 x1 y0 y1 for 2D grid" |
| 71 | + ), |
| 72 | + required=True, |
| 73 | + ) |
| 74 | + parser.add_argument( |
| 75 | + "--idt", |
| 76 | + nargs="+", |
| 77 | + help="list of time step to process (1st = 0); -1 = all", |
| 78 | + type=int, |
| 79 | + default=([-1]), |
| 80 | + ) |
| 81 | + parser.add_argument( |
| 82 | + "--variable", |
| 83 | + nargs="+", |
| 84 | + required=True, |
| 85 | + metavar=("variable"), |
| 86 | + help="name of variable; all for all stored quantities", |
| 87 | + ) |
| 88 | + parser.add_argument( |
| 89 | + "--paraview_readable", |
| 90 | + dest="paraview_readable", |
| 91 | + action="store_true", |
| 92 | + help="generate paraview readable netcdf file", |
| 93 | + ) |
| 94 | + |
| 95 | + args = parser.parse_args() |
| 96 | + |
| 97 | + sx = SeisSolXdmfExtended(args.filename) |
| 98 | + ugrid = sx.generate_vtk_ugrid() |
| 99 | + |
| 100 | + lidt = compute_lIdt(sx.ndt, args.idt) |
| 101 | + |
| 102 | + if len(args.box[0].split()) == 7: |
| 103 | + dx, x0, x1, y0, y1, z0, z1 = [float(v) for v in args.box[0].split()] |
| 104 | + z = np.arange(z0, z1 + dx, dx) |
| 105 | + assert isinstance(ugrid, vtk.vtkUnstructuredGrid) |
| 106 | + is2DGrid = False |
| 107 | + elif len(args.box[0].split()) == 5: |
| 108 | + dx, x0, x1, y0, y1 = [float(v) for v in args.box[0].split()] |
| 109 | + z = np.array([0]) |
| 110 | + z0 = 0.0 |
| 111 | + is2DGrid = True |
| 112 | + else: |
| 113 | + raise ValueError(f"wrong number of arguments in args.box {args.box}") |
| 114 | + |
| 115 | + x = np.arange(x0, x1 + dx, dx) |
| 116 | + y = np.arange(y0, y1 + dx, dx) |
| 117 | + |
| 118 | + if is2DGrid: |
| 119 | + xx, yy = np.meshgrid(x, y) |
| 120 | + else: |
| 121 | + yy, zz, xx = np.meshgrid(y, z, x) |
| 122 | + |
| 123 | + # Create grid image volume |
| 124 | + image1Size = [x.shape[0], y.shape[0], z.shape[0]] |
| 125 | + image1Origin = [x0, y0, z0] |
| 126 | + image1Spacing = [dx, dx, dx] |
| 127 | + |
| 128 | + imageData1 = vtk.vtkImageData() |
| 129 | + imageData1.SetDimensions(image1Size) |
| 130 | + imageData1.SetOrigin(image1Origin) |
| 131 | + imageData1.SetSpacing(image1Spacing) |
| 132 | + |
| 133 | + # Perform the interpolation |
| 134 | + probeFilter = vtk.vtkProbeFilter() |
| 135 | + |
| 136 | + probeFilter.SetInputData(imageData1) |
| 137 | + probeFilter.SpatialMatchOn() |
| 138 | + |
| 139 | + for idt in lidt: |
| 140 | + probedData = [] |
| 141 | + for var in args.variable: |
| 142 | + print("update scalars") |
| 143 | + scalars = vtk.vtkFloatArray() |
| 144 | + |
| 145 | + W = sx.ReadData(var, idt) |
| 146 | + scalars = numpy_support.numpy_to_vtk( |
| 147 | + num_array=W, deep=True, array_type=vtk.VTK_FLOAT |
| 148 | + ) |
| 149 | + ugrid.GetCellData().SetScalars(scalars) |
| 150 | + |
| 151 | + # Create the CellDataToPointData filter |
| 152 | + cellToPointFilter = vtk.vtkCellDataToPointData() |
| 153 | + cellToPointFilter.SetInputData(ugrid) |
| 154 | + cellToPointFilter.Update() |
| 155 | + |
| 156 | + # Get the output grid with point data |
| 157 | + outputGrid = cellToPointFilter.GetOutput() |
| 158 | + |
| 159 | + # Perform the interpolation |
| 160 | + probeFilter.SetSourceData(outputGrid) |
| 161 | + start = time.time() |
| 162 | + print("start prob filter") |
| 163 | + probeFilter.Update() |
| 164 | + stop = time.time() |
| 165 | + print(f"{var} {idt}: done prob filter in {stop - start} s") |
| 166 | + |
| 167 | + polyout = probeFilter.GetOutput() |
| 168 | + projData = polyout.GetPointData().GetScalars() |
| 169 | + projDataNp = numpy_support.vtk_to_numpy(projData).reshape(xx.shape) |
| 170 | + probedData.append(projDataNp) |
| 171 | + |
| 172 | + xyz = [x, y] if is2DGrid else [x, y, z] |
| 173 | + if args.paraview_readable: |
| 174 | + for i, sdata in enumerate(args.variable): |
| 175 | + writeNetcdf( |
| 176 | + f"gridded_{sdata}_{dx:.0f}_{idt}{args.add2filename}", |
| 177 | + xyz, |
| 178 | + [sdata], |
| 179 | + [probedData[i]], |
| 180 | + paraview_readable=True, |
| 181 | + ) |
| 182 | + else: |
| 183 | + writeNetcdf( |
| 184 | + f"gridded_asagi_dx{dx:.0f}_{idt}{args.add2filename}", |
| 185 | + xyz, |
| 186 | + args.variable, |
| 187 | + probedData, |
| 188 | + False, |
| 189 | + ) |
| 190 | + |
| 191 | + |
| 192 | +if __name__ == "__main__": |
| 193 | + main() |
0 commit comments