~johan-hake/dolfin/general-rk-solver

« back to all changes in this revision

Viewing changes to site-packages/dolfin_utils/wrappers/wrappers.py

  • Committer: Johan Hake
  • Date: 2013-03-27 15:18:08 UTC
  • mfrom: (7352.1.227 working)
  • Revision ID: hake.dev@gmail.com-20130327151808-b73d4pueq1n432hg
Merge with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2011 Marie E. Rognes
2
 
#
3
 
# This file is part of DOLFIN.
4
 
#
5
 
# DOLFIN is free software: you can redistribute it and/or modify
6
 
# it under the terms of the GNU Lesser General Public License as published by
7
 
# the Free Software Foundation, either version 3 of the License, or
8
 
# (at your option) any later version.
9
 
#
10
 
# DOLFIN is distributed in the hope that it will be useful,
11
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 
# GNU Lesser General Public License for more details.
14
 
#
15
 
# You should have received a copy of the GNU Lesser General Public License
16
 
# along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
17
 
#
18
 
# Based on original implementation by Martin Alnes and Anders Logg
19
 
#
20
 
# Last changed: 2012-12-05
21
 
 
22
 
import includes as incl
23
 
from functionspace import *
24
 
from form import generate_form
25
 
from capsules import UFCElementNames
26
 
 
27
 
__all__ = ["generate_dolfin_code"]
28
 
 
29
 
# NB: generate_dolfin_namespace(...) assumes that if a coefficient has
30
 
# the same name in multiple forms, it is indeed the same coefficient:
31
 
parameters = {"use_common_coefficient_names": True}
32
 
 
33
 
#-------------------------------------------------------------------------------
34
 
def generate_dolfin_code(prefix, header, forms,
35
 
                         common_function_space=False, add_guards=False,
36
 
                         error_control=False):
37
 
    """Generate complete dolfin wrapper code with given generated names.
38
 
 
39
 
    @param prefix:
40
 
        String, prefix for all form names.
41
 
    @param header:
42
 
        Code that will be inserted at the top of the file.
43
 
    @param forms:
44
 
        List of UFCFormNames instances or single UFCElementNames.
45
 
    @param common_function_space:
46
 
        True if common function space, otherwise False
47
 
    @param add_guards:
48
 
        True iff guards (ifdefs) should be added
49
 
    @param error_control:
50
 
        True iff adaptivity typedefs (ifdefs) should be added
51
 
    """
52
 
 
53
 
    # Generate dolfin namespace
54
 
    namespace = generate_dolfin_namespace(prefix, forms, common_function_space,
55
 
                                          error_control)
56
 
 
57
 
    # Collect pieces of code
58
 
    code = [incl.dolfin_tag, header, incl.stl_includes, incl.dolfin_includes,
59
 
            namespace]
60
 
 
61
 
    # Add ifdefs/endifs if specified
62
 
    if add_guards:
63
 
        guard_name = ("%s_h" % prefix).upper()
64
 
        preguard = "#ifndef %s\n#define %s\n" % (guard_name, guard_name)
65
 
        postguard = "\n#endif\n\n"
66
 
        code = [preguard] + code + [postguard]
67
 
 
68
 
    # Return code
69
 
    return "\n".join(code)
70
 
 
71
 
#-------------------------------------------------------------------------------
72
 
def generate_dolfin_namespace(prefix, forms, common_function_space=False,
73
 
                              error_control=False):
74
 
 
75
 
    # Allow forms to represent a single space, and treat separately
76
 
    if isinstance(forms, UFCElementNames):
77
 
        return generate_single_function_space(prefix, forms)
78
 
 
79
 
    # Extract (common) coefficient spaces
80
 
    assert(parameters["use_common_coefficient_names"])
81
 
    spaces = extract_coefficient_spaces(forms)
82
 
 
83
 
    # Generate code for common coefficient spaces
84
 
    code = [apply_function_space_template(*space) for space in spaces]
85
 
 
86
 
    # Generate code for forms
87
 
    code += [generate_form(form, "Form_%s" % form.name) for form in forms]
88
 
 
89
 
    # Generate namespace typedefs (Bilinear/Linear & Test/Trial/Function)
90
 
    code += [generate_namespace_typedefs(forms, common_function_space,
91
 
                                         error_control)]
92
 
 
93
 
    # Wrap code in namespace block
94
 
    code = "\nnamespace %s\n{\n\n%s\n}" % (prefix, "\n".join(code))
95
 
 
96
 
    # Return code
97
 
    return code
98
 
 
99
 
#-------------------------------------------------------------------------------
100
 
def generate_single_function_space(prefix, space):
101
 
    code = apply_function_space_template("FunctionSpace",
102
 
                                         space.ufc_finite_element_classnames[0],
103
 
                                         space.ufc_dofmap_classnames[0])
104
 
    code = "\nnamespace %s\n{\n\n%s\n}" % (prefix, code)
105
 
    return code
106
 
 
107
 
#-------------------------------------------------------------------------------
108
 
def generate_namespace_typedefs(forms, common_function_space, error_control):
109
 
 
110
 
    # Generate typedefs as (fro, to) pairs of strings
111
 
    pairs = []
112
 
 
113
 
    # Add typedef for Functional/LinearForm/BilinearForm if only one
114
 
    # is present of each
115
 
    aliases = ["Functional", "LinearForm", "BilinearForm"]
116
 
    extra_aliases = {"LinearForm": "ResidualForm", "BilinearForm": "JacobianForm"}
117
 
    for rank in sorted(range(len(aliases)), reverse=True):
118
 
        forms_of_rank = [form for form in forms if form.rank == rank]
119
 
        if len(forms_of_rank) == 1:
120
 
            pairs += [("Form_%s" % forms_of_rank[0].name, aliases[rank])]
121
 
            if aliases[rank] in extra_aliases:
122
 
                extra_alias = extra_aliases[aliases[rank]]
123
 
                pairs += [("Form_%s" % forms_of_rank[0].name, extra_alias)]
124
 
 
125
 
    # Keepin' it simple: Add typedef for FunctionSpace if term applies
126
 
    if common_function_space:
127
 
        for i, form in enumerate(forms):
128
 
            if form.rank:
129
 
                pairs += [("Form_%s::TestSpace" % form.name, "FunctionSpace")]
130
 
                break
131
 
 
132
 
    # Add specialized typedefs when adding error control wrapppers
133
 
    if error_control:
134
 
        pairs += error_control_pairs(forms)
135
 
 
136
 
    # Combine data to typedef code
137
 
    typedefs = "\n".join("typedef %s %s;" % (to, fro) for (to, fro) in pairs)
138
 
 
139
 
    # Return typedefs or ""
140
 
    if not typedefs:
141
 
        return ""
142
 
    return "// Class typedefs\n" + typedefs + "\n"
143
 
 
144
 
#-------------------------------------------------------------------------------
145
 
def error_control_pairs(forms):
146
 
    assert (len(forms) == 11), "Expecting 11 error control forms"
147
 
 
148
 
    return [("Form_%s" % forms[8].name, "BilinearForm"),
149
 
            ("Form_%s" % forms[9].name, "LinearForm"),
150
 
            ("Form_%s" % forms[10].name, "GoalFunctional")]
151