steer-materials 0.1.16__tar.gz → 0.1.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {steer_materials-0.1.16 → steer_materials-0.1.17}/PKG-INFO +1 -1
  2. {steer_materials-0.1.16 → steer_materials-0.1.17}/steer_materials/Base.py +102 -0
  3. steer_materials-0.1.17/steer_materials/__init__.py +2 -0
  4. {steer_materials-0.1.16 → steer_materials-0.1.17}/steer_materials.egg-info/PKG-INFO +1 -1
  5. steer_materials-0.1.17/steer_materials.egg-info/SOURCES.txt +13 -0
  6. steer_materials-0.1.17/test/test_electrolyte.py +39 -0
  7. steer_materials-0.1.16/data_scripts/__init__.py +0 -0
  8. steer_materials-0.1.16/steer_materials/CellMaterials/Base.py +0 -278
  9. steer_materials-0.1.16/steer_materials/CellMaterials/Electrode.py +0 -1188
  10. steer_materials-0.1.16/steer_materials/CellMaterials/__init__.py +0 -0
  11. steer_materials-0.1.16/steer_materials/Electrolytes/Electrolytes.py +0 -16
  12. steer_materials-0.1.16/steer_materials/Electrolytes/Ions.py +0 -0
  13. steer_materials-0.1.16/steer_materials/Electrolytes/Salts.py +0 -27
  14. steer_materials-0.1.16/steer_materials/Electrolytes/Solvents.py +0 -0
  15. steer_materials-0.1.16/steer_materials/Electrolytes/__init__.py +0 -0
  16. steer_materials-0.1.16/steer_materials/__init__.py +0 -6
  17. steer_materials-0.1.16/steer_materials.egg-info/SOURCES.txt +0 -29
  18. {steer_materials-0.1.16 → steer_materials-0.1.17}/README.md +0 -0
  19. {steer_materials-0.1.16 → steer_materials-0.1.17}/pyproject.toml +0 -0
  20. {steer_materials-0.1.16 → steer_materials-0.1.17}/setup.cfg +0 -0
  21. {steer_materials-0.1.16 → steer_materials-0.1.17}/steer_materials.egg-info/dependency_links.txt +0 -0
  22. {steer_materials-0.1.16 → steer_materials-0.1.17}/steer_materials.egg-info/requires.txt +0 -0
  23. {steer_materials-0.1.16 → steer_materials-0.1.17}/steer_materials.egg-info/top_level.txt +0 -0
  24. {steer_materials-0.1.16 → steer_materials-0.1.17}/test/test_electrode_materials.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: steer-materials
3
- Version: 0.1.16
3
+ Version: 0.1.17
4
4
  Summary: Modelling energy storage from cell to site - STEER OpenCell Design
5
5
  Author-email: Nicholas Siemons <nsiemons@stanford.edu>
6
6
  Maintainer-email: Nicholas Siemons <nsiemons@stanford.edu>
