def genP3code():
    autocode = CCodeGen(project="Salvus")
    r,s,t = symbols("r,s,t")
    rstn = p3ReferenceNodes()
    (rn,sn,tn) = rstn
    Np = len(rn)
    phi = p3ElementPolynomials(rstn,r,s,t)
    (dphi_dr,dphi_ds,dphi_dt) = p3ElementDerivatives(phi,r,s,t)
    dphi_dr_rstn = np.zeros((Np,Np))
    dphi_ds_rstn = np.zeros((Np,Np))
    dphi_dt_rstn = np.zeros((Np,Np))
    for i in range(0,Np):
        dphi_dr_i = lambdify((r,s,t),dphi_dr[i])
        dphi_ds_i = lambdify((r,s,t),dphi_ds[i])
        dphi_dt_i = lambdify((r,s,t),dphi_dt[i])        
        for (n,(ri,si,ti)) in enumerate(zip(rn,sn,tn)):
            dphi_dr_rstn[i,n] = dphi_dr_i(ri,si,ti)
            dphi_ds_rstn[i,n] = dphi_ds_i(ri,si,ti)
            dphi_dt_rstn[i,n] = dphi_dt_i(ri,si,ti)

    dphi_dr_rstn = Matrix(dphi_dr_rstn)
    dphi_ds_rstn = Matrix(dphi_ds_rstn)
    dphi_dt_rstn = Matrix(dphi_dt_rstn)
    
    rn = Matrix([ri for (ri,si,ti) in zip(rn,sn,tn)])
    sn = Matrix([si for (ri,si,ti) in zip(rn,sn,tn)])
    tn = Matrix([ti for (ri,si,ti) in zip(rn,sn,tn)])
    wn = Matrix(p3QuadratureWeights())
    rn_routine = autocode.routine("coordinates_p3_tetrahedra_rn",rn,
                                  argument_sequence=None)
    sn_routine = autocode.routine("coordinates_p3_tetrahedra_sn",sn,
                                  argument_sequence=None)
    tn_routine = autocode.routine("coordinates_p3_tetrahedra_tn",tn,
                                  argument_sequence=None)
    wn_routine  = autocode.routine("quadrature_weights_p3_tetrahedra",wn,
                                   argument_sequence=None)

    # NOTE: writes out in Row Major (so we write the
    # transpose). Salvus (via Eigen) assumes Column Major
    dphi_dr_rstn_routine  = autocode.routine("dphi_dr_rstn_p3_tetrahedra",
                                             dphi_dr_rstn.transpose(),
                                             argument_sequence=None)
    dphi_ds_rstn_routine  = autocode.routine("dphi_ds_rstn_p3_tetrahedra",
                                             dphi_ds_rstn.transpose(),
                                             argument_sequence=None)
    dphi_dt_rstn_routine  = autocode.routine("dphi_dt_rstn_p3_tetrahedra",
                                             dphi_dt_rstn.transpose(),
                                             argument_sequence=None)
    
    routines = [rn_routine,
                sn_routine,
                tn_routine,
                wn_routine,
                dphi_dr_rstn_routine,
                dphi_ds_rstn_routine,
                dphi_dt_rstn_routine]

    autocode.write(routines,"p3_tetrahedra",to_files=True)

    buildVisualizationP3(rn,sn,tn)
