diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -108,60 +108,16 @@
 system. How to install such a library is beyond the scope of these
 instructions.
 
-<!---
-(It is important that the MPI library's include files, libraries, and
-executables are installed consistently. A common source of problems is
-that there are several MPI implementations available on a system, and
-that the default include file `mpi.h`, the library `libmpi.a`, and/or
-the executable `mpirun` are provided by different implementations.
-This will lead to various problems, often segfaults, since neither the
-operating system nor these libraries provide any protection against
-such a mismatch.)
--->
-
-In some cases, the MPI library will be installed in `/usr/include`,
-`/usr/lib`, and `/usr/bin`, respectively. In this case, no further
-configuration is necessary, and `mpi-hs` will build out of the box
-with `stack build`.
-
-For convenience, this package offers Cabal flags to handle several
-common cases where the MPI library is not installed in a standard
-location:
-
-- OpenMPI on Debian Linux (package `libopenmpi-dev`): use `--flag
-  mpi-hs:openmpi-debian`
-- OpenMPI on Ubuntu Linux (package `libopenmpi-dev`): use `--flag
-  mpi-hs:openmpi-ubuntu`
-- OpenMPI on macOS with MacPorts (package `openmpi`): use `--flag
-  mpi-hs:openmpi-macports`
-- MPICH on Debian Linux (package `libmpich-dev`): use `--flag
-  mpi-hs:mpich-debian`
-- MPICH on Ubuntu Linux (package `libmpich-dev`): use `--flag
-  mpi-hs:mpich-ubuntu`
-- MPICH on macOS with MacPorts (package `mpich`): use `--flag
-  mpi-hs:mpich-macports`
-
-For example, using the MPICH MPI implementation installed via MacPorts
-on macOS, you build `mpi-hs` like this:
-
-```sh
-stack build --flag mpi-hs:mpich-macports
-```
-
-In the general case, if your MPI library/operating system combination
-is not supported by a Cabal flag, you need to describe the location of
-your MPI library in `stack.yaml`. This might look like:
+`mpi-hs` uses pkg-config to find an MPI installation and supports:
 
-```yaml
-extra-include-dirs:
-  - /usr/lib/openmpi/include
-extra-lib-dirs:
-  - /usr/lib/openmpi/lib
-```
+- OpenMPI via the `-fopenmpi` cabal flag (default)
+- MVAPICH via the `-fmvapich -f-openmpi` cabal flags
+- MPICH via the `-fmpich -f-openmpi` cabal flags
 
-To remove default systems paths from the search paths, disable the
-`system-mpi` flag, which is enable by default: `--flag
-mpi-hs:-system-mpi`.
+Alternatively, `mpi-hs` can link against `-lmpi` an `mpi.h` generically, if all
+pkg-config options are disabled via `-f-openmpi -f-mpich -f-mvapich`.
+In this case you may need to specify `--extra-include-dirs` and `--extra-lib-dirs`
+and point them to your MPI installation directory.
 
 
 ### Testing the MPI installation with a C program
