void
DefaultDoubleQuadratureRuleFamily<CoordinateType>::
fillQuadraturePointsAndWeights(
        const DoubleQuadratureDescriptor& desc,
        arma::Mat<CoordinateType>& testPoints,
        arma::Mat<CoordinateType>& trialPoints,
        std::vector<CoordinateType>& testWeights,
        std::vector<CoordinateType>& trialWeights,
        bool& isTensor) const
{
    const ElementPairTopology& topology = desc.topology;
    if (topology.type == ElementPairTopology::Disjoint) {
        // Create a tensor rule
        fillSingleQuadraturePointsAndWeights(topology.testVertexCount,
                                             desc.testOrder,
                                             testPoints, testWeights);
        fillSingleQuadraturePointsAndWeights(topology.trialVertexCount,
                                             desc.trialOrder,
                                             trialPoints, trialWeights);
        isTensor = true;
    } else {
        // Create a non-tensor rule, leaving trialWeights empty
        fillDoubleSingularQuadraturePointsAndWeights(
            desc, testPoints, trialPoints, testWeights);
        trialWeights.clear();
        isTensor = false;
    }
}
void DefaultSingleQuadratureRuleFamily<CoordinateType>::
    fillQuadraturePointsAndWeights(const SingleQuadratureDescriptor &desc,
                                   arma::Mat<CoordinateType> &points,
                                   std::vector<CoordinateType> &weights) const {
  fillSingleQuadraturePointsAndWeights(desc.vertexCount, desc.order, points,
                                       weights);
}
void DefaultEvaluatorForIntegralOperators<BasisFunctionType, KernelType,
ResultType, GeometryFactory>::calcTrialData(
        Region region,
        int kernelTrialGeomDeps,
        GeometricalData<CoordinateType>& trialGeomData,
        CollectionOf2dArrays<ResultType>& trialTransfValues,
        std::vector<CoordinateType>& weights) const
{
    const int elementCount = m_rawGeometry->elementCount();
    const int worldDim = m_rawGeometry->worldDimension();
    const int gridDim = m_rawGeometry->gridDimension();
    const int transformationCount = m_trialTransformations->transformationCount();

    // Find out which basis data need to be calculated
    size_t basisDeps = 0;
    // Find out which geometrical data need to be calculated, in addition
    // to those needed by the kernel
    size_t trialGeomDeps = kernelTrialGeomDeps;
    m_trialTransformations->addDependencies(basisDeps, trialGeomDeps);
    trialGeomDeps |= INTEGRATION_ELEMENTS;

    // Initialise the geometry factory
    typedef typename GeometryFactory::Geometry Geometry;
    std::auto_ptr<Geometry> geometry(m_geometryFactory->make());

    // Find all unique trial bases
    // Set of unique quadrature variants
    typedef std::set<const Basis<BasisFunctionType>*> BasisSet;
    BasisSet uniqueTrialBases(m_trialBases->begin(), m_trialBases->end());

    // Initialise temporary (per-element) data containers
    std::vector<GeometricalData<CoordinateType> > geomDataPerElement(elementCount);
    std::vector<CollectionOf2dArrays<ResultType> >
            trialTransfValuesPerElement(elementCount);
    std::vector<std::vector<CoordinateType> > weightsPerElement(elementCount);

    int quadPointCount = 0; // Quadrature point counter

    for (typename BasisSet::const_iterator it = uniqueTrialBases.begin();
         it != uniqueTrialBases.end(); ++it)
    {
        const Basis<BasisFunctionType>& activeBasis = *(*it);
        int order = quadOrder(activeBasis, region);

        // Find out the element type
        int elementCornerCount = 0;
        for (int e = 0; e < elementCount; ++e)
            if ((*m_trialBases)[e] == &activeBasis)
            {
                // elementCornerCount = m_rawGeometry->elementCornerCount(e);
                // This implementation prevents a segmentation fault on Macs
                // when compiled with llvm in 64-bit mode with -O2 or -O3
                const arma::Mat<int>& elementCornerIndices =
                    m_rawGeometry->elementCornerIndices();
                for (size_t i = 0; i < elementCornerIndices.n_rows; ++i)
                    if (elementCornerIndices(i, e) >= 0)
                        elementCornerCount = i + 1;
                    else
                        break;

                break;
            }

        // Get quadrature points and weights
        arma::Mat<CoordinateType> localQuadPoints;
        std::vector<CoordinateType> quadWeights;
        fillSingleQuadraturePointsAndWeights(
                    elementCornerCount, order, localQuadPoints, quadWeights);

        // Get basis data
        BasisData<BasisFunctionType> basisData;
        activeBasis.evaluate(basisDeps, localQuadPoints, ALL_DOFS, basisData);

        BasisData<ResultType> argumentData;
        if (basisDeps & VALUES)
            argumentData.values.set_size(basisData.values.extent(0),
                                         1, // just one function
                                         basisData.values.extent(2));
        if (basisDeps & DERIVATIVES)
            argumentData.derivatives.set_size(basisData.derivatives.extent(0),
                                              basisData.derivatives.extent(1),
                                              1, // just one function
                                              basisData.derivatives.extent(3));

        // Loop over elements and process those that use the active basis
        CollectionOf3dArrays<ResultType> trialValues;
        for (int e = 0; e < elementCount; ++e)
        {
            if ((*m_trialBases)[e] != &activeBasis)
                continue;

            // Local coefficients of the argument in the current element
            const std::vector<ResultType>& localCoefficients =
                    (*m_argumentLocalCoefficients)[e];

            // Calculate the argument function's values and/or derivatives
            // at quadrature points in the current element
            if (basisDeps & VALUES)
            {
                std::fill(argumentData.values.begin(),
                          argumentData.values.end(), 0.);
                for (size_t point = 0; point < basisData.values.extent(2); ++point)
                    for (size_t dim = 0; dim < basisData.values.extent(0); ++dim)
                        for (size_t fun = 0; fun < basisData.values.extent(1); ++fun)
                            argumentData.values(dim, 0, point) +=
                                    basisData.values(dim, fun, point) *
                                    localCoefficients[fun];
            }
            if (basisDeps & DERIVATIVES)
            {
                std::fill(argumentData.derivatives.begin(),
                          argumentData.derivatives.end(), 0.);
                for (size_t point = 0; point < basisData.derivatives.extent(3); ++point)
                    for (size_t dim = 0; dim < basisData.derivatives.extent(1); ++dim)
                        for (size_t comp = 0; comp < basisData.derivatives.extent(0); ++comp)
                            for (size_t fun = 0; fun < basisData.derivatives.extent(2); ++fun)
                                argumentData.derivatives(comp, dim, 0, point) +=
                                    basisData.derivatives(comp, dim, fun, point) *
                                    localCoefficients[fun];
            }

            // Get geometrical data
            m_rawGeometry->setupGeometry(e, *geometry);
            geometry->getData(trialGeomDeps, localQuadPoints,
                              geomDataPerElement[e]);

            m_trialTransformations->evaluate(argumentData, geomDataPerElement[e],
                                             trialValues);

//            weightedTrialTransfValuesPerElement[e].set_size(transformationCount);
//            for (int transf = 0; transf < transformationCount; ++transf)
//            {
//                const size_t dimCount = trialValues[transf].extent(0);
//                const size_t quadPointCount = trialValues[transf].extent(2);
//                weightedTrialTransfValuesPerElement[e][transf].set_size(
//                            dimCount, quadPointCount);
//                for (size_t point = 0; point < quadPointCount; ++point)
//                    for (size_t dim = 0; dim < dimCount; ++dim)
//                        weightedTrialTransfValuesPerElement[e][transf](dim, point) =
//                                trialValues[transf](dim, 0, point) *
//                                geomDataPerElement[e].integrationElements(point) *
//                                quadWeights[point];
//            } // end of loop over transformations

            const size_t localQuadPointCount = quadWeights.size();

            trialTransfValuesPerElement[e].set_size(transformationCount);
            for (int transf = 0; transf < transformationCount; ++transf)
            {
                const size_t dimCount = trialValues[transf].extent(0);
                assert(trialValues[transf].extent(2) == localQuadPointCount);
                trialTransfValuesPerElement[e][transf].set_size(
                            dimCount, localQuadPointCount);
                for (size_t point = 0; point < localQuadPointCount; ++point)
                    for (size_t dim = 0; dim < dimCount; ++dim)
                        trialTransfValuesPerElement[e][transf](dim, point) =
                                trialValues[transf](dim, 0, point);
            } // end of loop over transformations

            weightsPerElement[e].resize(localQuadPointCount);
            for (size_t point = 0; point < localQuadPointCount; ++point)
                weightsPerElement[e][point] = quadWeights[point] *
                        geomDataPerElement[e].integrationElements(point);

            quadPointCount += quadWeights.size();
        } // end of loop over elements
    } // end of loop over unique bases

    // In the following, weightedTrialExprValuesPerElement[e][transf].extent(1) is used
    // repeatedly as the number of quadrature points in e'th element

    // Now convert std::vectors of arrays into unique big arrays
    // and store them in trialGeomData and weightedTrialTransfValues

    // Fill member matrices of trialGeomData
    if (kernelTrialGeomDeps & GLOBALS)
        trialGeomData.globals.set_size(worldDim, quadPointCount);
    if (kernelTrialGeomDeps & INTEGRATION_ELEMENTS)
        trialGeomData.integrationElements.set_size(quadPointCount);
    if (kernelTrialGeomDeps & NORMALS)
        trialGeomData.normals.set_size(worldDim, quadPointCount);
    if (kernelTrialGeomDeps & JACOBIANS_TRANSPOSED)
        trialGeomData.jacobiansTransposed.set_size(gridDim, worldDim, quadPointCount);
    if (kernelTrialGeomDeps & JACOBIAN_INVERSES_TRANSPOSED)
        trialGeomData.jacobianInversesTransposed.set_size(worldDim, gridDim, quadPointCount);
//    weightedTrialTransfValues.set_size(transformationCount);
//    for (int transf = 0; transf < transformationCount; ++transf)
//        weightedTrialTransfValues[transf].set_size(
//                    m_trialTransformations->resultDimension(transf), quadPointCount);
    trialTransfValues.set_size(transformationCount);
    for (int transf = 0; transf < transformationCount; ++transf)
        trialTransfValues[transf].set_size(
                    m_trialTransformations->resultDimension(transf), quadPointCount);
    weights.resize(quadPointCount);

    for (int e = 0, startCol = 0;
         e < elementCount;
         startCol += trialTransfValuesPerElement[e][0].extent(1), ++e)
    {
        int endCol = startCol + trialTransfValuesPerElement[e][0].extent(1) - 1;
        if (kernelTrialGeomDeps & GLOBALS)
            trialGeomData.globals.cols(startCol, endCol) =
                    geomDataPerElement[e].globals;
        if (kernelTrialGeomDeps & INTEGRATION_ELEMENTS)
            trialGeomData.integrationElements.cols(startCol, endCol) =
                    geomDataPerElement[e].integrationElements;
        if (kernelTrialGeomDeps & NORMALS)
            trialGeomData.normals.cols(startCol, endCol) =
                    geomDataPerElement[e].normals;
        if (kernelTrialGeomDeps & JACOBIANS_TRANSPOSED)
            trialGeomData.jacobiansTransposed.slices(startCol, endCol) =
                    geomDataPerElement[e].jacobiansTransposed;
        if (kernelTrialGeomDeps & JACOBIAN_INVERSES_TRANSPOSED)
            trialGeomData.jacobianInversesTransposed.slices(startCol, endCol) =
                    geomDataPerElement[e].jacobianInversesTransposed;
        for (int transf = 0; transf < transformationCount; ++transf)
            for (size_t point = 0; point < trialTransfValuesPerElement[e][transf].extent(1); ++point)
                for (size_t dim = 0; dim < trialTransfValuesPerElement[e][transf].extent(0); ++dim)
                    trialTransfValues[transf](dim, startCol + point) =
                            trialTransfValuesPerElement[e][transf](dim, point);
        for (size_t point = 0; point < trialTransfValuesPerElement[e][0].extent(1); ++point)
                weights[startCol + point] = weightsPerElement[e][point];
    }
}