Exemple #2
0
def tensorized_basis_2D(order):

    total_integration_points = (order + 1) * (order + 1)
    eps, eta, rho = sym.symbols('epsilon eta rho')
    eps_gll = sym.symbols('epsilon_0:%d' % (order + 1))
    eta_gll = sym.symbols('eta_0:%d' % (order + 1))

    # Get N + 1 lagrange polynomials in each direction.
    generator_eps = generating_polynomial_lagrange(order, 'epsilon', eps_gll)
    generator_eta = generating_polynomial_lagrange(order, 'eta', eta_gll)

    # Get tensorized basis.
    basis = TensorProduct(generator_eta, generator_eps)
    basis = basis.subs([(v, c)
                        for v, c in zip(eps_gll, gll_coordinates(order))])
    basis = basis.subs([(v, c)
                        for v, c in zip(eta_gll, gll_coordinates(order))])
    sym.pprint(basis)

    # Get gradient of basis functions.
    basis_gradient_eps = sym.Matrix([sym.diff(i, eps) for i in basis])
    basis_gradient_eta = sym.Matrix([sym.diff(i, eta) for i in basis])

    # Get diagonal mass matrix
    mass_matrix = rho * basis * basis.T
    mass_matrix_diagonal = sym.Matrix(
        [mass_matrix[i, i] for i in range(total_integration_points)])

    # Write code
    routines = []
    autocode = CCodeGen()
    routines.append(
        autocode.routine('interpolate_order{}_square'.format(order),
                         basis,
                         argument_sequence=None))
    routines.append(
        autocode.routine(
            'interpolate_eps_derivative_order{}_square'.format(order),
            basis_gradient_eps,
            argument_sequence=None))
    routines.append(
        autocode.routine(
            'interpolate_eta_derivative_order{}_square'.format(order),
            basis_gradient_eta,
            argument_sequence=None))
    routines.append(
        autocode.routine('diagonal_mass_matrix_order{}_square'.format(order),
                         mass_matrix_diagonal,
                         argument_sequence=None))
    autocode.write(routines, 'order{}_square'.format(order), to_files=True)
Exemple #3
0
def create_module(module_name, expression_name_tuples, directory):
    """Generates a cython module that can be imported."""

    routines = []

    for name, expression, args in expression_name_tuples:
        try:
            routine = make_routine(name, [expression], args)

        except CodeGenArgumentListError as e:
            new_args = []
            for missing in e.missing_args:
                if not isinstance(missing, OutputArgument):
                    raise
                new_args.append(missing.name)

            routine = make_routine(name, expression, list(args) + new_args)

        routines.append(routine)

    if not os.path.exists(directory):
        os.makedirs(directory)

    cg = CCodeGen()

    [(cf, cs), (hf, hs)] = cg.write(routines, module_name + '_code')

    with open(directory + '/' + cf, "w") as text_file:
        text_file.write(cs)

    with open(directory + '/' + hf, "w") as text_file:
        text_file.write(hs)

    ccw = CythonCodeWrapper(cg)

    with open(directory + '/' + module_name + '.pyx', "w") as text_file:
        ccw.dump_pyx(routines, text_file, module_name + '_code')

    create_setup(module_name + '.pyx', module_name + '_code.c', directory,
                 module_name)

    open(directory + '/__init__.py', 'w').close()

    oldwork = os.getcwd()
    os.chdir(directory)
    workdir = os.getcwd()
    command = [sys.executable, "setup.py", "build_ext", "--inplace"]
    try:
        sys.path.append(workdir)
        retoutput = check_output(command, stderr=STDOUT)
    except CalledProcessError as e:
        raise CodeWrapError(
            "Error while executing command: %s. Command output is:\n%s" %
            (" ".join(command), e.output.decode()))

    finally:
        sys.path.remove(workdir)
        os.chdir(oldwork)
