SyFi  0.3
SyFi::Nedelec2Hdiv Class Reference

#include <Nedelec2Hdiv.h>

Inheritance diagram for SyFi::Nedelec2Hdiv:
SyFi::StandardFE SyFi::FE

List of all members.

Public Member Functions

 Nedelec2Hdiv ()
 Nedelec2Hdiv (Polygon &p, unsigned int order=1)
virtual ~Nedelec2Hdiv ()
virtual void compute_basis_functions ()

Public Attributes

GiNaC::lst dof_repr

Detailed Description

Definition at line 26 of file Nedelec2Hdiv.h.


Constructor & Destructor Documentation

Definition at line 32 of file Nedelec2Hdiv.cpp.

References SyFi::StandardFE::description.

                                    : StandardFE()
        {
                description = "Nedelec2Hdiv";
        }
SyFi::Nedelec2Hdiv::Nedelec2Hdiv ( Polygon p,
unsigned int  order = 1 
)

Definition at line 37 of file Nedelec2Hdiv.cpp.

References compute_basis_functions().

virtual SyFi::Nedelec2Hdiv::~Nedelec2Hdiv ( ) [inline, virtual]

Definition at line 32 of file Nedelec2Hdiv.h.

{}

Member Function Documentation

Reimplemented from SyFi::StandardFE.

Definition at line 42 of file Nedelec2Hdiv.cpp.

References SyFi::bernstein(), SyFi::bernsteinv(), test_syfi::debug::c, SyFi::coeff(), SyFi::collapse(), SyFi::StandardFE::description, dof_repr, SyFi::StandardFE::dofs, SyFi::homogenous_polv(), SyFi::inner(), SyFi::Triangle::integrate(), SyFi::Tetrahedron::integrate(), SyFi::istr(), SyFi::matrix_from_equations(), SyFi::normal(), SyFi::StandardFE::Ns, SyFi::StandardFE::order, SyFi::StandardFE::p, SyFi::pol2basisandcoeff(), SyFi::Polygon::str(), SyFi::t, SyFi::Tetrahedron::triangle(), SyFi::Polygon::vertex(), SyFi::x, SyFi::y, and SyFi::z.

Referenced by SyFi::ArnoldFalkWintherWeakSymSigma::compute_basis_functions(), main(), and Nedelec2Hdiv().

        {

                // remove previously computed basis functions and dofs
                Ns.clear();
                dofs.clear();

                if ( order < 1 )
                {
                        throw(std::logic_error("Nedelec2Hdiv 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"));
                }

                if ( p->str().find("Line") != string::npos )
                {

                        cout <<"Can not define the Nedelec2Hdiv element on a line"<<endl;

                }
                else if ( p->str().find("Triangle") != string::npos )
                {

                        cout <<"Can not define the Nedelec2Hdiv element on a Triangle "<<endl;

                }
                else if ( p->str().find("Tetrahedron") != string::npos )
                {

                        description = istr( "Nedelec2Hdiv_", order) + "_3D";

                        int k = order;

                        Tetrahedron& tetrahedron= (Tetrahedron&)(*p);
                        GiNaC::lst equations;
                        GiNaC::lst variables;

                        // create p
                        GiNaC::ex P_k = bernsteinv(3,k, tetrahedron, "b");
                        GiNaC::ex P_k_x = P_k.op(0).op(0);
                        GiNaC::ex P_k_y = P_k.op(0).op(1);
                        GiNaC::ex P_k_z = P_k.op(0).op(2);

                        GiNaC::lst pspace = GiNaC::lst( P_k_x, P_k_y, P_k_z);

                        variables = collapse(GiNaC::ex_to<GiNaC::lst>(P_k.op(1)));

                        int counter = 0;
                        GiNaC::symbol t("t");
                        GiNaC::ex dofi;
                        GiNaC::ex bernstein_pol;

                        // 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, 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(triangle.integrate(x*basis),
                                        //                                  triangle.integrate(y*basis),
                                        //                                  triangle.integrate(z*basis));
                                        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 tetrahedron

                        int tetradofs = 0;
                        if ( order > 1 )
                        {
                                GiNaC::ex bernstein_pol = bernsteinv(3,k-2, tetrahedron, istr("c", 0));
                                GiNaC::ex basis_space = bernstein_pol.op(2);
                                GiNaC::ex basis;
                                tetradofs += basis_space.nops();
                                for (unsigned int j=0; j<basis_space.nops(); j++)
                                {
                                        basis = basis_space.op(j);
                                        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(tetrahedron.integrate(x*basis.op(0)),
                                        //                                  tetrahedron.integrate(y*basis.op(1)),
                                        //                                  tetrahedron.integrate(z*basis.op(2)));

                                        GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0),
                                                tetrahedron.vertex(1),
                                                tetrahedron.vertex(2),
                                                tetrahedron.vertex(3),j);

                                        dofs.insert(dofs.end(), d);

                                }
                        }

                        // Construction of S_k
                        //
                        //
                        if ( order >= 1 )
                        {
                                GiNaC::ex H_k = homogenous_polv(3,k-1, 3, "a");
                                GiNaC::ex H_k_x = H_k.op(0).op(0);
                                GiNaC::ex H_k_y = H_k.op(0).op(1);
                                GiNaC::ex H_k_z = H_k.op(0).op(2);

                                GiNaC::lst H_variables = collapse(GiNaC::ex_to<GiNaC::lst>(H_k.op(1)));

                                // Equations that make sure that r*x = 0

                                GiNaC::ex rx = (H_k_x*x + H_k_y*y + H_k_z*z).expand();
                                exmap pol_map = pol2basisandcoeff(rx);
                                exmap::iterator iter;
                                GiNaC::lst S_k;
                                GiNaC::lst S_k_equations;

                                GiNaC::lst null_eqs;
                                for (unsigned int i=0; i<H_variables.nops(); i++)
                                {
                                        null_eqs.append( H_variables.op(i) == 0);
                                }

                                for (iter = pol_map.begin(); iter != pol_map.end(); iter++)
                                {
                                        GiNaC::ex coeff = (*iter).second;
                                        GiNaC::ex basis;
                                        if (coeff.nops() > 1  )
                                        {
                                                if (coeff.nops()  == 2)
                                                {
                                                        S_k_equations.remove_all();
                                                        S_k_equations.append(coeff.op(0) == GiNaC::numeric(1));
                                                        S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1));
                                                        basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;
                                                        S_k.append(basis);
                                                }
                                                else if ( coeff.nops() == 3 )
                                                {
                                                        // 2 basis functions is added
                                                        // The first:

                                                        S_k_equations.remove_all();
                                                        S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2));
                                                        S_k_equations.append(coeff.op(1) == GiNaC::numeric(1));
                                                        S_k_equations.append(coeff.op(2) == GiNaC::numeric(-1,2));
                                                        basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;
                                                        S_k.append(basis);

                                                        // The second:
                                                        S_k_equations.remove_all();
                                                        S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2));
                                                        S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1,2));
                                                        S_k_equations.append(coeff.op(2) == GiNaC::numeric(1));
                                                        basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);;
                                                        S_k.append(basis);
                                                }
                                        }
                                }

                                std::cout <<"len (S_k) " <<S_k.nops()<<std::endl;

                                // dofs related to tetrahedron
                                if ( order >= 1 )
                                {
                                        GiNaC::ex basis;
                                        for (unsigned int j=0; j<S_k.nops(); j++)
                                        {
                                                basis = S_k.op(j);
                                                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(tetrahedron.vertex(0),
                                                        tetrahedron.vertex(1),
                                                        tetrahedron.vertex(2),
                                                        tetrahedron.vertex(3), tetradofs + j);

                                                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(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(i) = GiNaC::numeric(0);
                        }
                }
        }

Member Data Documentation

Definition at line 29 of file Nedelec2Hdiv.h.

Referenced by compute_basis_functions().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator