|
FhSim
3.1.0
Marine systems simulation
|
#include <SourceSetWake.h>
Inheritance diagram for marenv::wake::SourceSetWake:
Collaboration diagram for marenv::wake::SourceSetWake:Public Member Functions | |
| SourceSetWake ()=default | |
| A field whose sources compose with the default KernelParams. | |
| SourceSetWake (const KernelParams ¶ms) | |
| void | Publish (SourceSet sources, const double velocity[3], double t0, double blendTime, double seabedDepth) |
| Status | Sample (double t, const double pos[3], WakeSample &out) const override |
| bool | MayReach (const WakeQueryRegion ®ion) const override |
| WakeSampleParts | SampleParts (double t, const double pos[3]) const override |
Wake field of point and line sources by direct evaluation, cross-faded from one published source set to the next (contract C4).
The field of a wake-casting object's lumped source, of a net's private field in the Direct evaluation, of a fixed analytic source (fhsim_environment's PorousDiscWakeSource) and the reference against which a gridded wake is judged. Sample() evaluates ElementaryDeficit() of every point source and LineDeficit() of every line source at the query point and composes them by params.superposition (lead ruling R88, owner ruling R95): Product, deficit = 1 - prod(1 - d_i) (the default; a net's private field), or MomentumFlux, deficit (1 - deficit) = sum d_i (1 - d_i) (MomentumFluxSum; the lumped fields, LumpedKernel()). Each source has the images of MirrorImages(params): a mirror image at the free surface and one at the seabed (owner ruling R53) and, with both planes, the image of each at the other plane (R98). An image's deficit at pos is the source's deficit at the image's query depth of pos, composed in by the same rule. The cost of a query is O(N) kernel evaluations per source and image (up to 5 per source); each source's KernelProfile is built once per publish (MENV-0036).
One Publish(SourceSet, velocity, t0, blendTime, seabedDepth) moves the sources with velocity (a source given at p is at p + velocity (t - t0) at time t), drags the water at velocity (u_s) and starts the blend at t0, so a wake cannot travel at one velocity and drag the water at another; the seabed depth of the images (R53) is per publish. A source fixed in space is published with velocity 0.
Blending (WakeBlend): the field cross-fades from the source set in use to the new one over blendTime from t0, with the C1 smoothstep s = 3 tau^2 - 2 tau^3, tau = (t - t0) / blendTime. The weights act on the waked velocity: d = (1 - s) d_old + s d_new, and d u_s is blended the same way; the source velocity is d u_s / d, or zero where d = 0. The first source set fades in from no wake (outside the field before t0); a blend time of 0 replaces the set in use at once, for every t. Publish() refuses a new blend while the previous one is still running (lead ruling R22, WakeBlend::Publish()), so a state blends from the previous source set alone and no blend chain forms.
Thread safety (see WakeField::Sample): register the field during setup only. After that one writer thread may call Publish() concurrently with readers; Sample() is const and thread-safe. Publish() builds a new immutable blend state, which holds the source sets' snapshots directly, and swaps it in through std::atomic<std::shared_ptr<const ...>>, the pattern of GriddedWake, so a query does one atomic load (MENV-0025) and a query running concurrently with Publish() evaluates either the old or the new state, never a mix. Keep to one writer. Sample() takes no mutex; the libstdc++ spin bit of the atomic shared pointer is the known caveat.
|
explicit |
|
overridevirtual |
Returns false only if the published state contributes nothing in the region (see WakeField::MayReach).
A source set may reach the region unless, at the exact tier (region.cutoff = 0), the whole sphere, swept back by the sources' translation over the interval, lies upstream of x_start of every source, where the kernel is 0; or, at the cutoff tier, the sum over the sources of a bound of the kernel over that sphere (the largest centreline amplitude over its x range times the Gaussian at its smallest distance from the axis and the largest sigma) is below region.cutoff; the composed deficit is at most that sum (MomentumFluxBound() of it for MomentumFlux). The images (R53, R98) are bounded the same way, as their sources over the region moved to each image's query depth. The blended deficit is at most the larger of the two source sets' deficits, so the field may reach the region when a source set it samples in [region.tBegin, region.tEnd] or later may: the set blended to from its publish instant on (owner ruling R136, for held SampleParts()), the set blended from until the blend has ended by tBegin. True before the first Publish().
Reimplemented from marenv::wake::WakeField.
| void marenv::wake::SourceSetWake::Publish | ( | SourceSet | sources, |
| const double | velocity[3], | ||
| double | t0, | ||
| double | blendTime, | ||
| double | seabedDepth | ||
| ) |
Publishes a source set, blended in from the one in use (MENV-0058).
| [in] | sources | The point and line sources, world NED at t0; each flowDir (and axis) is normalised. An empty set gives a zero deficit. |
| [in] | velocity | Velocity of the sources, m/s, NED: they translate with it from t0 on and drag the water at it (u_s). |
| [in] | t0 | Time at which the sources are at their given positions and the blend starts, s. |
| [in] | blendTime | Duration of the cross-fade, s; 0 switches at once. |
| [in] | seabedDepth | Depth of the seabed image plane (R53), m; infinity: no seabed image. It replaces KernelParams::seabedDepth of the constructor's params for this publish, so every caller gives it (there is no default: a params.seabedDepth would be lost silently). |
| std::logic_error | if the previous blend has not ended by t0 (R22, WakeBlend::Publish()). |
| std::invalid_argument | for a negative blend time, a non-finite t0 or velocity, a seabed depth for which Validate() throws, a point source with a non-finite position, area or momentum deficit, a non-positive area, a negative momentum deficit or a zero flowDir (MENV-0047, MENV-0049), or a line source with a non-finite or non-positive length or width, a negative momentum deficit, a zero flowDir or axis, or an axis parallel to flowDir (LineKernelProfile, MENV-0044). A throwing Publish() leaves the field in use unchanged. |
|
overridevirtual |
Returns the blended deficit and source velocity at pos (see WakeField::Sample).
| [in] | t | Simulation time, s. |
| [in] | pos | Position (x,y,z) to query, m, NED. |
| [out] | out | Deficit in [0, 1] and deficit-weighted source velocity. |
Implements marenv::wake::WakeField.
|
overridevirtual |
Returns the sample split into the parts the blend weighs (see WakeField::SampleParts; owner ruling R136).
While the published state blends at t or later, the parts hold the sample of the set blended to and of the set blended from at (t, pos); otherwise Sample(t, pos).
Reimplemented from marenv::wake::WakeField.