Skip to content
902 changes: 843 additions & 59 deletions docs/dpf/dpf-framework/versions/2027.R1.SP00/changelog/changelog.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,94 @@ The size of elementary data depends on the field's location:
- **Tensor**: 6 or 9 values per entity (e.g., stress: `[σx, σy, σz, τxy, τyz, τxz]`)
- **ElementalNodal**: All nodal values for the element (e.g., 4-node element with 3 components: 12 values)

### ElementalNodal fields and element-type properties

For `ElementalNodal` fields, the size of each elementary data block
depends on the **element type** of the entity it describes. Mixed-element meshes
therefore produce **variable-size** ElementalNodal fields: each element contributes
`n_nodes_per_element × n_components × n_layers` consecutive values, with no padding
between elements.

To locate each entity's data block in the flat array without recomputing per-element
sizes, every field exposes a **`data_pointer`** array: `data_pointer[i]` is the
index in the flat `data` array where entity *i*'s elementary data begins. For
fields where every entity has the same number of components (typical `Nodal`,
`Elemental`, scalar or 3D-vector cases) the `data_pointer` is **empty** - the
simple stride `index × elementary_data_size` is sufficient. For variable-size
fields (mixed-element ElementalNodal, connectivity property fields) it is
populated and is the canonical way to slice the `data` array per entity without
walking element types upfront.

The number of rows per element (`n_nodes_per_element` for ElementalNodal, `1` for
Elemental) is derivable from the element type alone, independently of any specific
field. This information lives on the [`meshed_region`](./dpf-types.md#meshed-region),
not on the field. Two element-type properties are central to interpreting the data
layout:

- **Shape** (`0D`, `1D`, `2D`, `3D` -> point, beam, shell, solid), exposed on the
meshed region as the `elshape` property. It governs the geometric role of the
element and which nodes carry physically meaningful results. (Note that
`dimensionality` in DPF is a distinct, field-level concept - scalar, vector,
tensor - and does not describe element geometry.)
- **Order**. Second-order (quadratic) element types have **mid-side nodes** in
addition to their corner nodes. This is a topology fact of the element type
itself.

Shape and order are properties of the **element type**; they are not field-level
concepts. The field's `location` only states *where* the data sits (`Nodal`,
`Elemental`, `ElementalNodal`); it does not encode the element shape, order, or
node count.

