vtf-logo

clawpack/applications/euler/2d/Spheres/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 <cmath>
00010 #include "euler2.h"
00011 #include "ClpProblem.h"
00012 #undef NAUX
00013 #define NAUX 4
00014 
00015 #define f_combl_read FORTRAN_NAME(cblread, CBLREAD)
00016 
00017 extern "C" {
00018   void f_combl_read(INTEGER& NSph, DOUBLE xm[], DOUBLE rd[], INTEGER Np[]); 
00019 }
00020 
00021 #define OWN_FLAGGING
00022 #define OWN_GFMAMRSOLVER
00023 #include "ClpStdGFMProblem.h"
00024 #include "AMRGFMInterpolation.h"
00025 
00026 class FlaggingSpecific : 
00027   public AMRFlagging<VectorType,FixupType,FlagType,DIM> {
00028   typedef AMRFlagging<VectorType,FixupType,FlagType,DIM> base;
00029 public:
00030   FlaggingSpecific(base::solver_type& solver) : base(solver), _MaxLev(10000), _LastTime(10000.0) {
00031       base::AddCriterion(new ByValue<VectorType,FlagType,DIM>());
00032       base::AddCriterion(new ScaledGradient<VectorType,FlagType,DIM>());
00033       base::AddCriterion(new LimiterType<VectorType,FlagType,DIM>());
00034       base::AddCriterion(new AbsoluteError<VectorType,FixupType,FlagType,DIM>(solver));
00035       base::AddCriterion(new RelativeError<VectorType,FixupType,FlagType,DIM>(solver));
00036 #ifdef f_flgout
00037       base::AddCriterion(new F77ByValue<VectorType,FlagType,DIM>(f_flgout));
00038       base::AddCriterion(new F77ScaledGradient<VectorType,FlagType,DIM>(f_flgout));
00039       base::AddCriterion(new F77LimiterType<VectorType,FlagType,DIM>(f_flgout));
00040       base::AddCriterion(new F77AbsoluteError<VectorType,FixupType,FlagType,DIM>(solver,f_flgout));
00041       base::AddCriterion(new F77RelativeError<VectorType,FixupType,FlagType,DIM>(solver,f_flgout));
00042 #endif
00043     }
00044 
00045   ~FlaggingSpecific() { DeleteAllCriterions(); }
00046 
00047   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00048     base::register_at(Ctrl, prefix);
00049     RegisterAt(base::LocCtrl,"MaxLev",_MaxLev);    
00050     RegisterAt(base::LocCtrl,"LastTime",_LastTime);    
00051   }
00052   virtual void register_at(ControlDevice& Ctrl) { register_at(Ctrl, ""); }
00053 
00054   virtual void SetFlags(const int Time, const int Level, double t, double dt) {
00055     if (t>_LastTime || Level<=_MaxLev) 
00056        base::SetFlags(Time, Level, t,dt);
00057     else {
00058       forall (base::Flags(),Time,Level,c)  
00059         base::Flags()(Time,Level,c) = GoodPoint;
00060       end_forall
00061     }
00062   }
00063 
00064 protected:
00065   int _MaxLev;
00066   double _LastTime;
00067 };
00068 
00069 
00070 class SolverSpecific : 
00071   public AMRGFMSolver<VectorType,FixupType,FlagType,DIM> {
00072   typedef VectorType::InternalDataType DataType;
00073   typedef AMRGFMSolver<VectorType,FixupType,FlagType,DIM> base;
00074   typedef AMRGFMInterpolation<VectorType,FixupType,FlagType,DIM> interpolation_type;
00075   typedef interpolation_type::point_type point_type;
00076   typedef F77GFMFileOutput<VectorType,FixupType,FlagType,DIM> output_type;
00077 public:
00078   SolverSpecific(IntegratorSpecific& integ, 
00079                  base::initial_condition_type& init,
00080                  base::boundary_conditions_type& bc) : base(integ, init, bc), OutputDragEvery(1) {
00081     SetLevelTransfer(new F77LevelTransfer<VectorType,DIM>(f_prolong, f_restrict));
00082 #ifdef f_flgout
00083     SetFileOutput(new F77GFMFileOutput<VectorType,FixupType,FlagType,DIM>(*this,f_flgout)); 
00084 #else   
00085     SetFileOutput(new GFMFileOutput<VectorType,FixupType,FlagType,DIM>(*this)); 
00086 #endif
00087     SetFixup(new FixupSpecific(integ));
00088     SetFlagging(new FlaggingSpecific(*this)); 
00089     AddGFM(new GhostFluidMethod<VectorType,DIM>(
00090               new F77GFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans),
00091               new F77GFMLevelSet<DataType,DIM>(f_lset)));
00092     _Interpolation = new interpolation_type(*this);
00093   }  
00094  
00095   ~SolverSpecific() {
00096     DeleteGFM(_GFM[0]);
00097     delete _Flagging;
00098     delete _Fixup;
00099     delete _Interpolation;
00100   }
00101 
00102   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00103     base::register_at(Ctrl,prefix);
00104     RegisterAt(base::LocCtrl,"OutputDragEvery",OutputDragEvery);
00105   } 
00106   virtual void register_at(ControlDevice& Ctrl) {
00107     base::register_at(Ctrl);
00108   }
00109 
00110   virtual void SetupData() {
00111     base::SetupData();
00112     _Interpolation->SetupData(base::PGH(), base::NGhosts());
00113   }
00114 
00115   // Overloading of Tick() to evaluate force integral on spheres after each
00116   // level 0 time step.
00117 
00118   virtual double Tick(int VariableTimeStepping, const double dtv[], 
00119                       const double cflv[], int& Rejections) {
00120 
00121     double cfl = base::Tick(VariableTimeStepping, dtv, cflv, Rejections);
00122 
00123     int TimeZero  = CurrentTime(base::GH(),0);
00124     TimeZero /= RefinedBy(base::GH(),MaxLevel(base::GH()));
00125     if (TimeZero % OutputDragEvery != 0) return cfl;
00126 
00127     int me = MY_PROC; 
00128     double pi = 4.0*std::atan(1.0);
00129     
00130     // Read sphere info from F77 common block
00131     int NSph, Np[5];
00132     double xm[10], rd[5];
00133     point_type sum[5];
00134     f_combl_read(NSph,xm,rd,Np);
00135 
00136     // Calculate pressure
00137     for (register int l=0; l<=FineLevel(base::GH()); l++) {
00138       int Time = CurrentTime(base::GH(),l);
00139       int press_cnt = base::Dim()+4;      
00140       ((output_type*) _FileOutput)->Transform(base::U(), base::Work(), Time, l, 
00141                                               press_cnt, base::t[l]);
00142     }
00143 
00144     for (int ns=0; ns<NSph; ns++) {
00145       int Npoints = 4*Np[ns];
00146       DataType* p = new DataType[Npoints];
00147       point_type* xc = new point_type[Npoints];
00148       point_type* normals = new point_type[Npoints];
00149       DataType* dist = (DataType*) 0;    
00150       double dalpha = 0.5*pi/Np[ns];
00151 
00152       register int n;
00153 
00154       // Calculate equidistant points on shere's surfaces
00155       for (n=0; n<Npoints; n++) {
00156         double alpha = dalpha*(n+0.5);
00157         xc[n](0) = xm[base::Dim()*ns  ]+rd[ns]*std::cos(alpha); 
00158         xc[n](1) = xm[base::Dim()*ns+1]+rd[ns]*std::sin(alpha);
00159       }
00160     
00161       // Interpolate/extrapolate pressure values and assemble results on processor VizServer
00162       _Interpolation->PointsValues(base::Work(),base::t[0],Npoints,xc,p);
00163       _Interpolation->ArrayCombine(VizServer,Npoints,p);
00164 
00165       // Approximate normals and assemble results on processor VizServer
00166       _Interpolation->PointsGeom(base::GFM(0).Phi(),base::t[0],Npoints,xc,normals,dist);
00167       _Interpolation->ArrayCombine(VizServer,base::Dim()*Npoints,normals[0].data());
00168 
00169       // Do the integration on the surface only on processor VizServer
00170       if (me == VizServer) {
00171         sum[ns] = 0.0;
00172         double ds = 2.*pi*rd[ns]/Npoints; 
00173         for (n=0; n<Npoints; n++)
00174           sum[ns] += p[n]*normals[n]*ds; 
00175       }
00176 
00177       delete [] p;
00178       delete [] xc;
00179       delete [] normals;
00180     }
00181 
00182     // Append to output file only on processor VizServer
00183     if (me == VizServer) {
00184       std::ofstream outfile;
00185       std::ostream* out;
00186       std::string fname = "drag.dat";
00187       outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00188       out = new std::ostream(outfile.rdbuf());
00189       *out << base::t[0];
00190       for (int ns=0; ns<NSph; ns++)
00191         for (int d=0; d<base::Dim(); d++)
00192           *out << " " << sum[ns](d); 
00193       *out << std::endl;
00194       outfile.close();
00195       delete out;      
00196     }
00197 
00198     return cfl;
00199   } 
00200 
00201 protected:
00202   int OutputDragEvery;
00203   interpolation_type* _Interpolation;