SyFi
0.3
|
#include <RaviartThomas.h>
Public Member Functions | |
RaviartThomas () | |
RaviartThomas (Polygon &p, int order=1, bool pointwise=true) | |
virtual | ~RaviartThomas () |
virtual void | compute_basis_functions () |
Public Attributes | |
bool | pointwise |
GiNaC::lst | dof_repr |
Definition at line 26 of file RaviartThomas.h.
Definition at line 30 of file RaviartThomas.cpp.
References SyFi::StandardFE::description.
: StandardFE() { description = "RaviartThomas"; }
SyFi::RaviartThomas::RaviartThomas | ( | Polygon & | p, |
int | order = 1 , |
||
bool | pointwise = true |
||
) |
Definition at line 35 of file RaviartThomas.cpp.
References compute_basis_functions(), and pointwise.
: StandardFE(p, order) { pointwise = pointwise_; compute_basis_functions(); }
virtual SyFi::RaviartThomas::~RaviartThomas | ( | ) | [inline, virtual] |
Definition at line 33 of file RaviartThomas.h.
{}
void SyFi::RaviartThomas::compute_basis_functions | ( | ) | [virtual] |
Reimplemented from SyFi::StandardFE.
Definition at line 41 of file RaviartThomas.cpp.
References SyFi::bernstein(), SyFi::bernsteinv(), test_syfi::debug::c, SyFi::collapse(), SyFi::StandardFE::description, dof_repr, SyFi::StandardFE::dofs, SyFi::inner(), SyFi::Line::integrate(), SyFi::Triangle::integrate(), SyFi::Tetrahedron::integrate(), SyFi::interior_coordinates(), SyFi::istr(), SyFi::Triangle::line(), SyFi::matrix_from_equations(), SyFi::normal(), SyFi::StandardFE::Ns, SyFi::StandardFE::order, SyFi::StandardFE::p, pointwise, SyFi::Polygon::str(), SyFi::t, SyFi::Tetrahedron::triangle(), SyFi::Polygon::vertex(), SyFi::x, SyFi::y, and SyFi::z.
Referenced by check_RaviartThomas(), main(), and RaviartThomas().
{ 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"<<endl; } else if ( p->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<GiNaC::lst>(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 "<<variables.nops()<<std::endl; // std::cout <<"no equations "<<equations.nops()<<std::endl; // 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<ncols; ++r) for (unsigned c=0; c<ncols; ++c) vars_sq(r, c) = GiNaC::symbol(); GiNaC::matrix id(ncols, ncols); // identity const GiNaC::ex _ex1(1); for (unsigned i=0; i<ncols; ++i) id(i, i) = _ex1; // invert the matrix GiNaC::matrix m_inv(ncols, ncols); m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss); for (unsigned int i=0; i<dofs.size(); i++) { b.let_op(removed_dofs + i) = GiNaC::numeric(1); GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); GiNaC::lst subs; for (unsigned int ii=0; ii<xx.nops(); ii++) { subs.append(variables.op(ii) == xx.op(ii)); } GiNaC::ex Nj1 = pspace.op(0).subs(subs); GiNaC::ex Nj2 = pspace.op(1).subs(subs); Ns.insert(Ns.end(), GiNaC::matrix(2,1,GiNaC::lst(Nj1,Nj2))); b.let_op(removed_dofs + i) = GiNaC::numeric(0); } } else if ( p->str().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<GiNaC::lst>(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 "<<variables.nops()<<std::endl; // std::cout <<"no equations "<<equations.nops()<<std::endl; // 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<ncols; ++r) for (unsigned c=0; c<ncols; ++c) vars_sq(r, c) = GiNaC::symbol(); GiNaC::matrix id(ncols, ncols); // identity const GiNaC::ex _ex1(1); for (unsigned i=0; i<ncols; ++i) id(i, i) = _ex1; // invert the matrix GiNaC::matrix m_inv(ncols, ncols); m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss); for (unsigned int i=0; i<dofs.size(); i++) { b.let_op(removed_dofs + i) = GiNaC::numeric(1); GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); GiNaC::lst subs; for (unsigned int ii=0; ii<xx.nops(); ii++) { subs.append(variables.op(ii) == xx.op(ii)); } GiNaC::ex Nj1 = pspace.op(0).subs(subs); GiNaC::ex Nj2 = pspace.op(1).subs(subs); GiNaC::ex Nj3 = pspace.op(2).subs(subs); Ns.insert(Ns.end(), GiNaC::matrix(3,1,GiNaC::lst(Nj1,Nj2,Nj3))); b.let_op(removed_dofs + i) = GiNaC::numeric(0); } } } else { if ( p->str().find("ReferenceLine") != string::npos ) { cout <<"Can not define the Raviart-Thomas element on a line"<<endl; } else if ( p->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<GiNaC::lst>(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<GiNaC::lst>(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<ncols; ++r) for (unsigned c=0; c<ncols; ++c) vars_sq(r, c) = GiNaC::symbol(); GiNaC::matrix id(ncols, ncols); // identity const GiNaC::ex _ex1(1); for (unsigned i=0; i<ncols; ++i) id(i, i) = _ex1; // invert the matrix GiNaC::matrix m_inv(ncols, ncols); m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss); for (unsigned int i=0; i<dofs.size(); i++) { b.let_op(removed_dofs + i) = GiNaC::numeric(1); GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); GiNaC::lst subs; for (unsigned int ii=0; ii<xx.nops(); ii++) { subs.append(variables.op(ii) == xx.op(ii)); } GiNaC::ex Nj1 = pspace.op(0).subs(subs); GiNaC::ex Nj2 = pspace.op(1).subs(subs); Ns.insert(Ns.end(), GiNaC::matrix(2,1,GiNaC::lst(Nj1,Nj2))); b.let_op(removed_dofs + i) = GiNaC::numeric(0); } } else if ( p->str().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<GiNaC::lst>(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<GiNaC::lst>(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<ncols; ++r) for (unsigned c=0; c<ncols; ++c) vars_sq(r, c) = GiNaC::symbol(); GiNaC::matrix id(ncols, ncols); // identity const GiNaC::ex _ex1(1); for (unsigned i=0; i<ncols; ++i) id(i, i) = _ex1; // invert the matrix GiNaC::matrix m_inv(ncols, ncols); m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss); for (unsigned int i=0; i<dofs.size(); i++) { b.let_op(removed_dofs + i) = GiNaC::numeric(1); GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); GiNaC::lst subs; for (unsigned int ii=0; ii<xx.nops(); ii++) { subs.append(variables.op(ii) == xx.op(ii)); } GiNaC::ex Nj1 = pspace.op(0).subs(subs); GiNaC::ex Nj2 = pspace.op(1).subs(subs); GiNaC::ex Nj3 = pspace.op(2).subs(subs); Ns.insert(Ns.end(), GiNaC::matrix(3,1,GiNaC::lst(Nj1,Nj2,Nj3))); b.let_op(removed_dofs + i) = GiNaC::numeric(0); } } } }
GiNaC::lst SyFi::RaviartThomas::dof_repr |
Definition at line 30 of file RaviartThomas.h.
Referenced by compute_basis_functions().
Definition at line 29 of file RaviartThomas.h.
Referenced by compute_basis_functions(), and RaviartThomas().