vtf-logo

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