class_docstr: Fast 'geometric' approximation, recommended for large arrays.
class_docstr_tok: ["Fast","'geometric","'","approximation",",","recommended","for","large","arrays","."]
docstr: Compute the (global) gradient component of f assumed linear (~f).
  returns array df of shape (nelems, 2)
  df[ielem].dM[ielem] = dz[ielem] i.e. df = dz x dM = dM.T^-1 x dz
docstr_tok: ["Compute","the","(","global",")","gradient","component","of","f","assumed","linear","(","~f",")",".","returns","array","df","of","shape","(","nelems",",","2",")","df","[","ielem","]",".dM","[","ielem","]","=","dz","[","ielem","]","i.e",".","df","=","dz","x","dM","=","dM.T^-1","x","dz"]
code: def compute_geom_grads(self):
      """
      Compute the (global) gradient component of f assumed linear (~f).
      returns array df of shape (nelems, 2)
      df[ielem].dM[ielem] = dz[ielem] i.e. df = dz x dM = dM.T^-1 x dz
      """
      tris_pts = self._tris_pts
      tris_f = self.z[self._triangles]
  
      dM1 = tris_pts[:, 1, :] - tris_pts[:, 0, :]
      dM2 = tris_pts[:, 2, :] - tris_pts[:, 0, :]
      dM = np.dstack([dM1, dM2])
      # Here we try to deal with the simplest colinear cases: a null
      # gradient is assumed in this case.
      dM_inv = _safe_inv22_vectorized(dM)
  
      dZ1 = tris_f[:, 1] - tris_f[:, 0]
      dZ2 = tris_f[:, 2] - tris_f[:, 0]
      dZ = np.vstack([dZ1, dZ2]).T
      df = np.empty_like(dZ)
  
      # With np.einsum: could be ej,eji -> ej
      df[:, 0] = dZ[:, 0] * dM_inv[:, 0, 0] + dZ[:, 1] * dM_inv[:, 1, 0]
      df[:, 1] = dZ[:, 0] * dM_inv[:, 0, 1] + dZ[:, 1] * dM_inv[:, 1, 1]
      return df
  
imports: import numpy
  from matplotlib import _api
  from matplotlib.tri import Triangulation
  from matplotlib.tri._trifinder import TriFinder
  from matplotlib.tri._tritools import TriAnalyzer
label_desc: Use image node_id 3 for calling the _DOF_estimator_geom obj's underlying member method code with example usage: obj.compute_geom_grads() and returns: df