Пример #1
0
def omf2vtk(input_omf_file,
            output_vtk_file,
            output_format='ascii'
            ):
    """
    Convert a given input_omf_file into a VTK file in ascii or binary format
    Magnetisation (direction and magnitude) values are stored as cell values
    """

    data = MagnetisationData(input_omf_file)
    data.generate_field()
    data.generate_coordinates()

    grid = (np.linspace(data.xmin * 1e9, data.xmax * 1e9, data.nx + 1),
            np.linspace(data.ymin * 1e9, data.ymax * 1e9, data.ny + 1),
            np.linspace(data.zmin * 1e9, data.zmax * 1e9, data.nz + 1))

    structure = pyvtk.RectilinearGrid(* grid)
    vtk_data = pyvtk.VtkData(structure, "")

    # Save the magnetisation
    vtk_data.cell_data.append(pyvtk.Vectors(np.column_stack((data.field_x,
                                                             data.field_y,
                                                             data.field_z)),
                              "m"))

    # Save Ms as scalar field
    vtk_data.cell_data.append(pyvtk.Scalars(data.field_norm, "Ms"))

    # Save to VTK file with specified output filename
    vtk_data.tofile(output_vtk_file, output_format)
Пример #2
0
def numpy2vtkgrid_file(outfilename,
                       xmin,
                       xmax,
                       ymin,
                       ymax,
                       numpy_matrix,
                       zlevel=0.0,
                       vtk_format='ascii',
                       vtkfilecomment="Created with numpy2vtkgrid",
                       vtkdatacomment="Scalar field"):
    assert len(numpy_matrix.shape) == 2,\
           "data needs to be 2d, but shape is '%s'" % numpy_matrix.shape

    nx, ny = numpy_matrix.shape

    xpos = numpy.linspace(xmin, xmax, nx)
    ypos = numpy.linspace(ymin, ymax, ny)

    print "point set = %d*%d=%d" % (nx, ny, nx * ny)

    vtk = pyvtk.VtkData(
        pyvtk.RectilinearGrid(\
            xpos.tolist(),ypos.tolist(),[zlevel]
            ),
        vtkfilecomment,
        pyvtk.PointData(
             pyvtk.Scalars( numpy_matrix.flatten().tolist(),
                            vtkdatacomment )
             ),
        format=vtk_format
        )
    vtk.tofile(outfilename, format=vtk_format)
Пример #3
0
def test_vtk_writer_speed():
    """
    Comparison of C backend with the old pyvtk interface

    For this we use a 200 x 200 x 1 mesh and convert the OMF file into a VTK
    file using both the C library and the PyVTK library. We run the same
    conversion for each method during 20 times and print a mean.

    """

    # C backend ---------------------------------------------------------------
    _file = glob.glob('./vtk_writer_omfs/isolated_sk_Cnv_n_200-Oxs*.omf')[0]
    data = op.MagnetisationData(_file)
    data.generate_field()
    data.generate_coordinates()
    output_vtk_file = 'vtk_writer_omfs/isolated_sk_Cnv_n_200.vtk'

    C_timings = []
    for i in range(20):
        start = timeit.default_timer()

        ot.clib.WriteVTK_RectilinearGrid_C(data.grid[0],
                                           data.grid[1], data.grid[2],
                                           data.field.reshape(-1),
                                           data.field_norm, data.nx, data.ny,
                                           data.nz, output_vtk_file)

        end = timeit.default_timer()
        C_timings.append(end - start)
    print('C writer (best of 20): ', np.mean(np.array(C_timings)))

    # PyVTK -------------------------------------------------------------------
    output_vtk_file = 'vtk_writer_omfs/isolated_sk_Cnv_n_200_pyvtk.vtk'

    pyvtk_timings = []
    for i in range(20):
        start = timeit.default_timer()

        structure = pyvtk.RectilinearGrid(*data.grid)
        vtk_data = pyvtk.VtkData(structure, "")

        # Save the magnetisation
        vtk_data.cell_data.append(pyvtk.Vectors(data.field, "m"))

        # Save Ms as scalar field
        vtk_data.cell_data.append(pyvtk.Scalars(data.field_norm, "Ms"))

        # Save to VTK file with specified output filename
        vtk_data.tofile(output_vtk_file, 'binary')

        end = timeit.default_timer()
        pyvtk_timings.append(end - start)
    print('PyVTK writer (best of 20): ', np.mean(np.array(pyvtk_timings)))
