Example #1
0
Set<MultipleDeriv> DiffOp::internalFindW(int order, const EvalContext& context) const
{
  Tabs tabs(0);
  int verb = context.setupVerbosity();

  SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindW(order="
    << order << ") for " << toString());

  Set<MultipleDeriv> rtn ;
  if (order <= 2)
  {
    Tabs tab1;
    const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context);
    const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
    const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context);

    SUNDANCE_MSG5(verb, tab1 << "W1 = " << W1);
    SUNDANCE_MSG5(verb, tab1 << "WArg = " << WArg);
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus);
    Set<MultipleDeriv> Tx = applyTx(WArg, mi_);
    Set<MultipleDeriv> ZXx = applyZx(W1, mi_).setUnion(Xx(mi_));
    SUNDANCE_MSG5(verb, tab1 << "Tx(Warg) = " << Tx);
    SUNDANCE_MSG5(verb, tab1 << "ZXx(W1) = " << ZXx);
    Set<MultipleDeriv> WargPlusOslashZXx = setDivision(WArgPlus, ZXx);
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus / ZXx = " 
      << WargPlusOslashZXx);
    rtn = WargPlusOslashZXx.setUnion(Tx); 
  }
  SUNDANCE_MSG3(verb, tabs << "W[" << order << "]=" << rtn);
  SUNDANCE_MSG3(verb, tabs << "done with DiffOp::internalFindW(" << order << ") for "
    << toString());

  return rtn;
}
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement
::internalFindC(int order, const EvalContext& context) const
{
  Tabs tabs(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tabs << "ExplicitFunctionalDerivativeElement::internalFindC() for " 
    << toString());
  Set<MultipleDeriv> rtn ;
  if (order < 3) 
  {
    Tabs tab1;
    SUNDANCE_MSG5(verb, tab1 << "finding R");
    const Set<MultipleDeriv>& R = findR(order, context);
    SUNDANCE_MSG5(verb, tab1 << "R=" << R);

    SUNDANCE_MSG5(verb, tab1 << "finding C for arg");
    const Set<MultipleDeriv>& argC 
      = evaluatableArg()->findC(order+1, context);
    SUNDANCE_MSG5(verb, tab1 << "argC=" << argC);

    MultipleDeriv me(fd_);
    Set<MultipleDeriv> tmp = setDivision(argC, makeSet(me));
    rtn = tmp.intersection(R);
  }

  SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=" << rtn);
  SUNDANCE_MSG2(verb, tabs << "done with ExplicitFunctionalDerivativeElement::internalFindC for "
    << toString());
  return rtn;
}
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement
::internalFindW(int order, const EvalContext& context) const
{
  Tabs tab0(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tab0 
    << "ExplicitFunctionalDerivativeElement::internalFindW(order="
    << order << ") for " << toString());


  Set<MultipleDeriv> rtn ;

  if (order < 3)
  {
    Tabs tab1;
    const Set<MultipleDeriv>& WArgPlus 
      = evaluatableArg()->findW(order+1, context);
    
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus = " << WArgPlus);
    MultipleDeriv me(fd_);
    Set<MultipleDeriv> WargPlusOslashFD = setDivision(WArgPlus, makeSet(me));
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus / fd = " 
      << WargPlusOslashFD);
    rtn = WargPlusOslashFD;
  }
  SUNDANCE_MSG2(verb, tab0 << "W[" << order << "]=" << rtn);
  SUNDANCE_MSG2(verb, tab0 << "done with ExplicitFunctionalDerivativeElement::internalFindW(" << order << ") for "
                     << toString());

  return rtn;
}
Example #4
0
Set<MultipleDeriv> DiffOp::internalFindC(int order, const EvalContext& context) const
{
  Tabs tabs(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindC() for " 
    << toString());
  Set<MultipleDeriv> rtn ;

  {
    Tabs tab1;
    SUNDANCE_MSG5(verb, tab1 << "finding R");
    const Set<MultipleDeriv>& R = findR(order, context);
    SUNDANCE_MSG5(verb, tab1 << "finding V");
    const Set<MultipleDeriv>& V = findV(order, context);
    /** Call findC() to ensure that the argument has C tabulated */
    evaluatableArg()->findC(order, context);

    SUNDANCE_MSG5(verb, tab1 << "R=" << R);
    SUNDANCE_MSG5(verb, tab1 << "V=" << V);
    rtn = R.setDifference(V);
    SUNDANCE_MSG3(verb, tabs << "C[" << order << "]=" << rtn);
  }

  SUNDANCE_MSG2(verb, tabs << "C[" << order << "]=R\\V = " << rtn);
  SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindC for "
    << toString());
  return rtn;
}
Example #5
0
void DiffOp::requestMultiIndexAtEvalPoint(const MultiIndex& mi,
  const MultipleDeriv& u,
  const EvalContext& context) const 
{
  int verb = context.setupVerbosity();
  Tabs tab0(0);
  SUNDANCE_MSG3(verb, tab0 << "DiffOp::requestMultiIndexAtEvalPoint() for=" << toString());
  TEUCHOS_TEST_FOR_EXCEPT(u.size() != 1);
  const Deriv& d = *(u.begin());

  if (d.isFunctionalDeriv())
  {
    const SpatialDerivSpecifier& sds = d.opOnFunc();

    TEUCHOS_TEST_FOR_EXCEPTION(sds.isDivergence(), std::logic_error,
      "divergence operators not possible within DiffOp");
    TEUCHOS_TEST_FOR_EXCEPTION(sds.isNormal(), std::logic_error,
      "normal deriv operators not possible within DiffOp");

    const MultiIndex& newMi = sds.mi();

    const SymbolicFuncElement* sfe = d.symbFuncElem();
    TEUCHOS_TEST_FOR_EXCEPT(sfe == 0);
    const EvaluatableExpr* evalPt = sfe->evalPt();
    const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt);
    if (z != 0) return;
    const DiscreteFuncElement* df 
      = dynamic_cast<const DiscreteFuncElement*>(evalPt);
    df->addMultiIndex(newMi);
    df->findW(1, context);
    df->findV(1, context);
    df->findC(1, context);
  }
}
Set<MultiSet<int> > ProductExpr::internalFindQ_V(int order, const EvalContext& context) const
{
  Tabs tab0(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tab0 << "ProdExpr::internalFindQ_V(" << order << ")");

  Set<MultiSet<int> > rtn;
  if (order > 1) return rtn;

  const Set<MultipleDeriv>& vLeft 
    = leftEvaluatable()->findV(0, context);
  const Set<MultipleDeriv>& vRight
    = rightEvaluatable()->findV(0, context);

  if (order==0)
  {
    if (vLeft.size() > 0)
    {
      rtn.put(makeMultiSet<int>(0));
    }
    if (vRight.size() > 0)
    {
      rtn.put(makeMultiSet<int>(1));
    }
  }

  if (order==1)
  {
    if (vLeft.size() > 0) rtn.put(makeMultiSet<int>(1));
    if (vRight.size() > 0) rtn.put(makeMultiSet<int>(0));
  }

  SUNDANCE_MSG2(verb, tab0 << "Q_V[" << order << "]=" << rtn);  
  return rtn;
}
Set<MultipleDeriv> 
ConstantExpr::internalFindC(int order, const EvalContext& context) const
{
  Tabs tab;
  SUNDANCE_MSG2(context.setupVerbosity(), 
    tab << "ConstantExpr::internalFindC is forwarding to findR()");
  return findR(order, context);
}
Set<MultipleDeriv> 
ConstantExpr::internalFindV(int order, const EvalContext& context) const
{
  Set<MultipleDeriv> rtn;
  Tabs tab;
  SUNDANCE_MSG2(context.setupVerbosity(), 
    tab << "ConstantExpr::internalFindV is a no-op");
  return rtn;
}
Set<MultipleDeriv> 
UnknownParameterElement::internalFindV(int order, const EvalContext& context) const
{
  Tabs tab;
  SUNDANCE_MSG2(context.setupVerbosity(), 
    tab << "UPE::internalFindV is a no-op");
  Set<MultipleDeriv> rtn;

  return rtn;
}
Example #10
0
Set<MultipleDeriv>
ZeroExpr::internalFindC(int order, const EvalContext& context) const
{
    Set<MultipleDeriv> rtn;

    Tabs tab;
    SUNDANCE_MSG2(context.setupVerbosity(),
                  tab << "ZeroExpr::internalFindC found" << rtn << " for order="
                  << order);
    return rtn;
}
RCP<Array<Set<MultipleDeriv> > > 
ExplicitFunctionalDerivativeElement
::internalDetermineR(const EvalContext& context,
                           const Array<Set<MultipleDeriv> >& RInput) const
{
  Tabs tab0(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tab0 << "ExplicitFunctionalDerivativeElement::internalDetermineR for=" << toString());
  SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput );

  RCP<Array<Set<MultipleDeriv> > > rtn 
    = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));
  
  {
    Tabs tab1;
    for (int i=0; i<RInput.size(); i++)
      {
        Tabs tab2;
        const Set<MultipleDeriv>& Wi = findW(i, context);
        SUNDANCE_MSG5(verb,  tab2 << "W[" << i << "] = " << Wi );
        (*rtn)[i] = RInput[i].intersection(Wi);
      }

    Array<Set<MultipleDeriv> > RArg(RInput.size()+1);
    MultipleDeriv me(fd_);
    
    for (int order=1; order<=RInput.size(); order++)
      {
        Tabs tab2;
        SUNDANCE_MSG3(verb, tab2 << "order = " << order);
        if (RInput[order-1].size() == 0) continue;
        const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
        const Set<MultipleDeriv>& RMinus = (*rtn)[order-1];

        SUNDANCE_MSG3(verb, tab2 << "RInput = " << RInput[order-1]);
        SUNDANCE_MSG3(verb, tab2 << "FD times RInput = " 
          << setProduct(RMinus, makeSet(me)));
        
        RArg[order].merge(setProduct(RMinus, makeSet(me)).intersection(WArg));
      }
    SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg);
    
    SUNDANCE_MSG3(verb, tab1 << "calling determineR() for arg "
                       << evaluatableArg()->toString());
    evaluatableArg()->determineR(context, RArg);
  }
  printR(verb, rtn);
  SUNDANCE_MSG2(verb, tab0 << "done with ExplicitFunctionalDerivativeElement::internalDetermineR for "
                     << toString());
  /* all done */  
  return rtn;
}
Set<MultipleDeriv> 
ConstantExpr::internalFindW(int order, const EvalContext& context) const
{
  Set<MultipleDeriv> rtn;

  if (order==0) rtn.put(MultipleDeriv());
  Tabs tab;
  SUNDANCE_MSG2(context.setupVerbosity(), 
    tab << "ConstantExpr::internalFindW found" << rtn << " for order="
    << order);

  return rtn;
}
RCP<SparsitySuperset> 
EvaluatableExpr::sparsitySuperset(const EvalContext& context) const 
{
  Tabs tab;
  
  SUNDANCE_MSG2(context.setupVerbosity(), 
    tab << "getting sparsity superset for " << toString());

  RCP<SparsitySuperset> rtn;

  if (sparsity_.containsKey(context))
  {
    Tabs tab1;
    SUNDANCE_MSG2(context.setupVerbosity(), 
      tab1 << "reusing previously computed data...");
    rtn = sparsity_.get(context);
  }
  else
  {
    Tabs tab1;
    SUNDANCE_MSG2(context.setupVerbosity(), 
      tab1 << "computing from scratch...");
    const Set<MultipleDeriv>& R = findR(context);
    const Set<MultipleDeriv>& C = findC(context);
    const Set<MultipleDeriv>& V = findV(context);
    if (context.setupVerbosity() > 4)
    {
      Out::os() << tab1 << "R=" << R << endl;
      Out::os() << tab1 << "C=" << C << endl;
      Out::os() << tab1 << "V=" << V << endl;
    }
    rtn = rcp(new SparsitySuperset(C.intersection(R), V.intersection(R)));
    sparsity_.put(context, rtn);
  }
  return rtn;
}
Example #14
0
Set<MultipleDeriv> DiffOp::internalFindV(int order, const EvalContext& context) const
{
  Tabs tabs(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tabs << "DiffOp::internalFindV(" << order << ") for " 
    << toString());

  Set<MultipleDeriv> rtn;
  
  if (order <= 2)
  {
    Tabs tab1;
    const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context);
    const Set<MultipleDeriv>& VArg = evaluatableArg()->findV(order, context);
    const Set<MultipleDeriv>& VArgPlus 
      = evaluatableArg()->findV(order+1, context);
    const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
    const Set<MultipleDeriv>& WArgPlus 
      = evaluatableArg()->findW(order+1, context);

    SUNDANCE_MSG5(verb, tab1 << "W1=" << W1);
    SUNDANCE_MSG5(verb, tab1 << "VArg=" << VArg);
    SUNDANCE_MSG5(verb, tab1 << "VArgPlus=" << VArgPlus);
    SUNDANCE_MSG5(verb, tab1 << "WArg=" << WArg);
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus=" << WArgPlus);

    Set<MultipleDeriv> Tx = applyTx(VArg, mi_);
    Set<MultipleDeriv> Zx = applyZx(W1, mi_);
    SUNDANCE_MSG5(verb, tab1 << "Tx(Varg) = " << Tx);
    SUNDANCE_MSG5(verb, tab1 << "Zx(W1) = " << Zx);
    Set<MultipleDeriv> WargPlusOslashZx = setDivision(WArgPlus, Zx);
    Set<MultipleDeriv> VargPlusOslashXx = setDivision(VArgPlus, Xx(mi_));
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus / Z_alpha = " 
      << WargPlusOslashZx);
    SUNDANCE_MSG5(verb, tab1 << "VArgPlus / X_alpha = " 
      << VargPlusOslashXx);
    rtn = WargPlusOslashZx.setUnion(VargPlusOslashXx).setUnion(Tx); 
   
    SUNDANCE_MSG5(verb, tab1 << "WArgPlus/Z union VArgPlus/X union T =" << rtn);
    rtn = rtn.intersection(findR(order, context));
  }

  SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn);
  SUNDANCE_MSG2(verb, tabs << "done with DiffOp::internalFindV(" << order << ") for "
    << toString());

  return rtn;
}
Set<MultiSet<int> > ProductExpr::internalFindQ_W(int order, const EvalContext& context) const
{
  Tabs tab0(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tab0 << "ProdExpr::internalFindQ_W(" << order << ")");

  Set<MultiSet<int> > rtn;
  if (order > 2) return rtn;

  if (order==2)
  {
    rtn.put(makeMultiSet<int>(0,1));
    return rtn;
  }

  Tabs tab1;
  SUNDANCE_MSG3(verb, tab1 << "calling findW(0) for left");
  const Set<MultipleDeriv>& wLeft 
    = leftEvaluatable()->findW(0, context);
  SUNDANCE_MSG3(verb, tab1 << "found wLeft(0)=" << wLeft);

  SUNDANCE_MSG3(verb, tab1 << "calling findW(0) for right");
  const Set<MultipleDeriv>& wRight
    = rightEvaluatable()->findW(0, context);
  SUNDANCE_MSG3(verb, tab1 << "found wRight(0)=" << wRight);
  
  if (order==0)
  {
    if (wLeft.size() > 0)
    {
      rtn.put(makeMultiSet<int>(0));
    }
    if (wRight.size() > 0)
    {
      rtn.put(makeMultiSet<int>(1));
    }
  }
  
  if (order==1)
  {
    if (wLeft.size() > 0) rtn.put(makeMultiSet<int>(1));
    if (wRight.size() > 0) rtn.put(makeMultiSet<int>(0));
  }
  
  SUNDANCE_MSG2(verb, tab0 << "Q_W[" << order << "]=" << rtn);
  return rtn;
}
Set<MultipleDeriv> 
UnknownParameterElement::internalFindW(int order, const EvalContext& context) const
{
  Tabs tab;
  SUNDANCE_MSG2(context.setupVerbosity(), 
    tab << "in UPE::internalFindW, order=" << order);
  Set<MultipleDeriv> rtn;

  if (order==0) 
  {
    if (!evalPtIsZero()) rtn.put(MultipleDeriv());
  }
  else if (order==1)
  {
    MultipleDeriv md = makeMultiDeriv(funcDeriv(this));
    rtn.put(md);
  }

  return rtn;
}
Array<Set<MultipleDeriv> > EvaluatableExpr
::computeInputR(const EvalContext& context,
  const Array<Set<MultiSet<int> > >& funcIDCombinations,
  const Array<Set<MultiIndex> >& spatialDerivs) const 
{
  int verb = context.setupVerbosity();
  Tabs tabs(0);
  SUNDANCE_MSG2(verb, tabs << "in EE::computeInputR()");
  Array<Set<MultipleDeriv> > rtn(funcIDCombinations.size());
  for (int order=0; order<funcIDCombinations.size(); order++)
  {
    Tabs tabs1;
    SUNDANCE_MSG2(verb, tabs << "order=" << order);
    SUNDANCE_MSG2(verb, tabs1 << "funcID combs=" 
      << funcIDCombinations[order]);
    const Set<MultipleDeriv>& W = findW(order, context);
    SUNDANCE_MSG2(verb, tabs1 << "W[order=" << order << "]=" << W);

    for (Set<MultipleDeriv>::const_iterator i=W.begin(); i!=W.end(); i++)
    {
      Tabs tab2;
      const MultipleDeriv& nonzeroDeriv = *i;
      if (nonzeroDeriv.isInRequiredSet(funcIDCombinations[order],
          spatialDerivs[order]))
      {
        SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv 
          << " added to inputR");
        rtn[order].put(nonzeroDeriv);
      }
      else
      {
        SUNDANCE_MSG2(verb, tab2 << "md=" << nonzeroDeriv << " not needed");
      }
    }
  }
  SUNDANCE_MSG2(verb, tabs << "inputR=" << rtn);
  return rtn;
}
CellDiameterExprEvaluator::CellDiameterExprEvaluator(
    const CellDiameterExpr* expr,
    const EvalContext& context)
    : SubtypeEvaluator<CellDiameterExpr>(expr, context),
      stringRep_(expr->toString())
{

    Tabs tabs;
    int verb = context.setupVerbosity();
    SUNDANCE_MSG1(verb, tabs << "initializing cell diameter expr evaluator for "
                  << expr->toString());
    SUNDANCE_MSG2(verb, tabs << "return sparsity " << std::endl << *(this->sparsity)());

    TEUCHOS_TEST_FOR_EXCEPTION(this->sparsity()->numDerivs() > 1, std::logic_error,
                               "CellDiameterExprEvaluator ctor found a sparsity table "
                               "with more than one entry. The bad sparsity table is "
                               << *(this->sparsity)());

    /*
     * There is only one possible entry in the nozeros table for a
     * cell diameter expression: a zeroth derivative.
     */

    for (int i=0; i<this->sparsity()->numDerivs(); i++)
    {
        const MultipleDeriv& d = this->sparsity()->deriv(i);

        TEUCHOS_TEST_FOR_EXCEPTION(d.order()!=0, std::logic_error,
                                   "CellDiameterExprEvaluator ctor found an entry in the "
                                   "sparsity superset that is not a zeroth-order derivative. "
                                   "The bad entry is " << this->sparsity()->deriv(i)
                                   << ". The superset is "
                                   << *(this->sparsity)());
        addVectorIndex(i, 0);
    }
}
RCP<Array<Set<MultipleDeriv> > > EvaluatableExpr
::internalDetermineR(const EvalContext& context,
  const Array<Set<MultipleDeriv> >& RInput) const
{
  Tabs tab0(0);
  int verb = context.setupVerbosity();
  RCP<Array<Set<MultipleDeriv> > > rtn 
    = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));

  SUNDANCE_MSG2(verb, tab0 << "EE::internalDetermineR() for " << toString() );
  SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput );

  for (int i=0; i<RInput.size(); i++)
  {
    Tabs tab1;
    if (RInput[i].size()==0) continue;
    const Set<MultipleDeriv>& Wi = findW(i, context);
    SUNDANCE_MSG3(verb, tab1 << "W[" << i << "] = " << Wi );
    (*rtn)[i] = RInput[i].intersection(Wi);
  }

  printR(verb, rtn);
  return rtn;
}
Set<MultipleDeriv> ExplicitFunctionalDerivativeElement
::internalFindV(int order, const EvalContext& context) const
{
  Tabs tabs(0);
  int verb = context.setupVerbosity();
  SUNDANCE_MSG2(verb, tabs << "ExplicitFunctionalDerivativeElement::internalFindV(" << order << ") for " 
                     << toString());

  Set<MultipleDeriv> rtn;
  
  {
    Tabs tab1;
    SUNDANCE_MSG5(verb, tab1 << "finding R");
    const Set<MultipleDeriv>& R = findR(order, context);
    SUNDANCE_MSG5(verb, tab1 << "finding C");
    const Set<MultipleDeriv>& C = findC(order, context);
    rtn = R.setDifference(C);
  }
  SUNDANCE_MSG2(verb, tabs << "V[" << order << "]=" << rtn);
  SUNDANCE_MSG2(verb, tabs << "done with ExplicitFunctionalDerivativeElement::internalFindV(" << order << ") for "
    << toString());
  
  return rtn;
}
Example #21
0
RCP<Array<Set<MultipleDeriv> > > 
DiffOp::internalDetermineR(const EvalContext& context,
  const Array<Set<MultipleDeriv> >& RInput) const
{
  Tabs tab0(0);
  int verb = context.setupVerbosity();

  SUNDANCE_MSG2(verb, tab0 << "DiffOp::internalDetermineR for=" << toString());
  SUNDANCE_MSG2(verb, tab0 << "RInput = " << RInput );

  RCP<Array<Set<MultipleDeriv> > > rtn 
    = rcp(new Array<Set<MultipleDeriv> >(RInput.size()));
  
  {
    Tabs tab1;
    for (int i=0; i<RInput.size(); i++)
    {
      Tabs tab2;
      const Set<MultipleDeriv>& Wi = findW(i, context);
      SUNDANCE_MSG5(verb,  tab2 << "W[" << i << "] = " << Wi );
      (*rtn)[i] = RInput[i].intersection(Wi);
    }

    const Set<MultipleDeriv>& W1 = evaluatableArg()->findW(1, context);
    SUNDANCE_MSG3(verb, tab1 << "arg W1 = " << W1);
    Set<MultipleDeriv> ZxXx = applyZx(W1, mi_).setUnion(Xx(mi_));
    SUNDANCE_MSG3(verb, tab1 << "Z union X = " << ZxXx);
    Array<Set<MultipleDeriv> > RArg(RInput.size()+1);
    RArg[0].put(MultipleDeriv());
    RArg[1].put(MultipleDeriv(coordDeriv(mi_.firstOrderDirection())));


    
    for (int order=0; order<RInput.size(); order++)
    {
      Tabs tab2;
      const Set<MultipleDeriv>& WArgPlus = evaluatableArg()->findW(order+1, context);
      const Set<MultipleDeriv>& WArg = evaluatableArg()->findW(order, context);
      SUNDANCE_MSG3(verb, tab2 << "order = " << order);
      SUNDANCE_MSG3(verb, tab2 << "RInput = " << RInput[order]);
      SUNDANCE_MSG3(verb, tab2 << "WArg = " << WArg);
      SUNDANCE_MSG3(verb, tab2 << "WArgPlus = " << WArgPlus);
      SUNDANCE_MSG3(verb, tab2 << "ZxXx times RInput = " 
        << setProduct(ZxXx, RInput[order]));
      SUNDANCE_MSG3(verb, tab2 << "Tx(RInput, " << -mi_ << ") = " 
        << applyTx(RInput[order], -mi_) );
      RArg[order+1].merge(setProduct(ZxXx, RInput[order]).intersection(WArgPlus));
      RArg[order].merge(applyTx(RInput[order], -mi_).intersection(WArg));
    }
    SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg);
    
    SUNDANCE_MSG2(verb, tab1 << "calling determineR() for arg "
      << evaluatableArg()->toString());
    evaluatableArg()->determineR(context, RArg);

    /* inform the evaluation points of all functions appearing in the argument
     * that we'll need their spatial derivatives in direction mi(). */
    
    SUNDANCE_MSG3(verb, tab1 << "calling findR(1) to determine required spatial derivatives ");
    const Set<MultipleDeriv>& RArg1 = evaluatableArg()->findR(1, context);
    SUNDANCE_MSG3(verb, tab1 << "RArg1 = " << RArg1);
    for (Set<MultipleDeriv>::const_iterator i=RArg1.begin(); i!=RArg1.end(); i++)
    {
      requestMultiIndexAtEvalPoint(mi(), *i, context);
    }
  }
  printR(verb, rtn);
  SUNDANCE_MSG2(verb, tab0 << "done with DiffOp::internalDetermineR for "
    << toString());
  /* all done */  
  return rtn;
}
DerivSet SymbPreprocessor::setupVariations(const Expr& expr, 
  const Expr& vars,
  const Expr& varEvalPts,
  const Expr& unks,
  const Expr& unkEvalPts,
  const Expr& unkParams,
  const Expr& unkParamEvalPts,
  const Expr& fixedFields,
  const Expr& fixedFieldEvalPts, 
  const Expr& fixedParams,
  const Expr& fixedParamEvalPts, 
  const EvalContext& context,
  const ComputationType& compType)
{
  TimeMonitor t(preprocTimer());
  Tabs tab;

  const EvaluatableExpr* e 
    = dynamic_cast<const EvaluatableExpr*>(expr.ptr().get());

  Array<Set<MultiSet<int> > > funcDerivs(3);
  Array<Set<MultiIndex> > spatialDerivs(3);

  int verb=context.setupVerbosity();
  SUNDANCE_BANNER1(verb, tab, "in setupVariations()");
  verbosity<EvaluatableExpr>() = verb;
  SUNDANCE_MSG1(verb,
    tab << "************ setting up variations of expr: " 
    << expr 
    << std::endl << tab << "context is " << context 
    << std::endl << tab << "conp type is " << compType
    << std::endl << tab << "vars are " << vars
    << std::endl << tab << "unks are " << unks
    << std::endl << tab << "unk parameters " << unkParams
    << std::endl << tab << "fixed parameters " << fixedParams
    << std::endl << tab << "the eval points for the vars are " 
    << varEvalPts
    << std::endl << tab << "the eval points for the unks are " 
    << unkEvalPts
    << std::endl << tab 
    << "the eval points for the unknown parameters are " 
    << unkParamEvalPts 
    << std::endl << tab 
    << "the eval points for the fixed parameters are " 
    << fixedParamEvalPts 
    << tab << std::endl);

  TEUCHOS_TEST_FOR_EXCEPTION(e==0, std::logic_error,
    "Non-evaluatable expr " << expr.toString()
    << " given to SymbPreprocessor::setupExpr()");

  /* make flat lists of variations, unknowns, parameters, and fixed fields */
  Expr v = vars.flatten();
  Expr v0 = varEvalPts.flatten();
  Expr u = unks.flatten();
  Expr u0 = unkEvalPts.flatten();
  Expr alpha = unkParams.flatten();
  Expr alpha0 = unkParamEvalPts.flatten();
  Expr beta = fixedParams.flatten();
  Expr beta0 = fixedParamEvalPts.flatten();
  Expr f = fixedFields.flatten();
  Expr f0 = fixedFieldEvalPts.flatten();
  


  Set<int> varID = processInputFuncs<SymbolicFuncElement>(v, v0);

  Set<int> unkID = processInputFuncs<UnknownFuncElement>(u, u0);

  Set<int> fixedID = processInputFuncs<UnknownFuncElement>(f, f0);

  Set<int> unkParamID 
    = processInputParams<UnknownParameterElement>(alpha, alpha0);

  Set<int> fixedParamID 
    = processInputParams<UnknownParameterElement>(beta, beta0);


  

  /* put together the set of functions that are active differentiation
   * variables */

  SUNDANCE_MSG2(verb, tab << "forming active set");
  Array<Sundance::Set<MultiSet<int> > > activeFuncIDs(3);
  if (context.needsDerivOrder(0)) activeFuncIDs[0].put(MultiSet<int>());
  if (context.topLevelDiffOrder() >= 1)
  {
    for (Set<int>::const_iterator i=varID.begin(); i != varID.end(); i++)
    {
      if (context.needsDerivOrder(1)) activeFuncIDs[1].put(makeMultiSet<int>(*i));
      if (context.topLevelDiffOrder()==2)
      {
        for (Set<int>::const_iterator j=unkID.begin(); j != unkID.end(); j++)
        {
          activeFuncIDs[2].put(makeMultiSet<int>(*i, *j));
        }
        if (compType==MatrixAndVector)
        {
          for (Set<int>::const_iterator 
                 j=unkParamID.begin(); j != unkParamID.end(); j++)
          {
            activeFuncIDs[2].put(makeMultiSet<int>(*i, *j));
          }
        }
        else if (compType==Sensitivities)
        {
          for (Set<int>::const_iterator 
                 j=fixedParamID.begin(); j != fixedParamID.end(); j++)
          {
            activeFuncIDs[2].put(makeMultiSet<int>(*i, *j));
          }
        }
      }
    }
  }
  SUNDANCE_MSG1(verb, tab << std::endl << tab 
    << " ************* Finding nonzeros for expr " << std::endl << tab);
  for (int i=0; i<=context.topLevelDiffOrder(); i++)
  {
    Tabs tab2;
    SUNDANCE_MSG4(verb, tab2 << "diff order=" << i << ", active funcs="
      << activeFuncIDs[i]);
  }

  Set<MultiIndex> miSet;
  miSet.put(MultiIndex());
  e->registerSpatialDerivs(context, miSet);
  
  SUNDANCE_MSG2(verb,
    tab << std::endl << tab 
    << " ************* finding required functions" << std::endl << tab);
  SUNDANCE_MSG2(verb,
    tab << "activeFuncIDs are = " << activeFuncIDs);
  SUNDANCE_MSG2(verb,
    tab << "spatial derivs are = " << spatialDerivs);
  Array<Set<MultipleDeriv> > RInput 
    = e->computeInputR(context, activeFuncIDs, spatialDerivs);

  SUNDANCE_MSG3(verb,
    tab << std::endl << tab 
    << " ************* Top-level required funcs are " << RInput << std::endl << tab);


  SUNDANCE_MSG2(verb,
    tab << std::endl << tab 
    << " ************* Calling determineR()" << std::endl << tab);
  
  e->determineR(context, RInput);

  
  SUNDANCE_MSG1(verb,
    tab << std::endl << tab 
    << " ************* Finding sparsity structure " << std::endl << tab);
  DerivSet derivs = e->sparsitySuperset(context)->derivSet();
  SUNDANCE_MSG1(verb,
    tab << std::endl << tab 
    << "Nonzero deriv set = " << derivs);

  SUNDANCE_MSG1(verb,
    tab << std::endl << tab 
    << " ************* Setting up evaluators for expr " << std::endl << tab);

  int saveVerb = context.setupVerbosity();
  context.setSetupVerbosity(0);
  e->setupEval(context);

  if (verb>1)
  { 
    SUNDANCE_MSG1(verb,
      tab << std::endl << tab 
      << " ************* Nonzeros are:");
    e->displayNonzeros(Out::os(), context);

  }


  context.setSetupVerbosity(saveVerb);
  return derivs;
}
DiffOpEvaluator
::DiffOpEvaluator(const DiffOp* expr,
  const EvalContext& context)
  : UnaryEvaluator<DiffOp>(expr, context),
    isConstant_(this->sparsity()->numDerivs()),
    resultIndices_(this->sparsity()->numDerivs()),
    constantMonomials_(this->sparsity()->numDerivs()),
    vectorMonomials_(this->sparsity()->numDerivs()),
    constantFuncCoeffs_(this->sparsity()->numDerivs()),
    vectorFuncCoeffs_(this->sparsity()->numDerivs()),
    funcEvaluators_(),
    constantCoeffFuncIndices_(this->sparsity()->numDerivs()),
    constantCoeffFuncMi_(this->sparsity()->numDerivs()),
    vectorCoeffFuncIndices_(this->sparsity()->numDerivs()),
    vectorCoeffFuncMi_(this->sparsity()->numDerivs())
{
  int verb = context.setupVerbosity();
  Tabs tabs;
  SUNDANCE_MSG1(verb, tabs << "initializing diff op evaluator for " 
    << expr->toString());

  {
    Tabs tab0;
  
    SUNDANCE_MSG2(verb, tab0 << "return sparsity " << std::endl << *(this->sparsity)());

    SUNDANCE_MSG2(verb, tab0 << "argument sparsity subset " << std::endl 
      << *(argSparsitySuperset()));

    Map<const DiscreteFuncElementEvaluator*, int> funcToIndexMap;

    int vecResultIndex = 0;
    int constResultIndex = 0;
  
    for (int i=0; i<this->sparsity()->numDerivs(); i++)
    {
      Tabs tab1;
      const MultipleDeriv& resultDeriv = this->sparsity()->deriv(i);
      SUNDANCE_MSG3(verb, tab0 << "working out procedure for computing " 
        << resultDeriv);

      if (this->sparsity()->state(i)==ConstantDeriv)
      {
        Tabs tab2;
        addConstantIndex(i, constResultIndex);
        resultIndices_[i] = constResultIndex++;
        isConstant_[i] = true;
        SUNDANCE_MSG3(verb, tab2 << "deriv is constant, will be stored at index "
          << resultIndices_[i] << " in the const result array");
      }
      else
      {
        Tabs tab2;
        addVectorIndex(i, vecResultIndex);
        resultIndices_[i] = vecResultIndex++;
        isConstant_[i] = false;
        SUNDANCE_MSG3(verb, tab2 << "deriv is variable, will be stored at index "
          << resultIndices_[i] << " in the var result array");
      }

      int order = resultDeriv.order();
      const Set<MultipleDeriv>& RArg 
        = argExpr()->findR(order, context);
      const Set<MultipleDeriv>& RArgPlus
        = argExpr()->findR(order+1, context);
      const Set<MultipleDeriv>& W1Arg 
        = argExpr()->findW(1, context);

        
      SUNDANCE_MSG3(verb, tab1 << "RArg = " << RArg);
      SUNDANCE_MSG3(verb, tab1 << "RArgPlus = " << RArgPlus);
      SUNDANCE_MSG3(verb, tab1 << "W1Arg = " << W1Arg);

      Set<MultipleDeriv> funcTermCoeffs 
        = RArgPlus.intersection(increasedDerivs(resultDeriv, W1Arg, verb));
      SUNDANCE_MSG3(verb, tab1 << "function term coeffs = " << funcTermCoeffs);

      
      if (funcTermCoeffs.size()==0)
      {
        SUNDANCE_MSG3(verb, tab1 << "no direct chain rule terms");
      }
      else
      {
        SUNDANCE_MSG3(verb, tab1 << "getting direct chain rule terms");
      }


      for (Set<MultipleDeriv>::const_iterator 
             j=funcTermCoeffs.begin(); j != funcTermCoeffs.end(); j++)
      {
        Tabs tab2;
        SUNDANCE_MSG3(verb, tab2 << "getting coefficient of " << *j);

        int argIndex = argSparsitySuperset()->getIndex(*j);
        TEUCHOS_TEST_FOR_EXCEPTION(argIndex==-1, std::runtime_error,
          "Derivative " << *j << " expected in argument "
          "but not found");

        Deriv lambda = remainder(*j, resultDeriv, verb);

        if (lambda.isCoordDeriv())
        {
          Tabs tab3;
          SUNDANCE_MSG3(verb, tab2 << "detected coordinate deriv");
          if (lambda.coordDerivDir()!=expr->mi().firstOrderDirection())
          {
            SUNDANCE_MSG3(verb, tab2 << "direction mismatch, skipping");
            continue;
          }
          const DerivState& argState = argSparsitySuperset()->state(argIndex);
          if (argState==ConstantDeriv)
          {
            int constArgIndex = argEval()->constantIndexMap().get(argIndex);
            constantMonomials_[i].append(constArgIndex);
          }
          else
          {
            int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
            vectorMonomials_[i].append(vectorArgIndex);
          }
        }
        else if (lambda.opOnFunc().isPartial() || lambda.opOnFunc().isIdentity())
        {
          Tabs tab3;
          SUNDANCE_MSG3(verb, tab3 << "detected functional deriv " << lambda);
          const SymbolicFuncElement* f = lambda.symbFuncElem();
          const MultiIndex& mi = expr->mi() + lambda.opOnFunc().mi(); 
          SUNDANCE_MSG3(verb, tab3 << "modified multiIndex is " << mi);

          const TestFuncElement* t 
            = dynamic_cast<const TestFuncElement*>(f);
          if (t != 0) continue;

          const UnknownFuncElement* u 
            = dynamic_cast<const UnknownFuncElement*>(f);
          TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::logic_error,
            "Non-unknown function detected where an unknown "
            "function was expected in "
            "DiffOpEvaluator ctor");


          const EvaluatableExpr* evalPt = u->evalPt();
          const ZeroExpr* z = dynamic_cast<const ZeroExpr*>(evalPt);
          if (z != 0) continue;
          TEUCHOS_TEST_FOR_EXCEPTION(z != 0, std::logic_error,
            "DiffOpEvaluator detected identically zero "
            "function");

          const DiscreteFuncElement* df 
            = dynamic_cast<const DiscreteFuncElement*>(evalPt);
          
          TEUCHOS_TEST_FOR_EXCEPTION(df==0, std::logic_error,
            "DiffOpEvaluator ctor: evaluation point of "
            "unknown function " << u->toString() 
            << " is not a discrete function");

          const SymbolicFuncElementEvaluator* uEval 
            = dynamic_cast<const SymbolicFuncElementEvaluator*>(u->evaluator(context).get());

          const DiscreteFuncElementEvaluator* dfEval = uEval->dfEval();


          TEUCHOS_TEST_FOR_EXCEPTION(dfEval==0, std::logic_error,
            "DiffOpEvaluator ctor: evaluator for "
            "evaluation point is not a "
            "DiscreteFuncElementEvaluator");

          TEUCHOS_TEST_FOR_EXCEPTION(!dfEval->hasMultiIndex(mi), std::logic_error,
            "DiffOpEvaluator ctor: evaluator for "
            "discrete function " << df->toString()
            << " does not know about multiindex "
            << mi.toString());
          
          int fIndex;
          int miIndex = dfEval->miIndex(mi);
          
          if (funcToIndexMap.containsKey(dfEval))
          {
            fIndex = funcToIndexMap.get(dfEval);
          }
          else
          {
            fIndex = funcEvaluators_.size();
            funcEvaluators_.append(dfEval);
            funcToIndexMap.put(dfEval, fIndex);
          }

            
          const DerivState& argState = argSparsitySuperset()->state(argIndex);
          if (argState==ConstantDeriv)
          {
            int constArgIndex = argEval()->constantIndexMap().get(argIndex);
            constantCoeffFuncIndices_[i].append(fIndex);
            constantCoeffFuncMi_[i].append(miIndex);
            constantFuncCoeffs_[i].append(constArgIndex);
          }
          else
          {
            int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
            vectorCoeffFuncIndices_[i].append(fIndex);
            vectorCoeffFuncMi_[i].append(miIndex);
            vectorFuncCoeffs_[i].append(vectorArgIndex);
          }
        }
        else
        {
          TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
            "DiffOpEvaluator has been asked to preprocess a Deriv that "
            "is not a simple partial derivative. The problem child is: "
            << lambda);
        }
      }
      
      
      Set<MultipleDeriv> isolatedTerms 
        = RArg.intersection(backedDerivs(resultDeriv, W1Arg, verb));
      
      if (isolatedTerms.size()==0)
      {
        SUNDANCE_MSG3(verb, tab1 << "no indirect chain rule terms");
      }
      else
      {
        SUNDANCE_MSG3(verb, tab1 << "getting indirect chain rule terms");
        SUNDANCE_MSG3(verb, tab1 << "isolated terms = " << isolatedTerms);
      }

      for (Set<MultipleDeriv>::const_iterator 
             j=isolatedTerms.begin(); j != isolatedTerms.end(); j++)
      {
        int argIndex = argSparsitySuperset()->getIndex(*j);
        TEUCHOS_TEST_FOR_EXCEPTION(argIndex==-1, std::runtime_error,
          "Derivative " << *j << " expected in argument "
          "but not found");
        const DerivState& argState = argSparsitySuperset()->state(argIndex);
        if (argState==ConstantDeriv)
        {
          int constArgIndex = argEval()->constantIndexMap().get(argIndex);
          constantMonomials_[i].append(constArgIndex);
        }
        else
        {
          int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
          vectorMonomials_[i].append(vectorArgIndex);
        }
      }
    }
  }

  if (verb > 2)
  {
    Out::os() << tabs << "instruction tables for summing spatial/functional chain rule" << std::endl;
    for (int i=0; i<this->sparsity()->numDerivs(); i++)
    {
      Tabs tab1;
      Out::os() << tab1 << "deriv " << sparsity()->deriv(i) << std::endl;
      {
        Tabs tab2;
        Out::os() << tab2 << "constant monomials: " << constantMonomials_[i]
                  << std::endl;
        Out::os() << tab2 << "vector monomials: " << vectorMonomials_[i]
                  << std::endl;
            
        Out::os() << tab2 << "constant coeff functions: " << std::endl;
        for (int j=0; j<constantFuncCoeffs_[i].size(); j++)
        {
          Tabs tab3;
          Out::os() << tab3 << "func=" << constantCoeffFuncIndices_[i][j]
                    << " mi=" << constantCoeffFuncMi_[i][j] << std::endl;
        } 
        Out::os() << tab2 << "vector coeff functions: " << std::endl;
        for (int j=0; j<vectorFuncCoeffs_[i].size(); j++)
        {
          Tabs tab3;
          Out::os() << tab3 << "func=" << vectorCoeffFuncIndices_[i][j]
                    << " mi=" << vectorCoeffFuncMi_[i][j] << std::endl;
        }
            
      }
    }
  }
}
CoordExprEvaluator::CoordExprEvaluator(const CoordExpr* expr, 
                                       const EvalContext& context)
  : SubtypeEvaluator<CoordExpr>(expr, context), 
    doValue_(false),
    doDeriv_(false),
    stringRep_(expr->toString())
{
  int verb = context.setupVerbosity();
  Tabs tabs;
  SUNDANCE_MSG1(verb, tabs << "initializing coord expr evaluator for " 
                    << expr->toString());
  SUNDANCE_MSG2(verb, tabs << "return sparsity " << std::endl << tabs << *(this->sparsity)());

  TEUCHOS_TEST_FOR_EXCEPTION(this->sparsity()->numDerivs() > 2, std::logic_error,
                     "CoordExprEvaluator ctor found a sparsity table "
                     "with more than two entries. The bad sparsity table is "
                     << *(this->sparsity)());

  /* 
   * There are only two possible entries in the nozeros table for a
   * coordinate expression: a zeroth derivative, and a first-order
   * spatial derivative in the same direction as the expr's coordinate. 
   */
  
  for (int i=0; i<this->sparsity()->numDerivs(); i++)
    {
      const MultipleDeriv& d = this->sparsity()->deriv(i);

      /* for a zeroth-order derivative, evaluate the coord expr */
      if (d.order()==0) 
        {
          doValue_ = true;
          addVectorIndex(i, 0);
        }
      else /* for a first-order deriv, make sure it's in the proper direction,
            * then evaluate the spatial derivative. */
        {
          TEUCHOS_TEST_FOR_EXCEPTION(!this->sparsity()->isSpatialDeriv(i), std::logic_error,
                             "CoordExprEvaluator ctor found an entry in the "
                             "sparsity superset that is not a spatial derivative. "
                             "The bad entry is " << this->sparsity()->deriv(i) 
                             << ". The superset is " 
                             << *(this->sparsity)());

          const MultiIndex& mi = this->sparsity()->multiIndex(i);
          
          TEUCHOS_TEST_FOR_EXCEPTION(mi.order() != 1, std::logic_error,
                             "CoordExprEvaluator ctor found a multiindex of "
                             "order != 1. Bad multiindex is " << mi.toString());
          
          TEUCHOS_TEST_FOR_EXCEPTION(mi[expr->dir()]!=1, std::logic_error,
                             "CoordExprEvaluator sparsity pattern has an "
                             "element corresponding to differentiation wrt "
                             "a coordinate direction other than that of the "
                             "coord expr's direction");
          doDeriv_ = true;
          addConstantIndex(i, 0);
        }
    }
  
}