pycalphad.codegen package

Submodules

pycalphad.codegen.callables module

pycalphad.codegen.callables.build_callables(dbf, comps, phases, model=None, parameters=None, callables=None, output='GM', build_gradients=True, verbose=False)[source]

Create dictionaries of callable dictionaries and PhaseRecords.

Parameters:
  • dbf (Database) – A Database object
  • comps (list) – List of component names
  • phases (list) – List of phase names
  • model (dict or type) – Dictionary of {phase_name: Model subclass} or a type corresponding to a Model subclass. Defaults to Model.
  • parameters (dict, optional) – Maps SymPy Symbol to numbers, for overriding the values of parameters in the Database.
  • callables (dict, optional) – Pre-computed callables
  • output (str) – Output property of the particular Model to sample
  • build_gradients (bool) – Whether or not to build gradient functions. Defaults to True.
  • verbose (bool) – Print the name of the phase when its callables are built
Returns:

callables – Dictionary of keyword argument callables to pass to equilibrium.

Return type:

dict

Example

>>> dbf = Database('AL-NI.tdb')
>>> comps = ['AL', 'NI', 'VA']
>>> phases = ['FCC_L12', 'BCC_B2', 'LIQUID', 'AL3NI5', 'AL3NI2', 'AL3NI']
>>> callables = build_callables(dbf, comps, phases)
>>> equilibrium(dbf, comps, phases, conditions, **callables)
pycalphad.codegen.callables.wrap_symbol(obj)[source]

pycalphad.codegen.custom_autowrap module

Module for compiling codegen output, and wrap the binary for use in python.

Note

To use the autowrap module it must first be imported

>>> from sympy.utilities.autowrap import autowrap

This module provides a common interface for different external backends, such as f2py, fwrap, Cython, SWIG(?) etc. (Currently only f2py and Cython are implemented) The goal is to provide access to compiled binaries of acceptable performance with a one-button user interface, i.e.

>>> from sympy.abc import x,y
>>> expr = ((x - y)**(25)).expand()
>>> binary_callable = autowrap(expr)
>>> binary_callable(1, 2)
-1.0

The callable returned from autowrap() is a binary python function, not a SymPy object. If it is desired to use the compiled function in symbolic expressions, it is better to use binary_function() which returns a SymPy Function object. The binary callable is attached as the _imp_ attribute and invoked when a numerical evaluation is requested with evalf(), or with lambdify().

>>> from sympy.utilities.autowrap import binary_function
>>> f = binary_function('f', expr)
>>> 2*f(x, y) + y
y + 2*f(x, y)
>>> (2*f(x, y) + y).evalf(2, subs={x: 1, y:2})
0.e-110

The idea is that a SymPy user will primarily be interested in working with mathematical expressions, and should not have to learn details about wrapping tools in order to evaluate expressions numerically, even if they are computationally expensive.

When is this useful?

  1. For computations on large arrays, Python iterations may be too slow, and depending on the mathematical expression, it may be difficult to exploit the advanced index operations provided by NumPy.
  2. For really long expressions that will be called repeatedly, the compiled binary should be significantly faster than SymPy’s .evalf()
  3. If you are generating code with the codegen utility in order to use it in another project, the automatic python wrappers let you test the binaries immediately from within SymPy.
  4. To create customized ufuncs for use with numpy arrays. See ufuncify.

When is this module NOT the best approach?

  1. If you are really concerned about speed or memory optimizations, you will probably get better results by working directly with the wrapper tools and the low level code. However, the files generated by this utility may provide a useful starting point and reference code. Temporary files will be left intact if you supply the keyword tempdir=”path/to/files/”.
  2. If the array computation can be handled easily by numpy, and you don’t need the binaries for another project.
class pycalphad.codegen.custom_autowrap.C89CodePrinter(settings={})[source]

Bases: sympy.printing.ccode.C89CodePrinter

C89-compatible code printing allows for Windows compatibility. (MSVC 14 and newer support C99, but we are going for broad compatibility.)

order = 'none'
exception pycalphad.codegen.custom_autowrap.CodeWrapError[source]

Bases: Exception

class pycalphad.codegen.custom_autowrap.CustomCCodeGen(project='project', printer=None, preprocessor_statements=None, cse=False)[source]

Bases: sympy.utilities.codegen.CCodeGen

dump_fns = [<function CCodeGen.dump_c>, <function CustomCCodeGen.dump_h>]
dump_h(routines, f, prefix, header=True, empty=True)[source]

Writes the C header file.

This file contains all the function declarations.

