1/**
2 * Backend abstraction over the spherical harmonic transform, mirroring the
3 * websph "porting boundary": the solver only ever needs coeffs->vals,
4 * vals->coeffs, and the grid. Spectral layout is the SHTNS convention used
5 * by shtns-webgpu (see src/sht/layout.ts): complex interleaved [re, im],
6 * m >= 0 only, m-major ordering, orthonormal + Condon-Shortley.
7 */
8import { ShtPlan, requestShtDevice } from '../sht/sht.ts';
9import { ShtReference } from '../sht/reference.ts';
10import type { ShtConfig } from '../sht/layout.ts';
12export interface ShtBackend {
13 readonly cfg: ShtConfig;
14 readonly nlm: number;
15 /** cos(colatitude), length nlat, decreasing (north to south). */
16 readonly cosTheta: Float64Array;
17 readonly kind: 'webgpu' | 'cpu';
18 synth(qlm: Float64Array): Promise<Float32Array | Float64Array>;
19 analys(spat: Float64Array): Promise<Float32Array | Float64Array>;
20 destroy(): void;
21}
23/** fp32 WebGPU backend (fast path). */
24export class GpuBackend implements ShtBackend {
25 readonly kind = 'webgpu';
26 readonly cfg: ShtConfig;
27 readonly nlm: number;
28 readonly cosTheta: Float64Array;
29 #plan: ShtPlan;
30 #qlm32: Float32Array;
31 #spat32: Float32Array;
33 private constructor(plan: ShtPlan) {
34 this.#plan = plan;
35 this.cfg = plan.cfg;
36 this.nlm = plan.nlm;
37 this.cosTheta = plan.cosTheta;
38 this.#qlm32 = new Float32Array(2 * plan.nlm);
39 this.#spat32 = new Float32Array(plan.cfg.nlat * plan.cfg.nphi);
40 }
42 static async create(device: GPUDevice, cfg: ShtConfig): Promise<GpuBackend> {
43 return new GpuBackend(await ShtPlan.create(device, cfg));
44 }
46 synth(qlm: Float64Array): Promise<Float32Array> {
47 this.#qlm32.set(qlm);
48 return this.#plan.synth(this.#qlm32);
49 }
51 analys(spat: Float64Array): Promise<Float32Array> {
52 this.#spat32.set(spat);
53 return this.#plan.analys(this.#spat32);
54 }
56 destroy(): void {
57 this.#plan.destroy();
58 }
59}
61/** f64 CPU backend by direct summation (slow; tests and no-WebGPU fallback). */
62export class CpuBackend implements ShtBackend {
63 readonly kind = 'cpu';
64 readonly cfg: ShtConfig;
65 readonly nlm: number;
66 readonly cosTheta: Float64Array;
67 #ref: ShtReference;
69 constructor(cfg: ShtConfig) {
70 this.#ref = new ShtReference(cfg);
71 this.cfg = cfg;
72 this.nlm = this.#ref.nlm;
73 this.cosTheta = this.#ref.ct;
74 }
76 synth(qlm: Float64Array): Promise<Float64Array> {
77 return Promise.resolve(this.#ref.synth(qlm));
78 }
80 analys(spat: Float64Array): Promise<Float64Array> {
81 return Promise.resolve(this.#ref.analys(spat));
82 }
84 destroy(): void {}
85}
87export { requestShtDevice };