def tensorized_basis_2D(order):

    total_integration_points = (order + 1) * (order + 1)
    eps, eta, rho = sym.symbols("epsilon eta rho")
    eps_gll = sym.symbols("epsilon_0:%d" % (order + 1))
    eta_gll = sym.symbols("eta_0:%d" % (order + 1))

    # Get N + 1 lagrange polynomials in each direction.
    generator_eps = generating_polynomial_lagrange(order, "epsilon", eps_gll)
    generator_eta = generating_polynomial_lagrange(order, "eta", eta_gll)

    # Get tensorized basis.
    basis = TensorProduct(generator_eta, generator_eps)
    basis = basis.subs([(v, c) for v, c in zip(eps_gll, gll_coordinates(order))])
    basis = basis.subs([(v, c) for v, c in zip(eta_gll, gll_coordinates(order))])
    sym.pprint(basis)

    # Get gradient of basis functions.
    basis_gradient_eps = sym.Matrix([sym.diff(i, eps) for i in basis])
    basis_gradient_eta = sym.Matrix([sym.diff(i, eta) for i in basis])

    # Get diagonal mass matrix
    mass_matrix = rho * basis * basis.T
    mass_matrix_diagonal = sym.Matrix([mass_matrix[i, i] for i in range(total_integration_points)])

    # Write code
    routines = []
    autocode = CCodeGen()
    routines.append(autocode.routine("interpolate_order{}_square".format(order), basis, argument_sequence=None))
    routines.append(
        autocode.routine(
            "interpolate_eps_derivative_order{}_square".format(order), basis_gradient_eps, argument_sequence=None
        )
    )
    routines.append(
        autocode.routine(
            "interpolate_eta_derivative_order{}_square".format(order), basis_gradient_eta, argument_sequence=None
        )
    )
    routines.append(
        autocode.routine(
            "diagonal_mass_matrix_order{}_square".format(order), mass_matrix_diagonal, argument_sequence=None
        )
    )
    autocode.write(routines, "order{}_square".format(order), to_files=True)
Exemple #5
0
def genP3code():
    autocode = CCodeGen(project="Salvus")
    r,s = symbols("r,s")
    rsn = p3ReferenceNodes()
    Np = len(rsn)
    phi = p3ElementPolynomials(rsn,r,s)
    (dphi_dr,dphi_ds) = p3ElementDerivatives(phi,r,s)
    dphi_dr_rsn = np.zeros((Np,Np))
    dphi_ds_rsn = np.zeros((Np,Np))
    for i in range(0,Np):
        dphi_dr_i = lambdify((r,s),dphi_dr[i])
        dphi_ds_i = lambdify((r,s),dphi_ds[i])
        for (n,(rn,sn)) in enumerate(rsn):
            dphi_dr_rsn[i,n] = dphi_dr_i(rn,sn)
            dphi_ds_rsn[i,n] = dphi_ds_i(rn,sn)

    dphi_dr_rsn = Matrix(dphi_dr_rsn)
    dphi_ds_rsn = Matrix(dphi_ds_rsn)
    print(dphi_dr_rsn[0,:])
    rn = Matrix([ri for (ri,si) in rsn])
    sn = Matrix([si for (ri,si) in rsn])
    wn = Matrix(p3QuadratureWeights())
    rn_routine = autocode.routine("coordinates_p3_triangle_rn",rn,
                                  argument_sequence=None)
    sn_routine = autocode.routine("coordinates_p3_triangle_sn",sn,
                                  argument_sequence=None)
    wn_routine  = autocode.routine("quadrature_weights_p3_triangle",wn,
                                   argument_sequence=None)

    # NOTE: by default, it writes out in Row Major (so we write the
    # transpose). Salvus (via Eigen) assumes Column Major
    dphi_dr_rsn_routine  = autocode.routine("dphi_dr_rsn_p3_triangle",
                                            dphi_dr_rsn.transpose(),
                                            argument_sequence=None)
    dphi_ds_rsn_routine  = autocode.routine("dphi_ds_rsn_p3_triangle",
                                            dphi_ds_rsn.transpose(),
                                            argument_sequence=None)

    routines = [rn_routine,
                sn_routine,
                wn_routine,
                dphi_dr_rsn_routine,
                dphi_ds_rsn_routine]

    autocode.write(routines,"p3_triangle",to_files=True)
Exemple #6
0
def test_output_arg_c():
    from sympy import sin, cos, Equality
    x, y, z = symbols("x,y,z")
    r = Routine("foo", [Equality(y, sin(x)), cos(x)])
    c = CCodeGen()
    result = c.write([r], "test", header=False, empty=False)
    assert result[0][0] == "test.c"
    expected = ('#include "test.h"\n'
                '#include <math.h>\n'
                'double foo(double x, double &y) {\n'
                '   y = sin(x);\n'
                '   return cos(x);\n'
                '}\n')
    assert result[0][1] == expected
