00001
00002
00003
00004
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
00275
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
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
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
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
00364 int Np;
00365 double xm, vm, cm, rd;
00366 f_combl_read(xm,vm,cm,rd,Np);
00367
00368
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
00390 _Interpolation->PointsValues(base::Work(),base::t[0],Npoints,xc,p);
00391 _Interpolation->ArrayCombine(VizServer,Npoints,p);
00392
00393
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;