Пример #4
0
 def visitPrint(self, k):
     """
     Uses PyVTK to write out data in a VisIt Visualization Tool capable format.
     """
     import pyvtk
     uVel = pyvtk.Scalars(self.fluid.u().flatten(), name='u')
     vVel = pyvtk.Scalars(self.fluid.v().flatten(), name='v')
     totp = pyvtk.Scalars(self.fluid.p().flatten(), name='p')
     celldat = pyvtk.PointData(uVel, vVel, totp)
     grid = pyvtk.RectilinearGrid(self.domain.x, self.domain.y,
                                  self.domain.z)
     vtk = pyvtk.VtkData(grid, celldat)
     vtk.tofile('data%i' % k)
Пример #5
0
def savevtk(v, fn='', lons=[], lats=[], levels=[]):
    """save tracer field into vtk format,
    """
    import pyvtk

    def norm(c):
        return (c - c[0]) / (c[-1] - c[0])

    z = levels / abs(levels).max() * (lons.max() - lons.min()) * 0.7

    point_data = pyvtk.PointData(pyvtk.Scalars(v.T.flatten()))
    vtk_object = pyvtk.VtkData(pyvtk.RectilinearGrid(x=lons, y=lats, z=z),
                               point_data)
    vtk_object.tofile(fn)
    return
Пример #6
0
    def _writevtk(self, filename):
        grid = [
            pmini + np.linspace(0, li, ni + 1)
            for pmini, li, ni in zip(self.mesh.pmin, self.mesh.l, self.mesh.n)
        ]

        structure = pyvtk.RectilinearGrid(*grid)
        vtkdata = pyvtk.VtkData(structure)

        vectors = [self.__call__(i) for i in self.mesh.coordinates]
        vtkdata.cell_data.append(pyvtk.Vectors(vectors, self.name))
        for i, component in enumerate(dfu.axesdict.keys()):
            name = "{}_{}".format(self.name, component)
            vtkdata.cell_data.append(
                pyvtk.Scalars(list(zip(*vectors))[i], name))

        vtkdata.tofile(filename)
Пример #7
0
    def __init__(self, mesh, header="", directory=".", filename="unnamed"):
        self.mesh = mesh
        self.directory = directory
        self.filename = filename

        if isinstance(mesh, HexagonalMesh):
            structure = pyvtk.PolyData(points=mesh.vertices,
                                       polygons=mesh.hexagons)
        elif isinstance(mesh, CuboidMesh):
            # for keyword argument dimensions: if the mesh is made up of
            # nx * ny * nz cells, it has (nx + 1) * (ny + 1) * (nz + 1)
            # vertices.
            structure = pyvtk.RectilinearGrid(*mesh.grid)
        else:
            raise NotImplementedError(
                "Mesh should be CuboidMesh or HexagonalMesh, is {}.".format(
                    mesh.__class__.__name__))
        self.structure = structure
        self.header = header

        self.init_VtkData(structure, header)
Пример #8
0
def ovf2vtk_main():
    start_time = time.time()

    banner_doc = 70 * "-" + \
        "\novf2vtk --- converting ovf files to vtk files" + "\n" + \
        "Hans Fangohr, Richard Boardman, University of Southampton\n"""\
        + 70 * "-"

    # extracts command line arguments
    # If any of the arguments given appear in the command line, a list of...
    # ...these args and corresponding values (if any) is returned -> ('args').
    # Any arguments that dont dont match the given ones are retuned in a...
    # ...separate list -> ('params')
    # Note (fangohr 30/12/2006 20:52): the use of getopt is historic,
    args, params = getopt.getopt(sys.argv[1:], 'Vvhbta:', [
        "verbose", "help", "add=", "binary", "text", "ascii",
        "surface-effects", "version", "datascale=", "posscale="
    ])

    # default value
    surfaceEffects = False
    datascale = 0.0  # 0.0 has special meaning -- see help text
    posscale = 0.0  # 0.0 has special meaning -- see help text

    # provide data from getopt.getopt (args) in form of dictionary
    options = {}
    for item in args:
        if item[1] == '':
            options[item[0]] = None
        else:
            options[item[0]] = item[1]
    keys = options.keys()

    # set system responses to arguments given
    if "--surface-effects" in keys:
        surfaceEffects = True

    if "--posscale" in keys:
        posscale = float(options["--posscale"])

    if "--datascale" in keys:
        datascale = float(options["--datascale"])

    if "-v" in keys or "--verbose" in keys:
        print("running in verbose mode")
        debug = True
    else:
        debug = False

    if "-h" in keys or "--help" in keys:
        print(__doc__)
        sys.exit(0)

    if "-V" in keys or "--version" in keys:
        print("This is version {:s}.".format(version))
        sys.exit(0)

    if len(params) == 0:
        print(__doc__)
        print("ERROR: An input file (and an output file need to be "
              "specified).")
        sys.exit(1)
    else:
        infile = params[0]

    if len(params) == 1:
        print(__doc__)
        print("ERROR: An input file AND an output file need to be specified.")
        print("specify output file")
        sys.exit(1)
    else:
        outfile = params[1]

    # okay: it seems the essential parameters are given.
    # Let's check for others:

    print(banner_doc)

    if debug:
        print("infile = {}".format(infile))
        print("outfile = {}".format(outfile))
        print("args = {}".format(args))
        print("options = {}".format(options))
        print("datascale = {}".format(datascale))
        print("posscale = {}".format(posscale))

    # read data from infile
    vf = omf.read_structured_omf_file(infile, debug)

    # compute magnitude for all cells
    Ms = ana.magnitude(vf)

    # Compute number of cells with non-zero Ms (rpb01r)
    Ms_num_of_nonzeros = Numeric.sum(Numeric.not_equal(Ms, 0.0))
    print("({:5.2f}% of {:d} cells filled)".format(
        100.0 * Ms_num_of_nonzeros / len(Ms), len(Ms)))

    # scale magnetisation data as required:
    if datascale == 0.0:
        scale = max(Ms)
        print("Will scale data down by {:f}".format(scale))
    else:
        scale = datascale
    # normalise vectorfield by scale
    vf = Numeric.divide(vf, scale)

    # read metadata in data file
    ovf_run = omf.analyze(infile)
    datatitle = ovf_run["Title:"] + "/{:g}".format(scale)

    #
    # need x, y and z vectors for vtk format
    #
    # taking actual spacings for dx, dy and dz results generally in
    # poor visualisation results (in particular for thin films, one
    # would like to have some magnification in z-direction).  Also:vtk
    # is not happy with positions on the 10e-9 scale, so one better
    # scales this to something closer to unity.

    # extract dimensions from file
    dimensions = (int(ovf_run["xnodes:"]), int(ovf_run["ynodes:"]),
                  int(ovf_run["znodes:"]))

    # scale data by given factor
    if posscale != 0.0:

        # find range between max and min values of components
        xrange = abs(float(ovf_run["xmax:"]) - float(ovf_run["xmin:"]))
        yrange = abs(float(ovf_run["ymax:"]) - float(ovf_run["ymin:"]))
        zrange = abs(float(ovf_run["zmax:"]) - float(ovf_run["zmin:"]))

        # define no. of x,y,z nodes
        xnodes = float(ovf_run["xnodes:"])
        ynodes = float(ovf_run["ynodes:"])
        znodes = float(ovf_run["znodes:"])

        # define stepsizes
        xstepsize = float(ovf_run["xstepsize:"])
        ystepsize = float(ovf_run["ystepsize:"])
        zstepsize = float(ovf_run["zstepsize:"])

        # define bases
        xbase = float(ovf_run["xbase:"])
        ybase = float(ovf_run["ybase:"])
        zbase = float(ovf_run["zbase:"])

        # find dx, dy, dz in SI units:
        dx = xrange / xnodes
        dy = yrange / ynodes
        dz = zrange / znodes

        # find scale factor that OOMMF uses for xstepsize and xnodes,
        # etc. (Don't know how to get this directly.)
        xscale = dx * xstepsize
        yscale = dy * ystepsize
        zscale = dz * zstepsize

        # extract x, y and z positions from ovf file.
        xbasevector = [None] * dimensions[0]  # create empty vector
        for i in range(dimensions[0]):
            # data is stored for 'centre' of each cuboid, therefore (i+0.5)
            xbasevector[i] = xbase + (i + 0.5) * xstepsize * xscale

        ybasevector = [None] * dimensions[1]
        for i in range(dimensions[1]):
            ybasevector[i] = ybase + (i + 0.5) * ystepsize * yscale

        zbasevector = [None] * dimensions[2]
        for i in range(dimensions[2]):
            zbasevector[i] = zbase + (i + 0.5) * zstepsize * zscale

        # finally, convert list to numeric (need to have this consistent)
        xbasevector = Numeric.array(xbasevector) / float(posscale)
        ybasevector = Numeric.array(ybasevector) / float(posscale)
        zbasevector = Numeric.array(zbasevector) / float(posscale)

    else:
        # posscale == 0.0
        # this generally looks better:
        xbasevector = Numeric.arange(dimensions[0])
        ybasevector = Numeric.arange(dimensions[1])
        zbasevector = Numeric.arange(dimensions[2])

    #
    # write ascii or binary vtk-file (default is binary)
    #
    vtk_data = 'binary'

    if '--ascii' in keys or '-t' in keys or '--text' in keys:
        vtk_data = 'ascii'
        if debug:
            print("switching to ascii vtk-data")

    if '--binary' in keys or '-b' in keys:
        vtk_data = 'binary'
        if debug:
            print("switching to binary vtk-data")

    #
    # and now open vtk-file
    #
    vtkfilecomment = "Output from ovf2vtk (version {:s}), {:s}, infile={:s}. "\
        .format(version, time.asctime(), infile)
    vtkfilecomment += "Calling command line was '{:s}' executed in '{:s}'"\
        .format(" ".join(sys.argv), os.getcwd())

    # define inputs
    RecGrid = pyvtk.RectilinearGrid(xbasevector.tolist(), ybasevector.tolist(),
                                    zbasevector.tolist())

    PData = pyvtk.PointData(pyvtk.Vectors(vf.tolist(), datatitle))

    # define vtk file.
    vtk = pyvtk.VtkData(RecGrid, vtkfilecomment, PData, format=vtk_data)

    # now compute all the additional data such as angles, etc

    # check whether we should do all
    keys = map(lambda x: x[1], args)
    if "all" in keys:
        args = []
        for add_arg in add_features:
            args.append(("--add", add_arg))

    # when ovf2vtk was re-written using Numeric, I had to group
    # certain operations to make them fast. Now some switches are
    # unneccessary. (fangohr 25/08/2003 01:35)
    # To avoid executing the
    # same code again, we remember what we have computed already:

    done_angles = 0
    done_comp = 0

    for arg in args:
        if arg[0] == "-a" or arg[0] == "--add":
            print("working on {}".format(arg))

            data = []
            lookup_table = 'default'

            # compute observables that need more than one field value
            # i.e. div, rot
            if arg[1][0:6] == "divrot":  # rotation = vorticity, curl

                (div, rot, rotx, roty, rotz, rotmag) = \
                    ana.divergence_and_curl(vf, surfaceEffects, ovf_run)
                # change order of observables for upcoming loop
                observables = (rotx, roty, rotz, rotmag, rot, div)

                comments = [
                    "curl, x-comp", "curl, y-comp", "curl, z-comp",
                    "curl, magnitude", "curl", "divergence"
                ]

                # append data to vtk file
                for obs, comment in zip(observables, comments):
                    # for rotx, roty, rotz, rotmag, div
                    if comment != "curl":
                        vtk.point_data.append(
                            pyvtk.Scalars(obs.tolist(), comment, lookup_table))
                    # for rot
                    else:
                        vtk.point_data.append(
                            pyvtk.Vectors(obs.tolist(), comment))

            # components
            elif arg[1] in ["Mx", "My", "Mz", "Ms"]:
                if done_comp == 0:
                    done_comp = 1
                    comments = "x-component", "y-component", "z-component"

                    for data, comment in zip(ana.components(vf), comments):
                        vtk.point_data.append(
                            pyvtk.Scalars(data.tolist(), comment,
                                          lookup_table))

                    # magnitude of magnitisation
                    Mmag = ana.magnitude(vf)
                    vtk.point_data.append(
                        pyvtk.Scalars(Mmag.tolist(), "Magnitude",
                                      lookup_table))

            elif arg[1] in ["xy", "xz", "yz"]:
                if done_angles == 0:
                    done_angles = 1
                    # in-plane angles
                    comments = ("xy in-plane angle", "yz in-plane angle",
                                "xz in-plane angle")
                    for data, comment in zip(ana.plane_angles(vf), comments):
                        vtk.point_data.append(
                            pyvtk.Scalars(data.tolist(), comment,
                                          lookup_table))

            else:
                print("only xy, xz, Mx, My, Mz, divergence, Ms, or 'all' \
allowed after -a or --add")
                print("Current choice is {}".format(arg))
                print(__doc__)
                sys.exit(1)

    #
    # eventually, write the file
    #
    print("saving file ({:s})".format(outfile))
    vtk.tofile(outfile, format=vtk_data)

    print("finished conversion (execution time {:5.3s} seconds)".format(
        str(time.time() - start_time)))
