UNPKG

ts-quantum

Version:

TypeScript library for quantum mechanics calculations and utilities

430 lines 16.6 kB
"use strict"; /** * Angular momentum operators implementation * Implements J₊, J₋, Jz, and J² operators for arbitrary angular momentum j */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCoherentState = exports.jmExpectationValue = exports.createRotationOperator = exports.isValidM = exports.getValidM = exports.validateJ = exports.createJ2FromComponents = exports.createJ2 = exports.createJy = exports.createJx = exports.createJz = exports.createJminus = exports.createJplus = exports.identifyBasis = exports.angularToComputationalBasis = exports.computationalToAngularBasis = exports.createJmState = void 0; const operator_1 = require("../operators/operator"); const measurement_1 = require("../operators/measurement"); const stateVector_1 = require("../states/stateVector"); const matrixOperations_1 = require("../utils/matrixOperations"); const math = __importStar(require("mathjs")); /** * Creates an angular momentum state |j,m⟩ * * @param j Total angular momentum quantum number * @param m Magnetic quantum number * @returns The state |j,m⟩ as a StateVector */ function createJmState(j, m) { validateJ(j); if (!isValidM(j, m)) { throw new Error(`Invalid m=${m} for j=${j}`); } const dim = Math.floor(2 * j + 1); const amplitudes = Array(dim).fill(null).map(() => math.complex(0, 0)); const idx = dim - 1 - (j + m); amplitudes[idx] = math.complex(1, 0); const state = new stateVector_1.StateVector(dim, amplitudes, `|${j},${m}⟩`); // Add angular momentum metadata const metadata = { type: 'angular_momentum', j: j, mRange: [-j, j], couplingHistory: [{ operation: 'single', resultJ: [j], timestamp: Date.now() }], jComponents: new Map([[j, { j: j, startIndex: 0, dimension: dim, normalizationFactor: 1 }]]), isComposite: false }; state.setAngularMomentumMetadata(metadata); return state; } exports.createJmState = createJmState; /** * Converts a state vector from computational basis to angular momentum basis * For j=1/2: |0⟩ -> |1/2,-1/2⟩, |1⟩ -> |1/2,1/2⟩ * * @param state State vector in computational basis * @param j Total angular momentum quantum number * @returns State vector in angular momentum basis */ function computationalToAngularBasis(state, j) { validateJ(j); const dim = Math.floor(2 * j + 1); // Check input dimension matches 2j+1 if (state.dimension !== dim) { throw new Error(`State dimension ${state.dimension} does not match 2j+1 = ${dim}`); } // Create new array for amplitudes in angular momentum basis const newAmplitudes = Array(dim).fill(null).map(() => math.complex(0, 0)); // Map each computational basis state to angular momentum basis // |n⟩ maps to |j,m⟩ where m = -j + n for (let n = 0; n < dim; n++) { const m = -j + n; // Use consistent indexing convention: higher m values get lower indices const angularIndex = dim - 1 - (j + m); newAmplitudes[angularIndex] = state.amplitudes[n]; } // Create labels for basis states const labels = []; for (let m = -j; m <= j; m++) { labels.push(`|${j},${m}⟩`); } return new stateVector_1.StateVector(dim, newAmplitudes, 'angular'); } exports.computationalToAngularBasis = computationalToAngularBasis; /** * Converts a state vector from angular momentum basis to computational basis * For j=1/2: |1/2,-1/2⟩ -> |0⟩, |1/2,1/2⟩ -> |1⟩ * * @param state State vector in angular momentum basis * @param j Total angular momentum quantum number * @returns State vector in computational basis */ function angularToComputationalBasis(state, j) { validateJ(j); const dim = Math.floor(2 * j + 1); // Check input dimension matches 2j+1 if (state.dimension !== dim) { throw new Error(`State dimension ${state.dimension} does not match 2j+1 = ${dim}`); } // Create new array for amplitudes in computational basis const newAmplitudes = Array(dim).fill(null).map(() => math.complex(0, 0)); // Map each angular momentum basis state to computational basis // |j,m⟩ maps to |n⟩ where n = m + j for (let m = -j; m <= j; m++) { const n = m + j; // Index in angular basis array goes from -j to +j const angularIndex = dim - 1 - (j + m); newAmplitudes[n] = state.amplitudes[angularIndex]; } // Create computational basis labels const labels = []; for (let i = 0; i < dim; i++) { labels.push(`|${i}⟩`); } return new stateVector_1.StateVector(dim, newAmplitudes, 'computational'); } exports.angularToComputationalBasis = angularToComputationalBasis; /** * Attempts to identify the basis of a state vector based on its label format * * @param state State vector to identify basis for * @returns 'angular' for angular momentum basis, 'computational' for computational basis, * or 'unknown' if basis cannot be determined */ function identifyBasis(state) { const str = state.toString(); // Check for angular momentum basis format |j,m⟩ if (str.match(/\|\d+\/?\d*,[-+]?\d+\/?\d*⟩/)) { return 'angular'; } // Check for computational basis format |n⟩ if (str.match(/\|\d+⟩/)) { return 'computational'; } return 'unknown'; } exports.identifyBasis = identifyBasis; /** * Creates a zero complex matrix of given dimension */ function createZeroMatrix(dim) { return Array(dim).fill(null) .map(() => Array(dim).fill(null) .map(() => math.complex(0, 0))); } /** * Creates the raising operator J₊ for given angular momentum j * J₊|j,m⟩ = √(j(j+1) - m(m+1)) |j,m+1⟩ * * @param j Total angular momentum quantum number * @returns The J₊ operator as a matrix */ function createJplus(j) { validateJ(j); const dim = Math.floor(2 * j + 1); const matrix = createZeroMatrix(dim); // Fill matrix elements - use consistent indexing with states for (let m = -j; m < j; m++) { // States use: idx = dim - 1 - (j + m) const fromStateIdx = dim - 1 - (j + m); // |j,m⟩ const toStateIdx = dim - 1 - (j + (m + 1)); // |j,m+1⟩ const element = Math.sqrt(j * (j + 1) - m * (m + 1)); // Matrix element: ⟨j,m+1| J₊ |j,m⟩ matrix[toStateIdx][fromStateIdx] = math.complex(element, 0); } return new operator_1.MatrixOperator(matrix, 'general', true, { j }); } exports.createJplus = createJplus; /** * Creates the lowering operator J₋ for given angular momentum j * J₋|j,m⟩ = √(j(j+1) - m(m-1)) |j,m-1⟩ * * @param j Total angular momentum quantum number * @returns The J₋ operator as a matrix */ function createJminus(j) { validateJ(j); const dim = Math.floor(2 * j + 1); const matrix = createZeroMatrix(dim); // Fill matrix elements - use consistent indexing with states for (let m = -j + 1; m <= j; m++) { // States use: idx = dim - 1 - (j + m) const fromStateIdx = dim - 1 - (j + m); // |j,m⟩ const toStateIdx = dim - 1 - (j + (m - 1)); // |j,m-1⟩ const element = Math.sqrt(j * (j + 1) - m * (m - 1)); // Matrix element: ⟨j,m-1| J₋ |j,m⟩ matrix[toStateIdx][fromStateIdx] = math.complex(element, 0); } return new operator_1.MatrixOperator(matrix, 'general', true, { j }); } exports.createJminus = createJminus; /** * Creates the z-component operator Jz for given angular momentum j * Jz|j,m⟩ = m|j,m⟩ * * @param j Total angular momentum quantum number * @returns The Jz operator as a matrix */ function createJz(j) { validateJ(j); const dim = Math.floor(2 * j + 1); const matrix = createZeroMatrix(dim); // Fill diagonal elements - m goes from j to -j as idx goes from 0 to 2j for (let idx = 0; idx < dim; idx++) { const m = -j + (dim - 1 - idx); matrix[idx][idx] = math.complex(m, 0); } return new operator_1.MatrixOperator(matrix, 'hermitian', true, { j }); } exports.createJz = createJz; /** * Creates the x-component operator Jx for given angular momentum j * Jx = (J₊ + J₋)/2 * * @param j Total angular momentum quantum number * @returns The Jx operator as a matrix */ function createJx(j) { const jPlus = createJplus(j); const jMinus = createJminus(j); // Jx = (J₊ + J₋)/2 const plusMatrix = jPlus.toMatrix(); const minusMatrix = jMinus.toMatrix(); const matrix = plusMatrix.map((row, i) => row.map((_, j) => math.multiply(math.add(plusMatrix[i][j], minusMatrix[i][j]), math.complex(0.5, 0)))); return new operator_1.MatrixOperator(matrix, 'hermitian', true, { j }); } exports.createJx = createJx; /** * Creates the y-component operator Jy for given angular momentum j * Jy = (J₊ - J₋)/(2i) * * @param j Total angular momentum quantum number * @returns The Jy operator as a matrix */ function createJy(j) { const jPlus = createJplus(j); const jMinus = createJminus(j); // Jy = (J₊ - J₋)/(2i) const plusMatrix = jPlus.toMatrix(); const minusMatrix = jMinus.toMatrix(); const matrix = plusMatrix.map((row, i) => row.map((_, j) => math.multiply(math.subtract(plusMatrix[i][j], minusMatrix[i][j]), math.complex(0, -0.5) // multiply by 1/(2i) ))); return new operator_1.MatrixOperator(matrix, 'general', true, { j }); } exports.createJy = createJy; /** * Creates the total angular momentum operator J² for given j * J²|j,m⟩ = j(j+1)|j,m⟩ * * @param j Total angular momentum quantum number * @returns The J² operator as a matrix */ function createJ2(j) { validateJ(j); const dim = Math.floor(2 * j + 1); const eigenvalue = j * (j + 1); const matrix = createZeroMatrix(dim); // Fill diagonal elements with j(j+1) for (let i = 0; i < dim; i++) { matrix[i][i] = math.complex(eigenvalue, 0); } const op = new operator_1.MatrixOperator(matrix); return Object.assign(op, { j }); } exports.createJ2 = createJ2; /** * Creates total angular momentum operator J² from components * J² = Jx² + Jy² + Jz² = J₊J₋ + Jz² - Jz = J₋J₊ + Jz² + Jz * * This is an alternative implementation that constructs J² from its components. * Useful for verification against createJ2(). * * @param j Total angular momentum quantum number * @returns The J² operator as a matrix */ function createJ2FromComponents(j) { const jPlus = createJplus(j); const jMinus = createJminus(j); const jz = createJz(j); // Calculate J² = J₊J₋ + Jz² - Jz const jPlusJMinus = jPlus.compose(jMinus); const jzSquared = jz.compose(jz); const result = jPlusJMinus.add(jzSquared).add(jz.scale(math.complex(-1, 0))); return Object.assign(new operator_1.MatrixOperator(result.toMatrix()), { j }); } exports.createJ2FromComponents = createJ2FromComponents; /** * Validates angular momentum quantum number j * j must be a non-negative integer or half-integer * * @param j Angular momentum quantum number to validate * @throws Error if j is invalid */ function validateJ(j) { if (j < 0) { throw new Error('Angular momentum j must be non-negative'); } // Check if j is integer or half-integer const isValid = Math.abs(j * 2 - Math.round(j * 2)) < 1e-10; if (!isValid) { throw new Error('Angular momentum j must be integer or half-integer'); } } exports.validateJ = validateJ; /** * Gets the valid m values for a given j * m ranges from -j to +j in integer steps * * @param j Total angular momentum quantum number * @returns Array of valid m values */ function getValidM(j) { validateJ(j); const mValues = []; for (let m = -j; m <= j; m++) { mValues.push(m); } return mValues; } exports.getValidM = getValidM; /** * Checks if a given m value is valid for angular momentum j * * @param j Total angular momentum quantum number * @param m Magnetic quantum number to check * @returns true if m is valid for given j */ function isValidM(j, m) { validateJ(j); // First check range if (m < -j || m > j) { return false; } // For integer j, m must be integer // For half-integer j, m must be half-integer const mValues = getValidM(j); return mValues.includes(m); } exports.isValidM = isValidM; /** * Creates Wigner rotation operator D(α,β,γ) = exp(-iαJz)exp(-iβJy)exp(-iγJz) * * @param j Total angular momentum quantum number * @param alpha First Euler angle * @param beta Second Euler angle * @param gamma Third Euler angle * @returns The Wigner rotation operator */ function createRotationOperator(j, alpha, beta, gamma) { // Get Jz and construct Jy = (J₊ - J₋)/(2i) const jz = createJz(j); const jPlus = createJplus(j); const jMinus = createJminus(j); // Create Jy from J₊ and J₋ const jyMatrix = jPlus.toMatrix().map((row, i) => row.map((_, j) => { const plusElem = jPlus.toMatrix()[i][j]; const minusElem = jMinus.toMatrix()[i][j]; return math.multiply(math.subtract(plusElem, minusElem), math.complex(0, -0.5)); })); const jy = new operator_1.MatrixOperator(jyMatrix, 'general', true, { j }); // Calculate rotation matrices const expAlpha = Object.assign(new operator_1.MatrixOperator((0, matrixOperations_1.matrixExponential)(jz.scale(math.complex(0, -alpha)).toMatrix())), { j }); const expBeta = Object.assign(new operator_1.MatrixOperator((0, matrixOperations_1.matrixExponential)(jy.scale(math.complex(0, -beta)).toMatrix())), { j }); const expGamma = Object.assign(new operator_1.MatrixOperator((0, matrixOperations_1.matrixExponential)(jz.scale(math.complex(0, -gamma)).toMatrix())), { j }); // Combine the rotations const result = expAlpha.compose(expBeta).compose(expGamma); return Object.assign(new operator_1.MatrixOperator(result.toMatrix()), { j }); } exports.createRotationOperator = createRotationOperator; /** * Calculates expectation value ⟨j,m|O|j,m⟩ for an angular momentum operator * * @param operator Angular momentum operator to calculate expectation for * @param j Total angular momentum quantum number * @param m Magnetic quantum number * @returns Complex expectation value */ function jmExpectationValue(operator, j, m) { // Create the angular momentum state |j,m⟩ const state = createJmState(j, m); // Calculate ⟨j,m|O|j,m⟩ using the proper expectation value formula return (0, measurement_1.expectationValue)(state, operator); } exports.jmExpectationValue = jmExpectationValue; /** * Creates a coherent angular momentum state |j,θ,φ⟩ * This is an eigenstate of the angular momentum operator pointing in the direction (θ,φ) * * @param j Total angular momentum quantum number * @param theta Polar angle θ in radians * @param phi Azimuthal angle φ in radians * @returns The coherent state as a StateVector */ function createCoherentState(j, theta, phi) { validateJ(j); // Create rotation operator to rotate from |j,j⟩ to desired direction const alpha = phi; const beta = theta; const gamma = 0; const D = createRotationOperator(j, alpha, beta, gamma); // Start with highest weight state |j,j⟩ const highestState = createJmState(j, j); // Rotate to desired direction return D.apply(highestState); } exports.createCoherentState = createCoherentState; //# sourceMappingURL=core.js.map