Commit ed09817e authored by Moreland, Ken's avatar Moreland, Ken
Browse files

Add a Jupyter notebook to convert LAMMPS Atom to VTK

The problem with LAMMPS Atom format is that it is a text format
that has a bunch of concatinated timesteps. Both the LAMMPS
and VisIt/ParaView readers read through a bunch of the file to
get to a small portion of it. To make it easier/faster to
go through timesteps of the data, I am converting them to a
group of legacy VTK files. I am also generating a ParaView
series file so that the timesteps are preserved.
parent bd54b30a
Loading
Loading
Loading
Loading
+153 −0
Original line number Diff line number Diff line
%% Cell type:markdown id:296bffef-9245-4144-b96f-7c86dd250fd2 tags:

Load VTK module.

%% Cell type:code id:a870c2d3-261c-484f-a82e-e21057e950cb tags:

``` python
import sys
sys.version
```

%% Output

    '3.11.4 (main, Jul  5 2023, 08:41:25) [Clang 14.0.6 ]'

%% Cell type:code id:f3a3f2e9-1a0d-45ae-9d58-9e8734b209f7 tags:

``` python
import sys
sys.path.append('/Users/4d5/builds/VTK/Debug/lib/python3.11/site-packages')
import vtk
```

%% Cell type:markdown id:f72ad50b-3132-46e9-9a11-a56f9d0799e6 tags:

Create an object that can read in text LAMMPS atom files and convert them to VTK objects.

%% Cell type:code id:0a559e46-13bb-470c-bbd9-b242c9c9a29d tags:

``` python
class LammpsAtomLoadBase:
    def __init__(self, filename):
        self._file = open(filename, 'r')

    def _lerp_coord(self, x, index):
        return (float(x) * self._coord_scales[index] +
                self._coord_offsets[index])

    def read_next_timestep(self):
        import re
        self.timestep = None
        self.number_of_atoms = None
        self._coord_offsets = None
        self._coord_scales = None
        while True:
            line = self._file.readline().strip()
            if line == 'ITEM: TIMESTEP':
                self.timestep = int(self._file.readline())
            elif line == 'ITEM: NUMBER OF ATOMS':
                self.number_of_atoms = int(self._file.readline())
            elif line == 'ITEM: BOX BOUNDS pp pp ff':  # Only valid for case from PSI code
                self._coord_offsets = []
                self._coord_scales = []
                for i in range(3):
                    bounds = self._file.readline().split()
                    min = float(bounds[0])
                    max = float(bounds[1])
                    self._coord_offsets.append(min)
                    self._coord_scales.append(max - min)
            elif line == 'ITEM: ATOMS id type xs ys zs':
                if not self.number_of_atoms:
                    raise RuntimeError(
                        'ITEM: NUMBER OF ATOMS not encountered.')
                if not self._coord_offsets:
                    raise RuntimeError(
                        'ITEM: BOX BOUNDS not encountered.')
                self._initialize_data()
                for i in range(self.number_of_atoms):
                    fieldvalues = self._file.readline().split()
                    fields = {}
                    fields['id'] = int(fieldvalues[0])
                    fields['type'] = int(fieldvalues[1])
                    coords = [ self._lerp_coord(fieldvalues[2], 0),
                               self._lerp_coord(fieldvalues[3], 1),
                               self._lerp_coord(fieldvalues[4], 2),
                             ]
                    self._add_data(coords, fields)
                self._finalize_data()
                return True
            elif line == '':
                return False
            else:
                raise RuntimeError(
                    'Unknown line encountered: `{}`'.format(line))

class LammpsAtomLoadVTK(LammpsAtomLoadBase):
    def __init__(self, filename):
        LammpsAtomLoadBase.__init__(self, filename)

    def _initialize_data(self):
        self._points = vtk.vtkPoints()
        self._points.Allocate(self.number_of_atoms)
        self._type_array = vtk.vtkSignedCharArray()
        self._type_array.SetName('type')
        self._type_array.SetNumberOfComponents(1)
        self._type_array.Allocate(self.number_of_atoms)
        self._id_array = vtk.vtkIntArray()
        self._id_array.SetName('id')
        self._id_array.SetNumberOfComponents(1)
        self._id_array.Allocate(self.number_of_atoms)

    def _add_data(self, coords, fields):
        self._points.InsertNextPoint(coords)
        self._type_array.InsertNextValue(fields['type'])
        self._id_array.InsertNextValue(fields['id'])

    def _finalize_data(self):
        self.data = vtk.vtkUnstructuredGrid()
        self.data.SetPoints(self._points)
        self.data.GetPointData().AddArray(self._type_array)
        self.data.GetPointData().AddArray(self._id_array)
```

%% Cell type:code id:521be01e-c970-45c1-b851-ad97026e4a85 tags:

``` python
loader = LammpsAtomLoadVTK(
    '/Users/4d5/data/PSI/karl-hammond-2023/110-25x25nm/dump.110-25x25nm')
```

%% Cell type:code id:26cbe0a8-cc84-4440-9d2e-0ce15295faff tags:

``` python
targetdir = '/Users/4d5/Downloads/'
targetname = '110-25x25nm'
series_file = open(targetdir + targetname + '.vtk.series', 'w')
series_file.write('{\n')
series_file.write('  "file-series-version" : "1.0",\n')
series_file.write('  "files" : [\n')
while loader.read_next_timestep():
    print('.', end='', flush=True)
    vtkfilename = '{}{:06}.vtk'.format(targetname, loader.timestep)
    writer = vtk.vtkDataSetWriter()
    writer.SetFileTypeToBinary()
    writer.SetFileName(targetdir + vtkfilename)
    writer.SetInputData(loader.data)
    writer.Write()
    series_file.write(
        '    {{ "name" : "{}", "time" : {} }},\n'.format(
            vtkfilename, loader.timestep))
series_file.write('  ]\n')
series_file.write('}\n')
series_file.close()
```

%% Output

    ...................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

%% Cell type:code id:27f94099-5e0c-4e58-801c-713822958559 tags:

``` python
```