Exemple #7
0
def test_output_arg_c():
    from sympy import sin, cos, Equality
    x, y, z = symbols("x,y,z")
    r = Routine("foo", [Equality(y, sin(x)), cos(x)])
    c = CCodeGen()
    result = c.write([r], "test", header=False, empty=False)
    assert result[0][0] == "test.c"
    expected = (
        '#include "test.h"\n'
        '#include <math.h>\n'
        'double foo(double x, double &y) {\n'
        '   y = sin(x);\n'
        '   return cos(x);\n'
        '}\n'
    )
    assert result[0][1] == expected
Exemple #8
0
def _fixed_autowrap(energy_expr, prefix, save_filename=None):

    codegen = CCodeGen()

    routines = []
    _logger.debug('Writing code for energy_expr')
    routines.append(codegen.routine('autofunc', energy_expr))
    [(c_name, bad_c_code), (h_name, h_code)] = codegen.write(
        routines,
        prefix,
    )
    c_code = '#include <complex.h>\n'
    c_code += bad_c_code
    c_code = c_code.replace('conjugate', 'conj')

    write_directory = Path(tempfile.mkdtemp()).absolute()

    c_path = write_directory / Path(prefix + '.c')
    h_path = write_directory / Path(prefix + '.h')
    o_path = write_directory / Path(prefix + '.o')
    so_path = write_directory / Path(prefix + '.so')

    with open(c_path, 'w') as fh:
        fh.write(c_code)
        fh.write('\n')
    with open(h_path, 'w') as fh:
        fh.write(h_code)
        fh.write('\n')

    start = time.time()
    _logger.debug('Start compiling code.')
    os.system(f'gcc -c -lm {c_path} -o {o_path}')
    os.system(f'gcc -shared {o_path} -o {so_path}')
    _logger.debug(f'Compiling code took {time.time()-start} seconds.')

    if save_filename is not None:
        if Path(save_filename).exists():
            Path(save_filename).unlink()
        shutil.copy(so_path, save_filename)

    cost_func = _load_func(so_path)

    shutil.rmtree(write_directory)

    return cost_func
Exemple #9
0
def test_output_arg_c_reserved_words():
    from sympy import sin, cos, Equality
    x, y, z = symbols("if, while, z")
    r = make_routine("foo", [Equality(y, sin(x)), cos(x)])
    c = CCodeGen()
    result = c.write([r], "test", header=False, empty=False)
    assert result[0][0] == "test.c"
    expected = (
        '#include "test.h"\n'
        '#include <math.h>\n'
        'double foo(double if_, double *while_) {\n'
        '   (*while_) = sin(if_);\n'
        '   double foo_result;\n'
        '   foo_result = cos(if_);\n'
        '   return foo_result;\n'
        '}\n'
    )
    assert result[0][1] == expected
