SyFi
0.3
|
#include <Lagrange.h>
Public Member Functions | |
Lagrange () | |
Lagrange (Polygon &p, unsigned int order=1) | |
virtual | ~Lagrange () |
virtual void | compute_basis_functions () |
Definition at line 26 of file Lagrange.h.
Definition at line 31 of file Lagrange.cpp.
References SyFi::StandardFE::description.
: StandardFE() { description = "Lagrange"; }
SyFi::Lagrange::Lagrange | ( | Polygon & | p, |
unsigned int | order = 1 |
||
) |
Definition at line 36 of file Lagrange.cpp.
References compute_basis_functions().
: StandardFE(p, order) { compute_basis_functions(); }
virtual SyFi::Lagrange::~Lagrange | ( | ) | [inline, virtual] |
Definition at line 31 of file Lagrange.h.
{}
void SyFi::Lagrange::compute_basis_functions | ( | ) | [virtual] |
Reimplemented from SyFi::StandardFE.
Reimplemented in SyFi::DiscontinuousLagrange.
Definition at line 41 of file Lagrange.cpp.
References SyFi::bernstein(), SyFi::bezier_ordinates(), test_syfi::debug::c, SyFi::StandardFE::description, SyFi::StandardFE::dof(), SyFi::StandardFE::dofs, SyFi::istr(), SyFi::matrix_from_equations(), SyFi::StandardFE::N(), SyFi::StandardFE::nbf(), SyFi::StandardFE::Ns, SyFi::StandardFE::order, SyFi::StandardFE::p, SyFi::pol(), SyFi::Polygon::str(), SyFi::t, SyFi::x, SyFi::y, and SyFi::z.
Referenced by SyFi::VectorLagrange::compute_basis_functions(), SyFi::TensorLagrange::compute_basis_functions(), Lagrange(), and main().
{ // NOTE: in the below code dof(i) is not used to // determine the basis functions // remove previously computed basis functions and dofs Ns.clear(); dofs.clear(); if ( order < 1 ) { throw(std::logic_error("Lagrangian 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")); } GiNaC::lst equations; GiNaC::lst variables; GiNaC::ex polynom; if (p->str().find("ReferenceLine") != string::npos) { description = istr("Lagrange_", order) + "_1D"; // Look at the case with the Triangle for a documented code // polynom = pol(order, 1, "a"); // variables = coeffs(polynom); GiNaC::ex polynom_space = bernstein(order, *p, "a"); // GiNaC::ex polynom_space = pol(order, 1, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); GiNaC::ex increment = GiNaC::numeric(1,order); GiNaC::ex Nj; for (GiNaC::ex p=0; p<= 1 ; p += increment ) { GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(x == p)); dofs.insert(dofs.end(), GiNaC::lst(p)); } } else if (p->str().find("Line") != string::npos ) { description = istr("Lagrange_", order) + "_1D"; // Look at the case with the Triangle for a documented code // polynom = pol(order, 1, "a"); // variables = coeffs(polynom); GiNaC::ex polynom_space = bernstein(order, *p, "a"); // GiNaC::ex polynom_space = pol(order, 1, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); Polygon& pp = *p; Line& l = (Line&) pp; GiNaC::lst points = bezier_ordinates(l,order); GiNaC::ex Nj; for (unsigned int i=1; i<= points.nops() ; i++ ) { GiNaC::ex point = points.op(i-1); GiNaC::ex eq = polynom == GiNaC::numeric(0); if (point.nops() == 0) eq = eq.subs(x == point); if (point.nops() > 0) eq = eq.subs(x == point.op(0)); if (point.nops() > 1) eq = eq.subs(y == point.op(1)); if (point.nops() > 2) eq = eq.subs(z == point.op(2)); equations.append(eq); dofs.insert(dofs.end(), GiNaC::lst(point)); } } else if (p->str().find("ReferenceTriangle") != string::npos ) { description = istr("Lagrange_", order) + "_2D"; // Look at the case with the Triangle for a documented code // polynom = pol(order, 2, "b"); // variables = coeffs(polynom); GiNaC::ex polynom_space = bernstein(order, *p, "b"); // GiNaC::ex polynom_space = pol(order, 2, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); GiNaC::ex increment = GiNaC::numeric(1,order); GiNaC::ex Nj; GiNaC::numeric one = 1; for (GiNaC::ex q=0; q<= one ; q += increment ) { for (GiNaC::ex p=0; p<= one-q ; p += increment ) { GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(GiNaC::lst(x == p, y == q))); dofs.insert(dofs.end(), GiNaC::lst(p,q)); } } } else if ( p->str().find("Triangle") != string::npos) { description = istr("Lagrange_", order) + "_2D"; // Look HERE for the documented code // GiNaC::ex polynom_space = pol(order, 2, "a"); GiNaC::ex polynom_space = bernstein(order, *p, "b"); // the polynomial spaces on the form: // first item: a0 + a1*x + a2*y + a3*x^2 + a4*x*y ... the polynom // second item: a0, a1, a2, ... the coefficents // third item 1, x, y, x^2, .. the basis // Could also do: // GiNaC::ex polynom_space = bernstein(order, t, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); GiNaC::ex Nj; Polygon& pp = *p; Triangle& t = (Triangle&) pp; // The bezier ordinates (in which the basis function should be either 0 or 1) GiNaC::lst points = bezier_ordinates(t,order); for (unsigned int i=1; i<= points.nops() ; i++ ) { GiNaC::ex point = points.op(i-1); GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(GiNaC::lst(x == point.op(0) , y == point.op(1)))); dofs.insert(dofs.end(), GiNaC::lst(point.op(0),point.op(1))); } } else if ( p->str().find("ReferenceRectangle") != string::npos) { description = istr("Lagrange_", order) + "_2D"; // create 1D element, then create tensor product ReferenceLine line; Lagrange fe(line, order); for (unsigned int i=0; i< fe.nbf(); i++) { for (unsigned int j=0; j< fe.nbf(); j++) { Ns.insert(Ns.end(), fe.N(i)*fe.N(j).subs(x==y)); dofs.insert(dofs.end(), GiNaC::lst(fe.dof(i).op(0), fe.dof(j).op(0))); } } return; /* OLD CODE GiNaC::ex polynom_space = legendre(order, 2, "b"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); GiNaC::ex Nj; Polygon& pp = *p; ReferenceRectangle& b = (ReferenceRectangle&) pp; int no_points = (order+1)*(order+1); GiNaC::ex increment = GiNaC::numeric(1,order); GiNaC::numeric one=1.0; for (GiNaC::ex q=0; q <= one ; q += increment ) { for (GiNaC::ex p=0; p <= one ; p += increment ) { GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(GiNaC::lst(x == p, y == q))); dofs.push_back(GiNaC::lst(p,q)); } } */ } else if ( p->str().find("ReferenceTetrahedron") != string::npos) { description = istr("Lagrange_", order) + "_3D"; // Look at the case with the Triangle for a documented code // polynom = pol(order, 3, "b"); // GiNaC::ex polynom_space = pol(order, 3, "a"); GiNaC::ex polynom_space = bernstein(order, *p, "b"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); int nno =0; for (unsigned int j=0; j<= order; j++) { nno += (j+1)*(j+2)/2; } GiNaC::ex increment = GiNaC::numeric(1,order); GiNaC::ex Nj; for (GiNaC::ex r=0; r<= 1 ; r += increment ) { for (GiNaC::ex q=0; q<= 1-r ; q += increment ) { for (GiNaC::ex p=0; p<= 1-r-q ; p += increment ) { GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(GiNaC::lst(x == p, y == q, z == r ))); dofs.push_back(GiNaC::lst(p,q,r)); } } } } else if ( p->str().find("Tetrahedron") != string::npos) { description = istr("Lagrange_", order) + "_3D"; // Look at the case with the Triangle for a documented code GiNaC::ex polynom_space = pol(order, 3, "a"); // GiNaC::ex polynom_space = bernstein(order, *p, "b"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); GiNaC::ex increment = GiNaC::numeric(1,order); GiNaC::ex Nj; Polygon& pp = *p; Tetrahedron& t = (Tetrahedron&) pp; GiNaC::lst points = bezier_ordinates(t,order); for (unsigned int i=1; i<= points.nops() ; i++ ) { GiNaC::ex point = points.op(i-1); GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(GiNaC::lst(x == point.op(0) , y == point.op(1), z == point.op(2)))); dofs.push_back(GiNaC::lst(point.op(0),point.op(1),point.op(2))); } } else if ( p->str().find("ReferenceBox") != string::npos) { description = istr("Lagrange_", order) + "_3D"; ReferenceLine line; Lagrange fe(line, order); for (unsigned int i=0; i< fe.nbf(); i++) { for (unsigned int j=0; j< fe.nbf(); j++) { for (unsigned int k=0; k< fe.nbf(); k++) { Ns.insert(Ns.end(), fe.N(i)*fe.N(j).subs(x==y)*fe.N(k).subs(x==z)); dofs.insert(dofs.end(), GiNaC::lst(fe.dof(i).op(0), fe.dof(j).op(0), fe.dof(k).op(0))); } } } return; /* OLD CODE GiNaC::ex polynom_space = legendre(order, 3, "b"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); GiNaC::ex Nj; Polygon& pp = *p; ReferenceRectangle& b = (ReferenceRectangle&) pp; int no_points = (order+1)*(order+1)*(order+1); GiNaC::ex increment = GiNaC::numeric(1,order); GiNaC::numeric one = 1; for (GiNaC::ex p=0; p <= one ; p += increment) { for (GiNaC::ex q=0; q <= one ; q += increment) { for (GiNaC::ex r=0; r <= one ; r += increment) { GiNaC::ex eq = polynom == GiNaC::numeric(0); equations.append(eq.subs(GiNaC::lst(x == p, y == q, z==r))); dofs.push_back(GiNaC::lst(p,q,r)); } } } / * GiNaC::ex subs = lsolve(equations, variables); Nj = polynom.subs(subs); Ns.push_back(Nj); */ } // 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. // // std::cout <<"no variables "<<variables.nops()<<std::endl; // std::cout <<"no equations "<<equations.nops()<<std::endl; // print(equations); // print(variables); 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(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 Nj = polynom.subs(subs); Ns.insert(Ns.end(), Nj); b.let_op(i) = GiNaC::numeric(0); } }