Skip to content

Commit

Permalink
merge changes
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisrichardson committed Aug 13, 2023
2 parents 0f1f6cd + 4618c33 commit 5deeb08
Show file tree
Hide file tree
Showing 8 changed files with 693 additions and 472 deletions.
49 changes: 0 additions & 49 deletions ffcx/codegeneration/C/dofmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,12 @@
# old implementation in FFC

import logging
import typing

import ffcx.codegeneration.C.dofmap_template as ufcx_dofmap

logger = logging.getLogger("ffcx")


def tabulate_entity_dofs(
entity_dofs: typing.List[typing.List[typing.List[int]]],
num_dofs_per_entity: typing.List[int],
):
# TODO: Removed check for (d <= tdim + 1)
tdim = len(num_dofs_per_entity) - 1

# Generate cases for each dimension:
cases = "switch (d)\n{\n"
for dim in range(tdim + 1):
# Ignore if no entities for this dimension
if num_dofs_per_entity[dim] == 0:
continue
cases += f" case {dim}:\n"
cases += " switch (i)\n {\n"
# Generate cases for each mesh entity
for entity in range(len(entity_dofs[dim])):
cases += f" case {entity}:\n"
for j, dof in enumerate(entity_dofs[dim][entity]):
cases += f" dofs[{j}] = {dof};\n"
cases += " break;\n"

cases += " }\n break;\n"
cases += "}\n"
return cases


def generator(ir, options):
"""Generate UFC code for a dofmap."""
logger.info("Generating code for dofmap:")
Expand All @@ -57,21 +29,6 @@ def generator(ir, options):
d["num_element_support_dofs"] = ir.num_element_support_dofs
d["num_sub_dofmaps"] = ir.num_sub_dofmaps

num_entity_dofs = ir.num_entity_dofs + [0, 0, 0, 0]
num_entity_dofs = num_entity_dofs[:4]
d["num_entity_dofs"] = f"num_entity_dofs_{ir.name}"
d[
"num_entity_dofs_init"
] = f"int num_entity_dofs_{ir.name}[4] = {{{', '.join(str(i) for i in num_entity_dofs)}}};"

num_entity_closure_dofs = ir.num_entity_closure_dofs + [0, 0, 0, 0]
num_entity_closure_dofs = num_entity_closure_dofs[:4]
d["num_entity_closure_dofs"] = f"num_entity_closure_dofs_{ir.name}"
values = ", ".join(str(i) for i in num_entity_closure_dofs)
d[
"num_entity_closure_dofs_init"
] = f"int num_entity_closure_dofs_{ir.name}[] = {{{values}}};"

flattened_entity_dofs = []
entity_dof_offsets = [0]
for dim in ir.entity_dofs:
Expand Down Expand Up @@ -108,12 +65,6 @@ def generator(ir, options):

d["block_size"] = ir.block_size

# Functions
d["tabulate_entity_dofs"] = tabulate_entity_dofs(ir.entity_dofs, ir.num_entity_dofs)
d["tabulate_entity_closure_dofs"] = tabulate_entity_dofs(
ir.entity_closure_dofs, ir.num_entity_closure_dofs
)

if len(ir.sub_dofmaps) > 0:
values = ", ".join(f"&{dofmap}" for dofmap in ir.sub_dofmaps)
d[
Expand Down
18 changes: 0 additions & 18 deletions ffcx/codegeneration/C/dofmap_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,6 @@
{sub_dofmaps_initialization}
void tabulate_entity_dofs_{factory_name}(int* restrict dofs, int d, int i)
{{
{tabulate_entity_dofs}
}}
void tabulate_entity_closure_dofs_{factory_name}(int* restrict dofs, int d, int i)
{{
{tabulate_entity_closure_dofs}
}}
{num_entity_dofs_init}
{num_entity_closure_dofs_init}
{entity_dofs_init}
{entity_dof_offsets_init}
Expand All @@ -44,10 +30,6 @@
.entity_dof_offsets = {entity_dof_offsets},
.entity_closure_dofs = {entity_closure_dofs},
.entity_closure_dof_offsets = {entity_closure_dof_offsets},
.num_entity_dofs = {num_entity_dofs},
.tabulate_entity_dofs = tabulate_entity_dofs_{factory_name},
.num_entity_closure_dofs = {num_entity_closure_dofs},
.tabulate_entity_closure_dofs = tabulate_entity_closure_dofs_{factory_name},
.num_sub_dofmaps = {num_sub_dofmaps},
.sub_dofmaps = {sub_dofmaps}
}};
Expand Down
17 changes: 10 additions & 7 deletions ffcx/codegeneration/C/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ def generator(ir, options):
d["num_coefficients"] = ir.num_coefficients
d["num_constants"] = ir.num_constants

code = "switch(integral_type)\n{\n"
for itg_type in ("cell", "interior_facet", "exterior_facet"):
code += f"case {itg_type}: return {len(ir.subdomain_ids[itg_type])};\n"
code += "default: return 0;\n}\n"
d["num_integrals"] = code

