WrappedPython_ParFlow_parflow.h
Go to the documentation of this file.
1 // Loadable modules
2 //
3 // Generated by /builds/gitlab-kitware-sciviz-ci/build/bin/vtkProcessXML-pv6.0
4 //
5 #ifndef WrappedPython_ParFlow_parflow_h
6 #define WrappedPython_ParFlow_parflow_h
7 
8 #include <cstring>
9 #include <cassert>
10 #include <algorithm>
11 
12 
13 // From file /builds/gitlab-kitware-sciviz-ci/Plugins/ParFlow/parflow.py
14 static const char* const module_parflow_parflow_string0 =
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"
19 "\n"
20 "from paraview.util.vtkAlgorithm import *\n"
21 "import numpy as np\n"
22 "\n"
23 "class pftools:\n"
24 " \"\"\"This class defines some utilities to perform computations similar\n"
25 " to those implemented by ParFlow's pftools suite.\"\"\"\n"
26 "\n"
27 " @staticmethod\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"
31 "\n"
32 " Note that VTK normally assumes data is (i,j,k) ordered.\"\"\"\n"
33 " ext = tuple(np.flip(dataset.GetDimensions()))\n"
34 " return ext\n"
35 "\n"
36 " @staticmethod\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"
40 "\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"
46 " return ext\n"
47 "\n"
48 " @staticmethod\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"
63 " return top\n"
64 "\n"
65 " @staticmethod\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"
70 "\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"
73 " \"\"\"\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"
78 " return itop\n"
79 "\n"
80 " @staticmethod\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"
91 " dx = dx[:,0]\n"
92 " dy = dy[:,1]\n"
93 "\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"
97 " return sus\n"
98 "\n"
99 " @staticmethod\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"
104 " return sbs\n"
105 "\n"
106 " @staticmethod\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"
111 " \"\"\"\n"
112 " import numpy as np\n"
113 " sbs = (saturation == 1.0) * volume * (porosity + pressure * specific_storage)\n"
114 " return sbs\n"
115 "\n"
116 " @staticmethod\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"
123 " \"\"\"\n"
124 " # We would like to do this:\n"
125 " # sro += \\\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"
132 " sro[ww] += \\\n"
133 " np.sqrt(np.abs(slope[ww])) / mannings[ww] * \\\n"
134 " np.power(ptop[ww], 5.0/3.0) * delta[ww]\n"
135 "\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"
147 "\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"
150 "\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"
157 "\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"
164 "\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"
167 "\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"
174 "\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"
181 "\n"
182 " return sro\n"
183 "\n"
184 " @staticmethod\n"
185 " def computeWaterTableDepth(top, saturation, xx):\n"
186 " \"\"\"Compute the depth to the water table.\n"
187 "\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"
192 " \"\"\"\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"
205 "\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"
211 " return depth\n"
212 "\n"
213 "class ParFlowAlgorithm(VTKPythonAlgorithmBase):\n"
214 " \"\"\"A base class for algorithms that operate on\n"
215 " ParFlow simulation data.\n"
216 "\n"
217 " This class provides method implementations that\n"
218 " simplify working with data from the vtkParFlowMetaReader.\n"
219 " Specifically,\n"
220 "\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"
228 "\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"
233 " filter.\n"
234 " \"\"\"\n"
235 " def FillInputPortInformation(self, port, info):\n"
236 " info.Set(self.INPUT_REQUIRED_DATA_TYPE(), \"vtkDataSet\")\n"
237 " return 1\n"
238 "\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"
245 "\n"
246 " if opt and opt.IsA(input0.GetClassName()):\n"
247 " return 1\n"
248 "\n"
249 " opt = input0.NewInstance()\n"
250 " outInfoVec.GetInformationObject(0).Set(dm.vtkDataObject.DATA_OBJECT(), opt)\n"
251 " return 1\n"
252 "\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"
256 "\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"
260 " \"\"\"\n"
261 " from vtkmodules.vtkCommonExecutionModel import vtkStreamingDemandDrivenPipeline as sddp\n"
262 "\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"
268 "\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"
280 " #\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"
292 " return 1\n"
293 "\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"
298 "\"\"\")\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"
305 " \"\"\"\n"
306 " def __init__(self):\n"
307 " VTKPythonAlgorithmBase.__init__(self, nInputPorts=1, nOutputPorts=1, outputType=\"vtkDataSet\")\n"
308 "\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"
316 "\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"
321 "\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"
333 " return 0\n"
334 "\n"
335 " ## Compute the volume of each cell:\n"
336 " mqf = mq()\n"
337 " mqf.SetHexQualityMeasureToVolume()\n"
338 ;
339 
340 // From file /builds/gitlab-kitware-sciviz-ci/Plugins/ParFlow/parflow.py
341 static const char* const module_parflow_parflow_string1 =
342 " mqf.SetInputDataObject(0, output)\n"
343 " mqf.Update()\n"
344 " volume = vton(mqf.GetOutputDataObject(0).GetCellData().GetArray('Quality'))\n"
345 "\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"
352 "\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"
357 " arr = ntov(sbs)\n"
358 " arr.SetName('subsurface storage')\n"
359 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n"
360 " output.GetFieldData().AddArray(arr)\n"
361 "\n"
362 " return 1\n"
363 "\n"
364 "\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"
369 "\"\"\")\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"
376 " \"\"\"\n"
377 " def __init__(self):\n"
378 " VTKPythonAlgorithmBase.__init__(self, nInputPorts=2, nOutputPorts=1, outputType=\"vtkDataSet\")\n"
379 "\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"
383 "\n"
384 " iin = inInfoVec[1].GetInformationObject(0)\n"
385 " outInfoVec.GetInformationObject(0).Set(sddp.WHOLE_EXTENT(), iin.Get(sddp.WHOLE_EXTENT()), 6);\n"
386 " return 1\n"
387 "\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"
395 "\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"
401 "\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"
409 " return 0\n"
410 "\n"
411 " ## Get NumPy versions of each array so we can do arithmetic:\n"
412 " mask = vton(vmask)\n"
413 " saturation = vton(vsaturation)\n"
414 "\n"
415 " ## Find the top surface\n"
416 " ext = pftools.dataCellExtent(input0)\n"
417 " top = pftools.computeTopSurface(ext, mask)\n"
418 "\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"
424 " arr = ntov(wtd)\n"
425 " arr.SetName('water table depth')\n"
426 " output.GetCellData().AddArray(arr)\n"
427 "\n"
428 " return 1\n"
429 "\n"
430 "\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"
435 "\"\"\")\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"
444 " \"\"\"\n"
445 " def __init__(self):\n"
446 " VTKPythonAlgorithmBase.__init__(self, nInputPorts=2, nOutputPorts=1, outputType=\"vtkDataSet\")\n"
447 "\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"
455 "\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"
461 "\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"
477 " return 0\n"
478 "\n"
479 " ## Compute the volume of each cell:\n"
480 " mqf = mq()\n"
481 " mqf.SetHexQualityMeasureToVolume()\n"
482 " mqf.SetInputDataObject(0, output)\n"
483 " mqf.Update()\n"
484 " volume = vton(mqf.GetOutputDataObject(0).GetCellData().GetArray('Quality'))\n"
485 "\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"
494 "\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"
499 " arr = ntov(sbs)\n"
500 " arr.SetName('subsurface storage')\n"
501 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n"
502 " output.GetFieldData().AddArray(arr)\n"
503 "\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"
508 "\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"
513 " arr = ntov(sus)\n"
514 " arr.SetName('surface storage')\n"
515 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n"
516 " output.GetFieldData().AddArray(arr)\n"
517 "\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"
522 " arr = ntov(sro)\n"
523 " arr.SetName('surface runoff')\n"
524 " arr.GetInformation().Set(e2r.GLOBAL_TEMPORAL_VARIABLE(), 1)\n"
525 " output.GetFieldData().AddArray(arr)\n"
526 "\n"
527 " return 1\n"
528 "\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"
535 "\n";
536 // Get single string
538 {
539 
540  const size_t len0 = strlen(module_parflow_parflow_string0);
541  const size_t len1 = strlen(module_parflow_parflow_string1);
542  size_t len = ( 0
543  + len0
544  + len1 );
545  char* res = new char[ len + 1];
546  size_t offset = 0;
547  std::copy(module_parflow_parflow_string0, module_parflow_parflow_string0 + len0, res + offset); offset += len0;
548  std::copy(module_parflow_parflow_string1, module_parflow_parflow_string1 + len1, res + offset); offset += len1;
549  assert(offset == len);
550  res[offset] = 0;
551  return res;
552 }
553 
554 
555 
556 #endif
offset
static const char *const module_parflow_parflow_string0
static const char *const module_parflow_parflow_string1
char * module_parflow_parflow_source()