Spaces:
Running
Running
bugfix
Browse files
marimo/docs/LabManualCHEM2000-1.pdf
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f364d817342f54021293b252d540252f283f25a0c17223106b23a1152192bf1d
|
| 3 |
+
size 4005337
|
src/pycek_public/bomb_calorimetry.py
CHANGED
|
@@ -2,17 +2,17 @@ import pycek_public as cek
|
|
| 2 |
import numpy as np
|
| 3 |
import pprint as pp
|
| 4 |
|
|
|
|
| 5 |
class bomb_calorimetry(cek.cek_labs):
|
| 6 |
def setup_lab(self):
|
| 7 |
"""
|
| 8 |
Define base information for the lab
|
| 9 |
"""
|
| 10 |
-
self.add_metadata(
|
| 11 |
-
laboratory
|
| 12 |
-
|
| 13 |
-
)
|
| 14 |
|
| 15 |
-
self.available_samples = [
|
| 16 |
|
| 17 |
self.ignition_time = 20
|
| 18 |
self.relaxation_time = 3
|
|
@@ -20,45 +20,45 @@ class bomb_calorimetry(cek.cek_labs):
|
|
| 20 |
self.noise_level = 0.1
|
| 21 |
self.precision = 2
|
| 22 |
|
| 23 |
-
self.slope_before = np.random.uniform(0., self.noise_level) / 3
|
| 24 |
-
self.slope_after = np.random.uniform(0., self.noise_level) / 3
|
| 25 |
-
|
| 26 |
self.RT = self.R * self.temperature
|
| 27 |
-
|
| 28 |
# calorimeter constant (J/K)
|
| 29 |
-
self.calorimeter_constant = {
|
| 30 |
self.sample_parameters["co2"] = {
|
| 31 |
-
"mM"
|
| 32 |
-
"dH"
|
| 33 |
}
|
| 34 |
self.sample_parameters["h2o"] = {
|
| 35 |
-
"mM"
|
| 36 |
-
"dH"
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
self.sample_parameters["benzoic"] = {
|
| 40 |
-
"mM"
|
| 41 |
-
"n1"
|
| 42 |
-
"n2"
|
| 43 |
-
"dn"
|
| 44 |
-
"dHf"
|
| 45 |
-
"dHc"
|
| 46 |
}
|
| 47 |
self.sample_parameters["sucrose"] = {
|
| 48 |
-
"mM"
|
| 49 |
-
"n1"
|
| 50 |
-
"n2"
|
| 51 |
-
"dn"
|
| 52 |
-
"dHf"
|
| 53 |
-
"dHc"
|
| 54 |
}
|
| 55 |
self.sample_parameters["naphthalene"] = {
|
| 56 |
-
"mM"
|
| 57 |
-
"n1"
|
| 58 |
-
"n2"
|
| 59 |
-
"dn"
|
| 60 |
-
"dHf"
|
| 61 |
-
"dHc"
|
| 62 |
}
|
| 63 |
|
| 64 |
def create_data(self):
|
|
@@ -68,50 +68,56 @@ class bomb_calorimetry(cek.cek_labs):
|
|
| 68 |
if self.sample is None:
|
| 69 |
raise Exception("Sample not defined")
|
| 70 |
|
| 71 |
-
prm = self.sample_parameters[
|
| 72 |
|
| 73 |
-
self.set_parameters(
|
| 74 |
-
sample
|
| 75 |
-
number_of_values
|
| 76 |
-
|
| 77 |
|
| 78 |
self.mass = np.random.normal(1000, 100)
|
| 79 |
-
self.add_metadata(
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
|
|
|
|
|
|
| 84 |
|
| 85 |
moles = self.mass / 1000 / prm["mM"]
|
| 86 |
|
| 87 |
# combustion enthalpy
|
| 88 |
# nH{co2} + mH{h2o} - H = DcH
|
| 89 |
-
DcH =
|
| 90 |
-
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
dH = DcH * moles
|
| 93 |
dnrt = moles * self.RT * prm["dn"]
|
| 94 |
dU = dH - dnrt
|
| 95 |
-
|
| 96 |
-
deltaT = -dU / self.calorimeter_constant[
|
| 97 |
|
| 98 |
x = np.linspace(0, self.number_of_values, self.number_of_values)
|
| 99 |
y = np.random.normal(0, self.noise_level, self.number_of_values)
|
| 100 |
|
| 101 |
-
x = self._round_values(x,precision=0)
|
| 102 |
|
| 103 |
-
dd = 0.
|
| 104 |
T = self.temperature
|
| 105 |
for i in range(self.number_of_values):
|
| 106 |
if i < self.ignition_time:
|
| 107 |
-
T += self.slope_before
|
| 108 |
-
else:
|
| 109 |
T += self.slope_after
|
| 110 |
-
dd = deltaT * (
|
| 111 |
-
|
|
|
|
|
|
|
| 112 |
|
| 113 |
y = self._round_values(y)
|
| 114 |
-
self.data = np.column_stack((x,y))
|
| 115 |
|
| 116 |
return self.data
|
| 117 |
-
|
|
|
|
| 2 |
import numpy as np
|
| 3 |
import pprint as pp
|
| 4 |
|
| 5 |
+
|
| 6 |
class bomb_calorimetry(cek.cek_labs):
|
| 7 |
def setup_lab(self):
|
| 8 |
"""
|
| 9 |
Define base information for the lab
|
| 10 |
"""
|
| 11 |
+
self.add_metadata(
|
| 12 |
+
laboratory="Bomb Calorimetry", columns=["Time (s)", "Temperature (K)"]
|
| 13 |
+
)
|
|
|
|
| 14 |
|
| 15 |
+
self.available_samples = ["benzoic", "sucrose", "naphthalene"]
|
| 16 |
|
| 17 |
self.ignition_time = 20
|
| 18 |
self.relaxation_time = 3
|
|
|
|
| 20 |
self.noise_level = 0.1
|
| 21 |
self.precision = 2
|
| 22 |
|
| 23 |
+
self.slope_before = np.random.uniform(0.0, self.noise_level) / 3
|
| 24 |
+
self.slope_after = np.random.uniform(0.0, self.noise_level) / 3
|
| 25 |
+
|
| 26 |
self.RT = self.R * self.temperature
|
| 27 |
+
|
| 28 |
# calorimeter constant (J/K)
|
| 29 |
+
self.calorimeter_constant = {"value": 10135, "std_error": 0.0}
|
| 30 |
self.sample_parameters["co2"] = {
|
| 31 |
+
"mM": 44.01,
|
| 32 |
+
"dH": -393.51e3, # co2 enthapy of formation (J/mol/K)
|
| 33 |
}
|
| 34 |
self.sample_parameters["h2o"] = {
|
| 35 |
+
"mM": 18.015,
|
| 36 |
+
"dH": -285.83e3, # h2o enthapy of formation (J/mol/K)
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
self.sample_parameters["benzoic"] = {
|
| 40 |
+
"mM": 122.123,
|
| 41 |
+
"n1": 7,
|
| 42 |
+
"n2": 3,
|
| 43 |
+
"dn": 7 - 15 / 2,
|
| 44 |
+
"dHf": {"value": -384.8e3, "std_error": 0.5e3},
|
| 45 |
+
"dHc": {"value": -3227.26e3, "std_error": 0.2e3},
|
| 46 |
}
|
| 47 |
self.sample_parameters["sucrose"] = {
|
| 48 |
+
"mM": 342.3,
|
| 49 |
+
"n1": 12,
|
| 50 |
+
"n2": 11,
|
| 51 |
+
"dn": 0,
|
| 52 |
+
"dHf": {"value": -2221.2e3, "std_error": 0.2e3},
|
| 53 |
+
"dHc": {"value": -5643.4e3, "std_error": 1.8e3},
|
| 54 |
}
|
| 55 |
self.sample_parameters["naphthalene"] = {
|
| 56 |
+
"mM": 128.17,
|
| 57 |
+
"n1": 10,
|
| 58 |
+
"n2": 4,
|
| 59 |
+
"dn": 10 - 12,
|
| 60 |
+
"dHf": {"value": 77e3, "std_error": 10.0e3},
|
| 61 |
+
"dHc": {"value": -5160e3, "std_error": 20.0e3},
|
| 62 |
}
|
| 63 |
|
| 64 |
def create_data(self):
|
|
|
|
| 68 |
if self.sample is None:
|
| 69 |
raise Exception("Sample not defined")
|
| 70 |
|
| 71 |
+
prm = self.sample_parameters[self.sample]
|
| 72 |
|
| 73 |
+
self.set_parameters(
|
| 74 |
+
sample=self.sample,
|
| 75 |
+
number_of_values=self.number_of_values,
|
| 76 |
+
)
|
| 77 |
|
| 78 |
self.mass = np.random.normal(1000, 100)
|
| 79 |
+
self.add_metadata(
|
| 80 |
+
**{
|
| 81 |
+
"Tablet mass (mg)": f"{self.mass:.1f}",
|
| 82 |
+
"Ignition time (s)": self.ignition_time,
|
| 83 |
+
"Sample": self.sample,
|
| 84 |
+
}
|
| 85 |
+
)
|
| 86 |
|
| 87 |
moles = self.mass / 1000 / prm["mM"]
|
| 88 |
|
| 89 |
# combustion enthalpy
|
| 90 |
# nH{co2} + mH{h2o} - H = DcH
|
| 91 |
+
DcH = (
|
| 92 |
+
prm["n1"] * self.sample_parameters["co2"]["dH"]
|
| 93 |
+
+ prm["n2"] * self.sample_parameters["h2o"]["dH"]
|
| 94 |
+
- prm["dHf"]["value"]
|
| 95 |
+
)
|
| 96 |
|
| 97 |
dH = DcH * moles
|
| 98 |
dnrt = moles * self.RT * prm["dn"]
|
| 99 |
dU = dH - dnrt
|
| 100 |
+
|
| 101 |
+
deltaT = -dU / self.calorimeter_constant["value"]
|
| 102 |
|
| 103 |
x = np.linspace(0, self.number_of_values, self.number_of_values)
|
| 104 |
y = np.random.normal(0, self.noise_level, self.number_of_values)
|
| 105 |
|
| 106 |
+
x = self._round_values(x, precision=0)
|
| 107 |
|
| 108 |
+
dd = 0.0
|
| 109 |
T = self.temperature
|
| 110 |
for i in range(self.number_of_values):
|
| 111 |
if i < self.ignition_time:
|
| 112 |
+
T += self.slope_before
|
| 113 |
+
else:
|
| 114 |
T += self.slope_after
|
| 115 |
+
dd = deltaT * (
|
| 116 |
+
1 - np.exp(-(i - self.ignition_time) / self.relaxation_time)
|
| 117 |
+
)
|
| 118 |
+
y[i] += T + dd
|
| 119 |
|
| 120 |
y = self._round_values(y)
|
| 121 |
+
self.data = np.column_stack((x, y))
|
| 122 |
|
| 123 |
return self.data
|
|
|