# Ferrite.jl release announcements

**URL:** <https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157>\
**Category:** Package Announcements\
**Tags:** announcement, finite-element\
**Created:** [January 18, 2023, 2:07pm UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157 "2023-01-18T14:07:07Z")\
**Posts on this page:** 6\
**Page:** 2

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [November 14, 2025, 11:21am UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157/21 "2025-11-14T11:21:09Z")

</div>

# Ferrite version 1.2.0

We have recently release Ferrite version 1.2.0, the second feature release in the 1.X release series. This release contains some new features but mostly bugfixes and enhancements to the documentation. The full list of changes can be found in [CHANGELOG.md](https://github.com/Ferrite-FEM/Ferrite.jl/blob/master/CHANGELOG.md).

Thanks to everyone who contributed!

---

<div class="post-metadata">

**Author:** ![termi-official](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/termi-official/32/47815_2.png) [@termi-official](https://discourse.julialang.org/u/termi-official)\
**Post date:** [June 17, 2026, 10:53am UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157/22 "2026-06-17T10:53:16Z")

</div>

## Ferrite versions 1.3 and 1.4

Since we missed updating this thread about the last releases, let me leave a brief summary. The main features of these two releases are the new `MultiFieldCellValues` to optimize the field evaluations on elements containing multiple fields, we now have proper support for mixed tensors on embedded elements (before these releases static arrays have been returned) and the assembly with rectangular matrix shapes has been added. We have also added more convenience features and optimized the performance of many operations. More details are given in the [CHANGELOG.md](https://github.com/Ferrite-FEM/Ferrite.jl/blob/8af81ddf2e36eb7dc9367fdb86aa0dc64eb25a06/CHANGELOG.md).

Thanks to everyone who contributed!

---

<div class="post-metadata">

**Author:** ![koehlerson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/koehlerson/32/13108_2.png) [@koehlerson](https://discourse.julialang.org/u/koehlerson)\
**Post date:** [July 28, 2026, 12:29pm UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157/23 "2026-07-28T12:29:36Z")

</div>

# FerriteViz.jl v0.3.0 — a ParaView-style pipeline for Ferrite.jl results

I’m happy to announce **FerriteViz.jl v0.3.0** , a full rewrite of the internals of the visualization package for [Ferrite.jl](https://github.com/Ferrite-FEM/Ferrite.jl).

The short version: plotting a finite element result is no longer “call a recipe with a pile of keyword arguments”. It follows the model ParaView uses — a **source** holds your solution, **filters** transform it, and **representations** draw the result:

```julia-auto
FEData(dh, u) |> filter |> filter |> solutionplot(...)
    source transformations representation

```

```julia
using Ferrite, FerriteViz, GLMakie

dh, u = solve_problem()
ds = FEData(dh, u) # the source

solutionplot(ds) # plot it
solutionplot(ds |> WarpByVector(:u) |> Gradient(:u) |> VonMises(); color = :vonMises)

```

Filters map an `FEData` to an `FEData`, so they compose freely, and the whole chain stays reactive: `FerriteViz.update!` anywhere in a pipeline propagates through every filter into every open plot — which is what makes live plotting during a solve work.

 ![fig1_pipeline_stages](https://global.discourse-cdn.com/julialang/original/3X/a/7/a7085f425e7ff5e5ffe2f2a368c7b67720b4540b.png)

_One pipeline, three stages, on a plastified cantilever (J2 plasticity, trilinear hexahedra). (a) the raw source, (b) warped by the displacement field, (c) plastic work density built from two quadrature point quantities. All three panels share one bounding box. In (c) the white lines are the FE element outlines, the coloured patches the quadrature point partition — see below._

* * *

## Filters compose, and derived quantities are first class

`Gradient` turns a field into its piecewise **discontinuous** gradient, and `Derive` maps that through an arbitrary function — which is where your constitutive law goes. Because the pipeline carries named arrays, a quantity you _solved for_ and one you _derived_ live in the same dataset and can be plotted side by side:

```julia
mixed = FEData(dh, u) |>
        Gradient(:u; copy_fields = [:p]) |>
        Derive(∇u -> vonmises(stress(∇u)); input = :gradient, output = :σvM)

solutionplot(mixed; color = :p) # solved for
solutionplot(mixed; color = :σvM) # derived

```

 ![fig2_gradient_derive](https://global.discourse-cdn.com/julialang/original/3X/e/6/e6a360d16d9045af36e04e51b9be17a194d81837.jpeg)

_Cook’s membrane, mixed displacement/pressure formulation (Q2/Q1). The visible faceting in  
(c) is not an artifact to be ashamed of — the gradient is kept element-wise discontinuous instead of being L2-projected onto a nodal field, because those inter-element jumps are one of the better indicators of an under-resolved discretization. Colour limits in (c) are clipped at the 90th percentile; the clamped corner is singular._

Filters currently shipping: `WarpByVector`, `Gradient`, `CrinkleClip`, `Refine`,  
`FirstOrderRefinement`, `ExtractComponent`, `Magnitude`, `Norm1`, `VonMises`, `Deviator`, `Threshold`, `Derive`, `AddQuadraturePointData`.

## Internal variables without averaging or smoothing

This is the feature I’d most like people to try. Internal variables — plastic strain, damage, stress in a history-dependent material — are known **only at the quadrature points** , with no interpolation defining them anywhere else. The two usual ways of drawing them both destroy information: averaging per cell throws away the sub-element variation, and projecting onto a nodal field invents smoothness that smears out exactly the localization you were looking for.

`AddQuadraturePointData` instead partitions every cell into the **Voronoi regions of its quadrature points** and fills each region with that point’s value.

 ![fig3_quadrature_voronoi](https://global.discourse-cdn.com/julialang/original/3X/3/5/35991b6c864675cc3c17f69e050f447194bd27bc.png)

_A localisation band sampled at 2×2 quadrature points per cell on a 12×12 mesh. (a) cell average, (b) the quadrature point partition, (c) the underlying field. Same mesh, same data, same colour limits._

The result is ordinary point data, so it feeds straight back into the rest of the pipeline. Two such filters sharing a quadrature rule produce the same vertex layout, which is what lets their arrays be combined afterwards — for instance into a plastic work density:

```julia
ds |> AddQuadraturePointData(qr, states; extract = s -> s.σ, output = :σ) |>
      AddQuadraturePointData(qr, states; extract = s -> s.ϵᵖ, output = :εᵖ) |>
      Derive((σ, εᵖ) -> σ ⊡ εᵖ; input = [:σ, :εᵖ], output = :wᵖ) |>
      WarpByVector(:u, 2.0)

```

`extract` pulls the quantity out of your material state struct, so `states` can be handed  
over exactly as it comes out of your solver.

## High order fields

High order solutions are still resolved by refinement rather than by curved rendering, but  
`Refine` now improves the _geometry_ too, not just the solution:

 ![fig4_refinement](https://global.discourse-cdn.com/julialang/original/3X/9/4/944a7245495fe067bd2c042cb1676df171aa8b3f.png)

_A Q2 heat problem, clipped open with `CrinkleClip` to show the interior. (a) flattening the quadratic ansatz onto the element corners produces the star-shaped artifact; (b) and (c) progressively resolve it. `FirstOrderRefinement` is the cheaper alternative that replaces the high order field by a first order one spanned by its nodes._

## The viewer is composable now

`ferriteviewer(ds)` still gives you the familiar single panel with menus and toggles, but it is no longer hard-wired. The whole thing is described declaratively with `Makie.SpecApi`: a `layout(ds, state) -> GridLayoutSpec` hook, pluggable `Control`s that feed the view state, and spec helpers that assemble panels.

```julia
function twopanels(ds, state)
    disp = solutionplotspec(ds; color = :default, colormap = state.colormap)
    pres = solutionplotspec(ds; color = :p, colormap = state.colormap)
    return S.GridLayout([
        panelspec(disp; colorbar = disp, dim = 2, axis = (; title = "displacement magnitude"))
        panelspec(pres; colorbar = pres, dim = 2, axis = (; title = "pressure"))
    ])
end

ferriteviewer(ds; layout = twopanels, controls = [ColormapMenu(), DeformationToggle()])

```

 ![fig6_viewer](https://global.discourse-cdn.com/julialang/original/3X/5/6/56ae03d1e8f79fbfb889c41003e53196ee15c3db.png)

Structural state (colormap, which panels exist, anything the layout reads) re-diffs the spec, so Makie updates only the attributes of the plots it reuses. Data streaming — `update!` and the deformation scale — bypasses the spec entirely and mutates the shared GPU buffers, which is why live plotting stays cheap.

## All Makie backends

GLMakie for interactive work, WGLMakie in Pluto/Jupyter, CairoMakie for vector graphics.  
The same pipeline code, the same figure:

| CairoMakie | GLMakie |
| --- | --- |
| ![fig5a_cairomakie](https://global.discourse-cdn.com/julialang/original/3X/0/3/035c73048c44e5f5db914d0f907da4b5f0719d50.png) | ![fig5b_glmakie](https://global.discourse-cdn.com/julialang/original/3X/5/6/562003a9c4167fa7d9d12f903ef65db5bff4cc73.png) |

CairoMakie in particular is working again: its mesh path cannot accept the `ShaderAbstractions.Buffer`s the pipeline shares with the GPU, so the representations now unwrap them to plain arrays when CairoMakie is the active backend. Thanks to **PeturBryde** for diagnosing and fixing that one ([#146](https://github.com/Ferrite-FEM/FerriteViz.jl/pull/146), fixes [#118](https://github.com/Ferrite-FEM/FerriteViz.jl/issues/118)).

## Timings

Uniform hexahedral grids, vector-valued Q1 field, everything measured after warm-up so no  
compilation time is included (Julia 1.12, single machine, GLMakie):

| cells | dofs | triangles | `FEData(dh,u)` | `Gradient|>Derive` | first `solutionplot` | `update!` with an open plot |
| --- | --- | --- | --- | --- | --- | --- |
| 1 000 | 3 993 | 24 000 | 0.04 s | 0.13 s | 0.04 s | **3.8 ms** |
| 8 000 | 27 783 | 192 000 | 0.34 s | 1.18 s | 0.37 s | **26 ms** |
| 27 000 | 89 373 | 648 000 | 1.24 s | 4.26 s | 1.20 s | **74 ms** |
| 64 000 | 206 763 | 1 536 000 | 2.79 s | 10.0 s | 3.09 s | **144 ms** |

The last column is the one that matters for live plotting: pushing a new solution vector into an open plot costs milliseconds, because it streams through the shared buffers instead of rebuilding anything. Setting up the tessellation is the one-off cost. `Gradient |> Derive` is the expensive filter — it evaluates your constitutive function at every tessellation vertex — and is worth applying downstream of a `CrinkleClip` if you only want to look at a cut.

## Breaking changes

v0.3.0 is a breaking release. The main renames:

| before | now |
| --- | --- |
| `MakiePlotter(dh, u)` | `FEData(dh, u)` |
| `solutionplot(p, field = :p)` | `solutionplot(ds, color = :p)` |
| `solutionplot(p, deformation_field = :u)` | `solutionplot(ds |> WarpByVector(:u))` |
| `solutionplot(p, field = :gradient, process = f)` | `solutionplot(ds |> Gradient(:u) |> Derive(f, output = :name), color = :name)` |
| `crinkle_clip(!)` | `CrinkleClip` filter |
| `uniform_refinement` | `Refine` |
| `for_discretization` | `FirstOrderRefinement` |
| `arrows` | `arrowplot` |
| `wireframe` | `meshplot` |

`FEData(dh, u)` copies `u`, so `update!` no longer mutates your solution vector. `transfer_solution`’s `process` keyword, `postprocess`, `x₁`/`x₂`/`x₃` and `l1`/`l2` are gone — use the derivation filters instead.

Adding your own cell type is now a single method, `reference_tessellation(::Type{<:AbstractRefShape})`; `Wedge` and `Pyramid` work out of the box, and there is a worked example for cohesive/interface elements in the docs.

## Links

- Docs: [Home · FerriteViz](https://ferrite-fem.github.io/FerriteViz.jl/dev/)
- Repo: [GitHub - Ferrite-FEM/FerriteViz.jl: Plot your Ferrite.jl data · GitHub](https://github.com/Ferrite-FEM/FerriteViz.jl)
- Changelog: [FerriteViz.jl/CHANGELOG.md at master · Ferrite-FEM/FerriteViz.jl · GitHub](https://github.com/Ferrite-FEM/FerriteViz.jl/blob/master/CHANGELOG.md)

Feedback, bug reports and feature requests very welcome — especially from anyone with history-dependent material models, since the quadrature point machinery is new and I’d like to know how it holds up on real problems.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [July 28, 2026, 4:14pm UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157/24 "2026-07-28T16:14:42Z")

</div>

3 posts were split to a new topic: [Possibly using GeoTables/Meshes for Ferrite’s visualizations?](https://discourse.julialang.org/t/possibly-using-geotables-meshes-for-ferrites-visualizations/138514)

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [August 3, 2026, 12:19pm UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157/25 "2026-08-03T12:19:54Z")

</div>

# Ferrite version 1.6.0

![heat_adaptivity-dark](https://global.discourse-cdn.com/julialang/original/3X/d/2/d28da93d9f9916059b349bf89fc9a9c38e9bfb01.webp)

_Refined mesh from [heat equation with adaptive mesh refinement](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/heat_adaptivity/)_

We have just released Ferrite version 1.6.0, the biggest feature release since 1.0.0. The full list of changes can be found in [CHANGELOG.md](https://github.com/Ferrite-FEM/Ferrite.jl/blob/master/CHANGELOG.md), but the main highlights are summarized below.

## Adaptive mesh refinement

The biggest feature of this release is adaptive mesh refinement (AMR) for quadrilateral and hexahedral grids, based on a `p4est`-style forest of octrees. This is a pure Julia implementation of the `p4est` algorithms and not just a wrapper around the C library. This means that everything down to the octree data structures is accessible, extensible, and debuggable from Julia. This feature has been under development for a long time. The pull request ([#780](https://github.com/Ferrite-FEM/Ferrite.jl/pull/780)) was opened almost exactly three years ago and the implementation has been presented at our yearly [FerriteCon](https://ferrite-fem.github.io/FerriteCon/) both in [2023](https://www.youtube.com/watch?v=T-p-wPiTdeA) and [2024](https://www.youtube.com/watch?v=FFAVNzOK_Xo). It is great to see it merged finally!

Note that the feature is marked experimental for now: the API may change in minor releases without following semantic versioning. To get started, see the new [AMR topic guide](https://ferrite-fem.github.io/Ferrite.jl/stable/topics/amr/), the tutorial on [Heat equation with adaptive mesh refinement](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/heat_adaptivity/), and the example [Linear elasticity with adaptive mesh refinement](https://ferrite-fem.github.io/Ferrite.jl/stable/gallery/elasticity_adaptivity/) in the code gallery. Feedback from early adopters is very welcome!

## Higher order elements

- New interpolations `Lagrange{RefTetrahedron, 3}`, `Lagrange{RefTetrahedron, 4}`, and `Lagrange{RefHexahedron, 3}`. Supporting these required teaching the dof distribution to handle multiple nodal dofs on faces shared between cells by taking the relative orientation of the face into account.
- New quadrature rule type `:polyquad` for `RefTetrahedron` supporting orders 1 to 10 (previously the maximum order was 5), with positive weights and points strictly inside the reference tetrahedron.

## Export to the VTKHDF file format

The new `VTKHDFGridFile` is the counterpart of `VTKGridFile` for the HDF5-based [VTKHDF file format](https://docs.vtk.org/en/latest/vtk_file_formats/vtkhdf_file_format/index.html), provided through a package extension that loads together with the new [VTKHDF.jl](https://github.com/Ferrite-FEM/VTKHDF.jl) package. It supports the same data functions as `VTKGridFile` (`write_solution`, `write_cell_data`, `write_projection`, …), but unlike the XML-based formats a whole simulation can be stored in a single file, with the grid written only once for time series on a fixed mesh.

## Multi-threaded assembly without grid coloring

`start_assemble(K, f; atomic = true)` returns an assembler that accumulates into `K` and `f` using atomic additions. This makes it safe to assemble from multiple concurrent tasks _without_ first partitioning the cells into independent sets (“grid coloring”), at the cost of some accumulation overhead. The [how-to on multi-threaded assembly](https://ferrite-fem.github.io/Ferrite.jl/stable/howto/threaded_assembly/) has been updated to show both approaches.

## New tutorials and documentation improvements

- New tutorial: [Darcy flow](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/darcy_flow/) using the H(div)-conforming Raviart-Thomas interpolations that were introduced in Ferrite 1.1.0.
- New tutorial: [Elastodynamics and modal analysis of a cantilever beam](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/elastodynamics/) (mass matrix assembly, generalized eigenvalue problem, Rayleigh damping, and Newmark time integration).
- Code blocks in the documentation now have line numbers, and individual lines can be selected and linked to, similar to code on GitHub, using [the new DocumenterCodeBlocks package](https://discourse.julialang.org/t/documentercodeblocks-jl-announcement/138552).
- The figures and animations for the tutorials and code gallery are now rendered programmatically from the generated vtk output files (instead of via print screen from within ParaView) to give them a consistent look.
- The overview page for the [tutorials](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/) and [code gallery](https://ferrite-fem.github.io/Ferrite.jl/stable/gallery/) has been made visually nicer.
- Other figures in the documentation have also been improved, especially for dark mode.

## FerriteCon 2026

Finally, a reminder that [FerriteCon 2026](https://ferrite-fem.github.io/FerriteCon/2026/), the fifth annual Ferrite user and developer conference, takes place on September 24 in Braunschweig, Germany, hosted by Technische Universität Braunschweig. Attendance is free, but registration is required (deadline September 18) and if you want to present something please submit a short abstract before August 28 (see the [conference page](https://ferrite-fem.github.io/FerriteCon/2026/) for details). Talks will also be live-streamed and recorded for those who cannot attend in person. We hope to see you there!

Thanks to everyone that contributed!

---

<div class="post-metadata">

**Author:** ![fredrikekre](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fredrikekre/32/1688_2.png) [@fredrikekre](https://discourse.julialang.org/u/fredrikekre)\
**Post date:** [September 7, 2026, 10:31am UTC](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157/26 "2026-09-07T10:31:13Z")

</div>

# Ferrite version 1.7.0

 ![stress_driven_homogenization-dark](https://global.discourse-cdn.com/julialang/original/3X/6/b/6b7fe67498411ac9f5b51e0b12a260acbae91a11.png)

_The von Mises stress in the RVE from the [stress-driven computational homogenization tutorial](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/stress_driven_homogenization/), where the macroscopic strain is an unknown algebraic variable._

We have just released Ferrite version 1.7.0. This release adds a new kind of unknown to the `DofHandler`, brings experimental GPU support, improves the support for blocked matrices, and makes some of the most common setup steps significantly faster. The full list of changes can be found in [CHANGELOG.md](https://github.com/Ferrite-FEM/Ferrite.jl/blob/master/CHANGELOG.md), but the main features are summarized below.

## Algebraic variables

One of the main new features in this release is the `AlgebraicVariable` type. This represents a mesh-free unknown that can be integrated together with the regular unknowns in the `DofHandler`. Some use cases are Lagrange multipliers for e.g. a mean value constraint, or a macroscopic stress or strain in computational homogenization. The value can be a scalar, a `Vec`, or a second or fourth order tensor. The coupling to the spatial fields is declared explicitly, so that the coupling blocks are included in the sparsity pattern and assembled alongside the regular element contributions. Previously, this type of unknown had to be handled outside of the `DofHandler` (or eliminated manually using `AffineConstraint`s).

There is a new [algebraic variables topic guide](https://ferrite-fem.github.io/Ferrite.jl/stable/topics/algebraic_variables/) where you can read more, and there are also two tutorials that make use of it: [Stress-driven computational homogenization](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/stress_driven_homogenization/) and [Stokes flow](https://ferrite-fem.github.io/Ferrite.jl/stable/tutorials/stokes-flow/).

## Experimental GPU support

This release adds experimental support for performing element assembly on CUDA GPUs. The feature is marked experimental because the interfaces may change without following semantic versioning. See the new [how-to on GPU assembly](https://ferrite-fem.github.io/Ferrite.jl/stable/howto/gpu_assembly/) for a walkthrough of assembling the heat equation on the GPU. The GPU integration builds on top of [KernelAbstractions.jl](https://github.com/JuliaGPU/KernelAbstractions.jl) so it will soon be extended to the AMDGPU, Metal, and oneAPI backends as well (see [this pull request](https://github.com/Ferrite-FEM/Ferrite.jl/pull/1496)).

## Better support for blocked matrices

The `BlockMatrix` integration (using [BlockArrays.jl](https://github.com/JuliaArrays/BlockArrays.jl)) has been improved and the features should now be on par with the regular sparse matrix types:

- `apply!`, `apply_zero!`, and condensation of affine constraints are now supported (previously constraints could only be applied to a blocked system with `apply_assemble!`)
- Assembly performance into a `BlockMatrix` has been drastically improved
- The `BlockAssembler` now supports atomic assembly

## Performance improvements

Several setup steps that can dominate the total time for large grids have been made significantly faster: creating a sparsity pattern and allocating a matrix from it (typically 3-8x, and 10-25x with `interface_coupling`, at roughly half the peak memory use, and now multithreaded), `create_coloring` (3-10x serial, and another 2-3x with 8 threads), and `ExclusiveTopology` construction and queries.

## FerriteCon 2026

Finally, a reminder that [FerriteCon 2026](https://ferrite-fem.github.io/FerriteCon/2026/), the fifth annual Ferrite user and developer conference, takes place on September 24 in Braunschweig, Germany, hosted by Technische Universität Braunschweig. Attendance is free, but registration is required (deadline September 18), see the [conference page](https://ferrite-fem.github.io/FerriteCon/2026/) for details. Talks will also be live-streamed and recorded for those who cannot attend in person. We hope to see you there!

Thanks to everyone that contributed!

[Previous page](https://discourse.julialang.org/t/ferrite-jl-release-announcements/93157.md?page=1)
