⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compile_functions.py

📁 利用C
💻 PY
字号:
"This module provides functionality for compilation of strings as dolfin Functions."__author__ = "Martin Sandve Alnes (martinal@simula.no)"__date__ = "2008-06-04 -- 2008-06-04"__copyright__ = "Copyright (C) 2008-2008 Martin Sandve Alnes"__license__  = "GNU LGPL Version 2.1"import reimport numpyimport instant__all__ = ["compile_functions",]# FIXME: Extend this list, needed to autodetect variable names that are not builtins_builtins = [             # local symbols:             "v", "x", "_dim", "pi",             # cmath funcions:             "cos", "sin", "tan", "acos", "asin", "atan", "atan2",             "cosh", "sinh", "tanh",             "exp", "frexp", "ldexp", "log", "log10", "modf",             "pow", "sqrt", "ceil", "fabs", "floor", "fmod",            ]# Add utility code here_header = """// cmath functionsusing std::cos;using std::sin;using std::tan;using std::acos;using std::asin;using std::atan;using std::atan2;using std::cosh;using std::sinh;using std::tanh;using std::exp;using std::frexp;using std::ldexp;using std::log;using std::log10;using std::modf;using std::pow;using std::sqrt;using std::ceil;using std::fabs;using std::floor;using std::fmod;const double pi = acos(-1.0);"""_function_template = """class %(classname)s: public dolfin::Function{public:  unsigned _dim;%(members)s  %(classname)s(dolfin::Mesh & mesh):    dolfin::Function(mesh)  {    _dim = mesh.geometry().dim();%(constructor)s  }  void eval(real* v, const real* x) const  {%(eval)s  }%(rank)s%(dim)s};"""_ranktemplate = """\  dolfin::uint rank() const  {    return %d;  }"""_dimtemplate = """\  dolfin::uint dim(dolfin::uint i) const  {    switch(i) {%s    }    throw std::runtime_error("Invalid dimension i in dim(i).");  }"""def expression_to_function(e, classname):    "Generates code for a dolfin::Function subclass for a single expression."    # Get shape from e and make e a flat tuple of strings    if isinstance(e, str):        e = (e,)        shape = ()    elif isinstance(e, tuple):        if isinstance(e[0], str):            shape = (len(e),)        elif isinstance(e[0], tuple):            shape = (len(e),len(e[0]))            assert isinstance(e[0][0], str)            e = sum(e, ())    else:        raise RuntimeError("Invalid expression %s" % e)    # Autodetect variables from function strings    variables = set()    for c in e:        # Find groups of connected alphanumeric letters        variables.update(re.findall(r"([\w]+)", c))    variables.difference_update(_builtins)    numerals = [v for v in variables if v[0] in "0123456789"]    variables.difference_update(numerals)        # Generate code for member variables    memberscode = "\n".join("  double %s;" % name for name in variables)        # Generate constructor code for initialization of member variables    constructorcode = "\n".join("    %s = 0.0;" % name for name in variables)        # Generate code for rank and dim    if len(shape) > 0:        rankcode = _ranktemplate % len(shape)        cases = "\n".join("      case %d: return %d;" % (d,n) for (d,n) in enumerate(shape))        dimcode = _dimtemplate % cases    else:        dimcode  = ""        rankcode = ""        # Generate code for the actual function evaluation    evalcode = "\n".join("    v[%d] = %s;" % (i, c) for (i,c) in enumerate(e))        # Connect the code fragments using the function template code    fragments = {}    fragments["classname"] = classname    fragments["members"]   = memberscode    fragments["rank"]      = rankcode    fragments["dim"]       = dimcode    fragments["eval"]      = evalcode    fragments["constructor"] = constructorcode    code = _function_template % fragments    return code_function_count = 0def generate_functions(expressions):    "Generates code for dolfin::Function subclasses for a list of expressions."    global _function_count    assert isinstance(expressions, list)    code = ""    classnames = []    for e in expressions:        classname = "function_%d" % _function_count        code += expression_to_function(e, classname)        classnames.append(classname)        _function_count += 1    return code, classnames# NB! This code is highly dependent on the dolfin swig setup!_additional_declarations = r"""%rename(cpp_Function) Function;%include exception.i%include cpointer.i%pointer_class(int, intp);%pointer_class(double, doublep);%include std_vector.i%template(STLVectorFunctionPtr) std::vector<dolfin::Function *>;%import dolfin.i"""    _additional_definitions  = """#include <dolfin.h>using namespace dolfin;#include <numpy/arrayobject.h>"""_module_count = 0def compile_function_code(code, mesh, classnames=None, module_name=None):    # Create unique module name for this application run    global _module_count, _header, _additional_definitions, _additional_declarations    if module_name is None:        module_name = "functions_%d" % _module_count        _module_count += 1    # Autodetect classnames:    _classnames = re.findall(r"class[ ]+([\w]+).*", code)    # Just a little assertion for safety:    if classnames is None:        classnames = _classnames    else:        assert all(a == b for (a,b) in zip(classnames, _classnames))        # Get system configuration       (includes, flags, libraries, libdirs) = instant.header_and_libs_from_pkgconfig("dolfin")    dolfin_include_dir = includes[0] # FIXME: is this safe?    numpy_dir = numpy.get_include()    includes.append(numpy_dir)        sysheaders = ["cmath", "iostream", "stdexcept",                  "dolfin.h", "dolfin/mesh/Mesh.h", "dolfin/function/Function.h"]        # FIXME: use dolfin flags?    cppargs = flags    cppargs = " ".join(flags)    cppargs = ""        # Let swig see the installed dolfin swig files    swigopts = "-c++ -I%s -I%s/dolfin/swig" % (dolfin_include_dir, dolfin_include_dir)        # Compile extension module with instant    compiled_module = instant.create_extension(\             code           = _header + code,             module         = module_name,             swigopts       = swigopts,             system_headers = sysheaders,             include_dirs   = includes,             cppargs        = cppargs,             libraries      = libraries,             library_dirs   = libdirs,             additional_definitions  = _additional_definitions,             additional_declarations = _additional_declarations             )    compiled_module = __import__(module_name)        # Construct instances of the compiled functor classes    functions = [eval("compiled_module.%s(mesh)" % name) for name in classnames]    return functionsdef compile_functions(expressions, mesh):    """Compiles C++ string expressions into dolfin::Function instances.        The variable 'expressions' can either be a str or a list.        If 'expressions' is a str, it is interpreted as a C++ string    with complete implementations of subclasses of dolfin::Function.    The compiled functions returned will be in the same order     as they are defined in this code.    If it is a list, each item of the list is interpreted as    a function expression, and the compiled functions returned    will be in the same order as they occur in this list.        Each expression item in the list can either be a str,    in which case it is interpreted as a scalar expression    and a scalar Function is generated, or it can be a tuple.        A tuple of str objects is interpreted as a vector expression,    and a rank 1 Function is generated.        A tuple of tuples of str objects is interpreted as a matrix    expression, and a rank 2 Function is generated.    If an expression string contains a name, it is assumed to    be a scalar variable name, and is added as a public member    of the generated function. The exceptions are set in the    variable dolfin.compile_functions._builtins."""    #, which contains:    #    %s    #""" % "\n".join("        " + b for b in _builtins)    if isinstance(expressions, list):        code, classnames = generate_functions(expressions)        functions = compile_function_code(code, mesh, classnames)    else:        functions = compile_function_code(expressions, mesh)    return functionsif __name__ == "__main__":    code, cn = generate_functions([                              "exp(alpha)",                              ("sin(x[0])", "cos(x[1])", "0.0"),                              (("sin(x[0])", "cos(x[1])"), ("0.0", "1.0"))                             ])    print code    print cn

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -