Commit 1ed3b74a authored by dedner's avatar dedner
Browse files

add a convience writer on the Python side

[bugfix]

[bugfix]

[to be dropped] added a test using some dune-fem bindings to test different aspects of the VtkWriter bindings

use 'pointData' instead of 'pointVector' as argument for vtkWriter since
that argument can also be used for tensors.

[python] remove dune packages from 'install_requires' in setup.py.in

add metadata to dune.module for pip packaging

add cellData method and add missing parameter to constructor of write

remove test requiring dune-fem (moved to dune-fem)

fix cut and paste error in dune.module file
parent d93834ef
...@@ -5,7 +5,15 @@ ...@@ -5,7 +5,15 @@
#Name of the module #Name of the module
Module: dune-vtk Module: dune-vtk
Version: 0.2 Version: 0.2
#meta data
Author: Simon Praetorius
Maintainer: simon.praetorius@tu-dresden.de Maintainer: simon.praetorius@tu-dresden.de
Description: File reader and writer for the VTK Format
URL: https://gitlab.dune-project.org/extensions/dune-vtk
#depending on #depending on
Depends: dune-grid (>= 2.7) dune-localfunctions (>= 2.7) Depends: dune-grid (>= 2.7) dune-localfunctions (>= 2.7)
Suggests: dune-functions dune-spgrid dune-polygongrid dune-alugrid dune-foamgrid dune-uggrid Suggests: dune-functions dune-spgrid dune-polygongrid dune-alugrid dune-foamgrid dune-uggrid
Python-Requires:
Whitespace-Hook: Yes
import math import math
from dune.grid import structuredGrid, gridFunction from dune.grid import structuredGrid, gridFunction
from dune.vtk import vtkUnstructuredGridWriter, RangeTypes, FieldInfo from dune.vtk import vtkUnstructuredGridWriter, vtkWriter, RangeTypes, FieldInfo
grid = structuredGrid([0,0],[1,1],[10,10]) grid = structuredGrid([0,0],[1,1],[5,5])
def test1(writer): def test1(writer):
@gridFunction(grid) @gridFunction(grid)
...@@ -45,3 +45,30 @@ writer4.addPointData(g, info=FieldInfo(name="g2S", range=RangeTypes.scalar), ...@@ -45,3 +45,30 @@ writer4.addPointData(g, info=FieldInfo(name="g2S", range=RangeTypes.scalar),
writer4.addPointData(g, info=FieldInfo(name="g2V", range=RangeTypes.vector), writer4.addPointData(g, info=FieldInfo(name="g2V", range=RangeTypes.vector),
components=[2]) # is vector components=[2]) # is vector
writer4.write("test4") writer4.write("test4")
@gridFunction(grid)
def f(x):
return math.sin(2*math.pi*x[0]*x[1]/(1+x[0]*x[0]))
"""
def vtkWriter(grid, name,
version="unstructured",
cellScalar=None, pointScalar=None,
cellVector=None, pointVector=None,
number=None, outputType=OutputType.appendedbase64,
write=True,
**kwargs # additional ctor arguments for writer
"""
# Note: {"gV":g} has only one components in the data file although the range is auto
writer = vtkWriter( grid, "test",
pointData = { "gV":g, ("g43V",(4,3)):g, ("g435V",(4,3,5)):g },
pointScalar = { "fS":f, "gS":g, ("g23S",(2,3)):g },
)
writer = vtkWriter( grid, "testLagrange",
version="lagrange", order=3,
pointData = {"gV":g, ("g43V",(4,3)):g},
pointScalar = {("g435V",(4,3,5)):g},
cellData = {("g23V",(2,3)):g, ("g234V",(2,3,4)):g},
cellScalar = { "fS":f, "gS":g}
)
...@@ -25,12 +25,20 @@ namespace Dune ...@@ -25,12 +25,20 @@ namespace Dune
using GridView = typename Writer::GridView; using GridView = typename Writer::GridView;
using VirtualizedGF = Dune::Vtk::Function<GridView>; using VirtualizedGF = Dune::Vtk::Function<GridView>;
cls.def( pybind11::init( [] ( GridView &grid ) cls.def( pybind11::init( [] ( GridView &grid,
{ return new Writer( grid ); } ), Vtk::FormatTypes format,
pybind11::keep_alive< 1, 2 >() ); Vtk::DataTypes datatype,
Vtk::DataTypes headertype,
pybind11::kwargs kwargs) {
return new Writer( grid, format, datatype, headertype );
}), pybind11::arg("grid"),
pybind11::arg("format") = Vtk::FormatTypes::BINARY,
pybind11::arg("datatype") = Vtk::DataTypes::FLOAT32,
pybind11::arg("headertype") = Vtk::DataTypes::UINT32,
pybind11::keep_alive< 1, 2 >());
cls.def( "write", cls.def( "write",
[] ( Writer &writer, const std::string &name) { [] ( Writer &writer, const std::string &name ) {
writer.write( name ); writer.write( name );
}, },
pybind11::arg("name") ); pybind11::arg("name") );
...@@ -46,8 +54,11 @@ namespace Dune ...@@ -46,8 +54,11 @@ namespace Dune
[] ( Writer &writer, VirtualizedGF &f, [] ( Writer &writer, VirtualizedGF &f,
RangeTypes range, DataTypes data RangeTypes range, DataTypes data
) { ) {
f.setRangeType(range);
f.setDataType(data);
writer.addPointData(f); writer.addPointData(f);
}, },
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("f"),
pybind11::arg("range")=RangeTypes::AUTO, pybind11::arg("range")=RangeTypes::AUTO,
pybind11::arg("data")=DataTypes::FLOAT32 pybind11::arg("data")=DataTypes::FLOAT32
...@@ -58,8 +69,11 @@ namespace Dune ...@@ -58,8 +69,11 @@ namespace Dune
RangeTypes range, DataTypes data RangeTypes range, DataTypes data
) { ) {
f.setName(name); f.setName(name);
f.setRangeType(range);
f.setDataType(data);
writer.addPointData(f); writer.addPointData(f);
}, },
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("name"), pybind11::arg("f"), pybind11::arg("name"),
pybind11::arg("range")=RangeTypes::AUTO, pybind11::arg("range")=RangeTypes::AUTO,
pybind11::arg("data")=DataTypes::FLOAT32 pybind11::arg("data")=DataTypes::FLOAT32
...@@ -71,9 +85,12 @@ namespace Dune ...@@ -71,9 +85,12 @@ namespace Dune
RangeTypes range, DataTypes data RangeTypes range, DataTypes data
) { ) {
f.setName(name); f.setName(name);
f.setRangeType(range);
f.setDataType(data);
f.setComponents(components); f.setComponents(components);
writer.addPointData(f); writer.addPointData(f);
}, },
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("name"), pybind11::arg("f"), pybind11::arg("name"),
pybind11::arg("components"), pybind11::arg("components"),
pybind11::arg("range")=RangeTypes::AUTO, pybind11::arg("range")=RangeTypes::AUTO,
...@@ -85,6 +102,7 @@ namespace Dune ...@@ -85,6 +102,7 @@ namespace Dune
f.setFieldInfo(info); f.setFieldInfo(info);
writer.addPointData(f); writer.addPointData(f);
}, },
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("info") ); pybind11::arg("f"), pybind11::arg("info") );
cls.def( "addPointData", cls.def( "addPointData",
[] ( Writer &writer, VirtualizedGF &f, [] ( Writer &writer, VirtualizedGF &f,
...@@ -93,11 +111,76 @@ namespace Dune ...@@ -93,11 +111,76 @@ namespace Dune
f.setComponents(components); f.setComponents(components);
writer.addPointData(f); writer.addPointData(f);
}, },
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("components"), pybind11::arg("info") );
cls.def( "addCellData",
[] ( Writer &writer, VirtualizedGF &f,
RangeTypes range, DataTypes data
) {
f.setRangeType(range);
f.setDataType(data);
writer.addCellData(f);
},
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"),
pybind11::arg("range")=RangeTypes::AUTO,
pybind11::arg("data")=DataTypes::FLOAT32
);
cls.def( "addCellData",
[] ( Writer &writer, VirtualizedGF &f,
std::string &name,
RangeTypes range, DataTypes data
) {
f.setName(name);
f.setRangeType(range);
f.setDataType(data);
writer.addCellData(f);
},
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("name"),
pybind11::arg("range")=RangeTypes::AUTO,
pybind11::arg("data")=DataTypes::FLOAT32
);
cls.def( "addCellData",
[] ( Writer &writer, VirtualizedGF &f,
std::string &name,
std::vector<int> &components,
RangeTypes range, DataTypes data
) {
f.setName(name);
f.setRangeType(range);
f.setDataType(data);
f.setComponents(components);
writer.addCellData(f);
},
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("name"),
pybind11::arg("components"),
pybind11::arg("range")=RangeTypes::AUTO,
pybind11::arg("data")=DataTypes::FLOAT32
);
cls.def( "addCellData",
[] ( Writer &writer, VirtualizedGF &f,
FieldInfo &info) {
f.setFieldInfo(info);
writer.addCellData(f);
},
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("info") );
cls.def( "addCellData",
[] ( Writer &writer, VirtualizedGF &f,
std::vector<int> &components, FieldInfo &info ) {
f.setFieldInfo(info);
f.setComponents(components);
writer.addCellData(f);
},
pybind11::keep_alive< 1, 2 >(),
pybind11::arg("f"), pybind11::arg("components"), pybind11::arg("info") ); pybind11::arg("f"), pybind11::arg("components"), pybind11::arg("info") );
} }
} // namespace Python } // namespace Vtk
} // namespace Dune } // namespace Dune
#endif // #ifndef DUNE_PYTHON_GRID_VTK_HH #endif // DUNE_PYTHON_VTK_WRITER_HH
...@@ -25,8 +25,6 @@ namespace Dune ...@@ -25,8 +25,6 @@ namespace Dune
{ {
template <class> friend class TimeseriesWriter; template <class> friend class TimeseriesWriter;
template <class> friend class PvdWriter; template <class> friend class PvdWriter;
public:
using GridView = GV;
public: public:
using GridView = GV; using GridView = GV;
......
...@@ -2,17 +2,144 @@ import hashlib ...@@ -2,17 +2,144 @@ import hashlib
from dune.generator.generator import SimpleGenerator from dune.generator.generator import SimpleGenerator
from ._vtk import * from ._vtk import *
from dune.grid import OutputType
from dune.grid.grid_generator import _writeVTKDispatcher as addDispatcher
generator = SimpleGenerator("VtkWriter", "Dune::Vtk") generator = SimpleGenerator("VtkWriter", "Dune::Vtk")
def load(includes, typeName, *args): def load(includes, typeName):
includes += ["dune/python/vtk/writer.hh"] includes += ["dune/python/vtk/writer.hh"]
moduleName = "vtkwriter_" + hashlib.md5(typeName.encode('utf-8')).hexdigest() moduleName = "vtkwriter_" + hashlib.md5(typeName.encode('utf-8')).hexdigest()
module = generator.load(includes, typeName, moduleName, *args) module = generator.load(includes, typeName, moduleName)
return module return module.VtkWriter
######################################################################
allCollectors = {
"continuous":
lambda grid:
"ContinuousDataCollector<"+grid._typeName+">",
"lagrange":
lambda grid, **kwargs:
"Dune::Vtk::LagrangeDataCollector<"+grid._typeName+","+str(kwargs["order"])+">"
}
allWriters = {
"default": [ lambda grid:
"Dune::VtkUnstructuredGridWriter<"+grid._typeName+">",
["dune/vtk/writers/vtkunstructuredgridwriter.hh"] ],
"lagrange": [ lambda grid, **kwargs:
"Dune::VtkUnstructuredGridWriter<"+grid._typeName+","+\
allCollectors["lagrange"](grid,**kwargs)+">",
["dune/vtk/writers/vtkunstructuredgridwriter.hh",
"dune/vtk/datacollectors/lagrangedatacollector.hh"] ]
}
def vtkWriter(grid, name,
version="default",
pointData=None, pointScalar=None,
cellData=None, cellScalar=None,
number=None, write=True,
format = FormatTypes.binary,
datatype = DataTypes.Float32, headertype = DataTypes.UInt32,
**kwargs # additional ctor arguments for dataContainer or Writer
):
writer = load( allWriters[version][1],
allWriters[version][0](grid,**kwargs) )\
(grid, format, datatype, headertype, **kwargs)
# method to extract the range dimension from a given grid function
def rangeDimension(f):
try: return len(f)
except: pass
try: return f.ufl_shape[0]
except: pass
try: return f.dimRange
except: pass
return None
# reinterpret `functions` argument list as list of the form
# return list with entries [f,{name,components}] or [f,{name}]
def extract(functions, toScalar):
ret = []
if type(functions)==dict: # form name:function, or (name,components):function
for k,v in functions.items():
if type(k) == str:
ret += [ [v,{"name":k}] ]
else: # name component pair assumed
ret += [ [v,{"name":k[0], "components":k[1]}] ]
elif type(functions)==list: # each entry is a function with a 'name'
# and possibly a 'components' attribute
for v in functions:
try:
ret += [ [v,{"name":v.name, "components":v.components}] ]
except AttributeError:
ret += [ [v,{"name":v.name}] ]
if toScalar: # convert scalar functions with multiply components
scalarRet = []
for r in ret:
# can we extract range dimension from a grid function?
dimR = rangeDimension(r[0])
comp = r[1].get("components",range(dimR))
if dimR is None or len(comp)==1:
scalarRet += [ [ r[0], {"name":r[1]["name"],
"components":comp} ] ]
else:
for i, c in enumerate(comp):
scalarRet += [ [ r[0], {"name":r[1]["name"]+"_"+str(i),
"components":[c]} ] ]
return scalarRet
else:
return ret
# call the actual `add` method on the writer here other packages can
# add dispatch method to convert `f` into a `Vtk::Function`, i.e., a
# ufl expression.
def addDefault(addMethod, f, **kwargs):
try:
addMethod(f,**kwargs)
return
except TypeError:
pass
for dispatch in addDispatcher:
func = dispatch(grid,f)
if func is not None:
addMethod(func,**kwargs)
return
raise AttributeError("coundn't find a way to add function "+str(f)+
" of type "+str(type(f))+" to the VtkWriter")
# add all the functions provided as arguments to the writer
for f in extract(pointData, toScalar=False):
addDefault( writer.addPointData, f[0], **f[1], range=RangeTypes.auto)
for f in extract(pointScalar, toScalar=True):
addDefault( writer.addPointData, f[0], **f[1], range=RangeTypes.scalar)
for f in extract(cellData,False):
addDefault( writer.addCellData, f[0], **f[1], range=RangeTypes.vector)
for f in extract(cellScalar,True):
addDefault( writer.addCellData, f[0], **f[1], range=RangeTypes.scalar)
# the class is returned. It doesn't allow for adding additional data
# since after the first `write` this doesn't make sense. The name is
# fixed by the provided argument and in addition a consecutive number
# is added for each execution of __call__.
class _Writer:
def __init__(self,writer,name,number):
self.writer = writer
self.name = name
self.number = number
def __call__(self):
if self.number is None:
self.writer.write(self.name)
else:
self.writer.write(self.name,self.number)
self.number += 1
_writer = _Writer(writer,name,number)
if write:
_writer()
return _writer
#######################################################
def vtkUnstructuredGridWriter(grid): def vtkUnstructuredGridWriter(grid):
"""create a VtkWriter for higher order lagrange elements """create a VtkWriter for unstructured grids
Args: Args:
grid: grid view to use for the vtk file grid: grid view to use for the vtk file
...@@ -20,9 +147,5 @@ def vtkUnstructuredGridWriter(grid): ...@@ -20,9 +147,5 @@ def vtkUnstructuredGridWriter(grid):
Returns: Returns:
vtkWriter: the constructed writer vtkWriter: the constructed writer
""" """
return load( allWriters["default"][1],
typeName = "Dune::VtkUnstructuredGridWriter<" + grid._typeName + ">" allWriters["default"][0](grid) )(grid)
includes = grid._includes + ["dune/vtk/writers/vtkunstructuredgridwriter.hh"]
Writer = load(includes, typeName).VtkWriter
return Writer(grid)
from setuptools import setup, find_packages from setuptools import setup, find_packages
pkg = [m for m in "${ProjectPythonRequires}".split(' ') if "dune" not in m]
setup(name="${ProjectName}", setup(name="${ProjectName}",
namespace_packages=['dune'], namespace_packages=['dune'],
description="${ProjectDescription}", description="${ProjectDescription}",
...@@ -9,5 +11,5 @@ setup(name="${ProjectName}", ...@@ -9,5 +11,5 @@ setup(name="${ProjectName}",
packages = find_packages(), packages = find_packages(),
zip_safe = 0, zip_safe = 0,
package_data = {'': ['*.so']}, package_data = {'': ['*.so']},
install_requires = "${ProjectPythonRequires}".split(' ') install_requires = pkg
) )
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment