Data types and IO

Import general modules

mpi4py is always required when using these tools. Numpy is always good to have if any manipulation is to be done.

[1]:
# Import required modules
from mpi4py import MPI #equivalent to the use of MPI_init() in C
import matplotlib.pyplot as plt
import numpy as np

# Get mpi info
comm = MPI.COMM_WORLD

Import modules from pysemtools

In this case we will import all the data types that we currently support, as well as io functions that are required to populate them.

[2]:
# Data types
from pysemtools.datatypes.msh import Mesh
from pysemtools.datatypes.coef import Coef
from pysemtools.datatypes.field import Field, FieldRegistry

# Readers
from pysemtools.io.ppymech.neksuite import preadnek, pynekread

# Writers
from pysemtools.io.ppymech.neksuite import pwritenek, pynekwrite

fname_2d = '../data/mixlay0.f00001'
fname_3d = '../data/rbc0.f00001'

Mesh

The mesh object is designed to interact with the coordinates of the SEM domain. It goes without saying then, that if a file is used to initialize the object, it must contain the mesh.

Initializing

The mesh object can be initialized in multiple manners that we have ideantified to be typical when post processing data, here we show some of them.

Initializing an empty object

We can initialize an empty mesh object by just providing the communicator.

Note that at this stage we must indicate if we want to find the connectivity of the points. This is important if later one whishes to average points at element interfaces. Be carefull, however, as it will require more memory.

[3]:
msh_2d = Mesh(comm, create_connectivity=True)
msh_3d = Mesh(comm, create_connectivity=True)
2024-10-04 11:15:26,856 - Mesh - INFO - Initializing empty Mesh object.
2024-10-04 11:15:26,857 - Mesh - INFO - Initializing empty Mesh object.

Initializing from a file

The standard way to initialize the data in a mesh object requires that an empty object is initialized and the the pynekread function is called. This function will take the empty object and read only the data containing the mesh.

One must give the name and the empty object that will hold the data. Aditionally, the type of the data is an input.

[4]:
pynekread(fname_2d, comm, data_dtype=np.double, msh=msh_2d)
pynekread(fname_3d, comm, data_dtype=np.single, msh=msh_3d)
2024-10-04 11:15:26,868 - pynekread - INFO - Reading file: ../data/mixlay0.f00001
2024-10-04 11:15:26,875 - Mesh - INFO - Initializing Mesh object from x,y,z ndarrays.
2024-10-04 11:15:26,876 - Mesh - INFO - Initializing common attributes.
2024-10-04 11:15:26,877 - Mesh - INFO - Getting vertices
2024-10-04 11:15:26,878 - Mesh - INFO - Getting edge centers
2024-10-04 11:15:26,886 - Mesh - INFO - Facet centers not available for 2D
2024-10-04 11:15:26,887 - Mesh - INFO - Creating connectivity
2024-10-04 11:15:27,254 - Mesh - INFO - Mesh object initialized.
2024-10-04 11:15:27,255 - Mesh - INFO - Mesh data is of type: float64
2024-10-04 11:15:27,256 - Mesh - INFO - Elapsed time: 0.380877588s
2024-10-04 11:15:27,257 - pynekread - INFO - File read
2024-10-04 11:15:27,258 - pynekread - INFO - Elapsed time: 0.38954081s
2024-10-04 11:15:27,259 - pynekread - INFO - Reading file: ../data/rbc0.f00001
2024-10-04 11:15:27,264 - Mesh - INFO - Initializing Mesh object from x,y,z ndarrays.
2024-10-04 11:15:27,265 - Mesh - INFO - Initializing common attributes.
2024-10-04 11:15:27,265 - Mesh - INFO - Getting vertices
2024-10-04 11:15:27,266 - Mesh - INFO - Getting edge centers
2024-10-04 11:15:27,273 - Mesh - INFO - Getting facet centers
2024-10-04 11:15:27,279 - Mesh - INFO - Creating connectivity
2024-10-04 11:15:27,681 - Mesh - INFO - Mesh object initialized.
2024-10-04 11:15:27,682 - Mesh - INFO - Mesh data is of type: float32
2024-10-04 11:15:27,683 - Mesh - INFO - Elapsed time: 0.419004522s
2024-10-04 11:15:27,684 - pynekread - INFO - File read
2024-10-04 11:15:27,684 - pynekread - INFO - Elapsed time: 0.42567180499999996s

