import _ from 'lodash' ; import { Cx } from './Complex' ; import Dimension from './Dimension' ; import Vector from './Vector' ; import Operator from './Operator' ; import { DEG_TO_RAD , TAU } from './Constants' ; import * as ops from './Ops' ; import { Elem , ICell , IXYOperator } from './interfaces' ; const dimPol = Dimension . polarization ( ) ; const dimDir = Dimension . direction ( ) ; const idPol = Operator . identity ( [ dimPol ] ) ; const idDir = Operator . identity ( [ dimDir ] ) ; const projH = Operator . indicator ( [ dimPol ] , 'H' ) ; const projV = Operator . indicator ( [ dimPol ] , 'V' ) ; const mod = ( x , n ) : number => ( ( x % n ) + n ) % n ; param rot export function sugarSolution ( polarizationRotation = 0.125 ) { return Operator . outer ( [ idDir , ops . rotationMatrix ( polarizationRotation * TAU , dimPol ) ] ) ; } param r export function attenuator ( r = Math . SQRT1_2 ) { return ops . amplitudeIntensity ( r , 0 ) ; } /**
 * A vacuum jar - advances phase by lambda/4.
 */ export function vacuumJar ( ) { return ops . amplitudeIntensity ( 1 , - 0.25 ) ; } /**
 * A glass slab - delays phase by lambda/4.
 */ export function glassSlab ( ) { return ops . amplitudeIntensity ( 1 , + 0.25 ) ; } angle returns export function mirror ( angle ) { return Operator . outer ( [ ops . reflectFromPlaneDirection ( angle ) , ops . reflectPhaseFromDenser ( ) ] ) ; } angle returns todo export function beamSplitter ( angle , split = 0.5 ) { const reflect = ops . reflectFromPlaneDirection ( angle ) . outer ( ops . reflectPhaseFromDenser ( ) ) . mulConstant ( Cx ( 0.0 , Math . sqrt ( split ) ) ) ; const transmit = ops . beamsplitterTransmittionDirections ( angle ) . outer ( idPol ) . mulConstant ( Cx ( Math . sqrt ( 1 - split ) , 0.0 ) ) ; return reflect . add ( transmit ) ; } /**
 * A corner cube, from in all 4 directions.
 * https://en.wikipedia.org/wiki/Corner_reflector
 */ export function cornerCube ( ) { return Operator . outer ( [ Operator . fromSparseCoordNames ( [ [ '<' , '>' , Cx ( 1 ) ] , [ 'v' , '^' , Cx ( 1 ) ] , [ '>' , '<' , Cx ( 1 ) ] , [ '^' , 'v' , Cx ( 1 ) ] , ] , [ dimDir ] ) , idPol , ] ) ; } note angle returns export function polarizingBeamsplitter ( angle ) { if ( ! _ . includes ( [ 0 , 90 ] , mod ( angle , 180 ) ) ) { throw new Error ( `polarizingBeamsplitter: angle ${ angle } mod 180 not in [0, 90].` ) ; } return Operator . add ( [ idDir . outer ( projH ) , ops . reflectFromPlaneDirection ( angle + 45 ) . outer ( projV ) ] ) ; } angle param rot export function faradayRotator ( angle , polarizationRotation = 0.125 ) { return Operator . add ( [ Operator . outer ( [ ops . diodeForDirections ( angle ) , ops . rotationMatrix ( polarizationRotation * TAU , dimPol ) ] ) , Operator . outer ( [ ops . diodeForDirections ( angle + 180 ) , ops . rotationMatrix ( - polarizationRotation * TAU , dimPol ) ] ) , ] ) ; } param angle param polarizationOrientation todo export function polarizer ( angle ) { return Operator . add ( [ Operator . outer ( [ ops . diodeForDirections ( 0 ) , ops . projectionMatrix ( angle * DEG_TO_RAD , dimPol ) ] ) , Operator . outer ( [ ops . diodeForDirections ( 90 ) , ops . projectionMatrix ( ( angle + 90 ) * DEG_TO_RAD , dimPol ) ] ) , Operator . outer ( [ ops . diodeForDirections ( 180 ) , ops . projectionMatrix ( ( angle + 180 ) * DEG_TO_RAD , dimPol ) ] ) , Operator . outer ( [ ops . diodeForDirections ( 270 ) , ops . projectionMatrix ( ( angle + 270 ) * DEG_TO_RAD , dimPol ) ] ) , ] ) ; } param rotation param phase todo export function phasePlate ( rotation , phaseShift ) { return Operator . add ( [ Operator . outer ( [ ops . diodeForDirections ( 0 ) , ops . phaseShiftForRealEigenvectors ( rotation * DEG_TO_RAD , 0 , phaseShift , dimPol ) , ] ) , Operator . outer ( [ ops . diodeForDirections ( 90 ) , ops . phaseShiftForRealEigenvectors ( ( rotation + 90 ) * DEG_TO_RAD , 0 , phaseShift , dimPol ) , ] ) , Operator . outer ( [ ops . diodeForDirections ( 180 ) , ops . phaseShiftForRealEigenvectors ( ( rotation + 180 ) * DEG_TO_RAD , 0 , phaseShift , dimPol ) , ] ) , Operator . outer ( [ ops . diodeForDirections ( 270 ) , ops . phaseShiftForRealEigenvectors ( ( rotation + 270 ) * DEG_TO_RAD , 0 , phaseShift , dimPol ) , ] ) , ] ) ; } param opDirPol return export function incoherentLightOperator ( opDirPol ) { const opIntensity = opDirPol . mapValues ( ( z ) => z . mul ( z . conj ( ) ) ) ; const polInputs = Vector . fromArray ( [ Cx ( 0.5 ) , Cx ( 0.5 ) ] , [ Dimension . polarization ( ) ] ) ; const polOutpus = Vector . fromArray ( [ Cx ( 1 ) , Cx ( 1 ) ] , [ Dimension . polarization ( ) ] ) ; return opIntensity . contractLeft ( [ 1 ] , polOutpus ) . contractRight ( [ 1 ] , polInputs ) ; } /**
 * Compute local operator for given cell
 */ function cellLocalOperator ( cell ) { switch ( cell . element ) { case Elem . Absorber : return attenuator ( Math . sqrt ( cell . strength ?? 0.5 ) ) ; case Elem . BeamSplitter : return beamSplitter ( cell . rotation , cell . split ?? 0.5 ) ; case Elem . CoatedBeamSplitter : return beamSplitter ( cell . rotation , cell . split ?? 0.5 ) ; case Elem . CornerCube : return cornerCube ( ) ; case Elem . Detector : return attenuator ( 0 ) ; case Elem . DetectorFour : return attenuator ( 0 ) ; case Elem . FaradayRotator : return faradayRotator ( cell . rotation ) ; case Elem . Gate : return attenuator ( 0 ) ; case Elem . Glass : return glassSlab ( ) ; case Elem . Laser : return attenuator ( 0 ) ; case Elem . Mine : return attenuator ( 0 ) ; case Elem . Mirror : return mirror ( cell . rotation ) ; case Elem . NonLinearCrystal : return attenuator ( 1 ) ; case Elem . Polarizer : return polarizer ( cell . rotation ) ; case Elem . PolarizingBeamSplitter : return polarizingBeamsplitter ( cell . rotation ) ; case Elem . HalfWavePlate : return phasePlate ( cell . rotation , 0.5 ) ; case Elem . QuarterWavePlate : return phasePlate ( cell . rotation , 0.25 ) ; case Elem . Rock : return attenuator ( 0 ) ; case Elem . SugarSolution : return sugarSolution ( 0.25 ) ; case Elem . VacuumJar : return vacuumJar ( ) ; case Elem . Void : return attenuator ( 1 ) ; case Elem . Wall : return attenuator ( 0 ) ; default : { throw new Error ( `Conversion from cell to operator failed: ${ cell }.` ) ; } } } param cell returns export function generateOperator ( cell ) { const x = cell . x ; const y = cell . y ; return { x , y , op : cellLocalOperator ( cell ) , } ; } param grid returns export function generateOperators ( cells ) { return cells . map ( ( cell ) => { return generateOperator ( cell ) ; } ) ; }