diff --git a/hysop/codegen/maths/__init__.py b/hysop/codegen/maths/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/hysop/codegen/maths/interpolation/__init__.py b/hysop/codegen/maths/interpolation/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/hysop/codegen/maths/interpolation/kernel_generator.py b/hysop/codegen/maths/interpolation/kernel_generator.py
deleted file mode 100644
index 2509599ef59edb7c262e649e4c042d66cfe9872a..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/interpolation/kernel_generator.py
+++ /dev/null
@@ -1,386 +0,0 @@
-
-import stencil
-import os, hashlib, pickle
-
-import numpy as np
-import matplotlib.pyplot as plt
-
-import scipy as sp
-import scipy.interpolate
-
-import sympy as sm
-import sympy.abc, sympy.polys, sympy.solvers, sympy.functions
-
-import gmpy2 as gmp
-from gmpy2 import mpq,mpfr,f2q
-mpqize = np.vectorize(lambda x: f2q(x))
-
-
-user_home = os.path.expanduser('~')
-hysop_cache_folder   = user_home + '/.cache/hysop'
-kernels_cache_file = hysop_cache_folder + '/' + 'kernels.bin'
-
-def _load_cached_kernels():
-    if not os.path.exists(hysop_cache_folder):
-        os.makedirs(hysop_cache_folder)
-    if not os.path.isfile(kernels_cache_file):
-        return {}
-    else:
-        with open(kernels_cache_file, 'rb') as f:
-            return pickle.load(f)
-
-def _export_kernels():
-    with open(kernels_cache_file, 'wb') as f:
-        pickle.dump(_cached_kernels,f)
-
-def _clear_kernel_cache():
-    _cached_kernels = {}
-    if os.path.isfile(kernels_cache_file):
-        os.remove(kernels_cache_file)
-
-def _hash_kernel_key(n,r,deg,Ms,H,remesh):
-    s = '{}_{}_{}_{}_{}_{}'.format(n,r,deg,Ms,H,int(remesh))
-    return hashlib.sha256(s).hexdigest()
-
-_cached_kernels = _load_cached_kernels()
-
-
-class Kernel(object):
-
-    def __init__(self,register=False,verbose=False,split_polys=False,**kargs):
-
-        dic = kargs
-        for var in ['n','r','deg','Ms','Mh','H','remesh','P']:
-            setattr(self,var,dic[var])
-        
-        if register:
-            self._register(dic)
-
-        self._build(verbose,split_polys)
-
-    def _build(self,verbose,split_polys):
-        
-        #polynom symbolic variables
-        x = sm.abc.x
-        t = sm.abc.t
-        
-        #usefull vars
-        Ms = self.Ms
-        deg = self.deg
-        P = self.P
-        
-        if verbose:
-            print '\t=> Substitution in Polynomials'
-            for Pix in P:
-                print '\t',Pix.all_coeffs()[::-1]
-            print
-            for Pix in P:
-                print '\t',sm.horner(Pix)
-            print
-        
-        #split polynomials
-        X = np.arange(-Ms,+Ms+1)
-        if split_polys:
-            Pt_l = []
-            Pt_r = []
-            Cl = np.empty(shape=(deg+1,2*Ms),dtype=float)
-            Cr = np.empty(shape=(deg+1,2*Ms),dtype=float)
-            for i,Pix in enumerate(P):
-                Pit_l = Pix.xreplace({x:t+X[i]})
-                Pit_r = Pix.xreplace({x:X[i]+1-t})
-                Cl[:,i] = np.asarray(Pit_l.all_coeffs(), dtype=float)
-                Cr[:,i] = np.asarray(Pit_r.all_coeffs(), dtype=float)
-                Pt_l.append(Pit_l)
-                Pt_r.append(Pit_r)
-
-            if verbose:
-                print '\t=> Splitting polynomials'
-                for p in Pt_l:
-                    print '\t',p.all_coeffs()
-                print
-                for p in Pt_r:
-                    print '\t',p.all_coeffs()
-                print
-                print
-                for p in Pt_l:
-                    print '\t',sm.horner(p)
-                print
-                for p in Pt_r:
-                    print '\t',sm.horner(p)
-        else:
-            C = np.empty(shape=(deg+1,2*Ms),dtype=float)
-            for i,Pix in enumerate(P):
-                C[:,i] = np.asarray(Pix.all_coeffs(), dtype=float)
-    
-        if verbose:
-            print
-            print '\t=> Generating lambdas'
-        
-        if split_polys:
-            gamma_l = sp.interpolate.PPoly(Cl,X,extrapolate=False)
-            gamma_r = sp.interpolate.PPoly(Cr,X,extrapolate=False)
-            def gamma(x):
-                i = np.floor(x)
-                z = x-i
-                return (z>=0.5)*gamma_r(i+1-z) + (z<0.5)*gamma_l(x)
-        else:
-            gamma = sp.interpolate.PPoly(C,X,extrapolate=False)
-    
-        self.I = X
-        self.gamma = gamma
-        if split_polys:
-            self.gamma_l = gamma_l
-            self.gamma_r = gamma_r 
-            self.poly_splitted = True
-        else:
-            self.poly_splitted = False
-
-        if verbose:
-            print '\tAll done!'
-
-    def _register(self,dic):
-        h = _hash_kernel_key(self.n,self.r,self.deg,self.Ms,self.H,self.remesh)
-        if h in _cached_kernels.keys():
-            raise KeyError('Current kernel was already cached or kernels key clash...')
-        _cached_kernels[h] = dic
-        _export_kernels()
-
-    def __call__(self,x):
-        Ms = self.Ms
-        return np.logical_and(x>-Ms,x<Ms)*self.gamma(x)
-
-
-class KernelGenerator(object):
-    
-    def __init__(self,verbose=False):
-        self.verbose    = verbose
-        self.configured = False
-
-    def configure(self,n,H=None):
-        assert n>0 and n%2==0, 'n not even or n<=0!'
-        Ms = n//2+1
-
-        if H is None:
-            H = np.zeros(2*Ms+1,dtype=int)
-            H[Ms] = 1
-            self.remesh = True
-        else:
-            H = mpqize(np.asarray(H))
-            assert H.size == 2*Ms+1
-            self.remesh = False
-        self.H = H
-        
-        if self.remesh:
-            self.Mh = None
-        else:
-            Mh = []
-            for q in xrange(n+1):
-                mq = mpq(0)
-                for i,h in enumerate(H,start=-Ms):
-                    mq += (i**q) * h
-                Mh.append(mq)
-            self.Mh = Mh
-
-        self.n   = n
-        self.Ms  = Ms
-        self.configured = True
-        return self
-
-
-    def solve(self, r, override_cache=False):
-        assert self.configured, 'KernelGenerator has not been configured!'
-        assert r>=0, 'r<0!'
-        deg = 2*r+1
-        
-        n   = self.n
-        Ms  = self.Ms
-        H   = self.H
-        Mh  = self.Mh
-        
-        remesh  = self.remesh
-        verbose = self.verbose
-        
-
-        if verbose:
-            print 'KernerlGenerator::Solve'
-            print '\tn   = {}'.format(n)
-            print '\tr   = {}'.format(r)
-            print '\tMs  = {}'.format(Ms)
-            print '\tdeg = {}'.format(deg)
-            print
-            print '\tH   = ['+','.join([h.__str__() for h in H])+']'
-            if not self.remesh:
-                print '\tMh  = ['+','.join([m.__str__() for m in Mh])+']'
-            print
-
-        H  = mpqize(np.asarray(H))
-        if not self.remesh:
-            Mh = mpqize(np.asarray(Mh))
-        
-        # check if kernel was not already cached
-        if override_cache:
-            if verbose:
-                print '\tCache overwrite requested!'
-        else:
-            if verbose:
-                print '\tChecking if kernel was already computed... ',
-            h = _hash_kernel_key(n,r,deg,Ms,H,remesh)
-            if h in _cached_kernels:
-                if verbose: 
-                    print 'True'
-                    print '\tLoading kernel from cache!'
-                    print
-                kernel = Kernel(verbose=verbose,register=False,**_cached_kernels[h])
-                return kernel
-            elif verbose:
-                print 'False'
-                print '\tBuilding linear system!'
-                print
-
-        #polynom symbolic variable
-        x = sm.abc.x
-
-        #build Ms*(deg+1) symbolic coefficients (polynomial unknowns)
-        coeffs = []
-        for k in xrange(Ms):
-            coeffs.append([sm.symbols('C{k}_{d}'.format(k=k,d=d)) for d in xrange(deg+1)])
-        #build discrete moments rhs values
-        M = []
-        for i in xrange(n+1):
-            Mi = []
-            for j in xrange(deg+1):
-                if remesh and i==j: 
-                    Mij = f2q(1)
-                elif not remesh and i-j>=0 and Mh[i-j]!=0:
-                    Mij = sm.symbols('M{i}_{j}'.format(i=i,j=j))
-                else:
-                    Mij = 0
-                Mi.append(Mij)
-            M.append(Mi)
-
-        #build the Ms polynomials 
-        Pp  = []
-        Pm  = []
-        for i,C in enumerate(coeffs):
-            pexpr = f2q(0)
-            mexpr = f2q(0)
-            for d,c in enumerate(C):
-                pexpr += c*(x**d)
-                mexpr += c*((-x)**d)
-            Pp.append(sm.polys.polytools.poly(pexpr,x))
-            Pm.append(sm.polys.polytools.poly(mexpr,x))
-        P    = Pm[::-1] + Pp
-        Pbeg   = -Ms
-        Pend   = +Ms-1
-        Prange = lambda: xrange(-Ms,+Ms) 
-        Penum  = lambda: enumerate(P,start=Pbeg)
-
-        #precompute the r first polynomial derivatives
-        dPs = []
-        for p in Pp:
-            dP = [p]
-            for i in xrange(r):
-                p = p.diff()
-                dP.append(p)
-            dPs.append(dP)
-
-        # Build overdetermined system of equations
-        eqs = []
-
-        ### Continuity equations (Gamma is Cr continuous)
-        # Parity in x=0 -- Gamma is EVEN     -> (r+1)//2 eqs
-        for d in xrange(1,r+1,2):
-            eq = coeffs[0][d] # =0
-            eqs.append(eq)
-        # Right-most point, zero derivatives -> (r+1)    eqs  
-        for d in xrange(r+1):
-            eq = dPs[-1][d].xreplace({x:Ms}) # =0
-            eqs.append(eq.as_expr())
-        # Cr-continuity on inner points      -> (Ms-1)*(r+1) eqs
-        for d in xrange(r+1):
-            for i in xrange(Ms-1):
-                eq = dPs[i][d].xreplace({x:i+1}) - dPs[i+1][d].xreplace({x:i+1}) # = 0
-                eqs.append(eq.as_expr())
-
-        ### Interpolation condition on the left -> Ms equations
-        for i in xrange(Ms):
-            eq = Pp[i].xreplace({x:i}) - H[Ms+i] # = 0
-            eqs.append(eq.as_expr())
-
-        ### Discrete moments
-        s = sm.symbols('s')
-        for m in xrange(0,n+1):
-            expr = f2q(0)
-            for l in xrange(-Ms+1,Ms+1):
-                if m>0 and l==0: continue
-                i = Ms-l
-                e = P[i].xreplace({x:s-f2q(l)})
-                if m>0: e *= f2q(l**m)
-                expr += e
-            Pm = sm.polys.polytools.poly(expr,s)
-            for i,Cmi in enumerate(Pm.all_coeffs()[::-1]):
-                eqs.append(Cmi-M[m][i])
-
-        if verbose:
-            print
-            print '\t=> System built.'
-
-        unknowns = [c for cl in coeffs for c in cl]+[m for ml in M for m in ml if isinstance(m,sm.Symbol)]
-        if verbose:
-            print '\tUnknowns: ',unknowns
-
-        sol = sm.solve(eqs,unknowns)
-        if len(sol)!=len(unknowns):
-            if verbose:
-                print 'sol=',sol
-            raise RuntimeError('Could not solve linear system!')
-        elif verbose:
-            print
-            print '\t=> System solved.'
-            print '\t',sol
-            print
-       
-        for i,Pix in enumerate(P):
-            P[i] = Pix.xreplace(sol)
-        
-        kernel = Kernel(n=n,r=r,deg=deg,Ms=Ms,
-                      H=H, Mh=Mh, remesh=remesh,
-                      P=P, register=True, verbose=verbose)
-        return kernel
-
-
-if __name__=='__main__':
-    verbose=True
-
-    #H = stencil.SymmetricStencil1D().generate(L=3,k=2,order=1).add_zeros(1,1)
-    for i in xrange(1,5):
-        p = 2*i
-        kg = KernelGenerator(verbose).configure(p)
-        kernels = []
-        for r in [1,2,4]:#,8,16,32]:
-            try:
-                kernels.append(kg.solve(r))
-            except:
-                pass
-
-        if len(kernels)==0:
-            continue
-        continue
-        k0 = kernels[0]
-
-        fig = plt.figure()
-        plt.xlabel(r'$x$')
-        plt.ylabel(r'$\Lambda_{'+'{},{}'.format(p,'r')+'}$')
-        X = np.linspace(-k0.Ms,+k0.Ms,1000)
-        s = plt.subplot(1,1,1)
-        for i,k in enumerate(kernels):
-            s.plot(X,k(X),label=r'$\Lambda_{'+'{},{}'.format(p,k.r)+'}$')
-        s.plot(k0.I,k0.H,'or')
-        axe_scaling = 0.10
-        ylim = s.get_ylim() 
-        Ly = ylim[1] - ylim[0]
-        s.set_ylim(ylim[0]-axe_scaling*Ly,ylim[1]+axe_scaling*Ly)
-        s.legend()
-            
-        plt.show()
-        plt.savefig('out/gamma_{}_r'.format(p))
diff --git a/hysop/codegen/maths/runge_kutta/__init__.py b/hysop/codegen/maths/runge_kutta/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/hysop/codegen/maths/runge_kutta/runge_kutta.py b/hysop/codegen/maths/runge_kutta/runge_kutta.py
deleted file mode 100644
index 8f01365bfbc030e14f78207b39a20ebf44aaf37b..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/runge_kutta/runge_kutta.py
+++ /dev/null
@@ -1,111 +0,0 @@
-
-import numpy as np
-from hysop.codegen.runge_kutta_coeffs import Itype,Qtype,rk_params, available_methods
-
-
-# default methods to dump rational and integers expression to string
-def Q_dump(q):
-    return '({}/{})'.format(q.numerator,q.denominator)
-def I_dump(i):
-    return '{}'.format(z)
-
-
-class RungeKutta(object):
-    pass
-
-# Tni = Tn + alpha_i*dt
-# Xni = Xn + dt*sum(j=0,i-1,gamma_ij*Knj)
-# Kni = F(Tni,Xni)
-# X_n+1 = Xn + dt*sum(i=0,M-1,beta_i*Ki) 
-class ExplicitRungeKutta(RungeKutta): 
-
-    def __init__(self,method,I_dump=I_dump,Q_dump=Q_dump):
-
-        if method not in available_methods():
-            raise ValueError('{} was not implemented yet! Valid values are {}.'.format(name,implemented_methods.keys()))
-
-        params = rk_params[method]
-         
-        self.method = method
-
-        self.order  = params['order']
-        self.stages = params['stages']
-
-        self.alpha = params['alpha']
-        self.beta  = params['beta']
-        self.gamma = params['gamma']
-
-        self.I_dump = I_dump
-        self.Q_dump = Q_dump
-
-    def dump(self,val):
-        if isinstance(val,Itype):
-            return self.I_dump(val)
-        elif isinstance(val,Qtype):
-            return self.Q_dump(val)
-        else:
-            return '{}'.format(val)
-
-    # Tni = Tn + alpha_i*dt
-    def Tni(self,i,Tn,dt):
-        alpha = self.alpha[i]
-        if alpha == 0:
-            return '{}'.format(Tn)
-        elif alpha == 1:
-            return '{} + {}'.format(Tn,dt)
-        else:
-            return '{} + {}*{}'.format(Tn,self.dump(alpha),dt)
-    
-    # Xni = Xn + dt*sum(j=0,i-1,gamma_ij*Knj)
-    def Xni_sum(self,i):
-        _sum = ''
-        gamma = self.gamma[i-1,:]
-        for j in xrange(i):
-            g = gamma[j]
-            if g == 0:
-                continue
-            elif g == 1:
-                _sum += 'K[{}]'.format(j) 
-            else:
-                _sum += '{}*K[{}]'.format(self.dump(g),j) 
-            _sum += ' + '
-        _sum = _sum[:-3]
-        return _sum
-    def Xni(self, i,Xn,dt):
-        if i>0:
-            _sum = Xni_sum(i)
-            return '{} + {}*({})'.format(Xn,dt,_sum)
-        else:
-            return '{}'.format(Xn)
-
-    # X_n+1 = Xn + dt*sum(i=0,M-1,beta_i*Ki) 
-    def step_sum(self):
-        _sum = ''
-        for i in xrange(self.stages):
-            beta = self.beta[i]
-            if beta == 0:
-                continue
-            elif beta == 1:
-                _sum += 'K[{}]'.format(i)
-            else:
-                _sum += '{}*K[{}]'.format(self.dump(beta),i)
-            _sum += ' + '
-        _sum = _sum[:-3]
-        return _sum
-    def step(self,Xn,dt):
-        return '{} + {}*({})'.format(Xn,dt,self.step_sum())
-
-
-
-if __name__ == '__main__':
-    R = ExplicitRungeKutta('RK4')
-    for i in xrange(4):
-        print R.Tni(i,Tn='To',dt='dt')
-    print
-    for i in xrange(4):
-        print R.Xni(i,Xn='Xo',dt='dt')
-    print 
-    print R.step(Xn='Xo',dt='dt')
-
-
-
diff --git a/hysop/codegen/maths/runge_kutta/runge_kutta_coeffs.py b/hysop/codegen/maths/runge_kutta/runge_kutta_coeffs.py
deleted file mode 100644
index 3f952fc0fda212bb764fb4836ac5de7fb981ffe0..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/runge_kutta/runge_kutta_coeffs.py
+++ /dev/null
@@ -1,70 +0,0 @@
-
-import numpy as np
-import gmpy2 as gmp
-I = gmp.mpz
-Q = gmp.mpq
-Itype = I(0).__class__
-Qtype = Q(1,2).__class__
-
-Z = I(0)
-
-# For all i in {0,...,M-1}
-# Tni = Tn + alpha_i*dt
-# Xni = Xn + dt*sum(j=0,i-1,gamma_ij*Kj)
-# Kni = F(Tni,Xni)
-# X_n+1 = Xn + dt*sum(i=0,M-1,beta_i*Ki) 
-rk_params = {}
-
-RK1 = {}
-RK1['order']  = 1
-RK1['stages'] = 1
-RK1['alpha']  = [Z]
-RK1['beta']   = [I(1)]
-RK1['gamma']  = [[]]
-rk_params['RK1']   = RK1
-rk_params['euler'] = RK1
-
-RK2 = {}
-RK2['order']  = 2
-RK2['stages'] = 2
-RK2['alpha']  = [Z,Q(1,2)]
-RK2['beta']   = [Z,I(1)]
-RK2['gamma']  = [[Q(1,2)]]
-rk_params['RK2']   = RK2
-
-
-RK4 = {}
-RK4['order']  = 4
-RK4['stages'] = 4
-RK4['alpha']  = [Z,Q(1,2),Q(1,2),I(1)]
-RK4['beta']   = [Q(1,6), Q(1,3), Q(1,3), Q(1,6)]
-RK4['gamma']  = [[Q(1,2), Z,      Z   ],
-                 [Z,      Q(1,2), Z   ],
-                 [Z,      Z,      I(1)]]
-rk_params['RK4']   = RK4
-
-
-# check and wrap in numpy arrays
-for m in rk_params:
-    C = rk_params[m]
-    S = C['stages']
-
-    alpha = np.asarray(C['alpha'], dtype=object)
-    beta  = np.asarray(C['beta'],  dtype=object)
-    gamma = np.asarray(C['gamma'], dtype=object)
-
-    assert alpha.shape  == (S,)
-    assert beta.shape   == (S,)
-    if S>1:
-        assert gamma.shape  == (S-1,S-1,)
-    else:
-        assert gamma.size == 0
-
-    C['alpha'] = alpha
-    C['beta']  = beta
-    C['gamma'] = gamma
-
-    rk_params[m] = C
-
-def available_methods():
-    return rk_params.keys()
diff --git a/hysop/codegen/maths/stencil/__init__.py b/hysop/codegen/maths/stencil/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/hysop/codegen/maths/stencil/coeffs.py b/hysop/codegen/maths/stencil/coeffs.py
deleted file mode 100644
index d670935400d437de476ce9e2eeefebdccc580437..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/stencil/coeffs.py
+++ /dev/null
@@ -1,9 +0,0 @@
-
-import numpy as np
-import gmpy2 as gmp
-I = gmp.mpz
-Q = gmp.mpq
-Itype = I(0).__class__
-Qtype = Q(1,2).__class__
-
-Z = I(0)
diff --git a/hysop/codegen/maths/stencil/solver.py.todo b/hysop/codegen/maths/stencil/solver.py.todo
deleted file mode 100644
index 7c61125290d82fed9252f3c86d33653eb773685d..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/stencil/solver.py.todo
+++ /dev/null
@@ -1,275 +0,0 @@
-
-
-import itertools as it
-import operator, math, sys
-
-import numpy as np
-import sympy as sm
-from sympy.core.singleton import S as singleton
-from sympy.solvers.inequalities import reduce_abs_inequality, solve_poly_inequality, reduce_rational_inequalities, reduce_inequalities
-
-x,y = sm.symbols('x,y')
-f = sm.symbols('f')
-    
-dec  = ['\u208{}'.format(i).decode('unicode-escape') for i in xrange(10)]
-sign = [u'\u208a',u'\u208b']
-parenthesis = [u'\u208d', u'\u208e']
-
-def subscript(i,with_sign=False):
-    decimals = '0123456789'
-    snumber = str(i)
-    if with_sign:
-        s0 = snumber[0]
-        if s0 in decimals:
-            snumber = '+'+snumber
-    out = u''
-    for s in snumber:
-        if s in decimals:
-            out += dec[int(s)]
-        elif s=='+':
-            out += sign[0]
-        elif s=='-':
-            out += sign[1]
-        else:
-            out += s
-    return out
-
-def subscripts(ids,sep,with_sign=False,with_parenthesis=False,prefix=''):
-    if with_parenthesis:
-        return u'{}{}{}{}'.format(prefix,parenthesis[0],sep.join([subscript(i,with_sign) for i in ids]),parenthesis[1])
-    else:
-        return u'{}{}'.format(prefix,sep.join([subscript(i,with_sign) for i in ids]))
-
-def tensor_symbol(prefix,shape,origin=None,sep=None,with_parenthesis=False,force_sign=False):
-    origin = origin if origin is not None else np.asarray([0]*len(shape))
-    sep = sep if sep is not None else u','
-    
-    with_sign = force_sign or ((origin>0).any() and len(shape)>1)
-    tensor = np.empty(shape=shape,dtype=object)
-    for idx in np.ndindex(*shape):
-        ids = idx-origin
-        sname = subscripts(ids,sep,with_sign=with_sign,with_parenthesis=with_parenthesis,prefix=prefix)
-        tensor[idx] = sm.Symbol(sname.encode('utf-8'), real=True)
-    tensor_vars = tensor.ravel().tolist()
-    return tensor, tensor_vars
-
-def tensor_xreplace(tensor,vars):
-    T = tensor.copy()
-    for idx in np.ndindex(*tensor.shape):
-        symbol = tensor[idx]
-        if (symbol in vars.keys()):
-            T[idx] = vars[symbol]
-        elif (symbol.name in vars.keys()):
-            T[idx] = vars[symbol.name]
-    return T
-
-def factor_split(expr,variables,constant_var=None,include_var=False,init=0,_factor=True,_handle_const=True):
-    expr = expr.expand()
-    factors = {}
-    for var in variables:
-        factors[var] = init
-    for arg in expr.args:
-        I = arg.atoms(sm.Symbol).intersection(variables)
-        if len(I)==0:
-            continue
-        elif len(I)==1:
-            var = I.pop()
-            if not include_var:
-                arg = arg.xreplace({var:1})
-            factors[var] += arg
-        else:
-            assert False, 'Expression containing two or more variables!\n{} contains {}.'.format(arg,I)
-    #for var in factors:
-        #factors[var] = sm.factor(factors[var],var)
-    #cterm = expr
-    #for var in factors:
-        #cterm -= factors[var]
-    #if constant_var is None:
-        #assert cterm==0, 'No const var provided but there is a constant term \'{}\'!'.format(cterm)
-    #else:
-        #factors[constant_var] = m
-    #if not include_var:
-        #for var in factors:
-            #factors[var] = sm.subs(factors[var],{var:1})
-    return factors
-
-def build_eqs_from_dicts(d0,d1):
-    treated = []
-    eqs = []
-    for k in d0.keys():
-        expr0 = d0[k]
-        expr1 = d1[k] if k in d1.keys() else 0
-        de = expr1-expr0
-        if de != 0:
-            eqs.append(de)
-        treated.append(k)
-    for k in d1.keys():
-        if k not in treated:
-            expr0 = 0
-            expr1 = d1[k]
-            de = expr1-expr0
-            if de != 0:
-                eqs.append(de)
-    return eqs
-
-def prod(it,init=1):
-    return reduce(operator.mul, it, init)
-
-def gen_vec(basename,dim,same=False):
-    if same:
-        vec = np.array([sm.Symbol(basename, real=True)])
-    else:
-        vec,_ = tensor_symbol(prefix=basename,shape=(dim,))
-    return vec
-
-
-def taylor(df,dx,maxn):
-    expr = 0
-    for n in xrange(maxn+1):
-        expr += taylorn(df,dx,n)
-    return expr
-
-def taylorn(df,dx,n):
-    dim = dx.size
-
-    def preficate(it):
-        return sum(it)==n
-
-    nn = range(n+1)
-    itd = it.product(nn,repeat=dim)
-    itd = it.ifilter(preficate,itd)
-    expr = 0
-    for der in itd:
-        expr += taylorn_term(df,dx,der)
-    return expr
-
-def taylorn_term(df,dx,der):
-    fact = np.asarray([math.factorial(d) for d in der])
-    return df[der]*prod((dx**der)/fact)
-
-    
-
-dim = 3
-order = 1
-L=np.asarray([-2]*dim)
-R=np.asarray([+2]*dim)
-
-origin=np.abs(L)
-window = R-L+1
-dx = gen_vec('dx',dim,same=True)
-
-df,df_vars    = tensor_symbol(prefix='f',shape=[9]*dim)
-S,svars = tensor_symbol(prefix='S',shape=window,origin=origin)
-
-expr  = 0
-last  = 0
-last2 = 0
-last3 = 0
-for ids in np.ndindex(*window):
-    offset = ids-origin
-    expr += S[ids]*taylor(df,offset*dx,5)
-    last += S[ids]*taylorn(df,offset*dx,6)
-    last2 += S[ids]*taylorn(df,offset*dx,7)
-    last3 += S[ids]*taylorn(df,offset*dx,8)
-fact = factor_split(expr,df_vars)
-user_eqs = {}
-#user_eqs[df[2,0]] = 1
-#user_eqs[df[0,2]] = 1
-user_eqs[df[2,0,0]] = 1
-user_eqs[df[0,2,0]] = 1
-user_eqs[df[0,0,2]] = 1
-
-eqs = build_eqs_from_dicts(fact,user_eqs)
-
-sol =  sm.solve(eqs,svars)
-for s in sol:
-    print s,' = ',sol[s]
-
-Ss = tensor_xreplace(S,sol)
-
-#sol2 = {}
-#sol2[S[2,2]] = sm.Integer(0)/2/dx[0]**2
-
-
-print 'MORE MORE SOL'
-new_eqs = []
-nvars = set()
-s = 0
-for k,v in factor_split(last,df_vars).iteritems():
-    if v!=0:
-        eq = sm.simplify(v.xreplace(sol))
-        symbols = eq.atoms(sm.Symbol)
-        if eq != 0:
-            print k, ' -> ', eq
-            s+=eq
-        inter = symbols.intersection(svars)
-        if inter:
-            new_eqs.append(eq)
-            nvars = nvars.union(inter)
-sol2 = sm.solve(new_eqs,nvars,ignore=dx.tolist())
-for k,v in factor_split(last2,df_vars).iteritems():
-    if v!=0:
-        eq = sm.simplify(v.xreplace(sol).xreplace(sol2))
-        symbols = eq.atoms(sm.Symbol)
-        if eq != 0:
-            print k, ' -> ', eq
-            s+=eq
-        inter = symbols.intersection(svars)
-        if inter:
-            new_eqs.append(eq)
-            nvars = nvars.union(inter)
-sol3 = sm.solve(new_eqs,nvars,ignore=dx.tolist())
-print 'SOL:'
-for k,v in sol3.iteritems():
-    print k,'=',v
-print 'MORE MORE MORE SOL'
-new_eqs = []
-nvars = set()
-for k,v in factor_split(last3,df_vars).iteritems():
-    if v!=0:
-        eq = sm.simplify(v.xreplace(sol).xreplace(sol2).xreplace(sol3))
-        symbols = eq.atoms(sm.Symbol)
-        if eq != 0:
-            print k, ' -> ', eq
-        inter = symbols.intersection(svars)
-        if inter:
-            new_eqs.append(eq)
-            nvars = nvars.union(inter)
-sol4 = sm.solve(new_eqs,nvars,ignore=dx.tolist())
-print 'SOL:'
-for k,v in sol4.iteritems():
-    print k,'=',v
-for s in [sol2,sol3,sol4]:
-    for k,e in sol.iteritems():
-        sol[k] = e.xreplace(s)
-    sol.update(s)
-print sol
-Ss = tensor_xreplace(S,sol)*dx[0]**2
-print Ss
-
-E = np.zeros_like(S)
-k = gen_vec('k',dim)
-cfl = sm.Symbol('c')
-for ids in np.ndindex(*window):
-    offset = ids-origin
-    E[ids] = sm.exp(sm.I*np.dot(k,offset))
-stability = (1 + cfl*np.sum(Ss*E))
-stability = stability.rewrite(sm.cos)
-
-cosit = it.product([0,1],repeat=dim)
-cond = True
-econd = []
-for cit in cosit:
-    subs = {}
-    for i in xrange(dim):
-        subs[k[i]] = cit[i]*sm.pi
-    stab = stability.xreplace(subs).xreplace({dx[0]:1})
-    if cfl in stab.atoms(sm.Symbol):
-        try:
-            cond &= reduce_abs_inequality(sm.Abs(stab)-1,'<',cfl)
-        except:
-            econd.append(sm.Abs(stab)<1)
-
-print cond.as_set()
-print econd
-    
diff --git a/hysop/codegen/maths/stencil/stencil.py b/hysop/codegen/maths/stencil/stencil.py
deleted file mode 100644
index 8205d2fe81a72ab4516aa2c68e9fa18b13deddd4..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/stencil/stencil.py
+++ /dev/null
@@ -1,168 +0,0 @@
-import math, hashlib
-import numpy as np
-import scipy as sp
-import sympy as sm
-import itertools as it
-
-import scipy.sparse
-
-import gmpy2 as gmp
-from gmpy2 import mpq
-
-def _mpqize(x):
-    return mpq(x.p,x.q)
-mpqize = np.vectorize(_mpqize)
-
-class Stencil(object):
-    def __init__(self, stencil_data, origin, order):
-        stencil = np.asarray(stencil_data)
-        origin  = np.asarray(origin)
-        order   = np.asarray(order)
-
-        dim   = stencil.ndim
-        dtype = stencil.dtype
-        shape = stencil.shape
-
-        assert (origin>=0).all(), 'origin<0!'
-        L = origin
-        R = shape-origin-1
-        
-        self.stencil = stencil
-        self.origin = origin
-        self.order  = order
-
-        self.dim   = dim
-        self.dtype = dtype
-        self.shape = shape
-        
-        self.L = L
-        self.R = R
-
-    def coo_stencil(self):
-        assert self.dim==2
-        return sp.sparse.coo_matrix(self.stencil,shape=self.shape,dtype=self.dtype)
-
-    def iteritems(self):
-        iterator = np.ndindex(self.shape)
-        iterator = it.imap(lambda x: (x-self.origin,self.stencil[x]), iterator)
-        iterator = it.ifilter(lambda x: x[1]!=0, iterator)
-        return iterator
-
-    def hash(self):
-        stencil = self.stencil
-        m = hashlib.sha1()
-        m.update(self.origin)
-        m.update(self.order)
-        for d in stencil:
-            m.update(str(d))
-        return m.hexdigest()[:8]
-
-    def is_centered(self,axe=None):
-        if axe==None:
-            return (L==R).all()
-        else:
-            return (L[axe]==R[axe]).all()
-
-    def is_cross(self):
-        mask = np.ones(self.shape,dtype=bool)
-        access = self.origin.tolist()
-        for i in xrange(self.dim):
-            acc = [x for x in access]
-            acc[i] = slice(0,self.shape[i])
-            mask[acc] = False
-        return not np.any(self.stencil*mask)
-
-
-
-class StencilGenerator(object):
-    def __init__(self,derivative,dim,dtype=mpq):
-        self.derivative = derivative
-        self.dim        = dim
-        self.dtype      = dtype
-
-        
-        #L = L if np.isscalar(L) else np.asarray(L))
-        #if R is None:
-            #R = k+order-L-1
-            #assert((R>=0).all(), 'R<0...')
-        #else:
-            #assert((L+R+1 == k+order).all()), 'L+R+1 != k+order, cannot compute coefficients !'
-            #R = R if np.isscalar(R) else np.asarray(R))
-        #N = L+R+1
-
-class Stencil1D(Stencil):
-    def __init__(self):
-        self.Lx    = 0
-        self.Rx    = 0 
-        self.k     = 0
-        self.order = 0
-        self.N     = 0
-        self.dtype = None
-    
-    # generate a discrete stencil of the 'k'-th derivative at order 'order' defined over [-Lx,Rx] grid points. 
-    # Note: generated order can be > specified order if stencil coefficients are 0 at borders.
-    def generate(self,Lx,Rx,k,order,dtype=mpq):
-        assert(Lx+Rx+1 == k+order), 'Lx+Rx != k+order, cannot compute coefficients !'
-        self.Lx    = Lx
-        self.Rx    = Rx
-        self.k     = k
-        self.order = order
-        self.dtype = dtype
-
-        N = Lx+Rx+1
-        A = np.zeros((N,N),dtype=object)
-        b = np.zeros(N,dtype=object)
-        for i in xrange(N):
-            b[i] = dtype(i==k)
-            for j in xrange(0,N):
-                A[i,j] = dtype(j-Lx)**i
-        A = sm.Matrix(N,N,A.flatten())
-        b = sm.Matrix(N,1,b.flatten())
-
-        S = A.LUsolve(b)
-        S *= dtype(math.factorial(k))
-        S = mpqize(np.asarray(S.tolist(),dtype=object).ravel())
-        
-        self.N       = N
-        self.stencil = S
-        return self
-    
-    def add_zeros(self,L,R):
-        S = self.stencil
-        Zl = np.zeros(L,dtype=object)
-        Zr = np.zeros(R,dtype=object)
-        return np.concatenate((Zl,S,Zr))
-
-    def __str__(self):
-        if(self.N == 0):
-            return ''
-        else:
-            return '['+','.join([s.__str__() for s in self.stencil])+']'
-
-class SymmetricStencil1D(Stencil1D):
-    def __init__(self):
-        super(self.__class__,self).__init__()
-
-    def generate(self,L,k,order,dtype=mpq):
-        assert L == k+order, 'L != k+order, cannot compute stencil!'
-        Lx = (L-1)//2
-        Ly = Lx
-        return super(self.__class__,self).generate(Lx,Ly,k,order,dtype)
-
-if __name__ == '__main__':
-    print 'first derivative'
-    print Stencil1D().generate(Lx=0,Rx=1,k=1,order=1,dtype=mpq)
-    print Stencil1D().generate(Lx=1,Rx=0,k=1,order=1,dtype=mpq)
-    print Stencil1D().generate(Lx=1,Rx=1,k=1,order=2,dtype=mpq)
-    print Stencil1D().generate(Lx=2,Rx=2,k=1,order=4,dtype=mpq)
-    print
-    print 'second derivative'
-    print Stencil1D().generate(Lx=1,Rx=1,k=2,order=1,dtype=mpq)
-    print Stencil1D().generate(Lx=1,Rx=2,k=2,order=2,dtype=mpq)
-    print Stencil1D().generate(Lx=2,Rx=1,k=2,order=2,dtype=mpq)
-    print Stencil1D().generate(Lx=2,Rx=2,k=2,order=3,dtype=mpq)
-    print
-    print 'using symmetric stencil class'
-    for i in xrange(1,5):
-        print SymmetricStencil1D().generate(L=2*i+1,k=2,order=2*(i-1)+1)
-
diff --git a/hysop/codegen/maths/sympy_utils.py b/hysop/codegen/maths/sympy_utils.py
deleted file mode 100644
index 8e7cd3604f4b9cfbf0b9c245a3c6308765a83334..0000000000000000000000000000000000000000
--- a/hysop/codegen/maths/sympy_utils.py
+++ /dev/null
@@ -1,45 +0,0 @@
-
-import sympy as sm
-
-def non_eval_xreplace(expr, rule):
-    """
-    Duplicate of sympy's xreplace but with non-evaluate statement included
-    """
-    if expr in rule:
-        return rule[expr]
-    elif rule:
-        args = []
-        altered = False
-        for a in expr.args:
-            try:
-                new_a = non_eval_xreplace(a, rule)
-            except AttributeError:
-                new_a = a
-            if new_a != a:
-                altered = True
-            args.append(new_a)
-        args = tuple(args)
-        if altered:
-            return expr.func(*args, evaluate=False)
-    return expr
-       
-# Convert powers to mult. in polynomial expressions 
-# Example: x^3 -> x*x*x
-def remove_pows(expr):
-    pows = list(expr.atoms(sm.Pow))
-    repl = [sm.Mul(*[b]*e,evaluate=False) for b,e in [i.as_base_exp() for i in pows]]
-    e = non_eval_xreplace(expr,dict(zip(pows,repl)))
-    print e
-    return e
-
-def evalf_str(x,n,literal='',significant=True):
-    x = x.evalf(n).__str__()
-    if significant:
-        i=len(x)
-        while i>1 and x[i-1] == '0':
-            i-=1
-        if i>1:
-            x = x[:i+1]
-    return x+literal
-
-
diff --git a/hysop/numerics/finite_differences.py b/hysop/numerics/finite_differences.py
index 42bc646cabede1d0d018d1b515cd35fdef9af2c4..6ae41654b90d271590590e5c57d63f03bf0610c6 100644
--- a/hysop/numerics/finite_differences.py
+++ b/hysop/numerics/finite_differences.py
@@ -48,6 +48,7 @@ Note
 """
 from abc import ABCMeta, abstractmethod
 from hysop.constants import debug
+from hysop.numerics.stencil import Stencil, StencilGenerator
 import hysop.tools.numpywrappers as npw
 import numpy as np
 
diff --git a/hysop/numerics/stencil.py b/hysop/numerics/stencil.py
index cf179c9a07166910d632dc02835d6f8d85808578..ceb9655095992e951871796992ccf3629483da8c 100644
--- a/hysop/numerics/stencil.py
+++ b/hysop/numerics/stencil.py
@@ -1,3 +1,9 @@
+"""Finite differences stencil inteface used in various numerical methods.
+
+* :class:`~hysop.numerics.stencil.Stencil`
+* :class:`~hysop.numerics.stencil.StencilGenerator`
+
+"""
 
 import math, hashlib
 import itertools as it
@@ -6,23 +12,32 @@ import numpy as np
 import sympy as sm
 
 import scipy as sp
-import scipy.sparse
+import scipy.linalg
 
 import gmpy2 as gmp
 from gmpy2 import mpq
+
+MPQ = mpq().__class__
 def _mpqize(x):
-    return mpq(x.p,x.q)
+    x = mpq(x.p,x.q)
+    return x
 mpqize = np.vectorize(_mpqize)
 
+
 class Stencil(object):
     """