Initializing from a hexadata object.

We have previously use the module pymech to post process data. Because of this we wrote io routines that produce objects of this type, in case some existing workflows already rely on that. We note that this is parallel and each rank will have a hexadata object with a portion of the total data.

Note that in our implementation, the hexadata object will always read the full file.

In general, this should not be the main way to initialize objects. But we give the option.

The steps that we follow to initialize are the following:

  1. Read the hexadata object.

  2. Initialize the mesh object from it

[5]:
# 1.
data_2d = preadnek(fname_2d, comm, data_dtype=np.double)
data_3d = preadnek(fname_3d, comm, data_dtype=np.single)
# 2.
msh_2d = Mesh(comm, data=data_2d, create_connectivity=True)
msh_3d = Mesh(comm, data=data_3d, create_connectivity=True)
2024-10-04 11:15:27,693 - preadnek - INFO - Reading file: ../data/mixlay0.f00001
2024-10-04 11:15:27,767 - preadnek - INFO - Elapsed time: 0.07367152700000001s
2024-10-04 11:15:27,768 - preadnek - INFO - Reading file: ../data/rbc0.f00001
2024-10-04 11:15:27,803 - preadnek - INFO - Elapsed time: 0.034677242s
2024-10-04 11:15:27,804 - Mesh - INFO - Initializing Mesh object from HexaData object.
2024-10-04 11:15:27,811 - Mesh - INFO - Initializing common attributes.
2024-10-04 11:15:27,811 - Mesh - INFO - Getting vertices
2024-10-04 11:15:27,812 - Mesh - INFO - Getting edge centers
2024-10-04 11:15:27,818 - Mesh - INFO - Facet centers not available for 2D
2024-10-04 11:15:27,819 - Mesh - INFO - Creating connectivity
2024-10-04 11:15:28,163 - Mesh - INFO - Mesh object initialized.
2024-10-04 11:15:28,163 - Mesh - INFO - Mesh data is of type: float64
2024-10-04 11:15:28,164 - Mesh - INFO - Elapsed time: 0.360178777s
2024-10-04 11:15:28,171 - Mesh - INFO - Initializing Mesh object from HexaData object.
2024-10-04 11:15:28,175 - Mesh - INFO - Initializing common attributes.
2024-10-04 11:15:28,176 - Mesh - INFO - Getting vertices
2024-10-04 11:15:28,177 - Mesh - INFO - Getting edge centers
2024-10-04 11:15:28,186 - Mesh - INFO - Getting facet centers
2024-10-04 11:15:28,192 - Mesh - INFO - Creating connectivity
2024-10-04 11:15:28,572 - Mesh - INFO - Mesh object initialized.
2024-10-04 11:15:28,573 - Mesh - INFO - Mesh data is of type: float32
2024-10-04 11:15:28,573 - Mesh - INFO - Elapsed time: 0.40260753000000005s

Initializing from an ndarray

In some instances, one might create the SEM coordinates directly in python. If that is the case, starting directly from the coordinates as an array is also a possibility. One would first create an empty object and the initialize from coordinates as follow:

[6]:
# 1.Copy the coordinates from before just to show

x = msh_3d.x.copy().astype(np.float64)
y = msh_3d.y.copy().astype(np.float64)
z = msh_3d.z.copy().astype(np.float64)

