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