def run_cc_test(label, routines, numerical_tests, friendly=True):
    """A driver for the codegen tests.

       This driver assumes that a compiler cc is present in the PATH and that
       cc is (at least) an ANSI C compiler. The generated code is written in
       a temporary directory, together with a main program that validates the
       generated code. The test passes when the compilation and the validation
       run correctly.
    """
    # Do all the magic to compile, run and validate the test code
    # 1) prepare the temporary working directory, swith to that dir
    work = tempfile.mkdtemp("_sympy_cc_test", "%s_" % label)
    oldwork = os.getcwd()
    os.chdir(work)
    # 2) write the generated code
    if friendly:
        # interpret the routines as a name_expr list and call the friendly
        # function codegen
        codegen(routines, 'C', "codegen", to_files=True)
    else:
        code_gen = CCodeGen()
        code_gen.write(routines, "codegen", to_files=True)
    # 3) write a simple main program that links to the generated code, and that
    #    includes the numerical tests
    test_strings = []
    for fn_name, args, expected, threshold in numerical_tests:
        call_string = "%s(%s)-(%s)" % (fn_name, ",".join(str(arg) for arg in args), expected)
        test_strings.append(numerical_test_template % {
            "call": call_string,
            "threshold": threshold,
        })
    f = file("main.c", "w")
    f.write(main_template % "".join(test_strings))
    f.close()
    # 4) Compile and link
    compiled = try_run([
        "cc -c codegen.c -o codegen.o",
        "cc -c main.c -o main.o",
        "cc main.o codegen.o -lm -o test"
    ])
    # 5) Run if compiled
    if compiled:
        executed = try_run(["./test"])
    else:
        executed = False
    # 6) Clean up stuff
    clean = os.getenv('SYMPY_TEST_CLEAN_TEMP', 'always').lower()
    if clean not in ('always', 'success', 'never'):
        raise ValueError("SYMPY_TEST_CLEAN_TEMP must be one of the following: 'always', 'success' or 'never'.")
    if clean == 'always' or (clean == 'success' and compiled and executed):
        def safe_remove(filename):
            if os.path.isfile(filename):
                os.remove(filename)
        safe_remove("codegen.c")
        safe_remove("codegen.h")
        safe_remove("codegen.o")
        safe_remove("main.c")
        safe_remove("main.o")
        safe_remove("test")
        os.chdir(oldwork)
        os.rmdir(work)
    else:
        print >> sys.stderr, "TEST NOT REMOVED: %s" % work
        os.chdir(oldwork)
    # 7) Do the assertions in the end
    assert compiled
    assert executed
Exemple #11
0
def run_cc_test(label, routines, numerical_tests, friendly=True):
    """A driver for the codegen tests.

       This driver assumes that a compiler cc is present in the PATH and that
       cc is (at least) an ANSI C compiler. The generated code is written in
       a temporary directory, together with a main program that validates the
       generated code. The test passes when the compilation and the validation
       run correctly.
    """
    # Do all the magic to compile, run and validate the test code
    # 1) prepare the temporary working directory, swith to that dir
    work = tempfile.mkdtemp("_sympy_cc_test", "%s_" % label)
    oldwork = os.getcwd()
    os.chdir(work)
    # 2) write the generated code
    if friendly:
        # interpret the routines as a name_expr list and call the friendly
        # function codegen
        codegen(routines, 'C', "codegen", to_files=True)
    else:
        code_gen = CCodeGen()
        code_gen.write(routines, "codegen", to_files=True)
    # 3) write a simple main program that links to the generated code, and that
    #    includes the numerical tests
    test_strings = []
    for fn_name, args, expected, threshold in numerical_tests:
        call_string = "%s(%s)-(%s)" % (fn_name, ",".join(
            str(arg) for arg in args), expected)
        test_strings.append(numerical_test_template % {
            "call": call_string,
            "threshold": threshold,
        })
    f = file("main.c", "w")
    f.write(main_template % "".join(test_strings))
    f.close()
    # 4) Compile and link
    compiled = try_run([
        "cc -c codegen.c -o codegen.o", "cc -c main.c -o main.o",
        "cc main.o codegen.o -lm -o test"
    ])
    # 5) Run if compiled
    if compiled:
        executed = try_run(["./test"])
    else:
        executed = False
    # 6) Clean up stuff
    clean = os.getenv('SYMPY_TEST_CLEAN_TEMP', 'always').lower()
    if clean not in ('always', 'success', 'never'):
        raise ValueError(
            "SYMPY_TEST_CLEAN_TEMP must be one of the following: 'always', 'success' or 'never'."
        )
    if clean == 'always' or (clean == 'success' and compiled and executed):

        def safe_remove(filename):
            if os.path.isfile(filename):
                os.remove(filename)

        safe_remove("codegen.c")
        safe_remove("codegen.h")
        safe_remove("codegen.o")
        safe_remove("main.c")
        safe_remove("main.o")
        safe_remove("test")
        os.chdir(oldwork)
        os.rmdir(work)
    else:
        print >> sys.stderr, "TEST NOT REMOVED: %s" % work
        os.chdir(oldwork)
    # 7) Do the assertions in the end
    assert compiled
    assert executed
