code: def build_grad_matrices(V, points):
      
      # See <https://www.allanswered.com/post/lkbkm/#zxqgk>
      mesh = V.mesh()
  
      bbt = BoundingBoxTree()
      bbt.build(mesh)
      dofmap = V.dofmap()
      el = V.element()
      rows = []
      cols = []
      datax = []
      datay = []
      for i, xy in enumerate(points):
          cell_id = bbt.compute_first_entity_collision(Point(*xy))
          cell = Cell(mesh, cell_id)
          coordinate_dofs = cell.get_vertex_coordinates()
  
          rows.append([i, i, i])
          cols.append(dofmap.cell_dofs(cell_id))
  
          v = el.evaluate_basis_derivatives_all(1, xy, coordinate_dofs, cell_id)
          v = v.reshape(3, 2)
          datax.append(v[:, 0])
          datay.append(v[:, 1])
  
      rows = numpy.concatenate(rows)
      cols = numpy.concatenate(cols)
      datax = numpy.concatenate(datax)
      datay = numpy.concatenate(datay)
  
      m = len(points)
      n = V.dim()
      dx_matrix = sparse.csr_matrix((datax, (rows, cols)), shape=(m, n))
      dy_matrix = sparse.csr_matrix((datay, (rows, cols)), shape=(m, n))
      return dx_matrix, dy_matrix
docs: Build the sparse m-by-n matrices that map a coefficient set for a function in V
      to the values of dx and dy at a number m of points.