• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FEniCS / ffcx / 20003395181

07 Dec 2025 11:15AM UTC coverage: 78.511% (-5.9%) from 84.457%
20003395181

Pull #803

github

schnellerhase
Reactivate check
Pull Request #803: Add `C++` backend

0 of 364 new or added lines in 10 files covered. (0.0%)

4059 of 5170 relevant lines covered (78.51%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/ffcx/codegeneration/cpp/form.py
1
# Copyright (C) 2009-2017 Anders Logg, Martin Sandve Alnæs, Chirs Richardson and Paul T. Kühner
2
#
3
# This file is part of FFCx.(https://www.fenicsproject.org)
4
#
5
# SPDX-License-Identifier:    LGPL-3.0-or-later
6

7
# Note: Most of the code in this file is a direct translation from the
8
# old implementation in FFC
9
"""Generate code for a form."""
10

NEW
11
import logging
×
12

NEW
13
import numpy as np
×
14

NEW
15
from ffcx.codegeneration.cpp import form_template
×
16

NEW
17
logger = logging.getLogger("ffcx")
×
18

19

20
# TODO: this is copy of C.form up to the provided template -> generalise
NEW
21
def generator(ir, options):
×
22
    """Generate UFC code for a form."""
NEW
23
    logger.info("Generating code for form:")
×
NEW
24
    logger.info(f"--- rank: {ir.rank}")
×
NEW
25
    logger.info(f"--- name: {ir.name}")
×
26

NEW
27
    d: dict[str, int | str] = {}
×
NEW
28
    d["factory_name"] = ir.name
×
NEW
29
    d["name_from_uflfile"] = ir.name_from_uflfile
×
NEW
30
    d["signature"] = f'"{ir.signature}"'
×
NEW
31
    d["rank"] = ir.rank
×
NEW
32
    d["num_coefficients"] = ir.num_coefficients
×
33

NEW
34
    if len(ir.original_coefficient_positions) > 0:
×
NEW
35
        values = ", ".join(str(i) for i in ir.original_coefficient_positions)
×
NEW
36
        sizes = len(ir.original_coefficient_positions)
×
37

NEW
38
        d["original_coefficient_position_init"] = (
×
39
            f"int original_coefficient_position_{ir.name}[{sizes}] = {{{values}}};"
40
        )
NEW
41
        d["original_coefficient_positions"] = f"original_coefficient_position_{ir.name}"
×
42
    else:
NEW
43
        d["original_coefficient_position_init"] = ""
×
NEW
44
        d["original_coefficient_positions"] = "NULL"
×
45

NEW
46
    if len(ir.coefficient_names) > 0:
×
NEW
47
        values = ", ".join(f'"{name}"' for name in ir.coefficient_names)
×
NEW
48
        sizes = len(ir.coefficient_names)
×
NEW
49
        d["coefficient_names_init"] = (
×
50
            f"static const char* coefficient_names_{ir.name}[{sizes}] = {{{values}}};"
51
        )
NEW
52
        d["coefficient_names"] = f"coefficient_names_{ir.name}"
×
53
    else:
NEW
54
        d["coefficient_names_init"] = ""
×
NEW
55
        d["coefficient_names"] = "NULL"
×
56

NEW
57
    d["num_constants"] = ir.num_constants
×
NEW
58
    if ir.num_constants > 0:
×
NEW
59
        d["constant_ranks_init"] = (
×
60
            f"static const int constant_ranks_{ir.name}[{ir.num_constants}] = "
61
            f"{{{str(ir.constant_ranks)[1:-1]}}};"
62
        )
NEW
63
        d["constant_ranks"] = f"constant_ranks_{ir.name}"
×
64

NEW
65
        shapes = [
×
66
            f"static const int constant_shapes_{ir.name}_{i}[{len(shape)}] = "
67
            f"{{{str(shape)[1:-1]}}};"
68
            for i, shape in enumerate(ir.constant_shapes)
69
            if len(shape) > 0
70
        ]
NEW
71
        names = [f"constant_shapes_{ir.name}_{i}" for i in range(ir.num_constants)]
×
NEW
72
        shapes1 = f"static const int* constant_shapes_{ir.name}[{ir.num_constants}] = " + "{"
×
NEW
73
        for rank, name in zip(ir.constant_ranks, names):
×
NEW
74
            if rank > 0:
×
NEW
75
                shapes1 += f"{name},\n"
×
76
            else:
NEW
77
                shapes1 += "NULL,\n"
×
NEW
78
        shapes1 += "};"
×
NEW
79
        shapes.append(shapes1)
×
80

NEW
81
        d["constant_shapes_init"] = "\n".join(shapes)
×
NEW
82
        d["constant_shapes"] = f"constant_shapes_{ir.name}"
×
83
    else:
NEW
84
        d["constant_ranks_init"] = ""
×
NEW
85
        d["constant_ranks"] = "NULL"
×
NEW
86
        d["constant_shapes_init"] = ""
×
NEW
87
        d["constant_shapes"] = "NULL"
×
88

NEW
89
    if len(ir.constant_names) > 0:
×
NEW
90
        values = ", ".join(f'"{name}"' for name in ir.constant_names)
×
NEW
91
        sizes = len(ir.constant_names)
×
NEW
92
        d["constant_names_init"] = (
×
93
            f"static const char* constant_names_{ir.name}[{sizes}] = {{{values}}};"
94
        )
NEW
95
        d["constant_names"] = f"constant_names_{ir.name}"
×
96
    else:
NEW
97
        d["constant_names_init"] = ""
×
NEW
98
        d["constant_names"] = "NULL"
×
99

NEW
100
    if len(ir.finite_element_hashes) > 0:
×
NEW
101
        d["finite_element_hashes"] = f"finite_element_hashes_{ir.name}"
×
NEW
102
        values = ", ".join(
×
103
            f"UINT64_C({0 if el is None else el})" for el in ir.finite_element_hashes
104
        )
NEW
105
        sizes = len(ir.finite_element_hashes)
×
NEW
106
        d["finite_element_hashes_init"] = (
×
107
            f"uint64_t finite_element_hashes_{ir.name}[{sizes}] = {{{values}}};"
108
        )
109
    else:
NEW
110
        d["finite_element_hashes"] = "NULL"
×
NEW
111
        d["finite_element_hashes_init"] = ""
×
112

NEW
113
    integrals = []
×
NEW
114
    integral_ids = []
×
NEW
115
    integral_offsets = [0]
×
NEW
116
    integral_domains = []
×
117
    # Note: the order of this list is defined by the enum ufcx_integral_type in ufcx.h
NEW
118
    for itg_type in ("cell", "exterior_facet", "interior_facet", "vertex", "ridge"):
×
NEW
119
        unsorted_integrals = []
×
NEW
120
        unsorted_ids = []
×
NEW
121
        unsorted_domains = []
×
NEW
122
        for name, domains, id in zip(
×
123
            ir.integral_names[itg_type],
124
            ir.integral_domains[itg_type],
125
            ir.subdomain_ids[itg_type],
126
        ):
NEW
127
            unsorted_integrals += [f"&{name}"]
×
NEW
128
            unsorted_ids += [id]
×
NEW
129
            unsorted_domains += [domains]
×
130

NEW
131
        id_sort = np.argsort(unsorted_ids)
×
NEW
132
        integrals += [unsorted_integrals[i] for i in id_sort]
×
NEW
133
        integral_ids += [unsorted_ids[i] for i in id_sort]
×
NEW
134
        integral_domains += [unsorted_domains[i] for i in id_sort]
×
135

NEW
136
        integral_offsets.append(sum(len(d) for d in integral_domains))
×
137

NEW
138
    if len(integrals) > 0:
×
NEW
139
        sizes = sum(len(domains) for domains in integral_domains)
×
NEW
140
        values = ", ".join(
×
141
            [
142
                f"{i}_{domain.name}"
143
                for i, domains in zip(integrals, integral_domains)
144
                for domain in domains
145
            ]
146
        )
NEW
147
        d["form_integrals_init"] = (
×
148
            f"static ufcx_integral* form_integrals_{ir.name}[{sizes}] = {{{values}}};"
149
        )
NEW
150
        d["form_integrals"] = f"form_integrals_{ir.name}"
×
NEW
151
        values = ", ".join(
×
152
            f"{i}" for i, domains in zip(integral_ids, integral_domains) for _ in domains
153
        )
NEW
154
        d["form_integral_ids_init"] = f"int form_integral_ids_{ir.name}[{sizes}] = {{{values}}};"
×
NEW
155
        d["form_integral_ids"] = f"form_integral_ids_{ir.name}"
×
156
    else:
NEW
157
        d["form_integrals_init"] = ""
×
NEW
158
        d["form_integrals"] = "NULL"
×
NEW
159
        d["form_integral_ids_init"] = ""
×
NEW
160
        d["form_integral_ids"] = "NULL"
×
161

NEW
162
    sizes = len(integral_offsets)
×
NEW
163
    values = ", ".join(str(i) for i in integral_offsets)
×
NEW
164
    d["form_integral_offsets_init"] = (
×
165
        f"int form_integral_offsets_{ir.name}[{sizes}] = {{{values}}};"
166
    )
167

168
    # Check that no keys are redundant or have been missed
NEW
169
    from string import Formatter
×
170

NEW
171
    fields = [fname for _, fname, _, _ in Formatter().parse(form_template.factory) if fname]
×
NEW
172
    assert set(fields) == set(d.keys()), "Mismatch between keys in template and in formatting dict"
×
173

174
    # Format implementation code
NEW
175
    implementation = form_template.factory.format_map(d)
×
176

177
    # Format declaration
NEW
178
    declaration = form_template.declaration.format(
×
179
        factory_name=d["factory_name"], name_from_uflfile=d["name_from_uflfile"]
180
    )
181

NEW
182
    return declaration, implementation
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc