Writing NETCDF Using Python

VisIt's NETCDF reader supports various flavors of NETCDF and the basic reader which is used when output from a specific code cannot be identified supports some of the most common conventions.

Writing Rectilinear Meshes

This code takes advantage of rectilinear grid support in VisIt's basic NETCDF reader in order to write rectilinear meshes with non-uniform cell sizes.

from numpy import shape
from Scientific.IO.NetCDF import NetCDFFile
import numpy as np

# Write a variable with rectilinear coordinates to NETCDF.
def write_rectilinear(file, var, varname, x_coord, y_coord):
    nx = len(x_coord)
    ny = len(y_coord)

    # Reshape for 2D
    my_data = np.reshape(var,(ny,nx),'F')

    # Create dimensions:
    file.createDimension('nx', nx)
    file.createDimension('ny', ny)

    x = file.createVariable('nx', 'd', ('nx',))
    y = file.createVariable('ny', 'd', ('ny',))

    # transfer the coordinate variables:
    x[:] = x_coord
    y[:] = y_coord

    # Create data variable in NetCDF.
    data = file.createVariable(varname, 'd', ('ny','nx'))

    # transfer the data variables:
    data[:] = my_data


# coordinate information:
x_coord = [0,2,4,6,8,10,12] 
y_coord = [0, 5, 10]

# number of points:
nx = len(x_coord)
ny = len(y_coord)

# Create a nodal data variable
nodal = []
for i in range(nx):
    for j in range(ny):
        nodal = nodal + [j*nx + i]

# Write the file.
file = NetCDFFile('rectilinear.nc', 'w')
write_rectilinear(file, nodal, 'data', x_coord, y_coord)
file.close()

NETCDF rectilinear.png

Writing Curvilinear Meshes

This code takes advantage of the curvilinear grid support in VisIt's CCSM reader in order to write NETCDF files that allow the mesh to be deformed. The following example writes independent time steps as separate files.

from numpy import shape
from Scientific.IO.NetCDF import NetCDFFile
import numpy as np
import math

# Write a variable with curvilinear coordinates to NETCDF.
def write_curvilinear(file, var, varname, x_coord, y_coord, nx, ny):
    dimnames=('longitude','latitude')
    dimsizes=(nx,ny)

    # Create dimensions:
    file.createDimension('longitude', nx)
    file.createDimension('latitude', ny)

    x = file.createVariable('LONGXY', 'd', dimnames)
    y = file.createVariable('LATIXY', 'd', dimnames)

    # transfer the coordinate variables:
    x[:] = np.reshape(x_coord,dimsizes,'F')
    y[:] = np.reshape(y_coord,dimsizes,'F')

    # Create data variable in NetCDF.
    data = file.createVariable(varname, 'd', dimnames)

    # transfer the data variables:
    data[:] = np.reshape(var,dimsizes,'F')

# number of time states:
time_coord = [x*math.pi/12 for x in range(30)]
ntime=len(time_coord)

# number of points:
nx = 40
ny = 30

for k in xrange(ntime):
    # Create a coordinates and data variable
    x_coord = [] 
    y_coord = []
    nodal = []
    index = 0
    for j in xrange(ny):
        ty = float(j) / float(ny-1)
        for i in xrange(nx):
            tx = float(i) / float(nx-1)
            angle = tx * math.pi * 2. * 2.  # [0,4pi]
            x_coord = x_coord + [angle]
            y_coord = y_coord + [ty*4. + math.sin(angle - time_coord[k])]
            nodal = nodal + [index]
            index = index + 1

    # Open the file:
    file = NetCDFFile('curvilinear%04d.nc' % k, 'w')
    write_curvilinear(file, nodal, "data", x_coord, y_coord, nx, ny)
    file.close()

NETCDF curvilinear.png