class_docstr: Calculate the bending energy based on second-order differentiation of ``pred`` using central finite difference.
  
  For more information,
  see https://github.com/Project-MONAI/tutorials/blob/main/modules/bending_energy_diffusion_loss_notes.ipynb.
  
  Adapted from:
      DeepReg (https://github.com/DeepRegNet/DeepReg)
class_docstr_tok: ["Calculate","the","bending","energy","based","on","second-order","differentiation","of","``","pred","``","using","central","finite","difference",".","For","more","information",",","see","https",":","\/\/github.com\/Project-MONAI\/tutorials\/blob\/main\/modules\/bending_energy_diffusion_loss_notes.ipynb",".","Adapted","from",":","DeepReg","(","https",":","\/\/github.com\/DeepRegNet\/DeepReg",")"]
docstr: Args:
      pred: the shape should be BCH(WD)
  
  Raises:
      ValueError: When ``self.reduction`` is not one of ["mean", "sum", "none"].
      ValueError: When ``pred`` is not 3-d, 4-d or 5-d.
      ValueError: When any spatial dimension of ``pred`` has size less than or equal to 4.
      ValueError: When the number of channels of ``pred`` does not match the number of spatial dimensions.
docstr_tok: ["Args",":","pred",":","the","shape","should","be","BCH","(","WD",")","Raises",":","ValueError",":","When","``","self.reduction","``","is","not","one","of","[","``","mean","''",",","``","sum","''",",","``","none","''","]",".","ValueError",":","When","``","pred","``","is","not","3-d",",","4-d","or","5-d.","ValueError",":","When","any","spatial","dimension","of","``","pred","``","has","size","less","than","or","equal","to","4",".","ValueError",":","When","the","number","of","channels","of","``","pred","``","does","not","match","the","number","of","spatial","dimensions","."]
code: def forward(self, pred: torch.Tensor) -> torch.Tensor:
      """
      Args:
          pred: the shape should be BCH(WD)
  
      Raises:
          ValueError: When ``self.reduction`` is not one of ["mean", "sum", "none"].
          ValueError: When ``pred`` is not 3-d, 4-d or 5-d.
          ValueError: When any spatial dimension of ``pred`` has size less than or equal to 4.
          ValueError: When the number of channels of ``pred`` does not match the number of spatial dimensions.
  
      """
      if pred.ndim not in [3, 4, 5]:
          raise ValueError(
              f"Expecting 3-d, 4-d or 5-d pred, instead got pred of shape {pred.shape}"
          )
      for i in range(pred.ndim - 2):
          if pred.shape[-i - 1] <= 4:
              raise ValueError(
                  f"All spatial dimensions must be > 4, got spatial dimensions {pred.shape[2:]}"
              )
      if pred.shape[1] != pred.ndim - 2:
          raise ValueError(
              f"Number of vector components, i.e. number of channels of the input DDF, {pred.shape[1]}, "
              f"does not match number of spatial dimensions, {pred.ndim - 2}"
          )
  
      # first order gradient
      first_order_gradient = [
          spatial_gradient(pred, dim) for dim in range(2, pred.ndim)
      ]
  
      # spatial dimensions in a shape suited for broadcasting below
      if self.normalize:
          spatial_dims = torch.tensor(pred.shape, device=pred.device)[
              2:
          ].reshape((1, -1) + (pred.ndim - 2) * (1,))
  
      energy = torch.tensor(0)
      for dim_1, g in enumerate(first_order_gradient):
          dim_1 += 2
          if self.normalize:
              g *= pred.shape[dim_1] / spatial_dims
              energy = (
                  energy
                  + (spatial_gradient(g, dim_1) * pred.shape[dim_1])
                  ** 2
              )
          else:
              energy = energy + spatial_gradient(g, dim_1) ** 2
          for dim_2 in range(dim_1 + 1, pred.ndim):
              if self.normalize:
                  energy = (
                      energy
                      + 2
                      * (spatial_gradient(g, dim_2) * pred.shape[dim_2])
                      ** 2
                  )
              else:
                  energy = energy + 2 * spatial_gradient(g, dim_2) ** 2
  
      if self.reduction == LossReduction.MEAN.value:
          energy = torch.mean(energy)  # the batch and channel average
      elif self.reduction == LossReduction.SUM.value:
          energy = torch.sum(
              energy
          )  # sum over the batch and channel dims
      elif self.reduction != LossReduction.NONE.value:
          raise ValueError(
              f'Unsupported reduction: {self.reduction}, available options are ["mean", "sum", "none"].'
          )
  
      return energy
  
file_path: MONAI/monai/losses/deform.py
imports: from __future__ import annotations
  import torch
  from torch.nn.modules.loss import _Loss
  from monai.utils import LossReduction
label_desc: Use image node_id 2 for calling the BendingEnergyLoss obj's underlying member method code with example usage: obj.forward(pred) and returns: energy