Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

omgNeumann_2spheres.C

Go to the documentation of this file.
00001 #include <mpi.h>
00002 #include <cstdio>
00003 #include "oda.h"
00004 #include "omg.h"
00005 #include "Point.h"
00006 #include "parUtils.h"
00007 #include "octUtils.h"
00008 #include "TreeNode.h"
00009 #include "handleStencils.h"
00010 #include <cstdlib>
00011 #include "sys.h"
00012 #include "externVars.h"
00013 #include <sstream>
00014 #include "omgNeumann.h"
00015 
00016 //Don't want time to be synchronized. Need to check load imbalance.
00017 #ifdef MPI_WTIME_IS_GLOBAL
00018 #undef MPI_WTIME_IS_GLOBAL
00019 #endif
00020 
00021 #ifdef PETSC_USE_LOG
00022 
00023 int Jac2DiagEvent;
00024 int Jac2MultEvent;
00025 int Jac2FinestDiagEvent;
00026 int Jac2FinestMultEvent;
00027 
00028 #endif
00029 
00030 const double w = 1;  // frequency for test purposes
00031 const double c_x =0.5;
00032 const double c_y =0.5;
00033 const double c_z =0.5;
00034 const double inneR = 0.2;
00035 const double outeR = 0.4;
00036 const double penalty = 1e8;
00037 
00038 void CalcVarCoef(const std::vector<double> & pts, std::vector<double> & coef)
00039 {
00040   const double inS = inneR*inneR;
00041   const double outS = outeR*outeR;
00042   
00043   for(int i=0,j=0; i<pts.size(); i+=3,j+=2)
00044   {
00045     double s = (pts[i]-c_x)*(pts[i]-c_x) + (pts[i+1]-c_y)*(pts[i+1]-c_y) + (pts[i+2]-c_z)*(pts[i+2]-c_z);   
00046     
00047     if ( s>=inS && s<=outS )
00048     {
00049       // we are inside the domain
00050       coef[j]=1;   // weight of -div grad u
00051       coef[j+1]=0; // weight of u
00052     }
00053     else
00054     {
00055       // we are outside the domain
00056       coef[j]=1;
00057       coef[j+1]=penalty;
00058     }
00059   }
00060 }
00061 
00062 void CalcVarRHS(const std::vector<double> & pts, std::vector<double> & rhs)
00063 {
00064   const double inS = inneR*inneR;
00065   const double outS = outeR*outeR;
00066   const double l = outeR-inneR;
00067   
00068   for(int i=0,j=0; i<pts.size(); i+=3,j++)
00069   {
00070    
00071     double s = (pts[i]-c_x)*(pts[i]-c_x) + (pts[i+1]-c_y)*(pts[i+1]-c_y) + (pts[i+2]-c_z)*(pts[i+2]-c_z);    
00072     if ( s>=inS && s<=outS )
00073     {
00074       // we are inside the domain
00075       double r = sqrt(s);
00076       rhs[j]= w*w*M_PI*M_PI/l/l*sin(w*M_PI*(r-inneR)/l)/r; 
00077     }
00078     else
00079     {
00080       // we are outside the domain
00081       rhs[j]=0;
00082     }
00083   }
00084 }
00085 
00086 int main(int argc, char ** argv )
00087 {
00088   PetscInitialize(&argc,&argv,"options","DENDRO example\n");
00089   ot::RegisterEvents();
00090 
00091   ot::DAMG_Initialize(MPI_COMM_WORLD);
00092 
00093   int size, rank;
00094   MPI_Comm_size(MPI_COMM_WORLD,&size);
00095   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
00096 
00097   if (argc<2) 
00098   {
00099     std::cout<<"Usage: mpirun -np <numProcs> "<<argv[0]<<" <filePrefix>"<<std::endl;
00100     return(-1);
00101   }
00102 
00103   std::ostringstream fName;
00104   fName<<argv[1]<<rank<<"_"<<size<<".ot";
00105 
00106   std::vector<ot::TreeNode> octs;
00107   ot::readNodesFromFile(const_cast<char*>(fName.str().c_str()), octs);
00108   
00109   Vec sol;
00110   ot::DAMG * damg;
00111   
00112   // This function pointer will be called while setting up the solver on the coarsest grid if not all processes are active on the coarse grid 
00113   ot::getPrivateMatricesForKSP_Shell = getPrivateMatricesForKSP_Shell_Jac2;
00114 
00115   solve_neumann_oct(
00116     /* input parameters: */
00117      octs,
00118      CalcVarCoef,
00119      CalcVarRHS,
00120      100,
00121 
00122      /* output parameters */
00123      sol,
00124      damg
00125     );
00126  
00127   // compare solution with the exact one
00128   unsigned numMultigridLevels = damg[0]->totalLevels;
00129   ot::DA* da=damg[numMultigridLevels-1]->da;
00130   PetscScalar *solArray;
00131   da->vecGetBuffer(sol,solArray,false,false,true,1);
00132   double maxDiff = 0;
00133   unsigned maxDepth=da->getMaxDepth()-1;
00134   double l = outeR - inneR;
00135 
00136   if(da->iAmActive())
00137   { 
00138     double outeS = outeR*outeR;
00139     double inneS = inneR*inneR;
00140     
00141     // first loop over those octants which do not contain ghost nodes.
00142     for(da->init<ot::DA_FLAGS::INDEPENDENT>(); da->curr() < da->end<ot::DA_FLAGS::INDEPENDENT>(); da->next<ot::DA_FLAGS::INDEPENDENT>())  
00143     {
00144       Point pt = da->getCurrentOffset();
00145       unsigned levelhere = da->getLevel(da->curr()) - 1;
00146       double hxOct = ldexp(1.0,-levelhere);
00147       double x = ldexp(pt.x(),-maxDepth );
00148       double y = ldexp(pt.y(),-maxDepth );
00149       double z = ldexp(pt.z(),-maxDepth );
00150 
00151       unsigned int indices[8];
00152       da->getNodeIndices(indices); 
00153 
00154       double coord[8][3] = {
00155         {0.0,0.0,0.0},
00156         {1.0,0.0,0.0},
00157         {0.0,1.0,0.0},
00158         {1.0,1.0,0.0},
00159         {0.0,0.0,1.0},
00160         {1.0,0.0,1.0},
00161         {0.0,1.0,1.0},
00162         {1.0,1.0,1.0}
00163       };
00164 
00165       unsigned char hn = da->getHangingNodeIndex(da->curr());
00166 
00167       double s = (x+hxOct/2-c_x)*(x+hxOct/2-c_x) + (y+hxOct/2-c_y)*(y+hxOct/2-c_y) + (z+hxOct/2-c_z)*(z+hxOct/2-c_z) ;
00168       if (s<inneS || s>outeS)
00169         continue; // octant outside the domain, don't account for the error on any of its nodes
00170 
00171       for(int i = 0; i < 8; i++)
00172         if (!(hn & (1 << i)))
00173         {
00174           double xhere, yhere, zhere;
00175           xhere = x + coord[i][0]*hxOct; 
00176           yhere = y + coord[i][1]*hxOct; 
00177           zhere = z + coord[i][2]*hxOct; 
00178 
00179           double rhere = sqrt( (xhere-c_x)*(xhere-c_x) + (yhere-c_y)*(yhere-c_y) + (zhere-c_z)*(zhere-c_z) );
00180           
00181           double currDiff;
00182           if (rhere<inneR || rhere>outeR)
00183             continue; // solution should be zero here, don't account for error
00184           else
00185           {
00186             // debug
00187             // cout<<rhere<<" "<< solArray[indices[i]]<<endl;
00188             currDiff = fabs ( solArray[indices[i]] - sin(w*M_PI*(rhere-inneR)/l)/rhere );
00189           }
00190           
00191           if (maxDiff < currDiff)
00192             maxDiff=currDiff;
00193         }
00194     }  
00195     
00196     // now loop over those octants which DO contain ghost nodes; now we need to  check if the node is ghost, and skip it if it is
00197     size_t myFirstNode = da->getIdxElementBegin();
00198     size_t postFirstNode = da->getIdxPostGhostBegin();
00199     for(da->init<ot::DA_FLAGS::DEPENDENT>(); da->curr() < da->end<ot::DA_FLAGS::DEPENDENT>(); da->next<ot::DA_FLAGS::DEPENDENT>())  
00200     {
00201       Point pt = da->getCurrentOffset();
00202       unsigned levelhere = da->getLevel(da->curr()) - 1;
00203       double hxOct = ldexp(1.0,-levelhere);
00204       double x = ldexp(pt.x(),-maxDepth );
00205       double y = ldexp(pt.y(),-maxDepth );
00206       double z = ldexp(pt.z(),-maxDepth );
00207 
00208       unsigned int indices[8];
00209       da->getNodeIndices(indices); 
00210 
00211       double coord[8][3] = {
00212         {0.0,0.0,0.0},
00213         {1.0,0.0,0.0},
00214         {0.0,1.0,0.0},
00215         {1.0,1.0,0.0},
00216         {0.0,0.0,1.0},
00217         {1.0,0.0,1.0},
00218         {0.0,1.0,1.0},
00219         {1.0,1.0,1.0}
00220       };
00221 
00222       unsigned char hn = da->getHangingNodeIndex(da->curr());
00223 
00224       double s = (x+hxOct/2-c_x)*(x+hxOct/2-c_x) + (y+hxOct/2-c_y)*(y+hxOct/2-c_y) + (z+hxOct/2-c_z)*(z+hxOct/2-c_z) ;
00225       if (s<inneS || s>outeS)
00226         continue; // octant outside the domain, don't account for the error on any of its nodes
00227       
00228       for(int i = 0; i < 8; i++)
00229         if ( indices[i]>=myFirstNode && indices[i]<postFirstNode && !(hn & (1 << i)) )
00230         {
00231           double xhere, yhere, zhere;
00232           xhere = x + coord[i][0]*hxOct; 
00233           yhere = y + coord[i][1]*hxOct; 
00234           zhere = z + coord[i][2]*hxOct; 
00235 
00236           double rhere = sqrt( (xhere-c_x)*(xhere-c_x) + (yhere-c_y)*(yhere-c_y) + (zhere-c_z)*(zhere-c_z) );
00237           
00238           double currDiff;
00239           if (rhere<inneR || rhere>outeR)
00240             continue; // solution should be zero here, don't account for error
00241           else
00242             currDiff = fabs ( solArray[indices[i]] - sin(w*M_PI*(rhere-inneR)/l)/rhere );
00243           
00244           if (maxDiff < currDiff)
00245             maxDiff=currDiff;
00246         }
00247     }  
00248   }
00249   da->vecRestoreBuffer(sol,solArray,false,false,true,1); 
00250 
00251     double gMaxDiff;
00252     par::Mpi_Reduce<double>(&maxDiff, &gMaxDiff, 1, MPI_MAX, 0, MPI_COMM_WORLD);  
00253   if (!rank)
00254   {
00255     std::cout<<"Maximum difference: "<<gMaxDiff<<std::endl;
00256   }
00257  
00258   // destroy multigrid context; this destroys the solution as well 
00259   DAMGDestroy(damg);
00260   
00261   ot::DAMG_Finalize();
00262   PetscFinalize();
00263   return 0;
00264 }
00265 

Generated on Tue Mar 24 16:13:59 2009 for DENDRO by  doxygen 1.3.9.1