← Back to team overview

dolfin team mailing list archive

[MERGE] Adding first benchmark for function eval

 

Hi!

This is a first patch for adding a function eval bench. Takes sin*sin*sin  
function, interpolates on P1 on UnitCube, eval 100000 random points and 
repeating whole procedure 10 times, refining the cube each time.  

Please have a look at it and let me know what you additonally wish to be 
added/changed (Maybe 1D and 2D or whatever...)

The other benchs will follow, planed  to submit one patch for each benchmark.

Cheers,
--
Andre

# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: massing@xxxxxxxxx-20100612095930-dhbta7h17j85y1yr
# target_branch: bzr+ssh://bazaar.launchpad.net/~dolfin-\
#   core/dolfin/main/
# testament_sha1: e9603ae789cbe1cc058f90a47322510a91b821a5
# timestamp: 2010-06-12 12:29:00 +0200
# base_revision_id: gnw20@xxxxxxxxx-20100608193514-3ej5hqzp6bz3wxmm
# 
# Begin patch
=== added directory 'bench/function/evaluation'
=== added directory 'bench/function/evaluation/cpp'
=== added file 'bench/function/evaluation/cpp/P1.h'
--- bench/function/evaluation/cpp/P1.h	1970-01-01 00:00:00 +0000
+++ bench/function/evaluation/cpp/P1.h	2010-06-10 21:06:35 +0000
@@ -0,0 +1,1264 @@
+// This code conforms with the UFC specification version 1.4
+// and was automatically generated by FFC version 0.9.2+.
+//
+// This code was generated with the option '-l dolfin' and
+// contains DOLFIN-specific wrappers that depend on DOLFIN.
+// 
+// This code was generated with the following parameters:
+// 
+//   cache_dir:                      ''
+//   convert_exceptions_to_warnings: False
+//   cpp_optimize:                   False
+//   epsilon:                        1e-14
+//   form_postfix:                   True
+//   format:                         'dolfin'
+//   log_level:                      10
+//   log_prefix:                     ''
+//   optimize:                       True
+//   output_dir:                     '.'
+//   precision:                      15
+//   quadrature_degree:              'auto'
+//   quadrature_rule:                'auto'
+//   representation:                 'auto'
+//   split:                          False
+
+#ifndef __P1_H
+#define __P1_H
+
+#include <cmath>
+#include <stdexcept>
+#include <fstream>
+#include <ufc.h>
+
+/// This class defines the interface for a finite element.
+
+class p1_finite_element_0: public ufc::finite_element
+{
+public:
+
+  /// Constructor
+  p1_finite_element_0() : ufc::finite_element()
+  {
+    // Do nothing
+  }
+
+  /// Destructor
+  virtual ~p1_finite_element_0()
+  {
+    // Do nothing
+  }
+
+  /// Return a string identifying the finite element
+  virtual const char* signature() const
+  {
+    return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+  }
+
+  /// Return the cell shape
+  virtual ufc::shape cell_shape() const
+  {
+    return ufc::triangle;
+  }
+
+  /// Return the dimension of the finite element function space
+  virtual unsigned int space_dimension() const
+  {
+    return 3;
+  }
+
+  /// Return the rank of the value space
+  virtual unsigned int value_rank() const
+  {
+    return 0;
+  }
+
+  /// Return the dimension of the value space for axis i
+  virtual unsigned int value_dimension(unsigned int i) const
+  {
+    return 1;
+  }
+
+  /// Evaluate basis function i at given point in cell
+  virtual void evaluate_basis(unsigned int i,
+                              double* values,
+                              const double* coordinates,
+                              const ufc::cell& c) const
+  {
+    // Extract vertex coordinates
+    const double * const * x = c.coordinates;
+    
+    // Compute Jacobian of affine map from reference cell
+    const double J_00 = x[1][0] - x[0][0];
+    const double J_01 = x[2][0] - x[0][0];
+    const double J_10 = x[1][1] - x[0][1];
+    const double J_11 = x[2][1] - x[0][1];
+    
+    // Compute determinant of Jacobian
+    double detJ = J_00*J_11 - J_01*J_10;
+    
+    // Compute inverse of Jacobian
+    
+    // Compute constants
+    const double C0 = x[1][0] + x[2][0];
+    const double C1 = x[1][1] + x[2][1];
+    
+    // Get coordinates and map to the reference (FIAT) element
+    double X = (J_01*(C1 - 2.0*coordinates[1]) + J_11*(2.0*coordinates[0] - C0)) / detJ;
+    double Y = (J_00*(2.0*coordinates[1] - C1) + J_10*(C0 - 2.0*coordinates[0])) / detJ;
+    
+    // Reset values.
+    *values = 0.000000000000000;
+    switch (i)
+    {
+    case 0:
+      {
+        
+      // Array of basisvalues.
+      double basisvalues[3] = {0.000000000000000, 0.000000000000000, 0.000000000000000};
+      
+      // Declare helper variables.
+      unsigned int rr = 0;
+      unsigned int ss = 0;
+      double tmp0 = (1.000000000000000 + Y + 2.000000000000000*X)/2.000000000000000;
+      
+      // Compute basisvalues.
+      basisvalues[0] = 1.000000000000000;
+      basisvalues[1] = tmp0;
+      for (unsigned int r = 0; r < 1; r++)
+      {
+        rr = (r + 1)*(r + 1 + 1)/2 + 1;
+        ss = r*(r + 1)/2;
+        basisvalues[rr] = basisvalues[ss]*(0.500000000000000 + r + Y*(1.500000000000000 + r));
+      }// end loop over 'r'
+      for (unsigned int r = 0; r < 2; r++)
+      {
+        for (unsigned int s = 0; s < 2 - r; s++)
+        {
+          rr = (r + s)*(r + s + 1)/2 + s;
+          basisvalues[rr] *= std::sqrt((0.500000000000000 + r)*(1.000000000000000 + r + s));
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Table(s) of coefficients.
+      static const double coefficients0[3] = \
+      {0.471404520791032, -0.288675134594813, -0.166666666666667};
+      
+      // Compute value(s).
+      for (unsigned int r = 0; r < 3; r++)
+      {
+        *values += coefficients0[r]*basisvalues[r];
+      }// end loop over 'r'
+        break;
+      }
+    case 1:
+      {
+        
+      // Array of basisvalues.
+      double basisvalues[3] = {0.000000000000000, 0.000000000000000, 0.000000000000000};
+      
+      // Declare helper variables.
+      unsigned int rr = 0;
+      unsigned int ss = 0;
+      double tmp0 = (1.000000000000000 + Y + 2.000000000000000*X)/2.000000000000000;
+      
+      // Compute basisvalues.
+      basisvalues[0] = 1.000000000000000;
+      basisvalues[1] = tmp0;
+      for (unsigned int r = 0; r < 1; r++)
+      {
+        rr = (r + 1)*(r + 1 + 1)/2 + 1;
+        ss = r*(r + 1)/2;
+        basisvalues[rr] = basisvalues[ss]*(0.500000000000000 + r + Y*(1.500000000000000 + r));
+      }// end loop over 'r'
+      for (unsigned int r = 0; r < 2; r++)
+      {
+        for (unsigned int s = 0; s < 2 - r; s++)
+        {
+          rr = (r + s)*(r + s + 1)/2 + s;
+          basisvalues[rr] *= std::sqrt((0.500000000000000 + r)*(1.000000000000000 + r + s));
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Table(s) of coefficients.
+      static const double coefficients0[3] = \
+      {0.471404520791032, 0.288675134594813, -0.166666666666667};
+      
+      // Compute value(s).
+      for (unsigned int r = 0; r < 3; r++)
+      {
+        *values += coefficients0[r]*basisvalues[r];
+      }// end loop over 'r'
+        break;
+      }
+    case 2:
+      {
+        
+      // Array of basisvalues.
+      double basisvalues[3] = {0.000000000000000, 0.000000000000000, 0.000000000000000};
+      
+      // Declare helper variables.
+      unsigned int rr = 0;
+      unsigned int ss = 0;
+      double tmp0 = (1.000000000000000 + Y + 2.000000000000000*X)/2.000000000000000;
+      
+      // Compute basisvalues.
+      basisvalues[0] = 1.000000000000000;
+      basisvalues[1] = tmp0;
+      for (unsigned int r = 0; r < 1; r++)
+      {
+        rr = (r + 1)*(r + 1 + 1)/2 + 1;
+        ss = r*(r + 1)/2;
+        basisvalues[rr] = basisvalues[ss]*(0.500000000000000 + r + Y*(1.500000000000000 + r));
+      }// end loop over 'r'
+      for (unsigned int r = 0; r < 2; r++)
+      {
+        for (unsigned int s = 0; s < 2 - r; s++)
+        {
+          rr = (r + s)*(r + s + 1)/2 + s;
+          basisvalues[rr] *= std::sqrt((0.500000000000000 + r)*(1.000000000000000 + r + s));
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Table(s) of coefficients.
+      static const double coefficients0[3] = \
+      {0.471404520791032, 0.000000000000000, 0.333333333333333};
+      
+      // Compute value(s).
+      for (unsigned int r = 0; r < 3; r++)
+      {
+        *values += coefficients0[r]*basisvalues[r];
+      }// end loop over 'r'
+        break;
+      }
+    }
+    
+  }
+
+  /// Evaluate all basis functions at given point in cell
+  virtual void evaluate_basis_all(double* values,
+                                  const double* coordinates,
+                                  const ufc::cell& c) const
+  {
+    // Helper variable to hold values of a single dof.
+    double dof_values = 0.000000000000000;
+    
+    // Loop dofs and call evaluate_basis.
+    for (unsigned int r = 0; r < 3; r++)
+    {
+      evaluate_basis(r, &dof_values, coordinates, c);
+      values[r] = dof_values;
+    }// end loop over 'r'
+  }
+
+  /// Evaluate order n derivatives of basis function i at given point in cell
+  virtual void evaluate_basis_derivatives(unsigned int i,
+                                          unsigned int n,
+                                          double* values,
+                                          const double* coordinates,
+                                          const ufc::cell& c) const
+  {
+    // Extract vertex coordinates
+    const double * const * x = c.coordinates;
+    
+    // Compute Jacobian of affine map from reference cell
+    const double J_00 = x[1][0] - x[0][0];
+    const double J_01 = x[2][0] - x[0][0];
+    const double J_10 = x[1][1] - x[0][1];
+    const double J_11 = x[2][1] - x[0][1];
+    
+    // Compute determinant of Jacobian
+    double detJ = J_00*J_11 - J_01*J_10;
+    
+    // Compute inverse of Jacobian
+    const double K_00 =  J_11 / detJ;
+    const double K_01 = -J_01 / detJ;
+    const double K_10 = -J_10 / detJ;
+    const double K_11 =  J_00 / detJ;
+    
+    // Compute constants
+    const double C0 = x[1][0] + x[2][0];
+    const double C1 = x[1][1] + x[2][1];
+    
+    // Get coordinates and map to the reference (FIAT) element
+    double X = (J_01*(C1 - 2.0*coordinates[1]) + J_11*(2.0*coordinates[0] - C0)) / detJ;
+    double Y = (J_00*(2.0*coordinates[1] - C1) + J_10*(C0 - 2.0*coordinates[0])) / detJ;
+    
+    // Compute number of derivatives.
+    unsigned int num_derivatives = 1;
+    for (unsigned int r = 0; r < n; r++)
+    {
+      num_derivatives *= 2;
+    }// end loop over 'r'
+    
+    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
+    unsigned int **combinations = new unsigned int *[num_derivatives];
+    for (unsigned int row = 0; row < num_derivatives; row++)
+    {
+      combinations[row] = new unsigned int [n];
+      for (unsigned int col = 0; col < n; col++)
+        combinations[row][col] = 0;
+    }
+    
+    // Generate combinations of derivatives
+    for (unsigned int row = 1; row < num_derivatives; row++)
+    {
+      for (unsigned int num = 0; num < row; num++)
+      {
+        for (unsigned int col = n-1; col+1 > 0; col--)
+        {
+          if (combinations[row][col] + 1 > 1)
+            combinations[row][col] = 0;
+          else
+          {
+            combinations[row][col] += 1;
+            break;
+          }
+        }
+      }
+    }
+    
+    // Compute inverse of Jacobian
+    const double Jinv[2][2] = {{K_00, K_01}, {K_10, K_11}};
+    
+    // Declare transformation matrix
+    // Declare pointer to two dimensional array and initialise
+    double **transform = new double *[num_derivatives];
+    
+    for (unsigned int j = 0; j < num_derivatives; j++)
+    {
+      transform[j] = new double [num_derivatives];
+      for (unsigned int k = 0; k < num_derivatives; k++)
+        transform[j][k] = 1;
+    }
+    
+    // Construct transformation matrix
+    for (unsigned int row = 0; row < num_derivatives; row++)
+    {
+      for (unsigned int col = 0; col < num_derivatives; col++)
+      {
+        for (unsigned int k = 0; k < n; k++)
+          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
+      }
+    }
+    
+    // Reset values. Assuming that values is always an array.
+    for (unsigned int r = 0; r < num_derivatives; r++)
+    {
+      values[r] = 0.000000000000000;
+    }// end loop over 'r'
+    
+    switch (i)
+    {
+    case 0:
+      {
+        
+      // Array of basisvalues.
+      double basisvalues[3] = {0.000000000000000, 0.000000000000000, 0.000000000000000};
+      
+      // Declare helper variables.
+      unsigned int rr = 0;
+      unsigned int ss = 0;
+      double tmp0 = (1.000000000000000 + Y + 2.000000000000000*X)/2.000000000000000;
+      
+      // Compute basisvalues.
+      basisvalues[0] = 1.000000000000000;
+      basisvalues[1] = tmp0;
+      for (unsigned int r = 0; r < 1; r++)
+      {
+        rr = (r + 1)*(r + 1 + 1)/2 + 1;
+        ss = r*(r + 1)/2;
+        basisvalues[rr] = basisvalues[ss]*(0.500000000000000 + r + Y*(1.500000000000000 + r));
+      }// end loop over 'r'
+      for (unsigned int r = 0; r < 2; r++)
+      {
+        for (unsigned int s = 0; s < 2 - r; s++)
+        {
+          rr = (r + s)*(r + s + 1)/2 + s;
+          basisvalues[rr] *= std::sqrt((0.500000000000000 + r)*(1.000000000000000 + r + s));
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Table(s) of coefficients.
+      static const double coefficients0[3] = \
+      {0.471404520791032, -0.288675134594813, -0.166666666666667};
+      
+      // Tables of derivatives of the polynomial base (transpose).
+      static const double dmats0[3][3] = \
+      {{0.000000000000000, 0.000000000000000, 0.000000000000000},
+      {4.898979485566356, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 0.000000000000000}};
+      
+      static const double dmats1[3][3] = \
+      {{0.000000000000000, 0.000000000000000, 0.000000000000000},
+      {2.449489742783178, 0.000000000000000, 0.000000000000000},
+      {4.242640687119285, 0.000000000000000, 0.000000000000000}};
+      
+      // Compute reference derivatives.
+      // Declare pointer to array of derivatives on FIAT element.
+      double *derivatives = new double[num_derivatives];
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        derivatives[r] = 0.000000000000000;
+      }// end loop over 'r'
+      
+      // Declare derivative matrix (of polynomial basis).
+      double dmats[3][3] = \
+      {{1.000000000000000, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 1.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 1.000000000000000}};
+      
+      // Declare (auxiliary) derivative matrix (of polynomial basis).
+      double dmats_old[3][3] = \
+      {{1.000000000000000, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 1.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 1.000000000000000}};
+      
+      // Loop possible derivatives.
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        // Resetting dmats values to compute next derivative.
+        for (unsigned int t = 0; t < 3; t++)
+        {
+          for (unsigned int u = 0; u < 3; u++)
+          {
+            dmats[t][u] = 0.000000000000000;
+            if (t == u)
+            {
+            dmats[t][u] = 1.000000000000000;
+            }
+            
+          }// end loop over 'u'
+        }// end loop over 't'
+        
+        // Looping derivative order to generate dmats.
+        for (unsigned int s = 0; s < n; s++)
+        {
+          // Updating dmats_old with new values and resetting dmats.
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              dmats_old[t][u] = dmats[t][u];
+              dmats[t][u] = 0.000000000000000;
+            }// end loop over 'u'
+          }// end loop over 't'
+          
+          // Update dmats using an inner product.
+          if (combinations[r][s] == 0)
+          {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              for (unsigned int tu = 0; tu < 3; tu++)
+              {
+                dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u];
+              }// end loop over 'tu'
+            }// end loop over 'u'
+          }// end loop over 't'
+          }
+          
+          if (combinations[r][s] == 1)
+          {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              for (unsigned int tu = 0; tu < 3; tu++)
+              {
+                dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u];
+              }// end loop over 'tu'
+            }// end loop over 'u'
+          }// end loop over 't'
+          }
+          
+        }// end loop over 's'
+        for (unsigned int s = 0; s < 3; s++)
+        {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t];
+          }// end loop over 't'
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Transform derivatives back to physical element
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        for (unsigned int s = 0; s < num_derivatives; s++)
+        {
+          values[r] += transform[r][s]*derivatives[s];
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Delete pointer to array of derivatives on FIAT element
+      delete [] derivatives;
+      
+      // Delete pointer to array of combinations of derivatives and transform
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        delete [] combinations[r];
+      }// end loop over 'r'
+      delete [] combinations;
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        delete [] transform[r];
+      }// end loop over 'r'
+      delete [] transform;
+        break;
+      }
+    case 1:
+      {
+        
+      // Array of basisvalues.
+      double basisvalues[3] = {0.000000000000000, 0.000000000000000, 0.000000000000000};
+      
+      // Declare helper variables.
+      unsigned int rr = 0;
+      unsigned int ss = 0;
+      double tmp0 = (1.000000000000000 + Y + 2.000000000000000*X)/2.000000000000000;
+      
+      // Compute basisvalues.
+      basisvalues[0] = 1.000000000000000;
+      basisvalues[1] = tmp0;
+      for (unsigned int r = 0; r < 1; r++)
+      {
+        rr = (r + 1)*(r + 1 + 1)/2 + 1;
+        ss = r*(r + 1)/2;
+        basisvalues[rr] = basisvalues[ss]*(0.500000000000000 + r + Y*(1.500000000000000 + r));
+      }// end loop over 'r'
+      for (unsigned int r = 0; r < 2; r++)
+      {
+        for (unsigned int s = 0; s < 2 - r; s++)
+        {
+          rr = (r + s)*(r + s + 1)/2 + s;
+          basisvalues[rr] *= std::sqrt((0.500000000000000 + r)*(1.000000000000000 + r + s));
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Table(s) of coefficients.
+      static const double coefficients0[3] = \
+      {0.471404520791032, 0.288675134594813, -0.166666666666667};
+      
+      // Tables of derivatives of the polynomial base (transpose).
+      static const double dmats0[3][3] = \
+      {{0.000000000000000, 0.000000000000000, 0.000000000000000},
+      {4.898979485566356, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 0.000000000000000}};
+      
+      static const double dmats1[3][3] = \
+      {{0.000000000000000, 0.000000000000000, 0.000000000000000},
+      {2.449489742783178, 0.000000000000000, 0.000000000000000},
+      {4.242640687119285, 0.000000000000000, 0.000000000000000}};
+      
+      // Compute reference derivatives.
+      // Declare pointer to array of derivatives on FIAT element.
+      double *derivatives = new double[num_derivatives];
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        derivatives[r] = 0.000000000000000;
+      }// end loop over 'r'
+      
+      // Declare derivative matrix (of polynomial basis).
+      double dmats[3][3] = \
+      {{1.000000000000000, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 1.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 1.000000000000000}};
+      
+      // Declare (auxiliary) derivative matrix (of polynomial basis).
+      double dmats_old[3][3] = \
+      {{1.000000000000000, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 1.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 1.000000000000000}};
+      
+      // Loop possible derivatives.
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        // Resetting dmats values to compute next derivative.
+        for (unsigned int t = 0; t < 3; t++)
+        {
+          for (unsigned int u = 0; u < 3; u++)
+          {
+            dmats[t][u] = 0.000000000000000;
+            if (t == u)
+            {
+            dmats[t][u] = 1.000000000000000;
+            }
+            
+          }// end loop over 'u'
+        }// end loop over 't'
+        
+        // Looping derivative order to generate dmats.
+        for (unsigned int s = 0; s < n; s++)
+        {
+          // Updating dmats_old with new values and resetting dmats.
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              dmats_old[t][u] = dmats[t][u];
+              dmats[t][u] = 0.000000000000000;
+            }// end loop over 'u'
+          }// end loop over 't'
+          
+          // Update dmats using an inner product.
+          if (combinations[r][s] == 0)
+          {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              for (unsigned int tu = 0; tu < 3; tu++)
+              {
+                dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u];
+              }// end loop over 'tu'
+            }// end loop over 'u'
+          }// end loop over 't'
+          }
+          
+          if (combinations[r][s] == 1)
+          {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              for (unsigned int tu = 0; tu < 3; tu++)
+              {
+                dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u];
+              }// end loop over 'tu'
+            }// end loop over 'u'
+          }// end loop over 't'
+          }
+          
+        }// end loop over 's'
+        for (unsigned int s = 0; s < 3; s++)
+        {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t];
+          }// end loop over 't'
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Transform derivatives back to physical element
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        for (unsigned int s = 0; s < num_derivatives; s++)
+        {
+          values[r] += transform[r][s]*derivatives[s];
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Delete pointer to array of derivatives on FIAT element
+      delete [] derivatives;
+      
+      // Delete pointer to array of combinations of derivatives and transform
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        delete [] combinations[r];
+      }// end loop over 'r'
+      delete [] combinations;
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        delete [] transform[r];
+      }// end loop over 'r'
+      delete [] transform;
+        break;
+      }
+    case 2:
+      {
+        
+      // Array of basisvalues.
+      double basisvalues[3] = {0.000000000000000, 0.000000000000000, 0.000000000000000};
+      
+      // Declare helper variables.
+      unsigned int rr = 0;
+      unsigned int ss = 0;
+      double tmp0 = (1.000000000000000 + Y + 2.000000000000000*X)/2.000000000000000;
+      
+      // Compute basisvalues.
+      basisvalues[0] = 1.000000000000000;
+      basisvalues[1] = tmp0;
+      for (unsigned int r = 0; r < 1; r++)
+      {
+        rr = (r + 1)*(r + 1 + 1)/2 + 1;
+        ss = r*(r + 1)/2;
+        basisvalues[rr] = basisvalues[ss]*(0.500000000000000 + r + Y*(1.500000000000000 + r));
+      }// end loop over 'r'
+      for (unsigned int r = 0; r < 2; r++)
+      {
+        for (unsigned int s = 0; s < 2 - r; s++)
+        {
+          rr = (r + s)*(r + s + 1)/2 + s;
+          basisvalues[rr] *= std::sqrt((0.500000000000000 + r)*(1.000000000000000 + r + s));
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Table(s) of coefficients.
+      static const double coefficients0[3] = \
+      {0.471404520791032, 0.000000000000000, 0.333333333333333};
+      
+      // Tables of derivatives of the polynomial base (transpose).
+      static const double dmats0[3][3] = \
+      {{0.000000000000000, 0.000000000000000, 0.000000000000000},
+      {4.898979485566356, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 0.000000000000000}};
+      
+      static const double dmats1[3][3] = \
+      {{0.000000000000000, 0.000000000000000, 0.000000000000000},
+      {2.449489742783178, 0.000000000000000, 0.000000000000000},
+      {4.242640687119285, 0.000000000000000, 0.000000000000000}};
+      
+      // Compute reference derivatives.
+      // Declare pointer to array of derivatives on FIAT element.
+      double *derivatives = new double[num_derivatives];
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        derivatives[r] = 0.000000000000000;
+      }// end loop over 'r'
+      
+      // Declare derivative matrix (of polynomial basis).
+      double dmats[3][3] = \
+      {{1.000000000000000, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 1.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 1.000000000000000}};
+      
+      // Declare (auxiliary) derivative matrix (of polynomial basis).
+      double dmats_old[3][3] = \
+      {{1.000000000000000, 0.000000000000000, 0.000000000000000},
+      {0.000000000000000, 1.000000000000000, 0.000000000000000},
+      {0.000000000000000, 0.000000000000000, 1.000000000000000}};
+      
+      // Loop possible derivatives.
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        // Resetting dmats values to compute next derivative.
+        for (unsigned int t = 0; t < 3; t++)
+        {
+          for (unsigned int u = 0; u < 3; u++)
+          {
+            dmats[t][u] = 0.000000000000000;
+            if (t == u)
+            {
+            dmats[t][u] = 1.000000000000000;
+            }
+            
+          }// end loop over 'u'
+        }// end loop over 't'
+        
+        // Looping derivative order to generate dmats.
+        for (unsigned int s = 0; s < n; s++)
+        {
+          // Updating dmats_old with new values and resetting dmats.
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              dmats_old[t][u] = dmats[t][u];
+              dmats[t][u] = 0.000000000000000;
+            }// end loop over 'u'
+          }// end loop over 't'
+          
+          // Update dmats using an inner product.
+          if (combinations[r][s] == 0)
+          {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              for (unsigned int tu = 0; tu < 3; tu++)
+              {
+                dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u];
+              }// end loop over 'tu'
+            }// end loop over 'u'
+          }// end loop over 't'
+          }
+          
+          if (combinations[r][s] == 1)
+          {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            for (unsigned int u = 0; u < 3; u++)
+            {
+              for (unsigned int tu = 0; tu < 3; tu++)
+              {
+                dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u];
+              }// end loop over 'tu'
+            }// end loop over 'u'
+          }// end loop over 't'
+          }
+          
+        }// end loop over 's'
+        for (unsigned int s = 0; s < 3; s++)
+        {
+          for (unsigned int t = 0; t < 3; t++)
+          {
+            derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t];
+          }// end loop over 't'
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Transform derivatives back to physical element
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        for (unsigned int s = 0; s < num_derivatives; s++)
+        {
+          values[r] += transform[r][s]*derivatives[s];
+        }// end loop over 's'
+      }// end loop over 'r'
+      
+      // Delete pointer to array of derivatives on FIAT element
+      delete [] derivatives;
+      
+      // Delete pointer to array of combinations of derivatives and transform
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        delete [] combinations[r];
+      }// end loop over 'r'
+      delete [] combinations;
+      for (unsigned int r = 0; r < num_derivatives; r++)
+      {
+        delete [] transform[r];
+      }// end loop over 'r'
+      delete [] transform;
+        break;
+      }
+    }
+    
+  }
+
+  /// Evaluate order n derivatives of all basis functions at given point in cell
+  virtual void evaluate_basis_derivatives_all(unsigned int n,
+                                              double* values,
+                                              const double* coordinates,
+                                              const ufc::cell& c) const
+  {
+    // Compute number of derivatives.
+    unsigned int num_derivatives = 1;
+    for (unsigned int r = 0; r < n; r++)
+    {
+      num_derivatives *= 2;
+    }// end loop over 'r'
+    
+    // Helper variable to hold values of a single dof.
+    double *dof_values = new double[num_derivatives];
+    for (unsigned int r = 0; r < num_derivatives; r++)
+    {
+      dof_values[r] = 0.000000000000000;
+    }// end loop over 'r'
+    
+    // Loop dofs and call evaluate_basis_derivatives.
+    for (unsigned int r = 0; r < 3; r++)
+    {
+      evaluate_basis_derivatives(r, n, dof_values, coordinates, c);
+      for (unsigned int s = 0; s < num_derivatives; s++)
+      {
+        values[r*num_derivatives + s] = dof_values[s];
+      }// end loop over 's'
+    }// end loop over 'r'
+    
+    // Delete pointer.
+    delete [] dof_values;
+  }
+
+  /// Evaluate linear functional for dof i on the function f
+  virtual double evaluate_dof(unsigned int i,
+                              const ufc::function& f,
+                              const ufc::cell& c) const
+  {
+    // Declare variables for result of evaluation.
+    double vals[1];
+    
+    // Declare variable for physical coordinates.
+    double y[2];
+    const double * const * x = c.coordinates;
+    switch (i)
+    {
+    case 0:
+      {
+        y[0] = x[0][0];
+      y[1] = x[0][1];
+      f.evaluate(vals, y, c);
+      return vals[0];
+        break;
+      }
+    case 1:
+      {
+        y[0] = x[1][0];
+      y[1] = x[1][1];
+      f.evaluate(vals, y, c);
+      return vals[0];
+        break;
+      }
+    case 2:
+      {
+        y[0] = x[2][0];
+      y[1] = x[2][1];
+      f.evaluate(vals, y, c);
+      return vals[0];
+        break;
+      }
+    }
+    
+    return 0.000000000000000;
+  }
+
+  /// Evaluate linear functionals for all dofs on the function f
+  virtual void evaluate_dofs(double* values,
+                             const ufc::function& f,
+                             const ufc::cell& c) const
+  {
+    // Declare variables for result of evaluation.
+    double vals[1];
+    
+    // Declare variable for physical coordinates.
+    double y[2];
+    const double * const * x = c.coordinates;
+    y[0] = x[0][0];
+    y[1] = x[0][1];
+    f.evaluate(vals, y, c);
+    values[0] = vals[0];
+    y[0] = x[1][0];
+    y[1] = x[1][1];
+    f.evaluate(vals, y, c);
+    values[1] = vals[0];
+    y[0] = x[2][0];
+    y[1] = x[2][1];
+    f.evaluate(vals, y, c);
+    values[2] = vals[0];
+  }
+
+  /// Interpolate vertex values from dof values
+  virtual void interpolate_vertex_values(double* vertex_values,
+                                         const double* dof_values,
+                                         const ufc::cell& c) const
+  {
+    // Evaluate function and change variables
+    vertex_values[0] = dof_values[0];
+    vertex_values[1] = dof_values[1];
+    vertex_values[2] = dof_values[2];
+  }
+
+  /// Return the number of sub elements (for a mixed element)
+  virtual unsigned int num_sub_elements() const
+  {
+    return 0;
+  }
+
+  /// Create a new finite element for sub element i (for a mixed element)
+  virtual ufc::finite_element* create_sub_element(unsigned int i) const
+  {
+    return 0;
+  }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p1_dof_map_0: public ufc::dof_map
+{
+private:
+
+  unsigned int _global_dimension;
+public:
+
+  /// Constructor
+  p1_dof_map_0() : ufc::dof_map()
+  {
+    _global_dimension = 0;
+  }
+
+  /// Destructor
+  virtual ~p1_dof_map_0()
+  {
+    // Do nothing
+  }
+
+  /// Return a string identifying the dof map
+  virtual const char* signature() const
+  {
+    return "FFC dofmap for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+  }
+
+  /// Return true iff mesh entities of topological dimension d are needed
+  virtual bool needs_mesh_entities(unsigned int d) const
+  {
+    switch (d)
+    {
+    case 0:
+      {
+        return true;
+        break;
+      }
+    case 1:
+      {
+        return false;
+        break;
+      }
+    case 2:
+      {
+        return false;
+        break;
+      }
+    }
+    
+    return false;
+  }
+
+  /// Initialize dof map for mesh (return true iff init_cell() is needed)
+  virtual bool init_mesh(const ufc::mesh& m)
+  {
+    _global_dimension = m.num_entities[0];
+    return false;
+  }
+
+  /// Initialize dof map for given cell
+  virtual void init_cell(const ufc::mesh& m,
+                         const ufc::cell& c)
+  {
+    // Do nothing
+  }
+
+  /// Finish initialization of dof map for cells
+  virtual void init_cell_finalize()
+  {
+    // Do nothing
+  }
+
+  /// Return the dimension of the global finite element function space
+  virtual unsigned int global_dimension() const
+  {
+    return _global_dimension;
+  }
+
+  /// Return the dimension of the local finite element function space for a cell
+  virtual unsigned int local_dimension(const ufc::cell& c) const
+  {
+    return 3;
+  }
+
+  /// Return the maximum dimension of the local finite element function space
+  virtual unsigned int max_local_dimension() const
+  {
+    return 3;
+  }
+
+  // Return the geometric dimension of the coordinates this dof map provides
+  virtual unsigned int geometric_dimension() const
+  {
+    return 2;
+  }
+
+  /// Return the number of dofs on each cell facet
+  virtual unsigned int num_facet_dofs() const
+  {
+    return 2;
+  }
+
+  /// Return the number of dofs associated with each cell entity of dimension d
+  virtual unsigned int num_entity_dofs(unsigned int d) const
+  {
+    switch (d)
+    {
+    case 0:
+      {
+        return 1;
+        break;
+      }
+    case 1:
+      {
+        return 0;
+        break;
+      }
+    case 2:
+      {
+        return 0;
+        break;
+      }
+    }
+    
+    return 0;
+  }
+
+  /// Tabulate the local-to-global mapping of dofs on a cell
+  virtual void tabulate_dofs(unsigned int* dofs,
+                             const ufc::mesh& m,
+                             const ufc::cell& c) const
+  {
+    dofs[0] = c.entity_indices[0][0];
+    dofs[1] = c.entity_indices[0][1];
+    dofs[2] = c.entity_indices[0][2];
+  }
+
+  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
+  virtual void tabulate_facet_dofs(unsigned int* dofs,
+                                   unsigned int facet) const
+  {
+    switch (facet)
+    {
+    case 0:
+      {
+        dofs[0] = 1;
+      dofs[1] = 2;
+        break;
+      }
+    case 1:
+      {
+        dofs[0] = 0;
+      dofs[1] = 2;
+        break;
+      }
+    case 2:
+      {
+        dofs[0] = 0;
+      dofs[1] = 1;
+        break;
+      }
+    }
+    
+  }
+
+  /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+  virtual void tabulate_entity_dofs(unsigned int* dofs,
+                                    unsigned int d, unsigned int i) const
+  {
+    if (d > 2)
+    {
+    throw std::runtime_error("d is larger than dimension (2)");
+    }
+    
+    switch (d)
+    {
+    case 0:
+      {
+        if (i > 2)
+      {
+      throw std::runtime_error("i is larger than number of entities (2)");
+      }
+      
+      switch (i)
+      {
+      case 0:
+        {
+          dofs[0] = 0;
+          break;
+        }
+      case 1:
+        {
+          dofs[0] = 1;
+          break;
+        }
+      case 2:
+        {
+          dofs[0] = 2;
+          break;
+        }
+      }
+      
+        break;
+      }
+    case 1:
+      {
+        
+        break;
+      }
+    case 2:
+      {
+        
+        break;
+      }
+    }
+    
+  }
+
+  /// Tabulate the coordinates of all dofs on a cell
+  virtual void tabulate_coordinates(double** coordinates,
+                                    const ufc::cell& c) const
+  {
+    const double * const * x = c.coordinates;
+    
+    coordinates[0][0] = x[0][0];
+    coordinates[0][1] = x[0][1];
+    coordinates[1][0] = x[1][0];
+    coordinates[1][1] = x[1][1];
+    coordinates[2][0] = x[2][0];
+    coordinates[2][1] = x[2][1];
+  }
+
+  /// Return the number of sub dof maps (for a mixed element)
+  virtual unsigned int num_sub_dof_maps() const
+  {
+    return 0;
+  }
+
+  /// Create a new dof_map for sub dof map i (for a mixed element)
+  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
+  {
+    return 0;
+  }
+
+};
+
+// DOLFIN wrappers
+
+// Standard library includes
+#include <string>
+
+// DOLFIN includes
+#include <dolfin/common/NoDeleter.h>
+#include <dolfin/fem/FiniteElement.h>
+#include <dolfin/fem/DofMap.h>
+#include <dolfin/fem/Form.h>
+#include <dolfin/function/FunctionSpace.h>
+#include <dolfin/function/GenericFunction.h>
+#include <dolfin/function/CoefficientAssigner.h>
+
+namespace P1
+{
+
+class FunctionSpace: public dolfin::FunctionSpace
+{
+public:
+
+  FunctionSpace(const dolfin::Mesh& mesh):
+    dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+                          boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_finite_element_0()))),
+                          boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_dof_map_0()), mesh)))
+  {
+    // Do nothing
+  }
+
+  FunctionSpace(dolfin::Mesh& mesh):
+    dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+                          boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_finite_element_0()))),
+                          boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_dof_map_0()), mesh)))
+  {
+    // Do nothing
+  }
+
+  FunctionSpace(boost::shared_ptr<dolfin::Mesh> mesh):
+    dolfin::FunctionSpace(mesh,
+                          boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_finite_element_0()))),
+                          boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_dof_map_0()), *mesh)))
+  {
+      // Do nothing
+  }
+
+  FunctionSpace(boost::shared_ptr<const dolfin::Mesh> mesh):
+    dolfin::FunctionSpace(mesh,
+                          boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_finite_element_0()))),
+                          boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_dof_map_0()), *mesh)))
+  {
+      // Do nothing
+  }
+
+  ~FunctionSpace()
+  {
+  }
+
+};
+
+}
+
+#endif

