\documentclass{fenicsmanual}
%\documentclass{article}
\usepackage{moreverb,relsize,ttname}
\usepackage{epsfig}
\usepackage{epic}
\usepackage{eepic}
\usepackage{bm}
\usepackage{amssymb}
\usepackage{amsmath}
\RequirePackage{url}

\newcommand{\emp}[1]{{\smaller\texttt{#1}}}
%%\newcommand{\eqref}[1]{(\ref{#1})}

\newtheorem{example}{Example}[section]
\newtheorem{definition}{Definition}[section]

%\usepackage{hyperref}




\renewcommand{\P}{{\mathbb P}}
\renewcommand{\S}{{\mathbb S}}
\renewcommand{\H}{{\mathbb H}}
\renewcommand{\R}{{\mathbb R}}
\newcommand{\xx}{\mathbf{x}}
\newcommand{\ff}{\mathbf{f}}
\newcommand{\kk}{\mathbf{k}}
\renewcommand{\gg}{\mathbf{g}}
\newcommand{\vv}{\mathbf{v}}
\newcommand{\VV}{\mathbf{V}}
\newcommand{\HH}{\mathbf{H}}
\newcommand{\GG}{\mathbf{G}}
\newcommand{\uu}{\mathbf{u}}
\newcommand{\nn}{\mathbf{n}}
\renewcommand{\tt}{\mathbf{t}}
\newcommand{\hh}{\mathbf{h}}
\newcommand{\FF}{\mathbf{F}}
\newcommand{\NN}{\mathbf{N}}
\newcommand{\LL}{\mathbf{L}}
\newcommand{\pp}{\mathbf{p}}
\newcommand{\qq}{\mathbf{q}}
\newcommand{\rr}{\mathbf{r}}
\newcommand{\nnull}{\mathbf{0}}
\newcommand{\grad}{\operatorname{\bf grad}}
\newcommand{\curl}{\operatorname{\bf curl}}
\renewcommand{\div}{\operatorname{div}}
\newcommand{\rot}{\operatorname{rot}}
\newcommand{\Hdiv}{\HH(\div)}
\newcommand{\Hcurl}{\HH(\curl)}
%\title{SyFi Tutorial} 
%\author{Kent-Andre Mardal}



\begin{document}


\fenicstitle{SyFi User Manual}
\fenicsauthor{Martin Aln\ae s  and   Kent-Andre Mardal}
\fenicspackage{\textbf{\textsf{SyFi}}}{syfi}
%\fenicsimage{eps/dolfin.eps}

\maketitle


\section{Introduction}


The finite element package SyFi 
is a C++ library built on top of 
the symbolic math library GiNaC \cite{www:ginac}.
The name SyFi stands for Symbolic Finite elements.  
The package provides polygonal domains,  polynomial spaces, 
and degrees of freedom as symbolic expressions that are easily 
manipulated. This makes it easy to define and use finite elements. 

All the test examples described in this tutorial can be found in the
directory \emp{tests}. The reader is of course encouraged to run
the examples along with the reading.  


Before we start to describe SyFi, we need to briefly review the
basic concepts in GiNaC.   
GiNaC is an open source C++ library for symbolic mathematics, which
has a strong support for polynomials. The basic structure
in GiNaC is an \emp{ex}, which may contain either
a number, a symbol, a function, a list of expressions, etc.        
(see \emp{simple.cpp}): 
%% BEGIN CODE FROM simple.h 
\begin{code}
   ex pi = 3.14;
   ex x = symbol("x");
   ex f = cos(x);
   ex list = lst(pi,x,f); 
\end{code}
%% END CODE FROM simple.h 
\noindent
Hence, \emp{ex} is a quite general class, and
it is the cornerstone of GiNaC. It has a
lot of functionality, for instance   
differentiation and integration  
(see \emp{simple2.cpp}),  
%% BEGIN CODE FROM simple2.h 
\begin{code}
  // initialization (f = x^2 + y^2) 
  ex f = x*x + y*y; 
  
  // differentiation (dfdx = df/dx = 2x) 
  ex dfdx = f.diff(x,1);  

  // integration (intf=1/3+y^2, integral of f(x,y) on x=[0,1]) 
  ex intf = integral(x,0,1,f);
\end{code} 
%% END CODE FROM simple2.h 
GiNaC also has a structure for lists of expressions, \emp{lst}, 
with the function \emp{nops()} which returns 
the size of the list, and \emp{operator [int i]} or the function \emp{op(int i)} which returns the $i$'th  element. 

We recommend the reader to glance through 
the GiNaC documentation before proceeding with 
this tutorial. GiNaC provides 
all the basic tools 
for manipulation of polynomials, such as differentiation
and integration with respect to one variable. Our
goal with the SyFi package is to employ GiNaC, but also to provide higher level constructs
such as differentiation with respect to several variables 
(e.g., $\nabla$), integration of functions over polygonal 
domains, and polynomial spaces. All of which are basic
ingredients  in the finite element method.      

Our motivation behind this project is threefold. First, we wish to make advanced 
finite element methods more readily available. We want to do this by implementing
a variety of finite elements and functions for computing element matrices.     
Second, in our experience developing and debugging codes for finite 
element methods is hard. Having the basis functions and the weak form as 
symbolic expressions, and being able to manipulate them may be extremely valuable. 
For instance, being able to differentiate the weak form to  compute
the Jacobian in the case of a nonlinear PDE, eliminates a lot of handwriting and coding. 
Third, having the symbolic expressions 
and employing GiNaCs tools for code generation, we are able
to write efficient and directly compilable  C++ code for the computation
of element matrices etc. 


To try to motivate the reader, 
we also show an example where we compute the element matrix  
for the weak form of the Poisson equation, i.e.,  
\[
A_{ij} = \int_T \nabla N_i N_j \, dx .    
\]
We remark that the following example is 
an attempt to make an appetizer. All concepts
will be carefully described during the tutorial.  
%% BEGIN CODE FROM check_poisson.h 
{\footnotesize 
\begin{code}
void compute_element_matrix(Polygon& T, int order) { 
  std::map<std::pair<int,int>, ex> A;      // matrix of expression 
  std::pair<int,int> index;                // index in matrix 
  LagrangeFE fe;                           // Lagrange element (any order) 
  fe.set_order(order);                           // set the order 
  fe.set_polygon(domain);                          // set the polygon 
  fe.compute_basis_functions();            // compute the basis functions
  for (int i=0; i< fe.nbf(); i++) {
    index.first = i; 
    for (int j=0; j< fe.nbf(); j++) {
      index.second = j; 
      ex nabla = inner(grad(fe.N(i)),           // compute integrands 
                       grad(fe.N(j)));
      ex Aij = T.integrate(nabla);              // compute weak form 
      A[index] = Aij;                           // update element matrix       
    }
  }
}
\end{code}
}
%% END CODE FROM check_poisson.h 

\noindent
In the above example, everything is computed symbolically. Even the polygon may be 
an abstract polygon, e.g., specified as a triangle with vertices $\xx_0$, $\xx_1$, 
and $\xx_2$, where the vertices are symbols and not concrete points.  
Notice also, that we usually use STL containers  to store our datastructure. This leads
to the somewhat unfamiliar notation \emp{A[index]} instead of \emp{A[i,j]}.   


There are quite a few other projects that are similar in various
respects to SyFi. We will not give a comprehensive description 
of these projects, only mention the projects such that 
the readers can look them up by themselves. 
Within the FEniCS~\cite{FEniCS} project there
are two Python projects: FIAT~\cite{FIAT} and FFC~\cite{FFC}. 
FIAT is a Python module 
for defining finite elements while FFC generates C++ code 
based on a high--level Python description of variational forms.    
The DSEL project~\cite{DSEL} is a project which employs high--level
C++ programming techniques such as expression templates 
and meta-programming for defining variational forms, performing
automatic differentiation, interpolation and more.
Sundance~\cite{sundance} is a C++ library with a powerful symbolic engine 
which supports automatic generation of discrete system 
for a given variational form. Analysa~\cite{analysa}, GetDP~\cite{getdp}, 
and FreeFem++~\cite{FreeFem}  define domain-specific languages
for finite element computations. 

Finally, we have to warn the reader: This project is still within its initial 
phase. 


\section{Software}

\subsection{License}


SyFi employs GiNaC and is therefore limited by GiNaCs license, which 
is the GPL-2 licence listed below.  

However, SyFi is usually used to generated code. The generated code
is free. 

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Notice, however that SyFi is usually used to generate code. This code is
free, but it comes without any warranty for fitness of any purpose.   

In the case where the GNU licence does not fit your need. Contact
the authors at \emp{syfi-dev@fenics.org}.




\subsection{Installation}

\paragraph{Dependencies}
SyFi is a C++ library and  therefore a C++ compiler is needed. 
At present the library has only been tested with the GNU C++
compiler. The \emp{configure} script is a shell script made
by the tools Automake and Autoconf. Hence, you can run this script 
with, e.g., the GNU Bourne-again shell. Finally, SyFi relies on the C++ library
GiNaC. 

\paragraph{Configuration and Installation} 
As mention earlier, the configuration, build and
installation scripts are all made by the Autoconf and
Automake tools. Hence,  to configure, build
and install the package, simply execute the commands,  
\begin{code}
bash >./configure
bash >make
bash >make install
\end{code}
\noindent
If this does not work, it is most likely because GiNaC is not properly 
installed on your system.  Check if you have the script \emp{ginac-config} in your path.         

\paragraph{Reporting Bugs/Submitting Patches} 


In case, you want to contribute code, please create a patch with \emp{diff}, 
\begin{code}
bash >diff -u -N -r SyFi  SyFi-mod > SyFi-<name>-<date>.patch 
\end{code}
\noindent
Here \emp{<name>} should be replaced with your name and 
\emp{<date>} should be replaced with the current date. 

The patch should be mailed to the SyFi mailing-list at \emp{syfi-dev@fenics.org}.   
 

\subsection{Python Support}
SyFi comes with Python support. The Python module
is made by using the tool SWIG \cite{www:swig}. In 
addition, one should also install Swiginac \cite{www:swiginac}, 
which is a Python interface to GiNaC created by using SWIG.  
More about the usage of the Python interface can be found in Section
\ref{sec:python}. 

\subsection{Examples and Tests}


A series of tests are located in the subdir \emp{tests}, these
test serve as unit test and document the features of SyFi as described
in this tutorial. If the tests are simple we use the function \emp{EQUAL\_OR\_DIE},
an example is (see also \emp{simple\_test.cpp} 
\begin{code}
  symbol x("x"); 
  ex f = x*x; 
  ex intf = integral(x,0,1,f);
  intf = eval_integ(intf);
  EQUAL_OR_DIE(integral1, "1/3");
\end{code}

When the tests or computed expressions  are bigger we typically   
store the expressions in a GiNaC archive (\emp{.gar} files) and compare the archive 
with a previously created and verified archive. The following 
code demostrates how the basis functions and degrees of freedom 
of a first order Lagrangian element is computed, stored in an archive
and then compared with the previously verified basis functions and 
degrees of freedom. 
\begin{code}
  int order = 1;
  ReferenceTriangle triangle;
  LagrangeFE fe(triangle, order);

  // regression test
  archive ar;
  for (int i=0; i< fe.nbf(); i++) {
    ar.archive_ex(fe.N(i) , istr("N",i).c_str());
    ar.archive_ex(fe.dof(i) , istr("D",i).c_str());
  }
  ofstream vfile("fe_ex1.gar.v");
  vfile << ar; vfile.close();
  if(!compare_archives("fe_ex1.gar.v", "fe_ex1.gar.r")) {
    cerr << "Failure!" << endl;
    return -1;
  }
\end{code}

All examples described in this tutorial are also implemented as tests in the \emp{tests} subdir. 

\subsection{GiNaC Tools}

\subsubsection{The symbol factory}
In GiNaC, the identity of a symbol is not defined by its name, but
by an internal number. Because of this, the code
\begin{code}
ex a = symbol("x");
ex b = symbol("x");
ex c = a-b;
\end{code}
does not yield 0 in c, since a and b refer to different symbols.
To solve this we have implemented a simple symbol factory, so
we can refer to variables by name without passing the symbol objects
around everywhere. The user can ask if a symbol exists, or get numbered
symbols and vectors or matrices of numbered symbols in a convenient way.
\begin{code}
ex x1 = get_symbol("x");
ex x2 = get_symbol("x");
assert( is_zero(x1-x2) );

ex u = get_symbolic_vector(3, "u");
ex A = get_symbolic_matrix(3, 3, "A");
ex c = isymb("c", 2);
assert( symbol_exists("c2") );
\end{code}



\subsubsection{Symbols for spatial variables}
Certain operations like the differential operators diff and grad needs to know certain symbols
to operate correctly. The spatial variables x,y,z and t are particularly important, and
because of this we have a shortcut to these variables. Operations like grad also need
to know the number of spatial dimensions, often abbreviated nsd in SyFi.
Therefore, a call to initSyFi(nsd) must be made before one can use these operators.
It is safe to call initSyFi more than once. The spatial symbols x,y,z,t can also be
retrieved from the symbol factory.
\begin{code}
initSyFi(3);
int space_dim = SyFi::nsd;
ex x = SyFi::x;
ex y = SyFi::y;
ex z = SyFi::z;
ex t = SyFi::t;
// or: 
ex x = get_symbol("x");
\end{code}



%\subsection{Notes on Style}

\section{A Finite Element}
\subsection{Basic Concepts}

To keep the abstractions clear we briefly review the general  
definition of a finite element, see e.g., 
Brenner and Scott \cite{BrennerScott} or 
Ciarlet \cite{Ciarlet}.
\begin{definition}[A Finite Element]
\label{def:finite:element}
A finite element consists of, 
\begin{enumerate}
\item A polygonal domain, $T$.  
\item A polynomial space, $V$.  
\item A set of degrees of freedom (linear forms), $L_i : V \rightarrow \R $,
for $i=1,\ldots,n$, where $n=\dim(V)$, that determines $V$ uniquely.      
\end{enumerate} 
\end{definition}
Furthermore, to determine a basis in $V$, $\{N_i\}_{i=1}^{n}$,  we form
the linear system of equations,   
\begin{equation}
\label{dofdelta}
L_i(N_j) = \delta_{ij},   
\end{equation}
and solve it. 

\begin{example}[Linear Lagrangian element on the reference triangle]
In this example we describe how the linear Lagrangian element is defined
on the reference triangle.  
Let $T$ be the unit triangle with vertices $(0,0)$, $(1,0)$, and $(0,1)$. 
Furthermore, the polynomial space $V$ consists of linear polynomials, i.e., 
polynomials on the form $ N(x,y) = a + b x + c y$. 
The degrees of freedom for a linear Lagrangian element are simply 
the pointvalues at the vertices, $\xx_i$,  
$L_i(N_j) = N_j(\xx_i)$. 
The degrees of freedom and \eqref{dofdelta} determined
$a_j$, $b_j$, and $c_j$ for each basis function $N_j$.  
For instance $N_1$, which is on the form 
$a_1 + b_1 x + c_1 y$, is determined by,  
\[
L_i(N_1) = N_1(\xx_i) = \delta_{i1}, 
\]
or written out as a system of linear equations,  
\[
\left[
\begin{array}{ccc}
1 & 0 & 0 \\
1 & 1 & 0 \\
1 & 0 & 1 \\
\end{array}
\right]
\left[
\begin{array}{c}
a_1 \\
b_1 \\
c_1 \\
\end{array}
\right]
= 
\left[
\begin{array}{c}
1 \\
0 \\
0 \\
\end{array}
\right]
\]
Hence, 
\[
N_1 = 1 - x - y . 
\]
The functions $N_2$ and $N_3$ can be determined similarly. 
\end{example}

\noindent
In the next sections we will go detailed through polygons, 
polynomial spaces and degrees of freedom, and the corresponding
software components. 


\subsection{Polygons}
In the finite element method we need the concept of  
simple  polygons to define integration, polynomial spaces etc. 
The basic polygons are lines, triangles, tetrahedra, and orthogonal rectangles and boxes. 
These basic components will be briefly described in this section.  

\subsubsection{Line} 
A line segment, L,  between two points $\xx_0 = [x_0, y_0, z_0]$ and $\xx_1 = [x_1, y_1, z_1]$ in 3D is defined as, see also Figure \ref{fig:line},    
\begin{eqnarray}
\label{line:repr:x}
x &=& x_0 + a\, t, \\ 
\label{line:repr:y}
y &=& y_0 + b\, t, \\ 
\label{line:repr:z} 
z &=& z_0 + c\, t, \\ 
\label{line:repr:t}
t &\in& [0,1],    
\end{eqnarray}
where $a = x_1 - x_0$, $b = y_1 - y_0$, and $c = z_1 - z_0 $.   

Integration of a function $f(x,y,z)$ along the line segment $L$
is performed by substitution,  
\begin{equation}
\int_L f(x,y,z) \,  dx \, dy \, dz  = \int_0^1 f(x(t), y(t), z(t)) \, D \,dt,   
\end{equation}
where $D = \sqrt{a^2 + b^2 + c^2}$.  

\begin{figure}
\begin{center}
\label{fig:line}
\caption{A line.}
\input{figs/line.xfig.eepicemu}
\end{center}
\end{figure}





\paragraph{Software Component: Line} 
The class \emp{Line} implements a general line. It is defined as follows 
(see \emp{Polygon.h}):  

%% BEGIN CODE FROM Polygon.h 
\begin{code}
class Line : public Polygon  {
ex a_; 
ex b_; 
  public: 
  Line() {}
  Line(ex x0, ex x1,  // x0_ and x1_ are points 
       string subscript = ""); 
  ~Line(){}

  virtual int no_vertices(); 
  virtual ex vertex(int i); 
  virtual ex repr(ex t); 
  virtual string str(); 
  virtual ex integrate(ex f);  
};
\end{code}
%% END CODE FROM Polygon.h 

\noindent 
Most of the functions in this class are self-explanatory. However, the function
\emp{repr} deserves special attention. The function \emp{repr} returns 
the mathematical
definition of a line. To be precise, this function returns
a list of expressions (\emp{lst}), where the items are
the items in \eqref{line:repr:x}-\eqref{line:repr:t} (see also the
example below).    

\noindent
The basic usage of a line is as follows (see \emp{line\_ex1.cpp}),  

%% BEGIN CODE FROM line_ex1.cpp 
\begin{code}
  ex p0 = lst(0.0,0.0,0.0);
  ex p1 = lst(1.0,1.0,1.0);
  
  Line line(p0,p1);
  
  // show usage of repr 
  symbol t("t"); 
  ex l_repr = line.repr(t);
  cout <<"l.repr "<<l_repr<<endl; 
  EQUAL_OR_DIE(l_repr, "{x==t,y==t,z==t,{t,0,1}}"); 

  for (int i=0; i< l_repr.nops(); i++) {
    cout <<"l_repr.op(" <<i<<"):  "<<l_repr.op(i)<<endl; 
  }
  
  // compute the integral of a function along the line 
  ex f = x*x + y*y*y + z;
  ex intf = line.integrate(f); 
  cout <<"intf "<<intf<<endl; 
  EQUAL_OR_DIE(intf, "13/12"); 
\end{code}
%% END CODE FROM line_ex1.cpp 
\noindent 
The function \emp{EQUAL\_OR\_DIE} compares the string representation of the
expression with an expected expression represented as a character array.   
If the string representation of the expression and the character array 
are not equal the program dies, and this tells the programmer that
the test faulted. The reason for the use of this function is that our test examples
also serve as regression tests for the package.  

\subsubsection{Triangle} 
A triangle is defined in terms of three points $\xx_0$, 
$\xx_1$, and $\xx_2$. Associated with each triangle
are three lines; the first line is between the points $\xx_0$ and  $\xx_1$, 
the second line is between the points $\xx_0$ and  $\xx_2$, and
the third line is between the points $\xx_1$ and  $\xx_2$.
This is  shown in Figure \ref{fig:triangle}.  The triangle can be represented as  
\begin{eqnarray}
\label{triangle:repr:x}
x &=& x_0 + a r + b s, \\ 
\label{triangle:repr:y}
y &=& y_0 + c r + d s, \\ 
\label{triangle:repr:z}
z &=& z_0 + e r + f s, \\ 
\label{triangle:repr:s}
s &\in& [0,1-r],    \\
\label{triangle:repr:r}
r &\in& [0,1],    
\end{eqnarray}
where $(a,c,e) = (x_1-x_0, y_1-y_0, z_1-z_0) $ and $(b,d,f) = (x_2-x_0, y_2-y_0, z_2-z_0) $. 

\begin{figure}
\begin{center}
\caption{Triangle}
\label{fig:triangle}
\input{figs/triangle.xfig.eepicemu}
\end{center}
\end{figure}



Integration is performed by substitution, 
\[
\int_T f(x,y,z) \, dx\,dy\,dz =  
\int^1_0 \int^{1-r}_0 f(x,y,z) \, D \, ds\, dr,   
\]
where $D= \sqrt{(cf-de)^2 + (af-be)^2 + (ad-bc)^2}$. 



\paragraph{Software Component: Triangle }  

The class \emp{Triangle} implements a general triangle. It is defined as follows 
(see \emp{Polygon.h}):  
  
%% BEGIN CODE FROM Polygon.h 
\begin{code}
class Triangle : public Polygon {
  public: 
  Triangle(ex x0, ex x1, ex x1, string subscript = ""); 
  Triangle() {}
  ~Triangle(){}

  virtual int no_vertices(); 
  virtual ex vertex(int i); 
  virtual Line line(int i); 
  virtual ex repr(); 
  virtual string str(); 
  virtual ex integrate(ex f); 
}; 
\end{code}
%% END CODE FROM Polygon.h 


\noindent
Here the function \emp{repr} returns a list with the items \eqref{triangle:repr:x}-\eqref{triangle:repr:r}. In addition to the functions also found
in \emp{Line}, \emp{Triangle} has a function \emp{line(int i)}, returning
a line.\\
\\
\noindent
The basic usage of a triangle is as follows (see \emp{triangle\_ex1.cpp}),  
%% BEGIN CODE FROM triangle_ex1.cpp 
\begin{code}
  ex p0 = lst(0.0,0.0,1.0);
  ex p1 = lst(1.0,0.0,1.0);
  ex p2 = lst(0.0,1.0,1.0);
  
  Triangle triangle(p0,p1,p2);
  
  ex repr = triangle.repr();
  cout <<"t.repr "<<repr<<endl; 
  EQUAL_OR_DIE(repr, "{x==r,y==s,z==1.0,{r,0,1},{s,0,1-r}}");   
  
  ex f = x*y*z;
  ex intf = triangle.integrate(f); 
  cout <<"intf "<<intf<<endl; 
  EQUAL_OR_DIE(intf, "1/24"); 
\end{code}
%% END CODE FROM triangle_ex1.cpp 

\subsubsection{Tetrahedron} 

A tetrahedron is defined by four points $\xx_0$, $\xx_1$, $\xx_2$, and
$\xx_3$. Associated with a tetrahedron are four triangles and 
six lines. The convention used so far is that 
\begin{itemize}
\item 
the first line connects $\xx_0$ and $\xx_1$, 
\item 
the second line connects $\xx_0$ and $\xx_2$, 
\item 
the third line connects $\xx_0$ and $\xx_3$, 
\item 
the fourth line connects $\xx_1$ and $\xx_2$, 
\item 
the fifth line connects $\xx_1$ and $\xx_3$, 
\item 
the sixth line connects $\xx_2$ and $\xx_3$. 
\end{itemize}
The $i$'th triangle has the vertices 
$\xx_{i\%4}$, $\xx_{(i+1)\%4}$, and  $\xx_{(i+2)\%4}$, where 
\% is the modulus operator. 
The tetrahedron can be represented as, see also Figure \ref{fig:tetrahedron}, 
\begin{eqnarray}
\label{tetrahedron:repr:x}
x &=& x_0 + a r + b s + c t , \\ 
\label{tetrahedron:repr:y}
y &=& y_0 + d r + e s + f t, \\ 
\label{tetrahedron:repr:z}
z &=& z_0 + g r + h s + k t, \\ 
\label{tetrahedron:repr:t}
t &\in& [0,1-r-s],    \\
\label{tetrahedron:repr:s}
s &\in& [0,1-r],    \\
\label{tetrahedron:repr:r}
r &\in& [0,1],    
\end{eqnarray}
where $(a,d,g) = (x_1-x_0, y_1-y_0, z_1-z_0) $, 
$(b,e,h) = (x_2-x_0, y_2-y_0, z_2-z_0) $, and  
$(c,f,k) = (x_3-x_0, y_3-y_0, z_3-z_0) $. 

As earlier, integration is performed with substitution, 
\begin{eqnarray*}
&&\int_T f(x,y,z) \, dx\, dy\, dz  =   \\
&& \int^1_0 \int_0^{1-r} \int_0^{1-r-s} f(x(r,s,t), y(r,s,t), z(r,s,t)) \, D \, dt\, ds \, dr,       
\end{eqnarray*}
where $D$ is the determinant of,   
\[
\left[
\begin{array}{ccc}
a & b & c \\  
d & e & f \\ 
g & h & k 
\end{array}
\right] .
\]




\begin{figure}
\begin{center}
\caption{A tetrahedron.}
\label{fig:tetrahedron}
\input{figs/tetrahedron.xfig.eepicemu}
\end{center}
\end{figure}



\paragraph{Software Component: Tetrahedron} 

The class \emp{Tetrahedron} implements a general tetrahedron. 
It is defined as follows (see \emp{Polygon.h}): 

%% BEGIN CODE FROM Polygon.h
\begin{code}
class Tetrahedron : public Polygon {
  public: 
  Tetrahedron(string subscript) {}
  Tetrahedron(ex x0, ex x1, ex x1, ex x2, string s= ""); 
  ~Tetrahedron(){}

  virtual int no_vertices(); 
  virtual ex vertex(int i); 
  virtual Line line(int i); 
  virtual Triangle triangle(int i); 
  virtual ex repr(); 
  virtual string str(); 
  virtual ex integrate(ex f);
}; 
\end{code}
%% END CODE FROM Polygon.h 
\noindent
The function \emp{repr} returns a list representing \eqref{tetrahedron:repr:x}
--\eqref{tetrahedron:repr:r}. In addition to the usual functions
it has the functions \emp{line(int i)} and \emp{triangle(int i)} for returning
the $i$'th line and the $i$'th triangle, respectively.  \\
\\

\noindent
Its basic usage is as follows (see \emp{tetrahedron\_ex1.cpp}), 

%% BEGIN CODE FROM tetrahedron_ex1.cpp 
\begin{code}
  ex p0 = lst(0.0,0.0,0.0);
  ex p1 = lst(1.0,0.0,0.0);
  ex p2 = lst(0.0,1.0,0.0);
  ex p3 = lst(0.0,0.0,1.0);
  
  Tetrahedron tetrahedron(p0,p1,p2,p3);
  
  ex repr = tetrahedron.repr();
  cout <<"t.repr "<<repr<<endl; 
  EQUAL_OR_DIE(repr, "{x==r,y==s,z==t,{r,0,1},
                      {s,0,1-r},{t,0,1-s-r}}");  
  
  ex f = x*y*z;
  ex intf = tetrahedron.integrate(f); 
  EQUAL_OR_DIE(intf, "1/720"); 
\end{code}
%% END CODE FROM tetrahedron_ex1.cpp 


\subsubsection{Rectangle}

The rectangles currently supported by SyFi are orthogonal. Such a rectangle
is defined in terms of two points $\xx_0$ and $\xx_1$, as shown in Figure
\ref{fig:rectangle}.  
\begin{figure}
\begin{center}
\caption{A rectangle.}
\label{fig:rectangle}
\input{figs/rectangle.xfig.eepicemu}
\end{center}
\end{figure}




The rectangle can be represented as 
\begin{eqnarray}
\label{rectangle:repr:x}
x &=& x_0 + a r, \\ 
\label{rectangle:repr:y}
y &=& y_0 + b s, \\ 
\label{rectangle:repr:z}
z &=& z_0 + c t, \\ 
\label{rectangle:repr:r}
r &\in& [0,1],    \\
\label{rectangle:repr:s}
s &\in& [0,1],   \\ 
\label{rectangle:repr:t}
t &\in& [0,1],    
\end{eqnarray}
where $a= x_1-x_0$, $b= y_1-y_0$, and $c= z_1-z_0$. Notice that either $a$, $b$, or $c$    
needs to be zero, or else \eqref{rectangle:repr:x}-\eqref{rectangle:repr:t} defines a
box (which will be described later). 

As earlier, integration is performed with substitution, 
\begin{eqnarray*}
&&\int_R f(x,y,z) \, dx\, dy\, dz  =   \\
&& \int^1_0 \int_0^1 \int_0^1 f(x(r,s,t), y(r,s,t), z(r,s,t)) \, D \, dt\, ds \, dr,       
\end{eqnarray*}
where $D = a b$ if $c=0$, $D = b c$, if $a=0$, and  
$D = a c$,  if $b=0$. 



\paragraph{Software Component: Rectangle} 

The class \emp{Rectangle} implements a general orthogonal rectangle. 
It is defined as follows (see \emp{Polygon.h}): 
%% BEGIN CODE FROM Polygon.h
\begin{code}
class Rectangle : public Polygon {
  public: 
  Rectangle(GiNaC::ex p0, GiNaC::ex p1, string s = "");
  Rectangle() {} 
  virtual ~Rectangle(){} 
  
  virtual int no_vertices(); 
  virtual GiNaC::ex vertex(int i); 
  virtual Line line(int i); 
  virtual GiNaC::ex repr(Repr_format format = SUBS_PERFORMED); 
  virtual string str(); 
  virtual GiNaC::ex integrate(GiNaC::ex f); 
}; 
\end{code}
%% END CODE FROM Polygon.h 

\noindent
As described with the previous polygons, the function \emp{repr} returns a list with the items  
\eqref{rectangle:repr:x}-\eqref{rectangle:repr:t}.  The basic usage of the
rectangle is as follows (see \emp{rectangle\_ex1.cpp}), 

%% BEGIN CODE FROM rectangle_ex1.cpp 
\begin{code}
  ex f = x*y;

  ex p0 = lst(0.0,0.0);
  ex p1 = lst(1.0,1.0);
  
  Rectangle rectangle(p0,p1);
  
  ex repr = rectangle.repr();
  cout <<"s.repr "<<repr<<endl; 
  
  ex intf = rectangle.integrate(f); 
  cout <<"intf "<<intf<<endl; 
 
  ex f2 = (x+1)*y*z;
  p0 = lst(0.0,0.0,1.0);
  p1 = lst(0.0,1.0,0.0);
  
  Rectangle rectangle2(p0,p1);
  
  ex repr2 = rectangle2.repr();
  cout <<"s2.repr "<<repr2<<endl; 
  
  ex intf2 = rectangle2.integrate(f2); 
  cout <<"intf2 "<<intf2<<endl; 
\end{code}
%% END CODE FROM rectangle_ex1.cpp 





\subsubsection{Box}

Currently, SyFi only supports orthogonal boxes (as was also the case with rectangles).  
Such a box is defined in terms of two points $\xx_0$ and $\xx_1$, as can be seen in 
Figure \ref{fig:box}. 
The box can be represented as 
\begin{eqnarray}
\label{box:repr:x}
x &=& x_0 + a r, \\ 
\label{box:repr:y}
y &=& y_0 + b s, \\ 
\label{box:repr:z}
z &=& z_0 + c t, \\ 
\label{box:repr:r}
r &\in& [0,1],    \\
\label{box:repr:s}
s &\in& [0,1],   \\ 
\label{box:repr:t}
t &\in& [0,1],    
\end{eqnarray}
where $a= x_1-x_0$, $b= y_1-y_0$, and $c= z_1-z_0$. 

As earlier, integration is performed with substitution, 
\begin{eqnarray*}
&&\int_R f(x,y,z) \, dx\, dy\, dz  =   \\
&& \int^1_0 \int_0^1 \int_0^1 f(x(r,s,t), y(r,s,t), z(r,s,t)) \, D \, dt\, ds \, dr,       
\end{eqnarray*}
where $D = a b c$. 

\begin{figure}
\begin{center}
\caption{A Box.}
\label{fig:box}
\input{figs/box.xfig.eepicemu}
\end{center}
\end{figure}

\paragraph{Software Component: Box} 

The class \emp{Box} implements a general orthogonal box. 
It is defined as follows (see \emp{Polygon.h}): 
%% BEGIN CODE FROM Polygon.h
\begin{code}
class Box: public Polygon {
  public: 
  Box(GiNaC::ex p0, GiNaC::ex p1, string subscript = "");
  Box(){}
  virtual ~Box(){} 
  
  virtual int no_vertices(); 
  virtual GiNaC::ex vertex(int i); 
  virtual Line line(int i); 
  virtual GiNaC::ex repr(Repr_format format = SUBS_PERFORMED); 
  virtual string str(); 
  virtual GiNaC::ex integrate(GiNaC::ex f); 
}; 
\end{code}
%% END CODE FROM Polygon.h 

\noindent
The \emp{repr} function returns a list of the definition of 
a orthogonal box in \eqref{box:repr:x}-\eqref{box:repr:t}. 
A box can be used as follows (see \emp{box\_ex1.cpp}), 

%% BEGIN CODE FROM box_ex1.cpp 
\begin{code}
  ex p0 = lst(-1.0,-1.0,-1.0);
  ex p1 = lst( 1.0, 1.0, 1.0);
  
  Box box(p0,p1);
  
  ex repr = box.repr();
  cout <<"b.repr "<<repr<<endl; 
  
  ex intf = box.integrate(f); 
  cout <<"intf "<<intf<<endl; 
\end{code}
%% END CODE FROM box_ex1.cpp 



Finally, we also mention that in addition to the above mentioned classes, 
\emp{Line}, \emp{Triangle}, \emp{Tetrahedron}, \emp{Rectangle}, and
\emp{Box}, we have implemented the corresponding reference geometries
in the subclasses  
\emp{ReferenceLine}, \emp{ReferenceTriangle}, \emp{ReferenceTetrahedron}, \emp{ReferenceRectangle}, and
\emp{ReferenceBox}. 



\subsection{Polynomial Spaces}
\label{sec:pol:space}
The space of polynomials of degree less or equal to $n$, $\P_n$, plays 
a fundamental role in the construction of finite elements. 
There are many ways to represent this polynomial space. The perhaps visually nicest representation is  having it spanned 
by the basis (in 1D) ${1, x, x^2, \ldots, x^n}$. This representation
is not suitable for polynomials of high degree\footnote{In that case, one should 
use the Bernstein or Legendre polynomials.}.
\\
\noindent
In 1D, $\P_n$ is spanned by functions on the form 
\begin{equation}
\label{pn1d}
v = a_0 + a_1 x + \ldots a_n x^n = \sum^n_{i=0} a_i x^i 
\end{equation}
In 2D on triangles, $\P_n$ is spanned by functions on the form:  
\begin{equation}
\label{pn2d}
v = \sum^{i+j<=n}_{i,j=0} a_{ij} x^i y^j   
\end{equation}
In 2D on quadrilaterals, $\P_n$ is spanned by functions on the form:  
\begin{equation}
\label{bn2d}
v = \sum^{i,j<=n}_{i,j=0} a_{ij} x^i y^j   
\end{equation}
The corresponding polynomial spaces in 3D are completely analogous. 

\paragraph{Software Component: Polynomial Space} 
The following functions generate symbolic expressions
for the above polynomial spaces \eqref{pn1d}, \eqref{pn2d}, and \eqref{bn2d}, 
their corresponding polynomial spaces in 3D and their vector counterparts. 
%% BEGIN CODE FROM tools.h 
\begin{code}
// generates a polynomial of any order on a line, 
// a triangle, or a tetrahedron 
ex pol(int order, int nsd, const string a);  

// generates a vector polynomial of any order on a line, 
// a triangle or a tetrahedron 
lst polv(int order, int nsd, const string a);  

// generates a polynomial of any order on a square or a box   
ex polb(int order, int nsd, const string a);  

// generates a vector polynomial of any order 
// on a square or a box  
lst polbv(int order, int nsd, const string a);  
\end{code}
%% END CODE FROM tools.h 

\noindent
The function \emp{pol} returns a list with the following 3 items,  
\label{function:pol}
\begin{enumerate}
\item The polynom, e.g.,  $a_0 + a_1 x + \ldots + a_n x^n$  in 1D.  
\item A list of variables, e.g., ${a_0, a_1,\ldots, a_n}$ in 1D. 
\item A list containing the basis, e.g., ${1, x,\ldots, x^n}$ in 1D. 
\end{enumerate}
The functions \emp{polb}, \emp{polv}, and \emp{polbv} return lists
that are completely analogous. 

These abstract polynomials (or polynomial spaces) can be easily manipulated, 
e.g., (see also \emp{pol.cpp}),   
 
%% BEGIN CODE FROM pol.cpp 
\begin{code}
  int order = 2; 
  int nsd   = 2; 

  ex polynom_space = pol(order,nsd, "a"); 
  cout <<"polynom_space "<<polynom_space<<endl; 

  ex p = polynom_space.op(0); 
  cout <<"polynom p = "<<p<<endl; 
  EQUAL_OR_DIE(p,"y^2*a5+x^2*a3+a2*y+y*x*a4+a0+a1*x"); 

  ex dpdx = diff(p,x);   
  cout <<"dpdx = "<<dpdx<<endl; 
  EQUAL_OR_DIE(dpdx, "y*a4+a1+2*x*a3"); 

  Triangle triangle(lst(0,0), lst(1,0), lst(0,1)); 
  ex intp = triangle.integrate(p); 
  cout <<"integral of p on reference triangle="<<intp<<endl;  
  EQUAL_OR_DIE(intp, "1/6*a2+1/6*a1+1/12*a5
                      +1/2*a0+1/24*a4+1/12*a3"); 
\end{code}
%% END CODE FROM pol.cpp 


\subsubsection{Bernstein Polynomials}

Another basis for $\P_n$ is the Bernstein polynomials. This basis 
is much better suited for polynomials of high degree. Moreover, these polynomials
can be easily expressed in barycentric coordinates, which makes
them easy to adapt to, e.g., faces of polygons\footnote{This will be used in 
the definition of the Raviart-Thomas element.} etc.     

In 1D, the polynomial basis is on the form,  
\[
B_{i,n} = \binom{i}{n} x^i (1-x)^{n-i}, \quad i=0,\ldots,n .    
\]
And with this basis, $\P_n$ can be spanned by functions on the form,   
\[
v = a_0 B_{0,n} + a_1 B_{1,n} + \ldots a_n B_{n,n}  . 
\]
One reason for the widespread use of these polynomials is that they adapt easily
to general triangles and tetrahedra, by using barycentric coordinates.   
Let $b_1$, $b_2$, and $b_3$ be the barycentric coordinates for
the triangle shown in Figure \ref{fig:triangle}. Then the basis is
on the form,  
\[
B_{i,j,k,n} = \frac{n!}{i!j!k!} b_1^i b_2^j b_3^k, \quad  for \ i+j+k=n .     
\]
and $\P_n$ is spanned by functions on the form,  
\[
v = \sum_{i+j+k=n} a_{i,j,k} B_{i,j,k,n} . 
\]
The Bernstein polynomials in 3D are completely analogous. 
  


\paragraph{Software Components: Bernstein polynomials}
The following functions generate symbolic expressions for 
$\P^n$ using the Bernstein basis, 

%% BEGIN CODE FROM Polygon.h 
\begin{code}
// polynom of arbitrary order on a line, a triangle, 
// or a tetrahedron using the Bernstein basis 
ex bernstein(int order, Polygon& p, const string a);  

// vector polynom of arbitrary order on a line, a triangle, 
// or a tetrahedron using the Bernstein basis 
lst bernsteinv(int order, Polygon& p, const string a);  
\end{code}
%% END CODE FROM Polygon.h 
\noindent
These functions return lists  that are analogous to the lists made by the functions \emp{pol}
 and \emp{polv} described on page \pageref{function:pol}.

As described earlier, GiNaC has the tools for manipulating these
polynomial spaces, (see also \emp{pol.cpp})
%% BEGIN CODE FROM pol.cpp  
\begin{code}
  ex polynom_space2 = bernstein(order,triangle, "a"); 
  ex p2 = polynom_space2.op(0); 
  cout <<"polynom p2 = "<<p2<<endl; 
  EQUAL_OR_DIE(p2, "y^2*a0+2*(1-y-x)*x*a4+2*(1-y-x)*a3*y
                    +(1-y-x)^2*a5+2*a1*y*x+a2*x^2"); 

  ex dp2dx = diff(p2,x);   
  cout <<"dp2dx = "<<dp2dx<<endl; 
  EQUAL_OR_DIE(dp2dx, "2*a1*y+2*(-1+y+x)*a5+2*a2*x
                       +2*(1-y-x)*a4-2*a3*y-2*x*a4"); 

  ex intp2 = triangle.integrate(p2); 
  cout <<"integral of p2 on reference triangle="<<intp<<endl;  
  EQUAL_OR_DIE(intp2, "1/12*a3+1/12*a2+1/12*a1+1/12*a5
                       +1/12*a0+1/12*a4"); 
\end{code}
%% END CODE FROM pol.cpp 


\subsubsection{Legendre Polynomials}

A popular polynomial basis for polygons that are either rectangles or boxes 
are the Legendre polynomials. 
This polynomial basis is also usable to represent polynomials of high degree.  
The basis is defined on the interval $[-1,1]$, as
\[  
L_k(x) = \frac{1}{2^k k!} \frac{d^k}{dx^k} (x^2 -1), \quad k=0,1,\ldots,     
\]
A nice feature with these polynomials is that they are orthogonal 
with respect to the $L_2$ inner product, i.e.,  
\[
\int_{-1}^1 L_k (x) L_l(x) \, dx  = 
\left\{ 
\begin{array}{c}   
\frac{2}{2k+1}, \ k=l, \\ 
0 , \ \ k\not= l, \\ 
\end{array}
\right. 
\]
The Legendre polynomials are extended to 2D and 3D simply by taking the tensor
product, 
\[
L_{k,l,m}(x,y,z) = L_k(x) L_l(y) L_m(z) .   
\]
and $\P^n$ is defined by functions on the form (in 3D),  
\[
v = \sum_{k,l,m=0}^{k,l,m <= n}   a_{k,l,m} L_{k,l,m} .   
\]


\paragraph{Software Components: Legendre polynomials}
The following functions generate symbolic expressions for 
$\P^n$ using the Legendre basis, 

%% BEGIN CODE FROM tools.h 
\begin{code}
// generates a Legendre polynom of arbitrary order 
GiNaC::ex legendre(int order, int nsd, const string a);  
// generates a Legendre vector polynom of arbitrary order 
GiNaC::lst legendrev(int no_fields, int order, 
                     int nsd, const string a);  
\end{code}
%% END CODE FROM tools.h 
\noindent
These functions return lists  that are analogous to the lists made by the functions \emp{pol}
 and \emp{polv} described on page \pageref{function:pol}.

The following code demonstrates the use of the Legendre polynomials, and 
(when runned) that the basis is orthogonal (see also \emp{legendre.cpp}).
%% BEGIN CODE FROM legendre.cpp  
\begin{code}
  int order = 2; 
  int nsd   = 2; 

  ex polynom_space = legendre(order,nsd, "a"); 
  cout <<"polynom_space "<<polynom_space<<endl; 

  ex p = polynom_space.op(0); 
  cout <<"polynom p = "<<p<<endl; 

  ex dpdx = diff(p,x);   
  cout <<"dpdx = "<<dpdx<<endl; 

  ex p0 = lst(-1,-1);
  ex p1 = lst(1,1);

  Rectangle rectangle(p0,p1) ;
  ex basis = polynom_space.op(2); 
  for (int i=0; i< basis.nops(); i++) {
      cout <<"i "<<i<<endl; 
      ex integrand = p*basis.op(i); 
      ex ai = rectangle.integrate(integrand); 
      cout <<"ai "<<ai<<endl; 
  }
\end{code}
%% END CODE FROM legendre.cpp 


\subsubsection{Homogeneous Polynomials}
\label{sec:homo:pol}

Another set of polynomials which sometimes are useful are the set
of homogeneous polynomials $\H^n$. These are polynomials where all terms
have the same degree. $\H^n$ is in 2D spanned by polynomials on the 
form:        
\[
v = \sum_{
{\small
\begin{array}{c}
i,j, \\
i+j=n
\end{array}
}
} 
a_{i,j,k} x^i y^j 
\]

\paragraph{Software Components: Homogeneous polynomials}

The following functions generate symbolic expressions for 
$\H^n$, 

%% BEGIN CODE FROM tools.h 
\begin{code}
// generates a homogeneous polynom of arbitrary order 
GiNaC::ex homogenous_pol(int order, int nsd, const string a);  
// generates a homogenous vector polynom of arbitrary order 
GiNaC::lst homogenous_polv(int no_fields, int order, 
                           int nsd, const string a);  
\end{code}


The use of these polynomials are similar to the other polynomials described earlier. 


\subsection{A Finite Element}

\label{sec:fem:usage}

Before we start describing how to construct a finite element
based on the Definition \ref{def:finite:element},  
we will concentrate on the \emph{usage} of a finite element.
A finite element has only two interesting components, 
the basis functions ${N_i}$ and the corresponding 
degrees of freedom ${L_i}$. The basis functions (and their 
derivatives) are used to compute the element matrices
and the element vectors, while the degrees of freedom 
are used to define the mapping between the element matrices/vectors 
and the global matrix/vector. 
As we see in the following, the observation that only these two 
components are needed  leads us to a
minimalistic definition of a finite element in our software
tools.  

  

\paragraph{Software Component: Finite Element} 

Due to the powerful expression class in GiNaC, \emp{ex},  
our base class for the finite elements can be very small. 
Both the basis function $N_i$ and the corresponding 
degree of freedom $L_i$ can be well represented as
an \emp{ex}. Hence, the following definition of 
a finite element is suitable,  
%% BEGIN CODE FROM FE.h
\begin{code}
class FE {
  public: 
  FE() {}
  ~FE() {}

  virtual void set_polygon(Polygon& p);  // Set domain
  virtual Polygon& get_polygon(); // Get polygonal domain 
  virtual ex N(int i);           // The i'th basis function  
  virtual ex dof(int i);         // The i'th degree of freedom 
  virtual int nbf();             // The number of basis 
                                 // functions/degrees of 
                                 // freedom 
};
\end{code}
%% END CODE FROM FE.h
\noindent
The usage of a finite element is as follows (see \emp{fe\_ex1.cpp} where Lagrangian elements are used), 
%% BEGIN CODE FROM fe_ex1.cpp
\begin{code}
  ex Ni; 
  ex gradNi; 
  ex dofi; 
  for (int i=0; i< fe.nbf(); i++) { 
    Ni = fe.N(i); 
    gradNi = grad(Ni); 
    dofi = fe.dof(i); 
    cout <<"The basis function, N("<<i<<")="<<Ni<<endl; 
    cout <<"The gradient of N("<<i<<")="<<gradNi<<endl; 
    cout <<"The corresponding dof, L("<<i<<")="<<dofi<<endl; 
  }
\end{code}
%% END CODE FROM fe_ex1.cp
\noindent
When you run \emp{fe\_ex1}, it produces the following output: 
%% BEGIN OUTPUT FROM fe_ex1  
\begin{code}
  The basis function, N(1)=2*y^2-y
  The gradient of N(1)=[[0],[-1+4*y]]
  The corresponding dof, L(1)={0,1}
  The basis function, N(2)=4*y*x
  The gradient of N(2)=[[4*y],[4*x]]
  The corresponding dof, L(2)={1/2,1/2}
  The basis function, N(3)=2*x^2-x
  The gradient of N(3)=[[-1+4*x],[0]]
  The corresponding dof, L(3)={1,0}
  The basis function, N(4)=-4*y*x-4*y^2+4*y
  The gradient of N(4)=[[-4*y],[4-8*y-4*x]]
  The corresponding dof, L(4)={0,1/2}
  The basis function, N(5)=-4*y*x-4*x^2+4*x
  The gradient of N(5)=[[4-4*y-8*x],[-4*x]]
  The corresponding dof, L(5)={1/2,0}
  The basis function, N(6)=1+4*y*x+2*x^2+2*y^2-3*y-3*x
  The gradient of N(6)=[[-3+4*y+4*x],[-3+4*y+4*x]]
  The corresponding dof, L(6)={0,0}
\end{code}
%% END OUTPUT FROM fe_ex1  



\noindent
The computation of the element matrix for a Poisson problem
is as follows (see \emp{fe\_ex2.cpp}), 
%% BEGIN CODE FROM fe_ex2.cpp
\begin{code}
  Triangle T(lst(0,0), lst(1,0), lst(0,1), "t"); 
  int order = 2; 

  std::map<std::pair<int,int>, ex> A;
  std::pair<int,int> index;
  LagrangeFE fe; 
  fe.set_order(order); 
  fe.set_polygon(T); 
  fe.compute_basis_functions(); 
  for (int i=0; i< fe.nbf(); i++) {
    index.first = i; 
    for (int j=0; j< fe.nbf(); j++) {
      index.second = j; 
      ex nabla = inner(grad(fe.N(i)), grad(fe.N(j))); 
      ex Aij = T.integrate(nabla);   
      A[index] = Aij;  
    }
  }
\end{code}
%% END CODE FROM fe_ex2.cp
\noindent 
Here, we have used the class \emp{LagrangeFE}, which is a subclass of \emp{FE},  
that implements
Lagrangian elements of arbitrary order. The construction of this element is
described later in Section \ref{Lagrangian:element}.   



\subsection{Degrees of Freedom}
\label{sec:dof}

As we have seen earlier, for each element $e$, we 
have a local set of degrees of freedom ${L_i^e}$, 
which in general are linear forms  on the polynomial
space. Degrees of freedom and linear forms are quite
general concepts, but the reader not familiar with this general definition can 
think of them for instance as nodal values at vertices, i.e., 
\[   
L_i(v) = v(\xx_i) . 
\]
Another example is the integral of $v$ over an edge (or a face), $e_i$,
of the polygon, 
\[
L_i(v) = \int_{e_i} v \,  ds.  
\]

The most important thing with the degrees of freedom, 
besides defining a basis for the polynomial space, 
is that
they provide a mapping from the local degree of freedom, $L_i^e$, 
on a given element, $e$,  to the global degree of freedom, $L_j$. This
mapping does in turn provide the mapping between the element matrices/vectors
and the global matrix/vector.  
Hence, we have the following mapping,  
\begin{equation}
\label{dof:loc2glob}
(e,i) \rightarrow L^e_i \rightarrow L_j  \rightarrow j . 
\end{equation}
Here $e$, $i$, and $j$ are integers, while $L^e_i$ and $L_j$
are degrees of freedom (or linear forms).  
Additionally, given a global degree of freedom we have 
a mapping to the local degrees of freedom, 
\begin{equation}
\label{dof:glob2loc}
j \rightarrow L_j \rightarrow {L^e_{i(e)}}_{e\in E(j)} \rightarrow { (e,i(e)) }_{e \in E(j)} .
\end{equation}
Here $E(j)$ is the set of elements sharing the degree of freedom $L_j$. 






\paragraph{Software Component: Degrees of Freedom Handler} 

A degree of freedom, local or global, is well represented
as an \emp{ex} (in fact \emp{ex} is more general than a linear form).   
Hence, to implement proper tools for handling the degrees of freedom, 
we only need to provide the mappings \eqref{dof:loc2glob} and
\eqref{dof:glob2loc}. 
We have implemented a class \emp{Dof} which provides these mappings,  

%% BEGIN CODE FROM Dof.h
\begin{code}
class Dof {
  protected: 
  int counter; 
  // the structures loc2dof, dof2index, and doc2loc  
  // are completely dynamic. They are all initialized 
  // and updated by insert_dof(int e, int d, ex dof) 
  
  // (int e, int i) -> ex Li 
  map<pair<int,int>, ex>          loc2dof;   
  // (ex Lj)    -> int j 
  map<ex,int,ex_is_less>          dof2index; 
  // (int j)        -> ex Lj 
  map<int,ex>                     index2dof;  
  // (ex Lj)    -> vector< pair<e1, i1>, ..  pair<en, in> >
  map <ex, vector<pair<int,int> >,ex_is_less >  dof2loc;     

  public: 
  Dof() { counter = 0; }
  ~Dof() {}
  int insert_dof(int e, int j, ex Lj);  // update internal 
                                        // structures  

  // Helper functions to be used when the dofs have been set.   
  // These do not modify the internal structure 
  int glob_dof(int e, int j); 
  int glob_dof(ex Lj); 
  ex  glob_dof(int j); 
  int size();  
  vector<pair<int, int> > glob2loc(int j); 
  void clear(); 
}; 
\end{code}
%% END CODE FROM Dof.h


\noindent 
Here, the function \emp{int insert\_dof(int e, int i, ex Li)}
creates the various mappings between the local dof $L^e_i$, in element $e$, 
and the global dof $L_j$. This is the only function for initializing
the mappings.    
After the mappings have been initialized, they can be used as follows, 
\begin{itemize}
\item \emp{int glob\_dof(int e, int i)} is the mapping $(e,i) \rightarrow j$, 
\item \emp{int glob\_dof(ex Lj)} is the mapping $L_j \rightarrow j$, 
\item \emp{ex glob\_dof(int j)} is the mapping $j \rightarrow L_j$, 
\item \emp{vector<pair<int, int> > glob2loc(int j)} 
is the mapping $j\rightarrow { (e,i(e)) }$. 
\end{itemize}


\noindent
The following code shows how to make two Lagrangian elements, implemented by the
class \emp{LagrangeFE} (The description of \emp{LagrangeFE} is postponed until Section \emp{sec:fem:examples}),
assign their local degrees of freedom to the global set
of degrees of freedom in \emp{Dof}, and print out the 
local degrees of freedom associated with each global degree
of freedom (see also \emp{dof\_ex.cpp}): 
%% BEGIN CODE FROM dof_ex.h
\begin{code}
  Dof dof; 

  Triangle t1(lst(0,0), lst(1,0), lst(0,1)); 
  Triangle t2(lst(1,1), lst(1,0), lst(0,1)); 

  // Create a finite element and corresponding 
  // degrees of freedom on the first triangle
  int order = 2; 
  LagrangeFE fe; 
  fe.set_order(order); 
  fe.set_polygon(t1); 
  fe.compute_basis_functions(); 
  for (int i=0; i< fe.nbf(); i++) {
    cout <<"fe.dof("<<i<<")= "<<fe.dof(i)<<endl;  
    // insert local dof in global set of dofs   
    dof.insert_dof(1,i, fe.dof(i)); 
  }

  // Create a finite element and corresponding 
  // degrees of freedom on the second triangle
  fe.set_polygon(t2); 
  fe.compute_basis_functions(); 
  for (int i=0; i< fe.nbf(); i++) {
    cout <<"fe.dof("<<i<<")= "<<fe.dof(i)<<endl; 
    // insert local dof in global set of dofs   
    dof.insert_dof(2,i, fe.dof(i)); 
  }

  // Print out the global degrees of freedom an their 
  // corresponding local degrees of freedom 
  vector<pair<int,int> > vec; 
  pair<int,int> index; 
  ex exdof; 
  for (int i=1; i<= dof.size(); i++) {
    exdof = dof.glob_dof(i); 
    vec = dof.glob2loc(i);
    cout <<"global dof " <<i<<" dof "<<exdof<<endl; 
    for (int j=0; j<vec.size(); j++) { 
      index = vec[j]; 
      cout <<"  element "<<index.first<<
             " local dof "<<index.second<<endl; 
    }
  }
\end{code}
%% END CODE FROM dof_ex.h

In the previous example, the reader that also runs the companion code
will notice that the degrees of freedom in \emp{LagrangeFE} 
are not linear forms on polynomial spaces, i.e., 
\[
L_i(v) = v(\xx_i) . 
\]
They are instead represented as points, $\xx_i$, which is the usual
way to represent these degrees of freedom in finite element software (because
of their obvious simplicity compared to linear forms on polynomial spaces).    
Hence, the degrees of freedom in \emp{LagrangeFE} are actually
implemented in the standard fashion. However, the tools we have described   
are far more general than conventional finite element codes. 
Still the tools are  equally simple to use, due
to the powerful expression class \emp{ex} in GiNaC.    

Our next example concerns degrees of freedom which are
line integrals over the edges of triangles. 
Let $T$ be a triangle with the edges 
$e_i$, $i\in[1,3]$. The degree of freedom associated with $e_i$ is then simply,  
\[
L_i(v) = \int_{e_i} v \, ds  .
\]
As our next example shows, such degrees of freedom can be implemented
equally easy as the point values shown in the previous example   
(see \emp{dof\_ex2.cpp}):  
%% BEGIN CODE FROM dof_ex2.h
\begin{code}
  Dof dof; 

  // create two triangles
  Triangle t1(lst(0,0), lst(1,0), lst(0,1)); 
  Triangle t2(lst(1,1), lst(1,0), lst(0,1)); 

  // create the polynomial space
  ex Nj = pol(1,2,"a"); 
  cout <<"Nj " <<Nj<<endl; 
  Line line; 
  ex   dofi; 

  // dofs on first triangle
  for (int i=1; i<= 3; i++) {
    line = t1.line(i);         // pick out the i'th line 
    dofi = line.integrate(Nj); // create the dof which is 
                               // a line integral 
    dof.insert_dof(1,i, dofi); // insert local dof in     
                               // global set of dofs 
  }

  // dofs on second triangle
  for (int i=1; i<= 3; i++) {
    line = t2.line(i);         // pick out the i'th line
    dofi = line.integrate(Nj); // create the dof which is 
                               // a line integral 
    dof.insert_dof(2,i, dofi); // insert local dof in 
                               // global set of dofs 
  }
\end{code}
%% END CODE FROM dof_ex2.h


\paragraph{Software Component: Degrees of Freedom Handler Template} 

We will also describe an equally general degree of freedom 
handler which is not based on GiNaC, but which employs templates
instead. This template class relies on two classes, 
the degree of freedom \emp{D} and a comparison function. 
The rest is basically identical to the previously 
described \emp{Dof}, 
except that we have added two boolean variables which can be used to turn
off the computation of the global to local mapping in  
\eqref{dof:glob2loc} and the $j\rightarrow N_j$ mapping.    
This class can be found in the header file \emp{DofT.h}:         
%% BEGIN CODE FROM DofT.h
\begin{code}
template <class D, class C>
class DofT {
  protected: 
  bool create_index2dof, create_dof2loc; 
  int counter; 
  // the structures loc2dof, dof2index, and doc2loc  are 
  // completely dynamic. They are all initialized and 
  // updated by insert_dof(int e, int i, ex Li). 
  
  // (int e, int i) ->  int j  
  map<pair<int,int>, int>          loc2dof;   
  // (ex Lj)    -> int j 
  map<D,int,C>                     dof2index; 
  typename map<D,int,C>:: iterator iter;

  // (int j)        -> ex Lj 
  map<int,D>                     index2dof;  
  // (ex j)    -> vector< pair<e1, i1>, ..  pair<en, in> >
  map <int, vector<pair<int,int> > >  dof2loc;     

  public: 
  DofT(bool create_index2dof_ = false, 
       bool create_dof2loc_   = false) 
  { 
    counter = -1; 
    create_index2dof = create_index2dof_; 
    create_dof2loc   = create_dof2loc; 
  }
  ~DofT() {}
  int insert_dof(int e, int i, D Li);  // update internal 
                                       // structures  

  // Helper functions to be used when the dofs have been set.  
  // These do not modify the internal structure. 
  int glob_dof(int e, int i); 
  int glob_dof(D Lj); 
  D  glob_dof(int j); 
  int size();  
  vector<pair<int, int> > glob2loc(int j); 
  void clear(); 
}; 
\end{code}
%% END CODE FROM DofT.h
The typical way to represent most common degrees of freedom is as  points. 
Hence, we have implemented a simple point class \emp{Ptv} and its comparison
function. The header file (see also \emp{Ptv.h}) is as follows:  
%% BEGIN CODE FROM Ptv.h
\begin{code}
class Ptv {
private: 
  int dim; 
  double* v; 
  static double tol;

public: 
  Ptv(int size_);
  Ptv(int size_, double* v_); 
  Ptv(const Ptv& p);
  Ptv();   

  virtual ~Ptv(); 

  const int size() const; 

  const double& operator [] (int i) const;
  double& operator [] (int i); 
  Ptv& operator = (const Ptv& p);  

  bool is_less(const Ptv& p) const; 

};

struct Ptv_is_less : 
       public std::binary_function<Ptv, Ptv, bool> {
  bool operator() (const Ptv &lh, const Ptv &rh) const { 
    return lh.is_less(rh);  }
};

std::ostream & operator<< ( std::ostream& os, const Ptv& p); 
\end{code}
%% END CODE FROM Ptv.h
The \emp{Ptv} class simply contain an array of doubles with variable
size. The comparison function should check whether a point $x\in \R^n$ is
less than $y \in \R^m$, which is not necessarily obvious how to do.  
For instance, which is the smallest of $x_1 = (1,0) \  \in \  \R^2$,  
$x_2 = (0,1) \ \in \R^2$ and $x_3 = (0,0,1) \ \in \R^3$ ? 
There are many possible ways to compare points. The convention we have
chosen so far is to first check the size of the points.  
Hence, $x<y$, where $x\in\R^n$ and $y\in\R^m$, if $n<m$.     
If $n=m$, then $x<y$ if $x_0<y_0$. 
If $x_0=y_0$, then $x<y$ if $x_1<y_1$ and we continue in this fashion, 
if $x_j=y_j, 0\le j < i$ then $x<y$ if $x_i< y_j$.   
Notice that this comparison operator only affects the ordering of the degrees of
freedom internally in the STL \emp{map} structure. But it
might be that other comparison conventions will speed up the search and insert  
routines in \emp{map}.   

Finally, we remark that the \emp{Ptv} class and \emp{DofT} can be used
also for degrees of freedom associated with lines, edges, faces or general 
polygons. For instance the edge of a 2D triangle, between the points 
$\xx_0 = (x_0, y_0)$ and $ \xx_1 = (x_1, y_1)$ can be represented as a point in $\R^4$, e.g.,
$(x_0, y_0, x_1, y_1)$ if $\xx_0 <  \xx_1$ and    
$(x_1, y_1, x_0, y_0)$ otherwise. Another simpler approach is to represent 
an edge by its midpoint.   

For degrees of freedom that are not well represented as points we have
created the structure \emp{OrderedPtvSet}. This class contains 
a ordered set of points \emp{Ptv}, where the ordering is determined by the 
\emp{Ptv::less} function. 
The class declaraton is as follows (see also \emp{OrderedPtvSet.h}):  
%% BEGIN CODE FROM OrderedPtvSet.h
\begin{code}
class OrderedPtvSet 
{ 
  vector<Ptv> Ptvs; 

  public: 
  OrderedPtvSet();        
  OrderedPtvSet(const Ptv& p0, const Ptv& p1);
  OrderedPtvSet(const Ptv& p0, const Ptv& p1, const Ptv& p2);
  OrderedPtvSet(const Ptv& p0, const Ptv& p1, const Ptv& p2, 
                const Ptv& p3);
  virtual ~OrderedPtvSet(); 

  void append(const Ptv& p); 
  int size() const; 
  const Ptv& operator [] (int i) const;
  Ptv& operator [] (int i); 
  OrderedPtvSet& operator = (const OrderedPtvSet& p);  
  bool less(const OrderedPtvSet& s) const; 
}; 
\end{code}
%% END CODE FROM OrderedPtvSet.h





\section{Some Examples of Finite Elements}
\label{sec:fem:examples}

Earlier in Section \ref{sec:fem:usage}, we described the 
usage of a general finite element. In this section we 
will show how various finite elements are constructed/implemented in SyFi.  

\subsection{Finite Elements in $H^1$ }

\subsubsection{The Lagrangian Element}
\label{Lagrangian:element}

We will describe the construction of a Lagrangian
element on a 2D triangle. The actual implementation
of the element in both 1D, 2D and 3D can be found in 
the class \emp{LagrangeFE}. 

As we saw in Section \ref{sec:pol:space}, 
the polynomial space $\P_n$ in 2D can be written on the form 
\[
N = \sum^{i+j<=n}_{i,j=0} a_{ij} x^i y^j  . 
\]
Hence, to determine the basis functions ${N_k}$ we simply represented them 
in abstract form, 
\[
N_k = \sum^{i+j<=n}_{i,j=0} a^k_{ij} x^i y^j .   
\]
Then the coefficients ${a_{ij}^k}$ are to be determined by the 
$(n+1)(n+2)/2$ degrees of freedom that are the nodal values at the
the points $\xx_i$, i.e.,  
\[
L_i(N_k) = N_k(\xx_i) .  
\]
Hence, we need a set of $(n+1)(n+2)/2$ nodal points to determine
the coefficients ${a^k_{ij}}$ for each basis function. We have
chosen to use the Bezier ordinates.  
When this is done, it is simply a matter of solving the linear system 
\[
L_i(N_k) = N_k(\xx_i) = \delta_{ik},   
\]
for each basis function $N_k$.

\paragraph{Software Component: The Lagrangian Element}

The Lagrangian element is implemented as a subclass of 
\emp{StandardFE}. The class definition is:  
%% BEGIN CODE FROM LagrangeFE.h 
\begin{code}
class LagrangeFE : public StandardFE {
  public: 
  LagrangeFE() {}
  virtual ~LagrangeFE() {}

  virtual void set_order(int order); 
  virtual void set_polygon(Polygon& p);  
  virtual void compute_basis_functions();  
  virtual int nbf(); 
  virtual GiNaC::ex N(int i);  
  virtual GiNaC::ex dof(int i); 
}; 
\end{code}
%% END CODE FROM LagrangeFE.h 



\paragraph{The Construction of the Lagrangian Element}
The Lagrangian element of arbitrary order in 1D, 2D, and 3D, is implemented in \emp{LagrangeFE.cpp}. 
The following code is taken from \emp{fe\_ex3.cpp}. 

%% BEGIN CODE FROM fe_ex3.cpp 
\begin{code}
    Triangle t(lst(0,0), lst(1,0), lst(0,1));  
    int order = 2;                //second order elements 
    ex polynom; 
    lst variables; 

    // the polynomial spaces on the form: 
    // first item,  the polynom:    
    //        a0 + a1*x + a2*y + a3*x^2 + a4*x*y ...     
    // second item, the coefficients: 
    //        a0, a1, a2, ...                           
    // third  item, the basis: 
              1, x, y, x^2       
    // Could also do:
    // GiNaC::ex polynom_space = bernstein(order, t, "a"); 
    ex polynom_space = pol(order, 2, "a"); 
    ex polynom = polynom_space.op(0); 

    // the variables a0,a1,a2 ..
    variables = ex_to<lst>(polynom_space.op(1));
  
    ex Nj; 
    // The Bezier ordinates in which the 
    // basis function should be either 0 or 1
    lst points = bezier_ordinates(t,order); 

    // Loop over all basis functions Nj and all points. 
    // Each basis function Nj is determined 
    // by a set of linear equations: 
    //   Nj(xi) = dirac(i,j) 
    // This system of equations is then solved by lsolve
    for (int j=1; j <= points.nops(); j++) {
      lst equations; 
      int i=0; 
      for (int i=1; i<= points.nops() ; i++ ) { 
        // The point xi 
        ex point = points.op(i-1); 
        // The equation Nj(x) = dirac(i,j)  
        ex eq = polynom == dirac(i,j); 
        // Substitute x = xi and y = yi and 
        // appended the equation to the list of equations 
        // to the list of equations
        equations.append(eq.subs(lst(x == point.op(0) , 
                                     y == point.op(1))));  
      }


      // We solve the linear system 
      ex subs = lsolve(equations, variables); 
      // Substitute to get the Nj 
      Nj = polynom.subs(subs);   
      cout <<"Nj "<<Nj<<endl; 
    }
\end{code}
%% END CODE FROM fe_ex3.cpp 

In this example the degrees of freedom are very 
simple. It is only a matter of evaluating the function
$v_k$ in the point $\xx_i$ (which in GiNaC is performed by substitution).  
Later we will see that more advanced degrees of freedom
are readily available since we have stored the degrees of freedom
as a set of \emp{ex}es. 


\subsubsection{The Crouizex-Raviart Element}
\label{CR:element}

The Crouizex-Raviart element \cite{CR} is the nonconforming equivalent of
linear continuous Lagrangian elements. The degrees of freedom are the values 
at the midpoint of the sides, i.e.,    
\[
L_i(v) = v(x_{m(e_i)}),  
\]
where $x_m(e_i)$ is the midpoint on the edge, $e_i$. 
An equivalent definition  of the degrees of freedom is,  
\[
L_i(v) = \int_{e_i} v \, ds,  
\]
This is the definition we will use. 


\paragraph{Software Component: The Crouzeix-Raviart Element}

The Crouzeix-Raviart class definition is similar to class
defined for the Lagrangian element: 

%% BEGIN CODE FROM CrouzeixRaviart.h 
\begin{code}
class CrouzeixRaviart : public StandardFE {
  public: 
  CrouzeixRaviart(); 
  virtual ~CrouzeixRaviart() {}

  void set_order(int order); 
  void set_polygon(Polygon& p);  
  void compute_basis_functions();  
  virtual int nbf(); 
  virtual GiNaC::ex N(int i);  
  virtual GiNaC::ex dof(int i); 
}; 
\end{code}
%% END CODE FROM CrouzeixRaviart.h 



\paragraph{The Construction of the Crouzeix-Raviart Element}

The following code, which is from the file \emp{CrouzeixRaviart.cpp}, shows
how this element can be defined in 2D. The definition of the element in
3D can also be found in this file. 

%% BEGIN CODE FROM CrouzeixRaviart.cpp 
\begin{code}
    Triangle triangle; 

    // create the polynomial space
    ex polynom_space = bernstein(1, triangle, "a"); 
    ex polynom = polynom_space.op(0); 
    ex variables = polynom_space.op(1); 
    ex basis = polynom_space.op(2); 


    // create the dofs
    int counter = 0; 
    symbol t("t"); 
    for (int i=1; i<= 3; i++) {
      Line line = triangle.line(i); 
      ex dofi = line.integrate(polynom); 
      dofs.insert(dofs.end(),dofi); 
    }

    // solve the linear system to compute 
    // each of the basis functions
    for (int i=1; i<= 3; i++) {
      lst equations; 
      for (int j=1; j<= 3; j++) {
        equations.append(dofs[j-1] == dirac(i,j));
      }
      ex sub = lsolve(equations, variables); 
      ex Ni = polynom.subs(sub); 
      Ns.insert(Ns.end(),Ni); 
    }
\end{code}
%% END CODE FROM CrouzeixRaviart.cpp 


\noindent 
This element can be used in a standard fashion, 
(see also \emp{crouzeixraviart\_ex.cpp}),  
%% BEGIN CODE FROM crouzeixraviart_ex.cpp
\begin{code}
  CrouzeixRaviart fe; 
  fe.set_order(1); 
  fe.set_polygon(p); 
  fe.compute_basis_functions(); 
  for (int i=0; i< fe.nbf(); i++) {
    cout <<"fe.N("<<i<<")="<<fe.N(i)<<endl; 
  }
\end{code}
%% END CODE FROM crouzeixraviart_ex.cpp 
\noindent 
See also the Python implementation of this element in Section \ref{sec:python}.  



\subsection{Finite Elements in $L^2$ }

\subsubsection{The $P_0$ Element}
\label{P0:element}
The $P_0$ element consists of piecewise constants, i.e.,  
\[
v|_T = 1, 
\]
where $T$ is the polygon. This element is discontinuous across elements.  

\paragraph{Software Component: The $P_0$ Element}
The $P_0$ element is implemented in the class \emp{P0}. 
The implementation is straightforward. 

\subsubsection{The Discontinuous Lagrangian Element}
\label{discont:Lagrange:element}
The discontinuous Lagrangian elements are similar to the continuous Lagrangian
elements except for the fact that they are discontinuous.  
Hence, locally on the polygon $T$, the basis functions are the same. 
The difference
is that discontinuous Lagrangian elements are not continuous between elements.   

\begin{figure}
\begin{center}
\caption{Some triangles with the common vertex V.}
\label{fig:discont}
\epsfig{file=figs/discont.xfig.eps,width=5cm}
\end{center}
\end{figure}

To exemplify this we consider the continuous and the discontinuous linear
Lagrangian elements in 2D. In Figure \ref{fig:discont} we see that 
the triangles $1,\ldots,5$ all share the common vertex $V$. For  
continuous Lagrangian elements, this means that there will be only one degree of freedom      
associated with $V$. On the other hand, for discontinuous Lagrangian elements, 
there will be one degree of freedom associated with $V$ per triangle. Hence, in
the concrete case depictured in Figure \ref{fig:discont}, there will be 5 degrees
of freedom associated with $V$. Each degree of freedom is 
associated with a basis function which is $1$ in $V$, $0$ in the other vertices, and zero outside 
the triangle.  


\paragraph{Software Component: The discontinuous Lagrangian element}

The implementation of the discontinuous Lagrangian element is really 
easy because this element is identical to the continuous Lagrangian element locally. 
Hence, the basis functions on each element is the same. We only need to 
modify the degrees of freedom.  

The degrees of freedom for the discontinuous Lagrangian elements
are such that for each element, each degree of freedom is new. 
Hence, none of degrees of freedom are shared among elements. 
It is fairly easy to implement this. Assume that the polygons 
in the mesh or the elements in the finite element space are numbered.    
Then the  degree of freedom can be   
represented by both the vertex $x_i$ and the element number $e$ associated with 
the polygon $T_e$,   
\[
L^e_i(v) = v|_{T_e} (x_i), 
\]
where $v|_{T_e}$ means the restriction of $v$ to the polygon $T_e$.   
It is important to take the restriction to $T_e$ since $v$ is in general
discontinuous in $x_i$.

We have implemented the discontinuous Lagrangian element as a
subclass of the continuous Lagrangian element, with an additional
integer parameter \emp{element} which is the element number.  
The class declaration is as follows, 
%% BEGIN CODE FROM DiscontinuousLagrangeFE.h 
\begin{code}
class DiscontinuousLagrangeFE : public LagrangeFE {
  int element; 
  public: 
  DiscontinuousLagrangeFE(); 
  ~DiscontinuousLagrangeFE() {}

  virtual void set_order(int order); 
  virtual void set_element_number(int element); 
  virtual void set_polygon(Polygon& p);  
  virtual void compute_basis_functions();  
  virtual int nbf(); 
  virtual GiNaC::ex N(int i);  
  virtual GiNaC::ex dof(int i); 
}; 
\end{code}
%% END CODE FROM DiscontinuousLagrangeFE.h 
Earlier, the degrees of freedom for continuous Lagrangian elements were represented
as vertices or points (instead of linear forms), 
as is usual in finite element codes. We do the same simplification
here, and store the degrees of freedom as $(x_i, e)$, where $x_i$ is the vertex/point 
and $e$ is the element number associated with $T_e$.  
This is implemented in the functions \emp{compute\_basis\_functions}: 
%% BEGIN CODE FROM DiscontinuousLagrangeFE.cpp 
\begin{code}
void DiscontinuousLagrangeFE:: compute_basis_functions() { 
  LagrangeFE:: compute_basis_functions(); 
  for (int i=0; i< dofs.size(); i++) { 
    dofs[i] = lst(dofs[i], element); 
  }
}
\end{code}
%% END CODE FROM DiscontinuousLagrangeFE.cpp 
\noindent
The usage is standard (see \emp{disconlagrange\_ex.cpp}), 
%% BEGIN CODE FROM disconlagrange_ex.cpp 
\begin{code}
  Dof dof; 
  // create two triangles
  Triangle t1(lst(0,0), lst(1,0), lst(0,1)); 
  Triangle t2(lst(1,1), lst(1,0), lst(0,1)); 

  int order = 2; 

  DiscontinuousLagrangeFE fe; 
  fe.set_order(order); 
  fe.set_polygon(t1); 
  fe.set_element_number(1); 
  fe.compute_basis_functions(); 
  usage(fe); 
  for (int i=0; i< fe.nbf(); i++) {
    dof.insert_dof(1,i,fe.dof(i)); 
  }

  fe.set_polygon(t2); 
  fe.set_element_number(2); 
  fe.compute_basis_functions(); 
  usage(fe); 
  for (int i=0; i< fe.nbf(); i++) {
    dof.insert_dof(2,i,fe.dof(i)); 
  }

  // Print out the global degrees of freedom an their 
  // corresponding local degrees of freedom 
  vector<pair<int,int> > vec; 
  pair<int,int> index; 
  ex exdof; 
  for (int i=1; i<= dof.size(); i++) {
    exdof = dof.glob_dof(i); 
    vec = dof.glob2loc(i);
    cout <<"global dof " <<i<<" dof "<<exdof<<endl; 
    for (int j=0; j<vec.size(); j++) { 
      index = vec[j]; 
      cout <<"  element "<<index.first<<
             " local dof "<<index.second<<endl; 
    }
  }
\end{code}
%% END CODE FROM disconlagrange_ex.h 

\noindent
When this program (\emp{disconlagrange}) runs, it prints out
12 degrees of freedom in contrast to 9 which it would 
be for continuous Lagrangian elements.   



\subsection{Finite Elements in $\mathbf{H}(div)$ }
%\subsection{Finite Elements in $\Hdiv$ }
\subsubsection{The Raviart-Thomas Element}
\label{sec:fem:rt}
The family of Raviart-Thomas elements \cite{RT} is popular when considering the 
mixed formulation of elliptic problems.    
In this case the polynomial space is not $\P_n^d$,  but 
\begin{equation} 
\label{pol:space:rt}
\P_n^d + \xx \P_n . 
\end{equation}
And the degrees of freedom are, 
\begin{eqnarray}
\label{dof:rt:1}
\int_{e_i} \vv\cdot \nn \, p_k \, ds, &&\forall p_k \in \P_k(e_i), \\   
\label{dof:rt:2}
\int_{T} \vv\cdot \pp_{k-1} \, dx, && \forall p_{k-1} \in \P^d_{k-1}(T),     
\end{eqnarray}
where $T$ is the polygon domain and $e_i$ is its edges (in 2D) or faces (in 3D). 
Degrees of freedom which are integrals have been dealt with already for the
Crouizex-Raviart element in Section \ref{CR:element}. 
Hence, there are mainly two new concepts we need to deal with to implement
this element. It is the polynomial space, which is on the form \eqref{pol:space:rt}, 
and the polynomial spaces on faces or edges of the polygon, as in  
\eqref{dof:rt:1}. Both concepts will be dealt with below.    

\paragraph{Software Component: The Raviart-Thomas Element} 

Notice that for the previously defined Lagrangian and Crouizex-Raviart
elements, the basis functions were scalar functions.  
The basis functions of the Raviart-Thomas elements are vector functions, 
but still, thanks to the general \emp{ex} class, the 
Raviart-Thomas element class can be defined in the same way
as earlier. The class definition is:   

%% BEGIN CODE FROM RaviartThomas.h 
\begin{code}
class RaviartThomas : public StandardFE {
  public: 
  RaviartThomas() {}
  virtual ~RaviartThomas() {}

  virtual void set_order(int order); 
  virtual void set_polygon(Polygon& p);  
  virtual void compute_basis_functions();  
  virtual int nbf(); 
  virtual GiNaC::ex N(int i);  
  virtual GiNaC::ex dof(int i); 
}; 
\end{code}
%% END CODE FROM RaviartThomas.h 



\paragraph{The Construction of the Raviart-Thomas Element} 
First, we described how to make the polynomial space \eqref{pol:space:rt}.  
The polynomial spaces, $\P_n(T)$ and $\P^d_n(T)$ on a polygonal domain, 
can be made by the functions
\emp{bernstein} and \emp{bernsteinv}, respectively. However, we can not 
just add the spaces $\P_n^d(T)$ and $\xx \P_n(T)$ together. Because, some
of the basis functions are the same in both space, while others are not.   
Consider for instance $\P_1^d(T)$, which has the basis functions,\\    
$${ (0,1)^T, (1,0)^T, (x,0)^T, (0,x)^T, (y,0)^T, (0,y)^T}$$ while  
$\xx \P_1(K)$ has the following basis functions \\ 
$${  (x,0)^T, (x^2,0)^T, (xy)^T, (0,y)^T, (0,y^2)^T, (0,xy)^T}.$$ 
Hence $(x,0)^T$ and $(0,y)^T$ are common. 

The way we solve this problem is that we create the two spaces
$\P_n^d(T)$ and $\xx \P_n(T)$ independently.  We then 
have two polynomial spaces, each with two independent sets of 
variables (or degrees of freedom). The variables associated with 
a basis in  $\xx \P_n(T)$ which is also a basis in  $\P_n^d(T)$ 
is then removed. This is done by removing all variables associated with basis
functions that have degree less than $n-1$ in $\P_n$ from  $\xx \P_n(T)$. 
This is done as follows in 2D (both 2D and 3D elements of arbitrary order are 
implemented in \emp{RaviartThomas.cpp}),  
%% BEGIN CODE FROM RaviartThomas.cpp
\begin{code}
    Triangle& triangle = (Triangle&)(*p); 
    lst equations; 
    lst variables; 
    ex polynom_space1 = bernstein(order-1, triangle, "a"); 
    ex polynom1 = polynom_space1.op(0); 
    ex polynom1_vars = polynom_space1.op(1); 
    ex polynom1_basis = polynom_space1.op(2); 

    lst polynom_space2 = bernsteinv(order-1, triangle, "b"); 
    ex polynom2 = polynom_space2.op(0).op(0); 
    ex polynom3 = polynom_space2.op(0).op(1); 


    lst pspace = lst( polynom2 + polynom1*x, 
                      polynom3 + polynom1*y);   

    // remove multiple dofs 
    if ( order >= 2) {
      ex expanded_pol = expand(polynom1);
      for (int c1=0; c1<= order-2;c1++) { 
        for (int c2=0; c2<= order-2;c2++) { 
          for (int c3=0; c3<= order-2;c3++) {
            if ( c1 + c2 + c3 <= order -2 ) {
              ex eq =  expanded_pol.coeff(x,c1)
                                   .coeff(y,c2).coeff(z,c3);  
              if ( eq != numeric(0) ) { 
                equations.append(eq == 0); 
              }
            }
          }
        }
      }
    }
\end{code}
%% END CODE FROM RaviartThomas.cpp 
Second, we described how to implement the degrees of freedom \eqref{dof:rt:1}-\eqref{dof:rt:2}. 
The degrees of freedom associated with the edges,  
\[
\int_{e_i} \vv\cdot \nn \, p_k \, ds, \forall p_k \in \P_k(e_i), \\   
\]
are implemented as follows (Notice that the polynomial space 
on the edges of the triangle is made by creating
Bernstein polynomials in standard fashion). 
%% BEGIN CODE FROM RaviartThomas.cpp
\begin{code}
    ex bernstein_pol; 

    int counter = 0; 
    symbol t("t"); 
    ex dofi; 
    // loop over all edges  
    for (int i=1; i<= 3; i++) {
      Line line = triangle.line(i); 
      lst normal_vec = normal(triangle, i); 
      bernstein_pol = bernstein(order-1, line, istr("a",i));
      ex basis_space = bernstein_pol.op(2); 
      ex pspace_n = inner(pspace, normal_vec);  

      // loop over all basis functions on current edge 
      ex basis; 
      for (int i=0; i< basis_space.nops(); i++) {
        counter++; 
        basis = basis_space.op(i); 
        ex integrand = pspace_n*basis; 
        dofi =  line.integrate(integrand);  
        dofs.insert(dofs.end(), dofi); 
        ex eq = dofi == numeric(0); 
        equations.append(eq); 
      }
    }
\end{code}
%% END CODE FROM RaviartThomas.cpp 
The degrees of freedom associated with the whole triangle, 
\[
\int_{T} \vv\cdot \pp_{k-1} \, dx,  \forall p_{k-1} \in \P^d_{k-1}(T),     
\]
is implemented as 
%% BEGIN CODE FROM RaviartThomas.cpp
\begin{code}
    // dofs related to the whole triangle
    lst bernstein_polv; 
    if ( order > 1) {
      counter++; 
      bernstein_polv = bernsteinv(order-2, triangle, "a");
      ex basis_space = bernstein_polv.op(2); 
      for (int i=0; i< basis_space.nops(); i++) {
        lst basis = ex_to<lst>(basis_space.op(i)); 
        ex integrand = inner(pspace, basis);  
        dofi = triangle.integrate(integrand);  
        dofs.insert(dofs.end(), dofi); 
        ex eq = dofi == numeric(0); 
        equations.append(eq); 
      }
    }
\end{code}
%% END CODE FROM RaviartThomas.cpp 
\noindent
In the above code we have formed the linear system,  
\[
L_i(v) = 0 
\]
To compute the different $v_j$ we then produce
different right hand sides corresponding to $\delta_{ij}$  
and solve the system.  
How this is done can be seen in the \emp{RaviartThomas.cpp}. 







\subsubsection{The Nedelec element of second kind}
\label{sec:nedelec:2nd}

The Nedelec $\Hdiv$ element introduced in \cite{Nedelec:1986:NFM}, is very similar to the
Raviart-Thomas element, except that the polynomial space is    
$\P_n^d$  instead of $\P_n^d + \xx \P_n$. Hence, it is the $\R^3$ analog of the Brezzi-Douglas-Marini element \cite{Brezzi:1985:TFM}. 
The degrees of freedom in the Nedelec $\Hdiv$ element are,  
\begin{eqnarray*}
\int_f (\pp \cdot \nn) ds, \quad \forall q\in \P_k(f), \\   
\int_K (\pp \cdot \qq) dx, \quad \forall \qq \in \R_{k-1}. 
\end{eqnarray*}
Here 
\begin{eqnarray*}
\R_k &=& (\P_{k-1}^3) \oplus \S^k, \\   
\S^k &=& \{ \pp \in \H_k^3 | \ (\rr\cdot\pp) = 0 \},   
\end{eqnarray*}
where $\rr = (x,y,z)$. 

\paragraph{Software Component: The Nedelec $\Hdiv$ Element} 

The Nedelec $\Hdiv$ element class definition is similar to the previous
element definitions.  

%% BEGIN CODE FROM Nedelec2Hdiv.h 
\begin{code}
class Nedelec2Hdiv : public StandardFE {
  public: 
  Nedelec2Hdiv() {}
  virtual ~Nedelec2Hdiv() {}

  virtual void set_order(int order); 
  virtual void set_polygon(Polygon& p);  
  virtual void compute_basis_functions();  
  virtual int nbf(); 
  virtual GiNaC::ex N(int i);  
  virtual GiNaC::ex dof(int i); 
}; 
\end{code}
%% END CODE FROM Nedelec2Hdiv.h 


\paragraph{The Construction of the Nedelec $\Hdiv$ Element} 

The construction of this element is very similar to the construction
of the Raviart--Thomas element. We will therefore not discuss this here.  


\subsection{Finite Elements in $H(div,\mathbb{M})$ }
\label{sec:afw:hdiv}

The Arnold, Falk and Winther element~\cite{AFWweak3D} for mixed elasticity problems  
in 3D with weak symmetry, has recently been added to SyFi.   
This element consists of basis functions which take values in $\mathbb{M}$, 
which is the space of $3 \times 3$ matrices. 
Each row is either a null row or the Nedelec $H(div)$ element of 
second kind as described in Section \ref{sec:nedelec:2nd}.  
The implementation is straightforward, since it is essentially a loop where each 
row is created as the basis functions a Nedelec  element. 
We therefore do not comment the implementation details here. 
The finite element is defined in \emp{ArnoldFalkWintherWeakSym.h}.


\subsection{A Finite Element in Both $\mathbf{H}(div)$ and $H^1$}


In \cite{robust} an element for both Darcy and Stokes types of flow
was introduced. The element is defined as:  
\[
\VV(T) = \{ \vv \in \P^2_3 \  : \  \div \vv \in \P_0, \ (\vv\cdot\nn_e) |_e  \in \P_1 \  \forall e \in E(T) \},    
\]
where $T$ is a given triangle,  $E(T)$ is the edges of $T$, $\nn_e$ is the 
normal vector on edge $e$, and $\P_k$ is the space of polynomials of degree $k$ and $\P_k^d$ the corresponding vector space. 
The degrees of freedom are, 
\begin{align*}
&\int_e (\vv\cdot \nn) \tau^k \, d\tau, \quad k=0,1,  &\forall e \in E(T), \\
&\int_e (\vv\cdot \tt) \, d\tau,  &\forall e \in E(T).
\end{align*}
This element is implemented as follows
(see also the PARA06 proceeding \emp{../para06/proceeding/para\_proceeding.pdf}). 
First we create the polynomial space, which 
consist of cubic vector functions,  $\P^2_3$ 

%% BEGIN CODE FROM Robust.cpp 
\begin{code}
      Triangle triangle 
      ex V_space = bernsteinv(2, 3, triangle, "a"); 
      ex V_polynomial = V_space.op(0); 
      ex V_variables = V_space.op(1); 
\end{code}
Here \emp{V\_space} is the above mentioned list, \emp{V\_polynomial} contains the polynomial, 
and \emp{V\_variables} contains the variables.   


In the second step we first 
specify the constraint $\div \vv \in \P_0$:
%% BEGIN CODE FROM Robust.cpp 
\begin{code}
      lst equations; 
      ex divV = div(V); 
      ex_ex_map b2c = pol2basisandcoeff(divV);   
      ex_ex_it iter; 
      // div constraints:  
      for (iter = b2c.begin(); iter != b2c.end(); iter++) {   
          ex basis = (*iter).first;  
          ex coeff= (*iter).second;  
          if ( coeff != 0 && ( basis.degree(x) > 0 
       || basis.degree(y)  > 0 )  ) { 
              equations.append( coeff == 0 ); 
          }
      }
\end{code}
Here, the divergence is computed with the \emp{div} function. The divergence of a function in $\P^2_3$ is in $\P_2$. Hence, it is on the form $b_0 + b_1 x + b_2 y + b_3 x y + b_4 x^2 + b_5 y^2$. In the above code we find the coefficients $b_i$, as expressions involving the above mentioned variables $a_i$ and the corresponding polynomial basis, with the function \emp{pol2basisandcoeff}. 
Then we ensure that the only coefficient which is not zero is $b_0$.  

The next constraints $(\vv\cdot\nn_e) |_e  \in \P_1$ are implemented in much of the same
way as the divergence constraint. We create a loop over each edge $e$  
of the triangle and multiply $\vv$ with the normal $\nn_e$. 
Then we substitute the expression  for the edge, i.e., in mathematical notation $|_e$, 
into $\vv\cdot\nn$.  
After substituting  the expression for these lines to get  
$(\vv\cdot\nn_e) |_e$  , we check that the remaining
polynomial is in $\P_1$ in the same way as we did above. 





%% BEGIN CODE FROM Robust.cpp 
\begin{code}
      // constraints on edges: 
      for (int i=1; i<= 3; i++) {
          Line line = triangle.line(i); 
          symbol s("s"); 
          lst normal_vec = normal(triangle, i); 
          ex Vn = inner(V, normal_vec);   
          Vn = Vn.subs(line.repr(s).op(0))
                       .subs(line.repr(s).op(1));
          b2c = pol2basisandcoeff(Vn,s); 
          for (iter = b2c.begin(); iter != b2c.end(); iter++){   
              ex basis = (*iter).first;  
              ex coeff= (*iter).second;  
              if ( coeff != 0 &&  basis.degree(s) > 1 )  
              { 
                  equations.append( coeff == 0 ); 
              }
          }
      }
\end{code}

In the third step we specify the degrees of freedom. 
First, we specify the equations coming from  
$\int_e (\vv\cdot \nn) \tau^k, k=0,1$ on all edges. To do this we need   
to create a loop over all edges, and on each edge we create the space of linear
Bernstein polynomials in barycentric coordinates on $e$, i.e.,  $\P_1(e)$. 
Then we create a loop
over the basis functions $\tau^k$ in $\P_1(e)$ and compute the integral 
$\int_e (\vv\cdot \nn) \tau^k \, d\tau $. 
 
%% BEGIN CODE FROM Robust.cpp 
\begin{code}
      // dofs related to the normal on the edges  
      for (int i=1; i<= 3; i++) {
          Line line = triangle.line(i); 
          lst normal_vec = normal(triangle, i); 
          ex P1_space = bernstein(1, line, istr("a",i));
          ex P1 = P1_space.op(2); 
          ex Vn = inner(V, normal_vec);  

          ex basis; 
          for (int j=0; j< P1.nops(); j++) {
              basis = P1.op(j); 
              ex integrand = Vn*basis; 
              ex dofi =  line.integrate(integrand);  
              dofs.insert(dofs.end(), lst(line.vertex(0), 
                                          line.vertex(1), j)); 
              ex eq = dofi == numeric(0); 
              equations.append(eq); 

          }
      }
\end{code}
Finally, the degrees of freedom  $\int_e (\vv\cdot \tt) d\tau $, can be implemented 
in basically the same fashion as the previously described degrees of freedom
To summarize, we have now specified 20 equations which is precisely the number of 
unknowns in  $\P^2_3$. Hence, the space $\VV(T)$ is uniquely defined, what remains
is simply to solve a linear system with 20 equations and 20 unknowns. 
The complete source code is in \emp{Robust.cpp}.





\subsection{Finite Elements in $\mathbf{H}(curl)$ }

\subsubsection{The Nedelec Element}

In electromagnetic applications, \cite{Nedelec:1980:MFE} the family of Nedelec elements are 
very common. As was also the case with the Raviart-Thomas elements, $\P^n$   
is not the most convenient space to define the basis functions.   
Instead, we will use
\begin{equation} 
\label{nedlec:pol:space}
\P_{n-1}^d + \hat{\H}^k, 
\end{equation}
where
\[
\hat{\H}^k = { \hh \in \H_k^d : \hh \cdot \xx = 0 }   
\]
and $\H$ is the space of homogenous polynomials described in Section \ref{sec:homo:pol}. 
The degrees of freedom that defines the Nedelec elements are (in 2D), 
\begin{eqnarray}
\label{nedelec:dof:1}
\int_e \tt \cdot \uu p \, dx, \quad \forall p\in\P_{k-1}(e),  \\ 
\label{nedelec:dof:2}
\int_T \ \uu \cdot \pp \, dx, \quad \forall \pp\in\P^n_{k-2}(T).    
\end{eqnarray}



\paragraph{Software Component: The Nedelec Element}

The Nedelec element class definition is similar to the previous
element definitions.  

%% BEGIN CODE FROM Nedelec.h 
\begin{code}
class Nedelec : public StandardFE {
  public: 
  Nedelec() {}
  virtual ~Nedelec() {}

  virtual void set_order(int order); 
  virtual void set_polygon(Polygon& p);  
  virtual void compute_basis_functions();  
  virtual int nbf(); 
  virtual GiNaC::ex N(int i);  
  virtual GiNaC::ex dof(int i); 
}; 
\end{code}
%% END CODE FROM Nedelec.h 




\paragraph{The Construction of the  Nedelec Element}

The Nedelec element of arbitrary order in both 2D and 3D is
implemented in \emp{Nedelec.cpp}. Here we will for simplicity describe
how the element is implemented in 2D. 

We first consider the polynomial space \eqref{nedlec:pol:space},  
%% BEGIN CODE FROM Nedelec.h 
\begin{code}
    // create r
    GiNaC::ex R_k = homogenous_polv(2,k+1, 2, "a"); 
    GiNaC::ex R_k_x = R_k.op(0).op(0); 
    GiNaC::ex R_k_y = R_k.op(0).op(1); 


    // Equations that make sure that r*x = 0
    GiNaC::ex rx = (R_k_x*x + R_k_y*y).expand(); 
    ex_ex_map pol_map = pol2basisandcoeff(rx); 
    ex_ex_it iter; 
    for (iter = pol_map.begin(); 
         iter != pol_map.end(); iter++) { 
      if ((*iter).second != 0 ) { 
        equations.append((*iter).second == 0 ); 
        removed_dofs++; 
      }
    }
\end{code}
%% END CODE FROM Nedelec.h 

The degree of freedom associated with the edges \eqref{nedelec:dof:1} are implemented as,  
%% BEGIN CODE FROM Nedelec.h 
\begin{code}


    GiNaC::ex dofi; 
    // dofs related to edges  
    for (int i=1; i<= 3; i++) {
      Line line = triangle.line(i); 
      GiNaC::lst tangent_vec = tangent(triangle, i); 
      GiNaC::ex bernstein_pol = bernstein(order, line, 
                                          istr("a",i));
      GiNaC::ex basis_space = bernstein_pol.op(2); 
      GiNaC::ex pspace_t = inner(pspace, tangent_vec);  

      GiNaC::ex basis; 
      for (int j=0; j< basis_space.nops(); j++) {
        counter++; 
        basis = basis_space.op(j); 
        GiNaC::ex integrand = pspace_t*basis; 
        dofi =  line.integrate(integrand);  
        dofs.insert(dofs.end(), dofi); 
        GiNaC::ex eq = dofi == GiNaC::numeric(0); 
        equations.append(eq); 
      }
    }
\end{code}
%% END CODE FROM Nedelec.h 

The degree of freedom associated with whole triangle \eqref{nedelec:dof:2} are implemented as,  
%% BEGIN CODE FROM Nedelec.h 
\begin{code}
    // dofs related to the whole triangle
    GiNaC::lst bernstein_polv; 
    if ( order > 0) {
      counter++; 
      bernstein_polv = bernsteinv(2,order-1, triangle, "a");
      GiNaC::ex basis_space = bernstein_polv.op(2); 
      for (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);  
        dofs.insert(dofs.end(), dofi); 
        GiNaC::ex eq = dofi == GiNaC::numeric(0); 
        equations.append(eq); 
      }
    }
\end{code}
%% END CODE FROM Nedelec.h 


















\section{Mixed Finite Elements}

Mixed finite element methods typically refer to discretization methods for systems 
of PDEs where different finite elements are used for the different unknowns.  
For instance, in incompressible flow problems, one
typically has (at least) two unknowns, the velocity $\vv$ and the 
pressure $p$. 
It is wellknown that the velocity elements should have higher order than the
pressure elements. 
The reasons for this have been extensively studied  the last 30 years, and we will 
not go into details on this here, see e.g., Brezzi and Fortin \cite{BrezziFortin} 
and Girault and Raviart\cite{GiraultRaviart}.   

What we will do here is to describe mixed finite elements from the 
programmers point of view. In this setting, we simply refer to mixed
elements as a  collection of finite elements of different types on the same polygon.  The elements themselves and their implementation were 
discussed in the previous section.  




\subsection{The Taylor--Hood and the $\P^d_n-\P_{n-2}$ Elements }

The Taylor--Hood and the $\P^d_n-\P_{n-2}$ elements are mixed elements that
are popular for incompressible flow. The elements for both the velocity
and the pressure are of Lagrangian type, but have different order. 
The Taylor--Hood element on a polygon $T$ is, 
\[
\vv(T) \in \P^d_2 \quad \text{and} \quad p(T)\in \P_1 .     
\]
The $\P_n-\P_{n-2}$ element on a polygon $T$ is, 
\[
\vv(T) \in \P^d_n \quad \text{and} \quad p(T)\in \P_{n-2}, \quad n\ge 2.     
\]
For $n>2$ the pressure element is of Lagrangian type, while for n=2 
the pressure element is piecewise constant. 
These elements satisfy the Babuska-Brezzi condition. 

The Taylor--Hood elements can be created as follows, (see also \emp{taylorhood\_ex.cpp}) 
%% BEGIN CODE FROM taylorhood.h 
\begin{code}
  VectorLagrangeFE v_fe;
  v_fe.set_order(2);
  v_fe.set_size(2); 
  v_fe.set_polygon(domain);
  v_fe.compute_basis_functions();

  LagrangeFE p_fe;
  p_fe.set_order(1);
  p_fe.set_polygon(domain);
  p_fe.compute_basis_functions();
\end{code}
%% END CODE FROM taylorhood.h 
The $\P_n^d-\P_{n-2}$ element can be made by changing the order of the elements  with 
the \emp{set} function. 





\subsection{The Mixed Crouizex-Raviart Element}
The mixed Crouizex-Raviart element is a nonconforming linear element
for the velocity and piecewise constant for the pressure. The 
Crouizex-Raviart element was described in Section \ref{CR:element}, 
while the $P_0$ element was described in Section \ref{P0:element}.  

These elements can be made as follows (see also \emp{crouzeixraviart\_ex2.cpp})
%% BEGIN CODE FROM crouzeixraviart_ex2.cpp 
\begin{code}

  ReferenceTriangle domain; 

  VectorCrouzeixRaviart v_fe;
  v_fe.set_size(2); 
  v_fe.set_polygon(domain);
  v_fe.compute_basis_functions();

  P0 p_fe;
  p_fe.set_polygon(domain);
  p_fe.compute_basis_functions();
\end{code}
%% END CODE FROM crouzeixraviart_ex2.cpp 






\subsection{The Mixed Raviart-Thomas Element}


The velocity element is the Raviart-Thomas element described in Section 
\ref{sec:fem:rt}.  
The pressure element is discontinuous polynomials of degree $n$. 
The $\P_0$ element is described in Section \ref{P0:element}, while
the discontinuous $\P_n$ element is described in Section \ref{discont:Lagrange:element}. 

The can be made as such (see also \emp{raviartthomas\_ex2}): 
%% BEGIN CODE FROM raviartthomas_ex2.cpp 
\begin{code}
  int order = 3; 

  ReferenceTriangle triangle("t"); 
  RaviartThomas vfe; 
  vfe.set_polygon(triangle); 
  vfe.set_order(order); 
  vfe.compute_basis_functions(); 

  DiscontinuousLagrangeFE pfe; 
  pfe.set_polygon(triangle); 
  pfe.set_order(order); 
  pfe.compute_basis_functions(); 

  for (int i=0; i< vfe.nbf(); i++) 
    cout <<"vfe.N("<<i<<")="<<vfe.N(i)<<endl; 

  for (int i=0; i< pfe.nbf(); i++) 
    cout <<"pfe.N("<<i<<")="<<pfe.N(i)<<endl; 
\end{code}
%% END CODE FROM raviartthomas_ex2.cpp 











\subsection{The Mixed Arnold-Falk-Winther element}

The mixed method of Arnold, Falk and Winther~\cite{AFWweak3D} for mixed 
elasticity problems in 3D, with weakly imposed symmetry 
consists of three different elements 
$\sigma_h\in H(div, \mathbb{M})$, $\uu_h \in L^2(\mathbb{V})$, $\pp_h \in L^2(\mathbb{K})$, 
 where $\mathbb{M}$ is the space of  $3\times 3$ matrices,  
       $\mathbb{V}$ is the space of  vectors in $\mathbb{R}^3$, and 
       $\mathbb{K}$ is the space of  $3\times 3$ skew symmetric matrices.  
The $\sigma_h$ element, described in Section \ref{sec:afw:hdiv}, 
is implemented as \emp{ArnoldFalkWintherWeakSymSigma}. 
The $\uu_h$ element is a discontinuous Galerkin vector element implemented as \emp{ArnoldFalkWintherWeakSymU}.  
Finally, the $\pp_h$ element is a discontinuous Galerkin skew symmetric matrix element implemented as \emp{ArnoldFalkWintherWeakSymP}. The implementation of both \emp{ArnoldFalkWintherWeakSymU} and \emp{ArnoldFalkWintherWeakSymP} 
is straightforward since the code is essentially a wrap around the discontinuous Lagrangian element described in 
Section \ref{discont:Lagrange:element} and we will not comment on the implementation details.  
The code can is in \emp{ArnoldFalkWintherWeakSym.cpp}.


\section{Computing Element Matrices} 
Our next task is to compute element matrices. 
As earlier, everything will be done symbolically.  
There are several reasons for doing the computations 
symbolically:
\begin{itemize}
\item Everything is exact (No floating point precision issues)!   
\item Differentiation of the weak form with respect to the variables is
      possible (Easy to compute the Jacobian for nonlinear PDEs).   
\item In case one uses integers and rational numbers as input (e.g., the
      vertices of the polygon) one gets rational numbers as output.   
      This enables nice output.  
\item In case one uses symbols as input, one get symbols as output. 
      Hence, one might actually compute an abstract element matrix, 
      where each entry in the matrix is a function of the vertices 
      of the polygon, $\xx_0, \xx_1,\ldots, \xx_n$, which are symbols.      
      We will consider this in more detail later. 
\item Every step can be checked against analytic computations. We can 
      even, as we will see, produce output in \LaTeX\ format, for easy reading.  
\item In Section \ref{sec:code:gen} we generate C++ code from the exactly
      computed element matrices.  
\end{itemize}


\subsection{A Poisson Problem}
The Poisson problem is on the form, 
\begin{eqnarray*}
-\Delta    u &=& f,  \quad \text{ in } \Omega, \\ 
           u &=& h, \quad \text{ on } \partial \Omega_E, \\ 
\frac{\partial u}{\partial n} &=& g, \quad \text{ on } \partial \Omega_N,   
\end{eqnarray*} 
where $\partial \Omega = \partial\Omega_E \cup \partial\Omega_N$. 

The weak form of the Poisson problem is (as we have already used):  
Find $u\in V_h$ such that   
\[
a(u,v) = b(v), \quad \forall v\in V_0 .  
\]
where, 
\begin{eqnarray*}
a(u,v) &=& \int_\Omega \nabla u \cdot \nabla v \,  dx, \\    
f(v)   &=& \int_\Omega f \, v \, dx  + \int_{\Gamma_N} g \, v \, ds .    
\end{eqnarray*}
and $V_k={ v \in H^1 ; v|_{\partial\Omega_E} = k }$, for $k=0,h$. 

From this weak form we obtain the element matrix, see e.g.,  
Brenner and Scott \cite{BrennerScott}, Ciarlet \cite{Ciarlet}, or Langtangen \cite{HPLBook},
\begin{equation}
\label{poisson:element:matrix}
A_{ij} = a(N_i, N_j) =  \int_T \nabla N_j \cdot \nabla N_i \, dx .   
\end{equation}
The computation of \eqref{poisson:element:matrix} is implemented in the function \emp{compute\_Poisson\_element\_matrix}
in  
\emp{ElementComputations.cpp}, 
%% BEGIN CODE FROM ElementComputations.h
\begin{code}
void compute_Poisson_element_matrix(
  FE& fe, 
  Dof& dof, 
  std::map<std::pair<int,int>, ex>& A)
{
  std::pair<int,int> index; 

   // Insert the local degrees of freedom into the global Dof
  for (int i=0; i< fe.nbf(); i++) {
    dof.insert_dof(1,i,fe.dof(i)); 
  }

  Polygon& domain = fe.get_polygon(); 

  // The term (grad u, grad v)  
  for (int i=0; i< fe.nbf(); i++) {
    index.first = dof.glob_dof(fe.dof(i));   // fetch the i'th 
                                             // global dof 
    for (int j=0; j< fe.nbf(); j++) {
      index.second = dof.glob_dof(fe.dof(j));// fetch the j'th 
                                             // global dof
      ex nabla = inner(grad(fe.N(i)),        // compute the 
                       grad(fe.N(j)));       // integrand 
      ex Aij = domain.integrate(nabla);    // compute integral  
      A[index] += Aij;                     // add to matrix 
    }
  }
}
\end{code}
%% END CODE FROM ElementComputations.h
\noindent
Notice that in this example, both the degrees of freedom \emp{dof} and the 
matrix \emp{A} are global. 

This function can be used as follows (see \emp{fe\_ex4.cpp}), 
%% BEGIN CODE FROM fe_ex4.h 
\begin{code}
  //matrix in terms of rational numbers 
  int order = 1; 
  Triangle triangle(lst(0,0), lst(1,0), lst(0,1));   
  LagrangeFE fe; 
  fe.set_order(order); 
  fe.set_polygon(triangle); 
  fe.compute_basis_functions(); 

  Dof dof; 
  std::map<std::pair<int,int>, ex> A; 
  compute_Poisson_element_matrix(fe, dof, A); 
\end{code}
%% END CODE FROM fe_ex4.h 
In the above example, the vertices were integers, therefore the entries in 
the matrix will be rational numbers. 
In the following example the vertices are symbols. 
%% BEGIN CODE FROM fe_ex4.h 
\begin{code}
  //matrix in terms of symbols 
  symbol x0("x0"), x1("x1"), x2("x2");  
  symbol y0("y0"), y1("y1"), y2("y2");  
  Triangle triangle2(lst(x0,y0), lst(x1,y1), lst(x2,y2));   

  LagrangeFE fe2; 
  fe2.set_order(order); 
  fe2.set_polygon(triangle2); 
  fe2.compute_basis_functions(); 

  Dof dof2; 
  std::map<std::pair<int,int>, ex> A2; 
  compute_Poisson_element_matrix(fe2, dof2, A2); 
\end{code}
%% END CODE FROM fe_ex4.h 
\noindent
In this case \emp{A2} will contain expressions involving the 
vertices, $(x_0, y_0)$,  $(x_1, y_1)$,  $(x_2, y_2)$ (we used a triangle above). 

The GiNaC
library supports many different ways to print out the output.     
In the example below, we turn on \LaTeX\ output with the 
command \emp{cout <<latex;} before we print out \emp{A2}.  
%% BEGIN CODE FROM fe_ex4.h 
\begin{code}
  cout <<"LaTeX format on output "<<endl; 
  cout <<latex; 
  print(A2); 
\end{code}
%% END CODE FROM fe_ex4.h 

\label{ginac:output:format}
\noindent
This gives the following expression (compiled by latex) for $A[1,1]$ (code for 
the other entries are also produced, but these are not shown here). 
%% BEGIN OUTPUT GENERATED WITH fe_ex4
\begin{eqnarray*}
A[1,1]=\frac{1}{2} \frac{ x_0^{2} {| {(-x_0+x_1)} {(y_2-y_0)}- {(-x_0+x_2)} {(y_1-y_0)}|}}{{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}} \\
-\frac{ y_1 y_0 {| {(-x_0+x_1)} {(y_2-y_0)}- {(-x_0+x_2)} {(y_1-y_0)}|}}{{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}} \\
+\frac{1}{2} \frac{ y_0^{2} {| {(-x_0+x_1)} {(y_2-y_0)}- {(-x_0+x_2)} {(y_1-y_0)}|}}{{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}} \\
-\frac{ x_0 {| {(-x_0+x_1)} {(y_2-y_0)}- {(-x_0+x_2)} {(y_1-y_0)}|} x_1}{{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}} \\
+\frac{1}{2} \frac{ {| {(-x_0+x_1)} {(y_2-y_0)}- {(-x_0+x_2)} {(y_1-y_0)}|} x_1^{2}}{{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}} \\
+\frac{1}{2} \frac{ y_1^{2} {| {(-x_0+x_1)} {(y_2-y_0)}- {(-x_0+x_2)} {(y_1-y_0)}|}}{{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}}
\end{eqnarray*}
%% END OUTPUT GENERATED WITH fe_ex4

\noindent
We can also print out C code,  
%% BEGIN CODE FROM fe_ex4.h 
\begin{code}
  cout <<"C code format on output "<<endl; 
  cout <<csrc; 
  print(A2); 
\end{code}
%% END CODE FROM fe_ex4.h 
\noindent
Then the following code for $A[1,1]$ is produced, 
%% BEGIN CODE GENERATED WITH fe_ex4  
\begin{code}
A[1,1]=(x0*x0)/pow(-y1*x2-x0*y2+y0*x2+y2*x1+x0*y1-y0*x1,2.0)
*fabs((-x0+x1)*(y2-y0)-(-x0+x2)*(y1-y0))/2.0
-y1/pow(-y1*x2-x0*y2+y0*x2+y2*x1+x0*y1-y0*x1,2.0)*y0
*fabs((-x0+x1)*(y2-y0)-(-x0+x2)*(y1-y0))
+1.0/pow(-y1*x2-x0*y2+y0*x2+y2*x1+x0*y1-y0*x1,2.0)*(y0*y0)
*fabs((-x0+x1)*(y2-y0)-(-x0+x2)*(y1-y0))/2.0
-x0/pow(-y1*x2-x0*y2+y0*x2+y2*x1+x0*y1-y0*x1,2.0)
*fabs((-x0+x1)*(y2-y0)-(-x0+x2)*(y1-y0))*x1
+1.0/pow(-y1*x2-x0*y2+y0*x2+y2*x1+x0*y1-y0*x1,2.0)
*fabs((-x0+x1)*(y2-y0)
-(-x0+x2)*(y1-y0))*(x1*x1)/2.0+(y1*y1)
/pow(-y1*x2-x0*y2+y0*x2+y2*x1+x0*y1-y0*x1,2.0)
*fabs((-x0+x1)*(y2-y0)-(-x0+x2)*(y1-y0))/2.0

\end{code}
%% END CODE GENERATED WITH fe_ex4  


As is clear, these expressions can be rather large. 
GiNaC does not, by default,  try to simplify these expressions. 
However, the above expressions is composed of smaller
expressions that appear many times and it is possible to simplify
these expressions fairly easy.  For instance, the expression 
${{(- y_1 x_2- x_0 y_2+ y_0 x_2+ y_2 x_1+ x_0 y_1- y_0 x_1)}^{2}} $
appears at least six times (and this is only in $A[1,1]$). Of course, this expression should be computed only
once. It seems that GiNaC has powerful tools for expression three traversal that could enable generation of 
efficient code based on finding common sub-expressions, but we have not exploited these tools to a great extent
yet. Some example code can be found in \emp{check\_visitor.cpp} in the sandbox.        


\subsection{A Poisson Problem on Mixed Form}
The Poisson problem can also be written on mixed form, 
\begin{eqnarray*}
\uu - \nabla p &=& 0, \quad \text{ in } \Omega,   \\  
\nabla \cdot \uu &=& f, \quad \text{ in } \Omega,  \\   
\uu\cdot\nn &=& g, \quad \text{ on } \partial \Omega_N, \\    
p \, \nn       &=& h \, \nn  \quad \text{ on } \partial \Omega_E.  
\end{eqnarray*}
Notice that essential boundary conditions for the Poisson problem on 
standard form become natural conditions for the Poisson problem on 
mixed form and vice versa. 

The weak form of the Poisson problem on mixed form is:   
Find $\uu\in\VV_g,p\in Q$ such that  
\begin{eqnarray}
a(\uu,\vv) + b(\vv,p) &=& \GG(\vv),     \quad \forall \vv \in \VV_0, \\  
b(\uu, q)              &=& F(q),  \quad \forall q \in Q, 
\end{eqnarray}
where 
\begin{eqnarray}
a(\uu,\vv) &=& \int_\Omega \uu \cdot \vv \, dx,  \\  
b(\uu,q)   &=& \int_\Omega \nabla \cdot \uu \,  q \, dx,  \\ 
F(q)       &=& \int_\Omega f \, q \, dx,      \\ 
\GG(\vv)   &=& \int_{\Omega_E} h \,\nn\cdot \vv \, ds  
\end{eqnarray}
\[
\VV_k = { \vv \in \Hdiv : \vv\cdot\nn|_{\partial\Omega_N} = k }, \quad k = 0,g.      
\]
\[
\Hdiv = { \vv \in \LL^2 : \nabla\cdot \vv \in L^2 },
\]
\[
Q = 
\left\{
\begin{array}{l} 
L_0^2 \text{ if } \partial\Omega_N = \partial \Omega, \\    
L^2   \text{ else. }
\end{array} \right. 
\]

The function \emp{compute\_mixed\_Poisson\_element\_matrix} in \emp{ElementComputations.cpp}
computes the element matrix for the mixed Poisson problem. We will not comment or
list the code here because it is very similar to the code described in the next section.  
An example of use is in \emp{mxpoisson\_ex.cpp}. 


\subsection{A Stokes Problem}
The Stokes problem is on the form: 
Find $\uu$ and $p$ such that  
\begin{eqnarray*}
-\Delta \uu + \nabla p                  &=& \ff, \quad \text{ in } \Omega, \\    
\nabla\cdot \uu                         &=& 0,   \quad \text{ in } \Omega, \\ 
            \uu                         &=& \gg, \quad \text{ on } \partial \Omega_E, \\  
\frac{\partial\uu}{\partial \nn} -p \nn &=& \hh, \quad \text{ on } \partial \Omega_N.  
\end{eqnarray*}
The weak form for the Stokes problem is:   
Find $\uu\in\VV_g, p\in Q$ such that 
\begin{eqnarray*}
a(\uu,\vv) + b(\vv,p) &=& \FF(\vv),     \quad \forall \vv \in \VV_\nnull, \\  
b(\uu, q)              &=& 0,  \quad \forall q \in Q, 
\end{eqnarray*}
where 
\begin{eqnarray*}
a(\uu,\vv) &=& \int_\Omega \nabla \uu : \nabla \vv \, dx,  \\  
b(\uu,q)   &=& -\int_\Omega \nabla \cdot \uu \,  q \, dx,  \\ 
\FF(q)       &=& \int_\Omega \ff \cdot \vv \, dx + \int_{\Omega_N} \hh \cdot \vv \,ds,        
\end{eqnarray*}
\[
\VV_\kk = { \vv \in \HH^1 : \vv|_{\partial\Omega_E} = \kk }, \quad \kk = \nnull,\gg,      
\]
\[
Q = 
\left\{
\begin{array}{l} 
L_0^2 \text{ if } \partial\Omega_E = \partial \Omega, \\    
L^2   \text{ else. } 
\end{array} \right.  
\]
Notice that we have multiplied the equation for the mass conservation, $\nabla\cdot\uu=0$,  
with $-1$ to obtain symmetry. 


The function \emp{compute\_Stokes\_element\_matrix} in \emp{ElementComputations}
implements the computation of an element matrix for the Stokes problem. 
The code is shown below. 
%% BEGIN CODE FROM stokes_ex.h
{\footnotesize 
\begin{code}
void compute_Stokes_element_matrix(
  FE& v_fe, 
  FE& p_fe,
  Dof& dof, 
  std::map<std::pair<int,int>, ex>& A)
{
  std::pair<int,int> index; 
  std::pair<int,int> index2; 

  Polygon& domain = v_fe.get_polygon(); 

   // Insert the local degrees of freedom into the global Dof
  for (int i=0; i< v_fe.nbf(); i++) {
    dof.insert_dof(1,i,v_fe.dof(i)); 
  }
  for (int i=0; i< p_fe.nbf(); i++) {
    dof.insert_dof(1,v_fe.nbf()+i,p_fe.dof(i)); 
  }


  // The term (grad u, grad v)  
  for (int i=0; i< v_fe.nbf(); i++) {
    index.first = dof.glob_dof(v_fe.dof(i));   // fetch the dof for v_i 
    for (int j=0; j< v_fe.nbf(); j++) {
      index.second = dof.glob_dof(v_fe.dof(j));// fetch the dof for v_j 
      GiNaC::ex nabla = inner(grad(v_fe.N(i)),
                              grad(v_fe.N(j)));// compute the integrand  
      GiNaC::ex Aij = domain.integrate(nabla); // compute the integral  
      A[index] += Aij;                         // add to global matrix 
    }
  }

  // The term (-div u, q)  
  for (int i=0; i< p_fe.nbf(); i++) {
    index.first = dof.glob_dof(p_fe.dof(i));   // fetch the dof for p_i 
    for (int j=1; j< v_fe.nbf(); j++) {
      index.second=dof.glob_dof(v_fe.dof(j));  // fetch the dof for v_j 
      ex divV= -p_fe.N(i)*div(v_fe.N(j));       // compute the integrand 
      ex Aij = domain.integrate(divV);         // compute the integral  
      A[index] += Aij;                         // add to global matrix  

      // Do not need to compute the term (grad(p),v), since the system is 
      // symmetric. We simply set Aji = Aij 
      index2.first = index.second; 
      index2.second = index.first; 
      A[index2] -= Aij; 
    }
  }
}
\end{code}
}
%% END CODE FROM stokes_ex.cpp


\subsection{A Nonlinear Convection Diffusion Problem}
Our next example concerns a nonlinear convection diffusion equation, where we compute
the element matrix for the Jacobian typically arising in a Newton iteration.  
Let the PDE be, 
\begin{eqnarray}
(\uu\cdot\nabla)\uu - \Delta \uu &=& \ff, \quad \text{ in } \Omega, \\   
                             \uu &=& \gg, \quad \text{ on } \partial \Omega.  
\end{eqnarray}
This can be stated on weak form as: 
Find $\uu\in\VV_g$ such that 
\[
\FF(\uu,\vv) = 0, \quad \forall \vv\in \VV_\nnull,  
\]
where 
\begin{eqnarray*}
\FF(\uu,\vv) &=& \int_\Omega (\uu\cdot\nabla\uu)\cdot\vv \, dx  
              + \int_\Omega \nabla\uu:\nabla \vv \, dx   
              - \int_\Omega \ff \cdot \vv \, dx   
\end{eqnarray*}
and 
\[
\VV_\kk = { \vv \in \HH^1 : \vv |_{\partial \Omega} = \kk  }, \quad \kk=\nnull,\gg.  
\]
The Jacobian is obtained by letting $\uu=\hat{\uu}=\sum_j u_j \NN_j$, $\vv=\NN_i$  
and differentiating $\FF$ with respect to $u_j$, 
\[
J_{ij} = \frac{\partial F(\hat{\uu}, \NN_i)}{\partial u_j } . 
\]
This is precisely the way it is done with SyFi, (see also \emp{nljacobian\_ex.cpp}), 
%% BEGIN CODE FROM nljacobian_ex.cpp
{\footnotesize 
\begin{code}
void compute_nlconvdiff_element_matrix(
       FE& fe, 
       Dof& dof, 
       std::map<std::pair<int,int>, ex>& A) 
{
  std::pair<int,int> index;
  Polygon& domain = fe.get_polygon(); 

  // insert the local dofs into the global Dof object
  for (int i=0; i< fe.nbf() ; i++) { 
    dof.insert_dof(1,i,fe.dof(i)); 
  }

  // create the local U field: U = sum_k u_k N_k 
  ex UU = matrix(2,1,lst(0,0)); 
  ex ujs = symbolic_matrix(1,fe.nbf(), "u");  
  for (int k=0; k< fe.nbf(); k++)  {
    UU +=ujs.op(k)*fe.N(k);   // U += u_k N_k  
  }

  //Get U represented as a matrix 
  matrix U = ex_to<matrix>(UU.evalm());

  for (int i=0; i< fe.nbf() ; i++) {
    index.first = dof.glob_dof(fe.dof(i));     // fetch global dof 

    // First: the diffusion term in Fi
    ex gradU = grad(U);                        // compute the gradient 
    ex Fi_diffusion  = inner(gradU,            // grad(U)*grad(Ni) 
                             grad(fe.N(i))); 

    // Second: the convection term in Fi 
    ex Ut = U.transpose();                     // get the transposed of U 
    ex UgradU = (Ut*gradU).evalm();            // compute U*grad(U)     
    ex Fi_convection = inner(UgradU, fe.N(i),  // compute U*grad(U)*Ni    
                             true);

    // add together terms for convection and diffusion 
    ex Fi = Fi_convection + Fi_diffusion;            


    // Loop over all uj and differentiate Fi with respect
    // to uj to get the Jacobian Jij 
    for (int j=0; j< fe.nbf() ; j++) {
      index.second = dof.glob_dof(fe.dof(j));  // fetch global dof 
      symbol uj = ex_to<symbol>(ujs.op(j)); // cast uj to a symbol  
      ex Jij = Fi.diff(uj,1);               // differentiate Fi wrt. uj  
      ex Aij = domain.integrate(Jij);       // intergrate the Jacobian Jij  
      A[index] += Aij;                      // update the global matrix  
    }
  }
}
\end{code}
}
%% END CODE FROM nljacobian_ex.cpp
\noindent
Running the example \emp{nljacobian\_ex}, which employs second order continuous Lagrangian
elements,  yields the following output for $A[1,1]$,   
\begin{eqnarray}
A[1,1]&=&\frac{1}{2}+\frac{2}{105} u_{3}+\frac{2}{105} u_{7}
+\frac{1}{21} u_{2} \frac{13}{420} u_{1}-\frac{1}{280} u_{11} \\
&-&\frac{1}{21} u_{6} - \frac{1}{280} u_{5}  
\frac{1}{140} u_{10}+\frac{1}{210} u_{9}-\frac{1}{140} u_{4} . 
\end{eqnarray}
We have used GiNaC to generate the \LaTeX code, as described on Page \pageref{ginac:output:format}.  


\subsection{Expression Simplification}
When generating expressions for complicated forms, and specially non-linear forms,
there is much room for optimization of the resulting expressions to generate more efficient code.
Generating optimal code for the computation of a large symbolic expression is a very difficult
problem, and the underlying symbolic engine in GiNaC has limited support for this. However,
GiNaC has many of the building blocks to perform this optimization. We have implemented a basic
algorithm to simplify general expressions, which generates helper variables for basic binary
operations that are repeated. The algorithm is very simple, and the resulting speedup (in the tests)
ranges from a factor four to slightly negative. Obviously more work is needed in this area to make this usable.
The current expression simplifier can be tested by running "make simplify \&\& ./simplify v" under tests/.
A basic code example is shown below.
\begin{code}
ExpressionSimplifier es;
es.add(e_symbol, e_expression);
es.add(f_symbol, f_expression);
es.simplify();
    
list< pair< symbol, ex > > & selist =
        es.get_output().get_symex_list();
genCodeSymbols(cout, selist);
\end{code}



\section{Python Support}


\label{sec:python}

SyFi comes with Python support. The SyFi Python module
is created by using the tool SWIG (http://www.swig.org).  
One should also install the Python interface to GiNaC 
called Swiginac (http://swiginac.berlios.de/).

The following code shows how Swiginac
can be used (see also \emp{simple.py}),    
%% BEGIN CODE FROM simple.py 
\begin{code}
from swiginac import *

x = symbol("x")
y = symbol("y")

f = sin(x)
print "f = ", f
dfdx = diff(f,x)
print "dfdx = ", dfdx
\end{code}
%% END CODE FROM simple.py 
\noindent 

SyFi classes and functions can be used in Python just as they are used
in C++. The following example shows how to compute the  element matrix
for a Poisson problem using forth order Lagrangian elements, 
%% BEGIN CODE FROM poisson1.py 
\begin{code}
from swiginac import *
from SyFi import *

p0 = [0,0,0]; p1 = [1,0,0]; p2 = [0,1,0]
triangle = Triangle(p0, p1, p2) 
fe = LagrangeFE(triangle,4)           
print fe.nbf()
for i in range(0,fe.nbf()): 
  for j in range(0,fe.nbf()): 
    integrand = inner(grad(fe.N(i)),grad(fe.N(j)))  
    Aij = triangle.integrate(integrand) 
    print "A(%d,%d)="%(i,j), Aij.eval()
\end{code}
%% END CODE FROM poisson1.py 







Finally, we show a Python implementation of the Crouizex-Raviart element 
(The C++ implementation can be found in the file \emp{CrouzeixRaviart.cpp}). 
Notice that in this code we inherit the functions \emp{ex N(int i)} and 
\emp{ex dof(int i)} and the \emp{exvector}s \emp{Ns} and \emp{dofs} from
the C++ class \emp{StandardFE}. Hence, thanks to SWIG, cross-language inheritance
works, and we therefore only need to implement the function \emp{compute\_basis\_functions}.       
The following example is implemented in \emp{crouzeixraviart.py}. 
%% BEGIN CODE FROM crouzeixraviart.py 
\begin{code}
from swiginac import *
from SyFi import *

x = cvar.x; y = cvar.y; z = cvar.z # fetch global variables 

class CrouzeixRaviart(StandardFE): 
  """ 
    Python implementation of the Crouzeix-Raviart element. 
    The corresponding C++ implementation is in the 
    file CrouzeixRaviart.cpp.

    Notice that cross-language inheritance works! 
    The functions (used below) 
      ex N(int i) 
      ex dof(int i) 
    and the exvectors Ns and dofs are inherited from 
    the C++ class StandardFE. 
  """ 

  def __init__(self):  
    """ Constructor """
    StandardFE.__init__(self)

  def compute_basis_functions(self): 
    """ 
    Compute the basis functions and degrees of freedom  
    and put them in Ns and dofs, respectively. 
    """
    polspace = bernstein(1,triangle,"a")
    N = polspace[0]
    variables = polspace[1]

    for i in range(0,3): 
      line = triangle.line(i+1)
      dofi = line.integrate(N) 
      self.dofs.append(dofi)

    for i in range(0,3): 
      equations = []
      for j in range(0,3): 
        equations.append(relational(self.dofs[j], dirac(i,j)))
      sub = lsolve(equations, variables) 
      Ni = N.subs(sub) 
      self.Ns.append(Ni); 


p0 = [0,0,0]; p1 = [1,0,0]; p2 = [0,1,0]; 

triangle = Triangle(p0, p1, p2) 

fe = CrouzeixRaviart()
fe.set_polygon(triangle)
fe.compute_basis_functions()
for i in range(0,fe.nbf()): 
  print "N(%d)       = "%i,   fe.N(i).eval().printc()
  print "grad(N(%d)) = "%i,   grad(fe.N(i)).eval().printc()
  print "dof(%d)     = "%i,   fe.dof(i).eval().printc()
\end{code}
%% END CODE FROM crouzeixraviart.py 








\section{Code Generation}
\label{sec:code:gen}

In this section we will describe some matrix factories created for the 
PyCC project~\cite{www:pycc}, which have been made by using SyFi, GiNaC and Swiginac.  
At present, we have written ca. 1500 lines of Python code using SyFi, Swiginac etc., 
which have generated roughly 60 000 lines of C++ code for the computation (of various variants)
of the mass matrix, the stiffness matrix, the convection matrix and
the divergence matrix using Lagrangian elements of order 1-5 in 2D and 1-3 in 3D.     
Furthermore, the generated C++ code is efficient, since everything except the
geometry mapping can be computed exactly.     
Notice also that although only Lagrangian elements have been used so far, most
of the Python code that generated the C++ code is completely element independent. 
In addition to the generated C++ code we have also written about 1500 lines of code
which loops over the cells  of a Dolfin mesh ~\cite{www:dolfin} such that
global matrices are made. 

We have create two matrix factories. These are implemented in  \emp{MatrixFactory} and \emp{MatrixFactory\_highorder}.
There are three differences between these two factories. The first difference is
that \emp{MatrixFactory} employs the numbering of degrees of freedom in the Dolfin mesh.  
Therefore, this \emp{MatrixFactory} is limited to linear Lagrangian elements. 
On the other hand, \emp{MatrixFactory\_highorder}  uses \emp{DofT}, 
described in Section \ref{sec:dof}, which works for general elements. 
The second difference is that in \emp{MatrixFactory} the integration
is performed on a global element with global basis functions, e.g., for the stiffness matrix, 
\begin{equation}
\label{stiffness:global}
A_{ij} = \int_T \nabla N_i \nabla N_j dx.  
\end{equation}
In \emp{MatrixFactory\_highorder}, the integration is performed on the reference 
element with a geometry tensor $G$ (the Jacobian of the geometry mapping) and $D = \det(G)$, 
\begin{equation}
\label{stiffness:reference}
A_{ij} = \int_{\hat{T}} (G^{-T} \nabla \hat{N}_i)\cdot (G^{-T} \nabla \hat{N}_j) D \, dx .  
\end{equation}
which is the typical way to do it in finite element codes. 
At present, we favor \eqref{stiffness:reference} to \eqref{stiffness:global} simply
because it produces much smaller expressions and therefore faster code. However, the large expressions in 
\eqref{stiffness:global} typically involve subexpressions repeated many times.      
Hence, it should be possible to postprocess these expressions to create smaller expressions
and faster code. However, we have not done this yet.   
Finally, the third difference is that  
\emp{MatrixFactory\_highorder} works for the \emp{FastMatSparse} matrix in PyCC, the
Epetra matrix in Trilinos \cite{www:trilinos} and for STL maps of type \emp{map<pair<int,int>,double>}. 



\subsection{Basic Tools}

We will illustrate the code generation by considering what was done for 
the  mass matrix in \emp{MatrixFactory\_highorder}.   

The entries of a mass matrix are:  
\[
M_{kl} = \int_T N_k N_l \, dx =  \int_{\hat{T}} \hat{N}_i \hat{N}_j D \, dx, ,   
\]
where $T$ is the global polygon, $N_k$ and $N_l$ are the $k$'th and $l$'th global basis functions, 
respectively, $\hat{T}$ is the reference polygon,   
$\hat{N}_i$ and $\hat{N}_j$ are the $i$'th and $j$'th basis functions on the reference polygon
corresponding to $k$ and $l$, respectively, and $D$ is the determinant of the Jacobian of 
the geometry mapping.  
The following code shows how this can be done  
(see also \emp{code\_gen.py}):
%% BEGIN CODE FROM code_gen.py  
\begin{code}
def create_A_string_mass(fe):
  A_str = "  double A[%d][%d];\\n "%(fe.nbf(), fe.nbf())
  domain = fe.get_polygon()
  
  # loop over all N(i) 
  for i in range(0,fe.nbf()):

    # loop over all N(j) 
    for j in range(0,fe.nbf()):

      # compute the integrand N(i)*N(j)  
      integrand = fe.N(i).eval()*fe.N(j).eval()

      # integrate over the domain 
      Aij = domain.integrate(toex(integrand))

      # generate C string and append the string to the rest  
      A_str += "  A[%d][%d]=(%s)*D;\\n "%
                 (i,j,Aij.eval().evalf().printc())
\end{code}
%% END CODE FROM code_gen.py  
\noindent
The following output is produced,  when using linear element 
on a 2D triangle (see also \emp{matrix\_factory\_mass\_2D.cc}, which also 
contains code for higher order Lagrangian elements),  
%% BEGIN CODE FROM matrix_factory_mass_2D.cc 
\begin{code}
  double A[3][3];
  A[0][0]=(8.3333333333333329e-02)*D;
  A[0][1]=(4.1666666666666664e-02)*D;
  A[0][2]=(4.1666666666666664e-02)*D;
  A[1][0]=(4.1666666666666664e-02)*D;
  A[1][1]=(8.3333333333333329e-02)*D;
  A[1][2]=(4.1666666666666664e-02)*D;
  A[2][0]=(4.1666666666666664e-02)*D;
  A[2][1]=(4.1666666666666664e-02)*D;
  A[2][2]=(8.3333333333333329e-02)*D;
\end{code}
%% END CODE FROM matrix_factory_mass_2D.cc 
Hence, this is the mass element matrix on the reference element 
multiplied with $D$. 
In addition to computing the element matrix we also need to computed the global 
degrees of freedom and generate a C function. We will not go into details on
this, but recommend the reader to have a look in \emp{code\_gen.py}. 

The complete function for the computation of the element matrix, in the case of linear Lagrangian elements,  
and the insertion of 
the element matrix in the global matrix can be found in \emp{matrix\_factory\_mass\_2D.cc} is: 
%% BEGIN CODE FROM matrix_factory_mass_2D.cc 
{\footnotesize 
\begin{code}
void matrix_factory_mass_2D_order1 (map<pair<int,int>,double>& matrix, 
         DofT<Ptv,Ptv_is_less>& dof, 
         int element, double pp0[2], double pp1[2], double pp2[2]){
  
  // geometry related stuff 

  double x0 = pp0[0]; double y0 = pp0[1]; 
  double x1 = pp1[0]; double y1 = pp1[1]; 
  double x2 = pp2[0]; double y2 = pp2[1]; 
  
  double G00 = x1 - x0; double G01 = x2 - x0;  
  double G10 = y1 - y0; double G11 = y2 - y0; 
  
  double D = fabs(G00*G11-G01*G10);  

  // inserting local dofs in the global dof handler (dof)  

  int iidof[3];
  double dof1[2];
  dof1[0]=x0;  dof1[1]=y0;
  Ptv pdof1(2,dof1);
  iidof[0] = dof.insert_dof(element,1,pdof1);

  double dof2[2];
  dof2[0]=G01+x0;  dof2[1]=y0+G11;
  Ptv pdof2(2,dof2);
  iidof[1] = dof.insert_dof(element,2,pdof2);

  double dof3[2];
  dof3[0]=G00+x0;  dof3[1]=G10+y0;
  Ptv pdof3(2,dof3);
  iidof[2] = dof.insert_dof(element,3,pdof3);

 
  // compute the element matrix 

  double A[3][3];
  A[0][0]=(8.3333333333333329e-02)*D;
  A[0][1]=(4.1666666666666664e-02)*D;
  A[0][2]=(4.1666666666666664e-02)*D;
  A[1][0]=(4.1666666666666664e-02)*D;
  A[1][1]=(8.3333333333333329e-02)*D;
  A[1][2]=(4.1666666666666664e-02)*D;
  A[2][0]=(4.1666666666666664e-02)*D;
  A[2][1]=(4.1666666666666664e-02)*D;
  A[2][2]=(8.3333333333333329e-02)*D;


  // insert element matrix into global matrix 

  int nbf = 3;  
  pair<int,int> index; 
  for (int i=0; i< nbf; i++) {
    index.first = iidof[i]; 
    for (int j=0; j< nbf; j++) {
      index.second = iidof[j]; 
      matrix[index] += A[i][j];   
    }
  }
}
\end{code}
}
%% END CODE FROM matrix_factory_mass_2D.cc 

Finally, we show how the above function is used in PyCC to compute
the mass matrix on a Dolfin mesh (see also \emp{MatrixFactory\_highorder.cpp})  
%% BEGIN CODE FROM MatrixFactory_highorder.cpp  
{\footnotesize
\begin{code}
void MapMatrixFactory:: computeMassMatrix(){ 

  int e = -1; 

  if (mesh->numSpaceDim() == 2) {

    double p0[2]; 
    double p1[2]; 
    double p2[2]; 

    for (CellIterator cell(*mesh); !cell.end(); ++cell) {

      e++; 

      // Obtain vertices from Dolfin mesh
      Vertex& v0 = (*cell).vertex(0);
      Vertex& v1 = (*cell).vertex(1);
      Vertex& v2 = (*cell).vertex(2);


      // Create double arrays with the data from the vertices
      p0[0] = v0.coord().x;  p0[1] = v0.coord().y;
      p1[0] = v1.coord().x;  p1[1] = v1.coord().y;
      p2[0] = v2.coord().x;  p2[1] = v2.coord().y;


      switch(order1) {
          case 1 :  
              matrix_factory_mass_2D_order1(*matrix,*idof,e,p0,p1,p2); 
              break; 
          case 2 :  
              matrix_factory_mass_2D_order2(*matrix,*idof,e,p0,p1,p2); 
              break; 
          case 3 :  
              matrix_factory_mass_2D_order3(*matrix,*idof,e,p0,p1,p2); 
              break; 
          case 4 :  
              matrix_factory_mass_2D_order4(*matrix,*idof,e,p0,p1,p2); 
              break; 
          case 5 :  
              matrix_factory_mass_2D_order5(*matrix,*idof,e,p0,p1,p2); 
              break; 
      }
    }
  }
}
\end{code}
}
%% END CODE FROM MatrixFactory_highorder.cpp 
Notice that this code works for Lagrangian elements of order 1-5 in 2D. 




%\section{The Finite Element Method: The Poisson Problem}

% \section{Mixed Problems}
% \subsection{Stokes Problem}
% \subsubsection{Finite Elements}
% \subsubsection{Software Components}
% 
% 
% 
% \subsection{Mixed Poisson}
% \subsubsection{\Hdiv approximation} 
% \subsubsection{Finite Elements}
% \subsubsection{Software Components}
% 


\subsection{UFC code generation}
The UFC project (Unified Form-assembly Code, \cite{www:ufc}) aims to define an interface for the computation of element tensors
for general variational forms. This interface includes minimal classes for computing element tensor contributions on a cell,
for evaluating finite element functions, and mapping of degrees of freedom (dofs) between local and global finite element spaces.

In SyFi, the Python module \emp{ufccodegen} can be used to generate code compliant with the UFC interface.
Support for generating UFC code is also planned for FFC~\cite{FFC}, to make it possible to use SyFi and FFC to define elements
and equations while assembling the system with PyCC~\cite{www:pycc} or Dolfin~\cite{www:dolfin}.
By implementing assembly using the UFC interface, other FEM packages can use both SyFi and FFC to define elements and variational forms.

These UFC code generation tools are under development, and not all features of SyFi and UFC are included yet.
When the ufccodegen module is more mature, it will replace the old code generation described elsewhere in this manual,
and a new and more general matrix factory will replace the older matrix factories also described in this manual.
Below we present an example of how to use the tools for some basic forms.
\begin{code}
def stiffness_with_M(u, v, M, G, Ginv):
    Du = grad(u, Ginv)
    Dv = grad(v, Ginv)
    return inner( mul(M,Du), Dv )

def rhs(v, f, G, Ginv):
    return inner(f, v)

def H1norm(u, G, Ginv):
    Du = grad(u, Ginv)
    return inner(u, u) + inner(Du, Du)

nsd = 2
SyFi.initSyFi(nsd)

polygon = SyFi.newReferenceSimplex(nsd)
fe1     = SyFi.LagrangeFE(polygon, 1)
fe0     = SyFi.P0(polygon)

A  = MatrixForm(stiffness_with_M)
b  = VectorForm(rhs)
H1 = ScalarForm(H1norm)

# generate UFC code
gen_form_code(A,  [fe1, fe1, fe0])
gen_form_code(b,  fe1)
gen_form_code(H1, fe1)
\end{code}
In the above code we first define the integrands of the forms
\begin{gather}
a(u,v; M) = \int_\Omega M\grad u \cdot \grad v\,dx , \\
b(v)      = \int_\Omega f \cdot v\,dx , \\
|u|_1     = \int_\Omega u \cdot u + \grad u \cdot \grad u \,dx ,
\end{gather}
by simple python functions. The operators \emp{grad}, \emp{inner} and \emp{mul} are defined (among others)
in the \emp{ufccodegen.symbolic\_utils} module, and use the symbolic engine swiginac.
We next define a linear Lagrange element \emp{fe} on a simplex, using the usual SyFi tools.
The final result of the above code is to generate UFC compliant code to compute the
element tensors of these forms with the linear Lagrange element, but with a scalar \emp{P0} element
for the coefficient \emp{M}. An excerpt from the code is shown below.
In the next section we describe some additional options.

\begin{code}
void cell_integral_stiffness_with_M_LagrangeFE_1_2D::
     tabulate_tensor(double* A, const double * const * w,
                     const ufc::cell& cell) const
{
  // coordinates
  double x0 = cell.coordinates[0][0];
  double y0 = cell.coordinates[0][1];
  double x1 = cell.coordinates[1][0];
  double y1 = cell.coordinates[1][1];
  double x2 = cell.coordinates[2][0];
  double y2 = cell.coordinates[2][1];

  // affine map
  double G00 = x1 - x0;
  double G01 = x2 - x0;

  double G10 = y1 - y0;
  double G11 = y2 - y0;

  double detG_tmp = G00*G11-G01*G10;
  double detG = fabs(detG_tmp);

  double Ginv00 =  G11 / detG_tmp;
  double Ginv01 = -G10 / detG_tmp;
  double Ginv10 = -G01 / detG_tmp;
  double Ginv11 =  G00 / detG_tmp;

  A[3*0 + 0] = (5.e-01*(Ginv01*Ginv01)*w[0][0]
               +5.e-01*(Ginv00*Ginv00)*w[0][0]
               +Ginv11*Ginv01*w[0][0]
               +5.e-01*(Ginv11*Ginv11)*w[0][0]
               +Ginv10*Ginv00*w[0][0]
               +5.e-01*(Ginv10*Ginv10)*w[0][0])*detG;
  A[3*0 + 1] = (-5.e-01*(Ginv01*Ginv01)*w[0][0]
               -5.e-01*(Ginv00*Ginv00)*w[0][0]
               -5.e-01*Ginv11*Ginv01*w[0][0]
               -5.e-01*Ginv10*Ginv00*w[0][0])*detG;
  A[3*0 + 2] = (-5.e-01*Ginv11*Ginv01*w[0][0]
               -5.e-01*(Ginv11*Ginv11)*w[0][0]
               -5.e-01*Ginv10*Ginv00*w[0][0]
               -5.e-01*(Ginv10*Ginv10)*w[0][0])*detG;
  A[3*1 + 0] = (-5.e-01*(Ginv01*Ginv01)*w[0][0]
               -5.e-01*(Ginv00*Ginv00)*w[0][0]
               -5.e-01*Ginv11*Ginv01*w[0][0]
               -5.e-01*Ginv10*Ginv00*w[0][0])*detG;
  A[3*1 + 1] = (5.e-01*(Ginv01*Ginv01)*w[0][0]
               +5.e-01*(Ginv00*Ginv00)*w[0][0])*detG;
  A[3*1 + 2] = (5.e-01*Ginv11*Ginv01*w[0][0]
               +5.e-01*Ginv10*Ginv00*w[0][0])*detG;
  A[3*2 + 0] = (-5.e-01*Ginv11*Ginv01*w[0][0]
               -5.e-01*(Ginv11*Ginv11)*w[0][0]
               -5.e-01*Ginv10*Ginv00*w[0][0]
               -5.e-01*(Ginv10*Ginv10)*w[0][0])*detG;
  A[3*2 + 1] = (5.e-01*Ginv11*Ginv01*w[0][0]
               +5.e-01*Ginv10*Ginv00*w[0][0])*detG;
  A[3*2 + 2] = (5.e-01*(Ginv11*Ginv11)*w[0][0]
               +5.e-01*(Ginv10*Ginv10)*w[0][0])*detG;
}
\end{code}
The expressions for A had to be edited manually to fit on the page.

\subsubsection{Additional options}
The integrand functions (\emp{stiffness\_with\_M} etc.) are wrapped in Form objects (\emp{MatrixForm} etc.),
which uses introspection functionality from the Python language to automatically choose the name of the form equal to the function name,
and to set the number of coefficient arguments of the form from the number of free arguments 
in the integrand function (\emp{M} in the case of \emp{stiffness\_with\_M}). If the integrand is not a common Python function (f.ex. a functor),
the \emp{MatrixForm} constructor also take the optional arguments \emp{name} and \emp{num\_coefficients}.
\emp{VectorForm} and \emp{ScalarForm} are similar to \emp{MatrixForm}, the important difference being the
different rank of the resulting element tensor.

Next, the function \emp{gen\_form\_code} has a SyFi finite element or a list of finite elements as argument.
If a list is provided, it must have one element for each coefficient plus the rank of the form.
This allows using different test and trial functions, as well as different finite element
spaces for each coefficient. By default, \emp{integration\_mode} is \emp{'symbolic'}, but setting \emp{integration\_mode='quadrature'}
will result in generated code using quadrature rules for computing the integrals.
Optionally, the \emp{quad\_order} argument lets the user specify the order of the quadrature rule.
If not set, the order is chosen by inspecting the integrand expression.
The function \emp{gen\_form\_code} can be replaced by \emp{compile\_form}, which uses Instant~\cite{www:Instant} to wrap
and compile the generated code as a Python module, then returns the compiled \emp{ufc::form} object.
Instant does not compile the generated code if it is equal to previously generated code,
which means that code generation and compilation can be performed in the same Python application
that assembles the system and solves the equation, without a large performance hit.
This is very useful for fast development and experimentation with elements and variational forms.

\begin{code}
from ufccodegen import compile_function
from swiginac import matrix
from SyFi import get_symbol

x, y = get_symbol("x"), get_symbol("y")
mat = matrix(2, 2, [x*x, x*y, y*x, y*y])
matfunc = compile_function(mat, "matfunc")
\end{code}

UFC defines a functor interface \emp{ufc::function}, which can be passed to the function \emp{evaluate\_dof(...)} of the \emp{ufc::finite\_element} class
to evaluate the degrees of freedom of the function in the local finite element space on a cell.
To easily generate such functions from Python, \emp{ufccodegen} provides the function \emp{compile\_function(expression, name)}.
This works similar to \emp{compile\_form(...)}. The argument \emp{name} is used both for naming the generated functor class 
and to name the Python module, so function names should be different and valid C++ names. The \emp{expression} can be
a number of different types. A string is assumed to be a valid C++ expression which is inserted into the generated code.
A list of strings is treated as a vector function. Tensor functions are the same as vector functions, just unpack the
components into a list like a matrix in C. Finally, the expression can be a swiginac expression, either scalar or matrix.
Below is an example Python code for compiling a function from a swiginac \emp{matrix}, and the resulting generated C++ code.

\begin{code}
class matfunc: public ufc::function
{
public:
  /// Evaluate the function at the point
  /// x = (x[0], x[1], ...) in the cell
  virtual void evaluate(double* values,
                        const double* x_,
                        const ufc::cell& c) const
  {
    const double x=x_[0], y=x_[1], z=x_[2];
    values[0] = (x*x);
    values[1] = y*x;
    values[2] = y*x;
    values[3] = (y*y);
  }
};
\end{code}

\subsubsection{Code generation}
This subsection describes some implementation details of the code generation, and will be most interesting for developers.
The classes and functions described above can be seen as the user interface of ufccodegen, and are found in \emp{forms.py},
\emp{ufc\_code\_gen.py} and \emp{symbolic\_utils.py}.

In \emp{code\_generator.py}, a class \emp{code\_generator} and some utility functions for code generation is defined.
A \emp{code\_generator} object is something that can generate a header and source contribution.
Some utility functions can generate complete code files with contributions from one or more \emp{code\_generator} objects.

The subclasses of \emp{code\_generator} closely mirror the ufc classes they generate code for.
They are \emp{dof\_map}, \emp{finite\_element}, \emp{form} and \emp{function}. The user created \emp{Form} classes
are thin wrappers around \emp{form} which is a \emp{code\_generator} subclass for generating \emp{ufc::form} implementations.
A \emp{form} object also has functions to create \emp{dof\_map} and \emp{finite\_element} objects, which are
\emp{code\_generator} subclasses for generating \emp{ufc::dof\_map} and \emp{ufc::finite\_element} implementations, respectively.
Both \emp{dof\_map} and \emp{finite\_element} can be constructed independently with a SyFi finite element as
the only argument to the constructor, but this should usually not be necessary. While the \emp{form} constructor
has arguments for specifying boundary integrands, this is not completely implemented yet and the arguments are
therefore not explained here. In the files \emp{affine\_map.py} and \emp{quadrature.py}, additional code generation
utilities are found. Quadrature rules are taken from \cite{solin-sergeth-dolezel}.


\subsection{Debugging}

Debugging finite element codes is often extremely hard, at least 
that is the authors' experience. This has been one of
the reasons why we have chosen to employ a symbolic math engine
behind the curtain in the first place. 

One of the advantages of SyFi is that one obtain explicit symbolic expressions  
for all the basis functions (and its derivatives). Another good thing is that
one can create global finite elements, that is finite elements that
are not defined on reference geometries, and perform integration and differentiation
on their geometries. For instance, when we created the divergence matrix factory 
we initially had a mysterious bug which took us several hours to find.            
To locate the bug, we computed the divergence element matrix on a
global element with the vertices $\xx_0 = (0.2,0.2)$, $\xx_1 = (0.4,0.2)$, 
and $\xx_2 = (0.1,0.3)$, and compared it with the divergence element matrix 
on the reference element with the corresponding geometry tensor. 
To do this, we wrote the following code (see also \emp{main\_syfi.cpp}):  

%% BEGIN CODE FROM main_syfi.cpp 
\begin{code}
  // create global triangle
  lst p0(0.2, 0.2); 
  lst p1(0.4, 0.2); 
  lst p2(0.1, 0.3); 
  Triangle triangle(p0,p1,p2); 

  // create vector element for v on the global triangle
  VectorLagrangeFE v_fe; 
  v_fe.set_size(2); 
  v_fe.set_order(vorder); 
  v_fe.set_polygon(triangle); 
  v_fe.compute_basis_functions();

  // create scalar element for p on the global triangle
  LagrangeFE p_fe; 
  p_fe.set_order(1); 
  p_fe.set_polygon(triangle); 
  p_fe.compute_basis_functions();


  // compute global element matrix 
  map<pair<int,int>, ex> A; 
  pair<int,int> index; 
  for (int i=0; i< p_fe.nbf(); i++) {
    index.first = i; 
    for (int j=0; j< v_fe.nbf(); j++) {
      index.second= j;
      ex divV= p_fe.N(i)*div(v_fe.N(j));  
      ex Aij = triangle.integrate(divV);    
      A[index] = Aij;                          
    }
  }
\end{code}
%% END CODE FROM main_syfi.cpp 
The element matrix created by this code was then printed out and compared
with the element matrix computed by the matrix factory on the same polygon
(see \emp{dolfin\_main.cpp}). By comparing each entry of the two matrices
we quickly found the (uninteresting) bug.     
Hence, in out experience it is extremely valuable to have the concrete basis
functions etc. on global element, and being able to work with 
them both with a pen and a paper and the computer, to reveal what
is going on.    



\bibliographystyle{plain}
\bibliography{refs}






\end{document}

%% BEGIN CODE FROM simple.h 
\begin{code}
\end{code}
%% END CODE FROM simple.h 




