I'm trying to build a mesh manually because I am linking Fenics into another project I'm working on where a mesh structure is already defined. It makes more sense to build the mesh in code rather than import two separate files.
Further, I would like to be able to assign the vertex and cell indices so that they correspond with the other mesh data structure that I'm already using.
When I try to do this, I am getting the error
*** Error: Unable to set given (local) rows to identity matrix.
*** Reason: some diagonal elements not preallocated (try assembler option keep_diagonal).
*** Where: This error was encountered inside PETScMatrix.cpp.
*** Process: 0
*** DOLFIN version: 2016.1.0
*** Git changeset: unknown
Here is a minimum working example
#include <iostream>
/*---------------------------------------------------------------------------*/
#include <dolfin.h>
#include "pde.h"
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
// Sub domain for Dirichlet boundary condition
class DirichletBoundary : public dolfin::SubDomain
{
bool inside(const dolfin::Array<double>& x, bool on_boundary) const
{ return on_boundary; }
};
// a function that gives the representation vector at every point on the boundary
class RepresentationVectorFunction : public dolfin::Expression
{
public:
RepresentationVectorFunction(std::size_t dim):dolfin::Expression(dim){}
private:
void eval(dolfin::Array<double> &values, const dolfin::Array<double> &x) const
{
values[0] = 0;
values[1] = 1;
}
};
/*---------------------------------------------------------------------------*/
int main()
{
//Create the mesh and open for editing
auto mesh = std::make_shared<dolfin::Mesh>();
dolfin::MeshEditor editor;
editor.open(*mesh, 2, 2);
std::vector<double> v = {0,0 //0
,0,1 //1
,0,2 //2
,1,0 //3
,1,1 //4
,1,2 //5
,2,0 //6
,2,1 //7
,2,2}; //8
editor.init_vertices(v.size());
int vertex_id = 0;
for (unsigned int i = 0; i < v.size(); i += 2)
{
editor.add_vertex(vertex_id++,v[i],v[i+1]);
}
int num_triangles = 8;
editor.init_cells(num_triangles);
editor.add_cell(0, 0,1,4);
editor.add_cell(1, 0,4,3);
editor.add_cell(2, 1,2,5);
editor.add_cell(3, 1,5,4);
editor.add_cell(4, 3,4,7);
editor.add_cell(5, 3,7,6);
editor.add_cell(6, 4,5,8);
editor.add_cell(7, 4,8,7);
// Close the mesh for editing
editor.close();
dolfin::plot(mesh);
dolfin::interactive();
// Create function space
auto V = std::make_shared<pde::FunctionSpace>(mesh);
auto f = std::make_shared<dolfin::Constant>(0,0);
// Define boundary condition
auto u0 = std::make_shared<RepresentationVectorFunction>(2);
auto boundary = std::make_shared<DirichletBoundary>();
dolfin::DirichletBC bc(V, u0, boundary);
// Define pde variational problem
pde::BilinearForm a(V, V);
pde::LinearForm L(V);
L.f = f;
// Compute pde solution
auto u = std::make_shared<dolfin::Function>(V);
dolfin::solve(a == L, *u, bc);
return 0;
}
The UFL file is
# Elements
V = VectorElement("Lagrange", triangle, 2)
# Trial and test functions
u = TrialFunction(V)
v = TestFunction(V)
f = Coefficient(V)
# Bilinear form
a = inner(grad(u), grad(v))*dx
# Linear form
L = dot(v,f)*dx