Store data in an ASCII Table#

  • Contributor: Tapashree Pradhan (GitHub profile)

  • DAMASK version: 3.0.2

[1]:
import numpy as np
import damask

Introduction#

This tutorial will demonstrate the use of DAMASK’s Table class to store and manage structured data. For this, we create a table with deformation gradient (\(F\)), second Piola–Kirchhoff stress (\(P\)), and orientation (\(O\)) information, then save it to file and load it back into memory.

One of the key benefits of using DAMASK’s Table class is that it preserves the dimension of the data, e.g. the information that \(F\) is a tensor of shape (3,3). This ensures that complex data such as tensors remain well-organized and can be retrieved without requiring reshaping or additional processing.

Getting data#

Load data from the last increment of a DADF5 file:

  • F: A 4096x3x3 array representing 4096 3x3 deformation gradient tensors

  • P: A 4096x3x3 array representing 4096 3x3 second Piola-Kirchhoff stress tensors

  • O: A 4096x4 array representing 4096 orientations as quaternions

[2]:
r = damask.Result('table_class/20grains16x16x16_tensionX.hdf5').view(increments=-1)
F = r.place('F')
P = r.place('P')
O = r.place('O')

Creating an initial Table#

We initialize an empty Table object and add \(F\) and \(O\) to that.

[3]:
t = damask.Table().set('F', F).set('O', O)
print(f'The table has columns {t.labels} with shapes {t.shapes} and contains\n{t}')
The table has columns ['F', 'O'] with shapes {'F': (3, 3), 'O': (4,)} and contains

         3x3:F         F         F         F         F         F         F  \
0     1.074900 -0.030979 -0.053431 -0.003686  0.933476  0.002005  0.016700
1     1.098802 -0.044958 -0.051170 -0.016674  0.920637 -0.006009  0.004992
2     1.098989  0.006283 -0.020055 -0.025187  0.920903  0.007179 -0.033068
3     1.106572  0.036929  0.034162  0.030394  0.932328 -0.000886 -0.007969
4     1.061430  0.023078  0.029158  0.006881  0.966724 -0.025743 -0.023537
...        ...       ...       ...       ...       ...       ...       ...
4091  1.059206  0.004049 -0.022388  0.014582  0.991471 -0.007827  0.021703
4092  1.117124 -0.014534 -0.014593  0.005108  0.919943 -0.020334  0.026241
4093  1.097042 -0.062004 -0.011108  0.058906  0.929480 -0.036493  0.016269
4094  1.083457 -0.045746 -0.004112  0.041138  0.941743 -0.009534  0.026624
4095  1.098039 -0.034969 -0.003580  0.028668  0.924006  0.000634  0.016954

             F         F       4:O         O         O         O
0    -0.007605  0.995968  0.796230 -0.285316 -0.346687  0.405488
1    -0.004929  0.988960  0.802647 -0.282950 -0.342533  0.397955
2    -0.015176  0.988630  0.810817 -0.269255 -0.322058  0.407869
3    -0.059044  0.970674  0.278609 -0.025514 -0.483566 -0.829391
4    -0.017799  0.975131  0.288227 -0.022573 -0.467561 -0.835346
...        ...       ...       ...       ...       ...       ...
4091 -0.004587  0.952626  0.071757  0.896810 -0.416654  0.130317
4092 -0.007574  0.972937  0.700437 -0.124366 -0.190746  0.676414
4093  0.005774  0.976943  0.683794 -0.114563 -0.200957  0.692038
4094 -0.008468  0.978459  0.687979 -0.123260 -0.193402  0.688541
4095  0.006634  0.984650  0.680783 -0.116550 -0.192622  0.697027

[4096 rows x 13 columns]
[4]:
# Check that the stored `F` values match the original `F` array.
print(f'shape F {F.shape}')
assert (F == t.get('F')).all()
shape F (4096, 3, 3)

Adding additional data#

Using the set method again, we add the stress tensor P to the existing table.

[5]:
t = t.set('P', P)

Save to file#

The resulting Table object can be directly saved to a text file with its save method. In below example, we use output.txt as filename.

[6]:
t.save('output.txt')

Load from file#

Existing ASCII Tables can be loaded from file. As a simple demonstration, let’s load the just saved Table into a new object and interrogate its deformation gradient (F) data. Note that the deformation gradient retains its original 3x3 shape.

[7]:
t_loaded = damask.Table.load('output.txt')
F_loaded = t_loaded.get('F')
print(f'shape F (loaded) {F_loaded.shape}')
shape F (loaded) (4096, 3, 3)
[8]:
# Storing data in ASCII format might lead to rounding errors.
print(f'exactly equal: {(F == F_loaded).all()}')
print(f'close: {np.allclose(F,F_loaded)}')
exactly equal: False
close: True