Hello,
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
fes.CreateSmoothingBlocks(0)
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?
Best,
Guosheng
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).
Best
Christopher
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)
pytable.append(MakePyList(row));
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
Best
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 
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.