template <typename T>
metric_t<T> calculate_metric(const cGH *const cctkGH,
const coords_t<T> &coords) {
const geom_t &geom = coords.geom;
metric_t<T> metric(geom);
#pragma omp simd
for (int n = 0; n < geom.npoints; ++n) {
const T x0 = 0.0;
const T y0 = 0.0;
const T z0 = 0.0;
const T M = 1.0;
using U = vect<T, 3>;
using DT = dual<T, U>;
const DT x{coords.x.data()[n], {1, 0, 0}};
const DT y{coords.y.data()[n], {0, 1, 0}};
const DT z{coords.z.data()[n], {0, 0, 1}};
const DT r = sqrt(pow(x - x0, 2) + pow(y - y0, 2) + pow(z - z0, 2));
const DT psi = pow(1 + M / (2 * r), 4);
metric.gxx.data()[n] = psi.val;
metric.gxy.data()[n] = 0;
metric.gxz.data()[n] = 0;
metric.gyy.data()[n] = psi.val;
metric.gyz.data()[n] = 0;
metric.gzz.data()[n] = psi.val;
metric.gxx_x.data()[n] = psi.eps[0];
metric.gxy_x.data()[n] = 0;
metric.gxz_x.data()[n] = 0;
metric.gyy_x.data()[n] = psi.eps[0];
metric.gyz_x.data()[n] = 0;
metric.gzz_x.data()[n] = psi.eps[0];
metric.gxx_y.data()[n] = psi.eps[1];
metric.gxy_y.data()[n] = 0;
metric.gxz_y.data()[n] = 0;
metric.gyy_y.data()[n] = psi.eps[1];
metric.gyz_y.data()[n] = 0;
metric.gzz_y.data()[n] = psi.eps[1];
metric.gxx_z.data()[n] = psi.eps[2];
metric.gxy_z.data()[n] = 0;
metric.gxz_z.data()[n] = 0;
metric.gyy_z.data()[n] = psi.eps[2];
metric.gyz_z.data()[n] = 0;
metric.gzz_z.data()[n] = psi.eps[2];
metric.kxx.data()[n] = 0;
metric.kxy.data()[n] = 0;
metric.kxz.data()[n] = 0;
metric.kyy.data()[n] = 0;
metric.kyz.data()[n] = 0;
metric.kzz.data()[n] = 0;
}