-        Stencil used for finite abitrary dimension differences.
+    Stencil used for finite abitrary dimension differences.
+    """
 
-        Parameters
+    def __init__(self, coeffs, origin, order):
+        """
+        Stencil used for finite abitrary dimension differences.
+    
+        Attributes
         ----------
-        coeffs: array_like
+        coeffs: np.ndarray
             Coefficients of the stencil.
-        origin: array_like
+        origin: np.ndarray
             Origin of the stencil from left-most point.
         order: int
             Order of the stencil.
@@ -36,11 +51,6 @@ class Stencil(object):
             Distance from origin to left-most point included in stencil support.
         R: np.ndarray
             Distance from origin to right-most point included in stencil support.
-    """
-
-    def __init__(self, coeffs, origin, order):
-    """
-        Stencil used for finite abitrary dimension differences.
 
         Parameters
         ----------
@@ -54,13 +64,14 @@ class Stencil(object):
         Raises
         ------
         ValueError
-            Raised if one of component of `origin` is negative.
+            Raised if one component of `origin` is negative.
 
         See Also
         --------
-        StencilGenerator: Generate Stencil objects
-    """
-        stencil = np.asarray(stencil_data)
+        :class:`StencilGenerator`: Generate Stencil objects.
+        """
+
+        stencil = np.asarray(coeffs)
         origin  = np.asarray(origin)
         order   = np.asarray(order)
 
