vtf-logo

clawpack/applications/euler_chem/2d/CellStrucModelDet/src/Problem.h

00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2007 California Institute of Technology
00004 // Ralf Deiterding, ralf@amroc.net
00005 
00006 #ifndef AMROC_PROBLEM_H
00007 #define AMROC_PROBLEM_H
00008 
00009 #include "eulerrhok2.h"
00010 #define NEQUATIONS 10
00011 #define NEQUSED     9
00012 #define NFIXUP      8
00013 #define NAUX        4
00014 
00015 #define GLOBALMAXIMA  5
00016 
00017 #include "ClpProblem.h"
00018 
00019 #define OWN_FLAGGING
00020 #define OWN_AMRSOLVER
00021 #include "ClpStdProblem.h"
00022 #include "F77Interfaces/F77UpdateLevelTransfer.h"
00023 #include "SpecialOutput/AMRGridAccumulation.h"
00024 
00025 #define f_rcveloc FORTRAN_NAME(rcveloc, RCVELOC)
00026 extern "C" {
00027   void f_rcveloc(const DOUBLE v[]);
00028 }
00029 
00030 class FlaggingSpecific : 
00031   public AMRFlagging<VectorType,FixupType,FlagType,DIM> {
00032   typedef AMRFlagging<VectorType,FixupType,FlagType,DIM> base;
00033 public:
00034   FlaggingSpecific(base::solver_type& solver) : base(solver) {
00035       base::AddCriterion(new ScaledGradient<VectorType,FlagType,DIM>());
00036       base::AddCriterion(new LimiterType<VectorType,FlagType,DIM>());
00037       base::AddCriterion(new AbsoluteError<VectorType,FixupType,FlagType,DIM>(solver));
00038       base::AddCriterion(new RelativeError<VectorType,FixupType,FlagType,DIM>(solver));
00039       base::AddCriterion(new F77ScaledGradient<VectorType,FlagType,DIM>(f_flg));
00040       base::AddCriterion(new F77LimiterType<VectorType,FlagType,DIM>(f_flg));
00041       base::AddCriterion(new F77AbsoluteError<VectorType,FixupType,FlagType,DIM>(solver,f_flg));
00042       base::AddCriterion(new F77RelativeError<VectorType,FixupType,FlagType,DIM>(solver,f_flg));
00043     }
00044   ~FlaggingSpecific() { DeleteAllCriterions(); }
00045 };
00046 
00047 class SolverSpecific : 
00048   public AMRSolver<VectorType,FixupType,FlagType,DIM> {
00049   typedef VectorType::InternalDataType DataType;
00050   typedef AMRSolver<VectorType,FixupType,FlagType,DIM> base;
00051   typedef AMRGridAccumulation<DataType,DIM> accumulation_type;
00052   typedef F77FileOutput<VectorType,DIM> output_type;
00053 public:
00054   typedef base::vec_grid_data_type vec_grid_data_type;  
00055   typedef base::grid_data_type grid_data_type;
00056 
00057   SolverSpecific(IntegratorSpecific& integ, 
00058                  base::initial_condition_type& init,
00059                  base::boundary_conditions_type& bc) : base(integ, init, bc) {
00060     SetLevelTransfer(new F77UpdateLevelTransfer<VectorType,DIM>(f_prolong, f_restrict, f_tupdate));
00061     SetFileOutput(new F77FileOutput<VectorType,DIM>(f_out)); 
00062     SetFixup(new FixupSpecific(integ));
00063     SetFlagging(new FlaggingSpecific(*this)); 
00064     _Accumulation = new accumulation_type(f_rcveloc);
00065     MaxType = 1;
00066     TrackLevel = -1;
00067     TrackMin = 0.1;
00068     TrackMax = 1.e4;
00069     TrackOutputSingleFile = 1;
00070     TrackOutputEvery = 1;
00071     for (register int i=0; i<GLOBALMAXIMA; i++) 
00072       TrackMaxima[i] = -1;
00073   }  
00074 
00075   ~SolverSpecific() {
00076     delete _LevelTransfer;
00077     delete _Flagging;
00078     delete _Fixup;
00079     delete _FileOutput;
00080     delete _Accumulation;
00081   }
00082 
00083   virtual void register_at(ControlDevice& Ctrl) { base::register_at(Ctrl); }
00084   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00085     base::register_at(Ctrl, prefix);
00086     TrackCtrl = base::LocCtrl.getSubDevice("TrackFront");
00087     RegisterAt(TrackCtrl,"Level",TrackLevel);
00088     RegisterAt(TrackCtrl,"Min",TrackMin);
00089     RegisterAt(TrackCtrl,"Max",TrackMax);
00090     RegisterAt(TrackCtrl,"OutputSingleFile",TrackOutputSingleFile);
00091     RegisterAt(TrackCtrl,"OutputEvery",TrackOutputEvery);
00092     RegisterAt(base::LocCtrl,"MaxType",MaxType);
00093     char VariableName[32];
00094     for (register int i=0; i<GLOBALMAXIMA; i++) {
00095       std::sprintf(VariableName,"Maximum(%d)",i+1);
00096       RegisterAt(TrackCtrl,VariableName,TrackMaxima[i]);
00097     }
00098     _Accumulation->register_at(base::LocCtrl, prefix);
00099   }
00100 
00101   virtual void SetupData() {
00102     base::SetupData();
00103     _Accumulation->SetupData(base::PGH(), base::NGhosts());
00104     if (TrackLevel>MaxLevel(base::GH())) 
00105       TrackLevel=MaxLevel(base::GH());
00106   }
00107 
00108   virtual void Initialize_(const double& dt_start) {
00109     base::Initialize_(dt_start);
00110     _Accumulation->Initialize();
00111   }
00112 
00113   virtual void Output() {
00114     int Time = CurrentTime(base::GH(),0);
00115     if (Time == base::LastOutputTime()) return;
00116     _Accumulation->GridCombine(VizServer);
00117     int me = MY_PROC; 
00118     if (me == VizServer) {
00119       int Level = _Accumulation->AccLevel();
00120       base::FileOutput_().WriteOut(_Accumulation->AccGrid(),_Accumulation->AccName(),
00121                                    Time,Level,base::t[0]);
00122     }
00123     base::Output();
00124   }
00125 
00126   virtual void Checkpointing_(const char* CheckpointFile) {
00127     base::Checkpointing_(CheckpointFile);
00128     _Accumulation->GridCombine(VizServer);
00129     if (MY_PROC == VizServer) 
00130       _Accumulation->Checkpointing();
00131   }
00132 
00133   virtual bool Restart_(const char* CheckpointFile) {
00134     if (base::Restart_(CheckpointFile)) {
00135       if (MY_PROC == VizServer) 
00136         _Accumulation->Restart();
00137       else 
00138         _Accumulation->Initialize();
00139       return true;
00140     }
00141     else 
00142       return false;
00143   }
00144 
00145   inline DataType sgn(const DataType& v) const {
00146     return (v>0. ? 1. : -1.);
00147   }
00148 
00149   virtual void AdvanceLevel(const int Level, int RegridEvery, bool RegridDone, 
00150                             bool ShadowAllowed, bool DoFixup,
00151                             bool RecomposeBaseLev, bool RecomposeHighLev) {
00152 
00153     base::AdvanceLevel(Level,RegridEvery,RegridDone,ShadowAllowed,
00154                        DoFixup,RecomposeBaseLev,RecomposeHighLev);
00155 
00156     int Time = CurrentTime(base::GH(),Level);
00157     int TStep = TimeStep(base::U(),Level);
00158     if (MaxType) {
00159       AdaptiveBoundaryUpdate(base::U(),Time,Level);
00160       Sync(base::U(),Time,Level);
00161       ExternalBoundaryUpdate(base::U(),Time,Level);
00162       
00163       int irho = 1;
00164       int iu   = NEQUSED-DIM-2;
00165       int iv   = NEQUSED-DIM-1;
00166       ((output_type*) base::_FileOutput)->Transform(base::U(), base::Work(), Time+TStep, 
00167                                                     Level, irho, base::t[Level]);
00168       forall (base::U(),Time,Level,c)
00169         Coords ss(base::U()(Time,Level,c).bbox().stepsize());
00170         BBox bbi(base::U().interiorbbox(Time,Level,c));
00171         BeginFastIndex2(U, base::U()(Time,Level,c).bbox(), 
00172                         base::U()(Time,Level,c).data(), VectorType);
00173         BeginFastIndex2(Work, Work()(Time,Level,c).bbox(), 
00174                         Work()(Time,Level,c).data(), DataType);
00175         BeginFastIndex2(WorkN, Work()(Time+TStep,Level,c).bbox(), 
00176                         Work()(Time+TStep,Level,c).data(), DataType);
00177         DataType uy, vx;
00178         DCoords dx = base::GH().worldStep(ss);
00179         for_2 (i, j, bbi, ss)
00180           vx = (FastIndex2(U,i+ss(0),j)(iv)/FastIndex2(WorkN,i+ss(0),j)-
00181                 FastIndex2(U,i-ss(0),j)(iv)/FastIndex2(WorkN,i-ss(0),j))/(2.0*dx(0));
00182           uy = (FastIndex2(U,i,j+ss(1))(iu)/FastIndex2(WorkN,i,j+ss(1))-
00183                 FastIndex2(U,i,j-ss(1))(iu)/FastIndex2(WorkN,i,j-ss(1)))/(2.0*dx(1));
00184           FastIndex2(Work,i,j) = std::fabs(vx-uy);
00185         end_for
00186         EndFastIndex2(U);      
00187         EndFastIndex2(Work);      
00188         EndFastIndex2(WorkN);      
00189       end_forall
00190     }
00191     else {
00192       int ipress = base::Dim()+4;      
00193       ((output_type*) base::_FileOutput)->Transform(base::U(), base::Work(), Time, Level, 
00194                                                     ipress, base::t[Level]);
00195     }
00196   
00197     _Accumulation->Accumulate(base::Work(), Time,  Level, base::t[Level]);
00198   }
00199 
00200   virtual double Tick(int VariableTimeStepping, const double dtv[], 
00201                       const double cflv[], int& Rejections) {
00202 
00203     double cfl = base::Tick(VariableTimeStepping,dtv,cflv,Rejections);
00204     if (TrackLevel<0) return cfl;
00205 
00206     int TimeZero  = CurrentTime(base::GH(),0);
00207     TimeZero /= RefinedBy(base::GH(),MaxLevel(base::GH()));
00208     if (TimeZero % TrackOutputEvery != 0) return cfl;
00209 
00210     int Level = std::min(TrackLevel,FineLevel(base::GH()));
00211     int Time = CurrentTime(base::GH(),Level);
00212     int TStep = TimeStep(base::U(),Level);
00213 
00214     BBox wholebb(base::GH().wholebbox());
00215     wholebb.refine(base::GH().refinedby(Level));
00216     int idxl = wholebb.extents(1);
00217     
00218     {
00219       // Track the shock front in each row of cells as greatest x-location 
00220       // with local minimum in curvature. This captures basically the von
00221       // Neumann point.
00222       int fds = base::Dim();
00223       DataType* front_data = new DataType[(base::NEquations()+fds)*idxl];
00224       VectorType* front_val = (VectorType *)(front_data+fds*idxl);
00225       for (register int j=0;j<idxl; j++) {
00226         for (register int i=0;i<fds; i++) 
00227           front_data[fds*j+i]   = -1.e37;
00228         front_val[j] = -1.e37;
00229       }
00230       
00231       int ipress = base::Dim()+4;      
00232       ((output_type*) base::_FileOutput)->Transform(base::U(), base::Work(), Time, Level, 
00233                                                     ipress, base::t[Level]);
00234       forall (base::Work(),Time,Level,c)
00235         Coords ss(base::Work()(Time,Level,c).bbox().stepsize());
00236         BBox bbi(base::Work()(Time,Level,c).bbox());
00237         bbi.upper(0) -= bbi.stepsize(0);
00238         BeginFastIndex2(P, Work()(Time,Level,c).bbox(), 
00239                         Work()(Time,Level,c).data(), DataType);
00240         BeginFastIndex2(dP, Work()(Time+TStep,Level,c).bbox(), 
00241                         Work()(Time+TStep,Level,c).data(), DataType);
00242         DCoords dx = base::GH().worldStep(ss);
00243         // 1st derivative
00244         for_2 (i, j, bbi, ss)
00245           FastIndex2(dP,i,j) = (FastIndex2(P,i+ss(0),j)-FastIndex2(P,i,j))/dx(0);
00246         end_for
00247         bbi.lower(0) += bbi.stepsize(0);
00248         grid_data_type DataddP(bbi);
00249         BeginFastIndex2(ddP, DataddP.bbox(), DataddP.data(), DataType);
00250         // 2nd derivative
00251         for_2 (i, j, bbi, ss)
00252           FastIndex2(ddP,i,j) = (FastIndex2(dP,i,j)-FastIndex2(dP,i-ss(0),j))/dx(0);
00253         end_for
00254         bbi.upper(0) -= bbi.stepsize(0);
00255         // 3rd derivative
00256         for_2 (i, j, bbi, ss)
00257           FastIndex2(dP,i,j) = (FastIndex2(ddP,i+ss(0),j)-FastIndex2(ddP,i,j))/dx(0);
00258         end_for
00259         bbi = base::U().interiorbbox(Time,Level,c);
00260         for_2 (i, j, bbi, ss)
00261           if (FastIndex2(P,i,j)>=TrackMin && FastIndex2(P,i,j)<=TrackMax &&
00262               FastIndex2(ddP,i,j)<0. && 
00263               sgn(FastIndex2(dP,i,j))!=sgn(FastIndex2(dP,i-ss(0),j))) {
00264             DCoords fc = base::GH().worldCoords(Coords(2,i,j),ss);
00265             fc(0) *= (1.+dx(0)/(FastIndex2(dP,i-ss(0),j)-FastIndex2(dP,i,j)));
00266             int jj = (j-wholebb.lower(1))/ss(1);
00267             if (fc(0) > front_data[2*jj]) {
00268               front_data[fds*jj] = fc(0);
00269               front_data[fds*jj+1] = fc(1)+0.5*dx(1);
00270               front_val[jj] = base::U()(Time,Level,c)(i,j);
00271               DataType pmax = FastIndex2(P,i,j);
00272               for (int ii=i-base::NGhosts()*ss(0); ii<=i+base::NGhosts()*ss(0); ii+=ss(0)) {
00273                 if (FastIndex2(P,ii,j) > pmax) {
00274                   front_val[jj] = base::U()(Time,Level,c)(ii,j);
00275                   pmax = FastIndex2(P,ii,j);
00276                 }
00277               }
00278             }
00279           }
00280         end_for
00281         EndFastIndex2(P);      
00282         EndFastIndex2(dP);      
00283         EndFastIndex2(ddP);      
00284       end_forall
00285 
00286 #ifdef DAGH_NO_MPI
00287 #else
00288       if (comm_service::dce() && comm_service::proc_num() > 1) {        
00289         int num = comm_service::proc_num();
00290         MPI_Status status;
00291         int R;
00292         int size = sizeof(DataType)*(NEquations()+fds)*idxl;
00293         int tag = 10000;
00294         if (MY_PROC!=VizServer) {
00295           R = MPI_Send((void *)front_data, size, MPI_BYTE, VizServer, tag, comm_service::comm());
00296           if ( MPI_SUCCESS != R ) 
00297             comm_service::error_die( "Tick", "MPI_Send", R );
00298         }
00299         else 
00300           for (int proc=0; proc<num; proc++) {
00301             if (proc==VizServer) continue;
00302             DataType* dat = new DataType[(NEquations()+fds)*idxl];
00303             VectorType* datv = (VectorType *)(dat+fds*idxl);
00304             R = MPI_Recv((void *)dat, size, MPI_BYTE, proc, tag, comm_service::comm(), &status);
00305             if ( MPI_SUCCESS != R ) 
00306               comm_service::error_die( "Tick", "MPI_Recv", R );
00307             for (register int j=0; j<idxl; j++) 
00308               if (dat[fds*j] > front_data[fds*j]) {
00309                 for (register int i=0;i<fds; i++) 
00310                   front_data[fds*j+i] = dat[fds*j+i];
00311                 front_val[j] = datv[j];
00312               }
00313             delete [] dat;
00314           }
00315       }
00316 #endif
00317 
00318       int me = MY_PROC; 
00319       if (me == VizServer) {
00320         DataType* output_data = new DataType[_FileOutput->Ncnt()*idxl];
00321         BBox bb(2,0,0,idxl-1,0,1,1);
00322         vec_grid_data_type val(bb,front_val);
00323         for (int cnt=1;cnt<=_FileOutput->Ncnt(); cnt++) {
00324           if (_FileOutput->OutputName(cnt-1).c_str()[0] == '-') continue;
00325           grid_data_type output(bb,output_data+(cnt-1)*idxl);
00326           ((output_type::out_2_func_type) (((output_type*) base::_FileOutput)->GetOutFunc()))
00327             (FA(2,val),FA(2,output),BOUNDING_BOX(bb),base::NEquations(),cnt,base::t[Level]);
00328           DataType* dummy;
00329           output.deallocate(dummy);
00330         }
00331         std::ofstream outfile;
00332         std::ostream* out;
00333         char name[256];
00334         if (TrackOutputSingleFile) 
00335           sprintf(name,"front.txt");
00336         else 
00337           sprintf(name,"front_%d.txt",Time);
00338         std::string fname = name;
00339         outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00340         out = new std::ostream(outfile.rdbuf());
00341         if (TrackOutputSingleFile)        
00342           *out << "**********   t=" << base::t[Level] << "   Step:" 
00343                << Time << "   **********" << std::endl;
00344         for (register int j=0;j<idxl; j++) {
00345           *out << front_data[fds*j] << " " << front_data[fds*j+1];
00346           for (int cnt=0;cnt<_FileOutput->Ncnt(); cnt++) 
00347             if (_FileOutput->OutputName(cnt).c_str()[0] != '-') 
00348               *out << " " << output_data[cnt*idxl+j];
00349           *out << std::endl;
00350         }
00351         val.deallocate(front_val);
00352         delete [] output_data;
00353         outfile.close();
00354         delete out;      
00355       }
00356     }
00357 
00358     // Track the maximum of selectable output components in the entire domain.
00359     for (register int im=0; im<GLOBALMAXIMA; im++) 
00360       if (TrackMaxima[im]>=0) {
00361         int fds = base::Dim()+1;
00362         DataType* front_data = new DataType[(base::NEquations()+fds)*idxl];
00363         VectorType* front_val = (VectorType *)(front_data+fds*idxl);
00364         for (register int j=0;j<idxl; j++) {
00365           for (register int i=0;i<fds; i++) 
00366           front_data[fds*j+i]   = -1.e37;
00367           front_val[j] = -1.e37;
00368         }
00369         
00370         ((output_type*) base::_FileOutput)->Transform(base::U(), base::Work(), Time, Level, 
00371                                                       TrackMaxima[im], base::t[Level]);
00372         forall (base::Work(),Time,Level,c)
00373           Coords ss(base::Work()(Time,Level,c).bbox().stepsize());
00374           BBox bbi(base::Work()(Time,Level,c).bbox());
00375           bbi.upper(0) -= bbi.stepsize(0);
00376           BeginFastIndex2(V, Work()(Time,Level,c).bbox(), 
00377                           Work()(Time,Level,c).data(), DataType);
00378           DCoords dx = base::GH().worldStep(ss);
00379           bbi = base::U().interiorbbox(Time,Level,c);
00380           for_2 (i, j, bbi, ss)
00381             int jj = (j-wholebb.lower(1))/ss(1);
00382             if (FastIndex2(V,i,j)>front_data[fds*jj]) {
00383               front_data[fds*jj] = FastIndex2(V,i,j);
00384               DCoords fc = base::GH().worldCoords(Coords(2,i,j),ss);
00385               front_data[fds*jj+1] = fc(0)+0.5*dx(0);
00386               front_data[fds*jj+2] = fc(1)+0.5*dx(1);
00387               front_val[jj] = base::U()(Time,Level,c)(i,j);
00388             }
00389           end_for
00390           EndFastIndex2(V);      
00391         end_forall
00392 
00393 #ifdef DAGH_NO_MPI
00394 #else
00395         if (comm_service::dce() && comm_service::proc_num() > 1) {      
00396           int num = comm_service::proc_num();
00397           MPI_Status status;
00398           int R;
00399           int size = sizeof(DataType)*(NEquations()+fds)*idxl;
00400           int tag = 10000;
00401           if (MY_PROC!=VizServer) {
00402             R = MPI_Send((void *)front_data, size, MPI_BYTE, VizServer, tag, comm_service::comm());
00403             if ( MPI_SUCCESS != R ) 
00404               comm_service::error_die( "Tick", "MPI_Send", R );
00405           }
00406           else 
00407             for (int proc=0; proc<num; proc++) {
00408               if (proc==VizServer) continue;
00409               DataType* dat = new DataType[(NEquations()+fds)*idxl];
00410               VectorType* datv = (VectorType *)(dat+fds*idxl);
00411               R = MPI_Recv((void *)dat, size, MPI_BYTE, proc, tag, comm_service::comm(), &status);
00412               if ( MPI_SUCCESS != R ) 
00413                 comm_service::error_die( "Tick", "MPI_Recv", R );
00414               for (register int j=0; j<idxl; j++) 
00415                 if (dat[fds*j] > front_data[fds*j]) {
00416                   for (register int i=0;i<fds; i++) 
00417                     front_data[fds*j+i] = dat[fds*j+i];
00418                   front_val[j] = datv[j];
00419                 }
00420               delete [] dat;
00421             }
00422         }
00423 #endif
00424 
00425         int me = MY_PROC; 
00426         if (me == VizServer) {
00427           DataType* output_data = new DataType[_FileOutput->Ncnt()*idxl];
00428           BBox bb(2,0,0,idxl-1,0,1,1);
00429           vec_grid_data_type val(bb,front_val);
00430           for (int cnt=1;cnt<=_FileOutput->Ncnt(); cnt++) {
00431             if (_FileOutput->OutputName(cnt-1).c_str()[0] == '-') continue;
00432             grid_data_type output(bb,output_data+(cnt-1)*idxl);
00433             ((output_type::out_2_func_type) (((output_type*) base::_FileOutput)->GetOutFunc()))
00434               (FA(2,val),FA(2,output),BOUNDING_BOX(bb),base::NEquations(),cnt,base::t[Level]);
00435             DataType* dummy;
00436             output.deallocate(dummy);
00437           }
00438           std::ofstream outfile;
00439           std::ostream* out;
00440           char name[256];
00441           if (TrackOutputSingleFile) 
00442             sprintf(name,"max_%d.txt",TrackMaxima[im]);
00443           else 
00444             sprintf(name,"max_%d_%d.txt",TrackMaxima[im],Time);
00445           std::string fname = name;
00446           outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00447           out = new std::ostream(outfile.rdbuf());
00448           if (TrackOutputSingleFile)        
00449             *out << "**********   t=" << base::t[Level] << "   Step:" 
00450                  << Time << "   **********" << std::endl;
00451           for (register int j=0;j<idxl; j++) {
00452           *out << front_data[fds*j+1] << " " << front_data[fds*j+2];
00453           for (int cnt=0;cnt<_FileOutput->Ncnt(); cnt++) 
00454             if (_FileOutput->OutputName(cnt).c_str()[0] != '-') 
00455               *out << " " << output_data[cnt*idxl+j];
00456           *out << std::endl;
00457           }
00458           val.deallocate(front_val);
00459           delete [] output_data;
00460           outfile.close();
00461           delete out;      
00462         }
00463         delete [] front_data;
00464       }
00465 
00466     return cfl;
00467   }
00468 
00469 protected:
00470   int MaxType, TrackLevel, TrackOutputEvery, TrackOutputSingleFile;
00471   int TrackMaxima[GLOBALMAXIMA];
00472   double TrackMin, TrackMax;
00473   accumulation_type* _Accumulation;
00474   ControlDevice TrackCtrl;