예제 #1
0
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());
		}
}
예제 #2
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());
}
예제 #3
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;
}
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_++;
    }
}
예제 #5
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;
}
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());
  }
}