Class: Quantify::Dimensions
- Inherits:
-
Object
- Object
- Quantify::Dimensions
- Defined in:
- lib/quantify/dimensions.rb
Overview
The Dimensions class represents specfic physical quantities in terms of powers of their constituent base dimensions, e.g.:
area = length^2 force = mass^1 x length^1 x time^-2
Each dimension object is characterised by instance variables which describe the power (or index) of the respective base dimensions. Dimension objects can be manipulated - multiplied, divided, raised to powers, etc.
Standard physical quantities (e.g. length, acceleration, energy) are loaded into the @@dimensions class variable at runtime. These can be accessed, used and manipulated for arbitrary dimensional uses.
Instances of Dimensions are also used as the basis for defining and manipulating objects of the Unit::Base class.
Constant Summary collapse
- BASE_QUANTITIES =
The BASE_QUANTITIES array specifies the system of base quantities upon which all Dimensions objects are defined.
:information, :currency, :item represent tentative additions to the standard set of base quantities.
:item is intended to represent arbitrary ‘things’ for specifying quantities such as, for example:
‘dollars per capita’ (:currency => 1, :items => -1) ‘trees per hectare’ (:items => 1, :length => -2).
[ :mass, :length, :time, :electric_current, :temperature, :luminous_intensity, :amount_of_substance, :information, :currency, :item ]
- @@dimensions =
Class variable which holds in memory all defined (and ‘loaded’) quantities
[]
Instance Attribute Summary collapse
-
#physical_quantity ⇒ Object
Returns the value of attribute physical_quantity.
Class Method Summary collapse
-
.base_dimensions ⇒ Object
Returns an array of Dimensions objects representing just the base quantities, i.e.
-
.configure(&block) ⇒ Object
Syntactic sugar for defining the known quantities.
-
.dimensions ⇒ Object
Provides access the class array which holds all defined quantities.
-
.for(name) ⇒ Object
Retrieve a known quantity - returns a Dimensions instance, which is a clone of the initialized instance of the specified quantity.
-
.load(options) ⇒ Object
This method allows specific, named quantities to be initialized and loaded into the @@dimensions array.
-
.method_missing(method, *args, &block) ⇒ Object
Provides a shorthand for retrieving known quantities, e.g.:.
-
.physical_quantities ⇒ Object
Returns an array containing the names/descriptions of all known (loaded) physical quantities, e.g.:.
-
.unload(*unloaded_dimensions) ⇒ Object
Remove a dimension from the system of known dimensions.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Compares the base quantities of two Dimensions objects and returns true if they are the same.
-
#describe ⇒ Object
Return a description of what physical quantity self represents.
-
#divide(other) ⇒ Object
(also: #/)
Similar to #divide! but returns a new Dimensions instance representing the physical quantity which results from the division.
-
#divide!(other) ⇒ Object
Similar to #multiply! but performs a division of self by the specified Dimensions object.
-
#get_description ⇒ Object
Searches the system of known physical quantities (@@dimensions class array) looking for any which match self in terms of the configuration of base dimensions, i.e.
- #has_same_identity_as?(other) ⇒ Boolean
-
#initialize(options = {}) ⇒ Dimensions
constructor
Initialize a new Dimension object.
-
#is_base? ⇒ Boolean
Returns true if self represents one of the base quantities (i.e. length, mass, time, etc.).
-
#is_dimensionless? ⇒ Boolean
Returns true if self is a dimensionless quantity.
-
#is_known? ⇒ Boolean
Returns true if the physical quantity that self represents is known.
-
#is_molar_quantity? ⇒ Boolean
Method for identifying quantities which are ‘molar’ quantities, i.e quantities which represent a quantity of something *per mole*.
-
#is_specific_quantity? ⇒ Boolean
Method for identifying quantities which are ‘specific’ quantities, i.e quantities which represent a quantity of something *per unit mass*.
-
#load ⇒ Object
Load an already instantiated Dimensions object into the @@dimensions class array, from which it will be accessible as a universal representation of that physical quantity.
- #loaded? ⇒ Boolean
-
#multiply(other) ⇒ Object
(also: #times, #*)
Similar to #multiply! but returns a new Dimensions instance representing the physical quantity which results from the multiplication.
-
#multiply!(other) ⇒ Object
Multiplies self by another Dimensions object, returning self with an updated configuration of dimensions.
-
#pow(power) ⇒ Object
(also: #**)
Similar to #pow! but returns a new Dimensions instance representing the physical quantity which results from the raised power.
-
#pow!(power) ⇒ Object
Raises self to the power provided.
-
#reciprocalize ⇒ Object
Similar to #reciprocalize! but returns a new Dimensions instance representing the physical quantity which results from the inversion.
-
#reciprocalize! ⇒ Object
Inverts self, returning a representation of 1/self.
-
#si_base_units(by = nil) ⇒ Object
Returns an array representing the base SI units for the physical quantity described by self.
-
#si_unit ⇒ Object
Returns the SI unit for the physical quantity described by self.
-
#units(by = nil) ⇒ Object
Returns an array containing the known units which represent the physical quantity described by self.
-
#unload ⇒ Object
Remove from system of known units.
Constructor Details
#initialize(options = {}) ⇒ Dimensions
Initialize a new Dimension object.
The options argument is a hash which represents the base dimensions that define the physical quantity. Each key-value pair should consist of a key included in the BASE_QUANTITIES array, and a value which represents the index/power of that base quantity.
In addition, a name or description of the physical quantity can be specified (i.e. ‘acceleration’, ‘electric_current’). This is optional for creating a new Dimensions instance, but required if that object is to be loaded into the @@dimensions class array. e.g.:
Dimensions.new :physical_quantity => :density,
:mass => 1,
:length => -3
184 185 186 187 188 189 190 |
# File 'lib/quantify/dimensions.rb', line 184 def initialize(={}) if .has_key?(:physical_quantity) @physical_quantity = .delete(:physical_quantity).remove_underscores.downcase end enumerate_base_quantities() describe end |
Instance Attribute Details
#physical_quantity ⇒ Object
Returns the value of attribute physical_quantity.
166 167 168 |
# File 'lib/quantify/dimensions.rb', line 166 def physical_quantity @physical_quantity end |
Class Method Details
.base_dimensions ⇒ Object
Returns an array of Dimensions objects representing just the base quantities, i.e. length, mass, time, temperature, etc.
52 53 54 55 56 |
# File 'lib/quantify/dimensions.rb', line 52 def self.base_dimensions @@dimensions.select do |dimensions| BASE_QUANTITIES.map {|quantity| quantity.remove_underscores}.include?(dimensions.describe) end end |
.configure(&block) ⇒ Object
Syntactic sugar for defining the known quantities. This method simply evaluates code within the context of the Dimensions class, enabling the required quantities to be loaded at runtime, e.g.
Dimensions.configure do
load :physical_quantity => :length, :length => 1
load :physical_quantity => :area, :length => 2
load :physical_quantity => :power, :mass => 1, :length => 2, :time => -3
end
142 143 144 |
# File 'lib/quantify/dimensions.rb', line 142 def self.configure(&block) self.class_eval(&block) if block end |
.dimensions ⇒ Object
Provides access the class array which holds all defined quantities
45 46 47 |
# File 'lib/quantify/dimensions.rb', line 45 def self.dimensions @@dimensions end |
.for(name) ⇒ Object
Retrieve a known quantity - returns a Dimensions instance, which is a clone of the initialized instance of the specified quantity. This enables the object to be modified/manipulated without corrupting the representation of the quantity in the @@dimensions class array.
The required quantity name/descriptor can be specified as a symbol or a string, e.g.:
Dimensions.for :acceleration
Dimensions.for 'luminous_flux'
These can be shortened to, e.g. Dimensions.acceleration by virtue of the #method_missing class method (below)
116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/quantify/dimensions.rb', line 116 def self.for(name) return name if name.is_a? Dimensions if (name.is_a?(String) || name.is_a?(Symbol)) name = name.remove_underscores.downcase if quantity = @@dimensions.find { |quantity| quantity.physical_quantity == name } return quantity.clone else raise Exceptions::InvalidArgumentError, "Physical quantity not known: #{name}" end else raise Exceptions::InvalidArgumentError, "Argument must be a Symbol or String" end end |
.load(options) ⇒ Object
This method allows specific, named quantities to be initialized and loaded into the @@dimensions array. Quantities are specified by their consituent base dimensions, but must also include a name/description, i.e. ‘acceleration’, :force - indicated by the :physical_quantity key - in order to be included in the system of known dimensions, e.g.:
Dimensions.load :physical_quantity => :force,
:length => 1,
:mass => 1,
:time => -2
Standard quantities such as force, energy, mass, etc. should not need to be defined as they are included in the set of quantities already defined (see config.rb) and automatically loaded. These can be removed, overridden or configured differently if desired.
74 75 76 77 78 79 80 |
# File 'lib/quantify/dimensions.rb', line 74 def self.load() if [:physical_quantity] @@dimensions << Dimensions.new() else raise Exceptions::InvalidDimensionError, "Cannot load dimensions without physical quantity description" end end |
.method_missing(method, *args, &block) ⇒ Object
Provides a shorthand for retrieving known quantities, e.g.:
Dimensions.force
is equivalent to
Dimensions.for :force
Both variants return a clone of the initialized dimensional representation of the specified physical quantity (i.e. force).
157 158 159 160 161 162 |
# File 'lib/quantify/dimensions.rb', line 157 def self.method_missing(method, *args, &block) if dimensions = self.for(method) return dimensions end super end |
.physical_quantities ⇒ Object
Returns an array containing the names/descriptions of all known (loaded) physical quantities, e.g.:
Dimensions.physical_quantities #=> [ 'acceleration',
'area',
'electric Current',
... ]
98 99 100 |
# File 'lib/quantify/dimensions.rb', line 98 def self.physical_quantities @@dimensions.map {|dimension| dimension.physical_quantity } end |
.unload(*unloaded_dimensions) ⇒ Object
Remove a dimension from the system of known dimensions
83 84 85 86 87 88 |
# File 'lib/quantify/dimensions.rb', line 83 def self.unload(*unloaded_dimensions) [unloaded_dimensions].flatten.each do |unloaded_dimension| unloaded_dimension = Dimensions.for(unloaded_dimension) @@dimensions.delete_if { |dimension| dimension.has_same_identity_as? unloaded_dimension } end end |
Instance Method Details
#==(other) ⇒ Object
Compares the base quantities of two Dimensions objects and returns true if they are the same. This indicates that the two objects represent the same physical quantity (irrespective of their names - @physical_quantity - being similar, different, or absent.
330 331 332 |
# File 'lib/quantify/dimensions.rb', line 330 def ==(other) self.to_hash == other.to_hash end |
#describe ⇒ Object
Return a description of what physical quantity self represents. If no value is found in the @physical_quantity instance variable, the task is delegated to the #get_description method.
226 227 228 |
# File 'lib/quantify/dimensions.rb', line 226 def describe @physical_quantity or get_description end |
#divide(other) ⇒ Object Also known as: /
Similar to #divide! but returns a new Dimensions instance representing the physical quantity which results from the division.
399 400 401 |
# File 'lib/quantify/dimensions.rb', line 399 def divide(other) Dimensions.new(self.to_hash).divide! other end |
#divide!(other) ⇒ Object
Similar to #multiply! but performs a division of self by the specified Dimensions object.
390 391 392 393 394 |
# File 'lib/quantify/dimensions.rb', line 390 def divide!(other) enumerate_base_quantities(other.reciprocalize.to_hash) get_description return self end |
#get_description ⇒ Object
Searches the system of known physical quantities (@@dimensions class array) looking for any which match self in terms of the configuration of base dimensions, i.e. an object which dimensionally represents the same thing.
If found, the name/description of that quantity is assigned to the This method is useful in cases where Dimensions instances are manipulated using operators (e.g. multiply, divide, power, reciprocal), resulting in a change to the configuration of base dimensions (perhaps as a new instance). This method tries to find a description of the new quantity.
If none is found, self.physical_quantity is set to nil.
245 246 247 248 |
# File 'lib/quantify/dimensions.rb', line 245 def get_description similar = @@dimensions.find { |quantity| quantity == self } @physical_quantity = similar.nil? ? nil : similar.physical_quantity end |
#has_same_identity_as?(other) ⇒ Boolean
218 219 220 |
# File 'lib/quantify/dimensions.rb', line 218 def has_same_identity_as?(other) @physical_quantity == other.physical_quantity && !@physical_quantity.nil? end |
#is_base? ⇒ Boolean
Returns true if self represents one of the base quantities (i.e. length, mass, time, etc.)
346 347 348 349 |
# File 'lib/quantify/dimensions.rb', line 346 def is_base? base_quantities.size == 1 && self.instance_variable_get(base_quantities.first) == 1 ? true : false end |
#is_dimensionless? ⇒ Boolean
Returns true if self is a dimensionless quantity
340 341 342 |
# File 'lib/quantify/dimensions.rb', line 340 def is_dimensionless? base_quantities.empty? end |
#is_known? ⇒ Boolean
Returns true if the physical quantity that self represents is known
335 336 337 |
# File 'lib/quantify/dimensions.rb', line 335 def is_known? describe ? true : false end |
#is_molar_quantity? ⇒ Boolean
Method for identifying quantities which are ‘molar’ quantities, i.e quantities which represent a quantity of something *per mole*
361 362 363 |
# File 'lib/quantify/dimensions.rb', line 361 def is_molar_quantity? denominator_quantities == [:@amount_of_substance] end |
#is_specific_quantity? ⇒ Boolean
Method for identifying quantities which are ‘specific’ quantities, i.e quantities which represent a quantity of something *per unit mass*
354 355 356 |
# File 'lib/quantify/dimensions.rb', line 354 def is_specific_quantity? denominator_quantities == [:@mass] end |
#load ⇒ Object
Load an already instantiated Dimensions object into the @@dimensions class array, from which it will be accessible as a universal representation of that physical quantity.
Object must include a non-nil @physical_quantity attribute, i.e. a name or description of the physical quantity represented.
199 200 201 202 203 204 205 206 207 |
# File 'lib/quantify/dimensions.rb', line 199 def load if describe && !loaded? @@dimensions << self elsif describe raise Exceptions::InvalidDimensionError, "A dimension instance with the same physical quantity already exists" else raise Exceptions::InvalidDimensionError, "Cannot load dimensions without physical quantity description" end end |
#loaded? ⇒ Boolean
209 210 211 |
# File 'lib/quantify/dimensions.rb', line 209 def loaded? Dimensions.dimensions.any? { |quantity| self.has_same_identity_as? quantity } end |
#multiply(other) ⇒ Object Also known as: times, *
Similar to #multiply! but returns a new Dimensions instance representing the physical quantity which results from the multiplication.
381 382 383 |
# File 'lib/quantify/dimensions.rb', line 381 def multiply(other) Dimensions.new(self.to_hash).multiply! other end |
#multiply!(other) ⇒ Object
Multiplies self by another Dimensions object, returning self with an updated configuration of dimensions. Since this is likely to have resulted in the representation of a different physical quantity than was originally represented, the #get_description method is invoked to attempt to find a suitable description.
372 373 374 375 376 |
# File 'lib/quantify/dimensions.rb', line 372 def multiply!(other) enumerate_base_quantities(other.to_hash) get_description return self end |
#pow(power) ⇒ Object Also known as: **
Similar to #pow! but returns a new Dimensions instance representing the physical quantity which results from the raised power.
423 424 425 |
# File 'lib/quantify/dimensions.rb', line 423 def pow(power) Dimensions.new(self.to_hash).pow!(power) end |
#pow!(power) ⇒ Object
Raises self to the power provided. As with multiply and divide, the #get_description method is invoked to attempt to find a suitable description for the new quantity represented.
408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/quantify/dimensions.rb', line 408 def pow!(power) make_dimensionless if power == 0 if power < 0 self.reciprocalize! power *= -1 end original_dimensions = self.clone (power - 1).times { self.multiply!(original_dimensions) } get_description return self end |
#reciprocalize ⇒ Object
Similar to #reciprocalize! but returns a new Dimensions instance representing the physical quantity which results from the inversion.
444 445 446 |
# File 'lib/quantify/dimensions.rb', line 444 def reciprocalize Dimensions.new(self.to_hash).reciprocalize! end |
#reciprocalize! ⇒ Object
Inverts self, returning a representation of 1/self. This is equivalent to raising to the power -1. The #get_description method is invoked to attempt to find a suitable description for the new quantity represented.
432 433 434 435 436 437 438 439 |
# File 'lib/quantify/dimensions.rb', line 432 def reciprocalize! base_quantities.each do |variable| new_value = self.instance_variable_get(variable) * -1 self.instance_variable_set(variable, new_value) end get_description return self end |
#si_base_units(by = nil) ⇒ Object
Returns an array representing the base SI units for the physical quantity described by self
If no argument is given, the array holds instances of Unit::Base (or subclasses) which represent each base unit. Alternatively only the names or symbols of each unit can be returned by providing the appropriate unit attribute as a symbolized argument, e.g.
Dimensions.energy.si_base_units #=> [ #<Quantify::Unit: .. >,
#<Quantify::Unit: .. >,
... ]
Dimensions.energy.si_base_units :name
#=> [ "metre squared",
"per second squared",
"kilogram"] #
Dimensions.force.units :symbol #=> [ "m", "s^-2", "kg"]
317 318 319 320 321 322 323 |
# File 'lib/quantify/dimensions.rb', line 317 def si_base_units(by=nil) self.to_hash.map do |dimension,index| Unit.base_quantity_si_units.select do |unit| unit.measures == dimension.remove_underscores end.first.clone ** index end.map(&by).to_a end |
#si_unit ⇒ Object
Returns the SI unit for the physical quantity described by self.
Plane/solid angle are special cases which are dimensionless units, and so are handled explicitly. Otherwise, the si base units for each of the base dimensions of self are indentified and the corresponding compound unit is derived. If this new unit is the same as a known (SI derived) unit, the known unit is returned.
Dimensions.energy.units #=> #<Quantify::Dimensions: .. >
Dimensions.energy.si_unit.name #=> 'joule'
Dimensions.kinematic_viscosity.si_unit.name
#=> 'metre squared per second'
287 288 289 290 291 292 293 294 295 |
# File 'lib/quantify/dimensions.rb', line 287 def si_unit return Unit.steridian if describe == 'solid angle' return Unit.radian if describe == 'plane angle' return si_base_units.inject(Unit.unity) do |compound,unit| compound * unit end.or_equivalent rescue return nil end |
#units(by = nil) ⇒ Object
Returns an array containing the known units which represent the physical quantity described by self
If no argument is given, the array holds instances of Unit::Base (or subclasses) which represent each unit. Alternatively only the names or symbols of each unit can be returned by providing the appropriate unit attribute as a symbolized argument, e.g.
Dimensions.energy.units #=> [ #<Quantify::Dimensions: .. >,
#<Quantify::Dimensions: .. >,
... ]
Dimensions.mass.units :name #=> [ 'kilogram', 'ounce',
'pound', ... ]
Dimensions.length.units :symbol #=> [ 'm', 'ft', 'yd', ... ]
267 268 269 |
# File 'lib/quantify/dimensions.rb', line 267 def units(by=nil) Unit.units.select { |unit| unit.dimensions == self }.map(&by).to_a end |
#unload ⇒ Object
Remove from system of known units.
214 215 216 |
# File 'lib/quantify/dimensions.rb', line 214 def unload Dimensions.unload(self.physical_quantity) end |