# 2.Initialize a new mesh object
msh_3d_sub = Mesh(comm, create_connectivity=True)
msh_3d_sub.init_from_coords(comm, x=x, y=y, z=z)
2024-10-04 11:15:28,593 - Mesh - INFO - Initializing empty Mesh object.
2024-10-04 11:15:28,594 - Mesh - INFO - Initializing Mesh object from x,y,z ndarrays.
2024-10-04 11:15:28,595 - Mesh - INFO - Initializing common attributes.
2024-10-04 11:15:28,596 - Mesh - INFO - Getting vertices
2024-10-04 11:15:28,597 - Mesh - INFO - Getting edge centers
2024-10-04 11:15:28,608 - Mesh - INFO - Getting facet centers
2024-10-04 11:15:28,616 - Mesh - INFO - Creating connectivity
2024-10-04 11:15:29,080 - Mesh - INFO - Mesh object initialized.
2024-10-04 11:15:29,081 - Mesh - INFO - Mesh data is of type: float64
2024-10-04 11:15:29,081 - Mesh - INFO - Elapsed time: 0.48709318999999995s

In this case, just to show a simple manipulation, we casted the arrays from single to double precision

Coef

The coef object holds the jacobian matrix components, mass matrix and routines to perform derivatives and integrals in the SEM mesh. It is always initialized from a mesh object.

One aditional option for 3D meshes is to also obtain integration weights for the area of the facets in the SEM mesh. If you do not need it, do not activate it, as this takes some extra time and requires extra memory.

The data type of the coef object attributes will match the type of the mesh object.

[7]:
coef_2d = Coef(msh_2d, comm, get_area=True)
coef_3d = Coef(msh_3d, comm, get_area=True)
2024-10-04 11:15:29,091 - Coef - INFO - Initializing Coef object
2024-10-04 11:15:29,092 - Coef - INFO - Getting derivative matrices
2024-10-04 11:15:29,094 - Coef - INFO - Calculating the components of the jacobian
2024-10-04 11:15:29,110 - Coef - INFO - Calculating the jacobian determinant and inverse of the jacobian matrix
2024-10-04 11:15:29,113 - Coef - INFO - Calculating the mass matrix
2024-10-04 11:15:29,114 - Coef - INFO - Coef object initialized
2024-10-04 11:15:29,114 - Coef - INFO - Coef data is of type: float64
2024-10-04 11:15:29,114 - Coef - INFO - Elapsed time: 0.023606959999999955s
2024-10-04 11:15:29,116 - Coef - INFO - Initializing Coef object
2024-10-04 11:15:29,117 - Coef - INFO - Getting derivative matrices
2024-10-04 11:15:29,121 - Coef - INFO - Calculating the components of the jacobian
2024-10-04 11:15:29,222 - Coef - INFO - Calculating the jacobian determinant and inverse of the jacobian matrix
2024-10-04 11:15:29,234 - Coef - INFO - Calculating the mass matrix
2024-10-04 11:15:29,235 - Coef - INFO - Calculating area weights and normal vectors
2024-10-04 11:15:29,255 - Coef - INFO - Coef object initialized
2024-10-04 11:15:29,256 - Coef - INFO - Coef data is of type: float32
2024-10-04 11:15:29,256 - Coef - INFO - Elapsed time: 0.14061485299999976s

Field

The field object is designed to hold the data from SEM fields in a way that intefacing to a nek5000 binary file is easily achieved.

The initialization can be done in similar ways as the mesh, i.e., by using hexadata and the pynekread routine.

Initializing

Initializing an empty object.

We follow the same procedure to initialize an empty object.

[8]:
fld_2d = Field(comm)
fld_3d = Field(comm)
2024-10-04 11:15:29,263 - Field - INFO - Initializing empty Field object
2024-10-04 11:15:29,265 - Field - INFO - Initializing empty Field object

Initializing from a file

Using the pynekread routine, one can follow the same procedure. In this case, if only the fld file is indicated as input, the mesh in the file will not be read

[9]:
pynekread(fname_2d, comm, data_dtype=np.double, fld=fld_2d)
pynekread(fname_3d, comm, data_dtype=np.single, fld=fld_3d)
2024-10-04 11:15:29,275 - pynekread - INFO - Reading file: ../data/mixlay0.f00001
2024-10-04 11:15:29,277 - pynekread - INFO - Reading field data
2024-10-04 11:15:29,282 - pynekread - INFO - File read
2024-10-04 11:15:29,283 - pynekread - INFO - Elapsed time: 0.007930652000000205s
2024-10-04 11:15:29,285 - pynekread - INFO - Reading file: ../data/rbc0.f00001
2024-10-04 11:15:29,287 - pynekread - INFO - Reading field data
2024-10-04 11:15:29,295 - pynekread - INFO - File read
2024-10-04 11:15:29,295 - pynekread - INFO - Elapsed time: 0.010863174999999892s

