How to access CreateSmoothingBlocks from python for fes?


I am trying to use the “many” default smoothing blocks implemented for finite element spaces for preconditioning.
So I tried to export CreateSmoothingBlocks for a finite element space (EdgeFESpace is “exactly” your NedelecFESpace), with

ExportFESpace<EdgeFESpace> (m, "EdgeFESpace")                                 
 .def("CreateSmoothingBlocks", [](shared_ptr<EdgeFESpace> self, int type) {  
    return self->CreateSmoothingBlocks(type);                     
 py::arg("type"), "create smoothing block for this type")               

But when I call


python complains:

TypeError: Unable to convert function return value to a Python type! The signature was
	(self: xfem.ngsxfem_py.EdgeFESpace, type: int) -> ngcore::Table<int, unsigned long>

I didn’t find a solution to this in the source files. Can you help with this?


This means that the class Table<int, unsigned long> doesn’t have a Python equivalent (=export). You can either export the table or convert the table first to some Python object (for example a list of lists).

Yes. I noticed that the python list will then be converted back to Table <int, unsigned long> in the CreateBlockSmoother class.
But, I haven’t found a way to convert the Table<int, …> class back to python list back. I don’t know how to create a python list in C++.

Something like

py::list pytable;
for(const auto& row : table)

should work.

But you could as well just export the Table and write another python constructor for the smoother to be constructed with a table, then you don’t have to copy


Thanks, Christopher. This works.
I need to change the loop to

for(const auto& row : *table)

as table is a smart pointer from CreateSmoothingBlocks.

The code works much faster now.
So, there is basically no difference from the python end whether the block is a list of lists or a list of sets (which we use to generate the blocks in the python script) because they will simply be converted to the Table type in CreateBlockSmoother, right?

To create a new python BlockSmoother constructor that takes the table as input seems the fastest approach, but then I need to modify the source file in linalg/python_linalg.cpp, which is a bit of a headache for me. (if you could include this in later ngsolve versions, that would be great :wink:

Currently I am simply adding “new” fespaces/classes in a separate project, which I feel a little bit safer as I don’t need to directly touch the git source files.

list and set shouldn’t make a difference, in Python we use set to prevent double entries.

You could create a separate Python function that takes in a table and returns a smoother.

Oh, yes. I can create a python function that takes in a table, and a basematrix to directly create the smoother. This approach further speed up the process by about a factor of 2. Thanks again!
For the timing of constructing a vertex patch block in 3D, python looping is about 200 times slower than the C++ looping (the AFW block in edge space) in my machine, which I found quite interesting.

Yes, this is to be expected. The pythonic way of creating the smoother is certainly more for studying purposes than for production code.