Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demos/FiniteVolume/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ level_set.cpp:finite-volume-level-set
level_set_from_scratch.cpp:finite-volume-level-set-from-scratch
advection_1d.cpp:finite-volume-advection-1d
advection_2d.cpp:finite-volume-advection-2d
advection_3d.cpp:finite-volume-advection-3d
advection_2d_user_bc.cpp:finite-volume-advection-2d-user-bc
scalar_burgers_2d.cpp:finite-volume-scalar-burgers-2d
linear_convection_obstacle.cpp:finite-volume-linear-convection-obstacle
Expand Down
165 changes: 165 additions & 0 deletions demos/FiniteVolume/advection_3d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright 2018-2025 the samurai's authors
// SPDX-License-Identifier: BSD-3-Clause

#include <array>

#include <xtensor/xfixed.hpp>

#include <samurai/algorithm.hpp>
#include <samurai/bc.hpp>
#include <samurai/field.hpp>
#include <samurai/io/hdf5.hpp>
#include <samurai/io/restart.hpp>
#include <samurai/mr/adapt.hpp>
#include <samurai/mr/mesh.hpp>
#include <samurai/samurai.hpp>
#include <samurai/stencil_field.hpp>
#include <samurai/subset/node.hpp>

#include <filesystem>
namespace fs = std::filesystem;

template <class Field>
void init(Field& u)
{
auto& mesh = u.mesh();
u.resize();

samurai::for_each_cell(mesh,
[&](auto& cell)
{
auto center = cell.center();
const double radius = .2;
const double x_center = 0.3;
const double y_center = 0.3;
const double z_center = 0.3;
if (((center[0] - x_center) * (center[0] - x_center) + (center[1] - y_center) * (center[1] - y_center)
+ (center[2] - z_center) * (center[2] - z_center))
<= radius * radius)
{
u[cell] = 1;
}
else
{
u[cell] = 0;
}
});
}

template <class Field>
void save(const fs::path& path, const std::string& filename, const Field& u, const std::string& suffix = "")
{
auto& mesh = u.mesh();

#ifdef SAMURAI_WITH_MPI
mpi::communicator world;
samurai::save(path, fmt::format("{}_size_{}{}", filename, world.size(), suffix), mesh, u);
#else
samurai::save(path, fmt::format("{}{}", filename, suffix), mesh, u);
samurai::dump(path, fmt::format("{}_restart{}", filename, suffix), mesh, u);
#endif
}

int main(int argc, char* argv[])
{
auto& app = samurai::initialize("Finite volume example for the advection equation in 3d using multiresolution", argc, argv);

constexpr std::size_t dim = 3;
using Config = samurai::MRConfig<dim>;

// Simulation parameters
xt::xtensor_fixed<double, xt::xshape<dim>> min_corner = {0., 0., 0.};
xt::xtensor_fixed<double, xt::xshape<dim>> max_corner = {1., 1., 1.};
std::array<double, dim> a{
{1, 1, 1}
};
double Tf = .1;
double cfl = 0.25;
double t = 0.;
std::string restart_file;

// Multiresolution parameters
std::size_t min_level = 4;
std::size_t max_level = 10;

// Output parameters
fs::path path = fs::current_path();
std::string filename = "FV_advection_3d";
std::size_t nfiles = 1;

app.add_option("--min-corner", min_corner, "The min corner of the box")->capture_default_str()->group("Simulation parameters");
app.add_option("--max-corner", max_corner, "The max corner of the box")->capture_default_str()->group("Simulation parameters");
app.add_option("--velocity", a, "The velocity of the advection equation")->capture_default_str()->group("Simulation parameters");
app.add_option("--cfl", cfl, "The CFL")->capture_default_str()->group("Simulation parameters");
app.add_option("--Ti", t, "Initial time")->capture_default_str()->group("Simulation parameters");
app.add_option("--Tf", Tf, "Final time")->capture_default_str()->group("Simulation parameters");
app.add_option("--restart-file", restart_file, "Restart file")->capture_default_str()->group("Simulation parameters");
app.add_option("--min-level", min_level, "Minimum level of the multiresolution")->capture_default_str()->group("Multiresolution");
app.add_option("--max-level", max_level, "Maximum level of the multiresolution")->capture_default_str()->group("Multiresolution");
app.add_option("--path", path, "Output path")->capture_default_str()->group("Output");
app.add_option("--filename", filename, "File name prefix")->capture_default_str()->group("Output");
app.add_option("--nfiles", nfiles, "Number of output files")->capture_default_str()->group("Output");

SAMURAI_PARSE(argc, argv);

const samurai::Box<double, dim> box(min_corner, max_corner);
samurai::MRMesh<Config> mesh;
auto u = samurai::make_scalar_field<double>("u", mesh);

if (restart_file.empty())
{
mesh = {
box,
min_level,
max_level,
{true, true, true}
};
init(u);
}
else
{
samurai::load(restart_file, mesh, u);
}
// samurai::make_bc<samurai::Dirichlet<1>>(u, 0.);

double dt = cfl * mesh.cell_length(max_level);
const double dt_save = Tf / static_cast<double>(nfiles);

auto unp1 = samurai::make_scalar_field<double>("unp1", mesh);

auto MRadaptation = samurai::make_MRAdapt(u);
auto mra_config = samurai::mra_config().epsilon(2e-4);
MRadaptation(mra_config);
save(path, filename, u, "_init");

std::size_t nsave = 1;
std::size_t nt = 0;

while (t != Tf)
{
MRadaptation(mra_config);

t += dt;
if (t > Tf)
{
dt += Tf - t;
t = Tf;
}

std::cout << fmt::format("iteration {}: t = {}, dt = {}", nt++, t, dt) << std::endl;

samurai::update_ghost_mr(u);
unp1.resize();
unp1 = u - dt * samurai::upwind(a, u);

std::swap(u.array(), unp1.array());

if (t >= static_cast<double>(nsave + 1) * dt_save || t == Tf)
{
const std::string suffix = (nfiles != 1) ? fmt::format("_ite_{}", nsave++) : "";
save(path, filename, u, suffix);
}
}
samurai::finalize();
return 0;
}
3 changes: 2 additions & 1 deletion demos/FiniteVolume/linear_convection_obstacle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ int main(int argc, char* argv[])
}

