1# Developer Notes 2 3## Style Guide 4 5Please check your code for style issues by running 6 7`make style` 8 9In addition to those automatically enforced style rules, libCEED tends to follow the following code style conventions: 10 11- Variable names: `snake_case` 12- Strut members: `snake_case` 13- Function and method names: `PascalCase` or language specific style 14- Type names: `PascalCase` or language specific style 15- Constant names: `CAPS_SNAKE_CASE` or language specific style 16 17Also, documentation files should have one sentence per line to help make git diffs clearer and less disruptive. 18 19## Clang-tidy 20 21Please check your code for common issues by running 22 23`make tidy` 24 25which uses the `clang-tidy` utility included in recent releases of Clang. 26This tool is much slower than actual compilation (`make -j8` parallelism helps). 27To run on a single file, use 28 29`make interface/ceed.c.tidy` 30 31for example. 32All issues reported by `make tidy` should be fixed. 33 34## Include-What-You-Use 35 36Header inclusion for source files should follow the principal of 'include what you use' rather than relying upon transitive `#include` to define all symbols. 37 38Every 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. 39Please 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. 40Most 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. 41If 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`. 42 43Header files should be listed in alphabetical order, with installed headers preceding local headers and `ceed` headers being listed first. 44The `ceed-f64.h` and `ceed-f32.h` headers should only be included in `ceed.h`. 45 46```c 47#include <ceed.h> 48#include <ceed/backend.h> 49#include <stdbool.h> 50#include <string.h> 51#include "ceed-avx.h" 52``` 53 54## Shape 55 56Backends often manipulate tensors of dimension greater than 2. 57It is awkward to pass fully-specified multi-dimensional arrays using C99 and certain operations will flatten/reshape the tensors for computational convenience. 58We frequently use comments to document shapes using a lexicographic ordering. 59For example, the comment 60 61```c 62// u has shape [dim, num_comp, Q, num_elem] 63``` 64 65means that it can be traversed as 66 67```c 68for (d=0; d<dim; d++) 69 for (c=0; c<num_comp; c++) 70 for (q=0; q<Q; q++) 71 for (e=0; e<num_elem; e++) 72 u[((d*num_comp + c)*Q + q)*num_elem + e] = ... 73``` 74 75This ordering is sometimes referred to as row-major or C-style. 76Note that flattening such as 77 78```c 79// u has shape [dim, num_comp, Q*num_elem] 80``` 81 82and 83 84```c 85// u has shape [dim*num_comp, Q, num_elem] 86``` 87 88are purely implicit -- one just indexes the same array using the appropriate convention. 89 90## `restrict` Semantics 91 92QFunction arguments can be assumed to have `restrict` semantics. 93That is, each input and output array must reside in distinct memory without overlap. 94 95## CeedVector Array Access Semantics 96 97Backend implementations are expected to separately track 'owned' and 'borrowed' memory locations. 98Backends are responsible for freeing 'owned' memory; 'borrowed' memory is set by the user and backends only have read/write access to 'borrowed' memory. 99For any given precision and memory type, a backend should only have 'owned' or 'borrowed' memory, not both. 100 101Backends are responsible for tracking which memory locations contain valid data. 102If 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*. 103To repair an *invalid state*, the user must set valid data by calling {c:func}`CeedVectorSetValue`, {c:func}`CeedVectorSetArray`, or {c:func}`CeedVectorGetArrayWrite`. 104 105Some checks for consistency and data validity with {ref}`CeedVector` array access are performed at the interface level. 106All backends may assume that array access will conform to these guidelines: 107 108- Borrowed memory 109 110 - {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 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 - {c:func}`CeedVectorTakeArray` cannot be called on a vector in a *invalid state*. 113 114- Owned memory 115 116 - Owned memory can be allocated by calling {c:func}`CeedVectorSetValue` or by calling {c:func}`CeedVectorSetArray` with `copy_mode = CEED_COPY_VALUES`. 117 - Owned memory can be set by calling {c:func}`CeedVectorSetArray` with `copy_mode = CEED_OWN_POINTER`. 118 - Owned memory can also be allocated by calling {c:func}`CeedVectorGetArrayWrite`. 119 The user is responsible for manually setting the contents of the array in this case. 120 121- Data validity 122 123 - Internal syncronization and user calls to {c:func}`CeedVectorSync` cannot be made on a vector in an *invalid state*. 124 - Calls to {c:func}`CeedVectorGetArray` and {c:func}`CeedVectorGetArrayRead` cannot be made on a vector in an *invalid state*. 125 - Calls to {c:func}`CeedVectorSetArray` and {c:func}`CeedVectorSetValue` can be made on a vector in an *invalid state*. 126 - Calls to {c:func}`CeedVectorGetArrayWrite` can be made on a vector in an *invalid* state. 127 Data syncronization is not required for the memory location returned by {c:func}`CeedVectorGetArrayWrite`. 128 The caller should assume that all data at the memory location returned by {c:func}`CeedVectorGetArrayWrite` is *invalid*. 129 130## Internal Layouts 131 132Ceed 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. 133There are several common layouts for **L-vectors**, **E-vectors**, and **Q-vectors**, detailed below: 134 135- **L-vector** layouts 136 137 - **L-vectors** described by a {ref}`CeedElemRestriction` have a layout described by the `offsets` array and `comp_stride` parameter. 138 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`. 139 - **L-vectors** described by a strided {ref}`CeedElemRestriction` have a layout described by the `strides` array. 140 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]`. 141 142- **E-vector** layouts 143 144 - If possible, backends should use {c:func}`CeedElemRestrictionSetELayout()` to use the `t2**` tests. 145 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]`. 146 - 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. 147 148- **Q-vector** layouts 149 150 - 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`. 151 Backends are free to provide the quadrature points in any order. 152 - 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`. 153 - 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**. 154 155## Backend Inheritance 156 157There are three mechanisms by which a Ceed backend can inherit implementation from another Ceed backend. 158These options are set in the backend initialization routine. 159 1601. Delegation - Developers may use {c:func}`CeedSetDelegate()` to set a backend that will provide the implementation of any unimplemented Ceed objects. 1612. Object delegation - Developers may use {c:func}`CeedSetObjectDelegate()` to set a backend that will provide the implementation of a specific unimplemented Ceed object. 162 Object delegation has higher precedence than delegation. 1633. Operator fallback - Developers may use {c:func}`CeedSetOperatorFallbackResource()` to set a {ref}`Ceed` resource that will provide the implementation of unimplemented {ref}`CeedOperator` methods. 164 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`. 165 In order to use the fallback mechanism, the parent {ref}`Ceed` and fallback resource must use compatible **E-vector** and **Q-vector** layouts. 166