Skip to content

Postprocessing Tool: Subvolume Data Output #1547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
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 amr-wind/utilities/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ target_sources(${amr_wind_lib_name}

add_subdirectory(tagging)
add_subdirectory(sampling)
add_subdirectory(subvolume)
add_subdirectory(averaging)

if (AMR_WIND_ENABLE_NETCDF)
Expand Down
5 changes: 3 additions & 2 deletions amr-wind/utilities/sampling/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ target_sources(${amr_wind_lib_name}
DTUSpinnerSampler.cpp
PlaneSampler.cpp
ProbeSampler.cpp
FreeSurfaceSampler.cpp
VolumeSampler.cpp
# The ones below should probably be moved
FieldNorms.cpp
KineticEnergy.cpp
Enstrophy.cpp
FreeSurfaceSampler.cpp
VolumeSampler.cpp
WaveEnergy.cpp
)
6 changes: 6 additions & 0 deletions amr-wind/utilities/subvolume/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
target_sources(${amr_wind_lib_name}
PRIVATE

Subvolume.cpp
RectangularSubvolume.cpp
)
63 changes: 63 additions & 0 deletions amr-wind/utilities/subvolume/RectangularSubvolume.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#ifndef LINESAMPLER_H
#define LINESAMPLER_H

#include "amr-wind/utilities/subvolume/SubvolumeBase.H"

namespace amr_wind::subvolume {

/** Get subvolume defined by 3D rectangle
* \ingroup subvolume
*
* Defines volume region with origin, number of points in each direction, and
* target mesh resolution in each direction. Also has an optional parameter
* regarding the data organization, which is the chunk size.
*/
class RectangularSubvolume
: public SubvolumeBase::Register<RectangularSubvolume>
{
public:
static std::string identifier() { return "Rectangular"; }

explicit RectangularSubvolume(const CFDSim& /*sim*/);

~RectangularSubvolume() override;

/** Read user inputs and initialize the subvolume object
*
* \param key Prefix used to parse inputs from file
*/
void initialize(const std::string& key) override;

//! Check if inputs have a valid correspondence in the mesh and save
//! quantities for output steps
void evaluate_inputs() override;

//! Name of this subvolume object
std::string label() const override { return m_label; }
std::string& label() override { return m_label; }

//! Type of this subvolume object
std::string subvolumetype() const override { return identifier(); }

int lev() const override { return m_lev_for_sub; }

amrex::BoxArray box_array() const override { return m_ba; }

protected:
const CFDSim& m_sim;

amrex::Vector<amrex::Real> m_origin;
amrex::Vector<int> m_npts_vec;
amrex::Vector<amrex::Real> m_dx_vec;
amrex::Vector<int> m_chunk_size_vec;

int m_lev_for_sub{0};

amrex::BoxArray m_ba;

std::string m_label;
};

} // namespace amr_wind::subvolume

#endif /* LINESAMPLER_H */
122 changes: 122 additions & 0 deletions amr-wind/utilities/subvolume/RectangularSubvolume.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#include "amr-wind/utilities/subvolume/RectangularSubvolume.H"
#include "amr-wind/utilities/constants.H"
#include "amr-wind/CFDSim.H"

#include "AMReX_ParmParse.H"

namespace amr_wind::subvolume {

RectangularSubvolume::RectangularSubvolume(const CFDSim& sim) : m_sim(sim) {}

RectangularSubvolume::~RectangularSubvolume() = default;

void RectangularSubvolume::initialize(const std::string& key)
{
amrex::ParmParse pp(key);

pp.getarr("origin", m_origin);
pp.getarr("num_points", m_npts_vec);
pp.getarr("dx_vec", m_dx_vec);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just dx?


m_chunk_size_vec.resize(AMREX_SPACEDIM);
m_chunk_size_vec[0] = m_sim.mesh().maxGridSize(0)[0];
m_chunk_size_vec[1] = m_sim.mesh().maxGridSize(0)[1];
m_chunk_size_vec[2] = m_sim.mesh().maxGridSize(0)[2];
pp.queryarr("chunk_size", m_chunk_size_vec);
}

void RectangularSubvolume::evaluate_inputs()
{
bool found = false;
const auto& geom = m_sim.mesh().Geom();
for (int i = 0; i < m_sim.repo().num_active_levels(); i++) {
if (!found) {
if (std::abs(m_dx_vec[0] - geom[i].CellSize(0)) < 1e-4 &&
std::abs(m_dx_vec[1] - geom[i].CellSize(1)) < 1e-4 &&
std::abs(m_dx_vec[2] - geom[i].CellSize(2)) < 1e-4) {

amrex::Print()
<< "RectangularSubvolume " + m_label +
": Resolution specified matches that of level "
<< i << std::endl;
found = true;
m_lev_for_sub = i;
}
}
}

if (!found) {
amrex::Abort(
"RectangularSubvolume " + m_label +
": Resolution specified for subvolume does not match the "
"resolution "
"of any of the mesh levels.");
}

// **************************************************************
// Now that we know which level we're at, we can figure out which (i,j,k)
// the origin corresponds to Note we use 1.0001 as a fudge factor since the
// division of two reals --> integer will do a floor
// **************************************************************
int i0 = static_cast<int>(
(m_origin[0] - geom[m_lev_for_sub].ProbLo(0)) * 1.0001 /
geom[m_lev_for_sub].CellSize(0));
int j0 = static_cast<int>(
(m_origin[1] - geom[m_lev_for_sub].ProbLo(1)) * 1.0001 /
geom[m_lev_for_sub].CellSize(1));
int k0 = static_cast<int>(
(m_origin[2] - geom[m_lev_for_sub].ProbLo(2)) * 1.0001 /
geom[m_lev_for_sub].CellSize(2));

found = false;
if (std::abs(
geom[m_lev_for_sub].ProbLo(0) +
i0 * geom[m_lev_for_sub].CellSize(0) - m_origin[0]) < 1e-4 &&
std::abs(
geom[m_lev_for_sub].ProbLo(1) +
j0 * geom[m_lev_for_sub].CellSize(1) - m_origin[1]) < 1e-4 &&
std::abs(
geom[m_lev_for_sub].ProbLo(2) +
k0 * geom[m_lev_for_sub].CellSize(2) - m_origin[2]) < 1e-4) {
amrex::Print()
<< "RectangularSubvolume " + m_label +
": Specified origin is the lower left corner of cell "
<< amrex::IntVect(i0, j0, k0) << std::endl;
found = true;
}

if (!found) {
amrex::Abort(
"RectangularSubvolume " + m_label +
": Origin specified does not correspond to a node at this level.");
}

amrex::Box domain(geom[m_lev_for_sub].Domain());

amrex::Box bx(
amrex::IntVect(i0, j0, k0),
amrex::IntVect(
i0 + m_npts_vec[0] - 1, j0 + m_npts_vec[1] - 1,
k0 + m_npts_vec[2] - 1));
amrex::Print() << "RectangularSubvolume " + m_label + ": Box requested is "
<< bx << std::endl;

if (!domain.contains(bx)) {
amrex::Abort(
"RectangularSubvolume " + m_label +
": Box requested is larger than the existing domain");
}

amrex::IntVect chunk_size(
m_chunk_size_vec[0], m_chunk_size_vec[1], m_chunk_size_vec[2]);

amrex::BoxArray ba(bx);
ba.maxSize(chunk_size);

amrex::Print() << "RectangularSubvolume " + m_label + ": BoxArray is " << ba
<< std::endl;

m_ba = ba;
}

} // namespace amr_wind::subvolume
96 changes: 96 additions & 0 deletions amr-wind/utilities/subvolume/Subvolume.H
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#ifndef SUBVOLUME_H
#define SUBVOLUME_H

#include <memory>

#include "amr-wind/CFDSim.H"
#include "amr-wind/utilities/DerivedQuantity.H"
#include "amr-wind/utilities/PostProcessing.H"
#include "amr-wind/utilities/subvolume/SubvolumeBase.H"
#include <AMReX_PlotFileUtil.H>

/**
* \defgroup subvolume Mesh data subvolume utilities
* Mesh data subvolume utilities
*
* Subvolume is a data-retrieval tool designed to obtain partitions (chunks)
* directly from the AMR-Wind computational mesh. It is distinct from the
* sampling utilities because it does not use particles and is therefore
* confined to the actual cell locations; however, it is another way to sample
* data from the simulation. In essence, subvolume outputs are like plotfiles
* but only contain a portion of the domain.
*
* \ingroup utilities
*/

namespace amr_wind::subvolume {

class Subvolume : public PostProcessBase::Register<Subvolume>
{
public:
static std::string identifier() { return "Subvolume"; }

Subvolume(CFDSim& /*sim*/, std::string /*label*/);

~Subvolume() override;

//! Perform actions before mesh is created
void pre_init_actions() override {}

//! Read user inputs for chunks, output timing
void initialize() override;

//! Do any work that needs to happen after regrid
void post_regrid_actions() override;

//! Get chunks and output to disk
void post_advance_work() override;

void write_subvolume();

const amrex::Vector<std::string>& var_names() const { return m_var_names; }

protected:
private:
CFDSim& m_sim;

amrex::Vector<std::unique_ptr<SubvolumeBase>> m_subvolumes;

//! List of variable names for output
amrex::Vector<std::string> m_var_names;

//! List of fields to be sampled for this collection of probes
amrex::Vector<Field*> m_fields;

//! List of IntFields to be sampled for this collection of probes
amrex::Vector<IntField*> m_int_fields;

//! List of derived fields to be sampled for this collection of probes
std::unique_ptr<DerivedQtyMgr> m_derived_mgr;

/** Name of this subvolume object.
*
* The label is used to read user inputs from file and is also used for
* naming files directories.
*/
const std::string m_label;

// number of field components
int m_ncomp{0};

// number of int field components
int m_nicomp{0};

// number of derived field components
int m_ndcomp{0};

//! Frequency of data output
int m_out_freq{100};

//! Delay number of timestep before output
int m_out_delay{0};
};

} // namespace amr_wind::subvolume

#endif /* SUBVOLUME_H */
Loading
Loading