Please note that if h comes from a function, it needs to be mapped to the mesh nodes.
See for instance: Moving submesh diverges from its designated trajectory in a two-phase problem - #2 by dokken
It is quite easy to gather the local mesh geometry and topology, as each of them has an index map that can be used to map from local to global indices.
An illustration of this is done with:
from mpi4py import MPI
import dolfinx
import numpy as np
mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
geom_imap = mesh.geometry.index_map()
local_range = geom_imap.local_range
num_nodes_local = local_range[1] - local_range[0]
nodes = mesh.geometry.x.reshape(-1, 3)[:num_nodes_local, :]
all_nodes = mesh.comm.gather(nodes, root=0)
if mesh.comm.rank == 0:
all_nodes = np.vstack(all_nodes)
print(all_nodes.shape)
num_cells_local = mesh.topology.index_map(mesh.topology.dim).size_local
connectivity = mesh.geometry.dofmap[:num_cells_local, :]
global_connectivity = geom_imap.local_to_global(connectivity.flatten()).reshape(-1, connectivity.shape[1])
all_connectivity = mesh.comm.gather(global_connectivity, root=0)
if mesh.comm.rank == 0:
all_connectivity = np.vstack(all_connectivity)
print(all_connectivity.shape)