Note that you can read both mesh and fields with pynekread if you specify both keywords, i.e, msh= and fld=

Initializing from hexadata

Just as for the mesh, the same interface is valid.

[10]:
# 1.
data_2d = preadnek(fname_2d, comm, data_dtype=np.double)
data_3d = preadnek(fname_3d, comm, data_dtype=np.single)
# 2.
fld_2d = Field(comm, data=data_2d)
fld_3d = Field(comm, data=data_3d)
2024-10-04 11:15:29,304 - preadnek - INFO - Reading file: ../data/mixlay0.f00001
2024-10-04 11:15:29,451 - preadnek - INFO - Elapsed time: 0.1472354819999997s
2024-10-04 11:15:29,455 - preadnek - INFO - Reading file: ../data/rbc0.f00001
2024-10-04 11:15:29,491 - preadnek - INFO - Elapsed time: 0.035575633000000106s
2024-10-04 11:15:29,493 - Field - INFO - Initializing Field object from HexaData
2024-10-04 11:15:29,508 - Field - INFO - Field object initialized
2024-10-04 11:15:29,509 - Field - INFO - Elapsed time: 0.015144010000000208s
2024-10-04 11:15:29,509 - Field - INFO - Initializing Field object from HexaData
2024-10-04 11:15:29,515 - Field - INFO - Field object initialized
2024-10-04 11:15:29,515 - Field - INFO - Elapsed time: 0.006332111999999945s

The field object contains all the information in a subdirectory called fields that is divided into the conventions of a nek5000 binary format.

The keywords are:

[11]:
for key in fld_2d.fields.keys():
    print(f'{key} has {len(fld_2d.fields[key])} fields')

print('=================')

for key in fld_3d.fields.keys():
    print(f'{key} has {len(fld_3d.fields[key])} fields')
vel has 2 fields
pres has 1 fields
temp has 1 fields
scal has 2 fields
=================
vel has 3 fields
pres has 1 fields
temp has 1 fields
scal has 0 fields

Each keword has a list of fields depending on the contents of the file. Note how the 2 files that we test here have different information.

To access the content of the files, one can do something like this:

[12]:
u = fld_3d.fields['vel'][0]
v = fld_3d.fields['vel'][1]
w = fld_3d.fields['vel'][2]
p = fld_3d.fields['pres'][0]
t = fld_3d.fields['temp'][0]

If one wishes to add new data, it is as simple as appending arrays to any of the keys of the field object. Given that nek5000 readers follow certain logic, it is always safer to add new data to the scalars, unless one wishes to overwrite velocity, pressure, and/or temperature.

For example, we can add the velocity magnitude as a scalar with:

[13]:
mag = np.sqrt(u**2 + v**2 + w**2)
fld_3d.fields['scal'].append(mag)
fld_3d.update_vars()

If one adds new data, it is needed that one calls the update_vars method to update the attributes that keep track of the number of fields in the field object. This is needed, for example, if one wishes to write data to disk.

Writing out data

Writing the data out always needs a mesh and field object, even if one does not wish to write the mesh out.

The procedure is as simple as follows:

[14]:
fname_out = '../data/out_rbc0.f00001'

pynekwrite(fname_out, comm, msh=msh_3d, fld=fld_3d, write_mesh=True, wdsz=4)
2024-10-04 11:15:29,554 - pynekwrite - INFO - Writing file: ../data/out_rbc0.f00001
2024-10-04 11:15:29,565 - pynekwrite - INFO - Elapsed time: 0.010662473000000006s

Field registry

The field registry is a class that extends the field class. We believe this is the class that should be used instead of fields, as it allows to do the same things, but with some extra flexibility.

