Skip to content

Commit

Permalink
add gradientField query parameter for testing, #66
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelzoom committed May 10, 2024
1 parent 92cc78f commit 9c1861f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 12 deletions.
5 changes: 4 additions & 1 deletion js/common/FELConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,10 @@ const FELConstants = {
'while the sign indicates the direction of flow.',

// Diameter for charged particles (electrons and imaginary positive charges)
CHARGED_PARTICLE_DIAMETER: 9
CHARGED_PARTICLE_DIAMETER: 9,

// See FELQueryParameters.calibrationField
GRADIENT_FIELD_X_RANGE: new Range( 100, 650 )
};

faradaysElectromagneticLab.register( 'FELConstants', FELConstants );
Expand Down
22 changes: 22 additions & 0 deletions js/common/FELQueryParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import logGlobal from '../../../phet-core/js/logGlobal.js';
import faradaysElectromagneticLab from '../faradaysElectromagneticLab.js';
import FELConstants from './FELConstants.js';

export const MagneticUnitsValues = [ 'G', 'T' ] as const;
export type MagneticUnits = ( typeof MagneticUnitsValues )[number];
Expand Down Expand Up @@ -78,6 +79,27 @@ const SCHEMA_MAP = {
// FELScreenView base class that is shared by all screens.
showFieldPositions: {
type: 'flag'
},

// Ignores the magnet model and sets up a static gradient B-field, where all field vectors are (Bx,0), and Bx varies
// linearly over a range. The value for this query parameter is the range of Bx from positions x=100 to x=650.
// These positions will be noted by yellow vertical lines. By is always 0.
//
// This is useful for calibrating the sim, and verifying behavior of the pickup coil. This query parameter affects
// all screens, even though it is only useful in the Pickup Coil and Transformer screens.
//
// Examples:
// calibrationField=300,300 sets up a B-field that has Bx=300 everywhere.
// calibrationField=0,300 sets up a B-field that linearly increases from Bx=0 to Bx=300 from left to right.
//
gradientField: {
type: 'array',
elementSchema: {
type: 'number',
isValidValue: ( value: number ) => ( Number.isInteger( value ) && FELConstants.MAGNET_STRENGTH_RANGE.contains( value ) )
},
defaultValue: null,
isValidValue: ( array: null | number[] ) => ( array === null ) || ( array.length === 2 )
}
} as const;

Expand Down
36 changes: 26 additions & 10 deletions js/common/model/Magnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import BooleanProperty from '../../../../axon/js/BooleanProperty.js';
import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js';
import Bounds2 from '../../../../dot/js/Bounds2.js';
import Dimension3 from '../../../../dot/js/Dimension3.js';
import Utils from '../../../../dot/js/Utils.js';
import FELQueryParameters from '../FELQueryParameters.js';
import FELConstants from '../FELConstants.js';

type SelfOptions = {

Expand Down Expand Up @@ -131,19 +134,32 @@ export default abstract class Magnet extends FELMovable {

returnVector = returnVector || new Vector2( 0, 0 );

// Convert to the magnet's local coordinate frame, writes to this.reusablePosition.
this.globalToLocalPosition( position, this.reusablePosition );
if ( FELQueryParameters.gradientField ) {

// Get strength in the magnet's local coordinate frame, writes to returnVector.
this.getLocalFieldVector( this.reusablePosition, returnVector );
// Create a B-field whose Bx changes linearly from left to right, and whose By is always 0.
const minX = FELConstants.GRADIENT_FIELD_X_RANGE.min;
const maxX = FELConstants.GRADIENT_FIELD_X_RANGE.max;
const minBx = FELQueryParameters.gradientField[ 0 ];
const maxBx = FELQueryParameters.gradientField[ 1 ];
const Bx = Utils.clamp( Utils.linear( minX, maxX, minBx, maxBx, position.x ), minBx, maxBx );
const By = 0;
returnVector.setXY( Bx, By );
}
else {
// Convert to the magnet's local coordinate frame, writes to this.reusablePosition.
this.globalToLocalPosition( position, this.reusablePosition );

// Get strength in the magnet's local coordinate frame, writes to returnVector.
this.getLocalFieldVector( this.reusablePosition, returnVector );

// Adjust the field vector to match the magnet's direction.
returnVector.rotate( this.rotationProperty.value );
// Adjust the field vector to match the magnet's direction.
returnVector.rotate( this.rotationProperty.value );

// Do not allow field vector magnitude to exceed magnet strength, due to small floating-point error.
// This was a problem in both the Java and HTML5 versions of the sim.
if ( returnVector.magnitude > this.strengthProperty.value ) {
returnVector.setMagnitude( this.strengthProperty.value );
// Do not allow field vector magnitude to exceed magnet strength, due to small floating-point error.
// This was a problem in both the Java and HTML5 versions of the sim.
if ( returnVector.magnitude > this.strengthProperty.value ) {
returnVector.setMagnitude( this.strengthProperty.value );
}
}
return returnVector;
}
Expand Down
11 changes: 10 additions & 1 deletion js/common/view/FELScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import ScreenView, { ScreenViewOptions } from '../../../../joist/js/ScreenView.j
import ResetAllButton from '../../../../scenery-phet/js/buttons/ResetAllButton.js';
import FELConstants from '../../common/FELConstants.js';
import faradaysElectromagneticLab from '../../faradaysElectromagneticLab.js';
import { Node } from '../../../../scenery/js/imports.js';
import { Line, Node } from '../../../../scenery/js/imports.js';
import Multilink from '../../../../axon/js/Multilink.js';
import FieldNode from '../../common/view/FieldNode.js';
import FieldMeterNode from '../../common/view/FieldMeterNode.js';
Expand All @@ -28,6 +28,7 @@ import Property from '../../../../axon/js/Property.js';
import PickupCoilNode from './PickupCoilNode.js';
import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import isSettingPhetioStateProperty from '../../../../tandem/js/isSettingPhetioStateProperty.js';
import FELQueryParameters from '../FELQueryParameters.js';

type SelfOptions = {

Expand Down Expand Up @@ -126,6 +127,14 @@ export default class FELScreenView extends ScreenView {
timeControlNode.bottom = visibleBounds.bottom - FELConstants.SCREEN_VIEW_Y_MARGIN;
} );
}

// Add vertical lines to show the range of x over which the gradient B-field extends.
if ( FELQueryParameters.gradientField ) {
const minX = FELConstants.GRADIENT_FIELD_X_RANGE.min;
const maxX = FELConstants.GRADIENT_FIELD_X_RANGE.max;
this.addChild( new Line( minX, this.layoutBounds.minY, minX, this.layoutBounds.maxY, { stroke: 'yellow' } ) );
this.addChild( new Line( maxX, this.layoutBounds.minY, maxX, this.layoutBounds.maxY, { stroke: 'yellow' } ) );
}
}

/**
Expand Down

1 comment on commit 9c1861f

@pixelzoom
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.