double t = 0;
while (t != Tf)
//~ while (t != Tf)
for (int ite = 0; ite != 23; ++ite)
{
// Move to next timestep
t += dt;
Expand Down
2 changes: 1 addition & 1 deletion demos/tutorial/set_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ int main()
u[cell] = cell.indices[0];
});

auto subset1 = samurai::intersection(ca[0], samurai::contraction(ca[1], 1));
auto subset1 = samurai::intersection(ca[0], samurai::contract(ca[1], 1));
subset1.on(0)(
[&](const auto& i, auto)
{
Expand Down
25 changes: 19 additions & 6 deletions include/samurai/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include "cell.hpp"
#include "mesh_holder.hpp"

#include "concepts.hpp"
#include "subset/node.hpp"

using namespace xt::placeholders;

namespace samurai
Expand Down Expand Up @@ -111,18 +114,28 @@ namespace samurai
}
}

template <class Mesh, class Func>
template <IsMesh Mesh, class Func>
inline void for_each_interval(const Mesh& mesh, Func&& f)
{
using mesh_id_t = typename Mesh::config::mesh_id_t;
for_each_interval(mesh[mesh_id_t::cells], std::forward<Func>(f));
}

template <class Op, class StartEndOp, class... S>
class Subset;

template <class Func, class Op, class StartEndOp, class... S>
inline void for_each_interval(Subset<Op, StartEndOp, S...>& set, Func&& f)
//~ template <class Op, class StartEndOp, class... S>
//~ class Subset;

//~ template <class Func, class Op, class StartEndOp, class... S>
//~ inline void for_each_interval(Subset<Op, StartEndOp, S...>& set, Func&& f)
//~ {
//~ set(
//~ [&](const auto& i, const auto& index)
//~ {
//~ f(set.level(), i, index);
//~ });
//~ }

template <class Func, class Set>
inline void for_each_interval(const SetBase<Set>& set, Func&& f)
{
set(
[&](const auto& i, const auto& index)
Expand Down
4 changes: 2 additions & 2 deletions include/samurai/boundary.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace samurai
{
using mesh_id_t = typename Mesh::mesh_id_t;

auto& cells = mesh[mesh_id_t::cells][level];
const auto& cells = mesh[mesh_id_t::cells][level];

return difference(cells, translate(self(domain).on(level), -layer_width * direction));
}
Expand Down Expand Up @@ -43,7 +43,7 @@ namespace samurai
{
using mesh_id_t = typename Mesh::mesh_id_t;

auto& cells = mesh[mesh_id_t::cells][level];
const auto& cells = mesh[mesh_id_t::cells][level];

return difference(cells, contract(self(mesh.domain()).on(level), 1));
}
Expand Down
14 changes: 13 additions & 1 deletion include/samurai/interval.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ namespace samurai
template <class value_t, class index_t>
inline bool operator==(const Interval<value_t, index_t>& i1, const Interval<value_t, index_t>& i2)
{
return !(i1.start != i2.start || i1.end != i2.end || i1.step != i2.step || i1.index != i2.index);
//~ return !(i1.start != i2.start || i1.end != i2.end || i1.step != i2.step || i1.index != i2.index);
return !(i1.start != i2.start || i1.end != i2.end || i1.step != i2.step);
}

template <class value_t, class index_t>
Expand All @@ -376,6 +377,17 @@ namespace samurai
{
return i1.start < i2.start;
}

template <typename T>
struct IsInterval : std::false_type
{
};

template <class value_t, class index_t>
struct IsInterval<Interval<value_t, index_t>> : std::true_type
{
};

} // namespace samurai

template <class TValue, class TIndex>
Expand Down
49 changes: 45 additions & 4 deletions include/samurai/level_cell_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ namespace samurai
LevelCellArray() = default;
LevelCellArray(const LevelCellList<Dim, TInterval>& lcl);

template <class Op, class StartEndOp, class... S>
LevelCellArray(Subset<Op, StartEndOp, S...> set);
template <class Set>
explicit LevelCellArray(const SetBase<Set>& set);

template <class Set>
LevelCellArray(const SetBase<Set>& set, const coords_t& origin_point, const double scaling_factor);

LevelCellArray(std::size_t level, const Box<value_t, dim>& box);
LevelCellArray(std::size_t level,
Expand Down Expand Up @@ -344,9 +347,21 @@ namespace samurai
}
}