The methods to initialize it and write data with it are the same. It also contains the fields attribute with a list of the present fields.

It however, has an additional registry attribute that names and points to each field.

[15]:
fld_3d_r = FieldRegistry(comm)
pynekread(fname_3d, comm, data_dtype=np.single, fld=fld_3d_r)
2024-10-04 11:15:29,575 - Field - INFO - Initializing empty Field object
2024-10-04 11:15:29,577 - pynekread - INFO - Reading file: ../data/rbc0.f00001
2024-10-04 11:15:29,579 - pynekread - INFO - Reading field data
2024-10-04 11:15:29,582 - pynekread - INFO - File read
2024-10-04 11:15:29,584 - pynekread - INFO - Elapsed time: 0.006489980999999645s
[16]:
for key in fld_3d_r.registry.keys():
    print(f'{key} has {fld_3d_r.registry[key].dtype} dtype')
u has float32 dtype
v has float32 dtype
w has float32 dtype
p has float32 dtype
t has float32 dtype

Note that all the fields that have been adressed as indices in a list have now been assigned names.

Adding new fields

From memory

Adding new fields can now also been done very easy as well. Here we can add a new field named mag that is the velocity magnitude calculated earlier.

This field will be added as an scalar to the fields attribute.

[17]:
fld_3d_r.add_field(comm, field_name='mag', field=mag, dtype=mag.dtype)
print(f'Field mag added to registry and fields directory in pos {fld_3d_r.registry_pos["mag"]}')
Field mag added to registry and fields directory in pos scal_0

From disk

You can also just read one field from a file, which reduces the memory footprint.

The procesude is shown below, note that here we know that we have written the field mag as an scalar.

[18]:
fld_3d_r.add_field(comm, field_name='mag_r', file_name=fname_out, file_type='fld', file_key='scal_0', dtype=mag.dtype)
print(f'Field mag_r added to registry and fields directory in pos {fld_3d_r.registry_pos["mag_r"]}')
2024-10-04 11:15:29,613 - pynekread_field - INFO - Reading field: scal_0 from file: ../data/out_rbc0.f00001
2024-10-04 11:15:29,624 - pynekread_field - INFO - File read
2024-10-04 11:15:29,629 - pynekread_field - INFO - Elapsed time: 0.016024912999999863s
Field mag_r added to registry and fields directory in pos scal_1

Let’s compare the field that we previously wrote with the one we calculated

[19]:
eq = np.allclose(fld_3d_r.registry['mag'], fld_3d_r.registry['mag_r'])
print(eq)
True

In our implementation, each member of the registry is linked to a member of the lists contained in the fields attribute.

For the link to be mantained, we must modify the registry in place, not reassing fields to it.

If you would like to replace an entry in the field registry, then use the add field method with the same key

Lets experiment adding a field full of ones. Based on the order of our operations, we know it is stored in scal 2. You can also check the registry_pos attribute:

[20]:
fld_3d_r.add_field(comm, field_name='ones', field=np.ones_like(mag), dtype=mag.dtype)
print(fld_3d_r.registry_pos['ones'])
print(fld_3d_r.registry['ones'][100,0,:,:])
print(fld_3d_r.fields['scal'][2][100,0,:,:])
scal_2
[[1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]]
[[1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1.]]

If I modify the registry, the list is modified:

[21]:
fld_3d_r.registry['ones'][100,0,:,:] = 2.0
print(fld_3d_r.fields['scal'][2][100,0,:,:])
[[2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]
 [2. 2. 2. 2. 2. 2. 2. 2.]]

The same happens in the opposite direction

[22]:
fld_3d_r.fields['scal'][2][100,0,:,:] = 3.0
print(fld_3d_r.registry['ones'][100,0,:,:])
[[3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3. 3. 3. 3.]]

However if you try to assing a field directly to the registry, you will get an error:

[23]:
zeros = np.zeros_like(mag)

try:
    fld_3d_r.registry['ones'] = zeros
except KeyError as e:
    print(e)
"Key 'ones' already exists. Cannot overwrite existing array without the add field method"