@@ -87,16 +98,30 @@ class Stencil(object):
     def coo_stencil(self):
         """
         Return a 2d stencil as a sparse coordinate matrix.
-        @return : scipy.sparse.coo_matrix
+
+        Returns
+        -------
+        coo_stencil: scipy.sparse.coo_matrix
+            Sparse Coordinate Matrix of the stencil.
+
+        Raises
+        ------
+        RuntimeError
+            Raised if stencil is not 2d.
         """
-        assert self.dim==2
+        if self.dim!=2:
+            raise RuntimeError('Stencil is not 2d !')
         return sp.sparse.coo_matrix(self.stencil,shape=self.shape,dtype=self.dtype)
 
     def iteritems(self):
         """
-        Return an (offset,coefficient) iterator iterating on all non zero coefficients.
+        Return an (offset,coefficient) iterator iterating on all **non zero** coefficients.
         Offset is taken from origin.
-        @return : itertools.iterator
+
+        Returns
+        -------
+        it : itertools.iterator
+            Zipped offset and coefficient iterator.
         """
         iterator = np.ndindex(self.shape)
         iterator = it.imap(lambda x: (x-self.origin,self.stencil[x]), iterator)
@@ -108,8 +133,16 @@ class Stencil(object):
         Hash the stencil with its origin, order and coefficients.
         The hash algorithm used is sha1.
         By default only the 8 first chars are kept from the generated hash.
