MultipleDeriv MultipleDeriv::product(const MultipleDeriv& other) const 
{
  MultipleDeriv rtn;
  
  for (MultipleDeriv::const_iterator i=this->begin(); i!=this->end(); i++)
  {
    rtn.put(*i);
  }
  for (MultipleDeriv::const_iterator i=other.begin(); i!=other.end(); i++)
  {
    rtn.put(*i);
  }
  return rtn;
}
void SparsitySuperset::addDeriv(const Deriv& d, 
                               const DerivState& state)
{
  MultipleDeriv md;
  md.put(d);
  addDeriv(md, state);
}
Set<MultipleDeriv> applyTx(const Set<MultipleDeriv>& s,
  const MultiIndex& x)
{
  Set<MultipleDeriv> rtn;

  for (Set<MultipleDeriv>::const_iterator i=s.begin(); i!=s.end(); i++)
  {
    const MultipleDeriv& md = *i;
    for (MultipleDeriv::const_iterator j=md.begin(); j!=md.end(); j++)
    {
      const Deriv& d = *j;
      if (d.isFunctionalDeriv())
      {
        const MultiIndex& mi = d.opOnFunc().mi();
        MultiIndex miNew = mi+x;
        if (miNew.isValid())
        {
          Deriv dNew = d.derivWrtMultiIndex(miNew);
          MultipleDeriv mdNew = md;
          mdNew.erase(mdNew.find(d));
          mdNew.put(dNew);
          rtn.put(mdNew);
        }
      }
    }
  }
  return rtn;
}
void MultipleDeriv
::productRulePermutations(ProductRulePerms& perms) const 
{
  int N = order();

  if (N==0)
  {
    MultipleDeriv md0;
    DerivPair p(md0, md0);
    perms.put(p, 1);
    return;
  }

  int p2 = pow2(N);

  for (int i=0; i<p2; i++)
  {
    MultipleDeriv left;
    MultipleDeriv right;
    Array<int> bits = bitsOfAnInteger(i, N);
    int j=0; 
    MultipleDeriv::const_iterator iter;
    for (iter=this->begin(); iter != this->end(); iter++, j++)
    {
      if (bits[j]==true)
      {
        left.put(*iter);
      }
      else
      {
        right.put(*iter);
      }
    }
    DerivPair p(left, right);
    if (!perms.containsKey(p))
    {
      perms.put(p, 1);
    }
    else
    {
      int count = perms.get(p);
      perms.put(p, count+1);
    }
  }
}
MultipleDeriv FunctionalPolynomial::successorTerm(const MultipleDeriv& md) const
{
  MultipleDeriv rtn;

  unsigned int k = 0;
  for (MultipleDeriv::const_iterator i=md.begin(); i!=md.end(); i++, k++)
    {
      if (k < md.size()-1) rtn.put(*i);
    }
  return rtn;
}
FunctionalPolynomial::FunctionalPolynomial(const RCP<ScalarExpr>& expr)
  : funcs_(),
    funcMultiIndices_(),
    coeffs_(),
    keys_()
{
  TEUCHOS_TEST_FOR_EXCEPTION(!isConvertibleToPoly(expr.get()), std::logic_error, 
                     "FunctionalPolynomial ctor called with an argument that "
                     "cannot be converted to a polynomial");
  int funcID;
  MultiIndex mi;
  Deriv deriv;

  const SymbolicFuncElement* s 
    = dynamic_cast<const SymbolicFuncElement*>(expr.get());
  if (s != 0)
    {
      mi = MultiIndex();
      deriv = funcDeriv(s);
    }
  
  const DerivOfSymbFunc* d
    = dynamic_cast<const DerivOfSymbFunc*>(expr.get());
  if (d != 0)
    {
      deriv = d->representMeAsFunctionalDeriv();
    }

  MultipleDeriv mu;
  mu.put(deriv);


  if (d != 0 || s != 0)
    {
      funcs_.put(funcID, expr);
      Set<MultiIndex> miSet;
      miSet.put(mi);
      funcMultiIndices_.put(funcID, miSet);

      Expr coeff = 1.0;
      RCP<ScalarExpr> cPtr = rcp_dynamic_cast<ScalarExpr>(coeff.ptr());

      coeffs_.resize(2);
      keys_.resize(2);
      coeffs_[1].put(mu, cPtr);
      keys_[1].put(mu);
    }
  else
    {
      TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, 
                         "impossible case in FunctionalPolynomial ctor");
    }
}
Set<MultipleDeriv> DiffOpEvaluator
::increasedDerivs(const MultipleDeriv& mu,
  const Set<MultipleDeriv>& W1, int verb) const
{
  Tabs tabs;
  SUNDANCE_MSG3(verb, tabs << "computing increased derivs");
  Set<MultipleDeriv> rtn;
  for (Set<MultipleDeriv>::const_iterator i=W1.begin(); i!=W1.end(); i++)
  {
    MultipleDeriv md = *i;
    TEUCHOS_TEST_FOR_EXCEPT(md.order() != 1);
    Deriv lambda = *(md.begin());
    MultipleDeriv lambdaMu = mu;
    lambdaMu.put(lambda);
    rtn.put(lambdaMu);
  }
  SUNDANCE_MSG3(verb, tabs << "increased derivs = " << rtn);
  return rtn;
}
Set<MultipleDeriv> DiffOpEvaluator
::backedDerivs(const MultipleDeriv& mu,
  const Set<MultipleDeriv>& W1, int verb) const
{
  Tabs tabs;
  SUNDANCE_MSG3(verb, tabs << "computing backed-out derivs for mu= " << mu
    << ", W1=" << W1);
  Set<MultipleDeriv> rtn;
  if (mu.order() != 0) 
  {
    const MultiIndex& alpha = expr()->mi();

    for (Set<MultipleDeriv>::const_iterator i=W1.begin(); i!=W1.end(); i++)
    {
      const MultipleDeriv& md = *i;
      TEUCHOS_TEST_FOR_EXCEPT(md.order() != 1);
      Deriv lambda = *(md.begin());
      if (lambda.isCoordDeriv()) continue;
      TEUCHOS_TEST_FOR_EXCEPT(!lambda.isFunctionalDeriv());
      FunctionIdentifier lambda_fid = lambda.fid();
      const MultiIndex& lambda_mi = lambda.opOnFunc().mi(); 
      for (MultipleDeriv::const_iterator j=mu.begin(); j!=mu.end(); j++)
      {
        const Deriv& d = *j;
        if (d.isCoordDeriv()) continue;
        FunctionIdentifier d_fid = d.fid();
        const MultiIndex& d_mi = d.opOnFunc().mi(); 
        if (d_fid != lambda_fid) continue;
        if (!(alpha + lambda_mi == d_mi)) continue;
        MultipleDeriv z = mu.factorOutDeriv(d);
        z.put(lambda);
        rtn.put(z);
      }
    }
  }
  SUNDANCE_MSG3(verb, tabs << "backed-out derivs = " << rtn);
  return rtn;
}
void FunctionalPolynomial
::stepRecurrence(int level, const Map<MultipleDeriv, std::string>& sPrev,
                 Map<MultipleDeriv, std::string>& sCurr) const 
{
  Set<MultipleDeriv> allKeys;
  Set<MultipleDeriv> inducedKeys;
  Set<MultipleDeriv> prevKeys;
  for (Map<MultipleDeriv, std::string>::const_iterator 
         i = sPrev.begin(); i != sPrev.end(); i++)
    {
      inducedKeys.put(successorTerm(i->first));
    }
  for (Map<MultipleDeriv, std::string>::const_iterator 
         i = sPrev.begin(); i != sPrev.end(); i++)
    {
      prevKeys.put(i->first);
    }

  Out::os() << "keys from prev level are " << prevKeys << std::endl;
  Out::os() << "induced keys are " << inducedKeys << std::endl;
  Out::os() << "natural keys are " << keys_[level] << std::endl;

  allKeys.merge(inducedKeys);
  allKeys.merge(keys_[level]);

  Out::os() << "keys active at this level are " << allKeys << std::endl;

  for (Set<MultipleDeriv>::const_iterator 
         i = allKeys.begin(); i != allKeys.end(); i++)
    {
      const MultipleDeriv& key = *i;
      Out::os() << "working on key " << key << std::endl;
      std::string str;
      if (coeffs_[level].containsKey(key))
        {
          str = coeffs_[level].get(key)->toString();
        }

      Set<Deriv> funcs = findFuncsForSummation(prevKeys, key);
      Out::os() << "funcs to sum are " << funcs << std::endl;
      for (Set<Deriv>::const_iterator 
             j = funcs.begin(); j != funcs.end(); j++)
        {
          MultipleDeriv prevKey = key;
          Out::os() << "prev key = " << prevKey << std::endl;
          Out::os() << "func = " << *j << std::endl;
          // if (key.size() > 0 && key.upper_bound(*j) == key.end()) 
          //  {
          //    Out::os() << "skipping" << std::endl;
          //    continue;
          // }
          prevKey.put(*j);
          TEUCHOS_TEST_FOR_EXCEPTION(!sPrev.containsKey(prevKey), std::logic_error,
                             "inconsisent key lookup");
          const std::string& prevStr = sPrev.get(prevKey);
          std::string funcStr = (*j).toString();
          if (str.length() > 0) str += " + ";
          str += funcStr + "*(" + prevStr + ")";
        }
      if (str.length() > 0) sCurr.put(key, str);
    }
}
MultipleDeriv makeMultiDeriv(const Deriv& d)
{
  MultipleDeriv rtn;
  rtn.put(d);
  return rtn;
}
Example #11
0
EFDEEvaluator::EFDEEvaluator(
  const ExplicitFunctionalDerivativeElement* expr, 
  const EvalContext& context
  )
  : UnaryEvaluator<ExplicitFunctionalDerivativeElement>(expr, context),
    constValIndexToArgIndexMap_(),
    varValIndexToArgIndexMap_()
{

  Tabs tabs;
  SUNDANCE_VERB_LOW(tabs << "initializing EFDE evaluator for " 
                    << expr->toString());
  SUNDANCE_VERB_MEDIUM(tabs << "return sparsity " << std::endl << *(this->sparsity)());

  /* 
   * This evaluator requires no calculations. All that is done is to
   * map derivatives (md, fd) in the argument's result arrays to 
   * derivatives (md) in this expression's result arrays. 
   */
  

  int vecResultIndex = 0;
  int constResultIndex = 0;

  const Deriv& fd = expr->fd();

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

      if (myState==ConstantDeriv)
      {
        Tabs tab2;
        SUNDANCE_VERB_HIGH(tab2 
          << "deriv is constant, will be stored at index "
          << constResultIndex << " in the const result array");
        addConstantIndex(i, constResultIndex++);
      }
      else
      {
        Tabs tab2;
        SUNDANCE_VERB_HIGH(tab2 
          << "deriv is variable, will be stored at index "
          << vecResultIndex << " in the var result array");
        addVectorIndex(i, vecResultIndex++);
      }
      
      MultipleDeriv dArg = d;
      dArg.put(fd);

      int argIndex = argSparsitySuperset()->getIndex(dArg);

      
      TEST_FOR_EXCEPTION(argIndex==-1, RuntimeError,
        "Derivative " << dArg << " expected in argument but not found");

      
      const DerivState& argState = argSparsitySuperset()->state(argIndex);
      TEST_FOR_EXCEPTION(argState != myState, InternalError, 
        "mismatched states");

      if (argState==ConstantDeriv)
      {
        int constArgIndex = argEval()->constantIndexMap().get(argIndex);
        constValIndexToArgIndexMap_.append(constArgIndex);
      }
      else
      {
        int vectorArgIndex = argEval()->vectorIndexMap().get(argIndex);
        varValIndexToArgIndexMap_.append(vectorArgIndex);
      }
    }
  
  SUNDANCE_VERB_HIGH(tabs 
    << " constant index map " 
    << constValIndexToArgIndexMap_ << std::endl 
    << " vector index map " 
    << varValIndexToArgIndexMap_
    );
}