But see that if you add the field again with the proper method, then it should work as you want

[24]:
fld_3d_r.add_field(comm, field_name='ones', field=zeros, dtype=zeros.dtype)
print(fld_3d_r.fields['scal'][2][100,0,:,:])
2024-10-04 11:15:29,750 - Field - WARNING - Field ones already in registry. Overwriting
[[0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0.]]

Wrappers

In the event that all you want is a numpy array with the data, you can also use a wrapper to retrieve the data.

[25]:
from pysemtools.io.wrappers import read_data

data = read_data(comm, fname_out, ["x", "y", "z", "scal_0"], dtype = np.single)
2024-10-04 11:15:29,791 - Field - INFO - Initializing empty Field object
2024-10-04 11:15:29,792 - Mesh - INFO - Initializing empty Mesh object.
2024-10-04 11:15:29,792 - pynekread - INFO - Reading file: ../data/out_rbc0.f00001
2024-10-04 11:15:29,797 - Mesh - INFO - Initializing Mesh object from x,y,z ndarrays.
2024-10-04 11:15:29,798 - Mesh - INFO - Initializing common attributes.
2024-10-04 11:15:29,798 - Mesh - INFO - Getting vertices
2024-10-04 11:15:29,799 - Mesh - INFO - Getting edge centers
2024-10-04 11:15:29,810 - Mesh - INFO - Getting facet centers
2024-10-04 11:15:29,817 - Mesh - INFO - Creating connectivity
2024-10-04 11:15:30,204 - Mesh - INFO - Mesh object initialized.
2024-10-04 11:15:30,205 - Mesh - INFO - Mesh data is of type: float32
2024-10-04 11:15:30,206 - Mesh - INFO - Elapsed time: 0.40879251299999986s
2024-10-04 11:15:30,207 - pynekread - INFO - File read
2024-10-04 11:15:30,207 - pynekread - INFO - Elapsed time: 0.4150390530000001s
2024-10-04 11:15:30,209 - pynekread_field - INFO - Reading field: scal_0 from file: ../data/out_rbc0.f00001
2024-10-04 11:15:30,212 - pynekread_field - INFO - File read
2024-10-04 11:15:30,212 - pynekread_field - INFO - Elapsed time: 0.003471009999999719s

data is a dictionary that contains the data of the keys that were given.

[26]:
print(np.allclose(data["x"], msh_3d.x))
print(np.allclose(data["y"], msh_3d.y))
print(np.allclose(data["z"], msh_3d.z))
print(np.allclose(data["scal_0"], fld_3d_r.registry['mag_r']))
True
True
True
True

Inspecting memory usage

To inspect the memory usage, one can use the monitoring module

[27]:
from pysemtools.monitoring.memory_monitor import MemoryMonitor

mm = MemoryMonitor()

You can chose to inspect the total memory used, or check the ussage of each attibute.

[28]:
mm.object_memory_usage(comm, msh_3d, "mesh_3d", print_msg=False)
mm.object_memory_usage_per_attribute(comm, msh_3d, "mesh_3d", print_msg=False)

mm.object_memory_usage(comm, coef_3d, "coef_3d", print_msg=False)
mm.object_memory_usage_per_attribute(comm, coef_3d, "coef_3d", print_msg=False)

mm.object_memory_usage(comm, fld_3d_r, "fld_3d", print_msg=False)
mm.object_memory_usage_per_attribute(comm, fld_3d_r, "fld_3d", print_msg=False)

Report

Report the information.

Note that for field registry objects, the information of registry and field will appear as duplicate. We have seen howeverm that they point to the sampe places in memory, therefore no need to worry about memory duplication.

[29]:
if comm.Get_rank() == 0:
    for key in mm.object_report.keys():
        mm.report_object_information(comm, key)
        print('===================================')

