docstr: Test CUDA implementation for PointFaceArrayDistanceForward
      &  PointFaceArrayDistanceBackward
docstr_tok: ["Test","CUDA","implementation","for","PointFaceArrayDistanceForward","&","PointFaceArrayDistanceBackward"]
code: def test_point_face_array_distance(self):
      """
      Test CUDA implementation for PointFaceArrayDistanceForward
          &  PointFaceArrayDistanceBackward
      """
      P, T = 16, 32
      device = get_random_cuda_device()
      points = torch.rand((P, 3), dtype=torch.float32, device=device)
      tris = torch.rand((T, 3, 3), dtype=torch.float32, device=device)
      points_cpu = points.clone().cpu()
      tris_cpu = tris.clone().cpu()
  
      points.requires_grad = True
      tris.requires_grad = True
      grad_dists = torch.rand(
          (P, T), dtype=torch.float32, device=device
      )
  
      points_temp = points.clone().detach()
      points_temp.requires_grad = True
      tris_temp = tris.clone().detach()
      tris_temp.requires_grad = True
  
      # Naive python implementation
      dists_naive = torch.zeros(
          (P, T), dtype=torch.float32, device=device
      )
      for p in range(P):
          for t in range(T):
              dist = self._point_to_tri_distance(points[p], tris[t])
              dists_naive[p, t] = dist
  
      # Naive Backward
      dists_naive.backward(grad_dists)
      grad_points_naive = points.grad.cpu()
      grad_tris_naive = tris.grad.cpu()
  
      # Cuda Forward Implementation
      dists_cuda = _C.point_face_array_dist_forward(
          points, tris, TestPointMeshDistance.min_triangle_area()
      )
      dists_cpu = _C.point_face_array_dist_forward(
          points_cpu,
          tris_cpu,
          TestPointMeshDistance.min_triangle_area(),
      )
  
      # Compare
      self.assertClose(dists_naive.cpu(), dists_cuda.cpu())
      self.assertClose(dists_naive.cpu(), dists_cpu)
  
      # CUDA Backward Implementation
      (
          grad_points_cuda,
          grad_tris_cuda,
      ) = _C.point_face_array_dist_backward(
          points,
          tris,
          grad_dists,
          TestPointMeshDistance.min_triangle_area(),
      )
      (
          grad_points_cpu,
          grad_tris_cpu,
      ) = _C.point_face_array_dist_backward(
          points_cpu,
          tris_cpu,
          grad_dists.cpu(),
          TestPointMeshDistance.min_triangle_area(),
      )
  
      # Compare
      self.assertClose(grad_points_naive, grad_points_cuda.cpu())
      self.assertClose(grad_tris_naive, grad_tris_cuda.cpu(), atol=5e-6)
      self.assertClose(grad_points_naive, grad_points_cpu)
      self.assertClose(grad_tris_naive, grad_tris_cpu, atol=5e-6)
  
imports: import unittest
  import numpy
  import torch
  from pytorch3d import _C
  from pytorch3d.loss import point_mesh_edge_distance, point_mesh_face_distance
  from pytorch3d.structures import Meshes, packed_to_list, Pointclouds
  from .common_testing import get_random_cuda_device, TestCaseMixin
label_desc: Use image node_id 13 for calling the TestPointMeshDistance obj's underlying member method code with example usage: obj.test_point_face_array_distance() without return types