Exemple #12
0
def _make_energy_func_chunked(energy_expr_list, prefix, save_filename=None):

    codegen = CCodeGen()

    routines = []
    for i, expr in enumerate(energy_expr_list):
        _logger.debug(f'Writing code for expr {i} of {len(energy_expr_list)}')
        routines.append(codegen.routine('expr' + str(i), expr))
    [(c_name, bad_c_code), (h_name, h_code)] = codegen.write(
        routines,
        prefix,
    )
    c_code = '#include <complex.h>\n'
    c_code += bad_c_code
    c_code += """
double autofunc(double *xs){

    double autofunc_result;
    autofunc_result = %s;
    return autofunc_result;

}
""" % ('+'.join(
        ['expr' + str(i) + '(xs)' for i in range(len(energy_expr_list))]))
    c_code = c_code.replace('conjugate', 'conj')

    h_code = h_code.replace('\n#endif', """double autofunc(double *xs);

#endif
""")

    write_directory = Path(tempfile.mkdtemp()).absolute()

    c_path = write_directory / Path(prefix + '.c')
    h_path = write_directory / Path(prefix + '.h')
    o_path = write_directory / Path(prefix + '.o')
    so_path = write_directory / Path(prefix + '.so')

    with open(c_path, 'w') as fh:
        fh.write(c_code)
        fh.write('\n')
    with open(h_path, 'w') as fh:
        fh.write(h_code)
        fh.write('\n')

    start = time.time()
    _logger.debug('Start compiling code.')
    os.system(f'gcc -c -lm -fPIC {c_path} -o {o_path}')
    os.system(f'gcc -shared -fPIC {o_path} -o {so_path}')
    _logger.debug(f'Compiling code took {time.time()-start} seconds.')

    if save_filename is not None:
        if Path(save_filename).exists():
            Path(save_filename).unlink()
        shutil.copy(so_path, save_filename)

    cost_func = _load_func(so_path)

    shutil.rmtree(write_directory)

    return cost_func
    
print mass_matrix_int
print boun_shell_tops

# // INTEGRATE STIFFNESS MATRIX //
print 'Integrating stiffness matrix...'
stiffness_matrix = dN.T * C * dN
stiffness_matrix = stiffness_matrix.subs(replace_e)
stiffness_matrix = stiffness_matrix.subs(replace_n)
stiffness_matrix_int = sym.Matrix.zeros(dof_tot, dof_tot)
for c_e, w_x in zip(coords, weights):
    for c_n, w_y in zip(coords, weights):
        stiffness_matrix_int += stiffness_matrix.subs(
            [(e, c_e), (n, c_n)]) * w_x * w_y * Jdet

routines.append(sem_c.routine(
    'stiffness_matrix', stiffness_matrix_int, argument_sequence=None))

# // OUTPUT DERIVATIVES //
print 'Writing derivatives of shape functions.'
routines.append(sem_c.routine(
    'shape_derivatives', grad_N, argument_sequence=None))

# // OUTPUT JACOBIAN //
print 'Writing Jacobian function.'
routines.append(sem_c.routine(
    'eval_jacobian', J, argument_sequence=None))