Пример #9
0
def ovf2vtk_main():
    start_time = time.time()
    
    banner_doc = 70*"-"+\
    "\novf2vtk --- converting ovf files to vtk files"+"\n"+\
    "Hans Fangohr, Richard Boardman, University of Southampton\n"""+70*"-"

    #extract command line arguments
    additions,params = getopt.getopt( sys.argv[1:], 'Vvhbta:', ["verbose","help","add=","binary","text","ascii","surface-effects","version","datascale=","posscale="] )

    #Note (fangohr 30/12/2006 20:52): the use of getopt is historic,
    #and so is the use of the name 'additions'. 

    #default value
    surfaceEffects = False
    datascale = 0.0 #0.0 has special meaning -- see help text
    posscale = 0.0  #0.0 has special meaning -- see help text

    #provide data from getopt.getopt (additions) in form of hash table
    options = {}
    for item in additions:
        if item[1]=='':
            options[item[0]] = None
        else:
            options[item[0]] = item[1]
    keys = options.keys()
            
    if "--surface-effects" in keys:
        surfaceEffects = True

    if "--posscale" in keys:
        posscale = float(options["--posscale"])

    if "--datascale" in keys:
        datascale = float(options["--datascale"])

    if "-v" in keys or "--verbose" in keys:
        print "running in verbose mode"
        debug = True
    else:
        debug = False

    if "-h" in keys or "--help" in keys:
        print __doc__
        sys.exit(0)

    if "-V" in keys or "--version" in keys:
        print "This is version %s." % ovf2vtk.__version__
        sys.exit(0)

    if len( params ) == 0:
        print __doc__
        print "ERROR: An input file (and an output file need to be specified)."
        sys.exit(1)
    else:
        infile = params[0]

    if len( params ) == 1:
        print __doc__
        print "ERROR: An input file AND an output file need to be specified."
        print "specify output file"
        sys.exit(1)
    else:
        outfile = params[1]

    # okay: it seems the essential parameters are given. Let's check for others:

    print banner_doc

    if debug:
        print "infile  = ", infile
        print "outfile = ",outfile
        print "additions= ",additions
        print "options = ",options
        print "datascale=",datascale
        print "posscale=",posscale

    #read data from infile
    vf = read_structured_omf_file( infile, debug )

    #compute magnitude for all cells 
    Ms = magnitude( vf )
    
    # Compute number of cells with non-zero Ms (rpb01r) 
    Ms_num_of_nonzeros = Numeric.sum( Numeric.not_equal( Ms, 0.0 ) ) 
    print "(%5.2f%% of %d cells filled)" % (100.0*Ms_num_of_nonzeros/len(Ms), len(Ms))


    #read metadata in data file 
    ovf_run  = analyze( infile  )



    #scale magnetisation data as required:
    if datascale == 0.0:
        scale = max( Ms )
        print "Will scale data down by %f" % scale
    else:
        scale = datascale
    vf = Numeric.divide( vf, scale )

    datatitle = ovf_run["Title:"]+"/%g" % (scale)

    #
    #need x, y and z vectors for vtk format
    #

    #taking actual spacings for dx, dy and dz results generally in
    #poor visualisation results (in particular for thin films, one
    #would like to have some magnification in z-direction).  Also:vtk
    #is not happy with positions on the 10e-9 scale, so one better
    #scales this to something closer to unity.



    #extract dimensions from file
    dimensions = ( int( ovf_run["xnodes:"] ), \
                   int( ovf_run["ynodes:"] ), \
                   int( ovf_run["znodes:"] ))

    if posscale != 0.0:  #scale data by given factor

        #find dx, dy, dz in SI units:
        Lx = abs(float(ovf_run["xmax:"])-float(ovf_run["xmin:"]))
        Ly = abs(float(ovf_run["ymax:"])-float(ovf_run["ymin:"]))
        Lz = abs(float(ovf_run["zmax:"])-float(ovf_run["zmin:"]))

        dx = Lx / float( ovf_run["xnodes:"] )
        dy = Ly / float( ovf_run["ynodes:"] )
        dz = Lz / float( ovf_run["znodes:"] )

        #find scale factor that OOMMF uses for xstepsize and xnodes,
        #etc. (Don't know how to get this directly.)
        xscale = Lx / (float( ovf_run["xnodes:"])*float(ovf_run["xstepsize:"]))
        yscale = Ly / (float( ovf_run["ynodes:"])*float(ovf_run["ystepsize:"]))
        zscale = Lz / (float( ovf_run["znodes:"])*float(ovf_run["zstepsize:"]))

        #extract x, y and z positions from ovf file.
        xbasevector = [None] * dimensions[0] #create empty vector
        for i in range( dimensions[0] ):
            #data is stored for 'centre' of each cuboid, therefore (i+0.5)
            xbasevector[i] = float( ovf_run["xbase:"] ) +\
                             (i+0.5) *float( ovf_run["xstepsize:"] )*xscale

        ybasevector = [None]* dimensions[1]
        for i in range( dimensions[1] ):
            ybasevector[i] = float( ovf_run["ybase:"] ) + (i+0.5) *float( ovf_run["ystepsize:"] )*yscale

        zbasevector = [None]* dimensions[2]
        for i in range( dimensions[2] ):
            zbasevector[i] = float( ovf_run["zbase:"] ) + (i+0.5) *float( ovf_run["zstepsize:"] )*zscale


        #finally, convert list to numerix (need to have this consistent)
        xbasevector = Numeric.array(xbasevector)/float(posscale)
        ybasevector = Numeric.array(ybasevector)/float(posscale)
        zbasevector = Numeric.array(zbasevector)/float(posscale)
        
    else: #posscale == 0.0
        #
        #this generally looks better:
        #
        xbasevector = Numeric.arange( dimensions[0] )
        ybasevector = Numeric.arange( dimensions[1] )
        zbasevector = Numeric.arange( dimensions[2] )

    #
    # write ascii or binary vtk-file (default is binary)
    #
    vtk_data = 'binary'
        
    if '--ascii' in keys or '-t' in keys or '--text' in keys:
        vtk_data = 'ascii'
        if debug:
            print "switching to ascii vtk-data"
    if '--binary' in keys or '-b' in keys:
        vtk_data = 'binary'
        if debug:
            print "switching to binary vtk-data"

    #
    #and now open vtk-file
    #
    vtkfilecomment =  "Output from ovf2vtk (version %s), %s, infile=%s. " % (ovf2vtk.__version__,\
                                                                   time.asctime(),\
                                                                   infile)
    vtkfilecomment += "Calling command line was '%s' executed in '%s'" % (" ".join(sys.argv),\
                                                                        os.getcwd())

    vtk = pyvtk.VtkData(    pyvtk.RectilinearGrid(xbasevector.tolist(),ybasevector.tolist(),zbasevector.tolist()),
                            vtkfilecomment,
                            pyvtk.PointData(pyvtk.Vectors( vf.tolist(), datatitle ) ),
                            format=vtk_data)

    #
    # now compute all the additional data such as angles, etc
    #

    # check whether we should do all
    keys = map(lambda x:x[1], additions)
    if "all" in keys:
        additions = []
        for add in add_features:
            additions.append(("--add",add))


    # when ovf2vtk was re-written using Numeric, I had to group
    # certain operations to make them fast. Now some switches are
    # unneccessary. (fangohr 25/08/2003 01:35)
    # To avoid executing the
    # same code again, we remember what we have computed already:
    
    done_angles = 0
    done_comp   = 0

    for add in additions:
        if add[0]=="-a" or add[0]=="--add":
            print "working on",add

            data=[]

            #compute observables that need more than one field value, i.e. div, rot
            if add[1][0:6] == "divrot":  #rotation = vorticity, curl
                
                (div, rot, rotx, roty, rotz, rotmag) = divergence_and_curl( vf, surfaceEffects, ovf_run )
                    
                comment = "curl, x-comp" 
                vtk.point_data.append( pyvtk.Scalars( rotx.tolist() , comment , lookup_table='default') )
                Comment = "curl, y-comp" 
                vtk.point_data.append( pyvtk.Scalars( roty.tolist() , comment , lookup_table='default') )
                comment = "curl, z-comp" 
                vtk.point_data.append( pyvtk.Scalars( rotz.tolist() , comment , lookup_table='default') )
                comment = "curl, magnitude" 
                vtk.point_data.append( pyvtk.Scalars( rotmag.tolist(), comment , lookup_table='default') )
                comment = "curl" 
                vtk.point_data.append( pyvtk.Vectors( rot.tolist() , comment ) )

                comment = "divergence"
                vtk.point_data.append( pyvtk.Scalars( div.tolist() , comment , lookup_table='default') )

                done_div_rot = True
            elif add[1] in ["Mx","My","Mz","Ms"]:                # components
                if not done_comp:
                    done_comp = 1
                                
                    comments = "x-component", "y-component", "z-component"

                    for data, comment in zip( components( vf ), comments):
                        vtk.point_data.append( pyvtk.Scalars( data.tolist(), comment,lookup_table='default' ) )
    
                    # magnitude of magnitisation
                    Mmag = magnitude( vf )
                    vtk.point_data.append( pyvtk.Scalars(Mmag.tolist(), "Magnitude",lookup_table='default' ) )

            elif add[1] in ["xy","xz","yz"]:
                if not done_angles:
                    done_angles = 1

                    # in-plane angles
                    comments = "xy in-plane angle", "yz in-plane angle", "xz in-plane angle"

                    for data, comment in zip( plane_angles( vf ), comments):
                        vtk.point_data.append( pyvtk.Scalars( data.tolist(), comment, lookup_table='default' )  )

            else:
                print "only xy, xz, Mx, My, Mz, divergence, Ms, or 'all' allowed after -a or --add"
                print "Current choice is",add
                print __doc__
                sys.exit(1)


    #
    #eventually, write the file
    #
    print "saving file (%s)" % (outfile)
    vtk.tofile(outfile,format=vtk_data)

    print "finished conversion (execution time %5.3s seconds)" % (time.time()-start_time)