Phyth v0.1.0
A dimensional safe C++ header-only mechanics and electromagnetics simulation library.
Loading...
Searching...
No Matches
VolumeForce.hpp
Go to the documentation of this file.
1#ifndef PHYTH_VOLUME_FORCE_HPP
2#define PHYTH_VOLUME_FORCE_HPP
3
4#include "ForceSource.hpp"
7
8namespace Phyth::Mechanics {
24 class VolumeForce : public ForceSource {
25 public:
51
60 ) const override {
61 return NumericalIntegrateStress(point, 16, 16, 16);
62 }
63
71 ) const override {
72 return {};
73 }
74
82 }
83
92 ) const override {
93 const auto half_w = width_ / 2.0;
94 const auto half_h = height_ / 2.0;
95 const auto half_d = depth_ / 2.0;
96
97 if (const auto local = point - center_; Utils::abs(local.x) <= half_w &&
98 Utils::abs(local.y) <= half_h &&
99 Utils::abs(local.z) <= half_d) {
100 return force_density_;
101 }
102 return {};
103 }
104
113 ) const override {
114 const auto half_w = width_ / 2.0;
115 const auto half_h = height_ / 2.0;
116 const auto half_d = depth_ / 2.0;
117
118 const auto local = point - center_;
119 const auto dx = std::clamp(local.x, -half_w, half_w);
120 const auto dy = std::clamp(local.y, -half_h, half_h);
121 const auto dz = std::clamp(local.z, -half_d, half_d);
122
123 const auto closest = center_ + Vector3<Quantity<Meter>>(dx, dy, dz);
124 return (point - closest).Length();
125 }
126
133
140
141 private:
146
155 const int nx,
156 const int ny,
157 const int nz
158 ) const {
160
161 const auto poisson_ratio = material_.GetPoissonRatio();
162 const auto prefactor = -1.0 / (8.0 * Consts::pi * (1.0 - poisson_ratio));
163
164 const auto dx = width_ / nx;
165 const auto dy = height_ / ny;
166 const auto dz = depth_ / nz;
167 const auto dV = dx * dy * dz;
168 const auto dF = force_density_ * dV;
169
170 const auto half_w = width_ / 2.0;
171 const auto half_h = height_ / 2.0;
172 const auto half_d = depth_ / 2.0;
173
174 for (int i = 0; i < nx; ++i) {
175 for (int j = 0; j < ny; ++j) {
176 for (int k = 0; k < nz; ++k) {
177 const auto x = (i + 0.5) / nx * width_ - half_w;
178 const auto y = (j + 0.5) / ny * height_ - half_h;
179 const auto z = (k + 0.5) / nz * depth_ - half_d;
180
181 const auto pos = center_ + Vector3<Quantity<Meter>>(x, y, z);
182 const auto R = point - pos;
183 const auto R_mag = R.Length();
184
186 continue;
187 }
188
189 const auto R3 = R_mag * R_mag * R_mag;
190 const auto R5 = R3 * R_mag * R_mag;
191
192 const auto one_minus_2nu = 1.0 - 2.0 * poisson_ratio;
193 const auto dF_dot_R = dF.Dot(R);
194
195 for (int m = 0; m < 3; ++m) {
196 for (int n = 0; n < 3; ++n) {
197 const auto term1 = one_minus_2nu * (
198 dF[m] * R[n] + dF[n] * R[m]
199 - (m == n ? 1.0 : 0.0) * dF_dot_R
200 ) / R3;
201
202 const auto term2 = 3.0 * dF_dot_R * R[m] * R[n] / R5;
203
204 stress(m, n) += prefactor * (term1 - term2);
205 }
206 }
207 }
208 }
209 }
210
211 return stress;
212 }
213 };
214}
215
216#endif // PHYTH_VOLUME_FORCE_HPP
Linear elastic isotropic material model.
Scalar GetPoissonRatio() const
Get Poisson's ratio.
Abstract base class for all force/traction distributions.
Uniform body force distributed over a rectangular box.
Vector3< Quantity< Newton > > GetTotalForce() const override
Get the total force of this source.
Matrix3x3< Quantity< Pascal > > NumericalIntegrateStress(const Vector3< Quantity< Meter > > &point, const int nx, const int ny, const int nz) const
Numerical integration of stress over the volume.
void SetForceDensity(const Vector3< Quantity< NewtonPerMeterCubed > > &force_density)
Set the force density vector.
Vector3< Quantity< NewtonPerMeterCubed > > force_density_
Vector3< Quantity< NewtonPerMeterCubed > > GetBodyForceDensityAt(const Vector3< Quantity< Meter > > &point) const override
Get the body force density at a point.
Vector3< Quantity< NewtonPerMeterCubed > > GetForceDensity() const
Get the force density vector.
Quantity< Meter > GetMinimumDistanceTo(const Vector3< Quantity< Meter > > &point) const override
Get the minimum distance from a point to the rectangular volume.
Matrix3x3< Quantity< Pascal > > GetStressAt(const Vector3< Quantity< Meter > > &point) const override
Compute stress tensor at a point using numerical integration.
Vector3< Quantity< Meter > > center_
Vector3< Quantity< Newton > > GetForceAt(const Vector3< Quantity< Meter > > &point) const override
Get the force vector at a point.
VolumeForce(const Vector3< Quantity< Meter > > &center, const Quantity< Meter > width, const Quantity< Meter > height, const Quantity< Meter > depth, const Vector3< Quantity< NewtonPerMeterCubed > > &force_density, const IsotropicMaterial &material) noexcept
Construct a rectangular volume force.
double epsilon
Definition Config.hpp:13
constexpr double pi
Definition Constants.hpp:5
auto abs(Quantity< UnitT > q)
Absolute value of a quantity.
constexpr bool is_unit_v
Definition Unit.hpp:79
3x3 matrix with Quantity components
Definition Matrix3x3.hpp:27
Physical quantity with a value and a compile-time unit.
Definition Quantity.hpp:27
3D vector with Quantity components
Definition Vector3.hpp:28
auto Length() const
Euclidean length (magnitude)
Definition Vector3.hpp:358