ilm 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +99 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ilm.gemspec +45 -0
- data/lib/class_overrides.rb +6 -0
- data/lib/ilm.rb +14 -0
- data/lib/ilm/chemical.rb +7 -0
- data/lib/ilm/chemical/reactors.rb +10 -0
- data/lib/ilm/chemical/reactors/batch_reactor.rb +16 -0
- data/lib/ilm/chemical/reactors/continuous_stirred_tank_reactor.rb +30 -0
- data/lib/ilm/chemical/reactors/plug_flow_reactor.rb +14 -0
- data/lib/ilm/chemical/reactors/reactor.rb +81 -0
- data/lib/ilm/chemistry.rb +8 -0
- data/lib/ilm/chemistry/compound.rb +61 -0
- data/lib/ilm/chemistry/element.rb +53 -0
- data/lib/ilm/chemistry/elements.csv +110 -0
- data/lib/ilm/chemistry/reaction.rb +156 -0
- data/lib/ilm/chemistry/substance.rb +18 -0
- data/lib/ilm/structures.rb +6 -0
- data/lib/ilm/structures/pipe.rb +13 -0
- data/lib/ilm/structures/structure.rb +12 -0
- data/lib/ilm/version.rb +3 -0
- data/lib/matrix_overrides.rb +22 -0
- data/lib/string_overrides.rb +16 -0
- metadata +187 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4c67e12299f88a4bb312a67bd7bb37a1d1b829fc93ffdeb4d87acc826eae8fcb
|
4
|
+
data.tar.gz: 5434f80608d68863df2fd4e5a8be083a076c825d7a09947b040edfd862a69527
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 801f05d4c616bad30cc1cbb9e4bc3b00742de17574f0e4c9af4a547ae25ae0ade896f99619d548f3a3139915dff847fc547f0d72972a4e54103d63ef259b2f16
|
7
|
+
data.tar.gz: 56dbc9694e76f33333f97bb3bf5cb2c55a131943494d6ecd5371f1a3058fa7c5c6472cf0c2163b8eb8cc6d2f267c260c08a228023ff1c45ee117400d3f586fde
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at fazil.basheer@quester.xyz. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 syedfazilbasheer-quester
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 syedfazilbasheer-quester
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# Ilm
|
2
|
+
Ilm is a Ruby gem for Chemistry, which supports the calculation of molecular mass of compound, balancing chemical equations and efficient handling of states of chemical species.
|
3
|
+
|
4
|
+
We aim to make Ilm easy to use, fast and accurate chemistry library, with complete test coverage.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'ilm'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install ilm
|
21
|
+
|
22
|
+
## Modules
|
23
|
+
|
24
|
+
* Structrues
|
25
|
+
* Chemistry
|
26
|
+
|
27
|
+
### Structures
|
28
|
+
* Pipe
|
29
|
+
|
30
|
+
### Chemistry
|
31
|
+
|
32
|
+
* Element
|
33
|
+
* Compound
|
34
|
+
* Reaction
|
35
|
+
|
36
|
+
#### Element
|
37
|
+
|
38
|
+
* H, He, Li, Be, B, C, N, O, F, Ne, Na, Mg, Al, Si, P, S, Cl, Ar, K , Ca, Sc, Ti, V, Cr, Mn, Fe, Co, Ni, Cu, Zn, Ga, Ge, As, Se, Br, Kr, Rb, Sr, Y, Zr, Nb, Mo, Tc, Ru, Rh, Pd, Ag, Cd, In, Sn, Sb, Te, I, Xe, Cs, Ba, La, Ce, Pr, Nd, Pm, Sm, Eu, Gd, Tb, Dy, Ho, Er, Tm, Yb, Lu, Hf, Ta, W, Re, Os, Ir, Pt, Au, Hg, Tl, Pb, Bi, Po, At, Rn, Fr, Ra, Ac, Th, Pa, U, Np, Pu, Am, Cm, Bk, Cf, Es, Fm, Md, No, Lr, Rf, Db, Sg, Bh, Hs, Mt,
|
39
|
+
* attributes: symbol, name, atomic_number, atomic_mass
|
40
|
+
* methods: get_by_* (* can be any of the attributes)
|
41
|
+
|
42
|
+
#### Compound
|
43
|
+
|
44
|
+
* attributes: formula, molecular_mass, constituents
|
45
|
+
* methods: new('compound formula')
|
46
|
+
|
47
|
+
### Reaction
|
48
|
+
|
49
|
+
* attributes: equation, is_valid, is_balanced, species, balanced_eqn
|
50
|
+
* methods: new(equation: "Put your reaction string here", rate_equation: "r_{CaCo3} = k[CaO]")
|
51
|
+
* For eg: (equation: '2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)', rate_equation: "rNa = k[HCl]")
|
52
|
+
|
53
|
+
## Usage
|
54
|
+
```bash
|
55
|
+
$ Ilm::Chemistry::Element.get_by_symbol "H"
|
56
|
+
=> #<Ilm::Chemistry::Element:0x000000025e5ab8 @name="Hydrogen", @symbol="H", @atomic_number=1, @atomic_mass=#<Unitwise::Measurement value=1.0079 unit=u>>
|
57
|
+
|
58
|
+
$ Ilm::Chemistry::Element.get_by_atomic_number 12
|
59
|
+
=> #<Ilm::Chemistry::Element:0x00000002c87560 @name="Magnesium", @symbol="Mg", @atomic_number=12, @atomic_mass=#<Unitwise::Measurement value=24.305 unit=u>>
|
60
|
+
|
61
|
+
$ Ilm::Chemistry::Element.get_by_name "helium" # or "Helium"
|
62
|
+
=> #<Ilm::Chemistry::Element:0x00000002ca66e0 @name="Helium", @symbol="He", @atomic_number=2, @atomic_mass=#<Unitwise::Measurement value=4.002602 unit=u>>
|
63
|
+
|
64
|
+
$ Ilm::Chemistry::Compound.new("CaCO3")
|
65
|
+
=> #<Ilm::Chemistry::Compound:0x00000002a65340 @formula="CaCO3", @constituents={"Ca"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c805a8 @name="Calcium", @symbol="Ca", @atomic_number=20, @atomic_mass=#<Unitwise::Measurement value=40.078 unit=u>>, :atom_count=>1}, "C"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c8f6e8 @name="Carbon", @symbol="C", @atomic_number=6, @atomic_mass=#<Unitwise::Measurement value=12.0107 unit=u>>, :atom_count=>1}, "O"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c8dc30 @name="Oxygen", @symbol="O", @atomic_number=8, @atomic_mass=#<Unitwise::Measurement value=15.9996 unit=u>>, :atom_count=>3}}, @molecular_mass=#<Unitwise::Measurement value=100.0875 unit=u>>
|
66
|
+
|
67
|
+
$ Ilm::Chemistry::Reaction.new(equation: 'KMnO4 + HCl >> KCl + MnCl2 + H2O + Cl2').balanced_eqn
|
68
|
+
=> "2KMnO4 + 16HCl >> 2KCl + 2MnCl2 + 8H2O + 5Cl2"
|
69
|
+
|
70
|
+
$ Ilm::Chemistry::Reaction.new(equation: '2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)').equation
|
71
|
+
=> "2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)"
|
72
|
+
|
73
|
+
$ Ilm::Chemistry::Reaction.new(equation: '2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)').is_valid
|
74
|
+
=> true
|
75
|
+
|
76
|
+
$ Ilm::Chemistry::Reaction.new(equation: '2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)').is_balanced
|
77
|
+
=> true
|
78
|
+
|
79
|
+
$ Ilm::Chemistry::Reaction.new(equation: '2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)').species
|
80
|
+
=> {:reactants=>{"Na"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002ca6910 @formula="Na", @constituents={"Na"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c88e10 @name="Sodium", @symbol="Na", @atomic_number=11, @atomic_mass=#<Unitwise::Measurement value=22.9897 unit=u>>, :atom_count=>1}}, @molecular_mass=#<Unitwise::Measurement value=22.9897 unit=u>>, :stoichiometry=>2, :state=>"solid"}, "HCl"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002c90ed0 @formula="HCl", @constituents={"H"=>{:element=>#<Ilm::Chemistry::Element:0x000000025e5ab8 @name="Hydrogen", @symbol="H", @atomic_number=1, @atomic_mass=#<Unitwise::Measurement value=1.0079 unit=u>>, :atom_count=>1}, "Cl"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c82c90 @name="Chlorine", @symbol="Cl", @atomic_number=17, @atomic_mass=#<Unitwise::Measurement value=35.453 unit=u>>, :atom_count=>1}}, @molecular_mass=#<Unitwise::Measurement value=36.4609 unit=u>>, :stoichiometry=>2, :state=>"aqueous"}}, :products=>{"NaCl"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002c73bf0 @formula="NaCl", @constituents={"Na"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c88e10 @name="Sodium", @symbol="Na", @atomic_number=11, @atomic_mass=#<Unitwise::Measurement value=22.9897 unit=u>>, :atom_count=>1}, "Cl"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c82c90 @name="Chlorine", @symbol="Cl", @atomic_number=17, @atomic_mass=#<Unitwise::Measurement value=35.453 unit=u>>, :atom_count=>1}}, @molecular_mass=#<Unitwise::Measurement value=58.4427 unit=u>>, :stoichiometry=>2, :state=>"aqueous"}, "H2"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002c34180 @formula="H2", @constituents={"H"=>{:element=>#<Ilm::Chemistry::Element:0x000000025e5ab8 @name="Hydrogen", @symbol="H", @atomic_number=1, @atomic_mass=#<Unitwise::Measurement value=1.0079 unit=u>>, :atom_count=>2}}, @molecular_mass=#<Unitwise::Measurement value=2.0158 unit=u>>, :stoichiometry=>1, :state=>"gaseous"}}}
|
81
|
+
|
82
|
+
$ Ilm::Chemistry::Reaction.new(equation: '2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)')
|
83
|
+
=> #<Ilm::Chemistry::Reaction:0x00000002ce22f8 @equation="2Na(s) + 2HCl(aq) >> 2NaCl(aq) + H2(g)", @species={:reactants=>{"Na"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002ce1d80 @formula="Na", @constituents={"Na"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c88e10 @name="Sodium", @symbol="Na", @atomic_number=11, @atomic_mass=#<Unitwise::Measurement value=22.9897 unit=u>>, :atom_count=>1}}, @molecular_mass=#<Unitwise::Measurement value=22.9897 unit=u>>, :stoichiometry=>2, :state=>"solid"}, "HCl"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002cabdc0 @formula="HCl", @constituents={"H"=>{:element=>#<Ilm::Chemistry::Element:0x000000025e5ab8 @name="Hydrogen", @symbol="H", @atomic_number=1, @atomic_mass=#<Unitwise::Measurement value=1.0079 unit=u>>, :atom_count=>1}, "Cl"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c82c90 @name="Chlorine", @symbol="Cl", @atomic_number=17, @atomic_mass=#<Unitwise::Measurement value=35.453 unit=u>>, :atom_count=>1}}, @molecular_mass=#<Unitwise::Measurement value=36.4609 unit=u>>, :stoichiometry=>2, :state=>"aqueous"}}, :products=>{"NaCl"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002c8cda8 @formula="NaCl", @constituents={"Na"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c88e10 @name="Sodium", @symbol="Na", @atomic_number=11, @atomic_mass=#<Unitwise::Measurement value=22.9897 unit=u>>, :atom_count=>1}, "Cl"=>{:element=>#<Ilm::Chemistry::Element:0x00000002c82c90 @name="Chlorine", @symbol="Cl", @atomic_number=17, @atomic_mass=#<Unitwise::Measurement value=35.453 unit=u>>, :atom_count=>1}}, @molecular_mass=#<Unitwise::Measurement value=58.4427 unit=u>>, :stoichiometry=>2, :state=>"aqueous"},"H2"=>{:compound=>#<Ilm::Chemistry::Compound:0x00000002c6f938 @formula="H2", @constituents={"H"=>{:element=>#<Ilm::Chemistry::Element:0x000000025e5ab8 @name="Hydrogen", @symbol="H", @atomic_number=1, @atomic_mass=#<Unitwise::Measurement value=1.0079 unit=u>>, :atom_count=>2}}, @molecular_mass=#<Unitwise::Measurement value=2.0158 unit=u>>, :stoichiometry=>1, :state=>"gaseous"}}}, @is_valid=true, @is_balanced=true>
|
84
|
+
```
|
85
|
+
## Development
|
86
|
+
|
87
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
88
|
+
|
89
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
90
|
+
|
91
|
+
## Contributing
|
92
|
+
|
93
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/syedfazilbasheer-quester/ilm-gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
94
|
+
|
95
|
+
|
96
|
+
## License
|
97
|
+
|
98
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
99
|
+
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'ilm'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require 'pry'
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/ilm.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'ilm/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'ilm'
|
9
|
+
spec.version = Ilm::VERSION
|
10
|
+
spec.authors = ['Syed Fazil Basheer', 'Somesh Choudhary']
|
11
|
+
spec.email = ['fazil.basheer@quester.xyz', 'c.somesh5@gmail.com']
|
12
|
+
|
13
|
+
spec.summary = 'A gem for scientific data.'
|
14
|
+
spec.description = 'A gem for scientific data.'
|
15
|
+
spec.homepage = 'https://github.com/ilm-labs/ilm'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
# Prevent pushing this gem to RubyGems.org.
|
19
|
+
# To allow pushes either set the 'allowed_push_host'
|
20
|
+
# to allow pushing to a single host
|
21
|
+
# or delete this section to allow pushing to any host.
|
22
|
+
# if spec.respond_to?(:metadata)
|
23
|
+
# spec.metadata['allowed_push_host'] =
|
24
|
+
# 'https://github.com/ilm-labs/ilm'
|
25
|
+
# else
|
26
|
+
# raise 'RubyGems 2.0 or newer is required to protect against ' \
|
27
|
+
# 'public gem pushes.'
|
28
|
+
# end
|
29
|
+
|
30
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
31
|
+
f.match(%r{^(test|spec|features)/})
|
32
|
+
end
|
33
|
+
spec.bindir = 'exe'
|
34
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
35
|
+
spec.require_paths = ['lib']
|
36
|
+
|
37
|
+
spec.add_development_dependency 'bundler', '~> 2.0', '>= 2.0.1'
|
38
|
+
spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.2'
|
39
|
+
spec.add_development_dependency 'rspec', '~> 3.8'
|
40
|
+
spec.add_development_dependency 'rubocop', '~> 0.67.2'
|
41
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.1'
|
42
|
+
|
43
|
+
spec.add_dependency 'rubypython', '~> 0.6.4'
|
44
|
+
spec.add_dependency 'unitwise', '~>2.2'
|
45
|
+
end
|
data/lib/ilm.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative 'matrix_overrides'
|
2
|
+
require_relative 'string_overrides'
|
3
|
+
require_relative 'class_overrides'
|
4
|
+
require 'unitwise'
|
5
|
+
|
6
|
+
# Root module. Everything in the gem goes inside this
|
7
|
+
module Ilm
|
8
|
+
end
|
9
|
+
|
10
|
+
def Unitwise(*args)
|
11
|
+
regex = /(\d+)(.*)/
|
12
|
+
args = args.first.scan(regex).first.collect(&:strip) if args.count == 1
|
13
|
+
Unitwise::Measurement.new(*args.first.to_f, *args.last)
|
14
|
+
end
|
data/lib/ilm/chemical.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative 'reactor'
|
2
|
+
|
3
|
+
module Ilm
|
4
|
+
module Chemical
|
5
|
+
module Reactors
|
6
|
+
# This class is for batch reactors
|
7
|
+
# assumptions: well mixed, closed system
|
8
|
+
class BatchReactor < Reactor
|
9
|
+
def initialize(args = {})
|
10
|
+
super args
|
11
|
+
@system = args[:system] == :isolated ? :isolated : :closed
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'reactor'
|
2
|
+
|
3
|
+
module Ilm
|
4
|
+
module Chemical
|
5
|
+
module Reactors
|
6
|
+
# This class is for cst reactors
|
7
|
+
class ContinuousStirredTankReactor < Reactor
|
8
|
+
def initialize(args = {})
|
9
|
+
super args
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_volume
|
13
|
+
# accumulation is zero
|
14
|
+
compound_formula = @reaction.rate_equation.split(' ').first.split('r').last
|
15
|
+
ci = @input[:substance].species[compound_formula]
|
16
|
+
co = @output[:substance].species[compound_formula]
|
17
|
+
input = @input[:quantity] * ci[:weight_percent] /
|
18
|
+
(100 * ci[:compound].molar_mass)
|
19
|
+
output = @output[:quantity] * co[:weight_percent] /
|
20
|
+
(100 * co[:compound].molar_mass)
|
21
|
+
x = (input - output) / input
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.humanized_name
|
25
|
+
'Continuous stirred-tank reactor'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Ilm
|
2
|
+
module Chemical
|
3
|
+
module Reactors
|
4
|
+
# This is the base class for the diff kinds of reactors
|
5
|
+
class Reactor
|
6
|
+
attr_reader :system, :volume, :input, :output, :reaction
|
7
|
+
|
8
|
+
# ATTRS = [:system, :volume, :input, :output, :rate_equation]
|
9
|
+
|
10
|
+
def initialize(args = {})
|
11
|
+
self.system = args[:system]
|
12
|
+
self.volume = args[:volume] if args[:volume]
|
13
|
+
self.input = args[:input] if args[:input]
|
14
|
+
self.output = args[:output] if args[:output]
|
15
|
+
self.reaction = args[:reaction] if args[:reaction]
|
16
|
+
end
|
17
|
+
|
18
|
+
def system=(sys)
|
19
|
+
@system = sys || :open
|
20
|
+
end
|
21
|
+
|
22
|
+
def volume=(vol)
|
23
|
+
@volume = volume_if_valid vol
|
24
|
+
end
|
25
|
+
|
26
|
+
def input=(inp)
|
27
|
+
@input = feed_if_valid inp
|
28
|
+
end
|
29
|
+
|
30
|
+
def output=(out)
|
31
|
+
@output = feed_if_valid out
|
32
|
+
end
|
33
|
+
|
34
|
+
def reaction=(rxn)
|
35
|
+
@reaction = reaction_if_valid rxn
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def volume_if_valid(vol)
|
41
|
+
begin
|
42
|
+
vol = Unitwise vol
|
43
|
+
rescue
|
44
|
+
raise ArgumentError, 'Invalid volume'
|
45
|
+
end
|
46
|
+
return vol if vol.composition.to_h == { 'L' => 3 }
|
47
|
+
|
48
|
+
raise ArgumentError, 'Invalid volume unit'
|
49
|
+
end
|
50
|
+
|
51
|
+
def feed_if_valid(f)
|
52
|
+
raise ArgumentError, 'Invalid substance' if f[:substance].class != Ilm::Chemistry::Substance
|
53
|
+
|
54
|
+
begin
|
55
|
+
f[:quantity] = Unitwise f[:quantity]
|
56
|
+
rescue
|
57
|
+
raise ArgumentError, 'Invalid quantity'
|
58
|
+
end
|
59
|
+
dim = f[:quantity].composition.to_h
|
60
|
+
return f if valid_feed_quantity_dimensions.include? dim
|
61
|
+
|
62
|
+
raise ArgumentError, 'Invalid quantity unit'
|
63
|
+
end
|
64
|
+
|
65
|
+
def valid_feed_quantity_dimensions
|
66
|
+
[{ 'M' => 1 }, { 'M' => 1, 'T' => -1 }]
|
67
|
+
end
|
68
|
+
|
69
|
+
def reaction_if_valid(r)
|
70
|
+
# raise ArgumentError, 'Substance not in reaction' if
|
71
|
+
# @input && (
|
72
|
+
# r.species[:reactants].keys &
|
73
|
+
# @input[:substance].species.keys
|
74
|
+
# ).empty?
|
75
|
+
return r if r.class == Ilm::Chemistry::Reaction && r.is_valid
|
76
|
+
raise ArgumentError, 'Invalid reaction argument'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'unitwise'
|
2
|
+
|
3
|
+
module Ilm
|
4
|
+
module Chemistry
|
5
|
+
# This class has functionality for compounds
|
6
|
+
# Ex: constituent elements, molecular mass, etc
|
7
|
+
class Compound
|
8
|
+
COMPOUND_REGEXP =
|
9
|
+
/[A-Z][a-z]{0,2}\d*|\((?:[^()]*(?:\(.*\))?[^()]*)+\)\d*/
|
10
|
+
|
11
|
+
attr_accessor :molecular_mass, :constituents, :formula, :molar_mass
|
12
|
+
|
13
|
+
def initialize(arg)
|
14
|
+
@formula = arg
|
15
|
+
build_constituents
|
16
|
+
calculate_mass
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def calculate_mass
|
22
|
+
@molecular_mass = Unitwise(0.0, 'u')
|
23
|
+
@constituents.each do |_symbol, info|
|
24
|
+
@molecular_mass += info[:element].atomic_mass * info[:atom_count]
|
25
|
+
end
|
26
|
+
@molar_mass = Unitwise(@molecular_mass.value / 1000.0, 'kg/mol')
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_constituents
|
30
|
+
@constituents = {}
|
31
|
+
get_const_atoms.each do |symbol, count|
|
32
|
+
@constituents[symbol] = {
|
33
|
+
element: Element.get_by_symbol(symbol),
|
34
|
+
atom_count: count
|
35
|
+
}
|
36
|
+
end
|
37
|
+
@constituents
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_const_atoms(formula = @formula, r = {})
|
41
|
+
formula.scan(COMPOUND_REGEXP).each do |const|
|
42
|
+
multipler = get_multipler const
|
43
|
+
if const[0] != '(' && multipler.zero?
|
44
|
+
r[const] = r[const] ? r[const] + 1 : 1
|
45
|
+
else
|
46
|
+
(multipler.zero? ? 1 : multipler).times do
|
47
|
+
sub_const = const.match(/^\(?(.*?)\)?($|\d*$)/).to_a
|
48
|
+
get_const_atoms sub_const[const == sub_const.first ? 1 : 0], r
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
r
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_multipler(const)
|
56
|
+
multipler = const.match(/\d*$/).to_a.first.to_i
|
57
|
+
multipler
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'csv'
|
2
|
+
require 'unitwise'
|
3
|
+
|
4
|
+
module Ilm
|
5
|
+
module Chemistry
|
6
|
+
# This class has functionality for elements
|
7
|
+
# Ex: symbol, atomic mass, atomic number
|
8
|
+
class Element
|
9
|
+
attr_accessor :atomic_mass, :symbol, :name, :atomic_number
|
10
|
+
|
11
|
+
ATTRS = %w[symbol name atomic_number atomic_mass].freeze
|
12
|
+
# Data taken from 'www.science.co.il/elements/'
|
13
|
+
ELEMENTS = []
|
14
|
+
|
15
|
+
def initialize(arg)
|
16
|
+
@name = arg[1]
|
17
|
+
@symbol = arg[0]
|
18
|
+
@atomic_number = arg[2].to_i
|
19
|
+
@atomic_mass = Unitwise(arg[3].to_f, 'u')
|
20
|
+
end
|
21
|
+
|
22
|
+
CSV.foreach(File.join(File.dirname(__FILE__), 'elements.csv'), headers: true) do |row|
|
23
|
+
ELEMENTS << new(row)
|
24
|
+
end
|
25
|
+
|
26
|
+
private_class_method def self.method_missing(m, *args)
|
27
|
+
attribute = m.to_s.split('get_by_').last
|
28
|
+
valid_method? m, attribute
|
29
|
+
raise 'please give argument' if args.empty?
|
30
|
+
args[0] = attribute == 'name' ? args[0].capitalize : args[0]
|
31
|
+
element_data = get_element_by_attribute attribute, args[0]
|
32
|
+
raise 'Element not found' unless element_data
|
33
|
+
element_data
|
34
|
+
end
|
35
|
+
|
36
|
+
private_class_method def self.get_element_by_attribute(attribute, value)
|
37
|
+
ELEMENTS.each do |element|
|
38
|
+
# elements value of attribute == value give by user
|
39
|
+
return element if
|
40
|
+
element.instance_variable_get(('@' + attribute).intern) == value
|
41
|
+
end
|
42
|
+
raise(NameError, 'element not found')
|
43
|
+
end
|
44
|
+
|
45
|
+
private_class_method def self.valid_method?(m, attribute)
|
46
|
+
super unless m.to_s.start_with?('get_by_')
|
47
|
+
raise(NameError, 'Invalid attribute') unless ATTRS.include? attribute
|
48
|
+
end
|
49
|
+
|
50
|
+
private_class_method :new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
symbol,name,atomic_number,atomic_weight
|
2
|
+
H,Hydrogen,1,1.0079
|
3
|
+
He,Helium,2,4.002602
|
4
|
+
Li,Lithium,3,6.941
|
5
|
+
Be,Beryllium,4,9.012182
|
6
|
+
B,Boron,5,10.811
|
7
|
+
C,Carbon,6,12.0107
|
8
|
+
N,Nitrogen,7,14.0067
|
9
|
+
O,Oxygen,8,15.9996
|
10
|
+
F,Fluorine,9,18.9984
|
11
|
+
Ne,Neon,10,20.1797
|
12
|
+
Na,Sodium,11,22.9897
|
13
|
+
Mg,Magnesium,12,24.305
|
14
|
+
Al,Aluminium,13,26.9815
|
15
|
+
Si,Silicon,14,28.0855
|
16
|
+
P,Phosphorus,15,30.9738
|
17
|
+
S,Sulfur,16,32.065
|
18
|
+
Cl,Chlorine,17,35.453
|
19
|
+
Ar,Argon,18,39.948
|
20
|
+
K,Potassium,19,39.0983
|
21
|
+
Ca,Calcium,20,40.078
|
22
|
+
Sc,Scandium,21,44.9559
|
23
|
+
Ti,Titanium,22,47.867
|
24
|
+
V,Vanadium,23,50.9415
|
25
|
+
Cr,Chromium,24,51.9961
|
26
|
+
Mn,Manganese,25,54.938
|
27
|
+
Fe,Iron,26,55.845
|
28
|
+
Co,Cobalt,27,58.9332
|
29
|
+
Ni,Nickel,28,58.6934
|
30
|
+
Cu,Copper,29,63.546
|
31
|
+
Zn,Zinc,30,65.39
|
32
|
+
Ga,Gallium,31,69.723
|
33
|
+
Ge,Germanium,32,72.64
|
34
|
+
As,Arsenic,33,74.9216
|
35
|
+
Se,Selenium,34,78.96
|
36
|
+
Br,Bromine,35,79.904
|
37
|
+
Kr,Krypton,36,83.3
|
38
|
+
Rb,Rubidium,37,85.4678
|
39
|
+
Sr,Strontium,38,87.62
|
40
|
+
Y,Yttrium,39,88.9059
|
41
|
+
Zr,Zirconium,40,91.224
|
42
|
+
Nb,Niobium,41,92.9064
|
43
|
+
Mo,Molybdenum,42,95.94
|
44
|
+
Tc,Technitium,43,98
|
45
|
+
Ru,Ruthenium,44,101.07
|
46
|
+
Rh,Rhodium,45,102.9055
|
47
|
+
Pd,Palladium,46,106.42
|
48
|
+
Ag,Silver,47,107.8682
|
49
|
+
Cd,Cadmiuim,48,112.411
|
50
|
+
In,Indium,49,114.818
|
51
|
+
Sn,Tin,50,118.71
|
52
|
+
Sb,Antimony,51,121.76
|
53
|
+
Te,Tellurium,52,127.6
|
54
|
+
I,Iodine,53,126.9045
|
55
|
+
Xe,Xenon,54,131.293
|
56
|
+
Cs,Cesium,55,132.9055
|
57
|
+
Ba,Barium,56,137.327
|
58
|
+
La,Lanthanum,57,138.9055
|
59
|
+
Ce,Cerium,58,140.116
|
60
|
+
Pr,Praseodymium,59,140.9077
|
61
|
+
Nd,Neodymium,60,144.24
|
62
|
+
Pm,Promethium,61,145
|
63
|
+
Sm,Samarium,62,150.36
|
64
|
+
Eu,Europium,63,151.964
|
65
|
+
Gd,Gadolium,64,157.25
|
66
|
+
Tb,Terbium,65,158.9253
|
67
|
+
Dy,Dysprosium,66,162.5
|
68
|
+
Ho,Holmium,67,164.9303
|
69
|
+
Er,Erbium,68,167.259
|
70
|
+
Tm,Thulium,69,168.9342
|
71
|
+
Yb,Ytterbium,70,173.04
|
72
|
+
Lu,Lutetium,71,174.967
|
73
|
+
Hf,Hafnium,72,178.49
|
74
|
+
Ta,Tantalum,73,180.9479
|
75
|
+
W,Tungsten,74,183.84
|
76
|
+
Re,Rhenium,75,186.207
|
77
|
+
Os,Osmium,76,190.23
|
78
|
+
Ir,Iridium,77,192.217
|
79
|
+
Pt,Platinum,78,195.078
|
80
|
+
Au,Gold,79,196.9665
|
81
|
+
Hg,Mercury,80,200.59
|
82
|
+
Tl,Thallium,81,204.3833
|
83
|
+
Pb,Lead,82,207.2
|
84
|
+
Bi,Bismuth,83,208.9804
|
85
|
+
Po,Polonium,84,209
|
86
|
+
At,Astatine,85,210
|
87
|
+
Rn,Radon,86,222
|
88
|
+
Fr,Francium,87,223
|
89
|
+
Ra,Radium,88,226
|
90
|
+
Ac,Actinium,89,227
|
91
|
+
Th,Thorium,90,232.0381
|
92
|
+
Pa,Protactinium,91,231.0359
|
93
|
+
U,Uranium,92,238.0289
|
94
|
+
Np,Neptunum,93,237
|
95
|
+
Pu,Plutonium,94,244
|
96
|
+
Am,Americium,95,243
|
97
|
+
Cm,Curium,96,247
|
98
|
+
Bk,Berkilium,97,247
|
99
|
+
Cf,Californium,98,251
|
100
|
+
Es,Einsteinium,99,252
|
101
|
+
Fm,Fermium,100,257
|
102
|
+
Md,Mendelevium,101,258
|
103
|
+
No,Nobelium,102,259
|
104
|
+
Lr,Lawrencium,103,262
|
105
|
+
Rf,Rutherfordium,104,261
|
106
|
+
Db,Dubnium,105,262
|
107
|
+
Sg,Seaborgium,106,266
|
108
|
+
Bh,Bohrium,107,264
|
109
|
+
Hs,Hassium,108,277
|
110
|
+
Mt,Meitnerium,109,268
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Ilm
|
2
|
+
module Chemistry
|
3
|
+
# This class has functionality for reaction
|
4
|
+
# Ex: check for balanced rxn, validity of a rxn
|
5
|
+
class Reaction
|
6
|
+
attr_accessor :equation, :is_valid, :species, :participants, :balanced_eqn, :rate_equation
|
7
|
+
|
8
|
+
STATES = {
|
9
|
+
'(s)' => 'solid', '(l)' => 'liquid',
|
10
|
+
'(g)' => 'gaseous', '(aq)' => 'aqueous',
|
11
|
+
'' => ''
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def initialize(args)
|
15
|
+
# rate_eqn should be of the form: 'r_{CaO} = k[CaO][CO2]'
|
16
|
+
@equation = args[:equation]
|
17
|
+
@species = build_species
|
18
|
+
@is_valid = valid_rxn?
|
19
|
+
participant_elements
|
20
|
+
@balanced_eqn = balance_rxn
|
21
|
+
@rate_equation = validify_rate_eqn args[:rate_equation]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def validify_rate_eqn(rate_eqn)
|
27
|
+
if rate_eqn
|
28
|
+
rate_eqn.gsub('_{', '')
|
29
|
+
.gsub('}', '')
|
30
|
+
.gsub('[', ' * c')
|
31
|
+
.gsub(']', '')
|
32
|
+
else
|
33
|
+
specie = @species[:reactants].keys.first
|
34
|
+
'r' + specie + ' = k * c' + specie
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_species
|
39
|
+
r = {}
|
40
|
+
result = {}
|
41
|
+
r[:reactants], r[:products] = @equation.split('>>')
|
42
|
+
r.each do |type, _type_species|
|
43
|
+
result[type] = {}
|
44
|
+
r[type].split('+').each do |specie|
|
45
|
+
result[type].merge!(get_specie_info(specie.strip))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
result
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_specie_info(specie)
|
52
|
+
sc = get_stoichiometry specie
|
53
|
+
st = get_state specie
|
54
|
+
offset_sc = sc.zero? ? 0 : sc.to_s.length
|
55
|
+
offset_st = st.empty? ? 0 : st.length
|
56
|
+
specie_str = specie[offset_sc..(specie.length - offset_st - 1)]
|
57
|
+
{
|
58
|
+
specie_str => {
|
59
|
+
compound: Compound.new(specie_str),
|
60
|
+
stoichiometry: sc.zero? ? 1 : sc,
|
61
|
+
state: STATES[st]
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def balanced_rxn?
|
67
|
+
bal = { reactants: {}, products: {} }
|
68
|
+
@species.each do |type, type_species|
|
69
|
+
type_species.each do |_specie, s_info|
|
70
|
+
s_info[:compound].constituents.each do |sym, c_info|
|
71
|
+
bal[type][sym] ||= 0
|
72
|
+
bal[type][sym] += c_info[:atom_count] * s_info[:stoichiometry]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
bal[:products] == bal[:reactants]
|
77
|
+
end
|
78
|
+
|
79
|
+
def valid_rxn?
|
80
|
+
valid = {}
|
81
|
+
@species.each do |type, type_species|
|
82
|
+
valid[type] = []
|
83
|
+
type_species.each do |_specie, info|
|
84
|
+
info[:compound].constituents.each do |symbol, _count|
|
85
|
+
valid[type] << symbol
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
valid[:reactants].sort.uniq == valid[:products].sort.uniq
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_stoichiometry(specie)
|
93
|
+
specie.match(/^\d*/).to_a.first.to_i
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_state(specie)
|
97
|
+
specie.match(/\((s|l|g|aq)\)$/).to_s
|
98
|
+
end
|
99
|
+
|
100
|
+
def participant_elements
|
101
|
+
participants = []
|
102
|
+
@species[:reactants].keys.each do |r|
|
103
|
+
participants << @species[:reactants][r][:compound].constituents.keys
|
104
|
+
end
|
105
|
+
@participants = participants.flatten.uniq
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_participant_row(parti)
|
109
|
+
row = []
|
110
|
+
@species.keys.each do |key|
|
111
|
+
i = key == :reactants ? 1 : -1
|
112
|
+
@species[key].keys.each do |specie|
|
113
|
+
if specie.include? parti
|
114
|
+
row << @species[key][specie][:compound]
|
115
|
+
.constituents[parti][:atom_count] * i
|
116
|
+
else
|
117
|
+
row << 0
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
row
|
122
|
+
end
|
123
|
+
|
124
|
+
def write_matrix
|
125
|
+
@matrix = Matrix[]
|
126
|
+
@participants.each do |parti|
|
127
|
+
@matrix = Matrix.rows(@matrix.to_a << get_participant_row(parti))
|
128
|
+
end
|
129
|
+
@matrix
|
130
|
+
end
|
131
|
+
|
132
|
+
def balanced_coeff_array
|
133
|
+
write_matrix
|
134
|
+
null_space_array = @matrix.nullspace_array
|
135
|
+
lcm = null_space_array.collect(&:denominator).reduce(1, :lcm)
|
136
|
+
null_space_array.collect { |x| (x * lcm).to_i }
|
137
|
+
end
|
138
|
+
|
139
|
+
def balance_rxn
|
140
|
+
exp = ''
|
141
|
+
i = 0
|
142
|
+
bal_coeff = balanced_coeff_array
|
143
|
+
@species.keys.each do |key|
|
144
|
+
@species[key].keys.each do |comp|
|
145
|
+
coeff = bal_coeff[i] == 1 ? ' ' : ' ' + bal_coeff[i].abs.to_s
|
146
|
+
state = STATES.key(@species[key][comp][:state])
|
147
|
+
exp = exp + coeff + comp + state + ' +'
|
148
|
+
i += 1
|
149
|
+
end
|
150
|
+
exp = key == :reactants ? exp.chomp('+') + '>>' : exp.chomp('+')
|
151
|
+
end
|
152
|
+
exp.strip
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Ilm
|
2
|
+
module Chemistry
|
3
|
+
# This class is for mixture of compounds/elements
|
4
|
+
class Substance
|
5
|
+
attr_accessor :species
|
6
|
+
def initialize(args)
|
7
|
+
@species = {}
|
8
|
+
tt_wt_p = args.inject(0) { |sum, arg| sum + arg.last }
|
9
|
+
args.each do |specie, wt_p|
|
10
|
+
@species.merge! specie => {
|
11
|
+
compound: Compound.new(specie),
|
12
|
+
weight_percent: wt_p.to_f / tt_wt_p * 100
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/ilm/version.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubypython'
|
2
|
+
require 'matrix'
|
3
|
+
|
4
|
+
# this class is extension of Matrix class offered by ruby
|
5
|
+
class Matrix
|
6
|
+
def nullspace_as_string
|
7
|
+
a = to_a
|
8
|
+
RubyPython.start
|
9
|
+
main = RubyPython.import('__main__')
|
10
|
+
RubyPython::Python.PyRun_SimpleString <<-PYTHON
|
11
|
+
from sympy import Matrix
|
12
|
+
import numpy as np
|
13
|
+
def null_space(a):
|
14
|
+
return np.array_str(np.array(Matrix(a).nullspace()))
|
15
|
+
PYTHON
|
16
|
+
main.null_space(a).rubify
|
17
|
+
end
|
18
|
+
|
19
|
+
def nullspace_array
|
20
|
+
nullspace_as_string[2..-3].split(' ').map(&:to_r)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Custom enhancements
|
2
|
+
class String
|
3
|
+
def underscore
|
4
|
+
gsub(/::/, '/')
|
5
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
6
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
7
|
+
.tr('-', '_')
|
8
|
+
.downcase
|
9
|
+
end
|
10
|
+
|
11
|
+
def humanize(options = { capitalize: true })
|
12
|
+
s = underscore.tr('_', ' ')
|
13
|
+
s = s.capitalize if options[:capitalize]
|
14
|
+
s
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ilm
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Syed Fazil Basheer
|
8
|
+
- Somesh Choudhary
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2019-04-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '2.0'
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 2.0.1
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '2.0'
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.1
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: rake
|
36
|
+
requirement: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '12.3'
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 12.3.2
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '12.3'
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 12.3.2
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: rspec
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.8'
|
61
|
+
type: :development
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.8'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: rubocop
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 0.67.2
|
75
|
+
type: :development
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 0.67.2
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: rubocop-performance
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.1'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '1.1'
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: rubypython
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 0.6.4
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.6.4
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: unitwise
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '2.2'
|
117
|
+
type: :runtime
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '2.2'
|
124
|
+
description: A gem for scientific data.
|
125
|
+
email:
|
126
|
+
- fazil.basheer@quester.xyz
|
127
|
+
- c.somesh5@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rspec"
|
134
|
+
- ".travis.yml"
|
135
|
+
- CODE_OF_CONDUCT.md
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE
|
138
|
+
- LICENSE.txt
|
139
|
+
- README.md
|
140
|
+
- Rakefile
|
141
|
+
- bin/console
|
142
|
+
- bin/setup
|
143
|
+
- ilm.gemspec
|
144
|
+
- lib/class_overrides.rb
|
145
|
+
- lib/ilm.rb
|
146
|
+
- lib/ilm/chemical.rb
|
147
|
+
- lib/ilm/chemical/reactors.rb
|
148
|
+
- lib/ilm/chemical/reactors/batch_reactor.rb
|
149
|
+
- lib/ilm/chemical/reactors/continuous_stirred_tank_reactor.rb
|
150
|
+
- lib/ilm/chemical/reactors/plug_flow_reactor.rb
|
151
|
+
- lib/ilm/chemical/reactors/reactor.rb
|
152
|
+
- lib/ilm/chemistry.rb
|
153
|
+
- lib/ilm/chemistry/compound.rb
|
154
|
+
- lib/ilm/chemistry/element.rb
|
155
|
+
- lib/ilm/chemistry/elements.csv
|
156
|
+
- lib/ilm/chemistry/reaction.rb
|
157
|
+
- lib/ilm/chemistry/substance.rb
|
158
|
+
- lib/ilm/structures.rb
|
159
|
+
- lib/ilm/structures/pipe.rb
|
160
|
+
- lib/ilm/structures/structure.rb
|
161
|
+
- lib/ilm/version.rb
|
162
|
+
- lib/matrix_overrides.rb
|
163
|
+
- lib/string_overrides.rb
|
164
|
+
homepage: https://github.com/ilm-labs/ilm
|
165
|
+
licenses:
|
166
|
+
- MIT
|
167
|
+
metadata: {}
|
168
|
+
post_install_message:
|
169
|
+
rdoc_options: []
|
170
|
+
require_paths:
|
171
|
+
- lib
|
172
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubygems_version: 3.0.1
|
184
|
+
signing_key:
|
185
|
+
specification_version: 4
|
186
|
+
summary: A gem for scientific data.
|
187
|
+
test_files: []
|