Beispiel #1
0
 /** Solve operation for a single right hand side. Solves the
  *  linear system A * Sol = Rhs.  See MultiSolve for more
  *  details. */
 ESymSolverStatus Solve(const SymMatrix &A,
                        const Vector& rhs, Vector& sol,
                        bool check_NegEVals,
                        Index numberOfNegEVals)
 {
   std::vector<SmartPtr<const Vector> > rhsV(1);
   rhsV[0] = &rhs;
   std::vector<SmartPtr<Vector> > solV(1);
   solV[0] = &sol;
   return MultiSolve(A, rhsV, solV, check_NegEVals,
                     numberOfNegEVals);
 }
Beispiel #2
0
int MAC3DTest_StationaryBubble() {
    // Set initial level set
    const double Re = 0.0, We = 0.0, Fr = 0.0;
    const double L = 1.0, U = 1.0;
    const double rhoL = 1.226, muL = 1.78e-5;
    // const double rhoH = 1000, muH = 1.137e-3;
    const double rhoH = 1000, muH = 1.137e-3, sigma = 0.0728;
    // const double rhoL = 1000, muL = 1.137e-3, sigma = 0.0;
    const double ambientPressure = 1.0;
    const double gConstant = 0.0; 
    GAXISENUM3D GAxis = GAXISENUM3D::Y;
    // # of cells
    const int nx = 128, ny = 128, nz = 128;
    // related to initialize level set
    const double baseX = 0.0, baseY = 0.0, baseZ = 0.0, lenX = 0.04, lenY = 0.04, lenZ = 0.04, cfl = 0.5;
    double radius = 0.01, x = 0.0, y = 0.0, z = 0.0, d = 0.0;

    const int maxiter = 5, niterskip = 1, num_bc_grid = 3;
    const int64_t arrSize = (nx + 2 * num_bc_grid) * (ny + 2 * num_bc_grid) * (nz + 2 * num_bc_grid);
    const double maxtime = 0.06;
    const bool writeVTK = false;
    // length of each cell
    const double dx = lenX / nx, dy = lenY / ny, dz = lenZ / nz;
    std::ostringstream outfname_stream1;
    outfname_stream1 << "testMAC3D_StationaryBubbleBubbleRisingVel_Re_"
        << std::to_string(Re) << "_"
        << static_cast<std::ostringstream*>(&(std::ostringstream() << nx))->str()
        << "x"
        << static_cast<std::ostringstream*>(&(std::ostringstream() << ny))->str()
        << "x"
        << static_cast<std::ostringstream*>(&(std::ostringstream() << nz))->str();
    const std::string fname_vel = outfname_stream1.str();

    std::ostringstream outfname_stream2;
    outfname_stream2 << "testMAC3D_StationaryBubbleBubbleRisingDiv_Re_"
        << std::to_string(Re) << "_"
        << static_cast<std::ostringstream*>(&(std::ostringstream() << nx))->str()
        << "x"
        << static_cast<std::ostringstream*>(&(std::ostringstream() << ny))->str()
        << "x"
        << static_cast<std::ostringstream*>(&(std::ostringstream() << nz))->str();
    const std::string fname_div = outfname_stream2.str();
    const int iterskip = 1;
    int stat = 0;

    std::unique_ptr<MACSolver3D> MSolver;
    MSolver = std::make_unique<MACSolver3D>(rhoH, rhoL, muH, muL, gConstant, GAxis,
        L, U, sigma, nx, ny, nz, baseX, baseY, baseY, lenX, lenY, lenZ,
        cfl, maxtime, maxiter, niterskip, num_bc_grid, writeVTK);
    MSolver->SetBC_U_3D("wall", "wall", "wall", "wall", "wall", "wall");
    MSolver->SetBC_V_3D("wall", "wall", "wall", "wall", "wall", "wall");
    MSolver->SetBC_W_3D("wall", "wall", "wall", "wall", "wall", "wall");
    MSolver->SetBC_P_3D("wall", "wall", "wall", "wall", "wall", "wall");
    MSolver->SetBCConstantUW(0.0);
    MSolver->SetBCConstantUE(0.0);
    MSolver->SetBCConstantUS(0.0);
    MSolver->SetBCConstantUN(0.0);
    MSolver->SetBCConstantUB(0.0);
    MSolver->SetBCConstantUT(0.0);
    MSolver->SetBCConstantVW(0.0);
    MSolver->SetBCConstantVE(0.0);
    MSolver->SetBCConstantVS(0.0);
    MSolver->SetBCConstantVN(0.0);
    MSolver->SetBCConstantVB(0.0);
    MSolver->SetBCConstantVT(0.0);
    MSolver->SetBCConstantWW(0.0);
    MSolver->SetBCConstantWE(0.0);
    MSolver->SetBCConstantWS(0.0);
    MSolver->SetBCConstantWN(0.0);
    MSolver->SetBCConstantWB(0.0);
    MSolver->SetBCConstantWT(0.0);
    MSolver->UpdateAmbientPressure(MSolver->m_dt * ambientPressure);
    MSolver->SetPLTType(PLTTYPE::BINARY);

    MSolver->SetPoissonSolver(POISSONTYPE::CG);
    MSolver->SetImplicitSolver(POISSONTYPE::CG);
    const int poissonMaxIter = 2500;

    std::shared_ptr<LevelSetSolver3D> LSolver;
    LSolver = std::make_shared<LevelSetSolver3D>(nx, ny, nz, num_bc_grid, baseX, baseY, baseZ, dx, dy, dz);
    // \phi^n
    std::vector<double> lsB(arrSize, 0.0);
    // \phi^{n + 1}
    std::vector<double> ls(arrSize, 0.0);
    // inside value must be positive levelset, otherwise, negative
    
    std::vector<double> H(arrSize, 0.0), 
        HSmooth(arrSize, 0.0);
    // init velocity and pseudo-pressure
    MSolver->AllocateVariables();

    MSolver->ApplyBC_U_3D(MSolver->m_u);
    MSolver->ApplyBC_V_3D(MSolver->m_v);
    MSolver->ApplyBC_W_3D(MSolver->m_w);
    MSolver->ApplyBC_P_3D(MSolver->m_ps);
    MSolver->ApplyBC_P_3D(MSolver->m_p);
    LSolver->SetBC_P_3D("neumann", "neumann", "neumann", "neumann", "neumann", "neumann");
    LSolver->SetBCConstantPW(0.0);
    LSolver->SetBCConstantPE(0.0);
    LSolver->SetBCConstantPS(0.0);
    LSolver->SetBCConstantPN(0.0);
    LSolver->SetBCConstantPB(0.0);
    LSolver->SetBCConstantPT(0.0);
    
    for (int k = 0; k < nz + 2 * num_bc_grid; k++)
    for (int j = 0; j < ny + 2 * num_bc_grid; j++)
    for (int i = 0; i < nx + 2 * num_bc_grid; i++) {
        // positive : inside & gas, negative : outside & liquid 
        x = baseX + (i + 0.5 - num_bc_grid) * dx;
        y = baseY + (j + 0.5 - num_bc_grid) * dy;
        z = baseZ + (k + 0.5 - num_bc_grid) * dz;

        // d - inside : -, outside : +
        d = std::sqrt(std::pow(x - 0.02, 2.0) + std::pow(y - 0.02, 2.0) + std::pow(z - 0.02, 2.0)) - radius;

        // ls - inside : -(gas), outside : +(liquid)
        ls[idx3_3D(ny, nz, i, j, k)] = d;
    }
    LSolver->ApplyBC_P_3D(ls);
    LSolver->Reinit_MinRK2_3D(ls);
    
    LSolver->ApplyBC_P_3D(ls);

    // prevent dt == 0.0
    MSolver->m_dt = cfl * std::min(dx, dy) / U;
    std::cout << " dt : " << MSolver->m_dt << std::endl;

    std::vector<double> rhsU(arrSize), rhsV(arrSize), rhsW(arrSize);
    std::vector<double> uhat(arrSize), vhat(arrSize), what(arrSize);
    std::vector<double> div(arrSize);
    MSolver->OutRes(MSolver->m_iter, MSolver->m_curTime, fname_vel, fname_div,
        MSolver->m_u, MSolver->m_v, MSolver->m_w, MSolver->m_ps, ls);

    while (MSolver->m_curTime < MSolver->kMaxTime && MSolver->m_iter < MSolver->kMaxIter) {
        // Solver Level set part first
        // Have to use \phi^{n+1} for rho, mu, kappa
        MSolver->m_iter++;

        lsB = ls;
        LSolver->Solve_LevelSet_3D(ls, MSolver->m_u, MSolver->m_v, MSolver->m_w, MSolver->m_dt);
        LSolver->ApplyBC_P_3D(ls);
        LSolver->Reinit_MinRK2_3D(ls);
        
        LSolver->ApplyBC_P_3D(ls);
        
        // Solve Momentum Part
        MSolver->UpdateKappa(ls);
        H = MSolver->UpdateHeavisideFunc(ls);
        HSmooth = MSolver->UpdateSmoothHeavisideFunc(ls);

        rhsU = MSolver->GetRHSU(LSolver, ls, MSolver->m_u, MSolver->m_v, MSolver->m_w, H);
        rhsV = MSolver->GetRHSV(LSolver, ls, MSolver->m_u, MSolver->m_v, MSolver->m_w, H);
        rhsW = MSolver->GetRHSW(LSolver, ls, MSolver->m_u, MSolver->m_v, MSolver->m_w, H);

        uhat = MSolver->GetUHat(ls, rhsU, H, poissonMaxIter);
        vhat = MSolver->GetVHat(ls, rhsV, H, poissonMaxIter);
        what = MSolver->GetWHat(ls, rhsW, H, poissonMaxIter);

        MSolver->ApplyBC_U_3D(uhat);
        MSolver->ApplyBC_V_3D(vhat);
        MSolver->ApplyBC_W_3D(what);
        
        // From intermediate velocity, get divergence
        div = MSolver->GetDivergence(uhat, vhat, what);
        MSolver->ApplyBC_P_3D(MSolver->m_ps);
        LSolver->ApplyBC_P_3D(ls);

        // Solve Poisson equation
        // m_phi = pressure * dt
        stat = MSolver->SolvePoisson(MSolver->m_ps, div, ls, lsB, MSolver->m_u, MSolver->m_v, MSolver->m_w, H, poissonMaxIter);
        MSolver->ApplyBC_P_3D(MSolver->m_ps);

        stat = MSolver->UpdateVel(MSolver->m_u, MSolver->m_v, MSolver->m_w,
            uhat, vhat, what, MSolver->m_ps, ls, lsB, H);

        MSolver->ApplyBC_U_3D(MSolver->m_u);
        MSolver->ApplyBC_V_3D(MSolver->m_v);
        MSolver->ApplyBC_W_3D(MSolver->m_w);

        MSolver->m_dt = MSolver->UpdateDt(MSolver->m_u, MSolver->m_v, MSolver->m_w);
        MSolver->m_curTime += MSolver->m_dt;

        if ((MSolver->m_iter % MSolver->kNIterSkip) == 0) {
            std::chrono::high_resolution_clock::time_point p = std::chrono::high_resolution_clock::now();
            std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(p.time_since_epoch());

            std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(ms);
            std::time_t t = s.count();
            std::size_t fractional_seconds = ms.count() % 1000;

            std::cout << "Stationary Bubble : " << std::ctime(&t) << " " << MSolver->m_iter << " " << MSolver->m_curTime << " " << MSolver->m_dt << " " << std::endl;

            MSolver->OutRes(MSolver->m_iter, MSolver->m_curTime, fname_vel, fname_div,
                MSolver->m_u, MSolver->m_v, MSolver->m_w, MSolver->m_ps, ls);
        }
        std::fill(uhat.begin(), uhat.end(), 0.0);
        std::fill(vhat.begin(), vhat.end(), 0.0);
    }
    // http://stackoverflow.com/a/12836048/743078
    std::chrono::high_resolution_clock::time_point p = std::chrono::high_resolution_clock::now();
    std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(p.time_since_epoch());

    std::chrono::seconds s = std::chrono::duration_cast<std::chrono::seconds>(ms);
    std::time_t t = s.count();
    std::size_t fractional_seconds = ms.count() % 1000;

    std::cout << "(Final) Stationary Bubble : " << std::ctime(&t) << " " << MSolver->m_iter << " " << MSolver->m_curTime << " " << MSolver->m_dt << " " << std::endl;
    MSolver->OutRes(MSolver->m_iter, MSolver->m_curTime, fname_vel, fname_div,
        MSolver->m_u, MSolver->m_v, MSolver->m_w, MSolver->m_ps, ls);
    MSolver->OutResClose();

    MSolver.reset();
    LSolver.reset();

    return 0;
}