Last Updated: May 17, 2025
This document explores various data structure options for storing and accessing Clebsch-Gordan coefficients in the context of spin network calculations.
type CGTable = number[][][][]; // [j1_idx][j2_idx][j_idx][m_idx]
// Index mapping
function getIndices(j1: number, m1: number, j2: number, m2: number, j: number): [number, number, number, number] {
return [
Math.round(m1 + j1), // j1_idx
Math.round(m2 + j2), // j2_idx
Math.round(j - Math.abs(j1-j2)), // j_idx
Math.round(m1 + m2 + j) // m_idx
];
}
const table: CGTable = Array(2*j1+1).fill(null)
.map(() => Array(2*j2+1).fill(null)
.map(() => Array(Math.floor(j1+j2)-Math.floor(Math.abs(j1-j2))+1).fill(null)
.map(() => Array(2*Math.floor(j1+j2)+1).fill(0))));
const [j1_idx, j2_idx, j_idx, m_idx] = getIndices(j1, m1, j2, m2, j);
const coeff = table[j1_idx][j2_idx][j_idx][m_idx];
type CGSparseTable = Map<string, number>;
// Key format: "j1,m1,j2,m2,j,m"
function makeKey(j1: number, m1: number, j2: number, m2: number, j: number, m: number): string {
return `${j1},${m1},${j2},${m2},${j},${m}`;
}
const table = new Map<string, number>();
table.set(makeKey(0.5, 0.5, 0.5, -0.5, 0, 0), 1/Math.sqrt(2));
const coeff = table.get(makeKey(j1, m1, j2, m2, j, m)) ?? 0;
type CGArray = number[][][]; // [m1_idx][m2_idx][j_idx]
interface CGDimensions {
j1: number;
j2: number;
dims: {
m1_size: number; // 2*j1 + 1
m2_size: number; // 2*j2 + 1
j_size: number; // j1 + j2 - |j1-j2| + 1
}
}
const dims: CGDimensions = {
j1: 0.5,
j2: 0.5,
dims: {
m1_size: 2,
m2_size: 2,
j_size: 2
}
};
const table: CGArray = Array(dims.dims.m1_size)
.fill(null)
.map(() => Array(dims.dims.m2_size)
.fill(null)
.map(() => Array(dims.dims.j_size)
.fill(0)));
const [m1_idx, m2_idx, j_idx] = getIndices(j1, m1, j2, m2, j);
const coeff = table[m1_idx][m2_idx][j_idx];
interface CGTablePair {
j1: number;
j2: number;
coeffs: {
[j: number]: { // total angular momentum
[m: number]: { // total m
[m1: number]: number; // coefficient for given m1
}
}
}
}
const table: CGTablePair = {
j1: 0.5,
j2: 0.5,
coeffs: {
0: { // singlet
0: { // m = 0
0.5: 1/Math.sqrt(2), // m1 = 1/2
-0.5: -1/Math.sqrt(2) // m1 = -1/2
}
},
1: { // triplet
1: { 0.5: 1 },
0: {
0.5: 1/Math.sqrt(2),
-0.5: 1/Math.sqrt(2)
},
-1: { -0.5: 1 }
}
}
};
// Access with helper function
function getCG(table: CGTablePair, j: number, m: number, m1: number): number {
return table.coeffs[j]?.[m]?.[m1] ?? 0;
}
interface CGFlatTable {
j1: number;
j2: number;
data: Float64Array;
dims: {
m1_size: number;
m2_size: number;
j_size: number;
}
}
function getIndex(dims: CGFlatTable['dims'], j: number, m: number, m1: number): number {
const m1_idx = Math.round(m1 + dims.m1_size/2);
const m2_idx = Math.round((m - m1) + dims.m2_size/2);
const j_idx = Math.round(j - Math.abs(j1-j2));
return m1_idx + dims.m1_size * (m2_idx + dims.m2_size * j_idx);
}
const table: CGFlatTable = {
j1: 0.5,
j2: 0.5,
dims: {
m1_size: 2,
m2_size: 2,
j_size: 2
},
data: new Float64Array(8) // 2 * 2 * 2
};
const idx = getIndex(table.dims, j, m, m1);
const coeff = table.data[idx];
type CGTuple = [j: number, m: number, m1: number, coeff: number];
interface CGTupleTable {
j1: number;
j2: number;
coeffs: CGTuple[];
}
const table: CGTupleTable = {
j1: 0.5,
j2: 0.5,
coeffs: [
[0, 0, 0.5, 1/Math.sqrt(2)],
[0, 0, -0.5, -1/Math.sqrt(2)],
[1, 1, 0.5, 1],
[1, 0, 0.5, 1/Math.sqrt(2)],
[1, 0, -0.5, 1/Math.sqrt(2)],
[1, -1, -0.5, 1]
]
};
function getCG(table: CGTupleTable, j: number, m: number, m1: number): number {
return table.coeffs.find(([j_, m_, m1_]) =>
j_ === j && m_ === m && m1_ === m1
)?.[3] ?? 0;
}
Option 4 (Structured Object) or Option 5 (Flat Array) are recommended:
Option 4 when:
Option 5 when:
Recommend implementing both:
CGTablePair for coefficient generation and storageCGFlatTable for performance-critical calculations// Generation and storage
const storedTable: CGTablePair = generateCGTable(j1, j2);
// Convert to flat array for calculations
const flatTable: CGFlatTable = convertToFlat(storedTable);
This gives us the best of both worlds: clear structure for generation and maintenance, with optimized performance for calculations.