print 'Writing functions...'
sem_c.write(routines, './src/functions', to_files=True)
def genP3code():
    autocode = CCodeGen(project="Salvus")
    r, s, t = symbols("r,s,t")
    rstn = p3ReferenceNodes()
    (rn, sn, tn) = rstn
    Np = len(rn)
    phi = p3ElementPolynomials(rstn, r, s, t)
    (dphi_dr, dphi_ds, dphi_dt) = p3ElementDerivatives(phi, r, s, t)
    dphi_dr_rstn = np.zeros((Np, Np))
    dphi_ds_rstn = np.zeros((Np, Np))
    dphi_dt_rstn = np.zeros((Np, Np))
    for i in range(0, Np):
        dphi_dr_i = lambdify((r, s, t), dphi_dr[i])
        dphi_ds_i = lambdify((r, s, t), dphi_ds[i])
        dphi_dt_i = lambdify((r, s, t), dphi_dt[i])
        for (n, (ri, si, ti)) in enumerate(zip(rn, sn, tn)):
            dphi_dr_rstn[i, n] = dphi_dr_i(ri, si, ti)
            dphi_ds_rstn[i, n] = dphi_ds_i(ri, si, ti)
            dphi_dt_rstn[i, n] = dphi_dt_i(ri, si, ti)

    dphi_dr_rstn = Matrix(dphi_dr_rstn)
    dphi_ds_rstn = Matrix(dphi_ds_rstn)
    dphi_dt_rstn = Matrix(dphi_dt_rstn)

    rn = Matrix([ri for (ri, si, ti) in zip(rn, sn, tn)])
    sn = Matrix([si for (ri, si, ti) in zip(rn, sn, tn)])
    tn = Matrix([ti for (ri, si, ti) in zip(rn, sn, tn)])
    wn = Matrix(p3QuadratureWeights())
    rn_routine = autocode.routine("coordinates_p3_tetrahedra_rn",
                                  rn,
                                  argument_sequence=None)
    sn_routine = autocode.routine("coordinates_p3_tetrahedra_sn",
                                  sn,
                                  argument_sequence=None)
    tn_routine = autocode.routine("coordinates_p3_tetrahedra_tn",
                                  tn,
                                  argument_sequence=None)
    wn_routine = autocode.routine("quadrature_weights_p3_tetrahedra",
                                  wn,
                                  argument_sequence=None)

    # NOTE: writes out in Row Major (so we write the
    # transpose). Salvus (via Eigen) assumes Column Major
    dphi_dr_rstn_routine = autocode.routine("dphi_dr_rstn_p3_tetrahedra",
                                            dphi_dr_rstn.transpose(),
                                            argument_sequence=None)
    dphi_ds_rstn_routine = autocode.routine("dphi_ds_rstn_p3_tetrahedra",
                                            dphi_ds_rstn.transpose(),
                                            argument_sequence=None)
    dphi_dt_rstn_routine = autocode.routine("dphi_dt_rstn_p3_tetrahedra",
                                            dphi_dt_rstn.transpose(),
                                            argument_sequence=None)

    routines = [
        rn_routine, sn_routine, tn_routine, wn_routine, dphi_dr_rstn_routine,
        dphi_ds_rstn_routine, dphi_dt_rstn_routine
    ]

    autocode.write(routines, "p3_tetrahedra", to_files=True)

    buildVisualizationP3(rn, sn, tn)
	# Get gradient of basis functions
	gn = sym.Matrix(([sym.diff(i, eta) for i in n])).T
	sym.pprint(gn)

	# Mass matrix
	mm = (rho * n.T * n)
	mm = sym.Matrix([mm[i,i] for i in range(nPtsPelm)])

	# Get mapping
	m = sym.Matrix(getMap(nPtsPvtx, nPtsPedg, nPtsPfac))

	# Write code
	routines = []
	sem_c = CCodeGen()
	routines.append(sem_c.routine(
		'interpolateOrder%dDim%d' % (args.order, args.dimension), n,
		argument_sequence=None))
	routines.append(sem_c.routine(
      'massMatrixOrder%dDim%d' % (args.order, args.dimension), mm, 
      argument_sequence=None))
	routines.append(sem_c.routine(
      'gradientOperatorOrder%dDim%d' % (args.order, args.dimension), gn, 
      argument_sequence=None))
	routines.append(sem_c.routine(
      'mappingOrder%dDim%d' % (args.order, args.dimension), m, 
      argument_sequence=None))	
	sem_c.write(
		routines, 'auto/order%dDim%d' % (args.order, args.dimension), 
		to_files=True)