vtf-logo

clawpack/applications/eulerm/2d/WaterShockTube/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 "eulerm2.h"
00010 
00011 #undef  NAUX
00012 #define NAUX       1
00013 
00014 #include "ClpProblem.h"
00015 
00016 #define f_combl_read FORTRAN_NAME(cblread, CBLREAD)
00017 #define f_combl_write FORTRAN_NAME(cblwrite, CBLWRITE)
00018 #define f_ipvel FORTRAN_NAME(ipvel, IPVEL)
00019 
00020 extern "C" {
00021   void f_combl_read(DOUBLE xm[], DOUBLE vm[], DOUBLE& cm, DOUBLE& rd, INTEGER& Np); 
00022   void f_combl_write(DOUBLE xm[], DOUBLE vm[], DOUBLE& cm, DOUBLE& rd, INTEGER& Np); 
00023   void f_ipvel(); 
00024 }
00025 
00026 #define OUTPUTPOINTSMAX  20
00027 #define OWN_GFMAMRSOLVER
00028 #include "ClpStdGFMProblem.h"
00029 #include "AMRGFMInterpolation.h"
00030 
00031 class SolverSpecific : 
00032   public AMRGFMSolver<VectorType,FixupType,FlagType,DIM> {
00033   typedef VectorType::InternalDataType DataType;
00034   typedef AMRGFMSolver<VectorType,FixupType,FlagType,DIM> base;
00035   typedef AMRGFMInterpolation<VectorType,FixupType,FlagType,DIM> interpolation_type;
00036   typedef interpolation_type::point_type point_type;
00037   typedef F77GFMFileOutput<VectorType,FixupType,FlagType,DIM> output_type;
00038   typedef GhostFluidMethod<VectorType,DIM>::boundary_conditions_type gfm_bc_type;
00039 public:
00040   typedef base::vec_grid_data_type vec_grid_data_type;  
00041 
00042   SolverSpecific(IntegratorSpecific& integ, 
00043                  base::initial_condition_type& init,
00044                  base::boundary_conditions_type& bc) : base(integ, init, bc), OutputEvery(0), Nxc(0) {
00045     SetLevelTransfer(new F77LevelTransfer<VectorType,DIM>(f_prolong, f_restrict));
00046 #ifdef f_flgout
00047     SetFileOutput(new F77GFMFileOutput<VectorType,FixupType,FlagType,DIM>(*this,f_flgout)); 
00048 #else   
00049     SetFileOutput(new GFMFileOutput<VectorType,FixupType,FlagType,DIM>(*this)); 
00050 #endif
00051     SetFixup(new FixupSpecific(integ));
00052     SetFlagging(new FlaggingSpecific(*this)); 
00053     AddGFM(new GhostFluidMethod<VectorType,DIM>(
00054               new F77GFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans,f_ipvel),
00055               new F77GFMLevelSet<DataType,DIM>(f_lset),
00056               (gfm_bc_type*)(new F77BoundaryConditions<Vector<DataType,1>,DIM>(f_boundary))));
00057     _Interpolation = new interpolation_type(*this);
00058   }  
00059  
00060   ~SolverSpecific() {
00061     delete _GFM[0]->GetBoundaryConditionsP();
00062     DeleteGFM(_GFM[0]);
00063     delete _Flagging;
00064     delete _Fixup;
00065     delete _Interpolation;
00066   }
00067 
00068   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00069     base::register_at(Ctrl,prefix);
00070     SensorsCtrl = base::LocCtrl.getSubDevice("SensorsOutput");
00071     RegisterAt(SensorsCtrl,"OutputEvery",OutputEvery);
00072     RegisterAt(SensorsCtrl,"NSensors",Nxc);
00073     char VariableName[32];
00074     for (register int i=0; i<OUTPUTPOINTSMAX; i++) 
00075       for (register int d=0; d<base::Dim(); d++) {
00076         std::sprintf(VariableName,"xc(%d,%d)",i+1,d+1);
00077         RegisterAt(SensorsCtrl,VariableName,xc[i](d));
00078       }
00079   } 
00080   virtual void register_at(ControlDevice& Ctrl) {
00081     base::register_at(Ctrl);
00082   }
00083 
00084   virtual void SetupData() {
00085     base::SetupData();
00086     _GFM[0]->BoundaryConditions_().SetupData(base::PGH(), base::NGhosts());
00087     _Interpolation->SetupData(base::PGH(), base::NGhosts());
00088     if (OutputEvery<0) OutputEvery=0;
00089     if (Nxc<0) Nxc=0;
00090     if (Nxc>OUTPUTPOINTSMAX) Nxc=OUTPUTPOINTSMAX;
00091   }
00092 
00093   // Overloading of Advance() to add pointwise output after each level 0 time step
00094   virtual void Advance(double& t, double& dt) {
00095 
00096     int me = MY_PROC; 
00097     point_type force_old;
00098     double t_old = t;
00099     CalculateForce(force_old);
00100 
00101     base::Advance(t,dt);
00102 
00103     point_type a, force_new;
00104     CalculateForce(force_new);
00105     
00106     int Np;
00107     double xm[2], vm[2], cm, rd;
00108     f_combl_read(xm,vm,cm,rd,Np);
00109 
00110     a = 0.5/cm*(force_old+force_new);
00111     vm[0] += a(0)*dt;
00112     vm[1] += a(1)*dt;
00113     xm[0] += vm[0]*dt;
00114     xm[1] += vm[1]*dt;
00115 
00116     f_combl_write(xm,vm,cm,rd,Np);
00117     
00118     // Append to output file only on processor VizServer
00119     if (me == VizServer) {
00120       std::ofstream outfile;
00121       std::ostream* out;
00122       std::string fname = "boundary.txt";
00123       outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00124       out = new std::ostream(outfile.rdbuf());
00125       *out << t;
00126       int d;
00127       for (d=0; d<base::Dim(); d++)
00128         *out << " " << force_new(d); 
00129       for (d=0; d<base::Dim(); d++)
00130         *out << " " << xm[d]; 
00131       for (d=0; d<base::Dim(); d++)
00132         *out << " " << vm[d]; 
00133       *out << std::endl;
00134       outfile.close();
00135       delete out;      
00136     }
00137 
00138     if (!OutputEvery) return;
00139 
00140     int TimeZero  = CurrentTime(base::GH(),0);
00141     TimeZero /= RefinedBy(base::GH(),MaxLevel(base::GH()));
00142     if (TimeZero % OutputEvery != 0) return;
00143 
00144     VectorType* dat = new VectorType[Nxc];
00145 
00146     // Interpolate/extrapolate pressure values and assemble results on processor VizServer
00147     _Interpolation->PointsValues(base::U(),t,Nxc,xc,dat);
00148     int NValues = Nxc*base::NEquations();
00149     _Interpolation->ArrayCombine(VizServer,NValues,&(dat[0](0)));
00150 
00151     // Append to output file only on processor VizServer
00152     if (MY_PROC == VizServer) {
00153       DataType* output_data = new DataType[_FileOutput->Ncnt()*Nxc];
00154       BBox bb(2,0,0,Nxc-1,0,1,1);
00155       vec_grid_data_type val(bb,dat);
00156       for (int cnt=1;cnt<=_FileOutput->Ncnt(); cnt++) {
00157         if (_FileOutput->OutputName(cnt-1).c_str()[0] == '-') continue;
00158         grid_data_type output(bb,output_data+(cnt-1)*Nxc);
00159         ((output_type::out_2_func_type) (((output_type*) base::_FileOutput)->GetOutFunc()))
00160           (FA(2,val),FA(2,output),BOUNDING_BOX(bb),base::NEquations(),cnt,t);
00161         DataType* dummy;
00162         output.deallocate(dummy);
00163       }
00164       VectorType* dummy;
00165       val.deallocate(dummy);
00166       std::ofstream outfile;
00167       std::ostream* out;
00168       std::string fname = "sensors.txt";
00169       outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00170       out = new std::ostream(outfile.rdbuf());
00171       *out << t << " ";
00172       for (register int j=0;j<Nxc; j++)
00173         for (int cnt=0;cnt<_FileOutput->Ncnt(); cnt++) 
00174           if (_FileOutput->OutputName(cnt).c_str()[0] != '-') 
00175             *out << " " << output_data[cnt*Nxc+j];
00176       *out << std::endl;
00177       delete [] output_data;
00178       outfile.close();
00179       delete out;      
00180     }
00181     delete [] dat;
00182   } 
00183 
00184   void CalculateForce(point_type& sum) {
00185     int me = MY_PROC; 
00186 
00187     double pi = 4.0*std::atan(1.0);
00188     
00189     // Read sphere info from F77 common block
00190     int Np;
00191     double xm[2], vm[2], cm, rd;
00192     f_combl_read(xm,vm,cm,rd,Np);
00193 
00194     // Calculate pressure
00195     for (register int l=0; l<=FineLevel(base::GH()); l++) {
00196       int Time = CurrentTime(base::GH(),l);
00197       int press_cnt = base::Dim()+4;      
00198       ((output_type*) _FileOutput)->Transform(base::U(), base::Work(), Time, l, 
00199                                               press_cnt, base::t[l]);
00200     }
00201 
00202     DataType* p = new DataType[Np];
00203     point_type* xc = new point_type[Np];
00204 
00205     register int n;
00206 
00207     for (n=0; n<Np; n++) {
00208       xc[n](0) = xm[0]; 
00209       xc[n](1) = xm[1]+(2.*n/Np-1.)*rd;
00210     }
00211     
00212     // Interpolate/extrapolate pressure values and assemble results on processor VizServer
00213     _Interpolation->PointsValues(base::Work(),base::t[0],Np,xc,p);
00214     _Interpolation->ArrayCombine(VizServer,Np,p);
00215 
00216     // Do the integration on the surface only on processor VizServer
00217     if (me == VizServer) {
00218       sum = 0.;
00219       int c=0;
00220       for (n=0; n<Np; n++)
00221         if (p[n]>-1.e37) {
00222           sum(0) += p[n]; c++;
00223         }
00224       sum(0) /= c;
00225       sum(0) -= 101325.;
00226       sum(0) *= pi*rd*rd;
00227 
00228       delete [] p;
00229       delete [] xc;
00230     }
00231 
00232 #ifdef DAGH_NO_MPI
00233 #else
00234     if (comm_service::dce() && comm_service::proc_num() > 1) {  
00235       int num = comm_service::proc_num();
00236       MPI_Status status;
00237       int R;
00238       int size = sizeof(DataType);
00239       int tag = 10001;
00240       if (me == VizServer) 
00241         for (int proc=0; proc<num; proc++) {
00242           if (proc==VizServer) continue;
00243           R = MPI_Send((void *)&sum, size, MPI_BYTE, proc, tag, comm_service::comm());
00244           if ( MPI_SUCCESS != R ) 
00245             comm_service::error_die( "SumCombine", "MPI_Send", R );
00246         }
00247       else {
00248         R = MPI_Recv((void *)&sum, size, MPI_BYTE, VizServer, tag, comm_service::comm(), &status);
00249         if ( MPI_SUCCESS != R ) 
00250           comm_service::error_die( "ArrayCombine", "MPI_Recv", R );
00251       }
00252     }
00253 #endif
00254   }
00255 
00256 protected:
00257   int OutputEvery, Nxc;
00258   point_type xc[OUTPUTPOINTSMAX];
00259   interpolation_type* _Interpolation;