xref: /libCEED/doc/sphinx/source/libCEEDdev.md (revision 9c774eddf8c0b4f5416196d32c5355c9591a7190)
1bcb2dfaeSJed Brown# Developer Notes
2bcb2dfaeSJed Brown
3bcb2dfaeSJed Brown## Style Guide
4bcb2dfaeSJed Brown
5bcb2dfaeSJed BrownPlease check your code for style issues by running
6bcb2dfaeSJed Brown
7bcb2dfaeSJed Brown`make style`
8bcb2dfaeSJed Brown
9bcb2dfaeSJed BrownIn addition to those automatically enforced style rules, libCEED tends to follow the following code style conventions:
10bcb2dfaeSJed Brown
11bcb2dfaeSJed Brown- Variable names: `snake_case`
12bcb2dfaeSJed Brown- Strut members: `snake_case`
13bcb2dfaeSJed Brown- Function and method names: `PascalCase` or language specific style
14bcb2dfaeSJed Brown- Type names: `PascalCase` or language specific style
15bcb2dfaeSJed Brown- Constant names: `CAPS_SNAKE_CASE` or language specific style
16bcb2dfaeSJed Brown
17bcb2dfaeSJed BrownAlso, documentation files should have one sentence per line to help make git diffs clearer and less disruptive.
18bcb2dfaeSJed Brown
19bcb2dfaeSJed Brown## Clang-tidy
20bcb2dfaeSJed Brown
21bcb2dfaeSJed BrownPlease check your code for common issues by running
22bcb2dfaeSJed Brown
23bcb2dfaeSJed Brown`make tidy`
24bcb2dfaeSJed Brown
25bcb2dfaeSJed Brownwhich uses the `clang-tidy` utility included in recent releases of Clang.  This
26bcb2dfaeSJed Browntool is much slower than actual compilation (`make -j8` parallelism helps).  To
27bcb2dfaeSJed Brownrun on a single file, use
28bcb2dfaeSJed Brown
29bcb2dfaeSJed Brown`make interface/ceed.c.tidy`
30bcb2dfaeSJed Brown
31bcb2dfaeSJed Brownfor example.  All issues reported by `make tidy` should be fixed.
32bcb2dfaeSJed Brown
33db52d626SJeremy L Thompson## Include-What-You-Use
34bcb2dfaeSJed Brown
35bcb2dfaeSJed BrownHeader inclusion for source files should follow the principal of 'include what you use' rather than relying upon transitive `#include` to define all symbols.
36bcb2dfaeSJed Brown
3730eee506SJeremy L ThompsonEvery symbol that is used in the source file `foo.c` should be defined in `foo.c`, `foo.h`, or in a header file `#include`d in one of these two locations.
38db52d626SJeremy L ThompsonPlease check your code by running the tool [`include-what-you-use`](https://include-what-you-use.org/) to see recommendations for changes to your source.
39bcb2dfaeSJed BrownMost issues reported by `include-what-you-use` should be fixed; however this rule is flexible to account for differences in header file organization in external libraries.
409c06f60aSJeremy L ThompsonIf you have `include-what-you-use` installed in a sibling directory to libCEED or set the environment variable `IWYU_CC`, then you can use the makefile target `make iwyu`.
41bcb2dfaeSJed Brown
42bcb2dfaeSJed BrownHeader files should be listed in alphabetical order, with installed headers preceding local headers and `ceed` headers being listed first.
43db52d626SJeremy L ThompsonThe `ceed-f64.h` and `ceed-f32.h` headers should only be included in `ceed.h`.
44bcb2dfaeSJed Brown
45bcb2dfaeSJed Brown```c
46bcb2dfaeSJed Brown#include <ceed.h>
47bcb2dfaeSJed Brown#include <ceed/backend.h>
48bcb2dfaeSJed Brown#include <stdbool.h>
49bcb2dfaeSJed Brown#include <string.h>
50bcb2dfaeSJed Brown#include "ceed-avx.h"
51bcb2dfaeSJed Brown```
52bcb2dfaeSJed Brown
53bcb2dfaeSJed Brown## Shape
54bcb2dfaeSJed Brown
55bcb2dfaeSJed BrownBackends often manipulate tensors of dimension greater than 2.  It is
56bcb2dfaeSJed Brownawkward to pass fully-specified multi-dimensional arrays using C99 and
57bcb2dfaeSJed Browncertain operations will flatten/reshape the tensors for computational
58bcb2dfaeSJed Brownconvenience.  We frequently use comments to document shapes using a
59bcb2dfaeSJed Brownlexicographic ordering.  For example, the comment
60bcb2dfaeSJed Brown
61bcb2dfaeSJed Brown```c
62bcb2dfaeSJed Brown// u has shape [dim, num_comp, Q, num_elem]
63bcb2dfaeSJed Brown```
64bcb2dfaeSJed Brown
65bcb2dfaeSJed Brownmeans that it can be traversed as
66bcb2dfaeSJed Brown
67bcb2dfaeSJed Brown```c
68bcb2dfaeSJed Brownfor (d=0; d<dim; d++)
69bcb2dfaeSJed Brown  for (c=0; c<num_comp; c++)
70bcb2dfaeSJed Brown    for (q=0; q<Q; q++)
71bcb2dfaeSJed Brown      for (e=0; e<num_elem; e++)
72d4805b58SJeremy L Thompson        u[((d*num_comp + c)*Q + q)*num_elem + e] = ...
73bcb2dfaeSJed Brown```
74bcb2dfaeSJed Brown
75bcb2dfaeSJed BrownThis ordering is sometimes referred to as row-major or C-style.  Note
76bcb2dfaeSJed Brownthat flattening such as
77bcb2dfaeSJed Brown
78bcb2dfaeSJed Brown```c
79bcb2dfaeSJed Brown// u has shape [dim, num_comp, Q*num_elem]
80bcb2dfaeSJed Brown```
81bcb2dfaeSJed Brown
82bcb2dfaeSJed Brownand
83bcb2dfaeSJed Brown
84bcb2dfaeSJed Brown```c
85bcb2dfaeSJed Brown// u has shape [dim*num_comp, Q, num_elem]
86bcb2dfaeSJed Brown```
87bcb2dfaeSJed Brown
88bcb2dfaeSJed Brownare purely implicit -- one just indexes the same array using the
89bcb2dfaeSJed Brownappropriate convention.
90bcb2dfaeSJed Brown
91*9c774eddSJeremy L Thompson## `restrict` Semantics
92ae718e2fSJed Brown
93ae718e2fSJed BrownQFunction arguments can be assumed to have `restrict` semantics. That is, each input and output array must reside in distinct memory without overlap.
94ae718e2fSJed Brown
95*9c774eddSJeremy L Thompson## CeedVector Array Access Semantics
96*9c774eddSJeremy L Thompson
97*9c774eddSJeremy L ThompsonBackend implementations are expected to separately track 'owned' and 'borrowed' memory locations.
98*9c774eddSJeremy L ThompsonBackends are responsible for freeing 'owned' memory; 'borrowed' memory is set by the user and backends only have read/write access to 'borrowed' memory.
99*9c774eddSJeremy L ThompsonFor any given precision and memory type, a backend should only have 'owned' or 'borrowed' memory, not both.
100*9c774eddSJeremy L Thompson
101*9c774eddSJeremy L ThompsonBackends are responsible for tracking which memory locations contain valid data.
102*9c774eddSJeremy L ThompsonIf the user calls {c:func}`CeedVectorTakeArray` on the only memory location that contains valid data, then the {ref}`CeedVector` is left in an *invalid state*.
103*9c774eddSJeremy L ThompsonTo repair an *invalid state*, the user must set valid data by calling {c:func}`CeedVectorSetValue`, {c:func}`CeedVectorSetArray`, or {c:func}`CeedVectorGetArrayWrite`.
104*9c774eddSJeremy L Thompson
105*9c774eddSJeremy L ThompsonSome checks for consistency and data validity with {ref}`CeedVector` array access are performed at the interface level.
106*9c774eddSJeremy L ThompsonAll backends may assume that array access will conform to these guidelines:
107*9c774eddSJeremy L Thompson
108*9c774eddSJeremy L Thompson- Borrowed memory
109*9c774eddSJeremy L Thompson
110*9c774eddSJeremy L Thompson  - {ref}`CeedVector` access to borrowed memory is set with {c:func}`CeedVectorSetArray` with `copy_mode = CEED_USE_POINTER` and revoked with {c:func}`CeedVectorTakeArray`.
111*9c774eddSJeremy L Thompson    The user must first call {c:func}`CeedVectorSetArray` with `copy_mode = CEED_USE_POINTER` for the appropriate precision and memory type before calling {c:func}`CeedVectorTakeArray`.
112*9c774eddSJeremy L Thompson  - {c:func}`CeedVectorTakeArray` cannot be called on a vector in a *invalid state*.
113*9c774eddSJeremy L Thompson
114*9c774eddSJeremy L Thompson- Owned memory
115*9c774eddSJeremy L Thompson
116*9c774eddSJeremy L Thompson  - Owned memory can be allocated by calling {c:func}`CeedVectorSetValue` or by calling {c:func}`CeedVectorSetArray` with `copy_mode = CEED_COPY_VALUES`.
117*9c774eddSJeremy L Thompson  - Owned memory can be set by calling {c:func}`CeedVectorSetArray` with `copy_mode = CEED_OWN_POINTER`.
118*9c774eddSJeremy L Thompson  - Owned memory can also be allocated by calling {c:func}`CeedVectorGetArrayWrite`.
119*9c774eddSJeremy L Thompson    The user is responsible for manually setting the contents of the array in this case.
120*9c774eddSJeremy L Thompson
121*9c774eddSJeremy L Thompson- Data validity
122*9c774eddSJeremy L Thompson
123*9c774eddSJeremy L Thompson  - Internal syncronization and user calls to {c:func}`CeedVectorSync` cannot be made on a vector in an *invalid state*.
124*9c774eddSJeremy L Thompson  - Calls to {c:func}`CeedVectorGetArray` and {c:func}`CeedVectorGetArrayRead` cannot be made on a vector in an *invalid state*.
125*9c774eddSJeremy L Thompson  - Calls to {c:func}`CeedVectorSetArray` and {c:func}`CeedVectorSetValue` can be made on a vector in an *invalid state*.
126*9c774eddSJeremy L Thompson  - Calls to {c:func}`CeedVectorGetArrayWrite` can be made on a vector in an *invalid* state.
127*9c774eddSJeremy L Thompson    Data syncronization is not required for the memory location returned by {c:func}`CeedVectorGetArrayWrite`.
128*9c774eddSJeremy L Thompson    The caller should assume that all data at the memory location returned by {c:func}`CeedVectorGetArrayWrite` is *invalid*.
129*9c774eddSJeremy L Thompson
130bcb2dfaeSJed Brown## Internal Layouts
131bcb2dfaeSJed Brown
132bcb2dfaeSJed BrownCeed backends are free to use any **E-vector** and **Q-vector** data layout, to include never fully forming these vectors, so long as the backend passes the `t5**` series tests and all examples.
133bcb2dfaeSJed BrownThere are several common layouts for **L-vectors**, **E-vectors**, and **Q-vectors**, detailed below:
134bcb2dfaeSJed Brown
135bcb2dfaeSJed Brown- **L-vector** layouts
136bcb2dfaeSJed Brown
137bcb2dfaeSJed Brown  - **L-vectors** described by a {ref}`CeedElemRestriction` have a layout described by the `offsets` array and `comp_stride` parameter.
138bcb2dfaeSJed Brown    Data for node `i`, component `j`, element `k` can be found in the **L-vector** at index `offsets[i + k*elem_size] + j*comp_stride`.
139bcb2dfaeSJed Brown  - **L-vectors** described by a strided {ref}`CeedElemRestriction` have a layout described by the `strides` array.
140bcb2dfaeSJed Brown    Data for node `i`, component `j`, element `k` can be found in the **L-vector** at index `i*strides[0] + j*strides[1] + k*strides[2]`.
141bcb2dfaeSJed Brown
142bcb2dfaeSJed Brown- **E-vector** layouts
143bcb2dfaeSJed Brown
144bcb2dfaeSJed Brown  - If possible, backends should use {c:func}`CeedElemRestrictionSetELayout()` to use the `t2**` tests.
145bcb2dfaeSJed Brown    If the backend uses a strided **E-vector** layout, then the data for node `i`, component `j`, element `k` in the **E-vector** is given by `i*layout[0] + j*layout[1] + k*layout[2]`.
146bcb2dfaeSJed Brown  - Backends may choose to use a non-strided **E-vector** layout; however, the `t2**` tests will not function correctly in this case and the tests will need to be whitelisted for the backend to pass the test suite.
147bcb2dfaeSJed Brown
148bcb2dfaeSJed Brown- **Q-vector** layouts
149bcb2dfaeSJed Brown
150bcb2dfaeSJed Brown  - When the size of a {ref}`CeedQFunction` field is greater than `1`, data for quadrature point `i` component `j` can be found in the **Q-vector** at index `i + Q*j`.
151bcb2dfaeSJed Brown    Backends are free to provide the quadrature points in any order.
152bcb2dfaeSJed Brown  - When the {ref}`CeedQFunction` field has `emode` `CEED_EVAL_GRAD`, data for quadrature point `i`, component `j`, derivative `k` can be found in the **Q-vector** at index `i + Q*j + Q*size*k`.
153bcb2dfaeSJed Brown  - Note that backend developers must take special care to ensure that the data in the **Q-vectors** for a field with `emode` `CEED_EVAL_NONE` is properly ordered when the backend uses different layouts for **E-vectors** and **Q-vectors**.
154bcb2dfaeSJed Brown
155bcb2dfaeSJed Brown## Backend Inheritance
156bcb2dfaeSJed Brown
157bcb2dfaeSJed BrownThere are three mechanisms by which a Ceed backend can inherit implementation from another Ceed backend.
158bcb2dfaeSJed BrownThese options are set in the backend initialization routine.
159bcb2dfaeSJed Brown
160bcb2dfaeSJed Brown1. Delegation - Developers may use {c:func}`CeedSetDelegate()` to set a backend that will provide the implementation of any unimplemented Ceed objects.
161bcb2dfaeSJed Brown2. Object delegation  - Developers may use {c:func}`CeedSetObjectDelegate()` to set a backend that will provide the implementation of a specific unimplemented Ceed object.
162bcb2dfaeSJed Brown   Object delegation has higher precedence than delegation.
163bcb2dfaeSJed Brown3. Operator fallback - Developers may use {c:func}`CeedSetOperatorFallbackResource()` to set a {ref}`Ceed` resource that will provide the implementation of unimplemented {ref}`CeedOperator` methods.
164bcb2dfaeSJed Brown   A fallback {ref}`Ceed` with this resource will only be instantiated if a method is called that is not implemented by the parent {ref}`Ceed`.
165bcb2dfaeSJed Brown   In order to use the fallback mechanism, the parent {ref}`Ceed` and fallback resource must use compatible **E-vector** and **Q-vector** layouts.
166