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 "SundanceFunctionSupportResolver.hpp"
00043 #include "PlayaTabs.hpp"
00044 #include "SundanceSumOfBCs.hpp"
00045 #include "SundanceRegionQuadCombo.hpp"
00046 #include "SundanceOut.hpp"
00047 #include "SundanceUnknownFuncElement.hpp"
00048 #include "SundanceSpectralExpr.hpp"
00049 #include "SundanceUnknownParameterElement.hpp"
00050 #include "SundanceTestFuncElement.hpp"
00051 #include "PlayaExceptions.hpp"
00052
00053 using namespace Sundance;
00054 using namespace Sundance;
00055 using namespace Teuchos;
00056 using namespace std;
00057
00058 FunctionSupportResolver::FunctionSupportResolver(
00059 const Expr& eqns,
00060 const Expr& bcs,
00061 const Array<Expr>& vars,
00062 const Array<Expr>& unks,
00063 const Expr& unkParams,
00064 const Expr& fixedParams,
00065 const Array<Expr>& fixedFields,
00066 bool isVariational)
00067 :
00068 eqns_(eqns),
00069 bcs_(bcs),
00070 integralSum_(dynamic_cast<const SumOfIntegrals*>(eqns.ptr().get())),
00071 bcSum_(0),
00072 varFuncSet_(),
00073 unkFuncSet_(),
00074 unkParamSet_(),
00075 fixedParamSet_(),
00076 regions_(),
00077 regionToIndexMap_(),
00078 varsOnRegions_(),
00079 unksOnRegions_(),
00080 bcVarsOnRegions_(),
00081 bcUnksOnRegions_(),
00082 testToRegionsMap_(),
00083 unkToRegionsMap_(),
00084 varFuncData_(),
00085 unkFuncData_(),
00086 varFuncs_(flattenSpectral(vars)),
00087 unkFuncs_(flattenSpectral(unks)),
00088 fixedFields_(flattenSpectral(fixedFields)),
00089 unkParams_(unkParams),
00090 fixedParams_(fixedParams),
00091 varIDToReducedIDMap_(),
00092 unkIDToReducedIDMap_(),
00093 unkParamIDToReducedUnkParamIDMap_(),
00094 fixedParamIDToReducedFixedParamIDMap_(),
00095 varIDToBlockMap_(),
00096 unkIDToBlockMap_(),
00097 unreducedVarID_(),
00098 unreducedUnkID_(),
00099 unreducedUnkParamID_(),
00100 unreducedFixedParamID_(),
00101 isVariationalProblem_(isVariational)
00102 {
00103 Tabs tab0(0);
00104 Tabs tab1;
00105
00106
00107
00108
00109 TEUCHOS_TEST_FOR_EXCEPTION(eqns.ptr().get()==0, std::runtime_error,
00110 "FunctionSupportResolver ctor detected empty equation set input");
00111
00112 TEUCHOS_TEST_FOR_EXCEPTION(integralSum_==0, std::runtime_error,
00113 "FunctionSupportResolver ctor detected an input equation set that "
00114 "is not in integral form");
00115
00116 bool hasBCs = false;
00117 if (bcs.ptr().get() != 0)
00118 {
00119 bcSum_ = dynamic_cast<const SumOfBCs*>(bcs.ptr().get());
00120 TEUCHOS_TEST_FOR_EXCEPTION(bcSum_==0, std::runtime_error,
00121 "FunctionSupport ctor detected an input Essential "
00122 "BC that is not an EssentialBC object. "
00123 "Object is " << bcs);
00124 hasBCs = true;
00125 }
00126
00127
00128 int verb = 0;
00129 if (integralSum_->hasWatchedTerm() || (hasBCs && bcSum_->hasWatchedTerm()))
00130 {
00131 int v1 = integralSum_->eqnSetSetupVerb();
00132 int v2 = 0;
00133 if (hasBCs) v2 = bcSum_->eqnSetSetupVerb();
00134 verb = std::max(verb, max(v1, v2));
00135 }
00136 SUNDANCE_BANNER1(verb, tab0, "FunctionSupportResolver setup");
00137
00138 if (hasBCs)
00139 {
00140 SUNDANCE_MSG1(verb, tab1 << "Problem has EssentialBCs");
00141 }
00142 else
00143 {
00144 SUNDANCE_MSG1(verb, tab1 << "Problem has no EssentialBCs");
00145 }
00146
00147 SUNDANCE_MSG1(verb, tab1 << "verbosity is " << verb);
00148
00149
00150
00151
00152
00153
00154
00155 bool varsAreTestFunctions = false;
00156 for (int b=0; b<vars.size(); b++)
00157 {
00158 for (int i=0; i<vars[b].size(); i++)
00159 {
00160 const TestFuncElement* t
00161 = dynamic_cast<const TestFuncElement*>(vars[b][i].ptr().get());
00162 TEUCHOS_TEST_FOR_EXCEPTION(t == 0 && varsAreTestFunctions==true,
00163 std::runtime_error,
00164 "variational function list " << vars
00165 << " contains a mix of test and "
00166 "non-test functions");
00167 TEUCHOS_TEST_FOR_EXCEPTION(t != 0 && i>0 && varsAreTestFunctions==false,
00168 std::runtime_error,
00169 "variational function list " << vars
00170 << " contains a mix of test and "
00171 "non-test functions");
00172 if (t!=0) varsAreTestFunctions=true;
00173 }
00174 }
00175
00176 TEUCHOS_TEST_FOR_EXCEPTION(varsAreTestFunctions == true
00177 && isVariationalProblem_,
00178 std::runtime_error,
00179 "test functions given to a variational equation set");
00180
00181 TEUCHOS_TEST_FOR_EXCEPTION(varsAreTestFunctions == false
00182 && !isVariationalProblem_,
00183 std::runtime_error,
00184 "variational functions are unknowns, but equation "
00185 "set is not variational");
00186
00187 if (isVariationalProblem_)
00188 {
00189 SUNDANCE_MSG1(verb, tab1 << "is variational problem");
00190 }
00191 else
00192 {
00193 SUNDANCE_MSG1(verb, tab1 << "is not in variational form");
00194 }
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 varFuncData_.resize(vars.size());
00205 unkFuncData_.resize(unks.size());
00206 varIDToReducedIDMap_.resize(vars.size());
00207 unreducedVarID_.resize(vars.size());
00208
00209
00210
00211
00212 for (int b=0; b<vars.size(); b++)
00213 {
00214 Tabs tab2;
00215 unreducedVarID_[b].resize(vars[b].size());
00216 int k=0;
00217 for (int i=0; i<vars[b].size(); i++)
00218 {
00219 const FuncElementBase* t
00220 = dynamic_cast<const FuncElementBase*>(vars[b][i].ptr().get());
00221 int fid = t->fid().dofID();
00222 if (varFuncSet_.contains(fid)) continue;
00223 varFuncData_[b].append(getSharedFunctionData(t));
00224 varFuncSet_.put(fid);
00225 varIDToBlockMap_.put(fid, b);
00226 varIDToReducedIDMap_[b].put(fid, k);
00227 unreducedVarID_[b][k] = fid;
00228 k++;
00229 }
00230 SUNDANCE_MSG2(verb, tab2 << "block=" << b << " var functions are "
00231 << unreducedVarID_[b]);
00232 }
00233
00234
00235 unkIDToReducedIDMap_.resize(unks.size());
00236 unreducedUnkID_.resize(unks.size());
00237 for (int b=0; b<unks.size(); b++)
00238 {
00239 Tabs tab2;
00240 unreducedUnkID_[b].resize(unks[b].size());
00241 int k=0;
00242 for (int i=0; i<unks[b].size(); i++)
00243 {
00244 const UnknownFuncElement* u
00245 = dynamic_cast<const UnknownFuncElement*>(unks[b][i].ptr().get());
00246 TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::runtime_error,
00247 "EquationSet ctor input unk function "
00248 << unks[b][i]
00249 << " does not appear to be a unk function");
00250 int fid = u->fid().dofID();
00251 if (unkFuncSet_.contains(fid)) continue;
00252 unkFuncData_[b].append(getSharedFunctionData(u));
00253 unkFuncSet_.put(fid);
00254 unkIDToBlockMap_.put(fid, b);
00255 unkIDToReducedIDMap_[b].put(fid, k);
00256 unreducedUnkID_[b][k] = fid;
00257 k++;
00258 }
00259 SUNDANCE_MSG2(verb, tab2 << "block=" << b << " unk functions are "
00260 << unreducedUnkID_[b]);
00261 }
00262
00263
00264
00265
00266
00267 unreducedUnkParamID_.resize(unkParams.size());
00268 for (int i=0; i<unkParams.size(); i++)
00269 {
00270 const UnknownParameterElement* u
00271 = dynamic_cast<const UnknownParameterElement*>(unkParams[i].ptr().get());
00272 TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::runtime_error,
00273 "EquationSet ctor input unk parameter "
00274 << unkParams[i]
00275 << " does not appear to be a unk parameter");
00276 int fid = u->fid().dofID();
00277 unkParamSet_.put(fid);
00278 unkParamIDToReducedUnkParamIDMap_.put(fid, i);
00279 unreducedUnkParamID_[i] = fid;
00280 }
00281 SUNDANCE_MSG2(verb, tab1 << "unk parameters are "
00282 << unreducedUnkParamID_);
00283
00284
00285
00286
00287 unreducedFixedParamID_.resize(fixedParams.size());
00288 for (int i=0; i<fixedParams.size(); i++)
00289 {
00290 const UnknownParameterElement* u
00291 = dynamic_cast<const UnknownParameterElement*>(fixedParams[i].ptr().get());
00292 TEUCHOS_TEST_FOR_EXCEPTION(u==0, std::runtime_error,
00293 "EquationSet ctor input fixed parameter "
00294 << fixedParams[i]
00295 << " does not appear to be a fixed parameter");
00296 int fid = u->fid().dofID();
00297 fixedParamSet_.put(fid);
00298 fixedParamIDToReducedFixedParamIDMap_.put(fid, i);
00299 unreducedFixedParamID_[i] = fid;
00300 }
00301 SUNDANCE_MSG2(verb, tab1 << "fixed parameters are "
00302 << unreducedFixedParamID_);
00303
00304 Set<OrderedHandle<CellFilterStub> > regionSet;
00305
00306
00307 SUNDANCE_MSG1(verb, tab1 << "processing integral terms");
00308 {
00309 Tabs tab2;
00310 SUNDANCE_MSG3(verb, tab2 << integralSum_->rqcToExprMap());
00311 }
00312 for (Sundance::Map<RegionQuadCombo, Expr>::const_iterator
00313 r=integralSum_->rqcToExprMap().begin();
00314 r!=integralSum_->rqcToExprMap().end(); r++)
00315 {
00316 Tabs tab15;
00317 Tabs tab2;
00318 RegionQuadCombo rqc = r->first;
00319 int rqcVerb = verb;
00320 if (rqc.watch().isActive())
00321 {
00322 rqcVerb=rqc.watch().param("equation set setup");
00323 SUNDANCE_MSG1(max(verb, rqcVerb), tab15 << "processing RQC = " << rqc);
00324 }
00325
00326 Expr term = r->second;
00327
00328 SUNDANCE_MSG2(rqcVerb, tab2 << "expr = " << term);
00329 OrderedHandle<CellFilterStub> reg = rqc.domain();
00330
00331 if (!regionSet.contains(reg))
00332 {
00333 regionSet.put(reg);
00334 Set<int> vf = integralSum_->funcsOnRegion(reg, varFuncSet_);
00335 Set<int> uf = integralSum_->funcsOnRegion(reg, unkFuncSet_);
00336 SUNDANCE_MSG2(rqcVerb, tab2 << "vf = " << vf);
00337 SUNDANCE_MSG2(rqcVerb, tab2 << "uf = " << uf);
00338 varsOnRegions_.put(reg, vf);
00339 unksOnRegions_.put(reg, uf);
00340 }
00341 else
00342 {
00343 Set<int>& t = varsOnRegions_.get(reg);
00344 t.merge(integralSum_->funcsOnRegion(reg, varFuncSet_));
00345 Set<int>& u = unksOnRegions_.get(reg);
00346 u.merge(integralSum_->funcsOnRegion(reg, unkFuncSet_));
00347 }
00348 SUNDANCE_MSG2(rqcVerb, tab2 << "varsOnRegion = " << varsOnRegions_.get(reg));
00349 SUNDANCE_MSG2(rqcVerb, tab2 << "unksOnRegion = " << unksOnRegions_.get(reg));
00350 }
00351
00352
00353
00354 if (hasBCs)
00355 {
00356
00357
00358 for (Sundance::Map<RegionQuadCombo, Expr>::const_iterator
00359 r=bcSum_->rqcToExprMap().begin();
00360 r!=bcSum_->rqcToExprMap().end(); r++)
00361 {
00362 Tabs tab15;
00363 RegionQuadCombo rqc = r->first;
00364 int rqcVerb = verb;
00365 if (rqc.watch().isActive())
00366 {
00367 rqcVerb=rqc.watch().param("equation set setup");
00368 SUNDANCE_MSG1(max(verb, rqcVerb), tab15 << "processing RQC = " << rqc);
00369 }
00370
00371 Expr term = r->second;
00372 OrderedHandle<CellFilterStub> reg = rqc.domain();
00373
00374 if (!regionSet.contains(reg))
00375 {
00376 regionSet.put(reg);
00377 varsOnRegions_.put(reg, bcSum_->funcsOnRegion(reg, varFuncSet_));
00378 unksOnRegions_.put(reg, bcSum_->funcsOnRegion(reg, unkFuncSet_));
00379 bcVarsOnRegions_.put(reg, bcSum_->funcsOnRegion(reg, varFuncSet_));
00380 bcUnksOnRegions_.put(reg, bcSum_->funcsOnRegion(reg, unkFuncSet_));
00381 }
00382 else
00383 {
00384 if (!bcVarsOnRegions_.containsKey(reg))
00385 {
00386 bcVarsOnRegions_.put(reg, bcSum_->funcsOnRegion(reg, varFuncSet_));
00387 }
00388 if (!bcUnksOnRegions_.containsKey(reg))
00389 {
00390 bcUnksOnRegions_.put(reg, bcSum_->funcsOnRegion(reg, unkFuncSet_));
00391 }
00392 Set<int>& t = varsOnRegions_.get(reg);
00393 t.merge(bcSum_->funcsOnRegion(reg, varFuncSet_));
00394 Set<int>& u = unksOnRegions_.get(reg);
00395 u.merge(bcSum_->funcsOnRegion(reg, unkFuncSet_));
00396 }
00397 }
00398 }
00399
00400
00401 regions_ = regionSet.elements();
00402
00403 reducedVarsOnRegions_.resize(regions_.size());
00404 reducedUnksOnRegions_.resize(regions_.size());
00405 for (int r=0; r<regions_.size(); r++)
00406 {
00407 Tabs tab1;
00408 regionToIndexMap_.put(regions_[r], r);
00409 reducedVarsOnRegions_[r].resize(numVarBlocks());
00410 reducedUnksOnRegions_[r].resize(numUnkBlocks());
00411 OrderedHandle<CellFilterStub> cf = regions_[r];
00412 const Set<int>& v = this->varsOnRegion(r);
00413 const Set<int>& u = this->unksOnRegion(r);
00414 const Set<int>& bv = this->varsOnRegion(r);
00415 const Set<int>& bu = this->unksOnRegion(r);
00416 Set<int> vf = v;
00417 Set<int> uf = u;
00418 vf.merge(bv);
00419 uf.merge(bu);
00420 for (Set<int>::const_iterator i=vf.begin(); i!=vf.end(); i++)
00421 {
00422 int fid = *i;
00423 SUNDANCE_MSG2(verb, tab1 << "adding VF=" << fid << " to testToRegionMap");
00424 if (testToRegionsMap_.containsKey(fid))
00425 {
00426 testToRegionsMap_[fid].put(cf);
00427 }
00428 else
00429 {
00430 Set<OrderedHandle<CellFilterStub> > s;
00431 s.put(cf);
00432 testToRegionsMap_.put(fid, s);
00433 }
00434 int rv = reducedVarID(fid);
00435 int br = blockForVarID(fid);
00436 reducedVarsOnRegions_[r][br].put(rv);
00437 }
00438 for (Set<int>::const_iterator i=uf.begin(); i!=uf.end(); i++)
00439 {
00440 int fid = *i;
00441 if (unkToRegionsMap_.containsKey(fid))
00442 {
00443 unkToRegionsMap_[fid].put(cf);
00444 }
00445 else
00446 {
00447 Set<OrderedHandle<CellFilterStub> > s;
00448 s.put(cf);
00449 unkToRegionsMap_.put(fid, s);
00450 }
00451 int ru = reducedUnkID(fid);
00452 int bc = blockForUnkID(fid);
00453 reducedUnksOnRegions_[r][bc].put(ru);
00454 }
00455 }
00456 }
00457
00458
00459
00460
00461 Array<Expr> FunctionSupportResolver::flattenSpectral(const Array<Expr>& expr) const
00462 {
00463 Array<Expr> rtn(expr.size());
00464 for (int i=0; i<expr.size(); i++)
00465 {
00466 const Expr& e = expr[i];
00467 rtn[i] = flattenSpectral(e);
00468 }
00469 return rtn;
00470 }
00471
00472 Expr FunctionSupportResolver::flattenSpectral(const Expr& expr) const
00473 {
00474 Array<Expr> rtn(expr.size());
00475 for (int i=0; i<expr.size(); i++)
00476 {
00477 if (expr[i].size() == 1)
00478 {
00479 const SpectralExpr* se
00480 = dynamic_cast<const SpectralExpr*>(expr[i][0].ptr().get());
00481 if (se != 0)
00482 {
00483 int nt = se->getSpectralBasis().nterms();
00484 Array<Expr> e(nt);
00485 for (int j=0; j<nt; j++)
00486 {
00487 e[j] = se->getCoeff(j);
00488 }
00489 rtn[i] = new ListExpr(e);
00490 }
00491 else
00492 {
00493 rtn[i] = expr[i];
00494 }
00495 }
00496 else
00497 {
00498 rtn[i] = flattenSpectral(expr[i]);
00499 }
00500 }
00501 Expr r = new ListExpr(rtn);
00502 return r.flatten();
00503
00504 }
00505
00506 int FunctionSupportResolver::reducedVarID(int varID) const
00507 {
00508 TEUCHOS_TEST_FOR_EXCEPTION(!hasVarID(varID), std::runtime_error,
00509 "varID " << varID << " not found in equation set");
00510
00511 int b = blockForVarID(varID);
00512 return varIDToReducedIDMap_[b].get(varID);
00513 }
00514
00515 int FunctionSupportResolver::reducedUnkID(int unkID) const
00516 {
00517 TEUCHOS_TEST_FOR_EXCEPTION(!hasUnkID(unkID), std::runtime_error,
00518 "unkID " << unkID << " not found in equation set");
00519
00520 int b = blockForUnkID(unkID);
00521 return unkIDToReducedIDMap_[b].get(unkID);
00522 }
00523
00524
00525 int FunctionSupportResolver::reducedUnkParamID(int unkID) const
00526 {
00527 TEUCHOS_TEST_FOR_EXCEPTION(!hasUnkParamID(unkID), std::runtime_error,
00528 "unkParamID " << unkID << " not found in equation set");
00529
00530 return unkParamIDToReducedUnkParamIDMap_.get(unkID);
00531 }
00532
00533 int FunctionSupportResolver::reducedFixedParamID(int parID) const
00534 {
00535 TEUCHOS_TEST_FOR_EXCEPTION(!hasFixedParamID(parID), std::runtime_error,
00536 "fixedParamID " << parID << " not found in equation set");
00537
00538 return fixedParamIDToReducedFixedParamIDMap_.get(parID);
00539 }
00540
00541 int FunctionSupportResolver::blockForVarID(int varID) const
00542 {
00543 TEUCHOS_TEST_FOR_EXCEPTION(!varIDToBlockMap_.containsKey(varID), std::runtime_error,
00544 "key " << varID << " not found in map "
00545 << varIDToBlockMap_);
00546 return varIDToBlockMap_.get(varID);
00547 }
00548
00549 int FunctionSupportResolver::blockForUnkID(int unkID) const
00550 {
00551 TEUCHOS_TEST_FOR_EXCEPTION(!unkIDToBlockMap_.containsKey(unkID), std::runtime_error,
00552 "key " << unkID << " not found in map "
00553 << unkIDToBlockMap_);
00554 return unkIDToBlockMap_.get(unkID);
00555 }
00556
00557 const Set<OrderedHandle<CellFilterStub> >& FunctionSupportResolver::regionsForTestFunc(int testID) const
00558 {
00559 TEUCHOS_TEST_FOR_EXCEPTION(!testToRegionsMap_.containsKey(testID), std::runtime_error,
00560 "key " << testID << " not found in map "
00561 << testToRegionsMap_);
00562 return testToRegionsMap_.get(testID);
00563 }
00564
00565 const Set<OrderedHandle<CellFilterStub> >& FunctionSupportResolver::regionsForUnkFunc(int unkID) const
00566 {
00567 TEUCHOS_TEST_FOR_EXCEPTION(!unkToRegionsMap_.containsKey(unkID), std::runtime_error,
00568 "key " << unkID << " not found in map "
00569 << testToRegionsMap_);
00570 return unkToRegionsMap_.get(unkID);
00571 }
00572
00573 int FunctionSupportResolver::indexForRegion(const OrderedHandle<CellFilterStub>& region) const
00574 {
00575 TEUCHOS_TEST_FOR_EXCEPTION(!regionToIndexMap_.containsKey(region), std::runtime_error,
00576 "key " << region << " not found in map "
00577 << regionToIndexMap_);
00578 return regionToIndexMap_.get(region);
00579 }
00580
00581 bool FunctionSupportResolver::hasBCs() const
00582 {
00583 return bcSum_ != 0;
00584 }
00585
00586
00587 namespace Sundance
00588 {
00589
00590 RCP<const CommonFuncDataStub> getSharedFunctionData(const FuncElementBase* f)
00591 {
00592 const UnknownFuncElement* u = dynamic_cast<const UnknownFuncElement*>(f);
00593 const TestFuncElement* t = dynamic_cast<const TestFuncElement*>(f);
00594
00595 if (u != 0)
00596 {
00597 return rcp_dynamic_cast<const CommonFuncDataStub>(u->commonData());
00598 }
00599 if (t != 0)
00600 {
00601 return rcp_dynamic_cast<const CommonFuncDataStub>(t->commonData());
00602 }
00603
00604 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error,
00605 "unrecognized function type: " << typeid(*f).name());
00606 return u->commonData();
00607 }
00608 }
00609