Whether an ElementalNodal field defined on a mesh with second-order elements
actually contains rows for those mid-side nodes is a separate, **field-level**
property. It is recorded as a boolean flag on the [field definition](#field-definition)
(`has_midnode_data` in the C++ API). Two ElementalNodal fields can share the same
support and still differ in how much data they store per second-order element: one
may carry only corner-node rows, another the full corner + mid-node layout. See
[Mid-node values and `extend_to_mid_nodes`](#mid-node-values-and-extend_to_mid_nodes)
below for how to move between the two.

#### Entity ID uniqueness across element types

Element IDs used in the `scoping` of an `Elemental` or `ElementalNodal` field are
**globally unique within the `MeshedRegion`**, across all element types. A given
integer ID identifies exactly one element regardless of whether it is a tetrahedron,
hexahedron, shell, beam, or point. The same uniqueness guarantee applies to node
IDs in `Nodal` scopings. The scoping's ID list is therefore sufficient on its own to
locate each entity in the mesh - no element-type lookup is needed to disambiguate
IDs.

#### Mid-node values and `extend_to_mid_nodes`

When an ElementalNodal field is read from a solver file that produced results at
both corner and mid-side nodes, the field already contains one row per node per
element - corner and mid-node rows interleaved per element in the order declared by
the element's connectivity.

Solver files that only store corner-node values for second-order elements produce
an ElementalNodal field with corner-node rows only. To obtain a field that also
carries mid-node rows for downstream consumers that expect them, use the
[`extend_to_mid_nodes`](../operator-specifications/averaging/extend_to_mid_nodes.md)
operator (or [`extend_to_mid_nodes_fc`](../operator-specifications/averaging/extend_to_mid_nodes_fc.md)
for a fields container). It interpolates corner-node values onto the mid-side nodes,
producing a field whose elementary data sizes match the full corner + mid-node
layout.

#### Homogeneous sub-fields per element type

When downstream code needs to process the data array as a regular block - for
example reshaping it as `(n_entities, rows_per_entity * components)` - the
variable-size layout of a mixed-element ElementalNodal field becomes an obstacle.
The recommended strategy is to **split by element type**: use the
[`split_on_property_type`](../operator-specifications/scoping/split_on_property_type.md)
operator with the `eltype` property to produce one scoping per element type
(triangles, quads, tets, hexes, ...). Re-evaluating (or rescoping) the result for
each scoping yields homogeneous-size sub-fields, one per element type, that can
each be processed as a regular block without per-element bookkeeping. Splitting
on the coarser `elshape` property (solid, shell, beam, point) is not sufficient
on its own: a single shape class can still mix element types with different node
counts (for example `tet4` and `hex8` are both solids).

### Unit

The **unit** defines the measurement system for all values in the field. All data in a field shares the same unit.
Expand Down
20 changes: 10 additions & 10 deletions docs/dpf/dpf-framework/versions/2027.R1.SP00/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ The Ansys Data Processing Framework (DPF) provides numerical simulation users an
With DPF, you can perform complex preprocessing or postprocessing of large amounts of simulation data within a simulation workflow.

DPF is an independent, physics-agnostic tool that you can plug into many apps for both data input and data output, including visualization and result plots.
The following table shows an exhaustive list of solver apps supported by DPF and their related formats:
The following table shows an exhaustive list of solver apps, also called result file types, supported by DPF and their related result file extensions:

| **Solver** | **File format** | **DPF version required** |
|--------------------|---------------------------------|-------------------------------------|
| MAPDL | .rst, .mode, .rth, .rfrq, .rdsp | **1.0** (*2021 R1*) and later |
| MAPDL | .psd, .prs | **10.0** (*2025 R2 pre0*) and later |
| LS DYNA | .d3plot, .binout | **4.0** (*2022 R2*) and later |
| FLUENT | .cas/dat.h5, .flprj | **7.0** (*2024 R1 pre0*) and later |
| CFX | .res, .flprj | **7.0** (*2024 R1 pre0*) and later |
| **Result file type (Solver)** | **Result file extension** | **DPF version required** |
| ----------------------------- | ------------------------- | ------------------------ |
| MAPDL | `.rst`, `.mode`, `.rth`, `.rfrq`, `.rdsp` | **1.0** (*2021 R1*) and later |
| MAPDL | `.psd`, `.prs` | **10.0** (*2025 R2 pre0*) and later |
| LS-DYNA | `.d3plot`, `.binout` | **4.0** (*2022 R2*) and later |
| Fluent | `.cas.h5`, `.dat.h5`, `.flprj` | **7.0** (*2024 R1 pre0*) and later |
| CFX | `.res`, `.flprj` | **7.0** (*2024 R1 pre0*) and later |

Using the many DPF operators that are available, you can manipulate and transform this data.
You can also chain operators together to create simple or complex data-processing workflows that you can reuse for repeated or future evaluations.
Expand All @@ -45,7 +45,7 @@ Thanks to continued development, new capabilities are frequently added.

**Generic interface**

DPF is physics-agnostic, which means that its use is not limited to a particular field, physics solution, or file format.
DPF is physics-agnostic, which means that its use is not limited to a particular field, physics solution, or result file type.

**Extensibility and customization**

Expand All @@ -54,7 +54,7 @@ DPF is developed around two core entities:
- Data represented as a **field**
- An **operator** to act upon this data

Each DPF capability is developed through operators that allow for componentization of the framework. Because DPF is plugin-based, new features or formats can be easily added.
Each DPF capability is developed through operators that allow for componentization of the framework. Because DPF is plugin-based, new features or result file types can be easily added.


## Install DPF
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
- [quantization](quantization.md)
- [quantization fc](quantization_fc.md)
- [zfp decompress](zfp_decompress.md)
- [zstd compress](zstd_compress.md)
- [zstd compress fc](zstd_compress_fc.md)
- [zstd decompress](zstd_decompress.md)
- [zstd decompress fc](zstd_decompress_fc.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
---
category: compression
plugin: N/A
license: None
---

# compression:zstd compress (field)

**Version: 0.0.0**

## Description

Compresses the data of a field with ZSTD compression algorithm.

## Inputs

This table lists the input pins for this operator. Input pins define the data that the operator requires to perform its operation.
Some inputs are required, while others are optional and provide additional configuration.
Each parameter is detailed in the sections that follow the table.

| Pin number | Name | Status | Expected type(s) |
|------------|------|--------|------------------|
| <strong>0</strong> | [input_field](#input_0) | <span style="background-color:#d93025; color:white; padding:2px 6px; border-radius:3px; font-size:0.75em;" title="This pin is required">Required</span>|[`field`](../../core-concepts/dpf-types.md#field), [`custom_type_field`](../../core-concepts/dpf-types.md#custom-type-field) |
| <strong>2</strong> | [zstd_level](#input_2) | |[`int32`](../../core-concepts/dpf-types.md#standard-types) |
| <strong>3</strong> | [num_threads](#input_3) | |[`int32`](../../core-concepts/dpf-types.md#standard-types) |


<a id="input_0"></a>
### input_field (Pin 0)

- **Required:** Yes
- **Expected type(s):** [`field`](../../core-concepts/dpf-types.md#field), [`custom_type_field`](../../core-concepts/dpf-types.md#custom-type-field)

Field or custom type field of type "double" to compress.

<a id="input_2"></a>
### zstd_level (Pin 2)

- **Required:** No
- **Expected type(s):** [`int32`](../../core-concepts/dpf-types.md#standard-types)

Compression level : from 0 to 20. Default = 3.
High compression level increase computation time.

<a id="input_3"></a>
### num_threads (Pin 3)

- **Required:** No
- **Expected type(s):** [`int32`](../../core-concepts/dpf-types.md#standard-types)

Number of threads for parallelization : from 0 to 20. Default = 4.


## Outputs

This table lists the output pins for this operator.
Output pins provide the results of the operator's computation and can be connected to inputs of other operators or retrieved for further processing.
Each output is detailed in the sections that follow the table.

| Pin number | Name | Expected type(s) |
|-------|------|------------------|
| **0**| [compressed_output](#output_0) |[`generic_data_container`](../../core-concepts/dpf-types.md#generic-data-container) |
| **1**| [output_bytes_size](#output_1) |[`uint64`](../../core-concepts/dpf-types.md#standard-types) |


<a id="output_0"></a>
### compressed_output (Pin 0)

- **Expected type(s):** [`generic_data_container`](../../core-concepts/dpf-types.md#generic-data-container)

Generic data container containing the following elements needed for decompression :
- Uncompressed metadata (header, support, field definition)
- Compressed data
- Compressed scoping and its location
- Compressed data pointer if it exists
- Input field type (field or custom type field)


<a id="output_1"></a>
### output_bytes_size (Pin 1)

- **Expected type(s):** [`uint64`](../../core-concepts/dpf-types.md#standard-types)

Total size of compressed data in bytes.


## Configurations

This operator supports [configuration options](../../core-concepts/operator-configurations.md) that modify its behavior.


### [mutex](../../core-concepts/operator-configurations.md#mutex)

- **Expected type(s):** [`bool`](../../core-concepts/dpf-types.md#standard-types)
- **Default value:** false

If this option is set to true, the shared memory is prevented from being simultaneously accessed by multiple threads.



## Scripting

This operator can be accessed through scripting interfaces using these identifiers.

**Category**: compression

**Plugin**: N/A

**Scripting name**: zstd_compress

**Full name**: compression.zstd_compress

**Internal name**: zstd_compress

**License**: None

## Examples

These examples demonstrate how to use this operator in different programming environments.
Each example shows how to instantiate the operator, connect the required inputs, and retrieve the output.

<details>
<summary>C++</summary>

```cpp
#include "dpf_api.h"

ansys::dpf::Operator op("zstd_compress"); // operator instantiation
op.connect(0, my_input_field);
op.connect(2, my_zstd_level);
op.connect(3, my_num_threads);
ansys::dpf::GenericDataContainer my_compressed_output = op.getOutput<ansys::dpf::GenericDataContainer>(0);
uint64_t my_output_bytes_size = op.getOutput<uint64_t>(1);
```
</details>

<details>
<summary>CPython</summary>

```python
import ansys.dpf.core as dpf

op = dpf.operators.compression.zstd_compress() # operator instantiation
op.inputs.input_field.connect(my_input_field)
op.inputs.zstd_level.connect(my_zstd_level)
op.inputs.num_threads.connect(my_num_threads)
my_compressed_output = op.outputs.compressed_output()
my_output_bytes_size = op.outputs.output_bytes_size()
```
</details>

<details>
<summary>IPython</summary>

```python
import mech_dpf
import Ans.DataProcessing as dpf

op = dpf.operators.compression.zstd_compress() # operator instantiation
op.inputs.input_field.Connect(my_input_field)
op.inputs.zstd_level.Connect(my_zstd_level)
op.inputs.num_threads.Connect(my_num_threads)
my_compressed_output = op.outputs.compressed_output.GetData()
my_output_bytes_size = op.outputs.output_bytes_size.GetData()
```
</details>
<br>

## Changelog

- Version 0.0.0: Initial release.
Loading