if len(ir.original_coefficient_position) > 0:
orig_coeff = ', '.join(str(i) for i in ir.original_coefficient_position)
d["original_coefficient_position_init"] = \
Expand Down Expand Up @@ -81,7 +75,7 @@ def generator(ir, options):
integrals = []
integral_ids = []
integral_offsets = [0]
for itg_type in ("cell", "interior_facet", "exterior_facet"):
for itg_type in ("cell", "exterior_facet", "interior_facet"):
integrals += ir.integral_names[itg_type]
integral_ids += ir.subdomain_ids[itg_type]
integral_offsets.append(len(integrals))
Expand Down Expand Up @@ -140,6 +134,15 @@ def generator(ir, options):
fields = [
fname for _, fname, _, _ in Formatter().parse(form_template.factory) if fname
]

for f in fields:
if f not in d.keys():
print(f, "not in d.keys()")

for f in d.keys():
if f not in fields:
print(f, "not in fields")

assert set(fields) == set(
d.keys()
), "Mismatch between keys in template and in formatting dict"
Expand Down
20 changes: 0 additions & 20 deletions ffcx/codegeneration/C/form_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,6 @@
{constant_name_map}
}}
int* integral_ids_{factory_name}(ufcx_integral_type integral_type)
{{
{integral_ids}
}}
int num_integrals_{factory_name}(ufcx_integral_type integral_type)
{{
{num_integrals}
}}
ufcx_integral** integrals_{factory_name}(ufcx_integral_type integral_type)
{{
{integrals}
}}
ufcx_form {factory_name} =
{{
Expand All @@ -70,11 +55,6 @@
.finite_elements = {finite_elements},
.dofmaps = {dofmaps},
.integral_ids = integral_ids_{factory_name},
.num_integrals = num_integrals_{factory_name},
.integrals = integrals_{factory_name},
.form_integrals = {form_integrals},
.form_integral_ids = {form_integral_ids},
.form_integral_offsets = form_integral_offsets_{factory_name}
Expand Down
9 changes: 0 additions & 9 deletions ffcx/codegeneration/ufcx.h
Original file line number Diff line number Diff line change
Expand Up @@ -456,15 +456,6 @@ extern "C"
/// Coefficient number j=i-r if r+j <= i < r+n
ufcx_dofmap** dofmaps;

/// All ids for integrals
int* (*integral_ids)(ufcx_integral_type);

/// Number of integrals
int (*num_integrals)(ufcx_integral_type);

/// Get an integral on sub domain subdomain_id
ufcx_integral** (*integrals)(ufcx_integral_type);

/// List of cell, interior facet and exterior facet integrals
ufcx_integral** form_integrals;

Expand Down
95 changes: 56 additions & 39 deletions test/test_add_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,32 @@
from ffcx.naming import cdtype_to_numpy, scalar_to_value_type


@pytest.mark.parametrize("mode",
[
"double",
"float",
"long double",
"double _Complex",
"float _Complex"
])
@pytest.mark.parametrize(
"mode", ["double", "float", "long double", "double _Complex", "float _Complex"]
)
def test_additive_facet_integral(mode, compile_args):
element = basix.ufl.element("Lagrange", "triangle", 1)
u, v = ufl.TrialFunction(element), ufl.TestFunction(element)
a = ufl.inner(u, v) * ufl.ds
forms = [a]
compiled_forms, module, code = ffcx.codegeneration.jit.compile_forms(
forms, options={'scalar_type': mode}, cffi_extra_compile_args=compile_args)
forms, options={"scalar_type": mode}, cffi_extra_compile_args=compile_args
)

for f, compiled_f in zip(forms, compiled_forms):
assert compiled_f.rank == len(f.arguments())

ffi = module.ffi
form0 = compiled_forms[0]

assert form0.num_integrals(module.lib.exterior_facet) == 1
ids = form0.integral_ids(module.lib.exterior_facet)
assert ids[0] == -1
integral_offsets = form0.form_integral_offsets
ex = module.lib.exterior_facet
num_integrals = integral_offsets[ex + 1] - integral_offsets[ex]
assert num_integrals == 1
integral_id = form0.form_integral_ids[integral_offsets[ex]]
assert integral_id == -1

default_integral = form0.integrals(module.lib.exterior_facet)[0]
default_integral = form0.form_integrals[integral_offsets[ex]]

np_type = cdtype_to_numpy(mode)
A = np.zeros((3, 3), dtype=np_type)
Expand All @@ -50,44 +49,53 @@ def test_additive_facet_integral(mode, compile_args):

geom_type = scalar_to_value_type(mode)
np_gtype = cdtype_to_numpy(geom_type)
coords = np.array([0.0, 2.0, 0.0,
np.sqrt(3.0), -1.0, 0.0,
-np.sqrt(3.0), -1.0, 0.0], dtype=np_gtype)
coords = np.array(
[0.0, 2.0, 0.0, np.sqrt(3.0), -1.0, 0.0, -np.sqrt(3.0), -1.0, 0.0],
dtype=np_gtype,
)

kernel = getattr(default_integral, f"tabulate_tensor_{np_type}")

for i in range(3):
facets[0] = i
kernel(ffi.cast('{type} *'.format(type=mode), A.ctypes.data),
ffi.cast('{type} *'.format(type=mode), w.ctypes.data),
ffi.cast('{type} *'.format(type=mode), c.ctypes.data),
ffi.cast(f'{geom_type} *', coords.ctypes.data),
ffi.cast('int *', facets.ctypes.data),
ffi.cast('uint8_t *', perm.ctypes.data))
kernel(
ffi.cast("{type} *".format(type=mode), A.ctypes.data),
ffi.cast("{type} *".format(type=mode), w.ctypes.data),
ffi.cast("{type} *".format(type=mode), c.ctypes.data),
ffi.cast(f"{geom_type} *", coords.ctypes.data),
ffi.cast("int *", facets.ctypes.data),
ffi.cast("uint8_t *", perm.ctypes.data),
)

assert np.isclose(A.sum(), np.sqrt(12) * (i + 1))


@pytest.mark.parametrize("mode", ["double", "float", "long double", "double _Complex", "float _Complex"])
@pytest.mark.parametrize(
"mode", ["double", "float", "long double", "double _Complex", "float _Complex"]
)
def test_additive_cell_integral(mode, compile_args):
element = basix.ufl.element("Lagrange", "triangle", 1)
u, v = ufl.TrialFunction(element), ufl.TestFunction(element)
a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
forms = [a]
compiled_forms, module, code = ffcx.codegeneration.jit.compile_forms(
forms, options={'scalar_type': mode}, cffi_extra_compile_args=compile_args)
forms, options={"scalar_type": mode}, cffi_extra_compile_args=compile_args
)

