5 #ifndef WrappedPython_ParFlow_parflow_h 6 #define WrappedPython_ParFlow_parflow_h 15 "\"\"\"This module provides ParaView equivalents to several ParFlow\n" 16 "pftools algorithms; these are implemented using VTKPythonAlgorithmBase\n" 17 "subclasses and demonstrate how to access both surface and subsurface\n" 18 "computational grids within a single filter.\"\"\"\n" 20 "from paraview.util.vtkAlgorithm import *\n" 21 "import numpy as np\n" 24 " \"\"\"This class defines some utilities to perform computations similar\n" 25 " to those implemented by ParFlow's pftools suite.\"\"\"\n" 28 " def dataPointExtent(dataset):\n" 29 " \"\"\"Return the parflow extents in (k,j,i) order of the *point*\n" 30 " extents of this dataset, which is assumed to be structured.\n" 32 " Note that VTK normally assumes data is (i,j,k) ordered.\"\"\"\n" 33 " ext = tuple(np.flip(dataset.GetDimensions()))\n" 37 " def dataCellExtent(dataset):\n" 38 " \"\"\"Return the parflow extents in (k,j,i) order of the *cell*\n" 39 " extents of this dataset, which is assumed to be structured.\n" 41 " Note that (1) VTK normally uses point counts along axes rather\n" 42 " than cell counts and (2) assumes data is (i,j,k) ordered.\"\"\"\n" 43 " # Subtracting 1 from GetDimensions accounts for point-counts\n" 44 " # vs cell-counts, while np.flip(...) switches the axis order:\n" 45 " ext = tuple(np.flip(dataset.GetDimensions()) - 1)\n" 49 " def computeTopSurface(ext, mask):\n" 50 " # I. Reshape the mask and create zk, a column of k-axis indices:\n" 51 " mr = np.reshape(mask > 0, ext)\n" 52 " zk = np.reshape(np.arange(ext[0]), (ext[0],1,1))\n" 53 " # II. The top surface at each (i,j) is the location\n" 54 " # of the highest zk-value that is not masked:\n" 55 " top = np.argmax(mr * zk, axis=0)\n" 56 " # III. Mark completely-masked columns of cells with an\n" 57 " # invalid \"top\" index of -1:\n" 58 " # Columns in mask that had no valid value for mr * zk result\n" 59 " # in entries of \"top\" that are 0. But 0 is also a valid k index\n" 60 " # so we mark those which should be marked out with -1:\n" 61 " mr = (mr == False) # Invert the mask to catch bad cells\n" 62 " top = top - np.all(mr, axis=0) # Subtract 1 from masked column entries.\n" 66 " def computeTopSurfaceIndices(top):\n" 67 " \"\"\"Convert the \"top\" surface matrix into an array of indices that\n" 68 " only include valid top-surface cells. Any negative entry of \"top\"\n" 69 " does not have its index included.\n" 71 " The result is a matrix; each row corresponds to a top-surface cell\n" 72 " and each column holds a cell's k-, j-, and i-indices, respectively.\n" 74 " itop = np.array([(top[i,j], j, i) \\\n" 75 " for i in range(top.shape[0]) \\\n" 76 " for j in range(top.shape[1]) \\\n" 77 " if top[i,j] >= 0])\n" 81 " def computeSurfaceStorage(ext, itop, xx, pressure):\n" 82 " # I. Compute the dx * dy area term using point coordinates from the mesh:\n" 83 " xt = xx[itop[:,0], itop[:,1], itop[:,2]]\n" 84 " dx = xx[itop[:,0], itop[:,1], itop[:,2] + 1] - xt\n" 85 " dy = xx[itop[:,0], itop[:,1] + 1, itop[:,2]] - xt\n" 86 " # Now dx and dy are matrices whose rows are vectors.\n" 87 " # Compute the norms of the vectors.\n" 88 " # dx = np.sqrt(np.sum(dx * dx,axis=1))\n" 89 " # dy = np.sqrt(np.sum(dy * dy,axis=1))\n" 90 " # To more closely match parflow:\n" 94 " pp = np.reshape(pressure, ext)\n" 95 " pt = pp[itop[:,0], itop[:,1], itop[:,2]]\n" 96 " sus = pt * (pt > 0.0) * dx * dy\n" 100 " def computeSubsurfaceStorage(saturation, pressure, volume, porosity, specific_storage):\n" 101 " \"\"\"Compute the subsurface storage for the entire domain.\"\"\"\n" 102 " import numpy as np\n" 103 " sbs = saturation * volume * (porosity + pressure * specific_storage)\n" 107 " def computeGroundwaterStorage(saturation, pressure, volume, porosity, specific_storage):\n" 108 " \"\"\"Compute the groundwater storage.\n" 109 " This is the same calculation as subsurface storage, but only\n" 110 " sums values over cells with a saturation of 1.0.\n" 112 " import numpy as np\n" 113 " sbs = (saturation == 1.0) * volume * (porosity + pressure * specific_storage)\n" 117 " def computeSurfaceRunoff(top, xx, pressure, slope, mannings):\n" 118 " \"\"\"Compute surface runoff (water leaving the domain boundary\n" 119 " or flowing into a masked area)\"\"\"\n" 120 " def addToRunoff(runoff, sro, top, slope, pressure, mannings, delta):\n" 121 " \"\"\"Given a truthy 2-d array (idx) of places where runoff occurs,\n" 122 " compute the runoff and add it to the total (sro).\n" 124 " # We would like to do this:\n" 126 " # runoff * np.sqrt(np.abs(slope)) / mannings * \\\n" 127 " # np.power(ptop, 5.0/3.0) * delta\n" 128 " # ... but we can't since it might result in NaN values where\n" 129 " # runoff is False. Instead, only compute the runoff exactly\n" 130 " # at locations where runoff is true:\n" 131 " ww = np.where(runoff)\n" 133 " np.sqrt(np.abs(slope[ww])) / mannings[ww] * \\\n" 134 " np.power(ptop[ww], 5.0/3.0) * delta[ww]\n" 136 " # Initialize runoff:\n" 137 " sro = np.zeros(top.shape)\n" 138 " # Prepare indices and tempororary variables:\n" 139 " sz = np.prod(top.shape)\n" 140 " ext = (int(np.prod(pressure.shape)/sz),) + top.shape\n" 141 " tk = np.reshape(top, sz)\n" 142 " tj = np.floor(np.arange(sz)/top.shape[1]).astype(int)\n" 143 " ti = np.arange(sz) % top.shape[1]\n" 144 " tt = np.zeros(top.shape) # temporary array\n" 145 " # Subset of pressure at the top surface:\n" 146 " ptop = np.reshape(np.reshape(pressure, ext)[tk, tj, ti], top.shape)\n" 148 " # Determine size of top-surface cells along north-south direction:\n" 149 " delta = np.reshape((xx[tk, tj + 1, ti] - xx[tk, tj, ti])[:,1], top.shape)\n" 151 " # Fill the temporary array with data shifted south by 1:\n" 152 " np.concatenate((top[1:,:], -np.ones((1,top.shape[1]))), axis=0, out=tt)\n" 153 " # Compute conditions for flow exiting to the north:\n" 154 " cnorth = (top >= 0) & (tt < 0) & (slope[:,:,1] < 0) & (ptop > 0)\n" 155 " # Now add values to per-cell runoff sro:\n" 156 " addToRunoff(cnorth, sro, top, slope[:,:,1], pressure, mannings, delta)\n" 158 " # Fill the temporary array with data shifted north by 1:\n" 159 " np.concatenate((-np.ones((1,top.shape[1])), top[0:-1,:]), axis=0, out=tt)\n" 160 " # Compute conditions for flow exiting to the south:\n" 161 " csouth = (top >= 0) & (tt < 0) & (slope[:,:,1] > 0) & (ptop > 0)\n" 162 " # Now add values to per-cell runoff sro:\n" 163 " addToRunoff(csouth, sro, top, slope[:,:,1], pressure, mannings, delta)\n" 165 " # Determine size of top-surface cells along east-west direction:\n" 166 " delta = np.reshape((xx[tk, tj, ti + 1] - xx[tk, tj, ti])[:,0], top.shape)\n" 168 " # Fill the temporary array with data shifted east by 1:\n" 169 " np.concatenate((top[:,1:], -np.ones((top.shape[0], 1))), axis=1, out=tt)\n" 170 " # Compute conditions for flow exiting to the west:\n" 171 " cwest = (top >= 0) & (tt < 0) & (slope[:,:,0] < 0) & (ptop > 0)\n" 172 " # Now add values to per-cell runoff sro:\n" 173 " addToRunoff(cwest, sro, top, slope[:,:,0], pressure, mannings, delta)\n" 175 " # Fill the temporary array with data shifted north by 1:\n" 176 " np.concatenate((-np.ones((top.shape[0], 1)), top[:,0:-1]), axis=1, out=tt)\n" 177 " # Compute conditions for flow exiting to the south:\n" 178 " ceast = (top >= 0) & (tt < 0) & (slope[:,:,0] > 0) & (ptop > 0)\n" 179 " # Now add values to per-cell runoff sro:\n" 180 " addToRunoff(ceast, sro, top, slope[:,:,0], pressure, mannings, delta)\n" 185 " def computeWaterTableDepth(top, saturation, xx):\n" 186 " \"\"\"Compute the depth to the water table.\n" 188 " The returned array is the distance along the z axis between\n" 189 " the water surface and ground level. It should always be\n" 190 " negative (i.e., it is a displacement on the z axis starting\n" 191 " at the surface).\n" 193 " sz = np.prod(top.shape)\n" 194 " ext = (int(np.prod(saturation.shape)/sz),) + top.shape\n" 195 " sr = np.reshape(saturation >= 1.0, ext)\n" 196 " zk = np.reshape(np.arange(ext[0]), (ext[0],1,1))\n" 197 " # The top surface at each (i,j) is the location\n" 198 " # of the highest zk-value that is not masked:\n" 199 " depthIdx = np.argmax(sr * zk, axis=0)\n" 200 " tk = np.reshape(top, sz)\n" 201 " dk = np.reshape(depthIdx, sz)\n" 202 " dj = np.floor(np.arange(sz)/top.shape[1]).astype(int)\n" 203 " di = np.arange(sz) % top.shape[1]\n" 204 " depth = xx[dk, dj, di, 2] - xx[tk, dj, di, 2]\n" 206 " # Mark locations where the domain is masked or\n" 207 " # no water table appears as NaN (not-a-number):\n" 208 " sr = (sr == False) # Invert the saturation mask\n" 209 " ww = np.where(np.reshape(np.all(sr, axis=0), sz))\n" 210 " depth[ww] = np.nan\n" 213 "class ParFlowAlgorithm(VTKPythonAlgorithmBase):\n" 214 " \"\"\"A base class for algorithms that operate on\n" 215 " ParFlow simulation data.\n" 217 " This class provides method implementations that\n" 218 " simplify working with data from the vtkParFlowMetaReader.\n" 221 " 1. RequestUpdateExtent will ensure valid extents\n" 222 " are passed to each of the filter's inputs based on\n" 223 " their available whole extents. Without this, passing\n" 224 " both the surface and subsurface meshes to a python\n" 225 " filter would cause warnings as the default\n" 226 " implementation simply mirrors the downstream request\n" 227 " to each of its upstream filters.\n" 229 " 2. RequestDataObject will create the same type of\n" 230 " output as the input data objects so that either\n" 231 " image data or structured grids (both of which may\n" 232 " be output by the reader) can be passed through the\n" 235 " def FillInputPortInformation(self, port, info):\n" 236 " info.Set(self.INPUT_REQUIRED_DATA_TYPE(), \"vtkDataSet\")\n" 239 " def RequestDataObject(self, request, inInfoVec, outInfoVec):\n" 240 " \"\"\"Create a data object of the same type as the input.\"\"\"\n" 241 " from vtkmodules.vtkCommonDataModel import vtkTable, vtkDataSet, vtkPolyData\n" 242 " from vtkmodules import vtkCommonDataModel as dm\n" 243 " input0 = vtkDataSet.GetData(inInfoVec[0], 0)\n" 244 " opt = dm.vtkDataObject.GetData(outInfoVec)\n" 246 " if opt and opt.IsA(input0.GetClassName()):\n" 249 " opt = input0.NewInstance()\n" 250 " outInfoVec.GetInformationObject(0).Set(dm.vtkDataObject.DATA_OBJECT(), opt)\n" 253 " def RequestUpdateExtent(self, request, inInfoVec, outInfoVec):\n" 254 " \"\"\"Override the default algorithm for updating extents to handle the\n" 255 " surface and subsurface models, which have different dimensionality.\n" 257 " Take the requested (downstream) extent and intersect it with the\n" 258 " available (upstream) extents; use that as the request rather than\n" 259 " blindly copying the request upstream.\n" 261 " from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline as sddp\n" 263 " # Determine the port requesting an update from us:\n" 264 " reqPort = request.Get(sddp.FROM_OUTPUT_PORT())\n" 265 " # Get that port's information and the extents it is requesting:\n" 266 " outInfo = self.GetOutputInformation(reqPort)\n" 267 " esrc = outInfo.Get(sddp.UPDATE_EXTENT())\n" 269 " # Slice the extents into tuples holding the lo and hi indices:\n" 270 " losrc = esrc[0:6:2]\n" 271 " hisrc = esrc[1:6:2]\n" 272 " np = self.GetNumberOfInputPorts()\n" 273 " for port in range(np):\n" 274 " # Loop over all the input connections and set their update extents:\n" 275 " nc = self.GetNumberOfInputConnections(port)\n" 276 " for connection in range(nc):\n" 277 " inInfo = self.GetInputInformation(port, connection)\n" 278 " # Set UPDATE_EXTENT to be the intersection of the input\n" 279 " # port's WHOLE_EXTENT with the output port's UPDATE_EXTENT.\n" 281 " # NB/FIXME: Really this is incorrect. If reqPort is 1, then\n" 282 " # someone is asking for an update of the 2-d surface grid\n" 283 " # and they could conceivably need the entire 3-d subsurface\n" 284 " # grid that overlaps the surface grid in x and y...\n" 285 " etgt = inInfo.Get(sddp.WHOLE_EXTENT())\n" 286 " lotgt = etgt[0:6:2]\n" 287 " hitgt = etgt[1:6:2]\n" 288 " lodst = [int(max(x)) for x in zip(losrc, lotgt)]\n" 289 " hidst = [int(min(x)) for x in zip(hisrc, hitgt)]\n" 290 " edst = [val for tup in zip(lodst, hidst) for val in tup]\n" 291 " inInfo.Set(sddp.UPDATE_EXTENT(), tuple(edst), 6)\n" 294 "@smproxy.filter(label='Subsurface Storage')\n" 295 "@smhint.xml(\"\"\"\n" 296 " <ShowInMenu category=\"ParFlow\"/>\n" 297 " <RepresentationType port=\"0\" view=\"RenderView\" type=\"Surface\" />\n" 299 "@smproperty.input(name=\"Subsurface\", port_index=0)\n" 300 "@smdomain.datatype(dataTypes=[\"vtkDataSet\"], composite_data_supported=False)\n" 301 "class SubsurfaceStorage(ParFlowAlgorithm):\n" 302 " \"\"\"This algorithm computes the subsurface storage across the entire domain.\n" 303 " The result is added as field data and marked as time-varying so it\n" 304 " can be plotted as a timeseries.\n" 306 " def __init__(self):\n" 307 " VTKPythonAlgorithmBase.__init__(self, nInputPorts=1, nOutputPorts=1, outputType=\"vtkDataSet\")\n" 309 " def RequestData(self, request, inInfoVec, outInfoVec):\n" 310 " from vtkmodules.vtkCommonDataModel import vtkTable, vtkDataSet, vtkPolyData\n" 311 " from vtkmodules.vtkIOExodus import vtkExodusIIReader as e2r\n" 312 " from vtkmodules.vtkFiltersVerdict import vtkMeshQuality as mq\n" 313 " from vtkmodules.util.numpy_support import vtk_to_numpy as vton\n" 314 " from vtkmodules.util.numpy_support import numpy_to_vtk as ntov\n" 315 " import numpy as np\n" 317 " ## Fetch the filter inputs and outputs:\n" 318 " input0 = vtkDataSet.GetData(inInfoVec[0], 0)\n" 319 " output = vtkDataSet.GetData(outInfoVec, 0)\n" 320 " output.ShallowCopy(input0)\n" 322 " ## Fetch input arrays\n" 323 " cd = output.GetCellData()\n" 324 " vmask = cd.GetArray('mask')\n" 325 " vsaturation = cd.GetArray('saturation')\n" 326 " vporosity = cd.GetArray('porosity')\n" 327 " vpressure = cd.GetArray('pressure')\n" 328 " vspecstor = cd.GetArray('specific storage')\n" 329 " if vmask == None or vsaturation == None or \\\n" 330 " vporosity == None or vpressure == None or \\\n" 331 " vspecstor == None:\n" 332 " print('Error: A required array was not present.')\n" 335 " ## Compute the volume of each cell:\n" 337 " mqf.SetHexQualityMeasureToVolume()\n" 342 " mqf.SetInputDataObject(0, output)\n" 344 " volume = vton(mqf.GetOutputDataObject(0).GetCellData().GetArray('Quality'))\n" 346 " ## Get NumPy versions of each array so we can do arithmetic:\n" 347 " mask = vton(vmask)\n" 348 " saturation = vton(vsaturation)\n" 349 " porosity = vton(vporosity)\n" 350 " pressure = vton(vpressure)\n" 351 " specstor = vton(vspecstor)\n" 353 " ## Compute the subsurface storage as sbs\n" 354 " ## and store it as field data.\n" 355 " sbs = np.sum(pftools.computeSubsurfaceStorage( \\\n" 356 " saturation, pressure, volume, porosity, specstor))\n" 358 " arr.SetName('subsurface storage')\n" 359 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n" 360 " output.GetFieldData().AddArray(arr)\n" 365 "@smproxy.filter(label='Water Table Depth')\n" 366 "@smhint.xml(\"\"\"\n" 367 " <ShowInMenu category=\"ParFlow\"/>\n" 368 " <RepresentationType port=\"0\" view=\"RenderView\" type=\"Surface\" />\n" 370 "@smproperty.input(name=\"Surface\", port_index=1)\n" 371 "@smdomain.datatype(dataTypes=[\"vtkDataSet\"], composite_data_supported=False)\n" 372 "@smproperty.input(name=\"Subsurface\", port_index=0)\n" 373 "@smdomain.datatype(dataTypes=[\"vtkDataSet\"], composite_data_supported=False)\n" 374 "class WaterTableDepth(ParFlowAlgorithm):\n" 375 " \"\"\"This algorithm computes the depth to the water table the domain surface.\n" 377 " def __init__(self):\n" 378 " VTKPythonAlgorithmBase.__init__(self, nInputPorts=2, nOutputPorts=1, outputType=\"vtkDataSet\")\n" 380 " def RequestInformation(self, request, inInfoVec, outInfoVec):\n" 381 " \"\"\"Tell ParaView our output extents match the surface, not the subsurface.\"\"\"\n" 382 " from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline as sddp\n" 384 " iin = inInfoVec[1].GetInformationObject(0)\n" 385 " outInfoVec.GetInformationObject(0).Set(sddp.WHOLE_EXTENT(), iin.Get(sddp.WHOLE_EXTENT()), 6);\n" 388 " def RequestData(self, request, inInfoVec, outInfoVec):\n" 389 " from vtkmodules.vtkCommonDataModel import vtkTable, vtkDataSet, vtkPolyData\n" 390 " from vtkmodules.vtkIOExodus import vtkExodusIIReader as e2r\n" 391 " from vtkmodules.vtkFiltersVerdict import vtkMeshQuality as mq\n" 392 " from vtkmodules.util.numpy_support import vtk_to_numpy as vton\n" 393 " from vtkmodules.util.numpy_support import numpy_to_vtk as ntov\n" 394 " import numpy as np\n" 396 " ## Fetch the filter inputs and outputs:\n" 397 " input0 = vtkDataSet.GetData(inInfoVec[0], 0)\n" 398 " input1 = vtkDataSet.GetData(inInfoVec[1], 0)\n" 399 " output = vtkDataSet.GetData(outInfoVec, 0)\n" 400 " output.ShallowCopy(input1)\n" 402 " ## Fetch input arrays\n" 403 " cd = output.GetCellData()\n" 404 " scd = input0.GetCellData()\n" 405 " vmask = scd.GetArray('mask')\n" 406 " vsaturation = scd.GetArray('saturation')\n" 407 " if vmask == None or vsaturation == None:\n" 408 " print('Error: A required array was not present.')\n" 411 " ## Get NumPy versions of each array so we can do arithmetic:\n" 412 " mask = vton(vmask)\n" 413 " saturation = vton(vsaturation)\n" 415 " ## Find the top surface\n" 416 " ext = pftools.dataCellExtent(input0)\n" 417 " top = pftools.computeTopSurface(ext, mask)\n" 419 " ## Compute the water table depth storage as wtd\n" 420 " ## and store it as cell data.\n" 421 " ps = pftools.dataPointExtent(input0) + (3,)\n" 422 " xx = np.reshape(vton(input0.GetPoints().GetData()), ps)\n" 423 " wtd = pftools.computeWaterTableDepth(top, saturation, xx)\n" 425 " arr.SetName('water table depth')\n" 426 " output.GetCellData().AddArray(arr)\n" 431 "@smproxy.filter(label='Water Balance')\n" 432 "@smhint.xml(\"\"\"\n" 433 " <ShowInMenu category=\"ParFlow\"/>\n" 434 " <RepresentationType port=\"0\" view=\"RenderView\" type=\"Surface\" />\n" 436 "@smproperty.input(name=\"Surface\", port_index=1)\n" 437 "@smdomain.datatype(dataTypes=[\"vtkDataSet\"], composite_data_supported=False)\n" 438 "@smproperty.input(name=\"Subsurface\", port_index=0)\n" 439 "@smdomain.datatype(dataTypes=[\"vtkDataSet\"], composite_data_supported=False)\n" 440 "class WaterBalance(ParFlowAlgorithm):\n" 441 " \"\"\"This algorithm computes the subsurface storage across the entire domain.\n" 442 " The result is added as field data and marked as time-varying so it\n" 443 " can be plotted as a timeseries.\n" 445 " def __init__(self):\n" 446 " VTKPythonAlgorithmBase.__init__(self, nInputPorts=2, nOutputPorts=1, outputType=\"vtkDataSet\")\n" 448 " def RequestData(self, request, inInfoVec, outInfoVec):\n" 449 " from vtkmodules.vtkCommonDataModel import vtkTable, vtkDataSet, vtkPolyData\n" 450 " from vtkmodules.vtkIOExodus import vtkExodusIIReader as e2r\n" 451 " from vtkmodules.vtkFiltersVerdict import vtkMeshQuality as mq\n" 452 " from vtkmodules.util.numpy_support import vtk_to_numpy as vton\n" 453 " from vtkmodules.util.numpy_support import numpy_to_vtk as ntov\n" 454 " import numpy as np\n" 456 " ## Fetch the filter inputs and outputs:\n" 457 " input0 = vtkDataSet.GetData(inInfoVec[0], 0)\n" 458 " input1 = vtkDataSet.GetData(inInfoVec[1], 0)\n" 459 " output = vtkDataSet.GetData(outInfoVec, 0)\n" 460 " output.ShallowCopy(input0)\n" 462 " ## Fetch input arrays\n" 463 " cd = output.GetCellData()\n" 464 " scd = input1.GetCellData()\n" 465 " vmask = cd.GetArray('mask')\n" 466 " vsaturation = cd.GetArray('saturation')\n" 467 " vporosity = cd.GetArray('porosity')\n" 468 " vpressure = cd.GetArray('pressure')\n" 469 " vspecstor = cd.GetArray('specific storage')\n" 470 " vslope = scd.GetArray('slope')\n" 471 " vmannings = scd.GetArray('mannings')\n" 472 " if vmask == None or vsaturation == None or \\\n" 473 " vporosity == None or vpressure == None or \\\n" 474 " vspecstor == None or vslope == None or \\\n" 475 " vmannings == None:\n" 476 " print('Error: A required array was not present.')\n" 479 " ## Compute the volume of each cell:\n" 481 " mqf.SetHexQualityMeasureToVolume()\n" 482 " mqf.SetInputDataObject(0, output)\n" 484 " volume = vton(mqf.GetOutputDataObject(0).GetCellData().GetArray('Quality'))\n" 486 " ## Get NumPy versions of each array so we can do arithmetic:\n" 487 " mask = vton(vmask)\n" 488 " saturation = vton(vsaturation)\n" 489 " porosity = vton(vporosity)\n" 490 " pressure = vton(vpressure)\n" 491 " specstor = vton(vspecstor)\n" 492 " slope = vton(vslope)\n" 493 " mannings = vton(vmannings)\n" 495 " ## Compute the subsurface storage as sbs\n" 496 " ## and store it as field data.\n" 497 " sbs = np.sum(pftools.computeSubsurfaceStorage( \\\n" 498 " saturation, pressure, volume, porosity, specstor))\n" 500 " arr.SetName('subsurface storage')\n" 501 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n" 502 " output.GetFieldData().AddArray(arr)\n" 504 " ## Find the top surface\n" 505 " ext = pftools.dataCellExtent(input0)\n" 506 " top = pftools.computeTopSurface(ext, mask)\n" 507 " itop = pftools.computeTopSurfaceIndices(top)\n" 509 " ## Compute the surface storage\n" 510 " ps = pftools.dataPointExtent(input0) + (3,)\n" 511 " xx = np.reshape(vton(output.GetPoints().GetData()), ps)\n" 512 " sus = np.sum(pftools.computeSurfaceStorage(ext, itop, xx, pressure))\n" 514 " arr.SetName('surface storage')\n" 515 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n" 516 " output.GetFieldData().AddArray(arr)\n" 518 " ## Compute the surface runoff\n" 519 " slope = np.reshape(slope, top.shape + (2,))\n" 520 " mannings = np.reshape(mannings, top.shape)\n" 521 " sro = np.sum(pftools.computeSurfaceRunoff(top, xx, pressure, slope, mannings))\n" 523 " arr.SetName('surface runoff')\n" 524 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n" 525 " output.GetFieldData().AddArray(arr)\n" 529 "if __name__ == \"__main__\":\n" 530 " from paraview.detail.pythonalgorithm import get_plugin_xmls\n" 531 " from xml.dom.minidom import parseString\n" 532 " for xml in get_plugin_xmls(globals()):\n" 533 " dom = parseString(xml)\n" 534 " print(dom.toprettyxml(\" \",\"\\n\"))\n" 545 char* res =
new char[ len + 1];
549 assert(offset == len);
static const char *const module_parflow_parflow_string0
static const char *const module_parflow_parflow_string1
char * module_parflow_parflow_source()