diff --git a/lib/Control/Distributed/MPI.chs b/lib/Control/Distributed/MPI.chs
--- a/lib/Control/Distributed/MPI.chs
+++ b/lib/Control/Distributed/MPI.chs
@@ -29,7 +29,7 @@
 -- MPI (the [Message Passing Interface](https://www.mpi-forum.org)) is
 -- widely used standard for distributed-memory programming on HPC
 -- (High Performance Computing) systems. MPI allows exchanging data
--- (_messages_) between programs running in parallel. There are
+-- (/messages/) between programs running in parallel. There are
 -- several high-quality open source MPI implementations (e.g. MPICH,
 -- MVAPICH, OpenMPI) as well as a variety of closed-source
 -- implementations. These libraries can typically make use of
@@ -88,7 +88,9 @@
     Buffer(..)
 
     -- ** Communicators
-  , Comm(..)
+  , Comm
+  , withComm
+  , peekComm
   , ComparisonResult(..)
   , commCompare
   , commRank
@@ -97,6 +99,9 @@
   , commSelf
   , commWorld
 
+    -- *** Cartesian Communication Grids
+  , cartCreate
+
     -- ** Message sizes
   , Count(..)
   , fromCount
@@ -217,6 +222,7 @@
   , bcast
   , exscan
   , gather
+  , gatherv
   , reduce
   , scan
   , scatter
@@ -642,8 +648,45 @@
     { alloca- `Comm' peekComm*
     } -> `()'#}
 
+{#fun MPI_Dims_create as dimsCreatePrim
+    { `CInt'
+    , `Int'
+    , id `Ptr CInt'
+    } -> `()'#}
 
+withBoolArray :: [Bool] -> (Ptr CInt -> IO a) -> IO a
+withBoolArray bools f = withArray (fmap fromBool bools) f
 
+{#fun MPI_Cart_create as cartCreatePrim 
+    { withComm* %`Comm'
+    , `Int'
+    , id `Ptr CInt'
+    , withBoolArray* `[Bool]'
+    , `Bool'
+    , alloca- `Comm' peekComm*
+    } -> `()'#}
+
+-- | Create a Cartesian process topology.
+cartCreate :: 
+    -- | Communicator from which to create a Cartesian topology.
+    Comm ->
+    -- | The dimensions of the cartesian grid and whether to treat them as 
+    -- periodic. E.g. @[True, False]@ is a two-dimensional grid with the first
+    -- dimension periodic and the second not.
+    [Bool] ->
+    -- | Communicator for the new Cartesian topology and the number of ranks
+    -- along each axis.
+    IO (Comm, [Int])
+cartCreate comm dimPeriodictiy = do
+    let nDims = length dimPeriodictiy
+    Rank cmSz <- commSize comm
+    withArray (replicate nDims 0) $ \dimsPtr -> do
+        dimsCreatePrim cmSz nDims dimsPtr
+        comm <- cartCreatePrim comm nDims dimsPtr dimPeriodictiy False
+        newDims <- peekArray nDims dimsPtr
+        return (comm, fmap fromIntegral newDims)
+
+
 -- | Error value returned by 'getCount' if the message is too large,
 -- or if the message size is not an integer multiple of the provided
 -- datatype (@MPI_UNDEFINED@).
@@ -1084,6 +1127,47 @@
   gatherTyped (castPtr sendptr) sendcount senddatatype
               (castPtr recvptr) recvcount recvdatatype
               root comm
+
+{# fun Gatherv as gatherVTyped
+{ id `Ptr ()'
+, fromCount `Count'
+, withDatatype* %`Datatype'
+, id `Ptr ()'
+, withArray* `[CInt]'
+, withArray* `[CInt]'
+, withDatatype* %`Datatype'
+, fromRank `Rank'
+, withComm* %`Comm'
+} -> `()' return*-
+#}
+
+-- | Gather data from all processes to the root process (collective, 
+-- @[MPI_Gatherv](https://www.mpich.org/static/docs/v3.0.x/www3/MPI_Gatherv.html)@).
+-- The MPI datatypes are determined automatically from the buffer pointer types.
+gatherv :: (Buffer sb, Buffer rb) 
+  => sb 
+  -- | A list with as many elements the communicator has ('commSize'), that
+  -- specifies how many elements to receive from each of the ranks, e.g. @[1, 2, 3]@
+  -- means that the root process will receive 1 element from rank 0, 2 elements from rank 1,
+  -- and 3 elements from rank 2.
+  -> [Count]
+  -- | A list with as many elements as the communicator has ('commSize'), that specifies
+  -- the displacement in the receive buffer where the data from each rank should be placed.
+  -> [Int]
+  -- | Receive buffer. The count of elements from this buffer will be ignored in favour
+  -- of the '[Count]' argument.
+  -> rb
+  -- | Rank of the gathering process
+  -> Rank
+  -- | Communicator
+  -> Comm
+  -> IO ()
+gatherv sendbuf recvcounts displacements recvbuf root comm =
+  withPtrLenType sendbuf $ \sendptr sendcount senddatatype ->
+  withPtrLenType recvbuf $ \recvptr _ recvdatatype ->
+  gatherVTyped (castPtr sendptr) sendcount senddatatype
+               (castPtr recvptr) (fmap fromCount recvcounts) (fmap fromIntegral displacements) recvdatatype
+               root comm
 
 -- | Get the size of a message, in terms of objects of type 'Datatype'
 -- (@[MPI_Get_count](https://www.open-mpi.org/doc/current/man3/MPI_Get_count.3.php)@).
diff --git a/lib/Control/Distributed/MPI/Storable.hs b/lib/Control/Distributed/MPI/Storable.hs
--- a/lib/Control/Distributed/MPI/Storable.hs
+++ b/lib/Control/Distributed/MPI/Storable.hs
@@ -15,7 +15,7 @@
     MPIException(..)
 
     -- ** Communicators
-  , Comm(..)
+  , Comm
   , commSelf
   , commWorld
 
@@ -97,7 +97,7 @@
 
 import qualified Control.Distributed.MPI as MPI
 import Control.Distributed.MPI
-  ( Comm(..)
+  ( Comm
   , commSelf
   , commWorld
   , Count(..)
diff --git a/mpi-hs.cabal b/mpi-hs.cabal
--- a/mpi-hs.cabal
+++ b/mpi-hs.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           mpi-hs
-version:        0.7.3.0
+version:        0.7.3.1
 synopsis:       MPI bindings for Haskell
 description:    MPI (the [Message Passinag Interface](https://www.mpi-forum.org)) is
                 a widely used standard for distributed-memory programming on HPC
@@ -39,8 +39,8 @@
 homepage:       https://github.com/eschnett/mpi-hs#readme
 bug-reports:    https://github.com/eschnett/mpi-hs/issues
 author:         Erik Schnetter <schnetter@gmail.com>
-maintainer:     Erik Schnetter <schnetter@gmail.com>, Phillip Seeber <phillip.seeber@googlemail.com
-copyright:      2018, 2019, 2020, 2023 Erik Schnetter <schnetter@gmail.com>
+maintainer:     Erik Schnetter <schnetter@gmail.com>, Phillip Seeber <phillip.seeber@googlemail.com>
+copyright:      2018, 2019, 2020, 2023, 2024 Erik Schnetter <schnetter@gmail.com>, 2024 Phillip Seeber Phillip Seeber <phillip.seeber@googlemail.com>
 license:        Apache-2.0
 license-file:   LICENSE
 build-type:     Simple
diff --git a/package.yaml b/package.yaml
--- a/package.yaml
+++ b/package.yaml
@@ -1,10 +1,10 @@
 name: mpi-hs
-version: '0.7.3.0'
+version: '0.7.3.1'
 github: "eschnett/mpi-hs"
 license: Apache-2.0
 author: "Erik Schnetter <schnetter@gmail.com>"
-maintainer: "Erik Schnetter <schnetter@gmail.com>, Phillip Seeber <phillip.seeber@googlemail.com"
-copyright: "2018, 2019, 2020, 2023 Erik Schnetter <schnetter@gmail.com>"
+maintainer: "Erik Schnetter <schnetter@gmail.com>, Phillip Seeber <phillip.seeber@googlemail.com>"
+copyright: "2018, 2019, 2020, 2023, 2024 Erik Schnetter <schnetter@gmail.com>, 2024 Phillip Seeber Phillip Seeber <phillip.seeber@googlemail.com>"
 category: Distributed Computing
 synopsis: MPI bindings for Haskell
 description: |
