% This is LLNCS.DEM the demonstration file of
% the LaTeX macro package from Springer-Verlag
% for Lecture Notes in Computer Science,
% version 2.2 for LaTeX2e
%
\documentclass{llncs}
\usepackage{moreverb,relsize,ttname}
\usepackage{bm}
\usepackage{amssymb}
\usepackage{amsmath}



\newcommand{\FF}{\mathbf{F}}
\newcommand{\uu}{\mathbf{u}}
\newcommand{\vv}{\mathbf{v}}
\newcommand{\ff}{\mathbf{f}}
\newcommand{\NN}{\mathbf{N}}
\renewcommand{\P}{{\mathbb P}}

%
\begin{document}
%

\pagestyle{headings} 
\mainmatter              % start of the contributions
%
\title{SyFi - An Element Matrix Factory, with Emphasis on the Incompressible Navier-Stokes Equations }
%
\titlerunning{SyFi - An Element Matrix Factory}  % abbreviated title (for running head)
%                                     also used for the TOC unless
%                                     \toctitle is used
%
\author{Kent-Andre Mardal}
%
\authorrunning{Kent-Andre Mardal}   % abbreviated author list (for running head)
%
%%%% modified list of authors for the TOC (add the affiliations)
\tocauthor{Kent-Andre Mardal (Simula Research Laboratory)}
%
\institute{Simula Research Laboratory, P.O. Box 134, NO-1325 Lysaker, Norway,\\
\email{kent-and@simula.no},\\ WWW home page:
\texttt{http://www.simula.no/portal\_memberdata/kent-and}
}
\maketitle              % typeset the title of the contribution


\begin{abstract}
SyFi  is an open source C++ library for defining and using advanced
finite elements based on  symbolic representations of polygonal domains, 
degrees of freedom and polynomial spaces. Once the finite elements
and weak forms are defined, they are used to generate efficient C/C++ code.    
\end{abstract}
%


\section{Introduction}

SyFi \cite{SyFi} is an open source C++ library for defining finite elements and weak forms as symbolic expressions. 
These expressions are then used to generate efficient C/C++ code. 
It relies on the open source C++ library GiNaC \cite{GiNaC}, which is a library
for symbolic computations with a strong support for polynomials.  
SyFi has Python bindings created by using SWIG \cite{SWIG}. 

In this short paper we will demonstrate its use by two examples. 
These examples are explained further in the SyFi tutorial, 
which can be found on the homepage \cite{SyFi}.  

The first example shows how a finite element, namely the Crouzeix-Raviart element \cite{c-r}
is defined in Python using SyFi.  
The degrees of freedom for the Crouzeix-Raviart element  are the integral of the function over
an edge,  
\[
L_i(v) = \int_{e_i} v \, ds, 
\]
where $v = a_0 + a_1 x + a_2 y$.
These degrees of freedom are then used to
form a linear system of equations,   
\begin{equation}
\label{dofdelta}
L_i(v_j) = \delta_{ij},   
\end{equation}
which determine the basis functions of the Crouzeix-Raviart element. 
The following Python code demonstrates how this can be done with SyFi, 


%% BEGIN CODE FROM crouzeixraviart.py 
{
\renewcommand{\baselinestretch}{0.85}\footnotesize
\begin{verbatimtab}[8]

class CrouzeixRaviart(StandardFE): 
  def __init__(self):  
    StandardFE.__init__(self)


  def compute_basis_functions(self):  

    # create a polynomial space, which is a list with the following items 
    # 1. the polynom   : a0 + a1*x + a2*y
    # 2. the variables : a0, a1, a2
    # 3. the basis     : 1, x, y 
    polspace = pol(1,2,"a") # create a polynomial space
                   
    N = polspace.eval()[0]               # fetch the polynomial
    variables = polspace.eval()[1]       # fetch the variables

    for i in range(1,4):                 # run over all sides (1,2,3)  
      line = triangle.line(i)            # fetch the side/line  
      dofi = line.integrate(toex(N))     # the dof as a line integral 
      self.dofs.append(dofi)             # append to the list of dofs

    #create the linear system of equations
    for i in range(1,4): 
      equations = []
      for j in range(1,4): 
        equations.append(self.dofs[j-1].eval() == dirac(i,j) )
      sub = lsolve(equations, variables)  # solve the system  
      Ni = N.subs(sub)                    # substitute a0, a1, a2 
      self.Ns.append(toex(Ni));           # append to the basisfunc list 
\end{verbatimtab}
}
\noindent
As can be seen below, it is straightforward to used this Python element to generate
C code for the basis functions, their derivatives
and the corresponding degrees of freedom: 
{
\renewcommand{\baselinestretch}{0.85}\footnotesize
\begin{verbatimtab}[8]
triangle = ReferenceTriangle() 
fe = CrouzeixRaviart()
fe.set(triangle)
fe.compute_basis_functions()
for i in range(1,fe.nbf()+1): 
  print "N(%d)  = "%i,fe.N(i).eval().printc()       # print N_i in C 
  print "dN(%d) = "%i,grad(fe.N(i)).eval().printc() # print grad in C
  print "dof(%d)= "%i,fe.dof(i).eval().printc()     # print dof_i in C 
\end{verbatimtab}
}

The second example shows the (symbolic) computation of the Jacobian
of a nonlinear convection-diffusion equation,   
\[
(\uu\cdot\nabla)\uu - \Delta \uu = \ff  
\]
The equation on weak form is given by: 
\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*}
By letting $\uu=\hat{\uu}=\sum_j u_j \NN_j$ and  $\vv=\NN_i$, 
where $\NN_i$ and $\NN_j$ are finite element basis functions
and $u_j$ the corresponding degrees of freedom,  
we can compute the Jacobian to be used in a finite element method,  
\[
J_{ij} = \frac{\partial F(\hat{\uu}, \NN_i)}{\partial u_j } . 
\]
The following code shows how this can be done with SyFi. 
We emphasize that all of the computations are done symbolically, 
simply by differentiating functions  of polynomials. 
Therefore, the code below works for any finite element. 
%% BEGIN CODE FROM nljacobian_ex.cpp
{
\renewcommand{\baselinestretch}{0.85}\footnotesize
\begin{verbatimtab}[8]
void compute_nlconvdiff_element_matrix(
       FE& fe, 
       matrix& A) 
{
  Polygon& domain = fe.getPolygon(); 

  // 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=1; k<= fe.nbf(); k++)  {
    UU +=ujs.op(k-1)*fe.N(k);   // U += u_k N_k  
  }

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

  for (int i=1; i<= fe.nbf() ; i++) {

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

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

    // 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=1; j<= fe.nbf() ; j++) {
      symbol uj = ex_to<symbol>(ujs[j-1]);  // cast uj to a symbol  
      ex Jij = Fi.diff(uj,1);                  // differentiate Fi wrt. uj  
      A[i][j] = domain.integrate(Jij);          // intergrate the Jacobian Jij  
    }
  }
}
\end{verbatimtab}
}
%% END CODE FROM nljacobian_ex.cpp

At present continuous and discontinuous Lagrangian elements, 
of arbitrary order in both 2D and 3D have been implemented in SyFi. 
Hence, Taylor-Hood elements and $\P^d_n-\P_{n-2}$ elements 
are readily available. The Crouzeix-Raviart element has
also been implemented in 2D and 3D. In addition element 
matrices for Stokes problems as well as the above described 
nonlinear convection-diffusion equation have been implemented.    
Currently, we are coupling the SyFi framework with the Trilinos
package \cite{Trilinos} to solve the linear system of equations obtained by SyFi.  



\begin{thebibliography}{5}

\bibitem{c-r} M. Crouzeix and P.A. Raviart,
Conforming and non--conforming finite element methods for solving
the stationary Stokes equations,
RAIRO Anal. Num\'{e}r. 7 (1973), pp. 33--76.

\bibitem{GiNaC}
GiNaC - is not a CAS, 
http://www.ginac.de

\bibitem{SyFi}
SyFi - Symbolic Finite Elements, 
http://syfi.sf.net



\bibitem{SWIG}
SWIG - Simplified Wrapper and Interface Generator, 
http://www.swig.org


\bibitem{Trilinos}
Trilinos, 
http://software.sandia.gov/trilinos/

\end{thebibliography}

\end{document}