for f, compiled_f in zip(forms, compiled_forms):
assert compiled_f.rank == len(f.arguments())

ffi = module.ffi
form0 = compiled_forms[0]

assert form0.num_integrals(module.lib.cell) == 1
ids = form0.integral_ids(module.lib.cell)
assert ids[0] == -1
offsets = form0.form_integral_offsets
cell = module.lib.cell
num_integrals = offsets[cell + 1] - offsets[cell]
assert num_integrals == 1
integral_id = form0.form_integral_ids[offsets[cell]]
assert integral_id == -1

default_integral = form0.integrals(0)[0]
default_integral = form0.form_integrals[offsets[cell]]

np_type = cdtype_to_numpy(mode)
A = np.zeros((3, 3), dtype=np_type)
Expand All @@ -96,22 +104,31 @@ def test_additive_cell_integral(mode, compile_args):

geom_type = scalar_to_value_type(mode)
np_gtype = cdtype_to_numpy(geom_type)
coords = np.array([0.0, 2.0, 0.0,
np.sqrt(3.0), -1.0, 0.0,
-np.sqrt(3.0), -1.0, 0.0], dtype=np_gtype)
coords = np.array(
[0.0, 2.0, 0.0, np.sqrt(3.0), -1.0, 0.0, -np.sqrt(3.0), -1.0, 0.0],
dtype=np_gtype,
)

kernel = getattr(default_integral, f"tabulate_tensor_{np_type}")

kernel(ffi.cast('{type} *'.format(type=mode), A.ctypes.data),
ffi.cast('{type} *'.format(type=mode), w.ctypes.data),
ffi.cast('{type} *'.format(type=mode), c.ctypes.data),
ffi.cast(f'{geom_type} *', coords.ctypes.data), ffi.NULL, ffi.NULL)
kernel(
ffi.cast("{type} *".format(type=mode), A.ctypes.data),
ffi.cast("{type} *".format(type=mode), w.ctypes.data),
ffi.cast("{type} *".format(type=mode), c.ctypes.data),
ffi.cast(f"{geom_type} *", coords.ctypes.data),
ffi.NULL,
ffi.NULL,
)

A0 = np.array(A)
for i in range(3):
kernel(ffi.cast('{type} *'.format(type=mode), A.ctypes.data),
ffi.cast('{type} *'.format(type=mode), w.ctypes.data),
ffi.cast('{type} *'.format(type=mode), c.ctypes.data),
ffi.cast(f'{geom_type} *', coords.ctypes.data), ffi.NULL, ffi.NULL)
kernel(
ffi.cast("{type} *".format(type=mode), A.ctypes.data),
ffi.cast("{type} *".format(type=mode), w.ctypes.data),
ffi.cast("{type} *".format(type=mode), c.ctypes.data),
ffi.cast(f"{geom_type} *", coords.ctypes.data),
ffi.NULL,
ffi.NULL,
)

assert np.all(np.isclose(A, (i + 2) * A0))
Loading

0 comments on commit 5deeb08

Please sign in to comment.