11 #include <wx/button.h>
12 #include <wx/checkbox.h>
13 #include <wx/msgdlg.h>
15 #include <wx/spinctrl.h>
16 #include <wx/statbox.h>
17 #include <wx/stattext.h>
42 : wxPanel(parent, wxID_ANY, wxDefaultPosition, size)
45 wxBoxSizer* sizer =
new wxBoxSizer(wxVERTICAL);
47 wxBoxSizer* countSizer =
new wxBoxSizer(wxHORIZONTAL);
48 countSizer->Add(
new wxStaticText(
this, wxID_ANY,
"Number of fragments"));
49 countSpinner =
new wxSpinCtrl(
this, wxID_ANY);
50 countSpinner->SetValue(4);
51 countSizer->Add(countSpinner);
52 sizer->Add(countSizer);
54 wxGridSizer* boxSizer =
new wxGridSizer(4, 2, 2);
65 wxStaticBox* moonGroup =
new wxStaticBox(
this, wxID_ANY,
"Moons", wxDefaultPosition, wxSize(-1, 60));
66 wxBoxSizer* moonSizer =
new wxBoxSizer(wxHORIZONTAL);
67 wxCheckBox* moonBox =
new wxCheckBox(moonGroup,
int(
CheckFlag::MOONS),
"Moon counts");
68 moonSizer->Add(moonBox);
69 moonSizer->AddSpacer(30);
70 moonSizer->Add(
new wxStaticText(moonGroup, wxID_ANY,
"Mass ratio limit"));
72 moonSizer->Add(limitSpinner);
73 limitSpinner->Enable(
false);
74 moonGroup->SetSizer(moonSizer);
75 moonSizer->AddSpacer(30);
76 moonSizer->Add(
new wxStaticText(moonGroup, wxID_ANY,
"Pericenter limit"));
78 moonSizer->Add(radiiSpinner);
79 radiiSpinner->Enable(
false);
80 moonGroup->SetSizer(moonSizer);
81 sizer->Add(moonGroup);
82 moonBox->Bind(wxEVT_CHECKBOX, [moonBox, limitSpinner, radiiSpinner](wxCommandEvent&) {
83 limitSpinner->Enable(moonBox->GetValue());
84 radiiSpinner->Enable(moonBox->GetValue());
87 wxBoxSizer* buttonSizer =
new wxBoxSizer(wxHORIZONTAL);
88 wxButton* computeButton =
new wxButton(
this, wxID_ANY,
"Compute");
89 buttonSizer->Add(computeButton);
91 wxButton* saveButton =
new wxButton(
this, wxID_ANY,
"Save to file");
92 saveButton->Enable(
false);
93 buttonSizer->Add(saveButton);
94 sizer->Add(buttonSizer);
96 this->SetSizer(sizer);
99 computeButton->Bind(wxEVT_BUTTON,
100 [
this, size, sizer, saveButton, limitSpinner, radiiSpinner](wxCommandEvent&
UNUSED(evt)) {
101 const Size checkCount = this->getCheckedCount();
102 if (checkCount == 0) {
103 wxMessageBox(
"No parameters selected",
"Fail", wxOK | wxCENTRE);
106 if (grid !=
nullptr) {
108 this->RemoveChild(grid);
110 grid =
new wxGrid(
this, wxID_ANY, wxDefaultPosition, size);
111 grid->EnableEditing(
false);
113 grid->CreateGrid(countSpinner->GetValue(), checkCount);
115 saveButton->Enable(
true);
118 config.moonLimit = limitSpinner->
getValue();
119 config.radiiLimit = radiiSpinner->
getValue();
120 this->update(this->storage, config);
123 saveButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) {
126 std::ofstream ofs(path->native());
128 for (
int col = 0; col < grid->GetNumberCols(); ++col) {
129 const wxString label = grid->GetColLabelValue(col);
130 ofs << std::string(
max(1, 26 -
int(label.size())),
' ') << label;
133 for (
int row = 0; row < grid->GetNumberRows(); ++row) {
135 for (
int col = 0; col < grid->GetNumberCols(); ++col) {
136 ofs << std::setw(25) << grid->GetCellValue(row, col) <<
" ";
145 if (thread.joinable()) {
173 for (
Size i = 0; i < indices.
size(); ++i) {
174 if (indices[i] != idx) {
183 if (lazy.masses.empty()) {
184 this->computeIntegrals();
190 if (lazy.positions.empty()) {
191 this->computeIntegrals();
193 return lazy.positions;
197 if (lazy.velocities.empty()) {
198 this->computeIntegrals();
200 return lazy.velocities;
204 void computeIntegrals()
const {
205 lazy.masses.resizeAndSet(maxIdx, 0._f);
206 lazy.positions.resizeAndSet(maxIdx,
Vector(0._f));
207 lazy.velocities.resizeAndSet(maxIdx,
Vector(0._f));
215 for (
Size i = 0; i < indices.
size(); ++i) {
216 lazy.masses[indices[i]] += m[i];
217 lazy.positions[indices[i]] += m[i] * r[i];
218 lazy.velocities[indices[i]] += m[i] * v[i];
219 radii[indices[i]] +=
pow<3>(r[i][
H]);
221 for (
Size k = 0; k < maxIdx; ++k) {
222 lazy.positions[k] /= lazy.masses[k];
223 lazy.positions[k][
H] =
cbrt(radii[k]);
224 lazy.velocities[k] /= lazy.masses[k];
231 return { 0._f, 0._f };
237 Float diameter = 0._f;
238 for (
Size i = 0; i < m.
size(); ++i) {
240 diameter += m[i] / rho[i];
242 diameter =
cbrt(3._f * diameter / (4._f *
PI)) * 2._f;
243 return { mass, diameter };
257 SPH_ASSERT(a > 0._f && b > 0._f && c > 0._f, a, b, c);
258 return { c / b, b / a };
272 for (
Size i = 0; i < m1.
size(); ++i) {
282 for (
Size i = 0; i < m2.
size(); ++i) {
287 return getLength(p1 / mtot1 - p2 / mtot2);
298 return 2._f *
PI / (3600._f * omega);
311 void GridPage::update(
const Storage& storage,
const Config& config) {
312 if (thread.joinable()) {
313 wxMessageBox(
"Computation in progress",
"Fail", wxOK | wxCENTRE);
320 wxCheckBox* box = this->getCheck(flag);
321 if (box->GetValue()) {
322 grid->SetColLabelValue(colIdx++, box->GetLabel());
328 const Size fragmentCnt = countSpinner->GetValue();
330 thread = std::thread([
this, &storage, fragmentCnt, checks, config] {
332 this->updateAsync(storage, fragmentCnt, checks, config);
333 }
catch (
const std::exception& e) {
335 wxMessageBox(
"Failed to compute fragment parameters.\n\n" + message,
"Fail", wxOK | wxCENTRE);
341 void GridPage::updateAsync(
const Storage& storage,
342 const Size fragmentCnt,
346 const Float totalMass = std::accumulate(m.
begin(), m.
end(), 0._f);
351 for (
Size i = 0; i < fragmentCnt; ++i) {
352 const Storage fragment = getter.getComponent(i);
367 const Pair<Float> massAndDiameter = getMassAndDiameter(fragment);
369 this->updateCell(i, colIdx++, massAndDiameter[0] / totalMass);
372 this->updateCell(i, colIdx++, massAndDiameter[1] / 1.e3_f);
377 this->updateCell(i, colIdx++, getVelocityDifference(fragment, lr));
381 const Float period = getPeriod(fragment);
382 this->updateCell(i, colIdx++, period);
386 const Pair<Float> ratios = getSemiaxisRatios(fragment);
388 this->updateCell(i, colIdx++, ratios[0]);
391 this->updateCell(i, colIdx++, ratios[1]);
404 getMoons(masses, positions, velocities, i, config.moonLimit, config.radiiLimit);
405 this->updateCell(i, colIdx++, count);
414 template <
typename T>
415 void GridPage::updateCell(
const Size rowIdx,
const Size colIdx,
const T& value) {
417 grid->SetCellValue(rowIdx, colIdx, std::to_string(value));
421 wxCheckBox* GridPage::getCheck(
const CheckFlag check)
const {
422 wxCheckBox* box =
dynamic_cast<wxCheckBox*
>(this->FindWindow(
int(check)));
427 Size GridPage::getCheckedCount()
const {
443 count += int(this->getCheck(
id)->GetValue());
#define SPH_ASSERT(x,...)
uint32_t Size
Integral type used to index arrays (by default).
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
NAMESPACE_SPH_BEGIN void executeOnMainThread(const Function< void()> &function)
Posts a callback to be executed on main thread.
Posting events to be executed on main thread.
constexpr INLINE T max(const T &f1, const T &f2)
INLINE Float cbrt(const Float f)
Returns a cubed root of a value.
INLINE T sqrt(const T f)
Return a squared root of a value.
constexpr INLINE Float pow< 3 >(const Float v)
constexpr Float PI
Mathematical constants.
#define NAMESPACE_SPH_END
Object representing a path on a filesystem, similar to std::filesystem::path in c++17.
@ POSITION
Positions (velocities, accelerations) of particles, always a vector quantity,.
@ DENSITY
Density, always a scalar quantity.
@ MASS
Paricles masses, always a scalar quantity.
Holder of quantity values and their temporal derivatives.
Interface for executing tasks (potentially) asynchronously.
StaticArray< T0 &, sizeof...(TArgs)+1 > tie(T0 &t0, TArgs &... rest)
Creates a static array from a list of l-value references.
Eigen eigenDecomposition(const SymmetricTensor &t)
Computes eigenvectors and corresponding eigenvalues of symmetric matrix.
Optional< Path > doSaveFileDialog(const std::string &title, Array< FileFormat > &&formats)
Random utility functions for drawing stuff to DC.
INLINE Float getLength(const Vector &v)
Returns the length of the vector. Enabled only for vectors of floating-point precision.
BasicVector< Float > Vector
INLINE TCounter size() const
INLINE Iterator< StorageType > begin()
INLINE Iterator< StorageType > end()
INLINE void push(U &&u)
Adds new element to the end of the array, resizing the array if necessary.
INLINE TCounter size() const noexcept
Storage getComponent(const Size idx)
ComponentGetter(const Storage &storage)
Array< Vector > positions
ArrayView< const Vector > getVelocities() const
Array< Vector > velocities
ArrayView< const Float > getMasses() const
ArrayView< const Vector > getPositions() const
Provides functionality for reading and writing configuration files.
constexpr INLINE bool has(const TEnum flag) const
Checks if the object has a given flag.
constexpr INLINE bool hasAny(const TEnum flag, const TArgs... others) const
Checks if the object has any of given flags.
INLINE void set(const TEnum flag)
Adds a single flag into the object. All previously stored flags are kept unchanged.
GridPage(wxWindow *parent, const wxSize size, const Storage &storage)
Wrapper of type value of which may or may not be present.
static const Settings & getDefaults()
\brief Returns a reference to object containing default values of all settings.
Array with fixed number of allocated elements.
INLINE TCounter size() const
Returns the current size of the array (number of constructed elements).
Container storing all quantities used within the simulations.
StaticArray< Array< TValue > &, 3 > getAll(const QuantityId key)
Retrieves quantity buffers from the storage, given its key and value type.
Array< TValue > & getDt(const QuantityId key)
Retrieves a quantity derivative from the storage, given its key and value type.
Size getParticleCnt() const
Returns the number of particles.
auto getValues(const QuantityId first, const QuantityId second, const TArgs... others)
Retrieves an array of quantities from the key.
@ INDICES_SORTED
Use if the given array is already sorted (optimization)
void remove(ArrayView< const Size > idxs, const Flags< IndicesFlag > flags=EMPTY_FLAGS)
Removes specified particles from the storage.
bool has(const QuantityId key) const
Checks if the storage contains quantity with given key.
Storage clone(const Flags< VisitorEnum > buffers) const
Clones specified buffers of the storage.
Array< TValue > & getValue(const QuantityId key)
Retrieves a quantity values from the storage, given its key and value type.
Symmetric tensor of 2nd order.
Creating code components based on values from settings.
@ VELOCITY_DIFFERENCE
Signal speed given by relative velocity projected to the positive vector, as in Valdarnini (2018),...
SharedPtr< IScheduler > getScheduler(const RunSettings &settings=RunSettings::getDefaults())
Vector getAngularFrequency(ArrayView< const Float > m, ArrayView< const Vector > r, ArrayView< const Vector > v, const Vector &r0, const Vector &v0, ArrayView< const Size > idxs=nullptr)
Computes the immediate vector of angular frequency of a rigid body.
@ OVERLAP
Specifies that overlapping particles belong into the same component.
Size findComponents(const Storage &storage, const Float particleRadius, const Flags< ComponentFlag > flags, Array< Size > &indices)
Finds and marks connected components (a.k.a. separated bodies) in the array of vertices.
SymmetricTensor getInertiaTensor(ArrayView< const Float > m, ArrayView< const Vector > r, const Vector &r0, ArrayView< const Size > idxs=nullptr)
Computes the total inertia tensor of particles with respect to given center.
Float getSphericity(IScheduler &scheduler, const Storage &strorage, const Float resolution=0.05_f)
Computes the sphericity coefficient of a body.
Size findMoonCount(ArrayView< const Float > m, ArrayView< const Vector > r, ArrayView< const Vector > v, const Size i, const Float radius=1._f, const Float limit=0._f)
Find the number of moons of given body.
Vector values
Eigenvalues.