% 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}

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

%
\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://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 a symbolic representation of polygonal domains, 
degrees of freedom and polynomial spaces. Once the finite elements
and weak forms are definied, they are used to generate efficient 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 use to generate efficient 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, before 
we will summarize the current features and uses of SyFi. 
The first example shows how a finite element, namly the Crouzeix-Raviart element
is defined in Python. 

The degrees of freedom are the integral of the function over
an edge,  
\[
L_i(v) = \int_{e_i} v \, ds.  
\]
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 determined the basis functions of the Crouzeix-Raviart element. 
The following Python code demostrates 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):  
    polspace = bernstein(1,triangle,"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): 
      line = triangle.line(i)
      dofi = line.integrate(toex(N))     # the dof as a line integral 
      self.dofs.append(dofi)

    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) 
      Ni = N.subs(sub) 
      self.Ns.append(toex(Ni)); 


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

triangle = Triangle(toex(p0), toex(p1), toex(p2)) 

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()
  print "grad(N(%d)) = "%i,   grad(fe.N(i)).eval()
  print "dof(%d)     = "%i,   fe.dof(i).eval()

\end{verbatimtab}
}

The second example shows the (symbolic) computation of the Jacobian
of a nonlinear convection-diffusion equation.   
The equation on variational 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*}
The Jacobian is 
\[
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 compuations are done symbolically, 
simply by differentiation 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
\noindent


\begin{thebibliography}{5}

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


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

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

\end{thebibliography}

\end{document}