@@ -90,13 +90,32 @@ class _Material(
90
90
 
91
91
  @density.setter
92
92
  def density(self, density: float) -> None:
93
+
94
+ # validate input
93
95
  self.validate_positive_float(density, "Density")
96
+
97
+ # convert and set
94
98
  self._density = density * G_TO_KG / CM_TO_M**3
95
99
 
100
+ # If this is a volumed material and volume is set, recalculate mass
101
+ if hasattr(self, '_volume') and self._volume is not None:
102
+ self._mass = self._volume * self._density
103
+ if hasattr(self, '_cost'):
104
+ self._cost = self._mass * self._specific_cost
105
+
96
106
  @specific_cost.setter
97
107
  def specific_cost(self, specific_cost: float) -> None:
108
+
109
+ # validate input
98
110
  self.validate_positive_float(specific_cost, "Specific Cost")
111
+
112
+ # set value
99
113
  self._specific_cost = specific_cost
114
+
115
+ # If this is a volumed material with mass, recalculate cost
116
+ if hasattr(self, '_mass') and self._mass is not None:
117
+ if hasattr(self, '_cost'):
118
+ self._cost = self._mass * self._specific_cost
100
119
 
101
120
  @name.setter
102
121
  def name(self, name: str) -> None:
@@ -117,3 +136,86 @@ class Solvent(_Material):
117
136
 
118
137
  super().__init__(name, density, specific_cost, color)
119
138
 
139
+
140
+ class _VolumedMaterialMixin:
141
+ """
142
+ Mixin for materials that optionally track volume (cm^3) or mass (kg).
143
+ Cost ($) is always derived from mass and specific_cost.
144
+ """
145
+
146
+ def __init__(
147
+ self,
148
+ *,
149
+ volume=None,
150
+ mass=None,
151
+ **kwargs
152
+ ):
153
+
154
+ super().__init__(**kwargs)
155
+
156
+ # Check that only one of volume or mass is provided
157
+ provided = sum([volume is not None, mass is not None])
158
+ if provided > 1:
159
+ raise ValueError(
160
+ "Only one of 'volume' or 'mass' can be provided during initialization. "
161
+ f"Received: volume={volume}, mass={mass}"
162
+ )
163
+
164
+ self._volume = None
165
+ self._mass = None
166
+ self._cost = None
167
+
168
+ if volume is not None:
169
+ self.volume = volume
170
+ elif mass is not None:
171
+ self.mass = mass
172
+
173
+ @property
174
+ def volume(self):
175
+ if hasattr(self, '_volume') and self._volume is not None:
176
+ return round(self._volume * (M_TO_CM**3), 4)
177
+ else:
178
+ return None
179
+
180
+ @property
181
+ def mass(self):
182
+ if hasattr(self, '_mass') and self._mass is not None:
183
+ return round(self._mass * KG_TO_G, 2)
184
+ else:
185
+ return None
186
+
187
+ @property
188
+ def cost(self):
189
+ if hasattr(self, '_cost') and self._cost is not None:
190
+ return round(self._cost, 2)
191
+ else:
192
+ return None
193
+
194
+
195
+ @volume.setter
196
+ def volume(self, value):
197
+
198
+ if value is not None:
199
+ ValidationMixin.validate_positive_float(value, "Volume")
200
+ self._volume = value * CM_TO_M**3
201
+ self._mass = self._volume * self._density
202
+ self._cost = self._mass * self._specific_cost
203
+ else:
204
+ self._volume = None
205
+ self._mass = None
206
+ self._cost = None
207
+
208
+ @mass.setter
209
+ def mass(self, value):
210
+
211
+ if value is not None:
212
+ ValidationMixin.validate_positive_float(value, "Mass")
213
+ self._mass = value * G_TO_KG
214
+ self._volume = self._mass / self._density
215
+ self._cost = self._mass * self._specific_cost
216
+ else:
217
+ self._volume = None
218
+ self._mass = None
219
+ self._cost = None
220
+
221
+
@@ -0,0 +1,2 @@
1
+ __version__ = "0.1.17"
2
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: steer-materials
3
- Version: 0.1.16
3
+ Version: 0.1.17
4
4
  Summary: Modelling energy storage from cell to site - STEER OpenCell Design
5
5
  Author-email: Nicholas Siemons <nsiemons@stanford.edu>
6
6
  Maintainer-email: Nicholas Siemons <nsiemons@stanford.edu>
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ ./steer_materials/Base.py
4
+ ./steer_materials/__init__.py
5
+ steer_materials/Base.py
6
+ steer_materials/__init__.py
7
+ steer_materials.egg-info/PKG-INFO
8
+ steer_materials.egg-info/SOURCES.txt
9
+ steer_materials.egg-info/dependency_links.txt
10
+ steer_materials.egg-info/requires.txt
11
+ steer_materials.egg-info/top_level.txt
12
+ test/test_electrode_materials.py
13
+ test/test_electrolyte.py
@@ -0,0 +1,39 @@
1
+ import unittest
2
+
3
+ from steer_materials.Electrolytes.Electrolytes import Electrolyte
4
+
5
+
6
+ class TestElectrolyteVolumeMassCost(unittest.TestCase):
7
+
8
+ def setUp(self):
9
+ self.electrolyte = Electrolyte(
10
+ name="Test Electrolyte",
11
+ density=1.2, # g/cm^3
12
+ specific_cost=15.0, # $/kg
13
+ color="#abcdef",
14
+ )
15
+
16
+ def test_volume_setter_updates_mass_and_cost(self):
17
+ self.electrolyte.volume = 10.0
18
+
19
+ self.assertAlmostEqual(self.electrolyte.volume, 10.0, places=4)
20
+ self.assertAlmostEqual(self.electrolyte.mass, 12.0, places=2)
21
+ self.assertAlmostEqual(self.electrolyte.cost, 0.18, places=2)
22
+
23
+ def test_mass_setter_updates_volume_and_cost(self):
24
+ self.electrolyte.mass = 25.0
25
+
26
+ self.assertAlmostEqual(self.electrolyte.mass, 25.0, places=2)
27
+ self.assertAlmostEqual(self.electrolyte.volume, 20.8333, places=3)
28
+ self.assertAlmostEqual(self.electrolyte.cost, 0.38, places=2)
29
+
30
+ def test_cost_setter_updates_mass_and_volume(self):
31
+ self.electrolyte.cost = 5.0
32
+
33
+ self.assertAlmostEqual(self.electrolyte.cost, 5.0, places=2)
34
+ self.assertAlmostEqual(self.electrolyte.mass, 333.33, places=2)
35
+ self.assertAlmostEqual(self.electrolyte.volume, 277.7778, places=1)
36
+
37
+
38
+ if __name__ == "__main__":
39
+ unittest.main()
File without changes
@@ -1,278 +0,0 @@
1
- from steer_core.DataManager import DataManager
2
- from steer_core.Mixins.Serializer import SerializerMixin
3
- from steer_materials.Base import Metal, _Material
4
-
5
-
6
- class CurrentCollectorMaterial(Metal):
7
- """
8
- Materials from which current collectors are made.
9
- """
10
-
11
- def __init__(self, name: str, density: float, specific_cost: float, color: str):
12
- """
13
- Current collector material for encapsulation of the cell
14
-
15
- Parameters
16
- ----------
17
- name : str
18
- Name of the current collector material.
19
- density : float
20
- Density of the material in g/cm^3.
21
- specific_cost : float
22
- Specific cost of the material in $/kg.
23
- color : str
24
- Color of the material.
25
- """
26
- super().__init__(name, density, specific_cost, color)
27
-
28
- @staticmethod
29
- def from_database(name) -> "CurrentCollectorMaterial":
30
- """
31
- Pull object from the database.
32
-
33
- Parameters
34
- ----------
35
- name : str
36
- Name of the current collector material.
37
-
38
- Returns
39
- -------
40
- CurrentCollectorMaterial: Instance of the class.
41
-
42
- Raises
43
- ------
44
- ValueError: If the material is not found in the database.
45
- """
46
- database = DataManager()
47
-
48
- available_materials = database.get_unique_values(
49
- "current_collector_materials", "name"
50
- )
51
-
52
- if name not in available_materials:
53
- raise ValueError(
54
- f"Material '{name}' not found in the database. Available materials: {available_materials}"
55
- )
56
-
57
- data = database.get_current_collector_materials(most_recent=True).query(
58
- f"name == '{name}'"
59
- )
60
-
61
- string_rep = data["object"].iloc[0]
62
-
63
- material = SerializerMixin.deserialize(string_rep)
64
-
65
- return material
66
-
67
-
68
- class InsulationMaterial(_Material):
69
- """
70
- Materials from which insulation is made.
71
- """
72
-
73
- def __init__(self, name: str, density: float, specific_cost: float, color: str):
74
- """
75
- Insulation material for encapsulation of the cell
76
-
77
- Parameters
78
- ----------
79
- name : str
80
- Name of the insulation material.
81
- density : float
82
- Density of the material in g/cm^3.
83
- specific_cost : float
84
- Specific cost of the material in $/kg.
85
- color : str
86
- Color of the material.
87
- """
88
- super().__init__(name, density, specific_cost, color)
89
-
90
- @staticmethod
91
- def from_database(name) -> "InsulationMaterial":
92
- """
93
- Pull object from the database.
94
-
95
- Parameters
96
- ----------
97
- name : str
98
- Name of the insulation material.
99
-
100
- Returns
101
- -------
102
- InsulationMaterial: Instance of the class.
103
-
104
- Raises
105
- ------
106
- ValueError: If the material is not found in the database.
107
- """
108
- database = DataManager()
109
- available_materials = database.get_unique_values("insulation_materials", "name")
110
-
111
- if name not in available_materials:
112
- raise ValueError(
113
- f"Material '{name}' not found in the database. Available materials: {available_materials}"
114
- )
115
-
116
- data = database.get_data(table_name="insulation_materials").query(
117
- f"name == '{name}'"
118
- )
119
-
120
- string_data = data["object"].iloc[0]
121
- material = SerializerMixin.deserialize(string_data)
122
- return material
123
-
124
-
125
- class SeparatorMaterial(_Material):
126
- """
127
- Materials from which separators are made.
128
- """
129
-
130
- def __init__(
131
- self,
132
- name: str,
133
- density: float,
134
- specific_cost: float,
135
- porosity: float,
136
- color: str,
137
- ):
138
- """
139
- Separator material for encapsulation of the cell
140
-
141
- Parameters
142
- ----------
143
- name : str
144
- Name of the separator material.
145
- density : float
146
- Density of the material in g/cm^3.
147
- specific_cost : float
148
- Specific cost of the material in $/kg.
149
- porosity : float
150
- Porosity of the separator material in %.
151
- color : str
152
- Color of the material.
153
- """
154
- super().__init__(
155
- name,
156
- density,
157
- specific_cost,
158
- color
159
- )
160
-
161
- self.porosity = porosity
162
-
163
- @property
164
- def porosity(self):
165
- return round(self._porosity * 100, 2)
166
-
167
- @property
168
- def porosity_range(self):
169
- return (0, 100)
170
-
171
- @porosity.setter
172
- def porosity(self, porosity: float) -> None:
173
- self.validate_percentage(porosity, "Porosity")
174
- self._porosity = porosity / 100.0
175
-
176
- @staticmethod
177
- def from_database(name) -> "SeparatorMaterial":
178
- """
179
- Pull object from the database.
180
-
181
- Parameters
182
- ----------
183
- name : str
184
- Name of the separator material.
185
-
186
- Returns
187
- -------
188
- SeparatorMaterial: Instance of the class.
189
-
190
- Raises
191
- ------
192
- ValueError: If the material is not found in the database.
193
- """
194
- database = DataManager()
195
-
196
- available_materials = database.get_unique_values("separator_materials", "name")
197
-
198
- if name not in available_materials:
199
- raise ValueError(
200
- f"Material '{name}' not found in the database. Available materials: {available_materials}"
201
- )
202
-
203
- data = database.get_data(table_name="separator_materials").query(
204
- f"name == '{name}'"
205
- )
206
-
207
- string_data = data["object"].iloc[0]
208
- material = SerializerMixin.deserialize(string_data)
209
- return material
210
-
211
-
212
-
213
- class TapeMaterial(_Material):
214
- """
215
- Materials from which tapes are made.
216
- """
217
-
218
- def __init__(
219
- self,
220
- name: str,
221
- density: float,
222
- specific_cost: float,
223
- color: str,
224
- ):
225
- """
226
- Separator material for encapsulation of the cell
227
-
228
- Parameters
229
- ----------
230
- name : str
231
- Name of the tape material.
232
- density : float
233
- Density of the material in g/cm^3.
234
- specific_cost : float
235
- Specific cost of the material in $/kg.
236
- color : str
237
- Color of the material.
238
- """
239
- super().__init__(
240
- name,
241
- density,
242
- specific_cost,
243
- color
244
- )
245
-
246
- @staticmethod
247
- def from_database(name) -> "TapeMaterial":
248
- """
249
- Pull object from the database.
250
-
251
- Parameters
252
- ----------
253
- name : str
254
- Name of the tape material.
255
-
256
- Returns
257
- -------
258
- TapeMaterial: Instance of the class.
259
- Raises
260
- ------
261
- ValueError: If the material is not found in the database.
262
- """
263
- database = DataManager()
264
-
265
- available_materials = database.get_unique_values("tape_materials", "name")
266
-
267
- if name not in available_materials:
268
- raise ValueError(
269
- f"Material '{name}' not found in the database. Available materials: {available_materials}"
270
- )
271
-
272
- data = database.get_data(table_name="tape_materials").query(
273
- f"name == '{name}'"
274
- )
275
-
276
- string_data = data["object"].iloc[0]
277
- material = SerializerMixin.deserialize(string_data)
278
- return material