LCOV - code coverage report
Current view: top level - include/numerics - wrapped_petsc.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 13 17 76.5 %
Date: 2025-08-19 19:27:09 Functions: 40 58 69.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : #ifndef LIBMESH_WRAPPED_PETSC_H
      19             : #define LIBMESH_WRAPPED_PETSC_H
      20             : 
      21             : #include "libmesh/libmesh_config.h"
      22             : 
      23             : #ifdef LIBMESH_HAVE_PETSC
      24             : 
      25             : // C++ includes
      26             : #include <utility> // std::swap, std::move
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : // Template class which wraps PETSc objects and specializes the
      32             : // destructor to call the appropriate "XXXDestroy()" routine.
      33             : template <typename T>
      34             : struct WrappedPetsc
      35             : {
      36             :   /**
      37             :    * Default constructor. This should mimic the way that we normally
      38             :    * write e.g.
      39             :    * KSP ksp;
      40             :    * and then proceed to use ksp in different PETSc routines. That is,
      41             :    * obj is not initialized to any particular value.
      42             :    */
      43      368839 :   WrappedPetsc() : obj() {}
      44             : 
      45             :   /**
      46             :    * Constructor which initializes obj to a specific passed-in value.
      47             :    * This mimics code in which we explicitly create a PETSc object via
      48             :    * IS is = NULL;
      49             :    * Technically one could pass any pointer value in here, but it usually
      50             :    * only makes sense to pass nullptr.
      51             :    */
      52       23496 :   WrappedPetsc(T obj_in) : obj(obj_in) {}
      53             : 
      54             :   /**
      55             :    * Destructor. Just calls destroy().
      56             :    */
      57       80262 :   ~WrappedPetsc()
      58             :   {
      59      788740 :     destroy();
      60      787770 :   }
      61             : 
      62             :   /**
      63             :    * Calls destroy() _and_ sets the managed object to nullptr. As far
      64             :    * as I can tell, setting obj to nullptr is not done by the various
      65             :    * XXXDestroy() routines of PETSc, so we also don't do this in the
      66             :    * wrapping class's destructor, however, there are situations where
      67             :    * it is sometimes useful to both call the relevant XXXDestroy()
      68             :    * function and reset the pointer, hence the need for this function.
      69             :    */
      70           6 :   void reset_to_zero()
      71             :   {
      72         210 :     destroy();
      73         210 :     obj = nullptr;
      74         204 :   }
      75             : 
      76             :   /**
      77             :    * Copy constructor and copy assignment operator. These are deleted
      78             :    * since I don't think we can safely shallow copy PETSc objects like
      79             :    * KSP and Vec, which are internally reference-counted pointers and
      80             :    * probably don't do the right thing if they are shallow-copied.
      81             :    */
      82             :   WrappedPetsc(const WrappedPetsc & other) = delete;
      83             :   WrappedPetsc & operator= (const WrappedPetsc &) = delete;
      84             : 
      85             :   /**
      86             :    * Move constructor. We could almost default this, but we need to
      87             :    * set other.obj to nullptr so that when it is subsequently
      88             :    * Destroy()ed it's just a no-op rather than messing up the
      89             :    * reference count or trying to double-free memory.
      90             :    */
      91           0 :   WrappedPetsc(WrappedPetsc && other) noexcept
      92           0 :     : obj(other.obj)
      93             :   {
      94           0 :     other.obj = nullptr;
      95           0 :   }
      96             : 
      97             :   /**
      98             :    * Move-assignment operator. Use move-construct-and-swap idiom
      99             :    * instead of defaulting since we want to make sure our move
     100             :    * constructor leaves the passed-in object in a Destroy()able state.
     101             :    */
     102             :   WrappedPetsc & operator= (WrappedPetsc && other) noexcept
     103             :   {
     104             :     WrappedPetsc tmp(std::move(other));
     105             :     std::swap(tmp, *this);
     106             :     return *this;
     107             :   }
     108             : 
     109             :   /**
     110             :    * \returns pointer to the managed object
     111             :    * This is used to mimic code such as:
     112             :    * KSP ksp;
     113             :    * KSPCreate(comm, &ksp);
     114             :    * Since taking the address of the wrapping object doesn't make
     115             :    * sense in this context.
     116             :    */
     117       90549 :   T * get() { return &obj; }
     118             : 
     119             :   /**
     120             :    * User-defined conversion function. We provide non-const access to
     121             :    * the underlying T object even when the "this" object is considered
     122             :    * const, since PETSc APIs which are "logically const" typically
     123             :    * still take non-const parameters.
     124             :    */
     125     4703570 :   operator T() const { return obj; }
     126             : 
     127             :   /**
     128             :    * The "dereferencing" operator. Returns a reference to the managed
     129             :    * object. This is needed for some situations in which the
     130             :    * user-defined conversion operator doesn't work, for example with
     131             :    * C-style casts:
     132             :    * KSP ksp;
     133             :    * ...
     134             :    * PetscObjectSetOptionsPrefix((PetscObject)(*ksp), "balance_");
     135             :    */
     136        1176 :   T & operator*() { return obj; }
     137             : 
     138             :   /**
     139             :    * User-defined conversion to bool. This is intended to mimic code like:
     140             :    * IS is = nullptr;
     141             :    * ...
     142             :    * if (!is)
     143             :    *   ...
     144             :    * Note that this comparison is thus concerned with obj itself and
     145             :    * not &obj.
     146             :    */
     147     1299032 :   operator bool() const { return obj != nullptr; }
     148             : 
     149             :   /**
     150             :    * Must be specialized to call the appropriate XXXDestroy() routine
     151             :    * in order for a WrappedPetsc<T> object to be instantiated.
     152             :    *
     153             :    * We could try to do extra error checking in destroy() as shown
     154             :    * below, but note that:
     155             :    * 1.) destroy() is called from destructors, sometimes during
     156             :    *     stack unwinding. If there's an error code returned from
     157             :    *     XXXDestroy(), then our only option is to immediately terminate
     158             :    *     the program, which would then kill any chance of recovering from
     159             :    *     the exception.
     160             :    * 2.) It's not always safe to call non-Destroy() functions on PETSc objects
     161             :    *     which are about to be Destroy()ed, that is, we would have to check
     162             :    *     for nullptr, etc. which would lead to more complexity, and more code.
     163             :    *
     164             :    * One possible approach for extra error checking with immediate
     165             :    * abort on error:
     166             :    *
     167             :    * MPI_Comm comm;
     168             :    * PetscObjectGetComm((PetscObject)(&obj), &comm);
     169             :    * PetscErrorCode ierr = Type ## Destroy(&obj);
     170             :    * CHKERRABORT(comm, ierr);
     171             :    */
     172             :   void destroy();
     173             : 
     174             : private:
     175             :   T obj;
     176             : };
     177             : 
     178             : } // namespace libMesh
     179             : 
     180             : #endif // LIBMESH_HAVE_PETSC
     181             : 
     182             : #endif

Generated by: LCOV version 1.14