55 lines
2.7 KiB
C++
55 lines
2.7 KiB
C++
#pragma once
|
|
#include "FluidSim/PipeProfile.hpp"
|
|
|
|
namespace fluidsim::port {
|
|
enum class SilencerType { StraightThrough, ExpansionResonator, Chambered };
|
|
struct SilencerConfig {
|
|
SilencerType type{SilencerType::Chambered};
|
|
float volume{.018f}, length{.65f}, core_diameter{.055f};
|
|
int chambers{2};
|
|
float passage_diameter{.058f};
|
|
float resistance{2.f}; // linear momentum decay, 1/s (packing surrogate)
|
|
float loss_coefficient{.35f}; // total dimensionless quadratic flow resistance
|
|
float diameter() const { return std::sqrt(4*volume/(pi*length)); }
|
|
};
|
|
struct ExhaustConfig {
|
|
bool enabled{true};
|
|
float inlet_length{1.4f}, outlet_length{.35f}, connecting_length{.8f}, diameter{.060f}, cell_length{.035f};
|
|
SilencerConfig resonator{SilencerType::StraightThrough,.006f,.40f,.060f,1,.060f,2, .1f};
|
|
SilencerConfig muffler{SilencerType::StraightThrough,.018f,.65f,.060f,1,.060f,4, .35f};
|
|
};
|
|
inline Pipe1D make_silenced_exhaust(const ExhaustConfig& c) {
|
|
std::vector<PipeSection> sections;
|
|
std::vector<float> linear, quadratic;
|
|
auto add=[&](float length,float a,float b,float r=0,float k=0) {
|
|
if(!std::isfinite(length)||length<=0||!std::isfinite(r)||r<0||!std::isfinite(k)||k<0)
|
|
throw std::invalid_argument("invalid silencer resistance or length");
|
|
sections.push_back({length,a,b}); linear.push_back(r); quadratic.push_back(k/length);
|
|
};
|
|
add(c.inlet_length,c.diameter,c.diameter);
|
|
if(c.enabled) for(int index=0;index<2;++index) {
|
|
if(index) add(c.connecting_length,c.diameter,c.diameter);
|
|
const auto& s=index?c.muffler:c.resonator;
|
|
if(!std::isfinite(s.volume)||s.volume<=0||!std::isfinite(s.length)||s.length<=0||s.chambers<1||s.chambers>16 || s.core_diameter<=0 || s.passage_diameter<=0)
|
|
throw std::invalid_argument("invalid silencer geometry");
|
|
const float d=s.type==SilencerType::StraightThrough?s.core_diameter:s.diameter();
|
|
const int n=s.type==SilencerType::Chambered?s.chambers:1;
|
|
float previous=c.diameter;
|
|
for(int i=0;i<n;++i) {
|
|
add(s.length*.1f/n,previous,d,s.resistance,s.loss_coefficient*.5f/n);
|
|
add(s.length*.8f/n,d,d,s.resistance,0);
|
|
const float end=i+1==n?c.diameter:s.passage_diameter;
|
|
add(s.length*.1f/n,d,end,s.resistance,s.loss_coefficient*.5f/n);
|
|
previous=end;
|
|
}
|
|
}
|
|
add(c.outlet_length,c.diameter,c.diameter);
|
|
auto pipe=make_profiled_pipe(sections,c.cell_length);
|
|
for(std::size_t i=0;i<sections.size();++i) {
|
|
const int n=profile_section_cells(sections[i].length,c.cell_length);
|
|
for(int j=0;j<n;++j) { pipe.linear_resistance.push_back(linear[i]);pipe.quadratic_resistance.push_back(quadratic[i]); }
|
|
}
|
|
return pipe;
|
|
}
|
|
}
|