コード例 #1
0
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;
}
コード例 #2
0
void SparsitySuperset::addDeriv(const Deriv& d, 
                               const DerivState& state)
{
  MultipleDeriv md;
  md.put(d);
  addDeriv(md, state);
}
コード例 #3
0
ファイル: SundanceDiffOp.cpp プロジェクト: 00liujj/trilinos
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);
  }
}
コード例 #4
0
bool hasParameter(const MultipleDeriv& d)
{
  for (MultipleDeriv::const_iterator i=d.begin(); i!=d.end(); i++)
  {
    if (i->isParameter()) return true;
  }
  return false;
}
コード例 #5
0
bool MultipleDeriv::containsDeriv(const MultipleDeriv& x) const
{
  for (MultipleDeriv::const_iterator i=x.begin(); i!=x.end(); i++)
  {
    if ( count(*i) <= x.count(*i) ) return false;
  }
  return true;
}
コード例 #6
0
ファイル: ChainRule.cpp プロジェクト: 00liujj/trilinos
int main(int argc, char** argv)
{
  typedef Array<OrderedPair<Array<MultiSet<int> >, Array<MultipleDeriv> > > CR;
  try
		{
      GlobalMPISession session(&argc, &argv);

			Expr u = new UnknownFunctionStub("u");
			Expr v = new UnknownFunctionStub("v");
			Expr w = new UnknownFunctionStub("w");

      int nArgs = 2;
      MultipleDeriv md = makeDeriv(u,u);
      int order = md.order();
      

      for (int l=1; l<=order; l++)
        {
          Array<int> s(l, nArgs);
          Array<Array<int> > distinctQ = indexCombinations(s);
          Set<MultiSet<int> > q;
          for (int p=0; p<distinctQ.size(); p++)
            {
              q.put(makeMultiSet(distinctQ[p]));
            }
          if (l > 1) cout << " + " << std::endl;
          for (Set<MultiSet<int> >::const_iterator 
                 i=q.begin(); i!=q.end(); i++)
            {
              const MultiSet<int>& lambda = *i;
              if (lambda != *(q.begin())) cout << " + " << std::endl;
              cout << "f_" << lambda << " * [";
              for (int s=1; s<=md.order(); s++)
                {
                  CR p = chainRuleTerms(s, lambda, md);
                  bool firstTerm = true;
                  for (CR::const_iterator j=p.begin(); j!=p.end(); j++)
                    {
                      if (!firstTerm) cout << "+";
                      firstTerm = false;
                      Array<MultiSet<int> > K = j->first();
                      Array<MultipleDeriv> L = j->second();
                      write(md, K, L);
                    }
                }
              cout << "]" << std::endl;
            }
        }
    }
	catch(std::exception& e)
		{
			Out::println(e.what());
		}
}
コード例 #7
0
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;
}
コード例 #8
0
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");
    }
}
コード例 #9
0
MultipleDeriv MultipleDeriv::factorOutDeriv(const Deriv& x) const
{
  MultipleDeriv rtn = *this;

  MultipleDeriv::iterator i = rtn.find(x);

  /* remove a single copy of the given derivative */
  if (i != rtn.end()) rtn.erase(i);

  if (rtn.size() == this->size()) return MultipleDeriv();

  return rtn;
}
コード例 #10
0
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;
}
コード例 #11
0
Set<MultipleDeriv>  
EvaluatableExpr::setDivision(const Set<MultipleDeriv>& a,
  const Set<MultipleDeriv>& b) const
{
  Set<MultipleDeriv> rtn;
  for (Set<MultipleDeriv>::const_iterator i=a.begin(); i!=a.end(); i++)
  {
    for (Set<MultipleDeriv>::const_iterator j=b.begin(); j!=b.end(); j++)
    {
      MultipleDeriv c = i->factorOutDeriv(*j);
      if (c.size() != 0) rtn.put(c);
      if (*i == *j) rtn.put(MultipleDeriv());
    }
  }
  return rtn;
}
コード例 #12
0
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);
    }
  }
}
コード例 #13
0
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;
}
コード例 #14
0
int factorial(const MultipleDeriv& ms)
{
  Sundance::Map<Deriv, int> counts;
    
  for (MultipleDeriv::const_iterator i=ms.begin(); i!=ms.end(); i++)
  {
    if (counts.containsKey(*i)) counts[*i]++;
    else counts.put(*i, 1);
  }

  int rtn = 1;
  for (Sundance::Map<Deriv, int>::const_iterator
         i=counts.begin(); i!=counts.end(); i++)
  {
    int f = 1;
    for (int j=1; j<=i->second; j++) f *= j;
    rtn *= f;
  }
  return rtn;
}
コード例 #15
0
Set<Deriv> FunctionalPolynomial
::findFuncsForSummation(const Set<MultipleDeriv>& prevSet,
                        const MultipleDeriv& currentDeriv) const
{
  Set<Deriv> rtn;

  for (Set<MultipleDeriv>::const_iterator
         i = prevSet.begin(); i != prevSet.end(); i++)
    {
      const MultipleDeriv& mdPrev = *i;
      TEUCHOS_TEST_FOR_EXCEPTION(currentDeriv.size()+1 != mdPrev.size(),
                         std::logic_error,
                         "deriv orders must differ by 1. Found "
                         "currentDeriv.size()=" << currentDeriv.size()
                         << " while mdPrev.size()=" << mdPrev.size());

      /* We are looking for cases where the previous multiple derivative
       * is equal to the current plus one *greater* element. In such cases, the
       * set difference will contain exactly one element, and that element
       * will be greater than or equal to the the upper bound of the current 
       * set */
      Set<Deriv> tmp;
      set_difference(mdPrev.begin(), mdPrev.end(),
                     currentDeriv.begin(), currentDeriv.end(),
                     inserter(tmp, tmp.begin()));
      if (tmp.size()==1)
        {
          const Deriv& d = *(tmp.begin());
          if (currentDeriv.upper_bound(d) == currentDeriv.end()) rtn.put(d);
        }
    }
  return rtn;
}
コード例 #16
0
void SparsitySuperset::addDeriv(const MultipleDeriv& d, 
                               const DerivState& state)
{
  maxOrder_ = std::max(d.order(), maxOrder_);

  if (containsDeriv(d))
    {
      const DerivState& oldState = states_[getIndex(d)];
      if (state > oldState) 
        {
          states_[getIndex(d)] = state;
          numConstantDerivs_--;
          numVectorDerivs_++;
        }
    }
  else
    {
      int index = derivs_.size();
      derivs_.append(d);
      states_.append(state);
      derivToIndexMap_.put(d, index);
      MultiIndex mi;
      for (MultipleDeriv::const_iterator i=d.begin(); 
           i != d.end(); i++)
        {
          if (i->isCoordDeriv())
            {
              MultiIndex m;
              int dir = i->coordDerivDir();
              m[dir] = 1;
              mi = mi + m;
            }

        }
      multiIndex_.append(mi);
      if (state==ConstantDeriv) numConstantDerivs_++;
      else numVectorDerivs_++;
    }
}
コード例 #17
0
MultipleDeriv MultipleDeriv::factorOutDeriv(const MultipleDeriv& x) const
{
  MultipleDeriv rtn = *this;

  for (MultipleDeriv::const_iterator i=x.begin(); i!=x.end(); i++)
  {
    MultipleDeriv::iterator j = rtn.find(*i);

    /* remove a single copy of the given derivative */
    if (j != rtn.end()) rtn.erase(j);
  }

  if (rtn.size() == this->size()) return MultipleDeriv();
  return rtn;
}
コード例 #18
0
Deriv DiffOpEvaluator::remainder(const MultipleDeriv& big, 
  const MultipleDeriv& little, int verb) const 
{
  Tabs tab;
  SUNDANCE_MSG5(verb, tab << "computing remainder: big=" << big << ", little="
    << little);
  TEUCHOS_TEST_FOR_EXCEPT(big.order()-little.order() != 1);

  MultipleDeriv r;
  if (little.order()==0) r = big;
  else r = big.factorOutDeriv(little);

  SUNDANCE_MSG5(verb, tab << "remainder = " << r);

  TEUCHOS_TEST_FOR_EXCEPT(r.order() != 1);

  return *(r.begin());
}
コード例 #19
0
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;
}
コード例 #20
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_
    );
}
コード例 #21
0
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);
    }
}
コード例 #22
0
ProductEvaluator::ProductEvaluator(const ProductExpr* expr,
  const EvalContext& context)
  : BinaryEvaluator<ProductExpr>(expr, context),
    maxOrder_(this->sparsity()->maxOrder()),
    resultIndex_(maxOrder_+1),
    resultIsConstant_(maxOrder_+1),
    hasWorkspace_(maxOrder_+1),
    workspaceIsLeft_(maxOrder_+1),
    workspaceIndex_(maxOrder_+1),
    workspaceCoeffIndex_(maxOrder_+1),
    workspaceCoeffIsConstant_(maxOrder_+1),
    ccTerms_(maxOrder_+1),
    cvTerms_(maxOrder_+1),
    vcTerms_(maxOrder_+1),
    vvTerms_(maxOrder_+1),
    startingVectors_(maxOrder_+1),
    startingParities_(maxOrder_+1)
{
  int verb = context.evalSetupVerbosity();

  try
  {
    Tabs tabs(0);
    {
      Tabs tab;
      Tabs tabz;
      SUNDANCE_MSG1(verb,
        tabs << "initializing product evaluator for " 
        << expr->toString());

      SUNDANCE_MSG2(verb,
        tab << "return sparsity " << std::endl
        << tabz << *(this->sparsity)());

      SUNDANCE_MSG2(verb,
        tab << "left sparsity " << std::endl 
        << tabz << *(leftSparsity()) << std::endl
        << tabz << "right sparsity " << std::endl 
        << tabz << *(rightSparsity()));
  
      SUNDANCE_MSG3(verb,
        tab << "left vector index map " 
        << leftEval()->vectorIndexMap() << std::endl
        << tabz << "right vector index map " 
        << rightEval()->vectorIndexMap() << std::endl
        << tabz << "left constant index map " 
        << leftEval()->constantIndexMap() << std::endl
        << tabz << "right constant index map " 
        << rightEval()->constantIndexMap());
    }                
    int vecResultIndex = 0;
    int constResultIndex = 0;

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

      SUNDANCE_MSG2(verb,
        tabs << std::endl 
        << tabs << "finding rules for deriv " << d);

      int order = d.order();

      /* Determine the index into which the result will be written */
      bool resultIsConstant = this->sparsity()->state(i)==ConstantDeriv; 
      resultIsConstant_[order].append(resultIsConstant);
      if (resultIsConstant)
      {
        SUNDANCE_MSG3(verb,
          tab0 << std::endl 
          << tab0 << "result will be in constant index " << constResultIndex);
        resultIndex_[order].append(constResultIndex);
        addConstantIndex(i, constResultIndex);
        constResultIndex++;
      }
      else
      {
        SUNDANCE_MSG3(verb,
          tab0 << std::endl 
          << tab0 << "result will be in constant index " << vecResultIndex);
        resultIndex_[order].append(vecResultIndex);
        addVectorIndex(i, vecResultIndex);
        vecResultIndex++;
      }

      /* If possible, we want to do the calculations in-place, writing into
       * one of the two operand's results vectors for the same derivative.
       * Provided that we process derivatives in descending order, it is
       * safe to destroy the operands' result vectors.
       */
       
      int dnLeftIndex = leftSparsity()->getIndex(d);
      int dnRightIndex = rightSparsity()->getIndex(d);

      
      bool hasVectorWorkspace = false;
      bool workspaceIsLeft = false;
      int workspaceIndex = -1;
      int workspaceCoeffIndex = -1;
      bool workspaceCoeffIsConstant = false;


      bool dnLeftIsConst = false;
      if (dnLeftIndex != -1) 
      {
        dnLeftIsConst = leftSparsity()->state(dnLeftIndex)==ConstantDeriv;
      }
      bool dnRightIsConst = false;
      if (dnRightIndex != -1)
      {
        dnRightIsConst = rightSparsity()->state(dnRightIndex)==ConstantDeriv;
      }

      /* First try to use the left result as a workspace */
      if (dnLeftIndex != -1 && !dnLeftIsConst 
        && rightSparsity()->containsDeriv(MultipleDeriv()))
      {
        /* We can write onto left vector */
        hasVectorWorkspace = true;
        workspaceIndex = leftEval()->vectorIndexMap().get(dnLeftIndex);       
        SUNDANCE_MSG3(verb,
          tab0 << "using left as workspace");
        workspaceIsLeft = true;
        int d0RightIndex = rightSparsity()->getIndex(MultipleDeriv());
        bool d0RightIsConst = rightSparsity()->state(d0RightIndex)==ConstantDeriv;
        workspaceCoeffIsConstant = d0RightIsConst;
        if (d0RightIsConst)
        {
          workspaceCoeffIndex 
            = rightEval()->constantIndexMap().get(d0RightIndex);
        }
        else
        {
          workspaceCoeffIndex 
            = rightEval()->vectorIndexMap().get(d0RightIndex);
        }
      }

      /* If the left didn't provide a workspace, try the right */
      if (!hasVectorWorkspace && dnRightIndex != -1 && !dnRightIsConst
        && leftSparsity()->containsDeriv(MultipleDeriv()))
      {
        /* We can write onto right vector */
        hasVectorWorkspace = true;
        workspaceIndex = rightEval()->vectorIndexMap().get(dnRightIndex); 
        workspaceIsLeft = false;
        SUNDANCE_MSG3(verb,
          tab0 << "using right as workspace");
        int d0LeftIndex = leftSparsity()->getIndex(MultipleDeriv());
        bool d0LeftIsConst = leftSparsity()->state(d0LeftIndex)==ConstantDeriv;
        workspaceCoeffIsConstant = d0LeftIsConst;
        if (d0LeftIsConst)
        {
          workspaceCoeffIndex 
            = leftEval()->constantIndexMap().get(d0LeftIndex);
        }
        else
        {
          workspaceCoeffIndex 
            = leftEval()->vectorIndexMap().get(d0LeftIndex);
        }
      }
      
      if (hasVectorWorkspace && verb > 2)
      {
        std::string wSide = "right";
        MultipleDeriv wsDeriv;
        if (workspaceIsLeft) 
        {
          wSide = "left";
          wsDeriv = leftSparsity()->deriv(dnLeftIndex);
        }
        else
        {
          wsDeriv = rightSparsity()->deriv(dnRightIndex);
        }
        SUNDANCE_MSG2(verb, tab0 << "has workspace vector: "
          << wSide << " deriv= " 
          << wsDeriv
          << ", coeff index= " << workspaceCoeffIndex);
      }
      else
      {
        SUNDANCE_MSG2(verb, tab0 << "has no workspace vector");
      }

      hasWorkspace_[order].append(hasVectorWorkspace);
      workspaceIsLeft_[order].append(workspaceIsLeft);
      workspaceIndex_[order].append(workspaceIndex);
      workspaceCoeffIndex_[order].append(workspaceCoeffIndex);
      workspaceCoeffIsConstant_[order].append(workspaceCoeffIsConstant);
      
      ProductRulePerms perms;
      d.productRulePermutations(perms);
      SUNDANCE_MSG4(verb,
        tabs << "product rule permutations " << perms);

      Array<Array<int> > ccTerms;
      Array<Array<int> > cvTerms;
      Array<Array<int> > vcTerms;
      Array<Array<int> > vvTerms;
      Array<int> startingVector;
      ProductParity startingParity;

      bool hasStartingVector = false;

      for (ProductRulePerms::const_iterator 
             iter = perms.begin(); iter != perms.end(); iter++)
      {
        Tabs tab1;
        MultipleDeriv dLeft = iter->first.first();
        MultipleDeriv dRight = iter->first.second();
        int multiplicity = iter->second;
          
        /* skip this combination if we've already pulled it out 
         * for workspace */
        if (hasVectorWorkspace && workspaceIsLeft 
          && dLeft.order()==order) continue;
        if (hasVectorWorkspace && !workspaceIsLeft 
          && dRight.order()==order) continue;

        if (!leftSparsity()->containsDeriv(dLeft)
          || !rightSparsity()->containsDeriv(dRight)) continue;
        int iLeft = leftSparsity()->getIndex(dLeft);
        int iRight = rightSparsity()->getIndex(dRight);

        if (iLeft==-1 || iRight==-1) continue;
        SUNDANCE_MSG4(verb,
          tab1 << "left deriv=" << dLeft);
        SUNDANCE_MSG4(verb,
          tab1 << "right deriv=" << dRight);

        bool leftIsConst = leftSparsity()->state(iLeft)==ConstantDeriv;
        bool rightIsConst = rightSparsity()->state(iRight)==ConstantDeriv;

        if (leftIsConst)
        {
          Tabs tab2;
          SUNDANCE_MSG4(verb,
            tab2 << "left is const");
          int leftIndex = leftEval()->constantIndexMap().get(iLeft);
          if (rightIsConst)
          {
            SUNDANCE_MSG4(verb,
              tab2 << "right is const");
            int rightIndex = rightEval()->constantIndexMap().get(iRight);
            ccTerms.append(tuple(leftIndex, rightIndex, multiplicity));
          }
          else
          {
            SUNDANCE_MSG4(verb,
              tab2 << "right is vec");
            int rightIndex = rightEval()->vectorIndexMap().get(iRight);
            if (!hasVectorWorkspace && !hasStartingVector)
            {
              SUNDANCE_MSG4(verb,
                tab1 << "found c-v starting vec");
              startingVector = tuple(leftIndex, rightIndex, 
                multiplicity);
              hasStartingVector = true;
              startingParity = ConstVec;
            }
            else
            {
              SUNDANCE_MSG4(verb,
                tab1 << "found c-v term");
              cvTerms.append(tuple(leftIndex, rightIndex, 
                  multiplicity));
            }
          }
        }
        else
        {
          Tabs tab2;
          SUNDANCE_MSG4(verb,
            tab2 << "left is vec");
          int leftIndex = leftEval()->vectorIndexMap().get(iLeft);
          if (rightIsConst)
          {
            SUNDANCE_MSG4(verb,
              tab2 << "right is const");
            int rightIndex = rightEval()->constantIndexMap().get(iRight);
            if (!hasVectorWorkspace && !hasStartingVector)
            {
              SUNDANCE_MSG4(verb,
                tab1 << "found v-c starting vec");
              startingVector = tuple(leftIndex, rightIndex, 
                multiplicity);
              hasStartingVector = true;
              startingParity = VecConst;
            }
            else
            {
              SUNDANCE_MSG4(verb,
                tab1 << "found v-c term");
              vcTerms.append(tuple(leftIndex, rightIndex, 
                  multiplicity));
            }
          }
          else
          {
            SUNDANCE_MSG4(verb,
              tab2 << "right is vec");
            int rightIndex = rightEval()->vectorIndexMap().get(iRight);
            if (!hasVectorWorkspace && !hasStartingVector)
            {
              SUNDANCE_MSG4(verb,
                tab1 << "found v-v starting vec");
              startingVector = tuple(leftIndex, rightIndex, 
                multiplicity);
              hasStartingVector = true;
              startingParity = VecVec;
            }
            else
            {
              SUNDANCE_MSG4(verb,
                tab1 << "found v-v term");
              vvTerms.append(tuple(leftIndex, rightIndex, 
                  multiplicity));
            }
          }
        }
      }
      ccTerms_[order].append(ccTerms);
      cvTerms_[order].append(cvTerms);
      vcTerms_[order].append(vcTerms);
      vvTerms_[order].append(vvTerms);
      startingVectors_[order].append(startingVector);
      startingParities_[order].append(startingParity);

      if (verb > 2)
      {
        Tabs tab0;
        Out::os() << tab0 << "deriv " << i << " order=" << order ;
        if (resultIsConstant)
        {
          Out::os() << " constant result, index= ";
        }
        else
        {
          Out::os() << " vector result, index= ";
        }
        Out::os() << resultIndex_[order] << std::endl;
        {
          Tabs tab1;
          if (hasStartingVector) 
          {
            Out::os() << tab1 << "starting vector " << startingVector << std::endl;
          }
          Out::os() << tab1 << "c-c terms " << ccTerms << std::endl;
          Out::os() << tab1 << "c-v terms " << cvTerms << std::endl;
          Out::os() << tab1 << "v-c terms " << vcTerms << std::endl;
          Out::os() << tab1 << "v-v terms " << vvTerms << std::endl;
        }
      }
    }

    if (verb > 2)
    {
      Out::os() << tabs << "maps: " << std::endl;
      Out::os() << tabs << "vector index map " << vectorIndexMap() << std::endl;
      Out::os() << tabs << "constant index map " << constantIndexMap() << std::endl;
    }
  }
  catch(std::exception& e)
  {
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, 
      "exception detected in ProductEvaluator: expr="
      << expr->toString() << std::endl
      << "exception=" << e.what());
  }
}
コード例 #23
0
MultipleDeriv makeMultiDeriv(const Deriv& d)
{
  MultipleDeriv rtn;
  rtn.put(d);
  return rtn;
}