AMROC Main     Blockstructured Adaptive Mesh Refinement in object-oriented C++


Main Page   Class Hierarchy   Compound List   File List  

AMRSolver.h

Go to the documentation of this file.
00001 #ifndef AMROC_AMRSOLVER_H
00002 #define AMROC_AMRSOLVER_H
00003 
00011 #include "Solver.h"
00012 #include "SolverControl.h"
00013 #include "AMRSolverInterface.h"
00014 
00015 
00016 #ifndef AMRSolverName
00017 #define AMRSolver(dim)      name2(AMRSolver,dim)
00018 #define AMRSolverName
00019 #endif
00020 
00021 #define DAGHCluster(dim)      name2(name2(DAGHCluster,dim),d)
00022 
00023 #define AMRSolverRegridFalse             (0)
00024 #define VERY_LARGE_CFL                 (1.5)
00025 #define MAXOVERLAPWIDTH                (100) 
00026 
00033 //******************************************************************************
00034 // flag_cells_by_error(), flag_cells_by_difference() and the fixup make use of
00035 // u(Time+TStep). Ensure that the next time step is only used when all data,
00036 // especially the adaptive boundary conditions (-> RecomposeHierarchy() ) have 
00037 // been set.
00038 // If problems occur, the use of a working function might be unavoidable.
00039 //******************************************************************************
00040 
00041 template <class VectorType, class FixupType, class FlagType>
00042 class AMRSolver(DIM) : 
00043   public Solver(DIM)<VectorType,FixupType,FlagType>,
00044   public AMRSolverInterface(DIM)<VectorType> {
00045 
00046   typedef Integrator(DIM)<VectorType> integrator_type;
00047   typedef InitialCondition(DIM)<VectorType> initial_condition_type;
00048   typedef BoundaryConditions(DIM)<VectorType> boundary_conditions_type;
00049 
00050   typedef typename VectorType::InternalDataType DataType;
00051   typedef GridFunction(DIM)<VectorType> vec_grid_fct_type;  
00052   typedef GridData(DIM)<VectorType> vec_grid_data_type;
00053 
00054   typedef Vector(1)<FlagType> VFlagType;
00055   typedef GridData(DIM)<VFlagType> vflag_grid_data_type;
00056   typedef GridData(DIM)<FlagType>  flag_data_type;
00057 
00058 public:
00059   AMRSolver(DIM)(integrator_type& integ, 
00060                  initial_condition_type& init,
00061                  boundary_conditions_type& bc) : 
00062     Solver(DIM)<VectorType, FixupType, FlagType>(integ, init, bc), 
00063       FixupPar(1), RegridEvery(1), MinEfficiency(0.7), 
00064       BlockWidth(1), OverlapWidth(0), BufferWidth(2), NestingBuffer(1),
00065       PlotFlags(0) {
00066 
00067     t = (double *)0; dt = (double *)0; cfl_new = (double *)0; 
00068     BufferWidth = NGhosts();
00069     AllocError::SetTexts("AMRSolver(DIM)","Constructor");
00070   }
00071 
00072   ~AMRSolver(DIM)() {    
00073     if (t) delete [] t;
00074     if (dt) delete [] dt;
00075     if (cfl_new) delete [] cfl_new;
00076   }
00077 
00078   virtual void register_at(ControlDevice& Ctrl, const string& prefix) {
00079     LocCtrl = Ctrl.getSubDevice(prefix+"AMRSolver");
00080     RegisterAt(LocCtrl,"DoFixup",FixupPar);
00081     RegisterAt(LocCtrl,"RegridEvery",RegridEvery);
00082     RegisterAt(LocCtrl,"MinEfficiency",MinEfficiency);
00083     RegisterAt(LocCtrl,"BufferWidth",BufferWidth);
00084     RegisterAt(LocCtrl,"BlockWidth",BlockWidth);
00085     RegisterAt(LocCtrl,"OverlapWidth",OverlapWidth);    
00086     RegisterAt(LocCtrl,"NestingBuffer",NestingBuffer);
00087     RegisterAt(LocCtrl,"PlotFlags",PlotFlags);
00088 
00089     Integrator_().register_at(LocCtrl, prefix);
00090     InitialCondition_().register_at(LocCtrl, prefix);
00091     BoundaryConditions_().register_at(LocCtrl, prefix); 
00092     if (_Flagging)
00093       Flagging_().register_at(LocCtrl, prefix); 
00094     if (_Fixup)
00095       Fixup_().register_at(LocCtrl, prefix); 
00096   } 
00097   virtual void register_at(ControlDevice& Ctrl) {
00098     register_at(Ctrl, "");
00099   }
00100 
00101   virtual void SetupData() {
00102     int me = MY_PROC(_Hierarchy); 
00103     int help_set = NGhosts();           
00104     f_init_opcommon(help_set);             
00105     SetProlongFunction(U(), (void *) &f_prolong_amr);
00106     SetRestrictFunction(U(), (void *) &f_restrict_amr);
00107     if (ErrorEstimation()) {
00108       SetProlongFunction(Ush(), (void *) &f_prolong_amr);
00109       SetRestrictFunction(Ush(), (void *) &f_restrict_amr);
00110     }
00111 
00112     t = new double[MaxLevel(GH())+1];
00113     dt = new double[MaxLevel(GH())+1];
00114     cfl_new = new double[MaxLevel(GH())+1];
00115 
00116     Integrator_().SetupData();
00117     if (_Flagging && MaxLevel(GH())>=1) {
00118       Flagging_().SetBufferwidth(Min(Max(BufferWidth,OverlapWidth-1),
00119                                      MAXOVERLAPWIDTH));
00120       Flagging_().SetupData();
00121     }
00122     else
00123       RegridEvery = 0; 
00124 
00125     if (_Fixup && FixupPar>0)
00126       Fixup_().SetupData();
00127     else
00128       FixupPar = 0;
00129 
00130     if (FixupPar && NestingBuffer<1 && RegridEvery!=AMRSolverRegridFalse) {
00131       if (me == VizServer) 
00132         cout << "   Fixup requires a NestingBuffer>0 ! Using Default." << endl;
00133       NestingBuffer = 1;
00134     }
00135     GH().DAGH_SetNestingBuffer(NestingBuffer);
00136   }
00137 
00138   virtual void Initialize(const double dt_start) {   
00139     START_WATCH
00140 
00141     U().GF_DeleteStorage(1);
00142     if (ErrorEstimation()) 
00143       Ush().GF_DeleteStorage(1);
00144 
00145     //---------------------------------------------------------------
00146     // Calculate first grid distribution  
00147     //---------------------------------------------------------------
00148     int lev = 0;
00149     if (RegridEvery != AMRSolverRegridFalse) {
00150       while (lev<=FineLevel(GH()) && lev<MaxLevel(GH())) {
00151         //------------------------------------------------------------------
00152         // Set up initial data  
00153         //------------------------------------------------------------------                      
00154 #ifdef DEBUG_PRINT_AMRSOLVER
00155         ( comm_service::log() <<  "  *** Setting flags at Level: " << lev << "\n" ).flush();
00156 #endif
00157         //------------------------------------------------------------------
00158         // Initializing all levels ensures correct prolongation
00159         //------------------------------------------------------------------                      
00160         for (register int l=0; l<=FineLevel(GH()); l++) {
00161           InitialCondition_().Set(U(), l);
00162           if (ErrorEstimation()) 
00163             InitialCondition_().Set(Ush(), l);
00164         }
00165         BBoxList bblist;
00166         RegridLevel(0, 0, bblist, false);
00167  
00168         END_WATCH_INITIALIZATION
00169         START_WATCH
00170           RecomposeHierarchy(GH());
00171         END_WATCH_RECOMPOSING_WHOLE
00172         START_WATCH       
00173         lev++;
00174       }
00175 
00176       if (FineLevel(GH())>0) {
00177         for (register int l=0; l<=FineLevel(GH()); l++) 
00178           InitialCondition_().Set(U(), l);
00179         BBoxList bblist;
00180         forall (U(),0,FineLevel(GH()),c)      
00181           bblist.add(coarsen(U().interiorbbox(0,FineLevel(GH()),c),
00182                              RefineFactor(GH(),FineLevel(GH())-1)));
00183         end_forall
00184         RegridLevel(0, 0, bblist, true);
00185         END_WATCH_INITIALIZATION
00186         START_WATCH
00187           RecomposeHierarchy(GH());
00188         END_WATCH_RECOMPOSING_WHOLE
00189         START_WATCH
00190       }
00191     }
00192  
00193     U().GF_CreateStorage(1);
00194     if (ErrorEstimation()) 
00195       Ush().GF_CreateStorage(1);
00196 
00197     for (lev=0; lev<=FineLevel(GH()); lev++) { 
00198 #ifdef DEBUG_PRINT_AMRSOLVER
00199       ( comm_service::log() <<  "  *** Initializing Level: " << lev << " *** \n" ).flush();
00200 #endif 
00201       InitialCondition_().Set(U(), lev);
00202       if (ErrorEstimation()) 
00203         InitialCondition_().Set(Ush(), lev);
00204       t[lev] = 0.0;
00205     }    
00206 
00207     SetTimeSpecs(GH(), 0.0, dt_start, 2);
00208     END_WATCH_INITIALIZATION
00209   }
00210 
00211   virtual void Restart(const char* CheckpointFile) {
00212     START_WATCH
00213     RecomposeHierarchy(GH(), CheckpointFile);      
00214     double NextTime;
00215     for (register int l=0; l<=FineLevel(GH()); l++) {
00216       GH().DAGH_GetTimeSpecs(t[l], NextTime);
00217       int Time = CurrentTime(GH(),l);
00218       SetPhysicalTime(U(),Time,l,t[l]);
00219       if (ErrorEstimation()) SetPhysicalTime(Ush(),Time,l,t[l]);
00220     }
00221     END_WATCH_INITIALIZATION
00222   }
00223 
00224   virtual double Tick(int VariableTimeStepping, const double dtv[], const double cflv[],
00225                       int& Rejections, int& RedistributeEvery) {
00226 
00227     double told = t[0];
00228     double cfl_max;
00229     Rejections = 0;
00230     do {
00231       strstream* RestartStorage = (strstream *)0;
00232       char* RestartPt = (char *)0;
00233       if (VariableTimeStepping==AutomaticTimeStepsRestart) {
00234         AllocError::SetTexts("AMRSolver(DIM)","Memory for restart");      
00235 #if defined(__xlC__)
00236         RestartStorage = new strstream();
00237 #else
00238         int sizept = GH().DAGH_Checkpoint_StrStream_Memory();
00239         RestartPt = new char[sizept]; 
00240         RestartStorage = new strstream(RestartPt,sizept);
00241 #endif
00242         GH().DAGH_Checkpoint(*RestartStorage); 
00243       }  
00244 
00245 #ifdef DEBUG_PRINT_AMRSOLVER
00246       double Current_Time, Next_Time;
00247       GH().DAGH_GetTimeSpecs(Current_Time, Next_Time);
00248       ( comm_service::log() <<  " --- Iteration: " << StepsTaken(GH(),0)+1 << " ---"
00249         << "   t = " << Current_Time << "   dt = " 
00250         << DeltaT(GH(), 0) << "\n" ).flush();
00251 #endif
00252 #ifdef DEBUG_PROFILE
00253       ( cout << "\n" ).flush();
00254 #endif
00255       
00256       dt[0] = DeltaT(GH(), 0);
00257       int l=1;
00258       for (; l<=FineLevel(GH()); l++)
00259         dt[l] = dt[l-1] / RefineFactor(GH(),l-1);
00260       // Use this for simplified AMR
00261       //        dt[l] = dt[l-1];
00262 
00263       AdvanceLevel(0, RegridEvery, 
00264                    !(RegridEvery != AMRSolverRegridFalse ? 
00265                      StepsTaken(GH(),0)%RegridEvery==0 && StepsTaken(GH(),0)>0 : false),
00266                    ErrorEstimation() && (RegridEvery != AMRSolverRegridFalse ? 
00267                      (StepsTaken(GH(),0)+1)%RegridEvery==0 : false), FixupPar > 0,
00268                    !(RedistributeEvery>0 && StepsTaken(GH(),0)%RedistributeEvery!=0),
00269                    RedistributeEvery<=0); 
00270 
00271       cfl_max = 0.0;
00272       for (l=0; l<=FineLevel(GH()); l++)
00273         cfl_max = cfl_max > cfl_new[l] ? cfl_max : cfl_new[l];
00274       
00275 #ifdef DAGH_NO_MPI
00276 #else
00277       if (comm_service::dce() && comm_service::proc_num() > 1) { 
00278         
00279         int num = comm_service::proc_num();
00280         
00281         int R;
00282         int size = sizeof(double);
00283         void *values = (void *) new char[size*num];
00284         
00285         R = MPI_Allgather(&cfl_max, size, MPI_BYTE, values, size, MPI_BYTE, 
00286                           comm_service::comm(U().GF_Id()));
00287         if ( MPI_SUCCESS != R ) 
00288           comm_service::error_die( "AMRSolver(DIM)::cfl_max", "MPI_Allgather", R );
00289 
00290         for (int i=0;i<num;i++) {
00291           double tmax = *((double *)values + i);
00292           cfl_max = cfl_max > tmax ? cfl_max : tmax;
00293         }
00294         if (values) delete [] (char *)values;
00295       }
00296 #endif
00297      
00298 #ifdef DEBUG_PRINT_AMRSOLVER
00299       ( comm_service::log() << "   Levels = " << FineLevel(GH())+1 
00300         << "   max. CFL = " << cfl_max << "\n" ).flush();
00301 #endif
00302 #ifdef DEBUG_PROFILE
00303       ( cout << "\n" ).flush();
00304 #endif
00305 
00306       if (cfl_max > cflv[0]) 
00307         if (VariableTimeStepping==AutomaticTimeStepsRestart) {
00308           if (RestartStorage!=(strstream *)0) {     
00309             GH().DAGH_RecomposeHierarchy(*RestartStorage);
00310             for (int lev=0; lev<=FineLevel(GH()); lev++)  
00311               t[lev] = told;
00312             Rejections++;
00313           }
00314           else
00315             cerr << "   Restart failure!" << endl << flush ;        
00316           if (cfl_max > VERY_LARGE_CFL)
00317             cerr << "   max. CFL>" << (double)VERY_LARGE_CFL << "   " << flush;
00318         }
00319         else if (cfl_max > 1.0)
00320           cerr << "   max. CFL>1.0 !   " << flush;
00321         
00322       if (VariableTimeStepping!=FixedTimeSteps) 
00323         if (cfl_max == 0.0)
00324           SetTimeSpecs(GH(), t[0], t[0]+dtv[1], 2);
00325         else {
00326           double dt_predict = (DeltaT(GH(), 0) / cfl_max) * cflv[1];
00327           SetTimeSpecs(GH(), t[0], t[0] + 
00328                        (dtv[1] < dt_predict ? dtv[1] : dt_predict), 2);
00329         }
00330       else
00331         SetTimeSpecs(GH(), t[0], t[0]+dtv[0], 2);
00332 
00333       if (RestartStorage != (strstream *)0)
00334         delete RestartStorage;
00335       if (RestartPt != (char *)0)
00336         delete [] RestartPt;
00337 
00338     } while (t[0] <= told);
00339 
00340     return cfl_max;
00341   }  
00342 
00343   virtual double IntegrateLevel(vec_grid_fct_type& u, const int Time, const int Level, 
00344                                 double t, double dt, bool DoFixup, double tc, 
00345                                 const int which) {
00346 
00347     //---------------------------------------------------------------
00348     // Take one step on u. u(Time, Level) remains unchanged. 
00349     //---------------------------------------------------------------
00350     char errtext[256], whichtext[16];
00351     if (which<=0 || which>2) sprintf(whichtext,"Main");
00352     else if (which==1) sprintf(whichtext,"Estimate");
00353     else sprintf(whichtext,"Shadow");
00354     sprintf(errtext,"Flux allocation for %s",whichtext);
00355     AllocError::SetTexts("AMRSolver(DIM)",errtext);      
00356 
00357     int TStep = TimeStep(u,Level);
00358     double cfl = 0, cfl_grid;
00359     DCoords dx(DIM);
00360     for (int d=0; d<DIM; d++)
00361       dx(d) = DeltaX(u,d,Level);
00362 
00363     int mpass = 0; 
00364     if (Integrator_().MaxIntegratorPasses() > 0) mpass = 1;
00365     do {
00366 
00367       forall (u,Time,Level,c)      
00368         vec_grid_data_type& u_old = u(Time, Level, c);
00369         vec_grid_data_type& u_new = u(Time+TStep, Level, c); 
00370 
00371         temporary_fluxes(f, u_old) 
00372 #ifdef DEBUG_PRINT_INTEGRATOR
00373         if (mpass<=1) ( comm_service::log() << "      " << which << ": " ).flush();
00374 #endif
00375         START_WATCH
00376           cfl_grid = Integrator_().CalculateGrid(u_new, u_old, f, t, dt, dx, mpass);
00377         END_WATCH_INTEGRATION(which)  
00378 #ifdef DEBUG_PROFILE
00379         if (mpass<=1) ( cout << "." ).flush();
00380 #endif
00381  
00382         cfl = (cfl > cfl_grid ? cfl : cfl_grid);
00383 
00384         if (Level>0 && DoFixup) {
00385           // add_first_order_fluxes() solves a Riemann-problem on the basis of
00386           // u(CurrentTime(GH,Level-1),Level-1) at fine-coarse interfaces. 
00387           // Do not change u(CurrentTime(GH,Level-1),Level-1)!
00388           START_WATCH
00389             Fixup_().AddFluxes(Time, Level, c, f, tc, t, dt, dx, mpass);
00390           END_WATCH_FIXUP_WHOLE 
00391         }
00392           
00393         if (Level<FineLevel(GH()) && DoFixup) {
00394           START_WATCH
00395             Fixup_().SaveFluxes(Time, Level, c, f , dt, dx, mpass);
00396           END_WATCH_FIXUP_WHOLE 
00397         }
00398 
00399         end_temporary_fluxes(f) 
00400       end_forall
00401 
00402       // Set boundary values again at t=Time. As the partially updated time
00403       // step is stored at Time+TStep the two time steps have to swaped. 
00404       if (mpass > 0) {
00405         SwapTimeLevels(u,Level,Time,Time+TStep);
00406         START_WATCH
00407           AdaptiveBoundaryUpdate(u,Time,Level);
00408         END_WATCH_BOUNDARIES_INTERPOLATION  
00409         START_WATCH
00410           Sync(u,Time,Level);
00411         END_WATCH_BOUNDARIES_SYNC
00412         START_WATCH
00413           ExternalBoundaryUpdate(u,Time,Level);
00414         END_WATCH_BOUNDARIES_WHOLE
00415         SwapTimeLevels(u,Level,Time,Time+TStep);
00416       }
00417 
00418       mpass++;
00419     } while (mpass <= Integrator_().MaxIntegratorPasses());
00420 
00421     return cfl;
00422   }
00423   
00424 protected:
00425   void RegridLevel(const int Time, const int BaseLevel, 
00426                    BBoxList& bblist, bool TakeListOnFinestLevel) {
00427 
00428 #ifdef DEBUG_PRINT_AMRSOLVER
00429     ( comm_service::log() <<  "  *** Regridding at Level: " << BaseLevel 
00430       << "   t: " << Time << " Max: " << MaxLevel(GH()) << " fine: " 
00431       << FineLevel(GH()) << "\n" ).flush();
00432 #endif
00433 
00434     int l;
00435     int flev = FineLevel(GH());
00436     if (flev == 0) l = 0;
00437     else if (flev >= MaxLevel(GH())) l = MaxLevel(GH())-1;      
00438     else l = flev;
00439     if (TakeListOnFinestLevel) {
00440       Refine(GH(),bblist,l);      
00441       l--;
00442     } 
00443 
00444     char flagname[DAGHBktGFNameWidth+16];
00445     if (PlotFlags && LastOutputTime()==Time) 
00446       sprintf(flagname,"flag_%d",Time); 
00447     int me = MY_PROC(GH); 
00448 
00449     for (;l>=BaseLevel;l--) { 
00450       //---------------------------------------------------------------
00451       // Flag cells for refinement by error estimation
00452       //---------------------------------------------------------------
00453       START_WATCH
00454 
00455 #ifdef DEBUG_AMR
00456         CheckLevel(U(),Time,l,"AMRSolver(DIM).RegridLevel::before Flagging");
00457 #endif
00458         Flagging_().FlagLevel(Time, l, t[l], dt[l]);
00459 
00460         // Ensure nesting of higher level patches. Then syncronize the flags.
00461         forall (Flagging_().Flags(),Time,l,c)  
00462           for (BBox *_b = bblist.first();_b;_b=bblist.next()) 
00463             if (!_b->empty()) {
00464               BBox wb = Flagging_().Flags().interiorbbox(Time,l,c);
00465               if(wb.stepsize(0)>_b->stepsize(0))
00466                 _b->coarsen(wb.stepsize(0)/_b->stepsize(0));
00467               Flagging_().Flags()(Time,l,c).plus(200,*_b);
00468             }
00469         end_forall
00470 
00471         // The flags have to be synced to create the bufferzone around flagged cells
00472         // correctly. Without syncing no bufferzone into neighbouring patches on other
00473         // processors would be created.
00474         // The radius for the syncronization stencil is set to
00475         // Min(Max(BufferWidth,OverlapWidth-1),MAXOVERLAPWIDTH)
00476         START_WATCH
00477           Sync(Flagging_().Flags(), Time, l);
00478         END_WATCH_BOUNDARIES_SYNC
00479       END_WATCH_FLAGGING 
00480 
00481       if (PlotFlags && LastOutputTime()==Time) {
00482         forall (Work(),Time,l,c)  
00483           flag_data_type& flag = Flagging_().Flags()(Time,l,c);
00484           vflag_grid_data_type vflag_help(flag.bbox(),(VFlagType*) flag.data());
00485           equals_from(Work()(Time,l,c), vflag_help, 0);
00486           VFlagType* databuf;
00487           vflag_help.deallocate(databuf);
00488         end_forall      
00489         if (me == VizServer && l==0) 
00490           cout << " *** Writing " << flagname << endl; 
00491         Write(Work(),Time,l,DAGH_Double,flagname); 
00492       }  
00493 
00494       //---------------------------------------------------------------
00495       // Cluster at refine 
00496       //---------------------------------------------------------------
00497 #ifdef DEBUG_PRINT_INTEGRATOR
00498       ( comm_service::log() << "  *** Clustering at Level: " << l << "\n" ).flush();
00499 #endif
00500       START_WATCH        
00501         BBoxList bblexclude, bblcut;
00502         for (BBox *bbi=GH().wholebaselist()->first();bbi;
00503              bbi=GH().wholebaselist()->next())      
00504           bblexclude.add(refine(*bbi,GH().refinedby(l)));
00505         GH().glb_bboxlist(bblcut,l);
00506         bblexclude -= bblcut;
00507 
00508         // After syncing, the clusterer creates the bufferzone locally.
00509         DAGHCluster(DIM)(Flagging_().Flags(), Time, l, 
00510                          BlockWidth, OverlapWidth, BufferWidth, 
00511                          MinEfficiency, (FlagType)GoodPoint,
00512                          bblist, bblist, bblexclude);
00513       END_WATCH_CLUSTERING
00514 
00515       if (bblist.isempty()) {
00516         BBox empty_box;
00517         bblist.add(empty_box);
00518       }
00519 
00520 #ifdef DEBUG_PRINT_RG_REFINE
00521       ( comm_service::log() << "\n************* New refine list at level " 
00522         << l << " *************\n" << bblist
00523         << "\n************* ***************** *************\n"
00524         ).flush();
00525 #endif
00526 
00527       Refine(GH(),bblist,l);      
00528     }
00529 
00530 #ifndef DAGH_NO_MPI
00531     if (PlotFlags && LastOutputTime()==Time) 
00532       MPI_Barrier(comm_service::comm()); 
00533 #endif
00534   }
00535 
00536   virtual void AdvanceLevel(const int Level, int RegridEvery, bool RegridDone, 
00537                              bool ShadowAllowed, bool DoFixup,
00538                              bool RecomposeBaseLev, bool RecomposeHighLev) {
00539     //---------------------------------------------------------------
00540     // Select number of iterations to run based on current grid level
00541     //---------------------------------------------------------------
00542     int NoIterations = 0;
00543     if (Level==0) 
00544       NoIterations = 1;
00545     else
00546       NoIterations = RefineFactor(GH(),Level-1);
00547     // Use this for simplified AMR
00548     //       NoIterations = 1;
00549 
00550     int Time;
00551     int TStep = TimeStep(U(),Level);
00552     double cfl;
00553     cfl_new[Level] = 0.0;
00554     DCoords dx(DIM);
00555     for(int d=0; d<DIM; d++)
00556       dx(d) = DeltaX(U(),d,Level);
00557 
00558     for (int k=0; k<NoIterations; k++) {      
00559       Time = CurrentTime(GH(),Level);
00560       SetPhysicalTime(U(),Time+TStep,Level,t[Level]+dt[Level]);
00561       if (ShadowAllowed) 
00562         SetPhysicalTime(Ush(),Time+TimeStep(Ush(),Level),Level, 
00563                         t[Level]+dt[Level]*Ush().factor());
00564 
00565       bool DoRegrid = (RegridEvery!= AMRSolverRegridFalse ?
00566                        Level<MaxLevel(GH()) && k%RegridEvery==0 && 
00567                        !RegridDone && t[Level]>0.0 : false);    
00568      
00569       // Set boundary conditions for current time
00570       //
00571       // Interpolation at fine-coarse interfaces is done in the following way:
00572       // k=0: Space prolongation from 
00573       //      u(CurrentTime(GH,Level-1),Level-1)
00574       // k>0: Space prolongation of 
00575       //      u(CurrentTime(GH,Level-1)+TimeStep(GH,Level-1),
00576       //        Level-1) and (CurrentTime(GH,Level-1,) and
00577       //      time interpolation
00578       // Ghostcells are filled in the following order:
00579       // 1. forall (u,Time,Level,c) 
00580       //      Interpolate completely into all sides abutting a patch of the coarser level.
00581       // 2. forall (u,Time,Level,c) 
00582       //      Override previous values in ghostcells overlying a patch of the same level.
00583       // 3. forall (u,Time,Level,c)
00584       //      Set physical boundary conditions at sides outside of the domain.
00585       // BoundaryUpdate() calls all necessary functions in the right order!
00586       // RecomposeHierarchy() calls BoundaryUpdate() on all available time steps
00587       // and levels. Therefore, we can skip the setting of boundary conditions on fine 
00588       // grid levels, if RecomposeHierarchy() has been called on the coarse base level.
00589       if (Level==0 || !RegridDone) {
00590         START_WATCH
00591           AdaptiveBoundaryUpdate(U(),Time,Level);
00592 #ifdef DEBUG_AMR
00593           CheckLevel(U(),Time,Level,
00594                      "AMRSolver(DIM).AdvanceLevel::after AdaptiveBoundaryUpdate");
00595 #endif
00596         END_WATCH_BOUNDARIES_INTERPOLATION
00597    
00598         START_WATCH
00599           Sync(U(),Time,Level);
00600 #ifdef DEBUG_AMR
00601           CheckLevel(U(),Time,Level,"AMRSolver(DIM).AdvanceLevel::after Sync");
00602 #endif
00603         END_WATCH_BOUNDARIES_SYNC
00604 
00605         START_WATCH 
00606           ExternalBoundaryUpdate(U(),Time,Level);
00607 #ifdef DEBUG_AMR
00608           CheckLevel(U(),Time,Level,
00609                      "AMRSolver(DIM).AdvanceLevel::after ExternalBoundaryUpdate");
00610 #endif
00611         END_WATCH_BOUNDARIES_WHOLE
00612       }
00613 
00614       //---------------------------------------------------------------
00615       // regridding...
00616       //---------------------------------------------------------------
00617       if (DoRegrid) {   
00618         //---------------------------------------------------------------
00619         // Regrid all levels > Level, Level itself stays fixed
00620         //---------------------------------------------------------------       
00621         BBoxList bblist;
00622         RegridLevel(Time, Level, bblist, false);
00623         
00624         //---------------------------------------------------------------
00625         // Recompose the GridHierarchy
00626         //---------------------------------------------------------------
00627         int finest = FineLevel(GH());
00628         
00629         START_WATCH
00630           // Time interpolation needs two time steps only on the coarser levels.
00631           if (DoFixup) 
00632             Fixup_().SetMaxRecomposeLevel(Level);
00633           register int lev;
00634           for (lev=Level; lev<=MaxLevel(GH()); lev++) {
00635             U().GF_DeleteStorage(1,lev);
00636             if (ShadowAllowed) {
00637               Ush().GF_DeleteStorage(1,lev);
00638               if (lev==MaxLevel(GH())) Ush().GF_DeleteStorage(0,lev);
00639             }
00640           }
00641 
00642 #ifdef DEBUG_AMR
00643           if (Integrator_().Abort()) 
00644             for (register int l=0; l<=FineLevel(GH()); l++) {
00645               int time = CurrentTime(GH(),l);
00646               int tstep = TimeStep(U(),l);
00647               CheckLevel(U(),time,l,"AMRSolver(DIM).AdvanceLevel::before Recompose");
00648               if (l<Level) 
00649                 CheckLevel(U(),time+tstep,l,
00650                            "AMRSolver(DIM).AdvanceLevel::before Recompose for Time+TStep");
00651               if (ShadowAllowed && l<MaxLevel(GH())) {
00652                 int shtstep = TimeStep(Ush(),l);
00653                 CheckLevel(Ush(),time,l,
00654                            "AMRSolver(DIM).AdvanceLevel::before Recompose for Shadow");
00655                 if (l<Level) 
00656                   CheckLevel(Ush(),time+shtstep,l,
00657                      "AMRSolver(DIM).AdvanceLevel::before Recompose for Time+TStep for Shadow");
00658               }         
00659             }
00660 #endif
00661 
00662           RecomposeHierarchy(GH(), (Level==0 && RecomposeBaseLev) || 
00663                              (Level>0 && RecomposeHighLev) ? DAGHTrue : DAGHFalse);
00664 #ifdef DEBUG_AMR
00665           if (Integrator_().Abort()) 
00666             for (register int l=0; l<=FineLevel(GH()); l++) {
00667               int time = CurrentTime(GH(),l);
00668               int tstep = TimeStep(U(),l);
00669               CheckLevel(U(),time,l,"AMRSolver(DIM).AdvanceLevel::after Recompose");
00670               if (l<Level) 
00671                 CheckLevel(U(),time+tstep,l,
00672                            "AMRSolver(DIM).AdvanceLevel::after Recompose for Time+TStep");
00673               if (ShadowAllowed && l<MaxLevel(GH())) {
00674                 int shtstep = TimeStep(Ush(),l);
00675                 CheckLevel(Ush(),time,l,
00676                            "AMRSolver(DIM).AdvanceLevel::after Recompose for Shadow");
00677                 if (l<Level) 
00678                   CheckLevel(Ush(),time+shtstep,l,
00679                      "AMRSolver(DIM).AdvanceLevel::after Recompose for Time+TStep for Shadow");
00680               }         
00681             }
00682 #endif
00683 
00684           for (lev=Level; lev<=MaxLevel(GH()); lev++) {
00685             U().GF_CreateStorage(1,lev);
00686             if (ShadowAllowed && lev<MaxLevel(GH()))
00687               Ush().GF_CreateStorage(1,lev);
00688           }
00689         END_WATCH_RECOMPOSING_WHOLE
00690           
00691         if (finest < FineLevel(GH())) {
00692           t[FineLevel(GH())] = t[finest];
00693           dt[FineLevel(GH())] = dt[finest] / RefineFactor(GH(),finest);
00694           // Use this for simplified AMR
00695           //      dt[FineLevel(GH())] = dt[finest];
00696         }
00697         RegridDone = true;
00698       } 
00699       else 
00700         RegridDone = false;
00701         
00702       //---------------------------------------------------------------
00703       // Take one step on U(). U()(Time, Level) remains unchanged. 
00704       // In principle, it would be possible to skip this step after error estimation on the 
00705       // unchanged level. But this is not the case here, because numerical fluxes are only 
00706       // available for single grids.  As fine grids might change due to error estimation,
00707       // the saving of coarse grid fluxes would require the storage of numerical fluxes
00708       // on the entire coarse level.
00709       //---------------------------------------------------------------      
00710       cfl = IntegrateLevel(U(), Time, Level, t[Level], dt[Level], 
00711                            DoFixup, t[Level-1], 0); 
00712       cfl_new[Level] = cfl_new[Level] > cfl ? cfl_new[Level] : cfl;
00713 
00714       //---------------------------------------------------------------
00715       // Take one step on Ush().
00716       // If restriction into Ush() is done AFTER the step on
00717       // U(), U()(Time,Level) has to remain unchanged in a fractional 
00718       // step method!
00719       //---------------------------------------------------------------
00720                 
00721       if (RegridEvery != AMRSolverRegridFalse ?
00722           Level<MaxLevel(GH()) && ShadowAllowed &&
00723           (Level>0 ? (k+1)%RegridEvery==0 : true) : false) {
00724 
00725         double dt_sh = dt[Level] * Ush().factor();
00726         SetPhysicalTime(Ush(),Time,Level,t[Level]);
00727         
00728         //------------------------------------------------------------------------
00729         // Restrict from U() into Ush()
00730         //------------------------------------------------------------------------
00731         int myargc = sizeof(int); int myargs = NEquations();
00732         forall (U(),Time,Level,cm)   
00733           vec_grid_data_type& u_main = U()(Time, Level, cm);
00734           forall (Ush(),Time,Level,cs)          
00735             vec_grid_data_type& u_shadow = Ush()(Time, Level, cs);
00736             BBox bb = u_shadow.bbox()*u_main.bbox();
00737             if (!bb.empty())
00738               f_restrict_amr(FA(DIM,u_main),FA(DIM,u_shadow),
00739                              BOUNDING_BOX(bb),(char *)&myargs, &myargc); 
00740           end_forall
00741         end_forall
00742 
00743         START_WATCH
00744           AdaptiveBoundaryUpdate(Ush(),Time,Level);
00745 #ifdef DEBUG_AMR
00746           CheckLevel(Ush(),Time,Level,
00747                      "AMRSolver(DIM).AdvanceLevel::after AdaptiveBoundaryUpdate for Shadow");
00748 #endif
00749         END_WATCH_BOUNDARIES_INTERPOLATION
00750         START_WATCH
00751           Sync(Ush(),Time,Level);
00752 #ifdef DEBUG_AMR
00753           CheckLevel(Ush(),Time,Level,"AMRSolver(DIM).AdvanceLevel::after Sync for Shadow");
00754 #endif
00755         END_WATCH_BOUNDARIES_SYNC
00756         START_WATCH
00757           ExternalBoundaryUpdate(Ush(),Time,Level);
00758 #ifdef DEBUG_AMR
00759           CheckLevel(Ush(),Time,Level,
00760                      "AMRSolver(DIM).AdvanceLevel::after ExternalBoundaryUpdate for Shadow");
00761 #endif
00762         END_WATCH_BOUNDARIES_WHOLE
00763 
00764         IntegrateLevel(Ush(), Time, Level, t[Level], dt_sh, false, 0.0, 2); 
00765         
00766       } // Ends if statement for Ush()   
00767         
00768       //---------------------------------------------------------------
00769       // If we are not at the finest level then go to next level
00770       //---------------------------------------------------------------
00771       
00772       if (Level < FineLevel(GH())) {
00773         
00774         // Boundary conditions have to be applied on U()(Time+TStep,Level)
00775         // to ensure correct time-space interpolation for Level+1.
00776         START_WATCH
00777           AdaptiveBoundaryUpdate(U(),Time+TStep,Level);
00778 #ifdef DEBUG_AMR
00779           CheckLevel(U(),Time+TStep,Level,
00780                      "AMRSolver(DIM).AdvanceLevel::after AdaptiveBoundaryUpdate for Time+TStep");
00781 #endif
00782         END_WATCH_BOUNDARIES_INTERPOLATION
00783 
00784         START_WATCH
00785           Sync(U(),Time+TStep,Level);
00786 #ifdef DEBUG_AMR
00787           CheckLevel(U(),Time+TStep,Level,
00788                      "AMRSolver(DIM).AdvanceLevel::after Sync for Time+TStep");
00789 #endif
00790         END_WATCH_BOUNDARIES_SYNC
00791 
00792         START_WATCH
00793           ExternalBoundaryUpdate(U(),Time+TStep,Level);
00794 #ifdef DEBUG_AMR
00795           CheckLevel(U(),Time+TStep,Level,
00796                      "AMRSolver(DIM).AdvanceLevel::after ExternalBoundaryUpdate for Time+TStep");
00797 #endif
00798         END_WATCH_BOUNDARIES_WHOLE
00799 
00800         // Recursive Integration of next level in hierarchy
00801         AdvanceLevel(Level+1, RegridEvery, RegridDone, 
00802                      ShadowAllowed, DoFixup, RecomposeBaseLev, 
00803                      RecomposeHighLev);
00804         
00805 #ifdef DEBUG_AMR
00806         CheckLevel(U(),Time+TStep,Level,"AMRSolver(DIM).AdvanceLevel::before Restrict and Fixup");
00807 #endif
00808 
00809 #ifdef DEBUG_PRINT_FIXUP
00810         VectorType mass_old;
00811         if (Level == 0 && _Fixup) 
00812           mass_old = Sum(U(),Time+TStep,Level);
00813 #endif
00814  
00815         if (DoFixup) {
00816           START_WATCH
00817             Fixup_().Correction(Time+TStep, Time, Level, dx);     
00818           END_WATCH_FIXUP_WHOLE 
00819         }
00820 
00821         // Implementation of fixup assumes that restriction is done AFTERWARDS!
00822         // Only values from internal cells are used. Ghostcell values are not restricted.
00823         int myargc = sizeof(int); int myargs = NEquations();
00824         Restrict(U(), Time+TStep, Level+1, Time+TStep, Level, (char *)&myargs, myargc);
00825 
00826 #ifdef DEBUG_AMR
00827         CheckLevel(U(),Time+TStep,Level,"AMRSolver(DIM).AdvanceLevel::after Restrict and Fixup");
00828 #endif
00829 
00830 #ifdef DEBUG_PRINT_FIXUP
00831         VectorType mass_new;
00832         if (Level == 0 && _Fixup) {
00833           ( comm_service::log() 
00834             << "\n*********** Difference in state variables at level " 
00835             << Level << " after fixup ********\n" ).flush();
00836           // Sum() uses only internal cells. No synchronization on Level is therefore 
00837           // necessary after restriction!
00838           mass_new = Sum(U(),Time+TStep,Level);
00839           ( comm_service::log() << mass_old << "-" 
00840             << mass_new << "=" << mass_old - mass_new ).flush();
00841           ( comm_service::log() 
00842             << "\n**************************************************************"
00843             << "***********\n" ).flush();
00844         }
00845 #endif
00846         
00847       } 
00848 #ifdef DEBUG_PROFILE
00849       ( cout << "\n" ).flush();
00850 #endif
00851 
00852       //---------------------------------------------------------------
00853       // Move from current time to previous.
00854       //---------------------------------------------------------------
00855       CycleTimeLevels(U(),Level);
00856       if (ShadowAllowed)
00857         CycleTimeLevels(Ush(),Level);
00858         
00859       //---------------------------------------------------------------
00860       //  Increment time step on current level
00861       //  IncrCurrentTime() moves internal time-indices.
00862       //  Can only be called after all time-depended operations, like
00863       //  time-interpolation or time-cycling.
00864       //---------------------------------------------------------------
00865       t[Level] += dt[Level]; 
00866       IncrCurrentTime(GH(),Level);
00867       SetPhysicalTime(U(),Time+TStep,Level,t[Level]);
00868       if (ShadowAllowed) 
00869           SetPhysicalTime(Ush(),Time+TStep,Level,t[Level]+ 
00870                           dt[Level]*(Ush().factor()-1));
00871       // Use this for simplified AMR
00872       //       if (Level>0) 
00873       //        for (int kk=1; kk<RefineFactor(GH(),Level-1); kk++)
00874       //          IncrCurrentTime(GH(),Level);
00875       RegridDone = false;
00876     }  
00877   } 
00878 
00879   void CheckLevel(vec_grid_fct_type &u, const int time, const int level, const char *text) {
00880     if (Integrator_().Abort()) {
00881       char wtext[1024];
00882       sprintf(wtext,"\non Level=%d at Time=%d: %s\n",level,time,text);
00883       forall (u,time,level,c)      
00884         vec_grid_data_type& uw = u(time,level,c);
00885         Integrator_().CheckGrid(uw, uw.bbox(), wtext);
00886       end_forall
00887     }
00888   }
00889 
00890 protected:
00891   BBox BoundaryBBox(const BBox& whole, const int s) {    
00892     int d = s/2;
00893 #ifdef DEBUG_PRINT
00894     assert (d>=0 && d<DIM);
00895 #endif
00896     BBox bb(whole); 
00897     if (s%2 == 0) 
00898       bb.upper(d) = bb.lower(d)+(NGhosts()-1)*bb.stepsize(d);
00899     else
00900       bb.lower(d) = bb.upper(d)-(NGhosts()-1)*bb.stepsize(d);
00901    return bb;
00902   }
00903 
00904 
00905   int FixupPar;
00906   int RegridEvery;
00907   double MinEfficiency;         
00908   int BlockWidth, OverlapWidth, BufferWidth, NestingBuffer;
00909   int PlotFlags;
00910 
00911   double *t, *dt;
00912   double *cfl_new;
00913 };
00914 
00915 
00916 #endif


Quickstart     Users Guide     Programmers Reference     Installation      Examples     Download



AMROC Main      Home      Contact
last update: 06/01/04