Skip to content

Commit

Permalink
Creating scaffolding for the Stern Gerlach experiments, see #53
Browse files Browse the repository at this point in the history
  • Loading branch information
AgustinVallejo committed Oct 11, 2024
1 parent 7deaa9b commit 2b7c513
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 17 deletions.
64 changes: 64 additions & 0 deletions js/spin/model/SpinExperiments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2024, University of Colorado Boulder

/**
* SpinExperiments contains the details for all posisble Stern-Gerlach configurations of the Spin Screen.
*
* // TODO: So far basing off OrbitalSystem.ts https://github.com/phetsims/quantum-measurement/issues/53
*
* @author Agustín Vallejo
*/

import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import Enumeration from '../../../../phet-core/js/Enumeration.js';
import EnumerationValue from '../../../../phet-core/js/EnumerationValue.js';
import quantumMeasurement from '../../quantumMeasurement.js';


type SternGerlachOptions = {
isZOriented: boolean;
active: boolean;
};

export default class SpinExperiments extends EnumerationValue {

public static readonly EXPERIMENT_1 = new SpinExperiments( 'Experiment 1 [SGz]', [
{ isZOriented: true, active: true }
] );
public static readonly EXPERIMENT_2 = new SpinExperiments( 'Experiment 2 [SGx]', [
{ isZOriented: false, active: true }
] );
public static readonly EXPERIMENT_3 = new SpinExperiments( 'Experiment 3 [Sz, Sx]', [
{ isZOriented: true, active: true },
{ isZOriented: false, active: true }
] );
public static readonly EXPERIMENT_4 = new SpinExperiments( 'Experiment 4 [Sz, Sz]', [
{ isZOriented: true, active: true },
{ isZOriented: true, active: true }
] );
public static readonly EXPERIMENT_5 = new SpinExperiments( 'Experiment 5 [Sx, Sz]', [
{ isZOriented: false, active: true },
{ isZOriented: true, active: true }
] );
public static readonly EXPERIMENT_6 = new SpinExperiments( 'Experiment 6 [Sx, Sx]', [
{ isZOriented: false, active: true },
{ isZOriented: false, active: true }
] );
public static readonly CUSTOM = new SpinExperiments( 'Custom', [
{ isZOriented: false, active: false },
{ isZOriented: false, active: false }
] );

public static readonly enumeration = new Enumeration( SpinExperiments );

public readonly experimentName: string | TReadOnlyProperty<string>;

public readonly experimentSettings: SternGerlachOptions[];

public constructor( experimentName: string | TReadOnlyProperty<string>, experimentSettings: SternGerlachOptions[] ) {
super();
this.experimentName = experimentName;
this.experimentSettings = experimentSettings;
}
}

quantumMeasurement.register( 'SpinExperiments', SpinExperiments );
51 changes: 38 additions & 13 deletions js/spin/model/SpinModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,66 @@ import PickRequired from '../../../../phet-core/js/types/PickRequired.js';
import { PhetioObjectOptions } from '../../../../tandem/js/PhetioObject.js';
import quantumMeasurement from '../../quantumMeasurement.js';
import SimpleBlochSphere from './SimpleBlochSphere.js';
import SpinExperiments from './SpinExperiments.js';
import SternGerlachModel from './SternGerlachModel.js';

type SelfOptions = {
// TODO add options that are specific to QuantumMeasurementModel here, see see https://github.com/phetsims/quantum-measurement/issues/1.
};

type QuantumMeasurementModelOptions = SelfOptions & PickRequired<PhetioObjectOptions, 'tandem'>;

const EXPERIMENTS = [
'Experiment 1 [SGz]',
'Experiment 2 [SGx]',
'Experiment 3 [Sz, Sx]',
'Experiment 4 [Sz, Sz]',
'Experiment 5 [Sx, Sz]',
'Experiment 6 [Sx, Sx]',
'Custom'
] as const;
type ValidExperiments = typeof EXPERIMENTS[number];

