FENICSFORMCOMPILERX(1)
๐ FENICSFORMCOMPILERX(1) โ bestie edition ๐
okay so. you opened the manual page for fenicsformcompilerx, and the manual name is FFCx (FEniCS Form Compiler), so like. buckle up. this is the whole FFCx docs situation and we're gonna get through it together, no skipping, no summarizing, every last option and signature stays. slay. ๐
โจ NAME โจ
fenicsformcompilerx โ FFCx Documentation, bestie.
The is a new version of the FEniCS Form Compiler. It is developed at https://github.com/FEniCS/ffcx ๐ฆ
and here's the whole module roster, no cap, every single one:
ffcxโ FEniCS Form Compiler (FFCx).ffcx.__main__โ Run FFCx on a UFL file.ffcx.analysisโ Compiler stage 1: Analysis.ffcx.compilerโ Main interface for compilation of forms.ffcx.element_interfaceโ Finite element interface.ffcx.formattingโ Compiler stage 5: Code formatting.ffcx.mainโ Command-line interface to FFCx.ffcx.namingโ Naming.ffcx.codegenerationโ FFCx code generation.ffcx.optionsโ Options.ffcx.ir.representationโ Compiler stage 2: Code representation.ffcx.ir.representationutilsโ Utility functions for some code shared between representations.
๐ง FFCX ๐ง
FEniCS Form Compiler (FFCx). that's the whole vibe.
FFCx compiles finite element variational forms into C code. literally its entire personality. ๐
๐ธ FFCX.__MAIN__ ๐ธ
Run FFCx on a UFL file. that's it, that's the job, it eats a UFL file and goes to work. ๐
๐ฆ FFCX.ANALYSIS ๐ฆ
Compiler stage 1: Analysis.
This module implements the analysis/preprocessing of variational forms, including automatic selection of elements, degrees and form representation type. it's giving very much the "figuring out what you actually meant" era of the pipeline. ๐
โญ Functions
analyze_ufl_objects(ufl_objects, scalar_type)โ Analyze ufl object(s).
โญ Classes
UFLData(form_data, unique_elements, ...)โ UFL data.
๐ class ffcx.analysis.UFLData(...) ๐
class ffcx.analysis.UFLData(form_data: tuple[FormData, ...],
unique_elements: list[basix.ufl._ElementBase], element_numbers:
dict[basix.ufl._ElementBase, int], unique_coordinate_elements:
list[basix.ufl._ElementBase], expressions:
list[tuple[ufl.core.expr.Expr, npt.NDArray[np.floating],
ufl.core.expr.Expr]])
Bases: NamedTuple
UFL data. yes the class is literally named that. iconic.
Create new instance of UFLData(form_data, unique_elements, element_numbers, unique_coordinate_elements, expressions)
so here's every field, spelled out, because bestie we do not leave fields behind:
element_numbers: dict[basix.ufl._ElementBase, int]โ Mapping to unique numbers for all elements.expressions: list[tuple[ufl.core.expr.Expr, npt.NDArray[np.floating], ufl.core.expr.Expr]]โ List of all expressions after post-processing, with evaluation points and original expression.form_data: tuple[FormData, ...]โFormDataobjects.unique_coordinate_elements: list[basix.ufl._ElementBase]โ Unique coordinate elements across all forms and expressions.unique_elements: list[basix.ufl._ElementBase]โ Unique elements across all forms and expressions.
๐ ffcx.analysis.analyze_ufl_objects(...) ๐
ffcx.analysis.analyze_ufl_objects(ufl_objects: list[Form | _ElementBase
| Mesh | tuple[Expr, ndarray[tuple[Any, ...], dtype[floating]]]],
scalar_type: DTypeLike) -> UFLData
Analyze ufl object(s). that's the task.
Parameters
- ufl_objects โ UFL objects
- scalar_type โ Scalar type that should be used for the analysis
Returns โ A named tuple UFLData.
๐ฅ FFCX.COMPILER ๐ฅ
Main interface for compilation of forms.
Breaks the compilation into several sequential stages. The output of each stage is the input of the next stage. it's a relay race and every leg hands off perfectly. ๐โ๏ธ๐จ
๐ Compiler stages
- Language, parsing
- Input: Python code or
.uflfile - Output: UFL form
- Input: Python code or
This stage consists of parsing and expressing a form in the UFL form language. This stage is handled by UFL.
- Analysis
- Input: UFL form
- Output: Preprocessed UFL form and
FormData(metadata)
This stage preprocesses the UFL form and extracts form metadata. It may also perform simplifications on the form.
- Code representation
- Input: Preprocessed UFL form and
FormData(metadata) - Output: Intermediate Representation (IR)
- Input: Preprocessed UFL form and
This stage examines the input and generates all data needed for code generation. This includes generation of finite element basis functions, extraction of data for mapping of degrees of freedom and possible precomputation of integrals. Most of the complexity of compilation is handled in this stage. (the way that "most of the complexity" is just casually dropped here ๐ญ)
The IR is stored as a dictionary, mapping names of UFCx functions to data needed for generation of the corresponding code.
- Code generation
- Input: Intermediate Representation (IR)
- Output: C code
This stage examines the IR and generates the actual C code for the body of each UFCx function.
The code is stored as a dictionary, mapping names of UFCx functions to strings containing the C code of the body of each function.
- Code formatting
- Input: C code
- Output: C code files
This stage examines the generated C++ code and formats it according to the UFCx format, generating as output one or more .h/.c files conforming to the UFCx format.
bestie note: yeah the numbering in the original really does start at 0 for parsing and the formatting stage is listed as stage 5. we're just honoring the original, no edits, periodt. ๐
๐ง Functions
compile_ufl_objects(ufl_objects, options[, ...])โ Generate UFCx code for a given UFL objects.
๐ ffcx.compiler.compile_ufl_objects(...) ๐
ffcx.compiler.compile_ufl_objects(ufl_objects: list[Any], options:
dict[str, int | float | DTypeLike], object_names: dict[int, str] | None
= None, namespace: str | None = None, visualise: bool = False) ->
tuple[list[str], tuple[str, ...]]
Generate UFCx code for a given UFL objects. the main character function, honestly. โญ
Parameters
- ufl_objects โ Objects to be compiled. Accepts elements, forms, integrals or coordinate mappings.
- object_names โ Map from object Python id to object name
- namespace โ Convenience namespace/prefix for generated code.
- options โ Options
- visualise โ Toggle visualisation
Returns: tuple containing list of code file strings and tuple of associated file suffixes.
๐ FFCX.ELEMENT_INTERFACE ๐
Finite element interface. Bestie, this is the little drawer where all the finite-element plumbing lives. ๐ง
๐ Functions
basix_index(indices)โ Get the Basix index of a derivative. ๐ขcreate_quadrature(cellname, degree, rule, ...)โ Create a quadrature rule. โจmap_edge_points(points, edge, cellname)โ Map points from a reference edge to a physical edge. ๐ชmap_facet_points(points, facet, cellname)โ Map points from a reference facet to a physical facet. ๐ชreference_cell_vertices(cellname)โ Get the vertices of a reference cell. ๐
โจ ffcx.element_interface.basix_index
ffcx.element_interface.basix_index(indices: tuple[int]) -> int
Get the Basix index of a derivative. Yeah that's the whole vibe โ hand it the indices and it hands back the index. ๐
โจ ffcx.element_interface.create_quadrature
ffcx.element_interface.create_quadrature(cellname: str, degree: int,
rule: str, elements: list[_ElementBase]) -> tuple[ArrayLike, ArrayLike]
Create a quadrature rule. Cell name, degree, rule, elements in โ quadrature out. ๐
โจ ffcx.element_interface.map_edge_points
ffcx.element_interface.map_edge_points(points: ndarray[tuple[Any, ...],
dtype[float64]], edge: int, cellname: str) -> ndarray[tuple[Any, ...],
dtype[float64]]
Map points from a reference edge to a physical edge. Glow-up arc for your points, fr fr. ๐ฆ
โจ ffcx.element_interface.map_facet_points
ffcx.element_interface.map_facet_points(points: ndarray[tuple[Any, ...],
dtype[float64]], facet: int, cellname: str) -> ndarray[tuple[Any, ...],
dtype[float64]]
Map points from a reference facet to a physical facet. Same energy, facet edition. ๐
โจ ffcx.element_interface.reference_cell_vertices
ffcx.element_interface.reference_cell_vertices(cellname: str) ->
ndarray[tuple[Any, ...], dtype[float64]]
Get the vertices of a reference cell. Corners, but make it math. ๐ท
๐จ FFCX.FORMATTING ๐จ
Compiler stage 5: Code formatting. We're at stage FIVE bestie, can you believe. ๐ญ
This module implements the formatting of UFCx code from a given dictionary of generated C++ code for the body of each UFCx function. It relies on templates for UFCx code available as part of the module ufcx_utils. iykyk
๐ธ Functions
format_code(code_blocks)โ Format given code in UFCx format. โจwrite_code(code, prefix, suffixes, output_dir)โ Write code to files. ๐
โจ ffcx.formatting.format_code
ffcx.formatting.format_code(code_blocks: CodeBlocks) -> list[str]
Format given code in UFCx format.
Returns two strings with header and source file contents. Two strings. Header and source. Not one. Not three. Two. ๐
โจ ffcx.formatting.write_code
ffcx.formatting.write_code(code: list[str], prefix: str, suffixes:
tuple[str, ...], output_dir: str) -> None
Write code to files. Literally what it says on the tin. ๐ซถ
๐ FFCX.MAIN ๐
Command-line interface to FFCx.
Parse command-line arguments and generate code from input UFL form files. This is the main character. ๐
๐ Functions
main([args])โ Run ffcx on a UFL file.
โจ ffcx.main.main
ffcx.main.main(args: Sequence[str] | None = None) -> int
Run ffcx on a UFL file. That's it, that's the function. ๐
๐ท๏ธ FFCX.NAMING ๐ท๏ธ
Naming. Because everything in code needs a name and the names have to be correct, and honestly? Respect. โจ
๐ Functions
compute_signature(ufl_objects, tag)โ Compute the signature hash. ๐expression_name(expression, prefix)โ Get expression name.form_name(original_form, form_id, prefix)โ Get form name.integral_name(original_form, integral_type, ...)โ Get integral name.
โจ ffcx.naming.compute_signature
ffcx.naming.compute_signature(ufl_objects: list[Form] | list[tuple[Expr,
ndarray[tuple[Any, ...], dtype[floating]]]], tag: str) -> str
Compute the signature hash.
Based on the UFL type of the objects and an additional optional 'tag'. ๐
โจ ffcx.naming.expression_name
ffcx.naming.expression_name(expression: tuple[Expr, ndarray[tuple[Any,
...], dtype[floating]]], prefix: str) -> str
Get expression name. ๐ง
โจ ffcx.naming.form_name
ffcx.naming.form_name(original_form: Form, form_id: int, prefix: str) ->
str
Get form name. ๐
โจ ffcx.naming.integral_name
ffcx.naming.integral_name(original_form: Form, integral_type: str,
form_id: int, subdomain_id: Literal['everywhere'] | Integral |
tuple[Integral, ...], prefix: str) -> str
Get integral name. And yes, subdomain_id can literally be the string 'everywhere' or an Integral or a tuple of Integrals. Iconic flexibility tbh. ๐
โ๏ธ FFCX.CODEGENERATION โ๏ธ
FFCx code generation. The actual code-spitting-out part. Chef's kiss. ๐จโ๐ณ๐
๐ Functions
get_include_path()โ Return location of UFCx header files. ๐get_signature()โ Return SHA-1 hash of the contents ofufcx.h. ๐
โจ ffcx.codegeneration.get_include_path
ffcx.codegeneration.get_include_path()
Return location of UFCx header files. Where the headers at. ๐
โจ ffcx.codegeneration.get_signature
ffcx.codegeneration.get_signature()
Return SHA-1 hash of the contents of ufcx.h.
In this implementation, the value is computed on import. On import, bestie, so it's already done by the time you ask. โก
๐ FFCX.OPTIONS ๐
Options. The settings drawer. Every good tool has one. ๐
๐ฆ Functions
get_language(options)โ Retrieve the language option from the options database. ๐ฃ๏ธget_options([priority_options])โ Return (a copy of) the merged option values for FFCX. ๐งพ
โจ ffcx.options.get_language
ffcx.options.get_language(options: dict[str, int | float | DTypeLike])
-> str
Retrieve the language option from the options database.
Applies for internal languages the alias conversion. โจ
โจ ffcx.options.get_options
ffcx.options.get_options(priority_options: dict[str, DTypeLike | int |
float] | None = None) -> dict[str, int | float | DTypeLike]
Return (a copy of) the merged option values for FFCX.
Parameters
priority_optionsโ take priority over all other option values (see notes) ๐
Returns
- merged option values โจ
Note:
This function sets the log level from the merged option values prior to returning.
The ffcx_options.json files are cached on the first call. Subsequent calls to this function use this cache. ๐๏ธ
Priority ordering of options from highest to lowest is:
priority_options(API and command line options) ๐ฅ$PWD/ffcx_options.json(local options) ๐$XDG_CONFIG_HOME/ffcx/ffcx_options.json(user options) ๐FFCX_DEFAULT_OPTIONSinffcx.options๐ฑ
XDG_CONFIG_HOME is ~/.config/ if the environment variable is not set.
Example ffcx_options.json file:
{ "epsilon": 1e-7 }
๐ Heads up bestie: the priority order is not a suggestion, it's the whole entire ruleset. Highest wins. Periodt.
โจ FFCX.IR.REPRESENTATION โจ
okay bestie, welcome to compiler stage 2: code representation ๐ this is where the intermediate representation (IR) of forms gets computed, and honestly it's giving main character energy ๐
so this module computes the intermediate representations of forms. for each UFC function, we pull out exactly the data we'll need for code generation at a later stage. efficiency? iconic. โจ
the representation has to conform strictly to the naming and order of functions in UFC โ no wiggle room, no cap ๐ซถ so when you're code-generating the function "foo", you should literally only need to use the data stored in the intermediate representation under the key "foo". that's the whole vibe.
๐ธ Functions ๐ธ
basix_cell_from_string(string)โ turns a string into a BasixCellType๐ฆcompute_ir(analysis, object_names, prefix, ...)โ computes the intermediate representation โจ
๐ง Classes ๐ง
DataIR(integrals, forms, expressions)โ intermediate representation of data ๐ฆExpressionIR(expression, ...)โ intermediate representation of a DOLFINx Expression ๐FormIR(id, name, signature, rank, ...)โ intermediate representation of a form ๐IntegralIR(expression, rank, ...)โ intermediate representation of an integral ๐งฎQuadratureIR(cell_shape, points, weights)โ intermediate representation of a quadrature rule โญ
๐ class ffcx.ir.representation.DataIR(integrals: list[IntegralIR], forms: list[FormIR], expressions: list[ExpressionIR])
Bases: NamedTuple
intermediate representation of data ๐ซถ
- Creates a new instance of
DataIR(integrals, forms, expressions)
Fields, bestie (yes the aliases are literally just field numbers, don't @ me):
expressions: list[ExpressionIR]โ alias for field number 2forms: list[FormIR]โ alias for field number 1integrals: list[IntegralIR]โ alias for field number 0
๐ class ffcx.ir.representation.ExpressionIR(expression: CommonExpressionIR, original_coefficient_positions: list[int], coefficient_names: list[str], constant_names: list[str], name_from_uflfile: str)
Bases: NamedTuple
intermediate representation of a DOLFINx Expression ๐
- Creates a new instance of
ExpressionIR(expression, original_coefficient_positions, coefficient_names, constant_names, name_from_uflfile) coefficient_names: list[str]โ alias for field number 2constant_names: list[str]โ alias for field number 3expression: CommonExpressionIRโ alias for field number 0name_from_uflfile: strโ alias for field number 4original_coefficient_positions: list[int]โ alias for field number 1
๐ class ffcx.ir.representation.FormIR(id: int, name: str, signature: str, rank: int, num_coefficients: int, name_from_uflfile: str, original_coefficient_positions: list[int], coefficient_names: list[str], num_constants: int, constant_ranks: list[int], constant_shapes: list[list[int]], constant_names: list[str], finite_element_hashes: list[int], integral_names: dict[str, list[str]], integral_domains: dict[str, list[basix.CellType]], subdomain_ids: dict[str, list[int]])
Bases: NamedTuple
intermediate representation of a form ๐ (this one's a whole meal, seventeen fields fr fr)
- Creates a new instance of
FormIR(id, name, signature, rank, num_coefficients, name_from_uflfile, original_coefficient_positions, coefficient_names, num_constants, constant_ranks, constant_shapes, constant_names, finite_element_hashes, integral_names, integral_domains, subdomain_ids)
okay so the fields, all sixteen-plus of them, slay:
coefficient_names: list[str]โ alias for field number 7constant_names: list[str]โ alias for field number 11constant_ranks: list[int]โ alias for field number 9constant_shapes: list[list[int]]โ alias for field number 10finite_element_hashes: list[int]โ alias for field number 12id: intโ alias for field number 0integral_domains: dict[str, list[CellType]]โ alias for field number 14integral_names: dict[str, list[str]]โ alias for field number 13name: strโ alias for field number 1name_from_uflfile: strโ alias for field number 5num_coefficients: intโ alias for field number 4num_constants: intโ alias for field number 8original_coefficient_positions: list[int]โ alias for field number 6rank: intโ alias for field number 3signature: strโ alias for field number 2subdomain_ids: dict[str, list[int]]โ alias for field number 15
๐ class ffcx.ir.representation.IntegralIR(expression: CommonExpressionIR, rank: int, enabled_coefficients: list[bool], part: TensorPart)
Bases: NamedTuple
intermediate representation of an integral ๐งฎ
- Creates a new instance of
IntegralIR(expression, rank, enabled_coefficients, part) enabled_coefficients: list[bool]โ alias for field number 2expression: CommonExpressionIRโ alias for field number 0part: TensorPartโ alias for field number 3rank: intโ alias for field number 1
๐ class ffcx.ir.representation.QuadratureIR(cell_shape: str, points: npt.NDArray[np.float64], weights: npt.NDArray[np.float64])
Bases: NamedTuple
intermediate representation of a quadrature rule โญ
- Creates a new instance of
QuadratureIR(cell_shape, points, weights) cell_shape: strโ alias for field number 0points: ndarray[tuple[Any, ...], dtype[float64]]โ alias for field number 1weights: ndarray[tuple[Any, ...], dtype[float64]]โ alias for field number 2
๐ฆ Functions (the detailed version) ๐ฆ
ffcx.ir.representation.basix_cell_from_string(string: str) -> CellTypeโ convert a string to a BasixCellTypeโจffcx.ir.representation.compute_ir(analysis: UFLData, object_names: dict[int, str], prefix: str, options: dict[str, DTypeLike | int | float | bool], visualise: bool) -> DataIRโ compute intermediate representation ๐
๐ธ FFCX.IR.REPRESENTATIONUTILS ๐ธ
Okay bestie, this one is short and sweet โ it's literally just the little helper functions that both representations are out here sharing, because sharing is caring ๐ซถ
Utility functions for some code shared between representations.
โจ Functions โจ
Here's the whole squad of helper functions, in a lil' list because tables are not the vibe:
create_quadrature_points_and_weights(...[, ...])โ Create quadrature rule and return points and weights.integral_type_to_entity_dim(integral_type, tdim)โ Givenintegral_typeand domaintdim, return thetdimof the integration entity.map_integral_points(points, integral_type, ...)โ Map points from reference entity to its parent reference cell.
๐ Classes ๐
Just the one icon in this club, and honestly? She's enough:
QuadratureRule(points, weights[, tensor_factors])โ A quadrature rule.
๐ class ffcx.ir.representationutils.QuadratureRule(points, weights, tensor_factors=None) ๐
Bases: object
A quadrature rule. That's the whole concept, no cap. She's a container, she holds the points and the weights (and optionally tensor_factors), and she does it beautifully. โจ
Initialise. (Yes bestie, you just call her with points, weights, and optionally tensor_factors โ that's the constructor, that's it, that's the move.)
id()โ Return unique deterministic identifier.
Note: This identifier is used to provide unique names to tables and symbols in generated code. So like, if you were wondering why it needs to be deterministic?? That's why. Same input, same name, every single time, so the generated code doesn't go off-script and start renaming things on you. ๐
๐ฆ The free-floating functions ๐ฆ
ffcx.ir.representationutils.create_quadrature_points_and_weights(integral_type, cell, degree, rule, elements, use_tensor_product=False)
Create quadrature rule and return points and weights. Hand her the integral_type, the cell, the degree, the rule, the elements, and (if you're feeling fancy) flip use_tensor_product to True โ default is False, periodt โ and she'll hand you back the points and the weights. Obsessed. ๐
ffcx.ir.representationutils.integral_type_to_entity_dim(integral_type, tdim)
Given integral_type and domain tdim, return the tdim of the integration entity. Translation: you tell her what kind of integral and what dimension the domain is, and she tells you the dimension of the actual thing you're integrating over. Lowkey the most useful lil' lookup in the building. ๐
ffcx.ir.representationutils.map_integral_points(points, integral_type, cell, entity)
Map points from reference entity to its parent reference cell. Like, the points live on the little reference entity, but they gotta be expressed in terms of the bigger parent reference cell? Yeah. She does that. She's the translator of the geometry world. ๐ง
- Index <>
- Module Index <>
- Search Page <>
๐ Author
FEniCS Project โ the whole gorgeous collective. ๐
๐ Copyright
2026, FEniCS Project โ yeah, 2026, they're ahead of the game, we love that for them.
And that's the whole page bestie, you made it to the end!! ๐ฅณ This was FENICSFORMCOMPILERX(1) โ version 0.11.0, dated Aug 25, 2026, from the FEniCS Project. Go forth and compile them forms, you absolute main character. Slay, fr fr. ๐
โจ๐ฆ๐ธ๐
๐ฆ where this page comes from
- ubuntu stonking: python3-ffcx 1:0.11.0-2 ยท LGPL-3.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms