-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.typ
More file actions
370 lines (309 loc) · 12.9 KB
/
Copy pathmain.typ
File metadata and controls
370 lines (309 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
#import "lib.typ": *
#import "defs.typ": *
#import "@preview/unify:0.7.1": qty, add-unit
#set heading(numbering: "1.")
#set par(justify: true)
#let result(body) = box(width: 100%, stroke: (left: gray + 2pt),
inset: (left: 8pt, top: 5pt, bottom: 5pt), outset: (left: -2pt),
[#body])
// ============================================================================
= Basic Conversions
This package defines units, e. g. `#kilogram` or `#watt`.
It is possible to define custom shorthands for units as well as custom quantities:
```typc
let kwh = multiply(kilo, watt, hour)
let mj = multiply(mega, joule)
let myenergyqty = multiply(15, kwh)
```
#let kwh = multiply(kilo, watt, hour)
#let mj = multiply(mega, joule)
#let myenergyqty = multiply(15, kwh)
As you saw here, each unit already has an implicit value of `1`.
Using the `value-in(qty, unit)` function, a quantity is converted to another unit, provided that the physical dimensions are equal:
#result(value-in(myenergyqty, mj))
Furthermore, units may be prepared for formatting using the `fmt(qty, unit, digits)` function.
The resulting strings can then be passed to Christian Hecker's `unify` package @unify which provides the formatting function (`qty`):
```typc
import "@preview/unify:0.7.1": qty
$qty(..fmt(myenergyqty)) = qty(..fmt(myenergyqty, unit: mj))$
```
#result($qty(..fmt(myenergyqty)) = qty(..fmt(myenergyqty, unit: mj))$)
If no unit for formatting is specified, we use the unit, that was originally used for defining the quantity.
The result may be automatically rounded to a specified number of digits:
```typc
let ms2 = divide(meter, pow(second, 2))
let mygravity = multiply(9.80665, ms2)
$qty(..fmt(mygravity)) approx #qty(..fmt(mygravity, digits: 1))$
// ^^^ make sure to add
```
#result[
#let ms2 = divide(meter, pow(second, 2))
#let mygravity = multiply(9.80665, ms2)
$qty(..fmt(mygravity)) approx #qty(..fmt(mygravity, digits: 1))$
]
Note that typst parses numbers inside math mode as content.
However, we cannot use content as an argument to any of the functions.
To correct for the wrong parsing, either
- begin one of the function calls with `#`
- escape the number with `#`
We can also perform maths using the `add`, `subtract`, `multiply`, `divide`, `pow` functions:
```typc
let myvolt = multiply(115, volt)
let myohm = multiply(220, kilo, ohm)
let mycurrent = divide(myvolt, myohm)
When applying
qty(..fmt(myvolt))
on a
qty(..fmt(myohm, unit: multiply(mega, ohm)))
resistor, the current is
qty(..fmt(mycurrent, unit: multiply(milli, ampere), digits: 3))
```
#let myvolt = multiply(115, volt)
#let myohm = multiply(220, kilo, ohm)
#let mycurrent = divide(myvolt, myohm)
#result[When applying #qty(..fmt(myvolt)) on a #qty(..fmt(myohm, unit: multiply(mega, ohm))) resistor,
the current is #qty(..fmt(mycurrent, unit: multiply(milli, ampere), digits: 3)).]
// ============================================================================
#pagebreak()
= A Complete Example: Switching Converter
== Context
#let vi = multiply(5, volt)
#let vo = multiply(2200, milli, volt)
#let dcycle = divide(vo, vi)
#let fs = multiply(300, kilo, hertz)
#let io = multiply(10, ampere)
#let cr = multiply(30, percent)
#let ir = multiply(io, cr)
#let dvo = multiply(10, milli, volt)
When calculating switching converters, there are many units and even more prefixes.
In this example, we will calculate an exemplary switching calculator:
- Input voltage is given as $V_I = qty(..fmt(vi))$
- Output voltage is given as $V_O = qty(..fmt(vo)) = qty(..fmt(vo, unit: volt))$
- Switching frequency is determined by the controller which uses $f_S = qty(..fmt(fs))$
- Output current is given as $I = qty(..fmt(io))$ and inductor current ripple ratio shall be $C R = qty(..fmt(cr))$ @buck-analog
- The output voltage ripple shall be less than $Delta V_O = qty(..fmt(dvo))$.
== Basics
First, we define all our known values. From there, we can already perform some basic calculations:
```typc
let vi = multiply(5, volt)
let vo = multiply(2200, milli, volt)
let fs = multiply(300, kilo, hertz)
let io = multiply(10, ampere)
let cr = multiply(30, percent)
let dcycle = divide(vo, vi)
let ir = multiply(io, cr)
The duty cycle can be calculated to $D = V_O/V_I = qty(..fmt(dcycle, unit: #1))$.
The current ripple would be $Delta I_L = qty(..fmt(ir, unit: ampere))$.
```
#result[
The duty cycle can be calculated to $D = V_O/V_I = qty(..fmt(dcycle, unit: #1))$.
The current ripple would be $Delta I_L = qty(..fmt(ir, unit: ampere))$.
]
== Complex Calculations
Calculation of the inductance and output capacitor is a more complex calculation @buck-ti:
$ L = (D (V_I - V_O))/(Delta I_L f_S) quad quad quad
C_O = (Delta I_L)/(8 f_S Delta V_O) $
```typc
let inductance = divide(multiply(dcycle, subtract(vi, vo)), multiply(ir, fs))
let capacitance = divide(ir, multiply(8, fs, dvo))
```
#let inductance = divide(multiply(dcycle, subtract(vi, vo)), multiply(ir, fs))
#let capacitance = divide(ir, multiply(8, fs, dvo))
With a simple calculator, one would get results such as
$ L &= qty(..fmt(inductance)) \
C_O &= qty(..fmt(capacitance)) $
Which this library can simply convert using:
```typc
$ L &= qty(..fmt(inductance, unit: multiply(micro, henry), digits: #3)) \
C_O &= qty(..fmt(capacitance, unit: multiply(micro, farad), digits: #3)) $
```
#result[$ L &= qty(..fmt(inductance, unit: multiply(micro, henry), digits: #3)) \
C_O &= qty(..fmt(capacitance, unit: multiply(micro, farad), digits: #3)) $]
// ============================================================================
= Example: Stress Analysis
#let height = multiply(140, milli, meter)
#let width = multiply(120, milli, meter)
#let thick = multiply(8, milli, meter)
#let length = multiply(3, meter)
#let force = multiply(16, kilo, newton)
#let yield = multiply(355, mega, pascal)
#columns(2)[
#include "ibeam.typ" // Show a little picture
#colbreak()
A simple I beam is defined using
- Height $H = qty(..fmt(height))$
- Width $W = qty(..fmt(width))$
- Constant thickness $t = qty(..fmt(thick))$
- Beam length $l = qty(..fmt(length))$
- Applied force at the end $F = qty(..fmt(force))$
- Yield strength $sigma_y = qty(..fmt(yield))$ (S355 material)
Approximation for $t << W, H$:
$ I_(y y) & approx t integral_s z^2 dif s = (W^3 t)/6 \
I_(z z) & approx t integral_s y^2 dif s = (W H^2 t)/2 + (W^3 t)/12 $
]
```typc
let height = multiply(140, milli, meter)
let width = multiply(120, milli, meter)
let thick = multiply(8, milli, meter)
let length = multiply(3, meter)
let force = multiply(16, kilo, newton)
let yield = multiply(355, mega, pascal)
```
We can calculate the area moment of inertia $I$ using the specified sizes:
```typc
let iyy = divide(multiply(pow(width, 3), thick), 6)
let izz = add(divide(multiply(width, pow(height, 2), thick), 2),
divide(multiply(pow(width, 3), thick), 12))
let mm4 = pow(multiply(milli, meter), 4)
$I_(y y) = qty(..fmt(iyy, unit: mm4, digits: #0))$ "and"
$I_(z z) = qty(..fmt(izz, unit: mm4, digits: #0))$.
```
#let iyy = divide(multiply(pow(width, 3), thick), 6)
#let izz = add(divide(multiply(width, pow(height, 2), thick), 2),
divide(multiply(pow(width, 3), thick), 12))
#let mm4 = pow(multiply(milli, meter), 4)
#result[
$I_(y y) = qty(..fmt(iyy, unit: mm4, digits: #0))$
and
$I_(z z) = qty(..fmt(izz, unit: mm4, digits: #0))$.]
The section modulus $W$ measures the resistance against a bending moment $M$:
$ W := M/sigma $
We can calculate it automatically using
```typc
let wy = multiply(iyy, divide(2, width))
let wz = multiply(izz, divide(2, height))
let mm3 = pow(multiply(milli, meter), 3)
$W_y = I_(y y)/(W\/2) = qty(..fmt(wy, unit: mm3, digits: #0))$ and
$W_z = I_(y y)/(H\/2) = qty(..fmt(wz, unit: mm3, digits: #0))$.
```
#let wy = multiply(iyy, divide(2, width))
#let wz = multiply(izz, divide(2, height))
#let mm3 = pow(multiply(milli, meter), 3)
#result[
$W_y = I_(y y)/(W\/2) = qty(..fmt(wy, unit: mm3, digits: #0))$ and
$W_z = I_(y y)/(H\/2) = qty(..fmt(wz, unit: mm3, digits: #0))$.]
Finally, we can analyze the stress under load and calculate the reserve factor $R F = "strength"/"load"$:
$ sigma_"load" = M/W = (F dot l)/W quad quad R F = sigma_y/sigma_"load" $
```typc
let load = divide(multiply(force, length), wz)
let reserve = divide(yield, load)
$ sigma = qty(..fmt(load, unit: multiply(mega, pascal), digits: #0)) quad
R F = qty(..fmt(reserve, unit: percent, digits: #1)) $
```
#let load = divide(multiply(force, length), wz)
#let reserve = divide(yield, load)
#result[
$ sigma = qty(..fmt(load, unit: multiply(mega, pascal), digits: #0)) quad
R F = qty(..fmt(reserve, unit: percent, digits: #1)) $]
// ============================================================================
#pagebreak()
= Defining Custom Units
== Defining Imperial Units
We can define custom units based on existing units using `define_unit`:
```typc
let inch = define_unit(multiply(25.4, milli, meter), "in ")
let foot = define_unit(multiply(12, inch), "ft ")
let yard = define_unit(multiply(3, foot), "yd ")
let mile = define_unit(multiply(1760, yard), "mi ")
```
Furthermore, when introducing new units, make sure that they either exist in `unify`, or that you register them there as well @unify:
```typc
import "@preview/unify:0.7.1": add-unit
add-unit("inch", "in", "upright(\"in\")")
add-unit("feet", "ft", "upright(\"ft\")")
add-unit("yard", "yd", "upright(\"yd\")")
add-unit("mile", "mi", "upright(\"mi\")")
```
#let inch = define_unit(multiply(25.4, milli, meter), "in ")
#let foot = define_unit(multiply(12, inch), "ft ")
#let yard = define_unit(multiply(3, foot), "yd ")
#let mile = define_unit(multiply(1760, yard), "mi ")
// We need to add imperial units to unify as well:
#add-unit("inch", "in", "upright(\"in\")")
#add-unit("feet", "ft", "upright(\"ft\")")
#add-unit("yard", "yd", "upright(\"yd\")")
#add-unit("mile", "mi", "upright(\"mi\")")
Afterwards, it is no more problem to convert these units:
```typc
let mydist = multiply(3, mile)
$qty(..fmt(mydist, unit: mile)) =
qty(..fmt(mydist, unit: foot)) =
qty(..fmt(mydist, unit: meter, digits: #2)) =
qty(..fmt(mydist, unit: multiply(kilo, meter), digits: #3))$
```
#let mydist = multiply(3, mile)
#result[
$qty(..fmt(mydist, unit: mile)) =
qty(..fmt(mydist, unit: foot)) =
qty(..fmt(mydist, unit: meter, digits: #2)) =
qty(..fmt(mydist, unit: multiply(kilo, meter), digits: #3))$
]
== Using Custom Units in Powers
This also works with squared and cubed units:
```typc
define_unit(pow(multiply(deci, meter), 3), "L ")
#let myvolume = multiply(10, pow(yard, 3))
A concrete truck carries $qty(..fmt(myvolume)) =
qty(..fmt(myvolume, unit: pow(meter, #3), digits: #2)) =
qty(..fmt(myvolume, unit: liter, digits: #0))$ of concrete.
```
#let liter = define_unit(pow(multiply(deci, meter), 3), "L ")
#let myvolume = multiply(10, pow(yard, 3))
#result[
A concrete truck carries $qty(..fmt(myvolume)) =
qty(..fmt(myvolume, unit: pow(meter, #3), digits: #2)) =
qty(..fmt(myvolume, unit: liter, digits: #0))$ of concrete.]
== Common Mistake
The second argument is the unit format, which is at some point passed to unify.
When defining a unit instead of a prefix, you must add a space after the formatting string.
The library has no way of verifying that the unit format is correct, it is possible to do something like:
```typc
let inch = define_unit(multiply(25.4, second), "in ")
// ^^^^^^ ^^^^^ undetectable mismatch
```
And the library has no way of detecting that error!
== Pressure Conversion
First, we define some alternative units for pressure measurement:
```typc
let bar = define_unit(multiply(100, kilo, pascal), "bar ")
let atm = define_unit(multiply(1.01325, bar), "atm ")
let hecto = define_unit(100, "h") // for hPa
```
#let bar = define_unit(multiply(100, kilo, pascal), "bar ")
#let atm = define_unit(multiply(1.01325, bar), "atm ")
#let hecto = define_unit(100, "h")
We can use these units to directly convert the standard atmospheric pressure @isa:
```typc
let pres = multiply(1, atm)
$qty(..fmt(pres)) =
qty(..fmt(pres, unit: bar)) =
qty(..fmt(pres, unit: multiply(hecto, pascal)))$
```
#let pres = multiply(1, atm)
#result[
$qty(..fmt(pres)) =
qty(..fmt(pres, unit: bar)) =
qty(..fmt(pres, unit: multiply(hecto, pascal)))$
]
Furthermore, using the density of mercury, we can convert the pressure to the height of the liquid column:
```typc
let density = divide(multiply(13595.1, kilogram), pow(meter, 3))
let gravity = multiply(9.81, divide(meter, pow(second, 2)))
let hg = multiply(density, gravity)
let height = divide(pres, hg)
qty(..fmt(pres)) is equivalent to
qty(..fmt(height, unit: multiply(milli, meter), digits: 0)) or
qty(..fmt(height, unit: inch, digits: 2)) of mercury.
```
#let density = divide(multiply(13595.1, kilogram), pow(meter, 3))
#let gravity = multiply(9.81, divide(meter, pow(second, 2)))
#let hg = multiply(density, gravity)
#let height = divide(pres, hg)
#result[
#qty(..fmt(pres)) is equivalent to
#qty(..fmt(height, unit: multiply(milli, meter), digits: 0)) or
#qty(..fmt(height, unit: inch, digits: 2)) of mercury.
]
// ============================================================================
#pagebreak()
#bibliography("bib.yaml")