@@ -91,3 +91,82 @@ from a statepoint file, the ``openmc.statepoint`` module can be used. An
9191`example notebook `_ demontrates how to analyze and plot source information.
9292
9393.. _example notebook : https://nbviewer.jupyter.org/github/openmc-dev/openmc-notebooks/blob/main/post-processing.ipynb
94+
95+ ------------------------
96+ VTK Mesh File Generation
97+ ------------------------
98+
99+ VTK files of OpenMC meshes can be created using the
100+ :meth: `openmc.Mesh.write_data_to_vtk ` method. Data can be applied to the
101+ elements of the resulting mesh from mesh filter objects. This data can be
102+ provided either as a flat array or, in the case of structured meshes
103+ (:class: `~openmc.RegularMesh `, :class: `~openmc.RectilinearMesh `,
104+ :class: `~openmc.CylindricalMesh `, or :class: `SphericalMesh `), the data can be
105+ shaped with dimensions that match the dimensions of the mesh itself.
106+
107+
108+ .. image :: ../_images/sphere-mesh-vtk.png
109+ :width: 400px
110+ :align: center
111+ :alt: OpenMC spherical mesh exported to VTK
112+
113+
114+ For all mesh types, if a flat data array is provided to the mesh, it is expected
115+ that the data is ordered in the same ordering as the :attr: `openmc.Mesh.indices `
116+ for that mesh object. When providing data directly from a tally, as shown below,
117+ a flat array for a given dataset can be passed directly to this method.
118+
119+ ::
120+
121+ # create model above
122+
123+ # create a mesh tally
124+ mesh = openmc.RegularMesh()
125+ mesh.dimension = [10, 20, 30]
126+ mesh.lower_left = [-5, -10, -15]
127+ mesh.upper_right = [5, 10, 15]
128+ mesh_filter = openmc.MeshFilter(mesh)
129+ tally = openmc.Tally()
130+ tally.filters = [mesh_filter]
131+ tally.scores = ['flux']
132+
133+ model.tallies = [tally]
134+ model.run(apply_tally_results=True)
135+
136+ # provide the data as-is to the method
137+ mesh.write_data_to_vtk('flux.vtk', {'flux-mean': tally.mean})
138+
139+ The :class: `~openmc.Tally ` object also provides a way to expand the dimensions
140+ of the mesh filter into a meaningful form where indexing the mesh filter
141+ dimensions results in intuitive slicing of structured meshes by setting
142+ ``expand_dims=True `` when using :meth: `openmc.Tally.get_reshaped_data `. This
143+ reshaping does cause flat indexing of the data to change, however. As noted
144+ above, provided datasets are allowed to be shaped so long as such datasets have
145+ shapes that match the mesh dimensions. The ability to pass datasets in this way
146+ is useful when additional filters are applied to a tally. The example below
147+ demonstrates such a case for tally with both a :class: `~openmc.MeshFilter ` and
148+ :class: `~openmc.EnergyFilter ` applied.
149+
150+ ::
151+
152+ # create model above
153+
154+ # create a mesh tally with energy filter
155+ mesh = openmc.RegularMesh()
156+ mesh.dimension = [10, 20, 30]
157+ mesh.lower_left = [-5, -10, -15]
158+ mesh.upper_right = [5, 10, 15]
159+ mesh_filter = openmc.MeshFilter(mesh)
160+ energy_filter = openmc.EnergyFilter([0.0, 1.0, 20.0e6])
161+ tally = openmc.Tally()
162+ tally.filters = [mesh_filter, energy_filter]
163+ tally.scores = ['flux']
164+
165+ model.tallies = [tally]
166+ model.run(apply_tally_results=True)
167+
168+ # get the data with mesh dimensions expanded, squeeze out length-one dimensions (nuclides, scores)
169+ flux = tally.get_reshaped_data(expand_dims=True).squeeze() # shape: (10, 20, 30, 2)
170+
171+ # write the lowest energy group to a VTK file
172+ mesh.write_data_to_vtk('flux-group1.vtk', datasets={'flux-mean': flux[..., 0]})
0 commit comments