00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef MULTIGRID_HPP
00022 #define MULTIGRID_HPP
00023
00024 #include <Vector.hpp>
00025
00026 #include <Structured3DVector.hpp>
00027 #include <Structured3DMeshShape.hpp>
00028
00029 #include <Structured3DMesh.hpp>
00030
00031 #include <SpectralMesh.hpp>
00032
00033 #include <UnAssembledMatrix.hpp>
00034 #include <SparseMatrix.hpp>
00035
00036 #include <MultiGridOptions.hpp>
00037 #include <GetParameter.hpp>
00038
00039 #include <Preconditioner.hpp>
00040
00041 #include <fstream>
00042 #include <set>
00043 #include <list>
00044
00045 #include <DegreeOfFreedomSet.hpp>
00046
00047 #include <BoundaryConditionDiscretizationElimination.hpp>
00048
00049 #include <SolverInformationCenter.hpp>
00050
00060 class MultiGrid
00061 : public Preconditioner
00062 {
00063 private:
00064
00065 class DirichletPositions
00066 {
00067 private:
00068 Vector<size_t> __positions;
00069
00070 public:
00071 size_t size() const
00072 {
00073 return __positions.size();
00074 }
00075
00076 const size_t& operator()(const size_t i) const
00077 {
00078 ASSERT (i<__positions.size());
00079 return __positions[i];
00080 }
00081
00082 void setPosition(const size_t& level, const size_t& pos)
00083 {
00084 __positions[level]=pos;
00085 }
00086
00087 const DirichletPositions& operator=(const DirichletPositions& d)
00088 {
00089 __positions=d.__positions;
00090 return *this;
00091 }
00092
00093 DirichletPositions(const size_t numberOfLevel)
00094 : __positions(numberOfLevel)
00095 {
00096 ;
00097 }
00098
00099 DirichletPositions(const DirichletPositions& d)
00100 : __positions(d.__positions)
00101 {
00102 ;
00103 }
00104
00105 ~DirichletPositions()
00106 {
00107 ;
00108 }
00109 };
00110
00111 mutable size_t __level;
00112 int nu1;
00113 int nu2;
00114 int mu1;
00115 int mu2;
00116
00117 int maxiter;
00118
00119 real_t omega;
00120 real_t epsilon;
00121
00122 const DegreeOfFreedomSet& __degreeOfFreedomSet;
00123
00124 Structured3DMeshShape __meshShape;
00125
00126 GetParameter<MultiGridOptions> __options;
00127
00128 Structured3DVector<bool> __dirichlet;
00129
00130 std::vector<Structured3DMeshShape> __meshesShape;
00131 std::list<DirichletPositions> __positionList;
00132
00133 mutable std::vector<Vector<real_t> > __dirichletValues;
00134
00135 public:
00136 std::string name() const
00137 {
00138 return "finite differences multigrid";
00139 }
00140
00141
00142 MultiGrid(const Problem& problem,
00143 const SparseMatrix& A,
00144 const DegreeOfFreedomSet& degreeOfFreedomSet)
00145 : Preconditioner (problem,
00146 Preconditioner::multigrid),
00147 __degreeOfFreedomSet(degreeOfFreedomSet),
00148 __meshShape(TinyVector<3,size_t>(0,0,0),
00149 TinyVector<3,real_t>(-1,-1,-1),
00150 TinyVector<3,real_t>(1,1,1)),
00151 __dirichlet(Array3DShape(0,0,0))
00152 {
00153 const Mesh& solverMesh = SolverInformationCenter::instance().mesh();
00154 const DiscretizationType& discretization = SolverInformationCenter::instance().discretizationType();
00155 switch (solverMesh.type()) {
00156 case Mesh::cartesianHexahedraMesh: {
00157 const Structured3DMesh& mesh = static_cast<const Structured3DMesh&>(solverMesh);
00158 __meshShape = Structured3DMeshShape(TinyVector<3,size_t>(mesh.shape().shape().nx(),
00159 mesh.shape().shape().ny(),
00160 mesh.shape().shape().nz()),
00161 mesh.shape().a(),mesh.shape().b());
00162 __dirichlet.resize(mesh.shape().shape());
00163 break;
00164 }
00165 case Mesh::spectralMesh: {
00166 const SpectralMesh& mesh = static_cast<const SpectralMesh&>(solverMesh);
00167 __meshShape = Structured3DMeshShape(TinyVector<3,size_t>(mesh.shape().shape().nx()-1,
00168 mesh.shape().shape().ny()-1,
00169 mesh.shape().shape().nz()-1),
00170 mesh.shape().a(),mesh.shape().b());
00171
00172 __dirichlet.resize(__meshShape.shape());
00173 break;
00174 }
00175 default: {
00176 throw ErrorHandler(__FILE__,__LINE__,
00177 "Multigrid does not implemented for this kind of mesh",
00178 ErrorHandler::normal);
00179 }
00180 }
00181
00182 __level = (int)(std::log(real_t(__meshShape.nx()-1))/std::log(2.));
00183
00184 nu1 = __options.value().nu1();
00185 nu2 = __options.value().nu2();
00186 mu1 = __options.value().mu1();
00187 mu2 = __options.value().mu2();
00188
00189 epsilon = __options.value().epsilon();
00190 maxiter = __options.value().maxiter();
00191
00192 omega = __options.value().omega();
00193
00194 Structured3DMesh mesh(__meshShape,
00195 new VerticesCorrespondance(__meshShape.numberOfVertices()));
00196
00197 ReferenceCounting<BoundaryConditionDiscretization>
00198 e = new BoundaryConditionDiscretizationElimination<Structured3DMesh,
00199 ScalarDiscretizationTypeBase::lagrangianFEM1>(__problem,
00200 mesh,
00201 __degreeOfFreedomSet);
00202
00203
00204
00205
00206
00207
00208
00209 for (size_t i=0; i<__degreeOfFreedomSet.size(); ++i) {
00210 __dirichlet[i] = (*e).dirichlet(i);
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 __meshesShape.reserve(__level);
00224 __dirichletValues.reserve(__level);
00225
00226 for (size_t i=0; i<__level; ++i) {
00227 size_t nx = ((__meshShape.nx()-1)/(1<<i))+1;
00228 size_t ny = ((__meshShape.ny()-1)/(1<<i))+1;
00229 size_t nz = ((__meshShape.nz()-1)/(1<<i))+1;
00230
00231 __meshesShape.push_back(Structured3DMeshShape(TinyVector<3,size_t>(nx,ny,nz),
00232 __meshShape.a(),
00233 __meshShape.b()));
00234 }
00235
00236 for (size_t i=0; i<__level; ++i) {
00237 __dirichletValues
00238 .push_back(Vector<real_t>(__meshesShape[i].numberOfVertices()));
00239 }
00240
00241
00242 for (size_t i=0; i<__dirichlet.nx(); ++i) {
00243 for (size_t j=0; j<__dirichlet.ny(); ++j) {
00244 for (size_t k=0; k<__dirichlet.nz(); ++k) {
00245 if(__dirichlet(i,j,k)) {
00246 DirichletPositions p(__level);
00247
00248 p.setPosition(0, __dirichlet.shape()(i,j,k));
00249
00250 for(size_t l=1; l<__level; ++l) {
00251 const real_t x = i*__meshShape.hx();
00252 const real_t y = j*__meshShape.hy();
00253 const real_t z = k*__meshShape.hz();
00254
00255 const size_t I = size_t(rint(x/__meshesShape[l].hx()));
00256 const size_t J = size_t(rint(y/__meshesShape[l].hy()));
00257 const size_t K = size_t(rint(z/__meshesShape[l].hz()));
00258
00259 p.setPosition(l,__meshesShape[l].shape()(I,J,K));
00260 }
00261 __positionList.push_back(p);
00262 }
00263 }
00264 }
00265 }
00266 }
00267
00268 void copyDirichlet(const Vector<real_t>& u,
00269 Vector<real_t>& v,
00270 const size_t level) const
00271 {
00272 ASSERT(v.size() == __meshesShape[__level-level].numberOfVertices());
00273 ASSERT(u.size() == __meshesShape[__level-level].numberOfVertices());
00274
00275 for(std::list<DirichletPositions>::const_iterator i
00276 = __positionList.begin();
00277 i != __positionList.end(); ++i) {
00278 size_t j = (*i)(__level-level);
00279 v[j] = u[j];
00280 }
00281 }
00282
00283 void residuDirichlet(Vector<real_t>& v,
00284 const Vector<real_t>& u1,
00285 const Vector<real_t>& u2,
00286 const size_t level) const
00287 {
00288 ASSERT(v.size() == __meshesShape[__level-level].numberOfVertices());
00289 for(std::list<DirichletPositions>::const_iterator i
00290 = __positionList.begin();
00291 i != __positionList.end(); ++i) {
00292 size_t j = (*i)(__level-level);
00293 v[j] = u1[j] - u2[j];
00294 }
00295 }
00296
00297 void setDirichlet(const size_t level,Vector<real_t>& v) const
00298 {
00299 for(std::list<DirichletPositions>::const_iterator i
00300 = __positionList.begin();
00301 i != __positionList.end(); ++i) {
00302 size_t j = (*i)(__level-level);
00303 v[j] = __dirichletValues[__level-level][j];
00304 }
00305 }
00306
00307 void getDirichlet(const size_t level, Vector<real_t>& v) const
00308 {
00309 for(std::list<DirichletPositions>::const_iterator i
00310 = __positionList.begin();
00311 i != __positionList.end(); ++i) {
00312 size_t j = (*i)(__level-level);
00313 __dirichletValues[__level-level][j] = v[j];
00314 }
00315 }
00316
00317 void interpolateDirichlet(Vector<real_t>& u2,
00318 const Vector<real_t>& u1,
00319 const size_t currentLevel) const
00320 {
00321 for(std::list<DirichletPositions>::const_iterator i
00322 = __positionList.begin();
00323 i != __positionList.end(); ++i) {
00324
00325 const size_t i1 = (*i)(__level-currentLevel);
00326 const size_t i2 = (*i)(__level-currentLevel+1);
00327
00328 u2[i2] = u1[i1];
00329 }
00330
00331 }
00332
00333 void restrictDirichlet(const Vector<real_t>& u2,
00334 Vector<real_t>& u1,
00335 const size_t currentLevel) const
00336 {
00337 for(std::list<DirichletPositions>::const_iterator i
00338 = __positionList.begin();
00339 i != __positionList.end(); ++i) {
00340
00341 const size_t i1 = (*i)(__level-currentLevel);
00342 const size_t i2 = (*i)(__level-currentLevel+1);
00343
00344 u1[i1] = u2[i2];
00345 }
00346 }
00347
00348 void initializes()
00349 {
00350 ;
00351 }
00352
00353 void weightJacobi(Structured3DVector<real_t>& u,
00354 const Structured3DVector<real_t>& b,
00355 const size_t currentLevel) const
00356 {
00357 const Array3DShape& shape = b.shape();
00358
00359 Vector<real_t> d (u.size());
00360
00361 real_t dx= __meshShape.dimension(0)/(shape.nx()-1);
00362 real_t dy= __meshShape.dimension(1)/(shape.ny()-1);
00363 real_t dz= __meshShape.dimension(2)/(shape.nz()-1);
00364
00365 Structured3DVector<real_t> v(u.shape());
00366 v=0;
00367
00368 for (size_t i=1; i<shape.nx()-1; ++i)
00369 for (size_t j=1; j<shape.ny()-1; ++j)
00370 for (size_t k=1; k<shape.nz()-1; ++k) {
00371 real_t dijk = (2./(dx*dx)+2./(dy*dy)+2./(dz*dz)
00372
00373 );
00374 v(i,j,k) = ((u(i-1,j,k) + u(i+1,j,k))/(dx*dx)
00375 + (u(i,j-1,k) + u(i,j+1,k))/(dy*dy)
00376 + (u(i,j,k-1) + u(i,j,k+1))/(dz*dz)
00377 + b(i,j,k)
00378 )/dijk;
00379 }
00380
00381 copyDirichlet(u,v,currentLevel);
00382
00383 v *= 1-omega;
00384 u *= omega;
00385 u += v;
00386 }
00387
00388 void computeResidu(Structured3DVector<real_t>& r,
00389 const Structured3DVector<real_t>& u,
00390 const Structured3DVector<real_t>& f,
00391 const size_t currentLevel) const
00392 {
00394 real_t dx= __meshShape.dimension(0)/(u.nx()-1);
00395 real_t dy= __meshShape.dimension(1)/(u.ny()-1);
00396 real_t dz= __meshShape.dimension(2)/(u.nz()-1);
00397
00398 r = 0.;
00399
00400 ASSERT (u.shape()==r.shape());
00401 ASSERT (u.shape()==f.shape());
00402
00403 for (size_t i=1; i<u.nx()-1; ++i)
00404 for (size_t j=1; j<u.ny()-1; ++j)
00405 for (size_t k=1; k<u.nz()-1; ++k)
00406 r(i,j,k) =
00407 f(i,j,k)
00408 - (u(i,j,k)*(2./(dx*dx)+2./(dy*dy)+2./(dz*dz)
00409
00410
00411
00412 )
00413 - (u(i-1,j,k) + u(i+1,j,k))/(dx*dx)
00414 - (u(i,j-1,k) + u(i,j+1,k))/(dy*dy)
00415 - (u(i,j,k-1) + u(i,j,k+1))/(dz*dz));
00416
00417 residuDirichlet(r,f,u,currentLevel);
00418 }
00419
00420
00421 void correct(Structured3DVector<real_t>& u,
00422 const Structured3DVector<real_t>& u2,
00423 const size_t currentLevel) const
00424 {
00425
00426 getDirichlet(currentLevel,u);
00427 ASSERT(u.nx() == ((u2.nx()-1)*2+1));
00428 ASSERT(u.ny() == ((u2.ny()-1)*2+1));
00429 ASSERT(u.nz() == ((u2.nz()-1)*2+1));
00430
00431 for (size_t i=1; i<u.nx()-1; ++i) {
00432 std::vector<int> indicesI;
00433 indicesI.push_back(i/2);
00434 if (i%2 != 0)
00435 indicesI.push_back(i/2 + 1);
00436 for (size_t j=1; j<u.ny()-1; ++j) {
00437 std::vector<int> indicesJ;
00438 indicesJ.push_back(j/2);
00439 if (j%2 != 0)
00440 indicesJ.push_back(j/2 + 1);
00441 for (size_t k=1; k<u.nz()-1; ++k) {
00442 std::vector<int> indicesK;
00443 indicesK.push_back(k/2);
00444 if (k%2 != 0)
00445 indicesK.push_back(k/2 + 1);
00446
00447 real_t sum=0;
00448 for (size_t ii=0; ii<indicesI.size(); ++ii) {
00449 for (size_t jj=0; jj<indicesJ.size(); ++jj) {
00450 for (size_t kk=0; kk<indicesK.size(); ++kk) {
00451 sum += u2(indicesI[ii],indicesJ[jj],indicesK[kk]);
00452 }
00453 }
00454 }
00455 u(i,j,k)
00456 += sum / (indicesI.size()*indicesJ.size()*indicesK.size());
00457 }
00458 }
00459 }
00460 setDirichlet(currentLevel,u);
00461
00462 }
00463
00464 void project (Structured3DVector<real_t>& u2,
00465 const Structured3DVector<real_t>& u,
00466 const size_t currentLevel) const
00467 {
00468
00469
00470 real_t c0 = 1./8.;
00471 real_t c1 = 1./16;
00472 real_t c2 = 1./32;
00473 real_t c3 = 1./64;
00474
00475 for (size_t i=1; i<u2.nx()-1; ++i)
00476 for (size_t j=1; j<u2.ny()-1; ++j)
00477 for (size_t k=1; k<u2.nz()-1; ++k) {
00478 int i1 = 2*i;
00479 int i2 = 2*j;
00480 int i3 = 2*k;
00481
00482 u2(i,j,k) = c0 * u(i1,i2,i3)
00483 + c1 * ( u(i1-1,i2, i3 ) + u(i1+1,i2, i3 )
00484 +u(i1, i2-1,i3 ) + u(i1, i2+1,i3 )
00485 +u(i1, i2, i3-1) + u(i1, i2, i3+1) )
00486 + c2 * ( u(i1-1,i2-1,i3 ) + u(i1+1,i2-1,i3 )
00487 +u(i1-1,i2+1,i3 ) + u(i1+1,i2+1,i3 )
00488 +u(i1, i2-1,i3-1) + u(i1, i2+1,i3-1)
00489 +u(i1, i2-1,i3+1) + u(i1, i2+1,i3+1)
00490 +u(i1-1,i2, i3-1) + u(i1-1,i2, i3+1)
00491 +u(i1+1,i2, i3-1) + u(i1+1,i2, i3+1) )
00492 + c3 * ( u(i1-1,i2-1,i3-1) + u(i1+1,i2-1,i3-1)
00493 +u(i1-1,i2+1,i3-1) + u(i1+1,i2+1,i3-1)
00494 +u(i1-1,i2-1,i3+1) + u(i1+1,i2-1,i3+1)
00495 +u(i1-1,i2+1,i3+1) + u(i1+1,i2+1,i3+1) );
00496 }
00497 interpolateDirichlet(u2,u,currentLevel);
00498 }
00499
00500 void multigrid(Structured3DVector<real_t>& u,
00501 const Structured3DVector<real_t>& b,
00502 int currentLevel) const
00503 {
00504 Structured3DVector<real_t> r(u.shape());
00505
00506 for (int i=0; i<nu1; ++i)
00507 weightJacobi(u,b,currentLevel);
00508
00509 Array3DShape newShape ((u.nx()+1)/2,
00510 (u.ny()+1)/2,
00511 (u.nz()+1)/2);
00512
00513 if (currentLevel > 1) {
00514
00515 for (int i=0; i<mu1; ++i) {
00516 Structured3DVector<real_t> u2(newShape);
00517 u2 = 0;
00518
00519 Structured3DVector<real_t> b2(newShape);
00520 computeResidu(r,u,b, currentLevel);
00521
00522 project(b2,r,currentLevel);
00523
00524 multigrid(u2, b2, currentLevel-1);
00525 correct(u,u2,currentLevel);
00526 }
00527 } else {
00529 #warning Arrange this.
00530 for (size_t i=0; i<nu1+nu2; ++i)
00531 weightJacobi(u,b,currentLevel);
00532 }
00533 for (int i=0; i<nu2; ++i)
00534 weightJacobi(u,b,currentLevel);
00535 }
00536
00537 void FMV(Structured3DVector<real_t>& u,
00538 const Structured3DVector<real_t>& b,
00539 int currentLevel) const
00540 {
00541 if (currentLevel > 1) {
00542 Array3DShape newShape ((u.nx()+1)/2,
00543 (u.ny()+1)/2,
00544 (u.nz()+1)/2);
00545
00546 Structured3DVector<real_t> r(u.shape());
00547
00548 Structured3DVector<real_t> u2(newShape);
00549 u2 = 0;
00550
00551 Structured3DVector<real_t> b2(newShape);
00552 computeResidu(r,u,b,currentLevel);
00553 project(b2,r,currentLevel);
00554
00555 FMV(u2, b2, currentLevel-1);
00556 correct(u,u2,currentLevel);
00557 }
00558
00559 for (int i=0; i<mu2; ++i)
00560 multigrid(u,b,currentLevel);
00561 }
00562
00563 void computes(const Vector<real_t>& f,
00564 Vector<real_t>& v) const
00565 {
00566 Structured3DVector<real_t> u(__meshShape.shape());
00567 Structured3DVector<real_t> b(__meshShape.shape());
00568
00569 ASSERT(u.size() == v.size());
00570 ASSERT(b.size() == f.size());
00571
00572 u = v;
00573 b = f;
00574
00575 real_t dx = __meshShape.hx();
00576 real_t dy = __meshShape.hy();
00577 real_t dz = __meshShape.hz();
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 getDirichlet(__level,b);
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 u=0;
00622
00623 setDirichlet(__level,u);
00624 setDirichlet(__level,b);
00625
00626 Structured3DVector<real_t> r(u);
00627 computeResidu(r,u,b,__level);
00628
00629 real_t resid0 = Norm(r);
00630
00631 real_t norm;
00632 int n = 0;
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 do {
00647 FMV(u, b, __level);
00648
00649 computeResidu(r,u,b,__level);
00650
00651 real_t resid = Norm(r);
00652
00653 norm = resid/resid0;
00654 ffout(0) << "\tFMG norme:" << norm <<" (" << resid << '/' << resid0 << ")\n";
00655 n++;
00656 } while ((norm>epsilon) and (n<maxiter));
00657
00658 for (size_t i=1; i<b.nx()-1; ++i)
00659 for (size_t j=1; j<b.ny()-1; ++j)
00660 for (size_t k=1; k<b.nz()-1; ++k) {
00661 v[u.shape()(i,j,k)] = u(i,j,k);
00662
00663 }
00664
00665 }
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 };
00756 #endif // _MULTIGRID_HPP_
00757