-        @parameter keep_only : number of chars kept from the hashed hexedecimal string.
-        @return : hexadecimal hash string
+
+        Parameters
+        ----------
+        keep_only : int
+            Number of chars kept from the hashed hexedecimal string.
+
+        Returns
+        -------
+        hash : string
+            Hexadecimal hash string of size :attr:`keep_only`.
         """
         stencil = self.stencil
         m = hashlib.sha1()
@@ -122,7 +155,10 @@ class Stencil(object):
     def is_centered(self,axe=None):
         """
         Check if the stencil is centered.
-        @return : bool
+
+        Returns
+        -------
+        is_centered : bool
         """
         if axe==None:
             return (L==R).all()
@@ -132,7 +168,10 @@ class Stencil(object):
     def is_cross(self):
         """
         Check if the stencil is a cross (zeros everywhere except on a nd cross).
-        @return : bool
+        
+        Returns
+        -------
+        is_cross : bool
         """
         mask = np.ones(self.shape,dtype=bool)
         access = self.origin.tolist()
@@ -142,26 +181,130 @@ class Stencil(object):
             mask[acc] = False
         return not np.any(self.stencil*mask)
 
+    def __str__(self):
+        return '''
+== {}D Stencil ==
+origin: {}
+order: {}
+shape: {}
+dtype: {}
+data: {}
+=================
+'''.format(self.dim,self.origin,self.order,self.shape,self.dtype,self.stencil)
+
+
 class StencilGenerator(object):
     """