=== added file 'bench/function/evaluation/cpp/P1.ufl'
--- bench/function/evaluation/cpp/P1.ufl	1970-01-01 00:00:00 +0000
+++ bench/function/evaluation/cpp/P1.ufl	2010-06-10 21:06:35 +0000
@@ -0,0 +1,13 @@
+# Copyright (C) 2009 Garth N. Wells.
+# Licensed under the GNU LGPL Version 2.1.
+#
+# First added:  2009-06-18
+# Last changed: 
+#
+# The bilinear form a(v, u) and linear form L(v) for
+# projection onto piecewise quadratics.
+#
+# Compile this form with FFC: ffc -l dolfin P1.ufl
+
+element = FiniteElement("Lagrange", "triangle", 1)
+

=== added file 'bench/function/evaluation/cpp/SConstruct'
--- bench/function/evaluation/cpp/SConstruct	1970-01-01 00:00:00 +0000
+++ bench/function/evaluation/cpp/SConstruct	2010-06-10 21:06:35 +0000
@@ -0,0 +1,14 @@
+import os, commands
+
+# Get compiler from pkg-config
+compiler = commands.getoutput('pkg-config --variable=compiler dolfin')
+
+# Create a SCons Environment based on the main os environment
+env = Environment(ENV=os.environ, CXX=compiler)
+
+# Get compiler flags from pkg-config
+env.ParseConfig('pkg-config --cflags --libs dolfin')
+
+# Program name
+env.Program('bench', 'main.cpp')
+

