vtf-logo

AMRSolver.h

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

Generated on Fri Aug 24 13:00:47 2007 for AMROC Fluid-solver Framework - by  doxygen 1.4.7