syfi-1.0.0.dfsg.orig/ 0000700 0001750 0001750 00000000000 11674103626 014217 5 ustar johannr johannr syfi-1.0.0.dfsg.orig/syfi/ 0000755 0001750 0001750 00000000000 11674103626 015203 5 ustar johannr johannr syfi-1.0.0.dfsg.orig/syfi/RaviartThomas.cpp 0000644 0001750 0001750 00000050333 11672223006 020470 0 ustar johannr johannr // Copyright (C) 2006-2009 Kent-Andre Mardal and Simula Research Laboratory
//
// This file is part of SyFi.
//
// SyFi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// SyFi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SyFi. If not, see .
#include "RaviartThomas.h"
#include
#include "tools.h"
using std::cout;
using std::endl;
using std::string;
namespace SyFi
{
RaviartThomas:: RaviartThomas() : StandardFE()
{
description = "RaviartThomas";
}
RaviartThomas:: RaviartThomas(Polygon& p, int order, bool pointwise_) : StandardFE(p, order)
{
pointwise = pointwise_;
compute_basis_functions();
}
void RaviartThomas:: compute_basis_functions()
{
if ( order < 1 )
{
throw(std::logic_error("Raviart-Thomas elements must be of order 1 or higher."));
}
if ( p == NULL )
{
throw(std::logic_error("You need to set a polygon before the basisfunctions can be computed"));
}
// see e.g. Brezzi and Fortin book page 116 for the definition
GiNaC::ex nsymb = GiNaC::symbol("n");
if (pointwise)
{
if ( p->str().find("ReferenceLine") != string::npos )
{
cout <<"Can not define the Raviart-Thomas element on a line"<str().find("Triangle") != string::npos )
{
description = istr("RaviartThomas_", order) + "_2D";
Triangle& triangle = (Triangle&)(*p);
GiNaC::lst equations;
GiNaC::lst variables;
GiNaC::ex polynom_space1 = bernstein(order-1, triangle, "a");
GiNaC::ex polynom1 = polynom_space1.op(0);
GiNaC::ex polynom1_vars = polynom_space1.op(1);
GiNaC::ex polynom1_basis = polynom_space1.op(2);
GiNaC::lst polynom_space2 = bernsteinv(2,order-1, triangle, "b");
GiNaC::ex polynom2 = polynom_space2.op(0).op(0);
GiNaC::ex polynom3 = polynom_space2.op(0).op(1);
GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x,
polynom3 + polynom1*y);
GiNaC::lst v2 = collapse(GiNaC::ex_to(polynom_space2.op(1)));
variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));
// remove multiple dofs
if ( order >= 2)
{
GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
for (unsigned int c1=0; c1<= order-2;c1++)
{
for (unsigned int c2=0; c2<= order-2;c2++)
{
for (unsigned int c3=0; c3<= order-2;c3++)
{
if ( c1 + c2 + c3 <= order -2 )
{
GiNaC::ex eq = expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);
if ( eq != GiNaC::numeric(0) )
{
equations.append(eq == 0);
}
}
}
}
}
}
int removed_dofs = equations.nops();
GiNaC::ex bernstein_pol;
int counter = 0;
GiNaC::symbol t("t");
GiNaC::ex dofi;
// dofs related to edges
for (int i=0; i< 3; i++)
{
Line line = triangle.line(i);
GiNaC::lst normal_vec = normal(triangle, i);
GiNaC::ex Vn = inner(pspace, normal_vec);
GiNaC::lst points = interior_coordinates(line, order-1);
GiNaC::ex edge_length = line.integrate(GiNaC::numeric(1));
GiNaC::ex point;
for (unsigned int j=0; j< points.nops(); j++)
{
point = points.op(j);
dofi = Vn.subs(x == point.op(0)).subs(y == point.op(1))*edge_length;
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,nsymb));
}
}
// dofs related to the whole triangle
if ( order > 1)
{
counter++;
GiNaC::lst points = interior_coordinates(triangle, order-2);
GiNaC::ex point;
for (unsigned int j=0; j< points.nops(); j++)
{
point = points.op(j);
// x -component
dofi = pspace.op(0).subs(x == point.op(0)).subs(y == point.op(1));
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,0));
// y -component
dofi = pspace.op(1).subs(x == point.op(0)).subs(y == point.op(1));
eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,1));
}
}
// std::cout <<"no variables "<(b));
GiNaC::lst subs;
for (unsigned int ii=0; iistr().find("Tetrahedron") != string::npos )
{
description = istr("RaviartThomas_", order) + "_3D";
Tetrahedron& tetrahedron = (Tetrahedron&)(*p);
GiNaC::lst equations;
GiNaC::lst variables;
GiNaC::ex polynom_space1 = bernstein(order-1, tetrahedron, "a");
GiNaC::ex polynom1 = polynom_space1.op(0);
GiNaC::ex polynom1_vars = polynom_space1.op(1);
GiNaC::ex polynom1_basis = polynom_space1.op(2);
GiNaC::lst polynom_space2 = bernsteinv(3,order-1, tetrahedron, "b");
GiNaC::ex polynom2 = polynom_space2.op(0).op(0);
GiNaC::ex polynom3 = polynom_space2.op(0).op(1);
GiNaC::ex polynom4 = polynom_space2.op(0).op(2);
GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x,
polynom3 + polynom1*y,
polynom4 + polynom1*z);
GiNaC::lst v2 = collapse(GiNaC::ex_to(polynom_space2.op(1)));
variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));
GiNaC::ex bernstein_pol;
// remove multiple dofs
if ( order >= 2)
{
GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
for (unsigned int c1=0; c1<= order-2;c1++)
{
for (unsigned int c2=0; c2<= order-2;c2++)
{
for (unsigned int c3=0; c3<= order-2;c3++)
{
if ( c1 + c2 + c3 <= order -2 )
{
GiNaC::ex eq = expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);
if ( eq != GiNaC::numeric(0) )
{
equations.append(eq == 0);
}
}
}
}
}
}
int removed_dofs = equations.nops();
GiNaC::symbol t("t");
GiNaC::ex dofi;
// dofs related to edges
for (int i=0; i< 4; i++)
{
Triangle triangle = tetrahedron.triangle(i);
GiNaC::lst normal_vec = normal(tetrahedron, i);
GiNaC::ex Vn = inner(pspace, normal_vec);
GiNaC::lst points = interior_coordinates(triangle, order-1);
GiNaC::ex triangle_size = triangle.integrate(GiNaC::numeric(1));
GiNaC::ex point;
for (unsigned int j=0; j< points.nops(); j++)
{
point = points.op(j);
dofi = Vn.subs(x == point.op(0)).subs(y == point.op(1)).subs(z == point.op(2))*triangle_size;
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,nsymb));
}
}
// dofs related to the whole tetrahedron
if ( order > 1)
{
GiNaC::lst points = interior_coordinates(tetrahedron, order-2);
GiNaC::ex point;
for (unsigned int j=0; j< points.nops(); j++)
{
point = points.op(j);
// x -component
dofi = pspace.op(0).subs(x == point.op(0)).subs(y == point.op(1)).subs(z == point.op(2));
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,0));
// y -component
dofi = pspace.op(1).subs(x == point.op(0)).subs(y == point.op(1)).subs(z == point.op(2));
eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,1));
// z -component
dofi = pspace.op(2).subs(x == point.op(0)).subs(y == point.op(1)).subs(z == point.op(2));
eq = dofi == GiNaC::numeric(0);
equations.append(eq);
dofs.insert(dofs.end(), GiNaC::lst(point,1));
}
}
// std::cout <<"no variables "<(b));
GiNaC::lst subs;
for (unsigned int ii=0; iistr().find("ReferenceLine") != string::npos )
{
cout <<"Can not define the Raviart-Thomas element on a line"<str().find("Triangle") != string::npos )
{
description = istr("RaviartThomas_", order) + "_2D";
Triangle& triangle = (Triangle&)(*p);
GiNaC::lst equations;
GiNaC::lst variables;
GiNaC::ex polynom_space1 = bernstein(order-1, triangle, "a");
GiNaC::ex polynom1 = polynom_space1.op(0);
GiNaC::ex polynom1_vars = polynom_space1.op(1);
GiNaC::ex polynom1_basis = polynom_space1.op(2);
GiNaC::lst polynom_space2 = bernsteinv(2,order-1, triangle, "b");
GiNaC::ex polynom2 = polynom_space2.op(0).op(0);
GiNaC::ex polynom3 = polynom_space2.op(0).op(1);
GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x,
polynom3 + polynom1*y);
GiNaC::lst v2 = collapse(GiNaC::ex_to(polynom_space2.op(1)));
variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));
// remove multiple dofs
if ( order >= 2)
{
GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
for (unsigned int c1=0; c1<= order-2;c1++)
{
for (unsigned int c2=0; c2<= order-2;c2++)
{
for (unsigned int c3=0; c3<= order-2;c3++)
{
if ( c1 + c2 + c3 <= order -2 )
{
GiNaC::ex eq = expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);
if ( eq != GiNaC::numeric(0) )
{
equations.append(eq == 0);
}
}
}
}
}
}
int removed_dofs = equations.nops();
GiNaC::ex bernstein_pol;
int counter = 0;
GiNaC::symbol t("t");
GiNaC::ex dofi;
// dofs related to edges
for (int i=0; i< 3; i++)
{
Line line = triangle.line(i);
GiNaC::lst normal_vec = normal(triangle, i);
bernstein_pol = bernstein(order-1, line, istr("a",i));
GiNaC::ex basis_space = bernstein_pol.op(2);
GiNaC::ex pspace_n = inner(pspace, normal_vec);
GiNaC::ex basis;
for (unsigned int j=0; j< basis_space.nops(); j++)
{
counter++;
basis = basis_space.op(j);
GiNaC::ex integrand = pspace_n*basis;
dofi = line.integrate(integrand);
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
GiNaC::lst d = GiNaC::lst(GiNaC::lst(line.vertex(0), line.vertex(1)),j);
dofs.insert(dofs.end(), d);
GiNaC::ex u = GiNaC::matrix(2,1,GiNaC::lst(GiNaC::symbol("v[0]"), GiNaC::symbol("v[1]")));
GiNaC::ex n = GiNaC::matrix(2,1,GiNaC::lst(GiNaC::symbol("normal_vec[0]"), GiNaC::symbol("normal_vec[1]")));
dof_repr.append(GiNaC::lst(inner(u,n)*basis.subs( x == GiNaC::symbol("xi[0]"))
.subs( y == GiNaC::symbol("xi[1]")), d));
}
}
// dofs related to the whole triangle
GiNaC::lst bernstein_polv;
if ( order > 1)
{
counter++;
bernstein_polv = bernsteinv(2,order-2, triangle, "a");
GiNaC::ex basis_space = bernstein_polv.op(2);
for (unsigned int i=0; i< basis_space.nops(); i++)
{
GiNaC::lst basis = GiNaC::ex_to(basis_space.op(i));
GiNaC::ex integrand = inner(pspace, basis);
dofi = triangle.integrate(integrand);
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
GiNaC::lst d = GiNaC::lst(GiNaC::lst(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2)), i);
dofs.insert(dofs.end(), d);
}
}
// invert the matrix:
// GiNaC has a bit strange way to invert a matrix.
// It solves the system AA^{-1} = Id.
// It seems that this way is the only way to do
// properly with the solve_algo::gauss flag.
//
GiNaC::matrix b; GiNaC::matrix A;
matrix_from_equations(equations, variables, A, b);
unsigned int ncols = A.cols();
GiNaC::matrix vars_sq(ncols, ncols);
// matrix of symbols
for (unsigned r=0; r(b));
GiNaC::lst subs;
for (unsigned int ii=0; iistr().find("Tetrahedron") != string::npos )
{
description = istr("RaviartThomas_", order) + "_3D";
Tetrahedron& tetrahedron = (Tetrahedron&)(*p);
GiNaC::lst equations;
GiNaC::lst variables;
GiNaC::ex polynom_space1 = bernstein(order-1, tetrahedron, "a");
GiNaC::ex polynom1 = polynom_space1.op(0);
GiNaC::ex polynom1_vars = polynom_space1.op(1);
GiNaC::ex polynom1_basis = polynom_space1.op(2);
GiNaC::lst polynom_space2 = bernsteinv(3,order-1, tetrahedron, "b");
GiNaC::ex polynom2 = polynom_space2.op(0).op(0);
GiNaC::ex polynom3 = polynom_space2.op(0).op(1);
GiNaC::ex polynom4 = polynom_space2.op(0).op(2);
GiNaC::lst pspace = GiNaC::lst( polynom2 + polynom1*x,
polynom3 + polynom1*y,
polynom4 + polynom1*z);
GiNaC::lst v2 = collapse(GiNaC::ex_to(polynom_space2.op(1)));
variables = collapse(GiNaC::lst(polynom_space1.op(1), v2));
GiNaC::ex bernstein_pol;
// remove multiple dofs
if ( order >= 2)
{
GiNaC::ex expanded_pol = GiNaC::expand(polynom1);
for (unsigned int c1=0; c1<= order-2;c1++)
{
for (unsigned int c2=0; c2<= order-2;c2++)
{
for (unsigned int c3=0; c3<= order-2;c3++)
{
if ( c1 + c2 + c3 <= order -2 )
{
GiNaC::ex eq = expanded_pol.coeff(x,c1).coeff(y,c2).coeff(z,c3);
if ( eq != GiNaC::numeric(0) )
{
equations.append(eq == 0);
}
}
}
}
}
}
int removed_dofs = equations.nops();
int counter = 0;
GiNaC::symbol t("t");
GiNaC::ex dofi;
// dofs related to edges
for (int i=0; i< 4; i++)
{
Triangle triangle = tetrahedron.triangle(i);
GiNaC::lst normal_vec = normal(tetrahedron, i);
bernstein_pol = bernstein(order-1, triangle, istr("a",i));
GiNaC::ex basis_space = bernstein_pol.op(2);
GiNaC::ex pspace_n = inner(pspace, normal_vec);
GiNaC::ex basis;
for (unsigned int j=0; j< basis_space.nops(); j++)
{
counter++;
basis = basis_space.op(j);
GiNaC::ex integrand = pspace_n*basis;
dofi = triangle.integrate(integrand);
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
GiNaC::lst d = GiNaC::lst(GiNaC::lst(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2)), j);
dofs.insert(dofs.end(), d);
GiNaC::ex u = GiNaC::matrix(3,1,GiNaC::lst(GiNaC::symbol("v[0]"), GiNaC::symbol("v[1]"), GiNaC::symbol("v[2]")));
GiNaC::ex n = GiNaC::matrix(3,1,GiNaC::lst(GiNaC::symbol("normal_vec[0]"), GiNaC::symbol("normal_vec[1]"), GiNaC::symbol("normal_vec[2]")));
dof_repr.append(GiNaC::lst(inner(u,n)*basis.subs( x == GiNaC::symbol("xi[0]"))
.subs( y == GiNaC::symbol("xi[1]"))
.subs( z == GiNaC::symbol("xi[2]")), d));
}
}
// dofs related to the whole tetrahedron
GiNaC::lst bernstein_polv;
if ( order > 1)
{
counter++;
bernstein_polv = bernsteinv(3,order-2, tetrahedron, "a");
GiNaC::ex basis_space = bernstein_polv.op(2);
for (unsigned int i=0; i< basis_space.nops(); i++)
{
GiNaC::lst basis = GiNaC::ex_to(basis_space.op(i));
GiNaC::ex integrand = inner(pspace, basis);
dofi = tetrahedron.integrate(integrand);
GiNaC::ex eq = dofi == GiNaC::numeric(0);
equations.append(eq);
GiNaC::lst d = GiNaC::lst(GiNaC::lst(tetrahedron.vertex(0), tetrahedron.vertex(1), tetrahedron.vertex(2), tetrahedron.vertex(3)), i);
dofs.insert(dofs.end(), d);
}
}
// invert the matrix:
// GiNaC has a bit strange way to invert a matrix.
// It solves the system AA^{-1} = Id.
// It seems that this way is the only way to do
// properly with the solve_algo::gauss flag.
//
GiNaC::matrix b; GiNaC::matrix A;
matrix_from_equations(equations, variables, A, b);
unsigned int ncols = A.cols();
GiNaC::matrix vars_sq(ncols, ncols);
// matrix of symbols
for (unsigned r=0; r(b));
GiNaC::lst subs;
for (unsigned int ii=0; ii