Commit eae45480 authored by Andreas Dedner's avatar Andreas Dedner

Improve compile time of hierarchic grid classes

- only compile levelgridview on demand - so hierarchic grid only contains
  leafgridview
- for a gridview only compile indexset and mapper on demand
parent aa554992
Pipeline #12985 passed with stage
in 15 minutes and 28 seconds
......@@ -20,8 +20,8 @@
#include <dune/python/grid/entity.hh>
#include <dune/python/grid/function.hh>
#include <dune/python/grid/indexset.hh>
#include <dune/python/grid/intersection.hh>
#include <dune/python/grid/mapper.hh>
#include <dune/python/grid/intersection.hh>
#include <dune/python/grid/numpy.hh>
#include <dune/python/grid/range.hh>
#include <dune/python/grid/vtk.hh>
......@@ -141,10 +141,7 @@ namespace Dune
registerGridEntities< GridView >( cls );
registerGridIntersection< GridView >( cls );
registerGridViewIndexSet< GridView >( cls );
registerMultipleCodimMultipleGeomTypeMapper< GridView >( cls );
cls.def( "mapper", [] ( GridView &self, pybind11::object layout ) {
cls.def( "_mapper", [] ( GridView &self, pybind11::object layout ) {
return makeMultipleCodimMultipleGeomTypeMapper( self, layout );
}, pybind11::keep_alive< 0, 1 >(), "layout"_a,
R"doc(
......@@ -168,7 +165,6 @@ namespace Dune
)doc" );
// register iterators
Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [ &cls ] ( auto &&codim ) {
registerPyGridViewIterator< GridView, codim >();
} );
......@@ -323,7 +319,7 @@ namespace Dune
return self.ghostSize( codim );
}, "codim"_a );
cls.def_property_readonly( "indexSet", [] ( const GridView &self ) -> const typename GridView::IndexSet & {
cls.def_property_readonly( "_indexSet", [] ( const GridView &self ) -> const typename GridView::IndexSet & {
return self.indexSet();
}, pybind11::return_value_policy::reference, pybind11::keep_alive< 0, 1 >(),
R"doc(
......
......@@ -272,10 +272,6 @@ namespace Dune
pybind11::options opts;
opts.disable_function_signatures();
auto clsLevelView = insertClass< typename Grid::LevelGridView >( module, "LevelGrid", GenerateTypeName( cls, "LevelGridView" ) );
if( clsLevelView.second )
registerGridView( module, clsLevelView.first );
auto clsLeafView = insertClass< typename Grid::LeafGridView >( module, "LeafGrid", GenerateTypeName( cls, "LeafGridView" ) );
if( clsLeafView.second )
registerGridView( module, clsLeafView.first );
......@@ -297,7 +293,7 @@ namespace Dune
Returns: leaf grid view
)doc" );
cls.def( "levelView", [] ( const Grid &self, int level ) {
cls.def( "_levelView", [] ( const Grid &self, int level ) {
return self.levelGridView( level );
}, pybind11::keep_alive< 0, 1 >(), "level"_a,
R"doc(
......@@ -310,7 +306,6 @@ namespace Dune
)doc" );
typedef typename Grid::template Codim< 0 >::Entity Element;
cls.def( "mark", [] ( Grid &self, const Element &element, Marker marker ) {
self.mark( static_cast< int >( marker ), element );
}, "element"_a, "marker"_a,
......
......@@ -207,7 +207,7 @@ namespace Dune
// registerGridViewIndexSet
// ------------------------
template< class GridView, class IndexSet, class... options >
template< class IndexSet, class... options >
inline static void registerGridViewIndexSet ( pybind11::handle scope, pybind11::class_< IndexSet, options... > cls )
{
using pybind11::operator""_a;
......@@ -244,8 +244,8 @@ namespace Dune
cls.def( "size", [] ( IndexSet &self, Dune::GeometryType type ) { return self.size( type ); } );
cls.def( "size", [] ( IndexSet &self, int codim ) {
if( (codim < 0) || (codim > GridView::dimension) )
throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( GridView::dimension ) + "])" );
if( (codim < 0) || (codim > IndexSet::dimension) )
throw pybind11::value_error( "Invalid codimension: " + std::to_string( codim ) + " (must be in [0, " + std::to_string( IndexSet::dimension ) + "])" );
return self.size( codim );
} );
......@@ -265,8 +265,8 @@ namespace Dune
domain of the index set
)doc" );
Hybrid::forEach( std::make_integer_sequence< int, GridView::dimension+1 >(), [ &cls ] ( auto &&codim ) {
typedef typename GridView::template Codim< codim >::Entity Entity;
Hybrid::forEach( std::make_integer_sequence< int, IndexSet::dimension+1 >(), [ &cls ] ( auto &&codim ) {
typedef typename IndexSet::template Codim< codim >::Entity Entity;
using pybind11::operator""_a;
......@@ -310,7 +310,7 @@ namespace Dune
typedef typename GridView::IndexSet IndexSet;
auto cls = insertClass< IndexSet >( scope, "IndexSet", GenerateTypeName( MetaType< GridView >(), "IndexSet" ) ).first;
registerGridViewIndexSet< GridView >( scope, cls );
registerGridViewIndexSet( scope, cls );
return cls;
}
......
......@@ -168,7 +168,7 @@ namespace Dune
const auto tuple = pybind11::cast< pybind11::tuple >( layout );
if( pybind11::len( tuple ) != GridView::dimension+1 )
throw pybind11::value_error( "len(layout) must be " + std::to_string( GridView::dimension ) + "." );
for( int d = 0; d < GridView::dimension; ++d )
for( int d = 0; d <= GridView::dimension; ++d )
count[ d ] = pybind11::cast< int >( tuple[ GridView::dimension - d ] );
return new MCMGMapper( gridView, [ count ] ( Dune::GeometryType gt, int griddim ) { return count[ gt.dim() ]; } );
}
......@@ -179,7 +179,7 @@ namespace Dune
const auto list = pybind11::cast< pybind11::list >( layout );
if( pybind11::len( list ) != GridView::dimension+1 )
throw pybind11::value_error( "len(layout) must be " + std::to_string( GridView::dimension ) + "." );
for( int d = 0; d < GridView::dimension; ++d )
for( int d = 0; d <= GridView::dimension; ++d )
count[ d ] = pybind11::cast< int >( list[ GridView::dimension - d ] );
return new MCMGMapper( gridView, [ count ] ( Dune::GeometryType gt, int griddim ) { return count[ gt.dim() ]; } );
}
......@@ -390,15 +390,12 @@ namespace Dune
// registerMultipleCodimMultipleGeomTypeMapper
// -------------------------------------------
template<typename GridView>
auto registerMultipleCodimMultipleGeomTypeMapper(pybind11::handle scope)
template< class MCMGMapper, class... options >
inline static auto registerMultipleCodimMultipleGeomTypeMapper( pybind11::handle scope, pybind11::class_< MCMGMapper, options... > cls )
{
typedef typename MCMGMapper::GridView GridView;
using pybind11::operator""_a;
typedef MultipleCodimMultipleGeomTypeMapper<GridView> MCMGMapper;
auto cls = insertClass<MCMGMapper>(scope, "MultipleCodimMultipleGeomTypeMapper",
GenerateTypeName("Dune::MultipleCodimMultipleGeomTypeMapper", MetaType<GridView>()),
IncludeFiles{"dune/grid/common/mcmgmapper.hh","dune/python/grid/mapper.hh"}).first;
registerMapper<GridView>(cls);
cls.def( pybind11::init( [] ( const GridView &grid, pybind11::object layout ) {
return makeMultipleCodimMultipleGeomTypeMapper( grid, layout );
......@@ -421,6 +418,15 @@ namespace Dune
)doc" );
return cls;
}
template<typename GridView>
auto registerMultipleCodimMultipleGeomTypeMapper(pybind11::handle scope)
{
typedef MultipleCodimMultipleGeomTypeMapper<GridView> MCMGMapper;
auto cls = insertClass<MCMGMapper>(scope, "MultipleCodimMultipleGeomTypeMapper",
GenerateTypeName("Dune::MultipleCodimMultipleGeomTypeMapper", MetaType<GridView>()),
IncludeFiles{"dune/grid/common/mcmgmapper.hh","dune/python/grid/mapper.hh"}).first;
registerMultipleCodimMultipleGeomTypeMapper(scope,cls);
}
} // namespace Python
......
......@@ -16,6 +16,11 @@ logger = logging.getLogger(__name__)
class SimpleGenerator(object):
def __init__(self, typeName, namespace, pythonname=None, filename=None):
if not (isinstance(typeName,list) or isinstance(typeName,tuple)):
self.single = True
typeName = [typeName]
else:
self.single = False
self.typeName = typeName
if namespace:
self.namespace = namespace+"::"
......@@ -27,9 +32,7 @@ class SimpleGenerator(object):
self.pythonName = pythonname
self.fileName = filename
def load(self, includes, typeName, moduleName, *args, **kwargs):
defines = kwargs.get("defines",[])
preamble = kwargs.get("preamble",None)
def pre(self, includes, duneType, moduleName, defines=[], preamble=None):
source = '#include <config.h>\n\n'
source += '#define USING_DUNE_PYTHON 1\n\n'
source += ''.join(["#define " + d + "\n" for d in defines])
......@@ -48,39 +51,87 @@ class SimpleGenerator(object):
source += preamble
source += "\n"
source += "typedef " + typeName + " DuneType;\n"
source += "\n"
if self.namespace == "":
source += "void register" + self.typeName + "( ... ) {}\n"
source += "void register" + self.typeName[0] + "( ... ) {}\n"
source += "PYBIND11_MODULE( " + moduleName + ", module )\n"
source += "{\n"
source += " using pybind11::operator\"\"_a;\n"
options = kwargs.get("options", [])
if not kwargs.get("bufferProtocol", False):
return source
def main(self, nr, includes, duneType, *args,
options=[], bufferProtocol=False, dynamicAttr=False ):
source = " using pybind11::operator\"\"_a;\n"
if not bufferProtocol: # kwargs.get("bufferProtocol", False):
clsParams = []
else:
clsParams = ['pybind11::buffer_protocol()']
if kwargs.get("dynamicAttr", False):
if dynamicAttr:
clsParams += ['pybind11::dynamic_attr()']
source += ' auto cls = Dune::Python::insertClass' +\
'< DuneType' + ', '.join([""]+options) + ' >' +\
'( module, "' + self.pythonName + '"' +\
','.join(['']+clsParams) +\
', Dune::Python::GenerateTypeName("' + typeName + '")' +\
', Dune::Python::IncludeFiles{' + ','.join(['"' + i + '"' for i in includes]) + '}' +\
").first;\n"
source += " " + self.namespace + "register" + self.typeName + "( module, cls );\n"
if nr == 0:
module = "module"
else:
module = "cls0"
if nr == 0:
source += ' pybind11::handle cls0;\n'
source += ' {\n'
source += " typedef " + duneType + " DuneType;\n"
source += ' auto cls = Dune::Python::insertClass' +\
'< ' + duneType +\
', '.join([""]+options) + ' >' +\
'( ' + module + ', "' + self.typeName[nr] + '"' +\
','.join(['']+clsParams) +\
', Dune::Python::GenerateTypeName("' + duneType + '")' +\
', Dune::Python::IncludeFiles{' + ','.join(['"' + i + '"' for i in includes]) + '}' +\
").first;\n"
source += " " + self.namespace + "register" + self.typeName[nr] + "( module, cls );\n"
for arg in args:
if arg:
source += "".join(" " + s + "\n" for s in str(arg).splitlines())
source += "".join(" " + s + "\n" for s in str(arg).splitlines())
if nr == 0:
source += ' cls0 = cls;\n'
source += ' }\n'
return source
def post(self, moduleName, source):
source += "}\n"
module = builder.load(moduleName, source, self.pythonName)
# setattr(getattr(module,self.pythonName),"_module",module)
module = builder.load(moduleName, source, self.typeName[0])
return module
def _load(self, includes, duneType, moduleName, *args,
defines=[], preamble=None,
options=[], bufferProtocol=False, dynamicAttr=False ):
source = self.pre(includes, duneType, moduleName, defines=defines, preamble=preamble)
source += self.main(includes, duneType, *args,
options=options, bufferProtocol=bufferProtocol, dynamicAttr=dynamicAttr)
return self.post(moduleName, source)
def load(self, includes, typeName, moduleName, *args,
defines=[], preamble=None,
options=[], bufferProtocol=False, dynamicAttr=False ):
if self.single:
typeName = (typeName,)
options = (options,)
bufferProtocol = (bufferProtocol,)
dynamicAttr = (dynamicAttr,)
args = (args,)
else:
if args == ():
args=((),)*2
else:
args = args[0]
if options == ():
options = ((),)*len(typeName)
if not bufferProtocol:
bufferProtocol = (False,)*len(typeName)
if not dynamicAttr:
dynamicAttr = (False,)*len(typeName)
source = self.pre(includes, typeName[0], moduleName, defines, preamble)
for nr, (tn, a, o, b, d) in enumerate( zip(typeName, args, options, bufferProtocol, dynamicAttr) ):
source += self.main(nr, includes, tn, *a, options=o, bufferProtocol=b, dynamicAttr=d)
return self.post(moduleName, source)
from dune.common.hashit import hashIt
def simpleGenerator(inc, baseType, namespace, pythonname=None, filename=None):
generator = SimpleGenerator(baseType, namespace, pythonname, filename)
......
......@@ -10,8 +10,8 @@ registry = dict()
registry["grid"] = grid_registry
def leafGrid(*args, **kwargs):
return create(*args, **kwargs)
# def leafGrid(*args, **kwargs):
# return create(*args, **kwargs)
def _getGridFunction(view,y,dimR):
if dimR is None:
......
......@@ -123,6 +123,21 @@ def position(self,*arg,**kwarg):
def localPosition(self,*arg,**kwarg):
return self.toLocal(*arg,**kwarg)
isGenerator = SimpleGenerator("GridViewIndexSet", "Dune::Python")
def indexSet(gv):
includes = gv._includes + ["dune/python/grid/indexset.hh"]
typeName = gv._typeName+"::IndexSet"
moduleName = "indexset_" + hashIt(typeName)
module = isGenerator.load(includes, typeName, moduleName)
return gv._indexSet
mcmgGenerator = SimpleGenerator("MultipleCodimMultipleGeomTypeMapper", "Dune::Python")
def mapper(gv,layout):
includes = gv._includes + ["dune/python/grid/mapper.hh"]
typeName = "Dune::MultipleCodimMultipleGeomTypeMapper< "+gv._typeName+" >"
moduleName = "mcmgmapper_" + hashIt(typeName)
module = mcmgGenerator.load(includes, typeName, moduleName)
return gv._mapper(layout)
def addAttr(module, cls):
setattr(cls, "_module", module)
setattr(cls, "writeVTK", writeVTK)
......@@ -151,23 +166,30 @@ def addAttr(module, cls):
Geo.domain = property(domain)
setattr( Geo, "position", position)
setattr( Geo, "localPosition", localPosition)
cls.indexSet = property(indexSet)
setattr(cls,"mapper",mapper)
gvGenerator = SimpleGenerator("GridView", "Dune::Python")
def levelView(hgrid,level):
includes = hgrid._includes + ["dune/python/grid/gridview.hh"]
typeName = "typename "+hgrid._typeName+"::LevelGridView"
moduleName = "view_" + hashIt(typeName)
module = gvGenerator.load(includes, typeName, moduleName)
addAttr(module, module.GridView)
return hgrid._levelView(level)
generator = SimpleGenerator("HierarchicalGrid", "Dune::Python")
def module(includes, typeName, *args):
includes = includes + ["dune/python/grid/hierarchical.hh"]
typeHash = "hierarchicalgrid_" + hashIt(typeName)
module = generator.load(includes, typeName, typeHash, *args)
addAttr(module, module.LeafGrid)
addAttr(module, module.LevelGrid)
# register reference element for this grid
import dune.geometry
for d in range(module.LeafGrid.dimension+1):
dune.geometry.module(d)
setattr(module.HierarchicalGrid,"levelView",levelView)
return module
......
Markdown is supported
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