vtf-logo

clawpack/applications/euler/3d/Spheres/src/Problem.h

00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2007 California Institute of Technology
00004 // Ralf Deiterding, ralf@amroc.net
00005 // Stuart Laurence
00006 
00007 #ifndef AMROC_PROBLEM_H
00008 #define AMROC_PROBLEM_H
00009 
00010 #include <cmath>
00011 #include "euler3.h"
00012 #include "ClpProblem.h"
00013 
00014 #define f_combl_read FORTRAN_NAME(cblread, CBLREAD)
00015 
00016 extern "C" {
00017   void f_combl_read(INTEGER& NSph, DOUBLE xm[], DOUBLE rd[], INTEGER Np[]); 
00018 }
00019 
00020 #define OWN_GFMAMRSOLVER
00021 #include "ClpStdGFMProblem.h"
00022 #include "AMRGFMInterpolation.h"
00023 
00024 class SolverSpecific : 
00025   public AMRGFMSolver<VectorType,FixupType,FlagType,DIM> {
00026   typedef VectorType::InternalDataType DataType;
00027   typedef AMRGFMSolver<VectorType,FixupType,FlagType,DIM> base;
00028   typedef AMRGFMInterpolation<VectorType,FixupType,FlagType,DIM> interpolation_type;
00029   typedef interpolation_type::point_type point_type;
00030   typedef F77GFMFileOutput<VectorType,FixupType,FlagType,DIM> output_type;
00031 public:
00032   SolverSpecific(IntegratorSpecific& integ, 
00033                  base::initial_condition_type& init,
00034                  base::boundary_conditions_type& bc) : base(integ, init, bc), OutputDragEvery(1) {
00035     SetLevelTransfer(new F77LevelTransfer<VectorType,DIM>(f_prolong, f_restrict));
00036 #ifdef f_flgout
00037     SetFileOutput(new F77GFMFileOutput<VectorType,FixupType,FlagType,DIM>(*this,f_flgout)); 
00038 #else   
00039     SetFileOutput(new GFMFileOutput<VectorType,FixupType,FlagType,DIM>(*this)); 
00040 #endif
00041     SetFixup(new FixupSpecific(integ));
00042     SetFlagging(new FlaggingSpecific(*this)); 
00043     AddGFM(new GhostFluidMethod<VectorType,DIM>(
00044               new F77GFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans),
00045               new F77GFMLevelSet<DataType,DIM>(f_lset)));
00046     _Interpolation = new interpolation_type(*this);
00047   }  
00048  
00049   ~SolverSpecific() {
00050     DeleteGFM(_GFM[0]);
00051     delete _Flagging;
00052     delete _Fixup;
00053     delete _Interpolation;
00054   }
00055 
00056   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00057     base::register_at(Ctrl,prefix);
00058     RegisterAt(base::LocCtrl,"OutputDragEvery",OutputDragEvery);
00059   } 
00060   virtual void register_at(ControlDevice& Ctrl) {
00061     base::register_at(Ctrl);
00062   }
00063 
00064   virtual void SetupData() {
00065     base::SetupData();
00066     _Interpolation->SetupData(base::PGH(), base::NGhosts());
00067     if (OutputDragEvery<=0) OutputDragEvery=1;
00068   }
00069 
00070   // Overloading of Tick() to evaluate force integral on spheres after each
00071   // level 0 time step.
00072 
00073   virtual double Tick(int VariableTimeStepping, const double dtv[], 
00074                       const double cflv[], int& Rejections) {
00075 
00076     double cfl = base::Tick(VariableTimeStepping, dtv, cflv, Rejections);
00077 
00078     int TimeZero  = CurrentTime(base::GH(),0);
00079     TimeZero /= RefinedBy(base::GH(),MaxLevel(base::GH()));
00080     if (TimeZero % OutputDragEvery != 0) return cfl;
00081 
00082     int me = MY_PROC; 
00083     double pi = 4.0*std::atan(1.0);
00084     
00085     // Read sphere info from F77 common block
00086     int NSph, Np[5];
00087     double xm[15], rd[5];
00088     point_type sum[5];
00089     f_combl_read(NSph,xm,rd,Np);
00090 
00091     // Calculate pressure
00092     for (register int l=0; l<=FineLevel(base::GH()); l++) {
00093       int Time = CurrentTime(base::GH(),l);
00094       int press_cnt = base::Dim()+4;
00095       ((output_type*) _FileOutput)->Transform(base::U(), base::Work(), Time, l, 
00096                                               press_cnt, base::t[l]);
00097     }
00098 
00099     for (int ns=0; ns<NSph; ns++) {
00100       int Npoints = 8*Np[ns]*Np[ns];
00101       DataType* p = new DataType[Npoints];
00102       point_type* xc = new point_type[Npoints];
00103       point_type* normals = new point_type[Npoints];
00104       DataType* ds = new DataType[Npoints];
00105       DataType* dist = (DataType*) 0;    
00106       double dalpha = 0.5*pi/Np[ns];
00107       double dbeta = 0.5*pi/Np[ns];
00108       register int n = 0;
00109 
00110       // Calculate equidistant points on shere's surfaces
00111       for (register int l=0; l<4*Np[ns]; l++) {
00112         double alpha = dalpha*(l+0.5);
00113         for (register int m=0; m<2*Np[ns]; m++) {
00114           double beta = dalpha*(m+0.5);
00115           xc[n](0) = xm[base::Dim()*ns  ]+rd[ns]*std::cos(alpha)*std::sin(beta); 
00116           xc[n](1) = xm[base::Dim()*ns+1]+rd[ns]*std::sin(alpha)*std::sin(beta);
00117           xc[n](2) = xm[base::Dim()*ns+2]+rd[ns]*std::cos(beta);
00118           ds[n] = pi*rd[ns]*rd[ns]*dbeta*std::sin(beta)/(2.*Np[ns]);
00119           n++;
00120         }
00121       }
00122     
00123       // Interpolate/extrapolate pressure values and assemble results on processor VizServer
00124       _Interpolation->PointsValues(base::Work(),base::t[0],Npoints,xc,p);
00125       _Interpolation->ArrayCombine(VizServer,Npoints,p);
00126 
00127       // Approximate normals and assemble results on processor VizServer
00128       _Interpolation->PointsGeom(base::GFM(0).Phi(),base::t[0],Npoints,xc,normals,dist);
00129       _Interpolation->ArrayCombine(VizServer,base::Dim()*Npoints,normals[0].data());
00130 
00131       // Do the integration on the surface only on processor VizServer
00132       if (me == VizServer) {
00133         sum[ns] = 0.0; 
00134         for (n=0; n<Npoints; n++)
00135           sum[ns] += p[n]*normals[n]*ds[n]; 
00136       }
00137 
00138       delete [] p;
00139       delete [] xc;
00140       delete [] normals;
00141       delete [] ds;
00142     }
00143 
00144     // Append to output file only on processor VizServer
00145     if (me == VizServer) {
00146       std::ofstream outfile;
00147       std::ostream* out;
00148       std::string fname = "drag.dat";
00149       outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00150       out = new std::ostream(outfile.rdbuf());
00151       *out << base::t[0];
00152       for (int ns=0; ns<NSph; ns++)
00153         for (int d=0; d<base::Dim(); d++)
00154           *out << " " << sum[ns](d); 
00155       *out << std::endl;
00156       outfile.close();
00157       delete out;      
00158     }
00159 
00160     return cfl;
00161   } 
00162 
00163 protected:
00164   int OutputDragEvery;
00165   interpolation_type* _Interpolation;