=== added file 'bench/function/evaluation/cpp/main.cpp'
--- bench/function/evaluation/cpp/main.cpp	1970-01-01 00:00:00 +0000
+++ bench/function/evaluation/cpp/main.cpp	2010-06-12 09:59:30 +0000
@@ -0,0 +1,86 @@
+// =====================================================================================
+//
+// Copyright (C) 2010-06-10  André Massing
+// Licensed under the GNU LGPL Version 2.1.
+//
+// Modified by André Massing, 2010
+//
+// First added:  2010-06-10
+// Last changed: 2010-06-12
+// 
+//Author:  André Massing (am), massing@xxxxxxxxx
+//Company:  Simula Research Laboratory, Fornebu, Norway
+//
+//Description: Benchmark for the evaluations of functions at arbitrary points.
+//=====================================================================================
+
+#include <dolfin.h>
+#include "P1.h"
+
+using namespace dolfin;
+using dolfin::uint;
+
+class F : public Expression
+{
+public:
+
+  void eval(Array<double>& values, const Array<double>& x) const
+  {
+    values[0] = sin(3.0*x[0])*sin(3.0*x[1])*sin(3.0*x[2]);
+  }
+
+};
+
+#ifdef HAS_CGAL
+
+int main(int argc, char* argv[])
+{
+  not_working_in_parallel("Function evalutation benchmark");
+  
+  const uint mesh_max_size = 32;
+  const uint num_points  = 10000000;
+  
+  //starting timing
+  tic();  
+  for (uint N = 10; N < mesh_max_size; N += 2)
+  {
+    UnitCube mesh(N, N, N);
+
+    P1::FunctionSpace V0(mesh);
+    Function f0(V0);
+    F f;
+    f0.interpolate(f);
+
+    Array<double> X(3);
+    Array<double> value(1);
+
+    //Initialize random generator generator (produces same sequence each test).
+    srand(1);
+
+    for (uint i = 1; i <= num_points; ++i)
+    {
+      X[0] = std::rand()/static_cast<double>(RAND_MAX);
+      X[1] = std::rand()/static_cast<double>(RAND_MAX);
+      X[2] = std::rand()/static_cast<double>(RAND_MAX);
+
+      f.eval(value, X);
+    }
+
+    //use X variable.
+    info("x = %.12e\ty = %.12e\tz = %.12e\tf(x) = %.12e",X[0],X[1],X[2],value[0]);
+  }
+  info("BENCH  %g",toc()); 
+
+return 0;
+
+}
+
+#elif
+
+int main()
+{
+  info("DOLFIN must be compiled with CGAL to run function eval benchmark.");
+  return 0;
+}
+
+#endif