Parameters:
  • routines (list) – A list of Routine instances.
  • f (file-like) – Where to write the file.
  • prefix (string) – The filename prefix, used to construct the include guards. Only the basename of the prefix is used.
  • header (bool, optional) – When True, a header comment is included on top of each source file. [default : True]
  • empty (bool, optional) – When True, empty lines are included to structure the source files. [default : True]
get_prototype(routine)[source]

Returns a string for the function prototype of the routine.

If the routine has multiple result objects, an CodeGenError is raised.

See: http://en.wikipedia.org/wiki/Function_prototype

routine(name, expr, argument_sequence, global_vars)[source]

Creates an Routine object that is appropriate for this language.

This implementation is appropriate for at least C/Fortran. Subclasses can override this if necessary.

Here, we assume at most one return value (the l-value) which must be scalar. Additional outputs are OutputArguments (e.g., pointers on right-hand-side or pass-by-reference). Matrices are always returned via OutputArguments. If argument_sequence is None, arguments will be ordered alphabetically, but with all InputArguments first, and then OutputArgument and InOutArguments.

This implementation is almost the same as the CodeGen class, but expensive calls to Basic.atoms() have been replaced with cheaper equivalents.

class pycalphad.codegen.custom_autowrap.ThreadSafeCythonCodeWrapper(*args, **kwargs)[source]

Bases: sympy.utilities.autowrap.CythonCodeWrapper

command
filename
module_name
pyx_func = 'def {name}_c({arg_string}):\n\n{declarations}{body}\ndef get_pointer_c():\n return PyCapsule_New(<void*>{name}, NULL, NULL)\n'
pyx_header = "cdef extern from '{header_file}.h':\n {prototype}\n\n"
pyx_imports = 'import numpy as np\ncimport numpy as np\nfrom cpython cimport PyCapsule_New\n\n'
setup_template = "from distutils.core import setup\nfrom distutils.extension import Extension\nfrom Cython.Distutils import build_ext\n{np_import}\nsetup(\n cmdclass = {{'build_ext': build_ext}},\n ext_modules = [Extension({ext_args},\n extra_compile_args=['-std=c99'])],\n{np_includes} )"
wrap_code(routine, helpers=None)[source]
pycalphad.codegen.custom_autowrap.autowrap(expr, language=None, backend='Cython', tempdir=None, args=None, flags=None, verbose=False, helpers=None)[source]

Generates python callable binaries based on the math expression.

Parameters:
  • expr – The SymPy expression that should be wrapped as a binary routine.
  • language (string, optional) – If supplied, (options: ‘C’ or ‘F95’), specifies the language of the generated code. If None [default], the language is inferred based upon the specified backend.
  • backend (string, optional) – Backend used to wrap the generated code. Either ‘f2py’, or ‘cython’ [default].
  • tempdir (string, optional) – Path to directory for temporary files. If this argument is supplied, the generated code and the wrapper input files are left intact in the specified path.
  • args (iterable, optional) – An ordered iterable of symbols. Specifies the argument sequence for the function.
  • flags (iterable, optional) – Additional option flags that will be passed to the backend.
  • verbose (bool, optional) – If True, autowrap will not mute the command line backends. This can be helpful for debugging.
  • helpers (iterable, optional) – Used to define auxillary expressions needed for the main expr. If the main expression needs to call a specialized function it should be put in the helpers iterable. Autowrap will then make sure that the compiled main expression can link to the helper routine. Items should be tuples with (<funtion_name>, <sympy_expression>, <arguments>). It is mandatory to supply an argument sequence to helper routines.
  • from sympy.abc import x, y, z (>>>) –
  • from sympy.utilities.autowrap import autowrap (>>>) –
  • expr = ((x - y + z)**(13))expand() (>>>) –
  • binary_func = autowrap(expr) (>>>) –
  • binary_func(1, 4, 2) (>>>) –
  • -1.0
pycalphad.codegen.custom_autowrap.binary_function(symfunc, expr, **kwargs)[source]

Returns a sympy function with expr as binary implementation

This is a convenience function that automates the steps needed to autowrap the SymPy expression and attaching it to a Function object with implemented_function().

>>> from sympy.abc import x, y
>>> from sympy.utilities.autowrap import binary_function
>>> expr = ((x - y)**(25)).expand()
>>> f = binary_function('f', expr)
>>> type(f)
<class 'sympy.core.function.UndefinedFunction'>
>>> 2*f(x, y)
2*f(x, y)
>>> f(x, y).evalf(2, subs={x: 1, y: 2})
-1.0
pycalphad.codegen.custom_autowrap.get_code_generator(language, project)[source]
pycalphad.codegen.custom_autowrap.import_extension(path, modname)[source]
pycalphad.codegen.custom_autowrap.make_routine(name, expr, argument_sequence=None, global_vars=None, language='C')[source]