// TODO: Consider using EnumerationValues for these, see https://github.com/phetsims/quantum-measurement/issues/53
export const SpinValues = [ 'Z_PLUS', 'X_PLUS', 'Z_MINUS' ] as const;
export type SpinTypes = typeof SpinValues[number]; // Creates a union type of 'Z_PLUS' | 'Z_MINUS' | 'X_PLUS'

export const SourceModes = [ 'single', 'continuous' ] as const;
export type SourceModeTypes = typeof SourceModes[number];

export default class SpinModel implements TModel {

public readonly sourceModeProperty: Property<SourceModeTypes>;

public readonly blochSphere: SimpleBlochSphere;

public readonly experiments = EXPERIMENTS;
public readonly currentExperimentProperty: Property<ValidExperiments>;
public readonly currentExperimentProperty: Property<SpinExperiments>;

// Models for the three available Stern-Gerlach experiments. Second and Third are counted top to bottom.
public readonly firstSternGerlachModel: SternGerlachModel;
public readonly secondSternGerlachModel: SternGerlachModel;
public readonly thirdSternGerlachModel: SternGerlachModel;

public constructor( providedOptions: QuantumMeasurementModelOptions ) {

this.sourceModeProperty = new Property<SourceModeTypes>( 'single' );

this.blochSphere = new SimpleBlochSphere( {
tandem: providedOptions.tandem.createTandem( 'blochSphere' )
} );

this.currentExperimentProperty = new Property<ValidExperiments>( 'Experiment 1 [SGz]' );
this.currentExperimentProperty = new Property<SpinExperiments>( SpinExperiments.EXPERIMENT_1 );

const sternGerlachModelsTandem = providedOptions.tandem.createTandem( 'sternGerlachModels' );
this.firstSternGerlachModel = new SternGerlachModel( true, sternGerlachModelsTandem.createTandem( 'firstSternGerlachModel' ) );
this.secondSternGerlachModel = new SternGerlachModel( false, sternGerlachModelsTandem.createTandem( 'secondSternGerlachModel' ) );
this.thirdSternGerlachModel = new SternGerlachModel( false, sternGerlachModelsTandem.createTandem( 'thirdSternGerlachModel' ) );

const sternGerlachModels = [ this.firstSternGerlachModel, this.secondSternGerlachModel, this.thirdSternGerlachModel ];

this.currentExperimentProperty.link( experiment => {
sternGerlachModels.forEach( ( sternGerlachModel, index ) => {
if ( experiment.experimentSettings.length > index ) {
// TODO: Should visibility be only handled via the View? https://github.com/phetsims/quantum-measurement/issues/53
sternGerlachModel.isVisibleProperty.set( experiment.experimentSettings[ index ].active );
sternGerlachModel.isZOrientedProperty.set( experiment.experimentSettings[ index ].isZOriented );
}
else {
sternGerlachModel.isVisibleProperty.set( false );
}
} );
} );

}

/**
Expand Down
40 changes: 40 additions & 0 deletions js/spin/model/SternGerlachModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2024, University of Colorado Boulder

/**
* SternGerlachModel handles the internal states of the Stern Gerlach experiment. This includes:
* - The direction of the experiment (currently constrained to X and +-Z)
* - The state of the incoming particles
* - The state of the particles after the experiment
*
* @author Agustín Vallejo
*/

import BooleanProperty from '../../../../axon/js/BooleanProperty.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import quantumMeasurement from '../../quantumMeasurement.js';

export default class SternGerlachModel {

public readonly isZOrientedProperty: BooleanProperty;

public readonly isVisibleProperty: BooleanProperty;

public constructor( isZOriented: boolean, tandem: Tandem ) {

this.isZOrientedProperty = new BooleanProperty( isZOriented, {
tandem: tandem.createTandem( 'isZOrientedProperty' )
} );

this.isVisibleProperty = new BooleanProperty( true, {
tandem: tandem.createTandem( 'isVisibleProperty' )
} );

}

public reset(): void {
// no-op TODO https://github.com/phetsims/quantum-measurement/issues/53
}

}

quantumMeasurement.register( 'SternGerlachModel', SternGerlachModel );
57 changes: 53 additions & 4 deletions js/spin/view/SpinMeasurementArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@
* @author Agustín Vallejo
*/

import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import { Shape } from '../../../../kite/js/imports.js';
import PhetFont from '../../../../scenery-phet/js/PhetFont.js';
import { Node, Text, VBox } from '../../../../scenery/js/imports.js';
import { HBox, Node, Path, Text, VBox } from '../../../../scenery/js/imports.js';
import ComboBox, { ComboBoxItem } from '../../../../sun/js/ComboBox.js';
import Tandem from '../../../../tandem/js/Tandem.js';
import quantumMeasurement from '../../quantumMeasurement.js';
import SpinExperiments from '../model/SpinExperiments.js';
import SpinModel from '../model/SpinModel.js';

export default class SpinMeasurementArea extends VBox {

public constructor( model: SpinModel, parentNode: Node, tandem: Tandem ) {

const items: ComboBoxItem<string>[] = model.experiments.map( experiment => {
const items: ComboBoxItem<SpinExperiments>[] = SpinExperiments.enumeration.values.map( experiment => {
return {
value: experiment,
createNode: () => new Text( experiment, { font: new PhetFont( 16 ) } )
createNode: () => new Text( experiment.experimentName, { font: new PhetFont( 16 ) } )
};
} );

Expand All @@ -30,7 +34,52 @@ export default class SpinMeasurementArea extends VBox {
super( {
children: [
experimentComboBox,
new Text( 'Stern-Gerlach (SG) Measurements', { font: new PhetFont( { size: 20, weight: 'bolder' } ) } )
new Text( 'Stern-Gerlach (SG) Measurements', { font: new PhetFont( { size: 20, weight: 'bolder' } ) } ),

// TODO: Really really rough sketch of the behavior of the SG experiments, see https://github.com/phetsims/quantum-measurement/issues/53
new HBox( {
spacing: 50,
children: [
new Path( new Shape().rect( 0, 0, 100, 100 ),
{ fill: 'black' } ),
new Node( {
children: [
new Path( new Shape().rect( 0, 0, 100, 100 ),
{ fill: 'red', visibleProperty: model.firstSternGerlachModel.isVisibleProperty } ),
new Text( new DerivedProperty(
[ model.firstSternGerlachModel.isZOrientedProperty ],
( isZOriented: boolean ) => isZOriented ? 'Z' : 'X' ),
{ font: new PhetFont( 16 ), fill: 'white', center: new Vector2( 50, 50 ) } )
]
} ),
new VBox( {
spacing: 20,
children: [
new Node( {
children: [
new Path( new Shape().rect( 0, 0, 100, 100 ),
{ fill: 'green', visibleProperty: model.secondSternGerlachModel.isVisibleProperty } ),
new Text( new DerivedProperty(
[ model.secondSternGerlachModel.isZOrientedProperty ],
( isZOriented: boolean ) => isZOriented ? 'Z' : 'X' ),
{ font: new PhetFont( 16 ), fill: 'white', center: new Vector2( 50, 50 ) } )
]
} ),
new Node( {
children: [
new Path( new Shape().rect( 0, 0, 100, 100 ),
{ fill: 'blue', visibleProperty: model.secondSternGerlachModel.isVisibleProperty } ),
new Text( new DerivedProperty(
[ model.secondSternGerlachModel.isZOrientedProperty ],
( isZOriented: boolean ) => isZOriented ? 'Z' : 'X' ),
{ font: new PhetFont( 16 ), fill: 'white', center: new Vector2( 50, 50 ) } )
]
} )
]
} )
]
} )

],
spacing: 20,
margin: 20
Expand Down

0 comments on commit 2b7c513

Please sign in to comment.