~ubuntu-branches/ubuntu/vivid/ffc/vivid

« back to all changes in this revision

Viewing changes to ffc/dolfin/form.py

  • Committer: Package Import Robot
  • Author(s): Johannes Ring
  • Date: 2014-06-03 18:26:02 UTC
  • mfrom: (1.1.15)
  • Revision ID: package-import@ubuntu.com-20140603182602-zvnubjjh7i78e1v0
Tags: 1.4.0-1
* New upstream release.
* debian/control:
  - Add swig in Build-Depends.
  - Remove python-ufc from Depends.
  - Add ufc and python-ufc to Provides, Conflicts and Replaces.
  - Remove python-ferari and python-dolfin from Suggests.
  - Bump minimum required version for python-fiat, python-instant and
    python-ufl to 1.4.0.
* debian/rules: Add override for auto clean target to remove generated
  cmake and pkg-config files.

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
 
# Modified by Anders Logg 2011
21
 
#
22
 
# Last changed: 2011-11-15
23
 
 
24
 
from includes import snippets
25
 
from functionspace import *
26
 
from goalfunctional import generate_update_ec
27
 
 
28
 
__all__ = ["generate_form"]
29
 
 
30
 
#-------------------------------------------------------------------------------
31
 
def generate_form(form, classname):
32
 
    """Generate dolfin wrapper code associated with a form including
33
 
    code for function spaces used in form and typedefs
34
 
 
35
 
    @param form:
36
 
        A UFCFormNames instance
37
 
    @param classname
38
 
        Name of Form class.
39
 
    """
40
 
 
41
 
    # Generate code for Form_x_FunctionSpace_y subclasses
42
 
    wrap = apply_function_space_template
43
 
    blocks = [wrap("%s_FunctionSpace_%d" % (classname, i),
44
 
                   form.ufc_finite_element_classnames[i],
45
 
                   form.ufc_dofmap_classnames[i]) for i in range(form.rank)]
46
 
 
47
 
    # Add typedefs CoefficientSpace_z -> Form_x_FunctionSpace_y
48
 
    blocks += ["typedef CoefficientSpace_%s %s_FunctionSpace_%d;\n"
49
 
               % (form.coefficient_names[i], classname, form.rank + i)
50
 
               for i in range(form.num_coefficients)]
51
 
 
52
 
    # Generate Form subclass
53
 
    blocks += [generate_form_class(form, classname)]
54
 
 
55
 
    # Return code
56
 
    return "\n".join(blocks)
57
 
#-------------------------------------------------------------------------------
58
 
def generate_form_class(form, classname):
59
 
    "Generate dolfin wrapper code for a single Form class."
60
 
 
61
 
    # Generate constructors
62
 
    constructors = generate_form_constructors(form, classname)
63
 
 
64
 
    # Generate data for coefficient assignments
65
 
    (number, name) = generate_coefficient_map_data(form)
66
 
 
67
 
    # Generate typedefs for FunctionSpace subclasses for Coefficients
68
 
    typedefs = ["  // Typedefs", generate_typedefs(form, classname), ""]
69
 
 
70
 
    # Member variables for coefficients
71
 
    members = ["  dolfin::CoefficientAssigner %s;" % coefficient
72
 
               for coefficient in form.coefficient_names]
73
 
    if form.superclassname == "GoalFunctional":
74
 
        members += [generate_update_ec(form)]
75
 
 
76
 
    # Group typedefs and members together for inserting into template
77
 
    additionals = "\n".join(typedefs + ["  // Coefficients"] + members)
78
 
 
79
 
    # Wrap functions in class body
80
 
    code = apply_form_template(classname, constructors, number, name,
81
 
                               additionals, form.superclassname)
82
 
 
83
 
    # Return code
84
 
    return code
85
 
#-------------------------------------------------------------------------------
86
 
def generate_coefficient_map_data(form):
87
 
    """Generate data for code for the functions
88
 
    Form::coefficient_number and Form::coefficient_name."""
89
 
 
90
 
    # Write error if no coefficients
91
 
    if form.num_coefficients == 0:
92
 
        message = '''\
93
 
dolfin::dolfin_error("generated code for class %s",
94
 
                         "access coefficient data",
95
 
                         "There are no coefficients");''' % form.superclassname
96
 
        num  = "\n    %s\n    return 0;" % message
97
 
        name = '\n    %s\n    return "unnamed";' % message
98
 
        return (num, name)
99
 
 
100
 
    # Otherwise create switch
101
 
    ifstr = "if "
102
 
    num = ""
103
 
    name = '    switch (i)\n    {\n'
104
 
    for i, coeff in enumerate(form.coefficient_names):
105
 
        num += '    %s(name == "%s")\n      return %d;\n' % (ifstr, coeff, i)
106
 
        name += '    case %d:\n      return "%s";\n' % (i, coeff)
107
 
        ifstr = 'else if '
108
 
 
109
 
    # Create final return
110
 
    message = '''\
111
 
dolfin::dolfin_error("generated code for class %s",
112
 
                         "access coefficient data",
113
 
                         "Invalid coefficient");''' % form.superclassname
114
 
    num +=  "\n    %s\n    return 0;" % message
