vtf-logo

fsi/sfc-amroc/WaterBlastFracture/src/FluidProblem.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // Copyright (C) 2003-2007 California Institute of Technology
00004 // Ralf Deiterding, ralf@amroc.net
00005 
00006 #ifndef AMROC_FLUIDPROBLEM_H
00007 #define AMROC_FLUIDPROBLEM_H
00008 
00009 #include "eulerm3.h"
00010 
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_piston FORTRAN_NAME(ipvelpiston, IPVELPISTON)
00016 #define f_lset_piston FORTRAN_NAME(lspiston, LSPISTON)
00017 
00018 extern "C" {
00019   void f_combl_read(DOUBLE& xm, DOUBLE& vm, DOUBLE& cm, DOUBLE& rd, INTEGER& Np); 
00020   void f_combl_write(DOUBLE& xm, DOUBLE& vm, DOUBLE& cm, DOUBLE& rd, INTEGER& Np); 
00021   void f_ipvel_piston(); 
00022   void f_lset_piston(); 
00023 }
00024 
00025 #define MaxDPoints (10)
00026 #define OUTPUTPOINTSMAX  20
00027 
00028 #define OWN_FLAGGING
00029 #define OWN_ELCGFMAMRSOLVER
00030 #include "ClpStdELCGFMProblem.h" 
00031 #include "AMRGFMInterpolation.h"
00032 
00033 
00034 class FlaggingSpecific : 
00035   public AMRFlagging<VectorType,FixupType,FlagType,DIM> {
00036   typedef AMRFlagging<VectorType,FixupType,FlagType,DIM> base;
00037 public:
00038   FlaggingSpecific(base::solver_type& solver) : base(solver) {
00039       base::AddCriterion(new ByValue<VectorType,FlagType,DIM>());
00040       base::AddCriterion(new ScaledGradient<VectorType,FlagType,DIM>());
00041       base::AddCriterion(new LimiterType<VectorType,FlagType,DIM>());
00042       base::AddCriterion(new AbsoluteError<VectorType,FixupType,FlagType,DIM>(solver));
00043       base::AddCriterion(new RelativeError<VectorType,FixupType,FlagType,DIM>(solver));
00044 #ifdef f_flgout
00045       base::AddCriterion(new F77ByValue<VectorType,FlagType,DIM>(f_flgout));
00046       base::AddCriterion(new F77ScaledGradient<VectorType,FlagType,DIM>(f_flgout));
00047       base::AddCriterion(new F77LimiterType<VectorType,FlagType,DIM>(f_flgout));
00048       base::AddCriterion(new F77AbsoluteError<VectorType,FixupType,FlagType,DIM>(solver,f_flgout));
00049       base::AddCriterion(new F77RelativeError<VectorType,FixupType,FlagType,DIM>(solver,f_flgout));
00050 #endif
00051       dcmin = new int[MaxDPoints*base::Dim()];
00052       dcmax = new int[MaxDPoints*base::Dim()];
00053       dclev = new int[MaxDPoints];
00054       for (int d=0; d<MaxDPoints*base::Dim(); d++) {
00055         dcmin[d] = 0; dcmax[d] = -1;
00056       }
00057       for (int i=0; i<MaxDPoints; i++)
00058         dclev[i] = 1000000;
00059     }
00060 
00061   ~FlaggingSpecific() { 
00062     DeleteAllCriterions(); 
00063     delete [] dcmin;
00064     delete [] dcmax;
00065   }
00066 
00067   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00068     base::register_at(Ctrl, prefix);
00069     char VariableName[32];
00070     for (int i=0; i<MaxDPoints; i++) {
00071       for (int d=0; d<base::Dim(); d++) {
00072         sprintf(VariableName,"DCellsMin(%d,%d)",i+1,d+1);
00073         RegisterAt(base::LocCtrl,VariableName,dcmin[i*base::Dim()+d]);
00074         sprintf(VariableName,"DCellsMax(%d,%d)",i+1,d+1);
00075         RegisterAt(base::LocCtrl,VariableName,dcmax[i*base::Dim()+d]);
00076       }
00077       sprintf(VariableName,"DMinLevel(%d)",i+1);
00078       RegisterAt(base::LocCtrl,VariableName,dclev[i]);
00079     }
00080   }
00081   virtual void register_at(ControlDevice& Ctrl) {
00082     register_at(Ctrl, "");
00083   }
00084 
00085   virtual void SetFlags(const int Time, const int Level, double t, double dt) {
00086     base::SetFlags(Time, Level, t, dt);
00087     for (int i=0; i<MaxDPoints; i++) 
00088       if (Level>=dclev[i]) {
00089         Coords lb(base::Dim(), dcmin+i*base::Dim()), ub(base::Dim(), dcmax+i*base::Dim()), 
00090                   s(base::Dim(),1);
00091         BBox bbox(lb*RefinedBy(base::GH(),MaxLevel(base::GH())),
00092                   ub*RefinedBy(base::GH(),MaxLevel(base::GH())),
00093                   s*StepSize(base::GH(),Level));
00094         forall (base::Flags(),Time,Level,c)  
00095           base::Flags()(Time,Level,c).equals(GoodPoint, bbox);
00096         end_forall    
00097       }
00098   }
00099 
00100 private:
00101   int *dcmin, *dcmax, *dclev;
00102 };
00103 
00104 
00105 template <class DataType, int dim>
00106 class F77CPTLevelSet : public CPTLevelSet<DataType,dim> {
00107   typedef CPTLevelSet<DataType,dim> base;
00108 public:
00109   typedef typename base::grid_fct_type grid_fct_type;  
00110   typedef typename base::grid_data_type grid_data_type;
00111   typedef generic_fortran_func generic_func_type; 
00112 
00113   typedef void (*lset_3_func_type) ( const INTEGER& maxmx, const INTEGER& maxmy, const INTEGER& maxmz,
00114                                      const INTEGER& mbc,
00115                                      const INTEGER& mx, const INTEGER& my, const INTEGER& mz,
00116                                      const DOUBLE x[], const DOUBLE y[], const DOUBLE z[],
00117                                      const DOUBLE& dx, const DOUBLE& dy, const DOUBLE& dz, 
00118                                      DataType q[], const DOUBLE& t);
00119 
00120   F77CPTLevelSet() : base(), f_lset(0) {}
00121   F77CPTLevelSet(generic_func_type lset) : base(), f_lset(lset) {}
00122 
00123   virtual void SetPhi(grid_fct_type& phi, const int Time, const int Level, double t) { 
00124     base::SetPhi(phi,Time,Level,t);
00125     forall (phi,Time,Level,c)
00126       SetGrid(phi(Time,Level,c),Level,t);    
00127     end_forall
00128   }
00129 
00130   virtual void SetGrid(grid_data_type& gdphi, const int& level, const double& t) {   
00131     assert(f_lset != (generic_func_type) 0);
00132     Coords ex = gdphi.extents();
00133     DCoords lbcorner = base::GH().worldCoords(gdphi.lower(), gdphi.stepsize());
00134     DCoords dx = base::GH().worldStep(gdphi.stepsize());
00135     int maxm[3], mx[3], d;
00136     DataType* x[3];
00137     for (d=0; d<dim; d++) {
00138       maxm[d] = ex(d);
00139       mx[d] = ex(d)-2*base::NGhosts();
00140       x[d] = new DataType[maxm[d]];
00141       for (int i=0; i<maxm[d]; i++) x[d][i] = (i+0.5)*dx(d)+lbcorner(d);
00142     }
00143 
00144     ((lset_3_func_type) f_lset)(AA(3,mx), base::NGhosts(), AA(3,mx), 
00145                                 AA(3,x), AA(3,dx), gdphi.data(), t);
00146 
00147     for (d=0; d<dim; d++) 
00148       delete [] x[d];
00149   }
00150 
00151   inline void SetFunc(generic_func_type lset) { f_lset = lset; }
00152   generic_func_type GetFunc() const { return f_lset; }
00153 
00154 protected:
00155   generic_func_type f_lset;
00156 };
00157 
00158 
00159 class FluidSolverSpecific : 
00160   public AMRELCGFMSolver<VectorType,FixupType,FlagType,DIM> {
00161   typedef VectorType::InternalDataType DataType;
00162   typedef AMRELCGFMSolver<VectorType,FixupType,FlagType,DIM> base;
00163   typedef AMRGFMInterpolation<VectorType,FixupType,FlagType,DIM> interpolation_type;
00164 public:
00165   typedef F77GFMFileOutput<VectorType,FixupType,FlagType,DIM> output_type;
00166   typedef base::point_type point_type;
00167   typedef base::eul_comm_type eul_comm_type;
00168 
00169   FluidSolverSpecific() : base(_IntegratorSpecific, _InitialConditionSpecific, 
00170                                _BoundaryConditionsSpecific) {
00171     SetLevelTransfer(new F77LevelTransfer<VectorType,DIM>(f_prolong, f_restrict));
00172     SetFileOutput(new output_type(*this,f_flgout)); 
00173     SetFixup(new FixupSpecific(_IntegratorSpecific));
00174     SetFlagging(new FlaggingSpecific(*this)); 
00175     AddGFM(new GhostFluidMethod<VectorType,DIM>(
00176               new F77ELCGFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans,*this),
00177               new CPTLevelSet<DataType,DIM>()));
00178     AddGFM(new GhostFluidMethod<VectorType,DIM>(
00179               new F77GFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans),
00180               new F77GFMLevelSet<DataType,DIM>(f_lset)));
00181     AddGFM(new GhostFluidMethod<VectorType,DIM>(
00182               new F77GFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans,f_ipvel_piston),
00183               new F77GFMLevelSet<DataType,DIM>(f_lset_piston)));
00184     SetCoupleGFM(0);
00185     _Interpolation = new interpolation_type(*this);
00186   }  
00187  
00188   ~FluidSolverSpecific() {
00189     DeleteGFM(_GFM[2]);
00190     DeleteGFM(_GFM[1]);
00191     DeleteGFM(_GFM[0]);
00192     delete _Flagging;
00193     delete _Fixup;
00194     delete _Interpolation;
00195   }
00196 
00197   virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00198     base::register_at(Ctrl,prefix);
00199     SensorsCtrl = base::LocCtrl.getSubDevice("SensorsOutput");
00200     RegisterAt(SensorsCtrl,"OutputEvery",OutputEvery);
00201     RegisterAt(SensorsCtrl,"NSensors",Nxc);
00202     char VariableName[32];
00203     for (register int i=0; i<OUTPUTPOINTSMAX; i++) 
00204       for (register int d=0; d<base::Dim(); d++) {
00205         std::sprintf(VariableName,"xc(%d,%d)",i+1,d+1);
00206         RegisterAt(SensorsCtrl,VariableName,xc[i](d));
00207       }
00208   } 
00209   virtual void register_at(ControlDevice& Ctrl) {
00210     base::register_at(Ctrl);
00211   }
00212 
00213   virtual void SetupData() {
00214     base::SetupData();
00215     _Interpolation->SetupData(base::PGH(), base::NGhosts());
00216     if (OutputEvery<0) OutputEvery=0;
00217     if (Nxc<0) Nxc=0;
00218     if (Nxc>OUTPUTPOINTSMAX) Nxc=OUTPUTPOINTSMAX;
00219   }
00220 
00221   virtual void Restart(double& t, double& dt) {
00222     std::ifstream ifs("boundary.cp", std::ios::in);
00223     int Np;
00224     double xm, vm, cm, rd;
00225     f_combl_read(xm,vm,cm,rd,Np);
00226     ifs >> xm >> vm;
00227     ifs.close();
00228     f_combl_write(xm,vm,cm,rd,Np);
00229     base::Restart(t,dt);
00230   }
00231   virtual void Checkpointing() {
00232     int me = MY_PROC; 
00233     if (me == VizServer) {
00234       int Np;
00235       double xm, vm, cm, rd;
00236       f_combl_read(xm,vm,cm,rd,Np);
00237       std::ofstream ofs("boundary.cp", std::ios::out);
00238       ofs << xm << " " << vm << std::endl; 
00239       ofs.close();
00240     }
00241     base::Checkpointing();
00242   }
00243 
00244   virtual void SendBoundaryData() {
00245     START_WATCH
00246       for (register int l=0; l<=FineLevel(base::GH()); l++) 
00247         ((output_type*) _FileOutput)->Transform(base::U(), base::Work(), 
00248                                                 CurrentTime(base::GH(),l), l, 
00249                                                 base::Dim()+4, base::t[l]);
00250     END_WATCH(FLUID_CPL_PRESSURE_CALCULATE)
00251     base::SendBoundaryData();
00252   }
00253 
00254   virtual void ModifyELCSendData(eul_comm_type* eulComm) {
00255     DataType distance = -GFM(CoupleGFM()).Boundary().Cutoff();
00256     int Npoints = _eulComm->getNumberOfFaces();
00257     double *press_data = _eulComm->getPressuresData();
00258     const int* con = _eulComm->getConnectivitiesData();
00259     const point_type *pos = reinterpret_cast<const point_type *>(_eulComm->getPositionsData());
00260     for (register int n=0; n<Npoints; n++) {
00261       bool inside = true;
00262       for (register int d=0; d<base::Dim(); d++) {
00263         const point_type &p = pos[con[base::Dim()*n+d]]; 
00264         if (std::sqrt(p(1)*p(1)+p(2)*p(2))>0.0323) {
00265           inside = false;
00266           break;
00267         }
00268       }
00269       if (!inside) 
00270         press_data[n] = std::numeric_limits<DataType>::max();
00271     }
00272   }
00273   
00274   // Overloading of Advance() to add pointwise output after each level 0 time step
00275   // and propagate piston
00276   virtual void Advance(double& t, double& dt) {
00277 
00278     int me = MY_PROC; 
00279     DataType force_old;
00280     if (base::GFM(2).IsUsed())
00281       CalculateForce(force_old);
00282 
00283     base::Advance(t,dt);
00284 
00285     if (base::GFM(2).IsUsed()) {
00286       DataType a, force_new;
00287       CalculateForce(force_new);
00288       
00289       int Np;
00290       double xm, vm, cm, rd;
00291       f_combl_read(xm,vm,cm,rd,Np);
00292       
00293       a = 0.5/cm*(force_old+force_new);
00294       vm += a*dt;
00295       xm += vm*dt;
00296       
00297       f_combl_write(xm,vm,cm,rd,Np);
00298     
00299       // Append to output file only on processor VizServer
00300       if (me == VizServer) {
00301         std::ofstream outfile;
00302         std::ostream* out;
00303         std::string fname = "boundary.txt";
00304         outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00305         out = new std::ostream(outfile.rdbuf());
00306         *out << t << " " << force_new << " " << xm << " " << vm << std::endl;
00307         outfile.close();
00308         delete out;      
00309       }
00310     }
00311 
00312     if (!OutputEvery) return;
00313 
00314     int TimeZero  = CurrentTime(base::GH(),0);
00315     TimeZero /= RefinedBy(base::GH(),MaxLevel(base::GH()));
00316     if (TimeZero % OutputEvery != 0) return;
00317 
00318     VectorType* dat = new VectorType[Nxc];
00319 
00320     // Interpolate/extrapolate pressure values and assemble results on processor VizServer
00321     _Interpolation->PointsValues(base::U(),t,Nxc,xc,dat);
00322     int NValues = Nxc*base::NEquations();
00323     _Interpolation->ArrayCombine(VizServer,NValues,&(dat[0](0)));
00324 
00325     // Append to output file only on processor VizServer
00326     if (MY_PROC == VizServer) {
00327       DataType* output_data = new DataType[_FileOutput->Ncnt()*Nxc];
00328       BBox bb(3,0,0,0,Nxc-1,0,0,1,1,1);
00329       vec_grid_data_type val(bb,dat);
00330       for (int cnt=1;cnt<=_FileOutput->Ncnt(); cnt++) {
00331         if (_FileOutput->OutputName(cnt-1).c_str()[0] == '-') continue;
00332         grid_data_type output(bb,output_data+(cnt-1)*Nxc);
00333         ((output_type::out_3_func_type) (((output_type*) base::_FileOutput)->GetOutFunc()))
00334           (FA(3,val),FA(3,output),BOUNDING_BOX(bb),base::NEquations(),cnt,t);
00335         DataType* dummy;
00336         output.deallocate(dummy);
00337       }
00338       VectorType* dummy;
00339       val.deallocate(dummy);
00340       std::ofstream outfile;
00341       std::ostream* out;
00342       std::string fname = "sensors.txt";
00343       outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00344       out = new std::ostream(outfile.rdbuf());
00345       *out << t << " ";
00346       for (register int j=0;j<Nxc; j++)
00347         for (int cnt=0;cnt<_FileOutput->Ncnt(); cnt++) 
00348           if (_FileOutput->OutputName(cnt).c_str()[0] != '-') 
00349             *out << " " << output_data[cnt*Nxc+j];
00350       *out << std::endl;
00351       delete [] output_data;
00352       outfile.close();
00353       delete out;      
00354     }
00355     delete [] dat;
00356   } 
00357 
00358   void CalculateForce(DataType& sum) {
00359     int me = MY_PROC; 
00360 
00361     double pi = 4.0*std::atan(1.0);
00362     
00363     // Read sphere info from F77 common block
00364     int Np;
00365     double xm, vm, cm, rd;
00366     f_combl_read(xm,vm,cm,rd,Np);
00367 
00368     // Calculate pressure
00369     for (register int l=0; l<=FineLevel(base::GH()); l++) {
00370       int Time = CurrentTime(base::GH(),l);
00371       int press_cnt = base::Dim()+4;      
00372       ((output_type*) _FileOutput)->Transform(base::U(), base::Work(), Time, l, 
00373                                               press_cnt, base::t[l]);
00374     }
00375 
00376     int Npoints = Np*Np;
00377     DataType* p = new DataType[Npoints];
00378     point_type* xc = new point_type[Npoints];
00379 
00380     register int n;
00381 
00382     for (n=0; n<Np; n++) 
00383       for (register int m=0; m<Np; m++) {
00384         xc[n*Np+m](0) = xm; 
00385         xc[n*Np+m](1) = (2.*n/Np-1.)*rd;
00386         xc[n*Np+m](2) = (2.*m/Np-1.)*rd;
00387       }
00388     
00389     // Interpolate/extrapolate pressure values and assemble results on processor VizServer
00390     _Interpolation->PointsValues(base::Work(),base::t[0],Npoints,xc,p);
00391     _Interpolation->ArrayCombine(VizServer,Npoints,p);
00392 
00393     // Do the integration on the surface only on processor VizServer
00394     if (me == VizServer) {
00395       int vp = 0;
00396       sum = 0.;
00397       for (n=0; n<Npoints; n++)
00398         if (p[n]>-1.e37) {
00399           sum += p[n]; vp++;
00400         }
00401       sum /= vp;
00402       sum -= 101325.;
00403       sum *= pi*rd*rd;
00404 
00405       delete [] p;
00406       delete [] xc;
00407     }
00408 
00409 #ifdef DAGH_NO_MPI
00410 #else
00411     if (comm_service::dce() && comm_service::proc_num() > 1) {  
00412       int num = comm_service::proc_num();
00413       MPI_Status status;
00414       int R;
00415       int size = sizeof(DataType);
00416       int tag = 10001;
00417       if (me == VizServer) 
00418         for (int proc=0; proc<num; proc++) {
00419           if (proc==VizServer) continue;
00420           R = MPI_Send((void *)&sum, size, MPI_BYTE, proc, tag, comm_service::comm());
00421           if ( MPI_SUCCESS != R ) 
00422             comm_service::error_die( "SumCombine", "MPI_Send", R );
00423         }
00424       else {
00425         R = MPI_Recv((void *)&sum, size, MPI_BYTE, VizServer, tag, comm_service::comm(), &status);
00426         if ( MPI_SUCCESS != R ) 
00427           comm_service::error_die( "ArrayCombine", "MPI_Recv", R );
00428       }
00429     }
00430 #endif
00431   }
00432 
00433 protected:
00434   IntegratorSpecific _IntegratorSpecific;
00435   InitialConditionSpecific _InitialConditionSpecific;
00436   BoundaryConditionsSpecific _BoundaryConditionsSpecific;
00437   int OutputEvery, Nxc;
00438   point_type xc[OUTPUTPOINTSMAX];
00439   interpolation_type* _Interpolation;