JET_END_TEST_F

JET_BEGIN_TEST_F(FmmLevelSetSolver2, Extrapolate) {
    Size2 size(160, 120);
    Vector2D gridSpacing(1.0/size.x, 1.0/size.x);
    double maxDistance = 20.0 * gridSpacing.x;

    FmmLevelSetSolver2 solver;
    CellCenteredScalarGrid2 sdf(size, gridSpacing);
    CellCenteredScalarGrid2 input(size, gridSpacing);
    CellCenteredScalarGrid2 output(size, gridSpacing);

    sdf.fill([&](const Vector2D& x) {
        return (x - Vector2D(0.75, 0.5)).length() - 0.3;
    });

    input.fill([&](const Vector2D& x) {
        if ((x - Vector2D(0.75, 0.5)).length() <= 0.3) {
            double p = 10.0 * kPiD;
            return 0.5 * 0.25 * std::sin(p * x.x) * std::sin(p * x.y);
        } else {
            return 0.0;
        }
    });

    solver.extrapolate(input, sdf, maxDistance, &output);

    saveData(sdf.constDataAccessor(), "sdf_#grid2,iso.npy");
    saveData(input.constDataAccessor(), "input_#grid2.npy");
    saveData(output.constDataAccessor(), "output_#grid2.npy");
}
void LevelSetLiquidSolver2::extrapolateVelocityToAir(double currentCfl) {
    auto sdf = signedDistanceField();
    auto vel = gridSystemData()->velocity();

    auto u = vel->uAccessor();
    auto v = vel->vAccessor();
    auto uPos = vel->uPosition();
    auto vPos = vel->vPosition();

    Array2<char> uMarker(u.size());
    Array2<char> vMarker(v.size());

    uMarker.parallelForEachIndex([&](size_t i, size_t j) {
        if (isInsideSdf(sdf->sample(uPos(i, j)))) {
            uMarker(i, j) = 1;
        } else {
            uMarker(i, j) = 0;
            u(i, j) = 0.0;
        }
    });

    vMarker.parallelForEachIndex([&](size_t i, size_t j) {
        if (isInsideSdf(sdf->sample(vPos(i, j)))) {
            vMarker(i, j) = 1;
        } else {
            vMarker(i, j) = 0;
            v(i, j) = 0.0;
        }
    });

    const Vector2D gridSpacing = sdf->gridSpacing();
    const double h = std::max(gridSpacing.x, gridSpacing.y);
    const double maxDist
        = std::max(2.0 * currentCfl, _minReinitializeDistance) * h;

    JET_INFO << "Max velocity extrapolation distance: " << maxDist;

    FmmLevelSetSolver2 fmmSolver;
    fmmSolver.extrapolate(*vel, *sdf, maxDist, vel.get());

    applyBoundaryCondition();
}