Rank: 0 - Memory usage of mesh_3d: 25.399681091308594 MB
Rank: 0 - Memory usage of mesh_3d attributes:
Rank: 0 - Memory usage of mesh_3d attr - coord_hash_to_shared_map: 21.699501037597656 MB
Rank: 0 - Memory usage of mesh_3d attr - create_connectivity_bool: 3.0517578125e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - edge_centers: 0.082550048828125 MB
Rank: 0 - Memory usage of mesh_3d attr - facet_centers: 0.041351318359375 MB
Rank: 0 - Memory usage of mesh_3d attr - gdim: 3.0517578125e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - glb_nelv: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - global_element_number: 0.004730224609375 MB
Rank: 0 - Memory usage of mesh_3d attr - lx: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - lxyz: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - ly: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - lz: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - nelv: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - offset_el: 4.57763671875e-05 MB
Rank: 0 - Memory usage of mesh_3d attr - vertices: 0.055084228515625 MB
Rank: 0 - Memory usage of mesh_3d attr - x: 1.172027587890625 MB
Rank: 0 - Memory usage of mesh_3d attr - y: 1.172027587890625 MB
Rank: 0 - Memory usage of mesh_3d attr - z: 1.172027587890625 MB
===================================
Rank: 0 - Memory usage of coef_3d: 26.96227264404297 MB
Rank: 0 - Memory usage of coef_3d attributes:
Rank: 0 - Memory usage of coef_3d attr - B: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - apply_1d_operators: 3.0517578125e-05 MB
Rank: 0 - Memory usage of coef_3d attr - area: 0.879058837890625 MB
Rank: 0 - Memory usage of coef_3d attr - dn: 0.000396728515625 MB
Rank: 0 - Memory usage of coef_3d attr - dr: 0.000396728515625 MB
Rank: 0 - Memory usage of coef_3d attr - drdx: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - drdy: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - drdz: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - ds: 0.000396728515625 MB
Rank: 0 - Memory usage of coef_3d attr - dsdx: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dsdy: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dsdz: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dt: 0.000396728515625 MB
Rank: 0 - Memory usage of coef_3d attr - dtdx: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dtdy: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dtdz: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dtype: 0.00011444091796875 MB
Rank: 0 - Memory usage of coef_3d attr - dxdr: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dxds: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dxdt: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dydr: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dyds: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dydt: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dzdr: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dzds: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - dzdt: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - gdim: 3.0517578125e-05 MB
Rank: 0 - Memory usage of coef_3d attr - jac: 1.172027587890625 MB
Rank: 0 - Memory usage of coef_3d attr - nx: 0.879058837890625 MB
Rank: 0 - Memory usage of coef_3d attr - ny: 0.879058837890625 MB
Rank: 0 - Memory usage of coef_3d attr - nz: 0.879058837890625 MB
Rank: 0 - Memory usage of coef_3d attr - v: 0.000396728515625 MB
Rank: 0 - Memory usage of coef_3d attr - vinv: 0.000396728515625 MB
Rank: 0 - Memory usage of coef_3d attr - w: 0.0004119873046875 MB
Rank: 0 - Memory usage of coef_3d attr - w3: 0.002105712890625 MB
Rank: 0 - Memory usage of coef_3d attr - x: 0.0004119873046875 MB
===================================
Rank: 0 - Memory usage of fld_3d: 18.75537109375 MB
Rank: 0 - Memory usage of fld_3d attributes:
Rank: 0 - Memory usage of fld_3d attr - fields: 9.376884460449219 MB
Rank: 0 - Memory usage of fld_3d attr - pres_fields: 3.0517578125e-05 MB
Rank: 0 - Memory usage of fld_3d attr - registry: 9.376899719238281 MB
Rank: 0 - Memory usage of fld_3d attr - registry_pos: 0.00119781494140625 MB
Rank: 0 - Memory usage of fld_3d attr - scal_fields: 3.0517578125e-05 MB
Rank: 0 - Memory usage of fld_3d attr - scal_fields_names: 0.000244140625 MB
Rank: 0 - Memory usage of fld_3d attr - t: 2.288818359375e-05 MB
Rank: 0 - Memory usage of fld_3d attr - temp_fields: 3.0517578125e-05 MB
Rank: 0 - Memory usage of fld_3d attr - vel_fields: 3.0517578125e-05 MB
===================================