1
# Copyright (C) 2011 Marie E. Rognes
3
# This file is part of DOLFIN.
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.
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.
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/>.
18
# Based on original implementation by Martin Alnes and Anders Logg
20
# Last changed: 2012-12-05
22
import includes as incl
23
from functionspace import *
24
from form import generate_form
25
from capsules import UFCElementNames
27
__all__ = ["generate_dolfin_code"]
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}
33
#-------------------------------------------------------------------------------
34
def generate_dolfin_code(prefix, header, forms,
35
common_function_space=False, add_guards=False,
37
"""Generate complete dolfin wrapper code with given generated names.
40
String, prefix for all form names.
42
Code that will be inserted at the top of the file.
44
List of UFCFormNames instances or single UFCElementNames.
45
@param common_function_space:
46
True if common function space, otherwise False
48
True iff guards (ifdefs) should be added
50
True iff adaptivity typedefs (ifdefs) should be added
53
# Generate dolfin namespace
54
namespace = generate_dolfin_namespace(prefix, forms, common_function_space,
57
# Collect pieces of code
58
code = [incl.dolfin_tag, header, incl.stl_includes, incl.dolfin_includes,
61
# Add ifdefs/endifs if specified
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]
69
return "\n".join(code)
71
#-------------------------------------------------------------------------------
72
def generate_dolfin_namespace(prefix, forms, common_function_space=False,
75
# Allow forms to represent a single space, and treat separately
76
if isinstance(forms, UFCElementNames):
77
return generate_single_function_space(prefix, forms)
79
# Extract (common) coefficient spaces
80
assert(parameters["use_common_coefficient_names"])
81
spaces = extract_coefficient_spaces(forms)
83
# Generate code for common coefficient spaces
84
code = [apply_function_space_template(*space) for space in spaces]
86
# Generate code for forms
87
code += [generate_form(form, "Form_%s" % form.name) for form in forms]
89
# Generate namespace typedefs (Bilinear/Linear & Test/Trial/Function)
90
code += [generate_namespace_typedefs(forms, common_function_space,
93
# Wrap code in namespace block
94
code = "\nnamespace %s\n{\n\n%s\n}" % (prefix, "\n".join(code))
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)
107
#-------------------------------------------------------------------------------
108
def generate_namespace_typedefs(forms, common_function_space, error_control):
110
# Generate typedefs as (fro, to) pairs of strings
113
# Add typedef for Functional/LinearForm/BilinearForm if only one
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)]
125
# Keepin' it simple: Add typedef for FunctionSpace if term applies
126
if common_function_space:
127
for i, form in enumerate(forms):
129
pairs += [("Form_%s::TestSpace" % form.name, "FunctionSpace")]
132
# Add specialized typedefs when adding error control wrapppers
134
pairs += error_control_pairs(forms)
136
# Combine data to typedef code
137
typedefs = "\n".join("typedef %s %s;" % (to, fro) for (to, fro) in pairs)
139
# Return typedefs or ""
142
return "// Class typedefs\n" + typedefs + "\n"
144
#-------------------------------------------------------------------------------
145
def error_control_pairs(forms):
146
assert (len(forms) == 11), "Expecting 11 error control forms"
148
return [("Form_%s" % forms[8].name, "BilinearForm"),
149
("Form_%s" % forms[9].name, "LinearForm"),
150
("Form_%s" % forms[10].name, "GoalFunctional")]