Release notes
v0.5.5
The last release before 0.6, which removes every shim and flips several defaults. Run your code on 0.5.5 with warnings on and fix what they report; "Coming in v0.6" lists the changes that print no warning.
Coming in v0.6
These change what working code does or remove a name. The ones marked "warns" print a warning in this release; the others can't warn without firing on correct code.
- KSP, SNES and TS apply their constructor options once, at the first
setup!orsolve!, asoptions_at = :first_solvedoes now. SNES no longer re-reads the options at every solve, which can reset a preconditioner configured in code. solve!throws aConvergenceErrorwhen a KSP, SNES or TS solve does not converge, instead of warning (warns since 0.5.3;check = truethrows now).- Every name, method and keyword form that warns in 0.5.x is removed.
VecPtrandMatPtrgo (warns). Wrap a raw handle withPetscVec(petsclib, ptr; own)orPetscMat(petsclib, ptr; own).isapprox(v, w)on two PetscVecs compares norms, ‖v − w‖ ≤ max(atol, rtol·max(‖v‖, ‖w‖)), as for Julia arrays, instead of entry by entry (warns).- An out-of-place broadcast on a PetscVec,
w = 2 .* x, returns a PetscVec ofx's layout instead of aVector, and works on a distributed vector. The caller destroys it.2 * xandx + yalready return a PetscVec. size(v)on a PetscVec returns a tuple(n,)ofIntandlength(v)anInt, as for any vector.size(v) == nbecomes false, so check code that usessize(v)as a number.copy_disc!(dst, src)takes the destination first, ascopyto!does. Both arguments are DMs, so a call in the old order runs and copies the wrong way.set_convergence_test!passes the norms to the callback asPetscReal, notFloat64. This matters only for a Float32 library with a callback whose arguments are annotatedFloat64.star_fd_coloringreturns its index arrays asVector{Int}, notVector{Int32}.- The
…Fncallback types (SNESSetFunctionFn,TSSetRHSFunctionFn, …) are no longer public. PetscVec <: AbstractVectorandPetscMat <: AbstractMatrix. Element-by-element fallbacks throw by default, so a generic method that would make one C call per entry fails instead.==on two PetscVecs compares values (VecEqual, collective) as it already does on PetscMats, andhashon either throws.
Added
PetscMat(petsclib, ptr; own = false)wraps a rawMathandle, asPetscVec(petsclib, ptr; own)does for aVec.PetscVechascopy,dot,axpy!,axpby!,rmul!,lmul!and the operatorsx + y,x - y,-x,α * xandx / α, throughVecCopy,VecDot,VecAXPY,VecAXPBY,VecScaleandVecWAXPY. An assembledPetscMathascopy,A + B,A - B,-Aandα * A, throughMatDuplicate,MatAXPYandMatScale. All are collective and work on distributed objects;copyand the operators return a new Vec or Mat, which on more than one rank needsdestroy!like any other.dot(x, y)conjugatesx, as for Julia arrays.MatShelltakes the operationsmult_transpose(y, x),diagonal(d)andmult_add(z, x, y)as keywords, sotranspose(A) * x,A' * x,pc_type = jacobiandMatMultAddwork on a shell.with_local_arrays!(f!, g_fx, l_x)callsf!(fx, lx)with the local arrays of the two Vecs, on the device when a GPU extension is loaded, and hands them back afterwards, also whenf!throws.with_local_coordinate_array(f, dm)callsf(coord)with the local coordinates of aDMDAorDMStag, addressed with global indices, and hands the array back whenfreturns or throws.- AMD GPUs: with AMDGPU.jl loaded and a PETSc built with HIP,
with_local_array!andwith_local_arrays!returnROCArrays for Vecs in HIP memory (PETScAMDGPUExt).with_local_arrays!also handles one Vec on the host and the other on the device, as on coarser multigrid levels.with_field_views!on a DMStag with device vectors gives views of device arrays for kernels; broadcast overparent(view), sinceOffsetArraybroadcasts on the host.
Deprecated
VecPtr(petsclib, ptr; own)andMatPtr(…)warn and go in v0.6: usePetscVec(petsclib, ptr; own)andPetscMat(petsclib, ptr; own), which give the same wrappers.isapprox(v, w)on two PetscVecs warns once that it compares norms from v0.6.user_ctx,set_user_ctx!and the callback forms with a trailing context warn and go in v0.6. A closure carries the context:set_rhs_function!(ts) do F, ts, t, u … endreads what it needs from the enclosing scope, and every callback then has one calling form.vtk_merge_tensorandcreate_split_boundary_labels!warn and go in v0.6. Both fit particular examples rather than PETSc: copies are inexamples/dmplex/vtk_tensor.jlandexamples/dmplex/ex69.jl.local_arraysandrestore_local_arrays!warn: usewith_local_arrays!. An exception between the two calls left both Vecs checked out.local_coordinate_array(dm)warns: usewith_local_coordinate_array(f, dm). It now returns a copy. It used to leave the coordinate vector checked out until the garbage collector freed the array, and if the DM was destroyed first, that late hand-back crashed Julia.@simple_fn,@residual_fn,@jacobian_fnand@bd_fntake the library first,@residual_fn(petsclib, f0, Nf), and use itsPetscInt,PetscRealandPetscScalarfor the C signature. The library value or its type both work; it is evaluated when the macro expands, so it must be a global defined before the call. Without the library, the macros takePetscInt,PetscScalarandPetscRealfrom the calling module's globals as before, and warn. That form needed those three consts and allowed only one library per module.
Behaviour changes
star_fd_coloringthrows anArgumentErrorfor a DMDA that is not 2-D with a STAR stencil, where a 1-D or 3-D one gave aMethodErrorand a BOX one a coloring that leaves out entries.
Fixed
- CUDA:
with_local_arrays!with one Vec on the host and the other on the device threw aMethodError, and arrays went back to PETSc before CUDA.jl's kernels on them had finished unless one was a host copy. Both now work as with AMDGPU: the host Vec is copied to the device and back, and the device is synchronized before every hand-back. Not tested on an NVIDIA GPU. examples/dmda/ex19.jlruns on the GPU again, with CUDA or HIP (const gpu = :cudaor:hip). Its GPU branch passed a raw pointer toMatSetValuesCOO, which takes aVector, and its residual got a host and a device array on coarser multigrid levels.LibPETSc.PetscGetArgs,PetscGetArguments,PetscStrToArray,PetscFunctionListGetandPetscViewerBinaryReadStringArrayreturn aVector{String}. They passed onechar **where PETSc takes achar ***, so they returned a wrong string or crashed.PetscStrArrayallocpy,PetscStrArrayDestroy,PetscStrNArrayallocpy,PetscStrNArrayDestroyandPetscOptionsInsertstill take achar ***orchar **as one string and are not usable.audit_fileno longer reportsPetscVec(petsclib, ptr; own = false)orPetscMat(…; own = false)as a leak: a borrowed handle has nothing to destroy.
v0.5.4
Deprecated
- Insert modes, scatter modes and
diagare keywords,mode,scatteranddiag:set_values!(A, rows, cols, vals; mode = ADD_VALUES),ghost_update!(v; mode = ADD_VALUES, scatter = SCATTER_REVERSE),global_to_local!(l, dm, g; mode),zero_rows!(A, rows; diag = 2). This coversghost_update!,ghost_update_begin!,ghost_update_end!,local_to_global!,global_to_local!,local_to_local!,set_values!,project_function!,project_field!,zero_rows!andzero_rows_local!. The positional forms still work and warn once; they go in v0.6.project_function!also takesctxsas a keyword, and both projections default tomode = INSERT_VALUES. DMDAandDMStagtake the stencil width and type as keywords with defaults,DMStag(petsclib, comm, boundary, dims, dof; stencil_width = 1, stencil_type = :box), where they were positional. The DM constructors'setfromoptionsanddmsetupkeywords areset_from_optionsandsetup. The old forms still work and warn once; they go in v0.6.add_coarsen_hook!takes the DM first,add_coarsen_hook!(dm, coarsenhook, restricthook), asset_residual!does. Its hooks are C function pointers, whichdosyntax can't supply, so putting them first bought nothing. The hook-first order still works and warns.distribute!isdistribute: it returns a new distributed DM and leaves its argument unchanged, so the name has no!.distribute!andplexdistribute!still work and warn.ownis a keyword with defaultfalsewhen wrapping a raw handle:VecPtr(petsclib, ptr; own = true),MatPtr(petsclib, ptr; own)andPetscVec(petsclib, ptr; own), as innarrow(dm; own). The positionalownstill works and warns.- The CSR constructor takes the communicator second,
PetscMat(petsclib, comm, rowptr, colval, nzval), as every other constructor does; thecommkeyword still works and warns. Withoutcommthe matrix is onMPI.COMM_SELF, as before. MatShelltakes the operator first,MatShell(f, petsclib, comm, local_rows, local_cols; global_rows, global_cols), soMatShell(petsclib, comm, m, n) do y, x … endworks. The global sizes are keywords. The library-first order still works and warns.
Behaviour changes
- A
LibPETSccall whose arguments match no generated method, such as anIntwhere the library takes its scalar type, throws aMethodErrornaming the argument types, instead of anErrorExceptionwith the text "no generated method for these argument types". library_info()prints as theNamedTupleit returns. The report it printed came from ashowmethod that also changed how any otherNamedTuplewith the same five field names printed.PETSc.petsclibslists the libraries loaded in the session.
Added
- The handle types are public API, with docstrings: the abstract types to annotate with (
AbstractPetscVec,AbstractPetscMat,AbstractPetscDM,AbstractKSP,AbstractPC,AbstractSNES,AbstractTS,AbstractPetscOptions,AbstractIS,AbstractAO,AbstractPF,AbstractTao) and the handlesPetscDM,PC,IS,AO,PFandTao, all reachable asPETSc.X.PETSc.realtype(petsclib)gives the library's real type. - A
PetscErrorprints the C function the failing call went to and PETSc's message for it, for examplePetscError(56) from VecSetSizes: No support for this operation for this object type. Cannot change/reset vector sizes to 4 local 4 global after previously setting them to 3 local 3 global, where it printedPetscError(56). The fieldsfuncandmessagehold the two;PetscError(code)still works. DMStag(dm, dof)takesprefix, and everyDMDA,DMStag,DMPlex,KSP,SNESandTSconstructor takes anyAbstractStringasprefix, aSubStringincluded.PetscVec(petsclib, comm, n; local_size = PETSC_DECIDE)creates a vector distributed overcomm, by global lengthnor bylocal_sizewithn = PETSC_DETERMINE.
Fixed
- A dense matrix made with
PetscMat(petsclib, A::Matrix)orPetscMat(petsclib, m, n; type = :dense)could lose its storage while a KSP still used it: once the Julia handle was collected, the array went with it, and the next solve read freed memory (a wrong answer or a PETSc zero-pivot error). The array now lives as long as the PETSc matrix, as it already did for CSR matrices and vectors on Julia arrays.type = :denselets PETSc allocate the storage. - A
DMDA,DMStagorDMPlexconstructor, orfe_create_default, that threw inside PETSc (for example onda_refine = "abc") left its options pushed on PETSc's options stack. Every object created afterwards read them, and the options could no longer be destroyed. The options are now popped whether or not the call throws. PETSc.scalartypeandPETSc.inttypeare now the same functions asLibPETSc.scalartypeandLibPETSc.inttype. They were two separate copies, so a method added to one was missing from the other.mul!,ksp \ b,ldiv!andsolve!(x, ksp, b)took onlyPetscVec, so a borrowedVecPtrgave aMethodError(A * xwith aVecPtrfailed inside). They take any vector handle.- A 2D or 3D
DMDAbuilt without a stencil type threw aMethodError; it now defaults to:box, asDMStagdoes. DMStag(dm, dof; dmsetfromoptions = false)passed-dmsetfromoptionsto PETSc as an option and still applied the options; the keyword is honoured, with a deprecation warning pointing toset_from_options.
v0.5.3
Behaviour changes
- A KSP, SNES or TS solve that stops without converging now prints a warning, once per call site, instead of returning in silence: PETSc leaves the last iterate in the solution vector, and nothing else said the solve had failed. From v0.6 such a solve should throw a
ConvergenceError. Passcheck = falsetosolve!to keep handlingconverged_reasonyourself and silence the warning, orcheck = trueto throw now.
Fixed
- Pushing a
PetscOptionsthat was already on PETSc's options stack broke the stack: the nextpop!failed, and PETSc's global options were lost for the rest of the run.push!now throws anArgumentErrorinstead. - An MPI run started against a stale precompile cache (after an update, or a change to a
deved PETSc.jl) could hang for good at 0% CPU. The rank that precompiled PETSc calledMPI.Initinside the precompile process, which then waited for peers that never came. PETSc no longer initializes MPI while it loads;initializedoes it, as before. A' * x,transpose(A) * xandmul!(y, A', x)on a PETSc matrix threw aMethodError: the transposed products existed but could not be reached. They now runMatMultHermitianTransposeandMatMultTranspose, without forming the transpose.- On a
PetscVecmade on a Julia array (PetscVec(petsclib, x)), every norm type after the first came back as 0:norm(v)followed bynorm(v, LibPETSc.NORM_1)gave 5 and then 0. PETSc saw the other norms as already cached, because such a vector starts in the same object state as PETSc's empty norm cache. The vector is now moved past that state when it is created. isapprox(v, w; rtol = 1e-8)on twoPetscVecs threw aMethodError;atol,rtolandnansnow apply to each entry.DMDAandDMStagwith more than three dimensions failed with anUndefVarError; they throw anArgumentErrorsaying a DM has 1 to 3 dimensions.PetscVec(petsclib, comm, x)with anxof the wrong element type throws anArgumentErrornaming both types, asPetscVec(petsclib, x)does, instead of aMethodErrorfrom the generated layer.copyto!(A, S::SparseMatrixCSC)has a docstring saying howSis placed (from the first row the rank owns; in parallel, the rank's diagonal block), and throws aDimensionMismatchwhenSdoes not fit.LibPETSc.DMCreateFieldDecompositionreturned the field names as one garbled string: it passed PETSc'schar ***as achar **. It now returns aVector{String}(for a DMStag Stokes layout["face", "element"], the names PCFIELDSPLIT uses as option prefixes) and frees the names and the array.LibPETSc.DMCreateDomainDecompositionleaked its subdomain names; they are freed too.
Added
- The manual page "Direct solvers" says which of the direct solvers in
PETSc_jllgive the right answer, serially and on several ranks, andscripts/direct_solvers.jlchecks an installation against it. PETSc's default LU doesn't pivot and SuperLUDIST is wrong on one saddle-point test; both report success. MUMPS on more than one rank needs MUMPSjll 5.9.5 or later on Linux. tolerancesandset_tolerances!on aKSP(rtol,atol,divtol,max_it) and aSNES(atol,rtol,stol,max_it,max_funcs), asTShad them. The names are the options' without their prefix, soset_tolerances!(ksp; max_it = 200)does what-ksp_max_it 200does.set_from_options!also takes aPC, matrix or vector;options_prefixandset_options_prefix!also take a DM, matrix or vector;commalso takes aPCor an index set; andinterpolate(ts, t)returns the interpolated solution in a new vector.examples/dmstag/dmstag_stokes.jland the manual page "Stokes flow on a DMStag": 2D incompressible Stokes flow around a stiff sinker, with each equation written as a residual and turned into a matrix row by ForwardDiff, free-slip walls, and a Schur-complement fieldsplit whose velocity block is a geometric multigrid V-cycle set up in aset_post_setup!hook. FGMRES takes 12 iterations at uniform viscosity and about 30 at a contrast of 10⁴, flat from 32² to 128².with_destroy(f)destroys a group of objects when its block ends, also after an exception: objects registered withtrack!(list, obj)are destroyed in reverse order, the same on every rank. On more than one process nothing else frees them, and every rank must destroy the same objects in the same order.untrack!takes out an object that should outlive the block, and a borrowed handle is never tracked.set_post_setup!(f!, pc)runsf!(pc)at the end of every preconditioner setup. It is the place to configure the solvers of a:fieldsplit's splits, which exist only once the preconditioner is set up, for example a multigrid on one split with interpolation operators built in Julia.set_pre_solve!(f!, ksp)runsf!(ksp, b, x)at the start of every solve. Both keep the closure with the PETSc object, and an exception thrown inside comes out of thesolve!that ran it.ConvergenceErrorand acheckkeyword onsolve!(KSP, SNES, TS) andstep!: withcheck = truea solve that stops without converging throws aConvergenceErrorcarrying the solver, its converged reason, the iteration count and, for a SNES, the last residual norm. Its message says in words why the solver stopped and which options show more. A TS step that fails whileerrorifstepfailedis set (the default) throws aConvergenceErrorwithcheck = true, and thePetscErrorit threw before otherwise.- An
options_atkeyword on theKSP,SNESandTSconstructors says when their options are applied::construction,:each_solveor:first_solve(once, at the firstsetup!orsolve!, after the DM and callbacks are attached). The defaults keep each type's behaviour:KSPapplies them at construction,SNESandTSat every solve, where they override a preconditioner set in code.with_options(f, ksp)(orsnes,ts, or aPetscOptions) runsfwith those options pushed and returns its result.setup!works on aKSPand aSNES. set_values!(both 0-based forms),ksp \ b, the CSRPetscMat(petsclib, rowptr, colval, nzval)constructor anddof_slotaccept any vector or integer type: other element types, views, ranges and offset arrays. Arrays already of the library's types still go to PETSc without a copy; anything else is copied once.ksp \ breturnsxwith the axes ofb.norm(v, p)forp= 1, 2 andInf, andnorm(A, 2)(Frobenius), beside theNormTypemethods;opnorm(A, 1)andopnorm(A, Inf)for the induced matrix norms.size(v, d),size(A, d),axes(A)andaxes(A, d)for any PETSc vector or matrix, withsize(_, d) == 1beyond the last dimension as for a Julia array;ndimson a matrix no longer calls into PETSc.
v0.5.2
0.5.2 is what a staggered-grid solver needs from PETSc.jl: DMStag gets locations keyed by axis, stencils built from 1-based indices, assembly and halo exchange, and field views that hand a callback concretely typed arrays. TS gets what a long run needs, and Vec and Mat get the Base verbs that were missing. The rest is leaks closed in the generated layer and two performance traps, one of which made a 4-rank DMStag solve 25 times slower. Working code is most likely to notice the three behaviour changes below; the rest is additive.
Behaviour changes
- When several MPI ranks share a node,
initializesets Julia's BLAS pool to one thread, unless-blas_num_threads,OPENBLAS_NUM_THREADSorOMP_NUM_THREADSsays otherwise. Each rank otherwise ran a pool of busy-waiting threads, which made a 4-rank DMStag Stokes solve 25× slower. Serial runs and one rank per node are unaffected. solution(ksp),solution(ts),local_coordinates(dm)and thevatol/vrtoloftolerances(ts)return a borrowedPetscVec, assolution(snes)already did, instead of aVecPtr. Both areAbstractPetscVecs with the same ownership, so only code that checks forVecPtrby type notices.LibPETScrelease functions that free a C array of handles (VecDestroyVecs,MatDestroyMatrices,DMPlexRestoreConeRecursive, …) no longer accept a Julia array of raw handles, which PETSc would have freed as its own memory. They take the pointer PETSc returned;MatDestroySubMatrices,MatDestroyMatrices,VecNestRestoreSubVecsReadand the two subdomain destroyers also take the vector the matching wrapper returned.
Fixed
with_local_array!spent 23 allocations per call and did not infer its return type: it queried every vector'sPetscMemTypewith a checkout of its own before checking the vectors out for real, andmemtype_backenddispatched on aValbuilt from that run-time value. Host memory, the common case, now answers before the dispatch and the extra query is gone, so a one-vector checkout costs 2 allocations and infers.with_field_views!had the same fault plus aread/writevariable that changed type, and goes from 24 allocations to 8. A SNES solve whose callbacks check arrays out drops from 210 allocations to 47. Device memory dispatches as before, so the CUDA extension is unaffected.v[i] = aon aPetscVecandv[i]built their one-element index vector twice over.v[i] = anow allocates nothing andv[i]two.- Out-of-place broadcasting over a
PetscVec,w = 2 .* x, read one entry at a time throughVecGetValues, which cost 4003 allocations at 10 000 entries and failed on a distributed vector with a raw PETSc error. It runs on the local arrays now, at about 5 allocations whatever the length, and still gives aVector. A distributed vector throws anArgumentError, since aVectorof the whole vector only means something where one rank holds all of it. - Broadcasting into a
PetscVec(y .= 2 .* x, a typicalMatShellbody) read and wrote the vectors one entry at a time, throughVecGetValuesandVecSetValues: at 10 000 entries aMatShellproduct took 139 000 allocations and was 500× slower than the same loop on the local arrays. The vectors now take part as their local arrays, at a fixed cost of about 10 allocations. On several ranks the broadcast runs over the entries each rank owns. LibPETSc.ISColoringGetISwithPETSC_OWN_POINTERreturned the index sets as borrowed, so they and the C array holding them leaked. The index sets are now owned by the caller and the array is freed.ISColoringRestoreISaccepts the vectorISColoringGetISreturns.LibPETSc.DMCreateFieldISleaked the field names and both C arrays.- The TS and SNES manual pages still described the 0.5.0 callback rules (return an error code, exceptions become a
PetscError). - 14
LibPETScfunctions that return a vector of new handles leaked the C array PETSc allocated for them:DMCreateDomainDecomposition,DMCreateFieldDecomposition,DMCreateSuperDM,DMCreateSectionSuperDM,MatSubdomainsCreateCoalesce,PCASMCreateSubdomains,PCASMCreateSubdomains2D,PCGASMCreateSubdomains,PCGASMCreateSubdomains2D,PCGASMGetSubdomains,PCGetCoarseOperators,PCGetInterpolations,PetscQuadratureComputePermutationsandVecConcatenate. The array is now freed once the handles are copied. LibPETSc.MatCreateSubMatricesandMatCreateSubMatricesMPIdid not work withMAT_REUSE_MATRIX, andMatDestroySubMatricescould not take their result. Pass the returned vector back to either.LibPETSc.VecNestRestoreSubVecsReadaccepts the vectorVecNestGetSubVecsReadreturns; before, it only took a raw pointer that no wrapper handed out, so the read lock could not be released.LibPETSc.PCASMDestroySubdomainsandPCGASMDestroySubdomainsaccept the vectors the subdomain creators return.- On an Int32 PETSc build (the
PetscInt = "Int32"preference),LibPETSc.DMStagStencil,MatStenciland the other C structs hadInt64fields, so PETSc read them wrong. They now take the integer width of the loaded library, and the two stencil constructors convert their indices to it. LibPETSc.DMStagRestoreProductCoordinateArraysReadrestored the arrays through the writable restore, which does not match the read-only get.- The
KSPandSNESdocstrings did not say when the options given to the constructor are applied: once at construction forKSP, at everysolve!forSNES(andTS). -blas_num_threadshad no effect. Every PETScjll build calls BLAS through libblastrampoline, so PETSc's BLAS runs in Julia's OpenBLAS pool, which PETSc cannot size.initializenow forwards the option to `LinearAlgebra.BLAS.setnum_threads`.initialize(petsclib; options)appended-no_signal_handlerto the caller'soptionsvector.- On Windows, the
optionsandlog_viewgiven toinitializenever reached PETSc: they went throughENV["PETSC_OPTIONS"], which PETSc there reads from its own copy of the environment. They are now PETSc's command line (LibPETSc.PetscInitializetakes aVector{String}), and still override aPETSC_OPTIONSset before Julia starts.
Added
- A performance contract:
test/core/performance.jlchecks that 29 calls meant for a loop infer a concrete return type and allocate the same amount at two problem sizes, anddocs/src/man/performance.mdsays how to keep that cost (array blocks, BLAS threads per rank, concretely typed objects, precompiling beforempiexec,-log_view). copyto!(dst, src)between twoPetscVecs.- Matrix methods:
fill!(A, 0),zero_rows!andzero_rows_local!for Dirichlet rows,set_option!,diagonal!(d, A)andisassembled. destroy!onIS,AO,PFandTaohandles.LibPETSc.PetscFree, for memory PETSc hands to the caller.- Long
TSruns:set_pre_step!(f!, ts)andset_post_step!(f!, ts)hooks that may change the run,set_max_snes_failures!,set_max_step_rejections!,set_error_if_step_fails!,set_step_number!for restarts, andequation_type/set_equation_type!. set_solution!(snes, x), as onTS.LibPETSc.PETSC_UNLIMITEDandLibPETSc.PETSC_CURRENT, which PETSc's manual pages ask for.- DMStag locations by axis:
vertex_location(dm),edge_location(dm, a, b),face_location(dm, axis)andelement_location(dm), which mean the same in 2D and 3D, unlikeDMSTAG_DOWN. stencil(dm, loc, I; dof = 0)builds aDMStagStencilfrom a 1-based element index, allocation free.- Assembly with DMStag stencils:
set_values!(J, dm, rows, cols, vals, mode),set_values!(v, dm, positions, vals, mode)andzero_rows_local!(J, dm, rows, diag). They take anyAbstractVector, and pass aVectoror a prefix viewview(buf, 1:n)of one without a copy. LibPETSc.IS(dm, loc => dof, ...), the index set of whole DMStag fields, forset_fieldsplit_is!.length(is)on anIS: its global size, aslengthof aPetscVec.on_lower_side(loc, axis): whether a DMStag location sits on the lower side of its element alongaxis, so on the axes where it has one more index than there are elements.local_to_local!(dst, dm, src)and the in-placelocal_to_local!(v, dm), to refresh ghost points.with_product_coordinates(f, dm): read-only access to a DMStag's per-axis coordinates, handed back whenfreturns.set_matrix_preallocate_only!(dm, flag), so a matrix fromdmgets its nonzero pattern from the first assembly.with_field_views!(f, dm, vecs...; fields, read, write): concretely typed views of DMStag local vectors bylocation => dof, indexed likestencil, handed back whenfreturns. About 9 allocations per vector, whatever the grid size. The docstring shows two DMs checked out by nesting, with one vector handed back mid-scope for a halo exchange.
v0.5.1
0.5.1 settles how a wrapper relates to its PETSc object and what happens when PETSc calls back into Julia (docs/src/man/naming.md §18), fixes a use-after-free, and adds what a nested or logged solve needs. Working code is most likely to notice the four behaviour changes below; each replaces behaviour that was unsafe or contradicted the docs.
Behaviour changes
- Handles returned by a
LibPETScGetfunction are borrowed, as in PETSc:destroy!on them does nothing. This coverssnes(ts),ksp(ts),pc(ksp)and callback arguments, which could be destroyed from under a running solver. The 36Getfunctions that return a new reference (MatGetFactor,DMLabelGetStratumIS, …; seewrapping/generator/rules/ownership.toml) still return an owner. - An exception in a
TScallback comes out ofsolve!orstep!as itself, not as aPetscError. LibPETSc.PCis a handle type,PC{PetscLib}, instead of a raw pointer. Code that passes a PC between calls is unaffected; code that expects aPtrneedspc.ptr.add_boundary!andadd_natural_boundary!returndminstead of the boundary number, whichLibPETSc.DMAddBoundarystill returns.
Fixed
- Use-after-free:
PetscVec(petsclib, array)andPetscVec(petsclib, comm, array)did not keeparrayalive, so after a garbage collection the vector could use reclaimed memory.ksp \ bwith a Julia vector andM * xwith aMatShellhad the same bug. The same applied to matrices built on CSR arrays once a solver outlived the handle. - An exception in a SNES, KSP or
MatShellcallback unwound through PETSc's C code, which is undefined behaviour.solve!,step!andsetup!now rethrow the original exception; a solve started throughLibPETSclogs it and throwsPetscError. - A callback set through a borrowed handle, such as
set_function!(f!, snes(ts), r), could be garbage-collected while the solver still used it. Callbacks, the user context and constructor options now live with the PETSc object (naming.md §18.3); the old fields such assnes.user_ctxstill work. set_convergence_test!overwrotesnes.user_ctx.KSP(petsclib, comm, S::SparseMatrixCSC)leaked its matrix.TSIRKtypes (-ts_irk_type gauss, …) were lost afterfinalizeandinitialize.PetscOptions(petsclib)succeeded on an uninitialized library; it now throwsPetscNotInitializedlike every other constructor.set_from_options!(ts)ignored the options given to theTSconstructor.converged_reason(ksp),solution(snes)andset_from_options!(snes), shown in the manual, did not exist.
Added
pc(ksp), withset_type!,type_nameandset_fieldsplit_is!, and a Julia:shellpreconditioner throughset_shell_apply!(apply!, p)andset_shell_setup!(setup!, p).- Solver readers:
ksp(snes),solution(snes),iteration_number,converged_reason,ksp_iterations(snes),function_norm(snes)andprev_time(ts). - Nested solvers without
LibPETSc:set_operators!(ksp, A, P = A),set_dm_active!,set_options_prefix!andoptions_prefix, andset_from_options!onKSPandSNES. set_function_domain_error!(snes), anduser_ctx/set_user_ctx!onSNESandTS.- Every handle carries an
ownfield, read byowns(obj); constructors takeownas a keyword.destroy!(pc)destroys aPCcreated withLibPETSc.PCCreate.
Changed
- Every
!function returns the object it mutates (naming.md §7), for exampleset_type!(ksp, :cg)returnskspandsolve!(x, ksp, b)returnsx; about 60 returnednothing. The exceptions aredestroy!and other releases, which returnnothing, andwith_local_array!, which returns its block's result. - A callback's return value is ignored: it fails by throwing. Until v0.6, a nonzero
Integerstill fails the call and warns. KSP,MatShelland the CSR andSparseMatrixCSCPetscMatconstructors attach a finalizer on one process, likeSNESandTS.save_vtk!andvtk_merge_tensor!are nowsave_vtkandvtk_merge_tensor, since they mutate no argument; the old names warn until v0.6.MPIPreferencesis a test-only dependency.
v0.5.0
PETSc.jl 0.5 wraps PETSc 3.25.4 (PETSc_jll 3.25) and requires Julia 1.12. The low-level LibPETSc bindings are regenerated by a new rules-based generator (wrapping/, see wrapping/WRAPPING.md) that can be rerun for every PETSc release; the hand edits that used to live in src/autowrapped/ are expressed as rules and overrides. This changes the calling convention of many LibPETSc functions.
Breaking changes (low-level LibPETSc)
- Outputs are returned, not written into caller-supplied handles or
Refs.PCCreate(petsclib, comm)returns thePC;KSPGetPC(petsclib, ksp)returns thePC;DMPlexDistribute(petsclib, dm, overlap)returns(sf, dmParallel);ISSorted(petsclib, is)returns aPetscBool;PetscSFGetGraph(petsclib, sf)returns(nroots, nleaves, ilocal, iremote). About 480 functions changed this way (wrapping/DEVIATIONS.mdlists every category). XDestroytakes the handle or aRefto it:PetscViewerDestroy(petsclib, viewer).- String enums are Julia
Strings.PCSetType(petsclib, pc, "ilu")works directly;Base.unsafe_convert(Ptr{Int8}, "ilu")is no longer accepted, and the hand-writtenStringoverloads (src/string_wrappers*.jl) are gone. The registered names are constants:LibPETSc.PCMG == "mg",LibPETSc.KSPGMRES,LibPETSc.MATSEQAIJ, ...XGetTypereturns aString(""when unset). PetscKSP->KSP,PetscSNES->SNES,AbstractPetscKSP->AbstractKSP,AbstractPetscSNES->AbstractSNES;AbstractPETScMemBackend->AbstractPetscMemBackend(PR #260 naming conventions). The old names remain as deprecated aliases until v0.6.- Input arguments accept abstract types (
AbstractPetscVec,AbstractVector{<:Number},Integer), returned handles are concrete (PR #263). A call with unsupported argument types throws instead of silently returningnothing. - Callbacks and contexts are
Ptr{Cvoid};const T *xinputs areVector{T};char[]inputs areString;const char *x[]outputs return aString. - PETSc-owned output arrays with a documented length come back as
Vectors (arrays of handles asVector{IS}etc.); those without one return the raw pointer. PetscSplitOwnership*,PetscSortRemoveDups*and thenmaxofPetscOptionsGet*Arraytake and return their in/out scalar.- 95 header-inline functions and macros without a symbol in
libpetsc(PetscStrcmp,PetscTime,VecSetValue,MatSetValue,PetscOptionsBegin, ...) are no longer wrapped. - Deprecated enum values are not emitted.
KSPSetDMActivetakes theKSPDMActiveflag (PETSc 3.25).
High-level API renamed (naming conventions)
The high-level interface follows docs/src/man/naming.md from v0.5 on. Roughly a hundred names change, and the full rename table is at the end of that page — what follows is what the changes are and how to move.
The register and the shims. scripts/renames.jl is the register: a plain list of old => new pairs plus the internal and unchanged-public sets. src/deprecations.jl, src/public_names.jl, src/audit_names.jl and test/test_deprecations.jl are generated from it by scripts/generate_renames.jl, so they cannot drift apart, and scripts/api_surface.jl --check (run by the test suite) fails if a binding is in none of its sets. Every renamed name keeps a forwarding shim that warns once per call site — through @warn, not Base.depwarn, so it prints whatever --depwarn is set to — and the shims are removed in v0.6.
Exports. PETSc now exports only types and construction entry points:
export LibPETSc
export DMDA, DMStag, DMPlex
export PetscVec, PetscMat, PetscOptions
export KSP, SNES, TS
export petsclibsv0.4 exported twelve functions and no types at all. audit_petsc_file, set_petsclib, set_library!, unset_library!, library_info, AbstractPetscMemBackend, AbstractPETScMemBackend, determine_memtype, get_petsc_arrays, restore_petsc_arrays and dmda_star_fd_coloring lose their export (HostBackend was exported but never defined). No shim can help here: the replacements are not exported either, so using PETSc code qualifies the call (PETSc.set_library!) or imports the name. The rest of the API is marked public, so names(PETSc) reports it without exporting it.
Construction goes through the type. PetscVec(petsclib, …) replaces VecSeq and as_petsc_vec; PetscMat(petsclib, …) replaces MatSeqAIJ, MatSeqDense, MatCreateSeqAIJ, MatSeqAIJWithArrays and MatAIJ; PetscOptions replaces Options; PetscLibType(path; …) replaces set_petsclib. KSP, SNES and TS are types rather than factory functions, so ksp isa PETSc.KSP holds.
A typed DM hierarchy. DMDA{L,N}, DMStag{L,N} and DMPlex{L} are concrete types under LibPETSc.AbstractPetscDM, not one type with a runtime string flavour. Code annotated ::PetscDM no longer matches — use AbstractPetscDM. PETSc.narrow(dm) turns a low-level handle into the typed one; it queries PETSc, so its return type is a wide Union and hot code should narrow once behind a function barrier. The nine DM-flavour @asserts are gone: dispatch enforces what they checked.
Borrowed handles. A reader that hands back a PETSc object owned by another object — dm(ksp), solution(snes), local_coordinates(dm), tolerances(ts)'s vectors — returns a borrowed handle: no finalizer, and destroy! on it is a no-op (PETSc.owns tells the two apart). Nothing changed at runtime; destroying such a handle was corrupting the owner's already. destroy is now destroy!, per the mutation convention.
Type names are Symbol. type_name on a Vec, Mat, KSP, SNES, TS or DM returns a Symbol, or nothing when PETSc has no type for the object yet, so type_name(ksp) == "gmres" is now false; compare against :gmres. The new set_type!(obj, :gmres) covers Vec, Mat, KSP, SNES and DM as well as TS, and set_type!(obj, "gmres") warns until v0.6. This break has no shim on the reader side.
Argument order, and petsclib dropped. The written vector leads, the DM follows it, and the library is recovered from the object: project_function!(X, dm, time, funcs, ctxs, mode), project_field!(X, dm, time, U, funcs, mode), global_to_local!(lvec, dm, gvec, mode), local_to_global!(gvec, dm, lvec, mode), l2diff(dm, time, funcs, ctxs, X), add_boundary!(dm, …), add_natural_boundary!(dm, …), set_snes_local_fem!(dm), save_vtk!(vec, filename), star_fd_coloring(da). The v0.4 spellings forward and warn, but a call passed through invoke or a function reference is not caught.
Callback setters take the callback first, only. set_function!, set_snes_jacobian!, set_convergence_test!, set_compute_rhs!, set_compute_operators!, set_rhs_function!, set_rhs_jacobian!, set_ifunction!, set_ijacobian!, set_monitor! and add_coarsen_hook! no longer accept the subject-first order v0.4 also offered, so do syntax is always available. No shim: dispatch cannot tell the two orders apart.
Dimension-correct returns. corners, ghost_corners, local_indices, global_indices, info and size answer with the DM's own dimension: lower/upper are CartesianIndex{N}, size/nextra are NTuple{N,Int}, and center/vertex are keyed x, y (, z) by dimension. v0.4 padded everything to three, so corners(dm2d).size[3] returned 1 and now throws a BoundsError. This is also a performance fix: the tuples are built with ntuple(…, Val(N)) and infer concretely instead of allocating. info drops the duplicate s field, renames dof to ndofs and mpi_proc_size to procs, and ghost_corners(::DMStag) has no nextra field: DMStagGetGhostCorners never reported one, though the v0.4 docstring promised it.
ownership_range(A) is 1-based. That was already the default; the positional ownership_range(A, false) still returns PETSc's numbering, warns, and is a MethodError in v0.6. set_values! spells its index parameters rows_0b/cols_0b and star_fd_coloring returns row_coo_local_0b, col_coo_local_0b, perturb_cols_1b, coo_idxs_1b and local_rows_1b, so every bulk index vector says which base it uses.
Smaller changes. library_info() returns (; source, path, scalar, int, real) and prints its old report from a show method. Argument problems raise ArgumentError, DimensionMismatch or PetscNotInitialized rather than AssertionError or a bare error. PETSc.KSP(…) / PETSc.SNES(…) construct the LibPETSc.KSP / LibPETSc.SNES types.
The rename table, and the reasoning behind each rule, are in docs/src/man/naming.md; the C-function-to-Julia-name lookup is the generated "C to Julia name index" page in the manual.
Changed
ForwardDiff,UnicodePlots,StatisticsandPkgare no longer dependencies of the package: nothing insrc/used them, and the tests and examples that do now pull them through[extras]andexamples/Project.toml. Installing PETSc.jl resolves 86 packages instead of 121, which cuts cold precompilation by roughly a factor of five.Only one
PetscIntwidth ofPETSc_jllis loaded per process (#241):PETSc.petsclibsholds the four scalar variants ofInt64by default,PETSc.set_petscint!(Int32)switches to theInt32libraries on the next session. Loading both widths cross-binds the identically named HYPRE/SuperLU_DIST symbols of the two integer ABIs. Code indexingpetsclibs[5:8]breaks.
Added
- PetscSF communication:
PetscSFBcastBegin/End,PetscSFReduceBegin/End,PetscSFFetchAndOpBegin/End(hand-written;getAPI.pyrejectsMPI_Datatypefunctions). PetscDrawandTSMonitorLGCtxhandles work (they were empty placeholder structs).- Windows CI with MPI (PETSc_jll 3.25.4 ships MPI-enabled Windows binaries).
- Documentation pages for every wrapper file, and the maintainer guide "Regenerating the wrappers".
- Test coverage:
test/wrapper_quality.jl(every generated method infers a concrete return type; representatives are allocation free),test/wrapper_leaks.jl, an ambiguity budget,test/low_level_petscsf.jl.
Fixed
PetscBoolis one byte, matching PETSc'stypedef bool PetscBool(since 3.24). The previous 32-bit type read three bytes PETSc never wrote, so aPETSC_FALSEoutput could come back as true (#268),Vector{PetscBool}arguments had the wrong stride and theMatFactorInfo,PetscFEGeomandPetscEventPerfInfostruct layouts were off.Re-initialising PETSc after
finalizeworks with Tao, TaoTerm and TSTrajectory (PETSc 3.25.x does not reset theirRegisterAllCalledflags; on Windows the internal symbols are not exported, seePETSc.tao_usable_after_reinitialize()).Re-initialising PETSc no longer overwrites three bytes of PETSc's memory: the
TaoRegisterAllCalled,TaoTermRegisterAllCalledandTSTrajectoryRegisterAllCalledflags were reset with a 4-byte store, whilePetscBoolis 1 byte.unsafe_local_arrayno longer touches a destroyed vector or a finalized library.Double free of DMDA coordinate vectors;
PCMGSetLevelsreading uninitialised communicators.Block assignment
A[rows, cols] = blockon aPetscMatworks (#248, #271). It threw aMethodError, and the values were laid out column by column whereMatSetValuesreads them row by row. A block whose size does not match the index ranges raises aDimensionMismatch.PetscOptionsrecords the initialize/finalize cycle it was created in, likePetscVec,PetscMat,KSP,SNES,TSand the DMs, sodestroy!and its finalizer no longer callPetscOptionsDestroyon an object from an earlier cycle (#270).
Removed
- The old PythonCall-based generator (
wrapping/generatejuliabindings.jl),src/deprecated/,src/startup.jl,src/string_wrappers*.jl. LibPETSc.petsc_versionandPETSc.SUPPORTED_PETSC_VERSIONS, added in 0.4.14 for running on PETSc 3.22 and 3.25. 0.5 binds PETSc 3.25 only;PETSc.check_wrappers_version(petsclib).installed_versionreturns the library version.