ResultType evaluate(
            const ConstGeometricalDataSlice<CoordinateType>& /* testGeomData */,
            const ConstGeometricalDataSlice<CoordinateType>& /* trialGeomData */,
            const CollectionOf1dSlicesOfConst3dArrays<BasisFunctionType>& testValues,
            const CollectionOf1dSlicesOfConst3dArrays<BasisFunctionType>& trialValues,
            const CollectionOf2dSlicesOfConstNdArrays<KernelType>& kernelValues) const {
        // Assert that there is at least one scalar-valued kernel
        assert(kernelValues.size() >= 1);
        assert(kernelValues[0].extent(0) == 1);
        assert(kernelValues[0].extent(1) == 1);

        // Assert that there is at least one test and trial transformation
        // and that their dimensions agree
        assert(testValues.size() >= 1);
        assert(trialValues.size() >= 1);
        const size_t transCount = testValues.size();
        assert(trialValues.size() == transCount);
        if (kernelValues.size() > 1)
            assert(kernelValues.size() == transCount);

        ResultType result = 0.;
        for (size_t transIndex = 0; transIndex < transCount; ++transIndex) {
            const size_t transDim = testValues[transIndex].extent(0);
            assert(trialValues[transIndex].extent(0) == transDim);
            BasisFunctionType dotProduct = 0.;
            for (size_t dim = 0; dim < transDim; ++dim)
                dotProduct += conjugate(testValues[transIndex](dim)) *
                        trialValues[transIndex](dim);
            if (transCount == 1)
                result += dotProduct * kernelValues[0](0, 0);
            else
                result += dotProduct * kernelValues[transIndex](0, 0);
        }
        return result;
    }
  ResultType
  evaluate(const ConstGeometricalDataSlice<CoordinateType> &testGeomData,
           const ConstGeometricalDataSlice<CoordinateType> &trialGeomData,
           const CollectionOf1dSlicesOfConst3dArrays<BasisFunctionType>
               &testTransfValues,
           const CollectionOf1dSlicesOfConst3dArrays<BasisFunctionType>
               &trialTransfValues,
           const CollectionOf2dSlicesOfConstNdArrays<KernelType> &kernelValues)
      const {
    const int dimWorld = 3;

    // Assert that there are at least two scalar-valued kernels
    assert(kernelValues.size() >= 2);
    assert(kernelValues[0].extent(0) == 1);
    assert(kernelValues[0].extent(1) == 1);
    assert(kernelValues[1].extent(0) == 1);
    assert(kernelValues[1].extent(1) == 1);

    // Assert that there are at least two test and trial transformations
    // (function value and surface div) of correct dimensions
    assert(testTransfValues.size() >= 2);
    assert(trialTransfValues.size() >= 2);
    _1dSliceOfConst3dArray<BasisFunctionType> testValues = testTransfValues[0];
    _1dSliceOfConst3dArray<BasisFunctionType> trialValues =
        trialTransfValues[0];
    _1dSliceOfConst3dArray<BasisFunctionType> testSurfaceDivs =
        testTransfValues[1];
    _1dSliceOfConst3dArray<BasisFunctionType> trialSurfaceDivs =
        trialTransfValues[1];
    assert(testValues.extent(0) == 3);
    assert(trialValues.extent(0) == 3);
    assert(testSurfaceDivs.extent(0) == 1);
    assert(trialSurfaceDivs.extent(0) == 1);

    // Let K_0(x, y) = kappa * K(x, y) and K_1(x, y) = K(x, y) / kappa.
    // Return
    // K_0(x, y) u*(x) . v(y) + K_1(x, y) div u*(x) div v(y)

    BasisFunctionType sum = 0.;
    for (int dim = 0; dim < dimWorld; ++dim)
      sum += conjugate(testValues(dim)) * trialValues(dim);
    ResultType term_0 = sum * kernelValues[0](0, 0);
    ResultType term_1 = (conjugate(testSurfaceDivs(0)) * trialSurfaceDivs(0)) *
                        kernelValues[1](0, 0);
    return term_0 + term_1;
  }