void CurveEvalMediator
::evalDiscreteFuncElement(const DiscreteFuncElement* expr,
  const Array<MultiIndex>& multiIndices,
  Array<RCP<EvalVector> >& vec) const
{

	  int verbo = dfVerb();
	  Tabs tab1;
	  SUNDANCE_MSG2(verbo , tab1
	    << "CurveEvalMediator evaluating Discrete Function expr " << expr->toString());

	  const DiscreteFunctionData* f = DiscreteFunctionData::getData(expr);

	  TEUCHOS_TEST_FOR_EXCEPTION(f==0, std::logic_error,
	    "QuadratureEvalMediator::evalDiscreteFuncElement() called "
	    "with expr that is not a discrete function");

	  SUNDANCE_MSG2(verbo , tab1 << "After casting DiscreteFunctionData" << expr->toString());

	  RCP<Array<Array<double> > > localValues;
	  Array<int> cellLIDs_tmp(1);
	  Array<Point> phyPoints;
	  Array<Point> refPoints;
	  Array<Point> refDevs;
	  Array<Point> refNormal;
	  int nCells = cellLID()->size();

      RCP<const MapStructure> mapStruct;
	  int myIndex = expr->myIndex();
	  int nQuad = numQuadPtsForMaxCell_;
	  Array<int> k(multiIndices.size(),0);

	  Teuchos::BLAS<int,double> blas;

	  SUNDANCE_MSG2(verbo , tab1 << "After declaring BLAS: " << expr->toString());

	  // resize correctly the result vector
	  for (int i=0; i<multiIndices.size(); i++)
	  {
		  vec[i]->resize(nCells*nQuad);
	  }

	  // loop over each cell
	  for (int c=0; c<nCells; c++)
	  {
			int maxCellLID = (*cellLID())[c];
		    localValues = rcp(new Array<Array<double> >());
			SUNDANCE_MSG2(verbo , tab1 <<  "Cell:" << c <<  " of " << nCells << " , maxCellLID:" << maxCellLID );

			cellLIDs_tmp[0] = (*cellLID())[c];
			SUNDANCE_MSG2(verbo , tab1 <<  " Before calling f->getLocalValues:" << cellLIDs_tmp.size() <<
					" f==0 : " << (f==0) << " tmp:" << f->mesh().spatialDim());
			// - get local values from the DiscreteFunctionElementData
			mapStruct = f->getLocalValues(maxCellDim(), cellLIDs_tmp , *localValues);
			SUNDANCE_MSG2(verbo , tab1 <<  " After getting mapStruct:" << maxCellLID );
			SUNDANCE_MSG2(verbo , tab1 <<  " mapStruct->numBasisChunks():" << mapStruct->numBasisChunks() );
		    int chunk = mapStruct->chunkForFuncID(myIndex);
		    int funcIndex = mapStruct->indexForFuncID(myIndex);
		    int nFuncs = mapStruct->numFuncs(chunk);
			SUNDANCE_MSG2(verbo , tab1 <<  " chunk:" << chunk );
			SUNDANCE_MSG2(verbo , tab1 <<  " funcIndex:" << funcIndex );
			SUNDANCE_MSG2(verbo , tab1 <<  " nFuncs:" << nFuncs );

			// the chunk of the function
		    BasisFamily basis = rcp_dynamic_cast<BasisFamilyBase>(mapStruct->basis(chunk));
		    int nNodesTotal = basis.nReferenceDOFsWithFacets(maxCellType(), maxCellType());

			// - get intersection (reference)points from the mesh (if not existent than compute them)
			if ( mesh().hasCurvePoints( maxCellLID , paramcurve_.myID() ))
			{
				mesh().getCurvePoints( maxCellLID , paramcurve_.myID() , refPoints , refDevs , refNormal );
			}
			else // we have to calculate now the points
			{
				// calculate the intersection points
				CurveIntegralCalc::getCurveQuadPoints( maxCellType_ , maxCellLID , mesh() , paramcurve_ , quad_ ,
						refPoints, refDevs , refNormal);
				// store the intersection point in the mesh
				mesh().setCurvePoints( maxCellLID , paramcurve_.myID() , refPoints, refDevs , refNormal );
			}

			// loop over each multi-index
			SUNDANCE_MSG2(verbo , tab1 << " multiIndices.size()" << multiIndices.size() );
			for (int i=0; i<multiIndices.size(); i++)
			{

				int nDerivResults = 1;
				if ( multiIndices[i].order() == 1 ) nDerivResults = maxCellDim();

			    int pDir = 0;
			    int derivNum = 1;
				MultiIndex mi;
				SUNDANCE_MSG2(verbo , tab1 << " before asking anything i = " << i);
				SUNDANCE_MSG2(verbo , tab1 << " multiindex order : " << multiIndices[i].order());
				SUNDANCE_MSG2(verbo , tab1 << " multiindex : " << multiIndices[i] );
				if (multiIndices[i].order() > 0){
					pDir = multiIndices[i].firstOrderDirection();
					mi[pDir] = 1;
					derivNum = mesh().spatialDim();
				}

				Array<Array<double> > result(nQuad*derivNum);
				Array<Array<Array<double> > > tmp;

				int offs = nNodesTotal;

				// resize the result vector
				for (int deriv = 0 ; deriv < derivNum ; deriv++)
				{
                    // test weather we have to compute derivative
					if (multiIndices[i].order() > 0){
						// in case of derivatives we set one dimension
						MultiIndex mi_tmp;
						mi_tmp[deriv] = 1;
						SpatialDerivSpecifier deriv(mi_tmp);
						SUNDANCE_MSG2(verbo , tab1 << "computing derivatives : " << deriv << " on reference cell ");
						basis.refEval( maxCellType_ , refPoints , deriv, tmp , verbo );
					} else {
						SpatialDerivSpecifier deriv(mi);
						 // --- end eval basis functions
						SUNDANCE_MSG2(verbo , tab1 << "computing values reference cell ");
						basis.refEval( maxCellType_ , refPoints , deriv, tmp , verbo );
					}

					SUNDANCE_MSG2(verbo , tab1 << "resize result vector , offs:" << offs);
					for (int q=0; q<nQuad; q++){
						result[nQuad*deriv + q].resize(offs);
					}

				   	// copy the result in an other format
					SUNDANCE_MSG2(verbo , tab1 << "copy results ");
					int  offs1 = 0;
				    for (int q=0; q<nQuad; q++)
				    {
				    	offs1 = 0;
						for (int d=0; d<basis.dim(); d++)
						{
						   int nNodes = tmp[d][q].size();
					       for (int n=0; n<nNodes; n++ , offs1++ )
					       {
					          	result[nQuad*deriv + q][offs1] = tmp[d][q][n];
					       }
					    }
					}
				}// loop over all dimensional derivative

                // multiply the local results with the coefficients, (matrix vector OP)
				SUNDANCE_MSG2(verbo , tab1 << "summing up values , funcIndex:" << funcIndex << " offs:" << offs);
				for (int deriv = 0 ; deriv < derivNum ; deriv++)
				{
					for (int q=0; q<nQuad; q++)
					{
						double sum = 0.0;
						// sum over nodes
						for (int n = 0 ; n < offs ; n++){
							sum = sum + result[nQuad*deriv + q][n] * (*localValues)[chunk][funcIndex*offs + n];
						}
						// sum up the result in the 0th element
						result[nQuad*deriv + q][0] = sum;
					}
				}

			    // multiply the result if necesary with the inverse of the Jacobian
				const CellJacobianBatch& J = JTrans();
				if (mi.order()==1)
				{
					Tabs tab1;
					Tabs tab2;
				    SUNDANCE_MSG2(verbo, tab2 << "Jacobian batch nCells=" << J.numCells());
			        SUNDANCE_MSG2(verbo, tab2 << "Jacobian batch cell dim=" << J.cellDim());
			        SUNDANCE_MSG2(verbo, tab2 << "Jacobian batch spatial dim=" << J.spatialDim());
                    // we just multiply the derivative direction component
			        Array<double> invJ;
			        J.getInvJ(c, invJ);
					for (int q=0; q<nQuad; q++)
					{
						double sum = 0.0;
						for (int deriv = 0 ; deriv < derivNum ; deriv++)
						{
							// multiply one row from the J^{-T} matrix with the gradient vector
							sum = sum + result[nQuad*deriv + q][0] * invJ[derivNum*pDir + deriv];
						}
						// the resulting derivative on the physical cell in the "pDir" direction
						result[q][0] = sum;
					}
			    }

				// --- just copy the result to the "vec" back, the result should be in the  "result[q][0]" place----
				//SUNDANCE_MSG2(verbo , tab1 << "copy results back ");
				double* vecPtr = vec[i]->start();
				for (int q=0; q<nQuad; q++, k[i]++)
				{
					vecPtr[k[i]] = result[q][0];
				}
				SUNDANCE_MSG2(verbo , tab1 << " END copy results back ");
			} // --- end loop multiindex
			SUNDANCE_MSG2(verbo , tab1 << " END loop over multiindex ");
	}// --- end loop over cells
	SUNDANCE_MSG2(verbo , tab1 << " END loop over cells ");
}
ElementIntegral::ElementIntegral(int spatialDim,
                                 const CellType& maxCellType,
                                 int dim,
                                 const CellType& cellType,
                                 const BasisFamily& testBasis,
                                 int alpha,
                                 int testDerivOrder,
                                 bool isInternalBdry,
                                 const ParametrizedCurve& globalCurve,
                                 const Mesh& mesh,
                                 int verb)
    : setupVerb_(verb),
      integrationVerb_(0),
      transformVerb_(0),
      spatialDim_(spatialDim),
      dim_(dim),
      isInternalBdry_(isInternalBdry),
      nFacetCases_(1),
      testDerivOrder_(testDerivOrder),
      nRefDerivTest_(ipow(spatialDim, testDerivOrder)),
      nNodesTest_(testBasis.nReferenceDOFsWithFacets(maxCellType, cellType)),
      unkDerivOrder_(-1),
      nRefDerivUnk_(-1),
      nNodesUnk_(-1),
      nNodes_(nNodesTest_),
      order_(1),
      alpha_(alpha),
      beta_(-1),
      cellType_(cellType),
      maxCellType_(maxCellType),
      evalCellType_(cellType),
      testBasis_(testBasis),
      unkBasis_(),
      globalCurve_(globalCurve),
      mesh_(mesh)
{
    Tabs tab0(0);
    SUNDANCE_MSG2(setupVerb(), tab0 << "constructing 1-form ElementIntegral");
    /* if we're integrating a derivative along a facet, we
     * may need to refer back to the maximal cell. */
    bool okToRestrictTestToBdry = basisRestrictableToBoundary(testBasis);

    Tabs tab1;
    SUNDANCE_MSG2(setupVerb(), tab1 << "dim=" << dim << " spatialDim=" << spatialDim);
    if (dim != spatialDim)
    {
        if (isInternalBdry)
        {
            TEST_FOR_EXCEPT(!okToRestrictTestToBdry);
        }
        if (alwaysUseCofacets() || testDerivOrder>0)
        {
            Tabs tab2;
            evalCellType_ = maxCellType_;
            nFacetCases_ = numFacets(maxCellType, dim);
            nNodesTest_ = testBasis.nReferenceDOFsWithFacets(maxCellType, maxCellType);
            SUNDANCE_MSG2(setupVerb(), tab2 << "nNodesTest=" << nNodesTest_);
            nNodes_ = nNodesTest_;
            TEST_FOR_EXCEPT(nNodes_ == 0);
        }
        else
        {
            TEST_FOR_EXCEPT(!okToRestrictTestToBdry);
        }
    }

    SUNDANCE_MSG2(setupVerb(), tab1 << "nNodes=" << nNodes_);
}