class_docstr: The structural additive contextual(SAC) kernel.
  
  The kernel is used for contextual BO without oberseving context breakdowns.
  There are d parameters and M contexts. In total, the dimension of parameter space
  is d*M and input x can be written as
  x=[x_11, ..., x_1d, x_21, ..., x_2d, ...,  x_M1, ..., x_Md].
  
  The kernel uses the parameter decomposition and assumes an additive structure
  across contexts. Each context compponent is assumed to be independent.
  
  .. math::
     \begin{equation*}
        k(\mathbf{x}, \mathbf{x'}) = k_1(\mathbf{x_(1)}, \mathbf{x'_(1)}) + \cdots
        + k_M(\mathbf{x_(M)}, \mathbf{x'_(M)})
     \end{equation*}
  
  where
  * :math: M is the number of partitions of parameter space. Each partition contains
  same number of parameters d. Each kernel `k_i` acts only on d parameters of ith
  partition i.e. `\mathbf{x}_(i)`. Each kernel `k_i` is a scaled Matern kernel
  with same lengthscales but different outputscales.
code: def device(self) -> Optional[torch.device]:
      return self._device
  
file_path: botorch/botorch/models/kernels/contextual_sac.py
imports: from typing import Any, Dict, List, Optional
  import torch
  from gpytorch.kernels.kernel import Kernel
  from gpytorch.kernels.matern_kernel import MaternKernel
  from gpytorch.kernels.scale_kernel import ScaleKernel
  from gpytorch.priors.torch_priors import GammaPrior
  from linear_operator.operators.sum_linear_operator import SumLinearOperator
  from torch import Tensor
  from torch.nn import ModuleDict
label_desc: Use image node_id 2 for calling the SACKernel obj's underlying member method code with example usage: obj.device() and returns: self