FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
WakeBlend.h
1#pragma once
4
5#include <marenv/wake/WakeField.h>
6#include <marenv/wake/WakeTypes.h>
7
8#include <atomic>
9#include <concepts>
10#include <cstdint>
11#include <memory>
12#include <stdexcept>
13
14namespace marenv::wake
15{
23template<class S, class Value>
24concept BlendSnapshot = requires(const S& snapshot, double t, const double* pos, Value& out) {
25 { snapshot.Sample(t, pos, out) } -> std::convertible_to<bool>;
26};
27
31template<class S>
33
65template<class S, class Value = WakeSample, class SumType = WakeBlendSum, class SamplesType = WakeBlendSamples>
68{
69public:
71 struct State
72 {
73 std::shared_ptr<const S> current;
74 std::shared_ptr<const State> previous;
75 double start;
76 double time;
77 };
78
80 using Sum = SumType;
81
83 static double Weight(double t, double start, double time) { return BlendWeight(t, start, time); }
84
86 [[nodiscard]] std::shared_ptr<const State> Load() const { return m_state.load(); }
87
95 void Publish(std::shared_ptr<const S> next, double start, double time)
96 {
97 const auto inUse = Load();
98 if (inUse && inUse->start + inUse->time > start)
99 throw std::logic_error("WakeBlend::Publish: the previous blend has not ended (R22)");
100 auto previous = inUse && time > 0.0 ? Settled(inUse->current) : nullptr;
101 Install(std::move(next), std::move(previous), start, time);
102 }
103
105 static Sum Evaluate(const State& state, double t, const double pos[3])
106 {
107 return Evaluate(state, t, pos, SampleSnapshot);
108 }
109
116 template<class Sampler>
117 static Sum Evaluate(const State& state, double t, const double pos[3], const Sampler& sample)
118 {
119 Sum sum;
120 const double weight = Weight(t, state.start, state.time);
121 Value value {};
122 if (weight > 0.0 && sample(*state.current, t, pos, value))
123 sum.Add(weight, value);
124 if (weight < 1.0 && state.previous) {
125 const Sum previous = Evaluate(*state.previous, t, pos, sample);
126 if (previous.inside)
127 sum.Add(1.0 - weight, previous);
128 }
129 return sum;
130 }
131
133 static bool Blends(const State& state, double t) { return Weight(t, state.start, state.time) < 1.0; }
134
136 [[nodiscard]] std::uint64_t Revision() const { return m_revision.load(std::memory_order_acquire); }
137
142 bool StaticFrom(double t) const
143 {
144 const auto state = Load();
145 return !state || (!Blends(*state, t) && state->current->Stationary());
146 }
147
155 static SamplesType Samples(const State& state, double t, const double pos[3])
156 {
157 return Samples(state, t, pos, SampleSnapshot);
158 }
159
161 template<class Sampler>
162 static SamplesType Samples(const State& state, double t, const double pos[3], const Sampler& sample)
163 {
164 SamplesType samples;
165 samples.currentInside = sample(*state.current, t, pos, samples.current);
166 if (state.previous)
167 samples.previous = Evaluate(*state.previous, t, pos, sample);
168 samples.start = state.start;
169 samples.time = state.time;
170 return samples;
171 }
172
180 static bool MayReach(const State& state, const WakeQueryRegion& region)
181 {
182 const bool previousSampled = state.previous && Weight(region.tBegin, state.start, state.time) < 1.0;
183 return state.current->MayReach(region) || (previousSampled && MayReach(*state.previous, region));
184 }
185
186private:
188 static bool SampleSnapshot(const S& snapshot, double t, const double pos[3], Value& out) { return snapshot.Sample(t, pos, out); }
189
191 static std::shared_ptr<const State> Settled(std::shared_ptr<const S> snapshot)
192 {
193 return std::make_shared<const State>(State {std::move(snapshot), nullptr, 0.0, 0.0});
194 }
195
203 void Install(std::shared_ptr<const S> next, std::shared_ptr<const State> previous, double start, double time)
204 {
205 m_state.store(std::make_shared<const State>(State {std::move(next), std::move(previous), start, time}));
206 m_revision.fetch_add(1, std::memory_order_release);
207 }
208
209 std::atomic<std::shared_ptr<const State>> m_state;
210 std::atomic<std::uint64_t> m_revision {0};
211};
212} // namespace marenv::wake
Definition WakeBlend.h:68
static double Weight(double t, double start, double time)
Smoothstep weight of the new snapshot at t; 1 without blending (time <= 0 or NaN)....
Definition WakeBlend.h:83
std::uint64_t Revision() const
The number of publishes so far (WakeField::Revision()).
Definition WakeBlend.h:136
std::shared_ptr< const State > Load() const
The published state, one atomic load; null before the first Publish(). A query loads it once and uses...
Definition WakeBlend.h:86
void Publish(std::shared_ptr< const S > next, double start, double time)
Definition WakeBlend.h:95
static bool Blends(const State &state, double t)
Whether the state blends at t or later: the weight of t is below 1, so it still changes (owner ruling...
Definition WakeBlend.h:133
static SamplesType Samples(const State &state, double t, const double pos[3])
Definition WakeBlend.h:155
static bool MayReach(const State &state, const WakeQueryRegion &region)
Definition WakeBlend.h:180
SumType Sum
The sums over the snapshots that contributed at one point.
Definition WakeBlend.h:80
static Sum Evaluate(const State &state, double t, const double pos[3])
The sums of the snapshots of state at pos and t, weighted by the blend.
Definition WakeBlend.h:105
static SamplesType Samples(const State &state, double t, const double pos[3], const Sampler &sample)
Samples() with each snapshot sampled by sample(snapshot, t, pos, value), as Evaluate(state,...
Definition WakeBlend.h:162
static Sum Evaluate(const State &state, double t, const double pos[3], const Sampler &sample)
Definition WakeBlend.h:117
bool StaticFrom(double t) const
Definition WakeBlend.h:142
Definition WakeBlend.h:24
Definition WakeBlend.h:32
double BlendWeight(double t, double start, double time)
Definition WakeSampleParts.h:13
One immutable step of the blend chain.
Definition WakeBlend.h:72
double start
Start of the blend, s.
Definition WakeBlend.h:75
std::shared_ptr< const S > current
The snapshot blended to.
Definition WakeBlend.h:73
double time
Duration of the blend, s; 0 means no blending.
Definition WakeBlend.h:76
std::shared_ptr< const State > previous
The state blended from; null means no wake.
Definition WakeBlend.h:74
Definition WakeField.h:23
double tBegin
First query time, s.
Definition WakeField.h:26