From 6831feeea9982197c76dbef3b98f84c7b7005112 Mon Sep 17 00:00:00 2001 From: "Jack S. Hale" Date: Tue, 10 Sep 2024 18:02:35 +0200 Subject: [PATCH] Clarify memory management of returned petsc4py objects. (#3329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Clarify memory management of returned petsc4py objects. * Clearer. * Update text with Garth's suggestion --------- Co-authored-by: Jørgen Schartum Dokken Co-authored-by: Jørgen S. Dokken --- python/dolfinx/fem/petsc.py | 36 ++++++++++++++++++++++++++++++++++++ python/dolfinx/la.py | 19 ++++++++++++++++--- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/python/dolfinx/fem/petsc.py b/python/dolfinx/fem/petsc.py index 2e83bf2ba83..cf9f630dcc5 100644 --- a/python/dolfinx/fem/petsc.py +++ b/python/dolfinx/fem/petsc.py @@ -111,6 +111,12 @@ def create_vector(L: Form) -> PETSc.Vec: def create_vector_block(L: list[Form]) -> PETSc.Vec: """Create a PETSc vector (blocked) that is compatible with a list of linear forms. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Vec.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Vec.destroy()`` is collective over the object's MPI communicator. + Args: L: List of linear forms. @@ -148,6 +154,12 @@ def create_vector_nest(L: list[Form]) -> PETSc.Vec: def create_matrix(a: Form, mat_type=None) -> PETSc.Mat: """Create a PETSc matrix that is compatible with a bilinear form. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Mat.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Mat.destroy()`` is collective over the object's MPI communicator. + Args: a: A bilinear form. mat_type: The PETSc matrix type (``MatType``). @@ -164,6 +176,12 @@ def create_matrix(a: Form, mat_type=None) -> PETSc.Mat: def create_matrix_block(a: list[list[Form]]) -> PETSc.Mat: """Create a PETSc matrix that is compatible with a rectangular array of bilinear forms. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Mat.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Mat.destroy()`` is collective over the object's MPI communicator. + Args: a: Rectangular array of bilinear forms. @@ -178,6 +196,12 @@ def create_matrix_block(a: list[list[Form]]) -> PETSc.Mat: def create_matrix_nest(a: list[list[Form]]) -> PETSc.Mat: """Create a PETSc matrix (``MatNest``) that is compatible with an array of bilinear forms. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Mat.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Mat.destroy()`` is collective over the object's MPI communicator. + Args: a: Rectangular array of bilinear forms. @@ -958,6 +982,12 @@ def discrete_gradient(space0: _FunctionSpace, space1: _FunctionSpace) -> PETSc.M H1 space uses an identity map and the H(curl) space uses a covariant Piola map. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Mat.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Mat.destroy()`` is collective over the object's MPI communicator. + Args: space0: H1 space to interpolate the gradient from. space1: H(curl) space to interpolate into. @@ -971,6 +1001,12 @@ def discrete_gradient(space0: _FunctionSpace, space1: _FunctionSpace) -> PETSc.M def interpolation_matrix(space0: _FunctionSpace, space1: _FunctionSpace) -> PETSc.Mat: """Assemble an interpolation operator matrix. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Mat.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Mat.destroy()`` is collective over the object's MPI communicator. + Args: space0: Space to interpolate from. space1: Space to interpolate into. diff --git a/python/dolfinx/la.py b/python/dolfinx/la.py index 1c7b58ab676..9998be3fac1 100644 --- a/python/dolfinx/la.py +++ b/python/dolfinx/la.py @@ -263,6 +263,10 @@ def petsc_vec(self): Upon first call, this function creates a PETSc ``Vec`` object that wraps the degree-of-freedom data. The ``Vec`` object is cached and the cached ``Vec`` is returned upon subsequent calls. + + Note: + When the object is destroyed it will destroy the underlying petsc4py + vector automatically. """ if self._petsc_x is None: self._petsc_x = create_petsc_vector_wrap(self) @@ -317,15 +321,18 @@ def vector(map, bs=1, dtype: npt.DTypeLike = np.float64) -> Vector: def create_petsc_vector_wrap(x: Vector): """Wrap a distributed DOLFINx vector as a PETSc vector. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Vec.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Vec.destroy()`` is collective over the object's MPI communicator. + Args: x: The vector to wrap as a PETSc vector. Returns: A PETSc vector that shares data with ``x``. - Note: - The vector ``x`` must not be destroyed before the returned PETSc - object. """ from petsc4py import PETSc @@ -339,6 +346,12 @@ def create_petsc_vector_wrap(x: Vector): def create_petsc_vector(map, bs: int): """Create a distributed PETSc vector. + Note: + Due to subtle issues in the interaction between petsc4py memory management + and the Python garbage collector, it is recommended that the method ``PETSc.Vec.destroy()`` + is called on the returned object once the object is no longer required. Note that + ``PETSc.Vec.destroy()`` is collective over the object's MPI communicator. + Args: map: Index map that describes the size and parallel layout of the vector to create.