I am working with a mixed formulation problem, where in my .ufl file I defined
V = FiniteElement("Lagrange", triangle, 1)
W = V*V
In the .cpp file I obtain a solution $p$ living in the dual space W which components I can plot without concern
Function p(W);
solve(a == L, p, bcs);
Function& p1 = p[0];
Function& p2 = p[1];
plot(p1,"Real part");
plot(p2,"Imaginary part");
interactive();
I would now like to plot the sources as well, so I tried doing
Function f1(W->sub(0));
Function f2(W->sub(1));
Source1 source1;
Source2 source2;
f1.interpolate(source1);
f2.interpolate(source2);
But I get the error
Error: Unable to create function.
Reason: Cannot be created from subspace. Consider collapsing the function space.
So, how do I access (or define) a subspace of my dual space?
As a small (not) working example consider
# Compile this form with FFC: ffc -l dolfin Complex.ufl.
V = FiniteElement("CG", triangle, 1)
W = V*V
(u_r, u_i) = TrialFunction(W)
(v_r, v_i) = TestFunction(W)
f_r = Coefficient(V)
f_i = Coefficient(V)
a_r = inner(grad(u_r),grad(v_r))*dx - inner(grad(u_i),grad(v_i))*dx
a_i = inner(grad(u_r),grad(v_i))*dx + inner(grad(u_i),grad(v_r))*dx
L_r = inner(f_r,v_r)*dx - inner(f_i,v_i)*dx
L_i = inner(f_r, v_i)*dx + inner(f_i,v_r)*dx
a = a_r + a_i
L = L_r + L_i
#include <dolfin.h>
#include "Complex.h"
#include <mshr.h>
using namespace dolfin;
// Source term
class SourceReal : public Expression
{
public:
void eval(Array<double>& values, const Array<double>& x) const
{
values[0] = cos(2*DOLFIN_PI * x[0]);
}
};
class SourceImag : public Expression
{
public:
void eval(Array<double>& values, const Array<double>& x) const
{
values[0] = sin(2*DOLFIN_PI * x[0]);
}
};
class BoundaryValue : public Expression
{
public:
void eval(Array<double>& values, const Array<double>& x) const
{
values[0] = 0.0;
}
};
// Sub domains for Dirichlet boundary conditions
class DirichletBCBox : public SubDomain
{
bool inside(const Array<double>& x, bool on_boundary) const
{
return ((x[0] < -1 + sqrt(DOLFIN_EPS) or x[0] > 1 - sqrt(DOLFIN_EPS) or x[1] < 1 + sqrt(DOLFIN_EPS) or x[1] > 1 - sqrt(DOLFIN_EPS)) and on_boundary);
}
};
int main()
{
//File file("results/Round_no_cloak.pvd");
// Mesh definition
auto rectangle = std::make_shared<mshr::Rectangle>(dolfin::Point(-1.0, 1.0, 0.0), dolfin::Point(1.0, -1.0, 0.0));
auto mesh = mshr::generate_mesh(*rectangle, 100);
auto W = std::make_shared<Complex::FunctionSpace>(mesh);
auto f_real = std::make_shared<SourceReal>();
auto f_imag = std::make_shared<SourceImag>();
auto boundary = std::make_shared<DirichletBCBox>();
DirichletBC bc1(W->sub(0), std::make_shared<BoundaryValue>(), boundary);
DirichletBC bc2(W->sub(1), std::make_shared<BoundaryValue>(), boundary);
std::vector<const DirichletBC*> bcs;
bcs.push_back(&bc1);
bcs.push_back(&bc2);
Complex::BilinearForm a(W, W);
Complex::LinearForm L(W);
L.f_r = f_real;
L.f_i = f_imag;
Function w(W);
solve(a == L, w, bcs);
// Extract sub functions (function views)
Function& u_real = w[0];
Function& u_imag = w[1];
plot(u_real,"Real part");
plot(u_imag,"Imaginary part");
Function p_real(W->sub(0));
Function p_imag(W->sub(1));
SourceReal source1;
SourceImag source2;
p_real.interpolate(source1);
p_imag.interpolate(source2);
plot(p_real);
interactive();
return 0;
}