Program Listing for File SpecsynLib.hpp

↰ Return to documentation for file (src/specsyn/SpecsynLib.hpp)

#ifndef SPECSYNLIB_HPP
#define SPECSYNLIB_HPP

#include "../utils/ThreadVec.hpp"
#include "Specsyn.hpp"
#include "SpecsynCommons.hpp"
#include <cstddef>
#include <mdspan> // NOLINT(misc-include-cleaner)
#include <string>
#include <vector>

namespace io
{
    class SimControls;
} // namespace io

namespace specsyn
{


    template <OOBPolicy Policy>
    class SpecsynLib : public Specsyn
    {
    public:

        explicit SpecsynLib(const io::SimControls& controls) :
            Specsyn(controls) { }

        [[nodiscard]] auto spec(const StarData& props, double feh) const
        -> std::vector<double> override = 0;

        virtual void resample(const std::vector<double>& wlNew);

        [[nodiscard]] static auto resample(const std::vector<double>& wl,
            const std::vector<double>& wlNew, const std::vector<double>& spectrum)
        -> std::vector<double>;

    protected:

        using SpectraGrid = std::mdspan<std::vector<double>, std::dextents<std::size_t, 3>>; // NOLINT(misc-include-cleaner) -- <mdspan> is already included above; clang-tidy-18's libc++-18 header-mapping data doesn't yet recognize it as std::mdspan/std::dextents' canonical header

        [[nodiscard]] virtual auto spec(double d1, double d2, double d3) const -> std::vector<double>;

        [[nodiscard]] static auto outOfBoundsResult(const std::string& message) -> std::vector<double>;

        std::vector<double> dim1_;
        std::vector<double> dim2_;
        std::vector<double> dim3_;
        std::vector<std::vector<double>> spectra_;

        SpectraGrid grid_;

    private:

        // Cached bracket indices for search acceleration, one per
        // tensor-grid axis, exactly as interp::Mesh2DGrid caches
        // iSave_/jSave_: the common calling pattern is a long series
        // of spec() queries at (d1, d2, d3) points that are sorted or
        // nearly sorted along each axis (e.g. a series of stars fed
        // through in Teff/logg order), so the bracket found for one
        // query is usually still correct, or nearly so, for the next
        // one. Caching it lets findBracket (utils::findBracket, in
        // src/utils/GridBracket.cpp) skip the binary search entirely
        // on a cache hit, and narrow its search range on a miss, rather than
        // always searching the full axis from scratch. ThreadVec's,
        // rather than plain size_t's, so that each OpenMP thread gets
        // its own private cached index -- without this, concurrent
        // calls from different threads would race to update a single
        // shared cache. spec(double, double, double) must bind a
        // local reference to the element private to the calling
        // thread (e.g. "dim1Cache_()") before passing it to
        // findBracket, exactly as Mesh2DGrid's own methods do with
        // iSave_/jSave_. dim2Cache_/dim3Cache_ are protected, rather
        // than private like dim1Cache_, so that SpecsynLib2D's own 2D
        // spec(double, double) -- which never touches dim1_ at all --
        // can reuse them directly instead of keeping a redundant cache
        // of its own.
        mutable utils::ThreadVec<size_t> dim1Cache_;
    protected:

        mutable utils::ThreadVec<size_t> dim2Cache_;
        mutable utils::ThreadVec<size_t> dim3Cache_;
    };

} // namespace specsyn

#endif // SPECSYNLIB_HPP