A factory that makes an appropriate Routine from an expression.

Parameters:
  • name (string) – The name of this routine in the generated code.
  • expr (expression or list/tuple of expressions) – A SymPy expression that the Routine instance will represent. If given a list or tuple of expressions, the routine will be considered to have multiple return values and/or output arguments.
  • argument_sequence (list or tuple, optional) – List arguments for the routine in a preferred order. If omitted, the results are language dependent, for example, alphabetical order or in the same order as the given expressions.
  • global_vars (iterable, optional) – Sequence of global variables used by the routine. Variables listed here will not show up as function arguments.
  • language (string, optional) – Specify a target language. The Routine itself should be language-agnostic but the precise way one is created, error checking, etc depend on the language. [default: “F95”].
  • decision about whether to use output arguments or return values is made (A) –
  • on both the language and the particular mathematical expressions. (depending) –
  • an expression of type Equality, the left hand side is typically made (For) –
  • an OutputArgument (or perhaps an InOutArgument if appropriate) (into) –
  • typically, the calculated expression is made a return values of (Otherwise,) –
  • routine. (the) –

Examples

>>> from sympy.utilities.codegen import make_routine
>>> from sympy.abc import x, y, f, g
>>> from sympy import Eq
>>> r = make_routine('test', [Eq(f, 2*x), Eq(g, x + y)])
>>> [arg.result_var for arg in r.results]
[]
>>> [arg.name for arg in r.arguments]
[x, y, f, g]
>>> [arg.name for arg in r.result_variables]
[f, g]
>>> r.local_vars
set()

Another more complicated example with a mixture of specified and automatically-assigned names. Also has Matrix output.

>>> from sympy import Matrix
>>> r = make_routine('fcn', [x*y, Eq(f, 1), Eq(g, x + g), Matrix([[x, 2]])])
>>> [arg.result_var for arg in r.results]  # doctest: +SKIP
[result_5397460570204848505]
>>> [arg.expr for arg in r.results]
[x*y]
>>> [arg.name for arg in r.arguments]  # doctest: +SKIP
[x, y, f, g, out_8598435338387848786]

We can examine the various arguments more closely:

>>> from sympy.utilities.codegen import (InputArgument, OutputArgument,
...                                      InOutArgument)
>>> [a.name for a in r.arguments if isinstance(a, InputArgument)]
[x, y]
>>> [a.name for a in r.arguments if isinstance(a, OutputArgument)]  # doctest: +SKIP
[f, out_8598435338387848786]
>>> [a.expr for a in r.arguments if isinstance(a, OutputArgument)]
[1, Matrix([[x, 2]])]
>>> [a.name for a in r.arguments if isinstance(a, InOutArgument)]
[g]
>>> [a.expr for a in r.arguments if isinstance(a, InOutArgument)]
[g + x]

pycalphad.codegen.sympydiff_utils module

This module constructs gradient functions for Models.

class pycalphad.codegen.sympydiff_utils.AutowrapFunction(sympy_vars, sympy_obj)[source]

Bases: pycalphad.codegen.sympydiff_utils.PickleableFunction

compile()[source]
class pycalphad.codegen.sympydiff_utils.PickleableFunction(sympy_vars, sympy_obj)[source]

Bases: object

A compiled function that is recompiled when unpickled. This works around several issues with sending JIT’d functions over the wire. This approach means only the underlying SymPy object must be pickleable. This also means multiprocessing using fork() will NOT force a recompile.

compile()[source]
kernel
pycalphad.codegen.sympydiff_utils.build_functions(sympy_graph, variables, wrt=None, include_obj=True, include_grad=True, parameters=None)[source]
Parameters:
  • sympy_graph
  • variables (tuple of Symbols) – Input arguments.
  • wrt (tuple of Symbols, optional) – Variables to differentiate with respect to. (Default: equal to variables)
  • include_obj
  • include_grad
  • parameters
Returns:

Return type:

One or more functions.

pycalphad.codegen.sympydiff_utils.chunks(l, n)[source]

Yield successive n-sized chunks from l. Source: http://stackoverflow.com/questions/312443/how-do-you-split-a-list-into-evenly-sized-chunks-in-python

Module contents