=== modified file 'dolfin/common/timing.cpp'
--- dolfin/common/timing.cpp	2010-05-03 07:34:12 +0000
+++ dolfin/common/timing.cpp	2010-06-11 12:00:11 +0000
@@ -2,11 +2,12 @@
 // Licensed under the GNU LGPL Version 2.1.
 //
 // First added:  2003-12-21
-// Last changed: 2010-05-03
+// Last changed: 2010-06-11
 
 #include <ctime>
 #include <dolfin/log/dolfin_log.h>
 #include "timing.h"
+#include <boost/timer.hpp>  
 
 namespace dolfin
 {

=== modified file 'dolfin/mesh/IntersectionOperatorImplementation.h'
--- dolfin/mesh/IntersectionOperatorImplementation.h	2010-03-03 11:48:38 +0000
+++ dolfin/mesh/IntersectionOperatorImplementation.h	2010-06-10 21:06:35 +0000
@@ -4,7 +4,7 @@
 // Modified by Johannes Ring, 2009.
 //
 // First added:  2009-09-11
-// Last changed: 2010-03-03
+// Last changed: 2010-06-08
 
 #ifndef __INTERSECTIONOPERATORIMPLEMENTATION_H
 #define __INTERSECTIONOPERATORIMPLEMENTATION_H

# Begin bundle
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
AZMEnvNzBq5v8VyvJX3mLz8lxwJ68IkomT0emejlvu8Ov5BWy9nj7PUTs7RlfmzmvvjK4J8HUd5h
eL9ibLZ8Uw0Y36HQwwwoZVKeKplsmJ+CeCZLZNk0TYnfHp5jwTmXM5LztDVUbvDvT6Pr7J7X0l3L
+67vVyqXYYnuJ7t06J8znsnNOpY+KbDkniOpdhhbHI2ThNxs8i6J47pw4emkzHQc5c03TZOFwjdO
19nbqMTZO559U6+tN0+h4DYbiaTo8ExWmk7+JcnZO4uw47MbnJOBum9wnBcS2J4OTSYmjtidRylw
mncnI5HcdnbY5F1VwnVOqcHVOi7sTqTsc+bzeDzh9e9Gl8EssKsdclfXSmLLnng6qs53Skqqw5nl
O+uUxUUrX0UEmxG23v5b3y9zs6HU0WytjTmm6cUnyTmmyYmk6vpYx0Tovie5OieCaTuO/mnJNXN7
02Tv604wuqfMOqdNlbs7Dn2HR0THBjSdB7HCfQ7Jyd66J17ObrjtgruR86dB2T5OErueIrn3us68
JuOqfPbtbeDrz703o8HU97hv1S8a0O93J1TiXZpOrhNDY257pojWzMyUY2MEVzaFUXxgZIqThqao
sjAzO7NFcuPFFzAtejcjBGt1XD4vPwTqnkdl2dyYcLcttYnN8nS9vp2tqk+ek3e5XsunXTPD3aY7
nxt/G737z/XevlfBh2uWShdQi6tt2ExVojmipgjCYoTwiwmSzSdUw8k9h5e/cuktNI9z0cNKmCL8
0Xt1+/UlyKsznijg1yFUYRNJ1V2TkdE3HfwnIneOR7+iabhubeUvEupO5ck4OSc2JwniMd+vzcJ1
ToO9Nk2TsdybHLH4+XVOydFzXTqnDsnIneXW7u3cOTw1U7qZJkaYZo2dnDw9WbjEwc8kbkc3M2Rz
jpQx2c3q871Lzq1U+c36uzHydXtad3Dd7Xc/r9zo8UTTyYImPkqwGnlIvtdyWtLiSceOWPXS8nkO
aexl1TE2O5L5J1TvTSb9Y96o9Hz/PunZPGnemJ4Yj5O/kmyebWttkbJ5W6YaNl8i8ExNj1DkmJoc
J83ZOacw6DuTnumPMeDhzOjc6J7dJuTY8Xy8ngnknYndLyl2NpYvHTyqc00nS597omk706ptrSeX
CeB3J3pzTku5XeneXqde6nNMTn08tLSthu5jBhpm7xvhY+c7OWrB4V6OKjTlvy4Ke6WOicReN2Pd
dW4hxU7yrbjkeJ7E6tJpMtGHgngm6eyjvlYd6rdNk2O8ubROaZsnA1TguWJzTapdXcm3tTdTpm6Z
1xO7sTnHVOq5OjZb8ucrdN0xOacW6W0urmcGN07vN07+ialzTuHedk6pyLYnJ1bYnM7ydzqmetyK
e7sXVPK704TulwnBd25TsneOZHcbObx8d006jdPY8h5p258KdxjG3XhpFGWCxijFrga7m+yOGETL
cojgjbBG46mq9FVTci5FRxYzyzlwpJLOw3uvFR1zr2fWw56f+kt19lduUcMr+nXhVS28Rl19rXG8
j8iOZyT/M4dVMTbo9nieKd7qmkzg2TUtJzTbep4p4l07fXbuydydyajouJeO5HejPE12vVM0bLka
5ove5167GdZa7J1TZNuidHvd+7zTcdTxbpzTwThOZyTsnRMTPHkMYThOic90zE7qbpwmHBcvBqDm
nJzcxkurS2Td4ufcnBdxaOydU6SXjPNG7ElTc0mk752oWd5gwYceOr07nvJs2UIpHS1qKJATwWkB
HXzFhsYUYU5Fw1CnGwMBgg0ncnuTdNr504bMTjsqzNuZyTyJk7HcjZFwwN6NWu8zaIvWKrIsq4OE
7+twnc27HewawnA6pzdE7MRoOxmbIyRidjmrub0YI8NImWxojzYxOadU9jm8uycLp093u1Oo3RzT
0TuT1uTvc31DzOsvJPBOzul16J8F5uDZ4Jwmw5Jrs6HZOW8tk6HqdFbL8GHNntevRRmjBY60VRki
9vLxecJidk83CcnJ0eLq7pdE6y9cufTyundLeEueBxZt3atlvvpTZhwblxPK3nEtSiOFEX713Kt+
tWbusjIs5ryOjRGyNxN6Nk6psnc5J4JhseCd5dU6vNyPEuFyMTobvFNnbC7u5OabDRNJwnXqXe6s
83c2TV4J2TuMTwd0tJvcm7dNNls92k5JxaM6OR17mOqc0xO40ae3WxOhw6jdN5bS06Ozh4mDfmMN
k0N3VO5N1xsu91uZ1d7g7hwTm1yblyT4fDrU7c06uqby23TqngNi2JwmxunEu93PrL18ybm6banN
F6NxniizDcbbM0XIvIwRVmRUdU7pgSkr3GDTrmuvX1aLMHZucPEwXu/moqzu5i5LKfKOpg7WTZua
Nzk3M2bOUlFVaKq1UqpVWtr8cc8882bNVVVWtfjc28+ZR/AcjtXLlHzmEv9lYuZPsPDJsVKN3KVH
NDy8tB7irutGLTxI0lptxxl8ROvi5M2i7GmoyyOxzarsbe3ZvTlOTYbtSsbHRk1uNVVdsrjhja7G
fP8xKH5q8rNLfm7D+9++XlWCw/AsxwXK0IsmC5YvPMxsZL8NjRxrRzc28tqaZDdzbvM5HJi4J1gb
Syo4t0uTjMzk17PL18LkVYTBO0NLtLUtFdQyFlpPhKmWRquabSahYMCdAj4j4ucjvHMbnc36Lc3N
6qqqp25tjd79vf5+fnul2KvKO6XiqeaWE8HlzeXR38NxOQnMnV1lu86jVR05eHSuToxcTJ8SrvYz
LTfRiXXYqrNamMpU0ztFVzubMxswxs0/nZC3JkK3Z1zODZttmYM0S7LuJqWibE5LCcGm60GiZRac
paTe+tU3ltSNqqgKFZCBCYSYVZhJgWL6aKW6P0NVafYfK3TdlkbhhSX4UyEViZE8dhLL7VaJhIi4
I0IwDVIP5YFdCMKmkdkcRB7HO+NkhJDedkhmYZGM9lCipctwE8VwQ2+/9f2T1DuvOmK8iPNNL9Hu
TtwYthyGGGGH+F77si/3X/G/zf8Ev+30U7CL949nORHa7J5awtTST45/rc/cPOuAQQGHtGe8ScWB
Q5/gwoXp87Dph4OUl7nRpTyGmDr/e8NC4U8/F/92Hc2FeYPzIf1NHvkG9XSByIDHC10eubh8JuND
k0/usu1hsxe03aXhUfp0cMd3tCYPZCD7hBgQYQHzgIV9shiD/nu2NP+cYdX+w0J5X/QjS9Qw+2Y8
NGnoaTxleS79MPkrspTw2WWUpazKfivp8k2loJjua8ey0YTGyrBH0P9777Z4YV120XvI8Mjw+X+f
+dVuAD9ZB8UEEh4iiiiiijFU4Ro0EQRBge383fdR2iFhGV2ViEiUIhIgj0gTQCYCeqJoTBPVE2Qc
gggOciKKKKKMR4QLo0EQUFgcNtBoIUpGJXSGQEQUgUBEFARk22NNttzZuZuaZTMRjIv/Jq5rctJ0
trV0sF2oOXJNmmn9Ri3ebvY1aTcLhMTdMFYmWWRTcVsmoLSYnUmyaVV1JiTlJqTEjpCujyXgk6Ti
YrFYxkytmtf3a1hhs3l/rSyW5uYMGorYR0hpCZhhmdjBiEdI+yYbEQRzXp61rWta1rFDBhSGBIeA
jmtuYgSwsLCxLG+J4npr0aFF737ECjgIgTGNc5HODgpIBbLFixYsJyW7vS/1EODiZm+6p4y/nlpL
zSwmhOOXLC3aNi2ERERVVVVTEWQugzVOiAYnfuQ2TsuBW1smJ0TgVtdLisHKKKmioTA6e11dXa7X
a4nE4jgmGDFhmFFGGGNFGGGGCplUUTVVJgQcePHjx48eJznEwIIcMSMKIxYzTTUxhmM02L0Tyepp
7HpUekvSSvRL2H8GzGJg/yf82FjGMLGmjRogIhIgI9g7PVXhfCHlByDygD6z0jgewHxxNxkRY7ab
cxmQRBzGB+I5cqoiqsNjY+SRhhgaIBj2joQ0B3+Y0aOJx41BBXoB1Bw5oCiDncwfa5I4oq+s+0g2
YOLkUgO1pmcY0eohZhnV1T0d7SbOjGMOTvODExjGMYtm5hvypAohL19Jmh+OUR0dHi8eD1Pm+Jc8
Xg1Yty9oszs4pZVb6d1nB6m/V8b8uC2D+sfnSyMliX8NDxH771ef1Q9ZlVhdZu290vzK+n9B9/R5
Pou36F1aP40uH7J9Djmfdd1HsX2PFJ7Hekfge+o8byHsWMl4MOGNGNhW7Q2MYxhwXDPAbnX8jw2c
nQV/BetaER0cn9XO8HT0yrh5XgnR+DJYaN7ZUw3Y8XDSyuBpVORwfDkV/3DDHrYNKdFzNF3D37zn
dzf5nUlsylwRxBtss86Tov2tpT+H+h4vA85cl75esRkkXdT0XdC7nxrlbbeTBhqek+J3vVLJabMH
amJejA0wxbGN3iw9hJ0nnUsbOstu/c+xp2G9zo0xB3UKdK51SNjR/1rxfCXC09fFIx/j1H6j9W+J
Pd8T1Pg7PM+upV4+1T4Nhe5RPO14BZI8TJMplJ45MpZJk9RP1wv2QtkviJvLQn8b0a8Nv0/LefIP
i3leKt28k+TpKr7ZYVesxVWGDEsUxkWIsj3iN69jyVXcpb/LcXdB64/zbfkvozmHdfz+69fyf+IO
tVe1jmS9WB3pTBodr6NbeHplGH0bililG98H4e3jJkBQ6W/lWxXVS1Wr/z1Y89kYyMYl6DlMvbw4
o9ZQpBSlAct7ksXHB6vf951qOZXsU81o87+s7um0tFzeT3/rh+HE8pz7K2bL4NwnVbq1dW1UfRcz
DmD8HNW6i/6C+lpVpkvwS+TH3PwY4cPbfX/i28P8dMyXtMSPEO5j7CmxL/i/5P9z0f5v0qr31LlV
7Biv0Ul6pVaT7ygehRD91Ow7zBimj1ZerUaXC5vh8n1tGB89XyYpmVWMrQ0cmzxabGywcqZho1So
adX1N1UX9eLjJcDJKz7ZVWViUPGxmlmZVRc9b53wPW8/KYXPr+71vbo6+U54dXw9A3b0Pa+h9lqw
nGro+nnzdqPdIPVS+JLYjzd7xep7/J3pf5eeed8iv2Lve/GXd1f+z5H3Mftl+2WS+9ktS3PacPtO
lkvHZS4T8JaqGllJgL9sukt5bVOjzOQvi+36Ht/WvEPfV7nR3GBgYeZJo/W2krxl/vS9JfbLJb1G
pbpaRyYfSxjTEwNNmH8RCdZAOwPzDB6w9QiXfySHThjEy7HrEHUrCBoDhlaqwI8w8cwTcjgjppDB
jSWJaMS0lpppVWhpOH62O94NHWuKvkutfezufRe6r9I+D5DR9J/Zs+1h8pcS7pWCN0v37D+ywPtM
Tlc27GxzYcUGPFquMK2S04MdzZLd+ns0cHWXOXKG5uMS0S07Glu3VpviYtho2bGMOEu80bJlOx/e
lp25OIbDvWNHEsS3hjaW7s0tpeHU0OxBzYXlolj7ahVsXnte3BZ8lCpq4szk3WDuw5pbS2S8ZbC2
/r/Y2ekubRe9+st48uVOX4uvJSJMm7dGLJ0evPbWlac6W1qdNNnB5HyNbPatNt/Jm/ZyeTRZfn3L
m93mzud9FIuXSOZaH7U6ZjLpZy1sLnxV7LZHsdnD5NyOyxzL10aOHNo5mPZ7Hc+ud2zk5lHmG+si
3Yu4Op6HeYv4ZJDyNJZ6JhyfcG26lQ5nt4XN7WWTqR6x4saef67udxuoq5zt49LT8UxbTF5e7yvI
owhPhCMUqoV2nKfD17+GXSejFWX+/t+qXJo84PkdqpKlBRSLCkRdpQDzAWCPpdYg+8EJ8J+wPOJf
yv6PNe+A8k90n5sPov4MvQqL8nnf4PwUx6X3xV1sg/OxWiz8nvOy+EYYfvl5xyOiWYS6I+a45951
cNncd12Ki9RyPMPtl1W1+eoyWHqVYcscMeXH6drcXK90Wx3buVCm0epcjTvWWH+2xG147mzvc3vY
ew3W0MMZVwalpLg0NNmNpfU1LhiXPuORwVjY3I0GiIIYiGWDFDARyXNLT9aW6abyxgLjY2qsNNGH
AiDATWgwVgzDWiInA1Fo1GliiiiiiiNkZAkZFGRwRgvOub9vZYqxPcl69ZDKyWuNXI2Or1K+ZaaM
PMmHjItHN7sOEuYncYsFjGUfA+NL+ppYxP7/9GNV8c73OT3CPF6B5ObeW1TxvWdT9VoLzNSyxKXv
bIywG/p71tXc8aZEtXF9G3re0q9r5X0MVnRV9h87l8DF82azbw+zo5dCQwavmo8hedijyGyqdOL4
mlANyrsfNxV+h1+pc4uDn2aq2CbHmr2pbzqEz6Z/Sn6i6l9lUejudDDdXuVur6271D5cvF4PCbT6
vrP7WmNGmJMZSYMkmLRLTKT+MTLC80sT+5Vlkch8wyl+arDJYyUwelo7P9O5eBJ61e1zt1MPr+K2
L0OsmMxkqf9bWv7DK/TgXce76ZX2bj6VMrslsv0c+1jdOCx/MfSaYcQI87k6r6DHR2+iHufTaxhj
RktYteExNslfUzY2PvL4Jfgu7iHRzHPCtLUaWTCNL8F+bS/8WQnDz9aWyN0w3X4brbr+NpeqV8b9
0OS+9Vj7TD6zGl/55aDoe9L12Un66jYtfSrB8Zej3S0cEt2l8GzVbNWNzyZLZxf5Xwly2CfPcPlF
9V9VLzP5W17nTyCdEd15fkV+l+g/RL+jwOdXVmM2dTtPS9cCNJ4MFi/vl7m7kuiTA+X+rdFyd/Vk
fTpZvZTVQ9uPmOxJ3STxK6H56Ocua9ow8OPZmdn9iPCj0l6VGtPUa0v/ByfsOTja5NQvHD5P/c7x
4q0LCtUewg+hB5sIZC/GAgO2RqFiUVW0i0fjj9n48+D/Ufx36rtdF5euyWWGEwsUIGCZGYiIAgWW
FB7Z5Y/2pfieuxBzfMroPrbDST6D53wc19rKuEKcN44hiDBYXhV9j5WpPKRTCX5JlUjSr5G46OuB
gYpnpnYCYjz3vngH8IbPeI5gOl7faJHNNjul9dgbvLlfxl9qR3LreB+NHTy6PU9CeadoaMpMX6jV
Whg2YNaY0K3aU5YtsWbjc0Ny8ZcWlcFurY8qLk9zrVHospuOdgyI9yC9xh/ImGMSGlhLRd44bt6m
8u3eF/msYMpYmKemTecSmpF6O1Uf/txLwenNXPZuw9Dqym5MMYYwxmAw+u0a6tHjbOsrxDoaMHex
fZ0dzYqLydlWOpWMBpidja0oegMIDTfnUeyWORqjGlxi2a5s3aNWzV/2scl8S3lwwHKUMYcekrL8
b/H8rV+v63D1PnaWmFhWJj7lr2dHRMjUxqxqY0zX5rwXsZethzVfmhDHZjzDiSejx9srNF7lrEnt
B9WGYTMiNdJ4rOzD3n5zQxerds7XK52neasqPI08WXhcxo4fjYtt74hXSwUN+tWD/6dNVJ2akunN
N9zJjfTQYwZYMBppqYY2ZsPJo4N2pvg4XdqbywwZDfkNRwmGMyhlbVATFHMFBA4JUJCykqMFqTVR
9zDbFjG0vpZtKT6TnS6WVsDrSNlbFRYYwG1GPmb20t7d/ksbK7udKh0Xa9stnRLkcPYGSYGKuU2m
MpJ0qwwY+q6tP/tgTzXB4XO3l/Ei9x+yo3d1GXOyC7bhFcEKtSWk2iGiNzGLMViYYwVsZCq1KxYT
MKbMtSXVlmNHCwjdkbcGNKsySzEcl+8+Zoi9snfWqXFyo6NPxeq7fZ7vb6/ipfkYj/qRirg4VNDL
/yYaX/SfYH3K2dTYn6W6+z+HFX+LdUf3e6qT8wfalqDQ80YlaT+izSk766v5Iv2SrTsnzGE2nuPu
gY6VR7m8TTmYxetzknznuqND1WLCmSxV8oeUGVhhTJhXTr1Syw7lij0XSumW7ktsQtklasYY5sft
P3nQqLEtiTaRz9UpLuatS8HqdTtbR6MykVmI5LT1YTryh0JPlzQ/nYqs9j6Ohc3/w3S6SMeNGvdK
U5clUXgk9T6jkIAkERh5xhYQjrAF8PgrFT+HFZi0Jvvmb7rMW4J8bCrk54qx3wPSIiSEZ5t/Iw8L
Awh7HoiO6vEft9D63oq9H/n4mrvo6jUth5N39Djq2ovIxjM9k6NqjjpyltLk+sX1Y8i/bw4eV6Xp
Xg5jsZcVvXlTv2rqpXM4PfO4JfZpw9SnF6tO7J1Tbut/TsltQphRO5JV6NFW8moGSZEsiLskrFKc
cCx6Ga0ZNE1o1LBlWWRLpd6ItpsucLihkmUMJymKn8zYmlKdTk5VuTpqf0nsOOap6iNd6XZLBMhi
WSpsbUd38rH6r33p1cLHvdKv4SxVfxGdGeUn5MXfo8aR4TaRZLawh8j+LDokdH66+o+t7HQj0dWP
ST1nJ7vOLnA3NiRoPCPx/YMB1OMUhEHeMDD1Uu1yuVXU6jwSyk15pjHw8LS83i4oU2Vcl7YLYx7I
LNnL/tOXNX+xj2J3nftfBY8S+tYPoV5T2qn8FTdLcqeT+5LKTDkjWJ3Xp96WyN2WNt0HnL6jB5O2
r3rl9iXTUwMr6j1P3d86GL9LHtYbMPa00d6VMqwq+rKk+4mxiWqDRhMq6NlTLL0fJ1OAY4ni2lwn
g5mn2+Xi5G7HfodDGzBidYZVjInZOpryYtmS8UvyfjUno2cHB1Y0xpjS+5L1JfiJhVhMVMJs4S3l
sJvUnDhgxjGB55PNLFzzMonRLEsS+tu08t3L19icCW6Xk9TUXOPIVMN5EHkMIykUp0CMK6Ek0JFA
BoJHAilIJDTmNNNNNO5KpIyMKEojpGVQxUYJw+dL1KmJYTaTRXi0wd7kg5uVz/d+7pO51MXtkn3P
JbvSXC25Zcu62fod3z+it1XEow7Mhbx8+ZhmfJObTTCPOXyhudKVDZ8X/zRb/BvPUGItjOTzrAeA
wyrDzJF3l90r3XvwzLMHR1HpZXow6y9Evy+4m6X3qnhT50HW+Mvvb1LbGnYh6r171tInHKRtatj5
PyJZd1D6WLhIeRcXMYZFh2Cp0Y9qCR0V33QHJyitXvtJo2l49oHuE2wmoG77JctTLlposXJYtn8U
tm6qt1bjGMVX1GezEhfaxC4oYcORvPugbr3c0tS4YMc9Dugc2kZLG3R5tEbZbX1Nkb8yfGXkJiBu
rddzg7m5bvEnv/BeI4eF/IyVdtrpDaRsdqDxjSWMGJbqw0sMhhsVqWhksqu1uLQsKw3MVyhaeFo0
ZMZbEnXvDCel/z7nW4ZJycqF4ow7/c9xxcci0S5cararndyfP8FzfhtntPRLrLo7Gx1m0jLrFMZI
CAjRigYSSjMQadiNUKfu/jLuS+8mIMJhME+wn2k2JsT6CbE2JhMJsTJJ0ZHcvuH1r/a2bu/xGT4U
adLbF8/K8yPkdJd7JfM82kvJh5y+Dxe59Z8XibrzVeepdRxbDdLCsSxTExZYllRmRJ79I7id5ORP
rE77slsS7ksS3JdEHUcQW5yfRlH/Zr+eV8icCYsLEsJdiWktUGJfb/id6o2SyoxL9ixB9yh6w/k+
+Up86v0PXMlg5AwZRhk6ZUVfk8CsGLBiv+oePztr5t79tFwHV+m8j5HDKE033P35MxGMWJYXW2v0
NLuTH/9YtIw/+TRubDNFU+1LKk2aS1AwmKjRi5Lr7ol+pwr+h4+69mVJ+3T7R8bJevwMP5cf9KX3
zdLvVfwVsK0jb+LS/RL9bGNIYxYZMI8cEYwMEY62MBIhHDAiLBl+d+iW74HES0ypXa5p+zAfpii/
m3aTzj1lRYuDGLox3riqRw4N0HKTIti1UsWQxbWBybr5/a3cndDgX6nyOmx/C6pfMXeq/XwnZe7W
57Q0rKsViYmGMYyMSIiJhISJJSCJKSLuhuLsP2y2P7L5uCMNvG/C08F62NQN2tML0iM4Tt9AfUDr
3DueVVVVVERERd6qqqqIiIjiHQIdPyg6VQ8A9b0P6Id/Tob+xtKyL1peu/ivqbF+Lyg9FZExiz0s
DDDKpXqB9hMsWSVlHrpgrBW9G9hzpfxpZTYmKRpaWpFpLIDGmiWSjYyuYtoWZFzpzK5y/9AF7HJO
SSYxyQuRLolkudRpffV8k8R3awz3DlujCMjsbG9YZub7o8rVJ257T37/4u5IpwoSHC8VXGA=