FhSim  3.1.0
Marine systems simulation
Loading...
Searching...
No Matches
WakeBlend.h
1#pragma once
4
5#include <marenv/AtomicSharedPtr.h>
6#include <marenv/wake/WakeField.h>
7#include <marenv/wake/WakeTypes.h>
8
9#include <atomic>
10#include <concepts>
11#include <cstdint>
12#include <memory>
13#include <stdexcept>
14
15namespace marenv::wake
16{
24template<class S, class Value>
25concept BlendSnapshot = requires(const S& snapshot, double t, const double* pos, Value& out) {
26 { snapshot.Sample(t, pos, out) } -> std::convertible_to<bool>;
27};
28
32template<class S>
34
66template<class S, class Value = WakeSample, class SumType = WakeBlendSum, class SamplesType = WakeBlendSamples>
69{
70public:
72 struct State
73 {
74 std::shared_ptr<const S> current;
75 std::shared_ptr<const State> previous;
76 double start;
77 double time;
78 };
79
81 using Sum = SumType;
82
84 static double Weight(double t, double start, double time) { return BlendWeight(t, start, time); }
85
87 [[nodiscard]] std::shared_ptr<const State> Load() const { return m_state.load(); }
88
96 void Publish(std::shared_ptr<const S> next, double start, double time)
97 {
98 const auto inUse = Load();
99 if (inUse && inUse->start + inUse->time > start)
100 throw std::logic_error("WakeBlend::Publish: the previous blend has not ended (R22)");
101 auto previous = inUse && time > 0.0 ? Settled(inUse->current) : nullptr;
102 Install(std::move(next), std::move(previous), start, time);
103 }
104
106 static Sum Evaluate(const State& state, double t, const double pos[3])
107 {
108 return Evaluate(state, t, pos, SampleSnapshot);
109 }
110
117 template<class Sampler>
118 static Sum Evaluate(const State& state, double t, const double pos[3], const Sampler& sample)
119 {
120 Sum sum;
121 const double weight = Weight(t, state.start, state.time);
122 Value value {};
123 if (weight > 0.0 && sample(*state.current, t, pos, value))
124 sum.Add(weight, value);
125 if (weight < 1.0 && state.previous) {
126 const Sum previous = Evaluate(*state.previous, t, pos, sample);
127 if (previous.inside)
128 sum.Add(1.0 - weight, previous);
129 }
130 return sum;
131 }
132
134 static bool Blends(const State& state, double t) { return Weight(t, state.start, state.time) < 1.0; }
135
137 [[nodiscard]] std::uint64_t Revision() const { return m_revision.load(std::memory_order_acquire); }
138
143 bool StaticFrom(double t) const
144 {
145 const auto state = Load();
146 return !state || (!Blends(*state, t) && state->current->Stationary());
147 }
148
156 static SamplesType Samples(const State& state, double t, const double pos[3])
157 {
158 return Samples(state, t, pos, SampleSnapshot);
159 }
160
162 template<class Sampler>
163 static SamplesType Samples(const State& state, double t, const double pos[3], const Sampler& sample)
164 {
165 SamplesType samples;
166 samples.currentInside = sample(*state.current, t, pos, samples.current);
167 if (state.previous)
168 samples.previous = Evaluate(*state.previous, t, pos, sample);
169 samples.start = state.start;
170 samples.time = state.time;
171 return samples;
172 }
173
181 static bool MayReach(const State& state, const WakeQueryRegion& region)
182 {
183 const bool previousSampled = state.previous && Weight(region.tBegin, state.start, state.time) < 1.0;
184 return state.current->MayReach(region) || (previousSampled && MayReach(*state.previous, region));
185 }
186
187private:
189 static bool SampleSnapshot(const S& snapshot, double t, const double pos[3], Value& out) { return snapshot.Sample(t, pos, out); }
190
192 static std::shared_ptr<const State> Settled(std::shared_ptr<const S> snapshot)
193 {
194 return std::make_shared<const State>(State {std::move(snapshot), nullptr, 0.0, 0.0});
195 }
196
204 void Install(std::shared_ptr<const S> next, std::shared_ptr<const State> previous, double start, double time)
205 {
206 m_state.store(std::make_shared<const State>(State {std::move(next), std::move(previous), start, time}));
207 m_revision.fetch_add(1, std::memory_order_release);
208 }
209
210 AtomicSharedPtr<const State> m_state;
211 std::atomic<std::uint64_t> m_revision {0};
212};
213} // namespace marenv::wake
Definition WakeBlend.h:69
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:84
std::uint64_t Revision() const
The number of publishes so far (WakeField::Revision()).
Definition WakeBlend.h:137
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:87
void Publish(std::shared_ptr< const S > next, double start, double time)
Definition WakeBlend.h:96
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:134
static SamplesType Samples(const State &state, double t, const double pos[3])
Definition WakeBlend.h:156
static bool MayReach(const State &state, const WakeQueryRegion &region)
Definition WakeBlend.h:181
SumType Sum
The sums over the snapshots that contributed at one point.
Definition WakeBlend.h:81
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:106
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:163
static Sum Evaluate(const State &state, double t, const double pos[3], const Sampler &sample)
Definition WakeBlend.h:118
bool StaticFrom(double t) const
Definition WakeBlend.h:143
Definition WakeBlend.h:25
Definition WakeBlend.h:33
double BlendWeight(double t, double start, double time)
Definition WakeSampleParts.h:13
One immutable step of the blend chain.
Definition WakeBlend.h:73
double start
Start of the blend, s.
Definition WakeBlend.h:76
std::shared_ptr< const S > current
The snapshot blended to.
Definition WakeBlend.h:74
double time
Duration of the blend, s; 0 means no blending.
Definition WakeBlend.h:77
std::shared_ptr< const State > previous
The state blended from; null means no wake.
Definition WakeBlend.h:75
Definition WakeField.h:23
double tBegin
First query time, s.
Definition WakeField.h:26