I'm trying to apply the Different material tutorial to C++.
As a simple test, I'm trying to solve the Poisson equation times a scalar parameter k on a square mesh where the value of k is different depending on whether we are on the left or right half of the mesh.
In particular, I don't see how I could translate in C++ the python code
k_values = [1.5, 50] # values of k in the two subdomains
for cell_no in range(len(subdomains.array())):
subdomain_no = subdomains.array()[cell_no]
k.vector()[cell_no] = k_values[subdomain_no]
Also, I am wondering whether it would be possible to somehow define two dx(0) and dx(1) so that the definition of the bilinear form in the .ufl file would look like
a = k0*inner(grad(u), grad(v))*dx(0) + k1*inner(grad(u), grad(v))*dx(1)
My incomplete and not working code so far is
# The bilinear form a(u, v) and linear form L(v) for
# Poisson's equation.
#
# Compile this form with FFC: ffc -l dolfin Poisson.ufl.
V = FiniteElement("Lagrange", triangle, 1)
u = TrialFunction(V)
v = TestFunction(V)
f = Coefficient(V)
k = Coefficient(V)
a = k*inner(grad(u), grad(v))*dx
L = f*v*dx
// This program solves Poisson's equation
//
// - div grad u(x, y) = f(x, y)
//
// on the [-1,1]x[-1,1] square with source f given by
//
// f(x, y) = - 4*exp(x^2 + y^2) * (1 + x^2 + y^2)
//
// and Dirichlet boundary conditions given by
//
// u(x, y) = exp(1)
#include <dolfin.h>
#include "Poisson.h"
#include <mshr.h>
using namespace dolfin;
// Source term (right-hand side)
class Source : public Expression
{
void eval(Array<double>& values, const Array<double>& x) const
{
double dx = x[0];
double dy = x[1];
values[0] = - 4*exp(dx*dx + dy*dy)*(1 + dx*dx + dy*dy);
}
};
// Sub domain for Dirichlet boundary condition
class DirichletBoundary : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
return ((x[0] < -1 + DOLFIN_EPS or x[0] > 1 - DOLFIN_EPS or x[1] < -1 + DOLFIN_EPS or x[1] > 1 - DOLFIN_EPS) and on_boundary);
}
};
// Left half of mesh
class Omega0 : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
if (x[0] <= 1.0)
return true;
else
return false;
}
};
// Right half of mesh
class Omega1 : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
if (x[0] >= 1.0)
return true;
else
return false;
}
};
int main()
{
auto circle = mshr::Rectangle(dolfin::Point(-1.0, 1.0, 0.0),dolfin::Point(1.0, -1.0, 0.0));
auto mesh = mshr::generate_mesh(circle, 32);
auto V = std::make_shared<Poisson::FunctionSpace>(mesh);
Omega0 omega0;
auto omega0_function = std::make_shared<MeshFunction<std::size_t>>(mesh, 2);
omega0.mark(*omega0_function, 0);
Omega1 omega1;
auto omega1_function = std::make_shared<MeshFunction<std::size_t>>(mesh, 2);
omega1.mark(*omega1_function, 1);
// Define boundary condition
auto u0 = std::make_shared<Constant>(exp(1.0));
auto boundary = std::make_shared<DirichletBoundary>();
DirichletBC bc(V, u0, boundary);
// Define variational forms
Poisson::BilinearForm a(V, V);
Poisson::LinearForm L(V);
auto f = std::make_shared<Source>();
L.f = f;
// Compute solution
Function u(V);
solve(a == L, u, bc);
// Save solution in VTK format
File file("poisson.pvd");
file << u;
// Plot solution
plot(u);
interactive();
return 0;
}
Thanks for your help!