00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _LSPROBLEMIMPLEM_H_
00012 #define _LSPROBLEMIMPLEM_H_
00013
00014 #if defined(CH_Darwin) && defined(__GNUC__) && ( __GNUC__ == 3 )
00015
00016 #include <unistd.h>
00017 #define _GLIBCPP_USE_C99 1
00018 #endif
00019
00020 #include <cmath>
00021 #include <cstdio>
00022 #include <cstdlib>
00023 #include <fstream>
00024 #include <iostream>
00025 #include <string>
00026 using std::endl;
00027
00028 #include "ConstrainedLS.H"
00029 #include "LSquares.H"
00030 #include "MultiIndex.H"
00031 #include "IFData.H"
00032 #include "CutCellMoments.H"
00033
00034 #include "NamespaceHeader.H"
00035
00036 template<int dim> int LSProblem<dim>::nChooseR(int a_n,
00037 int a_r)
00038 {
00039 if (a_r == 0) return 1;
00040 int num = 1;
00041 int den = 1;
00042 for (int i = 1; i <= a_r; ++i)
00043 {
00044 num *= (a_n+1-i);
00045 den *= i;
00046 }
00047 return num/den;
00048 }
00049
00050 template<int dim> void LSProblem<dim>::monoMaxMin(Real & a_maxVal,
00051 Real & a_minVal,
00052 const IndexTM<int,dim> & a_mono,
00053 const IFData<dim> & a_IFData)
00054 {
00055 a_maxVal = 0.0;
00056 a_minVal = 0.0;
00057
00058 for (typename IFData<dim>::CornerSigns::const_iterator cornerIt = a_IFData.m_cornerSigns.begin();
00059 cornerIt != a_IFData.m_cornerSigns.end();
00060 ++cornerIt)
00061 {
00062 const typename IFData<dim>::Vertex & vertex = cornerIt->first;
00063
00064
00065 typename IFData<dim>::RvDim corner;
00066 for (int idir = 0; idir < dim; ++idir)
00067 {
00068 corner[idir] = vertex[idir] - 0.5;
00069 corner[idir] *= a_IFData.m_cellCenterCoord.m_dx[idir];
00070 }
00071
00072
00073 typename IFData<dim>::RvDim cornerCoord = a_IFData.m_localCoord.convert(corner,a_IFData.m_cellCenterCoord);
00074
00075
00076 Real monoCorner = 1.0;
00077 for (int idir = 0; idir < dim ; ++idir)
00078 {
00079 monoCorner *= POW(cornerCoord[idir],a_mono[idir]);
00080 }
00081
00082 if (monoCorner > a_maxVal)
00083 {
00084 a_maxVal = monoCorner;
00085 }
00086
00087 if (monoCorner < a_minVal)
00088 {
00089 a_minVal = monoCorner;
00090 }
00091 }
00092 }
00093
00094 template<int dim> void LSProblem<dim>::computeBounds(const IndexTM<Real,dim> & a_dx,
00095 const CutCellMoments<dim> & a_ccm)
00096 {
00097 m_lowerBound.assign(-HUGE);
00098 m_upperBound.assign(HUGE);
00099
00100 int nEBBounds = 0;
00101 if (m_degreeP == 0 && dim == 2)
00102 {
00103 nEBBounds = m_numP;
00104 }
00105
00106
00107
00108
00109
00110 if (m_degreeP == 0 && dim == 2)
00111 {
00112 Real lobnd = 0.0;
00113 IvDim whichMono;
00114 for (typename CutCellMoments<dim>::PthMoment::const_iterator it = a_ccm.m_EBmoments.begin();
00115 it != a_ccm.m_EBmoments.end();++it)
00116 {
00117 IvDim mono = it->first;
00118 Real maxMono = 0.0;
00119 Real minMono = 0.0;
00120 monoMaxMin(maxMono,minMono,mono,a_ccm.m_IFData);
00121 Real val = it->second;
00122 if (minMono < 0.0)
00123 {
00124 Real newLoBnd = val/minMono;
00125 if (newLoBnd > lobnd)
00126 {
00127 lobnd = newLoBnd;
00128 whichMono = mono;
00129 }
00130 }
00131 if (maxMono > 0.0)
00132 {
00133 Real newLoBnd = val/maxMono;
00134 if (newLoBnd > lobnd)
00135 {
00136 lobnd = newLoBnd;
00137 whichMono = mono;
00138 }
00139 }
00140 }
00141
00142
00143
00144 IvDim mono = IvDim::Zero;
00145
00146 int ndx = 0;
00147 int variableNdx = ndx;
00148 m_lowerBound[variableNdx]=lobnd;
00149 m_upperBound[variableNdx]=HUGE;
00150
00151 }
00152
00153
00154 for (typename PthMomentLoc::const_iterator it = m_monoLocPLess1.begin();
00155 it != m_monoLocPLess1.end();++it)
00156 {
00157 IvDim mono = it->first;
00158
00159
00160 int ndx = it->second;
00161 int variableNdx = ndx + m_numP;
00162 Real lobnd, hibnd;
00163
00164
00165
00166
00167 momentBounds(lobnd,hibnd,mono, a_ccm.m_IFData);
00168
00169
00170
00171 bool isZeroDegree = (mono.sum() == 0);
00172
00173 if (isZeroDegree )
00174 {
00175 Real zeroDegreeLoBnd = 0.0;
00176
00177
00178
00179
00180
00181 IvDim whichMono;
00182
00183 for (typename CutCellMoments<dim>::PthMoment::const_iterator it2 = a_ccm.m_moments.begin();
00184 it2 != a_ccm.m_moments.end();++it2)
00185 {
00186 IvDim mono = it2->first;
00187 Real val = it2->second;
00188 Real maxMono = 0.0;
00189 Real minMono = 0.0;
00190 monoMaxMin(maxMono,minMono,mono,a_ccm.m_IFData);
00191 if (minMono < 0.0)
00192 {
00193 Real newLoBnd = val/minMono;
00194 if (newLoBnd > zeroDegreeLoBnd)
00195 {
00196 zeroDegreeLoBnd = newLoBnd;
00197 whichMono = mono;
00198 }
00199 }
00200 if (maxMono > 0.0)
00201 {
00202 Real newLoBnd = val/maxMono;
00203 if (newLoBnd > zeroDegreeLoBnd)
00204 {
00205 zeroDegreeLoBnd = newLoBnd;
00206 whichMono = mono;
00207 }
00208 }
00209 }
00210 lobnd = Max(lobnd, zeroDegreeLoBnd);
00211 }
00212
00213
00214 m_lowerBound[variableNdx] = lobnd;
00215 m_upperBound[variableNdx] = hibnd;
00216
00217 }
00218
00219
00220 }
00221
00222
00223 template<int dim> void LSProblem<dim>::momentBounds(Real & a_lobnd,
00224 Real & a_hibnd,
00225 const IvDim & a_mono,
00226 const IFData<dim> & a_IFData)
00227 {
00228 a_lobnd = 0.0;
00229 a_hibnd = 0.0;
00230
00231
00232 typename IFData<dim>::CornerSigns::const_iterator cornerIt;
00233
00234 for (cornerIt = a_IFData.m_cornerSigns.begin();
00235 cornerIt != a_IFData.m_cornerSigns.end();
00236 ++cornerIt)
00237 {
00238 const typename IFData<dim>::Vertex & vertex = cornerIt->first;
00239
00240 typename IFData<dim>::RvDim corner;
00241 for (int idir = 0; idir < dim; ++idir)
00242 {
00243 corner[idir] = vertex[idir] - 0.5;
00244 corner[idir] *= a_IFData.m_cellCenterCoord.m_dx[idir];
00245 }
00246
00247
00248 typename IFData<dim>::RvDim cornerCoord
00249 = a_IFData.m_localCoord.convert(corner,a_IFData.m_cellCenterCoord);
00250
00251 Real partialCellMag = 1.0;
00252 for (int idir = 0; idir < dim ; ++idir)
00253 {
00254 Real pPlus1 =(Real)( a_mono[idir]+1);
00255 partialCellMag *= POW(cornerCoord[idir],pPlus1)/pPlus1;
00256 if (cornerCoord[idir] < 0.0) partialCellMag *=-1.0;
00257 }
00258 if (partialCellMag > 0.0) a_hibnd += partialCellMag;
00259 if (partialCellMag < 0.0) a_lobnd += partialCellMag;
00260 }
00261 }
00262
00263 template<int dim> LSProblem<dim>::~LSProblem()
00264 {
00265 if (m_matrix != NULL)
00266 {
00267
00268 int numRows = dim*m_numP;
00269 int numCols = m_numP + m_numPLess1;
00270 freeArray(numRows,numCols,m_matrix);
00271
00272 }
00273 }
00274
00275
00276 template<int dim> LSProblem<dim>::LSProblem(const int & a_degreeP,
00277 const bool & a_useConstraints)
00278 :m_degreeP(a_degreeP),
00279 m_numActiveBounds(0),
00280 m_useConstraints(a_useConstraints)
00281 {
00282 fillMap(m_monoLocP,m_locMonoP,m_degreeP);
00283 fillMap(m_monoLocPLess1,m_locMonoPLess1,m_degreeP-1);
00284 m_numP = numMonomials(m_degreeP);
00285 m_numPLess1 = numMonomials(m_degreeP-1);
00286 m_matrix = NULL;
00287 }
00288
00289
00290 template<int dim> LSProblem<dim>::LSProblem(const int & a_order,
00291 const int & a_degreeP,
00292 const bool & a_useConstraints,
00293 const IndexTM<Real,dim> & a_normal)
00294 :m_order(a_order),
00295 m_degreeP(a_degreeP),
00296 m_numActiveBounds(0),
00297 m_useConstraints(a_useConstraints),
00298 m_normal(a_normal)
00299 {
00300 fillMap(m_monoLocP,m_locMonoP,m_degreeP);
00301 fillMap(m_monoLocPLess1,m_locMonoPLess1,m_degreeP-1);
00302 m_numP = numMonomials(m_degreeP);
00303 m_numPLess1 = numMonomials(m_degreeP-1);
00304 setMatrix();
00305
00306 m_unknowns.resize(m_numP + m_numPLess1);
00307 m_rhs.resize(m_numP*dim);
00308
00309 if (a_useConstraints)
00310 {
00311 m_lowerBound.resize(m_numP+m_numPLess1);
00312 m_upperBound.resize(m_numP+m_numPLess1);
00313 }
00314 }
00315
00316
00317 template<int dim> int LSProblem<dim>::invertNormalEq(const Vector<Real> & a_rhs,
00318 Vector<Real> & a_residual)
00319 {
00320 m_rhs = a_rhs;
00321 int retCode = -1;
00322 if (!m_useConstraints)
00323 {
00324 LSquares lsSolver;
00325 lsSolver.LeastSquares(m_matrix,m_unknowns,m_rhs);
00326 m_numActiveBounds = 0;
00327 retCode = 0;
00328 }
00329 else
00330 {
00331 ConstrainedLS cls;
00332 ConstrainedLS::LSResult result = cls.solveBoundConstrained(m_unknowns,
00333 m_matrix,
00334 m_rhs,
00335 m_lowerBound,
00336 m_upperBound);
00337 m_numActiveBounds = cls.numberActiveConstraints();
00338 retCode = (result == ConstrainedLS::SUCCESS) ? 0 : -1;
00339 switch(result)
00340 {
00341 case(ConstrainedLS::SUCCESS):
00342 break;
00343 case(ConstrainedLS::SINGULAR):
00344 pout() << "Singular LS problem. Linearly dependent columns (zero normal?)" << endl;
00345 break;
00346 case(ConstrainedLS::INCONSISTENT_BOUNDS):
00347 pout() << "Conflicting upper/lower bounds in LS problem. Zero or bad normal?" << endl;
00348 break;
00349 case(ConstrainedLS::UNDERDETERMINED):
00350 MayDay::Error("Malformed LS problem. Underdetermined");
00351 case(ConstrainedLS::UNCONVERGED):
00352 pout() << "BVLS failed to converge properly" << endl;
00353 break;
00354 }
00355
00356 }
00357
00358 a_residual.resize(3);
00359 a_residual[0] = 0.0;
00360 a_residual[1] = 0.0;
00361 a_residual[2] = 0.0;
00362 Real maxRi = 0.0;
00363 for (int i = 0 ; i < m_numP*dim ; i++)
00364 {
00365 Real AtimeX = 0.0;
00366 for (int j = 0 ; j < m_numP + m_numPLess1 ; j++)
00367 {
00368 AtimeX += m_matrix[i][j] * m_unknowns[j];
00369 }
00370 Real ri = Abs(AtimeX - m_rhs[i]);
00371 if (ri > maxRi)
00372 {
00373 a_residual[0] = ri;
00374 maxRi = ri;
00375 }
00376 a_residual[1] += ri;
00377 a_residual[2] += ri * ri;
00378 }
00379 a_residual[2] = sqrt(a_residual[2]);
00380
00381 return retCode;
00382 }
00383
00384 template<int dim> int LSProblem<dim>::factorial(const int & a_n,
00385 const int & a_m)
00386 {
00387 int retval = 1;
00388 if (a_n < 0 || a_m < 0)
00389 {
00390 MayDay::Abort("Attempting n! for n < 0");
00391 }
00392 for (int i = a_m+1; i <= a_n; ++i)
00393 {
00394 retval *= i;
00395 }
00396 return retval;
00397 }
00398
00399 template<int dim> int LSProblem<dim>::numMonomials(const int & a_monoDegree)
00400 {
00401 int retval = LARGEINTVAL;
00402 if (a_monoDegree == -1)
00403 {
00404 retval = 0;
00405 }
00406 else
00407 {
00408 int bigger;
00409 int smaller;
00410 if (dim- 1 > a_monoDegree)
00411 {
00412 bigger = dim-1;
00413 smaller = a_monoDegree;
00414 }
00415 else
00416 {
00417 smaller = dim-1;
00418 bigger = a_monoDegree;
00419 }
00420 int numerator = factorial(dim - 1 + a_monoDegree,bigger);
00421 int denominator = factorial(smaller);
00422
00423
00424 retval = numerator/denominator;
00425 }
00426 return retval;
00427 }
00428
00429
00430 template<int dim> void LSProblem<dim>::setMatrix()
00431 {
00432
00433
00434
00435
00436 int numRows = dim*m_numP;
00437 int numCols = m_numP + m_numPLess1;
00438 allocArray(numRows,numCols,m_matrix);
00439
00440
00441
00442 for (typename PthMomentLoc::const_iterator it = m_monoLocP.begin();
00443 it != m_monoLocP.end();++it)
00444 {
00445 for (int idir = 0; idir< dim; ++idir)
00446 {
00447
00448 int row = dim*(it->second) + idir;
00449 int pcol = it->second;
00450 m_matrix[row][pcol] = -m_normal[idir];
00451
00452
00453 IvDim Dmono;
00454 IvDim mono = it->first;
00455 int coeff = LARGEINTVAL;
00456
00457 differentiate(coeff,Dmono,idir,mono);
00458 int pLess1Col= LARGEINTVAL;
00459 if (coeff == LARGEINTVAL)
00460 {
00461 MayDay::Abort("problem wth differentiate");
00462 }
00463 if (coeff > 0)
00464 {
00465
00466 if (m_monoLocPLess1.find(Dmono) != m_monoLocPLess1.end())
00467 {
00468 pLess1Col = m_monoLocPLess1[Dmono] + m_numP;
00469 m_matrix[row][pLess1Col] = coeff;
00470 }
00471 else
00472 {
00473 MayDay::Abort("can't find derived mono");
00474 }
00475 }
00476 }
00477 }
00478 }
00479
00480
00481 template<int dim> void LSProblem<dim>::differentiate(int & a_coeff,
00482 IvDim & a_Dmono,
00483 int & a_idir,
00484 const IvDim & a_mono)
00485 {
00486 if (a_mono[a_idir] > 0)
00487 {
00488 a_coeff = a_mono[a_idir];
00489 a_Dmono = a_mono;
00490 a_Dmono[a_idir] -= 1;
00491 }
00492 else if (a_mono[a_idir] == 0)
00493 {
00494 a_coeff = 0;
00495 for (int idir = 0; idir < dim; ++idir)
00496 {
00497 a_Dmono[idir] = LARGEINTVAL;
00498 }
00499 }
00500 else
00501 {
00502 MayDay::Abort("Monomial has negative power");
00503 }
00504 }
00505
00506 template<int dim> void LSProblem<dim>::setRhs(const Vector<Real> & a_rhs)
00507 {
00508 }
00509
00510 template<int dim> void LSProblem<dim>::fillMap(PthMomentLoc & a_monoLoc,
00511 LocPthMoment & a_locMono,
00512 const int & a_degree)
00513 {
00514 if (a_degree >= 0)
00515 {
00516 Vector<IvDim> monomials;
00517
00518 generateMultiIndices(monomials,a_degree);
00519
00520 for (int i = 0; i < monomials.size(); i++)
00521 {
00522 const IvDim & monomial = monomials[i];
00523
00524 a_monoLoc[monomial] = i;
00525 a_locMono[i] = monomial;
00526 }
00527 }
00528 }
00529
00530 template<int dim> void LSProblem<dim>::allocArray(const int & a_rows,
00531 const int & a_cols,
00532 Real** & a_A)
00533 {
00534 a_A = new Real* [a_rows];
00535
00536 for (int i = 0; i < a_rows; i++)
00537 {
00538 a_A[i] = new Real [a_cols];
00539
00540 Real* scanA = a_A[i];
00541 for (int j = 0; j < a_cols; j++)
00542 {
00543 *(scanA++) = 0.0;
00544 }
00545 }
00546 }
00547
00548 template<int dim> void LSProblem<dim>::freeArray(const int & a_rows,
00549 const int & a_cols,
00550 Real** & a_A)
00551 {
00552 for (int i = 0; i < a_rows; i++)
00553 {
00554 delete[] a_A[i];
00555 }
00556
00557 delete[] a_A;
00558 }
00559
00560 template<int dim > void LSProblem<dim>::print(ostream & a_out) const
00561 {
00562 a_out << "Dim = " << dim << ", degree = " << m_degreeP << '\n';
00563 a_out << "m_monoLocP has " << m_monoLocP.size() << " elements" << '\n';
00564
00565 for (typename PthMomentLoc::const_iterator it = m_monoLocP.begin();
00566 it != m_monoLocP.end();++it)
00567 {
00568 a_out << "Monomial = " << it->first << ", Loc = " << it->second << '\n';
00569 }
00570
00571 a_out << "Dim = " << dim << '\n';
00572 a_out << "m_locMonoP has " << m_locMonoP.size() << " elements" << '\n';
00573
00574 for (typename LocPthMoment::const_iterator it = m_locMonoP.begin();
00575 it != m_locMonoP.end();++it)
00576 {
00577 a_out << "Loc = " << it->first << ", Monomial = " << it->second << '\n';
00578 }
00579
00580 a_out << "m_locMonoPLess1 has " << m_locMonoPLess1.size() << " elements" << '\n';
00581 for (typename PthMomentLoc::const_iterator it = m_monoLocPLess1.begin();
00582 it != m_monoLocPLess1.end();++it)
00583 {
00584 a_out << "Monomial = " << it->first << ", Loc = " << it->second << '\n';
00585 }
00586
00587 a_out << "m_locMonoPLess1 has " << m_locMonoPLess1.size() << " elements" << '\n';
00588
00589 for (typename LocPthMoment::const_iterator it = m_locMonoPLess1.begin();
00590 it != m_locMonoPLess1.end();++it)
00591 {
00592 a_out << "Loc = " << it->first << ", Monomial = " << it->second << '\n';
00593 }
00594
00595 a_out << "Matrix and rhs for least squares problem of dim = " << dim << endl;
00596 outputMatrix();
00597 outputRhs();
00598 outputUnknowns();
00599 outputBounds();
00600 }
00601
00602 template<int dim> ostream& operator<<(ostream & a_out,
00603 LSProblem<dim> & a_lsProblem)
00604 {
00605 a_lsProblem.print(a_out);
00606 return a_out;
00607 }
00608
00609 template<int dim> void LSProblem<dim>::outputMatrix() const
00610 {
00611 int rows = m_locMonoP.size()*dim;
00612 int cols = m_locMonoPLess1.size() + m_locMonoP.size();
00613 pout() << "numRows = " << rows << ", numCols = " << cols << endl;
00614
00615 for (int i = 0; i < rows; i++)
00616 {
00617 for (int j = 0; j < cols; j++)
00618 {
00619 pout() << m_matrix[i][j] << " ";
00620 }
00621 pout() << endl;
00622 }
00623 }
00624
00625 template<int dim> void LSProblem<dim>::outputRhs() const
00626 {
00627 pout() << "Outputting Rhs" << endl;
00628 for (int i = 0; i < m_rhs.size(); i++)
00629 {
00630 pout() << "m_rhs[" << i << "] = " << m_rhs[i] << endl;
00631 }
00632 }
00633
00634 template<int dim> void LSProblem<dim>::outputUnknowns()const
00635 {
00636 pout() << "Outputting Unknowns" << endl;
00637 for (int i = 0; i < m_unknowns.size(); i++)
00638 {
00639 pout() << "m_unknowns[" << i << "] = " << m_unknowns[i] << endl;
00640 }
00641 }
00642
00643 template<int dim> void LSProblem<dim>::outputBounds()const
00644 {
00645 if (m_useConstraints)
00646 {
00647 pout() << "Outputting Lower/Upper bounds" << endl;
00648 for (int i = 0; i < m_unknowns.size(); i++)
00649 {
00650 pout() << "m_lowerBound[" << setw(2) << i << "] = " << setw(14) << m_lowerBound[i]
00651 << " m_upperBound[" << setw(2) << i << "] = " << setw(14) << m_upperBound[i] << endl;
00652 }
00653 }
00654 else
00655 {
00656 pout() << "Problem is unconstrained" << endl;
00657 }
00658 }
00659
00660 #include "NamespaceFooter.H"
00661
00662 #endif