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
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;
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
00050 coef[j]=1;
00051 coef[j+1]=0;
00052 }
00053 else
00054 {
00055
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
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
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
00113 ot::getPrivateMatricesForKSP_Shell = getPrivateMatricesForKSP_Shell_Jac2;
00114
00115 solve_neumann_oct(
00116
00117 octs,
00118 CalcVarCoef,
00119 CalcVarRHS,
00120 100,
00121
00122
00123 sol,
00124 damg
00125 );
00126
00127
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
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;
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;
00184 else
00185 {
00186
00187
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
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;
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;
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
00259 DAMGDestroy(damg);
00260
00261 ot::DAMG_Finalize();
00262 PetscFinalize();
00263 return 0;
00264 }
00265