00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "SundanceProductEvaluator.hpp"
00043 #include "SundanceEvalManager.hpp"
00044 #include "SundanceProductExpr.hpp"
00045
00046 #include "PlayaTabs.hpp"
00047 #include "SundanceOut.hpp"
00048
00049 using namespace Sundance;
00050 using namespace Sundance;
00051 using namespace Sundance;
00052 using namespace Teuchos;
00053
00054
00055
00056
00057
00058 ProductEvaluator::ProductEvaluator(const ProductExpr* expr,
00059 const EvalContext& context)
00060 : BinaryEvaluator<ProductExpr>(expr, context),
00061 maxOrder_(this->sparsity()->maxOrder()),
00062 resultIndex_(maxOrder_+1),
00063 resultIsConstant_(maxOrder_+1),
00064 hasWorkspace_(maxOrder_+1),
00065 workspaceIsLeft_(maxOrder_+1),
00066 workspaceIndex_(maxOrder_+1),
00067 workspaceCoeffIndex_(maxOrder_+1),
00068 workspaceCoeffIsConstant_(maxOrder_+1),
00069 ccTerms_(maxOrder_+1),
00070 cvTerms_(maxOrder_+1),
00071 vcTerms_(maxOrder_+1),
00072 vvTerms_(maxOrder_+1),
00073 startingVectors_(maxOrder_+1),
00074 startingParities_(maxOrder_+1)
00075 {
00076 int verb = context.evalSetupVerbosity();
00077
00078 try
00079 {
00080 Tabs tabs(0);
00081 {
00082 Tabs tab;
00083 Tabs tabz;
00084 SUNDANCE_MSG1(verb,
00085 tabs << "initializing product evaluator for "
00086 << expr->toString());
00087
00088 SUNDANCE_MSG2(verb,
00089 tab << "return sparsity " << std::endl
00090 << tabz << *(this->sparsity)());
00091
00092 SUNDANCE_MSG2(verb,
00093 tab << "left sparsity " << std::endl
00094 << tabz << *(leftSparsity()) << std::endl
00095 << tabz << "right sparsity " << std::endl
00096 << tabz << *(rightSparsity()));
00097
00098 SUNDANCE_MSG3(verb,
00099 tab << "left vector index map "
00100 << leftEval()->vectorIndexMap() << std::endl
00101 << tabz << "right vector index map "
00102 << rightEval()->vectorIndexMap() << std::endl
00103 << tabz << "left constant index map "
00104 << leftEval()->constantIndexMap() << std::endl
00105 << tabz << "right constant index map "
00106 << rightEval()->constantIndexMap());
00107 }
00108 int vecResultIndex = 0;
00109 int constResultIndex = 0;
00110
00111 for (int i=0; i<this->sparsity()->numDerivs(); i++)
00112 {
00113 Tabs tab0;
00114 const MultipleDeriv& d = this->sparsity()->deriv(i);
00115
00116 SUNDANCE_MSG2(verb,
00117 tabs << std::endl
00118 << tabs << "finding rules for deriv " << d);
00119
00120 int order = d.order();
00121
00122
00123 bool resultIsConstant = this->sparsity()->state(i)==ConstantDeriv;
00124 resultIsConstant_[order].append(resultIsConstant);
00125 if (resultIsConstant)
00126 {
00127 SUNDANCE_MSG3(verb,
00128 tab0 << std::endl
00129 << tab0 << "result will be in constant index " << constResultIndex);
00130 resultIndex_[order].append(constResultIndex);
00131 addConstantIndex(i, constResultIndex);
00132 constResultIndex++;
00133 }
00134 else
00135 {
00136 SUNDANCE_MSG3(verb,
00137 tab0 << std::endl
00138 << tab0 << "result will be in constant index " << vecResultIndex);
00139 resultIndex_[order].append(vecResultIndex);
00140 addVectorIndex(i, vecResultIndex);
00141 vecResultIndex++;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150 int dnLeftIndex = leftSparsity()->getIndex(d);
00151 int dnRightIndex = rightSparsity()->getIndex(d);
00152
00153
00154 bool hasVectorWorkspace = false;
00155 bool workspaceIsLeft = false;
00156 int workspaceIndex = -1;
00157 int workspaceCoeffIndex = -1;
00158 bool workspaceCoeffIsConstant = false;
00159
00160
00161 bool dnLeftIsConst = false;
00162 if (dnLeftIndex != -1)
00163 {
00164 dnLeftIsConst = leftSparsity()->state(dnLeftIndex)==ConstantDeriv;
00165 }
00166 bool dnRightIsConst = false;
00167 if (dnRightIndex != -1)
00168 {
00169 dnRightIsConst = rightSparsity()->state(dnRightIndex)==ConstantDeriv;
00170 }
00171
00172
00173 if (dnLeftIndex != -1 && !dnLeftIsConst
00174 && rightSparsity()->containsDeriv(MultipleDeriv()))
00175 {
00176
00177 hasVectorWorkspace = true;
00178 workspaceIndex = leftEval()->vectorIndexMap().get(dnLeftIndex);
00179 SUNDANCE_MSG3(verb,
00180 tab0 << "using left as workspace");
00181 workspaceIsLeft = true;
00182 int d0RightIndex = rightSparsity()->getIndex(MultipleDeriv());
00183 bool d0RightIsConst = rightSparsity()->state(d0RightIndex)==ConstantDeriv;
00184 workspaceCoeffIsConstant = d0RightIsConst;
00185 if (d0RightIsConst)
00186 {
00187 workspaceCoeffIndex
00188 = rightEval()->constantIndexMap().get(d0RightIndex);
00189 }
00190 else
00191 {
00192 workspaceCoeffIndex
00193 = rightEval()->vectorIndexMap().get(d0RightIndex);
00194 }
00195 }
00196
00197
00198 if (!hasVectorWorkspace && dnRightIndex != -1 && !dnRightIsConst
00199 && leftSparsity()->containsDeriv(MultipleDeriv()))
00200 {
00201
00202 hasVectorWorkspace = true;
00203 workspaceIndex = rightEval()->vectorIndexMap().get(dnRightIndex);
00204 workspaceIsLeft = false;
00205 SUNDANCE_MSG3(verb,
00206 tab0 << "using right as workspace");
00207 int d0LeftIndex = leftSparsity()->getIndex(MultipleDeriv());
00208 bool d0LeftIsConst = leftSparsity()->state(d0LeftIndex)==ConstantDeriv;
00209 workspaceCoeffIsConstant = d0LeftIsConst;
00210 if (d0LeftIsConst)
00211 {
00212 workspaceCoeffIndex
00213 = leftEval()->constantIndexMap().get(d0LeftIndex);
00214 }
00215 else
00216 {
00217 workspaceCoeffIndex
00218 = leftEval()->vectorIndexMap().get(d0LeftIndex);
00219 }
00220 }
00221
00222 if (hasVectorWorkspace && verb > 2)
00223 {
00224 std::string wSide = "right";
00225 MultipleDeriv wsDeriv;
00226 if (workspaceIsLeft)
00227 {
00228 wSide = "left";
00229 wsDeriv = leftSparsity()->deriv(dnLeftIndex);
00230 }
00231 else
00232 {
00233 wsDeriv = rightSparsity()->deriv(dnRightIndex);
00234 }
00235 SUNDANCE_MSG2(verb, tab0 << "has workspace vector: "
00236 << wSide << " deriv= "
00237 << wsDeriv
00238 << ", coeff index= " << workspaceCoeffIndex);
00239 }
00240 else
00241 {
00242 SUNDANCE_MSG2(verb, tab0 << "has no workspace vector");
00243 }
00244
00245 hasWorkspace_[order].append(hasVectorWorkspace);
00246 workspaceIsLeft_[order].append(workspaceIsLeft);
00247 workspaceIndex_[order].append(workspaceIndex);
00248 workspaceCoeffIndex_[order].append(workspaceCoeffIndex);
00249 workspaceCoeffIsConstant_[order].append(workspaceCoeffIsConstant);
00250
00251 ProductRulePerms perms;
00252 d.productRulePermutations(perms);
00253 SUNDANCE_MSG4(verb,
00254 tabs << "product rule permutations " << perms);
00255
00256 Array<Array<int> > ccTerms;
00257 Array<Array<int> > cvTerms;
00258 Array<Array<int> > vcTerms;
00259 Array<Array<int> > vvTerms;
00260 Array<int> startingVector;
00261 ProductParity startingParity;
00262
00263 bool hasStartingVector = false;
00264
00265 for (ProductRulePerms::const_iterator
00266 iter = perms.begin(); iter != perms.end(); iter++)
00267 {
00268 Tabs tab1;
00269 MultipleDeriv dLeft = iter->first.first();
00270 MultipleDeriv dRight = iter->first.second();
00271 int multiplicity = iter->second;
00272
00273
00274
00275 if (hasVectorWorkspace && workspaceIsLeft
00276 && dLeft.order()==order) continue;
00277 if (hasVectorWorkspace && !workspaceIsLeft
00278 && dRight.order()==order) continue;
00279
00280 if (!leftSparsity()->containsDeriv(dLeft)
00281 || !rightSparsity()->containsDeriv(dRight)) continue;
00282 int iLeft = leftSparsity()->getIndex(dLeft);
00283 int iRight = rightSparsity()->getIndex(dRight);
00284
00285 if (iLeft==-1 || iRight==-1) continue;
00286 SUNDANCE_MSG4(verb,
00287 tab1 << "left deriv=" << dLeft);
00288 SUNDANCE_MSG4(verb,
00289 tab1 << "right deriv=" << dRight);
00290
00291 bool leftIsConst = leftSparsity()->state(iLeft)==ConstantDeriv;
00292 bool rightIsConst = rightSparsity()->state(iRight)==ConstantDeriv;
00293
00294 if (leftIsConst)
00295 {
00296 Tabs tab2;
00297 SUNDANCE_MSG4(verb,
00298 tab2 << "left is const");
00299 int leftIndex = leftEval()->constantIndexMap().get(iLeft);
00300 if (rightIsConst)
00301 {
00302 SUNDANCE_MSG4(verb,
00303 tab2 << "right is const");
00304 int rightIndex = rightEval()->constantIndexMap().get(iRight);
00305 ccTerms.append(tuple(leftIndex, rightIndex, multiplicity));
00306 }
00307 else
00308 {
00309 SUNDANCE_MSG4(verb,
00310 tab2 << "right is vec");
00311 int rightIndex = rightEval()->vectorIndexMap().get(iRight);
00312 if (!hasVectorWorkspace && !hasStartingVector)
00313 {
00314 SUNDANCE_MSG4(verb,
00315 tab1 << "found c-v starting vec");
00316 startingVector = tuple(leftIndex, rightIndex,
00317 multiplicity);
00318 hasStartingVector = true;
00319 startingParity = ConstVec;
00320 }
00321 else
00322 {
00323 SUNDANCE_MSG4(verb,
00324 tab1 << "found c-v term");
00325 cvTerms.append(tuple(leftIndex, rightIndex,
00326 multiplicity));
00327 }
00328 }
00329 }
00330 else
00331 {
00332 Tabs tab2;
00333 SUNDANCE_MSG4(verb,
00334 tab2 << "left is vec");
00335 int leftIndex = leftEval()->vectorIndexMap().get(iLeft);
00336 if (rightIsConst)
00337 {
00338 SUNDANCE_MSG4(verb,
00339 tab2 << "right is const");
00340 int rightIndex = rightEval()->constantIndexMap().get(iRight);
00341 if (!hasVectorWorkspace && !hasStartingVector)
00342 {
00343 SUNDANCE_MSG4(verb,
00344 tab1 << "found v-c starting vec");
00345 startingVector = tuple(leftIndex, rightIndex,
00346 multiplicity);
00347 hasStartingVector = true;
00348 startingParity = VecConst;
00349 }
00350 else
00351 {
00352 SUNDANCE_MSG4(verb,
00353 tab1 << "found v-c term");
00354 vcTerms.append(tuple(leftIndex, rightIndex,
00355 multiplicity));
00356 }
00357 }
00358 else
00359 {
00360 SUNDANCE_MSG4(verb,
00361 tab2 << "right is vec");
00362 int rightIndex = rightEval()->vectorIndexMap().get(iRight);
00363 if (!hasVectorWorkspace && !hasStartingVector)
00364 {
00365 SUNDANCE_MSG4(verb,
00366 tab1 << "found v-v starting vec");
00367 startingVector = tuple(leftIndex, rightIndex,
00368 multiplicity);
00369 hasStartingVector = true;
00370 startingParity = VecVec;
00371 }
00372 else
00373 {
00374 SUNDANCE_MSG4(verb,
00375 tab1 << "found v-v term");
00376 vvTerms.append(tuple(leftIndex, rightIndex,
00377 multiplicity));
00378 }
00379 }
00380 }
00381 }
00382 ccTerms_[order].append(ccTerms);
00383 cvTerms_[order].append(cvTerms);
00384 vcTerms_[order].append(vcTerms);
00385 vvTerms_[order].append(vvTerms);
00386 startingVectors_[order].append(startingVector);
00387 startingParities_[order].append(startingParity);
00388
00389 if (verb > 2)
00390 {
00391 Tabs tab0;
00392 Out::os() << tab0 << "deriv " << i << " order=" << order ;
00393 if (resultIsConstant)
00394 {
00395 Out::os() << " constant result, index= ";
00396 }
00397 else
00398 {
00399 Out::os() << " vector result, index= ";
00400 }
00401 Out::os() << resultIndex_[order] << std::endl;
00402 {
00403 Tabs tab1;
00404 if (hasStartingVector)
00405 {
00406 Out::os() << tab1 << "starting vector " << startingVector << std::endl;
00407 }
00408 Out::os() << tab1 << "c-c terms " << ccTerms << std::endl;
00409 Out::os() << tab1 << "c-v terms " << cvTerms << std::endl;
00410 Out::os() << tab1 << "v-c terms " << vcTerms << std::endl;
00411 Out::os() << tab1 << "v-v terms " << vvTerms << std::endl;
00412 }
00413 }
00414 }
00415
00416 if (verb > 2)
00417 {
00418 Out::os() << tabs << "maps: " << std::endl;
00419 Out::os() << tabs << "vector index map " << vectorIndexMap() << std::endl;
00420 Out::os() << tabs << "constant index map " << constantIndexMap() << std::endl;
00421 }
00422 }
00423 catch(std::exception& e)
00424 {
00425 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00426 "exception detected in ProductEvaluator: expr="
00427 << expr->toString() << std::endl
00428 << "exception=" << e.what());
00429 }
00430 }
00431
00432 void ProductEvaluator
00433 ::internalEval(const EvalManager& mgr,
00434 Array<double>& constantResults,
00435 Array<RCP<EvalVector> >& vectorResults) const
00436 {
00437 Tabs tabs(0);
00438
00439 SUNDANCE_MSG1(mgr.verb(),
00440 tabs << "ProductEvaluator::eval() expr="
00441 << expr()->toString());
00442
00443
00444 Array<RCP<EvalVector> > leftVectorResults;
00445 Array<RCP<EvalVector> > rightVectorResults;
00446 Array<double> leftConstantResults;
00447 Array<double> rightConstantResults;
00448 evalChildren(mgr, leftConstantResults, leftVectorResults,
00449 rightConstantResults, rightVectorResults);
00450
00451 if (mgr.verb() > 2)
00452 {
00453 Out::os() << tabs << "left operand results" << std::endl;
00454 mgr.showResults(Out::os(), leftSparsity(), leftVectorResults,
00455 leftConstantResults);
00456 Out::os() << tabs << "right operand results" << std::endl;
00457 mgr.showResults(Out::os(), rightSparsity(), rightVectorResults,
00458 rightConstantResults);
00459 }
00460
00461 constantResults.resize(this->sparsity()->numConstantDerivs());
00462 vectorResults.resize(this->sparsity()->numVectorDerivs());
00463
00464
00465
00466
00467
00468 for (int order=maxOrder_; order>=0; order--)
00469 {
00470 for (int i=0; i<resultIndex_[order].size(); i++)
00471 {
00472 double constantVal = 0.0;
00473 const Array<Array<int> >& ccTerms = ccTerms_[order][i];
00474 for (int j=0; j<ccTerms.size(); j++)
00475 {
00476
00477 constantVal += leftConstantResults[ccTerms[j][0]]
00478 * rightConstantResults[ccTerms[j][1]] * ccTerms[j][2];
00479 }
00480
00481 if (resultIsConstant_[order][i])
00482 {
00483 constantResults[resultIndex_[order][i]] = constantVal;
00484 continue;
00485 }
00486
00487
00488
00489
00490
00491
00492 RCP<EvalVector> result;
00493 if (hasWorkspace_[order][i])
00494 {
00495 int index = workspaceIndex_[order][i];
00496 int coeffIndex = workspaceCoeffIndex_[order][i];
00497 bool coeffIsConstant = workspaceCoeffIsConstant_[order][i];
00498 if (workspaceIsLeft_[order][i])
00499 {
00500 result = leftVectorResults[index];
00501 if (coeffIsConstant)
00502 {
00503 const double& coeff = rightConstantResults[coeffIndex];
00504 if (!isOne(coeff)) result->multiply_S(coeff);
00505 }
00506 else
00507 {
00508 const RCP<EvalVector>& coeff
00509 = rightVectorResults[coeffIndex];
00510 result->multiply_V(coeff.get());
00511 }
00512 }
00513 else
00514 {
00515 result = rightVectorResults[index];
00516 if (coeffIsConstant)
00517 {
00518 const double& coeff = leftConstantResults[coeffIndex];
00519 if (!isOne(coeff)) result->multiply_S(coeff);
00520 }
00521 else
00522 {
00523 const RCP<EvalVector>& coeff
00524 = leftVectorResults[coeffIndex];
00525 result->multiply_V(coeff.get());
00526 }
00527 }
00528 SUNDANCE_MSG5(mgr.verb(), tabs << "workspace = " << result->str());
00529 }
00530 else
00531 {
00532 result = mgr.popVector();
00533 const Array<int>& sv = startingVectors_[order][i];
00534 int multiplicity = sv[2];
00535 switch(startingParities_[order][i])
00536 {
00537 case VecVec:
00538 if (!isZero(constantVal))
00539 {
00540 if (!isOne(multiplicity))
00541 {
00542 result->setTo_S_add_SVV(constantVal,
00543 multiplicity,
00544 leftVectorResults[sv[0]].get(),
00545 rightVectorResults[sv[1]].get());
00546 }
00547 else
00548 {
00549 result->setTo_S_add_VV(constantVal,
00550 leftVectorResults[sv[0]].get(),
00551 rightVectorResults[sv[1]].get());
00552 }
00553 }
00554 else
00555 {
00556 if (!isOne(multiplicity))
00557 {
00558 result->setTo_SVV(multiplicity,
00559 leftVectorResults[sv[0]].get(),
00560 rightVectorResults[sv[1]].get());
00561 }
00562 else
00563 {
00564 result->setTo_VV(leftVectorResults[sv[0]].get(),
00565 rightVectorResults[sv[1]].get());
00566 }
00567 }
00568 SUNDANCE_MSG5(mgr.verb(), tabs << "init to v-v prod, m="
00569 << multiplicity << ", left="
00570 << leftVectorResults[sv[0]]->str()
00571 << ", right="
00572 << rightVectorResults[sv[1]]->str()
00573 << ", result=" << result->str());
00574 break;
00575 case VecConst:
00576 if (!isZero(constantVal))
00577 {
00578 if (!isOne(multiplicity*rightConstantResults[sv[1]]))
00579 {
00580 result->setTo_S_add_SV(constantVal,
00581 multiplicity
00582 *rightConstantResults[sv[1]],
00583 leftVectorResults[sv[0]].get());
00584 }
00585 else
00586 {
00587 result->setTo_S_add_V(constantVal,
00588 leftVectorResults[sv[0]].get());
00589 }
00590 }
00591 else
00592 {
00593 if (!isOne(multiplicity*rightConstantResults[sv[1]]))
00594 {
00595 result->setTo_SV(multiplicity
00596 *rightConstantResults[sv[1]],
00597 leftVectorResults[sv[0]].get());
00598 }
00599 else
00600 {
00601 result->setTo_V(leftVectorResults[sv[0]].get());
00602 }
00603 }
00604 SUNDANCE_MSG5(mgr.verb(), tabs << "init to v-c prod, m="
00605 << multiplicity << ", left="
00606 << leftVectorResults[sv[0]]->str()
00607 << ", right="
00608 << rightConstantResults[sv[1]]
00609 << ", result=" << result->str());
00610 break;
00611 case ConstVec:
00612 if (!isZero(constantVal))
00613 {
00614 if (!isOne(multiplicity*leftConstantResults[sv[0]]))
00615 {
00616 result->setTo_S_add_SV(constantVal,
00617 multiplicity
00618 *leftConstantResults[sv[0]],
00619 rightVectorResults[sv[1]].get());
00620 }
00621 else
00622 {
00623 result->setTo_S_add_V(constantVal,
00624 rightVectorResults[sv[1]].get());
00625 }
00626 }
00627 else
00628 {
00629 if (!isOne(multiplicity*leftConstantResults[sv[0]]))
00630 {
00631 result->setTo_SV(multiplicity
00632 *leftConstantResults[sv[0]],
00633 rightVectorResults[sv[1]].get());
00634 }
00635 else
00636 {
00637 result->setTo_V(rightVectorResults[sv[1]].get());
00638 }
00639 }
00640 SUNDANCE_MSG5(mgr.verb(), tabs << "init to c-v prod, m="
00641 << multiplicity << ", left="
00642 << leftConstantResults[sv[0]]
00643 << ", right="
00644 << rightVectorResults[sv[1]]->str()
00645 << ", result=" << result->str());
00646
00647 }
00648 SUNDANCE_MSG4(mgr.verb(), tabs << "starting value = " << result->str());
00649 }
00650 vectorResults[resultIndex_[order][i]] = result;
00651
00652 const Array<Array<int> >& cvTerms = cvTerms_[order][i];
00653 const Array<Array<int> >& vcTerms = vcTerms_[order][i];
00654 const Array<Array<int> >& vvTerms = vvTerms_[order][i];
00655
00656 for (int j=0; j<cvTerms.size(); j++)
00657 {
00658 SUNDANCE_MSG4(mgr.verb(), tabs << "adding c-v term " << cvTerms[j]);
00659
00660 double multiplicity = cvTerms[j][2];
00661 double scalar = multiplicity*leftConstantResults[cvTerms[j][0]];
00662 const EvalVector* vec = rightVectorResults[cvTerms[j][1]].get();
00663 if (!isOne(scalar))
00664 {
00665 result->add_SV(scalar, vec);
00666 }
00667 else
00668 {
00669 result->add_V(vec);
00670 }
00671 }
00672
00673 for (int j=0; j<vcTerms.size(); j++)
00674 {
00675 SUNDANCE_MSG4(mgr.verb(), tabs << "adding v-c term " << vcTerms[j]);
00676
00677 double multiplicity = vcTerms[j][2];
00678 double scalar = multiplicity*rightConstantResults[vcTerms[j][1]];
00679 const EvalVector* vec = leftVectorResults[vcTerms[j][0]].get();
00680 if (!isOne(scalar))
00681 {
00682 result->add_SV(scalar, vec);
00683 }
00684 else
00685 {
00686 result->add_V(vec);
00687 }
00688 }
00689
00690 for (int j=0; j<vvTerms.size(); j++)
00691 {
00692 SUNDANCE_MSG4(mgr.verb(), tabs << "adding v-v term " << vvTerms[j]);
00693
00694 double multiplicity = vvTerms[j][2];
00695 const EvalVector* vec1 = leftVectorResults[vvTerms[j][0]].get();
00696 const EvalVector* vec2 = rightVectorResults[vvTerms[j][1]].get();
00697 if (!isOne(multiplicity))
00698 {
00699 result->add_SVV(multiplicity, vec1, vec2);
00700 }
00701 else
00702 {
00703 result->add_VV(vec1, vec2);
00704 }
00705 }
00706
00707
00708 }
00709 }
00710
00711 if (mgr.verb() > 1)
00712 {
00713 Out::os() << tabs << "product result " << std::endl;
00714 mgr.showResults(Out::os(), this->sparsity(), vectorResults,
00715 constantResults);
00716 }
00717 }