SyFi
0.3
|
#include <Hermite.h>
Public Member Functions | |
Hermite () | |
Hermite (Polygon &p, int order=1) | |
virtual | ~Hermite () |
virtual void | compute_basis_functions () |
Definition at line 28 of file Hermite.cpp.
References SyFi::StandardFE::description.
: StandardFE() { description = "Hermite"; }
SyFi::Hermite::Hermite | ( | Polygon & | p, |
int | order = 1 |
||
) |
Definition at line 33 of file Hermite.cpp.
References compute_basis_functions().
: StandardFE(p,order) { compute_basis_functions(); }
virtual SyFi::Hermite::~Hermite | ( | ) | [inline, virtual] |
void SyFi::Hermite::compute_basis_functions | ( | ) | [virtual] |
Reimplemented from SyFi::StandardFE.
Definition at line 38 of file Hermite.cpp.
References test_syfi::debug::c, SyFi::StandardFE::description, SyFi::StandardFE::dofs, SyFi::legendre(), SyFi::matrix_from_equations(), SyFi::StandardFE::Ns, SyFi::StandardFE::p, SyFi::pol(), SyFi::Polygon::str(), test_syfi::debug::v, SyFi::Polygon::vertex(), SyFi::x, SyFi::y, and SyFi::z.
Referenced by Hermite(), and main().
{ // remove previously computed basis functions and dofs Ns.clear(); dofs.clear(); if ( p == NULL ) { throw(std::logic_error("You need to set a polygon before the basisfunctions can be computed")); } GiNaC::ex polynom_space; GiNaC::ex polynom; GiNaC::lst variables; GiNaC::lst equations; if ( p->str().find("Line") != string::npos ) { description = "Hermite_1D"; polynom_space = legendre(3, 1, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); for (int i=0; i< 2; i++) { GiNaC::ex v = p->vertex(i); GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0))); GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0))); equations.append( dofv == GiNaC::numeric(0)); equations.append( dofvdx == GiNaC::numeric(0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), 0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), 1)); } } if ( p->str().find("Triangle") != string::npos ) { description = "Hermite_2D"; polynom_space = pol(3, 2, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); for (int i=0; i<= 2; i++) { GiNaC::ex v = p->vertex(i); GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1))); GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1))); GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1))); equations.append( dofv == GiNaC::numeric(0)); equations.append( dofvdx == GiNaC::numeric(0)); equations.append( dofvdy == GiNaC::numeric(0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2)); } GiNaC::ex midpoint = GiNaC::lst((p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0))/3, (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1))/3); GiNaC::ex dofm = polynom.subs(GiNaC::lst(x == midpoint.op(0), y == midpoint.op(1))); dofs.insert(dofs.end(), midpoint ); equations.append( dofm == GiNaC::numeric(0)); } else if ( p->str().find("Rectangle") != string::npos ) { description = "Hermite_2D"; polynom_space = legendre(3, 2, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); for (int i=0; i< 4; i++) { GiNaC::ex v = p->vertex(i); GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1))); GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1))); GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1))); GiNaC::ex dofvdyx = diff(diff(polynom,y),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1))); equations.append( dofv == GiNaC::numeric(0)); equations.append( dofvdx == GiNaC::numeric(0)); equations.append( dofvdy == GiNaC::numeric(0)); equations.append( dofvdyx == GiNaC::numeric(0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 3)); } } else if ( p->str().find("Tetrahedron") != string::npos ) { description = "Hermite_3D"; polynom_space = pol(3, 3, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); for (int i=0; i<= 3; i++) { GiNaC::ex v = p->vertex(i); GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdz = diff(polynom,z).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); equations.append( dofv == GiNaC::numeric(0)); equations.append( dofvdx == GiNaC::numeric(0)); equations.append( dofvdy == GiNaC::numeric(0)); equations.append( dofvdz == GiNaC::numeric(0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 1)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 2)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), 3)); } GiNaC::ex midpoint1 = GiNaC::lst( (p->vertex(0).op(0)*2 + p->vertex(1).op(0) + p->vertex(2).op(0) + p->vertex(3).op(0))/5, (p->vertex(0).op(1)*2 + p->vertex(1).op(1) + p->vertex(2).op(1) + p->vertex(3).op(1))/5, (p->vertex(0).op(2)*2 + p->vertex(1).op(2) + p->vertex(2).op(2) + p->vertex(3).op(2))/5); GiNaC::ex midpoint2 = GiNaC::lst( (p->vertex(0).op(0) + p->vertex(1).op(0)*2 + p->vertex(2).op(0) + p->vertex(3).op(0))/5, (p->vertex(0).op(1) + p->vertex(1).op(1)*2 + p->vertex(2).op(1) + p->vertex(3).op(1))/5, (p->vertex(0).op(2) + p->vertex(1).op(2)*2 + p->vertex(2).op(2) + p->vertex(3).op(2))/5); GiNaC::ex midpoint3 = GiNaC::lst( (p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0)*2 + p->vertex(3).op(0))/5, (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1)*2 + p->vertex(3).op(1))/5, (p->vertex(0).op(2) + p->vertex(1).op(2) + p->vertex(2).op(2)*2 + p->vertex(3).op(2))/5); GiNaC::ex midpoint4 = GiNaC::lst( (p->vertex(0).op(0) + p->vertex(1).op(0) + p->vertex(2).op(0) + p->vertex(3).op(0)*2)/5, (p->vertex(0).op(1) + p->vertex(1).op(1) + p->vertex(2).op(1) + p->vertex(3).op(1)*2)/5, (p->vertex(0).op(2) + p->vertex(1).op(2) + p->vertex(2).op(2) + p->vertex(3).op(2)*2)/5); GiNaC::ex dofm1 = polynom.subs(GiNaC::lst(x == midpoint1.op(0), y == midpoint1.op(1), z == midpoint1.op(2))); GiNaC::ex dofm2 = polynom.subs(GiNaC::lst(x == midpoint2.op(0), y == midpoint2.op(1), z == midpoint2.op(2))); GiNaC::ex dofm3 = polynom.subs(GiNaC::lst(x == midpoint3.op(0), y == midpoint3.op(1), z == midpoint3.op(2))); GiNaC::ex dofm4 = polynom.subs(GiNaC::lst(x == midpoint4.op(0), y == midpoint4.op(1), z == midpoint4.op(2))); dofs.insert(dofs.end(), midpoint1 ); dofs.insert(dofs.end(), midpoint2 ); dofs.insert(dofs.end(), midpoint3 ); dofs.insert(dofs.end(), midpoint4 ); equations.append( dofm1 == GiNaC::numeric(0)); equations.append( dofm2 == GiNaC::numeric(0)); equations.append( dofm3 == GiNaC::numeric(0)); equations.append( dofm4 == GiNaC::numeric(0)); } else if ( p->str().find("Box") != string::npos ) { description = "Hermite_3D"; polynom_space = legendre(3, 3, "a"); polynom = polynom_space.op(0); variables = GiNaC::ex_to<GiNaC::lst>(polynom_space.op(1)); for (int i=0; i<= 7; i++) { GiNaC::ex v = p->vertex(i); GiNaC::ex dofv = polynom.subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdx = diff(polynom,x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdy = diff(polynom,y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdyx = diff(diff(polynom,y),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdz = diff(polynom,z).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdzy = diff(diff(polynom,z),y).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdzx = diff(diff(polynom,z),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); GiNaC::ex dofvdzyx = diff(diff(diff(polynom,z),y),x).subs(GiNaC::lst(x == v.op(0), y == v.op(1), z == v.op(2) )); equations.append( dofv == GiNaC::numeric(0)); equations.append( dofvdx == GiNaC::numeric(0)); equations.append( dofvdy == GiNaC::numeric(0)); equations.append( dofvdyx == GiNaC::numeric(0)); equations.append( dofvdz == GiNaC::numeric(0)); // FIXME check Andrew/Ola numbering equations.append( dofvdzy == GiNaC::numeric(0)); // FIXME check Andrew/Ola numbering equations.append( dofvdzx == GiNaC::numeric(0)); equations.append( dofvdzyx == GiNaC::numeric(0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 0)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 1)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 2)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 3)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 4)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 5)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 6)); dofs.insert(dofs.end(), GiNaC::lst(v.op(0), v.op(1), v.op(2), 7)); } } 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).expand(); Ns.insert(Ns.end(), Nj); b.let_op(i) = GiNaC::numeric(0); } }