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 F77CPTLevelSet<DataType,DIM>(f_lset)));
00178 AddGFM(new GhostFluidMethod<VectorType,DIM>(
00179 new F77GFMBoundary<VectorType,DIM>(f_ibndrfl,f_itrans,f_ipvel_piston),
00180 new F77GFMLevelSet<DataType,DIM>(f_lset_piston)));
00181 SetCoupleGFM(0);
00182 _Interpolation = new interpolation_type(*this);
00183 }
00184
00185 ~FluidSolverSpecific() {
00186 DeleteGFM(_GFM[1]);
00187 DeleteGFM(_GFM[0]);
00188 delete _Flagging;
00189 delete _Fixup;
00190 delete _Interpolation;
00191 }
00192
00193 virtual void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00194 base::register_at(Ctrl,prefix);
00195 SensorsCtrl = base::LocCtrl.getSubDevice("SensorsOutput");
00196 RegisterAt(SensorsCtrl,"OutputEvery",OutputEvery);
00197 RegisterAt(SensorsCtrl,"NSensors",Nxc);
00198 char VariableName[32];
00199 for (register int i=0; i<OUTPUTPOINTSMAX; i++)
00200 for (register int d=0; d<base::Dim(); d++) {
00201 std::sprintf(VariableName,"xc(%d,%d)",i+1,d+1);
00202 RegisterAt(SensorsCtrl,VariableName,xc[i](d));
00203 }
00204 }
00205 virtual void register_at(ControlDevice& Ctrl) {
00206 base::register_at(Ctrl);
00207 }
00208
00209 virtual void SetupData() {
00210 base::SetupData();
00211 _Interpolation->SetupData(base::PGH(), base::NGhosts());
00212 if (OutputEvery<0) OutputEvery=0;
00213 if (Nxc<0) Nxc=0;
00214 if (Nxc>OUTPUTPOINTSMAX) Nxc=OUTPUTPOINTSMAX;
00215 }
00216
00217 virtual void Restart(double& t, double& dt) {
00218 std::ifstream ifs("boundary.cp", std::ios::in);
00219 int Np;
00220 double xm, vm, cm, rd;
00221 f_combl_read(xm,vm,cm,rd,Np);
00222 ifs >> xm >> vm;
00223 ifs.close();
00224 f_combl_write(xm,vm,cm,rd,Np);
00225 base::Restart(t,dt);
00226 }
00227 virtual void Checkpointing() {
00228 int me = MY_PROC;
00229 if (me == VizServer) {
00230 int Np;
00231 double xm, vm, cm, rd;
00232 f_combl_read(xm,vm,cm,rd,Np);
00233 std::ofstream ofs("boundary.cp", std::ios::out);
00234 ofs << xm << " " << vm << std::endl;
00235 ofs.close();
00236 }
00237 base::Checkpointing();
00238 }
00239
00240 virtual void SendBoundaryData() {
00241 START_WATCH
00242 for (register int l=0; l<=FineLevel(base::GH()); l++)
00243 ((output_type*) _FileOutput)->Transform(base::U(), base::Work(),
00244 CurrentTime(base::GH(),l), l,
00245 base::Dim()+4, base::t[l]);
00246 END_WATCH(FLUID_CPL_PRESSURE_CALCULATE)
00247 base::SendBoundaryData();
00248 }
00249
00250 virtual void ModifyELCSendData(eul_comm_type* eulComm) {
00251 DataType distance = -GFM(CoupleGFM()).Boundary().Cutoff();
00252 int Npoints = _eulComm->getNumberOfFaces();
00253 double *press_data = _eulComm->getPressuresData();
00254 const point_type *norm = reinterpret_cast<const point_type *>(_eulComm->getFaceNormalsData());
00255 const point_type *cent = reinterpret_cast<const point_type *>(_eulComm->getFaceCentroidsData());
00256 for (register int n=0; n<Npoints; n++) {
00257 if (press_data[n]!=std::numeric_limits<DataType>::max()) {
00258 press_data[n] *= -1; press_data[n] += base::PressureConversionFactor()*101325.;
00259 }
00260 point_type p = cent[n];
00261 if (distance>1.e-12) p += distance*norm[n];
00262 if (std::sqrt(p(1)*p(1)+p(2)*p(2))>0.032)
00263 press_data[n] = std::numeric_limits<DataType>::max();
00264 }
00265 }
00266
00267
00268
00269 virtual void Advance(double& t, double& dt) {
00270
00271 int me = MY_PROC;
00272 DataType force_old;
00273 if (base::GFM(1).IsUsed())
00274 CalculateForce(force_old);
00275
00276 base::Advance(t,dt);
00277
00278 if (base::GFM(1).IsUsed()) {
00279 DataType a, force_new;
00280 CalculateForce(force_new);
00281
00282 int Np;
00283 double xm, vm, cm, rd;
00284 f_combl_read(xm,vm,cm,rd,Np);
00285
00286 a = 0.5/cm*(force_old+force_new);
00287 vm += a*dt;
00288 xm += vm*dt;
00289
00290 f_combl_write(xm,vm,cm,rd,Np);
00291
00292
00293 if (me == VizServer) {
00294 std::ofstream outfile;
00295 std::ostream* out;
00296 std::string fname = "boundary.txt";
00297 outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00298 out = new std::ostream(outfile.rdbuf());
00299 *out << t << " " << force_new << " " << xm << " " << vm << std::endl;
00300 outfile.close();
00301 delete out;
00302 }
00303 }
00304
00305 if (!OutputEvery) return;
00306
00307 int TimeZero = CurrentTime(base::GH(),0);
00308 TimeZero /= RefinedBy(base::GH(),MaxLevel(base::GH()));
00309 if (TimeZero % OutputEvery != 0) return;
00310
00311 VectorType* dat = new VectorType[Nxc];
00312
00313
00314 _Interpolation->PointsValues(base::U(),t,Nxc,xc,dat);
00315 int NValues = Nxc*base::NEquations();
00316 _Interpolation->ArrayCombine(VizServer,NValues,&(dat[0](0)));
00317
00318
00319 if (MY_PROC == VizServer) {
00320 DataType* output_data = new DataType[_FileOutput->Ncnt()*Nxc];
00321 BBox bb(3,0,0,0,Nxc-1,0,0,1,1,1);
00322 vec_grid_data_type val(bb,dat);
00323 for (int cnt=1;cnt<=_FileOutput->Ncnt(); cnt++) {
00324 if (_FileOutput->OutputName(cnt-1).c_str()[0] == '-') continue;
00325 grid_data_type output(bb,output_data+(cnt-1)*Nxc);
00326 ((output_type::out_3_func_type) (((output_type*) base::_FileOutput)->GetOutFunc()))
00327 (FA(3,val),FA(3,output),BOUNDING_BOX(bb),base::NEquations(),cnt,t);
00328 DataType* dummy;
00329 output.deallocate(dummy);
00330 }
00331 VectorType* dummy;
00332 val.deallocate(dummy);
00333 std::ofstream outfile;
00334 std::ostream* out;
00335 std::string fname = "sensors.txt";
00336 outfile.open(fname.c_str(), std::ios::out | std::ios::app);
00337 out = new std::ostream(outfile.rdbuf());
00338 *out << t << " ";
00339 for (register int j=0;j<Nxc; j++)
00340 for (int cnt=0;cnt<_FileOutput->Ncnt(); cnt++)
00341 if (_FileOutput->OutputName(cnt).c_str()[0] != '-')
00342 *out << " " << output_data[cnt*Nxc+j];
00343 *out << std::endl;
00344 delete [] output_data;
00345 outfile.close();
00346 delete out;
00347 }
00348 delete [] dat;
00349 }
00350
00351 void CalculateForce(DataType& sum) {
00352 int me = MY_PROC;
00353
00354 double pi = 4.0*std::atan(1.0);
00355
00356
00357 int Np;
00358 double xm, vm, cm, rd;
00359 f_combl_read(xm,vm,cm,rd,Np);
00360
00361
00362 for (register int l=0; l<=FineLevel(base::GH()); l++) {
00363 int Time = CurrentTime(base::GH(),l);
00364 int press_cnt = base::Dim()+4;
00365 ((output_type*) _FileOutput)->Transform(base::U(), base::Work(), Time, l,
00366 press_cnt, base::t[l]);
00367 }
00368
00369 int Npoints = Np*Np;
00370 DataType* p = new DataType[Npoints];
00371 point_type* xc = new point_type[Npoints];
00372
00373 register int n;
00374
00375 for (n=0; n<Np; n++)
00376 for (register int m=0; m<Np; m++) {
00377 xc[n*Np+m](0) = xm;
00378 xc[n*Np+m](1) = (2.*n/Np-1.)*rd;
00379 xc[n*Np+m](2) = (2.*m/Np-1.)*rd;
00380 }
00381
00382
00383 _Interpolation->PointsValues(base::Work(),base::t[0],Npoints,xc,p);
00384 _Interpolation->ArrayCombine(VizServer,Npoints,p);
00385
00386
00387 if (me == VizServer) {
00388 int vp = 0;
00389 sum = 0.;
00390 for (n=0; n<Npoints; n++)
00391 if (p[n]>-1.e37) {
00392 sum += p[n]; vp++;
00393 }
00394 sum /= vp;
00395 sum -= 101325.;
00396 sum *= pi*rd*rd;
00397
00398 delete [] p;
00399 delete [] xc;
00400 }
00401
00402 #ifdef DAGH_NO_MPI
00403 #else
00404 if (comm_service::dce() && comm_service::proc_num() > 1) {
00405 int num = comm_service::proc_num();
00406 MPI_Status status;
00407 int R;
00408 int size = sizeof(DataType);
00409 int tag = 10001;
00410 if (me == VizServer)
00411 for (int proc=0; proc<num; proc++) {
00412 if (proc==VizServer) continue;
00413 R = MPI_Send((void *)&sum, size, MPI_BYTE, proc, tag, comm_service::comm());
00414 if ( MPI_SUCCESS != R )
00415 comm_service::error_die( "SumCombine", "MPI_Send", R );
00416 }
00417 else {
00418 R = MPI_Recv((void *)&sum, size, MPI_BYTE, VizServer, tag, comm_service::comm(), &status);
00419 if ( MPI_SUCCESS != R )
00420 comm_service::error_die( "ArrayCombine", "MPI_Recv", R );
00421 }
00422 }
00423 #endif
00424 }
00425
00426 protected:
00427 IntegratorSpecific _IntegratorSpecific;
00428 InitialConditionSpecific _InitialConditionSpecific;
00429 BoundaryConditionsSpecific _BoundaryConditionsSpecific;
00430 int OutputEvery, Nxc;
00431 point_type xc[OUTPUTPOINTSMAX];
00432 interpolation_type* _Interpolation;