//~ template <std::size_t Dim, class TInterval>
//~ template <class Op, class StartEndOp, class... S>
//~ inline LevelCellArray<Dim, TInterval>::LevelCellArray(Subset<Op, StartEndOp, S...> set)
//~ : m_level(set.level())
//~ {
//~ set(
//~ [this](const auto& i, const auto& index)
//~ {
//~ add_interval_back(i, index);
//~ });
//~ }

template <std::size_t Dim, class TInterval>
template <class Op, class StartEndOp, class... S>
inline LevelCellArray<Dim, TInterval>::LevelCellArray(Subset<Op, StartEndOp, S...> set)
template <class Set>
inline LevelCellArray<Dim, TInterval>::LevelCellArray(const SetBase<Set>& set)
: m_level(set.level())
{
set(
Expand All @@ -356,6 +371,32 @@ namespace samurai
});
}

template <std::size_t Dim, class TInterval>
template <class Set>
inline LevelCellArray<Dim, TInterval>::LevelCellArray(const SetBase<Set>& set, const coords_t& origin_point, const double scaling_factor)
: m_level(set.level())
, m_origin_point(origin_point)
, m_scaling_factor(scaling_factor)
{
set(
[this](const auto& i, const auto& index)
{
add_interval_back(i, index);
});
}

//~ template <std::size_t Dim, class TInterval>
//~ template <class Op, class StartEndOp, class... S>
//~ inline LevelCellArray<Dim, TInterval>::LevelCellArray(Subset<Op, StartEndOp, S...> set)
//~ : m_level(set.level())
//~ {
//~ set(
//~ [this](const auto& i, const auto& index)
//~ {
//~ add_interval_back(i, index);
//~ });
//~ }

template <std::size_t Dim, class TInterval>
inline LevelCellArray<Dim, TInterval>::LevelCellArray(std::size_t level, const Box<value_t, dim>& box)
: m_level{level}
Expand Down
5 changes: 5 additions & 0 deletions include/samurai/list_of_intervals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ namespace samurai

void add_point(value_t point);
void add_interval(const interval_t& interval);

void clear()
{
std::forward_list<Interval<TValue, TIndex>>::clear();
}
};

////////////////////////////////////
Expand Down
10 changes: 6 additions & 4 deletions include/samurai/mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,16 +815,18 @@ namespace samurai
{
if constexpr (dim == 2)
{
m_corners.push_back(difference(
m_domain,
union_(translate(m_domain, direction_t{-direction[0], 0}), translate(m_domain, direction_t{0, -direction[1]}))));
m_corners.push_back(difference(m_domain,
union_(translate(m_domain, direction_t{-direction[0], 0}),
translate(m_domain, direction_t{0, -direction[1]})))
.to_lca());
}
else if constexpr (dim == 3)
{
m_corners.push_back(difference(m_domain,
union_(translate(m_domain, direction_t{-direction[0], 0, 0}),
translate(m_domain, direction_t{0, -direction[1], 0}),
translate(m_domain, direction_t{0, 0, -direction[2]}))));
translate(m_domain, direction_t{0, 0, -direction[2]})))
.to_lca());
}
});
}
Expand Down
3 changes: 3 additions & 0 deletions include/samurai/samurai_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ namespace samurai
static constexpr std::size_t graduation_width = 1;
static constexpr std::size_t prediction_order = 1;

static constexpr bool projection_with_list_of_intervals = true;
static constexpr bool use_native_expand = true;

using index_t = signed long long int;
using value_t = int;
using interval_t = Interval<value_t, index_t>;
Expand Down
Loading