예제 #1
0
void 
solve_with_f90(PArray<MultiFab>& rhs, PArray<MultiFab>& phi, 
               Array< PArray<MultiFab> >& grad_phi_edge, 
               const Array<Geometry>& geom, int base_level, int finest_level, Real tol, Real abs_tol)
{
    int nlevs = finest_level - base_level + 1;

    int mg_bc[2*BL_SPACEDIM];

    // This tells the solver that we are using periodic bc's
    if (Geometry::isAllPeriodic())
    {
        for (int dir = 0; dir < BL_SPACEDIM; ++dir)
        {
            mg_bc[2*dir + 0] = 0;
            mg_bc[2*dir + 1] = 0;
        }
    } else {
	BoxLib::Abort("non periodic boundraies not supported here");
    }

    // Have to do some packing because these arrays does not always start with base_level
    PArray<Geometry> geom_p(nlevs);
    PArray<MultiFab> rhs_p(nlevs);
    PArray<MultiFab> phi_p(nlevs);
    for (int ilev = 0; ilev < nlevs; ++ilev) {
	geom_p.set(ilev, &geom[ilev+base_level]);
	rhs_p.set (ilev,  &rhs[ilev+base_level]);
	phi_p.set (ilev,  &phi[ilev+base_level]);
    }
    
    // Refinement ratio is hardwired to 2 here.
    IntVect crse_ratio = (base_level == 0) ? 
	IntVect::TheZeroVector() : IntVect::TheUnitVector() * 2;

    FMultiGrid fmg(geom_p, base_level, crse_ratio);

    if (base_level == 0) {
	fmg.set_bc(mg_bc, phi[base_level]);
    } else {
	fmg.set_bc(mg_bc, phi[base_level-1], phi[base_level]);
    }

    fmg.set_const_gravity_coeffs();

    int always_use_bnorm = 0;
    int need_grad_phi = 1;
    fmg.set_verbose(1);
    fmg.solve(phi_p, rhs_p, tol, abs_tol, always_use_bnorm, need_grad_phi);
   
    for (int ilev = 0; ilev < nlevs; ++ilev)
    {
	int amr_level = ilev + base_level;
	fmg.get_fluxes(grad_phi_edge[amr_level], ilev);
    }
}
예제 #2
0
파일: main.cpp 프로젝트: qinyubo/BoxLib
void solve_with_F90(MultiFab& soln, MultiFab& gphi, Real a, Real b, MultiFab& alpha, 
		    PArray<MultiFab>& beta, MultiFab& rhs, const BoxArray& bs, const Geometry& geom)
{
  BL_PROFILE("solve_with_F90()");

  FMultiGrid fmg(geom);

  int mg_bc[2*BL_SPACEDIM];
  if (bc_type == Periodic) {
    // Define the type of boundary conditions to be periodic
    for ( int n = 0; n < BL_SPACEDIM; ++n ) {
      mg_bc[2*n + 0] = MGT_BC_PER;
      mg_bc[2*n + 1] = MGT_BC_PER;
    }
  }
  else if (bc_type == Neumann) {
    // Define the type of boundary conditions to be Neumann
    for ( int n = 0; n < BL_SPACEDIM; ++n ) {
      mg_bc[2*n + 0] = MGT_BC_NEU;
      mg_bc[2*n + 1] = MGT_BC_NEU;
    }
  }
  else if (bc_type == Dirichlet) {
    // Define the type of boundary conditions to be Dirichlet
    for ( int n = 0; n < BL_SPACEDIM; ++n ) {
      mg_bc[2*n + 0] = MGT_BC_DIR;
      mg_bc[2*n + 1] = MGT_BC_DIR;
    }
  }

  fmg.set_bc(mg_bc);
  fmg.set_maxorder(maxorder);

  fmg.set_scalars(a, b);
  fmg.set_coefficients(alpha, beta);

  int always_use_bnorm = 0;
  int need_grad_phi = 1;
  fmg.solve(soln, rhs, tolerance_rel, tolerance_abs, always_use_bnorm, need_grad_phi);

  PArray<MultiFab> grad_phi(BL_SPACEDIM, PArrayManage);
  for (int n = 0; n < BL_SPACEDIM; ++n)
      grad_phi.set(n, new MultiFab(BoxArray(soln.boxArray()).surroundingNodes(n), 1, 0));

  fmg.get_fluxes(grad_phi);

  // Average edge-centered gradients to cell centers.
  BoxLib::average_face_to_cellcenter(gphi, grad_phi, geom);
}
예제 #3
0
void
Diffusion::applyop (int level, MultiFab& Temperature, 
                    MultiFab& CrseTemp, MultiFab& DiffTerm, 
                    PArray<MultiFab>& temp_cond_coef)
{
    if (verbose && ParallelDescriptor::IOProcessor()) {
        std::cout << "   " << '\n';
        std::cout << "... compute diffusive term at level " << level << '\n';
    }

    PArray<MultiFab> coeffs_curv;
#if (BL_SPACEDIM < 3)
    // NOTE: we just pass DiffTerm here to use in the MFIter loop...
    if (Geometry::IsRZ() || Geometry::IsSPHERICAL())
    {
	coeffs_curv.resize(BL_SPACEDIM, PArrayManage);

	for (int i = 0; i< BL_SPACEDIM; ++i) {
	    coeffs_curv.set(i, new MultiFab(temp_cond_coef[i].boxArray(), 1, 0, Fab_allocate));
	    MultiFab::Copy(coeffs_curv[i], temp_cond_coef[i], 0, 0, 1, 0);
	}

	applyMetricTerms(0, DiffTerm, coeffs_curv);
    }
#endif

    PArray<MultiFab> & coeffs = (coeffs_curv.size() > 0) ? coeffs_curv : temp_cond_coef;

    IntVect crse_ratio = level > 0 ? parent->refRatio(level-1)
                                   : IntVect::TheZeroVector();

    FMultiGrid fmg(parent->Geom(level), level, crse_ratio);

    if (level == 0) {
	fmg.set_bc(mg_bc, Temperature);
    } else {
	fmg.set_bc(mg_bc, CrseTemp, Temperature);
    }

    fmg.set_diffusion_coeffs(coeffs);

    fmg.applyop(Temperature, DiffTerm);

#if (BL_SPACEDIM < 3)
    // Do this to unweight Res
    if (Geometry::IsSPHERICAL() || Geometry::IsRZ() )
	unweight_cc(level, DiffTerm);
#endif
}
예제 #4
0
void fmg_mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    const int *dm;
    int        cyc=1, nit=1, rtype=2;
    double     *A, *b, *x, *scratch;
    static double param[] = {1.0, 1.0, 1.0, 1.0, 0.0};

    if (nrhs!=3 || nlhs>1)
        mexErrMsgTxt("Incorrect usage");
    if (!mxIsNumeric(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) || !mxIsDouble(prhs[0]))
        mexErrMsgTxt("Data must be numeric, real, full and double");
    if (mxGetNumberOfDimensions(prhs[0])!=3) mexErrMsgTxt("Wrong number of dimensions.");

    if (!mxIsNumeric(prhs[1]) || mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]) || !mxIsDouble(prhs[1]))
        mexErrMsgTxt("Data must be numeric, real, full and double");
    if (mxGetNumberOfDimensions(prhs[1])!=3) mexErrMsgTxt("Wrong number of dimensions.");
    dm = mxGetDimensions(prhs[1]);

    if (mxGetDimensions(prhs[0])[0] != dm[0])
        mexErrMsgTxt("Incompatible 1st dimension.");
    if (mxGetDimensions(prhs[0])[1] != dm[1])
        mexErrMsgTxt("Incompatible 2nd dimension.");
    if (mxGetDimensions(prhs[0])[2] != dm[2])
        mexErrMsgTxt("Incompatible 3rd dimension.");

    if (!mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2]) || mxIsSparse(prhs[2]) || !mxIsDouble(prhs[2]))
        mexErrMsgTxt("Data must be numeric, real, full and double");
    if (mxGetNumberOfElements(prhs[2]) != 4)
        mexErrMsgTxt("Third argument should contain rtype, lambda, ncycles and relax-its.");

    rtype    = (int)(mxGetPr(prhs[2])[0]);
    param[3] = mxGetPr(prhs[2])[1];
    cyc      = (int)(mxGetPr(prhs[2])[2]);
    nit      = (int)(mxGetPr(prhs[2])[3]);

    plhs[0] = mxCreateNumericArray(3,dm, mxDOUBLE_CLASS, mxREAL);

    A       = (double *)mxGetPr(prhs[0]);
    b       = (double *)mxGetPr(prhs[1]);
    x       = (double *)mxGetPr(plhs[0]);
    scratch = (double *)mxCalloc(fmg_scratchsize((int *)dm),sizeof(double));
    fmg((int *)dm, A, b, rtype, param, cyc, nit, x, scratch);
    mxFree((void *)scratch);
}
예제 #5
0
void
Diffusion::applyViscOp (int level, MultiFab& Vel, 
                        MultiFab& CrseVel, MultiFab& ViscTerm, 
                        PArray<MultiFab>& visc_coeff)
{
    if (verbose && ParallelDescriptor::IOProcessor()) {
        std::cout << "   " << '\n';
        std::cout << "... compute second part of viscous term at level " << level << '\n';
    }

    IntVect crse_ratio = level > 0 ? parent->refRatio(level-1)
                                   : IntVect::TheZeroVector();

    FMultiGrid fmg(parent->Geom(level), level, crse_ratio);

    if (level == 0) {
	fmg.set_bc(mg_bc, Vel);
    } else {
	fmg.set_bc(mg_bc, CrseVel, Vel);
    }

    // Here we DO NOT multiply the coefficients by (1/r^2) for spherical coefficients
    // because we are computing (1/r^2) d/dr (const * d/dr(r^2 u))
    fmg.set_diffusion_coeffs(visc_coeff);

#if (BL_SPACEDIM < 3)
    // Here we weight the Vel going into the FMG applyop
    if (Geometry::IsSPHERICAL() || Geometry::IsRZ() )
	weight_cc(level, Vel);
#endif

    fmg.applyop(Vel, ViscTerm);

#if (BL_SPACEDIM < 3)
    // Do this to unweight Res
    if (Geometry::IsSPHERICAL() || Geometry::IsRZ() )
	unweight_cc(level, ViscTerm);
#endif
}
예제 #6
0
static void fmg_mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    int nd, i;
     int dm[4];
    int   cyc=1, nit=1, rtype=0;
    float *A, *b, *x, *scratch;
    static double param[6] = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0};
    double scal[256];

    if ((nrhs!=3 && nrhs!=4) || nlhs>1)
        mexErrMsgTxt("Incorrect usage");
    if (!mxIsNumeric(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) || !mxIsSingle(prhs[0]))
        mexErrMsgTxt("Data must be numeric, real, full and single");
    if (!mxIsNumeric(prhs[1]) || mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]) || !mxIsSingle(prhs[1]))
        mexErrMsgTxt("Data must be numeric, real, full and single");

    nd = mxGetNumberOfDimensions(prhs[1]);
    if (nd>4) mexErrMsgTxt("Wrong number of dimensions.");
    for(i=0; i<nd; i++) dm[i] = mxGetDimensions(prhs[1])[i];
    for(i=nd; i<4; i++) dm[i] = 1;

    nd = mxGetNumberOfDimensions(prhs[0]);
    if (nd>4) mexErrMsgTxt("Wrong number of dimensions.");
    if ((nd==4) && (mxGetDimensions(prhs[0])[3] != (dm[3]*(dm[3]+1))/2))
        mexErrMsgTxt("Incompatible 4th dimension (must be (n*(n+1))/2).");
    if (nd>3) nd=3;
    for(i=0; i<nd; i++) if (mxGetDimensions(prhs[0])[i] != dm[i]) mexErrMsgTxt("Incompatible dimensions.");
    for(i=nd; i<3; i++) if (dm[i] != 1) mexErrMsgTxt("Incompatible dimensions.");
 
    if (!mxIsNumeric(prhs[2]) || mxIsComplex(prhs[2]) || mxIsSparse(prhs[2]) || !mxIsDouble(prhs[2]))
        mexErrMsgTxt("Data must be numeric, real, full and double");

    if (mxGetNumberOfElements(prhs[2]) != 9)
        mexErrMsgTxt("Third argument should contain rtype, vox1, vox2, vox3, param1, param2, param3, ncycles and relax-its.");
    rtype    = (int)(mxGetPr(prhs[2])[0]);
    param[0] = 1/mxGetPr(prhs[2])[1];
    param[1] = 1/mxGetPr(prhs[2])[2];
    param[2] = 1/mxGetPr(prhs[2])[3];
    param[3] = mxGetPr(prhs[2])[4];
    param[4] = mxGetPr(prhs[2])[5];
    param[5] = mxGetPr(prhs[2])[6];
    cyc      = mxGetPr(prhs[2])[7];
    nit      = (int)(mxGetPr(prhs[2])[8]);

    if (nrhs==4)
    {
        double *s;
        if (!mxIsNumeric(prhs[3]) || mxIsComplex(prhs[3]) || mxIsSparse(prhs[3]) || !mxIsDouble(prhs[3]))
            mexErrMsgTxt("Data must be numeric, real, full and double");
        if (mxGetNumberOfElements(prhs[3]) != dm[3])
            mexErrMsgTxt("Incompatible number of scales.");
        s = (double *)mxGetPr(prhs[3]);
        for(i=0; i< dm[3]; i++)
            scal[i] = s[i];
    }
    else
    {
        for(i=0; i<dm[3]; i++)
            scal[i] = 1.0;
    }
    plhs[0] = mxCreateNumericArray(4,(unsigned int *)dm, mxSINGLE_CLASS, mxREAL);

    A       = (float *)mxGetPr(prhs[0]);
    b       = (float *)mxGetPr(prhs[1]);
    x       = (float *)mxGetPr(plhs[0]);
    scratch = (float *)mxCalloc(fmg_scratchsize((int *)dm),sizeof(float));
    fmg((int *)dm, A, b, rtype, param, scal, cyc, nit, x, scratch);
    mxFree((void *)scratch);
}