upgrade from 2017.1 to 2019.1: cppcode in Expressions
I’m in the process of upgrading a 2017.1-compatible dolfin code to 2019.1. Here I have a fairly complex Expression
that relies on cppcode:
def supg(mesh, convection, diffusion, element_degree):
cppcode = """#include <dolfin/mesh/Vertex.h>
class SupgStab : public Expression {
public:
double epsilon;
int p;
std::shared_ptr<GenericFunction> convection;
std::shared_ptr<Mesh> mesh;
SupgStab(): Expression()
{}
void eval(
Array<double>& tau,
const Array<double>& x,
const ufc::cell& c
) const
{
Array<double> v(x.size());
convection->eval(v, x, c);
double conv_norm = 0.0;
for (uint i = 0; i < v.size(); ++i)
conv_norm += v[i]*v[i];
conv_norm = sqrt(conv_norm);
Cell cell(*mesh, c.index);
//// The alternative for the lazy:
//const double h = cell.diameter();
// Compute the directed diameter of the cell, cf. :cite:`sold2`.
//
// diam(cell, s) = 2*||s|| / sum_{nodes n_i} |s.\\grad\\psi|
//
// where \\psi is the P_1 basis function of n_i.
//
const double area = cell.volume();
const unsigned int* vertices = cell.entities(0);
assert(vertices);
double sum = 0.0;
for (int i=0; i<3; i++) {
for (int j=i+1; j<3; j++) {
// Get edge coords.
const dolfin::Vertex v0(*mesh, vertices[i]);
const dolfin::Vertex v1(*mesh, vertices[j]);
const Point p0 = v0.point();
const Point p1 = v1.point();
const double e0 = p0[0] - p1[0];
const double e1 = p0[1] - p1[1];
// Note that
//
// \\grad\\psi = ortho_edge / edgelength / height
// = ortho_edge / (2*area)
//
// so
//
// (v.\\grad\\psi) = (v.ortho_edge) / (2*area).
//
// Move the constant factors out of the summation.
//
// It would be really nice if we could just do
// edge.dot((-v[1], v[0]))
// but unfortunately, edges just dot with other edges.
sum += fabs(e1*v[0] - e0*v[1]);
}
}
const double h = 4 * conv_norm * area / sum;
// Just a little sanity check here.
assert(h <= cell.diameter());
const double Pe = 0.5*conv_norm * h/(p*epsilon);
assert(Pe > 0.0);
// We'd like to compute `xi = (1.0/tanh(Pe) - 1.0/Pe) / Pe`. This expression
// can hardly be evaluated for small Pe, see
// <https://stackoverflow.com/a/43279491/353337>. Hence, use its Taylor
// expansion around 0.
const double xi = Pe > 1.0e-5 ?
(1.0/tanh(Pe) - 1.0/Pe) / Pe :
1.0/3.0 - Pe*Pe / 45.0 + 2.0/945.0 * Pe*Pe*Pe*Pe;
// const double xi = (Pe > 1.0 ? 1.0 - 1.0/Pe : 0.0) / Pe;
tau[0] = h*h / 4 / epsilon / p * xi;
if (tau[0] > 1.0e3)
{
std::cout << "tau = " << tau[0] << std::endl;
std::cout << "||b|| = " << conv_norm << std::endl;
std::cout << "Pe = " << Pe << std::endl;
std::cout << "h = " << h << std::endl;
std::cout << "xi = " << xi << std::endl;
throw 1;
}
return;
}
};
"""
# TODO set degree
tau = Expression(cppcode, degree=5)
tau.convection = convection
tau.mesh = mesh
tau.epsilon = diffusion
tau.p = element_degree
return tau
With 2019.1, this fails to compile. In the generated output, I find
void eval(Eigen::Ref<Eigen::VectorXd> values, Eigen::Ref<const Eigen::VectorXd> x) const override
{
values[0] = #include <dolfin/mesh/Vertex.h>
// [...]
so I’m guessing the entire cppcode
is supposed to be one expression that’s a valid rhs.
Well, I don’t have that. Any hint on how to modify the code?
Comments (14)
-
-
reporter Thanks Michal for the link, this helped me a great deal. This now gets me to the cryptic
E ImportError: generic_type: type "SupgStab" referenced unknown base type "dolfin::Expression"
Any idea what this might be about?
-
Maybe you forgot to
#include <dolfin/function/Expression.h>
in the cpp string beginning? -
reporter MWE:
from dolfin import compile_cpp_code cppcode = """ #include <dolfin/function/Expression.h> #include <pybind11/pybind11.h> namespace py = pybind11; class SupgStab : public dolfin::Expression { public: SupgStab(): dolfin::Expression() {} }; PYBIND11_MODULE(SIGNATURE, m) { py::class_<SupgStab, std::shared_ptr<SupgStab>, dolfin::Expression> (m, "SupgStab") .def(py::init<>()); } """ compiled_module = compile_cpp_code(cppcode)
-
reporter Okay, even the linked demo fails with this error on my machine
ImportError: generic_type: type "Conductivity" referenced unknown base type "dolfin::Expression"
Apparently, something is wrong with my installation. Hm.
-
Sorry for delayed response. It seems the pybind cpp code cannot find dolfin. You can pass
include_dirs
andlibraries
as kwargs to compile_cpp_code. Try to manually include dolfin cpp library. -
reporter Huh? That’s funny. Everything is in the default directories, installed from Debian. And indeed,
compiled_module = compile_cpp_code(cppcode, include_dirs=["/usr/include/"])
doesn’t help. I would have expected a different error on missing includes/linker errors, too.
-
I am having a similar issue, which arose here. I boot up a Docker container running fenics 2109.1 and try to create a compiled expression with
from dolfin import * cpp_code = """ #include <pybind11/pybind11.h> #include <dolfin.h> namespace py = pybind11; #include <dolfin/function/Expression.h> class Profile : public dolfin::Expression { public: Profile() : dolfin::Expression(){} }; PYBIND11_MODULE(SIGNATURE, m) { py::class_<Profile, std::shared_ptr<Profile>, dolfin::Expression> (m, "Profile") .def(py::init<>()); } """ # Compile expression expr = CompiledExpression(compile_cpp_code(cpp_code, include_dirs=["/usr/local/include/"]).Profile(), degree=1)
This fails with the error:
Traceback (most recent call last):
File "expr_test.py", line 27, in <module>
expr = CompiledExpression(compile_cpp_code(cpp_code, include_dirs=["/usr/local/include/"]).Profile(), degree=1)
File "/usr/local/lib/python3.6/dist-packages/dolfin/jit/pybind11jit.py", line 96, in compile_cpp_code
generate=jit_generate)
File "/usr/local/lib/python3.6/dist-packages/dolfin/jit/jit.py", line 47, in mpi_jit
return local_jit(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/dolfin/jit/jit.py", line 103, in dijitso_jit
return dijitso.jit(*args, **kwargs)
File "/usr/local/lib/python3.6/dist-packages/dijitso/jit.py", line 212, in jit
lib = load_library(signature, cache_params)
File "/usr/local/lib/python3.6/dist-packages/dijitso/cache.py", line 363, in load_library
lib = __import__(signature)
ImportError: generic_type: type "Profile" referenced unknown base type "dolfin::Expression"
Any progress in understanding this issue?
-
Hi, I am having the same issue, are there updates on this?
-
This is resolved in the latest dev image:
quay.io/fenicsproject/dev:latest
. -
Hi, can this be fixed in the Debian/Ubuntu packages? I am using the FEniCS PPA on Ubuntu 20.04 (as described here: https://fenics.readthedocs.io/en/latest/installation.html#ubuntu-ppa) and I am getting the same error.
-
There has been talk about having a new/final release of dolfin (as all development has moved to dolfinx). With this release I think it would be natural to update the debian packages. Usually @Drew Parsons is kind enough to build these packages for us. @Marie Elisabeth Rognes @Cécile Daversin-Catty , are we closing in on a release? UFL has already been tagged with: 2021.1.0
-
Would be nice to release a last(?) FEniCS (non-x) yes. I’ll discuss with the SC.
-
I have it too on 2019.2, and waiting for a new Ubuntu PPA. Is there any progress @Marie Elisabeth Rognes ?
- Log in to comment
Hi Nico,
please see the CompiledExpression interface, https://bitbucket.org/fenics-project/dolfin/src/master/python/demo/documented/tensor-weighted-poisson/demo_tensor-weighted-poisson.py
One basically defines entire cpp file string which is compiled into python layer with pybind11.