Skip to content

Commit 0da05f1

Browse files
authored
add python script for making vectors in paraview (#4549)
## Summary ## Additional background ## Checklist The proposed changes: - [ ] fix a bug or incorrect behavior in AMReX - [ ] add new capabilities to AMReX - [ ] changes answers in the test suite to more than roundoff level - [ ] are likely to significantly affect the results of downstream AMReX users - [X] include documentation in the code and/or rst files, if appropriate
1 parent a6394da commit 0da05f1

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

Docs/sphinx_documentation/source/Visualization.rst

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,15 +458,33 @@ Plot a Vector Field
458458

459459
Paraview can be used to plot a vector field from AMR plotfile data. In this example
460460
we will assume a single vector has been stored as three separate variables,
461-
``V_x``, ``V_y`` and ``V_z``. The steps below outline a basic construction:
461+
``V_x``, ``V_y`` and ``V_z``.
462462

463-
#. Open a plotfile or plotfile group, using ``File`` :math:`\rightarrow` ``Open``.
463+
The easiest way to create a vector ``V`` from the components is to
464+
first download the python file
465+
:download:`makevector.py </Visualization/makevector.py>`.
466+
467+
If you are running paraview remotely, put ``makevector.py`` in the location
468+
of the plotfiles you will open under the heading ``Remote Plugins``.
469+
470+
#. Now open a plotfile or plotfile group, using ``File`` :math:`\rightarrow` ``Open``.
464471
A pop-up will appear, select "AMReX/Boxlib Grid Reader".
465472

466473
#. Select the plotfile or group in the Pipeline Browser. The Cell Array Status
467474
window of the Properties should populate with the values ``V_x``, ``V_y``
468475
and ``V_z``. Select these values and click apply.
469476

477+
#. Select ``Tools`` :math:`\rightarrow` ``Manage Plugins...`` then choose
478+
``Load New...``. Select ``makevector.py``; after you load it you will see
479+
``makevector`` in the list of plugins.
480+
481+
#. Select the MakeVector filter from ``Filters`` :math:`\rightarrow` ``Alphabetical``
482+
:math:`\rightarrow` ``MakeVector`` and apply. You will now have the vector ``V``
483+
listed with your other variables.
484+
485+
Alternatively, if you prefer not to use the python plugin, you can follow the
486+
steps below:
487+
470488
#. Select the Cell Centers filter from ``Filters`` :math:`\rightarrow` ``Alphabetical``
471489
:math:`\rightarrow` ``Cell Centers`` and apply.
472490

@@ -479,7 +497,9 @@ we will assume a single vector has been stored as three separate variables,
479497
Note that, the values ``V_x``, ``V_y`` and ``V_z``, should be selectable
480498
from the dropdown Scalars menu. Apply the filter.
481499

482-
#. To plot the arrows, select the Glyph filter,
500+
To plot the arrows corresponding to this vector field
501+
502+
#. Select the Glyph filter,
483503
``Filters`` :math:`\rightarrow` ``Alphabetical`` :math:`\rightarrow` ``Glyph``.
484504
Under the heading, Glyph Source, select ``Arrow``. Under Orientation, select
485505
the name of the vector value created in the last step. The default name is
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from paraview.util.vtkAlgorithm import *
2+
3+
@smproxy.filter()
4+
@smproperty.input(name="InputDataset", port_index=0)
5+
@smdomain.datatype(dataTypes=["vtkOverlappingAMR"])
6+
class MakeVector(VTKPythonAlgorithmBase):
7+
def __init__(self):
8+
VTKPythonAlgorithmBase.__init__(self, nInputPorts=1, nOutputPorts=1, outputType="vtkOverlappingAMR", inputType="vtkOverlappingAMR")
9+
10+
def _find_names(self, fields):
11+
# This method uses regular expressions to figure out
12+
# vectors that can be merged. It assumes that the component
13+
# scalars are named as [xyz]name or name[xyz]
14+
import re
15+
array_names = fields.keys()
16+
to_merge = {}
17+
matches = {}
18+
for a in array_names:
19+
grp = re.search(r'^([xyz])[_-]?([\w]*)', a)
20+
if grp:
21+
grp = grp.groups()
22+
if grp[0] and grp[1]:
23+
try:
24+
matches[grp[1]][grp[0]] = a
25+
except KeyError:
26+
matches[grp[1]] = { grp[0] : a }
27+
for a in array_names:
28+
grp = re.search(r'([\w]*)[_-]?([xyz])$', a)
29+
if grp:
30+
grp = grp.groups()
31+
if grp[0] and grp[1]:
32+
try:
33+
matches[grp[0]][grp[1]] = a
34+
except KeyError:
35+
matches[grp[0]] = { grp[1] : a }
36+
for key, value in matches.items():
37+
keys = set(value.keys())
38+
if (len(keys) == 2 or len(keys) == 3) and 'x' in keys \
39+
and 'y' in keys:
40+
try:
41+
to_merge[key] = (value['x'], value['y'], value['z'])
42+
except KeyError:
43+
to_merge[key] = (value['x'], value['y'])
44+
return to_merge
45+
46+
def RequestData(self, request, inInfoVec, outInfoVec):
47+
# These modules are needed for the data model and numpy convenience
48+
# methods.
49+
from vtkmodules.vtkCommonDataModel import vtkOverlappingAMR
50+
from vtkmodules.numpy_interface import dataset_adapter as dsa
51+
from vtkmodules.numpy_interface import algorithms as algs
52+
# Boilerplate code to get the input and output
53+
inp = vtkOverlappingAMR.GetData(inInfoVec[0], 0)
54+
output = vtkOverlappingAMR.GetData(outInfoVec, 0)
55+
56+
# Pass all of the AMR structure and fields to the output.
57+
output.ShallowCopy(inp)
58+
59+
# Create objects that offer convenience APIs that interact
60+
# with numpy.
61+
inp = dsa.WrapDataObject(inp)
62+
output = dsa.WrapDataObject(output)
63+
64+
# Workhorse. Merge all arrays of for [xyz]name and name[xyz] in
65+
# point and cell data
66+
for inp_field, output_field in [(inp.CellData, output.CellData), \
67+
(inp.PointData, output.PointData)]:
68+
# This method find the arrays names that match the criteria
69+
to_merge = self._find_names(inp_field)
70+
for name, arrays in to_merge.items():
71+
if len(arrays) == 2:
72+
# make_vector is really all we need.
73+
output_field.append(
74+
algs.make_vector(inp_field[arrays[0]],
75+
inp_field[arrays[1]]), name)
76+
else:
77+
output_field.append(
78+
algs.make_vector(inp_field[arrays[0]],
79+
inp_field[arrays[1]],
80+
inp_field[arrays[2]]), name)
81+
82+
return 1

0 commit comments

Comments
 (0)