Upgrading from 0.4
PETSc.jl 0.5 is a breaking release. Most of the high-level API has new names, the low-level LibPETSc functions return their outputs, and the package needs Julia 1.12 and PETSc 3.25. This page is the order in which to update code written for 0.4. Every change is listed in the Release notes, and every renamed function in the rename table at the end of Naming Conventions.
1. Requirements
- Julia 1.12 or newer. On an older Julia, the package manager keeps installing 0.4.
- PETSc 3.25.
PETSc_jll3.25 is installed automatically. A library configured withPETSc.set_library!must be a PETSc 3.25 build;PETSc.check_wrappers_version()warns when it is not. - One
PetscIntwidth per process.PETSc.petsclibsholds four libraries (Float64,Float32,ComplexF64,ComplexF32) withInt64indices. Code that indexespetsclibs[5:8], or asksPETSc.getlibfor anInt32library, fails. To useInt32indices, callPETSc.set_petscint!(Int32)once and restart Julia (see Installation).
2. Run your code and fix the warnings
About a hundred functions were renamed. The old names still work until 0.6 and print a warning the first time each call site runs, for example
┌ Warning: getcorners is deprecated, use cornersThese warnings appear without --depwarn=yes. Run your code or its test suite once, and replace every name a warning reports.
3. Qualify names that are no longer exported
using PETSc now brings in only the types you construct:
LibPETSc
DMDA, DMStag, DMPlex
PetscVec, PetscMat, PetscOptions
KSP, SNES, TS
petsclibsEverything else, including functions 0.4 exported such as set_library!, library_info and audit_petsc_file, fails with an UndefVarError. Write PETSc.set_library!(…), or import the names you use: using PETSc: set_library!, initialize, finalize.
4. Changes that print no warning
These changes have no deprecation warning, because the name stayed the same or dispatch cannot tell the old call from the new one. Check your code for each of them.
Callback setters take the callback first. 0.4 accepted both orders; 0.5 accepts only the callback-first one, which is the one do syntax needs. This applies to set_function!, set_snes_jacobian!, set_convergence_test!, set_compute_rhs!, set_compute_operators!, set_rhs_function!, set_rhs_jacobian!, set_ifunction!, set_ijacobian! and set_monitor!. add_coarsen_hook! takes C function pointers, which do can't supply, so it takes the DM first: add_coarsen_hook!(dm, hook).
# 0.4
PETSc.setfunction!(snes, f!, r)
# 0.5
PETSc.set_function!(f!, snes, r)
PETSc.set_function!(snes, r) do fx, snes, x
# ...
endType names are Symbols. type_name (0.4: gettype or type) returns a Symbol, or nothing when PETSc has not set a type yet. A comparison with a String is now false without any error.
# 0.4
PETSc.gettype(snes) == "newtonls"
# 0.5
PETSc.type_name(snes) === :newtonlsDM queries return the DM's own dimension. 0.4 padded every answer to three dimensions. In 0.5, corners, ghost_corners, local_indices, global_indices, info and size return values of the DM's dimension: for a 2D DMDA, corners(da).lower is a CartesianIndex{2} and corners(da).size an NTuple{2,Int}, so corners(da).size[3] throws a BoundsError. info renames dof to ndofs and mpi_proc_size to procs, and drops s, which duplicated stencil_width.
DMs have their own types. DMDA, DMStag and DMPlex are concrete types below LibPETSc.AbstractPetscDM. A method annotated ::PetscDM no longer matches them; annotate with LibPETSc.AbstractPetscDM or with the concrete type. A DM that comes back from PETSc without a known type (for example PETSc.dm(ksp)) can be turned into the typed one with PETSc.narrow(dm).
Errors have specific types. Invalid arguments raise ArgumentError or DimensionMismatch where 0.4 failed an @assert, and creating a PETSc object with PetscVec, PetscMat, KSP, SNES, TS or a DM constructor on a library that is not initialized raises PETSc.PetscNotInitialized. Code that caught AssertionError must catch these instead.
Handles you do not own. Readers such as PETSc.dm(ksp), PETSc.solution(snes) and PETSc.local_coordinates(dm) return a handle that belongs to the object they were called on. destroy! on such a handle does nothing (PETSc.owns tells you which is which). Destroying it was never correct, and code that did so should stop.
Reordered arguments. Functions that write into a vector take that vector first, and the DM second:
# 0.4
PETSc.dm_global_to_local!(gvec, lvec, dm)
PETSc.dm_local_to_global!(lvec, gvec, dm)
# 0.5
PETSc.global_to_local!(lvec, dm, gvec)
PETSc.local_to_global!(gvec, dm, lvec)The 0.4 names still work and warn, but only when called directly: a 0.4-order call passed through invoke, or through a variable holding the function, is not translated. The same applies to project_function! and project_field!.
5. Low-level LibPETSc code
The LibPETSc wrappers are regenerated for PETSc 3.25 and follow a new calling convention:
Outputs are returned. A C output argument is no longer passed in as a
Ref:# 0.4 s = Ref{LibPETSc.PetscSection}() LibPETSc.PetscSectionCreate(petsclib, comm, s) section = s[] # 0.5 section = LibPETSc.PetscSectionCreate(petsclib, comm)Several outputs come back as a tuple, for example
nroots, nleaves, ilocal, iremote = LibPETSc.PetscSFGetGraph(petsclib, sf).Type names are
Strings.LibPETSc.PCSetType(petsclib, pc, "ilu")works directly, and the registered names are constants such asLibPETSc.PCILUandLibPETSc.KSPGMRES.XGetTypefunctions return aString.Renamed handle types.
PetscKSPandPetscSNESare nowKSPandSNES(AbstractPetscKSPandAbstractPetscSNESareAbstractKSPandAbstractSNES). The old names still work until 0.6.Functions PETSc defines only in its headers are gone. About 95 macros and inline functions with no symbol in the library (
VecSetValue,MatSetValue,PetscStrcmp,PetscTime, …) are no longer wrapped. Use the array versions (VecSetValues,MatSetValues) or plain Julia.PetscBoolis one byte, as it is in PETSc since 3.24. Code that usesLibPETSc.PetscBoolneeds no change. Code that writes a PETSc boolean asCintorInt32in its ownccallorunsafe_store!must useLibPETSc.PetscBoolinstead.
The Release notes list the remaining changes, and wrapping/DEVIATIONS.md lists every category of changed wrapper.
6. Within 0.5: the 0.5.4 spellings
0.5.4 moves options to keywords and puts arguments in the same order across constructors. Every old form still works until 0.6 and warns, so step 2 finds them; this is the list to update by hand.
| Up to 0.5.3 | From 0.5.4 |
|---|---|
set_values!(A, rows, cols, vals, ADD_VALUES) | set_values!(A, rows, cols, vals; mode = ADD_VALUES) |
ghost_update!(v, ADD_VALUES, SCATTER_REVERSE) | ghost_update!(v; mode = ADD_VALUES, scatter = SCATTER_REVERSE) |
global_to_local!(l, dm, g, ADD_VALUES), also local_to_global!, local_to_local!, project_function!, project_field! | …; mode = ADD_VALUES |
zero_rows!(A, rows, 1.0) | zero_rows!(A, rows; diag = 1.0) |
DMStag(petsclib, comm, bnd, dims, dof, 1, :box), the same for DMDA | DMStag(petsclib, comm, bnd, dims, dof; stencil_width = 1, stencil_type = :box); both default to these values |
setfromoptions, dmsetup, dmsetfromoptions on a DM constructor | set_from_options, setup |
add_coarsen_hook!(hook, dm) | add_coarsen_hook!(dm, hook) |
distribute!(dm) | distribute(dm): it returns a new DM and leaves dm as it is |
VecPtr(petsclib, ptr, false), also MatPtr and PetscVec(petsclib, ptr, own) | PetscVec(petsclib, ptr; own = false), PetscMat(petsclib, ptr; own = false); own defaults to false |
PetscMat(petsclib, rowptr, colval, nzval; comm) | PetscMat(petsclib, comm, rowptr, colval, nzval) |
MatShell(petsclib, f, comm, m, n, M, N) | MatShell(f, petsclib, comm, m, n; global_rows = M, global_cols = N), or MatShell(petsclib, comm, m, n) do y, x … end |
0.5.4 also adds PetscVec(petsclib, comm, n; local_size) for a vector distributed over comm.
7. Within 0.5: the 0.5.5 deprecations
0.5.5 is the last release before 0.6. Everything below still works and warns once, and is removed in 0.6, so step 2 finds it; this is the list to update by hand.
| Up to 0.5.4 | From 0.5.5 |
|---|---|
VecPtr(petsclib, ptr; own), MatPtr(petsclib, ptr; own) | PetscVec(petsclib, ptr; own), PetscMat(petsclib, ptr; own) (new) |
A SNES or TS callback that takes a trailing context argument; user_ctx(snes), user_ctx(ts), set_user_ctx! | A closure carries the context: set_rhs_function!(ts) do F, ts, t, u … end reads it from the enclosing scope |
local_arrays(…) with restore_local_arrays! | with_local_arrays!(f!, g_fx, l_x) |
local_coordinate_array(dm) | with_local_coordinate_array(f, dm); the array is handed back when f returns or throws |
@residual_fn f0 Nf, @jacobian_fn, @bd_fn, @simple_fn | @residual_fn petsclib f0 Nf: the library comes first, as a top-level const |
vtk_merge_tensor, create_split_boundary_labels! | Copies in examples/dmplex/vtk_tensor.jl and examples/dmplex/ex69.jl |
isapprox(v, w) on two PetscVecs | Compares entry by entry now and norm-wise from 0.6, ‖v − w‖ ≤ max(atol, rtol·max(‖v‖, ‖w‖)); say which you mean with all(isapprox.(v[:], w[:])) or norm(v - w) ≤ … |
0.5.5 also adds x + y, x - y, α * x, dot, axpy! and copy on PetscVecs and PetscMats, MatShell operations (mult_transpose, diagonal, mult_add) and AMD GPU support.
What changes in 0.6 without a warning
These can't warn without firing on correct code, so check them now. The release notes give the detail under "Coming in v0.6".
- Options are applied once, at the first
setup!orsolve!of a KSP, SNES or TS. Passoptions_at = :first_solvetoday to get that behavior. - Solves throw on divergence. Pass
check = truetosolve!today. w = 2 .* xreturns aPetscVec, not aVector, andsize(v)becomes(n,).2 * xalready returns aPetscVec.copy_disc!(dst, src)takes the destination first.PetscVec <: AbstractVectorandPetscMat <: AbstractMatrix, with==comparing values andhashthrowing.
8. Looking up a name
- An old high-level name: the rename table at the end of Naming Conventions.
- A PETSc C function: the C to Julia name index.
- Why a name is what it is: the rules in Naming Conventions.