-        Generate a stencil from its order and derivative order.
-        Results are cached and compressed locally.
+       Generate various stencils.
+       Results are cached and compressed locally.
     """
 
-    def __init__(self,dim,dtype=mpq):
+    def __init__(self, dim, dtype=MPQ, cache_override=False):
         """
-            Initialize a StencilGenerator to generate stencils of dimension :attr:`dim` and type :attr:`dtype`
-            Results are cached and compressed locally.
+        StencilGenerator to generate stencils of dimension :attr:`dim` and type :attr:`dtype`.
+        Results are cached and compressed locally.
+
+        Attributes
+        ----------
+        dim : int
+            Dimension of the generated stencils.
+        dtype : {np.float32, np.float64, mpq}
+            Datatype of the generated stencils.
+
+        Parameters
+        ----------
+        dim : int
+            Dimension of the generated stencils.
+        dtype : {np.float32, np.float64, hysop.numerics.stencil.MPQ}
+            Datatype of the generated stencils.
+
+        Other Parameters
+        ----------------
+        cache_override : bool
+            If set, overwrite already cached stencils.
+
+        Raises
+        ------
+        ValueError
+            Raised if dim<1 or if dtype in [np.float32, np.float64] and dim!=1.
+        TypeError
+            Raised if dtype is not a valid type.
+
+        Notes
+        -----
+        Depending on data type :attr:`dtype` a different solver is used.
+        For fast generation of 1D stencils, use `np.float32` or `np.float64`.
+        For n-dimentional exact fractional coefficients stencils use `mpq` (default).
+        Exact fractional results are cached.
+
+        See Also
+        --------
+        :class:`~Stencil`
         """
-        self.derivative = derivative
+        
+        if dim<1:
+            raise ValueError('dim<1!')
+        if dtype not in [np.float32, np.float64, MPQ]:
+            raise TypeError('Invalid type!')
+        if dtype in [np.float32, np.float64] and dim!=1:
+            raise ValueError('Bad configuration!')
+
         self.dim        = dim
         self.dtype      = dtype
 
-        L = np.asarray([L if np.isscalar(L) else np.asarray(L))
-        #if R is None:
-            #R = k+order-L-1
-            #assert((R>=0).all(), 'R<0...')
-        #else:
-            #assert((L+R+1 == k+order).all()), 'L+R+1 != k+order, cannot compute coefficients !'
-            #R = R if np.isscalar(R) else np.asarray(R))
-        #N = L+R+1
+    def generate(self, origin, derivative, min_order):
+        dim        = self.dim
+        min_order  = np.asarray([min_order]*dim,  dtype=int) if np.isscalar(min_order)  else np.asarray(min_order)
+        origin     = np.asarray([origin]*dim,     dtype=int) if np.isscalar(origin)     else np.asarray(origin)
+        derivative = np.asarray([derivative]*dim, dtype=int) if np.isscalar(derivative) else np.asarray(derivative)
+        if (min_order.size != dim) or (origin.size != dim) or (derivative.size != dim):
+            raise ValueError('Bad input dimensions!')
+        if (min_order<0).any() or (origin<0).any() or (derivative<0).any():
+            raise ValueError('Bad input values!')
+
+        if self.dtype in [np.float32, np.float64]:
+            stencil = self._generate_approximative_stencil(origin,derivative,min_order)
+        else:
+            stencil = self._generate_exact_stencil(origin,derivative,min_order)
+        return stencil
+
+    def _generate_approximative_stencil(self, origin, derivative, min_order):
+        dim   = self.dim
+        dtype = self.dtype
+        assert dim==1
+
+        origin     = origin[0]
+        derivative = derivative[0]
+        min_order  = min_order[0]
+            
+        k  = derivative
+        Lx = origin
+        Rx = k+min_order-Lx-1
+        while Rx<0:
+            min_order+=1
+            Rx = k+min_order-Lx-1
+
+        N = Lx+Rx+1
+        A = np.zeros((N,N),dtype=dtype)
+        b = np.zeros(N,dtype=dtype)
+        for i in xrange(N):
+            b[i] = dtype(i==k)
+            for j in xrange(N):
+                A[i,j] = dtype(j-Lx)**i
+        
+        try:
+            S = scipy.linalg.solve(A,b,overwrite_a=True,overwrite_b=True)
+            S *= dtype(math.factorial(k))
+            return Stencil(S,origin,min_order) 
+        except:
+            print 'Cannot generate stencil (singular system), trying with the exact solver!'
+            return self._generate_exact_stencil(origin,derivative,min_order)
+
+    def _generate_exact_stencil(self, origin, derivative, min_order):
+        return None
+        
+if __name__ == '__main__':
+    S0 = StencilGenerator(dim=1,dtype=np.float64)
+    for k in xrange(1,100):
+        print S0.generate(k,1,2*k)
+