code: def _construct_space_discretized_eqn_params(
      coord_grid,
      coord_grid_deltas,
      value_grid,
      boundary_conditions,
      has_default_lower_boundary,
      has_default_upper_boundary,
      second_order_coeff_fn,
      first_order_coeff_fn,
      zeroth_order_coeff_fn,
      inner_second_order_coeff_fn,
      inner_first_order_coeff_fn,
      t,
  ):
      """Constructs the tridiagonal matrix and the inhomogeneous term."""
      # The space-discretized PDE has the form dv/dt = A(t) v(t) + b(t), where
      # v(t) is V(t, x) discretized by x, A(t) is a tridiagonal matrix and b(t) is
      # a vector. A(t) and b(t) depend on the PDE coefficients and the boundary
      # conditions. This function constructs A(t) and b(t). See construction of
      # A(t) e.g. in [Forsyth, Vetzal][1] (we denote `beta` and `gamma` from the
      # paper as `dx_coef` and `dxdx_coef`).
  
      # Get forward, backward and total differences.
      forward_deltas = coord_grid_deltas[..., 1:]
      backward_deltas = coord_grid_deltas[..., :-1]
      # Note that sum_deltas = 2 * central_deltas.
      sum_deltas = forward_deltas + backward_deltas
  
      # 3-diagonal matrix construction. See matrix `M` in [Forsyth, Vetzal][1].
      #  The `tridiagonal` matrix is of shape
      # `[value_dim, 3, num_grid_points]`.
  
      # Get the PDE coefficients and broadcast them to the shape of value grid.
      second_order_coeff_fn = second_order_coeff_fn or (
          lambda *args: [[None]]
      )
      first_order_coeff_fn = first_order_coeff_fn or (
          lambda *args: [None]
      )
      zeroth_order_coeff_fn = zeroth_order_coeff_fn or (
          lambda *args: None
      )
      inner_second_order_coeff_fn = inner_second_order_coeff_fn or (
          lambda *args: [[None]]
      )
      inner_first_order_coeff_fn = inner_first_order_coeff_fn or (
          lambda *args: [None]
      )
  
      second_order_coeff = _prepare_pde_coeffs(
          second_order_coeff_fn(t, coord_grid)[0][0], value_grid
      )
      first_order_coeff = _prepare_pde_coeffs(
          first_order_coeff_fn(t, coord_grid)[0], value_grid
      )
      zeroth_order_coeff = _prepare_pde_coeffs(
          zeroth_order_coeff_fn(t, coord_grid), value_grid
      )
      inner_second_order_coeff = _prepare_pde_coeffs(
          inner_second_order_coeff_fn(t, coord_grid)[0][0], value_grid
      )
      inner_first_order_coeff = _prepare_pde_coeffs(
          inner_first_order_coeff_fn(t, coord_grid)[0], value_grid
      )
  
      zeros = tf.zeros_like(value_grid[..., 1:-1])
  
      # Discretize zeroth-order term.
      if zeroth_order_coeff is None:
          diag_zeroth_order = zeros
      else:
          # Minus is due to moving to rhs.
          diag_zeroth_order = -zeroth_order_coeff[..., 1:-1]
  
      # Discretize first-order term.
      if first_order_coeff is None and inner_first_order_coeff is None:
          # No first-order term.
          superdiag_first_order = zeros
          diag_first_order = zeros
          subdiag_first_order = zeros
      else:
          superdiag_first_order = -backward_deltas / (
              sum_deltas * forward_deltas
          )
          subdiag_first_order = forward_deltas / (
              sum_deltas * backward_deltas
          )
          diag_first_order = (
              -superdiag_first_order - subdiag_first_order
          )
          if first_order_coeff is not None:
              superdiag_first_order *= first_order_coeff[..., 1:-1]
              subdiag_first_order *= first_order_coeff[..., 1:-1]
              diag_first_order *= first_order_coeff[..., 1:-1]
          if inner_first_order_coeff is not None:
              superdiag_first_order *= inner_first_order_coeff[..., 2:]
              subdiag_first_order *= inner_first_order_coeff[..., :-2]
              diag_first_order *= inner_first_order_coeff[..., 1:-1]
  
      # Discretize second-order term.
      if (
          second_order_coeff is None
          and inner_second_order_coeff is None
      ):
          # No second-order term.
          superdiag_second_order = zeros
          diag_second_order = zeros
          subdiag_second_order = zeros
      else:
          superdiag_second_order = -2 / (sum_deltas * forward_deltas)
          subdiag_second_order = -2 / (sum_deltas * backward_deltas)
          diag_second_order = (
              -superdiag_second_order - subdiag_second_order
          )
          if second_order_coeff is not None:
              superdiag_second_order *= second_order_coeff[..., 1:-1]
              subdiag_second_order *= second_order_coeff[..., 1:-1]
              diag_second_order *= second_order_coeff[..., 1:-1]
          if inner_second_order_coeff is not None:
              superdiag_second_order *= inner_second_order_coeff[
                  ..., 2:
              ]
              subdiag_second_order *= inner_second_order_coeff[..., :-2]
              diag_second_order *= inner_second_order_coeff[..., 1:-1]
  
      superdiag = superdiag_first_order + superdiag_second_order
      subdiag = subdiag_first_order + subdiag_second_order
      diag = diag_zeroth_order + diag_first_order + diag_second_order
      # Apply default BC, if needed. This adds extra points to the diagonal terms
      # coming from discretization of 'V_t + b * d(B * V)/dx + c * V = 0'.
      (subdiag, diag, superdiag) = _apply_default_boundary(
          subdiag,
          diag,
          superdiag,
          zeroth_order_coeff,
          inner_first_order_coeff,
          first_order_coeff,
          forward_deltas,
          backward_deltas,
          has_default_lower_boundary,
          has_default_upper_boundary,
      )
      # Apply Robin boundary conditions
      return _apply_robin_boundary_conditions(
          value_grid,
          boundary_conditions,
          has_default_lower_boundary,
          has_default_upper_boundary,
          coord_grid,
          coord_grid_deltas,
          diag,
          superdiag,
          subdiag,
          t,
      )
  
file_path: tf-quant-finance/tf_quant_finance/math/pde/steppers/parabolic_equation_stepper.py
imports: import tensorflow.compat.v2
  from tf_quant_finance import utils
label_desc: Use image node_id 2 for calling a global function with example usage: _construct_space_discretized_eqn_params(coord_grid, coord_grid_deltas, value_grid, boundary_conditions, has_default_lower_boundary, has_default_upper_boundary, second_order_coeff_fn, first_order_coeff_fn, zeroth_order_coeff_fn, inner_second_order_coeff_fn, inner_first_order_coeff_fn, t) and returns: _apply_robin_boundary_conditions