115
 
    name += '    }\n\n    %s\n    return "unnamed";' % message
116
 
 
117
 
    return (num, name)
118
 
#-------------------------------------------------------------------------------
119
 
def generate_form_constructors(form, classname):
120
 
    """Generate the dolfin::Form constructors for different
121
 
    combinations of references/shared pointers etc."""
122
 
 
123
 
    coeffs = ("referenced_coefficient", "shared_ptr_coefficient")
124
 
    spaces = ("referenced_space", "shared_ptr_space")
125
 
 
126
 
    # Treat functionals a little special
127
 
    if form.rank == 0:
128
 
        spaces = ("referenced_mesh", "shared_ptr_mesh")
129
 
 
130
 
    # Generate permutations of constructors
131
 
    constructors = []
132
 
    for space in spaces:
133
 
        constructors += [generate_constructor(form, classname, space)]
134
 
        if form.num_coefficients > 0:
135
 
            constructors += [generate_constructor(form, classname, space, coeff)
136
 
                             for coeff in coeffs]
137
 
 
138
 
    # Return joint constructor code
139
 
    return "\n\n".join(constructors)
140
 
 
141
 
#-------------------------------------------------------------------------------
142
 
def generate_constructor(form, classname, space_tag, coefficient_tag=None):
143
 
    "Generate a single Form constructor according to the given parameters."
144
 
 
145
 
    # Extract correct code snippets
146
 
    (argument, assign) = snippets[space_tag]
147
 
 
148
 
    # Construct list of arguments and function space assignments
149
 
    name = "V%d"
150
 
    if form.rank > 0:
151
 
        arguments = [argument % (name % i) for i in reversed(range(form.rank))]
152
 
        assignments = [assign % (i, name % i) for i in range(form.rank)]
153
 
    else:
154
 
        arguments = [argument]
155
 
        assignments = [assign]
156
 
 
157
 
    # Add coefficients to argument/assignment lists if specified
158
 
    if coefficient_tag is not None:
159
 
        (argument, assign) = snippets[coefficient_tag]
160
 
        arguments += [argument % name for name in form.coefficient_names]
161
 
        if form.rank > 0: # FIXME: To match old generated code only
162
 
            assignments += [""]
163
 
        assignments += [assign %(name, name) for name in form.coefficient_names]
164
 
 
165
 
    # Add assignment of _ufc_form variable
166
 
    line = "\n    _ufc_form = boost::shared_ptr<const ufc::form>(new %s());"
167
 
    # FIXME: To match old generated code only
168
 
    if form.rank == 0 and coefficient_tag is None:
169
 
        line =  "    _ufc_form = boost::shared_ptr<const ufc::form>(new %s());"
170
 
    assignments += [line % form.ufc_form_classname]
171
 
 
172
 
    # Construct list for initialization of Coefficient references
173
 
    initializers = ["%s(*this, %d)" % (name, number)
174
 
                    for (number, name) in enumerate(form.coefficient_names)]
175
 
 
176
 
    # Join lists together
177
 
    arguments = ", ".join(arguments)
178
 
    initializers = ", " + ", ".join(initializers) if initializers else ""
179
 
    body = "\n".join(assignments)
180
 
 
181
 
    # Wrap code into template
182
 
    args = {"classname": classname,
183
 
            "rank": form.rank,
184
 
            "num_coefficients": form.num_coefficients,
185
 
            "arguments": arguments,
186
 
            "initializers": initializers,
187
 
            "body": body,
188
 
            "superclass": form.superclassname
189
 
            }
190
 
    code = form_constructor_template % args
191
 
    return code
192
 
#-------------------------------------------------------------------------------
193
 
form_class_template = """\
194
 
class %(classname)s: public dolfin::%(superclass)s
195
 
{
196
 
public:
197
 
 
198
 
%(constructors)s
199
 
 
200
 
  // Destructor
201
 
  ~%(classname)s()
202
 
  {}
203
 
 
204
 
  /// Return the number of the coefficient with this name
205
 
  virtual std::size_t coefficient_number(const std::string& name) const
206
 
  {
207
 
%(coefficient_number)s
208
 
  }
209
 
 
210
 
  /// Return the name of the coefficient with this number
211
 
  virtual std::string coefficient_name(std::size_t i) const
212
 
  {
213
 
%(coefficient_name)s
214
 
  }
215
 
 
216
 
%(members)s
217
 
};
218
 
"""
219
 
#-------------------------------------------------------------------------------
220
 
# Template code for Form constructor
221
 
form_constructor_template = """\
222
 
  // Constructor
223
 
  %(classname)s(%(arguments)s):
224
 
    dolfin::%(superclass)s(%(rank)d, %(num_coefficients)d)%(initializers)s
225
 
  {
226
 
%(body)s
227
 
  }"""
228
 
#-------------------------------------------------------------------------------
229
 
def apply_form_template(classname, constructors, number, name, members,
230
 
                        superclass):
231
 
    args = {"classname": classname,
232
 
            "superclass": superclass,
233
 
            "constructors": constructors,
234
 
            "coefficient_number": number,
235
 
            "coefficient_name": name,
236
 
            "members": members}
237
 
    return form_class_template % args
238
 
#-------------------------------------------------------------------------------