#include <Nedelec2Hdiv.h>
Inheritance diagram for Nedelec2Hdiv:
Public Member Functions | |
Nedelec2Hdiv () | |
virtual | ~Nedelec2Hdiv () |
virtual void | set (int order) |
virtual void | set (Polygon &p) |
virtual void | compute_basis_functions () |
virtual int | nbf () |
virtual GiNaC::ex | N (int i) |
virtual GiNaC::ex | dof (int i) |
Definition at line 8 of file Nedelec2Hdiv.h.
|
Definition at line 10 of file Nedelec2Hdiv.h.
|
|
Definition at line 11 of file Nedelec2Hdiv.h.
|
|
Reimplemented from StandardFE. Definition at line 10 of file Nedelec2Hdiv.cpp. References bernstein(), bernsteinv(), coeff(), collapse(), StandardFE::dofs, homogenous_polv(), inner(), Tetrahedron::integrate(), Triangle::integrate(), istr(), matrix_from_equations(), normal(), StandardFE::Ns, StandardFE::order, StandardFE::p, pol2basisandcoeff(), Polygon::str(), Tetrahedron::triangle(), Tetrahedron::vertex(), Triangle::vertex(), x, y, and z. Referenced by ArnoldFalkWintherWeakSymSigma::compute_basis_functions(), and main(). 00010 { 00011 00012 if ( order < 1 ) { 00013 cout <<"Nedelec2Hdiv elements must be of order 1 or higher."<<endl; 00014 return; 00015 } 00016 00017 00018 if ( p == NULL ) { 00019 cout <<"You need to set a polygon before the basisfunctions can be computed"<<endl; 00020 return; 00021 } 00022 00023 00024 00025 if (p->str() == "ReferenceLine" || p->str() == "Line" ) { 00026 00027 cout <<"Can not define the Nedelec2Hdiv element on a line"<<endl; 00028 00029 } else if (p->str() == "ReferenceTriangle" || p->str() == "Triangle" ) { 00030 00031 cout <<"Can not define the Nedelec2Hdiv element on a Triangle "<<endl; 00032 00033 } else if (p->str() == "ReferenceTetrahedron" || p->str() == "Tetrahedron" ) { 00034 int k = order; 00035 00036 Tetrahedron& tetrahedron= (Tetrahedron&)(*p); 00037 GiNaC::lst equations; 00038 GiNaC::lst variables; 00039 00040 // create p 00041 GiNaC::ex P_k = bernsteinv(3,k, tetrahedron, "b"); 00042 GiNaC::ex P_k_x = P_k.op(0).op(0); 00043 GiNaC::ex P_k_y = P_k.op(0).op(1); 00044 GiNaC::ex P_k_z = P_k.op(0).op(2); 00045 00046 00047 GiNaC::lst pspace = GiNaC::lst( P_k_x, P_k_y, P_k_z); 00048 00049 variables = collapse(GiNaC::ex_to<GiNaC::lst>(P_k.op(1))); 00050 00051 int counter = 0; 00052 GiNaC::symbol t("t"); 00053 GiNaC::ex dofi; 00054 GiNaC::ex bernstein_pol; 00055 00056 // dofs related to edges 00057 for (int i=1; i<= 4; i++) { 00058 Triangle triangle = tetrahedron.triangle(i); 00059 GiNaC::lst normal_vec = normal(tetrahedron, i); 00060 bernstein_pol = bernstein(order, triangle, istr("a",i)); 00061 GiNaC::ex basis_space = bernstein_pol.op(2); 00062 GiNaC::ex pspace_n = inner(pspace, normal_vec); 00063 00064 GiNaC::ex basis; 00065 for (int j=0; j< basis_space.nops(); j++) { 00066 counter++; 00067 basis = basis_space.op(j); 00068 GiNaC::ex integrand = pspace_n*basis; 00069 dofi = triangle.integrate(integrand); 00070 GiNaC::ex eq = dofi == GiNaC::numeric(0); 00071 equations.append(eq); 00072 // GiNaC::lst d = GiNaC::lst(triangle.integrate(x*basis), 00073 // triangle.integrate(y*basis), 00074 // triangle.integrate(z*basis)); 00075 GiNaC::lst d = GiNaC::lst(triangle.vertex(0), 00076 triangle.vertex(1), 00077 triangle.vertex(2),j); 00078 00079 dofs.insert(dofs.end(), d); 00080 00081 } 00082 } 00083 00084 00085 00086 // dofs related to tetrahedron 00087 00088 int tetradofs = 0; 00089 if ( order > 1 ) { 00090 GiNaC::ex bernstein_pol = bernsteinv(3,k-2, tetrahedron, istr("c", 0)); 00091 GiNaC::ex basis_space = bernstein_pol.op(2); 00092 GiNaC::ex basis; 00093 tetradofs += basis_space.nops(); 00094 for (int j=0; j<basis_space.nops(); j++) { 00095 basis = basis_space.op(j); 00096 GiNaC::ex integrand = inner(pspace,basis); 00097 dofi = tetrahedron.integrate(integrand); 00098 GiNaC::ex eq = dofi == GiNaC::numeric(0); 00099 equations.append(eq); 00100 00101 // GiNaC::lst d = GiNaC::lst(tetrahedron.integrate(x*basis.op(0)), 00102 // tetrahedron.integrate(y*basis.op(1)), 00103 // tetrahedron.integrate(z*basis.op(2))); 00104 00105 GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0), 00106 tetrahedron.vertex(1), 00107 tetrahedron.vertex(2), 00108 tetrahedron.vertex(3),j); 00109 00110 00111 dofs.insert(dofs.end(), d); 00112 00113 } 00114 } 00115 00116 00117 // Construction of S_k 00118 // 00119 // 00120 if ( order >= 1 ) { 00121 GiNaC::ex H_k = homogenous_polv(3,k-1, 3, "a"); 00122 GiNaC::ex H_k_x = H_k.op(0).op(0); 00123 GiNaC::ex H_k_y = H_k.op(0).op(1); 00124 GiNaC::ex H_k_z = H_k.op(0).op(2); 00125 00126 GiNaC::lst H_variables = collapse(GiNaC::ex_to<GiNaC::lst>(H_k.op(1))); 00127 00128 00129 // Equations that make sure that r*x = 0 00130 00131 GiNaC::ex rx = (H_k_x*x + H_k_y*y + H_k_z*z).expand(); 00132 ex_ex_map pol_map = pol2basisandcoeff(rx); 00133 ex_ex_it iter; 00134 GiNaC::lst S_k; 00135 GiNaC::lst S_k_equations; 00136 00137 GiNaC::lst null_eqs; 00138 for (int i=0; i<H_variables.nops(); i++) { 00139 null_eqs.append( H_variables.op(i) == 0); 00140 } 00141 00142 for (iter = pol_map.begin(); iter != pol_map.end(); iter++) { 00143 GiNaC::ex coeff = (*iter).second; 00144 GiNaC::ex basis; 00145 if (coeff.nops() > 1 ) { 00146 if (coeff.nops() == 2) { 00147 S_k_equations.remove_all(); 00148 S_k_equations.append(coeff.op(0) == GiNaC::numeric(1)); 00149 S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1)); 00150 basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);; 00151 S_k.append(basis); 00152 } else if ( coeff.nops() == 3 ) { 00153 // 2 basis functions is added 00154 // The first: 00155 00156 S_k_equations.remove_all(); 00157 S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2)); 00158 S_k_equations.append(coeff.op(1) == GiNaC::numeric(1)); 00159 S_k_equations.append(coeff.op(2) == GiNaC::numeric(-1,2)); 00160 basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);; 00161 S_k.append(basis); 00162 00163 // The second: 00164 S_k_equations.remove_all(); 00165 S_k_equations.append(coeff.op(0) == GiNaC::numeric(-1,2)); 00166 S_k_equations.append(coeff.op(1) == GiNaC::numeric(-1,2)); 00167 S_k_equations.append(coeff.op(2) == GiNaC::numeric(1)); 00168 basis = H_k.op(0).subs(S_k_equations).subs(null_eqs);; 00169 S_k.append(basis); 00170 } 00171 } 00172 } 00173 00174 00175 // dofs related to tetrahedron 00176 if ( order >= 1 ) { 00177 GiNaC::ex basis; 00178 for (int j=0; j<S_k.nops(); j++) { 00179 basis = S_k.op(j); 00180 GiNaC::ex integrand = inner(pspace,basis); 00181 dofi = tetrahedron.integrate(integrand); 00182 GiNaC::ex eq = dofi == GiNaC::numeric(0); 00183 equations.append(eq); 00184 00185 GiNaC::lst d = GiNaC::lst(tetrahedron.vertex(0), 00186 tetrahedron.vertex(1), 00187 tetrahedron.vertex(2), 00188 tetrahedron.vertex(3), tetradofs + j); 00189 00190 00191 dofs.insert(dofs.end(), d); 00192 00193 } 00194 } 00195 } 00196 00197 00198 // invert the matrix: 00199 // GiNaC has a bit strange way to invert a matrix. 00200 // It solves the system AA^{-1} = Id. 00201 // It seems that this way is the only way to do 00202 // properly with the solve_algo::gauss flag. 00203 // 00204 GiNaC::matrix b; GiNaC::matrix A; 00205 matrix_from_equations(equations, variables, A, b); 00206 00207 int ncols = A.cols(); 00208 GiNaC::matrix vars_sq(ncols, ncols); 00209 00210 // matrix of symbols 00211 for (unsigned r=0; r<ncols; ++r) 00212 for (unsigned c=0; c<ncols; ++c) 00213 vars_sq(r, c) = GiNaC::symbol(); 00214 00215 GiNaC::matrix id(ncols, ncols); 00216 00217 // identity 00218 const GiNaC::ex _ex1(1); 00219 for (unsigned i=0; i<ncols; ++i) 00220 id(i, i) = _ex1; 00221 00222 00223 // invert the matrix 00224 GiNaC::matrix m_inv(ncols, ncols); 00225 m_inv = A.solve(vars_sq, id, GiNaC::solve_algo::gauss); 00226 00227 00228 for (int i=0; i<dofs.size(); i++) { 00229 b.let_op(i) = GiNaC::numeric(1); 00230 GiNaC::ex xx = m_inv.mul(GiNaC::ex_to<GiNaC::matrix>(b)); 00231 00232 GiNaC::lst subs; 00233 for (int ii=0; ii<xx.nops(); ii++) { 00234 subs.append(variables.op(ii) == xx.op(ii)); 00235 } 00236 GiNaC::ex Nj1 = pspace.op(0).subs(subs); 00237 GiNaC::ex Nj2 = pspace.op(1).subs(subs); 00238 GiNaC::ex Nj3 = pspace.op(2).subs(subs); 00239 Ns.insert(Ns.end(), GiNaC::matrix(1,3,GiNaC::lst(Nj1,Nj2,Nj3))); 00240 b.let_op(i) = GiNaC::numeric(0); 00241 } 00242 } 00243 }
|
|
Reimplemented from StandardFE. Definition at line 256 of file Nedelec2Hdiv.cpp. References StandardFE::dof(). Referenced by ArnoldFalkWintherWeakSymSigma::compute_basis_functions(). 00256 { 00257 return StandardFE::dof(i); 00258 }
|
|
Reimplemented from StandardFE. Definition at line 261 of file Nedelec2Hdiv.cpp. References StandardFE::N(). Referenced by ArnoldFalkWintherWeakSymSigma::compute_basis_functions(). 00261 { 00262 return StandardFE::N(i); 00263 }
|
|
Reimplemented from StandardFE. Definition at line 6 of file Nedelec2Hdiv.cpp. References StandardFE::Ns. Referenced by ArnoldFalkWintherWeakSymSigma::compute_basis_functions(). 00006 { 00007 return Ns.size(); 00008 }
|
|
Reimplemented from StandardFE. Definition at line 246 of file Nedelec2Hdiv.cpp. References StandardFE::set(). 00246 { 00247 StandardFE:: set(p_); 00248 }
|
|
Reimplemented from StandardFE. Definition at line 251 of file Nedelec2Hdiv.cpp. References StandardFE::set(). Referenced by ArnoldFalkWintherWeakSymSigma::compute_basis_functions(), and main(). 00251 { 00252 StandardFE:: set(order_); 00253 }
|