// Real part is only defined for real derivative components
      static FadType real(const FadType& x) { 
#ifdef TEUCHOS_DEBUG
	TEST_FOR_EXCEPTION(is_fad_real(x) == false, std::runtime_error,
			   "Real component is not a differentiable "
			   "function of complex inputs.");
#endif
	FadType y = x;
	y.val() = Teuchos::ScalarTraits<ValueT>::real(x.val());
	return y;
      }
      static bool isnaninf(const FadType& x) { 
	if (Teuchos::ScalarTraits<ValueT>::isnaninf(x.val()))
	  return true;
	for (int i=0; i<x.size(); i++)
	  if (Teuchos::ScalarTraits<ValueT>::isnaninf(x.dx(i)))
	    return true;
	return false;
      }
      // Imaginary part is only defined for real derivative components
      static FadType imag(const FadType& x) { 
#ifdef TEUCHOS_DEBUG
	TEST_FOR_EXCEPTION(is_fad_real(x) == false, std::runtime_error,
			   "Imaginary component is not a differentiable "
			   "function of complex inputs.");
#endif
	return FadType(Teuchos::ScalarTraits<ValueT>::imag(x.val()));
      }
      // Helper function to determine whether a Fad type is real
      static bool is_fad_real(const FadType& x) {
	if (x.size() == 0)
	  return true;
	if (Teuchos::ScalarTraits<ValueT>::isComplex) {
	  if (!is_complex_real(x.val()))
	    return false;
	  for (int i=0; i<x.size(); i++)
	    if (!is_complex_real(x.fastAccessDx(i)))
	      return false;
	}
	return true;
      }
      static magnitudeType magnitude(const FadType& a) {
#ifdef TEUCHOS_DEBUG
	TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
	  a, "Error, the input value to magnitude(...) a = " << a << 
	  " can not be NaN!" );
	TEST_FOR_EXCEPTION(is_fad_real(a) == false, std::runtime_error,
			   "Complex magnitude is not a differentiable "
			   "function of complex inputs.");
#endif
	//return std::fabs(a); 
	magnitudeType b(a.size(), 
			Teuchos::ScalarTraits<ValueT>::magnitude(a.val()));
	if (Teuchos::ScalarTraits<ValueT>::real(a.val()) >= 0)
	  for (int i=0; i<a.size(); i++)
	    b.fastAccessDx(i) = 
	      Teuchos::ScalarTraits<ValueT>::magnitude(a.fastAccessDx(i));
	else
	  for (int i=0; i<a.size(); i++)
	    b.fastAccessDx(i) = 
	      -Teuchos::ScalarTraits<ValueT>::magnitude(a.fastAccessDx(i));
	return b;
      }
TEUCHOS_UNIT_TEST_TEMPLATE_3_DECL(
  Kokkos_View_Fad, UnmanagedConst, FadType, Layout, Device )
{
  typedef typename FadType::value_type scalar_type;
  typedef typename ApplyView<scalar_type***,Layout,Device>::type ViewType;
  typedef typename ApplyView<const scalar_type***,Layout,Device>::type ConstViewType;
  typedef typename ApplyView<FadType**,Layout,Device,Kokkos::MemoryUnmanaged>::type FadViewType;
  typedef typename ApplyView<const FadType**,Layout,Device,Kokkos::MemoryUnmanaged>::type ConstFadViewType;
  typedef typename ViewType::size_type size_type;
  typedef typename ViewType::HostMirror host_view_type;
  typedef typename FadViewType::HostMirror fad_host_view_type;

  const size_type num_rows = global_num_rows;
  const size_type num_cols = global_num_cols;
  const size_type fad_size = global_fad_size;

  // Create and fill view
  ViewType v("view", num_rows, num_cols, fad_size+1);
  host_view_type h_v = Kokkos::create_mirror_view(v);
  for (size_type i=0; i<num_rows; ++i) {
    for (size_type j=0; j<num_cols; ++j) {
      FadType f = generate_fad<FadType>(num_rows, num_cols, fad_size, i, j);
      for (size_type k=0; k<fad_size; k++)
        h_v(i,j,k) = f.dx(k);
      h_v(i,j,fad_size) = f.val();
    }
  }
  Kokkos::deep_copy(v, h_v);
  ConstViewType v_const = v;

  // Create unmanaged view
  ConstFadViewType v_fad(
    v_const.ptr_on_device(), num_rows, num_cols, fad_size+1);

  // Copy back -- can't use create_mirror_view() because v_fad is unmanaged
  fad_host_view_type h_v_fad("host_view_fad", num_rows, num_cols, fad_size+1);
  Kokkos::deep_copy(h_v_fad, v_fad);

  // Check
  success = true;
  for (size_type i=0; i<num_rows; ++i) {
    for (size_type j=0; j<num_cols; ++j) {
      FadType f = generate_fad<FadType>(num_rows, num_cols, fad_size, i, j);
      success = success && checkFads(f, h_v_fad(i,j), out);
    }
  }
}
TEUCHOS_UNIT_TEST_TEMPLATE_3_DECL(
  Kokkos_View_Fad, DeepCopy_ConstantFad, FadType, Layout, Device )
{
  typedef typename ApplyView<FadType**,Layout,Device>::type ViewType;
  typedef typename ViewType::size_type size_type;
  typedef typename ViewType::HostMirror host_view_type;

  const size_type num_rows = global_num_rows;
  const size_type num_cols = global_num_cols;
  const size_type fad_size = global_fad_size;

  // Create and fill view
  ViewType v("view", num_rows, num_cols, fad_size+1);
  typename ViewType::array_type va = v;
  Kokkos::deep_copy( va, 1.0 );

  // Deep copy a constant scalar
  FadType a = 2.3456;
  Kokkos::deep_copy( v, a );

  // Copy to host
  host_view_type hv = Kokkos::create_mirror_view(v);
  Kokkos::deep_copy(hv, v);

  // Check
  success = true;
  for (size_type i=0; i<num_rows; ++i) {
    for (size_type j=0; j<num_cols; ++j) {
#if defined(HAVE_SACADO_VIEW_SPEC) && !defined(SACADO_DISABLE_FAD_VIEW_SPEC)
      FadType f = FadType(fad_size, a.val());
#else
      FadType f = a;
#endif
      success = success && checkFads(f, hv(i,j), out);
    }
  }
}